diff --git a/.claude/skills/pseudocode/SKILL.md b/.claude/skills/pseudocode/SKILL.md index 8ac2899..f612868 100644 --- a/.claude/skills/pseudocode/SKILL.md +++ b/.claude/skills/pseudocode/SKILL.md @@ -20,10 +20,11 @@ data provenance are written as high-level pseudocode, infrastructure is declared the whole thing compiles to C4 diagrams, sequence diagrams, and a doc site (`pds doc`). This skill is the **method**, not the grammar. For any syntax question — keywords, `Result` -handling, `from` composition, macros, modules, visibility, the EBNF — read **`references/LANG.md`** -(the language specification) and follow it exactly. Do **not** invent syntax; if the spec doesn't -support a form (e.g. comparison operators in conditions — see its Open Questions), model around it -with a call that returns a `Result` or `bool` instead. +handling, `from` composition, macros, modules, visibility, the EBNF — run **`pds lang`** to print +the full language reference (spec + patterns + the conformance/grammar suite) and follow it exactly. +Do **not** invent syntax; if the spec doesn't support a form (e.g. comparison operators in +conditions — see its Open Questions), model around it with a call that returns a `Result` or `bool` +instead. Two jobs only: - **Map** an existing application into a `.pds` model (reverse). @@ -57,14 +58,14 @@ disclose it as a branch. *How the JWT is parsed* is plumbing → omit it. ## Concern → construct map Read it top-to-bottom when mapping an existing app; read it right-to-left when reconstituting code -from a model. (Constructs and call syntax are defined in `references/LANG.md`.) +from a model. (Constructs and call syntax are defined in the language reference — run `pds lang`.) | App concern | PseudoScript | Disclosed? | |---|---|---| | HTTP route / controller / RPC handler | callable with `#[http("VERB /path")]` | body disclosed only for the orchestration that carries meaning; routing/serialization is the macro, not the body | | Use case / application service / interactor | disclosed callable | **disclose** | | Domain rule, validation, **authorization** decision | `if (r.isErr) { return Err(...) }` branches | **disclose** | -| Calculation / assembling a result from parts | `x = T from { a, b }` + the calls feeding it | **disclose** (provenance) | +| Calculation / assembling a result from parts | `x: T = T from { a, b }` + the calls feeding it | **disclose** (provenance) | | Repository / DAO / ORM mapper | black-box `component` (or `container`) with `fetch`/`save`/… signatures | black box | | Database / cache / queue infrastructure | black-box `container`, often tagged `#critical` | black box | | DTO / entity / domain event / message | `data` record; events as a discriminated union | fields disclosed when they matter; `data X;` otherwise | @@ -90,7 +91,8 @@ from a model. (Constructs and call syntax are defined in `references/LANG.md`.) 5. **Disclose the use cases.** Translate each service/interactor method into a disclosed callable, tracing the **business logic line for line**: every guard becomes an `if (…isErr) { return Err }`, every assembled value becomes `from { … }`, every dependency call becomes a `Target.method(args)`. - Keep bodies at flow-and-provenance level — never field-level arithmetic. + Every binding states its type (`x: T = …`). Keep bodies at flow-and-provenance level — never + field-level arithmetic. 6. **Mark the entry points.** Attach the trigger macro that matches how each callable is actually initiated: `#[http]`, `#[onevent]`, `#[schedule]`, `#[manual]`. These become inbound edges and sequence-diagram entry points. @@ -188,18 +190,18 @@ public container Checkout for Shop { /// Reserve stock, price it, charge, persist, announce. #[http("POST /orders")] public PlaceOrder(cmd: PlaceOrder): Result { - reserved = Inventory::Reservations.reserve(cmd.sku, cmd.qty) + reserved: Result = Inventory::Reservations.reserve(cmd.sku, cmd.qty) if (reserved.isErr) { return Err(reserved.error) } - quote = self.Quote(cmd.sku, cmd.qty) - order = Order from { cmd, quote } - paid = Payments.charge(order) + quote: number = self.Quote(cmd.sku, cmd.qty) + order: Order = Order from { cmd, quote } + paid: Result = Payments.charge(order) if (paid.isErr) { return Err(paid.error) } OrderStore::Orders.save(order) - evt = OrderPlaced from { order } + evt: OrderPlaced = OrderPlaced from { order } Bus.publish(evt) return Ok(order) } @@ -264,4 +266,4 @@ Before declaring a model done, confirm: - [ ] **Features cover the behaviour** — one `feature` per acceptance scenario, each `for` a real node, given/when/then in order, steps phrased as observable behaviour. - [ ] **Spec-faithful syntax** — names are fully qualified or aliased; visibility is correct; nothing - uses a form `references/LANG.md` doesn't define. \ No newline at end of file + uses a form the language reference (`pds lang`) doesn't define. \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..182c6ba --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,72 @@ +name: test + +on: + pull_request: + push: + branches: [main] + +permissions: + contents: read + +concurrency: + group: test-${{ github.ref }} + cancel-in-progress: true + +jobs: + rust: + name: Rust (fmt, clippy, test) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy, rustfmt + - uses: Swatinem/rust-cache@v2 + # The dependency-install tests shell out to `git commit`, which needs an + # author identity the bare runner lacks. + - name: Configure git identity for tests + run: | + git config --global user.email "ci@flying-dice.test" + git config --global user.name "pseudoscript CI" + - run: cargo fmt --all --check + - run: cargo clippy --workspace --all-targets -- -D warnings + - run: cargo test --workspace + + web: + name: Web IDE (vitest, build, e2e, storybook) + runs-on: ubuntu-latest + defaults: + run: + working-directory: web-ide + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + cache-dependency-path: web-ide/package-lock.json + - run: npm ci + # The wasm bundle is vendored under src/lib/pds-wasm, so no Rust build here. + - run: npm run check + - run: npm run test + - run: npm run build + - run: npx playwright install --with-deps chromium + - run: npm run test:e2e + - run: npm run build-storybook + + landing: + name: Landing (svelte-check, build) + runs-on: ubuntu-latest + defaults: + run: + working-directory: web-landing + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + cache-dependency-path: web-landing/package-lock.json + - run: npm ci + - run: npm run check + - run: npm run build diff --git a/.gitignore b/.gitignore index c07258a..3968ac9 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ target/ .DS_Store .idea/ .playwright-mcp/ +node_modules/ diff --git a/CLAUDE.md b/CLAUDE.md index 8f6c6a1..cc4bfad 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## What this repository is -This is the specification for **PseudoScript** (file extension `.pds`), an architecture-modeling language where the model *is* the source: it reads like high-level pseudocode, expresses C4-style structure (system / container / component / person), and compiles to SVG diagrams. The deliverable right now is the **spec and its conformance suite**, not an implementation — the Rust crate is a stub (`crates/pseudoscript/src/main.rs` prints "Hello, world!"). Most work here is writing and refining spec prose, conformance cases, and decision records. +This is the specification for **PseudoScript** (file extension `.pds`), an architecture-modeling language where the model *is* the source: it reads like high-level pseudocode, expresses C4-style structure (system / container / component / person), and compiles to SVG diagrams. The **spec and its conformance suite lead**: `LANG.md` and the cases under `CONFORMANCE/` are the source of truth, and expected outputs are hand-written, never copied from the implementation. The toolchain is now implemented — a Cargo workspace under `crates/` (lexer/parser, model/checker, formatter, diagram emitter, doc-site generator, LSP) driven by the `pds` binary — but it follows the spec, not the other way round. Much of the work here is still writing and refining spec prose, conformance cases, and decision records. ## Source of truth and its layers @@ -36,4 +36,13 @@ A `PreToolUse` hook in `.claude/settings.json` **denies any `git commit`** until ## Rust crate -A Cargo workspace (`resolver = "3"`, edition 2024) with one member, `crates/pseudoscript`, whose binary is named `pds`. Standard commands: `cargo build`, `cargo test`, `cargo run -p pseudoscript`, `cargo test ` for a single test. The implementation is not started; when writing Rust, the `idiomatic-rust` skill is required. +A Cargo workspace (`resolver = "3"`, edition 2024) with several members under `crates/` — `pseudoscript-syntax` (lexer/parser), `pseudoscript-model` (resolution + checks), `pseudoscript-format`, `pseudoscript-emit` (diagrams), `pseudoscript-doc`, `pseudoscript-lsp` / `pseudoscript-lsp-core`, `pseudoscript-wasm` — plus `crates/pseudoscript`, whose binary is `pds`. Standard commands: `cargo build`, `cargo test`, `cargo test -p pseudoscript ` for a single test. The `pds` binary wraps the libraries: `check`/`eval` (diagnostics — `eval` reads stdin so an agent can check a snippet without a file), `fmt`, `tokens`, `doc`, `outline`, `svg`, `lsp`, `lang`/`skill`, and the `add`/`install`/`update` dependency commands. When writing Rust, the `idiomatic-rust` skill is required. + +## One LSP API, two transports — do not fork it + +Language intelligence has a single source of truth: **`crates/pseudoscript-lsp-core`** — transport-neutral `text + position -> lsp_types value` handlers (completion, hover, definition, references, semantic tokens, folding, symbols, diagnostics, formatting). It depends on `pseudoscript-model` + the standalone `lsp-types` (pinned to tower-lsp 0.20's `=0.94.1`, WASM-safe), **not** `tower-lsp`. Two thin edges share it: + +- **`crates/pseudoscript-lsp`** — the stdio server (`server.rs` + `workspace.rs`): tower-lsp transport over `lsp-core`. What native editors (e.g. `pseudoscript-jetbrains`) get. +- **`crates/pseudoscript-wasm`** — the browser bridge: each language export calls the same `lsp-core` handler and serialises its `lsp_types` result to JSON, so the WASM API is byte-for-byte the LSP API. The web IDE (`web-ide/src/lib/pds.js` + `pseudoscript-language.js`) is an LSP client — it decodes delta-encoded semantic tokens, integer `CompletionItemKind`, line-based `FoldingRange`, Markdown `Hover`. `definition`/`references` stay WASM-ergonomic (fqn-based, with previews) because LSP `Location` is URL-centric and the browser has no file URLs; they still route through `model::resolve`, so no logic forks. Diagram/doc exports (`emit_scene`, `symbol_scene`, …) are WASM-only — no LSP equivalent. + +To change a language feature, edit it once in `lsp-core` (or its `model` primitive). After a *wasm-exported* surface changes, rebuild: `npm run build:wasm` in `web-ide`, then commit the regenerated `pds-wasm/` artifacts. Highlight **colours** and pure editor UX stay client-side. diff --git a/CONFORMANCE/generation/9-sequence.pds b/CONFORMANCE/generation/9-sequence.pds index 4ac0701..c647600 100644 --- a/CONFORMANCE/generation/9-sequence.pds +++ b/CONFORMANCE/generation/9-sequence.pds @@ -16,7 +16,7 @@ public container Inventory for Shop; public container Orders for Shop { #[manual] public Place(order: Order): Result { - r = Inventory.reserve(order) + r: Result = Inventory.reserve(order) if (r.isErr) { return Err(r.error) } diff --git a/CONFORMANCE/static/0-ok-worked-example.pds b/CONFORMANCE/static/0-ok-worked-example.pds index 40a52d3..8a8c455 100644 --- a/CONFORMANCE/static/0-ok-worked-example.pds +++ b/CONFORMANCE/static/0-ok-worked-example.pds @@ -16,7 +16,7 @@ public system Banking; public container Mainframe for Banking { public GetBankingInfo(id: number): Result { - r = AccountStore::Repository.fetch(id) + r: Result = AccountStore::Repository.fetch(id) if (r.isErr) { return Err(r.error) } diff --git a/CONFORMANCE/static/5-missing-return.pds b/CONFORMANCE/static/5-missing-return.pds index 4be3f4a..7cec524 100644 --- a/CONFORMANCE/static/5-missing-return.pds +++ b/CONFORMANCE/static/5-missing-return.pds @@ -10,7 +10,7 @@ public system Banking; public container Mainframe for Banking { Get(): Result { - r = self.Fetch() + r: Result = self.Fetch() if (r.isErr) { return Err(r.error) } diff --git a/CONFORMANCE/static/6-accessor-on-non-optional.diagnostics b/CONFORMANCE/static/6-accessor-on-non-optional.diagnostics new file mode 100644 index 0000000..f812399 --- /dev/null +++ b/CONFORMANCE/static/6-accessor-on-non-optional.diagnostics @@ -0,0 +1 @@ +no field `isSome` on `Ref`; `.isSome` is an `Option` accessor (§6.2) — type the value `Option` to use it diff --git a/CONFORMANCE/static/6-accessor-on-non-optional.pds b/CONFORMANCE/static/6-accessor-on-non-optional.pds new file mode 100644 index 0000000..8aeed1d --- /dev/null +++ b/CONFORMANCE/static/6-accessor-on-non-optional.pds @@ -0,0 +1,18 @@ +// LANG.md §6.2: `.isSome` is an `Option` accessor. `mv` is a plain record, not +// an `Option`, so the read names no field — the diagnostic points at typing the +// value `Option<...>`. + +//! example + +public data Ref { id: number } + +public system S; + +public container C for S { + pick(mv: Ref): number { + if (mv.isSome) { + return 1 + } + return 0 + } +} diff --git a/CONFORMANCE/static/6-call-method-on-data-value.diagnostics b/CONFORMANCE/static/6-call-method-on-data-value.diagnostics new file mode 100644 index 0000000..b8a9ab8 --- /dev/null +++ b/CONFORMANCE/static/6-call-method-on-data-value.diagnostics @@ -0,0 +1 @@ +no method `doThing` on `Conv` diff --git a/CONFORMANCE/static/6-call-method-on-data-value.pds b/CONFORMANCE/static/6-call-method-on-data-value.pds new file mode 100644 index 0000000..ed3b5a2 --- /dev/null +++ b/CONFORMANCE/static/6-call-method-on-data-value.pds @@ -0,0 +1,13 @@ +// LANG.md §6: a `.name(args)` call's member MUST exist on the receiver's type. +// `c` is a `Conv` record (fields only); a `data` value has no callables, so any +// method call on one is rejected. + +//! example + +public data Conv { id: uuid } + +public system S; + +public container C for S { + run(c: Conv): void { c.doThing() } +} diff --git a/CONFORMANCE/static/6-call-unknown-method-on-node.diagnostics b/CONFORMANCE/static/6-call-unknown-method-on-node.diagnostics new file mode 100644 index 0000000..d399956 --- /dev/null +++ b/CONFORMANCE/static/6-call-unknown-method-on-node.diagnostics @@ -0,0 +1 @@ +no method `nope` on `Store` diff --git a/CONFORMANCE/static/6-call-unknown-method-on-node.pds b/CONFORMANCE/static/6-call-unknown-method-on-node.pds new file mode 100644 index 0000000..632e12b --- /dev/null +++ b/CONFORMANCE/static/6-call-unknown-method-on-node.pds @@ -0,0 +1,16 @@ +// LANG.md §6: a `.name(args)` call's member MUST exist on the receiver's type. +// `Store` resolves to a component node; `nope` is not one of its callables. + +//! example + +public system S; + +public container Db for S; + +public component Store for Db { + get(): void; +} + +public container C for S { + run(): void { Store.nope() } +} diff --git a/CONFORMANCE/static/6-option-value-on-none.pds b/CONFORMANCE/static/6-option-value-on-none.pds index 4958aad..a349a87 100644 --- a/CONFORMANCE/static/6-option-value-on-none.pds +++ b/CONFORMANCE/static/6-option-value-on-none.pds @@ -10,7 +10,7 @@ public system Registry; public container Directory for Registry { public find(id: number): Option { - o = self.lookup(id) + o: Option = self.lookup(id) if (o.isNone) { return Some(o.value) } diff --git a/CONFORMANCE/static/6-result-wrong-accessor.pds b/CONFORMANCE/static/6-result-wrong-accessor.pds index 52da799..a2d63a6 100644 --- a/CONFORMANCE/static/6-result-wrong-accessor.pds +++ b/CONFORMANCE/static/6-result-wrong-accessor.pds @@ -11,7 +11,7 @@ public system Banking; public container Mainframe for Banking { public GetBankingInfo(id: number): Result { - r = AccountStore::Repository.fetch(id) + r: Result = AccountStore::Repository.fetch(id) if (r.isErr) { return Err(r.value) } diff --git a/CONFORMANCE/static/6-void-as-value.diagnostics b/CONFORMANCE/static/6-void-as-value.diagnostics new file mode 100644 index 0000000..19ef819 --- /dev/null +++ b/CONFORMANCE/static/6-void-as-value.diagnostics @@ -0,0 +1 @@ +unresolved reference `void`; `void` is a type, not a value — a void result returns bare `Ok` (§6.1) diff --git a/CONFORMANCE/static/6-void-as-value.pds b/CONFORMANCE/static/6-void-as-value.pds new file mode 100644 index 0000000..1db5e39 --- /dev/null +++ b/CONFORMANCE/static/6-void-as-value.pds @@ -0,0 +1,15 @@ +// LANG.md §6.1: `void` is a type, not a value. A void-returning callable returns +// with a bare `Ok`; `Ok(void)` reads `void` as a value, which resolves to no +// parameter, binding, node, alias, or variant. + +//! example + +public data Failure { reason: string } + +public system S; + +public container C for S { + run(): Result { + return Ok(void) + } +} diff --git a/CONFORMANCE/static/7-1-binding-type-mismatch.diagnostics b/CONFORMANCE/static/7-1-binding-type-mismatch.diagnostics new file mode 100644 index 0000000..c6fc173 --- /dev/null +++ b/CONFORMANCE/static/7-1-binding-type-mismatch.diagnostics @@ -0,0 +1 @@ +binding `n` is annotated `number` but its value is `string` diff --git a/CONFORMANCE/static/7-1-binding-type-mismatch.pds b/CONFORMANCE/static/7-1-binding-type-mismatch.pds new file mode 100644 index 0000000..5b7fb10 --- /dev/null +++ b/CONFORMANCE/static/7-1-binding-type-mismatch.pds @@ -0,0 +1,12 @@ +// LANG.md §7.1 (ADR-027): a binding's annotation must match a determinable +// initialiser. A `number`-annotated binding initialised with a string literal +// is rejected. + +//! example + +public system S; +public container C for S { + run(): void { + n: number = "" + } +} diff --git a/CONFORMANCE/static/7-rebind-rejected.pds b/CONFORMANCE/static/7-rebind-rejected.pds index 11c6d62..b9d8f9c 100644 --- a/CONFORMANCE/static/7-rebind-rejected.pds +++ b/CONFORMANCE/static/7-rebind-rejected.pds @@ -9,8 +9,8 @@ public system Banking; public container Mainframe for Banking { Run(): void { - r = self.Make() - r = self.Make() + r: Info = self.Make() + r: Info = self.Make() } Make(): Info; } diff --git a/CONFORMANCE/syntax/3-option.pds b/CONFORMANCE/syntax/3-option.pds index b94a174..5239f56 100644 --- a/CONFORMANCE/syntax/3-option.pds +++ b/CONFORMANCE/syntax/3-option.pds @@ -10,7 +10,7 @@ public system Registry; public container Directory for Registry { /// The optional person on file for an id. public find(id: number): Option { - o = self.lookup(id) + o: Option = self.lookup(id) if (o.isNone) { return None } diff --git a/CONFORMANCE/syntax/7-1-untyped-assignment-rejected.reject b/CONFORMANCE/syntax/7-1-untyped-assignment-rejected.reject new file mode 100644 index 0000000..def9d63 --- /dev/null +++ b/CONFORMANCE/syntax/7-1-untyped-assignment-rejected.reject @@ -0,0 +1,10 @@ +// LANG.md §7.1 (ADR-027): a binding states its type. An unannotated +// `x = Expr` no longer parses. + +public system S; +public container C for S { + run(): void { + x = self.make() + } + make(): number; +} diff --git a/CONFORMANCE/syntax/7-1-untyped-assignment-rejected.reject.expected b/CONFORMANCE/syntax/7-1-untyped-assignment-rejected.reject.expected new file mode 100644 index 0000000..7264244 --- /dev/null +++ b/CONFORMANCE/syntax/7-1-untyped-assignment-rejected.reject.expected @@ -0,0 +1 @@ +assignment requires a type annotation: write `name: Type = …` diff --git a/CONFORMANCE/syntax/7-chaining.pds b/CONFORMANCE/syntax/7-chaining.pds index 5c5b9ac..e7016e5 100644 --- a/CONFORMANCE/syntax/7-chaining.pds +++ b/CONFORMANCE/syntax/7-chaining.pds @@ -7,7 +7,7 @@ data Info { owner: string } public container Mainframe for Banking { Run(): void { - a = Store::Repo.fetch(1).value.owner - b = self.Pick().first().tag + a: string = Store::Repo.fetch(1).value.owner + b: string = self.Pick().first().tag } } diff --git a/CONFORMANCE/syntax/7-from-labelled-source.reject b/CONFORMANCE/syntax/7-from-labelled-source.reject new file mode 100644 index 0000000..182b34f --- /dev/null +++ b/CONFORMANCE/syntax/7-from-labelled-source.reject @@ -0,0 +1,14 @@ +// LANG.md §7.2: a `from` source set holds bare references (bindings, field +// accesses, or calls), separated by `,` and closed by `}`. A `key: value` +// label is not a source — `data` is never constructed with field values +// (ADR-003) — so the `:` is rejected at the source set. + +//! example + +public data Thing { name: string } + +public system S; + +public container C for S { + make(): Thing { return Thing from { name: "x" } } +} diff --git a/CONFORMANCE/syntax/7-from-labelled-source.reject.expected b/CONFORMANCE/syntax/7-from-labelled-source.reject.expected new file mode 100644 index 0000000..2c5ca82 --- /dev/null +++ b/CONFORMANCE/syntax/7-from-labelled-source.reject.expected @@ -0,0 +1 @@ +`from` takes bare references, not `field: value` — bind the value to a name and list the name (§7.2) diff --git a/CONFORMANCE/syntax/7-statements.pds b/CONFORMANCE/syntax/7-statements.pds index f186084..fee27f0 100644 --- a/CONFORMANCE/syntax/7-statements.pds +++ b/CONFORMANCE/syntax/7-statements.pds @@ -8,13 +8,13 @@ data BankingInfo { id: number } public container Mainframe for Banking { Run(): void { - a = Foo.getThing() - b = Bar.getOther() - c = BankingInfo from { a, b } + a: Result = Foo.getThing() + b: BankingInfo = Bar.getOther() + c: BankingInfo = BankingInfo from { a, b } if (a.isErr) { return } else { - x = a.value + x: BankingInfo = a.value } while (cond) { self.step() diff --git a/Cargo.lock b/Cargo.lock index defceb3..09836ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1335,6 +1335,7 @@ dependencies = [ "futures", "notify", "pseudoscript-doc", + "pseudoscript-emit", "pseudoscript-format", "pseudoscript-lsp", "pseudoscript-model", @@ -1361,6 +1362,7 @@ dependencies = [ "cucumber", "futures", "pseudoscript-emit", + "pseudoscript-layout", "pseudoscript-model", "pulldown-cmark", "rquickjs", @@ -1407,6 +1409,7 @@ dependencies = [ "cucumber", "futures", "pseudoscript-format", + "pseudoscript-lsp-core", "pseudoscript-model", "pseudoscript-syntax", "serde_json", @@ -1415,6 +1418,16 @@ dependencies = [ "walkdir", ] +[[package]] +name = "pseudoscript-lsp-core" +version = "0.1.0" +dependencies = [ + "lsp-types", + "pseudoscript-format", + "pseudoscript-model", + "pseudoscript-syntax", +] + [[package]] name = "pseudoscript-model" version = "0.1.0" @@ -1445,6 +1458,7 @@ dependencies = [ "pseudoscript-doc", "pseudoscript-emit", "pseudoscript-format", + "pseudoscript-lsp-core", "pseudoscript-model", "pseudoscript-syntax", "serde", diff --git a/LANG.md b/LANG.md index 4e08d44..7e6183d 100644 --- a/LANG.md +++ b/LANG.md @@ -302,9 +302,9 @@ Valid inside callable bodies. Each maps to a sequence-diagram element. | Construct | Syntax | Sequence mapping | |-----------|--------|------------------| -| Assignment | `x = Expr` | — (binds the name; single-assignment) | +| Assignment | `x: Type = Expr` | — (binds the name; single-assignment) | | Call | `Target.method(args)` | solid request → return arrow | -| Composition | `x = Type from { a, b }` | — (local; provenance edge in data-flow view) | +| Composition | `x: Type = Type from { a, b }` | — (local; provenance edge in data-flow view) | | Return | `return Expr` | return arrow (`Err` labeled with `E`) | | If | `if (C) { } else { }` | `alt` frame | | For | `for (x in Expr) { }` | `loop` frame | @@ -313,14 +313,14 @@ Valid inside callable bodies. Each maps to a sequence-diagram element. An `if`/`while` condition `C` MUST be `bool` where its type is inferable (ADR-023). ### 7.1 Assignment -`x = Expr` binds `x` once. Type is inferred from the right-hand side. Bindings are immutable: re-binding a name MUST be rejected, including by an inner `if`/`for`/`while` block (no shadowing). +`x: Type = Expr` binds `x` once. The binding MUST state its type; an unannotated `x = Expr` is rejected. Where the initialiser's type is determinable — a literal, a `from`, an `Ok`/`Err`/`Some`/`None` marker, or a bare reference — it MUST match the annotation; a call, field access, `self`, or `::` path is not inferred (ADR-022), so there the annotation stands. Bindings are immutable: re-binding a name MUST be rejected, including by an inner `if`/`for`/`while` block (no shadowing). ### 7.2 Composition with `from` `x` of type `Type` is composed *from* a set of sources. The braces enclose a **source set** (bindings, field accesses, or calls). ```pds -a = Foo.getThing() -b = Bar.getOther() -c = BankingInfo from { a, b } +a: Thing = Foo.getThing() +b: Other = Bar.getOther() +c: BankingInfo = BankingInfo from { a, b } ``` - `from` composes a `data` record or union variant. The built-in constructors `Ok` / `Err` / `Some` / `None` produce `Result` / `Option` values (§6). No other construction exists. - The `from` target MUST resolve to a `data` record or union variant; a primitive, `Result`, `Option`, or node target MUST be rejected. @@ -494,7 +494,7 @@ Primitive = "number" | "string" | "bool" | "datetime" | "uuid" | "void" ; Block = "{" { Stmt } "}" ; Stmt = Assign | Return | If | For | While | Postfix ; -Assign = Ident "=" Expr ; // binds once (single-assignment) +Assign = Ident ":" Type "=" Expr ; // binds once (single-assignment), type stated Return = "return" [ Expr ] ; If = "if" "(" Expr ")" Block [ "else" Block ] ; For = "for" "(" Ident "in" Expr ")" Block ; // Expr MUST be an array type diff --git a/README.md b/README.md new file mode 100644 index 0000000..269b36a --- /dev/null +++ b/README.md @@ -0,0 +1,43 @@ +
+ +# PseudoScript + +### Model the intent. Implement the detail. + +Architecture-as-code for the agentic era. Write your system as plain +[pseudocode](https://en.wikipedia.org/wiki/Pseudocode); the toolchain validates +the model and generates the C4 and sequence diagrams your team and your agents +build against. [Model-driven engineering](https://en.wikipedia.org/wiki/Model-driven_engineering), +reignited. + +[**Open the Web IDE →**](http://ide.pdscript.dev/) · [Language spec](LANG.md) · [Patterns](PATTERNS.md) + +
+ +--- + +## Where things are + +| Path | What it is | +| --- | --- | +| [`LANG.md`](LANG.md) | The normative language spec (§1–§12). The source of truth. | +| [`PATTERNS.md`](PATTERNS.md) | Idioms and recipes for modelling in PseudoScript. | +| [`CONFORMANCE/`](CONFORMANCE/) | The executable contract — lexical, syntax, static, generation cases. | +| [`decisions/`](decisions/) | Architecture Decision Records, one per resolved fork. | +| [`crates/`](crates/) | The Rust toolchain: parser, checker, formatter, diagram emitter, LSP, and the `pds` binary. | +| [`web-ide/`](web-ide/) | The browser IDE — the whole toolchain compiled to WebAssembly. | +| [`web-landing/`](web-landing/) | The marketing site. | +| [`pseudoscript/`](pseudoscript/) | A worked example: PseudoScript modelling its own compiler. | + +## The `pds` CLI + +```sh +pds init # scaffold a workspace +pds eval # read a model from stdin, report diagnostics (great for agents) +pds check # check a file or workspace +pds doc --serve # render the live C4 + sequence-diagram doc site +pds lang | pds skill # print the grammar / authoring method for an LLM +``` + +Building a model with an agent? `pds skill` and `pds lang` teach it the method +and grammar; `pds eval` lets it check its work as it goes. diff --git a/crates/pseudoscript-doc/Cargo.toml b/crates/pseudoscript-doc/Cargo.toml index 2c8677a..656e898 100644 --- a/crates/pseudoscript-doc/Cargo.toml +++ b/crates/pseudoscript-doc/Cargo.toml @@ -13,6 +13,7 @@ path = "src/lib.rs" [dependencies] pseudoscript-model = { path = "../pseudoscript-model" } pseudoscript-emit = { path = "../pseudoscript-emit" } +pseudoscript-layout = { path = "../pseudoscript-layout" } serde = { version = "1", features = ["derive"] } serde_json = "1" # Renders `[[doc.sidebar]]` markdown pages to HTML. Pure Rust (no C), so it diff --git a/crates/pseudoscript-doc/examples/smoke.rs b/crates/pseudoscript-doc/examples/smoke.rs index 4e6ed12..715c517 100644 --- a/crates/pseudoscript-doc/examples/smoke.rs +++ b/crates/pseudoscript-doc/examples/smoke.rs @@ -34,7 +34,7 @@ public container Api for Bank { /// Post a new entry. #[manual] public Post(posting: Posting): number { - n = Ledger.Append(posting) + n: number = Ledger.Append(posting) return n } } diff --git a/crates/pseudoscript-doc/src/assets/client.js b/crates/pseudoscript-doc/src/assets/client.js index 53bfba0..4e88e7c 100644 --- a/crates/pseudoscript-doc/src/assets/client.js +++ b/crates/pseudoscript-doc/src/assets/client.js @@ -1,76 +1,76 @@ -(()=>{var Ah=Object.defineProperty;var Nh=e=>{throw TypeError(e)};var dC=(e,t,r)=>t in e?Ah(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r;var v=(e,t)=>()=>(e&&(t=e(e=0)),t);var jd=(e,t)=>{for(var r in t)Ah(e,r,{get:t[r],enumerable:!0})};var Be=(e,t,r)=>dC(e,typeof t!="symbol"?t+"":t,r),Kd=(e,t,r)=>t.has(e)||Nh("Cannot "+r);var m=(e,t,r)=>(Kd(e,t,"read from private field"),r?r.call(e):t.get(e)),U=(e,t,r)=>t.has(e)?Nh("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,r),ge=(e,t,r,n)=>(Kd(e,t,"write to private field"),n?n.call(e,r):t.set(e,r),r),Ie=(e,t,r)=>(Kd(e,t,"access private method"),r);var Fh=v(()=>{});var G,qd=v(()=>{G=!1});var Ne=v(()=>{Fh();qd();qd()});function Yo(e){return typeof e=="function"}function Qh(e){return e()}function Ki(e){for(var t=0;t{e=n,t=o});return{promise:r,resolve:e,reject:t}}function Rt(e,t,r=!1){return e===void 0?r?t():t:e}function dn(e,t){if(Array.isArray(e))return e;if(t===void 0||!(Symbol.iterator in e))return Array.from(e);let r=[];for(let n of e)if(r.push(n),r.length===t)break;return r}function ru(e,t){var r={};for(var n in e)t.includes(n)||(r[n]=e[n]);for(var o of Object.getOwnPropertySymbols(e))Object.propertyIsEnumerable.call(e,o)&&!t.includes(o)&&(r[o]=e[o]);return r}var Yr,Gh,_o,ji,eu,Mt,rr,Gl,Zl,Zh,bo,tu,ft,Le=v(()=>{Yr=Array.isArray,Gh=Array.prototype.indexOf,_o=Array.prototype.includes,ji=Array.from,eu=Object.keys,Mt=Object.defineProperty,rr=Object.getOwnPropertyDescriptor,Gl=Object.getOwnPropertyDescriptors,Zl=Object.prototype,Zh=Array.prototype,bo=Object.getPrototypeOf,tu=Object.isExtensible;ft=()=>{}});var yt,qi,Rh,Rl,Ll,Ks,qs,ea,xo,nu,yo,es,Ul,Po,Nr,Ae=v(()=>{yt=Symbol("$state"),qi=Symbol("legacy props"),Rh=Symbol(""),Rl=Symbol("proxy path"),Ll=Symbol("attributes"),Ks=Symbol("class"),qs=Symbol("style"),ea=Symbol("text"),xo=Symbol("form reset"),nu=Symbol("hmr anchor"),yo=new class extends Error{constructor(){super(...arguments);Be(this,"name","StaleReactionError");Be(this,"message","The reaction that called `getAbortSignal()` was re-run or destroyed")}},es=!!globalThis.document?.contentType&&globalThis.document.contentType.includes("xml"),Ul=1,Po=3,Nr=8});function Tl(e){if(G){let t=new Error(`experimental_async_required +(()=>{var $p=Object.defineProperty;var Ap=e=>{throw TypeError(e)};var mC=(e,t,r)=>t in e?$p(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r;var v=(e,t)=>()=>(e&&(t=e(e=0)),t);var Pd=(e,t)=>{for(var r in t)$p(e,r,{get:t[r],enumerable:!0})};var Ae=(e,t,r)=>mC(e,typeof t!="symbol"?t+"":t,r),Jd=(e,t,r)=>t.has(e)||Ap("Cannot "+r);var m=(e,t,r)=>(Jd(e,t,"read from private field"),r?r.call(e):t.get(e)),L=(e,t,r)=>t.has(e)?Ap("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,r),he=(e,t,r,n)=>(Jd(e,t,"write to private field"),n?n.call(e,r):t.set(e,r),r),Ce=(e,t,r)=>(Jd(e,t,"access private method"),r);var Gp=v(()=>{});var R,jd=v(()=>{R=!1});var Se=v(()=>{Gp();jd();jd()});function Yo(e){return typeof e=="function"}function Zp(e){return e()}function Ji(e){for(var t=0;t{e=n,t=o});return{promise:r,resolve:e,reject:t}}function Qt(e,t,r=!1){return e===void 0?r?t():t:e}function un(e,t){if(Array.isArray(e))return e;if(t===void 0||!(Symbol.iterator in e))return Array.from(e);let r=[];for(let n of e)if(r.push(n),r.length===t)break;return r}function eu(e,t){var r={};for(var n in e)t.includes(n)||(r[n]=e[n]);for(var o of Object.getOwnPropertySymbols(e))Object.propertyIsEnumerable.call(e,o)&&!t.includes(o)&&(r[o]=e[o]);return r}var zr,Fp,vo,Pi,Kd,Ht,tr,Nl,Ql,Sp,_o,qd,ct,Re=v(()=>{zr=Array.isArray,Fp=Array.prototype.indexOf,vo=Array.prototype.includes,Pi=Array.from,Kd=Object.keys,Ht=Object.defineProperty,tr=Object.getOwnPropertyDescriptor,Nl=Object.getOwnPropertyDescriptors,Ql=Object.prototype,Sp=Array.prototype,_o=Object.getPrototypeOf,qd=Object.isExtensible;ct=()=>{}});var _t,ji,kp,Rl,Ul,qs,ea,ta,ra,tu,bo,Ki,Ll,zo,Zr,Fe=v(()=>{_t=Symbol("$state"),ji=Symbol("legacy props"),kp=Symbol(""),Rl=Symbol("proxy path"),Ul=Symbol("attributes"),qs=Symbol("class"),ea=Symbol("style"),ta=Symbol("text"),ra=Symbol("form reset"),tu=Symbol("hmr anchor"),bo=new class extends Error{constructor(){super(...arguments);Ae(this,"name","StaleReactionError");Ae(this,"message","The reaction that called `getAbortSignal()` was re-run or destroyed")}},Ki=!!globalThis.document?.contentType&&globalThis.document.contentType.includes("xml"),Ll=1,zo=3,Zr=8});function Vl(e){if(R){let t=new Error(`experimental_async_required Cannot use \`${e}(...)\` unless the \`experimental.async\` compiler option is \`true\` -https://svelte.dev/e/experimental_async_required`);throw t.name="Svelte error",t}else throw new Error("https://svelte.dev/e/experimental_async_required")}function Lh(e){if(G){let t=new Error(`invariant_violation +https://svelte.dev/e/experimental_async_required`);throw t.name="Svelte error",t}else throw new Error("https://svelte.dev/e/experimental_async_required")}function Np(e){if(R){let t=new Error(`invariant_violation An invariant violation occurred, meaning Svelte's internal assumptions were flawed. This is a bug in Svelte, not your app \u2014 please open an issue at https://github.com/sveltejs/svelte, citing the following message: "${e}" -https://svelte.dev/e/invariant_violation`);throw t.name="Svelte error",t}else throw new Error("https://svelte.dev/e/invariant_violation")}function Mn(e){if(G){let t=new Error(`lifecycle_outside_component +https://svelte.dev/e/invariant_violation`);throw t.name="Svelte error",t}else throw new Error("https://svelte.dev/e/invariant_violation")}function Mn(e){if(R){let t=new Error(`lifecycle_outside_component \`${e}(...)\` can only be used during component initialisation -https://svelte.dev/e/lifecycle_outside_component`);throw t.name="Svelte error",t}else throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function Uh(){if(G){let e=new Error(`missing_context +https://svelte.dev/e/lifecycle_outside_component`);throw t.name="Svelte error",t}else throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function Qp(){if(R){let e=new Error(`missing_context Context was not set in a parent component -https://svelte.dev/e/missing_context`);throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/missing_context")}var ta=v(()=>{Ne()});function Vh(){if(G){let e=new Error("async_derived_orphan\nCannot create a `$derived(...)` with an `await` expression outside of an effect tree\nhttps://svelte.dev/e/async_derived_orphan");throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/async_derived_orphan")}function ou(){if(G){let e=new Error("bind_invalid_checkbox_value\nUsing `bind:value` together with a checkbox input is not allowed. Use `bind:checked` instead\nhttps://svelte.dev/e/bind_invalid_checkbox_value");throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/bind_invalid_checkbox_value")}function Dh(){if(G){let e=new Error(`derived_references_self +https://svelte.dev/e/missing_context`);throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/missing_context")}var na=v(()=>{Se()});function Rp(){if(R){let e=new Error("async_derived_orphan\nCannot create a `$derived(...)` with an `await` expression outside of an effect tree\nhttps://svelte.dev/e/async_derived_orphan");throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/async_derived_orphan")}function Up(){if(R){let e=new Error(`derived_references_self A derived value cannot reference itself recursively -https://svelte.dev/e/derived_references_self`);throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/derived_references_self")}function iu(e,t,r){if(G){let n=new Error(`each_key_duplicate +https://svelte.dev/e/derived_references_self`);throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/derived_references_self")}function ru(e,t,r){if(R){let n=new Error(`each_key_duplicate ${r?`Keyed each block has duplicate key \`${r}\` at indexes ${e} and ${t}`:`Keyed each block has duplicate key at indexes ${e} and ${t}`} -https://svelte.dev/e/each_key_duplicate`);throw n.name="Svelte error",n}else throw new Error("https://svelte.dev/e/each_key_duplicate")}function Oh(e,t,r){if(G){let n=new Error(`each_key_volatile +https://svelte.dev/e/each_key_duplicate`);throw n.name="Svelte error",n}else throw new Error("https://svelte.dev/e/each_key_duplicate")}function Lp(e,t,r){if(R){let n=new Error(`each_key_volatile Keyed each block has key that is not idempotent \u2014 the key for item at index ${e} was \`${t}\` but is now \`${r}\`. Keys must be the same each time for a given item -https://svelte.dev/e/each_key_volatile`);throw n.name="Svelte error",n}else throw new Error("https://svelte.dev/e/each_key_volatile")}function Xh(e){if(G){let t=new Error(`effect_in_teardown +https://svelte.dev/e/each_key_volatile`);throw n.name="Svelte error",n}else throw new Error("https://svelte.dev/e/each_key_volatile")}function Vp(e){if(R){let t=new Error(`effect_in_teardown \`${e}\` cannot be used inside an effect cleanup function -https://svelte.dev/e/effect_in_teardown`);throw t.name="Svelte error",t}else throw new Error("https://svelte.dev/e/effect_in_teardown")}function Mh(){if(G){let e=new Error("effect_in_unowned_derived\nEffect cannot be created inside a `$derived` value that was not itself created inside an effect\nhttps://svelte.dev/e/effect_in_unowned_derived");throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/effect_in_unowned_derived")}function Wh(e){if(G){let t=new Error(`effect_orphan +https://svelte.dev/e/effect_in_teardown`);throw t.name="Svelte error",t}else throw new Error("https://svelte.dev/e/effect_in_teardown")}function Wp(){if(R){let e=new Error("effect_in_unowned_derived\nEffect cannot be created inside a `$derived` value that was not itself created inside an effect\nhttps://svelte.dev/e/effect_in_unowned_derived");throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/effect_in_unowned_derived")}function Tp(e){if(R){let t=new Error(`effect_orphan \`${e}\` can only be used inside an effect (e.g. during component initialisation) -https://svelte.dev/e/effect_orphan`);throw t.name="Svelte error",t}else throw new Error("https://svelte.dev/e/effect_orphan")}function Hh(){if(G){let e=new Error(`effect_update_depth_exceeded +https://svelte.dev/e/effect_orphan`);throw t.name="Svelte error",t}else throw new Error("https://svelte.dev/e/effect_orphan")}function Dp(){if(R){let e=new Error(`effect_update_depth_exceeded Maximum update depth exceeded. This typically indicates that an effect reads and writes the same piece of state -https://svelte.dev/e/effect_update_depth_exceeded`);throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/effect_update_depth_exceeded")}function zh(){if(G){let e=new Error(`fork_discarded +https://svelte.dev/e/effect_update_depth_exceeded`);throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/effect_update_depth_exceeded")}function Op(){if(R){let e=new Error(`fork_discarded Cannot commit a fork that was already discarded -https://svelte.dev/e/fork_discarded`);throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/fork_discarded")}function Yh(){if(G){let e=new Error(`fork_timing +https://svelte.dev/e/fork_discarded`);throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/fork_discarded")}function Hp(){if(R){let e=new Error(`fork_timing Cannot create a fork inside an effect or when state changes are pending -https://svelte.dev/e/fork_timing`);throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/fork_timing")}function Ph(){if(G){let e=new Error("get_abort_signal_outside_reaction\n`getAbortSignal()` can only be called inside an effect or derived\nhttps://svelte.dev/e/get_abort_signal_outside_reaction");throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/get_abort_signal_outside_reaction")}function Jh(e){if(G){let t=new Error(`hydratable_missing_but_required +https://svelte.dev/e/fork_timing`);throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/fork_timing")}function Mp(){if(R){let e=new Error("get_abort_signal_outside_reaction\n`getAbortSignal()` can only be called inside an effect or derived\nhttps://svelte.dev/e/get_abort_signal_outside_reaction");throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/get_abort_signal_outside_reaction")}function Yp(e){if(R){let t=new Error(`hydratable_missing_but_required Expected to find a hydratable with key \`${e}\` during hydration, but did not. -https://svelte.dev/e/hydratable_missing_but_required`);throw t.name="Svelte error",t}else throw new Error("https://svelte.dev/e/hydratable_missing_but_required")}function jh(){if(G){let e=new Error(`hydration_failed +https://svelte.dev/e/hydratable_missing_but_required`);throw t.name="Svelte error",t}else throw new Error("https://svelte.dev/e/hydratable_missing_but_required")}function zp(){if(R){let e=new Error(`hydration_failed Failed to hydrate the application -https://svelte.dev/e/hydration_failed`);throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/hydration_failed")}function Kh(){if(G){let e=new Error("invalid_snippet\nCould not `{@render}` snippet due to the expression being `null` or `undefined`. Consider using optional chaining `{@render snippet?.()}`\nhttps://svelte.dev/e/invalid_snippet");throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/invalid_snippet")}function su(e){if(G){let t=new Error(`lifecycle_legacy_only +https://svelte.dev/e/hydration_failed`);throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/hydration_failed")}function Pp(){if(R){let e=new Error("invalid_snippet\nCould not `{@render}` snippet due to the expression being `null` or `undefined`. Consider using optional chaining `{@render snippet?.()}`\nhttps://svelte.dev/e/invalid_snippet");throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/invalid_snippet")}function nu(e){if(R){let t=new Error(`lifecycle_legacy_only \`${e}(...)\` cannot be used in runes mode -https://svelte.dev/e/lifecycle_legacy_only`);throw t.name="Svelte error",t}else throw new Error("https://svelte.dev/e/lifecycle_legacy_only")}function qh(e){if(G){let t=new Error(`props_invalid_value +https://svelte.dev/e/lifecycle_legacy_only`);throw t.name="Svelte error",t}else throw new Error("https://svelte.dev/e/lifecycle_legacy_only")}function Jp(e){if(R){let t=new Error(`props_invalid_value Cannot do \`bind:${e}={undefined}\` when \`${e}\` has a fallback value -https://svelte.dev/e/props_invalid_value`);throw t.name="Svelte error",t}else throw new Error("https://svelte.dev/e/props_invalid_value")}function eg(e){if(G){let t=new Error(`props_rest_readonly +https://svelte.dev/e/props_invalid_value`);throw t.name="Svelte error",t}else throw new Error("https://svelte.dev/e/props_invalid_value")}function jp(e){if(R){let t=new Error(`props_rest_readonly Rest element properties of \`$props()\` such as \`${e}\` are readonly -https://svelte.dev/e/props_rest_readonly`);throw t.name="Svelte error",t}else throw new Error("https://svelte.dev/e/props_rest_readonly")}function tg(e){if(G){let t=new Error(`rune_outside_svelte +https://svelte.dev/e/props_rest_readonly`);throw t.name="Svelte error",t}else throw new Error("https://svelte.dev/e/props_rest_readonly")}function Kp(e){if(R){let t=new Error(`rune_outside_svelte The \`${e}\` rune is only available inside \`.svelte\` and \`.svelte.js/ts\` files -https://svelte.dev/e/rune_outside_svelte`);throw t.name="Svelte error",t}else throw new Error("https://svelte.dev/e/rune_outside_svelte")}function rg(){if(G){let e=new Error("set_context_after_init\n`setContext` must be called when a component first initializes, not in a subsequent effect or after an `await` expression\nhttps://svelte.dev/e/set_context_after_init");throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/set_context_after_init")}function ng(){if(G){let e=new Error("state_descriptors_fixed\nProperty descriptors defined on `$state` objects must contain `value` and always be `enumerable`, `configurable` and `writable`.\nhttps://svelte.dev/e/state_descriptors_fixed");throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/state_descriptors_fixed")}function og(){if(G){let e=new Error("state_prototype_fixed\nCannot set prototype of `$state` object\nhttps://svelte.dev/e/state_prototype_fixed");throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/state_prototype_fixed")}function ig(){if(G){let e=new Error("state_unsafe_mutation\nUpdating state inside `$derived(...)`, `$inspect(...)` or a template expression is forbidden. If the value should not be reactive, declare it without `$state`\nhttps://svelte.dev/e/state_unsafe_mutation");throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/state_unsafe_mutation")}function sg(){if(G){let e=new Error("svelte_boundary_reset_onerror\nA `` `reset` function cannot be called while an error is still being handled\nhttps://svelte.dev/e/svelte_boundary_reset_onerror");throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/svelte_boundary_reset_onerror")}var Lt=v(()=>{Ne();ta()});var Bn,He,yr,Vl,ra,au,lu,Te=v(()=>{Bn={},He=Symbol("uninitialized"),yr=Symbol("filename"),Vl="http://www.w3.org/1999/xhtml",ra="http://www.w3.org/2000/svg",au="http://www.w3.org/1998/Math/MathML",lu="@attach"});function ag(e){G?console.warn(`%c[svelte] await_reactivity_loss +https://svelte.dev/e/rune_outside_svelte`);throw t.name="Svelte error",t}else throw new Error("https://svelte.dev/e/rune_outside_svelte")}function qp(){if(R){let e=new Error("set_context_after_init\n`setContext` must be called when a component first initializes, not in a subsequent effect or after an `await` expression\nhttps://svelte.dev/e/set_context_after_init");throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/set_context_after_init")}function eh(){if(R){let e=new Error("state_descriptors_fixed\nProperty descriptors defined on `$state` objects must contain `value` and always be `enumerable`, `configurable` and `writable`.\nhttps://svelte.dev/e/state_descriptors_fixed");throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/state_descriptors_fixed")}function th(){if(R){let e=new Error("state_prototype_fixed\nCannot set prototype of `$state` object\nhttps://svelte.dev/e/state_prototype_fixed");throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/state_prototype_fixed")}function rh(){if(R){let e=new Error("state_unsafe_mutation\nUpdating state inside `$derived(...)`, `$inspect(...)` or a template expression is forbidden. If the value should not be reactive, declare it without `$state`\nhttps://svelte.dev/e/state_unsafe_mutation");throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/state_unsafe_mutation")}function nh(){if(R){let e=new Error("svelte_boundary_reset_onerror\nA `` `reset` function cannot be called while an error is still being handled\nhttps://svelte.dev/e/svelte_boundary_reset_onerror");throw e.name="Svelte error",e}else throw new Error("https://svelte.dev/e/svelte_boundary_reset_onerror")}var Xt=v(()=>{Se();na()});var Gn,Ye,Ir,Wl,oa,ou,iu,Ve=v(()=>{Gn={},Ye=Symbol("uninitialized"),Ir=Symbol("filename"),Wl="http://www.w3.org/1999/xhtml",oa="http://www.w3.org/2000/svg",ou="http://www.w3.org/1998/Math/MathML",iu="@attach"});function oh(e){R?console.warn(`%c[svelte] await_reactivity_loss %cDetected reactivity loss when reading \`${e}\`. This happens when state is read in an async function after an earlier \`await\` -https://svelte.dev/e/await_reactivity_loss`,Fr,Gr):console.warn("https://svelte.dev/e/await_reactivity_loss")}function lg(e,t){G?console.warn(`%c[svelte] await_waterfall +https://svelte.dev/e/await_reactivity_loss`,kr,Nr):console.warn("https://svelte.dev/e/await_reactivity_loss")}function ih(e,t){R?console.warn(`%c[svelte] await_waterfall %cAn async derived, \`${e}\` (${t}) was not read immediately after it resolved. This often indicates an unnecessary waterfall, which can slow down your app -https://svelte.dev/e/await_waterfall`,Fr,Gr):console.warn("https://svelte.dev/e/await_waterfall")}function cg(){G?console.warn(`%c[svelte] derived_inert +https://svelte.dev/e/await_waterfall`,kr,Nr):console.warn("https://svelte.dev/e/await_waterfall")}function sh(){R?console.warn(`%c[svelte] derived_inert %cReading a derived belonging to a now-destroyed effect may result in stale values -https://svelte.dev/e/derived_inert`,Fr,Gr):console.warn("https://svelte.dev/e/derived_inert")}function dg(e){G?console.warn(`%c[svelte] hydratable_missing_but_expected +https://svelte.dev/e/derived_inert`,kr,Nr):console.warn("https://svelte.dev/e/derived_inert")}function ah(e){R?console.warn(`%c[svelte] hydratable_missing_but_expected %cExpected to find a hydratable with key \`${e}\` during hydration, but did not. -https://svelte.dev/e/hydratable_missing_but_expected`,Fr,Gr):console.warn("https://svelte.dev/e/hydratable_missing_but_expected")}function ug(e,t,r){G?console.warn(`%c[svelte] hydration_attribute_changed +https://svelte.dev/e/hydratable_missing_but_expected`,kr,Nr):console.warn("https://svelte.dev/e/hydratable_missing_but_expected")}function lh(e,t,r){R?console.warn(`%c[svelte] hydration_attribute_changed %cThe \`${e}\` attribute on \`${t}\` changed its value between server and client renders. The client value, \`${r}\`, will be ignored in favour of the server value -https://svelte.dev/e/hydration_attribute_changed`,Fr,Gr):console.warn("https://svelte.dev/e/hydration_attribute_changed")}function fg(e){G?console.warn(`%c[svelte] hydration_html_changed +https://svelte.dev/e/hydration_attribute_changed`,kr,Nr):console.warn("https://svelte.dev/e/hydration_attribute_changed")}function ch(e){R?console.warn(`%c[svelte] hydration_html_changed %c${e?`The value of an \`{@html ...}\` block ${e} changed between server and client renders. The client value will be ignored in favour of the server value`:"The value of an `{@html ...}` block changed between server and client renders. The client value will be ignored in favour of the server value"} -https://svelte.dev/e/hydration_html_changed`,Fr,Gr):console.warn("https://svelte.dev/e/hydration_html_changed")}function wo(e){G?console.warn(`%c[svelte] hydration_mismatch +https://svelte.dev/e/hydration_html_changed`,kr,Nr):console.warn("https://svelte.dev/e/hydration_html_changed")}function xo(e){R?console.warn(`%c[svelte] hydration_mismatch %c${e?`Hydration failed because the initial UI does not match what was rendered on the server. The error occurred near ${e}`:"Hydration failed because the initial UI does not match what was rendered on the server"} -https://svelte.dev/e/hydration_mismatch`,Fr,Gr):console.warn("https://svelte.dev/e/hydration_mismatch")}function pg(){G?console.warn("%c[svelte] invalid_raw_snippet_render\n%cThe `render` function passed to `createRawSnippet` should return HTML for a single element\nhttps://svelte.dev/e/invalid_raw_snippet_render",Fr,Gr):console.warn("https://svelte.dev/e/invalid_raw_snippet_render")}function hg(){G?console.warn(`%c[svelte] lifecycle_double_unmount +https://svelte.dev/e/hydration_mismatch`,kr,Nr):console.warn("https://svelte.dev/e/hydration_mismatch")}function dh(){R?console.warn("%c[svelte] invalid_raw_snippet_render\n%cThe `render` function passed to `createRawSnippet` should return HTML for a single element\nhttps://svelte.dev/e/invalid_raw_snippet_render",kr,Nr):console.warn("https://svelte.dev/e/invalid_raw_snippet_render")}function uh(){R?console.warn(`%c[svelte] lifecycle_double_unmount %cTried to unmount a component that was not mounted -https://svelte.dev/e/lifecycle_double_unmount`,Fr,Gr):console.warn("https://svelte.dev/e/lifecycle_double_unmount")}function gg(){G?console.warn("%c[svelte] select_multiple_invalid_value\n%cThe `value` property of a `` element should be an array, but it received a non-array value. The selection will be kept as is.\nhttps://svelte.dev/e/select_multiple_invalid_value",kr,Nr):console.warn("https://svelte.dev/e/select_multiple_invalid_value")}function Tl(e){R?console.warn(`%c[svelte] state_proxy_equality_mismatch %cReactive \`$state(...)\` proxies and the values they proxy have different identities. Because of this, comparisons with \`${e}\` will produce unexpected results -https://svelte.dev/e/state_proxy_equality_mismatch`,Fr,Gr):console.warn("https://svelte.dev/e/state_proxy_equality_mismatch")}function mg(){G?console.warn(`%c[svelte] state_proxy_unmount +https://svelte.dev/e/state_proxy_equality_mismatch`,kr,Nr):console.warn("https://svelte.dev/e/state_proxy_equality_mismatch")}function gh(){R?console.warn(`%c[svelte] state_proxy_unmount %cTried to unmount a state proxy, rather than a component -https://svelte.dev/e/state_proxy_unmount`,Fr,Gr):console.warn("https://svelte.dev/e/state_proxy_unmount")}function vg(){G?console.warn("%c[svelte] svelte_boundary_reset_noop\n%cA `` `reset` function only resets the boundary the first time it is called\nhttps://svelte.dev/e/svelte_boundary_reset_noop",Fr,Gr):console.warn("https://svelte.dev/e/svelte_boundary_reset_noop")}var Fr,Gr,Ut=v(()=>{Ne();Fr="font-weight: bold",Gr="font-weight: normal"});function at(e){oe=e}function Ue(e){if(e===null)throw wo(),Bn;return ye=e}function wt(){return Ue(Bt(ye))}function L(e){if(oe){if(Bt(ye)!==null)throw wo(),Bn;ye=e}}function zt(e=1){if(oe){for(var t=e,r=ye;t--;)r=Bt(r);ye=r}}function un(e=!0){for(var t=0,r=ye;;){if(r.nodeType===Nr){var n=r.data;if(n==="]"){if(t===0)return r;t-=1}else(n==="["||n==="[!"||n[0]==="["&&!isNaN(Number(n.slice(1))))&&(t+=1)}var o=Bt(r);e&&r.remove(),r=o}}function os(e){if(!e||e.nodeType!==Nr)throw wo(),Bn;return e.data}var oe,ye,Me=v(()=>{Ae();Te();Ut();It();oe=!1});function Ol(e){return e===this.v}function Xl(e,t){return e!=e?t==t:e!==t||e!==null&&typeof e=="object"||typeof e=="function"}function Ml(e){return!Xl(e,this.v)}var na=v(()=>{});function _g(){kn=!0}var lt,kn,fn,lr=v(()=>{lt=!1,kn=!1,fn=!1});function cu(e){G?console.warn(`%c[svelte] state_snapshot_uncloneable +https://svelte.dev/e/state_proxy_unmount`,kr,Nr):console.warn("https://svelte.dev/e/state_proxy_unmount")}function ph(){R?console.warn("%c[svelte] svelte_boundary_reset_noop\n%cA `` `reset` function only resets the boundary the first time it is called\nhttps://svelte.dev/e/svelte_boundary_reset_noop",kr,Nr):console.warn("https://svelte.dev/e/svelte_boundary_reset_noop")}var kr,Nr,Rt=v(()=>{Se();kr="font-weight: bold",Nr="font-weight: normal"});function it(e){se=e}function Ue(e){if(e===null)throw xo(),Gn;return be=e}function bt(){return Ue(Bt(be))}function Q(e){if(se){if(Bt(be)!==null)throw xo(),Gn;be=e}}function Ct(e=1){if(se){for(var t=e,r=be;t--;)r=Bt(r);be=r}}function fn(e=!0){for(var t=0,r=be;;){if(r.nodeType===Zr){var n=r.data;if(n==="]"){if(t===0)return r;t-=1}else(n==="["||n==="[!"||n[0]==="["&&!isNaN(Number(n.slice(1))))&&(t+=1)}var o=Bt(r);e&&r.remove(),r=o}}function rs(e){if(!e||e.nodeType!==Zr)throw xo(),Gn;return e.data}var se,be,He=v(()=>{Fe();Ve();Rt();xt();se=!1});function Dl(e){return e===this.v}function Ol(e,t){return e!=e?t==t:e!==t||e!==null&&typeof e=="object"||typeof e=="function"}function Hl(e){return!Ol(e,this.v)}var ia=v(()=>{});function hh(){Fn=!0}var dt,Fn,gn,lr=v(()=>{dt=!1,Fn=!1,gn=!1});function su(e){R?console.warn(`%c[svelte] state_snapshot_uncloneable %c${e?`The following properties cannot be cloned with \`$state.snapshot\` \u2014 the return value contains the originals: ${e}`:"Value cannot be cloned with `$state.snapshot` \u2014 the original value was returned"} -https://svelte.dev/e/state_snapshot_uncloneable`,fC,pC):console.warn("https://svelte.dev/e/state_snapshot_uncloneable")}var fC,pC,du=v(()=>{Ne();fC="font-weight: bold",pC="font-weight: normal"});function Wn(e,t=!1,r=!1){if(G&&!t){let n=[],o=oa(e,new Map,"",n,null,r);if(n.length===1&&n[0]==="")cu();else if(n.length>0){let i=n.length>10?n.slice(0,7):n.slice(0,10),s=n.length-i.length,a=i.map(l=>`- ${l}`).join(` +https://svelte.dev/e/state_snapshot_uncloneable`,_C,bC):console.warn("https://svelte.dev/e/state_snapshot_uncloneable")}var _C,bC,au=v(()=>{Se();_C="font-weight: bold",bC="font-weight: normal"});function Yn(e,t=!1,r=!1){if(R&&!t){let n=[],o=sa(e,new Map,"",n,null,r);if(n.length===1&&n[0]==="")su();else if(n.length>0){let i=n.length>10?n.slice(0,7):n.slice(0,10),s=n.length-i.length,a=i.map(l=>`- ${l}`).join(` `);s>0&&(a+=` -- ...and ${s} more`),cu(a)}return o}return oa(e,new Map,"",hC,null,r)}function oa(e,t,r,n,o=null,i=!1){if(typeof e=="object"&&e!==null){var s=t.get(e);if(s!==void 0)return s;if(e instanceof Map)return new Map(e);if(e instanceof Set)return new Set(e);if(Yr(e)){var a=Array(e.length);t.set(e,a),o!==null&&t.set(o,a);for(var l=0;l{Ne();du();Le();hC=[]});function pt(e,t){return e.label=t,Wl(e.v,t),e}function Wl(e,t){return e?.[Rl]?.(t),e}var ia,Zr=v(()=>{Te();is();Ae();Ce();Ee();ia=null});function pn(e){let t=new Error,r=gC();return r.length===0?null:(r.unshift(` -`),Mt(t,"stack",{value:r.join(` -`)}),Mt(t,"name",{value:e}),t)}function gC(){let e=Error.stackTraceLimit;Error.stackTraceLimit=1/0;let t=new Error().stack;if(Error.stackTraceLimit=e,!t)return[];let r=t.split(` -`),n=[];for(let o=0;o{Ne();Le();ta()});function Hn(e){be=e}function ss(e){hn=e}function Hl(e){Qr=e}function yg(){let e={};return[()=>(sa(e)||Uh(),zn(e)),t=>jo(e,t)]}function zn(e){return zl("getContext").get(e)}function jo(e,t){let r=zl("setContext");if(lt){var n=le.f,o=!me&&(n&32)!==0&&!be.i;o||rg()}return r.set(e,t),t}function sa(e){return zl("hasContext").has(e)}function wg(){return zl("getAllContexts")}function K(e,t=!1,r){be={p:be,i:!1,c:null,e:null,s:e,x:null,r:le,l:kn&&!t?{s:null,u:null,$:[]}:null},G&&(be.function=r,Qr=r)}function q(e){var t=be,r=t.e;if(r!==null){t.e=null;for(var n of r)uu(n)}return e!==void 0&&(t.x=e),t.i=!0,be=t.p,G&&(Qr=be?.function??null),e??{}}function Sn(){return!kn||be!==null&&be.l===null}function zl(e){return be===null&&Mn(e),be.c??(be.c=new Map(mC(be)||void 0))}function mC(e){let t=e.p;for(;t!==null;){let r=t.c;if(r!==null)return r;t=t.p}return null}var be,hn,Qr,st=v(()=>{Ne();Lt();Ee();Ce();lr();Te();Ae();be=null;hn=null;Qr=null});function Ig(){var e=Ko;Ko=[],Ki(e)}function Ct(e){if(Ko.length===0&&!qo){var t=Ko;queueMicrotask(()=>{t===Ko&&Ig()})}Ko.push(e)}function Cg(){for(;Ko.length>0;)Ig()}var Ko,gn=v(()=>{Le();Yt();Ko=[]});function Yl(e){var t=le;if(t===null)return me.f|=8388608,e;if(G&&e instanceof Error&&!fu.has(e)&&fu.set(e,vC(e,t)),(t.f&32768)===0&&(t.f&4)===0)throw G&&!t.parent&&e instanceof Error&&Eg(e),e;Jr(e,t)}function Jr(e,t){for(;t!==null;){if((t.f&128)!==0){if((t.f&32768)===0)throw e;try{t.b.error(e);return}catch(r){e=r}}t=t.parent}throw G&&e instanceof Error&&Eg(e),e}function vC(e,t){let r=rr(e,"message");if(!(r&&!r.configurable)){for(var n=la?" ":" ",o=` +- ...and ${s} more`),su(a)}return o}return sa(e,new Map,"",xC,null,r)}function sa(e,t,r,n,o=null,i=!1){if(typeof e=="object"&&e!==null){var s=t.get(e);if(s!==void 0)return s;if(e instanceof Map)return new Map(e);if(e instanceof Set)return new Set(e);if(zr(e)){var a=Array(e.length);t.set(e,a),o!==null&&t.set(o,a);for(var l=0;l{Se();au();Re();xC=[]});function ut(e,t){return e.label=t,Ml(e.v,t),e}function Ml(e,t){return e?.[Rl]?.(t),e}var aa,Qr=v(()=>{Ve();ns();Fe();Be();Ee();aa=null});function pn(e){let t=new Error,r=yC();return r.length===0?null:(r.unshift(` +`),Ht(t,"stack",{value:r.join(` +`)}),Ht(t,"name",{value:e}),t)}function yC(){let e=Error.stackTraceLimit;Error.stackTraceLimit=1/0;let t=new Error().stack;if(Error.stackTraceLimit=e,!t)return[];let r=t.split(` +`),n=[];for(let o=0;o{Se();Re();na()});function zn(e){_e=e}function os(e){hn=e}function Yl(e){Xr=e}function _h(){let e={};return[()=>(la(e)||Qp(),Pn(e)),t=>Jo(e,t)]}function Pn(e){return zl("getContext").get(e)}function Jo(e,t){let r=zl("setContext");if(dt){var n=ue.f,o=!me&&(n&32)!==0&&!_e.i;o||qp()}return r.set(e,t),t}function la(e){return zl("hasContext").has(e)}function bh(){return zl("getAllContexts")}function q(e,t=!1,r){_e={p:_e,i:!1,c:null,e:null,s:e,x:null,r:ue,l:Fn&&!t?{s:null,u:null,$:[]}:null},R&&(_e.function=r,Xr=r)}function ee(e){var t=_e,r=t.e;if(r!==null){t.e=null;for(var n of r)lu(n)}return e!==void 0&&(t.x=e),t.i=!0,_e=t.p,R&&(Xr=_e?.function??null),e??{}}function Sn(){return!Fn||_e!==null&&_e.l===null}function zl(e){return _e===null&&Mn(e),_e.c??(_e.c=new Map(IC(_e)||void 0))}function IC(e){let t=e.p;for(;t!==null;){let r=t.c;if(r!==null)return r;t=t.p}return null}var _e,hn,Xr,ot=v(()=>{Se();Xt();Ee();Be();lr();Ve();Fe();_e=null;hn=null;Xr=null});function xh(){var e=jo;jo=[],Ji(e)}function yt(e){if(jo.length===0&&!Ko){var t=jo;queueMicrotask(()=>{t===jo&&xh()})}jo.push(e)}function yh(){for(;jo.length>0;)xh()}var jo,mn=v(()=>{Re();zt();jo=[]});function Pl(e){var t=ue;if(t===null)return me.f|=8388608,e;if(R&&e instanceof Error&&!cu.has(e)&&cu.set(e,wC(e,t)),(t.f&32768)===0&&(t.f&4)===0)throw R&&!t.parent&&e instanceof Error&&Ih(e),e;Jr(e,t)}function Jr(e,t){for(;t!==null;){if((t.f&128)!==0){if((t.f&32768)===0)throw e;try{t.b.error(e);return}catch(r){e=r}}t=t.parent}throw R&&e instanceof Error&&Ih(e),e}function wC(e,t){let r=tr(e,"message");if(!(r&&!r.configurable)){for(var n=da?" ":" ",o=` ${n}in ${t.fn?.name||""}`,i=t.ctx;i!==null;)o+=` -${n}in ${i.function?.[yr].split("/").pop()}`,i=i.p;return{message:e.message+` +${n}in ${i.function?.[Ir].split("/").pop()}`,i=i.p;return{message:e.message+` ${o} `,stack:e.stack?.split(` `).filter(s=>!s.includes("svelte/src/internal")).join(` -`)}}}function Eg(e){let t=fu.get(e);t&&(Mt(e,"message",{value:t.message}),Mt(e,"stack",{value:t.stack}))}var fu,as=v(()=>{Ne();Te();It();Ae();Le();Ee();fu=new WeakMap});function De(e,t){e.f=e.f&_C|t}function ls(e){(e.f&512)!==0||e.deps===null?De(e,1024):De(e,4096)}var _C,Co=v(()=>{Ae();_C=-7169});function $g(e){if(e!==null)for(let t of e)(t.f&2)===0||(t.f&65536)===0||(t.f^=65536,$g(t.deps))}function Pl(e,t,r){(e.f&2048)!==0?t.add(e):(e.f&4096)!==0&&r.add(e),$g(e.deps),De(e,1024)}var pu=v(()=>{Ae();Co()});var hu=v(()=>{Ee();Le()});var Bg=v(()=>{Le();na();hu()});function gu(e){var t=Jl;try{return Jl=!1,[e(),Jl]}finally{Jl=t}}var kg,Jl,ca=v(()=>{hu();Bg();Le();Ee();Ce();vt();Ne();kg=!1,Jl=!1});var Sg=v(()=>{Ae();is();Ee()});function Nn(e){var t=qo;qo=!0;try{var r;for(e&&(xe!==null&&!xe.is_fork&&xe.flush(),r=e());;){if(Cg(),xe===null)return r;xe.flush()}}finally{qo=t}}function yC(){if(G){var e=new Map;for(let r of xe.current.keys())for(let[n,o]of r.updated??[]){var t=e.get(n);t||(t={error:o.error,count:0},e.set(n,t)),t.count+=o.count}for(let r of e.values())r.error&&console.error(r.error)}try{Hh()}catch(r){G&&Mt(r,"stack",{value:""}),Jr(r,_u)}}function Ng(e){var t=e.length;if(t!==0){for(var r=0;r0)){qn.clear();for(let o of Kr){if((o.f&24576)!==0)continue;let i=[o],s=o.parent;for(;s!==null;)Kr.has(s)&&(Kr.delete(s),i.push(s)),s=s.parent;for(let a=i.length-1;a>=0;a--){let l=i[a];(l.f&24576)===0&&Fn(l)}}Kr.clear()}}Kr=null}}function Qg(e,t,r,n){if(!r.has(e)&&(r.add(e),e.reactions!==null))for(let o of e.reactions){let i=o.f;(i&2)!==0?Qg(o,t,r,n):(i&4194320)!==0&&(i&2048)===0&&yu(o,t,n)&&(De(o,2048),ga(o))}}function Rg(e,t){if(e.reactions!==null)for(let r of e.reactions){let n=r.f;(n&2)!==0?Rg(r,t):(n&131072)!==0&&(De(r,2048),t.add(r))}}function yu(e,t,r){let n=r.get(e);if(n!==void 0)return n;if(e.deps!==null)for(let o of e.deps){if(_o.call(t,o))return!0;if((o.f&2)!==0&&yu(o,t,r))return r.set(o,!0),!0}return r.set(e,!1),!1}function ga(e){xe.schedule(e)}function Lg(e,t){if(!((e.f&32)!==0&&(e.f&1024)!==0)){(e.f&2048)!==0?t.d.push(e):(e.f&4096)!==0&&t.m.push(e),De(e,1024);for(var r=e.first;r!==null;)Lg(r,t),r=r.next}}function Ug(e){De(e,1024);for(var t=e.first;t!==null;)Ug(t),t=t.next}function Tg(e){lt||Tl("fork"),xe!==null&&Yh();var t=dr.ensure();t.is_fork=!0,At=new Map;var r=!1,n=t.settled();return Nn(e),{commit:async()=>{if(r){await n;return}t.linked||zh(),r=!0,t.is_fork=!1;for(var[o,[i]]of t.current)o.v=i,o.wv=Bo();Nn(()=>{var s=new Set;for(var a of t.current.keys())Rg(a,s);ma(s),va()}),t.flush(),await n},discard:()=>{for(var o of t.current.keys())o.wv=Bo();!r&&t.linked&&t.discard()}}}var jl,cs,xe,ni,At,_u,qo,mu,ri,fa,Ag,vu,xC,us,Pn,Jn,fs,ps,hs,jn,gs,cr,pa,Kn,vn,An,ms,$o,Oe,bu,da,xu,Fg,Gg,ds,Zg,ua,Kl,dr,Kr,Yt=v(()=>{Ae();lr();Le();Ee();Lt();gn();Ne();as();vt();Ce();pu();Te();Co();ca();Jo();Sg();jl=null,cs=null,xe=null,ni=null,At=null,_u=null,qo=!1,mu=!1,ri=null,fa=null,Ag=0,vu=new Set,xC=1,Kl=class Kl{constructor(){U(this,Oe);Be(this,"id",xC++);U(this,us,!1);Be(this,"linked",!0);U(this,Pn,null);U(this,Jn,null);Be(this,"async_deriveds",new Map);Be(this,"current",new Map);Be(this,"previous",new Map);U(this,fs,new Set);U(this,ps,new Set);U(this,hs,0);U(this,jn,new Map);U(this,gs,null);U(this,cr,[]);U(this,pa,[]);U(this,Kn,new Set);U(this,vn,new Set);U(this,An,new Map);U(this,ms,new Set);Be(this,"is_fork",!1);U(this,$o,!1);cs===null?jl=cs=this:(ge(cs,Jn,this),ge(this,Pn,cs)),cs=this}skip_effect(t){m(this,An).has(t)||m(this,An).set(t,{d:[],m:[]}),m(this,ms).delete(t)}unskip_effect(t,r=n=>this.schedule(n)){var n=m(this,An).get(t);if(n){m(this,An).delete(t);for(var o of n.d)De(o,2048),r(o);for(o of n.m)De(o,4096),r(o)}m(this,ms).add(t)}capture(t,r,n=!1){t.v!==He&&!this.previous.has(t)&&this.previous.set(t,t.v),(t.f&8388608)===0&&(this.current.set(t,[r,n]),At?.set(t,r)),this.is_fork||(t.v=r)}activate(){xe=this}deactivate(){xe=null,At=null}flush(){try{G&&vu.clear(),mu=!0,xe=this,Ie(this,Oe,da).call(this)}finally{if(Ag=0,_u=null,ri=null,fa=null,mu=!1,xe=null,At=null,qn.clear(),G)for(let t of vu)t.updated=null}}discard(){for(let t of m(this,ps))t(this);m(this,ps).clear(),Ie(this,Oe,ua).call(this),m(this,gs)?.resolve()}register_created_effect(t){m(this,pa).push(t)}increment(t,r){if(ge(this,hs,m(this,hs)+1),t){let n=m(this,jn).get(r)??0;m(this,jn).set(r,n+1)}}decrement(t,r){if(ge(this,hs,m(this,hs)-1),t){let n=m(this,jn).get(r)??0;n===1?m(this,jn).delete(r):m(this,jn).set(r,n-1)}m(this,$o)||(ge(this,$o,!0),Ct(()=>{ge(this,$o,!1),this.linked&&this.flush()}))}transfer_effects(t,r){for(let n of t)m(this,Kn).add(n);for(let n of r)m(this,vn).add(n);t.clear(),r.clear()}oncommit(t){m(this,fs).add(t)}ondiscard(t){m(this,ps).add(t)}settled(){return(m(this,gs)??ge(this,gs,Ql())).promise}static ensure(){if(xe===null){let t=xe=new Kl;!mu&&!qo&&Ct(()=>{m(t,us)||t.flush()})}return xe}apply(){if(!lt||!this.is_fork&&m(this,Pn)===null&&m(this,Jn)===null){At=null;return}At=new Map;for(let[r,[n]]of this.current)At.set(r,n);for(let r=jl;r!==null;r=m(r,Jn))if(!(r===this||r.is_fork)){var t=!1;if(r.id1e3&&(Ie(this,Oe,ua).call(this),yC()),G)for(let p of this.current.keys())vu.add(p);for(let p of m(this,Kn))m(this,vn).delete(p),De(p,2048),this.schedule(p);for(let p of m(this,vn))De(p,4096),this.schedule(p);let t=m(this,cr);ge(this,cr,[]),this.apply();var r=ri=[],n=[],o=fa=[];for(let p of t)try{Ie(this,Oe,xu).call(this,p,r,n)}catch(u){throw Ug(p),Ie(this,Oe,bu).call(this)||this.discard(),u}if(xe=null,o.length>0){var i=Kl.ensure();for(let p of o)i.schedule(p)}if(ri=null,fa=null,Ie(this,Oe,bu).call(this)){Ie(this,Oe,ds).call(this,n),Ie(this,Oe,ds).call(this,r);for(let[p,u]of m(this,An))Lg(p,u);o.length>0&&Ie(l=xe,Oe,da).call(l);return}let s=Ie(this,Oe,Fg).call(this);if(s){Ie(this,Oe,ds).call(this,n),Ie(this,Oe,ds).call(this,r),Ie(c=s,Oe,Gg).call(c,this);return}m(this,Kn).clear(),m(this,vn).clear();for(let p of m(this,fs))p(this);m(this,fs).clear(),ni=this,Ng(n),Ng(r),ni=null,m(this,gs)?.resolve();var a=xe;if(m(this,hs)===0&&(m(this,cr).length===0||a!==null)&&(Ie(this,Oe,ua).call(this),lt&&(Ie(this,Oe,Zg).call(this),xe=a)),m(this,cr).length>0)if(a!==null){let p=a;m(p,cr).push(...m(this,cr).filter(u=>!m(p,cr).includes(u)))}else a=this;a!==null&&Ie(f=a,Oe,da).call(f)},xu=function(t,r,n){t.f^=1024;for(var o=t.first;o!==null;){var i=o.f,s=(i&96)!==0,a=s&&(i&1024)!==0,l=a||(i&8192)!==0||m(this,An).has(o);if(!l&&o.fn!==null){s?o.f^=1024:(i&4)!==0?r.push(o):lt&&(i&16777224)!==0?n.push(o):So(o)&&((i&16)!==0&&m(this,vn).add(o),Fn(o));var c=o.first;if(c!==null){o=c;continue}}for(;o!==null;){var f=o.next;if(f!==null){o=f;break}o=o.parent}}},Fg=function(){for(var t=m(this,Pn);t!==null;){if(!t.is_fork){for(let[r,[,n]]of this.current)if(t.current.has(r)&&!n)return t}t=m(t,Pn)}return null},Gg=function(t){var n;for(let[o,i]of t.current)!this.previous.has(o)&&t.previous.has(o)&&this.previous.set(o,t.previous.get(o)),this.current.set(o,i);for(let[o,i]of t.async_deriveds){let s=this.async_deriveds.get(o);s&&i.promise.then(s.resolve).catch(s.reject)}this.transfer_effects(m(t,Kn),m(t,vn));let r=o=>{var i=o.reactions;if(i!==null)for(let l of i){var s=l.f;if((s&2)!==0)r(l);else{var a=l;s&4194320&&!this.async_deriveds.has(a)&&(m(this,vn).delete(a),De(a,2048),this.schedule(a))}}};for(let o of this.current.keys())r(o);this.oncommit(()=>t.discard()),Ie(n=t,Oe,ua).call(n),xe=this,Ie(this,Oe,da).call(this)},ds=function(t){for(var r=0;r!p.current.get(u)[1]&&!this.current.has(u));if(o.length===0)t&&p.discard();else if(r.length>0){if(G&&!m(p,$o)&&xg(m(p,cr).length===0,"Batch has scheduled roots"),t)for(let u of m(this,ms))p.unskip_effect(u,h=>{var g;(h.f&4194320)!==0?p.schedule(h):Ie(g=p,Oe,ds).call(g,[h])});p.activate();var i=new Set,s=new Map;for(var a of r)Qg(a,o,i,s);s=new Map;var l=[...p.current].filter(([u,h])=>{let g=this.current.get(u);return g?g[0]!==h[0]||g[1]!==h[1]:!0}).map(([u])=>u);if(l.length>0)for(let u of m(this,pa))(u.f&155648)===0&&yu(u,l,s)&&((u.f&4194320)!==0?(De(u,2048),p.schedule(u)):m(p,Kn).add(u));if(m(p,cr).length>0&&!m(p,$o)){p.apply();for(var c of m(p,cr))Ie(f=p,Oe,xu).call(f,c,[],[]);ge(p,cr,[])}p.deactivate()}}}},ua=function(){if(this.linked){var t=m(this,Pn),r=m(this,Jn);t===null?jl=r:ge(t,Jn,r),r===null?cs=t:ge(r,Pn,t),this.linked=!1}};dr=Kl;Kr=null});function _a(e){let t=0,r=Dt(0),n;return G&&pt(r,"createSubscriber version"),()=>{Io()&&(d(r),Nt(()=>(t===0&&(n=Ge(()=>e(()=>ur(r)))),t+=1,()=>{Ct(()=>{t-=1,t===0&&(n?.(),n=void 0,ur(r))})})))}}var ql=v(()=>{Ee();Ce();vt();Zr();Ne();gn()});function Bu(e,t,r,n){new Iu(e,t,r,n)}var IC,Lr,ba,qr,oi,Ir,en,fr,Ur,eo,ii,Ao,vs,xa,ya,Gn,rc,tt,Og,Xg,Mg,Cu,ec,tc,Eu,$u,Iu,nc=v(()=>{Ae();Te();st();as();Ce();Ee();Me();gn();Lt();Ut();Ne();Yt();vt();Zr();ql();It();pu();IC=589824;Iu=class{constructor(t,r,n,o){U(this,tt);Be(this,"parent");Be(this,"is_pending",!1);Be(this,"transform_error");U(this,Lr);U(this,ba,oe?ye:null);U(this,qr);U(this,oi);U(this,Ir);U(this,en,null);U(this,fr,null);U(this,Ur,null);U(this,eo,null);U(this,ii,0);U(this,Ao,0);U(this,vs,!1);U(this,xa,new Set);U(this,ya,new Set);U(this,Gn,null);U(this,rc,_a(()=>(ge(this,Gn,Dt(m(this,ii))),G&&pt(m(this,Gn),"$effect.pending()"),()=>{ge(this,Gn,null)})));ge(this,Lr,t),ge(this,qr,r),ge(this,oi,i=>{var s=le;s.b=this,s.f|=128,n(i)}),this.parent=le.b,this.transform_error=o??this.parent?.transform_error??(i=>i),ge(this,Ir,hr(()=>{if(oe){let i=m(this,ba);wt();let s=i.data==="[!";if(i.data.startsWith("[?")){let l=JSON.parse(i.data.slice("[?".length));Ie(this,tt,Xg).call(this,l)}else s?Ie(this,tt,Mg).call(this):Ie(this,tt,Og).call(this)}else Ie(this,tt,Cu).call(this)},IC)),oe&&ge(this,Lr,ye)}defer_effect(t){Pl(t,m(this,xa),m(this,ya))}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!m(this,qr).pending}update_pending_count(t,r){Ie(this,tt,Eu).call(this,t,r),ge(this,ii,m(this,ii)+t),!(!m(this,Gn)||m(this,vs))&&(ge(this,vs,!0),Ct(()=>{ge(this,vs,!1),m(this,Gn)&&_n(m(this,Gn),m(this,ii))}))}get_effect_pending(){return m(this,rc).call(this),d(m(this,Gn))}error(t){if(!m(this,qr).onerror&&!m(this,qr).failed)throw t;xe?.is_fork?(m(this,en)&&xe.skip_effect(m(this,en)),m(this,fr)&&xe.skip_effect(m(this,fr)),m(this,Ur)&&xe.skip_effect(m(this,Ur)),xe.oncommit(()=>{Ie(this,tt,$u).call(this,t)})):Ie(this,tt,$u).call(this,t)}};Lr=new WeakMap,ba=new WeakMap,qr=new WeakMap,oi=new WeakMap,Ir=new WeakMap,en=new WeakMap,fr=new WeakMap,Ur=new WeakMap,eo=new WeakMap,ii=new WeakMap,Ao=new WeakMap,vs=new WeakMap,xa=new WeakMap,ya=new WeakMap,Gn=new WeakMap,rc=new WeakMap,tt=new WeakSet,Og=function(){try{ge(this,en,_t(()=>m(this,oi).call(this,m(this,Lr))))}catch(t){this.error(t)}},Xg=function(t){let r=m(this,qr).failed;r&&ge(this,Ur,_t(()=>{r(m(this,Lr),()=>t,()=>()=>{})}))},Mg=function(){let t=m(this,qr).pending;t&&(this.is_pending=!0,ge(this,fr,_t(()=>t(m(this,Lr)))),Ct(()=>{var r=ge(this,eo,document.createDocumentFragment()),n=bt();r.append(n),ge(this,en,Ie(this,tt,tc).call(this,()=>_t(()=>m(this,oi).call(this,n)))),m(this,Ao)===0&&(m(this,Lr).before(r),ge(this,eo,null),Zn(m(this,fr),()=>{ge(this,fr,null)}),Ie(this,tt,ec).call(this,xe))}))},Cu=function(){try{if(this.is_pending=this.has_pending_snippet(),ge(this,Ao,0),ge(this,ii,0),ge(this,en,_t(()=>{m(this,oi).call(this,m(this,Lr))})),m(this,Ao)>0){var t=ge(this,eo,document.createDocumentFragment());_s(m(this,en),t);let r=m(this,qr).pending;ge(this,fr,_t(()=>r(m(this,Lr))))}else Ie(this,tt,ec).call(this,xe)}catch(r){this.error(r)}},ec=function(t){this.is_pending=!1,t.transfer_effects(m(this,xa),m(this,ya))},tc=function(t){var r=le,n=me,o=be;Ft(m(this,Ir)),$t(m(this,Ir)),Hn(m(this,Ir).ctx);try{return dr.ensure(),t()}catch(i){return Yl(i),null}finally{Ft(r),$t(n),Hn(o)}},Eu=function(t,r){var n;if(!this.has_pending_snippet()){this.parent&&Ie(n=this.parent,tt,Eu).call(n,t,r);return}ge(this,Ao,m(this,Ao)+t),m(this,Ao)===0&&(Ie(this,tt,ec).call(this,r),m(this,fr)&&Zn(m(this,fr),()=>{ge(this,fr,null)}),m(this,eo)&&(m(this,Lr).before(m(this,eo)),ge(this,eo,null)))},$u=function(t){m(this,en)&&(rt(m(this,en)),ge(this,en,null)),m(this,fr)&&(rt(m(this,fr)),ge(this,fr,null)),m(this,Ur)&&(rt(m(this,Ur)),ge(this,Ur,null)),oe&&(Ue(m(this,ba)),zt(),Ue(un()));var r=m(this,qr).onerror;let n=m(this,qr).failed;var o=!1,i=!1;let s=()=>{if(o){vg();return}o=!0,i&&sg(),m(this,Ur)!==null&&Zn(m(this,Ur),()=>{ge(this,Ur,null)}),Ie(this,tt,tc).call(this,()=>{Ie(this,tt,Cu).call(this)})},a=l=>{try{i=!0,r?.(l,s),i=!1}catch(c){Jr(c,m(this,Ir)&&m(this,Ir).parent)}n&&ge(this,Ur,Ie(this,tt,tc).call(this,()=>{try{return _t(()=>{var c=le;c.b=this,c.f|=128,n(m(this,Lr),()=>l,()=>s)})}catch(c){return Jr(c,m(this,Ir).parent),null}}))};Ct(()=>{var l;try{l=this.transform_error(t)}catch(c){Jr(c,m(this,Ir)&&m(this,Ir).parent);return}l!==null&&typeof l=="object"&&typeof l.then=="function"?l.then(a,c=>Jr(c,m(this,Ir)&&m(this,Ir).parent)):a(l)})}});function wa(e,t,r,n){let o=Sn()?ro:si;var i=e.filter(u=>!u.settled);if(r.length===0&&i.length===0){n(t.map(o));return}var s=le,a=Wg(),l=i.length===1?i[0].promise:i.length>1?Promise.all(i.map(u=>u.promise)):null;function c(u){if((s.f&16384)===0){a();try{n(u)}catch(h){Jr(h,s)}bs()}}var f=ku();if(r.length===0){l.then(()=>c(t.map(o))).finally(f);return}function p(){Promise.all(r.map(u=>Au(u))).then(u=>c([...t.map(o),...u])).catch(u=>Jr(u,s)).finally(f)}l?l.then(()=>{a(),p(),bs()}):p()}function Wg(){var e=le,t=me,r=be,n=xe;if(G)var o=hn;return function(s=!0){Ft(e),$t(t),Hn(r),s&&(e.f&16384)===0&&(n?.activate(),n?.apply()),G&&(Su(null),ss(o))}}function bs(e=!0){Ft(null),$t(null),Hn(null),e&&xe?.deactivate(),G&&(Su(null),ss(null))}function ku(){var e=le,t=e.b,r=xe,n=!!t?.is_rendered();return t?.update_pending_count(1,r),r.increment(n,e),()=>{t?.update_pending_count(-1,r),r.decrement(n,e)}}var No=v(()=>{Ae();Ne();st();nc();as();Ee();Yt();Fo();Ce()});function Su(e){Cr=e}function ro(e){var t=2050;le!==null&&(le.f|=524288);let r={ctx:be,deps:null,effects:null,equals:Ol,f:t,fn:e,reactions:null,rv:0,v:He,wv:0,parent:le,ac:null};return G&&fn&&(r.created=pn("created at")),r}function Au(e,t,r){let n=le;n===null&&Vh();var o=void 0,i=Dt(He);G&&(i.label=t??e.toString());var s=!me,a=new Set;return Yg(()=>{var l=le;G&&(Cr={effect:l,effect_deps:new Set,warned:!1});var c=Ql();o=c.promise;try{Promise.resolve(e()).then(c.resolve,h=>{h!==yo&&c.reject(h)}).finally(bs)}catch(h){c.reject(h),bs()}if(G){if(Cr){if(l.deps!==null)for(let h=0;h{G&&(Cr=null),p?.(),a.delete(c),g!==oc&&(f.activate(),g?(i.f|=8388608,_n(i,g)):((i.f&8388608)!==0&&(i.f^=8388608),G&&r!==void 0&&!i.equals(h)&&(Ia.add(i),setTimeout(()=>{Ia.has(i)&&(l.f&16384)===0&&(lg(i.label,r),Ia.delete(i))})),_n(i,h)),f.deactivate())};c.promise.then(u,h=>u(null,h||"unknown"))}),kt(()=>{for(let l of a)l.reject(oc)}),G&&(i.f|=4194304),new Promise(l=>{function c(f){function p(){f===o?l(i):c(o)}f.then(p,p)}c(o)})}function _(e){let t=ro(e);return lt||sc(t),t}function si(e){let t=ro(e);return t.equals=Ml,t}function Hg(e){var t=e.effects;if(t!==null){e.effects=null;for(var r=0;r{Ne();Ae();Ee();na();Lt();Ut();Ce();vt();Jo();lr();st();Te();Yt();No();Le();Co();Cr=null;Ia=new Set;oc=Symbol("obsolete");Nu=[]});function ma(e){ai=e}function Pg(){Zu=!0}function Dt(e,t){var r={f:0,v:e,reactions:null,equals:Ol,rv:0,wv:0};return G&&fn&&(r.created=t??pn("created at"),r.updated=null,r.set_during_effect=!1,r.trace=null),r}function we(e,t){let r=Dt(e,t);return sc(r),r}function ei(e,t=!1,r=!0){var o;let n=Dt(e);return t||(n.equals=Ml),kn&&r&&be!==null&&be.l!==null&&((o=be.l).s??(o.s=[])).push(n),n}function X(e,t,r=!1){me!==null&&(!mr||(me.f&131072)!==0)&&Sn()&&(me.f&4325394)!==0&&(bn===null||!bn.has(e))&&ig();let n=r?Xt(t):t;return G&&Wl(n,e.label),_n(e,n,fa)}function _n(e,t,r=null){if(!e.equals(t)){qn.set(e,Tr?t:e.v);var n=dr.ensure();if(n.capture(e,t),G){if(fn||le!==null){e.updated??(e.updated=new Map);let o=(e.updated.get("")?.count??0)+1;if(e.updated.set("",{error:null,count:o}),fn||o>5){let i=pn("updated at");if(i!==null){let s=e.updated.get(i.stack);s||(s={error:i,count:0},e.updated.set(i.stack,s)),s.count++}}}le!==null&&(e.set_during_effect=!0)}if((e.f&2)!==0){let o=e;(e.f&2048)!==0&&Ca(o),At===null&&ls(o)}e.wv=Bo(),Jg(e,2048,r),Sn()&&le!==null&&(le.f&1024)!==0&&(le.f&96)===0&&(Vr===null?jg([e]):Vr.push(e)),!n.is_fork&&ai.size>0&&!Zu&&va()}return t}function va(){Zu=!1;for(let e of ai){(e.f&1024)!==0&&De(e,4096);let t;try{t=So(e)}catch{t=!0}t&&Fn(e)}ai.clear()}function ur(e){X(e,e.v+1)}function Jg(e,t,r){var n=e.reactions;if(n!==null)for(var o=Sn(),i=n.length,s=0;s{Ne();Ee();na();Ae();Lt();lr();Zr();Jo();st();Yt();ci();Fo();Co();ai=new Set,qn=new Map;Zu=!1});function Xt(e){if(typeof e!="object"||e===null||yt in e)return e;let t=bo(e);if(t!==Zl&&t!==Zh)return e;var r=new Map,n=Yr(e),o=we(0),i=G&&fn?pn("created at"):null,s=Qn,a=p=>{if(Qn===s)return p();var u=me,h=Qn;$t(null),Qu(s);var g=p();return $t(u),Qu(h),g};n&&(r.set("length",we(e.length,i)),G&&(e=BC(e)));var l="";let c=!1;function f(p){if(!c){c=!0,l=p,pt(o,`${l} version`);for(let[u,h]of r)pt(h,di(l,u));c=!1}}return new Proxy(e,{defineProperty(p,u,h){(!("value"in h)||h.configurable===!1||h.enumerable===!1||h.writable===!1)&&ng();var g=r.get(u);return g===void 0?a(()=>{var b=we(h.value,i);return r.set(u,b),G&&typeof u=="string"&&pt(b,di(l,u)),b}):X(g,h.value,!0),!0},deleteProperty(p,u){var h=r.get(u);if(h===void 0){if(u in p){let g=a(()=>we(He,i));r.set(u,g),ur(o),G&&pt(g,di(l,u))}}else X(h,He),ur(o);return!0},get(p,u,h){if(u===yt)return e;if(G&&u===Rl)return f;var g=r.get(u),b=u in p;if(g===void 0&&(!b||rr(p,u)?.writable)&&(g=a(()=>{var w=Xt(b?p[u]:He),C=we(w,i);return G&&pt(C,di(l,u)),C}),r.set(u,g)),g!==void 0){var x=d(g);return x===He?void 0:x}return Reflect.get(p,u,h)},getOwnPropertyDescriptor(p,u){var h=Reflect.getOwnPropertyDescriptor(p,u);if(h&&"value"in h){var g=r.get(u);g&&(h.value=d(g))}else if(h===void 0){var b=r.get(u),x=b?.v;if(b!==void 0&&x!==He)return{enumerable:!0,configurable:!0,value:x,writable:!0}}return h},has(p,u){if(u===yt)return!0;var h=r.get(u),g=h!==void 0&&h.v!==He||Reflect.has(p,u);if(h!==void 0||le!==null&&(!g||rr(p,u)?.writable)){h===void 0&&(h=a(()=>{var x=g?Xt(p[u]):He,w=we(x,i);return G&&pt(w,di(l,u)),w}),r.set(u,h));var b=d(h);if(b===He)return!1}return g},set(p,u,h,g){var b=r.get(u),x=u in p;if(n&&u==="length")for(var w=h;wwe(He,i)),r.set(w+"",C),G&&pt(C,di(l,w)))}if(b===void 0)(!x||rr(p,u)?.writable)&&(b=a(()=>we(void 0,i)),G&&pt(b,di(l,u)),X(b,Xt(h)),r.set(u,b));else{x=b.v!==He;var E=a(()=>Xt(h));X(b,E)}var I=Reflect.getOwnPropertyDescriptor(p,u);if(I?.set&&I.set.call(g,h),!x){if(n&&typeof u=="string"){var T=r.get("length"),B=Number(u);Number.isInteger(B)&&B>=T.v&&X(T,B+1)}ur(o)}return!0},ownKeys(p){d(o);var u=Reflect.ownKeys(p).filter(b=>{var x=r.get(b);return x===void 0||x.v!==He});for(var[h,g]of r)g.v!==He&&!(h in p)&&u.push(h);return u},setPrototypeOf(){og()}})}function di(e,t){return typeof t=="symbol"?`${e}[Symbol(${t.description??""})]`:EC.test(t)?`${e}.${t}`:/^\d+$/.test(t)?`${e}[${t}]`:`${e}['${t}']`}function ys(e){try{if(e!==null&&typeof e=="object"&&yt in e)return e[yt]}catch{}return e}function Ru(e,t){return Object.is(ys(e),ys(t))}function BC(e){return new Proxy(e,{get(t,r,n){var o=Reflect.get(t,r,n);return $C.has(r)?function(...i){Pg();var s=o.apply(this,i);return va(),s}:o}})}var EC,$C,ci=v(()=>{Ne();Ee();Le();vt();Ae();Te();Lt();Zr();Jo();lr();EC=/^[a-zA-Z_$][a-zA-Z_$0-9]*$/;$C=new Set(["copyWithin","fill","pop","push","reverse","shift","sort","splice","unshift"])});function Kg(){let e=Array.prototype,t=Array.__svelte_cleanup;t&&t();let{indexOf:r,lastIndexOf:n,includes:o}=e;e.indexOf=function(i,s){let a=r.call(this,i,s);if(a===-1){for(let l=s??0;l{e.indexOf=r,e.lastIndexOf=n,e.includes=o}}var Lu=v(()=>{Ut();ci()});function ac(){if(ir===void 0){ir=window,qg=document,la=/Firefox/.test(navigator.userAgent);var e=Element.prototype,t=Node.prototype,r=Text.prototype;em=rr(t,"firstChild").get,tm=rr(t,"nextSibling").get,tu(e)&&(e[Ks]=void 0,e[Ll]=null,e[qs]=void 0,e.__e=void 0),tu(r)&&(r[ea]=void 0),G&&(e.__svelte_meta=null,Kg())}}function bt(e=""){return document.createTextNode(e)}function Ye(e){return em.call(e)}function Bt(e){return tm.call(e)}function V(e,t){if(!oe)return Ye(e);var r=Ye(ye);if(r===null)r=ye.appendChild(bt());else if(t&&r.nodeType!==Po){var n=bt();return r?.before(n),Ue(n),n}return t&&Ba(r),Ue(r),r}function ve(e,t=!1){if(!oe){var r=Ye(e);return r instanceof Comment&&r.data===""?Bt(r):r}if(t){if(ye?.nodeType!==Po){var n=bt();return ye?.before(n),Ue(n),n}Ba(ye)}return ye}function P(e,t=1,r=!1){let n=oe?ye:e;for(var o;t--;)o=n,n=Bt(n);if(!oe)return n;if(r){if(n?.nodeType!==Po){var i=bt();return n===null?o?.after(i):n.before(i),Ue(i),i}Ba(n)}return Ue(n),n}function $a(e){e.textContent=""}function lc(){if(!lt||Kr!==null)return!1;var e=le.f;return(e&32768)!==0}function Rn(e,t,r){return t==null||t===Vl?r?document.createElement(e,{is:r}):document.createElement(e):r?document.createElementNS(t,e,{is:r}):document.createElementNS(t,e)}function Ba(e){if(e.nodeValue.length<65536)return;let t=e.nextSibling;for(;t!==null&&t.nodeType===Po;)t.remove(),e.nodeValue+=t.nodeValue,t=e.nextSibling}var ir,qg,la,em,tm,It=v(()=>{Me();Ne();Lu();Le();Ee();lr();Ae();Yt();Te()});function Uu(e,t){if(t){let r=document.body;e.autofocus=!0,Ct(()=>{document.activeElement===r&&e.focus()})}}function cc(){rm||(rm=!0,document.addEventListener("reset",e=>{Promise.resolve().then(()=>{if(!e.defaultPrevented)for(let t of e.target.elements)t[xo]?.()})},{capture:!0}))}var rm,dc=v(()=>{Me();It();gn();Ae();rm=!1});function no(e){var t=me,r=le;$t(null),Ft(null);try{return e()}finally{$t(t),Ft(r)}}function Tu(e,t,r,n=r){e.addEventListener(t,()=>no(r));let o=e[xo];o?e[xo]=()=>{o(),n(!0)}:e[xo]=()=>n(!0),cc()}var tn=v(()=>{Ce();Ee();Ae();dc()});function Du(e){le===null&&(me===null&&Wh(e),Mh()),Tr&&Xh(e)}function kC(e,t){var r=t.last;r===null?t.last=t.first=e:(r.next=e,e.prev=r,t.last=e)}function rn(e,t){var r=le;if(G)for(;r!==null&&(r.f&131072)!==0;)r=r.parent;r!==null&&(r.f&8192)!==0&&(e|=8192);var n={ctx:be,deps:null,nodes:null,f:e|2048|512,first:null,fn:t,last:null,next:null,parent:r,b:r&&r.b,prev:null,teardown:null,wv:0,ac:null};G&&(n.component_function=Qr),xe?.register_created_effect(n);var o=n;if((e&4)!==0)ri!==null?ri.push(n):dr.ensure().schedule(n);else if(t!==null){try{Fn(n)}catch(s){throw rt(n),s}o.deps===null&&o.teardown===null&&o.nodes===null&&o.first===o.last&&(o.f&524288)===0&&(o=o.first,(e&16)!==0&&(e&65536)!==0&&o!==null&&(o.f|=65536))}if(o!==null&&(o.parent=r,r!==null&&kC(o,r),me!==null&&(me.f&2)!==0&&(e&64)===0)){var i=me;(i.effects??(i.effects=[])).push(o)}return n}function Io(){return me!==null&&!mr}function kt(e){let t=rn(8,null);return De(t,1024),t.teardown=e,t}function ct(e){Du("$effect"),G&&Mt(e,"name",{value:"$effect"});var t=le.f,r=!me&&(t&32)!==0&&be!==null&&!be.i;if(r){var n=be;(n.e??(n.e=[])).push(e)}else return uu(e)}function uu(e){return rn(1048580,e)}function ui(e){return Du("$effect.pre"),G&&Mt(e,"name",{value:"$effect.pre"}),rn(1048584,e)}function fi(e){dr.ensure();let t=rn(524352,e);return()=>{rt(t)}}function im(e){dr.ensure();let t=rn(524352,e);return(r={})=>new Promise(n=>{r.outro?Zn(t,()=>{rt(t),n(void 0)}):(rt(t),n(void 0))})}function sr(e){return rn(4,e)}function Yg(e){return rn(4718592,e)}function Nt(e,t=0){return rn(8|t,e)}function te(e,t=[],r=[],n=[]){wa(n,t,r,o=>{rn(8,()=>e(...o.map(d)))})}function hr(e,t=0){var r=rn(16|t,e);return G&&(r.dev_stack=hn),r}function uc(e,t=0){var r=rn(16777216|t,e);return G&&(r.dev_stack=hn),r}function _t(e){return rn(524320,e)}function Ou(e){var t=e.teardown;if(t!==null){let r=Tr,n=me;Vu(!0),$t(null);try{t.call(null)}finally{Vu(r),$t(n)}}}function Ea(e,t=!1){var r=e.first;for(e.first=e.last=null;r!==null;){let o=r.ac;o!==null&&no(()=>{o.abort(yo)});var n=r.next;(r.f&64)!==0?r.parent=null:rt(r,t),r=n}}function sm(e){for(var t=e.first;t!==null;){var r=t.next;(t.f&32)===0&&rt(t),t=r}}function rt(e,t=!0){var r=!1;(t||(e.f&262144)!==0)&&e.nodes!==null&&e.nodes.end!==null&&(Xu(e.nodes.start,e.nodes.end),r=!0),De(e,33554432),Ea(e,t&&!r),li(e,0);var n=e.nodes&&e.nodes.t;if(n!==null)for(let i of n)i.stop();Ou(e),e.f^=33554432,e.f|=16384;var o=e.parent;o!==null&&o.first!==null&&wu(e),G&&(e.component_function=null),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=e.b=null}function Xu(e,t){for(;e!==null;){var r=e===t?null:Bt(e);e.remove(),e=r}}function wu(e){var t=e.parent,r=e.prev,n=e.next;r!==null&&(r.next=n),n!==null&&(n.prev=r),t!==null&&(t.first===e&&(t.first=n),t.last===e&&(t.last=r))}function Zn(e,t,r=!0){var n=[];am(e,n,!0);var o=()=>{r&&rt(e),t&&t()},i=n.length;if(i>0){var s=()=>--i||o();for(var a of n)a.out(s)}else o()}function am(e,t,r){if((e.f&8192)===0){e.f^=8192;var n=e.nodes&&e.nodes.t;if(n!==null)for(let a of n)(a.is_global||r)&&t.push(a);for(var o=e.first;o!==null;){var i=o.next;if((o.f&64)===0){var s=(o.f&65536)!==0||(o.f&32)!==0&&(e.f&16)!==0;am(o,t,s?r:!1)}o=i}}}function ws(e){lm(e,!0)}function lm(e,t){if((e.f&8192)!==0){e.f^=8192,(e.f&1024)===0&&(De(e,2048),dr.ensure().schedule(e));for(var r=e.first;r!==null;){var n=r.next,o=(r.f&65536)!==0||(r.f&32)!==0;lm(r,o?t:!1),r=n}var i=e.nodes&&e.nodes.t;if(i!==null)for(let s of i)(s.is_global||t)&&s.in()}}function _s(e,t){if(e.nodes)for(var r=e.nodes.start,n=e.nodes.end;r!==null;){var o=r===n?null:Bt(r);t.append(r),r=o}}var Ce=v(()=>{Ee();Ae();Lt();Ne();Le();It();st();Yt();No();tn();Co()});var cm,Mu=v(()=>{vt();Ee();cm=null});function Vu(e){Tr=e}function $t(e){me=e}function Ft(e){le=e}function sc(e){me!==null&&(!lt||(me.f&2)!==0)&&(bn??(bn=new Set)).add(e)}function jg(e){Vr=e}function Qu(e){Qn=e}function Bo(){return++dm}function So(e){var t=e.f;if((t&2048)!==0)return!0;if(t&2&&(e.f&=-65537),(t&4096)!==0){for(var r=e.deps,n=r.length,o=0;oe.wv)return!0}(t&512)!==0&&At===null&&De(e,1024)}return!1}function um(e,t,r=!0){var n=e.reactions;if(n!==null&&!(!lt&&bn!==null&&bn.has(e)))for(var o=0;o{e.ac.abort(yo)}),e.ac=null);try{e.f|=2097152;var f=e.fn,p=f();e.f|=32768;var u=e.deps,h=xe?.is_fork;if(Ot!==null){var g;if(h||li(e,gr),u!==null&&gr>0)for(u.length=gr+Ot.length,g=0;g{requestAnimationFrame(()=>e()),setTimeout(()=>e())});await Promise.resolve(),Nn()}function fm(){return dr.ensure().settled()}function d(e){var t=e.f,r=(t&2)!==0;if(cm?.add(e),me!==null&&!mr){var n=le!==null&&(le.f&16384)!==0;if(!n&&(bn===null||!bn.has(e))){var o=me.deps;if((me.f&2097152)!==0)e.rv{Ne();Le();Ce();Ae();vt();Fo();lr();Zr();Jo();st();Yt();as();Te();Mu();tn();Co();Ut();fc=!1,Tr=!1;me=null,mr=!1;le=null;bn=null;Ot=null,gr=0,Vr=null;dm=1,pi=0,Qn=pi});var gm=v(()=>{ae();Te();Dr();Ce()});function mm(e){e=e.replace(AC,"");let t=5381,r=e.length;for(;r--;)t=(t<<5)-t^e.charCodeAt(r);return(t>>>0).toString(36)}function vm(e){return e.endsWith("capture")&&e!=="gotpointercapture"&&e!=="lostpointercapture"}function _m(e){return NC.includes(e)}function bm(e){return e=e.toLowerCase(),GC[e]??e}function xm(e){return ZC.includes(e)}function hc(e){return e?.replace(/\//g,"/\u200B")}var AC,NC,FC,GC,pQ,ZC,QC,hQ,Go=v(()=>{AC=/\r/g;NC=["beforeinput","click","change","dblclick","contextmenu","focusin","focusout","input","keydown","keyup","mousedown","mousemove","mouseout","mouseover","mouseup","pointerdown","pointermove","pointerout","pointerover","pointerup","touchend","touchmove","touchstart"];FC=["allowfullscreen","async","autofocus","autoplay","checked","controls","default","disabled","formnovalidate","indeterminate","inert","ismap","loop","multiple","muted","nomodule","novalidate","open","playsinline","readonly","required","reversed","seamless","selected","webkitdirectory","defer","disablepictureinpicture","disableremoteplayback"],GC={formnovalidate:"formNoValidate",ismap:"isMap",nomodule:"noModule",playsinline:"playsInline",readonly:"readOnly",defaultvalue:"defaultValue",defaultchecked:"defaultChecked",srcobject:"srcObject",novalidate:"noValidate",allowfullscreen:"allowFullscreen",disablepictureinpicture:"disablePictureInPicture",disableremoteplayback:"disableRemotePlayback"};pQ=[...FC,"formNoValidate","isMap","noModule","playsInline","readOnly","value","volume","defaultValue","defaultChecked","srcObject","noValidate","allowFullscreen","disablePictureInPicture","disableRemotePlayback"],ZC=["touchstart","touchmove"];QC=["$state","$state.raw","$derived","$derived.by"],hQ=[...QC,"$state.eager","$state.snapshot","$props","$props.id","$bindable","$effect","$effect.pre","$effect.tracking","$effect.root","$effect.pending","$inspect","$inspect().with","$inspect.trace","$host"]});var ym=v(()=>{Ae();Go();Ee();Ut()});var Wu=v(()=>{});var wm=v(()=>{Ae();Te();Me();st()});function mc(e,t,r,n={}){function o(i){if(n.capture||vc.call(t,i),!i.cancelBubble)return no(()=>r?.call(this,i))}return e.startsWith("pointer")||e.startsWith("touch")||e==="wheel"?Ct(()=>{t.addEventListener(e,o,n)}):t.addEventListener(e,o,n),o}function gi(e,t,r,n={}){var o=mc(t,e,r,n);return()=>{e.removeEventListener(t,o,n)}}function mi(e,t,r,n,o){var i={capture:n,passive:o},s=mc(e,t,r,i);(t===document.body||t===window||t===document||t instanceof HTMLMediaElement)&&kt(()=>{t.removeEventListener(e,s,i)})}function Pt(e,t,r){(t[hi]??(t[hi]={}))[e]=r}function oo(e){for(var t=0;t{throw b});throw u}}finally{e[hi]=t,delete e.currentTarget,$t(f),Ft(p)}}}var hi,Hu,gc,Im,Is=v(()=>{Ce();Le();Me();gn();Te();Ut();Ee();tn();hi=Symbol("events"),Hu=new Set,gc=new Set;Im=null});function Cm(e){return LC?.createHTML(e)??e}function Aa(e){var t=Rn("template");return t.innerHTML=Cm(e.replaceAll("","")),t.content}var LC,_c=v(()=>{It();LC=globalThis?.window?.trustedTypes&&globalThis.window.trustedTypes.createPolicy("svelte-trusted-html",{createHTML:e=>e})});function Gt(e,t){var r=le;r.nodes===null&&(r.nodes={start:e,end:t,a:null,t:null})}function Y(e,t){var r=(t&1)!==0,n=(t&2)!==0,o,i=!e.startsWith("");return()=>{if(oe)return Gt(ye,null),ye;o===void 0&&(o=Aa(i?e:""+e),r||(o=Ye(o)));var s=n||la?document.importNode(o,!0):o.cloneNode(!0);if(r){var a=Ye(s),l=s.lastChild;Gt(a,l)}else Gt(s,s);return s}}function VC(e,t,r="svg"){var n=!e.startsWith(""),o=(t&1)!==0,i=`<${r}>${n?e:""+e}`,s;return()=>{if(oe)return Gt(ye,null),ye;if(!s){var a=Aa(i),l=Ye(a);if(o)for(s=document.createDocumentFragment();Ye(l);)s.appendChild(Ye(l));else s=Ye(l)}var c=s.cloneNode(!0);if(o){var f=Ye(c),p=c.lastChild;Gt(f,p)}else Gt(c,c);return c}}function Ze(e,t){return VC(e,t,"svg")}function zu(e=""){if(!oe){var t=bt(e+"");return Gt(t,t),t}var r=ye;return r.nodeType!==Po?(r.before(r=bt()),Ue(r)):Ba(r),Gt(r,r),r}function Ve(){if(oe)return Gt(ye,null),ye;var e=document.createDocumentFragment(),t=document.createComment(""),r=bt();return e.append(t,r),Gt(t,r),e}function N(e,t){if(oe){var r=le;((r.f&32768)===0||r.nodes.end===null)&&(r.nodes.end=ye),wt();return}e!==null&&e.before(t)}var vi=v(()=>{Me();It();_c();Ee();Te();Ae()});function he(e,t){var n;var r=t==null?"":typeof t=="object"?`${t}`:t;r!==(e[n=ea]??(e[n]=e.nodeValue))&&(e[ea]=r,e.nodeValue=`${r}`)}function Na(e,t){return $m(e,t)}function Cs(e,t){ac(),t.intro=t.intro??!1;let r=t.target,n=oe,o=ye;try{for(var i=Ye(r);i&&(i.nodeType!==Nr||i.data!=="[");)i=Bt(i);if(!i)throw Bn;at(!0),Ue(i);let s=$m(e,{...t,anchor:i});return at(!1),s}catch(s){if(s instanceof Error&&s.message.split(` -`).some(a=>a.startsWith("https://svelte.dev/e/")))throw s;return s!==Bn&&console.warn("Failed to hydrate: ",s),t.recover===!1&&jh(),ac(),$a(r),at(!1),Na(e,t)}finally{at(n),Ue(o)}}function $m(e,{target:t,anchor:r,props:n={},events:o,context:i,intro:s=!0,transformError:a}){ac();var l=void 0,c=im(()=>{var f=r??t.appendChild(bt());Bu(f,{pending:()=>{}},h=>{K({});var g=be;if(i&&(g.c=i),o&&(n.$$events=o),oe&&Gt(h,null),Yu=s,l=e(h,n)||{},Yu=!0,oe&&(le.nodes.end=ye,ye===null||ye.nodeType!==Nr||ye.data!=="]"))throw wo(),Bn;q()},a);var p=new Set,u=h=>{for(var g=0;g{for(var h of p)for(let x of[t,document]){var g=bc.get(x),b=g.get(h);--b==0?(x.removeEventListener(h,vc),g.delete(h),g.size===0&&bc.delete(x)):g.set(h,b)}gc.delete(u),f!==r&&f.parentNode?.removeChild(f)}});return Pu.set(l,c),l}function xc(e,t){let r=Pu.get(e);return r?(Pu.delete(e),r(t)):(G&&(yt in e?mg():hg()),Promise.resolve())}var Yu,bc,Pu,_i=v(()=>{Ne();It();Te();Ee();st();Ce();Me();Le();Is();Ut();Lt();vi();Go();Ae();nc();Yu=!0;bc=new Map;Pu=new WeakMap});var Bm=v(()=>{Te();Ae();Me();Ce();vt();_i();Ee()});var km=v(()=>{Le();Ae();Te();st();Ut();Go()});var Sm=v(()=>{Lt();st();Te()});var Am=v(()=>{Te();is();Ce();Ee();Jo()});var Nm=v(()=>{No();Ee();Me()});var Fm=v(()=>{Lt()});var xn,Ln,Or,bi,Fa,Ga,yc,yn,xi=v(()=>{Yt();Ce();Ae();Me();It();Ne();yn=class{constructor(t,r=!0){Be(this,"anchor");U(this,xn,new Map);U(this,Ln,new Map);U(this,Or,new Map);U(this,bi,new Set);U(this,Fa,!0);U(this,Ga,t=>{if(m(this,xn).has(t)){var r=m(this,xn).get(t),n=m(this,Ln).get(r);if(n)ws(n),m(this,bi).delete(r);else{var o=m(this,Or).get(r);o&&(ws(o.effect),m(this,Ln).set(r,o.effect),m(this,Or).delete(r),G&&(o.fragment.lastChild[nu]=this.anchor),o.fragment.lastChild.remove(),this.anchor.before(o.fragment),n=o.effect)}for(let[i,s]of m(this,xn)){if(m(this,xn).delete(i),i===t)break;let a=m(this,Or).get(s);a&&(rt(a.effect),m(this,Or).delete(s))}for(let[i,s]of m(this,Ln)){if(i===r||m(this,bi).has(i))continue;let a=()=>{if(Array.from(m(this,xn).values()).includes(i)){var c=document.createDocumentFragment();_s(s,c),c.append(bt()),m(this,Or).set(i,{effect:s,fragment:c})}else rt(s);m(this,bi).delete(i),m(this,Ln).delete(i)};m(this,Fa)||!n?(m(this,bi).add(i),Zn(s,a,!1)):a()}}});U(this,yc,t=>{m(this,xn).delete(t);let r=Array.from(m(this,xn).values());for(let[n,o]of m(this,Or))r.includes(n)||(rt(o.effect),m(this,Or).delete(n))});this.anchor=t,ge(this,Fa,r)}ensure(t,r){var n=xe,o=lc();if(r&&!m(this,Ln).has(t)&&!m(this,Or).has(t))if(o){var i=document.createDocumentFragment(),s=bt();i.append(s),m(this,Or).set(t,{effect:_t(()=>r(s)),fragment:i})}else m(this,Ln).set(t,_t(()=>r(this.anchor)));if(m(this,xn).set(n,t),o){for(let[a,l]of m(this,Ln))a===t?n.unskip_effect(l):n.skip_effect(l);for(let[a,l]of m(this,Or))a===t?n.unskip_effect(l.effect):n.skip_effect(l.effect);n.oncommit(m(this,Ga)),n.ondiscard(m(this,yc))}else oe&&(this.anchor=ye),m(this,Ga).call(this,n)}};xn=new WeakMap,Ln=new WeakMap,Or=new WeakMap,bi=new WeakMap,Fa=new WeakMap,Ga=new WeakMap,yc=new WeakMap});var Gm=v(()=>{Le();Ce();vt();Me();gn();Te();st();Yt();xi();No();Ne()});function ue(e,t,r=!1){var n;oe&&(n=ye,wt());var o=new yn(e),i=r?65536:0;function s(a,l){if(oe){var c=os(n);if(a!==parseInt(c.substring(1))){var f=un();Ue(f),o.anchor=f,at(!1),o.ensure(a,l),at(!0);return}}o.ensure(a,l)}hr(()=>{var a=!1;t((l,c=0)=>{a=!0,s(c,l)}),a||s(-1,null)},i)}var Zm=v(()=>{Ae();Me();Ce();xi()});var Qm=v(()=>{st();Ce();Me();xi()});function Ju(e,t){oe&&Ue(Ye(e)),Nt(()=>{var r=t();for(var n in r){var o=r[n];o?e.style.setProperty(n,o):e.style.removeProperty(n)}})}var Rm=v(()=>{Ce();Me();It()});function ht(e,t){return t}function zC(e,t,r){for(var n=[],o=t.length,i,s=t.length,a=0;a{if(i){if(i.pending.delete(p),i.done.add(p),i.pending.size===0){var u=e.outrogroups;ju(e,ji(i.done)),u.delete(i),u.size===0&&(e.outrogroups=null)}}else s-=1},!1)}if(s===0){var l=n.length===0&&r!==null;if(l){var c=r,f=c.parentNode;$a(f),f.append(c),e.items.clear()}ju(e,t,!l)}else i={pending:new Set(t),done:new Set},(e.outrogroups??(e.outrogroups=new Set)).add(i)}function ju(e,t,r=!0){var n;if(e.pending.size>0){n=new Set;for(let s of e.pending.values())for(let a of s)n.add(e.items.get(a).e)}for(var o=0;o{var E=r();return Yr(E)?E:E==null?[]:ji(E)});G&&pt(p,"{#each ...}");var u,h=new Map,g=!0;function b(E){(C.effect.f&16384)===0&&(C.pending.delete(E),C.fallback=f,YC(C,u,s,t,n),f!==null&&(u.length===0?(f.f&33554432)===0?ws(f):(f.f^=33554432,Qa(f,null,s)):Zn(f,()=>{f=null})))}function x(E){C.pending.delete(E)}var w=hr(()=>{u=d(p);var E=u.length;let I=!1;if(oe){var T=os(s)==="[!";T!==(E===0)&&(s=un(),Ue(s),at(!1),I=!0)}for(var B=new Set,Z=xe,R=lc(),O=0;Oi(s)):(f=_t(()=>i(Lm??(Lm=bt()))),f.f|=33554432)),E>B.size&&(G?JC(u,n):iu("","","")),oe&&E>0&&Ue(un()),!g)if(h.set(Z,B),R){for(let[y,S]of a)B.has(y)||Z.skip_effect(S.e);Z.oncommit(b),Z.ondiscard(x)}else b(Z);I&&at(!0),d(p)}),C={effect:w,flags:t,items:a,pending:h,outrogroups:null,fallback:f};g=!1,oe&&(s=ye)}function Za(e){for(;e!==null&&(e.f&32)===0;)e=e.next;return e}function YC(e,t,r,n,o){var i=(n&8)!==0,s=t.length,a=e.items,l=Za(e.effect.first),c,f=null,p,u=[],h=[],g,b,x,w;if(i)for(w=0;w0){var O=(n&4)!==0&&s===0?r:null;if(i){for(w=0;w{if(p!==void 0)for(x of p)x.nodes?.a?.apply()})}function PC(e,t,r,n,o,i,s,a){var l=(s&1)!==0?(s&16)===0?ei(r,!1,!1):Dt(r):null,c=(s&2)!==0?Dt(o):null;return G&&l&&(l.trace=()=>{a()[c?.v??o]}),{v:l,i:c,e:_t(()=>(i(t,l??r,c??o,a),()=>{e.delete(n)}))}}function Qa(e,t,r){if(e.nodes)for(var n=e.nodes.start,o=e.nodes.end,i=t&&(t.f&33554432)===0?t.nodes.start:r;n!==null;){var s=Bt(n);if(i.before(n),n===o)return;n=s}}function Zo(e,t,r){t===null?e.effect.first=r:t.next=r,r===null?e.effect.last=t:r.prev=t}function JC(e,t){let r=new Map,n=e.length;for(let o=0;o{Te();Me();It();Ce();vt();Le();Ae();gn();Ee();Ne();Fo();Yt();Lt();Zr()});function jC(e,t,r){if(!t||t===mm(String(r??"")))return;let n,o=e.__svelte_meta?.loc;o?n=`near ${o.file}:${o.line}:${o.column}`:Qr?.[yr]&&(n=`in ${Qr[yr]}`),fg(hc(n))}function Ku(e,t,r=!1,n=!1,o=!1,i=!1){var s=e,a="";if(r){var l=e;oe&&(s=Ue(Ye(l)))}te(()=>{var c=le;if(a===(a=t()??"")){oe&&wt();return}if(r&&!oe){c.nodes=null,l.innerHTML=a,a!==""&&Gt(Ye(l),l.lastChild);return}if(c.nodes!==null&&(Xu(c.nodes.start,c.nodes.end),c.nodes=null),a!==""){if(oe){for(var f=ye.data,p=wt(),u=p;p!==null&&(p.nodeType!==Nr||p.data!=="");)u=p,p=Bt(p);if(p===null)throw wo(),Bn;G&&!i&&jC(p.parentNode,f,a),Gt(ye,u),s=Ue(p);return}var h=n?ra:o?au:void 0,g=Rn(n?"svg":o?"math":"template",h);g.innerHTML=a;var b=n||o?g:g.content;if(Gt(Ye(b),b.lastChild),n||o)for(;Ye(b);)s.before(Ye(b));else s.before(b)}})}var Vm=v(()=>{Te();Ce();Me();vi();Ut();Go();Ne();st();It();Ee();Ae()});var Dm=v(()=>{Me()});var qu=v(()=>{Go();du();ta();ta()});function dt(e,t,...r){var n=new yn(e);hr(()=>{let o=t()??null;G&&o==null&&Kh(),n.ensure(o,o&&(i=>o(i,...r)))},65536)}function Om(e){return(t,...r)=>{var n=e(...r),o;if(oe)o=ye,wt();else{var i=n.render().trim(),s=Aa(i);o=Ye(s),G&&(Bt(o)!==null||o.nodeType!==Ul)&&pg(),t.before(o)}let a=n.setup?.(o);Gt(o,o),typeof a=="function"&&kt(a)}}var ef=v(()=>{Ae();Ce();st();Me();_c();vi();Ut();Lt();Ne();It();qu();xi()});function io(e,t,r){var n;oe&&(n=ye,wt());var o=new yn(e);hr(()=>{var i=t()??null;if(oe){var s=os(n),a=s==="[",l=i!==null;if(a!==l){var c=un();Ue(c),o.anchor=c,at(!1),o.ensure(i,i&&(f=>r(f,i))),at(!0);return}}o.ensure(i,i&&(f=>r(f,i)))},65536)}var Xm=v(()=>{Ae();Ce();Me();xi();Te()});var tf=v(()=>{Le();Ne()});var Mm=v(()=>{tf()});var rf=v(()=>{Le();Ce();Ee();Mm();_i();Te();Ae();gn();tn()});var Wm=v(()=>{Te();Me();It();Ce();_i();Ee();st();Ne();Ae();vi();Go();xi();rf()});var Hm=v(()=>{Me();It();Ce();Ae()});var zm=v(()=>{Ne();Wu();Ce();It()});function gt(e,t,r){sr(()=>{var n=Ge(()=>t(e,r?.())||{});if(r&&n?.update){var o=!1,i={};Nt(()=>{var s=r();Sa(s),o&&Xl(i,s)&&(i=s,n.update(s))}),o=!0}if(n?.destroy)return()=>n.destroy()})}var Ym=v(()=>{Ce();na();Ee()});function wc(e,t){var r=void 0,n;uc(()=>{r!==(r=t())&&(n&&(rt(n),n=null),r&&(n=_t(()=>{sr(()=>r(e))})))})}var Ic=v(()=>{Ce()});var Pm=v(()=>{});function Jm(e){var t,r,n="";if(typeof e=="string"||typeof e=="number")n+=e;else if(typeof e=="object")if(Array.isArray(e)){var o=e.length;for(t=0;t{});function Jt(e){return typeof e=="object"?jm(e):e??""}function tv(e,t,r){var n=e==null?"":""+e;if(t&&(n=n?n+" "+t:t),r){for(var o of Object.keys(r))if(r[o])n=n?n+" "+o:o;else if(n.length)for(var i=o.length,s=0;(s=n.indexOf(o,s))>=0;){var a=s+i;(s===0||qm.includes(n[s-1]))&&(a===n.length||qm.includes(n[a]))?n=(s===0?"":n.substring(0,s))+n.substring(a+1):s=a}}return n===""?null:n}function ev(e,t=!1){var r=t?" !important;":";",n="";for(var o of Object.keys(e)){var i=e[o];i!=null&&i!==""&&(n+=" "+o+": "+i+r)}return n}function nf(e){return e[0]!=="-"||e[1]!=="-"?e.toLowerCase():e}function rv(e,t){if(t){var r="",n,o;if(Array.isArray(t)?(n=t[0],o=t[1]):n=t,e){e=String(e).replaceAll(/\s*\/\*.*?\*\/\s*/g,"").trim();var i=!1,s=0,a=!1,l=[];n&&l.push(...Object.keys(n).map(nf)),o&&l.push(...Object.keys(o).map(nf));var c=0,f=-1;let b=e.length;for(var p=0;p{Pm();Km();Le();qm=[...` -\r\f\xA0\v\uFEFF`]});function Pe(e,t,r,n,o,i){var s=e[Ks];if(oe||s!==r||s===void 0){var a=tv(r,n,i);(!oe||a!==e.getAttribute("class"))&&(a==null?e.removeAttribute("class"):t?e.className=a:e.setAttribute("class",a)),e[Ks]=r}else if(i&&o!==i)for(var l in i){var c=!!i[l];(o==null||c!==!!o[l])&&e.classList.toggle(l,c)}return i}var of=v(()=>{Ra();Ae();Me()});function sf(e,t={},r,n){for(var o in r){var i=r[o];t[o]!==i&&(r[o]==null?e.style.removeProperty(o):e.style.setProperty(o,i,n))}}function nt(e,t,r,n){var o=e[qs];if(oe||o!==t){var i=rv(t,n);(!oe||i!==e.getAttribute("style"))&&(i==null?e.removeAttribute("style"):e.style.cssText=i),e[qs]=t}else n&&(Array.isArray(n)?(sf(e,r?.[0],n[0]),sf(e,r?.[1],n[1],"important")):sf(e,r,n));return n}var af=v(()=>{Ra();Ae();Me()});function La(e,t,r=!1){if(e.multiple){if(t==null)return;if(!Yr(t))return gg();for(var n of e.options)n.selected=t.includes(nv(n));return}for(n of e.options){var o=nv(n);if(Ru(o,t)){n.selected=!0;return}}(!r||t!==void 0)&&(e.selectedIndex=-1)}function lf(e){var t=new MutationObserver(()=>{La(e,e.__value)});t.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["value"]}),kt(()=>{t.disconnect()})}function nv(e){return"__value"in e?e.__value:e.value}var cf=v(()=>{Ce();tn();ci();Le();Ut();Yt();lr()});function Cc(e){if(oe){var t=!1,r=()=>{if(!t){if(t=!0,e.hasAttribute("value")){var n=e.value;re(e,"value",null),e.value=n}if(e.hasAttribute("checked")){var o=e.checked;re(e,"checked",null),e.checked=o}}};e[xo]=r,Ct(r),cc()}}function lv(e,t){t?e.hasAttribute("selected")||e.setAttribute("selected",""):e.removeAttribute("selected")}function re(e,t,r,n){var o=cv(e);if(oe&&(o[t]=e.getAttribute(t),t==="src"||t==="srcset"||t==="href"&&e.nodeName===tE)){n||sE(e,t,r??"");return}o[t]!==(o[t]=r)&&(t==="loading"&&(e[Rh]=r),r==null?e.removeAttribute(t):typeof r!="string"&&dv(e).includes(t)?e[t]=r:e.setAttribute(t,r))}function iE(e,t,r,n,o=!1,i=!1){if(oe&&o&&e.nodeName===rE){var s=e,a=s.type==="checkbox"?"defaultChecked":"defaultValue";a in r||Cc(s)}var l=cv(e),c=l[sv],f=!l[av];let p=oe&&c;p&&at(!1);var u=t||{},h=e.nodeName===nE;for(var g in t)g in r||(r[g]=null);r.class?r.class=Jt(r.class):(n||r[nn])&&(r.class=null),r[Er]&&(r.style??(r.style=null));var b=dv(e);for(let B in r){let Z=r[B];if(h&&B==="value"&&Z==null){e.value=e.__value="",u[B]=Z;continue}if(B==="class"){var x=e.namespaceURI==="http://www.w3.org/1999/xhtml";Pe(e,x,Z,n,t?.[nn],r[nn]),u[B]=Z,u[nn]=r[nn];continue}if(B==="style"){nt(e,Z,t?.[Er],r[Er]),u[B]=Z,u[Er]=r[Er];continue}var w=u[B];if(!(Z===w&&!(Z===void 0&&e.hasAttribute(B)))){u[B]=Z;var C=B[0]+B[1];if(C!=="$$")if(C==="on"){let R={},O="$$"+B,H=B.slice(2);var E=_m(H);if(vm(H)&&(H=H.slice(0,-7),R.capture=!0),!E&&w){if(Z!=null)continue;e.removeEventListener(H,u[O],R),u[O]=null}if(E)Pt(H,e,Z),oo([H]);else if(Z!=null){let F=function($){u[B].call(this,$)};u[O]=mc(H,e,F,R)}}else if(B==="style")re(e,B,Z);else if(B==="autofocus")Uu(e,!!Z);else if(!c&&(B==="__value"||B==="value"&&Z!=null))e.value=e.__value=Z;else if(B==="selected"&&h)lv(e,Z);else{var I=B;f||(I=bm(I));var T=I==="defaultValue"||I==="defaultChecked";if(Z==null&&!c&&!T)if(l[B]=null,I==="value"||I==="checked"){let R=e,O=t===void 0;if(I==="value"){let H=R.defaultValue;R.removeAttribute(I),R.defaultValue=H,R.value=R.__value=O?H:null}else{let H=R.defaultChecked;R.removeAttribute(I),R.defaultChecked=H,R.checked=O?H:!1}}else e.removeAttribute(B);else T||b.includes(I)&&(c||typeof Z!="string")?(e[I]=Z,I in l&&(l[I]=He)):typeof Z!="function"&&re(e,I,Z,i)}}}return p&&at(!0),u}function jt(e,t,r=[],n=[],o=[],i,s=!1,a=!1){wa(o,r,n,l=>{var c=void 0,f={},p=e.nodeName===oE,u=!1;if(uc(()=>{var g=t(...l.map(d)),b=iE(e,c,g,i,s,a);u&&p&&"value"in g&&La(e,g.value);for(let w of Object.getOwnPropertySymbols(f))g[w]||rt(f[w]);for(let w of Object.getOwnPropertySymbols(g)){var x=g[w];w.description===lu&&(!c||x!==c[w])&&(f[w]&&rt(f[w]),f[w]=_t(()=>wc(e,()=>x))),b[w]=x}c=b}),p){var h=e;sr(()=>{La(h,c.value,!0),lf(h)})}u=!0})}function cv(e){var t;return e[t=Ll]??(e[t]={[sv]:e.nodeName.includes("-"),[av]:e.namespaceURI===Vl})}function dv(e){var t=e.getAttribute("is")||e.nodeName,r=ov.get(t);if(r)return r;ov.set(t,r=[]);for(var n,o=e,i=Element.prototype;i!==o;){n=Gl(o);for(var s in n)n[s].set&&s!=="innerHTML"&&s!=="textContent"&&s!=="innerText"&&r.push(s);o=bo(o)}return r}function sE(e,t,r){G&&(t==="srcset"&&aE(e,r)||df(e.getAttribute(t)??"",r)||ug(t,e.outerHTML.replace(e.innerHTML,e.innerHTML&&"..."),String(r)))}function df(e,t){return e===t?!0:new URL(e,document.baseURI).href===new URL(t,document.baseURI).href}function iv(e){return e.split(",").map(t=>t.trim().split(" ").filter(Boolean))}function aE(e,t){var r=iv(e.srcset),n=iv(t);return n.length===r.length&&n.every(([o,i],s)=>i===r[s][1]&&(df(r[s][0],o)||df(o,r[s][0])))}var nn,Er,sv,av,tE,rE,nE,oE,ov,uv=v(()=>{Ne();Me();Le();Is();dc();Ut();Ae();gn();Go();Ee();Ic();Ra();of();af();Te();Ce();cf();No();nn=Symbol("class"),Er=Symbol("style"),sv=Symbol("is custom element"),av=Symbol("is html"),tE=es?"link":"LINK",rE=es?"input":"INPUT",nE=es?"option":"OPTION",oE=es?"select":"SELECT";ov=new Map});var fv=v(()=>{Me();It();_c();Ic()});var pv=v(()=>{tn()});function pf(e,t,r=t){var n=new WeakSet;Tu(e,"input",async o=>{G&&e.type==="checkbox"&&ou();var i=o?e.defaultValue:e.value;if(i=uf(e)?ff(i):i,r(i),xe!==null&&n.add(xe),await ka(),i!==(i=t())){var s=e.selectionStart,a=e.selectionEnd,l=e.value.length;if(e.value=i??"",a!==null){var c=e.value.length;s===a&&a===l&&c>l?(e.selectionStart=c,e.selectionEnd=c):(e.selectionStart=s,e.selectionEnd=Math.min(a,c))}}}),(oe&&e.defaultValue!==e.value||Ge(t)==null&&e.value)&&(r(uf(e)?ff(e.value):e.value),xe!==null&&n.add(xe)),Nt(()=>{G&&e.type==="checkbox"&&ou();var o=t();if(e===document.activeElement){var i=lt?ni:xe;if(n.has(i))return}uf(e)&&o===ff(e.value)||e.type==="date"&&!o&&!e.value||o!==e.value&&(e.value=o??"")})}function uf(e){var t=e.type;return t==="number"||t==="range"}function ff(e){return e===""?null:+e}var hv=v(()=>{Ne();Ce();tn();Lt();ci();gn();Me();Ee();st();Yt();lr()});var gv=v(()=>{Ce();tn()});var mv=v(()=>{tn()});var vv=v(()=>{Ce();Le()});function kc(e,t,r){var n=lE.observe(e,()=>r(e[t]));sr(()=>(Ge(()=>r(e[t])),n))}var Qo,Es,Ua,$c,_v,Bc,hf,lE,bv=v(()=>{Ce();Ee();Bc=class Bc{constructor(t){U(this,$c);U(this,Qo,new WeakMap);U(this,Es);U(this,Ua);ge(this,Ua,t)}observe(t,r){var n=m(this,Qo).get(t)||new Set;return n.add(r),m(this,Qo).set(t,n),Ie(this,$c,_v).call(this).observe(t,m(this,Ua)),()=>{var o=m(this,Qo).get(t);o.delete(r),o.size===0&&(m(this,Qo).delete(t),m(this,Es).unobserve(t))}}};Qo=new WeakMap,Es=new WeakMap,Ua=new WeakMap,$c=new WeakSet,_v=function(){return m(this,Es)??ge(this,Es,new ResizeObserver(t=>{for(var r of t){Bc.entries.set(r.target,r);for(var n of m(this,Qo).get(r.target)||[])n(r)}}))},Be(Bc,"entries",new WeakMap);hf=Bc,lE=new hf({box:"border-box"})});function gf(e,t){return e===t||e?.[yt]===t}function Xr(e={},t,r,n){var o=be.r,i=le;return sr(()=>{var s,a;return Nt(()=>{s=a,a=n?.()||[],Ge(()=>{gf(r(...a),e)||(t(e,...a),s&&gf(r(...s),e)&&t(null,...s))})}),()=>{let l=i;for(;l!==o&&l.parent!==null&&l.parent.f&33554432;)l=l.parent;let c=()=>{a&&gf(r(...a),e)&&t(null,...a)},f=l.teardown;l.teardown=()=>{c(),f?.()}}}),e}var xv=v(()=>{Ae();st();Ce();Ee()});var yv=v(()=>{Ce();tn()});var wv=v(()=>{Ce();tn()});var mf=v(()=>{Le();Ce();Is()});function vf(e=!1){let t=be,r=t.l.u;if(!r)return;let n=()=>Sa(t.s);if(e){let o=0,i={},s=ro(()=>{let a=!1,l=t.s;for(let c in l)l[c]!==i[c]&&(i[c]=l[c],a=!0);return a&&o++,o});n=()=>d(s)}r.b.length&&ui(()=>{Iv(t,n),Ki(r.b)}),ct(()=>{let o=Ge(()=>r.m.map(Qh));return()=>{for(let i of o)typeof i=="function"&&i()}}),r.a.length&&ct(()=>{Iv(t,n),Ki(r.a)})}function Iv(e,t){if(e.l.s)for(let r of e.l.s)d(r);t()}var Cv=v(()=>{Le();st();Fo();Ce();Ee()});var Ev=v(()=>{vt();Ee();Le()});function Kt(e,t,r){return new Proxy(G?{props:e,exclude:t,name:r,other:{},to_proxy:[]}:{props:e,exclude:t},hE)}function wn(...e){return new Proxy({props:e},gE)}function z(e,t,r,n){var o=!kn||(r&2)!==0,i=(r&8)!==0,s=(r&16)!==0,a=n,l=!0,c=void 0,f=()=>s&&o?(c??(c=ro(n)),d(c)):(l&&(l=!1,a=s?Ge(n):n),a);let p;if(i){var u=yt in e||qi in e;p=rr(e,t)?.set??(u&&t in e?I=>e[t]=I:void 0)}var h,g=!1;i?[h,g]=gu(()=>e[t]):h=e[t],h===void 0&&n!==void 0&&(h=f(),p&&(o&&qh(t),p(h)));var b;if(o?b=()=>{var I=e[t];return I===void 0?f():(l=!0,I)}:b=()=>{var I=e[t];return I!==void 0&&(a=void 0),I===void 0?a:I},o&&(r&4)===0)return b;if(p){var x=e.$$legacy;return(function(I,T){return arguments.length>0?((!o||!T||x||g)&&p(T?b():I),I):b()})}var w=!1,C=((r&1)!==0?ro:si)(()=>(w=!1,b()));G&&(C.label=t),i&&d(C);var E=le;return(function(I,T){if(arguments.length>0){let B=T?d(C):o&&i?Xt(I):I;return X(C,B),w=!0,a!==void 0&&(a=B),I}return Tr&&w||(E.f&16384)!==0?C.v:d(C)})}var hE,gE,$v=v(()=>{Ne();Te();Le();vt();Fo();Ee();Lt();Ae();ci();ca();lr();Ce();hE={get(e,t){if(!e.exclude.has(t))return e.props[t]},set(e,t){return G&&eg(`${e.name}.${String(t)}`),!1},getOwnPropertyDescriptor(e,t){if(!e.exclude.has(t)&&t in e.props)return{enumerable:!0,configurable:!0,value:e.props[t]}},has(e,t){return e.exclude.has(t)?!1:t in e.props},ownKeys(e){return Reflect.ownKeys(e.props).filter(t=>!e.exclude.has(t))}};gE={get(e,t){let r=e.props.length;for(;r--;){let n=e.props[r];if(Yo(n)&&(n=n()),typeof n=="object"&&n!==null&&t in n)return n[t]}},set(e,t,r){let n=e.props.length;for(;n--;){let o=e.props[n];Yo(o)&&(o=o());let i=rr(o,t);if(i&&i.set)return i.set(r),!0}return!1},getOwnPropertyDescriptor(e,t){let r=e.props.length;for(;r--;){let n=e.props[r];if(Yo(n)&&(n=n()),typeof n=="object"&&n!==null&&t in n){let o=rr(n,t);return o&&!o.configurable&&(o.configurable=!0),o}}},has(e,t){if(t===yt||t===qi)return!1;for(let r of e.props)if(Yo(r)&&(r=r()),r!=null&&t in r)return!0;return!1},ownKeys(e){let t=[];for(let r of e.props)if(Yo(r)&&(r=r()),!!r){for(let n in r)t.includes(n)||t.push(n);for(let n of Object.getOwnPropertySymbols(r))t.includes(n)||t.push(n)}return t}}});var Bv=v(()=>{st();Te();Ce();Ut();ca();No()});function kv(e){return new _f(e)}var so,on,_f,Sv=v(()=>{Ae();Ce();vt();_i();Ee();Yt();Le();Lt();Ut();Ne();Te();st();lr();Co();mf();_f=class{constructor(t){U(this,so);U(this,on);var r=new Map,n=(i,s)=>{var a=ei(s,!1,!1);return r.set(i,a),a};let o=new Proxy({...t.props||{},$$events:{}},{get(i,s){return d(r.get(s)??n(s,Reflect.get(i,s)))},has(i,s){return s===qi?!0:(d(r.get(s)??n(s,Reflect.get(i,s))),Reflect.has(i,s))},set(i,s,a){return X(r.get(s)??n(s,a),a),Reflect.set(i,s,a)}});ge(this,on,(t.hydrate?Cs:Na)(t.component,{target:t.target,anchor:t.anchor,props:o,context:t.context,intro:t.intro??!1,recover:t.recover,transformError:t.transformError})),!lt&&(!t?.props?.$$host||t.sync===!1)&&Nn(),ge(this,so,o.$$events);for(let i of Object.keys(m(this,on)))i==="$set"||i==="$destroy"||i==="$on"||Mt(this,i,{get(){return m(this,on)[i]},set(s){m(this,on)[i]=s},enumerable:!0});m(this,on).$set=i=>{Object.assign(o,i)},m(this,on).$destroy=()=>{xc(m(this,on))}}$set(t){m(this,on).$set(t)}$on(t,r){m(this,so)[t]=m(this,so)[t]||[];let n=(...o)=>r.call(this,...o);return m(this,so)[t].push(n),()=>{m(this,so)[t]=m(this,so)[t].filter(o=>o!==n)}}$destroy(){m(this,on).$destroy()}};so=new WeakMap,on=new WeakMap});function bf(e,t,r,n){let o=r[e]?.type;if(t=o==="Boolean"&&typeof t!="boolean"?t!=null:t,!n||!r[e])return t;if(n==="toAttribute")switch(o){case"Object":case"Array":return t==null?null:JSON.stringify(t);case"Boolean":return t?"":null;case"Number":return t??null;default:return t}else switch(o){case"Object":case"Array":return t&&JSON.parse(t);case"Boolean":return t;case"Number":return t!=null?+t:t;default:return t}}function CE(e){let t={};return e.childNodes.forEach(r=>{t[r.slot||"default"]=!0}),t}var IE,Av=v(()=>{Sv();Ce();vi();Le();It();typeof HTMLElement=="function"&&(IE=class extends HTMLElement{constructor(t,r,n){super();Be(this,"$$ctor");Be(this,"$$s");Be(this,"$$c");Be(this,"$$cn",!1);Be(this,"$$d",{});Be(this,"$$r",!1);Be(this,"$$p_d",{});Be(this,"$$l",{});Be(this,"$$l_u",new Map);Be(this,"$$me");Be(this,"$$shadowRoot",null);this.$$ctor=t,this.$$s=r,n&&(this.$$shadowRoot=this.attachShadow(n))}addEventListener(t,r,n){if(this.$$l[t]=this.$$l[t]||[],this.$$l[t].push(r),this.$$c){let o=this.$$c.$on(t,r);this.$$l_u.set(r,o)}super.addEventListener(t,r,n)}removeEventListener(t,r,n){if(super.removeEventListener(t,r,n),this.$$c){let o=this.$$l_u.get(r);o&&(o(),this.$$l_u.delete(r))}}async connectedCallback(){if(this.$$cn=!0,!this.$$c){let t=function(o){return i=>{let s=Rn("slot");o!=="default"&&(s.name=o),N(i,s)}};if(await Promise.resolve(),!this.$$cn||this.$$c)return;let r={},n=CE(this);for(let o of this.$$s)o in n&&(o==="default"&&!this.$$d.children?(this.$$d.children=t(o),r.default=!0):r[o]=t(o));for(let o of this.attributes){let i=this.$$g_p(o.name);i in this.$$d||(this.$$d[i]=bf(i,o.value,this.$$p_d,"toProp"))}for(let o in this.$$p_d)!(o in this.$$d)&&this[o]!==void 0&&(this.$$d[o]=this[o],delete this[o]);this.$$c=kv({component:this.$$ctor,target:this.$$shadowRoot||this,props:{...this.$$d,$$slots:r,$$host:this}}),this.$$me=fi(()=>{Nt(()=>{this.$$r=!0;for(let o of eu(this.$$c)){if(!this.$$p_d[o]?.reflect)continue;this.$$d[o]=this.$$c[o];let i=bf(o,this.$$d[o],this.$$p_d,"toAttribute");i==null?this.removeAttribute(this.$$p_d[o].attribute||o):this.setAttribute(this.$$p_d[o].attribute||o,i)}this.$$r=!1})});for(let o in this.$$l)for(let i of this.$$l[o]){let s=this.$$c.$on(o,i);this.$$l_u.set(i,s)}this.$$l={}}}attributeChangedCallback(t,r,n){this.$$r||(t=this.$$g_p(t),this.$$d[t]=bf(t,n,this.$$p_d,"toProp"),this.$$c?.$set({[t]:this.$$d[t]}))}disconnectedCallback(){this.$$cn=!1,Promise.resolve().then(()=>{!this.$$cn&&this.$$c&&(this.$$c.$destroy(),this.$$me(),this.$$c=void 0)})}$$g_p(t){return eu(this.$$p_d).find(r=>this.$$p_d[r].attribute===t||!this.$$p_d[r].attribute&&r.toLowerCase()===t)||t}})});var Nv=v(()=>{Ae();is();Ut();Ee()});var ae=v(()=>{gm();Te();st();ym();Wu();wm();Bm();km();Sm();Zr();Am();Nm();Fm();Gm();Zm();Qm();Rm();Tm();Vm();Dm();ef();Xm();Wm();Hm();zm();Ym();Ic();uv();of();Is();dc();fv();af();rf();pv();hv();gv();mv();vv();cf();bv();xv();yv();wv();Me();mf();Cv();Ev();vi();No();Yt();Fo();Ce();vt();$v();ca();nc();Mu();_i();Ee();Bv();tf();ci();Av();It();Ra();is();Le();qu();Lu();Nv();as()});function Fv(e,t){if(lt||Tl("hydratable"),oe){let r=window.__svelte?.h;if(r?.has(e))return r.get(e);G?Jh(e):dg(e)}return t()}var Gv=v(()=>{lr();Me();Ut();Lt();Ne()});var Zv={};jd(Zv,{afterUpdate:()=>SE,beforeUpdate:()=>kE,createContext:()=>yg,createEventDispatcher:()=>BE,createRawSnippet:()=>Om,flushSync:()=>Nn,fork:()=>Tg,getAbortSignal:()=>EE,getAllContexts:()=>wg,getContext:()=>zn,hasContext:()=>sa,hydratable:()=>Fv,hydrate:()=>Cs,mount:()=>Na,onDestroy:()=>ao,onMount:()=>$s,setContext:()=>jo,settled:()=>fm,tick:()=>ka,unmount:()=>xc,untrack:()=>Ge});function EE(){var e;return me===null&&Ph(),((e=me).ac??(e.ac=new AbortController)).signal}function $s(e){be===null&&Mn("onMount"),kn&&be.l!==null?xf(be).m.push(e):ct(()=>{let t=Ge(e);if(typeof t=="function")return t})}function ao(e){be===null&&Mn("onDestroy"),$s(()=>()=>Ge(e))}function $E(e,t,{bubbles:r=!1,cancelable:n=!1}={}){return new CustomEvent(e,{detail:t,bubbles:r,cancelable:n})}function BE(){let e=be;return e===null&&Mn("createEventDispatcher"),(t,r,n)=>{let o=e.s.$$events?.[t];if(o){let i=Yr(o)?o.slice():[o],s=$E(t,r,n);for(let a of i)a.call(e.x,s);return!s.defaultPrevented}return!0}}function kE(e){be===null&&Mn("beforeUpdate"),be.l===null&&su("beforeUpdate"),xf(be).b.push(e)}function SE(e){be===null&&Mn("afterUpdate"),be.l===null&&su("afterUpdate"),xf(be).a.push(e)}function xf(e){var t=e.l;return t.u??(t.u={a:[],b:[],m:[]})}var Dr=v(()=>{Ee();Le();ae();Lt();lr();st();Ne();Yt();st();Gv();_i();Ee();ef();if(G){let e=function(t){if(!(t in globalThis)){let r;Object.defineProperty(globalThis,t,{configurable:!0,get:()=>{if(r!==void 0)return r;tg(t)},set:n=>{r=n}})}};e("$state"),e("$effect"),e("$derived"),e("$inspect"),e("$props"),e("$bindable")}});var Qv=v(()=>{});var Rv,_e=v(()=>{Qv();typeof window<"u"&&((Rv=window.__svelte??(window.__svelte={})).v??(Rv.v=new Set)).add("5")});function Uv(){for(var e=0,t=arguments.length,r={},n;e=0&&(n=r.slice(o+1),r=r.slice(0,o)),r&&!t.hasOwnProperty(r))throw new Error("unknown type: "+r);return{type:r,name:n}})}function XE(e,t){for(var r=0,n=e.length,o;r{DE={value:()=>{}};Sc.prototype=Uv.prototype={constructor:Sc,on:function(e,t){var r=this._,n=OE(e+"",r),o,i=-1,s=n.length;if(arguments.length<2){for(;++i0)for(var r=new Array(o),n=0,o,i;n{Tv()});var Nc,wf,If=v(()=>{Nc="http://www.w3.org/1999/xhtml",wf={svg:"http://www.w3.org/2000/svg",xhtml:Nc,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"}});function lo(e){var t=e+="",r=t.indexOf(":");return r>=0&&(t=e.slice(0,r))!=="xmlns"&&(e=e.slice(r+1)),wf.hasOwnProperty(t)?{space:wf[t],local:e}:e}var Fc=v(()=>{If()});function ME(e){return function(){var t=this.ownerDocument,r=this.namespaceURI;return r===Nc&&t.documentElement.namespaceURI===Nc?t.createElement(e):t.createElementNS(r,e)}}function WE(e){return function(){return this.ownerDocument.createElementNS(e.space,e.local)}}function Gc(e){var t=lo(e);return(t.local?WE:ME)(t)}var Cf=v(()=>{Fc();If()});function HE(){}function wi(e){return e==null?HE:function(){return this.querySelector(e)}}var Zc=v(()=>{});function Vv(e){typeof e!="function"&&(e=wi(e));for(var t=this._groups,r=t.length,n=new Array(r),o=0;o{In();Zc()});function Ef(e){return e==null?[]:Array.isArray(e)?e:Array.from(e)}var Ov=v(()=>{});function zE(){return[]}function Va(e){return e==null?zE:function(){return this.querySelectorAll(e)}}var $f=v(()=>{});function YE(e){return function(){return Ef(e.apply(this,arguments))}}function Xv(e){typeof e=="function"?e=YE(e):e=Va(e);for(var t=this._groups,r=t.length,n=[],o=[],i=0;i{In();Ov();$f()});function Da(e){return function(){return this.matches(e)}}function Qc(e){return function(t){return t.matches(e)}}var Oa=v(()=>{});function JE(e){return function(){return PE.call(this.children,e)}}function jE(){return this.firstElementChild}function Wv(e){return this.select(e==null?jE:JE(typeof e=="function"?e:Qc(e)))}var PE,Hv=v(()=>{Oa();PE=Array.prototype.find});function qE(){return Array.from(this.children)}function e$(e){return function(){return KE.call(this.children,e)}}function zv(e){return this.selectAll(e==null?qE:e$(typeof e=="function"?e:Qc(e)))}var KE,Yv=v(()=>{Oa();KE=Array.prototype.filter});function Pv(e){typeof e!="function"&&(e=Da(e));for(var t=this._groups,r=t.length,n=new Array(r),o=0;o{In();Oa()});function Rc(e){return new Array(e.length)}var Bf=v(()=>{});function jv(){return new mt(this._enter||this._groups.map(Rc),this._parents)}function Xa(e,t){this.ownerDocument=e.ownerDocument,this.namespaceURI=e.namespaceURI,this._next=null,this._parent=e,this.__data__=t}var kf=v(()=>{Bf();In();Xa.prototype={constructor:Xa,appendChild:function(e){return this._parent.insertBefore(e,this._next)},insertBefore:function(e,t){return this._parent.insertBefore(e,t)},querySelector:function(e){return this._parent.querySelector(e)},querySelectorAll:function(e){return this._parent.querySelectorAll(e)}}});function Kv(e){return function(){return e}}var qv=v(()=>{});function t$(e,t,r,n,o,i){for(var s=0,a,l=t.length,c=i.length;s=E&&(E=C+1);!(T=x[E])&&++E{In();kf();qv()});function r_(){return new mt(this._exit||this._groups.map(Rc),this._parents)}var n_=v(()=>{Bf();In()});function o_(e,t,r){var n=this.enter(),o=this,i=this.exit();return typeof e=="function"?(n=e(n),n&&(n=n.selection())):n=n.append(e+""),t!=null&&(o=t(o),o&&(o=o.selection())),r==null?i.remove():r(i),n&&o?n.merge(o).order():o}var i_=v(()=>{});function s_(e){for(var t=e.selection?e.selection():e,r=this._groups,n=t._groups,o=r.length,i=n.length,s=Math.min(o,i),a=new Array(o),l=0;l{In()});function l_(){for(var e=this._groups,t=-1,r=e.length;++t=0;)(s=n[o])&&(i&&s.compareDocumentPosition(i)^4&&i.parentNode.insertBefore(s,i),i=s);return this}var c_=v(()=>{});function d_(e){e||(e=i$);function t(p,u){return p&&u?e(p.__data__,u.__data__):!p-!u}for(var r=this._groups,n=r.length,o=new Array(n),i=0;it?1:e>=t?0:NaN}var u_=v(()=>{In()});function f_(){var e=arguments[0];return arguments[0]=this,e.apply(null,arguments),this}var p_=v(()=>{});function h_(){return Array.from(this)}var g_=v(()=>{});function m_(){for(var e=this._groups,t=0,r=e.length;t{});function __(){let e=0;for(let t of this)++e;return e}var b_=v(()=>{});function x_(){return!this.node()}var y_=v(()=>{});function w_(e){for(var t=this._groups,r=0,n=t.length;r{});function s$(e){return function(){this.removeAttribute(e)}}function a$(e){return function(){this.removeAttributeNS(e.space,e.local)}}function l$(e,t){return function(){this.setAttribute(e,t)}}function c$(e,t){return function(){this.setAttributeNS(e.space,e.local,t)}}function d$(e,t){return function(){var r=t.apply(this,arguments);r==null?this.removeAttribute(e):this.setAttribute(e,r)}}function u$(e,t){return function(){var r=t.apply(this,arguments);r==null?this.removeAttributeNS(e.space,e.local):this.setAttributeNS(e.space,e.local,r)}}function C_(e,t){var r=lo(e);if(arguments.length<2){var n=this.node();return r.local?n.getAttributeNS(r.space,r.local):n.getAttribute(r)}return this.each((t==null?r.local?a$:s$:typeof t=="function"?r.local?u$:d$:r.local?c$:l$)(r,t))}var E_=v(()=>{Fc()});function Lc(e){return e.ownerDocument&&e.ownerDocument.defaultView||e.document&&e||e.defaultView}var Sf=v(()=>{});function f$(e){return function(){this.style.removeProperty(e)}}function p$(e,t,r){return function(){this.style.setProperty(e,t,r)}}function h$(e,t,r){return function(){var n=t.apply(this,arguments);n==null?this.style.removeProperty(e):this.style.setProperty(e,n,r)}}function $_(e,t,r){return arguments.length>1?this.each((t==null?f$:typeof t=="function"?h$:p$)(e,t,r??"")):Ro(this.node(),e)}function Ro(e,t){return e.style.getPropertyValue(t)||Lc(e).getComputedStyle(e,null).getPropertyValue(t)}var Af=v(()=>{Sf()});function g$(e){return function(){delete this[e]}}function m$(e,t){return function(){this[e]=t}}function v$(e,t){return function(){var r=t.apply(this,arguments);r==null?delete this[e]:this[e]=r}}function B_(e,t){return arguments.length>1?this.each((t==null?g$:typeof t=="function"?v$:m$)(e,t)):this.node()[e]}var k_=v(()=>{});function S_(e){return e.trim().split(/^|\s+/)}function Nf(e){return e.classList||new A_(e)}function A_(e){this._node=e,this._names=S_(e.getAttribute("class")||"")}function N_(e,t){for(var r=Nf(e),n=-1,o=t.length;++n{A_.prototype={add:function(e){var t=this._names.indexOf(e);t<0&&(this._names.push(e),this._node.setAttribute("class",this._names.join(" ")))},remove:function(e){var t=this._names.indexOf(e);t>=0&&(this._names.splice(t,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(e){return this._names.indexOf(e)>=0}}});function y$(){this.textContent=""}function w$(e){return function(){this.textContent=e}}function I$(e){return function(){var t=e.apply(this,arguments);this.textContent=t??""}}function Q_(e){return arguments.length?this.each(e==null?y$:(typeof e=="function"?I$:w$)(e)):this.node().textContent}var R_=v(()=>{});function C$(){this.innerHTML=""}function E$(e){return function(){this.innerHTML=e}}function $$(e){return function(){var t=e.apply(this,arguments);this.innerHTML=t??""}}function L_(e){return arguments.length?this.each(e==null?C$:(typeof e=="function"?$$:E$)(e)):this.node().innerHTML}var U_=v(()=>{});function B$(){this.nextSibling&&this.parentNode.appendChild(this)}function T_(){return this.each(B$)}var V_=v(()=>{});function k$(){this.previousSibling&&this.parentNode.insertBefore(this,this.parentNode.firstChild)}function D_(){return this.each(k$)}var O_=v(()=>{});function X_(e){var t=typeof e=="function"?e:Gc(e);return this.select(function(){return this.appendChild(t.apply(this,arguments))})}var M_=v(()=>{Cf()});function S$(){return null}function W_(e,t){var r=typeof e=="function"?e:Gc(e),n=t==null?S$:typeof t=="function"?t:wi(t);return this.select(function(){return this.insertBefore(r.apply(this,arguments),n.apply(this,arguments)||null)})}var H_=v(()=>{Cf();Zc()});function A$(){var e=this.parentNode;e&&e.removeChild(this)}function z_(){return this.each(A$)}var Y_=v(()=>{});function N$(){var e=this.cloneNode(!1),t=this.parentNode;return t?t.insertBefore(e,this.nextSibling):e}function F$(){var e=this.cloneNode(!0),t=this.parentNode;return t?t.insertBefore(e,this.nextSibling):e}function P_(e){return this.select(e?F$:N$)}var J_=v(()=>{});function j_(e){return arguments.length?this.property("__data__",e):this.node().__data__}var K_=v(()=>{});function G$(e){return function(t){e.call(this,t,this.__data__)}}function Z$(e){return e.trim().split(/^|\s+/).map(function(t){var r="",n=t.indexOf(".");return n>=0&&(r=t.slice(n+1),t=t.slice(0,n)),{type:t,name:r}})}function Q$(e){return function(){var t=this.__on;if(t){for(var r=0,n=-1,o=t.length,i;r{});function tb(e,t,r){var n=Lc(e),o=n.CustomEvent;typeof o=="function"?o=new o(t,r):(o=n.document.createEvent("Event"),r?(o.initEvent(t,r.bubbles,r.cancelable),o.detail=r.detail):o.initEvent(t,!1,!1)),e.dispatchEvent(o)}function L$(e,t){return function(){return tb(this,e,t)}}function U$(e,t){return function(){return tb(this,e,t.apply(this,arguments))}}function rb(e,t){return this.each((typeof t=="function"?U$:L$)(e,t))}var nb=v(()=>{Sf()});function*ob(){for(var e=this._groups,t=0,r=e.length;t{});function mt(e,t){this._groups=e,this._parents=t}function sb(){return new mt([[document.documentElement]],Ff)}function T$(){return this}var Ff,co,In=v(()=>{Dv();Mv();Hv();Yv();Jv();t_();kf();n_();i_();a_();c_();u_();p_();g_();v_();b_();y_();I_();E_();Af();k_();Z_();R_();U_();V_();O_();M_();H_();Y_();J_();K_();eb();nb();ib();Ff=[null];mt.prototype=sb.prototype={constructor:mt,select:Vv,selectAll:Xv,selectChild:Wv,selectChildren:zv,filter:Pv,data:e_,enter:jv,exit:r_,join:o_,merge:s_,selection:T$,order:l_,sort:d_,call:f_,nodes:h_,node:m_,size:__,empty:x_,each:w_,attr:C_,style:$_,property:B_,classed:G_,text:Q_,html:L_,raise:T_,lower:D_,append:X_,insert:W_,remove:z_,clone:P_,datum:j_,on:q_,dispatch:rb,[Symbol.iterator]:ob};co=sb});function qt(e){return typeof e=="string"?new mt([[document.querySelector(e)]],[document.documentElement]):new mt([[e]],Ff)}var ab=v(()=>{In()});function lb(e){let t;for(;t=e.sourceEvent;)e=t;return e}var cb=v(()=>{});function vr(e,t){if(e=lb(e),t===void 0&&(t=e.currentTarget),t){var r=t.ownerSVGElement||t;if(r.createSVGPoint){var n=r.createSVGPoint();return n.x=e.clientX,n.y=e.clientY,n=n.matrixTransform(t.getScreenCTM().inverse()),[n.x,n.y]}if(t.getBoundingClientRect){var o=t.getBoundingClientRect();return[e.clientX-o.left-t.clientLeft,e.clientY-o.top-t.clientTop]}}return[e.pageX,e.pageY]}var db=v(()=>{cb()});var $r=v(()=>{Oa();Fc();db();ab();In();Zc();$f();Af()});function Uc(e){e.stopImmediatePropagation()}function Lo(e){e.preventDefault(),e.stopImmediatePropagation()}var ub,Ii,Gf=v(()=>{ub={passive:!1},Ii={capture:!0,passive:!1}});function Ma(e){var t=e.document.documentElement,r=qt(e).on("dragstart.drag",Lo,Ii);"onselectstart"in t?r.on("selectstart.drag",Lo,Ii):(t.__noselect=t.style.MozUserSelect,t.style.MozUserSelect="none")}function Wa(e,t){var r=e.document.documentElement,n=qt(e).on("dragstart.drag",null);t&&(n.on("click.drag",Lo,Ii),setTimeout(function(){n.on("click.drag",null)},0)),"onselectstart"in r?n.on("selectstart.drag",null):(r.style.MozUserSelect=r.__noselect,delete r.__noselect)}var Zf=v(()=>{$r();Gf()});var Ha,fb=v(()=>{Ha=e=>()=>e});function za(e,{sourceEvent:t,subject:r,target:n,identifier:o,active:i,x:s,y:a,dx:l,dy:c,dispatch:f}){Object.defineProperties(this,{type:{value:e,enumerable:!0,configurable:!0},sourceEvent:{value:t,enumerable:!0,configurable:!0},subject:{value:r,enumerable:!0,configurable:!0},target:{value:n,enumerable:!0,configurable:!0},identifier:{value:o,enumerable:!0,configurable:!0},active:{value:i,enumerable:!0,configurable:!0},x:{value:s,enumerable:!0,configurable:!0},y:{value:a,enumerable:!0,configurable:!0},dx:{value:l,enumerable:!0,configurable:!0},dy:{value:c,enumerable:!0,configurable:!0},_:{value:f}})}var pb=v(()=>{za.prototype.on=function(){var e=this._.on.apply(this._,arguments);return e===this._?this:e}});function V$(e){return!e.ctrlKey&&!e.button}function D$(){return this.parentNode}function O$(e,t){return t??{x:e.x,y:e.y}}function X$(){return navigator.maxTouchPoints||"ontouchstart"in this}function Qf(){var e=V$,t=D$,r=O$,n=X$,o={},i=yi("start","drag","end"),s=0,a,l,c,f,p=0;function u(I){I.on("mousedown.drag",h).filter(n).on("touchstart.drag",x).on("touchmove.drag",w,ub).on("touchend.drag touchcancel.drag",C).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function h(I,T){if(!(f||!e.call(this,I,T))){var B=E(this,t.call(this,I,T),I,T,"mouse");B&&(qt(I.view).on("mousemove.drag",g,Ii).on("mouseup.drag",b,Ii),Ma(I.view),Uc(I),c=!1,a=I.clientX,l=I.clientY,B("start",I))}}function g(I){if(Lo(I),!c){var T=I.clientX-a,B=I.clientY-l;c=T*T+B*B>p}o.mouse("drag",I)}function b(I){qt(I.view).on("mousemove.drag mouseup.drag",null),Wa(I.view,c),Lo(I),o.mouse("end",I)}function x(I,T){if(e.call(this,I,T)){var B=I.changedTouches,Z=t.call(this,I,T),R=B.length,O,H;for(O=0;O{Ac();$r();Zf();Gf();fb();pb()});var Rf=v(()=>{hb();Zf()});function Tc(e,t,r){e.prototype=t.prototype=r,r.constructor=e}function Lf(e,t){var r=Object.create(e.prototype);for(var n in t)r[n]=t[n];return r}var gb=v(()=>{});function Ja(){}function vb(){return this.rgb().formatHex()}function j$(){return this.rgb().formatHex8()}function K$(){return Cb(this).formatHsl()}function _b(){return this.rgb().formatRgb()}function En(e){var t,r;return e=(e+"").trim().toLowerCase(),(t=M$.exec(e))?(r=t[1].length,t=parseInt(t[1],16),r===6?bb(t):r===3?new Br(t>>8&15|t>>4&240,t>>4&15|t&240,(t&15)<<4|t&15,1):r===8?Vc(t>>24&255,t>>16&255,t>>8&255,(t&255)/255):r===4?Vc(t>>12&15|t>>8&240,t>>8&15|t>>4&240,t>>4&15|t&240,((t&15)<<4|t&15)/255):null):(t=W$.exec(e))?new Br(t[1],t[2],t[3],1):(t=H$.exec(e))?new Br(t[1]*255/100,t[2]*255/100,t[3]*255/100,1):(t=z$.exec(e))?Vc(t[1],t[2],t[3],t[4]):(t=Y$.exec(e))?Vc(t[1]*255/100,t[2]*255/100,t[3]*255/100,t[4]):(t=P$.exec(e))?wb(t[1],t[2]/100,t[3]/100,1):(t=J$.exec(e))?wb(t[1],t[2]/100,t[3]/100,t[4]):mb.hasOwnProperty(e)?bb(mb[e]):e==="transparent"?new Br(NaN,NaN,NaN,0):null}function bb(e){return new Br(e>>16&255,e>>8&255,e&255,1)}function Vc(e,t,r,n){return n<=0&&(e=t=r=NaN),new Br(e,t,r,n)}function q$(e){return e instanceof Ja||(e=En(e)),e?(e=e.rgb(),new Br(e.r,e.g,e.b,e.opacity)):new Br}function ks(e,t,r,n){return arguments.length===1?q$(e):new Br(e,t,r,n??1)}function Br(e,t,r,n){this.r=+e,this.g=+t,this.b=+r,this.opacity=+n}function xb(){return`#${Ci(this.r)}${Ci(this.g)}${Ci(this.b)}`}function e1(){return`#${Ci(this.r)}${Ci(this.g)}${Ci(this.b)}${Ci((isNaN(this.opacity)?1:this.opacity)*255)}`}function yb(){let e=Xc(this.opacity);return`${e===1?"rgb(":"rgba("}${Ei(this.r)}, ${Ei(this.g)}, ${Ei(this.b)}${e===1?")":`, ${e})`}`}function Xc(e){return isNaN(e)?1:Math.max(0,Math.min(1,e))}function Ei(e){return Math.max(0,Math.min(255,Math.round(e)||0))}function Ci(e){return e=Ei(e),(e<16?"0":"")+e.toString(16)}function wb(e,t,r,n){return n<=0?e=t=r=NaN:r<=0||r>=1?e=t=NaN:t<=0&&(e=NaN),new Cn(e,t,r,n)}function Cb(e){if(e instanceof Cn)return new Cn(e.h,e.s,e.l,e.opacity);if(e instanceof Ja||(e=En(e)),!e)return new Cn;if(e instanceof Cn)return e;e=e.rgb();var t=e.r/255,r=e.g/255,n=e.b/255,o=Math.min(t,r,n),i=Math.max(t,r,n),s=NaN,a=i-o,l=(i+o)/2;return a?(t===i?s=(r-n)/a+(r0&&l<1?0:s,new Cn(s,a,l,e.opacity)}function Eb(e,t,r,n){return arguments.length===1?Cb(e):new Cn(e,t,r,n??1)}function Cn(e,t,r,n){this.h=+e,this.s=+t,this.l=+r,this.opacity=+n}function Ib(e){return e=(e||0)%360,e<0?e+360:e}function Dc(e){return Math.max(0,Math.min(1,e||0))}function Uf(e,t,r){return(e<60?t+(r-t)*e/60:e<180?r:e<240?t+(r-t)*(240-e)/60:t)*255}var Ya,Oc,Bs,Pa,Tn,M$,W$,H$,z$,Y$,P$,J$,mb,$b=v(()=>{gb();Ya=.7,Oc=1/Ya,Bs="\\s*([+-]?\\d+)\\s*",Pa="\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)\\s*",Tn="\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)%\\s*",M$=/^#([0-9a-f]{3,8})$/,W$=new RegExp(`^rgb\\(${Bs},${Bs},${Bs}\\)$`),H$=new RegExp(`^rgb\\(${Tn},${Tn},${Tn}\\)$`),z$=new RegExp(`^rgba\\(${Bs},${Bs},${Bs},${Pa}\\)$`),Y$=new RegExp(`^rgba\\(${Tn},${Tn},${Tn},${Pa}\\)$`),P$=new RegExp(`^hsl\\(${Pa},${Tn},${Tn}\\)$`),J$=new RegExp(`^hsla\\(${Pa},${Tn},${Tn},${Pa}\\)$`),mb={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};Tc(Ja,En,{copy(e){return Object.assign(new this.constructor,this,e)},displayable(){return this.rgb().displayable()},hex:vb,formatHex:vb,formatHex8:j$,formatHsl:K$,formatRgb:_b,toString:_b});Tc(Br,ks,Lf(Ja,{brighter(e){return e=e==null?Oc:Math.pow(Oc,e),new Br(this.r*e,this.g*e,this.b*e,this.opacity)},darker(e){return e=e==null?Ya:Math.pow(Ya,e),new Br(this.r*e,this.g*e,this.b*e,this.opacity)},rgb(){return this},clamp(){return new Br(Ei(this.r),Ei(this.g),Ei(this.b),Xc(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:xb,formatHex:xb,formatHex8:e1,formatRgb:yb,toString:yb}));Tc(Cn,Eb,Lf(Ja,{brighter(e){return e=e==null?Oc:Math.pow(Oc,e),new Cn(this.h,this.s,this.l*e,this.opacity)},darker(e){return e=e==null?Ya:Math.pow(Ya,e),new Cn(this.h,this.s,this.l*e,this.opacity)},rgb(){var e=this.h%360+(this.h<0)*360,t=isNaN(e)||isNaN(this.s)?0:this.s,r=this.l,n=r+(r<.5?r:1-r)*t,o=2*r-n;return new Br(Uf(e>=240?e-240:e+120,o,n),Uf(e,o,n),Uf(e<120?e+240:e-120,o,n),this.opacity)},clamp(){return new Cn(Ib(this.h),Dc(this.s),Dc(this.l),Xc(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(){let e=Xc(this.opacity);return`${e===1?"hsl(":"hsla("}${Ib(this.h)}, ${Dc(this.s)*100}%, ${Dc(this.l)*100}%${e===1?")":`, ${e})`}`}}))});var Mc=v(()=>{$b()});function Tf(e,t,r,n,o){var i=e*e,s=i*e;return((1-3*e+3*i-s)*t+(4-6*i+3*s)*r+(1+3*e+3*i-3*s)*n+s*o)/6}function Bb(e){var t=e.length-1;return function(r){var n=r<=0?r=0:r>=1?(r=1,t-1):Math.floor(r*t),o=e[n],i=e[n+1],s=n>0?e[n-1]:2*o-i,a=n{});function kb(e){var t=e.length;return function(r){var n=Math.floor(((r%=1)<0?++r:r)*t),o=e[(n+t-1)%t],i=e[n%t],s=e[(n+1)%t],a=e[(n+2)%t];return Tf((r-n/t)*t,o,i,s,a)}}var Sb=v(()=>{Vf()});var ja,Df=v(()=>{ja=e=>()=>e});function t1(e,t){return function(r){return e+r*t}}function r1(e,t,r){return e=Math.pow(e,r),t=Math.pow(t,r)-e,r=1/r,function(n){return Math.pow(e+n*t,r)}}function Ab(e){return(e=+e)==1?Wc:function(t,r){return r-t?r1(t,r,e):ja(isNaN(t)?r:t)}}function Wc(e,t){var r=t-e;return r?t1(e,r):ja(isNaN(e)?t:e)}var Nb=v(()=>{Df()});function Fb(e){return function(t){var r=t.length,n=new Array(r),o=new Array(r),i=new Array(r),s,a;for(s=0;s{Mc();Vf();Sb();Nb();$i=(function e(t){var r=Ab(t);function n(o,i){var s=r((o=ks(o)).r,(i=ks(i)).r),a=r(o.g,i.g),l=r(o.b,i.b),c=Wc(o.opacity,i.opacity);return function(f){return o.r=s(f),o.g=a(f),o.b=l(f),o.opacity=c(f),o+""}}return n.gamma=e,n})(1);n1=Fb(Bb),o1=Fb(kb)});function Gb(e,t){t||(t=[]);var r=e?Math.min(t.length,e.length):0,n=t.slice(),o;return function(i){for(o=0;o{});function Rb(e,t){var r=t?t.length:0,n=e?Math.min(r,e.length):0,o=new Array(n),i=new Array(r),s;for(s=0;s{Hc()});function Ub(e,t){var r=new Date;return e=+e,t=+t,function(n){return r.setTime(e*(1-n)+t*n),r}}var Tb=v(()=>{});function _r(e,t){return e=+e,t=+t,function(r){return e*(1-r)+t*r}}var Ka=v(()=>{});function Vb(e,t){var r={},n={},o;(e===null||typeof e!="object")&&(e={}),(t===null||typeof t!="object")&&(t={});for(o in t)o in e?r[o]=uo(e[o],t[o]):n[o]=t[o];return function(i){for(o in r)n[o]=r[o](i);return n}}var Db=v(()=>{Hc()});function i1(e){return function(){return e}}function s1(e){return function(t){return e(t)+""}}function qa(e,t){var r=Mf.lastIndex=Xf.lastIndex=0,n,o,i,s=-1,a=[],l=[];for(e=e+"",t=t+"";(n=Mf.exec(e))&&(o=Xf.exec(t));)(i=o.index)>r&&(i=t.slice(r,i),a[s]?a[s]+=i:a[++s]=i),(n=n[0])===(o=o[0])?a[s]?a[s]+=o:a[++s]=o:(a[++s]=null,l.push({i:s,x:_r(n,o)})),r=Xf.lastIndex;return r{Ka();Mf=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,Xf=new RegExp(Mf.source,"g")});function uo(e,t){var r=typeof t,n;return t==null||r==="boolean"?ja(t):(r==="number"?_r:r==="string"?(n=En(t))?(t=n,$i):qa:t instanceof En?$i:t instanceof Date?Ub:Zb(t)?Gb:Array.isArray(t)?Rb:typeof t.valueOf!="function"&&typeof t.toString!="function"||isNaN(t)?Vb:_r)(e,t)}var Hc=v(()=>{Mc();Of();Lb();Tb();Ka();Db();Wf();Df();Qb()});function Hf(e,t,r,n,o,i){var s,a,l;return(s=Math.sqrt(e*e+t*t))&&(e/=s,t/=s),(l=e*r+t*n)&&(r-=e*l,n-=t*l),(a=Math.sqrt(r*r+n*n))&&(r/=a,n/=a,l/=a),e*n{Ob=180/Math.PI,zc={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1}});function Mb(e){let t=new(typeof DOMMatrix=="function"?DOMMatrix:WebKitCSSMatrix)(e+"");return t.isIdentity?zc:Hf(t.a,t.b,t.c,t.d,t.e,t.f)}function Wb(e){return e==null?zc:(Yc||(Yc=document.createElementNS("http://www.w3.org/2000/svg","g")),Yc.setAttribute("transform",e),(e=Yc.transform.baseVal.consolidate())?(e=e.matrix,Hf(e.a,e.b,e.c,e.d,e.e,e.f)):zc)}var Yc,Hb=v(()=>{Xb()});function zb(e,t,r,n){function o(c){return c.length?c.pop()+" ":""}function i(c,f,p,u,h,g){if(c!==p||f!==u){var b=h.push("translate(",null,t,null,r);g.push({i:b-4,x:_r(c,p)},{i:b-2,x:_r(f,u)})}else(p||u)&&h.push("translate("+p+t+u+r)}function s(c,f,p,u){c!==f?(c-f>180?f+=360:f-c>180&&(c+=360),u.push({i:p.push(o(p)+"rotate(",null,n)-2,x:_r(c,f)})):f&&p.push(o(p)+"rotate("+f+n)}function a(c,f,p,u){c!==f?u.push({i:p.push(o(p)+"skewX(",null,n)-2,x:_r(c,f)}):f&&p.push(o(p)+"skewX("+f+n)}function l(c,f,p,u,h,g){if(c!==p||f!==u){var b=h.push(o(h)+"scale(",null,",",null,")");g.push({i:b-4,x:_r(c,p)},{i:b-2,x:_r(f,u)})}else(p!==1||u!==1)&&h.push(o(h)+"scale("+p+","+u+")")}return function(c,f){var p=[],u=[];return c=e(c),f=e(f),i(c.translateX,c.translateY,f.translateX,f.translateY,p,u),s(c.rotate,f.rotate,p,u),a(c.skewX,f.skewX,p,u),l(c.scaleX,c.scaleY,f.scaleX,f.scaleY,p,u),c=f=null,function(h){for(var g=-1,b=u.length,x;++g{Ka();Hb();zf=zb(Mb,"px, ","px)","deg)"),Yf=zb(Wb,", ",")",")")});function Pb(e){return((e=Math.exp(e))+1/e)/2}function l1(e){return((e=Math.exp(e))-1/e)/2}function c1(e){return((e=Math.exp(2*e))-1)/(e+1)}var a1,Bi,Jb=v(()=>{a1=1e-12;Bi=(function e(t,r,n){function o(i,s){var a=i[0],l=i[1],c=i[2],f=s[0],p=s[1],u=s[2],h=f-a,g=p-l,b=h*h+g*g,x,w;if(b{Hc();Ka();Wf();Yb();Jb();Of()});function il(){return ki||(qb(d1),ki=nl.now()+jc)}function d1(){ki=0}function ol(){this._call=this._time=this._next=null}function Kc(e,t,r){var n=new ol;return n.restart(e,t,r),n}function ex(){il(),++As;for(var e=Pc,t;e;)(t=ki-e._time)>=0&&e._call.call(void 0,t),e=e._next;--As}function jb(){ki=(Jc=nl.now())+jc,As=tl=0;try{ex()}finally{As=0,f1(),ki=0}}function u1(){var e=nl.now(),t=e-Jc;t>Kb&&(jc-=t,Jc=e)}function f1(){for(var e,t=Pc,r,n=1/0;t;)t._call?(n>t._time&&(n=t._time),e=t,t=t._next):(r=t._next,t._next=null,t=e?e._next=r:Pc=r);rl=e,Pf(n)}function Pf(e){if(!As){tl&&(tl=clearTimeout(tl));var t=e-ki;t>24?(e<1/0&&(tl=setTimeout(jb,e-nl.now()-jc)),el&&(el=clearInterval(el))):(el||(Jc=nl.now(),el=setInterval(u1,Kb)),As=1,qb(jb))}}var As,tl,el,Kb,Pc,rl,Jc,ki,jc,nl,qb,Jf=v(()=>{As=0,tl=0,el=0,Kb=1e3,Jc=0,ki=0,jc=0,nl=typeof performance=="object"&&performance.now?performance:Date,qb=typeof window=="object"&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):function(e){setTimeout(e,17)};ol.prototype=Kc.prototype={constructor:ol,restart:function(e,t,r){if(typeof e!="function")throw new TypeError("callback is not a function");r=(r==null?il():+r)+(t==null?0:+t),!this._next&&rl!==this&&(rl?rl._next=this:Pc=this,rl=this),this._call=e,this._time=r,Pf()},stop:function(){this._call&&(this._call=null,this._time=1/0,Pf())}}});function qc(e,t,r){var n=new ol;return t=t==null?0:+t,n.restart(o=>{n.stop(),e(o+t)},t,r),n}var tx=v(()=>{Jf()});var jf=v(()=>{Jf();tx()});function Uo(e,t,r,n,o,i){var s=e.__transition;if(!s)e.__transition={};else if(r in s)return;g1(e,r,{name:t,index:n,group:o,on:p1,tween:h1,time:i.time,delay:i.delay,duration:i.duration,ease:i.ease,timer:null,state:ox})}function al(e,t){var r=Zt(e,t);if(r.state>ox)throw new Error("too late; already scheduled");return r}function er(e,t){var r=Zt(e,t);if(r.state>ed)throw new Error("too late; already running");return r}function Zt(e,t){var r=e.__transition;if(!r||!(r=r[t]))throw new Error("transition not found");return r}function g1(e,t,r){var n=e.__transition,o;n[t]=r,r.timer=Kc(i,0,r.time);function i(c){r.state=rx,r.timer.restart(s,r.delay,r.time),r.delay<=c&&s(c-r.delay)}function s(c){var f,p,u,h;if(r.state!==rx)return l();for(f in n)if(h=n[f],h.name===r.name){if(h.state===ed)return qc(s);h.state===nx?(h.state=sl,h.timer.stop(),h.on.call("interrupt",e,e.__data__,h.index,h.group),delete n[f]):+f{Ac();jf();p1=yi("start","end","cancel","interrupt"),h1=[],ox=0,rx=1,td=2,ed=3,nx=4,rd=5,sl=6});function Si(e,t){var r=e.__transition,n,o,i=!0,s;if(r){t=t==null?null:t+"";for(s in r){if((n=r[s]).name!==t){i=!1;continue}o=n.state>td&&n.state{kr()});function ix(e){return this.each(function(){Si(this,e)})}var sx=v(()=>{Kf()});function m1(e,t){var r,n;return function(){var o=er(this,e),i=o.tween;if(i!==r){n=r=i;for(var s=0,a=n.length;s{kr()});function nd(e,t){var r;return(typeof t=="number"?_r:t instanceof En?$i:(r=En(t))?(t=r,$i):qa)(e,t)}var qf=v(()=>{Mc();Ss()});function _1(e){return function(){this.removeAttribute(e)}}function b1(e){return function(){this.removeAttributeNS(e.space,e.local)}}function x1(e,t,r){var n,o=r+"",i;return function(){var s=this.getAttribute(e);return s===o?null:s===n?i:i=t(n=s,r)}}function y1(e,t,r){var n,o=r+"",i;return function(){var s=this.getAttributeNS(e.space,e.local);return s===o?null:s===n?i:i=t(n=s,r)}}function w1(e,t,r){var n,o,i;return function(){var s,a=r(this),l;return a==null?void this.removeAttribute(e):(s=this.getAttribute(e),l=a+"",s===l?null:s===n&&l===o?i:(o=l,i=t(n=s,a)))}}function I1(e,t,r){var n,o,i;return function(){var s,a=r(this),l;return a==null?void this.removeAttributeNS(e.space,e.local):(s=this.getAttributeNS(e.space,e.local),l=a+"",s===l?null:s===n&&l===o?i:(o=l,i=t(n=s,a)))}}function lx(e,t){var r=lo(e),n=r==="transform"?Yf:nd;return this.attrTween(e,typeof t=="function"?(r.local?I1:w1)(r,n,Ns(this,"attr."+e,t)):t==null?(r.local?b1:_1)(r):(r.local?y1:x1)(r,n,t))}var cx=v(()=>{Ss();$r();ll();qf()});function C1(e,t){return function(r){this.setAttribute(e,t.call(this,r))}}function E1(e,t){return function(r){this.setAttributeNS(e.space,e.local,t.call(this,r))}}function $1(e,t){var r,n;function o(){var i=t.apply(this,arguments);return i!==n&&(r=(n=i)&&E1(e,i)),r}return o._value=t,o}function B1(e,t){var r,n;function o(){var i=t.apply(this,arguments);return i!==n&&(r=(n=i)&&C1(e,i)),r}return o._value=t,o}function dx(e,t){var r="attr."+e;if(arguments.length<2)return(r=this.tween(r))&&r._value;if(t==null)return this.tween(r,null);if(typeof t!="function")throw new Error;var n=lo(e);return this.tween(r,(n.local?$1:B1)(n,t))}var ux=v(()=>{$r()});function k1(e,t){return function(){al(this,e).delay=+t.apply(this,arguments)}}function S1(e,t){return t=+t,function(){al(this,e).delay=t}}function fx(e){var t=this._id;return arguments.length?this.each((typeof e=="function"?k1:S1)(t,e)):Zt(this.node(),t).delay}var px=v(()=>{kr()});function A1(e,t){return function(){er(this,e).duration=+t.apply(this,arguments)}}function N1(e,t){return t=+t,function(){er(this,e).duration=t}}function hx(e){var t=this._id;return arguments.length?this.each((typeof e=="function"?A1:N1)(t,e)):Zt(this.node(),t).duration}var gx=v(()=>{kr()});function F1(e,t){if(typeof t!="function")throw new Error;return function(){er(this,e).ease=t}}function mx(e){var t=this._id;return arguments.length?this.each(F1(t,e)):Zt(this.node(),t).ease}var vx=v(()=>{kr()});function G1(e,t){return function(){var r=t.apply(this,arguments);if(typeof r!="function")throw new Error;er(this,e).ease=r}}function _x(e){if(typeof e!="function")throw new Error;return this.each(G1(this._id,e))}var bx=v(()=>{kr()});function xx(e){typeof e!="function"&&(e=Da(e));for(var t=this._groups,r=t.length,n=new Array(r),o=0;o{$r();Ai()});function wx(e){if(e._id!==this._id)throw new Error;for(var t=this._groups,r=e._groups,n=t.length,o=r.length,i=Math.min(n,o),s=new Array(n),a=0;a{Ai()});function Z1(e){return(e+"").trim().split(/^|\s+/).every(function(t){var r=t.indexOf(".");return r>=0&&(t=t.slice(0,r)),!t||t==="start"})}function Q1(e,t,r){var n,o,i=Z1(t)?al:er;return function(){var s=i(this,e),a=s.on;a!==n&&(o=(n=a).copy()).on(t,r),s.on=o}}function Cx(e,t){var r=this._id;return arguments.length<2?Zt(this.node(),r).on.on(e):this.each(Q1(r,e,t))}var Ex=v(()=>{kr()});function R1(e){return function(){var t=this.parentNode;for(var r in this.__transition)if(+r!==e)return;t&&t.removeChild(this)}}function $x(){return this.on("end.remove",R1(this._id))}var Bx=v(()=>{});function kx(e){var t=this._name,r=this._id;typeof e!="function"&&(e=wi(e));for(var n=this._groups,o=n.length,i=new Array(o),s=0;s{$r();Ai();kr()});function Ax(e){var t=this._name,r=this._id;typeof e!="function"&&(e=Va(e));for(var n=this._groups,o=n.length,i=[],s=[],a=0;a{$r();Ai();kr()});function Fx(){return new L1(this._groups,this._parents)}var L1,Gx=v(()=>{$r();L1=co.prototype.constructor});function U1(e,t){var r,n,o;return function(){var i=Ro(this,e),s=(this.style.removeProperty(e),Ro(this,e));return i===s?null:i===r&&s===n?o:o=t(r=i,n=s)}}function Zx(e){return function(){this.style.removeProperty(e)}}function T1(e,t,r){var n,o=r+"",i;return function(){var s=Ro(this,e);return s===o?null:s===n?i:i=t(n=s,r)}}function V1(e,t,r){var n,o,i;return function(){var s=Ro(this,e),a=r(this),l=a+"";return a==null&&(l=a=(this.style.removeProperty(e),Ro(this,e))),s===l?null:s===n&&l===o?i:(o=l,i=t(n=s,a))}}function D1(e,t){var r,n,o,i="style."+t,s="end."+i,a;return function(){var l=er(this,e),c=l.on,f=l.value[i]==null?a||(a=Zx(t)):void 0;(c!==r||o!==f)&&(n=(r=c).copy()).on(s,o=f),l.on=n}}function Qx(e,t,r){var n=(e+="")=="transform"?zf:nd;return t==null?this.styleTween(e,U1(e,n)).on("end.style."+e,Zx(e)):typeof t=="function"?this.styleTween(e,V1(e,n,Ns(this,"style."+e,t))).each(D1(this._id,e)):this.styleTween(e,T1(e,n,t),r).on("end.style."+e,null)}var Rx=v(()=>{Ss();$r();kr();ll();qf()});function O1(e,t,r){return function(n){this.style.setProperty(e,t.call(this,n),r)}}function X1(e,t,r){var n,o;function i(){var s=t.apply(this,arguments);return s!==o&&(n=(o=s)&&O1(e,s,r)),n}return i._value=t,i}function Lx(e,t,r){var n="style."+(e+="");if(arguments.length<2)return(n=this.tween(n))&&n._value;if(t==null)return this.tween(n,null);if(typeof t!="function")throw new Error;return this.tween(n,X1(e,t,r??""))}var Ux=v(()=>{});function M1(e){return function(){this.textContent=e}}function W1(e){return function(){var t=e(this);this.textContent=t??""}}function Tx(e){return this.tween("text",typeof e=="function"?W1(Ns(this,"text",e)):M1(e==null?"":e+""))}var Vx=v(()=>{ll()});function H1(e){return function(t){this.textContent=e.call(this,t)}}function z1(e){var t,r;function n(){var o=e.apply(this,arguments);return o!==r&&(t=(r=o)&&H1(o)),t}return n._value=e,n}function Dx(e){var t="text";if(arguments.length<1)return(t=this.tween(t))&&t._value;if(e==null)return this.tween(t,null);if(typeof e!="function")throw new Error;return this.tween(t,z1(e))}var Ox=v(()=>{});function Xx(){for(var e=this._name,t=this._id,r=od(),n=this._groups,o=n.length,i=0;i{Ai();kr()});function Wx(){var e,t,r=this,n=r._id,o=r.size();return new Promise(function(i,s){var a={value:s},l={value:function(){--o===0&&i()}};r.each(function(){var c=er(this,n),f=c.on;f!==e&&(t=(e=f).copy(),t._.cancel.push(a),t._.interrupt.push(a),t._.end.push(l)),c.on=t}),o===0&&i()})}var Hx=v(()=>{kr()});function br(e,t,r,n){this._groups=e,this._parents=t,this._name=r,this._id=n}function zx(e){return co().transition(e)}function od(){return++Y1}var Y1,fo,Ai=v(()=>{$r();cx();ux();px();gx();vx();bx();yx();Ix();Ex();Bx();Sx();Nx();Gx();Rx();Ux();Vx();Ox();Mx();ll();Hx();Y1=0;fo=co.prototype;br.prototype=zx.prototype={constructor:br,select:kx,selectAll:Ax,selectChild:fo.selectChild,selectChildren:fo.selectChildren,filter:xx,merge:wx,selection:Fx,transition:Xx,call:fo.call,nodes:fo.nodes,node:fo.node,size:fo.size,empty:fo.empty,each:fo.each,on:Cx,attr:lx,attrTween:dx,style:Qx,styleTween:Lx,text:Tx,textTween:Dx,remove:$x,tween:ax,delay:fx,duration:hx,ease:mx,easeVarying:_x,end:Wx,[Symbol.iterator]:fo[Symbol.iterator]}});function id(e){return((e*=2)<=1?e*e*e:(e-=2)*e*e+2)/2}var Yx=v(()=>{});var Px=v(()=>{Yx()});function J1(e,t){for(var r;!(r=e.__transition)||!(r=r[t]);)if(!(e=e.parentNode))throw new Error(`transition ${t} not found`);return r}function Jx(e){var t,r;e instanceof br?(t=e._id,e=e._name):(t=od(),(r=P1).time=il(),e=e==null?null:e+"");for(var n=this._groups,o=n.length,i=0;i{Ai();kr();Px();jf();P1={time:null,delay:0,duration:250,ease:id}});var Kx=v(()=>{$r();sx();jx();co.prototype.interrupt=ix;co.prototype.transition=Jx});var qx=v(()=>{Kx();Kf()});var cl,ey=v(()=>{cl=e=>()=>e});function ep(e,{sourceEvent:t,target:r,transform:n,dispatch:o}){Object.defineProperties(this,{type:{value:e,enumerable:!0,configurable:!0},sourceEvent:{value:t,enumerable:!0,configurable:!0},target:{value:r,enumerable:!0,configurable:!0},transform:{value:n,enumerable:!0,configurable:!0},_:{value:o}})}var ty=v(()=>{});function $n(e,t,r){this.k=e,this.x=t,this.y=r}function dl(e){for(;!e.__zoom;)if(!(e=e.parentNode))return Ni;return e.__zoom}var Ni,tp=v(()=>{$n.prototype={constructor:$n,scale:function(e){return e===1?this:new $n(this.k*e,this.x,this.y)},translate:function(e,t){return e===0&t===0?this:new $n(this.k,this.x+this.k*e,this.y+this.k*t)},apply:function(e){return[e[0]*this.k+this.x,e[1]*this.k+this.y]},applyX:function(e){return e*this.k+this.x},applyY:function(e){return e*this.k+this.y},invert:function(e){return[(e[0]-this.x)/this.k,(e[1]-this.y)/this.k]},invertX:function(e){return(e-this.x)/this.k},invertY:function(e){return(e-this.y)/this.k},rescaleX:function(e){return e.copy().domain(e.range().map(this.invertX,this).map(e.invert,e))},rescaleY:function(e){return e.copy().domain(e.range().map(this.invertY,this).map(e.invert,e))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};Ni=new $n(1,0,0);dl.prototype=$n.prototype});function sd(e){e.stopImmediatePropagation()}function Fs(e){e.preventDefault(),e.stopImmediatePropagation()}var ry=v(()=>{});function j1(e){return(!e.ctrlKey||e.type==="wheel")&&!e.button}function K1(){var e=this;return e instanceof SVGElement?(e=e.ownerSVGElement||e,e.hasAttribute("viewBox")?(e=e.viewBox.baseVal,[[e.x,e.y],[e.x+e.width,e.y+e.height]]):[[0,0],[e.width.baseVal.value,e.height.baseVal.value]]):[[0,0],[e.clientWidth,e.clientHeight]]}function ny(){return this.__zoom||Ni}function q1(e){return-e.deltaY*(e.deltaMode===1?.05:e.deltaMode?1:.002)*(e.ctrlKey?10:1)}function eB(){return navigator.maxTouchPoints||"ontouchstart"in this}function tB(e,t,r){var n=e.invertX(t[0][0])-r[0][0],o=e.invertX(t[1][0])-r[1][0],i=e.invertY(t[0][1])-r[0][1],s=e.invertY(t[1][1])-r[1][1];return e.translate(o>n?(n+o)/2:Math.min(0,n)||Math.max(0,o),s>i?(i+s)/2:Math.min(0,i)||Math.max(0,s))}function ad(){var e=j1,t=K1,r=tB,n=q1,o=eB,i=[0,1/0],s=[[-1/0,-1/0],[1/0,1/0]],a=250,l=Bi,c=yi("start","zoom","end"),f,p,u,h=500,g=150,b=0,x=10;function w(y){y.property("__zoom",ny).on("wheel.zoom",R,{passive:!1}).on("mousedown.zoom",O).on("dblclick.zoom",H).filter(o).on("touchstart.zoom",F).on("touchmove.zoom",$).on("touchend.zoom touchcancel.zoom",Q).style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}w.transform=function(y,S,k,D){var J=y.selection?y.selection():y;J.property("__zoom",ny),y!==J?T(y,S,k,D):J.interrupt().each(function(){B(this,arguments).event(D).start().zoom(null,typeof S=="function"?S.apply(this,arguments):S).end()})},w.scaleBy=function(y,S,k,D){w.scaleTo(y,function(){var J=this.__zoom.k,W=typeof S=="function"?S.apply(this,arguments):S;return J*W},k,D)},w.scaleTo=function(y,S,k,D){w.transform(y,function(){var J=t.apply(this,arguments),W=this.__zoom,j=k==null?I(J):typeof k=="function"?k.apply(this,arguments):k,ee=W.invert(j),se=typeof S=="function"?S.apply(this,arguments):S;return r(E(C(W,se),j,ee),J,s)},k,D)},w.translateBy=function(y,S,k,D){w.transform(y,function(){return r(this.__zoom.translate(typeof S=="function"?S.apply(this,arguments):S,typeof k=="function"?k.apply(this,arguments):k),t.apply(this,arguments),s)},null,D)},w.translateTo=function(y,S,k,D,J){w.transform(y,function(){var W=t.apply(this,arguments),j=this.__zoom,ee=D==null?I(W):typeof D=="function"?D.apply(this,arguments):D;return r(Ni.translate(ee[0],ee[1]).scale(j.k).translate(typeof S=="function"?-S.apply(this,arguments):-S,typeof k=="function"?-k.apply(this,arguments):-k),W,s)},D,J)};function C(y,S){return S=Math.max(i[0],Math.min(i[1],S)),S===y.k?y:new $n(S,y.x,y.y)}function E(y,S,k){var D=S[0]-k[0]*y.k,J=S[1]-k[1]*y.k;return D===y.x&&J===y.y?y:new $n(y.k,D,J)}function I(y){return[(+y[0][0]+ +y[1][0])/2,(+y[0][1]+ +y[1][1])/2]}function T(y,S,k,D){y.on("start.zoom",function(){B(this,arguments).event(D).start()}).on("interrupt.zoom end.zoom",function(){B(this,arguments).event(D).end()}).tween("zoom",function(){var J=this,W=arguments,j=B(J,W).event(D),ee=t.apply(J,W),se=k==null?I(ee):typeof k=="function"?k.apply(J,W):k,de=Math.max(ee[1][0]-ee[0][0],ee[1][1]-ee[0][1]),M=J.__zoom,ce=typeof S=="function"?S.apply(J,W):S,ne=l(M.invert(se).concat(de/M.k),ce.invert(se).concat(de/ce.k));return function(ie){if(ie===1)ie=ce;else{var pe=ne(ie),ke=de/pe[2];ie=new $n(ke,se[0]-pe[0]*ke,se[1]-pe[1]*ke)}j.zoom(null,ie)}})}function B(y,S,k){return!k&&y.__zooming||new Z(y,S)}function Z(y,S){this.that=y,this.args=S,this.active=0,this.sourceEvent=null,this.extent=t.apply(y,S),this.taps=0}Z.prototype={event:function(y){return y&&(this.sourceEvent=y),this},start:function(){return++this.active===1&&(this.that.__zooming=this,this.emit("start")),this},zoom:function(y,S){return this.mouse&&y!=="mouse"&&(this.mouse[1]=S.invert(this.mouse[0])),this.touch0&&y!=="touch"&&(this.touch0[1]=S.invert(this.touch0[0])),this.touch1&&y!=="touch"&&(this.touch1[1]=S.invert(this.touch1[0])),this.that.__zoom=S,this.emit("zoom"),this},end:function(){return--this.active===0&&(delete this.that.__zooming,this.emit("end")),this},emit:function(y){var S=qt(this.that).datum();c.call(y,this.that,new ep(y,{sourceEvent:this.sourceEvent,target:w,type:y,transform:this.that.__zoom,dispatch:c}),S)}};function R(y,...S){if(!e.apply(this,arguments))return;var k=B(this,S).event(y),D=this.__zoom,J=Math.max(i[0],Math.min(i[1],D.k*Math.pow(2,n.apply(this,arguments)))),W=vr(y);if(k.wheel)(k.mouse[0][0]!==W[0]||k.mouse[0][1]!==W[1])&&(k.mouse[1]=D.invert(k.mouse[0]=W)),clearTimeout(k.wheel);else{if(D.k===J)return;k.mouse=[W,D.invert(W)],Si(this),k.start()}Fs(y),k.wheel=setTimeout(j,g),k.zoom("mouse",r(E(C(D,J),k.mouse[0],k.mouse[1]),k.extent,s));function j(){k.wheel=null,k.end()}}function O(y,...S){if(u||!e.apply(this,arguments))return;var k=y.currentTarget,D=B(this,S,!0).event(y),J=qt(y.view).on("mousemove.zoom",se,!0).on("mouseup.zoom",de,!0),W=vr(y,k),j=y.clientX,ee=y.clientY;Ma(y.view),sd(y),D.mouse=[W,this.__zoom.invert(W)],Si(this),D.start();function se(M){if(Fs(M),!D.moved){var ce=M.clientX-j,ne=M.clientY-ee;D.moved=ce*ce+ne*ne>b}D.event(M).zoom("mouse",r(E(D.that.__zoom,D.mouse[0]=vr(M,k),D.mouse[1]),D.extent,s))}function de(M){J.on("mousemove.zoom mouseup.zoom",null),Wa(M.view,D.moved),Fs(M),D.event(M).end()}}function H(y,...S){if(e.apply(this,arguments)){var k=this.__zoom,D=vr(y.changedTouches?y.changedTouches[0]:y,this),J=k.invert(D),W=k.k*(y.shiftKey?.5:2),j=r(E(C(k,W),D,J),t.apply(this,S),s);Fs(y),a>0?qt(this).transition().duration(a).call(T,j,D,y):qt(this).call(w.transform,j,D,y)}}function F(y,...S){if(e.apply(this,arguments)){var k=y.touches,D=k.length,J=B(this,S,y.changedTouches.length===D).event(y),W,j,ee,se;for(sd(y),j=0;j{Ac();Rf();Ss();$r();qx();ey();ty();tp();ry()});var iy=v(()=>{oy();tp()});function _y(e,t){if(!e&&!t)return!0;if(!e||!t||e.size!==t.size)return!1;if(!e.size&&!t.size)return!0;for(let r of e.keys())if(!t.has(r))return!1;return!0}function ap(e,t,r){if(!r)return;let n=[];e.forEach((o,i)=>{t?.has(i)||n.push(o)}),n.length&&r(n)}function by(e){return e===null?null:e?"valid":"invalid"}function oB(e,t){let r=new Map,n=t?.nodes?new Set(t.nodes.map(o=>o.id)):null;return e.forEach(o=>{o.measured.width&&o.measured.height&&(t?.includeHiddenNodes||!o.hidden)&&(!n||n.has(o.id))&&r.set(o.id,o)}),r}async function wy({nodes:e,width:t,height:r,panZoom:n,minZoom:o,maxZoom:i},s){if(e.size===0)return Promise.resolve(!0);let a=oB(e,s),l=Do(a),c=gl(l,t,r,s?.minZoom??o,s?.maxZoom??i,s?.padding??.1);return await n.setViewport(c,{duration:s?.duration,ease:s?.ease,interpolate:s?.interpolate}),Promise.resolve(!0)}function dp({nodeId:e,nextPosition:t,nodeLookup:r,nodeOrigin:n=[0,0],nodeExtent:o,onError:i}){let s=r.get(e),a=s.parentId?r.get(s.parentId):void 0,{x:l,y:c}=a?a.internals.positionAbsolute:{x:0,y:0},f=s.origin??n,p=s.extent||o;if(s.extent==="parent"&&!s.expandParent)if(!a)i?.("005",Gi.error005());else{let h=a.measured.width,g=a.measured.height;h&&g&&(p=[[l,c],[l+h,c+g]])}else a&&Ls(s.extent)&&(p=[[s.extent[0][0]+l,s.extent[0][1]+c],[s.extent[1][0]+l,s.extent[1][1]+c]]);let u=Ls(p)?Zi(t,p,s.measured):t;return(s.measured.width===void 0||s.measured.height===void 0)&&i?.("015",Gi.error015()),{position:{x:u.x-l+(s.measured.width??0)*f[0],y:u.y-c+(s.measured.height??0)*f[1]},positionAbsolute:u}}async function Iy({nodesToRemove:e=[],edgesToRemove:t=[],nodes:r,edges:n,onBeforeDelete:o}){let i=new Set(e.map(u=>u.id)),s=[];for(let u of r){if(u.deletable===!1)continue;let h=i.has(u.id),g=!h&&u.parentId&&s.find(b=>b.id===u.parentId);(h||g)&&s.push(u)}let a=new Set(t.map(u=>u.id)),l=n.filter(u=>u.deletable!==!1),f=nB(s,l);for(let u of l)a.has(u.id)&&!f.find(g=>g.id===u.id)&&f.push(u);if(!o)return{edges:f,nodes:s};let p=await o({nodes:s,edges:f});return typeof p=="boolean"?p?{edges:f,nodes:s}:{edges:[],nodes:[]}:p}function Cy(e,t,r){let{width:n,height:o}=po(r),{x:i,y:s}=r.internals.positionAbsolute;return Zi(e,[[i,s],[i+n,s+o]],t)}function Gs(e,t){if(typeof e=="number")return Math.floor((t-t/(1+e))*.5);if(typeof e=="string"&&e.endsWith("px")){let r=parseFloat(e);if(!Number.isNaN(r))return Math.floor(r)}if(typeof e=="string"&&e.endsWith("%")){let r=parseFloat(e);if(!Number.isNaN(r))return Math.floor(t*r*.01)}return console.error(`[React Flow] The padding value "${e}" is invalid. Please provide a number or a string with a valid unit (px or %).`),0}function iB(e,t,r){if(typeof e=="string"||typeof e=="number"){let n=Gs(e,r),o=Gs(e,t);return{top:n,right:o,bottom:n,left:o,x:o*2,y:n*2}}if(typeof e=="object"){let n=Gs(e.top??e.y??0,r),o=Gs(e.bottom??e.y??0,r),i=Gs(e.left??e.x??0,t),s=Gs(e.right??e.x??0,t);return{top:n,right:s,bottom:o,left:i,x:i+s,y:n+o}}return{top:0,right:0,bottom:0,left:0,x:0,y:0}}function sB(e,t,r,n,o,i){let{x:s,y:a}=fl(e,[t,r,n]),{x:l,y:c}=fl({x:e.x+e.width,y:e.y+e.height},[t,r,n]),f=o-l,p=i-c;return{left:Math.floor(s),top:Math.floor(a),right:Math.floor(f),bottom:Math.floor(p)}}function Ls(e){return e!=null&&e!=="parent"}function po(e){return{width:e.measured?.width??e.width??e.initialWidth??0,height:e.measured?.height??e.height??e.initialHeight??0}}function hd(e){return(e.measured?.width??e.width??e.initialWidth)!==void 0&&(e.measured?.height??e.height??e.initialHeight)!==void 0}function $y(e,t={width:0,height:0},r,n,o){let i={...e},s=n.get(r);if(s){let a=s.origin||o;i.x+=s.internals.positionAbsolute.x-(t.width??0)*a[0],i.y+=s.internals.positionAbsolute.y-(t.height??0)*a[1]}return i}function By(e){return{...rB,...e||{}}}function rp(e,{snapGrid:t=[0,0],snapToGrid:r=!1,transform:n,containerBounds:o}){let{x:i,y:s}=sn(e),a=Ri({x:i-(o?.left??0),y:s-(o?.top??0)},n),{x:l,y:c}=r?Vs(a,t):a;return{xSnapped:l,ySnapped:c,...a}}function gd(e){let t=e.composedPath?.()?.[0]||e.target;return t?.nodeType!==1?!1:aB.includes(t.nodeName)||t.hasAttribute("contenteditable")||!!t.closest(".nokey")}function lB({sourceX:e,sourceY:t,targetX:r,targetY:n,sourceControlX:o,sourceControlY:i,targetControlX:s,targetControlY:a}){let l=e*.125+o*.375+s*.375+r*.125,c=t*.125+i*.375+a*.375+n*.125,f=Math.abs(l-e),p=Math.abs(c-t);return[l,c,f,p]}function ld(e,t){return e>=0?.5*e:t*25*Math.sqrt(-e)}function cy({pos:e,x1:t,y1:r,x2:n,y2:o,c:i}){switch(e){case $e.Left:return[t-ld(t-n,i),r];case $e.Right:return[t+ld(n-t,i),r];case $e.Top:return[t,r-ld(r-o,i)];case $e.Bottom:return[t,r+ld(o-r,i)]}}function md({sourceX:e,sourceY:t,sourcePosition:r=$e.Bottom,targetX:n,targetY:o,targetPosition:i=$e.Top,curvature:s=.25}){let[a,l]=cy({pos:r,x1:e,y1:t,x2:n,y2:o,c:s}),[c,f]=cy({pos:i,x1:n,y1:o,x2:e,y2:t,c:s}),[p,u,h,g]=lB({sourceX:e,sourceY:t,targetX:n,targetY:o,sourceControlX:a,sourceControlY:l,targetControlX:c,targetControlY:f});return[`M${e},${t} C${a},${l} ${c},${f} ${n},${o}`,p,u,h,g]}function Sy({sourceX:e,sourceY:t,targetX:r,targetY:n}){let o=Math.abs(r-e)/2,i=r0}function vd({sourceX:e,sourceY:t,targetX:r,targetY:n}){let[o,i,s,a]=Sy({sourceX:e,sourceY:t,targetX:r,targetY:n});return[`M ${e},${t}L ${r},${n}`,o,i,s,a]}function fB({source:e,sourcePosition:t=$e.Bottom,target:r,targetPosition:n=$e.Top,center:o,offset:i,stepPosition:s}){let a=dy[t],l=dy[n],c={x:e.x+a.x*i,y:e.y+a.y*i},f={x:r.x+l.x*i,y:r.y+l.y*i},p=uB({source:c,sourcePosition:t,target:f}),u=p.x!==0?"x":"y",h=p[u],g=[],b,x,w={x:0,y:0},C={x:0,y:0},[,,E,I]=Sy({sourceX:e.x,sourceY:e.y,targetX:r.x,targetY:r.y});if(a[u]*l[u]===-1){u==="x"?(b=o.x??c.x+(f.x-c.x)*s,x=o.y??(c.y+f.y)/2):(b=o.x??(c.x+f.x)/2,x=o.y??c.y+(f.y-c.y)*s);let R=[{x:b,y:c.y},{x:b,y:f.y}],O=[{x:c.x,y:x},{x:f.x,y:x}];a[u]===h?g=u==="x"?R:O:g=u==="x"?O:R}else{let R=[{x:c.x,y:f.y}],O=[{x:f.x,y:c.y}];if(u==="x"?g=a.x===h?O:R:g=a.y===h?R:O,t===n){let y=Math.abs(e[u]-r[u]);if(y<=i){let S=Math.min(i-1,i-y);a[u]===h?w[u]=(c[u]>e[u]?-1:1)*S:C[u]=(f[u]>r[u]?-1:1)*S}}if(t!==n){let y=u==="x"?"y":"x",S=a[u]===l[y],k=c[y]>f[y],D=c[y]=Q?(b=(H.x+F.x)/2,x=g[0].y):(b=g[0].x,x=(H.y+F.y)/2)}let T={x:c.x+w.x,y:c.y+w.y},B={x:f.x+C.x,y:f.y+C.y};return[[e,...T.x!==g[0].x||T.y!==g[0].y?[T]:[],...g,...B.x!==g[g.length-1].x||B.y!==g[g.length-1].y?[B]:[],r],b,x,E,I]}function pB(e,t,r,n){let o=Math.min(uy(e,t)/2,uy(t,r)/2,n),{x:i,y:s}=t;if(e.x===i&&i===r.x||e.y===s&&s===r.y)return`L${i} ${s}`;if(e.y===s){let c=e.xr.id===t):e[0])||null}function _d(e,t){return e?typeof e=="string"?e:`${t?`${t}__`:""}${Object.keys(e).sort().map(n=>`${n}=${e[n]}`).join("&")}`:""}function Zy(e,{id:t,defaultColor:r,defaultMarkerStart:n,defaultMarkerEnd:o}){let i=new Set;return e.reduce((s,a)=>([a.markerStart||n,a.markerEnd||o].forEach(l=>{if(l&&typeof l=="object"){let c=_d(l,t);i.has(c)||(s.push({id:c,color:l.color||r,...l}),i.add(c))}}),s),[]).sort((s,a)=>s.id.localeCompare(a.id))}function vp(e,t){let r={...e};for(let n in t)t[n]!==void 0&&(r[n]=t[n]);return r}function Ry(e,t,r){let n=vp(mp,r);for(let o of e.values())if(o.parentId)bp(o,e,t,n);else{let i=hl(o,n.nodeOrigin),s=Ls(o.extent)?o.extent:n.nodeExtent,a=Zi(i,s,po(o));o.internals.positionAbsolute=a}}function mB(e,t){if(!e.handles)return e.measured?t?.internals.handleBounds:void 0;let r=[],n=[];for(let o of e.handles){let i={id:o.id,width:o.width??1,height:o.height??1,nodeId:e.id,x:o.x,y:o.y,position:o.position,type:o.type};o.type==="source"?r.push(i):o.type==="target"&&n.push(i)}return{source:r,target:n}}function _p(e){return e==="manual"}function Ly(e,t,r,n={}){let o=vp(gB,n),i={i:0},s=new Map(t),a=o?.elevateNodesOnSelect&&!_p(o.zIndexMode)?Qy:0,l=e.length>0,c=!1;t.clear(),r.clear();for(let f of e){let p=s.get(f.id);if(o.checkEquality&&f===p?.internals.userNode)t.set(f.id,p);else{let u=hl(f,o.nodeOrigin),h=Ls(f.extent)?f.extent:o.nodeExtent,g=Zi(u,h,po(f));p={...o.defaults,...f,measured:{width:f.measured?.width,height:f.measured?.height},internals:{positionAbsolute:g,handleBounds:mB(f,p),z:Uy(f,a,o.zIndexMode),userNode:f}},t.set(f.id,p)}(p.measured===void 0||p.measured.width===void 0||p.measured.height===void 0)&&!p.hidden&&(l=!1),f.parentId&&bp(p,t,r,n,i),c||(c=f.selected??!1)}return{nodesInitialized:l,hasSelectedNodes:c}}function vB(e,t){if(!e.parentId)return;let r=t.get(e.parentId);r?r.set(e.id,e):t.set(e.parentId,new Map([[e.id,e]]))}function bp(e,t,r,n,o){let{elevateNodesOnSelect:i,nodeOrigin:s,nodeExtent:a,zIndexMode:l}=vp(mp,n),c=e.parentId,f=t.get(c);if(!f){console.warn(`Parent node ${c} not found. Please make sure that parent nodes are in front of their child nodes in the nodes array.`);return}vB(e,r),o&&!f.parentId&&f.internals.rootParentIndex===void 0&&l==="auto"&&(f.internals.rootParentIndex=++o.i,f.internals.z=f.internals.z+o.i*hB),o&&f.internals.rootParentIndex!==void 0&&(o.i=f.internals.rootParentIndex);let p=i&&!_p(l)?Qy:0,{x:u,y:h,z:g}=_B(e,f,s,a,p,l),{positionAbsolute:b}=e.internals,x=u!==b.x||h!==b.y;(x||g!==e.internals.z)&&t.set(e.id,{...e,internals:{...e.internals,positionAbsolute:x?{x:u,y:h}:b,z:g}})}function Uy(e,t,r){let n=Vn(e.zIndex)?e.zIndex:0;return _p(r)?n:n+(e.selected?t:0)}function _B(e,t,r,n,o,i){let{x:s,y:a}=t.internals.positionAbsolute,l=po(e),c=hl(e,r),f=Ls(e.extent)?Zi(c,e.extent,l):c,p=Zi({x:s+f.x,y:a+f.y},n,l);e.extent==="parent"&&(p=Cy(p,l,t));let u=Uy(e,o,i),h=t.internals.z??0;return{x:p.x,y:p.y,z:h>=u?h+1:u}}function bB(e,t,r,n=[0,0]){let o=[],i=new Map;for(let s of e){let a=t.get(s.parentId);if(!a)continue;let l=i.get(s.parentId)?.expandedRect??Qi(a),c=up(l,s.rect);i.set(s.parentId,{expandedRect:c,parent:a})}return i.size>0&&i.forEach(({expandedRect:s,parent:a},l)=>{let c=a.internals.positionAbsolute,f=po(a),p=a.origin??n,u=s.x0||h>0||x||w)&&(o.push({id:l,type:"position",position:{x:a.position.x-u+x,y:a.position.y-h+w}}),r.get(l)?.forEach(C=>{e.some(E=>E.id===C.id)||o.push({id:C.id,type:"position",position:{x:C.position.x+u,y:C.position.y+h}})})),(f.width0){let h=bB(u,t,r,o);c.push(...h)}return{changes:c,updatedInternals:l}}async function Vy({delta:e,panZoom:t,transform:r,translateExtent:n,width:o,height:i}){if(!t||!e.x&&!e.y)return Promise.resolve(!1);let s=await t.setViewportConstrained({x:r[0]+e.x,y:r[1]+e.y,zoom:r[2]},[[0,0],[o,i]],n),a=!!s&&(s.x!==r[0]||s.y!==r[1]||s.k!==r[2]);return Promise.resolve(a)}function gy(e,t,r,n,o,i){let s=o,a=n.get(s)||new Map;n.set(s,a.set(r,t)),s=`${o}-${e}`;let l=n.get(s)||new Map;if(n.set(s,l.set(r,t)),i){s=`${o}-${e}-${i}`;let c=n.get(s)||new Map;n.set(s,c.set(r,t))}}function Dy(e,t,r){e.clear(),t.clear();for(let n of r){let{source:o,target:i,sourceHandle:s=null,targetHandle:a=null}=n,l={edgeId:n.id,source:o,target:i,sourceHandle:s,targetHandle:a},c=`${o}-${s}--${i}-${a}`,f=`${i}-${a}--${o}-${s}`;gy("source",l,f,e,o,s),gy("target",l,c,e,i,a),t.set(n.id,n)}}function Oy(e,t){if(!e.parentId)return!1;let r=t.get(e.parentId);return r?r.selected?!0:Oy(r,t):!1}function my(e,t,r){let n=e;do{if(n?.matches?.(t))return!0;if(n===r)return!1;n=n?.parentElement}while(n);return!1}function xB(e,t,r,n){let o=new Map;for(let[i,s]of e)if((s.selected||s.id===n)&&(!s.parentId||!Oy(s,e))&&(s.draggable||t&&typeof s.draggable>"u")){let a=e.get(i);a&&o.set(i,{id:i,position:a.position||{x:0,y:0},distance:{x:r.x-a.internals.positionAbsolute.x,y:r.y-a.internals.positionAbsolute.y},extent:a.extent,parentId:a.parentId,origin:a.origin,expandParent:a.expandParent,internals:{positionAbsolute:a.internals.positionAbsolute||{x:0,y:0}},measured:{width:a.measured.width??0,height:a.measured.height??0}})}return o}function np({nodeId:e,dragItems:t,nodeLookup:r,dragging:n=!0}){let o=[];for(let[s,a]of t){let l=r.get(s)?.internals.userNode;l&&o.push({...l,position:a.position,dragging:n})}if(!e)return[o[0],o];let i=r.get(e)?.internals.userNode;return[i?{...i,position:t.get(e)?.position||i.position,dragging:n}:o[0],o]}function yB({dragItems:e,snapGrid:t,x:r,y:n}){let o=e.values().next().value;if(!o)return null;let i={x:r-o.distance.x,y:n-o.distance.y},s=Vs(i,t);return{x:s.x-i.x,y:s.y-i.y}}function Xy({onNodeMouseDown:e,getStoreItems:t,onDragStart:r,onDrag:n,onDragStop:o}){let i={x:null,y:null},s=0,a=new Map,l=!1,c={x:0,y:0},f=null,p=!1,u=null,h=!1,g=!1,b=null;function x({noDragClassName:C,handleSelector:E,domNode:I,isSelectable:T,nodeId:B,nodeClickDistance:Z=0}){u=qt(I);function R({x:$,y:Q}){let{nodeLookup:y,nodeExtent:S,snapGrid:k,snapToGrid:D,nodeOrigin:J,onNodeDrag:W,onSelectionDrag:j,onError:ee,updateNodePositions:se}=t();i={x:$,y:Q};let de=!1,M=a.size>1,ce=M&&S?sp(Do(a)):null,ne=M&&D?yB({dragItems:a,snapGrid:k,x:$,y:Q}):null;for(let[ie,pe]of a){if(!y.has(ie))continue;let ke={x:$-pe.distance.x,y:Q-pe.distance.y};D&&(ke=ne?{x:Math.round(ke.x+ne.x),y:Math.round(ke.y+ne.y)}:Vs(ke,k));let Qe=null;if(M&&S&&!pe.extent&&ce){let{positionAbsolute:Re}=pe.internals,ut=Re.x-ce.x+S[0][0],Je=Re.x+pe.measured.width-ce.x2+S[1][0],et=Re.y-ce.y+S[0][1],xt=Re.y+pe.measured.height-ce.y2+S[1][1];Qe=[[ut,et],[Je,xt]]}let{position:Se,positionAbsolute:ot}=dp({nodeId:ie,nextPosition:ke,nodeLookup:y,nodeExtent:Qe||S,nodeOrigin:J,onError:ee});de=de||pe.position.x!==Se.x||pe.position.y!==Se.y,pe.position=Se,pe.internals.positionAbsolute=ot}if(g=g||de,!!de&&(se(a,!0),b&&(n||W||!B&&j))){let[ie,pe]=np({nodeId:B,dragItems:a,nodeLookup:y});n?.(b,a,ie,pe),W?.(b,ie,pe),B||j?.(b,pe)}}async function O(){if(!f)return;let{transform:$,panBy:Q,autoPanSpeed:y,autoPanOnNodeDrag:S}=t();if(!S){l=!1,cancelAnimationFrame(s);return}let[k,D]=Ey(c,f,y);(k!==0||D!==0)&&(i.x=(i.x??0)-k/$[2],i.y=(i.y??0)-D/$[2],await Q({x:k,y:D})&&R(i)),s=requestAnimationFrame(O)}function H($){let{nodeLookup:Q,multiSelectionActive:y,nodesDraggable:S,transform:k,snapGrid:D,snapToGrid:J,selectNodesOnDrag:W,onNodeDragStart:j,onSelectionDragStart:ee,unselectNodesAndEdges:se}=t();p=!0,(!W||!T)&&!y&&B&&(Q.get(B)?.selected||se()),T&&W&&B&&e?.(B);let de=rp($.sourceEvent,{transform:k,snapGrid:D,snapToGrid:J,containerBounds:f});if(i=de,a=xB(Q,S,de,B),a.size>0&&(r||j||!B&&ee)){let[M,ce]=np({nodeId:B,dragItems:a,nodeLookup:Q});r?.($.sourceEvent,a,M,ce),j?.($.sourceEvent,M,ce),B||ee?.($.sourceEvent,ce)}}let F=Qf().clickDistance(Z).on("start",$=>{let{domNode:Q,nodeDragThreshold:y,transform:S,snapGrid:k,snapToGrid:D}=t();f=Q?.getBoundingClientRect()||null,h=!1,g=!1,b=$.sourceEvent,y===0&&H($),i=rp($.sourceEvent,{transform:S,snapGrid:k,snapToGrid:D,containerBounds:f}),c=sn($.sourceEvent,f)}).on("drag",$=>{let{autoPanOnNodeDrag:Q,transform:y,snapGrid:S,snapToGrid:k,nodeDragThreshold:D,nodeLookup:J}=t(),W=rp($.sourceEvent,{transform:y,snapGrid:S,snapToGrid:k,containerBounds:f});if(b=$.sourceEvent,($.sourceEvent.type==="touchmove"&&$.sourceEvent.touches.length>1||B&&!J.has(B))&&(h=!0),!h){if(!l&&Q&&p&&(l=!0,O()),!p){let j=sn($.sourceEvent,f),ee=j.x-c.x,se=j.y-c.y;Math.sqrt(ee*ee+se*se)>D&&H($)}(i.x!==W.xSnapped||i.y!==W.ySnapped)&&a&&p&&(c=sn($.sourceEvent,f),R(W))}}).on("end",$=>{if(!(!p||h)&&(l=!1,p=!1,cancelAnimationFrame(s),a.size>0)){let{nodeLookup:Q,updateNodePositions:y,onNodeDragStop:S,onSelectionDragStop:k}=t();if(g&&(y(a,!1),g=!1),o||S||!B&&k){let[D,J]=np({nodeId:B,dragItems:a,nodeLookup:Q,dragging:!1});o?.($.sourceEvent,a,D,J),S?.($.sourceEvent,D,J),B||k?.($.sourceEvent,J)}}}).filter($=>{let Q=$.target;return!$.button&&(!C||!my(Q,`.${C}`,I))&&(!E||my(Q,E,I))});u.call(F)}function w(){u?.on(".drag",null)}return{update:x,destroy:w}}function wB(e,t,r){let n=[],o={x:e.x-r,y:e.y-r,width:r*2,height:r*2};for(let i of t.values())Ts(o,Qi(i))>0&&n.push(i);return n}function CB(e,t,r,n){let o=[],i=1/0,s=wB(e,r,t+IB);for(let a of s){let l=[...a.internals.handleBounds?.source??[],...a.internals.handleBounds?.target??[]];for(let c of l){if(n.nodeId===c.nodeId&&n.type===c.type&&n.id===c.id)continue;let{x:f,y:p}=Vo(a,c,c.position,!0),u=Math.sqrt(Math.pow(f-e.x,2)+Math.pow(p-e.y,2));u>t||(u1){let a=n.type==="source"?"target":"source";return o.find(l=>l.type===a)??o[0]}return o[0]}function My(e,t,r,n,o,i=!1){let s=n.get(e);if(!s)return null;let a=o==="strict"?s.internals.handleBounds?.[t]:[...s.internals.handleBounds?.source??[],...s.internals.handleBounds?.target??[]],l=(r?a?.find(c=>c.id===r):a?.[0])??null;return l&&i?{...l,...Vo(s,l,l.position,!0)}:l}function Wy(e,t){return e||(t?.classList.contains("target")?"target":t?.classList.contains("source")?"source":null)}function EB(e,t){let r=null;return t?r=!0:e&&!t&&(r=!1),r}function $B(e,{connectionMode:t,connectionRadius:r,handleId:n,nodeId:o,edgeUpdaterType:i,isTarget:s,domNode:a,nodeLookup:l,lib:c,autoPanOnConnect:f,flowId:p,panBy:u,cancelConnection:h,onConnectStart:g,onConnect:b,onConnectEnd:x,isValidConnection:w=Hy,onReconnectEnd:C,updateConnection:E,getTransform:I,getFromHandle:T,autoPanSpeed:B,dragThreshold:Z=1,handleDomNode:R}){let O=hp(e.target),H=0,F,{x:$,y:Q}=sn(e),y=Wy(i,R),S=a?.getBoundingClientRect(),k=!1;if(!S||!y)return;let D=My(o,y,n,l,t);if(!D)return;let J=sn(e,S),W=!1,j=null,ee=!1,se=null;function de(){if(!f||!S)return;let[Se,ot]=Ey(J,S,B);u({x:Se,y:ot}),H=requestAnimationFrame(de)}let M={...D,nodeId:o,type:y,position:D.position},ce=l.get(o),ie={inProgress:!0,isValid:null,from:Vo(ce,M,$e.Left,!0),fromHandle:M,fromPosition:M.position,fromNode:ce,to:J,toHandle:null,toPosition:sy[M.position],toNode:null,pointer:J};function pe(){k=!0,E(ie),g?.(e,{nodeId:o,handleId:n,handleType:y})}Z===0&&pe();function ke(Se){if(!k){let{x:xt,y:Fe}=sn(Se),it=xt-$,tr=Fe-Q;if(!(it*it+tr*tr>Z*Z))return;pe()}if(!T()||!M){Qe(Se);return}let ot=I();J=sn(Se,S),F=CB(Ri(J,ot,!1,[1,1]),r,l,M),W||(de(),W=!0);let Re=zy(Se,{handle:F,connectionMode:t,fromNodeId:o,fromHandleId:n,fromType:s?"target":"source",isValidConnection:w,doc:O,lib:c,flowId:p,nodeLookup:l});se=Re.handleDomNode,j=Re.connection,ee=EB(!!F,Re.isValid);let ut=l.get(o),Je=ut?Vo(ut,M,$e.Left,!0):ie.from,et={...ie,from:Je,isValid:ee,to:Re.toHandle&&ee?fl({x:Re.toHandle.x,y:Re.toHandle.y},ot):J,toHandle:Re.toHandle,toPosition:ee&&Re.toHandle?Re.toHandle.position:sy[M.position],toNode:Re.toHandle?l.get(Re.toHandle.nodeId):null,pointer:J};E(et),ie=et}function Qe(Se){if(!("touches"in Se&&Se.touches.length>0)){if(k){(F||se)&&j&&ee&&b?.(j);let{inProgress:ot,...Re}=ie,ut={...Re,toPosition:ie.toHandle?ie.toPosition:null};x?.(Se,ut),i&&C?.(Se,ut)}h(),cancelAnimationFrame(H),W=!1,ee=!1,j=null,se=null,O.removeEventListener("mousemove",ke),O.removeEventListener("mouseup",Qe),O.removeEventListener("touchmove",ke),O.removeEventListener("touchend",Qe)}}O.addEventListener("mousemove",ke),O.addEventListener("mouseup",Qe),O.addEventListener("touchmove",ke),O.addEventListener("touchend",Qe)}function zy(e,{handle:t,connectionMode:r,fromNodeId:n,fromHandleId:o,fromType:i,doc:s,lib:a,flowId:l,isValidConnection:c=Hy,nodeLookup:f}){let p=i==="target",u=t?s.querySelector(`.${a}-flow__handle[data-id="${l}-${t?.nodeId}-${t?.id}-${t?.type}"]`):null,{x:h,y:g}=sn(e),b=s.elementFromPoint(h,g),x=b?.classList.contains(`${a}-flow__handle`)?b:u,w={handleDomNode:x,isValid:!1,connection:null,toHandle:null};if(x){let C=Wy(void 0,x),E=x.getAttribute("data-nodeid"),I=x.getAttribute("data-handleid"),T=x.classList.contains("connectable"),B=x.classList.contains("connectableend");if(!E||!C)return w;let Z={source:p?E:n,sourceHandle:p?I:o,target:p?n:E,targetHandle:p?o:I};w.connection=Z;let O=T&&B&&(r===To.Strict?p&&C==="source"||!p&&C==="target":E!==n||I!==o);w.isValid=O&&c(Z),w.toHandle=My(E,C,I,f,r,!0)}return w}function Yy({domNode:e,panZoom:t,getTransform:r,getViewScale:n}){let o=qt(e);function i({translateExtent:a,width:l,height:c,zoomStep:f=1,pannable:p=!0,zoomable:u=!0,inversePan:h=!1}){let g=E=>{if(E.sourceEvent.type!=="wheel"||!t)return;let I=r(),T=E.sourceEvent.ctrlKey&&Ds()?10:1,B=-E.sourceEvent.deltaY*(E.sourceEvent.deltaMode===1?.05:E.sourceEvent.deltaMode?1:.002)*f,Z=I[2]*Math.pow(2,B*T);t.scaleTo(Z)},b=[0,0],x=E=>{(E.sourceEvent.type==="mousedown"||E.sourceEvent.type==="touchstart")&&(b=[E.sourceEvent.clientX??E.sourceEvent.touches[0].clientX,E.sourceEvent.clientY??E.sourceEvent.touches[0].clientY])},w=E=>{let I=r();if(E.sourceEvent.type!=="mousemove"&&E.sourceEvent.type!=="touchmove"||!t)return;let T=[E.sourceEvent.clientX??E.sourceEvent.touches[0].clientX,E.sourceEvent.clientY??E.sourceEvent.touches[0].clientY],B=[T[0]-b[0],T[1]-b[1]];b=T;let Z=n()*Math.max(I[2],Math.log(I[2]))*(h?-1:1),R={x:I[0]-B[0]*Z,y:I[1]-B[1]*Z},O=[[0,0],[l,c]];t.setViewportConstrained({x:R.x,y:R.y,zoom:I[2]},O,a)},C=ad().on("start",x).on("zoom",p?w:null).on("zoom.wheel",u?g:null);o.call(C,{})}function s(){o.on("zoom",null)}return{update:i,destroy:s,pointer:vr}}function kB({zoomPanValues:e,noWheelClassName:t,d3Selection:r,d3Zoom:n,panOnScrollMode:o,panOnScrollSpeed:i,zoomOnPinch:s,onPanZoomStart:a,onPanZoom:l,onPanZoomEnd:c}){return f=>{if(Zs(f,t))return f.ctrlKey&&f.preventDefault(),!1;f.preventDefault(),f.stopImmediatePropagation();let p=r.property("__zoom").k||1;if(f.ctrlKey&&s){let x=vr(f),w=Jy(f),C=p*Math.pow(2,w);n.scaleTo(r,C,x,f);return}let u=f.deltaMode===1?20:1,h=o===Fi.Vertical?0:f.deltaX*u,g=o===Fi.Horizontal?0:f.deltaY*u;!Ds()&&f.shiftKey&&o!==Fi.Vertical&&(h=f.deltaY*u,g=0),n.translateBy(r,-(h/p)*i,-(g/p)*i,{internal:!0});let b=bd(r.property("__zoom"));clearTimeout(e.panScrollTimeout),e.isPanScrolling?(l?.(f,b),e.panScrollTimeout=setTimeout(()=>{c?.(f,b),e.isPanScrolling=!1},150)):(e.isPanScrolling=!0,a?.(f,b))}}function SB({noWheelClassName:e,preventScrolling:t,d3ZoomHandler:r}){return function(n,o){let i=n.type==="wheel",s=!t&&i&&!n.ctrlKey,a=Zs(n,e);if(n.ctrlKey&&i&&a&&n.preventDefault(),s||a)return null;n.preventDefault(),r.call(this,n,o)}}function AB({zoomPanValues:e,onDraggingChange:t,onPanZoomStart:r}){return n=>{if(n.sourceEvent?.internal)return;let o=bd(n.transform);e.mouseButton=n.sourceEvent?.button||0,e.isZoomingOrPanning=!0,e.prevViewport=o,n.sourceEvent?.type==="mousedown"&&t(!0),r&&r?.(n.sourceEvent,o)}}function NB({zoomPanValues:e,panOnDrag:t,onPaneContextMenu:r,onTransformChange:n,onPanZoom:o}){return i=>{e.usedRightMouseButton=!!(r&&Py(t,e.mouseButton??0)),i.sourceEvent?.sync||n([i.transform.x,i.transform.y,i.transform.k]),o&&!i.sourceEvent?.internal&&o?.(i.sourceEvent,bd(i.transform))}}function FB({zoomPanValues:e,panOnDrag:t,panOnScroll:r,onDraggingChange:n,onPanZoomEnd:o,onPaneContextMenu:i}){return s=>{if(!s.sourceEvent?.internal&&(e.isZoomingOrPanning=!1,i&&Py(t,e.mouseButton??0)&&!e.usedRightMouseButton&&s.sourceEvent&&i(s.sourceEvent),e.usedRightMouseButton=!1,n(!1),o)){let a=bd(s.transform);e.prevViewport=a,clearTimeout(e.timerId),e.timerId=setTimeout(()=>{o?.(s.sourceEvent,a)},r?150:0)}}}function GB({zoomActivationKeyPressed:e,zoomOnScroll:t,zoomOnPinch:r,panOnDrag:n,panOnScroll:o,zoomOnDoubleClick:i,userSelectionActive:s,noWheelClassName:a,noPanClassName:l,lib:c,connectionInProgress:f}){return p=>{let u=e||t,h=r&&p.ctrlKey,g=p.type==="wheel";if(p.button===1&&p.type==="mousedown"&&(Zs(p,`${c}-flow__node`)||Zs(p,`${c}-flow__edge`)))return!0;if(!n&&!u&&!o&&!i&&!r||s||f&&!g||Zs(p,a)&&g||Zs(p,l)&&(!g||o&&g&&!e)||!r&&p.ctrlKey&&g)return!1;if(!r&&p.type==="touchstart"&&p.touches?.length>1)return p.preventDefault(),!1;if(!u&&!o&&!h&&g||!n&&(p.type==="mousedown"||p.type==="touchstart")||Array.isArray(n)&&!n.includes(p.button)&&p.type==="mousedown")return!1;let b=Array.isArray(n)&&n.includes(p.button)||!p.button||p.button<=1;return(!p.ctrlKey||g)&&b}}function jy({domNode:e,minZoom:t,maxZoom:r,translateExtent:n,viewport:o,onPanZoom:i,onPanZoomStart:s,onPanZoomEnd:a,onDraggingChange:l}){let c={isZoomingOrPanning:!1,usedRightMouseButton:!1,prevViewport:{x:0,y:0,zoom:0},mouseButton:0,timerId:void 0,panScrollTimeout:void 0,isPanScrolling:!1},f=e.getBoundingClientRect(),p=ad().scaleExtent([t,r]).translateExtent(n),u=qt(e).call(p);C({x:o.x,y:o.y,zoom:Rs(o.zoom,t,r)},[[0,0],[f.width,f.height]],n);let h=u.on("wheel.zoom"),g=u.on("dblclick.zoom");p.wheelDelta(Jy);function b(F,$){return u?new Promise(Q=>{p?.interpolate($?.interpolate==="linear"?uo:Bi).transform(ip(u,$?.duration,$?.ease,()=>Q(!0)),F)}):Promise.resolve(!1)}function x({noWheelClassName:F,noPanClassName:$,onPaneContextMenu:Q,userSelectionActive:y,panOnScroll:S,panOnDrag:k,panOnScrollMode:D,panOnScrollSpeed:J,preventScrolling:W,zoomOnPinch:j,zoomOnScroll:ee,zoomOnDoubleClick:se,zoomActivationKeyPressed:de,lib:M,onTransformChange:ce,connectionInProgress:ne,paneClickDistance:ie,selectionOnDrag:pe}){y&&!c.isZoomingOrPanning&&w();let ke=S&&!de&&!y;p.clickDistance(pe?1/0:!Vn(ie)||ie<0?0:ie);let Qe=ke?kB({zoomPanValues:c,noWheelClassName:F,d3Selection:u,d3Zoom:p,panOnScrollMode:D,panOnScrollSpeed:J,zoomOnPinch:j,onPanZoomStart:s,onPanZoom:i,onPanZoomEnd:a}):SB({noWheelClassName:F,preventScrolling:W,d3ZoomHandler:h});if(u.on("wheel.zoom",Qe,{passive:!1}),!y){let ot=AB({zoomPanValues:c,onDraggingChange:l,onPanZoomStart:s});p.on("start",ot);let Re=NB({zoomPanValues:c,panOnDrag:k,onPaneContextMenu:!!Q,onPanZoom:i,onTransformChange:ce});p.on("zoom",Re);let ut=FB({zoomPanValues:c,panOnDrag:k,panOnScroll:S,onPaneContextMenu:Q,onPanZoomEnd:a,onDraggingChange:l});p.on("end",ut)}let Se=GB({zoomActivationKeyPressed:de,panOnDrag:k,zoomOnScroll:ee,panOnScroll:S,zoomOnDoubleClick:se,zoomOnPinch:j,userSelectionActive:y,noPanClassName:$,noWheelClassName:F,lib:M,connectionInProgress:ne});p.filter(Se),se?u.on("dblclick.zoom",g):u.on("dblclick.zoom",null)}function w(){p.on("zoom",null)}async function C(F,$,Q){let y=op(F),S=p?.constrain()(y,$,Q);return S&&await b(S),new Promise(k=>k(S))}async function E(F,$){let Q=op(F);return await b(Q,$),new Promise(y=>y(Q))}function I(F){if(u){let $=op(F),Q=u.property("__zoom");(Q.k!==F.zoom||Q.x!==F.x||Q.y!==F.y)&&p?.transform(u,$,null,{sync:!0})}}function T(){let F=u?dl(u.node()):{x:0,y:0,k:1};return{x:F.x,y:F.y,zoom:F.k}}function B(F,$){return u?new Promise(Q=>{p?.interpolate($?.interpolate==="linear"?uo:Bi).scaleTo(ip(u,$?.duration,$?.ease,()=>Q(!0)),F)}):Promise.resolve(!1)}function Z(F,$){return u?new Promise(Q=>{p?.interpolate($?.interpolate==="linear"?uo:Bi).scaleBy(ip(u,$?.duration,$?.ease,()=>Q(!0)),F)}):Promise.resolve(!1)}function R(F){p?.scaleExtent(F)}function O(F){p?.translateExtent(F)}function H(F){let $=!Vn(F)||F<0?0:F;p?.clickDistance($)}return{update:x,destroy:w,setViewport:E,setViewportConstrained:C,getViewport:T,scaleTo:B,scaleBy:Z,setScaleExtent:R,setTranslateExtent:O,syncViewport:I,setClickDistance:H}}var Gi,dd,ud,rB,To,Fi,Qs,pl,Dn,ul,$e,sy,lp,xy,cp,hl,yy,Do,Us,nB,Rs,Zi,ay,Ey,fd,sp,pd,Qi,cd,up,Ts,fp,Vn,pp,Vs,Ri,fl,gl,Ds,ky,hp,aB,gp,sn,ly,cB,dB,Fy,dy,uB,uy,Qy,hB,mp,gB,IB,Hy,xp,bd,op,Zs,Py,BB,ip,Jy,vy,ZB,T5,Ke=v(()=>{Rf();$r();iy();Ss();Gi={error001:()=>"[React Flow]: Seems like you have not used zustand provider as an ancestor. Help: https://reactflow.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:e=>`Node type "${e}" not found. Using fallback type "default".`,error004:()=>"The React Flow 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:e=>`The old edge with id=${e} does not exist.`,error009:e=>`Marker type "${e}" doesn't exist.`,error008:(e,{id:t,sourceHandle:r,targetHandle:n})=>`Couldn't create edge for ${e} handle id: "${e==="source"?r:n}", edge id: ${t}.`,error010:()=>"Handle: No node id found. Make sure to only use a Handle inside a custom Node.",error011:e=>`Edge type "${e}" not found. Using fallback type "default".`,error012:e=>`Node with id "${e}" does not exist, it may have been removed. This can happen when a node is deleted before the "onNodeClick" handler is called.`,error013:(e="react")=>`It seems that you haven't loaded the styles. Please import '@xyflow/${e}/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."},dd=[[Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY],[Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY]],ud=["Enter"," ","Escape"],rB={"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:e,x:t,y:r})=>`Moved selected node ${e}. New position, x: ${t}, y: ${r}`,"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"};(function(e){e.Strict="strict",e.Loose="loose"})(To||(To={}));(function(e){e.Free="free",e.Vertical="vertical",e.Horizontal="horizontal"})(Fi||(Fi={}));(function(e){e.Partial="partial",e.Full="full"})(Qs||(Qs={}));pl={inProgress:!1,isValid:null,from:null,fromHandle:null,fromPosition:null,fromNode:null,to:null,toHandle:null,toPosition:null,toNode:null,pointer:null};(function(e){e.Bezier="default",e.Straight="straight",e.Step="step",e.SmoothStep="smoothstep",e.SimpleBezier="simplebezier"})(Dn||(Dn={}));(function(e){e.Arrow="arrow",e.ArrowClosed="arrowclosed"})(ul||(ul={}));(function(e){e.Left="left",e.Top="top",e.Right="right",e.Bottom="bottom"})($e||($e={}));sy={[$e.Left]:$e.Right,[$e.Right]:$e.Left,[$e.Top]:$e.Bottom,[$e.Bottom]:$e.Top};lp=e=>"id"in e&&"source"in e&&"target"in e,xy=e=>"id"in e&&"position"in e&&!("source"in e)&&!("target"in e),cp=e=>"id"in e&&"internals"in e&&!("source"in e)&&!("target"in e),hl=(e,t=[0,0])=>{let{width:r,height:n}=po(e),o=e.origin??t,i=r*o[0],s=n*o[1];return{x:e.position.x-i,y:e.position.y-s}},yy=(e,t={nodeOrigin:[0,0]})=>{if(e.length===0)return{x:0,y:0,width:0,height:0};let r=e.reduce((n,o)=>{let i=typeof o=="string",s=!t.nodeLookup&&!i?o:void 0;t.nodeLookup&&(s=i?t.nodeLookup.get(o):cp(o)?o:t.nodeLookup.get(o.id));let a=s?cd(s,t.nodeOrigin):{x:0,y:0,x2:0,y2:0};return fd(n,a)},{x:1/0,y:1/0,x2:-1/0,y2:-1/0});return pd(r)},Do=(e,t={})=>{let r={x:1/0,y:1/0,x2:-1/0,y2:-1/0},n=!1;return e.forEach(o=>{(t.filter===void 0||t.filter(o))&&(r=fd(r,cd(o)),n=!0)}),n?pd(r):{x:0,y:0,width:0,height:0}},Us=(e,t,[r,n,o]=[0,0,1],i=!1,s=!1)=>{let a={...Ri(t,[r,n,o]),width:t.width/o,height:t.height/o},l=[];for(let c of e.values()){let{measured:f,selectable:p=!0,hidden:u=!1}=c;if(s&&!p||u)continue;let h=f.width??c.width??c.initialWidth??null,g=f.height??c.height??c.initialHeight??null,b=Ts(a,Qi(c)),x=(h??0)*(g??0),w=i&&b>0;(!c.internals.handleBounds||w||b>=x||c.dragging)&&l.push(c)}return l},nB=(e,t)=>{let r=new Set;return e.forEach(n=>{r.add(n.id)}),t.filter(n=>r.has(n.source)||r.has(n.target))};Rs=(e,t=0,r=1)=>Math.min(Math.max(e,t),r),Zi=(e={x:0,y:0},t,r)=>({x:Rs(e.x,t[0][0],t[1][0]-(r?.width??0)),y:Rs(e.y,t[0][1],t[1][1]-(r?.height??0))});ay=(e,t,r)=>er?-Rs(Math.abs(e-r),1,t)/t:0,Ey=(e,t,r=15,n=40)=>{let o=ay(e.x,n,t.width-n)*r,i=ay(e.y,n,t.height-n)*r;return[o,i]},fd=(e,t)=>({x:Math.min(e.x,t.x),y:Math.min(e.y,t.y),x2:Math.max(e.x2,t.x2),y2:Math.max(e.y2,t.y2)}),sp=({x:e,y:t,width:r,height:n})=>({x:e,y:t,x2:e+r,y2:t+n}),pd=({x:e,y:t,x2:r,y2:n})=>({x:e,y:t,width:r-e,height:n-t}),Qi=(e,t=[0,0])=>{let{x:r,y:n}=cp(e)?e.internals.positionAbsolute:hl(e,t);return{x:r,y:n,width:e.measured?.width??e.width??e.initialWidth??0,height:e.measured?.height??e.height??e.initialHeight??0}},cd=(e,t=[0,0])=>{let{x:r,y:n}=cp(e)?e.internals.positionAbsolute:hl(e,t);return{x:r,y:n,x2:r+(e.measured?.width??e.width??e.initialWidth??0),y2:n+(e.measured?.height??e.height??e.initialHeight??0)}},up=(e,t)=>pd(fd(sp(e),sp(t))),Ts=(e,t)=>{let r=Math.max(0,Math.min(e.x+e.width,t.x+t.width)-Math.max(e.x,t.x)),n=Math.max(0,Math.min(e.y+e.height,t.y+t.height)-Math.max(e.y,t.y));return Math.ceil(r*n)},fp=e=>Vn(e.width)&&Vn(e.height)&&Vn(e.x)&&Vn(e.y),Vn=e=>!isNaN(e)&&isFinite(e),pp=(e,t)=>{},Vs=(e,t=[1,1])=>({x:t[0]*Math.round(e.x/t[0]),y:t[1]*Math.round(e.y/t[1])}),Ri=({x:e,y:t},[r,n,o],i=!1,s=[1,1])=>{let a={x:(e-r)/o,y:(t-n)/o};return i?Vs(a,s):a},fl=({x:e,y:t},[r,n,o])=>({x:e*o+r,y:t*o+n});gl=(e,t,r,n,o,i)=>{let s=iB(i,t,r),a=(t-s.x)/e.width,l=(r-s.y)/e.height,c=Math.min(a,l),f=Rs(c,n,o),p=e.x+e.width/2,u=e.y+e.height/2,h=t/2-p*f,g=r/2-u*f,b=sB(e,h,g,f,t,r),x={left:Math.min(b.left-s.left,0),top:Math.min(b.top-s.top,0),right:Math.min(b.right-s.right,0),bottom:Math.min(b.bottom-s.bottom,0)};return{x:h-x.left+x.right,y:g-x.top+x.bottom,zoom:f}},Ds=()=>typeof navigator<"u"&&navigator?.userAgent?.indexOf("Mac")>=0;ky=e=>({width:e.offsetWidth,height:e.offsetHeight}),hp=e=>e?.getRootNode?.()||window?.document,aB=["INPUT","SELECT","TEXTAREA"];gp=e=>"clientX"in e,sn=(e,t)=>{let r=gp(e),n=r?e.clientX:e.touches?.[0].clientX,o=r?e.clientY:e.touches?.[0].clientY;return{x:n-(t?.left??0),y:o-(t?.top??0)}},ly=(e,t,r,n,o)=>{let i=t.querySelectorAll(`.${e}`);return!i||!i.length?null:Array.from(i).map(s=>{let a=s.getBoundingClientRect();return{id:s.getAttribute("data-handleid"),type:e,nodeId:o,position:s.getAttribute("data-handlepos"),x:(a.left-r.left)/n,y:(a.top-r.top)/n,...ky(s)}})};cB=({source:e,sourceHandle:t,target:r,targetHandle:n})=>`xy-edge__${e}${t||""}-${r}${n||""}`,dB=(e,t)=>t.some(r=>r.source===e.source&&r.target===e.target&&(r.sourceHandle===e.sourceHandle||!r.sourceHandle&&!e.sourceHandle)&&(r.targetHandle===e.targetHandle||!r.targetHandle&&!e.targetHandle)),Fy=(e,t,r={})=>{if(!e.source||!e.target)return pp("006",Gi.error006()),t;let n=r.getEdgeId||cB,o;return lp(e)?o={...e}:o={...e,id:n(e)},dB(o,t)?t:(o.sourceHandle===null&&delete o.sourceHandle,o.targetHandle===null&&delete o.targetHandle,t.concat(o))};dy={[$e.Left]:{x:-1,y:0},[$e.Right]:{x:1,y:0},[$e.Top]:{x:0,y:-1},[$e.Bottom]:{x:0,y:1}},uB=({source:e,sourcePosition:t=$e.Bottom,target:r})=>t===$e.Left||t===$e.Right?e.xMath.sqrt(Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2));Qy=1e3,hB=10,mp={nodeOrigin:[0,0],nodeExtent:dd,elevateNodesOnSelect:!0,zIndexMode:"basic",defaults:{}},gB={...mp,checkEquality:!0};IB=250;Hy=()=>!0;xp={onPointerDown:$B,isValid:zy};bd=e=>({x:e.x,y:e.y,zoom:e.k}),op=({x:e,y:t,zoom:r})=>Ni.translate(e,t).scale(r),Zs=(e,t)=>e.target.closest(`.${t}`),Py=(e,t)=>t===2&&Array.isArray(e)&&e.includes(2),BB=e=>((e*=2)<=1?e*e*e:(e-=2)*e*e+2)/2,ip=(e,t=0,r=BB,n=()=>{})=>{let o=typeof t=="number"&&t>0;return o||n(),o?e.transition().duration(t).ease(r).on("end",n):e},Jy=e=>{let t=e.ctrlKey&&Ds()?10:1;return-e.deltaY*(e.deltaMode===1?.05:e.deltaMode?1:.002)*t};(function(e){e.Line="line",e.Handle="handle"})(vy||(vy={}));ZB={width:0,height:0,x:0,y:0},T5={...ZB,pointerX:0,pointerY:0,aspectRatio:1}});function yp(){let e={};return[t=>{if(t&&!sa(e))throw new Error(t);return zn(e)},t=>jo(e,t)]}var Ky,qy,e0,t0,r0,n0,ml=v(()=>{Dr();[Ky,qy]=yp(),[e0,t0]=yp(),[r0,n0]=yp()});function ho(e,t){K(t,!0);let r=z(t,"id",3,null),n=z(t,"type",3,"source"),o=z(t,"position",19,()=>$e.Top),i=z(t,"isConnectableStart",3,!0),s=z(t,"isConnectableEnd",3,!0),a=Kt(t,QB),l=Ky("Handle must be used within a Custom Node component"),c=e0("Handle must be used within a Custom Node component"),f=_(()=>n()==="target"),p=_(()=>t.isConnectable!==void 0?t.isConnectable:c.value),u=Qt(),h=_(()=>u.ariaLabelConfig),g=null;ui(()=>{if(t.onconnect||t.ondisconnect){u.edges;let $=u.connectionLookup.get(`${l}-${n()}${r()?`-${r()}`:""}`);if(g&&!_y($,g)){let Q=$??new Map;ap(g,Q,t.ondisconnect),ap(Q,g,t.onconnect)}g=new Map($)}});let b=_(()=>{if(!u.connection.inProgress)return[!1,!1,!1,!1,null];let{fromHandle:$,toHandle:Q,isValid:y}=u.connection,S=$&&$.nodeId===l&&$.type===n()&&$.id===r(),k=Q&&Q.nodeId===l&&Q.type===n()&&Q.id===r(),D=u.connectionMode===To.Strict?$?.type!==n():l!==$?.nodeId||r()!==$?.id;return[!0,S,k,D,k&&y]}),x=_(()=>dn(d(b),5)),w=_(()=>d(x)[0]),C=_(()=>d(x)[1]),E=_(()=>d(x)[2]),I=_(()=>d(x)[3]),T=_(()=>d(x)[4]);function B($){let Q=u.onbeforeconnect?u.onbeforeconnect($):$;Q&&(u.addEdge(Q),u.onconnect?.($))}function Z($){let Q=gp($);$.currentTarget&&(Q&&$.button===0||!Q)&&xp.onPointerDown($,{handleId:r(),nodeId:l,isTarget:d(f),connectionRadius:u.connectionRadius,domNode:u.domNode,nodeLookup:u.nodeLookup,connectionMode:u.connectionMode,lib:"svelte",autoPanOnConnect:u.autoPanOnConnect,autoPanSpeed:u.autoPanSpeed,flowId:u.flowId,isValidConnection:t.isValidConnection||((...y)=>u.isValidConnection?.(...y)??!0),updateConnection:u.updateConnection,cancelConnection:u.cancelConnection,panBy:u.panBy,onConnect:B,onConnectStart:u.onconnectstart,onConnectEnd:(...y)=>u.onconnectend?.(...y),getTransform:()=>[u.viewport.x,u.viewport.y,u.viewport.zoom],getFromHandle:()=>u.connection.fromHandle,dragThreshold:u.connectionDragThreshold,handleDomNode:$.currentTarget})}function R($){if(!l||!u.clickConnectStartHandle&&!i())return;if(!u.clickConnectStartHandle){u.onclickconnectstart?.($,{nodeId:l,handleId:r(),handleType:n()}),u.clickConnectStartHandle={nodeId:l,type:n(),id:r()};return}let Q=hp($.target),y=t.isValidConnection??u.isValidConnection,{connectionMode:S,clickConnectStartHandle:k,flowId:D,nodeLookup:J}=u,{connection:W,isValid:j}=xp.isValid($,{handle:{nodeId:l,id:r(),type:n()},connectionMode:S,fromNodeId:k.nodeId,fromHandleId:k.id??null,fromType:k.type,isValidConnection:y,flowId:D,doc:Q,lib:"svelte",nodeLookup:J});j&&W&&B(W);let ee=structuredClone(Wn(u.connection));delete ee.inProgress,ee.toPosition=ee.toHandle?ee.toHandle.position:null,u.onclickconnectend?.($,ee),u.clickConnectStartHandle=null}var O=RB(),H=()=>{};jt(O,()=>({"data-handleid":r(),"data-nodeid":l,"data-handlepos":o(),"data-id":`${u.flowId??""}-${l??""}-${r()??"null"??""}-${n()??""}`,class:["svelte-flow__handle",`svelte-flow__handle-${o()}`,u.noDragClass,u.noPanClass,o(),t.class],onmousedown:Z,ontouchstart:Z,onclick:u.clickConnect?R:void 0,onkeypress:H,style:t.style,role:"button","aria-label":d(h)["handle.ariaLabel"],tabindex:"-1",...a,[nn]:{valid:d(T),connectingto:d(E),connectingfrom:d(C),source:!d(f),target:d(f),connectablestart:i(),connectableend:s(),connectable:d(p),connectionindicator:d(p)&&(!d(w)||d(I))&&(d(w)||u.clickConnectStartHandle?s():i())}}));var F=V(O);dt(F,()=>t.children??ft),L(O),N(e,O),q()}var QB,RB,o0=v(()=>{_e();ae();Ke();an();ml();QB=new Set(["$$slots","$$events","$$legacy","id","type","position","style","class","isConnectable","isConnectableStart","isConnectableEnd","isValidConnection","onconnect","ondisconnect","children"]),RB=Y("
")});var i0=v(()=>{});var vl=v(()=>{o0();i0()});function _l(e,t){K(t,!0);let r=z(t,"targetPosition",19,()=>$e.Top),n=z(t,"sourcePosition",19,()=>$e.Bottom);var o=LB(),i=ve(o);ho(i,{type:"target",get position(){return r()}});var s=P(i),a=P(s);ho(a,{type:"source",get position(){return n()}}),te(()=>he(s,` ${t.data?.label??""} `)),N(e,o),q()}var LB,wp=v(()=>{_e();ae();Ke();vl();LB=Y(" ",1)});function Ip(e,t){K(t,!0);let r=z(t,"data",19,()=>({label:"Node"})),n=z(t,"sourcePosition",19,()=>$e.Bottom);zt();var o=UB(),i=ve(o),s=P(i);ho(s,{type:"source",get position(){return n()}}),te(()=>he(i,`${r()?.label??""} `)),N(e,o),q()}var UB,s0=v(()=>{_e();ae();Ke();vl();UB=Y(" ",1)});function Cp(e,t){K(t,!0);let r=z(t,"data",19,()=>({label:"Node"})),n=z(t,"targetPosition",19,()=>$e.Top);zt();var o=TB(),i=ve(o),s=P(i);ho(s,{type:"target",get position(){return n()}}),te(()=>he(i,`${r()?.label??""} `)),N(e,o),q()}var TB,a0=v(()=>{_e();ae();Ke();vl();TB=Y(" ",1)});function Ep(e,t){}var l0=v(()=>{_e();ae()});function $p(e,t,r){if(!r||!t)return;let n=r==="root"?t:t.querySelector(`.svelte-flow__${r}`);n&&n.appendChild(e)}function Bp(e,t){let r=_(Qt),n=_(()=>d(r).domNode),o;return d(n)?$p(e,d(n),t):o=fi(()=>{ct(()=>{$p(e,d(n),t),o?.()})}),{async update(i){$p(e,d(n),i)},destroy(){e.parentNode&&e.parentNode.removeChild(e),o?.()}}}var c0=v(()=>{ae();an()});function kp(){let e=we(typeof window>"u");if(d(e)){let t=fi(()=>{ct(()=>{X(e,!1),t?.()})})}return{get value(){return d(e)}}}var d0=v(()=>{ae()});var Sp=v(()=>{c0();d0()});function xr(e){return e===void 0?void 0:`${e}px`}var Ap,u0,Xs,Oo=v(()=>{Ke();Ap=e=>xy(e),u0=e=>lp(e);Xs={ArrowUp:{x:0,y:-1},ArrowDown:{x:0,y:1},ArrowLeft:{x:-1,y:0},ArrowRight:{x:1,y:0}}});var f0=v(()=>{});function Np(e,t){K(t,!0);let r=z(t,"x",3,0),n=z(t,"y",3,0),o=z(t,"selectEdgeOnClick",3,!1),i=z(t,"transparent",3,!1),s=Kt(t,VB),a=Qt(),l=r0("EdgeLabel must be used within a Custom Edge component"),c=_(()=>a.visible.edges.get(l)?.zIndex);var f=DB(),p=()=>{o()&&l&&a.handleEdgeSelection(l)};jt(f,h=>({class:["svelte-flow__edge-label",{transparent:i()},t.class],tabindex:"-1",onclick:p,...s,[Er]:h}),[()=>({display:kp().value?"none":void 0,cursor:o()?"pointer":void 0,transform:`translate(-50%, -50%) translate(${r()??""}px,${n()??""}px)`,"pointer-events":"all",width:xr(t.width),height:xr(t.height),"z-index":d(c)})],void 0,void 0,"svelte-1wg91mu");var u=V(f);dt(u,()=>t.children??ft),L(f),gt(f,(h,g)=>Bp?.(h,g),()=>"edge-labels"),N(e,f),q()}var VB,DB,p0=v(()=>{_e();ae();ml();Sp();an();Oo();f0();VB=new Set(["$$slots","$$events","$$legacy","x","y","width","height","selectEdgeOnClick","transparent","class","children"]),DB=Y("
")});function go(e,t){let r=z(t,"interactionWidth",3,20),n=Kt(t,OB);var o=MB(),i=ve(o),s=P(i);{var a=f=>{var p=XB();jt(p,()=>({d:t.path,"stroke-opacity":0,"stroke-width":r(),fill:"none",class:"svelte-flow__edge-interaction",...n})),N(f,p)};ue(s,f=>{r()>0&&f(a)})}var l=P(s);{var c=f=>{Np(f,{get x(){return t.labelX},get y(){return t.labelY},get style(){return t.labelStyle},selectEdgeOnClick:!0,children:(p,u)=>{zt();var h=zu();te(()=>he(h,t.label)),N(p,h)},$$slots:{default:!0}})};ue(l,f=>{t.label&&f(c)})}te(()=>{re(i,"id",t.id),re(i,"d",t.path),Pe(i,0,Jt(["svelte-flow__edge-path",t.class])),re(i,"marker-start",t.markerStart),re(i,"marker-end",t.markerEnd),nt(i,t.style)}),N(e,o)}var OB,XB,MB,bl=v(()=>{_e();ae();p0();OB=new Set(["$$slots","$$events","$$legacy","id","path","label","labelX","labelY","labelStyle","markerStart","markerEnd","style","interactionWidth","class"]),XB=Ze(""),MB=Ze('',1)});function Ms(e,t){K(t,!0);let r=_(()=>md({sourceX:t.sourceX,sourceY:t.sourceY,targetX:t.targetX,targetY:t.targetY,sourcePosition:t.sourcePosition,targetPosition:t.targetPosition,curvature:t.pathOptions?.curvature})),n=_(()=>dn(d(r),3)),o=_(()=>d(n)[0]),i=_(()=>d(n)[1]),s=_(()=>d(n)[2]);go(e,{get id(){return t.id},get path(){return d(o)},get labelX(){return d(i)},get labelY(){return d(s)},get label(){return t.label},get labelStyle(){return t.labelStyle},get markerStart(){return t.markerStart},get markerEnd(){return t.markerEnd},get interactionWidth(){return t.interactionWidth},get style(){return t.style}}),q()}var h0=v(()=>{_e();ae();Ke();bl()});function xd(e,t){K(t,!0);let r=_(()=>Os({sourceX:t.sourceX,sourceY:t.sourceY,targetX:t.targetX,targetY:t.targetY,sourcePosition:t.sourcePosition,targetPosition:t.targetPosition})),n=_(()=>dn(d(r),3)),o=_(()=>d(n)[0]),i=_(()=>d(n)[1]),s=_(()=>d(n)[2]);go(e,{get path(){return d(o)},get labelX(){return d(i)},get labelY(){return d(s)},get label(){return t.label},get labelStyle(){return t.labelStyle},get markerStart(){return t.markerStart},get markerEnd(){return t.markerEnd},get interactionWidth(){return t.interactionWidth},get style(){return t.style}}),q()}var g0=v(()=>{_e();ae();Ke();bl()});function yd(e,t){K(t,!0);let r=_(()=>vd({sourceX:t.sourceX,sourceY:t.sourceY,targetX:t.targetX,targetY:t.targetY})),n=_(()=>dn(d(r),3)),o=_(()=>d(n)[0]),i=_(()=>d(n)[1]),s=_(()=>d(n)[2]);go(e,{get path(){return d(o)},get labelX(){return d(i)},get labelY(){return d(s)},get label(){return t.label},get labelStyle(){return t.labelStyle},get markerStart(){return t.markerStart},get markerEnd(){return t.markerEnd},get interactionWidth(){return t.interactionWidth},get style(){return t.style}}),q()}var m0=v(()=>{_e();ae();Ke();bl()});function wd(e,t){K(t,!0);let r=_(()=>Os({sourceX:t.sourceX,sourceY:t.sourceY,targetX:t.targetX,targetY:t.targetY,sourcePosition:t.sourcePosition,targetPosition:t.targetPosition,borderRadius:0})),n=_(()=>dn(d(r),3)),o=_(()=>d(n)[0]),i=_(()=>d(n)[1]),s=_(()=>d(n)[2]);go(e,{get path(){return d(o)},get labelX(){return d(i)},get labelY(){return d(s)},get label(){return t.label},get labelStyle(){return t.labelStyle},get markerStart(){return t.markerStart},get markerEnd(){return t.markerEnd},get interactionWidth(){return t.interactionWidth},get style(){return t.style}}),q()}var v0=v(()=>{_e();ae();Ke();bl()});var Fp=v(()=>{h0();g0();m0();v0()});var _0=v(()=>{ae();vt();Zr();Ee();Ne()});var b0=v(()=>{Ne();vt();Zr();Ee()});var x0=v(()=>{Ne();vt();Zr();Ee()});var y0,ar,yl,mo,Li,xl,Id,Gp=v(()=>{Ne();vt();Zr();Ee();Zp();y0=Symbol("replace"),Id=class extends URLSearchParams{constructor(){super(...arguments);U(this,Li);U(this,ar,G?pt(we(0),"SvelteURLSearchParams version"):we(0));U(this,yl,w0());U(this,mo,!1)}[y0](r){if(!m(this,mo)){ge(this,mo,!0);for(let n of[...super.keys()])super.delete(n);for(let[n,o]of r)super.append(n,o);ur(m(this,ar)),ge(this,mo,!1)}}append(r,n){super.append(r,n),Ie(this,Li,xl).call(this),ur(m(this,ar))}delete(r,n){var o=super.has(r,n);super.delete(r,n),o&&(Ie(this,Li,xl).call(this),ur(m(this,ar)))}get(r){return d(m(this,ar)),super.get(r)}getAll(r){return d(m(this,ar)),super.getAll(r)}has(r,n){return d(m(this,ar)),super.has(r,n)}keys(){return d(m(this,ar)),super.keys()}set(r,n){var o=super.getAll(r).join("");super.set(r,n),o!==super.getAll(r).join("")&&(Ie(this,Li,xl).call(this),ur(m(this,ar)))}sort(){super.sort(),Ie(this,Li,xl).call(this),ur(m(this,ar))}toString(){return d(m(this,ar)),super.toString()}values(){return d(m(this,ar)),super.values()}entries(){return d(m(this,ar)),super.entries()}[Symbol.iterator](){return this.entries()}get size(){return d(m(this,ar)),super.size}};ar=new WeakMap,yl=new WeakMap,mo=new WeakMap,Li=new WeakSet,xl=function(){if(!m(this,yl)||m(this,mo))return;ge(this,mo,!0);let r=this.toString();m(this,yl).search=r&&`?${r}`,ge(this,mo,!1)}});function w0(){return HB}var HB,Zp=v(()=>{Ne();vt();Zr();Ee();Gp();HB=null});var Qp=v(()=>{Is()});var wl,Il,Cd,I0=v(()=>{ql();Cd=class{constructor(t,r){U(this,wl);U(this,Il);ge(this,wl,t),ge(this,Il,_a(r))}get current(){return m(this,Il).call(this),m(this,wl).call(this)}};wl=new WeakMap,Il=new WeakMap});var zB,YB,Cl,C0=v(()=>{Qp();I0();zB=/\(.+\)/,YB=new Set(["all","print","screen","and","or","not","only"]),Cl=class extends Cd{constructor(t,r){let n=zB.test(t)||t.split(/[\s,]+/).some(i=>YB.has(i.trim()))?t:`(${t})`,o=window.matchMedia(n);super(()=>o.matches,i=>gi(o,"change",i))}}});var E0=v(()=>{_0();b0();x0();Zp();Gp();C0();ql()});function $0(e,t,r,n){let o=new Map;return Us(e,{x:0,y:0,width:r,height:n},t,!0).forEach(i=>{o.set(i.id,i)}),o}function Rp(e){let{edges:t,defaultEdgeOptions:r,nodeLookup:n,previousEdges:o,connectionMode:i,onerror:s,onlyRenderVisible:a,elevateEdgesOnSelect:l,zIndexMode:c}=e,f=new Map;for(let p of t){let u=n.get(p.source),h=n.get(p.target);if(!u||!h)continue;if(a){let{visibleNodes:x,transform:w,width:C,height:E}=e;if(Ny({sourceNode:u,targetNode:h,width:C,height:E,transform:w}))x.set(u.id,u),x.set(h.id,h);else continue}let g=o.get(p.id);if(g&&p===g.edge&&u==g.sourceNode&&h==g.targetNode){f.set(p.id,g);continue}let b=Gy({id:p.id,sourceNode:u,targetNode:h,sourceHandle:p.sourceHandle||null,targetHandle:p.targetHandle||null,connectionMode:i,onError:s});b&&f.set(p.id,{...r,...p,...b,zIndex:Ay({selected:p.selected,zIndex:p.zIndex??r.zIndex,sourceNode:u,targetNode:h,elevateOnSelect:l,zIndexMode:c}),sourceNode:u,targetNode:h,edge:p})}return f}var B0=v(()=>{Ke()});function PB(e,t,r,n,o,i){if(t&&!r&&n&&o){let s=Do(i,{filter:a=>!!((a.width||a.initialWidth)&&(a.height||a.initialHeight))});return gl(s,n,o,.5,2,.1)}else return r??{x:0,y:0,zoom:1}}function k0(e){var r,n,o,i,s,a,l,c,f,p,u,h,g,b,x,w,C,E,I,T,B,Z,R,O,H,F,$,Q,y,S,k,D,J,W,j,ee,se,de,M,ce,ne,ie,pe,ke,Qe,Se,ot,Re,ut,Je,et,xt,Fe,it,tr,We,Sr,Mr,Wr,Vi,Di,Oi,Xi,Mi,Wi,Hi,zi,Yi,Pi,Ji,Wo,Ho,Ar,zo,Hr,Js;class t{constructor(){U(this,r,_(()=>e.props.id??"1"));U(this,n,we(null));U(this,o,we(null));U(this,i,we(e.width??0));U(this,s,we(e.height??0));U(this,a,we(e.props.zIndexMode??"basic"));U(this,l,_(()=>{let{nodesInitialized:A}=Ly(e.nodes,this.nodeLookup,this.parentLookup,{nodeExtent:this.nodeExtent,nodeOrigin:this.nodeOrigin,elevateNodesOnSelect:e.props.elevateNodesOnSelect??!0,checkEquality:!0,zIndexMode:this.zIndexMode});return this.fitViewQueued&&A&&(this.fitViewOptions?.duration?this.resolveFitView():queueMicrotask(()=>{this.resolveFitView()})),A}));U(this,c,_(()=>this.panZoom!==null));U(this,f,_(()=>(Dy(this.connectionLookup,this.edgeLookup,e.edges),e.edges)));Be(this,"_prevSelectedNodes",[]);Be(this,"_prevSelectedNodeIds",new Set);U(this,p,_(()=>{let A=this._prevSelectedNodeIds.size,Xn=new Set,js=this.nodes.filter(zr=>(zr.selected&&(Xn.add(zr.id),this._prevSelectedNodeIds.delete(zr.id)),zr.selected));return(A!==Xn.size||this._prevSelectedNodeIds.size>0)&&(this._prevSelectedNodes=js),this._prevSelectedNodeIds=Xn,this._prevSelectedNodes}));Be(this,"_prevSelectedEdges",[]);Be(this,"_prevSelectedEdgeIds",new Set);U(this,u,_(()=>{let A=this._prevSelectedEdgeIds.size,Xn=new Set,js=this.edges.filter(zr=>(zr.selected&&(Xn.add(zr.id),this._prevSelectedEdgeIds.delete(zr.id)),zr.selected));return(A!==Xn.size||this._prevSelectedEdgeIds.size>0)&&(this._prevSelectedEdges=js),this._prevSelectedEdgeIds=Xn,this._prevSelectedEdges}));Be(this,"selectionChangeHandlers",new Map);Be(this,"nodeLookup",new Map);Be(this,"parentLookup",new Map);Be(this,"connectionLookup",new Map);Be(this,"edgeLookup",new Map);Be(this,"_prevVisibleEdges",new Map);U(this,h,_(()=>{let{nodes:A,_edges:Xn,_prevVisibleEdges:js,nodeLookup:zr,connectionMode:iC,onerror:sC,onlyRenderVisibleElements:aC,defaultEdgeOptions:lC,zIndexMode:cC}=this,Fl,Pd,$h={edges:Xn,defaultEdgeOptions:lC,previousEdges:js,nodeLookup:zr,connectionMode:iC,elevateEdgesOnSelect:e.props.elevateEdgesOnSelect??!0,zIndexMode:cC,onerror:sC};if(aC){let{viewport:Jd,width:Bh,height:kh}=this,Sh=[Jd.x,Jd.y,Jd.zoom];Fl=$0(zr,Sh,Bh,kh),Pd=Rp({...$h,onlyRenderVisible:!0,visibleNodes:Fl,transform:Sh,width:Bh,height:kh})}else Fl=this.nodeLookup,Pd=Rp($h);return{nodes:Fl,edges:Pd}}));U(this,g,_(()=>e.props.nodesDraggable??!0));U(this,b,_(()=>e.props.nodesConnectable??!0));U(this,x,_(()=>e.props.elementsSelectable??!0));U(this,w,_(()=>e.props.nodesFocusable??!0));U(this,C,_(()=>e.props.edgesFocusable??!0));U(this,E,_(()=>e.props.disableKeyboardA11y??!1));U(this,I,_(()=>e.props.minZoom??.5));U(this,T,_(()=>e.props.maxZoom??2));U(this,B,_(()=>e.props.nodeOrigin??[0,0]));U(this,Z,_(()=>e.props.nodeExtent??dd));U(this,R,_(()=>e.props.translateExtent??dd));U(this,O,_(()=>e.props.defaultEdgeOptions??{}));U(this,H,_(()=>e.props.nodeDragThreshold??1));U(this,F,_(()=>e.props.autoPanOnNodeDrag??!0));U(this,$,_(()=>e.props.autoPanOnConnect??!0));U(this,Q,_(()=>e.props.autoPanOnNodeFocus??!0));U(this,y,_(()=>e.props.autoPanSpeed??15));U(this,S,_(()=>e.props.connectionDragThreshold??1));Be(this,"fitViewQueued",e.props.fitView??!1);Be(this,"fitViewOptions",e.props.fitViewOptions);Be(this,"fitViewResolver",null);U(this,k,_(()=>e.props.snapGrid??null));U(this,D,we(!1));U(this,J,we(null));U(this,W,we(!1));U(this,j,we(!1));U(this,ee,we(!1));U(this,se,we(!1));U(this,de,we(!1));U(this,M,we(null));U(this,ce,we(""));U(this,ne,_(()=>e.props.selectionMode??Qs.Partial));U(this,ie,_(()=>({...Lp,...e.props.nodeTypes})));U(this,pe,_(()=>({...Up,...e.props.edgeTypes})));U(this,ke,_(()=>e.props.noPanClass??"nopan"));U(this,Qe,_(()=>e.props.noDragClass??"nodrag"));U(this,Se,_(()=>e.props.noWheelClass??"nowheel"));U(this,ot,_(()=>By(e.props.ariaLabelConfig)));U(this,Re,we(PB(this.nodesInitialized,e.props.fitView,e.props.initialViewport,this.width,this.height,this.nodeLookup)));U(this,ut,we(pl));U(this,Je,_(()=>this._connection.inProgress?{...this._connection,to:Ri(this._connection.to,[this.viewport.x,this.viewport.y,this.viewport.zoom])}:this._connection));U(this,et,_(()=>e.props.connectionMode??To.Strict));U(this,xt,_(()=>e.props.connectionRadius??20));U(this,Fe,_(()=>e.props.isValidConnection??(()=>!0)));U(this,it,_(()=>e.props.selectNodesOnDrag??!0));U(this,tr,_(()=>e.props.defaultMarkerColor===void 0?"#b1b1b7":e.props.defaultMarkerColor));U(this,We,_(()=>Zy(e.edges,{defaultColor:this.defaultMarkerColor,id:this.flowId,defaultMarkerStart:this.defaultEdgeOptions.markerStart,defaultMarkerEnd:this.defaultEdgeOptions.markerEnd})));U(this,Sr,_(()=>e.props.onlyRenderVisibleElements??!1));U(this,Mr,_(()=>e.props.onflowerror??pp));U(this,Wr,_(()=>e.props.ondelete));U(this,Vi,_(()=>e.props.onbeforedelete));U(this,Di,_(()=>e.props.onbeforeconnect));U(this,Oi,_(()=>e.props.onconnect));U(this,Xi,_(()=>e.props.onconnectstart));U(this,Mi,_(()=>e.props.onconnectend));U(this,Wi,_(()=>e.props.onbeforereconnect));U(this,Hi,_(()=>e.props.onreconnect));U(this,zi,_(()=>e.props.onreconnectstart));U(this,Yi,_(()=>e.props.onreconnectend));U(this,Pi,_(()=>e.props.clickConnect??!0));U(this,Ji,_(()=>e.props.onclickconnectstart));U(this,Wo,_(()=>e.props.onclickconnectend));U(this,Ho,we(null));U(this,Ar,_(()=>e.props.onselectiondrag));U(this,zo,_(()=>e.props.onselectiondragstart));U(this,Hr,_(()=>e.props.onselectiondragstop));Be(this,"resolveFitView",async()=>{this.panZoom&&(await wy({nodes:this.nodeLookup,width:this.width,height:this.height,panZoom:this.panZoom,minZoom:this.minZoom,maxZoom:this.maxZoom},this.fitViewOptions),this.fitViewResolver?.resolve(!0),this.fitViewQueued=!1,this.fitViewOptions=void 0,this.fitViewResolver=null)});Be(this,"_prefersDark",new Cl("(prefers-color-scheme: dark)",e.props.colorModeSSR==="dark"));U(this,Js,_(()=>e.props.colorMode==="system"?this._prefersDark.current?"dark":"light":e.props.colorMode??"light"))}get flowId(){return d(m(this,r))}set flowId(A){X(m(this,r),A)}get domNode(){return d(m(this,n))}set domNode(A){X(m(this,n),A)}get panZoom(){return d(m(this,o))}set panZoom(A){X(m(this,o),A)}get width(){return d(m(this,i))}set width(A){X(m(this,i),A)}get height(){return d(m(this,s))}set height(A){X(m(this,s),A)}get zIndexMode(){return d(m(this,a))}set zIndexMode(A){X(m(this,a),A)}get nodesInitialized(){return d(m(this,l))}set nodesInitialized(A){X(m(this,l),A)}get viewportInitialized(){return d(m(this,c))}set viewportInitialized(A){X(m(this,c),A)}get _edges(){return d(m(this,f))}set _edges(A){X(m(this,f),A)}get nodes(){return this.nodesInitialized,e.nodes}set nodes(A){e.nodes=A}get edges(){return this._edges}set edges(A){e.edges=A}get selectedNodes(){return d(m(this,p))}set selectedNodes(A){X(m(this,p),A)}get selectedEdges(){return d(m(this,u))}set selectedEdges(A){X(m(this,u),A)}get visible(){return d(m(this,h))}set visible(A){X(m(this,h),A)}get nodesDraggable(){return d(m(this,g))}set nodesDraggable(A){X(m(this,g),A)}get nodesConnectable(){return d(m(this,b))}set nodesConnectable(A){X(m(this,b),A)}get elementsSelectable(){return d(m(this,x))}set elementsSelectable(A){X(m(this,x),A)}get nodesFocusable(){return d(m(this,w))}set nodesFocusable(A){X(m(this,w),A)}get edgesFocusable(){return d(m(this,C))}set edgesFocusable(A){X(m(this,C),A)}get disableKeyboardA11y(){return d(m(this,E))}set disableKeyboardA11y(A){X(m(this,E),A)}get minZoom(){return d(m(this,I))}set minZoom(A){X(m(this,I),A)}get maxZoom(){return d(m(this,T))}set maxZoom(A){X(m(this,T),A)}get nodeOrigin(){return d(m(this,B))}set nodeOrigin(A){X(m(this,B),A)}get nodeExtent(){return d(m(this,Z))}set nodeExtent(A){X(m(this,Z),A)}get translateExtent(){return d(m(this,R))}set translateExtent(A){X(m(this,R),A)}get defaultEdgeOptions(){return d(m(this,O))}set defaultEdgeOptions(A){X(m(this,O),A)}get nodeDragThreshold(){return d(m(this,H))}set nodeDragThreshold(A){X(m(this,H),A)}get autoPanOnNodeDrag(){return d(m(this,F))}set autoPanOnNodeDrag(A){X(m(this,F),A)}get autoPanOnConnect(){return d(m(this,$))}set autoPanOnConnect(A){X(m(this,$),A)}get autoPanOnNodeFocus(){return d(m(this,Q))}set autoPanOnNodeFocus(A){X(m(this,Q),A)}get autoPanSpeed(){return d(m(this,y))}set autoPanSpeed(A){X(m(this,y),A)}get connectionDragThreshold(){return d(m(this,S))}set connectionDragThreshold(A){X(m(this,S),A)}get snapGrid(){return d(m(this,k))}set snapGrid(A){X(m(this,k),A)}get dragging(){return d(m(this,D))}set dragging(A){X(m(this,D),A)}get selectionRect(){return d(m(this,J))}set selectionRect(A){X(m(this,J),A)}get selectionKeyPressed(){return d(m(this,W))}set selectionKeyPressed(A){X(m(this,W),A)}get multiselectionKeyPressed(){return d(m(this,j))}set multiselectionKeyPressed(A){X(m(this,j),A)}get deleteKeyPressed(){return d(m(this,ee))}set deleteKeyPressed(A){X(m(this,ee),A)}get panActivationKeyPressed(){return d(m(this,se))}set panActivationKeyPressed(A){X(m(this,se),A)}get zoomActivationKeyPressed(){return d(m(this,de))}set zoomActivationKeyPressed(A){X(m(this,de),A)}get selectionRectMode(){return d(m(this,M))}set selectionRectMode(A){X(m(this,M),A)}get ariaLiveMessage(){return d(m(this,ce))}set ariaLiveMessage(A){X(m(this,ce),A)}get selectionMode(){return d(m(this,ne))}set selectionMode(A){X(m(this,ne),A)}get nodeTypes(){return d(m(this,ie))}set nodeTypes(A){X(m(this,ie),A)}get edgeTypes(){return d(m(this,pe))}set edgeTypes(A){X(m(this,pe),A)}get noPanClass(){return d(m(this,ke))}set noPanClass(A){X(m(this,ke),A)}get noDragClass(){return d(m(this,Qe))}set noDragClass(A){X(m(this,Qe),A)}get noWheelClass(){return d(m(this,Se))}set noWheelClass(A){X(m(this,Se),A)}get ariaLabelConfig(){return d(m(this,ot))}set ariaLabelConfig(A){X(m(this,ot),A)}get _viewport(){return d(m(this,Re))}set _viewport(A){X(m(this,Re),A)}get viewport(){return e.viewport??this._viewport}set viewport(A){e.viewport&&(e.viewport=A),this._viewport=A}get _connection(){return d(m(this,ut))}set _connection(A){X(m(this,ut),A)}get connection(){return d(m(this,Je))}set connection(A){X(m(this,Je),A)}get connectionMode(){return d(m(this,et))}set connectionMode(A){X(m(this,et),A)}get connectionRadius(){return d(m(this,xt))}set connectionRadius(A){X(m(this,xt),A)}get isValidConnection(){return d(m(this,Fe))}set isValidConnection(A){X(m(this,Fe),A)}get selectNodesOnDrag(){return d(m(this,it))}set selectNodesOnDrag(A){X(m(this,it),A)}get defaultMarkerColor(){return d(m(this,tr))}set defaultMarkerColor(A){X(m(this,tr),A)}get markers(){return d(m(this,We))}set markers(A){X(m(this,We),A)}get onlyRenderVisibleElements(){return d(m(this,Sr))}set onlyRenderVisibleElements(A){X(m(this,Sr),A)}get onerror(){return d(m(this,Mr))}set onerror(A){X(m(this,Mr),A)}get ondelete(){return d(m(this,Wr))}set ondelete(A){X(m(this,Wr),A)}get onbeforedelete(){return d(m(this,Vi))}set onbeforedelete(A){X(m(this,Vi),A)}get onbeforeconnect(){return d(m(this,Di))}set onbeforeconnect(A){X(m(this,Di),A)}get onconnect(){return d(m(this,Oi))}set onconnect(A){X(m(this,Oi),A)}get onconnectstart(){return d(m(this,Xi))}set onconnectstart(A){X(m(this,Xi),A)}get onconnectend(){return d(m(this,Mi))}set onconnectend(A){X(m(this,Mi),A)}get onbeforereconnect(){return d(m(this,Wi))}set onbeforereconnect(A){X(m(this,Wi),A)}get onreconnect(){return d(m(this,Hi))}set onreconnect(A){X(m(this,Hi),A)}get onreconnectstart(){return d(m(this,zi))}set onreconnectstart(A){X(m(this,zi),A)}get onreconnectend(){return d(m(this,Yi))}set onreconnectend(A){X(m(this,Yi),A)}get clickConnect(){return d(m(this,Pi))}set clickConnect(A){X(m(this,Pi),A)}get onclickconnectstart(){return d(m(this,Ji))}set onclickconnectstart(A){X(m(this,Ji),A)}get onclickconnectend(){return d(m(this,Wo))}set onclickconnectend(A){X(m(this,Wo),A)}get clickConnectStartHandle(){return d(m(this,Ho))}set clickConnectStartHandle(A){X(m(this,Ho),A)}get onselectiondrag(){return d(m(this,Ar))}set onselectiondrag(A){X(m(this,Ar),A)}get onselectiondragstart(){return d(m(this,zo))}set onselectiondragstart(A){X(m(this,zo),A)}get onselectiondragstop(){return d(m(this,Hr))}set onselectiondragstop(A){X(m(this,Hr),A)}get colorMode(){return d(m(this,Js))}set colorMode(A){X(m(this,Js),A)}resetStoreValues(){this.dragging=!1,this.selectionRect=null,this.selectionRectMode=null,this.selectionKeyPressed=!1,this.multiselectionKeyPressed=!1,this.deleteKeyPressed=!1,this.panActivationKeyPressed=!1,this.zoomActivationKeyPressed=!1,this._connection=pl,this.clickConnectStartHandle=null,this.viewport=e.props.initialViewport??{x:0,y:0,zoom:1},this.ariaLiveMessage=""}}return r=new WeakMap,n=new WeakMap,o=new WeakMap,i=new WeakMap,s=new WeakMap,a=new WeakMap,l=new WeakMap,c=new WeakMap,f=new WeakMap,p=new WeakMap,u=new WeakMap,h=new WeakMap,g=new WeakMap,b=new WeakMap,x=new WeakMap,w=new WeakMap,C=new WeakMap,E=new WeakMap,I=new WeakMap,T=new WeakMap,B=new WeakMap,Z=new WeakMap,R=new WeakMap,O=new WeakMap,H=new WeakMap,F=new WeakMap,$=new WeakMap,Q=new WeakMap,y=new WeakMap,S=new WeakMap,k=new WeakMap,D=new WeakMap,J=new WeakMap,W=new WeakMap,j=new WeakMap,ee=new WeakMap,se=new WeakMap,de=new WeakMap,M=new WeakMap,ce=new WeakMap,ne=new WeakMap,ie=new WeakMap,pe=new WeakMap,ke=new WeakMap,Qe=new WeakMap,Se=new WeakMap,ot=new WeakMap,Re=new WeakMap,ut=new WeakMap,Je=new WeakMap,et=new WeakMap,xt=new WeakMap,Fe=new WeakMap,it=new WeakMap,tr=new WeakMap,We=new WeakMap,Sr=new WeakMap,Mr=new WeakMap,Wr=new WeakMap,Vi=new WeakMap,Di=new WeakMap,Oi=new WeakMap,Xi=new WeakMap,Mi=new WeakMap,Wi=new WeakMap,Hi=new WeakMap,zi=new WeakMap,Yi=new WeakMap,Pi=new WeakMap,Ji=new WeakMap,Wo=new WeakMap,Ho=new WeakMap,Ar=new WeakMap,zo=new WeakMap,Hr=new WeakMap,Js=new WeakMap,new t}var Lp,Up,S0=v(()=>{ae();Ke();wp();s0();a0();l0();Fp();E0();B0();Lp={input:Ip,output:Cp,default:_l,group:Ep},Up={straight:yd,smoothstep:xd,default:Ms,step:wd}});function Qt(){let e=zn(El);if(!e)throw new Error("To call useStore outside of you need to wrap your component in a ");return e.getStore()}var A0=v(()=>{Dr();an()});function N0(e){let t=k0(e);function r(F){t.nodeTypes={...Lp,...F}}function n(F){t.edgeTypes={...Up,...F}}function o(F){t.edges=Fy(F,t.edges)}let i=(F,$=!1)=>{t.nodes=t.nodes.map(Q=>{if(t.connection.inProgress&&t.connection.fromNode.id===Q.id){let S=t.nodeLookup.get(Q.id);S&&(t.connection={...t.connection,from:Vo(S,t.connection.fromHandle,$e.Left,!0)})}let y=F.get(Q.id);return y?{...Q,position:y.position,dragging:$}:Q})};function s(F){let{changes:$,updatedInternals:Q}=Ty(F,t.nodeLookup,t.parentLookup,t.domNode,t.nodeOrigin,t.nodeExtent,t.zIndexMode);if(!Q)return;Ry(t.nodeLookup,t.parentLookup,{nodeOrigin:t.nodeOrigin,nodeExtent:t.nodeExtent,zIndexMode:t.zIndexMode}),t.fitViewQueued&&t.resolveFitView();let y=new Map;for(let S of $){let k=t.nodeLookup.get(S.id)?.internals.userNode;if(!k)continue;let D={...k};switch(S.type){case"dimensions":{let J={...D.measured,...S.dimensions};S.setAttributes&&(D.width=S.dimensions?.width??D.width,D.height=S.dimensions?.height??D.height),D.measured=J;break}case"position":D.position=S.position??D.position;break}y.set(S.id,D)}t.nodes=t.nodes.map(S=>y.get(S.id)??S)}function a(F){let $=t.fitViewResolver??Promise.withResolvers();return t.fitViewQueued=!0,t.fitViewOptions=F,t.fitViewResolver=$,t.nodes=[...t.nodes],$.promise}async function l(F,$,Q){let y=typeof Q?.zoom<"u"?Q.zoom:t.maxZoom,S=t.panZoom;return S?(await S.setViewport({x:t.width/2-F*y,y:t.height/2-$*y,zoom:y},{duration:Q?.duration,ease:Q?.ease,interpolate:Q?.interpolate}),Promise.resolve(!0)):Promise.resolve(!1)}function c(F,$){let Q=t.panZoom;return Q?Q.scaleBy(F,$):Promise.resolve(!1)}function f(F){return c(1.2,F)}function p(F){return c(1/1.2,F)}function u(F){let $=t.panZoom;$&&($.setScaleExtent([F,t.maxZoom]),t.minZoom=F)}function h(F){let $=t.panZoom;$&&($.setScaleExtent([t.minZoom,F]),t.maxZoom=F)}function g(F){let $=t.panZoom;$&&($.setTranslateExtent(F),t.translateExtent=F)}function b(F,$=null){let Q=!1,y=F.map(S=>($?$.has(S.id):!0)&&S.selected?(Q=!0,{...S,selected:!1}):S);return[Q,y]}function x(F){let $=F?.nodes?new Set(F.nodes.map(J=>J.id)):null,[Q,y]=b(t.nodes,$);Q&&(t.nodes=y);let S=F?.edges?new Set(F.edges.map(J=>J.id)):null,[k,D]=b(t.edges,S);k&&(t.edges=D)}function w(F){let $=t.multiselectionKeyPressed;t.nodes=t.nodes.map(Q=>{let y=F.includes(Q.id),S=$&&Q.selected||y;return!!Q.selected!==S?{...Q,selected:S}:Q}),$||x({nodes:[]})}function C(F){let $=t.multiselectionKeyPressed;t.edges=t.edges.map(Q=>{let y=F.includes(Q.id),S=$&&Q.selected||y;return!!Q.selected!==S?{...Q,selected:S}:Q}),$||x({edges:[]})}function E(F,$,Q){let y=t.nodeLookup.get(F);if(!y){console.warn("012",Gi.error012(F));return}t.selectionRect=null,t.selectionRectMode=null,y.selected?($||y.selected&&t.multiselectionKeyPressed)&&(x({nodes:[y],edges:[]}),requestAnimationFrame(()=>Q?.blur())):w([F])}function I(F){let $=t.edgeLookup.get(F);if(!$){console.warn("012",Gi.error012(F));return}($.selectable||t.elementsSelectable&&typeof $.selectable>"u")&&(t.selectionRect=null,t.selectionRectMode=null,$.selected?$.selected&&t.multiselectionKeyPressed&&x({nodes:[],edges:[$]}):C([F]))}function T(F,$){let{nodeExtent:Q,snapGrid:y,nodeOrigin:S,nodeLookup:k,nodesDraggable:D,onerror:J}=t,W=new Map,j=y?.[0]??5,ee=y?.[1]??5,se=F.x*j*$,de=F.y*ee*$;for(let M of k.values()){if(!(M.selected&&(M.draggable||D&&typeof M.draggable>"u")))continue;let ne={x:M.internals.positionAbsolute.x+se,y:M.internals.positionAbsolute.y+de};y&&(ne=Vs(ne,y));let{position:ie,positionAbsolute:pe}=dp({nodeId:M.id,nextPosition:ne,nodeLookup:k,nodeExtent:Q,nodeOrigin:S,onError:J});M.position=ie,M.internals.positionAbsolute=pe,W.set(M.id,M)}i(W)}function B(F){return Vy({delta:F,panZoom:t.panZoom,transform:[t.viewport.x,t.viewport.y,t.viewport.zoom],translateExtent:t.translateExtent,width:t.width,height:t.height})}let Z=F=>{t._connection={...F}};function R(){t._connection=pl}function O(){t.resetStoreValues(),x()}return Object.assign(t,{setNodeTypes:r,setEdgeTypes:n,addEdge:o,updateNodePositions:i,updateNodeInternals:s,zoomIn:f,zoomOut:p,fitView:a,setCenter:l,setMinZoom:u,setMaxZoom:h,setTranslateExtent:g,unselectNodesAndEdges:x,addSelectedNodes:w,addSelectedEdges:C,handleNodeSelection:E,handleEdgeSelection:I,moveSelectedNodes:T,panBy:B,updateConnection:Z,cancelConnection:R,reset:O})}var El,an=v(()=>{Ke();S0();A0();El=Symbol()});function Tp(e,t){let{minZoom:r,maxZoom:n,initialViewport:o,onPanZoomStart:i,onPanZoom:s,onPanZoomEnd:a,translateExtent:l,setPanZoomInstance:c,onDraggingChange:f,onTransformChange:p}=t,u=jy({domNode:e,minZoom:r,maxZoom:n,translateExtent:l,viewport:o,onPanZoom:s,onPanZoomStart:i,onPanZoomEnd:a,onDraggingChange:f}),h=u.getViewport();return(o.x!==h.x||o.y!==h.y||o.zoom!==h.zoom)&&p([h.x,h.y,h.zoom]),c(u),u.update(t),{update(g){u.update(g)}}}var F0=v(()=>{Ke()});function Ed(e,t){K(t,!0);let r=z(t,"store",15),n=_(()=>r().panActivationKeyPressed||t.panOnDrag),o=_(()=>r().panActivationKeyPressed||t.panOnScroll),{viewport:i}=r(),s=!1;ct(()=>{!s&&r().viewportInitialized&&(t.oninit?.(),s=!0)});var a=JB(),l=V(a);dt(l,()=>t.children),L(a),gt(a,(c,f)=>Tp?.(c,f),()=>({viewport:r().viewport,minZoom:r().minZoom,maxZoom:r().maxZoom,initialViewport:i,onDraggingChange:c=>{r(r().dragging=c,!0)},setPanZoomInstance:c=>{r(r().panZoom=c,!0)},onPanZoomStart:t.onmovestart,onPanZoom:t.onmove,onPanZoomEnd:t.onmoveend,zoomOnScroll:t.zoomOnScroll,zoomOnDoubleClick:t.zoomOnDoubleClick,zoomOnPinch:t.zoomOnPinch,panOnScroll:d(o),panOnDrag:d(n),panOnScrollSpeed:t.panOnScrollSpeed,panOnScrollMode:t.panOnScrollMode,zoomActivationKeyPressed:r().zoomActivationKeyPressed,preventScrolling:typeof t.preventScrolling=="boolean"?t.preventScrolling:!0,noPanClassName:r().noPanClass,noWheelClassName:r().noWheelClass,userSelectionActive:!!r().selectionRect,translateExtent:r().translateExtent,lib:"svelte",paneClickDistance:t.paneClickDistance,selectionOnDrag:t.selectionOnDrag,onTransformChange:c=>{r(r().viewport={x:c[0],y:c[1],zoom:c[2]},!0)},connectionInProgress:r().connection.inProgress})),N(e,a),q()}var JB,G0=v(()=>{_e();ae();F0();JB=Y('
')});var Z0=v(()=>{G0()});function Q0(e,t){return r=>{r.target===t&&e?.(r)}}function R0(e){return t=>{let r=e.has(t.id);return!!t.selected!==r?{...t,selected:r}:t}}function L0(e,t){if(e.size!==t.size)return!1;for(let r of e)if(!t.has(r))return!1;return!0}function $d(e,t){K(t,!0);let r=z(t,"store",15),n=z(t,"panOnDrag",3,!0),o=z(t,"paneClickDistance",3,1),i,s=null,a=new Set,l=new Set,c=_(()=>r().panActivationKeyPressed||n()),f=_(()=>r().selectionKeyPressed||!!r().selectionRect||t.selectionOnDrag&&d(c)!==!0),p=_(()=>r().elementsSelectable&&(d(f)||r().selectionRectMode==="user")),u=!1;function h(R){if(s=i?.getBoundingClientRect(),!s)return;let O=R.target===i,H=!O&&!!R.target.closest(".nokey"),F=t.selectionOnDrag&&O||r().selectionKeyPressed;if(H||!d(f)||!F||R.button!==0||!R.isPrimary)return;R.target?.setPointerCapture?.(R.pointerId),u=!1;let{x:$,y:Q}=sn(R,s);r(r().selectionRect={width:0,height:0,startX:$,startY:Q,x:$,y:Q},!0),O||(R.stopPropagation(),R.preventDefault())}function g(R){if(!d(f)||!s||!r().selectionRect)return;let O=sn(R,s),{startX:H=0,startY:F=0}=r().selectionRect;if(!u){let k=r().selectionKeyPressed?0:o();if(Math.hypot(O.x-H,O.y-F)<=k)return;r().unselectNodesAndEdges(),t.onselectionstart?.(R)}u=!0;let $={...r().selectionRect,x:O.xk.id));let S=r().defaultEdgeOptions.selectable??!0;l=new Set;for(let k of a){let D=r().connectionLookup.get(k);if(D)for(let{edgeId:J}of D.values()){let W=r().edgeLookup.get(J);W&&(W.selectable??S)&&l.add(J)}}L0(Q,a)||r(r().nodes=r().nodes.map(R0(a)),!0),L0(y,l)||r(r().edges=r().edges.map(R0(l)),!0),r(r().selectionRectMode="user",!0),r(r().selectionRect=$,!0)}function b(R){R.button===0&&(R.target?.releasePointerCapture?.(R.pointerId),!u&&R.target===i&&C?.(R),r(r().selectionRect=null,!0),u&&r(r().selectionRectMode=a.size>0?"nodes":null,!0),u&&t.onselectionend?.(R))}let x=R=>{if(Array.isArray(d(c))&&d(c).includes(2)){R.preventDefault();return}t.onpanecontextmenu?.({event:R})},w=R=>{u&&(R.stopPropagation(),u=!1)};function C(R){if(u||r().connection.inProgress){u=!1;return}t.onpaneclick?.({event:R}),r().unselectNodesAndEdges(),r(r().selectionRectMode=null,!0),r(r().selectionRect=null,!0)}var E=jB();let I;var T=_(()=>d(p)?void 0:Q0(C,i)),B=_(()=>Q0(x,i)),Z=V(E);dt(Z,()=>t.children),L(E),Xr(E,R=>i=R,()=>i),te(R=>I=Pe(E,1,"svelte-flow__pane svelte-flow__container",null,I,R),[()=>({draggable:n()===!0||Array.isArray(n())&&n().includes(0),dragging:r().dragging,selection:d(f)})]),Pt("click",E,function(...R){d(T)?.apply(this,R)}),mi("pointerdown",E,function(...R){(d(p)?h:void 0)?.apply(this,R)},!0),Pt("pointermove",E,function(...R){(d(p)?g:void 0)?.apply(this,R)}),Pt("pointerup",E,function(...R){(d(p)?b:void 0)?.apply(this,R)}),Pt("contextmenu",E,function(...R){d(B)?.apply(this,R)}),mi("click",E,function(...R){(d(p)?w:void 0)?.apply(this,R)},!0),N(e,E),q()}var jB,U0=v(()=>{_e();ae();Ke();jB=Y("
");oo(["click","pointermove","pointerup","contextmenu"])});var T0=v(()=>{});var V0=v(()=>{U0();T0()});function Bd(e,t){K(t,!0);var r=KB();let n;var o=V(r);dt(o,()=>t.children),L(r),te(()=>n=nt(r,"",n,{transform:`translate(${t.store.viewport.x??""}px, ${t.store.viewport.y??""}px) scale(${t.store.viewport.zoom??""})`})),N(e,r),q()}var KB,D0=v(()=>{_e();ae();KB=Y('
')});var O0=v(()=>{D0()});function $l(e,t){let{store:r,onDrag:n,onDragStart:o,onDragStop:i,onNodeMouseDown:s}=t,a=Xy({onDrag:n,onDragStart:o,onDragStop:i,onNodeMouseDown:s,getStoreItems:()=>{let{snapGrid:c,viewport:f}=r;return{nodes:r.nodes,nodeLookup:r.nodeLookup,edges:r.edges,nodeExtent:r.nodeExtent,snapGrid:c||[0,0],snapToGrid:!!c,nodeOrigin:r.nodeOrigin,multiSelectionActive:r.multiselectionKeyPressed,domNode:r.domNode,transform:[f.x,f.y,f.zoom],autoPanOnNodeDrag:r.autoPanOnNodeDrag,nodesDraggable:r.nodesDraggable,selectNodesOnDrag:r.selectNodesOnDrag,nodeDragThreshold:r.nodeDragThreshold,unselectNodesAndEdges:r.unselectNodesAndEdges,updateNodePositions:r.updateNodePositions,onSelectionDrag:r.onselectiondrag,onSelectionDragStart:r.onselectiondragstart,onSelectionDragStop:r.onselectiondragstop,panBy:r.panBy}}});function l(c,f){if(f.disabled){a.destroy();return}a.update({domNode:c,noDragClassName:f.noDragClass,handleSelector:f.handleSelector,nodeId:f.nodeId,isSelectable:f.isSelectable,nodeClickDistance:f.nodeClickDistance})}return l(e,t),{update(c){l(e,c)},destroy(){a.destroy()}}}var Vp=v(()=>{Ke()});var X0=v(()=>{});function kd(e,t){K(t,!0);var r=ek(),n=ve(r),o=V(n,!0);L(n);var i=P(n,2),s=V(i,!0);L(i);var a=P(i,2);{var l=c=>{var f=qB(),p=V(f,!0);L(f),te(()=>{re(f,"id",`${W0}-${t.store.flowId}`),he(p,t.store.ariaLiveMessage)}),N(c,f)};ue(a,c=>{t.store.disableKeyboardA11y||c(l)})}te(()=>{re(n,"id",`${Sd}-${t.store.flowId}`),he(o,t.store.disableKeyboardA11y?t.store.ariaLabelConfig["node.a11yDescription.default"]:t.store.ariaLabelConfig["node.a11yDescription.keyboardDisabled"]),re(i,"id",`${Ad}-${t.store.flowId}`),he(s,t.store.ariaLabelConfig["edge.a11yDescription.default"])}),N(e,r),q()}var qB,ek,M0=v(()=>{_e();ae();Bl();X0();qB=Y('
'),ek=Y('
',1)});var Sd,Ad,W0,Bl=v(()=>{M0();Sd="svelte-flow__node-desc",Ad="svelte-flow__edge-desc",W0="svelte-flow__aria-live"});function Nd(e,t){K(t,!0);let r=z(t,"store",15),n=_(()=>Rt(t.node.data,()=>({}),!0)),o=_(()=>Rt(t.node.selected,!1)),i=_(()=>t.node.draggable),s=_(()=>t.node.selectable),a=_(()=>Rt(t.node.deletable,!0)),l=_(()=>t.node.connectable),c=_(()=>t.node.focusable),f=_(()=>Rt(t.node.hidden,!1)),p=_(()=>Rt(t.node.dragging,!1)),u=_(()=>Rt(t.node.style,"")),h=_(()=>t.node.class),g=_(()=>Rt(t.node.type,"default")),b=_(()=>t.node.parentId),x=_(()=>t.node.sourcePosition),w=_(()=>t.node.targetPosition),C=_(()=>Rt(t.node.measured,()=>({width:0,height:0}),!0).width),E=_(()=>Rt(t.node.measured,()=>({width:0,height:0}),!0).height),I=_(()=>t.node.initialWidth),T=_(()=>t.node.initialHeight),B=_(()=>t.node.width),Z=_(()=>t.node.height),R=_(()=>t.node.dragHandle),O=_(()=>Rt(t.node.internals.z,0)),H=_(()=>t.node.internals.positionAbsolute.x),F=_(()=>t.node.internals.positionAbsolute.y),$=_(()=>t.node.internals.userNode),{id:Q}=t.node,y=_(()=>d(i)??r().nodesDraggable),S=_(()=>d(s)??r().elementsSelectable),k=_(()=>d(l)??r().nodesConnectable),D=_(()=>hd(t.node)),J=_(()=>!!t.node.internals.handleBounds),W=_(()=>d(D)&&d(J)),j=_(()=>d(c)??r().nodesFocusable);function ee(Fe){return r().parentLookup.has(Fe)}let se=_(()=>ee(Q)),de=we(null),M=null,ce=d(g),ne=d(x),ie=d(w),pe=_(()=>r().nodeTypes[d(g)]??_l),ke=_(()=>r().ariaLabelConfig),Qe={get value(){return d(k)}};qy(Q),t0(Qe);let Se=_(()=>{let Fe=d(C)===void 0?d(B)??d(I):d(B),it=d(E)===void 0?d(Z)??d(T):d(Z);if(!(Fe===void 0&&it===void 0&&d(u)===void 0))return`${d(u)};${Fe?`width:${xr(Fe)};`:""}${it?`height:${xr(it)};`:""}`});ct(()=>{(d(g)!==ce||d(x)!==ne||d(w)!==ie)&&d(de)!==null&&requestAnimationFrame(()=>{d(de)!==null&&r().updateNodeInternals(new Map([[Q,{id:Q,nodeElement:d(de),force:!0}]]))}),ce=d(g),ne=d(x),ie=d(w)}),ct(()=>{t.resizeObserver&&(!d(W)||d(de)!==M)&&(M&&t.resizeObserver.unobserve(M),d(de)&&t.resizeObserver.observe(d(de)),M=d(de))}),ao(()=>{M&&t.resizeObserver?.unobserve(M)});function ot(Fe){d(S)&&(!r().selectNodesOnDrag||!d(y)||r().nodeDragThreshold>0)&&r().handleNodeSelection(Q),t.onnodeclick?.({node:d($),event:Fe})}function Re(Fe){if(!(gd(Fe)||r().disableKeyboardA11y))if(ud.includes(Fe.key)&&d(S)){let it=Fe.key==="Escape";r().handleNodeSelection(Q,it,d(de))}else d(y)&&t.node.selected&&Object.prototype.hasOwnProperty.call(Xs,Fe.key)&&(Fe.preventDefault(),r(r().ariaLiveMessage=d(ke)["node.a11yDescription.ariaLiveMessage"]({direction:Fe.key.replace("Arrow","").toLowerCase(),x:~~t.node.internals.positionAbsolute.x,y:~~t.node.internals.positionAbsolute.y}),!0),r().moveSelectedNodes(Xs[Fe.key],Fe.shiftKey?4:1))}let ut=()=>{if(r().disableKeyboardA11y||!r().autoPanOnNodeFocus||!d(de)?.matches(":focus-visible"))return;let{width:Fe,height:it,viewport:tr}=r();Us(new Map([[Q,t.node]]),{x:0,y:0,width:Fe,height:it},[tr.x,tr.y,tr.zoom],!0).length>0||r().setCenter(t.node.position.x+(t.node.measured.width??0)/2,t.node.position.y+(t.node.measured.height??0)/2,{zoom:tr.zoom})};var Je=Ve(),et=ve(Je);{var xt=Fe=>{var it=tk();jt(it,()=>({"data-id":Q,class:["svelte-flow__node",`svelte-flow__node-${d(g)}`,d(h)],style:d(Se),onclick:ot,onpointerenter:t.onnodepointerenter?We=>t.onnodepointerenter({node:d($),event:We}):void 0,onpointerleave:t.onnodepointerleave?We=>t.onnodepointerleave({node:d($),event:We}):void 0,onpointermove:t.onnodepointermove?We=>t.onnodepointermove({node:d($),event:We}):void 0,oncontextmenu:t.onnodecontextmenu?We=>t.onnodecontextmenu({node:d($),event:We}):void 0,onkeydown:d(j)?Re:void 0,onfocus:d(j)?ut:void 0,tabIndex:d(j)?0:void 0,role:t.node.ariaRole??(d(j)?"group":void 0),"aria-roledescription":"node","aria-describedby":r().disableKeyboardA11y?void 0:`${Sd}-${r().flowId}`,...t.node.domAttributes,[nn]:{dragging:d(p),selected:d(o),draggable:d(y),connectable:d(k),selectable:d(S),nopan:d(y),parent:d(se)},[Er]:{"z-index":d(O),transform:`translate(${d(H)??""}px, ${d(F)??""}px)`,visibility:d(D)?"visible":"hidden"}}));var tr=V(it);io(tr,()=>d(pe),(We,Sr)=>{Sr(We,{get data(){return d(n)},get id(){return Q},get selected(){return d(o)},get selectable(){return d(S)},get deletable(){return d(a)},get sourcePosition(){return d(x)},get targetPosition(){return d(w)},get zIndex(){return d(O)},get dragging(){return d(p)},get draggable(){return d(y)},get dragHandle(){return d(R)},get parentId(){return d(b)},get type(){return d(g)},get isConnectable(){return d(k)},get positionAbsoluteX(){return d(H)},get positionAbsoluteY(){return d(F)},get width(){return d(B)},get height(){return d(Z)}})}),L(it),gt(it,(We,Sr)=>$l?.(We,Sr),()=>({nodeId:Q,isSelectable:d(S),disabled:!d(y),handleSelector:d(R),noDragClass:r().noDragClass,nodeClickDistance:t.nodeClickDistance,onNodeMouseDown:r().handleNodeSelection,onDrag:(We,Sr,Mr,Wr)=>{t.onnodedrag?.({event:We,targetNode:Mr,nodes:Wr})},onDragStart:(We,Sr,Mr,Wr)=>{t.onnodedragstart?.({event:We,targetNode:Mr,nodes:Wr})},onDragStop:(We,Sr,Mr,Wr)=>{t.onnodedragstop?.({event:We,targetNode:Mr,nodes:Wr})},store:r()})),Xr(it,We=>X(de,We),()=>d(de)),N(Fe,it)};ue(et,Fe=>{d(f)||Fe(xt)})}N(e,Je),q()}var tk,H0=v(()=>{_e();ae();Dr();Ke();Vp();ml();Oo();Bl();wp();tk=Y("
")});var z0=v(()=>{H0()});function Fd(e,t){K(t,!0);let r=z(t,"store",15),n=typeof ResizeObserver>"u"?null:new ResizeObserver(i=>{let s=new Map;i.forEach(a=>{let l=a.target.getAttribute("data-id");s.set(l,{id:l,nodeElement:a.target,force:!0})}),r().updateNodeInternals(s)});ao(()=>{n?.disconnect()});var o=rk();Xe(o,21,()=>r().visible.nodes.values(),i=>i.id,(i,s)=>{Nd(i,{get node(){return d(s)},get resizeObserver(){return n},get nodeClickDistance(){return t.nodeClickDistance},get onnodeclick(){return t.onnodeclick},get onnodepointerenter(){return t.onnodepointerenter},get onnodepointermove(){return t.onnodepointermove},get onnodepointerleave(){return t.onnodepointerleave},get onnodedrag(){return t.onnodedrag},get onnodedragstart(){return t.onnodedragstart},get onnodedragstop(){return t.onnodedragstop},get onnodecontextmenu(){return t.onnodecontextmenu},get store(){return r()},set store(a){r(a)}})}),L(o),N(e,o),q()}var rk,Y0=v(()=>{_e();ae();Dr();z0();rk=Y('
')});var P0=v(()=>{Y0()});function Gd(e,t){K(t,!0);let r=_(()=>t.edge.id),n=_(()=>t.edge.source),o=_(()=>t.edge.target),i=_(()=>t.edge.sourceX),s=_(()=>t.edge.sourceY),a=_(()=>t.edge.targetX),l=_(()=>t.edge.targetY),c=_(()=>t.edge.sourcePosition),f=_(()=>t.edge.targetPosition),p=_(()=>Rt(t.edge.animated,!1)),u=_(()=>Rt(t.edge.selected,!1)),h=_(()=>t.edge.label),g=_(()=>t.edge.labelStyle),b=_(()=>Rt(t.edge.data,()=>({}),!0)),x=_(()=>t.edge.style),w=_(()=>t.edge.interactionWidth),C=_(()=>Rt(t.edge.type,"default")),E=_(()=>t.edge.sourceHandle),I=_(()=>t.edge.targetHandle),T=_(()=>t.edge.markerStart),B=_(()=>t.edge.markerEnd),Z=_(()=>t.edge.selectable),R=_(()=>t.edge.focusable),O=_(()=>Rt(t.edge.deletable,!0)),H=_(()=>t.edge.hidden),F=_(()=>t.edge.zIndex),$=_(()=>t.edge.class),Q=_(()=>t.edge.ariaLabel);n0(d(r));let y=null,S=_(()=>d(Z)??t.store.elementsSelectable),k=_(()=>d(R)??t.store.edgesFocusable),D=_(()=>t.store.edgeTypes[d(C)]??Ms),J=_(()=>d(T)?`url('#${_d(d(T),t.store.flowId)}')`:void 0),W=_(()=>d(B)?`url('#${_d(d(B),t.store.flowId)}')`:void 0);function j(ne){let ie=t.store.edgeLookup.get(d(r));ie&&(d(S)&&t.store.handleEdgeSelection(d(r)),t.onedgeclick?.({event:ne,edge:ie}))}function ee(ne,ie){let pe=t.store.edgeLookup.get(d(r));pe&&ie({event:ne,edge:pe})}function se(ne){if(!t.store.disableKeyboardA11y&&ud.includes(ne.key)&&d(S)){let{unselectNodesAndEdges:ie,addSelectedEdges:pe}=t.store;ne.key==="Escape"?(y?.blur(),ie({edges:[t.edge]})):pe([d(r)])}}var de=Ve(),M=ve(de);{var ce=ne=>{var ie=nk();let pe;var ke=V(ie);jt(ke,()=>({class:["svelte-flow__edge",d($)],"data-id":d(r),onclick:j,oncontextmenu:t.onedgecontextmenu?Se=>{ee(Se,t.onedgecontextmenu)}:void 0,onpointerenter:t.onedgepointerenter?Se=>{ee(Se,t.onedgepointerenter)}:void 0,onpointerleave:t.onedgepointerleave?Se=>{ee(Se,t.onedgepointerleave)}:void 0,"aria-label":d(Q)===null?void 0:d(Q)?d(Q):`Edge from ${d(n)} to ${d(o)}`,"aria-describedby":d(k)?`${Ad}-${t.store.flowId}`:void 0,role:t.edge.ariaRole??(d(k)?"group":"img"),"aria-roledescription":"edge",onkeydown:d(k)?se:void 0,tabindex:d(k)?0:void 0,...t.edge.domAttributes,[nn]:{animated:d(p),selected:d(u),selectable:d(S)}}));var Qe=V(ke);io(Qe,()=>d(D),(Se,ot)=>{ot(Se,{get id(){return d(r)},get source(){return d(n)},get target(){return d(o)},get sourceX(){return d(i)},get sourceY(){return d(s)},get targetX(){return d(a)},get targetY(){return d(l)},get sourcePosition(){return d(c)},get targetPosition(){return d(f)},get animated(){return d(p)},get selected(){return d(u)},get label(){return d(h)},get labelStyle(){return d(g)},get data(){return d(b)},get style(){return d(x)},get interactionWidth(){return d(w)},get selectable(){return d(S)},get deletable(){return d(O)},get type(){return d(C)},get sourceHandleId(){return d(E)},get targetHandleId(){return d(I)},get markerStart(){return d(J)},get markerEnd(){return d(W)}})}),L(ke),Xr(ke,Se=>y=Se,()=>y),L(ie),te(()=>pe=nt(ie,"",pe,{"z-index":d(F)})),N(ne,ie)};ue(M,ne=>{d(H)||ne(ce)})}N(e,de),q()}var nk,J0=v(()=>{_e();ae();Ke();ml();Fp();Bl();nk=Ze('')});var j0=v(()=>{J0()});var Xo=v(()=>{lr();_g()});function Zd(e,t){K(t,!1);let r=Qt();vf();var n=ok();Xe(n,5,()=>r.markers,o=>o.id,(o,i)=>{Qd(o,wn(()=>d(i)))}),L(n),N(e,n),q()}var ok,K0=v(()=>{_e();Xo();ae();an();Dp();ok=Ze("")});function Qd(e,t){K(t,!0);let r=z(t,"width",3,12.5),n=z(t,"height",3,12.5),o=z(t,"markerUnits",3,"strokeWidth"),i=z(t,"orient",3,"auto-start-reverse"),s=z(t,"color",3,"none");var a=ak(),l=V(a);{var c=p=>{var u=ik();let h;te(()=>{re(u,"stroke-width",t.strokeWidth),h=nt(u,"",h,{stroke:s()})}),N(p,u)},f=p=>{var u=sk();let h;te(()=>{re(u,"stroke-width",t.strokeWidth),h=nt(u,"",h,{stroke:s(),fill:s()})}),N(p,u)};ue(l,p=>{t.type===ul.Arrow?p(c):t.type===ul.ArrowClosed&&p(f,1)})}L(a),te(()=>{re(a,"id",t.id),re(a,"markerWidth",`${r()}`),re(a,"markerHeight",`${n()}`),re(a,"markerUnits",o()),re(a,"orient",i())}),N(e,a),q()}var ik,sk,ak,q0=v(()=>{_e();ae();Ke();ik=Ze(''),sk=Ze(''),ak=Ze('')});var Dp=v(()=>{K0();q0()});function Rd(e,t){K(t,!0);let r=z(t,"store",15);var n=lk(),o=V(n),i=V(o);Zd(i,{}),L(o);var s=P(o,2);Xe(s,17,()=>r().visible.edges.values(),a=>a.id,(a,l)=>{Gd(a,{get edge(){return d(l)},get onedgeclick(){return t.onedgeclick},get onedgecontextmenu(){return t.onedgecontextmenu},get onedgepointerenter(){return t.onedgepointerenter},get onedgepointerleave(){return t.onedgepointerleave},get store(){return r()},set store(c){r(c)}})}),L(n),N(e,n),q()}var lk,ew=v(()=>{_e();ae();j0();Dp();lk=Y('
')});var tw=v(()=>{ew()});var rw=v(()=>{});function Ws(e,t){K(t,!0);let r=z(t,"x",3,0),n=z(t,"y",3,0),o=z(t,"width",3,0),i=z(t,"height",3,0),s=z(t,"isVisible",3,!0);var a=Ve(),l=ve(a);{var c=f=>{var p=ck();let u;te(h=>u=nt(p,"",u,h),[()=>({width:typeof o()=="string"?o():xr(o()),height:typeof i()=="string"?i():xr(i()),transform:`translate(${r()}px, ${n()}px)`})]),N(f,p)};ue(l,f=>{s()&&f(c)})}N(e,a),q()}var ck,nw=v(()=>{_e();ae();Oo();rw();ck=Y('
')});var Op=v(()=>{nw()});var ow=v(()=>{});function Ld(e,t){K(t,!0);let r=we(void 0);ct(()=>{t.store.disableKeyboardA11y||d(r)?.focus({preventScroll:!0})});let n=_(()=>{if(t.store.selectionRectMode==="nodes"){t.store.nodes;let p=Do(t.store.nodeLookup,{filter:u=>!!u.selected});if(p.width>0&&p.height>0)return p}return null});function o(p){let u=t.store.nodes.filter(h=>h.selected);t.onselectioncontextmenu?.({nodes:u,event:p})}function i(p){let u=t.store.nodes.filter(h=>h.selected);t.onselectionclick?.({nodes:u,event:p})}function s(p){Object.prototype.hasOwnProperty.call(Xs,p.key)&&(p.preventDefault(),t.store.moveSelectedNodes(Xs[p.key],p.shiftKey?4:1))}var a=Ve(),l=ve(a);{var c=p=>{var u=dk();let h;var g=V(u);Ws(g,{width:"100%",height:"100%",x:0,y:0}),L(u),gt(u,(b,x)=>$l?.(b,x),()=>({disabled:!1,store:t.store,onDrag:(b,x,w,C)=>{t.onnodedrag?.({event:b,targetNode:null,nodes:C})},onDragStart:(b,x,w,C)=>{t.onnodedragstart?.({event:b,targetNode:null,nodes:C})},onDragStop:(b,x,w,C)=>{t.onnodedragstop?.({event:b,targetNode:null,nodes:C})}})),Xr(u,b=>X(r,b),()=>d(r)),te(b=>{Pe(u,1,Jt(["svelte-flow__selection-wrapper",t.store.noPanClass]),"svelte-sf2y5e"),re(u,"role",t.store.disableKeyboardA11y?void 0:"button"),re(u,"tabindex",t.store.disableKeyboardA11y?void 0:-1),h=nt(u,"",h,b)},[()=>({width:xr(d(n).width),height:xr(d(n).height),transform:`translate(${d(n).x??""}px, ${d(n).y??""}px)`})]),Pt("contextmenu",u,o),Pt("click",u,i),Pt("keydown",u,function(...b){(t.store.disableKeyboardA11y?void 0:s)?.apply(this,b)}),N(p,u)},f=_(()=>t.store.selectionRectMode==="nodes"&&d(n)&&Vn(d(n).x)&&Vn(d(n).y));ue(l,p=>{d(f)&&p(c)})}N(e,a),q()}var dk,iw=v(()=>{_e();ae();Ke();Op();Vp();Oo();ow();dk=Y("
");oo(["contextmenu","click","keydown"])});var sw=v(()=>{iw()});function uk(e){switch(e){case"ctrl":return 8;case"shift":return 4;case"alt":return 2;case"meta":return 1}}function ln(e,t){let{enabled:r=!0,trigger:n,type:o="keydown"}=t;function i(a){let l=Array.isArray(n)?n:[n],c=[a.metaKey,a.altKey,a.shiftKey,a.ctrlKey].reduce((f,p,u)=>p?f|1<0){let C=Array.isArray(u)?u:[u],E=!1;for(let I of C)if((Array.isArray(I)?I:[I]).reduce((B,Z)=>B|uk(Z),0)===c){E=!0;break}if(!E)continue}b&&a.preventDefault();let w={node:e,trigger:p,originalEvent:a};e.dispatchEvent(new CustomEvent("shortcut",{detail:w})),g?.(w)}}}let s;return r&&(s=gi(e,o,i)),{update:a=>{let{enabled:l=!0,type:c="keydown"}=a;r&&(!l||o!==c)?s?.():!r&&l&&(s=gi(e,c,i)),r=l,o=c,n=a.trigger},destroy:()=>{s?.()}}}var aw=v(()=>{Qp()});var lw=v(()=>{});var cw=v(()=>{aw();lw()});function uw(){let e=_(Qt),t=i=>{let s=Ap(i)?i:d(e).nodeLookup.get(i.id),a=s.parentId?$y(s.position,s.measured,s.parentId,d(e).nodeLookup,d(e).nodeOrigin):s.position,l={...s,position:a,width:s.measured?.width??s.width,height:s.measured?.height??s.height};return Qi(l)};function r(i,s,a={replace:!1}){d(e).nodes=Ge(()=>d(e).nodes).map(l=>{if(l.id===i){let c=typeof s=="function"?s(l):s;return a?.replace&&Ap(c)?c:{...l,...c}}return l})}function n(i,s,a={replace:!1}){d(e).edges=Ge(()=>d(e).edges).map(l=>{if(l.id===i){let c=typeof s=="function"?s(l):s;return a.replace&&u0(c)?c:{...l,...c}}return l})}let o=i=>d(e).nodeLookup.get(i);return{zoomIn:d(e).zoomIn,zoomOut:d(e).zoomOut,getInternalNode:o,getNode:i=>o(i)?.internals.userNode,getNodes:i=>i===void 0?d(e).nodes:dw(d(e).nodeLookup,i),getEdge:i=>d(e).edgeLookup.get(i),getEdges:i=>i===void 0?d(e).edges:dw(d(e).edgeLookup,i),setZoom:(i,s)=>{let a=d(e).panZoom;return a?a.scaleTo(i,s):Promise.resolve(!1)},getZoom:()=>d(e).viewport.zoom,setViewport:async(i,s)=>{let a=d(e).viewport;return d(e).panZoom?(await d(e).panZoom.setViewport({x:i.x??a.x,y:i.y??a.y,zoom:i.zoom??a.zoom},s),Promise.resolve(!0)):Promise.resolve(!1)},getViewport:()=>Wn(d(e).viewport),setCenter:async(i,s,a)=>d(e).setCenter(i,s,a),fitView:i=>d(e).fitView(i),fitBounds:async(i,s)=>{if(!d(e).panZoom)return Promise.resolve(!1);let a=gl(i,d(e).width,d(e).height,d(e).minZoom,d(e).maxZoom,s?.padding??.1);return await d(e).panZoom.setViewport(a,{duration:s?.duration,ease:s?.ease,interpolate:s?.interpolate}),Promise.resolve(!0)},getIntersectingNodes:(i,s=!0,a)=>{let l=fp(i),c=l?i:t(i);return c?(a||d(e).nodes).filter(f=>{let p=d(e).nodeLookup.get(f.id);if(!p||!l&&f.id===i.id)return!1;let u=Qi(p),h=Ts(u,c);return s&&h>0||h>=u.width*u.height||h>=c.width*c.height}):[]},isNodeIntersecting:(i,s,a=!0)=>{let c=fp(i)?i:t(i);if(!c)return!1;let f=Ts(c,s);return a&&f>0||f>=s.width*s.height||f>=c.width*c.height},deleteElements:async({nodes:i=[],edges:s=[]})=>{let{nodes:a,edges:l}=await Iy({nodesToRemove:i,edgesToRemove:s,nodes:d(e).nodes,edges:d(e).edges,onBeforeDelete:d(e).onbeforedelete});return a&&(d(e).nodes=Ge(()=>d(e).nodes).filter(c=>!a.some(({id:f})=>f===c.id))),l&&(d(e).edges=Ge(()=>d(e).edges).filter(c=>!l.some(({id:f})=>f===c.id))),(a.length>0||l.length>0)&&d(e).ondelete?.({nodes:a,edges:l}),{deletedNodes:a,deletedEdges:l}},screenToFlowPosition:(i,s={snapToGrid:!0})=>{if(!d(e).domNode)return i;let a=s.snapToGrid?d(e).snapGrid:!1,{x:l,y:c,zoom:f}=d(e).viewport,{x:p,y:u}=d(e).domNode.getBoundingClientRect(),h={x:i.x-p,y:i.y-u};return Ri(h,[l,c,f],a!==null,a||[1,1])},flowToScreenPosition:i=>{if(!d(e).domNode)return i;let{x:s,y:a,zoom:l}=d(e).viewport,{x:c,y:f}=d(e).domNode.getBoundingClientRect(),p=fl(i,[s,a,l]);return{x:p.x+c,y:p.y+f}},toObject:()=>structuredClone({nodes:[...d(e).nodes],edges:[...d(e).edges],viewport:{...d(e).viewport}}),updateNode:r,updateNodeData:(i,s,a)=>{let l=d(e).nodeLookup.get(i)?.internals.userNode;if(!l)return;let c=typeof s=="function"?s(l):s;r(i,f=>({...f,data:a?.replace?c:{...f.data,...c}}))},updateEdge:n,getNodesBounds:i=>yy(i,{nodeLookup:d(e).nodeLookup,nodeOrigin:d(e).nodeOrigin}),getHandleConnections:({type:i,id:s,nodeId:a})=>Array.from(d(e).connectionLookup.get(`${a}-${i}-${s??null}`)?.values()??[])}}function dw(e,t){let r=[];for(let n of t){let o=e.get(n);if(o){let i="internals"in o?o.internals?.userNode:o;r.push(i)}}return r}var Xp=v(()=>{ae();Ke();an();Oo();Dr()});function Ud(e,t){K(t,!0);let r=z(t,"store",15),n=z(t,"selectionKey",3,"Shift"),o=z(t,"multiSelectionKey",19,()=>Ds()?"Meta":"Control"),i=z(t,"deleteKey",3,"Backspace"),s=z(t,"panActivationKey",3," "),a=z(t,"zoomActivationKey",19,()=>Ds()?"Meta":"Control"),{deleteElements:l}=uw();function c(b){return b!==null&&typeof b=="object"}function f(b){return c(b)?b.modifier||[]:[]}function p(b){return b==null?"":c(b)?b.key:b}function u(b,x){return(Array.isArray(b)?b:[b]).map(C=>{let E=p(C);return{key:E,modifier:f(C),enabled:E!==null,callback:x}})}function h(){r(r().selectionRect=null,!0),r(r().selectionKeyPressed=!1,!0),r(r().multiselectionKeyPressed=!1,!0),r(r().deleteKeyPressed=!1,!0),r(r().panActivationKeyPressed=!1,!0),r(r().zoomActivationKeyPressed=!1,!0)}function g(){let b=r().nodes.filter(w=>w.selected),x=r().edges.filter(w=>w.selected);l({nodes:b,edges:x})}mi("blur",ir,h),mi("contextmenu",ir,h),gt(ir,(b,x)=>ln?.(b,x),()=>({trigger:u(n(),()=>r(r().selectionKeyPressed=!0,!0)),type:"keydown"})),gt(ir,(b,x)=>ln?.(b,x),()=>({trigger:u(n(),()=>r(r().selectionKeyPressed=!1,!0)),type:"keyup"})),gt(ir,(b,x)=>ln?.(b,x),()=>({trigger:u(o(),()=>{r(r().multiselectionKeyPressed=!0,!0)}),type:"keydown"})),gt(ir,(b,x)=>ln?.(b,x),()=>({trigger:u(o(),()=>r(r().multiselectionKeyPressed=!1,!0)),type:"keyup"})),gt(ir,(b,x)=>ln?.(b,x),()=>({trigger:u(i(),b=>{!(b.originalEvent.ctrlKey||b.originalEvent.metaKey||b.originalEvent.shiftKey)&&!gd(b.originalEvent)&&(r(r().deleteKeyPressed=!0,!0),g())}),type:"keydown"})),gt(ir,(b,x)=>ln?.(b,x),()=>({trigger:u(i(),()=>r(r().deleteKeyPressed=!1,!0)),type:"keyup"})),gt(ir,(b,x)=>ln?.(b,x),()=>({trigger:u(s(),()=>r(r().panActivationKeyPressed=!0,!0)),type:"keydown"})),gt(ir,(b,x)=>ln?.(b,x),()=>({trigger:u(s(),()=>r(r().panActivationKeyPressed=!1,!0)),type:"keyup"})),gt(ir,(b,x)=>ln?.(b,x),()=>({trigger:u(a(),()=>r(r().zoomActivationKeyPressed=!0,!0)),type:"keydown"})),gt(ir,(b,x)=>ln?.(b,x),()=>({trigger:u(a(),()=>r(r().zoomActivationKeyPressed=!1,!0)),type:"keyup"})),q()}var fw=v(()=>{_e();ae();cw();Ke();Xp()});var pw=v(()=>{fw()});function Td(e,t){K(t,!0);let r=_(()=>{if(!t.store.connection.inProgress)return"";let s={sourceX:t.store.connection.from.x,sourceY:t.store.connection.from.y,sourcePosition:t.store.connection.fromPosition,targetX:t.store.connection.to.x,targetY:t.store.connection.to.y,targetPosition:t.store.connection.toPosition};switch(t.type){case Dn.Bezier:{let[a]=md(s);return a}case Dn.Straight:{let[a]=vd(s);return a}case Dn.Step:case Dn.SmoothStep:{let[a]=Os({...s,borderRadius:t.type===Dn.Step?0:void 0});return a}}});var n=Ve(),o=ve(n);{var i=s=>{var a=pk(),l=V(a),c=V(l);{var f=u=>{var h=Ve(),g=ve(h);io(g,()=>t.LineComponent,(b,x)=>{x(b,{})}),N(u,h)},p=u=>{var h=fk();te(()=>{re(h,"d",d(r)),nt(h,t.style)}),N(u,h)};ue(c,u=>{t.LineComponent?u(f):u(p,-1)})}L(l),L(a),te(u=>{re(a,"width",t.store.width),re(a,"height",t.store.height),nt(a,t.containerStyle),Pe(l,0,u)},[()=>Jt(["svelte-flow__connection",by(t.store.connection.isValid)])]),N(s,a)};ue(o,s=>{t.store.connection.inProgress&&s(i)})}N(e,n),q()}var fk,pk,hw=v(()=>{_e();ae();Ke();fk=Ze(''),pk=Ze('')});var gw=v(()=>{hw()});function Mo(e,t){K(t,!0);let r=z(t,"position",3,"top-right"),n=Kt(t,hk),o=_(()=>`${r()}`.split("-"));var i=gk();jt(i,a=>({class:a,style:t.style,...n}),[()=>["svelte-flow__panel",t.class,...d(o)]]);var s=V(i);dt(s,()=>t.children??ft),L(i),N(e,i),q()}var hk,gk,Mp=v(()=>{_e();ae();hk=new Set(["$$slots","$$events","$$legacy","position","style","class","children"]),gk=Y("
")});var mw=v(()=>{});var Vd=v(()=>{Mp();mw()});function Dd(e,t){K(t,!0);let r=z(t,"position",3,"bottom-right");var n=Ve(),o=ve(n);{var i=s=>{Mo(s,{get position(){return r()},class:"svelte-flow__attribution","data-message":"Feel free to remove the attribution or check out how you could support us: https://svelteflow.dev/support-us",children:(a,l)=>{var c=mk();N(a,c)},$$slots:{default:!0}})};ue(o,s=>{t.proOptions?.hideAttribution||s(i)})}N(e,n),q()}var mk,vw=v(()=>{_e();ae();Vd();mk=Y('Svelte Flow')});var _w=v(()=>{vw()});var bw=v(()=>{});function Wp(e,t){K(t,!0);let r=z(t,"domNode",15),n=z(t,"clientWidth",15),o=z(t,"clientHeight",15),i=_(()=>t.rest.id),s=_(()=>t.rest.class),a=_(()=>t.rest.nodeTypes),l=_(()=>t.rest.edgeTypes),c=_(()=>t.rest.colorMode),f=_(()=>t.rest.isValidConnection),p=_(()=>t.rest.onmove),u=_(()=>t.rest.onmovestart),h=_(()=>t.rest.onmoveend),g=_(()=>t.rest.onflowerror),b=_(()=>t.rest.ondelete),x=_(()=>t.rest.onbeforedelete),w=_(()=>t.rest.onbeforeconnect),C=_(()=>t.rest.onconnect),E=_(()=>t.rest.onconnectstart),I=_(()=>t.rest.onconnectend),T=_(()=>t.rest.onbeforereconnect),B=_(()=>t.rest.onreconnect),Z=_(()=>t.rest.onreconnectstart),R=_(()=>t.rest.onreconnectend),O=_(()=>t.rest.onclickconnectstart),H=_(()=>t.rest.onclickconnectend),F=_(()=>t.rest.oninit),$=_(()=>t.rest.onselectionchange),Q=_(()=>t.rest.onselectiondragstart),y=_(()=>t.rest.onselectiondrag),S=_(()=>t.rest.onselectiondragstop),k=_(()=>t.rest.onselectionstart),D=_(()=>t.rest.onselectionend),J=_(()=>t.rest.clickConnect),W=_(()=>t.rest.fitView),j=_(()=>t.rest.fitViewOptions),ee=_(()=>t.rest.nodeOrigin),se=_(()=>t.rest.nodeDragThreshold),de=_(()=>t.rest.connectionDragThreshold),M=_(()=>t.rest.minZoom),ce=_(()=>t.rest.maxZoom),ne=_(()=>t.rest.initialViewport),ie=_(()=>t.rest.connectionRadius),pe=_(()=>t.rest.connectionMode),ke=_(()=>t.rest.selectionMode),Qe=_(()=>t.rest.selectNodesOnDrag),Se=_(()=>t.rest.snapGrid),ot=_(()=>t.rest.defaultMarkerColor),Re=_(()=>t.rest.translateExtent),ut=_(()=>t.rest.nodeExtent),Je=_(()=>t.rest.onlyRenderVisibleElements),et=_(()=>t.rest.autoPanOnConnect),xt=_(()=>t.rest.autoPanOnNodeDrag),Fe=_(()=>t.rest.colorModeSSR),it=_(()=>t.rest.defaultEdgeOptions),tr=_(()=>t.rest.elevateNodesOnSelect),We=_(()=>t.rest.elevateEdgesOnSelect),Sr=_(()=>t.rest.nodesDraggable),Mr=_(()=>t.rest.autoPanOnNodeFocus),Wr=_(()=>t.rest.nodesConnectable),Vi=_(()=>t.rest.elementsSelectable),Di=_(()=>t.rest.nodesFocusable),Oi=_(()=>t.rest.edgesFocusable),Xi=_(()=>t.rest.disableKeyboardA11y),Mi=_(()=>t.rest.noDragClass),Wi=_(()=>t.rest.noPanClass),Hi=_(()=>t.rest.noWheelClass),zi=_(()=>t.rest.ariaLabelConfig),Yi=_(()=>t.rest.autoPanSpeed),Pi=_(()=>t.rest.panOnScrollSpeed),Ji=_(()=>t.rest.zIndexMode),Wo=_(()=>ru(t.rest,["id","class","nodeTypes","edgeTypes","colorMode","isValidConnection","onmove","onmovestart","onmoveend","onflowerror","ondelete","onbeforedelete","onbeforeconnect","onconnect","onconnectstart","onconnectend","onbeforereconnect","onreconnect","onreconnectstart","onreconnectend","onclickconnectstart","onclickconnectend","oninit","onselectionchange","onselectiondragstart","onselectiondrag","onselectiondragstop","onselectionstart","onselectionend","clickConnect","fitView","fitViewOptions","nodeOrigin","nodeDragThreshold","connectionDragThreshold","minZoom","maxZoom","initialViewport","connectionRadius","connectionMode","selectionMode","selectNodesOnDrag","snapGrid","defaultMarkerColor","translateExtent","nodeExtent","onlyRenderVisibleElements","autoPanOnConnect","autoPanOnNodeDrag","colorModeSSR","defaultEdgeOptions","elevateNodesOnSelect","elevateEdgesOnSelect","nodesDraggable","autoPanOnNodeFocus","nodesConnectable","elementsSelectable","nodesFocusable","edgesFocusable","disableKeyboardA11y","noDragClass","noPanClass","noWheelClass","ariaLabelConfig","autoPanSpeed","panOnScrollSpeed","zIndexMode"]));function Ho(Hr){Hr.currentTarget.scrollTo({top:0,left:0,behavior:"auto"}),t.rest.onscroll&&t.rest.onscroll(Hr)}var Ar=vk();jt(Ar,Hr=>({class:["svelte-flow","svelte-flow__container",d(s),t.colorMode],"data-testid":"svelte-flow__wrapper",role:"application",onscroll:Ho,...d(Wo),[Er]:Hr}),[()=>({width:xr(t.width),height:xr(t.height)})],void 0,void 0,"svelte-mkap6j");var zo=V(Ar);dt(zo,()=>t.children??ft),L(Ar),Xr(Ar,Hr=>r(Hr),()=>r()),kc(Ar,"clientHeight",o),kc(Ar,"clientWidth",n),N(e,Ar),q()}var vk,xw=v(()=>{_e();ae();Oo();bw();vk=Y("
")});function Ui(e,t){K(t,!0);let r=z(t,"paneClickDistance",3,1),n=z(t,"nodeClickDistance",3,1),o=z(t,"panOnScrollMode",19,()=>Fi.Free),i=z(t,"preventScrolling",3,!0),s=z(t,"zoomOnScroll",3,!0),a=z(t,"zoomOnDoubleClick",3,!0),l=z(t,"zoomOnPinch",3,!0),c=z(t,"panOnScroll",3,!1),f=z(t,"panOnScrollSpeed",3,.5),p=z(t,"panOnDrag",3,!0),u=z(t,"selectionOnDrag",3,!1),h=z(t,"connectionLineType",19,()=>Dn.Bezier),g=z(t,"nodes",31,()=>Xt([])),b=z(t,"edges",31,()=>Xt([])),x=z(t,"viewport",15,void 0),w=Kt(t,_k),C=N0({props:w,width:t.width,height:t.height,get nodes(){return g()},set nodes(I){g(I)},get edges(){return b()},set edges(I){b(I)},get viewport(){return x()},set viewport(I){x(I)}}),E=zn(El);E&&E.setStore&&E.setStore(C),jo(El,{provider:!1,getStore(){return C}}),ct(()=>{let I={nodes:C.selectedNodes,edges:C.selectedEdges};Ge(()=>t.onselectionchange)?.(I);for(let T of C.selectionChangeHandlers.values())T(I)}),ao(()=>{C.reset()}),Wp(e,{get colorMode(){return C.colorMode},get width(){return t.width},get height(){return t.height},get rest(){return w},get domNode(){return C.domNode},set domNode(I){C.domNode=I},get clientWidth(){return C.width},set clientWidth(I){C.width=I},get clientHeight(){return C.height},set clientHeight(I){C.height=I},children:(I,T)=>{var B=yk(),Z=ve(B);Ud(Z,{get selectionKey(){return t.selectionKey},get deleteKey(){return t.deleteKey},get panActivationKey(){return t.panActivationKey},get multiSelectionKey(){return t.multiSelectionKey},get zoomActivationKey(){return t.zoomActivationKey},get store(){return C},set store($){C=$}});var R=P(Z,2);Ed(R,{get panOnScrollMode(){return o()},get preventScrolling(){return i()},get zoomOnScroll(){return s()},get zoomOnDoubleClick(){return a()},get zoomOnPinch(){return l()},get panOnScroll(){return c()},get panOnScrollSpeed(){return f()},get panOnDrag(){return p()},get paneClickDistance(){return r()},get selectionOnDrag(){return u()},get onmovestart(){return t.onmovestart},get onmove(){return t.onmove},get onmoveend(){return t.onmoveend},get oninit(){return t.oninit},get store(){return C},set store($){C=$},children:($,Q)=>{$d($,{get onpaneclick(){return t.onpaneclick},get onpanecontextmenu(){return t.onpanecontextmenu},get onselectionstart(){return t.onselectionstart},get onselectionend(){return t.onselectionend},get panOnDrag(){return p()},get paneClickDistance(){return r()},get selectionOnDrag(){return u()},get store(){return C},set store(y){C=y},children:(y,S)=>{var k=xk(),D=ve(k);Bd(D,{get store(){return C},set store(W){C=W},children:(W,j)=>{var ee=bk(),se=P(ve(ee),2);Rd(se,{get onedgeclick(){return t.onedgeclick},get onedgecontextmenu(){return t.onedgecontextmenu},get onedgepointerenter(){return t.onedgepointerenter},get onedgepointerleave(){return t.onedgepointerleave},get store(){return C},set store(ne){C=ne}});var de=P(se,4);Td(de,{get type(){return h()},get LineComponent(){return t.connectionLineComponent},get containerStyle(){return t.connectionLineContainerStyle},get style(){return t.connectionLineStyle},get store(){return C},set store(ne){C=ne}});var M=P(de,2);Fd(M,{get nodeClickDistance(){return n()},get onnodeclick(){return t.onnodeclick},get onnodecontextmenu(){return t.onnodecontextmenu},get onnodepointerenter(){return t.onnodepointerenter},get onnodepointermove(){return t.onnodepointermove},get onnodepointerleave(){return t.onnodepointerleave},get onnodedrag(){return t.onnodedrag},get onnodedragstart(){return t.onnodedragstart},get onnodedragstop(){return t.onnodedragstop},get store(){return C},set store(ne){C=ne}});var ce=P(M,2);Ld(ce,{get onselectionclick(){return t.onselectionclick},get onselectioncontextmenu(){return t.onselectioncontextmenu},get onnodedrag(){return t.onnodedrag},get onnodedragstart(){return t.onnodedragstart},get onnodedragstop(){return t.onnodedragstop},get store(){return C},set store(ne){C=ne}}),zt(2),N(W,ee)},$$slots:{default:!0}});var J=P(D,2);{let W=_(()=>!!(C.selectionRect&&C.selectionRectMode==="user")),j=_(()=>C.selectionRect?.width),ee=_(()=>C.selectionRect?.height),se=_(()=>C.selectionRect?.x),de=_(()=>C.selectionRect?.y);Ws(J,{get isVisible(){return d(W)},get width(){return d(j)},get height(){return d(ee)},get x(){return d(se)},get y(){return d(de)}})}N(y,k)},$$slots:{default:!0}})},$$slots:{default:!0}});var O=P(R,2);Dd(O,{get proOptions(){return t.proOptions},get position(){return t.attributionPosition}});var H=P(O,2);kd(H,{get store(){return C}});var F=P(H,2);dt(F,()=>t.children??ft),N(I,B)},$$slots:{default:!0}}),q()}var _k,bk,xk,yk,yw=v(()=>{_e();ae();Dr();Ke();an();Z0();V0();O0();P0();tw();sw();Op();pw();gw();_w();xw();Bl();_k=new Set(["$$slots","$$events","$$legacy","width","height","proOptions","selectionKey","deleteKey","panActivationKey","multiSelectionKey","zoomActivationKey","paneClickDistance","nodeClickDistance","onmovestart","onmoveend","onmove","oninit","onnodeclick","onnodecontextmenu","onnodedrag","onnodedragstart","onnodedragstop","onnodepointerenter","onnodepointermove","onnodepointerleave","onselectionclick","onselectioncontextmenu","onselectionstart","onselectionend","onedgeclick","onedgecontextmenu","onedgepointerenter","onedgepointerleave","onpaneclick","onpanecontextmenu","panOnScrollMode","preventScrolling","zoomOnScroll","zoomOnDoubleClick","zoomOnPinch","panOnScroll","panOnScrollSpeed","panOnDrag","selectionOnDrag","connectionLineComponent","connectionLineStyle","connectionLineContainerStyle","connectionLineType","attributionPosition","children","nodes","edges","viewport"]),bk=Y('
',1),xk=Y(" ",1),yk=Y(" ",1)});var Hp=v(()=>{});var ww=v(()=>{yw();Hp()});var Iw=v(()=>{});var Cw=v(()=>{});var Ew=v(()=>{Cw()});var $w=v(()=>{});var Bw=v(()=>{$w()});var kw=v(()=>{});var Sw=v(()=>{kw()});function Hs(e,t){let r=Kt(t,wk);var n=Ik();jt(n,()=>({type:"button",onclick:t.onclick,class:["svelte-flow__controls-button",t.class],...r,[Er]:{"--xy-controls-button-background-color-props":t.bgColor,"--xy-controls-button-background-color-hover-props":t.bgColorHover,"--xy-controls-button-color-props":t.color,"--xy-controls-button-color-hover-props":t.colorHover,"--xy-controls-button-border-color-props":t.borderColor}}));var o=V(n);dt(o,()=>t.children??ft),L(n),N(e,n)}var wk,Ik,Aw=v(()=>{_e();ae();wk=new Set(["$$slots","$$events","$$legacy","class","bgColor","bgColorHover","color","colorHover","borderColor","onclick","children"]),Ik=Y("")});function zp(e){var t=Ck();N(e,t)}var Ck,Nw=v(()=>{_e();Xo();ae();Ck=Ze('')});function Yp(e){var t=Ek();N(e,t)}var Ek,Fw=v(()=>{_e();Xo();ae();Ek=Ze('')});function Pp(e){var t=$k();N(e,t)}var $k,Gw=v(()=>{_e();Xo();ae();$k=Ze('')});function Jp(e){var t=Bk();N(e,t)}var Bk,Zw=v(()=>{_e();Xo();ae();Bk=Ze('')});function jp(e){var t=kk();N(e,t)}var kk,Qw=v(()=>{_e();Xo();ae();kk=Ze('')});function Od(e,t){K(t,!0);let r=z(t,"position",3,"bottom-left"),n=z(t,"orientation",3,"vertical"),o=z(t,"showZoom",3,!0),i=z(t,"showFitView",3,!0),s=z(t,"showLock",3,!0),a=Kt(t,Sk),l=_(Qt),c={bgColor:t.buttonBgColor,bgColorHover:t.buttonBgColorHover,color:t.buttonColor,colorHover:t.buttonColorHover,borderColor:t.buttonBorderColor},f=_(()=>d(l).nodesDraggable||d(l).nodesConnectable||d(l).elementsSelectable),p=_(()=>d(l).viewport.zoom<=d(l).minZoom),u=_(()=>d(l).viewport.zoom>=d(l).maxZoom),h=_(()=>d(l).ariaLabelConfig),g=_(()=>n()==="horizontal"?"horizontal":"vertical"),b=()=>{d(l).zoomIn()},x=()=>{d(l).zoomOut()},w=()=>{d(l).fitView(t.fitViewOptions)},C=()=>{let E=!d(f);d(l).nodesDraggable=E,d(l).nodesConnectable=E,d(l).elementsSelectable=E};{let E=_(()=>["svelte-flow__controls",d(g),t.class]);Mo(e,wn({get class(){return d(E)},get position(){return r()},"data-testid":"svelte-flow__controls",get"aria-label"(){return d(h)["controls.ariaLabel"]},get style(){return t.style}},()=>a,{children:(I,T)=>{var B=Nk(),Z=ve(B);{var R=W=>{var j=Ve(),ee=ve(j);dt(ee,()=>t.before),N(W,j)};ue(Z,W=>{t.before&&W(R)})}var O=P(Z,2);{var H=W=>{var j=Ak(),ee=ve(j);Hs(ee,wn({onclick:b,class:"svelte-flow__controls-zoomin",get title(){return d(h)["controls.zoomIn.ariaLabel"]},get"aria-label"(){return d(h)["controls.zoomIn.ariaLabel"]},get disabled(){return d(u)}},()=>c,{children:(de,M)=>{zp(de,{})},$$slots:{default:!0}}));var se=P(ee,2);Hs(se,wn({onclick:x,class:"svelte-flow__controls-zoomout",get title(){return d(h)["controls.zoomOut.ariaLabel"]},get"aria-label"(){return d(h)["controls.zoomOut.ariaLabel"]},get disabled(){return d(p)}},()=>c,{children:(de,M)=>{Yp(de,{})},$$slots:{default:!0}})),N(W,j)};ue(O,W=>{o()&&W(H)})}var F=P(O,2);{var $=W=>{Hs(W,wn({class:"svelte-flow__controls-fitview",onclick:w,get title(){return d(h)["controls.fitView.ariaLabel"]},get"aria-label"(){return d(h)["controls.fitView.ariaLabel"]}},()=>c,{children:(j,ee)=>{Pp(j,{})},$$slots:{default:!0}}))};ue(F,W=>{i()&&W($)})}var Q=P(F,2);{var y=W=>{Hs(W,wn({class:"svelte-flow__controls-interactive",onclick:C,get title(){return d(h)["controls.interactive.ariaLabel"]},get"aria-label"(){return d(h)["controls.interactive.ariaLabel"]}},()=>c,{children:(j,ee)=>{var se=Ve(),de=ve(se);{var M=ne=>{jp(ne,{})},ce=ne=>{Jp(ne,{})};ue(de,ne=>{d(f)?ne(M):ne(ce,-1)})}N(j,se)},$$slots:{default:!0}}))};ue(Q,W=>{s()&&W(y)})}var S=P(Q,2);{var k=W=>{var j=Ve(),ee=ve(j);dt(ee,()=>t.children),N(W,j)};ue(S,W=>{t.children&&W(k)})}var D=P(S,2);{var J=W=>{var j=Ve(),ee=ve(j);dt(ee,()=>t.after),N(W,j)};ue(D,W=>{t.after&&W(J)})}N(I,B)},$$slots:{default:!0}}))}q()}var Sk,Ak,Nk,Rw=v(()=>{_e();ae();an();Mp();Aw();Nw();Fw();Gw();Zw();Qw();Sk=new Set(["$$slots","$$events","$$legacy","position","orientation","showZoom","showFitView","showLock","style","class","buttonBgColor","buttonBgColorHover","buttonColor","buttonColorHover","buttonBorderColor","fitViewOptions","children","before","after"]),Ak=Y(" ",1),Nk=Y(" ",1)});var Lw=v(()=>{});var Uw=v(()=>{Rw();Lw()});var vo,Tw=v(()=>{(function(e){e.Lines="lines",e.Dots="dots",e.Cross="cross"})(vo||(vo={}))});function Kp(e,t){var r=Fk();te(()=>{re(r,"cx",t.radius),re(r,"cy",t.radius),re(r,"r",t.radius),Pe(r,0,Jt(["svelte-flow__background-pattern","dots",t.class]))}),N(e,r)}var Fk,Vw=v(()=>{_e();ae();Fk=Ze("")});function qp(e,t){K(t,!0);var r=Gk();te(()=>{re(r,"stroke-width",t.lineWidth),re(r,"d",`M${t.dimensions[0]/2} 0 V${t.dimensions[1]} M0 ${t.dimensions[1]/2} H${t.dimensions[0]}`),Pe(r,0,Jt(["svelte-flow__background-pattern",t.variant,t.class]))}),N(e,r),q()}var Gk,Dw=v(()=>{_e();ae();Gk=Ze("")});function zs(e,t){K(t,!0);let r=z(t,"variant",19,()=>vo.Dots),n=z(t,"gap",3,20),o=z(t,"lineWidth",3,1),i=_(Qt),s=_(()=>r()===vo.Dots),a=_(()=>r()===vo.Cross),l=_(()=>Array.isArray(n())?n():[n(),n()]),c=_(()=>`background-pattern-${d(i).flowId}-${t.id??""}`),f=_(()=>[d(l)[0]*d(i).viewport.zoom||1,d(l)[1]*d(i).viewport.zoom||1]),p=_(()=>(t.size??Zk[r()])*d(i).viewport.zoom),u=_(()=>d(a)?[d(p),d(p)]:d(f)),h=_(()=>d(s)?[d(p)/2,d(p)/2]:[d(u)[0]/2,d(u)[1]/2]);var g=Qk();let b;var x=V(g),w=V(x);{var C=T=>{{let B=_(()=>d(p)/2);Kp(T,{get radius(){return d(B)},get class(){return t.patternClass}})}},E=T=>{qp(T,{get dimensions(){return d(u)},get variant(){return r()},get lineWidth(){return o()},get class(){return t.patternClass}})};ue(w,T=>{d(s)?T(C):T(E,-1)})}L(x);var I=P(x);L(g),te(()=>{Pe(g,0,Jt(["svelte-flow__background","svelte-flow__container",t.class])),b=nt(g,"",b,{"--xy-background-color-props":t.bgColor,"--xy-background-pattern-color-props":t.patternColor}),re(x,"id",d(c)),re(x,"x",d(i).viewport.x%d(f)[0]),re(x,"y",d(i).viewport.y%d(f)[1]),re(x,"width",d(f)[0]),re(x,"height",d(f)[1]),re(x,"patternTransform",`translate(-${d(h)[0]},-${d(h)[1]})`),re(I,"fill",`url(#${d(c)})`)}),N(e,g),q()}var Zk,Qk,Ow=v(()=>{_e();ae();an();Tw();Vw();Dw();Zk={[vo.Dots]:1,[vo.Lines]:1,[vo.Cross]:6},Qk=Ze('')});var Xw=v(()=>{Ow()});function Mw(e){let t=_(Qt),r=_(()=>d(t).nodeLookup),n=_(()=>d(t).nodes),o=_(()=>(d(n),d(r).get(e)));return{get current(){return d(o)}}}var eh=v(()=>{ae();an()});function th(e,t){K(t,!0);let r=z(t,"borderRadius",3,5),n=z(t,"strokeWidth",3,2),o=_(()=>Mw(t.id)),i=_(()=>{if(!d(o).current)return{width:0,height:0,x:0,y:0};let{width:g,height:b}=po(d(o).current);return{width:t.width??g,height:t.height??b,x:t.x??d(o).current.internals.positionAbsolute.x,y:t.y??d(o).current.internals.positionAbsolute.y}}),s=_(()=>d(i).width),a=_(()=>d(i).height),l=_(()=>d(i).x),c=_(()=>d(i).y);var f=Ve(),p=ve(f);{var u=g=>{let b=_(()=>t.nodeComponent);var x=Ve(),w=ve(x);io(w,()=>d(b),(C,E)=>{E(C,{get id(){return t.id},get x(){return d(l)},get y(){return d(c)},get width(){return d(s)},get height(){return d(a)},get borderRadius(){return r()},get class(){return t.class},get color(){return t.color},get shapeRendering(){return t.shapeRendering},get strokeColor(){return t.strokeColor},get strokeWidth(){return n()},get selected(){return t.selected}})}),N(g,x)},h=g=>{var b=Rk();let x,w;te(()=>{x=Pe(b,0,Jt(["svelte-flow__minimap-node",t.class]),null,x,{selected:t.selected}),re(b,"x",d(l)),re(b,"y",d(c)),re(b,"rx",r()),re(b,"ry",r()),re(b,"width",d(s)),re(b,"height",d(a)),re(b,"shape-rendering",t.shapeRendering),w=nt(b,"",w,{fill:t.color,stroke:t.strokeColor,"stroke-width":n()})}),N(g,b)};ue(p,g=>{t.nodeComponent?g(u):g(h,-1)})}N(e,f),q()}var Rk,Ww=v(()=>{_e();ae();eh();Ke();Rk=Ze("")});function rh(e,t){let r=Yy({domNode:e,panZoom:t.panZoom,getTransform:()=>{let{viewport:o}=t.store;return[o.x,o.y,o.zoom]},getViewScale:t.getViewScale});r.update({translateExtent:t.translateExtent,width:t.width,height:t.height,inversePan:t.inversePan,zoomStep:t.zoomStep,pannable:t.pannable,zoomable:t.zoomable});function n(o){r.update({translateExtent:o.translateExtent,width:o.width,height:o.height,inversePan:o.inversePan,zoomStep:o.zoomStep,pannable:o.pannable,zoomable:o.zoomable})}return{update:n,destroy(){r.destroy()}}}var Hw=v(()=>{Ke()});function Xd(e,t){K(t,!0);let r=z(t,"position",3,"bottom-right"),n=z(t,"nodeStrokeColor",3,"transparent"),o=z(t,"nodeClass",3,""),i=z(t,"nodeBorderRadius",3,5),s=z(t,"nodeStrokeWidth",3,2),a=z(t,"width",3,200),l=z(t,"height",3,150),c=z(t,"pannable",3,!0),f=z(t,"zoomable",3,!0),p=Kt(t,Lk),u=_(Qt),h=_(()=>d(u).ariaLabelConfig),g=typeof window>"u"||window.chrome?"crispEdges":"geometricPrecision",b=_(()=>`svelte-flow__minimap-desc-${d(u).flowId}`),x=_(()=>({x:-d(u).viewport.x/d(u).viewport.zoom,y:-d(u).viewport.y/d(u).viewport.zoom,width:d(u).width/d(u).viewport.zoom,height:d(u).height/d(u).viewport.zoom})),w=_(()=>up(Do(d(u).nodeLookup,{filter:S=>!S.hidden}),d(x))),C=_(()=>d(w).width/a()),E=_(()=>d(w).height/l()),I=_(()=>Math.max(d(C),d(E))),T=_(()=>d(I)*a()),B=_(()=>d(I)*l()),Z=_(()=>5*d(I)),R=_(()=>d(w).x-(d(T)-d(w).width)/2-d(Z)),O=_(()=>d(w).y-(d(B)-d(w).height)/2-d(Z)),H=_(()=>d(T)+d(Z)*2),F=_(()=>d(B)+d(Z)*2),$=()=>d(I);var Q=Vk(),y=ve(Q);{let S=_(()=>["svelte-flow__minimap",t.class]);Ju(y,()=>({"--xy-minimap-background-color-props":t.bgColor})),Mo(y.lastChild,wn({get position(){return r()},get class(){return d(S)},"data-testid":"svelte-flow__minimap"},()=>p,{children:(k,D)=>{var J=Ve(),W=ve(J);{var j=ee=>{var se=Tk();let de;var M=V(se);{var ce=pe=>{var ke=Uk(),Qe=V(ke,!0);L(ke),te(()=>{re(ke,"id",d(b)),he(Qe,t.ariaLabel??d(h)["minimap.ariaLabel"])}),N(pe,ke)};ue(M,pe=>{(t.ariaLabel??d(h)["minimap.ariaLabel"])&&pe(ce)})}var ne=P(M);Xe(ne,17,()=>d(u).nodes,pe=>pe.id,(pe,ke)=>{let Qe=_(()=>d(u).nodeLookup.get(d(ke).id));var Se=Ve(),ot=ve(Se);{var Re=Je=>{{let et=_(()=>t.nodeColor===void 0?void 0:nh(t.nodeColor)(d(ke))),xt=_(()=>nh(n())(d(ke))),Fe=_(()=>nh(o())(d(ke)));th(Je,{get id(){return d(Qe).id},get selected(){return d(Qe).selected},get nodeComponent(){return t.nodeComponent},get color(){return d(et)},get borderRadius(){return i()},get strokeColor(){return d(xt)},get strokeWidth(){return s()},get shapeRendering(){return g},get class(){return d(Fe)}})}},ut=_(()=>d(Qe)&&hd(d(Qe))&&!d(Qe).hidden);ue(ot,Je=>{d(ut)&&Je(Re)})}N(pe,Se)});var ie=P(ne);L(se),gt(se,(pe,ke)=>rh?.(pe,ke),()=>({store:d(u),panZoom:d(u).panZoom,getViewScale:$,translateExtent:d(u).translateExtent,width:d(u).width,height:d(u).height,inversePan:t.inversePan,zoomStep:t.zoomStep,pannable:c(),zoomable:f()})),te(()=>{re(se,"width",a()),re(se,"height",l()),re(se,"viewBox",`${d(R)??""} ${d(O)??""} ${d(H)??""} ${d(F)??""}`),re(se,"aria-labelledby",d(b)),de=nt(se,"",de,{"--xy-minimap-mask-background-color-props":t.maskColor,"--xy-minimap-mask-stroke-color-props":t.maskStrokeColor,"--xy-minimap-mask-stroke-width-props":t.maskStrokeWidth?t.maskStrokeWidth*d(I):void 0}),re(ie,"d",`M${d(R)-d(Z)},${d(O)-d(Z)}h${d(H)+d(Z)*2}v${d(F)+d(Z)*2}h${-d(H)-d(Z)*2}z - M${d(x).x??""},${d(x).y??""}h${d(x).width??""}v${d(x).height??""}h${-d(x).width}z`)}),N(ee,se)};ue(W,ee=>{d(u).panZoom&&ee(j)})}N(k,J)},$$slots:{default:!0}})),L(y)}N(e,Q),q()}var nh,Lk,Uk,Tk,Vk,zw=v(()=>{_e();ae();Ke();an();Vd();Ww();Hw();nh=e=>e instanceof Function?e:()=>e,Lk=new Set(["$$slots","$$events","$$legacy","position","ariaLabel","nodeStrokeColor","nodeColor","nodeClass","nodeBorderRadius","nodeStrokeWidth","nodeComponent","bgColor","maskColor","maskStrokeColor","maskStrokeWidth","width","height","pannable","zoomable","inversePan","zoomStep","class"]),Uk=Ze(" "),Tk=Ze(''),Vk=Y('',1)});var Yw=v(()=>{});var Pw=v(()=>{zw();Yw()});var Jw=v(()=>{});var jw=v(()=>{Jw()});var Kw=v(()=>{});var qw=v(()=>{Kw()});var eI=v(()=>{});var tI=v(()=>{ae()});var rI=v(()=>{ae()});var nI=v(()=>{ae()});var oI=v(()=>{ae()});var iI=v(()=>{ae()});var sI=v(()=>{ae()});var aI=v(()=>{ae()});var lI=v(()=>{});var oh=v(()=>{ww();Hp();Vd();Iw();Ew();vl();Bw();Sw();Uw();Xw();Pw();jw();qw();eI();Oo();Xp();tI();rI();nI();oI();iI();eh();sI();aI();Sp();lI()});function cI(e,t){e[t]?e[t]++:e[t]=1}function dI(e,t){e[t]!==void 0&&!--e[t]&&delete e[t]}function kl(e,t,r,n){let o=""+t,i=""+r;if(!e&&o>i){let s=o;o=i,i=s}return o+""+i+""+(n===void 0?"\0":n)}function Wk(e,t,r,n){let o=""+t,i=""+r;if(!e&&o>i){let a=o;o=i,i=a}let s={v:o,w:i};return n&&(s.name=n),s}function ih(e,t){return kl(e,t.v,t.w,t.name)}function zk(e){let t={options:{directed:e.isDirected(),multigraph:e.isMultigraph(),compound:e.isCompound()},nodes:Yk(e),edges:Pk(e)},r=e.graph();return r!==void 0&&(t.value=structuredClone(r)),t}function Yk(e){return e.nodes().map(t=>{let r=e.node(t),n=e.parent(t),o={v:t};return r!==void 0&&(o.value=r),n!==void 0&&(o.parent=n),o})}function Pk(e){return e.edges().map(t=>{let r=e.edge(t),n={v:t.v,w:t.w};return t.name!==void 0&&(n.name=t.name),r!==void 0&&(n.value=r),n})}function Jk(e){let t=new cn(e.options);return e.value!==void 0&&t.setGraph(e.value),e.nodes.forEach(r=>{t.setNode(r.v,r.value),r.parent&&t.setParent(r.v,r.parent)}),e.edges.forEach(r=>{t.setEdge({v:r.v,w:r.w,name:r.name},r.value)}),t}function $I(e,t,r,n){return Kk(e,String(t),r||jk,n||function(o){return e.outEdges(o)})}function Kk(e,t,r,n){let o={},i,s=0,a=e.nodes(),l=function(p){let u=r(p);o[p.v].distance+u0&&(s=i.removeMin(),a=o[s],a.distance!==Number.POSITIVE_INFINITY);)n(s).forEach(l);return o}function rS(e,t,r){return e.nodes().reduce(function(n,o){return n[o]=Md(e,o,t,r),n},{})}function kI(e){let t=0,r=[],n={},o=[];function i(s){let a=n[s]={onStack:!0,lowlink:t,index:t++};if(r.push(s),e.successors(s).forEach(function(l){l in n?n[l].onStack&&(a.lowlink=Math.min(a.lowlink,n[l].index)):(i(l),a.lowlink=Math.min(a.lowlink,n[l].lowlink))}),a.lowlink===a.index){let l=[],c;do c=r.pop(),n[c].onStack=!1,l.push(c);while(s!==c);o.push(l)}}return e.nodes().forEach(function(s){s in n||i(s)}),o}function nS(e){return kI(e).filter(function(t){return t.length>1||t.length===1&&e.hasEdge(t[0],t[0])})}function iS(e,t,r){return sS(e,t||oS,r||function(n){return e.outEdges(n)})}function sS(e,t,r){let n={},o=e.nodes();return o.forEach(function(i){n[i]={},n[i][i]={distance:0,predecessor:""},o.forEach(function(s){i!==s&&(n[i][s]={distance:Number.POSITIVE_INFINITY,predecessor:""})}),r(i).forEach(function(s){let a=s.v===i?s.w:s.v,l=t(s);n[i][a]={distance:l,predecessor:i}})}),o.forEach(function(i){let s=n[i];o.forEach(function(a){let l=n[a];o.forEach(function(c){let f=l[i],p=s[c],u=l[c],h=f.distance+p.distance;h{var l;return(l=e.isDirected()?e.successors(a):e.neighbors(a))!=null?l:[]}),s={};return t.forEach(function(a){if(!e.hasNode(a))throw new Error("Graph does not have node: "+a);o=AI(e,a,r==="post",s,i,n,o)}),o}function AI(e,t,r,n,o,i,s){return t in n||(n[t]=!0,r||(s=i(s,t)),o(t).forEach(function(a){s=AI(e,a,r,n,o,i,s)}),r&&(s=i(s,t))),s}function NI(e,t,r){return lS(e,t,r,function(n,o){return n.push(o),n},[])}function cS(e,t){return NI(e,t,"post")}function dS(e,t){return NI(e,t,"pre")}function uS(e,t){let r=new cn,n={},o=new BI,i;function s(l){let c=l.v===i?l.w:l.v,f=o.priority(c);if(f!==void 0){let p=t(l);p0;){if(i=o.removeMin(),i in n)r.setEdge(i,n[i]);else{if(a)throw new Error("Input graph is not connected: "+e);a=!0}e.nodeEdges(i).forEach(s)}return r}function fS(e,t,r,n){return pS(e,t,r,n??(o=>{let i=e.outEdges(o);return i??[]}))}function pS(e,t,r,n){if(r===void 0)return Md(e,t,r,n);let o=!1,i=e.nodes();for(let s=0;st.setNode(r,e.node(r))),e.edges().forEach(r=>{let n=t.edge(r.v,r.w)||{weight:0,minlen:1},o=e.edge(r);t.setEdge(r.v,r.w,{weight:n.weight+o.weight,minlen:Math.max(n.minlen,o.minlen)})}),t}function FI(e){let t=new cn({multigraph:e.isMultigraph()}).setGraph(e.graph());return e.nodes().forEach(r=>{e.children(r).length||t.setNode(r,e.node(r))}),e.edges().forEach(r=>{t.setEdge(r,e.edge(r))}),t}function uI(e,t){let r=e.x,n=e.y,o=t.x-r,i=t.y-n,s=e.width/2,a=e.height/2;if(!o&&!i)throw new Error("Not possible to find intersection inside of the rectangle");let l,c;return Math.abs(i)*s>Math.abs(o)*a?(i<0&&(a=-a),l=a*o/i,c=a):(o<0&&(s=-s),l=s,c=s*i/o),{x:r+l,y:n+c}}function Al(e){let t=Sl(ZI(e)+1).map(()=>[]);return e.nodes().forEach(r=>{let n=e.node(r),o=n.rank;o!==void 0&&(t[o]||(t[o]=[]),t[o][n.order]=r)}),t}function gS(e){let t=e.nodes().map(n=>{let o=e.node(n).rank;return o===void 0?Number.MAX_VALUE:o}),r=On(Math.min,t);e.nodes().forEach(n=>{let o=e.node(n);Object.hasOwn(o,"rank")&&(o.rank-=r)})}function mS(e){let t=e.nodes().map(s=>e.node(s).rank).filter(s=>s!==void 0),r=On(Math.min,t),n=[];e.nodes().forEach(s=>{let a=e.node(s).rank-r;n[a]||(n[a]=[]),n[a].push(s)});let o=0,i=e.graph().nodeRankFactor;Array.from(n).forEach((s,a)=>{s===void 0&&a%i!==0?--o:s!==void 0&&o&&s.forEach(l=>e.node(l).rank+=o)})}function fI(e,t,r,n){let o={width:0,height:0};return arguments.length>=4&&(o.rank=r,o.order=n),Ps(e,"border",o,t)}function vS(e,t=GI){let r=[];for(let n=0;nGI){let r=vS(t);return e(...r.map(n=>e(...n)))}else return e(...t)}function ZI(e){let t=e.nodes().map(r=>{let n=e.node(r).rank;return n===void 0?Number.MIN_VALUE:n});return On(Math.max,t)}function _S(e,t){let r={lhs:[],rhs:[]};return e.forEach(n=>{t(n)?r.lhs.push(n):r.rhs.push(n)}),r}function QI(e,t){let r=Date.now();try{return t()}finally{console.log(e+" time: "+(Date.now()-r)+"ms")}}function RI(e,t){return t()}function ph(e){let t=++bS;return e+(""+t)}function Sl(e,t,r=1){t==null&&(t=e,e=0);let n=i=>itn[t]:r=t,Object.entries(e).reduce((n,[o,i])=>(n[o]=r(i,o),n),{})}function xS(e,t){return e.reduce((r,n,o)=>(r[n]=t[o],r),{})}function pI(e){e._prev._next=e._next,e._next._prev=e._prev,delete e._next,delete e._prev}function IS(e,t){if(e!=="_next"&&e!=="_prev")return t}function $S(e,t){if(e.nodeCount()<=1)return[];let r=kS(e,t||ES);return BS(r.graph,r.buckets,r.zeroIdx).flatMap(n=>e.outEdges(n.v,n.w)||[])}function BS(e,t,r){var n;let o=[],i=t[t.length-1],s=t[0],a;for(;e.nodeCount();){for(;a=s.dequeue();)sh(e,t,r,a);for(;a=i.dequeue();)sh(e,t,r,a);if(e.nodeCount()){for(let l=t.length-2;l>0;--l)if(a=(n=t[l])==null?void 0:n.dequeue(),a){o=o.concat(sh(e,t,r,a,!0)||[]);break}}}return o}function sh(e,t,r,n,o){let i=[],s=o?i:void 0;return(e.inEdges(n.v)||[]).forEach(a=>{let l=e.edge(a),c=e.node(a.v);o&&i.push({v:a.v,w:a.w}),c.out-=l,uh(t,r,c)}),(e.outEdges(n.v)||[]).forEach(a=>{let l=e.edge(a),c=a.w,f=e.node(c);f.in-=l,uh(t,r,f)}),e.removeNode(n.v),s}function kS(e,t){let r=new cn,n=0,o=0;e.nodes().forEach(a=>{r.setNode(a,{v:a,in:0,out:0})}),e.edges().forEach(a=>{let l=r.edge(a.v,a.w)||0,c=t(a),f=l+c;r.setEdge(a.v,a.w,f);let p=r.node(a.v),u=r.node(a.w);o=Math.max(o,p.out+=c),n=Math.max(n,u.in+=c)});let i=SS(o+n+3).map(()=>new CS),s=n+1;return r.nodes().forEach(a=>{uh(i,s,r.node(a))}),{graph:r,buckets:i,zeroIdx:s}}function uh(e,t,r){var n,o,i;r.out?r.in?(i=e[r.out-r.in+t])==null||i.enqueue(r):(o=e[e.length-1])==null||o.enqueue(r):(n=e[0])==null||n.enqueue(r)}function SS(e){let t=[];for(let r=0;r{let n=e.edge(r);e.removeEdge(r),n.forwardName=r.name,n.reversed=!0,e.setEdge(r.w,r.v,n,ph("rev"))});function t(r){return n=>r.edge(n).weight}}function NS(e){let t=[],r={},n={};function o(i){Object.hasOwn(n,i)||(n[i]=!0,r[i]=!0,e.outEdges(i).forEach(s=>{Object.hasOwn(r,s.w)?t.push(s):o(s.w)}),delete r[i])}return e.nodes().forEach(o),t}function FS(e){e.edges().forEach(t=>{let r=e.edge(t);if(r.reversed){e.removeEdge(t);let n=r.forwardName;delete r.reversed,delete r.forwardName,e.setEdge(t.w,t.v,r,n)}})}function GS(e){e.graph().dummyChains=[],e.edges().forEach(t=>ZS(e,t))}function ZS(e,t){let r=t.v,n=e.node(r).rank,o=t.w,i=e.node(o).rank,s=t.name,a=e.edge(t),l=a.labelRank;if(i===n+1)return;e.removeEdge(t);let c,f,p;for(p=0,++n;n{let r=e.node(t),n=r.edgeLabel,o;for(e.setEdge(r.edgeObj,n);r.dummy;)o=e.successors(t)[0],e.removeNode(t),n.points.push({x:r.x,y:r.y}),r.dummy==="edge-label"&&(n.x=r.x,n.y=r.y,n.width=r.width,n.height=r.height),t=o,r=e.node(t)})}function hh(e){let t={};function r(n){let o=e.node(n);if(Object.hasOwn(t,n))return o.rank;t[n]=!0;let i=e.outEdges(n),s=i?i.map(l=>l==null?Number.POSITIVE_INFINITY:r(l.w)-e.edge(l).minlen):[],a=On(Math.min,s);return a===Number.POSITIVE_INFINITY&&(a=0),o.rank=a}e.sources().forEach(r)}function Ys(e,t){return e.node(t.w).rank-e.node(t.v).rank-e.edge(t).minlen}function RS(e){let t=new cn({directed:!1}),r=e.nodes();if(r.length===0)throw new Error("Graph must have at least one node");let n=r[0],o=e.nodeCount();t.setNode(n,{});let i,s;for(;LS(t,e){let s=i.v,a=n===s?i.w:s;!e.hasNode(a)&&!Ys(t,i)&&(e.setNode(a,{}),e.setEdge(n,a,{}),r(a))})}return e.nodes().forEach(r),e.nodeCount()}function US(e,t){return t.edges().reduce((r,n)=>{let o=Number.POSITIVE_INFINITY;return e.hasNode(n.v)!==e.hasNode(n.w)&&(o=Ys(t,n)),ot.node(n).rank+=r)}function Ti(e){e=hS(e),hh(e);let t=LI(e);mh(t),gh(t,e);let r,n;for(;r=VI(t);)n=DI(t,e,r),OI(t,e,r,n)}function gh(e,t){let r=DS(e,e.nodes());r=r.slice(0,r.length-1),r.forEach(n=>XS(e,t,n))}function XS(e,t,r){let n=e.node(r).parent,o=e.edge(r,n);o.cutvalue=UI(e,t,r)}function UI(e,t,r){let n=e.node(r).parent,o=!0,i=t.edge(r,n),s=0;i||(o=!1,i=t.edge(n,r)),s=i.weight;let a=t.nodeEdges(r);return a&&a.forEach(l=>{let c=l.v===r,f=c?l.w:l.v;if(f!==n){let p=c===o,u=t.edge(l).weight;if(s+=p?u:-u,WS(e,r,f)){let h=e.edge(r,f).cutvalue;s+=p?-h:h}}}),s}function mh(e,t){arguments.length<2&&(t=e.nodes()[0]),TI(e,{},1,t)}function TI(e,t,r,n,o){let i=r,s=e.node(n);t[n]=!0;let a=e.neighbors(n);return a&&a.forEach(l=>{Object.hasOwn(t,l)||(r=TI(e,t,r,l,n))}),s.low=i,s.lim=r++,o?s.parent=o:delete s.parent,r}function VI(e){return e.edges().find(t=>e.edge(t).cutvalue<0)}function DI(e,t,r){let n=r.v,o=r.w;t.hasEdge(n,o)||(n=r.w,o=r.v);let i=e.node(n),s=e.node(o),a=i,l=!1;return i.lim>s.lim&&(a=s,l=!0),t.edges().filter(c=>l===hI(e,e.node(c.v),a)&&l!==hI(e,e.node(c.w),a)).reduce((c,f)=>Ys(t,f)!e.node(o).parent);if(!r)return;let n=VS(e,[r]);n=n.slice(1),n.forEach(o=>{let i=e.node(o).parent,s=t.edge(o,i),a=!1;s||(s=t.edge(i,o),a=!0),t.node(o).rank=t.node(i).rank+(a?s.minlen:-s.minlen)})}function WS(e,t,r){return e.hasEdge(t,r)}function hI(e,t,r){return r.low<=t.lim&&t.lim<=r.lim}function zS(e){let t=e.graph().ranker;if(typeof t=="function")return t(e);switch(t){case"network-simplex":gI(e);break;case"tight-tree":PS(e);break;case"longest-path":YS(e);break;case"none":break;default:gI(e)}}function PS(e){hh(e),LI(e)}function gI(e){OS(e)}function jS(e){let t=qS(e);e.graph().dummyChains.forEach(r=>{let n=e.node(r),o=n.edgeObj,i=KS(e,t,o.v,o.w),s=i.path,a=i.lca,l=0,c=s[l],f=!0;for(;r!==o.w;){if(n=e.node(r),f){for(;(c=s[l])!==a&&e.node(c).maxRanks||a>t[l].lim));let c=l,f=n;for(;(f=e.parent(f))!==c;)i.push(f);return{path:o.concat(i.reverse()),lca:c}}function qS(e){let t={},r=0;function n(o){let i=r;e.children(o).forEach(n),t[o]={low:i,lim:r++}}return e.children(Yd).forEach(n),t}function eA(e){let t=Ps(e,"root",{},"_root"),r=tA(e),n=Object.values(r),o=On(Math.max,n)-1,i=2*o+1;e.graph().nestingRoot=t,e.edges().forEach(a=>e.edge(a).minlen*=i);let s=rA(e)+1;e.children(Yd).forEach(a=>XI(e,t,i,s,o,r,a)),e.graph().nodeRankFactor=i}function XI(e,t,r,n,o,i,s){var a;let l=e.children(s);if(!l.length){s!==t&&e.setEdge(t,s,{weight:0,minlen:r});return}let c=fI(e,"_bt"),f=fI(e,"_bb"),p=e.node(s);e.setParent(c,s),p.borderTop=c,e.setParent(f,s),p.borderBottom=f,l.forEach(u=>{var h;XI(e,t,r,n,o,i,u);let g=e.node(u),b=g.borderTop?g.borderTop:u,x=g.borderBottom?g.borderBottom:u,w=g.borderTop?n:2*n,C=b!==x?1:o-((h=i[s])!=null?h:0)+1;e.setEdge(c,b,{weight:w,minlen:C,nestingEdge:!0}),e.setEdge(x,f,{weight:w,minlen:C,nestingEdge:!0})}),e.parent(s)||e.setEdge(t,c,{weight:0,minlen:o+((a=i[s])!=null?a:0)})}function tA(e){let t={};function r(n,o){let i=e.children(n);i&&i.length&&i.forEach(s=>r(s,o+1)),t[n]=o}return e.children(Yd).forEach(n=>r(n,1)),t}function rA(e){return e.edges().reduce((t,r)=>t+e.edge(r).weight,0)}function nA(e){let t=e.graph();e.removeNode(t.nestingRoot),delete t.nestingRoot,e.edges().forEach(r=>{e.edge(r).nestingEdge&&e.removeEdge(r)})}function iA(e){function t(r){let n=e.children(r),o=e.node(r);if(n.length&&n.forEach(t),Object.hasOwn(o,"minRank")){o.borderLeft=[],o.borderRight=[];for(let i=o.minRank,s=o.maxRank+1;ivI(e.node(t))),e.edges().forEach(t=>vI(e.edge(t)))}function vI(e){let t=e.width;e.width=e.height,e.height=t}function lA(e){e.nodes().forEach(t=>ah(e.node(t))),e.edges().forEach(t=>{var r;let n=e.edge(t);(r=n.points)==null||r.forEach(ah),Object.hasOwn(n,"y")&&ah(n)})}function ah(e){e.y=-e.y}function cA(e){e.nodes().forEach(t=>lh(e.node(t))),e.edges().forEach(t=>{var r;let n=e.edge(t);(r=n.points)==null||r.forEach(lh),Object.hasOwn(n,"x")&&lh(n)})}function lh(e){let t=e.x;e.x=e.y,e.y=t}function dA(e){let t={},r=e.nodes().filter(a=>!e.children(a).length),n=r.map(a=>e.node(a).rank),o=On(Math.max,n),i=Sl(o+1).map(()=>[]);function s(a){if(t[a])return;t[a]=!0;let l=e.node(a);i[l.rank].push(a);let c=e.successors(a);c&&c.forEach(s)}return r.sort((a,l)=>e.node(a).rank-e.node(l).rank).forEach(s),i}function uA(e,t){let r=0;for(let n=1;nf)),o=t.flatMap(c=>{let f=e.outEdges(c);return f?f.map(p=>({pos:n[p.w],weight:e.edge(p).weight})).sort((p,u)=>p.pos-u.pos):[]}),i=1;for(;i{let f=c.pos+i;a[f]+=c.weight;let p=0;for(;f>0;)f%2&&(p+=a[f+1]),f=f-1>>1,a[f]+=c.weight;l+=c.weight*p}),l}function pA(e,t=[]){return t.map(r=>{let n=e.inEdges(r);if(!n||!n.length)return{v:r};{let o=n.reduce((i,s)=>{let a=e.edge(s),l=e.node(s.v);return{sum:i.sum+a.weight*l.order,weight:i.weight+a.weight}},{sum:0,weight:0});return{v:r,barycenter:o.sum/o.weight,weight:o.weight}}})}function hA(e,t){let r={};e.forEach((o,i)=>{let s={indegree:0,in:[],out:[],vs:[o.v],i};o.barycenter!==void 0&&(s.barycenter=o.barycenter,s.weight=o.weight),r[o.v]=s}),t.edges().forEach(o=>{let i=r[o.v],s=r[o.w];i!==void 0&&s!==void 0&&(s.indegree++,i.out.push(s))});let n=Object.values(r).filter(o=>!o.indegree);return gA(n)}function gA(e){let t=[];function r(o){return i=>{i.merged||(i.barycenter===void 0||o.barycenter===void 0||i.barycenter>=o.barycenter)&&mA(o,i)}}function n(o){return i=>{i.in.push(o),--i.indegree===0&&e.push(i)}}for(;e.length;){let o=e.pop();t.push(o),o.in.reverse().forEach(r(o)),o.out.forEach(n(o))}return t.filter(o=>!o.merged).map(o=>Hd(o,["vs","i","barycenter","weight"]))}function mA(e,t){let r=0,n=0;e.weight&&(r+=e.barycenter*e.weight,n+=e.weight),t.weight&&(r+=t.barycenter*t.weight,n+=t.weight),e.vs=t.vs.concat(e.vs),e.barycenter=r/n,e.weight=n,e.i=Math.min(t.i,e.i),t.merged=!0}function vA(e,t){let r=_S(e,f=>Object.hasOwn(f,"barycenter")),n=r.lhs,o=r.rhs.sort((f,p)=>p.i-f.i),i=[],s=0,a=0,l=0;n.sort(_A(!!t)),l=_I(i,o,l),n.forEach(f=>{l+=f.vs.length,i.push(f.vs),s+=f.barycenter*f.weight,a+=f.weight,l=_I(i,o,l)});let c={vs:i.flat(1)};return a&&(c.barycenter=s/a,c.weight=a),c}function _I(e,t,r){let n;for(;t.length&&(n=t[t.length-1]).i<=r;)t.pop(),e.push(n.vs),r++;return r}function _A(e){return(t,r)=>t.barycenterr.barycenter?1:e?r.i-t.i:t.i-r.i}function WI(e,t,r,n){let o=e.children(t),i=e.node(t),s=i?i.borderLeft:void 0,a=i?i.borderRight:void 0,l={};s&&(o=o.filter(u=>u!==s&&u!==a));let c=pA(e,o);c.forEach(u=>{if(e.children(u.v).length){let h=WI(e,u.v,r,n);l[u.v]=h,Object.hasOwn(h,"barycenter")&&xA(u,h)}});let f=hA(c,r);bA(f,l);let p=vA(f,n);if(s&&a){p.vs=[s,p.vs,a].flat(1);let u=e.predecessors(s);if(u&&u.length){let h=e.node(u[0]),g=e.predecessors(a),b=e.node(g[0]);Object.hasOwn(p,"barycenter")||(p.barycenter=0,p.weight=0),p.barycenter=(p.barycenter*p.weight+h.order+b.order)/(p.weight+2),p.weight+=2}}return p}function bA(e,t){e.forEach(r=>{r.vs=r.vs.flatMap(n=>t[n]?t[n].vs:n)})}function xA(e,t){e.barycenter!==void 0?(e.barycenter=(e.barycenter*e.weight+t.barycenter*t.weight)/(e.weight+t.weight),e.weight+=t.weight):(e.barycenter=t.barycenter,e.weight=t.weight)}function yA(e,t,r,n){n||(n=e.nodes());let o=wA(e),i=new cn({compound:!0}).setGraph({root:o}).setDefaultNodeLabel(s=>e.node(s));return n.forEach(s=>{let a=e.node(s),l=e.parent(s);if(a.rank===t||a.minRank<=t&&t<=a.maxRank){i.setNode(s),i.setParent(s,l||o);let c=e[r](s);c&&c.forEach(f=>{let p=f.v===s?f.w:f.v,u=i.edge(p,s),h=u!==void 0?u.weight:0;i.setEdge(p,s,{weight:e.edge(f).weight+h})}),Object.hasOwn(a,"minRank")&&i.setNode(s,{borderLeft:a.borderLeft[t],borderRight:a.borderRight[t]})}}),i}function wA(e){let t;for(;e.hasNode(t=ph("_root")););return t}function IA(e,t,r){let n={},o;r.forEach(i=>{let s=e.parent(i),a,l;for(;s;){if(a=e.parent(s),a?(l=n[a],n[a]=s):(l=o,o=s),l&&l!==s){t.setEdge(l,s);return}s=a}})}function HI(e,t={}){if(typeof t.customOrder=="function"){t.customOrder(e,HI);return}let r=ZI(e),n=bI(e,Sl(1,r+1),"inEdges"),o=bI(e,Sl(r-1,-1,-1),"outEdges"),i=dA(e);if(xI(e,i),t.disableOptimalOrderHeuristic)return;let s=Number.POSITIVE_INFINITY,a,l=t.constraints||[];for(let c=0,f=0;f<4;++c,++f){CA(c%2?n:o,c%4>=2,l),i=Al(e);let p=uA(e,i);p{n.has(i)||n.set(i,[]),n.get(i).push(s)};for(let i of e.nodes()){let s=e.node(i);if(typeof s.rank=="number"&&o(s.rank,i),typeof s.minRank=="number"&&typeof s.maxRank=="number")for(let a=s.minRank;a<=s.maxRank;a++)a!==s.rank&&o(a,i)}return t.map(function(i){return yA(e,i,r,n.get(i)||[])})}function CA(e,t,r){let n=new cn;e.forEach(function(o){r.forEach(a=>n.setEdge(a.left,a.right));let i=o.graph().root,s=WI(o,i,n,t);s.vs.forEach((a,l)=>o.node(a).order=l),IA(o,n,s.vs)})}function xI(e,t){Object.values(t).forEach(r=>r.forEach((n,o)=>e.node(n).order=o))}function EA(e,t){let r={};function n(o,i){let s=0,a=0,l=o.length,c=i[i.length-1];return i.forEach((f,p)=>{let u=BA(e,f),h=u?e.node(u).order:l;(u||f===c)&&(i.slice(a,p+1).forEach(g=>{let b=e.predecessors(g);b&&b.forEach(x=>{let w=e.node(x),C=w.order;(C{let p=i[f];if(p!==void 0&&e.node(p).dummy){let u=e.predecessors(p);u&&u.forEach(h=>{if(h===void 0)return;let g=e.node(h);g.dummy&&(g.orderc)&&zI(r,h,p)})}})}function o(i,s){let a=-1,l=-1,c=0;return s.forEach((f,p)=>{if(e.node(f).dummy==="border"){let u=e.predecessors(f);if(u&&u.length){let h=u[0];if(h===void 0)return;l=e.node(h).order,n(s,c,p,a,l),c=p,a=l}}n(s,c,s.length,l,i.length)}),s}return t.length&&t.reduce(o),r}function BA(e,t){if(e.node(t).dummy){let r=e.predecessors(t);if(r)return r.find(n=>e.node(n).dummy)}}function zI(e,t,r){if(t>r){let o=t;t=r,r=o}let n=e[t];n||(e[t]=n={}),n[r]=!0}function kA(e,t,r){if(t>r){let o=t;t=r,r=o}let n=e[t];return n!==void 0&&Object.hasOwn(n,r)}function SA(e,t,r,n){let o={},i={},s={};return t.forEach(a=>{a.forEach((l,c)=>{o[l]=l,i[l]=l,s[l]=c})}),t.forEach(a=>{let l=-1;a.forEach(c=>{let f=n(c);if(f&&f.length){let p=f.sort((h,g)=>{let b=s[h],x=s[g];return(b!==void 0?b:0)-(x!==void 0?x:0)}),u=(p.length-1)/2;for(let h=Math.floor(u),g=Math.ceil(u);h<=g;++h){let b=p[h];if(b===void 0)continue;let x=s[b];if(x!==void 0&&i[c]===c&&l{var w;let C=(w=i[x.v])!=null?w:0,E=s.edge(x);return Math.max(b,C+(E!==void 0?E:0))},0):i[h]=0}function f(h){let g=s.outEdges(h),b=Number.POSITIVE_INFINITY;g&&(b=g.reduce((w,C)=>{let E=i[C.w],I=s.edge(C);return Math.min(w,(E!==void 0?E:0)-(I!==void 0?I:0))},Number.POSITIVE_INFINITY));let x=e.node(h);b!==Number.POSITIVE_INFINITY&&x.borderType!==a&&(i[h]=Math.max(i[h]!==void 0?i[h]:0,b))}function p(h){return s.predecessors(h)||[]}function u(h){return s.successors(h)||[]}return l(c,p),l(f,u),Object.keys(n).forEach(h=>{var g;let b=r[h];b!==void 0&&(i[h]=(g=i[b])!=null?g:0)}),i}function NA(e,t,r,n){let o=new cn,i=e.graph(),s=RA(i.nodesep,i.edgesep,n);return t.forEach(a=>{let l;a.forEach(c=>{let f=r[c];if(f!==void 0){if(o.setNode(f),l!==void 0){let p=r[l];if(p!==void 0){let u=o.edge(p,f);o.setEdge(p,f,Math.max(s(e,c,l),u||0))}}l=c}})}),o}function FA(e,t){return Object.values(t).reduce((r,n)=>{let o=Number.NEGATIVE_INFINITY,i=Number.POSITIVE_INFINITY;Object.entries(n).forEach(([a,l])=>{let c=LA(e,a)/2;o=Math.max(l+c,o),i=Math.min(l-c,i)});let s=o-i;return s{["l","r"].forEach(s=>{let a=i+s,l=e[a];if(!l||l===t)return;let c=Object.values(l),f=n-On(Math.min,c);s!=="l"&&(f=o-On(Math.max,c)),f&&(e[a]=zd(l,p=>p+f))})})}function ZA(e,t=void 0){let r=e.ul;return r?zd(r,(n,o)=>{var i,s;if(t){let l=t.toLowerCase(),c=e[l];if(c&&c[o]!==void 0)return c[o]}let a=Object.values(e).map(l=>{let c=l[o];return c!==void 0?c:0}).sort((l,c)=>l-c);return(((i=a[1])!=null?i:0)+((s=a[2])!=null?s:0))/2}):{}}function QA(e){let t=Al(e),r=Object.assign(EA(e,t),$A(e,t)),n={},o;["u","d"].forEach(s=>{o=s==="u"?t:Object.values(t).reverse(),["l","r"].forEach(a=>{a==="r"&&(o=o.map(f=>Object.values(f).reverse()));let l=SA(e,o,r,f=>(s==="u"?e.predecessors(f):e.successors(f))||[]),c=AA(e,o,l.root,l.align,a==="r");a==="r"&&(c=zd(c,f=>-f)),n[s+a]=c})});let i=FA(e,n);return GA(n,i),ZA(n,e.graph().align)}function RA(e,t,r){return(n,o,i)=>{let s=n.node(o),a=n.node(i),l=0,c;if(l+=s.width/2,Object.hasOwn(s,"labelpos"))switch(s.labelpos.toLowerCase()){case"l":c=-s.width/2;break;case"r":c=s.width/2;break}if(c&&(l+=r?c:-c),c=void 0,l+=(s.dummy?t:e)/2,l+=(a.dummy?t:e)/2,l+=a.width/2,Object.hasOwn(a,"labelpos"))switch(a.labelpos.toLowerCase()){case"l":c=a.width/2;break;case"r":c=-a.width/2;break}return c&&(l+=r?c:-c),l}}function LA(e,t){return e.node(t).width}function UA(e){e=FI(e),TA(e),Object.entries(QA(e)).forEach(([t,r])=>e.node(t).x=r)}function TA(e){let t=Al(e),r=e.graph(),n=r.ranksep,o=r.rankalign,i=0;t.forEach(s=>{let a=s.reduce((l,c)=>{var f;let p=(f=e.node(c).height)!=null?f:0;return l>p?l:p},0);s.forEach(l=>{let c=e.node(l);o==="top"?c.y=i+c.height/2:o==="bottom"?c.y=i+a-c.height/2:c.y=i+a/2}),i+=a+n})}function VA(e,t={}){let r=t.debugTiming?QI:RI;return r("layout",()=>{let n=r(" buildLayoutGraph",()=>JA(e));return r(" runLayout",()=>DA(n,r,t)),r(" updateInputGraph",()=>OA(e,n)),n})}function DA(e,t,r){t(" makeSpaceForEdgeLabels",()=>jA(e)),t(" removeSelfEdges",()=>sN(e)),t(" acyclic",()=>AS(e)),t(" nestingGraph.run",()=>eA(e)),t(" rank",()=>HS(FI(e))),t(" injectEdgeLabelProxies",()=>KA(e)),t(" removeEmptyRanks",()=>mS(e)),t(" nestingGraph.cleanup",()=>nA(e)),t(" normalizeRanks",()=>gS(e)),t(" assignRankMinMax",()=>qA(e)),t(" removeEdgeLabelProxies",()=>eN(e)),t(" normalize.run",()=>GS(e)),t(" parentDummyChains",()=>JS(e)),t(" addBorderSegments",()=>oA(e)),t(" order",()=>HI(e,r)),t(" insertSelfEdges",()=>aN(e)),t(" adjustCoordinateSystem",()=>sA(e)),t(" position",()=>UA(e)),t(" positionSelfEdges",()=>lN(e)),t(" removeBorderNodes",()=>iN(e)),t(" normalize.undo",()=>QS(e)),t(" fixupEdgeLabelCoords",()=>nN(e)),t(" undoCoordinateSystem",()=>aA(e)),t(" translateGraph",()=>tN(e)),t(" assignNodeIntersects",()=>rN(e)),t(" reversePoints",()=>oN(e)),t(" acyclic.undo",()=>FS(e))}function OA(e,t){e.nodes().forEach(r=>{let n=e.node(r),o=t.node(r);n&&(n.x=o.x,n.y=o.y,n.order=o.order,n.rank=o.rank,t.children(r).length&&(n.width=o.width,n.height=o.height))}),e.edges().forEach(r=>{let n=e.edge(r),o=t.edge(r);n.points=o.points,Object.hasOwn(o,"x")&&(n.x=o.x,n.y=o.y)}),e.graph().width=t.graph().width,e.graph().height=t.graph().height}function JA(e){let t=new cn({multigraph:!0,compound:!0}),r=dh(e.graph());return t.setGraph(Object.assign({},MA,ch(r,XA),Hd(r,WA))),e.nodes().forEach(n=>{let o=dh(e.node(n)),i=ch(o,HA);Object.keys(yI).forEach(a=>{i[a]===void 0&&(i[a]=yI[a])}),t.setNode(n,i);let s=e.parent(n);s!==void 0&&t.setParent(n,s)}),e.edges().forEach(n=>{let o=dh(e.edge(n));t.setEdge(n,Object.assign({},YA,ch(o,zA),Hd(o,PA)))}),t}function jA(e){let t=e.graph();t.ranksep/=2,e.edges().forEach(r=>{let n=e.edge(r);n.minlen*=2,n.labelpos.toLowerCase()!=="c"&&(t.rankdir==="TB"||t.rankdir==="BT"?n.width+=n.labeloffset:n.height+=n.labeloffset)})}function KA(e){e.edges().forEach(t=>{let r=e.edge(t);if(r.width&&r.height){let n=e.node(t.v),o={rank:(e.node(t.w).rank-n.rank)/2+n.rank,e:t};Ps(e,"edge-proxy",o,"_ep")}})}function qA(e){let t=0;e.nodes().forEach(r=>{let n=e.node(r);n.borderTop&&(n.minRank=e.node(n.borderTop).rank,n.maxRank=e.node(n.borderBottom).rank,t=Math.max(t,n.maxRank))}),e.graph().maxRank=t}function eN(e){e.nodes().forEach(t=>{let r=e.node(t);if(r.dummy==="edge-proxy"){let n=r;e.edge(n.e).labelRank=r.rank,e.removeNode(t)}})}function tN(e){let t=Number.POSITIVE_INFINITY,r=0,n=Number.POSITIVE_INFINITY,o=0,i=e.graph(),s=i.marginx||0,a=i.marginy||0;function l(c){let f=c.x,p=c.y,u=c.width,h=c.height;t=Math.min(t,f-u/2),r=Math.max(r,f+u/2),n=Math.min(n,p-h/2),o=Math.max(o,p+h/2)}e.nodes().forEach(c=>l(e.node(c))),e.edges().forEach(c=>{let f=e.edge(c);Object.hasOwn(f,"x")&&l(f)}),t-=s,n-=a,e.nodes().forEach(c=>{let f=e.node(c);f.x-=t,f.y-=n}),e.edges().forEach(c=>{let f=e.edge(c);f.points.forEach(p=>{p.x-=t,p.y-=n}),Object.hasOwn(f,"x")&&(f.x-=t),Object.hasOwn(f,"y")&&(f.y-=n)}),i.width=r-t+s,i.height=o-n+a}function rN(e){e.edges().forEach(t=>{let r=e.edge(t),n=e.node(t.v),o=e.node(t.w),i,s;r.points?(i=r.points[0],s=r.points[r.points.length-1]):(r.points=[],i=o,s=n),r.points.unshift(uI(n,i)),r.points.push(uI(o,s))})}function nN(e){e.edges().forEach(t=>{let r=e.edge(t);if(Object.hasOwn(r,"x"))switch((r.labelpos==="l"||r.labelpos==="r")&&(r.width-=r.labeloffset),r.labelpos){case"l":r.x-=r.width/2+r.labeloffset;break;case"r":r.x+=r.width/2+r.labeloffset;break}})}function oN(e){e.edges().forEach(t=>{let r=e.edge(t);r.reversed&&r.points.reverse()})}function iN(e){e.nodes().forEach(t=>{if(e.children(t).length){let r=e.node(t),n=e.node(r.borderTop),o=e.node(r.borderBottom),i=e.node(r.borderLeft[r.borderLeft.length-1]),s=e.node(r.borderRight[r.borderRight.length-1]);r.width=Math.abs(s.x-i.x),r.height=Math.abs(o.y-n.y),r.x=i.x+r.width/2,r.y=n.y+r.height/2}}),e.nodes().forEach(t=>{e.node(t).dummy==="border"&&e.removeNode(t)})}function sN(e){e.edges().forEach(t=>{if(t.v===t.w){let r=e.node(t.v);r.selfEdges||(r.selfEdges=[]),r.selfEdges.push({e:t,label:e.edge(t)}),e.removeEdge(t)}})}function aN(e){Al(e).forEach(t=>{let r=0;t.forEach((n,o)=>{let i=e.node(n);i.order=o+r,(i.selfEdges||[]).forEach(s=>{Ps(e,"selfedge",{width:s.label.width,height:s.label.height,rank:i.rank,order:o+ ++r,e:s.e,label:s.label},"_se")}),delete i.selfEdges})})}function lN(e){e.nodes().forEach(t=>{let r=e.node(t);if(r.dummy==="selfedge"){let n=r,o=e.node(n.e.v),i=o.x+o.width/2,s=o.y,a=r.x-i,l=o.height/2;e.setEdge(n.e,n.label),e.removeNode(t),n.label.points=[{x:i+2*a/3,y:s-l},{x:i+5*a/6,y:s-l},{x:i+a,y:s},{x:i+5*a/6,y:s+l},{x:i+2*a/3,y:s+l}],n.label.x=r.x,n.label.y=r.y}})}function ch(e,t){return zd(Hd(e,t),Number)}function dh(e){let t={};return e&&Object.entries(e).forEach(([r,n])=>{typeof r=="string"&&(r=r.toLowerCase()),t[r]=n}),t}function cN(e){let t=Al(e),r=new cn({compound:!0,multigraph:!0}).setGraph({});return e.nodes().forEach(n=>{r.setNode(n,{label:n}),r.setParent(n,"layer"+e.node(n).rank)}),e.edges().forEach(n=>r.setEdge(n.v,n.w,{},n.name)),t.forEach((n,o)=>{let i="layer"+o;r.setNode(i,{rank:"same"}),n.reduce((s,a)=>(r.setEdge(s,a,{style:"invis"}),a))}),r}var wI,Dk,Ok,Xk,II,Mk,CI,cn,Hk,EI,fh,jk,BI,eS,oS,Wd,GI,bS,Yd,yS,wS,CS,ES,LI,VS,DS,OS,HS,YS,JS,oA,XA,MA,WA,HA,yI,zA,YA,PA,dN,vh,YI=v(()=>{wI=Object.defineProperty,Dk=(e,t,r)=>t in e?wI(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,Ok=(e,t)=>{for(var r in t)wI(e,r,{get:t[r],enumerable:!0})},Xk=(e,t,r)=>Dk(e,typeof t!="symbol"?t+"":t,r),II={};Ok(II,{Graph:()=>cn,alg:()=>fh,json:()=>EI,version:()=>Hk});Mk=Object.defineProperty,CI=(e,t)=>{for(var r in t)Mk(e,r,{get:t[r],enumerable:!0})},cn=class{constructor(e){this._isDirected=!0,this._isMultigraph=!1,this._isCompound=!1,this._nodes={},this._in={},this._preds={},this._out={},this._sucs={},this._edgeObjs={},this._edgeLabels={},this._nodeCount=0,this._edgeCount=0,this._defaultNodeLabelFn=()=>{},this._defaultEdgeLabelFn=()=>{},e&&(this._isDirected="directed"in e?e.directed:!0,this._isMultigraph="multigraph"in e?e.multigraph:!1,this._isCompound="compound"in e?e.compound:!1),this._isCompound&&(this._parent={},this._children={},this._children["\0"]={})}isDirected(){return this._isDirected}isMultigraph(){return this._isMultigraph}isCompound(){return this._isCompound}setGraph(e){return this._label=e,this}graph(){return this._label}setDefaultNodeLabel(e){return typeof e!="function"?this._defaultNodeLabelFn=()=>e:this._defaultNodeLabelFn=e,this}nodeCount(){return this._nodeCount}nodes(){return Object.keys(this._nodes)}sources(){return this.nodes().filter(e=>Object.keys(this._in[e]).length===0)}sinks(){return this.nodes().filter(e=>Object.keys(this._out[e]).length===0)}setNodes(e,t){return e.forEach(r=>{t!==void 0?this.setNode(r,t):this.setNode(r)}),this}setNode(e,t){return e in this._nodes?(arguments.length>1&&(this._nodes[e]=t),this):(this._nodes[e]=arguments.length>1?t:this._defaultNodeLabelFn(e),this._isCompound&&(this._parent[e]="\0",this._children[e]={},this._children["\0"][e]=!0),this._in[e]={},this._preds[e]={},this._out[e]={},this._sucs[e]={},++this._nodeCount,this)}node(e){return this._nodes[e]}hasNode(e){return e in this._nodes}removeNode(e){if(e in this._nodes){let t=r=>this.removeEdge(this._edgeObjs[r]);delete this._nodes[e],this._isCompound&&(this._removeFromParentsChildList(e),delete this._parent[e],this.children(e).forEach(r=>{this.setParent(r)}),delete this._children[e]),Object.keys(this._in[e]).forEach(t),delete this._in[e],delete this._preds[e],Object.keys(this._out[e]).forEach(t),delete this._out[e],delete this._sucs[e],--this._nodeCount}return this}setParent(e,t){if(!this._isCompound)throw new Error("Cannot set parent in a non-compound graph");if(t===void 0)t="\0";else{t+="";for(let r=t;r!==void 0;r=this.parent(r))if(r===e)throw new Error("Setting "+t+" as parent of "+e+" would create a cycle");this.setNode(t)}return this.setNode(e),this._removeFromParentsChildList(e),this._parent[e]=t,this._children[t][e]=!0,this}parent(e){if(this._isCompound){let t=this._parent[e];if(t!=="\0")return t}}children(e="\0"){if(this._isCompound){let t=this._children[e];if(t)return Object.keys(t)}else{if(e==="\0")return this.nodes();if(this.hasNode(e))return[]}return[]}predecessors(e){let t=this._preds[e];if(t)return Object.keys(t)}successors(e){let t=this._sucs[e];if(t)return Object.keys(t)}neighbors(e){let t=this.predecessors(e);if(t){let r=new Set(t);for(let n of this.successors(e))r.add(n);return Array.from(r.values())}}isLeaf(e){let t;return this.isDirected()?t=this.successors(e):t=this.neighbors(e),t.length===0}filterNodes(e){let t=new this.constructor({directed:this._isDirected,multigraph:this._isMultigraph,compound:this._isCompound});t.setGraph(this.graph()),Object.entries(this._nodes).forEach(([o,i])=>{e(o)&&t.setNode(o,i)}),Object.values(this._edgeObjs).forEach(o=>{t.hasNode(o.v)&&t.hasNode(o.w)&&t.setEdge(o,this.edge(o))});let r={},n=o=>{let i=this.parent(o);return!i||t.hasNode(i)?(r[o]=i??void 0,i??void 0):i in r?r[i]:n(i)};return this._isCompound&&t.nodes().forEach(o=>t.setParent(o,n(o))),t}setDefaultEdgeLabel(e){return typeof e!="function"?this._defaultEdgeLabelFn=()=>e:this._defaultEdgeLabelFn=e,this}edgeCount(){return this._edgeCount}edges(){return Object.values(this._edgeObjs)}setPath(e,t){return e.reduce((r,n)=>(t!==void 0?this.setEdge(r,n,t):this.setEdge(r,n),n)),this}setEdge(e,t,r,n){let o,i,s,a,l=!1;typeof e=="object"&&e!==null&&"v"in e?(o=e.v,i=e.w,s=e.name,arguments.length===2&&(a=t,l=!0)):(o=e,i=t,s=n,arguments.length>2&&(a=r,l=!0)),o=""+o,i=""+i,s!==void 0&&(s=""+s);let c=kl(this._isDirected,o,i,s);if(c in this._edgeLabels)return l&&(this._edgeLabels[c]=a),this;if(s!==void 0&&!this._isMultigraph)throw new Error("Cannot set a named edge when isMultigraph = false");this.setNode(o),this.setNode(i),this._edgeLabels[c]=l?a:this._defaultEdgeLabelFn(o,i,s);let f=Wk(this._isDirected,o,i,s);return o=f.v,i=f.w,Object.freeze(f),this._edgeObjs[c]=f,cI(this._preds[i],o),cI(this._sucs[o],i),this._in[i][c]=f,this._out[o][c]=f,this._edgeCount++,this}edge(e,t,r){let n=arguments.length===1?ih(this._isDirected,e):kl(this._isDirected,e,t,r);return this._edgeLabels[n]}edgeAsObj(e,t,r){let n=arguments.length===1?this.edge(e):this.edge(e,t,r);return typeof n!="object"?{label:n}:n}hasEdge(e,t,r){return(arguments.length===1?ih(this._isDirected,e):kl(this._isDirected,e,t,r))in this._edgeLabels}removeEdge(e,t,r){let n=arguments.length===1?ih(this._isDirected,e):kl(this._isDirected,e,t,r),o=this._edgeObjs[n];if(o){let i=o.v,s=o.w;delete this._edgeLabels[n],delete this._edgeObjs[n],dI(this._preds[s],i),dI(this._sucs[i],s),delete this._in[s][n],delete this._out[i][n],this._edgeCount--}return this}inEdges(e,t){return this.isDirected()?this.filterEdges(this._in[e],e,t):this.nodeEdges(e,t)}outEdges(e,t){return this.isDirected()?this.filterEdges(this._out[e],e,t):this.nodeEdges(e,t)}nodeEdges(e,t){if(e in this._nodes)return this.filterEdges({...this._in[e],...this._out[e]},e,t)}_removeFromParentsChildList(e){delete this._children[this._parent[e]][e]}filterEdges(e,t,r){if(!e)return;let n=Object.values(e);return r?n.filter(o=>o.v===t&&o.w===r||o.v===r&&o.w===t):n}};Hk="4.0.1",EI={};CI(EI,{read:()=>Jk,write:()=>zk});fh={};CI(fh,{CycleException:()=>Wd,bellmanFord:()=>$I,components:()=>qk,dijkstra:()=>Md,dijkstraAll:()=>rS,findCycles:()=>nS,floydWarshall:()=>iS,isAcyclic:()=>aS,postorder:()=>cS,preorder:()=>dS,prim:()=>uS,shortestPaths:()=>fS,tarjan:()=>kI,topsort:()=>SI});jk=()=>1;BI=class{constructor(){this._arr=[],this._keyIndices={}}size(){return this._arr.length}keys(){return this._arr.map(e=>e.key)}has(e){return e in this._keyIndices}priority(e){let t=this._keyIndices[e];if(t!==void 0)return this._arr[t].priority}min(){if(this.size()===0)throw new Error("Queue underflow");return this._arr[0].key}add(e,t){let r=this._keyIndices,n=String(e);if(!(n in r)){let o=this._arr,i=o.length;return r[n]=i,o.push({key:n,priority:t}),this._decrease(i),!0}return!1}removeMin(){this._swap(0,this._arr.length-1);let e=this._arr.pop();return delete this._keyIndices[e.key],this._heapify(0),e.key}decrease(e,t){let r=this._keyIndices[e];if(r===void 0)throw new Error(`Key not found: ${e}`);let n=this._arr[r].priority;if(t>n)throw new Error(`New priority is greater than current priority. Key: ${e} Old: ${n} New: ${t}`);this._arr[r].priority=t,this._decrease(r)}_heapify(e){let t=this._arr,r=2*e,n=r+1,o=e;r>1,!(t[n].priority1;oS=()=>1;Wd=class extends Error{constructor(...e){super(...e)}};GI=65535;bS=0;Yd="\0",yS="3.0.0",wS=class{constructor(){Xk(this,"_sentinel");let e={};e._next=e._prev=e,this._sentinel=e}dequeue(){let e=this._sentinel,t=e._prev;if(t!==e)return pI(t),t}enqueue(e){let t=this._sentinel;e._prev&&e._next&&pI(e),e._next=t._next,t._next._prev=e,t._next=e,e._prev=t}toString(){let e=[],t=this._sentinel,r=t._prev;for(;r!==t;)e.push(JSON.stringify(r,IS)),r=r._prev;return"["+e.join(", ")+"]"}};CS=wS,ES=()=>1;LI=RS;({preorder:VS,postorder:DS}=fh),OS=Ti;Ti.initLowLimValues=mh;Ti.initCutValues=gh;Ti.calcCutValue=UI;Ti.leaveEdge=VI;Ti.enterEdge=DI;Ti.exchangeEdges=OI;HS=zS;YS=hh;JS=jS;oA=iA;XA=["nodesep","edgesep","ranksep","marginx","marginy"],MA={ranksep:50,edgesep:20,nodesep:50,rankdir:"TB",rankalign:"center"},WA=["acyclicer","ranker","rankdir","align","rankalign"],HA=["width","height","rank"],yI={width:0,height:0},zA=["minlen","weight","width","height","labeloffset"],YA={minlen:1,weight:1,width:0,height:0,labeloffset:10,labelpos:"r"},PA=["labelpos"];dN={graphlib:II,version:yS,layout:VA,debug:cN,util:{time:QI,notime:RI}},vh=dN;});var JI={};jd(JI,{default:()=>PI});function PI(e,t){K(t,!0);let r=188,n=66;function o(f){let p=new vh.graphlib.Graph;p.setGraph({rankdir:"TB",nodesep:56,ranksep:84,marginx:24,marginy:24}),p.setDefaultEdgeLabel(()=>({}));for(let g of f.nodes)p.setNode(g.fqn,{width:r,height:n});for(let g of f.edges)p.setEdge(g.from,g.to);vh.layout(p);let u=f.nodes.map(g=>{let b=p.node(g.fqn);return{id:g.fqn,position:{x:b.x-r/2,y:b.y-n/2},data:{label:g.label,kind:g.kind,summary:g.summary??""},class:`c4-node ${g.kind}`,width:r,height:n}}),h=f.edges.map((g,b)=>({id:`e${b}`,source:g.from,target:g.to,label:g.label||void 0,type:"smoothstep",animated:g.kind==="trigger",class:`c4-edge ${g.kind}`}));return{nodes:u,edges:h}}let i=o(t.scene),s=we(Xt(i.nodes)),a=we(Xt(i.edges));var l=fN(),c=V(l);Ui(c,{fitView:!0,minZoom:.2,maxZoom:2.5,proOptions:{hideAttribution:!0},get nodes(){return d(s)},set nodes(f){X(s,f,!0)},get edges(){return d(a)},set edges(f){X(a,f,!0)},children:(f,p)=>{var u=uN(),h=ve(u);zs(h,{gap:22});var g=P(h,2);Xd(g,{pannable:!0,zoomable:!0});var b=P(g,2);Od(b,{showLock:!1}),N(f,u)},$$slots:{default:!0}}),L(l),N(e,l),q()}var uN,fN,jI=v(()=>{_e();ae();oh();YI();uN=Y(" ",1),fN=Y('
')});var KI=v(()=>{});var eC={};jd(eC,{default:()=>qI});function qI(e,t){K(t,!0);let r=M=>M.split("::").pop();function n(M){if(M)return M.kind==="return"?M.detail?M.label?`${M.label}<${M.detail}>`:`return ${M.detail}`:M.label||"return":M.label||void 0}function o(M,ce,ne){for(let ie of M)ie.Message?ne.push({...ie.Message,frame:ce}):ie.Frame&&o(ie.Frame.body,`${ie.Frame.kind} ${ie.Frame.cond}`,ne);return ne}let i=o(t.scene.items,null,[]),s=new Map(t.scene.participants.map(M=>[M.fqn,M.kind])),a=230,l=168,c=we(0),f=we(!1),p=null;function u(){p&&clearInterval(p),p=null,X(f,!1)}function h(){d(c)>=i.length&&X(c,0),X(f,!0),p=setInterval(()=>d(c)>=i.length?u():X(c,d(c)+1),1150)}let g=()=>d(f)?u():h(),b=M=>{u(),X(c,Math.max(0,Math.min(i.length,d(c)+M)),!0)};ao(u);function x(M){let ce=[],ne=ie=>{ce.includes(ie)||ce.push(ie)};ne(t.scene.entry);for(let ie=0;ie{let M=x(d(c));X(w,M.map((ce,ne)=>({id:ce,position:{x:ne*a+30,y:80},data:{label:r(ce),kind:s.get(ce)??"component"},class:`c4-node ${s.get(ce)??"component"}`,width:l,height:58,selectable:!1,draggable:!1})),!0),X(C,i.slice(0,d(c)).map((ce,ne)=>({id:`m${ne}`,source:ce.from,target:ce.to,label:n(ce),type:"smoothstep",animated:ne===d(c)-1,class:`flow-edge ${ne===d(c)-1?"current":"past"}`})),!0)});let E=_(()=>d(c)>0?i[d(c)-1]:null),I=_(()=>d(c)>=i.length&&i.length>0);var T=vN(),B=V(T),Z=V(B),R=P(V(Z),2),O=V(R,!0);L(R),L(Z);var H=P(Z,2),F=V(H);{var $=M=>{var ce=gN(),ne=ve(ce),ie=V(ne,!0);L(ne);var pe=P(ne,4),ke=V(pe,!0);L(pe);var Qe=P(pe,2);{var Se=Je=>{var et=pN(),xt=V(et,!0);L(et),te(Fe=>he(xt,Fe),[()=>n(d(E))]),N(Je,et)},ot=_(()=>n(d(E)));ue(Qe,Je=>{d(ot)&&Je(Se)})}var Re=P(Qe,2);{var ut=Je=>{var et=hN(),xt=V(et,!0);L(et),te(()=>he(xt,d(E).frame)),N(Je,et)};ue(Re,Je=>{d(E).frame&&Je(ut)})}te((Je,et,xt,Fe)=>{Pe(ne,1,`chip ${Je??""}`,"svelte-1kd9vyo"),he(ie,et),Pe(pe,1,`chip ${xt??""}`,"svelte-1kd9vyo"),he(ke,Fe)},[()=>s.get(d(E).from)??"component",()=>r(d(E).from),()=>s.get(d(E).to)??"component",()=>r(d(E).to)]),N(M,ce)},Q=M=>{var ce=mN();N(M,ce)};ue(F,M=>{d(E)?M($):M(Q,-1)})}L(H),L(B);var y=P(B,2),S=V(y);Ui(S,{fitView:!0,minZoom:.2,maxZoom:2,nodesDraggable:!1,proOptions:{hideAttribution:!0},get nodes(){return d(w)},set nodes(M){X(w,M,!0)},get edges(){return d(C)},set edges(M){X(C,M,!0)},children:(M,ce)=>{zs(M,{gap:24})},$$slots:{default:!0}}),L(y);var k=P(y,2),D=V(k),J=P(D,2),W=V(J,!0);L(J);var j=P(J,2),ee=P(j,2);Cc(ee);var se=P(ee,2),de=V(se);L(se),L(k),L(T),te(M=>{he(O,M),D.disabled=d(c)===0,re(J,"aria-label",d(f)?"Pause":"Play"),he(W,d(f)?"\u275A\u275A":d(I)?"\u21BA":"\u25B6"),j.disabled=d(c)>=i.length,re(ee,"max",i.length),he(de,`${d(c)??""}/${i.length??""}`)},[()=>r(t.scene.entry)]),Pt("click",D,()=>b(-1)),Pt("click",J,g),Pt("click",j,()=>b(1)),Pt("input",ee,u),pf(ee,()=>d(c),M=>X(c,M)),N(e,T),q()}var pN,hN,gN,mN,vN,tC=v(()=>{_e();ae();Dr();oh();KI();pN=Y(' '),hN=Y(' '),gN=Y(' ',1),mN=Y('triggered entry point \u2014 press play to trace the request'),vN=Y('
flow
');oo(["click","input"])});Dr();_e();ae();Dr();_e();ae();_e();ae();var NE=Y(''),FE=Y(''),GE=Y('
    '),ZE=Y('
  • ');function Ta(e,t){K(t,!0);var r=ZE(),n=V(r),o=V(n);{var i=h=>{var g=NE();N(h,g)},s=h=>{var g=FE();N(h,g)};ue(o,h=>{t.node.children.length?h(i):h(s,-1)})}var a=P(o,2),l=V(a),c=P(l,2),f=V(c,!0);L(c),L(a),L(n);var p=P(n,2);{var u=h=>{var g=GE();Xe(g,21,()=>t.node.children,ht,(b,x)=>{Ta(b,{get node(){return d(x)}})}),L(g),N(h,g)};ue(p,h=>{t.node.children.length&&h(u)})}L(r),te(()=>{re(r,"data-search",t.node.fqn),re(a,"href",t.node.href),Pe(l,1,`kind-dot ${t.node.kind??""}`),he(f,t.node.name)}),N(e,r),q()}var QE=Y(''),RE=Y('
  • '),LE=Y('
      '),UE=Y(''),TE=Y('
      • '),VE=Y('');function yf(e,t){K(t,!0);let r=z(t,"docGroups",19,()=>[]);var n=VE(),o=V(n),i=V(o),s=V(i);{var a=h=>{var g=QE();te(()=>re(g,"src",`${t.site.prefix??""}${t.site.logoFilename??""}`)),N(h,g)};ue(s,h=>{t.site.logoFilename&&h(a)})}var l=P(s,2),c=V(l,!0);zt(),L(l),L(i),L(o);var f=P(o,4);{var p=h=>{var g=UE();Xe(g,21,r,ht,(b,x)=>{var w=LE(),C=V(w),E=V(C,!0);L(C);var I=P(C,2);Xe(I,21,()=>d(x).items,ht,(T,B)=>{var Z=RE(),R=V(Z),O=V(R,!0);L(R),L(Z),te(()=>{re(R,"href",d(B).href),he(O,d(B).title)}),N(T,Z)}),L(I),L(w),te(()=>he(E,d(x).title)),N(b,w)}),L(g),N(h,g)};ue(f,h=>{r().length&&h(p)})}var u=P(f,2);Xe(u,21,()=>t.sidebar,ht,(h,g)=>{var b=TE(),x=V(b),w=P(V(x),2),C=V(w,!0);L(w),L(x);var E=P(x,2);Xe(E,21,()=>d(g).nodes,ht,(I,T)=>{Ta(I,{get node(){return d(T)}})}),L(E),L(b),te(()=>{re(b,"data-search",d(g).label),re(w,"href",d(g).href),he(C,d(g).label)}),N(h,b)}),L(u),L(n),te(()=>{re(i,"href",`${t.site.prefix??""}index.html`),he(c,t.site.name)}),N(e,n),q()}_e();ae();_e();ae();Dr();var _N=Y('
        '),bN=Y('
        ');function Nl(e,t){K(t,!0);let r=we(null);$s(async()=>{if(!d(r)||t.diagram.diagram==="empty")return;let{mount:a}=await Promise.resolve().then(()=>(Dr(),Zv)),l=t.diagram.diagram==="c4"?await Promise.resolve().then(()=>(jI(),JI)):await Promise.resolve().then(()=>(tC(),eC));a(l.default,{target:d(r),props:{scene:t.diagram.scene}})});var n=Ve(),o=ve(n);{var i=a=>{var l=_N(),c=V(l);L(l),te(()=>he(c,`No ${t.diagram.eyebrow??""} diagram available.`)),N(a,l)},s=a=>{var l=bN(),c=V(l),f=V(c),p=V(f,!0);L(f);var u=P(f,2),h=V(u,!0);L(u),L(c);var g=P(c,2);Xr(g,b=>X(r,b),()=>d(r)),L(l),te(()=>{he(p,t.diagram.caption),he(h,t.diagram.diagram==="sequence"?"play \xB7 scrub the flow":"scroll to zoom \xB7 drag to pan"),re(g,"data-diagram",t.diagram.diagram)}),N(a,l)};ue(o,a=>{t.diagram.diagram==="empty"?a(i):a(s,-1)})}N(e,n),q()}var xN=Y('
        '),yN=Y(`
        Architecture documentation

        A C4 model of the workspace: persons, systems, and their containers and - components, with relationships and animated sequence flows.

        `,1);function _h(e,t){K(t,!0);var r=yN(),n=ve(r),o=P(V(n),2),i=V(o,!0);L(o),zt(2),L(n);var s=P(n,2);Nl(s,{get diagram(){return t.page.contextDiagram}});var a=P(s,2);Xe(a,21,()=>t.page.cards,ht,(l,c)=>{var f=xN(),p=V(f),u=V(p,!0);L(p);var h=P(p,2),g=V(h,!0);L(h),L(f),te(()=>{re(f,"href",d(c).href),he(u,d(c).name),he(g,d(c).meta)}),N(l,f)}),L(a),te(()=>he(i,t.page.title)),N(e,r),q()}_e();ae();_e();ae();_e();ae();var wN=Y(''),IN=Y(' '),CN=Y(' '),EN=Y(' '),$N=Y('
      • '),BN=Y('

          '),kN=Y('
          ');function bh(e,t){K(t,!0);var r=Ve(),n=ve(r);{var o=i=>{var s=kN();Xe(s,21,()=>t.groups,ht,(a,l)=>{var c=BN(),f=V(c),p=V(f,!0);L(f);var u=P(f,2);Xe(u,21,()=>d(l).items,ht,(h,g)=>{var b=$N(),x=V(b),w=V(x,!0);L(x);var C=P(x,2);{var E=O=>{var H=wN();N(O,H)};ue(C,O=>{d(g).arrow&&O(E)})}var I=P(C,2);{var T=O=>{var H=IN(),F=V(H,!0);L(H),te(()=>{re(H,"href",d(g).href),he(F,d(g).fqn)}),N(O,H)},B=O=>{var H=CN(),F=V(H,!0);L(H),te(()=>he(F,d(g).fqn)),N(O,H)};ue(I,O=>{d(g).href?O(T):O(B,-1)})}var Z=P(I,2);{var R=O=>{var H=EN(),F=V(H);L(H),te(()=>he(F,`\xB7 ${d(g).label??""}`)),N(O,H)};ue(Z,O=>{d(g).label&&O(R)})}L(b),te(()=>he(w,d(g).edgeKind)),N(h,b)}),L(u),L(c),te(()=>he(p,d(l).title)),N(a,c)}),L(s),N(i,s)};ue(n,i=>{t.groups.length&&i(o)})}N(e,r),q()}_e();ae();var SN=Y('

          '),AN=Y('

          '),NN=Y(' '),FN=Y('
          '),GN=Y('
        • '),ZN=Y('
            '),QN=Y('

            Scenarios

            ');function xh(e,t){K(t,!0);var r=Ve(),n=ve(r);{var o=i=>{var s=QN(),a=P(V(s),2);Xe(a,17,()=>t.scenarios,ht,(l,c)=>{var f=ZN(),p=V(f),u=V(p,!0);L(p);var h=P(p,2);{var g=I=>{var T=SN(),B=V(T,!0);L(T),te(()=>he(B,d(c).summary)),N(I,T)};ue(h,I=>{d(c).summary&&I(g)})}var b=P(h,2);{var x=I=>{var T=AN(),B=V(T,!0);L(T),te(()=>he(B,d(c).extended)),N(I,T)};ue(b,I=>{d(c).extended&&I(x)})}var w=P(b,2);{var C=I=>{var T=FN();Xe(T,21,()=>d(c).tags,ht,(B,Z)=>{var R=NN(),O=V(R,!0);L(R),te(()=>he(O,d(Z))),N(B,R)}),L(T),N(I,T)};ue(w,I=>{d(c).tags.length&&I(C)})}var E=P(w,2);Xe(E,21,()=>d(c).steps,ht,(I,T)=>{var B=GN(),Z=V(B),R=V(Z,!0);L(Z);var O=P(Z,2),H=V(O,!0);L(O),L(B),te(()=>{Pe(Z,1,`step-kw ${d(T).keyword??""}`),he(R,d(T).keyword),he(H,d(T).text)}),N(I,B)}),L(E),L(f),te(()=>he(u,d(c).name)),N(l,f)}),L(s),N(i,s)};ue(n,i=>{t.scenarios.length&&i(o)})}N(e,r),q()}var RN=Y('

            '),LN=Y('

            '),UN=Y(' '),TN=Y('
            '),VN=Y('

            #

            ');function yh(e,t){K(t,!0);var r=VN(),n=V(r),o=V(n),i=V(o,!0);L(o);var s=P(o,2),a=V(s),l=V(a,!0);L(a),zt(2),L(s);var c=P(s,2),f=V(c,!0);L(c),L(n);var p=P(n,2),u=V(p,!0);L(p);var h=P(p,2);{var g=B=>{var Z=RN(),R=V(Z,!0);L(Z),te(()=>he(R,t.section.summary)),N(B,Z)};ue(h,B=>{t.section.summary&&B(g)})}var b=P(h,2);{var x=B=>{var Z=LN(),R=V(Z,!0);L(Z),te(()=>he(R,t.section.extended)),N(B,Z)};ue(b,B=>{t.section.extended&&B(x)})}var w=P(b,2);{var C=B=>{var Z=TN();Xe(Z,21,()=>t.section.tags,ht,(R,O)=>{var H=UN(),F=V(H,!0);L(H),te(()=>he(F,d(O))),N(R,H)}),L(Z),N(B,Z)};ue(w,B=>{t.section.tags.length&&B(C)})}var E=P(w,2);bh(E,{get groups(){return t.section.relationships}});var I=P(E,2);xh(I,{get scenarios(){return t.section.scenarios}});var T=P(I,2);Xe(T,17,()=>t.section.diagrams,ht,(B,Z)=>{Nl(B,{get diagram(){return d(Z)}})}),L(r),te(()=>{re(r,"id",t.section.id),Pe(o,1,`kind-badge ${t.section.kind??""}`),he(i,t.section.kind),re(a,"href",`#${t.section.id??""}`),he(l,t.section.name),he(f,t.section.visibility),he(u,t.section.fqn)}),N(e,r),q()}var DN=Y('
            Module

            ',1);function wh(e,t){K(t,!0);var r=DN(),n=ve(r),o=P(V(n),2),i=V(o,!0);L(o),L(n);var s=P(n,2);Xe(s,17,()=>t.page.sections,ht,(a,l)=>{yh(a,{get section(){return d(l)}})}),te(()=>he(i,t.page.name)),N(e,r),q()}_e();ae();var ON=Y('
            Documentation

            ',1);function Ih(e,t){K(t,!0);var r=ON(),n=ve(r),o=P(V(n),2),i=V(o,!0);L(o),L(n);var s=P(n,2);Ku(s,()=>t.page.html,!0),L(s),te(()=>he(i,t.page.title)),N(e,r),q()}_e();Xo();ae();var XN=Y('
            Generated by pds doc.
            ');function Ch(e){var t=XN();N(e,t)}function rC(e){WN(e),HN(e),YN(e),MN(e)}function MN(e){let t=location.pathname.split("/").pop();t&&e.querySelectorAll(".docs-link").forEach(r=>{r.getAttribute("href").split("/").pop().split("#")[0]===t&&r.classList.add("is-active")})}function WN(e){e.querySelectorAll(".tree .toggle").forEach(t=>{t.addEventListener("click",r=>{r.preventDefault(),r.stopPropagation();let n=t.closest("li");n&&n.classList.toggle("collapsed")})})}function HN(e){let t=e.querySelector(".search input"),r=e.querySelector(".tree");if(!t||!r)return;let n=document.createElement("li");n.className="no-results",n.textContent="No matches",n.hidden=!0,r.appendChild(n),t.addEventListener("input",()=>{let o=t.value.trim().toLowerCase(),i=zN(r,o);n.hidden=i||o===""})}function zN(e,t){if(t==="")return e.querySelectorAll("li").forEach(n=>n.classList.remove("hidden")),!0;let r=!1;return e.querySelectorAll(":scope > li").forEach(n=>{nC(n,t,!1)&&(r=!0)}),r}function nC(e,t,r){let n=(e.dataset.search||"").toLowerCase(),o=r||n.indexOf(t)!==-1,i=!1;e.querySelectorAll(":scope > ul.children > li").forEach(a=>{nC(a,t,o)&&(i=!0)});let s=o||i;return e.classList.toggle("hidden",!s),s&&e.classList.remove("collapsed"),s}function YN(e){function t(){let r=decodeURIComponent(location.hash.replace(/^#/,""));if(e.querySelectorAll(".tree .node-link.is-active").forEach(o=>{o.classList.remove("is-active")}),!r)return;let n=e.querySelector('.tree a[href$="#'+PN(r)+'"]');if(n){n.classList.add("is-active");let o=n.closest("li");for(;o;){o.classList.remove("collapsed");let i=o.parentElement;o=i?i.closest("li"):null}}}window.addEventListener("hashchange",t),t()}function PN(e){return window.CSS&&window.CSS.escape?window.CSS.escape(e):e.replace(/[^a-zA-Z0-9_-]/g,"\\$&")}var JN=Y('
            ');function Eh(e,t){K(t,!0);let r=z(t,"docGroups",19,()=>[]);$s(()=>rC(document));var n=JN(),o=V(n);yf(o,{get site(){return t.site},get docGroups(){return r()},get sidebar(){return t.sidebar}});var i=P(o,2),s=V(i),a=V(s);{var l=u=>{_h(u,{get page(){return t.page}})},c=u=>{Ih(u,{get page(){return t.page}})},f=u=>{wh(u,{get page(){return t.page}})};ue(a,u=>{t.page.kind==="index"?u(l):t.page.kind==="doc"?u(c,1):u(f,-1)})}var p=P(a,2);Ch(p,{}),L(s),L(i),L(n),N(e,n),q()}var oC=document.getElementById("app");oC&&window.__DATA__&&Cs(Eh,{target:oC,props:window.__DATA__});})(); +`)}}}function Ih(e){let t=cu.get(e);t&&(Ht(e,"message",{value:t.message}),Ht(e,"stack",{value:t.stack}))}var cu,is=v(()=>{Se();Ve();xt();Fe();Re();Ee();cu=new WeakMap});function Te(e,t){e.f=e.f&CC|t}function ss(e){(e.f&512)!==0||e.deps===null?Te(e,1024):Te(e,4096)}var CC,Io=v(()=>{Fe();CC=-7169});function wh(e){if(e!==null)for(let t of e)(t.f&2)===0||(t.f&65536)===0||(t.f^=65536,wh(t.deps))}function Jl(e,t,r){(e.f&2048)!==0?t.add(e):(e.f&4096)!==0&&r.add(e),wh(e.deps),Te(e,1024)}var du=v(()=>{Fe();Io()});var uu=v(()=>{Ee();Re()});var Ch=v(()=>{Re();ia();uu()});function fu(e){var t=jl;try{return jl=!1,[e(),jl]}finally{jl=t}}var Bh,jl,ua=v(()=>{uu();Ch();Re();Ee();Be();pt();Se();Bh=!1,jl=!1});var Eh=v(()=>{Fe();ns();Ee()});function kn(e){var t=Ko;Ko=!0;try{var r;for(e&&(xe!==null&&!xe.is_fork&&xe.flush(),r=e());;){if(yh(),xe===null)return r;xe.flush()}}finally{Ko=t}}function $C(){if(R){var e=new Map;for(let r of xe.current.keys())for(let[n,o]of r.updated??[]){var t=e.get(n);t||(t={error:o.error,count:0},e.set(n,t)),t.count+=o.count}for(let r of e.values())r.error&&console.error(r.error)}try{Dp()}catch(r){R&&Ht(r,"stack",{value:""}),Jr(r,hu)}}function Ah(e){var t=e.length;if(t!==0){for(var r=0;r0)){to.clear();for(let o of Kr){if((o.f&24576)!==0)continue;let i=[o],s=o.parent;for(;s!==null;)Kr.has(s)&&(Kr.delete(s),i.push(s)),s=s.parent;for(let a=i.length-1;a>=0;a--){let l=i[a];(l.f&24576)===0&&Nn(l)}}Kr.clear()}}Kr=null}}function Zh(e,t,r,n){if(!r.has(e)&&(r.add(e),e.reactions!==null))for(let o of e.reactions){let i=o.f;(i&2)!==0?Zh(o,t,r,n):(i&4194320)!==0&&(i&2048)===0&&_u(o,t,n)&&(Te(o,2048),va(o))}}function kh(e,t){if(e.reactions!==null)for(let r of e.reactions){let n=r.f;(n&2)!==0?kh(r,t):(n&131072)!==0&&(Te(r,2048),t.add(r))}}function _u(e,t,r){let n=r.get(e);if(n!==void 0)return n;if(e.deps!==null)for(let o of e.deps){if(vo.call(t,o))return!0;if((o.f&2)!==0&&_u(o,t,r))return r.set(o,!0),!0}return r.set(e,!1),!1}function va(e){xe.schedule(e)}function Nh(e,t){if(!((e.f&32)!==0&&(e.f&1024)!==0)){(e.f&2048)!==0?t.d.push(e):(e.f&4096)!==0&&t.m.push(e),Te(e,1024);for(var r=e.first;r!==null;)Nh(r,t),r=r.next}}function Qh(e){Te(e,1024);for(var t=e.first;t!==null;)Qh(t),t=t.next}function Xh(e){dt||Vl("fork"),xe!==null&&Hp();var t=dr.ensure();t.is_fork=!0,At=new Map;var r=!1,n=t.settled();return kn(e),{commit:async()=>{if(r){await n;return}t.linked||Op(),r=!0,t.is_fork=!1;for(var[o,[i]]of t.current)o.v=i,o.wv=Bo();kn(()=>{var s=new Set;for(var a of t.current.keys())kh(a,s);_a(s),ba()}),t.flush(),await n},discard:()=>{for(var o of t.current.keys())o.wv=Bo();!r&&t.linked&&t.discard()}}}var Kl,as,xe,hs,At,hu,Ko,gu,ti,pa,$h,pu,EC,cs,jn,Kn,ds,us,fs,qn,gs,cr,ha,eo,_n,Zn,ps,Co,De,mu,fa,vu,Gh,Fh,ls,Sh,ga,ql,dr,Kr,zt=v(()=>{Fe();lr();Re();Ee();Xt();mn();Se();is();pt();Be();du();Ve();Io();ua();Po();Eh();Kl=null,as=null,xe=null,hs=null,At=null,hu=null,Ko=!1,gu=!1,ti=null,pa=null,$h=0,pu=new Set,EC=1,ql=class ql{constructor(){L(this,De);Ae(this,"id",EC++);L(this,cs,!1);Ae(this,"linked",!0);L(this,jn,null);L(this,Kn,null);Ae(this,"async_deriveds",new Map);Ae(this,"current",new Map);Ae(this,"previous",new Map);L(this,ds,new Set);L(this,us,new Set);L(this,fs,0);L(this,qn,new Map);L(this,gs,null);L(this,cr,[]);L(this,ha,[]);L(this,eo,new Set);L(this,_n,new Set);L(this,Zn,new Map);L(this,ps,new Set);Ae(this,"is_fork",!1);L(this,Co,!1);as===null?Kl=as=this:(he(as,Kn,this),he(this,jn,as)),as=this}skip_effect(t){m(this,Zn).has(t)||m(this,Zn).set(t,{d:[],m:[]}),m(this,ps).delete(t)}unskip_effect(t,r=n=>this.schedule(n)){var n=m(this,Zn).get(t);if(n){m(this,Zn).delete(t);for(var o of n.d)Te(o,2048),r(o);for(o of n.m)Te(o,4096),r(o)}m(this,ps).add(t)}capture(t,r,n=!1){t.v!==Ye&&!this.previous.has(t)&&this.previous.set(t,t.v),(t.f&8388608)===0&&(this.current.set(t,[r,n]),At?.set(t,r)),this.is_fork||(t.v=r)}activate(){xe=this}deactivate(){xe=null,At=null}flush(){try{R&&pu.clear(),gu=!0,xe=this,Ce(this,De,fa).call(this)}finally{if($h=0,hu=null,ti=null,pa=null,gu=!1,xe=null,At=null,to.clear(),R)for(let t of pu)t.updated=null}}discard(){for(let t of m(this,us))t(this);m(this,us).clear(),Ce(this,De,ga).call(this),m(this,gs)?.resolve()}register_created_effect(t){m(this,ha).push(t)}increment(t,r){if(he(this,fs,m(this,fs)+1),t){let n=m(this,qn).get(r)??0;m(this,qn).set(r,n+1)}}decrement(t,r){if(he(this,fs,m(this,fs)-1),t){let n=m(this,qn).get(r)??0;n===1?m(this,qn).delete(r):m(this,qn).set(r,n-1)}m(this,Co)||(he(this,Co,!0),yt(()=>{he(this,Co,!1),this.linked&&this.flush()}))}transfer_effects(t,r){for(let n of t)m(this,eo).add(n);for(let n of r)m(this,_n).add(n);t.clear(),r.clear()}oncommit(t){m(this,ds).add(t)}ondiscard(t){m(this,us).add(t)}settled(){return(m(this,gs)??he(this,gs,Xl())).promise}static ensure(){if(xe===null){let t=xe=new ql;!gu&&!Ko&&yt(()=>{m(t,cs)||t.flush()})}return xe}apply(){if(!dt||!this.is_fork&&m(this,jn)===null&&m(this,Kn)===null){At=null;return}At=new Map;for(let[r,[n]]of this.current)At.set(r,n);for(let r=Kl;r!==null;r=m(r,Kn))if(!(r===this||r.is_fork)){var t=!1;if(r.id1e3&&(Ce(this,De,ga).call(this),$C()),R)for(let g of this.current.keys())pu.add(g);for(let g of m(this,eo))m(this,_n).delete(g),Te(g,2048),this.schedule(g);for(let g of m(this,_n))Te(g,4096),this.schedule(g);let t=m(this,cr);he(this,cr,[]),this.apply();var r=ti=[],n=[],o=pa=[];for(let g of t)try{Ce(this,De,vu).call(this,g,r,n)}catch(d){throw Qh(g),Ce(this,De,mu).call(this)||this.discard(),d}if(xe=null,o.length>0){var i=ql.ensure();for(let g of o)i.schedule(g)}if(ti=null,pa=null,Ce(this,De,mu).call(this)){Ce(this,De,ls).call(this,n),Ce(this,De,ls).call(this,r);for(let[g,d]of m(this,Zn))Nh(g,d);o.length>0&&Ce(l=xe,De,fa).call(l);return}let s=Ce(this,De,Gh).call(this);if(s){Ce(this,De,ls).call(this,n),Ce(this,De,ls).call(this,r),Ce(u=s,De,Fh).call(u,this);return}m(this,eo).clear(),m(this,_n).clear();for(let g of m(this,ds))g(this);m(this,ds).clear(),hs=this,Ah(n),Ah(r),hs=null,m(this,gs)?.resolve();var a=xe;if(m(this,fs)===0&&(m(this,cr).length===0||a!==null)&&(Ce(this,De,ga).call(this),dt&&(Ce(this,De,Sh).call(this),xe=a)),m(this,cr).length>0)if(a!==null){let g=a;m(g,cr).push(...m(this,cr).filter(d=>!m(g,cr).includes(d)))}else a=this;a!==null&&Ce(f=a,De,fa).call(f)},vu=function(t,r,n){t.f^=1024;for(var o=t.first;o!==null;){var i=o.f,s=(i&96)!==0,a=s&&(i&1024)!==0,l=a||(i&8192)!==0||m(this,Zn).has(o);if(!l&&o.fn!==null){s?o.f^=1024:(i&4)!==0?r.push(o):dt&&(i&16777224)!==0?n.push(o):$o(o)&&((i&16)!==0&&m(this,_n).add(o),Nn(o));var u=o.first;if(u!==null){o=u;continue}}for(;o!==null;){var f=o.next;if(f!==null){o=f;break}o=o.parent}}},Gh=function(){for(var t=m(this,jn);t!==null;){if(!t.is_fork){for(let[r,[,n]]of this.current)if(t.current.has(r)&&!n)return t}t=m(t,jn)}return null},Fh=function(t){var n;for(let[o,i]of t.current)!this.previous.has(o)&&t.previous.has(o)&&this.previous.set(o,t.previous.get(o)),this.current.set(o,i);for(let[o,i]of t.async_deriveds){let s=this.async_deriveds.get(o);s&&i.promise.then(s.resolve).catch(s.reject)}this.transfer_effects(m(t,eo),m(t,_n));let r=o=>{var i=o.reactions;if(i!==null)for(let l of i){var s=l.f;if((s&2)!==0)r(l);else{var a=l;s&4194320&&!this.async_deriveds.has(a)&&(m(this,_n).delete(a),Te(a,2048),this.schedule(a))}}};for(let o of this.current.keys())r(o);this.oncommit(()=>t.discard()),Ce(n=t,De,ga).call(n),xe=this,Ce(this,De,fa).call(this)},ls=function(t){for(var r=0;r!g.current.get(d)[1]&&!this.current.has(d));if(o.length===0)t&&g.discard();else if(r.length>0){if(R&&!m(g,Co)&&vh(m(g,cr).length===0,"Batch has scheduled roots"),t)for(let d of m(this,ps))g.unskip_effect(d,p=>{var h;(p.f&4194320)!==0?g.schedule(p):Ce(h=g,De,ls).call(h,[p])});g.activate();var i=new Set,s=new Map;for(var a of r)Zh(a,o,i,s);s=new Map;var l=[...g.current].filter(([d,p])=>{let h=this.current.get(d);return h?h[0]!==p[0]||h[1]!==p[1]:!0}).map(([d])=>d);if(l.length>0)for(let d of m(this,ha))(d.f&155648)===0&&_u(d,l,s)&&((d.f&4194320)!==0?(Te(d,2048),g.schedule(d)):m(g,eo).add(d));if(m(g,cr).length>0&&!m(g,Co)){g.apply();for(var u of m(g,cr))Ce(f=g,De,vu).call(f,u,[],[]);he(g,cr,[])}g.deactivate()}}}},ga=function(){if(this.linked){var t=m(this,jn),r=m(this,Kn);t===null?Kl=r:he(t,Kn,r),r===null?as=t:he(r,jn,t),this.linked=!1}};dr=ql;Kr=null});function xa(e){let t=0,r=Vt(0),n;return R&&ut(r,"createSubscriber version"),()=>{yo()&&(c(r),Wt(()=>(t===0&&(n=ke(()=>e(()=>ur(r)))),t+=1,()=>{yt(()=>{t-=1,t===0&&(n?.(),n=void 0,ur(r))})})))}}var ec=v(()=>{Ee();Be();pt();Qr();Se();mn()});function Cu(e,t,r,n){new xu(e,t,r,n)}var GC,Ur,ya,qr,ri,Cr,en,fr,Lr,ro,ni,Ao,ms,Ia,wa,Qn,nc,tt,Lh,Vh,Wh,yu,tc,rc,Iu,wu,xu,oc=v(()=>{Fe();Ve();ot();is();Be();Ee();He();mn();Xt();Rt();Se();zt();pt();Qr();ec();xt();du();GC=589824;xu=class{constructor(t,r,n,o){L(this,tt);Ae(this,"parent");Ae(this,"is_pending",!1);Ae(this,"transform_error");L(this,Ur);L(this,ya,se?be:null);L(this,qr);L(this,ri);L(this,Cr);L(this,en,null);L(this,fr,null);L(this,Lr,null);L(this,ro,null);L(this,ni,0);L(this,Ao,0);L(this,ms,!1);L(this,Ia,new Set);L(this,wa,new Set);L(this,Qn,null);L(this,nc,xa(()=>(he(this,Qn,Vt(m(this,ni))),R&&ut(m(this,Qn),"$effect.pending()"),()=>{he(this,Qn,null)})));he(this,Ur,t),he(this,qr,r),he(this,ri,i=>{var s=ue;s.b=this,s.f|=128,n(i)}),this.parent=ue.b,this.transform_error=o??this.parent?.transform_error??(i=>i),he(this,Cr,pr(()=>{if(se){let i=m(this,ya);bt();let s=i.data==="[!";if(i.data.startsWith("[?")){let l=JSON.parse(i.data.slice("[?".length));Ce(this,tt,Vh).call(this,l)}else s?Ce(this,tt,Wh).call(this):Ce(this,tt,Lh).call(this)}else Ce(this,tt,yu).call(this)},GC)),se&&he(this,Ur,be)}defer_effect(t){Jl(t,m(this,Ia),m(this,wa))}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!m(this,qr).pending}update_pending_count(t,r){Ce(this,tt,Iu).call(this,t,r),he(this,ni,m(this,ni)+t),!(!m(this,Qn)||m(this,ms))&&(he(this,ms,!0),yt(()=>{he(this,ms,!1),m(this,Qn)&&bn(m(this,Qn),m(this,ni))}))}get_effect_pending(){return m(this,nc).call(this),c(m(this,Qn))}error(t){if(!m(this,qr).onerror&&!m(this,qr).failed)throw t;xe?.is_fork?(m(this,en)&&xe.skip_effect(m(this,en)),m(this,fr)&&xe.skip_effect(m(this,fr)),m(this,Lr)&&xe.skip_effect(m(this,Lr)),xe.oncommit(()=>{Ce(this,tt,wu).call(this,t)})):Ce(this,tt,wu).call(this,t)}};Ur=new WeakMap,ya=new WeakMap,qr=new WeakMap,ri=new WeakMap,Cr=new WeakMap,en=new WeakMap,fr=new WeakMap,Lr=new WeakMap,ro=new WeakMap,ni=new WeakMap,Ao=new WeakMap,ms=new WeakMap,Ia=new WeakMap,wa=new WeakMap,Qn=new WeakMap,nc=new WeakMap,tt=new WeakSet,Lh=function(){try{he(this,en,ht(()=>m(this,ri).call(this,m(this,Ur))))}catch(t){this.error(t)}},Vh=function(t){let r=m(this,qr).failed;r&&he(this,Lr,ht(()=>{r(m(this,Ur),()=>t,()=>()=>{})}))},Wh=function(){let t=m(this,qr).pending;t&&(this.is_pending=!0,he(this,fr,ht(()=>t(m(this,Ur)))),yt(()=>{var r=he(this,ro,document.createDocumentFragment()),n=mt();r.append(n),he(this,en,Ce(this,tt,rc).call(this,()=>ht(()=>m(this,ri).call(this,n)))),m(this,Ao)===0&&(m(this,Ur).before(r),he(this,ro,null),Xn(m(this,fr),()=>{he(this,fr,null)}),Ce(this,tt,tc).call(this,xe))}))},yu=function(){try{if(this.is_pending=this.has_pending_snippet(),he(this,Ao,0),he(this,ni,0),he(this,en,ht(()=>{m(this,ri).call(this,m(this,Ur))})),m(this,Ao)>0){var t=he(this,ro,document.createDocumentFragment());vs(m(this,en),t);let r=m(this,qr).pending;he(this,fr,ht(()=>r(m(this,Ur))))}else Ce(this,tt,tc).call(this,xe)}catch(r){this.error(r)}},tc=function(t){this.is_pending=!1,t.transfer_effects(m(this,Ia),m(this,wa))},rc=function(t){var r=ue,n=me,o=_e;Gt(m(this,Cr)),wt(m(this,Cr)),zn(m(this,Cr).ctx);try{return dr.ensure(),t()}catch(i){return Pl(i),null}finally{Gt(r),wt(n),zn(o)}},Iu=function(t,r){var n;if(!this.has_pending_snippet()){this.parent&&Ce(n=this.parent,tt,Iu).call(n,t,r);return}he(this,Ao,m(this,Ao)+t),m(this,Ao)===0&&(Ce(this,tt,tc).call(this,r),m(this,fr)&&Xn(m(this,fr),()=>{he(this,fr,null)}),m(this,ro)&&(m(this,Ur).before(m(this,ro)),he(this,ro,null)))},wu=function(t){m(this,en)&&(rt(m(this,en)),he(this,en,null)),m(this,fr)&&(rt(m(this,fr)),he(this,fr,null)),m(this,Lr)&&(rt(m(this,Lr)),he(this,Lr,null)),se&&(Ue(m(this,ya)),Ct(),Ue(fn()));var r=m(this,qr).onerror;let n=m(this,qr).failed;var o=!1,i=!1;let s=()=>{if(o){ph();return}o=!0,i&&nh(),m(this,Lr)!==null&&Xn(m(this,Lr),()=>{he(this,Lr,null)}),Ce(this,tt,rc).call(this,()=>{Ce(this,tt,yu).call(this)})},a=l=>{try{i=!0,r?.(l,s),i=!1}catch(u){Jr(u,m(this,Cr)&&m(this,Cr).parent)}n&&he(this,Lr,Ce(this,tt,rc).call(this,()=>{try{return ht(()=>{var u=ue;u.b=this,u.f|=128,n(m(this,Ur),()=>l,()=>s)})}catch(u){return Jr(u,m(this,Cr).parent),null}}))};yt(()=>{var l;try{l=this.transform_error(t)}catch(u){Jr(u,m(this,Cr)&&m(this,Cr).parent);return}l!==null&&typeof l=="object"&&typeof l.then=="function"?l.then(a,u=>Jr(u,m(this,Cr)&&m(this,Cr).parent)):a(l)})}});function Ca(e,t,r,n){let o=Sn()?oo:oi;var i=e.filter(d=>!d.settled);if(r.length===0&&i.length===0){n(t.map(o));return}var s=ue,a=Th(),l=i.length===1?i[0].promise:i.length>1?Promise.all(i.map(d=>d.promise)):null;function u(d){if((s.f&16384)===0){a();try{n(d)}catch(p){Jr(p,s)}_s()}}var f=Bu();if(r.length===0){l.then(()=>u(t.map(o))).finally(f);return}function g(){Promise.all(r.map(d=>$u(d))).then(d=>u([...t.map(o),...d])).catch(d=>Jr(d,s)).finally(f)}l?l.then(()=>{a(),g(),_s()}):g()}function Th(){var e=ue,t=me,r=_e,n=xe;if(R)var o=hn;return function(s=!0){Gt(e),wt(t),zn(r),s&&(e.f&16384)===0&&(n?.activate(),n?.apply()),R&&(Eu(null),os(o))}}function _s(e=!0){Gt(null),wt(null),zn(null),e&&xe?.deactivate(),R&&(Eu(null),os(null))}function Bu(){var e=ue,t=e.b,r=xe,n=!!t?.is_rendered();return t?.update_pending_count(1,r),r.increment(n,e),()=>{t?.update_pending_count(-1,r),r.decrement(n,e)}}var Go=v(()=>{Fe();Se();ot();oc();is();Ee();zt();Fo();Be()});function Eu(e){Br=e}function oo(e){var t=2050;ue!==null&&(ue.f|=524288);let r={ctx:_e,deps:null,effects:null,equals:Dl,f:t,fn:e,reactions:null,rv:0,v:Ye,wv:0,parent:ue,ac:null};return R&&gn&&(r.created=pn("created at")),r}function $u(e,t,r){let n=ue;n===null&&Rp();var o=void 0,i=Vt(Ye);R&&(i.label=t??e.toString());var s=!me,a=new Set;return Hh(()=>{var l=ue;R&&(Br={effect:l,effect_deps:new Set,warned:!1});var u=Xl();o=u.promise;try{Promise.resolve(e()).then(u.resolve,p=>{p!==bo&&u.reject(p)}).finally(_s)}catch(p){u.reject(p),_s()}if(R){if(Br){if(l.deps!==null)for(let p=0;p{R&&(Br=null),g?.(),a.delete(u),h!==ic&&(f.activate(),h?(i.f|=8388608,bn(i,h)):((i.f&8388608)!==0&&(i.f^=8388608),R&&r!==void 0&&!i.equals(p)&&(Ba.add(i),setTimeout(()=>{Ba.has(i)&&(l.f&16384)===0&&(ih(i.label,r),Ba.delete(i))})),bn(i,p)),f.deactivate())};u.promise.then(d,p=>d(null,p||"unknown"))}),Et(()=>{for(let l of a)l.reject(ic)}),R&&(i.f|=4194304),new Promise(l=>{function u(f){function g(){f===o?l(i):u(o)}f.then(g,g)}u(o)})}function _(e){let t=oo(e);return dt||ac(t),t}function oi(e){let t=oo(e);return t.equals=Hl,t}function Dh(e){var t=e.effects;if(t!==null){e.effects=null;for(var r=0;r{Se();Fe();Ee();ia();Xt();Rt();Be();pt();Po();lr();ot();Ve();zt();Go();Re();Io();Br=null;Ba=new Set;ic=Symbol("obsolete");Au=[]});function _a(e){ii=e}function Mh(){Su=!0}function Vt(e,t){var r={f:0,v:e,reactions:null,equals:Dl,rv:0,wv:0};return R&&gn&&(r.created=t??pn("created at"),r.updated=null,r.set_during_effect=!1,r.trace=null),r}function ye(e,t){let r=Vt(e,t);return ac(r),r}function qo(e,t=!1,r=!0){var o;let n=Vt(e);return t||(n.equals=Hl),Fn&&r&&_e!==null&&_e.l!==null&&((o=_e.l).s??(o.s=[])).push(n),n}function M(e,t,r=!1){me!==null&&(!mr||(me.f&131072)!==0)&&Sn()&&(me.f&4325394)!==0&&(xn===null||!xn.has(e))&&rh();let n=r?Dt(t):t;return R&&Ml(n,e.label),bn(e,n,pa)}function bn(e,t,r=null){if(!e.equals(t)){to.set(e,Vr?t:e.v);var n=dr.ensure();if(n.capture(e,t),R){if(gn||ue!==null){e.updated??(e.updated=new Map);let o=(e.updated.get("")?.count??0)+1;if(e.updated.set("",{error:null,count:o}),gn||o>5){let i=pn("updated at");if(i!==null){let s=e.updated.get(i.stack);s||(s={error:i,count:0},e.updated.set(i.stack,s)),s.count++}}}ue!==null&&(e.set_during_effect=!0)}if((e.f&2)!==0){let o=e;(e.f&2048)!==0&&Ea(o),At===null&&ss(o)}e.wv=Bo(),Yh(e,2048,r),Sn()&&ue!==null&&(ue.f&1024)!==0&&(ue.f&96)===0&&(Wr===null?zh([e]):Wr.push(e)),!n.is_fork&&ii.size>0&&!Su&&ba()}return t}function ba(){Su=!1;for(let e of ii){(e.f&1024)!==0&&Te(e,4096);let t;try{t=$o(e)}catch{t=!0}t&&Nn(e)}ii.clear()}function ur(e){M(e,e.v+1)}function Yh(e,t,r){var n=e.reactions;if(n!==null)for(var o=Sn(),i=n.length,s=0;s{Se();Ee();ia();Fe();Xt();lr();Qr();Po();ot();zt();ai();Fo();Io();ii=new Set,to=new Map;Su=!1});function Dt(e){if(typeof e!="object"||e===null||_t in e)return e;let t=_o(e);if(t!==Ql&&t!==Sp)return e;var r=new Map,n=zr(e),o=ye(0),i=R&&gn?pn("created at"):null,s=Rn,a=g=>{if(Rn===s)return g();var d=me,p=Rn;wt(null),Zu(s);var h=g();return wt(d),Zu(p),h};n&&(r.set("length",ye(e.length,i)),R&&(e=kC(e)));var l="";let u=!1;function f(g){if(!u){u=!0,l=g,ut(o,`${l} version`);for(let[d,p]of r)ut(p,li(l,d));u=!1}}return new Proxy(e,{defineProperty(g,d,p){(!("value"in p)||p.configurable===!1||p.enumerable===!1||p.writable===!1)&&eh();var h=r.get(d);return h===void 0?a(()=>{var b=ye(p.value,i);return r.set(d,b),R&&typeof d=="string"&&ut(b,li(l,d)),b}):M(h,p.value,!0),!0},deleteProperty(g,d){var p=r.get(d);if(p===void 0){if(d in g){let h=a(()=>ye(Ye,i));r.set(d,h),ur(o),R&&ut(h,li(l,d))}}else M(p,Ye),ur(o);return!0},get(g,d,p){if(d===_t)return e;if(R&&d===Rl)return f;var h=r.get(d),b=d in g;if(h===void 0&&(!b||tr(g,d)?.writable)&&(h=a(()=>{var w=Dt(b?g[d]:Ye),C=ye(w,i);return R&&ut(C,li(l,d)),C}),r.set(d,h)),h!==void 0){var x=c(h);return x===Ye?void 0:x}return Reflect.get(g,d,p)},getOwnPropertyDescriptor(g,d){var p=Reflect.getOwnPropertyDescriptor(g,d);if(p&&"value"in p){var h=r.get(d);h&&(p.value=c(h))}else if(p===void 0){var b=r.get(d),x=b?.v;if(b!==void 0&&x!==Ye)return{enumerable:!0,configurable:!0,value:x,writable:!0}}return p},has(g,d){if(d===_t)return!0;var p=r.get(d),h=p!==void 0&&p.v!==Ye||Reflect.has(g,d);if(p!==void 0||ue!==null&&(!h||tr(g,d)?.writable)){p===void 0&&(p=a(()=>{var x=h?Dt(g[d]):Ye,w=ye(x,i);return R&&ut(w,li(l,d)),w}),r.set(d,p));var b=c(p);if(b===Ye)return!1}return h},set(g,d,p,h){var b=r.get(d),x=d in g;if(n&&d==="length")for(var w=p;wye(Ye,i)),r.set(w+"",C),R&&ut(C,li(l,w)))}if(b===void 0)(!x||tr(g,d)?.writable)&&(b=a(()=>ye(void 0,i)),R&&ut(b,li(l,d)),M(b,Dt(p)),r.set(d,b));else{x=b.v!==Ye;var E=a(()=>Dt(p));M(b,E)}var y=Reflect.getOwnPropertyDescriptor(g,d);if(y?.set&&y.set.call(h,p),!x){if(n&&typeof d=="string"){var U=r.get("length"),B=Number(d);Number.isInteger(B)&&B>=U.v&&M(U,B+1)}ur(o)}return!0},ownKeys(g){c(o);var d=Reflect.ownKeys(g).filter(b=>{var x=r.get(b);return x===void 0||x.v!==Ye});for(var[p,h]of r)h.v!==Ye&&!(p in g)&&d.push(p);return d},setPrototypeOf(){th()}})}function li(e,t){return typeof t=="symbol"?`${e}[Symbol(${t.description??""})]`:SC.test(t)?`${e}.${t}`:/^\d+$/.test(t)?`${e}[${t}]`:`${e}['${t}']`}function xs(e){try{if(e!==null&&typeof e=="object"&&_t in e)return e[_t]}catch{}return e}function ku(e,t){return Object.is(xs(e),xs(t))}function kC(e){return new Proxy(e,{get(t,r,n){var o=Reflect.get(t,r,n);return ZC.has(r)?function(...i){Mh();var s=o.apply(this,i);return ba(),s}:o}})}var SC,ZC,ai=v(()=>{Se();Ee();Re();pt();Fe();Ve();Xt();Qr();Po();lr();SC=/^[a-zA-Z_$][a-zA-Z_$0-9]*$/;ZC=new Set(["copyWithin","fill","pop","push","reverse","shift","sort","splice","unshift"])});function Ph(){let e=Array.prototype,t=Array.__svelte_cleanup;t&&t();let{indexOf:r,lastIndexOf:n,includes:o}=e;e.indexOf=function(i,s){let a=r.call(this,i,s);if(a===-1){for(let l=s??0;l{e.indexOf=r,e.lastIndexOf=n,e.includes=o}}var Nu=v(()=>{Rt();ai()});function lc(){if(or===void 0){or=window,Jh=document,da=/Firefox/.test(navigator.userAgent);var e=Element.prototype,t=Node.prototype,r=Text.prototype;jh=tr(t,"firstChild").get,Kh=tr(t,"nextSibling").get,qd(e)&&(e[qs]=void 0,e[Ul]=null,e[ea]=void 0,e.__e=void 0),qd(r)&&(r[ta]=void 0),R&&(e.__svelte_meta=null,Ph())}}function mt(e=""){return document.createTextNode(e)}function Pe(e){return jh.call(e)}function Bt(e){return Kh.call(e)}function V(e,t){if(!se)return Pe(e);var r=Pe(be);if(r===null)r=be.appendChild(mt());else if(t&&r.nodeType!==zo){var n=mt();return r?.before(n),Ue(n),n}return t&&Ga(r),Ue(r),r}function le(e,t=!1){if(!se){var r=Pe(e);return r instanceof Comment&&r.data===""?Bt(r):r}if(t){if(be?.nodeType!==zo){var n=mt();return be?.before(n),Ue(n),n}Ga(be)}return be}function O(e,t=1,r=!1){let n=se?be:e;for(var o;t--;)o=n,n=Bt(n);if(!se)return n;if(r){if(n?.nodeType!==zo){var i=mt();return n===null?o?.after(i):n.before(i),Ue(i),i}Ga(n)}return Ue(n),n}function Aa(e){e.textContent=""}function cc(){if(!dt||Kr!==null)return!1;var e=ue.f;return(e&32768)!==0}function Un(e,t,r){return t==null||t===Wl?r?document.createElement(e,{is:r}):document.createElement(e):r?document.createElementNS(t,e,{is:r}):document.createElementNS(t,e)}function Ga(e){if(e.nodeValue.length<65536)return;let t=e.nextSibling;for(;t!==null&&t.nodeType===zo;)t.remove(),e.nodeValue+=t.nodeValue,t=e.nextSibling}var or,Jh,da,jh,Kh,xt=v(()=>{He();Se();Nu();Re();Ee();lr();Fe();zt();Ve()});function Qu(e,t){if(t){let r=document.body;e.autofocus=!0,yt(()=>{document.activeElement===r&&e.focus()})}}function Xu(){qh||(qh=!0,document.addEventListener("reset",e=>{Promise.resolve().then(()=>{if(!e.defaultPrevented)for(let t of e.target.elements)t[ra]?.()})},{capture:!0}))}var qh,dc=v(()=>{He();xt();mn();Fe();qh=!1});function So(e){var t=me,r=ue;wt(null),Gt(null);try{return e()}finally{wt(t),Gt(r)}}var tn=v(()=>{Be();Ee();Fe();dc()});function Uu(e){ue===null&&(me===null&&Tp(e),Wp()),Vr&&Vp(e)}function NC(e,t){var r=t.last;r===null?t.last=t.first=e:(r.next=e,e.prev=r,t.last=e)}function rn(e,t){var r=ue;if(R)for(;r!==null&&(r.f&131072)!==0;)r=r.parent;r!==null&&(r.f&8192)!==0&&(e|=8192);var n={ctx:_e,deps:null,nodes:null,f:e|2048|512,first:null,fn:t,last:null,next:null,parent:r,b:r&&r.b,prev:null,teardown:null,wv:0,ac:null};R&&(n.component_function=Xr),xe?.register_created_effect(n);var o=n;if((e&4)!==0)ti!==null?ti.push(n):dr.ensure().schedule(n);else if(t!==null){try{Nn(n)}catch(s){throw rt(n),s}o.deps===null&&o.teardown===null&&o.nodes===null&&o.first===o.last&&(o.f&524288)===0&&(o=o.first,(e&16)!==0&&(e&65536)!==0&&o!==null&&(o.f|=65536))}if(o!==null&&(o.parent=r,r!==null&&NC(o,r),me!==null&&(me.f&2)!==0&&(e&64)===0)){var i=me;(i.effects??(i.effects=[])).push(o)}return n}function yo(){return me!==null&&!mr}function Et(e){let t=rn(8,null);return Te(t,1024),t.teardown=e,t}function st(e){Uu("$effect"),R&&Ht(e,"name",{value:"$effect"});var t=ue.f,r=!me&&(t&32)!==0&&_e!==null&&!_e.i;if(r){var n=_e;(n.e??(n.e=[])).push(e)}else return lu(e)}function lu(e){return rn(1048580,e)}function ci(e){return Uu("$effect.pre"),R&&Ht(e,"name",{value:"$effect.pre"}),rn(1048584,e)}function di(e){dr.ensure();let t=rn(524352,e);return()=>{rt(t)}}function rm(e){dr.ensure();let t=rn(524352,e);return(r={})=>new Promise(n=>{r.outro?Xn(t,()=>{rt(t),n(void 0)}):(rt(t),n(void 0))})}function ir(e){return rn(4,e)}function Hh(e){return rn(4718592,e)}function Wt(e,t=0){return rn(8|t,e)}function te(e,t=[],r=[],n=[]){Ca(n,t,r,o=>{rn(8,()=>e(...o.map(c)))})}function pr(e,t=0){var r=rn(16|t,e);return R&&(r.dev_stack=hn),r}function uc(e,t=0){var r=rn(16777216|t,e);return R&&(r.dev_stack=hn),r}function ht(e){return rn(524320,e)}function Lu(e){var t=e.teardown;if(t!==null){let r=Vr,n=me;Ru(!0),wt(null);try{t.call(null)}finally{Ru(r),wt(n)}}}function $a(e,t=!1){var r=e.first;for(e.first=e.last=null;r!==null;){let o=r.ac;o!==null&&So(()=>{o.abort(bo)});var n=r.next;(r.f&64)!==0?r.parent=null:rt(r,t),r=n}}function nm(e){for(var t=e.first;t!==null;){var r=t.next;(t.f&32)===0&&rt(t),t=r}}function rt(e,t=!0){var r=!1;(t||(e.f&262144)!==0)&&e.nodes!==null&&e.nodes.end!==null&&(Vu(e.nodes.start,e.nodes.end),r=!0),Te(e,33554432),$a(e,t&&!r),si(e,0);var n=e.nodes&&e.nodes.t;if(n!==null)for(let i of n)i.stop();Lu(e),e.f^=33554432,e.f|=16384;var o=e.parent;o!==null&&o.first!==null&&bu(e),R&&(e.component_function=null),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=e.b=null}function Vu(e,t){for(;e!==null;){var r=e===t?null:Bt(e);e.remove(),e=r}}function bu(e){var t=e.parent,r=e.prev,n=e.next;r!==null&&(r.next=n),n!==null&&(n.prev=r),t!==null&&(t.first===e&&(t.first=n),t.last===e&&(t.last=r))}function Xn(e,t,r=!0){var n=[];om(e,n,!0);var o=()=>{r&&rt(e),t&&t()},i=n.length;if(i>0){var s=()=>--i||o();for(var a of n)a.out(s)}else o()}function om(e,t,r){if((e.f&8192)===0){e.f^=8192;var n=e.nodes&&e.nodes.t;if(n!==null)for(let a of n)(a.is_global||r)&&t.push(a);for(var o=e.first;o!==null;){var i=o.next;if((o.f&64)===0){var s=(o.f&65536)!==0||(o.f&32)!==0&&(e.f&16)!==0;om(o,t,s?r:!1)}o=i}}}function ys(e){im(e,!0)}function im(e,t){if((e.f&8192)!==0){e.f^=8192,(e.f&1024)===0&&(Te(e,2048),dr.ensure().schedule(e));for(var r=e.first;r!==null;){var n=r.next,o=(r.f&65536)!==0||(r.f&32)!==0;im(r,o?t:!1),r=n}var i=e.nodes&&e.nodes.t;if(i!==null)for(let s of i)(s.is_global||t)&&s.in()}}function vs(e,t){if(e.nodes)for(var r=e.nodes.start,n=e.nodes.end;r!==null;){var o=r===n?null:Bt(r);t.append(r),r=o}}var Be=v(()=>{Ee();Fe();Xt();Se();Re();xt();ot();zt();Go();tn();Io()});var sm,Wu=v(()=>{pt();Ee();sm=null});function Ru(e){Vr=e}function wt(e){me=e}function Gt(e){ue=e}function ac(e){me!==null&&(!dt||(me.f&2)!==0)&&(xn??(xn=new Set)).add(e)}function zh(e){Wr=e}function Zu(e){Rn=e}function Bo(){return++am}function $o(e){var t=e.f;if((t&2048)!==0)return!0;if(t&2&&(e.f&=-65537),(t&4096)!==0){for(var r=e.deps,n=r.length,o=0;oe.wv)return!0}(t&512)!==0&&At===null&&Te(e,1024)}return!1}function lm(e,t,r=!0){var n=e.reactions;if(n!==null&&!(!dt&&xn!==null&&xn.has(e)))for(var o=0;o{e.ac.abort(bo)}),e.ac=null);try{e.f|=2097152;var f=e.fn,g=f();e.f|=32768;var d=e.deps,p=xe?.is_fork;if(Tt!==null){var h;if(p||si(e,hr),d!==null&&hr>0)for(d.length=hr+Tt.length,h=0;h{requestAnimationFrame(()=>e()),setTimeout(()=>e())});await Promise.resolve(),kn()}function cm(){return dr.ensure().settled()}function c(e){var t=e.f,r=(t&2)!==0;if(sm?.add(e),me!==null&&!mr){var n=ue!==null&&(ue.f&16384)!==0;if(!n&&(xn===null||!xn.has(e))){var o=me.deps;if((me.f&2097152)!==0)e.rv{Se();Re();Be();Fe();pt();Fo();lr();Qr();Po();ot();zt();is();Ve();Wu();tn();Io();Rt();fc=!1,Vr=!1;me=null,mr=!1;ue=null;xn=null;Tt=null,hr=0,Wr=null;am=1,ui=0,Rn=ui});var fm=v(()=>{ie();Ve();nn();Be()});function gm(e){e=e.replace(XC,"");let t=5381,r=e.length;for(;r--;)t=(t<<5)-t^e.charCodeAt(r);return(t>>>0).toString(36)}function pm(e){return e.endsWith("capture")&&e!=="gotpointercapture"&&e!=="lostpointercapture"}function hm(e){return RC.includes(e)}function mm(e){return e=e.toLowerCase(),LC[e]??e}function vm(e){return VC.includes(e)}function hc(e){return e?.replace(/\//g,"/\u200B")}var XC,RC,UC,LC,EQ,VC,WC,$Q,Zo=v(()=>{XC=/\r/g;RC=["beforeinput","click","change","dblclick","contextmenu","focusin","focusout","input","keydown","keyup","mousedown","mousemove","mouseout","mouseover","mouseup","pointerdown","pointermove","pointerout","pointerover","pointerup","touchend","touchmove","touchstart"];UC=["allowfullscreen","async","autofocus","autoplay","checked","controls","default","disabled","formnovalidate","indeterminate","inert","ismap","loop","multiple","muted","nomodule","novalidate","open","playsinline","readonly","required","reversed","seamless","selected","webkitdirectory","defer","disablepictureinpicture","disableremoteplayback"],LC={formnovalidate:"formNoValidate",ismap:"isMap",nomodule:"noModule",playsinline:"playsInline",readonly:"readOnly",defaultvalue:"defaultValue",defaultchecked:"defaultChecked",srcobject:"srcObject",novalidate:"noValidate",allowfullscreen:"allowFullscreen",disablepictureinpicture:"disablePictureInPicture",disableremoteplayback:"disableRemotePlayback"};EQ=[...UC,"formNoValidate","isMap","noModule","playsInline","readOnly","value","volume","defaultValue","defaultChecked","srcObject","noValidate","allowFullscreen","disablePictureInPicture","disableRemotePlayback"],VC=["touchstart","touchmove"];WC=["$state","$state.raw","$derived","$derived.by"],$Q=[...WC,"$state.eager","$state.snapshot","$props","$props.id","$bindable","$effect","$effect.pre","$effect.tracking","$effect.root","$effect.pending","$inspect","$inspect().with","$inspect.trace","$host"]});var _m=v(()=>{Fe();Zo();Ee();Rt()});var Tu=v(()=>{});var bm=v(()=>{Fe();Ve();He();ot()});function vc(e,t,r,n={}){function o(i){if(n.capture||_c.call(t,i),!i.cancelBubble)return So(()=>r?.call(this,i))}return e.startsWith("pointer")||e.startsWith("touch")||e==="wheel"?yt(()=>{t.addEventListener(e,o,n)}):t.addEventListener(e,o,n),o}function gi(e,t,r,n={}){var o=vc(t,e,r,n);return()=>{e.removeEventListener(t,o,n)}}function Ft(e,t,r,n,o){var i={capture:n,passive:o},s=vc(e,t,r,i);(t===document.body||t===window||t===document||t instanceof HTMLMediaElement)&&Et(()=>{t.removeEventListener(e,s,i)})}function St(e,t,r){(t[fi]??(t[fi]={}))[e]=r}function yn(e){for(var t=0;t{throw b});throw d}}finally{e[fi]=t,delete e.currentTarget,wt(f),Gt(g)}}}var fi,Du,mc,xm,Is=v(()=>{Be();Re();He();mn();Ve();Rt();Ee();tn();fi=Symbol("events"),Du=new Set,mc=new Set;xm=null});function ym(e){return DC?.createHTML(e)??e}function Sa(e){var t=Un("template");return t.innerHTML=ym(e.replaceAll("","")),t.content}var DC,bc=v(()=>{xt();DC=globalThis?.window?.trustedTypes&&globalThis.window.trustedTypes.createPolicy("svelte-trusted-html",{createHTML:e=>e})});function Zt(e,t){var r=ue;r.nodes===null&&(r.nodes={start:e,end:t,a:null,t:null})}function J(e,t){var r=(t&1)!==0,n=(t&2)!==0,o,i=!e.startsWith("");return()=>{if(se)return Zt(be,null),be;o===void 0&&(o=Sa(i?e:""+e),r||(o=Pe(o)));var s=n||da?document.importNode(o,!0):o.cloneNode(!0);if(r){var a=Pe(s),l=s.lastChild;Zt(a,l)}else Zt(s,s);return s}}function MC(e,t,r="svg"){var n=!e.startsWith(""),o=(t&1)!==0,i=`<${r}>${n?e:""+e}`,s;return()=>{if(se)return Zt(be,null),be;if(!s){var a=Sa(i),l=Pe(a);if(o)for(s=document.createDocumentFragment();Pe(l);)s.appendChild(Pe(l));else s=Pe(l)}var u=s.cloneNode(!0);if(o){var f=Pe(u),g=u.lastChild;Zt(f,g)}else Zt(u,u);return u}}function Ge(e,t){return MC(e,t,"svg")}function Ou(e=""){if(!se){var t=mt(e+"");return Zt(t,t),t}var r=be;return r.nodeType!==zo?(r.before(r=mt()),Ue(r)):Ga(r),Zt(r,r),r}function Xe(){if(se)return Zt(be,null),be;var e=document.createDocumentFragment(),t=document.createComment(""),r=mt();return e.append(t,r),Zt(t,r),e}function F(e,t){if(se){var r=ue;((r.f&32768)===0||r.nodes.end===null)&&(r.nodes.end=be),bt();return}e!==null&&e.before(t)}var pi=v(()=>{He();xt();bc();Ee();Ve();Fe()});function oe(e,t){var n;var r=t==null?"":typeof t=="object"?`${t}`:t;r!==(e[n=ta]??(e[n]=e.nodeValue))&&(e[ta]=r,e.nodeValue=`${r}`)}function Za(e,t){return wm(e,t)}function ws(e,t){lc(),t.intro=t.intro??!1;let r=t.target,n=se,o=be;try{for(var i=Pe(r);i&&(i.nodeType!==Zr||i.data!=="[");)i=Bt(i);if(!i)throw Gn;it(!0),Ue(i);let s=wm(e,{...t,anchor:i});return it(!1),s}catch(s){if(s instanceof Error&&s.message.split(` +`).some(a=>a.startsWith("https://svelte.dev/e/")))throw s;return s!==Gn&&console.warn("Failed to hydrate: ",s),t.recover===!1&&zp(),lc(),Aa(r),it(!1),Za(e,t)}finally{it(n),Ue(o)}}function wm(e,{target:t,anchor:r,props:n={},events:o,context:i,intro:s=!0,transformError:a}){lc();var l=void 0,u=rm(()=>{var f=r??t.appendChild(mt());Cu(f,{pending:()=>{}},p=>{q({});var h=_e;if(i&&(h.c=i),o&&(n.$$events=o),se&&Zt(p,null),Hu=s,l=e(p,n)||{},Hu=!0,se&&(ue.nodes.end=be,be===null||be.nodeType!==Zr||be.data!=="]"))throw xo(),Gn;ee()},a);var g=new Set,d=p=>{for(var h=0;h{for(var p of g)for(let x of[t,document]){var h=xc.get(x),b=h.get(p);--b==0?(x.removeEventListener(p,_c),h.delete(p),h.size===0&&xc.delete(x)):h.set(p,b)}mc.delete(d),f!==r&&f.parentNode?.removeChild(f)}});return Mu.set(l,u),l}function yc(e,t){let r=Mu.get(e);return r?(Mu.delete(e),r(t)):(R&&(_t in e?gh():uh()),Promise.resolve())}var Hu,xc,Mu,hi=v(()=>{Se();xt();Ve();Ee();ot();Be();He();Re();Is();Rt();Xt();pi();Zo();Fe();oc();Hu=!0;xc=new Map;Mu=new WeakMap});var Cm=v(()=>{Ve();Fe();He();Be();pt();hi();Ee()});var Bm=v(()=>{Re();Fe();Ve();ot();Rt();Zo()});var Em=v(()=>{Xt();ot();Ve()});var $m=v(()=>{Ve();ns();Be();Ee();Po()});var Am=v(()=>{Go();Ee();He()});var Gm=v(()=>{Xt()});var In,Ln,Tr,mi,ka,Na,Ic,wn,vi=v(()=>{zt();Be();Fe();He();xt();Se();wn=class{constructor(t,r=!0){Ae(this,"anchor");L(this,In,new Map);L(this,Ln,new Map);L(this,Tr,new Map);L(this,mi,new Set);L(this,ka,!0);L(this,Na,t=>{if(m(this,In).has(t)){var r=m(this,In).get(t),n=m(this,Ln).get(r);if(n)ys(n),m(this,mi).delete(r);else{var o=m(this,Tr).get(r);o&&(ys(o.effect),m(this,Ln).set(r,o.effect),m(this,Tr).delete(r),R&&(o.fragment.lastChild[tu]=this.anchor),o.fragment.lastChild.remove(),this.anchor.before(o.fragment),n=o.effect)}for(let[i,s]of m(this,In)){if(m(this,In).delete(i),i===t)break;let a=m(this,Tr).get(s);a&&(rt(a.effect),m(this,Tr).delete(s))}for(let[i,s]of m(this,Ln)){if(i===r||m(this,mi).has(i))continue;let a=()=>{if(Array.from(m(this,In).values()).includes(i)){var u=document.createDocumentFragment();vs(s,u),u.append(mt()),m(this,Tr).set(i,{effect:s,fragment:u})}else rt(s);m(this,mi).delete(i),m(this,Ln).delete(i)};m(this,ka)||!n?(m(this,mi).add(i),Xn(s,a,!1)):a()}}});L(this,Ic,t=>{m(this,In).delete(t);let r=Array.from(m(this,In).values());for(let[n,o]of m(this,Tr))r.includes(n)||(rt(o.effect),m(this,Tr).delete(n))});this.anchor=t,he(this,ka,r)}ensure(t,r){var n=xe,o=cc();if(r&&!m(this,Ln).has(t)&&!m(this,Tr).has(t))if(o){var i=document.createDocumentFragment(),s=mt();i.append(s),m(this,Tr).set(t,{effect:ht(()=>r(s)),fragment:i})}else m(this,Ln).set(t,ht(()=>r(this.anchor)));if(m(this,In).set(n,t),o){for(let[a,l]of m(this,Ln))a===t?n.unskip_effect(l):n.skip_effect(l);for(let[a,l]of m(this,Tr))a===t?n.unskip_effect(l.effect):n.skip_effect(l.effect);n.oncommit(m(this,Na)),n.ondiscard(m(this,Ic))}else se&&(this.anchor=be),m(this,Na).call(this,n)}};In=new WeakMap,Ln=new WeakMap,Tr=new WeakMap,mi=new WeakMap,ka=new WeakMap,Na=new WeakMap,Ic=new WeakMap});var Fm=v(()=>{Re();Be();pt();He();mn();Ve();ot();zt();vi();Go();Se()});function ce(e,t,r=!1){var n;se&&(n=be,bt());var o=new wn(e),i=r?65536:0;function s(a,l){if(se){var u=rs(n);if(a!==parseInt(u.substring(1))){var f=fn();Ue(f),o.anchor=f,it(!1),o.ensure(a,l),it(!0);return}}o.ensure(a,l)}pr(()=>{var a=!1;t((l,u=0)=>{a=!0,s(u,l)}),a||s(-1,null)},i)}var Sm=v(()=>{Fe();He();Be();vi()});var Zm=v(()=>{ot();Be();He();vi()});function Yu(e,t){se&&Ue(Pe(e)),Wt(()=>{var r=t();for(var n in r){var o=r[n];o?e.style.setProperty(n,o):e.style.removeProperty(n)}})}var km=v(()=>{Be();He();xt()});function et(e,t){return t}function qC(e,t,r){for(var n=[],o=t.length,i,s=t.length,a=0;a{if(i){if(i.pending.delete(g),i.done.add(g),i.pending.size===0){var d=e.outrogroups;zu(e,Pi(i.done)),d.delete(i),d.size===0&&(e.outrogroups=null)}}else s-=1},!1)}if(s===0){var l=n.length===0&&r!==null;if(l){var u=r,f=u.parentNode;Aa(f),f.append(u),e.items.clear()}zu(e,t,!l)}else i={pending:new Set(t),done:new Set},(e.outrogroups??(e.outrogroups=new Set)).add(i)}function zu(e,t,r=!0){var n;if(e.pending.size>0){n=new Set;for(let s of e.pending.values())for(let a of s)n.add(e.items.get(a).e)}for(var o=0;o{var E=r();return zr(E)?E:E==null?[]:Pi(E)});R&&ut(g,"{#each ...}");var d,p=new Map,h=!0;function b(E){(C.effect.f&16384)===0&&(C.pending.delete(E),C.fallback=f,eB(C,d,s,t,n),f!==null&&(d.length===0?(f.f&33554432)===0?ys(f):(f.f^=33554432,Xa(f,null,s)):Xn(f,()=>{f=null})))}function x(E){C.pending.delete(E)}var w=pr(()=>{d=c(g);var E=d.length;let y=!1;if(se){var U=rs(s)==="[!";U!==(E===0)&&(s=fn(),Ue(s),it(!1),y=!0)}for(var B=new Set,k=xe,G=cc(),W=0;Wi(s)):(f=ht(()=>i(Nm??(Nm=mt()))),f.f|=33554432)),E>B.size&&(R?rB(d,n):ru("","","")),se&&E>0&&Ue(fn()),!h)if(p.set(k,B),G){for(let[I,A]of a)B.has(I)||k.skip_effect(A.e);k.oncommit(b),k.ondiscard(x)}else b(k);y&&it(!0),c(g)}),C={effect:w,flags:t,items:a,pending:p,outrogroups:null,fallback:f};h=!1,se&&(s=be)}function Qa(e){for(;e!==null&&(e.f&32)===0;)e=e.next;return e}function eB(e,t,r,n,o){var i=(n&8)!==0,s=t.length,a=e.items,l=Qa(e.effect.first),u,f=null,g,d=[],p=[],h,b,x,w;if(i)for(w=0;w0){var W=(n&4)!==0&&s===0?r:null;if(i){for(w=0;w{if(g!==void 0)for(x of g)x.nodes?.a?.apply()})}function tB(e,t,r,n,o,i,s,a){var l=(s&1)!==0?(s&16)===0?qo(r,!1,!1):Vt(r):null,u=(s&2)!==0?Vt(o):null;return R&&l&&(l.trace=()=>{a()[u?.v??o]}),{v:l,i:u,e:ht(()=>(i(t,l??r,u??o,a),()=>{e.delete(n)}))}}function Xa(e,t,r){if(e.nodes)for(var n=e.nodes.start,o=e.nodes.end,i=t&&(t.f&33554432)===0?t.nodes.start:r;n!==null;){var s=Bt(n);if(i.before(n),n===o)return;n=s}}function ko(e,t,r){t===null?e.effect.first=r:t.next=r,r===null?e.effect.last=t:r.prev=t}function rB(e,t){let r=new Map,n=e.length;for(let o=0;o{Ve();He();xt();Be();pt();Re();Fe();mn();Ee();Se();Fo();zt();Xt();Qr()});function nB(e,t,r){if(!t||t===gm(String(r??"")))return;let n,o=e.__svelte_meta?.loc;o?n=`near ${o.file}:${o.line}:${o.column}`:Xr?.[Ir]&&(n=`in ${Xr[Ir]}`),ch(hc(n))}function Pu(e,t,r=!1,n=!1,o=!1,i=!1){var s=e,a="";if(r){var l=e;se&&(s=Ue(Pe(l)))}te(()=>{var u=ue;if(a===(a=t()??"")){se&&bt();return}if(r&&!se){u.nodes=null,l.innerHTML=a,a!==""&&Zt(Pe(l),l.lastChild);return}if(u.nodes!==null&&(Vu(u.nodes.start,u.nodes.end),u.nodes=null),a!==""){if(se){for(var f=be.data,g=bt(),d=g;g!==null&&(g.nodeType!==Zr||g.data!=="");)d=g,g=Bt(g);if(g===null)throw xo(),Gn;R&&!i&&nB(g.parentNode,f,a),Zt(be,d),s=Ue(g);return}var p=n?oa:o?ou:void 0,h=Un(n?"svg":o?"math":"template",p);h.innerHTML=a;var b=n||o?h:h.content;if(Zt(Pe(b),b.lastChild),n||o)for(;Pe(b);)s.before(Pe(b));else s.before(b)}})}var Rm=v(()=>{Ve();Be();He();pi();Rt();Zo();Se();ot();xt();Ee();Fe()});var Um=v(()=>{He()});var Ju=v(()=>{Zo();au();na();na()});function at(e,t,...r){var n=new wn(e);pr(()=>{let o=t()??null;R&&o==null&&Pp(),n.ensure(o,o&&(i=>o(i,...r)))},65536)}function Lm(e){return(t,...r)=>{var n=e(...r),o;if(se)o=be,bt();else{var i=n.render().trim(),s=Sa(i);o=Pe(s),R&&(Bt(o)!==null||o.nodeType!==Ll)&&dh(),t.before(o)}let a=n.setup?.(o);Zt(o,o),typeof a=="function"&&Et(a)}}var ju=v(()=>{Fe();Be();ot();He();bc();pi();Rt();Xt();Se();xt();Ju();vi()});function io(e,t,r){var n;se&&(n=be,bt());var o=new wn(e);pr(()=>{var i=t()??null;if(se){var s=rs(n),a=s==="[",l=i!==null;if(a!==l){var u=fn();Ue(u),o.anchor=u,it(!1),o.ensure(i,i&&(f=>r(f,i))),it(!0);return}}o.ensure(i,i&&(f=>r(f,i)))},65536)}var Vm=v(()=>{Fe();Be();He();vi();Ve()});var Ku=v(()=>{Re();Se()});var Wm=v(()=>{Ku()});var qu=v(()=>{Re();Be();Ee();Wm();hi();Ve();Fe();mn();tn()});var Tm=v(()=>{Ve();He();xt();Be();hi();Ee();ot();Se();Fe();pi();Zo();vi();qu()});var Dm=v(()=>{He();xt();Be();Fe()});var Om=v(()=>{Se();Tu();Be();xt()});function ft(e,t,r){ir(()=>{var n=ke(()=>t(e,r?.())||{});if(r&&n?.update){var o=!1,i={};Wt(()=>{var s=r();Fa(s),o&&Ol(i,s)&&(i=s,n.update(s))}),o=!0}if(n?.destroy)return()=>n.destroy()})}var Hm=v(()=>{Be();ia();Ee()});function wc(e,t){var r=void 0,n;uc(()=>{r!==(r=t())&&(n&&(rt(n),n=null),r&&(n=ht(()=>{ir(()=>r(e))})))})}var Cc=v(()=>{Be()});var Mm=v(()=>{});function Ym(e){var t,r,n="";if(typeof e=="string"||typeof e=="number")n+=e;else if(typeof e=="object")if(Array.isArray(e)){var o=e.length;for(t=0;t{});function Pt(e){return typeof e=="object"?zm(e):e??""}function Km(e,t,r){var n=e==null?"":""+e;if(t&&(n=n?n+" "+t:t),r){for(var o of Object.keys(r))if(r[o])n=n?n+" "+o:o;else if(n.length)for(var i=o.length,s=0;(s=n.indexOf(o,s))>=0;){var a=s+i;(s===0||Jm.includes(n[s-1]))&&(a===n.length||Jm.includes(n[a]))?n=(s===0?"":n.substring(0,s))+n.substring(a+1):s=a}}return n===""?null:n}function jm(e,t=!1){var r=t?" !important;":";",n="";for(var o of Object.keys(e)){var i=e[o];i!=null&&i!==""&&(n+=" "+o+": "+i+r)}return n}function ef(e){return e[0]!=="-"||e[1]!=="-"?e.toLowerCase():e}function qm(e,t){if(t){var r="",n,o;if(Array.isArray(t)?(n=t[0],o=t[1]):n=t,e){e=String(e).replaceAll(/\s*\/\*.*?\*\/\s*/g,"").trim();var i=!1,s=0,a=!1,l=[];n&&l.push(...Object.keys(n).map(ef)),o&&l.push(...Object.keys(o).map(ef));var u=0,f=-1;let b=e.length;for(var g=0;g{Mm();Pm();Re();Jm=[...` +\r\f\xA0\v\uFEFF`]});function Je(e,t,r,n,o,i){var s=e[qs];if(se||s!==r||s===void 0){var a=Km(r,n,i);(!se||a!==e.getAttribute("class"))&&(a==null?e.removeAttribute("class"):t?e.className=a:e.setAttribute("class",a)),e[qs]=r}else if(i&&o!==i)for(var l in i){var u=!!i[l];(o==null||u!==!!o[l])&&e.classList.toggle(l,u)}return i}var tf=v(()=>{Ra();Fe();He()});function rf(e,t={},r,n){for(var o in r){var i=r[o];t[o]!==i&&(r[o]==null?e.style.removeProperty(o):e.style.setProperty(o,i,n))}}function Oe(e,t,r,n){var o=e[ea];if(se||o!==t){var i=qm(t,n);(!se||i!==e.getAttribute("style"))&&(i==null?e.removeAttribute("style"):e.style.cssText=i),e[ea]=t}else n&&(Array.isArray(n)?(rf(e,r?.[0],n[0]),rf(e,r?.[1],n[1],"important")):rf(e,r,n));return n}var nf=v(()=>{Ra();Fe();He()});function Ua(e,t,r=!1){if(e.multiple){if(t==null)return;if(!zr(t))return fh();for(var n of e.options)n.selected=t.includes(ev(n));return}for(n of e.options){var o=ev(n);if(ku(o,t)){n.selected=!0;return}}(!r||t!==void 0)&&(e.selectedIndex=-1)}function of(e){var t=new MutationObserver(()=>{Ua(e,e.__value)});t.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["value"]}),Et(()=>{t.disconnect()})}function ev(e){return"__value"in e?e.__value:e.value}var sf=v(()=>{Be();tn();ai();Re();Rt();zt();lr()});function iv(e){if(se){var t=!1,r=()=>{if(!t){if(t=!0,e.hasAttribute("value")){var n=e.value;D(e,"value",null),e.value=n}if(e.hasAttribute("checked")){var o=e.checked;D(e,"checked",null),e.checked=o}}};e[ra]=r,yt(r),Xu()}}function sv(e,t){t?e.hasAttribute("selected")||e.setAttribute("selected",""):e.removeAttribute("selected")}function D(e,t,r,n){var o=av(e);if(se&&(o[t]=e.getAttribute(t),t==="src"||t==="srcset"||t==="href"&&e.nodeName===lB)){n||gB(e,t,r??"");return}o[t]!==(o[t]=r)&&(t==="loading"&&(e[kp]=r),r==null?e.removeAttribute(t):typeof r!="string"&&lv(e).includes(t)?e[t]=r:e.setAttribute(t,r))}function fB(e,t,r,n,o=!1,i=!1){if(se&&o&&e.nodeName===cB){var s=e,a=s.type==="checkbox"?"defaultChecked":"defaultValue";a in r||iv(s)}var l=av(e),u=l[nv],f=!l[ov];let g=se&&u;g&&it(!1);var d=t||{},p=e.nodeName===dB;for(var h in t)h in r||(r[h]=null);r.class?r.class=Pt(r.class):(n||r[on])&&(r.class=null),r[Er]&&(r.style??(r.style=null));var b=lv(e);for(let B in r){let k=r[B];if(p&&B==="value"&&k==null){e.value=e.__value="",d[B]=k;continue}if(B==="class"){var x=e.namespaceURI==="http://www.w3.org/1999/xhtml";Je(e,x,k,n,t?.[on],r[on]),d[B]=k,d[on]=r[on];continue}if(B==="style"){Oe(e,k,t?.[Er],r[Er]),d[B]=k,d[Er]=r[Er];continue}var w=d[B];if(!(k===w&&!(k===void 0&&e.hasAttribute(B)))){d[B]=k;var C=B[0]+B[1];if(C!=="$$")if(C==="on"){let G={},W="$$"+B,H=B.slice(2);var E=hm(H);if(pm(H)&&(H=H.slice(0,-7),G.capture=!0),!E&&w){if(k!=null)continue;e.removeEventListener(H,d[W],G),d[W]=null}if(E)St(H,e,k),yn([H]);else if(k!=null){let Z=function($){d[B].call(this,$)};d[W]=vc(H,e,Z,G)}}else if(B==="style")D(e,B,k);else if(B==="autofocus")Qu(e,!!k);else if(!u&&(B==="__value"||B==="value"&&k!=null))e.value=e.__value=k;else if(B==="selected"&&p)sv(e,k);else{var y=B;f||(y=mm(y));var U=y==="defaultValue"||y==="defaultChecked";if(k==null&&!u&&!U)if(l[B]=null,y==="value"||y==="checked"){let G=e,W=t===void 0;if(y==="value"){let H=G.defaultValue;G.removeAttribute(y),G.defaultValue=H,G.value=G.__value=W?H:null}else{let H=G.defaultChecked;G.removeAttribute(y),G.defaultChecked=H,G.checked=W?H:!1}}else e.removeAttribute(B);else U||b.includes(y)&&(u||typeof k!="string")?(e[y]=k,y in l&&(l[y]=Ye)):typeof k!="function"&&D(e,y,k,i)}}}return g&&it(!0),d}function Jt(e,t,r=[],n=[],o=[],i,s=!1,a=!1){Ca(o,r,n,l=>{var u=void 0,f={},g=e.nodeName===uB,d=!1;if(uc(()=>{var h=t(...l.map(c)),b=fB(e,u,h,i,s,a);d&&g&&"value"in h&&Ua(e,h.value);for(let w of Object.getOwnPropertySymbols(f))h[w]||rt(f[w]);for(let w of Object.getOwnPropertySymbols(h)){var x=h[w];w.description===iu&&(!u||x!==u[w])&&(f[w]&&rt(f[w]),f[w]=ht(()=>wc(e,()=>x))),b[w]=x}u=b}),g){var p=e;ir(()=>{Ua(p,u.value,!0),of(p)})}d=!0})}function av(e){var t;return e[t=Ul]??(e[t]={[nv]:e.nodeName.includes("-"),[ov]:e.namespaceURI===Wl})}function lv(e){var t=e.getAttribute("is")||e.nodeName,r=tv.get(t);if(r)return r;tv.set(t,r=[]);for(var n,o=e,i=Element.prototype;i!==o;){n=Nl(o);for(var s in n)n[s].set&&s!=="innerHTML"&&s!=="textContent"&&s!=="innerText"&&r.push(s);o=_o(o)}return r}function gB(e,t,r){R&&(t==="srcset"&&pB(e,r)||af(e.getAttribute(t)??"",r)||lh(t,e.outerHTML.replace(e.innerHTML,e.innerHTML&&"..."),String(r)))}function af(e,t){return e===t?!0:new URL(e,document.baseURI).href===new URL(t,document.baseURI).href}function rv(e){return e.split(",").map(t=>t.trim().split(" ").filter(Boolean))}function pB(e,t){var r=rv(e.srcset),n=rv(t);return n.length===r.length&&n.every(([o,i],s)=>i===r[s][1]&&(af(r[s][0],o)||af(o,r[s][0])))}var on,Er,nv,ov,lB,cB,dB,uB,tv,cv=v(()=>{Se();He();Re();Is();dc();Rt();Fe();mn();Zo();Ee();Cc();Ra();tf();nf();Ve();Be();sf();Go();on=Symbol("class"),Er=Symbol("style"),nv=Symbol("is custom element"),ov=Symbol("is html"),lB=Ki?"link":"LINK",cB=Ki?"input":"INPUT",dB=Ki?"option":"OPTION",uB=Ki?"select":"SELECT";tv=new Map});var dv=v(()=>{He();xt();bc();Cc()});var uv=v(()=>{tn()});var fv=v(()=>{Se();Be();tn();Xt();ai();mn();He();Ee();ot();zt();lr()});var gv=v(()=>{Be();tn()});var pv=v(()=>{tn()});var hv=v(()=>{Be();Re()});function Ac(e,t,r){var n=hB.observe(e,()=>r(e[t]));ir(()=>(ke(()=>r(e[t])),n))}var No,Cs,La,Ec,mv,$c,lf,hB,vv=v(()=>{Be();Ee();$c=class $c{constructor(t){L(this,Ec);L(this,No,new WeakMap);L(this,Cs);L(this,La);he(this,La,t)}observe(t,r){var n=m(this,No).get(t)||new Set;return n.add(r),m(this,No).set(t,n),Ce(this,Ec,mv).call(this).observe(t,m(this,La)),()=>{var o=m(this,No).get(t);o.delete(r),o.size===0&&(m(this,No).delete(t),m(this,Cs).unobserve(t))}}};No=new WeakMap,Cs=new WeakMap,La=new WeakMap,Ec=new WeakSet,mv=function(){return m(this,Cs)??he(this,Cs,new ResizeObserver(t=>{for(var r of t){$c.entries.set(r.target,r);for(var n of m(this,No).get(r.target)||[])n(r)}}))},Ae($c,"entries",new WeakMap);lf=$c,hB=new lf({box:"border-box"})});function cf(e,t){return e===t||e?.[_t]===t}function Dr(e={},t,r,n){var o=_e.r,i=ue;return ir(()=>{var s,a;return Wt(()=>{s=a,a=n?.()||[],ke(()=>{cf(r(...a),e)||(t(e,...a),s&&cf(r(...s),e)&&t(null,...s))})}),()=>{let l=i;for(;l!==o&&l.parent!==null&&l.parent.f&33554432;)l=l.parent;let u=()=>{a&&cf(r(...a),e)&&t(null,...a)},f=l.teardown;l.teardown=()=>{u(),f?.()}}}),e}var _v=v(()=>{Fe();ot();Be();Ee()});var bv=v(()=>{Be();tn()});var xv=v(()=>{Be();tn()});var df=v(()=>{Re();Be();Is()});function uf(e=!1){let t=_e,r=t.l.u;if(!r)return;let n=()=>Fa(t.s);if(e){let o=0,i={},s=oo(()=>{let a=!1,l=t.s;for(let u in l)l[u]!==i[u]&&(i[u]=l[u],a=!0);return a&&o++,o});n=()=>c(s)}r.b.length&&ci(()=>{yv(t,n),Ji(r.b)}),st(()=>{let o=ke(()=>r.m.map(Zp));return()=>{for(let i of o)typeof i=="function"&&i()}}),r.a.length&&st(()=>{yv(t,n),Ji(r.a)})}function yv(e,t){if(e.l.s)for(let r of e.l.s)c(r);t()}var Iv=v(()=>{Re();ot();Fo();Be();Ee()});var wv=v(()=>{pt();Ee();Re()});function jt(e,t,r){return new Proxy(R?{props:e,exclude:t,name:r,other:{},to_proxy:[]}:{props:e,exclude:t},yB)}function Cn(...e){return new Proxy({props:e},IB)}function P(e,t,r,n){var o=!Fn||(r&2)!==0,i=(r&8)!==0,s=(r&16)!==0,a=n,l=!0,u=void 0,f=()=>s&&o?(u??(u=oo(n)),c(u)):(l&&(l=!1,a=s?ke(n):n),a);let g;if(i){var d=_t in e||ji in e;g=tr(e,t)?.set??(d&&t in e?y=>e[t]=y:void 0)}var p,h=!1;i?[p,h]=fu(()=>e[t]):p=e[t],p===void 0&&n!==void 0&&(p=f(),g&&(o&&Jp(t),g(p)));var b;if(o?b=()=>{var y=e[t];return y===void 0?f():(l=!0,y)}:b=()=>{var y=e[t];return y!==void 0&&(a=void 0),y===void 0?a:y},o&&(r&4)===0)return b;if(g){var x=e.$$legacy;return(function(y,U){return arguments.length>0?((!o||!U||x||h)&&g(U?b():y),y):b()})}var w=!1,C=((r&1)!==0?oo:oi)(()=>(w=!1,b()));R&&(C.label=t),i&&c(C);var E=ue;return(function(y,U){if(arguments.length>0){let B=U?c(C):o&&i?Dt(y):y;return M(C,B),w=!0,a!==void 0&&(a=B),y}return Vr&&w||(E.f&16384)!==0?C.v:c(C)})}var yB,IB,Cv=v(()=>{Se();Ve();Re();pt();Fo();Ee();Xt();Fe();ai();ua();lr();Be();yB={get(e,t){if(!e.exclude.has(t))return e.props[t]},set(e,t){return R&&jp(`${e.name}.${String(t)}`),!1},getOwnPropertyDescriptor(e,t){if(!e.exclude.has(t)&&t in e.props)return{enumerable:!0,configurable:!0,value:e.props[t]}},has(e,t){return e.exclude.has(t)?!1:t in e.props},ownKeys(e){return Reflect.ownKeys(e.props).filter(t=>!e.exclude.has(t))}};IB={get(e,t){let r=e.props.length;for(;r--;){let n=e.props[r];if(Yo(n)&&(n=n()),typeof n=="object"&&n!==null&&t in n)return n[t]}},set(e,t,r){let n=e.props.length;for(;n--;){let o=e.props[n];Yo(o)&&(o=o());let i=tr(o,t);if(i&&i.set)return i.set(r),!0}return!1},getOwnPropertyDescriptor(e,t){let r=e.props.length;for(;r--;){let n=e.props[r];if(Yo(n)&&(n=n()),typeof n=="object"&&n!==null&&t in n){let o=tr(n,t);return o&&!o.configurable&&(o.configurable=!0),o}}},has(e,t){if(t===_t||t===ji)return!1;for(let r of e.props)if(Yo(r)&&(r=r()),r!=null&&t in r)return!0;return!1},ownKeys(e){let t=[];for(let r of e.props)if(Yo(r)&&(r=r()),!!r){for(let n in r)t.includes(n)||t.push(n);for(let n of Object.getOwnPropertySymbols(r))t.includes(n)||t.push(n)}return t}}});var Bv=v(()=>{ot();Ve();Be();Rt();ua();Go()});function Ev(e){return new ff(e)}var so,sn,ff,$v=v(()=>{Fe();Be();pt();hi();Ee();zt();Re();Xt();Rt();Se();Ve();ot();lr();Io();df();ff=class{constructor(t){L(this,so);L(this,sn);var r=new Map,n=(i,s)=>{var a=qo(s,!1,!1);return r.set(i,a),a};let o=new Proxy({...t.props||{},$$events:{}},{get(i,s){return c(r.get(s)??n(s,Reflect.get(i,s)))},has(i,s){return s===ji?!0:(c(r.get(s)??n(s,Reflect.get(i,s))),Reflect.has(i,s))},set(i,s,a){return M(r.get(s)??n(s,a),a),Reflect.set(i,s,a)}});he(this,sn,(t.hydrate?ws:Za)(t.component,{target:t.target,anchor:t.anchor,props:o,context:t.context,intro:t.intro??!1,recover:t.recover,transformError:t.transformError})),!dt&&(!t?.props?.$$host||t.sync===!1)&&kn(),he(this,so,o.$$events);for(let i of Object.keys(m(this,sn)))i==="$set"||i==="$destroy"||i==="$on"||Ht(this,i,{get(){return m(this,sn)[i]},set(s){m(this,sn)[i]=s},enumerable:!0});m(this,sn).$set=i=>{Object.assign(o,i)},m(this,sn).$destroy=()=>{yc(m(this,sn))}}$set(t){m(this,sn).$set(t)}$on(t,r){m(this,so)[t]=m(this,so)[t]||[];let n=(...o)=>r.call(this,...o);return m(this,so)[t].push(n),()=>{m(this,so)[t]=m(this,so)[t].filter(o=>o!==n)}}$destroy(){m(this,sn).$destroy()}};so=new WeakMap,sn=new WeakMap});function gf(e,t,r,n){let o=r[e]?.type;if(t=o==="Boolean"&&typeof t!="boolean"?t!=null:t,!n||!r[e])return t;if(n==="toAttribute")switch(o){case"Object":case"Array":return t==null?null:JSON.stringify(t);case"Boolean":return t?"":null;case"Number":return t??null;default:return t}else switch(o){case"Object":case"Array":return t&&JSON.parse(t);case"Boolean":return t;case"Number":return t!=null?+t:t;default:return t}}function SB(e){let t={};return e.childNodes.forEach(r=>{t[r.slot||"default"]=!0}),t}var FB,Av=v(()=>{$v();Be();pi();Re();xt();typeof HTMLElement=="function"&&(FB=class extends HTMLElement{constructor(t,r,n){super();Ae(this,"$$ctor");Ae(this,"$$s");Ae(this,"$$c");Ae(this,"$$cn",!1);Ae(this,"$$d",{});Ae(this,"$$r",!1);Ae(this,"$$p_d",{});Ae(this,"$$l",{});Ae(this,"$$l_u",new Map);Ae(this,"$$me");Ae(this,"$$shadowRoot",null);this.$$ctor=t,this.$$s=r,n&&(this.$$shadowRoot=this.attachShadow(n))}addEventListener(t,r,n){if(this.$$l[t]=this.$$l[t]||[],this.$$l[t].push(r),this.$$c){let o=this.$$c.$on(t,r);this.$$l_u.set(r,o)}super.addEventListener(t,r,n)}removeEventListener(t,r,n){if(super.removeEventListener(t,r,n),this.$$c){let o=this.$$l_u.get(r);o&&(o(),this.$$l_u.delete(r))}}async connectedCallback(){if(this.$$cn=!0,!this.$$c){let t=function(o){return i=>{let s=Un("slot");o!=="default"&&(s.name=o),F(i,s)}};if(await Promise.resolve(),!this.$$cn||this.$$c)return;let r={},n=SB(this);for(let o of this.$$s)o in n&&(o==="default"&&!this.$$d.children?(this.$$d.children=t(o),r.default=!0):r[o]=t(o));for(let o of this.attributes){let i=this.$$g_p(o.name);i in this.$$d||(this.$$d[i]=gf(i,o.value,this.$$p_d,"toProp"))}for(let o in this.$$p_d)!(o in this.$$d)&&this[o]!==void 0&&(this.$$d[o]=this[o],delete this[o]);this.$$c=Ev({component:this.$$ctor,target:this.$$shadowRoot||this,props:{...this.$$d,$$slots:r,$$host:this}}),this.$$me=di(()=>{Wt(()=>{this.$$r=!0;for(let o of Kd(this.$$c)){if(!this.$$p_d[o]?.reflect)continue;this.$$d[o]=this.$$c[o];let i=gf(o,this.$$d[o],this.$$p_d,"toAttribute");i==null?this.removeAttribute(this.$$p_d[o].attribute||o):this.setAttribute(this.$$p_d[o].attribute||o,i)}this.$$r=!1})});for(let o in this.$$l)for(let i of this.$$l[o]){let s=this.$$c.$on(o,i);this.$$l_u.set(i,s)}this.$$l={}}}attributeChangedCallback(t,r,n){this.$$r||(t=this.$$g_p(t),this.$$d[t]=gf(t,n,this.$$p_d,"toProp"),this.$$c?.$set({[t]:this.$$d[t]}))}disconnectedCallback(){this.$$cn=!1,Promise.resolve().then(()=>{!this.$$cn&&this.$$c&&(this.$$c.$destroy(),this.$$me(),this.$$c=void 0)})}$$g_p(t){return Kd(this.$$p_d).find(r=>this.$$p_d[r].attribute===t||!this.$$p_d[r].attribute&&r.toLowerCase()===t)||t}})});var Gv=v(()=>{Fe();ns();Rt();Ee()});var ie=v(()=>{fm();Ve();ot();_m();Tu();bm();Cm();Bm();Em();Qr();$m();Am();Gm();Fm();Sm();Zm();km();Xm();Rm();Um();ju();Vm();Tm();Dm();Om();Hm();Cc();cv();tf();Is();dc();dv();nf();qu();uv();fv();gv();pv();hv();sf();vv();_v();bv();xv();He();df();Iv();wv();pi();Go();zt();Fo();Be();pt();Cv();ua();oc();Wu();hi();Ee();Bv();Ku();ai();Av();xt();Ra();ns();Re();Ju();Nu();Gv();is()});function Fv(e,t){if(dt||Vl("hydratable"),se){let r=window.__svelte?.h;if(r?.has(e))return r.get(e);R?Yp(e):ah(e)}return t()}var Sv=v(()=>{lr();He();Rt();Xt();Se()});var Zv={};Pd(Zv,{afterUpdate:()=>XB,beforeUpdate:()=>QB,createContext:()=>_h,createEventDispatcher:()=>NB,createRawSnippet:()=>Lm,flushSync:()=>kn,fork:()=>Xh,getAbortSignal:()=>ZB,getAllContexts:()=>bh,getContext:()=>Pn,hasContext:()=>la,hydratable:()=>Fv,hydrate:()=>ws,mount:()=>Za,onDestroy:()=>_i,onMount:()=>Bs,setContext:()=>Jo,settled:()=>cm,tick:()=>pc,unmount:()=>yc,untrack:()=>ke});function ZB(){var e;return me===null&&Mp(),((e=me).ac??(e.ac=new AbortController)).signal}function Bs(e){_e===null&&Mn("onMount"),Fn&&_e.l!==null?pf(_e).m.push(e):st(()=>{let t=ke(e);if(typeof t=="function")return t})}function _i(e){_e===null&&Mn("onDestroy"),Bs(()=>()=>ke(e))}function kB(e,t,{bubbles:r=!1,cancelable:n=!1}={}){return new CustomEvent(e,{detail:t,bubbles:r,cancelable:n})}function NB(){let e=_e;return e===null&&Mn("createEventDispatcher"),(t,r,n)=>{let o=e.s.$$events?.[t];if(o){let i=zr(o)?o.slice():[o],s=kB(t,r,n);for(let a of i)a.call(e.x,s);return!s.defaultPrevented}return!0}}function QB(e){_e===null&&Mn("beforeUpdate"),_e.l===null&&nu("beforeUpdate"),pf(_e).b.push(e)}function XB(e){_e===null&&Mn("afterUpdate"),_e.l===null&&nu("afterUpdate"),pf(_e).a.push(e)}function pf(e){var t=e.l;return t.u??(t.u={a:[],b:[],m:[]})}var nn=v(()=>{Ee();Re();ie();Xt();lr();ot();Se();zt();ot();Sv();hi();Ee();ju();if(R){let e=function(t){if(!(t in globalThis)){let r;Object.defineProperty(globalThis,t,{configurable:!0,get:()=>{if(r!==void 0)return r;Kp(t)},set:n=>{r=n}})}};e("$state"),e("$effect"),e("$derived"),e("$inspect"),e("$props"),e("$bindable")}});var kv=v(()=>{});var Nv,ve=v(()=>{kv();typeof window<"u"&&((Nv=window.__svelte??(window.__svelte={})).v??(Nv.v=new Set)).add("5")});function Xv(){for(var e=0,t=arguments.length,r={},n;e=0&&(n=r.slice(o+1),r=r.slice(0,o)),r&&!t.hasOwnProperty(r))throw new Error("unknown type: "+r);return{type:r,name:n}})}function JB(e,t){for(var r=0,n=e.length,o;r{zB={value:()=>{}};Gc.prototype=Xv.prototype={constructor:Gc,on:function(e,t){var r=this._,n=PB(e+"",r),o,i=-1,s=n.length;if(arguments.length<2){for(;++i0)for(var r=new Array(o),n=0,o,i;n{Rv()});var Sc,mf,vf=v(()=>{Sc="http://www.w3.org/1999/xhtml",mf={svg:"http://www.w3.org/2000/svg",xhtml:Sc,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"}});function ao(e){var t=e+="",r=t.indexOf(":");return r>=0&&(t=e.slice(0,r))!=="xmlns"&&(e=e.slice(r+1)),mf.hasOwnProperty(t)?{space:mf[t],local:e}:e}var Zc=v(()=>{vf()});function jB(e){return function(){var t=this.ownerDocument,r=this.namespaceURI;return r===Sc&&t.documentElement.namespaceURI===Sc?t.createElement(e):t.createElementNS(r,e)}}function KB(e){return function(){return this.ownerDocument.createElementNS(e.space,e.local)}}function kc(e){var t=ao(e);return(t.local?KB:jB)(t)}var _f=v(()=>{Zc();vf()});function qB(){}function xi(e){return e==null?qB:function(){return this.querySelector(e)}}var Nc=v(()=>{});function Uv(e){typeof e!="function"&&(e=xi(e));for(var t=this._groups,r=t.length,n=new Array(r),o=0;o{Bn();Nc()});function bf(e){return e==null?[]:Array.isArray(e)?e:Array.from(e)}var Vv=v(()=>{});function eE(){return[]}function Wa(e){return e==null?eE:function(){return this.querySelectorAll(e)}}var xf=v(()=>{});function tE(e){return function(){return bf(e.apply(this,arguments))}}function Wv(e){typeof e=="function"?e=tE(e):e=Wa(e);for(var t=this._groups,r=t.length,n=[],o=[],i=0;i{Bn();Vv();xf()});function Ta(e){return function(){return this.matches(e)}}function Qc(e){return function(t){return t.matches(e)}}var Da=v(()=>{});function nE(e){return function(){return rE.call(this.children,e)}}function oE(){return this.firstElementChild}function Dv(e){return this.select(e==null?oE:nE(typeof e=="function"?e:Qc(e)))}var rE,Ov=v(()=>{Da();rE=Array.prototype.find});function sE(){return Array.from(this.children)}function aE(e){return function(){return iE.call(this.children,e)}}function Hv(e){return this.selectAll(e==null?sE:aE(typeof e=="function"?e:Qc(e)))}var iE,Mv=v(()=>{Da();iE=Array.prototype.filter});function Yv(e){typeof e!="function"&&(e=Ta(e));for(var t=this._groups,r=t.length,n=new Array(r),o=0;o{Bn();Da()});function Xc(e){return new Array(e.length)}var yf=v(()=>{});function Pv(){return new gt(this._enter||this._groups.map(Xc),this._parents)}function Oa(e,t){this.ownerDocument=e.ownerDocument,this.namespaceURI=e.namespaceURI,this._next=null,this._parent=e,this.__data__=t}var If=v(()=>{yf();Bn();Oa.prototype={constructor:Oa,appendChild:function(e){return this._parent.insertBefore(e,this._next)},insertBefore:function(e,t){return this._parent.insertBefore(e,t)},querySelector:function(e){return this._parent.querySelector(e)},querySelectorAll:function(e){return this._parent.querySelectorAll(e)}}});function Jv(e){return function(){return e}}var jv=v(()=>{});function lE(e,t,r,n,o,i){for(var s=0,a,l=t.length,u=i.length;s=E&&(E=C+1);!(U=x[E])&&++E{Bn();If();jv()});function e_(){return new gt(this._exit||this._groups.map(Xc),this._parents)}var t_=v(()=>{yf();Bn()});function r_(e,t,r){var n=this.enter(),o=this,i=this.exit();return typeof e=="function"?(n=e(n),n&&(n=n.selection())):n=n.append(e+""),t!=null&&(o=t(o),o&&(o=o.selection())),r==null?i.remove():r(i),n&&o?n.merge(o).order():o}var n_=v(()=>{});function o_(e){for(var t=e.selection?e.selection():e,r=this._groups,n=t._groups,o=r.length,i=n.length,s=Math.min(o,i),a=new Array(o),l=0;l{Bn()});function s_(){for(var e=this._groups,t=-1,r=e.length;++t=0;)(s=n[o])&&(i&&s.compareDocumentPosition(i)^4&&i.parentNode.insertBefore(s,i),i=s);return this}var a_=v(()=>{});function l_(e){e||(e=fE);function t(g,d){return g&&d?e(g.__data__,d.__data__):!g-!d}for(var r=this._groups,n=r.length,o=new Array(n),i=0;it?1:e>=t?0:NaN}var c_=v(()=>{Bn()});function d_(){var e=arguments[0];return arguments[0]=this,e.apply(null,arguments),this}var u_=v(()=>{});function f_(){return Array.from(this)}var g_=v(()=>{});function p_(){for(var e=this._groups,t=0,r=e.length;t{});function m_(){let e=0;for(let t of this)++e;return e}var v_=v(()=>{});function __(){return!this.node()}var b_=v(()=>{});function x_(e){for(var t=this._groups,r=0,n=t.length;r{});function gE(e){return function(){this.removeAttribute(e)}}function pE(e){return function(){this.removeAttributeNS(e.space,e.local)}}function hE(e,t){return function(){this.setAttribute(e,t)}}function mE(e,t){return function(){this.setAttributeNS(e.space,e.local,t)}}function vE(e,t){return function(){var r=t.apply(this,arguments);r==null?this.removeAttribute(e):this.setAttribute(e,r)}}function _E(e,t){return function(){var r=t.apply(this,arguments);r==null?this.removeAttributeNS(e.space,e.local):this.setAttributeNS(e.space,e.local,r)}}function I_(e,t){var r=ao(e);if(arguments.length<2){var n=this.node();return r.local?n.getAttributeNS(r.space,r.local):n.getAttribute(r)}return this.each((t==null?r.local?pE:gE:typeof t=="function"?r.local?_E:vE:r.local?mE:hE)(r,t))}var w_=v(()=>{Zc()});function Rc(e){return e.ownerDocument&&e.ownerDocument.defaultView||e.document&&e||e.defaultView}var wf=v(()=>{});function bE(e){return function(){this.style.removeProperty(e)}}function xE(e,t,r){return function(){this.style.setProperty(e,t,r)}}function yE(e,t,r){return function(){var n=t.apply(this,arguments);n==null?this.style.removeProperty(e):this.style.setProperty(e,n,r)}}function C_(e,t,r){return arguments.length>1?this.each((t==null?bE:typeof t=="function"?yE:xE)(e,t,r??"")):Qo(this.node(),e)}function Qo(e,t){return e.style.getPropertyValue(t)||Rc(e).getComputedStyle(e,null).getPropertyValue(t)}var Cf=v(()=>{wf()});function IE(e){return function(){delete this[e]}}function wE(e,t){return function(){this[e]=t}}function CE(e,t){return function(){var r=t.apply(this,arguments);r==null?delete this[e]:this[e]=r}}function B_(e,t){return arguments.length>1?this.each((t==null?IE:typeof t=="function"?CE:wE)(e,t)):this.node()[e]}var E_=v(()=>{});function $_(e){return e.trim().split(/^|\s+/)}function Bf(e){return e.classList||new A_(e)}function A_(e){this._node=e,this._names=$_(e.getAttribute("class")||"")}function G_(e,t){for(var r=Bf(e),n=-1,o=t.length;++n{A_.prototype={add:function(e){var t=this._names.indexOf(e);t<0&&(this._names.push(e),this._node.setAttribute("class",this._names.join(" ")))},remove:function(e){var t=this._names.indexOf(e);t>=0&&(this._names.splice(t,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(e){return this._names.indexOf(e)>=0}}});function AE(){this.textContent=""}function GE(e){return function(){this.textContent=e}}function FE(e){return function(){var t=e.apply(this,arguments);this.textContent=t??""}}function k_(e){return arguments.length?this.each(e==null?AE:(typeof e=="function"?FE:GE)(e)):this.node().textContent}var N_=v(()=>{});function SE(){this.innerHTML=""}function ZE(e){return function(){this.innerHTML=e}}function kE(e){return function(){var t=e.apply(this,arguments);this.innerHTML=t??""}}function Q_(e){return arguments.length?this.each(e==null?SE:(typeof e=="function"?kE:ZE)(e)):this.node().innerHTML}var X_=v(()=>{});function NE(){this.nextSibling&&this.parentNode.appendChild(this)}function R_(){return this.each(NE)}var U_=v(()=>{});function QE(){this.previousSibling&&this.parentNode.insertBefore(this,this.parentNode.firstChild)}function L_(){return this.each(QE)}var V_=v(()=>{});function W_(e){var t=typeof e=="function"?e:kc(e);return this.select(function(){return this.appendChild(t.apply(this,arguments))})}var T_=v(()=>{_f()});function XE(){return null}function D_(e,t){var r=typeof e=="function"?e:kc(e),n=t==null?XE:typeof t=="function"?t:xi(t);return this.select(function(){return this.insertBefore(r.apply(this,arguments),n.apply(this,arguments)||null)})}var O_=v(()=>{_f();Nc()});function RE(){var e=this.parentNode;e&&e.removeChild(this)}function H_(){return this.each(RE)}var M_=v(()=>{});function UE(){var e=this.cloneNode(!1),t=this.parentNode;return t?t.insertBefore(e,this.nextSibling):e}function LE(){var e=this.cloneNode(!0),t=this.parentNode;return t?t.insertBefore(e,this.nextSibling):e}function Y_(e){return this.select(e?LE:UE)}var z_=v(()=>{});function P_(e){return arguments.length?this.property("__data__",e):this.node().__data__}var J_=v(()=>{});function VE(e){return function(t){e.call(this,t,this.__data__)}}function WE(e){return e.trim().split(/^|\s+/).map(function(t){var r="",n=t.indexOf(".");return n>=0&&(r=t.slice(n+1),t=t.slice(0,n)),{type:t,name:r}})}function TE(e){return function(){var t=this.__on;if(t){for(var r=0,n=-1,o=t.length,i;r{});function q_(e,t,r){var n=Rc(e),o=n.CustomEvent;typeof o=="function"?o=new o(t,r):(o=n.document.createEvent("Event"),r?(o.initEvent(t,r.bubbles,r.cancelable),o.detail=r.detail):o.initEvent(t,!1,!1)),e.dispatchEvent(o)}function OE(e,t){return function(){return q_(this,e,t)}}function HE(e,t){return function(){return q_(this,e,t.apply(this,arguments))}}function eb(e,t){return this.each((typeof t=="function"?HE:OE)(e,t))}var tb=v(()=>{wf()});function*rb(){for(var e=this._groups,t=0,r=e.length;t{});function gt(e,t){this._groups=e,this._parents=t}function ob(){return new gt([[document.documentElement]],Ef)}function ME(){return this}var Ef,lo,Bn=v(()=>{Lv();Tv();Ov();Mv();zv();qv();If();t_();n_();i_();a_();c_();u_();g_();h_();v_();b_();y_();w_();Cf();E_();Z_();N_();X_();U_();V_();T_();O_();M_();z_();J_();K_();tb();nb();Ef=[null];gt.prototype=ob.prototype={constructor:gt,select:Uv,selectAll:Wv,selectChild:Dv,selectChildren:Hv,filter:Yv,data:Kv,enter:Pv,exit:e_,join:r_,merge:o_,selection:ME,order:s_,sort:l_,call:d_,nodes:f_,node:p_,size:m_,empty:__,each:x_,attr:I_,style:C_,property:B_,classed:S_,text:k_,html:Q_,raise:R_,lower:L_,append:W_,insert:D_,remove:H_,clone:Y_,datum:P_,on:j_,dispatch:eb,[Symbol.iterator]:rb};lo=ob});function Kt(e){return typeof e=="string"?new gt([[document.querySelector(e)]],[document.documentElement]):new gt([[e]],Ef)}var ib=v(()=>{Bn()});function sb(e){let t;for(;t=e.sourceEvent;)e=t;return e}var ab=v(()=>{});function vr(e,t){if(e=sb(e),t===void 0&&(t=e.currentTarget),t){var r=t.ownerSVGElement||t;if(r.createSVGPoint){var n=r.createSVGPoint();return n.x=e.clientX,n.y=e.clientY,n=n.matrixTransform(t.getScreenCTM().inverse()),[n.x,n.y]}if(t.getBoundingClientRect){var o=t.getBoundingClientRect();return[e.clientX-o.left-t.clientLeft,e.clientY-o.top-t.clientTop]}}return[e.pageX,e.pageY]}var lb=v(()=>{ab()});var $r=v(()=>{Da();Zc();lb();ib();Bn();Nc();xf();Cf()});function Uc(e){e.stopImmediatePropagation()}function Xo(e){e.preventDefault(),e.stopImmediatePropagation()}var cb,yi,$f=v(()=>{cb={passive:!1},yi={capture:!0,passive:!1}});function Ha(e){var t=e.document.documentElement,r=Kt(e).on("dragstart.drag",Xo,yi);"onselectstart"in t?r.on("selectstart.drag",Xo,yi):(t.__noselect=t.style.MozUserSelect,t.style.MozUserSelect="none")}function Ma(e,t){var r=e.document.documentElement,n=Kt(e).on("dragstart.drag",null);t&&(n.on("click.drag",Xo,yi),setTimeout(function(){n.on("click.drag",null)},0)),"onselectstart"in r?n.on("selectstart.drag",null):(r.style.MozUserSelect=r.__noselect,delete r.__noselect)}var Af=v(()=>{$r();$f()});var Ya,db=v(()=>{Ya=e=>()=>e});function za(e,{sourceEvent:t,subject:r,target:n,identifier:o,active:i,x:s,y:a,dx:l,dy:u,dispatch:f}){Object.defineProperties(this,{type:{value:e,enumerable:!0,configurable:!0},sourceEvent:{value:t,enumerable:!0,configurable:!0},subject:{value:r,enumerable:!0,configurable:!0},target:{value:n,enumerable:!0,configurable:!0},identifier:{value:o,enumerable:!0,configurable:!0},active:{value:i,enumerable:!0,configurable:!0},x:{value:s,enumerable:!0,configurable:!0},y:{value:a,enumerable:!0,configurable:!0},dx:{value:l,enumerable:!0,configurable:!0},dy:{value:u,enumerable:!0,configurable:!0},_:{value:f}})}var ub=v(()=>{za.prototype.on=function(){var e=this._.on.apply(this._,arguments);return e===this._?this:e}});function YE(e){return!e.ctrlKey&&!e.button}function zE(){return this.parentNode}function PE(e,t){return t??{x:e.x,y:e.y}}function JE(){return navigator.maxTouchPoints||"ontouchstart"in this}function Gf(){var e=YE,t=zE,r=PE,n=JE,o={},i=bi("start","drag","end"),s=0,a,l,u,f,g=0;function d(y){y.on("mousedown.drag",p).filter(n).on("touchstart.drag",x).on("touchmove.drag",w,cb).on("touchend.drag touchcancel.drag",C).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function p(y,U){if(!(f||!e.call(this,y,U))){var B=E(this,t.call(this,y,U),y,U,"mouse");B&&(Kt(y.view).on("mousemove.drag",h,yi).on("mouseup.drag",b,yi),Ha(y.view),Uc(y),u=!1,a=y.clientX,l=y.clientY,B("start",y))}}function h(y){if(Xo(y),!u){var U=y.clientX-a,B=y.clientY-l;u=U*U+B*B>g}o.mouse("drag",y)}function b(y){Kt(y.view).on("mousemove.drag mouseup.drag",null),Ma(y.view,u),Xo(y),o.mouse("end",y)}function x(y,U){if(e.call(this,y,U)){var B=y.changedTouches,k=t.call(this,y,U),G=B.length,W,H;for(W=0;W{Fc();$r();Af();$f();db();ub()});var Ff=v(()=>{fb();Af()});function Lc(e,t,r){e.prototype=t.prototype=r,r.constructor=e}function Sf(e,t){var r=Object.create(e.prototype);for(var n in t)r[n]=t[n];return r}var gb=v(()=>{});function ja(){}function hb(){return this.rgb().formatHex()}function o1(){return this.rgb().formatHex8()}function i1(){return Ib(this).formatHsl()}function mb(){return this.rgb().formatRgb()}function $n(e){var t,r;return e=(e+"").trim().toLowerCase(),(t=jE.exec(e))?(r=t[1].length,t=parseInt(t[1],16),r===6?vb(t):r===3?new Ar(t>>8&15|t>>4&240,t>>4&15|t&240,(t&15)<<4|t&15,1):r===8?Vc(t>>24&255,t>>16&255,t>>8&255,(t&255)/255):r===4?Vc(t>>12&15|t>>8&240,t>>8&15|t>>4&240,t>>4&15|t&240,((t&15)<<4|t&15)/255):null):(t=KE.exec(e))?new Ar(t[1],t[2],t[3],1):(t=qE.exec(e))?new Ar(t[1]*255/100,t[2]*255/100,t[3]*255/100,1):(t=e1.exec(e))?Vc(t[1],t[2],t[3],t[4]):(t=t1.exec(e))?Vc(t[1]*255/100,t[2]*255/100,t[3]*255/100,t[4]):(t=r1.exec(e))?xb(t[1],t[2]/100,t[3]/100,1):(t=n1.exec(e))?xb(t[1],t[2]/100,t[3]/100,t[4]):pb.hasOwnProperty(e)?vb(pb[e]):e==="transparent"?new Ar(NaN,NaN,NaN,0):null}function vb(e){return new Ar(e>>16&255,e>>8&255,e&255,1)}function Vc(e,t,r,n){return n<=0&&(e=t=r=NaN),new Ar(e,t,r,n)}function s1(e){return e instanceof ja||(e=$n(e)),e?(e=e.rgb(),new Ar(e.r,e.g,e.b,e.opacity)):new Ar}function $s(e,t,r,n){return arguments.length===1?s1(e):new Ar(e,t,r,n??1)}function Ar(e,t,r,n){this.r=+e,this.g=+t,this.b=+r,this.opacity=+n}function _b(){return`#${Ii(this.r)}${Ii(this.g)}${Ii(this.b)}`}function a1(){return`#${Ii(this.r)}${Ii(this.g)}${Ii(this.b)}${Ii((isNaN(this.opacity)?1:this.opacity)*255)}`}function bb(){let e=Dc(this.opacity);return`${e===1?"rgb(":"rgba("}${wi(this.r)}, ${wi(this.g)}, ${wi(this.b)}${e===1?")":`, ${e})`}`}function Dc(e){return isNaN(e)?1:Math.max(0,Math.min(1,e))}function wi(e){return Math.max(0,Math.min(255,Math.round(e)||0))}function Ii(e){return e=wi(e),(e<16?"0":"")+e.toString(16)}function xb(e,t,r,n){return n<=0?e=t=r=NaN:r<=0||r>=1?e=t=NaN:t<=0&&(e=NaN),new En(e,t,r,n)}function Ib(e){if(e instanceof En)return new En(e.h,e.s,e.l,e.opacity);if(e instanceof ja||(e=$n(e)),!e)return new En;if(e instanceof En)return e;e=e.rgb();var t=e.r/255,r=e.g/255,n=e.b/255,o=Math.min(t,r,n),i=Math.max(t,r,n),s=NaN,a=i-o,l=(i+o)/2;return a?(t===i?s=(r-n)/a+(r0&&l<1?0:s,new En(s,a,l,e.opacity)}function wb(e,t,r,n){return arguments.length===1?Ib(e):new En(e,t,r,n??1)}function En(e,t,r,n){this.h=+e,this.s=+t,this.l=+r,this.opacity=+n}function yb(e){return e=(e||0)%360,e<0?e+360:e}function Wc(e){return Math.max(0,Math.min(1,e||0))}function Zf(e,t,r){return(e<60?t+(r-t)*e/60:e<180?r:e<240?t+(r-t)*(240-e)/60:t)*255}var Pa,Tc,Es,Ja,Wn,jE,KE,qE,e1,t1,r1,n1,pb,Cb=v(()=>{gb();Pa=.7,Tc=1/Pa,Es="\\s*([+-]?\\d+)\\s*",Ja="\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)\\s*",Wn="\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)%\\s*",jE=/^#([0-9a-f]{3,8})$/,KE=new RegExp(`^rgb\\(${Es},${Es},${Es}\\)$`),qE=new RegExp(`^rgb\\(${Wn},${Wn},${Wn}\\)$`),e1=new RegExp(`^rgba\\(${Es},${Es},${Es},${Ja}\\)$`),t1=new RegExp(`^rgba\\(${Wn},${Wn},${Wn},${Ja}\\)$`),r1=new RegExp(`^hsl\\(${Ja},${Wn},${Wn}\\)$`),n1=new RegExp(`^hsla\\(${Ja},${Wn},${Wn},${Ja}\\)$`),pb={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};Lc(ja,$n,{copy(e){return Object.assign(new this.constructor,this,e)},displayable(){return this.rgb().displayable()},hex:hb,formatHex:hb,formatHex8:o1,formatHsl:i1,formatRgb:mb,toString:mb});Lc(Ar,$s,Sf(ja,{brighter(e){return e=e==null?Tc:Math.pow(Tc,e),new Ar(this.r*e,this.g*e,this.b*e,this.opacity)},darker(e){return e=e==null?Pa:Math.pow(Pa,e),new Ar(this.r*e,this.g*e,this.b*e,this.opacity)},rgb(){return this},clamp(){return new Ar(wi(this.r),wi(this.g),wi(this.b),Dc(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:_b,formatHex:_b,formatHex8:a1,formatRgb:bb,toString:bb}));Lc(En,wb,Sf(ja,{brighter(e){return e=e==null?Tc:Math.pow(Tc,e),new En(this.h,this.s,this.l*e,this.opacity)},darker(e){return e=e==null?Pa:Math.pow(Pa,e),new En(this.h,this.s,this.l*e,this.opacity)},rgb(){var e=this.h%360+(this.h<0)*360,t=isNaN(e)||isNaN(this.s)?0:this.s,r=this.l,n=r+(r<.5?r:1-r)*t,o=2*r-n;return new Ar(Zf(e>=240?e-240:e+120,o,n),Zf(e,o,n),Zf(e<120?e+240:e-120,o,n),this.opacity)},clamp(){return new En(yb(this.h),Wc(this.s),Wc(this.l),Dc(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(){let e=Dc(this.opacity);return`${e===1?"hsl(":"hsla("}${yb(this.h)}, ${Wc(this.s)*100}%, ${Wc(this.l)*100}%${e===1?")":`, ${e})`}`}}))});var Oc=v(()=>{Cb()});function kf(e,t,r,n,o){var i=e*e,s=i*e;return((1-3*e+3*i-s)*t+(4-6*i+3*s)*r+(1+3*e+3*i-3*s)*n+s*o)/6}function Bb(e){var t=e.length-1;return function(r){var n=r<=0?r=0:r>=1?(r=1,t-1):Math.floor(r*t),o=e[n],i=e[n+1],s=n>0?e[n-1]:2*o-i,a=n{});function Eb(e){var t=e.length;return function(r){var n=Math.floor(((r%=1)<0?++r:r)*t),o=e[(n+t-1)%t],i=e[n%t],s=e[(n+1)%t],a=e[(n+2)%t];return kf((r-n/t)*t,o,i,s,a)}}var $b=v(()=>{Nf()});var Ka,Qf=v(()=>{Ka=e=>()=>e});function l1(e,t){return function(r){return e+r*t}}function c1(e,t,r){return e=Math.pow(e,r),t=Math.pow(t,r)-e,r=1/r,function(n){return Math.pow(e+n*t,r)}}function Ab(e){return(e=+e)==1?Hc:function(t,r){return r-t?c1(t,r,e):Ka(isNaN(t)?r:t)}}function Hc(e,t){var r=t-e;return r?l1(e,r):Ka(isNaN(e)?t:e)}var Gb=v(()=>{Qf()});function Fb(e){return function(t){var r=t.length,n=new Array(r),o=new Array(r),i=new Array(r),s,a;for(s=0;s{Oc();Nf();$b();Gb();Ci=(function e(t){var r=Ab(t);function n(o,i){var s=r((o=$s(o)).r,(i=$s(i)).r),a=r(o.g,i.g),l=r(o.b,i.b),u=Hc(o.opacity,i.opacity);return function(f){return o.r=s(f),o.g=a(f),o.b=l(f),o.opacity=u(f),o+""}}return n.gamma=e,n})(1);d1=Fb(Bb),u1=Fb(Eb)});function Sb(e,t){t||(t=[]);var r=e?Math.min(t.length,e.length):0,n=t.slice(),o;return function(i){for(o=0;o{});function Nb(e,t){var r=t?t.length:0,n=e?Math.min(r,e.length):0,o=new Array(n),i=new Array(r),s;for(s=0;s{Mc()});function Xb(e,t){var r=new Date;return e=+e,t=+t,function(n){return r.setTime(e*(1-n)+t*n),r}}var Rb=v(()=>{});function _r(e,t){return e=+e,t=+t,function(r){return e*(1-r)+t*r}}var qa=v(()=>{});function Ub(e,t){var r={},n={},o;(e===null||typeof e!="object")&&(e={}),(t===null||typeof t!="object")&&(t={});for(o in t)o in e?r[o]=co(e[o],t[o]):n[o]=t[o];return function(i){for(o in r)n[o]=r[o](i);return n}}var Lb=v(()=>{Mc()});function f1(e){return function(){return e}}function g1(e){return function(t){return e(t)+""}}function el(e,t){var r=Uf.lastIndex=Rf.lastIndex=0,n,o,i,s=-1,a=[],l=[];for(e=e+"",t=t+"";(n=Uf.exec(e))&&(o=Rf.exec(t));)(i=o.index)>r&&(i=t.slice(r,i),a[s]?a[s]+=i:a[++s]=i),(n=n[0])===(o=o[0])?a[s]?a[s]+=o:a[++s]=o:(a[++s]=null,l.push({i:s,x:_r(n,o)})),r=Rf.lastIndex;return r{qa();Uf=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,Rf=new RegExp(Uf.source,"g")});function co(e,t){var r=typeof t,n;return t==null||r==="boolean"?Ka(t):(r==="number"?_r:r==="string"?(n=$n(t))?(t=n,Ci):el:t instanceof $n?Ci:t instanceof Date?Xb:Zb(t)?Sb:Array.isArray(t)?Nb:typeof t.valueOf!="function"&&typeof t.toString!="function"||isNaN(t)?Ub:_r)(e,t)}var Mc=v(()=>{Oc();Xf();Qb();Rb();qa();Lb();Lf();Qf();kb()});function Vf(e,t,r,n,o,i){var s,a,l;return(s=Math.sqrt(e*e+t*t))&&(e/=s,t/=s),(l=e*r+t*n)&&(r-=e*l,n-=t*l),(a=Math.sqrt(r*r+n*n))&&(r/=a,n/=a,l/=a),e*n{Vb=180/Math.PI,Yc={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1}});function Tb(e){let t=new(typeof DOMMatrix=="function"?DOMMatrix:WebKitCSSMatrix)(e+"");return t.isIdentity?Yc:Vf(t.a,t.b,t.c,t.d,t.e,t.f)}function Db(e){return e==null?Yc:(zc||(zc=document.createElementNS("http://www.w3.org/2000/svg","g")),zc.setAttribute("transform",e),(e=zc.transform.baseVal.consolidate())?(e=e.matrix,Vf(e.a,e.b,e.c,e.d,e.e,e.f)):Yc)}var zc,Ob=v(()=>{Wb()});function Hb(e,t,r,n){function o(u){return u.length?u.pop()+" ":""}function i(u,f,g,d,p,h){if(u!==g||f!==d){var b=p.push("translate(",null,t,null,r);h.push({i:b-4,x:_r(u,g)},{i:b-2,x:_r(f,d)})}else(g||d)&&p.push("translate("+g+t+d+r)}function s(u,f,g,d){u!==f?(u-f>180?f+=360:f-u>180&&(u+=360),d.push({i:g.push(o(g)+"rotate(",null,n)-2,x:_r(u,f)})):f&&g.push(o(g)+"rotate("+f+n)}function a(u,f,g,d){u!==f?d.push({i:g.push(o(g)+"skewX(",null,n)-2,x:_r(u,f)}):f&&g.push(o(g)+"skewX("+f+n)}function l(u,f,g,d,p,h){if(u!==g||f!==d){var b=p.push(o(p)+"scale(",null,",",null,")");h.push({i:b-4,x:_r(u,g)},{i:b-2,x:_r(f,d)})}else(g!==1||d!==1)&&p.push(o(p)+"scale("+g+","+d+")")}return function(u,f){var g=[],d=[];return u=e(u),f=e(f),i(u.translateX,u.translateY,f.translateX,f.translateY,g,d),s(u.rotate,f.rotate,g,d),a(u.skewX,f.skewX,g,d),l(u.scaleX,u.scaleY,f.scaleX,f.scaleY,g,d),u=f=null,function(p){for(var h=-1,b=d.length,x;++h{qa();Ob();Wf=Hb(Tb,"px, ","px)","deg)"),Tf=Hb(Db,", ",")",")")});function Yb(e){return((e=Math.exp(e))+1/e)/2}function h1(e){return((e=Math.exp(e))-1/e)/2}function m1(e){return((e=Math.exp(2*e))-1)/(e+1)}var p1,Bi,zb=v(()=>{p1=1e-12;Bi=(function e(t,r,n){function o(i,s){var a=i[0],l=i[1],u=i[2],f=s[0],g=s[1],d=s[2],p=f-a,h=g-l,b=p*p+h*h,x,w;if(b{Mc();qa();Lf();Mb();zb();Xf()});function sl(){return Ei||(jb(v1),Ei=ol.now()+jc)}function v1(){Ei=0}function il(){this._call=this._time=this._next=null}function Kc(e,t,r){var n=new il;return n.restart(e,t,r),n}function Kb(){sl(),++Gs;for(var e=Pc,t;e;)(t=Ei-e._time)>=0&&e._call.call(void 0,t),e=e._next;--Gs}function Pb(){Ei=(Jc=ol.now())+jc,Gs=rl=0;try{Kb()}finally{Gs=0,b1(),Ei=0}}function _1(){var e=ol.now(),t=e-Jc;t>Jb&&(jc-=t,Jc=e)}function b1(){for(var e,t=Pc,r,n=1/0;t;)t._call?(n>t._time&&(n=t._time),e=t,t=t._next):(r=t._next,t._next=null,t=e?e._next=r:Pc=r);nl=e,Df(n)}function Df(e){if(!Gs){rl&&(rl=clearTimeout(rl));var t=e-Ei;t>24?(e<1/0&&(rl=setTimeout(Pb,e-ol.now()-jc)),tl&&(tl=clearInterval(tl))):(tl||(Jc=ol.now(),tl=setInterval(_1,Jb)),Gs=1,jb(Pb))}}var Gs,rl,tl,Jb,Pc,nl,Jc,Ei,jc,ol,jb,Of=v(()=>{Gs=0,rl=0,tl=0,Jb=1e3,Jc=0,Ei=0,jc=0,ol=typeof performance=="object"&&performance.now?performance:Date,jb=typeof window=="object"&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):function(e){setTimeout(e,17)};il.prototype=Kc.prototype={constructor:il,restart:function(e,t,r){if(typeof e!="function")throw new TypeError("callback is not a function");r=(r==null?sl():+r)+(t==null?0:+t),!this._next&&nl!==this&&(nl?nl._next=this:Pc=this,nl=this),this._call=e,this._time=r,Df()},stop:function(){this._call&&(this._call=null,this._time=1/0,Df())}}});function qc(e,t,r){var n=new il;return t=t==null?0:+t,n.restart(o=>{n.stop(),e(o+t)},t,r),n}var qb=v(()=>{Of()});var Hf=v(()=>{Of();qb()});function Ro(e,t,r,n,o,i){var s=e.__transition;if(!s)e.__transition={};else if(r in s)return;I1(e,r,{name:t,index:n,group:o,on:x1,tween:y1,time:i.time,delay:i.delay,duration:i.duration,ease:i.ease,timer:null,state:rx})}function ll(e,t){var r=kt(e,t);if(r.state>rx)throw new Error("too late; already scheduled");return r}function qt(e,t){var r=kt(e,t);if(r.state>ed)throw new Error("too late; already running");return r}function kt(e,t){var r=e.__transition;if(!r||!(r=r[t]))throw new Error("transition not found");return r}function I1(e,t,r){var n=e.__transition,o;n[t]=r,r.timer=Kc(i,0,r.time);function i(u){r.state=ex,r.timer.restart(s,r.delay,r.time),r.delay<=u&&s(u-r.delay)}function s(u){var f,g,d,p;if(r.state!==ex)return l();for(f in n)if(p=n[f],p.name===r.name){if(p.state===ed)return qc(s);p.state===tx?(p.state=al,p.timer.stop(),p.on.call("interrupt",e,e.__data__,p.index,p.group),delete n[f]):+f{Fc();Hf();x1=bi("start","end","cancel","interrupt"),y1=[],rx=0,ex=1,td=2,ed=3,tx=4,rd=5,al=6});function $i(e,t){var r=e.__transition,n,o,i=!0,s;if(r){t=t==null?null:t+"";for(s in r){if((n=r[s]).name!==t){i=!1;continue}o=n.state>td&&n.state{Gr()});function nx(e){return this.each(function(){$i(this,e)})}var ox=v(()=>{Mf()});function w1(e,t){var r,n;return function(){var o=qt(this,e),i=o.tween;if(i!==r){n=r=i;for(var s=0,a=n.length;s{Gr()});function nd(e,t){var r;return(typeof t=="number"?_r:t instanceof $n?Ci:(r=$n(t))?(t=r,Ci):el)(e,t)}var Yf=v(()=>{Oc();As()});function B1(e){return function(){this.removeAttribute(e)}}function E1(e){return function(){this.removeAttributeNS(e.space,e.local)}}function $1(e,t,r){var n,o=r+"",i;return function(){var s=this.getAttribute(e);return s===o?null:s===n?i:i=t(n=s,r)}}function A1(e,t,r){var n,o=r+"",i;return function(){var s=this.getAttributeNS(e.space,e.local);return s===o?null:s===n?i:i=t(n=s,r)}}function G1(e,t,r){var n,o,i;return function(){var s,a=r(this),l;return a==null?void this.removeAttribute(e):(s=this.getAttribute(e),l=a+"",s===l?null:s===n&&l===o?i:(o=l,i=t(n=s,a)))}}function F1(e,t,r){var n,o,i;return function(){var s,a=r(this),l;return a==null?void this.removeAttributeNS(e.space,e.local):(s=this.getAttributeNS(e.space,e.local),l=a+"",s===l?null:s===n&&l===o?i:(o=l,i=t(n=s,a)))}}function sx(e,t){var r=ao(e),n=r==="transform"?Tf:nd;return this.attrTween(e,typeof t=="function"?(r.local?F1:G1)(r,n,Fs(this,"attr."+e,t)):t==null?(r.local?E1:B1)(r):(r.local?A1:$1)(r,n,t))}var ax=v(()=>{As();$r();cl();Yf()});function S1(e,t){return function(r){this.setAttribute(e,t.call(this,r))}}function Z1(e,t){return function(r){this.setAttributeNS(e.space,e.local,t.call(this,r))}}function k1(e,t){var r,n;function o(){var i=t.apply(this,arguments);return i!==n&&(r=(n=i)&&Z1(e,i)),r}return o._value=t,o}function N1(e,t){var r,n;function o(){var i=t.apply(this,arguments);return i!==n&&(r=(n=i)&&S1(e,i)),r}return o._value=t,o}function lx(e,t){var r="attr."+e;if(arguments.length<2)return(r=this.tween(r))&&r._value;if(t==null)return this.tween(r,null);if(typeof t!="function")throw new Error;var n=ao(e);return this.tween(r,(n.local?k1:N1)(n,t))}var cx=v(()=>{$r()});function Q1(e,t){return function(){ll(this,e).delay=+t.apply(this,arguments)}}function X1(e,t){return t=+t,function(){ll(this,e).delay=t}}function dx(e){var t=this._id;return arguments.length?this.each((typeof e=="function"?Q1:X1)(t,e)):kt(this.node(),t).delay}var ux=v(()=>{Gr()});function R1(e,t){return function(){qt(this,e).duration=+t.apply(this,arguments)}}function U1(e,t){return t=+t,function(){qt(this,e).duration=t}}function fx(e){var t=this._id;return arguments.length?this.each((typeof e=="function"?R1:U1)(t,e)):kt(this.node(),t).duration}var gx=v(()=>{Gr()});function L1(e,t){if(typeof t!="function")throw new Error;return function(){qt(this,e).ease=t}}function px(e){var t=this._id;return arguments.length?this.each(L1(t,e)):kt(this.node(),t).ease}var hx=v(()=>{Gr()});function V1(e,t){return function(){var r=t.apply(this,arguments);if(typeof r!="function")throw new Error;qt(this,e).ease=r}}function mx(e){if(typeof e!="function")throw new Error;return this.each(V1(this._id,e))}var vx=v(()=>{Gr()});function _x(e){typeof e!="function"&&(e=Ta(e));for(var t=this._groups,r=t.length,n=new Array(r),o=0;o{$r();Ai()});function xx(e){if(e._id!==this._id)throw new Error;for(var t=this._groups,r=e._groups,n=t.length,o=r.length,i=Math.min(n,o),s=new Array(n),a=0;a{Ai()});function W1(e){return(e+"").trim().split(/^|\s+/).every(function(t){var r=t.indexOf(".");return r>=0&&(t=t.slice(0,r)),!t||t==="start"})}function T1(e,t,r){var n,o,i=W1(t)?ll:qt;return function(){var s=i(this,e),a=s.on;a!==n&&(o=(n=a).copy()).on(t,r),s.on=o}}function Ix(e,t){var r=this._id;return arguments.length<2?kt(this.node(),r).on.on(e):this.each(T1(r,e,t))}var wx=v(()=>{Gr()});function D1(e){return function(){var t=this.parentNode;for(var r in this.__transition)if(+r!==e)return;t&&t.removeChild(this)}}function Cx(){return this.on("end.remove",D1(this._id))}var Bx=v(()=>{});function Ex(e){var t=this._name,r=this._id;typeof e!="function"&&(e=xi(e));for(var n=this._groups,o=n.length,i=new Array(o),s=0;s{$r();Ai();Gr()});function Ax(e){var t=this._name,r=this._id;typeof e!="function"&&(e=Wa(e));for(var n=this._groups,o=n.length,i=[],s=[],a=0;a{$r();Ai();Gr()});function Fx(){return new O1(this._groups,this._parents)}var O1,Sx=v(()=>{$r();O1=lo.prototype.constructor});function H1(e,t){var r,n,o;return function(){var i=Qo(this,e),s=(this.style.removeProperty(e),Qo(this,e));return i===s?null:i===r&&s===n?o:o=t(r=i,n=s)}}function Zx(e){return function(){this.style.removeProperty(e)}}function M1(e,t,r){var n,o=r+"",i;return function(){var s=Qo(this,e);return s===o?null:s===n?i:i=t(n=s,r)}}function Y1(e,t,r){var n,o,i;return function(){var s=Qo(this,e),a=r(this),l=a+"";return a==null&&(l=a=(this.style.removeProperty(e),Qo(this,e))),s===l?null:s===n&&l===o?i:(o=l,i=t(n=s,a))}}function z1(e,t){var r,n,o,i="style."+t,s="end."+i,a;return function(){var l=qt(this,e),u=l.on,f=l.value[i]==null?a||(a=Zx(t)):void 0;(u!==r||o!==f)&&(n=(r=u).copy()).on(s,o=f),l.on=n}}function kx(e,t,r){var n=(e+="")=="transform"?Wf:nd;return t==null?this.styleTween(e,H1(e,n)).on("end.style."+e,Zx(e)):typeof t=="function"?this.styleTween(e,Y1(e,n,Fs(this,"style."+e,t))).each(z1(this._id,e)):this.styleTween(e,M1(e,n,t),r).on("end.style."+e,null)}var Nx=v(()=>{As();$r();Gr();cl();Yf()});function P1(e,t,r){return function(n){this.style.setProperty(e,t.call(this,n),r)}}function J1(e,t,r){var n,o;function i(){var s=t.apply(this,arguments);return s!==o&&(n=(o=s)&&P1(e,s,r)),n}return i._value=t,i}function Qx(e,t,r){var n="style."+(e+="");if(arguments.length<2)return(n=this.tween(n))&&n._value;if(t==null)return this.tween(n,null);if(typeof t!="function")throw new Error;return this.tween(n,J1(e,t,r??""))}var Xx=v(()=>{});function j1(e){return function(){this.textContent=e}}function K1(e){return function(){var t=e(this);this.textContent=t??""}}function Rx(e){return this.tween("text",typeof e=="function"?K1(Fs(this,"text",e)):j1(e==null?"":e+""))}var Ux=v(()=>{cl()});function q1(e){return function(t){this.textContent=e.call(this,t)}}function e$(e){var t,r;function n(){var o=e.apply(this,arguments);return o!==r&&(t=(r=o)&&q1(o)),t}return n._value=e,n}function Lx(e){var t="text";if(arguments.length<1)return(t=this.tween(t))&&t._value;if(e==null)return this.tween(t,null);if(typeof e!="function")throw new Error;return this.tween(t,e$(e))}var Vx=v(()=>{});function Wx(){for(var e=this._name,t=this._id,r=od(),n=this._groups,o=n.length,i=0;i{Ai();Gr()});function Dx(){var e,t,r=this,n=r._id,o=r.size();return new Promise(function(i,s){var a={value:s},l={value:function(){--o===0&&i()}};r.each(function(){var u=qt(this,n),f=u.on;f!==e&&(t=(e=f).copy(),t._.cancel.push(a),t._.interrupt.push(a),t._.end.push(l)),u.on=t}),o===0&&i()})}var Ox=v(()=>{Gr()});function br(e,t,r,n){this._groups=e,this._parents=t,this._name=r,this._id=n}function Hx(e){return lo().transition(e)}function od(){return++t$}var t$,uo,Ai=v(()=>{$r();ax();cx();ux();gx();hx();vx();bx();yx();wx();Bx();$x();Gx();Sx();Nx();Xx();Ux();Vx();Tx();cl();Ox();t$=0;uo=lo.prototype;br.prototype=Hx.prototype={constructor:br,select:Ex,selectAll:Ax,selectChild:uo.selectChild,selectChildren:uo.selectChildren,filter:_x,merge:xx,selection:Fx,transition:Wx,call:uo.call,nodes:uo.nodes,node:uo.node,size:uo.size,empty:uo.empty,each:uo.each,on:Ix,attr:sx,attrTween:lx,style:kx,styleTween:Qx,text:Rx,textTween:Lx,remove:Cx,tween:ix,delay:dx,duration:fx,ease:px,easeVarying:mx,end:Dx,[Symbol.iterator]:uo[Symbol.iterator]}});function id(e){return((e*=2)<=1?e*e*e:(e-=2)*e*e+2)/2}var Mx=v(()=>{});var Yx=v(()=>{Mx()});function n$(e,t){for(var r;!(r=e.__transition)||!(r=r[t]);)if(!(e=e.parentNode))throw new Error(`transition ${t} not found`);return r}function zx(e){var t,r;e instanceof br?(t=e._id,e=e._name):(t=od(),(r=r$).time=sl(),e=e==null?null:e+"");for(var n=this._groups,o=n.length,i=0;i{Ai();Gr();Yx();Hf();r$={time:null,delay:0,duration:250,ease:id}});var Jx=v(()=>{$r();ox();Px();lo.prototype.interrupt=nx;lo.prototype.transition=zx});var jx=v(()=>{Jx();Mf()});var dl,Kx=v(()=>{dl=e=>()=>e});function zf(e,{sourceEvent:t,target:r,transform:n,dispatch:o}){Object.defineProperties(this,{type:{value:e,enumerable:!0,configurable:!0},sourceEvent:{value:t,enumerable:!0,configurable:!0},target:{value:r,enumerable:!0,configurable:!0},transform:{value:n,enumerable:!0,configurable:!0},_:{value:o}})}var qx=v(()=>{});function An(e,t,r){this.k=e,this.x=t,this.y=r}function ul(e){for(;!e.__zoom;)if(!(e=e.parentNode))return Gi;return e.__zoom}var Gi,Pf=v(()=>{An.prototype={constructor:An,scale:function(e){return e===1?this:new An(this.k*e,this.x,this.y)},translate:function(e,t){return e===0&t===0?this:new An(this.k,this.x+this.k*e,this.y+this.k*t)},apply:function(e){return[e[0]*this.k+this.x,e[1]*this.k+this.y]},applyX:function(e){return e*this.k+this.x},applyY:function(e){return e*this.k+this.y},invert:function(e){return[(e[0]-this.x)/this.k,(e[1]-this.y)/this.k]},invertX:function(e){return(e-this.x)/this.k},invertY:function(e){return(e-this.y)/this.k},rescaleX:function(e){return e.copy().domain(e.range().map(this.invertX,this).map(e.invert,e))},rescaleY:function(e){return e.copy().domain(e.range().map(this.invertY,this).map(e.invert,e))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};Gi=new An(1,0,0);ul.prototype=An.prototype});function sd(e){e.stopImmediatePropagation()}function Ss(e){e.preventDefault(),e.stopImmediatePropagation()}var e0=v(()=>{});function o$(e){return(!e.ctrlKey||e.type==="wheel")&&!e.button}function i$(){var e=this;return e instanceof SVGElement?(e=e.ownerSVGElement||e,e.hasAttribute("viewBox")?(e=e.viewBox.baseVal,[[e.x,e.y],[e.x+e.width,e.y+e.height]]):[[0,0],[e.width.baseVal.value,e.height.baseVal.value]]):[[0,0],[e.clientWidth,e.clientHeight]]}function t0(){return this.__zoom||Gi}function s$(e){return-e.deltaY*(e.deltaMode===1?.05:e.deltaMode?1:.002)*(e.ctrlKey?10:1)}function a$(){return navigator.maxTouchPoints||"ontouchstart"in this}function l$(e,t,r){var n=e.invertX(t[0][0])-r[0][0],o=e.invertX(t[1][0])-r[1][0],i=e.invertY(t[0][1])-r[0][1],s=e.invertY(t[1][1])-r[1][1];return e.translate(o>n?(n+o)/2:Math.min(0,n)||Math.max(0,o),s>i?(i+s)/2:Math.min(0,i)||Math.max(0,s))}function ad(){var e=o$,t=i$,r=l$,n=s$,o=a$,i=[0,1/0],s=[[-1/0,-1/0],[1/0,1/0]],a=250,l=Bi,u=bi("start","zoom","end"),f,g,d,p=500,h=150,b=0,x=10;function w(I){I.property("__zoom",t0).on("wheel.zoom",G,{passive:!1}).on("mousedown.zoom",W).on("dblclick.zoom",H).filter(o).on("touchstart.zoom",Z).on("touchmove.zoom",$).on("touchend.zoom touchcancel.zoom",X).style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}w.transform=function(I,A,S,T){var K=I.selection?I.selection():I;K.property("__zoom",t0),I!==K?U(I,A,S,T):K.interrupt().each(function(){B(this,arguments).event(T).start().zoom(null,typeof A=="function"?A.apply(this,arguments):A).end()})},w.scaleBy=function(I,A,S,T){w.scaleTo(I,function(){var K=this.__zoom.k,Y=typeof A=="function"?A.apply(this,arguments):A;return K*Y},S,T)},w.scaleTo=function(I,A,S,T){w.transform(I,function(){var K=t.apply(this,arguments),Y=this.__zoom,z=S==null?y(K):typeof S=="function"?S.apply(this,arguments):S,j=Y.invert(z),re=typeof A=="function"?A.apply(this,arguments):A;return r(E(C(Y,re),z,j),K,s)},S,T)},w.translateBy=function(I,A,S,T){w.transform(I,function(){return r(this.__zoom.translate(typeof A=="function"?A.apply(this,arguments):A,typeof S=="function"?S.apply(this,arguments):S),t.apply(this,arguments),s)},null,T)},w.translateTo=function(I,A,S,T,K){w.transform(I,function(){var Y=t.apply(this,arguments),z=this.__zoom,j=T==null?y(Y):typeof T=="function"?T.apply(this,arguments):T;return r(Gi.translate(j[0],j[1]).scale(z.k).translate(typeof A=="function"?-A.apply(this,arguments):-A,typeof S=="function"?-S.apply(this,arguments):-S),Y,s)},T,K)};function C(I,A){return A=Math.max(i[0],Math.min(i[1],A)),A===I.k?I:new An(A,I.x,I.y)}function E(I,A,S){var T=A[0]-S[0]*I.k,K=A[1]-S[1]*I.k;return T===I.x&&K===I.y?I:new An(I.k,T,K)}function y(I){return[(+I[0][0]+ +I[1][0])/2,(+I[0][1]+ +I[1][1])/2]}function U(I,A,S,T){I.on("start.zoom",function(){B(this,arguments).event(T).start()}).on("interrupt.zoom end.zoom",function(){B(this,arguments).event(T).end()}).tween("zoom",function(){var K=this,Y=arguments,z=B(K,Y).event(T),j=t.apply(K,Y),re=S==null?y(j):typeof S=="function"?S.apply(K,Y):S,ae=Math.max(j[1][0]-j[0][0],j[1][1]-j[0][1]),ne=K.__zoom,Ie=typeof A=="function"?A.apply(K,Y):A,fe=l(ne.invert(re).concat(ae/ne.k),Ie.invert(re).concat(ae/Ie.k));return function(ge){if(ge===1)ge=Ie;else{var pe=fe(ge),we=ae/pe[2];ge=new An(we,re[0]-pe[0]*we,re[1]-pe[1]*we)}z.zoom(null,ge)}})}function B(I,A,S){return!S&&I.__zooming||new k(I,A)}function k(I,A){this.that=I,this.args=A,this.active=0,this.sourceEvent=null,this.extent=t.apply(I,A),this.taps=0}k.prototype={event:function(I){return I&&(this.sourceEvent=I),this},start:function(){return++this.active===1&&(this.that.__zooming=this,this.emit("start")),this},zoom:function(I,A){return this.mouse&&I!=="mouse"&&(this.mouse[1]=A.invert(this.mouse[0])),this.touch0&&I!=="touch"&&(this.touch0[1]=A.invert(this.touch0[0])),this.touch1&&I!=="touch"&&(this.touch1[1]=A.invert(this.touch1[0])),this.that.__zoom=A,this.emit("zoom"),this},end:function(){return--this.active===0&&(delete this.that.__zooming,this.emit("end")),this},emit:function(I){var A=Kt(this.that).datum();u.call(I,this.that,new zf(I,{sourceEvent:this.sourceEvent,target:w,type:I,transform:this.that.__zoom,dispatch:u}),A)}};function G(I,...A){if(!e.apply(this,arguments))return;var S=B(this,A).event(I),T=this.__zoom,K=Math.max(i[0],Math.min(i[1],T.k*Math.pow(2,n.apply(this,arguments)))),Y=vr(I);if(S.wheel)(S.mouse[0][0]!==Y[0]||S.mouse[0][1]!==Y[1])&&(S.mouse[1]=T.invert(S.mouse[0]=Y)),clearTimeout(S.wheel);else{if(T.k===K)return;S.mouse=[Y,T.invert(Y)],$i(this),S.start()}Ss(I),S.wheel=setTimeout(z,h),S.zoom("mouse",r(E(C(T,K),S.mouse[0],S.mouse[1]),S.extent,s));function z(){S.wheel=null,S.end()}}function W(I,...A){if(d||!e.apply(this,arguments))return;var S=I.currentTarget,T=B(this,A,!0).event(I),K=Kt(I.view).on("mousemove.zoom",re,!0).on("mouseup.zoom",ae,!0),Y=vr(I,S),z=I.clientX,j=I.clientY;Ha(I.view),sd(I),T.mouse=[Y,this.__zoom.invert(Y)],$i(this),T.start();function re(ne){if(Ss(ne),!T.moved){var Ie=ne.clientX-z,fe=ne.clientY-j;T.moved=Ie*Ie+fe*fe>b}T.event(ne).zoom("mouse",r(E(T.that.__zoom,T.mouse[0]=vr(ne,S),T.mouse[1]),T.extent,s))}function ae(ne){K.on("mousemove.zoom mouseup.zoom",null),Ma(ne.view,T.moved),Ss(ne),T.event(ne).end()}}function H(I,...A){if(e.apply(this,arguments)){var S=this.__zoom,T=vr(I.changedTouches?I.changedTouches[0]:I,this),K=S.invert(T),Y=S.k*(I.shiftKey?.5:2),z=r(E(C(S,Y),T,K),t.apply(this,A),s);Ss(I),a>0?Kt(this).transition().duration(a).call(U,z,T,I):Kt(this).call(w.transform,z,T,I)}}function Z(I,...A){if(e.apply(this,arguments)){var S=I.touches,T=S.length,K=B(this,A,I.changedTouches.length===T).event(I),Y,z,j,re;for(sd(I),z=0;z{Fc();Ff();As();$r();jx();Kx();qx();Pf();e0()});var n0=v(()=>{r0();Pf()});function m0(e,t){if(!e&&!t)return!0;if(!e||!t||e.size!==t.size)return!1;if(!e.size&&!t.size)return!0;for(let r of e.keys())if(!t.has(r))return!1;return!0}function tg(e,t,r){if(!r)return;let n=[];e.forEach((o,i)=>{t?.has(i)||n.push(o)}),n.length&&r(n)}function v0(e){return e===null?null:e?"valid":"invalid"}function u$(e,t){let r=new Map,n=t?.nodes?new Set(t.nodes.map(o=>o.id)):null;return e.forEach(o=>{o.measured.width&&o.measured.height&&(t?.includeHiddenNodes||!o.hidden)&&(!n||n.has(o.id))&&r.set(o.id,o)}),r}async function x0({nodes:e,width:t,height:r,panZoom:n,minZoom:o,maxZoom:i},s){if(e.size===0)return Promise.resolve(!0);let a=u$(e,s),l=Vo(a),u=ml(l,t,r,s?.minZoom??o,s?.maxZoom??i,s?.padding??.1);return await n.setViewport(u,{duration:s?.duration,ease:s?.ease,interpolate:s?.interpolate}),Promise.resolve(!0)}function og({nodeId:e,nextPosition:t,nodeLookup:r,nodeOrigin:n=[0,0],nodeExtent:o,onError:i}){let s=r.get(e),a=s.parentId?r.get(s.parentId):void 0,{x:l,y:u}=a?a.internals.positionAbsolute:{x:0,y:0},f=s.origin??n,g=s.extent||o;if(s.extent==="parent"&&!s.expandParent)if(!a)i?.("005",Si.error005());else{let p=a.measured.width,h=a.measured.height;p&&h&&(g=[[l,u],[l+p,u+h]])}else a&&Xs(s.extent)&&(g=[[s.extent[0][0]+l,s.extent[0][1]+u],[s.extent[1][0]+l,s.extent[1][1]+u]]);let d=Xs(g)?Zi(t,g,s.measured):t;return(s.measured.width===void 0||s.measured.height===void 0)&&i?.("015",Si.error015()),{position:{x:d.x-l+(s.measured.width??0)*f[0],y:d.y-u+(s.measured.height??0)*f[1]},positionAbsolute:d}}async function y0({nodesToRemove:e=[],edgesToRemove:t=[],nodes:r,edges:n,onBeforeDelete:o}){let i=new Set(e.map(d=>d.id)),s=[];for(let d of r){if(d.deletable===!1)continue;let p=i.has(d.id),h=!p&&d.parentId&&s.find(b=>b.id===d.parentId);(p||h)&&s.push(d)}let a=new Set(t.map(d=>d.id)),l=n.filter(d=>d.deletable!==!1),f=d$(s,l);for(let d of l)a.has(d.id)&&!f.find(h=>h.id===d.id)&&f.push(d);if(!o)return{edges:f,nodes:s};let g=await o({nodes:s,edges:f});return typeof g=="boolean"?g?{edges:f,nodes:s}:{edges:[],nodes:[]}:g}function I0(e,t,r){let{width:n,height:o}=fo(r),{x:i,y:s}=r.internals.positionAbsolute;return Zi(e,[[i,s],[i+n,s+o]],t)}function Zs(e,t){if(typeof e=="number")return Math.floor((t-t/(1+e))*.5);if(typeof e=="string"&&e.endsWith("px")){let r=parseFloat(e);if(!Number.isNaN(r))return Math.floor(r)}if(typeof e=="string"&&e.endsWith("%")){let r=parseFloat(e);if(!Number.isNaN(r))return Math.floor(t*r*.01)}return console.error(`[React Flow] The padding value "${e}" is invalid. Please provide a number or a string with a valid unit (px or %).`),0}function f$(e,t,r){if(typeof e=="string"||typeof e=="number"){let n=Zs(e,r),o=Zs(e,t);return{top:n,right:o,bottom:n,left:o,x:o*2,y:n*2}}if(typeof e=="object"){let n=Zs(e.top??e.y??0,r),o=Zs(e.bottom??e.y??0,r),i=Zs(e.left??e.x??0,t),s=Zs(e.right??e.x??0,t);return{top:n,right:s,bottom:o,left:i,x:i+s,y:n+o}}return{top:0,right:0,bottom:0,left:0,x:0,y:0}}function g$(e,t,r,n,o,i){let{x:s,y:a}=gl(e,[t,r,n]),{x:l,y:u}=gl({x:e.x+e.width,y:e.y+e.height},[t,r,n]),f=o-l,g=i-u;return{left:Math.floor(s),top:Math.floor(a),right:Math.floor(f),bottom:Math.floor(g)}}function Xs(e){return e!=null&&e!=="parent"}function fo(e){return{width:e.measured?.width??e.width??e.initialWidth??0,height:e.measured?.height??e.height??e.initialHeight??0}}function pd(e){return(e.measured?.width??e.width??e.initialWidth)!==void 0&&(e.measured?.height??e.height??e.initialHeight)!==void 0}function C0(e,t={width:0,height:0},r,n,o){let i={...e},s=n.get(r);if(s){let a=s.origin||o;i.x+=s.internals.positionAbsolute.x-(t.width??0)*a[0],i.y+=s.internals.positionAbsolute.y-(t.height??0)*a[1]}return i}function B0(e){return{...c$,...e||{}}}function Jf(e,{snapGrid:t=[0,0],snapToGrid:r=!1,transform:n,containerBounds:o}){let{x:i,y:s}=an(e),a=Ni({x:i-(o?.left??0),y:s-(o?.top??0)},n),{x:l,y:u}=r?Ls(a,t):a;return{xSnapped:l,ySnapped:u,...a}}function hd(e){let t=e.composedPath?.()?.[0]||e.target;return t?.nodeType!==1?!1:p$.includes(t.nodeName)||t.hasAttribute("contenteditable")||!!t.closest(".nokey")}function h$({sourceX:e,sourceY:t,targetX:r,targetY:n,sourceControlX:o,sourceControlY:i,targetControlX:s,targetControlY:a}){let l=e*.125+o*.375+s*.375+r*.125,u=t*.125+i*.375+a*.375+n*.125,f=Math.abs(l-e),g=Math.abs(u-t);return[l,u,f,g]}function ld(e,t){return e>=0?.5*e:t*25*Math.sqrt(-e)}function a0({pos:e,x1:t,y1:r,x2:n,y2:o,c:i}){switch(e){case $e.Left:return[t-ld(t-n,i),r];case $e.Right:return[t+ld(n-t,i),r];case $e.Top:return[t,r-ld(r-o,i)];case $e.Bottom:return[t,r+ld(o-r,i)]}}function md({sourceX:e,sourceY:t,sourcePosition:r=$e.Bottom,targetX:n,targetY:o,targetPosition:i=$e.Top,curvature:s=.25}){let[a,l]=a0({pos:r,x1:e,y1:t,x2:n,y2:o,c:s}),[u,f]=a0({pos:i,x1:n,y1:o,x2:e,y2:t,c:s}),[g,d,p,h]=h$({sourceX:e,sourceY:t,targetX:n,targetY:o,sourceControlX:a,sourceControlY:l,targetControlX:u,targetControlY:f});return[`M${e},${t} C${a},${l} ${u},${f} ${n},${o}`,g,d,p,h]}function $0({sourceX:e,sourceY:t,targetX:r,targetY:n}){let o=Math.abs(r-e)/2,i=r0}function vd({sourceX:e,sourceY:t,targetX:r,targetY:n}){let[o,i,s,a]=$0({sourceX:e,sourceY:t,targetX:r,targetY:n});return[`M ${e},${t}L ${r},${n}`,o,i,s,a]}function b$({source:e,sourcePosition:t=$e.Bottom,target:r,targetPosition:n=$e.Top,center:o,offset:i,stepPosition:s}){let a=l0[t],l=l0[n],u={x:e.x+a.x*i,y:e.y+a.y*i},f={x:r.x+l.x*i,y:r.y+l.y*i},g=_$({source:u,sourcePosition:t,target:f}),d=g.x!==0?"x":"y",p=g[d],h=[],b,x,w={x:0,y:0},C={x:0,y:0},[,,E,y]=$0({sourceX:e.x,sourceY:e.y,targetX:r.x,targetY:r.y});if(a[d]*l[d]===-1){d==="x"?(b=o.x??u.x+(f.x-u.x)*s,x=o.y??(u.y+f.y)/2):(b=o.x??(u.x+f.x)/2,x=o.y??u.y+(f.y-u.y)*s);let G=[{x:b,y:u.y},{x:b,y:f.y}],W=[{x:u.x,y:x},{x:f.x,y:x}];a[d]===p?h=d==="x"?G:W:h=d==="x"?W:G}else{let G=[{x:u.x,y:f.y}],W=[{x:f.x,y:u.y}];if(d==="x"?h=a.x===p?W:G:h=a.y===p?G:W,t===n){let I=Math.abs(e[d]-r[d]);if(I<=i){let A=Math.min(i-1,i-I);a[d]===p?w[d]=(u[d]>e[d]?-1:1)*A:C[d]=(f[d]>r[d]?-1:1)*A}}if(t!==n){let I=d==="x"?"y":"x",A=a[d]===l[I],S=u[I]>f[I],T=u[I]=X?(b=(H.x+Z.x)/2,x=h[0].y):(b=h[0].x,x=(H.y+Z.y)/2)}let U={x:u.x+w.x,y:u.y+w.y},B={x:f.x+C.x,y:f.y+C.y};return[[e,...U.x!==h[0].x||U.y!==h[0].y?[U]:[],...h,...B.x!==h[h.length-1].x||B.y!==h[h.length-1].y?[B]:[],r],b,x,E,y]}function x$(e,t,r,n){let o=Math.min(c0(e,t)/2,c0(t,r)/2,n),{x:i,y:s}=t;if(e.x===i&&i===r.x||e.y===s&&s===r.y)return`L${i} ${s}`;if(e.y===s){let u=e.xr.id===t):e[0])||null}function _d(e,t){return e?typeof e=="string"?e:`${t?`${t}__`:""}${Object.keys(e).sort().map(n=>`${n}=${e[n]}`).join("&")}`:""}function Z0(e,{id:t,defaultColor:r,defaultMarkerStart:n,defaultMarkerEnd:o}){let i=new Set;return e.reduce((s,a)=>([a.markerStart||n,a.markerEnd||o].forEach(l=>{if(l&&typeof l=="object"){let u=_d(l,t);i.has(u)||(s.push({id:u,color:l.color||r,...l}),i.add(u))}}),s),[]).sort((s,a)=>s.id.localeCompare(a.id))}function ug(e,t){let r={...e};for(let n in t)t[n]!==void 0&&(r[n]=t[n]);return r}function N0(e,t,r){let n=ug(dg,r);for(let o of e.values())if(o.parentId)gg(o,e,t,n);else{let i=hl(o,n.nodeOrigin),s=Xs(o.extent)?o.extent:n.nodeExtent,a=Zi(i,s,fo(o));o.internals.positionAbsolute=a}}function w$(e,t){if(!e.handles)return e.measured?t?.internals.handleBounds:void 0;let r=[],n=[];for(let o of e.handles){let i={id:o.id,width:o.width??1,height:o.height??1,nodeId:e.id,x:o.x,y:o.y,position:o.position,type:o.type};o.type==="source"?r.push(i):o.type==="target"&&n.push(i)}return{source:r,target:n}}function fg(e){return e==="manual"}function Q0(e,t,r,n={}){let o=ug(I$,n),i={i:0},s=new Map(t),a=o?.elevateNodesOnSelect&&!fg(o.zIndexMode)?k0:0,l=e.length>0,u=!1;t.clear(),r.clear();for(let f of e){let g=s.get(f.id);if(o.checkEquality&&f===g?.internals.userNode)t.set(f.id,g);else{let d=hl(f,o.nodeOrigin),p=Xs(f.extent)?f.extent:o.nodeExtent,h=Zi(d,p,fo(f));g={...o.defaults,...f,measured:{width:f.measured?.width,height:f.measured?.height},internals:{positionAbsolute:h,handleBounds:w$(f,g),z:X0(f,a,o.zIndexMode),userNode:f}},t.set(f.id,g)}(g.measured===void 0||g.measured.width===void 0||g.measured.height===void 0)&&!g.hidden&&(l=!1),f.parentId&&gg(g,t,r,n,i),u||(u=f.selected??!1)}return{nodesInitialized:l,hasSelectedNodes:u}}function C$(e,t){if(!e.parentId)return;let r=t.get(e.parentId);r?r.set(e.id,e):t.set(e.parentId,new Map([[e.id,e]]))}function gg(e,t,r,n,o){let{elevateNodesOnSelect:i,nodeOrigin:s,nodeExtent:a,zIndexMode:l}=ug(dg,n),u=e.parentId,f=t.get(u);if(!f){console.warn(`Parent node ${u} not found. Please make sure that parent nodes are in front of their child nodes in the nodes array.`);return}C$(e,r),o&&!f.parentId&&f.internals.rootParentIndex===void 0&&l==="auto"&&(f.internals.rootParentIndex=++o.i,f.internals.z=f.internals.z+o.i*y$),o&&f.internals.rootParentIndex!==void 0&&(o.i=f.internals.rootParentIndex);let g=i&&!fg(l)?k0:0,{x:d,y:p,z:h}=B$(e,f,s,a,g,l),{positionAbsolute:b}=e.internals,x=d!==b.x||p!==b.y;(x||h!==e.internals.z)&&t.set(e.id,{...e,internals:{...e.internals,positionAbsolute:x?{x:d,y:p}:b,z:h}})}function X0(e,t,r){let n=Tn(e.zIndex)?e.zIndex:0;return fg(r)?n:n+(e.selected?t:0)}function B$(e,t,r,n,o,i){let{x:s,y:a}=t.internals.positionAbsolute,l=fo(e),u=hl(e,r),f=Xs(e.extent)?Zi(u,e.extent,l):u,g=Zi({x:s+f.x,y:a+f.y},n,l);e.extent==="parent"&&(g=I0(g,l,t));let d=X0(e,o,i),p=t.internals.z??0;return{x:g.x,y:g.y,z:p>=d?p+1:d}}function E$(e,t,r,n=[0,0]){let o=[],i=new Map;for(let s of e){let a=t.get(s.parentId);if(!a)continue;let l=i.get(s.parentId)?.expandedRect??ki(a),u=ig(l,s.rect);i.set(s.parentId,{expandedRect:u,parent:a})}return i.size>0&&i.forEach(({expandedRect:s,parent:a},l)=>{let u=a.internals.positionAbsolute,f=fo(a),g=a.origin??n,d=s.x0||p>0||x||w)&&(o.push({id:l,type:"position",position:{x:a.position.x-d+x,y:a.position.y-p+w}}),r.get(l)?.forEach(C=>{e.some(E=>E.id===C.id)||o.push({id:C.id,type:"position",position:{x:C.position.x+d,y:C.position.y+p}})})),(f.width0){let p=E$(d,t,r,o);u.push(...p)}return{changes:u,updatedInternals:l}}async function U0({delta:e,panZoom:t,transform:r,translateExtent:n,width:o,height:i}){if(!t||!e.x&&!e.y)return Promise.resolve(!1);let s=await t.setViewportConstrained({x:r[0]+e.x,y:r[1]+e.y,zoom:r[2]},[[0,0],[o,i]],n),a=!!s&&(s.x!==r[0]||s.y!==r[1]||s.k!==r[2]);return Promise.resolve(a)}function g0(e,t,r,n,o,i){let s=o,a=n.get(s)||new Map;n.set(s,a.set(r,t)),s=`${o}-${e}`;let l=n.get(s)||new Map;if(n.set(s,l.set(r,t)),i){s=`${o}-${e}-${i}`;let u=n.get(s)||new Map;n.set(s,u.set(r,t))}}function L0(e,t,r){e.clear(),t.clear();for(let n of r){let{source:o,target:i,sourceHandle:s=null,targetHandle:a=null}=n,l={edgeId:n.id,source:o,target:i,sourceHandle:s,targetHandle:a},u=`${o}-${s}--${i}-${a}`,f=`${i}-${a}--${o}-${s}`;g0("source",l,f,e,o,s),g0("target",l,u,e,i,a),t.set(n.id,n)}}function V0(e,t){if(!e.parentId)return!1;let r=t.get(e.parentId);return r?r.selected?!0:V0(r,t):!1}function p0(e,t,r){let n=e;do{if(n?.matches?.(t))return!0;if(n===r)return!1;n=n?.parentElement}while(n);return!1}function $$(e,t,r,n){let o=new Map;for(let[i,s]of e)if((s.selected||s.id===n)&&(!s.parentId||!V0(s,e))&&(s.draggable||t&&typeof s.draggable>"u")){let a=e.get(i);a&&o.set(i,{id:i,position:a.position||{x:0,y:0},distance:{x:r.x-a.internals.positionAbsolute.x,y:r.y-a.internals.positionAbsolute.y},extent:a.extent,parentId:a.parentId,origin:a.origin,expandParent:a.expandParent,internals:{positionAbsolute:a.internals.positionAbsolute||{x:0,y:0}},measured:{width:a.measured.width??0,height:a.measured.height??0}})}return o}function jf({nodeId:e,dragItems:t,nodeLookup:r,dragging:n=!0}){let o=[];for(let[s,a]of t){let l=r.get(s)?.internals.userNode;l&&o.push({...l,position:a.position,dragging:n})}if(!e)return[o[0],o];let i=r.get(e)?.internals.userNode;return[i?{...i,position:t.get(e)?.position||i.position,dragging:n}:o[0],o]}function A$({dragItems:e,snapGrid:t,x:r,y:n}){let o=e.values().next().value;if(!o)return null;let i={x:r-o.distance.x,y:n-o.distance.y},s=Ls(i,t);return{x:s.x-i.x,y:s.y-i.y}}function W0({onNodeMouseDown:e,getStoreItems:t,onDragStart:r,onDrag:n,onDragStop:o}){let i={x:null,y:null},s=0,a=new Map,l=!1,u={x:0,y:0},f=null,g=!1,d=null,p=!1,h=!1,b=null;function x({noDragClassName:C,handleSelector:E,domNode:y,isSelectable:U,nodeId:B,nodeClickDistance:k=0}){d=Kt(y);function G({x:$,y:X}){let{nodeLookup:I,nodeExtent:A,snapGrid:S,snapToGrid:T,nodeOrigin:K,onNodeDrag:Y,onSelectionDrag:z,onError:j,updateNodePositions:re}=t();i={x:$,y:X};let ae=!1,ne=a.size>1,Ie=ne&&A?eg(Vo(a)):null,fe=ne&&T?A$({dragItems:a,snapGrid:S,x:$,y:X}):null;for(let[ge,pe]of a){if(!I.has(ge))continue;let we={x:$-pe.distance.x,y:X-pe.distance.y};T&&(we=fe?{x:Math.round(we.x+fe.x),y:Math.round(we.y+fe.y)}:Ls(we,S));let We=null;if(ne&&A&&!pe.extent&&Ie){let{positionAbsolute:Le}=pe.internals,vt=Le.x-Ie.x+A[0][0],Ot=Le.x+pe.measured.width-Ie.x2+A[1][0],ar=Le.y-Ie.y+A[0][1],yr=Le.y+pe.measured.height-Ie.y2+A[1][1];We=[[vt,ar],[Ot,yr]]}let{position:Ze,positionAbsolute:lt}=og({nodeId:ge,nextPosition:we,nodeLookup:I,nodeExtent:We||A,nodeOrigin:K,onError:j});ae=ae||pe.position.x!==Ze.x||pe.position.y!==Ze.y,pe.position=Ze,pe.internals.positionAbsolute=lt}if(h=h||ae,!!ae&&(re(a,!0),b&&(n||Y||!B&&z))){let[ge,pe]=jf({nodeId:B,dragItems:a,nodeLookup:I});n?.(b,a,ge,pe),Y?.(b,ge,pe),B||z?.(b,pe)}}async function W(){if(!f)return;let{transform:$,panBy:X,autoPanSpeed:I,autoPanOnNodeDrag:A}=t();if(!A){l=!1,cancelAnimationFrame(s);return}let[S,T]=w0(u,f,I);(S!==0||T!==0)&&(i.x=(i.x??0)-S/$[2],i.y=(i.y??0)-T/$[2],await X({x:S,y:T})&&G(i)),s=requestAnimationFrame(W)}function H($){let{nodeLookup:X,multiSelectionActive:I,nodesDraggable:A,transform:S,snapGrid:T,snapToGrid:K,selectNodesOnDrag:Y,onNodeDragStart:z,onSelectionDragStart:j,unselectNodesAndEdges:re}=t();g=!0,(!Y||!U)&&!I&&B&&(X.get(B)?.selected||re()),U&&Y&&B&&e?.(B);let ae=Jf($.sourceEvent,{transform:S,snapGrid:T,snapToGrid:K,containerBounds:f});if(i=ae,a=$$(X,A,ae,B),a.size>0&&(r||z||!B&&j)){let[ne,Ie]=jf({nodeId:B,dragItems:a,nodeLookup:X});r?.($.sourceEvent,a,ne,Ie),z?.($.sourceEvent,ne,Ie),B||j?.($.sourceEvent,Ie)}}let Z=Gf().clickDistance(k).on("start",$=>{let{domNode:X,nodeDragThreshold:I,transform:A,snapGrid:S,snapToGrid:T}=t();f=X?.getBoundingClientRect()||null,p=!1,h=!1,b=$.sourceEvent,I===0&&H($),i=Jf($.sourceEvent,{transform:A,snapGrid:S,snapToGrid:T,containerBounds:f}),u=an($.sourceEvent,f)}).on("drag",$=>{let{autoPanOnNodeDrag:X,transform:I,snapGrid:A,snapToGrid:S,nodeDragThreshold:T,nodeLookup:K}=t(),Y=Jf($.sourceEvent,{transform:I,snapGrid:A,snapToGrid:S,containerBounds:f});if(b=$.sourceEvent,($.sourceEvent.type==="touchmove"&&$.sourceEvent.touches.length>1||B&&!K.has(B))&&(p=!0),!p){if(!l&&X&&g&&(l=!0,W()),!g){let z=an($.sourceEvent,f),j=z.x-u.x,re=z.y-u.y;Math.sqrt(j*j+re*re)>T&&H($)}(i.x!==Y.xSnapped||i.y!==Y.ySnapped)&&a&&g&&(u=an($.sourceEvent,f),G(Y))}}).on("end",$=>{if(!(!g||p)&&(l=!1,g=!1,cancelAnimationFrame(s),a.size>0)){let{nodeLookup:X,updateNodePositions:I,onNodeDragStop:A,onSelectionDragStop:S}=t();if(h&&(I(a,!1),h=!1),o||A||!B&&S){let[T,K]=jf({nodeId:B,dragItems:a,nodeLookup:X,dragging:!1});o?.($.sourceEvent,a,T,K),A?.($.sourceEvent,T,K),B||S?.($.sourceEvent,K)}}}).filter($=>{let X=$.target;return!$.button&&(!C||!p0(X,`.${C}`,y))&&(!E||p0(X,E,y))});d.call(Z)}function w(){d?.on(".drag",null)}return{update:x,destroy:w}}function G$(e,t,r){let n=[],o={x:e.x-r,y:e.y-r,width:r*2,height:r*2};for(let i of t.values())Us(o,ki(i))>0&&n.push(i);return n}function S$(e,t,r,n){let o=[],i=1/0,s=G$(e,r,t+F$);for(let a of s){let l=[...a.internals.handleBounds?.source??[],...a.internals.handleBounds?.target??[]];for(let u of l){if(n.nodeId===u.nodeId&&n.type===u.type&&n.id===u.id)continue;let{x:f,y:g}=Lo(a,u,u.position,!0),d=Math.sqrt(Math.pow(f-e.x,2)+Math.pow(g-e.y,2));d>t||(d1){let a=n.type==="source"?"target":"source";return o.find(l=>l.type===a)??o[0]}return o[0]}function T0(e,t,r,n,o,i=!1){let s=n.get(e);if(!s)return null;let a=o==="strict"?s.internals.handleBounds?.[t]:[...s.internals.handleBounds?.source??[],...s.internals.handleBounds?.target??[]],l=(r?a?.find(u=>u.id===r):a?.[0])??null;return l&&i?{...l,...Lo(s,l,l.position,!0)}:l}function D0(e,t){return e||(t?.classList.contains("target")?"target":t?.classList.contains("source")?"source":null)}function Z$(e,t){let r=null;return t?r=!0:e&&!t&&(r=!1),r}function k$(e,{connectionMode:t,connectionRadius:r,handleId:n,nodeId:o,edgeUpdaterType:i,isTarget:s,domNode:a,nodeLookup:l,lib:u,autoPanOnConnect:f,flowId:g,panBy:d,cancelConnection:p,onConnectStart:h,onConnect:b,onConnectEnd:x,isValidConnection:w=O0,onReconnectEnd:C,updateConnection:E,getTransform:y,getFromHandle:U,autoPanSpeed:B,dragThreshold:k=1,handleDomNode:G}){let W=lg(e.target),H=0,Z,{x:$,y:X}=an(e),I=D0(i,G),A=a?.getBoundingClientRect(),S=!1;if(!A||!I)return;let T=T0(o,I,n,l,t);if(!T)return;let K=an(e,A),Y=!1,z=null,j=!1,re=null;function ae(){if(!f||!A)return;let[Ze,lt]=w0(K,A,B);d({x:Ze,y:lt}),H=requestAnimationFrame(ae)}let ne={...T,nodeId:o,type:I,position:T.position},Ie=l.get(o),ge={inProgress:!0,isValid:null,from:Lo(Ie,ne,$e.Left,!0),fromHandle:ne,fromPosition:ne.position,fromNode:Ie,to:K,toHandle:null,toPosition:o0[ne.position],toNode:null,pointer:K};function pe(){S=!0,E(ge),h?.(e,{nodeId:o,handleId:n,handleType:I})}k===0&&pe();function we(Ze){if(!S){let{x:yr,y:Qe}=an(Ze),nt=yr-$,er=Qe-X;if(!(nt*nt+er*er>k*k))return;pe()}if(!U()||!ne){We(Ze);return}let lt=y();K=an(Ze,A),Z=S$(Ni(K,lt,!1,[1,1]),r,l,ne),Y||(ae(),Y=!0);let Le=H0(Ze,{handle:Z,connectionMode:t,fromNodeId:o,fromHandleId:n,fromType:s?"target":"source",isValidConnection:w,doc:W,lib:u,flowId:g,nodeLookup:l});re=Le.handleDomNode,z=Le.connection,j=Z$(!!Z,Le.isValid);let vt=l.get(o),Ot=vt?Lo(vt,ne,$e.Left,!0):ge.from,ar={...ge,from:Ot,isValid:j,to:Le.toHandle&&j?gl({x:Le.toHandle.x,y:Le.toHandle.y},lt):K,toHandle:Le.toHandle,toPosition:j&&Le.toHandle?Le.toHandle.position:o0[ne.position],toNode:Le.toHandle?l.get(Le.toHandle.nodeId):null,pointer:K};E(ar),ge=ar}function We(Ze){if(!("touches"in Ze&&Ze.touches.length>0)){if(S){(Z||re)&&z&&j&&b?.(z);let{inProgress:lt,...Le}=ge,vt={...Le,toPosition:ge.toHandle?ge.toPosition:null};x?.(Ze,vt),i&&C?.(Ze,vt)}p(),cancelAnimationFrame(H),Y=!1,j=!1,z=null,re=null,W.removeEventListener("mousemove",we),W.removeEventListener("mouseup",We),W.removeEventListener("touchmove",we),W.removeEventListener("touchend",We)}}W.addEventListener("mousemove",we),W.addEventListener("mouseup",We),W.addEventListener("touchmove",we),W.addEventListener("touchend",We)}function H0(e,{handle:t,connectionMode:r,fromNodeId:n,fromHandleId:o,fromType:i,doc:s,lib:a,flowId:l,isValidConnection:u=O0,nodeLookup:f}){let g=i==="target",d=t?s.querySelector(`.${a}-flow__handle[data-id="${l}-${t?.nodeId}-${t?.id}-${t?.type}"]`):null,{x:p,y:h}=an(e),b=s.elementFromPoint(p,h),x=b?.classList.contains(`${a}-flow__handle`)?b:d,w={handleDomNode:x,isValid:!1,connection:null,toHandle:null};if(x){let C=D0(void 0,x),E=x.getAttribute("data-nodeid"),y=x.getAttribute("data-handleid"),U=x.classList.contains("connectable"),B=x.classList.contains("connectableend");if(!E||!C)return w;let k={source:g?E:n,sourceHandle:g?y:o,target:g?n:E,targetHandle:g?o:y};w.connection=k;let W=U&&B&&(r===Uo.Strict?g&&C==="source"||!g&&C==="target":E!==n||y!==o);w.isValid=W&&u(k),w.toHandle=T0(E,C,y,f,r,!0)}return w}function M0({domNode:e,panZoom:t,getTransform:r,getViewScale:n}){let o=Kt(e);function i({translateExtent:a,width:l,height:u,zoomStep:f=1,pannable:g=!0,zoomable:d=!0,inversePan:p=!1}){let h=E=>{if(E.sourceEvent.type!=="wheel"||!t)return;let y=r(),U=E.sourceEvent.ctrlKey&&Vs()?10:1,B=-E.sourceEvent.deltaY*(E.sourceEvent.deltaMode===1?.05:E.sourceEvent.deltaMode?1:.002)*f,k=y[2]*Math.pow(2,B*U);t.scaleTo(k)},b=[0,0],x=E=>{(E.sourceEvent.type==="mousedown"||E.sourceEvent.type==="touchstart")&&(b=[E.sourceEvent.clientX??E.sourceEvent.touches[0].clientX,E.sourceEvent.clientY??E.sourceEvent.touches[0].clientY])},w=E=>{let y=r();if(E.sourceEvent.type!=="mousemove"&&E.sourceEvent.type!=="touchmove"||!t)return;let U=[E.sourceEvent.clientX??E.sourceEvent.touches[0].clientX,E.sourceEvent.clientY??E.sourceEvent.touches[0].clientY],B=[U[0]-b[0],U[1]-b[1]];b=U;let k=n()*Math.max(y[2],Math.log(y[2]))*(p?-1:1),G={x:y[0]-B[0]*k,y:y[1]-B[1]*k},W=[[0,0],[l,u]];t.setViewportConstrained({x:G.x,y:G.y,zoom:y[2]},W,a)},C=ad().on("start",x).on("zoom",g?w:null).on("zoom.wheel",d?h:null);o.call(C,{})}function s(){o.on("zoom",null)}return{update:i,destroy:s,pointer:vr}}function Q$({zoomPanValues:e,noWheelClassName:t,d3Selection:r,d3Zoom:n,panOnScrollMode:o,panOnScrollSpeed:i,zoomOnPinch:s,onPanZoomStart:a,onPanZoom:l,onPanZoomEnd:u}){return f=>{if(ks(f,t))return f.ctrlKey&&f.preventDefault(),!1;f.preventDefault(),f.stopImmediatePropagation();let g=r.property("__zoom").k||1;if(f.ctrlKey&&s){let x=vr(f),w=z0(f),C=g*Math.pow(2,w);n.scaleTo(r,C,x,f);return}let d=f.deltaMode===1?20:1,p=o===Fi.Vertical?0:f.deltaX*d,h=o===Fi.Horizontal?0:f.deltaY*d;!Vs()&&f.shiftKey&&o!==Fi.Vertical&&(p=f.deltaY*d,h=0),n.translateBy(r,-(p/g)*i,-(h/g)*i,{internal:!0});let b=bd(r.property("__zoom"));clearTimeout(e.panScrollTimeout),e.isPanScrolling?(l?.(f,b),e.panScrollTimeout=setTimeout(()=>{u?.(f,b),e.isPanScrolling=!1},150)):(e.isPanScrolling=!0,a?.(f,b))}}function X$({noWheelClassName:e,preventScrolling:t,d3ZoomHandler:r}){return function(n,o){let i=n.type==="wheel",s=!t&&i&&!n.ctrlKey,a=ks(n,e);if(n.ctrlKey&&i&&a&&n.preventDefault(),s||a)return null;n.preventDefault(),r.call(this,n,o)}}function R$({zoomPanValues:e,onDraggingChange:t,onPanZoomStart:r}){return n=>{if(n.sourceEvent?.internal)return;let o=bd(n.transform);e.mouseButton=n.sourceEvent?.button||0,e.isZoomingOrPanning=!0,e.prevViewport=o,n.sourceEvent?.type==="mousedown"&&t(!0),r&&r?.(n.sourceEvent,o)}}function U$({zoomPanValues:e,panOnDrag:t,onPaneContextMenu:r,onTransformChange:n,onPanZoom:o}){return i=>{e.usedRightMouseButton=!!(r&&Y0(t,e.mouseButton??0)),i.sourceEvent?.sync||n([i.transform.x,i.transform.y,i.transform.k]),o&&!i.sourceEvent?.internal&&o?.(i.sourceEvent,bd(i.transform))}}function L$({zoomPanValues:e,panOnDrag:t,panOnScroll:r,onDraggingChange:n,onPanZoomEnd:o,onPaneContextMenu:i}){return s=>{if(!s.sourceEvent?.internal&&(e.isZoomingOrPanning=!1,i&&Y0(t,e.mouseButton??0)&&!e.usedRightMouseButton&&s.sourceEvent&&i(s.sourceEvent),e.usedRightMouseButton=!1,n(!1),o)){let a=bd(s.transform);e.prevViewport=a,clearTimeout(e.timerId),e.timerId=setTimeout(()=>{o?.(s.sourceEvent,a)},r?150:0)}}}function V$({zoomActivationKeyPressed:e,zoomOnScroll:t,zoomOnPinch:r,panOnDrag:n,panOnScroll:o,zoomOnDoubleClick:i,userSelectionActive:s,noWheelClassName:a,noPanClassName:l,lib:u,connectionInProgress:f}){return g=>{let d=e||t,p=r&&g.ctrlKey,h=g.type==="wheel";if(g.button===1&&g.type==="mousedown"&&(ks(g,`${u}-flow__node`)||ks(g,`${u}-flow__edge`)))return!0;if(!n&&!d&&!o&&!i&&!r||s||f&&!h||ks(g,a)&&h||ks(g,l)&&(!h||o&&h&&!e)||!r&&g.ctrlKey&&h)return!1;if(!r&&g.type==="touchstart"&&g.touches?.length>1)return g.preventDefault(),!1;if(!d&&!o&&!p&&h||!n&&(g.type==="mousedown"||g.type==="touchstart")||Array.isArray(n)&&!n.includes(g.button)&&g.type==="mousedown")return!1;let b=Array.isArray(n)&&n.includes(g.button)||!g.button||g.button<=1;return(!g.ctrlKey||h)&&b}}function P0({domNode:e,minZoom:t,maxZoom:r,translateExtent:n,viewport:o,onPanZoom:i,onPanZoomStart:s,onPanZoomEnd:a,onDraggingChange:l}){let u={isZoomingOrPanning:!1,usedRightMouseButton:!1,prevViewport:{x:0,y:0,zoom:0},mouseButton:0,timerId:void 0,panScrollTimeout:void 0,isPanScrolling:!1},f=e.getBoundingClientRect(),g=ad().scaleExtent([t,r]).translateExtent(n),d=Kt(e).call(g);C({x:o.x,y:o.y,zoom:Qs(o.zoom,t,r)},[[0,0],[f.width,f.height]],n);let p=d.on("wheel.zoom"),h=d.on("dblclick.zoom");g.wheelDelta(z0);function b(Z,$){return d?new Promise(X=>{g?.interpolate($?.interpolate==="linear"?co:Bi).transform(qf(d,$?.duration,$?.ease,()=>X(!0)),Z)}):Promise.resolve(!1)}function x({noWheelClassName:Z,noPanClassName:$,onPaneContextMenu:X,userSelectionActive:I,panOnScroll:A,panOnDrag:S,panOnScrollMode:T,panOnScrollSpeed:K,preventScrolling:Y,zoomOnPinch:z,zoomOnScroll:j,zoomOnDoubleClick:re,zoomActivationKeyPressed:ae,lib:ne,onTransformChange:Ie,connectionInProgress:fe,paneClickDistance:ge,selectionOnDrag:pe}){I&&!u.isZoomingOrPanning&&w();let we=A&&!ae&&!I;g.clickDistance(pe?1/0:!Tn(ge)||ge<0?0:ge);let We=we?Q$({zoomPanValues:u,noWheelClassName:Z,d3Selection:d,d3Zoom:g,panOnScrollMode:T,panOnScrollSpeed:K,zoomOnPinch:z,onPanZoomStart:s,onPanZoom:i,onPanZoomEnd:a}):X$({noWheelClassName:Z,preventScrolling:Y,d3ZoomHandler:p});if(d.on("wheel.zoom",We,{passive:!1}),!I){let lt=R$({zoomPanValues:u,onDraggingChange:l,onPanZoomStart:s});g.on("start",lt);let Le=U$({zoomPanValues:u,panOnDrag:S,onPaneContextMenu:!!X,onPanZoom:i,onTransformChange:Ie});g.on("zoom",Le);let vt=L$({zoomPanValues:u,panOnDrag:S,panOnScroll:A,onPaneContextMenu:X,onPanZoomEnd:a,onDraggingChange:l});g.on("end",vt)}let Ze=V$({zoomActivationKeyPressed:ae,panOnDrag:S,zoomOnScroll:j,panOnScroll:A,zoomOnDoubleClick:re,zoomOnPinch:z,userSelectionActive:I,noPanClassName:$,noWheelClassName:Z,lib:ne,connectionInProgress:fe});g.filter(Ze),re?d.on("dblclick.zoom",h):d.on("dblclick.zoom",null)}function w(){g.on("zoom",null)}async function C(Z,$,X){let I=Kf(Z),A=g?.constrain()(I,$,X);return A&&await b(A),new Promise(S=>S(A))}async function E(Z,$){let X=Kf(Z);return await b(X,$),new Promise(I=>I(X))}function y(Z){if(d){let $=Kf(Z),X=d.property("__zoom");(X.k!==Z.zoom||X.x!==Z.x||X.y!==Z.y)&&g?.transform(d,$,null,{sync:!0})}}function U(){let Z=d?ul(d.node()):{x:0,y:0,k:1};return{x:Z.x,y:Z.y,zoom:Z.k}}function B(Z,$){return d?new Promise(X=>{g?.interpolate($?.interpolate==="linear"?co:Bi).scaleTo(qf(d,$?.duration,$?.ease,()=>X(!0)),Z)}):Promise.resolve(!1)}function k(Z,$){return d?new Promise(X=>{g?.interpolate($?.interpolate==="linear"?co:Bi).scaleBy(qf(d,$?.duration,$?.ease,()=>X(!0)),Z)}):Promise.resolve(!1)}function G(Z){g?.scaleExtent(Z)}function W(Z){g?.translateExtent(Z)}function H(Z){let $=!Tn(Z)||Z<0?0:Z;g?.clickDistance($)}return{update:x,destroy:w,setViewport:E,setViewportConstrained:C,getViewport:U,scaleTo:B,scaleBy:k,setScaleExtent:G,setTranslateExtent:W,syncViewport:y,setClickDistance:H}}var Si,dd,ud,c$,Uo,Fi,Ns,pl,Dn,fl,$e,o0,rg,_0,ng,hl,b0,Vo,Rs,d$,Qs,Zi,i0,w0,fd,eg,gd,ki,cd,ig,Us,sg,Tn,ag,Ls,Ni,gl,ml,Vs,E0,lg,p$,cg,an,s0,m$,v$,F0,l0,_$,c0,k0,y$,dg,I$,F$,O0,pg,bd,Kf,ks,Y0,N$,qf,z0,h0,W$,eP,Ke=v(()=>{Ff();$r();n0();As();Si={error001:()=>"[React Flow]: Seems like you have not used zustand provider as an ancestor. Help: https://reactflow.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:e=>`Node type "${e}" not found. Using fallback type "default".`,error004:()=>"The React Flow 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:e=>`The old edge with id=${e} does not exist.`,error009:e=>`Marker type "${e}" doesn't exist.`,error008:(e,{id:t,sourceHandle:r,targetHandle:n})=>`Couldn't create edge for ${e} handle id: "${e==="source"?r:n}", edge id: ${t}.`,error010:()=>"Handle: No node id found. Make sure to only use a Handle inside a custom Node.",error011:e=>`Edge type "${e}" not found. Using fallback type "default".`,error012:e=>`Node with id "${e}" does not exist, it may have been removed. This can happen when a node is deleted before the "onNodeClick" handler is called.`,error013:(e="react")=>`It seems that you haven't loaded the styles. Please import '@xyflow/${e}/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."},dd=[[Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY],[Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY]],ud=["Enter"," ","Escape"],c$={"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:e,x:t,y:r})=>`Moved selected node ${e}. New position, x: ${t}, y: ${r}`,"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"};(function(e){e.Strict="strict",e.Loose="loose"})(Uo||(Uo={}));(function(e){e.Free="free",e.Vertical="vertical",e.Horizontal="horizontal"})(Fi||(Fi={}));(function(e){e.Partial="partial",e.Full="full"})(Ns||(Ns={}));pl={inProgress:!1,isValid:null,from:null,fromHandle:null,fromPosition:null,fromNode:null,to:null,toHandle:null,toPosition:null,toNode:null,pointer:null};(function(e){e.Bezier="default",e.Straight="straight",e.Step="step",e.SmoothStep="smoothstep",e.SimpleBezier="simplebezier"})(Dn||(Dn={}));(function(e){e.Arrow="arrow",e.ArrowClosed="arrowclosed"})(fl||(fl={}));(function(e){e.Left="left",e.Top="top",e.Right="right",e.Bottom="bottom"})($e||($e={}));o0={[$e.Left]:$e.Right,[$e.Right]:$e.Left,[$e.Top]:$e.Bottom,[$e.Bottom]:$e.Top};rg=e=>"id"in e&&"source"in e&&"target"in e,_0=e=>"id"in e&&"position"in e&&!("source"in e)&&!("target"in e),ng=e=>"id"in e&&"internals"in e&&!("source"in e)&&!("target"in e),hl=(e,t=[0,0])=>{let{width:r,height:n}=fo(e),o=e.origin??t,i=r*o[0],s=n*o[1];return{x:e.position.x-i,y:e.position.y-s}},b0=(e,t={nodeOrigin:[0,0]})=>{if(e.length===0)return{x:0,y:0,width:0,height:0};let r=e.reduce((n,o)=>{let i=typeof o=="string",s=!t.nodeLookup&&!i?o:void 0;t.nodeLookup&&(s=i?t.nodeLookup.get(o):ng(o)?o:t.nodeLookup.get(o.id));let a=s?cd(s,t.nodeOrigin):{x:0,y:0,x2:0,y2:0};return fd(n,a)},{x:1/0,y:1/0,x2:-1/0,y2:-1/0});return gd(r)},Vo=(e,t={})=>{let r={x:1/0,y:1/0,x2:-1/0,y2:-1/0},n=!1;return e.forEach(o=>{(t.filter===void 0||t.filter(o))&&(r=fd(r,cd(o)),n=!0)}),n?gd(r):{x:0,y:0,width:0,height:0}},Rs=(e,t,[r,n,o]=[0,0,1],i=!1,s=!1)=>{let a={...Ni(t,[r,n,o]),width:t.width/o,height:t.height/o},l=[];for(let u of e.values()){let{measured:f,selectable:g=!0,hidden:d=!1}=u;if(s&&!g||d)continue;let p=f.width??u.width??u.initialWidth??null,h=f.height??u.height??u.initialHeight??null,b=Us(a,ki(u)),x=(p??0)*(h??0),w=i&&b>0;(!u.internals.handleBounds||w||b>=x||u.dragging)&&l.push(u)}return l},d$=(e,t)=>{let r=new Set;return e.forEach(n=>{r.add(n.id)}),t.filter(n=>r.has(n.source)||r.has(n.target))};Qs=(e,t=0,r=1)=>Math.min(Math.max(e,t),r),Zi=(e={x:0,y:0},t,r)=>({x:Qs(e.x,t[0][0],t[1][0]-(r?.width??0)),y:Qs(e.y,t[0][1],t[1][1]-(r?.height??0))});i0=(e,t,r)=>er?-Qs(Math.abs(e-r),1,t)/t:0,w0=(e,t,r=15,n=40)=>{let o=i0(e.x,n,t.width-n)*r,i=i0(e.y,n,t.height-n)*r;return[o,i]},fd=(e,t)=>({x:Math.min(e.x,t.x),y:Math.min(e.y,t.y),x2:Math.max(e.x2,t.x2),y2:Math.max(e.y2,t.y2)}),eg=({x:e,y:t,width:r,height:n})=>({x:e,y:t,x2:e+r,y2:t+n}),gd=({x:e,y:t,x2:r,y2:n})=>({x:e,y:t,width:r-e,height:n-t}),ki=(e,t=[0,0])=>{let{x:r,y:n}=ng(e)?e.internals.positionAbsolute:hl(e,t);return{x:r,y:n,width:e.measured?.width??e.width??e.initialWidth??0,height:e.measured?.height??e.height??e.initialHeight??0}},cd=(e,t=[0,0])=>{let{x:r,y:n}=ng(e)?e.internals.positionAbsolute:hl(e,t);return{x:r,y:n,x2:r+(e.measured?.width??e.width??e.initialWidth??0),y2:n+(e.measured?.height??e.height??e.initialHeight??0)}},ig=(e,t)=>gd(fd(eg(e),eg(t))),Us=(e,t)=>{let r=Math.max(0,Math.min(e.x+e.width,t.x+t.width)-Math.max(e.x,t.x)),n=Math.max(0,Math.min(e.y+e.height,t.y+t.height)-Math.max(e.y,t.y));return Math.ceil(r*n)},sg=e=>Tn(e.width)&&Tn(e.height)&&Tn(e.x)&&Tn(e.y),Tn=e=>!isNaN(e)&&isFinite(e),ag=(e,t)=>{},Ls=(e,t=[1,1])=>({x:t[0]*Math.round(e.x/t[0]),y:t[1]*Math.round(e.y/t[1])}),Ni=({x:e,y:t},[r,n,o],i=!1,s=[1,1])=>{let a={x:(e-r)/o,y:(t-n)/o};return i?Ls(a,s):a},gl=({x:e,y:t},[r,n,o])=>({x:e*o+r,y:t*o+n});ml=(e,t,r,n,o,i)=>{let s=f$(i,t,r),a=(t-s.x)/e.width,l=(r-s.y)/e.height,u=Math.min(a,l),f=Qs(u,n,o),g=e.x+e.width/2,d=e.y+e.height/2,p=t/2-g*f,h=r/2-d*f,b=g$(e,p,h,f,t,r),x={left:Math.min(b.left-s.left,0),top:Math.min(b.top-s.top,0),right:Math.min(b.right-s.right,0),bottom:Math.min(b.bottom-s.bottom,0)};return{x:p-x.left+x.right,y:h-x.top+x.bottom,zoom:f}},Vs=()=>typeof navigator<"u"&&navigator?.userAgent?.indexOf("Mac")>=0;E0=e=>({width:e.offsetWidth,height:e.offsetHeight}),lg=e=>e?.getRootNode?.()||window?.document,p$=["INPUT","SELECT","TEXTAREA"];cg=e=>"clientX"in e,an=(e,t)=>{let r=cg(e),n=r?e.clientX:e.touches?.[0].clientX,o=r?e.clientY:e.touches?.[0].clientY;return{x:n-(t?.left??0),y:o-(t?.top??0)}},s0=(e,t,r,n,o)=>{let i=t.querySelectorAll(`.${e}`);return!i||!i.length?null:Array.from(i).map(s=>{let a=s.getBoundingClientRect();return{id:s.getAttribute("data-handleid"),type:e,nodeId:o,position:s.getAttribute("data-handlepos"),x:(a.left-r.left)/n,y:(a.top-r.top)/n,...E0(s)}})};m$=({source:e,sourceHandle:t,target:r,targetHandle:n})=>`xy-edge__${e}${t||""}-${r}${n||""}`,v$=(e,t)=>t.some(r=>r.source===e.source&&r.target===e.target&&(r.sourceHandle===e.sourceHandle||!r.sourceHandle&&!e.sourceHandle)&&(r.targetHandle===e.targetHandle||!r.targetHandle&&!e.targetHandle)),F0=(e,t,r={})=>{if(!e.source||!e.target)return ag("006",Si.error006()),t;let n=r.getEdgeId||m$,o;return rg(e)?o={...e}:o={...e,id:n(e)},v$(o,t)?t:(o.sourceHandle===null&&delete o.sourceHandle,o.targetHandle===null&&delete o.targetHandle,t.concat(o))};l0={[$e.Left]:{x:-1,y:0},[$e.Right]:{x:1,y:0},[$e.Top]:{x:0,y:-1},[$e.Bottom]:{x:0,y:1}},_$=({source:e,sourcePosition:t=$e.Bottom,target:r})=>t===$e.Left||t===$e.Right?e.xMath.sqrt(Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2));k0=1e3,y$=10,dg={nodeOrigin:[0,0],nodeExtent:dd,elevateNodesOnSelect:!0,zIndexMode:"basic",defaults:{}},I$={...dg,checkEquality:!0};F$=250;O0=()=>!0;pg={onPointerDown:k$,isValid:H0};bd=e=>({x:e.x,y:e.y,zoom:e.k}),Kf=({x:e,y:t,zoom:r})=>Gi.translate(e,t).scale(r),ks=(e,t)=>e.target.closest(`.${t}`),Y0=(e,t)=>t===2&&Array.isArray(e)&&e.includes(2),N$=e=>((e*=2)<=1?e*e*e:(e-=2)*e*e+2)/2,qf=(e,t=0,r=N$,n=()=>{})=>{let o=typeof t=="number"&&t>0;return o||n(),o?e.transition().duration(t).ease(r).on("end",n):e},z0=e=>{let t=e.ctrlKey&&Vs()?10:1;return-e.deltaY*(e.deltaMode===1?.05:e.deltaMode?1:.002)*t};(function(e){e.Line="line",e.Handle="handle"})(h0||(h0={}));W$={width:0,height:0,x:0,y:0},eP={...W$,pointerX:0,pointerY:0,aspectRatio:1}});function hg(){let e={};return[t=>{if(t&&!la(e))throw new Error(t);return Pn(e)},t=>Jo(e,t)]}var J0,j0,K0,q0,ey,ty,vl=v(()=>{nn();[J0,j0]=hg(),[K0,q0]=hg(),[ey,ty]=hg()});function go(e,t){q(t,!0);let r=P(t,"id",3,null),n=P(t,"type",3,"source"),o=P(t,"position",19,()=>$e.Top),i=P(t,"isConnectableStart",3,!0),s=P(t,"isConnectableEnd",3,!0),a=jt(t,T$),l=J0("Handle must be used within a Custom Node component"),u=K0("Handle must be used within a Custom Node component"),f=_(()=>n()==="target"),g=_(()=>t.isConnectable!==void 0?t.isConnectable:u.value),d=Nt(),p=_(()=>d.ariaLabelConfig),h=null;ci(()=>{if(t.onconnect||t.ondisconnect){d.edges;let $=d.connectionLookup.get(`${l}-${n()}${r()?`-${r()}`:""}`);if(h&&!m0($,h)){let X=$??new Map;tg(h,X,t.ondisconnect),tg(X,h,t.onconnect)}h=new Map($)}});let b=_(()=>{if(!d.connection.inProgress)return[!1,!1,!1,!1,null];let{fromHandle:$,toHandle:X,isValid:I}=d.connection,A=$&&$.nodeId===l&&$.type===n()&&$.id===r(),S=X&&X.nodeId===l&&X.type===n()&&X.id===r(),T=d.connectionMode===Uo.Strict?$?.type!==n():l!==$?.nodeId||r()!==$?.id;return[!0,A,S,T,S&&I]}),x=_(()=>un(c(b),5)),w=_(()=>c(x)[0]),C=_(()=>c(x)[1]),E=_(()=>c(x)[2]),y=_(()=>c(x)[3]),U=_(()=>c(x)[4]);function B($){let X=d.onbeforeconnect?d.onbeforeconnect($):$;X&&(d.addEdge(X),d.onconnect?.($))}function k($){let X=cg($);$.currentTarget&&(X&&$.button===0||!X)&&pg.onPointerDown($,{handleId:r(),nodeId:l,isTarget:c(f),connectionRadius:d.connectionRadius,domNode:d.domNode,nodeLookup:d.nodeLookup,connectionMode:d.connectionMode,lib:"svelte",autoPanOnConnect:d.autoPanOnConnect,autoPanSpeed:d.autoPanSpeed,flowId:d.flowId,isValidConnection:t.isValidConnection||((...I)=>d.isValidConnection?.(...I)??!0),updateConnection:d.updateConnection,cancelConnection:d.cancelConnection,panBy:d.panBy,onConnect:B,onConnectStart:d.onconnectstart,onConnectEnd:(...I)=>d.onconnectend?.(...I),getTransform:()=>[d.viewport.x,d.viewport.y,d.viewport.zoom],getFromHandle:()=>d.connection.fromHandle,dragThreshold:d.connectionDragThreshold,handleDomNode:$.currentTarget})}function G($){if(!l||!d.clickConnectStartHandle&&!i())return;if(!d.clickConnectStartHandle){d.onclickconnectstart?.($,{nodeId:l,handleId:r(),handleType:n()}),d.clickConnectStartHandle={nodeId:l,type:n(),id:r()};return}let X=lg($.target),I=t.isValidConnection??d.isValidConnection,{connectionMode:A,clickConnectStartHandle:S,flowId:T,nodeLookup:K}=d,{connection:Y,isValid:z}=pg.isValid($,{handle:{nodeId:l,id:r(),type:n()},connectionMode:A,fromNodeId:S.nodeId,fromHandleId:S.id??null,fromType:S.type,isValidConnection:I,flowId:T,doc:X,lib:"svelte",nodeLookup:K});z&&Y&&B(Y);let j=structuredClone(Yn(d.connection));delete j.inProgress,j.toPosition=j.toHandle?j.toHandle.position:null,d.onclickconnectend?.($,j),d.clickConnectStartHandle=null}var W=D$(),H=()=>{};Jt(W,()=>({"data-handleid":r(),"data-nodeid":l,"data-handlepos":o(),"data-id":`${d.flowId??""}-${l??""}-${r()??"null"??""}-${n()??""}`,class:["svelte-flow__handle",`svelte-flow__handle-${o()}`,d.noDragClass,d.noPanClass,o(),t.class],onmousedown:k,ontouchstart:k,onclick:d.clickConnect?G:void 0,onkeypress:H,style:t.style,role:"button","aria-label":c(p)["handle.ariaLabel"],tabindex:"-1",...a,[on]:{valid:c(U),connectingto:c(E),connectingfrom:c(C),source:!c(f),target:c(f),connectablestart:i(),connectableend:s(),connectable:c(g),connectionindicator:c(g)&&(!c(w)||c(y))&&(c(w)||d.clickConnectStartHandle?s():i())}}));var Z=V(W);at(Z,()=>t.children??ct),Q(W),F(e,W),ee()}var T$,D$,ry=v(()=>{ve();ie();Ke();ln();vl();T$=new Set(["$$slots","$$events","$$legacy","id","type","position","style","class","isConnectable","isConnectableStart","isConnectableEnd","isValidConnection","onconnect","ondisconnect","children"]),D$=J("
            ")});var ny=v(()=>{});var _l=v(()=>{ry();ny()});function bl(e,t){q(t,!0);let r=P(t,"targetPosition",19,()=>$e.Top),n=P(t,"sourcePosition",19,()=>$e.Bottom);var o=O$(),i=le(o);go(i,{type:"target",get position(){return r()}});var s=O(i),a=O(s);go(a,{type:"source",get position(){return n()}}),te(()=>oe(s,` ${t.data?.label??""} `)),F(e,o),ee()}var O$,mg=v(()=>{ve();ie();Ke();_l();O$=J(" ",1)});function vg(e,t){q(t,!0);let r=P(t,"data",19,()=>({label:"Node"})),n=P(t,"sourcePosition",19,()=>$e.Bottom);Ct();var o=H$(),i=le(o),s=O(i);go(s,{type:"source",get position(){return n()}}),te(()=>oe(i,`${r()?.label??""} `)),F(e,o),ee()}var H$,oy=v(()=>{ve();ie();Ke();_l();H$=J(" ",1)});function _g(e,t){q(t,!0);let r=P(t,"data",19,()=>({label:"Node"})),n=P(t,"targetPosition",19,()=>$e.Top);Ct();var o=M$(),i=le(o),s=O(i);go(s,{type:"target",get position(){return n()}}),te(()=>oe(i,`${r()?.label??""} `)),F(e,o),ee()}var M$,iy=v(()=>{ve();ie();Ke();_l();M$=J(" ",1)});function bg(e,t){}var sy=v(()=>{ve();ie()});function xg(e,t,r){if(!r||!t)return;let n=r==="root"?t:t.querySelector(`.svelte-flow__${r}`);n&&n.appendChild(e)}function yg(e,t){let r=_(Nt),n=_(()=>c(r).domNode),o;return c(n)?xg(e,c(n),t):o=di(()=>{st(()=>{xg(e,c(n),t),o?.()})}),{async update(i){xg(e,c(n),i)},destroy(){e.parentNode&&e.parentNode.removeChild(e),o?.()}}}var ay=v(()=>{ie();ln()});function Ig(){let e=ye(typeof window>"u");if(c(e)){let t=di(()=>{st(()=>{M(e,!1),t?.()})})}return{get value(){return c(e)}}}var ly=v(()=>{ie()});var wg=v(()=>{ay();ly()});function xr(e){return e===void 0?void 0:`${e}px`}var Cg,cy,Ts,Wo=v(()=>{Ke();Cg=e=>_0(e),cy=e=>rg(e);Ts={ArrowUp:{x:0,y:-1},ArrowDown:{x:0,y:1},ArrowLeft:{x:-1,y:0},ArrowRight:{x:1,y:0}}});var dy=v(()=>{});function Bg(e,t){q(t,!0);let r=P(t,"x",3,0),n=P(t,"y",3,0),o=P(t,"selectEdgeOnClick",3,!1),i=P(t,"transparent",3,!1),s=jt(t,Y$),a=Nt(),l=ey("EdgeLabel must be used within a Custom Edge component"),u=_(()=>a.visible.edges.get(l)?.zIndex);var f=z$(),g=()=>{o()&&l&&a.handleEdgeSelection(l)};Jt(f,p=>({class:["svelte-flow__edge-label",{transparent:i()},t.class],tabindex:"-1",onclick:g,...s,[Er]:p}),[()=>({display:Ig().value?"none":void 0,cursor:o()?"pointer":void 0,transform:`translate(-50%, -50%) translate(${r()??""}px,${n()??""}px)`,"pointer-events":"all",width:xr(t.width),height:xr(t.height),"z-index":c(u)})],void 0,void 0,"svelte-1wg91mu");var d=V(f);at(d,()=>t.children??ct),Q(f),ft(f,(p,h)=>yg?.(p,h),()=>"edge-labels"),F(e,f),ee()}var Y$,z$,uy=v(()=>{ve();ie();vl();wg();ln();Wo();dy();Y$=new Set(["$$slots","$$events","$$legacy","x","y","width","height","selectEdgeOnClick","transparent","class","children"]),z$=J("
            ")});function po(e,t){let r=P(t,"interactionWidth",3,20),n=jt(t,P$);var o=j$(),i=le(o),s=O(i);{var a=f=>{var g=J$();Jt(g,()=>({d:t.path,"stroke-opacity":0,"stroke-width":r(),fill:"none",class:"svelte-flow__edge-interaction",...n})),F(f,g)};ce(s,f=>{r()>0&&f(a)})}var l=O(s);{var u=f=>{Bg(f,{get x(){return t.labelX},get y(){return t.labelY},get style(){return t.labelStyle},selectEdgeOnClick:!0,children:(g,d)=>{Ct();var p=Ou();te(()=>oe(p,t.label)),F(g,p)},$$slots:{default:!0}})};ce(l,f=>{t.label&&f(u)})}te(()=>{D(i,"id",t.id),D(i,"d",t.path),Je(i,0,Pt(["svelte-flow__edge-path",t.class])),D(i,"marker-start",t.markerStart),D(i,"marker-end",t.markerEnd),Oe(i,t.style)}),F(e,o)}var P$,J$,j$,xl=v(()=>{ve();ie();uy();P$=new Set(["$$slots","$$events","$$legacy","id","path","label","labelX","labelY","labelStyle","markerStart","markerEnd","style","interactionWidth","class"]),J$=Ge(""),j$=Ge('',1)});function Ds(e,t){q(t,!0);let r=_(()=>md({sourceX:t.sourceX,sourceY:t.sourceY,targetX:t.targetX,targetY:t.targetY,sourcePosition:t.sourcePosition,targetPosition:t.targetPosition,curvature:t.pathOptions?.curvature})),n=_(()=>un(c(r),3)),o=_(()=>c(n)[0]),i=_(()=>c(n)[1]),s=_(()=>c(n)[2]);po(e,{get id(){return t.id},get path(){return c(o)},get labelX(){return c(i)},get labelY(){return c(s)},get label(){return t.label},get labelStyle(){return t.labelStyle},get markerStart(){return t.markerStart},get markerEnd(){return t.markerEnd},get interactionWidth(){return t.interactionWidth},get style(){return t.style}}),ee()}var fy=v(()=>{ve();ie();Ke();xl()});function xd(e,t){q(t,!0);let r=_(()=>Ws({sourceX:t.sourceX,sourceY:t.sourceY,targetX:t.targetX,targetY:t.targetY,sourcePosition:t.sourcePosition,targetPosition:t.targetPosition})),n=_(()=>un(c(r),3)),o=_(()=>c(n)[0]),i=_(()=>c(n)[1]),s=_(()=>c(n)[2]);po(e,{get path(){return c(o)},get labelX(){return c(i)},get labelY(){return c(s)},get label(){return t.label},get labelStyle(){return t.labelStyle},get markerStart(){return t.markerStart},get markerEnd(){return t.markerEnd},get interactionWidth(){return t.interactionWidth},get style(){return t.style}}),ee()}var gy=v(()=>{ve();ie();Ke();xl()});function yd(e,t){q(t,!0);let r=_(()=>vd({sourceX:t.sourceX,sourceY:t.sourceY,targetX:t.targetX,targetY:t.targetY})),n=_(()=>un(c(r),3)),o=_(()=>c(n)[0]),i=_(()=>c(n)[1]),s=_(()=>c(n)[2]);po(e,{get path(){return c(o)},get labelX(){return c(i)},get labelY(){return c(s)},get label(){return t.label},get labelStyle(){return t.labelStyle},get markerStart(){return t.markerStart},get markerEnd(){return t.markerEnd},get interactionWidth(){return t.interactionWidth},get style(){return t.style}}),ee()}var py=v(()=>{ve();ie();Ke();xl()});function Id(e,t){q(t,!0);let r=_(()=>Ws({sourceX:t.sourceX,sourceY:t.sourceY,targetX:t.targetX,targetY:t.targetY,sourcePosition:t.sourcePosition,targetPosition:t.targetPosition,borderRadius:0})),n=_(()=>un(c(r),3)),o=_(()=>c(n)[0]),i=_(()=>c(n)[1]),s=_(()=>c(n)[2]);po(e,{get path(){return c(o)},get labelX(){return c(i)},get labelY(){return c(s)},get label(){return t.label},get labelStyle(){return t.labelStyle},get markerStart(){return t.markerStart},get markerEnd(){return t.markerEnd},get interactionWidth(){return t.interactionWidth},get style(){return t.style}}),ee()}var hy=v(()=>{ve();ie();Ke();xl()});var Eg=v(()=>{fy();gy();py();hy()});var my=v(()=>{ie();pt();Qr();Ee();Se()});var vy=v(()=>{Se();pt();Qr();Ee()});var _y=v(()=>{Se();pt();Qr();Ee()});var by,sr,Il,ho,Qi,yl,wd,$g=v(()=>{Se();pt();Qr();Ee();Ag();by=Symbol("replace"),wd=class extends URLSearchParams{constructor(){super(...arguments);L(this,Qi);L(this,sr,R?ut(ye(0),"SvelteURLSearchParams version"):ye(0));L(this,Il,xy());L(this,ho,!1)}[by](r){if(!m(this,ho)){he(this,ho,!0);for(let n of[...super.keys()])super.delete(n);for(let[n,o]of r)super.append(n,o);ur(m(this,sr)),he(this,ho,!1)}}append(r,n){super.append(r,n),Ce(this,Qi,yl).call(this),ur(m(this,sr))}delete(r,n){var o=super.has(r,n);super.delete(r,n),o&&(Ce(this,Qi,yl).call(this),ur(m(this,sr)))}get(r){return c(m(this,sr)),super.get(r)}getAll(r){return c(m(this,sr)),super.getAll(r)}has(r,n){return c(m(this,sr)),super.has(r,n)}keys(){return c(m(this,sr)),super.keys()}set(r,n){var o=super.getAll(r).join("");super.set(r,n),o!==super.getAll(r).join("")&&(Ce(this,Qi,yl).call(this),ur(m(this,sr)))}sort(){super.sort(),Ce(this,Qi,yl).call(this),ur(m(this,sr))}toString(){return c(m(this,sr)),super.toString()}values(){return c(m(this,sr)),super.values()}entries(){return c(m(this,sr)),super.entries()}[Symbol.iterator](){return this.entries()}get size(){return c(m(this,sr)),super.size}};sr=new WeakMap,Il=new WeakMap,ho=new WeakMap,Qi=new WeakSet,yl=function(){if(!m(this,Il)||m(this,ho))return;he(this,ho,!0);let r=this.toString();m(this,Il).search=r&&`?${r}`,he(this,ho,!1)}});function xy(){return q$}var q$,Ag=v(()=>{Se();pt();Qr();Ee();$g();q$=null});var Gg=v(()=>{Is()});var wl,Cl,Cd,yy=v(()=>{ec();Cd=class{constructor(t,r){L(this,wl);L(this,Cl);he(this,wl,t),he(this,Cl,xa(r))}get current(){return m(this,Cl).call(this),m(this,wl).call(this)}};wl=new WeakMap,Cl=new WeakMap});var eA,tA,Bl,Iy=v(()=>{Gg();yy();eA=/\(.+\)/,tA=new Set(["all","print","screen","and","or","not","only"]),Bl=class extends Cd{constructor(t,r){let n=eA.test(t)||t.split(/[\s,]+/).some(i=>tA.has(i.trim()))?t:`(${t})`,o=window.matchMedia(n);super(()=>o.matches,i=>gi(o,"change",i))}}});var wy=v(()=>{my();vy();_y();Ag();$g();Iy();ec()});function Cy(e,t,r,n){let o=new Map;return Rs(e,{x:0,y:0,width:r,height:n},t,!0).forEach(i=>{o.set(i.id,i)}),o}function Fg(e){let{edges:t,defaultEdgeOptions:r,nodeLookup:n,previousEdges:o,connectionMode:i,onerror:s,onlyRenderVisible:a,elevateEdgesOnSelect:l,zIndexMode:u}=e,f=new Map;for(let g of t){let d=n.get(g.source),p=n.get(g.target);if(!d||!p)continue;if(a){let{visibleNodes:x,transform:w,width:C,height:E}=e;if(G0({sourceNode:d,targetNode:p,width:C,height:E,transform:w}))x.set(d.id,d),x.set(p.id,p);else continue}let h=o.get(g.id);if(h&&g===h.edge&&d==h.sourceNode&&p==h.targetNode){f.set(g.id,h);continue}let b=S0({id:g.id,sourceNode:d,targetNode:p,sourceHandle:g.sourceHandle||null,targetHandle:g.targetHandle||null,connectionMode:i,onError:s});b&&f.set(g.id,{...r,...g,...b,zIndex:A0({selected:g.selected,zIndex:g.zIndex??r.zIndex,sourceNode:d,targetNode:p,elevateOnSelect:l,zIndexMode:u}),sourceNode:d,targetNode:p,edge:g})}return f}var By=v(()=>{Ke()});function rA(e,t,r,n,o,i){if(t&&!r&&n&&o){let s=Vo(i,{filter:a=>!!((a.width||a.initialWidth)&&(a.height||a.initialHeight))});return ml(s,n,o,.5,2,.1)}else return r??{x:0,y:0,zoom:1}}function Ey(e){var r,n,o,i,s,a,l,u,f,g,d,p,h,b,x,w,C,E,y,U,B,k,G,W,H,Z,$,X,I,A,S,T,K,Y,z,j,re,ae,ne,Ie,fe,ge,pe,we,We,Ze,lt,Le,vt,Ot,ar,yr,Qe,nt,er,Me,Fr,Or,Hr,Ui,Li,Vi,Wi,Ti,Di,Oi,Hi,Mi,Yi,zi,Oo,Ho,Sr,Mo,Mr,js;class t{constructor(){L(this,r,_(()=>e.props.id??"1"));L(this,n,ye(null));L(this,o,ye(null));L(this,i,ye(e.width??0));L(this,s,ye(e.height??0));L(this,a,ye(e.props.zIndexMode??"basic"));L(this,l,_(()=>{let{nodesInitialized:N}=Q0(e.nodes,this.nodeLookup,this.parentLookup,{nodeExtent:this.nodeExtent,nodeOrigin:this.nodeOrigin,elevateNodesOnSelect:e.props.elevateNodesOnSelect??!0,checkEquality:!0,zIndexMode:this.zIndexMode});return this.fitViewQueued&&N&&(this.fitViewOptions?.duration?this.resolveFitView():queueMicrotask(()=>{this.resolveFitView()})),N}));L(this,u,_(()=>this.panZoom!==null));L(this,f,_(()=>(L0(this.connectionLookup,this.edgeLookup,e.edges),e.edges)));Ae(this,"_prevSelectedNodes",[]);Ae(this,"_prevSelectedNodeIds",new Set);L(this,g,_(()=>{let N=this._prevSelectedNodeIds.size,Hn=new Set,Ks=this.nodes.filter(Yr=>(Yr.selected&&(Hn.add(Yr.id),this._prevSelectedNodeIds.delete(Yr.id)),Yr.selected));return(N!==Hn.size||this._prevSelectedNodeIds.size>0)&&(this._prevSelectedNodes=Ks),this._prevSelectedNodeIds=Hn,this._prevSelectedNodes}));Ae(this,"_prevSelectedEdges",[]);Ae(this,"_prevSelectedEdgeIds",new Set);L(this,d,_(()=>{let N=this._prevSelectedEdgeIds.size,Hn=new Set,Ks=this.edges.filter(Yr=>(Yr.selected&&(Hn.add(Yr.id),this._prevSelectedEdgeIds.delete(Yr.id)),Yr.selected));return(N!==Hn.size||this._prevSelectedEdgeIds.size>0)&&(this._prevSelectedEdges=Ks),this._prevSelectedEdgeIds=Hn,this._prevSelectedEdges}));Ae(this,"selectionChangeHandlers",new Map);Ae(this,"nodeLookup",new Map);Ae(this,"parentLookup",new Map);Ae(this,"connectionLookup",new Map);Ae(this,"edgeLookup",new Map);Ae(this,"_prevVisibleEdges",new Map);L(this,p,_(()=>{let{nodes:N,_edges:Hn,_prevVisibleEdges:Ks,nodeLookup:Yr,connectionMode:uC,onerror:fC,onlyRenderVisibleElements:gC,defaultEdgeOptions:pC,zIndexMode:hC}=this,kl,Yd,wp={edges:Hn,defaultEdgeOptions:pC,previousEdges:Ks,nodeLookup:Yr,connectionMode:uC,elevateEdgesOnSelect:e.props.elevateEdgesOnSelect??!0,zIndexMode:hC,onerror:fC};if(gC){let{viewport:zd,width:Cp,height:Bp}=this,Ep=[zd.x,zd.y,zd.zoom];kl=Cy(Yr,Ep,Cp,Bp),Yd=Fg({...wp,onlyRenderVisible:!0,visibleNodes:kl,transform:Ep,width:Cp,height:Bp})}else kl=this.nodeLookup,Yd=Fg(wp);return{nodes:kl,edges:Yd}}));L(this,h,_(()=>e.props.nodesDraggable??!0));L(this,b,_(()=>e.props.nodesConnectable??!0));L(this,x,_(()=>e.props.elementsSelectable??!0));L(this,w,_(()=>e.props.nodesFocusable??!0));L(this,C,_(()=>e.props.edgesFocusable??!0));L(this,E,_(()=>e.props.disableKeyboardA11y??!1));L(this,y,_(()=>e.props.minZoom??.5));L(this,U,_(()=>e.props.maxZoom??2));L(this,B,_(()=>e.props.nodeOrigin??[0,0]));L(this,k,_(()=>e.props.nodeExtent??dd));L(this,G,_(()=>e.props.translateExtent??dd));L(this,W,_(()=>e.props.defaultEdgeOptions??{}));L(this,H,_(()=>e.props.nodeDragThreshold??1));L(this,Z,_(()=>e.props.autoPanOnNodeDrag??!0));L(this,$,_(()=>e.props.autoPanOnConnect??!0));L(this,X,_(()=>e.props.autoPanOnNodeFocus??!0));L(this,I,_(()=>e.props.autoPanSpeed??15));L(this,A,_(()=>e.props.connectionDragThreshold??1));Ae(this,"fitViewQueued",e.props.fitView??!1);Ae(this,"fitViewOptions",e.props.fitViewOptions);Ae(this,"fitViewResolver",null);L(this,S,_(()=>e.props.snapGrid??null));L(this,T,ye(!1));L(this,K,ye(null));L(this,Y,ye(!1));L(this,z,ye(!1));L(this,j,ye(!1));L(this,re,ye(!1));L(this,ae,ye(!1));L(this,ne,ye(null));L(this,Ie,ye(""));L(this,fe,_(()=>e.props.selectionMode??Ns.Partial));L(this,ge,_(()=>({...Sg,...e.props.nodeTypes})));L(this,pe,_(()=>({...Zg,...e.props.edgeTypes})));L(this,we,_(()=>e.props.noPanClass??"nopan"));L(this,We,_(()=>e.props.noDragClass??"nodrag"));L(this,Ze,_(()=>e.props.noWheelClass??"nowheel"));L(this,lt,_(()=>B0(e.props.ariaLabelConfig)));L(this,Le,ye(rA(this.nodesInitialized,e.props.fitView,e.props.initialViewport,this.width,this.height,this.nodeLookup)));L(this,vt,ye(pl));L(this,Ot,_(()=>this._connection.inProgress?{...this._connection,to:Ni(this._connection.to,[this.viewport.x,this.viewport.y,this.viewport.zoom])}:this._connection));L(this,ar,_(()=>e.props.connectionMode??Uo.Strict));L(this,yr,_(()=>e.props.connectionRadius??20));L(this,Qe,_(()=>e.props.isValidConnection??(()=>!0)));L(this,nt,_(()=>e.props.selectNodesOnDrag??!0));L(this,er,_(()=>e.props.defaultMarkerColor===void 0?"#b1b1b7":e.props.defaultMarkerColor));L(this,Me,_(()=>Z0(e.edges,{defaultColor:this.defaultMarkerColor,id:this.flowId,defaultMarkerStart:this.defaultEdgeOptions.markerStart,defaultMarkerEnd:this.defaultEdgeOptions.markerEnd})));L(this,Fr,_(()=>e.props.onlyRenderVisibleElements??!1));L(this,Or,_(()=>e.props.onflowerror??ag));L(this,Hr,_(()=>e.props.ondelete));L(this,Ui,_(()=>e.props.onbeforedelete));L(this,Li,_(()=>e.props.onbeforeconnect));L(this,Vi,_(()=>e.props.onconnect));L(this,Wi,_(()=>e.props.onconnectstart));L(this,Ti,_(()=>e.props.onconnectend));L(this,Di,_(()=>e.props.onbeforereconnect));L(this,Oi,_(()=>e.props.onreconnect));L(this,Hi,_(()=>e.props.onreconnectstart));L(this,Mi,_(()=>e.props.onreconnectend));L(this,Yi,_(()=>e.props.clickConnect??!0));L(this,zi,_(()=>e.props.onclickconnectstart));L(this,Oo,_(()=>e.props.onclickconnectend));L(this,Ho,ye(null));L(this,Sr,_(()=>e.props.onselectiondrag));L(this,Mo,_(()=>e.props.onselectiondragstart));L(this,Mr,_(()=>e.props.onselectiondragstop));Ae(this,"resolveFitView",async()=>{this.panZoom&&(await x0({nodes:this.nodeLookup,width:this.width,height:this.height,panZoom:this.panZoom,minZoom:this.minZoom,maxZoom:this.maxZoom},this.fitViewOptions),this.fitViewResolver?.resolve(!0),this.fitViewQueued=!1,this.fitViewOptions=void 0,this.fitViewResolver=null)});Ae(this,"_prefersDark",new Bl("(prefers-color-scheme: dark)",e.props.colorModeSSR==="dark"));L(this,js,_(()=>e.props.colorMode==="system"?this._prefersDark.current?"dark":"light":e.props.colorMode??"light"))}get flowId(){return c(m(this,r))}set flowId(N){M(m(this,r),N)}get domNode(){return c(m(this,n))}set domNode(N){M(m(this,n),N)}get panZoom(){return c(m(this,o))}set panZoom(N){M(m(this,o),N)}get width(){return c(m(this,i))}set width(N){M(m(this,i),N)}get height(){return c(m(this,s))}set height(N){M(m(this,s),N)}get zIndexMode(){return c(m(this,a))}set zIndexMode(N){M(m(this,a),N)}get nodesInitialized(){return c(m(this,l))}set nodesInitialized(N){M(m(this,l),N)}get viewportInitialized(){return c(m(this,u))}set viewportInitialized(N){M(m(this,u),N)}get _edges(){return c(m(this,f))}set _edges(N){M(m(this,f),N)}get nodes(){return this.nodesInitialized,e.nodes}set nodes(N){e.nodes=N}get edges(){return this._edges}set edges(N){e.edges=N}get selectedNodes(){return c(m(this,g))}set selectedNodes(N){M(m(this,g),N)}get selectedEdges(){return c(m(this,d))}set selectedEdges(N){M(m(this,d),N)}get visible(){return c(m(this,p))}set visible(N){M(m(this,p),N)}get nodesDraggable(){return c(m(this,h))}set nodesDraggable(N){M(m(this,h),N)}get nodesConnectable(){return c(m(this,b))}set nodesConnectable(N){M(m(this,b),N)}get elementsSelectable(){return c(m(this,x))}set elementsSelectable(N){M(m(this,x),N)}get nodesFocusable(){return c(m(this,w))}set nodesFocusable(N){M(m(this,w),N)}get edgesFocusable(){return c(m(this,C))}set edgesFocusable(N){M(m(this,C),N)}get disableKeyboardA11y(){return c(m(this,E))}set disableKeyboardA11y(N){M(m(this,E),N)}get minZoom(){return c(m(this,y))}set minZoom(N){M(m(this,y),N)}get maxZoom(){return c(m(this,U))}set maxZoom(N){M(m(this,U),N)}get nodeOrigin(){return c(m(this,B))}set nodeOrigin(N){M(m(this,B),N)}get nodeExtent(){return c(m(this,k))}set nodeExtent(N){M(m(this,k),N)}get translateExtent(){return c(m(this,G))}set translateExtent(N){M(m(this,G),N)}get defaultEdgeOptions(){return c(m(this,W))}set defaultEdgeOptions(N){M(m(this,W),N)}get nodeDragThreshold(){return c(m(this,H))}set nodeDragThreshold(N){M(m(this,H),N)}get autoPanOnNodeDrag(){return c(m(this,Z))}set autoPanOnNodeDrag(N){M(m(this,Z),N)}get autoPanOnConnect(){return c(m(this,$))}set autoPanOnConnect(N){M(m(this,$),N)}get autoPanOnNodeFocus(){return c(m(this,X))}set autoPanOnNodeFocus(N){M(m(this,X),N)}get autoPanSpeed(){return c(m(this,I))}set autoPanSpeed(N){M(m(this,I),N)}get connectionDragThreshold(){return c(m(this,A))}set connectionDragThreshold(N){M(m(this,A),N)}get snapGrid(){return c(m(this,S))}set snapGrid(N){M(m(this,S),N)}get dragging(){return c(m(this,T))}set dragging(N){M(m(this,T),N)}get selectionRect(){return c(m(this,K))}set selectionRect(N){M(m(this,K),N)}get selectionKeyPressed(){return c(m(this,Y))}set selectionKeyPressed(N){M(m(this,Y),N)}get multiselectionKeyPressed(){return c(m(this,z))}set multiselectionKeyPressed(N){M(m(this,z),N)}get deleteKeyPressed(){return c(m(this,j))}set deleteKeyPressed(N){M(m(this,j),N)}get panActivationKeyPressed(){return c(m(this,re))}set panActivationKeyPressed(N){M(m(this,re),N)}get zoomActivationKeyPressed(){return c(m(this,ae))}set zoomActivationKeyPressed(N){M(m(this,ae),N)}get selectionRectMode(){return c(m(this,ne))}set selectionRectMode(N){M(m(this,ne),N)}get ariaLiveMessage(){return c(m(this,Ie))}set ariaLiveMessage(N){M(m(this,Ie),N)}get selectionMode(){return c(m(this,fe))}set selectionMode(N){M(m(this,fe),N)}get nodeTypes(){return c(m(this,ge))}set nodeTypes(N){M(m(this,ge),N)}get edgeTypes(){return c(m(this,pe))}set edgeTypes(N){M(m(this,pe),N)}get noPanClass(){return c(m(this,we))}set noPanClass(N){M(m(this,we),N)}get noDragClass(){return c(m(this,We))}set noDragClass(N){M(m(this,We),N)}get noWheelClass(){return c(m(this,Ze))}set noWheelClass(N){M(m(this,Ze),N)}get ariaLabelConfig(){return c(m(this,lt))}set ariaLabelConfig(N){M(m(this,lt),N)}get _viewport(){return c(m(this,Le))}set _viewport(N){M(m(this,Le),N)}get viewport(){return e.viewport??this._viewport}set viewport(N){e.viewport&&(e.viewport=N),this._viewport=N}get _connection(){return c(m(this,vt))}set _connection(N){M(m(this,vt),N)}get connection(){return c(m(this,Ot))}set connection(N){M(m(this,Ot),N)}get connectionMode(){return c(m(this,ar))}set connectionMode(N){M(m(this,ar),N)}get connectionRadius(){return c(m(this,yr))}set connectionRadius(N){M(m(this,yr),N)}get isValidConnection(){return c(m(this,Qe))}set isValidConnection(N){M(m(this,Qe),N)}get selectNodesOnDrag(){return c(m(this,nt))}set selectNodesOnDrag(N){M(m(this,nt),N)}get defaultMarkerColor(){return c(m(this,er))}set defaultMarkerColor(N){M(m(this,er),N)}get markers(){return c(m(this,Me))}set markers(N){M(m(this,Me),N)}get onlyRenderVisibleElements(){return c(m(this,Fr))}set onlyRenderVisibleElements(N){M(m(this,Fr),N)}get onerror(){return c(m(this,Or))}set onerror(N){M(m(this,Or),N)}get ondelete(){return c(m(this,Hr))}set ondelete(N){M(m(this,Hr),N)}get onbeforedelete(){return c(m(this,Ui))}set onbeforedelete(N){M(m(this,Ui),N)}get onbeforeconnect(){return c(m(this,Li))}set onbeforeconnect(N){M(m(this,Li),N)}get onconnect(){return c(m(this,Vi))}set onconnect(N){M(m(this,Vi),N)}get onconnectstart(){return c(m(this,Wi))}set onconnectstart(N){M(m(this,Wi),N)}get onconnectend(){return c(m(this,Ti))}set onconnectend(N){M(m(this,Ti),N)}get onbeforereconnect(){return c(m(this,Di))}set onbeforereconnect(N){M(m(this,Di),N)}get onreconnect(){return c(m(this,Oi))}set onreconnect(N){M(m(this,Oi),N)}get onreconnectstart(){return c(m(this,Hi))}set onreconnectstart(N){M(m(this,Hi),N)}get onreconnectend(){return c(m(this,Mi))}set onreconnectend(N){M(m(this,Mi),N)}get clickConnect(){return c(m(this,Yi))}set clickConnect(N){M(m(this,Yi),N)}get onclickconnectstart(){return c(m(this,zi))}set onclickconnectstart(N){M(m(this,zi),N)}get onclickconnectend(){return c(m(this,Oo))}set onclickconnectend(N){M(m(this,Oo),N)}get clickConnectStartHandle(){return c(m(this,Ho))}set clickConnectStartHandle(N){M(m(this,Ho),N)}get onselectiondrag(){return c(m(this,Sr))}set onselectiondrag(N){M(m(this,Sr),N)}get onselectiondragstart(){return c(m(this,Mo))}set onselectiondragstart(N){M(m(this,Mo),N)}get onselectiondragstop(){return c(m(this,Mr))}set onselectiondragstop(N){M(m(this,Mr),N)}get colorMode(){return c(m(this,js))}set colorMode(N){M(m(this,js),N)}resetStoreValues(){this.dragging=!1,this.selectionRect=null,this.selectionRectMode=null,this.selectionKeyPressed=!1,this.multiselectionKeyPressed=!1,this.deleteKeyPressed=!1,this.panActivationKeyPressed=!1,this.zoomActivationKeyPressed=!1,this._connection=pl,this.clickConnectStartHandle=null,this.viewport=e.props.initialViewport??{x:0,y:0,zoom:1},this.ariaLiveMessage=""}}return r=new WeakMap,n=new WeakMap,o=new WeakMap,i=new WeakMap,s=new WeakMap,a=new WeakMap,l=new WeakMap,u=new WeakMap,f=new WeakMap,g=new WeakMap,d=new WeakMap,p=new WeakMap,h=new WeakMap,b=new WeakMap,x=new WeakMap,w=new WeakMap,C=new WeakMap,E=new WeakMap,y=new WeakMap,U=new WeakMap,B=new WeakMap,k=new WeakMap,G=new WeakMap,W=new WeakMap,H=new WeakMap,Z=new WeakMap,$=new WeakMap,X=new WeakMap,I=new WeakMap,A=new WeakMap,S=new WeakMap,T=new WeakMap,K=new WeakMap,Y=new WeakMap,z=new WeakMap,j=new WeakMap,re=new WeakMap,ae=new WeakMap,ne=new WeakMap,Ie=new WeakMap,fe=new WeakMap,ge=new WeakMap,pe=new WeakMap,we=new WeakMap,We=new WeakMap,Ze=new WeakMap,lt=new WeakMap,Le=new WeakMap,vt=new WeakMap,Ot=new WeakMap,ar=new WeakMap,yr=new WeakMap,Qe=new WeakMap,nt=new WeakMap,er=new WeakMap,Me=new WeakMap,Fr=new WeakMap,Or=new WeakMap,Hr=new WeakMap,Ui=new WeakMap,Li=new WeakMap,Vi=new WeakMap,Wi=new WeakMap,Ti=new WeakMap,Di=new WeakMap,Oi=new WeakMap,Hi=new WeakMap,Mi=new WeakMap,Yi=new WeakMap,zi=new WeakMap,Oo=new WeakMap,Ho=new WeakMap,Sr=new WeakMap,Mo=new WeakMap,Mr=new WeakMap,js=new WeakMap,new t}var Sg,Zg,$y=v(()=>{ie();Ke();mg();oy();iy();sy();Eg();wy();By();Sg={input:vg,output:_g,default:bl,group:bg},Zg={straight:yd,smoothstep:xd,default:Ds,step:Id}});function Nt(){let e=Pn(El);if(!e)throw new Error("To call useStore outside of you need to wrap your component in a ");return e.getStore()}var Ay=v(()=>{nn();ln()});function Gy(e){let t=Ey(e);function r(Z){t.nodeTypes={...Sg,...Z}}function n(Z){t.edgeTypes={...Zg,...Z}}function o(Z){t.edges=F0(Z,t.edges)}let i=(Z,$=!1)=>{t.nodes=t.nodes.map(X=>{if(t.connection.inProgress&&t.connection.fromNode.id===X.id){let A=t.nodeLookup.get(X.id);A&&(t.connection={...t.connection,from:Lo(A,t.connection.fromHandle,$e.Left,!0)})}let I=Z.get(X.id);return I?{...X,position:I.position,dragging:$}:X})};function s(Z){let{changes:$,updatedInternals:X}=R0(Z,t.nodeLookup,t.parentLookup,t.domNode,t.nodeOrigin,t.nodeExtent,t.zIndexMode);if(!X)return;N0(t.nodeLookup,t.parentLookup,{nodeOrigin:t.nodeOrigin,nodeExtent:t.nodeExtent,zIndexMode:t.zIndexMode}),t.fitViewQueued&&t.resolveFitView();let I=new Map;for(let A of $){let S=t.nodeLookup.get(A.id)?.internals.userNode;if(!S)continue;let T={...S};switch(A.type){case"dimensions":{let K={...T.measured,...A.dimensions};A.setAttributes&&(T.width=A.dimensions?.width??T.width,T.height=A.dimensions?.height??T.height),T.measured=K;break}case"position":T.position=A.position??T.position;break}I.set(A.id,T)}t.nodes=t.nodes.map(A=>I.get(A.id)??A)}function a(Z){let $=t.fitViewResolver??Promise.withResolvers();return t.fitViewQueued=!0,t.fitViewOptions=Z,t.fitViewResolver=$,t.nodes=[...t.nodes],$.promise}async function l(Z,$,X){let I=typeof X?.zoom<"u"?X.zoom:t.maxZoom,A=t.panZoom;return A?(await A.setViewport({x:t.width/2-Z*I,y:t.height/2-$*I,zoom:I},{duration:X?.duration,ease:X?.ease,interpolate:X?.interpolate}),Promise.resolve(!0)):Promise.resolve(!1)}function u(Z,$){let X=t.panZoom;return X?X.scaleBy(Z,$):Promise.resolve(!1)}function f(Z){return u(1.2,Z)}function g(Z){return u(1/1.2,Z)}function d(Z){let $=t.panZoom;$&&($.setScaleExtent([Z,t.maxZoom]),t.minZoom=Z)}function p(Z){let $=t.panZoom;$&&($.setScaleExtent([t.minZoom,Z]),t.maxZoom=Z)}function h(Z){let $=t.panZoom;$&&($.setTranslateExtent(Z),t.translateExtent=Z)}function b(Z,$=null){let X=!1,I=Z.map(A=>($?$.has(A.id):!0)&&A.selected?(X=!0,{...A,selected:!1}):A);return[X,I]}function x(Z){let $=Z?.nodes?new Set(Z.nodes.map(K=>K.id)):null,[X,I]=b(t.nodes,$);X&&(t.nodes=I);let A=Z?.edges?new Set(Z.edges.map(K=>K.id)):null,[S,T]=b(t.edges,A);S&&(t.edges=T)}function w(Z){let $=t.multiselectionKeyPressed;t.nodes=t.nodes.map(X=>{let I=Z.includes(X.id),A=$&&X.selected||I;return!!X.selected!==A?{...X,selected:A}:X}),$||x({nodes:[]})}function C(Z){let $=t.multiselectionKeyPressed;t.edges=t.edges.map(X=>{let I=Z.includes(X.id),A=$&&X.selected||I;return!!X.selected!==A?{...X,selected:A}:X}),$||x({edges:[]})}function E(Z,$,X){let I=t.nodeLookup.get(Z);if(!I){console.warn("012",Si.error012(Z));return}t.selectionRect=null,t.selectionRectMode=null,I.selected?($||I.selected&&t.multiselectionKeyPressed)&&(x({nodes:[I],edges:[]}),requestAnimationFrame(()=>X?.blur())):w([Z])}function y(Z){let $=t.edgeLookup.get(Z);if(!$){console.warn("012",Si.error012(Z));return}($.selectable||t.elementsSelectable&&typeof $.selectable>"u")&&(t.selectionRect=null,t.selectionRectMode=null,$.selected?$.selected&&t.multiselectionKeyPressed&&x({nodes:[],edges:[$]}):C([Z]))}function U(Z,$){let{nodeExtent:X,snapGrid:I,nodeOrigin:A,nodeLookup:S,nodesDraggable:T,onerror:K}=t,Y=new Map,z=I?.[0]??5,j=I?.[1]??5,re=Z.x*z*$,ae=Z.y*j*$;for(let ne of S.values()){if(!(ne.selected&&(ne.draggable||T&&typeof ne.draggable>"u")))continue;let fe={x:ne.internals.positionAbsolute.x+re,y:ne.internals.positionAbsolute.y+ae};I&&(fe=Ls(fe,I));let{position:ge,positionAbsolute:pe}=og({nodeId:ne.id,nextPosition:fe,nodeLookup:S,nodeExtent:X,nodeOrigin:A,onError:K});ne.position=ge,ne.internals.positionAbsolute=pe,Y.set(ne.id,ne)}i(Y)}function B(Z){return U0({delta:Z,panZoom:t.panZoom,transform:[t.viewport.x,t.viewport.y,t.viewport.zoom],translateExtent:t.translateExtent,width:t.width,height:t.height})}let k=Z=>{t._connection={...Z}};function G(){t._connection=pl}function W(){t.resetStoreValues(),x()}return Object.assign(t,{setNodeTypes:r,setEdgeTypes:n,addEdge:o,updateNodePositions:i,updateNodeInternals:s,zoomIn:f,zoomOut:g,fitView:a,setCenter:l,setMinZoom:d,setMaxZoom:p,setTranslateExtent:h,unselectNodesAndEdges:x,addSelectedNodes:w,addSelectedEdges:C,handleNodeSelection:E,handleEdgeSelection:y,moveSelectedNodes:U,panBy:B,updateConnection:k,cancelConnection:G,reset:W})}var El,ln=v(()=>{Ke();$y();Ay();El=Symbol()});function kg(e,t){let{minZoom:r,maxZoom:n,initialViewport:o,onPanZoomStart:i,onPanZoom:s,onPanZoomEnd:a,translateExtent:l,setPanZoomInstance:u,onDraggingChange:f,onTransformChange:g}=t,d=P0({domNode:e,minZoom:r,maxZoom:n,translateExtent:l,viewport:o,onPanZoom:s,onPanZoomStart:i,onPanZoomEnd:a,onDraggingChange:f}),p=d.getViewport();return(o.x!==p.x||o.y!==p.y||o.zoom!==p.zoom)&&g([p.x,p.y,p.zoom]),u(d),d.update(t),{update(h){d.update(h)}}}var Fy=v(()=>{Ke()});function Bd(e,t){q(t,!0);let r=P(t,"store",15),n=_(()=>r().panActivationKeyPressed||t.panOnDrag),o=_(()=>r().panActivationKeyPressed||t.panOnScroll),{viewport:i}=r(),s=!1;st(()=>{!s&&r().viewportInitialized&&(t.oninit?.(),s=!0)});var a=nA(),l=V(a);at(l,()=>t.children),Q(a),ft(a,(u,f)=>kg?.(u,f),()=>({viewport:r().viewport,minZoom:r().minZoom,maxZoom:r().maxZoom,initialViewport:i,onDraggingChange:u=>{r(r().dragging=u,!0)},setPanZoomInstance:u=>{r(r().panZoom=u,!0)},onPanZoomStart:t.onmovestart,onPanZoom:t.onmove,onPanZoomEnd:t.onmoveend,zoomOnScroll:t.zoomOnScroll,zoomOnDoubleClick:t.zoomOnDoubleClick,zoomOnPinch:t.zoomOnPinch,panOnScroll:c(o),panOnDrag:c(n),panOnScrollSpeed:t.panOnScrollSpeed,panOnScrollMode:t.panOnScrollMode,zoomActivationKeyPressed:r().zoomActivationKeyPressed,preventScrolling:typeof t.preventScrolling=="boolean"?t.preventScrolling:!0,noPanClassName:r().noPanClass,noWheelClassName:r().noWheelClass,userSelectionActive:!!r().selectionRect,translateExtent:r().translateExtent,lib:"svelte",paneClickDistance:t.paneClickDistance,selectionOnDrag:t.selectionOnDrag,onTransformChange:u=>{r(r().viewport={x:u[0],y:u[1],zoom:u[2]},!0)},connectionInProgress:r().connection.inProgress})),F(e,a),ee()}var nA,Sy=v(()=>{ve();ie();Fy();nA=J('
            ')});var Zy=v(()=>{Sy()});function ky(e,t){return r=>{r.target===t&&e?.(r)}}function Ny(e){return t=>{let r=e.has(t.id);return!!t.selected!==r?{...t,selected:r}:t}}function Qy(e,t){if(e.size!==t.size)return!1;for(let r of e)if(!t.has(r))return!1;return!0}function Ed(e,t){q(t,!0);let r=P(t,"store",15),n=P(t,"panOnDrag",3,!0),o=P(t,"paneClickDistance",3,1),i,s=null,a=new Set,l=new Set,u=_(()=>r().panActivationKeyPressed||n()),f=_(()=>r().selectionKeyPressed||!!r().selectionRect||t.selectionOnDrag&&c(u)!==!0),g=_(()=>r().elementsSelectable&&(c(f)||r().selectionRectMode==="user")),d=!1;function p(G){if(s=i?.getBoundingClientRect(),!s)return;let W=G.target===i,H=!W&&!!G.target.closest(".nokey"),Z=t.selectionOnDrag&&W||r().selectionKeyPressed;if(H||!c(f)||!Z||G.button!==0||!G.isPrimary)return;G.target?.setPointerCapture?.(G.pointerId),d=!1;let{x:$,y:X}=an(G,s);r(r().selectionRect={width:0,height:0,startX:$,startY:X,x:$,y:X},!0),W||(G.stopPropagation(),G.preventDefault())}function h(G){if(!c(f)||!s||!r().selectionRect)return;let W=an(G,s),{startX:H=0,startY:Z=0}=r().selectionRect;if(!d){let S=r().selectionKeyPressed?0:o();if(Math.hypot(W.x-H,W.y-Z)<=S)return;r().unselectNodesAndEdges(),t.onselectionstart?.(G)}d=!0;let $={...r().selectionRect,x:W.xS.id));let A=r().defaultEdgeOptions.selectable??!0;l=new Set;for(let S of a){let T=r().connectionLookup.get(S);if(T)for(let{edgeId:K}of T.values()){let Y=r().edgeLookup.get(K);Y&&(Y.selectable??A)&&l.add(K)}}Qy(X,a)||r(r().nodes=r().nodes.map(Ny(a)),!0),Qy(I,l)||r(r().edges=r().edges.map(Ny(l)),!0),r(r().selectionRectMode="user",!0),r(r().selectionRect=$,!0)}function b(G){G.button===0&&(G.target?.releasePointerCapture?.(G.pointerId),!d&&G.target===i&&C?.(G),r(r().selectionRect=null,!0),d&&r(r().selectionRectMode=a.size>0?"nodes":null,!0),d&&t.onselectionend?.(G))}let x=G=>{if(Array.isArray(c(u))&&c(u).includes(2)){G.preventDefault();return}t.onpanecontextmenu?.({event:G})},w=G=>{d&&(G.stopPropagation(),d=!1)};function C(G){if(d||r().connection.inProgress){d=!1;return}t.onpaneclick?.({event:G}),r().unselectNodesAndEdges(),r(r().selectionRectMode=null,!0),r(r().selectionRect=null,!0)}var E=oA();let y;var U=_(()=>c(g)?void 0:ky(C,i)),B=_(()=>ky(x,i)),k=V(E);at(k,()=>t.children),Q(E),Dr(E,G=>i=G,()=>i),te(G=>y=Je(E,1,"svelte-flow__pane svelte-flow__container",null,y,G),[()=>({draggable:n()===!0||Array.isArray(n())&&n().includes(0),dragging:r().dragging,selection:c(f)})]),St("click",E,function(...G){c(U)?.apply(this,G)}),Ft("pointerdown",E,function(...G){(c(g)?p:void 0)?.apply(this,G)},!0),St("pointermove",E,function(...G){(c(g)?h:void 0)?.apply(this,G)}),St("pointerup",E,function(...G){(c(g)?b:void 0)?.apply(this,G)}),St("contextmenu",E,function(...G){c(B)?.apply(this,G)}),Ft("click",E,function(...G){(c(g)?w:void 0)?.apply(this,G)},!0),F(e,E),ee()}var oA,Xy=v(()=>{ve();ie();Ke();oA=J("
            ");yn(["click","pointermove","pointerup","contextmenu"])});var Ry=v(()=>{});var Uy=v(()=>{Xy();Ry()});function $d(e,t){q(t,!0);var r=iA();let n;var o=V(r);at(o,()=>t.children),Q(r),te(()=>n=Oe(r,"",n,{transform:`translate(${t.store.viewport.x??""}px, ${t.store.viewport.y??""}px) scale(${t.store.viewport.zoom??""})`})),F(e,r),ee()}var iA,Ly=v(()=>{ve();ie();iA=J('
            ')});var Vy=v(()=>{Ly()});function $l(e,t){let{store:r,onDrag:n,onDragStart:o,onDragStop:i,onNodeMouseDown:s}=t,a=W0({onDrag:n,onDragStart:o,onDragStop:i,onNodeMouseDown:s,getStoreItems:()=>{let{snapGrid:u,viewport:f}=r;return{nodes:r.nodes,nodeLookup:r.nodeLookup,edges:r.edges,nodeExtent:r.nodeExtent,snapGrid:u||[0,0],snapToGrid:!!u,nodeOrigin:r.nodeOrigin,multiSelectionActive:r.multiselectionKeyPressed,domNode:r.domNode,transform:[f.x,f.y,f.zoom],autoPanOnNodeDrag:r.autoPanOnNodeDrag,nodesDraggable:r.nodesDraggable,selectNodesOnDrag:r.selectNodesOnDrag,nodeDragThreshold:r.nodeDragThreshold,unselectNodesAndEdges:r.unselectNodesAndEdges,updateNodePositions:r.updateNodePositions,onSelectionDrag:r.onselectiondrag,onSelectionDragStart:r.onselectiondragstart,onSelectionDragStop:r.onselectiondragstop,panBy:r.panBy}}});function l(u,f){if(f.disabled){a.destroy();return}a.update({domNode:u,noDragClassName:f.noDragClass,handleSelector:f.handleSelector,nodeId:f.nodeId,isSelectable:f.isSelectable,nodeClickDistance:f.nodeClickDistance})}return l(e,t),{update(u){l(e,u)},destroy(){a.destroy()}}}var Ng=v(()=>{Ke()});var Wy=v(()=>{});function Ad(e,t){q(t,!0);var r=aA(),n=le(r),o=V(n,!0);Q(n);var i=O(n,2),s=V(i,!0);Q(i);var a=O(i,2);{var l=u=>{var f=sA(),g=V(f,!0);Q(f),te(()=>{D(f,"id",`${Dy}-${t.store.flowId}`),oe(g,t.store.ariaLiveMessage)}),F(u,f)};ce(a,u=>{t.store.disableKeyboardA11y||u(l)})}te(()=>{D(n,"id",`${Gd}-${t.store.flowId}`),oe(o,t.store.disableKeyboardA11y?t.store.ariaLabelConfig["node.a11yDescription.default"]:t.store.ariaLabelConfig["node.a11yDescription.keyboardDisabled"]),D(i,"id",`${Fd}-${t.store.flowId}`),oe(s,t.store.ariaLabelConfig["edge.a11yDescription.default"])}),F(e,r),ee()}var sA,aA,Ty=v(()=>{ve();ie();Al();Wy();sA=J('
            '),aA=J('
            ',1)});var Gd,Fd,Dy,Al=v(()=>{Ty();Gd="svelte-flow__node-desc",Fd="svelte-flow__edge-desc",Dy="svelte-flow__aria-live"});function Sd(e,t){q(t,!0);let r=P(t,"store",15),n=_(()=>Qt(t.node.data,()=>({}),!0)),o=_(()=>Qt(t.node.selected,!1)),i=_(()=>t.node.draggable),s=_(()=>t.node.selectable),a=_(()=>Qt(t.node.deletable,!0)),l=_(()=>t.node.connectable),u=_(()=>t.node.focusable),f=_(()=>Qt(t.node.hidden,!1)),g=_(()=>Qt(t.node.dragging,!1)),d=_(()=>Qt(t.node.style,"")),p=_(()=>t.node.class),h=_(()=>Qt(t.node.type,"default")),b=_(()=>t.node.parentId),x=_(()=>t.node.sourcePosition),w=_(()=>t.node.targetPosition),C=_(()=>Qt(t.node.measured,()=>({width:0,height:0}),!0).width),E=_(()=>Qt(t.node.measured,()=>({width:0,height:0}),!0).height),y=_(()=>t.node.initialWidth),U=_(()=>t.node.initialHeight),B=_(()=>t.node.width),k=_(()=>t.node.height),G=_(()=>t.node.dragHandle),W=_(()=>Qt(t.node.internals.z,0)),H=_(()=>t.node.internals.positionAbsolute.x),Z=_(()=>t.node.internals.positionAbsolute.y),$=_(()=>t.node.internals.userNode),{id:X}=t.node,I=_(()=>c(i)??r().nodesDraggable),A=_(()=>c(s)??r().elementsSelectable),S=_(()=>c(l)??r().nodesConnectable),T=_(()=>pd(t.node)),K=_(()=>!!t.node.internals.handleBounds),Y=_(()=>c(T)&&c(K)),z=_(()=>c(u)??r().nodesFocusable);function j(Qe){return r().parentLookup.has(Qe)}let re=_(()=>j(X)),ae=ye(null),ne=null,Ie=c(h),fe=c(x),ge=c(w),pe=_(()=>r().nodeTypes[c(h)]??bl),we=_(()=>r().ariaLabelConfig),We={get value(){return c(S)}};j0(X),q0(We);let Ze=_(()=>{let Qe=c(C)===void 0?c(B)??c(y):c(B),nt=c(E)===void 0?c(k)??c(U):c(k);if(!(Qe===void 0&&nt===void 0&&c(d)===void 0))return`${c(d)};${Qe?`width:${xr(Qe)};`:""}${nt?`height:${xr(nt)};`:""}`});st(()=>{(c(h)!==Ie||c(x)!==fe||c(w)!==ge)&&c(ae)!==null&&requestAnimationFrame(()=>{c(ae)!==null&&r().updateNodeInternals(new Map([[X,{id:X,nodeElement:c(ae),force:!0}]]))}),Ie=c(h),fe=c(x),ge=c(w)}),st(()=>{t.resizeObserver&&(!c(Y)||c(ae)!==ne)&&(ne&&t.resizeObserver.unobserve(ne),c(ae)&&t.resizeObserver.observe(c(ae)),ne=c(ae))}),_i(()=>{ne&&t.resizeObserver?.unobserve(ne)});function lt(Qe){c(A)&&(!r().selectNodesOnDrag||!c(I)||r().nodeDragThreshold>0)&&r().handleNodeSelection(X),t.onnodeclick?.({node:c($),event:Qe})}function Le(Qe){if(!(hd(Qe)||r().disableKeyboardA11y))if(ud.includes(Qe.key)&&c(A)){let nt=Qe.key==="Escape";r().handleNodeSelection(X,nt,c(ae))}else c(I)&&t.node.selected&&Object.prototype.hasOwnProperty.call(Ts,Qe.key)&&(Qe.preventDefault(),r(r().ariaLiveMessage=c(we)["node.a11yDescription.ariaLiveMessage"]({direction:Qe.key.replace("Arrow","").toLowerCase(),x:~~t.node.internals.positionAbsolute.x,y:~~t.node.internals.positionAbsolute.y}),!0),r().moveSelectedNodes(Ts[Qe.key],Qe.shiftKey?4:1))}let vt=()=>{if(r().disableKeyboardA11y||!r().autoPanOnNodeFocus||!c(ae)?.matches(":focus-visible"))return;let{width:Qe,height:nt,viewport:er}=r();Rs(new Map([[X,t.node]]),{x:0,y:0,width:Qe,height:nt},[er.x,er.y,er.zoom],!0).length>0||r().setCenter(t.node.position.x+(t.node.measured.width??0)/2,t.node.position.y+(t.node.measured.height??0)/2,{zoom:er.zoom})};var Ot=Xe(),ar=le(Ot);{var yr=Qe=>{var nt=lA();Jt(nt,()=>({"data-id":X,class:["svelte-flow__node",`svelte-flow__node-${c(h)}`,c(p)],style:c(Ze),onclick:lt,onpointerenter:t.onnodepointerenter?Me=>t.onnodepointerenter({node:c($),event:Me}):void 0,onpointerleave:t.onnodepointerleave?Me=>t.onnodepointerleave({node:c($),event:Me}):void 0,onpointermove:t.onnodepointermove?Me=>t.onnodepointermove({node:c($),event:Me}):void 0,oncontextmenu:t.onnodecontextmenu?Me=>t.onnodecontextmenu({node:c($),event:Me}):void 0,onkeydown:c(z)?Le:void 0,onfocus:c(z)?vt:void 0,tabIndex:c(z)?0:void 0,role:t.node.ariaRole??(c(z)?"group":void 0),"aria-roledescription":"node","aria-describedby":r().disableKeyboardA11y?void 0:`${Gd}-${r().flowId}`,...t.node.domAttributes,[on]:{dragging:c(g),selected:c(o),draggable:c(I),connectable:c(S),selectable:c(A),nopan:c(I),parent:c(re)},[Er]:{"z-index":c(W),transform:`translate(${c(H)??""}px, ${c(Z)??""}px)`,visibility:c(T)?"visible":"hidden"}}));var er=V(nt);io(er,()=>c(pe),(Me,Fr)=>{Fr(Me,{get data(){return c(n)},get id(){return X},get selected(){return c(o)},get selectable(){return c(A)},get deletable(){return c(a)},get sourcePosition(){return c(x)},get targetPosition(){return c(w)},get zIndex(){return c(W)},get dragging(){return c(g)},get draggable(){return c(I)},get dragHandle(){return c(G)},get parentId(){return c(b)},get type(){return c(h)},get isConnectable(){return c(S)},get positionAbsoluteX(){return c(H)},get positionAbsoluteY(){return c(Z)},get width(){return c(B)},get height(){return c(k)}})}),Q(nt),ft(nt,(Me,Fr)=>$l?.(Me,Fr),()=>({nodeId:X,isSelectable:c(A),disabled:!c(I),handleSelector:c(G),noDragClass:r().noDragClass,nodeClickDistance:t.nodeClickDistance,onNodeMouseDown:r().handleNodeSelection,onDrag:(Me,Fr,Or,Hr)=>{t.onnodedrag?.({event:Me,targetNode:Or,nodes:Hr})},onDragStart:(Me,Fr,Or,Hr)=>{t.onnodedragstart?.({event:Me,targetNode:Or,nodes:Hr})},onDragStop:(Me,Fr,Or,Hr)=>{t.onnodedragstop?.({event:Me,targetNode:Or,nodes:Hr})},store:r()})),Dr(nt,Me=>M(ae,Me),()=>c(ae)),F(Qe,nt)};ce(ar,Qe=>{c(f)||Qe(yr)})}F(e,Ot),ee()}var lA,Oy=v(()=>{ve();ie();nn();Ke();Ng();vl();Wo();Al();mg();lA=J("
            ")});var Hy=v(()=>{Oy()});function Zd(e,t){q(t,!0);let r=P(t,"store",15),n=typeof ResizeObserver>"u"?null:new ResizeObserver(i=>{let s=new Map;i.forEach(a=>{let l=a.target.getAttribute("data-id");s.set(l,{id:l,nodeElement:a.target,force:!0})}),r().updateNodeInternals(s)});_i(()=>{n?.disconnect()});var o=cA();Ne(o,21,()=>r().visible.nodes.values(),i=>i.id,(i,s)=>{Sd(i,{get node(){return c(s)},get resizeObserver(){return n},get nodeClickDistance(){return t.nodeClickDistance},get onnodeclick(){return t.onnodeclick},get onnodepointerenter(){return t.onnodepointerenter},get onnodepointermove(){return t.onnodepointermove},get onnodepointerleave(){return t.onnodepointerleave},get onnodedrag(){return t.onnodedrag},get onnodedragstart(){return t.onnodedragstart},get onnodedragstop(){return t.onnodedragstop},get onnodecontextmenu(){return t.onnodecontextmenu},get store(){return r()},set store(a){r(a)}})}),Q(o),F(e,o),ee()}var cA,My=v(()=>{ve();ie();nn();Hy();cA=J('
            ')});var Yy=v(()=>{My()});function kd(e,t){q(t,!0);let r=_(()=>t.edge.id),n=_(()=>t.edge.source),o=_(()=>t.edge.target),i=_(()=>t.edge.sourceX),s=_(()=>t.edge.sourceY),a=_(()=>t.edge.targetX),l=_(()=>t.edge.targetY),u=_(()=>t.edge.sourcePosition),f=_(()=>t.edge.targetPosition),g=_(()=>Qt(t.edge.animated,!1)),d=_(()=>Qt(t.edge.selected,!1)),p=_(()=>t.edge.label),h=_(()=>t.edge.labelStyle),b=_(()=>Qt(t.edge.data,()=>({}),!0)),x=_(()=>t.edge.style),w=_(()=>t.edge.interactionWidth),C=_(()=>Qt(t.edge.type,"default")),E=_(()=>t.edge.sourceHandle),y=_(()=>t.edge.targetHandle),U=_(()=>t.edge.markerStart),B=_(()=>t.edge.markerEnd),k=_(()=>t.edge.selectable),G=_(()=>t.edge.focusable),W=_(()=>Qt(t.edge.deletable,!0)),H=_(()=>t.edge.hidden),Z=_(()=>t.edge.zIndex),$=_(()=>t.edge.class),X=_(()=>t.edge.ariaLabel);ty(c(r));let I=null,A=_(()=>c(k)??t.store.elementsSelectable),S=_(()=>c(G)??t.store.edgesFocusable),T=_(()=>t.store.edgeTypes[c(C)]??Ds),K=_(()=>c(U)?`url('#${_d(c(U),t.store.flowId)}')`:void 0),Y=_(()=>c(B)?`url('#${_d(c(B),t.store.flowId)}')`:void 0);function z(fe){let ge=t.store.edgeLookup.get(c(r));ge&&(c(A)&&t.store.handleEdgeSelection(c(r)),t.onedgeclick?.({event:fe,edge:ge}))}function j(fe,ge){let pe=t.store.edgeLookup.get(c(r));pe&&ge({event:fe,edge:pe})}function re(fe){if(!t.store.disableKeyboardA11y&&ud.includes(fe.key)&&c(A)){let{unselectNodesAndEdges:ge,addSelectedEdges:pe}=t.store;fe.key==="Escape"?(I?.blur(),ge({edges:[t.edge]})):pe([c(r)])}}var ae=Xe(),ne=le(ae);{var Ie=fe=>{var ge=dA();let pe;var we=V(ge);Jt(we,()=>({class:["svelte-flow__edge",c($)],"data-id":c(r),onclick:z,oncontextmenu:t.onedgecontextmenu?Ze=>{j(Ze,t.onedgecontextmenu)}:void 0,onpointerenter:t.onedgepointerenter?Ze=>{j(Ze,t.onedgepointerenter)}:void 0,onpointerleave:t.onedgepointerleave?Ze=>{j(Ze,t.onedgepointerleave)}:void 0,"aria-label":c(X)===null?void 0:c(X)?c(X):`Edge from ${c(n)} to ${c(o)}`,"aria-describedby":c(S)?`${Fd}-${t.store.flowId}`:void 0,role:t.edge.ariaRole??(c(S)?"group":"img"),"aria-roledescription":"edge",onkeydown:c(S)?re:void 0,tabindex:c(S)?0:void 0,...t.edge.domAttributes,[on]:{animated:c(g),selected:c(d),selectable:c(A)}}));var We=V(we);io(We,()=>c(T),(Ze,lt)=>{lt(Ze,{get id(){return c(r)},get source(){return c(n)},get target(){return c(o)},get sourceX(){return c(i)},get sourceY(){return c(s)},get targetX(){return c(a)},get targetY(){return c(l)},get sourcePosition(){return c(u)},get targetPosition(){return c(f)},get animated(){return c(g)},get selected(){return c(d)},get label(){return c(p)},get labelStyle(){return c(h)},get data(){return c(b)},get style(){return c(x)},get interactionWidth(){return c(w)},get selectable(){return c(A)},get deletable(){return c(W)},get type(){return c(C)},get sourceHandleId(){return c(E)},get targetHandleId(){return c(y)},get markerStart(){return c(K)},get markerEnd(){return c(Y)}})}),Q(we),Dr(we,Ze=>I=Ze,()=>I),Q(ge),te(()=>pe=Oe(ge,"",pe,{"z-index":c(Z)})),F(fe,ge)};ce(ne,fe=>{c(H)||fe(Ie)})}F(e,ae),ee()}var dA,zy=v(()=>{ve();ie();Ke();vl();Eg();Al();dA=Ge('')});var Py=v(()=>{zy()});var To=v(()=>{lr();hh()});function Nd(e,t){q(t,!1);let r=Nt();uf();var n=uA();Ne(n,5,()=>r.markers,o=>o.id,(o,i)=>{Qd(o,Cn(()=>c(i)))}),Q(n),F(e,n),ee()}var uA,Jy=v(()=>{ve();To();ie();ln();Qg();uA=Ge("")});function Qd(e,t){q(t,!0);let r=P(t,"width",3,12.5),n=P(t,"height",3,12.5),o=P(t,"markerUnits",3,"strokeWidth"),i=P(t,"orient",3,"auto-start-reverse"),s=P(t,"color",3,"none");var a=pA(),l=V(a);{var u=g=>{var d=fA();let p;te(()=>{D(d,"stroke-width",t.strokeWidth),p=Oe(d,"",p,{stroke:s()})}),F(g,d)},f=g=>{var d=gA();let p;te(()=>{D(d,"stroke-width",t.strokeWidth),p=Oe(d,"",p,{stroke:s(),fill:s()})}),F(g,d)};ce(l,g=>{t.type===fl.Arrow?g(u):t.type===fl.ArrowClosed&&g(f,1)})}Q(a),te(()=>{D(a,"id",t.id),D(a,"markerWidth",`${r()}`),D(a,"markerHeight",`${n()}`),D(a,"markerUnits",o()),D(a,"orient",i())}),F(e,a),ee()}var fA,gA,pA,jy=v(()=>{ve();ie();Ke();fA=Ge(''),gA=Ge(''),pA=Ge('')});var Qg=v(()=>{Jy();jy()});function Xd(e,t){q(t,!0);let r=P(t,"store",15);var n=hA(),o=V(n),i=V(o);Nd(i,{}),Q(o);var s=O(o,2);Ne(s,17,()=>r().visible.edges.values(),a=>a.id,(a,l)=>{kd(a,{get edge(){return c(l)},get onedgeclick(){return t.onedgeclick},get onedgecontextmenu(){return t.onedgecontextmenu},get onedgepointerenter(){return t.onedgepointerenter},get onedgepointerleave(){return t.onedgepointerleave},get store(){return r()},set store(u){r(u)}})}),Q(n),F(e,n),ee()}var hA,Ky=v(()=>{ve();ie();Py();Qg();hA=J('
            ')});var qy=v(()=>{Ky()});var eI=v(()=>{});function Os(e,t){q(t,!0);let r=P(t,"x",3,0),n=P(t,"y",3,0),o=P(t,"width",3,0),i=P(t,"height",3,0),s=P(t,"isVisible",3,!0);var a=Xe(),l=le(a);{var u=f=>{var g=mA();let d;te(p=>d=Oe(g,"",d,p),[()=>({width:typeof o()=="string"?o():xr(o()),height:typeof i()=="string"?i():xr(i()),transform:`translate(${r()}px, ${n()}px)`})]),F(f,g)};ce(l,f=>{s()&&f(u)})}F(e,a),ee()}var mA,tI=v(()=>{ve();ie();Wo();eI();mA=J('
            ')});var Xg=v(()=>{tI()});var rI=v(()=>{});function Rd(e,t){q(t,!0);let r=ye(void 0);st(()=>{t.store.disableKeyboardA11y||c(r)?.focus({preventScroll:!0})});let n=_(()=>{if(t.store.selectionRectMode==="nodes"){t.store.nodes;let g=Vo(t.store.nodeLookup,{filter:d=>!!d.selected});if(g.width>0&&g.height>0)return g}return null});function o(g){let d=t.store.nodes.filter(p=>p.selected);t.onselectioncontextmenu?.({nodes:d,event:g})}function i(g){let d=t.store.nodes.filter(p=>p.selected);t.onselectionclick?.({nodes:d,event:g})}function s(g){Object.prototype.hasOwnProperty.call(Ts,g.key)&&(g.preventDefault(),t.store.moveSelectedNodes(Ts[g.key],g.shiftKey?4:1))}var a=Xe(),l=le(a);{var u=g=>{var d=vA();let p;var h=V(d);Os(h,{width:"100%",height:"100%",x:0,y:0}),Q(d),ft(d,(b,x)=>$l?.(b,x),()=>({disabled:!1,store:t.store,onDrag:(b,x,w,C)=>{t.onnodedrag?.({event:b,targetNode:null,nodes:C})},onDragStart:(b,x,w,C)=>{t.onnodedragstart?.({event:b,targetNode:null,nodes:C})},onDragStop:(b,x,w,C)=>{t.onnodedragstop?.({event:b,targetNode:null,nodes:C})}})),Dr(d,b=>M(r,b),()=>c(r)),te(b=>{Je(d,1,Pt(["svelte-flow__selection-wrapper",t.store.noPanClass]),"svelte-sf2y5e"),D(d,"role",t.store.disableKeyboardA11y?void 0:"button"),D(d,"tabindex",t.store.disableKeyboardA11y?void 0:-1),p=Oe(d,"",p,b)},[()=>({width:xr(c(n).width),height:xr(c(n).height),transform:`translate(${c(n).x??""}px, ${c(n).y??""}px)`})]),St("contextmenu",d,o),St("click",d,i),St("keydown",d,function(...b){(t.store.disableKeyboardA11y?void 0:s)?.apply(this,b)}),F(g,d)},f=_(()=>t.store.selectionRectMode==="nodes"&&c(n)&&Tn(c(n).x)&&Tn(c(n).y));ce(l,g=>{c(f)&&g(u)})}F(e,a),ee()}var vA,nI=v(()=>{ve();ie();Ke();Xg();Ng();Wo();rI();vA=J("
            ");yn(["contextmenu","click","keydown"])});var oI=v(()=>{nI()});function _A(e){switch(e){case"ctrl":return 8;case"shift":return 4;case"alt":return 2;case"meta":return 1}}function cn(e,t){let{enabled:r=!0,trigger:n,type:o="keydown"}=t;function i(a){let l=Array.isArray(n)?n:[n],u=[a.metaKey,a.altKey,a.shiftKey,a.ctrlKey].reduce((f,g,d)=>g?f|1<0){let C=Array.isArray(d)?d:[d],E=!1;for(let y of C)if((Array.isArray(y)?y:[y]).reduce((B,k)=>B|_A(k),0)===u){E=!0;break}if(!E)continue}b&&a.preventDefault();let w={node:e,trigger:g,originalEvent:a};e.dispatchEvent(new CustomEvent("shortcut",{detail:w})),h?.(w)}}}let s;return r&&(s=gi(e,o,i)),{update:a=>{let{enabled:l=!0,type:u="keydown"}=a;r&&(!l||o!==u)?s?.():!r&&l&&(s=gi(e,u,i)),r=l,o=u,n=a.trigger},destroy:()=>{s?.()}}}var iI=v(()=>{Gg()});var sI=v(()=>{});var aI=v(()=>{iI();sI()});function cI(){let e=_(Nt),t=i=>{let s=Cg(i)?i:c(e).nodeLookup.get(i.id),a=s.parentId?C0(s.position,s.measured,s.parentId,c(e).nodeLookup,c(e).nodeOrigin):s.position,l={...s,position:a,width:s.measured?.width??s.width,height:s.measured?.height??s.height};return ki(l)};function r(i,s,a={replace:!1}){c(e).nodes=ke(()=>c(e).nodes).map(l=>{if(l.id===i){let u=typeof s=="function"?s(l):s;return a?.replace&&Cg(u)?u:{...l,...u}}return l})}function n(i,s,a={replace:!1}){c(e).edges=ke(()=>c(e).edges).map(l=>{if(l.id===i){let u=typeof s=="function"?s(l):s;return a.replace&&cy(u)?u:{...l,...u}}return l})}let o=i=>c(e).nodeLookup.get(i);return{zoomIn:c(e).zoomIn,zoomOut:c(e).zoomOut,getInternalNode:o,getNode:i=>o(i)?.internals.userNode,getNodes:i=>i===void 0?c(e).nodes:lI(c(e).nodeLookup,i),getEdge:i=>c(e).edgeLookup.get(i),getEdges:i=>i===void 0?c(e).edges:lI(c(e).edgeLookup,i),setZoom:(i,s)=>{let a=c(e).panZoom;return a?a.scaleTo(i,s):Promise.resolve(!1)},getZoom:()=>c(e).viewport.zoom,setViewport:async(i,s)=>{let a=c(e).viewport;return c(e).panZoom?(await c(e).panZoom.setViewport({x:i.x??a.x,y:i.y??a.y,zoom:i.zoom??a.zoom},s),Promise.resolve(!0)):Promise.resolve(!1)},getViewport:()=>Yn(c(e).viewport),setCenter:async(i,s,a)=>c(e).setCenter(i,s,a),fitView:i=>c(e).fitView(i),fitBounds:async(i,s)=>{if(!c(e).panZoom)return Promise.resolve(!1);let a=ml(i,c(e).width,c(e).height,c(e).minZoom,c(e).maxZoom,s?.padding??.1);return await c(e).panZoom.setViewport(a,{duration:s?.duration,ease:s?.ease,interpolate:s?.interpolate}),Promise.resolve(!0)},getIntersectingNodes:(i,s=!0,a)=>{let l=sg(i),u=l?i:t(i);return u?(a||c(e).nodes).filter(f=>{let g=c(e).nodeLookup.get(f.id);if(!g||!l&&f.id===i.id)return!1;let d=ki(g),p=Us(d,u);return s&&p>0||p>=d.width*d.height||p>=u.width*u.height}):[]},isNodeIntersecting:(i,s,a=!0)=>{let u=sg(i)?i:t(i);if(!u)return!1;let f=Us(u,s);return a&&f>0||f>=s.width*s.height||f>=u.width*u.height},deleteElements:async({nodes:i=[],edges:s=[]})=>{let{nodes:a,edges:l}=await y0({nodesToRemove:i,edgesToRemove:s,nodes:c(e).nodes,edges:c(e).edges,onBeforeDelete:c(e).onbeforedelete});return a&&(c(e).nodes=ke(()=>c(e).nodes).filter(u=>!a.some(({id:f})=>f===u.id))),l&&(c(e).edges=ke(()=>c(e).edges).filter(u=>!l.some(({id:f})=>f===u.id))),(a.length>0||l.length>0)&&c(e).ondelete?.({nodes:a,edges:l}),{deletedNodes:a,deletedEdges:l}},screenToFlowPosition:(i,s={snapToGrid:!0})=>{if(!c(e).domNode)return i;let a=s.snapToGrid?c(e).snapGrid:!1,{x:l,y:u,zoom:f}=c(e).viewport,{x:g,y:d}=c(e).domNode.getBoundingClientRect(),p={x:i.x-g,y:i.y-d};return Ni(p,[l,u,f],a!==null,a||[1,1])},flowToScreenPosition:i=>{if(!c(e).domNode)return i;let{x:s,y:a,zoom:l}=c(e).viewport,{x:u,y:f}=c(e).domNode.getBoundingClientRect(),g=gl(i,[s,a,l]);return{x:g.x+u,y:g.y+f}},toObject:()=>structuredClone({nodes:[...c(e).nodes],edges:[...c(e).edges],viewport:{...c(e).viewport}}),updateNode:r,updateNodeData:(i,s,a)=>{let l=c(e).nodeLookup.get(i)?.internals.userNode;if(!l)return;let u=typeof s=="function"?s(l):s;r(i,f=>({...f,data:a?.replace?u:{...f.data,...u}}))},updateEdge:n,getNodesBounds:i=>b0(i,{nodeLookup:c(e).nodeLookup,nodeOrigin:c(e).nodeOrigin}),getHandleConnections:({type:i,id:s,nodeId:a})=>Array.from(c(e).connectionLookup.get(`${a}-${i}-${s??null}`)?.values()??[])}}function lI(e,t){let r=[];for(let n of t){let o=e.get(n);if(o){let i="internals"in o?o.internals?.userNode:o;r.push(i)}}return r}var Rg=v(()=>{ie();Ke();ln();Wo();nn()});function Ud(e,t){q(t,!0);let r=P(t,"store",15),n=P(t,"selectionKey",3,"Shift"),o=P(t,"multiSelectionKey",19,()=>Vs()?"Meta":"Control"),i=P(t,"deleteKey",3,"Backspace"),s=P(t,"panActivationKey",3," "),a=P(t,"zoomActivationKey",19,()=>Vs()?"Meta":"Control"),{deleteElements:l}=cI();function u(b){return b!==null&&typeof b=="object"}function f(b){return u(b)?b.modifier||[]:[]}function g(b){return b==null?"":u(b)?b.key:b}function d(b,x){return(Array.isArray(b)?b:[b]).map(C=>{let E=g(C);return{key:E,modifier:f(C),enabled:E!==null,callback:x}})}function p(){r(r().selectionRect=null,!0),r(r().selectionKeyPressed=!1,!0),r(r().multiselectionKeyPressed=!1,!0),r(r().deleteKeyPressed=!1,!0),r(r().panActivationKeyPressed=!1,!0),r(r().zoomActivationKeyPressed=!1,!0)}function h(){let b=r().nodes.filter(w=>w.selected),x=r().edges.filter(w=>w.selected);l({nodes:b,edges:x})}Ft("blur",or,p),Ft("contextmenu",or,p),ft(or,(b,x)=>cn?.(b,x),()=>({trigger:d(n(),()=>r(r().selectionKeyPressed=!0,!0)),type:"keydown"})),ft(or,(b,x)=>cn?.(b,x),()=>({trigger:d(n(),()=>r(r().selectionKeyPressed=!1,!0)),type:"keyup"})),ft(or,(b,x)=>cn?.(b,x),()=>({trigger:d(o(),()=>{r(r().multiselectionKeyPressed=!0,!0)}),type:"keydown"})),ft(or,(b,x)=>cn?.(b,x),()=>({trigger:d(o(),()=>r(r().multiselectionKeyPressed=!1,!0)),type:"keyup"})),ft(or,(b,x)=>cn?.(b,x),()=>({trigger:d(i(),b=>{!(b.originalEvent.ctrlKey||b.originalEvent.metaKey||b.originalEvent.shiftKey)&&!hd(b.originalEvent)&&(r(r().deleteKeyPressed=!0,!0),h())}),type:"keydown"})),ft(or,(b,x)=>cn?.(b,x),()=>({trigger:d(i(),()=>r(r().deleteKeyPressed=!1,!0)),type:"keyup"})),ft(or,(b,x)=>cn?.(b,x),()=>({trigger:d(s(),()=>r(r().panActivationKeyPressed=!0,!0)),type:"keydown"})),ft(or,(b,x)=>cn?.(b,x),()=>({trigger:d(s(),()=>r(r().panActivationKeyPressed=!1,!0)),type:"keyup"})),ft(or,(b,x)=>cn?.(b,x),()=>({trigger:d(a(),()=>r(r().zoomActivationKeyPressed=!0,!0)),type:"keydown"})),ft(or,(b,x)=>cn?.(b,x),()=>({trigger:d(a(),()=>r(r().zoomActivationKeyPressed=!1,!0)),type:"keyup"})),ee()}var dI=v(()=>{ve();ie();aI();Ke();Rg()});var uI=v(()=>{dI()});function Ld(e,t){q(t,!0);let r=_(()=>{if(!t.store.connection.inProgress)return"";let s={sourceX:t.store.connection.from.x,sourceY:t.store.connection.from.y,sourcePosition:t.store.connection.fromPosition,targetX:t.store.connection.to.x,targetY:t.store.connection.to.y,targetPosition:t.store.connection.toPosition};switch(t.type){case Dn.Bezier:{let[a]=md(s);return a}case Dn.Straight:{let[a]=vd(s);return a}case Dn.Step:case Dn.SmoothStep:{let[a]=Ws({...s,borderRadius:t.type===Dn.Step?0:void 0});return a}}});var n=Xe(),o=le(n);{var i=s=>{var a=xA(),l=V(a),u=V(l);{var f=d=>{var p=Xe(),h=le(p);io(h,()=>t.LineComponent,(b,x)=>{x(b,{})}),F(d,p)},g=d=>{var p=bA();te(()=>{D(p,"d",c(r)),Oe(p,t.style)}),F(d,p)};ce(u,d=>{t.LineComponent?d(f):d(g,-1)})}Q(l),Q(a),te(d=>{D(a,"width",t.store.width),D(a,"height",t.store.height),Oe(a,t.containerStyle),Je(l,0,d)},[()=>Pt(["svelte-flow__connection",v0(t.store.connection.isValid)])]),F(s,a)};ce(o,s=>{t.store.connection.inProgress&&s(i)})}F(e,n),ee()}var bA,xA,fI=v(()=>{ve();ie();Ke();bA=Ge(''),xA=Ge('')});var gI=v(()=>{fI()});function Do(e,t){q(t,!0);let r=P(t,"position",3,"top-right"),n=jt(t,yA),o=_(()=>`${r()}`.split("-"));var i=IA();Jt(i,a=>({class:a,style:t.style,...n}),[()=>["svelte-flow__panel",t.class,...c(o)]]);var s=V(i);at(s,()=>t.children??ct),Q(i),F(e,i),ee()}var yA,IA,Ug=v(()=>{ve();ie();yA=new Set(["$$slots","$$events","$$legacy","position","style","class","children"]),IA=J("
            ")});var pI=v(()=>{});var Vd=v(()=>{Ug();pI()});function Wd(e,t){q(t,!0);let r=P(t,"position",3,"bottom-right");var n=Xe(),o=le(n);{var i=s=>{Do(s,{get position(){return r()},class:"svelte-flow__attribution","data-message":"Feel free to remove the attribution or check out how you could support us: https://svelteflow.dev/support-us",children:(a,l)=>{var u=wA();F(a,u)},$$slots:{default:!0}})};ce(o,s=>{t.proOptions?.hideAttribution||s(i)})}F(e,n),ee()}var wA,hI=v(()=>{ve();ie();Vd();wA=J('Svelte Flow')});var mI=v(()=>{hI()});var vI=v(()=>{});function Lg(e,t){q(t,!0);let r=P(t,"domNode",15),n=P(t,"clientWidth",15),o=P(t,"clientHeight",15),i=_(()=>t.rest.id),s=_(()=>t.rest.class),a=_(()=>t.rest.nodeTypes),l=_(()=>t.rest.edgeTypes),u=_(()=>t.rest.colorMode),f=_(()=>t.rest.isValidConnection),g=_(()=>t.rest.onmove),d=_(()=>t.rest.onmovestart),p=_(()=>t.rest.onmoveend),h=_(()=>t.rest.onflowerror),b=_(()=>t.rest.ondelete),x=_(()=>t.rest.onbeforedelete),w=_(()=>t.rest.onbeforeconnect),C=_(()=>t.rest.onconnect),E=_(()=>t.rest.onconnectstart),y=_(()=>t.rest.onconnectend),U=_(()=>t.rest.onbeforereconnect),B=_(()=>t.rest.onreconnect),k=_(()=>t.rest.onreconnectstart),G=_(()=>t.rest.onreconnectend),W=_(()=>t.rest.onclickconnectstart),H=_(()=>t.rest.onclickconnectend),Z=_(()=>t.rest.oninit),$=_(()=>t.rest.onselectionchange),X=_(()=>t.rest.onselectiondragstart),I=_(()=>t.rest.onselectiondrag),A=_(()=>t.rest.onselectiondragstop),S=_(()=>t.rest.onselectionstart),T=_(()=>t.rest.onselectionend),K=_(()=>t.rest.clickConnect),Y=_(()=>t.rest.fitView),z=_(()=>t.rest.fitViewOptions),j=_(()=>t.rest.nodeOrigin),re=_(()=>t.rest.nodeDragThreshold),ae=_(()=>t.rest.connectionDragThreshold),ne=_(()=>t.rest.minZoom),Ie=_(()=>t.rest.maxZoom),fe=_(()=>t.rest.initialViewport),ge=_(()=>t.rest.connectionRadius),pe=_(()=>t.rest.connectionMode),we=_(()=>t.rest.selectionMode),We=_(()=>t.rest.selectNodesOnDrag),Ze=_(()=>t.rest.snapGrid),lt=_(()=>t.rest.defaultMarkerColor),Le=_(()=>t.rest.translateExtent),vt=_(()=>t.rest.nodeExtent),Ot=_(()=>t.rest.onlyRenderVisibleElements),ar=_(()=>t.rest.autoPanOnConnect),yr=_(()=>t.rest.autoPanOnNodeDrag),Qe=_(()=>t.rest.colorModeSSR),nt=_(()=>t.rest.defaultEdgeOptions),er=_(()=>t.rest.elevateNodesOnSelect),Me=_(()=>t.rest.elevateEdgesOnSelect),Fr=_(()=>t.rest.nodesDraggable),Or=_(()=>t.rest.autoPanOnNodeFocus),Hr=_(()=>t.rest.nodesConnectable),Ui=_(()=>t.rest.elementsSelectable),Li=_(()=>t.rest.nodesFocusable),Vi=_(()=>t.rest.edgesFocusable),Wi=_(()=>t.rest.disableKeyboardA11y),Ti=_(()=>t.rest.noDragClass),Di=_(()=>t.rest.noPanClass),Oi=_(()=>t.rest.noWheelClass),Hi=_(()=>t.rest.ariaLabelConfig),Mi=_(()=>t.rest.autoPanSpeed),Yi=_(()=>t.rest.panOnScrollSpeed),zi=_(()=>t.rest.zIndexMode),Oo=_(()=>eu(t.rest,["id","class","nodeTypes","edgeTypes","colorMode","isValidConnection","onmove","onmovestart","onmoveend","onflowerror","ondelete","onbeforedelete","onbeforeconnect","onconnect","onconnectstart","onconnectend","onbeforereconnect","onreconnect","onreconnectstart","onreconnectend","onclickconnectstart","onclickconnectend","oninit","onselectionchange","onselectiondragstart","onselectiondrag","onselectiondragstop","onselectionstart","onselectionend","clickConnect","fitView","fitViewOptions","nodeOrigin","nodeDragThreshold","connectionDragThreshold","minZoom","maxZoom","initialViewport","connectionRadius","connectionMode","selectionMode","selectNodesOnDrag","snapGrid","defaultMarkerColor","translateExtent","nodeExtent","onlyRenderVisibleElements","autoPanOnConnect","autoPanOnNodeDrag","colorModeSSR","defaultEdgeOptions","elevateNodesOnSelect","elevateEdgesOnSelect","nodesDraggable","autoPanOnNodeFocus","nodesConnectable","elementsSelectable","nodesFocusable","edgesFocusable","disableKeyboardA11y","noDragClass","noPanClass","noWheelClass","ariaLabelConfig","autoPanSpeed","panOnScrollSpeed","zIndexMode"]));function Ho(Mr){Mr.currentTarget.scrollTo({top:0,left:0,behavior:"auto"}),t.rest.onscroll&&t.rest.onscroll(Mr)}var Sr=CA();Jt(Sr,Mr=>({class:["svelte-flow","svelte-flow__container",c(s),t.colorMode],"data-testid":"svelte-flow__wrapper",role:"application",onscroll:Ho,...c(Oo),[Er]:Mr}),[()=>({width:xr(t.width),height:xr(t.height)})],void 0,void 0,"svelte-mkap6j");var Mo=V(Sr);at(Mo,()=>t.children??ct),Q(Sr),Dr(Sr,Mr=>r(Mr),()=>r()),Ac(Sr,"clientHeight",o),Ac(Sr,"clientWidth",n),F(e,Sr),ee()}var CA,_I=v(()=>{ve();ie();Wo();vI();CA=J("
            ")});function Xi(e,t){q(t,!0);let r=P(t,"paneClickDistance",3,1),n=P(t,"nodeClickDistance",3,1),o=P(t,"panOnScrollMode",19,()=>Fi.Free),i=P(t,"preventScrolling",3,!0),s=P(t,"zoomOnScroll",3,!0),a=P(t,"zoomOnDoubleClick",3,!0),l=P(t,"zoomOnPinch",3,!0),u=P(t,"panOnScroll",3,!1),f=P(t,"panOnScrollSpeed",3,.5),g=P(t,"panOnDrag",3,!0),d=P(t,"selectionOnDrag",3,!1),p=P(t,"connectionLineType",19,()=>Dn.Bezier),h=P(t,"nodes",31,()=>Dt([])),b=P(t,"edges",31,()=>Dt([])),x=P(t,"viewport",15,void 0),w=jt(t,BA),C=Gy({props:w,width:t.width,height:t.height,get nodes(){return h()},set nodes(y){h(y)},get edges(){return b()},set edges(y){b(y)},get viewport(){return x()},set viewport(y){x(y)}}),E=Pn(El);E&&E.setStore&&E.setStore(C),Jo(El,{provider:!1,getStore(){return C}}),st(()=>{let y={nodes:C.selectedNodes,edges:C.selectedEdges};ke(()=>t.onselectionchange)?.(y);for(let U of C.selectionChangeHandlers.values())U(y)}),_i(()=>{C.reset()}),Lg(e,{get colorMode(){return C.colorMode},get width(){return t.width},get height(){return t.height},get rest(){return w},get domNode(){return C.domNode},set domNode(y){C.domNode=y},get clientWidth(){return C.width},set clientWidth(y){C.width=y},get clientHeight(){return C.height},set clientHeight(y){C.height=y},children:(y,U)=>{var B=AA(),k=le(B);Ud(k,{get selectionKey(){return t.selectionKey},get deleteKey(){return t.deleteKey},get panActivationKey(){return t.panActivationKey},get multiSelectionKey(){return t.multiSelectionKey},get zoomActivationKey(){return t.zoomActivationKey},get store(){return C},set store($){C=$}});var G=O(k,2);Bd(G,{get panOnScrollMode(){return o()},get preventScrolling(){return i()},get zoomOnScroll(){return s()},get zoomOnDoubleClick(){return a()},get zoomOnPinch(){return l()},get panOnScroll(){return u()},get panOnScrollSpeed(){return f()},get panOnDrag(){return g()},get paneClickDistance(){return r()},get selectionOnDrag(){return d()},get onmovestart(){return t.onmovestart},get onmove(){return t.onmove},get onmoveend(){return t.onmoveend},get oninit(){return t.oninit},get store(){return C},set store($){C=$},children:($,X)=>{Ed($,{get onpaneclick(){return t.onpaneclick},get onpanecontextmenu(){return t.onpanecontextmenu},get onselectionstart(){return t.onselectionstart},get onselectionend(){return t.onselectionend},get panOnDrag(){return g()},get paneClickDistance(){return r()},get selectionOnDrag(){return d()},get store(){return C},set store(I){C=I},children:(I,A)=>{var S=$A(),T=le(S);$d(T,{get store(){return C},set store(Y){C=Y},children:(Y,z)=>{var j=EA(),re=O(le(j),2);Xd(re,{get onedgeclick(){return t.onedgeclick},get onedgecontextmenu(){return t.onedgecontextmenu},get onedgepointerenter(){return t.onedgepointerenter},get onedgepointerleave(){return t.onedgepointerleave},get store(){return C},set store(fe){C=fe}});var ae=O(re,4);Ld(ae,{get type(){return p()},get LineComponent(){return t.connectionLineComponent},get containerStyle(){return t.connectionLineContainerStyle},get style(){return t.connectionLineStyle},get store(){return C},set store(fe){C=fe}});var ne=O(ae,2);Zd(ne,{get nodeClickDistance(){return n()},get onnodeclick(){return t.onnodeclick},get onnodecontextmenu(){return t.onnodecontextmenu},get onnodepointerenter(){return t.onnodepointerenter},get onnodepointermove(){return t.onnodepointermove},get onnodepointerleave(){return t.onnodepointerleave},get onnodedrag(){return t.onnodedrag},get onnodedragstart(){return t.onnodedragstart},get onnodedragstop(){return t.onnodedragstop},get store(){return C},set store(fe){C=fe}});var Ie=O(ne,2);Rd(Ie,{get onselectionclick(){return t.onselectionclick},get onselectioncontextmenu(){return t.onselectioncontextmenu},get onnodedrag(){return t.onnodedrag},get onnodedragstart(){return t.onnodedragstart},get onnodedragstop(){return t.onnodedragstop},get store(){return C},set store(fe){C=fe}}),Ct(2),F(Y,j)},$$slots:{default:!0}});var K=O(T,2);{let Y=_(()=>!!(C.selectionRect&&C.selectionRectMode==="user")),z=_(()=>C.selectionRect?.width),j=_(()=>C.selectionRect?.height),re=_(()=>C.selectionRect?.x),ae=_(()=>C.selectionRect?.y);Os(K,{get isVisible(){return c(Y)},get width(){return c(z)},get height(){return c(j)},get x(){return c(re)},get y(){return c(ae)}})}F(I,S)},$$slots:{default:!0}})},$$slots:{default:!0}});var W=O(G,2);Wd(W,{get proOptions(){return t.proOptions},get position(){return t.attributionPosition}});var H=O(W,2);Ad(H,{get store(){return C}});var Z=O(H,2);at(Z,()=>t.children??ct),F(y,B)},$$slots:{default:!0}}),ee()}var BA,EA,$A,AA,bI=v(()=>{ve();ie();nn();Ke();ln();Zy();Uy();Vy();Yy();qy();oI();Xg();uI();gI();mI();_I();Al();BA=new Set(["$$slots","$$events","$$legacy","width","height","proOptions","selectionKey","deleteKey","panActivationKey","multiSelectionKey","zoomActivationKey","paneClickDistance","nodeClickDistance","onmovestart","onmoveend","onmove","oninit","onnodeclick","onnodecontextmenu","onnodedrag","onnodedragstart","onnodedragstop","onnodepointerenter","onnodepointermove","onnodepointerleave","onselectionclick","onselectioncontextmenu","onselectionstart","onselectionend","onedgeclick","onedgecontextmenu","onedgepointerenter","onedgepointerleave","onpaneclick","onpanecontextmenu","panOnScrollMode","preventScrolling","zoomOnScroll","zoomOnDoubleClick","zoomOnPinch","panOnScroll","panOnScrollSpeed","panOnDrag","selectionOnDrag","connectionLineComponent","connectionLineStyle","connectionLineContainerStyle","connectionLineType","attributionPosition","children","nodes","edges","viewport"]),EA=J('
            ',1),$A=J(" ",1),AA=J(" ",1)});var Vg=v(()=>{});var xI=v(()=>{bI();Vg()});var yI=v(()=>{});var II=v(()=>{});var wI=v(()=>{II()});var CI=v(()=>{});var BI=v(()=>{CI()});var EI=v(()=>{});var $I=v(()=>{EI()});function Hs(e,t){let r=jt(t,GA);var n=FA();Jt(n,()=>({type:"button",onclick:t.onclick,class:["svelte-flow__controls-button",t.class],...r,[Er]:{"--xy-controls-button-background-color-props":t.bgColor,"--xy-controls-button-background-color-hover-props":t.bgColorHover,"--xy-controls-button-color-props":t.color,"--xy-controls-button-color-hover-props":t.colorHover,"--xy-controls-button-border-color-props":t.borderColor}}));var o=V(n);at(o,()=>t.children??ct),Q(n),F(e,n)}var GA,FA,AI=v(()=>{ve();ie();GA=new Set(["$$slots","$$events","$$legacy","class","bgColor","bgColorHover","color","colorHover","borderColor","onclick","children"]),FA=J("")});function Wg(e){var t=SA();F(e,t)}var SA,GI=v(()=>{ve();To();ie();SA=Ge('')});function Tg(e){var t=ZA();F(e,t)}var ZA,FI=v(()=>{ve();To();ie();ZA=Ge('')});function Dg(e){var t=kA();F(e,t)}var kA,SI=v(()=>{ve();To();ie();kA=Ge('')});function Og(e){var t=NA();F(e,t)}var NA,ZI=v(()=>{ve();To();ie();NA=Ge('')});function Hg(e){var t=QA();F(e,t)}var QA,kI=v(()=>{ve();To();ie();QA=Ge('')});function Ms(e,t){q(t,!0);let r=P(t,"position",3,"bottom-left"),n=P(t,"orientation",3,"vertical"),o=P(t,"showZoom",3,!0),i=P(t,"showFitView",3,!0),s=P(t,"showLock",3,!0),a=jt(t,XA),l=_(Nt),u={bgColor:t.buttonBgColor,bgColorHover:t.buttonBgColorHover,color:t.buttonColor,colorHover:t.buttonColorHover,borderColor:t.buttonBorderColor},f=_(()=>c(l).nodesDraggable||c(l).nodesConnectable||c(l).elementsSelectable),g=_(()=>c(l).viewport.zoom<=c(l).minZoom),d=_(()=>c(l).viewport.zoom>=c(l).maxZoom),p=_(()=>c(l).ariaLabelConfig),h=_(()=>n()==="horizontal"?"horizontal":"vertical"),b=()=>{c(l).zoomIn()},x=()=>{c(l).zoomOut()},w=()=>{c(l).fitView(t.fitViewOptions)},C=()=>{let E=!c(f);c(l).nodesDraggable=E,c(l).nodesConnectable=E,c(l).elementsSelectable=E};{let E=_(()=>["svelte-flow__controls",c(h),t.class]);Do(e,Cn({get class(){return c(E)},get position(){return r()},"data-testid":"svelte-flow__controls",get"aria-label"(){return c(p)["controls.ariaLabel"]},get style(){return t.style}},()=>a,{children:(y,U)=>{var B=UA(),k=le(B);{var G=Y=>{var z=Xe(),j=le(z);at(j,()=>t.before),F(Y,z)};ce(k,Y=>{t.before&&Y(G)})}var W=O(k,2);{var H=Y=>{var z=RA(),j=le(z);Hs(j,Cn({onclick:b,class:"svelte-flow__controls-zoomin",get title(){return c(p)["controls.zoomIn.ariaLabel"]},get"aria-label"(){return c(p)["controls.zoomIn.ariaLabel"]},get disabled(){return c(d)}},()=>u,{children:(ae,ne)=>{Wg(ae,{})},$$slots:{default:!0}}));var re=O(j,2);Hs(re,Cn({onclick:x,class:"svelte-flow__controls-zoomout",get title(){return c(p)["controls.zoomOut.ariaLabel"]},get"aria-label"(){return c(p)["controls.zoomOut.ariaLabel"]},get disabled(){return c(g)}},()=>u,{children:(ae,ne)=>{Tg(ae,{})},$$slots:{default:!0}})),F(Y,z)};ce(W,Y=>{o()&&Y(H)})}var Z=O(W,2);{var $=Y=>{Hs(Y,Cn({class:"svelte-flow__controls-fitview",onclick:w,get title(){return c(p)["controls.fitView.ariaLabel"]},get"aria-label"(){return c(p)["controls.fitView.ariaLabel"]}},()=>u,{children:(z,j)=>{Dg(z,{})},$$slots:{default:!0}}))};ce(Z,Y=>{i()&&Y($)})}var X=O(Z,2);{var I=Y=>{Hs(Y,Cn({class:"svelte-flow__controls-interactive",onclick:C,get title(){return c(p)["controls.interactive.ariaLabel"]},get"aria-label"(){return c(p)["controls.interactive.ariaLabel"]}},()=>u,{children:(z,j)=>{var re=Xe(),ae=le(re);{var ne=fe=>{Hg(fe,{})},Ie=fe=>{Og(fe,{})};ce(ae,fe=>{c(f)?fe(ne):fe(Ie,-1)})}F(z,re)},$$slots:{default:!0}}))};ce(X,Y=>{s()&&Y(I)})}var A=O(X,2);{var S=Y=>{var z=Xe(),j=le(z);at(j,()=>t.children),F(Y,z)};ce(A,Y=>{t.children&&Y(S)})}var T=O(A,2);{var K=Y=>{var z=Xe(),j=le(z);at(j,()=>t.after),F(Y,z)};ce(T,Y=>{t.after&&Y(K)})}F(y,B)},$$slots:{default:!0}}))}ee()}var XA,RA,UA,NI=v(()=>{ve();ie();ln();Ug();AI();GI();FI();SI();ZI();kI();XA=new Set(["$$slots","$$events","$$legacy","position","orientation","showZoom","showFitView","showLock","style","class","buttonBgColor","buttonBgColorHover","buttonColor","buttonColorHover","buttonBorderColor","fitViewOptions","children","before","after"]),RA=J(" ",1),UA=J(" ",1)});var QI=v(()=>{});var XI=v(()=>{NI();QI()});var mo,RI=v(()=>{(function(e){e.Lines="lines",e.Dots="dots",e.Cross="cross"})(mo||(mo={}))});function Mg(e,t){var r=LA();te(()=>{D(r,"cx",t.radius),D(r,"cy",t.radius),D(r,"r",t.radius),Je(r,0,Pt(["svelte-flow__background-pattern","dots",t.class]))}),F(e,r)}var LA,UI=v(()=>{ve();ie();LA=Ge("")});function Yg(e,t){q(t,!0);var r=VA();te(()=>{D(r,"stroke-width",t.lineWidth),D(r,"d",`M${t.dimensions[0]/2} 0 V${t.dimensions[1]} M0 ${t.dimensions[1]/2} H${t.dimensions[0]}`),Je(r,0,Pt(["svelte-flow__background-pattern",t.variant,t.class]))}),F(e,r),ee()}var VA,LI=v(()=>{ve();ie();VA=Ge("")});function Ys(e,t){q(t,!0);let r=P(t,"variant",19,()=>mo.Dots),n=P(t,"gap",3,20),o=P(t,"lineWidth",3,1),i=_(Nt),s=_(()=>r()===mo.Dots),a=_(()=>r()===mo.Cross),l=_(()=>Array.isArray(n())?n():[n(),n()]),u=_(()=>`background-pattern-${c(i).flowId}-${t.id??""}`),f=_(()=>[c(l)[0]*c(i).viewport.zoom||1,c(l)[1]*c(i).viewport.zoom||1]),g=_(()=>(t.size??WA[r()])*c(i).viewport.zoom),d=_(()=>c(a)?[c(g),c(g)]:c(f)),p=_(()=>c(s)?[c(g)/2,c(g)/2]:[c(d)[0]/2,c(d)[1]/2]);var h=TA();let b;var x=V(h),w=V(x);{var C=U=>{{let B=_(()=>c(g)/2);Mg(U,{get radius(){return c(B)},get class(){return t.patternClass}})}},E=U=>{Yg(U,{get dimensions(){return c(d)},get variant(){return r()},get lineWidth(){return o()},get class(){return t.patternClass}})};ce(w,U=>{c(s)?U(C):U(E,-1)})}Q(x);var y=O(x);Q(h),te(()=>{Je(h,0,Pt(["svelte-flow__background","svelte-flow__container",t.class])),b=Oe(h,"",b,{"--xy-background-color-props":t.bgColor,"--xy-background-pattern-color-props":t.patternColor}),D(x,"id",c(u)),D(x,"x",c(i).viewport.x%c(f)[0]),D(x,"y",c(i).viewport.y%c(f)[1]),D(x,"width",c(f)[0]),D(x,"height",c(f)[1]),D(x,"patternTransform",`translate(-${c(p)[0]},-${c(p)[1]})`),D(y,"fill",`url(#${c(u)})`)}),F(e,h),ee()}var WA,TA,VI=v(()=>{ve();ie();ln();RI();UI();LI();WA={[mo.Dots]:1,[mo.Lines]:1,[mo.Cross]:6},TA=Ge('')});var WI=v(()=>{VI()});function TI(e){let t=_(Nt),r=_(()=>c(t).nodeLookup),n=_(()=>c(t).nodes),o=_(()=>(c(n),c(r).get(e)));return{get current(){return c(o)}}}var zg=v(()=>{ie();ln()});function Pg(e,t){q(t,!0);let r=P(t,"borderRadius",3,5),n=P(t,"strokeWidth",3,2),o=_(()=>TI(t.id)),i=_(()=>{if(!c(o).current)return{width:0,height:0,x:0,y:0};let{width:h,height:b}=fo(c(o).current);return{width:t.width??h,height:t.height??b,x:t.x??c(o).current.internals.positionAbsolute.x,y:t.y??c(o).current.internals.positionAbsolute.y}}),s=_(()=>c(i).width),a=_(()=>c(i).height),l=_(()=>c(i).x),u=_(()=>c(i).y);var f=Xe(),g=le(f);{var d=h=>{let b=_(()=>t.nodeComponent);var x=Xe(),w=le(x);io(w,()=>c(b),(C,E)=>{E(C,{get id(){return t.id},get x(){return c(l)},get y(){return c(u)},get width(){return c(s)},get height(){return c(a)},get borderRadius(){return r()},get class(){return t.class},get color(){return t.color},get shapeRendering(){return t.shapeRendering},get strokeColor(){return t.strokeColor},get strokeWidth(){return n()},get selected(){return t.selected}})}),F(h,x)},p=h=>{var b=DA();let x,w;te(()=>{x=Je(b,0,Pt(["svelte-flow__minimap-node",t.class]),null,x,{selected:t.selected}),D(b,"x",c(l)),D(b,"y",c(u)),D(b,"rx",r()),D(b,"ry",r()),D(b,"width",c(s)),D(b,"height",c(a)),D(b,"shape-rendering",t.shapeRendering),w=Oe(b,"",w,{fill:t.color,stroke:t.strokeColor,"stroke-width":n()})}),F(h,b)};ce(g,h=>{t.nodeComponent?h(d):h(p,-1)})}F(e,f),ee()}var DA,DI=v(()=>{ve();ie();zg();Ke();DA=Ge("")});function Jg(e,t){let r=M0({domNode:e,panZoom:t.panZoom,getTransform:()=>{let{viewport:o}=t.store;return[o.x,o.y,o.zoom]},getViewScale:t.getViewScale});r.update({translateExtent:t.translateExtent,width:t.width,height:t.height,inversePan:t.inversePan,zoomStep:t.zoomStep,pannable:t.pannable,zoomable:t.zoomable});function n(o){r.update({translateExtent:o.translateExtent,width:o.width,height:o.height,inversePan:o.inversePan,zoomStep:o.zoomStep,pannable:o.pannable,zoomable:o.zoomable})}return{update:n,destroy(){r.destroy()}}}var OI=v(()=>{Ke()});function zs(e,t){q(t,!0);let r=P(t,"position",3,"bottom-right"),n=P(t,"nodeStrokeColor",3,"transparent"),o=P(t,"nodeClass",3,""),i=P(t,"nodeBorderRadius",3,5),s=P(t,"nodeStrokeWidth",3,2),a=P(t,"width",3,200),l=P(t,"height",3,150),u=P(t,"pannable",3,!0),f=P(t,"zoomable",3,!0),g=jt(t,OA),d=_(Nt),p=_(()=>c(d).ariaLabelConfig),h=typeof window>"u"||window.chrome?"crispEdges":"geometricPrecision",b=_(()=>`svelte-flow__minimap-desc-${c(d).flowId}`),x=_(()=>({x:-c(d).viewport.x/c(d).viewport.zoom,y:-c(d).viewport.y/c(d).viewport.zoom,width:c(d).width/c(d).viewport.zoom,height:c(d).height/c(d).viewport.zoom})),w=_(()=>ig(Vo(c(d).nodeLookup,{filter:A=>!A.hidden}),c(x))),C=_(()=>c(w).width/a()),E=_(()=>c(w).height/l()),y=_(()=>Math.max(c(C),c(E))),U=_(()=>c(y)*a()),B=_(()=>c(y)*l()),k=_(()=>5*c(y)),G=_(()=>c(w).x-(c(U)-c(w).width)/2-c(k)),W=_(()=>c(w).y-(c(B)-c(w).height)/2-c(k)),H=_(()=>c(U)+c(k)*2),Z=_(()=>c(B)+c(k)*2),$=()=>c(y);var X=YA(),I=le(X);{let A=_(()=>["svelte-flow__minimap",t.class]);Yu(I,()=>({"--xy-minimap-background-color-props":t.bgColor})),Do(I.lastChild,Cn({get position(){return r()},get class(){return c(A)},"data-testid":"svelte-flow__minimap"},()=>g,{children:(S,T)=>{var K=Xe(),Y=le(K);{var z=j=>{var re=MA();let ae;var ne=V(re);{var Ie=pe=>{var we=HA(),We=V(we,!0);Q(we),te(()=>{D(we,"id",c(b)),oe(We,t.ariaLabel??c(p)["minimap.ariaLabel"])}),F(pe,we)};ce(ne,pe=>{(t.ariaLabel??c(p)["minimap.ariaLabel"])&&pe(Ie)})}var fe=O(ne);Ne(fe,17,()=>c(d).nodes,pe=>pe.id,(pe,we)=>{let We=_(()=>c(d).nodeLookup.get(c(we).id));var Ze=Xe(),lt=le(Ze);{var Le=Ot=>{{let ar=_(()=>t.nodeColor===void 0?void 0:jg(t.nodeColor)(c(we))),yr=_(()=>jg(n())(c(we))),Qe=_(()=>jg(o())(c(we)));Pg(Ot,{get id(){return c(We).id},get selected(){return c(We).selected},get nodeComponent(){return t.nodeComponent},get color(){return c(ar)},get borderRadius(){return i()},get strokeColor(){return c(yr)},get strokeWidth(){return s()},get shapeRendering(){return h},get class(){return c(Qe)}})}},vt=_(()=>c(We)&&pd(c(We))&&!c(We).hidden);ce(lt,Ot=>{c(vt)&&Ot(Le)})}F(pe,Ze)});var ge=O(fe);Q(re),ft(re,(pe,we)=>Jg?.(pe,we),()=>({store:c(d),panZoom:c(d).panZoom,getViewScale:$,translateExtent:c(d).translateExtent,width:c(d).width,height:c(d).height,inversePan:t.inversePan,zoomStep:t.zoomStep,pannable:u(),zoomable:f()})),te(()=>{D(re,"width",a()),D(re,"height",l()),D(re,"viewBox",`${c(G)??""} ${c(W)??""} ${c(H)??""} ${c(Z)??""}`),D(re,"aria-labelledby",c(b)),ae=Oe(re,"",ae,{"--xy-minimap-mask-background-color-props":t.maskColor,"--xy-minimap-mask-stroke-color-props":t.maskStrokeColor,"--xy-minimap-mask-stroke-width-props":t.maskStrokeWidth?t.maskStrokeWidth*c(y):void 0}),D(ge,"d",`M${c(G)-c(k)},${c(W)-c(k)}h${c(H)+c(k)*2}v${c(Z)+c(k)*2}h${-c(H)-c(k)*2}z + M${c(x).x??""},${c(x).y??""}h${c(x).width??""}v${c(x).height??""}h${-c(x).width}z`)}),F(j,re)};ce(Y,j=>{c(d).panZoom&&j(z)})}F(S,K)},$$slots:{default:!0}})),Q(I)}F(e,X),ee()}var jg,OA,HA,MA,YA,HI=v(()=>{ve();ie();Ke();ln();Vd();DI();OI();jg=e=>e instanceof Function?e:()=>e,OA=new Set(["$$slots","$$events","$$legacy","position","ariaLabel","nodeStrokeColor","nodeColor","nodeClass","nodeBorderRadius","nodeStrokeWidth","nodeComponent","bgColor","maskColor","maskStrokeColor","maskStrokeWidth","width","height","pannable","zoomable","inversePan","zoomStep","class"]),HA=Ge(" "),MA=Ge(''),YA=J('',1)});var MI=v(()=>{});var YI=v(()=>{HI();MI()});var zI=v(()=>{});var PI=v(()=>{zI()});var JI=v(()=>{});var jI=v(()=>{JI()});var KI=v(()=>{});var qI=v(()=>{ie()});var ew=v(()=>{ie()});var tw=v(()=>{ie()});var rw=v(()=>{ie()});var nw=v(()=>{ie()});var ow=v(()=>{ie()});var iw=v(()=>{ie()});var sw=v(()=>{});var Kg=v(()=>{xI();Vg();Vd();yI();wI();_l();BI();$I();XI();WI();YI();PI();jI();KI();Wo();Rg();qI();ew();tw();rw();nw();zg();ow();iw();wg();sw()});function aw(e,t){e[t]?e[t]++:e[t]=1}function lw(e,t){e[t]!==void 0&&!--e[t]&&delete e[t]}function Gl(e,t,r,n){let o=""+t,i=""+r;if(!e&&o>i){let s=o;o=i,i=s}return o+""+i+""+(n===void 0?"\0":n)}function KA(e,t,r,n){let o=""+t,i=""+r;if(!e&&o>i){let a=o;o=i,i=a}let s={v:o,w:i};return n&&(s.name=n),s}function qg(e,t){return Gl(e,t.v,t.w,t.name)}function eG(e){let t={options:{directed:e.isDirected(),multigraph:e.isMultigraph(),compound:e.isCompound()},nodes:tG(e),edges:rG(e)},r=e.graph();return r!==void 0&&(t.value=structuredClone(r)),t}function tG(e){return e.nodes().map(t=>{let r=e.node(t),n=e.parent(t),o={v:t};return r!==void 0&&(o.value=r),n!==void 0&&(o.parent=n),o})}function rG(e){return e.edges().map(t=>{let r=e.edge(t),n={v:t.v,w:t.w};return t.name!==void 0&&(n.name=t.name),r!==void 0&&(n.value=r),n})}function nG(e){let t=new dn(e.options);return e.value!==void 0&&t.setGraph(e.value),e.nodes.forEach(r=>{t.setNode(r.v,r.value),r.parent&&t.setParent(r.v,r.parent)}),e.edges.forEach(r=>{t.setEdge({v:r.v,w:r.w,name:r.name},r.value)}),t}function Cw(e,t,r,n){return iG(e,String(t),r||oG,n||function(o){return e.outEdges(o)})}function iG(e,t,r,n){let o={},i,s=0,a=e.nodes(),l=function(g){let d=r(g);o[g.v].distance+d0&&(s=i.removeMin(),a=o[s],a.distance!==Number.POSITIVE_INFINITY);)n(s).forEach(l);return o}function cG(e,t,r){return e.nodes().reduce(function(n,o){return n[o]=Td(e,o,t,r),n},{})}function Ew(e){let t=0,r=[],n={},o=[];function i(s){let a=n[s]={onStack:!0,lowlink:t,index:t++};if(r.push(s),e.successors(s).forEach(function(l){l in n?n[l].onStack&&(a.lowlink=Math.min(a.lowlink,n[l].index)):(i(l),a.lowlink=Math.min(a.lowlink,n[l].lowlink))}),a.lowlink===a.index){let l=[],u;do u=r.pop(),n[u].onStack=!1,l.push(u);while(s!==u);o.push(l)}}return e.nodes().forEach(function(s){s in n||i(s)}),o}function dG(e){return Ew(e).filter(function(t){return t.length>1||t.length===1&&e.hasEdge(t[0],t[0])})}function fG(e,t,r){return gG(e,t||uG,r||function(n){return e.outEdges(n)})}function gG(e,t,r){let n={},o=e.nodes();return o.forEach(function(i){n[i]={},n[i][i]={distance:0,predecessor:""},o.forEach(function(s){i!==s&&(n[i][s]={distance:Number.POSITIVE_INFINITY,predecessor:""})}),r(i).forEach(function(s){let a=s.v===i?s.w:s.v,l=t(s);n[i][a]={distance:l,predecessor:i}})}),o.forEach(function(i){let s=n[i];o.forEach(function(a){let l=n[a];o.forEach(function(u){let f=l[i],g=s[u],d=l[u],p=f.distance+g.distance;p{var l;return(l=e.isDirected()?e.successors(a):e.neighbors(a))!=null?l:[]}),s={};return t.forEach(function(a){if(!e.hasNode(a))throw new Error("Graph does not have node: "+a);o=Aw(e,a,r==="post",s,i,n,o)}),o}function Aw(e,t,r,n,o,i,s){return t in n||(n[t]=!0,r||(s=i(s,t)),o(t).forEach(function(a){s=Aw(e,a,r,n,o,i,s)}),r&&(s=i(s,t))),s}function Gw(e,t,r){return hG(e,t,r,function(n,o){return n.push(o),n},[])}function mG(e,t){return Gw(e,t,"post")}function vG(e,t){return Gw(e,t,"pre")}function _G(e,t){let r=new dn,n={},o=new Bw,i;function s(l){let u=l.v===i?l.w:l.v,f=o.priority(u);if(f!==void 0){let g=t(l);g0;){if(i=o.removeMin(),i in n)r.setEdge(i,n[i]);else{if(a)throw new Error("Input graph is not connected: "+e);a=!0}e.nodeEdges(i).forEach(s)}return r}function bG(e,t,r,n){return xG(e,t,r,n??(o=>{let i=e.outEdges(o);return i??[]}))}function xG(e,t,r,n){if(r===void 0)return Td(e,t,r,n);let o=!1,i=e.nodes();for(let s=0;st.setNode(r,e.node(r))),e.edges().forEach(r=>{let n=t.edge(r.v,r.w)||{weight:0,minlen:1},o=e.edge(r);t.setEdge(r.v,r.w,{weight:n.weight+o.weight,minlen:Math.max(n.minlen,o.minlen)})}),t}function Fw(e){let t=new dn({multigraph:e.isMultigraph()}).setGraph(e.graph());return e.nodes().forEach(r=>{e.children(r).length||t.setNode(r,e.node(r))}),e.edges().forEach(r=>{t.setEdge(r,e.edge(r))}),t}function cw(e,t){let r=e.x,n=e.y,o=t.x-r,i=t.y-n,s=e.width/2,a=e.height/2;if(!o&&!i)throw new Error("Not possible to find intersection inside of the rectangle");let l,u;return Math.abs(i)*s>Math.abs(o)*a?(i<0&&(a=-a),l=a*o/i,u=a):(o<0&&(s=-s),l=s,u=s*i/o),{x:r+l,y:n+u}}function Sl(e){let t=Fl(Zw(e)+1).map(()=>[]);return e.nodes().forEach(r=>{let n=e.node(r),o=n.rank;o!==void 0&&(t[o]||(t[o]=[]),t[o][n.order]=r)}),t}function IG(e){let t=e.nodes().map(n=>{let o=e.node(n).rank;return o===void 0?Number.MAX_VALUE:o}),r=On(Math.min,t);e.nodes().forEach(n=>{let o=e.node(n);Object.hasOwn(o,"rank")&&(o.rank-=r)})}function wG(e){let t=e.nodes().map(s=>e.node(s).rank).filter(s=>s!==void 0),r=On(Math.min,t),n=[];e.nodes().forEach(s=>{let a=e.node(s).rank-r;n[a]||(n[a]=[]),n[a].push(s)});let o=0,i=e.graph().nodeRankFactor;Array.from(n).forEach((s,a)=>{s===void 0&&a%i!==0?--o:s!==void 0&&o&&s.forEach(l=>e.node(l).rank+=o)})}function dw(e,t,r,n){let o={width:0,height:0};return arguments.length>=4&&(o.rank=r,o.order=n),Js(e,"border",o,t)}function CG(e,t=Sw){let r=[];for(let n=0;nSw){let r=CG(t);return e(...r.map(n=>e(...n)))}else return e(...t)}function Zw(e){let t=e.nodes().map(r=>{let n=e.node(r).rank;return n===void 0?Number.MIN_VALUE:n});return On(Math.max,t)}function BG(e,t){let r={lhs:[],rhs:[]};return e.forEach(n=>{t(n)?r.lhs.push(n):r.rhs.push(n)}),r}function kw(e,t){let r=Date.now();try{return t()}finally{console.log(e+" time: "+(Date.now()-r)+"ms")}}function Nw(e,t){return t()}function ap(e){let t=++EG;return e+(""+t)}function Fl(e,t,r=1){t==null&&(t=e,e=0);let n=i=>itn[t]:r=t,Object.entries(e).reduce((n,[o,i])=>(n[o]=r(i,o),n),{})}function $G(e,t){return e.reduce((r,n,o)=>(r[n]=t[o],r),{})}function uw(e){e._prev._next=e._next,e._next._prev=e._prev,delete e._next,delete e._prev}function FG(e,t){if(e!=="_next"&&e!=="_prev")return t}function kG(e,t){if(e.nodeCount()<=1)return[];let r=QG(e,t||ZG);return NG(r.graph,r.buckets,r.zeroIdx).flatMap(n=>e.outEdges(n.v,n.w)||[])}function NG(e,t,r){var n;let o=[],i=t[t.length-1],s=t[0],a;for(;e.nodeCount();){for(;a=s.dequeue();)ep(e,t,r,a);for(;a=i.dequeue();)ep(e,t,r,a);if(e.nodeCount()){for(let l=t.length-2;l>0;--l)if(a=(n=t[l])==null?void 0:n.dequeue(),a){o=o.concat(ep(e,t,r,a,!0)||[]);break}}}return o}function ep(e,t,r,n,o){let i=[],s=o?i:void 0;return(e.inEdges(n.v)||[]).forEach(a=>{let l=e.edge(a),u=e.node(a.v);o&&i.push({v:a.v,w:a.w}),u.out-=l,ip(t,r,u)}),(e.outEdges(n.v)||[]).forEach(a=>{let l=e.edge(a),u=a.w,f=e.node(u);f.in-=l,ip(t,r,f)}),e.removeNode(n.v),s}function QG(e,t){let r=new dn,n=0,o=0;e.nodes().forEach(a=>{r.setNode(a,{v:a,in:0,out:0})}),e.edges().forEach(a=>{let l=r.edge(a.v,a.w)||0,u=t(a),f=l+u;r.setEdge(a.v,a.w,f);let g=r.node(a.v),d=r.node(a.w);o=Math.max(o,g.out+=u),n=Math.max(n,d.in+=u)});let i=XG(o+n+3).map(()=>new SG),s=n+1;return r.nodes().forEach(a=>{ip(i,s,r.node(a))}),{graph:r,buckets:i,zeroIdx:s}}function ip(e,t,r){var n,o,i;r.out?r.in?(i=e[r.out-r.in+t])==null||i.enqueue(r):(o=e[e.length-1])==null||o.enqueue(r):(n=e[0])==null||n.enqueue(r)}function XG(e){let t=[];for(let r=0;r{let n=e.edge(r);e.removeEdge(r),n.forwardName=r.name,n.reversed=!0,e.setEdge(r.w,r.v,n,ap("rev"))});function t(r){return n=>r.edge(n).weight}}function UG(e){let t=[],r={},n={};function o(i){Object.hasOwn(n,i)||(n[i]=!0,r[i]=!0,e.outEdges(i).forEach(s=>{Object.hasOwn(r,s.w)?t.push(s):o(s.w)}),delete r[i])}return e.nodes().forEach(o),t}function LG(e){e.edges().forEach(t=>{let r=e.edge(t);if(r.reversed){e.removeEdge(t);let n=r.forwardName;delete r.reversed,delete r.forwardName,e.setEdge(t.w,t.v,r,n)}})}function VG(e){e.graph().dummyChains=[],e.edges().forEach(t=>WG(e,t))}function WG(e,t){let r=t.v,n=e.node(r).rank,o=t.w,i=e.node(o).rank,s=t.name,a=e.edge(t),l=a.labelRank;if(i===n+1)return;e.removeEdge(t);let u,f,g;for(g=0,++n;n{let r=e.node(t),n=r.edgeLabel,o;for(e.setEdge(r.edgeObj,n);r.dummy;)o=e.successors(t)[0],e.removeNode(t),n.points.push({x:r.x,y:r.y}),r.dummy==="edge-label"&&(n.x=r.x,n.y=r.y,n.width=r.width,n.height=r.height),t=o,r=e.node(t)})}function lp(e){let t={};function r(n){let o=e.node(n);if(Object.hasOwn(t,n))return o.rank;t[n]=!0;let i=e.outEdges(n),s=i?i.map(l=>l==null?Number.POSITIVE_INFINITY:r(l.w)-e.edge(l).minlen):[],a=On(Math.min,s);return a===Number.POSITIVE_INFINITY&&(a=0),o.rank=a}e.sources().forEach(r)}function Ps(e,t){return e.node(t.w).rank-e.node(t.v).rank-e.edge(t).minlen}function DG(e){let t=new dn({directed:!1}),r=e.nodes();if(r.length===0)throw new Error("Graph must have at least one node");let n=r[0],o=e.nodeCount();t.setNode(n,{});let i,s;for(;OG(t,e){let s=i.v,a=n===s?i.w:s;!e.hasNode(a)&&!Ps(t,i)&&(e.setNode(a,{}),e.setEdge(n,a,{}),r(a))})}return e.nodes().forEach(r),e.nodeCount()}function HG(e,t){return t.edges().reduce((r,n)=>{let o=Number.POSITIVE_INFINITY;return e.hasNode(n.v)!==e.hasNode(n.w)&&(o=Ps(t,n)),ot.node(n).rank+=r)}function Ri(e){e=yG(e),lp(e);let t=Qw(e);dp(t),cp(t,e);let r,n;for(;r=Uw(t);)n=Lw(t,e,r),Vw(t,e,r,n)}function cp(e,t){let r=zG(e,e.nodes());r=r.slice(0,r.length-1),r.forEach(n=>JG(e,t,n))}function JG(e,t,r){let n=e.node(r).parent,o=e.edge(r,n);o.cutvalue=Xw(e,t,r)}function Xw(e,t,r){let n=e.node(r).parent,o=!0,i=t.edge(r,n),s=0;i||(o=!1,i=t.edge(n,r)),s=i.weight;let a=t.nodeEdges(r);return a&&a.forEach(l=>{let u=l.v===r,f=u?l.w:l.v;if(f!==n){let g=u===o,d=t.edge(l).weight;if(s+=g?d:-d,KG(e,r,f)){let p=e.edge(r,f).cutvalue;s+=g?-p:p}}}),s}function dp(e,t){arguments.length<2&&(t=e.nodes()[0]),Rw(e,{},1,t)}function Rw(e,t,r,n,o){let i=r,s=e.node(n);t[n]=!0;let a=e.neighbors(n);return a&&a.forEach(l=>{Object.hasOwn(t,l)||(r=Rw(e,t,r,l,n))}),s.low=i,s.lim=r++,o?s.parent=o:delete s.parent,r}function Uw(e){return e.edges().find(t=>e.edge(t).cutvalue<0)}function Lw(e,t,r){let n=r.v,o=r.w;t.hasEdge(n,o)||(n=r.w,o=r.v);let i=e.node(n),s=e.node(o),a=i,l=!1;return i.lim>s.lim&&(a=s,l=!0),t.edges().filter(u=>l===fw(e,e.node(u.v),a)&&l!==fw(e,e.node(u.w),a)).reduce((u,f)=>Ps(t,f)!e.node(o).parent);if(!r)return;let n=YG(e,[r]);n=n.slice(1),n.forEach(o=>{let i=e.node(o).parent,s=t.edge(o,i),a=!1;s||(s=t.edge(i,o),a=!0),t.node(o).rank=t.node(i).rank+(a?s.minlen:-s.minlen)})}function KG(e,t,r){return e.hasEdge(t,r)}function fw(e,t,r){return r.low<=t.lim&&t.lim<=r.lim}function eF(e){let t=e.graph().ranker;if(typeof t=="function")return t(e);switch(t){case"network-simplex":gw(e);break;case"tight-tree":rF(e);break;case"longest-path":tF(e);break;case"none":break;default:gw(e)}}function rF(e){lp(e),Qw(e)}function gw(e){PG(e)}function oF(e){let t=sF(e);e.graph().dummyChains.forEach(r=>{let n=e.node(r),o=n.edgeObj,i=iF(e,t,o.v,o.w),s=i.path,a=i.lca,l=0,u=s[l],f=!0;for(;r!==o.w;){if(n=e.node(r),f){for(;(u=s[l])!==a&&e.node(u).maxRanks||a>t[l].lim));let u=l,f=n;for(;(f=e.parent(f))!==u;)i.push(f);return{path:o.concat(i.reverse()),lca:u}}function sF(e){let t={},r=0;function n(o){let i=r;e.children(o).forEach(n),t[o]={low:i,lim:r++}}return e.children(Md).forEach(n),t}function aF(e){let t=Js(e,"root",{},"_root"),r=lF(e),n=Object.values(r),o=On(Math.max,n)-1,i=2*o+1;e.graph().nestingRoot=t,e.edges().forEach(a=>e.edge(a).minlen*=i);let s=cF(e)+1;e.children(Md).forEach(a=>Ww(e,t,i,s,o,r,a)),e.graph().nodeRankFactor=i}function Ww(e,t,r,n,o,i,s){var a;let l=e.children(s);if(!l.length){s!==t&&e.setEdge(t,s,{weight:0,minlen:r});return}let u=dw(e,"_bt"),f=dw(e,"_bb"),g=e.node(s);e.setParent(u,s),g.borderTop=u,e.setParent(f,s),g.borderBottom=f,l.forEach(d=>{var p;Ww(e,t,r,n,o,i,d);let h=e.node(d),b=h.borderTop?h.borderTop:d,x=h.borderBottom?h.borderBottom:d,w=h.borderTop?n:2*n,C=b!==x?1:o-((p=i[s])!=null?p:0)+1;e.setEdge(u,b,{weight:w,minlen:C,nestingEdge:!0}),e.setEdge(x,f,{weight:w,minlen:C,nestingEdge:!0})}),e.parent(s)||e.setEdge(t,u,{weight:0,minlen:o+((a=i[s])!=null?a:0)})}function lF(e){let t={};function r(n,o){let i=e.children(n);i&&i.length&&i.forEach(s=>r(s,o+1)),t[n]=o}return e.children(Md).forEach(n=>r(n,1)),t}function cF(e){return e.edges().reduce((t,r)=>t+e.edge(r).weight,0)}function dF(e){let t=e.graph();e.removeNode(t.nestingRoot),delete t.nestingRoot,e.edges().forEach(r=>{e.edge(r).nestingEdge&&e.removeEdge(r)})}function fF(e){function t(r){let n=e.children(r),o=e.node(r);if(n.length&&n.forEach(t),Object.hasOwn(o,"minRank")){o.borderLeft=[],o.borderRight=[];for(let i=o.minRank,s=o.maxRank+1;ihw(e.node(t))),e.edges().forEach(t=>hw(e.edge(t)))}function hw(e){let t=e.width;e.width=e.height,e.height=t}function hF(e){e.nodes().forEach(t=>tp(e.node(t))),e.edges().forEach(t=>{var r;let n=e.edge(t);(r=n.points)==null||r.forEach(tp),Object.hasOwn(n,"y")&&tp(n)})}function tp(e){e.y=-e.y}function mF(e){e.nodes().forEach(t=>rp(e.node(t))),e.edges().forEach(t=>{var r;let n=e.edge(t);(r=n.points)==null||r.forEach(rp),Object.hasOwn(n,"x")&&rp(n)})}function rp(e){let t=e.x;e.x=e.y,e.y=t}function vF(e){let t={},r=e.nodes().filter(a=>!e.children(a).length),n=r.map(a=>e.node(a).rank),o=On(Math.max,n),i=Fl(o+1).map(()=>[]);function s(a){if(t[a])return;t[a]=!0;let l=e.node(a);i[l.rank].push(a);let u=e.successors(a);u&&u.forEach(s)}return r.sort((a,l)=>e.node(a).rank-e.node(l).rank).forEach(s),i}function _F(e,t){let r=0;for(let n=1;nf)),o=t.flatMap(u=>{let f=e.outEdges(u);return f?f.map(g=>({pos:n[g.w],weight:e.edge(g).weight})).sort((g,d)=>g.pos-d.pos):[]}),i=1;for(;i{let f=u.pos+i;a[f]+=u.weight;let g=0;for(;f>0;)f%2&&(g+=a[f+1]),f=f-1>>1,a[f]+=u.weight;l+=u.weight*g}),l}function xF(e,t=[]){return t.map(r=>{let n=e.inEdges(r);if(!n||!n.length)return{v:r};{let o=n.reduce((i,s)=>{let a=e.edge(s),l=e.node(s.v);return{sum:i.sum+a.weight*l.order,weight:i.weight+a.weight}},{sum:0,weight:0});return{v:r,barycenter:o.sum/o.weight,weight:o.weight}}})}function yF(e,t){let r={};e.forEach((o,i)=>{let s={indegree:0,in:[],out:[],vs:[o.v],i};o.barycenter!==void 0&&(s.barycenter=o.barycenter,s.weight=o.weight),r[o.v]=s}),t.edges().forEach(o=>{let i=r[o.v],s=r[o.w];i!==void 0&&s!==void 0&&(s.indegree++,i.out.push(s))});let n=Object.values(r).filter(o=>!o.indegree);return IF(n)}function IF(e){let t=[];function r(o){return i=>{i.merged||(i.barycenter===void 0||o.barycenter===void 0||i.barycenter>=o.barycenter)&&wF(o,i)}}function n(o){return i=>{i.in.push(o),--i.indegree===0&&e.push(i)}}for(;e.length;){let o=e.pop();t.push(o),o.in.reverse().forEach(r(o)),o.out.forEach(n(o))}return t.filter(o=>!o.merged).map(o=>Od(o,["vs","i","barycenter","weight"]))}function wF(e,t){let r=0,n=0;e.weight&&(r+=e.barycenter*e.weight,n+=e.weight),t.weight&&(r+=t.barycenter*t.weight,n+=t.weight),e.vs=t.vs.concat(e.vs),e.barycenter=r/n,e.weight=n,e.i=Math.min(t.i,e.i),t.merged=!0}function CF(e,t){let r=BG(e,f=>Object.hasOwn(f,"barycenter")),n=r.lhs,o=r.rhs.sort((f,g)=>g.i-f.i),i=[],s=0,a=0,l=0;n.sort(BF(!!t)),l=mw(i,o,l),n.forEach(f=>{l+=f.vs.length,i.push(f.vs),s+=f.barycenter*f.weight,a+=f.weight,l=mw(i,o,l)});let u={vs:i.flat(1)};return a&&(u.barycenter=s/a,u.weight=a),u}function mw(e,t,r){let n;for(;t.length&&(n=t[t.length-1]).i<=r;)t.pop(),e.push(n.vs),r++;return r}function BF(e){return(t,r)=>t.barycenterr.barycenter?1:e?r.i-t.i:t.i-r.i}function Dw(e,t,r,n){let o=e.children(t),i=e.node(t),s=i?i.borderLeft:void 0,a=i?i.borderRight:void 0,l={};s&&(o=o.filter(d=>d!==s&&d!==a));let u=xF(e,o);u.forEach(d=>{if(e.children(d.v).length){let p=Dw(e,d.v,r,n);l[d.v]=p,Object.hasOwn(p,"barycenter")&&$F(d,p)}});let f=yF(u,r);EF(f,l);let g=CF(f,n);if(s&&a){g.vs=[s,g.vs,a].flat(1);let d=e.predecessors(s);if(d&&d.length){let p=e.node(d[0]),h=e.predecessors(a),b=e.node(h[0]);Object.hasOwn(g,"barycenter")||(g.barycenter=0,g.weight=0),g.barycenter=(g.barycenter*g.weight+p.order+b.order)/(g.weight+2),g.weight+=2}}return g}function EF(e,t){e.forEach(r=>{r.vs=r.vs.flatMap(n=>t[n]?t[n].vs:n)})}function $F(e,t){e.barycenter!==void 0?(e.barycenter=(e.barycenter*e.weight+t.barycenter*t.weight)/(e.weight+t.weight),e.weight+=t.weight):(e.barycenter=t.barycenter,e.weight=t.weight)}function AF(e,t,r,n){n||(n=e.nodes());let o=GF(e),i=new dn({compound:!0}).setGraph({root:o}).setDefaultNodeLabel(s=>e.node(s));return n.forEach(s=>{let a=e.node(s),l=e.parent(s);if(a.rank===t||a.minRank<=t&&t<=a.maxRank){i.setNode(s),i.setParent(s,l||o);let u=e[r](s);u&&u.forEach(f=>{let g=f.v===s?f.w:f.v,d=i.edge(g,s),p=d!==void 0?d.weight:0;i.setEdge(g,s,{weight:e.edge(f).weight+p})}),Object.hasOwn(a,"minRank")&&i.setNode(s,{borderLeft:a.borderLeft[t],borderRight:a.borderRight[t]})}}),i}function GF(e){let t;for(;e.hasNode(t=ap("_root")););return t}function FF(e,t,r){let n={},o;r.forEach(i=>{let s=e.parent(i),a,l;for(;s;){if(a=e.parent(s),a?(l=n[a],n[a]=s):(l=o,o=s),l&&l!==s){t.setEdge(l,s);return}s=a}})}function Ow(e,t={}){if(typeof t.customOrder=="function"){t.customOrder(e,Ow);return}let r=Zw(e),n=vw(e,Fl(1,r+1),"inEdges"),o=vw(e,Fl(r-1,-1,-1),"outEdges"),i=vF(e);if(_w(e,i),t.disableOptimalOrderHeuristic)return;let s=Number.POSITIVE_INFINITY,a,l=t.constraints||[];for(let u=0,f=0;f<4;++u,++f){SF(u%2?n:o,u%4>=2,l),i=Sl(e);let g=_F(e,i);g{n.has(i)||n.set(i,[]),n.get(i).push(s)};for(let i of e.nodes()){let s=e.node(i);if(typeof s.rank=="number"&&o(s.rank,i),typeof s.minRank=="number"&&typeof s.maxRank=="number")for(let a=s.minRank;a<=s.maxRank;a++)a!==s.rank&&o(a,i)}return t.map(function(i){return AF(e,i,r,n.get(i)||[])})}function SF(e,t,r){let n=new dn;e.forEach(function(o){r.forEach(a=>n.setEdge(a.left,a.right));let i=o.graph().root,s=Dw(o,i,n,t);s.vs.forEach((a,l)=>o.node(a).order=l),FF(o,n,s.vs)})}function _w(e,t){Object.values(t).forEach(r=>r.forEach((n,o)=>e.node(n).order=o))}function ZF(e,t){let r={};function n(o,i){let s=0,a=0,l=o.length,u=i[i.length-1];return i.forEach((f,g)=>{let d=NF(e,f),p=d?e.node(d).order:l;(d||f===u)&&(i.slice(a,g+1).forEach(h=>{let b=e.predecessors(h);b&&b.forEach(x=>{let w=e.node(x),C=w.order;(C{let g=i[f];if(g!==void 0&&e.node(g).dummy){let d=e.predecessors(g);d&&d.forEach(p=>{if(p===void 0)return;let h=e.node(p);h.dummy&&(h.orderu)&&Hw(r,p,g)})}})}function o(i,s){let a=-1,l=-1,u=0;return s.forEach((f,g)=>{if(e.node(f).dummy==="border"){let d=e.predecessors(f);if(d&&d.length){let p=d[0];if(p===void 0)return;l=e.node(p).order,n(s,u,g,a,l),u=g,a=l}}n(s,u,s.length,l,i.length)}),s}return t.length&&t.reduce(o),r}function NF(e,t){if(e.node(t).dummy){let r=e.predecessors(t);if(r)return r.find(n=>e.node(n).dummy)}}function Hw(e,t,r){if(t>r){let o=t;t=r,r=o}let n=e[t];n||(e[t]=n={}),n[r]=!0}function QF(e,t,r){if(t>r){let o=t;t=r,r=o}let n=e[t];return n!==void 0&&Object.hasOwn(n,r)}function XF(e,t,r,n){let o={},i={},s={};return t.forEach(a=>{a.forEach((l,u)=>{o[l]=l,i[l]=l,s[l]=u})}),t.forEach(a=>{let l=-1;a.forEach(u=>{let f=n(u);if(f&&f.length){let g=f.sort((p,h)=>{let b=s[p],x=s[h];return(b!==void 0?b:0)-(x!==void 0?x:0)}),d=(g.length-1)/2;for(let p=Math.floor(d),h=Math.ceil(d);p<=h;++p){let b=g[p];if(b===void 0)continue;let x=s[b];if(x!==void 0&&i[u]===u&&l{var w;let C=(w=i[x.v])!=null?w:0,E=s.edge(x);return Math.max(b,C+(E!==void 0?E:0))},0):i[p]=0}function f(p){let h=s.outEdges(p),b=Number.POSITIVE_INFINITY;h&&(b=h.reduce((w,C)=>{let E=i[C.w],y=s.edge(C);return Math.min(w,(E!==void 0?E:0)-(y!==void 0?y:0))},Number.POSITIVE_INFINITY));let x=e.node(p);b!==Number.POSITIVE_INFINITY&&x.borderType!==a&&(i[p]=Math.max(i[p]!==void 0?i[p]:0,b))}function g(p){return s.predecessors(p)||[]}function d(p){return s.successors(p)||[]}return l(u,g),l(f,d),Object.keys(n).forEach(p=>{var h;let b=r[p];b!==void 0&&(i[p]=(h=i[b])!=null?h:0)}),i}function UF(e,t,r,n){let o=new dn,i=e.graph(),s=DF(i.nodesep,i.edgesep,n);return t.forEach(a=>{let l;a.forEach(u=>{let f=r[u];if(f!==void 0){if(o.setNode(f),l!==void 0){let g=r[l];if(g!==void 0){let d=o.edge(g,f);o.setEdge(g,f,Math.max(s(e,u,l),d||0))}}l=u}})}),o}function LF(e,t){return Object.values(t).reduce((r,n)=>{let o=Number.NEGATIVE_INFINITY,i=Number.POSITIVE_INFINITY;Object.entries(n).forEach(([a,l])=>{let u=OF(e,a)/2;o=Math.max(l+u,o),i=Math.min(l-u,i)});let s=o-i;return s{["l","r"].forEach(s=>{let a=i+s,l=e[a];if(!l||l===t)return;let u=Object.values(l),f=n-On(Math.min,u);s!=="l"&&(f=o-On(Math.max,u)),f&&(e[a]=Hd(l,g=>g+f))})})}function WF(e,t=void 0){let r=e.ul;return r?Hd(r,(n,o)=>{var i,s;if(t){let l=t.toLowerCase(),u=e[l];if(u&&u[o]!==void 0)return u[o]}let a=Object.values(e).map(l=>{let u=l[o];return u!==void 0?u:0}).sort((l,u)=>l-u);return(((i=a[1])!=null?i:0)+((s=a[2])!=null?s:0))/2}):{}}function TF(e){let t=Sl(e),r=Object.assign(ZF(e,t),kF(e,t)),n={},o;["u","d"].forEach(s=>{o=s==="u"?t:Object.values(t).reverse(),["l","r"].forEach(a=>{a==="r"&&(o=o.map(f=>Object.values(f).reverse()));let l=XF(e,o,r,f=>(s==="u"?e.predecessors(f):e.successors(f))||[]),u=RF(e,o,l.root,l.align,a==="r");a==="r"&&(u=Hd(u,f=>-f)),n[s+a]=u})});let i=LF(e,n);return VF(n,i),WF(n,e.graph().align)}function DF(e,t,r){return(n,o,i)=>{let s=n.node(o),a=n.node(i),l=0,u;if(l+=s.width/2,Object.hasOwn(s,"labelpos"))switch(s.labelpos.toLowerCase()){case"l":u=-s.width/2;break;case"r":u=s.width/2;break}if(u&&(l+=r?u:-u),u=void 0,l+=(s.dummy?t:e)/2,l+=(a.dummy?t:e)/2,l+=a.width/2,Object.hasOwn(a,"labelpos"))switch(a.labelpos.toLowerCase()){case"l":u=a.width/2;break;case"r":u=-a.width/2;break}return u&&(l+=r?u:-u),l}}function OF(e,t){return e.node(t).width}function HF(e){e=Fw(e),MF(e),Object.entries(TF(e)).forEach(([t,r])=>e.node(t).x=r)}function MF(e){let t=Sl(e),r=e.graph(),n=r.ranksep,o=r.rankalign,i=0;t.forEach(s=>{let a=s.reduce((l,u)=>{var f;let g=(f=e.node(u).height)!=null?f:0;return l>g?l:g},0);s.forEach(l=>{let u=e.node(l);o==="top"?u.y=i+u.height/2:o==="bottom"?u.y=i+a-u.height/2:u.y=i+a/2}),i+=a+n})}function YF(e,t={}){let r=t.debugTiming?kw:Nw;return r("layout",()=>{let n=r(" buildLayoutGraph",()=>nS(e));return r(" runLayout",()=>zF(n,r,t)),r(" updateInputGraph",()=>PF(e,n)),n})}function zF(e,t,r){t(" makeSpaceForEdgeLabels",()=>oS(e)),t(" removeSelfEdges",()=>gS(e)),t(" acyclic",()=>RG(e)),t(" nestingGraph.run",()=>aF(e)),t(" rank",()=>qG(Fw(e))),t(" injectEdgeLabelProxies",()=>iS(e)),t(" removeEmptyRanks",()=>wG(e)),t(" nestingGraph.cleanup",()=>dF(e)),t(" normalizeRanks",()=>IG(e)),t(" assignRankMinMax",()=>sS(e)),t(" removeEdgeLabelProxies",()=>aS(e)),t(" normalize.run",()=>VG(e)),t(" parentDummyChains",()=>nF(e)),t(" addBorderSegments",()=>uF(e)),t(" order",()=>Ow(e,r)),t(" insertSelfEdges",()=>pS(e)),t(" adjustCoordinateSystem",()=>gF(e)),t(" position",()=>HF(e)),t(" positionSelfEdges",()=>hS(e)),t(" removeBorderNodes",()=>fS(e)),t(" normalize.undo",()=>TG(e)),t(" fixupEdgeLabelCoords",()=>dS(e)),t(" undoCoordinateSystem",()=>pF(e)),t(" translateGraph",()=>lS(e)),t(" assignNodeIntersects",()=>cS(e)),t(" reversePoints",()=>uS(e)),t(" acyclic.undo",()=>LG(e))}function PF(e,t){e.nodes().forEach(r=>{let n=e.node(r),o=t.node(r);n&&(n.x=o.x,n.y=o.y,n.order=o.order,n.rank=o.rank,t.children(r).length&&(n.width=o.width,n.height=o.height))}),e.edges().forEach(r=>{let n=e.edge(r),o=t.edge(r);n.points=o.points,Object.hasOwn(o,"x")&&(n.x=o.x,n.y=o.y)}),e.graph().width=t.graph().width,e.graph().height=t.graph().height}function nS(e){let t=new dn({multigraph:!0,compound:!0}),r=op(e.graph());return t.setGraph(Object.assign({},jF,np(r,JF),Od(r,KF))),e.nodes().forEach(n=>{let o=op(e.node(n)),i=np(o,qF);Object.keys(bw).forEach(a=>{i[a]===void 0&&(i[a]=bw[a])}),t.setNode(n,i);let s=e.parent(n);s!==void 0&&t.setParent(n,s)}),e.edges().forEach(n=>{let o=op(e.edge(n));t.setEdge(n,Object.assign({},tS,np(o,eS),Od(o,rS)))}),t}function oS(e){let t=e.graph();t.ranksep/=2,e.edges().forEach(r=>{let n=e.edge(r);n.minlen*=2,n.labelpos.toLowerCase()!=="c"&&(t.rankdir==="TB"||t.rankdir==="BT"?n.width+=n.labeloffset:n.height+=n.labeloffset)})}function iS(e){e.edges().forEach(t=>{let r=e.edge(t);if(r.width&&r.height){let n=e.node(t.v),o={rank:(e.node(t.w).rank-n.rank)/2+n.rank,e:t};Js(e,"edge-proxy",o,"_ep")}})}function sS(e){let t=0;e.nodes().forEach(r=>{let n=e.node(r);n.borderTop&&(n.minRank=e.node(n.borderTop).rank,n.maxRank=e.node(n.borderBottom).rank,t=Math.max(t,n.maxRank))}),e.graph().maxRank=t}function aS(e){e.nodes().forEach(t=>{let r=e.node(t);if(r.dummy==="edge-proxy"){let n=r;e.edge(n.e).labelRank=r.rank,e.removeNode(t)}})}function lS(e){let t=Number.POSITIVE_INFINITY,r=0,n=Number.POSITIVE_INFINITY,o=0,i=e.graph(),s=i.marginx||0,a=i.marginy||0;function l(u){let f=u.x,g=u.y,d=u.width,p=u.height;t=Math.min(t,f-d/2),r=Math.max(r,f+d/2),n=Math.min(n,g-p/2),o=Math.max(o,g+p/2)}e.nodes().forEach(u=>l(e.node(u))),e.edges().forEach(u=>{let f=e.edge(u);Object.hasOwn(f,"x")&&l(f)}),t-=s,n-=a,e.nodes().forEach(u=>{let f=e.node(u);f.x-=t,f.y-=n}),e.edges().forEach(u=>{let f=e.edge(u);f.points.forEach(g=>{g.x-=t,g.y-=n}),Object.hasOwn(f,"x")&&(f.x-=t),Object.hasOwn(f,"y")&&(f.y-=n)}),i.width=r-t+s,i.height=o-n+a}function cS(e){e.edges().forEach(t=>{let r=e.edge(t),n=e.node(t.v),o=e.node(t.w),i,s;r.points?(i=r.points[0],s=r.points[r.points.length-1]):(r.points=[],i=o,s=n),r.points.unshift(cw(n,i)),r.points.push(cw(o,s))})}function dS(e){e.edges().forEach(t=>{let r=e.edge(t);if(Object.hasOwn(r,"x"))switch((r.labelpos==="l"||r.labelpos==="r")&&(r.width-=r.labeloffset),r.labelpos){case"l":r.x-=r.width/2+r.labeloffset;break;case"r":r.x+=r.width/2+r.labeloffset;break}})}function uS(e){e.edges().forEach(t=>{let r=e.edge(t);r.reversed&&r.points.reverse()})}function fS(e){e.nodes().forEach(t=>{if(e.children(t).length){let r=e.node(t),n=e.node(r.borderTop),o=e.node(r.borderBottom),i=e.node(r.borderLeft[r.borderLeft.length-1]),s=e.node(r.borderRight[r.borderRight.length-1]);r.width=Math.abs(s.x-i.x),r.height=Math.abs(o.y-n.y),r.x=i.x+r.width/2,r.y=n.y+r.height/2}}),e.nodes().forEach(t=>{e.node(t).dummy==="border"&&e.removeNode(t)})}function gS(e){e.edges().forEach(t=>{if(t.v===t.w){let r=e.node(t.v);r.selfEdges||(r.selfEdges=[]),r.selfEdges.push({e:t,label:e.edge(t)}),e.removeEdge(t)}})}function pS(e){Sl(e).forEach(t=>{let r=0;t.forEach((n,o)=>{let i=e.node(n);i.order=o+r,(i.selfEdges||[]).forEach(s=>{Js(e,"selfedge",{width:s.label.width,height:s.label.height,rank:i.rank,order:o+ ++r,e:s.e,label:s.label},"_se")}),delete i.selfEdges})})}function hS(e){e.nodes().forEach(t=>{let r=e.node(t);if(r.dummy==="selfedge"){let n=r,o=e.node(n.e.v),i=o.x+o.width/2,s=o.y,a=r.x-i,l=o.height/2;e.setEdge(n.e,n.label),e.removeNode(t),n.label.points=[{x:i+2*a/3,y:s-l},{x:i+5*a/6,y:s-l},{x:i+a,y:s},{x:i+5*a/6,y:s+l},{x:i+2*a/3,y:s+l}],n.label.x=r.x,n.label.y=r.y}})}function np(e,t){return Hd(Od(e,t),Number)}function op(e){let t={};return e&&Object.entries(e).forEach(([r,n])=>{typeof r=="string"&&(r=r.toLowerCase()),t[r]=n}),t}function mS(e){let t=Sl(e),r=new dn({compound:!0,multigraph:!0}).setGraph({});return e.nodes().forEach(n=>{r.setNode(n,{label:n}),r.setParent(n,"layer"+e.node(n).rank)}),e.edges().forEach(n=>r.setEdge(n.v,n.w,{},n.name)),t.forEach((n,o)=>{let i="layer"+o;r.setNode(i,{rank:"same"}),n.reduce((s,a)=>(r.setEdge(s,a,{style:"invis"}),a))}),r}var xw,zA,PA,JA,yw,jA,Iw,dn,qA,ww,sp,oG,Bw,aG,uG,Dd,Sw,EG,Md,AG,GG,SG,ZG,Qw,YG,zG,PG,qG,tF,nF,uF,JF,jF,KF,qF,bw,eS,tS,rS,vS,up,Mw=v(()=>{xw=Object.defineProperty,zA=(e,t,r)=>t in e?xw(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,PA=(e,t)=>{for(var r in t)xw(e,r,{get:t[r],enumerable:!0})},JA=(e,t,r)=>zA(e,typeof t!="symbol"?t+"":t,r),yw={};PA(yw,{Graph:()=>dn,alg:()=>sp,json:()=>ww,version:()=>qA});jA=Object.defineProperty,Iw=(e,t)=>{for(var r in t)jA(e,r,{get:t[r],enumerable:!0})},dn=class{constructor(e){this._isDirected=!0,this._isMultigraph=!1,this._isCompound=!1,this._nodes={},this._in={},this._preds={},this._out={},this._sucs={},this._edgeObjs={},this._edgeLabels={},this._nodeCount=0,this._edgeCount=0,this._defaultNodeLabelFn=()=>{},this._defaultEdgeLabelFn=()=>{},e&&(this._isDirected="directed"in e?e.directed:!0,this._isMultigraph="multigraph"in e?e.multigraph:!1,this._isCompound="compound"in e?e.compound:!1),this._isCompound&&(this._parent={},this._children={},this._children["\0"]={})}isDirected(){return this._isDirected}isMultigraph(){return this._isMultigraph}isCompound(){return this._isCompound}setGraph(e){return this._label=e,this}graph(){return this._label}setDefaultNodeLabel(e){return typeof e!="function"?this._defaultNodeLabelFn=()=>e:this._defaultNodeLabelFn=e,this}nodeCount(){return this._nodeCount}nodes(){return Object.keys(this._nodes)}sources(){return this.nodes().filter(e=>Object.keys(this._in[e]).length===0)}sinks(){return this.nodes().filter(e=>Object.keys(this._out[e]).length===0)}setNodes(e,t){return e.forEach(r=>{t!==void 0?this.setNode(r,t):this.setNode(r)}),this}setNode(e,t){return e in this._nodes?(arguments.length>1&&(this._nodes[e]=t),this):(this._nodes[e]=arguments.length>1?t:this._defaultNodeLabelFn(e),this._isCompound&&(this._parent[e]="\0",this._children[e]={},this._children["\0"][e]=!0),this._in[e]={},this._preds[e]={},this._out[e]={},this._sucs[e]={},++this._nodeCount,this)}node(e){return this._nodes[e]}hasNode(e){return e in this._nodes}removeNode(e){if(e in this._nodes){let t=r=>this.removeEdge(this._edgeObjs[r]);delete this._nodes[e],this._isCompound&&(this._removeFromParentsChildList(e),delete this._parent[e],this.children(e).forEach(r=>{this.setParent(r)}),delete this._children[e]),Object.keys(this._in[e]).forEach(t),delete this._in[e],delete this._preds[e],Object.keys(this._out[e]).forEach(t),delete this._out[e],delete this._sucs[e],--this._nodeCount}return this}setParent(e,t){if(!this._isCompound)throw new Error("Cannot set parent in a non-compound graph");if(t===void 0)t="\0";else{t+="";for(let r=t;r!==void 0;r=this.parent(r))if(r===e)throw new Error("Setting "+t+" as parent of "+e+" would create a cycle");this.setNode(t)}return this.setNode(e),this._removeFromParentsChildList(e),this._parent[e]=t,this._children[t][e]=!0,this}parent(e){if(this._isCompound){let t=this._parent[e];if(t!=="\0")return t}}children(e="\0"){if(this._isCompound){let t=this._children[e];if(t)return Object.keys(t)}else{if(e==="\0")return this.nodes();if(this.hasNode(e))return[]}return[]}predecessors(e){let t=this._preds[e];if(t)return Object.keys(t)}successors(e){let t=this._sucs[e];if(t)return Object.keys(t)}neighbors(e){let t=this.predecessors(e);if(t){let r=new Set(t);for(let n of this.successors(e))r.add(n);return Array.from(r.values())}}isLeaf(e){let t;return this.isDirected()?t=this.successors(e):t=this.neighbors(e),t.length===0}filterNodes(e){let t=new this.constructor({directed:this._isDirected,multigraph:this._isMultigraph,compound:this._isCompound});t.setGraph(this.graph()),Object.entries(this._nodes).forEach(([o,i])=>{e(o)&&t.setNode(o,i)}),Object.values(this._edgeObjs).forEach(o=>{t.hasNode(o.v)&&t.hasNode(o.w)&&t.setEdge(o,this.edge(o))});let r={},n=o=>{let i=this.parent(o);return!i||t.hasNode(i)?(r[o]=i??void 0,i??void 0):i in r?r[i]:n(i)};return this._isCompound&&t.nodes().forEach(o=>t.setParent(o,n(o))),t}setDefaultEdgeLabel(e){return typeof e!="function"?this._defaultEdgeLabelFn=()=>e:this._defaultEdgeLabelFn=e,this}edgeCount(){return this._edgeCount}edges(){return Object.values(this._edgeObjs)}setPath(e,t){return e.reduce((r,n)=>(t!==void 0?this.setEdge(r,n,t):this.setEdge(r,n),n)),this}setEdge(e,t,r,n){let o,i,s,a,l=!1;typeof e=="object"&&e!==null&&"v"in e?(o=e.v,i=e.w,s=e.name,arguments.length===2&&(a=t,l=!0)):(o=e,i=t,s=n,arguments.length>2&&(a=r,l=!0)),o=""+o,i=""+i,s!==void 0&&(s=""+s);let u=Gl(this._isDirected,o,i,s);if(u in this._edgeLabels)return l&&(this._edgeLabels[u]=a),this;if(s!==void 0&&!this._isMultigraph)throw new Error("Cannot set a named edge when isMultigraph = false");this.setNode(o),this.setNode(i),this._edgeLabels[u]=l?a:this._defaultEdgeLabelFn(o,i,s);let f=KA(this._isDirected,o,i,s);return o=f.v,i=f.w,Object.freeze(f),this._edgeObjs[u]=f,aw(this._preds[i],o),aw(this._sucs[o],i),this._in[i][u]=f,this._out[o][u]=f,this._edgeCount++,this}edge(e,t,r){let n=arguments.length===1?qg(this._isDirected,e):Gl(this._isDirected,e,t,r);return this._edgeLabels[n]}edgeAsObj(e,t,r){let n=arguments.length===1?this.edge(e):this.edge(e,t,r);return typeof n!="object"?{label:n}:n}hasEdge(e,t,r){return(arguments.length===1?qg(this._isDirected,e):Gl(this._isDirected,e,t,r))in this._edgeLabels}removeEdge(e,t,r){let n=arguments.length===1?qg(this._isDirected,e):Gl(this._isDirected,e,t,r),o=this._edgeObjs[n];if(o){let i=o.v,s=o.w;delete this._edgeLabels[n],delete this._edgeObjs[n],lw(this._preds[s],i),lw(this._sucs[i],s),delete this._in[s][n],delete this._out[i][n],this._edgeCount--}return this}inEdges(e,t){return this.isDirected()?this.filterEdges(this._in[e],e,t):this.nodeEdges(e,t)}outEdges(e,t){return this.isDirected()?this.filterEdges(this._out[e],e,t):this.nodeEdges(e,t)}nodeEdges(e,t){if(e in this._nodes)return this.filterEdges({...this._in[e],...this._out[e]},e,t)}_removeFromParentsChildList(e){delete this._children[this._parent[e]][e]}filterEdges(e,t,r){if(!e)return;let n=Object.values(e);return r?n.filter(o=>o.v===t&&o.w===r||o.v===r&&o.w===t):n}};qA="4.0.1",ww={};Iw(ww,{read:()=>nG,write:()=>eG});sp={};Iw(sp,{CycleException:()=>Dd,bellmanFord:()=>Cw,components:()=>sG,dijkstra:()=>Td,dijkstraAll:()=>cG,findCycles:()=>dG,floydWarshall:()=>fG,isAcyclic:()=>pG,postorder:()=>mG,preorder:()=>vG,prim:()=>_G,shortestPaths:()=>bG,tarjan:()=>Ew,topsort:()=>$w});oG=()=>1;Bw=class{constructor(){this._arr=[],this._keyIndices={}}size(){return this._arr.length}keys(){return this._arr.map(e=>e.key)}has(e){return e in this._keyIndices}priority(e){let t=this._keyIndices[e];if(t!==void 0)return this._arr[t].priority}min(){if(this.size()===0)throw new Error("Queue underflow");return this._arr[0].key}add(e,t){let r=this._keyIndices,n=String(e);if(!(n in r)){let o=this._arr,i=o.length;return r[n]=i,o.push({key:n,priority:t}),this._decrease(i),!0}return!1}removeMin(){this._swap(0,this._arr.length-1);let e=this._arr.pop();return delete this._keyIndices[e.key],this._heapify(0),e.key}decrease(e,t){let r=this._keyIndices[e];if(r===void 0)throw new Error(`Key not found: ${e}`);let n=this._arr[r].priority;if(t>n)throw new Error(`New priority is greater than current priority. Key: ${e} Old: ${n} New: ${t}`);this._arr[r].priority=t,this._decrease(r)}_heapify(e){let t=this._arr,r=2*e,n=r+1,o=e;r>1,!(t[n].priority1;uG=()=>1;Dd=class extends Error{constructor(...e){super(...e)}};Sw=65535;EG=0;Md="\0",AG="3.0.0",GG=class{constructor(){JA(this,"_sentinel");let e={};e._next=e._prev=e,this._sentinel=e}dequeue(){let e=this._sentinel,t=e._prev;if(t!==e)return uw(t),t}enqueue(e){let t=this._sentinel;e._prev&&e._next&&uw(e),e._next=t._next,t._next._prev=e,t._next=e,e._prev=t}toString(){let e=[],t=this._sentinel,r=t._prev;for(;r!==t;)e.push(JSON.stringify(r,FG)),r=r._prev;return"["+e.join(", ")+"]"}};SG=GG,ZG=()=>1;Qw=DG;({preorder:YG,postorder:zG}=sp),PG=Ri;Ri.initLowLimValues=dp;Ri.initCutValues=cp;Ri.calcCutValue=Xw;Ri.leaveEdge=Uw;Ri.enterEdge=Lw;Ri.exchangeEdges=Vw;qG=eF;tF=lp;nF=oF;uF=fF;JF=["nodesep","edgesep","ranksep","marginx","marginy"],jF={ranksep:50,edgesep:20,nodesep:50,rankdir:"TB",rankalign:"center"},KF=["acyclicer","ranker","rankdir","align","rankalign"],qF=["width","height","rank"],bw={width:0,height:0},eS=["minlen","weight","width","height","labeloffset"],tS={minlen:1,weight:1,width:0,height:0,labeloffset:10,labelpos:"r"},rS=["labelpos"];vS={graphlib:yw,version:AG,layout:YF,debug:mS,util:{time:kw,notime:Nw}},up=vS;});var zw={};Pd(zw,{default:()=>Yw});function Yw(e,t){q(t,!0);let r=188,n=66;function o(f){let g=new up.graphlib.Graph;g.setGraph({rankdir:"TB",nodesep:56,ranksep:84,marginx:24,marginy:24}),g.setDefaultEdgeLabel(()=>({}));for(let h of f.nodes)g.setNode(h.fqn,{width:r,height:n});for(let h of f.edges)g.setEdge(h.from,h.to);up.layout(g);let d=f.nodes.map(h=>{let b=g.node(h.fqn);return{id:h.fqn,position:{x:b.x-r/2,y:b.y-n/2},data:{label:h.label,kind:h.kind,summary:h.summary??""},class:`c4-node ${h.kind}`,width:r,height:n}}),p=f.edges.map((h,b)=>({id:`e${b}`,source:h.from,target:h.to,label:h.label||void 0,type:"smoothstep",animated:h.kind==="trigger",class:`c4-edge ${h.kind}`}));return{nodes:d,edges:p}}let i=o(t.scene),s=ye(Dt(i.nodes)),a=ye(Dt(i.edges));var l=bS(),u=V(l);Xi(u,{fitView:!0,minZoom:.2,maxZoom:2.5,proOptions:{hideAttribution:!0},get nodes(){return c(s)},set nodes(f){M(s,f,!0)},get edges(){return c(a)},set edges(f){M(a,f,!0)},children:(f,g)=>{var d=_S(),p=le(d);Ys(p,{gap:22});var h=O(p,2);zs(h,{pannable:!0,zoomable:!0});var b=O(h,2);Ms(b,{showLock:!1}),F(f,d)},$$slots:{default:!0}}),Q(l),F(e,l),ee()}var _S,bS,Pw=v(()=>{ve();ie();Kg();Mw();_S=J(" ",1),bS=J('
            ')});var Jw=v(()=>{});function fp(e,t){q(t,!0);let r=t.data.placed,n=t.data.act;function o(B){return B?B.startsWith("event:")?{kind:"onevent",title:B.slice(6)}:B==="client"?{kind:"http",title:"client"}:B==="scheduler"?{kind:"schedule",title:"scheduler"}:B==="caller"?{kind:"caller",title:"caller"}:null:null}let i=o(r.id),s=i?i.kind:r.kind,a=i?i.title:r.label,l=i?"initiator":r.kind,u=!!r.id,f=B=>{u&&(B.metaKey||B.ctrlKey)&&(B.preventDefault(),t.data.onusages?.(r.id,B))};var g=yS(),d=V(g);let p;var h=V(d),b=V(h,!0);Q(h);var x=O(h,2),w=V(x,!0);Q(x),Q(d);var C=O(d,2),E=V(C),y=O(E);{var U=B=>{var k=xS();te(G=>{Je(k,0,`seq-act ${n.owner?"seq-act-owner":""}`,"svelte-jnt8ke"),D(k,"x",n.x-5),D(k,"y",n.top),D(k,"height",G)},[()=>Math.max(10,n.bottom-n.top)]),F(B,k)};ce(y,B=>{n&&B(U)})}Q(C),Q(g),te(()=>{p=Je(d,1,`seq-card c4-node ${l??""}`,"svelte-jnt8ke",p,{interactive:u}),Oe(d,`left:${r.card.x??""}px; top:${r.card.y??""}px; width:${r.card.w??""}px; height:${r.card.h??""}px`),D(d,"role",u?"button":void 0),D(d,"tabindex",u?0:void 0),oe(b,s),oe(w,a),D(E,"x1",r.lifeline_x),D(E,"y1",r.top),D(E,"x2",r.lifeline_x),D(E,"y2",r.bottom)}),Ft("mouseenter",d,B=>u&&t.data.oninfo?.(r.id,B)),Ft("mouseleave",d,()=>u&&t.data.oninfoend?.()),St("click",d,f),F(e,g),ee()}var xS,yS,jw=v(()=>{ve();ie();Jw();xS=Ge(''),yS=J('
            ');yn(["click"])});var Kw=v(()=>{});function gp(e,t){q(t,!0);var r=wS(),n=V(r),o=V(n,!0);Q(n);var i=O(n,2),s=V(i);Q(i);var a=O(i,2);Ne(a,17,()=>t.data.dividers,l=>l.y,(l,u)=>{var f=IS(),g=le(f),d=O(g,2),p=V(d);Q(d),te(()=>{Oe(g,`top:${c(u).y??""}px`),Oe(d,`top:${c(u).y??""}px`),oe(p,`[${(c(u).guard||"else")??""}]`)}),F(l,f)}),Q(r),te(()=>{D(r,"title",`${t.data.kind??""} [${t.data.label??""}]`),oe(o,t.data.kind),oe(s,`[${t.data.label??""}]`)}),F(e,r),ee()}var IS,wS,qw=v(()=>{ve();ie();Kw();IS=J('
            ',1),wS=J('
            ')});var eC=v(()=>{});function pp(e,t){q(t,!0);let r=g=>g?g.length*7.8+14:0;function n(g){return g==="Ok"||g==="Some"?{color:"var(--seq-ok)",text:`\u21A9 ${g}`}:g==="Err"||g==="None"?{color:"var(--seq-err)",text:`\u21A9 ${g}`}:{color:"var(--ink-faint)",text:g?`\u21A9 ${g}`:"\u21A9 return"}}let o=g=>g.detail?g.label?`<${g.detail}>`:` ${g.detail}`:"",i=g=>(t.data.lifelineX[g.from]??g.from_x)-17,s=g=>g.kind==="self"?`${g.from}::${g.label}`:`${g.to}::${g.label}`,a=(g,d)=>{(d.metaKey||d.ctrlKey)&&(d.preventDefault(),t.data.onusages?.(s(g),d))},l=(g,d)=>{(d.metaKey||d.ctrlKey)&&(d.preventDefault(),t.data.onusages?.(g,d))},u=g=>(g??"").split(/([A-Za-z_][A-Za-z0-9_]*)/).map((d,p)=>({text:d,fqn:p%2===1?t.data.typeFqn?.[d]??null:null})).filter(d=>d.text!=="");var f=AS();Ne(f,21,()=>t.data.messages,et,(g,d)=>{var p=Xe(),h=le(p);{var b=C=>{var E=BS(),y=le(E),U=O(y),B=O(U);{var k=Z=>{let $=_(()=>(c(d).from_x+c(d).to_x)/2),X=_(()=>c(d).label+(c(d).detail??""));var I=CS(),A=le(I),S=O(A),T=V(S),K=V(T,!0);Q(T);var Y=O(T);Ne(Y,17,()=>u(c(d).detail),et,(z,j)=>{var re=Xe(),ae=le(re);{var ne=fe=>{var ge=tC(),pe=V(ge,!0);Q(ge),te(()=>oe(pe,c(j).text)),Ft("mouseenter",ge,we=>t.data.oninfo?.(c(j).fqn,we)),Ft("mouseleave",ge,()=>t.data.oninfoend?.()),St("click",ge,we=>l(c(j).fqn,we)),F(fe,ge)},Ie=fe=>{var ge=rC(),pe=V(ge,!0);Q(ge),te(()=>oe(pe,c(j).text)),F(fe,ge)};ce(ae,fe=>{c(j).fqn?fe(ne):fe(Ie,-1)})}F(z,re)}),Q(S),te((z,j)=>{D(A,"x",z),D(A,"y",c(d).y-21),D(A,"width",j),D(S,"x",c($)),D(S,"y",c(d).y-9),oe(K,c(d).label)},[()=>c($)-r(c(X))/2,()=>r(c(X))]),Ft("mouseenter",T,z=>t.data.oninfo?.(s(c(d)),z)),Ft("mouseleave",T,()=>t.data.oninfoend?.()),St("click",T,z=>a(c(d),z)),F(Z,I)};ce(B,Z=>{c(d).label&&Z(k)})}var G=O(B),W=O(G),H=V(W,!0);Q(W),te((Z,$)=>{D(y,"x1",c(d).from_x),D(y,"y1",c(d).y),D(y,"x2",c(d).to_x),D(y,"y2",c(d).y),D(U,"d",`M${c(d).to_x-c(d).dir*7},${c(d).y-4} L${c(d).to_x??""},${c(d).y??""} L${c(d).to_x-c(d).dir*7},${c(d).y+4} z`),D(G,"cx",Z),D(G,"cy",c(d).y),D(W,"x",$),D(W,"y",c(d).y+3),oe(H,c(d).step)},[()=>i(c(d)),()=>i(c(d))]),F(C,E)},x=C=>{let E=_(()=>c(d).from_x+5);var y=ES(),U=le(y),B=O(U),k=O(B),G=V(k,!0);Q(k);var W=O(k),H=O(W),Z=V(H,!0);Q(H),te(($,X)=>{D(U,"d",`M${c(E)??""},${c(d).y??""} h34 a6 6 0 0 1 6 6 v8 a6 6 0 0 1 -6 6 h-34`),D(B,"d",`M${c(E)+7},${c(d).y+16} L${c(E)??""},${c(d).y+20} L${c(E)+7},${c(d).y+24}`),D(k,"x",c(E)+46),D(k,"y",c(d).y+4),oe(G,c(d).label),D(W,"cx",$),D(W,"cy",c(d).y),D(H,"x",X),D(H,"y",c(d).y+3),oe(Z,c(d).step)},[()=>i(c(d)),()=>i(c(d))]),Ft("mouseenter",k,$=>t.data.oninfo?.(s(c(d)),$)),Ft("mouseleave",k,()=>t.data.oninfoend?.()),St("click",k,$=>a(c(d),$)),F(C,y)},w=C=>{let E=_(()=>n(c(d).label)),y=_(()=>(c(d).from_x+c(d).to_x)/2),U=_(()=>o(c(d))),B=_(()=>c(E).text+c(U));var k=$S(),G=le(k),W=O(G),H=O(W),Z=O(H),$=V(Z,!0),X=O($);Ne(X,17,()=>u(c(U)),et,(I,A)=>{var S=Xe(),T=le(S);{var K=z=>{var j=tC(),re=V(j,!0);Q(j),te(()=>oe(re,c(A).text)),Ft("mouseenter",j,ae=>t.data.oninfo?.(c(A).fqn,ae)),Ft("mouseleave",j,()=>t.data.oninfoend?.()),St("click",j,ae=>l(c(A).fqn,ae)),F(z,j)},Y=z=>{var j=rC(),re=V(j,!0);Q(j),te(()=>oe(re,c(A).text)),F(z,j)};ce(T,z=>{c(A).fqn?z(K):z(Y,-1)})}F(I,S)}),Q(Z),te((I,A)=>{D(G,"x1",c(d).from_x),D(G,"y1",c(d).y),D(G,"x2",c(d).to_x),D(G,"y2",c(d).y),D(G,"stroke",c(E).color),D(W,"d",`M${c(d).to_x-c(d).dir*7},${c(d).y-4} L${c(d).to_x??""},${c(d).y??""} L${c(d).to_x-c(d).dir*7},${c(d).y+4}`),D(W,"stroke",c(E).color),D(H,"x",I),D(H,"y",c(d).y-21),D(H,"width",A),D(Z,"x",c(y)),D(Z,"y",c(d).y-9),D(Z,"fill",c(E).color),oe($,c(E).text)},[()=>c(y)-r(c(B))/2,()=>r(c(B))]),F(C,k)};ce(h,C=>{c(d).kind==="call"?C(b):c(d).kind==="self"?C(x,1):C(w,-1)})}F(g,p)}),Q(f),te(()=>{D(f,"width",t.data.width),D(f,"height",t.data.height),D(f,"viewBox",`0 0 ${t.data.width??""} ${t.data.height??""}`)}),F(e,f),ee()}var tC,rC,CS,BS,ES,$S,AS,nC=v(()=>{ve();ie();eC();tC=Ge(' '),rC=Ge(' '),CS=Ge(' ',1),BS=Ge(' ',1),ES=Ge(' ',1),$S=Ge(' ',1),AS=Ge('');yn(["click"])});var oC=v(()=>{});var sC={};Pd(sC,{default:()=>iC});function iC(e,t){q(t,!0);let r=P(t,"oninfo",3,null),n=P(t,"oninfoend",3,null),o=P(t,"onusages",3,null),i=P(t,"typeFqn",3,null),s=typeof document<"u"&&document.documentElement.getAttribute("data-theme")==="light"?"light":"dark",a={lifeline:fp,fragment:gp,messages:pp},l=y=>(y??"").split("::").pop();function u(y){if(!y||!Array.isArray(y.participants))return{nodes:[],edges:[]};let U=new Map((y.activations??[]).map(G=>[G.participant,G])),B=Object.fromEntries(y.participants.map(G=>[G.id,G.lifeline_x]));return{nodes:[...y.fragments.map((G,W)=>({id:`frag${W}`,type:"fragment",position:{x:G.rect.x,y:G.rect.y},width:G.rect.w,height:G.rect.h,data:{kind:G.kind,label:G.label,dividers:G.dividers.map(H=>({guard:H.guard,y:H.y-G.rect.y}))},class:"seq-shell",draggable:!1,selectable:!1,connectable:!1,zIndex:2})),...y.participants.map(G=>({id:G.id,type:"lifeline",position:{x:0,y:0},width:y.width,height:y.height,data:{placed:G,act:U.get(G.id)??null,oninfo:r(),oninfoend:n(),onusages:o()},class:"seq-shell",draggable:!1,selectable:!1,connectable:!1,zIndex:1})),{id:"__messages",type:"messages",position:{x:0,y:0},width:y.width,height:y.height,data:{messages:y.messages,width:y.width,height:y.height,lifelineX:B,oninfo:r(),oninfoend:n(),onusages:o(),typeFqn:i()},class:"seq-shell",draggable:!1,selectable:!1,connectable:!1,zIndex:3}],edges:[]}}let f=_(()=>u(t.layout)),g=ye(Dt([])),d=ye(Dt([]));st(()=>{M(g,c(f).nodes,!0),M(d,c(f).edges,!0)});var p=FS(),h=V(p),b=V(h),x=O(V(b),2),w=V(x,!0);Q(x),Q(b),Ct(2),Q(h);var C=O(h,2),E=V(C);Xi(E,{get nodeTypes(){return a},fitView:!0,get colorMode(){return s},minZoom:.2,maxZoom:2.5,nodesDraggable:!1,nodesConnectable:!1,elementsSelectable:!1,proOptions:{hideAttribution:!0},get nodes(){return c(g)},set nodes(y){M(g,y,!0)},get edges(){return c(d)},set edges(y){M(d,y,!0)},children:(y,U)=>{var B=GS(),k=le(B);Ys(k,{gap:24});var G=O(k,2);zs(G,{pannable:!0,zoomable:!0});var W=O(G,2);Ms(W,{showLock:!1}),F(y,B)},$$slots:{default:!0}}),Q(C),Q(p),te(y=>oe(w,y),[()=>l(t.scene?.entry)]),F(e,p),ee()}var GS,FS,aC=v(()=>{ve();ie();Kg();jw();qw();nC();oC();GS=J(" ",1),FS=J('
            flow
            sequence diagram \u2014 scroll to zoom \xB7 drag to pan
            ')});nn();ve();ie();nn();ve();ie();ve();ie();var UB=J(''),LB=J(''),VB=J('
              '),WB=J('
            • ');function Va(e,t){q(t,!0);var r=WB(),n=V(r),o=V(n);{var i=p=>{var h=UB();F(p,h)},s=p=>{var h=LB();F(p,h)};ce(o,p=>{t.node.children.length?p(i):p(s,-1)})}var a=O(o,2),l=V(a),u=O(l,2),f=V(u,!0);Q(u),Q(a),Q(n);var g=O(n,2);{var d=p=>{var h=VB();Ne(h,21,()=>t.node.children,et,(b,x)=>{Va(b,{get node(){return c(x)}})}),Q(h),F(p,h)};ce(g,p=>{t.node.children.length&&p(d)})}Q(r),te(()=>{D(r,"data-search",t.node.fqn),D(a,"href",t.node.href),Je(l,1,`kind-dot ${t.node.kind??""}`),oe(f,t.node.name)}),F(e,r),ee()}var TB=J(''),DB=J('
            • '),OB=J('
                '),HB=J(''),MB=J('
                • '),YB=J('');function hf(e,t){q(t,!0);let r=P(t,"docGroups",19,()=>[]);var n=YB(),o=V(n),i=V(o),s=V(i);{var a=p=>{var h=TB();te(()=>D(h,"src",`${t.site.prefix??""}${t.site.logoFilename??""}`)),F(p,h)};ce(s,p=>{t.site.logoFilename&&p(a)})}var l=O(s,2),u=V(l,!0);Ct(),Q(l),Q(i),Q(o);var f=O(o,4);{var g=p=>{var h=HB();Ne(h,21,r,et,(b,x)=>{var w=OB(),C=V(w),E=V(C,!0);Q(C);var y=O(C,2);Ne(y,21,()=>c(x).items,et,(U,B)=>{var k=DB(),G=V(k),W=V(G,!0);Q(G),Q(k),te(()=>{D(G,"href",c(B).href),oe(W,c(B).title)}),F(U,k)}),Q(y),Q(w),te(()=>oe(E,c(x).title)),F(b,w)}),Q(h),F(p,h)};ce(f,p=>{r().length&&p(g)})}var d=O(f,2);Ne(d,21,()=>t.sidebar,et,(p,h)=>{var b=MB(),x=V(b),w=O(V(x),2),C=V(w,!0);Q(w),Q(x);var E=O(x,2);Ne(E,21,()=>c(h).nodes,et,(y,U)=>{Va(y,{get node(){return c(U)}})}),Q(E),Q(b),te(()=>{D(b,"data-search",c(h).label),D(w,"href",c(h).href),oe(C,c(h).label)}),F(p,b)}),Q(d),Q(n),te(()=>{D(i,"href",`${t.site.prefix??""}index.html`),oe(u,t.site.name)}),F(e,n),ee()}ve();ie();ve();ie();nn();var SS=J('
                  '),ZS=J('
                  ');function Zl(e,t){q(t,!0);let r=ye(null);Bs(async()=>{if(!c(r)||t.diagram.diagram==="empty")return;let{mount:a}=await Promise.resolve().then(()=>(nn(),Zv)),l=t.diagram.diagram==="c4",u=l?await Promise.resolve().then(()=>(Pw(),zw)):await Promise.resolve().then(()=>(aC(),sC)),f=l?{scene:t.diagram.scene}:{scene:t.diagram.scene,layout:t.diagram.layout};a(u.default,{target:c(r),props:f})});var n=Xe(),o=le(n);{var i=a=>{var l=SS(),u=V(l);Q(l),te(()=>oe(u,`No ${t.diagram.eyebrow??""} diagram available.`)),F(a,l)},s=a=>{var l=ZS(),u=V(l),f=V(u),g=V(f,!0);Q(f);var d=O(f,2),p=V(d,!0);Q(d),Q(u);var h=O(u,2);Dr(h,b=>M(r,b),()=>c(r)),Q(l),te(()=>{oe(g,t.diagram.caption),oe(p,t.diagram.diagram==="sequence"?"play \xB7 scrub the flow":"scroll to zoom \xB7 drag to pan"),D(h,"data-diagram",t.diagram.diagram)}),F(a,l)};ce(o,a=>{t.diagram.diagram==="empty"?a(i):a(s,-1)})}F(e,n),ee()}var kS=J('
                  '),NS=J(`
                  Architecture documentation

                  A C4 model of the workspace: persons, systems, and their containers and + components, with relationships and animated sequence flows.

                  `,1);function hp(e,t){q(t,!0);var r=NS(),n=le(r),o=O(V(n),2),i=V(o,!0);Q(o),Ct(2),Q(n);var s=O(n,2);Zl(s,{get diagram(){return t.page.contextDiagram}});var a=O(s,2);Ne(a,21,()=>t.page.cards,et,(l,u)=>{var f=kS(),g=V(f),d=V(g,!0);Q(g);var p=O(g,2),h=V(p,!0);Q(p),Q(f),te(()=>{D(f,"href",c(u).href),oe(d,c(u).name),oe(h,c(u).meta)}),F(l,f)}),Q(a),te(()=>oe(i,t.page.title)),F(e,r),ee()}ve();ie();ve();ie();ve();ie();var QS=J(''),XS=J(' '),RS=J(' '),US=J(' '),LS=J('
                • '),VS=J('

                    '),WS=J('
                    ');function mp(e,t){q(t,!0);var r=Xe(),n=le(r);{var o=i=>{var s=WS();Ne(s,21,()=>t.groups,et,(a,l)=>{var u=VS(),f=V(u),g=V(f,!0);Q(f);var d=O(f,2);Ne(d,21,()=>c(l).items,et,(p,h)=>{var b=LS(),x=V(b),w=V(x,!0);Q(x);var C=O(x,2);{var E=W=>{var H=QS();F(W,H)};ce(C,W=>{c(h).arrow&&W(E)})}var y=O(C,2);{var U=W=>{var H=XS(),Z=V(H,!0);Q(H),te(()=>{D(H,"href",c(h).href),oe(Z,c(h).fqn)}),F(W,H)},B=W=>{var H=RS(),Z=V(H,!0);Q(H),te(()=>oe(Z,c(h).fqn)),F(W,H)};ce(y,W=>{c(h).href?W(U):W(B,-1)})}var k=O(y,2);{var G=W=>{var H=US(),Z=V(H);Q(H),te(()=>oe(Z,`\xB7 ${c(h).label??""}`)),F(W,H)};ce(k,W=>{c(h).label&&W(G)})}Q(b),te(()=>oe(w,c(h).edgeKind)),F(p,b)}),Q(d),Q(u),te(()=>oe(g,c(l).title)),F(a,u)}),Q(s),F(i,s)};ce(n,i=>{t.groups.length&&i(o)})}F(e,r),ee()}ve();ie();var TS=J('

                    '),DS=J('

                    '),OS=J(' '),HS=J('
                    '),MS=J('
                  • '),YS=J('
                      '),zS=J('

                      Scenarios

                      ');function vp(e,t){q(t,!0);var r=Xe(),n=le(r);{var o=i=>{var s=zS(),a=O(V(s),2);Ne(a,17,()=>t.scenarios,et,(l,u)=>{var f=YS(),g=V(f),d=V(g,!0);Q(g);var p=O(g,2);{var h=y=>{var U=TS(),B=V(U,!0);Q(U),te(()=>oe(B,c(u).summary)),F(y,U)};ce(p,y=>{c(u).summary&&y(h)})}var b=O(p,2);{var x=y=>{var U=DS(),B=V(U,!0);Q(U),te(()=>oe(B,c(u).extended)),F(y,U)};ce(b,y=>{c(u).extended&&y(x)})}var w=O(b,2);{var C=y=>{var U=HS();Ne(U,21,()=>c(u).tags,et,(B,k)=>{var G=OS(),W=V(G,!0);Q(G),te(()=>oe(W,c(k))),F(B,G)}),Q(U),F(y,U)};ce(w,y=>{c(u).tags.length&&y(C)})}var E=O(w,2);Ne(E,21,()=>c(u).steps,et,(y,U)=>{var B=MS(),k=V(B),G=V(k,!0);Q(k);var W=O(k,2),H=V(W,!0);Q(W),Q(B),te(()=>{Je(k,1,`step-kw ${c(U).keyword??""}`),oe(G,c(U).keyword),oe(H,c(U).text)}),F(y,B)}),Q(E),Q(f),te(()=>oe(d,c(u).name)),F(l,f)}),Q(s),F(i,s)};ce(n,i=>{t.scenarios.length&&i(o)})}F(e,r),ee()}var PS=J('

                      '),JS=J('

                      '),jS=J(' '),KS=J('
                      '),qS=J('

                      #

                      ');function _p(e,t){q(t,!0);var r=qS(),n=V(r),o=V(n),i=V(o,!0);Q(o);var s=O(o,2),a=V(s),l=V(a,!0);Q(a),Ct(2),Q(s);var u=O(s,2),f=V(u,!0);Q(u),Q(n);var g=O(n,2),d=V(g,!0);Q(g);var p=O(g,2);{var h=B=>{var k=PS(),G=V(k,!0);Q(k),te(()=>oe(G,t.section.summary)),F(B,k)};ce(p,B=>{t.section.summary&&B(h)})}var b=O(p,2);{var x=B=>{var k=JS(),G=V(k,!0);Q(k),te(()=>oe(G,t.section.extended)),F(B,k)};ce(b,B=>{t.section.extended&&B(x)})}var w=O(b,2);{var C=B=>{var k=KS();Ne(k,21,()=>t.section.tags,et,(G,W)=>{var H=jS(),Z=V(H,!0);Q(H),te(()=>oe(Z,c(W))),F(G,H)}),Q(k),F(B,k)};ce(w,B=>{t.section.tags.length&&B(C)})}var E=O(w,2);mp(E,{get groups(){return t.section.relationships}});var y=O(E,2);vp(y,{get scenarios(){return t.section.scenarios}});var U=O(y,2);Ne(U,17,()=>t.section.diagrams,et,(B,k)=>{Zl(B,{get diagram(){return c(k)}})}),Q(r),te(()=>{D(r,"id",t.section.id),Je(o,1,`kind-badge ${t.section.kind??""}`),oe(i,t.section.kind),D(a,"href",`#${t.section.id??""}`),oe(l,t.section.name),oe(f,t.section.visibility),oe(d,t.section.fqn)}),F(e,r),ee()}var eZ=J('
                      Module

                      ',1);function bp(e,t){q(t,!0);var r=eZ(),n=le(r),o=O(V(n),2),i=V(o,!0);Q(o),Q(n);var s=O(n,2);Ne(s,17,()=>t.page.sections,et,(a,l)=>{_p(a,{get section(){return c(l)}})}),te(()=>oe(i,t.page.name)),F(e,r),ee()}ve();ie();var tZ=J('
                      Documentation

                      ',1);function xp(e,t){q(t,!0);var r=tZ(),n=le(r),o=O(V(n),2),i=V(o,!0);Q(o),Q(n);var s=O(n,2);Pu(s,()=>t.page.html,!0),Q(s),te(()=>oe(i,t.page.title)),F(e,r),ee()}ve();To();ie();var rZ=J('
                      Generated by pds doc.
                      ');function yp(e){var t=rZ();F(e,t)}function lC(e){oZ(e),iZ(e),aZ(e),nZ(e)}function nZ(e){let t=location.pathname.split("/").pop();t&&e.querySelectorAll(".docs-link").forEach(r=>{r.getAttribute("href").split("/").pop().split("#")[0]===t&&r.classList.add("is-active")})}function oZ(e){e.querySelectorAll(".tree .toggle").forEach(t=>{t.addEventListener("click",r=>{r.preventDefault(),r.stopPropagation();let n=t.closest("li");n&&n.classList.toggle("collapsed")})})}function iZ(e){let t=e.querySelector(".search input"),r=e.querySelector(".tree");if(!t||!r)return;let n=document.createElement("li");n.className="no-results",n.textContent="No matches",n.hidden=!0,r.appendChild(n),t.addEventListener("input",()=>{let o=t.value.trim().toLowerCase(),i=sZ(r,o);n.hidden=i||o===""})}function sZ(e,t){if(t==="")return e.querySelectorAll("li").forEach(n=>n.classList.remove("hidden")),!0;let r=!1;return e.querySelectorAll(":scope > li").forEach(n=>{cC(n,t,!1)&&(r=!0)}),r}function cC(e,t,r){let n=(e.dataset.search||"").toLowerCase(),o=r||n.indexOf(t)!==-1,i=!1;e.querySelectorAll(":scope > ul.children > li").forEach(a=>{cC(a,t,o)&&(i=!0)});let s=o||i;return e.classList.toggle("hidden",!s),s&&e.classList.remove("collapsed"),s}function aZ(e){function t(){let r=decodeURIComponent(location.hash.replace(/^#/,""));if(e.querySelectorAll(".tree .node-link.is-active").forEach(o=>{o.classList.remove("is-active")}),!r)return;let n=e.querySelector('.tree a[href$="#'+lZ(r)+'"]');if(n){n.classList.add("is-active");let o=n.closest("li");for(;o;){o.classList.remove("collapsed");let i=o.parentElement;o=i?i.closest("li"):null}}}window.addEventListener("hashchange",t),t()}function lZ(e){return window.CSS&&window.CSS.escape?window.CSS.escape(e):e.replace(/[^a-zA-Z0-9_-]/g,"\\$&")}var cZ=J('
                      ');function Ip(e,t){q(t,!0);let r=P(t,"docGroups",19,()=>[]);Bs(()=>lC(document));var n=cZ(),o=V(n);hf(o,{get site(){return t.site},get docGroups(){return r()},get sidebar(){return t.sidebar}});var i=O(o,2),s=V(i),a=V(s);{var l=d=>{hp(d,{get page(){return t.page}})},u=d=>{xp(d,{get page(){return t.page}})},f=d=>{bp(d,{get page(){return t.page}})};ce(a,d=>{t.page.kind==="index"?d(l):t.page.kind==="doc"?d(u,1):d(f,-1)})}var g=O(a,2);yp(g,{}),Q(s),Q(i),Q(n),F(e,n),ee()}var dC=document.getElementById("app");dC&&window.__DATA__&&ws(Ip,{target:dC,props:window.__DATA__});})(); diff --git a/crates/pseudoscript-doc/src/assets/ssr.js b/crates/pseudoscript-doc/src/assets/ssr.js index 89ee2e6..51d282c 100644 --- a/crates/pseudoscript-doc/src/assets/ssr.js +++ b/crates/pseudoscript-doc/src/assets/ssr.js @@ -1,34 +1,34 @@ -var SSR=(()=>{var To=Object.create;var Ze=Object.defineProperty;var Oo=Object.getOwnPropertyDescriptor;var Xo=Object.getOwnPropertyNames;var Vo=Object.getPrototypeOf,Yo=Object.prototype.hasOwnProperty;var Or=t=>{throw TypeError(t)};var Wo=(t,r,e)=>r in t?Ze(t,r,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[r]=e;var nt=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(r,e)=>(typeof require<"u"?require:r)[e]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var p=(t,r)=>()=>(t&&(r=t(t=0)),r);var ot=(t,r)=>{for(var e in r)Ze(t,e,{get:r[e],enumerable:!0})},Xr=(t,r,e,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of Xo(r))!Yo.call(t,o)&&o!==e&&Ze(t,o,{get:()=>r[o],enumerable:!(n=Oo(r,o))||n.enumerable});return t};var Vr=(t,r,e)=>(e=t!=null?To(Vo(t)):{},Xr(r||!t||!t.__esModule?Ze(e,"default",{value:t,enumerable:!0}):e,t)),Mo=t=>Xr(Ze({},"__esModule",{value:!0}),t);var O=(t,r,e)=>Wo(t,typeof r!="symbol"?r+"":r,e),Gt=(t,r,e)=>r.has(t)||Or("Cannot "+e);var m=(t,r,e)=>(Gt(t,r,"read from private field"),e?e.call(t):r.get(t)),M=(t,r,e)=>r.has(t)?Or("Cannot add the same private member more than once"):r instanceof WeakSet?r.add(t):r.set(t,e),j=(t,r,e,n)=>(Gt(t,r,"write to private field"),n?n.call(t,e):r.set(t,e),e),y=(t,r,e)=>(Gt(t,r,"access private method"),e);var oe,Z=p(()=>{oe=Symbol("uninitialized")});function h(t,r){let e=String(t??""),n=r?Jo:Ho;n.lastIndex=0;let o="",a=0;for(;n.test(e);){let s=n.lastIndex-1,l=e[s];o+=e.substring(a,s)+(l==="&"?"&":l==='"'?""":"<"),a=s+1}return o+e.substring(a)}var Jo,Ho,st=p(()=>{Jo=/[&"<]/g,Ho=/[&<]/g});function Yr(t){var r,e,n="";if(typeof t=="string"||typeof t=="number")n+=t;else if(typeof t=="object")if(Array.isArray(t)){var o=t.length;for(r=0;r{});function Hr(t){return t()}function at(){var t,r,e=new Promise((n,o)=>{t=n,r=o});return{promise:e,resolve:t,reject:r}}var $o,Nt,Jr,jo,it,C,k=p(()=>{$o=Array.prototype.indexOf,Nt=Array.prototype.includes,Jr=Object.prototype,jo=Array.prototype,it=Object.prototype.hasOwnProperty,C=()=>{}});function Q(t,r,e=!1){if(t==="hidden"&&r!=="until-found"&&(e=!0),r==null||!r&&e)return"";let n=it.call($r,t)&&$r[t].get(r)||r,o=e?'=""':`="${h(n,!0)}"`;return` ${t}${o}`}function Pr(t){return typeof t=="object"?Wr(t):t??""}function Dt(t,r,e){var n=t==null?"":""+t;if(r&&(n=n?n+" "+r:r),e){for(var o of Object.keys(e))if(e[o])n=n?n+" "+o:o;else if(n.length)for(var a=o.length,s=0;(s=n.indexOf(o,s))>=0;){var l=s+a;(s===0||jr.includes(n[s-1]))&&(l===n.length||jr.includes(n[l]))?n=(s===0?"":n.substring(0,s))+n.substring(l+1):s=l}}return n===""?null:n}function zr(t,r=!1){var e=r?" !important;":";",n="";for(var o of Object.keys(t)){var a=t[o];a!=null&&a!==""&&(n+=" "+o+": "+a+e)}return n}function Lt(t){return t[0]!=="-"||t[1]!=="-"?t.toLowerCase():t}function Kr(t,r){if(r){var e="",n,o;if(Array.isArray(r)?(n=r[0],o=r[1]):n=r,t){t=String(t).replaceAll(/\s*\/\*.*?\*\/\s*/g,"").trim();var a=!1,s=0,l=!1,d=[];n&&d.push(...Object.keys(n).map(Lt)),o&&d.push(...Object.keys(o).map(Lt));var i=0,f=-1;let $=t.length;for(var c=0;c<$;c++){var _=t[c];if(l?_==="/"&&t[c-1]==="*"&&(l=!1):a?a===_&&(a=!1):_==="/"&&t[c+1]==="*"?l=!0:_==='"'||_==="'"?a=_:_==="("?s++:_===")"&&s--,!l&&a===!1&&s===0){if(_===":"&&f===-1)f=c;else if(_===";"||c===$-1){if(f!==-1){var u=Lt(t.substring(i,f).trim());if(!d.includes(u)){_!==";"&&c++;var g=t.substring(i,c).trim();e+=" "+g+";"}}i=c+1,f=-1}}}}return n&&(e+=zr(n)),o&&(e+=zr(o,!0)),e=e.trim(),e===""?null:e}return t==null?null:String(t)}var $r,jr,qr=p(()=>{st();Mr();k();$r={translate:new Map([[!0,"yes"],[!1,"no"]])};jr=[...` -\r\f\xA0\v\uFEFF`]});var b,lt=p(()=>{b=!1});var E=p(()=>{lt();lt();lt()});var Qe,Li,G=p(()=>{Qe=new class extends Error{constructor(){super(...arguments);O(this,"name","StaleReactionError");O(this,"message","The reaction that called `getAbortSignal()` was re-run or destroyed")}},Li=!!globalThis.document?.contentType&&globalThis.document.contentType.includes("xml")});function Rt(t){if(b){let r=new Error(`experimental_async_required +var SSR=(()=>{var Oo=Object.create;var Xe=Object.defineProperty;var Jo=Object.getOwnPropertyDescriptor;var Mo=Object.getOwnPropertyNames;var $o=Object.getPrototypeOf,jo=Object.prototype.hasOwnProperty;var Yn=t=>{throw TypeError(t)};var zo=(t,n,e)=>n in t?Xe(t,n,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[n]=e;var et=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(n,e)=>(typeof require<"u"?require:n)[e]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var h=(t,n)=>()=>(t&&(n=t(t=0)),n);var tt=(t,n)=>{for(var e in n)Xe(t,e,{get:n[e],enumerable:!0})},Dn=(t,n,e,r)=>{if(n&&typeof n=="object"||typeof n=="function")for(let o of Mo(n))!jo.call(t,o)&&o!==e&&Xe(t,o,{get:()=>n[o],enumerable:!(r=Jo(n,o))||r.enumerable});return t};var Tn=(t,n,e)=>(e=t!=null?Oo($o(t)):{},Dn(n||!t||!t.__esModule?Xe(e,"default",{value:t,enumerable:!0}):e,t)),Po=t=>Dn(Xe({},"__esModule",{value:!0}),t);var T=(t,n,e)=>zo(t,typeof n!="symbol"?n+"":n,e),Ut=(t,n,e)=>n.has(t)||Yn("Cannot "+e);var v=(t,n,e)=>(Ut(t,n,"read from private field"),e?e.call(t):n.get(t)),J=(t,n,e)=>n.has(t)?Yn("Cannot add the same private member more than once"):n instanceof WeakSet?n.add(t):n.set(t,e),j=(t,n,e,r)=>(Ut(t,n,"write to private field"),r?r.call(t,e):n.set(t,e),e),w=(t,n,e)=>(Ut(t,n,"access private method"),e);var re,D=h(()=>{re=Symbol("uninitialized")});function m(t,n){let e=String(t??""),r=n?Ko:qo;r.lastIndex=0;let o="",l=0;for(;r.test(e);){let s=r.lastIndex-1,a=e[s];o+=e.substring(l,s)+(a==="&"?"&":a==='"'?""":"<"),l=s+1}return o+e.substring(l)}var Ko,qo,nt=h(()=>{Ko=/[&"<]/g,qo=/[&<]/g});function Hn(t){var n,e,r="";if(typeof t=="string"||typeof t=="number")r+=t;else if(typeof t=="object")if(Array.isArray(t)){var o=t.length;for(n=0;n{});function $n(t){return t()}function ot(){var t,n,e=new Promise((r,o)=>{t=r,n=o});return{promise:e,resolve:t,reject:n}}var es,Zt,Mn,ts,rt,U,L=h(()=>{es=Array.prototype.indexOf,Zt=Array.prototype.includes,Mn=Object.prototype,ts=Array.prototype,rt=Object.prototype.hasOwnProperty,U=()=>{}});function p(t,n,e=!1){if(t==="hidden"&&n!=="until-found"&&(e=!0),n==null||!n&&e)return"";let r=rt.call(jn,t)&&jn[t].get(n)||n,o=e?'=""':`="${m(r,!0)}"`;return` ${t}${o}`}function Kn(t){return typeof t=="object"?On(t):t??""}function St(t,n,e){var r=t==null?"":""+t;if(n&&(r=r?r+" "+n:n),e){for(var o of Object.keys(e))if(e[o])r=r?r+" "+o:o;else if(r.length)for(var l=o.length,s=0;(s=r.indexOf(o,s))>=0;){var a=s+l;(s===0||zn.includes(r[s-1]))&&(a===r.length||zn.includes(r[a]))?r=(s===0?"":r.substring(0,s))+r.substring(a+1):s=a}}return r===""?null:r}function Pn(t,n=!1){var e=n?" !important;":";",r="";for(var o of Object.keys(t)){var l=t[o];l!=null&&l!==""&&(r+=" "+o+": "+l+e)}return r}function Et(t){return t[0]!=="-"||t[1]!=="-"?t.toLowerCase():t}function kt(t,n){if(n){var e="",r,o;if(Array.isArray(n)?(r=n[0],o=n[1]):r=n,t){t=String(t).replaceAll(/\s*\/\*.*?\*\/\s*/g,"").trim();var l=!1,s=0,a=!1,g=[];r&&g.push(...Object.keys(r).map(Et)),o&&g.push(...Object.keys(o).map(Et));var i=0,d=-1;let f=t.length;for(var u=0;u{nt();Jn();L();jn={translate:new Map([[!0,"yes"],[!1,"no"]])};zn=[...` +\r\f\xA0\v\uFEFF`]});var F,st=h(()=>{F=!1});var E=h(()=>{st();st();st()});var Fe,Di,N=h(()=>{Fe=new class extends Error{constructor(){super(...arguments);T(this,"name","StaleReactionError");T(this,"message","The reaction that called `getAbortSignal()` was re-run or destroyed")}},Di=!!globalThis.document?.contentType&&globalThis.document.contentType.includes("xml")});function Xt(t){if(F){let n=new Error(`experimental_async_required Cannot use \`${t}(...)\` unless the \`experimental.async\` compiler option is \`true\` -https://svelte.dev/e/experimental_async_required`);throw r.name="Svelte error",r}else throw new Error("https://svelte.dev/e/experimental_async_required")}function Zt(t){if(b){let r=new Error(`lifecycle_outside_component +https://svelte.dev/e/experimental_async_required`);throw n.name="Svelte error",n}else throw new Error("https://svelte.dev/e/experimental_async_required")}function Lt(t){if(F){let n=new Error(`lifecycle_outside_component \`${t}(...)\` can only be used during component initialisation -https://svelte.dev/e/lifecycle_outside_component`);throw r.name="Svelte error",r}else throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function Tt(){if(b){let t=new Error(`missing_context +https://svelte.dev/e/lifecycle_outside_component`);throw n.name="Svelte error",n}else throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function Nt(){if(F){let t=new Error(`missing_context Context was not set in a parent component -https://svelte.dev/e/missing_context`);throw t.name="Svelte error",t}else throw new Error("https://svelte.dev/e/missing_context")}var Ee=p(()=>{E()});var se=p(()=>{E();Ee()});var Ae=p(()=>{E()});var ct=p(()=>{G();Z();Ae();Ue()});var ut=p(()=>{});var ee,z=p(()=>{ee=!1});var Xt=p(()=>{E()});var ft=p(()=>{E();Xt();k()});var ke=p(()=>{Z();ft();G();J();R()});function ln(){let t=Error.stackTraceLimit;Error.stackTraceLimit=1/0;let r=new Error().stack;if(Error.stackTraceLimit=t,!r)return[];let e=r.split(` -`),n=[];for(let o=0;o{E();k();Ee()});var ve=p(()=>{E();se();R();J();z();Z();G()});var Ve=p(()=>{k();te()});var Ye=p(()=>{E();Z();Ue();G();k();R()});var Na,be=p(()=>{G();Na=-7169});var Jt=p(()=>{G();be()});var fn=p(()=>{k();ut();mt()});var dn=p(()=>{mt();fn();k();R();J();re();E()});var _n=p(()=>{G();ft();R()});var te=p(()=>{G();z();k();R();se();Ve();E();Ye();re();J();Jt();Z();be();dn();me();_n()});var xn=p(()=>{R();J();re();ke();E();Ve()});var uc,Cn=p(()=>{G();Z();ve();Ye();J();R();ct();Ve();se();Ae();E();te();re();ke();xn();Ue();Jt();uc=589824});var tr=p(()=>{G();E();ve();Cn();Ye();R();te();Ft();J()});var Ft=p(()=>{E();G();R();ut();se();Ae();J();re();me();z();ve();Z();te();tr();k();be()});var re=p(()=>{E();R();ut();G();se();z();ke();me();ve();te();or();Ft();be()});var or=p(()=>{E();R();k();re();G();Z();se();ke();me();z()});var Gn=p(()=>{Ae();or()});var Ue=p(()=>{ct();E();Gn();k();R();z();G();te();Z()});var Nn=p(()=>{ct();Ue();Ve();G()});var sr=p(()=>{J();R();G();Nn()});var J=p(()=>{R();G();se();E();k();Ue();ve();te();tr();sr();be()});var Ln=p(()=>{re();R()});var R=p(()=>{E();k();J();G();re();Ft();z();ke();me();ve();te();Ye();Z();Ln();sr();be();Ae()});var mt=p(()=>{R();k()});var He,Qs,ye,ir=p(()=>{Z();He=``,Qs=``,ye=``});function Dn(t){t=t.replace(Es,"");let r=5381,e=t.length;for(;e--;)r=(r<<5)-r^t.charCodeAt(e);return(r>>>0).toString(36)}function Zn(t){return Rn.includes(t)}var Es,Rn,Ep,As,Ap,It=p(()=>{Es=/\r/g;Rn=["allowfullscreen","async","autofocus","autoplay","checked","controls","default","disabled","formnovalidate","indeterminate","inert","ismap","loop","multiple","muted","nomodule","novalidate","open","playsinline","readonly","required","reversed","seamless","selected","webkitdirectory","defer","disablepictureinpicture","disableremoteplayback"];Ep=[...Rn,"formNoValidate","isMap","noModule","playsInline","readOnly","value","volume","defaultValue","defaultChecked","srcObject","noValidate","allowFullscreen","disablePictureInPicture","disableRemotePlayback"],As=["$state","$state.raw","$derived","$derived.by"],Ap=[...As,"$state.eager","$state.snapshot","$props","$props.id","$bindable","$effect","$effect.pre","$effect.tracking","$effect.root","$effect.pending","$inspect","$inspect().with","$inspect.trace","$host"]});var ar=p(()=>{It();Xt();Ee();Ee()});function cr(){lr?.abort(Qe),lr=null}function Tn(){return(lr??(lr=new AbortController)).signal}var lr,ur=p(()=>{G();lr=null});function On(){let t=new Error("async_local_storage_unavailable\nThe node API `AsyncLocalStorage` is not available, but is required to use async server rendering.\nhttps://svelte.dev/e/async_local_storage_unavailable");throw t.name="Svelte error",t}function wt(){let t=new Error(`await_invalid +https://svelte.dev/e/missing_context`);throw t.name="Svelte error",t}else throw new Error("https://svelte.dev/e/missing_context")}var Be=h(()=>{E()});var oe=h(()=>{E();Be()});var we=h(()=>{E()});var it=h(()=>{N();D();we();Qe()});var lt=h(()=>{});var q,z=h(()=>{q=!1});var Rt=h(()=>{E()});var at=h(()=>{E();Rt();L()});var Ae=h(()=>{D();at();N();M();Y()});function lr(){let t=Error.stackTraceLimit;Error.stackTraceLimit=1/0;let n=new Error().stack;if(Error.stackTraceLimit=t,!n)return[];let e=n.split(` +`),r=[];for(let o=0;o{E();L();Be()});var ge=h(()=>{E();oe();Y();M();z();D();N()});var Re=h(()=>{L();ee()});var Ve=h(()=>{E();D();Qe();N();L();Y()});var Yl,be=h(()=>{N();Yl=-7169});var Ht=h(()=>{N();be()});var ur=h(()=>{L();lt();dt()});var pr=h(()=>{dt();ur();L();Y();M();te();E()});var hr=h(()=>{N();at();Y()});var ee=h(()=>{N();z();L();Y();oe();Re();E();Ve();te();M();Ht();D();be();pr();he();hr()});var Ir=h(()=>{Y();M();te();Ae();E();Re()});var bc,Br=h(()=>{N();D();ge();Ve();M();Y();it();Re();oe();we();E();ee();te();Ae();Ir();Qe();Ht();bc=589824});var qt=h(()=>{N();E();ge();Br();Ve();Y();ee();vt();M()});var vt=h(()=>{E();N();Y();lt();oe();we();M();te();he();z();ge();D();ee();qt();L();be()});var te=h(()=>{E();Y();lt();N();oe();z();Ae();he();ge();ee();nn();vt();be()});var nn=h(()=>{E();Y();L();te();N();D();oe();Ae();he();z()});var Er=h(()=>{we();nn()});var Qe=h(()=>{it();E();Er();L();Y();z();N();ee();D()});var Sr=h(()=>{it();Qe();Re();N()});var rn=h(()=>{M();Y();N();Sr()});var M=h(()=>{Y();N();oe();E();L();Qe();ge();ee();qt();rn();be()});var kr=h(()=>{te();Y()});var Y=h(()=>{E();L();M();N();te();vt();z();Ae();he();ge();ee();Ve();D();kr();rn();be();we()});var dt=h(()=>{Y();L()});var He,Ss,_e,on=h(()=>{D();He=``,Ss=``,_e=``});function Xr(t){t=t.replace(ks,"");let n=5381,e=t.length;for(;e--;)n=(n<<5)-n^t.charCodeAt(e);return(n>>>0).toString(36)}function Nr(t){return Lr.includes(t)}var ks,Lr,Xp,Xs,Lp,It=h(()=>{ks=/\r/g;Lr=["allowfullscreen","async","autofocus","autoplay","checked","controls","default","disabled","formnovalidate","indeterminate","inert","ismap","loop","multiple","muted","nomodule","novalidate","open","playsinline","readonly","required","reversed","seamless","selected","webkitdirectory","defer","disablepictureinpicture","disableremoteplayback"];Xp=[...Lr,"formNoValidate","isMap","noModule","playsInline","readOnly","value","volume","defaultValue","defaultChecked","srcObject","noValidate","allowFullscreen","disablePictureInPicture","disableRemotePlayback"],Xs=["$state","$state.raw","$derived","$derived.by"],Lp=[...Xs,"$state.eager","$state.snapshot","$props","$props.id","$bindable","$effect","$effect.pre","$effect.tracking","$effect.root","$effect.pending","$inspect","$inspect().with","$inspect.trace","$host"]});var sn=h(()=>{It();Rt();Be();Be()});function an(){ln?.abort(Fe),ln=null}function Wr(){return(ln??(ln=new AbortController)).signal}var ln,cn=h(()=>{N();ln=null});function Rr(){let t=new Error("async_local_storage_unavailable\nThe node API `AsyncLocalStorage` is not available, but is required to use async server rendering.\nhttps://svelte.dev/e/async_local_storage_unavailable");throw t.name="Svelte error",t}function xt(){let t=new Error(`await_invalid Encountered asynchronous work while rendering synchronously. -https://svelte.dev/e/await_invalid`);throw t.name="Svelte error",t}function Xn(){let t=new Error("html_deprecated\nThe `html` property of server render results has been deprecated. Use `body` instead.\nhttps://svelte.dev/e/html_deprecated");throw t.name="Svelte error",t}function Vn(t,r){let e=new Error(`hydratable_clobbering +https://svelte.dev/e/await_invalid`);throw t.name="Svelte error",t}function Vr(){let t=new Error("html_deprecated\nThe `html` property of server render results has been deprecated. Use `body` instead.\nhttps://svelte.dev/e/html_deprecated");throw t.name="Svelte error",t}function Yr(t,n){let e=new Error(`hydratable_clobbering Attempted to set \`hydratable\` with key \`${t}\` twice with different values. -${r} -https://svelte.dev/e/hydratable_clobbering`);throw e.name="Svelte error",e}function Yn(t,r){let e=new Error(`hydratable_serialization_failed +${n} +https://svelte.dev/e/hydratable_clobbering`);throw e.name="Svelte error",e}function Dr(t,n){let e=new Error(`hydratable_serialization_failed Failed to serialize \`hydratable\` data for key \`${t}\`. \`hydratable\` can serialize anything [\`uneval\` from \`devalue\`](https://npmjs.com/package/uneval) can, plus Promises. Cause: -${r} -https://svelte.dev/e/hydratable_serialization_failed`);throw e.name="Svelte error",e}function Wn(){let t=new Error("invalid_csp\n`csp.nonce` was set while `csp.hash` was `true`. These options cannot be used simultaneously.\nhttps://svelte.dev/e/invalid_csp");throw t.name="Svelte error",t}function Mn(){let t=new Error("invalid_id_prefix\nThe `idPrefix` option cannot include `--`.\nhttps://svelte.dev/e/invalid_id_prefix");throw t.name="Svelte error",t}function $e(t){let r=new Error(`lifecycle_function_unavailable +${n} +https://svelte.dev/e/hydratable_serialization_failed`);throw e.name="Svelte error",e}function Tr(){let t=new Error("invalid_csp\n`csp.nonce` was set while `csp.hash` was `true`. These options cannot be used simultaneously.\nhttps://svelte.dev/e/invalid_csp");throw t.name="Svelte error",t}function Hr(){let t=new Error("invalid_id_prefix\nThe `idPrefix` option cannot include `--`.\nhttps://svelte.dev/e/invalid_id_prefix");throw t.name="Svelte error",t}function Oe(t){let n=new Error(`lifecycle_function_unavailable \`${t}(...)\` is not available on the server -https://svelte.dev/e/lifecycle_function_unavailable`);throw r.name="Svelte error",r}function Jn(){let t=new Error("server_context_required\nCould not resolve `render` context.\nhttps://svelte.dev/e/server_context_required");throw t.name="Svelte error",t}var le=p(()=>{Ee()});function N(t){F=t}function Hn(){let t={};return[()=>(dr(t)||Tt(),fr(t)),r=>pr(t,r)]}function fr(t){return Bt("getContext").get(t)}function pr(t,r){return Bt("setContext").set(t,r),r}function dr(t){return Bt("hasContext").has(t)}function $n(){return Bt("getAllContexts")}function Bt(t){return F===null&&Zt(t),F.c??(F.c=new Map(Ss(F)||void 0))}function jn(t){F={p:F,c:null,r:null},b&&(F.function=t,F.element=F.p?.element)}function zn(){F=F.p}function Ss(t){let r=t.p;for(;r!==null;){let e=r.c;if(e!==null)return e;r=r.p}return null}var F,Fe=p(()=>{E();le();F=null});function Pn(t,r){b?console.warn(`%c[svelte] unresolved_hydratable +https://svelte.dev/e/lifecycle_function_unavailable`);throw n.name="Svelte error",n}function Or(){let t=new Error("server_context_required\nCould not resolve `render` context.\nhttps://svelte.dev/e/server_context_required");throw t.name="Svelte error",t}var le=h(()=>{Be()});function W(t){A=t}function Jr(){let t={};return[()=>(pn(t)||Nt(),un(t)),n=>fn(t,n)]}function un(t){return yt("getContext").get(t)}function fn(t,n){return yt("setContext").set(t,n),n}function pn(t){return yt("hasContext").has(t)}function Mr(){return yt("getAllContexts")}function yt(t){return A===null&&Lt(t),A.c??(A.c=new Map(Ws(A)||void 0))}function $r(t){A={p:A,c:null,r:null},F&&(A.function=t,A.element=A.p?.element)}function jr(){A=A.p}function Ws(t){let n=t.p;for(;n!==null;){let e=n.c;if(e!==null)return e;n=n.p}return null}var A,Ie=h(()=>{E();le();A=null});function zr(t,n){F?console.warn(`%c[svelte] unresolved_hydratable %cA \`hydratable\` value with key \`${t}\` was created, but at least part of it was not used during the render. The \`hydratable\` was initialized in: -${r} -https://svelte.dev/e/unresolved_hydratable`,Gs,Ns):console.warn("https://svelte.dev/e/unresolved_hydratable")}var Gs,Ns,Kn=p(()=>{E();Gs="font-weight: bold",Ns="font-weight: normal"});function Et(){let t=Ct??Qt?.getStore();return t||Jn(),t}async function to(t){if(Ct={hydratable:{lookup:new Map,comparisons:[],unresolved_promises:new Map}},Ds()){let{promise:r,resolve:e}=at(),n=qn;return qn=r,await n,t().finally(e)}try{return Qt===null&&On(),Qt.run(Ct,t)}finally{Ct=null}}function ro(){return eo??(eo=import("node:async_hooks").then(t=>{Qt=new t.AsyncLocalStorage}).then(C,C)),eo}function Ds(){return!!globalThis.process?.versions?.webcontainer}var qn,Ct,Qt,eo,hr=p(()=>{k();le();qn=null,Ct=null;Qt=null,eo=null});async function so(t){no??(no=new TextEncoder),oo??(oo=globalThis.crypto?.subtle?.digest?globalThis.crypto:(await Rs("node:crypto")).webcrypto);let r=await oo.subtle.digest("SHA-256",no.encode(t));return Zs(r)}function Zs(t){if(!b&&globalThis.Buffer)return globalThis.Buffer.from(t).toString("base64");let r="";for(let e=0;e{E();Rs=t=>import(t)});function je(t){return t===null||typeof t!="object"&&typeof t!="function"}function lo(t){let r=Object.getPrototypeOf(t);return r===Object.prototype||r===null||Object.getPrototypeOf(r)===null||Object.getOwnPropertyNames(r).sort().join("\0")===Ts}function At(t){return Object.prototype.toString.call(t).slice(8,-1)}function Os(t){switch(t){case'"':return'\\"';case"<":return"\\u003C";case"\\":return"\\\\";case` -`:return"\\n";case"\r":return"\\r";case" ":return"\\t";case"\b":return"\\b";case"\f":return"\\f";case"\u2028":return"\\u2028";case"\u2029":return"\\u2029";default:return t<" "?`\\u${t.charCodeAt(0).toString(16).padStart(4,"0")}`:""}}function H(t){let r="",e=0,n=t.length;for(let o=0;oObject.getOwnPropertyDescriptor(t,r).enumerable)}function uo(t){return Xs.test(t)?"."+t:"["+JSON.stringify(t)+"]"}function Vs(t){return!(!Number.isInteger(t)||t<0||t>4294967294)}function Ys(t){if(t.length===0||t.length>1&&t.charCodeAt(0)===48)return!1;for(let r=0;r57)return!1}return Vs(+t)}function fo(t){let r=Object.keys(t);for(var e=r.length-1;e>=0&&!Ys(r[e]);e--);return r.length=e+1,r}var ao,ce,Ts,Xs,po=p(()=>{ao={"<":"\\u003C","\\":"\\\\","\b":"\\b","\f":"\\f","\n":"\\n","\r":"\\r"," ":"\\t","\u2028":"\\u2028","\u2029":"\\u2029"},ce=class extends Error{constructor(r,e,n,o){super(r),this.name="DevalueError",this.path=e.join(""),this.value=n,this.root=o}};Ts=Object.getOwnPropertyNames(Object.prototype).sort().join("\0");Xs=/^[a-zA-Z_$][a-zA-Z_$0-9]*$/});function Ne(t,r){let e=new Map,n=[],o=new Map;function a(i){if(je(i)){if(typeof i=="symbol")throw new ce("Cannot stringify a Symbol primitive",n,i,t)}else{if(e.has(i)){e.set(i,e.get(i)+1);return}if(e.set(i,1),r){let c=r(i,_=>Ne(_,r));if(typeof c=="string"){o.set(i,c);return}}if(typeof i=="function")throw new ce("Cannot stringify a function",n,i,t);switch(At(i)){case"Number":case"BigInt":case"String":case"Boolean":case"Date":case"RegExp":case"URL":case"URLSearchParams":return;case"Array":i.forEach((c,_)=>{n.push(`[${_}]`),a(c),n.pop()});break;case"Set":Array.from(i).forEach(a);break;case"Map":for(let[c,_]of i)n.push(`.get(${je(c)?mr(c):"..."})`),a(_),n.pop();break;case"Int8Array":case"Uint8Array":case"Uint8ClampedArray":case"Int16Array":case"Uint16Array":case"Float16Array":case"Int32Array":case"Uint32Array":case"Float32Array":case"Float64Array":case"BigInt64Array":case"BigUint64Array":case"DataView":a(i.buffer);return;case"ArrayBuffer":return;case"Temporal.Duration":case"Temporal.Instant":case"Temporal.PlainDate":case"Temporal.PlainTime":case"Temporal.PlainDateTime":case"Temporal.PlainMonthDay":case"Temporal.PlainYearMonth":case"Temporal.ZonedDateTime":return;default:if(!lo(i))throw new ce("Cannot stringify arbitrary non-POJOs",n,i,t);if(co(i).length>0)throw new ce("Cannot stringify POJOs with symbolic keys",n,i,t);for(let c of Object.keys(i)){if(c==="__proto__")throw new ce("Cannot stringify objects with __proto__ keys",n,i,t);n.push(uo(c)),a(i[c]),n.pop()}}}}a(t);let s=new Map;Array.from(e).filter(i=>i[1]>1).sort((i,f)=>f[1]-i[1]).forEach((i,f)=>{s.set(i[0],Js(f))});function l(i){if(s.has(i))return s.get(i);if(je(i))return mr(i);if(o.has(i))return o.get(i);let f=At(i);switch(f){case"Number":case"String":case"Boolean":case"BigInt":return`Object(${l(i.valueOf())})`;case"RegExp":let{source:c,flags:_}=i;return _?`new RegExp(${H(c)},"${_}")`:`new RegExp(${H(c)})`;case"Date":return`new Date(${i.getTime()})`;case"URL":return`new URL(${H(i.toString())})`;case"URLSearchParams":return`new URLSearchParams(${H(i.toString())})`;case"Array":{let U=!1,I="[";for(let D=0;D0&&(I+=","),Object.hasOwn(i,D))I+=l(i[D]);else if(!U){let pe=fo(i),Y=pe.length,rt=String(i.length).length,Ce=i.length+2,Re=25+rt+Y*(rt+2);if(Ce>Re){let St=pe.map(v=>`${v}:${l(i[v])}`).join(",");return`Object.assign(Array(${i.length}),{${St}})`}U=!0,D-=1}let w=i.length===0||i.length-1 in i?"":",";return I+w+"]"}case"Set":case"Map":return`new ${f}([${Array.from(i).map(l).join(",")}])`;case"Int8Array":case"Uint8Array":case"Uint8ClampedArray":case"Int16Array":case"Uint16Array":case"Float16Array":case"Int32Array":case"Uint32Array":case"Float32Array":case"Float64Array":case"BigInt64Array":case"BigUint64Array":{let U=`new ${f}`;if(s.has(i.buffer))U+=`(${l(i.buffer)})`;else{let I=new i.constructor(i.buffer);U+=`([${I}])`}if(i.byteLength!==i.buffer.byteLength){let I=i.byteOffset/i.BYTES_PER_ELEMENT,w=I+i.length;U+=`.subarray(${I},${w})`}return U}case"DataView":{let U="new DataView";return s.has(i.buffer)?U+=`(${l(i.buffer)}`:U+=`(new Uint8Array([${new Uint8Array(i.buffer)}]).buffer`,i.byteLength!==i.buffer.byteLength&&(U+=`,${i.startOffset},${i.byteLength}`),U+")"}case"ArrayBuffer":return`new Uint8Array([${new Uint8Array(i).toString()}]).buffer`;case"Temporal.Duration":case"Temporal.Instant":case"Temporal.PlainDate":case"Temporal.PlainTime":case"Temporal.PlainDateTime":case"Temporal.PlainMonthDay":case"Temporal.PlainYearMonth":case"Temporal.ZonedDateTime":return`${f}.from(${H(i.toString())})`;default:let u=Object.keys(i),g=u.map(U=>`${$s(U)}:${l(i[U])}`).join(",");return Object.getPrototypeOf(i)===null?u.length>0?`{${g},__proto__:null}`:"{__proto__:null}":`{${g}}`}}let d=l(t);if(s.size){let i=[],f=[],c=[];return s.forEach((_,u)=>{if(i.push(_),o.has(u)){c.push(o.get(u));return}if(je(u)){c.push(mr(u));return}let g=At(u);switch(g){case"Number":case"String":case"Boolean":case"BigInt":c.push(`Object(${l(u.valueOf())})`);break;case"RegExp":let{source:$,flags:U}=u,I=U?`new RegExp(${H($)},"${U}")`:`new RegExp(${H($)})`;c.push(I);break;case"Date":c.push(`new Date(${u.getTime()})`);break;case"URL":c.push(`new URL(${H(u.toString())})`);break;case"URLSearchParams":c.push(`new URLSearchParams(${H(u.toString())})`);break;case"Array":c.push(`Array(${u.length})`),u.forEach((w,D)=>{f.push(`${_}[${D}]=${l(w)}`)});break;case"Set":c.push("new Set"),f.push(`${_}.${Array.from(u).map(w=>`add(${l(w)})`).join(".")}`);break;case"Map":c.push("new Map"),f.push(`${_}.${Array.from(u).map(([w,D])=>`set(${l(w)}, ${l(D)})`).join(".")}`);break;case"Int8Array":case"Uint8Array":case"Uint8ClampedArray":case"Int16Array":case"Uint16Array":case"Float16Array":case"Int32Array":case"Uint32Array":case"Float32Array":case"Float64Array":case"BigInt64Array":case"BigUint64Array":{let w=`new ${g}`;if(s.has(u.buffer))w+=`(${l(u.buffer)})`;else{let D=new u.constructor(u.buffer);w+=`([${D}])`}if(u.byteLength!==u.buffer.byteLength){let D=u.byteOffset/u.BYTES_PER_ELEMENT,pe=D+u.length;w+=`.subarray(${D},${pe})`}c.push("{}"),f.push(`${_}=${w}`);break}case"DataView":{let w="new DataView";s.has(u.buffer)?w+=`(${l(u.buffer)}`:w+=`(new Uint8Array([${new Uint8Array(u.buffer)}]).buffer`,u.byteLength!==u.buffer.byteLength&&(w+=`,${u.byteOffset},${u.byteLength}`),w+=")",c.push("{}"),f.push(`${_}=${w}`);break}case"ArrayBuffer":c.push(`new Uint8Array([${new Uint8Array(u)}]).buffer`);break;default:c.push(Object.getPrototypeOf(u)===null?"Object.create(null)":"{}"),Object.keys(u).forEach(w=>{f.push(`${_}${js(w)}=${l(u[w])}`)})}}),f.push(`return ${d}`),`(function(${i.join(",")}){${f.join(";")}}(${c.join(",")}))`}else return d}function Js(t){let r="";do r=_r[t%_r.length]+r,t=~~(t/_r.length)-1;while(t>=0);return Ms.test(r)?`${r}0`:r}function Hs(t){return ao[t]||t}function ho(t){return t.replace(Ws,Hs)}function $s(t){return/^[_$a-zA-Z][_$a-zA-Z0-9]*$/.test(t)?t:ho(JSON.stringify(t))}function js(t){return/^[_$a-zA-Z][_$a-zA-Z0-9]*$/.test(t)?`.${t}`:`[${ho(JSON.stringify(t))}]`}function mr(t){let r=typeof t;if(r==="string")return H(t);if(t===void 0)return"void 0";if(t===0&&1/t<0)return"-0";let e=String(t);return r==="number"?e.replace(/^(-)?0\./,"$1."):r==="bigint"?t+"n":e}var _r,Ws,Ms,_o=p(()=>{po();_r="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$",Ws=/[<\b\f\n\r\t\0\u2028\u2029]/g,Ms=/^(?:do|if|in|for|int|let|new|try|var|byte|case|char|else|enum|goto|long|this|void|with|await|break|catch|class|const|final|float|short|super|throw|while|yield|delete|double|export|import|native|return|switch|throws|typeof|boolean|default|extends|finally|package|private|abstract|continue|debugger|function|volatile|interface|protected|transient|implements|instanceof|synchronized)$/});var vr=p(()=>{_o()});var x,Le,De,we,ue,L,Ut,A,vo,gr,br,ze,go,Pe,Ie,bo,yr,xr,yo,B,Ke,Be,Fr,wr=p(()=>{z();ur();Fe();le();Kn();ir();Z();T();hr();io();vr();k();st();B=class B{constructor(r,e){M(this,A);M(this,x,[]);M(this,Le);M(this,De,!1);M(this,we,null);O(this,"type");M(this,ue);O(this,"promise");O(this,"global");O(this,"local");j(this,ue,e),this.global=r,this.local=e?{...e.local}:{select_value:void 0},this.type=e?e.type:"body"}head(r){let e=new B(this.global,this);e.type="head",m(this,x).push(e),e.child(r)}async_block(r,e){m(this,x).push(He),this.async(r,e),m(this,x).push(ye)}async(r,e){let n=e;if(r.length>0){let o=F;n=a=>Promise.all(r).then(()=>{let s=F;try{return N(o),e(a)}finally{N(s)}})}this.child(n)}run(r){let e=F,n=Promise.resolve(r[0]()),o=[n];for(let a of r.slice(1))n=n.then(()=>{let s=F;N(e);try{return a()}finally{N(s)}}),o.push(n);return n.catch(C),this.promise=n,o}child_block(r){m(this,x).push(He),this.child(r),m(this,x).push(ye)}child(r){let e=new B(this.global,this);m(this,x).push(e);let n=F;N({...F,p:n,c:null,r:e});let o=r(e);return N(n),o instanceof Promise&&(o.catch(C),o.finally(()=>N(null)).catch(C),e.global.mode==="sync"&&wt(),e.promise=o),e}boundary(r,e){var a;let n=new B(this.global,this);m(this,x).push(n);let o=F;r.failed&&j(n,we,{failed:r.failed,transformError:this.global.transformError,context:o}),N({...F,p:o,c:null,r:n});try{let s=e(n);N(o),s instanceof Promise&&(n.global.mode==="sync"&&wt(),s.catch(C),n.promise=s)}catch(s){N(o);let l=r.failed;if(!l)throw s;let d=this.global.transformError(s);m(n,x).length=0,j(n,we,null),d instanceof Promise?(this.global.mode==="sync"&&wt(),n.promise=d.then(i=>{var f;N(o),m(n,x).push(y(f=B,L,Ut).call(f,i)),l(n,i,C),m(n,x).push(ye)}),n.promise.catch(C)):(m(n,x).push(y(a=B,L,Ut).call(a,d)),l(n,d,C),m(n,x).push(ye))}}component(r,e){jn(e);let n=this.child(r);j(n,De,!0),zn()}select(r,e,n,o,a,s,l){let{value:d,...i}=r;this.push(``),this.child(f=>{f.local.select_value=d,e(f)}),this.push(`${l?"":""}`)}option(r,e,n,o,a,s,l){m(this,x).push(`{it.call(r,"value")&&(f=r.value),f===this.local.select_value&&m(i,x).push(' selected=""'),m(i,x).push(`>${_}${l?"":""}`),c&&i.head(u=>u.push(c))};typeof e=="function"?this.child(i=>{var c,_;let f=new B(this.global,this);if(e(f),this.global.mode==="async")return y(c=f,A,Ie).call(c).then(u=>{d(i,u.body.replaceAll("",""),u)});{let u=y(_=f,A,Pe).call(_);d(i,u.body.replaceAll("",""),u)}}):d(this,e,{body:h(e)})}title(r){let e=this.get_path(),n=o=>{this.global.set_title(o,e)};this.child(o=>{var s,l;let a=new B(o.global,o);if(r(a),o.global.mode==="async")return y(s=a,A,Ie).call(s).then(d=>{n(d.head)});{let d=y(l=a,A,Pe).call(l);n(d.head)}})}push(r){typeof r=="function"?this.child(async e=>e.push(await r())):m(this,x).push(r)}on_destroy(r){(m(this,Le)??j(this,Le,[])).push(r)}get_path(){return m(this,ue)?[...m(this,ue).get_path(),m(m(this,ue),x).indexOf(this)]:[]}copy(){let r=new B(this.global,m(this,ue));return j(r,x,m(this,x).map(e=>e instanceof B?e.copy():e)),r.promise=this.promise,r}subsume(r){if(this.global.mode!==r.global.mode)throw new Error("invariant: A renderer cannot switch modes. If you're seeing this, there's a compiler bug. File an issue!");this.local=r.local,j(this,x,m(r,x).map((e,n)=>{let o=m(this,x)[n];return o instanceof B&&e instanceof B?(o.subsume(e),o):e})),this.promise=r.promise,this.type=r.type}get length(){return m(this,x).length}static render(r,e={}){let n,o,a={};return Object.defineProperties(a,{html:{get:()=>{var s;return(n??(n=y(s=B,L,ze).call(s,r,e))).body}},head:{get:()=>{var s;return(n??(n=y(s=B,L,ze).call(s,r,e))).head}},body:{get:()=>{var s;return(n??(n=y(s=B,L,ze).call(s,r,e))).body}},hashes:{value:{script:""}},then:{value:(s,l)=>{var d;if(!ee){let i=n??(n=y(d=B,L,ze).call(d,r,e)),f=s({head:i.head,body:i.body,html:i.body,hashes:{script:[]}});return Promise.resolve(f)}return o??(o=ro().then(()=>to(()=>{var i;return y(i=B,L,go).call(i,r,e)}))),o.then(i=>(Object.defineProperty(i,"html",{get:()=>{Xn()}}),s(i)),l)}}}),a}};x=new WeakMap,Le=new WeakMap,De=new WeakMap,we=new WeakMap,ue=new WeakMap,L=new WeakSet,Ut=function(r){var e=JSON.stringify(r),n=e.replace(/>/g,"\\u003e").replace(/`},A=new WeakSet,vo=function*(){var r;for(let e of y(this,A,gr).call(this))yield*y(r=e,A,br).call(r)},gr=function*(){var r;for(let e of m(this,x))typeof e!="string"&&(yield*y(r=e,A,gr).call(r));m(this,De)&&(yield this)},br=function*(){var r;if(m(this,Le))for(let e of m(this,Le))yield e;for(let e of m(this,x))e instanceof B&&!m(e,De)&&(yield*y(r=e,A,br).call(r))},ze=function(r,e){var o,a,s;var n=F;try{let l=y(o=B,L,yr).call(o,"sync",r,e),d=y(a=l,A,Pe).call(a);return y(s=B,L,xr).call(s,d,l)}finally{cr(),N(n)}},go=async function(r,e){var o,a,s,l;let n=F;try{let d=y(o=B,L,yr).call(o,"async",r,e),i=await y(a=d,A,Ie).call(a),f=await y(s=d,A,bo).call(s);return f!==null&&(i.head=f+i.head),y(l=B,L,xr).call(l,i,d)}finally{N(n),cr()}},Pe=function(r={head:"",body:""}){var e;for(let n of m(this,x))typeof n=="string"?r[this.type]+=n:n instanceof B&&y(e=n,A,Pe).call(e,r);return r},Ie=async function(r={head:"",body:""}){var e,n,o,a;await this.promise;for(let s of m(this,x))if(typeof s=="string")r[this.type]+=s;else if(s instanceof B)if(m(s,we)){let l={head:"",body:""};try{await y(e=s,A,Ie).call(e,l),r.head+=l.head,r.body+=l.body}catch(d){let{context:i,failed:f,transformError:c}=m(s,we);N(i);let _=c(d);N(null);let u=await _;N(i);let g=new B(s.global,s);g.type=s.type,m(g,x).push(y(n=B,L,Ut).call(n,u)),f(g,u,C),m(g,x).push(ye),await y(o=g,A,Ie).call(o,r)}}else await y(a=s,A,Ie).call(a,r);return r},bo=async function(){let r=Et().hydratable;for(let[e,n]of r.unresolved_promises)Pn(n,r.lookup.get(n)?.stack??"");for(let e of r.comparisons)await e;return await y(this,A,yo).call(this,r)},yr=function(r,e,n){n.idPrefix?.includes("--")&&Mn();var o=F;try{let a=new B(new Fr(r,n.idPrefix?n.idPrefix+"-":"",n.csp,n.transformError)),s={p:null,c:n.context??null,r:a};return N(s),a.push(He),e(a,n.props??{}),a.push(ye),a}finally{N(o)}},xr=function(r,e){var a;for(let s of y(a=e,A,vo).call(a))s();let n=r.head+e.global.get_title(),o=r.body;for(let{hash:s,code:l}of e.global.css)n+=``;return{head:n,body:o,hashes:{script:e.global.csp.script_hashes}}},yo=async function(r){if(r.lookup.size===0)return null;let e=[],n=!1;for(let[l,d]of r.lookup){if(d.promises){n=!0;for(let i of d.promises)await i}e.push(`[${Ne(l)},${d.serialized}]`)}let o="const h = (window.__svelte ??= {}).h ??= new Map();";n&&(o=`const r = (v) => Promise.resolve(v); - ${o}`);let a=` +${n} +https://svelte.dev/e/unresolved_hydratable`,Rs,Vs):console.warn("https://svelte.dev/e/unresolved_hydratable")}var Rs,Vs,Pr=h(()=>{E();Rs="font-weight: bold",Vs="font-weight: normal"});function Bt(){let t=Ct??Ft?.getStore();return t||Or(),t}async function eo(t){if(Ct={hydratable:{lookup:new Map,comparisons:[],unresolved_promises:new Map}},Ds()){let{promise:n,resolve:e}=ot(),r=Kr;return Kr=n,await r,t().finally(e)}try{return Ft===null&&Rr(),Ft.run(Ct,t)}finally{Ct=null}}function to(){return qr??(qr=import("node:async_hooks").then(t=>{Ft=new t.AsyncLocalStorage}).then(U,U)),qr}function Ds(){return!!globalThis.process?.versions?.webcontainer}var Kr,Ct,Ft,qr,dn=h(()=>{L();le();Kr=null,Ct=null;Ft=null,qr=null});async function oo(t){no??(no=new TextEncoder),ro??(ro=globalThis.crypto?.subtle?.digest?globalThis.crypto:(await Ts("node:crypto")).webcrypto);let n=await ro.subtle.digest("SHA-256",no.encode(t));return Hs(n)}function Hs(t){if(!F&&globalThis.Buffer)return globalThis.Buffer.from(t).toString("base64");let n="";for(let e=0;e{E();Ts=t=>import(t)});function Je(t){return t===null||typeof t!="object"&&typeof t!="function"}function lo(t){let n=Object.getPrototypeOf(t);return n===Object.prototype||n===null||Object.getPrototypeOf(n)===null||Object.getOwnPropertyNames(n).sort().join("\0")===Os}function wt(t){return Object.prototype.toString.call(t).slice(8,-1)}function Js(t){switch(t){case'"':return'\\"';case"<":return"\\u003C";case"\\":return"\\\\";case` +`:return"\\n";case"\r":return"\\r";case" ":return"\\t";case"\b":return"\\b";case"\f":return"\\f";case"\u2028":return"\\u2028";case"\u2029":return"\\u2029";default:return t<" "?`\\u${t.charCodeAt(0).toString(16).padStart(4,"0")}`:""}}function $(t){let n="",e=0,r=t.length;for(let o=0;oObject.getOwnPropertyDescriptor(t,n).enumerable)}function co(t){return Ms.test(t)?"."+t:"["+JSON.stringify(t)+"]"}function $s(t){return!(!Number.isInteger(t)||t<0||t>4294967294)}function js(t){if(t.length===0||t.length>1&&t.charCodeAt(0)===48)return!1;for(let n=0;n57)return!1}return $s(+t)}function uo(t){let n=Object.keys(t);for(var e=n.length-1;e>=0&&!js(n[e]);e--);return n.length=e+1,n}var io,ae,Os,Ms,fo=h(()=>{io={"<":"\\u003C","\\":"\\\\","\b":"\\b","\f":"\\f","\n":"\\n","\r":"\\r"," ":"\\t","\u2028":"\\u2028","\u2029":"\\u2029"},ae=class extends Error{constructor(n,e,r,o){super(n),this.name="DevalueError",this.path=e.join(""),this.value=r,this.root=o}};Os=Object.getOwnPropertyNames(Object.prototype).sort().join("\0");Ms=/^[a-zA-Z_$][a-zA-Z_$0-9]*$/});function Ze(t,n){let e=new Map,r=[],o=new Map;function l(i){if(Je(i)){if(typeof i=="symbol")throw new ae("Cannot stringify a Symbol primitive",r,i,t)}else{if(e.has(i)){e.set(i,e.get(i)+1);return}if(e.set(i,1),n){let u=n(i,_=>Ze(_,n));if(typeof u=="string"){o.set(i,u);return}}if(typeof i=="function")throw new ae("Cannot stringify a function",r,i,t);switch(wt(i)){case"Number":case"BigInt":case"String":case"Boolean":case"Date":case"RegExp":case"URL":case"URLSearchParams":return;case"Array":i.forEach((u,_)=>{r.push(`[${_}]`),l(u),r.pop()});break;case"Set":Array.from(i).forEach(l);break;case"Map":for(let[u,_]of i)r.push(`.get(${Je(u)?gn(u):"..."})`),l(_),r.pop();break;case"Int8Array":case"Uint8Array":case"Uint8ClampedArray":case"Int16Array":case"Uint16Array":case"Float16Array":case"Int32Array":case"Uint32Array":case"Float32Array":case"Float64Array":case"BigInt64Array":case"BigUint64Array":case"DataView":l(i.buffer);return;case"ArrayBuffer":return;case"Temporal.Duration":case"Temporal.Instant":case"Temporal.PlainDate":case"Temporal.PlainTime":case"Temporal.PlainDateTime":case"Temporal.PlainMonthDay":case"Temporal.PlainYearMonth":case"Temporal.ZonedDateTime":return;default:if(!lo(i))throw new ae("Cannot stringify arbitrary non-POJOs",r,i,t);if(ao(i).length>0)throw new ae("Cannot stringify POJOs with symbolic keys",r,i,t);for(let u of Object.keys(i)){if(u==="__proto__")throw new ae("Cannot stringify objects with __proto__ keys",r,i,t);r.push(co(u)),l(i[u]),r.pop()}}}}l(t);let s=new Map;Array.from(e).filter(i=>i[1]>1).sort((i,d)=>d[1]-i[1]).forEach((i,d)=>{s.set(i[0],Ks(d))});function a(i){if(s.has(i))return s.get(i);if(Je(i))return gn(i);if(o.has(i))return o.get(i);let d=wt(i);switch(d){case"Number":case"String":case"Boolean":case"BigInt":return`Object(${a(i.valueOf())})`;case"RegExp":let{source:u,flags:_}=i;return _?`new RegExp(${$(u)},"${_}")`:`new RegExp(${$(u)})`;case"Date":return`new Date(${i.getTime()})`;case"URL":return`new URL(${$(i.toString())})`;case"URLSearchParams":return`new URLSearchParams(${$(i.toString())})`;case"Array":{let y=!1,C="[";for(let x=0;x0&&(C+=","),Object.hasOwn(i,x))C+=a(i[x]);else if(!y){let X=uo(i),O=X.length,ke=String(i.length).length,k=i.length+2,Gt=25+ke+O*(ke+2);if(k>Gt){let qe=X.map(Vn=>`${Vn}:${a(i[Vn])}`).join(",");return`Object.assign(Array(${i.length}),{${qe}})`}y=!0,x-=1}let B=i.length===0||i.length-1 in i?"":",";return C+B+"]"}case"Set":case"Map":return`new ${d}([${Array.from(i).map(a).join(",")}])`;case"Int8Array":case"Uint8Array":case"Uint8ClampedArray":case"Int16Array":case"Uint16Array":case"Float16Array":case"Int32Array":case"Uint32Array":case"Float32Array":case"Float64Array":case"BigInt64Array":case"BigUint64Array":{let y=`new ${d}`;if(s.has(i.buffer))y+=`(${a(i.buffer)})`;else{let C=new i.constructor(i.buffer);y+=`([${C}])`}if(i.byteLength!==i.buffer.byteLength){let C=i.byteOffset/i.BYTES_PER_ELEMENT,B=C+i.length;y+=`.subarray(${C},${B})`}return y}case"DataView":{let y="new DataView";return s.has(i.buffer)?y+=`(${a(i.buffer)}`:y+=`(new Uint8Array([${new Uint8Array(i.buffer)}]).buffer`,i.byteLength!==i.buffer.byteLength&&(y+=`,${i.startOffset},${i.byteLength}`),y+")"}case"ArrayBuffer":return`new Uint8Array([${new Uint8Array(i).toString()}]).buffer`;case"Temporal.Duration":case"Temporal.Instant":case"Temporal.PlainDate":case"Temporal.PlainTime":case"Temporal.PlainDateTime":case"Temporal.PlainMonthDay":case"Temporal.PlainYearMonth":case"Temporal.ZonedDateTime":return`${d}.from(${$(i.toString())})`;default:let c=Object.keys(i),b=c.map(y=>`${ei(y)}:${a(i[y])}`).join(",");return Object.getPrototypeOf(i)===null?c.length>0?`{${b},__proto__:null}`:"{__proto__:null}":`{${b}}`}}let g=a(t);if(s.size){let i=[],d=[],u=[];return s.forEach((_,c)=>{if(i.push(_),o.has(c)){u.push(o.get(c));return}if(Je(c)){u.push(gn(c));return}let b=wt(c);switch(b){case"Number":case"String":case"Boolean":case"BigInt":u.push(`Object(${a(c.valueOf())})`);break;case"RegExp":let{source:f,flags:y}=c,C=y?`new RegExp(${$(f)},"${y}")`:`new RegExp(${$(f)})`;u.push(C);break;case"Date":u.push(`new Date(${c.getTime()})`);break;case"URL":u.push(`new URL(${$(c.toString())})`);break;case"URLSearchParams":u.push(`new URLSearchParams(${$(c.toString())})`);break;case"Array":u.push(`Array(${c.length})`),c.forEach((B,x)=>{d.push(`${_}[${x}]=${a(B)}`)});break;case"Set":u.push("new Set"),d.push(`${_}.${Array.from(c).map(B=>`add(${a(B)})`).join(".")}`);break;case"Map":u.push("new Map"),d.push(`${_}.${Array.from(c).map(([B,x])=>`set(${a(B)}, ${a(x)})`).join(".")}`);break;case"Int8Array":case"Uint8Array":case"Uint8ClampedArray":case"Int16Array":case"Uint16Array":case"Float16Array":case"Int32Array":case"Uint32Array":case"Float32Array":case"Float64Array":case"BigInt64Array":case"BigUint64Array":{let B=`new ${b}`;if(s.has(c.buffer))B+=`(${a(c.buffer)})`;else{let x=new c.constructor(c.buffer);B+=`([${x}])`}if(c.byteLength!==c.buffer.byteLength){let x=c.byteOffset/c.BYTES_PER_ELEMENT,X=x+c.length;B+=`.subarray(${x},${X})`}u.push("{}"),d.push(`${_}=${B}`);break}case"DataView":{let B="new DataView";s.has(c.buffer)?B+=`(${a(c.buffer)}`:B+=`(new Uint8Array([${new Uint8Array(c.buffer)}]).buffer`,c.byteLength!==c.buffer.byteLength&&(B+=`,${c.byteOffset},${c.byteLength}`),B+=")",u.push("{}"),d.push(`${_}=${B}`);break}case"ArrayBuffer":u.push(`new Uint8Array([${new Uint8Array(c)}]).buffer`);break;default:u.push(Object.getPrototypeOf(c)===null?"Object.create(null)":"{}"),Object.keys(c).forEach(B=>{d.push(`${_}${ti(B)}=${a(c[B])}`)})}}),d.push(`return ${g}`),`(function(${i.join(",")}){${d.join(";")}}(${u.join(",")}))`}else return g}function Ks(t){let n="";do n=hn[t%hn.length]+n,t=~~(t/hn.length)-1;while(t>=0);return Ps.test(n)?`${n}0`:n}function qs(t){return io[t]||t}function po(t){return t.replace(zs,qs)}function ei(t){return/^[_$a-zA-Z][_$a-zA-Z0-9]*$/.test(t)?t:po(JSON.stringify(t))}function ti(t){return/^[_$a-zA-Z][_$a-zA-Z0-9]*$/.test(t)?`.${t}`:`[${po(JSON.stringify(t))}]`}function gn(t){let n=typeof t;if(n==="string")return $(t);if(t===void 0)return"void 0";if(t===0&&1/t<0)return"-0";let e=String(t);return n==="number"?e.replace(/^(-)?0\./,"$1."):n==="bigint"?t+"n":e}var hn,zs,Ps,ho=h(()=>{fo();hn="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$",zs=/[<\b\f\n\r\t\0\u2028\u2029]/g,Ps=/^(?:do|if|in|for|int|let|new|try|var|byte|case|char|else|enum|goto|long|this|void|with|await|break|catch|class|const|final|float|short|super|throw|while|yield|delete|double|export|import|native|return|switch|throws|typeof|boolean|default|extends|finally|package|private|abstract|continue|debugger|function|volatile|interface|protected|transient|implements|instanceof|synchronized)$/});var mn=h(()=>{ho()});var Q,Ee,Se,ye,ce,R,Qt,S,mo,bn,_n,Me,bo,$e,xe,_o,vn,In,vo,G,je,Ce,xn,Cn=h(()=>{z();cn();Ie();le();Pr();on();D();V();dn();so();mn();L();nt();G=class G{constructor(n,e){J(this,S);J(this,Q,[]);J(this,Ee);J(this,Se,!1);J(this,ye,null);T(this,"type");J(this,ce);T(this,"promise");T(this,"global");T(this,"local");j(this,ce,e),this.global=n,this.local=e?{...e.local}:{select_value:void 0},this.type=e?e.type:"body"}head(n){let e=new G(this.global,this);e.type="head",v(this,Q).push(e),e.child(n)}async_block(n,e){v(this,Q).push(He),this.async(n,e),v(this,Q).push(_e)}async(n,e){let r=e;if(n.length>0){let o=A;r=l=>Promise.all(n).then(()=>{let s=A;try{return W(o),e(l)}finally{W(s)}})}this.child(r)}run(n){let e=A,r=Promise.resolve(n[0]()),o=[r];for(let l of n.slice(1))r=r.then(()=>{let s=A;W(e);try{return l()}finally{W(s)}}),o.push(r);return r.catch(U),this.promise=r,o}child_block(n){v(this,Q).push(He),this.child(n),v(this,Q).push(_e)}child(n){let e=new G(this.global,this);v(this,Q).push(e);let r=A;W({...A,p:r,c:null,r:e});let o=n(e);return W(r),o instanceof Promise&&(o.catch(U),o.finally(()=>W(null)).catch(U),e.global.mode==="sync"&&xt(),e.promise=o),e}boundary(n,e){var l;let r=new G(this.global,this);v(this,Q).push(r);let o=A;n.failed&&j(r,ye,{failed:n.failed,transformError:this.global.transformError,context:o}),W({...A,p:o,c:null,r});try{let s=e(r);W(o),s instanceof Promise&&(r.global.mode==="sync"&&xt(),s.catch(U),r.promise=s)}catch(s){W(o);let a=n.failed;if(!a)throw s;let g=this.global.transformError(s);v(r,Q).length=0,j(r,ye,null),g instanceof Promise?(this.global.mode==="sync"&&xt(),r.promise=g.then(i=>{var d;W(o),v(r,Q).push(w(d=G,R,Qt).call(d,i)),a(r,i,U),v(r,Q).push(_e)}),r.promise.catch(U)):(v(r,Q).push(w(l=G,R,Qt).call(l,g)),a(r,g,U),v(r,Q).push(_e))}}component(n,e){$r(e);let r=this.child(n);j(r,Se,!0),jr()}select(n,e,r,o,l,s,a){let{value:g,...i}=n;this.push(``),this.child(d=>{d.local.select_value=g,e(d)}),this.push(`${a?"":""}`)}option(n,e,r,o,l,s,a){v(this,Q).push(`{rt.call(n,"value")&&(d=n.value),d===this.local.select_value&&v(i,Q).push(' selected=""'),v(i,Q).push(`>${_}${a?"":""}`),u&&i.head(c=>c.push(u))};typeof e=="function"?this.child(i=>{var u,_;let d=new G(this.global,this);if(e(d),this.global.mode==="async")return w(u=d,S,xe).call(u).then(c=>{g(i,c.body.replaceAll("",""),c)});{let c=w(_=d,S,$e).call(_);g(i,c.body.replaceAll("",""),c)}}):g(this,e,{body:m(e)})}title(n){let e=this.get_path(),r=o=>{this.global.set_title(o,e)};this.child(o=>{var s,a;let l=new G(o.global,o);if(n(l),o.global.mode==="async")return w(s=l,S,xe).call(s).then(g=>{r(g.head)});{let g=w(a=l,S,$e).call(a);r(g.head)}})}push(n){typeof n=="function"?this.child(async e=>e.push(await n())):v(this,Q).push(n)}on_destroy(n){(v(this,Ee)??j(this,Ee,[])).push(n)}get_path(){return v(this,ce)?[...v(this,ce).get_path(),v(v(this,ce),Q).indexOf(this)]:[]}copy(){let n=new G(this.global,v(this,ce));return j(n,Q,v(this,Q).map(e=>e instanceof G?e.copy():e)),n.promise=this.promise,n}subsume(n){if(this.global.mode!==n.global.mode)throw new Error("invariant: A renderer cannot switch modes. If you're seeing this, there's a compiler bug. File an issue!");this.local=n.local,j(this,Q,v(n,Q).map((e,r)=>{let o=v(this,Q)[r];return o instanceof G&&e instanceof G?(o.subsume(e),o):e})),this.promise=n.promise,this.type=n.type}get length(){return v(this,Q).length}static render(n,e={}){let r,o,l={};return Object.defineProperties(l,{html:{get:()=>{var s;return(r??(r=w(s=G,R,Me).call(s,n,e))).body}},head:{get:()=>{var s;return(r??(r=w(s=G,R,Me).call(s,n,e))).head}},body:{get:()=>{var s;return(r??(r=w(s=G,R,Me).call(s,n,e))).body}},hashes:{value:{script:""}},then:{value:(s,a)=>{var g;if(!q){let i=r??(r=w(g=G,R,Me).call(g,n,e)),d=s({head:i.head,body:i.body,html:i.body,hashes:{script:[]}});return Promise.resolve(d)}return o??(o=to().then(()=>eo(()=>{var i;return w(i=G,R,bo).call(i,n,e)}))),o.then(i=>(Object.defineProperty(i,"html",{get:()=>{Vr()}}),s(i)),a)}}}),l}};Q=new WeakMap,Ee=new WeakMap,Se=new WeakMap,ye=new WeakMap,ce=new WeakMap,R=new WeakSet,Qt=function(n){var e=JSON.stringify(n),r=e.replace(/>/g,"\\u003e").replace(/`},S=new WeakSet,mo=function*(){var n;for(let e of w(this,S,bn).call(this))yield*w(n=e,S,_n).call(n)},bn=function*(){var n;for(let e of v(this,Q))typeof e!="string"&&(yield*w(n=e,S,bn).call(n));v(this,Se)&&(yield this)},_n=function*(){var n;if(v(this,Ee))for(let e of v(this,Ee))yield e;for(let e of v(this,Q))e instanceof G&&!v(e,Se)&&(yield*w(n=e,S,_n).call(n))},Me=function(n,e){var o,l,s;var r=A;try{let a=w(o=G,R,vn).call(o,"sync",n,e),g=w(l=a,S,$e).call(l);return w(s=G,R,In).call(s,g,a)}finally{an(),W(r)}},bo=async function(n,e){var o,l,s,a;let r=A;try{let g=w(o=G,R,vn).call(o,"async",n,e),i=await w(l=g,S,xe).call(l),d=await w(s=g,S,_o).call(s);return d!==null&&(i.head=d+i.head),w(a=G,R,In).call(a,i,g)}finally{W(r),an()}},$e=function(n={head:"",body:""}){var e;for(let r of v(this,Q))typeof r=="string"?n[this.type]+=r:r instanceof G&&w(e=r,S,$e).call(e,n);return n},xe=async function(n={head:"",body:""}){var e,r,o,l;await this.promise;for(let s of v(this,Q))if(typeof s=="string")n[this.type]+=s;else if(s instanceof G)if(v(s,ye)){let a={head:"",body:""};try{await w(e=s,S,xe).call(e,a),n.head+=a.head,n.body+=a.body}catch(g){let{context:i,failed:d,transformError:u}=v(s,ye);W(i);let _=u(g);W(null);let c=await _;W(i);let b=new G(s.global,s);b.type=s.type,v(b,Q).push(w(r=G,R,Qt).call(r,c)),d(b,c,U),v(b,Q).push(_e),await w(o=b,S,xe).call(o,n)}}else await w(l=s,S,xe).call(l,n);return n},_o=async function(){let n=Bt().hydratable;for(let[e,r]of n.unresolved_promises)zr(r,n.lookup.get(r)?.stack??"");for(let e of n.comparisons)await e;return await w(this,S,vo).call(this,n)},vn=function(n,e,r){r.idPrefix?.includes("--")&&Hr();var o=A;try{let l=new G(new xn(n,r.idPrefix?r.idPrefix+"-":"",r.csp,r.transformError)),s={p:null,c:r.context??null,r:l};return W(s),l.push(He),e(l,r.props??{}),l.push(_e),l}finally{W(o)}},In=function(n,e){var l;for(let s of w(l=e,S,mo).call(l))s();let r=n.head+e.global.get_title(),o=n.body;for(let{hash:s,code:a}of e.global.css)r+=``;return{head:r,body:o,hashes:{script:e.global.csp.script_hashes}}},vo=async function(n){if(n.lookup.size===0)return null;let e=[],r=!1;for(let[a,g]of n.lookup){if(g.promises){r=!0;for(let i of g.promises)await i}e.push(`[${Ze(a)},${g.serialized}]`)}let o="const h = (window.__svelte ??= {}).h ??= new Map();";r&&(o=`const r = (v) => Promise.resolve(v); + ${o}`);let l=` { ${o} @@ -39,15 +39,15 @@ https://svelte.dev/e/unresolved_hydratable`,Gs,Ns):console.warn("https://svelte. h.set(k, v); } } - `,s="";if(this.global.csp.nonce)s=` nonce="${this.global.csp.nonce}"`;else if(this.global.csp.hash){let l=await so(a);this.global.csp.script_hashes.push(`sha256-${l}`)}return` - ${a}`},M(B,L);Ke=B,Fr=class{constructor(r,e="",n={hash:!1},o){O(this,"csp");O(this,"mode");O(this,"uid");O(this,"css",new Set);O(this,"transformError");M(this,Be,{path:[],value:""});this.mode=r,this.csp={...n,script_hashes:[]},this.transformError=o??(s=>{throw s});let a=1;this.uid=()=>`${e}s${a++}`}get_title(){return m(this,Be).value}set_title(r,e){let n=m(this,Be).path,o=0,a=Math.min(e.length,n.length);for(;on[o])&&(m(this,Be).path=e,m(this,Be).value=r)}};Be=new WeakMap});function Br(t){var r=String(t??""),e=b?``:"";return e+r+""}var xo=p(()=>{E();It()});var zs,hd,Fo=p(()=>{zs={li:{direct:["li"]},dt:{descendant:["dt","dd"],reset_by:["dl"]},dd:{descendant:["dt","dd"],reset_by:["dl"]},p:{descendant:["address","article","aside","blockquote","div","dl","fieldset","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","hr","main","menu","nav","ol","p","pre","section","table","ul"]},rt:{descendant:["rt","rp"]},rp:{descendant:["rt","rp"]},optgroup:{descendant:["optgroup"]},option:{descendant:["option","optgroup"]},thead:{direct:["tbody","tfoot"]},tbody:{direct:["tbody","tfoot"]},tfoot:{direct:["tbody"]},tr:{direct:["tr","tbody"]},td:{direct:["td","th","tr"]},th:{direct:["td","th","tr"]}},hd={...zs,form:{descendant:["form"]},a:{descendant:["a"]},button:{descendant:["button"]},h1:{descendant:["h1","h2","h3","h4","h5","h6"]},h2:{descendant:["h1","h2","h3","h4","h5","h6"]},h3:{descendant:["h1","h2","h3","h4","h5","h6"]},h4:{descendant:["h1","h2","h3","h4","h5","h6"]},h5:{descendant:["h1","h2","h3","h4","h5","h6"]},h6:{descendant:["h1","h2","h3","h4","h5","h6"]},tr:{only:["th","td","style","script","template"]},tbody:{only:["tr","style","script","template"]},thead:{only:["tr","style","script","template"]},tfoot:{only:["tr","style","script","template"]},colgroup:{only:["col","template"]},table:{only:["caption","colgroup","tbody","thead","tfoot","style","script","template"]},head:{only:["base","basefont","bgsound","link","meta","title","noscript","noframes","style","script","template"]},html:{only:["head","body","frameset"]},frameset:{only:["frame"]},"#document":{only:["html"]}}});function Io(){return ln().filter(r=>r.trim().startsWith("at ")).map(r=>r.replace(/\((.*):\d+:\d+\)$/,(e,n)=>`(${n})`)).join(` -`)}var Cr=p(()=>{Z();Fo();me();Fe();le();wr()});function Qr(t,r={}){return r.csp?.hash&&r.csp.nonce&&Wn(),Ke.render(t,r)}function Ir(t,r,e,n,o=0){n&&(t.style=Kr(t.style,n)),t.class&&(t.class=Pr(t.class)),(r||e)&&(t.class=Dt(t.class,r,e));let a="",s,l=(o&1)===0,d=(o&2)===0,i=(o&4)!==0;for(s of Object.keys(t))if(typeof t[s]!="function"&&!(s[0]==="$"&&s[1]==="$")&&!(s===""||ei.test(s))){var f=t[s],c=s.toLowerCase();d&&(s=c),!(c.length>2&&c.startsWith("on"))&&(i&&(s==="defaultvalue"||s==="defaultchecked")&&(s=s==="defaultvalue"?"value":"checked",t[s])||(a+=Q(s,f,l&&Zn(s))))}return a}function V(t){return typeof t=="string"?t:t==null?"":t+""}function ne(t,r,e){var n=Dt(t,r,e);return n?` class="${h(n,!0)}"`:""}function S(t){return t?t.length!==void 0?t:Array.from(t):[]}function ti(t){let r=oe;return()=>(r===oe&&(r=t()),r)}function Er(t){let r=F===null?t:ti(t),e;return function(n){return arguments.length===0?e??r():(e=n,e)}}var ei,T=p(()=>{Z();qr();k();mt();Z();st();E();ir();ar();It();wr();le();Fe();xo();Fe();Cr();ft();k();ar();ei=/[\s'">/=\u{FDD0}-\u{FDEF}\u{FFFE}\u{FFFF}\u{1FFFE}\u{1FFFF}\u{2FFFE}\u{2FFFF}\u{3FFFE}\u{3FFFF}\u{4FFFE}\u{4FFFF}\u{5FFFE}\u{5FFFF}\u{6FFFE}\u{6FFFF}\u{7FFFE}\u{7FFFF}\u{8FFFE}\u{8FFFF}\u{9FFFE}\u{9FFFF}\u{AFFFE}\u{AFFFF}\u{BFFFE}\u{BFFFF}\u{CFFFE}\u{CFFFF}\u{DFFFE}\u{DFFFF}\u{EFFFE}\u{EFFFF}\u{FFFFE}\u{FFFFF}\u{10FFFE}\u{10FFFF}]/u});function Bo(t,r){ee||Rt("hydratable");let{hydratable:e}=Et(),n=e.lookup.get(t);if(n!==void 0){if(b){let a=ni(t,n,wo(t,r()));a.catch(()=>{}),e.comparisons.push(a)}return n.value}let o=r();return n=wo(t,o,e.unresolved_promises),e.lookup.set(t,n),o}function wo(t,r,e){let n={value:r,serialized:""};b&&(n.stack=Io());let o=1;return n.serialized=Ne(n.value,(a,s)=>{if(ri(a)){let l=`"${o++}"`,d=a.then(i=>{n.serialized=n.serialized.replace(l,()=>`r(${s(i)})`)}).catch(i=>Yn(t,oi(n.stack,i?.stack)));return e?.set(d,t),d.catch(()=>{}).finally(()=>e?.delete(d)),(n.promises??(n.promises=[])).push(d),l}}),n}function ri(t){return Object.prototype.toString.call(t)==="[object Promise]"}async function ni(t,r,e){for(let n of r?.promises??[])await n;for(let n of e?.promises??[])await n;if(r.serialized!==e.serialized){let n=r.stack,o=e.stack,a=n===o?`Occurred at: -${n}`:`First occurrence at: -${n} + `,s="";if(this.global.csp.nonce)s=` nonce="${this.global.csp.nonce}"`;else if(this.global.csp.hash){let a=await oo(l);this.global.csp.script_hashes.push(`sha256-${a}`)}return` + ${l}`},J(G,R);je=G,xn=class{constructor(n,e="",r={hash:!1},o){T(this,"csp");T(this,"mode");T(this,"uid");T(this,"css",new Set);T(this,"transformError");J(this,Ce,{path:[],value:""});this.mode=n,this.csp={...r,script_hashes:[]},this.transformError=o??(s=>{throw s});let l=1;this.uid=()=>`${e}s${l++}`}get_title(){return v(this,Ce).value}set_title(n,e){let r=v(this,Ce).path,o=0,l=Math.min(e.length,r.length);for(;or[o])&&(v(this,Ce).path=e,v(this,Ce).value=n)}};Ce=new WeakMap});function Fn(t){var n=String(t??""),e=F?``:"";return e+n+""}var Io=h(()=>{E();It()});var ni,xd,xo=h(()=>{ni={li:{direct:["li"]},dt:{descendant:["dt","dd"],reset_by:["dl"]},dd:{descendant:["dt","dd"],reset_by:["dl"]},p:{descendant:["address","article","aside","blockquote","div","dl","fieldset","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","hr","main","menu","nav","ol","p","pre","section","table","ul"]},rt:{descendant:["rt","rp"]},rp:{descendant:["rt","rp"]},optgroup:{descendant:["optgroup"]},option:{descendant:["option","optgroup"]},thead:{direct:["tbody","tfoot"]},tbody:{direct:["tbody","tfoot"]},tfoot:{direct:["tbody"]},tr:{direct:["tr","tbody"]},td:{direct:["td","th","tr"]},th:{direct:["td","th","tr"]}},xd={...ni,form:{descendant:["form"]},a:{descendant:["a"]},button:{descendant:["button"]},h1:{descendant:["h1","h2","h3","h4","h5","h6"]},h2:{descendant:["h1","h2","h3","h4","h5","h6"]},h3:{descendant:["h1","h2","h3","h4","h5","h6"]},h4:{descendant:["h1","h2","h3","h4","h5","h6"]},h5:{descendant:["h1","h2","h3","h4","h5","h6"]},h6:{descendant:["h1","h2","h3","h4","h5","h6"]},tr:{only:["th","td","style","script","template"]},tbody:{only:["tr","style","script","template"]},thead:{only:["tr","style","script","template"]},tfoot:{only:["tr","style","script","template"]},colgroup:{only:["col","template"]},table:{only:["caption","colgroup","tbody","thead","tfoot","style","script","template"]},head:{only:["base","basefont","bgsound","link","meta","title","noscript","noframes","style","script","template"]},html:{only:["head","body","frameset"]},frameset:{only:["frame"]},"#document":{only:["html"]}}});function yo(){return lr().filter(n=>n.trim().startsWith("at ")).map(n=>n.replace(/\((.*):\d+:\d+\)$/,(e,r)=>`(${r})`)).join(` +`)}var Bn=h(()=>{D();xo();he();Ie();le();Cn()});function wn(t,n={}){return n.csp?.hash&&n.csp.nonce&&Tr(),je.render(t,n)}function yn(t,n,e,r,o=0){r&&(t.style=kt(t.style,r)),t.class&&(t.class=Kn(t.class)),(n||e)&&(t.class=St(t.class,n,e));let l="",s,a=(o&1)===0,g=(o&2)===0,i=(o&4)!==0;for(s of Object.keys(t))if(typeof t[s]!="function"&&!(s[0]==="$"&&s[1]==="$")&&!(s===""||ii.test(s))){var d=t[s],u=s.toLowerCase();g&&(s=u),!(u.length>2&&u.startsWith("on"))&&(i&&(s==="defaultvalue"||s==="defaultchecked")&&(s=s==="defaultvalue"?"value":"checked",t[s])||(l+=p(s,d,a&&Nr(s))))}return l}function I(t){return typeof t=="string"?t:t==null?"":t+""}function ne(t,n,e){var r=St(t,n,e);return r?` class="${m(r,!0)}"`:""}function ze(t,n){var e=kt(t,n);return e?` style="${m(e,!0)}"`:""}function Z(t){return t?t.length!==void 0?t:Array.from(t):[]}function li(t){let n=re;return()=>(n===re&&(n=t()),n)}function Co(t){let n=A===null?t:li(t),e;return function(r){return arguments.length===0?e??n():(e=r,e)}}var ii,V=h(()=>{D();qn();L();dt();D();nt();E();on();sn();It();Cn();le();Ie();Io();Ie();Bn();at();L();sn();ii=/[\s'">/=\u{FDD0}-\u{FDEF}\u{FFFE}\u{FFFF}\u{1FFFE}\u{1FFFF}\u{2FFFE}\u{2FFFF}\u{3FFFE}\u{3FFFF}\u{4FFFE}\u{4FFFF}\u{5FFFE}\u{5FFFF}\u{6FFFE}\u{6FFFF}\u{7FFFE}\u{7FFFF}\u{8FFFE}\u{8FFFF}\u{9FFFE}\u{9FFFF}\u{AFFFE}\u{AFFFF}\u{BFFFE}\u{BFFFF}\u{CFFFE}\u{CFFFF}\u{DFFFE}\u{DFFFF}\u{EFFFE}\u{EFFFF}\u{FFFFE}\u{FFFFF}\u{10FFFE}\u{10FFFF}]/u});function Bo(t,n){q||Xt("hydratable");let{hydratable:e}=Bt(),r=e.lookup.get(t);if(r!==void 0){if(F){let l=ci(t,r,Fo(t,n()));l.catch(()=>{}),e.comparisons.push(l)}return r.value}let o=n();return r=Fo(t,o,e.unresolved_promises),e.lookup.set(t,r),o}function Fo(t,n,e){let r={value:n,serialized:""};F&&(r.stack=yo());let o=1;return r.serialized=Ze(r.value,(l,s)=>{if(ai(l)){let a=`"${o++}"`,g=l.then(i=>{r.serialized=r.serialized.replace(a,()=>`r(${s(i)})`)}).catch(i=>Dr(t,ui(r.stack,i?.stack)));return e?.set(g,t),g.catch(()=>{}).finally(()=>e?.delete(g)),(r.promises??(r.promises=[])).push(g),a}}),r}function ai(t){return Object.prototype.toString.call(t)==="[object Promise]"}async function ci(t,n,e){for(let r of n?.promises??[])await r;for(let r of e?.promises??[])await r;if(n.serialized!==e.serialized){let r=n.stack,o=e.stack,l=r===o?`Occurred at: +${r}`:`First occurrence at: +${r} Second occurrence at: -${o}`;Vn(t,a)}}function oi(t,r){let e="";return t&&(e+=t+` -`),r&&(e+=`Caused by: -`+r+` -`),e||""}var Co=p(()=>{z();hr();le();vr();E();Cr()});function Qo(t){return(r,...e)=>{var n=e.map(o=>()=>o);r.push(t(...n).render().trim())}}var Eo=p(()=>{});var Ao={};ot(Ao,{afterUpdate:()=>C,beforeUpdate:()=>C,createContext:()=>Hn,createEventDispatcher:()=>si,createRawSnippet:()=>Qo,flushSync:()=>C,fork:()=>ci,getAbortSignal:()=>Tn,getAllContexts:()=>$n,getContext:()=>fr,hasContext:()=>dr,hydratable:()=>Bo,hydrate:()=>ai,mount:()=>ii,onDestroy:()=>Ar,onMount:()=>C,setContext:()=>pr,settled:()=>fi,tick:()=>ui,unmount:()=>li,untrack:()=>Hr});function Ar(t){F.r.on_destroy(t)}function si(){return C}function ii(){$e("mount")}function ai(){$e("hydrate")}function li(){$e("unmount")}function ci(){$e("fork")}async function ui(){}async function fi(){}var qe=p(()=>{Fe();k();le();k();ur();Fe();Co();Eo()});var ko={};ot(ko,{default:()=>Uo});function Uo(t,r){t.component(e=>{let{scene:n}=r,o=188,a=66;function s(u){let g=new kr.default.graphlib.Graph;g.setGraph({rankdir:"TB",nodesep:56,ranksep:84,marginx:24,marginy:24}),g.setDefaultEdgeLabel(()=>({}));for(let I of u.nodes)g.setNode(I.fqn,{width:o,height:a});for(let I of u.edges)g.setEdge(I.from,I.to);kr.default.layout(g);let $=u.nodes.map(I=>{let w=g.node(I.fqn);return{id:I.fqn,position:{x:w.x-o/2,y:w.y-a/2},data:{label:I.label,kind:I.kind,summary:I.summary??""},class:`c4-node ${I.kind}`,width:o,height:a}}),U=u.edges.map((I,w)=>({id:`e${w}`,source:I.from,target:I.to,label:I.label||void 0,type:"smoothstep",animated:I.kind==="trigger",class:`c4-edge ${I.kind}`}));return{nodes:$,edges:U}}let l=s(n),d=l.nodes,i=l.edges,f=!0,c;function _(u){u.push('
                      '),(0,fe.SvelteFlow)(u,{fitView:!0,minZoom:.2,maxZoom:2.5,proOptions:{hideAttribution:!0},get nodes(){return d},set nodes(g){d=g,f=!1},get edges(){return i},set edges(g){i=g,f=!1},children:g=>{(0,fe.Background)(g,{gap:22}),g.push(" "),(0,fe.MiniMap)(g,{pannable:!0,zoomable:!0}),g.push(" "),(0,fe.Controls)(g,{showLock:!1}),g.push("")},$$slots:{default:!0}}),u.push("
                      ")}do f=!0,c=e.copy(),_(c);while(!f);e.subsume(c)})}var fe,kr,So=p(()=>{T();fe=nt("@xyflow/svelte"),kr=Vr(nt("@dagrejs/dagre"))});var Go=p(()=>{});var Lo={};ot(Lo,{default:()=>No});function No(t,r){t.component(e=>{let{scene:n}=r,o=v=>v.split("::").pop();function a(v){if(v)return v.kind==="return"?v.detail?v.label?`${v.label}<${v.detail}>`:`return ${v.detail}`:v.label||"return":v.label||void 0}function s(v,W,de){for(let X of v)X.Message?de.push({...X.Message,frame:W}):X.Frame&&s(X.Frame.body,`${X.Frame.kind} ${X.Frame.cond}`,de);return de}let l=s(n.items,null,[]),d=new Map(n.participants.map(v=>[v.fqn,v.kind])),i=230,f=168,c=0,_=!1,u=null;function g(){u&&clearInterval(u),u=null,_=!1}function $(){c>=l.length&&(c=0),_=!0,u=setInterval(()=>c>=l.length?g():c+=1,1150)}let U=()=>_?g():$(),I=v=>{g(),c=Math.max(0,Math.min(l.length,c+v))};Ar(g);function w(v){let W=[],de=X=>{W.includes(X)||W.push(X)};de(n.entry);for(let X=0;Xc>0?l[c-1]:null),rt=Er(()=>c>=l.length&&l.length>0),Ce=!0,Re;function St(v){v.push(`
                      flow ${h(o(n.entry))}
                      `),Y()?(v.push(""),v.push(`${h(o(Y().from))} \u2192 ${h(o(Y().to))} `),a(Y())?(v.push(""),v.push(`${h(a(Y()))}`)):v.push(""),v.push(" "),Y().frame?(v.push(""),v.push(`${h(Y().frame)}`)):v.push(""),v.push("")):(v.push(""),v.push('triggered entry point \u2014 press play to trace the request')),v.push('
                      '),(0,kt.SvelteFlow)(v,{fitView:!0,minZoom:.2,maxZoom:2,nodesDraggable:!1,proOptions:{hideAttribution:!0},get nodes(){return D},set nodes(W){D=W,Ce=!1},get edges(){return pe},set edges(W){pe=W,Ce=!1},children:W=>{(0,kt.Background)(W,{gap:24})},$$slots:{default:!0}}),v.push(`
                      ${h(c)}/${h(l.length)}
                      `)}do Ce=!0,Re=e.copy(),St(Re);while(!Ce);e.subsume(Re)})}var kt,Do=p(()=>{T();qe();kt=nt("@xyflow/svelte");Go()});var bi={};ot(bi,{renderPage:()=>gi});T();T();qe();T();T();function et(t,r){t.component(e=>{let{node:n}=r;if(e.push(`
                      `),n.children.length?(e.push(""),e.push('\u25BE')):(e.push(""),e.push('')),e.push(` ${h(n.name)}
                      `),n.children.length){e.push(""),e.push('
                        ');let o=S(n.children);for(let a=0,s=o.length;a
                      ")}else e.push("");e.push("")})}function Ur(t,r){t.component(e=>{let{site:n,docGroups:o=[],sidebar:a}=r;if(e.push(`")})}T();T();qe();function tt(t,r){t.component(e=>{let{diagram:n}=r,o=null;C(async()=>{if(!o||n.diagram==="empty")return;let{mount:a}=await Promise.resolve().then(()=>(qe(),Ao)),s=n.diagram==="c4"?await Promise.resolve().then(()=>(So(),ko)):await Promise.resolve().then(()=>(Do(),Lo));a(s.default,{target:o,props:{scene:n.scene}})}),n.diagram==="empty"?(e.push(""),e.push(`
                      No ${h(n.eyebrow)} diagram available.
                      `)):(e.push(""),e.push(`
                      ${h(n.caption)} ${h(n.diagram==="sequence"?"play \xB7 scrub the flow":"scroll to zoom \xB7 drag to pan")}
                      `)),e.push("")})}function Sr(t,r){t.component(e=>{let{page:n}=r;e.push(`
                      Architecture documentation

                      ${h(n.title)}

                      A C4 model of the workspace: persons, systems, and their containers and - components, with relationships and animated sequence flows.

                      `),tt(e,{diagram:n.contextDiagram}),e.push('
                      ');let o=S(n.cards);for(let a=0,s=o.length;a
                      ${h(l.name)}
                      ${h(l.meta)}
                      `)}e.push("
                      ")})}T();T();T();function Gr(t,r){t.component(e=>{let{groups:n}=r;if(n.length){e.push(""),e.push('
                      ');let o=S(n);for(let a=0,s=o.length;a

                      ${h(l.title)}

                        `);let d=S(l.items);for(let i=0,f=d.length;i${h(c.edgeKind)} `),c.arrow?(e.push(""),e.push('\u2192')):e.push(""),e.push(" "),c.href?(e.push(""),e.push(`${h(c.fqn)}`)):(e.push(""),e.push(`${h(c.fqn)}`)),e.push(" "),c.label?(e.push(""),e.push(`\xB7 ${h(c.label)}`)):e.push(""),e.push("")}e.push("
                      ")}e.push("")}else e.push("");e.push("")})}T();function Nr(t,r){t.component(e=>{let{scenarios:n}=r;if(n.length){e.push(""),e.push('

                      Scenarios

                      ');let o=S(n);for(let a=0,s=o.length;a
                      ${h(l.name)}
                      `),l.summary?(e.push(""),e.push(`

                      ${h(l.summary)}

                      `)):e.push(""),e.push(" "),l.extended?(e.push(""),e.push(`

                      ${h(l.extended)}

                      `)):e.push(""),e.push(" "),l.tags.length){e.push(""),e.push('
                      ');let i=S(l.tags);for(let f=0,c=i.length;f${h(_)}`)}e.push("
                      ")}else e.push("");e.push('
                        ');let d=S(l.steps);for(let i=0,f=d.length;i${h(c.keyword)} ${h(c.text)}`)}e.push("
                      ")}e.push("")}else e.push("");e.push("")})}function Lr(t,r){t.component(e=>{let{section:n}=r;if(e.push(`
                      ${h(n.kind)}

                      ${h(n.name)} #

                      ${h(n.visibility)}
                      ${h(n.fqn)} `),n.summary?(e.push(""),e.push(`

                      ${h(n.summary)}

                      `)):e.push(""),e.push(" "),n.extended?(e.push(""),e.push(`

                      ${h(n.extended)}

                      `)):e.push(""),e.push(" "),n.tags.length){e.push(""),e.push('
                      ');let a=S(n.tags);for(let s=0,l=a.length;s${h(d)}`)}e.push("
                      ")}else e.push("");e.push(" "),Gr(e,{groups:n.relationships}),e.push(" "),Nr(e,{scenarios:n.scenarios}),e.push(" ");let o=S(n.diagrams);for(let a=0,s=o.length;a
                      ")})}function Dr(t,r){t.component(e=>{let{page:n}=r;e.push(`
                      Module

                      ${h(n.name)}

                      `);let o=S(n.sections);for(let a=0,s=o.length;a")})}T();function Rr(t,r){t.component(e=>{let{page:n}=r;e.push(`
                      Documentation

                      ${h(n.title)}

                      ${Br(n.html)}
                      `)})}T();function Zr(t){t.push('
                      Generated by pds doc.
                      ')}function Ro(t){di(t),hi(t),mi(t),pi(t)}function pi(t){let r=location.pathname.split("/").pop();r&&t.querySelectorAll(".docs-link").forEach(e=>{e.getAttribute("href").split("/").pop().split("#")[0]===r&&e.classList.add("is-active")})}function di(t){t.querySelectorAll(".tree .toggle").forEach(r=>{r.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation();let n=r.closest("li");n&&n.classList.toggle("collapsed")})})}function hi(t){let r=t.querySelector(".search input"),e=t.querySelector(".tree");if(!r||!e)return;let n=document.createElement("li");n.className="no-results",n.textContent="No matches",n.hidden=!0,e.appendChild(n),r.addEventListener("input",()=>{let o=r.value.trim().toLowerCase(),a=_i(e,o);n.hidden=a||o===""})}function _i(t,r){if(r==="")return t.querySelectorAll("li").forEach(n=>n.classList.remove("hidden")),!0;let e=!1;return t.querySelectorAll(":scope > li").forEach(n=>{Zo(n,r,!1)&&(e=!0)}),e}function Zo(t,r,e){let n=(t.dataset.search||"").toLowerCase(),o=e||n.indexOf(r)!==-1,a=!1;t.querySelectorAll(":scope > ul.children > li").forEach(l=>{Zo(l,r,o)&&(a=!0)});let s=o||a;return t.classList.toggle("hidden",!s),s&&t.classList.remove("collapsed"),s}function mi(t){function r(){let e=decodeURIComponent(location.hash.replace(/^#/,""));if(t.querySelectorAll(".tree .node-link.is-active").forEach(o=>{o.classList.remove("is-active")}),!e)return;let n=t.querySelector('.tree a[href$="#'+vi(e)+'"]');if(n){n.classList.add("is-active");let o=n.closest("li");for(;o;){o.classList.remove("collapsed");let a=o.parentElement;o=a?a.closest("li"):null}}}window.addEventListener("hashchange",r),r()}function vi(t){return window.CSS&&window.CSS.escape?window.CSS.escape(t):t.replace(/[^a-zA-Z0-9_-]/g,"\\$&")}function Tr(t,r){t.component(e=>{let{site:n,docGroups:o=[],sidebar:a,page:s}=r;C(()=>Ro(document)),e.push('
                      '),Ur(e,{site:n,docGroups:o,sidebar:a}),e.push('
                      '),s.kind==="index"?(e.push(""),Sr(e,{page:s})):s.kind==="doc"?(e.push(""),Rr(e,{page:s})):(e.push(""),Dr(e,{page:s})),e.push(" "),Zr(e,{}),e.push("
                      ")})}function gi(t){let r=JSON.parse(t),{head:e,body:n}=Qr(Tr,{props:r});return JSON.stringify({head:e,body:n})}return Mo(bi);})(); +${o}`;Yr(t,l)}}function ui(t,n){let e="";return t&&(e+=t+` +`),n&&(e+=`Caused by: +`+n+` +`),e||""}var wo=h(()=>{z();dn();le();mn();E();Bn()});function Qo(t){return(n,...e)=>{var r=e.map(o=>()=>o);n.push(t(...r).render().trim())}}var Ao=h(()=>{});var Go={};tt(Go,{afterUpdate:()=>U,beforeUpdate:()=>U,createContext:()=>Jr,createEventDispatcher:()=>pi,createRawSnippet:()=>Qo,flushSync:()=>U,fork:()=>mi,getAbortSignal:()=>Wr,getAllContexts:()=>Mr,getContext:()=>un,hasContext:()=>pn,hydratable:()=>Bo,hydrate:()=>hi,mount:()=>di,onDestroy:()=>fi,onMount:()=>U,setContext:()=>fn,settled:()=>_i,tick:()=>bi,unmount:()=>gi,untrack:()=>$n});function fi(t){A.r.on_destroy(t)}function pi(){return U}function di(){Oe("mount")}function hi(){Oe("hydrate")}function gi(){Oe("unmount")}function mi(){Oe("fork")}async function bi(){}async function _i(){}var At=h(()=>{Ie();L();le();L();cn();Ie();wo();Ao()});var Zo={};tt(Zo,{default:()=>Uo});function Uo(t,n){t.component(e=>{let{scene:r}=n,o=188,l=66;function s(c){let b=new An.default.graphlib.Graph;b.setGraph({rankdir:"TB",nodesep:56,ranksep:84,marginx:24,marginy:24}),b.setDefaultEdgeLabel(()=>({}));for(let C of c.nodes)b.setNode(C.fqn,{width:o,height:l});for(let C of c.edges)b.setEdge(C.from,C.to);An.default.layout(b);let f=c.nodes.map(C=>{let B=b.node(C.fqn);return{id:C.fqn,position:{x:B.x-o/2,y:B.y-l/2},data:{label:C.label,kind:C.kind,summary:C.summary??""},class:`c4-node ${C.kind}`,width:o,height:l}}),y=c.edges.map((C,B)=>({id:`e${B}`,source:C.from,target:C.to,label:C.label||void 0,type:"smoothstep",animated:C.kind==="trigger",class:`c4-edge ${C.kind}`}));return{nodes:f,edges:y}}let a=s(r),g=a.nodes,i=a.edges,d=!0,u;function _(c){c.push('
                      '),(0,ue.SvelteFlow)(c,{fitView:!0,minZoom:.2,maxZoom:2.5,proOptions:{hideAttribution:!0},get nodes(){return g},set nodes(b){g=b,d=!1},get edges(){return i},set edges(b){i=b,d=!1},children:b=>{(0,ue.Background)(b,{gap:22}),b.push(" "),(0,ue.MiniMap)(b,{pannable:!0,zoomable:!0}),b.push(" "),(0,ue.Controls)(b,{showLock:!1}),b.push("")},$$slots:{default:!0}}),c.push("
                      ")}do d=!0,u=e.copy(),_(u);while(!d);e.subsume(u)})}var ue,An,Eo=h(()=>{V();ue=et("@xyflow/svelte"),An=Tn(et("@dagrejs/dagre"))});var So=h(()=>{});function Gn(t,n){t.component(e=>{let{data:r}=n,o=r.placed,l=r.act;function s(c){return c?c.startsWith("event:")?{kind:"onevent",title:c.slice(6)}:c==="client"?{kind:"http",title:"client"}:c==="scheduler"?{kind:"schedule",title:"scheduler"}:c==="caller"?{kind:"caller",title:"caller"}:null:null}let a=s(o.id),g=a?a.kind:o.kind,i=a?a.title:o.label,d=a?"initiator":o.kind,u=!!o.id,_=c=>{u&&(c.metaKey||c.ctrlKey)&&(c.preventDefault(),r.onusages?.(o.id,c))};e.push(`
                      ${m(g)} ${m(i)}
                      `),l?(e.push(""),e.push(``)):e.push(""),e.push("")})}var ko=h(()=>{V();So()});var Xo=h(()=>{});function Un(t,n){t.component(e=>{let{data:r}=n;e.push(`
                      ${m(r.kind)} [${m(r.label)}] `);let o=Z(r.dividers);for(let l=0,s=o.length;l
                      [${m(a.guard||"else")}]`)}e.push("")})}var Lo=h(()=>{V();Xo()});var No=h(()=>{});function Zn(t,n){t.component(e=>{let{data:r}=n,o=c=>c?c.length*7.8+14:0;function l(c){return c==="Ok"||c==="Some"?{color:"var(--seq-ok)",text:`\u21A9 ${c}`}:c==="Err"||c==="None"?{color:"var(--seq-err)",text:`\u21A9 ${c}`}:{color:"var(--ink-faint)",text:c?`\u21A9 ${c}`:"\u21A9 return"}}let s=c=>c.detail?c.label?`<${c.detail}>`:` ${c.detail}`:"",a=c=>(r.lifelineX[c.from]??c.from_x)-17,g=c=>c.kind==="self"?`${c.from}::${c.label}`:`${c.to}::${c.label}`,i=(c,b)=>{(b.metaKey||b.ctrlKey)&&(b.preventDefault(),r.onusages?.(g(c),b))},d=(c,b)=>{(b.metaKey||b.ctrlKey)&&(b.preventDefault(),r.onusages?.(c,b))},u=c=>(c??"").split(/([A-Za-z_][A-Za-z0-9_]*)/).map((b,f)=>({text:b,fqn:f%2===1?r.typeFqn?.[b]??null:null})).filter(b=>b.text!=="");e.push(``);let _=Z(r.messages);for(let c=0,b=_.length;c"),e.push(``),f.label){e.push("");let y=(f.from_x+f.to_x)/2,C=f.label+(f.detail??"");e.push(`${m(f.label)}`);let B=Z(u(f.detail));for(let x=0,X=B.length;x"),e.push(`${m(O.text)}`)):(e.push(""),e.push(`${m(O.text)}`)),e.push("")}e.push("")}else e.push("");e.push(`${m(f.step)}`)}else if(f.kind==="self"){e.push("");let y=f.from_x+5;e.push(`${m(f.label)}${m(f.step)}`)}else{e.push("");let y=l(f.label),C=(f.from_x+f.to_x)/2,B=s(f),x=y.text+B;e.push(`${m(y.text)}`);let X=Z(u(B));for(let O=0,ke=X.length;O"),e.push(`${m(k.text)}`)):(e.push(""),e.push(`${m(k.text)}`)),e.push("")}e.push("")}e.push("")}e.push("")})}var Wo=h(()=>{V();No()});var Ro=h(()=>{});var Yo={};tt(Yo,{default:()=>Vo});function Vo(t,n){t.component(e=>{let{scene:r,layout:o,oninfo:l=null,oninfoend:s=null,onusages:a=null,typeFqn:g=null}=n,i=typeof document<"u"&&document.documentElement.getAttribute("data-theme")==="light"?"light":"dark",d={lifeline:Gn,fragment:Un,messages:Zn},u=x=>(x??"").split("::").pop();function _(x){if(!x||!Array.isArray(x.participants))return{nodes:[],edges:[]};let X=new Map((x.activations??[]).map(k=>[k.participant,k])),O=Object.fromEntries(x.participants.map(k=>[k.id,k.lifeline_x]));return{nodes:[...x.fragments.map((k,Gt)=>({id:`frag${Gt}`,type:"fragment",position:{x:k.rect.x,y:k.rect.y},width:k.rect.w,height:k.rect.h,data:{kind:k.kind,label:k.label,dividers:k.dividers.map(qe=>({guard:qe.guard,y:qe.y-k.rect.y}))},class:"seq-shell",draggable:!1,selectable:!1,connectable:!1,zIndex:2})),...x.participants.map(k=>({id:k.id,type:"lifeline",position:{x:0,y:0},width:x.width,height:x.height,data:{placed:k,act:X.get(k.id)??null,oninfo:l,oninfoend:s,onusages:a},class:"seq-shell",draggable:!1,selectable:!1,connectable:!1,zIndex:1})),{id:"__messages",type:"messages",position:{x:0,y:0},width:x.width,height:x.height,data:{messages:x.messages,width:x.width,height:x.height,lifelineX:O,oninfo:l,oninfoend:s,onusages:a,typeFqn:g},class:"seq-shell",draggable:!1,selectable:!1,connectable:!1,zIndex:3}],edges:[]}}let c=Co(()=>_(o)),b=[],f=[],y=!0,C;function B(x){x.push(`
                      flow ${m(u(r?.entry))}
                      sequence diagram \u2014 scroll to zoom \xB7 drag to pan
                      `),(0,fe.SvelteFlow)(x,{nodeTypes:d,fitView:!0,colorMode:i,minZoom:.2,maxZoom:2.5,nodesDraggable:!1,nodesConnectable:!1,elementsSelectable:!1,proOptions:{hideAttribution:!0},get nodes(){return b},set nodes(X){b=X,y=!1},get edges(){return f},set edges(X){f=X,y=!1},children:X=>{(0,fe.Background)(X,{gap:24}),X.push(" "),(0,fe.MiniMap)(X,{pannable:!0,zoomable:!0}),X.push(" "),(0,fe.Controls)(X,{showLock:!1}),X.push("")},$$slots:{default:!0}}),x.push("
                      ")}do y=!0,C=e.copy(),B(C);while(!y);e.subsume(C)})}var fe,Do=h(()=>{V();fe=et("@xyflow/svelte");ko();Lo();Wo();Ro()});var wi={};tt(wi,{renderPage:()=>Bi});V();V();At();V();V();function Pe(t,n){t.component(e=>{let{node:r}=n;if(e.push(`
                      `),r.children.length?(e.push(""),e.push('\u25BE')):(e.push(""),e.push('')),e.push(` ${m(r.name)}
                      `),r.children.length){e.push(""),e.push('
                        ');let o=Z(r.children);for(let l=0,s=o.length;l
                      ")}else e.push("");e.push("")})}function Qn(t,n){t.component(e=>{let{site:r,docGroups:o=[],sidebar:l}=n;if(e.push(`")})}V();V();At();function Ke(t,n){t.component(e=>{let{diagram:r}=n,o=null;U(async()=>{if(!o||r.diagram==="empty")return;let{mount:l}=await Promise.resolve().then(()=>(At(),Go)),s=r.diagram==="c4",a=s?await Promise.resolve().then(()=>(Eo(),Zo)):await Promise.resolve().then(()=>(Do(),Yo)),g=s?{scene:r.scene}:{scene:r.scene,layout:r.layout};l(a.default,{target:o,props:g})}),r.diagram==="empty"?(e.push(""),e.push(`
                      No ${m(r.eyebrow)} diagram available.
                      `)):(e.push(""),e.push(`
                      ${m(r.caption)} ${m(r.diagram==="sequence"?"play \xB7 scrub the flow":"scroll to zoom \xB7 drag to pan")}
                      `)),e.push("")})}function En(t,n){t.component(e=>{let{page:r}=n;e.push(`
                      Architecture documentation

                      ${m(r.title)}

                      A C4 model of the workspace: persons, systems, and their containers and + components, with relationships and animated sequence flows.

                      `),Ke(e,{diagram:r.contextDiagram}),e.push('
                      ');let o=Z(r.cards);for(let l=0,s=o.length;l
                      ${m(a.name)}
                      ${m(a.meta)}
                      `)}e.push("
                      ")})}V();V();V();function Sn(t,n){t.component(e=>{let{groups:r}=n;if(r.length){e.push(""),e.push('
                      ');let o=Z(r);for(let l=0,s=o.length;l

                      ${m(a.title)}

                        `);let g=Z(a.items);for(let i=0,d=g.length;i${m(u.edgeKind)} `),u.arrow?(e.push(""),e.push('\u2192')):e.push(""),e.push(" "),u.href?(e.push(""),e.push(`${m(u.fqn)}`)):(e.push(""),e.push(`${m(u.fqn)}`)),e.push(" "),u.label?(e.push(""),e.push(`\xB7 ${m(u.label)}`)):e.push(""),e.push("")}e.push("
                      ")}e.push("")}else e.push("");e.push("")})}V();function kn(t,n){t.component(e=>{let{scenarios:r}=n;if(r.length){e.push(""),e.push('

                      Scenarios

                      ');let o=Z(r);for(let l=0,s=o.length;l
                      ${m(a.name)}
                      `),a.summary?(e.push(""),e.push(`

                      ${m(a.summary)}

                      `)):e.push(""),e.push(" "),a.extended?(e.push(""),e.push(`

                      ${m(a.extended)}

                      `)):e.push(""),e.push(" "),a.tags.length){e.push(""),e.push('
                      ');let i=Z(a.tags);for(let d=0,u=i.length;d${m(_)}`)}e.push("
                      ")}else e.push("");e.push('
                        ');let g=Z(a.steps);for(let i=0,d=g.length;i${m(u.keyword)} ${m(u.text)}`)}e.push("
                      ")}e.push("")}else e.push("");e.push("")})}function Xn(t,n){t.component(e=>{let{section:r}=n;if(e.push(`
                      ${m(r.kind)}

                      ${m(r.name)} #

                      ${m(r.visibility)}
                      ${m(r.fqn)} `),r.summary?(e.push(""),e.push(`

                      ${m(r.summary)}

                      `)):e.push(""),e.push(" "),r.extended?(e.push(""),e.push(`

                      ${m(r.extended)}

                      `)):e.push(""),e.push(" "),r.tags.length){e.push(""),e.push('
                      ');let l=Z(r.tags);for(let s=0,a=l.length;s${m(g)}`)}e.push("
                      ")}else e.push("");e.push(" "),Sn(e,{groups:r.relationships}),e.push(" "),kn(e,{scenarios:r.scenarios}),e.push(" ");let o=Z(r.diagrams);for(let l=0,s=o.length;l
                      ")})}function Ln(t,n){t.component(e=>{let{page:r}=n;e.push(`
                      Module

                      ${m(r.name)}

                      `);let o=Z(r.sections);for(let l=0,s=o.length;l")})}V();function Nn(t,n){t.component(e=>{let{page:r}=n;e.push(`
                      Documentation

                      ${m(r.title)}

                      ${Fn(r.html)}
                      `)})}V();function Wn(t){t.push('
                      Generated by pds doc.
                      ')}function To(t){Ii(t),xi(t),Ci(t),vi(t)}function vi(t){let n=location.pathname.split("/").pop();n&&t.querySelectorAll(".docs-link").forEach(e=>{e.getAttribute("href").split("/").pop().split("#")[0]===n&&e.classList.add("is-active")})}function Ii(t){t.querySelectorAll(".tree .toggle").forEach(n=>{n.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation();let r=n.closest("li");r&&r.classList.toggle("collapsed")})})}function xi(t){let n=t.querySelector(".search input"),e=t.querySelector(".tree");if(!n||!e)return;let r=document.createElement("li");r.className="no-results",r.textContent="No matches",r.hidden=!0,e.appendChild(r),n.addEventListener("input",()=>{let o=n.value.trim().toLowerCase(),l=yi(e,o);r.hidden=l||o===""})}function yi(t,n){if(n==="")return t.querySelectorAll("li").forEach(r=>r.classList.remove("hidden")),!0;let e=!1;return t.querySelectorAll(":scope > li").forEach(r=>{Ho(r,n,!1)&&(e=!0)}),e}function Ho(t,n,e){let r=(t.dataset.search||"").toLowerCase(),o=e||r.indexOf(n)!==-1,l=!1;t.querySelectorAll(":scope > ul.children > li").forEach(a=>{Ho(a,n,o)&&(l=!0)});let s=o||l;return t.classList.toggle("hidden",!s),s&&t.classList.remove("collapsed"),s}function Ci(t){function n(){let e=decodeURIComponent(location.hash.replace(/^#/,""));if(t.querySelectorAll(".tree .node-link.is-active").forEach(o=>{o.classList.remove("is-active")}),!e)return;let r=t.querySelector('.tree a[href$="#'+Fi(e)+'"]');if(r){r.classList.add("is-active");let o=r.closest("li");for(;o;){o.classList.remove("collapsed");let l=o.parentElement;o=l?l.closest("li"):null}}}window.addEventListener("hashchange",n),n()}function Fi(t){return window.CSS&&window.CSS.escape?window.CSS.escape(t):t.replace(/[^a-zA-Z0-9_-]/g,"\\$&")}function Rn(t,n){t.component(e=>{let{site:r,docGroups:o=[],sidebar:l,page:s}=n;U(()=>To(document)),e.push('
                      '),Qn(e,{site:r,docGroups:o,sidebar:l}),e.push('
                      '),s.kind==="index"?(e.push(""),En(e,{page:s})):s.kind==="doc"?(e.push(""),Nn(e,{page:s})):(e.push(""),Ln(e,{page:s})),e.push(" "),Wn(e,{}),e.push("
                      ")})}function Bi(t){let n=JSON.parse(t),{head:e,body:r}=wn(Rn,{props:n});return JSON.stringify({head:e,body:r})}return Po(wi);})(); diff --git a/crates/pseudoscript-doc/src/assets/style.css b/crates/pseudoscript-doc/src/assets/style.css index 3f2e92d..a3e2815 100644 --- a/crates/pseudoscript-doc/src/assets/style.css +++ b/crates/pseudoscript-doc/src/assets/style.css @@ -1487,5 +1487,16 @@ code, transition-duration: 0.01ms !important; } } +:root { + --seq-ok: #2ec5ad; + --seq-err: #ff6a5e; +} +.svelte-flow__node.seq-shell { + background: transparent; + border: 0; + box-shadow: none; + padding: 0; + pointer-events: none; +} -.transparent.svelte-1wg91mu{background:transparent}.a11y-hidden.svelte-13pq11u{display:none}.a11y-live-msg.svelte-13pq11u{position:absolute;width:1px;height:1px;margin:-1px;border:0;padding:0;overflow:hidden;clip:rect(0px,0px,0px,0px);clip-path:inset(100%)}.svelte-flow__selection.svelte-1vr3gfi{position:absolute;top:0;left:0}.svelte-flow__selection-wrapper.svelte-sf2y5e{position:absolute;top:0;left:0;z-index:2000;pointer-events:all}.svelte-flow__selection-wrapper.svelte-sf2y5e:focus,.svelte-flow__selection-wrapper.svelte-sf2y5e:focus-visible{outline:none}.svelte-flow.svelte-mkap6j{width:100%;height:100%;overflow:hidden;position:relative;z-index:0;background-color:var(--background-color, var(--background-color-default))}:root{--background-color-default: #fff;--background-pattern-color-default: #ddd;--minimap-mask-color-default: rgb(240, 240, 240, .6);--minimap-mask-stroke-color-default: none;--minimap-mask-stroke-width-default: 1;--controls-button-background-color-default: #fefefe;--controls-button-background-color-hover-default: #f4f4f4;--controls-button-color-default: inherit;--controls-button-color-hover-default: inherit;--controls-button-border-color-default: #eee}.timeline.svelte-1kd9vyo{display:flex;flex-direction:column;height:100%;min-height:0}.flow-head.svelte-1kd9vyo{display:flex;align-items:center;gap:1rem;padding:.7rem 1rem;border-bottom:1px solid var(--line);background:var(--surface)}.title.svelte-1kd9vyo{display:flex;align-items:baseline;gap:.5rem;flex:none}.title.svelte-1kd9vyo .kicker:where(.svelte-1kd9vyo){font-family:var(--font-mono);font-size:.56rem;letter-spacing:.22em;text-transform:uppercase;color:var(--ink-faint)}.title.svelte-1kd9vyo .name:where(.svelte-1kd9vyo){font-family:var(--font-display);font-weight:700;font-size:1rem;color:var(--ink)}.narration.svelte-1kd9vyo{display:flex;align-items:center;gap:.4rem;min-width:0;overflow:hidden;font-family:var(--font-mono);font-size:.78rem}.narration.svelte-1kd9vyo .chip:where(.svelte-1kd9vyo){padding:.1rem .45rem;border-radius:5px;color:var(--ink);background:var(--surface-3);border-left:2px solid var(--k, var(--ink-faint));white-space:nowrap}.narration.svelte-1kd9vyo .chip.person:where(.svelte-1kd9vyo){--k: var(--k-person)}.narration.svelte-1kd9vyo .chip.system:where(.svelte-1kd9vyo){--k: var(--k-system)}.narration.svelte-1kd9vyo .chip.container:where(.svelte-1kd9vyo){--k: var(--k-container)}.narration.svelte-1kd9vyo .chip.component:where(.svelte-1kd9vyo){--k: var(--k-component)}.narration.svelte-1kd9vyo .chip.data:where(.svelte-1kd9vyo){--k: var(--k-data)}.narration.svelte-1kd9vyo .chip.callable:where(.svelte-1kd9vyo){--k: var(--k-callable)}.narration.svelte-1kd9vyo .arrow:where(.svelte-1kd9vyo){color:var(--accent)}.narration.svelte-1kd9vyo .method:where(.svelte-1kd9vyo){color:var(--ink-soft)}.narration.svelte-1kd9vyo .frame:where(.svelte-1kd9vyo){margin-left:.3rem;padding:.05rem .4rem;border:1px dashed var(--line-strong);border-radius:4px;color:var(--ink-faint);font-size:.7rem}.narration.svelte-1kd9vyo .muted:where(.svelte-1kd9vyo){color:var(--ink-faint)}.flow.svelte-1kd9vyo{flex:1;min-height:0}.transport.svelte-1kd9vyo{display:flex;align-items:center;gap:.7rem;padding:.55rem 1rem;border-top:1px solid var(--line);background:var(--surface)}.transport.svelte-1kd9vyo .ctrl:where(.svelte-1kd9vyo),.transport.svelte-1kd9vyo .play:where(.svelte-1kd9vyo){display:grid;place-items:center;border:1px solid var(--line-strong);background:var(--surface-2);color:var(--ink-soft);border-radius:6px}.transport.svelte-1kd9vyo .ctrl:where(.svelte-1kd9vyo){width:1.8rem;height:1.8rem;font-size:.7rem}.transport.svelte-1kd9vyo .ctrl:where(.svelte-1kd9vyo):disabled{opacity:.35;cursor:not-allowed}.transport.svelte-1kd9vyo .ctrl:where(.svelte-1kd9vyo):hover:not(:disabled){border-color:var(--accent);color:var(--ink)}.transport.svelte-1kd9vyo .play:where(.svelte-1kd9vyo){width:2.1rem;height:2.1rem;font-size:.75rem;color:var(--accent-ink);background:var(--accent);border-color:var(--accent)}.transport.svelte-1kd9vyo .play:where(.svelte-1kd9vyo):hover{background:var(--accent-hi)}.transport.svelte-1kd9vyo .scrub:where(.svelte-1kd9vyo){flex:1;accent-color:var(--accent);cursor:pointer}.transport.svelte-1kd9vyo .count:where(.svelte-1kd9vyo){flex:none;font-family:var(--font-mono);font-size:.72rem;color:var(--ink-faint);min-width:3rem;text-align:right}.doc-prose.svelte-exuwic{max-width:var(--measure, 72ch);color:var(--ink);line-height:1.7;font-size:.975rem}.doc-prose.svelte-exuwic h1,.doc-prose.svelte-exuwic h2,.doc-prose.svelte-exuwic h3,.doc-prose.svelte-exuwic h4{font-family:var(--font-display);color:var(--ink);line-height:1.25;margin:2em 0 .6em;scroll-margin-top:1.5rem}.doc-prose.svelte-exuwic h1{font-size:1.6rem}.doc-prose.svelte-exuwic h2{font-size:1.3rem;border-bottom:1px solid var(--line);padding-bottom:.3em}.doc-prose.svelte-exuwic h3{font-size:1.1rem}.doc-prose.svelte-exuwic p,.doc-prose.svelte-exuwic ul,.doc-prose.svelte-exuwic ol,.doc-prose.svelte-exuwic blockquote,.doc-prose.svelte-exuwic table{margin:0 0 1em}.doc-prose.svelte-exuwic ul,.doc-prose.svelte-exuwic ol{padding-left:1.4em}.doc-prose.svelte-exuwic li{margin:.3em 0}.doc-prose.svelte-exuwic a{color:var(--accent);text-decoration:none}.doc-prose.svelte-exuwic a:hover{text-decoration:underline}.doc-prose.svelte-exuwic code{font-family:var(--font-mono);font-size:.85em;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--radius-sm);padding:.1em .35em}.doc-prose.svelte-exuwic pre{background:var(--surface-2);border:1px solid var(--line);border-radius:var(--radius);padding:.9em 1.1em;overflow-x:auto;margin:0 0 1.2em}.doc-prose.svelte-exuwic pre code{background:none;border:none;padding:0;font-size:.85rem}.doc-prose.svelte-exuwic blockquote{border-left:3px solid var(--accent);background:var(--accent-soft);padding:.4em 1em;color:var(--ink-soft)}.doc-prose.svelte-exuwic blockquote>:last-child{margin-bottom:0}.doc-prose.svelte-exuwic .callout{--callout: var(--accent);border-left:3px solid var(--callout);background:color-mix(in srgb,var(--callout) 9%,transparent);border-radius:var(--radius-sm);padding:.6em 1em;margin:0 0 1em}.doc-prose.svelte-exuwic .callout-note{--callout: var(--k-person)}.doc-prose.svelte-exuwic .callout-tip{--callout: var(--k-container)}.doc-prose.svelte-exuwic .callout-important{--callout: var(--k-data)}.doc-prose.svelte-exuwic .callout-warning{--callout: var(--k-component)}.doc-prose.svelte-exuwic .callout-caution{--callout: var(--k-system)}.doc-prose.svelte-exuwic .callout-title{margin:0 0 .3em;color:var(--callout);font-weight:700;font-size:.8em;text-transform:uppercase;letter-spacing:.05em}.doc-prose.svelte-exuwic .callout>:last-child{margin-bottom:0}.doc-prose.svelte-exuwic table{border-collapse:collapse;width:100%;font-size:.9rem}.doc-prose.svelte-exuwic th,.doc-prose.svelte-exuwic td{border:1px solid var(--line);padding:.5em .7em;text-align:left}.doc-prose.svelte-exuwic th{background:var(--surface-2);font-weight:600}.doc-prose.svelte-exuwic hr{border:none;border-top:1px solid var(--line);margin:2em 0}.doc-prose.svelte-exuwic img{max-width:100%;border-radius:var(--radius-sm)} +.transparent.svelte-1wg91mu{background:transparent}.a11y-hidden.svelte-13pq11u{display:none}.a11y-live-msg.svelte-13pq11u{position:absolute;width:1px;height:1px;margin:-1px;border:0;padding:0;overflow:hidden;clip:rect(0px,0px,0px,0px);clip-path:inset(100%)}.svelte-flow__selection.svelte-1vr3gfi{position:absolute;top:0;left:0}.svelte-flow__selection-wrapper.svelte-sf2y5e{position:absolute;top:0;left:0;z-index:2000;pointer-events:all}.svelte-flow__selection-wrapper.svelte-sf2y5e:focus,.svelte-flow__selection-wrapper.svelte-sf2y5e:focus-visible{outline:none}.svelte-flow.svelte-mkap6j{width:100%;height:100%;overflow:hidden;position:relative;z-index:0;background-color:var(--background-color, var(--background-color-default))}:root{--background-color-default: #fff;--background-pattern-color-default: #ddd;--minimap-mask-color-default: rgb(240, 240, 240, .6);--minimap-mask-stroke-color-default: none;--minimap-mask-stroke-width-default: 1;--controls-button-background-color-default: #fefefe;--controls-button-background-color-hover-default: #f4f4f4;--controls-button-color-default: inherit;--controls-button-color-hover-default: inherit;--controls-button-border-color-default: #eee}.seq-life.svelte-jnt8ke{position:relative;width:100%;height:100%;background:transparent;pointer-events:none}.seq-card.svelte-jnt8ke{position:absolute;display:flex;flex-direction:column;justify-content:center;gap:.15rem;padding:0 .7rem;overflow:hidden;background:var(--surface-2);border:1px solid var(--line-strong);border-left:3px solid var(--k, var(--ink-faint));border-radius:var(--radius-sm);box-shadow:var(--shadow-md)}.seq-card.interactive.svelte-jnt8ke{pointer-events:auto;cursor:pointer}.seq-card.interactive.svelte-jnt8ke:hover{border-color:var(--accent)}.seq-card.person.svelte-jnt8ke{--k: var(--k-person)}.seq-card.system.svelte-jnt8ke{--k: var(--k-system)}.seq-card.container.svelte-jnt8ke{--k: var(--k-container)}.seq-card.component.svelte-jnt8ke{--k: var(--k-component)}.seq-card.data.svelte-jnt8ke{--k: var(--k-data)}.seq-card.callable.svelte-jnt8ke{--k: var(--k-callable)}.seq-card.initiator.svelte-jnt8ke{--k: var(--ink-faint)}.seq-card.initiator.svelte-jnt8ke .seq-kind:where(.svelte-jnt8ke){font-style:italic}.seq-kind.svelte-jnt8ke{font-family:var(--font-mono);font-size:.52rem;font-weight:600;letter-spacing:.2em;text-transform:uppercase;color:var(--k, var(--ink-faint))}.seq-name.svelte-jnt8ke{font-family:var(--font-mono);font-size:.82rem;font-weight:600;color:var(--ink);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.seq-overlay.svelte-jnt8ke{position:absolute;inset:0;overflow:visible}.seq-lifeline.svelte-jnt8ke{stroke:var(--line-strong);stroke-dasharray:2 4}.seq-act.svelte-jnt8ke{fill:var(--surface-3);stroke:var(--line-strong)}.seq-act-owner.svelte-jnt8ke{fill:color-mix(in srgb,var(--accent) 18%,transparent);stroke:color-mix(in srgb,var(--accent) 55%,transparent)}.seq-frag.svelte-c5cldi{width:100%;height:100%;border:1px solid var(--line-strong);border-radius:4px;background:color-mix(in srgb,var(--ink) 2%,transparent);pointer-events:none}.seq-frag-tab.svelte-c5cldi{position:absolute;top:0;left:0;padding:.05rem .7rem .1rem .4rem;font-family:var(--font-mono);font-size:11px;font-weight:700;color:var(--ink);background:var(--line-strong);clip-path:polygon(0 0,100% 0,calc(100% - 8px) 100%,0 100%)}.seq-frag-guard.svelte-c5cldi{position:absolute;top:.1rem;left:3.4rem;font-family:var(--font-mono);font-size:11px;color:var(--ink-faint)}.seq-frag-divider.svelte-c5cldi{position:absolute;left:0;right:0;border-top:1px dashed var(--line-strong)}.seq-frag-else.svelte-c5cldi{position:absolute;left:.5rem;margin-top:.15rem;font-family:var(--font-mono);font-size:11px;font-weight:700;color:var(--ink-faint)}.seq-messages.svelte-6084xu{position:absolute;inset:0;overflow:visible;pointer-events:none}.seq-hit.svelte-6084xu{pointer-events:auto;cursor:pointer}.seq-hit.svelte-6084xu:hover{fill:var(--accent)}.seq-type-link.svelte-6084xu{pointer-events:auto;cursor:pointer}.seq-type-link.svelte-6084xu:hover{fill:var(--accent);text-decoration:underline}.seq-call-line.svelte-6084xu{stroke:var(--ink);stroke-width:1.4}.seq-call-head.svelte-6084xu{fill:var(--ink)}.seq-ret-line.svelte-6084xu{stroke-width:1.3;stroke-dasharray:5 3}.seq-ret-head.svelte-6084xu{fill:none;stroke-width:1.3}.seq-pill.svelte-6084xu{fill:var(--surface);fill-opacity:.92}.seq-call-text.svelte-6084xu{fill:var(--ink);font-family:var(--font-mono);font-size:12.5px}.seq-ret-text.svelte-6084xu{font-family:var(--font-mono);font-size:12.5px}.seq-type.svelte-6084xu{fill:var(--ink-faint)}.seq-self.svelte-6084xu,.seq-self-head.svelte-6084xu{stroke:var(--ink-soft);stroke-width:1.4}.seq-label.svelte-6084xu{fill:var(--ink-soft);font-family:var(--font-mono);font-size:11px}.seq-call-dot.svelte-6084xu{fill:var(--accent)}.seq-call-num.svelte-6084xu{fill:var(--accent-ink);font-family:var(--font-mono);font-size:10px;font-weight:700}.timeline.svelte-1kd9vyo{display:flex;flex-direction:column;height:100%;min-height:0}.flow-head.svelte-1kd9vyo{display:flex;align-items:center;gap:1rem;padding:.7rem 1rem;border-bottom:1px solid var(--line);background:var(--surface)}.title.svelte-1kd9vyo{display:flex;align-items:baseline;gap:.5rem;flex:none}.title.svelte-1kd9vyo .kicker:where(.svelte-1kd9vyo){font-family:var(--font-mono);font-size:.56rem;letter-spacing:.22em;text-transform:uppercase;color:var(--ink-faint)}.title.svelte-1kd9vyo .name:where(.svelte-1kd9vyo){font-family:var(--font-display);font-weight:700;font-size:1rem;color:var(--ink)}.hint.svelte-1kd9vyo{margin-left:auto;font-family:var(--font-mono);font-size:.62rem;letter-spacing:.04em;color:var(--ink-faint)}.flow.svelte-1kd9vyo{flex:1;min-height:0}.doc-prose.svelte-exuwic{max-width:var(--measure, 72ch);color:var(--ink);line-height:1.7;font-size:.975rem}.doc-prose.svelte-exuwic h1,.doc-prose.svelte-exuwic h2,.doc-prose.svelte-exuwic h3,.doc-prose.svelte-exuwic h4{font-family:var(--font-display);color:var(--ink);line-height:1.25;margin:2em 0 .6em;scroll-margin-top:1.5rem}.doc-prose.svelte-exuwic h1{font-size:1.6rem}.doc-prose.svelte-exuwic h2{font-size:1.3rem;border-bottom:1px solid var(--line);padding-bottom:.3em}.doc-prose.svelte-exuwic h3{font-size:1.1rem}.doc-prose.svelte-exuwic p,.doc-prose.svelte-exuwic ul,.doc-prose.svelte-exuwic ol,.doc-prose.svelte-exuwic blockquote,.doc-prose.svelte-exuwic table{margin:0 0 1em}.doc-prose.svelte-exuwic ul,.doc-prose.svelte-exuwic ol{padding-left:1.4em}.doc-prose.svelte-exuwic li{margin:.3em 0}.doc-prose.svelte-exuwic a{color:var(--accent);text-decoration:none}.doc-prose.svelte-exuwic a:hover{text-decoration:underline}.doc-prose.svelte-exuwic code{font-family:var(--font-mono);font-size:.85em;background:var(--surface-2);border:1px solid var(--line);border-radius:var(--radius-sm);padding:.1em .35em}.doc-prose.svelte-exuwic pre{background:var(--surface-2);border:1px solid var(--line);border-radius:var(--radius);padding:.9em 1.1em;overflow-x:auto;margin:0 0 1.2em}.doc-prose.svelte-exuwic pre code{background:none;border:none;padding:0;font-size:.85rem}.doc-prose.svelte-exuwic blockquote{border-left:3px solid var(--accent);background:var(--accent-soft);padding:.4em 1em;color:var(--ink-soft)}.doc-prose.svelte-exuwic blockquote>:last-child{margin-bottom:0}.doc-prose.svelte-exuwic .callout{--callout: var(--accent);border-left:3px solid var(--callout);background:color-mix(in srgb,var(--callout) 9%,transparent);border-radius:var(--radius-sm);padding:.6em 1em;margin:0 0 1em}.doc-prose.svelte-exuwic .callout-note{--callout: var(--k-person)}.doc-prose.svelte-exuwic .callout-tip{--callout: var(--k-container)}.doc-prose.svelte-exuwic .callout-important{--callout: var(--k-data)}.doc-prose.svelte-exuwic .callout-warning{--callout: var(--k-component)}.doc-prose.svelte-exuwic .callout-caution{--callout: var(--k-system)}.doc-prose.svelte-exuwic .callout-title{margin:0 0 .3em;color:var(--callout);font-weight:700;font-size:.8em;text-transform:uppercase;letter-spacing:.05em}.doc-prose.svelte-exuwic .callout>:last-child{margin-bottom:0}.doc-prose.svelte-exuwic table{border-collapse:collapse;width:100%;font-size:.9rem}.doc-prose.svelte-exuwic th,.doc-prose.svelte-exuwic td{border:1px solid var(--line);padding:.5em .7em;text-align:left}.doc-prose.svelte-exuwic th{background:var(--surface-2);font-weight:600}.doc-prose.svelte-exuwic hr{border:none;border-top:1px solid var(--line);margin:2em 0}.doc-prose.svelte-exuwic img{max-width:100%;border-radius:var(--radius-sm)} diff --git a/crates/pseudoscript-doc/src/props.rs b/crates/pseudoscript-doc/src/props.rs index 399761a..22a228f 100644 --- a/crates/pseudoscript-doc/src/props.rs +++ b/crates/pseudoscript-doc/src/props.rs @@ -9,6 +9,7 @@ //! out and animate them. use pseudoscript_emit::{C4Scene, SequenceScene}; +use pseudoscript_layout::sequence::Layout; use serde::{Deserialize, Serialize}; /// The complete props for one page. Serialised to JSON, passed to the SSR @@ -239,12 +240,16 @@ pub(crate) enum Diagram { /// The laid-out C4 scene (nodes + edges). scene: C4Scene, }, - /// A sequence view, animated by the timeline component. + /// A sequence view, drawn as the IDE's lifeline/message diagram. Sequence { /// The figure caption. caption: String, /// The sequence scene (participants + ordered items). scene: SequenceScene, + /// The positioned layout (lifelines, activations, fragments, messages) + /// from `pseudoscript-layout` — the same geometry the web IDE renders, + /// so the figure needs no client-side layout engine. + layout: Layout, }, /// A view that could not be projected (e.g. an empty boundary). Empty { diff --git a/crates/pseudoscript-doc/src/render.rs b/crates/pseudoscript-doc/src/render.rs index 23baceb..e34717e 100644 --- a/crates/pseudoscript-doc/src/render.rs +++ b/crates/pseudoscript-doc/src/render.rs @@ -7,7 +7,7 @@ use crate::config::{DocConfig, DocPage}; use crate::nav::{callables_of, child_nodes, module_top_level, sorted_modules}; use crate::url::{UrlMap, anchor, doc_page_path, module_page_path}; -use pseudoscript_emit::{Scene, View, project}; +use pseudoscript_emit::{Scene, View, layout_sequence_scene, project}; use pseudoscript_model::{Edge, EdgeKind, Graph, GraphNode, NodeKind, Visibility}; use pulldown_cmark::{BlockQuoteKind, Event, Options, Parser, Tag, TagEnd, html}; @@ -349,6 +349,7 @@ fn build_diagram(graph: &Graph, view: View, eyebrow: &str, caption: &str) -> Dia }, Ok(Scene::Sequence(scene)) => Diagram::Sequence { caption: caption.to_owned(), + layout: layout_sequence_scene(&scene), scene, }, Err(_) => Diagram::Empty { diff --git a/crates/pseudoscript-doc/tests/site.rs b/crates/pseudoscript-doc/tests/site.rs index cd1d683..db75cf3 100644 --- a/crates/pseudoscript-doc/tests/site.rs +++ b/crates/pseudoscript-doc/tests/site.rs @@ -52,7 +52,7 @@ public container Api for Bank { /// #entrypoint #[manual] public Post(posting: Posting): number { - n = Ledger.Append(posting) + n: number = Ledger.Append(posting) return n } } diff --git a/crates/pseudoscript-doc/web/src/lib/Diagram.svelte b/crates/pseudoscript-doc/web/src/lib/Diagram.svelte index 88f6b83..935abbf 100644 --- a/crates/pseudoscript-doc/web/src/lib/Diagram.svelte +++ b/crates/pseudoscript-doc/web/src/lib/Diagram.svelte @@ -10,11 +10,14 @@ onMount(async () => { if (!host || diagram.diagram === "empty") return; const { mount } = await import("svelte"); - const mod = - diagram.diagram === "c4" - ? await import("./C4Flow.svelte") - : await import("./FlowTimeline.svelte"); - mount(mod.default, { target: host, props: { scene: diagram.scene } }); + const isC4 = diagram.diagram === "c4"; + const mod = isC4 ? await import("./C4Flow.svelte") : await import("./FlowTimeline.svelte"); + // The sequence timeline renders the positioned layout from the compiler (the + // same geometry the web IDE draws); C4 lays itself out client-side. + const props = isC4 + ? { scene: diagram.scene } + : { scene: diagram.scene, layout: diagram.layout }; + mount(mod.default, { target: host, props }); }); diff --git a/crates/pseudoscript-doc/web/src/lib/FlowTimeline.svelte b/crates/pseudoscript-doc/web/src/lib/FlowTimeline.svelte index 0f43687..3874d21 100644 --- a/crates/pseudoscript-doc/web/src/lib/FlowTimeline.svelte +++ b/crates/pseudoscript-doc/web/src/lib/FlowTimeline.svelte @@ -1,152 +1,128 @@
                      flow - {leaf(scene.entry)} -
                      -
                      - {#if current} - {leaf(current.from)} - - {leaf(current.to)} - {#if msgLabel(current)}{msgLabel(current)}{/if} - {#if current.frame}{current.frame}{/if} - {:else} - triggered entry point — press play to trace the request - {/if} + {leaf(scene?.entry)}
                      + sequence diagram — scroll to zoom · drag to pan
                      + +
                      - -
                      - - - - - {cursor}/{steps.length} -
                      diff --git a/crates/pseudoscript-doc/web/src/lib/SequenceFragment.svelte b/crates/pseudoscript-doc/web/src/lib/SequenceFragment.svelte new file mode 100644 index 0000000..8ef4b94 --- /dev/null +++ b/crates/pseudoscript-doc/web/src/lib/SequenceFragment.svelte @@ -0,0 +1,64 @@ + + +
                      + {data.kind} + [{data.label}] + {#each data.dividers as d (d.y)} +
                      + [{d.guard || "else"}] + {/each} +
                      + + diff --git a/crates/pseudoscript-doc/web/src/lib/SequenceLifeline.svelte b/crates/pseudoscript-doc/web/src/lib/SequenceLifeline.svelte new file mode 100644 index 0000000..b78fffe --- /dev/null +++ b/crates/pseudoscript-doc/web/src/lib/SequenceLifeline.svelte @@ -0,0 +1,145 @@ + + +
                      +
                      interactive && data.oninfo?.(p.id, e)} + onmouseleave={() => interactive && data.oninfoend?.()} + {onclick} + > + {kindLabel} + {nameLabel} +
                      + + + + + + + {#if act} + + {/if} + +
                      + + diff --git a/crates/pseudoscript-doc/web/src/lib/SequenceMessages.svelte b/crates/pseudoscript-doc/web/src/lib/SequenceMessages.svelte new file mode 100644 index 0000000..ba79994 --- /dev/null +++ b/crates/pseudoscript-doc/web/src/lib/SequenceMessages.svelte @@ -0,0 +1,125 @@ + + + + {#each data.messages as m, i (i)} + {#if m.kind === "call"} + + + {#if m.label} + {@const mx = (m.from_x + m.to_x) / 2} + {@const full = m.label + (m.detail ?? "")} + + data.oninfo?.(callee(m), e)} + onmouseleave={() => data.oninfoend?.()} + onclick={(e) => onLabelClick(m, e)} + >{m.label}{#each typeParts(m.detail) as part, pi (pi)}{#if part.fqn} data.oninfo?.(part.fqn, e)} onmouseleave={() => data.oninfoend?.()} onclick={(e) => onTypeClick(part.fqn, e)}>{part.text}{:else}{part.text}{/if}{/each} + {/if} + + {m.step} + {:else if m.kind === "self"} + {@const lx = m.from_x + 5} + + + data.oninfo?.(callee(m), e)} + onmouseleave={() => data.oninfoend?.()} + onclick={(e) => onLabelClick(m, e)}>{m.label} + + {m.step} + {:else} + {@const r = ret(m.label)} + {@const mx = (m.from_x + m.to_x) / 2} + {@const type = retType(m)} + {@const full = r.text + type} + + + + {r.text}{#each typeParts(type) as part, pi (pi)}{#if part.fqn} data.oninfo?.(part.fqn, e)} onmouseleave={() => data.oninfoend?.()} onclick={(e) => onTypeClick(part.fqn, e)}>{part.text}{:else}{part.text}{/if}{/each} + {/if} + {/each} + + + diff --git a/crates/pseudoscript-doc/web/src/style.css b/crates/pseudoscript-doc/web/src/style.css index c780bae..ec75ece 100644 --- a/crates/pseudoscript-doc/web/src/style.css +++ b/crates/pseudoscript-doc/web/src/style.css @@ -974,3 +974,18 @@ code, transition-duration: 0.01ms !important; } } + +/* Sequence diagram (ported from the web IDE): the lifeline/message timeline. + `--seq-ok`/`--seq-err` colour return arrows; the seq-shell nodes are + transparent projection shells whose SVG paints itself. */ +:root { + --seq-ok: #2ec5ad; + --seq-err: #ff6a5e; +} +.svelte-flow__node.seq-shell { + background: transparent; + border: 0; + box-shadow: none; + padding: 0; + pointer-events: none; +} diff --git a/crates/pseudoscript-emit/src/c4_render.rs b/crates/pseudoscript-emit/src/c4_render.rs index 29dab63..e5ec733 100644 --- a/crates/pseudoscript-emit/src/c4_render.rs +++ b/crates/pseudoscript-emit/src/c4_render.rs @@ -37,20 +37,13 @@ use std::panic::{AssertUnwindSafe, catch_unwind}; use pseudoscript_model::NodeKind; +use crate::render::pal; use crate::scene::{C4EdgeKind, C4Scene, PlacedNode, RoutedEdge}; -// Shared ink-on-paper palette (matches the sequence renderer for a cohesive -// look across the static site's diagrams). -/// Stroke colour for routed edges and arrowheads. -const STROKE: &str = "#2a2f3a"; -/// Card border colour (cool hairline). -const CARD_BORDER: &str = "#c3c8d2"; -/// Card background fill. -const CARD_FILL: &str = "#ffffff"; -/// Title text colour. -const TITLE_FILL: &str = "#2a2f3a"; -/// Description text colour (muted). -const DESC_FILL: &str = "#6b7280"; +// All SVG colours come from the active theme palette (crate::render::pal); the +// hand-written emitters bind their roles as locals at the top of each function. +// The engine-side box/edge styles below feed the layout engine only — the +// `Capture` backend ignores their colours — so they keep harmless literals. /// Margin added around the laid-out extent and inside the document. const MARGIN: f64 = 24.0; /// Font size handed to the layout engine for edge-label sizing. @@ -220,16 +213,20 @@ fn fallback_svg(scene: &C4Scene, boundary: Option<&str>) -> String { let mut out = String::new(); svg_open(&mut out, w.max(pad), h.max(pad)); + #[allow(non_snake_case)] + let (CARD_BORDER, TITLE_FILL, STROKE) = (pal().hairline, pal().ink, pal().ink); + for node in &scene.nodes { if Some(node.fqn.as_str()) != boundary { continue; } let _ = write!( out, - "\ {label}", + boundary_fill = pal().boundary_fill, x = node.rect.x, y = node.rect.y, w = node.rect.w, @@ -282,9 +279,9 @@ fn fallback_svg(scene: &C4Scene, boundary: Option<&str>) -> String { /// needs to size and place a plain rectangle; its fill never reaches the SVG. fn node_style() -> StyleAttr { StyleAttr { - line_color: web_color(CARD_BORDER), + line_color: web_color("#c3c8d2"), line_width: 1, - fill_color: Some(web_color(CARD_FILL)), + fill_color: Some(web_color("#ffffff")), rounded: CARD_RADIUS_PX, font_size: FONT_SIZE, } @@ -299,7 +296,7 @@ fn edge_arrow(edge: &RoutedEdge) -> Arrow { LineStyleKind::Normal }; let look = StyleAttr { - line_color: web_color(STROKE), + line_color: web_color("#2a2f3a"), line_width: 1, fill_color: None, rounded: 0, @@ -564,6 +561,8 @@ fn emit_svg(capture: &Capture, scene: &C4Scene, boundary: Option<&str>) -> Strin svg_open(&mut out, w, h); if let Some((frame_min, frame_max, title)) = &boundary_frame { + #[allow(non_snake_case)] + let (CARD_BORDER, TITLE_FILL) = (pal().hairline, pal().ink); let x = round(frame_min.x); let y = round(frame_min.y); let fw = round(frame_max.x - frame_min.x); @@ -571,9 +570,10 @@ fn emit_svg(capture: &Capture, scene: &C4Scene, boundary: Option<&str>) -> Strin let _ = write!( &mut out, "\ + fill=\"{boundary_fill}\" stroke=\"{CARD_BORDER}\" stroke-dasharray=\"6 5\"/>\ {label}", + boundary_fill = pal().boundary_fill, tx = x + 12, ty = y + 19, label = escape_xml(title), @@ -629,6 +629,9 @@ pub(crate) fn draw_card( title: &str, summary: Option<&str>, ) { + #[allow(non_snake_case)] + let (CARD_FILL, CARD_BORDER, TITLE_FILL, DESC_FILL) = + (pal().card_fill, pal().hairline, pal().ink, pal().muted); let accent = kind_color(kind); let r = CARD_RADIUS; @@ -765,14 +768,17 @@ fn svg_open(out: &mut String, w: i32, h: i32) { w = w, h = h, ); - out.push_str( + let _ = write!( + out, "\ \ + fill=\"{ink}\"/>\ \ - ", + ink = pal().ink, + shadow = pal().shadow, ); } @@ -791,6 +797,8 @@ fn draw_arrow(out: &mut String, arrow: &CapturedArrow) { } else { "" }; + #[allow(non_snake_case)] + let STROKE = pal().ink; let _ = write!( out, "\ + fill=\"{plate}\"/>\ {text}", + plate = pal().edge_plate, rx = lx - plate_w / 2, ry = ly - 8, ty = ly + 4, diff --git a/crates/pseudoscript-emit/src/lib.rs b/crates/pseudoscript-emit/src/lib.rs index 1e1afde..9fe291a 100644 --- a/crates/pseudoscript-emit/src/lib.rs +++ b/crates/pseudoscript-emit/src/lib.rs @@ -41,7 +41,7 @@ mod render; mod scene; pub use project::{EmitError, View, project, project_symbol}; -pub use render::{layout_sequence_scene, render_svg}; +pub use render::{Theme, layout_sequence_scene, render_svg, render_svg_themed}; pub use scene::{ C4EdgeKind, C4Scene, C4View, Frame, FrameKind, Lifeline, Message, MessageKind, PlacedNode, Rect, RoutedEdge, Scene, SeqItem, SequenceScene, diff --git a/crates/pseudoscript-emit/src/render.rs b/crates/pseudoscript-emit/src/render.rs index 4a74cd7..c2ba410 100644 --- a/crates/pseudoscript-emit/src/render.rs +++ b/crates/pseudoscript-emit/src/render.rs @@ -190,13 +190,124 @@ fn kind_token(kind: NodeKind) -> &'static str { // --- SVG rendering ---------------------------------------------------------- -/// Renders a laid-out [`Scene`] to a self-contained SVG document. +/// The colour theme a diagram renders in. `Light` reproduces the original +/// ink-on-paper palette byte-for-byte; `Dark` swaps the structural colours +/// (ink, hairlines, card/boundary fills, plates) for a dark surface while +/// keeping the per-kind accent colours, mirroring the doc site's two modes. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Theme { + Light, + Dark, +} + +/// Every colour the SVG emitters draw with, by role. Two instances exist +/// ([`LIGHT`]/[`DARK`]); the active one is held in a thread-local for the +/// duration of one render so the many emit helpers need no extra argument. +pub(crate) struct Palette { + /// Primary ink: text, lines, the C4 arrowhead. + pub ink: &'static str, + /// Sequence-arrowhead ink (a slightly softer near-black in light mode). + pub arrow_seq: &'static str, + /// Hairlines: card borders and dashed lifelines. + pub hairline: &'static str, + /// Secondary text: descriptions, guards, return markers. + pub muted: &'static str, + /// Combined-fragment frame strokes/tabs. + pub frame: &'static str, + /// The entry/owner accent (activation, step badges). + pub accent: &'static str, + /// Success-return colour (`Ok`/`Some`). + pub ok: &'static str, + /// Error-return colour (`Err`/`None`). + pub err: &'static str, + /// A card's interior fill. + pub card_fill: &'static str, + /// A boundary frame's fill. + pub boundary_fill: &'static str, + /// The card drop-shadow colour. + pub shadow: &'static str, + /// A plain (non-owner) activation bar's fill. + pub act_fill: &'static str, + /// Text drawn on an accent fill (step numbers) — stays light in both themes. + pub on_accent: &'static str, + /// The faint backing pill behind a sequence label. + pub pill: &'static str, + /// The plate behind a C4 edge label (carries its own alpha). + pub edge_plate: &'static str, +} + +/// The original ink-on-paper palette — light output is unchanged from before +/// the theme split, so golden SVGs still match. +pub(crate) static LIGHT: Palette = Palette { + ink: "#2a2f3a", + arrow_seq: "#333", + hairline: "#c3c8d2", + muted: "#6b7280", + frame: "#aab0bd", + accent: "#e8431f", + ok: "#0f9d8a", + err: "#d6432a", + card_fill: "#ffffff", + boundary_fill: "#f6f7fa", + shadow: "#1a1f2a", + act_fill: "#fff", + on_accent: "#fff", + pill: "#fff", + edge_plate: "#ffffffe6", +}; + +/// The dark surface palette: light ink, dark cards/plates, muted hairlines; the +/// per-kind accents (set elsewhere) carry through unchanged. +pub(crate) static DARK: Palette = Palette { + ink: "#d4d7dd", + arrow_seq: "#b7bbc3", + hairline: "#44474e", + muted: "#9a9ea8", + frame: "#565a62", + accent: "#ff5c38", + ok: "#23c2ab", + err: "#f0563b", + card_fill: "#2b2d31", + boundary_fill: "#26282d", + shadow: "#000000", + act_fill: "#3b3e45", + on_accent: "#fff", + pill: "#2b2d31", + edge_plate: "#2b2d31e6", +}; + +thread_local! { + /// The palette in effect for the current render (defaults to light). + static PALETTE: std::cell::Cell<&'static Palette> = const { std::cell::Cell::new(&LIGHT) }; +} + +/// The palette the emit helpers should draw with right now. +pub(crate) fn pal() -> &'static Palette { + PALETTE.with(std::cell::Cell::get) +} + +/// Renders a laid-out [`Scene`] to a self-contained SVG document (light theme). #[must_use] pub fn render_svg(scene: &Scene) -> String { - match scene { + render_svg_themed(scene, Theme::Light) +} + +/// Renders a laid-out [`Scene`] to a self-contained SVG document in `theme`. +/// Sets the thread-local palette for the duration of the render and restores +/// light afterwards, so a default `render_svg` elsewhere is unaffected. +#[must_use] +pub fn render_svg_themed(scene: &Scene, theme: Theme) -> String { + let palette: &'static Palette = match theme { + Theme::Light => &LIGHT, + Theme::Dark => &DARK, + }; + PALETTE.with(|p| p.set(palette)); + let svg = match scene { Scene::C4(c4) => render_c4(c4), Scene::Sequence(seq) => render_sequence(seq), - } + }; + PALETTE.with(|p| p.set(&LIGHT)); + svg } /// SVG document header with a viewBox and an arrowhead marker. @@ -210,23 +321,15 @@ fn svg_open(out: &mut String, w: i32, h: i32) { w = w, h = h, ); - out.push_str( + let _ = write!( + out, "", + fill=\"{}\"/>", + pal().arrow_seq, ); } -// Sequence-diagram palette (ink-on-paper, readable on the doc site's light -// plate in either theme). -const SEQ_INK: &str = "#2a2f3a"; -const SEQ_LINE: &str = "#c3c8d2"; -const SEQ_MUTED: &str = "#6b7280"; -const SEQ_ACCENT: &str = "#e8431f"; -const SEQ_OK: &str = "#0f9d8a"; -const SEQ_ERR: &str = "#d6432a"; -const SEQ_FRAME: &str = "#aab0bd"; - /// Positions a sequence scene with the layout engine, returning absolute /// coordinates a renderer (the static SVG here, or the web-ide) draws verbatim. #[must_use] @@ -235,6 +338,8 @@ pub fn layout_sequence_scene(scene: &SequenceScene) -> sequence::Layout { } fn render_sequence(scene: &SequenceScene) -> String { + #[allow(non_snake_case)] + let (SEQ_INK, SEQ_MUTED, SEQ_LINE) = (pal().ink, pal().muted, pal().hairline); let layout = layout_sequence_scene(scene); let mut out = String::new(); svg_open(&mut out, layout.width, layout.height); @@ -311,9 +416,9 @@ fn render_sequence(scene: &SequenceScene) -> String { /// plain. fn draw_activation(out: &mut String, act: &Activation) { let (fill, fill_op, stroke, stroke_op) = if act.owner { - (SEQ_ACCENT, "0.10", SEQ_ACCENT, "0.5") + (pal().accent, "0.10", pal().accent, "0.5") } else { - ("#fff", "1", SEQ_LINE, "1") + (pal().act_fill, "1", pal().hairline, "1") }; let _ = write!( out, @@ -329,6 +434,8 @@ fn draw_activation(out: &mut String, act: &Activation) { /// the target. /// A call: solid arrow source → target, numbered at its origin. fn draw_call(out: &mut String, msg: &PlacedMessage) { + #[allow(non_snake_case)] + let SEQ_INK = pal().ink; let _ = write!( out, ") { let Some(step) = step else { return }; + #[allow(non_snake_case)] + let SEQ_ACCENT = pal().accent; + let on_accent = pal().on_accent; let _ = write!( out, "\ {step}", + fill=\"{on_accent}\">{step}", cx = lifeline_x - ACT_W / 2 - 12, ty = y + 3, ); @@ -470,16 +584,19 @@ fn seq_label( colour: &str, pill: bool, ) { + #[allow(non_snake_case)] + let SEQ_MUTED = pal().muted; let label = escape_xml(text); let chars = text.chars().count() + detail.chars().count(); if pill && chars > 0 { let w = i32::try_from(chars).unwrap_or(0) * 7 + 12; let _ = write!( out, - "", rx = x - w / 2, ry = y - 12, + fill = pal().pill, ); } let detail_span = if detail.is_empty() { @@ -497,10 +614,10 @@ fn seq_label( /// The colour and display text for a return marker. fn return_style(marker: &str) -> (&'static str, String) { match marker { - "Ok" | "Some" => (SEQ_OK, format!("\u{21a9} {marker}")), - "Err" | "None" => (SEQ_ERR, format!("\u{21a9} {marker}")), - "" => (SEQ_MUTED, "\u{21a9} return".to_owned()), - other => (SEQ_MUTED, format!("\u{21a9} {other}")), + "Ok" | "Some" => (pal().ok, format!("\u{21a9} {marker}")), + "Err" | "None" => (pal().err, format!("\u{21a9} {marker}")), + "" => (pal().muted, "\u{21a9} return".to_owned()), + other => (pal().muted, format!("\u{21a9} {other}")), } } diff --git a/crates/pseudoscript-emit/tests/features/svg.feature b/crates/pseudoscript-emit/tests/features/svg.feature index d18481f..996b619 100644 --- a/crates/pseudoscript-emit/tests/features/svg.feature +++ b/crates/pseudoscript-emit/tests/features/svg.feature @@ -50,7 +50,7 @@ Feature: SVG rendering smoke public container Orders for Shop { #[manual] public Place(order: Order): Result { - r = Inventory.reserve(order) + r: Result = Inventory.reserve(order) return Ok(order) } } diff --git a/crates/pseudoscript-format/src/printer.rs b/crates/pseudoscript-format/src/printer.rs index cd5e96c..ce919cd 100644 --- a/crates/pseudoscript-format/src/printer.rs +++ b/crates/pseudoscript-format/src/printer.rs @@ -386,8 +386,10 @@ impl Printer { fn write_stmt(&mut self, stmt: &Stmt) { match &stmt.kind { - StmtKind::Assign { name, value } => { + StmtKind::Assign { name, ty, value } => { self.push(&name.name); + self.push(": "); + self.write_type(ty); self.push(" = "); self.write_expr(value); self.newline(); diff --git a/crates/pseudoscript-format/tests/features/golden.feature b/crates/pseudoscript-format/tests/features/golden.feature index 839993c..f6761b3 100644 --- a/crates/pseudoscript-format/tests/features/golden.feature +++ b/crates/pseudoscript-format/tests/features/golden.feature @@ -25,9 +25,9 @@ Feature: Golden canonical outputs Then the result equals "public component Repo for S {\n fetch(id: number): Result;\n}\n" Scenario: nested body, control flow, from-composition, and postfix chain - Given the source "public container M for B {\nrun(s:Source):Result{\ntree=Ast from {s.text,s.path}\nx=Repo.fetch(id).value.owner\nfor(item in xs){self.handle(item)}\nreturn Ok(tree)\n}\n}" + Given the source "public container M for B {\nrun(s:Source):Result{\ntree:Ast=Ast from {s.text,s.path}\nx:string=Repo.fetch(id).value.owner\nfor(item in xs){self.handle(item)}\nreturn Ok(tree)\n}\n}" When I format it - Then the result equals "public container M for B {\n run(s: Source): Result {\n tree = Ast from { s.text, s.path }\n x = Repo.fetch(id).value.owner\n for (item in xs) {\n self.handle(item)\n }\n return Ok(tree)\n }\n}\n" + Then the result equals "public container M for B {\n run(s: Source): Result {\n tree: Ast = Ast from { s.text, s.path }\n x: string = Repo.fetch(id).value.owner\n for (item in xs) {\n self.handle(item)\n }\n return Ok(tree)\n }\n}\n" Scenario: a feature reformats to one step per line Given the source "feature Open for Bank{given \"a\"\nwhen \"b\"\nthen \"c\"}" diff --git a/crates/pseudoscript-format/tests/features/idempotency.feature b/crates/pseudoscript-format/tests/features/idempotency.feature index ff1db99..1e8ec47 100644 --- a/crates/pseudoscript-format/tests/features/idempotency.feature +++ b/crates/pseudoscript-format/tests/features/idempotency.feature @@ -17,7 +17,7 @@ Feature: Formatting is idempotent Then formatting is idempotent Scenario: a disclosed container with control flow - Given the source "public container M for B {\n public Get(id:number):Result{\nr=Repo.fetch(id)\nif(r.isErr){return Err(r.error)}\nreturn Ok(r.value)\n}\n}" + Given the source "public container M for B {\n public Get(id:number):Result{\nr:Result=Repo.fetch(id)\nif(r.isErr){return Err(r.error)}\nreturn Ok(r.value)\n}\n}" Then formatting is idempotent Scenario: a union with inline records diff --git a/crates/pseudoscript-format/tests/features/semantics.feature b/crates/pseudoscript-format/tests/features/semantics.feature index 53d942f..52d6818 100644 --- a/crates/pseudoscript-format/tests/features/semantics.feature +++ b/crates/pseudoscript-format/tests/features/semantics.feature @@ -11,13 +11,13 @@ Feature: Formatting preserves semantics And the result preserves the meaningful tokens Scenario: callable with control flow - Given the source "public container M for B {\npublic Get(id:number):Result{\nr=Repo.fetch(id)\nif(r.isErr){return Err(r.error)}\nreturn Ok(r.value)\n}\n}" + Given the source "public container M for B {\npublic Get(id:number):Result{\nr:Result=Repo.fetch(id)\nif(r.isErr){return Err(r.error)}\nreturn Ok(r.value)\n}\n}" When I format it Then the result re-parses without errors And the result preserves the meaningful tokens Scenario: from-composition and postfix chain - Given the source "public container M for B {\nrun(s:Source):Result{\ntree=Ast from {s.text,s.path}\nx=Repo.fetch(id).value.owner\nreturn Ok(tree)\n}\n}" + Given the source "public container M for B {\nrun(s:Source):Result{\ntree:Ast=Ast from {s.text,s.path}\nx:string=Repo.fetch(id).value.owner\nreturn Ok(tree)\n}\n}" When I format it Then the result re-parses without errors And the result preserves the meaningful tokens diff --git a/crates/pseudoscript-format/tests/format.rs b/crates/pseudoscript-format/tests/format.rs index 749d550..92956b5 100644 --- a/crates/pseudoscript-format/tests/format.rs +++ b/crates/pseudoscript-format/tests/format.rs @@ -42,12 +42,12 @@ public container Web for Shop { #[http("POST /checkout")] public checkout(cart: Sku[]): Result { for (item in cart) { - line = Warehouse::Pricing.price(item) + line: Result = Warehouse::Pricing.price(item) if (line.isErr) { return Err(line.error) } } - r = self.finalize(cart) + r: Result = self.finalize(cart) return Ok(r.value) } @@ -58,8 +58,8 @@ public container Warehouse for Shop; component Pricing for Warehouse { price(item: Sku): Result { - base = Catalog.lookup(item).value - receipt = Receipt from { base } + base: Receipt = Catalog.lookup(item).value + receipt: Receipt = Receipt from { base } return Ok(receipt) } } diff --git a/crates/pseudoscript-lsp-core/Cargo.toml b/crates/pseudoscript-lsp-core/Cargo.toml new file mode 100644 index 0000000..04047e3 --- /dev/null +++ b/crates/pseudoscript-lsp-core/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "pseudoscript-lsp-core" +version.workspace = true +edition.workspace = true + +[lints] +workspace = true + +[lib] +name = "pseudoscript_lsp_core" +path = "src/lib.rs" + +# The transport-neutral LSP API: `text + position -> lsp_types value`. Depends on +# the standalone `lsp-types` (pure serde, WASM-safe) — NOT tower-lsp — so both +# the stdio server (pseudoscript-lsp) and the WASM bridge (pseudoscript-wasm) +# share one implementation. lsp-types is pinned to the version tower-lsp 0.20 +# re-exports, so the server passes these types through without conversion. +[dependencies] +pseudoscript-syntax = { path = "../pseudoscript-syntax" } +pseudoscript-model = { path = "../pseudoscript-model" } +pseudoscript-format = { path = "../pseudoscript-format" } +lsp-types = "=0.94.1" diff --git a/crates/pseudoscript-lsp/src/analysis.rs b/crates/pseudoscript-lsp-core/src/analysis.rs similarity index 93% rename from crates/pseudoscript-lsp/src/analysis.rs rename to crates/pseudoscript-lsp-core/src/analysis.rs index 65ff25d..daac6b8 100644 --- a/crates/pseudoscript-lsp/src/analysis.rs +++ b/crates/pseudoscript-lsp-core/src/analysis.rs @@ -1,16 +1,16 @@ //! Pure language logic, free of any server or I/O. //! //! Each function maps source text (and, for cursor features, an LSP position) -//! to an LSP value. The [`crate::server`] layer only owns the document store and +//! to an LSP value. The the server layer only owns the document store and //! the protocol plumbing; everything testable lives here. -use pseudoscript_format::format; -use pseudoscript_model::{Workspace, check}; -use pseudoscript_syntax::{LineIndex, Span, TokenKind, tokenize}; -use tower_lsp::lsp_types::{ +use lsp_types::{ Diagnostic, DiagnosticSeverity, Hover, HoverContents, InlayHint, InlayHintKind, InlayHintLabel, MarkupContent, MarkupKind, Position, TextEdit, }; +use pseudoscript_format::format; +use pseudoscript_model::{Workspace, check}; +use pseudoscript_syntax::{LineIndex, Span, TokenKind, tokenize}; use crate::convert::{full_range, offset_to_position, position_to_offset, span_to_range}; use crate::resolve::resolve_at; @@ -28,7 +28,7 @@ pub fn renameable( from_fqn: &str, src: &str, position: Position, -) -> Option { +) -> Option { let offset = position_to_offset(src, position); let hit = resolve_at(ws, from_fqn, src, offset)?; let index = LineIndex::new(src); @@ -80,7 +80,7 @@ pub fn hover(ws: &Workspace, from_fqn: &str, src: &str, position: Position) -> O // Fallback: a local binding shows its inferred type (`tokens: Token[]`). let (name, span) = ident_at(src, offset)?; - let local = crate::infer::binding_type_at(ws, from_fqn, &name)?; + let local = pseudoscript_model::infer::binding_type_at(ws, from_fqn, &name)?; Some(markup_hover( format!("**`{name}: {}`**\n\nlocal binding", local.ty), span_to_range(src, &index, span), @@ -91,7 +91,7 @@ pub fn hover(ws: &Workspace, from_fqn: &str, src: &str, position: Position) -> O #[must_use] pub fn inlay_hints(ws: &Workspace, from_fqn: &str, src: &str) -> Vec { let index = LineIndex::new(src); - crate::infer::local_types(ws, from_fqn) + pseudoscript_model::infer::local_types(ws, from_fqn) .into_iter() .map(|local| InlayHint { position: offset_to_position(src, &index, local.name_span.end), @@ -107,7 +107,7 @@ pub fn inlay_hints(ws: &Workspace, from_fqn: &str, src: &str) -> Vec } /// A Markdown hover with a range. -fn markup_hover(value: String, range: tower_lsp::lsp_types::Range) -> Hover { +fn markup_hover(value: String, range: lsp_types::Range) -> Hover { Hover { contents: HoverContents::Markup(MarkupContent { kind: MarkupKind::Markdown, @@ -154,10 +154,7 @@ pub fn lsp_diagnostics(src: &str, diags: &[pseudoscript_syntax::Diagnostic]) -> .map(|d| Diagnostic { range: span_to_range(src, &index, d.span), severity: Some(severity(d.severity)), - code: d - .code - .clone() - .map(tower_lsp::lsp_types::NumberOrString::String), + code: d.code.clone().map(lsp_types::NumberOrString::String), source: Some("pseudoscript".to_owned()), message: d.message.clone(), ..Diagnostic::default() diff --git a/crates/pseudoscript-lsp-core/src/complete.rs b/crates/pseudoscript-lsp-core/src/complete.rs new file mode 100644 index 0000000..3e40f6b --- /dev/null +++ b/crates/pseudoscript-lsp-core/src/complete.rs @@ -0,0 +1,96 @@ +//! LSP adapter over the shared completion engine. +//! +//! The context-aware logic lives in `pseudoscript_model::complete`; this module +//! only maps a `Position` to a byte offset and the engine's neutral +//! [`CompletionKind`] to `lsp_types::CompletionItemKind`. + +use lsp_types::{CompletionItem, CompletionItemKind, Position}; +use pseudoscript_model::{CompletionKind, Workspace, completion as model_completion}; + +use crate::convert::position_to_offset; + +/// Computes completion items for `position` in module `from_fqn`'s `src`. +#[must_use] +pub fn completion( + ws: &Workspace, + from_fqn: &str, + src: &str, + position: Position, +) -> Vec { + let offset = position_to_offset(src, position); + model_completion(ws, from_fqn, src, offset) + .into_iter() + .map(|c| CompletionItem { + label: c.label, + kind: Some(item_kind(c.kind)), + detail: Some(c.detail), + ..CompletionItem::default() + }) + .collect() +} + +/// Maps the engine's neutral kind to the LSP completion-item kind. +fn item_kind(kind: CompletionKind) -> CompletionItemKind { + match kind { + CompletionKind::Method => CompletionItemKind::METHOD, + CompletionKind::Field => CompletionItemKind::FIELD, + CompletionKind::Keyword => CompletionItemKind::KEYWORD, + CompletionKind::Macro => CompletionItemKind::FUNCTION, + CompletionKind::Type => CompletionItemKind::STRUCT, + CompletionKind::Class => CompletionItemKind::CLASS, + CompletionKind::Module => CompletionItemKind::MODULE, + CompletionKind::Reference => CompletionItemKind::REFERENCE, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::convert::offset_to_position; + use pseudoscript_syntax::{LineIndex, parse}; + + fn workspace(modules: &[(&str, &str)]) -> Workspace { + Workspace::build( + modules + .iter() + .map(|(fqn, src)| ((*fqn).to_owned(), parse(src).ast)), + ) + } + + /// Completion labels at the byte `offset` in module `from`, through the + /// LSP adapter (`Position` in, `lsp_types` out). + fn labels_at(ws: &Workspace, from: &str, src: &str, offset: u32) -> Vec { + let pos = offset_to_position(src, &LineIndex::new(src), offset); + completion(ws, from, src, pos) + .into_iter() + .map(|c| c.label) + .collect() + } + + #[test] + fn adapter_scopes_members_with_prefix() { + let src = + "//! m\n\nsystem S {\n run() {\n self.he\n }\n helper(x: number): uuid;\n}\n"; + let ws = workspace(&[("m", src)]); + let offset = (src.find("self.he").unwrap() + "self.he".len()) as u32; + let labels = labels_at(&ws, "m", src, offset); + assert!(labels.contains(&"helper".to_owned()), "{labels:?}"); + assert!( + !labels.contains(&"system".to_owned()), + "general scope leaked: {labels:?}" + ); + } + + #[test] + fn adapter_maps_kinds() { + let src = "//! m\n\n"; + let ws = workspace(&[("m", src)]); + let pos = offset_to_position(src, &LineIndex::new(src), src.len() as u32); + let items = completion(&ws, "m", src, pos); + let kw = items + .iter() + .find(|c| c.label == "system") + .expect("keyword present"); + assert_eq!(kw.kind, Some(CompletionItemKind::KEYWORD)); + } +} diff --git a/crates/pseudoscript-lsp/src/convert.rs b/crates/pseudoscript-lsp-core/src/convert.rs similarity index 98% rename from crates/pseudoscript-lsp/src/convert.rs rename to crates/pseudoscript-lsp-core/src/convert.rs index 3613f85..723f664 100644 --- a/crates/pseudoscript-lsp/src/convert.rs +++ b/crates/pseudoscript-lsp-core/src/convert.rs @@ -5,8 +5,8 @@ //! line/byte-column pair. LSP positions, by contrast, are 0-based line and //! 0-based UTF-16 code-unit character. This module bridges the two. +use lsp_types::{Position, Range}; use pseudoscript_syntax::{LineIndex, Span}; -use tower_lsp::lsp_types::{Position, Range}; /// Converts a byte `offset` into the source to a 0-based LSP [`Position`]. /// diff --git a/crates/pseudoscript-lsp-core/src/lib.rs b/crates/pseudoscript-lsp-core/src/lib.rs new file mode 100644 index 0000000..afc212b --- /dev/null +++ b/crates/pseudoscript-lsp-core/src/lib.rs @@ -0,0 +1,21 @@ +//! The transport-neutral `PseudoScript` LSP API. +//! +//! Pure `text + position -> lsp_types value` functions — diagnostics, hover, +//! definition, references, completion, semantic tokens, folding, symbols, +//! formatting. No transport, no async runtime, no `tower-lsp`: this crate is +//! WASM-safe, so both edges share one implementation — +//! +//! - [`pseudoscript-lsp`] wraps it in a tower-lsp stdio server, and +//! - [`pseudoscript-wasm`] serialises the same `lsp_types` results to JSON. +//! +//! Types are the standalone [`lsp_types`] crate at the version `tower-lsp` +//! re-exports, so the server passes them through with no conversion. + +pub mod analysis; +pub mod complete; +pub mod convert; +pub mod refs; +pub mod semantic; +pub mod symbols; + +pub use pseudoscript_model::resolve; diff --git a/crates/pseudoscript-lsp/src/refs.rs b/crates/pseudoscript-lsp-core/src/refs.rs similarity index 71% rename from crates/pseudoscript-lsp/src/refs.rs rename to crates/pseudoscript-lsp-core/src/refs.rs index e054147..24fbf30 100644 --- a/crates/pseudoscript-lsp/src/refs.rs +++ b/crates/pseudoscript-lsp-core/src/refs.rs @@ -73,6 +73,42 @@ pub fn references( out } +/// One file's rename edits: the module FQN and the spans of every occurrence of +/// the symbol within it (the declaration included). The caller substitutes the +/// new name at each span — this backs `textDocument/rename`. +#[derive(Debug, Clone)] +pub struct FileEdits { + /// FQN of the module the edits apply to. + pub fqn: String, + /// Spans to replace with the new name, in source order. + pub spans: Vec, +} + +/// Group every occurrence of the symbol under `offset` (declaration included) by +/// module, ready for a rename. Empty when the cursor is on no resolvable symbol. +/// Module and span order follow the workspace scan, so it is deterministic. +#[must_use] +pub fn rename( + ws: &Workspace, + modules: &[(String, String)], + from_fqn: &str, + src: &str, + offset: u32, +) -> Vec { + let mut by: Vec = Vec::new(); + for occ in references(ws, modules, from_fqn, src, offset, true) { + if let Some(file) = by.iter_mut().find(|f| f.fqn == occ.fqn) { + file.spans.push(occ.span); + } else { + by.push(FileEdits { + fqn: occ.fqn, + spans: vec![occ.span], + }); + } + } + by +} + /// The occurrences of the symbol under `offset` within the current file only /// (document highlight). #[must_use] @@ -160,6 +196,34 @@ mod tests { ); } + #[test] + fn rename_groups_occurrences_by_file_including_declaration() { + let mods = [ + ("a", "//! a\n\npublic system Svc;\n"), + ("b", "//! b\n\npublic container C for a::Svc;\n"), + ]; + let workspace = ws(&mods); + let owned = owned(&mods); + let offset = mods[0].1.find("Svc").unwrap() as u32; + + let edits = rename(&workspace, &owned, "a", mods[0].1, offset); + assert_eq!(edits.len(), 2, "both files carry an occurrence: {edits:?}"); + let a = edits.iter().find(|e| e.fqn == "a").expect("module a"); + let b = edits.iter().find(|e| e.fqn == "b").expect("module b"); + assert_eq!(a.spans.len(), 1, "the declaration in a"); + assert_eq!(b.spans.len(), 1, "the cross-file use in b"); + } + + #[test] + fn rename_on_no_symbol_is_empty() { + let mods = [("a", "//! a\n\npublic system Svc;\n")]; + let workspace = ws(&mods); + let owned = owned(&mods); + // offset 0 is the leading `//!` comment — no resolvable symbol. + let edits = rename(&workspace, &owned, "a", mods[0].1, 0); + assert!(edits.is_empty(), "no symbol under the cursor: {edits:?}"); + } + #[test] fn highlights_are_confined_to_the_active_file() { let mods = [ diff --git a/crates/pseudoscript-lsp-core/src/semantic.rs b/crates/pseudoscript-lsp-core/src/semantic.rs new file mode 100644 index 0000000..2130f31 --- /dev/null +++ b/crates/pseudoscript-lsp-core/src/semantic.rs @@ -0,0 +1,181 @@ +//! LSP adapter over the shared semantic-token engine. +//! +//! The AST-aware colouring lives in `pseudoscript_model::semantic`; this module +//! advertises the legend and delta-encodes the engine's byte-offset tokens into +//! the `lsp_types` wire format (single-line, non-overlapping, delta-encoded). + +use lsp_types::{ + SemanticToken, SemanticTokenModifier, SemanticTokenType, SemanticTokens, SemanticTokensLegend, +}; +use pseudoscript_model::{SemKind, semantic_tokens as model_semantic_tokens}; +use pseudoscript_syntax::LineIndex; + +use crate::convert::offset_to_position; + +/// The `declaration` modifier bit (bit 0 of the legend's modifier list). +const MOD_DECLARATION: u32 = 1 << 0; + +/// The token types this server emits, in legend order. The index MUST match +/// [`sem_index`]. +fn token_types() -> Vec { + vec![ + SemanticTokenType::NAMESPACE, + SemanticTokenType::TYPE, + SemanticTokenType::CLASS, + SemanticTokenType::PARAMETER, + SemanticTokenType::VARIABLE, + SemanticTokenType::PROPERTY, + SemanticTokenType::ENUM_MEMBER, + SemanticTokenType::METHOD, + SemanticTokenType::KEYWORD, + SemanticTokenType::COMMENT, + SemanticTokenType::STRING, + SemanticTokenType::NUMBER, + SemanticTokenType::DECORATOR, + ] +} + +/// The legend the server advertises and the encoder indexes into. +#[must_use] +pub fn legend() -> SemanticTokensLegend { + SemanticTokensLegend { + token_types: token_types(), + token_modifiers: vec![SemanticTokenModifier::DECLARATION], + } +} + +/// The legend index for a model token kind (must match [`token_types`] order). +fn sem_index(kind: SemKind) -> u32 { + match kind { + SemKind::Namespace => 0, + SemKind::Type => 1, + SemKind::Class => 2, + SemKind::Parameter => 3, + SemKind::Variable => 4, + SemKind::Property => 5, + SemKind::EnumMember => 6, + SemKind::Method => 7, + SemKind::Keyword => 8, + SemKind::Comment => 9, + SemKind::String => 10, + SemKind::Number => 11, + SemKind::Decorator => 12, + } +} + +/// Computes the semantic tokens for `src` as a full-document, delta-encoded set. +/// +/// The engine already returns sorted, non-overlapping byte-offset tokens; this +/// drops any spanning more than one line (the protocol requires single-line +/// tokens) and delta-encodes the rest. +#[must_use] +pub fn semantic_tokens(src: &str) -> SemanticTokens { + let index = LineIndex::new(src); + let mut data = Vec::new(); + let mut prev_line = 0; + let mut prev_start = 0; + + for token in model_semantic_tokens(src) { + let start = offset_to_position(src, &index, token.start); + let end = offset_to_position(src, &index, token.end); + if end.line != start.line || end.character <= start.character { + continue; + } + let delta_line = start.line - prev_line; + let delta_start = if delta_line == 0 { + start.character - prev_start + } else { + start.character + }; + data.push(SemanticToken { + delta_line, + delta_start, + length: end.character - start.character, + token_type: sem_index(token.kind), + token_modifiers_bitset: if token.declaration { + MOD_DECLARATION + } else { + 0 + }, + }); + prev_line = start.line; + prev_start = start.character; + } + + SemanticTokens { + result_id: None, + data, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + /// A decoded token in absolute coordinates, for assertion convenience. + #[derive(Debug, PartialEq, Eq)] + struct Decoded { + line: u32, + start: u32, + len: u32, + ty: SemanticTokenType, + declared: bool, + } + + fn decode(src: &str) -> Vec { + let types = token_types(); + let tokens = semantic_tokens(src); + let mut line = 0; + let mut start = 0; + tokens + .data + .iter() + .map(|t| { + if t.delta_line == 0 { + start += t.delta_start; + } else { + line += t.delta_line; + start = t.delta_start; + } + Decoded { + line, + start, + len: t.length, + ty: types[t.token_type as usize].clone(), + declared: t.token_modifiers_bitset & MOD_DECLARATION != 0, + } + }) + .collect() + } + + fn at<'a>(decoded: &'a [Decoded], src: &str, needle: &str) -> &'a Decoded { + let offset = src.find(needle).expect("substring present") as u32; + let line = src[..offset as usize].matches('\n').count() as u32; + let line_start = src[..offset as usize].rfind('\n').map_or(0, |nl| nl + 1) as u32; + let start = offset - line_start; + decoded + .iter() + .find(|d| d.line == line && d.start == start) + .unwrap_or_else(|| panic!("no token at {needle:?}")) + } + + #[test] + fn node_name_is_a_declared_namespace() { + let src = "//! m\n\npublic system Banking;\n"; + let decoded = decode(src); + let token = at(&decoded, src, "Banking"); + assert_eq!(token.ty, SemanticTokenType::NAMESPACE); + assert!(token.declared); + assert_eq!(token.len, 7); + } + + #[test] + fn data_name_and_members() { + let src = "//! m\n\ndata Account { id: uuid }\n"; + let decoded = decode(src); + assert_eq!(at(&decoded, src, "data").ty, SemanticTokenType::KEYWORD); + assert_eq!(at(&decoded, src, "Account").ty, SemanticTokenType::CLASS); + assert_eq!(at(&decoded, src, "id").ty, SemanticTokenType::PROPERTY); + assert_eq!(at(&decoded, src, "uuid").ty, SemanticTokenType::TYPE); + } +} diff --git a/crates/pseudoscript-lsp/src/symbols.rs b/crates/pseudoscript-lsp-core/src/symbols.rs similarity index 78% rename from crates/pseudoscript-lsp/src/symbols.rs rename to crates/pseudoscript-lsp-core/src/symbols.rs index 112b6f7..cd2aea5 100644 --- a/crates/pseudoscript-lsp/src/symbols.rs +++ b/crates/pseudoscript-lsp-core/src/symbols.rs @@ -3,11 +3,11 @@ //! `document_symbols` and `folding_ranges` are pure over one module's source; //! `workspace_symbols` searches the resolved [`Workspace`] index by name. -use pseudoscript_model::{SymbolKind as ModelKind, Workspace, ast}; -use pseudoscript_syntax::{LineIndex, Span, parse}; -use tower_lsp::lsp_types::{ +use lsp_types::{ DocumentSymbol, FoldingRange, FoldingRangeKind, Location, SymbolInformation, SymbolKind, Url, }; +use pseudoscript_model::{SymbolKind as ModelKind, Workspace, ast}; +use pseudoscript_syntax::{LineIndex, Span, parse}; use crate::convert::span_to_range; @@ -158,80 +158,21 @@ fn symbol( } /// The foldable regions of `src`: every multi-line declaration and statement -/// block. +/// block. Spans come from the shared engine; this only maps them to line-based +/// `FoldingRange`s and drops single-line spans. #[must_use] pub fn folding_ranges(src: &str) -> Vec { - let module = parse(src).ast; let index = LineIndex::new(src); - let mut spans = Vec::new(); - for item in &module.items { - if let ast::Item::Decl(decl) = item { - collect_decl_spans(decl, &mut spans); - } - } - spans + pseudoscript_model::folding_ranges(src) .into_iter() - .filter_map(|span| fold(span, &index)) + .filter_map(|range| fold(range, &index)) .collect() } -/// Collects the foldable span of a *disclosed* declaration (one with a `{ }` -/// body) and any blocks nested in it. A black-box `;` declaration has nothing -/// to fold. -fn collect_decl_spans(decl: &ast::Decl, out: &mut Vec) { - match &decl.kind { - ast::DeclKind::Person(node) - | ast::DeclKind::System(node) - | ast::DeclKind::Container(node) - | ast::DeclKind::Component(node) => { - let Some(body) = &node.body else { return }; - out.push(decl.span); - for member in body { - match member { - ast::BodyMember::Decl(inner) => collect_decl_spans(inner, out), - ast::BodyMember::Callable(callable) => { - if let Some(block) = &callable.body { - collect_block_spans(block, out); - } - } - } - } - } - ast::DeclKind::Data(data) => { - if !matches!(data.body, ast::DataBody::BlackBox) { - out.push(decl.span); - } - } - } -} - -/// Collects a block's span and the spans of any nested control-flow blocks. -fn collect_block_spans(block: &ast::Block, out: &mut Vec) { - out.push(block.span); - for stmt in &block.stmts { - match &stmt.kind { - ast::StmtKind::If { - then_block, - else_block, - .. - } => { - collect_block_spans(then_block, out); - if let Some(block) = else_block { - collect_block_spans(block, out); - } - } - ast::StmtKind::For { body, .. } | ast::StmtKind::While { body, .. } => { - collect_block_spans(body, out); - } - _ => {} - } - } -} - -/// A folding range for `span`, or `None` when it does not cross a line. -fn fold(span: Span, index: &LineIndex) -> Option { - let (start_line, _) = index.line_col(span.start); - let (end_line, _) = index.line_col(span.end); +/// A folding range for a byte span, or `None` when it does not cross a line. +fn fold(range: pseudoscript_model::FoldRange, index: &LineIndex) -> Option { + let (start_line, _) = index.line_col(range.start); + let (end_line, _) = index.line_col(range.end); (end_line > start_line).then_some(FoldingRange { start_line: start_line - 1, start_character: None, @@ -276,7 +217,7 @@ pub fn workspace_symbols( fn symbol_information( symbol: &pseudoscript_model::Symbol, uri: Url, - range: tower_lsp::lsp_types::Range, + range: lsp_types::Range, ) -> SymbolInformation { SymbolInformation { name: symbol.name.clone(), diff --git a/crates/pseudoscript-lsp/Cargo.toml b/crates/pseudoscript-lsp/Cargo.toml index 10d1a02..cd484c3 100644 --- a/crates/pseudoscript-lsp/Cargo.toml +++ b/crates/pseudoscript-lsp/Cargo.toml @@ -13,6 +13,7 @@ path = "src/lib.rs" [dependencies] pseudoscript-syntax = { path = "../pseudoscript-syntax" } pseudoscript-model = { path = "../pseudoscript-model" } +pseudoscript-lsp-core = { path = "../pseudoscript-lsp-core" } pseudoscript-format = { path = "../pseudoscript-format" } tower-lsp = "0.20" tokio = { version = "1", features = ["full"] } @@ -20,6 +21,7 @@ serde_json = "1" walkdir = "2" [dev-dependencies] +pseudoscript-lsp-core = { path = "../pseudoscript-lsp-core" } cucumber = "0.21" futures = "0.3" diff --git a/crates/pseudoscript-lsp/src/complete.rs b/crates/pseudoscript-lsp/src/complete.rs deleted file mode 100644 index dbe7683..0000000 --- a/crates/pseudoscript-lsp/src/complete.rs +++ /dev/null @@ -1,267 +0,0 @@ -//! Context-aware completion. -//! -//! The completion context is read from the token immediately left of the caret: -//! -//! - after `.` → the base node's callables and fields; -//! - after `::` → the named module's (public) symbols; -//! - after `#[` → the built-in macros; -//! - after `:` or `<` (type position) → primitive types, `Result`, and every -//! declared type; -//! - otherwise → keywords, this module's symbols, and its aliases. -//! -//! The client filters the returned set against the prefix being typed, so the -//! full candidate list is offered. - -use pseudoscript_model::{BUILTIN_MACROS, MemberKind, SymbolKind, Workspace}; -use pseudoscript_syntax::{Token, TokenKind, tokenize}; -use tower_lsp::lsp_types::{CompletionItem, CompletionItemKind, Position}; - -use crate::convert::position_to_offset; -use crate::resolve::{enclosing_node, module_of}; - -/// Computes completion items for `position` in module `from_fqn`'s `src`. -#[must_use] -pub fn completion( - ws: &Workspace, - from_fqn: &str, - src: &str, - position: Position, -) -> Vec { - let offset = position_to_offset(src, position); - let tokens = tokenize(src); - // The token whose context governs completion is the last one ending at or - // before the caret (an identifier under the caret ends after it, so its - // predecessor — the trigger — is selected instead). - let trigger = tokens.iter().rposition(|t| t.span.end <= offset); - - match trigger.map(|i| (i, tokens[i].kind)) { - Some((i, TokenKind::Dot)) => member_items(ws, from_fqn, src, &tokens, i), - Some((i, TokenKind::ColonColon)) => path_items(ws, from_fqn, &tokens, i), - Some((_, TokenKind::HashLBracket)) => macro_items(), - Some((_, TokenKind::Colon | TokenKind::LAngle)) => type_items(ws), - _ => general_items(ws, from_fqn), - } -} - -/// Callables and fields of the node named by the base before `tokens[dot]`. -fn member_items( - ws: &Workspace, - from_fqn: &str, - _src: &str, - tokens: &[Token], - dot: usize, -) -> Vec { - let Some((owner_module, owner_name)) = owner_before(ws, from_fqn, tokens, dot) else { - return Vec::new(); - }; - let Some(entry) = ws.module(&owner_module) else { - return Vec::new(); - }; - entry - .model - .members(&owner_name) - .iter() - .map(|m| { - let kind = match m.kind { - MemberKind::Callable => CompletionItemKind::METHOD, - MemberKind::Field => CompletionItemKind::FIELD, - }; - item(&m.name, kind, &m.detail) - }) - .collect() -} - -/// The `(module, node-name)` the base token before `tokens[dot]` denotes: -/// `self`'s enclosing node, or an in-scope node name. -fn owner_before( - ws: &Workspace, - from_fqn: &str, - tokens: &[Token], - dot: usize, -) -> Option<(String, String)> { - let base = tokens.get(dot.checked_sub(1)?)?; - match base.kind { - TokenKind::KwSelf => { - let node = enclosing_node(&ws.module(from_fqn)?.ast, base.span.start)?; - Some((from_fqn.to_owned(), node)) - } - TokenKind::Ident => { - let symbol = ws.module(from_fqn)?.model.symbol(&base.text)?; - Some((module_of(&symbol.fqn).to_owned(), symbol.name.clone())) - } - _ => None, - } -} - -/// Symbols of the module named by the `::` path ending at `tokens[ccolon]`. -/// A cross-module suggestion is offered only when `public` (§8.2). -fn path_items( - ws: &Workspace, - from_fqn: &str, - tokens: &[Token], - ccolon: usize, -) -> Vec { - let prefix = module_prefix(tokens, ccolon); - ws.symbols() - .filter(|s| module_of(&s.fqn) == prefix && (prefix == from_fqn || s.is_public)) - .map(|s| item(&s.name, symbol_kind(s.kind), &s.fqn)) - .collect() -} - -/// The `::`-joined module path written immediately before `tokens[ccolon]`. -fn module_prefix(tokens: &[Token], ccolon: usize) -> String { - let mut segments = Vec::new(); - let mut cursor = ccolon.checked_sub(1); - while let Some(i) = cursor { - if tokens[i].kind != TokenKind::Ident { - break; - } - segments.push(tokens[i].text.as_str()); - cursor = match i.checked_sub(1) { - Some(j) if tokens[j].kind == TokenKind::ColonColon => i.checked_sub(2), - _ => None, - }; - } - segments.reverse(); - segments.join("::") -} - -/// The built-in macros (`#[...]`). -fn macro_items() -> Vec { - BUILTIN_MACROS - .iter() - .map(|m| item(m, CompletionItemKind::FUNCTION, "built-in macro")) - .collect() -} - -/// Primitive types, `Result`, and every declared node/data type. -fn type_items(ws: &Workspace) -> Vec { - let primitives = TokenKind::PRIMITIVE_TYPES - .iter() - .map(|t| item(t, CompletionItemKind::STRUCT, "primitive type")) - .chain(std::iter::once(item( - "Result", - CompletionItemKind::STRUCT, - "built-in generic", - ))); - let declared = ws - .symbols() - .map(|s| item(&s.name, symbol_kind(s.kind), &s.fqn)); - primitives.chain(declared).collect() -} - -/// Keywords plus this module's own symbols and aliases. -fn general_items(ws: &Workspace, from_fqn: &str) -> Vec { - let keywords = TokenKind::KEYWORDS - .iter() - .map(|k| item(k, CompletionItemKind::KEYWORD, "keyword")); - let Some(entry) = ws.module(from_fqn) else { - return keywords.collect(); - }; - let symbols = entry - .model - .symbols() - .map(|s| item(&s.name, symbol_kind(s.kind), &s.fqn)); - let aliases = entry - .model - .aliases() - .map(|(name, a)| item(name, CompletionItemKind::REFERENCE, &a.target)); - keywords.chain(symbols).chain(aliases).collect() -} - -/// The completion kind for a declared symbol. -fn symbol_kind(kind: SymbolKind) -> CompletionItemKind { - match kind { - SymbolKind::Data => CompletionItemKind::CLASS, - _ => CompletionItemKind::MODULE, - } -} - -/// Builds a labelled completion item with a detail string. -fn item(label: &str, kind: CompletionItemKind, detail: &str) -> CompletionItem { - CompletionItem { - label: label.to_owned(), - kind: Some(kind), - detail: Some(detail.to_owned()), - ..CompletionItem::default() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::convert::offset_to_position; - use pseudoscript_syntax::{LineIndex, parse}; - - fn workspace(modules: &[(&str, &str)]) -> Workspace { - Workspace::build( - modules - .iter() - .map(|(fqn, src)| ((*fqn).to_owned(), parse(src).ast)), - ) - } - - /// Completion labels at the byte `offset` in module `from`. - fn labels_at(ws: &Workspace, from: &str, src: &str, offset: u32) -> Vec { - let pos = offset_to_position(src, &LineIndex::new(src), offset); - completion(ws, from, src, pos) - .into_iter() - .map(|c| c.label) - .collect() - } - - #[test] - fn members_after_self_dot() { - let src = "//! m\n\nsystem S {\n run() {\n self.\n }\n helper(x: number): uuid;\n}\n"; - let ws = workspace(&[("m", src)]); - let offset = (src.find("self.").unwrap() + "self.".len()) as u32; - let labels = labels_at(&ws, "m", src, offset); - assert!(labels.contains(&"helper".to_owned()), "{labels:?}"); - assert!(labels.contains(&"run".to_owned()), "{labels:?}"); - } - - #[test] - fn types_after_colon() { - let src = "//! m\n\ndata D { x: }\n"; - let ws = workspace(&[("m", src)]); - let offset = (src.find("x:").unwrap() + 2) as u32; - let labels = labels_at(&ws, "m", src, offset); - assert!(labels.contains(&"number".to_owned()), "{labels:?}"); - assert!(labels.contains(&"Result".to_owned()), "{labels:?}"); - assert!(labels.contains(&"D".to_owned()), "{labels:?}"); - } - - #[test] - fn macros_after_hash_bracket() { - let src = "//! m\n\n#[\nsystem S;\n"; - let ws = workspace(&[("m", src)]); - let offset = (src.find("#[").unwrap() + 2) as u32; - let labels = labels_at(&ws, "m", src, offset); - assert!(labels.contains(&"http".to_owned()), "{labels:?}"); - assert!(labels.contains(&"onevent".to_owned()), "{labels:?}"); - } - - #[test] - fn public_symbols_after_module_path() { - let mods = [ - ("a", "//! a\n\npublic system Svc;\n\nsystem Hidden;\n"), - ("b", "//! b\n\ncontainer C for a::\n"), - ]; - let ws = workspace(&mods); - let src = mods[1].1; - let offset = (src.find("a::").unwrap() + 3) as u32; - let labels = labels_at(&ws, "b", src, offset); - assert!(labels.contains(&"Svc".to_owned()), "{labels:?}"); - // a private node in another module is not offered (§8.2) - assert!(!labels.contains(&"Hidden".to_owned()), "{labels:?}"); - } - - #[test] - fn keywords_in_general_position() { - let src = "//! m\n\n"; - let ws = workspace(&[("m", src)]); - let labels = labels_at(&ws, "m", src, src.len() as u32); - assert!(labels.contains(&"system".to_owned()), "{labels:?}"); - assert!(labels.contains(&"public".to_owned()), "{labels:?}"); - } -} diff --git a/crates/pseudoscript-lsp/src/infer.rs b/crates/pseudoscript-lsp/src/infer.rs deleted file mode 100644 index cb9238c..0000000 --- a/crates/pseudoscript-lsp/src/infer.rs +++ /dev/null @@ -1,224 +0,0 @@ -//! Local-binding type inference, for inlay hints and hover. -//! -//! `PseudoScript` assignments are untyped (`x = expr`). This module infers a -//! binding's type from its right-hand side — a call's return type, a field -//! access, a `from` expression, or a literal — so the editor can show -//! `x: Token[]` without the author writing it. Inference is best-effort: an -//! expression it can't type yields no hint rather than a guess. - -use pseudoscript_model::{Workspace, ast}; -use pseudoscript_syntax::Span; - -use crate::resolve::{enclosing_node, resolve_owner}; - -/// An inferred local binding: its name, the span of that name, and its type. -pub struct LocalType { - pub name: String, - pub name_span: Span, - pub ty: String, -} - -/// Every typed local binding in module `from_fqn` (assignments whose right-hand -/// side has an inferable type). -#[must_use] -pub fn local_types(ws: &Workspace, from_fqn: &str) -> Vec { - let Some(entry) = ws.module(from_fqn) else { - return Vec::new(); - }; - let mut out = Vec::new(); - for item in &entry.ast.items { - if let ast::Item::Decl(decl) = item { - walk_decl(ws, from_fqn, decl, &mut out); - } - } - out -} - -/// The inferred type of the binding named by the identifier at `offset`, with -/// its name — for hover. Matches by binding name, so a use resolves to its -/// declaration's inferred type. -#[must_use] -pub fn binding_type_at(ws: &Workspace, from_fqn: &str, name: &str) -> Option { - local_types(ws, from_fqn) - .into_iter() - .find(|lt| lt.name == name) -} - -fn walk_decl(ws: &Workspace, from_fqn: &str, decl: &ast::Decl, out: &mut Vec) { - let (ast::DeclKind::Person(node) - | ast::DeclKind::System(node) - | ast::DeclKind::Container(node) - | ast::DeclKind::Component(node)) = &decl.kind - else { - return; - }; - for member in node.body.iter().flatten() { - match member { - ast::BodyMember::Callable(callable) => { - if let Some(block) = &callable.body { - walk_block(ws, from_fqn, block, out); - } - } - ast::BodyMember::Decl(inner) => walk_decl(ws, from_fqn, inner, out), - } - } -} - -fn walk_block(ws: &Workspace, from_fqn: &str, block: &ast::Block, out: &mut Vec) { - for stmt in &block.stmts { - match &stmt.kind { - ast::StmtKind::Assign { name, value } => { - if let Some(ty) = expr_type(ws, from_fqn, value) { - out.push(LocalType { - name: name.name.clone(), - name_span: name.span, - ty, - }); - } - } - ast::StmtKind::For { - binding, - iter, - body, - } => { - // `for (x in xs)` binds `x` to the element type of an array `xs`. - if let Some(ty) = expr_type(ws, from_fqn, iter) - && let Some(element) = ty.strip_suffix("[]") - { - out.push(LocalType { - name: binding.name.clone(), - name_span: binding.span, - ty: element.to_owned(), - }); - } - walk_block(ws, from_fqn, body, out); - } - ast::StmtKind::If { - then_block, - else_block, - .. - } => { - walk_block(ws, from_fqn, then_block, out); - if let Some(block) = else_block { - walk_block(ws, from_fqn, block, out); - } - } - ast::StmtKind::While { body, .. } => walk_block(ws, from_fqn, body, out), - ast::StmtKind::Return(_) | ast::StmtKind::Expr(_) => {} - } - } -} - -/// The inferred type of an expression, or `None` when it can't be typed. -fn expr_type(ws: &Workspace, from_fqn: &str, expr: &ast::Expr) -> Option { - match &expr.kind { - ast::ExprKind::Literal(ast::Literal::String { .. }) => Some("string".to_owned()), - ast::ExprKind::Literal(ast::Literal::Number { .. }) => Some("number".to_owned()), - ast::ExprKind::Literal(ast::Literal::Bool { .. }) => Some("bool".to_owned()), - ast::ExprKind::Paren(inner) => expr_type(ws, from_fqn, inner), - // `T from { .. }` produces a value of the named type. - ast::ExprKind::From { ty, .. } => ty.segments.last().map(|seg| seg.name.clone()), - ast::ExprKind::Postfix { base, segments } => postfix_type(ws, from_fqn, base, segments), - _ => None, - } -} - -/// The type of a postfix chain: walk each `.member`, the result is the last -/// member's type. Each non-final member's type must itself name a node/data so -/// the chain can continue. -fn postfix_type( - ws: &Workspace, - from_fqn: &str, - base: &ast::Expr, - segments: &[ast::PostfixSeg], -) -> Option { - let mut owner = base_owner(ws, from_fqn, base)?; - let mut result = None; - for (i, seg) in segments.iter().enumerate() { - let member_ty = ws - .module(&owner.0)? - .model - .members(&owner.1) - .iter() - .find(|m| m.name == seg.name.name)? - .ty - .clone(); - result = Some(member_ty.clone()); - if i + 1 < segments.len() { - owner = type_owner(ws, from_fqn, &member_ty)?; - } - } - result -} - -/// The node/data owner a postfix base denotes: `self`'s enclosing node, or the -/// node/data a path names. -fn base_owner(ws: &Workspace, from_fqn: &str, base: &ast::Expr) -> Option<(String, String)> { - match &base.kind { - ast::ExprKind::Ref(ast::Ref::SelfNode(span)) => { - let node = enclosing_node(&ws.module(from_fqn)?.ast, span.start)?; - Some((from_fqn.to_owned(), node)) - } - ast::ExprKind::Ref(ast::Ref::Path(path)) => { - let segments: Vec<&str> = path.segments.iter().map(|s| s.name.as_str()).collect(); - resolve_owner(ws, from_fqn, &segments) - } - ast::ExprKind::Paren(inner) => base_owner(ws, from_fqn, inner), - _ => None, - } -} - -/// The node/data named by a type string (`Token[]` → `Token`, `a::T` → `a::T`), -/// for continuing a postfix chain. -fn type_owner(ws: &Workspace, from_fqn: &str, ty: &str) -> Option<(String, String)> { - let base = ty.trim_end_matches("[]"); - let base = base.split('<').next().unwrap_or(base).trim(); - let segments: Vec<&str> = base.split("::").collect(); - resolve_owner(ws, from_fqn, &segments) -} - -#[cfg(test)] -mod tests { - use super::*; - use pseudoscript_syntax::parse; - - fn ws(modules: &[(&str, &str)]) -> Workspace { - Workspace::build(modules.iter().map(|(f, s)| ((*f).to_owned(), parse(s).ast))) - } - - // Mirrors the `syntax` module: `tokens` is the `Token[]` returned by - // `Lexer.tokenize`, reached through the container-qualified `Syntax::Lexer`. - const SYNTAX: &str = "//! syntax\n\n\ - public data Token { kind: string }\n\n\ - public component Lexer for Syntax {\n tokenize(text: string): Token[];\n}\n\n\ - public component Parser for Syntax {\n \ - public parse(text: string): string {\n \ - tokens = Syntax::Lexer.tokenize(text)\n return tokens.kind\n }\n}\n"; - - #[test] - fn infers_local_from_member_call_return() { - let workspace = ws(&[("syntax", SYNTAX)]); - let locals = local_types(&workspace, "syntax"); - let tokens = locals - .iter() - .find(|l| l.name == "tokens") - .expect("`tokens` typed"); - assert_eq!(tokens.ty, "Token[]"); - } - - #[test] - fn binding_type_at_resolves_by_name() { - let workspace = ws(&[("syntax", SYNTAX)]); - let local = binding_type_at(&workspace, "syntax", "tokens").expect("tokens"); - assert_eq!(local.ty, "Token[]"); - } - - #[test] - fn infers_literal_and_from_expression() { - let src = "//! m\n\nsystem S {\n go() {\n n = 42\n p = Parsed from { n }\n }\n}\n\npublic data Parsed { x: number }\n"; - let workspace = ws(&[("m", src)]); - let locals = local_types(&workspace, "m"); - assert_eq!(locals.iter().find(|l| l.name == "n").unwrap().ty, "number"); - assert_eq!(locals.iter().find(|l| l.name == "p").unwrap().ty, "Parsed"); - } -} diff --git a/crates/pseudoscript-lsp/src/lib.rs b/crates/pseudoscript-lsp/src/lib.rs index d043eca..8dd8c97 100644 --- a/crates/pseudoscript-lsp/src/lib.rs +++ b/crates/pseudoscript-lsp/src/lib.rs @@ -9,22 +9,14 @@ //! //! # Surfaces //! -//! - [`analysis`] — pure `text -> LSP value` functions (diagnostics, formatting -//! edit, hover, definition). These carry the behaviour and are unit/BDD -//! tested without spawning a server. +//! - [`pseudoscript_lsp_core`] — the transport-neutral `text -> LSP value` +//! handlers (diagnostics, hover, completion, semantic tokens, …), shared with +//! the WASM bridge. This crate only adds the stdio transport. //! - [`Backend`] — the [`tower_lsp::LanguageServer`] implementation and document //! store. //! - [`run_stdio`] — build the server over stdin/stdout and serve until exit. -pub mod analysis; -mod complete; -mod convert; -mod infer; -mod refs; -use pseudoscript_model::resolve; -mod semantic; mod server; -mod symbols; mod workspace; pub use server::Backend; diff --git a/crates/pseudoscript-lsp/src/semantic.rs b/crates/pseudoscript-lsp/src/semantic.rs deleted file mode 100644 index c70bafd..0000000 --- a/crates/pseudoscript-lsp/src/semantic.rs +++ /dev/null @@ -1,543 +0,0 @@ -//! AST-aware semantic tokens (LSP `textDocument/semanticTokens`). -//! -//! Two passes feed one sorted, non-overlapping, delta-encoded token list: -//! -//! - **Token pass** ([`tokenize`]) colours the leaves the tree does not expose -//! as convenient spans: keywords, doc comments, string/number literals, and -//! the `#[` macro opener. These kinds are never identifiers. -//! - **AST pass** ([`parse`]) colours identifiers by their *role* — a `system` -//! name is a namespace, a `data` name a class, a callable a method, a -//! parameter a parameter, a `.f()` step a method call. Identifiers are never -//! touched by the token pass, so the two sets cannot overlap. -//! -//! The shared [`legend`] keeps the server capability and the encoding in step: -//! [`Sem`] discriminants index it directly. - -use pseudoscript_syntax::{LineIndex, Span, TokenKind, ast, parse, tokenize}; -use tower_lsp::lsp_types::{ - SemanticToken, SemanticTokenModifier, SemanticTokenType, SemanticTokens, SemanticTokensLegend, -}; - -use crate::convert::offset_to_position; - -/// A semantic token type. The discriminant is its index into [`legend`]'s -/// `token_types`, so the two MUST stay in the same order. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -enum Sem { - Namespace = 0, - Type, - Class, - Parameter, - Variable, - Property, - EnumMember, - Method, - Keyword, - Comment, - Str, - Number, - Decorator, -} - -impl Sem { - /// The token type's index into the legend. - fn index(self) -> u32 { - self as u32 - } -} - -/// The `declaration` modifier bit (bit 0 of the legend's modifier list). -const MOD_DECLARATION: u32 = 1 << 0; - -/// The token types this server emits, in legend order (see [`Sem`]). -fn token_types() -> Vec { - vec![ - SemanticTokenType::NAMESPACE, - SemanticTokenType::TYPE, - SemanticTokenType::CLASS, - SemanticTokenType::PARAMETER, - SemanticTokenType::VARIABLE, - SemanticTokenType::PROPERTY, - SemanticTokenType::ENUM_MEMBER, - SemanticTokenType::METHOD, - SemanticTokenType::KEYWORD, - SemanticTokenType::COMMENT, - SemanticTokenType::STRING, - SemanticTokenType::NUMBER, - SemanticTokenType::DECORATOR, - ] -} - -/// The legend the server advertises and the encoder indexes into. -#[must_use] -pub fn legend() -> SemanticTokensLegend { - SemanticTokensLegend { - token_types: token_types(), - token_modifiers: vec![SemanticTokenModifier::DECLARATION], - } -} - -/// A coloured span before delta-encoding. -struct Raw { - span: Span, - ty: Sem, - mods: u32, -} - -/// Computes the semantic tokens for `src` as a full-document set. -#[must_use] -pub fn semantic_tokens(src: &str) -> SemanticTokens { - let mut raws = Vec::new(); - token_pass(src, &mut raws); - ast_pass(&parse(src).ast, &mut raws); - encode(src, &raws) -} - -/// Colours keywords, doc comments, literals, and the `#[` macro opener. -fn token_pass(src: &str, out: &mut Vec) { - for token in tokenize(src) { - let ty = match token.kind { - k if is_keyword(k) => Sem::Keyword, - TokenKind::Doc | TokenKind::InnerDoc | TokenKind::Tag => Sem::Comment, - TokenKind::String => Sem::Str, - TokenKind::Number => Sem::Number, - TokenKind::HashLBracket => Sem::Decorator, - _ => continue, - }; - out.push(Raw { - span: token.span, - ty, - mods: 0, - }); - } -} - -/// Whether `kind` is one of the reserved keywords (§2.3). `self`, `Ok`, `Err`, -/// `true`, and `false` count, so the AST pass need not re-colour them. -fn is_keyword(kind: TokenKind) -> bool { - matches!( - kind, - TokenKind::KwSystem - | TokenKind::KwContainer - | TokenKind::KwComponent - | TokenKind::KwPerson - | TokenKind::KwData - | TokenKind::KwFor - | TokenKind::KwAlias - | TokenKind::KwFrom - | TokenKind::KwPublic - | TokenKind::KwSelf - | TokenKind::KwReturn - | TokenKind::KwOk - | TokenKind::KwErr - | TokenKind::KwIf - | TokenKind::KwElse - | TokenKind::KwWhile - | TokenKind::KwIn - | TokenKind::KwTrue - | TokenKind::KwFalse - ) -} - -/// Colours identifiers by their declared role across the whole module. -fn ast_pass(module: &ast::Module, out: &mut Vec) { - for item in &module.items { - match item { - ast::Item::Alias(alias) => { - push(out, alias.name.span, Sem::Namespace, MOD_DECLARATION); - namespace_path(&alias.target, out); - } - ast::Item::Decl(decl) => decl_tokens(decl, out), - ast::Item::Feature(feature) => { - push(out, feature.name.span, Sem::Namespace, MOD_DECLARATION); - namespace_path(&feature.target, out); - } - } - } -} - -/// Colours a declaration: its macros, then its structural payload. -fn decl_tokens(decl: &ast::Decl, out: &mut Vec) { - for mac in &decl.macros { - macro_tokens(mac, out); - } - match &decl.kind { - ast::DeclKind::Person(node) - | ast::DeclKind::System(node) - | ast::DeclKind::Container(node) - | ast::DeclKind::Component(node) => node_tokens(node, out), - ast::DeclKind::Data(data) => data_tokens(data, out), - } -} - -/// Colours a node: its name (namespace, declared), its `for` parent path, and -/// its disclosed body members. -fn node_tokens(node: &ast::Node, out: &mut Vec) { - push(out, node.name.span, Sem::Namespace, MOD_DECLARATION); - if let Some(parent) = &node.parent { - namespace_path(parent, out); - } - for member in node.body.iter().flatten() { - match member { - ast::BodyMember::Callable(callable) => callable_tokens(callable, out), - ast::BodyMember::Decl(decl) => decl_tokens(decl, out), - } - } -} - -/// Colours a `data` declaration: its name (class, declared) and its fields or -/// variants. -fn data_tokens(data: &ast::Data, out: &mut Vec) { - push(out, data.name.span, Sem::Class, MOD_DECLARATION); - match &data.body { - ast::DataBody::Record(fields) => fields_tokens(fields, out), - ast::DataBody::Union(variants) => { - for variant in variants { - push(out, variant.name.span, Sem::EnumMember, MOD_DECLARATION); - if let Some(fields) = &variant.record { - fields_tokens(fields, out); - } - } - } - ast::DataBody::BlackBox => {} - } -} - -/// Colours record fields: each name (property, declared) and its type. -fn fields_tokens(fields: &[ast::Field], out: &mut Vec) { - for field in fields { - push(out, field.name.span, Sem::Property, MOD_DECLARATION); - type_tokens(&field.ty, out); - } -} - -/// Colours a callable: macros, name (method, declared), parameters, return -/// type, and body. -fn callable_tokens(callable: &ast::Callable, out: &mut Vec) { - for mac in &callable.macros { - macro_tokens(mac, out); - } - push(out, callable.name.span, Sem::Method, MOD_DECLARATION); - for param in &callable.params { - push(out, param.name.span, Sem::Parameter, MOD_DECLARATION); - type_tokens(¶m.ty, out); - } - if let Some(ret) = &callable.return_ty { - type_tokens(ret, out); - } - if let Some(block) = &callable.body { - block_tokens(block, out); - } -} - -/// Colours every statement in a block. -fn block_tokens(block: &ast::Block, out: &mut Vec) { - for stmt in &block.stmts { - stmt_tokens(stmt, out); - } -} - -/// Colours one statement and its sub-expressions. -fn stmt_tokens(stmt: &ast::Stmt, out: &mut Vec) { - match &stmt.kind { - ast::StmtKind::Assign { name, value } => { - push(out, name.span, Sem::Variable, MOD_DECLARATION); - expr_tokens(value, out); - } - ast::StmtKind::Return(value) => { - if let Some(value) = value { - expr_tokens(value, out); - } - } - ast::StmtKind::If { - cond, - then_block, - else_block, - } => { - expr_tokens(cond, out); - block_tokens(then_block, out); - if let Some(block) = else_block { - block_tokens(block, out); - } - } - ast::StmtKind::For { - binding, - iter, - body, - } => { - push(out, binding.span, Sem::Variable, MOD_DECLARATION); - expr_tokens(iter, out); - block_tokens(body, out); - } - ast::StmtKind::While { cond, body } => { - expr_tokens(cond, out); - block_tokens(body, out); - } - ast::StmtKind::Expr(expr) => expr_tokens(expr, out), - } -} - -/// Colours an expression: references, calls, field access, and `from` types. -fn expr_tokens(expr: &ast::Expr, out: &mut Vec) { - match &expr.kind { - ast::ExprKind::Marker { payload, .. } => { - if let Some(payload) = payload { - expr_tokens(payload, out); - } - } - ast::ExprKind::From { ty, sources, .. } => { - type_path(ty, out); - for source in sources { - expr_tokens(source, out); - } - } - ast::ExprKind::Postfix { base, segments } => { - expr_tokens(base, out); - for seg in segments { - let ty = if seg.call_args.is_some() { - Sem::Method - } else { - Sem::Property - }; - push(out, seg.name.span, ty, 0); - for arg in seg.call_args.iter().flatten() { - expr_tokens(arg, out); - } - } - } - ast::ExprKind::Ref(ast::Ref::Path(path)) => ref_path(path, out), - // `self` is a keyword and literals are coloured by the token pass. - ast::ExprKind::Ref(ast::Ref::SelfNode(_)) | ast::ExprKind::Literal(_) => {} - ast::ExprKind::Unary { expr, .. } => expr_tokens(expr, out), - ast::ExprKind::Paren(inner) => expr_tokens(inner, out), - } -} - -/// Colours a type: the base path (qualifiers as namespaces, the name as a type) -/// and any generic arguments. -fn type_tokens(ty: &ast::Type, out: &mut Vec) { - type_path(&ty.name, out); - for generic in &ty.generics { - type_tokens(generic, out); - } -} - -/// Colours a macro's name path as a decorator; its path/literal arguments take -/// type colours (literals are already coloured by the token pass). -fn macro_tokens(mac: &ast::Macro, out: &mut Vec) { - for segment in &mac.name.segments { - push(out, segment.span, Sem::Decorator, 0); - } - if let ast::MacroArgs::List(args) = &mac.args { - for arg in args { - match arg { - ast::MacroArg::Path(path) => type_path(path, out), - ast::MacroArg::Nested(nested) => macro_tokens(nested, out), - ast::MacroArg::Literal(_) => {} - } - } - } -} - -/// Colours a value-reference path: trailing name as a variable, qualifiers as -/// namespaces. -fn ref_path(path: &ast::Path, out: &mut Vec) { - split_path(path, Sem::Variable, out); -} - -/// Colours a type path: trailing name as a type, qualifiers as namespaces. -fn type_path(path: &ast::Path, out: &mut Vec) { - split_path(path, Sem::Type, out); -} - -/// Colours every segment of a path as a namespace (parent / alias target). -fn namespace_path(path: &ast::Path, out: &mut Vec) { - for segment in &path.segments { - push(out, segment.span, Sem::Namespace, 0); - } -} - -/// Colours a path's last segment as `last`, every qualifier as a namespace. -fn split_path(path: &ast::Path, last: Sem, out: &mut Vec) { - let Some((name, qualifiers)) = path.segments.split_last() else { - return; - }; - for segment in qualifiers { - push(out, segment.span, Sem::Namespace, 0); - } - push(out, name.span, last, 0); -} - -/// Records one coloured span. -fn push(out: &mut Vec, span: Span, ty: Sem, mods: u32) { - out.push(Raw { span, ty, mods }); -} - -/// Sorts the raw spans and delta-encodes them into LSP semantic tokens. -/// -/// Tokens are ordered by start offset; any token overlapping its predecessor, -/// spanning more than one line, or of zero width is dropped (the protocol -/// requires single-line, non-overlapping tokens). -fn encode(src: &str, raws: &[Raw]) -> SemanticTokens { - let index = LineIndex::new(src); - let mut ordered: Vec<&Raw> = raws.iter().collect(); - ordered.sort_by_key(|raw| raw.span.start); - - let mut data = Vec::new(); - let mut prev_line = 0; - let mut prev_start = 0; - let mut last_end = 0; - - for raw in ordered { - if raw.span.start < last_end { - continue; - } - let start = offset_to_position(src, &index, raw.span.start); - let end = offset_to_position(src, &index, raw.span.end); - if end.line != start.line || end.character <= start.character { - continue; - } - let delta_line = start.line - prev_line; - let delta_start = if delta_line == 0 { - start.character - prev_start - } else { - start.character - }; - data.push(SemanticToken { - delta_line, - delta_start, - length: end.character - start.character, - token_type: raw.ty.index(), - token_modifiers_bitset: raw.mods, - }); - prev_line = start.line; - prev_start = start.character; - last_end = raw.span.end; - } - - SemanticTokens { - result_id: None, - data, - } -} - -#[cfg(test)] -mod tests { - use super::*; - - /// A decoded token in absolute coordinates, for assertion convenience. - #[derive(Debug, PartialEq, Eq)] - struct Decoded { - line: u32, - start: u32, - len: u32, - ty: SemanticTokenType, - declared: bool, - } - - fn decode(src: &str) -> Vec { - let types = token_types(); - let tokens = semantic_tokens(src); - let mut line = 0; - let mut start = 0; - tokens - .data - .iter() - .map(|t| { - if t.delta_line == 0 { - start += t.delta_start; - } else { - line += t.delta_line; - start = t.delta_start; - } - Decoded { - line, - start, - len: t.length, - ty: types[t.token_type as usize].clone(), - declared: t.token_modifiers_bitset & MOD_DECLARATION != 0, - } - }) - .collect() - } - - /// Finds the decoded token starting at the first occurrence of `needle`. - fn at<'a>(decoded: &'a [Decoded], src: &str, needle: &str) -> &'a Decoded { - let offset = src.find(needle).expect("substring present") as u32; - let line = src[..offset as usize].matches('\n').count() as u32; - let line_start = src[..offset as usize].rfind('\n').map_or(0, |nl| nl + 1) as u32; - let start = offset - line_start; - decoded - .iter() - .find(|d| d.line == line && d.start == start) - .unwrap_or_else(|| panic!("no token at {needle:?}")) - } - - #[test] - fn legend_indices_match_discriminants() { - let types = token_types(); - assert_eq!(types[Sem::Namespace as usize], SemanticTokenType::NAMESPACE); - assert_eq!(types[Sem::Decorator as usize], SemanticTokenType::DECORATOR); - assert_eq!(types.len(), Sem::Decorator as usize + 1); - } - - #[test] - fn node_name_is_a_declared_namespace() { - let src = "//! m\n\npublic system Banking;\n"; - let decoded = decode(src); - let token = at(&decoded, src, "Banking"); - assert_eq!(token.ty, SemanticTokenType::NAMESPACE); - assert!(token.declared); - assert_eq!(token.len, 7); - } - - #[test] - fn keyword_and_data_name_colours() { - let src = "//! m\n\ndata Account { id: uuid }\n"; - let decoded = decode(src); - assert_eq!(at(&decoded, src, "data").ty, SemanticTokenType::KEYWORD); - let account = at(&decoded, src, "Account"); - assert_eq!(account.ty, SemanticTokenType::CLASS); - assert!(account.declared); - assert_eq!(at(&decoded, src, "id").ty, SemanticTokenType::PROPERTY); - assert_eq!(at(&decoded, src, "uuid").ty, SemanticTokenType::TYPE); - } - - #[test] - fn callable_param_type_and_calls() { - let src = "//! m\n\nsystem S {\n run(name: string): uuid {\n return self.alloc(name)\n }\n}\n"; - let decoded = decode(src); - assert_eq!(at(&decoded, src, "run").ty, SemanticTokenType::METHOD); - assert_eq!(at(&decoded, src, "name").ty, SemanticTokenType::PARAMETER); - assert_eq!(at(&decoded, src, "string").ty, SemanticTokenType::TYPE); - assert_eq!(at(&decoded, src, "self").ty, SemanticTokenType::KEYWORD); - // the `.alloc(...)` call segment - assert_eq!(at(&decoded, src, "alloc").ty, SemanticTokenType::METHOD); - } - - #[test] - fn member_call_is_a_method_token() { - // `run` in `Repo.run(x)` is a call segment → coloured as a method. - let src = "//! m\n\nsystem S {\n go() {\n Repo.run(x)\n }\n}\n"; - let decoded = decode(src); - assert_eq!(at(&decoded, src, "run").ty, SemanticTokenType::METHOD); - } - - #[test] - fn macro_name_is_a_decorator() { - let src = "//! m\n\n#[diagram]\nsystem S;\n"; - let decoded = decode(src); - assert_eq!( - at(&decoded, src, "diagram").ty, - SemanticTokenType::DECORATOR - ); - } - - #[test] - fn string_literal_is_a_string() { - let src = "//! m\n\nsystem S {\n f() {\n return Err(\"boom\")\n }\n}\n"; - let decoded = decode(src); - assert_eq!(at(&decoded, src, "\"boom\"").ty, SemanticTokenType::STRING); - assert_eq!(at(&decoded, src, "Err").ty, SemanticTokenType::KEYWORD); - } -} diff --git a/crates/pseudoscript-lsp/src/server.rs b/crates/pseudoscript-lsp/src/server.rs index fec02a6..57523c6 100644 --- a/crates/pseudoscript-lsp/src/server.rs +++ b/crates/pseudoscript-lsp/src/server.rs @@ -1,7 +1,7 @@ //! The tower-lsp server: a workspace-aware document store plus protocol //! plumbing. //! -//! All language logic lives in [`crate::analysis`]; this layer owns the +//! All language logic lives in [`pseudoscript_lsp_core::analysis`]; this layer owns the //! [`Project`] (the loaded `.pds` modules, with open buffers overlaying disk) //! and translates LSP notifications/requests into calls against it. Diagnostics //! are published for every module so cross-file issues surface in the file that @@ -27,8 +27,8 @@ use tower_lsp::lsp_types::{ }; use tower_lsp::{Client, LanguageServer}; -use crate::analysis; use crate::workspace::Project; +use pseudoscript_lsp_core::analysis; /// The `PseudoScript` language server. pub struct Backend { @@ -78,7 +78,7 @@ impl Backend { let index = LineIndex::new(source); Some(Location { uri, - range: crate::convert::span_to_range(source, &index, occ.span), + range: pseudoscript_lsp_core::convert::span_to_range(source, &index, occ.span), }) }) .collect() @@ -227,7 +227,7 @@ impl LanguageServer for Backend { let index = LineIndex::new(target_src); let location = Location { uri: target_uri, - range: crate::convert::span_to_range(target_src, &index, target.span), + range: pseudoscript_lsp_core::convert::span_to_range(target_src, &index, target.span), }; Ok(Some(GotoDefinitionResponse::Scalar(location))) } @@ -309,7 +309,7 @@ impl LanguageServer for Backend { let occurrences = { let mut project = self.project(); let modules = project.module_pairs(); - let offset = crate::convert::position_to_offset(&text, pos.position); + let offset = pseudoscript_lsp_core::convert::position_to_offset(&text, pos.position); analysis::references( project.workspace(), &modules, @@ -330,7 +330,7 @@ impl LanguageServer for Backend { let Some((text, fqn)) = self.active(&pos.text_document.uri) else { return Ok(None); }; - let offset = crate::convert::position_to_offset(&text, pos.position); + let offset = pseudoscript_lsp_core::convert::position_to_offset(&text, pos.position); let spans = { let mut project = self.project(); analysis::highlights(project.workspace(), &fqn, &text, offset) @@ -339,7 +339,7 @@ impl LanguageServer for Backend { let highlights = spans .into_iter() .map(|span| DocumentHighlight { - range: crate::convert::span_to_range(&text, &index, span), + range: pseudoscript_lsp_core::convert::span_to_range(&text, &index, span), kind: Some(DocumentHighlightKind::TEXT), }) .collect(); @@ -368,7 +368,7 @@ impl LanguageServer for Backend { let occurrences = { let mut project = self.project(); let modules = project.module_pairs(); - let offset = crate::convert::position_to_offset(&text, pos.position); + let offset = pseudoscript_lsp_core::convert::position_to_offset(&text, pos.position); analysis::references(project.workspace(), &modules, &fqn, &text, offset, true) }; if occurrences.is_empty() { @@ -384,7 +384,7 @@ impl LanguageServer for Backend { }; let index = LineIndex::new(source); changes.entry(uri).or_default().push(TextEdit { - range: crate::convert::span_to_range(source, &index, occ.span), + range: pseudoscript_lsp_core::convert::span_to_range(source, &index, occ.span), new_text: params.new_name.clone(), }); } diff --git a/crates/pseudoscript-lsp/src/workspace.rs b/crates/pseudoscript-lsp/src/workspace.rs index cdd0321..e774c73 100644 --- a/crates/pseudoscript-lsp/src/workspace.rs +++ b/crates/pseudoscript-lsp/src/workspace.rs @@ -207,7 +207,7 @@ impl Project { diagnostics.extend(static_diagnostics(workspace, &entry.fqn)); ( uri.clone(), - crate::analysis::lsp_diagnostics(&entry.source, &diagnostics), + pseudoscript_lsp_core::analysis::lsp_diagnostics(&entry.source, &diagnostics), ) }) .collect() diff --git a/crates/pseudoscript-lsp/tests/features/semantic_tokens.feature b/crates/pseudoscript-lsp/tests/features/semantic_tokens.feature index 6a227d3..be24240 100644 --- a/crates/pseudoscript-lsp/tests/features/semantic_tokens.feature +++ b/crates/pseudoscript-lsp/tests/features/semantic_tokens.feature @@ -40,14 +40,14 @@ Feature: LSP semantic tokens And the "self" token has type "keyword" And the "alloc" token has type "method" - Scenario: a macro name is a decorator + Scenario: a macro invocation is one decorator span Given the inline source: """ #[diagram] system S; """ When I compute semantic tokens - Then the "diagram" token has type "decorator" + Then the "#[diagram]" token has type "decorator" Scenario: keywords and string literals Given the inline source: diff --git a/crates/pseudoscript-lsp/tests/lsp.rs b/crates/pseudoscript-lsp/tests/lsp.rs index 4371688..7143e9d 100644 --- a/crates/pseudoscript-lsp/tests/lsp.rs +++ b/crates/pseudoscript-lsp/tests/lsp.rs @@ -5,7 +5,7 @@ use std::path::{Path, PathBuf}; use cucumber::{World, given, then, when}; -use pseudoscript_lsp::analysis; +use pseudoscript_lsp_core::analysis; use pseudoscript_model::Workspace; use tower_lsp::lsp_types::{Diagnostic, DiagnosticSeverity, Position, TextEdit}; diff --git a/crates/pseudoscript-model/src/check.rs b/crates/pseudoscript-model/src/check.rs index eb350d0..62826a4 100644 --- a/crates/pseudoscript-model/src/check.rs +++ b/crates/pseudoscript-model/src/check.rs @@ -479,8 +479,46 @@ impl Checker<'_> { // arity. self.check_call_arity(body, owner, &vars); + // §6: a `.method(args)` call names a callable of its receiver's type. + let recv_types = build_receiver_types(callable, body); + self.check_call_members(body, &recv_types); + // §7 (ADR-023): an `if`/`while` condition is boolean. self.check_conditions(body, &vars); + + // §7.1: a binding's annotation must match a determinable initialiser. + self.check_binding_types(body, &vars); + } + + /// §7.1: a binding states its type (`x: T = expr`). Where the initialiser's + /// type is determinable — a literal, marker, `from`, or bare reference — it + /// must match the annotation. Calls, field accesses, `self`, and `::` paths + /// infer to `Unknown` (ADR-022), so the annotation is authoritative there and + /// nothing is flagged. A generic annotation (`Result<…>`/`Option<…>`) is + /// compared only by its constructor, not its inner types. + fn check_binding_types(&mut self, block: &Block, vars: &FxHashMap) { + for_each_stmt(block, &mut |stmt| { + let StmtKind::Assign { name, ty, value } = &stmt.kind else { + return; + }; + // The placeholder type of an untyped-assignment parse error names no + // type; the missing-annotation diagnostic already stands. + if !ty.generics.is_empty() || type_leaf(ty).is_empty() { + return; + } + let found = infer(value, vars); + if !arg_matches(&found, type_leaf(ty), ty.is_array, &self.unions) { + self.error( + value.span, + format!( + "binding `{}` is annotated `{}` but its value is `{}`", + name.name, + type_display(ty), + ty_display(&found) + ), + ); + } + }); } /// §7: an `if`/`while` condition whose type is inferable must be `bool`. @@ -590,6 +628,89 @@ impl Checker<'_> { } } + /// §6: every `.name(args)` call in a body whose receiver's type is statically + /// known names a callable of that type. + fn check_call_members(&mut self, block: &Block, recv_types: &FxHashMap) { + for_each_expr(block, &mut |expr| { + self.check_call_member_at(expr, recv_types); + }); + } + + /// Checks the call segments of one postfix chain. Walks from a typed root — + /// the node a bare path names, or the record a parameter/binding is typed as + /// — resolving each field segment to continue. A call segment MUST name a + /// callable of the running receiver; a record (fields only) rejects every + /// call. Walking stops at a call result, a non-record field, or an unknown + /// receiver — those are not inferred (ADR-022). `self.` calls and `::` paths + /// are owned by `check_self_call_at` / cross-module resolution. + fn check_call_member_at(&mut self, expr: &Expr, recv_types: &FxHashMap) { + let ExprKind::Postfix { base, segments } = &expr.kind else { + return; + }; + // Each chain is processed once, from its `Ref` root; a sub-chain (base is + // itself a `Postfix`) is visited separately by `for_each_expr`. + let Some(mut recv) = self.chain_root_owner(base, recv_types) else { + return; + }; + for seg in segments { + let member = self + .model + .members(&recv) + .iter() + .find(|m| m.name == seg.name.name); + if seg.call_args.is_some() { + if !member.is_some_and(|m| m.kind == MemberKind::Callable) { + let cands: Vec<&str> = self + .model + .members(&recv) + .iter() + .filter(|m| m.kind == MemberKind::Callable) + .map(|m| m.name.as_str()) + .collect(); + let hint = suggest(&seg.name.name, &cands); + self.error( + seg.span, + format!("no method `{}` on `{recv}`{hint}", seg.name.name), + ); + } + return; // a call result's type is not inferred (ADR-022) + } + // A field read: continue only while the field's type names a same-module record. + match member.and_then(|m| param_shape(&m.ty)) { + Some((leaf, false)) if self.is_record(leaf) => recv = leaf.to_owned(), + _ => return, + } + } + } + + /// The receiver type a postfix chain starts from: the node a bare path names + /// (a `data` type is a value form, resolved via its binding instead), or the + /// same-module record a parameter/binding is typed as. `self`-rooted chains + /// and `::` paths return `None` — not checked here. + fn chain_root_owner(&self, base: &Expr, recv_types: &FxHashMap) -> Option { + let ExprKind::Ref(Ref::Path(path)) = &base.kind else { + return None; + }; + if !path.is_simple() { + return None; + } + let name = &path.segments[0].name; + if self + .model + .symbol(name) + .is_some_and(|s| s.kind != SymbolKind::Data) + { + return Some(name.clone()); + } + match recv_types.get(name) { + Some(Ty::Named { + name: ty, + array: false, + }) if self.is_record(ty) => Some(ty.clone()), + _ => None, + } + } + /// §2.2/§3.4: a `.field` read whose receiver is a known same-module `data` /// record (with disclosed fields) must name one of its fields. Black-box /// data, unions, cross-module types, and call/accessor results are not @@ -611,14 +732,19 @@ impl Checker<'_> { && self.is_record(&name) && !self.has_field(&name, &seg.name.name) { - let hint = { - let cands: Vec<&str> = self - .model - .members(&name) - .iter() - .map(|m| m.name.as_str()) - .collect(); - suggest(&seg.name.name, &cands) + // A close real field wins (`.values` typo'd as `.value`); only when + // none is near do we explain a `Result`/`Option` accessor misuse. + let cands: Vec<&str> = self + .model + .members(&name) + .iter() + .map(|m| m.name.as_str()) + .collect(); + let suggestion = suggest(&seg.name.name, &cands); + let hint = if suggestion.is_empty() { + accessor_hint(&seg.name.name, &name) + } else { + suggestion }; self.error( seg.span, @@ -668,7 +794,12 @@ impl Checker<'_> { && self.model.alias(name).is_none() && !self.variant_names.contains(name.as_str()) { - let hint = { + let hint = if name == "void" { + // `void` is a type, not a value: a void callable returns with a + // bare `Ok` (or `return`), never `Ok(void)` (§5.1, §6.1). + "; `void` is a type, not a value — a void result returns bare `Ok` (§6.1)" + .to_owned() + } else { let candidates: Vec<&str> = scope .iter() .copied() @@ -977,9 +1108,32 @@ fn build_vars(callable: &Callable, body: &Block) -> FxHashMap { vars } +/// Each parameter and annotated binding mapped to its *declared* type — the +/// receiver type a later `.method()` chain resolves against. Unlike [`build_vars`], +/// a call-initialised binding keeps its annotation rather than `Unknown`: calls +/// are not inferred (ADR-022), but the declared type names the receiver whose +/// members must exist (§6). Used only by the call-member check. +fn build_receiver_types(callable: &Callable, body: &Block) -> FxHashMap { + let mut types: FxHashMap = callable + .params + .iter() + .map(|p| (p.name.name.clone(), ty_from_ast(&p.ty))) + .collect(); + for_each_stmt(body, &mut |stmt| { + if let StmtKind::Assign { name, ty, .. } = &stmt.kind + && !type_leaf(ty).is_empty() + { + types.insert(name.name.clone(), ty_from_ast(ty)); + } + }); + types +} + fn collect_binding_types(block: &Block, vars: &mut FxHashMap) { for_each_stmt(block, &mut |stmt| match &stmt.kind { - StmtKind::Assign { name, value } => { + StmtKind::Assign { name, value, .. } => { + // The result-flow lattice keeps inferring from the RHS (calls stay + // Unknown, ADR-022); the annotation is validated separately. let ty = infer(value, vars); vars.insert(name.name.clone(), ty); } @@ -1141,6 +1295,26 @@ fn suggest(typed: &str, candidates: &[&str]) -> String { .unwrap_or_default() } +/// A hint when `name` is a `Result`/`Option` accessor (§6) read off a value that +/// is neither — the common cause is a field declared as a plain type that should +/// be `Option`. Empty when `name` is an ordinary (mistyped) field. +fn accessor_hint(name: &str, receiver: &str) -> String { + match name { + "isOk" | "isErr" | "error" => { + format!("; `.{name}` is a `Result` accessor (§6.1) — `{receiver}` is not a `Result`") + } + "isSome" | "isNone" => { + format!( + "; `.{name}` is an `Option` accessor (§6.2) — type the value `Option<{receiver}>` to use it" + ) + } + "value" => { + format!("; `.value` reads a `Result`/`Option` payload (§6) — `{receiver}` is neither") + } + _ => String::new(), + } +} + /// Visits every statement in `block`, descending into nested `if`/`for`/`while` /// blocks, calling `f` on each. The single statement-recursion skeleton the body /// checks share. diff --git a/crates/pseudoscript-model/src/check/result_flow.rs b/crates/pseudoscript-model/src/check/result_flow.rs index a32717d..d6db835 100644 --- a/crates/pseudoscript-model/src/check/result_flow.rs +++ b/crates/pseudoscript-model/src/check/result_flow.rs @@ -66,7 +66,7 @@ fn check_block(block: &Block, env: &mut Bindings, out: &mut Vec) -> fn check_stmt(stmt: &Stmt, env: &mut Bindings, out: &mut Vec) -> bool { match &stmt.kind { - StmtKind::Assign { name, value } => { + StmtKind::Assign { name, value, .. } => { check_expr(value, env, out); // A fresh binding starts Unknown; we only learn its branch through a // subsequent `if` guard. diff --git a/crates/pseudoscript-model/src/complete.rs b/crates/pseudoscript-model/src/complete.rs new file mode 100644 index 0000000..1863d86 --- /dev/null +++ b/crates/pseudoscript-model/src/complete.rs @@ -0,0 +1,500 @@ +//! Context-aware completion — the shared engine behind both the LSP +//! (`pseudoscript-lsp`) and the web IDE (`pseudoscript-wasm`). +//! +//! The completion context is read from the token immediately left of the caret: +//! +//! - after `.` → the base node's callables and fields; +//! - after `::` → the named module's (public) symbols; +//! - after `#[` → the built-in macros; +//! - after `:` or `<` (type position) → primitive types, `Result`, and every +//! declared type; +//! - otherwise → keywords, this module's symbols and aliases, and the other +//! workspace modules (to start a cross-module reference). +//! +//! The caller filters the returned set against the prefix being typed, so the +//! full candidate list is offered. Positions are byte offsets, so the engine is +//! adapter-neutral: the LSP maps to `lsp_types`, the IDE serialises to JSON. + +use pseudoscript_syntax::{Token, TokenKind, tokenize}; +use serde::Serialize; + +use crate::resolve::{enclosing_node, module_of}; +use crate::{BUILTIN_MACROS, MemberKind, SymbolKind, Workspace}; + +/// What a completion candidate denotes — drives the icon each surface renders. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)] +#[serde(rename_all = "lowercase")] +pub enum CompletionKind { + /// A callable member reached through `.`. + Method, + /// A record field reached through `.`. + Field, + /// A language keyword. + Keyword, + /// A built-in macro (`#[...]`). + Macro, + /// A primitive type or `Result`. + Type, + /// A `data` declaration. + Class, + /// A node declaration (system / container / component / person). + Module, + /// An alias. + Reference, +} + +/// One completion candidate: its insert text, what it is, and a one-line detail. +#[derive(Debug, Clone, PartialEq, Eq, Serialize)] +pub struct CompletionItem { + /// The text offered (and inserted). + pub label: String, + /// What the candidate denotes. + pub kind: CompletionKind, + /// A one-line detail (signature, fqn, or category). + pub detail: String, +} + +/// Completion candidates for byte `offset` in module `from_fqn`'s `src`. +#[must_use] +pub fn completion(ws: &Workspace, from_fqn: &str, src: &str, offset: u32) -> Vec { + let tokens = tokenize(src); + let trigger = governing_trigger(&tokens, offset); + + match trigger.map(|i| (i, tokens[i].kind)) { + Some((i, TokenKind::Dot)) => member_items(ws, from_fqn, src, &tokens, i), + Some((i, TokenKind::ColonColon)) => path_items(ws, from_fqn, &tokens, i), + Some((_, TokenKind::HashLBracket)) => macro_items(), + // A built-in macro's argument is a type path (`#[onevent(Event)]`). + Some((i, TokenKind::LParen)) if is_macro_arg(&tokens, i) => type_items(ws), + Some((_, TokenKind::Colon | TokenKind::LAngle)) => type_items(ws), + // A `for` parent (or feature target) names a node, possibly cross-module. + Some((_, TokenKind::KwFor)) => node_items(ws, from_fqn), + _ => general_items(ws, from_fqn), + } +} + +/// Visible node declarations (system / container / component / person) plus the +/// other modules — for a `for` parent or feature target. +fn node_items(ws: &Workspace, from_fqn: &str) -> Vec { + let nodes = ws + .symbols() + .filter(|s| { + !matches!(s.kind, SymbolKind::Data) && (module_of(&s.fqn) == from_fqn || s.is_public) + }) + .map(|s| item(&s.name, symbol_kind(s.kind), &s.fqn)); + let modules = ws + .modules() + .iter() + .filter(|m| m.fqn != from_fqn) + .map(|m| item(&m.fqn, CompletionKind::Module, "module")); + nodes.chain(modules).collect() +} + +/// Whether `tokens[lparen]` opens a built-in macro's argument list (`#[name(`). +fn is_macro_arg(tokens: &[Token], lparen: usize) -> bool { + lparen >= 2 + && tokens[lparen - 1].kind == TokenKind::Ident + && tokens[lparen - 2].kind == TokenKind::HashLBracket +} + +/// Index of the token whose kind governs completion at `offset`. +/// +/// The trigger is the rightmost token ending at or before the caret — except +/// for a partial identifier typed *under* the caret, which ends exactly at +/// `offset` (`span.end == offset`). That identifier is the prefix the caller +/// filters on, not the context, so its predecessor is the real trigger. A caret +/// strictly inside an identifier (`span.end > offset`) is already excluded by +/// the `<= offset` bound, so only the boundary case needs skipping. +fn governing_trigger(tokens: &[Token], offset: u32) -> Option { + let last = tokens.iter().rposition(|t| t.span.end <= offset)?; + if tokens[last].kind == TokenKind::Ident && tokens[last].span.end == offset { + last.checked_sub(1) + } else { + Some(last) + } +} + +/// Callables and fields of the node named by the base before `tokens[dot]`. +fn member_items( + ws: &Workspace, + from_fqn: &str, + src: &str, + tokens: &[Token], + dot: usize, +) -> Vec { + // The token-based path covers `self.`, `Module::Node.`, and a bare binding. + // A multi-step chain (`Repo.fetch(id).value.`) has no single base token, so + // fall back to typing the receiver expression at the cursor via the AST. + let owner = owner_before(ws, from_fqn, tokens, dot) + .or_else(|| crate::infer::owner_at_dot(ws, from_fqn, src, tokens[dot].span.start)); + let Some((owner_module, owner_name)) = owner else { + return Vec::new(); + }; + let Some(entry) = ws.module(&owner_module) else { + return Vec::new(); + }; + entry + .model + .members(&owner_name) + .iter() + .map(|m| { + let kind = match m.kind { + MemberKind::Callable => CompletionKind::Method, + MemberKind::Field => CompletionKind::Field, + }; + item(&m.name, kind, &m.detail) + }) + .collect() +} + +/// The `(module, node-name)` the base token before `tokens[dot]` denotes: +/// `self`'s enclosing node, a `::`-qualified node in another module +/// (`identity::sessions.`), or an in-scope node name in this module. +fn owner_before( + ws: &Workspace, + from_fqn: &str, + tokens: &[Token], + dot: usize, +) -> Option<(String, String)> { + let base = tokens.get(dot.checked_sub(1)?)?; + match base.kind { + TokenKind::KwSelf => { + let node = enclosing_node(&ws.module(from_fqn)?.ast, base.span.start)?; + Some((from_fqn.to_owned(), node)) + } + // `a::b::Node.` — the base is qualified, so it names a symbol in the + // module its qualifiers spell, not this one. Offered only when public + // (or in this module), mirroring `::` path resolution (§8.2). + TokenKind::Ident if dot >= 2 && tokens[dot - 2].kind == TokenKind::ColonColon => { + let module = module_prefix(tokens, dot - 2); + let symbol = ws.module(&module)?.model.symbol(&base.text)?; + (module == from_fqn || symbol.is_public).then(|| (module, symbol.name.clone())) + } + TokenKind::Ident => { + let module = ws.module(from_fqn)?; + if let Some(symbol) = module.model.symbol(&base.text) { + return Some((module_of(&symbol.fqn).to_owned(), symbol.name.clone())); + } + // Not a declared node — a local binding (`a = Repo.fetch(id); a.`): + // resolve its inferred type to the node whose members it offers. + let local = crate::infer::binding_type_at(ws, from_fqn, &base.text)?; + crate::infer::type_owner(ws, from_fqn, &local.ty) + } + _ => None, + } +} + +/// Symbols of the module named by the `::` path ending at `tokens[ccolon]`. +/// A cross-module suggestion is offered only when `public` (§8.2). +fn path_items( + ws: &Workspace, + from_fqn: &str, + tokens: &[Token], + ccolon: usize, +) -> Vec { + let prefix = module_prefix(tokens, ccolon); + ws.symbols() + .filter(|s| module_of(&s.fqn) == prefix && (prefix == from_fqn || s.is_public)) + .map(|s| item(&s.name, symbol_kind(s.kind), &s.fqn)) + .collect() +} + +/// The `::`-joined module path written immediately before `tokens[ccolon]`. +fn module_prefix(tokens: &[Token], ccolon: usize) -> String { + let mut segments = Vec::new(); + let mut cursor = ccolon.checked_sub(1); + while let Some(i) = cursor { + if tokens[i].kind != TokenKind::Ident { + break; + } + segments.push(tokens[i].text.as_str()); + cursor = match i.checked_sub(1) { + Some(j) if tokens[j].kind == TokenKind::ColonColon => i.checked_sub(2), + _ => None, + }; + } + segments.reverse(); + segments.join("::") +} + +/// The built-in macros (`#[...]`). +fn macro_items() -> Vec { + BUILTIN_MACROS + .iter() + .map(|m| item(m, CompletionKind::Macro, "built-in macro")) + .collect() +} + +/// Primitive types, `Result`, and every declared node/data type. +fn type_items(ws: &Workspace) -> Vec { + let generics = ["Result", "Option"] + .into_iter() + .map(|g| item(g, CompletionKind::Type, "built-in generic")); + let primitives = TokenKind::PRIMITIVE_TYPES + .iter() + .map(|t| item(t, CompletionKind::Type, "primitive type")) + .chain(generics); + let declared = ws + .symbols() + .map(|s| item(&s.name, symbol_kind(s.kind), &s.fqn)); + primitives.chain(declared).collect() +} + +/// Keywords, this module's own symbols and aliases, and the other modules in the +/// workspace (so a cross-module reference can be started — pick the module, then +/// `::` drills into its public symbols). +fn general_items(ws: &Workspace, from_fqn: &str) -> Vec { + let keywords = TokenKind::KEYWORDS + .iter() + .map(|k| item(k, CompletionKind::Keyword, "keyword")); + let modules = ws + .modules() + .iter() + .filter(|m| m.fqn != from_fqn) + .map(|m| item(&m.fqn, CompletionKind::Module, "module")); + let Some(entry) = ws.module(from_fqn) else { + return keywords.chain(modules).collect(); + }; + let symbols = entry + .model + .symbols() + .map(|s| item(&s.name, symbol_kind(s.kind), &s.fqn)); + let aliases = entry + .model + .aliases() + .map(|(name, a)| item(name, CompletionKind::Reference, &a.target)); + keywords + .chain(symbols) + .chain(aliases) + .chain(modules) + .collect() +} + +/// The completion kind for a declared symbol. +fn symbol_kind(kind: SymbolKind) -> CompletionKind { + match kind { + SymbolKind::Data => CompletionKind::Class, + _ => CompletionKind::Module, + } +} + +/// Builds a labelled completion item with a detail string. +fn item(label: &str, kind: CompletionKind, detail: &str) -> CompletionItem { + CompletionItem { + label: label.to_owned(), + kind, + detail: detail.to_owned(), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use pseudoscript_syntax::parse; + + fn workspace(modules: &[(&str, &str)]) -> Workspace { + Workspace::build( + modules + .iter() + .map(|(fqn, src)| ((*fqn).to_owned(), parse(src).ast)), + ) + } + + /// Completion labels at byte `offset` in module `from`. + fn labels_at(ws: &Workspace, from: &str, src: &str, offset: u32) -> Vec { + completion(ws, from, src, offset) + .into_iter() + .map(|c| c.label) + .collect() + } + + #[test] + fn members_after_qualified_node_path() { + // `identity::sessions.req` — a `::`-qualified node in another module; + // its members must complete (regression: only the bare name was tried + // in the current module). + let mods = [ + ( + "identity", + "//! identity\n\npublic system sessions {\n requireOrganizer(): void;\n}\n", + ), + ( + "m", + "//! m\n\nsystem S {\n run() {\n identity::sessions.req\n }\n}\n", + ), + ]; + let ws = workspace(&mods); + let src = mods[1].1; + let offset = (src.find("sessions.req").unwrap() + "sessions.req".len()) as u32; + let labels = labels_at(&ws, "m", src, offset); + assert!( + labels.contains(&"requireOrganizer".to_owned()), + "{labels:?}" + ); + // not the general keyword set + assert!( + !labels.contains(&"system".to_owned()), + "general scope leaked: {labels:?}" + ); + } + + #[test] + fn members_after_local_binding() { + // `a: Account = Repo.fetch(x); a.` — the binding's declared type drives + // member completion, even though `a` is not a declared node. + let src = "//! m\n\ndata Account { id: uuid, owner: string }\n\nsystem Repo {\n fetch(x: uuid): Account;\n}\n\nsystem S {\n run() {\n a: Account = Repo.fetch(x)\n a.\n }\n}\n"; + let ws = workspace(&[("m", src)]); + let offset = (src.find("a.\n").unwrap() + 2) as u32; + let labels = labels_at(&ws, "m", src, offset); + assert!(labels.contains(&"id".to_owned()), "{labels:?}"); + assert!(labels.contains(&"owner".to_owned()), "{labels:?}"); + } + + #[test] + fn option_offered_in_type_position() { + let src = "//! m\n\ndata D { x: }\n"; + let ws = workspace(&[("m", src)]); + let offset = (src.find("x:").unwrap() + 2) as u32; + let labels = labels_at(&ws, "m", src, offset); + assert!(labels.contains(&"Option".to_owned()), "{labels:?}"); + assert!(labels.contains(&"Result".to_owned()), "{labels:?}"); + } + + #[test] + fn members_after_self_dot() { + let src = "//! m\n\nsystem S {\n run() {\n self.\n }\n helper(x: number): uuid;\n}\n"; + let ws = workspace(&[("m", src)]); + let offset = (src.find("self.").unwrap() + "self.".len()) as u32; + let labels = labels_at(&ws, "m", src, offset); + assert!(labels.contains(&"helper".to_owned()), "{labels:?}"); + assert!(labels.contains(&"run".to_owned()), "{labels:?}"); + } + + #[test] + fn types_after_colon() { + let src = "//! m\n\ndata D { x: }\n"; + let ws = workspace(&[("m", src)]); + let offset = (src.find("x:").unwrap() + 2) as u32; + let labels = labels_at(&ws, "m", src, offset); + assert!(labels.contains(&"number".to_owned()), "{labels:?}"); + assert!(labels.contains(&"Result".to_owned()), "{labels:?}"); + assert!(labels.contains(&"D".to_owned()), "{labels:?}"); + } + + #[test] + fn macros_after_hash_bracket() { + let src = "//! m\n\n#[\nsystem S;\n"; + let ws = workspace(&[("m", src)]); + let offset = (src.find("#[").unwrap() + 2) as u32; + let labels = labels_at(&ws, "m", src, offset); + assert!(labels.contains(&"http".to_owned()), "{labels:?}"); + assert!(labels.contains(&"onevent".to_owned()), "{labels:?}"); + } + + #[test] + fn public_symbols_after_module_path() { + let mods = [ + ("a", "//! a\n\npublic system Svc;\n\nsystem Hidden;\n"), + ("b", "//! b\n\ncontainer C for a::\n"), + ]; + let ws = workspace(&mods); + let src = mods[1].1; + let offset = (src.find("a::").unwrap() + 3) as u32; + let labels = labels_at(&ws, "b", src, offset); + assert!(labels.contains(&"Svc".to_owned()), "{labels:?}"); + assert!(!labels.contains(&"Hidden".to_owned()), "{labels:?}"); + } + + #[test] + fn general_offers_other_modules() { + // At the root / a reference position, the other workspace modules are + // suggested (so a cross-module reference can be started), alongside + // keywords — but not this module itself. + let mods = [ + ("context", "//! context\n\npublic system AcmeTickets;\n"), + ("m", "//! m\n\n"), + ]; + let ws = workspace(&mods); + let src = mods[1].1; + let labels = labels_at(&ws, "m", src, src.len() as u32); + assert!(labels.contains(&"context".to_owned()), "{labels:?}"); + assert!(labels.contains(&"system".to_owned()), "{labels:?}"); + assert!( + !labels.contains(&"m".to_owned()), + "own module excluded: {labels:?}" + ); + } + + #[test] + fn keywords_in_general_position() { + let src = "//! m\n\n"; + let ws = workspace(&[("m", src)]); + let labels = labels_at(&ws, "m", src, src.len() as u32); + assert!(labels.contains(&"system".to_owned()), "{labels:?}"); + assert!(labels.contains(&"public".to_owned()), "{labels:?}"); + } + + // With a prefix typed, the caret sits at the end of a partial identifier. + // Each narrowing context must stay scoped — the trigger before the prefix + // governs — and must not leak the general keyword set. + + #[test] + fn members_after_self_dot_with_prefix() { + let src = + "//! m\n\nsystem S {\n run() {\n self.he\n }\n helper(x: number): uuid;\n}\n"; + let ws = workspace(&[("m", src)]); + let offset = (src.find("self.he").unwrap() + "self.he".len()) as u32; + let labels = labels_at(&ws, "m", src, offset); + assert!(labels.contains(&"helper".to_owned()), "{labels:?}"); + assert!(labels.contains(&"run".to_owned()), "{labels:?}"); + assert!( + !labels.contains(&"system".to_owned()), + "general scope leaked: {labels:?}" + ); + } + + #[test] + fn types_after_colon_with_prefix() { + let src = "//! m\n\ndata D { x: numb }\n"; + let ws = workspace(&[("m", src)]); + let offset = (src.find("numb").unwrap() + "numb".len()) as u32; + let labels = labels_at(&ws, "m", src, offset); + assert!(labels.contains(&"number".to_owned()), "{labels:?}"); + assert!(labels.contains(&"D".to_owned()), "{labels:?}"); + assert!( + !labels.contains(&"system".to_owned()), + "general scope leaked: {labels:?}" + ); + } + + #[test] + fn macros_after_hash_bracket_with_prefix() { + let src = "//! m\n\n#[ht\nsystem S;\n"; + let ws = workspace(&[("m", src)]); + let offset = (src.find("#[ht").unwrap() + "#[ht".len()) as u32; + let labels = labels_at(&ws, "m", src, offset); + assert!(labels.contains(&"http".to_owned()), "{labels:?}"); + assert!( + !labels.contains(&"system".to_owned()), + "general scope leaked: {labels:?}" + ); + } + + #[test] + fn public_symbols_after_module_path_with_prefix() { + let mods = [ + ("a", "//! a\n\npublic system Svc;\n\nsystem Hidden;\n"), + ("b", "//! b\n\ncontainer C for a::Sv\n"), + ]; + let ws = workspace(&mods); + let src = mods[1].1; + let offset = (src.find("a::Sv").unwrap() + "a::Sv".len()) as u32; + let labels = labels_at(&ws, "b", src, offset); + assert!(labels.contains(&"Svc".to_owned()), "{labels:?}"); + assert!(!labels.contains(&"Hidden".to_owned()), "{labels:?}"); + assert!( + !labels.contains(&"system".to_owned()), + "general scope leaked: {labels:?}" + ); + } +} diff --git a/crates/pseudoscript-model/src/fold.rs b/crates/pseudoscript-model/src/fold.rs new file mode 100644 index 0000000..f355255 --- /dev/null +++ b/crates/pseudoscript-model/src/fold.rs @@ -0,0 +1,162 @@ +//! Foldable source regions — the shared engine behind the LSP +//! (`pseudoscript-lsp`) and the web IDE (`pseudoscript-wasm`). +//! +//! Every brace-delimited declaration (a node or `data` record) and every +//! statement block is foldable; brace-less `data = | …` unions and black-box +//! `;` declarations are not. Ranges run from the construct's name/header through +//! its closing brace — never over the leading doc comments — in absolute byte +//! offsets; the LSP maps them to line-based `FoldingRange`s, the IDE to editor +//! offsets. + +use pseudoscript_syntax::{Span, ast, parse}; +use serde::Serialize; + +/// A foldable region in absolute byte offsets (from the construct's name/header +/// through its closing brace). +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)] +pub struct FoldRange { + /// Start byte offset of the construct. + pub start: u32, + /// End byte offset of the construct. + pub end: u32, +} + +/// The foldable regions of `src`: every multi-line declaration and statement +/// block. Order follows source position of the collected spans. +#[must_use] +pub fn folding_ranges(src: &str) -> Vec { + let module = parse(src).ast; + let mut spans = Vec::new(); + for item in &module.items { + if let ast::Item::Decl(decl) = item { + collect_decl_spans(decl, &mut spans); + } + } + spans + .into_iter() + .map(|s| FoldRange { + start: s.start, + end: s.end, + }) + .collect() +} + +/// Collects the foldable span of a *disclosed* declaration (one with a `{ }` +/// body) and any blocks nested in it. A black-box `;` declaration has nothing +/// to fold; a brace-less `data = | …` union is not a block fold. +/// +/// The span runs from the declaration's *name* (the header line) to its end, so +/// the fold keeps the header and any leading `///` doc comments visible — +/// `decl.span` itself reaches back over that leading trivia. +fn collect_decl_spans(decl: &ast::Decl, out: &mut Vec) { + match &decl.kind { + ast::DeclKind::Person(node) + | ast::DeclKind::System(node) + | ast::DeclKind::Container(node) + | ast::DeclKind::Component(node) => { + let Some(body) = &node.body else { return }; + out.push(head_span(node.name.span, decl.span)); + for member in body { + match member { + ast::BodyMember::Decl(inner) => collect_decl_spans(inner, out), + ast::BodyMember::Callable(callable) => { + if let Some(block) = &callable.body { + collect_block_spans(block, out); + } + } + } + } + } + // Only a brace-delimited record folds; a `| …` union has no body block. + ast::DeclKind::Data(data) => { + if matches!(data.body, ast::DataBody::Record(_)) { + out.push(head_span(data.name.span, decl.span)); + } + } + } +} + +/// A fold span from the start of `name` to the end of `decl`, excluding the +/// leading doc comments and blank lines `decl.span` reaches back over. +fn head_span(name: Span, decl: Span) -> Span { + Span { + start: name.start, + end: decl.end, + } +} + +/// Collects a block's span and the spans of any nested control-flow blocks. +fn collect_block_spans(block: &ast::Block, out: &mut Vec) { + out.push(block.span); + for stmt in &block.stmts { + match &stmt.kind { + ast::StmtKind::If { + then_block, + else_block, + .. + } => { + collect_block_spans(then_block, out); + if let Some(block) = else_block { + collect_block_spans(block, out); + } + } + ast::StmtKind::For { body, .. } | ast::StmtKind::While { body, .. } => { + collect_block_spans(body, out); + } + _ => {} + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn folds_disclosed_node_and_nested_block() { + let src = "//! m\n\nsystem S {\n run() {\n return self\n }\n}\n"; + let ranges = folding_ranges(src); + // the system declaration and the callable's block + assert!(ranges.len() >= 2, "{ranges:?}"); + let outer_close = (src.rfind('}').unwrap() + 1) as u32; + // the widest range covers the whole disclosed system, brace to brace + assert!( + ranges + .iter() + .any(|r| r.start <= src.find('{').unwrap() as u32 && r.end >= outer_close), + "{ranges:?}" + ); + } + + #[test] + fn black_box_decl_has_no_fold() { + let src = "//! m\n\nsystem S;\n"; + assert!(folding_ranges(src).is_empty()); + } + + #[test] + fn fold_starts_at_the_declaration_not_its_doc_comment() { + // A leading `///` doc comment (and the blank line above it) must stay + // outside the fold — it is not swallowed into the body. + let src = "//! m\n\n/// doc.\npublic data D {\n x: number\n}\n"; + let ranges = folding_ranges(src); + assert_eq!(ranges.len(), 1, "{ranges:?}"); + // the fold begins at `public data D`, after the doc comment + let decl = src.find("public data D").unwrap() as u32; + let doc = src.find("/// doc.").unwrap() as u32; + assert!( + ranges[0].start >= decl, + "fold reaches into the doc comment: {ranges:?}" + ); + assert!(ranges[0].start > doc, "{ranges:?}"); + } + + #[test] + fn brace_less_union_does_not_fold() { + let src = "//! m\n\npublic data U =\n | A\n | B\n"; + assert!( + folding_ranges(src).is_empty(), + "a `| …` union is not a block fold" + ); + } +} diff --git a/crates/pseudoscript-model/src/graph.rs b/crates/pseudoscript-model/src/graph.rs index c4df5b9..66d34cf 100644 --- a/crates/pseudoscript-model/src/graph.rs +++ b/crates/pseudoscript-model/src/graph.rs @@ -275,6 +275,10 @@ pub struct Scenario { pub name: String, /// The target node's FQN (canonicalised; as written if it does not resolve). pub target_fqn: String, + /// The FQN of the module that declares the feature. + pub module: String, + /// Source span of the feature's name (a host's go-to-definition target). + pub span: Span, /// Documentation lifted from the feature's `///` block. pub doc: NodeDoc, /// The ordered given/when/then steps. @@ -405,6 +409,8 @@ impl Builder<'_> { self.graph.scenarios.push(Scenario { name: feature.name.name.clone(), target_fqn, + module: module.to_owned(), + span: feature.name.span, doc: node_doc(&feature.doc), steps, }); diff --git a/crates/pseudoscript-model/src/infer.rs b/crates/pseudoscript-model/src/infer.rs new file mode 100644 index 0000000..ba2cbf9 --- /dev/null +++ b/crates/pseudoscript-model/src/infer.rs @@ -0,0 +1,382 @@ +//! Local-binding types and right-hand-side inference, for hover and completion. +//! +//! A binding's type is its explicit annotation (`x: T = expr`, §7.1), so +//! [`local_types`]/[`binding_type_at`] read the annotation directly. Inference +//! from the right-hand side is still needed elsewhere: a `for` binding's element +//! type, the type of a chain receiver mid-expression ([`owner_at_dot`]), and +//! validating an annotation against its initialiser. Inference is best-effort — +//! an expression it can't type yields nothing rather than a guess. + +use crate::{Workspace, ast}; +use pseudoscript_syntax::Span; + +use crate::resolve::{enclosing_node, resolve_owner}; + +/// An inferred local binding: its name, the span of that name, and its type. +pub struct LocalType { + pub name: String, + pub name_span: Span, + pub ty: String, +} + +/// Every typed local binding in module `from_fqn` (assignments whose right-hand +/// side has an inferable type). +#[must_use] +pub fn local_types(ws: &Workspace, from_fqn: &str) -> Vec { + let Some(entry) = ws.module(from_fqn) else { + return Vec::new(); + }; + let mut out = Vec::new(); + for item in &entry.ast.items { + if let ast::Item::Decl(decl) = item { + walk_decl(ws, from_fqn, decl, &mut out); + } + } + out +} + +/// The inferred type of the binding named by the identifier at `offset`, with +/// its name — for hover. Matches by binding name, so a use resolves to its +/// declaration's inferred type. +#[must_use] +pub fn binding_type_at(ws: &Workspace, from_fqn: &str, name: &str) -> Option { + local_types(ws, from_fqn) + .into_iter() + .find(|lt| lt.name == name) +} + +fn walk_decl(ws: &Workspace, from_fqn: &str, decl: &ast::Decl, out: &mut Vec) { + let (ast::DeclKind::Person(node) + | ast::DeclKind::System(node) + | ast::DeclKind::Container(node) + | ast::DeclKind::Component(node)) = &decl.kind + else { + return; + }; + for member in node.body.iter().flatten() { + match member { + ast::BodyMember::Callable(callable) => { + if let Some(block) = &callable.body { + walk_block(ws, from_fqn, block, out); + } + } + ast::BodyMember::Decl(inner) => walk_decl(ws, from_fqn, inner, out), + } + } +} + +fn walk_block(ws: &Workspace, from_fqn: &str, block: &ast::Block, out: &mut Vec) { + for stmt in &block.stmts { + match &stmt.kind { + ast::StmtKind::Assign { name, ty, .. } => { + // A binding's type is its explicit annotation (§7.1). The empty + // placeholder of an untyped assignment renders empty — skip it. + let rendered = crate::model::render_type(ty); + if !rendered.is_empty() { + out.push(LocalType { + name: name.name.clone(), + name_span: name.span, + ty: rendered, + }); + } + } + ast::StmtKind::For { + binding, + iter, + body, + } => { + // `for (x in xs)` binds `x` to the element type of an array `xs`. + if let Some(ty) = expr_type(ws, from_fqn, iter) + && let Some(element) = ty.strip_suffix("[]") + { + out.push(LocalType { + name: binding.name.clone(), + name_span: binding.span, + ty: element.to_owned(), + }); + } + walk_block(ws, from_fqn, body, out); + } + ast::StmtKind::If { + then_block, + else_block, + .. + } => { + walk_block(ws, from_fqn, then_block, out); + if let Some(block) = else_block { + walk_block(ws, from_fqn, block, out); + } + } + ast::StmtKind::While { body, .. } => walk_block(ws, from_fqn, body, out), + ast::StmtKind::Return(_) | ast::StmtKind::Expr(_) => {} + } + } +} + +/// The inferred type of an expression, or `None` when it can't be typed — +/// a call's return type, a field access, a `from`, or a literal. +fn expr_type(ws: &Workspace, from_fqn: &str, expr: &ast::Expr) -> Option { + match &expr.kind { + ast::ExprKind::Literal(ast::Literal::String { .. }) => Some("string".to_owned()), + ast::ExprKind::Literal(ast::Literal::Number { .. }) => Some("number".to_owned()), + ast::ExprKind::Literal(ast::Literal::Bool { .. }) => Some("bool".to_owned()), + ast::ExprKind::Paren(inner) => expr_type(ws, from_fqn, inner), + // `T from { .. }` produces a value of the named type. + ast::ExprKind::From { ty, .. } => ty.segments.last().map(|seg| seg.name.clone()), + ast::ExprKind::Postfix { base, segments } => postfix_type(ws, from_fqn, base, segments), + _ => None, + } +} + +/// The type of a postfix chain: walk each `.member`, the result is the last +/// member's type. Each non-final member's type must itself name a node/data so +/// the chain can continue. +fn postfix_type( + ws: &Workspace, + from_fqn: &str, + base: &ast::Expr, + segments: &[ast::PostfixSeg], +) -> Option { + let mut owner = base_owner(ws, from_fqn, base)?; + let mut result = None; + for (i, seg) in segments.iter().enumerate() { + let member_ty = ws + .module(&owner.0)? + .model + .members(&owner.1) + .iter() + .find(|m| m.name == seg.name.name)? + .ty + .clone(); + result = Some(member_ty.clone()); + if i + 1 < segments.len() { + owner = type_owner(ws, from_fqn, &member_ty)?; + } + } + result +} + +/// The node/data owner a postfix base denotes: `self`'s enclosing node, or the +/// node/data a path names. +fn base_owner(ws: &Workspace, from_fqn: &str, base: &ast::Expr) -> Option<(String, String)> { + match &base.kind { + ast::ExprKind::Ref(ast::Ref::SelfNode(span)) => { + let node = enclosing_node(&ws.module(from_fqn)?.ast, span.start)?; + Some((from_fqn.to_owned(), node)) + } + ast::ExprKind::Ref(ast::Ref::Path(path)) => { + let segments: Vec<&str> = path.segments.iter().map(|s| s.name.as_str()).collect(); + resolve_owner(ws, from_fqn, &segments).or_else(|| { + // A chain rooted at a local binding: `acc.balance` where `acc` + // was bound earlier. Resolve the binding's type, then its owner. + if let [name] = segments.as_slice() { + let local = binding_type_at(ws, from_fqn, name)?; + type_owner(ws, from_fqn, &local.ty) + } else { + None + } + }) + } + ast::ExprKind::Paren(inner) => base_owner(ws, from_fqn, inner), + _ => None, + } +} + +/// The node/data owner of the receiver whose trailing `.` sits at byte `dot` — +/// member completion on a chain (`Repo.fetch(id).value.` resolves the type of +/// `value`, so its members can be offered). Parses `src`, locates the postfix +/// chain straddling the cursor, and walks the segments left of it. Returns +/// `None` when the receiver can't be typed (the caller then offers nothing). +#[must_use] +pub fn owner_at_dot( + ws: &Workspace, + from_fqn: &str, + src: &str, + dot: u32, +) -> Option<(String, String)> { + let module = pseudoscript_syntax::parse(src).ast; + module.items.iter().find_map(|item| match item { + ast::Item::Decl(decl) => decl_owner_at(ws, from_fqn, decl, dot), + ast::Item::Alias(_) | ast::Item::Feature(_) => None, + }) +} + +fn decl_owner_at( + ws: &Workspace, + from_fqn: &str, + decl: &ast::Decl, + dot: u32, +) -> Option<(String, String)> { + let (ast::DeclKind::Person(node) + | ast::DeclKind::System(node) + | ast::DeclKind::Container(node) + | ast::DeclKind::Component(node)) = &decl.kind + else { + return None; + }; + node.body.iter().flatten().find_map(|member| match member { + ast::BodyMember::Callable(callable) => callable + .body + .as_ref() + .and_then(|block| block_owner_at(ws, from_fqn, block, dot)), + ast::BodyMember::Decl(inner) => decl_owner_at(ws, from_fqn, inner, dot), + }) +} + +fn block_owner_at( + ws: &Workspace, + from_fqn: &str, + block: &ast::Block, + dot: u32, +) -> Option<(String, String)> { + block.stmts.iter().find_map(|stmt| match &stmt.kind { + ast::StmtKind::Assign { value, .. } => expr_owner_at(ws, from_fqn, value, dot), + ast::StmtKind::Return(Some(e)) | ast::StmtKind::Expr(e) => { + expr_owner_at(ws, from_fqn, e, dot) + } + ast::StmtKind::Return(None) => None, + ast::StmtKind::If { + cond, + then_block, + else_block, + } => expr_owner_at(ws, from_fqn, cond, dot) + .or_else(|| block_owner_at(ws, from_fqn, then_block, dot)) + .or_else(|| { + else_block + .as_ref() + .and_then(|b| block_owner_at(ws, from_fqn, b, dot)) + }), + ast::StmtKind::For { iter, body, .. } => expr_owner_at(ws, from_fqn, iter, dot) + .or_else(|| block_owner_at(ws, from_fqn, body, dot)), + ast::StmtKind::While { cond, body } => expr_owner_at(ws, from_fqn, cond, dot) + .or_else(|| block_owner_at(ws, from_fqn, body, dot)), + }) +} + +fn expr_owner_at( + ws: &Workspace, + from_fqn: &str, + expr: &ast::Expr, + dot: u32, +) -> Option<(String, String)> { + match &expr.kind { + ast::ExprKind::Postfix { base, segments } => { + // The cursor may sit inside the base or a call argument's own chain — + // descend there first; those are more specific than this chain. + if let Some(owner) = expr_owner_at(ws, from_fqn, base, dot) { + return Some(owner); + } + for seg in segments { + for arg in seg.call_args.iter().flatten() { + if let Some(owner) = expr_owner_at(ws, from_fqn, arg, dot) { + return Some(owner); + } + } + } + // The receiver is the base plus the segments whose name begins left + // of the cursor; the trailing `.` sits past it, before the next name. + let k = segments + .iter() + .take_while(|s| s.name.span.start < dot) + .count(); + let recv_end = if k == 0 { + base.span.end + } else { + segments[k - 1].span.end + }; + let next_start = segments.get(k).map(|s| s.name.span.start); + if recv_end <= dot && next_start.is_none_or(|ns| dot < ns) && dot <= expr.span.end { + let mut owner = base_owner(ws, from_fqn, base)?; + for seg in &segments[..k] { + let ty = ws + .module(&owner.0)? + .model + .members(&owner.1) + .iter() + .find(|m| m.name == seg.name.name)? + .ty + .clone(); + owner = type_owner(ws, from_fqn, &ty)?; + } + return Some(owner); + } + None + } + ast::ExprKind::Paren(inner) | ast::ExprKind::Unary { expr: inner, .. } => { + expr_owner_at(ws, from_fqn, inner, dot) + } + ast::ExprKind::Marker { + payload: Some(p), .. + } => expr_owner_at(ws, from_fqn, p, dot), + ast::ExprKind::From { sources, .. } => sources + .iter() + .find_map(|s| expr_owner_at(ws, from_fqn, s, dot)), + _ => None, + } +} + +/// The node/data named by a type string (`Token[]` → `Token`, `a::T` → `a::T`), +/// for continuing a postfix chain. +#[must_use] +pub fn type_owner(ws: &Workspace, from_fqn: &str, ty: &str) -> Option<(String, String)> { + let base = ty.trim_end_matches("[]"); + let base = base.split('<').next().unwrap_or(base).trim(); + let segments: Vec<&str> = base.split("::").collect(); + resolve_owner(ws, from_fqn, &segments) +} + +#[cfg(test)] +mod tests { + use super::*; + use pseudoscript_syntax::parse; + + fn ws(modules: &[(&str, &str)]) -> Workspace { + Workspace::build(modules.iter().map(|(f, s)| ((*f).to_owned(), parse(s).ast))) + } + + // Mirrors the `syntax` module: `tokens` is annotated `Token[]`, reached + // through the container-qualified `Syntax::Lexer`. + const SYNTAX: &str = "//! syntax\n\n\ + public data Token { kind: string }\n\n\ + public component Lexer for Syntax {\n tokenize(text: string): Token[];\n}\n\n\ + public component Parser for Syntax {\n \ + public parse(text: string): string {\n \ + tokens: Token[] = Syntax::Lexer.tokenize(text)\n return tokens.kind\n }\n}\n"; + + #[test] + fn local_type_reads_the_annotation() { + let workspace = ws(&[("syntax", SYNTAX)]); + let locals = local_types(&workspace, "syntax"); + let tokens = locals + .iter() + .find(|l| l.name == "tokens") + .expect("`tokens` typed"); + assert_eq!(tokens.ty, "Token[]"); + } + + #[test] + fn binding_type_at_resolves_by_name() { + let workspace = ws(&[("syntax", SYNTAX)]); + let local = binding_type_at(&workspace, "syntax", "tokens").expect("tokens"); + assert_eq!(local.ty, "Token[]"); + } + + #[test] + fn owner_at_dot_types_a_binding_receiver() { + // `tokens` is bound to `Token[]`; the `.` in `tokens.kind` resolves to + // the `Token` owner so its members can be completed. + let workspace = ws(&[("syntax", SYNTAX)]); + let dot = (SYNTAX.find("tokens.kind").unwrap() + "tokens".len()) as u32; + let owner = owner_at_dot(&workspace, "syntax", SYNTAX, dot).expect("typed receiver"); + assert_eq!(owner, ("syntax".to_owned(), "Token".to_owned())); + } + + #[test] + fn local_types_read_literal_and_from_annotations() { + let src = "//! m\n\nsystem S {\n go() {\n n: number = 42\n p: Parsed = Parsed from { n }\n }\n}\n\npublic data Parsed { x: number }\n"; + let workspace = ws(&[("m", src)]); + let locals = local_types(&workspace, "m"); + assert_eq!(locals.iter().find(|l| l.name == "n").unwrap().ty, "number"); + assert_eq!(locals.iter().find(|l| l.name == "p").unwrap().ty, "Parsed"); + } +} diff --git a/crates/pseudoscript-model/src/lib.rs b/crates/pseudoscript-model/src/lib.rs index f8ab904..1bf91da 100644 --- a/crates/pseudoscript-model/src/lib.rs +++ b/crates/pseudoscript-model/src/lib.rs @@ -30,10 +30,16 @@ //! ``` mod check; +pub mod complete; +pub mod fold; mod graph; +pub mod infer; mod model; pub mod resolve; +pub mod semantic; +pub use complete::{CompletionItem, CompletionKind, completion}; +pub use fold::{FoldRange, folding_ranges}; pub use graph::{ Edge, EdgeKind, Graph, GraphNode, NodeDoc, NodeKind, SigParam, Signature, Step, Trigger, Visibility, @@ -43,6 +49,7 @@ pub use model::{ }; pub use pseudoscript_syntax::ast; pub use pseudoscript_syntax::{Diagnostic, Severity}; +pub use semantic::{SemKind, SemToken, semantic_tokens}; use pseudoscript_syntax::ast::Module; diff --git a/crates/pseudoscript-model/src/model.rs b/crates/pseudoscript-model/src/model.rs index ee679c0..1d567ec 100644 --- a/crates/pseudoscript-model/src/model.rs +++ b/crates/pseudoscript-model/src/model.rs @@ -506,7 +506,7 @@ fn callable_detail(callable: &Callable) -> String { } /// Renders a type to its source form: `Result`, `Account[]`. -fn render_type(ty: &Type) -> String { +pub(crate) fn render_type(ty: &Type) -> String { let mut out = path_str(&ty.name); if !ty.generics.is_empty() { let args = ty diff --git a/crates/pseudoscript-model/src/semantic.rs b/crates/pseudoscript-model/src/semantic.rs new file mode 100644 index 0000000..0e9bb04 --- /dev/null +++ b/crates/pseudoscript-model/src/semantic.rs @@ -0,0 +1,498 @@ +//! AST-aware semantic tokens — the shared engine behind the LSP +//! (`pseudoscript-lsp`) and the web IDE (`pseudoscript-wasm`). +//! +//! Two passes feed one sorted, non-overlapping token list in absolute byte +//! offsets: +//! +//! - **Token pass** ([`tokenize`]) colours the leaves the tree does not expose +//! as convenient spans: keywords, doc comments, and string/number literals. +//! - **AST pass** ([`parse`]) colours identifiers by their *role* — a `system` +//! name is a namespace, a `data` name a class, a callable a method, a +//! parameter a parameter, a `.f()` step a method call — and a whole `#[…]` +//! macro invocation as one decorator span. A later token overlapping an +//! earlier one is dropped, so the macro span subsumes its arguments. +//! +//! Offsets are bytes, so the engine is adapter-neutral: the LSP delta-encodes to +//! `lsp_types`, the IDE serialises to JSON and decorates ranges. + +use pseudoscript_syntax::{Span, TokenKind, Trivia, ast, lex, parse, tokenize}; +use serde::Serialize; + +/// A semantic token's role. Names follow the LSP standard token types so the +/// LSP adapter is a one-to-one mapping. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)] +#[serde(rename_all = "camelCase")] +pub enum SemKind { + Namespace, + Type, + Class, + Parameter, + Variable, + Property, + EnumMember, + Method, + Keyword, + Comment, + String, + Number, + Decorator, +} + +/// One coloured span in absolute byte offsets, with the `declaration` modifier. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)] +pub struct SemToken { + /// Start byte offset (inclusive). + pub start: u32, + /// End byte offset (exclusive). + pub end: u32, + /// What the token denotes. + pub kind: SemKind, + /// Whether this is the declaration site of the symbol. + pub declaration: bool, +} + +/// Computes the semantic tokens for `src`, sorted by start offset and free of +/// overlaps and zero-width spans (a later token overlapping an earlier one is +/// dropped, matching the token-then-AST precedence). +#[must_use] +pub fn semantic_tokens(src: &str) -> Vec { + let mut raws = Vec::new(); + token_pass(src, &mut raws); + comment_pass(src, &mut raws); + ast_pass(&parse(src).ast, &mut raws); + raws.sort_by_key(|t| t.start); + + let mut out: Vec = Vec::with_capacity(raws.len()); + let mut last_end = 0; + for raw in raws { + if raw.start < last_end || raw.end <= raw.start { + continue; + } + last_end = raw.end; + out.push(raw); + } + out +} + +/// Colours keywords, doc comments, and string/number literals. +fn token_pass(src: &str, out: &mut Vec) { + for token in tokenize(src) { + let kind = match token.kind { + k if is_keyword(k) => SemKind::Keyword, + TokenKind::Doc | TokenKind::InnerDoc | TokenKind::Tag => SemKind::Comment, + TokenKind::String => SemKind::String, + TokenKind::Number => SemKind::Number, + // `#[…]` is coloured whole as a decorator by the AST pass, so the + // opener is not coloured here (it would pre-empt the full span). + _ => continue, + }; + push(out, token.span, kind, false); + } +} + +/// Colours `//` line and `/* */` block comments. The lexer keeps these as +/// trivia (no token), so `token_pass` never sees them; without this pass only +/// `///` doc comments would be coloured. Blank-line trivia carries no glyph and +/// is skipped. +fn comment_pass(src: &str, out: &mut Vec) { + for entry in lex(src).trivia { + if matches!( + entry.trivia, + Trivia::LineComment(_) | Trivia::BlockComment(_) + ) { + push(out, entry.span, SemKind::Comment, false); + } + } +} + +/// Whether `kind` is one of the reserved keywords (§2.3) — every `Kw*` token, +/// including the `Ok`/`Err`/`Some`/`None` constructors and the `feature`/ +/// given/when/then/and/but BDD words. Colouring them all here means the AST pass +/// need not re-colour any keyword. +fn is_keyword(kind: TokenKind) -> bool { + matches!( + kind, + TokenKind::KwSystem + | TokenKind::KwContainer + | TokenKind::KwComponent + | TokenKind::KwPerson + | TokenKind::KwData + | TokenKind::KwFor + | TokenKind::KwAlias + | TokenKind::KwFrom + | TokenKind::KwPublic + | TokenKind::KwSelf + | TokenKind::KwReturn + | TokenKind::KwOk + | TokenKind::KwErr + | TokenKind::KwSome + | TokenKind::KwNone + | TokenKind::KwIf + | TokenKind::KwElse + | TokenKind::KwWhile + | TokenKind::KwIn + | TokenKind::KwTrue + | TokenKind::KwFalse + | TokenKind::KwFeature + | TokenKind::KwGiven + | TokenKind::KwWhen + | TokenKind::KwThen + | TokenKind::KwAnd + | TokenKind::KwBut + ) +} + +/// Colours identifiers by their declared role across the whole module. +fn ast_pass(module: &ast::Module, out: &mut Vec) { + for item in &module.items { + match item { + ast::Item::Alias(alias) => { + push(out, alias.name.span, SemKind::Namespace, true); + namespace_path(&alias.target, out); + } + ast::Item::Decl(decl) => decl_tokens(decl, out), + ast::Item::Feature(feature) => { + push(out, feature.name.span, SemKind::Namespace, true); + namespace_path(&feature.target, out); + } + } + } +} + +/// Colours a declaration: its macros, then its structural payload. +fn decl_tokens(decl: &ast::Decl, out: &mut Vec) { + for mac in &decl.macros { + macro_tokens(mac, out); + } + match &decl.kind { + ast::DeclKind::Person(node) + | ast::DeclKind::System(node) + | ast::DeclKind::Container(node) + | ast::DeclKind::Component(node) => node_tokens(node, out), + ast::DeclKind::Data(data) => data_tokens(data, out), + } +} + +/// Colours a node: its name (namespace, declared), its `for` parent path, and +/// its disclosed body members. +fn node_tokens(node: &ast::Node, out: &mut Vec) { + push(out, node.name.span, SemKind::Namespace, true); + if let Some(parent) = &node.parent { + namespace_path(parent, out); + } + for member in node.body.iter().flatten() { + match member { + ast::BodyMember::Callable(callable) => callable_tokens(callable, out), + ast::BodyMember::Decl(decl) => decl_tokens(decl, out), + } + } +} + +/// Colours a `data` declaration: its name (class, declared) and its fields or +/// variants. +fn data_tokens(data: &ast::Data, out: &mut Vec) { + push(out, data.name.span, SemKind::Class, true); + match &data.body { + ast::DataBody::Record(fields) => fields_tokens(fields, out), + ast::DataBody::Union(variants) => { + for variant in variants { + push(out, variant.name.span, SemKind::EnumMember, true); + if let Some(fields) = &variant.record { + fields_tokens(fields, out); + } + } + } + ast::DataBody::BlackBox => {} + } +} + +/// Colours record fields: each name (property, declared) and its type. +fn fields_tokens(fields: &[ast::Field], out: &mut Vec) { + for field in fields { + push(out, field.name.span, SemKind::Property, true); + type_tokens(&field.ty, out); + } +} + +/// Colours a callable: macros, name (method, declared), parameters, return +/// type, and body. +fn callable_tokens(callable: &ast::Callable, out: &mut Vec) { + for mac in &callable.macros { + macro_tokens(mac, out); + } + push(out, callable.name.span, SemKind::Method, true); + for param in &callable.params { + push(out, param.name.span, SemKind::Parameter, true); + type_tokens(¶m.ty, out); + } + if let Some(ret) = &callable.return_ty { + type_tokens(ret, out); + } + if let Some(block) = &callable.body { + block_tokens(block, out); + } +} + +/// Colours every statement in a block. +fn block_tokens(block: &ast::Block, out: &mut Vec) { + for stmt in &block.stmts { + stmt_tokens(stmt, out); + } +} + +/// Colours one statement and its sub-expressions. +fn stmt_tokens(stmt: &ast::Stmt, out: &mut Vec) { + match &stmt.kind { + ast::StmtKind::Assign { name, ty, value } => { + push(out, name.span, SemKind::Variable, true); + // A placeholder type (untyped-assignment error recovery) is an + // empty-named path at the binding span — don't re-colour it. + if !ty.name.segments.iter().all(|s| s.name.is_empty()) { + type_tokens(ty, out); + } + expr_tokens(value, out); + } + ast::StmtKind::Return(value) => { + if let Some(value) = value { + expr_tokens(value, out); + } + } + ast::StmtKind::If { + cond, + then_block, + else_block, + } => { + expr_tokens(cond, out); + block_tokens(then_block, out); + if let Some(block) = else_block { + block_tokens(block, out); + } + } + ast::StmtKind::For { + binding, + iter, + body, + } => { + push(out, binding.span, SemKind::Variable, true); + expr_tokens(iter, out); + block_tokens(body, out); + } + ast::StmtKind::While { cond, body } => { + expr_tokens(cond, out); + block_tokens(body, out); + } + ast::StmtKind::Expr(expr) => expr_tokens(expr, out), + } +} + +/// Colours an expression: references, calls, field access, and `from` types. +fn expr_tokens(expr: &ast::Expr, out: &mut Vec) { + match &expr.kind { + ast::ExprKind::Marker { payload, .. } => { + if let Some(payload) = payload { + expr_tokens(payload, out); + } + } + ast::ExprKind::From { ty, sources, .. } => { + type_path(ty, out); + for source in sources { + expr_tokens(source, out); + } + } + ast::ExprKind::Postfix { base, segments } => { + expr_tokens(base, out); + for seg in segments { + let kind = if seg.call_args.is_some() { + SemKind::Method + } else { + SemKind::Property + }; + push(out, seg.name.span, kind, false); + for arg in seg.call_args.iter().flatten() { + expr_tokens(arg, out); + } + } + } + ast::ExprKind::Ref(ast::Ref::Path(path)) => ref_path(path, out), + // `self` is a keyword and literals are coloured by the token pass. + ast::ExprKind::Ref(ast::Ref::SelfNode(_)) | ast::ExprKind::Literal(_) => {} + ast::ExprKind::Unary { expr, .. } => expr_tokens(expr, out), + ast::ExprKind::Paren(inner) => expr_tokens(inner, out), + } +} + +/// Colours a type: the base path (qualifiers as namespaces, the name as a type) +/// and any generic arguments. +fn type_tokens(ty: &ast::Type, out: &mut Vec) { + type_path(&ty.name, out); + for generic in &ty.generics { + type_tokens(generic, out); + } +} + +/// Colours the whole macro invocation (`#[name(args)]`) as one decorator span, +/// so it reads as a cohesive unit rather than a name plus typed arguments. +fn macro_tokens(mac: &ast::Macro, out: &mut Vec) { + push(out, mac.span, SemKind::Decorator, false); +} + +/// Colours a value-reference path: trailing name as a variable, qualifiers as +/// namespaces. +fn ref_path(path: &ast::Path, out: &mut Vec) { + split_path(path, SemKind::Variable, out); +} + +/// Colours a type path: trailing name as a type, qualifiers as namespaces. +fn type_path(path: &ast::Path, out: &mut Vec) { + split_path(path, SemKind::Type, out); +} + +/// Colours every segment of a path as a namespace (parent / alias target). +fn namespace_path(path: &ast::Path, out: &mut Vec) { + for segment in &path.segments { + push(out, segment.span, SemKind::Namespace, false); + } +} + +/// Colours a path's last segment as `last`, every qualifier as a namespace. +fn split_path(path: &ast::Path, last: SemKind, out: &mut Vec) { + let Some((name, qualifiers)) = path.segments.split_last() else { + return; + }; + for segment in qualifiers { + push(out, segment.span, SemKind::Namespace, false); + } + push(out, name.span, last, false); +} + +/// Records one coloured span. +fn push(out: &mut Vec, span: Span, kind: SemKind, declaration: bool) { + out.push(SemToken { + start: span.start, + end: span.end, + kind, + declaration, + }); +} + +#[cfg(test)] +mod tests { + use super::*; + + /// The token starting at the first occurrence of `needle`. + fn at<'a>(tokens: &'a [SemToken], src: &str, needle: &str) -> &'a SemToken { + let start = src.find(needle).expect("substring present") as u32; + tokens + .iter() + .find(|t| t.start == start) + .unwrap_or_else(|| panic!("no token at {needle:?}")) + } + + #[test] + fn line_and_block_comments_are_coloured() { + // `//` and `/* */` are trivia, not tokens — they still colour as comments. + let src = "//! m\n\n// a line note\nsystem S { /* inline */ }\n"; + let tokens = semantic_tokens(src); + assert_eq!(at(&tokens, src, "// a line note").kind, SemKind::Comment); + assert_eq!(at(&tokens, src, "/* inline */").kind, SemKind::Comment); + // the `//!` module doc still colours too + assert_eq!(at(&tokens, src, "//! m").kind, SemKind::Comment); + } + + #[test] + fn feature_and_step_keywords_are_coloured() { + let src = "//! m\n\npublic system S;\n\nfeature Open for S {\n given \"a user\"\n when \"they act\"\n then \"it works\"\n}\n"; + let tokens = semantic_tokens(src); + assert_eq!(at(&tokens, src, "feature").kind, SemKind::Keyword); + assert_eq!(at(&tokens, src, "given").kind, SemKind::Keyword); + assert_eq!(at(&tokens, src, "when").kind, SemKind::Keyword); + assert_eq!(at(&tokens, src, "then").kind, SemKind::Keyword); + // the feature name is still a declared namespace + assert_eq!(at(&tokens, src, "Open").kind, SemKind::Namespace); + } + + #[test] + fn option_markers_are_coloured() { + let src = "//! m\n\nsystem S {\n f(): void {\n x: Option = Some(1)\n y: Option = None\n }\n}\n"; + let tokens = semantic_tokens(src); + assert_eq!(at(&tokens, src, "Some").kind, SemKind::Keyword); + assert_eq!(at(&tokens, src, "None").kind, SemKind::Keyword); + } + + #[test] + fn node_name_is_a_declared_namespace() { + let src = "//! m\n\npublic system Banking;\n"; + let tokens = semantic_tokens(src); + let token = at(&tokens, src, "Banking"); + assert_eq!(token.kind, SemKind::Namespace); + assert!(token.declaration); + assert_eq!(token.end - token.start, 7); + } + + #[test] + fn keyword_and_data_name_colours() { + let src = "//! m\n\ndata Account { id: uuid }\n"; + let tokens = semantic_tokens(src); + assert_eq!(at(&tokens, src, "data").kind, SemKind::Keyword); + let account = at(&tokens, src, "Account"); + assert_eq!(account.kind, SemKind::Class); + assert!(account.declaration); + assert_eq!(at(&tokens, src, "id").kind, SemKind::Property); + assert_eq!(at(&tokens, src, "uuid").kind, SemKind::Type); + } + + #[test] + fn callable_param_type_and_calls() { + let src = "//! m\n\nsystem S {\n run(name: string): uuid {\n return self.alloc(name)\n }\n}\n"; + let tokens = semantic_tokens(src); + assert_eq!(at(&tokens, src, "run").kind, SemKind::Method); + assert_eq!(at(&tokens, src, "name").kind, SemKind::Parameter); + assert_eq!(at(&tokens, src, "string").kind, SemKind::Type); + assert_eq!(at(&tokens, src, "self").kind, SemKind::Keyword); + assert_eq!(at(&tokens, src, "alloc").kind, SemKind::Method); + } + + #[test] + fn member_access_vs_call() { + let src = "//! m\n\nsystem S {\n go() {\n Repo.run(x)\n }\n}\n"; + let tokens = semantic_tokens(src); + assert_eq!(at(&tokens, src, "run").kind, SemKind::Method); + } + + #[test] + fn string_literal_and_keyword() { + let src = "//! m\n\nsystem S {\n f() {\n return Err(\"boom\")\n }\n}\n"; + let tokens = semantic_tokens(src); + assert_eq!(at(&tokens, src, "\"boom\"").kind, SemKind::String); + assert_eq!(at(&tokens, src, "Err").kind, SemKind::Keyword); + } + + #[test] + fn macro_invocation_is_one_decorator_span() { + let src = "//! m\n\n#[onevent(a::B)]\nsystem S;\n"; + let tokens = semantic_tokens(src); + let dec = at(&tokens, src, "#[onevent"); + assert_eq!(dec.kind, SemKind::Decorator); + // covers the whole `#[…]`, subsuming the name and the path argument + let close = (src.find(']').unwrap() + 1) as u32; + assert!(dec.end >= close, "{dec:?}"); + assert!( + !tokens + .iter() + .any(|t| t.start > dec.start && t.start < close), + "args must be subsumed: {tokens:?}" + ); + } + + #[test] + fn tokens_are_sorted_and_non_overlapping() { + let src = "//! m\n\ndata Account { id: uuid }\n"; + let tokens = semantic_tokens(src); + let mut last_end = 0; + for t in &tokens { + assert!(t.start >= last_end, "overlap at {t:?}"); + assert!(t.end > t.start, "zero-width at {t:?}"); + last_end = t.end; + } + } +} diff --git a/crates/pseudoscript-model/tests/conformance.rs b/crates/pseudoscript-model/tests/conformance.rs index 8080c7b..38f7fe8 100644 --- a/crates/pseudoscript-model/tests/conformance.rs +++ b/crates/pseudoscript-model/tests/conformance.rs @@ -48,16 +48,16 @@ public container Emit for Pseudoscript; component Generate for Cli { #[manual] public run(req: Request): Result { - ast = Syntax::Parser.parse(req) + ast: Result = Syntax::Parser.parse(req) if (ast.isErr) { return Err(ast.error) } - graph = Model::Builder.build(ast.value) + graph: Result = Model::Builder.build(ast.value) if (graph.isErr) { return Err(graph.error) } - sub = Model::Views.extract(graph.value) - out = Emit::Transpiler.emit(sub) + sub: Graph = Model::Views.extract(graph.value) + out: Result = Emit::Transpiler.emit(sub) if (out.isErr) { return Err(out.error) } diff --git a/crates/pseudoscript-model/tests/features/graph.feature b/crates/pseudoscript-model/tests/features/graph.feature index d8ff664..25ef8ff 100644 --- a/crates/pseudoscript-model/tests/features/graph.feature +++ b/crates/pseudoscript-model/tests/features/graph.feature @@ -69,8 +69,8 @@ Feature: Resolved relationship graph (LANG.md §9) public system Shop; public container Web for shop::Shop { public checkout(): void { - a = self.price() - cart = shop::Cart from { Web.lookup() } + a: number = self.price() + cart: shop::Cart = shop::Cart from { Web.lookup() } } price(): number { return 0 } lookup(): number { return 0 } diff --git a/crates/pseudoscript-model/tests/features/member_calls.feature b/crates/pseudoscript-model/tests/features/member_calls.feature new file mode 100644 index 0000000..c64ed8e --- /dev/null +++ b/crates/pseudoscript-model/tests/features/member_calls.feature @@ -0,0 +1,78 @@ +Feature: Method calls resolve to a declared callable (LANG.md §6) + + A `.name(args)` call's member MUST exist on the receiver's type where the + receiver resolves to a same-module node or `data` record. A node receiver must + name one of its callables; a `data` record has only fields, so any call on a + record value is rejected. Receivers whose type is not inferred (call results, + `::` paths) are not checked (ADR-022); `self.` calls are checked separately. + + Scenario: Calling an undeclared method on a node receiver is rejected + Given the model file: + """ + //! example + public system S; + public container Db for S; + public component Store for Db { + get(): void; + } + public container C for S { + run(): void { Store.nope() } + } + """ + Then the diagnostics include "no method `nope` on `Store`" + And there is exactly 1 diagnostic + + Scenario: Calling a declared method on a node receiver is well-formed + Given the model file: + """ + //! example + public system S; + public container Db for S; + public component Store for Db { + get(): void; + } + public container C for S { + run(): void { Store.get() } + } + """ + Then there are no diagnostics + + Scenario: Calling a method on a data value is rejected + Given the model file: + """ + //! example + public data Conv { id: uuid } + public system S; + public container C for S { + run(c: Conv): void { c.doThing() } + } + """ + Then the diagnostics include "no method `doThing` on `Conv`" + And there is exactly 1 diagnostic + + Scenario: A method call through a field chain is checked against the field's type + Given the model file: + """ + //! example + public data Conv { id: uuid } + public data Deps { conversation: Conv } + public system S; + public container C for S { + run(d: Deps): void { d.conversation.participantHasWriteAccess(d) } + } + """ + Then the diagnostics include "no method `participantHasWriteAccess` on `Conv`" + And there is exactly 1 diagnostic + + Scenario: A method call on a call result is not checked + Given the model file: + """ + //! example + public data Conv { id: uuid } + public system S; + public container C for S { + fetch(): Conv; + run(): void { self.fetch().anything() } + } + """ + Then there are no diagnostics diff --git a/crates/pseudoscript-model/tests/features/references.feature b/crates/pseudoscript-model/tests/features/references.feature index 302bee3..7b43285 100644 --- a/crates/pseudoscript-model/tests/features/references.feature +++ b/crates/pseudoscript-model/tests/features/references.feature @@ -26,7 +26,7 @@ Feature: References in a body resolve (LANG.md §7, §8) public system S; public container C for S { get(x: Item): Item { - y = x + y: Item = x return y } } diff --git a/crates/pseudoscript-model/tests/features/rules.feature b/crates/pseudoscript-model/tests/features/rules.feature index 89a3f3b..2874091 100644 --- a/crates/pseudoscript-model/tests/features/rules.feature +++ b/crates/pseudoscript-model/tests/features/rules.feature @@ -97,7 +97,7 @@ Feature: Static rules, one scenario each (LANG.md §2.4, §3.5, §4, §5.1, §6, public system Banking; public container Mainframe for Banking { Get(): Result { - r = self.Fetch() + r: Result = self.Fetch() if (r.isErr) { return Err(r.error) } @@ -131,8 +131,8 @@ Feature: Static rules, one scenario each (LANG.md §2.4, §3.5, §4, §5.1, §6, public system Banking; public container Mainframe for Banking { Run(): void { - r = self.Make() - r = self.Make() + r: Info = self.Make() + r: Info = self.Make() } Make(): Info; } @@ -149,7 +149,7 @@ Feature: Static rules, one scenario each (LANG.md §2.4, §3.5, §4, §5.1, §6, public system Banking; public container Mainframe for Banking { public GetBankingInfo(id: number): Result { - r = AccountStore::Repository.fetch(id) + r: Result = AccountStore::Repository.fetch(id) if (r.isErr) { return Err(r.value) } @@ -173,7 +173,7 @@ Feature: Static rules, one scenario each (LANG.md §2.4, §3.5, §4, §5.1, §6, public system Banking; public container Mainframe for Banking { Get(): Result { - r = self.Fetch() + r: Result = self.Fetch() if (r.isOk) { return Ok(r.error) } diff --git a/crates/pseudoscript-model/tests/features/type_checking.feature b/crates/pseudoscript-model/tests/features/type_checking.feature index cef598b..54f54dc 100644 --- a/crates/pseudoscript-model/tests/features/type_checking.feature +++ b/crates/pseudoscript-model/tests/features/type_checking.feature @@ -136,7 +136,7 @@ Feature: Return-type and `from` type checking (LANG.md §5.1, §6, §7.2) public system S; public container C for S { one(): number { - x = "" + x: string = "" return x } } diff --git a/crates/pseudoscript-syntax/src/ast.rs b/crates/pseudoscript-syntax/src/ast.rs index b35fd0c..aac27ec 100644 --- a/crates/pseudoscript-syntax/src/ast.rs +++ b/crates/pseudoscript-syntax/src/ast.rs @@ -329,8 +329,8 @@ pub struct Stmt { /// The statement forms (§7). #[derive(Debug, Clone, PartialEq)] pub enum StmtKind { - /// `x = Expr` single-assignment (§7.1). - Assign { name: Ident, value: Expr }, + /// `x: T = Expr` single-assignment (§7.1): a binding states its type. + Assign { name: Ident, ty: Type, value: Expr }, /// `return [Expr]` (§7). Return(Option), /// `if (C) { } [else { }]` (§7). @@ -477,6 +477,28 @@ pub struct Type { pub span: Span, } +impl Type { + /// A placeholder type at `span` — an empty-named path, mirroring the + /// error-recovery [`Ident`] convention. The parser inserts one for an + /// untyped assignment so the statement still carries a `ty` while the + /// missing-annotation diagnostic stands on its own. + #[must_use] + pub fn placeholder(span: Span) -> Self { + Type { + name: Path { + segments: vec![Ident { + name: String::new(), + span, + }], + span, + }, + generics: Vec::new(), + is_array: false, + span, + } + } +} + /// A `::`-separated path of identifiers (§2.2, §10 `Path`). #[derive(Debug, Clone, PartialEq)] pub struct Path { diff --git a/crates/pseudoscript-syntax/src/parser.rs b/crates/pseudoscript-syntax/src/parser.rs index 35dadc1..4dd28d3 100644 --- a/crates/pseudoscript-syntax/src/parser.rs +++ b/crates/pseudoscript-syntax/src/parser.rs @@ -932,12 +932,33 @@ impl Parser { TokenKind::KwIf => self.parse_if(), TokenKind::KwFor => self.parse_for(), TokenKind::KwWhile => self.parse_while(), - // `Ident =` is an assignment; otherwise an expression statement. + // `name: Type = Expr` is the sole assignment form (§7.1): a binding + // states its type. `name = Expr` (no annotation) is still parsed — + // tolerantly, with a placeholder type — so the error is one precise + // diagnostic rather than a confusing expression-parse failure. + TokenKind::Ident if self.peek2_kind() == Some(TokenKind::Colon) => { + let name = self.expect_ident("binding name"); + self.bump(); // `:` + let ty = self.parse_type(); + if self.eat(TokenKind::Eq).is_none() { + self.error(self.cur_span(), "expected `=` after the binding type"); + } + let value = self.parse_expr(); + StmtKind::Assign { name, ty, value } + } TokenKind::Ident if self.peek2_kind() == Some(TokenKind::Eq) => { let name = self.expect_ident("binding name"); + self.error( + name.span, + "assignment requires a type annotation: write `name: Type = …`", + ); self.bump(); // `=` let value = self.parse_expr(); - StmtKind::Assign { name, value } + StmtKind::Assign { + ty: Type::placeholder(name.span), + name, + value, + } } _ => StmtKind::Expr(self.parse_expr()), }; @@ -1151,9 +1172,41 @@ impl Parser { let mut sources = Vec::new(); while !self.is_eof() && !self.at(TokenKind::RBrace) { sources.push(self.parse_expr()); - if self.eat(TokenKind::Comma).is_none() { - break; + if self.eat(TokenKind::Comma).is_some() { + continue; + } + if !self.at(TokenKind::RBrace) { + // A source set separates entries with `,` and closes with `}` + // (§7.2). A `key: value` colon is the common mistake: `from` + // takes bare references, not labelled fields (ADR-003), so the + // value is bound to a name and the name listed. Point at the fix + // and drop the mis-parsed label so it isn't later reported as an + // unresolved reference. Either way, skip to the closing `}` to + // keep the error local instead of derailing the body. + if self.at(TokenKind::Colon) { + sources.pop(); + self.error( + self.cur_span(), + "`from` takes bare references, not `field: value` — \ + bind the value to a name and list the name (§7.2)", + ); + } else { + self.error(self.cur_span(), "expected `,` or `}` in `from` source set"); + } + // Skip to this source set's own `}`, counting nested braces so a + // labelled *inner* `from { … }` doesn't swallow the outer close. + let mut depth: u32 = 0; + while !self.is_eof() { + match self.peek_kind() { + Some(TokenKind::LBrace) => depth += 1, + Some(TokenKind::RBrace) if depth == 0 => break, + Some(TokenKind::RBrace) => depth -= 1, + _ => {} + } + self.bump(); + } } + break; } let end = self .eat(TokenKind::RBrace) @@ -1412,4 +1465,57 @@ mod tests { let parsed = parse("public system S { = }"); assert!(parsed.diagnostics.iter().any(Diagnostic::is_error)); } + + /// Regression: a labelled `from` source set (`{ name: "x" }` — invalid, since + /// `from` takes bare references, ADR-003) reports one fix-oriented error and + /// recovers at its `}`. Before the fix, the stray `:` derailed the body into a + /// cascade of spurious "unexpected token at top level" errors, and the + /// callable after it was lost. The mis-parsed label is dropped, so it is not + /// also flagged as an unresolved reference. + #[test] + fn labelled_from_source_does_not_cascade() { + let parsed = parse( + "public system S { f(): T { return T from { name: \"x\" } } g(): T { return Ok } }", + ); + let errors: Vec<&str> = parsed + .diagnostics + .iter() + .filter(|d| d.is_error()) + .map(|d| d.message.as_str()) + .collect(); + assert!( + errors + .iter() + .any(|m| m.contains("`from` takes bare references")), + "the source set error names the fix: {errors:?}" + ); + assert!( + !errors.iter().any(|m| m.contains("top level")), + "no top-level cascade: {errors:?}" + ); + // The label `name` is dropped, not re-reported as a parse error. + assert_eq!(errors.len(), 1, "exactly one error: {errors:?}"); + // Both callables survive recovery — the container parses as one item. + assert_eq!(parsed.ast.items.len(), 1); + } + + /// A labelled *inner* `from` must not let recovery swallow the outer `}`: + /// brace-aware skipping stops at the source set's own close, so the trailing + /// statements still parse. + #[test] + fn labelled_nested_from_recovers_to_matching_brace() { + let parsed = + parse("public system S { f(a: T): T { x = T from { m: a from { n } } return Ok } }"); + let errors: Vec<&str> = parsed + .diagnostics + .iter() + .filter(|d| d.is_error()) + .map(|d| d.message.as_str()) + .collect(); + assert!( + !errors.iter().any(|m| m.contains("top level")), + "no top-level cascade from a nested labelled from: {errors:?}" + ); + assert_eq!(parsed.ast.items.len(), 1); + } } diff --git a/crates/pseudoscript-syntax/tests/conformance.rs b/crates/pseudoscript-syntax/tests/conformance.rs index 49d49f9..9eb8059 100644 --- a/crates/pseudoscript-syntax/tests/conformance.rs +++ b/crates/pseudoscript-syntax/tests/conformance.rs @@ -45,12 +45,12 @@ public container Web for Shop { #[http("POST /checkout")] public checkout(cart: Sku[]): Result { for (item in cart) { - line = Warehouse::Pricing.price(item) + line: Result = Warehouse::Pricing.price(item) if (line.isErr) { return Err(line.error) } } - r = self.finalize(cart) + r: Result = self.finalize(cart) return Ok(r.value) } @@ -61,8 +61,8 @@ public container Warehouse for Shop; component Pricing for Warehouse { price(item: Sku): Result { - base = Catalog.lookup(item).value - receipt = Receipt from { base } + base: Receipt = Catalog.lookup(item).value + receipt: Receipt = Receipt from { base } return Ok(receipt) } } diff --git a/crates/pseudoscript-syntax/tests/features/syntax.feature b/crates/pseudoscript-syntax/tests/features/syntax.feature index b4a70c2..c0436df 100644 --- a/crates/pseudoscript-syntax/tests/features/syntax.feature +++ b/crates/pseudoscript-syntax/tests/features/syntax.feature @@ -24,5 +24,5 @@ Feature: Syntax conformance (LANG.md §3–§10) Then parsing produces no error diagnostic Scenario: A from-composition with one source parses - Given the source "public system S { f(): void { x = T from { a } } }" + Given the source "public system S { f(): void { x: T = T from { a } } }" Then parsing produces no error diagnostic diff --git a/crates/pseudoscript-wasm/Cargo.toml b/crates/pseudoscript-wasm/Cargo.toml index 58deef5..3e58c6d 100644 --- a/crates/pseudoscript-wasm/Cargo.toml +++ b/crates/pseudoscript-wasm/Cargo.toml @@ -18,6 +18,7 @@ path = "src/lib.rs" pseudoscript-syntax = { path = "../pseudoscript-syntax" } pseudoscript-format = { path = "../pseudoscript-format" } pseudoscript-model = { path = "../pseudoscript-model" } +pseudoscript-lsp-core = { path = "../pseudoscript-lsp-core" } pseudoscript-emit = { path = "../pseudoscript-emit" } pseudoscript-doc = { path = "../pseudoscript-doc" } serde = { version = "1", features = ["derive"] } diff --git a/crates/pseudoscript-wasm/src/lib.rs b/crates/pseudoscript-wasm/src/lib.rs index 4a93a12..c489b22 100644 --- a/crates/pseudoscript-wasm/src/lib.rs +++ b/crates/pseudoscript-wasm/src/lib.rs @@ -23,10 +23,15 @@ //! Each `#[wasm_bindgen]` function is a thin wrapper over a `*_impl` that //! returns `Result<_, String>`; the wrapper maps the error to a `JsError`. The //! `*_impl`s carry the logic and are unit-tested on the host (a `JsError` -//! cannot be constructed off-wasm). Diagnostics are the foundation an -//! LSP-over-wasm server is built on; hover/completion/definition slot in here -//! and reuse [`pseudoscript_model`] without the native `tower-lsp`/`tokio` -//! transport. +//! cannot be constructed off-wasm). +//! +//! The language-intelligence functions — [`hover`], [`completion`], +//! [`semantic_tokens`], [`folding_ranges`] — are an **LSP-over-wasm** bridge: +//! they call [`pseudoscript_lsp_core`] (the same handlers the stdio server uses) +//! and serialise its `lsp_types` results to JSON, so the WASM API is byte-for- +//! byte the LSP API minus the `tower-lsp`/`tokio` transport. The diagram and doc +//! exports ([`emit_scene`], [`symbol_scene`], …) have no LSP equivalent and are +//! WASM-only. use std::collections::HashMap; @@ -39,9 +44,12 @@ use pseudoscript_emit::{ }; use pseudoscript_format::format as format_source; use pseudoscript_model::{ - Graph, NodeKind, Workspace, WorkspaceModule, check as check_source, check_workspace_modules, + Graph, Workspace, WorkspaceModule, check as check_source, check_workspace_modules, graph as build_graph, resolve::resolve_at, }; +// The shared LSP API: completion, hover, semantic tokens, and folding are served +// here exactly as the stdio server serves them — same `lsp_types` results. +use pseudoscript_lsp_core::{analysis, complete, convert, refs, semantic, symbols}; use pseudoscript_syntax::{ Diagnostic, LineIndex, Severity, TokenKind, parse as parse_source, tokenize, }; @@ -136,6 +144,28 @@ pub fn emit_svg(source: &str, view: &str, target: &str) -> Result String { + to_json(&semantic::semantic_tokens(source)) +} + +/// Foldable regions of `source` as the JSON of an LSP `FoldingRange` array +/// (`{ startLine, endLine, kind }`, 0-based lines) — every multi-line +/// declaration and statement block. Identical to the stdio server's +/// `textDocument/foldingRange` response; the editor folds these instead of +/// brace-matching in JS. +#[wasm_bindgen] +#[must_use] +pub fn folding_ranges(source: &str) -> String { + to_json(&symbols::folding_ranges(source)) +} + /// Lists the nodes declared in `source` as a JSON array of /// `{ fqn, name, kind, triggered }`. A host uses this to populate a diagram's /// target picker: `container` views target a `system`, `component` views a @@ -186,16 +216,14 @@ pub fn emit_scene_modules(modules_json: &str, view: &str, target: &str) -> Resul emit_scene_modules_impl(modules_json, view, target).map_err(|e| JsError::new(&e)) } -/// Resolves the symbol under `offset` (a byte offset) in module `module_fqn` -/// and returns it as JSON `{ info: { fqn, title, body }, svg }`, or `null` when -/// the cursor rests on no resolvable symbol. `svg` is the symbol's fitting -/// diagram ([`project_symbol`]) rendered to a self-contained string — a sequence -/// trace for a callable, a structural view for a node. `modules_json` is the +/// Resolves the symbol under `offset` (a byte offset) in module `module_fqn` and +/// returns it as an LSP `Hover` (`{ contents: { kind, value }, range }`, +/// Markdown), or `null` when the cursor rests on no resolvable symbol. Served by +/// the shared [`pseudoscript_lsp_core::analysis::hover`] — identical to the +/// stdio server's `textDocument/hover`, no diagram. The interactive diagram is a +/// separate concern: [`symbol_scene`] / [`symbol_svg`]. `modules_json` is the /// `[{fqn, source}]` workspace shape. /// -/// The host (an editor hover) shows the info and diagram together; it never -/// decides which diagram a symbol gets — the compiler does. -/// /// # Errors /// /// Returns an error when `modules_json` is not valid JSON of the expected shape. @@ -233,6 +261,46 @@ pub fn references(modules_json: &str, module_fqn: &str, offset: u32) -> Result Result { + rename_apply_impl(modules_json, module_fqn, offset, new_name, selected_json) + .map_err(|e| JsError::new(&e)) +} + +/// Context-aware completion at `offset` (a byte offset) in module `module_fqn`, +/// as a JSON array of LSP `CompletionItem`s (`{label, kind, detail}`, where +/// `kind` is the integer `CompletionItemKind`). Scoped to the trigger before the +/// caret (`.`/`::`/`#[`/type-position/general); the client filters against the +/// typed prefix. Served by the shared [`pseudoscript_lsp_core::complete`] — +/// identical to the stdio server's `textDocument/completion`. `modules_json` is +/// the `[{fqn, source}]` workspace shape. +/// +/// # Errors +/// +/// Returns an error when `modules_json` is not valid JSON of the expected shape. +#[wasm_bindgen] +pub fn completion(modules_json: &str, module_fqn: &str, offset: u32) -> Result { + completion_impl(modules_json, module_fqn, offset).map_err(|e| JsError::new(&e)) +} + /// Projects the fitting diagram for the symbol `fqn` over the whole workspace /// and returns its laid-out [`Scene`] as JSON (the interactive counterpart of /// [`hover`]'s `svg`, for a side panel or full-screen view). See @@ -400,7 +468,7 @@ fn outline_nodes( graph: &Graph, mut line_col: impl FnMut(&str, u32) -> (u32, u32), ) -> Vec { - graph + let mut entries: Vec = graph .nodes() .iter() .map(|n| { @@ -408,14 +476,30 @@ fn outline_nodes( OutlineNode { fqn: n.fqn.clone(), name: n.name.clone(), - kind: n.kind, + kind: n.kind.keyword().to_owned(), triggered: !n.triggers.is_empty(), line, col, parent: n.parent.clone(), } }) - .collect() + .collect(); + // Features are not graph nodes (§5.2); project each scenario as a `feature` + // entry nested under its target node, so the outline lists it as a selectable + // symbol — the host falls back to a single-lifeline scene on selection. + entries.extend(graph.scenarios().iter().map(|s| { + let (line, col) = line_col(&s.module, s.span.start); + OutlineNode { + fqn: format!("{}::{}", s.module, s.name), + name: s.name.clone(), + kind: "feature".to_owned(), + triggered: false, + line, + col, + parent: Some(s.target_fqn.clone()), + } + })); + entries } /// Parses the `[{fqn, source}]` workspace JSON into modules. @@ -461,22 +545,11 @@ fn hover_impl(modules_json: &str, module_fqn: &str, offset: u32) -> Result Result { @@ -570,6 +643,97 @@ fn references_impl(modules_json: &str, module_fqn: &str, offset: u32) -> Result< })) } +/// Whether `name` is a legal `PseudoScript` identifier (`[A-Za-z_]\w*`). +fn is_identifier(name: &str) -> bool { + let mut chars = name.chars(); + chars + .next() + .is_some_and(|c| c.is_ascii_alphabetic() || c == '_') + && chars.all(|c| c.is_ascii_alphanumeric() || c == '_') +} + +fn rename_apply_impl( + modules_json: &str, + module_fqn: &str, + offset: u32, + new_name: &str, + selected_json: &str, +) -> Result { + if !is_identifier(new_name) { + return Err(format!("`{new_name}` is not a valid identifier")); + } + let modules = modules_from_json(modules_json)?; + let selected: Vec = + serde_json::from_str(selected_json).map_err(|e| e.to_string())?; + let chosen: std::collections::HashSet<(String, u32, u32)> = selected + .into_iter() + .map(|s| (s.fqn, s.line, s.col)) + .collect(); + + let src = modules + .iter() + .find(|m| m.fqn == module_fqn) + .map_or("", |m| m.source.as_str()); + let workspace = Workspace::build( + modules + .iter() + .map(|m| (m.fqn.clone(), parse_source(&m.source).ast)), + ); + let pairs: Vec<(String, String)> = modules + .iter() + .map(|m| (m.fqn.clone(), m.source.clone())) + .collect(); + + let mut out: Vec = Vec::new(); + for file in refs::rename(&workspace, &pairs, module_fqn, src, offset) { + let Some(module) = modules.iter().find(|m| m.fqn == file.fqn) else { + continue; + }; + let index = LineIndex::new(&module.source); + // Keep the selected occurrences, then apply them right-to-left so each + // splice leaves the earlier byte offsets valid. + let mut spans: Vec<_> = file + .spans + .into_iter() + .filter(|span| { + let (line, col) = index.line_col(span.start); + chosen.contains(&(file.fqn.clone(), line, col)) + }) + .collect(); + if spans.is_empty() { + continue; + } + spans.sort_by_key(|span| std::cmp::Reverse(span.start)); + let mut source = module.source.clone(); + for span in spans { + source.replace_range(span.start as usize..span.end as usize, new_name); + } + out.push(FileSource { + fqn: file.fqn, + source, + }); + } + Ok(to_json(&out)) +} + +fn completion_impl(modules_json: &str, module_fqn: &str, offset: u32) -> Result { + let modules = modules_from_json(modules_json)?; + let src = modules + .iter() + .find(|m| m.fqn == module_fqn) + .map_or("", |m| m.source.as_str()); + let workspace = Workspace::build( + modules + .iter() + .map(|m| (m.fqn.clone(), parse_source(&m.source).ast)), + ); + let index = LineIndex::new(src); + let position = convert::offset_to_position(src, &index, offset); + Ok(to_json(&complete::completion( + &workspace, module_fqn, src, position, + ))) +} + fn symbol_scene_impl(modules_json: &str, fqn: &str) -> Result { let graph = build_graph(&modules_from_json(modules_json)?); let scene = project_symbol(&graph, fqn).map_err(|e| e.to_string())?; @@ -719,23 +883,6 @@ struct ModuleResult { diagnostics: Vec, } -/// The symbol a [`hover`] resolves to, with its diagram. `info` describes the -/// symbol (its graph `fqn`, a Markdown title, an optional doc/signature body); -/// `svg` is its fitting diagram rendered to a self-contained string. -#[derive(Serialize)] -struct HoverResult { - info: SymbolInfo, - svg: String, -} - -/// A resolved symbol's identity and description, for an editor hover. -#[derive(Serialize)] -struct SymbolInfo { - fqn: String, - title: String, - body: Option, -} - /// One declared node, for the [`outline`] target picker. `kind` serialises /// lowercase (`person`/`system`/`container`/`component`/`data`/`callable`); /// `triggered` marks a callable that carries a trigger macro (a sequence entry). @@ -747,7 +894,9 @@ struct SymbolInfo { struct OutlineNode { fqn: String, name: String, - kind: NodeKind, + /// A node's C4 keyword (`person`/`system`/…/`callable`) or `feature` for a + /// `feature` block — a string, since a feature is not a node kind. + kind: String, triggered: bool, line: u32, col: u32, @@ -780,6 +929,22 @@ struct RefOccurrence { decl: bool, } +/// One occurrence the host chose to rename, keyed by its module `fqn` and the +/// 1-based `line`/`col` [`references`] reported. Input to [`rename_apply`]. +#[derive(Deserialize)] +struct SelectedOccurrence { + fqn: String, + line: u32, + col: u32, +} + +/// One module's rewritten source after a rename — output of [`rename_apply`]. +#[derive(Serialize)] +struct FileSource { + fqn: String, + source: String, +} + /// A diagnostic enriched with 1-based line/column for both span ends, in /// addition to the raw byte offsets. #[derive(Serialize)] @@ -836,9 +1001,9 @@ fn to_json(value: &T) -> String { #[cfg(test)] mod tests { use super::{ - check, check_modules_impl, doc_config, doc_manifest_impl, emit_scene_modules_impl, - format_impl, hover_impl, outline, parse, project_view, references_impl, symbol_scene_impl, - symbol_svg_impl, to_json, + check, check_modules_impl, completion_impl, definition_impl, doc_config, doc_manifest_impl, + emit_scene_modules_impl, format_impl, hover_impl, layout_scene_impl, outline, parse, + project_view, references_impl, symbol_scene_impl, symbol_svg_impl, to_json, }; #[test] @@ -961,6 +1126,18 @@ mod tests { assert!(json.contains(r#""triggered":true"#), "{json}"); } + #[test] + fn outline_lists_features_under_their_target() { + // A `feature` is not a graph node, but the outline lists it as a selectable + // `feature` symbol nested under its target node (`fqn` = `module::name`). + let json = outline( + "//! m\npublic system S;\nfeature F for S {\n given \"a\"\n when \"b\"\n then \"c\"\n}", + ); + assert!(json.contains(r#""kind":"feature""#), "{json}"); + assert!(json.contains(r#""fqn":"m::F""#), "{json}"); + assert!(json.contains(r#""parent":"m::S""#), "{json}"); + } + #[test] fn emit_scene_modules_spans_modules() { // A container in one module, its components (with a call between them) in @@ -975,23 +1152,24 @@ mod tests { } #[test] - fn hover_on_a_node_reference_returns_info_and_a_diagram() { - // Cursor on `Web` in `sys::Web.View()` — resolves to the container. + fn hover_on_a_node_reference_returns_lsp_hover() { + // Cursor on `Web` in `sys::Web.View()` — resolves to the container. The + // result is an `lsp_types::Hover` (markup), no diagram SVG. let offset = (CTX_SRC.find("Web").expect("Web present") + 1) as u32; let json = hover_impl(&workspace_json(), "ctx", offset).expect("hovers"); - assert!(json.contains(r#""fqn":"sys::Web""#), "{json}"); assert!(json.contains("container `sys::Web`"), "{json}"); - // A container resolves to its (structural) component view as an SVG. - assert!(json.contains(" =====` header so the +//! single stream stays unambiguously splittable. + +use std::fmt::Write as _; +use std::fs; +use std::path::{Path, PathBuf}; + +fn main() { + let manifest = + PathBuf::from(std::env::var_os("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR")); + let repo_root = manifest + .join("../..") + .canonicalize() + .expect("workspace root resolves from the crate manifest dir"); + + // Spec and patterns first, then every conformance file sorted by path so a + // case sits next to its expected-output pair (e.g. `*.pds` then `*.tokens`). + let mut files = vec![repo_root.join("LANG.md"), repo_root.join("PATTERNS.md")]; + collect_files(&repo_root.join("CONFORMANCE"), &mut files); + files[2..].sort(); + + let mut bundle = String::new(); + for path in &files { + let rel = path + .strip_prefix(&repo_root) + .expect("every source lives under the repo root"); + let contents = fs::read_to_string(path) + .unwrap_or_else(|err| panic!("reading `{}`: {err}", path.display())); + write!(bundle, "\n\n===== {} =====\n\n", rel.display()) + .expect("writing to a String never fails"); + bundle.push_str(&contents); + println!("cargo:rerun-if-changed={}", path.display()); + } + + let out = PathBuf::from(std::env::var_os("OUT_DIR").expect("OUT_DIR")).join("lang-bundle.md"); + fs::write(&out, bundle).unwrap_or_else(|err| panic!("writing `{}`: {err}", out.display())); +} + +/// Appends every regular file under `dir`, recursively, to `files`. +fn collect_files(dir: &Path, files: &mut Vec) { + println!("cargo:rerun-if-changed={}", dir.display()); + let entries = + fs::read_dir(dir).unwrap_or_else(|err| panic!("reading `{}`: {err}", dir.display())); + for entry in entries { + let path = entry.expect("conformance dir entry").path(); + if path.is_dir() { + collect_files(&path, files); + } else { + files.push(path); + } + } +} diff --git a/crates/pseudoscript/src/main.rs b/crates/pseudoscript/src/main.rs index 644c3ec..4d09c85 100644 --- a/crates/pseudoscript/src/main.rs +++ b/crates/pseudoscript/src/main.rs @@ -2,8 +2,13 @@ //! //! Subcommands wrap the workspace libraries: //! +//! - `pds lang` — print the bundled language reference (spec + patterns + the +//! conformance suite), embedded at compile time. +//! - `pds skill` — print the bundled authoring skill. //! - `pds lsp` — start the language server over stdio ([`pseudoscript_lsp`]). //! - `pds check ` — report diagnostics; exit non-zero on any error. +//! - `pds eval` — read a model from stdin and report diagnostics; for agents +//! checking a snippet without writing a file. //! - `pds fmt [--write]` — canonical formatting. //! - `pds tokens ` — the lexical token stream, for debugging. //! - `pds doc [PATH]` — generate the documentation site @@ -28,13 +33,35 @@ use std::time::Duration; use anyhow::{Context, Result, bail}; use clap::{Parser, Subcommand}; +use pseudoscript_emit::{Theme, View, project, project_symbol, render_svg_themed}; use pseudoscript_format::{FormatError, format}; -use pseudoscript_model::{Diagnostic, check, check_workspace_with_externals, graph}; +use pseudoscript_model::{ + Diagnostic, WorkspaceModule, check, check_workspace_with_externals, graph, +}; use pseudoscript_syntax::{LineIndex, Severity, render_tokens}; +use serde::Serialize; + +/// The full authoring reference (spec + patterns + conformance suite), assembled +/// by `build.rs` and embedded so `pds lang` always matches the installed binary. +const LANG_BUNDLE: &str = include_str!(concat!(env!("OUT_DIR"), "/lang-bundle.md")); + +/// The `PseudoScript` authoring-method skill, embedded verbatim so `pds skill` +/// prints it like any other skill file. +const PDS_SKILL: &str = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/../../.claude/skills/pseudocode/SKILL.md" +)); /// The `PseudoScript` toolchain. #[derive(Debug, Parser)] -#[command(name = "pds", version, about = "PseudoScript toolchain")] +#[command( + name = "pds", + version, + about = "PseudoScript toolchain", + after_help = "Writing .pds files? Run `pds lang` for the full language \ +reference (spec + patterns + grammar suite), or `pds skill` for the authoring \ +method. New here? `pds init` scaffolds a workspace." +)] struct Cli { #[command(subcommand)] command: Command, @@ -53,6 +80,14 @@ enum Command { #[arg(long)] name: Option, }, + /// Print the bundled language reference (spec, patterns, and the full + /// conformance/grammar suite) for this exact version. Feed it to an LLM to + /// author .pds. + #[command(alias = "spec")] + Lang, + /// Print the bundled authoring skill — the method for modelling with .pds. + /// Run `pds lang` for the full grammar. + Skill, /// Start the language server over stdio. Lsp, /// Check a file and report diagnostics (exit non-zero on any error). @@ -66,6 +101,10 @@ enum Command { #[arg(long)] all: bool, }, + /// Read a model from stdin and report diagnostics (exit non-zero on any + /// error). For agents: pipe a snippet to rapidly check it parses and + /// resolves, without writing a file — e.g. `pds eval < model.pds`. + Eval, /// Format a file to canonical `PseudoScript`. Fmt { /// The `.pds` file to format. @@ -79,6 +118,38 @@ enum Command { /// The `.pds` file to tokenize. file: PathBuf, }, + /// Print the workspace's symbol outline as JSON — the structure tree an + /// editor draws (each node's `fqn`, `name`, `kind`, `parent`, whether it is + /// a `triggered` flow entry, and its declaration `module`/`line`/`col`). + Outline { + /// A file or directory inside the workspace; the project root is the + /// nearest enclosing `pds.toml`. Defaults to the current directory. + #[arg(default_value = ".")] + path: PathBuf, + }, + /// Render a single diagram to a self-contained SVG on stdout. With + /// `--symbol`, draws that symbol's fitting view (a system/container's C4 + /// sub-view, or a triggered callable's sequence); otherwise draws `--view` + /// over the whole workspace. + Svg { + /// A file or directory inside the workspace; the project root is the + /// nearest enclosing `pds.toml`. Defaults to the current directory. + #[arg(default_value = ".")] + path: PathBuf, + /// Render the fitting view for this symbol FQN (e.g. `acme::Billing`). + #[arg(long, conflicts_with = "view")] + symbol: Option, + /// Render a whole-workspace view: `context`, or `container`/`component`/ + /// `sequence` paired with `--target`. Defaults to `context`. + #[arg(long, conflicts_with = "symbol")] + view: Option, + /// The target FQN a `container`/`component`/`sequence` view is `of`. + #[arg(long, requires = "view")] + target: Option, + /// Colour theme: `light` (default) or `dark`. + #[arg(long, default_value = "light")] + theme: String, + }, /// Generate the documentation site for the workspace. Doc { /// A file or directory inside the workspace; the project root is the @@ -146,6 +217,8 @@ fn main() -> ExitCode { let cli = Cli::parse(); match cli.command { Command::Init { path, name } => cmd_init(&path, name.as_deref()), + Command::Lang => cmd_lang(), + Command::Skill => cmd_skill(), Command::Lsp => run_lsp(), Command::Check { file, all } => { if all { @@ -154,8 +227,23 @@ fn main() -> ExitCode { cmd_check(&file) } } + Command::Eval => cmd_eval(), Command::Fmt { file, write } => cmd_fmt(&file, write), Command::Tokens { file } => cmd_tokens(&file), + Command::Outline { path } => cmd_outline(&path), + Command::Svg { + path, + symbol, + view, + target, + theme, + } => cmd_svg( + &path, + symbol.as_deref(), + view.as_deref(), + target.as_deref(), + &theme, + ), Command::Doc { path, serve, @@ -185,6 +273,20 @@ fn main() -> ExitCode { } } +/// `pds lang`: print the embedded reference bundle verbatim to stdout. The blob +/// already ends in a newline, so `print!` reproduces it byte-for-byte. +fn cmd_lang() -> ExitCode { + print!("{LANG_BUNDLE}"); + ExitCode::SUCCESS +} + +/// `pds skill`: print the embedded authoring skill. The source has no trailing +/// newline, so add one for a clean terminal. +fn cmd_skill() -> ExitCode { + println!("{}", PDS_SKILL.trim_end_matches('\n')); + ExitCode::SUCCESS +} + /// `pds upgrade`: download and install a release over the running binary. fn cmd_upgrade(version: Option) -> ExitCode { report(upgrade::run(version)) @@ -446,14 +548,32 @@ fn cmd_check(path: &Path) -> ExitCode { Ok(src) => src, Err(code) => return code, }; - let index = LineIndex::new(&src); - let diagnostics = check(&src); + report_source(&path.display().to_string(), &src) +} + +/// `pds eval`: read a model from stdin and report diagnostics, exiting non-zero +/// on any error. Lets an agent check a snippet's syntax and resolution without +/// touching disk — `pds eval < model.pds` or a piped here-doc. +fn cmd_eval() -> ExitCode { + match std::io::read_to_string(std::io::stdin()) { + Ok(src) => report_source("", &src), + Err(err) => { + eprintln!(": {err}"); + ExitCode::FAILURE + } + } +} + +/// Run `check` over a single source buffer, printing each diagnostic to stderr +/// as `label:line:col: severity: message`. `label` is the file path or +/// ``. Returns `FAILURE` if any diagnostic is an error, else `SUCCESS`. +fn report_source(label: &str, src: &str) -> ExitCode { + let index = LineIndex::new(src); let mut had_error = false; - for diag in &diagnostics { + for diag in &check(src) { let (line, col) = index.line_col(diag.span.start); eprintln!( - "{}:{line}:{col}: {}: {}", - path.display(), + "{label}:{line}:{col}: {}: {}", severity_label(diag.severity), diag.message ); @@ -505,6 +625,164 @@ fn cmd_tokens(path: &Path) -> ExitCode { ExitCode::SUCCESS } +/// One entry in `pds outline` — a declared node, for an editor's structure tree. +/// Mirrors the workspace outline the web IDE builds, so the two agree on shape. +#[derive(Serialize)] +struct OutlineNode { + /// Fully-qualified name (the diagram/navigation key). + fqn: String, + /// The bare declared name shown in the tree. + name: String, + /// One of `person`/`system`/`container`/`component`/`data`/`callable`. + kind: &'static str, + /// The structural parent's FQN, if any (a node may nest under another + /// module's node, so the tree is workspace-wide). + #[serde(skip_serializing_if = "Option::is_none")] + parent: Option, + /// True for a callable that triggers a flow — its fitting diagram is a + /// sequence rather than a C4 view. + triggered: bool, + /// The module that declares it, and the 1-based position of its name (so a + /// host can offer go-to-definition). + module: String, + line: u32, + col: u32, +} + +/// Loads every module of the workspace enclosing `path` (the nearest `pds.toml`), +/// reporting a clear error to stderr on failure. +fn workspace_modules(path: &Path) -> Result, ExitCode> { + let fail = |err: anyhow::Error| { + eprintln!("error: {err:#}"); + ExitCode::FAILURE + }; + let root = workspace::find_root(path).map_err(fail)?; + workspace::load_modules(&root).map_err(fail) +} + +/// `pds outline`: print the workspace's symbol outline as JSON. +fn cmd_outline(path: &Path) -> ExitCode { + let modules = match workspace_modules(path) { + Ok(modules) => modules, + Err(code) => return code, + }; + // One line index per module so a node's byte offset maps to its 1-based + // position in the module that declares it. + let indices: std::collections::HashMap<&str, LineIndex> = modules + .iter() + .map(|m| (m.fqn.as_str(), LineIndex::new(&m.source))) + .collect(); + let line_col = |module: &str, offset| { + indices + .get(module) + .map_or((1, 1), |idx| idx.line_col(offset)) + }; + let graph = graph(&modules); + let nodes = graph.nodes().iter().map(|n| { + let (line, col) = line_col(n.module.as_str(), n.span.start); + OutlineNode { + fqn: n.fqn.clone(), + name: n.name.clone(), + kind: n.kind.keyword(), + parent: n.parent.clone(), + triggered: !n.triggers.is_empty(), + module: n.module.clone(), + line, + col, + } + }); + // Features are not graph nodes (§5.2); list each as a `feature` entry nested + // under its target node, so `pds outline` agrees with the web IDE's outline. + let features = graph.scenarios().iter().map(|s| { + let (line, col) = line_col(s.module.as_str(), s.span.start); + OutlineNode { + fqn: format!("{}::{}", s.module, s.name), + name: s.name.clone(), + kind: "feature", + parent: Some(s.target_fqn.clone()), + triggered: false, + module: s.module.clone(), + line, + col, + } + }); + let outline: Vec = nodes.chain(features).collect(); + match serde_json::to_string_pretty(&outline) { + Ok(json) => { + println!("{json}"); + ExitCode::SUCCESS + } + Err(err) => { + eprintln!("error: {err}"); + ExitCode::FAILURE + } + } +} + +/// `pds svg`: render one diagram to a self-contained SVG on stdout. `--symbol` +/// draws that symbol's fitting view; otherwise `--view` (+ `--target`) draws a +/// whole-workspace view. +fn cmd_svg( + path: &Path, + symbol: Option<&str>, + view: Option<&str>, + target: Option<&str>, + theme: &str, +) -> ExitCode { + let theme = match theme { + "light" => Theme::Light, + "dark" => Theme::Dark, + other => { + eprintln!("error: unknown theme `{other}` (expected `light` or `dark`)"); + return ExitCode::FAILURE; + } + }; + let modules = match workspace_modules(path) { + Ok(modules) => modules, + Err(code) => return code, + }; + let g = graph(&modules); + let scene = if let Some(fqn) = symbol { + project_symbol(&g, fqn) + } else { + let view = match resolve_view(view.unwrap_or("context"), target.unwrap_or("")) { + Ok(view) => view, + Err(err) => { + eprintln!("error: {err:#}"); + return ExitCode::FAILURE; + } + }; + project(&g, view) + }; + match scene { + Ok(scene) => { + print!("{}", render_svg_themed(&scene, theme)); + ExitCode::SUCCESS + } + Err(err) => { + eprintln!("error: {err}"); + ExitCode::FAILURE + } + } +} + +/// Resolves a `--view`/`--target` pair into an emit [`View`]. +fn resolve_view(view: &str, target: &str) -> Result { + Ok(match view { + "context" => View::Context, + "container" => View::Container { + of: target.to_owned(), + }, + "component" => View::Component { + of: target.to_owned(), + }, + "sequence" => View::Sequence { + entry: target.to_owned(), + }, + other => bail!("unknown view `{other}` (expected context/container/component/sequence)"), + }) +} + /// `pds doc`: generate the documentation site for the workspace rooted at the /// nearest `pds.toml`. /// diff --git a/crates/pseudoscript/tests/cli.rs b/crates/pseudoscript/tests/cli.rs index 049cddf..1e8d6d4 100644 --- a/crates/pseudoscript/tests/cli.rs +++ b/crates/pseudoscript/tests/cli.rs @@ -111,11 +111,34 @@ fn run(world: &mut CliWorld, args: &[&str]) { world.stderr = String::from_utf8_lossy(&output.stderr).into_owned(); } +/// Runs `pds` with `args` and no trailing path target, capturing the result. +fn run_bare(world: &mut CliWorld, args: &[&str]) { + let output = pds().args(args).output().expect("run pds"); + world.exit_code = output.status.code(); + world.stdout = String::from_utf8_lossy(&output.stdout).into_owned(); + world.stderr = String::from_utf8_lossy(&output.stderr).into_owned(); +} + #[when("I run pds check")] fn run_check(world: &mut CliWorld) { run(world, &["check"]); } +#[when("I run pds lang")] +fn run_lang(world: &mut CliWorld) { + run_bare(world, &["lang"]); +} + +#[when("I run pds spec")] +fn run_spec(world: &mut CliWorld) { + run_bare(world, &["spec"]); +} + +#[when("I run pds skill")] +fn run_skill(world: &mut CliWorld) { + run_bare(world, &["skill"]); +} + #[when("I run pds tokens")] fn run_tokens(world: &mut CliWorld) { run(world, &["tokens"]); @@ -137,6 +160,21 @@ fn run_doc(world: &mut CliWorld) { world.out_dir = Some(world.target.join("target/doc")); } +#[when("I run pds outline on the workspace")] +fn run_outline(world: &mut CliWorld) { + run(world, &["outline"]); +} + +#[when("I run pds svg for the context view")] +fn run_svg_context(world: &mut CliWorld) { + run(world, &["svg", "--view", "context"]); +} + +#[when("I run pds svg for an unknown symbol")] +fn run_svg_unknown(world: &mut CliWorld) { + run(world, &["svg", "--symbol", "nope::Nope"]); +} + // --- then ------------------------------------------------------------------- #[then("the exit code is zero")] @@ -169,6 +207,17 @@ fn stderr_contains(world: &mut CliWorld, needle: String) { ); } +#[then(regex = r#"^stdout contains "(.+)"$"#)] +// cucumber parses each regex capture into an owned `String`; `&str` won't compile here. +#[allow(clippy::needless_pass_by_value)] +fn stdout_contains(world: &mut CliWorld, needle: String) { + assert!( + world.stdout.contains(&needle), + "stdout {:?} did not contain {needle:?}", + world.stdout + ); +} + #[then(regex = r#"^stdout equals the golden "(.+)"$"#)] fn stdout_equals_golden(world: &mut CliWorld, rel: String) { let golden = std::fs::read_to_string(conformance_dir().join(rel)).expect("read golden"); diff --git a/crates/pseudoscript/tests/eval.rs b/crates/pseudoscript/tests/eval.rs new file mode 100644 index 0000000..049ae2c --- /dev/null +++ b/crates/pseudoscript/tests/eval.rs @@ -0,0 +1,47 @@ +//! Integration tests for `pds eval`: read a model from stdin and report +//! diagnostics, exiting non-zero on any error. The stdin path is what lets an +//! agent check a snippet without writing a file. + +use assert_cmd::Command as AssertCommand; + +/// A built `pds eval` command, ready for `.write_stdin(..)`. +fn pds_eval() -> AssertCommand { + let mut cmd = AssertCommand::cargo_bin("pds").expect("pds binary built"); + cmd.arg("eval"); + cmd +} + +#[test] +fn eval_accepts_a_well_formed_model() { + pds_eval() + .write_stdin("//! m\n\npublic system AcmeTickets;\n") + .assert() + .success(); +} + +#[test] +fn eval_reports_argument_type_mismatch_and_exits_nonzero() { + let src = "//! m\n\ +\n\ +public system S;\n\ +public data Money;\n\ +\n\ +public container C for S {\n\ + run(): void { self.charge(\"free\") }\n\ + charge(amt: Money): void { }\n\ +}\n"; + let output = pds_eval().write_stdin(src).output().expect("run pds eval"); + assert!( + !output.status.success(), + "expected non-zero exit on a type error" + ); + let stderr = String::from_utf8_lossy(&output.stderr); + assert!( + stderr.contains("argument 1: expected `Money`, found `string`"), + "diagnostic not found in stderr:\n{stderr}" + ); + assert!( + stderr.contains(":"), + "diagnostics should be labelled :\n{stderr}" + ); +} diff --git a/crates/pseudoscript/tests/features/lang.feature b/crates/pseudoscript/tests/features/lang.feature new file mode 100644 index 0000000..6813adb --- /dev/null +++ b/crates/pseudoscript/tests/features/lang.feature @@ -0,0 +1,22 @@ +Feature: pds lang + + Scenario: prints the full bundled grammar suite in one stream + When I run pds lang + Then the exit code is zero + And stderr is empty + And stdout contains "# PseudoScript" + And stdout contains "===== LANG.md =====" + And stdout contains "===== PATTERNS.md =====" + And stdout contains "===== CONFORMANCE/lexical/2-1-comments-and-docs.pds =====" + + Scenario: the spec alias prints the same bundle + When I run pds spec + Then the exit code is zero + And stdout contains "===== LANG.md =====" + + Scenario: prints the authoring skill, signposting the lang spec + When I run pds skill + Then the exit code is zero + And stderr is empty + And stdout contains "name: pseudoscript" + And stdout contains "pds lang" diff --git a/crates/pseudoscript/tests/features/outline.feature b/crates/pseudoscript/tests/features/outline.feature new file mode 100644 index 0000000..a87326d --- /dev/null +++ b/crates/pseudoscript/tests/features/outline.feature @@ -0,0 +1,17 @@ +Feature: pds outline + + Scenario: the workspace outline lists declared nodes with their kinds + Given a writable copy of fixture workspace "ws" + When I run pds outline on the workspace + Then the exit code is zero + And stdout contains "banking::core::Banking" + And stdout contains ""kind": "system"" + And stdout contains ""kind": "person"" + + Scenario: the workspace outline lists feature blocks under their target + Given a writable copy of fixture workspace "ws" + When I run pds outline on the workspace + Then the exit code is zero + And stdout contains "banking::core::OpenAccount" + And stdout contains ""kind": "feature"" + And stdout contains ""parent": "banking::core::Banking"" diff --git a/crates/pseudoscript/tests/features/svg.feature b/crates/pseudoscript/tests/features/svg.feature new file mode 100644 index 0000000..21a42a3 --- /dev/null +++ b/crates/pseudoscript/tests/features/svg.feature @@ -0,0 +1,13 @@ +Feature: pds svg + + Scenario: the context view renders a self-contained SVG + Given a writable copy of fixture workspace "ws" + When I run pds svg for the context view + Then the exit code is zero + And stdout contains " { - config = self.loadManifest(root) + config: Result = self.loadManifest(root) if (config.isErr) { return Err(config.error) } - modules = self.loadModules(root) + modules: Result = self.loadModules(root) if (modules.isErr) { return Err(modules.error) } - project = Workspace from { config.value, root, modules.value } + project: Workspace = Workspace from { config.value, root, modules.value } return Ok(project) } @@ -81,7 +81,7 @@ component Loader for Cli { component InitCmd for Cli { #[manual] public run(path: string, name: string): Result { - exists = self.manifestExists(path) + exists: Result = self.manifestExists(path) if (exists.isErr) { return Err(exists.error) } @@ -106,19 +106,19 @@ public component DocCmd for Cli { /// Invoked by the Developer (`context::Developer.renderDocs`). /// #headline public run(path: string): Result { - root = Cli::Loader.findRoot(path) + root: Result = Cli::Loader.findRoot(path) if (root.isErr) { return Err(root.error) } - project = Cli::Loader.load(root.value) + project: Result = Cli::Loader.load(root.value) if (project.isErr) { return Err(project.error) } - diagnostics = model::Checks.checkWorkspace(project.value.modules) + diagnostics: syntax::Diagnostic[] = model::Checks.checkWorkspace(project.value.modules) self.report(diagnostics) - graph = model::Builder.graph(project.value.modules) - site = doc::SiteBuilder.render(graph, project.value.config) - written = self.write(site, project.value.outDir) + graph: Graph = model::Builder.graph(project.value.modules) + site: Result = doc::SiteBuilder.render(graph, project.value.config) + written: Result = self.write(site, project.value.outDir) if (written.isErr) { return Err(written.error) } @@ -130,7 +130,7 @@ public component DocCmd for Cli { /// `watch` is set. `watch` implies `serve`. #[manual] public serve(path: string, serve: bool, watch: bool, port: number): Result { - built = self.run(path) + built: Result = self.run(path) if (built.isErr) { return Err(built.error) } @@ -158,9 +158,9 @@ public component DocCmd for Cli { component CheckCmd for Cli { #[manual] public run(text: string): Result { - diagnostics = model::Checks.check(text) + diagnostics: syntax::Diagnostic[] = model::Checks.check(text) if (self.anyError(diagnostics)) { - err = IoError from { diagnostics } + err: IoError = IoError from { diagnostics } return Err(err) } return Ok @@ -176,7 +176,7 @@ component CheckCmd for Cli { component FmtCmd for Cli { #[manual] public run(text: string, write: bool): Result { - out = format::Formatter.format(text) + out: Result = format::Formatter.format(text) if (out.isErr) { return Err(out.error) } @@ -199,7 +199,7 @@ component FmtCmd for Cli { component TokensCmd for Cli { #[manual] public run(text: string): Result { - stream = syntax::Lexer.renderTokens(text) + stream: string = syntax::Lexer.renderTokens(text) self.print(stream) return Ok } diff --git a/pseudoscript/doc.pds b/pseudoscript/doc.pds index ddcdd19..5600c48 100644 --- a/pseudoscript/doc.pds +++ b/pseudoscript/doc.pds @@ -125,29 +125,29 @@ public component SiteBuilder for Doc { /// shared assets. Any failed server-render aborts with its `RenderError`. public render(graph: model::Graph, config: DocConfig): Result { Doc::Urls.build(graph) - modules = Doc::Pages.sortedModules(graph) - index = self.emitPage("index.html", Doc::Pages.index(graph, config, modules)) + modules: string[] = Doc::Pages.sortedModules(graph) + index: Result = self.emitPage("index.html", Doc::Pages.index(graph, config, modules)) if (index.isErr) { return Err(index.error) } for (m in modules) { - page = self.emitPage(Doc::Urls.modulePagePath(m), Doc::Pages.modulePage(graph, config, m, modules)) + page: Result = self.emitPage(Doc::Urls.modulePagePath(m), Doc::Pages.modulePage(graph, config, m, modules)) if (page.isErr) { return Err(page.error) } } - assets = Doc::Assets.shared() + assets: SiteFile[] = Doc::Assets.shared() return Ok(Site from { index, modules, assets }) } /// Render one page: server-render its props through the engine, then wrap the /// `{head, body}` result in the document shell. Propagates a `RenderError`. emitPage(path: string, props: PageProps): Result { - rendered = Doc::Ssr.renderPage(props) + rendered: Result = Doc::Ssr.renderPage(props) if (rendered.isErr) { return Err(rendered.error) } - html = Doc::Shell.wrap(path, props, rendered.value) + html: string = Doc::Shell.wrap(path, props, rendered.value) return Ok(SiteFile from { path, html }) } } @@ -159,29 +159,29 @@ component Pages for Doc { /// The index props: the shared sidebar, a card per module, and the system-context /// diagram. index(graph: model::Graph, config: DocConfig, modules: string[]): PageProps { - sidebar = self.sidebar(graph, modules, "") - cards = self.moduleCards(graph, modules) - context = Doc::Diagrams.context(graph) - body = IndexPage from { config, context, cards } + sidebar: SidebarModule[] = self.sidebar(graph, modules, "") + cards: ModuleCard[] = self.moduleCards(graph, modules) + context: Diagram = Doc::Diagrams.context(graph) + body: IndexPage = IndexPage from { config, context, cards } return PageProps from { config, sidebar, body } } /// One module page's props: the sidebar (prefixed `../` for the page's depth) and /// a section per non-callable node declared in the module, sorted by FQN. modulePage(graph: model::Graph, config: DocConfig, module: string, modules: string[]): PageProps { - sidebar = self.sidebar(graph, modules, "../") - nodes = self.moduleNodes(graph, module) - sections = self.sections(graph, nodes) - body = ModulePage from { module, sections } + sidebar: SidebarModule[] = self.sidebar(graph, modules, "../") + nodes: model::GraphNode[] = self.moduleNodes(graph, module) + sections: NodeSection[] = self.sections(graph, nodes) + body: ModulePage = ModulePage from { module, sections } return PageProps from { config, sidebar, body } } /// One node section: head fields, `///` docs, tags, relationships, scenario cards, /// and embedded diagrams. section(graph: model::Graph, node: model::GraphNode): NodeSection { - rels = Doc::Relationships.groups(graph, node) - cards = Doc::Scenarios.cards(graph, node) - diagrams = Doc::Diagrams.forNode(graph, node) + rels: RelGroup[] = Doc::Relationships.groups(graph, node) + cards: ScenarioCard[] = Doc::Scenarios.cards(graph, node) + diagrams: Diagram[] = Doc::Diagrams.forNode(graph, node) return NodeSection from { node, rels, cards, diagrams } } @@ -228,7 +228,7 @@ component Shell for Doc { /// hydration, link the depth-relative `style.css` and `client.js`, and mount the /// body into `#app`. wrap(path: string, props: PageProps, rendered: RenderedPage): string { - title = Doc::Escape.text(props.site.name) + title: string = Doc::Escape.text(props.site.name) return self.document(path, title, props, rendered) } @@ -244,9 +244,9 @@ component Relationships for Doc { /// The relationship groups for `node`: parent, inbound, then outbound. Empty when /// the node has no parent and no edges. groups(graph: model::Graph, node: model::GraphNode): RelGroup[] { - parent = self.parentGroup(graph, node) - inbound = self.inboundGroup(graph, node) - outbound = self.outboundGroup(graph, node) + parent: RelGroup[] = self.parentGroup(graph, node) + inbound: RelGroup[] = self.inboundGroup(graph, node) + outbound: RelGroup[] = self.outboundGroup(graph, node) return self.collect(parent, inbound, outbound) } @@ -268,12 +268,12 @@ component Relationships for Doc { /// A `RelItem` for `fqn`: a resolved href when it names a node, absent (rendering /// plain text) otherwise (LANG.md §9.3). item(fqn: string, kind: model::EdgeKind, arrow: bool, label: string): RelItem { - edgeKind = self.edgeKindLabel(kind) - href = Doc::Urls.hrefTo(fqn) + edgeKind: string = self.edgeKindLabel(kind) + href: Result = Doc::Urls.hrefTo(fqn) if (href.isErr) { return RelItem from { fqn, edgeKind, arrow, label } } - link = href.value + link: string = href.value return RelItem from { fqn, edgeKind, arrow, label, link } } @@ -288,7 +288,7 @@ component Scenarios for Doc { /// The scenario cards for `node`: one per feature targeting it, with name, `///` /// docs, tags, and ordered steps. Empty when the node has no scenarios. cards(graph: model::Graph, node: model::GraphNode): ScenarioCard[] { - scenarios = self.scenariosOf(graph, node) + scenarios: model::Scenario[] = self.scenariosOf(graph, node) return self.toCards(scenarios) } @@ -333,7 +333,7 @@ component Diagrams for Doc { /// `Empty` placeholder on an `EmitError` (e.g. an empty boundary), so a failed /// projection never aborts the build. figure(graph: model::Graph, view: emit::View, eyebrow: string, caption: string): Diagram { - scene = emit::Projector.project(graph, view) + scene: Result = emit::Projector.project(graph, view) if (scene.isErr) { return Empty from { caption, eyebrow } } @@ -387,7 +387,7 @@ component Urls for Doc { /// The module-page-relative `href` to `fqn` (`.html#`), or an error /// when `fqn` resolves to no node. hrefTo(fqn: string): Result { - url = self.get(fqn) + url: Result = self.get(fqn) if (url.isErr) { return Err(url.error) } diff --git a/pseudoscript/emit.pds b/pseudoscript/emit.pds index 6b1bc18..9000264 100644 --- a/pseudoscript/emit.pds +++ b/pseudoscript/emit.pds @@ -122,8 +122,8 @@ public component Projector for Emit { /// The context view: every person and system, with inter-system edges and /// triggers. A cross-container call bubbles to a single system → system edge. projectContext(graph: model::Graph): Scene { - nodes = self.collectKinds(graph, "person", "system") - edges = Emit::Edges.collect(graph, nodes) + nodes: PlacedNode[] = self.collectKinds(graph, "person", "system") + edges: RoutedEdge[] = Emit::Edges.collect(graph, nodes) return Emit::Layout.solveC4(C4Scene from { nodes, edges }) } @@ -131,12 +131,12 @@ public component Projector for Emit { /// with edges among them lifted to the contained child. Errors when `of` is /// missing or not of `boundary` kind. projectBoundary(graph: model::Graph, of: string, boundary: string, child: string): Result { - anchor = self.requireKind(graph, of, boundary) + anchor: Result = self.requireKind(graph, of, boundary) if (anchor.isErr) { return Err(anchor.error) } - nodes = self.childrenOf(graph, of, child) - edges = Emit::Edges.collect(graph, nodes) + nodes: PlacedNode[] = self.childrenOf(graph, of, child) + edges: RoutedEdge[] = Emit::Edges.collect(graph, nodes) return Ok(Emit::Layout.solveC4(C4Scene from { of, nodes, edges })) } @@ -144,22 +144,22 @@ public component Projector for Emit { /// frames (LANG.md §9.2). Errors when the entry is not a callable, or has no /// disclosed body to trace. projectSequence(graph: model::Graph, entry: string): Result { - node = self.requireKind(graph, entry, "callable") + node: Result = self.requireKind(graph, entry, "callable") if (node.isErr) { return Err(node.error) } - body = self.bodyOf(graph, entry) + body: Result = self.bodyOf(graph, entry) if (body.isErr) { return Err(NoBody from { entry }) } - scene = Emit::Trace.walk(graph, entry, body.value) + scene: Scene = Emit::Trace.walk(graph, entry, body.value) return Ok(Emit::Layout.solveSequence(scene)) } /// Looks a node up and asserts its C4 kind, mapping a miss to `UnknownNode` /// and a mismatch to `WrongKind`. Reads the kind off the graph's nodes. requireKind(graph: model::Graph, fqn: string, expected: string): Result { - found = self.kindOf(graph, fqn) + found: Result = self.kindOf(graph, fqn) if (found.isErr) { return Err(UnknownNode from { fqn }) } @@ -195,7 +195,7 @@ public component Projector for Emit { component Edges for Emit { /// Collect the in-view routed edges for the nodes already placed in a scene. collect(graph: model::Graph, inView: PlacedNode[]): RoutedEdge[] { - routed = self.route(graph, inView) + routed: RoutedEdge[] = self.route(graph, inView) return self.sortDedup(routed) } @@ -224,9 +224,9 @@ component Trace for Emit { /// first lifeline; the body trace registers every other participant on first /// appearance. walk(graph: model::Graph, entry: string, body: model::Step[]): Scene { - owner = self.ownerOf(graph, entry) - items = self.traceItems(body, owner) - participants = self.participantsOf(graph, owner, items) + owner: string = self.ownerOf(graph, entry) + items: SeqItem[] = self.traceItems(body, owner) + participants: Lifeline[] = self.participantsOf(graph, owner, items) return SequenceScene from { entry, participants, items } } @@ -250,7 +250,7 @@ component Layout for Emit { /// boundary box. The renderer's Sugiyama pass refines this; this assigns the /// fallback rects. solveC4(scene: Scene): Scene { - acyclic = self.breakCycles(scene) + acyclic: RoutedEdge[] = self.breakCycles(scene) return self.placeC4(scene, acyclic) } diff --git a/pseudoscript/format.pds b/pseudoscript/format.pds index 3fae795..7f7708f 100644 --- a/pseudoscript/format.pds +++ b/pseudoscript/format.pds @@ -38,13 +38,13 @@ public component Formatter for Format { /// rendered messages and leave the source unrewritten; otherwise print the /// tree. public format(text: string): Result { - parsed = syntax::Parser.parse(text) + parsed: Parsed = syntax::Parser.parse(text) if (self.hasErrors(parsed)) { - errors = self.collectErrors(parsed) - err = FormatError from { errors } + errors: string[] = self.collectErrors(parsed) + err: FormatError = FormatError from { errors } return Err(err) } - out = Format::Printer.print(parsed.ast) + out: string = Format::Printer.print(parsed.ast) return Ok(out) } @@ -79,8 +79,8 @@ component Printer for Format { /// the `//!` inner docs, a blank separator if items follow, then each item in /// source order. print(ast: syntax::Module): string { - state = self.writeModule(ast) - out = self.finish(state) + state: PrinterState = self.writeModule(ast) + out: string = self.finish(state) return out } diff --git a/pseudoscript/lsp.pds b/pseudoscript/lsp.pds index 504aeec..ec58630 100644 --- a/pseudoscript/lsp.pds +++ b/pseudoscript/lsp.pds @@ -75,7 +75,7 @@ public component Server for Lsp { /// the editor against its own file. Computed under the store lock, published /// without it. publishAll(): void { - payloads = Lsp::Store.diagnostics() + payloads: model::ModuleDiagnostics[] = Lsp::Store.diagnostics() for (p in payloads) { self.publish(p.fqn, p.diagnostics) } @@ -86,15 +86,15 @@ public component Server for Lsp { /// Hover the symbol under the cursor in the active document. hover(uri: string, line: number, col: number): string { - text = Lsp::Store.source(uri) + text: string = Lsp::Store.source(uri) return Lsp::Analysis.hover(text, line, col) } /// Go-to-definition: resolve the cursor; if it resolves, map the target FQN /// back to its file and span. Nothing under the cursor yields no location. gotoDefinition(uri: string, line: number, col: number): Option { - text = Lsp::Store.source(uri) - target = Lsp::Analysis.definition(text, line, col) + text: string = Lsp::Store.source(uri) + target: Option = Lsp::Analysis.definition(text, line, col) if (target.isNone) { return None } @@ -103,7 +103,7 @@ public component Server for Lsp { /// Whole-document formatting edit, or nothing when the buffer does not parse. formatting(uri: string): string { - text = Lsp::Store.source(uri) + text: string = Lsp::Store.source(uri) return Lsp::Analysis.formatEdit(text) } @@ -135,7 +135,7 @@ component Store for Lsp { /// The memoised resolved workspace, rebuilt from cached parses on first use /// after an edit. Backs hover, definition, completion, references. workspace(): model::ModuleEntry[] { - entries = model::Checks.checkWorkspace(self.modules()) + entries: syntax::Diagnostic[] = model::Checks.checkWorkspace(self.modules()) return self.entries() } @@ -177,8 +177,8 @@ component Analysis for Lsp { /// signature plus any `///` summary. Falls back to a local binding's inferred /// type when the cursor resolves to no declaration. hover(text: string, line: number, col: number): string { - offset = Lsp::Convert.positionToOffset(text, line, col) - hit = Lsp::Resolve.resolveAt(text, offset) + offset: number = Lsp::Convert.positionToOffset(text, line, col) + hit: Result = Lsp::Resolve.resolveAt(text, offset) if (hit.isErr) { return Lsp::Infer.bindingHover(text, offset) } @@ -189,12 +189,12 @@ component Analysis for Lsp { /// files, through aliases, and into `self.`/node members; `None` when the /// cursor rests on nothing resolvable. definition(text: string, line: number, col: number): Option { - offset = Lsp::Convert.positionToOffset(text, line, col) - hit = Lsp::Resolve.resolveAt(text, offset) + offset: number = Lsp::Convert.positionToOffset(text, line, col) + hit: Result = Lsp::Resolve.resolveAt(text, offset) if (hit.isErr) { return None } - target = DefTarget from { hit.value } + target: DefTarget = DefTarget from { hit.value } return Some(target) } @@ -212,8 +212,8 @@ component Resolve for Lsp { /// definition. Tokenizes, picks the identifier (or the one ending at the /// caret), then dispatches: a `.member`, a self/field declaration, or a path. resolveAt(text: string, offset: number): Result { - tokens = syntax::Lexer.tokenize(text) - idx = self.identIndex(tokens, offset) + tokens: Token[] = syntax::Lexer.tokenize(text) + idx: Result = self.identIndex(tokens, offset) if (idx.isErr) { return Err(idx.error) } @@ -282,8 +282,8 @@ component Semantic for Lsp { /// The semantic tokens for the source as a full-document set: run both passes, /// then encode. semanticTokens(text: string): string { - raws = self.tokenPass(text) - coloured = self.astPass(text) + raws: syntax::Token[] = self.tokenPass(text) + coloured: syntax::Token[] = self.astPass(text) return self.encode(text, coloured) } @@ -350,8 +350,8 @@ component Refs for Lsp { component Complete for Lsp { /// Completion items for the caret position: dispatch on the trigger token. completion(text: string, line: number, col: number): string { - offset = Lsp::Convert.positionToOffset(text, line, col) - tokens = syntax::Lexer.tokenize(text) + offset: number = Lsp::Convert.positionToOffset(text, line, col) + tokens: Token[] = syntax::Lexer.tokenize(text) return self.dispatch(tokens, offset) } diff --git a/pseudoscript/model.pds b/pseudoscript/model.pds index 0beec0c..0d27b53 100644 --- a/pseudoscript/model.pds +++ b/pseudoscript/model.pds @@ -198,7 +198,7 @@ public component Resolver for Model { /// hoisted inline union variants); an alias records a binding; a feature adds /// nothing to this table — its name lives in a separate namespace. public build(ast: syntax::Module): SymbolTable { - path = self.modulePath(ast) + path: string = self.modulePath(ast) return self.buildWithPath(ast, path) } @@ -233,7 +233,7 @@ public component Workspace for Model { /// the global index keys on the correct cross-module names. public build(modules: WorkspaceModule[]): ModuleEntry[] { for (m in modules) { - parsed = syntax::Parser.parse(m.text) + parsed: Parsed = syntax::Parser.parse(m.text) Model::Resolver.buildWithPath(parsed.ast, m.fqn) } return self.collect(modules) @@ -249,7 +249,7 @@ public component Workspace for Model { /// §8.2 visibility rule: a same-module target resolves regardless of /// visibility; a cross-module target resolves only if it is `public`. public resolveQualified(fromModule: string, fqn: string): Resolution { - sym = self.symbol(fqn) + sym: Symbol = self.symbol(fqn) if (self.sameModule(fromModule, fqn)) { return Public from { sym } } @@ -272,8 +272,8 @@ public component Checks for Model { /// Parse and statically analyze one module's source: parse errors followed by /// the static-analysis errors. The CLI's `pds check` driver. public check(text: string): syntax::Diagnostic[] { - parsed = syntax::Parser.parse(text) - static = self.analyze(parsed.ast) + parsed: Parsed = syntax::Parser.parse(text) + static: syntax::Diagnostic[] = self.analyze(parsed.ast) return syntax::Diagnostic[] from { parsed.diagnostics, static } } @@ -281,7 +281,7 @@ public component Checks for Model { /// parse across diagnostics, hover, and definition. Returns only static /// diagnostics; the caller supplies the parse diagnostics. public analyze(ast: syntax::Module): syntax::Diagnostic[] { - model = Model::Resolver.build(ast) + model: SymbolTable = Model::Resolver.build(ast) return self.run(ast, model) } @@ -289,7 +289,7 @@ public component Checks for Model { /// static errors, then the cross-module visibility pass. Parses each module /// before resolving the workspace. public checkWorkspace(modules: WorkspaceModule[]): syntax::Diagnostic[] { - entries = Model::Workspace.build(modules) + entries: ModuleEntry[] = Model::Workspace.build(modules) return self.runWorkspace(entries) } @@ -301,8 +301,8 @@ public component Checks for Model { /// Runs every per-module check against a parsed module and its resolved model: /// variant collisions, feature collisions, then each item's checks. run(ast: syntax::Module, model: SymbolTable): syntax::Diagnostic[] { - variants = Model::VariantCollision.check(ast) - features = Model::FeatureCheck.check(ast, model) + variants: syntax::Diagnostic[] = Model::VariantCollision.check(ast) + features: syntax::Diagnostic[] = Model::FeatureCheck.check(ast, model) return syntax::Diagnostic[] from { variants, features } } @@ -408,7 +408,7 @@ public component Builder for Model { /// Builds the resolved graph: collect every node, derive its edges, and trace /// each disclosed callable body into an ordered step list. public graph(modules: WorkspaceModule[]): Graph { - entries = Model::Workspace.build(modules) + entries: ModuleEntry[] = Model::Workspace.build(modules) for (e in entries) { self.collectModule(e) } diff --git a/pseudoscript/pds.toml b/pseudoscript/pds.toml index 03512c1..c8d3d24 100644 --- a/pseudoscript/pds.toml +++ b/pseudoscript/pds.toml @@ -4,4 +4,4 @@ name = "PseudoScript" out = "target/doc" logo = "logo.svg" -theme = "light" +theme = "dark" diff --git a/pseudoscript/syntax.pds b/pseudoscript/syntax.pds index 43ce8af..6c40c96 100644 --- a/pseudoscript/syntax.pds +++ b/pseudoscript/syntax.pds @@ -280,7 +280,7 @@ public container Syntax for context::Pseudoscript; public component Lexer for Syntax { /// The conformance token stream (LANG.md §2). tokenize(text: string): Token[] { - lexed = self.lex(text) + lexed: Lexed = self.lex(text) return lexed.tokens } @@ -311,7 +311,7 @@ public component Lexer for Syntax { /// The conformance rendering: one `KIND@line:col "lexeme"` line per token, /// line/col resolved via `LineIndex`, interior `\` and `"` escaped. public renderTokens(text: string): string { - tokens = self.tokenize(text) + tokens: Token[] = self.tokenize(text) Syntax::LineIndex.build(text) return self.renderStream(tokens) } @@ -340,8 +340,8 @@ public component LineIndex for Syntax { public component Parser for Syntax { /// Lex, then build the module; bundle the tree with collected diagnostics. public parse(text: string): Parsed { - tokens = Syntax::Lexer.tokenize(text) - ast = self.parseModule(tokens) + tokens: Token[] = Syntax::Lexer.tokenize(text) + ast: Module = self.parseModule(tokens) return Parsed from { ast, tokens } } diff --git a/web-ide/.gitignore b/web-ide/.gitignore index 5b0e108..4d3a8d9 100644 --- a/web-ide/.gitignore +++ b/web-ide/.gitignore @@ -5,3 +5,8 @@ node_modules/ .DS_Store # The vendored wasm package (src/lib/pds-wasm/) is committed on purpose so the # Cloudflare build needs no Rust toolchain — do NOT ignore it. +/storybook-static/ +/test-results/ +/playwright-report/ +/blob-report/ +/.playwright/ diff --git a/web-ide/.storybook/main.js b/web-ide/.storybook/main.js new file mode 100644 index 0000000..9348560 --- /dev/null +++ b/web-ide/.storybook/main.js @@ -0,0 +1,9 @@ +/** @type {import('@storybook/sveltekit').StorybookConfig} */ +const config = { + stories: ["../src/**/*.stories.@(js|ts|svelte)"], + addons: [], + framework: { name: "@storybook/sveltekit", options: {} }, + core: { disableTelemetry: true }, +}; + +export default config; diff --git a/web-ide/.storybook/preview.js b/web-ide/.storybook/preview.js new file mode 100644 index 0000000..f13305c --- /dev/null +++ b/web-ide/.storybook/preview.js @@ -0,0 +1,15 @@ +import "../src/app.css"; + +/** @type {import('@storybook/sveltekit').Preview} */ +const preview = { + parameters: { + controls: { matchers: { color: /(background|color)$/i, date: /Date$/i } }, + }, +}; + +// Render stories on the IDE's dark theme (the design tokens key off `data-theme`). +if (typeof document !== "undefined") { + document.documentElement.setAttribute("data-theme", "dark"); +} + +export default preview; diff --git a/web-ide/components.json b/web-ide/components.json new file mode 100644 index 0000000..28c43c0 --- /dev/null +++ b/web-ide/components.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://shadcn-svelte.com/schema.json", + "tailwind": { + "css": "src/app.css", + "baseColor": "neutral" + }, + "aliases": { + "components": "$lib/components", + "utils": "$lib/utils", + "ui": "$lib/components/ui", + "hooks": "$lib/hooks", + "lib": "$lib" + }, + "typescript": true, + "registry": "https://shadcn-svelte.com/registry" +} diff --git a/web-ide/e2e/canvas-prefs.spec.ts b/web-ide/e2e/canvas-prefs.spec.ts new file mode 100644 index 0000000..277b596 --- /dev/null +++ b/web-ide/e2e/canvas-prefs.spec.ts @@ -0,0 +1,31 @@ +import { expect, test } from "@playwright/test"; +import { createProject, stubPicker } from "./harness"; + +// The canvas "Customise" modal owns the layout algorithm, its direction, and the +// edge line style. This pins that the modal drives the canvas-prefs store and +// that every choice persists to localStorage across sessions. +test.beforeEach(async ({ page }) => { + await stubPicker(page); +}); + +test("the Customise modal sets algorithm, direction, and line style — all persisted", async ({ page }) => { + await createProject(page, "empty"); + await page.getByLabel("Canvas").click(); + await expect(page.locator(".svelte-flow__node-card").first()).toBeVisible({ timeout: 20_000 }); + + await page.getByRole("button", { name: "Customise diagram" }).click(); + const dialog = page.getByTestId("canvas-settings"); + await expect(dialog).toBeVisible(); + + // A geometric algorithm persists and disables the direction control. + await dialog.locator("#cs-algo").selectOption("grid"); + await dialog.locator("#cs-edge").selectOption("straight"); + expect(await page.evaluate(() => localStorage.getItem("pds-canvas-algo"))).toBe("grid"); + expect(await page.evaluate(() => localStorage.getItem("pds-canvas-edge"))).toBe("straight"); + await expect(dialog.locator("#cs-dir")).toBeDisabled(); + + // The layered algorithm re-enables direction, which persists too. + await dialog.locator("#cs-algo").selectOption("layered"); + await dialog.locator("#cs-dir").selectOption("LR"); + expect(await page.evaluate(() => localStorage.getItem("pds-canvas-layout"))).toBe("LR"); +}); diff --git a/web-ide/e2e/canvas.spec.ts b/web-ide/e2e/canvas.spec.ts new file mode 100644 index 0000000..3ed106f --- /dev/null +++ b/web-ide/e2e/canvas.spec.ts @@ -0,0 +1,40 @@ +import { expect, test } from "@playwright/test"; +import { createProject, stubPicker } from "./harness"; + +// The C4 canvas is driven by a right-click context menu (hover + click are +// deprecated). This pins the menu's presence and its "Go to definition" action. +test.beforeEach(async ({ page }) => { + await stubPicker(page); +}); + +test("right-clicking a canvas node opens its context menu; Go to definition opens the source", async ({ page }) => { + await createProject(page, "empty"); + + // Switch to the Canvas activity and wait for the C4 graph to lay out. + await page.getByLabel("Canvas").click(); + const node = page.locator(".svelte-flow__node-card").first(); + await expect(node).toBeVisible({ timeout: 20_000 }); + + // Right-click opens the node context menu; a plain hover shows no info card. + await node.hover(); + await expect(page.locator(".canvas-pop.info")).toHaveCount(0); + await node.click({ button: "right" }); + const menu = page.locator(".ctx-menu"); + await expect(menu).toBeVisible(); + await expect(menu.getByRole("menuitem", { name: "Find usages" })).toBeVisible(); + + // Go to definition leaves the canvas for the editor. + await menu.getByRole("menuitem", { name: "Go to definition" }).click(); + await expect(page.getByTestId("editor").locator(".cm-content")).toBeVisible(); + await expect(page.locator(".svelte-flow")).toHaveCount(0); +}); + +test("the menu bar persists across views", async ({ page }) => { + await createProject(page, "empty"); + + // The menu bar stays put in both the code view and the canvas. + await expect(page.getByRole("button", { name: "File", exact: true })).toBeVisible(); + await page.getByLabel("Canvas").click(); + await expect(page.locator(".svelte-flow__node-card").first()).toBeVisible({ timeout: 20_000 }); + await expect(page.getByRole("button", { name: "File", exact: true })).toBeVisible(); +}); diff --git a/web-ide/e2e/export.spec.ts b/web-ide/e2e/export.spec.ts new file mode 100644 index 0000000..ea8c186 --- /dev/null +++ b/web-ide/e2e/export.spec.ts @@ -0,0 +1,24 @@ +import { expect, test } from "@playwright/test"; +import { createProject, stubPicker } from "./harness"; + +// The C4 canvas can be downloaded as a PNG or SVG image. This pins the export +// control's presence and that each format triggers a real browser download. +test.beforeEach(async ({ page }) => { + await stubPicker(page); +}); + +for (const format of ["PNG", "SVG"] as const) { + test(`downloading the canvas as ${format} triggers a file download`, async ({ page }) => { + await createProject(page, "empty"); + + // Switch to the Canvas activity and wait for the C4 graph to lay out. + await page.getByLabel("Canvas").click(); + await expect(page.locator(".svelte-flow__node-card").first()).toBeVisible({ timeout: 20_000 }); + + // Open the export menu and pick the format; the click should download a file. + await page.getByRole("button", { name: "Download diagram" }).click(); + const download = page.waitForEvent("download"); + await page.getByRole("menuitem", { name: `${format} image` }).click(); + expect((await download).suggestedFilename()).toMatch(new RegExp(`\\.${format.toLowerCase()}$`)); + }); +} diff --git a/web-ide/e2e/harness.ts b/web-ide/e2e/harness.ts new file mode 100644 index 0000000..79bca1d --- /dev/null +++ b/web-ide/e2e/harness.ts @@ -0,0 +1,50 @@ +import { type Page, expect } from "@playwright/test"; + +// The IDE is disk-only: every project is a real folder reached through the File +// System Access API. The native directory picker can't be driven headless, so we +// stub only its *destination* to a fresh OPFS directory — the browser's real, +// on-disk, per-origin filesystem. Everything downstream (scaffold writes, reads, +// manual save, external-change reload) runs against real FileSystemDirectoryHandles; +// only where the picker points is stubbed, exactly as a native dialog chooses. +// +// The picked handle is stashed on `window.__lastPicked` so a test can reach the +// same files the IDE wrote — e.g. to simulate an edit made outside the IDE. +declare global { + interface Window { + __lastPicked?: FileSystemDirectoryHandle; + } +} + +export async function stubPicker(page: Page): Promise { + await page.addInitScript(() => { + window.showDirectoryPicker = async () => { + const root = await navigator.storage.getDirectory(); + // A unique parent each call so `scaffoldWorkspace` creates its dir + // cleanly and tests stay isolated even within one browser context. + const name = "e2e-" + Math.random().toString(36).slice(2); + const dir = await root.getDirectoryHandle(name, { create: true }); + window.__lastPicked = dir; + return dir; + }; + }); +} + +// Boots the IDE and creates a project from `templateId` (the launcher's New-project +// flow), optionally opening a module by fqn. Resolves once a module is visible and +// highlighted — i.e. wasm is ready and the disk-backed workspace is mounted. +export async function createProject(page: Page, templateId: string, openFqn?: string): Promise { + await page.goto("/"); + // The launcher only offers Open/Recent/New; templates live in the New-project + // dialog and stay disabled until a name and a target folder are both set. The + // folder picker resolves to the stubbed OPFS dir; the project scaffolds inside it. + await page.getByTestId("new-project").click({ timeout: 30_000 }); + await page.getByTestId("new-project-name").fill("my-architecture"); + await page.getByTestId("choose-folder").click(); + await page.getByTestId(`template-${templateId}`).click({ timeout: 30_000 }); + if (openFqn) await page.getByTestId(`file-${openFqn}`).click(); + // Scaffolding the template to OPFS, mounting it, and producing the first wasm + // highlights can take a while on a loaded CI machine — wait generously. + const content = page.getByTestId("editor").locator(".cm-content"); + await expect(content).toBeVisible({ timeout: 20_000 }); + await expect(page.locator('[data-sem="keyword"]').first()).toBeVisible({ timeout: 20_000 }); +} diff --git a/web-ide/e2e/ide.spec.ts b/web-ide/e2e/ide.spec.ts new file mode 100644 index 0000000..350a1ef --- /dev/null +++ b/web-ide/e2e/ide.spec.ts @@ -0,0 +1,138 @@ +import { expect, test } from "@playwright/test"; +import { createProject, stubPicker } from "./harness"; + +// Bootstraps the ACME Tickets template into a real (OPFS) folder and opens its +// `orders` module before each test — the disk-backed path a user takes. All +// navigation is via data-testid; editor internals use CodeMirror's documented +// classes and our data-sem highlight attributes. +test.beforeEach(async ({ page }) => { + await stubPicker(page); + await createProject(page, "acme-tickets", "orders"); +}); + +test("highlighting is AST-aware: tokens carry their LSP role", async ({ page }) => { + // The token pass colours keywords; the AST pass colours node names as + // namespaces — a declaration-context role a regex tokenizer could not assign. + // (Param/field type tokens live inside folded bodies, so they are asserted in + // the Rust unit tests rather than here.) + await expect(page.locator('[data-sem="keyword"]').first()).toBeVisible(); + await expect(page.locator('[data-sem="namespace"]').first()).toBeVisible(); +}); + +test("completion is scoped to a module path, not the full symbol set", async ({ page }) => { + const content = page.getByTestId("editor").locator(".cm-content"); + await content.click(); + await page.keyboard.press("Control+End"); + await page.keyboard.type("\nshared::User"); + + const options = page.locator(".cm-tooltip-autocomplete li"); + // module `shared` has exactly one symbol matching the `User` prefix. The first + // dropdown is wasm-backed and debounced, so allow for a loaded machine. + await expect(options).toHaveCount(1, { timeout: 15_000 }); + await expect(options.first()).toContainText("UserId"); + // the general keyword set must not leak into a `::` context + await expect(page.locator(".cm-tooltip-autocomplete li", { hasText: /^system$/ })).toHaveCount(0); +}); + +test("completion narrows as the prefix is typed (scope fix)", async ({ page }) => { + const content = page.getByTestId("editor").locator(".cm-content"); + await content.click(); + await page.keyboard.press("Control+End"); + await page.keyboard.type("\nshared::"); + // explicit trigger at the bare caret shows the whole module + await page.keyboard.press("Control+Space"); + await expect(page.locator(".cm-tooltip-autocomplete li").first()).toBeVisible({ timeout: 15_000 }); + const all = await page.locator(".cm-tooltip-autocomplete li").count(); + expect(all).toBeGreaterThan(1); + // typing a prefix narrows the same scoped set without leaking keywords + await page.keyboard.type("User"); + await expect(page.locator(".cm-tooltip-autocomplete li")).toHaveCount(1, { timeout: 10_000 }); +}); + +test("diagnostics render with no runtime error", async ({ page }) => { + const errors = []; + page.on("pageerror", (e) => errors.push(String(e))); + const content = page.getByTestId("editor").locator(".cm-content"); + await content.click(); + await page.keyboard.press("Control+End"); + // a stray token makes the module invalid → the linter must produce a marker + await page.keyboard.type("\n%% broken"); + await expect(page.locator(".cm-lintRange, .cm-lint-marker").first()).toBeVisible({ timeout: 5000 }); + // the byte→char mapping in the linter must not throw (regressed once) + expect(errors.join("\n")).not.toContain("byteToChar"); +}); + +test("folding ranges come from the compiler (blocks fold)", async ({ page }) => { + // The IDE folds blocks by default using the compiler's AST fold ranges; a + // folded region renders CodeMirror's placeholder. + await expect(page.locator(".cm-foldPlaceholder").first()).toBeVisible(); + + // A fold must not swallow the lines between declarations: every fold starts + // at its declaration header, so no rendered line jams two closing braces or + // leaks a sibling's content (the regression when folds began at doc comments). + // No jamming, and a folded brace sits flush against the placeholder — the + // closing line's indentation folds away too (no `… }` trailing space). + const bad = await page.evaluate(() => + [...document.querySelectorAll(".cm-content .cm-line")] + .map((l) => l.innerText) + .filter((t) => /…\}…\}/.test(t) || /…\s+\}/.test(t)).length, + ); + expect(bad).toBe(0); + + // The doc comment above a record stays visible; the record body folds to `{…}`. + const docVisible = await page.evaluate(() => + [...document.querySelectorAll(".cm-content .cm-line")].some((l) => + l.innerText.startsWith("///"), + ), + ); + expect(docVisible).toBe(true); +}); + +test("the Help menu downloads the authoring skill folder as a zip", async ({ page }) => { + // Skill download lives under the Help menu. + await page.getByRole("button", { name: "Help", exact: true }).click(); + const link = page.getByTestId("download-skill"); + await expect(link).toBeVisible(); + const [download] = await Promise.all([page.waitForEvent("download"), link.click()]); + expect(download.suggestedFilename()).toBe("pseudocode-skill.zip"); +}); + +test("the editor right-click menu: Format always, symbol actions grey out off-target", async ({ page }) => { + const content = page.getByTestId("editor").locator(".cm-content"); + const menu = page.locator(".cm-ctx"); + + // On a symbol (a class identifier) every action is enabled. + await content.locator('[data-sem="class"]').first().click({ button: "right" }); + await expect(menu).toBeVisible(); + await expect(menu.getByRole("menuitem", { name: "Format document" })).toBeEnabled(); + await expect(menu.getByRole("menuitem", { name: "Go to definition" })).toBeEnabled(); + await page.keyboard.press("Escape"); + await expect(menu).toHaveCount(0); + + // On a keyword the symbol actions grey out; Format stays enabled. + await content.locator('[data-sem="keyword"]').first().click({ button: "right" }); + await expect(menu).toBeVisible(); + await expect(menu.getByRole("menuitem", { name: "Go to definition" })).toBeDisabled(); + await expect(menu.getByRole("menuitem", { name: "Format document" })).toBeEnabled(); +}); + +test("rename a symbol across the project via the LSP, with a selectable preview", async ({ page }) => { + const content = page.getByTestId("editor").locator(".cm-content"); + // Right-click a type identifier and open the rename preview. + await content.locator('[data-sem="class"]').first().click({ button: "right" }); + await page.locator(".cm-ctx").getByRole("menuitem", { name: /Rename symbol/ }).click(); + + const dialog = page.getByTestId("rename-dialog"); + await expect(dialog).toBeVisible(); + // The preview lists every occurrence (declaration included), each selectable. + await expect(dialog.locator(".occ").first()).toBeVisible(); + const occCount = await dialog.locator(".occ").count(); + expect(occCount).toBeGreaterThan(0); + + await dialog.getByRole("textbox", { name: "New name" }).fill("RenamedThing"); + await dialog.getByRole("button", { name: /^Rename \d+ occurrence/ }).click(); + + // Applying closes the dialog and edits the buffer (the open file goes dirty). + await expect(dialog).toHaveCount(0); + await expect(page.locator(".tab.active .tab-dirty")).toBeVisible(); +}); diff --git a/web-ide/e2e/panel-resize.spec.ts b/web-ide/e2e/panel-resize.spec.ts new file mode 100644 index 0000000..b9f0067 --- /dev/null +++ b/web-ide/e2e/panel-resize.spec.ts @@ -0,0 +1,30 @@ +import { expect, test } from "@playwright/test"; +import { createProject, stubPicker } from "./harness"; + +// The gutters between the islands carry drag handles (Splitter) that resize the +// explorer / structure panels. This pins that a drag widens the panel, that the +// width clamps to its bounds, and that the choice persists to localStorage. +test.beforeEach(async ({ page }) => { + await stubPicker(page); +}); + +test("dragging the explorer gutter resizes the panel, clamps, and persists", async ({ page }) => { + await createProject(page, "empty"); + + const splitter = page.getByRole("separator", { name: "Resize explorer" }); + await expect(splitter).toBeVisible(); + + // Drag the handle right; the explorer widens past its 248px default. + const box = await splitter.boundingBox(); + if (!box) throw new Error("splitter has no bounding box"); + await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2); + await page.mouse.down(); + await page.mouse.move(box.x + box.width / 2 + 60, box.y + box.height / 2, { steps: 6 }); + await page.mouse.up(); + expect(await page.evaluate(() => Number(localStorage.getItem("pds-explorer-w")))).toBeGreaterThan(248); + + // Arrow keys nudge the focused handle; shrinking well past the minimum clamps to 180. + await splitter.focus(); + for (let i = 0; i < 50; i++) await splitter.press("ArrowLeft"); + expect(await page.evaluate(() => localStorage.getItem("pds-explorer-w"))).toBe("180"); +}); diff --git a/web-ide/e2e/project.spec.ts b/web-ide/e2e/project.spec.ts new file mode 100644 index 0000000..8f8aa3f --- /dev/null +++ b/web-ide/e2e/project.spec.ts @@ -0,0 +1,119 @@ +import { expect, test } from "@playwright/test"; +import { createProject, stubPicker } from "./harness"; + +// The launcher is disk-first: open a folder, re-open a recent, or start a New +// project from a template. These drive the real flow against an OPFS tmp folder +// (see harness.ts) — the picker's destination is the only stub. +test.beforeEach(async ({ page }) => { + await stubPicker(page); +}); + +test("the launcher offers Open / New, and New opens the template dialog", async ({ page }) => { + await page.goto("/"); + await expect(page.getByTestId("open-folder")).toBeVisible({ timeout: 30_000 }); + await expect(page.getByTestId("new-project")).toBeVisible(); + // Templates are no longer on the launcher — they live in the New-project dialog. + await expect(page.getByTestId("template-empty")).toHaveCount(0); + + await page.getByTestId("new-project").click(); + await expect(page.getByTestId("template-empty")).toBeVisible(); + await expect(page.getByTestId("template-acme-tickets")).toBeVisible(); + // Name and target folder are both mandatory: templates stay disabled until both + // are set. + await expect(page.getByTestId("template-empty")).toBeDisabled(); + await page.getByTestId("new-project-name").fill("demo"); + await expect(page.getByTestId("template-empty")).toBeDisabled(); + await page.getByTestId("choose-folder").click(); + await expect(page.getByTestId("template-empty")).toBeEnabled(); +}); + +test("the empty template bootstraps a one-module project on disk", async ({ page }) => { + await createProject(page, "empty"); + const content = page.getByTestId("editor").locator(".cm-content"); + // the one-file starter — a valid PseudoScript model + await expect(content).toContainText("public container Api"); + await expect(page.getByTestId("file-main")).toBeVisible(); +}); + +test("edits persist only on save — no autosave; Cmd/Ctrl-S writes to disk", async ({ page }) => { + await createProject(page, "empty"); + const content = page.getByTestId("editor").locator(".cm-content"); + await expect(content).toContainText("public container Api"); + + const readDisk = () => + page.evaluate(async () => { + const proj = await window.__lastPicked!.getDirectoryHandle("my-architecture"); + const file = await proj.getFileHandle("main.pds"); + return (await file.getFile()).text(); + }); + + // Edit in the editor: append a comment line (keeps the model valid). + await content.click(); + await page.keyboard.press("Control+End"); + await page.keyboard.type("\n// SAVE_MARKER"); + + // No autosave: the active tab reads dirty and disk is untouched even after the + // old debounce window would have elapsed. + await expect(page.locator(".tab.active .tab-dirty")).toBeVisible(); + await page.waitForTimeout(800); + expect(await readDisk()).not.toContain("SAVE_MARKER"); + + // Explicit save writes the buffer and clears the dirty marker. + await page.keyboard.press("ControlOrMeta+s"); + await expect(page.locator(".tab.active .tab-dirty")).toHaveCount(0); + expect(await readDisk()).toContain("SAVE_MARKER"); +}); + +test("a file edited outside the IDE is reloaded", async ({ page }) => { + await createProject(page, "empty"); + const content = page.getByTestId("editor").locator(".cm-content"); + await expect(content).toContainText("public container Api"); + + // Edit main.pds on disk, outside the editor — through the very folder the IDE + // scaffolded into (the stubbed OPFS pick). + await page.evaluate(async () => { + const proj = await window.__lastPicked!.getDirectoryHandle("my-architecture"); + const file = await proj.getFileHandle("main.pds"); + const writable = await file.createWritable(); + await writable.write("//! main\n\npublic system ReloadedFromDisk;\n"); + await writable.close(); + }); + + // Regaining focus pulls in external changes immediately. + await page.evaluate(() => window.dispatchEvent(new Event("focus"))); + await expect(content).toContainText("ReloadedFromDisk"); + await expect(content).not.toContainText("public container Api"); +}); + +test("File ▸ Close project tears down the workspace and reopens the launcher", async ({ page }) => { + await createProject(page, "empty"); + await expect(page.getByTestId("editor").locator(".cm-content")).toContainText("public container Api"); + + await page.getByRole("button", { name: "File", exact: true }).click(); + await page.getByRole("menuitem", { name: "Close project" }).click(); + + // A clean workspace closes without a confirm; the launcher returns. + await expect(page.getByTestId("open-folder")).toBeVisible(); + await expect(page.getByTestId("new-project")).toBeVisible(); +}); + +test("Close project with unsaved edits asks before discarding", async ({ page }) => { + await createProject(page, "empty"); + const content = page.getByTestId("editor").locator(".cm-content"); + await expect(content).toContainText("public container Api"); + + // Dirty the active buffer. + await content.click(); + await page.keyboard.press("Control+End"); + await page.keyboard.type("\n// CLOSE_MARKER"); + await expect(page.locator(".tab.active .tab-dirty")).toBeVisible(); + + await page.getByRole("button", { name: "File", exact: true }).click(); + await page.getByRole("menuitem", { name: "Close project" }).click(); + + // The destructive-confirm appears; confirming closes to the launcher. + const confirm = page.getByTestId("confirm-dialog"); + await expect(confirm.getByText("Discard unsaved changes?")).toBeVisible(); + await confirm.getByRole("button", { name: "Discard", exact: true }).click(); + await expect(page.getByTestId("open-folder")).toBeVisible(); +}); diff --git a/web-ide/e2e/pwa.spec.ts b/web-ide/e2e/pwa.spec.ts new file mode 100644 index 0000000..65b920f --- /dev/null +++ b/web-ide/e2e/pwa.spec.ts @@ -0,0 +1,34 @@ +import { expect, test } from "@playwright/test"; + +// The IDE is an installable PWA: a linked web manifest, platform icons, and a +// theme colour. (The service worker is emitted by the build and registered by +// SvelteKit; install/offline behaviour isn't exercised against the dev server.) +test("ships an installable web app manifest with icons", async ({ page }) => { + await page.goto("/"); + + // The manifest is linked in the document head. + await expect(page.locator('link[rel="manifest"]')).toHaveAttribute("href", /manifest\.webmanifest/); + + // It is valid, standalone, and declares the required + maskable icons. + const manifest = await (await page.request.get("/manifest.webmanifest")).json(); + expect(manifest.name).toBe("PseudoScript IDE"); + expect(manifest.display).toBe("standalone"); + const sizes = manifest.icons.map((i: { sizes: string }) => i.sizes); + expect(sizes).toContain("192x192"); + expect(sizes).toContain("512x512"); + expect(manifest.icons.some((i: { purpose?: string }) => i.purpose === "maskable")).toBe(true); + + // An icon actually resolves as a PNG. + const icon = await page.request.get("/icons/icon-512.png"); + expect(icon.ok()).toBe(true); + expect(icon.headers()["content-type"]).toContain("image/png"); + + // The address-bar / splash theme colour tracks the resolved theme's --bg, set + // pre-paint by the inline head script. + await page.emulateMedia({ colorScheme: "dark" }); + await page.goto("/"); + await expect(page.locator('meta[name="theme-color"]')).toHaveAttribute("content", "#0a0b0e"); + await page.emulateMedia({ colorScheme: "light" }); + await page.goto("/"); + await expect(page.locator('meta[name="theme-color"]')).toHaveAttribute("content", "#e7eaef"); +}); diff --git a/web-ide/e2e/sequence.spec.ts b/web-ide/e2e/sequence.spec.ts new file mode 100644 index 0000000..7b5dda3 --- /dev/null +++ b/web-ide/e2e/sequence.spec.ts @@ -0,0 +1,73 @@ +import { type Locator, type Page, expect, test } from "@playwright/test"; +import { createProject, stubPicker } from "./harness"; + +// The hit targets are SVG s / canvas cards with no stable click point, so +// dispatch the contextmenu event the handler listens for instead of a pointer +// click. The target symbol comes from the element's bound data, not the pointer. +async function rightClick(locator: Locator): Promise { + await locator.dispatchEvent("contextmenu"); +} + +// The sequence diagram is driven by the same right-click context menu as the C4 +// graph (the hold-hover info card and Cmd-click are gone). This pins the menu on +// a message label and on a lifeline card, plus its "Go to definition" action. +// One project load drives all three — the acme-tickets scaffold is heavy. +test.beforeEach(async ({ page }) => { + await stubPicker(page); +}); + +// Open the acme-tickets checkout flow as a sequence: right-click the Attendee +// node on the canvas and pick its `checkout` entry point. +async function openCheckoutFlow(page: Page): Promise { + await createProject(page, "acme-tickets"); + await page.getByLabel("Canvas").click(); + const attendee = page.locator(".svelte-flow__node-card", { hasText: "Attendee" }).first(); + await expect(attendee).toBeVisible({ timeout: 20_000 }); + await attendee.click({ button: "right" }); + await page.locator(".ctx-menu").getByRole("menuitem", { name: "checkout" }).click(); + await expect(page.locator(".seq-messages")).toBeVisible({ timeout: 20_000 }); +} + +test("right-click opens the actions menu on sequence messages and lifelines", async ({ page }) => { + await openCheckoutFlow(page); + const menu = page.locator(".ctx-menu"); + + // No hover info card exists any more. + await expect(page.locator(".canvas-pop.info")).toHaveCount(0); + + // A message label: both actions present. + const label = page.locator(".seq-hit").first(); + await expect(label).toBeVisible(); + await rightClick(label); + await expect(menu).toBeVisible(); + await expect(menu.getByRole("menuitem", { name: "Find usages" })).toBeVisible(); + await expect(menu.getByRole("menuitem", { name: "Go to definition" })).toBeVisible(); + await page.keyboard.press("Escape"); + await expect(menu).toHaveCount(0); + + // A lifeline card opens the same menu. + const card = page.locator(".seq-card.interactive").first(); + await expect(card).toBeVisible(); + await rightClick(card); + await expect(menu).toBeVisible(); + await expect(menu.getByRole("menuitem", { name: "Go to definition" })).toBeVisible(); + await page.keyboard.press("Escape"); + await expect(menu).toHaveCount(0); + + // A signature type token (a declared `data` type) opens the same menu. + const typeLink = page.locator(".seq-type-link").first(); + await expect(typeLink).toBeVisible(); + await rightClick(typeLink); + await expect(menu).toBeVisible(); + await expect(menu.getByRole("menuitem", { name: "Go to definition" })).toBeVisible(); + await page.keyboard.press("Escape"); + await expect(menu).toHaveCount(0); + + // Go to definition from a message leaves the canvas for the editor. The menu + // anchors at the dispatched event's origin; dispatch the item's click too + // rather than depend on its on-screen position. + await rightClick(label); + await menu.getByRole("menuitem", { name: "Go to definition" }).dispatchEvent("click"); + await expect(page.getByTestId("editor").locator(".cm-content")).toBeVisible(); + await expect(page.locator(".svelte-flow")).toHaveCount(0); +}); diff --git a/web-ide/package-lock.json b/web-ide/package-lock.json index ed8f142..b15b92a 100644 --- a/web-ide/package-lock.json +++ b/web-ide/package-lock.json @@ -13,6 +13,7 @@ "@codemirror/lang-markdown": "^6.5.0", "@codemirror/language": "^6.12.3", "@codemirror/language-data": "^6.5.2", + "@codemirror/legacy-modes": "^6.5.3", "@codemirror/lint": "^6.9.6", "@codemirror/search": "^6.7.0", "@codemirror/state": "^6.6.0", @@ -20,17 +21,144 @@ "@dagrejs/dagre": "3.0.0", "@lezer/highlight": "^1.2.3", "@lezer/markdown": "^1.6.4", - "@lucide/svelte": "^1.17.0", "@xyflow/svelte": "1.5.2", + "bits-ui": "^2.18.1", + "clsx": "^2.1.1", "codemirror": "^6.0.2", - "prettier": "^3.8.3" + "html-to-image": "^1.11.13", + "prettier": "^3.8.3", + "tailwind-merge": "^3.6.0", + "tailwind-variants": "^3.2.2" }, "devDependencies": { + "@internationalized/date": "^3.12.2", + "@lucide/svelte": "^1.17.0", + "@playwright/test": "^1.60.0", + "@storybook/sveltekit": "^10.4.1", "@sveltejs/adapter-cloudflare": "^7.2.8", "@sveltejs/kit": "^2.61.1", "@sveltejs/vite-plugin-svelte": "^7.1.2", + "@tailwindcss/vite": "^4.3.0", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/svelte": "^5.3.1", + "@testing-library/user-event": "^14.6.1", + "@types/node": "^25.9.1", + "jsdom": "^29.1.1", + "sharp": "^0.34.5", + "storybook": "^10.4.1", "svelte": "^5.56.0", - "vite": "^8" + "svelte-check": "^4.5.0", + "tailwindcss": "^4.3.0", + "tw-animate-css": "^1.4.0", + "typescript": "^6.0.3", + "vite": "^8", + "vitest": "^3.2.4" + } + }, + "node_modules/@adobe/css-tools": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.5.0.tgz", + "integrity": "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@asamuzakjp/css-color": { + "version": "5.1.11", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.11.tgz", + "integrity": "sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/generational-cache": "^1.0.1", + "@csstools/css-calc": "^3.2.0", + "@csstools/css-color-parser": "^4.1.0", + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/dom-selector": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-7.1.1.tgz", + "integrity": "sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/generational-cache": "^1.0.1", + "@asamuzakjp/nwsapi": "^2.3.9", + "bidi-js": "^1.0.3", + "css-tree": "^3.2.1", + "is-potential-custom-element-name": "^1.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/generational-cache": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@asamuzakjp/generational-cache/-/generational-cache-1.0.1.tgz", + "integrity": "sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/nwsapi": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", + "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bramus/specificity": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@bramus/specificity/-/specificity-2.4.2.tgz", + "integrity": "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-tree": "^3.0.0" + }, + "bin": { + "specificity": "bin/cli.js" } }, "node_modules/@cloudflare/kv-asset-handler": { @@ -585,6 +713,146 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@csstools/color-helpers": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.2.tgz", + "integrity": "sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/@csstools/css-calc": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.2.1.tgz", + "integrity": "sha512-DtdHlgXh5ZkA43cwBcAm+huzgJiwx3ZTWVjBs94kwz2xKqSimDA3lBgCjphYgwgVUMWatSM0pDd8TILB1yrVVg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.1.1.tgz", + "integrity": "sha512-eZ5XOtyhK+mggRafYUWzA0tvaYOFgdY8AkgQiCJF9qNAePnUo/zmsqqYubBBb3sQ8uNUaSKTY9s9klfRaAXL0g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^6.0.2", + "@csstools/css-calc": "^3.2.1" + }, + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", + "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.4.tgz", + "integrity": "sha512-wgsqt92b7C7tQhIdPNxj0n9zuUbQlvAuI1exyzeNrOKOi62SD7ren8zqszmpVREjAOqg8cD2FqYhQfAuKjk4sw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "peerDependencies": { + "css-tree": "^3.2.1" + }, + "peerDependenciesMeta": { + "css-tree": { + "optional": true + } + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", + "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + } + }, "node_modules/@dagrejs/dagre": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@dagrejs/dagre/-/dagre-3.0.0.tgz", @@ -604,7 +872,6 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -616,7 +883,6 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -627,7 +893,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -641,13 +906,11 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "aix" ], - "peer": true, "engines": { "node": ">=18" } @@ -659,13 +922,11 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "android" ], - "peer": true, "engines": { "node": ">=18" } @@ -677,13 +938,11 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "android" ], - "peer": true, "engines": { "node": ">=18" } @@ -695,13 +954,11 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "android" ], - "peer": true, "engines": { "node": ">=18" } @@ -713,13 +970,11 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" ], - "peer": true, "engines": { "node": ">=18" } @@ -731,13 +986,11 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" ], - "peer": true, "engines": { "node": ">=18" } @@ -749,13 +1002,11 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "freebsd" ], - "peer": true, "engines": { "node": ">=18" } @@ -767,13 +1018,11 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "freebsd" ], - "peer": true, "engines": { "node": ">=18" } @@ -785,13 +1034,11 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -803,13 +1050,11 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -821,13 +1066,11 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -839,13 +1082,11 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -857,13 +1098,11 @@ "cpu": [ "mips64el" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -875,13 +1114,11 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -893,13 +1130,11 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -911,13 +1146,11 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -929,13 +1162,11 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -947,13 +1178,11 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "netbsd" ], - "peer": true, "engines": { "node": ">=18" } @@ -965,13 +1194,11 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "netbsd" ], - "peer": true, "engines": { "node": ">=18" } @@ -983,13 +1210,11 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "openbsd" ], - "peer": true, "engines": { "node": ">=18" } @@ -1001,13 +1226,11 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "openbsd" ], - "peer": true, "engines": { "node": ">=18" } @@ -1019,13 +1242,11 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "openharmony" ], - "peer": true, "engines": { "node": ">=18" } @@ -1037,13 +1258,11 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "sunos" ], - "peer": true, "engines": { "node": ">=18" } @@ -1055,13 +1274,11 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "win32" ], - "peer": true, "engines": { "node": ">=18" } @@ -1073,13 +1290,11 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "win32" ], - "peer": true, "engines": { "node": ">=18" } @@ -1091,24 +1306,64 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "win32" ], - "peer": true, "engines": { "node": ">=18" } }, + "node_modules/@exodus/bytes": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.1.tgz", + "integrity": "sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + }, + "peerDependencies": { + "@noble/hashes": "^1.8.0 || ^2.0.0" + }, + "peerDependenciesMeta": { + "@noble/hashes": { + "optional": true + } + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.5", + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", + "license": "MIT" + }, "node_modules/@img/colour": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=18" } @@ -1126,7 +1381,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, @@ -1150,7 +1404,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, @@ -1174,7 +1427,6 @@ "os": [ "darwin" ], - "peer": true, "funding": { "url": "https://opencollective.com/libvips" } @@ -1192,7 +1444,6 @@ "os": [ "darwin" ], - "peer": true, "funding": { "url": "https://opencollective.com/libvips" } @@ -1213,7 +1464,6 @@ "os": [ "linux" ], - "peer": true, "funding": { "url": "https://opencollective.com/libvips" } @@ -1234,7 +1484,6 @@ "os": [ "linux" ], - "peer": true, "funding": { "url": "https://opencollective.com/libvips" } @@ -1255,7 +1504,6 @@ "os": [ "linux" ], - "peer": true, "funding": { "url": "https://opencollective.com/libvips" } @@ -1276,7 +1524,6 @@ "os": [ "linux" ], - "peer": true, "funding": { "url": "https://opencollective.com/libvips" } @@ -1297,7 +1544,6 @@ "os": [ "linux" ], - "peer": true, "funding": { "url": "https://opencollective.com/libvips" } @@ -1318,7 +1564,6 @@ "os": [ "linux" ], - "peer": true, "funding": { "url": "https://opencollective.com/libvips" } @@ -1339,7 +1584,6 @@ "os": [ "linux" ], - "peer": true, "funding": { "url": "https://opencollective.com/libvips" } @@ -1360,7 +1604,6 @@ "os": [ "linux" ], - "peer": true, "funding": { "url": "https://opencollective.com/libvips" } @@ -1381,7 +1624,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, @@ -1408,7 +1650,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, @@ -1435,7 +1676,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, @@ -1462,7 +1702,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, @@ -1489,7 +1728,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, @@ -1516,7 +1754,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, @@ -1543,7 +1780,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, @@ -1570,7 +1806,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, @@ -1591,7 +1826,6 @@ "dev": true, "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, - "peer": true, "dependencies": { "@emnapi/runtime": "^1.7.0" }, @@ -1615,7 +1849,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, @@ -1636,7 +1869,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, @@ -1657,7 +1889,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, @@ -1665,6 +1896,15 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@internationalized/date": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.12.2.tgz", + "integrity": "sha512-FY1Y+H64NDs+HAF6omlnWxm3mEpfgaCSWtL5l551ZZfImA+kGjPFgrnJrGjH6lfmLL0g8Z/mBu1R3kufeCp6Jw==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -1891,6 +2131,7 @@ "version": "1.17.0", "resolved": "https://registry.npmjs.org/@lucide/svelte/-/svelte-1.17.0.tgz", "integrity": "sha512-q06YCFBN5CO8cd1ADmLCxWRVMVb7xxvHzqC0lvNoxGa+FLW6Cd1Y1AOxgbQk4Iwe68vkAMCRveNHint4WoaVKg==", + "dev": true, "license": "ISC", "peerDependencies": { "svelte": "^5" @@ -1906,7 +2147,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -1921,59 +2161,27 @@ "@emnapi/runtime": "^1.7.1" } }, - "node_modules/@oxc-project/types": { - "version": "0.132.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.132.0.tgz", - "integrity": "sha512-FESMOxil5Se014ui/Eq8fT5uHJo6nIRwH0PfJrZJXs6Gek3ZVFOrpUv3YIZT20m+extU98Hg1Ym72U58rlsxUQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/Boshen" - } - }, - "node_modules/@polka/url": { - "version": "1.0.0-next.29", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", - "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", - "dev": true, - "license": "MIT" - }, - "node_modules/@poppinss/colors": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.6.tgz", - "integrity": "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "kleur": "^4.1.5" - } - }, - "node_modules/@poppinss/dumper": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@poppinss/dumper/-/dumper-0.6.5.tgz", - "integrity": "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==", + "node_modules/@oxc-parser/binding-android-arm-eabi": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm-eabi/-/binding-android-arm-eabi-0.127.0.tgz", + "integrity": "sha512-0LC7ye4hvqbIKxAzThzvswgHLFu2AURKzYLeSVvLdu2TBOYWQDmHnTqPLeA597BcUCxiLqLsS4CJ5uoI5WYWCQ==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "@poppinss/colors": "^4.1.5", - "@sindresorhus/is": "^7.0.2", - "supports-color": "^10.0.0" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@poppinss/exception": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.3.tgz", - "integrity": "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.2.tgz", - "integrity": "sha512-ZS4D1JPGn/MYQN/SYDWftIE/nVsM8j/AFOYEzAoOE2O3NktQOZru+/vYXGbR/qtdLdIfGCP0lcoJiYVzsEz+iQ==", + "node_modules/@oxc-parser/binding-android-arm64": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm64/-/binding-android-arm64-0.127.0.tgz", + "integrity": "sha512-b5jtVTH6AU5CJXHNdj7Jj9IEiR9yVjjnwHzPJhGyHGPdcsZSzBCkS9GBbV33niRMvKthDwQRFRJfI4a+k4PvYg==", "cpu": [ "arm64" ], @@ -1987,10 +2195,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.2.tgz", - "integrity": "sha512-vdFA9+C/rekyGce7WqHs/xoT0ioZEWaOFyZLIV1mEeNFaFDUQrPIo8Vs2GvJ6eetb3rzDUtUBgzto3ExpXJB3w==", + "node_modules/@oxc-parser/binding-darwin-arm64": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.127.0.tgz", + "integrity": "sha512-obCE8B7ISKkJidjlhv9xRGJPOSDG2Yu6PRga9Ruaz35uintHxbp1Ki/Yc71wx4rj3Edrm0a1kzG1TAwit0wFpg==", "cpu": [ "arm64" ], @@ -2004,10 +2212,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.2.tgz", - "integrity": "sha512-BewSOwTHazv77DTYiAZXSqqKZ4KP/KonFisDMVU7PImxoWfB2aepnPhd2E4SWz3zDzYgDNbs6jBmTdgNnF02GA==", + "node_modules/@oxc-parser/binding-darwin-x64": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-x64/-/binding-darwin-x64-0.127.0.tgz", + "integrity": "sha512-JL6Xb5IwPQT8rUzlpsX7E+AgfcdNklXNPFp8pjCQQ5MQOQo5rtEB2ui+3Hgg9Sn7Y9Egj6YOLLiHhLpdAe12Aw==", "cpu": [ "x64" ], @@ -2021,10 +2229,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.2.tgz", - "integrity": "sha512-m41o7M0YWtUdqk61Tb+jnKb2rN++iRdIASlExkUoKfIAH30DOHCB8fVLzSUpbWHHU8esmEioY62PxzexE8MBuA==", + "node_modules/@oxc-parser/binding-freebsd-x64": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-freebsd-x64/-/binding-freebsd-x64-0.127.0.tgz", + "integrity": "sha512-SDQ/3MQFw58fqQz3Z1PhSKFF3JoCF4gmlNjziDm8X02tTahCw0qJbd7FGPDKw1i4VTBZene9JPyC3mHtSvi+wA==", "cpu": [ "x64" ], @@ -2038,10 +2246,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.2.tgz", - "integrity": "sha512-jcojB9H7W/jS29pMKWAK1N+fU99vXodHDTatS3b3y/XSOCiHo0kkA74pL3jJmkoQtYpOCxDvaKs1fo2Ij/1X5w==", + "node_modules/@oxc-parser/binding-linux-arm-gnueabihf": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.127.0.tgz", + "integrity": "sha512-Av+D1MIqzV0YMGPT9we2SIZaMKD7Cxs4CvXSx/yxaWHewZjYEjScpOf5igc8IILASViw4WTnjlwUdI1KzVtDHQ==", "cpu": [ "arm" ], @@ -2055,10 +2263,27 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.2.tgz", - "integrity": "sha512-1jn6qDU5iiOgFgygDzKUuKP0maTi0/f1+sBLgvij/76C77Nm3ts6ufz9Bjg5q5dduxiUIxtq86JIoBvo1xQ4Ig==", + "node_modules/@oxc-parser/binding-linux-arm-musleabihf": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.127.0.tgz", + "integrity": "sha512-Cs2fdJ8cPpFdeebj6p4dag8A4+56hPvZ0AhQQzlaLswGz1tz7bXt1nETLeorrM9+AMcWFFkqxcXwDGfTVidY8g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm64-gnu": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.127.0.tgz", + "integrity": "sha512-qdOfTcT6SY8gsJrrV92uyEUyjqMGPpIB5JZUG6QN5dukYd+7/j0kX6MwK1DgQj39jtUYixxPiaRUiEN1+0CXgQ==", "cpu": [ "arm64" ], @@ -2075,10 +2300,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.2.tgz", - "integrity": "sha512-QVLO/czFMdoMFSqlX3bcswcJNm/23r+qoa/jgtmFc/qEp6/jXmIkDjF/XIo8dPfGaiwy1xfQn8o77L79GeXFgw==", + "node_modules/@oxc-parser/binding-linux-arm64-musl": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.127.0.tgz", + "integrity": "sha512-EoTCZneNFU/P2qrpEM+RHmQwt+CvDkyGESG6qhr7KaegXLZwePfbrkCDfAk8/rhxbDUVGsZILX+2tqPzFtoFWA==", "cpu": [ "arm64" ], @@ -2095,10 +2320,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.2.tgz", - "integrity": "sha512-hgO5Abm0w5UL6FEa2iFnZqo2KlK7TQ5QhV5x09hujBf7t5KzHQ1VmfPuTpqRy/rNlSxua3eWH374xxiVrP+lcA==", + "node_modules/@oxc-parser/binding-linux-ppc64-gnu": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.127.0.tgz", + "integrity": "sha512-zALjmZYgxFLHjXeudcDF0xFGNydTAtkAeXAr2EuC17ywCyFxcmQra4w0BMde0Yi/re4Bi4iwEoEXtYN7l6eBLQ==", "cpu": [ "ppc64" ], @@ -2115,10 +2340,50 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.2.tgz", - "integrity": "sha512-fy8rXxuYEu602abC8MUNaPjYLIFzReOaEIEMKMUa0rFEUxNpVXhs15KSSQ4qlqSaM7B6rcj9rDZgADh/IGDzLQ==", + "node_modules/@oxc-parser/binding-linux-riscv64-gnu": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.127.0.tgz", + "integrity": "sha512-fPP8M6zQLS7Jz7o9d5ArUSuAuSK3e+WCYVrCpdzeCOejidtZExJ9tjhDrAd3HEPqARBCPmdpqxESPFqy44vkBQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-riscv64-musl": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.127.0.tgz", + "integrity": "sha512-7IcC4Ao02oGpfnjt+X/oF4U2mllo2qoSkw5xxiXNKL9MCTsTiAC6616beOuehdxGcnz1bRoPC1RQ2f1GQDdN+g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-s390x-gnu": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.127.0.tgz", + "integrity": "sha512-pbXIhiNFHoqWeqDNLiJ9JkpHz1IM9k4DXa66x+1GTWMG7iLxtkXgE53iiuKSXwmk3zIYmaPVfBvgcAhS583K4Q==", "cpu": [ "s390x" ], @@ -2135,10 +2400,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.2.tgz", - "integrity": "sha512-0+bOkiQ779+r1WpoHOWHqncvyySci0vKph+myNDYb+im6meJAzHQXay6oEgnkHuUGouM1LKTZwqKpBow6Kj7CQ==", + "node_modules/@oxc-parser/binding-linux-x64-gnu": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.127.0.tgz", + "integrity": "sha512-MYCguB9RvBvlSd6gbuNI7QwiLoCCAlGnlRJFPrzLI6U1/9wkC/WK6LtBAUln55H1Ctqw45PWmqrobKoMhsYQzQ==", "cpu": [ "x64" ], @@ -2155,10 +2420,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.2.tgz", - "integrity": "sha512-mjSkrzZK5Qsl0a9d1JgILOiuZOSDTVdKENcSXBoqbzSrspLR/4/IRVDo5wd2GgZjNss/viBFJdeq+j7qH2nypw==", + "node_modules/@oxc-parser/binding-linux-x64-musl": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-musl/-/binding-linux-x64-musl-0.127.0.tgz", + "integrity": "sha512-5eY0B/bxf1xIUxb4NOTvOI3KWtBQfPWYyKAzgcrCt0mDibSZygVpO1Pz8bkeiSZ5Jj9+M09dkggG3H8I5d0Uyg==", "cpu": [ "x64" ], @@ -2175,10 +2440,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.2.tgz", - "integrity": "sha512-1v5vHasdfQAZoEHakBV72LIFAC9JjnymsiKxp+GEr/ma3+NJCPSaYK+qavInOovJkgwFrs7GccX2d6IgDA3Z5w==", + "node_modules/@oxc-parser/binding-openharmony-arm64": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-openharmony-arm64/-/binding-openharmony-arm64-0.127.0.tgz", + "integrity": "sha512-Gld0ajrFTUXNtdw20fVBuTQx66FA75nIVg+//pPfR3sXkuABB4mTBhl3r9JNzrJpgW//qiwxf0nWXUWGJSL3UQ==", "cpu": [ "arm64" ], @@ -2192,10 +2457,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.2.tgz", - "integrity": "sha512-mb1VobWn6NheziTk5/WEaR6AKVbrwT5sOi6C7zk3gy/pD1qtJfU1j4PgTo2NJnOtbL9Dl3Aeei8w9jJ7qC2jZQ==", + "node_modules/@oxc-parser/binding-wasm32-wasi": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-wasm32-wasi/-/binding-wasm32-wasi-0.127.0.tgz", + "integrity": "sha512-T6KVD7rhLzFlwGRXMnxUFfkCZD8FHnb968wVXW1mXzgRFc5RNXOBY2mPPDZ77x5Ln76ltLMgtPg0cOkU1NSrEQ==", "cpu": [ "wasm32" ], @@ -2203,18 +2468,41 @@ "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "1.10.0", - "@emnapi/runtime": "1.10.0", + "@emnapi/core": "1.9.2", + "@emnapi/runtime": "1.9.2", "@napi-rs/wasm-runtime": "^1.1.4" }, "engines": { "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.2.tgz", - "integrity": "sha512-SqKonF56vA/L2yHwHYcEp2P34URpOZ7d1fS635cTkpDnUtEGdUbhI6NzsPdqeSWvAAeGDrxjWjNmibDIdFf9/A==", + "node_modules/@oxc-parser/binding-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", + "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@oxc-parser/binding-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", + "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@oxc-parser/binding-win32-arm64-msvc": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.127.0.tgz", + "integrity": "sha512-Ujvw4X+LD1CCGULcsQcvb4YNVoBGqt+JHgNNzGGaCImELiZLk477ifUH53gIbE7EKd933NdTi25JWEr9K2HwXw==", "cpu": [ "arm64" ], @@ -2228,12 +2516,12 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.2.tgz", - "integrity": "sha512-v7qRI7gXLRINcOGXt+7YmAZ6iFuyZVMIoXAxhd8oP+DR9dLfL9GfNIx7PLMxmhZdvq8waUJBQiWN9EKNy+TRBQ==", + "node_modules/@oxc-parser/binding-win32-ia32-msvc": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.127.0.tgz", + "integrity": "sha512-0cwxKO7KHQQQfo4Uf4B2SQrhgm+cJaP9OvFFhx52Tkg4bezsacu83GB2/In5bC415Ueeym+kXdnge/57rbSfTw==", "cpu": [ - "x64" + "ia32" ], "dev": true, "license": "MIT", @@ -2245,153 +2533,1750 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", - "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@sindresorhus/is": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz", - "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==", + "node_modules/@oxc-parser/binding-win32-x64-msvc": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.127.0.tgz", + "integrity": "sha512-rOrnSQSCbhI2kowr9XxE7m9a8oQXnBHjnS6j95LxxAnEZ0+Fz20WlRXG4ondQb+ejjt2KOsa65sE6++L6kUd+w==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "peer": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" + "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@speed-highlight/core": { - "version": "1.2.15", - "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.15.tgz", - "integrity": "sha512-BMq1K3DsElxDWawkX6eLg9+CKJrTVGCBAWVuHXVUV2u0s2711qiChLSId6ikYPfxhdYocLNt3wWwSvDiTvFabw==", - "dev": true, - "license": "CC0-1.0", - "peer": true - }, - "node_modules/@standard-schema/spec": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", - "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@svelte-put/shortcut": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@svelte-put/shortcut/-/shortcut-4.1.0.tgz", - "integrity": "sha512-wImNEIkbxAIWFqlfuhcbC+jRPDeRa/uJGIXHMEVVD+jqL9xCwWNnkGQJ6Qb2XVszuRLHlb8SGZDL3Io/h3vs8w==", + "node_modules/@oxc-project/types": { + "version": "0.132.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.132.0.tgz", + "integrity": "sha512-FESMOxil5Se014ui/Eq8fT5uHJo6nIRwH0PfJrZJXs6Gek3ZVFOrpUv3YIZT20m+extU98Hg1Ym72U58rlsxUQ==", + "devOptional": true, "license": "MIT", - "peerDependencies": { - "svelte": "^5.1.0" + "funding": { + "url": "https://github.com/sponsors/Boshen" } }, - "node_modules/@sveltejs/acorn-typescript": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.10.tgz", - "integrity": "sha512-4WfKk68eTih+MiJD4fSbxN7E8kVBmTMPWHUPYjvl2N0rMs53YLTT8/YjKU5Dtnz5LqDjl7LEw4U7lXR2W3J5WA==", + "node_modules/@oxc-resolver/binding-android-arm-eabi": { + "version": "11.20.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-android-arm-eabi/-/binding-android-arm-eabi-11.20.0.tgz", + "integrity": "sha512-IjfWOXRgJFNdORDl+Uf1aibNgZY2guOD3zmOhx1BGVb/MIiqlFTdmjpQNplSN58lhWehnX4UNqC3QwpUo8pjJg==", + "cpu": [ + "arm" + ], + "dev": true, "license": "MIT", - "peerDependencies": { - "acorn": "^8.9.0" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@sveltejs/adapter-cloudflare": { - "version": "7.2.8", - "resolved": "https://registry.npmjs.org/@sveltejs/adapter-cloudflare/-/adapter-cloudflare-7.2.8.tgz", - "integrity": "sha512-bIdhY/Fi4AQmqiBdQVKnafH1h9Gw+xbCvHyUu4EouC8rJOU02zwhi14k/FDhQ0mJF1iblIu3m8UNQ8GpGIvIOQ==", + "node_modules/@oxc-resolver/binding-android-arm64": { + "version": "11.20.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-android-arm64/-/binding-android-arm64-11.20.0.tgz", + "integrity": "sha512-QqslZAuFQG8Q9xm7JuIn8JUbvywhSBMVhuQHtYW+auirZJloS41oxUUaBXk7uUhZJgp44c5zQLeVvmFaDQB+2Q==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@cloudflare/workers-types": "^4.20250507.0", - "worktop": "0.8.0-next.18" - }, - "peerDependencies": { - "@sveltejs/kit": "^2.0.0", - "wrangler": "^4.0.0" - } + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@oxc-resolver/binding-darwin-arm64": { + "version": "11.20.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-11.20.0.tgz", + "integrity": "sha512-MUcavykj2ewlR+kc5arpg4tC2RvzJkUxWtNv74pf7lcNk00GpIpN43vXMj+j6r4eMmfZhlb8hueKoIb8e9kAGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oxc-resolver/binding-darwin-x64": { + "version": "11.20.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-11.20.0.tgz", + "integrity": "sha512-BGB16nRUK5Etiv//ihPyzj8Lj1px0mhh4YIfe0FDf045ywknfSm0GEbiRESpr6Q4K82AvnyaRIhhluHByvS4bg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oxc-resolver/binding-freebsd-x64": { + "version": "11.20.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-freebsd-x64/-/binding-freebsd-x64-11.20.0.tgz", + "integrity": "sha512-JZgtePaqj3qmD5XFHJaSLWzHRxQu0LaPkdoM1KJXYADvAaa83ijXHclV3ej3CueeW0wxfIAbGCZVP45J0CA7uQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@oxc-resolver/binding-linux-arm-gnueabihf": { + "version": "11.20.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-11.20.0.tgz", + "integrity": "sha512-hOQ/p3ry3v3SchUBXicrrnszaI/UmYzM4wtS4RGfwgVUX7a+HbyQSzJ5aOzu+o6XZkFkS3ZXN4PZAzhOb77OSg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-arm-musleabihf": { + "version": "11.20.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-11.20.0.tgz", + "integrity": "sha512-2ArPksaw0AqeuGBfoS715VF+JvJQAhD2niWgjE5hVO+L+nAfikVQopvngCMX9x4BD8itWoQ3dnikrQyl5Ho5Jg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-arm64-gnu": { + "version": "11.20.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-11.20.0.tgz", + "integrity": "sha512-0bJnmYFp62JdZ4nVMDUZ/C58BCZOCcqgKtnUlp7L9Ojf/czIN+3j72YlLPeWLkzlr6SlYvIQA4SGV/HyO0d+qg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-arm64-musl": { + "version": "11.20.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-11.20.0.tgz", + "integrity": "sha512-wKHHzPKZo7Ufhv/Bt6yxT7FOgnIgW4gwXcJUipkShGp68W3wGVqvr1Sr0fY65lN0Oy6y41+g2kIDvkgZaMMUkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-ppc64-gnu": { + "version": "11.20.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-11.20.0.tgz", + "integrity": "sha512-RN8goF7Ie0B79L4i4G6OeBocTgSC56vJbQ65VJje+oXnldVpLnOU7j/AQ/dP94TcCS+Yh6WG8u3Qt4ETteXFNQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-riscv64-gnu": { + "version": "11.20.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-11.20.0.tgz", + "integrity": "sha512-5l1yU6/xQEqLZRzxqmMxJfWPslpwCmBsdDGaBvABPehxquCXDC7dd7oraNdKSJUMDXSM7VvVj8H2D2FTjU7oWw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-riscv64-musl": { + "version": "11.20.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-11.20.0.tgz", + "integrity": "sha512-xHEvkbgz6UC+A3JOyDQy76LkUaxsNSfIr3/GV8slwZsnuooJiIB34gzJfsyvR4JdCYNUUPsRJc/w/oWkODu+hg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-s390x-gnu": { + "version": "11.20.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-11.20.0.tgz", + "integrity": "sha512-aWPDUUmSeyHvlW+SoEUd+JIJsQhVhu6a5tBpDRMu058naPAchTgAVGCFy35zjbnFlt0i8hLWziff6HX0D3LU4g==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-x64-gnu": { + "version": "11.20.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-11.20.0.tgz", + "integrity": "sha512-x2YeSimvhJjKLVD8KSu8f/rqU1potcdEMkApIPJqjZWN7c2Fpt4g2X32WDg1p+XDAmyT7nuQGe0vnhvXeLbH+g==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-linux-x64-musl": { + "version": "11.20.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-11.20.0.tgz", + "integrity": "sha512-kcRLEIxpZefeYfLChjpgFf3ilBzRDZ+yobMrpRsQlSrxuFGtm3U6PMU7AaEpMqo3NfDGVyJJseAjnRLzMFHjwQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxc-resolver/binding-openharmony-arm64": { + "version": "11.20.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-openharmony-arm64/-/binding-openharmony-arm64-11.20.0.tgz", + "integrity": "sha512-HHcfnApSZGtKhTiHqe8OZruOZe5XuFQH5/E0Yhj3u8fnFvzkM4/k6WjacUf4SvA0SPEAbfbgYmVPuo0VX/fIBQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@oxc-resolver/binding-wasm32-wasi": { + "version": "11.20.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-11.20.0.tgz", + "integrity": "sha512-Tn0y1XOFYHNfK1wp1Z5QK8Rcld/bsOwRISQXfqAZ5IBpv8Gz1IvV39fUWNprqNdRizgcvFhOzWwFun2zkJsyBg==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-resolver/binding-win32-arm64-msvc": { + "version": "11.20.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-11.20.0.tgz", + "integrity": "sha512-qPi25YNPe4YenS8MgsQU2+bIFHxxpLx1LVna2444cEHqNPhNjvWf9zqj4aWE43H9LpAsTmkkAlA3eL5ElBU3mA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@oxc-resolver/binding-win32-x64-msvc": { + "version": "11.20.0", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-11.20.0.tgz", + "integrity": "sha512-Wb14jWEW8huH6It9F6sXd9vrYmIS7pMrgkU6sxpLxkP+9z+wRgs71hUEhRpcn8FOXAFa27FVWfY2tRpbfTzfLw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@playwright/test": { + "version": "1.60.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.60.0.tgz", + "integrity": "sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.60.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@poppinss/colors": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.6.tgz", + "integrity": "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "kleur": "^4.1.5" + } + }, + "node_modules/@poppinss/dumper": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@poppinss/dumper/-/dumper-0.6.5.tgz", + "integrity": "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@poppinss/colors": "^4.1.5", + "@sindresorhus/is": "^7.0.2", + "supports-color": "^10.0.0" + } + }, + "node_modules/@poppinss/exception": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.3.tgz", + "integrity": "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.2.tgz", + "integrity": "sha512-ZS4D1JPGn/MYQN/SYDWftIE/nVsM8j/AFOYEzAoOE2O3NktQOZru+/vYXGbR/qtdLdIfGCP0lcoJiYVzsEz+iQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.2.tgz", + "integrity": "sha512-vdFA9+C/rekyGce7WqHs/xoT0ioZEWaOFyZLIV1mEeNFaFDUQrPIo8Vs2GvJ6eetb3rzDUtUBgzto3ExpXJB3w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.2.tgz", + "integrity": "sha512-BewSOwTHazv77DTYiAZXSqqKZ4KP/KonFisDMVU7PImxoWfB2aepnPhd2E4SWz3zDzYgDNbs6jBmTdgNnF02GA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.2.tgz", + "integrity": "sha512-m41o7M0YWtUdqk61Tb+jnKb2rN++iRdIASlExkUoKfIAH30DOHCB8fVLzSUpbWHHU8esmEioY62PxzexE8MBuA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.2.tgz", + "integrity": "sha512-jcojB9H7W/jS29pMKWAK1N+fU99vXodHDTatS3b3y/XSOCiHo0kkA74pL3jJmkoQtYpOCxDvaKs1fo2Ij/1X5w==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.2.tgz", + "integrity": "sha512-1jn6qDU5iiOgFgygDzKUuKP0maTi0/f1+sBLgvij/76C77Nm3ts6ufz9Bjg5q5dduxiUIxtq86JIoBvo1xQ4Ig==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.2.tgz", + "integrity": "sha512-QVLO/czFMdoMFSqlX3bcswcJNm/23r+qoa/jgtmFc/qEp6/jXmIkDjF/XIo8dPfGaiwy1xfQn8o77L79GeXFgw==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.2.tgz", + "integrity": "sha512-hgO5Abm0w5UL6FEa2iFnZqo2KlK7TQ5QhV5x09hujBf7t5KzHQ1VmfPuTpqRy/rNlSxua3eWH374xxiVrP+lcA==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.2.tgz", + "integrity": "sha512-fy8rXxuYEu602abC8MUNaPjYLIFzReOaEIEMKMUa0rFEUxNpVXhs15KSSQ4qlqSaM7B6rcj9rDZgADh/IGDzLQ==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.2.tgz", + "integrity": "sha512-0+bOkiQ779+r1WpoHOWHqncvyySci0vKph+myNDYb+im6meJAzHQXay6oEgnkHuUGouM1LKTZwqKpBow6Kj7CQ==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.2.tgz", + "integrity": "sha512-mjSkrzZK5Qsl0a9d1JgILOiuZOSDTVdKENcSXBoqbzSrspLR/4/IRVDo5wd2GgZjNss/viBFJdeq+j7qH2nypw==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.2.tgz", + "integrity": "sha512-1v5vHasdfQAZoEHakBV72LIFAC9JjnymsiKxp+GEr/ma3+NJCPSaYK+qavInOovJkgwFrs7GccX2d6IgDA3Z5w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.2.tgz", + "integrity": "sha512-mb1VobWn6NheziTk5/WEaR6AKVbrwT5sOi6C7zk3gy/pD1qtJfU1j4PgTo2NJnOtbL9Dl3Aeei8w9jJ7qC2jZQ==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.2.tgz", + "integrity": "sha512-SqKonF56vA/L2yHwHYcEp2P34URpOZ7d1fS635cTkpDnUtEGdUbhI6NzsPdqeSWvAAeGDrxjWjNmibDIdFf9/A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.2.tgz", + "integrity": "sha512-v7qRI7gXLRINcOGXt+7YmAZ6iFuyZVMIoXAxhd8oP+DR9dLfL9GfNIx7PLMxmhZdvq8waUJBQiWN9EKNy+TRBQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.4.tgz", + "integrity": "sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.4.tgz", + "integrity": "sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.4.tgz", + "integrity": "sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.4.tgz", + "integrity": "sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.4.tgz", + "integrity": "sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.4.tgz", + "integrity": "sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.4.tgz", + "integrity": "sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.4.tgz", + "integrity": "sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.4.tgz", + "integrity": "sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.4.tgz", + "integrity": "sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.4.tgz", + "integrity": "sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.4.tgz", + "integrity": "sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.4.tgz", + "integrity": "sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.4.tgz", + "integrity": "sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.4.tgz", + "integrity": "sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.4.tgz", + "integrity": "sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.4.tgz", + "integrity": "sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.4.tgz", + "integrity": "sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.4.tgz", + "integrity": "sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.4.tgz", + "integrity": "sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.4.tgz", + "integrity": "sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.4.tgz", + "integrity": "sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.4.tgz", + "integrity": "sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.4.tgz", + "integrity": "sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.4.tgz", + "integrity": "sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sindresorhus/is": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz", + "integrity": "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@speed-highlight/core": { + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.15.tgz", + "integrity": "sha512-BMq1K3DsElxDWawkX6eLg9+CKJrTVGCBAWVuHXVUV2u0s2711qiChLSId6ikYPfxhdYocLNt3wWwSvDiTvFabw==", + "dev": true, + "license": "CC0-1.0", + "peer": true + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@storybook/builder-vite": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-10.4.1.tgz", + "integrity": "sha512-/oyQrXoNOqN8SW5hNnYP+I1uvgFxKxWXj/EP6NXYzc5SQwImofgru+D2+6gDhL0+Q//+Hx05DJoQO2omvUJ8bQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/csf-plugin": "10.4.1", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^10.4.1", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@storybook/csf-plugin": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-10.4.1.tgz", + "integrity": "sha512-WdPepGBxDGOUDjYd8KxMtcf+us/2PAcnBczl77XtrnxxHNs0jWesxKkiJ9yiuGrge4BPhDeAj6rxjbBoaHxLBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "unplugin": "^2.3.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "esbuild": "*", + "rollup": "*", + "storybook": "^10.4.1", + "vite": "*", + "webpack": "*" + }, + "peerDependenciesMeta": { + "esbuild": { + "optional": true + }, + "rollup": { + "optional": true + }, + "vite": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@storybook/global": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz", + "integrity": "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@storybook/icons": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-2.0.2.tgz", + "integrity": "sha512-KZBCpXsshAIjczYNXR/rlxEtCUX/eAbpFNwKi8bcOomrLA4t/SyPz5RF+lVPO2oZBUE4sAkt43mfJUevQDSEEw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@storybook/svelte": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@storybook/svelte/-/svelte-10.4.1.tgz", + "integrity": "sha512-DzgCB5UngFZdeOy2wlTIgH2qJQPXFWhtLiv56YGp8KZXZMvj6Ta8dvVESp0aHhABex70jLNMvggN282prxXCuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ts-dedent": "^2.0.0", + "type-fest": "~2.19" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^10.4.1", + "svelte": "^5.0.0" + } + }, + "node_modules/@storybook/svelte-vite": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@storybook/svelte-vite/-/svelte-vite-10.4.1.tgz", + "integrity": "sha512-jbVIlrPOrfU66LBRhGTOyDyhIGtbsJDtesBATHsbUWGcEW97ocdFsjD98qEkl+oAY1Vf2tBAK1vqZgM0u/pb0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/builder-vite": "10.4.1", + "@storybook/svelte": "10.4.1", + "magic-string": "^0.30.0", + "svelte2tsx": "^0.7.44", + "typescript": "^4.9.4 || ^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "@sveltejs/vite-plugin-svelte": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0", + "storybook": "^10.4.1", + "svelte": "^5.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@storybook/svelte-vite/node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/@storybook/sveltekit": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@storybook/sveltekit/-/sveltekit-10.4.1.tgz", + "integrity": "sha512-54jDgjhUNGNPPl5yWDMOVG53wd6KF5UFS1gmL9nwyJWNP7JsQjOLnjrVCtDgrv0K9O/cX7SrgTtgPFoM18BeHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/builder-vite": "10.4.1", + "@storybook/svelte": "10.4.1", + "@storybook/svelte-vite": "10.4.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^10.4.1", + "svelte": "^5.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@svelte-put/shortcut": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@svelte-put/shortcut/-/shortcut-4.1.0.tgz", + "integrity": "sha512-wImNEIkbxAIWFqlfuhcbC+jRPDeRa/uJGIXHMEVVD+jqL9xCwWNnkGQJ6Qb2XVszuRLHlb8SGZDL3Io/h3vs8w==", + "license": "MIT", + "peerDependencies": { + "svelte": "^5.1.0" + } + }, + "node_modules/@sveltejs/acorn-typescript": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.10.tgz", + "integrity": "sha512-4WfKk68eTih+MiJD4fSbxN7E8kVBmTMPWHUPYjvl2N0rMs53YLTT8/YjKU5Dtnz5LqDjl7LEw4U7lXR2W3J5WA==", + "license": "MIT", + "peerDependencies": { + "acorn": "^8.9.0" + } + }, + "node_modules/@sveltejs/adapter-cloudflare": { + "version": "7.2.8", + "resolved": "https://registry.npmjs.org/@sveltejs/adapter-cloudflare/-/adapter-cloudflare-7.2.8.tgz", + "integrity": "sha512-bIdhY/Fi4AQmqiBdQVKnafH1h9Gw+xbCvHyUu4EouC8rJOU02zwhi14k/FDhQ0mJF1iblIu3m8UNQ8GpGIvIOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cloudflare/workers-types": "^4.20250507.0", + "worktop": "0.8.0-next.18" + }, + "peerDependencies": { + "@sveltejs/kit": "^2.0.0", + "wrangler": "^4.0.0" + } }, "node_modules/@sveltejs/kit": { "version": "2.61.1", "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.61.1.tgz", "integrity": "sha512-Ny8s1SR1TyQS2hD2Rvw0XKzU2Nw1eUF52dTb6T2bdcgz7wSC+Nyb5IwjWYlR4b2dvbbR5NJDiQwHg3rnNseghg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@sveltejs/acorn-typescript": "^1.0.9", + "@types/cookie": "^0.6.0", + "acorn": "^8.16.0", + "cookie": "^0.6.0", + "devalue": "^5.8.1", + "esm-env": "^1.2.2", + "kleur": "^4.1.5", + "magic-string": "^0.30.5", + "mrmime": "^2.0.0", + "set-cookie-parser": "^3.0.0", + "sirv": "^3.0.0" + }, + "bin": { + "svelte-kit": "svelte-kit.js" + }, + "engines": { + "node": ">=18.13" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0", + "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0 || ^7.0.0", + "svelte": "^4.0.0 || ^5.0.0-next.0", + "typescript": "^5.3.3 || ^6.0.0", + "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/@sveltejs/vite-plugin-svelte": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-7.1.2.tgz", + "integrity": "sha512-DrUBA2UXRfDmUX/ZTiEopd3X40yavsJF1FX2RygcuIScHL7o5YX1fMvoYnDhjeJQC4weCOklirpNWlcb2NiSeA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "deepmerge": "^4.3.1", + "magic-string": "^0.30.21", + "obug": "^2.1.0", + "vitefu": "^1.1.2" + }, + "engines": { + "node": "^20.19 || ^22.12 || >=24" + }, + "peerDependencies": { + "svelte": "^5.46.4", + "vite": "^8.0.0-beta.7 || ^8.0.0" + } + }, + "node_modules/@swc/helpers": { + "version": "0.5.23", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tailwindcss/node": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.0.tgz", + "integrity": "sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.21.0", + "jiti": "^2.6.1", + "lightningcss": "1.32.0", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.3.0" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.0.tgz", + "integrity": "sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.3.0", + "@tailwindcss/oxide-darwin-arm64": "4.3.0", + "@tailwindcss/oxide-darwin-x64": "4.3.0", + "@tailwindcss/oxide-freebsd-x64": "4.3.0", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.0", + "@tailwindcss/oxide-linux-arm64-gnu": "4.3.0", + "@tailwindcss/oxide-linux-arm64-musl": "4.3.0", + "@tailwindcss/oxide-linux-x64-gnu": "4.3.0", + "@tailwindcss/oxide-linux-x64-musl": "4.3.0", + "@tailwindcss/oxide-wasm32-wasi": "4.3.0", + "@tailwindcss/oxide-win32-arm64-msvc": "4.3.0", + "@tailwindcss/oxide-win32-x64-msvc": "4.3.0" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.0.tgz", + "integrity": "sha512-TJPiq67tKlLuObP6RkwvVGDoxCMBVtDgKkLfa/uyj7/FyxvQwHS+UOnVrXXgbEsfUaMgiVvC4KbJnRr26ho4Ng==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.0.tgz", + "integrity": "sha512-oMN/WZRb+SO37BmUElEgeEWuU8E/HXRkiODxJxLe1UTHVXLrdVSgfaJV7pSlhRGMSOiXLuxTIjfsF3wYvz8cgQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.0.tgz", + "integrity": "sha512-N6CUmu4a6bKVADfw77p+iw6Yd9Q3OBhe0veaDX+QazfuVYlQsHfDgxBrsjQ/IW+zywL8mTrNd0SdJT/zgtvMdA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.0.tgz", + "integrity": "sha512-zDL5hBkQdH5C6MpqbK3gQAgP80tsMwSI26vjOzjJtNCMUo0lFgOItzHKBIupOZNQxt3ouPH7RPhvNhiTfCe5CQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.0.tgz", + "integrity": "sha512-R06HdNi7A7OEoMsf6d4tjZ71RCWnZQPHj2mnotSFURjNLdBC+cIgXQ7l81CqeoiQftjf6OOblxXMInMgN2VzMA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.0.tgz", + "integrity": "sha512-qTJHELX8jetjhRQHCLilkVLmybpzNQAtaI/gaoVoidn/ufbNDbAo8KlK2J+yPoc8wQxvDxCmh/5lr8nC1+lTbg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.0.tgz", + "integrity": "sha512-Z6sukiQsngnWO+l39X4pPbiWT81IC+PLKF+PHxIlyZbGNb9MODfYlXEVlFvej5BOZInWX01kVyzeLvHsXhfczQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.0.tgz", + "integrity": "sha512-DRNdQRpSGzRGfARVuVkxvM8Q12nh19l4BF/G7zGA1oe+9wcC6saFBHTISrpIcKzhiXtSrlSrluCfvMuledoCTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.0.tgz", + "integrity": "sha512-Z0IADbDo8bh6I7h2IQMx601AdXBLfFpEdUotft86evd/8ZPflZe9COPO8Q1vw+pfLWIUo9zN/JGZvwuAJqduqg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.0.tgz", + "integrity": "sha512-HNZGOUxEmElksYR7S6sC5jTeNGpobAsy9u7Gu0AskJ8/20FR9GqebUyB+HBcU/ax6BHuiuJi+Oda4B+YX6H1yA==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "@standard-schema/spec": "^1.0.0", - "@sveltejs/acorn-typescript": "^1.0.9", - "@types/cookie": "^0.6.0", - "acorn": "^8.16.0", - "cookie": "^0.6.0", - "devalue": "^5.8.1", - "esm-env": "^1.2.2", - "kleur": "^4.1.5", - "magic-string": "^0.30.5", - "mrmime": "^2.0.0", - "set-cookie-parser": "^3.0.0", - "sirv": "^3.0.0" + "@emnapi/core": "^1.10.0", + "@emnapi/runtime": "^1.10.0", + "@emnapi/wasi-threads": "^1.2.1", + "@napi-rs/wasm-runtime": "^1.1.4", + "@tybys/wasm-util": "^0.10.1", + "tslib": "^2.8.1" }, - "bin": { - "svelte-kit": "svelte-kit.js" + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.0.tgz", + "integrity": "sha512-Pe+RPVTi1T+qymuuRpcdvwSVZjnll/f7n8gBxMMh3xLTctMDKqpdfGimbMyioqtLhUYZxdJ9wGNhV7MKHvgZsQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.0.tgz", + "integrity": "sha512-Mvrf2kXW/yeW/OTezZlCGOirXRcUuLIBx/5Y12BaPM7wJoryG6dfS/NJL8aBPqtTEx/Vm4T4vKzFUcKDT+TKUA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/vite": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.0.tgz", + "integrity": "sha512-t6J3OrB5Fc0ExuhohouH0fWUGMYL6PTLhW+E7zIk/pdbnJARZDCwjBznFnkh5ynRnIRSI4YjtTH0t6USjJISrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tailwindcss/node": "4.3.0", + "@tailwindcss/oxide": "4.3.0", + "tailwindcss": "4.3.0" + }, + "peerDependencies": { + "vite": "^5.2.0 || ^6 || ^7 || ^8" + } + }, + "node_modules/@testing-library/dom": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", + "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "picocolors": "1.1.1", + "pretty-format": "^27.0.2" }, "engines": { - "node": ">=18.13" + "node": ">=18" + } + }, + "node_modules/@testing-library/dom/node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.9.1.tgz", + "integrity": "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@adobe/css-tools": "^4.4.0", + "aria-query": "^5.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "picocolors": "^1.1.1", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@testing-library/svelte": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@testing-library/svelte/-/svelte-5.3.1.tgz", + "integrity": "sha512-8Ez7ZOqW5geRf9PF5rkuopODe5RGy3I9XR+kc7zHh26gBiktLaxTfKmhlGaSHYUOTQE7wFsLMN9xCJVCszw47w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@testing-library/dom": "9.x.x || 10.x.x", + "@testing-library/svelte-core": "1.0.0" + }, + "engines": { + "node": ">= 10" }, "peerDependencies": { - "@opentelemetry/api": "^1.0.0", - "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0 || ^7.0.0", - "svelte": "^4.0.0 || ^5.0.0-next.0", - "typescript": "^5.3.3 || ^6.0.0", - "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0 || ^8.0.0" + "svelte": "^3 || ^4 || ^5 || ^5.0.0-next.0", + "vite": "*", + "vitest": "*" }, "peerDependenciesMeta": { - "@opentelemetry/api": { + "vite": { "optional": true }, - "typescript": { + "vitest": { "optional": true } } }, - "node_modules/@sveltejs/vite-plugin-svelte": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-7.1.2.tgz", - "integrity": "sha512-DrUBA2UXRfDmUX/ZTiEopd3X40yavsJF1FX2RygcuIScHL7o5YX1fMvoYnDhjeJQC4weCOklirpNWlcb2NiSeA==", + "node_modules/@testing-library/svelte-core": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@testing-library/svelte-core/-/svelte-core-1.0.0.tgz", + "integrity": "sha512-VkUePoLV6oOYwSUvX6ShA8KLnJqZiYMIbP2JW2t0GLWLkJxKGvuH5qrrZBV/X7cXFnLGuFQEC7RheYiZOW68KQ==", "dev": true, "license": "MIT", - "dependencies": { - "deepmerge": "^4.3.1", - "magic-string": "^0.30.21", - "obug": "^2.1.0", - "vitefu": "^1.1.2" + "engines": { + "node": ">=16" }, + "peerDependencies": { + "svelte": "^3 || ^4 || ^5 || ^5.0.0-next.0" + } + }, + "node_modules/@testing-library/user-event": { + "version": "14.6.1", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz", + "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==", + "dev": true, + "license": "MIT", "engines": { - "node": "^20.19 || ^22.12 || >=24" + "node": ">=12", + "npm": ">=6" }, "peerDependencies": { - "svelte": "^5.46.4", - "vite": "^8.0.0-beta.7 || ^8.0.0" + "@testing-library/dom": ">=7.21.4" } }, "node_modules/@tybys/wasm-util": { "version": "0.10.2", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { "tslib": "^2.4.0" } }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, "node_modules/@types/cookie": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/@types/d3-color": { @@ -2443,18 +4328,130 @@ "@types/d3-selection": "*" } }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "license": "MIT" }, + "node_modules/@types/node": { + "version": "25.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz", + "integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "undici-types": ">=7.24.0 <7.24.7" + } + }, "node_modules/@types/trusted-types": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", "license": "MIT" }, + "node_modules/@vitest/expect": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", + "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", + "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "3.2.4", + "pathe": "^2.0.3", + "strip-literal": "^3.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", + "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.4", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", + "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^4.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", + "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.4", + "loupe": "^3.1.4", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@webcontainer/env": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@webcontainer/env/-/env-1.1.1.tgz", + "integrity": "sha512-6aN99yL695Hi9SuIk1oC88l9o0gmxL1nGWWQ/kNy81HigJ0FoaoTXpytCj6ItzgyCEwA9kF1wixsTuv5cjsgng==", + "dev": true, + "license": "MIT" + }, "node_modules/@xyflow/svelte": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/@xyflow/svelte/-/svelte-1.5.2.tgz", @@ -2485,43 +4482,192 @@ "d3-zoom": "^3.0.0" } }, - "node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/aria-query": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz", + "integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "require-from-string": "^2.0.2" + } + }, + "node_modules/bits-ui": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-2.18.1.tgz", + "integrity": "sha512-KkemzKFH4T3gt3H+P86JcnAWExjByv/6vlwjm/BoCwTPHu03yiCdxbghdJLvFReQTe0acCAiRcKfmixxD6XvlA==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.1", + "@floating-ui/dom": "^1.7.1", + "esm-env": "^1.1.2", + "runed": "^0.35.1", + "svelte-toolbelt": "^0.10.6", + "tabbable": "^6.2.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/huntabyte" + }, + "peerDependencies": { + "@internationalized/date": "^3.8.1", + "svelte": "^5.33.0" + } + }, + "node_modules/blake3-wasm": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", + "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, "license": "MIT", - "bin": { - "acorn": "bin/acorn" + "dependencies": { + "run-applescript": "^7.0.0" }, "engines": { - "node": ">=0.4.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/aria-query": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz", - "integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==", - "license": "Apache-2.0", + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=8" } }, - "node_modules/axobject-query": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", - "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", - "license": "Apache-2.0", + "node_modules/chai": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=18" } }, - "node_modules/blake3-wasm": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", - "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", + "node_modules/check-error": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", + "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", "dev": true, "license": "MIT", - "peer": true + "engines": { + "node": ">= 16" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } }, "node_modules/clsx": { "version": "2.1.1", @@ -2551,7 +4697,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -2563,6 +4709,27 @@ "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", "license": "MIT" }, + "node_modules/css-tree": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true, + "license": "MIT" + }, "node_modules/d3-color": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", @@ -2668,21 +4835,129 @@ "node": ">=12" } }, + "node_modules/data-urls": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz", + "integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^16.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "dev": true, + "license": "MIT" + }, + "node_modules/dedent-js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dedent-js/-/dedent-js-1.0.1.tgz", + "integrity": "sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, + "node_modules/default-browser": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "engines": { "node": ">=8" @@ -2694,6 +4969,40 @@ "integrity": "sha512-4CXDYRBGqN+57wVJkuXBYmpAVUSg3L6JAQa/DFqm238G73E1wuyc/JhGQJzN7vUf/CMphYau2zXbfWzDR5aTEw==", "license": "MIT" }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true, + "license": "MIT" + }, + "node_modules/enhanced-resolve": { + "version": "5.22.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.22.1.tgz", + "integrity": "sha512-6QEuw3zoX1SJQc7b87aBXke/no+mG2bTBgw29gWMQonLmpEkWoCAVkl+M49e48AZlWzxiDzDZzYdp6kobcyLww==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz", + "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/error-stack-parser-es": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", @@ -2705,14 +5014,20 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, "node_modules/esbuild": { "version": "0.27.3", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", - "dev": true, + "devOptional": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -2754,6 +5069,20 @@ "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==", "license": "MIT" }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/esrap": { "version": "2.2.9", "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.9.tgz", @@ -2771,11 +5100,31 @@ } } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=12.0.0" @@ -2793,7 +5142,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -2804,6 +5152,90 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/html-encoding-sniffer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", + "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.6.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/html-to-image": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-1.11.13.tgz", + "integrity": "sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg==", + "license": "MIT" + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inline-style-parser": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", + "license": "MIT" + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, "node_modules/is-reference": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", @@ -2813,11 +5245,95 @@ "@types/estree": "^1.0.6" } }, + "node_modules/is-wsl": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "devOptional": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsdom": { + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.1.1.tgz", + "integrity": "sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^5.1.11", + "@asamuzakjp/dom-selector": "^7.1.1", + "@bramus/specificity": "^2.4.2", + "@csstools/css-syntax-patches-for-csstree": "^1.1.3", + "@exodus/bytes": "^1.15.0", + "css-tree": "^3.2.1", + "data-urls": "^7.0.0", + "decimal.js": "^10.6.0", + "html-encoding-sniffer": "^6.0.0", + "is-potential-custom-element-name": "^1.0.1", + "lru-cache": "^11.3.5", + "parse5": "^8.0.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^6.0.1", + "undici": "^7.25.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^8.0.1", + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^16.0.1", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24.0.0" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/undici": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.26.0.tgz", + "integrity": "sha512-3O9Tf67pGhgOv9jM35AbhkXAKi13f3oy3aE4CSgr+TckGeY+/iu97ZXN+J7DpHPzLbVApFd1IFhcnBjREYXYcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, "node_modules/kleur": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=6" @@ -2827,7 +5343,7 @@ "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", - "dev": true, + "devOptional": true, "license": "MPL-2.0", "dependencies": { "detect-libc": "^2.0.3" @@ -2860,7 +5376,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -2881,7 +5396,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -2902,7 +5416,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -2923,7 +5436,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -2944,7 +5456,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -2965,7 +5476,6 @@ "cpu": [ "arm64" ], - "dev": true, "libc": [ "glibc" ], @@ -2989,7 +5499,6 @@ "cpu": [ "arm64" ], - "dev": true, "libc": [ "musl" ], @@ -3013,7 +5522,6 @@ "cpu": [ "x64" ], - "dev": true, "libc": [ "glibc" ], @@ -3037,7 +5545,6 @@ "cpu": [ "x64" ], - "dev": true, "libc": [ "musl" ], @@ -3061,7 +5568,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -3082,7 +5588,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -3102,6 +5607,32 @@ "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", "license": "MIT" }, + "node_modules/loupe": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "11.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz", + "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "license": "MIT", + "bin": { + "lz-string": "bin/bin.js" + } + }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -3111,6 +5642,23 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/miniflare": { "version": "4.20260526.0", "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20260526.0.tgz", @@ -3133,21 +5681,38 @@ "node": ">=22.0.0" } }, + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/mrmime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=10" } }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, "node_modules/nanoid": { "version": "3.3.12", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", - "dev": true, + "devOptional": true, "funding": [ { "type": "github", @@ -3166,13 +5731,124 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", - "dev": true, + "devOptional": true, "funding": [ "https://github.com/sponsors/sxzz", "https://opencollective.com/debug" ], "license": "MIT" }, + "node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/oxc-parser": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.127.0.tgz", + "integrity": "sha512-bkgD4qHlN7WxLdX8bLXdaU54TtQtAIg/ZBAfm0aje/mo3MRDo3P0hZSgr4U7O3xfX+fQmR5AP04JS/TGcZLcFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "^0.127.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/Boshen" + }, + "optionalDependencies": { + "@oxc-parser/binding-android-arm-eabi": "0.127.0", + "@oxc-parser/binding-android-arm64": "0.127.0", + "@oxc-parser/binding-darwin-arm64": "0.127.0", + "@oxc-parser/binding-darwin-x64": "0.127.0", + "@oxc-parser/binding-freebsd-x64": "0.127.0", + "@oxc-parser/binding-linux-arm-gnueabihf": "0.127.0", + "@oxc-parser/binding-linux-arm-musleabihf": "0.127.0", + "@oxc-parser/binding-linux-arm64-gnu": "0.127.0", + "@oxc-parser/binding-linux-arm64-musl": "0.127.0", + "@oxc-parser/binding-linux-ppc64-gnu": "0.127.0", + "@oxc-parser/binding-linux-riscv64-gnu": "0.127.0", + "@oxc-parser/binding-linux-riscv64-musl": "0.127.0", + "@oxc-parser/binding-linux-s390x-gnu": "0.127.0", + "@oxc-parser/binding-linux-x64-gnu": "0.127.0", + "@oxc-parser/binding-linux-x64-musl": "0.127.0", + "@oxc-parser/binding-openharmony-arm64": "0.127.0", + "@oxc-parser/binding-wasm32-wasi": "0.127.0", + "@oxc-parser/binding-win32-arm64-msvc": "0.127.0", + "@oxc-parser/binding-win32-ia32-msvc": "0.127.0", + "@oxc-parser/binding-win32-x64-msvc": "0.127.0" + } + }, + "node_modules/oxc-parser/node_modules/@oxc-project/types": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.127.0.tgz", + "integrity": "sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/oxc-resolver": { + "version": "11.20.0", + "resolved": "https://registry.npmjs.org/oxc-resolver/-/oxc-resolver-11.20.0.tgz", + "integrity": "sha512-CblytBiV/a/ZXY34dsVU2NxhIOxMXst8CvDCtyBelVITgd7PLrKzbEbA6oKLdPjvDKDzCiW48qzmzZ+mYaqn+g==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + }, + "optionalDependencies": { + "@oxc-resolver/binding-android-arm-eabi": "11.20.0", + "@oxc-resolver/binding-android-arm64": "11.20.0", + "@oxc-resolver/binding-darwin-arm64": "11.20.0", + "@oxc-resolver/binding-darwin-x64": "11.20.0", + "@oxc-resolver/binding-freebsd-x64": "11.20.0", + "@oxc-resolver/binding-linux-arm-gnueabihf": "11.20.0", + "@oxc-resolver/binding-linux-arm-musleabihf": "11.20.0", + "@oxc-resolver/binding-linux-arm64-gnu": "11.20.0", + "@oxc-resolver/binding-linux-arm64-musl": "11.20.0", + "@oxc-resolver/binding-linux-ppc64-gnu": "11.20.0", + "@oxc-resolver/binding-linux-riscv64-gnu": "11.20.0", + "@oxc-resolver/binding-linux-riscv64-musl": "11.20.0", + "@oxc-resolver/binding-linux-s390x-gnu": "11.20.0", + "@oxc-resolver/binding-linux-x64-gnu": "11.20.0", + "@oxc-resolver/binding-linux-x64-musl": "11.20.0", + "@oxc-resolver/binding-openharmony-arm64": "11.20.0", + "@oxc-resolver/binding-wasm32-wasi": "11.20.0", + "@oxc-resolver/binding-win32-arm64-msvc": "11.20.0", + "@oxc-resolver/binding-win32-x64-msvc": "11.20.0" + } + }, + "node_modules/parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz", + "integrity": "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^8.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/path-to-regexp": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", @@ -3186,21 +5862,30 @@ "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "dev": true, "license": "MIT", - "peer": true + "engines": { + "node": ">= 14.16" + } }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, + "devOptional": true, "license": "ISC" }, "node_modules/picomatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=12" @@ -3209,11 +5894,58 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/playwright": { + "version": "1.60.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.60.0.tgz", + "integrity": "sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.60.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.60.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.60.0.tgz", + "integrity": "sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/postcss": { "version": "8.5.15", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", - "dev": true, + "devOptional": true, "funding": [ { "type": "opencollective", @@ -3253,6 +5985,108 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/react": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", + "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz", + "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.6" + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true, + "license": "MIT" + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/recast": { + "version": "0.23.11", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz", + "integrity": "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ast-types": "^0.16.1", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tiny-invariant": "^1.3.3", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/regexparam": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/regexparam/-/regexparam-3.0.0.tgz", @@ -3263,11 +6097,21 @@ "node": ">=8" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/rolldown": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.2.tgz", "integrity": "sha512-oZx5zVDtVB44AW3eaifgDml1gWRDZGvjcfdxonE4swNPG98PrrXjaO/KrnUjzlMnztCCRVlUueA1kCXhARGk6g==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@oxc-project/types": "=0.132.0", @@ -3297,6 +6141,58 @@ "@rolldown/binding-win32-x64-msvc": "1.0.2" } }, + "node_modules/rollup": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.4.tgz", + "integrity": "sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.60.4", + "@rollup/rollup-android-arm64": "4.60.4", + "@rollup/rollup-darwin-arm64": "4.60.4", + "@rollup/rollup-darwin-x64": "4.60.4", + "@rollup/rollup-freebsd-arm64": "4.60.4", + "@rollup/rollup-freebsd-x64": "4.60.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.4", + "@rollup/rollup-linux-arm-musleabihf": "4.60.4", + "@rollup/rollup-linux-arm64-gnu": "4.60.4", + "@rollup/rollup-linux-arm64-musl": "4.60.4", + "@rollup/rollup-linux-loong64-gnu": "4.60.4", + "@rollup/rollup-linux-loong64-musl": "4.60.4", + "@rollup/rollup-linux-ppc64-gnu": "4.60.4", + "@rollup/rollup-linux-ppc64-musl": "4.60.4", + "@rollup/rollup-linux-riscv64-gnu": "4.60.4", + "@rollup/rollup-linux-riscv64-musl": "4.60.4", + "@rollup/rollup-linux-s390x-gnu": "4.60.4", + "@rollup/rollup-linux-x64-gnu": "4.60.4", + "@rollup/rollup-linux-x64-musl": "4.60.4", + "@rollup/rollup-openbsd-x64": "4.60.4", + "@rollup/rollup-openharmony-arm64": "4.60.4", + "@rollup/rollup-win32-arm64-msvc": "4.60.4", + "@rollup/rollup-win32-ia32-msvc": "4.60.4", + "@rollup/rollup-win32-x64-gnu": "4.60.4", + "@rollup/rollup-win32-x64-msvc": "4.60.4", + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup/node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, "node_modules/rosie-skills": { "version": "0.6.4", "resolved": "https://registry.npmjs.org/rosie-skills/-/rosie-skills-0.6.4.tgz", @@ -3331,43 +6227,120 @@ ], "peer": true }, - "node_modules/rosie-skills-freebsd-x64": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/rosie-skills-freebsd-x64/-/rosie-skills-freebsd-x64-0.6.4.tgz", - "integrity": "sha512-SxCRduPBMtfjkQ+q56Yw9OLA3PyaqoALzt7kER7IDKuUVfM2O/1w8sa5xhTDiCvWkZJixnH5d5Ya6KT+/Mwcng==", - "cpu": [ - "x64" - ], + "node_modules/rosie-skills-freebsd-x64": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/rosie-skills-freebsd-x64/-/rosie-skills-freebsd-x64-0.6.4.tgz", + "integrity": "sha512-SxCRduPBMtfjkQ+q56Yw9OLA3PyaqoALzt7kER7IDKuUVfM2O/1w8sa5xhTDiCvWkZJixnH5d5Ya6KT+/Mwcng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "freebsd" + ], + "peer": true + }, + "node_modules/rosie-skills-linux-x64": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/rosie-skills-linux-x64/-/rosie-skills-linux-x64-0.6.4.tgz", + "integrity": "sha512-D9Y9mfu7goB0s0X59uU3hcFeUTef3VbpCIDwFMzyvJrAq3XhRACWBDMHQsHlyWdHxTXPX/ILyW65RXyrJlgqng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/runed": { + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/runed/-/runed-0.35.1.tgz", + "integrity": "sha512-2F4Q/FZzbeJTFdIS/PuOoPRSm92sA2LhzTnv6FXhCoENb3huf5+fDuNOg1LNvGOouy3u/225qxmuJvcV3IZK5Q==", + "funding": [ + "https://github.com/sponsors/huntabyte", + "https://github.com/sponsors/tglide" + ], + "license": "MIT", + "dependencies": { + "dequal": "^2.0.3", + "esm-env": "^1.0.0", + "lz-string": "^1.5.0" + }, + "peerDependencies": { + "@sveltejs/kit": "^2.21.0", + "svelte": "^5.7.0" + }, + "peerDependenciesMeta": { + "@sveltejs/kit": { + "optional": true + } + } + }, + "node_modules/sade": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", + "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "mri": "^1.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", "dev": true, - "license": "BSD-3-Clause", - "optional": true, - "os": [ - "freebsd" - ], - "peer": true + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } }, - "node_modules/rosie-skills-linux-x64": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/rosie-skills-linux-x64/-/rosie-skills-linux-x64-0.6.4.tgz", - "integrity": "sha512-D9Y9mfu7goB0s0X59uU3hcFeUTef3VbpCIDwFMzyvJrAq3XhRACWBDMHQsHlyWdHxTXPX/ILyW65RXyrJlgqng==", - "cpu": [ - "x64" - ], + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", "dev": true, - "license": "BSD-3-Clause", - "optional": true, - "os": [ - "linux" - ], + "license": "MIT", "peer": true }, + "node_modules/scule": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/scule/-/scule-1.3.0.tgz", + "integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==", + "dev": true, + "license": "MIT" + }, "node_modules/semver": { "version": "7.8.1", "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", "integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", "dev": true, "license": "ISC", - "peer": true, "bin": { "semver": "bin/semver.js" }, @@ -3379,7 +6352,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-3.1.0.tgz", "integrity": "sha512-kjnC1DXBHcxaOaOXBHBeRtltsDG2nUiUni+jP92M9gYdW12rsmx92UsfpH7o5tDRs7I1ZZPSQJQGv3UaRfCiuw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/sharp": { @@ -3389,7 +6362,6 @@ "dev": true, "hasInstallScript": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", @@ -3428,11 +6400,18 @@ "@img/sharp-win32-x64": "0.34.5" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/sirv": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@polka/url": "^1.0.0-next.24", @@ -3443,22 +6422,135 @@ "node": ">=18" } }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, + "devOptional": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "dev": true, + "license": "MIT" + }, + "node_modules/storybook": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-10.4.1.tgz", + "integrity": "sha512-V1Zd2e+gBFufqAQVZ1JR8KLqALsEZ3JYSBnWwQbKa6zCfWWanR6AFMyuOkLt2gZOgGp3h2Riuz88pGNVTQSG0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/global": "^5.0.0", + "@storybook/icons": "^2.0.2", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/user-event": "^14.6.1", + "@vitest/expect": "3.2.4", + "@vitest/spy": "3.2.4", + "@webcontainer/env": "^1.1.1", + "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.26.0 || ^0.27.0", + "open": "^10.2.0", + "oxc-parser": "^0.127.0", + "oxc-resolver": "^11.19.1", + "recast": "^0.23.5", + "semver": "^7.7.3", + "use-sync-external-store": "^1.5.0", + "ws": "^8.18.0" + }, + "bin": { + "storybook": "dist/bin/dispatcher.js" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "prettier": "^2 || ^3", + "vite-plus": "^0.1.15" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "prettier": { + "optional": true + }, + "vite-plus": { + "optional": true + } + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-literal": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz", + "integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^9.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/strip-literal/node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true, + "license": "MIT" + }, "node_modules/style-mod": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz", "integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==", "license": "MIT" }, + "node_modules/style-to-object": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", + "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.7" + } + }, "node_modules/supports-color": { "version": "10.2.2", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", @@ -3500,11 +6592,153 @@ "node": ">=18" } }, + "node_modules/svelte-check": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.5.0.tgz", + "integrity": "sha512-9lNwPxCLWniFvQIcEv1LFqjIxcFtO3smb5+5BKbRJ3ttL4o2lXCej5rLF4DAnfLPI66oaA81vAxw6ILdIWI7kA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "chokidar": "^4.0.1", + "fdir": "^6.2.0", + "picocolors": "^1.0.0", + "sade": "^1.7.4" + }, + "bin": { + "svelte-check": "bin/svelte-check" + }, + "engines": { + "node": ">= 18.0.0" + }, + "peerDependencies": { + "svelte": "^4.0.0 || ^5.0.0-next.0", + "typescript": ">=5.0.0" + } + }, + "node_modules/svelte-toolbelt": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/svelte-toolbelt/-/svelte-toolbelt-0.10.6.tgz", + "integrity": "sha512-YWuX+RE+CnWYx09yseAe4ZVMM7e7GRFZM6OYWpBKOb++s+SQ8RBIMMe+Bs/CznBMc0QPLjr+vDBxTAkozXsFXQ==", + "funding": [ + "https://github.com/sponsors/huntabyte" + ], + "dependencies": { + "clsx": "^2.1.1", + "runed": "^0.35.1", + "style-to-object": "^1.0.8" + }, + "engines": { + "node": ">=18", + "pnpm": ">=8.7.0" + }, + "peerDependencies": { + "svelte": "^5.30.2" + } + }, + "node_modules/svelte2tsx": { + "version": "0.7.55", + "resolved": "https://registry.npmjs.org/svelte2tsx/-/svelte2tsx-0.7.55.tgz", + "integrity": "sha512-JWzgeM3lqySRNfqcsesvVEh8LhTWBxQJ9RMjzJ+VepdmXtVnNd0SbtGctG6+/fbHq0N6mhwSd823gszw9JHeGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dedent-js": "^1.0.1", + "scule": "^1.3.0" + }, + "peerDependencies": { + "svelte": "^3.55 || ^4.0.0-next.0 || ^4.0 || ^5.0.0-next.0", + "typescript": "^4.9.4 || ^5.0.0 || ^6.0.0" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tabbable": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", + "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", + "license": "MIT" + }, + "node_modules/tailwind-merge": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.6.0.tgz", + "integrity": "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwind-variants": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/tailwind-variants/-/tailwind-variants-3.2.2.tgz", + "integrity": "sha512-Mi4kHeMTLvKlM98XPnK+7HoBPmf4gygdFmqQPaDivc3DpYS6aIY6KiG/PgThrGvii5YZJqRsPz0aPyhoFzmZgg==", + "license": "MIT", + "engines": { + "node": ">=16.x", + "pnpm": ">=7.x" + }, + "peerDependencies": { + "tailwind-merge": ">=3.0.0", + "tailwindcss": "*" + }, + "peerDependenciesMeta": { + "tailwind-merge": { + "optional": true + } + } + }, + "node_modules/tailwindcss": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.0.tgz", + "integrity": "sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==", + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.16", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "fdir": "^6.5.0", @@ -3517,23 +6751,144 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, + "node_modules/tinypool": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz", + "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tldts": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.2.tgz", + "integrity": "sha512-kCwffuaH8ntKtygnWe1b4BJKWiCUH30n5KfoTr6IchcXOwR7chAOFJxFrH3vjANafUYrIA4a7SDL+nn7SiR4Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^7.4.2" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.2.tgz", + "integrity": "sha512-nwEyF4vl4RSJjwSjBUmOSxc3BFPoIFdlRthJ6e+5v9P3bHNsoD06UjuqMUspqp7vsEZ1beaHi1km+optiE17yA==", + "dev": true, + "license": "MIT" + }, "node_modules/totalist": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/tough-cookie": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.1.tgz", + "integrity": "sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^7.0.5" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.10" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tw-animate-css": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.4.0.tgz", + "integrity": "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Wombosvideo" + } + }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true, - "license": "0BSD", - "optional": true + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } }, "node_modules/undici": { "version": "7.24.8", @@ -3543,25 +6898,58 @@ "license": "MIT", "peer": true, "engines": { - "node": ">=20.18.1" + "node": ">=20.18.1" + } + }, + "node_modules/undici-types": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/unenv": { + "version": "2.0.0-rc.24", + "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz", + "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "pathe": "^2.0.3" + } + }, + "node_modules/unplugin": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.11.tgz", + "integrity": "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "acorn": "^8.15.0", + "picomatch": "^4.0.3", + "webpack-virtual-modules": "^0.6.2" + }, + "engines": { + "node": ">=18.12.0" } }, - "node_modules/unenv": { - "version": "2.0.0-rc.24", - "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz", - "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==", + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "pathe": "^2.0.3" + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/vite": { "version": "8.0.14", "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.14.tgz", "integrity": "sha512-s4BJJ+5y1pYL6Otw51FHhVJQhPnuRinKig64g/1+EUNaJsd3gCKdD31IPFvswUgW9/60QT9oFHbZHbQK5imcxw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "lightningcss": "^1.32.0", @@ -3635,11 +7023,109 @@ } } }, + "node_modules/vite-node": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.4.1", + "es-module-lexer": "^1.7.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite-node/node_modules/vite": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.3.tgz", + "integrity": "sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, "node_modules/vitefu": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.3.tgz", "integrity": "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==", - "dev": true, + "devOptional": true, "license": "MIT", "workspaces": [ "tests/deps/*", @@ -3655,12 +7141,259 @@ } } }, + "node_modules/vitest": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", + "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/expect": "3.2.4", + "@vitest/mocker": "3.2.4", + "@vitest/pretty-format": "^3.2.4", + "@vitest/runner": "3.2.4", + "@vitest/snapshot": "3.2.4", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "debug": "^4.4.1", + "expect-type": "^1.2.1", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "picomatch": "^4.0.2", + "std-env": "^3.9.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.14", + "tinypool": "^1.1.1", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", + "vite-node": "3.2.4", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.2.4", + "@vitest/ui": "3.2.4", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/@vitest/mocker": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", + "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.2.4", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/vite": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.3.tgz", + "integrity": "sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, "node_modules/w3c-keyname": { "version": "2.2.8", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", "license": "MIT" }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/webidl-conversions": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz", + "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=20" + } + }, + "node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/whatwg-mimetype": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", + "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/whatwg-url": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-16.0.1.tgz", + "integrity": "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.11.0", + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/workerd": { "version": "1.20260526.1", "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260526.1.tgz", @@ -3740,7 +7473,6 @@ "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10.0.0" }, @@ -3757,6 +7489,39 @@ } } }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" + }, "node_modules/youch": { "version": "4.1.0-beta.10", "resolved": "https://registry.npmjs.org/youch/-/youch-4.1.0-beta.10.tgz", diff --git a/web-ide/package.json b/web-ide/package.json index 04cb0dc..03de90f 100644 --- a/web-ide/package.json +++ b/web-ide/package.json @@ -8,14 +8,39 @@ "build": "vite build", "postbuild": "printf '_worker.js\\n_routes.json\\n' > .svelte-kit/cloudflare/.assetsignore", "preview": "vite preview", - "build:wasm": "wasm-pack build ../crates/pseudoscript-wasm --release --target web --out-dir ../../web-ide/src/lib/pds-wasm && rm -f src/lib/pds-wasm/.gitignore src/lib/pds-wasm/package.json src/lib/pds-wasm/README.md" + "build:wasm": "wasm-pack build ../crates/pseudoscript-wasm --release --target web --out-dir ../../web-ide/src/lib/pds-wasm && rm -f src/lib/pds-wasm/.gitignore src/lib/pds-wasm/package.json src/lib/pds-wasm/README.md", + "bundle:skill": "bun scripts/bundle-skill.mjs", + "icons": "node scripts/icons.mjs", + "test": "vitest run", + "test:watch": "vitest", + "test:e2e": "playwright test", + "storybook": "storybook dev -p 6006", + "build-storybook": "storybook build", + "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json" }, "devDependencies": { + "@internationalized/date": "^3.12.2", + "@lucide/svelte": "^1.17.0", + "@playwright/test": "^1.60.0", + "@storybook/sveltekit": "^10.4.1", "@sveltejs/adapter-cloudflare": "^7.2.8", "@sveltejs/kit": "^2.61.1", "@sveltejs/vite-plugin-svelte": "^7.1.2", + "@tailwindcss/vite": "^4.3.0", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/svelte": "^5.3.1", + "@testing-library/user-event": "^14.6.1", + "@types/node": "^25.9.1", + "jsdom": "^29.1.1", + "sharp": "^0.34.5", + "storybook": "^10.4.1", "svelte": "^5.56.0", - "vite": "^8" + "svelte-check": "^4.5.0", + "tailwindcss": "^4.3.0", + "tw-animate-css": "^1.4.0", + "typescript": "^6.0.3", + "vite": "^8", + "vitest": "^3.2.4" }, "dependencies": { "@codemirror/autocomplete": "^6.20.2", @@ -23,6 +48,7 @@ "@codemirror/lang-markdown": "^6.5.0", "@codemirror/language": "^6.12.3", "@codemirror/language-data": "^6.5.2", + "@codemirror/legacy-modes": "^6.5.3", "@codemirror/lint": "^6.9.6", "@codemirror/search": "^6.7.0", "@codemirror/state": "^6.6.0", @@ -30,9 +56,13 @@ "@dagrejs/dagre": "3.0.0", "@lezer/highlight": "^1.2.3", "@lezer/markdown": "^1.6.4", - "@lucide/svelte": "^1.17.0", "@xyflow/svelte": "1.5.2", + "bits-ui": "^2.18.1", + "clsx": "^2.1.1", "codemirror": "^6.0.2", - "prettier": "^3.8.3" + "html-to-image": "^1.11.13", + "prettier": "^3.8.3", + "tailwind-merge": "^3.6.0", + "tailwind-variants": "^3.2.2" } } diff --git a/web-ide/playwright.config.ts b/web-ide/playwright.config.ts new file mode 100644 index 0000000..826040c --- /dev/null +++ b/web-ide/playwright.config.ts @@ -0,0 +1,26 @@ +import { defineConfig, devices } from "@playwright/test"; + +// End-to-end tests drive the real IDE (real wasm compiler) headlessly. The dev +// server is started for the run and reused locally. Selectors are data-testid on +// our components and data-sem on highlight marks — never label text or styling +// classes — so the tests survive copy and CSS changes. +const PORT = 4173; + +export default defineConfig({ + testDir: "./e2e", + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + reporter: process.env.CI ? "github" : "list", + use: { + baseURL: `http://localhost:${PORT}`, + trace: "on-first-retry", + }, + projects: [{ name: "chromium", use: { ...devices["Desktop Chrome"] } }], + webServer: { + command: `npm run dev -- --port ${PORT} --strictPort`, + url: `http://localhost:${PORT}`, + reuseExistingServer: !process.env.CI, + timeout: 120_000, + }, +}); diff --git a/web-ide/scripts/bundle-skill.mjs b/web-ide/scripts/bundle-skill.mjs new file mode 100644 index 0000000..2f3d8bc --- /dev/null +++ b/web-ide/scripts/bundle-skill.mjs @@ -0,0 +1,108 @@ +// Packs the authoring skill folder (.claude/skills/pseudocode) into a real, +// DEFLATE-compressed `.zip` served as a static asset, so the IDE's "Download +// skill" button is a plain link — no client-side zip code. Run with Bun +// (`npm run bundle:skill`), which supplies the compression; the resulting +// static/pseudocode-skill.zip is committed and refreshed when the skill changes. + +import { mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs"; +import { dirname, join, relative } from "node:path"; +import { fileURLToPath } from "node:url"; + +const here = dirname(fileURLToPath(import.meta.url)); +const skillDir = join(here, "../../.claude/skills/pseudocode"); +const rootName = "pseudocode"; // the folder name under .claude/skills/ +const outFile = join(here, "../static/pseudocode-skill.zip"); + +// IEEE CRC-32 — ZIP stores one per entry regardless of compression method. +const CRC_TABLE = Uint32Array.from({ length: 256 }, (_, n) => { + let c = n; + for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1; + return c >>> 0; +}); +function crc32(bytes) { + let c = 0xffffffff; + for (const b of bytes) c = CRC_TABLE[(c ^ b) & 0xff] ^ (c >>> 8); + return (c ^ 0xffffffff) >>> 0; +} + +function walk(dir) { + const out = []; + for (const name of readdirSync(dir).sort()) { + const full = join(dir, name); + if (statSync(full).isDirectory()) out.push(...walk(full)); + else out.push(full); + } + return out; +} + +const enc = new TextEncoder(); +const entry = (path, bytes) => { + const raw = new Uint8Array(bytes); + const deflated = Bun.deflateSync(raw, { raw: true }); // Bun supplies DEFLATE + return { name: enc.encode(path), raw, deflated, crc: crc32(raw) }; +}; + +const entries = walk(skillDir).map((full) => + entry(`${rootName}/${relative(skillDir, full).split(/[\\/]/).join("/")}`, readFileSync(full)), +); +// SKILL.md defers every syntax question to `references/LANG.md`; ship the +// canonical spec (the repo root LANG.md) at that path so the skill is +// self-contained once downloaded. +entries.push(entry(`${rootName}/references/LANG.md`, readFileSync(join(here, "../../LANG.md")))); + +const locals = []; +const central = []; +let offset = 0; +for (const e of entries) { + const local = new Uint8Array(30 + e.name.length); + const lv = new DataView(local.buffer); + lv.setUint32(0, 0x04034b50, true); + lv.setUint16(4, 20, true); // version needed + lv.setUint16(8, 8, true); // method: deflate + lv.setUint16(12, 0x21, true); // mod date 1980-01-01 + lv.setUint32(14, e.crc, true); + lv.setUint32(18, e.deflated.length, true); // compressed size + lv.setUint32(22, e.raw.length, true); // uncompressed size + lv.setUint16(26, e.name.length, true); + local.set(e.name, 30); + locals.push(local, e.deflated); + + const cd = new Uint8Array(46 + e.name.length); + const cv = new DataView(cd.buffer); + cv.setUint32(0, 0x02014b50, true); + cv.setUint16(4, 20, true); + cv.setUint16(6, 20, true); + cv.setUint16(10, 8, true); // method: deflate + cv.setUint16(14, 0x21, true); + cv.setUint32(16, e.crc, true); + cv.setUint32(20, e.deflated.length, true); + cv.setUint32(24, e.raw.length, true); + cv.setUint16(28, e.name.length, true); + cv.setUint32(42, offset, true); + cd.set(e.name, 46); + central.push(cd); + + offset += locals[locals.length - 2].length + e.deflated.length; +} + +const centralSize = central.reduce((n, c) => n + c.length, 0); +const end = new Uint8Array(22); +const ev = new DataView(end.buffer); +ev.setUint32(0, 0x06054b50, true); +ev.setUint16(8, entries.length, true); +ev.setUint16(10, entries.length, true); +ev.setUint32(12, centralSize, true); +ev.setUint32(16, offset, true); + +const parts = [...locals, ...central, end]; +const total = parts.reduce((n, p) => n + p.length, 0); +const zip = new Uint8Array(total); +let at = 0; +for (const p of parts) { + zip.set(p, at); + at += p.length; +} + +mkdirSync(dirname(outFile), { recursive: true }); +writeFileSync(outFile, zip); +console.log(`packed ${entries.length} skill file(s) → static/pseudocode-skill.zip (${zip.length} bytes)`); diff --git a/web-ide/scripts/icons.mjs b/web-ide/scripts/icons.mjs new file mode 100644 index 0000000..68e02bb --- /dev/null +++ b/web-ide/scripts/icons.mjs @@ -0,0 +1,47 @@ +// Generates the PWA / app icons from the brand mark (the nested-C4 logo in +// accent on the app's dark surface) into static/icons. Run `npm run icons` after +// changing the mark; the PNGs are committed so the build and CI need no image +// toolchain. Requires `sharp` (a devDependency). + +import { mkdirSync, writeFileSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; +import sharp from "sharp"; + +const here = dirname(fileURLToPath(import.meta.url)); +const outDir = join(here, "../static/icons"); +mkdirSync(outDir, { recursive: true }); + +const BG = "#0a0b0e"; // --bg (dark surface) +const ACCENT = "#ff5a36"; // --accent + +// The brand mark on a full-bleed background. `scale` is the mark's fraction of +// the 512 canvas — smaller for the maskable variant so it survives a circular +// mask's safe zone. The mark is authored in a 24-unit box (matching logo.svg). +function iconSvg(scale) { + const size = 512; + const box = size * scale; + const offset = (size - box) / 2; + const k = box / 24; + return ` + + + + + + +`; +} + +async function emit(svg, size, name) { + const png = await sharp(Buffer.from(svg)).resize(size, size).png().toBuffer(); + writeFileSync(join(outDir, name), png); + console.log(` ${name} (${size}×${size}, ${png.length} bytes)`); +} + +// "any" icons fill the tile; the maskable leaves a safe margin for OS masking. +await emit(iconSvg(0.72), 192, "icon-192.png"); +await emit(iconSvg(0.72), 512, "icon-512.png"); +await emit(iconSvg(0.56), 512, "icon-maskable-512.png"); +await emit(iconSvg(0.72), 180, "apple-touch-icon.png"); +console.log("icons → static/icons"); diff --git a/web-ide/src/app.css b/web-ide/src/app.css index cf3e903..016345e 100644 --- a/web-ide/src/app.css +++ b/web-ide/src/app.css @@ -1,11 +1,53 @@ -/* Svelte Flow base styles first, so the dark `.svelte-flow` overrides further - * down win the cascade (importing it inside the diagram components injects it - * after this sheet and leaves the pane white). */ +@import "tailwindcss"; +@import "tw-animate-css"; +/* Svelte Flow base styles, so the dark `.svelte-flow` overrides further down win + * the cascade (importing it inside the diagram components injects it after this + * sheet and leaves the pane white). Tailwind's layers sit below the unlayered + * hand-written styles below, so existing UI keeps winning — only shadcn-svelte + * components (utility classes) draw from Tailwind. */ @import "@xyflow/svelte/dist/style.css"; +/* `dark:` keys off the project's `data-theme` (set pre-paint in app.html), not a + * `.dark` class. Most shadcn components theme via the semantic tokens below and + * never need this; it's here for completeness. */ +@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *)); + +/* Map shadcn-svelte's semantic tokens onto the existing design tokens, so its + * components inherit our colours and stay theme-aware automatically — the + * underlying --bg/--ink/--accent vars are re-pointed per [data-theme]. Brand + * accent → `primary`; shadcn's muted `accent` surface → `--surface-3`. Fonts + * already share Tailwind's `--font-sans`/`--font-mono` names. Shapes follow + * shadcn's radius scale, derived from --radius. */ +@theme inline { + --color-background: var(--bg); + --color-foreground: var(--ink); + --color-card: var(--surface); + --color-card-foreground: var(--ink); + --color-popover: var(--surface-2); + --color-popover-foreground: var(--ink); + --color-primary: var(--accent); + --color-primary-foreground: var(--accent-ink); + --color-secondary: var(--surface-3); + --color-secondary-foreground: var(--ink); + --color-muted: var(--surface-2); + --color-muted-foreground: var(--ink-soft); + --color-accent: var(--surface-3); + --color-accent-foreground: var(--ink); + --color-destructive: var(--err); + --color-destructive-foreground: var(--accent-ink); + --color-border: var(--line); + --color-input: var(--line-strong); + --color-ring: var(--accent); + + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); +} + /* PseudoScript Web IDE — "Drafting Terminal". * - * Ink-black canvas under a blueprint grid and a vermilion horizon glow. + * Ink-black canvas under a blueprint grid. * Hairline-framed panes, drafting corner ticks, one hot accent, mono-forward * uppercase micro-labels. Diagrams render on a dark interactive canvas. One * staggered reveal on load; everything else is restrained and precise. @@ -42,7 +84,11 @@ /* atmosphere */ --grid: rgba(255, 255, 255, 0.022); - --glow: radial-gradient(1100px 560px at 88% -12%, color-mix(in srgb, var(--accent) 12%, transparent), transparent 70%); + + /* one opaque surface for every docked island (explorer / centre / structure / + problems dock). Solid, not translucent — the old low-opacity mix only existed + to let the (now removed) backdrop glow bleed through. */ + --island-bg: var(--surface); /* kind palette (shared with the diagrams) */ --k-person: #6e8bff; @@ -61,10 +107,17 @@ --font-sans: "Hanken Grotesk", ui-sans-serif, system-ui, sans-serif; --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace; - --topbar-h: 60px; - --status-h: 30px; + /* top header bar; matches the 42px nav-rail width so the corners stay square */ + --topbar-h: 42px; + --status-h: 24px; + /* compact ("mira") chrome height for the island bars (content / tabs / panel heads) */ + --bar-h: 38px; + --activity-w: 42px; + --right-rail-w: 42px; --radius: 10px; --radius-sm: 7px; + /* the gutter between the Fleet-style islands */ + --island-gap: 5px; /* spacing scale (4px base) */ --space-1: 0.25rem; @@ -89,22 +142,42 @@ --shadow-md: 0 10px 30px -10px rgba(0, 0, 0, 0.6); --shadow-lg: 0 24px 60px -18px rgba(0, 0, 0, 0.7); + /* editor syntax highlight — one token per LSP semantic role (dark) */ + --hl-keyword: var(--accent); + --hl-namespace: #2dd4bf; + --hl-type: #5eead4; + --hl-class: #b87bf5; + --hl-parameter: #e0a93f; + --hl-variable: var(--ink); + --hl-property: #dcc98a; + --hl-enum: #6e8bff; + --hl-method: #f472b6; + --hl-comment: var(--ink-faint); + --hl-string: #7fd88f; + --hl-number: #e0a93f; + --hl-decorator: #ff7d5e; + color-scheme: dark; } -/* Light theme — the same token names re-pointed for a paper-pale drafting sheet. - The interactive diagram canvas keeps its own `--sheet`/`--bg` warmth so it - stays legible in both modes. */ +/* Light theme — the same token names re-pointed for a cool silver drafting sheet. + Neutrals are tinted blue (B ≥ G ≥ R) rather than cream so the surface reads + like brushed metal, not aged paper. */ :root[data-theme="light"] { - --bg: #f3f1ec; + --bg: #e7eaef; --surface: #ffffff; - --surface-2: #f4f2ed; - --surface-3: #e8e5dd; + --surface-2: #f4f6f9; + --surface-3: #e3e7ee; --ink: #1a1b20; --ink-soft: #4c4e57; - --ink-faint: #8a8c95; - --line: #e3e0d8; - --line-strong: #cfccc2; + --ink-faint: #888c95; + --line: #dde0e7; + --line-strong: #c6cad3; + + /* canvas sheet — silver in light mode (dark mode keeps its warm sheet) */ + --sheet: #f1f3f6; + --sheet-ink: #3a3c42; + --sheet-grid: rgba(40, 44, 58, 0.07); --accent: #e8401c; --accent-hi: #ff5a36; @@ -116,7 +189,6 @@ --err: #d63a32; --grid: rgba(20, 20, 30, 0.04); - --glow: radial-gradient(1100px 560px at 88% -12%, color-mix(in srgb, var(--accent) 9%, transparent), transparent 70%); --k-person: #3f5bd6; --k-system: #d6492f; @@ -129,6 +201,21 @@ --shadow-md: 0 10px 28px -12px rgba(20, 20, 30, 0.22); --shadow-lg: 0 22px 54px -20px rgba(20, 20, 30, 0.28); + /* editor syntax highlight (light) — darker, saturated for contrast on paper */ + --hl-keyword: var(--accent); + --hl-namespace: #0f766e; + --hl-type: #0d7a70; + --hl-class: #7c3aed; + --hl-parameter: #9a5b00; + --hl-variable: var(--ink); + --hl-property: #8a5a00; + --hl-enum: #2747c0; + --hl-method: #b3246b; + --hl-comment: var(--ink-faint); + --hl-string: #1d7a3a; + --hl-number: #9a5b00; + --hl-decorator: #c0392b; + color-scheme: light; } @@ -136,13 +223,18 @@ html, body { height: 100%; margin: 0; } +/* Fleet-style island: a rounded, hairline-framed surface that floats on the app + backdrop. Shared by the activity rail, explorer, centre, and structure panels; + the gaps between them come from the .body grid gutter. */ +.island { + border: 1px solid var(--line); + border-radius: var(--radius); + overflow: hidden; +} + body { color: var(--ink); background-color: var(--bg); - /* vermilion glow over a flat surface */ - background-image: var(--glow); - background-size: 100% 100%; - background-attachment: fixed; font-family: var(--font-sans); font-size: 15px; line-height: 1.6; @@ -151,6 +243,13 @@ body { text-rendering: optimizeLegibility; } +/* while a gutter splitter is dragged: force the resize cursor everywhere and + stop text selection from fighting the drag. */ +body.resizing { + cursor: col-resize; + user-select: none; +} + /* a whisper of grain over everything for tactile depth */ body::after { content: ""; @@ -208,7 +307,11 @@ button { font: inherit; cursor: pointer; color: inherit; } (a `.svelte-flow.svelte-xxxx` rule, higher specificity than a bare class); the dark `.stage` then shows through. */ background: transparent !important; - --xy-background-color-default: transparent; + /* Paint the pane with the island surface. Set the non-`-default` var: the pane + reads `var(--xy-background-color, var(--xy-background-color-default))`, so this + wins over Svelte Flow's `.svelte-flow.dark` default (#141414) without a + specificity fight. */ + --xy-background-color: var(--island-bg); --xy-edge-stroke-default: var(--line-strong); --xy-edge-stroke-selected-default: var(--accent); --xy-edge-label-color-default: var(--ink-soft); @@ -246,7 +349,7 @@ button { font: inherit; cursor: pointer; color: inherit; } border: 1px solid var(--line-strong); border-left: 3px solid var(--k, var(--ink-faint)); border-radius: var(--radius-sm); - box-shadow: 0 8px 20px -12px rgba(0, 0, 0, 0.8); + box-shadow: var(--shadow-sm); text-align: left; } .svelte-flow__node.c4-node.person { --k: var(--k-person); } @@ -297,20 +400,18 @@ button { font: inherit; cursor: pointer; color: inherit; } } .cm-nav-flash { animation: pds-nav-flash 1.3s ease-out forwards; } -/* Editor hover card: symbol info + its compiler-rendered diagram. The tooltip - wrapper CodeMirror injects (.cm-tooltip) is reset so the card paints itself. - CodeMirror dismisses a hover tooltip the moment the pointer leaves the symbol - range unless it stays within ~4px of the card's box, so crossing the gap to - the card dismisses it. The transparent vertical padding extends that hit box - up to the symbol (and below, when the card flips above); the equal negative - margin keeps the visible card where CodeMirror placed it. */ +/* Editor hover card: symbol info + actions. The tooltip wrapper CodeMirror + injects (.cm-tooltip) is reset so the card paints itself. The wrapper is + pointer-transparent so it never steals a click or double-click from the + editor text beneath it (the card itself re-enables pointer events, so its + buttons stay clickable and hovering it keeps the tooltip open). */ .cm-tooltip:has(.pds-hover) { border: none; background: transparent; - padding: 16px 0; - margin: -16px 0; + pointer-events: none; } .pds-hover { + pointer-events: auto; width: 360px; max-width: 80vw; padding: 0.7rem 0.8rem; @@ -357,29 +458,6 @@ button { font: inherit; cursor: pointer; color: inherit; } height: auto; max-height: 200px; } -.pds-hover .ph-actions { - display: flex; - flex-wrap: wrap; - gap: 0.3rem; - margin-top: 0.55rem; -} -.pds-hover .ph-actions button { - flex: none; - background: var(--surface-2); - border: 1px solid var(--line-strong); - border-radius: var(--radius-sm); - color: var(--ink-soft); - font-family: var(--font-mono); - font-size: 0.58rem; - letter-spacing: 0.03em; - padding: 0.18rem 0.4rem; - cursor: pointer; -} -.pds-hover .ph-actions button:hover { - border-color: var(--accent); - color: var(--ink); -} - /* Markdown live-preview (`.cm-md-live`): render prose in the readable grotesk sans rather than the `.pds` monospace, headings in the display grotesk, and keep only code in mono. The `.cm-editor.cm-md-live` selector outranks diff --git a/web-ide/src/app.html b/web-ide/src/app.html index d3bb313..bf30eec 100644 --- a/web-ide/src/app.html +++ b/web-ide/src/app.html @@ -6,6 +6,13 @@ + + + + + + + @@ -19,6 +26,9 @@ var dark = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; var resolved = p === "light" || p === "dark" ? p : dark ? "dark" : "light"; document.documentElement.setAttribute("data-theme", resolved); + // Match the address-bar / PWA theme-color to --bg before first paint. + var m = document.querySelector('meta[name="theme-color"]'); + if (m) m.setAttribute("content", resolved === "light" ? "#e7eaef" : "#0a0b0e"); } catch (e) { document.documentElement.setAttribute("data-theme", "dark"); } diff --git a/web-ide/src/lib/blocks.js b/web-ide/src/lib/blocks.js deleted file mode 100644 index 83165c4..0000000 --- a/web-ide/src/lib/blocks.js +++ /dev/null @@ -1,37 +0,0 @@ -// Brace-matched `{ … }` block extents for a PseudoScript source, used by the -// editor for folding and the navigation flash. A char-level scan that skips -// string literals and `//`/`///`/`//!` line comments, so braces inside them -// don't open or close a block. PseudoScript has no block comments and no -// multi-line strings, which keeps this exact. - -/** - * The matched brace pairs in `text`, innermost-last (a pair is pushed when its - * `}` is seen). Each entry is `{ open, close }` — the code-unit offsets of the - * `{` and its matching `}`. - * @param {string} text - * @returns {{ open: number, close: number }[]} - */ -export function blockRanges(text) { - const ranges = []; - const stack = []; - let inString = false; - for (let i = 0; i < text.length; i++) { - const c = text[i]; - if (inString) { - if (c === "\\") i++; // skip the escaped char - else if (c === '"') inString = false; - continue; - } - if (c === '"') inString = true; - else if (c === "/" && text[i + 1] === "/") { - const nl = text.indexOf("\n", i); - if (nl === -1) break; - i = nl; // resume at the newline - } else if (c === "{") stack.push(i); - else if (c === "}") { - const open = stack.pop(); - if (open !== undefined) ranges.push({ open, close: i }); - } - } - return ranges; -} diff --git a/web-ide/src/lib/codec.js b/web-ide/src/lib/codec.ts similarity index 68% rename from web-ide/src/lib/codec.js rename to web-ide/src/lib/codec.ts index 9f407bf..85d8197 100644 --- a/web-ide/src/lib/codec.js +++ b/web-ide/src/lib/codec.ts @@ -9,11 +9,54 @@ // docs: [{ path, content }] } // which is exactly what `mountWorkspace` consumes after `loadSample`. +/** A single source module within a workspace envelope. */ +export interface EnvelopeFile { + path: string; + fqn: string; + source: string; +} + +/** A single doc page within a workspace envelope. */ +export interface EnvelopeDoc { + path: string; + content: string; +} + +/** The versioned, serialisable envelope written to the hash/`.pdsx` file. */ +export interface Envelope { + magic: string; + v: number; + name: string; + manifestToml: string | null; + files: EnvelopeFile[]; + docs: EnvelopeDoc[]; +} + +/** The live workspace snapshot the IDE feeds into the codec. */ +export interface WorkspaceState { + name?: string | null; + manifestToml?: string | null; + files?: EnvelopeFile[] | null; + docs?: EnvelopeDoc[] | null; +} + +/** The in-memory workspace shape (`{ workspace, landing }`) `mountWorkspace` + * consumes — identical to what `loadSample` returns. */ +export interface MountableWorkspace { + workspace: { + name: string; + files: EnvelopeFile[]; + manifestToml: string | null; + docs: Record; + }; + landing: string | null; +} + const ENVELOPE_VERSION = 1; const MAGIC = "pdsx"; // leading tag so a wrong file fails fast with a clear error /** Build the versioned envelope from the IDE's live workspace state. */ -export function buildEnvelope({ name, manifestToml, files, docs }) { +export function buildEnvelope({ name, manifestToml, files, docs }: WorkspaceState): Envelope { return { magic: MAGIC, v: ENVELOPE_VERSION, @@ -26,8 +69,8 @@ export function buildEnvelope({ name, manifestToml, files, docs }) { /** Restore the in-memory workspace shape (`{ workspace, landing }`) from an * envelope — the same shape `loadSample` returns, so mounting is identical. */ -export function envelopeToWorkspace(env) { - const docs = {}; +export function envelopeToWorkspace(env: Envelope): MountableWorkspace { + const docs: Record = {}; for (const d of env.docs ?? []) docs[d.path] = d.content; return { workspace: { @@ -44,29 +87,29 @@ export function envelopeToWorkspace(env) { // ---- gzip via CompressionStream ------------------------------------------- -async function gzip(bytes) { +async function gzip(bytes: Uint8Array): Promise { const stream = new Blob([bytes]).stream().pipeThrough(new CompressionStream("gzip")); return new Uint8Array(await new Response(stream).arrayBuffer()); } -async function gunzip(bytes) { +async function gunzip(bytes: Uint8Array): Promise { const stream = new Blob([bytes]).stream().pipeThrough(new DecompressionStream("gzip")); return new Uint8Array(await new Response(stream).arrayBuffer()); } /** Encode a workspace state object to gzipped envelope bytes. */ -export async function encodeWorkspace(state) { +export async function encodeWorkspace(state: WorkspaceState): Promise { const json = JSON.stringify(buildEnvelope(state)); return gzip(new TextEncoder().encode(json)); } /** Decode gzipped envelope bytes back to `{ workspace, landing }`. Throws on a * corrupt stream or a wrong/unsupported envelope. */ -export async function decodeWorkspace(bytes) { - let env; +export async function decodeWorkspace(bytes: Uint8Array): Promise { + let env: Envelope; try { const json = new TextDecoder().decode(await gunzip(bytes)); - env = JSON.parse(json); + env = JSON.parse(json) as Envelope; } catch { throw new Error("Not a valid PseudoScript workspace (corrupt or wrong format)."); } @@ -78,7 +121,7 @@ export async function decodeWorkspace(bytes) { // ---- base64url (for the URL hash, T6) ------------------------------------- /** Bytes → URL-safe base64 (no padding), chunked to avoid call-stack limits. */ -export function bytesToBase64Url(bytes) { +export function bytesToBase64Url(bytes: Uint8Array): string { let bin = ""; const CHUNK = 0x8000; for (let i = 0; i < bytes.length; i += CHUNK) { @@ -88,7 +131,7 @@ export function bytesToBase64Url(bytes) { } /** URL-safe base64 → bytes. */ -export function base64UrlToBytes(text) { +export function base64UrlToBytes(text: string): Uint8Array { const b64 = text.replace(/-/g, "+").replace(/_/g, "/"); const bin = atob(b64); const bytes = new Uint8Array(bin.length); diff --git a/web-ide/src/lib/components/BoundaryNode.svelte b/web-ide/src/lib/components/BoundaryNode.svelte index bb6be1b..305d61e 100644 --- a/web-ide/src/lib/components/BoundaryNode.svelte +++ b/web-ide/src/lib/components/BoundaryNode.svelte @@ -1,10 +1,19 @@ - diff --git a/web-ide/src/lib/components/BuildNoticeDialog.svelte b/web-ide/src/lib/components/BuildNoticeDialog.svelte new file mode 100644 index 0000000..d208b1a --- /dev/null +++ b/web-ide/src/lib/components/BuildNoticeDialog.svelte @@ -0,0 +1,69 @@ + + + + + + Build the example as a preview? + +
                      +

                      + You're working in the bundled example, which lives in memory — there's no folder to write to. + Building it opens a read-only preview in a new tab, and the interactive diagrams don't load there. +

                      +

                      + To build a real, on-disk site like the pds doc CLI — written under target/doc/, + with the diagrams hydrated — open a folder as your workspace first. +

                      +
                      + + + {#if onopenfolder} + + {/if} + + +
                      +
                      + + diff --git a/web-ide/src/lib/components/C4Flow.svelte b/web-ide/src/lib/components/C4Flow.svelte index 7581688..37c6f9b 100644 --- a/web-ide/src/lib/components/C4Flow.svelte +++ b/web-ide/src/lib/components/C4Flow.svelte @@ -1,23 +1,85 @@ - -
                      +
                      + + - {#if picked} - - + +
                      + + +
                      + + {#if menu} + {@const m = menu} + {/if}
                      diff --git a/web-ide/src/lib/components/C4Node.svelte b/web-ide/src/lib/components/C4Node.svelte index 218f5e2..eb3695b 100644 --- a/web-ide/src/lib/components/C4Node.svelte +++ b/web-ide/src/lib/components/C4Node.svelte @@ -1,4 +1,4 @@ - diff --git a/web-ide/src/lib/components/CanvasMenu.svelte b/web-ide/src/lib/components/CanvasMenu.svelte new file mode 100644 index 0000000..8ee8005 --- /dev/null +++ b/web-ide/src/lib/components/CanvasMenu.svelte @@ -0,0 +1,184 @@ + + + e.key === "Escape" && onclose()} /> + +
                      + + + +
                      + + diff --git a/web-ide/src/lib/components/CanvasSettings.svelte b/web-ide/src/lib/components/CanvasSettings.svelte new file mode 100644 index 0000000..dbdd364 --- /dev/null +++ b/web-ide/src/lib/components/CanvasSettings.svelte @@ -0,0 +1,127 @@ + + + +{#snippet row(id: string, label: string, value: string, options: readonly { id: string; label: string }[], onpick: (v: string) => void, disabled = false)} +
                      + + +
                      +{/snippet} + + + + + + + Customise diagram + Layout and edges. Saved across sessions. + + +
                      + {@render row("cs-algo", "Algorithm", canvasPrefs.algorithm, ALGORITHMS, (v) => canvasPrefs.setAlgorithm(v as LayoutAlgo))} + {@render row("cs-dir", "Direction", canvasPrefs.layout, LAYOUTS, (v) => canvasPrefs.setLayout(v as LayoutDir), !directional)} + {@render row("cs-edge", "Lines", canvasPrefs.edge, EDGE_STYLES, (v) => canvasPrefs.setEdge(v as EdgeStyle))} +
                      +
                      +
                      + + diff --git a/web-ide/src/lib/components/ConfirmDialog.svelte b/web-ide/src/lib/components/ConfirmDialog.svelte new file mode 100644 index 0000000..61f6414 --- /dev/null +++ b/web-ide/src/lib/components/ConfirmDialog.svelte @@ -0,0 +1,36 @@ + + + + + + {title} + {message} + + + + + + + diff --git a/web-ide/src/lib/components/DiagramExport.svelte b/web-ide/src/lib/components/DiagramExport.svelte new file mode 100644 index 0000000..e636787 --- /dev/null +++ b/web-ide/src/lib/components/DiagramExport.svelte @@ -0,0 +1,80 @@ + + + + + + + run("png")}>PNG image + run("svg")}>SVG image + + + + diff --git a/web-ide/src/lib/components/DiagramPane.svelte b/web-ide/src/lib/components/DiagramPane.svelte index 42f1f54..9f44ee1 100644 --- a/web-ide/src/lib/components/DiagramPane.svelte +++ b/web-ide/src/lib/components/DiagramPane.svelte @@ -1,4 +1,4 @@ - - usagesMenu && e.key === "Escape" && closeUsagesMenu()} /> + { + if (e.key !== "Escape") return; + if (editorMenu) closeEditorMenu(); + else if (usagesMenu) closeUsagesMenu(); + }} +/>
                      +{#if editorMenu} + {@const m = editorMenu} +
                      + + +
                      +{/if} + {#if usagesMenu}
                      @@ -705,6 +1004,56 @@ overflow: hidden; } + /* right-click context menu, anchored at the pointer */ + .cm-ctx-scrim { + position: fixed; + inset: 0; + z-index: 42; + background: transparent; + border: none; + cursor: default; + } + .cm-ctx { + position: fixed; + z-index: 43; + min-width: 12rem; + padding: 0.3rem; + background: var(--surface); + border: 1px solid var(--line-strong); + border-radius: var(--radius); + box-shadow: var(--shadow-lg); + outline: none; + } + .cm-ctx-item { + display: block; + width: 100%; + padding: 0.4rem 0.5rem; + background: transparent; + border: 0; + border-radius: var(--radius-sm); + text-align: left; + font-family: var(--font-sans); + font-size: 0.8rem; + color: var(--ink-soft); + cursor: pointer; + } + .cm-ctx-item:hover:not(:disabled), + .cm-ctx-item:focus-visible:not(:disabled) { + background: var(--surface-2); + color: var(--ink); + outline: none; + } + .cm-ctx-item:disabled { + color: var(--ink-faint); + opacity: 0.45; + cursor: default; + } + .cm-ctx-sep { + height: 1px; + margin: 0.2rem 0.2rem; + background: var(--line); + } + /* find-usages dropdown, anchored under the declaration */ .um-scrim { position: fixed; diff --git a/web-ide/src/lib/components/FileTree.stories.ts b/web-ide/src/lib/components/FileTree.stories.ts new file mode 100644 index 0000000..e4ce509 --- /dev/null +++ b/web-ide/src/lib/components/FileTree.stories.ts @@ -0,0 +1,48 @@ +import type { Meta, StoryObj } from "@storybook/svelte"; + +import FileTree from "./FileTree.svelte"; + +// A unified file-tree entry — module / doc / manifest, addressed in tests by +// `data-testid="file-"`. +interface FileEntry { + key: string; + kind: "module" | "doc" | "manifest"; + relPath: string; + label: string; + fqn?: string; +} + +const meta: Meta = { + title: "IDE/FileTree", + component: FileTree, + tags: ["autodocs"], +}; + +export default meta; + +type Story = StoryObj; + +const entries: FileEntry[] = [ + { key: "orders", kind: "module", relPath: "orders.pds", label: "orders", fqn: "orders" }, + { key: "shared", kind: "module", relPath: "banking/shared.pds", label: "shared", fqn: "shared" }, + { key: "gateway", kind: "module", relPath: "banking/gateway.pds", label: "gateway", fqn: "gateway" }, + { key: "docs/intro.md", kind: "doc", relPath: "docs/intro.md", label: "Intro" }, + { key: "pds.toml", kind: "manifest", relPath: "pds.toml", label: "pds.toml" }, +]; + +export const Workspace: Story = { + args: { entries, openKey: "orders" }, +}; + +export const WithUnsavedAndError: Story = { + args: { + entries, + openKey: "orders", + dirtyKeys: new Set(["shared"]), + errorKeys: new Set(["gateway"]), + }, +}; + +export const Empty: Story = { + args: { entries: [] }, +}; diff --git a/web-ide/src/lib/components/FileTree.svelte b/web-ide/src/lib/components/FileTree.svelte index 8ca72bb..34bf8a9 100644 --- a/web-ide/src/lib/components/FileTree.svelte +++ b/web-ide/src/lib/components/FileTree.svelte @@ -1,534 +1,309 @@ - - {#if manifestPath} -
                      -
                      Manifest
                      -
                        -
                      • +{#snippet row(node: TreeNode, depth: number)} + {#if node.entry} + {@const e = node.entry} + {@const Icon = iconFor(e)} +
                      • + + -
                      • -
                      -
                      - {/if} - -
                      -
                      - Files - {files.length} - {#if oncreatefile} - - {/if} -
                      - {#if files.length === 0} -
                      No .pds modules here.
                      - {:else} - {#each fileGroups as fgroup} - {#if fgroup.dir} -
                      { - if (dragFile) { - e.preventDefault(); - dropDir = fgroup.dir; + + + onopen?.(e)}>Open + {#if e.kind === "module"} + {#if onrenamefile} onrenamefile?.(e.fqn!)}>Rename…{/if} + {#if oncreatefile} oncreatefile?.()}>New file…{/if} + {#if ondeletefile} + + ondeletefile?.(e.fqn!)}>Delete + {/if} + {/if} + + + + {:else} + {@const open = !collapsed.has(node.path)} +
                    • + + +
                    • - {/if} -
                        { - if (dragFile) { - e.preventDefault(); - dropDir = fgroup.dir; - } - }} - ondrop={(e) => { - e.preventDefault(); - onDrop(fgroup.dir); - }} - > - {#each fgroup.items as file} -
                      • -
                        - - {#if onrenamefile || ondeletefile} - - {#if onrenamefile} - - {/if} - {#if ondeletefile} - - {/if} - - {/if} -
                        -
                      • - {/each} + > +
                      - -
                      -
                      Symbols{symbols.length}
                      - {#if tree.roots.length === 0} -
                      No nodes declared yet.
                      - {:else} -
                        - {#each tree.roots as node}{@render row(node, 0, tree.children)}{/each} -
                      - {/if} -
                      - - -{#snippet row(node, depth, children)} - {@const kids = children.get(node.fqn) ?? []} - {@const Icon = ICONS[node.kind] ?? Box} - {@const open = !collapsed.has(node.fqn)} -
                    • -
                      - - -
                      - {#if open && kids.length} -
                        - {#each kids as kid}{@render row(kid, depth + 1, children)}{/each} -
                      - {/if} -
                    • + {/if} + + {/if} {/snippet} diff --git a/web-ide/src/lib/components/FileTree.test.ts b/web-ide/src/lib/components/FileTree.test.ts new file mode 100644 index 0000000..d84d0c4 --- /dev/null +++ b/web-ide/src/lib/components/FileTree.test.ts @@ -0,0 +1,68 @@ +import type { ComponentProps } from "svelte"; + +import { render, screen } from "@testing-library/svelte"; +import userEvent from "@testing-library/user-event"; +import { describe, expect, it, vi } from "vitest"; + +// Pull in the jest-dom matcher type augmentation (toBeInTheDocument, +// toHaveAttribute, …); the runtime registration lives in vitest-setup.js. +import "@testing-library/jest-dom/vitest"; + +import FileTree from "./FileTree.svelte"; + +// A unified file-tree entry — module / doc / manifest. +interface FileEntry { + key: string; + kind: "module" | "doc" | "manifest" | "other"; + relPath: string; + label: string; + fqn?: string; + binary?: boolean; +} + +// FileTree declares every action callback as an optional prop, but Svelte's +// generated props type marks them required. Tests only pass the few props a +// case needs, so render through a partial-props wrapper. +type FileTreeProps = ComponentProps; + +function renderTree(props: Partial): void { + render(FileTree, { props: props as FileTreeProps }); +} + +const entries: FileEntry[] = [ + { key: "orders", kind: "module", relPath: "orders.pds", label: "orders", fqn: "orders" }, + { key: "shared", kind: "module", relPath: "banking/shared.pds", label: "shared", fqn: "shared" }, + { key: "docs/intro.md", kind: "doc", relPath: "docs/intro.md", label: "Intro" }, +]; + +// The file tree is the entry point every e2e flow drives, so its module rows must +// be addressable by a stable `data-testid` (file-), never by label text. +describe("FileTree", () => { + it("renders a stable data-testid per module", () => { + renderTree({ entries }); + expect(screen.getByTestId("file-orders")).toBeInTheDocument(); + expect(screen.getByTestId("file-shared")).toBeInTheDocument(); + }); + + it("shows the file name as the row label and nests by directory", () => { + renderTree({ entries }); + expect(screen.getByTestId("file-shared")).toHaveTextContent("shared.pds"); + // a directory folder is rendered for the nested module + the docs + expect(screen.getByText("banking")).toBeInTheDocument(); + expect(screen.getByText("docs")).toBeInTheDocument(); + }); + + it("calls onopen with the entry when a row is clicked", async () => { + const onopen = vi.fn<(e: FileEntry) => void>(); + renderTree({ entries, onopen }); + await userEvent.click(screen.getByTestId("file-orders")); + expect(onopen).toHaveBeenCalledTimes(1); + expect(onopen).toHaveBeenCalledWith(entries[0]); + }); + + it("marks the open file with aria-current via openKey", () => { + renderTree({ entries, openKey: "orders" }); + expect(screen.getByTestId("file-orders")).toHaveAttribute("aria-current", "true"); + expect(screen.getByTestId("file-shared")).not.toHaveAttribute("aria-current"); + }); +}); diff --git a/web-ide/src/lib/components/FitView.svelte b/web-ide/src/lib/components/FitView.svelte new file mode 100644 index 0000000..6273145 --- /dev/null +++ b/web-ide/src/lib/components/FitView.svelte @@ -0,0 +1,25 @@ + diff --git a/web-ide/src/lib/components/FloatingEdge.svelte b/web-ide/src/lib/components/FloatingEdge.svelte new file mode 100644 index 0000000..6d615fd --- /dev/null +++ b/web-ide/src/lib/components/FloatingEdge.svelte @@ -0,0 +1,43 @@ + + +{#if geom} + +{/if} diff --git a/web-ide/src/lib/components/FlowTimeline.svelte b/web-ide/src/lib/components/FlowTimeline.svelte index a319780..d563545 100644 --- a/web-ide/src/lib/components/FlowTimeline.svelte +++ b/web-ide/src/lib/components/FlowTimeline.svelte @@ -1,4 +1,4 @@ - + + + + + diff --git a/web-ide/src/lib/components/Notifications.svelte b/web-ide/src/lib/components/Notifications.svelte index 782de28..ea682ee 100644 --- a/web-ide/src/lib/components/Notifications.svelte +++ b/web-ide/src/lib/components/Notifications.svelte @@ -1,10 +1,24 @@ -
                      @@ -23,11 +37,11 @@ diff --git a/web-ide/src/lib/components/ProblemsPane.svelte b/web-ide/src/lib/components/ProblemsPane.svelte index 2dfb6a9..3b6a435 100644 --- a/web-ide/src/lib/components/ProblemsPane.svelte +++ b/web-ide/src/lib/components/ProblemsPane.svelte @@ -1,5 +1,29 @@ -
                      @@ -8,21 +32,43 @@ No problems — the model is well-formed.
                      {:else} +
                      + {diagnostics.length} problem{diagnostics.length === 1 ? "" : "s"} + +
                        {#each diagnostics as d}
                      • - +
                        + + +
                      • {/each}
                      @@ -51,27 +97,71 @@ background: var(--ok); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ok) 18%, transparent); } + .bar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.6rem; + padding: 0.4rem 1.1rem; + border-bottom: 1px solid var(--line); + background: var(--surface-2); + } + .count { + font-family: var(--font-mono); + font-size: 0.7rem; + color: var(--ink-soft); + } + .copy-all { + display: inline-flex; + align-items: center; + gap: 0.35rem; + padding: 0.18rem 0.5rem; + border: 1px solid var(--line-strong); + border-radius: var(--radius-sm); + background: var(--surface); + color: var(--ink-soft); + font: inherit; + font-size: 0.7rem; + cursor: pointer; + } + .copy-all:hover { color: var(--ink); background: color-mix(in srgb, var(--accent) 8%, transparent); } ul { list-style: none; margin: 0; padding: 0; } li { border-bottom: 1px solid var(--line); } li.error { border-left: 2px solid var(--err); } li.warning { border-left: 2px solid var(--warn); } li.info { border-left: 2px solid var(--line-strong); } - .row { + .row { display: flex; align-items: stretch; } + .row:hover { background: color-mix(in srgb, var(--accent) 6%, transparent); } + li.error .row:hover { background: color-mix(in srgb, var(--err) 8%, transparent); } + .nav { display: flex; align-items: baseline; gap: 0.6rem; - width: 100%; + flex: 1; + min-width: 0; text-align: left; background: transparent; border: none; - padding: 0.45rem 1.1rem; + padding: 0.45rem 0.6rem 0.45rem 1.1rem; color: inherit; font: inherit; font-size: 0.82rem; cursor: pointer; } - .row:hover { background: color-mix(in srgb, var(--accent) 6%, transparent); } - li.error .row:hover { background: color-mix(in srgb, var(--err) 8%, transparent); } + .copy-one { + flex: none; + display: flex; + align-items: center; + padding: 0 0.7rem; + background: transparent; + border: none; + color: var(--ink-faint); + cursor: pointer; + opacity: 0; + } + .row:hover .copy-one, + .copy-one:focus-visible { opacity: 1; } + .copy-one:hover { color: var(--accent); } .badge { flex: none; font-family: var(--font-mono); diff --git a/web-ide/src/lib/components/ProjectPanel.svelte b/web-ide/src/lib/components/ProjectPanel.svelte index 4307ee3..e5fc3db 100644 --- a/web-ide/src/lib/components/ProjectPanel.svelte +++ b/web-ide/src/lib/components/ProjectPanel.svelte @@ -1,21 +1,53 @@ -
                      diff --git a/web-ide/src/lib/components/PromptDialog.svelte b/web-ide/src/lib/components/PromptDialog.svelte index 212be2d..ef4653d 100644 --- a/web-ide/src/lib/components/PromptDialog.svelte +++ b/web-ide/src/lib/components/PromptDialog.svelte @@ -1,8 +1,26 @@ - - + {#if error} +

                      {error}

                      + {:else if hint} +

                      {hint}

                      + {/if} + + + + + + + diff --git a/web-ide/src/lib/components/RenameDialog.svelte b/web-ide/src/lib/components/RenameDialog.svelte new file mode 100644 index 0000000..3fdb759 --- /dev/null +++ b/web-ide/src/lib/components/RenameDialog.svelte @@ -0,0 +1,250 @@ + + + + + + Rename {symbol} + Review the {occurrences.length} occurrence{occurrences.length === 1 ? "" : "s"}; uncheck any to skip. + + +
                      { + e.preventDefault(); + apply(); + }} + > + + {#if !valid} +

                      Not a valid identifier.

                      + {/if} + +
                      + +
                      + +
                      + {#each groups as group (group.fqn)} +
                      +
                      {group.fqn}
                      + {#each group.items as occ (keyOf(occ))} + + {/each} +
                      + {/each} +
                      + + + + + +
                      +
                      +
                      + + diff --git a/web-ide/src/lib/components/SequenceFragment.svelte b/web-ide/src/lib/components/SequenceFragment.svelte index 8ef4b94..3f55653 100644 --- a/web-ide/src/lib/components/SequenceFragment.svelte +++ b/web-ide/src/lib/components/SequenceFragment.svelte @@ -1,9 +1,16 @@ -
                      diff --git a/web-ide/src/lib/components/SequenceLifeline.svelte b/web-ide/src/lib/components/SequenceLifeline.svelte index b78fffe..7cfc10b 100644 --- a/web-ide/src/lib/components/SequenceLifeline.svelte +++ b/web-ide/src/lib/components/SequenceLifeline.svelte @@ -1,9 +1,43 @@ - @@ -45,11 +78,9 @@ class="seq-card c4-node {cardKind}" class:interactive style="left:{p.card.x}px; top:{p.card.y}px; width:{p.card.w}px; height:{p.card.h}px" - role={interactive ? "button" : undefined} - tabindex={interactive ? 0 : undefined} - onmouseenter={(e) => interactive && data.oninfo?.(p.id, e)} - onmouseleave={() => interactive && data.oninfoend?.()} - {onclick} + role="button" + tabindex="-1" + {oncontextmenu} > {kindLabel} {nameLabel} diff --git a/web-ide/src/lib/components/SequenceMessages.svelte b/web-ide/src/lib/components/SequenceMessages.svelte index ba79994..edaf18b 100644 --- a/web-ide/src/lib/components/SequenceMessages.svelte +++ b/web-ide/src/lib/components/SequenceMessages.svelte @@ -1,14 +1,49 @@ - - -
                      - - - PseudoScript - - - - -
                      - -

                      Hover a symbol for its diagram

                      - - - - - - - - - - {#if workspaceName} -
                      - {#if !canPersist} - session - {:else if saveState === "saving"} - saving… - {:else if saveState === "error"} - save failed - {:else if dirtyCount > 0} - {dirtyCount} unsaved - {:else} - saved - {/if} -
                      - {/if} - -
                      0} aria-live="polite"> - 0}> - {errorCount === 0 ? "no errors" : `${errorCount} error${errorCount === 1 ? "" : "s"}`} -
                      -
                      - - diff --git a/web-ide/src/lib/components/shell/ActivityBar.svelte b/web-ide/src/lib/components/shell/ActivityBar.svelte new file mode 100644 index 0000000..d3b9859 --- /dev/null +++ b/web-ide/src/lib/components/shell/ActivityBar.svelte @@ -0,0 +1,155 @@ + + + + + + +{#snippet item(Icon: ComponentType, label: string, onclick: () => void, on: boolean)} + + + + {label} + +{/snippet} + + diff --git a/web-ide/src/lib/components/shell/BottomDock.svelte b/web-ide/src/lib/components/shell/BottomDock.svelte new file mode 100644 index 0000000..cfbdb62 --- /dev/null +++ b/web-ide/src/lib/components/shell/BottomDock.svelte @@ -0,0 +1,79 @@ + + +
                      +
                      + Problems + {problems.length} + +
                      +
                      + +
                      +
                      + + diff --git a/web-ide/src/lib/components/shell/CommandPalette.svelte b/web-ide/src/lib/components/shell/CommandPalette.svelte new file mode 100644 index 0000000..365a5fb --- /dev/null +++ b/web-ide/src/lib/components/shell/CommandPalette.svelte @@ -0,0 +1,336 @@ + + + + +
                      +
                      + {#each TABS as t (t.id)} + + {/each} +
                      + + + {mode === "text" && q.trim().length < 2 ? "Type at least 2 characters." : "No matches."} + + {#if mode === "text"} + = MAX_TEXT ? "+" : ""} matches` : "Text"}> + {#each textMatches as m, i (m.fqn + ":" + m.line + ":" + i)} + pickText(m)}> + {m.fqn}:{m.line} + {m.text} + + {/each} + + {:else} + {#if fTypes.length} + = CAP ? `Types (${CAP}+)` : "Types"}> + {#each fTypes as s (s.fqn)} + pickSymbol(s.fqn)}> + {s.kind} + {s.name} + {s.fqn} + + {/each} + + {/if} + {#if fFiles.length} + = CAP ? `Files (${CAP}+)` : "Files"}> + {#each fFiles as f (f.fqn)} + pickFile(f)}> + {f.fqn} + + {/each} + + {/if} + {#if fSymbols.length} + = CAP ? `Symbols (${CAP}+)` : "Symbols"}> + {#each fSymbols as s (s.fqn)} + pickSymbol(s.fqn)}> + {s.kind} + {s.name} + {s.fqn} + + {/each} + + {/if} + {#if fActions.length} + + {#each fActions as a (a.id)} + pickAction(a)}> + {a.label} + {#if a.hint}{a.hint}{/if} + + {/each} + + {/if} + {/if} + +
                      +
                      + + diff --git a/web-ide/src/lib/components/shell/MenuBar.svelte b/web-ide/src/lib/components/shell/MenuBar.svelte new file mode 100644 index 0000000..5eafd25 --- /dev/null +++ b/web-ide/src/lib/components/shell/MenuBar.svelte @@ -0,0 +1,215 @@ + + + + + diff --git a/web-ide/src/lib/components/shell/RightRail.svelte b/web-ide/src/lib/components/shell/RightRail.svelte new file mode 100644 index 0000000..39047e9 --- /dev/null +++ b/web-ide/src/lib/components/shell/RightRail.svelte @@ -0,0 +1,73 @@ + + + + + + + diff --git a/web-ide/src/lib/components/shell/Splitter.svelte b/web-ide/src/lib/components/shell/Splitter.svelte new file mode 100644 index 0000000..d240d20 --- /dev/null +++ b/web-ide/src/lib/components/shell/Splitter.svelte @@ -0,0 +1,129 @@ + + + + + + diff --git a/web-ide/src/lib/components/shell/StatusBar.svelte b/web-ide/src/lib/components/shell/StatusBar.svelte new file mode 100644 index 0000000..e113dcb --- /dev/null +++ b/web-ide/src/lib/components/shell/StatusBar.svelte @@ -0,0 +1,28 @@ + + +
                      + {@render children?.()} +
                      + + diff --git a/web-ide/src/lib/components/shell/StructurePanel.svelte b/web-ide/src/lib/components/shell/StructurePanel.svelte new file mode 100644 index 0000000..e31beb0 --- /dev/null +++ b/web-ide/src/lib/components/shell/StructurePanel.svelte @@ -0,0 +1,114 @@ + + + + + diff --git a/web-ide/src/lib/components/shell/SymbolTree.svelte b/web-ide/src/lib/components/shell/SymbolTree.svelte new file mode 100644 index 0000000..485fd15 --- /dev/null +++ b/web-ide/src/lib/components/shell/SymbolTree.svelte @@ -0,0 +1,238 @@ + + +{#if tree.roots.length === 0} +
                      No nodes declared yet.
                      +{:else} +
                        + {#each tree.roots as node (node.fqn)}{@render row(node, 0, tree.children)}{/each} +
                      +{/if} + +{#snippet row(node: SymbolNode, depth: number, children: Map)} + {@const kids = children.get(node.fqn) ?? []} + {@const Icon = ICONS[node.kind] ?? Box} + {@const open = !collapsed.has(node.fqn)} +
                    • +
                      + + + + + + + onpicknode?.(node.fqn)}>Go to definition + {#if onreveal} onreveal?.(node.fqn)}>Reveal on canvas{/if} + + +
                      + {#if open && kids.length} +
                        + {#each kids as kid (kid.fqn)}{@render row(kid, depth + 1, children)}{/each} +
                      + {/if} +
                    • +{/snippet} + + diff --git a/web-ide/src/lib/components/shell/TabBar.svelte b/web-ide/src/lib/components/shell/TabBar.svelte new file mode 100644 index 0000000..b271009 --- /dev/null +++ b/web-ide/src/lib/components/shell/TabBar.svelte @@ -0,0 +1,133 @@ + + +
                      + {#each tabs as tab (tab.key)} + {@const Icon = ICON[tab.kind]} +
                      { + if (e.button === 1) { + e.preventDefault(); + onclose?.(tab.key); + } + }} + > + + +
                      + {/each} +
                      + + diff --git a/web-ide/src/lib/components/shell/TabBar.test.ts b/web-ide/src/lib/components/shell/TabBar.test.ts new file mode 100644 index 0000000..448c98c --- /dev/null +++ b/web-ide/src/lib/components/shell/TabBar.test.ts @@ -0,0 +1,39 @@ +import { fireEvent, render, screen } from "@testing-library/svelte"; +import userEvent from "@testing-library/user-event"; +import { describe, expect, it, vi } from "vitest"; + +import "@testing-library/jest-dom/vitest"; + +import TabBar from "./TabBar.svelte"; + +type Tab = { key: string; label: string; kind: "module" | "doc" | "manifest"; active: boolean; dirty: boolean }; + +const tabs: Tab[] = [ + { key: "orders", label: "orders.pds", kind: "module", active: true, dirty: false }, + { key: "docs/intro.md", label: "Intro", kind: "doc", active: false, dirty: true }, +]; + +describe("TabBar", () => { + it("selects a tab on click", async () => { + const onselect = vi.fn<(key: string) => void>(); + render(TabBar, { props: { tabs, onselect } }); + await userEvent.click(screen.getByRole("tab", { name: /Intro/ })); + expect(onselect).toHaveBeenCalledWith("docs/intro.md"); + }); + + it("closes a tab via its close button", async () => { + const onclose = vi.fn<(key: string) => void>(); + render(TabBar, { props: { tabs, onclose } }); + await userEvent.click(screen.getByRole("button", { name: "Close orders.pds" })); + expect(onclose).toHaveBeenCalledWith("orders"); + }); + + it("closes a tab on middle-click", async () => { + const onclose = vi.fn<(key: string) => void>(); + render(TabBar, { props: { tabs, onclose } }); + // Middle-click fires `auxclick` with button 1 on the tab row, not the close button. + const row = screen.getByRole("tab", { name: /Intro/ }).parentElement as HTMLElement; + await fireEvent(row, new MouseEvent("auxclick", { button: 1, bubbles: true })); + expect(onclose).toHaveBeenCalledWith("docs/intro.md"); + }); +}); diff --git a/web-ide/src/lib/components/shell/TopBar.svelte b/web-ide/src/lib/components/shell/TopBar.svelte new file mode 100644 index 0000000..137ac33 --- /dev/null +++ b/web-ide/src/lib/components/shell/TopBar.svelte @@ -0,0 +1,150 @@ + + +
                      +
                      + pds + + {#if workspaceName} + + {/if} +
                      + +
                      + {#if workspaceName} + + {/if} +
                      +
                      + + diff --git a/web-ide/src/lib/components/ui/button/button-showcase.svelte b/web-ide/src/lib/components/ui/button/button-showcase.svelte new file mode 100644 index 0000000..f1e180d --- /dev/null +++ b/web-ide/src/lib/components/ui/button/button-showcase.svelte @@ -0,0 +1,23 @@ + + +
                      +
                      + + + + + + +
                      +
                      + + + + +
                      +
                      diff --git a/web-ide/src/lib/components/ui/button/button.stories.ts b/web-ide/src/lib/components/ui/button/button.stories.ts new file mode 100644 index 0000000..6068f46 --- /dev/null +++ b/web-ide/src/lib/components/ui/button/button.stories.ts @@ -0,0 +1,16 @@ +import type { Meta, StoryObj } from "@storybook/svelte"; + +import Showcase from "./button-showcase.svelte"; + +// The shadcn-svelte Button, rendered on the IDE's aligned theme (brand-vermilion +// `primary`, existing surfaces/borders, --radius shapes). +const meta: Meta = { + title: "UI/Button", + component: Showcase, + tags: ["autodocs"], +}; + +export default meta; +type Story = StoryObj; + +export const Variants: Story = {}; diff --git a/web-ide/src/lib/components/ui/button/button.svelte b/web-ide/src/lib/components/ui/button/button.svelte new file mode 100644 index 0000000..89cedcb --- /dev/null +++ b/web-ide/src/lib/components/ui/button/button.svelte @@ -0,0 +1,82 @@ + + + + +{#if href} + + {@render children?.()} + +{:else} + +{/if} diff --git a/web-ide/src/lib/components/ui/button/index.ts b/web-ide/src/lib/components/ui/button/index.ts new file mode 100644 index 0000000..fb585d7 --- /dev/null +++ b/web-ide/src/lib/components/ui/button/index.ts @@ -0,0 +1,17 @@ +import Root, { + type ButtonProps, + type ButtonSize, + type ButtonVariant, + buttonVariants, +} from "./button.svelte"; + +export { + Root, + type ButtonProps as Props, + // + Root as Button, + buttonVariants, + type ButtonProps, + type ButtonSize, + type ButtonVariant, +}; diff --git a/web-ide/src/lib/components/ui/command/command-dialog.svelte b/web-ide/src/lib/components/ui/command/command-dialog.svelte new file mode 100644 index 0000000..63b445c --- /dev/null +++ b/web-ide/src/lib/components/ui/command/command-dialog.svelte @@ -0,0 +1,42 @@ + + + + + {title} + {description} + + + + + diff --git a/web-ide/src/lib/components/ui/command/command-empty.svelte b/web-ide/src/lib/components/ui/command/command-empty.svelte new file mode 100644 index 0000000..6726cd8 --- /dev/null +++ b/web-ide/src/lib/components/ui/command/command-empty.svelte @@ -0,0 +1,17 @@ + + + diff --git a/web-ide/src/lib/components/ui/command/command-group.svelte b/web-ide/src/lib/components/ui/command/command-group.svelte new file mode 100644 index 0000000..f5da0df --- /dev/null +++ b/web-ide/src/lib/components/ui/command/command-group.svelte @@ -0,0 +1,32 @@ + + + + {#if heading} + + {heading} + + {/if} + + diff --git a/web-ide/src/lib/components/ui/command/command-input.svelte b/web-ide/src/lib/components/ui/command/command-input.svelte new file mode 100644 index 0000000..1ca256f --- /dev/null +++ b/web-ide/src/lib/components/ui/command/command-input.svelte @@ -0,0 +1,34 @@ + + +
                      + + + {#snippet child({ props })} + + {/snippet} + + + + + +
                      diff --git a/web-ide/src/lib/components/ui/command/command-item.svelte b/web-ide/src/lib/components/ui/command/command-item.svelte new file mode 100644 index 0000000..4246840 --- /dev/null +++ b/web-ide/src/lib/components/ui/command/command-item.svelte @@ -0,0 +1,25 @@ + + + + {@render children?.()} + + diff --git a/web-ide/src/lib/components/ui/command/command-link-item.svelte b/web-ide/src/lib/components/ui/command/command-link-item.svelte new file mode 100644 index 0000000..ada6d2c --- /dev/null +++ b/web-ide/src/lib/components/ui/command/command-link-item.svelte @@ -0,0 +1,20 @@ + + + diff --git a/web-ide/src/lib/components/ui/command/command-list.svelte b/web-ide/src/lib/components/ui/command/command-list.svelte new file mode 100644 index 0000000..f663bd3 --- /dev/null +++ b/web-ide/src/lib/components/ui/command/command-list.svelte @@ -0,0 +1,17 @@ + + + diff --git a/web-ide/src/lib/components/ui/command/command-loading.svelte b/web-ide/src/lib/components/ui/command/command-loading.svelte new file mode 100644 index 0000000..19dd298 --- /dev/null +++ b/web-ide/src/lib/components/ui/command/command-loading.svelte @@ -0,0 +1,7 @@ + + + diff --git a/web-ide/src/lib/components/ui/command/command-separator.svelte b/web-ide/src/lib/components/ui/command/command-separator.svelte new file mode 100644 index 0000000..35c4c95 --- /dev/null +++ b/web-ide/src/lib/components/ui/command/command-separator.svelte @@ -0,0 +1,17 @@ + + + diff --git a/web-ide/src/lib/components/ui/command/command-shortcut.svelte b/web-ide/src/lib/components/ui/command/command-shortcut.svelte new file mode 100644 index 0000000..5322e6a --- /dev/null +++ b/web-ide/src/lib/components/ui/command/command-shortcut.svelte @@ -0,0 +1,20 @@ + + + + {@render children?.()} + diff --git a/web-ide/src/lib/components/ui/command/command.svelte b/web-ide/src/lib/components/ui/command/command.svelte new file mode 100644 index 0000000..c814599 --- /dev/null +++ b/web-ide/src/lib/components/ui/command/command.svelte @@ -0,0 +1,25 @@ + + + diff --git a/web-ide/src/lib/components/ui/command/index.ts b/web-ide/src/lib/components/ui/command/index.ts new file mode 100644 index 0000000..5435fbe --- /dev/null +++ b/web-ide/src/lib/components/ui/command/index.ts @@ -0,0 +1,37 @@ +import Root from "./command.svelte"; +import Loading from "./command-loading.svelte"; +import Dialog from "./command-dialog.svelte"; +import Empty from "./command-empty.svelte"; +import Group from "./command-group.svelte"; +import Item from "./command-item.svelte"; +import Input from "./command-input.svelte"; +import List from "./command-list.svelte"; +import Separator from "./command-separator.svelte"; +import Shortcut from "./command-shortcut.svelte"; +import LinkItem from "./command-link-item.svelte"; + +export { + Root, + Dialog, + Empty, + Group, + Item, + LinkItem, + Input, + List, + Separator, + Shortcut, + Loading, + // + Root as Command, + Dialog as CommandDialog, + Empty as CommandEmpty, + Group as CommandGroup, + Item as CommandItem, + LinkItem as CommandLinkItem, + Input as CommandInput, + List as CommandList, + Separator as CommandSeparator, + Shortcut as CommandShortcut, + Loading as CommandLoading, +}; diff --git a/web-ide/src/lib/components/ui/context-menu/context-menu-checkbox-item.svelte b/web-ide/src/lib/components/ui/context-menu/context-menu-checkbox-item.svelte new file mode 100644 index 0000000..9ffcfbe --- /dev/null +++ b/web-ide/src/lib/components/ui/context-menu/context-menu-checkbox-item.svelte @@ -0,0 +1,41 @@ + + + + {#snippet children({ checked })} + + {#if checked} + + {/if} + + {@render childrenProp?.()} + {/snippet} + diff --git a/web-ide/src/lib/components/ui/context-menu/context-menu-content.svelte b/web-ide/src/lib/components/ui/context-menu/context-menu-content.svelte new file mode 100644 index 0000000..5f32420 --- /dev/null +++ b/web-ide/src/lib/components/ui/context-menu/context-menu-content.svelte @@ -0,0 +1,28 @@ + + + + + diff --git a/web-ide/src/lib/components/ui/context-menu/context-menu-group-heading.svelte b/web-ide/src/lib/components/ui/context-menu/context-menu-group-heading.svelte new file mode 100644 index 0000000..0c0f459 --- /dev/null +++ b/web-ide/src/lib/components/ui/context-menu/context-menu-group-heading.svelte @@ -0,0 +1,21 @@ + + + diff --git a/web-ide/src/lib/components/ui/context-menu/context-menu-group.svelte b/web-ide/src/lib/components/ui/context-menu/context-menu-group.svelte new file mode 100644 index 0000000..c7c1e06 --- /dev/null +++ b/web-ide/src/lib/components/ui/context-menu/context-menu-group.svelte @@ -0,0 +1,7 @@ + + + diff --git a/web-ide/src/lib/components/ui/context-menu/context-menu-item.svelte b/web-ide/src/lib/components/ui/context-menu/context-menu-item.svelte new file mode 100644 index 0000000..fccba28 --- /dev/null +++ b/web-ide/src/lib/components/ui/context-menu/context-menu-item.svelte @@ -0,0 +1,27 @@ + + + diff --git a/web-ide/src/lib/components/ui/context-menu/context-menu-label.svelte b/web-ide/src/lib/components/ui/context-menu/context-menu-label.svelte new file mode 100644 index 0000000..8b9e9c6 --- /dev/null +++ b/web-ide/src/lib/components/ui/context-menu/context-menu-label.svelte @@ -0,0 +1,24 @@ + + +
                      + {@render children?.()} +
                      diff --git a/web-ide/src/lib/components/ui/context-menu/context-menu-portal.svelte b/web-ide/src/lib/components/ui/context-menu/context-menu-portal.svelte new file mode 100644 index 0000000..96b1e3e --- /dev/null +++ b/web-ide/src/lib/components/ui/context-menu/context-menu-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/web-ide/src/lib/components/ui/context-menu/context-menu-radio-group.svelte b/web-ide/src/lib/components/ui/context-menu/context-menu-radio-group.svelte new file mode 100644 index 0000000..964cb55 --- /dev/null +++ b/web-ide/src/lib/components/ui/context-menu/context-menu-radio-group.svelte @@ -0,0 +1,16 @@ + + + diff --git a/web-ide/src/lib/components/ui/context-menu/context-menu-radio-item.svelte b/web-ide/src/lib/components/ui/context-menu/context-menu-radio-item.svelte new file mode 100644 index 0000000..ad4e56f --- /dev/null +++ b/web-ide/src/lib/components/ui/context-menu/context-menu-radio-item.svelte @@ -0,0 +1,35 @@ + + + + {#snippet children({ checked })} + + {#if checked} + + {/if} + + {@render childrenProp?.({ checked })} + {/snippet} + diff --git a/web-ide/src/lib/components/ui/context-menu/context-menu-separator.svelte b/web-ide/src/lib/components/ui/context-menu/context-menu-separator.svelte new file mode 100644 index 0000000..7f5b237 --- /dev/null +++ b/web-ide/src/lib/components/ui/context-menu/context-menu-separator.svelte @@ -0,0 +1,17 @@ + + + diff --git a/web-ide/src/lib/components/ui/context-menu/context-menu-shortcut.svelte b/web-ide/src/lib/components/ui/context-menu/context-menu-shortcut.svelte new file mode 100644 index 0000000..3305abc --- /dev/null +++ b/web-ide/src/lib/components/ui/context-menu/context-menu-shortcut.svelte @@ -0,0 +1,20 @@ + + + + {@render children?.()} + diff --git a/web-ide/src/lib/components/ui/context-menu/context-menu-sub-content.svelte b/web-ide/src/lib/components/ui/context-menu/context-menu-sub-content.svelte new file mode 100644 index 0000000..fa46397 --- /dev/null +++ b/web-ide/src/lib/components/ui/context-menu/context-menu-sub-content.svelte @@ -0,0 +1,17 @@ + + + diff --git a/web-ide/src/lib/components/ui/context-menu/context-menu-sub-trigger.svelte b/web-ide/src/lib/components/ui/context-menu/context-menu-sub-trigger.svelte new file mode 100644 index 0000000..af016c5 --- /dev/null +++ b/web-ide/src/lib/components/ui/context-menu/context-menu-sub-trigger.svelte @@ -0,0 +1,29 @@ + + + + {@render children?.()} + + diff --git a/web-ide/src/lib/components/ui/context-menu/context-menu-sub.svelte b/web-ide/src/lib/components/ui/context-menu/context-menu-sub.svelte new file mode 100644 index 0000000..a03827b --- /dev/null +++ b/web-ide/src/lib/components/ui/context-menu/context-menu-sub.svelte @@ -0,0 +1,7 @@ + + + diff --git a/web-ide/src/lib/components/ui/context-menu/context-menu-trigger.svelte b/web-ide/src/lib/components/ui/context-menu/context-menu-trigger.svelte new file mode 100644 index 0000000..f6a1542 --- /dev/null +++ b/web-ide/src/lib/components/ui/context-menu/context-menu-trigger.svelte @@ -0,0 +1,17 @@ + + + diff --git a/web-ide/src/lib/components/ui/context-menu/context-menu.svelte b/web-ide/src/lib/components/ui/context-menu/context-menu.svelte new file mode 100644 index 0000000..cfaefb3 --- /dev/null +++ b/web-ide/src/lib/components/ui/context-menu/context-menu.svelte @@ -0,0 +1,7 @@ + + + diff --git a/web-ide/src/lib/components/ui/context-menu/index.ts b/web-ide/src/lib/components/ui/context-menu/index.ts new file mode 100644 index 0000000..cbeaee1 --- /dev/null +++ b/web-ide/src/lib/components/ui/context-menu/index.ts @@ -0,0 +1,52 @@ +import Root from "./context-menu.svelte"; +import Sub from "./context-menu-sub.svelte"; +import Portal from "./context-menu-portal.svelte"; +import Trigger from "./context-menu-trigger.svelte"; +import Group from "./context-menu-group.svelte"; +import RadioGroup from "./context-menu-radio-group.svelte"; +import Item from "./context-menu-item.svelte"; +import GroupHeading from "./context-menu-group-heading.svelte"; +import Content from "./context-menu-content.svelte"; +import Shortcut from "./context-menu-shortcut.svelte"; +import RadioItem from "./context-menu-radio-item.svelte"; +import Separator from "./context-menu-separator.svelte"; +import SubContent from "./context-menu-sub-content.svelte"; +import SubTrigger from "./context-menu-sub-trigger.svelte"; +import CheckboxItem from "./context-menu-checkbox-item.svelte"; +import Label from "./context-menu-label.svelte"; + +export { + Root, + Sub, + Portal, + Item, + GroupHeading, + Label, + Group, + Trigger, + Content, + Shortcut, + Separator, + RadioItem, + SubContent, + SubTrigger, + RadioGroup, + CheckboxItem, + // + Root as ContextMenu, + Sub as ContextMenuSub, + Portal as ContextMenuPortal, + Item as ContextMenuItem, + GroupHeading as ContextMenuGroupHeading, + Group as ContextMenuGroup, + Content as ContextMenuContent, + Trigger as ContextMenuTrigger, + Shortcut as ContextMenuShortcut, + RadioItem as ContextMenuRadioItem, + Separator as ContextMenuSeparator, + RadioGroup as ContextMenuRadioGroup, + SubContent as ContextMenuSubContent, + SubTrigger as ContextMenuSubTrigger, + CheckboxItem as ContextMenuCheckboxItem, + Label as ContextMenuLabel, +}; diff --git a/web-ide/src/lib/components/ui/dialog/dialog-close.svelte b/web-ide/src/lib/components/ui/dialog/dialog-close.svelte new file mode 100644 index 0000000..de68f2f --- /dev/null +++ b/web-ide/src/lib/components/ui/dialog/dialog-close.svelte @@ -0,0 +1,11 @@ + + + diff --git a/web-ide/src/lib/components/ui/dialog/dialog-content.svelte b/web-ide/src/lib/components/ui/dialog/dialog-content.svelte new file mode 100644 index 0000000..c0551ee --- /dev/null +++ b/web-ide/src/lib/components/ui/dialog/dialog-content.svelte @@ -0,0 +1,48 @@ + + + + + + {@render children?.()} + {#if showCloseButton} + + {#snippet child({ props })} + + {/snippet} + + {/if} + + diff --git a/web-ide/src/lib/components/ui/dialog/dialog-description.svelte b/web-ide/src/lib/components/ui/dialog/dialog-description.svelte new file mode 100644 index 0000000..0102d91 --- /dev/null +++ b/web-ide/src/lib/components/ui/dialog/dialog-description.svelte @@ -0,0 +1,17 @@ + + + diff --git a/web-ide/src/lib/components/ui/dialog/dialog-footer.svelte b/web-ide/src/lib/components/ui/dialog/dialog-footer.svelte new file mode 100644 index 0000000..e23160a --- /dev/null +++ b/web-ide/src/lib/components/ui/dialog/dialog-footer.svelte @@ -0,0 +1,32 @@ + + +
                      + {@render children?.()} + {#if showCloseButton} + + {#snippet child({ props })} + + {/snippet} + + {/if} +
                      diff --git a/web-ide/src/lib/components/ui/dialog/dialog-header.svelte b/web-ide/src/lib/components/ui/dialog/dialog-header.svelte new file mode 100644 index 0000000..c3ce8a2 --- /dev/null +++ b/web-ide/src/lib/components/ui/dialog/dialog-header.svelte @@ -0,0 +1,20 @@ + + +
                      + {@render children?.()} +
                      diff --git a/web-ide/src/lib/components/ui/dialog/dialog-overlay.svelte b/web-ide/src/lib/components/ui/dialog/dialog-overlay.svelte new file mode 100644 index 0000000..19f69f0 --- /dev/null +++ b/web-ide/src/lib/components/ui/dialog/dialog-overlay.svelte @@ -0,0 +1,17 @@ + + + diff --git a/web-ide/src/lib/components/ui/dialog/dialog-portal.svelte b/web-ide/src/lib/components/ui/dialog/dialog-portal.svelte new file mode 100644 index 0000000..ccfa79c --- /dev/null +++ b/web-ide/src/lib/components/ui/dialog/dialog-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/web-ide/src/lib/components/ui/dialog/dialog-title.svelte b/web-ide/src/lib/components/ui/dialog/dialog-title.svelte new file mode 100644 index 0000000..6ff1a4a --- /dev/null +++ b/web-ide/src/lib/components/ui/dialog/dialog-title.svelte @@ -0,0 +1,17 @@ + + + diff --git a/web-ide/src/lib/components/ui/dialog/dialog-trigger.svelte b/web-ide/src/lib/components/ui/dialog/dialog-trigger.svelte new file mode 100644 index 0000000..589ee0c --- /dev/null +++ b/web-ide/src/lib/components/ui/dialog/dialog-trigger.svelte @@ -0,0 +1,11 @@ + + + diff --git a/web-ide/src/lib/components/ui/dialog/dialog.svelte b/web-ide/src/lib/components/ui/dialog/dialog.svelte new file mode 100644 index 0000000..211672c --- /dev/null +++ b/web-ide/src/lib/components/ui/dialog/dialog.svelte @@ -0,0 +1,7 @@ + + + diff --git a/web-ide/src/lib/components/ui/dialog/index.ts b/web-ide/src/lib/components/ui/dialog/index.ts new file mode 100644 index 0000000..076cef5 --- /dev/null +++ b/web-ide/src/lib/components/ui/dialog/index.ts @@ -0,0 +1,34 @@ +import Root from "./dialog.svelte"; +import Portal from "./dialog-portal.svelte"; +import Title from "./dialog-title.svelte"; +import Footer from "./dialog-footer.svelte"; +import Header from "./dialog-header.svelte"; +import Overlay from "./dialog-overlay.svelte"; +import Content from "./dialog-content.svelte"; +import Description from "./dialog-description.svelte"; +import Trigger from "./dialog-trigger.svelte"; +import Close from "./dialog-close.svelte"; + +export { + Root, + Title, + Portal, + Footer, + Header, + Trigger, + Overlay, + Content, + Description, + Close, + // + Root as Dialog, + Title as DialogTitle, + Portal as DialogPortal, + Footer as DialogFooter, + Header as DialogHeader, + Trigger as DialogTrigger, + Overlay as DialogOverlay, + Content as DialogContent, + Description as DialogDescription, + Close as DialogClose, +}; diff --git a/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte new file mode 100644 index 0000000..e0e1971 --- /dev/null +++ b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte @@ -0,0 +1,16 @@ + + + diff --git a/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte new file mode 100644 index 0000000..a81b48d --- /dev/null +++ b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte @@ -0,0 +1,44 @@ + + + + {#snippet children({ checked, indeterminate })} + + {#if indeterminate} + + {:else if checked} + + {/if} + + {@render childrenProp?.()} + {/snippet} + diff --git a/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte new file mode 100644 index 0000000..261a5b0 --- /dev/null +++ b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte @@ -0,0 +1,31 @@ + + + + + diff --git a/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte new file mode 100644 index 0000000..433540f --- /dev/null +++ b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte @@ -0,0 +1,22 @@ + + + diff --git a/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte new file mode 100644 index 0000000..aca1f7b --- /dev/null +++ b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte @@ -0,0 +1,7 @@ + + + diff --git a/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte new file mode 100644 index 0000000..c425190 --- /dev/null +++ b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte @@ -0,0 +1,27 @@ + + + diff --git a/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte new file mode 100644 index 0000000..e0c534f --- /dev/null +++ b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte @@ -0,0 +1,24 @@ + + +
                      + {@render children?.()} +
                      diff --git a/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte new file mode 100644 index 0000000..274cfef --- /dev/null +++ b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte new file mode 100644 index 0000000..189aef4 --- /dev/null +++ b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte @@ -0,0 +1,16 @@ + + + diff --git a/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte new file mode 100644 index 0000000..c8aa07b --- /dev/null +++ b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte @@ -0,0 +1,34 @@ + + + + {#snippet children({ checked })} + + {#if checked} + + {/if} + + {@render childrenProp?.({ checked })} + {/snippet} + diff --git a/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte new file mode 100644 index 0000000..90f1b6f --- /dev/null +++ b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte @@ -0,0 +1,17 @@ + + + diff --git a/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte new file mode 100644 index 0000000..ed7cc85 --- /dev/null +++ b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte @@ -0,0 +1,20 @@ + + + + {@render children?.()} + diff --git a/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte new file mode 100644 index 0000000..b5750d4 --- /dev/null +++ b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte @@ -0,0 +1,17 @@ + + + diff --git a/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte new file mode 100644 index 0000000..fab0275 --- /dev/null +++ b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte @@ -0,0 +1,29 @@ + + + + {@render children?.()} + + diff --git a/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte new file mode 100644 index 0000000..f044581 --- /dev/null +++ b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte @@ -0,0 +1,7 @@ + + + diff --git a/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte new file mode 100644 index 0000000..cb05344 --- /dev/null +++ b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte new file mode 100644 index 0000000..cb4bc62 --- /dev/null +++ b/web-ide/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte @@ -0,0 +1,7 @@ + + + diff --git a/web-ide/src/lib/components/ui/dropdown-menu/index.ts b/web-ide/src/lib/components/ui/dropdown-menu/index.ts new file mode 100644 index 0000000..7850c6a --- /dev/null +++ b/web-ide/src/lib/components/ui/dropdown-menu/index.ts @@ -0,0 +1,54 @@ +import Root from "./dropdown-menu.svelte"; +import Sub from "./dropdown-menu-sub.svelte"; +import CheckboxGroup from "./dropdown-menu-checkbox-group.svelte"; +import CheckboxItem from "./dropdown-menu-checkbox-item.svelte"; +import Content from "./dropdown-menu-content.svelte"; +import Group from "./dropdown-menu-group.svelte"; +import Item from "./dropdown-menu-item.svelte"; +import Label from "./dropdown-menu-label.svelte"; +import RadioGroup from "./dropdown-menu-radio-group.svelte"; +import RadioItem from "./dropdown-menu-radio-item.svelte"; +import Separator from "./dropdown-menu-separator.svelte"; +import Shortcut from "./dropdown-menu-shortcut.svelte"; +import Trigger from "./dropdown-menu-trigger.svelte"; +import SubContent from "./dropdown-menu-sub-content.svelte"; +import SubTrigger from "./dropdown-menu-sub-trigger.svelte"; +import GroupHeading from "./dropdown-menu-group-heading.svelte"; +import Portal from "./dropdown-menu-portal.svelte"; + +export { + CheckboxGroup, + CheckboxItem, + Content, + Portal, + Root as DropdownMenu, + CheckboxGroup as DropdownMenuCheckboxGroup, + CheckboxItem as DropdownMenuCheckboxItem, + Content as DropdownMenuContent, + Portal as DropdownMenuPortal, + Group as DropdownMenuGroup, + Item as DropdownMenuItem, + Label as DropdownMenuLabel, + RadioGroup as DropdownMenuRadioGroup, + RadioItem as DropdownMenuRadioItem, + Separator as DropdownMenuSeparator, + Shortcut as DropdownMenuShortcut, + Sub as DropdownMenuSub, + SubContent as DropdownMenuSubContent, + SubTrigger as DropdownMenuSubTrigger, + Trigger as DropdownMenuTrigger, + GroupHeading as DropdownMenuGroupHeading, + Group, + GroupHeading, + Item, + Label, + RadioGroup, + RadioItem, + Root, + Separator, + Shortcut, + Sub, + SubContent, + SubTrigger, + Trigger, +}; diff --git a/web-ide/src/lib/components/ui/input-group/index.ts b/web-ide/src/lib/components/ui/input-group/index.ts new file mode 100644 index 0000000..fe1f55d --- /dev/null +++ b/web-ide/src/lib/components/ui/input-group/index.ts @@ -0,0 +1,22 @@ +import Root from "./input-group.svelte"; +import Addon from "./input-group-addon.svelte"; +import Button from "./input-group-button.svelte"; +import Input from "./input-group-input.svelte"; +import Text from "./input-group-text.svelte"; +import Textarea from "./input-group-textarea.svelte"; + +export { + Root, + Addon, + Button, + Input, + Text, + Textarea, + // + Root as InputGroup, + Addon as InputGroupAddon, + Button as InputGroupButton, + Input as InputGroupInput, + Text as InputGroupText, + Textarea as InputGroupTextarea, +}; diff --git a/web-ide/src/lib/components/ui/input-group/input-group-addon.svelte b/web-ide/src/lib/components/ui/input-group/input-group-addon.svelte new file mode 100644 index 0000000..ea075ea --- /dev/null +++ b/web-ide/src/lib/components/ui/input-group/input-group-addon.svelte @@ -0,0 +1,52 @@ + + + + +
                      { + if ((e.target as HTMLElement).closest("button")) { + return; + } + e.currentTarget.parentElement?.querySelector("input")?.focus(); + }} + {...restProps} +> + {@render children?.()} +
                      diff --git a/web-ide/src/lib/components/ui/input-group/input-group-button.svelte b/web-ide/src/lib/components/ui/input-group/input-group-button.svelte new file mode 100644 index 0000000..adb05b9 --- /dev/null +++ b/web-ide/src/lib/components/ui/input-group/input-group-button.svelte @@ -0,0 +1,49 @@ + + + + + diff --git a/web-ide/src/lib/components/ui/input-group/input-group-input.svelte b/web-ide/src/lib/components/ui/input-group/input-group-input.svelte new file mode 100644 index 0000000..316c0cb --- /dev/null +++ b/web-ide/src/lib/components/ui/input-group/input-group-input.svelte @@ -0,0 +1,20 @@ + + + diff --git a/web-ide/src/lib/components/ui/input-group/input-group-text.svelte b/web-ide/src/lib/components/ui/input-group/input-group-text.svelte new file mode 100644 index 0000000..77907c6 --- /dev/null +++ b/web-ide/src/lib/components/ui/input-group/input-group-text.svelte @@ -0,0 +1,19 @@ + + + + {@render children?.()} + diff --git a/web-ide/src/lib/components/ui/input-group/input-group-textarea.svelte b/web-ide/src/lib/components/ui/input-group/input-group-textarea.svelte new file mode 100644 index 0000000..9fbabe6 --- /dev/null +++ b/web-ide/src/lib/components/ui/input-group/input-group-textarea.svelte @@ -0,0 +1,20 @@ + + + diff --git a/web-ide/src/lib/components/ui/tooltip/index.ts b/web-ide/src/lib/components/ui/tooltip/index.ts new file mode 100644 index 0000000..1718604 --- /dev/null +++ b/web-ide/src/lib/components/ui/tooltip/index.ts @@ -0,0 +1,19 @@ +import Root from "./tooltip.svelte"; +import Trigger from "./tooltip-trigger.svelte"; +import Content from "./tooltip-content.svelte"; +import Provider from "./tooltip-provider.svelte"; +import Portal from "./tooltip-portal.svelte"; + +export { + Root, + Trigger, + Content, + Provider, + Portal, + // + Root as Tooltip, + Content as TooltipContent, + Trigger as TooltipTrigger, + Provider as TooltipProvider, + Portal as TooltipPortal, +}; diff --git a/web-ide/src/lib/components/ui/tooltip/tooltip-content.svelte b/web-ide/src/lib/components/ui/tooltip/tooltip-content.svelte new file mode 100644 index 0000000..0cf0694 --- /dev/null +++ b/web-ide/src/lib/components/ui/tooltip/tooltip-content.svelte @@ -0,0 +1,52 @@ + + + + + {@render children?.()} + + {#snippet child({ props })} +
                      + {/snippet} +
                      +
                      +
                      diff --git a/web-ide/src/lib/components/ui/tooltip/tooltip-portal.svelte b/web-ide/src/lib/components/ui/tooltip/tooltip-portal.svelte new file mode 100644 index 0000000..d234f7d --- /dev/null +++ b/web-ide/src/lib/components/ui/tooltip/tooltip-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/web-ide/src/lib/components/ui/tooltip/tooltip-provider.svelte b/web-ide/src/lib/components/ui/tooltip/tooltip-provider.svelte new file mode 100644 index 0000000..6dba9a6 --- /dev/null +++ b/web-ide/src/lib/components/ui/tooltip/tooltip-provider.svelte @@ -0,0 +1,7 @@ + + + diff --git a/web-ide/src/lib/components/ui/tooltip/tooltip-trigger.svelte b/web-ide/src/lib/components/ui/tooltip/tooltip-trigger.svelte new file mode 100644 index 0000000..1acdaa4 --- /dev/null +++ b/web-ide/src/lib/components/ui/tooltip/tooltip-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/web-ide/src/lib/components/ui/tooltip/tooltip.svelte b/web-ide/src/lib/components/ui/tooltip/tooltip.svelte new file mode 100644 index 0000000..0b0f9ce --- /dev/null +++ b/web-ide/src/lib/components/ui/tooltip/tooltip.svelte @@ -0,0 +1,7 @@ + + + diff --git a/web-ide/src/lib/core/canvas.test.ts b/web-ide/src/lib/core/canvas.test.ts new file mode 100644 index 0000000..118c059 --- /dev/null +++ b/web-ide/src/lib/core/canvas.test.ts @@ -0,0 +1,82 @@ +import { describe, expect, it, vi } from "vitest"; + +import { canvasHint, projectCanvas, type CanvasWasm } from "./canvas.js"; +import { buildModelIndex } from "./model.js"; +import type { Scene, StructureNode } from "./types.js"; + +const idx = buildModelIndex( + [{ fqn: "m::C", name: "C", kind: "container", triggered: false, line: 1, col: 1, parent: null } as StructureNode], + ["m"], +); + +const seqScene = (participants: unknown[]): Scene => ({ view: "sequence", participants, items: [] }); +const c4Scene = (nodes: unknown[]): Scene => ({ view: "context", nodes, edges: [] }); + +const wasm = (over: Partial = {}): CanvasWasm => ({ + symbolScene: () => seqScene([{ fqn: "m::C" }, { fqn: "x" }]), + emitSceneModules: () => c4Scene([{ fqn: "m::C" }]), + layoutScene: (s) => ({ ...s, laid: true }), + ...over, +}); + +describe("projectCanvas", () => { + it("lays out a sequence scene for a selected symbol", () => { + const r = projectCanvas({ selected: { fqn: "m::C" }, seqDepth: "component", modules: [], index: idx, wasm: wasm(), onError: () => {} }); + expect(r.error).toBe(""); + expect((r.layout as { laid?: boolean })?.laid).toBe(true); + }); + + it("projects the context overview with no selection (no layout)", () => { + const r = projectCanvas({ selected: null, seqDepth: "component", modules: [], index: idx, wasm: wasm(), onError: () => {} }); + expect((r.scene as { nodes: unknown[] }).nodes).toHaveLength(1); + expect(r.layout).toBeNull(); + }); + + it("falls back to a lifeline when a selected sequence is empty", () => { + const r = projectCanvas({ + selected: { fqn: "m::C" }, + seqDepth: "component", + modules: [], + index: idx, + wasm: wasm({ symbolScene: () => seqScene([]) }), + onError: () => {}, + }); + expect((r.scene as { participants: unknown[] }).participants).toHaveLength(1); + }); + + it("on a throw with a selection, reports and falls back to a lifeline", () => { + const onError = vi.fn(); + const r = projectCanvas({ + selected: { fqn: "m::C" }, + seqDepth: "component", + modules: [], + index: idx, + wasm: wasm({ symbolScene: () => { throw new Error("nope"); } }), + onError, + }); + expect(onError).toHaveBeenCalledWith("DIAGRAM_PROJECTION_FAILED", expect.stringContaining("nope")); + expect((r.scene as { view: string }).view).toBe("sequence"); // lifeline fallback + }); + + it("on a throw with no selection, reports an error result", () => { + const onError = vi.fn(); + const r = projectCanvas({ + selected: null, + seqDepth: "component", + modules: [], + index: idx, + wasm: wasm({ emitSceneModules: () => { throw new Error("boom"); } }), + onError, + }); + expect(onError).toHaveBeenCalledWith("DIAGRAM_RENDER_FAILED", "boom"); + expect(r.scene).toBeNull(); + expect(r.error).toBe("boom"); + }); +}); + +describe("canvasHint", () => { + it("differs for a selection vs the whole model", () => { + expect(canvasHint({ fqn: "x" })).toContain("Nothing to draw"); + expect(canvasHint(null)).toContain("context overview"); + }); +}); diff --git a/web-ide/src/lib/core/canvas.ts b/web-ide/src/lib/core/canvas.ts new file mode 100644 index 0000000..492783f --- /dev/null +++ b/web-ide/src/lib/core/canvas.ts @@ -0,0 +1,68 @@ +// Canvas scene projection — pure. +// +// Projects the selected node (or the whole-model context) to a laid-out scene: +// the compiler picks the view, a sequence scene is collapsed to the chosen depth, +// and a symbol with nothing to draw falls back to its own lifeline. The WASM scene +// functions are injected; errors are reported via an injected callback (wired to +// the error registry by the caller) so this stays side-effect-free. No Svelte. + +import { collapseSequence } from "../sequence.js"; +import { singleLifelineScene, type ModelIndex } from "./model.js"; +import type { Canvas, Depth, Module, Scene } from "./types.js"; + +// The WASM scene functions the projection needs. +export type CanvasWasm = { + symbolScene: (modules: Module[], fqn: string) => Scene; + emitSceneModules: (modules: Module[], view: string, target?: string) => Scene; + layoutScene: (scene: Scene) => Scene; +}; + +export type ProjectCanvasArgs = { + selected: { fqn: string } | null; + seqDepth: Depth; + modules: Module[]; + index: ModelIndex; + wasm: CanvasWasm; + onError: (code: "DIAGRAM_PROJECTION_FAILED" | "DIAGRAM_RENDER_FAILED", detail: string) => void; +}; + +/** + * Project the canvas scene + layout. A selected symbol projects its fitting view; + * no selection projects the context overview. A sequence is collapsed to `seqDepth` + * and positioned by the layout engine; C4 stays as-is. An empty or unprojectable + * selected symbol falls back to its single lifeline; an unprojectable context is an + * error. Both error paths report via `onError`. + */ +export function projectCanvas(args: ProjectCanvasArgs): Canvas { + const { selected, seqDepth, modules, index, wasm, onError } = args; + const lifelineFallback = (): Canvas => { + const scene = singleLifelineScene(index, selected!.fqn); + return { scene, layout: wasm.layoutScene(scene), error: "" }; + }; + try { + const raw = selected ? wasm.symbolScene(modules, selected.fqn) : wasm.emitSceneModules(modules, "context", ""); + const isSeq = !!raw && Array.isArray(raw.participants); + const shown = (isSeq ? collapseSequence(raw as never, seqDepth, index.nodeInfo) : raw) as Scene | null; + const isEmpty = isSeq + ? !(shown?.participants as unknown[] | undefined)?.length + : !(shown?.nodes as unknown[] | undefined)?.length; + if (isEmpty && selected) return lifelineFallback(); + const layout = isSeq && shown ? wasm.layoutScene(shown) : null; + return { scene: shown, layout, error: "" }; + } catch (e) { + const detail = String((e as Error)?.message ?? e); + if (selected) { + onError("DIAGRAM_PROJECTION_FAILED", `${selected.fqn}: ${detail}`); + return lifelineFallback(); + } + onError("DIAGRAM_RENDER_FAILED", detail); + return { scene: null, layout: null, error: detail }; + } +} + +/** The placeholder hint shown when the canvas is empty. */ +export function canvasHint(selected: unknown): string { + return selected + ? "Nothing to draw for this item." + : "No persons or systems declared yet — the context overview draws systems and people."; +} diff --git a/web-ide/src/lib/core/diagnostics.test.ts b/web-ide/src/lib/core/diagnostics.test.ts new file mode 100644 index 0000000..47c6970 --- /dev/null +++ b/web-ide/src/lib/core/diagnostics.test.ts @@ -0,0 +1,40 @@ +import { describe, expect, it } from "vitest"; + +import { computeDiagnostics } from "./diagnostics.js"; +import type { Module, OpenFile } from "./types.js"; + +const files: OpenFile[] = [ + { fqn: "a", path: "a.pds" }, + { fqn: "b", path: "nested/b.pds" }, +]; +const modules: Module[] = [ + { fqn: "a", source: "" }, + { fqn: "b", source: "" }, +]; + +describe("computeDiagnostics", () => { + it("tags each diagnostic with its module FQN and counts errors", () => { + const check = () => [ + { fqn: "a", diagnostics: [{ severity: "error", message: "boom", start_line: 1, start_col: 1 }] }, + { fqn: "b", diagnostics: [{ severity: "warning", message: "meh", start_line: 2, start_col: 3 }] }, + ]; + const r = computeDiagnostics(modules, files, check as never); + expect(r.problems.map((p) => p.file)).toEqual(["a", "b"]); + expect(r.errorCount).toBe(1); + expect([...r.errorPaths]).toEqual(["a.pds"]); // only the module with an error, by path + }); + + it("returns the empty result when the check throws", () => { + const r = computeDiagnostics(modules, files, () => { + throw new Error("wasm"); + }); + expect(r).toEqual({ results: null, problems: [], errorCount: 0, errorPaths: new Set() }); + }); + + it("collects no error paths when nothing errors", () => { + const check = () => [{ fqn: "a", diagnostics: [{ severity: "warning" }] }]; + const r = computeDiagnostics(modules, files, check as never); + expect(r.errorCount).toBe(0); + expect(r.errorPaths.size).toBe(0); + }); +}); diff --git a/web-ide/src/lib/core/diagnostics.ts b/web-ide/src/lib/core/diagnostics.ts new file mode 100644 index 0000000..95408b2 --- /dev/null +++ b/web-ide/src/lib/core/diagnostics.ts @@ -0,0 +1,56 @@ +// Workspace diagnostics — derive the problem list, error count, and error-marked +// file paths from a static check of every module. Pure: the WASM `checkModules` +// is injected, and a throw degrades to "no results" (the view stays usable). + +import type { Module, OpenFile, Problem } from "./types.js"; + +// A module's check result: its FQN and raw diagnostics. Structurally matches +// `pds.ts`'s `ModuleDiagnostics`, so the real `checkModules` is assignable. +type ModuleResult = { fqn: string; diagnostics: ReadonlyArray<{ severity: string }> }; + +export type DiagnosticsResult = { + // Per-module raw results, or null when the check threw / isn't ready. + results: ReadonlyArray | null; + // Every diagnostic, tagged with its owning module's FQN. + problems: Problem[]; + // Count of error-severity problems. + errorCount: number; + // Tree paths of files that have at least one error (for the file-tree marker). + errorPaths: Set; +}; + +const EMPTY: DiagnosticsResult = { results: null, problems: [], errorCount: 0, errorPaths: new Set() }; + +/** + * Check `modules` and shape the result for the view. `files` maps FQNs to disk + * paths for the error-path set. A `check` throw yields the empty result. + */ +export function computeDiagnostics( + modules: Module[], + files: OpenFile[], + check: (modules: Module[]) => ReadonlyArray, +): DiagnosticsResult { + let results: ReadonlyArray; + try { + results = check(modules); + } catch { + return EMPTY; + } + + const problems: Problem[] = results.flatMap((m) => + (m.diagnostics as unknown as Problem[]).map((d) => ({ ...d, file: m.fqn })), + ); + const errorCount = problems.filter((d) => d.severity === "error").length; + + const byFqn = new Map(); + for (const f of files) if (f.fqn) byFqn.set(f.fqn, f.path); + const errorPaths = new Set(); + for (const m of results) { + if (m.diagnostics.some((d) => d.severity === "error")) { + const p = byFqn.get(m.fqn); + if (p) errorPaths.add(p); + } + } + + return { results, problems, errorCount, errorPaths }; +} diff --git a/web-ide/src/lib/core/dirty.test.ts b/web-ide/src/lib/core/dirty.test.ts new file mode 100644 index 0000000..96a76bf --- /dev/null +++ b/web-ide/src/lib/core/dirty.test.ts @@ -0,0 +1,65 @@ +import { describe, expect, it } from "vitest"; + +import { classifyReload, computeDirty, dirtyPaths, keyOf, seedBaseline, type Buffers } from "./dirty.js"; +import type { OpenFile } from "./types.js"; + +const buffers = (over: Partial = {}): Buffers => ({ + manifestKey: "pds.toml", + manifestSource: "", + moduleSources: {}, + docSources: {}, + otherSources: {}, + ...over, +}); + +describe("keyOf", () => { + it("uses path for manifest/doc/companion, fqn for a module", () => { + expect(keyOf({ isManifest: true, path: "pds.toml" })).toBe("pds.toml"); + expect(keyOf({ isDoc: true, path: "docs/x.md" })).toBe("docs/x.md"); + expect(keyOf({ isOther: true, path: "README.md" })).toBe("README.md"); + expect(keyOf({ fqn: "m", path: "m.pds" })).toBe("m"); + expect(keyOf(null)).toBeUndefined(); + }); +}); + +describe("computeDirty", () => { + it("flags only buffers that diverge from their baseline", () => { + const persisted = { m: "old", "docs/x.md": "doc", "pds.toml": "t" }; + const b = buffers({ moduleSources: { m: "new" }, docSources: { "docs/x.md": "doc" }, manifestSource: "t" }); + expect([...computeDirty(persisted, b)]).toEqual(["m"]); + }); + + it("ignores keys with no live buffer and samples with no baseline", () => { + expect(computeDirty({}, buffers({ moduleSources: { m: "x" } })).size).toBe(0); // no baseline → never dirty + }); + + it("tracks companion (other) buffers against their baseline", () => { + const persisted = { "README.md": "old" }; + expect(computeDirty(persisted, buffers({ otherSources: { "README.md": "edited" } })).size).toBe(1); + expect(computeDirty(persisted, buffers({ otherSources: { "README.md": "old" } })).size).toBe(0); + }); +}); + +describe("dirtyPaths", () => { + it("maps module fqns to paths, leaves doc paths alone", () => { + const files: OpenFile[] = [{ fqn: "m", path: "m.pds" }]; + expect([...dirtyPaths(new Set(["m", "docs/x.md"]), files)]).toEqual(["m.pds", "docs/x.md"]); + }); +}); + +describe("seedBaseline", () => { + it("returns a new map with the entries advanced", () => { + const before = { a: "1" }; + const after = seedBaseline(before, [{ key: "a", text: "2" }, { key: "b", text: "3" }]); + expect(after).toEqual({ a: "2", b: "3" }); + expect(before).toEqual({ a: "1" }); // unmutated + }); +}); + +describe("classifyReload", () => { + it("skips unchanged, reloads clean changes, flags conflicts", () => { + expect(classifyReload("x", "x", "x")).toBe("skip"); + expect(classifyReload("disk", "base", "base")).toBe("reload"); + expect(classifyReload("disk", "base", "edited")).toBe("conflict"); + }); +}); diff --git a/web-ide/src/lib/core/dirty.ts b/web-ide/src/lib/core/dirty.ts new file mode 100644 index 0000000..8010e2c --- /dev/null +++ b/web-ide/src/lib/core/dirty.ts @@ -0,0 +1,74 @@ +// Dirty-state and baseline math — pure. +// +// "Dirty" = a live buffer differs from its on-disk baseline. Only files with a +// recorded baseline (handle-backed) can be dirty; in-memory samples have none. +// The debounce/FS/timer half of saving lives in the save store — this is only +// the derivation and the reload decision. No Svelte, no FS. + +import type { OpenFile } from "./types.js"; + +// The live buffers, by key, that a baseline is compared against. +export type Buffers = { + manifestKey: string | null; + manifestSource: string; + moduleSources: Record; + docSources: Record; + otherSources: Record; +}; + +/** A file's buffer key: its path for a doc, manifest, or companion file; its FQN + * for a module. */ +export function keyOf(file: OpenFile | null): string | undefined { + return file?.isManifest || file?.isDoc || file?.isOther ? file.path : file?.fqn; +} + +/** The live value for a baseline key, across the manifest / module / doc / companion buffers. */ +function currentFor(key: string, b: Buffers): string | undefined { + if (key === b.manifestKey) return b.manifestSource; + if (key in b.moduleSources) return b.moduleSources[key]; + if (key in b.docSources) return b.docSources[key]; + return b.otherSources[key]; +} + +/** The set of dirty keys: every baseline whose live buffer diverged from it. */ +export function computeDirty(persisted: Record, buffers: Buffers): Set { + const set = new Set(); + for (const key of Object.keys(persisted)) { + const current = currentFor(key, buffers); + if (current !== undefined && current !== persisted[key]) set.add(key); + } + return set; +} + +/** Dirty keys mapped to tree paths for the file-tree dot: module keys are FQNs + * (resolved to their path); doc/manifest keys are already paths. */ +export function dirtyPaths(dirty: Set, files: OpenFile[]): Set { + const pathByFqn = new Map(); + for (const f of files) if (f.fqn && f.path) pathByFqn.set(f.fqn, f.path); + const paths = new Set(); + for (const key of dirty) paths.add(pathByFqn.get(key) ?? key); + return paths; +} + +/** Advance the baseline for a batch of saved buffers; returns a new map. */ +export function seedBaseline( + persisted: Record, + entries: { key: string; text: string }[], +): Record { + const next = { ...persisted }; + for (const { key, text } of entries) next[key] = text; + return next; +} + +/** + * Decide how to handle a file whose disk content was re-read. `base` is its + * baseline, `buffer` the live buffer: + * - `skip` — unchanged on disk (`disk === base`). + * - `conflict`— disk changed but the buffer has unsaved edits (`buffer !== base`). + * - `reload` — disk changed and the buffer is clean; safe to pull in. + */ +export function classifyReload(disk: string, base: string, buffer: string | undefined): "skip" | "reload" | "conflict" { + if (disk === base) return "skip"; + if (buffer !== base) return "conflict"; + return "reload"; +} diff --git a/web-ide/src/lib/core/docs.test.ts b/web-ide/src/lib/core/docs.test.ts new file mode 100644 index 0000000..c052eea --- /dev/null +++ b/web-ide/src/lib/core/docs.test.ts @@ -0,0 +1,49 @@ +import { describe, expect, it } from "vitest"; + +import { buildDocConfig, findDocByPath, manifestHasDeps, resolveDocPath, sampleDocPages } from "./docs.js"; +import type { LiveDocGroup } from "./types.js"; + +const groups: LiveDocGroup[] = [ + { title: "Guide", items: [{ title: "Intro", path: "docs/intro.md" }, { title: "Deep", path: "docs/api/deep.md" }] }, +]; + +describe("manifestHasDeps", () => { + it("detects a [dependencies] table", () => { + expect(manifestHasDeps("[package]\nname='x'\n[dependencies]\n")).toBe(true); + expect(manifestHasDeps(" [dependencies.foo]")).toBe(true); + expect(manifestHasDeps("[package]\nname='x'")).toBe(false); + }); +}); + +describe("resolveDocPath", () => { + it("resolves siblings, ., and .. against the open doc's dir", () => { + expect(resolveDocPath("docs/intro.md", "api/deep.md")).toBe("docs/api/deep.md"); + expect(resolveDocPath("docs/api/deep.md", "../intro.md")).toBe("docs/intro.md"); + expect(resolveDocPath("docs/intro.md", "./intro.md#anchor")).toBe("docs/intro.md"); + expect(resolveDocPath("intro.md", "other.md")).toBe("other.md"); + }); +}); + +describe("findDocByPath", () => { + it("finds a sidebar item by path", () => { + expect(findDocByPath(groups, "docs/api/deep.md")?.title).toBe("Deep"); + expect(findDocByPath(groups, "missing.md")).toBeUndefined(); + }); +}); + +describe("buildDocConfig", () => { + it("inlines page content under each group", () => { + const cfg = buildDocConfig({ name: "X", theme: "dark", docGroups: groups, docSources: { "docs/intro.md": "# Hi" } }); + expect(cfg.name).toBe("X"); + expect(cfg.docs[0].items[0]).toEqual({ title: "Intro", path: "docs/intro.md", content: "# Hi" }); + expect(cfg.docs[0].items[1].content).toBe(""); // missing buffer → empty + }); +}); + +describe("sampleDocPages", () => { + it("folds bundled content and drops pages with none", () => { + const sidebar = [{ title: "G", items: [{ title: "A", path: "a.md" }, { title: "B", path: "b.md" }] }]; + const out = sampleDocPages(sidebar, { "a.md": "content" }); + expect(out[0].items).toEqual([{ title: "A", path: "a.md", content: "content" }]); + }); +}); diff --git a/web-ide/src/lib/core/docs.ts b/web-ide/src/lib/core/docs.ts new file mode 100644 index 0000000..a4db06d --- /dev/null +++ b/web-ide/src/lib/core/docs.ts @@ -0,0 +1,69 @@ +// Manifest / doc-sidebar resolution — pure. +// +// The async page loaders (reading `.md` from disk, the manifest parse, the +// load-race guard) stay in the workspace store; this module owns the value +// transforms: link path normalisation, sidebar lookup, the doc-site config, the +// sample-page fold, and the `[dependencies]` probe. No Svelte, no FS. + +import type { LiveDocGroup, LiveDocItem } from "./types.js"; + +/** Whether the manifest declares a `[dependencies]` table. */ +export function manifestHasDeps(toml: string): boolean { + return /^\s*\[dependencies/m.test(toml); +} + +/** Normalise a relative doc link against the open doc's directory to a workspace + * path (resolving `.`/`..`, stripping any `#`/`?` suffix). */ +export function resolveDocPath(openDocPath: string, rel: string): string { + const dir = openDocPath.includes("/") ? openDocPath.slice(0, openDocPath.lastIndexOf("/")) : ""; + const stack = dir ? dir.split("/").filter(Boolean) : []; + for (const seg of rel.replace(/[#?].*$/, "").split("/")) { + if (seg === "" || seg === ".") continue; + if (seg === "..") stack.pop(); + else stack.push(seg); + } + return stack.join("/"); +} + +/** The sidebar item at `path`, or undefined. */ +export function findDocByPath(docGroups: LiveDocGroup[], path: string): LiveDocItem | undefined { + return docGroups.flatMap((g) => g.items).find((it) => it.path === path); +} + +// The doc-site config the renderer consumes (a structural subset of pds.ts's +// `DocConfig` — typed here so core doesn't depend on the WASM module). +export type DocConfigInput = { + name: string; + theme: string; + docGroups: LiveDocGroup[]; + docSources: Record; +}; +export type DocSiteConfig = { + name: string; + theme: string; + docs: { title: string; items: { title: string; path: string; content: string }[] }[]; +}; + +/** Assemble the doc-site render config from the live manifest meta + pages. */ +export function buildDocConfig(input: DocConfigInput): DocSiteConfig { + return { + name: input.name, + theme: input.theme, + docs: input.docGroups.map((g) => ({ + title: g.title, + items: g.items.map((i) => ({ title: i.title, path: i.path, content: input.docSources[i.path] ?? "" })), + })), + }; +} + +/** Fold bundled sample Markdown into the manifest sidebar, dropping any page with + * no bundled content (mirrors the folder path's warn-and-skip). */ +export function sampleDocPages( + sidebar: { title: string; items?: { title: string; path: string }[] }[] | null | undefined, + docMap: Record, +): { title: string; items: { title: string; path: string; content: string }[] }[] { + return (sidebar ?? []).map((group) => ({ + title: group.title, + items: (group.items ?? []).filter((item) => docMap[item.path] != null).map((item) => ({ ...item, content: docMap[item.path] })), + })); +} diff --git a/web-ide/src/lib/core/model.test.ts b/web-ide/src/lib/core/model.test.ts new file mode 100644 index 0000000..d1855a1 --- /dev/null +++ b/web-ide/src/lib/core/model.test.ts @@ -0,0 +1,100 @@ +import { describe, expect, it } from "vitest"; + +import { + ancestry, + buildModelIndex, + nodeByteOffset, + nodeTitle, + ownerNodeOf, + resolveNodeFqn, + singleLifelineScene, +} from "./model.js"; +import type { StructureNode } from "./types.js"; + +const node = (fqn: string, kind: string, parent: string | null = null, name = fqn.split("::").at(-1)!): StructureNode => ({ + fqn, + name, + kind, + triggered: false, + line: 1, + col: 1, + parent, +}); + +// Two modules with the same path prefix — the longest-prefix grouping must not +// mis-file `m::core::Exchange` under `m`. +const nodes: StructureNode[] = [ + node("m::Sys", "system"), + node("m::core::Exchange", "container", "m::Sys"), + node("m::core::Exchange::Run", "callable", "m::core::Exchange"), + node("m::core::Conv", "data"), +]; +const moduleFqns = ["m", "m::core"]; + +describe("buildModelIndex", () => { + const idx = buildModelIndex(nodes, moduleFqns); + + it("groups nodes to their file by the longest module-FQN prefix", () => { + expect(idx.structureByFile["m"].map((n) => n.fqn)).toEqual(["m::Sys"]); + expect(idx.structureByFile["m::core"].map((n) => n.fqn)).toEqual([ + "m::core::Exchange", + "m::core::Exchange::Run", + "m::core::Conv", + ]); + }); + + it("keys nodeIndex by FQN with its declaring file", () => { + expect(idx.nodeIndex.get("m::core::Exchange")?.fileFqn).toBe("m::core"); + expect(idx.symbols.find((s) => s.fqn === "m::core::Exchange")?.fileFqn).toBe("m::core"); + }); + + it("buckets callables as flows under their owner, and maps types/info", () => { + expect(idx.flowsByNode.get("m::core::Exchange")?.map((f) => f.name)).toEqual(["Run"]); + expect(idx.typeFqnByName["Conv"]).toBe("m::core::Conv"); + expect(idx.nodeInfo["m::core::Exchange"]).toEqual({ kind: "container", parent: "m::Sys" }); + }); +}); + +describe("resolvers", () => { + const idx = buildModelIndex(nodes, moduleFqns); + + it("resolveNodeFqn returns a direct node, or a collapsed member's real node", () => { + expect(resolveNodeFqn(idx, "m::core::Exchange")).toBe("m::core::Exchange"); + // a call folded to its system owner still resolves to the real callable + expect(resolveNodeFqn(idx, "m::Sys::Run")).toBe("m::core::Exchange::Run"); + expect(resolveNodeFqn(idx, "m::Nope::ghost")).toBeNull(); + }); + + it("ownerNodeOf walks up to the nearest node (field → owner)", () => { + expect(ownerNodeOf(idx, "m::core::Conv::id")).toBe("m::core::Conv"); + expect(ownerNodeOf(idx, "m::core::Exchange")).toBeNull(); // already a node, no ancestor + }); + + it("ancestry follows parent to the root", () => { + expect(ancestry(idx, "m::core::Exchange::Run")).toEqual([ + "m::Sys", + "m::core::Exchange", + "m::core::Exchange::Run", + ]); + }); + + it("nodeTitle renders kind + name, falling back to the leaf", () => { + expect(nodeTitle(idx, "m::core::Exchange")).toBe("container `Exchange`"); + expect(nodeTitle(idx, "m::ghost")).toBe("`ghost`"); + }); + + it("singleLifelineScene builds a one-participant sequence", () => { + const s = singleLifelineScene(idx, "m::core::Exchange::Run") as Record; + expect(s.view).toBe("sequence"); + expect(s.entry).toBe("m::core::Exchange::Run"); + expect((s.participants as { kind: string }[])[0].kind).toBe("callable"); + }); +}); + +describe("nodeByteOffset", () => { + it("maps 1-based line/col to a byte offset", () => { + const src = "//! m\npublic system S;\n"; + expect(nodeByteOffset(src, 1, 1)).toBe(0); + expect(nodeByteOffset(src, 2, 8)).toBe(6 + 7); // line 2 starts at byte 6, col 8 → +7 + }); +}); diff --git a/web-ide/src/lib/core/model.ts b/web-ide/src/lib/core/model.ts new file mode 100644 index 0000000..46d959d --- /dev/null +++ b/web-ide/src/lib/core/model.ts @@ -0,0 +1,153 @@ +// The structural model index and its resolvers — pure. +// +// One builder turns the workspace outline into every lookup the view needs (node +// index, per-file grouping, flows, type map, collapse info), computed once. The +// resolvers (FQN → node, member → owner, ancestry, byte offset) are pure over +// that index. The WASM outline is produced by the view and passed in as `nodes`; +// no Svelte, no WASM import here. + +import { charToByte } from "../offsets.js"; +import type { Info, Scene, StructureNode, Symbol } from "./types.js"; + +// A node plus the FQN of the file that declares it. +export type NodeRef = { node: StructureNode; fileFqn: string }; + +// An entry-point flow listed under its owning node. +export type Flow = { fqn: string; name: string; triggered: boolean }; + +// Everything derived from the workspace outline, bundled so it computes once. +export type ModelIndex = { + nodes: StructureNode[]; + structureByFile: Record; + nodeIndex: Map; + symbols: Symbol[]; + flowsByNode: Map; + nodeInfo: Info; + typeFqnByName: Record; +}; + +/** + * Build the model index from the workspace outline `nodes` and the workspace's + * module FQNs. Each node is grouped to its file by the longest module FQN that + * prefixes it — node FQNs use the file's path-derived module name, the scheme + * `hover`/`definition`/`references` resolve against (single-file `outline` keys + * by the `//!` header instead, which diverged and broke cross-module GOTO). + */ +export function buildModelIndex(nodes: StructureNode[], moduleFqns: string[]): ModelIndex { + const structureByFile: Record = {}; + for (const mf of moduleFqns) if (mf) structureByFile[mf] = []; + const byLongest = [...moduleFqns].sort((a, b) => b.length - a.length); + for (const n of nodes) { + const fileFqn = byLongest.find((mf) => n.fqn === mf || n.fqn.startsWith(`${mf}::`)) ?? ""; + (structureByFile[fileFqn] ??= []).push(n); + } + + const nodeIndex = new Map(); + for (const [fileFqn, list] of Object.entries(structureByFile)) { + for (const n of list) nodeIndex.set(n.fqn, { node: n, fileFqn }); + } + + const symbols: Symbol[] = [...nodeIndex.entries()].map(([fqn, { node, fileFqn }]) => ({ ...node, fqn, fileFqn })); + + const flowsByNode = new Map(); + for (const n of nodes) { + if (n.kind !== "callable") continue; + const parent = n.fqn.split("::").slice(0, -1).join("::"); + let bucket = flowsByNode.get(parent); + if (!bucket) flowsByNode.set(parent, (bucket = [])); + bucket.push({ fqn: n.fqn, name: n.name, triggered: n.triggered }); + } + + const nodeInfo: Info = {}; + for (const n of nodes) nodeInfo[n.fqn] = { kind: n.kind, parent: n.parent ?? null }; + + const typeFqnByName: Record = {}; + for (const n of nodes) if (n.kind === "data") typeFqnByName[n.name] = n.fqn; + + return { nodes, structureByFile, nodeIndex, symbols, flowsByNode, nodeInfo, typeFqnByName }; +} + +/** An empty index, for the not-ready / no-workspace state. */ +export function emptyModelIndex(): ModelIndex { + return { + nodes: [], + structureByFile: {}, + nodeIndex: new Map(), + symbols: [], + flowsByNode: new Map(), + nodeInfo: {}, + typeFqnByName: {}, + }; +} + +/** + * Resolve a possibly depth-collapsed callee FQN to a real node: a direct hit, else + * a callable named `method` somewhere beneath the collapsed owner (so a call's + * member still resolves when its target was folded into an ancestor). + */ +export function resolveNodeFqn(index: ModelIndex, fqn: string): string | null { + if (index.nodeIndex.has(fqn)) return fqn; + const sep = fqn.lastIndexOf("::"); + if (sep < 0) return null; + const owner = fqn.slice(0, sep); + const method = fqn.slice(sep + 2); + for (const n of index.nodes) { + if (n.kind !== "callable" || n.name !== method) continue; + for (let cur = n.parent; cur; cur = index.nodeInfo[cur]?.parent ?? null) { + if (cur === owner) return n.fqn; + } + } + return null; +} + +/** + * The nearest enclosing structural node for a member/field FQN: drop trailing + * `::segment`s until one names a node. A field FQN like `M::Conv::id` isn't a node, + * so without this go-to-definition on a field would silently do nothing (PDS-GOTO-002). + */ +export function ownerNodeOf(index: ModelIndex, fqn: string): string | null { + let cur = fqn; + while (cur.includes("::")) { + cur = cur.slice(0, cur.lastIndexOf("::")); + if (index.nodeIndex.has(cur)) return cur; + } + return null; +} + +/** The structural ancestor chain (root system → … → the node), following `parent`. */ +export function ancestry(index: ModelIndex, fqn: string): string[] { + const chain: string[] = []; + const seen = new Set(); + let cur: string | null = fqn; + while (cur && index.nodeIndex.has(cur) && !seen.has(cur)) { + seen.add(cur); + chain.unshift(cur); + cur = index.nodeIndex.get(cur)?.node.parent ?? null; + } + return chain; +} + +/** A node's breadcrumb title: kind + simple name, falling back to the FQN leaf. */ +export function nodeTitle(index: ModelIndex, fqn: string): string { + const n = index.nodes.find((x) => x.fqn === fqn); + return n ? `${n.kind} \`${n.name}\`` : `\`${fqn.split("::").at(-1)}\``; +} + +/** A minimal single-lifeline sequence scene for a symbol with nothing to project. */ +export function singleLifelineScene(index: ModelIndex, fqn: string): Scene { + const node = index.nodeIndex.get(fqn)?.node; + return { + view: "sequence", + entry: fqn, + participants: [{ fqn, label: node?.name ?? fqn.split("::").at(-1), kind: node?.kind ?? "callable" }], + items: [], + }; +} + +/** The byte offset of a 1-based line/byte-column in `source` (col is a byte column). */ +export function nodeByteOffset(source: string, line: number, col: number): number { + const lines = source.split("\n"); + let charOffset = 0; + for (let i = 0; i < line - 1 && i < lines.length; i++) charOffset += lines[i].length + 1; + return charToByte(source, charOffset + Math.max(0, col - 1)); +} diff --git a/web-ide/src/lib/core/navigation.test.ts b/web-ide/src/lib/core/navigation.test.ts new file mode 100644 index 0000000..c13ee30 --- /dev/null +++ b/web-ide/src/lib/core/navigation.test.ts @@ -0,0 +1,74 @@ +import { describe, expect, it } from "vitest"; + +import { + canBack, + canForward, + HISTORY_CAP, + type NavState, + originLoc, + recordLocation, + samePosition, + stepBack, + stepForward, +} from "./navigation.js"; +import type { Loc } from "./types.js"; + +const at = (fileFqn: string, line: number, col = 1, label?: string): Loc => ({ fileFqn, line, col, label }); +const empty: NavState = { history: [], index: -1 }; + +describe("navigation history", () => { + it("records the first location at index 0", () => { + const s = recordLocation(empty, at("m", 1)); + expect(s).toEqual({ history: [at("m", 1)], index: 0 }); + }); + + it("collapses a repeat of the current location, refreshing its label", () => { + let s = recordLocation(empty, at("m", 1, 1, "old")); + s = recordLocation(s, at("m", 1, 1, "new")); + expect(s.history).toEqual([at("m", 1, 1, "new")]); + expect(s.index).toBe(0); + }); + + it("truncates the forward tail when recording after a back step", () => { + let s = recordLocation(empty, at("m", 1)); + s = recordLocation(s, at("m", 2)); + s = recordLocation(s, at("m", 3)); + s = stepBack(s)!.state; // index → 1 (at line 2) + s = recordLocation(s, at("m", 9)); // drops line 3 + expect(s.history.map((l) => l.line)).toEqual([1, 2, 9]); + expect(s.index).toBe(2); + }); + + it("caps the trail at HISTORY_CAP, dropping the oldest", () => { + let s = empty; + for (let i = 1; i <= HISTORY_CAP + 5; i++) s = recordLocation(s, at("m", i)); + expect(s.history).toHaveLength(HISTORY_CAP); + expect(s.history[0].line).toBe(6); // first 5 fell off + expect(s.index).toBe(HISTORY_CAP - 1); + }); + + it("gates back/forward at the boundaries", () => { + expect(canBack(empty)).toBe(false); + expect(canForward(empty)).toBe(false); + let s = recordLocation(empty, at("m", 1)); + s = recordLocation(s, at("m", 2)); + expect(canBack(s)).toBe(true); + expect(canForward(s)).toBe(false); // at the tip + const back = stepBack(s)!; + expect(back.loc.line).toBe(1); + expect(canForward(back.state)).toBe(true); + expect(stepForward(back.state)!.loc.line).toBe(2); + expect(stepBack(empty)).toBeNull(); + expect(stepForward(empty)).toBeNull(); + }); + + it("builds an origin label from the FQN leaf and line", () => { + expect(originLoc("pkg::Mod", 7, 3)).toEqual({ fileFqn: "pkg::Mod", line: 7, col: 3, label: "Mod:7" }); + }); + + it("compares positions by file/line/col, ignoring the label", () => { + expect(samePosition(at("m", 1, 2, "a"), at("m", 1, 2, "b"))).toBe(true); + expect(samePosition(at("m", 1, 2), at("m", 1, 3))).toBe(false); + expect(samePosition(undefined, at("m", 1))).toBe(false); + }); +}); diff --git a/web-ide/src/lib/core/navigation.ts b/web-ide/src/lib/core/navigation.ts new file mode 100644 index 0000000..c36043b --- /dev/null +++ b/web-ide/src/lib/core/navigation.ts @@ -0,0 +1,68 @@ +// Navigation history — a pure reducer over a visited-location trail. +// +// The view owns the impure half (opening files, jumping the editor, reading the +// caret); this module owns the trail math: recording with browser-history +// semantics (forward-tail truncation, repeat collapse, a bound), and stepping +// back/forward. No Svelte, no DOM. + +import type { Loc } from "./types.js"; + +// The history trail and the cursor into it. `index === -1` means empty. +export type NavState = { history: Loc[]; index: number }; + +// The maximum trail length kept; older entries fall off the front. +export const HISTORY_CAP = 50; + +/** Whether two locations point at the same file and caret position (label aside). */ +export function samePosition(a: Loc | undefined, b: Loc): boolean { + return !!a && a.fileFqn === b.fileFqn && a.line === b.line && a.col === b.col; +} + +/** + * Record a visited location. Drops any forward tail (a new jump invalidates + * "forward"), collapses a repeat of the current location (refreshing its label), + * and caps the trail. Returns the next state; never mutates the input. + */ +export function recordLocation(state: NavState, loc: Loc, cap = HISTORY_CAP): NavState { + const trail = state.history.slice(0, state.index + 1); + const last = trail.at(-1); + let history: Loc[]; + if (samePosition(last, loc)) { + history = [...trail.slice(0, -1), loc]; + } else { + history = [...trail, loc].slice(-cap); + } + return { history, index: history.length - 1 }; +} + +/** Whether a back step is available. */ +export function canBack(state: NavState): boolean { + return state.index > 0; +} + +/** Whether a forward step is available. */ +export function canForward(state: NavState): boolean { + return state.index >= 0 && state.index < state.history.length - 1; +} + +/** Step back one entry, returning the new state and the location to apply, or null. */ +export function stepBack(state: NavState): { state: NavState; loc: Loc } | null { + if (!canBack(state)) return null; + const index = state.index - 1; + return { state: { ...state, index }, loc: state.history[index] }; +} + +/** Step forward one entry, returning the new state and the location to apply, or null. */ +export function stepForward(state: NavState): { state: NavState; loc: Loc } | null { + if (!canForward(state)) return null; + const index = state.index + 1; + return { state: { ...state, index }, loc: state.history[index] }; +} + +/** + * The origin location to record before a jump, so Back returns to where the caret + * was. `fqn` is the open module's FQN; the label is its leaf name and line. + */ +export function originLoc(fqn: string, line: number, col: number): Loc { + return { fileFqn: fqn, line, col, label: `${fqn.split("::").at(-1)}:${line}` }; +} diff --git a/web-ide/src/lib/core/share.test.ts b/web-ide/src/lib/core/share.test.ts new file mode 100644 index 0000000..0356e50 --- /dev/null +++ b/web-ide/src/lib/core/share.test.ts @@ -0,0 +1,51 @@ +import { describe, expect, it } from "vitest"; + +import { mountedSources, parseHashPayload, snapshotWorkspace } from "./share.js"; +import type { SnapshotInput } from "./share.js"; + +describe("snapshotWorkspace", () => { + it("assembles files, manifest, and docs from live state", () => { + const input: SnapshotInput = { + name: "demo", + files: [{ path: "a.pds", fqn: "a" }], + moduleSources: { a: "public system S;" }, + manifestSource: "[package]\nname='demo'", + docGroups: [{ title: "G", items: [{ title: "Intro", path: "docs/intro.md" }] }], + docSources: { "docs/intro.md": "# Hi" }, + }; + expect(snapshotWorkspace(input)).toEqual({ + name: "demo", + manifestToml: "[package]\nname='demo'", + files: [{ path: "a.pds", fqn: "a", source: "public system S;" }], + docs: [{ path: "docs/intro.md", content: "# Hi" }], + }); + }); + + it("nulls an empty manifest and tolerates missing buffers", () => { + const snap = snapshotWorkspace({ + name: "x", + files: [{ fqn: "m" }], + moduleSources: {}, + manifestSource: "", + docGroups: [], + docSources: {}, + }); + expect(snap.manifestToml).toBeNull(); + expect(snap.files).toEqual([{ path: "", fqn: "m", source: "" }]); + }); +}); + +describe("mountedSources", () => { + it("keys decoded files by fqn", () => { + expect(mountedSources([{ fqn: "a", source: "x" }, { fqn: "b" }])).toEqual({ a: "x", b: "" }); + }); +}); + +describe("parseHashPayload", () => { + it("extracts the w= payload, or null", () => { + expect(parseHashPayload("#w=abc123")).toBe("abc123"); + expect(parseHashPayload("#foo&w=xyz&bar")).toBe("xyz"); + expect(parseHashPayload("#nothing")).toBeNull(); + expect(parseHashPayload("")).toBeNull(); + }); +}); diff --git a/web-ide/src/lib/core/share.ts b/web-ide/src/lib/core/share.ts new file mode 100644 index 0000000..3ee95d4 --- /dev/null +++ b/web-ide/src/lib/core/share.ts @@ -0,0 +1,48 @@ +// Share / export plumbing — pure assembly around the `codec` envelope. +// +// The view owns the impure edges (gzip via codec, clipboard, file download, +// `mountWorkspace`, URL hash mutation); this module owns the value transforms: +// snapshotting the live workspace into the serialisable shape, rebuilding the +// module buffers from a decoded workspace, and extracting the hash payload. + +import type { LiveDocGroup, OpenFile } from "./types.js"; + +// The live state a snapshot is assembled from. +export type SnapshotInput = { + name: string; + files: OpenFile[]; + moduleSources: Record; + manifestSource: string; + docGroups: LiveDocGroup[]; + docSources: Record; +}; + +// The serialisable workspace the codec envelope carries. +export type WorkspaceSnapshot = { + name: string; + manifestToml: string | null; + files: { path: string; fqn: string; source: string }[]; + docs: { path: string; content: string }[]; +}; + +/** Snapshot the live workspace (edits, manifest, docs) into the codec shape. */ +export function snapshotWorkspace(input: SnapshotInput): WorkspaceSnapshot { + const files = input.files.map((f) => ({ + path: f.path ?? "", + fqn: f.fqn ?? "", + source: input.moduleSources[f.fqn ?? ""] ?? "", + })); + const docs: { path: string; content: string }[] = []; + for (const g of input.docGroups) for (const it of g.items) docs.push({ path: it.path, content: input.docSources[it.path] ?? "" }); + return { name: input.name, manifestToml: input.manifestSource || null, files, docs }; +} + +/** Rebuild the in-memory module buffers from a decoded workspace's files. */ +export function mountedSources(files: { fqn?: string; source?: string }[]): Record { + return Object.fromEntries(files.map((f) => [f.fqn ?? "", f.source ?? ""])); +} + +/** The base64url `w=` payload in a URL hash, or null when absent. */ +export function parseHashPayload(hash: string): string | null { + return hash.match(/[#&]w=([^&]+)/)?.[1] ?? null; +} diff --git a/web-ide/src/lib/core/types.ts b/web-ide/src/lib/core/types.ts new file mode 100644 index 0000000..ea5917e --- /dev/null +++ b/web-ide/src/lib/core/types.ts @@ -0,0 +1,139 @@ +// Shared types for the framework-agnostic IDE core. +// +// Pure type declarations — no runtime, no Svelte. The view layer (`+page.svelte`, +// stores) and the pure `core/` modules both import from here, so a concern can be +// lifted out of the view without dragging Svelte or the WASM module with it. + +import type { Module, Occurrence, Scene } from "$lib/pds.js"; +import type { Depth, Info } from "$lib/sequence.js"; + +// Re-export the lib shapes the core builds on, so core modules import everything +// from one place (`$lib/core/types`) rather than reaching into each lib. +export type { Module, Occurrence, Scene, Depth, Info }; + +// A structural node listed by `outline`/`outlineModules`. The wasm payload carries +// `line`, `col`, and `parent` beyond `pds.ts`'s narrower `OutlineNode`. +export type StructureNode = { + fqn: string; + name: string; + kind: string; + triggered: boolean; + line: number; + col: number; + parent?: string | null; +}; + +// A structure node tagged with its declaring file's FQN. +export type Symbol = StructureNode & { fileFqn: string }; + +// A workspace diagnostic from `checkModules` (1-based positions), tagged with its +// owning module's FQN. +export type Problem = { + severity: string; + message: string; + start_line: number; + start_col: number; + end_line?: number; + end_col?: number; + code?: string; + file?: string; +}; + +// An open-file descriptor — a module, an authored doc page, or the manifest. The +// `isDoc`/`isManifest` discriminants gate which fields apply. +export type OpenFile = { + path?: string; + fqn?: string; + handle?: FileSystemFileHandle | null; + title?: string; + isDoc?: boolean; + isManifest?: boolean; + // A non-PDS companion file (editable text). `binary` ones show an inert + // placeholder (with `bytes`, the on-disk size) instead of the editor. + isOther?: boolean; + binary?: boolean; + bytes?: number; +}; + +// The live workspace: a real on-disk workspace or an in-memory sample/share. The +// superset of fields the view reads; on-disk-only fields optional. +export type WorkspaceModel = { + name: string; + files: OpenFile[]; + // Base-relative directories on disk (empty ones included). Absent for in-memory + // sample / share-link workspaces, where folders are implied by file paths. + dirs?: string[]; + manifestToml?: string | null; + root?: FileSystemDirectoryHandle | null; + base?: string; + manifest?: { handle?: FileSystemFileHandle | null; path: string } | null; + docs?: Record; + // Non-PDS companion files surfaced in the tree (editable text / inert binary). + // Absent for in-memory sample / share-link workspaces. + others?: OpenFile[]; +}; + +// A live doc sidebar item / group (handles optional for sample pages). +export type LiveDocItem = { title: string; path: string; handle?: FileSystemFileHandle | null }; +export type LiveDocGroup = { title: string; items: LiveDocItem[] }; + +// A code location recorded in / replayed from navigation history. +export type Loc = { fileFqn: string; line: number; col: number; label?: string; fqn?: string }; + +// The editor's imperative API, handed back via `onready`. Impure (DOM/CodeMirror) — +// held by the view/stores, injected into core only as plain values it returns. +export type EditorApi = { + goto: (line: number, col: number) => void; + location: () => { line: number; col: number } | null; + openSettings: () => void; +}; + +// A laid-out diagram scene + its positioned layout, or an error to show instead. +export type Canvas = { scene: Scene | null; layout?: Scene | null; error: string }; + +// The canvas find-usages popover: a reference list anchored at the pointer. +export type CanvasUsages = { name: string; items: Occurrence[]; x: number; y: number }; + +// The right-click menu, shared by the C4 graph and the sequence timeline. A +// target is the identity of the symbol clicked; a request opens the menu for it +// at the event point. A row carries its action plus optional adornments (a +// leading glyph, a trailing badge); a section is a rule-separated group of rows. +export type MenuTarget = { fqn: string; kind: string; label: string }; +export type MenuRequest = (target: MenuTarget, event: MouseEvent) => void; +export type MenuItem = { label: string; run: () => void; icon?: string; badge?: string }; +export type MenuSection = { label?: string; items: MenuItem[] }; + +// A FileTree name-prompt dialog config, and the destructive-confirm config. +export type Dialog = { + title: string; + label: string; + placeholder: string; + value: string; + confirmLabel: string; + hint: string; + validate: (name: string) => string | null; + run: (name: string) => void; +}; +export type ConfirmDialog = { title: string; message: string; confirmLabel?: string; run: () => void }; + +// A toast notification. +export type NoteKind = "success" | "error" | "info"; +export type Note = { id: number; kind: NoteKind; title: string; body: string }; + +// A pending debounced disk write. +export type PendingWrite = { handle: FileSystemFileHandle; key: string; text: string }; + +// The injected subset of `pds.ts` the core depends on. Passing this as a value +// (rather than importing `$lib/pds.js`) keeps core unit-testable with fakes and +// isolates the WASM lifecycle to one store. `outlineModules` is typed to the wider +// `StructureNode` the wasm payload actually carries (the `wasm` store adapts it). +export interface WasmApi { + checkModules: (modules: Module[]) => { fqn: string; diagnostics: Problem[] }[]; + outlineModules: (modules: Module[]) => StructureNode[]; + symbolScene: (modules: Module[], fqn: string) => Scene; + emitSceneModules: (modules: Module[], view: string, target?: string) => Scene; + layoutScene: (scene: Scene) => Scene; + hover: (modules: Module[], moduleFqn: string, offset: number) => unknown; + references: (modules: Module[], moduleFqn: string, offset: number) => unknown; + docManifest: (toml: string) => unknown; +} diff --git a/web-ide/src/lib/core/workspace-ops.test.ts b/web-ide/src/lib/core/workspace-ops.test.ts new file mode 100644 index 0000000..25bb42f --- /dev/null +++ b/web-ide/src/lib/core/workspace-ops.test.ts @@ -0,0 +1,118 @@ +import { describe, expect, it } from "vitest"; + +import { + danglingImporters, + docPathSet, + folderRenameClash, + normalizeDirPath, + normalizePdsPath, + pascalName, + pdsSkeleton, + remapDirs, + slugify, + validateNewDoc, + validateNewFile, + validateRename, + withBase, +} from "./workspace-ops.js"; +import type { OpenFile } from "./types.js"; + +describe("names & paths", () => { + it("pascalName camel-cases and defaults to Module", () => { + expect(pascalName("my-architecture")).toBe("MyArchitecture"); + expect(pascalName("billing_core")).toBe("BillingCore"); + expect(pascalName("")).toBe("Module"); + }); + + it("normalizePdsPath trims, strips leading slash, appends .pds", () => { + expect(normalizePdsPath(" /banking/core ")).toBe("banking/core.pds"); + expect(normalizePdsPath("a.pds")).toBe("a.pds"); + expect(normalizePdsPath("a.txt")).toBe("a.txt"); + }); + + it("slugify produces a clean url slug", () => { + expect(slugify("Release Notes!")).toBe("release-notes"); + expect(slugify(" --- ")).toBe(""); + }); + + it("withBase prefixes only when a base exists", () => { + expect(withBase("pkg", "a.pds")).toBe("pkg/a.pds"); + expect(withBase(undefined, "a.pds")).toBe("a.pds"); + }); + + it("pdsSkeleton emits a valid, drawable starter", () => { + const s = pdsSkeleton("billing"); + expect(s).toContain("//! billing"); + expect(s).toContain("public system Billing;"); + expect(s).toContain("public container Api for Billing"); + }); +}); + +describe("folders", () => { + it("normalizeDirPath trims segments and drops empties / .pds", () => { + expect(normalizeDirPath(" banking//adapters/ ")).toBe("banking/adapters"); + expect(normalizeDirPath("a\\b")).toBe("a/b"); + expect(normalizeDirPath("core.pds")).toBe("core"); + expect(normalizeDirPath(" ")).toBe(""); + }); + + it("folderRenameClash rejects self and nested-in/around targets", () => { + expect(folderRenameClash("a", "a")).toBe(true); // self + expect(folderRenameClash("a", "a/b")).toBe(true); // into own subtree + expect(folderRenameClash("a/b", "a")).toBe(true); // onto own ancestor + expect(folderRenameClash("a", "b")).toBe(false); // sibling — allowed + expect(folderRenameClash("ab", "a")).toBe(false); // prefix-but-not-segment + }); + + it("remapDirs re-points the folder and its subtree, leaving siblings", () => { + const dirs = ["a", "a/b", "a/bc", "other"]; + expect(remapDirs(dirs, "a", "x")).toEqual(["other", "x", "x/b", "x/bc"]); + // "a/bc" must not be mangled by the "a/b" prefix + expect(remapDirs(["a/b", "a/bc"], "a/b", "a/z")).toEqual(["a/bc", "a/z"]); + }); + + it("remapDirs always includes the new folder", () => { + expect(remapDirs([], "a", "x")).toEqual(["x"]); + }); +}); + +describe("validation", () => { + const files: OpenFile[] = [{ fqn: "a", path: "a.pds" }]; + + it("validateNewFile rejects empties, backslashes, .md, pds.toml, non-pds, dupes", () => { + expect(validateNewFile("", files, undefined)).toBe("Name can't be empty."); + expect(validateNewFile("a\\b", files, undefined)).toBe("Use forward slashes for folders."); + expect(validateNewFile("x/", files, undefined)).toBe("Name a file, not a folder."); + expect(validateNewFile("notes.md", files, undefined)).toBe("Use New doc for Markdown files."); + expect(validateNewFile("pds.toml", files, undefined)).toBe("pds.toml is reserved."); + expect(validateNewFile("x.rs", files, undefined)).toBe("Only .pds files are supported here."); + expect(validateNewFile("a", files, undefined)).toBe("A file with that path already exists."); + expect(validateNewFile("b", files, undefined)).toBeNull(); + }); + + it("validateRename allows the file's own path but rejects another's", () => { + const two: OpenFile[] = [{ fqn: "a", path: "a.pds" }, { fqn: "b", path: "b.pds" }]; + const a = two[0]; + expect(validateRename(a, "a", two, undefined)).toBeNull(); // unchanged + expect(validateRename(a, "b", two, undefined)).toBe("A file with that path already exists."); + }); + + it("validateNewDoc rejects empty/blank slug and collisions", () => { + const paths = new Set(["docs/intro.md"]); + expect(validateNewDoc("", paths)).toBe("Title can't be empty."); + expect(validateNewDoc("!!!", paths)).toBe("Title needs at least one letter or number."); + expect(validateNewDoc("Intro", paths)).toBe("A doc at docs/intro.md already exists."); + expect(validateNewDoc("Guide", paths)).toBeNull(); + }); + + it("docPathSet flattens sidebar paths", () => { + const set = docPathSet([{ title: "G", items: [{ title: "I", path: "docs/i.md" }] }]); + expect([...set]).toEqual(["docs/i.md"]); + }); + + it("danglingImporters finds modules still referencing the old fqn", () => { + const files2: OpenFile[] = [{ fqn: "a" }, { fqn: "b" }]; + const src = { a: "alias X = old::Thing", b: "public system S;" }; + expect(danglingImporters(files2, src, "new", "old::Thing")).toEqual(["a"]); + }); +}); diff --git a/web-ide/src/lib/core/workspace-ops.ts b/web-ide/src/lib/core/workspace-ops.ts new file mode 100644 index 0000000..7b023c5 --- /dev/null +++ b/web-ide/src/lib/core/workspace-ops.ts @@ -0,0 +1,150 @@ +// Workspace naming, path, and validation helpers — pure. +// +// The view passes in the current file set / base / doc paths rather than these +// reading global state, so each is a referentially-transparent function the unit +// tests can pin. No Svelte, no FS. + +import type { LiveDocGroup, OpenFile } from "./types.js"; + +/** A kebab/underscore name as a PascalCase identifier, defaulting to `Module`. */ +export function pascalName(s: string): string { + return ( + s + .replace(/[-_]+/g, " ") + .replace(/\b\w/g, (c) => c.toUpperCase()) + .replace(/\s+/g, "") || "Module" + ); +} + +/** The starter `.pds` module for a new file: a minimal valid, drawable model. */ +export function pdsSkeleton(fqn: string): string { + const leaf = fqn.split("::").pop() ?? ""; + const title = leaf.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()); + const sys = pascalName(leaf); + return `//! ${leaf} + +/// The ${title} system — describe this module's architecture here. +public system ${sys}; + +/// A first container. Add components, data, and callables beneath it. +public container Api for ${sys} { + /// A first behaviour. Replace with your own flows. + public Health(): void { + // Describe what happens here. + } +} +`; +} + +/** Normalise a typed name into a base-relative leaf path: trim, drop a leading + * slash, append `.pds` when no extension is given. */ +export function normalizePdsPath(name: string): string { + let p = name.trim().replace(/^\/+/, ""); + if (!/\.[a-z0-9]+$/i.test(p)) p += ".pds"; + return p; +} + +/** Normalise a typed folder path: trim each segment, drop empties and a stray + * `.pds`, and join with `/`. `" banking//adapters/ "` → `"banking/adapters"`. */ +export function normalizeDirPath(name: string): string { + return name + .trim() + .replace(/\\/g, "/") + .replace(/\.pds$/i, "") + .split("/") + .map((s) => s.trim()) + .filter(Boolean) + .join("/"); +} + +/** True when renaming folder `oldRel` to `newRel` is illegal because the target + * is the folder itself or nested in/around it — a move into your own subtree + * would delete what you just moved. */ +export function folderRenameClash(oldRel: string, newRel: string): boolean { + return newRel === oldRel || newRel.startsWith(`${oldRel}/`) || oldRel.startsWith(`${newRel}/`); +} + +/** Re-point a directory list when folder `oldRel` is renamed to `newRel`: the + * folder and everything under it move; the new path is guaranteed present. */ +export function remapDirs(dirs: string[], oldRel: string, newRel: string): string[] { + const prefix = `${oldRel}/`; + const mapped = dirs.map((d) => (d === oldRel ? newRel : d.startsWith(prefix) ? `${newRel}${d.slice(oldRel.length)}` : d)); + return Array.from(new Set([...mapped, newRel])).sort(); +} + +/** A doc title as a URL slug. */ +export function slugify(title: string): string { + return title + .trim() + .toLowerCase() + .replace(/[^a-z0-9]+/g, "-") + .replace(/^-+|-+$/g, ""); +} + +/** Prefix a base-relative path with the workspace base dir (the manifest dir). */ +export function withBase(base: string | undefined, rel: string): string { + return base ? `${base}/${rel}` : rel; +} + +/** Every doc path already in the live sidebar (base-relative). */ +export function docPathSet(docGroups: LiveDocGroup[]): Set { + const set = new Set(); + for (const g of docGroups) for (const it of g.items) set.add(it.path); + return set; +} + +/** Validate a new `.pds` path against the file set + reserved names. `/` is a + * directory separator; `\` and empty are rejected. Returns an error or null. */ +export function validateNewFile(name: string, files: OpenFile[], base: string | undefined): string | null { + const raw = name.trim(); + if (!raw) return "Name can't be empty."; + if (raw.includes("\\")) return "Use forward slashes for folders."; + if (raw.endsWith("/")) return "Name a file, not a folder."; + const lower = raw.toLowerCase(); + if (lower.endsWith(".md")) return "Use New doc for Markdown files."; + if (/(^|\/)pds\.toml$/i.test(raw)) return "pds.toml is reserved."; + if (/\.[a-z0-9]+$/i.test(raw) && !lower.endsWith(".pds")) return "Only .pds files are supported here."; + const path = withBase(base, normalizePdsPath(raw)); + if (files.some((f) => f.path === path)) return "A file with that path already exists."; + return null; +} + +/** Validate a rename target: like {@link validateNewFile}, but the file's own + * current path / unchanged name does not count as a collision. */ +export function validateRename( + file: OpenFile, + name: string, + files: OpenFile[], + base: string | undefined, +): string | null { + const err = validateNewFile(name, files, base); + if (!err) return null; + if (err === "A file with that path already exists.") { + const target = withBase(base, normalizePdsPath(name)); + if (!files.some((f) => f !== file && f.path === target)) return null; + } + return err; +} + +/** Validate a new doc title against the existing sidebar paths. */ +export function validateNewDoc(title: string, docPaths: Set): string | null { + const t = title.trim(); + if (!t) return "Title can't be empty."; + const slug = slugify(t); + if (!slug) return "Title needs at least one letter or number."; + if (docPaths.has(`docs/${slug}.md`)) return `A doc at docs/${slug}.md already exists.`; + return null; +} + +/** Modules whose source still references `oldFqn` after a rename — a warn-only + * signal (importers are not auto-rewritten). A verbatim substring test suffices. */ +export function danglingImporters( + files: OpenFile[], + moduleSources: Record, + newFqn: string, + oldFqn: string, +): string[] { + return files + .filter((f) => f.fqn !== newFqn && (moduleSources[f.fqn ?? ""] ?? "").includes(oldFqn)) + .map((f) => f.fqn ?? ""); +} diff --git a/web-ide/src/lib/errors.test.ts b/web-ide/src/lib/errors.test.ts new file mode 100644 index 0000000..92c8aa0 --- /dev/null +++ b/web-ide/src/lib/errors.test.ts @@ -0,0 +1,46 @@ +import { afterEach, describe, expect, it, vi } from "vitest"; + +import { CODES, clearErrorLog, errorLog, onError, reportError } from "./errors.js"; + +afterEach(() => { + clearErrorLog(); + vi.restoreAllMocks(); +}); + +describe("error registry", () => { + it("assigns every code a unique stable identifier", () => { + const codes = Object.values(CODES).map((d) => d.code); + expect(new Set(codes).size).toBe(codes.length); + for (const code of codes) expect(code).toMatch(/^PDS-[A-Z]+-\d{3}$/); + }); + + it("logs errors via console.error and warnings via console.warn", () => { + const err = vi.spyOn(console, "error").mockImplementation(() => {}); + const warn = vi.spyOn(console, "warn").mockImplementation(() => {}); + + reportError("GOTO_UNRESOLVED", "M::Ghost"); // severity: error + reportError("GOTO_MEMBER_FALLBACK", "M::Conv::id → M::Conv"); // severity: warn + + expect(err).toHaveBeenCalledTimes(1); + expect(warn).toHaveBeenCalledTimes(1); + expect(err.mock.calls[0][0]).toContain(CODES.GOTO_UNRESOLVED.code); + expect(err.mock.calls[0][0]).toContain("M::Ghost"); + }); + + it("retains reports in the ring buffer and notifies listeners", () => { + vi.spyOn(console, "error").mockImplementation(() => {}); + const seen: string[] = []; + const off = onError((r) => seen.push(r.code)); + + const report = reportError("WASM_CALL_FAILED", "definition: boom"); + + expect(report.code).toBe(CODES.WASM_CALL_FAILED.code); + expect(report.detail).toBe("definition: boom"); + expect(errorLog().at(-1)?.code).toBe(CODES.WASM_CALL_FAILED.code); + expect(seen).toEqual([CODES.WASM_CALL_FAILED.code]); + + off(); + reportError("WASM_CALL_FAILED", "again"); + expect(seen).toHaveLength(1); // unsubscribed + }); +}); diff --git a/web-ide/src/lib/errors.ts b/web-ide/src/lib/errors.ts new file mode 100644 index 0000000..07b437f --- /dev/null +++ b/web-ide/src/lib/errors.ts @@ -0,0 +1,122 @@ +// Central error-code registry for the IDE. +// +// Every recoverable failure or "nothing happened" path reports through here so +// the console carries a stable, greppable code (`PDS--`) instead of +// failing silently. Codes group by origin (GOTO, DIAGRAM, WASM, WORKSPACE), so +// a console scan reveals the failure pattern and where it came from. Reports are +// also retained in a small ring buffer (`errorLog`) for a future diagnostics +// view and for assertions in tests. + +export type Severity = "error" | "warn"; + +export interface ErrorDef { + // Stable wire identifier surfaced to the console — `PDS--`. + code: string; + // One-line description of the failure. + title: string; + severity: Severity; +} + +// The registry. Keys are the symbolic names used at call sites; `code` is the +// stable identifier. Add a new entry rather than reusing a code for a new cause +// — codes are how failures are correlated across sessions. +export const CODES = { + // ── Go-to-definition / navigation ────────────────────────────────────────── + GOTO_NO_SYMBOL: { + code: "PDS-GOTO-001", + title: "Go-to-definition found no resolvable symbol under the cursor", + severity: "warn", + }, + GOTO_MEMBER_FALLBACK: { + code: "PDS-GOTO-002", + title: "Go-to-definition landed on a member; navigated to its owner instead", + severity: "warn", + }, + GOTO_UNRESOLVED: { + code: "PDS-GOTO-003", + title: "Go-to-definition resolved to a symbol the navigator could not open", + severity: "error", + }, + GOTO_FILE_MISSING: { + code: "PDS-GOTO-004", + title: "Go-to-definition target's declaring file is not in the workspace", + severity: "error", + }, + + // ── Diagram projection / canvas ──────────────────────────────────────────── + DIAGRAM_PROJECTION_FAILED: { + code: "PDS-DIAGRAM-001", + title: "Symbol could not be projected to a diagram; using lifeline fallback", + severity: "warn", + }, + DIAGRAM_RENDER_FAILED: { + code: "PDS-DIAGRAM-002", + title: "Whole-model diagram could not be rendered", + severity: "error", + }, + + // ── Language-server (WASM) bridge ────────────────────────────────────────── + WASM_CALL_FAILED: { + code: "PDS-WASM-001", + title: "A language-server call threw", + severity: "error", + }, + + // ── Workspace / file IO ──────────────────────────────────────────────────── + WORKSPACE_IO_FAILED: { + code: "PDS-WORKSPACE-001", + title: "A workspace file operation failed", + severity: "error", + }, +} satisfies Record; + +export type CodeName = keyof typeof CODES; + +export interface ErrorReport extends ErrorDef { + // The symbolic registry key. + name: CodeName; + // Free-form specifics (the offending fqn, file, call name, …). + detail?: string; + // Structured context for inspection in the console / diagnostics view. + context?: Record; + // Epoch milliseconds the report was raised. + at: number; +} + +const RING_MAX = 200; +const ring: ErrorReport[] = []; +const listeners = new Set<(report: ErrorReport) => void>(); + +// Report a coded failure: logs to the console (error vs warn per the code), +// retains it in the ring buffer, and notifies listeners. Returns the report so +// callers can attach it to UI state. Never throws. +export function reportError(name: CodeName, detail?: string, context?: Record): ErrorReport { + const def = CODES[name]; + const report: ErrorReport = { ...def, name, detail, context, at: Date.now() }; + + ring.push(report); + if (ring.length > RING_MAX) ring.shift(); + + const line = `[${def.code}] ${def.title}${detail ? ` — ${detail}` : ""}`; + if (def.severity === "error") console.error(line, context ?? ""); + else console.warn(line, context ?? ""); + + for (const fn of listeners) fn(report); + return report; +} + +// The retained reports, oldest first — for a diagnostics view or test assertions. +export function errorLog(): readonly ErrorReport[] { + return ring; +} + +// Drop every retained report (used by tests and a future "clear" action). +export function clearErrorLog(): void { + ring.length = 0; +} + +// Subscribe to reports as they are raised. Returns an unsubscribe function. +export function onError(fn: (report: ErrorReport) => void): () => void { + listeners.add(fn); + return () => listeners.delete(fn); +} diff --git a/web-ide/src/lib/floating-edge.ts b/web-ide/src/lib/floating-edge.ts new file mode 100644 index 0000000..9b9b987 --- /dev/null +++ b/web-ide/src/lib/floating-edge.ts @@ -0,0 +1,67 @@ +// Floating-edge geometry: anchor an edge at the point where the straight line +// between two node centres crosses each node's border, rather than at a fixed +// handle. This gives the shortest visible connection and lets edges leave a card +// from whichever side faces the other node. Ported from Svelte Flow's floating- +// edges example, adapted to absolute node positions (parent offsets included). + +import { Position, type InternalNode } from "@xyflow/svelte"; + +type Rect = { x: number; y: number; w: number; h: number }; + +function rect(node: InternalNode): Rect { + return { + x: node.internals.positionAbsolute.x, + y: node.internals.positionAbsolute.y, + w: node.measured.width ?? 0, + h: node.measured.height ?? 0, + }; +} + +// Where the segment from `node`'s centre toward `other`'s centre meets node's +// border. Projects the centre-to-centre direction into the rectangle's +// normalised diagonal space, clamps it to the unit diamond (so it lands on an +// edge), then maps back — Svelte Flow's floating-edges intersection. +function intersection(node: Rect, other: Rect): { x: number; y: number } { + const halfW = node.w / 2; + const halfH = node.h / 2; + const cx = node.x + halfW; + const cy = node.y + halfH; + const ox = other.x + other.w / 2; + const oy = other.y + other.h / 2; + + // Direction to the other centre, rotated into the rectangle's diagonal axes. + const diagA = (ox - cx) / (2 * halfW) - (oy - cy) / (2 * halfH); + const diagB = (ox - cx) / (2 * halfW) + (oy - cy) / (2 * halfH); + const clamp = 1 / (Math.abs(diagA) + Math.abs(diagB) || 1); + const unitA = clamp * diagA; + const unitB = clamp * diagB; + return { x: halfW * (unitA + unitB) + cx, y: halfH * (-unitA + unitB) + cy }; +} + +// Which border the intersection sits on — drives the path's entry/exit direction. +function side(node: Rect, p: { x: number; y: number }): Position { + const nx = Math.round(node.x); + const ny = Math.round(node.y); + const px = Math.round(p.x); + const py = Math.round(p.y); + if (px <= nx + 1) return Position.Left; + if (px >= nx + node.w - 1) return Position.Right; + if (py <= ny + 1) return Position.Top; + return Position.Bottom; +} + +// The floating endpoints + their borders for a source→target pair. +export function getEdgeParams(source: InternalNode, target: InternalNode) { + const s = rect(source); + const t = rect(target); + const sp = intersection(s, t); + const tp = intersection(t, s); + return { + sx: sp.x, + sy: sp.y, + tx: tp.x, + ty: tp.y, + sourcePos: side(s, sp), + targetPos: side(t, tp), + }; +} diff --git a/web-ide/src/lib/flow-export.ts b/web-ide/src/lib/flow-export.ts new file mode 100644 index 0000000..77baf7d --- /dev/null +++ b/web-ide/src/lib/flow-export.ts @@ -0,0 +1,86 @@ +// Export a live svelte-flow canvas to a downloadable image. Captures the +// `.svelte-flow__viewport` DOM with html-to-image, so the output matches the +// canvas pixel-for-pixel (kind colours, cards, floating edges, lifelines). The +// viewport is re-framed to fit *every* node — independent of the current pan / +// zoom — using xyflow's pure bounds helpers, so the export is the whole diagram, +// not a screenshot of the visible region. + +import { getViewportForBounds, type Node, type Rect } from "@xyflow/svelte"; +import { toPng, toSvg } from "html-to-image"; + +export type ExportFormat = "png" | "svg"; + +// Frame bounds: keep the export legible without rendering an unbounded canvas. +const PADDING = 0.1; // fraction of the frame left as margin around the nodes +const MIN_ZOOM = 0.5; +const MAX_ZOOM = 2; +const MAX_EDGE = 4096; // cap the long edge (px) to bound memory +const PNG_PIXEL_RATIO = 2; // crisper raster on hi-dpi / when scaled up + +// The bounding rect of every node, in flow coordinates. Boundary views nest +// children under a parent with positions relative to it, so resolve each node's +// absolute position by summing its parent chain before measuring. (The standalone +// `getNodesBounds` can't resolve sub-flows without a nodeLookup; this can.) +function nodesBounds(nodes: Node[]): Rect { + const byId = new Map(nodes.map((n) => [n.id, n])); + let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity; + for (const n of nodes) { + let x = n.position?.x ?? 0; + let y = n.position?.y ?? 0; + for (let p = n.parentId ? byId.get(n.parentId) : undefined; p; p = p.parentId ? byId.get(p.parentId) : undefined) { + x += p.position?.x ?? 0; + y += p.position?.y ?? 0; + } + const w = n.measured?.width ?? n.width ?? 0; + const h = n.measured?.height ?? n.height ?? 0; + minX = Math.min(minX, x); + minY = Math.min(minY, y); + maxX = Math.max(maxX, x + w); + maxY = Math.max(maxY, y + h); + } + return { x: minX, y: minY, width: maxX - minX, height: maxY - minY }; +} + +// Whole-diagram pixel size from the node bounds, capped at MAX_EDGE while +// preserving aspect ratio. +function frameSize(width: number, height: number): { width: number; height: number } { + const scale = Math.min(1, MAX_EDGE / Math.max(width, height)); + return { width: Math.ceil(width * scale), height: Math.ceil(height * scale) }; +} + +/** + * Render the flow inside `container` to a PNG/SVG and trigger a browser download. + * `nodes` are the component's measured Svelte Flow nodes; `background` is a CSS + * colour painted behind the diagram. Rejects when the diagram has no nodes. + */ +export async function downloadDiagram( + container: HTMLElement, + nodes: Node[], + opts: { format: ExportFormat; filename: string; background: string }, +): Promise { + if (nodes.length === 0) throw new Error("nothing to export"); + + const viewport = container.querySelector(".svelte-flow__viewport"); + if (!viewport) throw new Error("diagram not ready"); + + const bounds = nodesBounds(nodes); + const { width, height } = frameSize(bounds.width, bounds.height); + const vp = getViewportForBounds(bounds, width, height, MIN_ZOOM, MAX_ZOOM, PADDING); + + const style = { + width: `${width}px`, + height: `${height}px`, + transform: `translate(${vp.x}px, ${vp.y}px) scale(${vp.zoom})`, + }; + const common = { backgroundColor: opts.background, width, height, style }; + + const dataUrl = + opts.format === "png" + ? await toPng(viewport, { ...common, pixelRatio: PNG_PIXEL_RATIO }) + : await toSvg(viewport, common); + + const a = document.createElement("a"); + a.href = dataUrl; + a.download = `${opts.filename}.${opts.format}`; + a.click(); +} diff --git a/web-ide/src/lib/keybindings.svelte.js b/web-ide/src/lib/keybindings.svelte.ts similarity index 78% rename from web-ide/src/lib/keybindings.svelte.js rename to web-ide/src/lib/keybindings.svelte.ts index 31d8afd..6ffbc0a 100644 --- a/web-ide/src/lib/keybindings.svelte.js +++ b/web-ide/src/lib/keybindings.svelte.ts @@ -6,9 +6,24 @@ const STORAGE_KEY = "pds.keybindings"; +// A single customisable command in the catalogue. +export interface Command { + id: string; + label: string; + key: string; + group: string; +} + +// A preset keymap: a baseline scheme mapping command ids to chords. +export interface Profile { + id: string; + label: string; + bindings: Record; +} + // One entry per customisable command. `key` is the default chord; `group` // buckets the rows in the settings UI. Array order is the display order. -export const COMMANDS = [ +export const COMMANDS: Command[] = [ { id: "triggerAutocomplete", label: "Trigger autocomplete", key: "Ctrl-Space", group: "Editing" }, { id: "acceptCompletion", label: "Accept completion", key: "Tab", group: "Editing" }, { id: "toggleComment", label: "Toggle line comment", key: "Mod-/", group: "Editing" }, @@ -21,13 +36,13 @@ export const COMMANDS = [ { id: "openSettings", label: "Keyboard shortcuts…", key: "Mod-,", group: "General" }, ]; -const DEFAULTS = Object.fromEntries(COMMANDS.map((c) => [c.id, c.key])); +const DEFAULTS: Record = Object.fromEntries(COMMANDS.map((c) => [c.id, c.key])); const PROFILE_KEY = "pds.keymap-profile"; // Preset keymaps mirroring the major IDEs, mapping our command set onto each // IDE's conventions. A profile sets the baseline scheme; per-command overrides // (recorded in Settings) layer on top and win. `default` uses DEFAULTS. -export const PROFILES = [ +export const PROFILES: Profile[] = [ { id: "default", label: "PseudoScript", bindings: {} }, { id: "vscode", @@ -65,21 +80,24 @@ export const PROFILES = [ // Load overrides, keeping only known ids with non-empty string chords (so a // stale or hand-edited entry can't poison the keymap). -function load() { +function load(): Record { try { - const obj = JSON.parse(localStorage.getItem(STORAGE_KEY) ?? "{}"); - const clean = {}; - for (const c of COMMANDS) if (typeof obj[c.id] === "string" && obj[c.id]) clean[c.id] = obj[c.id]; + const obj: Record = JSON.parse(localStorage.getItem(STORAGE_KEY) ?? "{}"); + const clean: Record = {}; + for (const c of COMMANDS) { + const v = obj[c.id]; + if (typeof v === "string" && v) clean[c.id] = v; + } return clean; } catch { return {}; } } -function loadProfile() { +function loadProfile(): string { try { const id = localStorage.getItem(PROFILE_KEY); - return PROFILES.some((p) => p.id === id) ? id : "default"; + return id !== null && PROFILES.some((p) => p.id === id) ? id : "default"; } catch { return "default"; } @@ -88,20 +106,20 @@ function loadProfile() { // Reactive state and a change counter the editor watches. Overrides hold only // genuine customisations (resetting an id deletes its entry); `profile` is the // active preset's id. -const overrides = $state(load()); -let profile = $state(loadProfile()); -let version = $state(0); +const overrides: Record = $state(load()); +let profile: string = $state(loadProfile()); +let version: number = $state(0); // The active profile's bindings (empty for `default`). -function profileBindings() { +function profileBindings(): Record { return PROFILES.find((p) => p.id === profile)?.bindings ?? {}; } // The baseline chord for a command under the active profile (before overrides). -function base(id) { +function base(id: string): string { return profileBindings()[id] ?? DEFAULTS[id]; } -function persist() { +function persist(): void { try { if (Object.keys(overrides).length) localStorage.setItem(STORAGE_KEY, JSON.stringify(overrides)); else localStorage.removeItem(STORAGE_KEY); @@ -123,31 +141,31 @@ export const keybindings = { }, // Effective chord for a command id: a personal override wins over the active // profile's binding, which wins over the built-in default. - keyFor(id) { + keyFor(id: string): string { return overrides[id] ?? base(id); }, // The profile baseline a reset returns to (no personal override). - defaultFor(id) { + defaultFor(id: string): string { return base(id); }, - isCustom(id) { + isCustom(id: string): boolean { return id in overrides; }, // The command id currently bound to `chord`, ignoring `exceptId` — for // conflict detection in the settings UI. - conflict(chord, exceptId) { + conflict(chord: string, exceptId: string): string | null { for (const c of COMMANDS) { if (c.id !== exceptId && (overrides[c.id] ?? base(c.id)) === chord) return c.id; } return null; }, - setKey(id, chord) { + setKey(id: string, chord: string): void { if (!chord || chord === base(id)) delete overrides[id]; else overrides[id] = chord; version += 1; persist(); }, - reset(id) { + reset(id: string): void { delete overrides[id]; version += 1; persist(); @@ -155,14 +173,14 @@ export const keybindings = { // Switch the baseline preset. Personal overrides are kept and stay layered on // top (use resetAll for a pure profile). Overrides that happen to match the // new profile's binding are pruned so they don't show as customised. - setProfile(id) { + setProfile(id: string): void { if (!PROFILES.some((p) => p.id === id)) return; profile = id; for (const k of Object.keys(overrides)) if (overrides[k] === base(k)) delete overrides[k]; version += 1; persist(); }, - resetAll() { + resetAll(): void { for (const k of Object.keys(overrides)) delete overrides[k]; version += 1; persist(); @@ -171,14 +189,14 @@ export const keybindings = { // Build a CodeMirror key string from a keydown event. Returns null for a lone // modifier press, so the recorder waits for the real key. -export function chordFromEvent(e) { +export function chordFromEvent(e: KeyboardEvent): string | null { if (e.key === "Control" || e.key === "Alt" || e.key === "Shift" || e.key === "Meta") return null; - const parts = []; + const parts: string[] = []; if (e.ctrlKey) parts.push("Ctrl"); if (e.altKey) parts.push("Alt"); if (e.metaKey) parts.push("Cmd"); if (e.shiftKey) parts.push("Shift"); - let key; + let key: string; if (e.key === " ") key = "Space"; else if (e.key.length === 1) key = e.key.toLowerCase(); else key = e.key; // named keys already match CodeMirror: F12, Tab, Enter, ArrowUp… @@ -186,7 +204,7 @@ export function chordFromEvent(e) { return parts.join("-"); } -const SYMBOLS = { +const SYMBOLS: Record = { Mod: "⌘", Cmd: "⌘", Meta: "⌘", @@ -205,13 +223,13 @@ const SYMBOLS = { // Pretty-print a chord for display: "Mod-Alt-l" → "⌘ ⌥ L". Multi-stroke // sequences (space-separated, e.g. "Mod-k Mod-s") render each stroke joined by a // thin gap: "⌘ K ⌘ S". -export function formatChord(chord) { +export function formatChord(chord: string): string { return chord .split(" ") - .map((stroke) => + .map((stroke: string) => stroke .split("-") - .map((p) => SYMBOLS[p] ?? (p.length === 1 ? p.toUpperCase() : p)) + .map((p: string) => SYMBOLS[p] ?? (p.length === 1 ? p.toUpperCase() : p)) .join(" "), ) .join(" "); diff --git a/web-ide/src/lib/markdown-live.js b/web-ide/src/lib/markdown-live.ts similarity index 85% rename from web-ide/src/lib/markdown-live.js rename to web-ide/src/lib/markdown-live.ts index c1d8ace..40987ed 100644 --- a/web-ide/src/lib/markdown-live.js +++ b/web-ide/src/lib/markdown-live.ts @@ -15,7 +15,10 @@ import { GFM } from "@lezer/markdown"; import { HighlightStyle, syntaxHighlighting, syntaxTree } from "@codemirror/language"; import { tags as t } from "@lezer/highlight"; import { StateField } from "@codemirror/state"; +import type { EditorState, Extension, Range } from "@codemirror/state"; import { Decoration, EditorView, ViewPlugin, WidgetType } from "@codemirror/view"; +import type { DecorationSet, ViewUpdate } from "@codemirror/view"; +import type { SyntaxNodeRef } from "@lezer/common"; // A hidden syntax marker (`#`, `**`, brackets, …): replaced by nothing. const hide = Decoration.replace({}); @@ -46,13 +49,13 @@ const codeHighlightStyle = HighlightStyle.define([ // prose font, so a wrapped item hangs precisely under its text. Measured with a // canvas rather than approximated in `ch` (the proportional font's marker is // narrower than a `0`, which overshot). Cached per font+prefix. -let measureCtx = null; -const widthCache = new Map(); -function prefixWidthPx(font, prefix) { +let measureCtx: CanvasRenderingContext2D | null = null; +const widthCache = new Map(); +function prefixWidthPx(font: string, prefix: string): number { const key = `${font}|${prefix}`; let w = widthCache.get(key); if (w === undefined) { - if (!measureCtx) measureCtx = document.createElement("canvas").getContext("2d"); + if (!measureCtx) measureCtx = document.createElement("canvas").getContext("2d")!; measureCtx.font = font; w = measureCtx.measureText(prefix).width; widthCache.set(key, w); @@ -61,7 +64,7 @@ function prefixWidthPx(font, prefix) { } // Inline spans styled in place; their markers are hidden separately. -const INLINE = { +const INLINE: Record = { StrongEmphasis: Decoration.mark({ class: "cm-md-strong" }), Emphasis: Decoration.mark({ class: "cm-md-em" }), Strikethrough: Decoration.mark({ class: "cm-md-strike" }), @@ -74,28 +77,28 @@ const INLINE_MARKS = new Set(["EmphasisMark", "StrikethroughMark", "CodeMark", " // A rendered horizontal rule, shown in place of `---`/`***` when off the line. class RuleWidget extends WidgetType { - toDOM() { + toDOM(): HTMLElement { const hr = document.createElement("hr"); hr.className = "cm-md-hr"; return hr; } - ignoreEvent() { + ignoreEvent(): boolean { return false; } } // A bullet glyph rendered in place of a `-`/`*`/`+` list marker. class BulletWidget extends WidgetType { - eq() { + eq(): boolean { return true; } - toDOM() { + toDOM(): HTMLElement { const dot = document.createElement("span"); dot.className = "cm-md-bullet"; dot.textContent = "•"; return dot; } - ignoreEvent() { + ignoreEvent(): boolean { return false; } } @@ -103,27 +106,30 @@ class BulletWidget extends WidgetType { // A checkbox rendered in place of a `- [ ]` / `- [x]` task prefix. Toggling it // rewrites the marker in the document. class TaskWidget extends WidgetType { - constructor(checked, from, to) { + readonly checked: boolean; + readonly from: number; + readonly to: number; + constructor(checked: boolean, from: number, to: number) { super(); this.checked = checked; this.from = from; this.to = to; } - eq(o) { + eq(o: TaskWidget): boolean { return o.checked === this.checked && o.from === this.from && o.to === this.to; } - toDOM(view) { + toDOM(view: EditorView): HTMLElement { const box = document.createElement("input"); box.type = "checkbox"; box.className = "cm-md-task"; box.checked = this.checked; - box.addEventListener("mousedown", (e) => e.preventDefault()); + box.addEventListener("mousedown", (e: MouseEvent) => e.preventDefault()); box.addEventListener("change", () => { view.dispatch({ changes: { from: this.from, to: this.to, insert: this.checked ? "[ ]" : "[x]" } }); }); return box; } - ignoreEvent() { + ignoreEvent(): boolean { return true; } } @@ -132,15 +138,17 @@ class TaskWidget extends WidgetType { // when the cursor is outside the table. Clicking it (off a link) drops the // cursor in to edit the source. class TableWidget extends WidgetType { - constructor(text, from) { + readonly text: string; + readonly from: number; + constructor(text: string, from: number) { super(); this.text = text; this.from = from; } - eq(o) { + eq(o: TableWidget): boolean { return o.text === this.text && o.from === this.from; } - toDOM(view) { + toDOM(view: EditorView): HTMLElement { const rows = this.text.split("\n").filter((l) => l.trim().length); const aligns = parseAligns(rows[1] || ""); const table = document.createElement("table"); @@ -154,47 +162,52 @@ class TableWidget extends WidgetType { for (let r = 2; r < rows.length; r += 1) body.appendChild(buildRow(rows[r], "td", aligns)); table.appendChild(body); - table.addEventListener("mousedown", (e) => { - if (e.target.closest("a")) return; // let links open + table.addEventListener("mousedown", (e: MouseEvent) => { + const target = e.target; + if (target instanceof Element && target.closest("a")) return; // let links open e.preventDefault(); view.dispatch({ selection: { anchor: this.from }, scrollIntoView: true }); view.focus(); }); return table; } - ignoreEvent() { + ignoreEvent(): boolean { return false; } } -/** Splits a table row on unescaped `|`, unescaping `\|` in each cell. */ -function splitPipes(s) { +// Per-column text alignment parsed from a table's delimiter row. +type ColAlign = "left" | "right" | "center" | null; + +// Splits a table row on unescaped `|`, unescaping `\|` in each cell. +function splitPipes(s: string): string[] { return s.split(/(? c.replace(/\\\|/g, "|")); } -/** A table line's cells: trimmed, with the outer pipes dropped. */ -function cellsOf(line) { +// A table line's cells: trimmed, with the outer pipes dropped. +function cellsOf(line: string): string[] { let s = line.trim(); if (s.startsWith("|")) s = s.slice(1); if (s.endsWith("|")) s = s.slice(0, -1); return splitPipes(s).map((c) => c.trim()); } -/** Per-column alignment from a `|:--|:-:|--:|` delimiter row. */ -function parseAligns(delim) { - return cellsOf(delim).map((c) => { +// Per-column alignment from a `|:--|:-:|--:|` delimiter row. +function parseAligns(delim: string): ColAlign[] { + return cellsOf(delim).map((c): ColAlign => { const l = c.startsWith(":"); const r = c.endsWith(":"); return l && r ? "center" : r ? "right" : l ? "left" : null; }); } -/** Builds a `` of ``/`` cells with inline Markdown rendered. */ -function buildRow(line, tag, aligns) { +// Builds a `` of ``/`` cells with inline Markdown rendered. +function buildRow(line: string, tag: "th" | "td", aligns: ColAlign[]): HTMLTableRowElement { const tr = document.createElement("tr"); cellsOf(line).forEach((text, i) => { const cell = document.createElement(tag); - if (aligns[i]) cell.style.textAlign = aligns[i]; + const align = aligns[i]; + if (align) cell.style.textAlign = align; renderInline(text, cell); tr.appendChild(cell); }); @@ -206,7 +219,7 @@ function buildRow(line, tag, aligns) { // strikethrough and links — enough for table cells; nesting is not expanded. const INLINE_RE = /(`[^`]+`)|(\*\*[^*]+\*\*)|(__[^_]+__)|(~~[^~]+~~)|(\*[^*]+\*)|(_[^_]+_)|(\[[^\]]+\]\([^)]+\))/; -function renderInline(text, el) { +function renderInline(text: string, el: HTMLElement): void { let rest = text; while (rest) { const m = INLINE_RE.exec(rest); @@ -216,7 +229,7 @@ function renderInline(text, el) { } if (m.index > 0) el.appendChild(document.createTextNode(rest.slice(0, m.index))); const tok = m[0]; - let node; + let node: HTMLElement; if (tok.startsWith("`")) { node = document.createElement("code"); node.className = "cm-md-code"; @@ -231,14 +244,15 @@ function renderInline(text, el) { node.textContent = tok.slice(2, -2); } else if (tok.startsWith("[")) { const lm = /^\[([^\]]+)\]\(([^)]+)\)$/.exec(tok); - node = document.createElement("a"); - node.className = "cm-md-link"; - node.textContent = lm[1]; - if (/^(https?:|mailto:|\/|#)/i.test(lm[2])) { - node.href = lm[2]; - node.target = "_blank"; - node.rel = "noreferrer"; + const a = document.createElement("a"); + a.className = "cm-md-link"; + a.textContent = lm ? lm[1] : tok; + if (lm && /^(https?:|mailto:|\/|#)/i.test(lm[2])) { + a.href = lm[2]; + a.target = "_blank"; + a.rel = "noreferrer"; } + node = a; } else { node = document.createElement("em"); node.className = "cm-md-em"; @@ -257,33 +271,35 @@ const CALLOUT_LABEL = { important: "Important", warning: "Warning", caution: "Caution", -}; +} as const; +type CalloutKind = keyof typeof CALLOUT_LABEL; const CALLOUT_RE = /^\s*>\s?\[!(\w+)\]/i; -/** The callout kind a blockquote's first line declares, or `null`. */ -function calloutKind(lineText) { +// The callout kind a blockquote's first line declares, or `null`. +function calloutKind(lineText: string): CalloutKind | null { const m = CALLOUT_RE.exec(lineText); const kind = m && m[1].toLowerCase(); - return kind && Object.hasOwn(CALLOUT_LABEL, kind) ? kind : null; + return kind && Object.hasOwn(CALLOUT_LABEL, kind) ? (kind as CalloutKind) : null; } // The rendered callout title (the coloured "Note"/"Warning"/… label) shown in // place of the `[!KIND]` marker when the cursor is off its line. class CalloutTitleWidget extends WidgetType { - constructor(kind) { + readonly kind: CalloutKind; + constructor(kind: CalloutKind) { super(); this.kind = kind; } - eq(o) { + eq(o: CalloutTitleWidget): boolean { return o.kind === this.kind; } - toDOM() { + toDOM(): HTMLElement { const span = document.createElement("span"); span.className = "cm-md-callout-title"; span.textContent = CALLOUT_LABEL[this.kind]; return span; } - ignoreEvent() { + ignoreEvent(): boolean { return false; } } @@ -291,17 +307,18 @@ class CalloutTitleWidget extends WidgetType { // Builds the decoration set for the visible ranges. The document is unchanged; // only its rendering is decorated. A marker reveals when a selection range // touches its "reveal range" (the heading line, the inline span, the rule line). -function decorate(view) { - const decos = []; +function decorate(view: EditorView): DecorationSet { + const decos: Range[] = []; const { state } = view; const sel = state.selection; - const touches = (from, to) => sel.ranges.some((r) => r.from <= to && r.to >= from); + const touches = (from: number, to: number): boolean => + sel.ranges.some((r) => r.from <= to && r.to >= from); for (const visible of view.visibleRanges) { syntaxTree(state).iterate({ from: visible.from, to: visible.to, - enter: (node) => { + enter: (node: SyntaxNodeRef): boolean | void => { const name = node.name; // ---- block headings: style the whole line, hide the leading `#`s ---- @@ -323,8 +340,9 @@ function decorate(view) { } // ---- inline spans: style in place ---- - if (INLINE[name]) { - if (node.from < node.to) decos.push(INLINE[name].range(node.from, node.to)); + const inlineMark = INLINE[name]; + if (inlineMark) { + if (node.from < node.to) decos.push(inlineMark.range(node.from, node.to)); return; } @@ -463,10 +481,11 @@ function decorate(view) { const livePreviewPlugin = ViewPlugin.fromClass( class { - constructor(view) { + decorations: DecorationSet; + constructor(view: EditorView) { this.decorations = decorate(view); } - update(u) { + update(u: ViewUpdate): void { if (u.docChanged || u.viewportChanged || u.selectionSet) { this.decorations = decorate(u.view); } @@ -478,12 +497,13 @@ const livePreviewPlugin = ViewPlugin.fromClass( // Block-level decorations (the rendered tables) must come from a state field, // not a plugin. Walks the whole document — fine for doc-sized files. A table // shows its pipe source while the cursor is inside it, the otherwise. -function buildTables(state) { - const decos = []; +function buildTables(state: EditorState): DecorationSet { + const decos: Range[] = []; const sel = state.selection; - const touches = (from, to) => sel.ranges.some((r) => r.from <= to && r.to >= from); + const touches = (from: number, to: number): boolean => + sel.ranges.some((r) => r.from <= to && r.to >= from); syntaxTree(state).iterate({ - enter: (node) => { + enter: (node: SyntaxNodeRef): boolean | void => { if (node.name !== "Table") return; if (touches(node.from, node.to)) return false; // editing: show source const first = state.doc.lineAt(node.from); @@ -592,11 +612,15 @@ const livePreviewTheme = EditorView.baseTheme({ }, }); +// Options for the Markdown live-preview bundle. Reserved for future tuning; +// no fields are read yet. +export interface MarkdownLivePreviewOptions {} + /** * The Markdown live-preview bundle: GFM-aware parsing, the in-place render * decorations, and their theme. Drop into a CodeMirror editor's extensions. */ -export function markdownLivePreview(opts = {}) { +export function markdownLivePreview(opts: MarkdownLivePreviewOptions = {}): Extension[] { return [ // `codeLanguages` nests real language parsers into fenced blocks; `languages` // lazy-loads each on first use, so the initial bundle stays small. diff --git a/web-ide/src/lib/offsets.test.ts b/web-ide/src/lib/offsets.test.ts new file mode 100644 index 0000000..d3a7aca --- /dev/null +++ b/web-ide/src/lib/offsets.test.ts @@ -0,0 +1,46 @@ +import { describe, expect, it } from "vitest"; + +import { byteToChar, charToByte } from "./offsets.js"; + +// The compiler reports UTF-8 byte offsets; CodeMirror counts UTF-16 code units. +// These conversions back the semantic-highlight and fold decorations, so a +// rounding error mis-places every colour. ASCII coincides; multi-byte diverges. +describe("offsets", () => { + it("is the identity for pure-ASCII source", () => { + const src = "system S { run() {} }"; + for (let i = 0; i <= src.length; i++) { + expect(byteToChar(src, i)).toBe(i); + expect(charToByte(src, i)).toBe(i); + } + }); + + it("accounts for a multi-byte character (é = 2 bytes)", () => { + const src = "café = 1"; // 'é' is 2 UTF-8 bytes, 1 code unit + // char index 4 (the space after café) sits at byte 5. + expect(charToByte(src, 4)).toBe(5); + expect(byteToChar(src, 5)).toBe(4); + }); + + it("round-trips char → byte → char across a multi-byte string", () => { + const src = "α: number // δ"; // α and δ are 2 bytes each + for (let i = 0; i <= src.length; i++) { + expect(byteToChar(src, charToByte(src, i))).toBe(i); + } + }); + + it("handles an astral character (😀 = 4 bytes, 2 code units)", () => { + const src = "x😀y"; + expect(charToByte(src, 0)).toBe(0); + expect(charToByte(src, 1)).toBe(1); // after 'x' + expect(charToByte(src, 3)).toBe(5); // after the surrogate pair + expect(byteToChar(src, 5)).toBe(3); + }); + + it("clamps out-of-range offsets to the bounds", () => { + const src = "abc"; + expect(byteToChar(src, -4)).toBe(0); + expect(byteToChar(src, 99)).toBe(3); + expect(charToByte(src, -1)).toBe(0); + expect(charToByte(src, 99)).toBe(3); + }); +}); diff --git a/web-ide/src/lib/offsets.js b/web-ide/src/lib/offsets.ts similarity index 78% rename from web-ide/src/lib/offsets.js rename to web-ide/src/lib/offsets.ts index 2f9a51f..607c5c3 100644 --- a/web-ide/src/lib/offsets.js +++ b/web-ide/src/lib/offsets.ts @@ -6,16 +6,13 @@ /** * Converts a UTF-8 byte offset into `source` to a UTF-16 code-unit offset. * Clamps to the document length. - * @param {string} source - * @param {number} byteOffset - * @returns {number} */ -export function byteToChar(source, byteOffset) { +export function byteToChar(source: string, byteOffset: number): number { if (byteOffset <= 0) return 0; let bytes = 0; for (let i = 0; i < source.length; i++) { if (bytes >= byteOffset) return i; - const code = source.codePointAt(i); + const code = source.codePointAt(i) ?? 0; bytes += utf8Len(code); // Surrogate pair: codePointAt consumed two code units. if (code > 0xffff) i++; @@ -27,15 +24,12 @@ export function byteToChar(source, byteOffset) { * Converts a UTF-16 code-unit offset into `source` to a UTF-8 byte offset — the * inverse of {@link byteToChar}, for handing an editor position to the compiler. * Clamps to the document's byte length. - * @param {string} source - * @param {number} charOffset - * @returns {number} */ -export function charToByte(source, charOffset) { +export function charToByte(source: string, charOffset: number): number { if (charOffset <= 0) return 0; let bytes = 0; for (let i = 0; i < source.length && i < charOffset; i++) { - const code = source.codePointAt(i); + const code = source.codePointAt(i) ?? 0; bytes += utf8Len(code); if (code > 0xffff) i++; // surrogate pair: two code units, one code point } @@ -43,7 +37,7 @@ export function charToByte(source, charOffset) { } /** UTF-8 byte length of a single Unicode code point. */ -function utf8Len(code) { +function utf8Len(code: number): number { if (code <= 0x7f) return 1; if (code <= 0x7ff) return 2; if (code <= 0xffff) return 3; diff --git a/web-ide/src/lib/pds-wasm/pseudoscript_wasm.d.ts b/web-ide/src/lib/pds-wasm/pseudoscript_wasm.d.ts index dcd7492..abca1b6 100644 --- a/web-ide/src/lib/pds-wasm/pseudoscript_wasm.d.ts +++ b/web-ide/src/lib/pds-wasm/pseudoscript_wasm.d.ts @@ -21,6 +21,21 @@ export function check(source: string): string; */ export function check_modules(modules_json: string): string; +/** + * Context-aware completion at `offset` (a byte offset) in module `module_fqn`, + * as a JSON array of LSP `CompletionItem`s (`{label, kind, detail}`, where + * `kind` is the integer `CompletionItemKind`). Scoped to the trigger before the + * caret (`.`/`::`/`#[`/type-position/general); the client filters against the + * typed prefix. Served by the shared [`pseudoscript_lsp_core::complete`] — + * identical to the stdio server's `textDocument/completion`. `modules_json` is + * the `[{fqn, source}]` workspace shape. + * + * # Errors + * + * Returns an error when `modules_json` is not valid JSON of the expected shape. + */ +export function completion(modules_json: string, module_fqn: string, offset: number): string; + /** * Resolves the symbol under `offset` (a byte offset) in module `module_fqn` to * the FQN of its declaration, for go-to-definition. Returns the FQN as a JSON @@ -91,6 +106,15 @@ export function emit_scene_modules(modules_json: string, view: string, target: s */ export function emit_svg(source: string, view: string, target: string): string; +/** + * Foldable regions of `source` as the JSON of an LSP `FoldingRange` array + * (`{ startLine, endLine, kind }`, 0-based lines) — every multi-line + * declaration and statement block. Identical to the stdio server's + * `textDocument/foldingRange` response; the editor folds these instead of + * brace-matching in JS. + */ +export function folding_ranges(source: string): string; + /** * Formats `source` into its canonical form. * @@ -102,16 +126,14 @@ export function emit_svg(source: string, view: string, target: string): string; export function format(source: string): string; /** - * Resolves the symbol under `offset` (a byte offset) in module `module_fqn` - * and returns it as JSON `{ info: { fqn, title, body }, svg }`, or `null` when - * the cursor rests on no resolvable symbol. `svg` is the symbol's fitting - * diagram ([`project_symbol`]) rendered to a self-contained string — a sequence - * trace for a callable, a structural view for a node. `modules_json` is the + * Resolves the symbol under `offset` (a byte offset) in module `module_fqn` and + * returns it as an LSP `Hover` (`{ contents: { kind, value }, range }`, + * Markdown), or `null` when the cursor rests on no resolvable symbol. Served by + * the shared [`pseudoscript_lsp_core::analysis::hover`] — identical to the + * stdio server's `textDocument/hover`, no diagram. The interactive diagram is a + * separate concern: [`symbol_scene`] / [`symbol_svg`]. `modules_json` is the * `[{fqn, source}]` workspace shape. * - * The host (an editor hover) shows the info and diagram together; it never - * decides which diagram a symbol gets — the compiler does. - * * # Errors * * Returns an error when `modules_json` is not valid JSON of the expected shape. @@ -170,6 +192,22 @@ export function parse(source: string): string; */ export function references(modules_json: string, module_fqn: string, offset: number): string; +/** + * Renames the symbol under `offset` in module `module_fqn` to `new_name`, + * applying only the occurrences in `selected_json` — a JSON array of + * `{fqn, line, col}` (1-based, matching [`references`]'s occurrence positions). + * Returns JSON `[{ fqn, source }]`: the new full source of every module that + * changed. The host swaps these into its buffers. The substitution is done here + * (over UTF-8 byte spans) so the host never does offset math. Occurrence spans + * come from the shared [`pseudoscript_lsp_core::refs::rename`]. + * + * # Errors + * + * Returns an error when `new_name` is not a valid identifier, or when either + * JSON argument is malformed. + */ +export function rename_apply(modules_json: string, module_fqn: string, offset: number, new_name: string, selected_json: string): string; + /** * Renders the whole documentation site for a workspace, exactly as the CLI's * `pds doc` does, driving server-side rendering through the host's JavaScript @@ -187,6 +225,15 @@ export function references(modules_json: string, module_fqn: string, offset: num */ export function render_doc_site(modules_json: string, config_json: string, render: Function): string; +/** + * AST-aware semantic tokens for `source`, as the JSON of an LSP + * `SemanticTokens` (the delta-encoded `data` array over UTF-16 positions; the + * `token_type` field indexes the [`pseudoscript_lsp_core::semantic`] legend). + * Identical to the stdio server's `textDocument/semanticTokens/full` response — + * the editor decodes and decorates it, replacing any hand-written tokenizer. + */ +export function semantic_tokens(source: string): string; + /** * Routes Rust panics to the browser console with a readable stack. Runs once * on module instantiation (wasm only). @@ -230,12 +277,14 @@ export interface InitOutput { readonly memory: WebAssembly.Memory; readonly check: (a: number, b: number) => [number, number]; readonly check_modules: (a: number, b: number) => [number, number, number, number]; + readonly completion: (a: number, b: number, c: number, d: number, e: number) => [number, number, number, number]; readonly definition: (a: number, b: number, c: number, d: number, e: number) => [number, number, number, number]; readonly doc_manifest: (a: number, b: number) => [number, number, number, number]; readonly doc_ssr_bundle: () => [number, number]; readonly emit_scene: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number]; readonly emit_scene_modules: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number]; readonly emit_svg: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number]; + readonly folding_ranges: (a: number, b: number) => [number, number]; readonly format: (a: number, b: number) => [number, number, number, number]; readonly hover: (a: number, b: number, c: number, d: number, e: number) => [number, number, number, number]; readonly layout_scene: (a: number, b: number) => [number, number, number, number]; @@ -243,7 +292,9 @@ export interface InitOutput { readonly outline_modules: (a: number, b: number) => [number, number, number, number]; readonly parse: (a: number, b: number) => [number, number]; readonly references: (a: number, b: number, c: number, d: number, e: number) => [number, number, number, number]; + readonly rename_apply: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => [number, number, number, number]; readonly render_doc_site: (a: number, b: number, c: number, d: number, e: any) => [number, number, number, number]; + readonly semantic_tokens: (a: number, b: number) => [number, number]; readonly symbol_scene: (a: number, b: number, c: number, d: number) => [number, number, number, number]; readonly symbol_svg: (a: number, b: number, c: number, d: number) => [number, number, number, number]; readonly version: () => [number, number]; diff --git a/web-ide/src/lib/pds-wasm/pseudoscript_wasm.js b/web-ide/src/lib/pds-wasm/pseudoscript_wasm.js index 8ad79c9..f97ab8c 100644 --- a/web-ide/src/lib/pds-wasm/pseudoscript_wasm.js +++ b/web-ide/src/lib/pds-wasm/pseudoscript_wasm.js @@ -56,6 +56,46 @@ export function check_modules(modules_json) { } } +/** + * Context-aware completion at `offset` (a byte offset) in module `module_fqn`, + * as a JSON array of LSP `CompletionItem`s (`{label, kind, detail}`, where + * `kind` is the integer `CompletionItemKind`). Scoped to the trigger before the + * caret (`.`/`::`/`#[`/type-position/general); the client filters against the + * typed prefix. Served by the shared [`pseudoscript_lsp_core::complete`] — + * identical to the stdio server's `textDocument/completion`. `modules_json` is + * the `[{fqn, source}]` workspace shape. + * + * # Errors + * + * Returns an error when `modules_json` is not valid JSON of the expected shape. + * @param {string} modules_json + * @param {string} module_fqn + * @param {number} offset + * @returns {string} + */ +export function completion(modules_json, module_fqn, offset) { + let deferred4_0; + let deferred4_1; + try { + const ptr0 = passStringToWasm0(modules_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(module_fqn, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ret = wasm.completion(ptr0, len0, ptr1, len1, offset); + var ptr3 = ret[0]; + var len3 = ret[1]; + if (ret[3]) { + ptr3 = 0; len3 = 0; + throw takeFromExternrefTable0(ret[2]); + } + deferred4_0 = ptr3; + deferred4_1 = len3; + return getStringFromWasm0(ptr3, len3); + } finally { + wasm.__wbindgen_free(deferred4_0, deferred4_1, 1); + } +} + /** * Resolves the symbol under `offset` (a byte offset) in module `module_fqn` to * the FQN of its declaration, for go-to-definition. Returns the FQN as a JSON @@ -265,6 +305,30 @@ export function emit_svg(source, view, target) { } } +/** + * Foldable regions of `source` as the JSON of an LSP `FoldingRange` array + * (`{ startLine, endLine, kind }`, 0-based lines) — every multi-line + * declaration and statement block. Identical to the stdio server's + * `textDocument/foldingRange` response; the editor folds these instead of + * brace-matching in JS. + * @param {string} source + * @returns {string} + */ +export function folding_ranges(source) { + let deferred2_0; + let deferred2_1; + try { + const ptr0 = passStringToWasm0(source, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.folding_ranges(ptr0, len0); + deferred2_0 = ret[0]; + deferred2_1 = ret[1]; + return getStringFromWasm0(ret[0], ret[1]); + } finally { + wasm.__wbindgen_free(deferred2_0, deferred2_1, 1); + } +} + /** * Formats `source` into its canonical form. * @@ -297,16 +361,14 @@ export function format(source) { } /** - * Resolves the symbol under `offset` (a byte offset) in module `module_fqn` - * and returns it as JSON `{ info: { fqn, title, body }, svg }`, or `null` when - * the cursor rests on no resolvable symbol. `svg` is the symbol's fitting - * diagram ([`project_symbol`]) rendered to a self-contained string — a sequence - * trace for a callable, a structural view for a node. `modules_json` is the + * Resolves the symbol under `offset` (a byte offset) in module `module_fqn` and + * returns it as an LSP `Hover` (`{ contents: { kind, value }, range }`, + * Markdown), or `null` when the cursor rests on no resolvable symbol. Served by + * the shared [`pseudoscript_lsp_core::analysis::hover`] — identical to the + * stdio server's `textDocument/hover`, no diagram. The interactive diagram is a + * separate concern: [`symbol_scene`] / [`symbol_svg`]. `modules_json` is the * `[{fqn, source}]` workspace shape. * - * The host (an editor hover) shows the info and diagram together; it never - * decides which diagram a symbol gets — the compiler does. - * * # Errors * * Returns an error when `modules_json` is not valid JSON of the expected shape. @@ -487,6 +549,53 @@ export function references(modules_json, module_fqn, offset) { } } +/** + * Renames the symbol under `offset` in module `module_fqn` to `new_name`, + * applying only the occurrences in `selected_json` — a JSON array of + * `{fqn, line, col}` (1-based, matching [`references`]'s occurrence positions). + * Returns JSON `[{ fqn, source }]`: the new full source of every module that + * changed. The host swaps these into its buffers. The substitution is done here + * (over UTF-8 byte spans) so the host never does offset math. Occurrence spans + * come from the shared [`pseudoscript_lsp_core::refs::rename`]. + * + * # Errors + * + * Returns an error when `new_name` is not a valid identifier, or when either + * JSON argument is malformed. + * @param {string} modules_json + * @param {string} module_fqn + * @param {number} offset + * @param {string} new_name + * @param {string} selected_json + * @returns {string} + */ +export function rename_apply(modules_json, module_fqn, offset, new_name, selected_json) { + let deferred6_0; + let deferred6_1; + try { + const ptr0 = passStringToWasm0(modules_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ptr1 = passStringToWasm0(module_fqn, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len1 = WASM_VECTOR_LEN; + const ptr2 = passStringToWasm0(new_name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len2 = WASM_VECTOR_LEN; + const ptr3 = passStringToWasm0(selected_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len3 = WASM_VECTOR_LEN; + const ret = wasm.rename_apply(ptr0, len0, ptr1, len1, offset, ptr2, len2, ptr3, len3); + var ptr5 = ret[0]; + var len5 = ret[1]; + if (ret[3]) { + ptr5 = 0; len5 = 0; + throw takeFromExternrefTable0(ret[2]); + } + deferred6_0 = ptr5; + deferred6_1 = len5; + return getStringFromWasm0(ptr5, len5); + } finally { + wasm.__wbindgen_free(deferred6_0, deferred6_1, 1); + } +} + /** * Renders the whole documentation site for a workspace, exactly as the CLI's * `pds doc` does, driving server-side rendering through the host's JavaScript @@ -529,6 +638,30 @@ export function render_doc_site(modules_json, config_json, render) { } } +/** + * AST-aware semantic tokens for `source`, as the JSON of an LSP + * `SemanticTokens` (the delta-encoded `data` array over UTF-16 positions; the + * `token_type` field indexes the [`pseudoscript_lsp_core::semantic`] legend). + * Identical to the stdio server's `textDocument/semanticTokens/full` response — + * the editor decodes and decorates it, replacing any hand-written tokenizer. + * @param {string} source + * @returns {string} + */ +export function semantic_tokens(source) { + let deferred2_0; + let deferred2_1; + try { + const ptr0 = passStringToWasm0(source, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.semantic_tokens(ptr0, len0); + deferred2_0 = ret[0]; + deferred2_1 = ret[1]; + return getStringFromWasm0(ret[0], ret[1]); + } finally { + wasm.__wbindgen_free(deferred2_0, deferred2_1, 1); + } +} + /** * Routes Rust panics to the browser console with a readable stack. Runs once * on module instantiation (wasm only). diff --git a/web-ide/src/lib/pds-wasm/pseudoscript_wasm_bg.wasm b/web-ide/src/lib/pds-wasm/pseudoscript_wasm_bg.wasm index c4978aa..baf18a4 100644 Binary files a/web-ide/src/lib/pds-wasm/pseudoscript_wasm_bg.wasm and b/web-ide/src/lib/pds-wasm/pseudoscript_wasm_bg.wasm differ diff --git a/web-ide/src/lib/pds-wasm/pseudoscript_wasm_bg.wasm.d.ts b/web-ide/src/lib/pds-wasm/pseudoscript_wasm_bg.wasm.d.ts index fe45ca2..142079d 100644 --- a/web-ide/src/lib/pds-wasm/pseudoscript_wasm_bg.wasm.d.ts +++ b/web-ide/src/lib/pds-wasm/pseudoscript_wasm_bg.wasm.d.ts @@ -3,12 +3,14 @@ export const memory: WebAssembly.Memory; export const check: (a: number, b: number) => [number, number]; export const check_modules: (a: number, b: number) => [number, number, number, number]; +export const completion: (a: number, b: number, c: number, d: number, e: number) => [number, number, number, number]; export const definition: (a: number, b: number, c: number, d: number, e: number) => [number, number, number, number]; export const doc_manifest: (a: number, b: number) => [number, number, number, number]; export const doc_ssr_bundle: () => [number, number]; export const emit_scene: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number]; export const emit_scene_modules: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number]; export const emit_svg: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number]; +export const folding_ranges: (a: number, b: number) => [number, number]; export const format: (a: number, b: number) => [number, number, number, number]; export const hover: (a: number, b: number, c: number, d: number, e: number) => [number, number, number, number]; export const layout_scene: (a: number, b: number) => [number, number, number, number]; @@ -16,7 +18,9 @@ export const outline: (a: number, b: number) => [number, number]; export const outline_modules: (a: number, b: number) => [number, number, number, number]; export const parse: (a: number, b: number) => [number, number]; export const references: (a: number, b: number, c: number, d: number, e: number) => [number, number, number, number]; +export const rename_apply: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => [number, number, number, number]; export const render_doc_site: (a: number, b: number, c: number, d: number, e: any) => [number, number, number, number]; +export const semantic_tokens: (a: number, b: number) => [number, number]; export const symbol_scene: (a: number, b: number, c: number, d: number) => [number, number, number, number]; export const symbol_svg: (a: number, b: number, c: number, d: number) => [number, number, number, number]; export const version: () => [number, number]; diff --git a/web-ide/src/lib/pds.js b/web-ide/src/lib/pds.js deleted file mode 100644 index fea76b1..0000000 --- a/web-ide/src/lib/pds.js +++ /dev/null @@ -1,196 +0,0 @@ -// Loader + typed wrappers around the PseudoScript compiler wasm module. -// -// The vendored `pds-wasm/` package is wasm-bindgen's `--target web` output: -// the default export initialises the module (fetching the `.wasm`), after which -// the named functions are synchronous. Call `initWasm()` once before using them. -import init, { - check as wasmCheck, - check_modules as wasmCheckModules, - parse as wasmParse, - format as wasmFormat, - emit_scene as wasmEmitScene, - emit_scene_modules as wasmEmitSceneModules, - layout_scene as wasmLayoutScene, - emit_svg as wasmEmitSvg, - hover as wasmHover, - definition as wasmDefinition, - references as wasmReferences, - doc_ssr_bundle as wasmDocSsrBundle, - doc_manifest as wasmDocManifest, - outline as wasmOutline, - outline_modules as wasmOutlineModules, - render_doc_site as wasmRenderDocSite, - symbol_scene as wasmSymbolScene, - symbol_svg as wasmSymbolSvg, - version as wasmVersion, -} from "./pds-wasm/pseudoscript_wasm.js"; - -let readyPromise; - -/** Initialise the wasm module once; subsequent calls reuse the same promise. */ -export function initWasm() { - if (!readyPromise) readyPromise = init(); - return readyPromise; -} - -/** Parse + static-check one module; returns the diagnostics array. */ -export function check(source) { - return JSON.parse(wasmCheck(source)); -} - -/** Parse-only diagnostics (syntax errors), for fast per-keystroke feedback. */ -export function parse(source) { - return JSON.parse(wasmParse(source)); -} - -/** - * Check a whole workspace. `modules` is `[{ fqn, source }]`; returns - * `[{ fqn, diagnostics }]` with cross-module errors attributed per module. - */ -export function checkModules(modules) { - return JSON.parse(wasmCheckModules(JSON.stringify(modules))); -} - -/** Format source to canonical form; throws on a parse error. */ -export function format(source) { - return wasmFormat(source); -} - -/** Project a diagram view to its laid-out scene object. */ -export function emitScene(source, view, target = "") { - return JSON.parse(wasmEmitScene(source, view, target)); -} - -/** - * List the nodes declared in `source`: `[{ fqn, name, kind, triggered }]`. - * Used to derive a diagram view's target options from the model itself. - */ -export function outline(source) { - return JSON.parse(wasmOutline(source)); -} - -/** Like {@link outline}, but over a whole workspace (`[{ fqn, source }]`). */ -export function outlineModules(modules) { - return JSON.parse(wasmOutlineModules(JSON.stringify(modules))); -} - -/** - * Project a diagram view over the whole workspace, so it shows nodes and edges - * across modules (a container's components, cross-system calls). - */ -export function emitSceneModules(modules, view, target = "") { - return JSON.parse(wasmEmitSceneModules(JSON.stringify(modules), view, target)); -} - -/** - * Position a (sequence) scene into absolute coordinates with the layout engine. - * `scene` is a sequence Scene object (optionally depth-collapsed first); returns - * the positioned `Layout` the renderer draws verbatim. - */ -export function layoutScene(scene) { - return JSON.parse(wasmLayoutScene(JSON.stringify(scene))); -} - -/** Project a diagram view to an SVG string. */ -export function emitSvg(source, view, target = "") { - return wasmEmitSvg(source, view, target); -} - -/** - * Resolve the symbol under a byte `offset` in module `moduleFqn`, returning - * `{ info: { fqn, title, body }, svg }` (the symbol's info and its fitting - * diagram as SVG), or `null` when the cursor rests on no symbol. The compiler - * chooses the diagram — a sequence trace for a callable, a structural view for - * a node. `modules` is `[{ fqn, source }]`. - */ -export function hover(modules, moduleFqn, offset) { - return JSON.parse(wasmHover(JSON.stringify(modules), moduleFqn, offset)); -} - -/** - * Resolve the symbol under a byte `offset` in module `moduleFqn` to the FQN of - * its declaration (go-to-definition), or `null` when the cursor rests on no - * resolvable symbol. Cheaper than {@link hover} — no diagram. `modules` is - * `[{ fqn, source }]`. - */ -export function definition(modules, moduleFqn, offset) { - return JSON.parse(wasmDefinition(JSON.stringify(modules), moduleFqn, offset)); -} - -/** - * Find every usage of the symbol under a byte `offset` in module `moduleFqn` - * across the workspace. Returns `{ fqn, title, occurrences: [{ fqn, line, col, - * end_line, end_col, text, decl }] }` (1-based positions, a trimmed source-line - * preview, `decl` marking the declaration), or `null` when the cursor rests on - * no resolvable symbol. `modules` is `[{ fqn, source }]`. - */ -export function references(modules, moduleFqn, offset) { - return JSON.parse(wasmReferences(JSON.stringify(modules), moduleFqn, offset)); -} - -/** - * Project the fitting diagram for a symbol to its laid-out scene object (the - * interactive counterpart of {@link hover}'s `svg`, for a side panel or - * full-screen view). `modules` is `[{ fqn, source }]`. - */ -export function symbolScene(modules, fqn) { - return JSON.parse(wasmSymbolScene(JSON.stringify(modules), fqn)); -} - -/** - * Render the fitting diagram for a symbol to a self-contained SVG string (the - * live, re-derivable form of {@link hover}'s `svg`, for a docked side panel). - * `modules` is `[{ fqn, source }]`. - */ -export function symbolSvg(modules, fqn) { - return wasmSymbolSvg(JSON.stringify(modules), fqn); -} - -/** The compiler crate version. */ -export function version() { - return wasmVersion(); -} - -let ssrLoaded = false; - -/** - * Evaluate the embedded Svelte SSR bundle once, defining `globalThis.SSR`. The - * browser is the JavaScript engine the compiler's site generator renders - * through (the native CLI uses an embedded QuickJS instead). - */ -function ensureSsr() { - if (ssrLoaded) return; - // The bundle is an esbuild IIFE that defines a top-level `var SSR`; that only - // becomes the global `SSR` when run at global scope, so inject it as a - // + +
                      - + + + + + diff --git a/web-landing/package-lock.json b/web-landing/package-lock.json index 1e39d08..093656a 100644 --- a/web-landing/package-lock.json +++ b/web-landing/package-lock.json @@ -12,7 +12,10 @@ }, "devDependencies": { "@sveltejs/vite-plugin-svelte": "^5.1.0", + "@tsconfig/svelte": "^5.0.8", "svelte": "^5.56.0", + "svelte-check": "^4.5.0", + "typescript": "^6.0.3", "vite": "^6.3.5" } }, @@ -950,6 +953,13 @@ "vite": "^6.0.0" } }, + "node_modules/@tsconfig/svelte": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/svelte/-/svelte-5.0.8.tgz", + "integrity": "sha512-UkNnw1/oFEfecR8ypyHIQuWYdkPvHiwcQ78sh+ymIiYoF+uc5H1UBetbjyqT+vgGJ3qQN6nhucJviX6HesWtKQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", @@ -992,6 +1002,22 @@ "node": ">= 0.4" } }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", @@ -1167,6 +1193,16 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -1242,6 +1278,20 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/rollup": { "version": "4.60.4", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.4.tgz", @@ -1294,6 +1344,19 @@ "dev": true, "license": "MIT" }, + "node_modules/sade": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", + "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "mri": "^1.1.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -1331,6 +1394,30 @@ "node": ">=18" } }, + "node_modules/svelte-check": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.5.0.tgz", + "integrity": "sha512-9lNwPxCLWniFvQIcEv1LFqjIxcFtO3smb5+5BKbRJ3ttL4o2lXCej5rLF4DAnfLPI66oaA81vAxw6ILdIWI7kA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "chokidar": "^4.0.1", + "fdir": "^6.2.0", + "picocolors": "^1.0.0", + "sade": "^1.7.4" + }, + "bin": { + "svelte-check": "bin/svelte-check" + }, + "engines": { + "node": ">= 18.0.0" + }, + "peerDependencies": { + "svelte": "^4.0.0 || ^5.0.0-next.0", + "typescript": ">=5.0.0" + } + }, "node_modules/tinyglobby": { "version": "0.2.17", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", @@ -1348,6 +1435,20 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/vite": { "version": "6.4.2", "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.2.tgz", diff --git a/web-landing/package.json b/web-landing/package.json index 7edf477..32a568e 100644 --- a/web-landing/package.json +++ b/web-landing/package.json @@ -4,13 +4,17 @@ "version": "0.1.0", "type": "module", "scripts": { - "dev": "vite", + "dev": "vite --host", "build": "vite build", - "preview": "vite preview" + "preview": "vite preview", + "check": "svelte-check --tsconfig ./tsconfig.json" }, "devDependencies": { "@sveltejs/vite-plugin-svelte": "^5.1.0", + "@tsconfig/svelte": "^5.0.8", "svelte": "^5.56.0", + "svelte-check": "^4.5.0", + "typescript": "^6.0.3", "vite": "^6.3.5" }, "dependencies": { diff --git a/web-landing/public/og.png b/web-landing/public/og.png new file mode 100644 index 0000000..e1cf633 Binary files /dev/null and b/web-landing/public/og.png differ diff --git a/web-landing/public/robots.txt b/web-landing/public/robots.txt new file mode 100644 index 0000000..4404853 --- /dev/null +++ b/web-landing/public/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Allow: / + +Sitemap: https://pdscript.dev/sitemap.xml diff --git a/web-landing/public/sitemap.xml b/web-landing/public/sitemap.xml new file mode 100644 index 0000000..a13249a --- /dev/null +++ b/web-landing/public/sitemap.xml @@ -0,0 +1,9 @@ + + + + https://pdscript.dev/ + 2026-06-02 + weekly + 1.0 + + diff --git a/web-landing/src/App.svelte b/web-landing/src/App.svelte index 38a74b8..724e7cb 100644 --- a/web-landing/src/App.svelte +++ b/web-landing/src/App.svelte @@ -1,12 +1,11 @@ - + +
                      +
                      +
                      +
                      With an agent
                      +

                      Don't want to write code? Let the agent handle it.

                      +

                      + Point your agent at your codebase and the PseudoScript model writes itself. You review the diagrams, not the grammar. Or talk it through and let the agent scope it from the transcript. +

                      +
                      + +
                      +
                      + Hand it to your agent + +
                      +
                      +

                      Model this project using PseudoScript. Run pds -h to get started.

                      +

                      Run pds skill and pds lang to learn the method and grammar, then write the model.

                      +
                      +
                      paste into any coding agent with a shell
                      +
                      +
                      +
                      + + diff --git a/web-landing/src/components/Convergence.svelte b/web-landing/src/components/Convergence.svelte deleted file mode 100644 index ed063eb..0000000 --- a/web-landing/src/components/Convergence.svelte +++ /dev/null @@ -1,33 +0,0 @@ - - -
                      -
                      -
                      -
                      One toolchain
                      -

                      Four disciplines, one artefact.

                      -

                      Spec-driven development, vibe programming, refinement, and design were separate steps. PseudoScript collapses them into a single source you write — and everything downstream regenerates.

                      -
                      - -
                      -
                      -
                      01 · INPUT

                      Spec-driven development

                      The model is the source. You declare structure — system, container, component, person — and the Analyzer holds you to it.

                      -
                      02 · INPUT

                      Vibe programming

                      Describe intent in high-level pseudocode. No boilerplate, no ceremony — just what the system is and does.

                      -
                      - -
                      -
                      - - - PseudoScript -
                      -
                      - -
                      -
                      03 · LOOP

                      Refinement

                      Live diagnostics shape the model as you type. You iterate until there are no problems — the model is well-formed.

                      -
                      04 · OUTPUT

                      Design

                      C4 models and sequence diagrams render straight from the spec. The picture is never stale, because it is generated.

                      -
                      -
                      -
                      -
                      diff --git a/web-landing/src/components/Cta.svelte b/web-landing/src/components/Cta.svelte index 68582e0..e03f25c 100644 --- a/web-landing/src/components/Cta.svelte +++ b/web-landing/src/components/Cta.svelte @@ -1,45 +1,17 @@ -
                      diff --git a/web-landing/src/components/Hero.svelte b/web-landing/src/components/Hero.svelte index 107f5d6..d8ce167 100644 --- a/web-landing/src/components/Hero.svelte +++ b/web-landing/src/components/Hero.svelte @@ -1,32 +1,24 @@ -
                      - Specification language - for the agentic era + Model-driven development + pseudo-programming
                      -

                      The spec is the source of truth. Everything else is generated.

                      -

                      Describe your program in PseudoScript. The Analyzer compiles it into design artefacts, C4 models, and sequence diagrams your agents can read and build against.

                      +

                      Model the intent. Implement the detail.

                      +

                      PseudoScript powers model-driven development and pseudo-programming for the agentic era. Model your system in plain pseudocode. Your team and your agents read one always-current map, not diagrams that rot.

                      -
                      - Analyzer - Formatter - Linter - LSP - all WASM · client-side + Open the Web IDE
                      +

                      Runs in your browser. Or install the CLI or the JetBrains plugin.

                      -
                      - +
                      context.pds @@ -40,7 +32,7 @@
                      -
                      +
                      diff --git a/web-landing/src/components/SiteFooter.svelte b/web-landing/src/components/SiteFooter.svelte index 3c042e8..9f952be 100644 --- a/web-landing/src/components/SiteFooter.svelte +++ b/web-landing/src/components/SiteFooter.svelte @@ -1,4 +1,4 @@ - @@ -7,29 +7,29 @@
                      - PseudoScript -

                      Architecture as code. Describe the system; generate the artefacts your agents read and build against.

                      +

                      Architecture as code. The model is the source. Describe the system once and generate the artefacts.

                      - PseudoScript — the spec is the source of truth. - pds 1.4.0 · drafting terminal + PseudoScript. The model is the source of truth.
                      diff --git a/web-landing/src/components/Topbar.svelte b/web-landing/src/components/Topbar.svelte index 84b3494..e07d820 100644 --- a/web-landing/src/components/Topbar.svelte +++ b/web-landing/src/components/Topbar.svelte @@ -1,22 +1,18 @@ -
                      diff --git a/web-landing/src/components/Tweaks.svelte b/web-landing/src/components/Tweaks.svelte index 8355c44..3b0865c 100644 --- a/web-landing/src/components/Tweaks.svelte +++ b/web-landing/src/components/Tweaks.svelte @@ -1,35 +1,53 @@ - +
                      How it works
                      @@ -6,12 +8,10 @@
                      -
                      01 — Describe
                      -

                      You write structure, not implementation.

                      -

                      A few lines of PseudoScript declare a bounded context and its guarantees. The intent is the code; the mechanism is named, then you stop.

                      +

                      Model intent, not implementation.

                      +

                      Capture how the system works in a few lines of pseudocode. There are no diagrams to maintain and no docs to keep in sync.

                      -
                      - +
                      inventory.pds
                      @@ -22,32 +22,28 @@
                      -
                      02 — Refine

                      Iterate until the model is well-formed.

                      -

                      The Linter flags missing docs, crossed references, and unreachable nodes as you go. Resolve them and the problem list empties.

                      +

                      The Analyzer knows your whole model. The moment something isn't valid, it tells you and helps you fix it.

                      -
                      - +
                      Problems3 problems
                        -
                      • errororders14:3unresolved reference payments::Charge
                      • -
                      • warnpricing7:3public node has no /// summary
                      • -
                      • infoshared1:1module doc //! recommended
                      • +
                      • errororders8:17argument 1: expected Money, found string
                      • +
                      • errororders9:9callable add expects 2 argument(s), got 3
                      • +
                      • errororders10:9self.refund does not name a callable of C
                      -
                      No problems — the model is well-formed.
                      +
                      No problems. The model is well-formed.
                      -
                      03 — Generate
                      -

                      Artefacts your agents can build against.

                      -

                      Every diagram is projected from the spec — C4 context, container, component, and the sequence diagrams that trace a saga end to end. Machine-readable by construction.

                      +

                      Artefacts projected straight from the model.

                      +

                      C4 context, containers, sequence diagrams that trace a saga end to end. All generated, all current.

                      -
                      - -
                      checkout · sequence
                      +
                      +
                      checkout · sequence from the model
                      @@ -56,4 +52,4 @@
                      -
                      + \ No newline at end of file diff --git a/web-landing/src/lib/landing-anim.js b/web-landing/src/lib/landing-anim.ts similarity index 59% rename from web-landing/src/lib/landing-anim.js rename to web-landing/src/lib/landing-anim.ts index a0fded5..881a6fc 100644 --- a/web-landing/src/lib/landing-anim.js +++ b/web-landing/src/lib/landing-anim.ts @@ -1,10 +1,10 @@ /* ============================================================================= PseudoScript landing — interactions (ported from the design's landing.js). - live .pds typing in the hero, syncing a C4 diagram that assembles - - static syntax-highlighted panels (Describe step, IDE editor) - - diagnostics resolving (Refine step) - - a projected sequence diagram (Generate step) - - scroll reveals + the convergence core pulse + - a static syntax-highlighted panel (Describe step) + - diagnostics that resolve as you scroll (Refine step, scroll-linked) + - a projected sequence diagram that draws in with scroll (Generate step) + - scroll reveals + the generation-spine active-section tracking Triggers are scroll-driven (with an immediate initial pass) so they fire reliably regardless of IntersectionObserver quirks. @@ -13,26 +13,65 @@ ========================================================================== */ import { pdsTokenize, pdsHighlight } from './pds-syntax.js'; +/* a single tokenised span emitted by the .pds tokenizer */ +interface Token { + c: string; + s: string; +} + +/* one-shot scroll trigger: fires fn once when el crosses ratio of the viewport */ +interface OneShot { + el: Element; + ratio: number; + fired: boolean; + fn: () => void; +} + +/* always-run watcher, invoked every scroll check with the viewport height */ +type Watcher = (vh: number) => void; + +/* zero-arg trigger keyed by hero line index */ +type LineTrigger = () => void; + +/* a sequence-diagram lane (vertical actor lifeline) */ +interface SeqLane { + x: number; + label: string; + kind: 'person' | 'component' | 'container'; +} + +/* a sequence-diagram message: [from lane, to lane, y, label, kind] */ +type SeqMessage = [number, number, number, string, 'call' | 'ret']; + const H = pdsHighlight; const T = pdsTokenize; -export function initLanding() { +export function initLanding(): () => void { const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches || document.body.classList.contains('no-motion'); - function $all(s, r) { return Array.prototype.slice.call((r || document).querySelectorAll(s)); } - function gutter(el, n) { + function $all(s: string, r?: ParentNode | null): Element[] { return Array.prototype.slice.call((r || document).querySelectorAll(s)); } + function gutter(el: Element | null, n: number): void { if (!el) return; let s = ''; for (let i = 1; i <= n; i++) s += '
                      ' + i + '
                      '; el.innerHTML = s; } - function top(el) { return el.getBoundingClientRect().top; } + function top(el: Element): number { return el.getBoundingClientRect().top; } + + /* scroll progress 0..1 as el's top travels from start*vh down to end*vh. + start > end, e.g. (0.8, 0.35): p=0 as the element enters at 80% of the + viewport, p=1 once its top reaches 35%. Used to scrub scroll-linked anims. */ + function prog(el: Element, vh: number, start: number, end: number): number { + const t = el.getBoundingClientRect().top; + const p = (start * vh - t) / ((start - end) * vh); + return p < 0 ? 0 : p > 1 ? 1 : p; + } /* registry of one-shot scroll triggers + always-run watchers */ - const oneShots = []; // { el, ratio, fired, fn } - const watchers = []; // function() (run every check) - function onScroll() { + const oneShots: OneShot[] = []; // { el, ratio, fired, fn } + const watchers: Watcher[] = []; // function() (run every check) + function onScroll(): void { const vh = window.innerHeight || document.documentElement.clientHeight; for (let i = 0; i < oneShots.length; i++) { const t = oneShots[i]; @@ -86,56 +125,17 @@ export function initLanding() { 'public data Hold { id: HoldId, seats: number }' ].join('\n'); - const IDE_SRC = [ - '//! context — the C4 system context.', - '', - 'public person Attendee {', - ' #[manual]', - ' public hold(req: ReserveRequest): void {', - ' gateway::ReservationApi.reserve(req)', - ' }', - '}', - '', - '/// ACME Tickets — the ticketing platform.', - '/// #headline', - 'public system AcmeTickets;', - '', - 'public system PaymentProvider {', - ' public authorize(amt: Money): Result;', - '}' - ].join('\n'); - /* ---- static highlighted panels ----------------------------------------- */ - function paintStatic(codeId, gutId, src) { + function paintStatic(codeId: string, gutId: string, src: string): void { const code = document.getElementById(codeId); if (!code) return; code.innerHTML = H(src); gutter(document.getElementById(gutId), src.split('\n').length); } paintStatic('describe-code', 'describe-gutter', DESCRIBE_SRC); - paintStatic('ide-code', 'ide-gutter', IDE_SRC); - - /* ---- manifest (pds.toml) ----------------------------------------------- */ - (function manifest() { - const el = document.getElementById('manifest'); - if (!el) return; - const rows = [ - '[workspace]', - 'name = "acme-tickets"', - 'version = "1.4.0"', - 'modules = ["context", "inventory",', - ' "orders", "payments"]', - '', - '[dependencies]', - 'acme/inventory = "1.4.0"', - 'std/money = "2.1.0"', - 'c4/patterns = "0.9.2"' - ]; - el.innerHTML = rows.join('\n'); - })(); /* ---- hero typing + diagram assembly ------------------------------------ */ - (function hero() { + (function hero(): void { const code = document.getElementById('hero-code'); const gut = document.getElementById('hero-gutter'); const status = document.getElementById('hero-status'); @@ -147,11 +147,11 @@ export function initLanding() { const nodes = $all('.c4-node', stage); const edges = $all('.edge', document.getElementById('hero-edges')); - function setStatus(state, text) { status.className = 'status ' + state; if (stext) stext.textContent = text; } - function showNode(i) { if (nodes[i]) nodes[i].classList.add('in'); } - function drawEdge(i) { const e = edges[i]; if (!e) return; e.style.transition = 'stroke-dashoffset .7s ease'; e.style.strokeDashoffset = '0'; } + function setStatus(state: string, text: string): void { if (status) status.className = 'status ' + state; if (stext) stext.textContent = text; } + function showNode(i: number): void { if (nodes[i]) nodes[i].classList.add('in'); } + function drawEdge(i: number): void { const e = edges[i] as SVGElement | undefined; if (!e) return; e.style.transition = 'stroke-dashoffset .7s ease'; e.style.strokeDashoffset = '0'; } - const triggers = { + const triggers: Record = { 3: function () { showNode(0); }, 10: function () { showNode(1); }, 12: function () { showNode(2); drawEdge(0); drawEdge(1); }, @@ -160,25 +160,25 @@ export function initLanding() { }; const lines = HERO_SRC.split('\n'); - function renderInstant() { - code.innerHTML = H(HERO_SRC); + function renderInstant(): void { + code!.innerHTML = H(HERO_SRC); gutter(gut, lines.length); - Object.keys(triggers).forEach(function (k) { triggers[k](); }); + Object.keys(triggers).forEach(function (k) { triggers[Number(k)](); }); setStatus('ok', 'well-formed'); } if (reduce) { renderInstant(); return; } let li = 0, html = ''; - function typeLine() { - if (li >= lines.length) { code.innerHTML = html; setStatus('ok', 'well-formed'); return; } - const toks = T(lines[li]); + function typeLine(): void { + if (li >= lines.length) { code!.innerHTML = html; setStatus('ok', 'well-formed'); return; } + const toks: Token[] = T(lines[li]); let ti = 0, lineHtml = ''; - function step() { + function step(): void { if (ti < toks.length) { const tk = toks[ti++]; const esc = tk.s.replace(/&/g, '&').replace(//g, '>'); lineHtml += tk.c === 'ws' ? esc : '' + esc + ''; - code.innerHTML = html + '' + lineHtml + '\n'; + code!.innerHTML = html + '' + lineHtml + '\n'; setTimeout(step, 14 + Math.random() * 22); } else { html += '' + lineHtml + '\n'; @@ -188,7 +188,7 @@ export function initLanding() { setTimeout(typeLine, lines[li - 1] === '' ? 40 : 90); } } - if (toks.length === 0) { code.innerHTML = html + '\n'; setTimeout(step, 60); } + if (toks.length === 0) { code!.innerHTML = html + '\n'; setTimeout(step, 60); } else { step(); } } oneShots.push({ el: term, ratio: 0.85, fired: false, fn: function () { @@ -197,46 +197,44 @@ export function initLanding() { } }); })(); - /* ---- refine: diagnostics resolving ------------------------------------- */ - (function refine() { + /* ---- refine: diagnostics resolve as you scroll ------------------------- */ + (function refine(): void { const box = document.getElementById('refine-visual'); if (!box) return; const items = $all('#problems li'); const count = document.getElementById('prob-count'); const well = document.getElementById('well-formed'); - function resolveSeq() { - if (reduce) { - items.forEach(function (li) { li.classList.add('resolved'); }); - if (count) count.textContent = '0 problems'; - if (well) well.classList.add('show'); - return; - } - [0, 1, 2].forEach(function (idx, k) { - setTimeout(function () { - if (items[idx]) items[idx].classList.add('resolved'); - const left = items.length - (k + 1); - if (count) count.textContent = left + (left === 1 ? ' problem' : ' problems'); - if (k === 2 && well) setTimeout(function () { well.classList.add('show'); }, 250); - }, 600 + k * 650); - }); + const n = items.length; + function setState(resolved: number): void { + items.forEach(function (li, i) { li.classList.toggle('resolved', i < resolved); }); + const left = n - resolved; + if (count) count.textContent = left + (left === 1 ? ' problem' : ' problems'); + if (well) well.classList.toggle('show', resolved >= n); } - oneShots.push({ el: box, ratio: 0.7, fired: false, fn: resolveSeq }); + if (reduce) { setState(n); return; } + // scrub: hold all problems visible until the panel is well into view, then + // resolve as it scrolls toward the top — finishing late so it's readable, + // not "gone by half way down". one problem clears per 1/(n+1) of progress. + watchers.push(function (vh: number) { + const p = prog(box, vh, 0.7, 0.08); + setState(Math.min(n, Math.floor(p * (n + 1)))); + }); })(); /* ---- generate: sequence diagram ---------------------------------------- */ - (function sequence() { + (function sequence(): void { const svg = document.getElementById('seq-svg'); if (!svg) return; const NS = 'http://www.w3.org/2000/svg'; - const col = { person: 'var(--k-person)', component: 'var(--k-component)', container: 'var(--k-container)' }; - const lanes = [ + const col: Record = { person: 'var(--k-person)', component: 'var(--k-component)', container: 'var(--k-container)' }; + const lanes: SeqLane[] = [ { x: 55, label: 'Attendee', kind: 'person' }, { x: 185, label: 'Checkout', kind: 'component' }, { x: 305, label: 'inventory', kind: 'container' }, { x: 420, label: 'payments', kind: 'container' } ]; - function mk(tag, attrs) { const e = document.createElementNS(NS, tag); for (const k in attrs) e.setAttribute(k, attrs[k]); return e; } - function text(x, y, str, cls) { const t = mk('text', { x: x, y: y, 'text-anchor': 'middle', class: cls }); t.textContent = str; return t; } + function mk(tag: string, attrs: Record): SVGElement { const e = document.createElementNS(NS, tag) as SVGElement; for (const k in attrs) e.setAttribute(k, String(attrs[k])); return e; } + function text(x: number, y: number, str: string, cls: string): SVGElement { const t = mk('text', { x: x, y: y, 'text-anchor': 'middle', class: cls }); t.textContent = str; return t; } const style = mk('style', {}); style.textContent = @@ -263,8 +261,8 @@ export function initLanding() { g.appendChild(mk('line', { x1: l.x, y1: topY + 10, x2: l.x, y2: botY, stroke: 'var(--line)', 'stroke-dasharray': '3 4' })); svg.appendChild(g); }); - function lx(i) { return lanes[i].x; } - const msgs = [ + function lx(i: number): number { return lanes[i].x; } + const msgs: SeqMessage[] = [ [0, 1, 64, 'checkout(req)', 'call'], [1, 2, 96, 'allocate(n)', 'call'], [2, 1, 124, 'Ok(Hold)', 'ret'], @@ -273,7 +271,7 @@ export function initLanding() { [1, 2, 216, 'commit(hold)', 'call'], [1, 0, 252, 'Confirmation', 'ret'] ]; - const groups = []; + const groups: SVGElement[] = []; msgs.forEach(function (m) { const x1 = lx(m[0]), x2 = lx(m[1]), y = m[2], ret = m[4] === 'ret'; const g = mk('g', { class: 'seq-msg' }); @@ -284,25 +282,36 @@ export function initLanding() { svg.appendChild(g); groups.push(g); }); - function play() { - if (reduce) { groups.forEach(function (g) { g.classList.add('in'); }); return; } - groups.forEach(function (g, i) { setTimeout(function () { g.classList.add('in'); }, 250 + i * 320); }); - } - oneShots.push({ el: svg, ratio: 0.6, fired: false, fn: play }); + if (reduce) { groups.forEach(function (g) { g.classList.add('in'); }); return; } + // scrub: messages draw in one by one as the diagram scrolls through view + const wrap = svg.closest('.seq') || svg; + const n = groups.length; + watchers.push(function (vh: number) { + const p = prog(wrap, vh, 0.8, 0.12); + const shown = Math.min(n, Math.floor(p * (n + 1))); + groups.forEach(function (g, i) { g.classList.toggle('in', i < shown); }); + }); })(); - /* ---- convergence core pulse -------------------------------------------- */ - (function core() { - const c = document.getElementById('core-mark'); - if (!c || reduce) return; - watchers.push(function (vh) { - const r = c.getBoundingClientRect(); - c.classList.toggle('live', r.top < vh * 0.8 && r.bottom > vh * 0.2); + /* ---- generation spine: light the active section's index ----------------- */ + (function spine(): void { + const ticks = $all('.spine a') as HTMLElement[]; + if (!ticks.length) return; + const targets = ticks.map(function (t) { return document.querySelector(t.getAttribute('href') || ''); }); + // Not gated on `reduce`: this is a class toggle, not an animation, so the + // rail still tracks the active section under prefers-reduced-motion. + watchers.push(function (vh: number) { + let active = 0; + for (let i = 0; i < targets.length; i++) { + const sec = targets[i]; + if (sec && sec.getBoundingClientRect().top < vh * 0.4) active = i; + } + ticks.forEach(function (t, i) { t.classList.toggle('lit', i === active); }); }); })(); /* ---- scroll reveals ----------------------------------------------------- */ - (function reveals() { + (function reveals(): void { const els = $all('.reveal'); if (reduce) { els.forEach(function (el) { el.classList.add('in'); }); return; } els.forEach(function (el) { @@ -312,7 +321,7 @@ export function initLanding() { /* ---- drive triggers ----------------------------------------------------- */ let ticking = false; - function requestCheck() { + function requestCheck(): void { if (ticking) return; ticking = true; window.requestAnimationFrame(function () { ticking = false; onScroll(); }); } @@ -329,11 +338,12 @@ export function initLanding() { // so above-the-fold content can never be stuck blank on first paint. const t3 = setTimeout(function () { $all('.reveal.in').forEach(function (el) { - if (getComputedStyle(el).opacity === '0') { el.style.transition = 'none'; el.style.opacity = '1'; el.style.transform = 'none'; } + const he = el as HTMLElement; + if (getComputedStyle(he).opacity === '0') { he.style.transition = 'none'; he.style.opacity = '1'; he.style.transform = 'none'; } }); }, 600); - return function teardown() { + return function teardown(): void { window.removeEventListener('scroll', requestCheck); window.removeEventListener('resize', requestCheck); window.removeEventListener('load', onScroll); diff --git a/web-landing/src/lib/pds-syntax.js b/web-landing/src/lib/pds-syntax.ts similarity index 81% rename from web-landing/src/lib/pds-syntax.js rename to web-landing/src/lib/pds-syntax.ts index 62ee605..4361765 100644 --- a/web-landing/src/lib/pds-syntax.js +++ b/web-landing/src/lib/pds-syntax.ts @@ -7,13 +7,19 @@ const STEP = new Set(['given', 'when', 'then', 'and', 'but']); const ATOMS = new Set(['Result', 'Option', 'Ok', 'Err', 'Some', 'None', 'true', 'false']); const PRIMS = new Set(['number', 'string', 'bool']); -export function pdsTokenize(line) { - const out = []; +/** A syntax-coloured span: `c` is the CSS class name, `s` is the source text. */ +export interface PdsToken { + c: string; + s: string; +} + +export function pdsTokenize(line: string): PdsToken[] { + const out: PdsToken[] = []; let i = 0; - const push = (c, s) => out.push({ c, s }); + const push = (c: string, s: string): number => out.push({ c, s }); while (i < line.length) { const rest = line.slice(i); - let m; + let m: RegExpMatchArray | null; if ((m = rest.match(/^\s+/))) { push('ws', m[0]); i += m[0].length; continue; } if (rest.startsWith('//!') || rest.startsWith('///')) { push('doc', rest); break; } if (rest.startsWith('//')) { push('cmt', rest); break; } @@ -25,7 +31,7 @@ export function pdsTokenize(line) { const w = m[0]; const prev = line[i - 1]; const immediate = line[i + w.length]; - let cls; + let cls: string; if (prev === '.') cls = 'mem'; else if (KEYWORDS.has(w)) cls = 'kw'; else if (STEP.has(w)) cls = 'step'; @@ -44,9 +50,9 @@ export function pdsTokenize(line) { // Build syntax-highlighted HTML for a whole multi-line source string. // Each line is a display:block .ln containing a trailing "\n" so empty // lines keep their height (matches the IDE editor). Lines join with "". -export function pdsHighlight(src) { - return src.split('\n').map(function (ln) { - const inner = pdsTokenize(ln).map(function (tk) { +export function pdsHighlight(src: string): string { + return src.split('\n').map(function (ln: string): string { + const inner = pdsTokenize(ln).map(function (tk: PdsToken): string { const esc = tk.s.replace(/&/g, '&').replace(//g, '>'); return tk.c === 'ws' ? esc : '' + esc + ''; }).join(''); diff --git a/web-landing/src/main.js b/web-landing/src/main.ts similarity index 61% rename from web-landing/src/main.js rename to web-landing/src/main.ts index ced6722..fa6de6a 100644 --- a/web-landing/src/main.js +++ b/web-landing/src/main.ts @@ -3,6 +3,8 @@ import './styles/landing.css'; import { mount } from 'svelte'; import App from './App.svelte'; -const app = mount(App, { target: document.getElementById('app') }); +const target: HTMLElement = document.getElementById('app')!; + +const app = mount(App, { target }); export default app; diff --git a/web-landing/src/styles/colors_and_type.css b/web-landing/src/styles/colors_and_type.css index 66355a5..2c6cc05 100644 --- a/web-landing/src/styles/colors_and_type.css +++ b/web-landing/src/styles/colors_and_type.css @@ -69,15 +69,17 @@ /* ---- LIGHT ---------------------------------------------------------------- */ :root[data-theme="light"] { - --bg: #f3f1ec; + /* matched to the web-ide light theme (web-ide/src/app.css): tinted blue + (B ≥ G ≥ R) so the surface reads like brushed metal, not aged paper. */ + --bg: #e7eaef; --surface: #ffffff; - --surface-2: #f4f2ed; - --surface-3: #e8e5dd; + --surface-2: #f4f6f9; + --surface-3: #e3e7ee; --ink: #1a1b20; --ink-soft: #4c4e57; - --ink-faint: #8a8c95; - --line: #e3e0d8; - --line-strong: #cfccc2; + --ink-faint: #888c95; + --line: #dde0e7; + --line-strong: #c6cad3; --accent: #e8401c; --accent-hi: #ff5a36; diff --git a/web-landing/src/styles/landing.css b/web-landing/src/styles/landing.css index 3626f43..673934a 100644 --- a/web-landing/src/styles/landing.css +++ b/web-landing/src/styles/landing.css @@ -1,7 +1,7 @@ /* ============================================================================= PseudoScript — Landing page styles. Built on colors_and_type.css tokens. "Drafting Terminal": ink canvas, vermilion horizon, hairline frames, - drafting corner ticks, uppercase mono micro-labels, one hot accent. + uppercase mono micro-labels, one hot accent. ========================================================================== */ * { box-sizing: border-box; } @@ -51,6 +51,13 @@ body::before { .btn-ghost:hover { border-color: var(--accent); color: var(--ink); } .btn-arrow svg { transition: transform .15s; } .btn:hover .btn-arrow svg { transform: translateX(3px); } +.btn-lg { padding: .82rem 1.5rem; font-size: 1rem; } +.btn-lg .ico svg { width: 18px; height: 18px; } + +/* secondary link line under a single primary CTA — keeps attention ratio low */ +.hero-alt { margin-top: 1.1rem; font-size: .82rem; color: var(--ink-faint); } +.hero-alt a { color: var(--ink-soft); text-decoration: none; border-bottom: 1px solid var(--line-strong); transition: color .14s, border-color .14s; } +.hero-alt a:hover { color: var(--accent); border-bottom-color: var(--accent); } /* ---- topbar --------------------------------------------------------------- */ .topbar { position: sticky; top: 0; z-index: 80; height: var(--topbar-h); border-bottom: 1px solid var(--line); background: color-mix(in srgb, var(--surface) 72%, transparent); backdrop-filter: blur(10px) saturate(1.3); } @@ -75,14 +82,6 @@ section { position: relative; padding: clamp(4rem, 9vw, 8rem) 0; } .lede { margin: 1.3rem 0 0; max-width: 46ch; color: var(--ink-soft); font-size: var(--text-md); line-height: 1.6; } .lede.wide { max-width: 60ch; } -/* drafting corner ticks for any framed box */ -.ticked { position: relative; } -.ticked > .tick { position: absolute; width: 13px; height: 13px; border: 1.5px solid var(--accent); opacity: .7; pointer-events: none; z-index: 3; } -.tick.tl { top: -1px; left: -1px; border-right: 0; border-bottom: 0; } -.tick.tr { top: -1px; right: -1px; border-left: 0; border-bottom: 0; } -.tick.bl { bottom: -1px; left: -1px; border-right: 0; border-top: 0; } -.tick.br { bottom: -1px; right: -1px; border-left: 0; border-top: 0; } - /* ============================================================================= HERO ========================================================================== */ @@ -92,9 +91,14 @@ section { position: relative; padding: clamp(4rem, 9vw, 8rem) 0; } .hero h1.statement { font-size: clamp(2.4rem, 6vw, 4.4rem); } .hero .lede { font-size: var(--text-lg); max-width: 42ch; } .hero-cta { display: flex; flex-wrap: wrap; gap: .8rem; margin-top: 2rem; } -.hero-hint { margin-top: 1.5rem; display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; } -.hero-hint .chip { font-family: var(--font-mono); font-size: .64rem; letter-spacing: .08em; color: var(--ink-faint); padding: .26rem .55rem; border: 1px solid var(--line); border-radius: 5px; background: color-mix(in srgb, var(--surface) 50%, transparent); } -.hero-hint .chip b { color: var(--ink-soft); font-weight: 600; } + +/* install band sits directly under the hero — no big top padding, the hero + already provides the gap; keep modest space before the next section */ +.install-section { padding: 0 0 clamp(2.5rem, 6vw, 4.5rem); } + +/* inline links inside body ledes — accent underline, no default link colour clash */ +.lede a { color: var(--accent); text-decoration: none; border-bottom: 1px solid color-mix(in srgb, var(--accent) 40%, transparent); transition: border-color .14s; } +.lede a:hover { border-bottom-color: var(--accent); } /* ---- drafting terminal (hero showcase) ------------------------------------ */ .terminal { border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--surface); box-shadow: var(--shadow-lg); overflow: hidden; } @@ -111,7 +115,9 @@ section { position: relative; padding: clamp(4rem, 9vw, 8rem) 0; } .terminal-head .status.busy { color: var(--warn); } .terminal-head .status.busy .sdot { background: var(--warn); } -.terminal-body { display: grid; grid-template-columns: 0.96fr 1.04fr; min-height: 340px; } +/* min-height fits the fully-typed hero source (19 lines ≈ 438px) so the editor + never grows on the last lines and pushes the layout during the typing anim */ +.terminal-body { display: grid; grid-template-columns: 0.96fr 1.04fr; min-height: 440px; } @media (max-width: 560px) { .terminal-body { grid-template-columns: 1fr; } .terminal-body .sheet-pane { display: none; } } /* compact C4 nodes inside the hero terminal so they fit the narrower sheet */ .terminal .c4-node { padding: .4rem .6rem; box-shadow: 0 6px 16px -10px rgba(0,0,0,.8); } @@ -121,7 +127,8 @@ section { position: relative; padding: clamp(4rem, 9vw, 8rem) 0; } /* editor side */ .editor-pane { display: flex; min-width: 0; border-right: 1px solid var(--line); background: var(--surface); } .code-block { display: flex; width: 100%; min-width: 0; overflow: hidden; } -.code-block .gutter { flex: none; text-align: right; padding: .7rem .7rem .7rem .85rem; font-family: var(--font-mono); font-size: .68rem; line-height: 1.75; color: var(--ink-faint); user-select: none; } +/* gutter must share the code's exact line box (12.5px × 1.75) or the numbers drift off the lines */ +.code-block .gutter { flex: none; text-align: right; padding: .7rem .7rem .7rem .85rem; font-family: var(--font-mono); font-size: 12.5px; line-height: 1.75; color: var(--ink-faint); user-select: none; } .code-block .code { flex: 1; min-width: 0; padding: .7rem .85rem; font-family: var(--font-mono); font-size: 12.5px; line-height: 1.75; white-space: pre; overflow-x: auto; tab-size: 2; } .code .ln { display: block; } .cursor { display: inline-block; width: 7px; height: 1.05em; vertical-align: text-bottom; background: var(--accent); margin-left: 1px; animation: blink 1s steps(1) infinite; } @@ -163,35 +170,6 @@ section { position: relative; padding: clamp(4rem, 9vw, 8rem) 0; } .c4-node.container { --k: var(--k-container); } .c4-node.component { --k: var(--k-component); } .c4-node.data { --k: var(--k-data); } .c4-node.callable { --k: var(--k-callable); } -/* ============================================================================= - CONVERGENCE — four disciplines into one artefact - ========================================================================== */ -.converge-head { text-align: center; max-width: 56ch; margin: 0 auto 3.5rem; } -.converge-head .statement { max-width: 18ch; margin-left: auto; margin-right: auto; } -.converge-head .lede { margin-left: auto; margin-right: auto; max-width: 52ch; } -.converge { display: grid; grid-template-columns: 1fr; gap: 2.5rem; } -.flow { position: relative; display: grid; grid-template-columns: 1fr auto 1fr; gap: clamp(1rem, 3vw, 3rem); align-items: center; } -@media (max-width: 880px) { .flow { grid-template-columns: 1fr; } } -.flow-col { display: flex; flex-direction: column; gap: 1rem; } -.disc { position: relative; padding: 1.1rem 1.2rem 1.1rem 1.3rem; background: var(--surface-2); border: 1px solid var(--line-strong); border-left: 3px solid var(--k, var(--accent)); border-radius: var(--radius-sm); box-shadow: var(--shadow-sm); transition: border-color .15s, transform .15s; } -.disc:hover { border-color: var(--accent); transform: translateY(-2px); } -.disc .num { font-family: var(--font-mono); font-size: .58rem; letter-spacing: .2em; color: var(--k, var(--accent)); } -.disc h3 { margin: .35rem 0 .35rem; font-family: var(--font-display); font-size: 1.12rem; letter-spacing: -.02em; } -.disc p { margin: 0; font-size: .86rem; color: var(--ink-soft); line-height: 1.5; } -.disc.k-spec { --k: var(--k-person); } .disc.k-vibe { --k: var(--k-component); } -.disc.k-refine { --k: var(--k-container); } .disc.k-design { --k: var(--k-data); } - -.flow-core { display: grid; place-items: center; } -.core-mark { position: relative; width: clamp(140px, 22vw, 200px); aspect-ratio: 1; display: grid; place-items: center; border: 1px solid var(--line-strong); border-radius: var(--radius); background: - radial-gradient(120px 120px at 50% 40%, color-mix(in srgb, var(--accent) 14%, transparent), transparent 70%), var(--surface); box-shadow: var(--shadow-md); } -.core-mark .pulse-ring { position: absolute; inset: 0; border-radius: var(--radius); border: 1px solid var(--accent); opacity: 0; } -.core-mark.live .pulse-ring { animation: corepulse 2.6s ease-out infinite; } -@keyframes corepulse { 0% { opacity: .5; transform: scale(.9); } 70% { opacity: 0; transform: scale(1.08); } 100% { opacity: 0; } } -.core-mark .mark { width: 46%; height: 46%; color: var(--ink); } -.core-mark .core-word { position: absolute; bottom: -2.1rem; left: 50%; transform: translateX(-50%); font-family: var(--font-mono); font-size: .6rem; letter-spacing: .2em; text-transform: uppercase; color: var(--ink-faint); white-space: nowrap; } -.flow-svg { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: -1; overflow: visible; } -.flow-svg path { stroke: var(--line-strong); stroke-width: 1.5; fill: none; } - /* ============================================================================= WORKFLOW — three moments ========================================================================== */ @@ -200,7 +178,6 @@ section { position: relative; padding: clamp(4rem, 9vw, 8rem) 0; } .step.flip { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); } .step.flip .step-copy { order: 2; } @media (max-width: 860px) { .step, .step.flip { grid-template-columns: 1fr; } .step.flip .step-copy { order: 0; } } -.step-index { font-family: var(--font-mono); font-size: .72rem; letter-spacing: .2em; color: var(--accent); margin-bottom: 1rem; } .step h2.statement { font-size: clamp(1.7rem, 3.6vw, 2.6rem); } .step .lede { max-width: 40ch; } .step-visual { border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--surface); box-shadow: var(--shadow-lg); overflow: hidden; min-height: 300px; position: relative; } @@ -235,92 +212,13 @@ section { position: relative; padding: clamp(4rem, 9vw, 8rem) 0; } .seq { position: relative; padding: 1.2rem 1.3rem; background: radial-gradient(600px 360px at 70% -10%, color-mix(in srgb, var(--accent) 6%, transparent), transparent 70%), var(--bg); min-height: 260px; } .seq svg { width: 100%; height: auto; display: block; } -/* ============================================================================= - IDE SHOWCASE - ========================================================================== */ -.ide-frame { border: 1px solid var(--line-strong); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-lg); background: var(--surface); } -.ide-top { display: flex; align-items: center; gap: .8rem; height: 46px; padding: 0 .9rem; border-bottom: 1px solid var(--line); background: color-mix(in srgb, var(--surface) 80%, transparent); } -.ide-top .brand .word { font-size: .92rem; } -.ide-top .tb-ghost { font-family: var(--font-mono); font-size: .68rem; color: var(--ink-soft); border: 1px solid var(--line-strong); border-radius: var(--radius-sm); padding: .3rem .6rem; white-space: nowrap; } -.ide-top .tb-ghost .acc { color: var(--accent); } -.ide-top .sp { flex: 1; } -.ide-top .tb-format { color: var(--accent-ink); background: var(--accent); border-radius: var(--radius-sm); padding: .34rem .8rem; font-family: var(--font-sans); font-weight: 700; font-size: .76rem; } -.ide-top .tb-status { display: inline-flex; align-items: center; gap: .4rem; font-family: var(--font-mono); font-size: .68rem; color: var(--ok); white-space: nowrap; } -.ide-top .tb-status .d { width: 7px; height: 7px; border-radius: 50%; background: var(--ok); } -.ide-body { display: grid; grid-template-columns: 200px 1fr 1fr; height: 380px; } -@media (max-width: 760px) { .ide-body { grid-template-columns: 150px 1fr; } .ide-body .ide-diagram { display: none; } } -.ide-tree { border-right: 1px solid var(--line); background: var(--surface); padding: .6rem .35rem; overflow: hidden; } -.ide-tree .tree-kicker { padding: .3rem .6rem .5rem; font-family: var(--font-mono); font-size: .56rem; font-weight: 600; letter-spacing: .22em; text-transform: uppercase; color: var(--ink-faint); } -.ide-tree .trow { display: flex; align-items: center; gap: .45rem; padding: .3rem .6rem; border-radius: var(--radius-sm); font-family: var(--font-mono); font-size: .74rem; color: var(--ink-soft); } -.ide-tree .trow svg { width: 14px; height: 14px; flex: none; } -.ide-tree .trow.file { color: var(--ink); font-weight: 600; } -.ide-tree .trow.file svg { color: var(--accent); } -.ide-tree .trow.active { background: var(--accent-soft); color: var(--accent); } -.ide-tree .trow.active svg { color: var(--accent); } -.ide-tree .trow.sym { padding-left: 1.3rem; } -.ide-tree .trow.sym.person svg { color: var(--k-person); } -.ide-tree .trow.sym.system svg { color: var(--k-system); } -.ide-tree .trow.sym.container svg { color: var(--k-container); } -.ide-tree .trow.sym.data svg { color: var(--k-data); } -.ide-editor { border-right: 1px solid var(--line); display: flex; min-width: 0; overflow: hidden; background: var(--surface); } -.ide-editor .gutter { flex: none; text-align: right; padding: .6rem .7rem .6rem .85rem; font-family: var(--font-mono); font-size: .66rem; line-height: 1.75; color: var(--ink-faint); } -.ide-editor .code { flex: 1; min-width: 0; padding: .6rem .8rem; font-family: var(--font-mono); font-size: 12px; line-height: 1.75; white-space: pre; overflow: hidden; } -.ide-diagram { position: relative; background: radial-gradient(600px 360px at 60% -10%, color-mix(in srgb, var(--accent) 6%, transparent), transparent 70%), var(--bg); overflow: hidden; } -.ide-diagram .grid-dots { position: absolute; inset: 0; background-image: radial-gradient(var(--ink) 1px, transparent 1px); background-size: 22px 22px; opacity: .03; } -.ide-status { display: flex; align-items: center; gap: 1.1rem; height: 30px; padding: 0 1rem; border-top: 1px solid var(--line); background: var(--surface); font-family: var(--font-mono); font-size: .64rem; color: var(--ink-faint); } -.ide-status .seg { display: flex; align-items: center; gap: .4rem; } -.ide-status .seg .d { width: 6px; height: 6px; border-radius: 50%; background: var(--ok); } -.ide-status .sp { flex: 1; } -.ide-caps { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: 1.8rem; } -.ide-caps .cap { display: inline-flex; align-items: center; gap: .45rem; font-family: var(--font-mono); font-size: .68rem; color: var(--ink-soft); padding: .35rem .7rem; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--surface-2); } -.ide-caps .cap b { color: var(--accent); font-weight: 600; } - -/* ============================================================================= - PACKAGES / WORKSPACE - ========================================================================== */ -.pkg-grid { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr); gap: clamp(2rem, 5vw, 4rem); align-items: center; } -@media (max-width: 860px) { .pkg-grid { grid-template-columns: 1fr; } } -.manifest { border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--surface); box-shadow: var(--shadow-md); overflow: hidden; } -.manifest .mf-head { display: flex; align-items: center; gap: .5rem; height: 34px; padding: 0 .85rem; border-bottom: 1px solid var(--line); background: var(--surface-2); } -.manifest .mf-head .fname { font-family: var(--font-mono); font-size: .68rem; color: var(--ink-soft); } -.manifest pre { margin: 0; padding: .9rem 1rem; font-family: var(--font-mono); font-size: 12px; line-height: 1.8; overflow-x: auto; } -.pkg-cards { display: flex; flex-direction: column; gap: .8rem; } -.pkg { display: flex; align-items: center; gap: .9rem; padding: .85rem 1rem; background: var(--surface-2); border: 1px solid var(--line-strong); border-left: 3px solid var(--k, var(--accent)); border-radius: var(--radius-sm); transition: border-color .15s, transform .15s; } -.pkg:hover { border-color: var(--accent); transform: translateX(3px); } -.pkg .glyph { flex: none; width: 2rem; height: 2rem; display: grid; place-items: center; border: 1px solid var(--line-strong); border-radius: 6px; color: var(--k, var(--accent)); } -.pkg .glyph svg { width: 16px; height: 16px; } -.pkg .meta { flex: 1; min-width: 0; } -.pkg .meta .name { font-family: var(--font-mono); font-size: .82rem; color: var(--ink); font-weight: 600; } -.pkg .meta .name .v { color: var(--ink-faint); font-weight: 400; } -.pkg .meta .sub { font-size: .76rem; color: var(--ink-soft); } -.pkg.k-person { --k: var(--k-person); } .pkg.k-container { --k: var(--k-container); } -.pkg.k-data { --k: var(--k-data); } .pkg.k-component { --k: var(--k-component); } - /* ============================================================================= CTA / GET STARTED ========================================================================== */ .cta-band { background: radial-gradient(1000px 500px at 50% -30%, color-mix(in srgb, var(--accent) 12%, transparent), transparent 70%); border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); } -.cta-head { text-align: center; margin-bottom: 3rem; } -.start-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.1rem; } -@media (max-width: 820px) { .start-grid { grid-template-columns: 1fr; } } -.start-card { position: relative; display: flex; flex-direction: column; gap: .7rem; padding: 1.5rem 1.4rem 1.4rem; background: var(--surface-2); border: 1px solid var(--line-strong); border-radius: var(--radius); box-shadow: var(--shadow-sm); transition: border-color .15s, transform .15s, background .15s; text-decoration: none; color: inherit; overflow: hidden; } -.start-card:hover { border-color: var(--accent); transform: translateY(-3px); } -.start-card .ct { position: absolute; width: 9px; height: 9px; border: 1.5px solid var(--accent); opacity: 0; transition: opacity .15s; } -.start-card .ct.tl { top: 7px; left: 7px; border-right: 0; border-bottom: 0; } -.start-card .ct.br { bottom: 7px; right: 7px; border-left: 0; border-top: 0; } -.start-card:hover .ct { opacity: .75; } -.start-card .sc-icon { width: 2.4rem; height: 2.4rem; display: grid; place-items: center; border: 1px solid var(--line-strong); border-radius: 8px; color: var(--accent); background: var(--surface); } -.start-card .sc-icon svg { width: 20px; height: 20px; } -.start-card .sc-step { font-family: var(--font-mono); font-size: .6rem; letter-spacing: .2em; text-transform: uppercase; color: var(--ink-faint); } -.start-card h3 { margin: 0; font-family: var(--font-display); font-size: 1.18rem; letter-spacing: -.02em; } -.start-card p { margin: 0; font-size: .85rem; color: var(--ink-soft); line-height: 1.55; flex: 1; } -.start-card .sc-go { font-family: var(--font-mono); font-size: .68rem; letter-spacing: .06em; text-transform: uppercase; color: var(--accent); display: inline-flex; align-items: center; gap: .4rem; } -.start-card .sc-go svg { width: 14px; height: 14px; transition: transform .15s; } -.start-card:hover .sc-go svg { transform: translateX(3px); } -.start-card .sc-tag { font-family: var(--font-mono); font-size: .64rem; color: var(--ink-faint); } -.start-card .sc-tag b { color: var(--ink-soft); font-weight: 600; } +.cta-head { text-align: center; } /* ============================================================================= FOOTER @@ -337,6 +235,25 @@ footer { padding: clamp(3rem, 6vw, 5rem) 0 3rem; border-top: 1px solid var(--lin .foot-bottom .copy { font-family: var(--font-mono); font-size: .68rem; color: var(--ink-faint); white-space: nowrap; } .foot-bottom .copy code { color: var(--ink-soft); } +/* ============================================================================= + GENERATION SPINE — one model, many projections + A fixed left-edge index rail; the active section's tick lights accent. + ========================================================================== */ +.spine { position: fixed; left: clamp(1rem, 3vw, 2.2rem); top: 50%; transform: translateY(-50%); z-index: 70; display: flex; flex-direction: column; gap: 1.6rem; } +.spine::before { content: ""; position: absolute; left: 4px; top: -.5rem; bottom: -.5rem; width: 1px; background: var(--line); } +.spine a { position: relative; display: flex; align-items: center; gap: .65rem; padding-left: 1rem; text-decoration: none; } +.spine a::before { content: ""; position: absolute; left: 0; top: 50%; transform: translateY(-50%); width: 9px; height: 9px; border-radius: 50%; border: 1px solid var(--line-strong); background: var(--bg); transition: border-color .2s, background .2s, box-shadow .2s; } +.spine .si { font-family: var(--font-mono); font-size: .58rem; font-weight: 600; letter-spacing: .18em; color: var(--ink-faint); transition: color .2s; } +.spine .sl { font-family: var(--font-mono); font-size: .58rem; font-weight: 600; letter-spacing: .18em; text-transform: uppercase; color: var(--ink-faint); opacity: 0; transform: translateX(-4px); transition: opacity .2s, transform .2s, color .2s; } +.spine a:hover .sl, .spine a.lit .sl { opacity: 1; transform: none; color: var(--ink-soft); } +.spine a.lit .si { color: var(--accent); } +.spine a.lit::before { border-color: var(--accent); background: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); } +@media (max-width: 980px) { .spine { display: none; } } + +/* provenance tag — "from the model" above a projected artefact */ +.provenance { display: inline-flex; align-items: center; gap: .4rem; color: var(--ink-faint); letter-spacing: .14em; white-space: nowrap; } +.provenance .pv-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); flex: none; } + /* ============================================================================= SCROLL REVEAL ========================================================================== */ @@ -345,4 +262,4 @@ footer { padding: clamp(3rem, 6vw, 5rem) 0 3rem; border-top: 1px solid var(--lin .reveal.d1 { transition-delay: .08s; } .reveal.d2 { transition-delay: .16s; } .reveal.d3 { transition-delay: .24s; } .reveal.d4 { transition-delay: .32s; } body.no-motion .reveal { opacity: 1 !important; transform: none !important; } -body.no-motion .cursor, body.no-motion .core-mark.live .pulse-ring, body.no-motion .brand .dot { animation: none !important; } +body.no-motion .cursor, body.no-motion .brand .dot { animation: none !important; } diff --git a/web-landing/src/vite-env.d.ts b/web-landing/src/vite-env.d.ts new file mode 100644 index 0000000..4078e74 --- /dev/null +++ b/web-landing/src/vite-env.d.ts @@ -0,0 +1,2 @@ +/// +/// diff --git a/web-landing/tsconfig.json b/web-landing/tsconfig.json new file mode 100644 index 0000000..d404e54 --- /dev/null +++ b/web-landing/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "bundler", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "isolatedModules": true, + "verbatimModuleSyntax": true + }, + "include": ["src/**/*.ts", "src/**/*.svelte", "vite.config.*"] +} diff --git a/web-landing/vite.config.js b/web-landing/vite.config.js index 0cf4613..e7fd49e 100644 --- a/web-landing/vite.config.js +++ b/web-landing/vite.config.js @@ -3,4 +3,8 @@ import { svelte } from '@sveltejs/vite-plugin-svelte'; export default defineConfig({ plugins: [svelte()], + server: { + // allow the Tailscale-proxied host (tailscale serve sets Host to the .ts.net name) + allowedHosts: ['.ts.net'], + }, });