diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..31d6546 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,57 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +# Cancel superseded runs on the same ref to save runner minutes. +concurrency: + group: ci-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + test: + name: Unit tests + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '22' + cache: npm + + - name: Install dependencies + run: npm ci + + - name: Lint + run: npm run lint + + - name: Run tests + run: npm test + + perf: + name: Renderer perf gates + runs-on: ubuntu-latest + # Timing/FPS gates can be noisy on shared runners, so this job reports but + # does not block merges. Treat a failure here as a signal to investigate. + continue-on-error: true + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '22' + cache: npm + + - name: Install dependencies + run: npm ci + + - name: Run perf benchmark (acceptance gates) + run: node scripts/perf_benchmark.js --assert diff --git a/.gitignore b/.gitignore index 29e6524..be3c65e 100644 --- a/.gitignore +++ b/.gitignore @@ -7,10 +7,16 @@ node_modules/ dist/ +# Coverage reports (npm run test:coverage) +coverage/ + # Generated bundle (rebuilt during dist/build) src/gll.bundle.js src/gll.bundle.js.map +# Perf benchmark artifacts (regenerate via npm run perf:fixture / npm run perf) +scripts/fixtures/ + # Compiled Java class files *.class diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..089fb81 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,22 @@ +# Dependencies & environments +node_modules/ +.venv/ + +# Build output & generated artifacts +dist/ +coverage/ +src/lib/ +src/gll.bundle.js +src/gll.bundle.js.map +src/**/*_prompt.js +scripts/fixtures/ + +# Lockfiles +package-lock.json +uv.lock + +# Research manuscript (kept as-is) +manuscript/ + +# Minified vendor files +*.min.js diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..8ba3323 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,9 @@ +{ + "semi": true, + "singleQuote": true, + "printWidth": 100, + "tabWidth": 2, + "trailingComma": "es5", + "arrowParens": "always", + "endOfLine": "lf" +} diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index edf72ab..0000000 --- a/AGENTS.md +++ /dev/null @@ -1,97 +0,0 @@ -# AGENTS.md — Graph Lens Lite - -## What This Is - -Desktop/web app for visualizing and analyzing property graphs. Built with vanilla JS (ES6 modules), G6 v5 for graph rendering, Electron for desktop packaging. Single-page app, no framework. - -## Architecture - -Central `Cache` singleton (defined in `gll.js`) holds all state and manager instances. All managers receive `cache` in their constructor and access shared state through it. - -### Manager System (two layers) - -**Graph managers** (`src/graph/`) — operate on the G6 graph instance: -- `core.js` — GraphCoreManager: creates G6 instance, registers behaviors (drag, zoom, lasso, click, hover), handles render/draw cycles with event locks -- `style.js` — GraphStyleManager: applies node/edge styles, per-layout persistence -- `layout.js` — GraphLayoutManager: workspace (layout) management, stores positions/styles/filters per workspace -- `filter.js` — GraphFilterManager: range slider + dropdown filtering logic -- `selection.js` — GraphSelectionManager: selection state, undo/redo memory (25 states) -- `bubble_sets.js` — GraphBubbleSetManager: visual grouping with 4 quadrant-based groups - -**Functional managers** (`src/managers/`) — business logic and UI: -- `io.js` — IOManager: Excel/JSON file loading, export (JSON/PNG), data preprocessing, Excel template generation -- `ui.js` — UIManager: loading overlays, enable/disable UI elements, notifications -- `query.js` — QueryManager: query DSL with AST (AND/OR/NOT, BETWEEN, IN, LOWER THAN) -- `ui_components.js` — builds filter UI (DropdownChecklist, InvertibleRangeSlider), tooltips -- `ui_style_div.js` — style panel UI generation -- `metrics.js` — NetworkMetrics: degree/betweenness/closeness/eigenvector centrality, PageRank - -### Utilities (`src/utilities/`) -- `static.js` — validation, color math, deep merge helpers -- `popup.js` — modal dialog system -- `demo_loader.js` — STRING DB protein interaction demo data -- `data_editor.js` — spreadsheet-like data editor (DataTable) -- `tour.js` — guided tour with sample dataset and step-by-step walkthrough -- `color_scale_picker.js` / `numeric_scale_picker.js` — scale UIs for styling - -### Key Files -- `src/gll.js` — entry point, Cache class, initialization -- `src/config.js` — DEFAULTS (node/edge/layout styles) and CFG (behavior flags) -- `src/graph_lens_lite.html` — single-page HTML -- `src/style.css` — all styling -- `src/package/electron_app.js` — Electron main process - -## Key Patterns - -**Event locks** — `cache.EVENT_LOCKS` prevents cascading events during render/draw/drag operations. Check and set locks before critical operations. - -**Property hash system** — properties encoded as `mainGroup::subGroup::propName`. Maps bidirectionally between properties and node/edge IDs. - -**Visibility model** — filtering works through `nodeIDsToBeShown`, `edgeIDsToBeShown`, and `hiddenDanglingNodeIDs` Sets on cache. - -**Reference maps** — `nodeRef`, `edgeRef`, `propToNodeIDs`, `nodeIDToEdgeIDs` Maps on cache for O(1) lookups. - -**Workspaces** — each layout independently stores node positions, styles, filters, bubble groups, and queries. - -## Build & Run - -```bash -npm run bundle:serve # dev server with watch + sourcemaps -npm run serve # static http server on :8000 -npm start # electron app -npm test # run vitest unit tests -npm run test:watch # vitest in watch mode -npm run dist-linux # build Linux packages -npm run dist-windows # build Windows packages -npm run dist-mac # build macOS packages -``` - -## File Structure - -``` -src/ -├── gll.js # entry point + Cache singleton -├── config.js # DEFAULTS, CFG constants -├── graph_lens_lite.html # SPA page -├── style.css # all CSS -├── lib/ # vendored libs (g6.min.js, exceljs.min.js) -├── graph/ # graph managers (6 files) -├── managers/ # business logic managers (6 files + assistant/ subfolder) -├── utilities/ # helpers (7 files) -└── package/ # electron + build scripts -templates/ # Excel input templates -static/ # icons, screenshots -scripts/ # dev helpers (Excel→JSON converter, template generator, screenshots) -tests/ # vitest unit tests + manual bug reproduction HTML files -``` - -## Session Rules - -- One feature or fix per session. -- Read relevant files before modifying. Understand existing patterns. -- Do not run builds unless explicitly asked. -- Minimal in-code comments — only where logic is non-obvious. -- No docstrings, no type annotations unless already present. -- No unnecessary abstractions or over-engineering. -- Follow existing code style (no semicolons in some files, semicolons in others — match the file you're editing). -- Git commits: Conventional Commits format `(): `, ≤ 72 chars, imperative mood, no sign-offs. See CONTRIBUTING.md. diff --git a/API.md b/API.md index 45248a3..b0b09d7 100644 --- a/API.md +++ b/API.md @@ -196,26 +196,38 @@ An edge is an object. `source` and `target` are required and must match node | `id` | string | `"::"` | Explicit edge id. Auto-generated if omitted. | | `label` | string | — | Display text along the edge. | | `description` | string | — | Tooltip text. | -| `type` | string | `"line"` | `line` (straight); also `cubic`, `quadratic`, `polyline`. | +| `type` | string | `"line"` | `line` (straight); also `cubic`, `quadratic`, `polyline`. **Note:** since the Sigma renderer, `polyline` renders as a curve (same as `cubic`/`quadratic`). | | `style` | object | — | Visual styling — see below. | | `D4Data` | object | — | Data attributes that define filters — see §6. | -### `edge.style` — line, arrows, halo +### `edge.style` — line, arrows, halo, flow | Path | Type | Default | Meaning | | ---------------- | ------- | ------------- | ---------------------------------------------------- | | `stroke` | hex | `"#403C5390"` | Line colour (last 2 hex digits = alpha). | | `lineWidth` | number | `0.75` | Line thickness (px). | -| `lineDash` | number | `0` | Dash length; `0` = solid, e.g. `10` = dashed. | -| `startArrow` | boolean | `false` | Arrowhead at the source end. | -| `startArrowType` | string | `"triangle"` | `triangle`/`circle`/`diamond`/`vee`/`rect`/`simple`. | -| `startArrowSize` | number | `8` | Source arrowhead size. | -| `endArrow` | boolean | `false` | Arrowhead at the target end. | -| `endArrowType` | string | `"triangle"` | Same enum as `startArrowType`. | -| `endArrowSize` | number | `8` | Target arrowhead size. | -| `halo` | boolean | `false` | Glow behind the edge. | +| `lineDash` | number | `0` | Dash length. **Note:** kept in the data model and round-trips through export, but the Sigma renderer draws all edges solid (dashes are not rendered in v1). | +| `startArrow` | boolean | `false` | End marker at the source end. | +| `startArrowType` | string | `"arrow"` | `arrow`/`rect`/`diamond`/`circle`/`tee` (⊣ inhibition bar). Legacy G6 names still load and round-trip unchanged (`triangle`/`vee`/`simple` → arrow, `triangleRect`/`square` → rect). | +| `startArrowSize` | number | `8` | Source marker length (graph px). Unset/0 → sized proportionally to the line width. | +| `startArrowColor` | hex | `null` | Source marker fill. `null` → inherits the edge stroke colour. | +| `startArrowBorderColor` | hex | `null` | Source marker border colour. `null` → no border (transparent). | +| `startArrowBorderSize` | number | `0` | Source marker border thickness (px). `0` → auto (~20% of the marker). | +| `endArrow` | boolean | `false` | End marker at the target end. | +| `endArrowType` | string | `"arrow"` | Same enum as `startArrowType`. | +| `endArrowSize` | number | `8` | Target marker length (graph px). | +| `endArrowColor` | hex | `null` | Target marker fill. `null` → inherits the edge stroke colour. | +| `endArrowBorderColor` | hex | `null` | Target marker border colour. `null` → no border (transparent). | +| `endArrowBorderSize` | number | `0` | Target marker border thickness (px). `0` → auto (~20% of the marker). | +| `halo` | boolean | `false` | Glow drawn under the edge (total width = line + 2 × `haloLineWidth`), on straight and curved edges. Selecting an edge widens line and halo together. | | `haloStroke` | hex | `"#403C53"` | Halo colour. | | `haloLineWidth` | number | `3` | Halo thickness (px). | +| `flow` | boolean | `false` | Enable the animated source→target flow overlay. | +| `flowType` | string | `"dash"` | `dash` / `pulse` / `comet` / `chevron`. | +| `flowSpeed` | number | `1` | Animation speed multiplier. | +| `flowStroke` | hex | `null` | Flow colour. `null` → derived from the edge stroke (lightened). | +| `flowOpacity` | number | `1` | Multiplies into the overlay colour's alpha (0–1). | +| `flowDensity` | number | `1` | Scales the pattern period (higher = sparser dashes/dots). | Edge labels use the same `label*` fields as nodes (§4), with edge-specific defaults: `labelPlacement` defaults to `"center"` (`start`/`center`/`end`), diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..bc92fd9 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,149 @@ +# Architecture — Graph Lens Lite + +A map of how the codebase is organised, for contributors and anyone reading the +source. For build, version, and commit conventions see +[CONTRIBUTING.md](CONTRIBUTING.md). + +## What This Is + +A desktop/web app for visualising and analysing property graphs. Vanilla +JavaScript (ES6 modules), no UI framework — a single-page app bundled with +esbuild and packaged for the desktop with Electron. Graph rendering is +[Sigma.js](https://www.sigmajs.org/) v3 (WebGL) over a +[graphology](https://graphology.github.io/) data model, with bubble-set group +outlines from the standalone MIT [`bubblesets-js`](https://github.com/upsetjs/bubblesets-js). + +## Architecture + +A central `Cache` singleton (defined in `gll.js`) holds all state and manager +instances. Every manager receives `cache` in its constructor and reaches shared +state through it. + +Rendering is isolated behind `src/graph/sigma_adapter.js` — the sole importer of +Sigma — which presents a stable facade over the `graphology` graph held in +`src/graph/graph_model.js`. Managers talk to the adapter and the model, never to +Sigma directly. + +### Graph layer (`src/graph/`, 27 files) + +The rendering and graph-operation core. Key modules: + +- `graph_model.js` — graphology population, sigma reducers, edge-type selection +- `sigma_adapter.js` — the only Sigma importer; transitional graph-shaped facade +- `core.js` — `GraphCoreManager`: render/draw cycles, event locks, behaviour wiring +- `interactions.js` — drag, zoom, lasso, click, hover handlers +- `style.js` — per-element style resolution with defaults, per-layout persistence +- `layout.js` / `layout_algorithms.js` — workspace management; headless layouts + (force via graphology forceAtlas2; circular/grid geometric; radial/concentric/mds + via `@antv/layout` v2) +- `filter.js` — range-slider + dropdown filtering +- `selection.js` — selection state with undo/redo memory +- `bubble_sets.js` / `bubble_layer.js` / `bubble_geometry.js` — bubble-set grouping + drawn on an owned canvas layer beneath the nodes +- `heatmap_layer.js` / `heatmap_geometry.js` — node-density heatmap overlay (off by + default; toggled from the workspace toolbar) +- `edge_programs.js` / `edge_flow_programs.js` / `edge_flow_glsl.js` / + `flow_animator.js` — custom WebGL edge programs and the animated source→target + flow overlay (dash/pulse/comet/chevron) +- `label_renderers.js`, `pie_slices.js`, `shape_textures.js`, `minimap.js`, + `visible_graph.js`, `lasso_geometry.js`, `communities.js`, `export_svg.js`, + `webgl_support.js` + +### Functional managers (`src/managers/`, 7 files + `assistant/`) + +Business logic and UI: + +- `io.js` — `IOManager`: Excel/JSON loading, export (JSON / PNG / SVG), data + preprocessing, Excel template generation +- `ui.js` — loading overlays, UI enable/disable, notifications +- `query.js` — query DSL with an AST (AND/OR/NOT, BETWEEN, IN, comparisons) +- `ui_components.js` — filter UI (dropdown checklists, invertible range sliders), tooltips +- `ui_style_div.js` — the styling panel (node/edge styles, badges, edge flow, density heatmap) +- `metrics.js` — `NetworkMetrics`: degree/betweenness/closeness/eigenvector centrality, PageRank +- `api_client.js` — client for the standalone ingest service +- `assistant/` — the natural-language Graph Assistant (intent parsing, query + generation, settings, budget UI) + +### Utilities (`src/utilities/`, 12 files) + +- `static.js` — validation, colour math, deep-merge helpers +- `popup.js` / `popover_position.js` — modal and popover positioning +- `data_editor.js` — spreadsheet-like data editor (`DataTable`), incl. Excel export +- `demo_loader.js` — STRING DB protein-interaction demo data +- `tour.js` — guided tour with a sample dataset +- `color_scale_picker.js` / `numeric_scale_picker.js` / `pie_chart_picker.js` — styling pickers +- `selection_hud.js`, `theme.js`, `export_scale.js` + +### Key files + +- `src/gll.js` — entry point, `Cache` class, initialisation +- `src/config.js` — `DEFAULTS` (node/edge/layout/flow/heatmap styles) and `CFG` (behaviour flags); also the injected `VERSION` +- `src/graph_lens_lite.html` — single-page HTML +- `src/style.css` — all styling +- `src/lib/` — vendored libs: `sigma.bundle.mjs`, `graphology.bundle.mjs`, `exceljs.min.js`, `marked.esm.js`, `purify.esm.mjs` +- `src/package/` — Electron main process + build scripts (vendor bundling, version injection, HTML inlining) +- `server/` — the standalone HTTP ingest service + live viewer + +## Key Patterns + +**Event locks** — `cache.EVENT_LOCKS` prevents cascading events during +render/draw/drag operations. Check and set locks before critical operations. + +**Property hash system** — properties are encoded as `mainGroup::subGroup::propName`, +mapping bidirectionally between properties and node/edge IDs. + +**Visibility model** — filtering works through `nodeIDsToBeShown`, +`edgeIDsToBeShown`, and `hiddenDanglingNodeIDs` Sets on `cache`. + +**Reference maps** — `nodeRef`, `edgeRef`, `propToNodeIDs`, `nodeIDToEdgeIDs` +Maps on `cache` for O(1) lookups. + +**Workspaces** — each layout independently stores node positions, styles, +filters, bubble groups, and queries. + +## Build & Run + +```bash +npm install # install dependencies +npm run bundle:serve # dev server with watch + sourcemaps +npm run serve # static http-server on :8000 +npm start # Electron app +npm run serve:api # standalone ingest service (HTTP API + live viewer) +npm test # vitest unit tests +npm run test:watch # vitest in watch mode +npm run perf # performance benchmark +npm run dist-linux # build Linux packages +npm run dist-windows # build Windows packages +npm run dist-mac # build macOS packages +``` + +## File Structure + +``` +src/ +├── gll.js # entry point + Cache singleton +├── config.js # DEFAULTS, CFG, VERSION +├── graph_lens_lite.html # SPA page +├── style.css # all CSS +├── lib/ # vendored libs (sigma, graphology, exceljs, marked, purify) +├── graph/ # rendering + graph operations (27 files) +├── managers/ # business-logic managers (7 files + assistant/) +├── utilities/ # helpers (12 files) +└── package/ # Electron main process + build scripts +server/ # standalone ingest service + live viewer +templates/ # Excel input templates +static/ # icons, screenshots +scripts/ # dev helpers (Excel→JSON converter, template generator, benchmarks) +tests/ # vitest unit tests +``` + +## Code Style + +- Vanilla ES6 modules; no framework, no build-time type system. +- Minimal in-code comments — only where logic is non-obvious. No docstrings or + type annotations unless a file already uses them. +- No unnecessary abstractions or speculative generality. +- Match the surrounding file's existing style (semicolon usage varies by file). +- Commits follow Conventional Commits: `(): `, ≤ 72 chars, + imperative mood. See [CONTRIBUTING.md](CONTRIBUTING.md). + diff --git a/ASSISTANT_QUESTIONS.md b/ASSISTANT_QUESTIONS.md deleted file mode 100644 index 20a512a..0000000 --- a/ASSISTANT_QUESTIONS.md +++ /dev/null @@ -1,90 +0,0 @@ -# AI Assistant — Example Questions - -## Graph State & Overview -- What's currently visible in the graph? -- How many nodes and edges are hidden? -- What workspace am I in? -- What workspaces do I have? -- Which nodes are selected right now? -- Are there any disconnected nodes? -- What properties does this graph have? - -## Filters -- How do I filter nodes by a numeric property? -- How do I show only nodes that belong to a specific category? -- How do I reset all filters? -- What's the difference between filtering and querying? -- How do I filter edges? -- How do I hide nodes that are not connected to anything? - -## Query Editor -- How do I write a query that keeps nodes where score is between 0.5 and 1? -- How do I select nodes in category "A" or "B"? -- How do I combine two conditions with AND? -- How do I exclude nodes matching a condition using NOT? -- What's the difference between Filter and Select in the query editor? -- How do I save my query? -- Why did my custom query get overwritten? -- How do I use the Sync button? - -## Selection -- How do I select multiple nodes at once? -- How do I select all visible nodes? -- How do I undo my last selection? -- How do I deselect everything? -- How do I zoom to my selected nodes? -- What is lasso selection and how do I use it? - -## Workspaces -- How do I create a new workspace? -- How do I duplicate the current workspace? -- How do I delete a workspace? -- Are filters saved per workspace? -- How do I switch between workspaces? - -## Layouts & Arrangements -- How do I apply a force layout? -- How do I arrange selected nodes in a circle? -- How do I fit the entire graph to the screen? -- How do I save node positions? -- How do I reset node positions? - -## Metrics -- How do I compute degree centrality? -- What does betweenness centrality measure? -- How do I colour nodes by a metric score? -- How do I see the top-ranked nodes by PageRank? -- What is eigenvector centrality? - -## Styling -- How do I change the colour of selected nodes? -- How do I change node shape? -- How do I show labels on nodes? -- How do I change the edge style to dashed? -- How do I add arrows to edges? -- How do I reset the style of selected elements? - -## Bubble Groups -- What are bubble groups? -- How do I add nodes to a bubble group? -- How do I assign nodes to a group by property? -- How do I change the colour of a bubble group? -- How do I remove nodes from a group? -- How many bubble groups can I have? - -## Data & Export -- How do I load a graph from Excel? -- What format does the Excel file need to be in? -- How do I export the graph as an image? -- How do I save the full model including workspaces? -- How do I add a new node or edge? -- How do I edit node properties? -- How do I export data back to Excel? - -## Troubleshooting -- Why are some nodes not visible? -- Why did my query get cleared? -- Why are labels not showing? -- Why is the hover effect disabled? -- How do I reload a graph without losing my workspaces? -- Why are edges not appearing after I filter? diff --git a/CHANGELOG.md b/CHANGELOG.md index 50f5630..f6e8054 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,87 @@ # Changelog +## 1.15.0 — 2026-06-16 + +Existing graph files (including version-less JSON saved by 1.14.x) load unchanged — this release adds and replaces functionality without breaking the saved-file format. + +### Features + +#### Renderer migration: AntV G6 → Sigma.js (WebGL) + +The entire rendering stack moved from AntV G6 5.x (canvas) to Sigma.js v3 (WebGL nodes/edges, canvas labels) on a graphology data model. Measured on the 6000-node / 9000-edge benchmark (see `MIGRATION.md` for the full record): + +| Metric | G6 (1.14.x) | Sigma (1.15.0) | +|---|---|---| +| Load (data → rendered) | 1.6 s | 0.79 s | +| Wheel-zoom FPS | ~4 | ~60 | +| First-interaction stall | ~11 s | 64 ms | +| 500-node select | 140 ms | 46 ms | + +* All six node shapes ported (circle and square as native WebGL programs; hexagon, diamond, triangle, star as crisp SVG textures) +* Selection, hover-highlight and dim states reimplemented as sigma reducers; lasso select is a custom canvas overlay; click/shift-select, node drag with position persistence, and tooltips preserved +* Bubble groups drawn natively on a canvas layer under the nodes via `bubblesets-js`; member sync, styling UI and filter/manual membership unchanged +* Minimap and PNG export (with the bubble-set layer composited) reimplemented on sigma +* Distribution is ≈0.9 MB smaller (the 1.1 MB vendored `g6.min.js` is gone; sigma + graphology + headless layouts add ≈0.2 MB) +* Documented degradations: dashed edges render solid and polyline edges render curved (no off-the-shelf WebGL programs for either) + +#### Layouts + +* **Live-animating ForceAtlas2** driven by a web-worker supervisor, so force layouts settle visibly without blocking the UI. +* **Dagre** layered layout, **circlepack**, and **random** added to the layout options. +* **Full-workspace re-layout** control to re-run a layout across the entire workspace, with animated transitions between layouts. +* Optional **noverlap** overlap-removal post-pass. +* Headless layouts: circular/grid (geometric), radial/concentric/mds (`@antv/layout` v2). + +#### Communities & metrics + +* **Louvain community detection** (weighted, with a tunable resolution) that populates manual bubble groups directly. +* Network centralities now come from **`graphology-metrics`** instead of the hand-rolled implementations. + +#### Edges & flow + +* **Animated directional edge flow** on both straight and curved edges, with `dash`, `pulse`, `comet` and `chevron` styles plus speed, colour, opacity and density controls. +* **Edge arrow markers and halos**, with arrow fill, border-colour and border-size controls. + +#### Nodes & styling + +* **Pie-chart nodes** that render proportional slices from data. +* **GLSL circle borders** via `@sigma/node-border`. +* **Node badges** with a size control and a scale-with-node option. +* **Dark-mode toggle**. + +#### Heatmap + +* **Density heatmap overlay** — an atmospheric node-density layer beneath the graph, off by default and toggled from the workspace toolbar, with opacity, intensity, gamma/contrast, threshold, bandwidth/radius and colour-ramp controls (default / viridis / magma / accent / grayscale) plus an optional dim-graph mode. Replaces the former selection glow. +* Bubble-group label **placement, close-to-path and auto-rotate** knobs are now honoured by the renderer (previously no-ops). + +#### UI + +* Reworked **selection grouping and selection-driven styling cards**. +* **Compact, density-aware filter panel** redesign; redesigned selection, styling and toolbar surfaces for clarity. +* Selection HUD now defaults to the **top-right corner** and snaps to a grid; tooltips are suppressed during shift+click multi-select. +* Subtle **top-centre loading indicator** card; compact header. + +#### Export & IO + +* **SVG vector export** alongside JSON and PNG; high-resolution PNG export. +* JSON saves now carry a top-level **`version`** stamp; loading a file saved by a newer app surfaces a soft notice (older and version-less files load as before). +* The **density-heatmap** overlay (enabled state + appearance settings) is saved into the JSON export and restored on load. + +### Performance + +* Network metrics are computed **lazily, only while the metrics panel is open**. +* Removed the automatic disabling of hover effects on large graphs (no longer needed on the WebGL renderer). + +### Fixes + +* Fixed slow deselection when clicking empty canvas on large graphs (antvis/G6#7195) — removed from Known Issues. +* PNG export: corrected dark-mode background, hi-res scaling and label z-order; dropped the unreliable 8× scale and added a GPU framebuffer ceiling margin so high-res exports no longer come out blurry or blank. +* Anchored popovers are clamped to the viewport so the right edge never truncates. +* Float filter sliders use a continuous step so a column's maximum value stays selectable. +* Heavy layouts keep the UI blocked on large graphs until the layout completes. +* The reset-style button no longer claims to reset node positions. +* Graceful guard when WebGL2 is unavailable, plus a redraw after container resize. + ## 1.14.2 ### Features @@ -14,6 +96,7 @@ The ingest service now supports optional per-session graphs, so multiple apps or * The live viewer reads `?session=` from its own URL and subscribes to the matching stream (works at the service root and behind a reverse-proxy sub-path) * Session ids are bounded (`^[A-Za-z0-9_-]{1,64}$`, `400` otherwise) and the server holds at most 64 sessions with least-recently-used eviction; the live-viewer cap (100) spans all sessions * Handoff pattern documented in [API.md](API.md) §2.1 and [SERVICE.md](SERVICE.md) +* `install-service.sh` / `update-service.sh` scripts for deploying the ingest service as a systemd unit ## 1.14.1 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..d2d7f15 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,83 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at matthias.ley@delta4.ai. All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of actions. + +**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at [https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/MIGRATION.md b/MIGRATION.md new file mode 100644 index 0000000..cba5c48 --- /dev/null +++ b/MIGRATION.md @@ -0,0 +1,171 @@ +# Migration: AntV G6 → Sigma.js v3 + +**Status: COMPLETE (v1.15.0, 2026-06-10).** All phases (0–6) landed on +`feat/sigma-renderer`; G6 is removed. This document is kept as the +architectural record of the cutover. + +Full cutover of the rendering stack from AntV G6 5.0.48 (canvas) to Sigma.js v3 + +graphology + bubblesets-js. G6 is removed entirely at the end; no dual-renderer +period. Work happens on a long-lived feature branch (`feat/sigma-renderer`) and +merges when the parity checklist below passes. + +## Why (measured 2026-06-10, 6000 nodes / 9000 edges, AMD Radeon 890M) + +| Metric | G6 canvas | G6 WebGL (`@antv/g-webgl`) | +|---|---|---| +| Initial load → rendered | 1.6 s | 55 s | +| Full `graph.render()` | ~10 s (includes layout) | 88–205 s, degrades per call | +| Pure redraw `graph.draw()` | 0.65 s | 90 s | +| Wheel zoom | **~4 FPS (~500 ms/tick)** | unusable | +| Warm drag-pan | ~163 FPS (fine) | unusable | +| First pan/zoom after load | **~11 s stall** (lazy init) | n/a | +| Select 500 nodes | 0.14 s | 21 s | + +- G6's WebGL renderer was spiked and rejected (10–100× slower than canvas). +- G6's `optimize-viewport-transform` behavior was tested and rejected (zoom 4 FPS + with vs 5 FPS without; it hides edges but nodes dominate zoom cost). +- The canvas pain (wheel zoom re-rendering every node, 11 s first-interaction + stall, 10 s full renders) is inherent to G6 at >10k elements. No tuning path + remains on the current stack. + +## Target stack + +| Concern | Library | Notes | +|---|---|---| +| Rendering | `sigma` v3 (WebGL nodes/edges, canvas labels) | MIT, actively maintained | +| Graph model | `graphology` + relevant `graphology-*` utils | replaces G6's internal data store | +| Bubble sets | `bubblesets-js` (standalone, MIT) | the SAME library G6's plugin wraps — outline geometry is renderer-agnostic. Drawn on a custom sigma canvas layer under the node layer; issue #7195 disappears with G6 | +| Layouts | keep `@antv/layout` headlessly (positions in → positions out) for force/radial/concentric/mds; circular + grid as trivial geometric functions | layouts were never the perf problem; replace opportunistically later. Alternative: `graphology-layout-forceatlas2` (web-worker build) for force | +| Node shapes | `@sigma/node-square` + texture-based shapes via `@sigma/node-image` (rasterize hexagon/diamond/triangle/star as SVG textures); circle is native | custom GLSL programs only if texture quality disappoints | +| Curved edges | `@sigma/edge-curve` | maps cubic/quadratic; polyline degrades to curve (note in UI docs) | +| PNG export | `@sigma/export-image` | replaces `graph.toDataURL` | +| Vendoring | esbuild bundle into `src/lib/` (same pattern as `src/package/vendor_libs.js` / `build` scripts); removes 1.12 MB `g6.min.js` | sigma+graphology ≈ 200 kB minified | + +## Concept mapping (G6 → Sigma) + +| G6 | Sigma/graphology | +|---|---| +| `new Graph({data, node.state, edge.state, behaviors, plugins})` | `new Sigma(graphologyGraph, container, settings)`; states → `nodeReducer`/`edgeReducer`; behaviors → explicit event handlers; plugins → custom layers / DOM | +| `updateData / updateNodeData / updateEdgeData` | graphology `setNodeAttribute` etc.; sigma re-renders reactively (`refresh()` when batching) | +| `render()` (async, layout+draw) | layout is explicit (run algorithm → write x/y attributes); `sigma.refresh()` is sync and cheap | +| `draw()` | `sigma.refresh({ skipIndexation: true })` for pure visual updates | +| `setElementState(map)` | maintain app-level Sets (`cache.selectedNodes` already exists) + `refresh`; reducers read them | +| `getElementState(id)` | read the same app-level Sets — G6 round-trips disappear | +| states `selected/highlight/dim` + halo | reducers return modified `color/size/zIndex/borderColor`; "halo" via border program or a bigger ghost node — decide in Phase 2 | +| `hover-activate` (1-degree) | `enterNode` event + `graph.neighbors()` + reducers (already gated by `DISABLE_HOVER_EFFECT` thresholds — keep them) | +| `drag-element` | `downNode` + mousemove → `graphToViewport`/`viewportToGraph`, standard sigma recipe | +| `drag-canvas` / `zoom-canvas` | built-in camera; `animation: false` equivalents via camera API options | +| `lasso-select` | custom canvas overlay + point-in-polygon over node viewport coords (no library dependency; ~150 LOC) | +| `click-select` (shift-multi) | `clickNode` event + modifier check | +| tooltip plugin | pure DOM positioned via `graphToViewport` on `clickNode` — `cache.toolTips` content generation is unchanged | +| minimap plugin | custom canvas layer rendering node positions at thumbnail scale (~100 LOC), or defer to a later release (decide at Phase 4) | +| bubble-sets plugin (4 groups) | `bubblesets-js` fed with node viewport rects + avoid rects → path2D on a `beforeLayer` canvas; group labels drawn on the same layer. `GraphBubbleSetManager` member/filter logic is renderer-agnostic and survives | +| `fitView / zoomTo / getZoom / translateBy` | `camera.animatedReset / camera.setState / getState` — also deletes the G6 zoom-at-non-1.0 workaround in `core.js` | +| `toDataURL` | `@sigma/export-image` | +| `setElementZIndex` (drag z-fix) | `zIndex` attribute via reducer; G6 workaround deleted | + +## Phases + +Each phase ends with tests green and a working app on the branch. + +### Phase 0 — Scaffolding (small) +- Branch `feat/sigma-renderer`; add deps; extend the esbuild vendoring so dev + serve (`npm run serve`), Electron, bundle, and inline-html dist all load sigma. +- Commit a benchmark fixture generator + Playwright perf script under `scripts/` + (recreate: 6000 nodes / 9000 edges, 8 clusters, deterministic seed; measure + load, wheel-zoom FPS, drag-pan FPS, 500-node select). These are the + acceptance gates and prevent regressions during the port. + +### Phase 1 — Data model + core lifecycle (medium) +- `Cache.iterNodes/iterEdges` populate a graphology `Graph` (keep `nodeRef` + Maps initially; collapse later — graphology attributes can become the single + source of truth in Phase 6). +- Rewrite `GraphCoreManager.createGraphInstance` (`src/graph/core.js:166`) and + `decideToRenderOrDraw` (`core.js:111`): render/draw distinction becomes + layout-vs-refresh. The `AFTER_DRAW`/`AFTER_RENDER` event-lock choreography + simplifies — sigma refresh is synchronous. +- Port `GraphFilterManager`: filtered elements get `hidden: true` attributes + (sigma reducers skip hidden cheaply) — same Sets (`nodeIDsToBeShown` etc.). + +### Phase 2 — Visual parity (medium-large) +- Node programs: circle native, square package, hexagon/diamond/triangle/star + as SVG textures via node-image. Per-node `type`/`style` from + `GraphStyleManager` maps to sigma attributes; per-layout style Maps unchanged. +- Edge rendering: straight + curved + arrows; lineDash needs a custom program + or is dropped for v1 (flag in UI docs). +- Labels: sigma's label density system replaces `MAX_NODES_BEFORE_HIDING_LABELS` + (keep the CFG as an override). Node + edge label styling parity. +- States via reducers: selected (border/halo), highlight, dim — colors from + `config.js` state specs. + +### Phase 3 — Interactions (medium) +- Node drag (with position persistence via `lm.persistNodePositions`), + click/shift-select, hover-activate with existing thresholds, lasso overlay, + hotkeys (renderer-agnostic already), tooltip. +- Delete G6 workarounds: lasso/canvas-click event juggling + (`APPLY_BUBBLE_SET_HOTFIX` paths), dragend zIndex reset, zoom-translate quirk. + +### Phase 4 — Overlays (medium) +- Bubble sets: custom layer + `bubblesets-js`; wire `GraphBubbleSetManager` + (member sync + style UI survive as-is; only the draw target changes). + `avoidMembers` becomes cheap — re-evaluate the + `MAX_NODES_BEFORE_DISABLING_AVOID_MEMBERS_IN_BUBBLE_GROUPS` threshold. +- PNG export; minimap (build or consciously defer). + +### Phase 5 — Layouts (small-medium) +- Wire `@antv/layout` (or FA2 worker) behind `GraphLayoutManager.applyLayout`; + circular/grid as geometric functions. Custom layout = position Maps, already + renderer-agnostic. Force layout for authored payloads without positions + (see commit b6f8606) must keep working. + +### Phase 6 — Cleanup + release (small) +- Remove `src/lib/g6.min.js`, the `G6` global destructures, `APPLY_BUBBLE_SET_HOTFIX`, + stale thresholds; collapse duplicate state between `nodeRef` and graphology + if not done earlier. Update README/API.md/CHANGELOG; bundle-size check + (expect ≈ −900 kB); minor version bump. + +## Files touched (from the 2026-06-10 audit; ~60 G6 call sites) + +| File | Work | +|---|---| +| `src/gll.js` | drop `G6` destructure; graphology instance in `Cache` | +| `src/graph/core.js` | full rewrite (instance, events, viewport, states) | +| `src/graph/layout.js` | layout execution + position persistence rewiring | +| `src/graph/selection.js` | swap state round-trips for app-level Sets + refresh | +| `src/graph/bubble_sets.js` | draw target → custom layer; logic survives | +| `src/graph/style.js`, `src/graph/filter.js` | attribute mapping only | +| `src/managers/ui.js` | behavior toggling → handler enable/disable | +| `src/managers/io.js`, `ui_components.js`, `metrics.js`, `api_client.js`, `query.js` | `getNodeData()/getEdgeData()` call sites → graphology reads | +| `server/*` | untouched (verified renderer-agnostic) | +| `tests/*` | new unit tests for reducers, lasso geometry, bubble-set layer, layout adapters (≥80 % on new modules); existing 622 tests must stay green | + +## Acceptance criteria (the merge gate) + +Perf at 15k elements (the Phase 0 harness): load ≤ 2 s · wheel zoom ≥ 30 FPS +(currently 4) · warm drag-pan ≥ 60 FPS · no first-interaction stall > 500 ms +(currently ~11 s) · 500-node select < 200 ms. + +Functional parity: 6 node shapes, edge styles (minus documented lineDash/polyline +degradations), labels + thresholds, all 4 bubble groups incl. styling UI and +filter/manual membership, lasso + click + shift-select, hover highlight, tooltip, +drag with persistence, all layouts incl. custom, Excel/JSON import-export +round-trip, PNG export, SSE live ingest (`?session=`), Electron + inline-html +dist builds. + +## Known risks + +1. **Shape fidelity via textures** (crisp at high zoom?) — prototype hexagon in + Phase 2 first; fall back to custom GLSL program if needed. +2. **lineDash / polyline edges** — no off-the-shelf sigma support; scope as + documented degradation or custom program. +3. **Minimap** — custom build; defer if Phase 4 runs long. +4. **Excel style round-trip** — exported styles must map back losslessly; + add a round-trip test early in Phase 2. +5. **Icon/texture-heavy styling at scale** — sigma's known weak spot; the + benchmark harness catches it. + +## Next-session kickoff prompt + +> Read MIGRATION.md and start the Sigma.js migration: create the +> `feat/sigma-renderer` branch and implement Phase 0 (deps, vendoring, benchmark +> harness with the acceptance gates), then continue with Phase 1. diff --git a/README.md b/README.md index 0ae311c..c09c9c7 100644 --- a/README.md +++ b/README.md @@ -34,9 +34,9 @@ Then: |:-----------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------:| | Open Excel or JSON files, explore demo networks, or take a tour; zero install with portable versions | Write expressive queries with boolean logic, nested conditions, and range operators to filter your graph | Lasso select elements, undo and redo, focus and expand neighborhoods, and group nodes visually | | Graph canvas with filters | Network metrics and data editor | Styling panel | -| Filter by any property using range sliders and dropdown checklists, inspect node and edge metadata via tooltips, and navigate large graphs with a minimap | Compute centrality metrics like degree, betweenness, closeness, eigenvector, and PageRank, and edit your graph data live in a built-in spreadsheet | Customize shapes, sizes, colors, labels, halos, badges, arrows, and bubble set appearance per element | +| Filter by any property using range sliders and dropdown checklists, inspect node and edge metadata via tooltips, and navigate large graphs with a minimap | Compute centrality metrics like degree, betweenness, closeness, eigenvector, and PageRank, and edit your graph data live in a built-in spreadsheet | Customize shapes, sizes, colors, labels, halos, badges, arrows, pie-chart nodes, animated edge flow, and bubble set appearance per element, with an optional density-heatmap overlay | | Workspace management | Graph Assistant | Numerical color mapping | -| Create independent workspaces, each preserving their own node positions, styles, filters, and bubble set groups | Ask questions in plain English — the assistant translates them into filters, queries, and styling actions | Map numeric properties to continuous color gradients with configurable stops, and export graphs as JSON, PNG, or Excel | +| Create independent workspaces, each preserving their own node positions, styles, filters, and bubble set groups | Ask questions in plain English — the assistant translates them into filters, queries, and styling actions | Map numeric properties to continuous color gradients with configurable stops, and export graphs as JSON, PNG, SVG, or Excel | ## Development @@ -74,7 +74,7 @@ Open `http://127.0.0.1:7637/` and the pushed graph appears; further pushes updat ## Contributing -Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) before filing issues or submitting pull requests. +Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) before filing issues or submitting pull requests. See [ARCHITECTURE.md](ARCHITECTURE.md) for a map of the codebase. ## License @@ -82,8 +82,7 @@ MIT — see [LICENSE](LICENSE) for details. ## Known Issues -1. Deselection by clicking on empty spaces in the canvas takes a long time on large graphs (see [GitHub issue](https://github.com/antvis/G6/issues/7195)) -2. The Query Editor cursor tends to change position on multiline queries +1. The Query Editor cursor tends to change position on multiline queries ## Disclaimer diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..c3872ca --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,53 @@ +# Security Policy + +## Supported versions + +Graph Lens Lite is distributed as versioned releases. Security fixes are +applied to the latest minor release line; please upgrade before reporting. + +| Version | Supported | +| ------- | ------------------ | +| 1.15.x | :white_check_mark: | +| < 1.15 | :x: | + +## Reporting a vulnerability + +**Please do not open public GitHub issues for security vulnerabilities.** + +Report privately through either channel: + +- **GitHub Security Advisories** — use *Security → Report a vulnerability* on + the [repository](https://github.com/Delta4AI/GraphLensLite/security/advisories/new) + (preferred; keeps disclosure coordinated). +- **Email** — with subject `GLL security`. + +Please include: + +- affected version and platform (Windows / Linux / macOS / browser build), +- a description of the issue and its impact, +- reproduction steps or a proof-of-concept, +- any suggested remediation. + +We aim to acknowledge reports within **5 business days** and to provide a +remediation timeline after triage. We will credit reporters in the release +notes unless you prefer to remain anonymous. + +## Scope and threat model + +Graph Lens Lite has two attack surfaces worth calling out: + +1. **The desktop app (Electron renderer).** The app loads graph data from + local JSON and Excel files. Treat loaded files as untrusted input: node, + edge, property, and layout names are escaped before being rendered. Reports + of injection (HTML/script) via crafted graph files are in scope. + +2. **The optional ingest service (`server/`).** When running `npm run serve:api`, + an HTTP endpoint accepts pushed graph data. It is authenticated with a bearer + token (`GLL_API_TOKEN`) and binds to loopback (`127.0.0.1`) by default. If you + change `GLL_API_HOST` to `0.0.0.0`, you are responsible for placing it behind + a firewall or reverse proxy. Auth bypass, request-smuggling, path traversal, + and denial-of-service against this endpoint are in scope. + +Out of scope: issues that require an already-compromised host, social +engineering, or attacks that depend on the user disabling the documented +loopback default without further protection. diff --git a/SERVICE.md b/SERVICE.md index 0a9ac25..6b04913 100644 --- a/SERVICE.md +++ b/SERVICE.md @@ -24,7 +24,7 @@ npm run serve:api On start the service prints the viewer URL and the ingest endpoint: ``` -Graph Lens Lite service v1.13.1 +Graph Lens Lite service vX.Y.Z Viewer: http://127.0.0.1:7637/ Ingest: POST http://127.0.0.1:7637/api/graph ``` diff --git a/THIRD_PARTY_NOTICES b/THIRD_PARTY_NOTICES index 3334642..8db8167 100644 --- a/THIRD_PARTY_NOTICES +++ b/THIRD_PARTY_NOTICES @@ -1,195 +1,782 @@ THIRD PARTY NOTICES Graph Lens Lite -The following third‑party software is included in this project. The full license texts are provided below. -No NOTICE files were provided by these dependencies, unless stated. +The following third-party software is bundled into the distributed +application (Electron desktop builds and the inline single-file HTML). +Each package is listed with its SPDX license identifier, source, and +copyright notice; the full text of every distinct license used appears +in the "Full License Texts" section at the end. + +This file is generated from the production dependency tree by +scripts/gen_third_party_notices.mjs — do not edit by hand. ------------------------------------------------------------ -electron +@antv/event-emitter@0.1.3 License: MIT -Source: https://github.com/electron/electron -Copyright (c) Electron contributors -Copyright (c) 2013-2020 GitHub Inc. - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - +Source: https://github.com/antvis/event-emitter ------------------------------------------------------------ -electron-builder +@antv/expr@1.0.2 License: MIT -Source: https://github.com/electron-userland/electron-builder -Copyright (c) 2015 Loopline Systems - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - +Source: https://github.com/antvis/expr +Copyright (c) 2025 bqxbqx ------------------------------------------------------------ -esbuild +@antv/graphlib@2.0.4 License: MIT -Source: https://github.com/evanw/esbuild -Copyright (c) 2020 Evan Wallace - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - +Source: https://github.com/antvis/graphlib +Copyright (c) 2022 AntV team +------------------------------------------------------------ +@antv/layout@2.0.0 +License: MIT +Source: https://github.com/antvis/layout +Copyright (c) 2018 Alipay.inc +------------------------------------------------------------ +@antv/util@3.3.11 +License: MIT +Source: https://github.com/antvis/util +Copyright (c) 2021 AntV +------------------------------------------------------------ +@sigma/edge-curve@3.1.0 +License: MIT +Source: http://github.com/jacomyal/sigma.js +Copyright (C) 2013-2024, Alexis Jacomy, Guillaume Plique, Benoît Simard https://www.sigmajs.org +------------------------------------------------------------ +@sigma/export-image@3.0.0 +License: MIT +Source: http://github.com/jacomyal/sigma.js +Copyright (C) 2013-2024, Alexis Jacomy, Guillaume Plique, Benoît Simard https://www.sigmajs.org +------------------------------------------------------------ +@sigma/node-border@3.0.0 +License: MIT +Source: http://github.com/jacomyal/sigma.js +Copyright (C) 2013-2024, Alexis Jacomy, Guillaume Plique, Benoît Simard https://www.sigmajs.org +------------------------------------------------------------ +@sigma/node-image@3.0.0 +License: MIT +Source: http://github.com/jacomyal/sigma.js +Copyright (C) 2013-2024, Alexis Jacomy, Guillaume Plique, Benoît Simard https://www.sigmajs.org +------------------------------------------------------------ +@sigma/node-piechart@3.0.1 +License: MIT +Source: http://github.com/jacomyal/sigma.js +Copyright (C) 2013-2025, Alexis Jacomy, Guillaume Plique, Benoît Simard https://www.sigmajs.org +------------------------------------------------------------ +@sigma/node-square@3.0.0 +License: MIT +Source: http://github.com/jacomyal/sigma.js +Copyright (C) 2013-2024, Alexis Jacomy, Guillaume Plique, Benoît Simard https://www.sigmajs.org +------------------------------------------------------------ +@types/trusted-types@2.0.7 +License: MIT +Source: https://github.com/DefinitelyTyped/DefinitelyTyped +Copyright (c) Microsoft Corporation. +------------------------------------------------------------ +@yomguithereal/helpers@1.1.1 +License: MIT +Source: https://github.com/Yomguithereal/helpers +Copyright (c) 2018 Guillaume Plique (Yomguithereal) +------------------------------------------------------------ +bubblesets-js@3.0.1 +License: MIT +Source: https://github.com/upsetjs/bubblesets-js +Copyright (c) 2021-2022 Samuel Gratzl +------------------------------------------------------------ +comlink@4.4.2 +License: Apache-2.0 +Source: https://github.com/GoogleChromeLabs/comlink +Copyright 2017 Google Inc. +------------------------------------------------------------ +d3-binarytree@1.0.2 +License: MIT +Source: https://github.com/vasturiano/d3-binarytree +Copyright (c) 2017 Vasco Asturiano +------------------------------------------------------------ +d3-dispatch@3.0.1 +License: ISC +Source: https://github.com/d3/d3-dispatch +Copyright 2010-2021 Mike Bostock +------------------------------------------------------------ +d3-force@3.0.0 +License: ISC +Source: https://github.com/d3/d3-force +Copyright 2010-2021 Mike Bostock +------------------------------------------------------------ +d3-force-3d@3.0.6 +License: MIT +Source: https://github.com/vasturiano/d3-force-3d +Copyright (c) 2017 Vasco Asturiano +------------------------------------------------------------ +d3-octree@1.1.0 +License: MIT +Source: https://github.com/vasturiano/d3-octree +Copyright (c) 2017 Vasco Asturiano +------------------------------------------------------------ +d3-quadtree@3.0.1 +License: ISC +Source: https://github.com/d3/d3-quadtree +Copyright 2010-2021 Mike Bostock ------------------------------------------------------------ -exceljs +d3-timer@3.0.1 +License: ISC +Source: https://github.com/d3/d3-timer +Copyright 2010-2021 Mike Bostock +------------------------------------------------------------ +dompurify@3.4.10 +License: (MPL-2.0 OR Apache-2.0) +Source: https://github.com/cure53/DOMPurify +------------------------------------------------------------ +electron@36.9.5 +License: MIT +Source: https://github.com/electron/electron +Copyright (c) Electron contributors +------------------------------------------------------------ +events@3.3.0 +License: MIT +Source: https://github.com/Gozala/events +------------------------------------------------------------ +exceljs@4.4.0 License: MIT Source: https://github.com/exceljs/exceljs Copyright (c) 2014-2019 Guyon Roche - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ------------------------------------------------------------ -inline-source +fast-deep-equal@3.1.3 License: MIT -Source: https://github.com/popeindustries/inline-source -Copyright (c) 2011-2022 Pope-Industries alex@pope-industries.com - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - +Source: https://github.com/epoberezkin/fast-deep-equal +Copyright (c) 2017 Evgeny Poberezkin ------------------------------------------------------------ -inline-source-cli +file-saver@2.0.5 License: MIT -Source: https://github.com/popeindustries/inline-source-cli -Copyright (c) 2016 Jason Miller - -MIT License +Source: https://github.com/eligrey/FileSaver.js +Copyright © 2016 [Eli Grey][1]. +------------------------------------------------------------ +gl-matrix@3.4.4 +License: MIT +Source: https://github.com/toji/gl-matrix +Copyright (c) 2015-2025, Brandon Jones, Colin MacKenzie IV. +------------------------------------------------------------ +graphlib@2.1.8 +License: MIT +Source: https://github.com/dagrejs/graphlib +Copyright (c) 2012-2014 Chris Pettitt +------------------------------------------------------------ +graphology@0.26.0 +License: MIT +Source: https://github.com/graphology/graphology +Copyright (c) 2016-2021 Guillaume Plique (Yomguithereal) +------------------------------------------------------------ +graphology-communities-louvain@2.0.2 +License: MIT +Source: https://github.com/graphology/graphology +Copyright (c) 2017-2021 Guillaume Plique (Yomguithereal) +------------------------------------------------------------ +graphology-indices@0.17.0 +License: MIT +Source: https://github.com/graphology/graphology +Copyright (c) 2020-2021 Guillaume Plique (Yomguithereal) +------------------------------------------------------------ +graphology-layout@0.6.1 +License: MIT +Source: https://github.com/graphology/graphology +Copyright (c) 2016-2021 Guillaume Plique (Yomguithereal) +------------------------------------------------------------ +graphology-layout-forceatlas2@0.10.1 +License: MIT +Source: https://github.com/graphology/graphology +Copyright (c) 2016-2021 Guillaume Plique (Yomguithereal) +------------------------------------------------------------ +graphology-layout-noverlap@0.4.2 +License: MIT +Source: https://github.com/graphology/graphology +Copyright (c) 2016-2021 Guillaume Plique (Yomguithereal) +------------------------------------------------------------ +graphology-metrics@2.4.0 +License: MIT +Source: https://github.com/graphology/graphology +Copyright (c) 2017-2021 Guillaume Plique (Yomguithereal) +------------------------------------------------------------ +graphology-shortest-path@2.1.0 +License: MIT +Source: https://github.com/graphology/graphology +Copyright (c) 2017-2021 Guillaume Plique (Yomguithereal) +------------------------------------------------------------ +graphology-types@0.24.8 +License: MIT +Source: https://github.com/graphology/graphology +Copyright (c) 2020-2021 Guillaume Plique (Yomguithereal) +------------------------------------------------------------ +graphology-utils@2.5.2 +License: MIT +Source: https://github.com/graphology/graphology +Copyright (c) 2017-2021 Guillaume Plique (Yomguithereal) +------------------------------------------------------------ +is-any-array@3.0.0 +License: MIT +Source: https://github.com/cheminfo-js/is-any-array +Copyright (c) 2018 cheminfo +------------------------------------------------------------ +lodash@4.17.21 +License: MIT +Source: lodash/lodash +------------------------------------------------------------ +marked@18.0.2 +License: MIT +Source: https://github.com/markedjs/marked +Copyright (c) 2018+, MarkedJS (https://github.com/markedjs/) +------------------------------------------------------------ +ml-array-max@2.0.0 +License: MIT +Source: https://github.com/mljs/array +Copyright (c) 2017 ml.js +------------------------------------------------------------ +ml-array-min@2.0.0 +License: MIT +Source: https://github.com/mljs/array +Copyright (c) 2017 mljs +------------------------------------------------------------ +ml-array-rescale@2.0.0 +License: MIT +Source: https://github.com/mljs/array +Copyright (c) 2017 mljs +------------------------------------------------------------ +ml-matrix@6.12.2 +License: MIT +Source: https://github.com/mljs/matrix +Copyright (c) 2014 Michaël Zasso +------------------------------------------------------------ +mnemonist@0.39.8 +License: MIT +Source: https://github.com/yomguithereal/mnemonist +Copyright (c) 2016 Guillaume Plique (Yomguithereal) +------------------------------------------------------------ +obliterator@2.0.5 +License: MIT +Source: https://github.com/yomguithereal/obliterator +Copyright (c) 2017-2021 Guillaume Plique (Yomguithereal) +------------------------------------------------------------ +pandemonium@2.4.1 +License: MIT +Source: https://github.com/yomguithereal/pandemonium +Copyright (c) 2017-2020 Guillaume Plique (Yomguithereal) +------------------------------------------------------------ +polygon-clipping@0.15.7 +License: MIT +Source: https://github.com/mfogel/polygon-clipping +Copyright (c) 2018 Mike Fogel - covers everything not specially attributed to others below. +------------------------------------------------------------ +robust-predicates@3.0.3 +License: Unlicense +Source: https://github.com/mourner/robust-predicates +------------------------------------------------------------ +sigma@3.0.3 +License: MIT +Source: http://github.com/jacomyal/sigma.js +Copyright (C) 2013-2025, Alexis Jacomy, Guillaume Plique, Benoît Simard https://www.sigmajs.org +------------------------------------------------------------ +splaytree@3.2.3 +License: MIT +Source: https://github.com/w8r/splay-tree +------------------------------------------------------------ +tslib@2.8.1 +License: 0BSD +Source: https://github.com/Microsoft/tslib +Copyright (c) Microsoft Corporation. +------------------------------------------------------------ -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +Full License Texts -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +------------------------------------------------------------ +(MPL-2.0 OR Apache-2.0) +------------------------------------------------------------ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. ------------------------------------------------------------ -rimraf -License: Blue Oak Model License 1.0.0 -Source: https://github.com/isaacs/rimraf +0BSD +------------------------------------------------------------ +Copyright (c) Microsoft Corporation. -Blue Oak Model License +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. -Version 1.0.0 -Purpose +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. -This license gives everyone as much permission to work with this software as possible, while protecting contributors from liability. -Acceptance +------------------------------------------------------------ +Apache-2.0 +------------------------------------------------------------ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2017 Google Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. -In order to receive this license, you must agree to its rules. The rules of this license are both obligations under that agreement and conditions to your license. You must not do anything with this software that triggers a rule that you cannot or will not follow. -Copyright +------------------------------------------------------------ +ISC +------------------------------------------------------------ +Copyright 2010-2021 Mike Bostock -Each contributor licenses you to do everything with this software that would otherwise infringe that contributor's copyright in it. -Notices +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. -You must ensure that everyone who gets a copy of any part of this software from you, with or without changes, also gets the text of this license or a link to https://blueoakcouncil.org/license/1.0.0. -Excuse +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. -If anyone notifies you in writing that you have not complied with Notices, you can keep your license by taking all practical steps to comply within 30 days after the notice. If you do not do so, your license ends immediately. -Patent +------------------------------------------------------------ +MIT +------------------------------------------------------------ +Copyright (c) Electron contributors +Copyright (c) 2013-2020 GitHub Inc. -Each contributor licenses you to do everything with this software that would otherwise infringe any patent claims they can license or become able to license. -Reliability +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -No contributor can revoke this license. -No Liability +------------------------------------------------------------ +Unlicense +------------------------------------------------------------ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to -As far as the law allows, this software comes as is, without any warranty or condition, and no contributor will be liable to anyone for any damages related to this software or this license, under any kind of legal claim. \ No newline at end of file diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..e6c47ba --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,86 @@ +import js from '@eslint/js'; +import globals from 'globals'; +import prettier from 'eslint-config-prettier'; + +// Flat config. Vendored/generated/build artifacts are not linted. Rules are +// tuned so the existing codebase passes clean; correctness-risk patterns are +// errors, stylistic noise is downgraded to warnings. +export default [ + { + ignores: [ + 'node_modules/**', + 'dist/**', + 'coverage/**', + 'src/lib/**', // vendored third-party bundles + 'src/gll.bundle.js', // generated esbuild bundle + 'src/gll.bundle.js.map', + 'src/**/*_prompt.js', // generated prompt strings + 'manuscript/**', + 'scripts/fixtures/**', + ], + }, + + js.configs.recommended, + + // Browser-side application source (ES modules). + { + files: ['src/**/*.{js,mjs}'], + ignores: ['src/package/**'], + languageOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + globals: { ...globals.browser, ...globals.worker }, + }, + rules: { + 'no-unused-vars': ['warn', { args: 'none', ignoreRestSiblings: true }], + 'no-empty': ['warn', { allowEmptyCatch: true }], + 'no-console': 'off', + }, + }, + + // Node-side code: Electron main, build/packaging scripts, dev server, tooling. + { + files: [ + 'src/package/**/*.{js,mjs}', + 'server/**/*.{js,mjs}', + 'scripts/**/*.{js,mjs}', + '*.config.js', + '*.mjs', + ], + languageOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + globals: { ...globals.node }, + }, + rules: { + 'no-unused-vars': ['warn', { args: 'none', ignoreRestSiblings: true }], + 'no-console': 'off', + }, + }, + + // CommonJS files in src/package use require()/module.exports. + { + files: ['src/package/**/*.js'], + languageOptions: { + sourceType: 'commonjs', + globals: { ...globals.node }, + }, + }, + + // Vitest test suites (jsdom or node per-file). + { + files: ['tests/**/*.{js,mjs}'], + languageOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + globals: { ...globals.browser, ...globals.node, ...globals.vitest }, + }, + rules: { + 'no-unused-vars': 'off', + 'no-console': 'off', + }, + }, + + // Turn off rules that conflict with Prettier formatting. + prettier, +]; diff --git a/package-lock.json b/package-lock.json index 1bc2ba6..a8e3ada 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,28 +1,104 @@ { "name": "graph-lens-lite", - "version": "1.14.1", + "version": "1.15.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "graph-lens-lite", - "version": "1.14.1", + "version": "1.15.0", + "license": "MIT", "dependencies": { - "dompurify": "^3.4.1", - "marked": "^18.0.2" + "@antv/layout": "^2.0.0", + "@sigma/edge-curve": "^3.1.0", + "@sigma/export-image": "^3.0.0", + "@sigma/node-border": "^3.0.0", + "@sigma/node-image": "^3.0.0", + "@sigma/node-piechart": "3.0.1", + "@sigma/node-square": "^3.0.0", + "bubblesets-js": "^3.0.1", + "dompurify": "^3.4.10", + "graphology": "^0.26.0", + "graphology-communities-louvain": "^2.0.2", + "graphology-layout": "^0.6.1", + "graphology-layout-forceatlas2": "^0.10.1", + "graphology-layout-noverlap": "^0.4.2", + "graphology-metrics": "^2.4.0", + "marked": "^18.0.2", + "polygon-clipping": "^0.15.7", + "sigma": "^3.0.3" }, "devDependencies": { + "@eslint/js": "^9.39.4", + "@vitest/coverage-v8": "^4.1.9", "electron": "^36.3.1", "electron-builder": "^26.0.12", "esbuild": "^0.25.11", + "eslint": "^9.39.4", + "eslint-config-prettier": "^10.1.8", "exceljs": "^4.4.0", + "globals": "^17.6.0", "inline-source": "^8.0.3", "inline-source-cli": "^1.2.0", "jsdom": "^29.0.2", + "playwright": "^1.60.0", + "prettier": "^3.8.4", "rimraf": "^6.0.1", "vitest": "^4.0.18" } }, + "node_modules/@antv/event-emitter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@antv/event-emitter/-/event-emitter-0.1.3.tgz", + "integrity": "sha512-4ddpsiHN9Pd4UIlWuKVK1C4IiZIdbwQvy9i7DUSI3xNJ89FPUFt8lxDYj8GzzfdllV0NkJTRxnG+FvLk0llidg==", + "license": "MIT" + }, + "node_modules/@antv/expr": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@antv/expr/-/expr-1.0.2.tgz", + "integrity": "sha512-vrfdmPHkTuiS5voVutKl2l06w1ihBh9A8SFdQPEE+2KMVpkymzGOF1eWpfkbGZ7tiFE15GodVdhhHomD/hdIwg==", + "license": "MIT" + }, + "node_modules/@antv/graphlib": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@antv/graphlib/-/graphlib-2.0.4.tgz", + "integrity": "sha512-zc/5oQlsdk42Z0ib1mGklwzhJ5vczLFiPa1v7DgJkTbgJ2YxRh9xdarf86zI49sKVJmgbweRpJs7Nu5bIiwv4w==", + "license": "MIT", + "dependencies": { + "@antv/event-emitter": "^0.1.3" + } + }, + "node_modules/@antv/layout": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@antv/layout/-/layout-2.0.0.tgz", + "integrity": "sha512-aCZ3UdNc40SfT7meFV7QTADY2HCnc0DShVw56CJNTI6oExUIVU736grPuL5Dhb8/JrVaU4Y83QPN/P7KafBzlw==", + "license": "MIT", + "dependencies": { + "@antv/event-emitter": "^0.1.3", + "@antv/expr": "^1.0.2", + "@antv/graphlib": "^2.0.0", + "@antv/util": "^3.3.2", + "comlink": "^4.4.1", + "d3-force": "^3.0.0", + "d3-force-3d": "^3.0.5", + "d3-octree": "^1.0.2", + "d3-quadtree": "^3.0.1", + "dagre": "^0.8.5", + "ml-matrix": "^6.10.4", + "tslib": "^2.8.1" + } + }, + "node_modules/@antv/util": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/@antv/util/-/util-3.3.11.tgz", + "integrity": "sha512-FII08DFM4ABh2q5rPYdr0hMtKXRgeZazvXaFYCs7J7uTcWDHUhczab2qOCJLNDugoj8jFag1djb7wS9ehaRYBg==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "gl-matrix": "^3.3.0", + "tslib": "^2.3.1" + } + }, "node_modules/@asamuzakjp/css-color": { "version": "5.1.11", "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.11.tgz", @@ -95,6 +171,66 @@ "dev": true, "license": "MIT" }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "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/parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/@bramus/specificity": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/@bramus/specificity/-/specificity-2.4.2.tgz", @@ -798,6 +934,40 @@ "node": ">= 10.0.0" } }, + "node_modules/@emnapi/core": { + "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": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "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": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "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": { + "tslib": "^2.4.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.11", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.11.tgz", @@ -1240,6 +1410,211 @@ "node": ">=18" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", + "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.14.0", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.5", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", + "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@exodus/bytes": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.0.tgz", @@ -1310,6 +1685,72 @@ "dev": true, "license": "MIT" }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -1467,9 +1908,9 @@ "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", "dependencies": { @@ -1555,6 +1996,25 @@ "node": ">= 10.0.0" } }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.5.tgz", + "integrity": "sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, "node_modules/@npmcli/fs": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", @@ -1614,6 +2074,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@oxc-project/types": { + "version": "0.133.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.133.0.tgz", + "integrity": "sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -1625,24 +2095,27 @@ "node": ">=14" } }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz", - "integrity": "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==", + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.3.tgz", + "integrity": "sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==", "cpu": [ - "arm" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "android" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz", - "integrity": "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==", + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.3.tgz", + "integrity": "sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==", "cpu": [ "arm64" ], @@ -1650,27 +2123,16 @@ "license": "MIT", "optional": true, "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz", - "integrity": "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==", - "cpu": [ - "arm64" + "darwin" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz", - "integrity": "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==", + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.3.tgz", + "integrity": "sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==", "cpu": [ "x64" ], @@ -1679,26 +2141,15 @@ "optional": true, "os": [ "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz", - "integrity": "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==", - "cpu": [ - "arm64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz", - "integrity": "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==", + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.3.tgz", + "integrity": "sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==", "cpu": [ "x64" ], @@ -1707,26 +2158,15 @@ "optional": true, "os": [ "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz", - "integrity": "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==", - "cpu": [ - "arm" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz", - "integrity": "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==", + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.3.tgz", + "integrity": "sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==", "cpu": [ "arm" ], @@ -1735,26 +2175,15 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz", - "integrity": "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==", - "cpu": [ - "arm64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz", - "integrity": "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==", + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.3.tgz", + "integrity": "sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==", "cpu": [ "arm64" ], @@ -1763,54 +2192,32 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz", - "integrity": "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==", - "cpu": [ - "loong64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz", - "integrity": "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==", + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.3.tgz", + "integrity": "sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==", "cpu": [ - "loong64" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz", - "integrity": "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==", - "cpu": [ - "ppc64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz", - "integrity": "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==", + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.3.tgz", + "integrity": "sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==", "cpu": [ "ppc64" ], @@ -1819,40 +2226,15 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz", - "integrity": "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz", - "integrity": "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==", - "cpu": [ - "riscv64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz", - "integrity": "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==", + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.3.tgz", + "integrity": "sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==", "cpu": [ "s390x" ], @@ -1861,12 +2243,15 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz", - "integrity": "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==", + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.3.tgz", + "integrity": "sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==", "cpu": [ "x64" ], @@ -1875,12 +2260,15 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz", - "integrity": "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==", + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.3.tgz", + "integrity": "sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==", "cpu": [ "x64" ], @@ -1889,26 +2277,15 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz", - "integrity": "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==", - "cpu": [ - "x64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz", - "integrity": "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==", + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.3.tgz", + "integrity": "sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==", "cpu": [ "arm64" ], @@ -1917,40 +2294,51 @@ "optional": true, "os": [ "openharmony" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz", - "integrity": "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==", + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.3.tgz", + "integrity": "sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==", "cpu": [ - "arm64" + "wasm32" ], "dev": true, "license": "MIT", "optional": true, - "os": [ - "win32" - ] + "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/@rollup/rollup-win32-ia32-msvc": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz", - "integrity": "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==", + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.3.tgz", + "integrity": "sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==", "cpu": [ - "ia32" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "win32" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz", - "integrity": "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==", + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.3.tgz", + "integrity": "sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==", "cpu": [ "x64" ], @@ -1959,21 +2347,74 @@ "optional": true, "os": [ "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz", - "integrity": "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==", - "cpu": [ - "x64" ], + "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==", "dev": true, + "license": "MIT" + }, + "node_modules/@sigma/edge-curve": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@sigma/edge-curve/-/edge-curve-3.1.0.tgz", + "integrity": "sha512-OFWkfAXEsm+X8l1K4K49cC0psB0gQ+gqxKA08HG5piNPdzrDZ5gG9Gza6htZ5AirOVwd/4/uq/gPpD5En+H+3Q==", "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "peerDependencies": { + "sigma": ">=3.0.0-beta.10" + } + }, + "node_modules/@sigma/export-image": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sigma/export-image/-/export-image-3.0.0.tgz", + "integrity": "sha512-6JmWle7byUzAOGE3P3ttDqn2PbdnNETyFU13i4R0G3PIZcIiVqPRpRWBkz11E89oxKEzEf1XdwQKa9VxHDMD0w==", + "license": "MIT", + "dependencies": { + "file-saver": "^2.0.5" + }, + "peerDependencies": { + "sigma": ">=3.0.0-beta.10" + } + }, + "node_modules/@sigma/node-border": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sigma/node-border/-/node-border-3.0.0.tgz", + "integrity": "sha512-mE3zUfjvJVuAMhSjiP/zdlkqe0OVTETxd04XHUwof01YqdzTk0OB4ACJIhWrwgsBXl7tTd9lPuKoroafLh8MtQ==", + "license": "MIT", + "peerDependencies": { + "sigma": ">=3.0.0-beta.17" + } + }, + "node_modules/@sigma/node-image": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sigma/node-image/-/node-image-3.0.0.tgz", + "integrity": "sha512-i4WLNPugDY4jgQEZtNSiSVj4HHXOraciXLtlgdygeUxMVEhH8PJ/+Q1vQ9f/SlKFnZQ+7vH3HnsSDW6FD9aP+g==", + "license": "MIT", + "peerDependencies": { + "sigma": ">=3.0.0-beta.10" + } + }, + "node_modules/@sigma/node-piechart": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sigma/node-piechart/-/node-piechart-3.0.1.tgz", + "integrity": "sha512-VxN9e/aKEPhw3y+3kLeDXzfbJViy2yKSe4tBx71ejA+5bQza6ioMl99R2MtWKgwXIJucZnSjcItCI8FRAs+YoQ==", + "license": "MIT", + "peerDependencies": { + "sigma": ">=3.0.0-beta.17" + } + }, + "node_modules/@sigma/node-square": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sigma/node-square/-/node-square-3.0.0.tgz", + "integrity": "sha512-hPX2oWo7WeaSe6M3D56AXsrLyg3F+7N/YsodaJh4Sw3KTce0GAFVWWPZZklu9CITz0xi3kEmlCGulqAH0cVG2w==", + "license": "MIT", + "peerDependencies": { + "sigma": ">=3.0.0-beta.17" + } }, "node_modules/@sindresorhus/is": { "version": "4.6.0", @@ -2028,6 +2469,17 @@ "node": ">=10.13.0" } }, + "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/cacheable-request": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", @@ -2070,9 +2522,9 @@ "license": "MIT" }, "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==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "dev": true, "license": "MIT" }, @@ -2093,6 +2545,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/keyv": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", @@ -2168,72 +2627,76 @@ "@types/node": "*" } }, - "node_modules/@vitest/expect": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz", - "integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==", + "node_modules/@vitest/coverage-v8": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.9.tgz", + "integrity": "sha512-G9/lgqibheLVBDRuya45EbsEXTYcWoSG+TLg7i2axuzx0Eq62eXn+aWXyaVdV5vKvFSWd6ywcX8hA7la9Pvu8g==", "dev": true, "license": "MIT", "dependencies": { - "@standard-schema/spec": "^1.0.0", - "@types/chai": "^5.2.2", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "chai": "^6.2.1", - "tinyrainbow": "^3.0.3" + "@bcoe/v8-coverage": "^1.0.2", + "@vitest/utils": "4.1.9", + "ast-v8-to-istanbul": "^1.0.0", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.2.0", + "magicast": "^0.5.2", + "obug": "^2.1.1", + "std-env": "^4.0.0-rc.1", + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/browser": "4.1.9", + "vitest": "4.1.9" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } } }, - "node_modules/@vitest/mocker": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz", - "integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==", + "node_modules/@vitest/expect": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.9.tgz", + "integrity": "sha512-vl/rYsUKcBr3SnQn166+XR5ZQcgMx3DQhFWdfli/cWpLnLUmbxZvyrJZotLFUryib+LtArYMSTJ5RbQ57ZqrlA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.0.18", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.21" + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.9", + "@vitest/utils": "4.1.9", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^6.0.0 || ^7.0.0-0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } } }, "node_modules/@vitest/pretty-format": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz", - "integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.9.tgz", + "integrity": "sha512-s0iufns3iIFitdgm+YR7g1whCAaGtXz459VS9/PqyKDEEFgYIhsHOQmXgIgDuYCt7DeQmiZT0Qe2OA2p4ZPu5A==", "dev": true, "license": "MIT", "dependencies": { - "tinyrainbow": "^3.0.3" + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/runner": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz", - "integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.9.tgz", + "integrity": "sha512-KXLMDtc7oe70+3mJfGrPUWPesswH+3sTxAMAMl8DG7I8IUQT4XW718dY5ID3vPUcmlu27CcKfY4P3h3I29SLJg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.0.18", + "@vitest/utils": "4.1.9", "pathe": "^2.0.3" }, "funding": { @@ -2241,13 +2704,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz", - "integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.9.tgz", + "integrity": "sha512-Jc7RKGNBo8Z28WYIm0Niej4xdSPByRf6mU58VpHQkd6Zh05rlnA+twjbK5HyeIGHxrzsc3mJgS43uM0CZKzaIA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.0.18", + "@vitest/pretty-format": "4.1.9", + "@vitest/utils": "4.1.9", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, @@ -2256,9 +2720,9 @@ } }, "node_modules/@vitest/spy": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz", - "integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.9.tgz", + "integrity": "sha512-fHpsS6mIi+PiEW+vcRVOMkX1oSaPKne3VOclSFICPcGOmfKgXPU5iAah+wcNcj2xPrCCmfq99IDGf+EojhhvhA==", "dev": true, "license": "MIT", "funding": { @@ -2266,14 +2730,15 @@ } }, "node_modules/@vitest/utils": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz", - "integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.9.tgz", + "integrity": "sha512-A51o8ymO5PpqlWNnBP9ZHPXDIpuMtTLlGSjN7la4US+LJzoUMyhwjA5QXlm39JexgwHKW4Xjs8Z2d3dLCXOeuA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.0.18", - "tinyrainbow": "^3.0.3" + "@vitest/pretty-format": "4.1.9", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" @@ -2289,6 +2754,12 @@ "node": ">=10.0.0" } }, + "node_modules/@yomguithereal/helpers": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@yomguithereal/helpers/-/helpers-1.1.1.tgz", + "integrity": "sha512-UYvAq/XCA7xoh1juWDYsq3W0WywOB+pz8cgVnE1b45ZfdMhBvHDrgmSFG3jXeZSr2tMTYLGHFHON+ekG05Jebg==", + "license": "MIT" + }, "node_modules/7zip-bin": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz", @@ -2316,6 +2787,16 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/agent-base": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", @@ -2354,9 +2835,9 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "license": "MIT", "dependencies": { @@ -2615,6 +3096,18 @@ "node": ">=12" } }, + "node_modules/ast-v8-to-istanbul": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.4.tgz", + "integrity": "sha512-0bC0/4bTSrnwdhU3IsZDwEdojvuPrSg59OYZfKsLRtJZ0u8VBx9DebfqqG8bRdCC0I7vjgxmPi41P0lpkhJHtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.31", + "estree-walker": "^3.0.3", + "js-tokens": "^10.0.0" + } + }, "node_modules/astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -2767,6 +3260,12 @@ "balanced-match": "^1.0.0" } }, + "node_modules/bubblesets-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/bubblesets-js/-/bubblesets-js-3.0.1.tgz", + "integrity": "sha512-EKPfysvIU5+u5RLW3mOr94wxzA3nKzqMBX0F95L95BPBDZPVgLBUnT0kJNz4UK/TXbGs8G7yEgl5MvibRBCQoQ==", + "license": "MIT" + }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -3086,6 +3585,16 @@ "node": ">= 0.4" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/camelcase": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", @@ -3409,6 +3918,12 @@ "node": ">= 0.8" } }, + "node_modules/comlink": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/comlink/-/comlink-4.4.2.tgz", + "integrity": "sha512-OxGdvBmJuNKSCMO4NTl1L47VRp6xn2wG4F/2hYzB6tiCb709otOxtEYCSvK80PtjODfXXZu8ds+Nw5kVCjqd2g==", + "license": "Apache-2.0" + }, "node_modules/commander": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", @@ -3510,6 +4025,13 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -3638,17 +4160,96 @@ "npm": ">=7.0.0" } }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } + "node_modules/d3-binarytree": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d3-binarytree/-/d3-binarytree-1.0.2.tgz", + "integrity": "sha512-cElUNH+sHu95L04m92pG73t2MEJXKu+GeKUN1TJkFsu93E5W8E9Sc3kHEGJKgenGvj19m6upSn2EunvMgMD2Yw==", + "license": "MIT" }, - "node_modules/data-urls": { + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force-3d": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/d3-force-3d/-/d3-force-3d-3.0.6.tgz", + "integrity": "sha512-4tsKHUPLOVkyfEffZo1v6sFHvGFwAIIjt/W8IThbp08DYAsXZck+2pSHEG5W1+gQgEvFLdZkYvmJAbRM2EzMnA==", + "license": "MIT", + "dependencies": { + "d3-binarytree": "1", + "d3-dispatch": "1 - 3", + "d3-octree": "1", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-octree": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-octree/-/d3-octree-1.1.0.tgz", + "integrity": "sha512-F8gPlqpP+HwRPMO/8uOu5wjH110+6q4cgJvgJT6vlpy3BEaDIKlTZrgHKZSp/i1InRpVfh4puY/kvL6MxK930A==", + "license": "MIT" + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/dagre": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz", + "integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==", + "license": "MIT", + "dependencies": { + "graphlib": "^2.1.8", + "lodash": "^4.17.15" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "dev": true, + "license": "MIT", + "engines": { + "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==", @@ -3733,6 +4334,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, "node_modules/defaults": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", @@ -3985,9 +4593,9 @@ } }, "node_modules/dompurify": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.1.tgz", - "integrity": "sha512-JahakDAIg1gyOm7dlgWSDjV4n7Ip2PKR55NIT6jrMfIgLFgWo81vdr1/QGqWtFNRqXP9UV71oVePtjqS2ebnPw==", + "version": "3.4.10", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.10.tgz", + "integrity": "sha512-0xzNv0e7oYC6yyuOGZIABPM4qtg3QxLFniDNPP4ZP90wR8Yq3zgwpRbrNiT4N3IKqDbbYFEJLV+JWEs19aZ//w==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -4396,9 +5004,9 @@ } }, "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==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", "dev": true, "license": "MIT" }, @@ -4497,7 +5105,6 @@ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", - "optional": true, "engines": { "node": ">=10" }, @@ -4505,6 +5112,181 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint": { + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", + "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "9.39.4", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/esprima": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", @@ -4519,6 +5301,42 @@ "node": ">=0.10.0" } }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", @@ -4529,6 +5347,25 @@ "@types/estree": "^1.0.0" } }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/exceljs": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/exceljs/-/exceljs-4.4.0.tgz", @@ -4617,7 +5454,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, "license": "MIT" }, "node_modules/fast-json-stable-stringify": { @@ -4627,6 +5463,13 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, "node_modules/fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -4679,6 +5522,25 @@ "node": "^12.20 || >= 14.13" } }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/file-saver": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==", + "license": "MIT" + }, "node_modules/filelist": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", @@ -4716,6 +5578,27 @@ "node": ">=0.10.0" } }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, "node_modules/foreground-child": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", @@ -4952,6 +5835,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gl-matrix": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.4.tgz", + "integrity": "sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ==", + "license": "MIT" + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -4974,6 +5863,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/glob/node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -5031,6 +5933,19 @@ "node": ">=10" } }, + "node_modules/globals": { + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.6.0.tgz", + "integrity": "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/globalthis": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", @@ -5095,36 +6010,169 @@ "dev": true, "license": "ISC" }, - "node_modules/has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", - "dev": true, + "node_modules/graphlib": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", + "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", "license": "MIT", "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" + "lodash": "^4.17.15" } }, - "node_modules/has-ansi/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, + "node_modules/graphology": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/graphology/-/graphology-0.26.0.tgz", + "integrity": "sha512-8SSImzgUUYC89Z042s+0r/vMibY7GX/Emz4LDO5e7jYXhuoWfHISPFJYjpRLUSJGq6UQ6xlenvX1p/hJdfXuXg==", "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "events": "^3.3.0" + }, + "peerDependencies": { + "graphology-types": ">=0.24.0" } }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, + "node_modules/graphology-communities-louvain": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/graphology-communities-louvain/-/graphology-communities-louvain-2.0.2.tgz", + "integrity": "sha512-zt+2hHVPYxjEquyecxWXoUoIuN/UvYzsvI7boDdMNz0rRvpESQ7+e+Ejv6wK7AThycbZXuQ6DkG8NPMCq6XwoA==", "license": "MIT", - "engines": { + "dependencies": { + "graphology-indices": "^0.17.0", + "graphology-utils": "^2.4.4", + "mnemonist": "^0.39.0", + "pandemonium": "^2.4.1" + }, + "peerDependencies": { + "graphology-types": ">=0.19.0" + } + }, + "node_modules/graphology-indices": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/graphology-indices/-/graphology-indices-0.17.0.tgz", + "integrity": "sha512-A7RXuKQvdqSWOpn7ZVQo4S33O0vCfPBnUSf7FwE0zNCasqwZVUaCXePuWo5HBpWw68KJcwObZDHpFk6HKH6MYQ==", + "license": "MIT", + "dependencies": { + "graphology-utils": "^2.4.2", + "mnemonist": "^0.39.0" + }, + "peerDependencies": { + "graphology-types": ">=0.20.0" + } + }, + "node_modules/graphology-layout": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/graphology-layout/-/graphology-layout-0.6.1.tgz", + "integrity": "sha512-m9aMvbd0uDPffUCFPng5ibRkb2pmfNvdKjQWeZrf71RS1aOoat5874+DcyNfMeCT4aQguKC7Lj9eCbqZj/h8Ag==", + "license": "MIT", + "dependencies": { + "graphology-utils": "^2.3.0", + "pandemonium": "^2.4.0" + }, + "peerDependencies": { + "graphology-types": ">=0.19.0" + } + }, + "node_modules/graphology-layout-forceatlas2": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/graphology-layout-forceatlas2/-/graphology-layout-forceatlas2-0.10.1.tgz", + "integrity": "sha512-ogzBeF1FvWzjkikrIFwxhlZXvD2+wlY54lqhsrWprcdPjopM2J9HoMweUmIgwaTvY4bUYVimpSsOdvDv1gPRFQ==", + "license": "MIT", + "dependencies": { + "graphology-utils": "^2.1.0" + }, + "peerDependencies": { + "graphology-types": ">=0.19.0" + } + }, + "node_modules/graphology-layout-noverlap": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/graphology-layout-noverlap/-/graphology-layout-noverlap-0.4.2.tgz", + "integrity": "sha512-13WwZSx96zim6l1dfZONcqLh3oqyRcjIBsqz2c2iJ3ohgs3605IDWjldH41Gnhh462xGB1j6VGmuGhZ2FKISXA==", + "license": "MIT", + "dependencies": { + "graphology-utils": "^2.3.0" + }, + "peerDependencies": { + "graphology-types": ">=0.19.0" + } + }, + "node_modules/graphology-metrics": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/graphology-metrics/-/graphology-metrics-2.4.0.tgz", + "integrity": "sha512-7WOfOP+mFLCaTJx55Qg4eY+211vr1/b3D/R3biz3SXGhAaCVcWYkfabnmO4O4WBNWANEHtVnFrGgJ0kj6MM6xw==", + "license": "MIT", + "dependencies": { + "graphology-indices": "^0.17.0", + "graphology-shortest-path": "^2.0.0", + "graphology-utils": "^2.4.4", + "mnemonist": "^0.39.0", + "pandemonium": "2.4.1" + }, + "peerDependencies": { + "graphology-types": ">=0.20.0" + } + }, + "node_modules/graphology-shortest-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/graphology-shortest-path/-/graphology-shortest-path-2.1.0.tgz", + "integrity": "sha512-KbT9CTkP/u72vGEJzyRr24xFC7usI9Es3LMmCPHGwQ1KTsoZjxwA9lMKxfU0syvT/w+7fZUdB/Hu2wWYcJBm6Q==", + "license": "MIT", + "dependencies": { + "@yomguithereal/helpers": "^1.1.1", + "graphology-indices": "^0.17.0", + "graphology-utils": "^2.4.3", + "mnemonist": "^0.39.0" + }, + "peerDependencies": { + "graphology-types": ">=0.20.0" + } + }, + "node_modules/graphology-types": { + "version": "0.24.8", + "resolved": "https://registry.npmjs.org/graphology-types/-/graphology-types-0.24.8.tgz", + "integrity": "sha512-hDRKYXa8TsoZHjgEaysSRyPdT6uB78Ci8WnjgbStlQysz7xR52PInxNsmnB7IBOM1BhikxkNyCVEFgmPKnpx3Q==", + "license": "MIT", + "peer": true + }, + "node_modules/graphology-utils": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/graphology-utils/-/graphology-utils-2.5.2.tgz", + "integrity": "sha512-ckHg8MXrXJkOARk56ZaSCM1g1Wihe2d6iTmz1enGOz4W/l831MBCKSayeFQfowgF8wd+PQ4rlch/56Vs/VZLDQ==", + "license": "MIT", + "peerDependencies": { + "graphology-types": ">=0.23.0" + } + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { "node": ">=8" } }, @@ -5210,6 +6258,13 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, "node_modules/htmlparser2": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", @@ -5341,6 +6396,16 @@ ], "license": "BSD-3-Clause" }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/immediate": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", @@ -5348,6 +6413,23 @@ "dev": true, "license": "MIT" }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -5844,6 +6926,12 @@ "node": ">= 12" } }, + "node_modules/is-any-array": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-any-array/-/is-any-array-3.0.0.tgz", + "integrity": "sha512-o4h+tylWykC4BD1vaejp6gDxoM13bwW8FGuNs4yIKpj8xbBJcRxJx8vZpq0dCr7ZDEfeKjmsi/euolKhX6f/ww==", + "license": "MIT" + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -5880,6 +6968,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -5890,6 +6988,19 @@ "node": ">=8" } }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-interactive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", @@ -5971,6 +7082,45 @@ "dev": true, "license": "ISC" }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/jackspeak": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", @@ -6030,11 +7180,28 @@ "node": "*" } }, + "node_modules/js-tokens": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", + "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", + "dev": true, + "license": "MIT" + }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -6174,6 +7341,13 @@ "dev": true, "license": "MIT" }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -6327,6 +7501,20 @@ "node": ">=0.10.0" } }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lie": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", @@ -6337,6 +7525,267 @@ "immediate": "~3.0.5" } }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/listenercount": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", @@ -6361,11 +7810,26 @@ "node": ">=0.10.0" } }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true, "license": "MIT" }, "node_modules/lodash.assign": { @@ -6453,6 +7917,13 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.union": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", @@ -6517,6 +7988,47 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, + "node_modules/magicast": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.3.tgz", + "integrity": "sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.3", + "@babel/types": "^7.29.0", + "source-map-js": "^1.2.1" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/make-fetch-happen": { "version": "10.2.1", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", @@ -6832,6 +8344,54 @@ "node": ">=10" } }, + "node_modules/ml-array-max": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ml-array-max/-/ml-array-max-2.0.0.tgz", + "integrity": "sha512-QQZ4kENwpWmyNb98UXRDFXrmtIXuXtt1+bSbda/2KA85+F+rrJP8hZk6QOkCQXM2Th9mUDYdq/PNByPdT9ID4A==", + "license": "MIT", + "dependencies": { + "is-any-array": "^3.0.0" + } + }, + "node_modules/ml-array-min": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ml-array-min/-/ml-array-min-2.0.0.tgz", + "integrity": "sha512-GRj6Ky6sW9vGL6yIjgsHmXZ9YgrdmcQ8nCxPqEGeKc6dkfYg1XDYxGFxADUjNuZyoCd5PUscWAS4N+cFaX6hFg==", + "license": "MIT", + "dependencies": { + "is-any-array": "^3.0.0" + } + }, + "node_modules/ml-array-rescale": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ml-array-rescale/-/ml-array-rescale-2.0.0.tgz", + "integrity": "sha512-2GGtKfSno94/kIloWGvpp/U5Q5vLvLrza+SAaGsLeo6Xj4mEbA6Gqx+oTfZFkxnd1grT2X007HfJNs3T5BsiVg==", + "license": "MIT", + "dependencies": { + "is-any-array": "^3.0.0", + "ml-array-max": "^2.0.0", + "ml-array-min": "^2.0.0" + } + }, + "node_modules/ml-matrix": { + "version": "6.12.2", + "resolved": "https://registry.npmjs.org/ml-matrix/-/ml-matrix-6.12.2.tgz", + "integrity": "sha512-GC+BnW+pBh8Auap8goAxY0senAmF0IEoc3HNVSfnfbvGw0buuDIYb9kAKMS1l+GiwJ1rfK2bzJ8IHhwjzATSFA==", + "license": "MIT", + "dependencies": { + "is-any-array": "^3.0.0", + "ml-array-rescale": "^2.0.0" + } + }, + "node_modules/mnemonist": { + "version": "0.39.8", + "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.39.8.tgz", + "integrity": "sha512-vyWo2K3fjrUw8YeeZ1zF0fy6Mu59RHokURlld8ymdUPjMlD9EC9ov1/YPqTgqRvUN9nTr3Gqfz29LYAmu0PHPQ==", + "license": "MIT", + "dependencies": { + "obliterator": "^2.0.1" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -6840,9 +8400,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", "dev": true, "funding": [ { @@ -6858,6 +8418,13 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, "node_modules/negotiator": { "version": "0.6.4", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", @@ -7078,6 +8645,12 @@ "node": ">= 0.4" } }, + "node_modules/obliterator": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.5.tgz", + "integrity": "sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==", + "license": "MIT" + }, "node_modules/obug": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", @@ -7115,6 +8688,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/ora": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", @@ -7178,6 +8769,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-map": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", @@ -7208,6 +8815,28 @@ "dev": true, "license": "(MIT AND Zlib)" }, + "node_modules/pandemonium": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/pandemonium/-/pandemonium-2.4.1.tgz", + "integrity": "sha512-wRqjisUyiUfXowgm7MFH2rwJzKIr20rca5FsHXCMNm1W5YPP1hCtrZfgmQ62kP7OZ7Xt+cR858aB28lu5NX55g==", + "license": "MIT", + "dependencies": { + "mnemonist": "^0.39.2" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", @@ -7373,9 +9002,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -7400,22 +9029,69 @@ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", "dev": true, - "license": "MIT", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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": ">=0.10.0" + "node": ">=18" } }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "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", - "dependencies": { - "pinkie": "^2.0.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=0.10.0" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, "node_modules/plist": { @@ -7433,10 +9109,20 @@ "node": ">=10.4.0" } }, + "node_modules/polygon-clipping": { + "version": "0.15.7", + "resolved": "https://registry.npmjs.org/polygon-clipping/-/polygon-clipping-0.15.7.tgz", + "integrity": "sha512-nhfdr83ECBg6xtqOAJab1tbksbBAOMUltN60bU+llHVOL0e5Onm1WpAXXWXVB39L8AJFssoIhEVuy/S90MmotA==", + "license": "MIT", + "dependencies": { + "robust-predicates": "^3.0.2", + "splaytree": "^3.1.0" + } + }, "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "dev": true, "funding": [ { @@ -7454,7 +9140,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", + "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -7492,6 +9178,32 @@ "node": "^12.20.0 || >=14" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.8.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.4.tgz", + "integrity": "sha512-N2MylSdi48+5N/6S5j+maeHbUSIzzZ5uOcX5Hm4QpV8Dkb1HFjfAKTKX6yNPJQD9AhcT3ifHNB66tWTTJDi11Q==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/proc-log": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-2.0.1.tgz", @@ -7739,6 +9451,16 @@ "dev": true, "license": "MIT" }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/responselike": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", @@ -7892,49 +9614,44 @@ "node": ">=8.0" } }, - "node_modules/rollup": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", - "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==", + "node_modules/robust-predicates": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.3.tgz", + "integrity": "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==", + "license": "Unlicense" + }, + "node_modules/rolldown": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.3.tgz", + "integrity": "sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.8" + "@oxc-project/types": "=0.133.0", + "@rolldown/pluginutils": "^1.0.0" }, "bin": { - "rollup": "dist/bin/rollup" + "rolldown": "bin/cli.mjs" }, "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" + "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.57.1", - "@rollup/rollup-android-arm64": "4.57.1", - "@rollup/rollup-darwin-arm64": "4.57.1", - "@rollup/rollup-darwin-x64": "4.57.1", - "@rollup/rollup-freebsd-arm64": "4.57.1", - "@rollup/rollup-freebsd-x64": "4.57.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", - "@rollup/rollup-linux-arm-musleabihf": "4.57.1", - "@rollup/rollup-linux-arm64-gnu": "4.57.1", - "@rollup/rollup-linux-arm64-musl": "4.57.1", - "@rollup/rollup-linux-loong64-gnu": "4.57.1", - "@rollup/rollup-linux-loong64-musl": "4.57.1", - "@rollup/rollup-linux-ppc64-gnu": "4.57.1", - "@rollup/rollup-linux-ppc64-musl": "4.57.1", - "@rollup/rollup-linux-riscv64-gnu": "4.57.1", - "@rollup/rollup-linux-riscv64-musl": "4.57.1", - "@rollup/rollup-linux-s390x-gnu": "4.57.1", - "@rollup/rollup-linux-x64-gnu": "4.57.1", - "@rollup/rollup-linux-x64-musl": "4.57.1", - "@rollup/rollup-openbsd-x64": "4.57.1", - "@rollup/rollup-openharmony-arm64": "4.57.1", - "@rollup/rollup-win32-arm64-msvc": "4.57.1", - "@rollup/rollup-win32-ia32-msvc": "4.57.1", - "@rollup/rollup-win32-x64-gnu": "4.57.1", - "@rollup/rollup-win32-x64-msvc": "4.57.1", - "fsevents": "~2.3.2" + "@rolldown/binding-android-arm64": "1.0.3", + "@rolldown/binding-darwin-arm64": "1.0.3", + "@rolldown/binding-darwin-x64": "1.0.3", + "@rolldown/binding-freebsd-x64": "1.0.3", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.3", + "@rolldown/binding-linux-arm64-gnu": "1.0.3", + "@rolldown/binding-linux-arm64-musl": "1.0.3", + "@rolldown/binding-linux-ppc64-gnu": "1.0.3", + "@rolldown/binding-linux-s390x-gnu": "1.0.3", + "@rolldown/binding-linux-x64-gnu": "1.0.3", + "@rolldown/binding-linux-x64-musl": "1.0.3", + "@rolldown/binding-openharmony-arm64": "1.0.3", + "@rolldown/binding-wasm32-wasi": "1.0.3", + "@rolldown/binding-win32-arm64-msvc": "1.0.3", + "@rolldown/binding-win32-x64-msvc": "1.0.3" } }, "node_modules/safe-buffer": { @@ -8074,6 +9791,16 @@ "dev": true, "license": "ISC" }, + "node_modules/sigma": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sigma/-/sigma-3.0.3.tgz", + "integrity": "sha512-5H0zFlx6/NTQpqBg4Rm569ZOpnBOXMaS25UQThIWMU3XyzI5AhmorK/gnl87BvJBLhQd0tW4C0LIp3enWzMoNw==", + "license": "MIT", + "dependencies": { + "events": "^3.3.0", + "graphology-utils": "^2.5.2" + } + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -8244,6 +9971,15 @@ "dev": true, "license": "CC0-1.0" }, + "node_modules/splaytree": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/splaytree/-/splaytree-3.2.3.tgz", + "integrity": "sha512-7OXrNWzy6CK+r7Ch9OLPBDTKfB6XlWHjX4P0RU5B3IgFuWPeYN0XtRtlexGRjgbQxpfaUve6jTAwBGWuGntz/w==", + "license": "MIT", + "engines": { + "node": ">=18.20 || >=20" + } + }, "node_modules/sprintf-js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", @@ -8282,9 +10018,9 @@ } }, "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.1.0.tgz", + "integrity": "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==", "dev": true, "license": "MIT" }, @@ -8369,6 +10105,19 @@ "node": ">=0.10.0" } }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/sumchecker": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", @@ -8674,14 +10423,14 @@ } }, "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "license": "MIT", "dependencies": { "fdir": "^6.5.0", - "picomatch": "^4.0.3" + "picomatch": "^4.0.4" }, "engines": { "node": ">=12.0.0" @@ -8691,9 +10440,9 @@ } }, "node_modules/tinyrainbow": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", - "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", + "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", "dev": true, "license": "MIT", "engines": { @@ -8786,6 +10535,25 @@ "utf8-byte-length": "^1.0.1" } }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-fest": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", @@ -9004,85 +10772,100 @@ "node": ">=0.6.0" } }, - "node_modules/vite": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", - "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "node_modules/vitest": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.9.tgz", + "integrity": "sha512-nE3/LEyc0z87uHYLZebqCUOaJr2hdtuPp7BQ4BosVFnfltxgAvMG08NyrSGlPpOUWvR27c5flSmYFTNr78L9GQ==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.27.0", - "fdir": "^6.5.0", + "@vitest/expect": "4.1.9", + "@vitest/mocker": "4.1.9", + "@vitest/pretty-format": "4.1.9", + "@vitest/runner": "4.1.9", + "@vitest/snapshot": "4.1.9", + "@vitest/spy": "4.1.9", + "@vitest/utils": "4.1.9", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", - "tinyglobby": "^0.2.15" + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" }, "bin": { - "vite": "bin/vite.js" + "vitest": "vitest.mjs" }, "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" }, "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" + "url": "https://opencollective.com/vitest" }, "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" + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.9", + "@vitest/browser-preview": "4.1.9", + "@vitest/browser-webdriverio": "4.1.9", + "@vitest/coverage-istanbul": "4.1.9", + "@vitest/coverage-v8": "4.1.9", + "@vitest/ui": "4.1.9", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { - "@types/node": { + "@edge-runtime/vm": { "optional": true }, - "jiti": { + "@opentelemetry/api": { "optional": true }, - "less": { + "@types/node": { "optional": true }, - "lightningcss": { + "@vitest/browser-playwright": { "optional": true }, - "sass": { + "@vitest/browser-preview": { "optional": true }, - "sass-embedded": { + "@vitest/browser-webdriverio": { "optional": true }, - "stylus": { + "@vitest/coverage-istanbul": { "optional": true }, - "sugarss": { + "@vitest/coverage-v8": { "optional": true }, - "terser": { + "@vitest/ui": { "optional": true }, - "tsx": { + "happy-dom": { "optional": true }, - "yaml": { + "jsdom": { "optional": true + }, + "vite": { + "optional": false } } }, - "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", - "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", + "node_modules/vitest/node_modules/@esbuild/aix-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", "cpu": [ "ppc64" ], @@ -9092,14 +10875,15 @@ "os": [ "aix" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", - "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", + "node_modules/vitest/node_modules/@esbuild/android-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", "cpu": [ "arm" ], @@ -9109,14 +10893,15 @@ "os": [ "android" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", - "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", + "node_modules/vitest/node_modules/@esbuild/android-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", "cpu": [ "arm64" ], @@ -9126,14 +10911,15 @@ "os": [ "android" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", - "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", + "node_modules/vitest/node_modules/@esbuild/android-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", "cpu": [ "x64" ], @@ -9143,14 +10929,15 @@ "os": [ "android" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", - "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", + "node_modules/vitest/node_modules/@esbuild/darwin-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", "cpu": [ "arm64" ], @@ -9160,14 +10947,15 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", - "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", + "node_modules/vitest/node_modules/@esbuild/darwin-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", "cpu": [ "x64" ], @@ -9177,14 +10965,15 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", - "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", + "node_modules/vitest/node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", "cpu": [ "arm64" ], @@ -9194,14 +10983,15 @@ "os": [ "freebsd" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", - "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", + "node_modules/vitest/node_modules/@esbuild/freebsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", "cpu": [ "x64" ], @@ -9211,14 +11001,15 @@ "os": [ "freebsd" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", - "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", + "node_modules/vitest/node_modules/@esbuild/linux-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", "cpu": [ "arm" ], @@ -9228,14 +11019,15 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", - "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", + "node_modules/vitest/node_modules/@esbuild/linux-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", "cpu": [ "arm64" ], @@ -9245,14 +11037,15 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", - "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", + "node_modules/vitest/node_modules/@esbuild/linux-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", "cpu": [ "ia32" ], @@ -9262,14 +11055,15 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", - "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", + "node_modules/vitest/node_modules/@esbuild/linux-loong64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", "cpu": [ "loong64" ], @@ -9279,14 +11073,15 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", - "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", + "node_modules/vitest/node_modules/@esbuild/linux-mips64el": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", "cpu": [ "mips64el" ], @@ -9296,14 +11091,15 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", - "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", + "node_modules/vitest/node_modules/@esbuild/linux-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", "cpu": [ "ppc64" ], @@ -9313,14 +11109,15 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", - "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", + "node_modules/vitest/node_modules/@esbuild/linux-riscv64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", "cpu": [ "riscv64" ], @@ -9330,14 +11127,15 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", - "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", + "node_modules/vitest/node_modules/@esbuild/linux-s390x": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", "cpu": [ "s390x" ], @@ -9347,14 +11145,15 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", - "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", + "node_modules/vitest/node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", "cpu": [ "x64" ], @@ -9364,14 +11163,15 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", - "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", + "node_modules/vitest/node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", "cpu": [ "arm64" ], @@ -9381,14 +11181,15 @@ "os": [ "netbsd" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", - "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", + "node_modules/vitest/node_modules/@esbuild/netbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", "cpu": [ "x64" ], @@ -9398,14 +11199,15 @@ "os": [ "netbsd" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", - "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", + "node_modules/vitest/node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", "cpu": [ "arm64" ], @@ -9415,14 +11217,15 @@ "os": [ "openbsd" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", - "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", + "node_modules/vitest/node_modules/@esbuild/openbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", "cpu": [ "x64" ], @@ -9432,14 +11235,15 @@ "os": [ "openbsd" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", - "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "node_modules/vitest/node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", "cpu": [ "arm64" ], @@ -9449,14 +11253,15 @@ "os": [ "openharmony" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", - "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", + "node_modules/vitest/node_modules/@esbuild/sunos-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", "cpu": [ "x64" ], @@ -9466,14 +11271,15 @@ "os": [ "sunos" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", - "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", + "node_modules/vitest/node_modules/@esbuild/win32-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", "cpu": [ "arm64" ], @@ -9483,14 +11289,15 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", - "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", + "node_modules/vitest/node_modules/@esbuild/win32-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", "cpu": [ "ia32" ], @@ -9500,14 +11307,15 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", - "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", + "node_modules/vitest/node_modules/@esbuild/win32-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", "cpu": [ "x64" ], @@ -9517,17 +11325,47 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">=18" } }, - "node_modules/vite/node_modules/esbuild": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", - "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", + "node_modules/vitest/node_modules/@vitest/mocker": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.9.tgz", + "integrity": "sha512-EVkXzBjrPGM+cK8/ANWgBrkUCfJfb38/EfTSO8h7pWvKkyPkpWxvR7BkD2MyItMF62C97zAEoqdpUixwR/e+Rw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.9", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", "dev": true, "hasInstallScript": true, "license": "MIT", + "optional": true, + "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -9535,108 +11373,108 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.3", - "@esbuild/android-arm": "0.27.3", - "@esbuild/android-arm64": "0.27.3", - "@esbuild/android-x64": "0.27.3", - "@esbuild/darwin-arm64": "0.27.3", - "@esbuild/darwin-x64": "0.27.3", - "@esbuild/freebsd-arm64": "0.27.3", - "@esbuild/freebsd-x64": "0.27.3", - "@esbuild/linux-arm": "0.27.3", - "@esbuild/linux-arm64": "0.27.3", - "@esbuild/linux-ia32": "0.27.3", - "@esbuild/linux-loong64": "0.27.3", - "@esbuild/linux-mips64el": "0.27.3", - "@esbuild/linux-ppc64": "0.27.3", - "@esbuild/linux-riscv64": "0.27.3", - "@esbuild/linux-s390x": "0.27.3", - "@esbuild/linux-x64": "0.27.3", - "@esbuild/netbsd-arm64": "0.27.3", - "@esbuild/netbsd-x64": "0.27.3", - "@esbuild/openbsd-arm64": "0.27.3", - "@esbuild/openbsd-x64": "0.27.3", - "@esbuild/openharmony-arm64": "0.27.3", - "@esbuild/sunos-x64": "0.27.3", - "@esbuild/win32-arm64": "0.27.3", - "@esbuild/win32-ia32": "0.27.3", - "@esbuild/win32-x64": "0.27.3" - } - }, - "node_modules/vitest": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz", - "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/expect": "4.0.18", - "@vitest/mocker": "4.0.18", - "@vitest/pretty-format": "4.0.18", - "@vitest/runner": "4.0.18", - "@vitest/snapshot": "4.0.18", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "es-module-lexer": "^1.7.0", - "expect-type": "^1.2.2", - "magic-string": "^0.30.21", - "obug": "^2.1.1", - "pathe": "^2.0.3", - "picomatch": "^4.0.3", - "std-env": "^3.10.0", - "tinybench": "^2.9.0", - "tinyexec": "^1.0.2", - "tinyglobby": "^0.2.15", - "tinyrainbow": "^3.0.3", - "vite": "^6.0.0 || ^7.0.0", - "why-is-node-running": "^2.3.0" + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + } + }, + "node_modules/vitest/node_modules/vite": { + "version": "8.0.16", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.16.tgz", + "integrity": "sha512-h9bXPmJichP5fLmVQo3PyaGSDE2n3aPuomeAlVRm0JLmt4rY6zmPKd59HYI4LNW8oTK7tlTsuC7l/m7awx9Jcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.32.0", + "picomatch": "^4.0.4", + "postcss": "^8.5.15", + "rolldown": "1.0.3", + "tinyglobby": "^0.2.17" }, "bin": { - "vitest": "vitest.mjs" + "vite": "bin/vite.js" }, "engines": { - "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^20.19.0 || >=22.12.0" }, "funding": { - "url": "https://opencollective.com/vitest" + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" }, "peerDependencies": { - "@edge-runtime/vm": "*", - "@opentelemetry/api": "^1.9.0", - "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.0.18", - "@vitest/browser-preview": "4.0.18", - "@vitest/browser-webdriverio": "4.0.18", - "@vitest/ui": "4.0.18", - "happy-dom": "*", - "jsdom": "*" + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.1.18", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.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": { - "@edge-runtime/vm": { + "@types/node": { "optional": true }, - "@opentelemetry/api": { + "@vitejs/devtools": { "optional": true }, - "@types/node": { + "esbuild": { "optional": true }, - "@vitest/browser-playwright": { + "jiti": { "optional": true }, - "@vitest/browser-preview": { + "less": { "optional": true }, - "@vitest/browser-webdriverio": { + "sass": { "optional": true }, - "@vitest/ui": { + "sass-embedded": { "optional": true }, - "happy-dom": { + "stylus": { "optional": true }, - "jsdom": { + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { "optional": true } } @@ -9772,6 +11610,16 @@ "node": ">= 0.10.0" } }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", diff --git a/package.json b/package.json index e44915b..837552d 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,17 @@ { "name": "graph-lens-lite", - "version": "1.14.2", + "version": "1.15.0", "main": "src/package/electron_app.js", "description": "Visualise and explore property graphs in a lightweight desktop app.", "homepage": "https://github.com/Delta4AI/GraphLensLite", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/Delta4AI/GraphLensLite.git" + }, + "bugs": { + "url": "https://github.com/Delta4AI/GraphLensLite/issues" + }, "author": { "name": "Matthias Ley", "email": "matthias.ley@delta4.ai" @@ -27,11 +35,19 @@ "dist-linux": "npm run dist:prep:linux && electron-builder --linux --publish=never && npm run substitute-gll end", "dist-mac": "npm run dist:prep && electron-builder --mac --publish=never && npm run substitute-gll end", "dist": "npm run dist-linux && npm run dist-windows", - "serve": "npm run vendor-libs && npx http-server src -p 8000 --cors -o /graph_lens_lite.html ", + "serve": "npm run vendor-libs && npx http-server src -p 8000 --cors -c-1 -o /graph_lens_lite.html ", "serve:api": "npm run vendor-libs && node --env-file-if-exists=.env server/index.js", "version": "npm run inject-version && git add src/config.js", "test": "vitest run", - "test:watch": "vitest" + "test:watch": "vitest", + "test:coverage": "vitest run --coverage", + "lint": "eslint src server scripts tests", + "lint:fix": "eslint src server scripts tests --fix", + "format": "prettier --write .", + "format:check": "prettier --check .", + "perf:fixture": "node scripts/generate_benchmark_fixture.js", + "perf": "node scripts/perf_benchmark.js", + "notices": "node scripts/gen_third_party_notices.mjs" }, "build": { "appId": "com.delta4ai.graphlenslite", @@ -65,18 +81,41 @@ } }, "devDependencies": { + "@eslint/js": "^9.39.4", + "@vitest/coverage-v8": "^4.1.9", "electron": "^36.3.1", "electron-builder": "^26.0.12", "esbuild": "^0.25.11", + "eslint": "^9.39.4", + "eslint-config-prettier": "^10.1.8", "exceljs": "^4.4.0", + "globals": "^17.6.0", "inline-source": "^8.0.3", "inline-source-cli": "^1.2.0", "jsdom": "^29.0.2", + "playwright": "^1.60.0", + "prettier": "^3.8.4", "rimraf": "^6.0.1", "vitest": "^4.0.18" }, "dependencies": { - "dompurify": "^3.4.1", - "marked": "^18.0.2" + "@antv/layout": "^2.0.0", + "@sigma/edge-curve": "^3.1.0", + "@sigma/export-image": "^3.0.0", + "@sigma/node-border": "^3.0.0", + "@sigma/node-image": "^3.0.0", + "@sigma/node-piechart": "3.0.1", + "@sigma/node-square": "^3.0.0", + "bubblesets-js": "^3.0.1", + "dompurify": "^3.4.10", + "graphology": "^0.26.0", + "graphology-communities-louvain": "^2.0.2", + "graphology-layout": "^0.6.1", + "graphology-layout-forceatlas2": "^0.10.1", + "graphology-layout-noverlap": "^0.4.2", + "graphology-metrics": "^2.4.0", + "marked": "^18.0.2", + "polygon-clipping": "^0.15.7", + "sigma": "^3.0.3" } } diff --git a/scripts/gen_third_party_notices.mjs b/scripts/gen_third_party_notices.mjs new file mode 100644 index 0000000..8b05381 --- /dev/null +++ b/scripts/gen_third_party_notices.mjs @@ -0,0 +1,134 @@ +#!/usr/bin/env node +// Regenerates THIRD_PARTY_NOTICES from the actual bundled (production) dependency +// tree. Reads each package's license metadata and LICENSE file straight from +// node_modules and writes the notice file — no hand-maintained drift. Run: +// node scripts/gen_third_party_notices.mjs +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); +const NM = path.join(ROOT, 'node_modules'); +const OUT = path.join(ROOT, 'THIRD_PARTY_NOTICES'); + +// Bundled/redistributed packages: the production dependency closure plus the +// Electron runtime (a devDependency by install, but shipped inside the app). +const PACKAGES = [ + 'electron', + '@antv/event-emitter', '@antv/expr', '@antv/graphlib', '@antv/layout', '@antv/util', + '@sigma/edge-curve', '@sigma/export-image', '@sigma/node-border', '@sigma/node-image', + '@sigma/node-piechart', '@sigma/node-square', '@types/trusted-types', '@yomguithereal/helpers', + 'bubblesets-js', 'comlink', 'd3-binarytree', 'd3-dispatch', 'd3-force', 'd3-force-3d', + 'd3-octree', 'd3-quadtree', 'd3-timer', 'dompurify', 'events', 'exceljs', 'fast-deep-equal', + 'file-saver', 'gl-matrix', 'graphlib', 'graphology', 'graphology-communities-louvain', + 'graphology-indices', 'graphology-layout', 'graphology-layout-forceatlas2', + 'graphology-layout-noverlap', 'graphology-metrics', 'graphology-shortest-path', + 'graphology-types', 'graphology-utils', 'is-any-array', 'lodash', 'marked', 'ml-array-max', + 'ml-array-min', 'ml-array-rescale', 'ml-matrix', 'mnemonist', 'obliterator', 'pandemonium', + 'polygon-clipping', 'robust-predicates', 'sigma', 'splaytree', 'tslib', +]; + +const LICENSE_FILE_RE = /^(LICENSE|LICENCE|COPYING)(\.|$)/i; + +function readPkg(name) { + const p = path.join(NM, name, 'package.json'); + if (!fs.existsSync(p)) return null; + return JSON.parse(fs.readFileSync(p, 'utf8')); +} + +function findLicenseText(name) { + const dir = path.join(NM, name); + if (!fs.existsSync(dir)) return null; + const file = fs.readdirSync(dir).find((f) => LICENSE_FILE_RE.test(f)); + if (!file) return null; + return fs.readFileSync(path.join(dir, file), 'utf8').trim(); +} + +function spdx(pkg) { + if (typeof pkg.license === 'string') return pkg.license; + if (pkg.license && pkg.license.type) return pkg.license.type; + if (Array.isArray(pkg.licenses)) return pkg.licenses.map((l) => l.type).join(' OR '); + return 'UNKNOWN'; +} + +function sourceUrl(pkg) { + const r = pkg.repository; + let url = typeof r === 'string' ? r : r && r.url; + if (url) { + url = url + .replace(/^git\+/, '') + .replace(/^git:\/\//, 'https://') + .replace(/^ssh:\/\/git@/, 'https://') + .replace(/^git@([^:]+):/, 'https://$1/') // git@github.com:owner/repo -> https://github.com/owner/repo + .replace(/\.git$/, ''); + if (url.startsWith('github:')) url = 'https://github.com/' + url.slice(7); + return url; + } + return pkg.homepage || `https://www.npmjs.com/package/${pkg.name}`; +} + +function copyrightLine(name, text) { + if (!text) return null; + const line = text.split('\n').find((l) => /copyright/i.test(l) && /\d{4}|\(c\)|©/i.test(l)); + return line ? line.trim() : null; +} + +const entries = []; +const byType = new Map(); // SPDX -> representative full license text +const missing = []; +const typeCounts = {}; + +for (const name of PACKAGES) { + const pkg = readPkg(name); + if (!pkg) { missing.push(name); continue; } + const lic = spdx(pkg); + const text = findLicenseText(name); + typeCounts[lic] = (typeCounts[lic] || 0) + 1; + if (text && !byType.has(lic)) byType.set(lic, text); + entries.push({ + name, + version: pkg.version, + license: lic, + source: sourceUrl(pkg), + copyright: copyrightLine(name, text), + }); +} + +const RULE = '------------------------------------------------------------'; +let out = ''; +out += 'THIRD PARTY NOTICES\n'; +out += 'Graph Lens Lite\n\n'; +out += 'The following third-party software is bundled into the distributed\n'; +out += 'application (Electron desktop builds and the inline single-file HTML).\n'; +out += 'Each package is listed with its SPDX license identifier, source, and\n'; +out += 'copyright notice; the full text of every distinct license used appears\n'; +out += 'in the "Full License Texts" section at the end.\n\n'; +out += 'This file is generated from the production dependency tree by\n'; +out += 'scripts/gen_third_party_notices.mjs — do not edit by hand.\n\n'; +out += RULE + '\n'; + +for (const e of entries.sort((a, b) => a.name.localeCompare(b.name))) { + out += `${e.name}@${e.version}\n`; + out += `License: ${e.license}\n`; + out += `Source: ${e.source}\n`; + if (e.copyright) out += `${e.copyright}\n`; + out += RULE + '\n'; +} + +out += '\n\nFull License Texts\n\n'; +for (const [type, text] of [...byType.entries()].sort()) { + out += RULE + '\n'; + out += `${type}\n`; + out += RULE + '\n'; + out += text + '\n\n'; +} + +fs.writeFileSync(OUT, out); + +// Report (no full texts in stdout — keep it terse). +console.log('Packages attributed:', entries.length); +console.log('License breakdown:', JSON.stringify(typeCounts, null, 0)); +console.log('Distinct license types with full text:', [...byType.keys()].sort().join(', ')); +console.log('Missing from node_modules:', missing.length ? missing.join(', ') : 'none'); +const copyleft = entries.filter((e) => /GPL|AGPL|LGPL|MPL|CDDL|EUPL|CC-BY-SA/i.test(e.license)); +console.log('Copyleft/incompatible:', copyleft.length ? copyleft.map((e) => `${e.name}(${e.license})`).join(', ') : 'NONE'); diff --git a/scripts/generate_benchmark_fixture.js b/scripts/generate_benchmark_fixture.js new file mode 100644 index 0000000..78c045e --- /dev/null +++ b/scripts/generate_benchmark_fixture.js @@ -0,0 +1,178 @@ +#!/usr/bin/env node +// Generates the deterministic benchmark fixture for the renderer perf harness +// (MIGRATION.md Phase 0): 6000 nodes / 9000 edges in 8 clusters, ~85% of the +// edges intra-cluster. Same PRNG seed -> byte-identical output, so the file is +// never committed — regenerate via `npm run perf:fixture`. +// +// Output shape mirrors a native JSON export (IOManager.exportGraphAsJSON / +// parseJSON / preProcessData) and is accepted by both the file input +// (cache.io.loadFileWrapper) and window.renderGraphData: +// - nodes: [{id, label, style: {labelText}, D4Data: {"Node filters": {...}}}] +// - edges: [{id, source, target, D4Data: {"Edge filters": {...}}}] +// - node/edgeDataHeaders: [{subGroup, key}] (drives the data table + filters) +// - layouts.Default.positions: {id: {style: {x, y}}} — precomputed positions +// so the load measurement times rendering, not the force layout +// - selectedLayout: "Default" +// Run: node scripts/generate_benchmark_fixture.js +// Output: scripts/fixtures/benchmark_6000x9000.json + +const fs = require("fs"); +const path = require("path"); + +const SEED = 0xd417a; +const NODE_COUNT = 6000; +const EDGE_COUNT = 9000; +const CLUSTER_COUNT = 8; +const INTRA_CLUSTER_EDGE_RATIO = 0.85; +const CLUSTER_RING_RADIUS = 1600; +const CLUSTER_SPREAD = 260; + +const OUT_DIR = path.join(__dirname, "fixtures"); +const OUT_FILE = path.join(OUT_DIR, "benchmark_6000x9000.json"); + +const CATEGORIES = ["Kinase", "Receptor", "Transporter", "Enzyme", "Ligand", "Channel"]; +const PATHWAYS = ["Apoptosis", "Inflammation", "Metabolism", "Signaling", "Transport"]; + +// Deterministic 32-bit PRNG (mulberry32) — no Math.random anywhere. +function mulberry32(seed) { + let state = seed >>> 0; + return function next() { + state = (state + 0x6d2b79f5) >>> 0; + let t = state; + t = Math.imul(t ^ (t >>> 15), t | 1); + t ^= t + Math.imul(t ^ (t >>> 7), t | 61); + return ((t ^ (t >>> 14)) >>> 0) / 4294967296; + }; +} + +const rand = mulberry32(SEED); +const randInt = (maxExclusive) => Math.floor(rand() * maxExclusive); +const pick = (arr) => arr[randInt(arr.length)]; +const round1 = (value) => Math.round(value * 10) / 10; + +// Box-Muller gaussian fed by the seeded PRNG (for cluster blobs). +function gaussian(mean, sigma) { + const u1 = Math.max(rand(), 1e-12); + const u2 = rand(); + return mean + sigma * Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2); +} + +function clusterCenter(clusterIndex) { + const angle = (2 * Math.PI * clusterIndex) / CLUSTER_COUNT; + return { + x: Math.cos(angle) * CLUSTER_RING_RADIUS, + y: Math.sin(angle) * CLUSTER_RING_RADIUS, + }; +} + +function buildNodes() { + const nodes = []; + const positions = {}; + const nodesPerCluster = NODE_COUNT / CLUSTER_COUNT; + + for (let i = 0; i < NODE_COUNT; i++) { + const cluster = Math.floor(i / nodesPerCluster); + const id = `n${i}`; + const label = `C${cluster}-Node-${i}`; + const center = clusterCenter(cluster); + + nodes.push({ + id, + label, + style: {labelText: label}, + D4Data: { + "Node filters": { + Topology: {Cluster: `Cluster ${cluster}`}, + Biology: { + Category: pick(CATEGORIES), + // Pipe-separated multi-value categorical (exercises the splitter) + Pathway: `${pick(PATHWAYS)}|${pick(PATHWAYS)}`, + Score: round1(rand() * 100), + }, + }, + }, + }); + positions[id] = { + style: { + x: round1(gaussian(center.x, CLUSTER_SPREAD)), + y: round1(gaussian(center.y, CLUSTER_SPREAD)), + }, + }; + } + return {nodes, positions}; +} + +function buildEdges() { + const nodesPerCluster = NODE_COUNT / CLUSTER_COUNT; + const nodeInCluster = (cluster) => `n${cluster * nodesPerCluster + randInt(nodesPerCluster)}`; + const edges = []; + + for (let i = 0; i < EDGE_COUNT; i++) { + const isIntra = rand() < INTRA_CLUSTER_EDGE_RATIO; + const sourceCluster = randInt(CLUSTER_COUNT); + let targetCluster = sourceCluster; + if (!isIntra) { + targetCluster = (sourceCluster + 1 + randInt(CLUSTER_COUNT - 1)) % CLUSTER_COUNT; + } + + let source = nodeInCluster(sourceCluster); + let target = nodeInCluster(targetCluster); + // Bounded self-loop avoidance: with a 1-node cluster an unbounded retry + // would never terminate; after a few attempts keep the self-loop (the + // app supports them) rather than spin. + for (let attempt = 0; target === source && attempt < 10; attempt++) { + target = nodeInCluster(targetCluster); + } + + edges.push({ + id: `e${i}`, + source, + target, + D4Data: { + "Edge filters": { + Scores: { + Weight: round1(rand() * 10), + Type: isIntra ? "intra-cluster" : "inter-cluster", + }, + }, + }, + }); + } + return edges; +} + +function main() { + const {nodes, positions} = buildNodes(); + const edges = buildEdges(); + + const fixture = { + nodes, + edges, + nodeDataHeaders: [ + {subGroup: "Topology", key: "Cluster"}, + {subGroup: "Biology", key: "Category"}, + {subGroup: "Biology", key: "Pathway"}, + {subGroup: "Biology", key: "Score"}, + ], + edgeDataHeaders: [ + {subGroup: "Scores", key: "Weight"}, + {subGroup: "Scores", key: "Type"}, + ], + selectedLayout: "Default", + // Positions present -> parseLayouts leaves layoutType undefined -> the app + // skips the initial force layout and renders the stored coordinates. + layouts: { + Default: {positions}, + }, + }; + + fs.mkdirSync(OUT_DIR, {recursive: true}); + fs.writeFileSync(OUT_FILE, JSON.stringify(fixture)); + const sizeMb = (fs.statSync(OUT_FILE).size / 1024 / 1024).toFixed(1); + console.log( + `[fixture] ${path.relative(process.cwd(), OUT_FILE)} — ` + + `${nodes.length} nodes / ${edges.length} edges, ${CLUSTER_COUNT} clusters, ${sizeMb} MB`, + ); +} + +main(); diff --git a/scripts/perf_benchmark.js b/scripts/perf_benchmark.js new file mode 100644 index 0000000..6e80bc3 --- /dev/null +++ b/scripts/perf_benchmark.js @@ -0,0 +1,522 @@ +#!/usr/bin/env node +/* global window, document, requestAnimationFrame, Image, Node */ // browser globals run inside page.evaluate() callbacks +// Renderer performance benchmark (MIGRATION.md Phase 0 acceptance gates). +// Boots the app in headless chromium against the benchmark fixture and +// measures: load time, first-interaction stall, wheel-zoom FPS, drag-pan FPS +// and 500-node select time. Prints a gate table and writes JSON results to +// scripts/fixtures/perf_results_.json. +// +// Run: node scripts/perf_benchmark.js [--assert] +// --assert exit 1 when any acceptance gate fails (CI mode) +// +// Fixture loading choice: the harness calls window.renderGraphData(data) +// (src/managers/api_client.js) instead of page.setInputFiles on #fileInput. +// renderGraphData returns a promise that resolves only after preProcessData → +// createGraphInstance → graph.render() → fitView → hideLoading, i.e. exactly +// "data handed over → graph rendered", with no FileReader noise in the timing. +// The fixture is fetched in-page from the harness's own static server so the +// JSON transfer happens before the timer starts. + +const fs = require('fs'); +const http = require('http'); +const path = require('path'); +const { spawnSync } = require('child_process'); +const { chromium } = require('playwright'); + +const ROOT = path.resolve(__dirname, '..'); +const SRC_DIR = path.join(ROOT, 'src'); +const FIXTURE_DIR = path.join(__dirname, 'fixtures'); +const FIXTURE_FILE = path.join(FIXTURE_DIR, 'benchmark_6000x9000.json'); +const FIXTURE_URL_PATH = '/__fixtures__/benchmark_6000x9000.json'; + +const LOAD_RUNS = 3; +const SELECT_RUNS = 3; +const SELECT_NODE_COUNT = 500; +const FPS_WINDOW_MS = 3000; +const WHEEL_INTERVAL_MS = 30; +const DRAG_WARMUP_MS = 1000; +// An idle rAF ceiling below this means the environment has no usable GPU and is +// rAF-throttled (some CI runners measure ~1.6 fps vs ~59 fps on real hardware). +// Used as a secondary non-representative-environment signal alongside the WebGL +// renderer string (idle cadence alone is insufficient — a runner can clock rAF +// at 60 Hz while painting through a software rasterizer at ~4 fps). +const REALTIME_FPS_FLOOR = 30; + +// A WebGL UNMASKED_RENDERER_WEBGL matching any of these is a software +// rasterizer (no usable GPU), so the GPU-bound gates can't be assessed. +const SOFTWARE_RENDERER_RE = /swiftshader|llvmpipe|softpipe|software|basic render|microsoft basic/i; + +// Acceptance gates from MIGRATION.md ("Acceptance criteria"). +const GATES = [ + { key: 'loadMs', label: 'Load (data → rendered)', unit: 'ms', limit: 2000, op: '<=' }, + { + key: 'firstInteractionStallMs', + label: 'First-interaction stall', + unit: 'ms', + limit: 500, + op: '<=', + }, + { key: 'wheelZoomFps', label: 'Wheel-zoom FPS', unit: 'fps', limit: 30, op: '>=' }, + { key: 'dragPanFps', label: 'Warm drag-pan FPS', unit: 'fps', limit: 60, op: '>=' }, + { key: 'select500Ms', label: '500-node select', unit: 'ms', limit: 200, op: '<=' }, +]; + +// Gates bound by GPU render throughput or frame cadence; unassessable without a +// real GPU. select500Ms is pure app-level JS, so it stays enforced everywhere. +const GPU_BOUND_GATE_KEYS = ['loadMs', 'firstInteractionStallMs', 'wheelZoomFps', 'dragPanFps']; + +function isSoftwareRenderer(renderer) { + return renderer === 'no-webgl' || SOFTWARE_RENDERER_RE.test(renderer); +} + +const MIME = { + '.html': 'text/html', + '.js': 'text/javascript', + '.mjs': 'text/javascript', + '.css': 'text/css', + '.json': 'application/json', + '.png': 'image/png', + '.svg': 'image/svg+xml', + '.map': 'application/json', + '.woff2': 'font/woff2', +}; + +function median(values) { + const sorted = [...values].sort((a, b) => a - b); + const mid = Math.floor(sorted.length / 2); + return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2; +} + +function run(cmd, args) { + const res = spawnSync(cmd, args, { cwd: ROOT, stdio: 'inherit' }); + if (res.status !== 0) { + console.error(`[perf] '${cmd} ${args.join(' ')}' failed (exit ${res.status})`); + process.exit(1); + } +} + +function ensurePreconditions() { + run('node', [path.join(SRC_DIR, 'package', 'vendor_libs.js')]); + if (!fs.existsSync(FIXTURE_FILE)) { + run('node', [path.join(__dirname, 'generate_benchmark_fixture.js')]); + } + // Only download chromium when the pinned revision is actually missing. + if (!fs.existsSync(chromium.executablePath())) { + console.log('[perf] playwright chromium missing, installing ..'); + run('npx', ['playwright', 'install', 'chromium']); + } +} + +// Minimal static server: serves src/ as web root, the fixture under +// /__fixtures__/, and a no-op SSE stub for api/events so the app's +// EventSource doesn't busy-reconnect (404) during FPS measurements. +function startServer() { + const server = http.createServer((req, res) => { + const urlPath = decodeURIComponent(new URL(req.url, 'http://localhost').pathname); + + if (urlPath === '/api/events') { + res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache' }); + res.write(': benchmark stub\n\n'); + return; // hold the connection open, never push a graph + } + + const baseDir = urlPath.startsWith('/__fixtures__/') ? FIXTURE_DIR : SRC_DIR; + const rel = urlPath.replace(/^\/__fixtures__\//, '/'); + const file = path.join(baseDir, path.normalize(rel)); + if (!file.startsWith(baseDir) || !fs.existsSync(file) || !fs.statSync(file).isFile()) { + res.writeHead(404); + res.end('not found'); + return; + } + res.writeHead(200, { 'Content-Type': MIME[path.extname(file)] || 'application/octet-stream' }); + fs.createReadStream(file).pipe(res); + }); + + return new Promise((resolve) => { + server.listen(0, '127.0.0.1', () => resolve(server)); + }); +} + +/** + * Load the fixture via window.renderGraphData and time until the first frame + * after the render pipeline resolves (render + fitView + overlay hidden + one + * rAF as the painted-frame marker). Runs entirely in-page. + */ +async function measureLoadOnce(page) { + return page.evaluate(async (fixtureUrl) => { + const data = await (await fetch(fixtureUrl)).json(); + const t0 = performance.now(); + const ok = await window.renderGraphData(data); + if (!ok) throw new Error('renderGraphData reported failure'); + await new Promise((resolve) => requestAnimationFrame(resolve)); + return performance.now() - t0; + }, FIXTURE_URL_PATH); +} + +/** Center of the graph container (Node-side geometry for real mouse input). */ +async function containerCenter(page) { + const box = await page.locator('#innerGraphContainer').boundingBox(); + return { box, cx: box.x + box.width / 2, cy: box.y + box.height / 2 }; +} + +/** + * Install a persistent in-page rAF counter (window.__fps). Real input events + * are driven from Node via CDP so the harness measures the renderer's real + * event path regardless of how it binds listeners (synthetic DOM WheelEvents + * bypassed G6's binding entirely — verified empirically pre-migration), while + * frame counting stays in-page. + */ +async function installFrameCounter(page) { + await page.evaluate(() => { + window.__fps = { frames: 0, start: 0, running: false }; + const loop = () => { + if (window.__fps.running) window.__fps.frames++; + requestAnimationFrame(loop); + }; + requestAnimationFrame(loop); + }); +} + +async function startFrameCounter(page) { + await page.evaluate(() => { + window.__fps.frames = 0; + window.__fps.running = true; + window.__fps.start = performance.now(); + }); +} + +async function stopFrameCounter(page) { + return page.evaluate(() => { + window.__fps.running = false; + const elapsed = performance.now() - window.__fps.start; + return { fps: window.__fps.frames / (elapsed / 1000), elapsedMs: elapsed }; + }); +} + +/** + * Idle rAF ceiling of this environment. Headless chromium pins rAF to a + * virtual 60 Hz BeginFrame regardless of --disable-frame-rate-limit (verified + * against chromium/headless-shell 1223), so a flawless renderer measures + * ~59 fps — the raw ≥60 drag-pan gate would be unreachable. The gate is + * therefore evaluated against min(60, 0.95 × ceiling). + */ +async function measureIdleFpsCeiling(page) { + await page.waitForTimeout(1000); // let deferred work from prior steps settle + await startFrameCounter(page); + await page.waitForTimeout(1000); + const { fps } = await stopFrameCounter(page); + return fps; +} + +/** + * The active WebGL renderer string (UNMASKED_RENDERER_WEBGL). Distinguishes a + * real GPU from a software rasterizer (SwiftShader/llvmpipe), which idle rAF + * cadence cannot — a runner can clock rAF at 60 Hz while painting in software. + * Returns 'no-webgl' when no context is available. + */ +async function detectRenderer(page) { + return page.evaluate(() => { + try { + const canvas = document.createElement('canvas'); + const gl = canvas.getContext('webgl2') || canvas.getContext('webgl'); + if (!gl) return 'no-webgl'; + const ext = gl.getExtension('WEBGL_debug_renderer_info'); + const renderer = ext + ? gl.getParameter(ext.UNMASKED_RENDERER_WEBGL) + : gl.getParameter(gl.RENDERER); + return String(renderer || 'unknown'); + } catch { + return 'unknown'; + } + }); +} + +/** + * First-interaction stall: time from the first wheel event after load until + * the next animation frame completes. t0/t1 are both taken from the in-page + * clock; the wheel itself is real CDP input. The two CDP round-trips add a few + * ms — negligible against the 500 ms gate (and the ~11 s G6 baseline). + */ +async function measureFirstInteractionStall(page) { + const { cx, cy } = await containerCenter(page); + await page.mouse.move(cx, cy); + + const t0 = await page.evaluate(() => performance.now()); + await page.mouse.wheel(0, -120); + const t1 = await page.evaluate( + () => + new Promise((resolve) => { + requestAnimationFrame(() => requestAnimationFrame(() => resolve(performance.now()))); + }) + ); + // No zoom-changed sanity check here: G6 swallows the very first wheel tick + // (zoom stays constant, verified empirically) while still running its + // lazy-init work — which is exactly the stall this measures. Zoom behavior + // is asserted in measureWheelZoomFps instead. + return { stallMs: t1 - t0 }; +} + +/** + * Wheel-zoom FPS: real wheel events over the canvas center for ~3 s + * (alternating direction to stay inside zoom bounds) while the in-page + * counter tallies rAF frames. + */ +async function measureWheelZoomFps(page) { + const { cx, cy } = await containerCenter(page); + await page.mouse.move(cx, cy); + const zoomBefore = await page.evaluate(() => window.cache.graph.getZoom()); + + await startFrameCounter(page); + const start = Date.now(); + let tick = 0; + while (Date.now() - start < FPS_WINDOW_MS) { + const dir = Math.floor(tick / 15) % 2 === 0 ? -1 : 1; + await page.mouse.wheel(0, dir * 120); + tick++; + await new Promise((resolve) => setTimeout(resolve, WHEEL_INTERVAL_MS)); + } + const counter = await stopFrameCounter(page); + const zoomAfter = await page.evaluate(() => window.cache.graph.getZoom()); + return { ...counter, events: tick, zoomChanged: zoomAfter !== zoomBefore }; +} + +/** + * Drag-pan FPS: real mouse input (Playwright CDP) dragging on empty canvas + * while an in-page rAF counter runs. Zooms out to 0.5 first so the canvas + * corners are guaranteed node-free, then performs a warmup drag (the gate is + * "warm" drag-pan) before the measured one. + */ +async function measureDragPanFps(page) { + await page.evaluate(async () => { + await window.cache.graph.zoomTo(0.5); + }); + + const { box } = await containerCenter(page); + const startX = box.x + box.width * 0.08; + const startY = box.y + box.height * 0.12; + + const drag = async (durationMs) => { + await page.mouse.move(startX, startY); + await page.mouse.down(); + const t0 = Date.now(); + let step = 0; + while (Date.now() - t0 < durationMs) { + const phase = ((step % 40) / 40) * 2 * Math.PI; + await page.mouse.move( + startX + Math.sin(phase) * box.width * 0.05, + startY + (1 - Math.cos(phase)) * box.height * 0.05 + ); + step++; + } + await page.mouse.up(); + return step; + }; + + await drag(DRAG_WARMUP_MS); // warmup: absorb any remaining lazy-init cost + + await startFrameCounter(page); + const moves = await drag(FPS_WINDOW_MS); + const counter = await stopFrameCounter(page); + return { ...counter, moves }; +} + +/** + * 500-node select via the app's selection manager (cache.sm.selectNodes -> + * cache.graph.getElementState/setElementState round-trips). + * + * NOTE(sigma-migration): this call site changes with the Sigma.js port — + * selection becomes app-level Sets + sigma.refresh() (MIGRATION.md Phase 1/3). + * Keep the entry point isolated here so only this function needs updating. + */ +async function measureSelectOnce(page) { + return page.evaluate(async (count) => { + const ids = []; + for (const id of window.cache.nodeRef.keys()) { + ids.push(id); + if (ids.length >= count) break; + } + const t0 = performance.now(); + await window.cache.sm.selectNodes(ids); + await new Promise((resolve) => requestAnimationFrame(resolve)); + const elapsed = performance.now() - t0; + await window.cache.sm.selectNodes([]); // deselect so reruns stay comparable + return elapsed; + }, SELECT_NODE_COUNT); +} + +function evaluateGates(results, limitOverrides = {}, skipKeys = new Set()) { + return GATES.map((gate) => { + const effectiveLimit = limitOverrides[gate.key] ?? gate.limit; + const measured = results[gate.key]; + const skipped = skipKeys.has(gate.key); + const pass = skipped + ? true + : gate.op === '<=' + ? measured <= effectiveLimit + : measured >= effectiveLimit; + return { ...gate, effectiveLimit, measured, skipped, pass }; + }); +} + +function printTable(rows) { + const fmt = (v, unit) => `${unit === 'fps' ? v.toFixed(1) : Math.round(v)} ${unit}`; + const widths = [28, 14, 28, 6]; + const line = (cols) => console.log(cols.map((c, i) => String(c).padEnd(widths[i])).join(' | ')); + console.log(''); + line(['Metric', 'Measured', 'Gate', 'Pass']); + line(widths.map((w) => '-'.repeat(w))); + for (const row of rows) { + const gateText = row.skipped + ? `${row.op} ${row.limit} ${row.unit} (no-GPU env)` + : row.effectiveLimit === row.limit + ? `${row.op} ${row.limit} ${row.unit}` + : `${row.op} ${fmt(row.effectiveLimit, row.unit)} (capped, raw ${row.limit})`; + const status = row.skipped ? 'SKIP' : row.pass ? 'PASS' : 'FAIL'; + line([row.label, fmt(row.measured, row.unit), gateText, status]); + } + console.log(''); +} + +async function main() { + const assertGates = process.argv.includes('--assert'); + ensurePreconditions(); + + const server = await startServer(); + const baseUrl = `http://127.0.0.1:${server.address().port}`; + console.log(`[perf] serving src/ at ${baseUrl}`); + + // The sigma renderer is WebGL: measured through SwiftShader (headless + // default) a bare 6000x9000 sigma scene caps at ~8 fps, on the real GPU at + // ~60 fps — software GL emulation is the bottleneck, not the renderer. The + // Vulkan flags pick the hardware GPU when present and fall back to + // SwiftShader's Vulkan device otherwise (verified 2026-06-10, chromium + // headless + AMD Radeon 890M/RADV). FPS gates are calibrated against the + // idle rAF ceiling (see measureIdleFpsCeiling) because headless rAF is + // pinned to 60 Hz. + const browser = await chromium.launch({ + headless: true, + args: [ + '--enable-gpu', + '--use-angle=vulkan', + '--enable-features=Vulkan', + '--ignore-gpu-blocklist', + ], + }); + const page = await browser.newPage({ viewport: { width: 1600, height: 900 } }); + page.on('pageerror', (err) => console.error(`[perf] page error: ${err.message}`)); + + const gotoApp = async () => { + await page.goto(`${baseUrl}/graph_lens_lite.html`, { waitUntil: 'load' }); + await page.waitForFunction(() => typeof window.renderGraphData === 'function'); + }; + + try { + // Reload the page between load runs: re-applying a graph into a running + // app would also time the teardown of the previous 15k-element instance. + console.log(`[perf] load: ${LOAD_RUNS} runs (fresh page each) ..`); + const loadRuns = []; + for (let i = 0; i < LOAD_RUNS; i++) { + await gotoApp(); + loadRuns.push(await measureLoadOnce(page)); + console.log(`[perf] run ${i + 1}: ${Math.round(loadRuns[i])} ms`); + } + await installFrameCounter(page); + + // Must run directly after a fresh load, before any other interaction. + console.log('[perf] first-interaction stall ..'); + const stall = await measureFirstInteractionStall(page); + + console.log('[perf] calibrating idle rAF ceiling ..'); + const idleFps = await measureIdleFpsCeiling(page); + console.log(`[perf] ceiling: ${idleFps.toFixed(1)} fps`); + + const renderer = await detectRenderer(page); + console.log(`[perf] GPU renderer: ${renderer}`); + + console.log('[perf] wheel-zoom FPS (~3 s) ..'); + const wheel = await measureWheelZoomFps(page); + if (!wheel.zoomChanged) { + console.warn('[perf] WARNING: wheel events did not change zoom — FPS value may be invalid'); + } + + console.log('[perf] drag-pan FPS (warmup + ~3 s) ..'); + const drag = await measureDragPanFps(page); + + console.log(`[perf] ${SELECT_NODE_COUNT}-node select: ${SELECT_RUNS} runs ..`); + const selectRuns = []; + for (let i = 0; i < SELECT_RUNS; i++) { + selectRuns.push(await measureSelectOnce(page)); + console.log(`[perf] run ${i + 1}: ${Math.round(selectRuns[i])} ms`); + } + + const results = { + loadMs: median(loadRuns), + firstInteractionStallMs: stall.stallMs, + wheelZoomFps: wheel.fps, + dragPanFps: drag.fps, + select500Ms: median(selectRuns), + }; + // rAF-pinned FPS gates can never exceed the environment's idle ceiling, so + // evaluate them against min(raw gate, 0.95 × ceiling). + const fpsCap = (key) => Math.min(GATES.find((g) => g.key === key).limit, idleFps * 0.95); + // Without a real GPU the render-throughput/frame-cadence gates are + // unassessable: report them but don't enforce. Detect via the software + // renderer string, with a low idle ceiling as a fallback signal. + const nonRepresentative = isSoftwareRenderer(renderer) || idleFps < REALTIME_FPS_FLOOR; + if (nonRepresentative) { + console.warn( + `[perf] non-representative environment (renderer "${renderer}", idle ${idleFps.toFixed(1)} fps): GPU-bound gates report-only; only the 500-node select gate is enforced. Run on real-GPU hardware for the full gate set.` + ); + } + const gateRows = evaluateGates( + results, + { wheelZoomFps: fpsCap('wheelZoomFps'), dragPanFps: fpsCap('dragPanFps') }, + nonRepresentative ? new Set(GPU_BOUND_GATE_KEYS) : new Set() + ); + printTable(gateRows); + + const report = { + timestamp: new Date().toISOString(), + fixture: path.basename(FIXTURE_FILE), + idleFpsCeiling: idleFps, + renderer, + nonRepresentative, + gates: gateRows.map( + ({ key, label, unit, limit, effectiveLimit, op, measured, skipped, pass }) => ({ + key, + label, + unit, + limit, + effectiveLimit, + op, + measured, + skipped, + pass, + }) + ), + raw: { loadRuns, stall, wheel, drag, selectRuns }, + }; + const stamp = report.timestamp.replace(/[:.]/g, '-'); + const outFile = path.join(FIXTURE_DIR, `perf_results_${stamp}.json`); + fs.writeFileSync(outFile, JSON.stringify(report, null, 2)); + console.log(`[perf] results written to ${path.relative(process.cwd(), outFile)}`); + + const failed = gateRows.filter((row) => !row.pass); + if (failed.length > 0) { + console.log( + `[perf] ${failed.length}/${gateRows.length} gates FAILED: ${failed.map((f) => f.key).join(', ')}` + ); + if (assertGates) process.exitCode = 1; + } else { + console.log('[perf] all gates passed'); + } + } finally { + await browser.close(); + server.close(); + } +} + +main().catch((err) => { + console.error(`[perf] fatal: ${err.stack || err.message}`); + process.exit(1); +}); diff --git a/scripts/resize_redraw_check.js b/scripts/resize_redraw_check.js new file mode 100644 index 0000000..3c19be2 --- /dev/null +++ b/scripts/resize_redraw_check.js @@ -0,0 +1,264 @@ +#!/usr/bin/env node +/* global window, document, requestAnimationFrame, Image, Node */ // browser globals run inside page.evaluate() callbacks +// Manual regression check: panel toggles must not blank the graph. +// +// Repro for the "graph disappears after sidebar/bottom-bar toggle until the +// next pan/zoom" bug: sigma.resize() resizes the WebGL canvases (which clears +// their drawing buffers) but never schedules a render, so a container-only +// resize (panel toggle — the window itself does not resize) left the scene +// blank until the next camera move triggered render(). The fix routes all +// container resizes through sigma.scheduleRender() (render() resizes first, +// then redraws). +// +// What it does: boots the app in headless chromium (same launch pattern as +// scripts/perf_benchmark.js), loads a tiny in-memory dataset via +// window.renderGraphData, opens/closes the bottom bar (#queryToggleBtn, rides +// the 0.3 s #mainContent height transition) and toggles the assistant panel, +// then after each settle samples the centre of #innerGraphContainer for +// non-background pixels and checks sigma's resize/afterRender event ordering. +// +// There is no wired e2e harness in this repo (perf_benchmark.js is the only +// browser script in package.json), so this stays a manual check: +// node scripts/resize_redraw_check.js +// Exit code 1 when any toggle leaves the graph blank. + +const fs = require('fs'); +const http = require('http'); +const path = require('path'); +const { spawnSync } = require('child_process'); +const { chromium } = require('playwright'); + +const ROOT = path.resolve(__dirname, '..'); +const SRC_DIR = path.join(ROOT, 'src'); + +const TRANSITION_SETTLE_MS = 900; // 300 ms CSS transition + debounce + frames +const MIN_DRAWN_PIXELS = 200; // blank ≈ 0; a drawn 30-node scene ≈ thousands + +const MIME = { + '.html': 'text/html', + '.js': 'text/javascript', + '.mjs': 'text/javascript', + '.css': 'text/css', + '.json': 'application/json', + '.png': 'image/png', + '.svg': 'image/svg+xml', + '.map': 'application/json', +}; + +// Tiny dataset mirroring the native JSON export shape consumed by +// window.renderGraphData (see scripts/generate_benchmark_fixture.js). +function buildTinyDataset() { + const nodes = []; + const positions = {}; + const edges = []; + const COUNT = 30; + for (let i = 0; i < COUNT; i++) { + const id = `n${i}`; + nodes.push({ + id, + label: `Node-${i}`, + style: { labelText: `Node-${i}` }, + D4Data: { 'Node filters': { Biology: { Score: i } } }, + }); + const angle = (2 * Math.PI * i) / COUNT; + positions[id] = { style: { x: Math.cos(angle) * 300, y: Math.sin(angle) * 300 } }; + } + for (let i = 0; i < COUNT; i++) { + edges.push({ + id: `e${i}`, + source: `n${i}`, + target: `n${(i + 7) % COUNT}`, + D4Data: { 'Edge filters': { Scores: { Weight: 1 } } }, + }); + } + return { + nodes, + edges, + nodeDataHeaders: [{ subGroup: 'Biology', key: 'Score' }], + edgeDataHeaders: [{ subGroup: 'Scores', key: 'Weight' }], + selectedLayout: 'Default', + layouts: { Default: { positions } }, + }; +} + +function ensurePreconditions() { + if (!fs.existsSync(path.join(SRC_DIR, 'lib', 'sigma.bundle.mjs'))) { + const res = spawnSync('node', [path.join(SRC_DIR, 'package', 'vendor_libs.js')], { + cwd: ROOT, + stdio: 'inherit', + }); + if (res.status !== 0) { + console.error('[resize-check] vendor_libs.js failed'); + process.exit(1); + } + } +} + +function startServer() { + const server = http.createServer((req, res) => { + const urlPath = decodeURIComponent(new URL(req.url, 'http://localhost').pathname); + if (urlPath === '/api/events') { + res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache' }); + res.write(': resize-check stub\n\n'); + return; + } + const file = path.join(SRC_DIR, path.normalize(urlPath)); + if (!file.startsWith(SRC_DIR) || !fs.existsSync(file) || !fs.statSync(file).isFile()) { + res.writeHead(404); + res.end('not found'); + return; + } + res.writeHead(200, { 'Content-Type': MIME[path.extname(file)] || 'application/octet-stream' }); + fs.createReadStream(file).pipe(res); + }); + return new Promise((resolve) => server.listen(0, '127.0.0.1', () => resolve(server))); +} + +/** + * Count non-background pixels in the central 50% of #innerGraphContainer. + * Screenshots come from the compositor, so this sees what the user sees + * (WebGL canvases use preserveDrawingBuffer:false — readPixels would lie). + * The centre crop excludes the minimap (bottom-right) and the border. + */ +async function countDrawnPixels(page, screenshotFile) { + const box = await page.locator('#innerGraphContainer').boundingBox(); + const clip = { + x: box.x + box.width * 0.25, + y: box.y + box.height * 0.25, + width: box.width * 0.5, + height: box.height * 0.5, + }; + const buffer = await page.screenshot({ clip }); + if (screenshotFile) fs.writeFileSync(screenshotFile, buffer); + return page.evaluate(async (base64) => { + const img = new Image(); + await new Promise((resolve, reject) => { + img.onload = resolve; + img.onerror = reject; + img.src = `data:image/png;base64,${base64}`; + }); + const canvas = document.createElement('canvas'); + canvas.width = img.width; + canvas.height = img.height; + const ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0); + const { data } = ctx.getImageData(0, 0, canvas.width, canvas.height); + let drawn = 0; + for (let i = 0; i < data.length; i += 4) { + // background is white; count anything visibly non-white + if (255 * 3 - (data[i] + data[i + 1] + data[i + 2]) > 30) drawn++; + } + return drawn; + }, buffer.toString('base64')); +} + +/** Sigma-side evidence: dimension state + renders since the last resize. */ +async function installSigmaProbe(page) { + await page.evaluate(() => { + const sigma = window.cache.graph.sigma; + window.__probe = { resizes: 0, rendersSinceResize: 0 }; + sigma.on('resize', () => { + window.__probe.resizes++; + window.__probe.rendersSinceResize = 0; + }); + sigma.on('afterRender', () => { + window.__probe.rendersSinceResize++; + }); + }); +} + +async function sampleSigmaState(page) { + return page.evaluate(() => { + const sigma = window.cache.graph.sigma; + const container = document.getElementById('innerGraphContainer'); + return { + ...window.__probe, + sigmaWidth: sigma.getDimensions().width, + sigmaHeight: sigma.getDimensions().height, + containerWidth: container.offsetWidth, + containerHeight: container.offsetHeight, + }; + }); +} + +async function main() { + ensurePreconditions(); + const server = await startServer(); + const baseUrl = `http://127.0.0.1:${server.address().port}`; + const browser = await chromium.launch({ + headless: true, + args: [ + '--enable-gpu', + '--use-angle=vulkan', + '--enable-features=Vulkan', + '--ignore-gpu-blocklist', + ], + }); + const failures = []; + + try { + const page = await browser.newPage({ viewport: { width: 1280, height: 800 } }); + page.on('pageerror', (err) => console.error(`[resize-check] page error: ${err.message}`)); + + await page.goto(`${baseUrl}/graph_lens_lite.html`, { waitUntil: 'load' }); + await page.waitForFunction(() => typeof window.renderGraphData === 'function'); + await page.evaluate(async (data) => { + const ok = await window.renderGraphData(data); + if (!ok) throw new Error('renderGraphData reported failure'); + await new Promise((resolve) => requestAnimationFrame(resolve)); + }, buildTinyDataset()); + await installSigmaProbe(page); + + const baseline = await countDrawnPixels( + page, + path.join(__dirname, 'fixtures', 'resize_check_baseline.png') + ); + console.log(`[resize-check] baseline drawn pixels: ${baseline}`); + if (baseline < MIN_DRAWN_PIXELS) { + throw new Error('graph not drawn after load — harness broken, aborting'); + } + + // Bottom-bar open/close exercises the shared SigmaAdapter.resize() path + // (ResizeObserver debounce); other panels route through the same seam. + // The assistant toggle is deliberately not driven here: with no API key + // configured it opens a modal overlay that blocks further clicks. + const steps = [ + { label: 'open bottom bar', action: () => page.click('#queryToggleBtn') }, + { label: 'close bottom bar', action: () => page.click('#queryToggleBtn') }, + ]; + + for (const [index, step] of steps.entries()) { + await step.action(); + await page.waitForTimeout(TRANSITION_SETTLE_MS); + const drawn = await countDrawnPixels( + page, + path.join(__dirname, 'fixtures', `resize_check_step${index + 1}.png`) + ); + const state = await sampleSigmaState(page); + const ok = drawn >= MIN_DRAWN_PIXELS; + console.log( + `[resize-check] ${step.label}: drawn=${drawn} ` + + `sigma=${state.sigmaWidth}x${state.sigmaHeight} ` + + `container=${state.containerWidth}x${state.containerHeight} ` + + `resizes=${state.resizes} rendersSinceResize=${state.rendersSinceResize} ` + + `=> ${ok ? 'PASS' : 'FAIL'}` + ); + if (!ok) failures.push(step.label); + } + } finally { + await browser.close(); + server.close(); + } + + if (failures.length > 0) { + console.error(`[resize-check] FAILED: graph blank after: ${failures.join(', ')}`); + process.exitCode = 1; + } else { + console.log('[resize-check] all panel toggles kept the graph drawn'); + } +} + +main().catch((err) => { + console.error(`[resize-check] error: ${err.message}`); + process.exit(1); +}); diff --git a/server/static.js b/server/static.js index 4350d74..ac314d4 100644 --- a/server/static.js +++ b/server/static.js @@ -28,7 +28,7 @@ const DEFAULT_DOCUMENT = "graph_lens_lite.html"; * path-traversal attempt. Returns null when the request escapes the root. * * @param {string} rootDir Absolute static root. - * @param {string} urlPath Decoded pathname (e.g. "/lib/g6.min.js"). + * @param {string} urlPath Decoded pathname (e.g. "/lib/sigma.bundle.mjs"). * @returns {string|null} */ function resolveStaticPath(rootDir, urlPath) { @@ -76,13 +76,59 @@ function serveStatic(req, res, rootDir) { res.end("Not Found"); return; } + + // Asset names are stable while their content changes between releases, so a + // long max-age would serve stale JS/CSS. `no-cache` makes the browser + // revalidate on every load; the validators below let that revalidation + // return a cheap 304 instead of refetching unchanged bytes. + const lastModified = stats.mtime.toUTCString(); + const etag = `W/"${stats.size.toString(16)}-${Math.floor(stats.mtimeMs).toString(16)}"`; + + if (isNotModified(req, etag, stats.mtimeMs)) { + res.writeHead(304, { + "Cache-Control": "no-cache", + ETag: etag, + "Last-Modified": lastModified, + }); + res.end(); + return; + } + res.writeHead(200, { "Content-Type": contentTypeFor(filePath), "Content-Length": stats.size, "X-Content-Type-Options": "nosniff", + "Cache-Control": "no-cache", + ETag: etag, + "Last-Modified": lastModified, }); fs.createReadStream(filePath).pipe(res); }); } +/** + * Decide whether a conditional GET can be answered with 304 Not Modified. + * Prefers the strong ETag match; falls back to If-Modified-Since (second + * resolution, matching HTTP date precision). + * + * @param {import('http').IncomingMessage} req + * @param {string} etag Current entity tag for the file. + * @param {number} mtimeMs File modification time in milliseconds. + * @returns {boolean} + */ +function isNotModified(req, etag, mtimeMs) { + const ifNoneMatch = req.headers["if-none-match"]; + if (ifNoneMatch) { + return ifNoneMatch.split(",").some((tag) => tag.trim() === etag); + } + const ifModifiedSince = req.headers["if-modified-since"]; + if (ifModifiedSince) { + const since = Date.parse(ifModifiedSince); + if (!Number.isNaN(since)) { + return Math.floor(mtimeMs / 1000) * 1000 <= since; + } + } + return false; +} + module.exports = { serveStatic, resolveStaticPath, contentTypeFor, DEFAULT_DOCUMENT }; diff --git a/src/config.js b/src/config.js index 45c99b2..c9f9f13 100644 --- a/src/config.js +++ b/src/config.js @@ -1,13 +1,29 @@ /** * Defaults for the graph, layouts and UI */ -const VERSION = "1.14.2"; +const VERSION = "1.15.0"; const DEFAULTS = { NODE: { FILL_COLOR: "#C33D35", SIZE: 20, LINE_WIDTH: 1, TYPE: "hexagon", STROKE_COLOR: null, BADGE: { - FONT_SIZE: 8, COLOR: "#C33D35" + FONT_SIZE: 8, COLOR: "#C33D35", SCALE_WITH_NODE: false + }, + // Pie-chart nodes (@sigma/node-piechart). The program is created with a + // FIXED slice count (slice K reads pieValueK/pieColorK per node), so + // MAX_SLICES caps how many categories/numeric columns one node can show; + // overflow is dropped with a UI warning (no silent truncation). Unused + // slices carry value 0 + a transparent color, collapsing to nothing. + // + // HARD CAP 6: the program consumes 4 base + 2 vertex attributes per slice + // (per-node color + value), and WebGL2 only guarantees MAX_VERTEX_ATTRIBS + // = 16 (4 + 2·6 = 16). The program is built eagerly for every graph and + // throws above the limit, so a larger value would break ALL rendering on + // 16-attribute GPUs — not just pie nodes. + PIE: { + MAX_SLICES: 6, + DEFAULT_COLOR: "#ABACBD", // fallback fill when a slice color is missing + SLICE_PALETTE: ["#C33D35", "#403C53", "#8CA6D9", "#EFB0AA", "#5B8C5A", "#E0A458"], }, LABEL: { FOREGROUND_COLOR: "#000000", BACKGROUND: false, BACKGROUND_COLOR: null, BACKGROUND_RADIUS: 5, @@ -17,7 +33,13 @@ const DEFAULTS = { }, EDGE: { COLOR: "#403C5390", LINE_WIDTH: 0.75, LINE_DASH: 0, TYPE: "line", - ARROWS: {START: false, END: false, START_SIZE: 8, START_TYPE: "triangle", END_SIZE: 8, END_TYPE: "triangle"}, + ARROWS: { + START: false, END: false, START_SIZE: 8, START_TYPE: "arrow", END_SIZE: 8, END_TYPE: "arrow", + // null fill → marker inherits the edge stroke color; null border → no border (transparent). + START_COLOR: null, START_BORDER_COLOR: null, END_COLOR: null, END_BORDER_COLOR: null, + // Border band thickness in px; 0 → auto (scales with the marker, ~20%). + START_BORDER_SIZE: 0, END_BORDER_SIZE: 0, + }, LABEL: { TEXT: null, FOREGROUND_COLOR: "#000000", BACKGROUND: false, BACKGROUND_COLOR: null, BACKGROUND_CURSOR: "default", BACKGROUND_FILL_OPACITY: 1, BACKGROUND_RADIUS: 0, BACKGROUND_STROKE_OPACITY: 1, @@ -27,19 +49,151 @@ const DEFAULTS = { }, HALO: { ENABLED: false, COLOR: "#403C53", WIDTH: 3, + }, + // Animated source→target flow overlay (edge_flow_programs.js). COLOR null + // → derived from the edge stroke (lightened, see graph_model.edgeMarkerHaloAttributes). + // OPACITY multiplies into the overlay color's alpha; DENSITY scales the + // pattern period (higher = sparser dashes/dots). + FLOW: { + ENABLED: false, TYPE: "dash", SPEED: 1, COLOR: null, OPACITY: 1, DENSITY: 1, } }, + // Element interaction-state spec (former G6 node/edge state config in + // core.js). Single source for the styling UI and the sigma reducers. + STATE: { + ACCENT_COLOR: "#C33D35", // selected/highlight halo + highlight fill + DIM_COLOR: "#E4E3EA", // dim fill + NODE_HALO_WIDTH: 12, // px, halo ring stroke width on nodes + EDGE_HALO_WIDTH: 6, // px, emphasis width budget on selected edges + HALO_OPACITY: 0.4, + }, + // Atmospheric canvas layer (heatmap_layer.js): node-density heatmap below + // the bubble-set canvas. Off by default; toggled from the workspace toolbar. + // OPACITY/INTENSITY/GAMMA/BANDWIDTH_SCALE/DIM_GRAPH are the runtime knobs + // exposed in the toolbar settings popover — these are the initial values. + HEATMAP: { + ENABLED: false, + MAX_RESOLUTION: 1024, // offscreen splat canvas long-side px cap + BANDWIDTH: 0, // splat radius in graph units; 0 → auto (heatBandwidth) + BANDWIDTH_SCALE: 1, // multiplier on the (auto or explicit) bandwidth + OPACITY: 0.55, // layer alpha — keeps the field atmospheric + INTENSITY: 0.18, // per-splat center alpha; densities saturate at ~1/INTENSITY overlaps + GAMMA: 0.7, // density exponent before the ramp; < 1 boosts low-density haze + // Density floor: pixels below this density clear entirely, the rest + // renormalizes over the ramp. A lone node peaks at exactly INTENSITY, so + // a value just above it shows only overlapping nodes (clusters). + THRESHOLD: 0, + RAMP: "default", // active RAMPS preset (styling-panel dropdown) + // Density ramp presets, one stop list per theme. First-stop alpha 00 so + // low densities fade out without graying. viridis/magma are perceptually + // uniform and read on either background, so both themes share the stops. + RAMPS: { + // transparent → cool → warm; dark variant brighter and slightly + // desaturated so the haze reads on a dark background without neon. + default: { + light: [ + { t: 0, color: "#8CA6D900" }, + { t: 0.35, color: "#8CA6D9" }, + { t: 0.7, color: "#EFB0AA" }, + { t: 1, color: "#C33D35" }, + ], + dark: [ + { t: 0, color: "#7C90C200" }, + { t: 0.35, color: "#7C90C2" }, + { t: 0.7, color: "#D89A90" }, + { t: 1, color: "#F0867B" }, + ], + }, + viridis: { + light: [ + { t: 0, color: "#44015400" }, + { t: 0.25, color: "#3B528B" }, + { t: 0.5, color: "#21918C" }, + { t: 0.75, color: "#5EC962" }, + { t: 1, color: "#FDE725" }, + ], + dark: [ + { t: 0, color: "#44015400" }, + { t: 0.25, color: "#3B528B" }, + { t: 0.5, color: "#21918C" }, + { t: 0.75, color: "#5EC962" }, + { t: 1, color: "#FDE725" }, + ], + }, + magma: { + light: [ + { t: 0, color: "#51127C00" }, + { t: 0.35, color: "#B73779" }, + { t: 0.7, color: "#FC8961" }, + { t: 1, color: "#FCFDBF" }, + ], + dark: [ + { t: 0, color: "#51127C00" }, + { t: 0.35, color: "#B73779" }, + { t: 0.7, color: "#FC8961" }, + { t: 1, color: "#FCFDBF" }, + ], + }, + // Single hue on the app accent — selection-styling adjacency. + accent: { + light: [ + { t: 0, color: "#C33D3500" }, + { t: 0.5, color: "#E0928D" }, + { t: 1, color: "#C33D35" }, + ], + dark: [ + { t: 0, color: "#F0867B00" }, + { t: 0.5, color: "#D86A60" }, + { t: 1, color: "#F0867B" }, + ], + }, + // Neutral: darkens toward ink on light, lightens toward paper on dark. + grayscale: { + light: [ + { t: 0, color: "#BBBBBB00" }, + { t: 0.5, color: "#999999" }, + { t: 1, color: "#333333" }, + ], + dark: [ + { t: 0, color: "#77777700" }, + { t: 0.5, color: "#AAAAAA" }, + { t: 1, color: "#EEEEEE" }, + ], + }, + }, + // Dim every non-emphasized node/edge while the heatmap is on, so the + // density field reads through the graph (the layer sits below everything). + DIM_GRAPH: false, + }, LAYOUT: "force", + // Keys define the layout template vocabulary (workspace-creation dropdown). + // Option objects ride into the headless @antv/layout classes for + // radial/concentric/mds/dagre; force (forceAtlas2.inferSettings), circular, + // circlepack, grid and random are self-tuning/geometric and take no options. LAYOUT_INTERNALS: { - "force": {gravity: 10}, - // "fruchterman": {gravity: 5, speed: 5, clustering: true, nodeClusterBy: 'cluster', clusterGravity: 16}, - // "antv-dagre": {nodesep: 100, ranksep: 70, controlPoints: true}, - "circular": {startRadius: 10, endRadius: 300}, + "force": {}, + "circular": {}, + // Circle packing (d3-hierarchy via graphology). Each node's circle radius + // is its `size` attribute (sigma radius); O(n), no expense guard. + "circlepack": {}, "radial": {direction: "LR", nodeSize: 32, unitRadius: 100, linkDistance: 200}, "concentric": {nodeSize: 32, maxLevelDiff: 0.5, sortBy: 'degree', preventOverlap: true}, - "grid": {sortBy: "id", nodeSize: 32}, + "grid": {}, + // Uniform random scatter centered on the origin; O(n), no expense guard. + "random": {}, "mds": {nodeSize: 32, linkDistance: 100}, + // Layered/hierarchical (Sugiyama). rankdir TB → ranks flow top-to-bottom + // (y negated into graphology's y-up frame in layout_algorithms.js); + // nodesep/ranksep are graph-space px between same-rank / adjacent ranks. + "dagre": {rankdir: "TB", nodesep: 40, ranksep: 90}, }, + // Layout templates whose headless compute scales super-linearly (dagre's + // Sugiyama ordering, classical MDS's O(n²) distance matrix). Above + // LAYOUT_NODE_WARNING_THRESHOLD nodes they can run for minutes even off the + // main thread, so workspace creation warns before kicking one off. force is + // excluded (worker-animated with a hard time budget); circular/grid are O(n). + EXPENSIVE_LAYOUTS: ["dagre", "mds"], + LAYOUT_NODE_WARNING_THRESHOLD: 2000, CUSTOM_LAYOUT_NAME: "custom", BUBBLE_GROUP_STYLE: { "groupOne": { @@ -169,7 +323,18 @@ const DEFAULTS = { EDGE_LABEL_OFFSET_Y: {"-25": -25, "0": 0, "25": 25}, // EDGE_LABEL_AUTOROTATE: {enable: true, disable: false}, // EDGE_ARROW_SIZES: {sm: 8, md: 10, lg: 14}, - EDGE_ARROW_TYPES: ["triangle", "circle", "diamond", "vee", "rect", "triangleRect", "simple"], + // End-marker vocabulary (graph_model.EDGE_MARKERS): direction shapes + + // "tee" (⊣ inhibition bar). Legacy G6 names (triangle/vee/...) still load + // via aliases but are no longer offered in the UI. + EDGE_ARROW_TYPES: ["arrow", "rect", "diamond", "circle", "tee"], + // Flow overlay vocabulary (graph_model.FLOW_MODES): marching dashes, + // travelling dots, fading comet tails and travelling chevron arrows, all + // moving source → target. + EDGE_FLOW_TYPES: ["dash", "pulse", "comet", "chevron"], + EDGE_ARROW_COLORS: {red: "#C33D35", purple: "#403C53", blue: "#8CA6D9", pink: "#EFB0AA", grey: "#ABACBD"}, + EDGE_ARROW_BORDER_COLORS: { + red: "#C33D35", purple: "#403C53", blue: "#8CA6D9", pink: "#EFB0AA", grey: "#ABACBD", none: "#00000000" + }, EDGE_HALO: {enable: true, disable: false}, EDGE_HALO_STROKE: {red: "#C33D35", purple: "#403C53", blue: "#8CA6D9"}, EDGE_HALO_WIDTH: {sm: 2, md: 3, lg: 5}, @@ -184,12 +349,11 @@ const CFG = { // Determines if filter sliders should be hidden when the minimum and maximum values are identical HIDE_SLIDERS_WITH_SAME_MIN_MAX_VALUES: true, -// Specifies the slider step size for integer-based properties +// Specifies the slider step size for integer-based properties. +// Float-based properties use a continuous slider (step="any"), so they have no +// configurable step — see InvertibleRangeSlider. FILTER_STEP_SIZE_INTEGER: 1, -// Specifies the slider step size for float-based properties - FILTER_STEP_SIZE_FLOAT: 0.000001, - // Specifies the slider thumb- and tooltip-values (only visually); internally, the full float precision is used FILTER_VISUAL_FLOAT_PRECISION: 3, @@ -209,13 +373,17 @@ const CFG = { MAX_NODES_BEFORE_HIDING_LABELS: 1000, HIDE_LABELS: false, -// if network is greater than defined threshold, hover effects are disabled - MAX_NODES_BEFORE_DISABLING_HOVER_EFFECT: 200, - MAX_EDGES_BEFORE_DISABLING_HOVER_EFFECT: 500, +// Hover highlight effect. Controlled only by the manual toggle button (sigma +// renders hover fast enough that no automatic node/edge-count cutoff is needed). DISABLE_HOVER_EFFECT: false, -// if network is greater than defined threshold, bubble groups may span across non-bubble group members - MAX_NODES_BEFORE_DISABLING_AVOID_MEMBERS_IN_BUBBLE_GROUPS: 300, +// if network is greater than defined threshold, bubble groups may span across non-bubble group members. +// Measured with the sigma renderer (bubblesets-js createOutline, virtualEdges on, viewport-scale +// coordinates, 2026-06-10): 60 members + 1000 avoid rects ≈ 69 ms, +2000 ≈ 194 ms, 300 members + +// 5700 avoid ≈ 12 s — virtual-edge routing around obstacles is O(members × avoid). 1000 keeps a +// full per-group outline recompute under the ~100 ms interactivity budget; camera pan/zoom reuses +// cached outlines and is unaffected (src/graph/bubble_layer.js). + MAX_NODES_BEFORE_DISABLING_AVOID_MEMBERS_IN_BUBBLE_GROUPS: 1000, AVOID_MEMBERS_IN_BUBBLE_GROUPS: false, // Maximum capacity of selection memory @@ -230,22 +398,10 @@ const CFG = { // Edge filter header EXCEL_EDGE_HEADER: "Edge filters", -// Set to true in case original g6.min.js is used and issue #7195 is NOT resolved (https://github.com/antvis/G6/issues/7195) - APPLY_BUBBLE_SET_HOTFIX: false, - // Set to true to use current filter configuration for pushing property to query editor, e.g. if slider is inverted // false uses defaults (non-inverted) and min/max QUERY_BTN_USE_CURRENT_FILTER: true, -// Set to true to reset positions of selected elements when clicking the reset selection button in the top right selection frame - RESET_SELECTION_BUTTON_RESETS_POSITIONS: true, - INVISIBLE_DUMMY_NODE: { - id: "INVISIBLEDUMMYNODEWITHIMPOSSIBLEID", - style: { - visibility: "hidden" - }, - }, - INVISIBLE_CHAR: "\u200B", // AI Assistant configuration lives entirely in localStorage (key diff --git a/src/gll.js b/src/gll.js index 4e8fd95..b5e5c60 100644 --- a/src/gll.js +++ b/src/gll.js @@ -1,17 +1,3 @@ -const { - Graph, - NodeEvent, - EdgeEvent, - GraphEvent, - CanvasEvent, - CommonEvent, - WindowEvent, - Layout, - BaseLayout, - ExtensionCategory, - register -} = G6; - import {VERSION, DEFAULTS, CFG} from './config.js'; import {GraphCoreManager} from './graph/core.js'; @@ -31,12 +17,15 @@ import {AssistantManager} from './managers/assistant/index.js'; import {ColorScalePicker} from './utilities/color_scale_picker.js'; import {NumericScalePicker} from './utilities/numeric_scale_picker.js'; +import {PieChartPicker} from './utilities/pie_chart_picker.js'; import {DataTable, buildDataTable} from "./utilities/data_editor.js"; import {StringDemoDataLoader} from "./utilities/demo_loader.js"; import {Popup} from "./utilities/popup.js"; import {StaticUtilities} from "./utilities/static.js"; import {generateTourData, GuidedTour} from "./utilities/tour.js"; import {initApiClient} from "./managers/api_client.js"; +import {initTheme} from "./utilities/theme.js"; +import {initSelectionHud} from "./utilities/selection_hud.js"; // Stores all reference objects @@ -46,7 +35,7 @@ class Cache { reset() { this.initialized = false; - this.graph = null; // The G6 graph object + this.graph = null; // The renderer adapter (SigmaAdapter) // Stores json serializable data that is essential to reconstruct the graph this.data = { @@ -76,20 +65,11 @@ class Cache { }; this.EVENT_LOCKS = { - BEFORE_DRAW_RUNNING: false, AFTER_DRAW_RUNNING: false, - DRAG_END_RUNNING: false, - BEFORE_RENDER_RUNNING: false, - AFTER_RENDER_RUNNING: false, - BEFORE_LAYOUT_RUNNING: false, - AFTER_LAYOUT_RUNNING: false, ONCE_AFTER_RENDER_RUNNING: false, ONCE_AFTER_RENDER_COMPLETED: false, - IS_DESELECTING: false, BUBBLE_GROUP_REDRAW_RUNNING: false, TRIGGER_SET_LAYOUT_ONCE: false, - HOTKEY_EVENTS_REGISTERED: false, - GLOBAL_EVENTS_REGISTERED: false, SKIP_QUERY_VALIDATION: false, QUERY_SELECTION_EVENT: false, QUERY_UPDATE_EVENT: false, @@ -111,6 +91,7 @@ class Cache { this.style = new GraphStyleManager(this); this.picker = new ColorScalePicker(this); this.numericPicker = new NumericScalePicker(this); + this.piePicker = new PieChartPicker(this); this.dataTable = new DataTable(this); this.metrics = new NetworkMetrics(this); this.assistant = new AssistantManager(this); @@ -199,6 +180,11 @@ class Cache { this.iterNodes(); this.iterEdges(); + // NOTE: cache.graphData (the graphology model) is built exclusively by + // gcm.createGraphInstance — a single owner keeps the renderer and the + // model from ever diverging across reload cycles. + this.graphData = null; + this.dataTable.init(); } @@ -406,6 +392,11 @@ async function loadDemoData() { cache.ui.buildUI(); await cache.gcm.createGraphInstance(); + if (!cache.graph) { + await cache.ui.hideLoading(); + resolve(false); + return; + } await cache.graph.render(); resolve(true); } else { @@ -446,6 +437,10 @@ async function startTour() { cache.ui.buildUI(); await cache.gcm.createGraphInstance(); + if (!cache.graph) { + await cache.ui.hideLoading(); + return; + } await cache.graph.render(); await cache.ui.hideLoading(); @@ -463,17 +458,19 @@ window.cache = cache; window.addEventListener('resize', () => { if (window.graph !== undefined && window.graph !== null && window.cache.initialized) { - const editModeActive = document.getElementById("editBtn").classList.contains("active"); const sidebar = document.getElementById("sidebar"); - const sidebarContentContainer = document.getElementById("sidebarContentContainer"); const status = document.getElementById("sidebarStatusContainer"); - status.style.maxWidth = editModeActive ? `${sidebarContentContainer.offsetWidth}px` : `${sidebar.offsetWidth}px`; + status.style.maxWidth = `${sidebar.offsetWidth}px`; } }) window.addEventListener("DOMContentLoaded", () => { + // Stored preference wins; prefers-color-scheme is only the first-run default. + initTheme(document, window); cache.reset(); + cache.ui.updateDarkModeButton(); + initSelectionHud(); // cache.initialize(); // Display version info @@ -532,13 +529,10 @@ window.addEventListener("DOMContentLoaded", () => { sidebar.style.width = `${newWidth}px`; - // Update status container max-width if needed - const editModeActive = document.getElementById("editBtn")?.classList.contains("active"); - const sidebarContentContainer = document.getElementById("sidebarContentContainer"); + // Update status container max-width to match the new sidebar width const status = document.getElementById("sidebarStatusContainer"); - - if (status && sidebarContentContainer) { - status.style.maxWidth = editModeActive ? `${sidebarContentContainer.offsetWidth}px` : `${newWidth}px`; + if (status) { + status.style.maxWidth = `${newWidth}px`; } isResizing = false; diff --git a/src/graph/bubble_geometry.js b/src/graph/bubble_geometry.js new file mode 100644 index 0000000..9d0c5f9 --- /dev/null +++ b/src/graph/bubble_geometry.js @@ -0,0 +1,336 @@ +/** + * Node-safe bubble-set geometry helpers (MIGRATION.md Phase 4). + * + * Pure math between the app's bubble groups and bubblesets-js: rect + * building, outline computation/sampling, label anchoring and the cache + * keys the browser layer (bubble_layer.js) uses to decide when a recompute + * is actually needed. Must never import the sigma bundle — vitest imports + * this module under node. + */ +import { bubblesets, polygonClipping } from "../lib/graphology.bundle.mjs"; + +// PointPath post-processing per the bubblesets-js README: sample the raw +// marching-squares outline, B-spline it and drop collinear points. 8 is the +// library's own example default and keeps point counts in the low hundreds. +// Scaled with opts.scale (a step of 8 would flatten a zoomed-out outline +// whose features are ~2 points) but never below 1. +// +// NOTE: bubblesets-js sample(step) treats `step` as an array INDEX stride +// (points.get(i += step)), NOT a pixel distance. PointPath.get() does +// `this.points[step]`, so a FRACTIONAL stride indexes between elements and +// returns undefined, which then crashes bSplines()/simplify() with +// "Cannot read properties of undefined". The stride must stay an integer. +const OUTLINE_SAMPLE_STEP = 8; +const OUTLINE_SAMPLE_MIN_STEP = 1; + +// bubblesets-js influence-field defaults (the library's own pixel-tuned +// constants). They are absolute pixel radii, so the caller must scale them +// with the on-screen node size (opts.scale): zoomed far out, an unscaled +// 50 px negative disc around every avoid node swallows the (shrunken) +// members' positive field and the outline collapses to nothing. +const FIELD_NODE_R0 = 15; +const FIELD_NODE_R1 = 50; +const FIELD_EDGE_R0 = 10; +const FIELD_EDGE_R1 = 20; +const FIELD_MORPH_BUFFER = 10; +const FIELD_PIXEL_GROUP = 4; +// Marching-squares grid cell can never go below 1 px (pixelGroup 0 hangs +// the library; sub-pixel cells just waste time). +const FIELD_PIXEL_GROUP_MIN = 1; + +/** + * Axis-aligned square around a node's viewport position. + * + * @param {number} x center x (viewport px) + * @param {number} y center y (viewport px) + * @param {number} radius on-screen node radius (px) + * @returns {{x: number, y: number, width: number, height: number}} + */ +function nodeViewportRect(x, y, radius) { + return { x: x - radius, y: y - radius, width: 2 * radius, height: 2 * radius }; +} + +/** + * Compute one group's outline polygon from member/avoid rects. + * + * @param {Array<{x,y,width,height}>} memberRects + * @param {Array<{x,y,width,height}>} avoidRects + * @param {{virtualEdges?: boolean, scale?: number}} [opts] + * virtualEdges routes connecting corridors around avoid rects (the + * per-group style enables it); its cost is O(members × avoid) — see + * MAX_NODES_BEFORE_DISABLING_AVOID_MEMBERS_IN_BUBBLE_GROUPS in config.js + * for the measured budget. + * scale multiplies the bubblesets influence-field pixel constants so the + * field stays proportional to the rects at any zoom (1 = library + * defaults; pass sigma's node-size zoom factor). + * @returns {Array<{x: number, y: number}>} closed polygon (empty when no + * members or the outline collapsed) + */ +function computeOutlinePoints(memberRects, avoidRects = [], opts = {}) { + if (!memberRects || memberRects.length === 0) return []; + const s = opts.scale ?? 1; + const path = bubblesets.createOutline(memberRects, avoidRects, [], { + virtualEdges: opts.virtualEdges !== false, + nodeR0: FIELD_NODE_R0 * s, + nodeR1: FIELD_NODE_R1 * s, + edgeR0: FIELD_EDGE_R0 * s, + edgeR1: FIELD_EDGE_R1 * s, + morphBuffer: FIELD_MORPH_BUFFER * s, + pixelGroup: Math.max(FIELD_PIXEL_GROUP_MIN, FIELD_PIXEL_GROUP * s), + }); + // Integer stride only (see OUTLINE_SAMPLE_STEP note): Math.round keeps the + // ~8-point cadence proportional to zoom without ever passing a fractional + // index into bubblesets-js' PointPath.get(). + const sampleStep = Math.max(OUTLINE_SAMPLE_MIN_STEP, Math.round(OUTLINE_SAMPLE_STEP * s)); + let sampled; + try { + sampled = path.sample(sampleStep).simplify(0).bSplines().simplify(0); + } catch { + // Boundary guard for bubblesets-js: a degenerate/collapsed outline must + // resolve to "no outline" (this function's documented contract) rather + // than throwing into the render loop and freezing the bubble canvas. + return []; + } + const smoothed = pointPathToArray(sampled); + // bubblesets can return a self-intersecting ring — virtualEdges corridor + // routing crosses itself at some scales, and the bSpline smoothing overshoots + // into self-loops when members spread faster than the influence field grows. + // Drawn directly these paint as phantom chords / lobes (and a downstream + // convex-hull fallback was worse). Repair via polygon self-union, which + // resolves the crossings into valid simple rings; keep the largest. The + // result still hugs every member — never a blocky hull. + if (polygonSelfIntersects(smoothed)) { + const repaired = repairSelfIntersections(smoothed); + if (repaired.length >= 3) return repaired; + } + return smoothed; +} + +/** Materialize a bubblesets-js PointPath into a plain {x,y} array. */ +function pointPathToArray(pointPath) { + const points = []; + for (let i = 0; i < pointPath.length; i++) { + const p = pointPath.get(i); + points.push({ x: p.x, y: p.y }); + } + return points; +} + +/** + * Resolve a self-intersecting closed polygon into a simple one via polygon + * self-union (polygon-clipping), returning the largest resulting outer ring. + * The union normalizes the crossings into valid, non-self-intersecting rings; + * the largest is the outline's outer boundary, which still encloses every + * member. Returns the input unchanged if the union throws or yields nothing. + * + * @param {Array<{x: number, y: number}>} points closed polygon ring + * @returns {Array<{x: number, y: number}>} + */ +function repairSelfIntersections(points) { + if (points.length < 4) return points; + const ring = points.map((p) => [p.x, p.y]); + ring.push([points[0].x, points[0].y]); // polygon-clipping expects closed rings + let result; + try { + result = polygonClipping.union([ring]); + } catch { + // A clipping edge case must never throw into the render loop and freeze + // the bubble canvas; the caller keeps the (self-intersecting) input. + return points; + } + let best = null; + let bestArea = -1; + for (const poly of result) { + const outer = poly[0]; + const area = Math.abs(ringSignedArea(outer)); + if (area > bestArea) { + bestArea = area; + best = outer; + } + } + if (!best || best.length < 4) return points; + // Drop polygon-clipping's repeated closing vertex; back to {x, y}. + return best.slice(0, -1).map(([x, y]) => ({ x, y })); +} + +/** Signed area (shoelace) of a closed ring of [x, y] pairs. */ +function ringSignedArea(ring) { + let area = 0; + for (let i = 0; i < ring.length - 1; i++) { + const [x1, y1] = ring[i]; + const [x2, y2] = ring[i + 1]; + area += x1 * y2 - x2 * y1; + } + return area / 2; +} + +/** Do two segments (p1→p2, p3→p4) cross at an interior point of both? */ +function segmentsCross(p1, p2, p3, p4) { + const d = (p2.x - p1.x) * (p4.y - p3.y) - (p2.y - p1.y) * (p4.x - p3.x); + if (Math.abs(d) < 1e-9) return false; // parallel/collinear + const t = ((p3.x - p1.x) * (p4.y - p3.y) - (p3.y - p1.y) * (p4.x - p3.x)) / d; + const u = ((p3.x - p1.x) * (p2.y - p1.y) - (p3.y - p1.y) * (p2.x - p1.x)) / d; + // Strict interiors so shared vertices of adjacent edges don't count. + return t > 1e-6 && t < 1 - 1e-6 && u > 1e-6 && u < 1 - 1e-6; +} + +/** + * Whether a closed polygon's edges cross each other (ignoring shared vertices + * of adjacent edges). O(n²) — only called once per outline refit, never per + * frame. Short-circuits on the first crossing. + * + * @param {Array<{x: number, y: number}>} points closed polygon ring + * @returns {boolean} + */ +function polygonSelfIntersects(points) { + const n = points.length; + if (n < 4) return false; + for (let i = 0; i < n; i++) { + const a = points[i]; + const b = points[(i + 1) % n]; + for (let j = i + 2; j < n; j++) { + if (i === 0 && j === n - 1) continue; // last edge shares vertex 0 with first + if (segmentsCross(a, b, points[j], points[(j + 1) % n])) return true; + } + } + return false; +} + +// Extreme-point comparators per placement (viewport space is y-down, so +// "top" is the smallest y). Unknown placements fall back to "top". +const PLACEMENT_EXTREME = { + top: (p, q) => p.y < q.y, + bottom: (p, q) => p.y > q.y, + left: (p, q) => p.x < q.x, + right: (p, q) => p.x > q.x, +}; + +/** + * Label anchor for an outline polygon. + * + * For edge placements ("top"/"bottom"/"left"/"right") the anchor is the + * extreme outline vertex in that direction; angle is the outline tangent at + * that vertex (from its two ring neighbors), normalized into [-PI/2, PI/2] + * so rotated text stays upright; (nx, ny) is the outward unit normal + * (perpendicular to the tangent, flipped if it points toward the vertex + * centroid). "center" returns the vertex centroid with angle 0, nx = ny = 0. + * + * @param {Array<{x: number, y: number}>} points + * @param {"top"|"bottom"|"left"|"right"|"center"} [placement] + * @returns {{x: number, y: number, angle: number, nx: number, ny: number}|null} + */ +function outlineLabelAnchor(points, placement = "top") { + if (!points || points.length === 0) return null; + const n = points.length; + let cx = 0; + let cy = 0; + for (const p of points) { + cx += p.x; + cy += p.y; + } + cx /= n; + cy /= n; + if (placement === "center") return { x: cx, y: cy, angle: 0, nx: 0, ny: 0 }; + + const isBetter = PLACEMENT_EXTREME[placement] ?? PLACEMENT_EXTREME.top; + let idx = 0; + for (let i = 1; i < n; i++) { + if (isBetter(points[i], points[idx])) idx = i; + } + const anchor = points[idx]; + const prev = points[(idx - 1 + n) % n]; + const next = points[(idx + 1) % n]; + + let angle = Math.atan2(next.y - prev.y, next.x - prev.x); + if (angle > Math.PI / 2) angle -= Math.PI; + else if (angle < -Math.PI / 2) angle += Math.PI; + + let nx = -Math.sin(angle); + let ny = Math.cos(angle); + if (nx * (cx - anchor.x) + ny * (cy - anchor.y) > 0) { + nx = -nx; + ny = -ny; + } + return { x: anchor.x, y: anchor.y, angle, nx, ny }; +} + +/** + * Order-insensitive identity key for a member id set. Sorting keeps the key + * stable across the manager's Set→Array conversions; NUL-joined so ids + * containing spaces cannot make distinct sets collide. + * + * @param {Iterable} ids + * @returns {string} + */ +function idsKey(ids) { + return [...ids].sort().join("\u0000"); +} + +/** + * Checksum over member positions so a node drag invalidates the cached + * outline. 32-bit FNV-style integer fold (Math.imul) over coordinates + * quantized to 1/8 px plus the index: exact integer arithmetic is immune to + * IEEE754 accumulation loss at large coordinate magnitudes and member + * counts, and folding the index in keeps it order-sensitive (transpositions + * hash differently). + * + * @param {Array<{x: number, y: number}>} points + * @returns {string} + */ +function positionsChecksum(points) { + let hash = 0x811c9dc5; + let i = 0; + for (const p of points) { + hash = Math.imul(hash ^ Math.round(p.x * 8), 0x01000193); + hash = Math.imul(hash ^ Math.round(p.y * 8), 0x01000193); + hash = Math.imul(hash ^ i, 0x01000193); + i++; + } + return `${points.length}:${hash >>> 0}`; +} + +// Style fields that change the painted result; everything else the manager +// passes (members, avoidMembers) is keyed elsewhere by the layer. +const STYLE_KEY_FIELDS = [ + "fill", + "fillOpacity", + "stroke", + "strokeOpacity", + "virtualEdges", + "label", + "labelText", + "labelFill", + "labelFontSize", + "labelPadding", + "labelBackground", + "labelBackgroundFill", + "labelBackgroundRadius", + "labelOffsetX", + "labelOffsetY", + "labelPlacement", + "labelCloseToPath", + "labelAutoRotate", +]; + +/** + * Stable key over the style options that affect painting. JSON-serialized + * per field so a literal "undefined" string can never collide with a + * missing field; null and missing collide on purpose (both paint via the + * group defaults). + * + * @param {object} opts group style options (manager-passed) + * @returns {string} + */ +function styleKey(opts = {}) { + return STYLE_KEY_FIELDS.map((field) => JSON.stringify(opts[field] ?? null)).join("|"); +} + +export { + nodeViewportRect, + computeOutlinePoints, + polygonSelfIntersects, + outlineLabelAnchor, + idsKey, + positionsChecksum, + styleKey, +}; diff --git a/src/graph/bubble_layer.js b/src/graph/bubble_layer.js new file mode 100644 index 0000000..4f1a5cf --- /dev/null +++ b/src/graph/bubble_layer.js @@ -0,0 +1,495 @@ +/** + * Browser-only bubble-set rendering layer (MIGRATION.md Phase 4). + * + * Two 2d canvases registered with sigma: the fill/outline canvas sits ABOVE + * the node layer (createCanvasContext + afterLayer: "nodes") so the group + * body/outline stays visible at deep zoom-in, where enlarged nodes would + * otherwise cover a body painted underneath them; the group-LABEL canvas sits + * ABOVE sigma's node-label layer (afterLayer: "labels") so a member node's own + * label can never obscure the group name (a primary read). All four bubble + * groups paint in a single pass. GraphBubbleSetManager keeps talking to per-group + * "plugin instances" — those are thin handles into this layer's group state + * (see getGroupHandle), so the manager's member/filter/style logic survives + * the G6 → sigma port unchanged. + * + * Outlines are fitted by bubblesets-js at the ratio-1 reference scale + * (bubble_geometry.js) and cached in GRAPH space, so they are zoom-invariant — + * a member is always enclosed at every zoom: + * - membership / style / member-position changes → full recompute (the + * identity key in #syncGroupOutline catches them on the next frame, so + * a filter event can never leave a stale outline painted) + * - camera pan/zoom → cheap per-frame reprojection of the cached graph + * points; the camera is NOT in the identity key, so zoom never re-fits + * This replaces the G6 plugin's recompute-per-draw churn (the patched + * updateBubbleSetsPath path coalescing, issue #7195) with an owned cache. + */ +import { DEFAULTS } from "../config.js"; +import { + nodeViewportRect, + computeOutlinePoints, + polygonSelfIntersects, + outlineLabelAnchor, + idsKey, + positionsChecksum, + styleKey, +} from "./bubble_geometry.js"; + +const LAYER_NAME = "bubbleSets"; +const LABEL_LAYER_NAME = "bubbleSetsLabels"; +const OUTLINE_STROKE_WIDTH = 2; +// Extra screen-px gap (beyond half the font box) between the outline and a +// label drawn with labelCloseToPath: false. +const LABEL_STANDOFF_PX = 8; + +class BubbleSetLayer { + /** + * @param {object} adapter SigmaAdapter (owns sigma + graphology) + * @param {object} cache app cache + */ + constructor(adapter, cache) { + this.adapter = adapter; + this.cache = cache; + this.killed = false; + + /** @type {Map, avoidMembers: string[], opts: object}>} */ + this.groups = new Map(); + // Per-group outline cache: identity key (membership, style, positions, + // viewport size, ratio bucket) + graph-space points. + /** @type {Map}>} */ + this.outlines = new Map(); + + this.rafHandle = null; + this.lastPaintSignature = null; + + const sigma = adapter.sigma; + // createCanvasContext returns the Sigma instance (fluent API); the canvas + // and 2d context land in sigma.elements / sigma.canvasContexts. + sigma.createCanvasContext(LAYER_NAME, { + afterLayer: "nodes", + style: { pointerEvents: "none" }, + }); + this.canvas = sigma.getCanvases()[LAYER_NAME]; + this.ctx = this.canvas.getContext("2d"); + + // Group labels paint on their own canvas stacked above sigma's node-label + // layer so they always win the z-order contest against member labels. + sigma.createCanvasContext(LABEL_LAYER_NAME, { + afterLayer: "labels", + style: { pointerEvents: "none" }, + }); + this.labelCanvas = sigma.getCanvases()[LABEL_LAYER_NAME]; + this.labelCtx = this.labelCanvas.getContext("2d"); + + this.renderHandler = () => this.scheduleRedraw(); + sigma.on("afterRender", this.renderHandler); + } + + /** + * Per-group handle with the old G6 plugin-instance call surface the + * manager expects: a `members` Map plus async update()/drawBubbleSets(). + * + * @param {string} group bubble group key (e.g. "groupOne") + */ + getGroupHandle(group) { + this.#groupState(group); // materialize the state slot + const layer = this; + return { + get members() { + return layer.#groupState(group).members; + }, + async update(opts = {}) { + layer.#updateGroup(group, opts); + }, + async drawBubbleSets() { + layer.scheduleRedraw(); + }, + }; + } + + destroy() { + if (this.killed) return; + this.killed = true; + if (this.rafHandle !== null) cancelAnimationFrame(this.rafHandle); + this.adapter.sigma.off("afterRender", this.renderHandler); + // sigma.kill() may or may not remove custom layer canvases; remove() on + // an already-detached node is a no-op, so drop ours defensively. + this.canvas?.remove(); + this.labelCanvas?.remove(); + } + + scheduleRedraw() { + if (this.killed || this.rafHandle !== null) return; + this.rafHandle = requestAnimationFrame(() => { + this.rafHandle = null; + this.#paint(); + }); + } + + // ------------------------------------------------------------ group state + + #groupState(group) { + let state = this.groups.get(group); + if (!state) { + state = { members: new Map(), avoidMembers: [], opts: {}, membersKey: "", avoidKey: "" }; + this.groups.set(group, state); + } + return state; + } + + #updateGroup(group, opts) { + const state = this.#groupState(group); + const { members, avoidMembers, ...style } = opts; + // Membership only changes here, so the O(n log n) identity keys are + // computed once per update instead of on every afterRender frame. + if (Array.isArray(members)) { + state.members = new Map(members.map((id) => [id, true])); + state.membersKey = idsKey(state.members.keys()); + } + if (Array.isArray(avoidMembers)) { + state.avoidMembers = [...avoidMembers]; + state.avoidKey = idsKey(state.avoidMembers); + } + state.opts = { ...state.opts, ...style }; + this.scheduleRedraw(); + } + + // ----------------------------------------------------------------- paint + + #paint() { + if (this.killed) return; + const sigma = this.adapter.sigma; + const { width, height } = sigma.getDimensions(); + const dpr = sigma.pixelRatio ?? window.devicePixelRatio ?? 1; + const camera = sigma.getCamera().getState(); + + // Outlines are fitted in GRAPH space (zoom-invariant), so the camera never + // forces a re-fit — #syncGroupOutline only re-fits when a group's identity + // (members, positions, style) changes. Any camera move just reprojects the + // cached graph points each frame (cheap), keeping the hull hugging at every + // zoom with members always enclosed. + let outlinesChanged = false; + const active = []; + for (const [group, state] of this.groups) { + if (state.members.size === 0) { + if (this.outlines.delete(group)) outlinesChanged = true; + continue; + } + outlinesChanged = this.#syncGroupOutline(group, state) || outlinesChanged; + if (this.outlines.get(group)?.graphPoints.length) active.push([group, state]); + } + + // Skip repainting when neither the outlines nor the view changed (sigma + // re-renders on hover etc. without clearing custom layers). + const signature = + `${width}x${height}x${dpr}|${camera.x},${camera.y},${camera.ratio},${camera.angle}` + + `|${active.map(([g]) => g).join(",")}`; + if (!outlinesChanged && signature === this.lastPaintSignature) return; + this.lastPaintSignature = signature; + + this.#prepareCanvas(this.canvas, this.ctx, width, height, dpr); + this.#prepareCanvas(this.labelCanvas, this.labelCtx, width, height, dpr); + this.#drawOutlines(active, sigma); + } + + /** Reproject each cached graph-space outline to viewport px and paint it. */ + #drawOutlines(active, sigma) { + for (const [group, state] of active) { + // Reprojection assumes camera.angle === 0 (the app never rotates the camera). + const points = this.outlines + .get(group) + .graphPoints.map((p) => sigma.graphToViewport(p)); + const defaults = this.cache.DEFAULTS.BUBBLE_GROUP_STYLE[group] ?? {}; + const drawn = this.#drawGroup(this.ctx, points, state, defaults); + // Labels paint on the top canvas (afterLayer: "labels") so they read + // over member-node labels; the body/outline stayed on the bottom one. + if (drawn && state.opts.label) { + this.#drawLabel(this.labelCtx, points, state.opts, defaults); + } + } + } + + // ---------------------------------------------------------------- export + + /** + * Outlines for export, in viewport CSS px at the CURRENT camera. The cached + * outline is graph-space and zoom-invariant, so reprojecting it at the + * current camera is exact — it matches the on-screen hull. Fits on the fly + * for any group not yet painted. + * + * @returns {Array<{group: string, points: Array<{x: number, y: number}>, + * opts: object, defaults: object}>} + */ + exportOutlines() { + const graph = this.adapter.graph; + const sigma = this.adapter.sigma; + const out = []; + for (const [group, state] of this.groups) { + if (state.members.size === 0) continue; + let graphPoints = this.outlines.get(group)?.graphPoints; + if (!graphPoints?.length) { + const visibleMembers = []; + for (const id of state.members.keys()) { + if (!graph.hasNode(id)) continue; + const attrs = graph.getNodeAttributes(id); + if (!attrs.hidden) visibleMembers.push({ id, attrs }); + } + if (visibleMembers.length === 0) continue; + graphPoints = this.#fitGraphOutline(state, visibleMembers); + } + if (!graphPoints || graphPoints.length < 2) continue; + out.push({ + group, + points: graphPoints.map((p) => sigma.graphToViewport(p)), + opts: state.opts, + defaults: this.cache.DEFAULTS.BUBBLE_GROUP_STYLE[group] ?? {}, + }); + } + return out; + } + + /** + * Paint the groups' bodies/outlines onto an export context at `scale` + * device px per CSS px. Geometry is in CSS px (same numbers the screen + * uses), so the transform re-renders it crisp at the export resolution — + * this replaces the old bitmap stretch of the on-screen canvas, which + * blurred hulls at 2×+ exports. + * + * @param {CanvasRenderingContext2D} ctx + * @param {ReturnType} groups + * @param {number} scale + */ + drawExportBodies(ctx, groups, scale) { + ctx.save(); + try { + ctx.setTransform(scale, 0, 0, scale, 0, 0); + for (const { points, opts, defaults } of groups) { + this.#drawGroup(ctx, points, { opts }, defaults); + } + } finally { + ctx.restore(); + } + } + + /** + * Paint the groups' labels onto an export context at `scale` device px per + * CSS px (composited ABOVE the sigma image, like the live label canvas). + * + * @param {CanvasRenderingContext2D} ctx + * @param {ReturnType} groups + * @param {number} scale + */ + drawExportLabels(ctx, groups, scale) { + ctx.save(); + try { + ctx.setTransform(scale, 0, 0, scale, 0, 0); + for (const { points, opts, defaults } of groups) { + if (opts.label) this.#drawLabel(ctx, points, opts, defaults); + } + } finally { + ctx.restore(); + } + } + + /** Resize (if needed) and clear a layer canvas, scaled to the device ratio. */ + #prepareCanvas(canvas, ctx, width, height, dpr) { + if (canvas.width !== width * dpr || canvas.height !== height * dpr) { + canvas.width = width * dpr; + canvas.height = height * dpr; + } + ctx.setTransform(dpr, 0, 0, dpr, 0, 0); + ctx.clearRect(0, 0, width, height); + } + + /** + * Recompute the group's outline when its identity (members, positions, + * style) changes. The fit is in graph space and zoom-invariant, so the + * camera is NOT part of the key — zoom never re-fits, it only reprojects. + * + * @returns {boolean} true when the cached outline was replaced + */ + #syncGroupOutline(group, state) { + const graph = this.adapter.graph; + const memberPositions = []; + const visibleMembers = []; + for (const id of state.members.keys()) { + if (!graph.hasNode(id)) continue; + const attrs = graph.getNodeAttributes(id); + if (attrs.hidden) continue; + visibleMembers.push({ id, attrs }); + memberPositions.push({ x: attrs.x, y: attrs.y }); + } + + // membersKey/avoidKey are precomputed in #updateGroup, so the per-frame + // cost here is the O(n) position checksum. Hidden flips stay correct: an + // unhide changes visibleMembers.length, and a same-count hidden swap + // changes the checksum. No camera/viewport term — the graph-space outline + // is the same at every zoom. + const key = + `${state.membersKey}|${state.avoidKey}|${visibleMembers.length}` + + `|${styleKey(state.opts)}|${positionsChecksum(memberPositions)}`; + const cached = this.outlines.get(group); + if (cached && cached.key === key) return false; + + if (visibleMembers.length === 0) { + this.outlines.delete(group); + return cached !== undefined; + } + + const graphPoints = this.#fitGraphOutline(state, visibleMembers); + // computeOutlinePoints repairs self-intersections, so a bad fit here is a + // collapse to nothing or the rare unrepairable self-cross. Never let it + // replace a good outline. + const selfIntersects = graphPoints.length >= 4 && polygonSelfIntersects(graphPoints); + const collapsed = graphPoints.length < 3; + if (selfIntersects || collapsed) { + if (cached?.graphPoints.length) { + this.outlines.set(group, { key, graphPoints: cached.graphPoints }); + return true; + } + // No prior good outline yet: stay absent until a clean fit appears. + return this.outlines.delete(group); + } + this.outlines.set(group, { key, graphPoints }); + return true; + } + + /** + * Fit a group's outline at the ratio-1 REFERENCE viewport scale, then map it + * to graph space for the cache. bubblesets-js' field constants are tuned for + * on-screen pixels, so the fit must run where node sizes are pixel-scale — + * the ratio-1 viewport, which is independent of the current camera. That + * makes the outline zoom-invariant: a member is always enclosed and the same + * cached hull reprojects to hug the nodes at any zoom. Shared by + * #syncGroupOutline and the export path. + * + * @param {object} state group state (avoidMembers, opts) + * @param {Array<{id: string, attrs: object}>} visibleMembers + * @returns {Array<{x: number, y: number}>} graph-space outline (may be empty) + */ + #fitGraphOutline(state, visibleMembers) { + const graph = this.adapter.graph; + const sigma = this.adapter.sigma; + const { width, height } = sigma.getDimensions(); + const camera = sigma.getCamera().getState(); + const cx = width / 2; + const cy = height / 2; + const r = camera.ratio; + // graphToViewport divides the offset-from-centre by the ratio; multiply it + // back to land at the ratio-1 viewport (ratio cancels, so this is the same + // at any zoom). Node radius is taken at ratio 1 too. + const toRefRect = (attrs) => { + const v = sigma.graphToViewport({ x: attrs.x, y: attrs.y }); + const rx = cx + (v.x - cx) * r; + const ry = cy + (v.y - cy) * r; + return nodeViewportRect(rx, ry, sigma.scaleSize(attrs.size ?? DEFAULTS.NODE.SIZE / 2, 1)); + }; + const memberRects = visibleMembers.map(({ attrs }) => toRefRect(attrs)); + const avoidRects = []; + for (const id of state.avoidMembers) { + if (!graph.hasNode(id)) continue; + const attrs = graph.getNodeAttributes(id); + if (attrs.hidden) continue; + avoidRects.push(toRefRect(attrs)); + } + + const outlineOpts = { virtualEdges: state.opts.virtualEdges, scale: 1 }; + let refPoints = computeOutlinePoints(memberRects, avoidRects, outlineOpts); + // Safety net: if the avoid nodes' negative field collapses the outline, a + // hull that ignores avoid nodes beats a vanished group. + if (refPoints.length === 0 && avoidRects.length > 0) { + refPoints = computeOutlinePoints(memberRects, [], outlineOpts); + } + // Reference-viewport → graph space (undo the ratio-1 mapping, then the + // camera): the cache holds zoom-independent graph coords. + return refPoints.map((p) => + sigma.viewportToGraph({ x: cx + (p.x - cx) / r, y: cy + (p.y - cy) / r }), + ); + } + + /** + * Paint one group's body + outline from viewport-projected points. Returns + * true when something was painted (false when the outline is too small), + * so the caller knows whether a label belongs on the top canvas. + */ + #drawGroup(ctx, points, { opts }, defaults) { + if (!points || points.length < 2) return false; + + const path = new Path2D(); + path.moveTo(points[0].x, points[0].y); + for (let i = 1; i < points.length; i++) path.lineTo(points[i].x, points[i].y); + path.closePath(); + + ctx.save(); + try { + ctx.globalAlpha = opts.fillOpacity ?? defaults.fillOpacity ?? 0.25; + ctx.fillStyle = opts.fill ?? defaults.fill ?? "#403C53"; + ctx.fill(path); + ctx.globalAlpha = opts.strokeOpacity ?? defaults.strokeOpacity ?? 1; + ctx.strokeStyle = opts.stroke ?? defaults.stroke ?? "#403C53"; + ctx.lineWidth = OUTLINE_STROKE_WIDTH; + ctx.stroke(path); + ctx.globalAlpha = 1; + } finally { + ctx.restore(); + } + return true; + } + + /** + * Group label at the outline extreme picked by labelPlacement (the old G6 + * plugin's surface): labelCloseToPath: false pushes it off the path along + * the outward normal; labelAutoRotate aligns on-path labels with the + * outline tangent. labelOffsetX/Y stay additive in screen space. + */ + #drawLabel(ctx, points, opts, defaults) { + const text = opts.labelText ?? defaults.labelText ?? ""; + if (!text) return; + const placement = opts.labelPlacement ?? defaults.labelPlacement ?? "bottom"; + const closeToPath = opts.labelCloseToPath ?? defaults.labelCloseToPath ?? true; + const autoRotate = opts.labelAutoRotate ?? defaults.labelAutoRotate ?? true; + const anchor = outlineLabelAnchor(points, placement); + if (!anchor) return; + + const fontSize = opts.labelFontSize ?? defaults.labelFontSize ?? 12; + const padding = opts.labelPadding ?? defaults.labelPadding ?? 2; + // Off-path labels clear the outline by half the padded font box plus a + // fixed gap, pushed along the outward normal (no-op for "center"). + const standoff = closeToPath ? 0 : fontSize / 2 + padding + LABEL_STANDOFF_PX; + const x = anchor.x + anchor.nx * standoff + (opts.labelOffsetX ?? 0); + const y = anchor.y + anchor.ny * standoff + (opts.labelOffsetY ?? 0); + + ctx.font = `${fontSize}px Arial, sans-serif`; + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; + const textWidth = ctx.measureText(text).width; + + // Rotation only makes sense hugging the path; "center" has no tangent. + const rotated = autoRotate && closeToPath && placement !== "center"; + if (rotated) { + ctx.save(); + ctx.translate(x, y); + ctx.rotate(anchor.angle); + } + const lx = rotated ? 0 : x; + const ly = rotated ? 0 : y; + + if (opts.labelBackground ?? defaults.labelBackground) { + const radius = opts.labelBackgroundRadius ?? defaults.labelBackgroundRadius ?? 5; + ctx.fillStyle = opts.labelBackgroundFill ?? defaults.labelBackgroundFill ?? "#403C53"; + ctx.beginPath(); + ctx.roundRect( + lx - textWidth / 2 - padding, + ly - fontSize / 2 - padding, + textWidth + 2 * padding, + fontSize + 2 * padding, + radius, + ); + ctx.fill(); + } + ctx.fillStyle = opts.labelFill ?? defaults.labelFill ?? "#fff"; + ctx.fillText(text, lx, ly); + if (rotated) ctx.restore(); + } +} + +export { BubbleSetLayer }; diff --git a/src/graph/bubble_sets.js b/src/graph/bubble_sets.js index 58fed0d..3ee9c2b 100644 --- a/src/graph/bubble_sets.js +++ b/src/graph/bubble_sets.js @@ -1,8 +1,16 @@ import {StaticUtilities} from "../utilities/static.js"; +import {detectCommunities as computeCommunityAssignments} from "./communities.js"; +import {clampPopoverLeft} from "../utilities/popover_position.js"; +import {Popup} from "../utilities/popup.js"; class GraphBubbleSetManager { constructor(cache) { this.cache = cache; + // Louvain detection prefs (transient UI state, not persisted/exported). + // weightProperty: undefined until first resolved (then a numeric edge + // prop hash, or null for topology-only); resolution: Louvain γ. + this.communityOptions = { weightProperty: undefined, resolution: 1 }; + this.communityPopover = null; this.redrawBubbleSets = debounce(async () => { if (!this.cache.EVENT_LOCKS.ONCE_AFTER_RENDER_COMPLETED) return; if (this.cache.EVENT_LOCKS.BUBBLE_GROUP_REDRAW_RUNNING) return; @@ -29,6 +37,42 @@ class GraphBubbleSetManager { } } + /** + * Single source of truth for a group's visible members in the current + * layout: filter/property-based (${group}Props) UNION manual selection + * (${group}ManualMembers), using the same visibility filter the outline + * renderer applies. Every count shown to the user (status badge, styling + * card enable state) and the rendered outline derive from THIS method, so + * the displayed number can never drift from what is highlighted. + * @param {string} group + * @returns {Set} visible node IDs + */ + getEffectiveGroupMembers(group) { + const currentLayout = this.cache.data.layouts[this.cache.data.selectedLayout]; + const members = new Set(); + + // Filter/property-based members: resolved live from the active props. + const propsInGroup = currentLayout[`${group}Props`] || new Set(); + for (const prop of propsInGroup) { + const nodeIDs = this.cache.propIDsToNodeIDsToBeShown.get(prop) || []; + for (const nodeID of nodeIDs) { + if (!this.cache.hiddenDanglingNodeIDs.has(nodeID)) members.add(nodeID); + } + } + + // Manual selection members: only nodes still present and visible. + const manualMembers = currentLayout[`${group}ManualMembers`]; + if (manualMembers) { + for (const nodeID of manualMembers) { + if (this.cache.nodeRef.has(nodeID) && !this.cache.hiddenDanglingNodeIDs.has(nodeID)) { + members.add(nodeID); + } + } + } + + return members; + } + async updateBubbleSetStyle(property, value) { const remainder = property.split('Bubble Set ')[1]; const parts = remainder.split(' '); @@ -98,31 +142,8 @@ class GraphBubbleSetManager { const currentLayout = this.cache.data.layouts[this.cache.data.selectedLayout]; const bubbleStyle = currentLayout.bubbleSetStyle[group]; - // Calculate actual members for this group in the current layout - let actualMembers = new Set(); - - // Add members from filter-based properties - const propsInGroup = currentLayout[`${group}Props`] || new Set(); - for (let prop of propsInGroup) { - let nodeIDsToBeGrouped = this.cache.propIDsToNodeIDsToBeShown.get(prop) || []; - for (let nodeID of nodeIDsToBeGrouped) { - // Explicitly exclude dummy node - if (nodeID !== this.cache.CFG.INVISIBLE_DUMMY_NODE.id) { - actualMembers.add(nodeID); - } - } - } - - // Add members from manual group selection - const manualMembers = currentLayout[`${group}ManualMembers`] || new Set(); - for (let nodeID of manualMembers) { - // Explicitly exclude dummy node - if (nodeID !== this.cache.CFG.INVISIBLE_DUMMY_NODE.id && this.cache.nodeRef.has(nodeID)) { - actualMembers.add(nodeID); - } - } - - const hasActiveMembers = actualMembers.size > 0; + // Same union the outline renders (see getEffectiveGroupMembers). + const hasActiveMembers = this.getEffectiveGroupMembers(group).size > 0; if (hasActiveMembers) anyGroupActive = true; const labelConfigShouldBeEnabled = bubbleStyle.label; @@ -196,35 +217,8 @@ class GraphBubbleSetManager { async updateBubbleSetIfChanged() { for (let group of this.traverseBubbleSets()) { - let propsInGroup = this.cache.data.layouts[this.cache.data.selectedLayout][`${group}Props`]; - let lastSetMembers = this.cache.lastBubbleSetMembers.get(group); - let newSetMembers = new Set(); - - // Add members from filter-based properties - for (let prop of propsInGroup) { - let nodeIDsToBeGrouped = this.cache.propIDsToNodeIDsToBeShown.get(prop) || []; - for (let nodeID of nodeIDsToBeGrouped) { - // Explicitly exclude dummy node and hidden dangling nodes - if (nodeID !== this.cache.CFG.INVISIBLE_DUMMY_NODE.id && - !this.cache.hiddenDanglingNodeIDs.has(nodeID)) { - newSetMembers.add(nodeID); - } - } - } - - // Add members from manual group selection - const manualMembers = this.cache.data.layouts[this.cache.data.selectedLayout][`${group}ManualMembers`]; - if (manualMembers && manualMembers.size > 0) { - for (let nodeID of manualMembers) { - // Only add if node is still visible (not filtered out), and explicitly exclude dummy node and hidden dangling nodes - if (nodeID !== this.cache.CFG.INVISIBLE_DUMMY_NODE.id && - this.cache.nodeRef.has(nodeID) && - !this.cache.hiddenDanglingNodeIDs.has(nodeID)) { - newSetMembers.add(nodeID); - } - } - } + let newSetMembers = this.getEffectiveGroupMembers(group); if (!StaticUtilities.setsAreEqual(lastSetMembers, newSetMembers)) { await this.updateBubbleSet(group, newSetMembers); @@ -235,15 +229,10 @@ class GraphBubbleSetManager { } async updateBubbleSet(group, members) { - // Ensure dummy node is never included in members - const filteredMembers = members instanceof Set - ? new Set([...members].filter(id => id !== this.cache.CFG.INVISIBLE_DUMMY_NODE.id)) - : [...members].filter(id => id !== this.cache.CFG.INVISIBLE_DUMMY_NODE.id); - - let empty = !filteredMembers || (filteredMembers instanceof Set ? filteredMembers.size === 0 : filteredMembers.length === 0); - const membersAsArray = filteredMembers instanceof Set ? [...filteredMembers] : filteredMembers; + let empty = !members || (members instanceof Set ? members.size === 0 : members.length === 0); + const membersAsArray = members instanceof Set ? [...members] : members; - const avoidMembers = empty ? [] : this.getAvoidMembers(filteredMembers); + const avoidMembers = empty ? [] : this.getAvoidMembers(members); if (StaticUtilities.arraysAreEqual(membersAsArray, [...this.cache.INSTANCES.BUBBLE_GROUPS[group].members.keys()])) { this.cache.ui.debug("BUBBLE GROUPS IN SYNC - SKIPPING UPDATE"); @@ -264,7 +253,12 @@ class GraphBubbleSetManager { } getAvoidMembers(members) { - if (this.cache.CFG.APPLY_BUBBLE_SET_HOTFIX && this.cache.CFG.AVOID_MEMBERS_IN_BUBBLE_GROUPS) return []; + // Flag is set by io.preProcessData when the network exceeds + // MAX_NODES_BEFORE_DISABLING_AVOID_MEMBERS_IN_BUBBLE_GROUPS: outlines + // then may span across non-members (bubblesets-js virtual-edge routing + // around obstacles is O(members × avoid) — see the threshold comment in + // config.js for the measured budget). + if (this.cache.CFG.AVOID_MEMBERS_IN_BUBBLE_GROUPS) return []; const checkMembership = members instanceof Set ? (nodeID) => members.has(nodeID) @@ -291,10 +285,7 @@ class GraphBubbleSetManager { } const manualMembers = this.cache.data.layouts[this.cache.data.selectedLayout][`${group}ManualMembers`]; - // Filter out dummy node from selected nodes - const selectedNodeIds = [...this.cache.selectedNodes].filter(nodeId => - nodeId !== this.cache.CFG.INVISIBLE_DUMMY_NODE.id - ); + const selectedNodeIds = [...this.cache.selectedNodes]; if (selectedNodeIds.length === 0) { this.cache.ui.warning("No nodes selected"); @@ -332,6 +323,217 @@ class GraphBubbleSetManager { await this.redrawBubbleSets(); } + /** + * Enumerate numeric edge properties available as Louvain edge weights. + * Source of truth is cache.data.filterDefaults (the same registry the + * filter UI uses): edge section, not categorical, finite min/max. + * @returns {Array<{propHash: string, prop: string, label: string}>} + */ + getNumericEdgeProperties() { + const props = []; + const filterDefaults = this.cache.data?.filterDefaults; + if (!filterDefaults) return props; + for (const [propHash, def] of filterDefaults) { + const [section, subSection, prop] = StaticUtilities.decodePropHashId(propHash); + if (section !== this.cache.CFG.EXCEL_EDGE_HEADER) continue; + if (def.isCategory) continue; + if (!Number.isFinite(def.lowerThreshold) || !Number.isFinite(def.upperThreshold)) continue; + props.push({ propHash, prop, label: subSection ? `${subSection} › ${prop}` : prop }); + } + return props; + } + + // Default weight: STRING's "Combined Score" when present, else topology-only + // (null) so generic graphs keep the original unweighted behaviour. + #defaultWeightProperty(numericProps) { + const combined = numericProps.find((p) => /combined\s*score/i.test(p.prop)); + return combined ? combined.propHash : null; + } + + async detectCommunities(options = {}) { + const weightProperty = options.weightProperty !== undefined + ? options.weightProperty + : (this.communityOptions.weightProperty ?? null); + const resolution = options.resolution ?? this.communityOptions.resolution ?? 1; + + const groups = [...this.traverseBubbleSets()]; + const result = computeCommunityAssignments(this.cache, groups, { weightProperty, resolution }); + + if (!result) { + this.cache.ui.warning("Community detection needs at least one visible edge"); + return; + } + + // Auto-grouping overwrites every group's manual members. If the user has + // built manual groupings, confirm before discarding them (detection is + // already computed, so the graph is untouched if they cancel). + const currentLayout = this.cache.data.layouts[this.cache.data.selectedLayout]; + const hasManualGroups = groups.some( + (g) => (currentLayout[`${g}ManualMembers`]?.size ?? 0) > 0 + ); + if (hasManualGroups) { + const confirmed = await Popup.confirm( + "Auto-grouping replaces your existing manual bubble groups with the " + + "detected communities. Clear them and continue?" + ); + if (!confirmed) return; + } + + // Replace the manual members of all groups for the current layout with + // the detected communities (largest community → first group). + for (const group of groups) { + currentLayout[`${group}ManualMembers`] = result.assignments.get(group) ?? new Set(); + } + + // Same post-change choreography as toggleSelectedNodesInManualGroup + this.updateManualGroupButtonState(); + this.updateManualGroupStatus(); + this.refreshBubbleStyleElements(); + + this.cache.bubbleSetChanged = true; + await this.updateBubbleSetIfChanged(); + await this.cache.graph.draw(); + await this.redrawBubbleSets(); + + const assignedText = result.communityCount <= groups.length + ? `all ${result.communityCount}` + : `largest ${groups.length}`; + const weightLabel = weightProperty + ? (this.getNumericEdgeProperties().find((p) => p.propHash === weightProperty)?.label ?? "edge weight") + : "topology"; + this.cache.ui.info( + `Detected ${result.communityCount} communities ` + + `(weight: ${weightLabel}, resolution ${resolution}, modularity ${result.modularity.toFixed(2)}); ` + + `assigned ${assignedText} to bubble groups` + ); + } + + /** + * Toggle the Louvain configurator anchored to the 🧩 button: pick a numeric + * edge property to weight by (or topology-only) and the resolution, then run + * detection. Built lazily and repopulated on each open so it reflects the + * currently loaded data. + */ + toggleCommunityDetectionPopover() { + if (this.communityPopover && this.communityPopover.classList.contains("open")) { + this.#closeCommunityDetectionPopover(); + return; + } + this.#openCommunityDetectionPopover(); + } + + #closeCommunityDetectionPopover() { + this.communityPopover?.classList.remove("open"); + if (this._communityOutsideHandler) { + document.removeEventListener("pointerdown", this._communityOutsideHandler, true); + this._communityOutsideHandler = null; + } + } + + #openCommunityDetectionPopover() { + const anchor = document.getElementById("detectCommunitiesBtn"); + if (!anchor) return; + + const numericProps = this.getNumericEdgeProperties(); + // Resolve the default weight on first open, and re-default whenever the + // stored property is gone (data was reloaded) so the dropdown selection + // and the stored option never drift out of sync. + const stored = this.communityOptions.weightProperty; + const storedExists = stored === null || numericProps.some((p) => p.propHash === stored); + if (stored === undefined || !storedExists) { + this.communityOptions.weightProperty = this.#defaultWeightProperty(numericProps); + } + + const popover = this.#ensureCommunityDetectionPopover(); + this.#populateCommunityDetectionPopover(numericProps); + + // Open first so offsetWidth is measurable, then anchor below the button + // and clamp to the viewport so the right edge never truncates. + popover.classList.add("open"); + const rect = anchor.getBoundingClientRect(); + popover.style.top = `${rect.bottom + 6}px`; + popover.style.left = `${clampPopoverLeft(rect.left, popover.offsetWidth, window.innerWidth)}px`; + + // Close on outside click (capture so it beats inner handlers). + this._communityOutsideHandler = (e) => { + if (!popover.contains(e.target) && e.target !== anchor) this.#closeCommunityDetectionPopover(); + }; + document.addEventListener("pointerdown", this._communityOutsideHandler, true); + } + + #ensureCommunityDetectionPopover() { + if (this.communityPopover) return this.communityPopover; + const popover = document.createElement("div"); + popover.className = "community-detection-popover"; + popover.id = "communityDetectionPopover"; + document.body.appendChild(popover); + this.communityPopover = popover; + return popover; + } + + #populateCommunityDetectionPopover(numericProps) { + const popover = this.communityPopover; + popover.replaceChildren(); + + const title = document.createElement("div"); + title.className = "community-popover-title"; + title.textContent = "Detect communities (Louvain)"; + popover.appendChild(title); + + // Weight dropdown ------------------------------------------------------ + const weightLabel = document.createElement("label"); + weightLabel.className = "community-popover-row"; + weightLabel.textContent = "Weight by"; + const weightSelect = document.createElement("select"); + weightSelect.className = "community-popover-select"; + const topoOpt = document.createElement("option"); + topoOpt.value = ""; + topoOpt.textContent = "Unweighted (topology)"; + weightSelect.appendChild(topoOpt); + for (const p of numericProps) { + const opt = document.createElement("option"); + opt.value = p.propHash; + opt.textContent = p.label; + weightSelect.appendChild(opt); + } + weightSelect.value = this.communityOptions.weightProperty ?? ""; + weightSelect.addEventListener("change", (e) => { + this.communityOptions.weightProperty = e.target.value || null; + }); + weightLabel.appendChild(weightSelect); + popover.appendChild(weightLabel); + + // Resolution slider ---------------------------------------------------- + const resRow = document.createElement("label"); + resRow.className = "community-popover-row"; + const resText = document.createElement("span"); + const setResText = (v) => { resText.textContent = `Resolution: ${Number(v).toFixed(2)}`; }; + setResText(this.communityOptions.resolution); + const resSlider = document.createElement("input"); + resSlider.type = "range"; + resSlider.min = "0.25"; + resSlider.max = "4"; + resSlider.step = "0.05"; + resSlider.value = String(this.communityOptions.resolution); + resSlider.className = "community-popover-slider"; + resSlider.addEventListener("input", (e) => { + this.communityOptions.resolution = parseFloat(e.target.value); + setResText(e.target.value); + }); + resRow.append(resText, resSlider); + popover.appendChild(resRow); + + // Detect button -------------------------------------------------------- + const detectBtn = document.createElement("button"); + detectBtn.className = "community-popover-detect nw-button"; + detectBtn.textContent = "Detect"; + detectBtn.addEventListener("click", async () => { + this.#closeCommunityDetectionPopover(); + await this.detectCommunities(); + }); + popover.appendChild(detectBtn); + } + updateManualGroupButtonState() { const button = document.getElementById('manualBubbleGroupButton'); if (!button) return; @@ -364,47 +566,96 @@ class GraphBubbleSetManager { const activeGroups = []; - for (let [group, quadrantPosition] of Object.entries(this.cache.DEFAULTS.BUBBLE_GROUP_QUADRANT_POSITIONS)) { - const manualMembers = this.cache.data.layouts[this.cache.data.selectedLayout][`${group}ManualMembers`] || new Set(); - - // Filter out nodes that are no longer visible (filtered out) and explicitly exclude dummy node - const visibleMembers = [...manualMembers].filter(nodeId => - nodeId !== this.cache.CFG.INVISIBLE_DUMMY_NODE.id && - this.cache.nodeRef.has(nodeId) && - this.cache.propIDsToNodeIDsToBeShown.size === 0 || - [...this.cache.propIDsToNodeIDsToBeShown.values()].some(set => set.has(nodeId)) - ); + for (let [group] of Object.entries(this.cache.DEFAULTS.BUBBLE_GROUP_QUADRANT_POSITIONS)) { + // Count exactly what the outline renders (prop ∪ manual, one filter). + const visibleCount = this.getEffectiveGroupMembers(group).size; - if (visibleMembers.length > 0) { + if (visibleCount > 0) { const color = this.cache.data.layouts[this.cache.data.selectedLayout].bubbleSetStyle[group].fill; - activeGroups.push(`●${visibleMembers.length}`); + activeGroups.push(this.buildManualGroupBadge(group, visibleCount, color)); } } // Show/hide elements based on active groups if (activeGroups.length > 0) { - statusSpan.innerHTML = activeGroups.join(' '); - statusSpan.style.display = 'inline'; - if (clearButton) clearButton.style.display = 'inline'; + statusSpan.replaceChildren(...activeGroups); + statusSpan.style.display = 'inline-flex'; + if (clearButton) clearButton.style.display = 'inline-flex'; if (separator) separator.style.display = 'inline-block'; + // A group now exists worth styling — surface the Bubble Sets card. + this.cache.ui?.expandStylingCard?.('Bubble Sets'); } else { - statusSpan.innerHTML = ''; + statusSpan.replaceChildren(); statusSpan.style.display = 'none'; if (clearButton) clearButton.style.display = 'none'; if (separator) separator.style.display = 'none'; } } + // One clickable badge per active group: shows the colored ●count and clears + // just that group on click (✕ revealed on hover). Lets users drop a single + // group without nuking all of them via "Clear all". + buildManualGroupBadge(group, count, color) { + const badge = document.createElement('button'); + badge.type = 'button'; + badge.className = 'manual-group-badge'; + badge.style.color = color; + badge.title = `Clear this group (${count} node${count === 1 ? '' : 's'})`; + const dot = document.createElement('span'); + dot.textContent = `●${count}`; + const x = document.createElement('span'); + x.className = 'mg-badge-x'; + x.textContent = '✕'; + badge.append(dot, x); + badge.addEventListener('click', () => this.clearManualGroup(group)); + return badge; + } + + /** + * Remove all filter/property-based assignments for a group from the current + * layout, mirroring the change into each prop's per-filter member set so the + * filter-panel quadrant buttons render inactive on the next build. + * @param {string} group + * @returns {boolean} true if any prop assignment was actually cleared + */ + clearGroupPropAssignments(group) { + const currentLayout = this.cache.data.layouts[this.cache.data.selectedLayout]; + const propsInGroup = currentLayout[`${group}Props`]; + if (!propsInGroup || propsInGroup.size === 0) return false; + + for (const propID of propsInGroup) { + const filter = currentLayout.filters?.get(propID); + const groupMembers = filter?.[`${group}Members`]; + if (groupMembers) groupMembers.delete(propID); + } + propsInGroup.clear(); + return true; + } + + async clearManualGroup(group) { + const manualMembers = this.cache.data.layouts[this.cache.data.selectedLayout][`${group}ManualMembers`]; + if (manualMembers) manualMembers.clear(); + // The badge spans both sources, so clearing the group clears both. + const propsCleared = this.clearGroupPropAssignments(group); + + this.updateManualGroupButtonState(); + this.updateManualGroupStatus(); + if (propsCleared) this.cache.ui?.buildFilterUI?.(); + + this.cache.bubbleSetChanged = true; + await this.updateBubbleSetIfChanged(); + await this.cache.graph.draw(); + } + cleanupManualGroupMembers() { - // Remove nodes from manual groups that are no longer visible (filtered out) or are the dummy node + // Remove nodes from manual groups that are no longer visible (filtered out) for (let group of Object.keys(this.cache.DEFAULTS.BUBBLE_GROUP_STYLE)) { const manualMembers = this.cache.data.layouts[this.cache.data.selectedLayout][`${group}ManualMembers`]; if (manualMembers && manualMembers.size > 0) { const toRemove = []; for (let nodeId of manualMembers) { - // Check if node is filtered out (not visible) or is the dummy node - if (nodeId === this.cache.CFG.INVISIBLE_DUMMY_NODE.id || !this.cache.nodeRef.has(nodeId)) { + if (!this.cache.nodeRef.has(nodeId)) { toRemove.push(nodeId); } } @@ -417,17 +668,20 @@ class GraphBubbleSetManager { } async clearAllManualGroups() { - // Clear all manual bubble groups + // Clear every group's contribution from both sources (manual + props). + let propsCleared = false; for (let group of Object.keys(this.cache.DEFAULTS.BUBBLE_GROUP_STYLE)) { const manualMembers = this.cache.data.layouts[this.cache.data.selectedLayout][`${group}ManualMembers`]; if (manualMembers) { manualMembers.clear(); } + if (this.clearGroupPropAssignments(group)) propsCleared = true; } // Update UI this.updateManualGroupButtonState(); this.updateManualGroupStatus(); + if (propsCleared) this.cache.ui?.buildFilterUI?.(); // Mark bubble sets as changed and redraw (don't re-layout) this.cache.bubbleSetChanged = true; @@ -437,7 +691,7 @@ class GraphBubbleSetManager { // Force bubble set redraw to fix positioning await this.redrawBubbleSets(); - this.cache.ui.info('Cleared all manual bubble groups'); + this.cache.ui.info('Cleared all bubble groups'); } } diff --git a/src/graph/communities.js b/src/graph/communities.js new file mode 100644 index 0000000..c86bc3b --- /dev/null +++ b/src/graph/communities.js @@ -0,0 +1,71 @@ +// Node-safe (no DOM): Louvain community detection over the visible subgraph. +// The pure algorithm lives here so it can be unit-tested; the DOM-bound +// application path (manual bubble-group members) lives in bubble_sets.js. +import {louvain} from "../lib/graphology.bundle.mjs"; +import {buildVisibleGraph} from "./visible_graph.js"; + +// Fixed seed: Louvain is non-deterministic by default (random node visit +// order), so a seeded PRNG keeps results reproducible and testable. +const LOUVAIN_RNG_SEED = 42; + +/** Mulberry32 — tiny seeded PRNG returning floats in [0, 1). */ +function mulberry32(seed) { + let state = seed >>> 0; + return function () { + state = (state + 0x6D2B79F5) >>> 0; + let t = state; + t = Math.imul(t ^ (t >>> 15), t | 1); + t ^= t + Math.imul(t ^ (t >>> 7), t | 61); + return ((t ^ (t >>> 14)) >>> 0) / 4294967296; + }; +} + +/** + * Runs Louvain community detection on the visible subgraph and maps the + * largest communities onto the given bubble groups (largest community → + * first group). Communities beyond the available groups stay unassigned. + * + * @param {{nodeIDsToBeShown: Set, edgeIDsToBeShown: Set, edgeRef: Map}} cache + * @param {string[]} groups bubble-group keys in assignment order + * @param {{weightProperty?: string|null, resolution?: number}} [options] + * weightProperty: numeric edge property hash to weight edges by (null = + * topology only, the default). resolution: Louvain resolution γ (>1 yields + * more, smaller communities; <1 fewer, larger; default 1). + * @returns {{assignments: Map>, communityCount: number, modularity: number} | null} + * null when the visible graph has no edges (Louvain needs at least one). + */ +function detectCommunities(cache, groups, options = {}) { + const weightProperty = options.weightProperty ?? null; + const resolution = options.resolution ?? 1; + + const graph = buildVisibleGraph(cache, {weightProperty}); + if (graph.size === 0) return null; + + const result = louvain.detailed(graph, { + rng: mulberry32(LOUVAIN_RNG_SEED), + // String attribute name when weighting (buildVisibleGraph sets `weight`); + // null keeps every edge at weight 1 (topology-only, the original behaviour). + getEdgeWeight: weightProperty !== null ? "weight" : null, + resolution, + }); + + // Group node ids by community index, preserving the community index for a + // deterministic tie-break when sizes are equal. + const byCommunity = new Map(); + for (const [node, community] of Object.entries(result.communities)) { + if (!byCommunity.has(community)) byCommunity.set(community, new Set()); + byCommunity.get(community).add(node); + } + + const ordered = [...byCommunity.entries()] + .sort((a, b) => (b[1].size - a[1].size) || (a[0] - b[0])) + .map(([, members]) => members); + + const assignments = new Map( + groups.map((group, i) => [group, ordered[i] ?? new Set()]) + ); + + return {assignments, communityCount: result.count, modularity: result.modularity}; +} + +export {detectCommunities, LOUVAIN_RNG_SEED}; diff --git a/src/graph/core.js b/src/graph/core.js index a71c26e..957eecd 100644 --- a/src/graph/core.js +++ b/src/graph/core.js @@ -1,94 +1,37 @@ -const { - Graph, - NodeEvent, - EdgeEvent, - GraphEvent, - CanvasEvent, - CommonEvent, - WindowEvent, - Layout, - BaseLayout, - ExtensionCategory, - register, -} = G6; - import { StaticUtilities } from "../utilities/static.js"; import { replaceColorScale } from "../utilities/color_scale_picker.js"; import { replaceNumericScale } from "../utilities/numeric_scale_picker.js"; +import { initTheme, nodeLabelColorForTheme } from "../utilities/theme.js"; +import { + buildGraphologyGraph, + makeNodeReducer, + makeEdgeReducer, +} from "./graph_model.js"; +// NOTE: sigma_adapter.js is imported lazily in createGraphInstance(), never +// statically: the sigma vendor bundle probes WebGL at module scope +// (@sigma/node-image reads MAX_TEXTURE_SIZE from a throwaway context), so a +// static import kills the whole app boot when WebGL is unavailable — before +// the isWebGL2Available() check below could ever run. +import { + isWebGL2Available, + renderWebGLUnavailableMessage, + WEBGL2_ERROR_MESSAGE, +} from "./webgl_support.js"; + +// One-time listener registration guards. These must live at module scope: +// the Cache singleton is reset *in place* on every file load (Cache.reset()), +// which would re-arm EVENT_LOCKS-based guards and stack duplicate document/ +// window listeners (even counts turn toggle hotkeys into no-ops). The handlers +// resolve managers through `this.cache.*`, which always points at the live, +// in-place-reset Cache instance. +let hotkeysRegistered = false; +let globalEventsRegistered = false; class GraphCoreManager { constructor(cache) { this.cache = cache; - this.BEHAVIOURS = { - DRAG_ELEMENT: { - type: "drag-element", - cursor: { default: "default", grab: "default", grabbing: "default" }, - shadow: true, - shadowFill: "#C33D35", - shadowFillOpacity: 0.5, - shadowStroke: "#C33D35", - shadowStrokeOpacity: 1.0, - }, - DRAG_CANVAS: { - type: "drag-canvas", - key: "drag-canvas", - animation: false, - }, - ZOOM_CANVAS: { - type: "zoom-canvas", - key: "zoom-canvas", - animation: false, - }, - HOVER_ACTIVATE: { - type: "hover-activate", - enable: (event) => { - return event.targetType === "node" || event.targetType === "edge"; - }, - degree: 1, - state: "highlight", - inactiveState: "dim", - }, - LASSO_SELECT: { - type: "lasso-select", - key: "lasso-select", - trigger: ["drag"], - style: { - fill: "#C33D35", - fillOpacity: 0.3, - stroke: "#C33D35", - }, - enable: (event) => { - this.cache.ui.debug("LASSO CANVAS CLICK"); - - if (!this.cache.CFG.APPLY_BUBBLE_SET_HOTFIX) return true; - - const selected = this.cache.graph - .getNodeData() - .filter((n) => n.states?.includes("selected")); - - if (selected.length !== 0) { - this.cache.ui.debug( - "PREVENTING LASSO DESELECT EVENT BY REMOVING CANVAS CLICK EVENT", - ); - const eventHandler = this.cache.graph.getEvents()["canvas:click"]; - this.cache.graph.off("canvas:click"); - setTimeout(() => { - this.cache.ui.debug("RESTORING CANVAS CLICK EVENT"); - this.cache.graph.on("canvas:click", eventHandler); - }, 1000); - - return false; - } - return true; - }, - }, - CLICK_SELECT: { - type: "click-select", - key: "click-select", - multiple: true, - trigger: ["shift"], - }, - }; + // In-flight createGraphInstance() memo — see the re-entrancy note there. + this.graphInitPromise = null; } *traverseD4Data(nodeOrEdge) { @@ -126,17 +69,17 @@ class GraphCoreManager { this.cache.layoutChanged || forceRender ) { - // NOTE: only `styleChanged` re-syncs cached-ref mutations to G6 here. - // `layoutChanged` does NOT trigger updateData — callers that flip it - // while mutating node.style.x/y on cache.nodeRef refs must push their - // own updateNodeData payload, or the change won't reach G6 until the - // next selection-state change. See layoutSelectedNodes in layout.js. + // NOTE: only `styleChanged` re-syncs cached-ref mutations to the + // renderer here. `layoutChanged` does NOT trigger updateData — callers + // that flip it while mutating node.style.x/y on cache.nodeRef refs must + // push their own updateNodeData payload. See layoutSelectedNodes. if (this.cache.styleChanged) { await this.cache.ui.showLoading("Loading", "Updating graph .."); await new Promise((resolve) => requestAnimationFrame(resolve)); - await this.cache.graph.updateData( - this.createSimplifiedDataForGraphObject(), - ); + await this.cache.graph.updateData({ + nodes: [...this.cache.nodeRef.values()], + edges: [...this.cache.edgeRef.values()], + }); this.cache.styleChanged = false; this.cache.labelStyleChanged = false; } @@ -148,12 +91,6 @@ class GraphCoreManager { await new Promise((resolve) => requestAnimationFrame(resolve)); return await this.cache.graph.draw(); } - - // TODO: might have to move this - if (this.cache.EVENT_LOCKS.QUERY_SELECTION_EVENT) { - this.cache.qm.storeQuery(); - this.cache.EVENT_LOCKS.QUERY_SELECTION_EVENT = false; - } } catch (errorMsg) { this.cache.ui.error(errorMsg); return false; @@ -164,219 +101,104 @@ class GraphCoreManager { } async createGraphInstance() { - if (this.cache.graph === null) { - const behaviors = [ - this.BEHAVIOURS.DRAG_CANVAS, - this.BEHAVIOURS.ZOOM_CANVAS, - this.BEHAVIOURS.DRAG_ELEMENT, - ]; - - if (!this.cache.CFG.DISABLE_HOVER_EFFECT) { - behaviors.push(this.BEHAVIOURS.HOVER_ACTIVATE); - } - - const plugins = [ - { - key: "tooltip", - type: "tooltip", - trigger: "click", - enterable: true, - getContent: (e, items) => { - const content = this.cache.toolTips.get(items[0].id); - requestAnimationFrame(() => { - const graphContainer = document.getElementById( - "innerGraphContainer", - ); - if (!graphContainer) return; - const tooltip = graphContainer.querySelector(".tooltip"); - if (!tooltip) return; - const body = tooltip.querySelector(".tooltip-content"); - const btn = tooltip.querySelector(".tooltip-expand-btn"); - if (!body || !btn) return; - tooltip.classList.remove("expanded"); - btn.textContent = "⛶"; - const isClipped = - body.scrollHeight > body.clientHeight + 1 || - body.scrollWidth > body.clientWidth + 1; - btn.style.display = isClipped ? "" : "none"; - }); - return content; - }, - }, - { - key: "minimap", - type: "minimap", - position: "bottom-left", - }, - ...[...this.cache.bs.traverseBubbleSets()].map((group) => ({ - key: `bubbleSetPlugin-${group}`, - type: "bubble-sets", - members: [], - avoidMembers: [this.cache.CFG.INVISIBLE_DUMMY_NODE.id], - // avoidMembers: [...this.cache.nodeRef.keys()], - ...this.cache.data.layouts[this.cache.data.selectedLayout] - .bubbleSetStyle[group], - strokeOpacity: 0, // hide bubble groups initially (1 node persists due to bug) - fillOpacity: 0, - label: false, - })), - ]; - - this.cache.graph = new Graph({ - container: "innerGraphContainer", - autoFit: false /* 'view' */, - animation: false, - autoResize: true, - padding: 10, - data: this.createSimplifiedDataForGraphObject(), - // NOTE: Do NOT add `type` or `style` here. In G6 v5, spec-level - // node/edge options override per-node data styles (Object.assign - // order in getComputedStyle: ...dataStyle, ...specDefault...). - // All per-node type/style is provided via createSimplifiedDataForGraphObject(). - node: { - state: { - selected: { - halo: true, - haloStroke: "#C33D35", - haloLineWidth: 12, - }, - highlight: { fill: "#C33D35", halo: true, lineWidth: 0 }, - dim: { fill: "#E4E3EA" }, - }, - }, - edge: { - state: { - highlight: { stroke: "#C33D35" }, - selected: { halo: true, haloStroke: "#C33D35", haloLineWidth: 6 }, - }, - }, - behaviors: behaviors, - plugins: plugins, - }); - - this.cache.graph.on("node:dragend", async (event) => { - /** - * Persist all positions on every drag event - * and reset zIndex elevated by G6's frontElement during drag - */ - if (this.cache.EVENT_LOCKS.DRAG_END_RUNNING) return; - - this.cache.ui.debug("DRAG END"); - this.cache.EVENT_LOCKS.DRAG_END_RUNNING = true; - await this.cache.lm.persistNodePositions(); - - const draggedId = event?.target?.id; - if (draggedId) { - await this.cache.graph.setElementZIndex(draggedId, 0); - } - - this.cache.EVENT_LOCKS.DRAG_END_RUNNING = false; - }); - - this.cache.graph.on("beforelayout", async () => { - this.cache.ui.debug("BEFORE LAYOUT"); - }); - - this.cache.graph.on("afterlayout", async () => { - /** - * Applies persisted positions (excel data or after moving nodes) after layouting has finished - * Also persists positions if this was the initial layout computation - */ - if (this.cache.EVENT_LOCKS.AFTER_LAYOUT_RUNNING) return; - - this.cache.ui.debug("AFTER LAYOUT"); - this.cache.EVENT_LOCKS.AFTER_LAYOUT_RUNNING = true; - - const layout = this.cache.data.layouts[this.cache.data.selectedLayout]; - - if (layout.positions.size > 0) { - // Apply stored positions - this.cache.graph.updateNodeData( - Array.from(layout.positions, ([id, pos]) => ({ - id, - style: pos.style, - })), - ); - await this.cache.graph.draw(); - } else if (layout.layoutType) { - // Initial layout - persist the computed positions and clean up layoutType - await this.cache.lm.persistNodePositions(); - delete layout.layoutType; - this.cache.ui.debug("Initial layout positions persisted"); - } - - this.cache.EVENT_LOCKS.AFTER_LAYOUT_RUNNING = false; - }); - - this.cache.graph.on("canvas:click", async (event) => { - this.cache.ui.debug("CANVAS CLICK"); - }); + if (this.cache.graph !== null) return; - // this.cache.graph.off("canvas:click"); + // The init body awaits (dynamic import, layout passes), so two rapid + // calls would both pass the null check above and construct two + // SigmaAdapters — the first one orphaned, leaking a WebGL context. + // Memoize the in-flight init; cleared in finally so a failed init + // (cache.graph stays null) can be retried by the next load. + if (this.graphInitPromise) return this.graphInitPromise; - this.cache.graph.on("node:click", async (event) => { - this.cache.ui.debug("NODE CLICK"); - }); - - this.cache.graph.on("edge:click", async (event) => { - this.cache.ui.debug("EDGE CLICK"); - }); - - this.cache.graph.on(GraphEvent.BEFORE_DRAW, async (event) => { - if (this.cache.EVENT_LOCKS.BEFORE_DRAW_RUNNING) return; - - this.cache.EVENT_LOCKS.BEFORE_DRAW_RUNNING = true; - this.cache.ui.debug("BEFORE DRAW"); - if (this.cache.EVENT_LOCKS.IS_DESELECTING) { - this.cache.ui.debug("BEFORE DRAW DESELECTION EVENT"); - this.cache.EVENT_LOCKS.IS_DESELECTING = false; - } - this.cache.EVENT_LOCKS.BEFORE_DRAW_RUNNING = false; - }); + this.graphInitPromise = this.#initGraphInstance(); + try { + return await this.graphInitPromise; + } finally { + this.graphInitPromise = null; + } + } - this.cache.graph.on(GraphEvent.AFTER_DRAW, async (event) => { - if (this.cache.EVENT_LOCKS.AFTER_DRAW_RUNNING) return; + async #initGraphInstance() { + // Sigma v3 dies with an opaque TypeError when no WebGL context can be + // created (GPU blocklist, remote desktop, disabled flags). Probe first + // and leave cache.graph null — the same state as "no data loaded", so + // the rest of the app chrome keeps working; load paths already guard + // on a null graph after this call. + const containerEl = document.getElementById("innerGraphContainer"); + if (!isWebGL2Available()) { + renderWebGLUnavailableMessage(containerEl); + this.cache.ui.error(WEBGL2_ERROR_MESSAGE); + return; + } - this.cache.EVENT_LOCKS.AFTER_DRAW_RUNNING = true; - this.cache.ui.debug("AFTER DRAW"); - await this.cache.sm.updateSelectedNodesAndEdges(); - await this.cache.bs.redrawBubbleSets(); + // Rebuild the graphology model from the current refs/positions; it is + // the single data source the sigma renderer reads from. + this.cache.graphData = buildGraphologyGraph(this.cache); - this.cache.EVENT_LOCKS.AFTER_DRAW_RUNNING = false; - await this.cache.ui.hideLoading(); + const elementStates = new Map(); + // Hover layer (InteractionManager writes, reducers read) is separate + // from elementStates so hover can never corrupt selection state. + const hoverIds = new Set(); + try { + const { SigmaAdapter } = await import("./sigma_adapter.js"); + // initTheme (not currentTheme): re-resolves stored/OS preference so a + // graph constructed before the DOMContentLoaded theme boot still gets + // the right label colors. Idempotent after boot. + const theme = initTheme(document, window); + this.cache.graph = new SigmaAdapter(this.cache, "innerGraphContainer", { + nodeReducer: makeNodeReducer(this.cache, elementStates, hoverIds), + edgeReducer: makeEdgeReducer(this.cache, elementStates, hoverIds), + elementStates, + hoverIds, + // Label visibility (CFG.HIDE_LABELS) is synced live by the adapter + // on construction and on every render(). The labelColor fallback is + // theme-driven (ui.toggleDarkMode flips it live via setSetting). + settings: { + labelColor: { color: nodeLabelColorForTheme(theme) }, + // Same for edge labels: label_renderers falls back here whenever + // the per-edge labelColor is the baked #000000 default (in light + // mode this resolves to #000 — identical to the old baked render). + edgeLabelColor: { color: nodeLabelColorForTheme(theme) }, + }, }); + } catch (err) { + // The probe can pass while sigma's own context creation still fails + // (e.g. context-count limits). Same dead-renderer handling. + this.cache.graph = null; + renderWebGLUnavailableMessage(containerEl); + this.cache.ui.error(`Graph renderer failed to initialize: ${err.message}`); + return; + } - this.cache.graph.on(GraphEvent.AFTER_RENDER, async () => { - this.cache.ui.debug("AFTER RENDER"); - - if (this.cache.EVENT_LOCKS.ONCE_AFTER_RENDER_COMPLETED) { - if (this.cache.EVENT_LOCKS.AFTER_RENDER_RUNNING) return; - - this.cache.EVENT_LOCKS.AFTER_RENDER_RUNNING = true; - - await this.cache.sm.updateSelectedNodesAndEdges(); - await this.cache.bs.redrawBubbleSets(); + const layout = this.cache.data.layouts[this.cache.data.selectedLayout]; + + // Re-apply per-layout node/edge styles on every graph rebuild (data-editor + // apply, JSON load). buildGraphologyGraph does not merge layout.nodeStyles/ + // edgeStyles, and the only other applyLayoutStyles caller is changeLayout(). + // Runs before the layout algorithm below so freshly computed positions are + // never clobbered by the style reset. Skipped when the layout carries no + // custom styles: refs are already originalStyle right after a rebuild, and + // the full reset pass clones every element (~700 ms at 15k elements). + if (layout.nodeStyles?.size || layout.edgeStyles?.size) { + await this.cache.lm.applyLayoutStyles(layout); + } - this.cache.EVENT_LOCKS.AFTER_RENDER_RUNNING = false; - await this.cache.ui.hideLoading(); - } else { - await this.initialAfterRenderEvent(); - } + // If layout has no positions yet but has a layoutType, apply that layout algorithm once + if (layout.positions.size === 0 && layout.layoutType) { + const internals = + this.cache.DEFAULTS.LAYOUT_INTERNALS[layout.layoutType] || {}; + await this.cache.graph.setLayout({ + type: layout.layoutType, + ...internals, }); - - let layout = this.cache.data.layouts[this.cache.data.selectedLayout]; - // If layout has no positions yet but has a layoutType, apply that layout algorithm once - if (layout.positions.size === 0 && layout.layoutType) { - const internals = - this.cache.DEFAULTS.LAYOUT_INTERNALS[layout.layoutType] || {}; - await this.cache.graph.setLayout({ - type: layout.layoutType, - ...internals, - }); - } } } + /** + * One-time post-first-render routine (hotkeys, global listeners, plugin + * stubs, initial filter pass, initial layout persistence). Called + * sequentially by SigmaAdapter.render() — formerly G6's AFTER_RENDER event. + */ async initialAfterRenderEvent() { if (this.cache.EVENT_LOCKS.ONCE_AFTER_RENDER_RUNNING) return; @@ -614,8 +436,8 @@ class GraphCoreManager { } // Centre and scale the viewport so the given set of nodes fills it with - // padding. Handles the G6 zoom/translate quirk where translateTo at - // non-1 zoom misbehaves (antvis/G6#6373). + // padding. Direct camera fit — the old G6 zoom-at-non-1 translate + // workaround (antvis/G6#6373) is gone with the sigma renderer. async fitViewToNodes(nodeIDs) { const ids = [...nodeIDs]; if (ids.length === 0) { @@ -643,37 +465,7 @@ class GraphCoreManager { return; } - // all measurements at zoom 1 to avoid G6 translateTo bug at non-1 zoom - // see: https://github.com/antvis/G6/issues/6373#issuecomment-3615152579 - await this.cache.graph.zoomTo(1); - - const canvasMin = this.cache.graph.getViewportByCanvas([minX, minY]); - const canvasMax = this.cache.graph.getViewportByCanvas([maxX, maxY]); - const bboxWidth = Math.abs(canvasMax[0] - canvasMin[0]) || 1; - const bboxHeight = Math.abs(canvasMax[1] - canvasMin[1]) || 1; - - const [viewportWidth, viewportHeight] = this.cache.graph.getSize(); - const padding = 80; - // Clamp zoom so a tiny selection (e.g. a single node) doesn't punch - // the viewport to 100× and turn a clean UX into a jarring jump. - const zoomRaw = Math.min( - (viewportWidth - padding * 2) / bboxWidth, - (viewportHeight - padding * 2) / bboxHeight, - ); - const zoom = Math.min(zoomRaw, 4); - - // translateTo at zoom 1, then restore target zoom (G6 bug workaround) - const viewportCenter = [viewportWidth / 2, viewportHeight / 2]; - const bboxCenter = this.cache.graph.getViewportByCanvas([ - (minX + maxX) / 2, - (minY + maxY) / 2, - ]); - const offset = [ - viewportCenter[0] - bboxCenter[0], - viewportCenter[1] - bboxCenter[1], - ]; - await this.cache.graph.translateBy(offset); - await this.cache.graph.zoomTo(zoom); + this.cache.graph.fitViewToBounds({ minX, minY, maxX, maxY }); } async updateEdges(overrides = {}, commands = []) { @@ -762,6 +554,15 @@ class GraphCoreManager { } } + let pieResult = null; + if (commands.includes("set_pie_chart")) { + pieResult = await this.cache.piePicker.pickPie(); + if (!pieResult) { + this.cache.ui.info("Aborted pie chart picker"); + return; + } + } + const badgesToAdd = overrides.style?.badges; const badgePaletteToAdd = overrides.style?.badgePalette; @@ -809,6 +610,11 @@ class GraphCoreManager { node.style.label = true; node.style.labelText = node.label; } + if (command === "clear_pie_chart") { + delete node.style.pieSlices; + delete node.style.pieMode; + delete node.style.pieProperties; + } } // apply overrides @@ -820,6 +626,15 @@ class GraphCoreManager { replaceNumericScale(overridesCopy, nodeID, numericScaleMap); } StaticUtilities.deepMerge(node, overridesCopy); + + // Pie chart: bake the per-node resolved slices (and the config, for + // re-edit/persistence) onto the style. Empty slices for a node means it + // carries none of the chosen values — it falls back to its shape. + if (pieResult) { + node.style.pieSlices = pieResult.sliceByNode.get(nodeID) ?? []; + node.style.pieMode = pieResult.mode; + node.style.pieProperties = pieResult.properties; + } this.cache.nodeRef.set(nodeID, node); // Save to current layout's style map (including type) @@ -857,169 +672,6 @@ class GraphCoreManager { ); } - createSimplifiedDataForGraphObject() { - const filterObject = (obj, excludedKeys) => { - return Object.keys(obj) - .filter((key) => !excludedKeys.includes(key)) // Exclude specified keys - .reduce((newObj, key) => { - newObj[key] = obj[key]; - return newObj; - }, {}); - }; - - // Get current graph nodes to preserve states - let graphNodesMap = new Map(); - if (this.cache.graph) { - try { - const graphNodes = this.cache.graph.getNodeData(); - for (const gNode of graphNodes) { - graphNodesMap.set(gNode.id, gNode); - } - } catch (e) { - // Graph might not be ready yet - } - } - - // Process nodes and exclude their unwanted properties - const filteredNodes = this.cache.data.nodes.map((node) => { - const filteredNode = filterObject(node, [ - "D4Data", - "features", - "featureValues", - "featureWithinThreshold", - "originalStyle", - "originalType", - ]); - - // Preserve states (like selection) from the current graph instance - const currentGraphNode = graphNodesMap.get(node.id); - if (currentGraphNode && currentGraphNode.states) { - filteredNode.states = currentGraphNode.states; - } - - // Preserve visibility from current graph state or loaded data - const savedVisibility = - currentGraphNode?.style?.visibility || node.style?.visibility; - - // load positions from the layouts position Map - const position = this.cache.data.layouts[ - this.cache.data.selectedLayout - ].positions.get(node.id); - - // Check if current layout has custom style for this node - const currentLayout = - this.cache.data.layouts[this.cache.data.selectedLayout]; - const layoutData = currentLayout.nodeStyles.get(node.id); - - if (layoutData) { - // Use layout-specific style and type - Object.assign( - filteredNode, - this.cache.style.getNodeStyleOrDefaults(node), - ); - // Override with layout-specific type and style - if (layoutData.type !== undefined) { - filteredNode.type = layoutData.type; - } - if (layoutData.style) { - filteredNode.style = structuredClone(layoutData.style); - } - } else { - // Use default style - Object.assign( - filteredNode, - this.cache.style.getNodeStyleOrDefaults(node), - ); - } - - // Restore visibility if it was set in the loaded data - if (savedVisibility) { - filteredNode.style.visibility = savedVisibility; - } - - if (position && position.style) { - filteredNode.style.x = position.style.x; - filteredNode.style.y = position.style.y; - } - - return filteredNode; - }); - - // Get current graph edges to preserve states - let graphEdgesMap = new Map(); - if (this.cache.graph) { - try { - const graphEdges = this.cache.graph.getEdgeData(); - for (const gEdge of graphEdges) { - graphEdgesMap.set(gEdge.id, gEdge); - } - } catch (e) { - // Graph might not be ready yet - } - } - - // Process edges if provided, and exclude unwanted properties - const filteredEdges = this.cache.data.edges.map((edge) => { - const filteredEdge = filterObject(edge, [ - "D4Data", - "features", - "featureValues", - "featureWithinThreshold", - "originalStyle", - "originalType", - ]); - - // Preserve states (like selection) from the current graph instance - const currentGraphEdge = graphEdgesMap.get(edge.id); - if (currentGraphEdge && currentGraphEdge.states) { - filteredEdge.states = currentGraphEdge.states; - } - - // Preserve visibility from current graph state or loaded data - const savedVisibility = - currentGraphEdge?.style?.visibility || edge.style?.visibility; - - // Check if current layout has custom style for this edge - const currentLayout = - this.cache.data.layouts[this.cache.data.selectedLayout]; - const layoutData = currentLayout.edgeStyles.get(edge.id); - - if (layoutData) { - // Use layout-specific style and type - Object.assign( - filteredEdge, - this.cache.style.getEdgeStyleOrDefaults(edge), - ); - // Override with layout-specific type and style - if (layoutData.type !== undefined) { - filteredEdge.type = layoutData.type; - } - if (layoutData.style) { - filteredEdge.style = structuredClone(layoutData.style); - } - } else { - // Use default style - Object.assign( - filteredEdge, - this.cache.style.getEdgeStyleOrDefaults(edge), - ); - } - - // Restore visibility if it was set in the loaded data - if (savedVisibility) { - filteredEdge.style.visibility = savedVisibility; - } - - return filteredEdge; - }); - - return { - nodes: [...filteredNodes, this.cache.CFG.INVISIBLE_DUMMY_NODE], - edges: filteredEdges, - combos: this.cache.data.combos || [], - }; - } - async preRenderEvent() { if (this.cache.styleChanged) return; @@ -1111,23 +763,23 @@ class GraphCoreManager { } resetEventLocks() { - this.cache.EVENT_LOCKS.BEFORE_DRAW_RUNNING = false; this.cache.EVENT_LOCKS.AFTER_DRAW_RUNNING = false; - this.cache.EVENT_LOCKS.DRAG_END_RUNNING = false; - this.cache.EVENT_LOCKS.BEFORE_RENDER_RUNNING = false; - this.cache.EVENT_LOCKS.AFTER_RENDER_RUNNING = false; - this.cache.EVENT_LOCKS.BEFORE_LAYOUT_RUNNING = false; - this.cache.EVENT_LOCKS.AFTER_LAYOUT_RUNNING = false; this.cache.EVENT_LOCKS.ONCE_AFTER_RENDER_RUNNING = false; this.cache.EVENT_LOCKS.ONCE_AFTER_RENDER_COMPLETED = false; - this.cache.EVENT_LOCKS.IS_DESELECTING = false; this.cache.EVENT_LOCKS.BUBBLE_GROUP_REDRAW_RUNNING = false; this.cache.EVENT_LOCKS.TRIGGER_SET_LAYOUT_ONCE = false; } async destroyGraphAndRollBackUI() { + // Anchored popovers hold document-level outside-click listeners and may + // reference the adapter being destroyed — close them with the graph. + this.cache.ui?.closeAnchoredPopovers?.(); await this.cache.graph?.destroy(); this.cache.graph = null; + // Drop renderer-cycle state with the instance: the graphology model is + // rebuilt by createGraphInstance, plugin stubs are re-registered there. + this.cache.graphData = null; + this.cache.INSTANCES.BUBBLE_GROUPS = {}; // isPositionsDirty = false; // syncPositionsDebounced.cancel?.(); @@ -1138,9 +790,14 @@ class GraphCoreManager { } registerHotkeyEvents() { - if (this.cache.EVENT_LOCKS.HOTKEY_EVENTS_REGISTERED) return; + if (hotkeysRegistered) return; document.addEventListener("keydown", async (event) => { + // Suppress hotkeys while a workspace/layout/render is loading. The overlay + // blocks pointer input but not keydown, so without this the user could + // fire export/toggle/fit actions against a graph that is still settling. + if (this.cache.ui.isBusy()) return; + const activeElement = document.activeElement; // Skip hotkeys if currently focused on an input, textarea, or select element @@ -1163,9 +820,6 @@ class GraphCoreManager { case "f": await this.fitViewToVisibleNodes(); break; - case "e": - await this.cache.ui.toggleEditMode(); - break; case "d": await this.cache.ui.toggleDataEditor(); break; @@ -1192,11 +846,13 @@ class GraphCoreManager { } }); - this.cache.EVENT_LOCKS.HOTKEY_EVENTS_REGISTERED = true; + hotkeysRegistered = true; } registerGlobalEventListeners() { - if (this.cache.EVENT_LOCKS.GLOBAL_EVENTS_REGISTERED) return; + // All targets (document, queryTextArea, innerGraphContainer, bottomBar) + // are static DOM that survives file loads — same stacking hazard as hotkeys. + if (globalEventsRegistered) return; [ "input", @@ -1226,7 +882,7 @@ class GraphCoreManager { this.cache.ui.makeBottomBarResizable(); this.registerTooltipWheelHandler(); this.registerTooltipExpandToggle(); - this.cache.EVENT_LOCKS.GLOBAL_EVENTS_REGISTERED = true; + globalEventsRegistered = true; } registerTooltipExpandToggle() { diff --git a/src/graph/edge_flow_glsl.js b/src/graph/edge_flow_glsl.js new file mode 100644 index 0000000..d63e10f --- /dev/null +++ b/src/graph/edge_flow_glsl.js @@ -0,0 +1,332 @@ +/** + * Pure GLSL string transforms forking the bundled @sigma/edge-curve shaders + * into the curved-edge flow overlay (node-safe: no sigma import — unit-tested + * against a verbatim bundle snapshot in tests/edge-flow-glsl.test.js). + * createCurveFlowProgram (edge_flow_programs.js) applies them to the parent + * curve program's shader sources at class-creation time. + * + * The parent fragment works in WINDOW PIXELS: v_cpA/v_cpB/v_cpC are the + * projected quadratic-bezier control points, compared against gl_FragCoord. + * Its getDistanceVector computes the bezier parameter t of the closest curve + * point and discards it — the fork exposes it (out param) and uses + * t × arc-length as the along-the-curve distance driving the same dash/pulse + * masks as the straight-edge flow program. + * + * Every patch is anchored on a small exact substring of the bundled source + * and THROWS when the anchor is missing — the drift guard for future sigma + * upgrades. buildProgramRegistry (sigma_adapter.js) try/catches the program + * creation and degrades to non-animated curves. + */ + +// --------------------------------------------------------------------------- +// Anchors (copied verbatim from src/lib/sigma.bundle.mjs, arrowHead: null). +// --------------------------------------------------------------------------- + +const FRAG_DISTANCE_FN_DECL = "vec2 getDistanceVector(vec2 b0, vec2 b1, vec2 b2) {"; +const FRAG_T_COMPUTATION = "float t = clamp((ap + bp) / (2.0 * a + b + d), 0.0, 1.0);"; +const FRAG_DIST_TO_CURVE_FN = `float distToQuadraticBezierCurve(vec2 p, vec2 b0, vec2 b1, vec2 b2) { + return length(getDistanceVector(b0 - p, b1 - p, b2 - p)); +}`; +const FRAG_VARYINGS_END = "varying vec2 v_cpC;"; +const FRAG_DIST_CALL = + "float dist = distToQuadraticBezierCurve(gl_FragCoord.xy, v_cpA, v_cpB, v_cpC);"; +const FRAG_BODY_OUTPUT = "gl_FragColor = mix(v_color, transparent, t);"; + +const VERT_ATTRIBUTES_END = "attribute float a_curvature;"; +// Coincidentally the same string as FRAG_VARYINGS_END (both stages declare +// the control-point varyings) — wrong-stage input is caught by the explicit +// assertStage() checks, not by this anchor. +const VERT_VARYINGS_END = "varying vec2 v_cpC;"; +const VERT_MAIN_START = `void main() { + float minThickness = u_minEdgeThickness;`; +const VERT_CONTROL_POINTS_DONE = "v_cpC = viewportTarget;"; + +/** + * Every anchor the two patchers rely on, exported so the unit tests can also + * grep the LIVE bundle text for them (early drift signal; the runtime + * try/catch in buildProgramRegistry is the actual guard). + */ +const CURVE_FLOW_ANCHORS = Object.freeze({ + fragment: Object.freeze([ + FRAG_DISTANCE_FN_DECL, + FRAG_T_COMPUTATION, + FRAG_DIST_TO_CURVE_FN, + FRAG_VARYINGS_END, + FRAG_DIST_CALL, + FRAG_BODY_OUTPUT, + ]), + vertex: Object.freeze([ + VERT_ATTRIBUTES_END, + VERT_VARYINGS_END, + VERT_MAIN_START, + VERT_CONTROL_POINTS_DONE, + ]), +}); + +// --------------------------------------------------------------------------- +// Injected GLSL. +// --------------------------------------------------------------------------- + +// Pattern constants — MUST stay numerically identical to the straight-edge +// program's copies in edge_flow_programs.js (FLOW_VERTEX_SHADER + +// FLOW_FRAGMENT_SHADER): straight and curved flow edges animate side by side, +// and any drift shows up as mismatched dash spacing, dot size or speed. +// language=GLSL +const FLOW_PATTERN_CONSTANTS = /*glsl*/ ` +// Base flow velocity in screen px per second (x per-edge v_flowSpeed). +const float SPEED_PX_PER_S = 40.0; +const float DASH_PERIOD_PX = 16.0; +const float DASH_DUTY = 0.5; +const float PULSE_PERIOD_PX = 48.0; +const float COMET_PERIOD_PX = 48.0; +const float CHEVRON_PERIOD_PX = 24.0; +// Chevron band: along-the-curve backsweep at the rim + filled period fraction. +const float CHEVRON_SLOPE_PX = 4.0; +const float CHEVRON_DUTY = 0.25; +// Pulse dot half-length along the edge. +const float DOT_RADIUS_PX = 3.0; +// Dash-end smoothing in screen px. +const float DASH_AA_PX = 1.0;`; + +// language=GLSL +const FRAG_FLOW_INPUTS = /*glsl*/ `varying float v_flow; +varying float v_flowSpeed; +varying float v_flowDensity; +varying float v_flowArcLenPx; + +uniform float u_time; +${FLOW_PATTERN_CONSTANTS}`; + +// Replaces the body-color output INSIDE the `dist < halfThickness` non-picking +// branch: `t` (just above) is the parent's rim feather term (0 at the spine, +// 1 at the rim), so (1.0 - t) is the coverage the body would have drawn with. +// PICKING_MODE is untouched — the parent's id output stays, and the body +// sub-program already draws this exact quad with this exact id, so picking +// coverage is unchanged (same reasoning as the straight flow program). +// language=GLSL +const FRAG_FLOW_MASK = /*glsl*/ `// Flow mask instead of the body color (v_color carries the flow color, + // substituted CPU-side like the curve halo does). curveT x arc length = + // distance along the curve in px; the pattern expressions mirror the + // straight program's (edge_flow_programs.js FLOW_FRAGMENT_SHADER), with + // the per-edge density multiplier stretching the period. + float alongPx = curveT * v_flowArcLenPx; + float basePeriod = v_flow < 1.5 ? DASH_PERIOD_PX + : v_flow < 2.5 ? PULSE_PERIOD_PX + : v_flow < 3.5 ? COMET_PERIOD_PX + : CHEVRON_PERIOD_PX; + float period = basePeriod * v_flowDensity; + float crossNorm = dist / halfThickness; + float phase = fract(alongPx / period - fract(u_time * v_flowSpeed * SPEED_PX_PER_S / period)); + float alpha; + if (v_flow < 1.5) { + // Dash: filled for phase in [0, duty), ends feathered in phase units. + float aa = DASH_AA_PX / period; + float dashDist = min(phase, DASH_DUTY - phase); + alpha = smoothstep(-0.5 * aa, 0.5 * aa, dashDist); + } else if (v_flow < 2.5) { + // Pulse: circular-ish dot — along-distance normalized to the dot + // radius, cross-distance to the half-thickness, soft radial falloff. + vec2 q = vec2((phase - 0.5) * period / DOT_RADIUS_PX, crossNorm); + alpha = 1.0 - smoothstep(0.8, 1.0, length(q)); + } else if (v_flow < 3.5) { + // Comet: alpha ramps over the period — fading tail behind the sharp + // head at the fract() wrap. + alpha = phase * phase; + } else { + // Chevron: dash band swept back with the cross-axis distance, tip + // leading at the spine — a > pointing along the travel direction. + float chevPhase = fract(phase + (CHEVRON_SLOPE_PX / period) * crossNorm); + float aa = DASH_AA_PX / period; + float chevDist = min(chevPhase, CHEVRON_DUTY - chevPhase); + alpha = smoothstep(-0.5 * aa, 0.5 * aa, chevDist); + } + gl_FragColor = mix(transparent, v_color, alpha * (1.0 - t));`; + +// language=GLSL +const VERT_FLOW_COLLAPSE = /*glsl*/ `if (a_flow < 0.5) { + // Flow disabled: zero-area triangle off-screen -> no fragments (the + // straight flow program's trick; the cheapest possible off state). + gl_Position = vec4(2.0, 2.0, 0.0, 1.0); + v_color = vec4(0.0); + v_thickness = 1.0; + v_feather = 1.0; + v_cpA = vec2(0.0); + v_cpB = vec2(0.0); + v_cpC = vec2(0.0); + v_flow = 0.0; + v_flowSpeed = 0.0; + v_flowDensity = 1.0; + v_flowArcLenPx = 0.0; + return; + } +`; + +// language=GLSL +const VERT_ARC_LENGTH = /*glsl*/ ` + v_flow = a_flow; + v_flowSpeed = a_flowSpeed; + // Clamp must match the straight program's vertex copy (period divisor). + v_flowDensity = max(a_flowDensity, 0.05); + // Arc length of the projected bezier (chord sum, 8 segments — well under + // 1% short at the app's fixed 0.25 curvature). The control points are in + // DEVICE px (gl_FragCoord space); divide by u_pixelRatio so the fragment's + // pattern geometry is in CSS px, matching the straight flow program's dash + // spacing on hidpi screens. + vec2 flowPrev = v_cpA; + float flowArcLen = 0.0; + for (int i = 1; i <= 8; i++) { + float ft = float(i) / 8.0; + vec2 flowPt = mix(mix(v_cpA, v_cpB, ft), mix(v_cpB, v_cpC, ft), ft); + flowArcLen += length(flowPt - flowPrev); + flowPrev = flowPt; + } + v_flowArcLenPx = flowArcLen / u_pixelRatio;`; + +// --------------------------------------------------------------------------- +// Patchers. +// --------------------------------------------------------------------------- + +/** + * Throw unless `source` looks like the expected shader stage. Both patchers' + * anchor sets overlap (the v_cpC varying exists in both stages), so the + * stage marker — gl_FragCoord reads vs gl_Position writes — is the check + * that actually rejects a source handed to the wrong patcher. + * + * @param {string} source + * @param {string} marker stage-distinctive substring + * @param {string} patcherName for the error message + */ +function assertStage(source, marker, patcherName) { + if (!source.includes(marker)) { + throw new Error( + `${patcherName}: source does not look like the expected shader stage ` + + `(missing ${JSON.stringify(marker)}) — wrong source passed, or a ` + + `sigma upgrade restructured the GLSL`, + ); + } +} + +/** + * Replace the first occurrence of `anchor`, throwing a descriptive error when + * the anchor is absent (sigma upgrade moved the GLSL). + * + * Patch-ordering invariant: the patchers apply several replaceOnce calls to + * the same accumulating string, so injected text must never contain a LATER + * call's anchor — the injected copy would be patched instead of the original. + * + * @param {string} source + * @param {string} anchor exact substring of the bundled shader source + * @param {string} replacement + * @param {string} patcherName for the error message + * @returns {string} + */ +function replaceOnce(source, anchor, replacement, patcherName) { + const index = source.indexOf(anchor); + if (index === -1) { + throw new Error( + `${patcherName}: anchor not found in @sigma/edge-curve shader source ` + + `(did a sigma upgrade change the GLSL?): ${JSON.stringify(anchor)}`, + ); + } + return source.slice(0, index) + replacement + source.slice(index + anchor.length); +} + +/** + * Fork the @sigma/edge-curve FRAGMENT shader: expose the closest-point bezier + * parameter t from getDistanceVector and replace the body-color output with + * the animated dash/pulse flow mask (non-picking only). + * + * @param {string} fragmentSource + * @returns {string} + * @throws {Error} when any anchor is missing from the source + */ +function patchCurveFragmentForFlow(fragmentSource) { + const name = "patchCurveFragmentForFlow"; + assertStage(fragmentSource, "gl_FragCoord", name); + // Scope dependencies of the injected mask that no anchor would otherwise + // verify: FRAG_FLOW_MASK reads the parent's halfThickness and rim term t. + assertStage(fragmentSource, "float halfThickness", name); + assertStage(fragmentSource, "float t = smoothstep(", name); + let source = fragmentSource; + // Expose t: out param on getDistanceVector + distToQuadraticBezierCurve. + source = replaceOnce( + source, + FRAG_DISTANCE_FN_DECL, + "vec2 getDistanceVector(vec2 b0, vec2 b1, vec2 b2, out float t_out) {", + name, + ); + source = replaceOnce(source, FRAG_T_COMPUTATION, `${FRAG_T_COMPUTATION}\n t_out = t;`, name); + source = replaceOnce( + source, + FRAG_DIST_TO_CURVE_FN, + `float distToQuadraticBezierCurve(vec2 p, vec2 b0, vec2 b1, vec2 b2, out float t_out) { + return length(getDistanceVector(b0 - p, b1 - p, b2 - p, t_out)); +}`, + name, + ); + // Flow inputs after the parent's last varying. + source = replaceOnce(source, FRAG_VARYINGS_END, `${FRAG_VARYINGS_END}\n${FRAG_FLOW_INPUTS}`, name); + // main: capture curveT at the existing distance call. + source = replaceOnce( + source, + FRAG_DIST_CALL, + `float curveT = 0.0; + float dist = distToQuadraticBezierCurve(gl_FragCoord.xy, v_cpA, v_cpB, v_cpC, curveT);`, + name, + ); + // Body color -> flow mask. + source = replaceOnce(source, FRAG_BODY_OUTPUT, FRAG_FLOW_MASK, name); + return source; +} + +/** + * Fork the @sigma/edge-curve VERTEX shader: add the a_flow/a_flowSpeed/ + * a_flowDensity attributes (the flow color rides the parent's a_color slot, + * substituted CPU-side), the flow-off vertex collapse, and the projected + * arc-length varying the fragment scales curveT by. + * + * @param {string} vertexSource + * @returns {string} + * @throws {Error} when any anchor is missing from the source + */ +function patchCurveVertexForFlow(vertexSource) { + const name = "patchCurveVertexForFlow"; + assertStage(vertexSource, "gl_Position", name); + let source = vertexSource; + source = replaceOnce( + source, + VERT_ATTRIBUTES_END, + `${VERT_ATTRIBUTES_END} +attribute float a_flow; +attribute float a_flowSpeed; +attribute float a_flowDensity;`, + name, + ); + source = replaceOnce( + source, + VERT_VARYINGS_END, + `${VERT_VARYINGS_END} +varying float v_flow; +varying float v_flowSpeed; +varying float v_flowDensity; +varying float v_flowArcLenPx;`, + name, + ); + source = replaceOnce( + source, + VERT_MAIN_START, + `void main() { + ${VERT_FLOW_COLLAPSE} + float minThickness = u_minEdgeThickness;`, + name, + ); + source = replaceOnce( + source, + VERT_CONTROL_POINTS_DONE, + `${VERT_CONTROL_POINTS_DONE}\n${VERT_ARC_LENGTH}`, + name, + ); + return source; +} + +export { patchCurveFragmentForFlow, patchCurveVertexForFlow, CURVE_FLOW_ANCHORS }; diff --git a/src/graph/edge_flow_programs.js b/src/graph/edge_flow_programs.js new file mode 100644 index 0000000..d2d13a0 --- /dev/null +++ b/src/graph/edge_flow_programs.js @@ -0,0 +1,390 @@ +/** + * Animated edge-flow overlay program (browser-only — imports the sigma + * bundle, must never be loaded under node/vitest). + * + * EdgeFlowProgram draws a moving source→target pattern OVER the straight + * edge body (composed into "styledLine" after EdgeRectangleProgram, before + * the marker heads — see sigma_adapter.buildProgramRegistry). Four patterns, + * selected by the per-edge `flowMode` float attr (FLOW_MODES in + * graph_model.js): marching dashes (1), travelling pulse dots (2), fading + * comet tails (3) or travelling chevron arrows (4); + * 0 collapses the quad in the vertex shader → zero fragments, so edges + * without flow cost (almost) nothing, same trick as the halo program. + * + * Animation: the programs are stateless — FlowAnimator advances the module + * `flowClock` and triggers redraw-only refreshes; setUniforms re-reads the + * clock each frame (buffers untouched). + * + * Curved edges get the same overlay from createCurveFlowProgram, a + * @sigma/edge-curve subclass whose shaders are forked by the string patchers + * in edge_flow_glsl.js (composed into "styledCurve" the same way). The + * patchers throw on GLSL anchor drift — buildProgramRegistry catches and + * degrades to non-animated curves. + */ +import { EdgeRectangleProgram, floatColor } from "../lib/sigma.bundle.mjs"; +import { patchCurveFragmentForFlow, patchCurveVertexForFlow } from "./edge_flow_glsl.js"; + +const { UNSIGNED_BYTE, FLOAT } = WebGLRenderingContext; + +const TRANSPARENT = "#00000000"; + +/** + * Module-level animation clock (seconds). FlowAnimator owns advancing it + * (and zeroes it in destroy()); every EdgeFlowProgram instance reads it in + * setUniforms as u_time. Wrapped by the animator (see TIME_WRAP_S there) so + * the shader's fract() never sees float-precision decay on long sessions. + * A single shared clock assumes one live SigmaAdapter at a time (the app's + * invariant) — concurrent adapters would tick each other's patterns, nothing + * worse. + */ +const flowClock = { time: 0 }; + +// --------------------------------------------------------------------------- +// Straight-edge flow: EdgeRectangleProgram clone drawing the animated pattern +// with the flow color at the body's own thickness. The vertex shader is the +// halo vertex shader (sigma's edge.vert.glsl + zero-normal collapse guard, NO +// minEdgeThickness clamp — the clamp would resurrect a disabled overlay as a +// minThickness-wide quad) extended with the along-the-edge phase varying. +// +// Pattern geometry is computed in SCREEN px so dash spacing/dot size are +// zoom-stable: a_edgeLength is the graph-coordinate endpoint distance, and +// graph-coordinate length → screen px is length / (2 × u_correctionRatio) +// (inverse of the px → pre-matrix convention the halo/marker shaders use: +// px × 2 × correctionRatio / sizeRatio pre-matrix ≙ px / sizeRatio screen px, +// and correctionRatio = 1 / (matrix scale × viewport width)). +// +// The time term is folded into the phase PER EDGE in the vertex shader +// (fract of whole periods travelled — constant across the quad, so the +// varying stays linear in a_positionCoef and small enough for mediump +// fragments). phase = alongPx/period − travelled ⇒ a fixed pattern feature +// satisfies alongPx = const + t·speed ⇒ it moves from positionCoef 0 (source) +// toward 1 (target). +// --------------------------------------------------------------------------- + +// language=GLSL +const FLOW_VERTEX_SHADER = /*glsl*/ ` +attribute vec4 a_id; +attribute vec4 a_color; +attribute vec2 a_normal; +attribute float a_normalCoef; +attribute vec2 a_positionStart; +attribute vec2 a_positionEnd; +attribute float a_positionCoef; +attribute float a_edgeLength; +attribute float a_flow; +attribute float a_flowSpeed; +attribute float a_flowDensity; + +uniform mat3 u_matrix; +uniform float u_sizeRatio; +uniform float u_zoomRatio; +uniform float u_pixelRatio; +uniform float u_correctionRatio; +uniform float u_minEdgeThickness; +uniform float u_feather; +uniform float u_time; + +varying vec4 v_color; +varying vec2 v_normal; +varying float v_thickness; +varying float v_feather; +varying float v_flow; +varying float v_phase; +varying float v_flowDensity; + +const float bias = 255.0 / 254.0; +// Base flow velocity in screen px per second (× per-edge a_flowSpeed). +const float SPEED_PX_PER_S = 40.0; +// Pattern periods — must stay equal to the same constants in the FRAGMENT +// shader (GLSL stages can't share consts; both fold px into period units) +// AND to FLOW_PATTERN_CONSTANTS in edge_flow_glsl.js (the curve overlay +// animates side by side with this one). +const float DASH_PERIOD_PX = 16.0; +const float PULSE_PERIOD_PX = 48.0; +const float COMET_PERIOD_PX = 48.0; +const float CHEVRON_PERIOD_PX = 24.0; + +void main() { + vec2 normal = a_normal * a_normalCoef; + float normalLength = length(normal); + + if (normalLength <= 0.0) { + // Flow disabled: zero-area triangle off-screen -> no fragments. + gl_Position = vec4(2.0, 2.0, 0.0, 1.0); + v_color = vec4(0.0); + v_normal = vec2(0.0); + v_thickness = 1.0; + v_feather = 1.0; + v_flow = 0.0; + v_phase = 0.0; + v_flowDensity = 1.0; + return; + } + + vec2 unitNormal = normal / normalLength; + float webGLThickness = normalLength * u_correctionRatio / u_sizeRatio; + + vec2 position = a_positionStart * (1.0 - a_positionCoef) + a_positionEnd * a_positionCoef; + gl_Position = vec4((u_matrix * vec3(position + unitNormal * webGLThickness, 1)).xy, 0, 1); + + v_thickness = webGLThickness / u_zoomRatio; + v_normal = unitNormal; + v_feather = u_feather * u_correctionRatio / u_zoomRatio / u_pixelRatio * 2.0; + v_flow = a_flow; + + // Phase in pattern periods: along-the-edge screen px / period, minus the + // periods travelled so far (fract'd per edge here in highp; the fragment's + // mediump fract then only ever sees |phase| ≲ edge length / period). + // The density multiplier stretches the period (sparser pattern) — the + // fragment rebuilds the same periodPx from v_flow x v_flowDensity, so the + // max() clamp must match its copy. + float basePeriodPx = a_flow < 1.5 ? DASH_PERIOD_PX + : a_flow < 2.5 ? PULSE_PERIOD_PX + : a_flow < 3.5 ? COMET_PERIOD_PX + : CHEVRON_PERIOD_PX; + v_flowDensity = max(a_flowDensity, 0.05); + float periodPx = basePeriodPx * v_flowDensity; + float alongPx = a_positionCoef * a_edgeLength / (2.0 * u_correctionRatio); + float travelled = fract(u_time * a_flowSpeed * SPEED_PX_PER_S / periodPx); + v_phase = alongPx / periodPx - travelled; + + #ifdef PICKING_MODE + v_color = a_id; + #else + v_color = a_color; + #endif + + v_color.a *= bias; +} +`; + +// language=GLSL +const FLOW_FRAGMENT_SHADER = /*glsl*/ ` +precision mediump float; + +varying vec4 v_color; +varying vec2 v_normal; +varying float v_thickness; +varying float v_feather; +varying float v_flow; +varying float v_phase; +varying float v_flowDensity; + +const vec4 transparent = vec4(0.0, 0.0, 0.0, 0.0); +// ALL pattern constants below must stay equal to the VERTEX shader's copies +// and to FLOW_PATTERN_CONSTANTS in edge_flow_glsl.js (curve overlay). +const float DASH_PERIOD_PX = 16.0; +const float DASH_DUTY = 0.5; +const float PULSE_PERIOD_PX = 48.0; +const float COMET_PERIOD_PX = 48.0; +const float CHEVRON_PERIOD_PX = 24.0; +// Chevron band: along-the-edge backsweep at the rim and filled fraction of +// the period (a "wide dash" swept into a > pointing at the target). +const float CHEVRON_SLOPE_PX = 4.0; +const float CHEVRON_DUTY = 0.25; +// Pulse dot half-length along the edge (≈6 px dot at default zoom). +const float DOT_RADIUS_PX = 3.0; +// Dash-end smoothing in screen px (the cross-section reuses v_feather). +const float DASH_AA_PX = 1.0; + +void main(void) { + #ifdef PICKING_MODE + // Whole quad picks the edge id — the body program already draws this exact + // quad with this exact id in the picking pass, so coverage is unchanged. + gl_FragColor = v_color; + #else + // Cross-section anti-alias feathering, identical to the halo/body edge. + float dist = length(v_normal) * v_thickness; + float crossSection = 1.0 - smoothstep(v_thickness - v_feather, v_thickness, dist); + + float f = fract(v_phase); + float alpha; + if (v_flow < 1.5) { + // Dash: filled for f ∈ [0, duty), ends feathered in phase units so the + // marching segments aren't aliased along the edge. + float aa = DASH_AA_PX / (DASH_PERIOD_PX * v_flowDensity); + float d = min(f, DASH_DUTY - f); // signed distance to the dash band edge + alpha = smoothstep(-0.5 * aa, 0.5 * aa, d); + } else if (v_flow < 2.5) { + // Pulse: circular-ish dot — along-distance normalized to the dot radius, + // cross-distance to the half-thickness, soft radial falloff. Density + // stretches the spacing; the dot itself stays DOT_RADIUS_PX. + vec2 q = vec2((f - 0.5) * PULSE_PERIOD_PX * v_flowDensity / DOT_RADIUS_PX, length(v_normal)); + alpha = 1.0 - smoothstep(0.8, 1.0, length(q)); + } else if (v_flow < 3.5) { + // Comet: alpha ramps up over the period — a tail fading in behind the + // sharp head sitting at the fract() wrap. + alpha = f * f; + } else { + // Chevron: a dash band whose phase is swept back with the cross-axis + // distance (length(v_normal) is 0 at the spine, 1 at the rim) — the + // band's tip leads at the spine, forming a > toward the target. + float periodPx = CHEVRON_PERIOD_PX * v_flowDensity; + float fc = fract(v_phase + (CHEVRON_SLOPE_PX / periodPx) * length(v_normal)); + float aa = DASH_AA_PX / periodPx; + float d = min(fc, CHEVRON_DUTY - fc); + alpha = smoothstep(-0.5 * aa, 0.5 * aa, d); + } + + gl_FragColor = mix(transparent, v_color, alpha * crossSection); + #endif +} +`; + +class EdgeFlowProgram extends EdgeRectangleProgram { + getDefinition() { + const definition = super.getDefinition(); + return { + ...definition, + VERTEX_SHADER_SOURCE: FLOW_VERTEX_SHADER, + FRAGMENT_SHADER_SOURCE: FLOW_FRAGMENT_SHADER, + UNIFORMS: [...definition.UNIFORMS, "u_time"], + ATTRIBUTES: [ + { name: "a_positionStart", size: 2, type: FLOAT }, + { name: "a_positionEnd", size: 2, type: FLOAT }, + { name: "a_normal", size: 2, type: FLOAT }, + { name: "a_edgeLength", size: 1, type: FLOAT }, + { name: "a_flow", size: 1, type: FLOAT }, + { name: "a_flowSpeed", size: 1, type: FLOAT }, + { name: "a_flowDensity", size: 1, type: FLOAT }, + ...definition.ATTRIBUTES.filter(({ name }) => name === "a_color" || name === "a_id"), + ], + }; + } + + processVisibleItem(edgeIndex, startIndex, sourceData, targetData, data) { + const flowMode = data.flowMode > 0 ? data.flowMode : 0; + // Post-reducer size: the overlay matches the body width, so a selected + // (widened) edge widens its flow pattern with the line. + const thickness = flowMode > 0 ? data.size || 1 : 0; + const color = floatColor(flowMode > 0 ? (data.flowColor ?? data.color) : TRANSPARENT); + + const x1 = sourceData.x; + const y1 = sourceData.y; + const x2 = targetData.x; + const y2 = targetData.y; + const dx = x2 - x1; + const dy = y2 - y1; + let edgeLength = 0; + let n1 = 0; + let n2 = 0; + const len = dx * dx + dy * dy; + if (len && thickness > 0) { + edgeLength = Math.sqrt(len); + n1 = (-dy / edgeLength) * thickness; + n2 = (dx / edgeLength) * thickness; + } + + const array = this.array; + array[startIndex++] = x1; + array[startIndex++] = y1; + array[startIndex++] = x2; + array[startIndex++] = y2; + array[startIndex++] = n1; + array[startIndex++] = n2; + array[startIndex++] = edgeLength; + array[startIndex++] = flowMode; + array[startIndex++] = data.flowSpeed || 0; + array[startIndex++] = data.flowDensity > 0 ? data.flowDensity : 1; + array[startIndex++] = color; + array[startIndex++] = edgeIndex; + } + + setUniforms(params, programInfo) { + super.setUniforms(params, programInfo); + programInfo.gl.uniform1f(programInfo.uniformLocations.u_time, flowClock.time); + } +} + +// --------------------------------------------------------------------------- +// Curved-edge flow: @sigma/edge-curve subclass whose shaders are forked by +// the edge_flow_glsl.js string patchers (out-param t from the bezier distance +// function × a projected arc-length varying drive the same dash/pulse masks). +// The flow color rides the parent's a_color slot (CPU-side substitution, like +// the curve halo); only a_flow/a_flowSpeed/a_flowDensity are appended after +// the parent's attributes. +// --------------------------------------------------------------------------- + +/** + * Floats one edge occupies in an instanced program's array (sigma's + * getAttributesItemsCount convention): FLOAT attrs contribute their size, + * UNSIGNED_BYTE×4-normalized color/id attrs pack into a single float slot. + * + * With arrowHead: null the parent layout is a_source:2 a_target:2 + * a_thickness:1 a_curvature:1 a_color:1 a_id:1 = 8 floats — cross-check + * against the bundle after a sigma upgrade. + * + * @param {Array<{name: string, size: number, type: number, normalized?: boolean}>} attributes + * @returns {number} + * @throws {Error} on an attribute layout this convention doesn't cover + * (caught by buildProgramRegistry's fallback, like the GLSL anchors) + */ +function attributeFloatCount(attributes) { + return attributes.reduce((count, { name, size, type, normalized }) => { + if (type === FLOAT) return count + size; + if (type === UNSIGNED_BYTE && normalized && size === 4) return count + 1; + throw new Error(`edge_flow_programs: unsupported attribute layout for "${name}"`); + }, 0); +} + +/** + * Build the curve flow sub-program for the "styledCurve" compound. Patches + * the parent's GLSL EAGERLY, so anchor drift after a sigma upgrade throws + * HERE (where buildProgramRegistry can catch it and drop the sub-program) + * instead of later inside sigma's render loop. + * + * @param {typeof EdgeRectangleProgram} CurveProgramClass a created @sigma/edge-curve program class + * @returns {typeof EdgeRectangleProgram} + * @throws {Error} when the bundled curve GLSL no longer matches the patchers' anchors + */ +function createCurveFlowProgram(CurveProgramClass) { + // The created curve program's getDefinition is closure-pure (no `this`); + // a bare prototype-derived receiver keeps this honest if that changes. + const parentDefinition = CurveProgramClass.prototype.getDefinition.call( + Object.create(CurveProgramClass.prototype), + ); + const vertexSource = patchCurveVertexForFlow(parentDefinition.VERTEX_SHADER_SOURCE); + const fragmentSource = patchCurveFragmentForFlow(parentDefinition.FRAGMENT_SHADER_SOURCE); + // a_flow/a_flowSpeed/a_flowDensity live right after the parent's per-edge floats. + const parentStrideFloats = attributeFloatCount(parentDefinition.ATTRIBUTES); + + return class CurveFlowProgram extends CurveProgramClass { + getDefinition() { + const definition = super.getDefinition(); + return { + ...definition, + VERTEX_SHADER_SOURCE: vertexSource, + FRAGMENT_SHADER_SOURCE: fragmentSource, + UNIFORMS: [...definition.UNIFORMS, "u_time"], + ATTRIBUTES: [ + ...definition.ATTRIBUTES, + { name: "a_flow", size: 1, type: FLOAT }, + { name: "a_flowSpeed", size: 1, type: FLOAT }, + { name: "a_flowDensity", size: 1, type: FLOAT }, + ], + }; + } + + processVisibleItem(edgeIndex, startIndex, sourceData, targetData, data) { + const flowMode = data.flowMode > 0 ? data.flowMode : 0; + // Flow color rides the parent's color slot; size stays the body's + // (post-reducer) size so the overlay widens with a selected edge. + // The a_flow < 0.5 vertex collapse makes the off-state values inert — + // TRANSPARENT is belt and braces. + super.processVisibleItem(edgeIndex, startIndex, sourceData, targetData, { + ...data, + color: flowMode > 0 ? (data.flowColor ?? data.color) : TRANSPARENT, + }); + this.array[startIndex + parentStrideFloats] = flowMode; + this.array[startIndex + parentStrideFloats + 1] = flowMode > 0 ? data.flowSpeed || 0 : 0; + this.array[startIndex + parentStrideFloats + 2] = data.flowDensity > 0 ? data.flowDensity : 1; + } + + setUniforms(params, programInfo) { + super.setUniforms(params, programInfo); + programInfo.gl.uniform1f(programInfo.uniformLocations.u_time, flowClock.time); + } + }; +} + +export { EdgeFlowProgram, createCurveFlowProgram, flowClock }; diff --git a/src/graph/edge_programs.js b/src/graph/edge_programs.js new file mode 100644 index 0000000..47938a0 --- /dev/null +++ b/src/graph/edge_programs.js @@ -0,0 +1,457 @@ +/** + * Custom WebGL edge programs (browser-only — imports the sigma bundle, must + * never be loaded under node/vitest). + * + * Three building blocks, composed into the "styledLine"/"styledCurve" + * registry entries by sigma_adapter.buildProgramRegistry: + * + * - EdgeHaloProgram: a wider quad UNDER the straight edge body reading the + * per-edge `haloWidth`/`haloColor` attrs (graph_model). haloWidth 0 + * collapses the quad in the vertex shader → zero fragments, so disabled + * halos cost (almost) nothing. Total halo width = edge size + 2×haloWidth, + * computed from the POST-reducer size so selection-widening widens the + * halo with the line. + * + * - createCurveHaloProgram(CurveProgram): same underdraw for @sigma/edge-curve + * edges, by re-processing the curve program with substituted size/color. + * The curve shader clamps thickness up to minEdgeThickness, so "off" is a + * hairline fully-transparent band instead of a degenerate quad. + * + * - createEdgeMarkerHeadProgram({extremity, curved}): parametric end-marker + * head. ONE program draws every marker shape — a per-edge float enum + * (`startMarker`/`endMarker`, see EDGE_MARKERS in graph_model.js) selects + * the SDF in the fragment shader (arrow/rect/diamond/circle/tee), and + * `startMarkerSize`/`endMarkerSize` give an explicit length in graph px + * (0 → proportional to edge thickness, sigma stock-arrow ratios). The + * curved variant orients the head along the quadratic-bezier tangent that + * @sigma/edge-curve renders (control point = midpoint + perp(delta) × + * curvature — the graph→viewport map is a similarity transform, so the + * graph-space construction matches the shader's viewport-space one). + */ +import { EdgeProgram, EdgeRectangleProgram, floatColor } from "../lib/sigma.bundle.mjs"; + +const { UNSIGNED_BYTE, FLOAT } = WebGLRenderingContext; + +// Mirrors @sigma/edge-curve DEFAULT_EDGE_CURVATURE (the app sets no per-edge +// curvature, so every curved edge renders with this value). +const DEFAULT_EDGE_CURVATURE = 0.25; + +const TRANSPARENT = "#00000000"; + +// --------------------------------------------------------------------------- +// Straight-edge halo: EdgeRectangleProgram clone whose thickness/color come +// from the halo attrs. The vertex shader is sigma's edge.vert.glsl with two +// changes: a zero-normal guard that collapses disabled halos to a zero-area +// off-screen triangle, and NO minEdgeThickness clamp (the clamp would +// resurrect a zero-width halo as a minThickness-wide quad). +// --------------------------------------------------------------------------- + +// language=GLSL +const HALO_VERTEX_SHADER = /*glsl*/ ` +attribute vec4 a_id; +attribute vec4 a_color; +attribute vec2 a_normal; +attribute float a_normalCoef; +attribute vec2 a_positionStart; +attribute vec2 a_positionEnd; +attribute float a_positionCoef; + +uniform mat3 u_matrix; +uniform float u_sizeRatio; +uniform float u_zoomRatio; +uniform float u_pixelRatio; +uniform float u_correctionRatio; +uniform float u_minEdgeThickness; +uniform float u_feather; + +varying vec4 v_color; +varying vec2 v_normal; +varying float v_thickness; +varying float v_feather; + +const float bias = 255.0 / 254.0; + +void main() { + vec2 normal = a_normal * a_normalCoef; + float normalLength = length(normal); + + if (normalLength <= 0.0) { + // Halo disabled: zero-area triangle off-screen -> no fragments. + gl_Position = vec4(2.0, 2.0, 0.0, 1.0); + v_color = vec4(0.0); + v_normal = vec2(0.0); + v_thickness = 1.0; + v_feather = 1.0; + return; + } + + vec2 unitNormal = normal / normalLength; + float webGLThickness = normalLength * u_correctionRatio / u_sizeRatio; + + vec2 position = a_positionStart * (1.0 - a_positionCoef) + a_positionEnd * a_positionCoef; + gl_Position = vec4((u_matrix * vec3(position + unitNormal * webGLThickness, 1)).xy, 0, 1); + + v_thickness = webGLThickness / u_zoomRatio; + v_normal = unitNormal; + v_feather = u_feather * u_correctionRatio / u_zoomRatio / u_pixelRatio * 2.0; + + #ifdef PICKING_MODE + v_color = a_id; + #else + v_color = a_color; + #endif + + v_color.a *= bias; +} +`; + +// language=GLSL +const HALO_FRAGMENT_SHADER = /*glsl*/ ` +precision mediump float; + +varying vec4 v_color; +varying vec2 v_normal; +varying float v_thickness; +varying float v_feather; + +const vec4 transparent = vec4(0.0, 0.0, 0.0, 0.0); + +void main(void) { + #ifdef PICKING_MODE + gl_FragColor = v_color; + #else + float dist = length(v_normal) * v_thickness; + float t = smoothstep(v_thickness - v_feather, v_thickness, dist); + gl_FragColor = mix(v_color, transparent, t); + #endif +} +`; + +class EdgeHaloProgram extends EdgeRectangleProgram { + getDefinition() { + return { + ...super.getDefinition(), + VERTEX_SHADER_SOURCE: HALO_VERTEX_SHADER, + FRAGMENT_SHADER_SOURCE: HALO_FRAGMENT_SHADER, + }; + } + + processVisibleItem(edgeIndex, startIndex, sourceData, targetData, data) { + const haloWidth = data.haloWidth > 0 ? data.haloWidth : 0; + // Post-reducer size: a selected (widened) edge widens its halo too. + const thickness = haloWidth > 0 ? (data.size || 1) + 2 * haloWidth : 0; + const color = floatColor(haloWidth > 0 ? (data.haloColor ?? data.color) : TRANSPARENT); + + const x1 = sourceData.x; + const y1 = sourceData.y; + const x2 = targetData.x; + const y2 = targetData.y; + const dx = x2 - x1; + const dy = y2 - y1; + let len = dx * dx + dy * dy; + let n1 = 0; + let n2 = 0; + if (len && thickness > 0) { + len = 1 / Math.sqrt(len); + n1 = -dy * len * thickness; + n2 = dx * len * thickness; + } + + const array = this.array; + array[startIndex++] = x1; + array[startIndex++] = y1; + array[startIndex++] = x2; + array[startIndex++] = y2; + array[startIndex++] = n1; + array[startIndex++] = n2; + array[startIndex++] = color; + array[startIndex++] = edgeIndex; + } +} + +// --------------------------------------------------------------------------- +// Curved-edge halo: re-process the curve program with halo size/color. +// --------------------------------------------------------------------------- + +/** @param {typeof EdgeProgram} CurveProgramClass a created @sigma/edge-curve program class */ +function createCurveHaloProgram(CurveProgramClass) { + return class CurveHaloProgram extends CurveProgramClass { + processVisibleItem(edgeIndex, startIndex, sourceData, targetData, data) { + const haloWidth = data.haloWidth > 0 ? data.haloWidth : 0; + // The curve shader clamps thickness up to minEdgeThickness, so a zero + // size cannot fully disable it — pair a hairline size with a fully + // transparent color instead (fragments blend to nothing). + const size = haloWidth > 0 ? (data.size || 1) + 2 * haloWidth : 0.001; + const color = haloWidth > 0 ? (data.haloColor ?? data.color) : TRANSPARENT; + super.processVisibleItem(edgeIndex, startIndex, sourceData, targetData, { + ...data, + size, + color, + }); + } + }; +} + +// --------------------------------------------------------------------------- +// Parametric marker head. +// +// Geometry: a quad anchored at the marked node's border, extending `length` +// back along the edge (straight) or along the bezier tangent (curved), tip +// side at the node. a_corner ∈ {-1,1}×{0,1} spans it as two triangles. +// All lengths are computed in graph px and converted with sigma's stock +// arrow-head convention (px → pre-matrix units = ×2·correctionRatio/sizeRatio). +// Default (markerSize 0) proportions match sigma's arrow: length 2.5×, full +// width 2× the edge thickness. +// --------------------------------------------------------------------------- + +// language=GLSL +const MARKER_VERTEX_SHADER = /*glsl*/ ` +attribute vec2 a_position; +attribute vec2 a_normal; +attribute float a_radius; +attribute float a_marker; +attribute float a_markerSize; +attribute float a_borderSize; +attribute vec2 a_corner; + +#ifdef PICKING_MODE +attribute vec4 a_id; +#else +attribute vec4 a_color; +attribute vec4 a_borderColor; +#endif + +uniform mat3 u_matrix; +uniform float u_sizeRatio; +uniform float u_correctionRatio; +uniform float u_minEdgeThickness; +uniform float u_feather; + +varying vec4 v_color; +varying vec4 v_borderColor; +varying float v_marker; +varying vec2 v_uv; +varying vec2 v_dimPx; +varying float v_borderSizePx; +varying float v_feather; + +const float bias = 255.0 / 254.0; +const float lengthToThicknessRatio = 2.5; +const float widenessToThicknessRatio = 2.0; + +void main() { + float normalLength = length(a_normal); + + if (a_marker < 0.5 || normalLength <= 0.0) { + // No marker on this end: zero-area triangle off-screen -> no fragments. + gl_Position = vec4(2.0, 2.0, 0.0, 1.0); + v_color = vec4(0.0); + v_borderColor = vec4(0.0); + v_marker = 0.0; + v_uv = vec2(0.0); + v_dimPx = vec2(1.0); + v_borderSizePx = 0.0; + v_feather = 1.0; + return; + } + + vec2 unitNormal = a_normal / normalLength; + // a_normal = perp(unitAway): recover the direction pointing from the node + // center back along the edge. + vec2 unitAway = vec2(unitNormal.y, -unitNormal.x); + + // Graph-px sizing (normalLength carries the edge thickness). + float thickness = max(normalLength, u_minEdgeThickness * u_sizeRatio); + float len = a_markerSize > 0.0 ? a_markerSize : thickness * lengthToThicknessRatio; + float halfWidth = a_markerSize > 0.0 + ? a_markerSize * 0.5 + : thickness * widenessToThicknessRatio * 0.5; + + float toWebGL = 2.0 * u_correctionRatio / u_sizeRatio; + vec2 pos = a_position + + unitAway * (a_radius + a_corner.y * len) * toWebGL + + unitNormal * (a_corner.x * halfWidth) * toWebGL; + + gl_Position = vec4((u_matrix * vec3(pos, 1)).xy, 0, 1); + + v_uv = a_corner; + v_dimPx = vec2(2.0 * halfWidth, len) / u_sizeRatio; + // Explicit border thickness (graph px → screen px); 0 lets the fragment derive it. + v_borderSizePx = a_borderSize > 0.0 ? a_borderSize / u_sizeRatio : 0.0; + v_marker = a_marker; + v_feather = u_feather; + + #ifdef PICKING_MODE + v_color = a_id; + #else + v_color = a_color; + v_borderColor = a_borderColor; + v_borderColor.a *= bias; + #endif + + v_color.a *= bias; +} +`; + +// language=GLSL +const MARKER_FRAGMENT_SHADER = /*glsl*/ ` +precision mediump float; + +varying vec4 v_color; +varying vec4 v_borderColor; +varying float v_marker; +varying vec2 v_uv; +varying vec2 v_dimPx; +varying float v_borderSizePx; +varying float v_feather; + +const vec4 transparent = vec4(0.0, 0.0, 0.0, 0.0); +// Auto border band thickness as a fraction of the marker's smaller dimension; +// used when no explicit border size is set, so the outline scales with the +// marker and reads the same at any size/zoom. +const float borderFraction = 0.2; + +void main(void) { + float w = v_dimPx.x; // full width across the edge (screen px) + float l = v_dimPx.y; // length along the edge; y=0 at the node border + float x = abs(v_uv.x) * w * 0.5; + float y = v_uv.y * l; + float d = 0.0; // approx signed distance (px), positive inside + + if (v_marker < 1.5) { + // arrow: triangle, tip at the node border, base toward the line + d = min(y * 0.5 * w / l - x, l - y); + } else if (v_marker < 2.5) { + // rect + d = min(w * 0.5 - x, min(y, l - y)); + } else if (v_marker < 3.5) { + // diamond + float norm = x / (w * 0.5) + abs(y - l * 0.5) / (l * 0.5); + d = (1.0 - norm) * 0.25 * min(w, l); + } else if (v_marker < 4.5) { + // circle + d = 0.5 * min(w, l) - length(vec2(x, y - l * 0.5)); + } else { + // tee: inhibition bar (⊣) hugging the node border + float barLen = max(l * 0.3, 1.5); + d = min(min(y, barLen - y), w * 0.5 - x); + } + + #ifdef PICKING_MODE + gl_FragColor = d >= 0.0 ? v_color : transparent; + #else + float feather = max(v_feather, 0.001); + float coverage = smoothstep(-feather * 0.5, feather * 0.5, d); // 0 outside -> 1 inside + float borderPx = v_borderSizePx > 0.0 ? v_borderSizePx : min(v_dimPx.x, v_dimPx.y) * borderFraction; + // fillMix: 0 inside the border band (near the edge), 1 in the interior. + float fillMix = smoothstep(borderPx - feather * 0.5, borderPx + feather * 0.5, d); + // No border color (alpha ~0) -> the whole marker uses the fill color. + fillMix = max(fillMix, 1.0 - step(0.0039, v_borderColor.a)); + vec4 body = mix(v_borderColor, v_color, fillMix); + gl_FragColor = mix(transparent, body, coverage); + #endif +} +`; + +/** + * @param {object} [options] + * @param {"source"|"target"} [options.extremity] + * @param {boolean} [options.curved] orient along the @sigma/edge-curve tangent + * @returns {typeof EdgeProgram} + */ +function createEdgeMarkerHeadProgram({ extremity = "target", curved = false } = {}) { + const isSource = extremity === "source"; + + return class EdgeMarkerHeadProgram extends EdgeProgram { + getDefinition() { + return { + VERTICES: 6, + VERTEX_SHADER_SOURCE: MARKER_VERTEX_SHADER, + FRAGMENT_SHADER_SOURCE: MARKER_FRAGMENT_SHADER, + METHOD: WebGLRenderingContext.TRIANGLES, + UNIFORMS: ["u_matrix", "u_sizeRatio", "u_correctionRatio", "u_minEdgeThickness", "u_feather"], + ATTRIBUTES: [ + { name: "a_position", size: 2, type: FLOAT }, + { name: "a_normal", size: 2, type: FLOAT }, + { name: "a_radius", size: 1, type: FLOAT }, + { name: "a_marker", size: 1, type: FLOAT }, + { name: "a_markerSize", size: 1, type: FLOAT }, + { name: "a_borderSize", size: 1, type: FLOAT }, + { name: "a_color", size: 4, type: UNSIGNED_BYTE, normalized: true }, + { name: "a_borderColor", size: 4, type: UNSIGNED_BYTE, normalized: true }, + { name: "a_id", size: 4, type: UNSIGNED_BYTE, normalized: true }, + ], + CONSTANT_ATTRIBUTES: [{ name: "a_corner", size: 2, type: FLOAT }], + CONSTANT_DATA: [ + [-1, 0], + [1, 0], + [1, 1], + [-1, 0], + [1, 1], + [-1, 1], + ], + }; + } + + processVisibleItem(edgeIndex, startIndex, sourceData, targetData, data) { + const marked = isSource ? sourceData : targetData; + const marker = (isSource ? data.startMarker : data.endMarker) || 0; + const markerSize = (isSource ? data.startMarkerSize : data.endMarkerSize) || 0; + const borderSize = (isSource ? data.startMarkerBorderSize : data.endMarkerBorderSize) || 0; + const thickness = data.size || 1; + // Explicit arrow fill wins; null inherits the edge color. Border null -> none. + const fillColor = (isSource ? data.startMarkerColor : data.endMarkerColor) ?? data.color; + const borderColor = (isSource ? data.startMarkerBorderColor : data.endMarkerBorderColor) ?? TRANSPARENT; + + // Direction from the marked node back along the edge. + let awayX; + let awayY; + if (curved) { + const curvature = data.curvature ?? DEFAULT_EDGE_CURVATURE; + const dx = targetData.x - sourceData.x; + const dy = targetData.y - sourceData.y; + // Quadratic control point as @sigma/edge-curve constructs it. + const cpX = (sourceData.x + targetData.x) / 2 - dy * curvature; + const cpY = (sourceData.y + targetData.y) / 2 + dx * curvature; + awayX = cpX - marked.x; + awayY = cpY - marked.y; + } else { + const other = isSource ? targetData : sourceData; + awayX = other.x - marked.x; + awayY = other.y - marked.y; + } + + const len = Math.sqrt(awayX * awayX + awayY * awayY); + let n1 = 0; + let n2 = 0; + if (len > 0) { + // a_normal = perp(unitAway) × thickness (the shader recovers both axes). + n1 = (-awayY / len) * thickness; + n2 = (awayX / len) * thickness; + } + + const array = this.array; + array[startIndex++] = marked.x; + array[startIndex++] = marked.y; + array[startIndex++] = n1; + array[startIndex++] = n2; + array[startIndex++] = marked.size || 1; + array[startIndex++] = marker; + array[startIndex++] = markerSize; + array[startIndex++] = borderSize; + array[startIndex++] = floatColor(fillColor); + array[startIndex++] = floatColor(borderColor); + array[startIndex++] = edgeIndex; + } + + setUniforms(params, { gl, uniformLocations }) { + gl.uniformMatrix3fv(uniformLocations.u_matrix, false, params.matrix); + gl.uniform1f(uniformLocations.u_sizeRatio, params.sizeRatio); + gl.uniform1f(uniformLocations.u_correctionRatio, params.correctionRatio); + gl.uniform1f(uniformLocations.u_minEdgeThickness, params.minEdgeThickness); + gl.uniform1f(uniformLocations.u_feather, params.antiAliasingFeather); + } + }; +} + +export { EdgeHaloProgram, createCurveHaloProgram, createEdgeMarkerHeadProgram }; diff --git a/src/graph/export_svg.js b/src/graph/export_svg.js new file mode 100644 index 0000000..f918a39 --- /dev/null +++ b/src/graph/export_svg.js @@ -0,0 +1,799 @@ +/** + * Vector (SVG) export of the rendered graph scene (node-safe). + * + * WHY: the raster export (canvas snapshot) pixelates when embedded in + * papers/slides; an SVG document scales forever. WebGL has no vector + * readback, so this module re-derives the scene geometrically from the live + * sigma instance: post-reducer display data (getNode/EdgeDisplayData), + * framed→viewport projection and scaleSize give the exact on-screen CSS-px + * geometry, and each painter below replicates one renderer: + * + * - edges/halos/markers: edge_programs.js shader math (quadratic control + * point built in FRAMED space — the viewport y-flip changes handedness, + * so screen-space construction would mirror the curve); + * - nodes: sigma's circle/square programs, @sigma/node-border rings, + * the app's SVG texture quads ("shape") and @sigma/node-piechart slices; + * - labels/badges: label_renderers.js, including the baked-#000000 theme + * fallback and the upright-rotation normalization; + * - bubble groups: bubble_layer.js #drawGroup/#drawLabel. + * + * Split into collectSvgScene (sigma → flat primitive list) and + * primitivesToSvg (pure serializer) so vitest can assert geometry and markup + * independently. No sigma import, no DOM at module scope: the sigma instance + * and a measureText(text, font) function are injected (duck-typed). + * + * SECURITY: labels and colors originate from user Excel/JSON files. Every + * text node and attribute value is XML-escaped, and every paint value must + * pass SAFE_PAINT_RE (same policy as shape_textures.js) or it falls back to + * a neutral grey. 8-digit hex (#rrggbbaa) is converted to rgba() because + * several SVG viewers (and all pre-CSS4 ones) reject hex alpha. + */ +import { DEFAULTS } from "../config.js"; +import { outlineLabelAnchor } from "./bubble_geometry.js"; +import { placementVector, BAKED_DEFAULT_LABEL_COLOR } from "./label_renderers.js"; + +// Conservative paint-value allowlist (shape_textures.js SAFE_PAINT_RE): +// hex/rgb()/hsl()/named colors pass; anything that could break out of an +// attribute (quotes, angle brackets, ampersands, colons) is rejected. +// url(#localref) passes intentionally (harmless: the document carries no +// ); the missing ":" blocks url(javascript:…) and url(data:…). +const SAFE_PAINT_RE = /^[#a-zA-Z0-9(),.%\s-]+$/; +const FALLBACK_COLOR = "#999999"; + +// Geometry constants mirrored from the live renderers (kept literal here so +// this module never imports browser-only files; values are asserted by the +// visual-check pass, see tests). +const OUTLINE_STROKE_WIDTH = 2; // bubble_layer.js +const LABEL_STANDOFF_PX = 8; // bubble_layer.js +const BACKGROUND_RADIUS = 4; // label_renderers.js +const ANCHOR_GAP = 2; // label_renderers.js +const FALLBACK_LABEL_SIZE = 14; // label_renderers.js +const BADGE_TEXT_COLOR = "#FFFFFF"; +const FALLBACK_BADGE_COLOR = "#C33D35"; +const FALLBACK_BADGE_FONT_SIZE = 8; +const BADGE_PADDING = 2; +const BUBBLE_LABEL_FONT_FAMILY = "Arial, sans-serif"; // bubble_layer.js font string + +// edge_programs.js marker shader constants. +const DEFAULT_EDGE_CURVATURE = 0.25; // @sigma/edge-curve default +const MARKER_LENGTH_RATIO = 2.5; // sigma stock-arrow length/thickness +const MARKER_AUTO_BORDER_FRACTION = 0.2; // shader borderFraction +const TEE_MIN_BAR_PX = 1.5; // shader: max(l * 0.3, 1.5) +const FULL_TURN_EPS = 1e-4; // pie slice spanning ~2π renders as a disc + +const RAD_TO_DEG = 180 / Math.PI; + +// --- untrusted-input plumbing ---------------------------------------------- + +/** @returns {number} value rounded to 2 decimals (keeps SVG files small) */ +function round2(value) { + return Math.round(value * 100) / 100; +} + +// Compact decimal for a coordinate/length. Non-finite input (NaN radius from +// malformed style data) becomes "0": deterministic invisibility beats "NaN", +// an SVG parse error with viewer-dependent fallback. +function fmt(value) { + return Number.isFinite(value) ? String(round2(value)) : "0"; +} + +/** @returns {string} value with &, <, >, " and ' XML-escaped */ +function escapeXml(value) { + return String(value).replace(/[&<>"']/g, (ch) => { + if (ch === "&") return "&"; + if (ch === "<") return "<"; + if (ch === ">") return ">"; + if (ch === '"') return """; + return "'"; + }); +} + +/** + * Validate an untrusted paint value for embedding in an SVG attribute. + * Rejected values fall back to a neutral grey; 8-digit hex is rewritten to + * rgba() for viewer compatibility. + * + * @param {unknown} color user-derived CSS color + * @returns {string} a safe CSS color + */ +function safeColor(color) { + if (typeof color !== "string" || color.length === 0 || !SAFE_PAINT_RE.test(color)) { + return FALLBACK_COLOR; + } + const hex8 = /^#([0-9a-fA-F]{8})$/.exec(color); + if (hex8) { + const n = parseInt(hex8[1], 16); + const alpha = Math.round(((n & 255) / 255) * 1000) / 1000; + return `rgba(${(n >>> 24) & 255},${(n >>> 16) & 255},${(n >>> 8) & 255},${alpha})`; + } + return color; +} + +/** + * Whether a color paints anything (non-zero alpha). Only formats that can + * carry alpha are inspected; every other parseable format is opaque. + * + * @param {unknown} color + * @returns {boolean} + */ +function hasVisibleAlpha(color) { + if (typeof color !== "string" || color.length === 0) return false; + const hex8 = /^#[0-9a-fA-F]{6}([0-9a-fA-F]{2})$/.exec(color); + if (hex8) return parseInt(hex8[1], 16) > 0; + const hex4 = /^#[0-9a-fA-F]{3}([0-9a-fA-F])$/.exec(color); + if (hex4) return parseInt(hex4[1], 16) > 0; + const fn = /^(?:rgba|hsla)\([^)]*[,/]\s*([0-9.]+)%?\s*\)$/.exec(color); + if (fn) return parseFloat(fn[1]) > 0; + return true; +} + +// --- label color resolution (label_renderers.js parity) -------------------- + +/** @returns {number} a finite label size, falling back hard */ +function finiteSize(perElement, fromSettings) { + const size = perElement ?? fromSettings; + return Number.isFinite(size) ? size : FALLBACK_LABEL_SIZE; +} + +function resolveSettingsColor(settingsColor, data) { + if (settingsColor?.attribute) { + return data[settingsColor.attribute] || settingsColor.color || "#000"; + } + return settingsColor?.color ?? "#000"; +} + +function resolveElementLabelColor(elementColor, settingsColor, data) { + if (elementColor != null && elementColor !== BAKED_DEFAULT_LABEL_COLOR) { + return elementColor; + } + return resolveSettingsColor(settingsColor, data); +} + +// --- graph iteration (duck-typed: graphology or plain fake) ---------------- + +function eachNodeId(graph, fn) { + if (typeof graph.forEachNode === "function") { + graph.forEachNode((id) => fn(id)); + return; + } + for (const id of graph.nodes()) fn(id); +} + +function eachEdgeId(graph, fn) { + if (typeof graph.forEachEdge === "function") { + graph.forEachEdge((id, _attrs, source, target) => fn(id, source, target)); + return; + } + for (const id of graph.edges()) fn(id, graph.source(id), graph.target(id)); +} + +/** Stable ascending-zIndex order (Array.sort is stable per ES2019). */ +function sortByZIndex(records) { + return [...records].sort((a, b) => (a.data.zIndex ?? 0) - (b.data.zIndex ?? 0)); +} + +// --- scene environment ------------------------------------------------------ + +/** + * Which labels sigma actually rendered this frame. Sets of keys when the + * instance exposes them; null means "no API available — include every + * visible element that has a label". + */ +function displayedLabelSet(sigma, method, property) { + if (typeof sigma[method] === "function") return sigma[method]() ?? null; + return sigma[property] ?? null; +} + +function labelEnvironment(sigma, measureText) { + const get = (name) => sigma.getSetting?.(name); + return { + measureText, + renderLabels: get("renderLabels") !== false, + renderEdgeLabels: get("renderEdgeLabels") !== false, + labelFont: get("labelFont") ?? "Arial", + labelWeight: get("labelWeight") ?? "normal", + labelSize: get("labelSize"), + labelColor: get("labelColor"), + edgeLabelFont: get("edgeLabelFont") ?? "Arial", + edgeLabelWeight: get("edgeLabelWeight") ?? "normal", + edgeLabelSize: get("edgeLabelSize"), + edgeLabelColor: get("edgeLabelColor"), + nodeLabelSet: displayedLabelSet(sigma, "getNodeDisplayedLabels", "displayedNodeLabels"), + edgeLabelSet: displayedLabelSet(sigma, "getEdgeDisplayedLabels", "displayedEdgeLabels"), + }; +} + +// --- node/edge collection ---------------------------------------------------- + +/** @returns {Map} visible nodes in screen px */ +function collectNodes(sigma, graph) { + const nodes = new Map(); + eachNodeId(graph, (id) => { + const data = sigma.getNodeDisplayData(id); + if (!data || data.hidden) return; + const point = sigma.framedGraphToViewport({ x: data.x, y: data.y }); + nodes.set(id, { id, data, x: point.x, y: point.y, r: sigma.scaleSize(data.size) }); + }); + return nodes; +} + +/** + * Visible edges with both endpoints visible, projected to screen px. Curved + * edges carry the projected quadratic control point: it is constructed in + * FRAMED space (display-data coordinates) because the framed→viewport map + * flips y, which would mirror a control point built from screen deltas. + */ +function collectEdges(sigma, graph, nodes) { + const minThickness = sigma.getSetting?.("minEdgeThickness") ?? 1; + const edges = []; + eachEdgeId(graph, (id, sourceId, targetId) => { + const data = sigma.getEdgeDisplayData(id); + if (!data || data.hidden) return; + const source = nodes.get(sourceId); + const target = nodes.get(targetId); + if (!source || !target) return; // hidden or missing endpoint + const curved = data.type === "curve" || data.type === "styledCurve"; + let cp = null; + if (curved) { + const c = data.curvature ?? DEFAULT_EDGE_CURVATURE; + const dx = target.data.x - source.data.x; + const dy = target.data.y - source.data.y; + cp = sigma.framedGraphToViewport({ + x: (source.data.x + target.data.x) / 2 - dy * c, + y: (source.data.y + target.data.y) / 2 + dx * c, + }); + } + const thickness = Math.max(sigma.scaleSize(data.size || 1), minThickness); + edges.push({ id, data, source, target, cp, curved, thickness }); + }); + return edges; +} + +// --- edge primitives ---------------------------------------------------------- + +function edgeStrokePrimitive(edge, stroke, strokeWidth) { + if (edge.curved) { + const { source: s, target: t, cp } = edge; + const d = + `M ${fmt(s.x)} ${fmt(s.y)} ` + + `Q ${fmt(cp.x)} ${fmt(cp.y)} ${fmt(t.x)} ${fmt(t.y)}`; + return { kind: "path", d, fill: "none", stroke, strokeWidth }; + } + const { source: s, target: t } = edge; + return { kind: "line", x1: s.x, y1: s.y, x2: t.x, y2: t.y, stroke, strokeWidth }; +} + +/** + * Marker head for one extremity, replicating the edge_programs.js shader + * SDFs as polygons/circles (all in CSS screen px). + */ +function markerPrimitives(edge, extremity, sigma) { + const isSource = extremity === "source"; + const data = edge.data; + const code = (isSource ? data.startMarker : data.endMarker) || 0; + if (!code) return []; + + const marked = isSource ? edge.source : edge.target; + const toward = edge.curved ? edge.cp : isSource ? edge.target : edge.source; + const awayLen = Math.hypot(toward.x - marked.x, toward.y - marked.y); + if (!(awayLen > 0)) return []; + const away = { x: (toward.x - marked.x) / awayLen, y: (toward.y - marked.y) / awayLen }; + const n = { x: -away.y, y: away.x }; + + const markerSize = (isSource ? data.startMarkerSize : data.endMarkerSize) || 0; + const len = markerSize > 0 ? sigma.scaleSize(markerSize) : MARKER_LENGTH_RATIO * edge.thickness; + const halfW = markerSize > 0 ? sigma.scaleSize(markerSize) / 2 : edge.thickness; + const anchor = { + x: marked.x + away.x * sigma.scaleSize(marked.data.size), + y: marked.y + away.y * sigma.scaleSize(marked.data.size), + }; + const at = (t, u) => ({ x: anchor.x + away.x * t + n.x * u, y: anchor.y + away.y * t + n.y * u }); + + const fill = safeColor((isSource ? data.startMarkerColor : data.endMarkerColor) ?? data.color); + const prim = markerShape(code, anchor, at, len, halfW, fill); + + const borderColor = isSource ? data.startMarkerBorderColor : data.endMarkerBorderColor; + if (borderColor != null) { + const borderSize = (isSource ? data.startMarkerBorderSize : data.endMarkerBorderSize) || 0; + prim.stroke = safeColor(borderColor); + // Approximation of the shader's INSIDE border band (an SVG stroke + // straddles the outline; the GLSL border lies fully within the SDF). + prim.strokeWidth = + borderSize > 0 + ? sigma.scaleSize(borderSize) + : MARKER_AUTO_BORDER_FRACTION * Math.min(2 * halfW, len); + } + return [prim]; +} + +/** One marker body per EDGE_MARKERS code (graph_model.js vocabulary). */ +function markerShape(code, anchor, at, len, halfW, fill) { + if (code === 2) { + return { kind: "polygon", points: [at(0, -halfW), at(0, halfW), at(len, halfW), at(len, -halfW)], fill }; + } + if (code === 3) { + return { kind: "polygon", points: [anchor, at(len / 2, halfW), at(len, 0), at(len / 2, -halfW)], fill }; + } + if (code === 4) { + const center = at(len / 2, 0); + return { kind: "circle", cx: center.x, cy: center.y, r: Math.min(2 * halfW, len) / 2, fill }; + } + if (code === 5) { + const bar = Math.max(len * 0.3, TEE_MIN_BAR_PX); + return { kind: "polygon", points: [at(0, -halfW), at(0, halfW), at(bar, halfW), at(bar, -halfW)], fill }; + } + // arrow (code 1; unknown codes degrade to it like the shader's first branch) + return { kind: "polygon", points: [anchor, at(len, -halfW), at(len, halfW)], fill }; +} + +/** Halo underdraw + body + marker heads for one edge. */ +function edgePrimitives(edge, sigma) { + const prims = []; + const styled = edge.data.type === "styledLine" || edge.data.type === "styledCurve"; + if (styled && edge.data.haloWidth > 0) { + const haloWidth = sigma.scaleSize((edge.data.size || 1) + 2 * edge.data.haloWidth); + prims.push(edgeStrokePrimitive(edge, safeColor(edge.data.haloColor ?? edge.data.color), haloWidth)); + } + prims.push(edgeStrokePrimitive(edge, safeColor(edge.data.color), edge.thickness)); + if (styled) { + prims.push(...markerPrimitives(edge, "source", sigma)); + prims.push(...markerPrimitives(edge, "target", sigma)); + } + return prims; +} + +// --- node primitives ----------------------------------------------------------- + +/** + * Plain disc, or @sigma/node-border rings when borderRatio > 0 (the border + * is the OUTER borderRatio fraction of the radius — graph_model.js bakes + * lineWidth/radius into the attr). + */ +function circleNodePrimitives({ data, x, y, r }) { + const fill = safeColor(data.color); + const ratio = data.borderRatio; + if (Number.isFinite(ratio) && ratio > 0) { + return [ + { kind: "circle", cx: x, cy: y, r, fill: safeColor(data.borderColor) }, + { kind: "circle", cx: x, cy: y, r: r * (1 - Math.min(ratio, 1)), fill }, + ]; + } + return [{ kind: "circle", cx: x, cy: y, r, fill }]; +} + +/** + * Texture node: the app's own SVG data URI as an quad. A visible + * display color (state halos use drawingMode "background") gets a disc + * underneath, mirroring the image program's background pass. + */ +// Only the app's own texture URIs (shapeTextureURI) may embed: javascript:, +// http(s): and other data: MIME types are dropped, so a future user-supplied +// node image can never become a script-execution or tracking vector. +const SAFE_IMAGE_HREF_RE = /^data:image\/svg\+xml,/; + +function shapeNodePrimitives({ data, x, y, r }) { + const prims = []; + if (hasVisibleAlpha(data.color)) { + prims.push({ kind: "circle", cx: x, cy: y, r, fill: safeColor(data.color) }); + } + if (typeof data.image === "string" && SAFE_IMAGE_HREF_RE.test(data.image)) { + prims.push({ kind: "image", href: data.image, x: x - r, y: y - r, width: 2 * r, height: 2 * r }); + } + return prims; +} + +/** + * One wedge path. Slice angles are GRAPH-space CCW from +x; the screen point + * negates y, so on the y-down screen the arc traces visually clockwise — + * which in SVG's y-down convention is sweep flag 0. + */ +function pieWedgePath(cx, cy, r, a0, a1) { + const p0 = { x: cx + r * Math.cos(a0), y: cy - r * Math.sin(a0) }; + const p1 = { x: cx + r * Math.cos(a1), y: cy - r * Math.sin(a1) }; + const largeArc = a1 - a0 > Math.PI ? 1 : 0; + return ( + `M ${fmt(cx)} ${fmt(cy)} L ${fmt(p0.x)} ${fmt(p0.y)} ` + + `A ${fmt(r)} ${fmt(r)} 0 ${largeArc} 0 ${fmt(p1.x)} ${fmt(p1.y)} Z` + ); +} + +/** @sigma/node-piechart parity: pieValue0..N-1 / pieColor0..N-1 slices. */ +function pieNodePrimitives({ data, x, y, r }) { + let total = 0; + const slices = []; + for (let k = 0; k < DEFAULTS.NODE.PIE.MAX_SLICES; k++) { + const raw = data[`pieValue${k}`]; + const value = Number.isFinite(raw) && raw > 0 ? raw : 0; + slices.push({ value, color: data[`pieColor${k}`] ?? DEFAULTS.NODE.PIE.DEFAULT_COLOR }); + total += value; + } + if (total <= 0) { + return [{ kind: "circle", cx: x, cy: y, r, fill: safeColor(DEFAULTS.NODE.PIE.DEFAULT_COLOR) }]; + } + const prims = []; + let angle = 0; + for (const slice of slices) { + if (slice.value <= 0) continue; + const start = angle; + angle += (slice.value * 2 * Math.PI) / total; + if (!hasVisibleAlpha(slice.color)) continue; + const fill = safeColor(slice.color); + if (angle - start >= 2 * Math.PI - FULL_TURN_EPS) { + prims.push({ kind: "circle", cx: x, cy: y, r, fill }); + } else { + prims.push({ kind: "path", d: pieWedgePath(x, y, r, start, angle), fill }); + } + } + return prims; +} + +function nodePrimitives(node) { + const type = node.data.type; + // NOTE for the visual-check pass: sigma's square program spans the FULL + // node size as the half-side, so the square circumscribes the equivalent + // disc rather than inscribing it. + if (type === "square") { + const { data, x, y, r } = node; + return [{ kind: "rect", x: x - r, y: y - r, width: 2 * r, height: 2 * r, fill: safeColor(data.color) }]; + } + if (type === "shape") return shapeNodePrimitives(node); + if (type === "pie") return pieNodePrimitives(node); + return circleNodePrimitives(node); // "circle", "borderCircle", default +} + +// --- label primitives ------------------------------------------------------------ + +function textPrimitive(x, y, text, fill, fontSize, fontFamily, fontWeight) { + return { kind: "text", x, y, text, fill, fontSize, fontFamily, fontWeight }; +} + +/** drawNodeBadges parity: colored pill + white text on the node perimeter. */ +function badgePrimitives(node, env) { + const { data, x, y, r } = node; + if (!data.badge || !Array.isArray(data.badges) || data.badges.length === 0) return []; + const fontSize = Number.isFinite(data.badgeFontSize) ? data.badgeFontSize : FALLBACK_BADGE_FONT_SIZE; + const scale = + Number.isFinite(data.badgeScaleFactor) && data.badgeScaleFactor > 0 ? data.badgeScaleFactor : 1; + const size = fontSize * scale; + const font = `bold ${size}px ${env.labelFont}`; + + const prims = []; + data.badges.forEach((badge, index) => { + const text = badge?.text == null ? "" : String(badge.text); + if (!text) return; + const boxWidth = env.measureText(text, font) + 2 * BADGE_PADDING; + const boxHeight = size + 2 * BADGE_PADDING; + const [ux, uy] = placementVector(badge.placement); + const norm = Math.hypot(ux, uy) || 1; + const cx = x + (ux / norm) * r; + const cy = y + (uy / norm) * r; + prims.push({ + kind: "rect", + x: cx - boxWidth / 2, + y: cy - boxHeight / 2, + width: boxWidth, + height: boxHeight, + rx: boxHeight / 2, // pill: fully rounded ends + fill: safeColor(data.badgePalette?.[index] ?? FALLBACK_BADGE_COLOR), + }); + prims.push(textPrimitive(cx, cy + size * 0.35, text, BADGE_TEXT_COLOR, size, env.labelFont, "bold")); + }); + return prims; +} + +/** drawNodeLabel parity (background + text + badges). */ +function nodeLabelPrimitives(node, env) { + const { data, x, y, r } = node; + if (!data.label) return []; + const size = finiteSize(data.labelSize, env.labelSize); + const font = `${env.labelWeight} ${size}px ${env.labelFont}`; + const color = safeColor(resolveElementLabelColor(data.labelColor, env.labelColor, data)); + const padding = data.labelPadding ?? 2; + const boxWidth = env.measureText(data.label, font) + 2 * padding; + const boxHeight = size + 2 * padding; + + const [ux, uy] = placementVector(data.labelPlacement); + const cx = x + ux * (r + ANCHOR_GAP + boxWidth / 2) + (data.labelOffsetX ?? 0); + const cy = y + uy * (r + ANCHOR_GAP + boxHeight / 2) + (data.labelOffsetY ?? 0); + + const prims = []; + if (data.labelBackground && data.labelBackgroundColor) { + prims.push({ + kind: "rect", + x: cx - boxWidth / 2, + y: cy - boxHeight / 2, + width: boxWidth, + height: boxHeight, + rx: BACKGROUND_RADIUS, + fill: safeColor(data.labelBackgroundColor), + }); + } + prims.push(textPrimitive(cx, cy + size * 0.35, data.label, color, size, env.labelFont, env.labelWeight)); + prims.push(...badgePrimitives(node, env)); // badges follow label visibility + return prims; +} + +/** + * Label anchor + tangent for an edge. Curved edges use the bezier point at + * t = 0.5 (= 0.25·S + 0.5·CP + 0.25·T) whose tangent is exactly T − S — + * an approximation of @sigma/edge-curve's path-following label drawer. + */ +function edgeLabelAnchor(edge) { + const { source: s, target: t, cp, data } = edge; + const offsetX = data.labelOffsetX ?? 0; + const offsetY = data.labelOffsetY ?? 0; + const tangent = { x: t.x - s.x, y: t.y - s.y }; + if (edge.curved) { + return { + x: 0.25 * s.x + 0.5 * cp.x + 0.25 * t.x + offsetX, + y: 0.25 * s.y + 0.5 * cp.y + 0.25 * t.y + offsetY, + tangent, + }; + } + const frac = { start: 0.2, center: 0.5, end: 0.8 }[data.labelPlacement] ?? 0.5; + return { x: s.x + tangent.x * frac + offsetX, y: s.y + tangent.y * frac + offsetY, tangent }; +} + +/** drawEdgeLabel parity: translated/rotated group with background + text. */ +function edgeLabelPrimitives(edge, env) { + const data = edge.data; + if (!data.label) return []; + const size = finiteSize(data.labelSize, env.edgeLabelSize); + const font = `${env.edgeLabelWeight} ${size}px ${env.edgeLabelFont}`; + const color = safeColor(resolveElementLabelColor(data.labelColor, env.edgeLabelColor, data)); + const padding = data.labelPadding ?? 1; + const width = env.measureText(data.label, font); + const { x, y, tangent } = edgeLabelAnchor(edge); + + let angle = 0; + if (data.labelAutoRotate) { + angle = Math.atan2(tangent.y, tangent.x); + // Keep text upright; range (-π/2, π/2] (label_renderers.js). + if (angle > Math.PI / 2) angle -= Math.PI; + else if (angle <= -Math.PI / 2) angle += Math.PI; + } + + const children = []; + if (data.labelBackground && data.labelBackgroundColor) { + children.push({ + kind: "rect", + x: -width / 2 - padding, + y: -size / 2 - padding, + width: width + 2 * padding, + height: size + 2 * padding, + rx: BACKGROUND_RADIUS, + fill: safeColor(data.labelBackgroundColor), + }); + } + children.push(textPrimitive(0, size * 0.35, data.label, color, size, env.edgeLabelFont, env.edgeLabelWeight)); + return [ + { + kind: "group", + transform: `translate(${fmt(x)} ${fmt(y)}) rotate(${fmt(angle * RAD_TO_DEG)})`, + children, + }, + ]; +} + +// --- bubble group primitives --------------------------------------------------- + +/** bubble_layer #drawGroup parity: closed body polygon + 2px outline. */ +function bubbleBodyPrimitives({ points, opts = {}, defaults = {} }) { + if (!points || points.length < 2) return []; + const d = points.map((p, i) => `${i === 0 ? "M" : "L"} ${fmt(p.x)} ${fmt(p.y)}`).join(" ") + " Z"; + return [ + { + kind: "path", + d, + fill: safeColor(opts.fill ?? defaults.fill ?? "#403C53"), + fillOpacity: opts.fillOpacity ?? defaults.fillOpacity ?? 0.25, + stroke: safeColor(opts.stroke ?? defaults.stroke ?? "#403C53"), + strokeWidth: OUTLINE_STROKE_WIDTH, + strokeOpacity: opts.strokeOpacity ?? defaults.strokeOpacity ?? 1, + }, + ]; +} + +/** + * bubble_layer #drawLabel parity. The live layer gates on the manager-merged + * opts.label; the export receives raw opts + defaults, so the gate resolves + * through the same opts ?? defaults chain as every other label option. + */ +function bubbleLabelPrimitives({ points, opts = {}, defaults = {} }, measureText) { + if (!points || points.length < 2) return []; + if (!(opts.label ?? defaults.label)) return []; + const text = String(opts.labelText ?? defaults.labelText ?? ""); + if (!text) return []; + const placement = opts.labelPlacement ?? defaults.labelPlacement ?? "bottom"; + const closeToPath = opts.labelCloseToPath ?? defaults.labelCloseToPath ?? true; + const autoRotate = opts.labelAutoRotate ?? defaults.labelAutoRotate ?? true; + const anchor = outlineLabelAnchor(points, placement); + if (!anchor) return []; + + const fontSize = opts.labelFontSize ?? defaults.labelFontSize ?? 12; + const padding = opts.labelPadding ?? defaults.labelPadding ?? 2; + const standoff = closeToPath ? 0 : fontSize / 2 + padding + LABEL_STANDOFF_PX; + const x = anchor.x + anchor.nx * standoff + (opts.labelOffsetX ?? 0); + const y = anchor.y + anchor.ny * standoff + (opts.labelOffsetY ?? 0); + const textWidth = measureText(text, `${fontSize}px ${BUBBLE_LABEL_FONT_FAMILY}`); + + const rotated = autoRotate && closeToPath && placement !== "center"; + const lx = rotated ? 0 : x; + const ly = rotated ? 0 : y; + + const prims = []; + if (opts.labelBackground ?? defaults.labelBackground) { + prims.push({ + kind: "rect", + x: lx - textWidth / 2 - padding, + y: ly - fontSize / 2 - padding, + width: textWidth + 2 * padding, + height: fontSize + 2 * padding, + rx: opts.labelBackgroundRadius ?? defaults.labelBackgroundRadius ?? 5, + fill: safeColor(opts.labelBackgroundFill ?? defaults.labelBackgroundFill ?? "#403C53"), + }); + } + prims.push( + textPrimitive( + lx, + ly + fontSize * 0.35, + text, + safeColor(opts.labelFill ?? defaults.labelFill ?? "#fff"), + fontSize, + BUBBLE_LABEL_FONT_FAMILY, + "normal", + ), + ); + if (!rotated) return prims; + return [ + { + kind: "group", + transform: `translate(${fmt(x)} ${fmt(y)}) rotate(${fmt(anchor.angle * RAD_TO_DEG)})`, + children: prims, + }, + ]; +} + +// --- scene collection ---------------------------------------------------------- + +/** + * Collect the full scene as a flat array of typed primitives, in draw order: + * bubble bodies → edges → nodes → edge labels → node labels (+badges) → + * bubble labels. (The background rect is the serializer's job.) + * + * @param {object} args same shape as buildGraphSvg (background unused here) + * @returns {Array} primitives ({kind: "rect"|"circle"|"path"| + * "polygon"|"line"|"image"|"text"|"group", ...}) + */ +function collectSvgScene({ sigma, graph, bubbleGroups = [], measureText }) { + const env = labelEnvironment(sigma, measureText); + const nodes = collectNodes(sigma, graph); + const edges = sortByZIndex(collectEdges(sigma, graph, nodes)); + const sortedNodes = sortByZIndex([...nodes.values()]); + + const prims = []; + for (const group of bubbleGroups) prims.push(...bubbleBodyPrimitives(group)); + for (const edge of edges) prims.push(...edgePrimitives(edge, sigma)); + for (const node of sortedNodes) prims.push(...nodePrimitives(node)); + if (env.renderEdgeLabels) { + for (const edge of edges) { + if (env.edgeLabelSet && !env.edgeLabelSet.has(edge.id)) continue; + prims.push(...edgeLabelPrimitives(edge, env)); + } + } + if (env.renderLabels) { + for (const node of sortedNodes) { + if (env.nodeLabelSet && !env.nodeLabelSet.has(node.id)) continue; + prims.push(...nodeLabelPrimitives(node, env)); + } + } + for (const group of bubbleGroups) prims.push(...bubbleLabelPrimitives(group, measureText)); + return prims; +} + +// --- serialization --------------------------------------------------------------- + +/** Shared fill/stroke/opacity attribute fragment. */ +function paintAttrs(p) { + let s = ""; + if (p.fill !== undefined) s += ` fill="${escapeXml(p.fill)}"`; + if (p.fillOpacity !== undefined) s += ` fill-opacity="${fmt(p.fillOpacity)}"`; + if (p.stroke !== undefined) s += ` stroke="${escapeXml(p.stroke)}"`; + if (p.strokeWidth !== undefined) s += ` stroke-width="${fmt(p.strokeWidth)}"`; + if (p.strokeOpacity !== undefined) s += ` stroke-opacity="${fmt(p.strokeOpacity)}"`; + return s; +} + +function serializePrimitive(p) { + if (p.kind === "rect") { + const rx = p.rx !== undefined ? ` rx="${fmt(p.rx)}"` : ""; + return ``; + } + if (p.kind === "circle") { + return ``; + } + if (p.kind === "line") { + return ``; + } + if (p.kind === "path") { + return ``; + } + if (p.kind === "polygon") { + const points = p.points.map((pt) => `${fmt(pt.x)},${fmt(pt.y)}`).join(" "); + return ``; + } + if (p.kind === "image") { + return ``; + } + if (p.kind === "text") { + return ( + `${escapeXml(p.text)}` + ); + } + if (p.kind === "group") { + return `${p.children.map(serializePrimitive).join("")}`; + } + throw new Error(`export_svg: unknown primitive kind "${p.kind}"`); +} + +/** + * Serialize primitives into a standalone SVG document. + * + * @param {Array} primitives collectSvgScene output + * @param {{width: number, height: number}} dims CSS px + * @param {string} background CSS color for the page rect + * @returns {string} + */ +function primitivesToSvg(primitives, dims, background) { + const w = fmt(dims.width); + const h = fmt(dims.height); + const parts = [ + ``, + ``, + ]; + for (const p of primitives) parts.push(serializePrimitive(p)); + parts.push(""); + return parts.join("\n"); +} + +// --- public API ------------------------------------------------------------------- + +/** + * Build a standalone SVG document of the current scene. + * + * @param {object} args + * @param {object} args.sigma live Sigma instance (duck-typed) + * @param {object} args.graph graphology graph (nodes()/edges()/source()/target() or forEach*) + * @param {{width: number, height: number}} args.dims CSS px + * @param {string} args.background CSS color for the page rect + * @param {Array<{group: string, points: Array<{x: number, y: number}>, opts: object, defaults: object}>} args.bubbleGroups + * @param {(text: string, font: string) => number} args.measureText + * @returns {string} standalone SVG document + */ +function buildGraphSvg(args) { + if (!args || typeof args !== "object") { + throw new TypeError("buildGraphSvg: args object required"); + } + const { sigma, graph, dims, measureText } = args; + if (!sigma || typeof sigma.getNodeDisplayData !== "function") { + throw new TypeError("buildGraphSvg: a sigma instance with getNodeDisplayData is required"); + } + if (!graph) throw new TypeError("buildGraphSvg: graph is required"); + if ( + !dims || + !Number.isFinite(dims.width) || + !Number.isFinite(dims.height) || + dims.width <= 0 || + dims.height <= 0 + ) { + throw new TypeError("buildGraphSvg: dims must have positive finite width/height"); + } + if (typeof measureText !== "function") { + throw new TypeError("buildGraphSvg: measureText function is required"); + } + return primitivesToSvg(collectSvgScene(args), dims, args.background); +} + +export { buildGraphSvg, collectSvgScene, primitivesToSvg }; diff --git a/src/graph/filter.js b/src/graph/filter.js index 831911c..66bcdde 100644 --- a/src/graph/filter.js +++ b/src/graph/filter.js @@ -124,20 +124,22 @@ class GraphFilterManager { } async updateElementVisibility(idsToShow, idsToHide) { + // cache.graph is null both before any data is loaded and when WebGL init + // failed (dead renderer); either way there is nothing to show/hide. + if (!this.cache.graph) return; + this.cache.visibleElementsChanged = false; + // Current visibility comes from the graphology `hidden` attrs, surfaced + // as style.visibility by the renderer facade (sigma migration, Phase 1). const { nodes, edges } = await this.cache.graph.getData(); - const { visible, hidden } = [...nodes, ...edges].reduce( - (acc, item) => { - acc[item.style.visibility === "visible" ? "visible" : "hidden"].push( - item.id, - ); - return acc; - }, - { visible: [], hidden: [] }, - ); + const visible = new Set(); + const hidden = new Set(); + for (const item of [...nodes, ...edges]) { + (item.style.visibility === "visible" ? visible : hidden).add(item.id); + } - const showElementsDiff = idsToShow.filter((id) => hidden.includes(id)); - const hideElementsDiff = idsToHide.filter((id) => visible.includes(id)); + const showElementsDiff = idsToShow.filter((id) => hidden.has(id)); + const hideElementsDiff = idsToHide.filter((id) => visible.has(id)); if (showElementsDiff.length > 0) { await this.cache.graph.showElement(showElementsDiff); diff --git a/src/graph/flow_animator.js b/src/graph/flow_animator.js new file mode 100644 index 0000000..959981f --- /dev/null +++ b/src/graph/flow_animator.js @@ -0,0 +1,81 @@ +/** + * Drives the edge-flow animation (browser-only — imports the flow programs, + * which import the sigma bundle; must never be loaded under node/vitest). + * + * One instance per SigmaAdapter. While at least one visible edge carries a + * positive flowMode AND the document is visible, a rAF loop advances the + * shared flowClock and asks sigma for a redraw-only refresh + * (skipIndexation: true — buffers untouched, the flow program's setUniforms + * re-reads the clock). Zero work otherwise: graphology edge events only flip + * a dirty flag, the actual someEdge rescan is deferred to one rAF so bulk + * style updates (N mergeEdgeAttributes → N events) pay for a single scan. + */ +import { flowClock } from "./edge_flow_programs.js"; + +// Graphology events that can change whether any edge flows. +const GRAPH_EVENTS = ["edgeAttributesUpdated", "edgeAdded", "edgeDropped", "edgesCleared", "cleared"]; + +// flowClock.time wrap, keeping the shader's highp fract() argument small on +// long sessions. 3600 s is a whole number of pattern cycles for every +// slider-step speed (0.2 increments × 40 px/s over 16/48 px periods), so +// wrapping is seamless there; exotic hand-set speeds get at most one phase +// jump per hour. +const TIME_WRAP_S = 3600; + +class FlowAnimator { + /** @param {import("./sigma_adapter.js").SigmaAdapter} adapter */ + constructor(adapter) { + this.adapter = adapter; + this.graph = adapter.graph; + this.killed = false; + this.rafId = null; + // Lazily-refreshed "does any visible edge flow" answer. + this.dirty = true; + this.hasFlow = false; + + this.onGraphChange = () => { + this.dirty = true; + this.#schedule(); + }; + this.onVisibilityChange = () => this.#schedule(); + + for (const event of GRAPH_EVENTS) this.graph.on(event, this.onGraphChange); + document.addEventListener("visibilitychange", this.onVisibilityChange); + this.#schedule(); + } + + destroy() { + this.killed = true; + if (this.rafId !== null) cancelAnimationFrame(this.rafId); + this.rafId = null; + for (const event of GRAPH_EVENTS) this.graph.off(event, this.onGraphChange); + document.removeEventListener("visibilitychange", this.onVisibilityChange); + // A successor adapter's animator starts from a fresh clock. + flowClock.time = 0; + } + + /** Single rAF entry point for ticking AND re-evaluating (never doubled). */ + #schedule() { + if (this.killed || this.rafId !== null) return; + this.rafId = requestAnimationFrame(this.#tick); + } + + #tick = (now) => { + this.rafId = null; + if (this.killed) return; + if (this.dirty) { + this.hasFlow = this.graph.someEdge((_, attrs) => attrs.flowMode > 0 && !attrs.hidden); + this.dirty = false; + } + // Hidden tab: stop dead (visibilitychange reschedules); browsers throttle + // background rAF anyway, but an explicit pause keeps the contract clear. + if (!this.hasFlow || document.visibilityState !== "visible") return; + + // rAF timestamps are DOMHighResTimeStamp milliseconds → seconds. + flowClock.time = (now / 1000) % TIME_WRAP_S; + this.adapter.sigma.refresh({ skipIndexation: true }); + this.#schedule(); + }; +} + +export { FlowAnimator }; diff --git a/src/graph/graph_model.js b/src/graph/graph_model.js new file mode 100644 index 0000000..3a1c2f4 --- /dev/null +++ b/src/graph/graph_model.js @@ -0,0 +1,702 @@ +/** + * Node-safe graph model for the Sigma.js renderer (MIGRATION.md Phases 1-2). + * + * Builds the graphology instance from the app cache and provides the + * G6-style → sigma attribute mapping plus the node/edge reducer factories. + * Must never import the sigma bundle (directly or transitively) — vitest + * imports this module under node. + */ +import { Graph } from "../lib/graphology.bundle.mjs"; +import { DEFAULTS } from "../config.js"; +import { shapeTextureURI, isTextureOnlyShape, HALO_EXTRA_PX } from "./shape_textures.js"; +import { pieAttributesFromSlices } from "./pie_slices.js"; + +// Element interaction-state colors (former G6 state spec) live in config so +// the styling UI and the reducers share one source. +const STATE_ACCENT_COLOR = DEFAULTS.STATE.ACCENT_COLOR; +const STATE_DIM_COLOR = DEFAULTS.STATE.DIM_COLOR; + +// Texture nodes paint their fill inside the SVG; the sigma `color` attribute +// must be fully transparent or the image quad shows a colored square. +const TRANSPARENT = "#00000000"; + +/** + * The model boundary owns the y-axis convention flip: the app model (G6 + * heritage: nodeRef styles, persisted positions, Excel/JSON files) is + * y-down, sigma/graphology is y-up. Negate exactly once when crossing in + * either direction so legacy files keep their orientation and save→load + * round-trips are stable. + */ +function flipY(y) { + return -y; +} + +/** + * Map a G6 node style + type to sigma node attributes. + * Only emits keys that are actually present on the style; shape-program + * attributes (`type`/`shape`/`image`/...) are only emitted when `type` is + * given. Shapes without a native sigma program — and any non-circle shape + * with a border, which the native circle/square programs cannot draw — + * render through the SVG texture program ("shape"); bordered circles render + * through the @sigma/node-border GLSL program ("borderCircle"). + * + * @param {object} style G6 node style ({x, y, size, fill, stroke, lineWidth, label*, visibility, ...}) + * @param {string} [type] G6 node type (circle|diamond|hexagon|rect|triangle|star) + * @returns {object} partial sigma attrs + */ +function nodeAttributesFromStyle(style = {}, type = undefined) { + const attrs = {}; + if (Number.isFinite(style.x)) attrs.x = style.x; + if (Number.isFinite(style.y)) attrs.y = flipY(style.y); + if (style.size !== undefined) { + // G6 size is a diameter (or [w, h]); sigma size is a radius. + attrs.size = (Array.isArray(style.size) ? style.size[0] : style.size) / 2; + } + if (style.fill !== undefined) attrs.color = style.fill; + if (style.stroke !== undefined) attrs.borderColor = style.stroke; + if (style.lineWidth !== undefined) attrs.borderSize = style.lineWidth; + + if (style.label === false) { + attrs.label = null; + } else if (style.label && style.labelText !== undefined) { + attrs.label = style.labelText == null ? null : String(style.labelText); + } + Object.assign(attrs, labelStyleAttributes(style)); + Object.assign(attrs, badgeAttributes(style)); + if (style.visibility !== undefined) { + attrs.hidden = style.visibility === "hidden"; + } + + if (type !== undefined) Object.assign(attrs, nodeProgramAttributes(style, type)); + + // Pie-chart override: orthogonal to the shape vocabulary — a non-empty + // pieSlices list routes the node to the @sigma/node-piechart program + // (type "pie") regardless of its underlying shape. Clearing pie (empty/absent + // pieSlices) leaves the shape attrs above in force. The stale texture attrs + // are nulled so a shape→pie switch can't smuggle a leftover image quad. + if (Array.isArray(style.pieSlices) && style.pieSlices.length > 0) { + Object.assign( + attrs, + pieAttributesFromSlices(style.pieSlices, DEFAULTS.NODE.PIE.MAX_SLICES, DEFAULTS.NODE.PIE.DEFAULT_COLOR), + ); + attrs.image = null; + attrs.fillColor = null; + attrs.borderRatio = 0; + } + return attrs; +} + +/** + * Badge attrs (read by drawNodeLabel). Emitted whenever the style carries + * explicit badge fields — including badge:false / empty arrays — because the + * adapter merges attributes; omitting the keys on a badge_clear would leave + * stale badges in graphology. Missing palette entries get the default badge + * color baked in so the renderer needs no config import. + */ +function badgeAttributes(style) { + if (style.badge === undefined && style.badges === undefined) return {}; + const badges = style.badge ? (style.badges ?? []) : []; + const attrs = { + badge: badges.length > 0, + badges, + badgePalette: badges.map((_, i) => style.badgePalette?.[i] ?? DEFAULTS.NODE.BADGE.COLOR), + }; + if (badges.length > 0) { + attrs.badgeFontSize = style.badgeFontSize ?? DEFAULTS.NODE.BADGE.FONT_SIZE; + attrs.badgeScaleFactor = badgeScaleFactor(style); + } + return attrs; +} + +/** + * Zoom-independent badge scale factor, baked here (not in the renderer, which + * only sees zoom-scaled display data and stays config-free). When + * `badgeScaleWithNode` is on, badges grow/shrink with the node's model size + * relative to the default node size; otherwise the factor is 1 (current + * behavior). Recomputed on every restyle because the merged ref style always + * carries `size` alongside the badge keys. + * + * @param {object} style G6 node style ({size, badgeScaleWithNode, ...}) + * @returns {number} multiplier applied to badgeFontSize by the renderer + */ +function badgeScaleFactor(style) { + const scaleWithNode = style.badgeScaleWithNode ?? DEFAULTS.NODE.BADGE.SCALE_WITH_NODE; + if (!scaleWithNode) return 1; + const diameter = Array.isArray(style.size) ? style.size[0] : style.size; + return Number.isFinite(diameter) && diameter > 0 ? diameter / DEFAULTS.NODE.SIZE : 1; +} + +/** + * Shape-program attributes for a node: which sigma program draws it, plus + * the texture data-URI when the SVG shape program is needed. + * + * Three programs and their attribute sets (the adapter applies updates via + * mergeNodeAttributes, so every branch must overwrite/clear exactly what the + * other branches set — a stale fillColor corrupts state textures on hover, a + * stale TRANSPARENT color makes the node invisible, a stale image would + * matter if the texture program saw it; the image program skips non-string + * images, so null is safe): + * - "shape" texture (fillColor, TRANSPARENT color, image, borderRatio 0) + * - "borderCircle" @sigma/node-border GLSL rings — bordered circles only + * (color=fill, borderRatio, fillColor/image cleared) + * - native circle/square (color=fill, fillColor/image cleared, borderRatio 0) + */ +function nodeProgramAttributes(style = {}, type) { + const fill = style.fill ?? DEFAULTS.NODE.FILL_COLOR; + const stroke = style.stroke ?? null; + const lineWidth = style.lineWidth ?? 0; + const hasBorder = Boolean(stroke) && lineWidth > 0; + const size = Array.isArray(style.size) ? style.size[0] : style.size; + const radius = (size ?? DEFAULTS.NODE.SIZE) / 2; + const attrs = { shape: type }; + + if (isTextureOnlyShape(type) || (hasBorder && type !== "circle")) { + attrs.type = "shape"; + attrs.fillColor = fill; + attrs.color = TRANSPARENT; + attrs.image = shapeTextureURI({ + shape: type, + fill, + stroke: hasBorder ? stroke : null, + lineWidth: hasBorder ? lineWidth : 0, + size: radius, + }); + attrs.borderRatio = 0; + } else if (hasBorder) { + // Bordered circle: the node-border program draws border + fill as GLSL + // rings (crisp at all zooms, no texture atlas churn). The border ring is + // a fraction of the radius so it scales with zoom exactly like the baked + // textures (and G6) did. State halos still go through the texture path — + // applyNodeState reads fillColor ?? color / borderColor / borderSize, + // all coherent here. + attrs.type = "borderCircle"; + attrs.color = fill; + attrs.fillColor = null; + attrs.image = null; + attrs.borderRatio = radius > 0 ? Math.min(lineWidth / radius, 1) : 1; + } else { + attrs.type = type === "rect" ? "square" : "circle"; + attrs.color = fill; + attrs.fillColor = null; + attrs.image = null; + attrs.borderRatio = 0; + // Unconditionally clear border attrs: a style delta that drops the border + // without an explicit stroke key (e.g. {lineWidth: 0} on the no-nodeRef + // fallback path) would otherwise leave a stale borderColor in graphology, + // which applyNodeState bakes into halo textures. + attrs.borderColor = null; + attrs.borderSize = 0; + } + return attrs; +} + +/** + * Shared label styling attrs (read by the custom label renderers). + * G6 names → renderer attrs; only present keys are emitted. + */ +function labelStyleAttributes(style) { + const attrs = {}; + if (style.labelFontSize !== undefined) attrs.labelSize = style.labelFontSize; + if (style.labelFill !== undefined) attrs.labelColor = style.labelFill; + if (style.labelBackground !== undefined) attrs.labelBackground = style.labelBackground; + if (style.labelBackgroundFill !== undefined) attrs.labelBackgroundColor = style.labelBackgroundFill; + if (style.labelPlacement !== undefined) attrs.labelPlacement = style.labelPlacement; + if (style.labelOffsetX !== undefined) attrs.labelOffsetX = style.labelOffsetX; + if (style.labelOffsetY !== undefined) attrs.labelOffsetY = style.labelOffsetY; + if (style.labelPadding !== undefined) attrs.labelPadding = style.labelPadding; + if (style.labelAutoRotate !== undefined) attrs.labelAutoRotate = style.labelAutoRotate; + return attrs; +} + +/** + * Edge end-marker vocabulary. The numeric codes are the `startMarker` / + * `endMarker` float attrs consumed by the WebGL marker-head program + * (edge_programs.js), which selects the SDF in its fragment shader: + * arrow (directional triangle), rect, diamond, circle, + * tee (⊣ inhibition bar, pharmacology-style). + * Legacy G6 arrow-type names map onto the nearest new marker so old files + * keep rendering; the original string still round-trips via the edge style. + */ +const EDGE_MARKERS = { arrow: 1, rect: 2, diamond: 3, circle: 4, tee: 5 }; +const LEGACY_MARKER_ALIASES = { + triangle: "arrow", + vee: "arrow", + simple: "arrow", + triangleRect: "rect", + square: "rect", +}; + +/** @returns {number} marker code for an arrow-type string (unknown → arrow) */ +function edgeMarkerCode(arrowType) { + const name = LEGACY_MARKER_ALIASES[arrowType] ?? arrowType; + return EDGE_MARKERS[name] ?? EDGE_MARKERS.arrow; +} + +/** Effective halo width in px: 0 unless halo is enabled with a positive width. */ +function edgeHaloWidth(style) { + const width = style.haloLineWidth ?? DEFAULTS.EDGE.HALO.WIDTH; + return style.halo && width > 0 ? width : 0; +} + +/** + * Edge flow-overlay vocabulary. The numeric codes are the `flowMode` float + * attr consumed by the WebGL flow program (edge_flow_programs.js), which + * selects the pattern in its fragment shader: dash (marching dash segments), + * pulse (discrete travelling dots), comet (sharp head with a fading tail) or + * chevron (travelling arrow shapes). 0 = no flow (the program collapses the + * quad to zero fragments, like disabled halos/markers). + */ +const FLOW_MODES = { dash: 1, pulse: 2, comet: 3, chevron: 4 }; + +/** @returns {number} flow mode code: 0 unless flow is enabled (unknown type → dash) */ +function edgeFlowMode(style) { + if (!style.flow) return 0; + return FLOW_MODES[style.flowType ?? DEFAULTS.EDGE.FLOW.TYPE] ?? FLOW_MODES.dash; +} + +// Default flow color = the edge stroke mixed this far toward white, so the +// overlay contrasts with the body it travels on without a config color. +const FLOW_LIGHTEN_AMOUNT = 0.45; + +/** + * Mix a hex color toward white in RGB space, preserving alpha. Accepts + * #rgb/#rgba/#rrggbb/#rrggbbaa; anything else (named colors, rgb() strings) + * is returned unchanged — lightening is best-effort for the flow default, + * not a general color parser. + * + * @param {string} hex + * @param {number} amount 0 = identity (normalized to long form), 1 = white + * @returns {string} #rrggbb or #rrggbbaa (lowercase) + */ +function lightenHexColor(hex, amount) { + if (typeof hex !== "string" || !/^#([0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(hex)) { + return hex; + } + let digits = hex.slice(1); + if (digits.length <= 4) { + digits = [...digits].map((d) => d + d).join(""); + } + const t = Math.min(Math.max(amount, 0), 1); + const channel = (i) => { + const value = parseInt(digits.slice(i, i + 2), 16); + return Math.round(value + (255 - value) * t) + .toString(16) + .padStart(2, "0"); + }; + const alpha = digits.length === 8 ? digits.slice(6, 8).toLowerCase() : ""; + return `#${channel(0)}${channel(2)}${channel(4)}${alpha}`; +} + +/** + * Multiply a hex color's alpha channel by `opacity` (flow-overlay prominence + * knob — the programs alpha-blend, so opacity folds into the color CPU-side + * with zero shader cost). Same best-effort contract as lightenHexColor: + * non-hex strings and opacity ≥ 1 return the input unchanged. + * + * @param {string} hex + * @param {number} opacity clamped to [0, 1] + * @returns {string} #rrggbbaa (lowercase) when applied, else the input + */ +function applyHexOpacity(hex, opacity) { + if (!(Number.isFinite(opacity) && opacity < 1)) return hex; + if (typeof hex !== "string" || !/^#([0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(hex)) { + return hex; + } + let digits = hex.slice(1).toLowerCase(); + if (digits.length <= 4) { + digits = [...digits].map((d) => d + d).join(""); + } + const baseAlpha = digits.length === 8 ? parseInt(digits.slice(6, 8), 16) : 255; + const alpha = Math.round(baseAlpha * Math.max(opacity, 0)) + .toString(16) + .padStart(2, "0"); + return `#${digits.slice(0, 6)}${alpha}`; +} + +/** + * Sigma edge program key for a G6 edge type + marker/halo/flow styling. + * Two parametric programs per curvature: the plain fast path ("line"/"curve") + * for the unstyled majority, and the compound halo+line+flow+marker-heads + * program ("styledLine"/"styledCurve") whenever any end marker, halo or flow + * is active — the per-edge attrs (start/endMarker, haloWidth, flowMode, ...) + * parameterize it, so the registry never grows with the marker vocabulary. + * Flow on curved edges routes to "styledCurve", whose flow sub-program forks + * the @sigma/edge-curve shaders (createCurveFlowProgram + edge_flow_glsl.js). + * Degradations (documented in API.md §5): `polyline` renders as a curve, + * `lineDash` is dropped. + */ +function sigmaEdgeType(type, style = {}) { + const curved = type === "cubic" || type === "quadratic" || type === "polyline"; + const styled = + Boolean(style.startArrow) || + Boolean(style.endArrow) || + edgeHaloWidth(style) > 0 || + edgeFlowMode(style) > 0; + if (curved) return styled ? "styledCurve" : "curve"; + return styled ? "styledLine" : "line"; +} + +/** + * Marker + halo + flow attrs read by the custom edge programs. Always emits + * the FULL set (off → 0/null): the adapter applies updates via + * mergeEdgeAttributes, so every toggle must overwrite what the previous + * style set or stale markers/halos/flows survive a disable. Sizes are + * graph-space px (G6 arrow-size heritage); 0 means "derive from edge + * thickness" (sigma stock-arrow proportions). + */ +function edgeMarkerHaloAttributes(style) { + const haloWidth = edgeHaloWidth(style); + const flowMode = edgeFlowMode(style); + return { + startMarker: style.startArrow ? edgeMarkerCode(style.startArrowType) : 0, + startMarkerSize: + Number.isFinite(style.startArrowSize) && style.startArrowSize > 0 ? style.startArrowSize : 0, + // null fill → marker program inherits the edge stroke color; null border → no border. + startMarkerColor: style.startArrow ? (style.startArrowColor ?? null) : null, + startMarkerBorderColor: style.startArrow ? (style.startArrowBorderColor ?? null) : null, + // Border band thickness in px; 0 → auto (proportional to the marker). + startMarkerBorderSize: + style.startArrow && Number.isFinite(style.startArrowBorderSize) && style.startArrowBorderSize > 0 + ? style.startArrowBorderSize + : 0, + endMarker: style.endArrow ? edgeMarkerCode(style.endArrowType) : 0, + endMarkerSize: + Number.isFinite(style.endArrowSize) && style.endArrowSize > 0 ? style.endArrowSize : 0, + endMarkerColor: style.endArrow ? (style.endArrowColor ?? null) : null, + endMarkerBorderColor: style.endArrow ? (style.endArrowBorderColor ?? null) : null, + endMarkerBorderSize: + style.endArrow && Number.isFinite(style.endArrowBorderSize) && style.endArrowBorderSize > 0 + ? style.endArrowBorderSize + : 0, + haloWidth, + haloColor: haloWidth > 0 ? (style.haloStroke ?? DEFAULTS.EDGE.HALO.COLOR) : null, + flowMode, + // Speed is a unitless multiplier on the shader's base px/s; non-finite or + // non-positive values fall back to the default rather than freezing/reversing. + flowSpeed: + flowMode > 0 + ? Number.isFinite(style.flowSpeed) && style.flowSpeed > 0 + ? style.flowSpeed + : DEFAULTS.EDGE.FLOW.SPEED + : 0, + // Explicit flow color wins; unset derives a lighter shade of the stroke + // so the overlay contrasts with the body without configuration. The + // opacity knob multiplies into the color's alpha (no shader involvement). + flowColor: + flowMode > 0 + ? applyHexOpacity( + style.flowStroke ?? lightenHexColor(style.stroke ?? DEFAULTS.EDGE.COLOR, FLOW_LIGHTEN_AMOUNT), + Number.isFinite(style.flowOpacity) ? style.flowOpacity : DEFAULTS.EDGE.FLOW.OPACITY, + ) + : null, + // Pattern-period multiplier (higher = sparser). Neutral 1 when off or + // invalid — the shaders divide by it, so it must stay positive. + flowDensity: + flowMode > 0 && Number.isFinite(style.flowDensity) && style.flowDensity > 0 + ? style.flowDensity + : 1, + }; +} + +/** + * Map a G6 edge style + type to sigma edge attributes. + * + * Like the node mapper, the program-dependent attrs (type + marker/halo/flow + * set) are only emitted when `type` is given — the adapter always maps from + * the merged ref (full style), so the set is complete and coherent there. + * + * @param {object} style G6 edge style ({lineWidth, stroke, *Arrow*, halo*, flow*, label*, visibility, ...}) + * @param {string} [type] G6 edge type (line|cubic|quadratic|polyline) + * @returns {object} partial sigma attrs + */ +function edgeAttributesFromStyle(style = {}, type = undefined) { + const attrs = {}; + if (style.lineWidth !== undefined) attrs.size = style.lineWidth; + if (style.stroke !== undefined) attrs.color = style.stroke; + if (style.label === false) { + attrs.label = null; + } else if (style.label && style.labelText !== undefined) { + attrs.label = style.labelText == null ? null : String(style.labelText); + } + Object.assign(attrs, labelStyleAttributes(style)); + if (style.visibility !== undefined) { + attrs.hidden = style.visibility === "hidden"; + } + if (type !== undefined) { + attrs.type = sigmaEdgeType(type, style); + Object.assign(attrs, edgeMarkerHaloAttributes(style)); + } + return attrs; +} + +/** + * Deterministic placeholder coordinate for nodes without a position. Sigma + * hard-requires numeric x/y on every node; the initial layout pass + * overwrites these (see SigmaAdapter.render()). + */ +function placeholderPosition(index, total) { + const angle = (2 * Math.PI * index) / Math.max(total, 1); + const radius = 100 + 10 * Math.sqrt(Math.max(total, 1)); + return { x: Math.cos(angle) * radius, y: Math.sin(angle) * radius }; +} + +/** + * Build the graph-space target map for a workspace-switch position tween + * (consumed by sigma/utils animateNodes via SigmaAdapter.runLayoutTransition). + * Persisted positions are app-model (y-down) → flipped into graphology's + * y-up frame. Nodes absent from the graph or carrying non-finite coordinates + * are skipped (a stale persisted id must not animate a missing node). + * + * @param {Map|null|undefined} positionsMap + * @param {(id: string) => boolean} hasNode graph membership predicate + * @returns {{targets: Record, count: number}} + */ +function buildLayoutTransitionTargets(positionsMap, hasNode) { + const targets = {}; + let count = 0; + if (!positionsMap) return { targets, count }; + for (const [id, pos] of positionsMap) { + const x = pos?.style?.x; + const y = pos?.style?.y; + if (hasNode(id) && Number.isFinite(x) && Number.isFinite(y)) { + targets[id] = { x, y: flipY(y) }; + count++; + } + } + return { targets, count }; +} + +/** + * Build a graphology Graph from cache.nodeRef/edgeRef. Positions come from + * the selected layout's persisted positions Map when present (app-model + * y-down → flipped), else from the node style (flipped by the mapper), else + * a deterministic placeholder spread (already in sigma space). + * + * @param {object} cache app cache (needs nodeRef, edgeRef, data.layouts/selectedLayout) + * @returns {Graph} + */ +function buildGraphologyGraph(cache) { + const graph = new Graph({ multi: true, allowSelfLoops: true, type: "directed" }); + const positions = cache.data?.layouts?.[cache.data?.selectedLayout]?.positions; + const total = cache.nodeRef.size; + + let index = 0; + for (const node of cache.nodeRef.values()) { + const mapped = nodeAttributesFromStyle(node.style ?? {}, node.type); + const persisted = positions?.get(node.id)?.style; + const fallback = placeholderPosition(index, total); + graph.addNode(node.id, { + ...mapped, + x: Number.isFinite(persisted?.x) ? persisted.x : (mapped.x ?? fallback.x), + y: Number.isFinite(persisted?.y) ? flipY(persisted.y) : (mapped.y ?? fallback.y), + label: mapped.label ?? null, + hidden: mapped.hidden ?? false, + zIndex: 0, + }); + index++; + } + + for (const edge of cache.edgeRef.values()) { + if (!graph.hasNode(edge.source) || !graph.hasNode(edge.target)) { + cache.ui?.debug?.(`Skipping edge ${edge.id}: missing endpoint node`); + continue; + } + const mapped = edgeAttributesFromStyle(edge.style ?? {}, edge.type); + graph.addEdgeWithKey(edge.id, edge.source, edge.target, { + ...mapped, + label: mapped.label ?? null, + hidden: mapped.hidden ?? false, + zIndex: 0, + }); + } + + return graph; +} + +/** + * State treatment for a node, per the old G6 state spec: + * selected → own fill, accent halo ring, raised zIndex + * highlight → accent fill, accent halo ring + * dim → dim fill + * Halo states render through the texture program (the only sigma mechanism + * that draws a ring around non-circular shapes); the node grows by + * HALO_EXTRA_PX so the halo bleeds outward like G6's did. Halos stay on the + * texture path for ALL shapes — including borderCircle nodes — so there is a + * single halo implementation; a node-border halo ring for circles would have + * to visually match the SVG halo on the other five shapes forever. This works + * unchanged for borderCircle data because its branch keeps fillColor ?? color, + * borderColor and borderSize coherent (reducers never write to graphology, so + * the transient type switch needs no merge hygiene). + */ +function applyNodeState(data, state) { + // Pie nodes have no texture/halo path (the SVG halo draws a single-fill + // shape, which would erase the slices). Emphasis is a size pop for + // selected/highlight; dim is a no-op — the slice colors carry the data, so + // there is no flat fill to dim toward. (Known limitation: pie nodes don't + // de-emphasize on hover-dim; selection/hover still raise them via zIndex.) + if (data.type === "pie") { + if (state === "dim") return data; + return { ...data, size: (data.size ?? DEFAULTS.NODE.SIZE / 2) + HALO_EXTRA_PX }; + } + + const res = { ...data }; + const shape = data.shape ?? "circle"; + const baseSize = data.size ?? DEFAULTS.NODE.SIZE / 2; + const fill = data.fillColor ?? data.color; + const stroke = data.borderColor ?? null; + const lineWidth = data.borderSize ?? 0; + + if (state === "dim" && data.type !== "shape") { + res.color = STATE_DIM_COLOR; + return res; + } + + res.type = "shape"; + res.color = TRANSPARENT; + res.image = shapeTextureURI({ shape, fill, stroke, lineWidth, size: baseSize, state }); + if (state !== "dim") res.size = baseSize + HALO_EXTRA_PX; + return res; +} + +/** + * 1-degree hover neighborhood (G6 hover-activate parity): the element itself + * plus, for a node, its neighbors and incident edges, or, for an edge, its + * two endpoints. Hidden members are harmless to include — the reducers bail + * out on hidden elements before consulting hover state. + * + * @param {import("../lib/graphology.bundle.mjs").Graph} graph + * @param {string} id node or edge key + * @param {boolean} isEdge + * @returns {Set} + */ +function hoverNeighborhood(graph, id, isEdge) { + const ids = new Set([id]); + if (isEdge) { + if (graph.hasEdge(id)) { + for (const nodeId of graph.extremities(id)) ids.add(nodeId); + } + return ids; + } + if (graph.hasNode(id)) { + for (const neighbor of graph.neighbors(id)) ids.add(neighbor); + for (const edge of graph.edges(id)) ids.add(edge); + } + return ids; +} + +/** + * Hover layer is separate from the selection-bearing elementStates Map so a + * hover/leave cycle can never corrupt selection: a non-empty hoverIds Set + * means "hover active" — members render highlighted, every other visible + * element dims. Selection wins over hover so selected elements stay + * recognizable while the rest of the graph dims. + */ +function hoverStateFor(id, hoverIds) { + if (hoverIds.size === 0) return null; + return hoverIds.has(id) ? "highlight" : "dim"; +} + +/** + * Heatmap dim-graph companion: while the density heatmap is on with its + * "dim graph" setting, every element without an explicit/hover state dims so + * the field reads through (the heatmap canvas sits BELOW nodes and edges — + * no ramp tuning can fix occlusion; de-emphasizing the occluders can). + * Selection, highlight and hover all keep their normal treatment. Read live + * off the cache each reducer call: the layer toggles trigger sigma.refresh. + */ +function heatmapDimActive(cache) { + const layer = cache.graph?.heatmapLayer; + return !!(layer?.heatmapEnabled && layer.settings?.dimGraph); +} + +/** + * Sigma nodeReducer factory. Reads the graphology `hidden` attribute, the + * app-level element-states Map (selected/highlight/dim, formerly G6 states) + * and the hover layer (see hoverStateFor). + * + * @param {object} cache + * @param {Map} elementStates + * @param {Set} [hoverIds] production code MUST pass the shared Set + * mutated by InteractionManager — the default creates a fresh (permanently + * empty) Set and exists only so node tests can omit hover wiring + */ +function makeNodeReducer(cache, elementStates, hoverIds = new Set()) { + return (node, data) => { + if (data.hidden) return data; + const states = elementStates.get(node) ?? []; + const hoverState = hoverStateFor(node, hoverIds); + if (states.includes("selected")) { + return { ...applyNodeState(data, "selected"), zIndex: 1 }; + } + if (states.includes("highlight") || hoverState === "highlight") { + return applyNodeState(data, "highlight"); + } + if (states.includes("dim") || hoverState === "dim") return applyNodeState(data, "dim"); + if (heatmapDimActive(cache)) return applyNodeState(data, "dim"); + return data; + }; +} + +/** + * Sigma edgeReducer factory. An edge is hidden when its own `hidden` attr is + * set OR either endpoint is hidden/filtered. States: selected = accent + + * widened (the emphasis budget), highlight = accent, dim = de-emphasis color. + * User halos compose with selection by construction: the halo program derives + * its width from the post-reducer `size` (+ 2 × haloWidth), so a selected + * edge's halo widens with the line while keeping its own color. + * + * @param {object} cache needs edgeRef and graphData (the live graphology graph) + * @param {Map} elementStates + * @param {Set} [hoverIds] + */ +function makeEdgeReducer(cache, elementStates, hoverIds = new Set()) { + return (edge, data) => { + if (data.hidden) return data; + const ref = cache.edgeRef.get(edge); + const graph = cache.graphData; + if (ref && graph?.hasNode(ref.source) && graph.hasNode(ref.target)) { + if ( + graph.getNodeAttribute(ref.source, "hidden") || + graph.getNodeAttribute(ref.target, "hidden") + ) { + return { ...data, hidden: true }; + } + } + const states = elementStates.get(edge) ?? []; + const hoverState = hoverStateFor(edge, hoverIds); + if (states.length === 0 && hoverState === null) { + return heatmapDimActive(cache) ? { ...data, color: STATE_DIM_COLOR } : data; + } + const res = { ...data }; + if (states.includes("selected")) { + res.color = STATE_ACCENT_COLOR; + res.size = (data.size ?? 1) + DEFAULTS.STATE.EDGE_HALO_WIDTH / 2; + res.zIndex = 1; + } else if (states.includes("highlight") || hoverState === "highlight") { + res.color = STATE_ACCENT_COLOR; + } else if (states.includes("dim") || hoverState === "dim") { + res.color = STATE_DIM_COLOR; + } + return res; + }; +} + +export { + buildGraphologyGraph, + buildLayoutTransitionTargets, + nodeAttributesFromStyle, + edgeAttributesFromStyle, + sigmaEdgeType, + edgeMarkerCode, + EDGE_MARKERS, + FLOW_MODES, + edgeFlowMode, + lightenHexColor, + applyHexOpacity, + flipY, + hoverNeighborhood, + makeNodeReducer, + makeEdgeReducer, + STATE_ACCENT_COLOR, + STATE_DIM_COLOR, +}; diff --git a/src/graph/heatmap_geometry.js b/src/graph/heatmap_geometry.js new file mode 100644 index 0000000..020f940 --- /dev/null +++ b/src/graph/heatmap_geometry.js @@ -0,0 +1,224 @@ +/** + * Node-safe density-heatmap geometry helpers. + * + * Pure math between the graph model and the atmospheric canvas layer + * (heatmap_layer.js): bbox/splat-canvas sizing, bandwidth derivation and the + * color-ramp lookup the layer applies to the accumulated splat density. Must + * never import the sigma bundle or touch the DOM — vitest imports this + * module under node. + */ + +// Derived-bandwidth clamp, as a fraction of the bbox diagonal. The default +// bandwidth shrinks as points get denser (diagonal/√n: average inter-point +// spacing for a uniform spread), but is bounded so it never degenerates — +// the lower clamp keeps splats visible on huge graphs, the upper clamp keeps +// tiny graphs from melting into one undifferentiated blob. +const BANDWIDTH_MIN_DIAGONAL_FRACTION = 0.02; +const BANDWIDTH_MAX_DIAGONAL_FRACTION = 0.12; + +// Degenerate-bbox fallback (single node / zero area with zero bandwidth): +// a fixed small canvas spanning 1 graph unit centered on the bbox keeps +// callers crash-free without allocating a meaningless 1024px surface. +const DEGENERATE_SPAN = 1; +const DEGENERATE_RESOLUTION = 8; + +const HEX_COLOR_RE = /^#([0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/; +const LUT_SIZE = 256; + +/** + * Axis-aligned bounding box over graph-space positions. Entries with a + * non-finite coordinate are ignored. + * + * @param {Iterable<{x: number, y: number}>} positions + * @returns {{minX: number, minY: number, maxX: number, maxY: number}|null} + * null when no finite position exists + */ +function graphBBox(positions) { + let minX = Infinity; + let minY = Infinity; + let maxX = -Infinity; + let maxY = -Infinity; + for (const p of positions) { + if (!Number.isFinite(p.x) || !Number.isFinite(p.y)) continue; + if (p.x < minX) minX = p.x; + if (p.x > maxX) maxX = p.x; + if (p.y < minY) minY = p.y; + if (p.y > maxY) maxY = p.y; + } + if (minX === Infinity) return null; + return { minX, minY, maxX, maxY }; +} + +/** + * Graph-space → offscreen-canvas-px mapping for the splat surface: the bbox + * PLUS a bandwidth margin on every side fits the canvas, long side capped at + * maxResolution. The mapping is uniform and axis-aligned: + * + * px = (x - offsetX) * scale, py = (y - offsetY) * scale + * + * (no y flip — the layer's per-frame drawImage affine absorbs whatever + * orientation sigma's graphToViewport applies). + * + * @param {{minX: number, minY: number, maxX: number, maxY: number}} bbox + * @param {number} bandwidth graph-units margin (splat radius) + * @param {number} [maxResolution] long-side px cap + * @returns {{scale: number, offsetX: number, offsetY: number, + * width: number, height: number}} + */ +function splatTransform(bbox, bandwidth, maxResolution = 1024) { + const spanX = bbox.maxX - bbox.minX + 2 * bandwidth; + const spanY = bbox.maxY - bbox.minY + 2 * bandwidth; + const longSide = Math.max(spanX, spanY); + if (!Number.isFinite(longSide) || longSide <= 0) { + const half = DEGENERATE_SPAN / 2; + return { + scale: DEGENERATE_RESOLUTION / DEGENERATE_SPAN, + offsetX: (bbox.minX + bbox.maxX) / 2 - half, + offsetY: (bbox.minY + bbox.maxY) / 2 - half, + width: DEGENERATE_RESOLUTION, + height: DEGENERATE_RESOLUTION, + }; + } + const scale = maxResolution / longSide; + return { + scale, + offsetX: bbox.minX - bandwidth, + offsetY: bbox.minY - bandwidth, + width: Math.max(1, Math.round(spanX * scale)), + height: Math.max(1, Math.round(spanY * scale)), + }; +} + +/** + * Gaussian splat radius in graph units. An explicit positive configBandwidth + * wins; otherwise diagonal/√(nodeCount), clamped to + * [BANDWIDTH_MIN_DIAGONAL_FRACTION, BANDWIDTH_MAX_DIAGONAL_FRACTION] of the + * diagonal (see the clamp-constants comment for the rationale). + * + * @param {{minX: number, minY: number, maxX: number, maxY: number}|null} bbox + * @param {number} nodeCount + * @param {number} configBandwidth graph units; <= 0 → derive + * @returns {number} 0 when there is no drawable extent + */ +function heatBandwidth(bbox, nodeCount, configBandwidth) { + if (configBandwidth > 0) return configBandwidth; + if (!bbox) return 0; + const diagonal = Math.hypot(bbox.maxX - bbox.minX, bbox.maxY - bbox.minY); + if (!(diagonal > 0)) return 0; + const derived = diagonal / Math.sqrt(Math.max(1, nodeCount)); + return Math.min( + BANDWIDTH_MAX_DIAGONAL_FRACTION * diagonal, + Math.max(BANDWIDTH_MIN_DIAGONAL_FRACTION * diagonal, derived), + ); +} + +/** + * @param {string} color "#rrggbb" or "#rrggbbaa" + * @returns {number[]} RGBA 0-255 + * @throws {Error} on any other form — silent NaN channels paint nothing + * (Canvas2D ignores invalid rgba() strings), which is far harder to debug + */ +function parseHexColor(color) { + if (typeof color !== "string" || !HEX_COLOR_RE.test(color)) { + throw new Error(`parseHexColor: expected "#rrggbb" or "#rrggbbaa", got ${JSON.stringify(color)}`); + } + const r = parseInt(color.slice(1, 3), 16); + const g = parseInt(color.slice(3, 5), 16); + const b = parseInt(color.slice(5, 7), 16); + const a = color.length === 9 ? parseInt(color.slice(7, 9), 16) : 255; + return [r, g, b, a]; +} + +/** + * 256-entry RGBA lookup table from color stops, linearly interpolated per + * channel. Densities below the first stop's t take the first color, above + * the last stop's t the last color. + * + * @param {Array<{t: number, color: string}>} stops t in [0, 1] ascending, + * color "#rrggbb" or "#rrggbbaa" + * @returns {Uint8ClampedArray} length 256*4 + * @throws {Error} on malformed stops (wrong shape, t out of range or + * unsorted, unparseable color) + */ +function buildRampLut(stops) { + if (!Array.isArray(stops) || stops.length < 2) { + throw new Error("buildRampLut: need an array of at least 2 stops"); + } + const parsed = stops.map((stop, i) => { + if (!stop || !Number.isFinite(stop.t) || stop.t < 0 || stop.t > 1) { + throw new Error(`buildRampLut: stop ${i} needs a finite t in [0, 1]`); + } + if (i > 0 && stop.t < stops[i - 1].t) { + throw new Error("buildRampLut: stops must be sorted ascending by t"); + } + if (typeof stop.color !== "string" || !HEX_COLOR_RE.test(stop.color)) { + throw new Error(`buildRampLut: stop ${i} color must be "#rrggbb" or "#rrggbbaa"`); + } + return { t: stop.t, rgba: parseHexColor(stop.color) }; + }); + + const lut = new Uint8ClampedArray(LUT_SIZE * 4); + for (let i = 0; i < LUT_SIZE; i++) { + const t = i / (LUT_SIZE - 1); + let seg = 0; + while (seg < parsed.length - 2 && parsed[seg + 1].t < t) seg++; + const lo = parsed[seg]; + const hi = parsed[seg + 1]; + const span = hi.t - lo.t; + // Clamping covers t outside [first.t, last.t]; coincident stops (span 0) + // resolve to the later stop. + const f = span > 0 ? Math.min(1, Math.max(0, (t - lo.t) / span)) : 1; + for (let c = 0; c < 4; c++) { + lut[i * 4 + c] = lo.rgba[c] + (hi.rgba[c] - lo.rgba[c]) * f; + } + } + return lut; +} + +/** + * Map each pixel's accumulated alpha through the ramp LUT into RGBA — IN + * PLACE (the one deliberate mutation in this module: the ImageData buffer is + * the output surface). Pixels with alpha 0 stay fully transparent. + * + * Threshold semantics: densities below `threshold` clear entirely and the + * surviving range renormalizes to [0, 1] before gamma, so the ramp keeps its + * full sweep above the cutoff. Splat accumulation is alpha compositing + * (1 − (1 − intensity)ⁿ for n overlaps), so a lone node peaks at exactly the + * splat intensity — a threshold just above it shows only real clusters. + * + * @param {{data: Uint8ClampedArray}} imageData canvas ImageData (or a + * node-side stand-in with a `data` buffer) + * @param {Uint8ClampedArray} lut buildRampLut output + * @param {number} [gamma] density exponent before the lookup (> 1 thins + * low-density haze, < 1 boosts it) + * @param {number} [threshold] density floor in [0, 1); <= 0 → no floor, + * >= 1 degenerates to a fully transparent field + * @returns {{data: Uint8ClampedArray}} the same imageData + */ +function applyRampToAlpha(imageData, lut, gamma = 1, threshold = 0) { + const data = imageData.data; + const span = 1 - threshold; + for (let i = 0; i < data.length; i += 4) { + const alpha = data[i + 3]; + if (alpha === 0) continue; + let density = alpha / 255; + if (threshold > 0) { + if (density < threshold || !(span > 0)) { + data[i] = 0; + data[i + 1] = 0; + data[i + 2] = 0; + data[i + 3] = 0; + continue; + } + density = (density - threshold) / span; + } + const idx = 4 * Math.min(LUT_SIZE - 1, Math.round((LUT_SIZE - 1) * Math.pow(density, gamma))); + data[i] = lut[idx]; + data[i + 1] = lut[idx + 1]; + data[i + 2] = lut[idx + 2]; + data[i + 3] = lut[idx + 3]; + } + return imageData; +} + +export { graphBBox, splatTransform, heatBandwidth, parseHexColor, buildRampLut, applyRampToAlpha }; diff --git a/src/graph/heatmap_layer.js b/src/graph/heatmap_layer.js new file mode 100644 index 0000000..96146df --- /dev/null +++ b/src/graph/heatmap_layer.js @@ -0,0 +1,352 @@ +/** + * Browser-only atmospheric canvas layer: node-density heatmap. + * + * One 2d canvas registered BOTTOM-MOST, below the edges canvas. + * LAYER ORDERING (verified against the bundled sigma createLayer): a layer + * created with beforeLayer: "edges" is inserted into the DOM immediately + * before the "edges" canvas via Element.before(). The full stack is + * heatmap < edges < nodes < bubbleSets body < labels < bubbleSets labels — + * the bubbleSets body paints ABOVE nodes (afterLayer: "nodes") so it stays + * visible at deep zoom; this heatmap stays deepest of all. + * + * HEATMAP pass (off by default): gaussian-ish alpha splats per visible node, + * accumulated into an OFFSCREEN canvas in graph-space px and colored through + * the theme ramp (heatmap_geometry.js). The offscreen is cached under a + * viewport-INDEPENDENT key (positions checksum + theme + settings), so + * pan/zoom never re-splats — each frame is a single drawImage with the + * camera affine. + * + * `settings` are the live appearance knobs (styling-panel card): intensity, + * gamma and threshold shape the density field, bandwidthScale the splat + * radius, ramp picks the color preset (config RAMPS) — all five ride the + * heat key so a tweak rebuilds the offscreen. opacity only affects the + * per-frame composite (signature, not key). dimGraph is consumed by the + * reducers (graph_model.js heatmapDimActive), not painted here — enabled/ + * dimGraph flips refresh sigma so the reducers re-run. + * + * Redraw plumbing mirrors bubble_layer.js: afterRender → scheduleRedraw rAF + * coalescing, paint-signature skip, destroy() discipline. With the pass off + * the canvas is cleared once and the handler does zero per-frame work. + * + * Known cost bound: dragging a node WITH the heatmap enabled re-splats the + * offscreen every frame (positions are part of the heat key — staleness + * would be worse). The dominant term is the getImageData readback of the + * ≤ MAX_RESOLUTION² offscreen; fine at the app's typical graph sizes, the + * knob to lower on huge graphs is DEFAULTS.HEATMAP.MAX_RESOLUTION. + */ +import { DEFAULTS } from "../config.js"; +import { currentTheme } from "../utilities/theme.js"; +import { positionsChecksum } from "./bubble_geometry.js"; +import { + graphBBox, + splatTransform, + heatBandwidth, + buildRampLut, + applyRampToAlpha, +} from "./heatmap_geometry.js"; + +const LAYER_NAME = "heatmap"; + +/** Initial runtime settings, copied from config (see header comment). */ +function defaultSettings() { + return { + opacity: DEFAULTS.HEATMAP.OPACITY, + intensity: DEFAULTS.HEATMAP.INTENSITY, + gamma: DEFAULTS.HEATMAP.GAMMA, + threshold: DEFAULTS.HEATMAP.THRESHOLD, + bandwidthScale: DEFAULTS.HEATMAP.BANDWIDTH_SCALE, + ramp: DEFAULTS.HEATMAP.RAMP, + dimGraph: DEFAULTS.HEATMAP.DIM_GRAPH, + }; +} + +/** Theme-resolved stops for a preset name; unknown names fall back to default. */ +function rampStopsFor(ramp, theme) { + const preset = DEFAULTS.HEATMAP.RAMPS[ramp] ?? DEFAULTS.HEATMAP.RAMPS.default; + return theme === "dark" ? preset.dark : preset.light; +} + +class HeatmapLayer { + /** + * @param {object} adapter SigmaAdapter (owns sigma + graphology) + */ + constructor(adapter) { + this.adapter = adapter; + this.killed = false; + this.heatmapEnabled = DEFAULTS.HEATMAP.ENABLED; + this.settings = defaultSettings(); + + this.rafHandle = null; + this.lastPaintSignature = null; + // Blank-canvas tracker: lets scheduleRedraw skip the rAF entirely while + // the pass is off (the canvas starts blank). + this.cleared = true; + /** @type {{key: string, canvas: HTMLCanvasElement|null, transform: object|null}|null} */ + this.heatCache = null; + /** @type {Map} ramp stops JSON → buildRampLut output */ + this.rampLuts = new Map(); + + const sigma = adapter.sigma; + sigma.createCanvasContext(LAYER_NAME, { + beforeLayer: "edges", + style: { pointerEvents: "none" }, + }); + this.canvas = sigma.getCanvases()[LAYER_NAME]; + this.ctx = this.canvas.getContext("2d"); + + this.renderHandler = () => this.scheduleRedraw(); + sigma.on("afterRender", this.renderHandler); + } + + /** @param {boolean} enabled */ + setHeatmapEnabled(enabled) { + if (this.heatmapEnabled === !!enabled) return; + this.heatmapEnabled = !!enabled; + this.lastPaintSignature = null; + // The reducers consult heatmapEnabled for the dim-graph companion; a + // refresh re-runs them and its afterRender drives our repaint too. + if (this.settings.dimGraph) this.adapter.sigma.refresh(); + this.scheduleRedraw(); + } + + /** + * Merge new appearance settings (styling-panel card). Field-shaping knobs + * ride the heat key, so the offscreen rebuilds on the next paint by itself. + * Unknown keys and non-finite numbers are dropped — a NaN would poison the + * heat key and the composite alpha silently. + * + * @param {Partial>} partial + */ + updateSettings(partial) { + const dimWas = this.settings.dimGraph; + const next = { ...this.settings }; + for (const [key, value] of Object.entries(partial)) { + if (!(key in next)) continue; + if (key === "dimGraph") next.dimGraph = !!value; + else if (key === "ramp") { + if (typeof value === "string" && value in DEFAULTS.HEATMAP.RAMPS) next.ramp = value; + } else if (Number.isFinite(value)) next[key] = value; + } + this.settings = next; + this.lastPaintSignature = null; + if (this.settings.dimGraph !== dimWas && this.heatmapEnabled) { + this.adapter.sigma.refresh(); + } + this.scheduleRedraw(); + } + + /** Reset all appearance settings to their config defaults. */ + resetSettings() { + this.updateSettings(defaultSettings()); + } + + destroy() { + if (this.killed) return; + this.killed = true; + if (this.rafHandle !== null) cancelAnimationFrame(this.rafHandle); + this.adapter.sigma.off("afterRender", this.renderHandler); + // sigma.kill() may or may not remove custom layer canvases; remove() on + // an already-detached node is a no-op, so drop ours defensively. + this.canvas?.remove(); + // The offscreen holds up to MAX_RESOLUTION² of GPU-backed canvas memory; + // release it eagerly rather than waiting out the GC (workspace switches + // replace the whole adapter, so these can otherwise pile up). + this.#releaseHeatCache(); + this.rampLuts.clear(); + } + + /** Zero the cached offscreen's backing store and drop the cache slot. */ + #releaseHeatCache() { + if (this.heatCache?.canvas) { + this.heatCache.canvas.width = 0; + this.heatCache.canvas.height = 0; + } + this.heatCache = null; + } + + scheduleRedraw() { + if (this.killed || this.rafHandle !== null) return; + // Pass off and the canvas already blank: the afterRender handler must + // stay free — don't even take a rAF. + if (!this.heatmapEnabled && this.cleared) return; + this.rafHandle = requestAnimationFrame(() => { + this.rafHandle = null; + this.#paint(); + }); + } + + // ----------------------------------------------------------------- paint + + #paint() { + if (this.killed) return; + const sigma = this.adapter.sigma; + const { width, height } = sigma.getDimensions(); + const dpr = sigma.pixelRatio ?? window.devicePixelRatio ?? 1; + + // Disabled: clear once, then scheduleRedraw stays a no-op (early return + // BEFORE any signature computation). + if (!this.heatmapEnabled) { + this.#prepareCanvas(width, height, dpr); + this.cleared = true; + this.lastPaintSignature = null; + return; + } + this.cleared = false; + + const camera = sigma.getCamera().getState(); + const theme = currentTheme(document); + + // Heatmap identity is viewport-INDEPENDENT — pan/zoom must not re-splat. + // positionsChecksum already folds the node count in (length prefix). + // The ramp rides the key as its serialized stops (not the theme name), + // so a runtime ramp edit can never serve a stale recolor. The field- + // shaping settings (intensity/gamma/bandwidthScale) ride it too. + const positions = this.#visibleNodePositions(); + const s = this.settings; + const rampStops = rampStopsFor(s.ramp, theme); + const heatKey = + `${positionsChecksum(positions)}|${JSON.stringify(rampStops)}` + + `|${DEFAULTS.HEATMAP.BANDWIDTH}|${DEFAULTS.HEATMAP.MAX_RESOLUTION}` + + `|${s.intensity}|${s.gamma}|${s.threshold}|${s.bandwidthScale}`; + + // Skip repainting when neither the content nor the view changed (sigma + // re-renders on hover etc. without clearing custom layers). opacity is + // composite-only: part of the signature, not the heat key. + const signature = + `${width}x${height}x${dpr}|${camera.x},${camera.y},${camera.ratio},${camera.angle}` + + `|h:${heatKey}|o:${s.opacity}`; + if (signature === this.lastPaintSignature) return; + this.lastPaintSignature = signature; + + this.#prepareCanvas(width, height, dpr); + this.#syncHeatmap(positions, heatKey, rampStops); + this.#drawHeatmap(); + } + + /** Resize (if needed) and clear the layer canvas, scaled to the device ratio. */ + #prepareCanvas(width, height, dpr) { + if (this.canvas.width !== width * dpr || this.canvas.height !== height * dpr) { + this.canvas.width = width * dpr; + this.canvas.height = height * dpr; + } + this.ctx.setTransform(dpr, 0, 0, dpr, 0, 0); + this.ctx.clearRect(0, 0, width, height); + } + + /** @returns {Array<{x: number, y: number}>} positions of non-hidden nodes */ + #visibleNodePositions() { + const positions = []; + this.adapter.graph.forEachNode((id, attrs) => { + if (!attrs.hidden) positions.push({ x: attrs.x, y: attrs.y }); + }); + return positions; + } + + // --------------------------------------------------------------- heatmap + + /** Ramp LUT, cached by the stops' serialization (not the theme name). */ + #rampLut(stops) { + const key = JSON.stringify(stops); + let lut = this.rampLuts.get(key); + if (!lut) { + lut = buildRampLut(stops); + this.rampLuts.set(key, lut); + } + return lut; + } + + /** + * Rebuild the colored offscreen when the viewport-independent key changed: + * alpha splats accumulated in graph-space px, then mapped through the + * theme ramp (a theme flip is part of the key, so it recolors). + */ + #syncHeatmap(positions, key, rampStops) { + if (this.heatCache?.key === key) return; + this.#releaseHeatCache(); + const bbox = graphBBox(positions); + const bandwidth = bbox + ? heatBandwidth(bbox, positions.length, DEFAULTS.HEATMAP.BANDWIDTH) * + this.settings.bandwidthScale + : 0; + if (!bbox || !(bandwidth > 0)) { + // No drawable field (empty graph, or a zero-extent bbox under auto + // bandwidth) — cache the verdict so the next frames stay free. + this.heatCache = { key, canvas: null, transform: null }; + return; + } + const transform = splatTransform(bbox, bandwidth, DEFAULTS.HEATMAP.MAX_RESOLUTION); + const off = document.createElement("canvas"); + off.width = transform.width; + off.height = transform.height; + const offCtx = off.getContext("2d", { willReadFrequently: true }); + + // One alpha-only sprite stamped per node beats N radial-gradient fills. + const radiusPx = Math.max(1, bandwidth * transform.scale); + const sprite = this.#buildSplatSprite(radiusPx); + const half = sprite.width / 2; + for (const p of positions) { + offCtx.drawImage( + sprite, + (p.x - transform.offsetX) * transform.scale - half, + (p.y - transform.offsetY) * transform.scale - half, + ); + } + + // NOTE: synchronous GPU→CPU readback of the whole offscreen — the slow + // path of a rebuild; MAX_RESOLUTION bounds it. applyRampToAlpha mutates + // in place and returns the same ImageData; using the return value keeps + // the contract explicit at this call site. + const image = offCtx.getImageData(0, 0, transform.width, transform.height); + offCtx.putImageData( + applyRampToAlpha(image, this.#rampLut(rampStops), this.settings.gamma, this.settings.threshold), + 0, + 0, + ); + this.heatCache = { key, canvas: off, transform }; + } + + /** Radial alpha falloff sprite: settings.intensity at center → 0 at radius. */ + #buildSplatSprite(radiusPx) { + const size = Math.max(2, Math.ceil(radiusPx * 2)); + const sprite = document.createElement("canvas"); + sprite.width = size; + sprite.height = size; + const ctx = sprite.getContext("2d"); + const c = size / 2; + const gradient = ctx.createRadialGradient(c, c, 0, c, c, radiusPx); + gradient.addColorStop(0, `rgba(0, 0, 0, ${this.settings.intensity})`); + gradient.addColorStop(1, "rgba(0, 0, 0, 0)"); + ctx.fillStyle = gradient; + ctx.fillRect(0, 0, size, size); + return sprite; + } + + /** + * Per-frame composite: one drawImage of the cached offscreen under the + * camera transform. The affine is derived from graphToViewport of the + * offscreen's two graph-space corners, which absorbs sigma's y orientation + * (sy comes out negative when graph y points up). Assumes camera.angle + * === 0 — the app never rotates the camera (same as bubble_layer.js). + */ + #drawHeatmap() { + const { canvas: off, transform: t } = this.heatCache; + if (!off) return; + const sigma = this.adapter.sigma; + const p0 = sigma.graphToViewport({ x: t.offsetX, y: t.offsetY }); + const p1 = sigma.graphToViewport({ + x: t.offsetX + t.width / t.scale, + y: t.offsetY + t.height / t.scale, + }); + const ctx = this.ctx; + ctx.save(); + try { + ctx.globalAlpha = this.settings.opacity; + ctx.transform((p1.x - p0.x) / t.width, 0, 0, (p1.y - p0.y) / t.height, p0.x, p0.y); + ctx.drawImage(off, 0, 0); + } finally { + ctx.restore(); + } + } +} + +export { HeatmapLayer }; diff --git a/src/graph/interactions.js b/src/graph/interactions.js new file mode 100644 index 0000000..d81d40e --- /dev/null +++ b/src/graph/interactions.js @@ -0,0 +1,448 @@ +/** + * Browser-only interaction wiring for the sigma renderer (MIGRATION.md + * Phase 3): node drag with position persistence, click/shift-select, hover + * 1-degree highlight, freehand lasso overlay and the click tooltip. Replaces + * the G6 behaviors/plugins; instantiated by SigmaAdapter. + * + * Selection changes are routed through GraphSelectionManager so selection + * memory (undo/redo), the data table and button states stay in sync. + */ +import DOMPurify from "../lib/purify.esm.mjs"; +import { hoverNeighborhood } from "./graph_model.js"; +import { idsInsidePolygon } from "./lasso_geometry.js"; + +// Lasso visuals from the old G6 lasso-select behavior style. +const LASSO_STROKE = "#C33D35"; +const LASSO_FILL = "rgba(195, 61, 53, 0.3)"; +const TOOLTIP_OFFSET_PX = 12; + +class InteractionManager { + /** + * @param {object} adapter SigmaAdapter (owns sigma + graphology + states) + * @param {object} cache app cache + * @param {Set} hoverIds hover layer shared with the reducers + * @param {HTMLElement} container the sigma container (#innerGraphContainer) + */ + constructor(adapter, cache, hoverIds, container) { + this.adapter = adapter; + this.cache = cache; + this.hoverIds = hoverIds; + this.container = container; + this.enabled = { drag: true, click: true, hover: true, tooltip: true, lasso: false }; + + this.draggedNode = null; + this.dragGroup = null; + this.dragMoved = false; + this.pinnedLabels = null; + // Covers the click that ends a micro-drag (1-2 move events — sigma's + // captor only swallows clicks after >=3 dragged events itself). + this.suppressNextClick = false; + + this.lassoCanvas = null; + this.lassoPolygon = null; + this.tooltipEl = null; + // Serializes drag-end persists: a second drag finishing while the first + // persist is still in flight must not race it. + this.persistChain = Promise.resolve(); + this.escHandler = (event) => { + if (event.key === "Escape" && this.enabled.lasso) this.cache.ui.toggleLassoSelection(); + }; + + this.#wireSigmaEvents(); + } + + /** @param {"drag"|"click"|"hover"|"tooltip"|"lasso"} name */ + setEnabled(name, enabled) { + if (!(name in this.enabled)) { + this.cache.ui.error(`Unknown interaction: ${name}`); + return; + } + this.enabled[name] = Boolean(enabled); + if (name === "hover" && !enabled) this.#clearHover(); + if (name === "tooltip" && !enabled) this.hideTooltip(); + if (name === "lasso") enabled ? this.#activateLasso() : this.#deactivateLasso(); + } + + isEnabled(name) { + return Boolean(this.enabled[name]); + } + + destroy() { + document.removeEventListener("keydown", this.escHandler); + this.lassoCanvas?.remove(); + this.lassoCanvas = null; + this.tooltipEl?.remove(); + this.tooltipEl = null; + // Sigma/captor/camera listeners die with sigma.kill() in the adapter. + } + + // ------------------------------------------------------------------ wiring + + /** + * Sigma's emitter does not handle rejected promises from async handlers — + * route them to the UI instead of letting them vanish unhandled. + */ + #guard(promise) { + promise.catch((err) => this.cache.ui.error(`Interaction failed: ${err?.message ?? err}`)); + } + + #wireSigmaEvents() { + const sigma = this.adapter.sigma; + const captor = sigma.getMouseCaptor(); + + sigma.on("downNode", (e) => this.#onDownNode(e.node)); + captor.on("mousemovebody", (e) => this.#onMouseMoveBody(e)); + captor.on("mouseup", () => this.#guard(this.#onMouseUp())); + captor.on("mousedown", () => { + this.suppressNextClick = false; + }); + + sigma.on("clickNode", (e) => this.#guard(this.#onClickElement(e.node, false, e.event))); + sigma.on("clickEdge", (e) => this.#guard(this.#onClickElement(e.edge, true, e.event))); + sigma.on("clickStage", () => this.#guard(this.#onClickStage())); + + sigma.on("enterNode", (e) => this.#onEnter(e.node, false)); + sigma.on("leaveNode", () => this.#clearHover()); + sigma.on("enterEdge", (e) => this.#onEnter(e.edge, true)); + sigma.on("leaveEdge", () => this.#clearHover()); + + // Any camera move (wheel zoom, drag-pan, programmatic fit) orphans the + // tooltip anchor — hide instead of tracking it. + sigma.getCamera().on("updated", () => this.hideTooltip()); + } + + // -------------------------------------------------------------------- drag + + #onDownNode(node) { + if (!this.enabled.drag) return; + this.draggedNode = node; + this.dragMoved = false; + // Dragging a selected node moves the whole selection along. + // (selectedNodes starts as a Set and becomes an array after the first + // selection — new Set() tolerates both.) + const selected = new Set(this.cache.selectedNodes ?? []); + this.dragGroup = selected.has(node) ? selected : null; + // Pin labels for the drag. Every position write rebuilds sigma's label + // grid, so the dragged node would evict neighbours' labels from any grid + // cell it passes through. Pin the dragged node's label (also keeps it up + // past labelRenderedSizeThreshold) AND every label currently on screen; + // all pins are released on mouseup and the grid re-settles. + // (displayedNodeLabels is a sigma internal — fall back to pinning just + // the dragged node if a future sigma drops it.) + this.pinnedLabels = new Set(this.adapter.sigma.displayedNodeLabels ?? []); + this.pinnedLabels.add(node); + for (const id of this.pinnedLabels) { + if (this.adapter.graph.hasNode(id)) { + this.adapter.graph.mergeNodeAttributes(id, { forceLabel: true }); + } + } + // Pin the normalization bbox: without it every x/y write re-normalizes + // the coordinate space and the graph swims under the cursor. + const sigma = this.adapter.sigma; + if (!sigma.getCustomBBox()) sigma.setCustomBBox(sigma.getBBox()); + } + + #onMouseMoveBody(event) { + if (!this.draggedNode) return; + // viewportToGraph returns sigma-space (y-up) — written to graphology + // as-is; the flip to app space happens once in getNodeData (see + // graph_model.js flipY contract). + const pos = this.adapter.sigma.viewportToGraph(event); + const graph = this.adapter.graph; + // Move by delta so a group drag preserves relative positions. + const dragged = graph.getNodeAttributes(this.draggedNode); + const dx = pos.x - dragged.x; + const dy = pos.y - dragged.y; + for (const id of this.dragGroup ?? [this.draggedNode]) { + if (!graph.hasNode(id)) continue; + const a = graph.getNodeAttributes(id); + graph.mergeNodeAttributes(id, { x: a.x + dx, y: a.y + dy }); + } + this.dragMoved = true; + this.hideTooltip(); + // Keep the camera from panning along with the node drag. + event.preventSigmaDefault(); + event.original.preventDefault(); + event.original.stopPropagation(); + } + + async #onMouseUp() { + if (!this.draggedNode) return; + const moved = this.dragMoved; + this.draggedNode = null; + this.dragGroup = null; + this.dragMoved = false; + const graph = this.adapter.graph; + for (const id of this.pinnedLabels ?? []) { + if (graph.hasNode(id)) graph.mergeNodeAttributes(id, { forceLabel: false }); + } + this.pinnedLabels = null; + if (!moved) return; + // Set synchronously before any await: sigma emits clickNode right after + // mouseup with no microtask boundary, so the flag must already be up. + this.suppressNextClick = true; + // Reads getNodeData (sigma y-up → app y-down) and persists app-space + // positions into the selected layout. Chained so overlapping drag-ends + // persist in order instead of racing. + this.persistChain = this.persistChain.then(() => this.cache.lm.persistNodePositions()); + await this.persistChain; + } + + // ----------------------------------------------------------------- clicks + + #consumeSuppressedClick() { + if (!this.suppressNextClick) return false; + this.suppressNextClick = false; + return true; + } + + /** nodeRef + edgeRef in one map so a plain click deselects everything else. */ + #combinedRefMap() { + return new Map([...this.cache.nodeRef, ...this.cache.edgeRef]); + } + + async #onClickElement(id, isEdge, event) { + if (this.#consumeSuppressedClick()) return; + if (this.enabled.click) { + const shift = Boolean(event?.original?.shiftKey); + if (shift) { + const refMap = isEdge ? this.cache.edgeRef : this.cache.nodeRef; + const isSelected = this.adapter.getElementState(id).includes("selected"); + await this.cache.sm.updateSelectedState([refMap.get(id)], !isSelected); + } else { + await this.cache.sm.selectElements([id], this.#combinedRefMap()); + } + } + // Tooltip means "inspect this one thing"; a shift+click is a + // selection-building gesture, so don't flash a tooltip on each one. + const shiftHeld = Boolean(event?.original?.shiftKey); + if (this.enabled.tooltip && !shiftHeld) this.showTooltip(id, isEdge); + } + + async #onClickStage() { + if (this.#consumeSuppressedClick()) return; + this.hideTooltip(); + if (!this.enabled.click) return; + await this.cache.sm.selectElements([], this.#combinedRefMap()); + } + + // ------------------------------------------------------------------ hover + + #onEnter(id, isEdge) { + // CFG.DISABLE_HOVER_EFFECT is checked live: io.preProcessData and the + // hover toggle button flip it at runtime. + if (!this.enabled.hover || this.cache.CFG.DISABLE_HOVER_EFFECT) return; + if (this.draggedNode) return; + this.hoverIds.clear(); + for (const member of hoverNeighborhood(this.adapter.graph, id, isEdge)) { + this.hoverIds.add(member); + } + this.adapter.sigma.refresh({ skipIndexation: true }); + } + + #clearHover() { + if (this.hoverIds.size === 0) return; + this.hoverIds.clear(); + this.adapter.sigma.refresh({ skipIndexation: true }); + } + + // ------------------------------------------------------------------ lasso + + #activateLasso() { + this.hideTooltip(); + this.#clearHover(); + if (!this.lassoCanvas) this.lassoCanvas = this.#createLassoCanvas(); + this.#resizeLassoCanvas(); + this.lassoCanvas.style.display = ""; + document.addEventListener("keydown", this.escHandler); + } + + #deactivateLasso() { + if (this.lassoCanvas) { + this.lassoCanvas.style.display = "none"; + this.lassoCanvas + .getContext("2d") + .clearRect(0, 0, this.lassoCanvas.width, this.lassoCanvas.height); + } + this.lassoPolygon = null; + document.removeEventListener("keydown", this.escHandler); + } + + #createLassoCanvas() { + const canvas = document.createElement("canvas"); + canvas.className = "lasso-overlay"; + // Sits above sigma's layers and swallows all pointer input while active, + // which is what disables camera pan / node drag in lasso mode. Stays + // below the toolbar (1000) so its lasso toggle remains clickable. + Object.assign(canvas.style, { + position: "absolute", + inset: "0", + zIndex: "900", + cursor: "crosshair", + touchAction: "none", + display: "none", + }); + canvas.addEventListener("pointerdown", (e) => this.#onLassoPointerDown(e)); + canvas.addEventListener("pointermove", (e) => this.#onLassoPointerMove(e)); + canvas.addEventListener("pointerup", (e) => this.#guard(this.#onLassoPointerUp(e))); + // OS-interrupted gestures (touch cancel, system gestures) must not leave + // a half-drawn polygon active. + canvas.addEventListener("pointercancel", () => this.#cancelLasso()); + this.container.appendChild(canvas); + return canvas; + } + + #resizeLassoCanvas() { + const canvas = this.lassoCanvas; + if (canvas.width !== this.container.clientWidth) canvas.width = this.container.clientWidth; + if (canvas.height !== this.container.clientHeight) canvas.height = this.container.clientHeight; + } + + #onLassoPointerDown(event) { + if (event.button !== 0) return; + this.#resizeLassoCanvas(); + this.lassoPolygon = [{ x: event.offsetX, y: event.offsetY }]; + // Capture keeps move/up events on the overlay even outside its bounds. + this.lassoCanvas.setPointerCapture(event.pointerId); + } + + #onLassoPointerMove(event) { + if (!this.lassoPolygon) return; + this.lassoPolygon.push({ x: event.offsetX, y: event.offsetY }); + this.#drawLasso(); + } + + async #onLassoPointerUp(event) { + if (!this.lassoPolygon) return; + const polygon = this.lassoPolygon; + this.lassoPolygon = null; + const ctx = this.lassoCanvas.getContext("2d"); + ctx.clearRect(0, 0, this.lassoCanvas.width, this.lassoCanvas.height); + await this.#applyLassoSelection(polygon, event.shiftKey); + } + + #cancelLasso() { + if (!this.lassoPolygon) return; + this.lassoPolygon = null; + const ctx = this.lassoCanvas.getContext("2d"); + ctx.clearRect(0, 0, this.lassoCanvas.width, this.lassoCanvas.height); + } + + #drawLasso() { + const ctx = this.lassoCanvas.getContext("2d"); + ctx.clearRect(0, 0, this.lassoCanvas.width, this.lassoCanvas.height); + ctx.beginPath(); + ctx.moveTo(this.lassoPolygon[0].x, this.lassoPolygon[0].y); + for (const p of this.lassoPolygon.slice(1)) ctx.lineTo(p.x, p.y); + ctx.closePath(); + ctx.fillStyle = LASSO_FILL; + ctx.strokeStyle = LASSO_STROKE; + ctx.lineWidth = 1.5; + ctx.fill("evenodd"); + ctx.stroke(); + } + + /** + * Point-in-polygon over VISIBLE node viewport coordinates. Plain lasso + * replaces the selection (an empty/degenerate lasso therefore deselects, + * matching a canvas click); shift adds the hits to the selection. + */ + async #applyLassoSelection(polygon, additive) { + const sigma = this.adapter.sigma; + const points = []; + this.adapter.graph.forEachNode((id, attrs) => { + if (attrs.hidden) return; + const p = sigma.graphToViewport({ x: attrs.x, y: attrs.y }); + points.push({ id, x: p.x, y: p.y }); + }); + const ids = idsInsidePolygon(points, polygon); + + if (additive) { + if (ids.length === 0) return; + const refs = ids.map((id) => this.cache.nodeRef.get(id)).filter(Boolean); + await this.cache.sm.updateSelectedState(refs, true); + } else { + await this.cache.sm.selectElements(ids, this.#combinedRefMap()); + } + } + + // ---------------------------------------------------------------- tooltip + + showTooltip(id, isEdge) { + const content = this.cache.toolTips.get(id); + if (!content) return; + const el = this.#ensureTooltipEl(); + // Tooltip HTML embeds unescaped node/edge labels, ids and descriptions + // from loaded files — sanitize at the display boundary. DOMPurify also + // strips inline onclick attrs; the expand/close buttons are driven by + // the delegated listener in #ensureTooltipEl instead. + el.innerHTML = DOMPurify.sanitize(content); + el.style.visibility = "visible"; + this.#positionTooltip(el, id, isEdge); + this.#syncExpandButton(el); + } + + hideTooltip() { + if (this.tooltipEl) this.tooltipEl.style.visibility = "hidden"; + } + + #ensureTooltipEl() { + if (this.tooltipEl) return this.tooltipEl; + const el = document.createElement("div"); + // The surviving core.js helpers (drag, wheel, expand/close) expect a + // `.tooltip` element inside #innerGraphContainer with this structure. + el.className = "tooltip"; + el.style.visibility = "hidden"; + // Backdrop comes from the .tooltip CSS rule (theme-aware var(--input-bg)). + // Delegated expand/close handling (sanitization strips inline onclick). + el.addEventListener("click", (event) => { + const expandBtn = event.target.closest(".tooltip-expand-btn"); + if (expandBtn) return window.toggleTooltipExpand(expandBtn); + const closeBtn = event.target.closest(".tooltip-close-btn"); + if (closeBtn) return window.closeTooltip(closeBtn); + }); + this.container.appendChild(el); + this.tooltipEl = el; + return el; + } + + #positionTooltip(el, id, isEdge) { + const graph = this.adapter.graph; + let anchor; + if (isEdge && graph.hasEdge(id)) { + const [source, target] = graph.extremities(id); + const a = graph.getNodeAttributes(source); + const b = graph.getNodeAttributes(target); + anchor = { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 }; + } else if (graph.hasNode(id)) { + const attrs = graph.getNodeAttributes(id); + anchor = { x: attrs.x, y: attrs.y }; + } else { + return; + } + const viewport = this.adapter.sigma.graphToViewport(anchor); + const maxLeft = Math.max(0, this.container.clientWidth - el.offsetWidth); + const maxTop = Math.max(0, this.container.clientHeight - el.offsetHeight); + el.style.left = `${Math.min(Math.max(0, viewport.x + TOOLTIP_OFFSET_PX), maxLeft)}px`; + el.style.top = `${Math.min(Math.max(0, viewport.y + TOOLTIP_OFFSET_PX), maxTop)}px`; + } + + /** + * Ported from the old G6 tooltip plugin: show the expand button only when + * the content actually clips, measured one frame after layout. + */ + #syncExpandButton(el) { + requestAnimationFrame(() => { + const body = el.querySelector(".tooltip-content"); + const btn = el.querySelector(".tooltip-expand-btn"); + if (!body || !btn) return; + el.classList.remove("expanded"); + btn.textContent = "⛶"; + const isClipped = + body.scrollHeight > body.clientHeight + 1 || body.scrollWidth > body.clientWidth + 1; + btn.style.display = isClipped ? "" : "none"; + }); + } +} + +export { InteractionManager }; diff --git a/src/graph/label_renderers.js b/src/graph/label_renderers.js new file mode 100644 index 0000000..6d29743 --- /dev/null +++ b/src/graph/label_renderers.js @@ -0,0 +1,244 @@ +/** + * Canvas label renderers for the sigma renderer (MIGRATION.md Phase 2). + * + * Replace sigma's built-in disc/straight label drawers to honour the + * per-element label attrs emitted by graph_model.js (labelSize, labelColor, + * labelBackground(Color), labelPlacement, labelOffsetX/Y, labelPadding, + * labelAutoRotate). Pure functions of (context, data, settings) — no DOM or + * sigma imports, so vitest covers them under node. + */ + +const BACKGROUND_RADIUS = 4; +const ANCHOR_GAP = 2; // px between node/edge geometry and the label box +// Last-resort font size: a non-finite size would silently corrupt the canvas +// font string ("normal undefinedpx Arial") and draw at whatever was set last. +const FALLBACK_LABEL_SIZE = 14; + +/** @returns {number} a finite label size, falling back hard */ +function finiteSize(perElement, fromSettings) { + const size = perElement ?? fromSettings; + return Number.isFinite(size) ? size : FALLBACK_LABEL_SIZE; +} + +// Unit direction per placement token; combined for corner placements +// ("left-top", "top-right", ...). Unknown tokens resolve to center. +const PLACEMENT_VECTORS = { + left: [-1, 0], + right: [1, 0], + top: [0, -1], + bottom: [0, 1], + center: [0, 0], +}; + +/** @returns {[number, number]} combined unit vector for a placement string */ +function placementVector(placement) { + let ux = 0; + let uy = 0; + for (const token of String(placement ?? "bottom").split("-")) { + const [dx, dy] = PLACEMENT_VECTORS[token] ?? [0, 0]; + ux = ux || dx; + uy = uy || dy; + } + return [ux, uy]; +} + +function resolveSettingsColor(settingsColor, data) { + if (settingsColor?.attribute) { + return data[settingsColor.attribute] || settingsColor.color || "#000"; + } + return settingsColor?.color ?? "#000"; +} + +// io.js bakes DEFAULTS.*.LABEL.FOREGROUND_COLOR ("#000000") into every +// labelled element's style, so the per-element labelColor attr always wins +// over the theme-driven sigma settings fallback. Treat that exact baked +// default as "no explicit choice" so dark mode can flip it (in light mode +// the fallback resolves to #000 — pixel-identical). Any other per-element +// label color is an explicit user choice and is honoured as-is. +const BAKED_DEFAULT_LABEL_COLOR = "#000000"; + +function resolveElementLabelColor(elementColor, settingsColor, data) { + if (elementColor != null && elementColor !== BAKED_DEFAULT_LABEL_COLOR) { + return elementColor; + } + return resolveSettingsColor(settingsColor, data); +} + +function drawBackground(context, color, x, y, width, height, radius = BACKGROUND_RADIUS) { + context.fillStyle = color; + context.beginPath(); + if (typeof context.roundRect === "function") { + context.roundRect(x, y, width, height, radius); + } else { + context.rect(x, y, width, height); + } + context.fill(); +} + +// G6 v5 badge parity: a badge is a small colored pill with white text, +// anchored on the node perimeter. Fallbacks mirror DEFAULTS.NODE.BADGE +// (config is intentionally not imported — this module stays dependency-free; +// graph_model.js bakes the configured defaults into the attrs). +const BADGE_TEXT_COLOR = "#FFFFFF"; +const FALLBACK_BADGE_COLOR = "#C33D35"; +const FALLBACK_BADGE_FONT_SIZE = 8; +const BADGE_PADDING = 2; + +/** + * Draw the node's badges as colored pills with white text, each centered on + * the node perimeter per its placement. Called from drawNodeLabel, so badges + * follow label visibility (v1 limitation). + * + * @param {CanvasRenderingContext2D} context + * @param {object} data node display data (x, y, size, badge, badges, badgePalette, + * badgeFontSize, badgeScaleFactor) + * @param {object} settings sigma settings (labelFont) + */ +function drawNodeBadges(context, data, settings) { + if (!data.badge || !Array.isArray(data.badges) || data.badges.length === 0) return; + + const fontSize = Number.isFinite(data.badgeFontSize) + ? data.badgeFontSize + : FALLBACK_BADGE_FONT_SIZE; + // badgeScaleFactor (graph_model.js) is zoom-independent — like labels, + // badges keep a constant on-screen size; only the perimeter anchor + // (data.size) follows the camera. + const scale = Number.isFinite(data.badgeScaleFactor) && data.badgeScaleFactor > 0 + ? data.badgeScaleFactor + : 1; + const size = fontSize * scale; + context.font = `bold ${size}px ${settings.labelFont}`; + + data.badges.forEach((badge, index) => { + const text = badge?.text == null ? "" : String(badge.text); + if (!text) return; + + const width = context.measureText(text).width; + const boxWidth = width + 2 * BADGE_PADDING; + const boxHeight = size + 2 * BADGE_PADDING; + + // Normalize corner placements onto the perimeter circle. + const [ux, uy] = placementVector(badge.placement); + const norm = Math.hypot(ux, uy) || 1; + const cx = data.x + (ux / norm) * data.size; + const cy = data.y + (uy / norm) * data.size; + + const color = data.badgePalette?.[index] ?? FALLBACK_BADGE_COLOR; + drawBackground( + context, + color, + cx - boxWidth / 2, + cy - boxHeight / 2, + boxWidth, + boxHeight, + boxHeight / 2, // pill: fully rounded ends + ); + context.fillStyle = BADGE_TEXT_COLOR; + context.fillText(text, cx - width / 2, cy + size * 0.35); + }); +} + +/** + * Node label drawer (sigma `defaultDrawNodeLabel`). G6 parity: default + * placement is "bottom" (sigma's default drawer is right-anchored only). + * Also draws the node's badges (see drawNodeBadges) after the label. + * + * @param {CanvasRenderingContext2D} context + * @param {object} data node display data in viewport px (x, y, size, label, label* attrs) + * @param {object} settings sigma settings (labelSize/labelFont/labelWeight/labelColor) + */ +function drawNodeLabel(context, data, settings) { + if (!data.label) return; + + const size = finiteSize(data.labelSize, settings.labelSize); + const font = settings.labelFont; + const weight = settings.labelWeight; + const color = resolveElementLabelColor(data.labelColor, settings.labelColor, data); + const padding = data.labelPadding ?? 2; + + context.font = `${weight} ${size}px ${font}`; + const width = context.measureText(data.label).width; + const boxWidth = width + 2 * padding; + const boxHeight = size + 2 * padding; + + const [ux, uy] = placementVector(data.labelPlacement); + const gap = ANCHOR_GAP; + const boxCenterX = + data.x + ux * (data.size + gap + boxWidth / 2) + (data.labelOffsetX ?? 0); + const boxCenterY = + data.y + uy * (data.size + gap + boxHeight / 2) + (data.labelOffsetY ?? 0); + + if (data.labelBackground && data.labelBackgroundColor) { + drawBackground( + context, + data.labelBackgroundColor, + boxCenterX - boxWidth / 2, + boxCenterY - boxHeight / 2, + boxWidth, + boxHeight, + ); + } + + context.fillStyle = color; + context.fillText(data.label, boxCenterX - width / 2, boxCenterY + size * 0.35); + + drawNodeBadges(context, data, settings); +} + +/** + * Straight-edge label drawer (sigma `defaultDrawEdgeLabel`). G6 parity: + * `labelPlacement` start/center/end positions along the edge, + * `labelAutoRotate` (default false) aligns the text with the edge. + * + * @param {CanvasRenderingContext2D} context + * @param {object} edgeData edge display data (label, size, label* attrs) + * @param {object} sourceData source node display data in viewport px + * @param {object} targetData target node display data in viewport px + * @param {object} settings sigma settings (edgeLabel*) + */ +function drawEdgeLabel(context, edgeData, sourceData, targetData, settings) { + if (!edgeData.label) return; + + const size = finiteSize(edgeData.labelSize, settings.edgeLabelSize); + const font = settings.edgeLabelFont; + const weight = settings.edgeLabelWeight; + const color = resolveElementLabelColor(edgeData.labelColor, settings.edgeLabelColor, edgeData); + const padding = edgeData.labelPadding ?? 1; + + context.font = `${weight} ${size}px ${font}`; + const width = context.measureText(edgeData.label).width; + + const t = { start: 0.2, center: 0.5, end: 0.8 }[edgeData.labelPlacement] ?? 0.5; + const x = sourceData.x + (targetData.x - sourceData.x) * t + (edgeData.labelOffsetX ?? 0); + const y = sourceData.y + (targetData.y - sourceData.y) * t + (edgeData.labelOffsetY ?? 0); + + let angle = 0; + if (edgeData.labelAutoRotate) { + angle = Math.atan2(targetData.y - sourceData.y, targetData.x - sourceData.x); + // Keep text upright (never upside down); range (-π/2, π/2] so the two + // vertical-edge boundaries (±π/2 exactly) normalize consistently. + if (angle > Math.PI / 2) angle -= Math.PI; + else if (angle <= -Math.PI / 2) angle += Math.PI; + } + + context.save(); + context.translate(x, y); + context.rotate(angle); + + if (edgeData.labelBackground && edgeData.labelBackgroundColor) { + drawBackground( + context, + edgeData.labelBackgroundColor, + -width / 2 - padding, + -size / 2 - padding, + width + 2 * padding, + size + 2 * padding, + ); + } + + context.fillStyle = color; + context.fillText(edgeData.label, -width / 2, size * 0.35); + context.restore(); +} + +export { drawNodeLabel, drawEdgeLabel, placementVector, BAKED_DEFAULT_LABEL_COLOR }; diff --git a/src/graph/lasso_geometry.js b/src/graph/lasso_geometry.js new file mode 100644 index 0000000..2681be0 --- /dev/null +++ b/src/graph/lasso_geometry.js @@ -0,0 +1,73 @@ +/** + * Node-safe lasso geometry (MIGRATION.md Phase 3). + * + * Pure point-in-polygon math for the freehand lasso overlay; the DOM/canvas + * part lives in interactions.js. Points and polygon vertices are plain + * {x, y} objects in the same coordinate space (viewport pixels in practice). + */ + +/** + * Axis-aligned bounding box of a polygon. + * + * @param {Array<{x: number, y: number}>} polygon + * @returns {{minX: number, minY: number, maxX: number, maxY: number}|null} + * null for an empty polygon + */ +function polygonBBox(polygon) { + if (!polygon || polygon.length === 0) return null; + let minX = Infinity; + let minY = Infinity; + let maxX = -Infinity; + let maxY = -Infinity; + for (const p of polygon) { + if (p.x < minX) minX = p.x; + if (p.x > maxX) maxX = p.x; + if (p.y < minY) minY = p.y; + if (p.y > maxY) maxY = p.y; + } + return { minX, minY, maxX, maxY }; +} + +/** + * Ray-casting point-in-polygon test (even-odd rule). Works for concave and + * self-intersecting polygons, which freehand lassos routinely are. + * + * @param {{x: number, y: number}} point + * @param {Array<{x: number, y: number}>} polygon at least 3 vertices + * @returns {boolean} + */ +function pointInPolygon(point, polygon) { + if (!polygon || polygon.length < 3) return false; + let inside = false; + for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) { + const a = polygon[i]; + const b = polygon[j]; + const crossesRay = a.y > point.y !== b.y > point.y; + if (crossesRay && point.x < ((b.x - a.x) * (point.y - a.y)) / (b.y - a.y) + a.x) { + inside = !inside; + } + } + return inside; +} + +/** + * IDs of the points that fall inside the polygon, with a bbox prefilter so + * the O(vertices) test only runs for candidates near the lasso. + * + * @param {Array<{id: string, x: number, y: number}>} points + * @param {Array<{x: number, y: number}>} polygon + * @returns {string[]} + */ +function idsInsidePolygon(points, polygon) { + const bbox = polygonBBox(polygon); + if (!bbox || polygon.length < 3) return []; + const ids = []; + for (const point of points) { + if (point.x < bbox.minX || point.x > bbox.maxX) continue; + if (point.y < bbox.minY || point.y > bbox.maxY) continue; + if (pointInPolygon(point, polygon)) ids.push(point.id); + } + return ids; +} + +export { pointInPolygon, polygonBBox, idsInsidePolygon }; diff --git a/src/graph/layout.js b/src/graph/layout.js index 038cd12..ed7f56f 100644 --- a/src/graph/layout.js +++ b/src/graph/layout.js @@ -1,4 +1,5 @@ import {Popup} from "../utilities/popup.js"; +import {applyNoverlap} from "./layout_algorithms.js"; class GraphLayoutManager { constructor(cache) { @@ -15,48 +16,86 @@ class GraphLayoutManager { async changeLayout() { this.cache.data.selectedLayout = document.getElementById('selectView').value; await this.cache.ui.showLoading("Switching Workspace", this.cache.data.selectedLayout); + // Pin the overlay up across the whole switch so the inner render's + // #postRefresh hideLoading() can't drop it before bubble-sync and + // hide-disconnected finish. Released right before the position tween (which + // is meant to animate with the overlay clear) and again in finally. + this.cache.ui.holdLoading(); await new Promise(resolve => requestAnimationFrame(resolve)); const currentLayout = this.cache.data.layouts[this.cache.data.selectedLayout]; - // Apply per-view node and edge styles - await this.applyLayoutStyles(currentLayout); + // Animate node positions from the outgoing workspace to this one when it + // carries persisted positions. The adapter leaves positions in place + // through the render (pendingLayoutTransition) and tweens them once the + // loading overlay clears (runLayoutTransition, last step below). A + // position-less view (fresh template) has nothing to tween from/to and + // takes the normal snap path. + const animatePositions = currentLayout.positions?.size > 0; + this.cache.graph.pendingLayoutTransition = animatePositions; + + // finally: never leave pendingLayoutTransition stuck on. If any step below + // throws before runLayoutTransition consumes it, every later render would + // otherwise skip #applyPersistedPositions and freeze nodes at the outgoing + // workspace for the adapter's lifetime. + try { + // Apply per-view node and edge styles (positions held at the outgoing + // view's when animating, so the tween starts from what's on screen). + await this.applyLayoutStyles(currentLayout, animatePositions); + + // All layouts are now position-based, no need to re-apply layout algorithms + this.cache.ui.buildFilterUI(); - // All layouts are now position-based, no need to re-apply layout algorithms - this.cache.ui.buildFilterUI(); + // Update filter lock state based on whether this layout has a custom query + this.cache.qm.updateQueryTextArea(); + if (currentLayout["query"]) { + this.cache.EVENT_LOCKS.FILTERS_LOCKED_BY_MANUAL_QUERY = true; + } else { + this.cache.EVENT_LOCKS.FILTERS_LOCKED_BY_MANUAL_QUERY = false; + } + this.cache.ui.updateFilterLockState(); + this.cache.ui.clearActivePropsCacheOnLayoutChange(); - // Update filter lock state based on whether this layout has a custom query - this.cache.qm.updateQueryTextArea(); - if (currentLayout["query"]) { - this.cache.EVENT_LOCKS.FILTERS_LOCKED_BY_MANUAL_QUERY = true; - } else { - this.cache.EVENT_LOCKS.FILTERS_LOCKED_BY_MANUAL_QUERY = false; - } - this.cache.ui.updateFilterLockState(); - this.cache.ui.clearActivePropsCacheOnLayoutChange(); + await this.cache.metrics.updateMetricUI(); - await this.cache.metrics.updateMetricUI(); + this.cache.EVENT_LOCKS.ONCE_AFTER_RENDER_COMPLETED = false; - this.cache.EVENT_LOCKS.ONCE_AFTER_RENDER_COMPLETED = false; + await this.cache.gcm.decideToRenderOrDraw(true); - await this.cache.gcm.decideToRenderOrDraw(true); + // Restore hide disconnected nodes state for this workspace + await this.cache.gcm.applyHideDisconnectedState(); + + // Force bubble group sync - recalculate which nodes should be in groups for this view + this.cache.bubbleSetChanged = true; + await this.cache.bs.updateBubbleSetIfChanged(); - // Restore hide disconnected nodes state for this workspace - await this.cache.gcm.applyHideDisconnectedState(); + // Update manual bubble group status after layout change + this.cache.bs.updateManualGroupStatus(); + this.cache.bs.updateManualGroupButtonState(); + this.cache.bs.refreshBubbleStyleElements(); - // Force bubble group sync - recalculate which nodes should be in groups for this view - this.cache.bubbleSetChanged = true; - await this.cache.bs.updateBubbleSetIfChanged(); + // Everything that mutates the graph is done — drop the overlay now so the + // position tween below animates with it clear (its design intent). + this.cache.ui.releaseLoading(); + await this.cache.ui.hideLoading(); - // Update manual bubble group status after layout change - this.cache.bs.updateManualGroupStatus(); - this.cache.bs.updateManualGroupButtonState(); - this.cache.bs.refreshBubbleStyleElements(); + // Last: tween node positions from the outgoing view to this one (no-op + // when there was nothing to animate; consumes pendingLayoutTransition). + if (animatePositions) { + await this.cache.graph.runLayoutTransition(currentLayout.positions); + } - this.cache.ui.info(`Switched to workspace: ${this.cache.data.selectedLayout}`); + this.cache.ui.info(`Switched to workspace: ${this.cache.data.selectedLayout}`); + } finally { + // Defensive: if a step above threw before the release, drop the hold and + // the overlay here so a failed switch never strands a blocked UI. + this.cache.ui.releaseLoading(); + await this.cache.ui.hideLoading(); + if (this.cache.graph) this.cache.graph.pendingLayoutTransition = false; + } } - async applyLayoutStyles(layout) { + async applyLayoutStyles(layout, animatePositions = false) { // Apply per-view node styles - reset ALL nodes, not just styled ones const nodeUpdates = []; for (const [nodeID, node] of this.cache.nodeRef.entries()) { @@ -81,11 +120,19 @@ class GraphLayoutManager { newType = node.originalType || node.type; } - // Apply positions from the layout's position map (positions are stored separately) - const position = layout.positions.get(nodeID); - if (position && position.style) { - newStyle.x = position.style.x; - newStyle.y = position.style.y; + // Apply positions from the layout's position map (positions are stored + // separately). While animating a workspace switch, keep each node at its + // current (outgoing) position so the tween starts from what's on screen; + // runLayoutTransition moves it to the target afterwards. + if (animatePositions) { + newStyle.x = node.style.x; + newStyle.y = node.style.y; + } else { + const position = layout.positions.get(nodeID); + if (position && position.style) { + newStyle.x = position.style.x; + newStyle.y = position.style.y; + } } nodeUpdates.push({id: nodeID, type: newType, style: newStyle}); @@ -96,7 +143,7 @@ class GraphLayoutManager { this.cache.nodeRef.set(nodeID, node); } if (nodeUpdates.length > 0) { - this.cache.graph.updateNodeData(nodeUpdates); + await this.cache.graph.updateNodeData(nodeUpdates); } // Apply per-view edge styles - reset ALL edges, not just styled ones @@ -131,7 +178,7 @@ class GraphLayoutManager { this.cache.edgeRef.set(edgeID, edge); } if (edgeUpdates.length > 0) { - this.cache.graph.updateEdgeData(edgeUpdates); + await this.cache.graph.updateEdgeData(edgeUpdates); } // Bubble set styles are automatically used since all references now use the current layout @@ -175,6 +222,7 @@ class GraphLayoutManager { this.cache.data.layouts[result.name] = { internals: null, + layoutType: currentLayout.layoutType, // inherit origin type for re-layout default positions: structuredClone(currentLayout.positions), filters: structuredClone(currentLayout.filters), isCustom: true, @@ -208,9 +256,30 @@ class GraphLayoutManager { // - Refreshing all UI elements await this.cache.lm.changeLayout(); } else { + // Warn before kicking off a super-linear layout (dagre/mds) on a large + // graph: even off the main thread it can run for minutes, and the overlay + // blocks the UI for the whole time. Bail out cleanly if the user declines, + // before any workspace state is created. + const nodeCount = this.cache.graphData?.order ?? this.cache.nodeRef.size; + if ( + this.cache.DEFAULTS.EXPENSIVE_LAYOUTS.includes(result.templateType) && + nodeCount > this.cache.DEFAULTS.LAYOUT_NODE_WARNING_THRESHOLD + ) { + const proceed = await Popup.confirm( + `The "${result.templateType}" layout is computationally intensive and may ` + + `take several minutes on ${nodeCount.toLocaleString()} nodes. The UI stays ` + + `blocked until it finishes. Continue?`, + ); + if (!proceed) { + this.cache.ui.info("Creating workspace canceled"); + return; + } + } + // Create the layout structure first this.cache.data.layouts[result.name] = { internals: null, + layoutType: result.templateType, // remember origin type for re-layout default positions: new Map(), // Will be filled after layout filters: structuredClone(this.cache.data.filterDefaults), // Reset to defaults isCustom: true, // All layouts are custom (position-based) @@ -234,6 +303,11 @@ class GraphLayoutManager { this.cache.data.selectedLayout = result.name; await this.cache.ui.showLoading("Creating Workspace", `Applying ${result.templateType} layout`); + // Pin the overlay up across the whole creation so the inner render's + // #postRefresh hideLoading() can't drop it while the layout (possibly an + // expensive off-thread worker), bubble-sync and hide-disconnected are + // still running. Released right before the position tween, and in finally. + this.cache.ui.holdLoading(); // Clear the filter lock since this is a fresh template with no query this.cache.EVENT_LOCKS.FILTERS_LOCKED_BY_MANUAL_QUERY = false; @@ -258,32 +332,77 @@ class GraphLayoutManager { // Process filters to determine which nodes should be visible await this.cache.gcm.preRenderEvent(); - // Apply the layout algorithm once - await this.cache.graph.setLayout({type: result.templateType, ...this.cache.DEFAULTS.LAYOUT_INTERNALS[result.templateType]}); - await this.cache.graph.layout(); + // Snapshot the on-screen (outgoing-workspace) positions so the new + // template layout animates IN from them instead of snapping — same + // effect as switching between existing workspaces. graphData is y-up + // graphology, which is exactly what runLayoutTransition tweens toward. + const fromPositions = new Map(); + this.cache.graphData?.forEachNode((id, attrs) => { + if (Number.isFinite(attrs.x) && Number.isFinite(attrs.y)) { + fromPositions.set(id, { x: attrs.x, y: attrs.y }); + } + }); - // Persist the positions so they're stored permanently - await this.cache.lm.persistNodePositions(); + // setLayout/layout (possibly the off-thread worker), the full render + // pipeline and the position tween all run under one try so any failure — + // including the layout worker rejecting — releases the loading hold, + // drops the overlay and clears pendingLayoutTransition. + try { + // Apply the layout algorithm once + await this.cache.graph.setLayout({type: result.templateType, ...this.cache.DEFAULTS.LAYOUT_INTERNALS[result.templateType]}); + await this.cache.graph.layout(); + + // Persist the positions so they're stored permanently + await this.cache.lm.persistNodePositions(); + + // Restore the outgoing positions and hand the move to the animated + // transition: render paints them in place (pendingLayoutTransition skips + // the snap), then runLayoutTransition tweens to the persisted target. + const animateNewWorkspace = fromPositions.size > 0; + if (animateNewWorkspace) { + for (const [id, p] of fromPositions) { + if (this.cache.graphData.hasNode(id)) { + this.cache.graphData.mergeNodeAttributes(id, { x: p.x, y: p.y }); + } + } + this.cache.graph.pendingLayoutTransition = true; + } - // Render with the full pipeline - this.cache.EVENT_LOCKS.ONCE_AFTER_RENDER_COMPLETED = false; - await this.cache.gcm.decideToRenderOrDraw(true); + // Render with the full pipeline + this.cache.EVENT_LOCKS.ONCE_AFTER_RENDER_COMPLETED = false; + await this.cache.gcm.decideToRenderOrDraw(true); - // Reset hide disconnected state for new workspace - await this.cache.gcm.applyHideDisconnectedState(); + // Reset hide disconnected state for new workspace + await this.cache.gcm.applyHideDisconnectedState(); - // Ensure bubble groups are properly cleared and synced for this new view - this.cache.bubbleSetChanged = true; - await this.cache.bs.updateBubbleSetIfChanged(); + // Ensure bubble groups are properly cleared and synced for this new view + this.cache.bubbleSetChanged = true; + await this.cache.bs.updateBubbleSetIfChanged(); - // Update metrics and bubble group status - await this.cache.metrics.updateMetricUI(); - this.cache.bs.updateManualGroupStatus(); - this.cache.bs.updateManualGroupButtonState(); - this.cache.bs.refreshBubbleStyleElements(); + // Update metrics and bubble group status + await this.cache.metrics.updateMetricUI(); + this.cache.bs.updateManualGroupStatus(); + this.cache.bs.updateManualGroupButtonState(); + this.cache.bs.refreshBubbleStyleElements(); - await this.cache.ui.hideLoading(); - this.cache.ui.info(`Created Workspace: ${result.name} (${result.templateType})`); + // Graph mutations done — drop the overlay so the tween animates clear. + this.cache.ui.releaseLoading(); + await this.cache.ui.hideLoading(); + + // Tween the new layout in from the outgoing positions, once the overlay + // has cleared (no-op when there was nothing on screen to animate from). + if (animateNewWorkspace) { + await this.cache.graph.runLayoutTransition(this.cache.data.layouts[result.name].positions); + } + + this.cache.ui.info(`Created Workspace: ${result.name} (${result.templateType})`); + } finally { + // Defensive: release the hold + drop the overlay on any failure so a + // half-created workspace never strands a blocked UI; clear the tween flag. + this.cache.ui.releaseLoading(); + await this.cache.ui.hideLoading(); + if (this.cache.graph) this.cache.graph.pendingLayoutTransition = false; + } } } @@ -305,13 +424,6 @@ class GraphLayoutManager { await this.changeLayout(); } - async getPos() { - const zoom = await this.cache.graph.getZoom(); - const pos = await this.cache.graph.getPosition(); - console.log(`Zoom: ${zoom}`); - console.log(`Position: ${pos}`); - } - async layoutSelectedNodes(action) { const cache = this.cache; if (cache.selectedNodes.length === 0) return; @@ -556,7 +668,7 @@ class GraphLayoutManager { // becomes visible once the selection state changes and forces a re-read. const movedNodes = await cache.sm.getSelectedNodes(); if (movedNodes.length > 0) { - this.cache.graph.updateNodeData( + await this.cache.graph.updateNodeData( movedNodes.map(n => ({id: n.id, style: {x: n.style.x, y: n.style.y}})) ); } @@ -564,6 +676,123 @@ class GraphLayoutManager { await this.handleLayoutChangeLoadingEvent(action, eventLabels[action]); } + /** + * Minimally spread overlapping nodes apart (noverlap anti-collision pass) + * across ALL nodes of the current workspace. Deliberately ignores the + * selection: overlap removal is global by nature — separating a selected + * subset would just push nodes into their unselected neighbours. + * + * Runs directly on the live graphology model (cache.graphData, the same + * instance the sigma adapter renders); its attribute merges trigger the + * sigma refresh, and persistNodePositions() reads the moved positions back + * through the adapter facade (graph.getNodeData syncs nodeRef styles). + */ + async removeNodeOverlaps() { + const graph = this.cache.graphData; + if (!graph || graph.order < 2) return; + applyNoverlap(graph); + await this.persistNodePositions(); + await this.handleLayoutChangeLoadingEvent("Remove overlaps", + "Spread overlapping nodes apart minimally"); + } + + /** + * Re-run a layout algorithm across the ENTIRE current workspace, recomputing + * every node's position. Unlike layoutSelectedNodes (selection-scoped) and + * removeNodeOverlaps (noverlap-only), this discards the current arrangement + * and lays the whole graph out afresh with a chosen algorithm. + * + * Styles, filters, query and bubble-group membership are untouched — only + * positions change. Mirrors the template branch of addLayout (setLayout → + * layout → persist → animated transition) but stays on the current workspace + * instead of creating a new one. Defaults the picker to the workspace's + * original layout type so it doubles as "redo the layout I started with". + */ + async relayoutWorkspace() { + const currentName = this.cache.data.selectedLayout; + const currentLayout = this.cache.data.layouts[currentName]; + if (!currentLayout) return; + + const nodeCount = this.cache.graphData?.order ?? this.cache.nodeRef.size; + const result = await Popup.layoutSelectDialog(this.cache.DEFAULTS.LAYOUT_INTERNALS, { + defaultType: currentLayout.layoutType || this.cache.DEFAULTS.LAYOUT, + hasPositions: currentLayout.positions?.size > 0, + nodeCount, + expensiveLayouts: this.cache.DEFAULTS.EXPENSIVE_LAYOUTS, + warningThreshold: this.cache.DEFAULTS.LAYOUT_NODE_WARNING_THRESHOLD, + }); + if (!result) { + this.cache.ui.info("Re-layout canceled"); + return; + } + + const layoutType = result.templateType; + + await this.cache.ui.showLoading("Re-layouting Workspace", `Applying ${layoutType} layout`); + // Pin the overlay up across the whole re-layout so the inner render's + // hideLoading() can't drop it while the layout (possibly an expensive + // off-thread worker) and bubble-sync are still running. Released right + // before the position tween, and again in finally. + this.cache.ui.holdLoading(); + + // Snapshot the on-screen positions so the new layout animates IN from them + // instead of snapping (same approach as the addLayout template branch). + const fromPositions = new Map(); + this.cache.graphData?.forEachNode((id, attrs) => { + if (Number.isFinite(attrs.x) && Number.isFinite(attrs.y)) { + fromPositions.set(id, {x: attrs.x, y: attrs.y}); + } + }); + + try { + await this.cache.graph.setLayout({type: layoutType, ...this.cache.DEFAULTS.LAYOUT_INTERNALS[layoutType]}); + await this.cache.graph.layout(); + + // Remember the chosen type so the next re-layout (and reload) defaults to it. + currentLayout.layoutType = layoutType; + + // Persist the freshly computed positions as this workspace's positions. + await this.persistNodePositions(); + + // Restore the outgoing positions and hand the move to the animated + // transition: render paints them in place (pendingLayoutTransition skips + // the snap), then runLayoutTransition tweens to the persisted target. + const animate = fromPositions.size > 0; + if (animate) { + for (const [id, p] of fromPositions) { + if (this.cache.graphData.hasNode(id)) { + this.cache.graphData.mergeNodeAttributes(id, {x: p.x, y: p.y}); + } + } + this.cache.graph.pendingLayoutTransition = true; + } + + this.cache.EVENT_LOCKS.ONCE_AFTER_RENDER_COMPLETED = false; + await this.cache.gcm.decideToRenderOrDraw(true); + + // Bubble outlines hug node positions — re-sync them to the new layout. + this.cache.bubbleSetChanged = true; + await this.cache.bs.updateBubbleSetIfChanged(); + this.cache.bs.refreshBubbleStyleElements(); + + // Graph mutations done — drop the overlay so the tween animates clear. + this.cache.ui.releaseLoading(); + await this.cache.ui.hideLoading(); + + if (animate) { + await this.cache.graph.runLayoutTransition(currentLayout.positions); + } + + this.cache.ui.info(`Re-layouted workspace: ${currentName} (${layoutType})`); + } finally { + // Defensive: release the hold + drop the overlay on any failure so a + // half-applied re-layout never strands a blocked UI; clear the tween flag. + this.cache.ui.releaseLoading(); + await this.cache.ui.hideLoading(); + if (this.cache.graph) this.cache.graph.pendingLayoutTransition = false; + } + } + async getPositions() { const posCopy = []; for (const node of await this.cache.graph.getNodeData()) { diff --git a/src/graph/layout_algorithms.js b/src/graph/layout_algorithms.js new file mode 100644 index 0000000..c15de90 --- /dev/null +++ b/src/graph/layout_algorithms.js @@ -0,0 +1,281 @@ +/** + * Node-safe layout execution (MIGRATION.md Phase 5). + * + * Maps the app's layout vocabulary (config LAYOUT_INTERNALS: force, circular, + * circlepack, radial, concentric, grid, random, mds, dagre) onto graphology + * layouts and headless @antv/layout v2 instances. Writes x/y straight into the + * graphology graph — no DOM/WebGL, so the whole module is unit-testable under + * vitest. + */ +import { + circular, + circlepack, + random, + forceAtlas2, + FA2Layout, + noverlap, + RadialLayout, + ConcentricLayout, + MDSLayout, + DagreLayout, +} from "../lib/graphology.bundle.mjs"; +import { LAYOUT_WORKER_SOURCE } from "../lib/layout_worker_source.js"; + +const FORCE_ITERATIONS = 200; +const GRID_SPACING = 100; + +// Noverlap anti-collision post-pass. The algorithm converges early once no +// node pair overlaps; the iteration cap only bounds pathological cases. +const NOVERLAP_MAX_ITERATIONS = 100; +const NOVERLAP_MARGIN = 5; // graph-space px kept between node circles + +// Live force-layout time budget. FA2 has no usable convergence signal, so the +// worker simply runs for a bounded wall-clock window: a base so small graphs +// settle visibly, a per-node share so larger graphs get proportionally more +// time, and a hard cap so huge graphs never hold the render pipeline hostage +// (render() awaits executeLayout before persisting positions). +const FORCE_ANIMATE_BASE_MS = 500; +const FORCE_ANIMATE_PER_NODE_MS = 2; +const FORCE_ANIMATE_MAX_MS = 5000; + +/** Graphs with a worker-supervised force layout currently in flight. */ +const animatingGraphs = new WeakSet(); + +/** + * Run FA2 through the web-worker supervisor for a bounded time window. + * Sigma is bound to the same graphology instance, so every per-tick position + * assign from the supervisor triggers a refresh — the layout animates live + * without blocking the main thread. Resolves once the window elapses and the + * worker is killed. Re-entrant calls for a graph that is already animating + * are no-ops (the running supervisor uses the same inferred settings). + * @param {import('graphology').default} graph + * @param {typeof FA2Layout} Supervisor + * @returns {Promise} + */ +async function executeForceAnimated(graph, Supervisor) { + if (animatingGraphs.has(graph)) return; + animatingGraphs.add(graph); + const budgetMs = Math.min( + FORCE_ANIMATE_MAX_MS, + FORCE_ANIMATE_BASE_MS + graph.order * FORCE_ANIMATE_PER_NODE_MS, + ); + let layout = null; + try { + layout = new Supervisor(graph, { settings: forceAtlas2.inferSettings(graph) }); + layout.start(); + await new Promise((resolve) => setTimeout(resolve, budgetMs)); + } finally { + if (layout) { + layout.stop(); + layout.kill(); // terminates the worker + unbinds the graph listeners + } + animatingGraphs.delete(graph); + } +} + +// @antv/layout v2 classes the app exposes. `negateY` flips the layout's y on +// the way into graphology: radial/concentric/mds are rotationally symmetric so +// orientation is irrelevant, but Dagre emits rank depth as increasing y +// (root at y=0), and graphology is y-up — without the flip a "TB" tree would +// render root-at-bottom. Negating y makes rankdir "TB" read top-to-bottom. +const ANTV_LAYOUTS = { + radial: { Layout: RadialLayout, negateY: false }, + concentric: { Layout: ConcentricLayout, negateY: false }, + mds: { Layout: MDSLayout, negateY: false }, + dagre: { Layout: DagreLayout, negateY: true }, +}; + +/** + * Run an @antv/layout v2 class headlessly and merge the resulting positions + * back into the graphology graph. The instance mutates an internal model; + * results are read via forEachNode (flat {id, x, y} fields, no data wrapper). + * Layout failures reject and propagate to the render pipeline. + * @param {boolean} [negateY] flip the layout's y into graphology's y-up frame + * @returns {Promise} + */ +async function executeAntvLayout(graph, LayoutClass, options, negateY = false) { + const data = { + nodes: graph.mapNodes((id) => ({ id })), + edges: graph.mapEdges((id, _attrs, source, target) => ({ id, source, target })), + }; + const inst = new LayoutClass(options); + try { + await inst.execute(data); + inst.forEachNode(({ id, x, y }) => { + // Non-finite output leaves the node at its pre-layout position + // (deliberate: a partial layout beats NaN coords corrupting the graph). + if (Number.isFinite(x) && Number.isFinite(y)) { + graph.mergeNodeAttributes(id, { x, y: negateY ? -y : y }); + } + }); + } finally { + inst.destroy(); // frees the layout's internal maps + } +} + +/** + * Lazily-created object URL for the layout worker. Built once from the embedded + * IIFE source (vendor_libs bundles @antv/layout into LAYOUT_WORKER_SOURCE) and + * reused for every worker so each layout run is just a cheap `new Worker(url)`. + * Touched only when a worker is actually spawned — never at module load. + */ +let layoutWorkerUrl = null; + +/** Default browser worker factory: a Blob worker over the embedded source. */ +function defaultLayoutWorkerFactory() { + if (layoutWorkerUrl === null) { + const blob = new Blob([LAYOUT_WORKER_SOURCE], { + type: "application/javascript", + }); + layoutWorkerUrl = URL.createObjectURL(blob); + } + return new Worker(layoutWorkerUrl); +} + +/** + * Run an @antv/layout v2 class in a worker thread and merge the positions back + * into the graphology graph. Same contract as executeAntvLayout (the synchronous + * twin) — flat {id,x,y} read-back, y-up negation, non-finite coords skipped — but + * the CPU-bound execute() runs off the main thread so a large graph never + * freezes the UI while the loading overlay is up. The worker is single-use: + * spawned, awaited, terminated. + * @param {string} type antv layout key (radial/concentric/mds/dagre) + * @param {() => Worker} workerFactory test seam (vitest has no Worker global) + * @returns {Promise} + */ +async function executeAntvLayoutWorker(graph, type, options, negateY, workerFactory) { + const nodes = graph.mapNodes((id) => ({ id })); + const edges = graph.mapEdges((id, _attrs, source, target) => ({ id, source, target })); + const worker = workerFactory(); + try { + const positions = await new Promise((resolve, reject) => { + worker.onmessage = (event) => { + if (event.data && event.data.error) { + reject(new Error(event.data.error)); + } else { + resolve(event.data.positions); + } + }; + worker.onerror = (event) => { + reject(new Error(event.message || "Layout worker failed")); + }; + worker.postMessage({ type, options, nodes, edges }); + }); + for (const { id, x, y } of positions) { + // Skip non-finite output (partial layout beats NaN-corrupted coords) and + // nodes that vanished while the worker ran. + if (Number.isFinite(x) && Number.isFinite(y) && graph.hasNode(id)) { + graph.mergeNodeAttributes(id, { x, y: negateY ? -y : y }); + } + } + } finally { + worker.terminate(); + } +} + +/** + * Anti-collision post-pass: minimally spreads overlapping nodes apart. + * Node sizes are read from the graphology `size` attribute (sigma radius, + * always set by graph_model's node mapper) via noverlap's default reducer; + * nodes end up ≥ size_a + size_b + 2·margin apart once converged. Mutates + * x/y in place — symmetric in y, so it is agnostic to the app-model y-flip. + * @param {import('graphology').default} graph + */ +export function applyNoverlap(graph) { + if (graph.order < 2) return; + noverlap.assign(graph, { + maxIterations: NOVERLAP_MAX_ITERATIONS, + settings: { margin: NOVERLAP_MARGIN }, + }); +} + +/** + * Execute a layout spec against a graphology graph, assigning x/y per node. + * @param {import('graphology').default} graph + * @param {{type?: string, noverlap?: boolean}|null|undefined} spec type + the + * LAYOUT_INTERNALS options for it; missing/unknown type falls back to + * forceAtlas2. `noverlap: true` runs the anti-collision post-pass after the + * base layout completes (any type). + * @param {{ForceSupervisor?: typeof FA2Layout, LayoutWorkerFactory?: () => Worker}} [testOverrides] + * test seams (vitest has no Worker global, so the worker branches are + * otherwise unreachable under node): substitute the FA2 worker supervisor + * class, and/or inject a factory for the @antv/layout worker. + * @returns {Promise} + */ +export async function executeLayout(graph, spec, testOverrides = {}) { + const { noverlap: removeOverlaps, ...baseSpec } = spec ?? {}; + await executeBaseLayout(graph, baseSpec, testOverrides); + if (removeOverlaps === true) applyNoverlap(graph); +} + +/** The pre-post-pass layout dispatch — see executeLayout. */ +async function executeBaseLayout(graph, spec, testOverrides) { + const { type, ...options } = spec; + if (type === "circular") { + // graphology's circular ignores the G6-era startRadius/endRadius options. + circular.assign(graph, { + scale: Math.max(100, 12 * Math.sqrt(graph.order)), + }); + return; + } + if (type === "grid") { + const cols = Math.ceil(Math.sqrt(graph.order)) || 1; + let i = 0; + graph.forEachNode((id) => { + graph.mergeNodeAttributes(id, { + x: (i % cols) * GRID_SPACING, + y: Math.floor(i / cols) * GRID_SPACING, + }); + i++; + }); + return; + } + if (type === "circlepack") { + // d3-hierarchy circle packing; each node's circle radius is its `size` + // attribute (sigma radius, set by graph_model's node mapper). center:0 + // packs the cluster around the origin. Assigns x/y in place. + circlepack.assign(graph, { center: 0 }); + return; + } + if (type === "random") { + // Uniform scatter around the origin. center:0 shifts random's [0,scale) + // range to [-scale/2, scale/2); scale tracks node count so the cloud grows + // with the graph instead of collapsing toward a point. + random.assign(graph, { + center: 0, + scale: Math.max(200, 24 * Math.sqrt(graph.order)), + }); + return; + } + if (graph.order < 2) return; // FA2/inferSettings and @antv layouts need ≥2 nodes + const antv = ANTV_LAYOUTS[type]; + if (antv) { + // Browser/Electron: run the heavy headless layout in a worker so a large + // graph never freezes the main thread. Under node (vitest, no Worker) and + // when no factory is injected, fall back to the synchronous twin — same + // positions, just on-thread. + const workerFactory = + testOverrides.LayoutWorkerFactory ?? + (typeof Worker === "undefined" ? null : defaultLayoutWorkerFactory); + if (workerFactory) { + await executeAntvLayoutWorker(graph, type, options, antv.negateY, workerFactory); + } else { + await executeAntvLayout(graph, antv.Layout, options, antv.negateY); + } + return; + } + // 'force' and everything else → forceAtlas2. Where Worker exists (browser, + // Electron renderer) the FA2 worker supervisor animates the layout live; + // under node (vitest) Worker is undefined → deterministic synchronous path. + const Supervisor = + testOverrides.ForceSupervisor ?? + (typeof Worker === "undefined" ? null : FA2Layout); + if (Supervisor) { + await executeForceAnimated(graph, Supervisor); + return; + } + forceAtlas2.assign(graph, { + iterations: FORCE_ITERATIONS, + settings: forceAtlas2.inferSettings(graph), + }); +} diff --git a/src/graph/minimap.js b/src/graph/minimap.js new file mode 100644 index 0000000..25d7872 --- /dev/null +++ b/src/graph/minimap.js @@ -0,0 +1,184 @@ +/** + * Browser-only minimap for the sigma renderer (MIGRATION.md Phase 4, + * replaces the G6 minimap plugin). Deliberately minimal: visible nodes as + * dots over a graph-space bounding-box fit, the current viewport as a + * rectangle, click/drag pans the camera. No edges, no labels. + * + * Position: bottom-right — the G6 plugin was configured "bottom-left" but + * style.css always overrode it to bottom-right, so that is the shipped + * position this port preserves (CSS class .gll-minimap). + */ +const MINIMAP_WIDTH = 200; +const MINIMAP_HEIGHT = 120; +const MINIMAP_PADDING = 8; +const DOT_RADIUS = 1.5; +const DOT_COLOR = "#403C53"; +const DOT_COLOR_DARK = "#AAA3C4"; // brand purple is invisible on the dark thumb +const VIEWPORT_STROKE = "#C33D35"; + +class Minimap { + /** + * @param {object} adapter SigmaAdapter (owns sigma + graphology) + * @param {HTMLElement} container the sigma container (#innerGraphContainer) + */ + constructor(adapter, container) { + this.adapter = adapter; + this.killed = false; + this.rafHandle = null; + this.dragging = false; + // Graph-space fit of the last draw; #panTo inverts it for clicks. + this.fit = null; + + const canvas = document.createElement("canvas"); + canvas.className = "gll-minimap"; + canvas.width = MINIMAP_WIDTH; + canvas.height = MINIMAP_HEIGHT; + canvas.addEventListener("pointerdown", (e) => this.#onPointerDown(e)); + canvas.addEventListener("pointermove", (e) => this.#onPointerMove(e)); + canvas.addEventListener("pointerup", (e) => this.#onPointerUp(e)); + canvas.addEventListener("pointercancel", () => { + this.dragging = false; + }); + container.appendChild(canvas); + this.canvas = canvas; + this.ctx = canvas.getContext("2d"); + + this.renderHandler = () => this.scheduleRedraw(); + adapter.sigma.on("afterRender", this.renderHandler); + this.scheduleRedraw(); + } + + destroy() { + if (this.killed) return; + this.killed = true; + if (this.rafHandle !== null) cancelAnimationFrame(this.rafHandle); + this.adapter.sigma.off("afterRender", this.renderHandler); + this.canvas.remove(); + } + + scheduleRedraw() { + if (this.killed || this.rafHandle !== null) return; + this.rafHandle = requestAnimationFrame(() => { + this.rafHandle = null; + this.#draw(); + }); + } + + // ------------------------------------------------------------------ draw + + /** Graph-space bbox of visible nodes → thumbnail transform (y flipped: + * graph space is y-up, canvas is y-down — matches the main view). */ + #computeFit() { + const graph = this.adapter.graph; + let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity; + graph.forEachNode((id, attrs) => { + if (attrs.hidden) return; + if (attrs.x < minX) minX = attrs.x; + if (attrs.x > maxX) maxX = attrs.x; + if (attrs.y < minY) minY = attrs.y; + if (attrs.y > maxY) maxY = attrs.y; + }); + if (!isFinite(minX)) return null; + const scale = Math.min( + (MINIMAP_WIDTH - 2 * MINIMAP_PADDING) / Math.max(maxX - minX, 1e-9), + (MINIMAP_HEIGHT - 2 * MINIMAP_PADDING) / Math.max(maxY - minY, 1e-9), + ); + return { + scale, + midX: (minX + maxX) / 2, + midY: (minY + maxY) / 2, + }; + } + + #toThumb(fit, x, y) { + return { + x: MINIMAP_WIDTH / 2 + (x - fit.midX) * fit.scale, + y: MINIMAP_HEIGHT / 2 - (y - fit.midY) * fit.scale, + }; + } + + #toGraph(fit, tx, ty) { + return { + x: fit.midX + (tx - MINIMAP_WIDTH / 2) / fit.scale, + y: fit.midY - (ty - MINIMAP_HEIGHT / 2) / fit.scale, + }; + } + + #draw() { + if (this.killed) return; + const ctx = this.ctx; + ctx.clearRect(0, 0, MINIMAP_WIDTH, MINIMAP_HEIGHT); + + const fit = this.#computeFit(); + this.fit = fit; + if (!fit) return; + + const graph = this.adapter.graph; + const isDark = document.documentElement.dataset.theme === "dark"; + ctx.fillStyle = isDark ? DOT_COLOR_DARK : DOT_COLOR; + graph.forEachNode((id, attrs) => { + if (attrs.hidden) return; + const p = this.#toThumb(fit, attrs.x, attrs.y); + ctx.fillRect(p.x - DOT_RADIUS, p.y - DOT_RADIUS, 2 * DOT_RADIUS, 2 * DOT_RADIUS); + }); + + // Current viewport rectangle (viewport corners → graph → thumbnail). + // Axis-aligned rect assumes camera.angle === 0 (the app never rotates the camera). + const sigma = this.adapter.sigma; + const { width, height } = sigma.getDimensions(); + const a = this.#toThumb(fit, ...corner(sigma, 0, 0)); + const b = this.#toThumb(fit, ...corner(sigma, width, height)); + ctx.strokeStyle = VIEWPORT_STROKE; + ctx.lineWidth = 1; + ctx.strokeRect( + Math.min(a.x, b.x), + Math.min(a.y, b.y), + Math.abs(b.x - a.x), + Math.abs(b.y - a.y), + ); + } + + // ----------------------------------------------------------- interaction + + #panTo(event) { + if (!this.fit) return; + const rect = this.canvas.getBoundingClientRect(); + const graphPoint = this.#toGraph( + this.fit, + event.clientX - rect.left, + event.clientY - rect.top, + ); + const sigma = this.adapter.sigma; + // Round-trip through the current camera yields the camera-independent + // framed coordinate of the graph point (same pattern as focusElement). + const framed = sigma.viewportToFramedGraph(sigma.graphToViewport(graphPoint)); + sigma.getCamera().setState({ x: framed.x, y: framed.y }); + } + + #onPointerDown(event) { + if (event.button !== 0) return; + event.stopPropagation(); + this.dragging = true; + this.canvas.setPointerCapture(event.pointerId); + this.#panTo(event); + } + + #onPointerMove(event) { + if (!this.dragging) return; + this.#panTo(event); + } + + #onPointerUp(event) { + this.dragging = false; + if (this.canvas.hasPointerCapture(event.pointerId)) { + this.canvas.releasePointerCapture(event.pointerId); + } + } +} + +function corner(sigma, x, y) { + const p = sigma.viewportToGraph({ x, y }); + return [p.x, p.y]; +} + +export { Minimap }; diff --git a/src/graph/pie_slices.js b/src/graph/pie_slices.js new file mode 100644 index 0000000..edb2427 --- /dev/null +++ b/src/graph/pie_slices.js @@ -0,0 +1,97 @@ +/** + * Node-safe pie-slice model for @sigma/node-piechart (no DOM/WebGL — vitest + * covers it, and graph_model.js may depend on it). + * + * The piechart program is created with a FIXED number of slices; slice K reads + * its angle from the per-node `pieValueK` attribute and its color from + * `pieColorK` (see sigma_adapter.buildProgramRegistry). So the app's job is two + * pure steps: + * 1. turn a node's chosen properties into an ordered [{value, color}] list + * (buildCategoricalSlices / buildNumericSlices), and + * 2. flatten that list onto the fixed pieValueK/pieColorK slots, padding the + * unused tail with value 0 + a transparent color so it collapses to + * nothing (pieAttributesFromSlices). + * + * Categorical slices are equal-weight (presence = 1) so the disc splits evenly + * across the values a node carries; numeric slices weight by magnitude. + */ + +// Unused slots: zero angle + transparent so the program draws nothing for them. +const TRANSPARENT = "#00000000"; + +/** + * Equal-weight slices for the distinct categorical values a node carries + * across the selected properties. Order is preserved (caller controls it); + * empty/nullish values are skipped. Each present value contributes one slice. + * + * @param {Iterable} distinctValues the node's values (already deduped) + * @param {Map|Record} valueColors value → hex + * @param {string} missingColor fallback when a value has no assigned color + * @returns {Array<{value: number, color: string}>} + */ +function buildCategoricalSlices(distinctValues, valueColors, missingColor) { + const lookup = valueColors instanceof Map ? valueColors : new Map(Object.entries(valueColors ?? {})); + const slices = []; + for (const raw of distinctValues ?? []) { + if (raw === null || raw === undefined) continue; + const value = String(raw).trim(); + if (value === "") continue; + slices.push({ value: 1, color: lookup.get(value) ?? missingColor }); + } + return slices; +} + +/** + * Magnitude-weighted slices: one slice per selected numeric property, angle + * proportional to that property's value on the node. Non-finite or negative + * values are clamped to 0 (a zero-angle, invisible slice) rather than dropped, + * so the slice order stays aligned with the property order and the legend. + * + * @param {Array} orderedProps selected property ids, in legend order + * @param {Map|Record} valueByProp prop → value + * @param {Map|Record} propColors prop → hex + * @param {string} missingColor fallback when a property has no assigned color + * @returns {Array<{value: number, color: string}>} + */ +function buildNumericSlices(orderedProps, valueByProp, propColors, missingColor) { + const values = valueByProp instanceof Map ? valueByProp : new Map(Object.entries(valueByProp ?? {})); + const colors = propColors instanceof Map ? propColors : new Map(Object.entries(propColors ?? {})); + const slices = []; + for (const prop of orderedProps ?? []) { + const raw = Number(values.get(prop)); + const value = Number.isFinite(raw) && raw > 0 ? raw : 0; + slices.push({ value, color: colors.get(prop) ?? missingColor }); + } + return slices; +} + +/** + * Flatten an ordered slice list onto the program's fixed pieValueK/pieColorK + * slots. Returns `type: "pie"` so the renderer routes the node to the piechart + * program. Slices beyond `maxSlices` are dropped (the picker warns before this + * point — see DEFAULTS.NODE.PIE.MAX_SLICES); the unused tail gets value 0 and a + * transparent color so old/larger pies never leave ghost wedges after a change. + * + * @param {Array<{value: number, color: string}>} slices + * @param {number} maxSlices program slice count (DEFAULTS.NODE.PIE.MAX_SLICES) + * @param {string} defaultColor fallback for a present slice missing a color + * @returns {{type: "pie"} & Record} + */ +function pieAttributesFromSlices(slices, maxSlices, defaultColor) { + const effective = Array.isArray(slices) ? slices.slice(0, maxSlices) : []; + const attrs = { type: "pie" }; + for (let k = 0; k < maxSlices; k++) { + const slice = effective[k]; + if (slice) { + const value = Number.isFinite(slice.value) && slice.value > 0 ? slice.value : 0; + attrs[`pieValue${k}`] = value; + attrs[`pieColor${k}`] = slice.color || defaultColor; + } else { + attrs[`pieValue${k}`] = 0; + attrs[`pieColor${k}`] = TRANSPARENT; + } + } + return attrs; +} + +export { buildCategoricalSlices, buildNumericSlices, pieAttributesFromSlices }; diff --git a/src/graph/selection.js b/src/graph/selection.js index 7db0721..5580823 100644 --- a/src/graph/selection.js +++ b/src/graph/selection.js @@ -1,4 +1,4 @@ -import {StaticUtilities} from "../utilities/static.js"; +import { StaticUtilities } from '../utilities/static.js'; class GraphSelectionManager { constructor(cache) { @@ -16,7 +16,11 @@ class GraphSelectionManager { /** * Selects given element IDs while deselecting all others */ - async selectElements(elementIDs, refMap, stateOverride = "selected") { + async selectElements(elementIDs, refMap, stateOverride = 'selected') { + // cache.graph is null both before any data is loaded and when WebGL init + // failed (dead renderer); selection is a silent no-op in either state. + if (!this.cache.graph) return; + const visibility = {}; const elementIDsAsSet = new Set(elementIDs); @@ -26,7 +30,8 @@ class GraphSelectionManager { const shouldSelect = elementIDsAsSet.has(nodeOrEdgeID); if (shouldSelect && !state.includes(stateOverride)) state.push(stateOverride); - if (!shouldSelect && state.includes(stateOverride)) state.splice(state.indexOf(stateOverride), 1); + if (!shouldSelect && state.includes(stateOverride)) + state.splice(state.indexOf(stateOverride), 1); visibility[nodeOrEdgeID] = state; } @@ -35,47 +40,58 @@ class GraphSelectionManager { } async updateSelectedState(elemData, enable) { - await this.cache.ui.showLoading(enable ? "Selecting" : "Deselecting", `Modifying selection of ${elemData.length} elements`); - await new Promise(resolve => requestAnimationFrame(resolve)); + if (!this.cache.graph) return; + + await this.cache.ui.showLoading( + enable ? 'Selecting' : 'Deselecting', + `Modifying selection of ${elemData.length} elements` + ); + await new Promise((resolve) => requestAnimationFrame(resolve)); const stateMap = {}; for (const item of elemData) { const states = await this.cache.graph.getElementState(item.id); - if (enable && !states.includes("selected")) states.push("selected"); - if (!enable && states.includes("selected")) states.splice(states.indexOf("selected"), 1); + if (enable && !states.includes('selected')) states.push('selected'); + if (!enable && states.includes('selected')) states.splice(states.indexOf('selected'), 1); stateMap[item.id] = states; } await this.cache.graph.setElementState(stateMap); - // Update manual bubble group button state when selection changes - this.cache.bs.updateManualGroupButtonState(); + // Button resync happens in updateSelectedNodesAndEdges (after-draw), once + // cache.selectedNodes reflects this change — doing it here reads stale data. await this.cache.ui.hideLoading(); - await new Promise(resolve => requestAnimationFrame(resolve)); + await new Promise((resolve) => requestAnimationFrame(resolve)); } async getSelectedNodes() { - return await this.cache.graph.getNodeData().filter(n => n.states?.includes("selected")); + if (!this.cache.graph) return []; + + return await this.cache.graph.getNodeData().filter((n) => n.states?.includes('selected')); } updateElementSelectedState(element, shouldSelect) { if (!element.states) { element.states = []; } - if (shouldSelect && !element.states.includes("selected")) { - element.states.push("selected"); + if (shouldSelect && !element.states.includes('selected')) { + element.states.push('selected'); } - if (!shouldSelect && element.states.includes("selected")) { - element.states.splice(element.states.indexOf("selected"), 1); + if (!shouldSelect && element.states.includes('selected')) { + element.states.splice(element.states.indexOf('selected'), 1); } } async toggleSelectionForAllNodes(enable) { + if (!this.cache.graph) return; + const nodes = await this.cache.graph.getNodeData(); await this.updateSelectedState(nodes, enable); } async toggleSelectionForAllEdges(enable) { + if (!this.cache.graph) return; + const edges = await this.cache.graph.getEdgeData(); await this.updateSelectedState(edges, enable); } @@ -90,15 +106,17 @@ class GraphSelectionManager { for (const node of this.cache.graph.getNodeData()) { const states = await this.cache.graph.getElementState(node.id); const shouldSelect = snapshot.nodes.includes(node.id); - if (shouldSelect && !states.includes("selected")) states.push("selected"); - if (!shouldSelect && states.includes("selected")) states.splice(states.indexOf("selected"), 1); + if (shouldSelect && !states.includes('selected')) states.push('selected'); + if (!shouldSelect && states.includes('selected')) + states.splice(states.indexOf('selected'), 1); stateMap[node.id] = states; } for (const edge of this.cache.graph.getEdgeData()) { const states = await this.cache.graph.getElementState(edge.id); const shouldSelect = snapshot.edges.includes(edge.id); - if (shouldSelect && !states.includes("selected")) states.push("selected"); - if (!shouldSelect && states.includes("selected")) states.splice(states.indexOf("selected"), 1); + if (shouldSelect && !states.includes('selected')) states.push('selected'); + if (!shouldSelect && states.includes('selected')) + states.splice(states.indexOf('selected'), 1); stateMap[edge.id] = states; } await this.cache.graph.setElementState(stateMap); @@ -108,36 +126,43 @@ class GraphSelectionManager { } undoSelection() { + // Silent no-op without a renderer: syncSelectionCacheAndElementStates + // below reads cache.graph, and moving the memory index without syncing + // would desync the snapshot stack. + if (!this.cache.graph) return; + if (this.cache.selectedMemoryIndex > 0) { this.cache.selectedMemoryIndex--; this.syncSelectionCacheAndElementStates(); } else { - this.cache.ui.warning("Cannot undo!"); + this.cache.ui.warning('Cannot undo!'); } } redoSelection() { + if (!this.cache.graph) return; + if (this.cache.selectionMemory.length > this.cache.selectedMemoryIndex + 1) { this.cache.selectedMemoryIndex++; this.syncSelectionCacheAndElementStates(); } else { - this.cache.ui.warning("Cannot redo!"); + this.cache.ui.warning('Cannot redo!'); } } async addNodeOrEdgeIDsToSelectionWrapper(elementIDs, isNode) { const shouldAdd = isNode - ? !document.getElementById("selectByNodeIDsSwitch").checked - : !document.getElementById("selectByEdgeIDsSwitch").checked; - const elementIDsAsArray = elementIDs ? elementIDs.split(",") : []; + ? !document.getElementById('selectByNodeIDsSwitch').checked + : !document.getElementById('selectByEdgeIDsSwitch').checked; + const elementIDsAsArray = elementIDs ? elementIDs.split(',') : []; await this.addNodeOrEdgeIDsToSelection(elementIDsAsArray, isNode, shouldAdd); } async addNodeOrEdgeLabelsToSelectionWrapper(elementLabels, isNode) { - const elementLabelsAsArray = elementLabels ? elementLabels.split(",") : []; + const elementLabelsAsArray = elementLabels ? elementLabels.split(',') : []; - const elementIDs = elementLabelsAsArray.flatMap(label => { + const elementIDs = elementLabelsAsArray.flatMap((label) => { const set = isNode ? this.cache.nodeLabelToNodeIDs.get(label) : this.cache.edgeLabelToEdgeIDs.get(label); @@ -145,18 +170,19 @@ class GraphSelectionManager { }); const shouldAdd = isNode - ? !document.getElementById("selectByNodeLabelsSwitch").checked - : !document.getElementById("selectByEdgeLabelsSwitch").checked; + ? !document.getElementById('selectByNodeLabelsSwitch').checked + : !document.getElementById('selectByEdgeLabelsSwitch').checked; await this.addNodeOrEdgeIDsToSelection(elementIDs, isNode, shouldAdd); } async addNodeOrEdgeIDsToSelection(elementIDs, isNode, shouldAdd) { - - const elemDescription = isNode ? "Node" : "Edge"; + const elemDescription = isNode ? 'Node' : 'Edge'; const visibleElements = isNode ? this.cache.nodeIDsToBeShown : this.cache.edgeIDsToBeShown; - const existingElements = isNode ? this.cache.nodeRef.keys().toArray() : this.cache.edgeRef.keys().toArray(); + const existingElements = isNode + ? this.cache.nodeRef.keys().toArray() + : this.cache.edgeRef.keys().toArray(); const selectedElements = isNode ? this.cache.selectedNodes : this.cache.selectedEdges; const ref = isNode ? this.cache.nodeRef : this.cache.edgeRef; @@ -167,7 +193,9 @@ class GraphSelectionManager { } if (!visibleElements.has(elemID)) { - this.cache.ui.warning(`Cannot update selection of ${elemDescription} with ID: '${elemID}' as it is not visible.`); + this.cache.ui.warning( + `Cannot update selection of ${elemDescription} with ID: '${elemID}' as it is not visible.` + ); continue; } @@ -206,18 +234,17 @@ class GraphSelectionManager { } return neighborsInSelection <= 1; - } + }; const update = async () => { if (edgesToShow.length > 0) await this.updateSelectedState(edgesToShow, true); if (edgesToHide.length > 0) await this.updateSelectedState(edgesToHide, false); if (nodesToShow.length > 0) await this.updateSelectedState(nodesToShow, true); if (nodesToHide.length > 0) await this.updateSelectedState(nodesToHide, false); - } + }; switch (mode) { - - case "expand-edges": + case 'expand-edges': for (let nodeID of this.cache.selectedNodes) { for (let edgeID of this.cache.nodeIDToEdgeIDs.get(nodeID) || []) { edgesToShow.push(this.cache.edgeRef.get(edgeID)); @@ -225,16 +252,17 @@ class GraphSelectionManager { } break; - case "reduce-edges": + case 'reduce-edges': for (let edgeID of this.cache.selectedEdges) { const edge = this.cache.edgeRef.get(edgeID); - const connectingNodesAreSelected = this.cache.selectedNodes.includes(edge.source) - && this.cache.selectedNodes.includes(edge.target); + const connectingNodesAreSelected = + this.cache.selectedNodes.includes(edge.source) && + this.cache.selectedNodes.includes(edge.target); connectingNodesAreSelected ? edgesToShow.push(edge) : edgesToHide.push(edge); } break; - case "expand-neighbors": + case 'expand-neighbors': for (let nodeID of this.cache.selectedNodes) { for (let edgeID of this.cache.nodeIDToEdgeIDs.get(nodeID) || []) { const edge = this.cache.edgeRef.get(edgeID); @@ -246,7 +274,7 @@ class GraphSelectionManager { } break; - case "reduce-neighbors": + case 'reduce-neighbors': for (const nodeID of this.cache.selectedNodes.filter(isOuterNodeInSelection)) { nodesToHide.push(this.cache.nodeRef.get(nodeID)); @@ -264,11 +292,11 @@ class GraphSelectionManager { } updateSelectionCache() { - const {selectedNodes, selectedEdges, selectionMemory, selectedMemoryIndex} = cache; + const { selectedNodes, selectedEdges, selectionMemory, selectedMemoryIndex } = this.cache; // this should never be triggered; in case no snapshot is available, create an empty one if (selectionMemory.length === 0) { - selectionMemory.push({nodes: [], edges: []}); + selectionMemory.push({ nodes: [], edges: [] }); this.cache.selectedMemoryIndex = 0; } @@ -278,7 +306,6 @@ class GraphSelectionManager { const edgesChanged = !StaticUtilities.arraysAreEqual(currentSnapshot.edges, selectedEdges); if (nodesChanged || edgesChanged) { - // In case the user goes back in memory & then changes the selection, clear all memories after the current selection if (selectedMemoryIndex < selectionMemory.length - 1) { selectionMemory.splice(selectedMemoryIndex + 1); @@ -301,50 +328,87 @@ class GraphSelectionManager { } updateEnabledStateUndoRedoSelectionButtons() { - const {selectionMemory, selectedMemoryIndex} = this.cache; - const canUndo = (selectedMemoryIndex > 0); - const canRedo = (selectedMemoryIndex < selectionMemory.length - 1); + const { selectionMemory, selectedMemoryIndex } = this.cache; + const canUndo = selectedMemoryIndex > 0; + const canRedo = selectedMemoryIndex < selectionMemory.length - 1; - this.cache.ui.toggleDisabledElements(["undoSelectionBtn"], canUndo); - this.cache.ui.toggleDisabledElements(["redoSelectionBtn"], canRedo); + this.cache.ui.toggleDisabledElements(['undoSelectionBtn'], canUndo); + this.cache.ui.toggleDisabledElements(['redoSelectionBtn'], canRedo); } async updateSelectedNodesAndEdges() { - this.cache.selectedNodes = await this.cache.graph.getNodeData() - .filter((n) => n.states?.includes("selected") && this.cache.nodeIDsToBeShown.has(n.id)) + this.cache.selectedNodes = await this.cache.graph + .getNodeData() + .filter((n) => n.states?.includes('selected') && this.cache.nodeIDsToBeShown.has(n.id)) .map((n) => n.id); - this.cache.selectedEdges = await this.cache.graph.getEdgeData() - .filter((e) => e.states?.includes("selected") && this.cache.edgeIDsToBeShown.has(e.id)) + this.cache.selectedEdges = await this.cache.graph + .getEdgeData() + .filter((e) => e.states?.includes('selected') && this.cache.edgeIDsToBeShown.has(e.id)) .map((e) => e.id); const selectedNodesCount = this.cache.selectedNodes?.length || 0; const selectedEdgesCount = this.cache.selectedEdges?.length || 0; - document.getElementById("selectedNodes").textContent = `${selectedNodesCount}`; - document.getElementById("selectedEdges").textContent = `${selectedEdgesCount}`; + document.getElementById('selectedNodes').textContent = `${selectedNodesCount}`; + document.getElementById('selectedEdges').textContent = `${selectedEdgesCount}`; const atLeastOneNodeSelected = selectedNodesCount > 0; const atLeastOneEdgeSelected = selectedEdgesCount > 0; const atLeastOneNodeOrEdgeSelected = atLeastOneNodeSelected || atLeastOneEdgeSelected; + + // Swap the HUD between its empty state (instructions) and its active + // state (counts + actions). CSS keys off the `has-selection` class. + document + .getElementById('selectedElementsContainer') + ?.classList.toggle('has-selection', atLeastOneNodeOrEdgeSelected); + + // Tell the styling panel what it is acting on, so the node/edge cards + // are no longer silently greyed with no explanation. + const stylingStatus = document.getElementById('stylingSelectionStatus'); + if (stylingStatus) { + if (atLeastOneNodeOrEdgeSelected) { + const parts = []; + if (selectedNodesCount) + parts.push(`${selectedNodesCount} node${selectedNodesCount === 1 ? '' : 's'}`); + if (selectedEdgesCount) + parts.push(`${selectedEdgesCount} edge${selectedEdgesCount === 1 ? '' : 's'}`); + stylingStatus.textContent = `Styling ${parts.join(' · ')}`; + stylingStatus.classList.remove('empty'); + // Open the config card(s) matching the selection (additive). + this.cache.ui.syncStylingCardsToSelection(atLeastOneNodeSelected, atLeastOneEdgeSelected); + } else { + stylingStatus.textContent = + 'Nothing selected — select nodes or edges to style them. Bubble-group styling below works without a selection.'; + stylingStatus.classList.add('empty'); + } + } const moreThanOneNodeSelected = selectedNodesCount > 1; this.cache.ui.toggleStyleElementsThatRequireAtLeastOneSelectedNode(atLeastOneNodeSelected); this.cache.ui.toggleStyleElementsThatRequireAtLeastOneSelectedEdge(atLeastOneEdgeSelected); - this.cache.ui.toggleStyleElementsThatRequireAtLeastOneSelectedNodeOrEdge(atLeastOneNodeOrEdgeSelected); + this.cache.ui.toggleStyleElementsThatRequireAtLeastOneSelectedNodeOrEdge( + atLeastOneNodeOrEdgeSelected + ); this.cache.ui.toggleStyleElementsThatRequireMoreThanOneSelectedNode(moreThanOneNodeSelected); this.updateSelectionCache(); this.updateEnabledStateUndoRedoSelectionButtons(); + // Single authoritative point where cache.selectedNodes is recomputed, so + // resync the "Add to group" quadrant button here. (updateSelectedState + // fires before this refresh and would read a stale selection.) + this.cache.bs.updateManualGroupButtonState(); + if (typeof this.cache.dataTable !== 'undefined' && this.cache.dataTable.fileData) { - if (this.cache.dataTable.currentTab === 'selectedNodes' - || this.cache.dataTable.currentTab === 'selectedEdges' - || this.cache.dataTable.currentTab === 'selectedElements') { + if ( + this.cache.dataTable.currentTab === 'selectedNodes' || + this.cache.dataTable.currentTab === 'selectedEdges' || + this.cache.dataTable.currentTab === 'selectedElements' + ) { this.cache.dataTable.refreshCurrentTab(); } } } - } -export {GraphSelectionManager} \ No newline at end of file +export { GraphSelectionManager }; diff --git a/src/graph/shape_textures.js b/src/graph/shape_textures.js new file mode 100644 index 0000000..18b7e5c --- /dev/null +++ b/src/graph/shape_textures.js @@ -0,0 +1,169 @@ +/** + * Node-safe SVG texture generation for non-circular node shapes + * (MIGRATION.md Phase 2, risk #1). + * + * Sigma renders circles natively; every other G6 shape (and any shape that + * needs a border or a state halo) is drawn from a crisp vector texture via + * @sigma/node-image. This module only does pure string work — no DOM, no + * sigma import — so vitest can cover it and graph_model.js may depend on it. + */ +import { DEFAULTS } from "../config.js"; + +// G6 shape vocabulary (config STYLES.NODE_FORM + io.js Shape column). +const SHAPE_NAMES = ["circle", "diamond", "hexagon", "rect", "triangle", "star"]; + +// Shapes that ALWAYS need a texture (no native sigma program). +const TEXTURE_ONLY_SHAPES = new Set(["diamond", "hexagon", "triangle", "star"]); + +// SVG canvas is a 100x100 viewBox; all geometry derives from its center. +const VIEWBOX = 100; +const CENTER = VIEWBOX / 2; +// Explicit raster size on the SVG root: data URIs take @sigma/node-image's +// raster path (it sniffs file extensions, not MIME types), and an SVG +// without width/height has no usable intrinsic size there — the atlas entry +// ends up 0×0 and the node renders invisible. +const RASTER_SIZE = 512; + +// Halo ring stroke is centered on the shape outline, so it extends half its +// width beyond the node bounds. Reducers grow `size` by this many px so the +// shape keeps its on-screen size and the halo bleeds outward (G6 parity). +const HALO_EXTRA_PX = DEFAULTS.STATE.NODE_HALO_WIDTH / 2; + +// Conservative paint-value allowlist: hex/rgb()/hsl()/named colors pass; +// anything that could break out of an SVG attribute (quotes, angle brackets, +// ampersands) or collide in the cache key (pipes) is rejected. fill/stroke +// originate from user-supplied Excel/JSON style data — never trust them. +const SAFE_PAINT_RE = /^[#a-zA-Z0-9(),.%\s-]+$/; +const FALLBACK_FILL = "#999999"; + +/** @returns {string|null} the color when safe to embed in SVG, else fallback */ +function safePaint(color, fallback) { + return typeof color === "string" && SAFE_PAINT_RE.test(color) ? color : fallback; +} + +// Full clear when the cache fills up: style churn (interactive recoloring) +// would otherwise grow it monotonically. Regeneration is cheap string work, +// so a flush beats LRU bookkeeping. +const MAX_TEXTURE_CACHE = 4096; + +const textureCache = new Map(); + +/** @returns {boolean} true when the G6 type has no native sigma program */ +function isTextureOnlyShape(type) { + return TEXTURE_ONLY_SHAPES.has(type); +} + +/** Points of a regular polygon (flat string for SVG `points`). */ +function polygonPoints(sides, radius, rotationRad = -Math.PI / 2) { + const pts = []; + for (let i = 0; i < sides; i++) { + const angle = rotationRad + (2 * Math.PI * i) / sides; + pts.push( + `${(CENTER + radius * Math.cos(angle)).toFixed(2)},${(CENTER + radius * Math.sin(angle)).toFixed(2)}`, + ); + } + return pts.join(" "); +} + +/** 5-point star points (outer radius r, inner radius 0.45 r). */ +function starPoints(radius) { + const pts = []; + for (let i = 0; i < 10; i++) { + const r = i % 2 === 0 ? radius : radius * 0.45; + const angle = -Math.PI / 2 + (Math.PI * i) / 5; + pts.push( + `${(CENTER + r * Math.cos(angle)).toFixed(2)},${(CENTER + r * Math.sin(angle)).toFixed(2)}`, + ); + } + return pts.join(" "); +} + +/** + * SVG element string for a shape outline. `radius` is the circumradius (or + * half-size for rect) in viewBox units; `paint` is an attribute string. + */ +function shapeElement(shape, radius, paint) { + switch (shape) { + case "rect": { + const side = radius * Math.SQRT1_2 * 2; // inscribe square in circumcircle + const off = CENTER - side / 2; + return ``; + } + case "diamond": + return ``; + case "triangle": + return ``; + case "hexagon": + return ``; + case "star": + return ``; + default: // circle + return ``; + } +} + +/** + * Build (and cache) an SVG data-URI for a node shape. + * + * @param {object} opts + * @param {string} opts.shape G6 type (circle|diamond|hexagon|rect|triangle|star) + * @param {string} opts.fill fill color (hex, may carry alpha) + * @param {string|null} [opts.stroke] border color (null/undefined = none) + * @param {number} [opts.lineWidth] border width in node px + * @param {number} [opts.size] node radius in px (sigma size attribute) + * @param {string|null} [opts.state] null | "selected" | "highlight" | "dim" + * @returns {string} data:image/svg+xml URI + */ +function shapeTextureURI({ shape, fill, stroke = null, lineWidth = 0, size = 10, state = null }) { + const safeShape = SHAPE_NAMES.includes(shape) ? shape : "circle"; + const safeSize = Number.isFinite(size) && size > 0 ? size : 10; + const safeFill = safePaint(fill, FALLBACK_FILL); + const safeStroke = stroke == null ? null : safePaint(stroke, null); + const key = `${safeShape}|${safeFill}|${safeStroke}|${lineWidth}|${safeSize}|${state}`; + const cached = textureCache.get(key); + if (cached) return cached; + + const { ACCENT_COLOR, DIM_COLOR, NODE_HALO_WIDTH, HALO_OPACITY } = DEFAULTS.STATE; + const hasHalo = state === "selected" || state === "highlight"; + // Old G6 state spec: highlight = accent fill + halo, no border; + // selected = own fill + accent halo; dim = dim fill, border kept. + const effFill = state === "highlight" ? ACCENT_COLOR : state === "dim" ? DIM_COLOR : safeFill; + const effStroke = state === "highlight" ? null : safeStroke; + const effLineWidth = effStroke ? lineWidth : 0; + + // px → viewBox units. With a halo the drawable px radius grows by + // HALO_EXTRA_PX, and the reducer grows the node size to match. + const unitsPerPx = VIEWBOX / (2 * (safeSize + (hasHalo ? HALO_EXTRA_PX : 0))); + const strokeUnits = effLineWidth * unitsPerPx; + const haloUnits = NODE_HALO_WIDTH * unitsPerPx; + // Keep stroke and halo inside the viewBox: the shape circumradius shrinks + // by half of whatever is painted on/over its outline. + const shapeRadius = + CENTER - (hasHalo ? haloUnits / 2 : 0) - strokeUnits / 2 - 0.5; + + const parts = []; + if (hasHalo) { + parts.push( + shapeElement( + safeShape, + shapeRadius, + `fill="none" stroke="${ACCENT_COLOR}" stroke-width="${haloUnits.toFixed(2)}" stroke-opacity="${HALO_OPACITY}" stroke-linejoin="round"`, + ), + ); + } + const strokeAttrs = effStroke + ? ` stroke="${effStroke}" stroke-width="${strokeUnits.toFixed(2)}" stroke-linejoin="round"` + : ""; + parts.push(shapeElement(safeShape, shapeRadius, `fill="${effFill}"${strokeAttrs}`)); + + const svg = + `` + + parts.join("") + + ""; + const uri = `data:image/svg+xml,${encodeURIComponent(svg)}`; + if (textureCache.size >= MAX_TEXTURE_CACHE) textureCache.clear(); + textureCache.set(key, uri); + return uri; +} + +export { shapeTextureURI, isTextureOnlyShape, HALO_EXTRA_PX, SHAPE_NAMES }; diff --git a/src/graph/sigma_adapter.js b/src/graph/sigma_adapter.js new file mode 100644 index 0000000..958b2d8 --- /dev/null +++ b/src/graph/sigma_adapter.js @@ -0,0 +1,1036 @@ +/** + * Browser-only Sigma.js adapter (MIGRATION.md Phase 1). + * + * The ONLY module in src/ that imports the sigma bundle (it references WebGL + * globals at module scope and crashes under node). Wraps the Sigma instance, + * the graphology graph, the element-states Map and a pending-layout slot + * behind the G6-shaped facade the rest of the app still calls. Facade methods + * are transitional and get slimmed/deleted in Phases 2-6. + */ +import { + Sigma, + exportImage, + EdgeRectangleProgram, + createEdgeCompoundProgram, + drawDiscNodeHover, + NodeSquareProgram, + createNodeBorderProgram, + nodeImage, + edgeCurve, + animateNodes, + createNodePiechartProgram, +} from "../lib/sigma.bundle.mjs"; +import { DEFAULTS } from "../config.js"; +import { + EdgeHaloProgram, + createCurveHaloProgram, + createEdgeMarkerHeadProgram, +} from "./edge_programs.js"; +import { + clampExportScale, + MAX_CANVAS_SIDE, + WEBGL_SAFE_SIDE_FRACTION, +} from "../utilities/export_scale.js"; +import { webglMaxCanvasSide } from "./webgl_support.js"; +import { buildGraphSvg } from "./export_svg.js"; +import { EdgeFlowProgram, createCurveFlowProgram } from "./edge_flow_programs.js"; +import { FlowAnimator } from "./flow_animator.js"; +import { + nodeAttributesFromStyle, + edgeAttributesFromStyle, + flipY, + buildLayoutTransitionTargets, +} from "./graph_model.js"; +import { executeLayout } from "./layout_algorithms.js"; +import { drawNodeLabel, drawEdgeLabel, BAKED_DEFAULT_LABEL_COLOR } from "./label_renderers.js"; +import { InteractionManager } from "./interactions.js"; +import { BubbleSetLayer } from "./bubble_layer.js"; +import { HeatmapLayer } from "./heatmap_layer.js"; +import { Minimap } from "./minimap.js"; + +// Rasterization resolution for the SVG shape textures. 512 px keeps shapes +// crisp at the ~4x zoom the UI allows (risk #1 in MIGRATION.md). +const SHAPE_TEXTURE_RESOLUTION = 512; +// @sigma/node-image defaults to 500 ms before regenerating the texture atlas +// after a miss; style changes left nodes invisible (transparent base color) +// for that long. 50 ms keeps batching without visible flicker. +const ATLAS_REGEN_DEBOUNCE_MS = 50; +// Trailing-edge debounce for container ResizeObserver → this.resize(); +// rides out the 0.3 s CSS panel transitions without a resize per frame. +const RESIZE_DEBOUNCE_MS = 50; +// Node-position tween when switching workspaces (sigma/utils animateNodes): +// long enough to read the motion, short enough not to gate interaction. +const LAYOUT_TRANSITION_MS = 450; +// Above this node count the per-frame attribute writes + refresh stop being +// free; snap instead of animating so big graphs never pay the tween cost. +const LAYOUT_TRANSITION_MAX_NODES = 2000; + +/** @returns {boolean} whether the user asked the OS to minimize motion */ +function prefersReducedMotion() { + return Boolean(window.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches); +} + +/** + * Sigma's hover layer (drawDiscNodeHover and per-program drawHover) paints a + * white disc + label pill on the hovers canvas, which sits ABOVE the labels + * canvas — on light backgrounds the pill invisibly blanks every label + * underneath. Acceptable on a deliberate hover; NOT while dragging, where + * the dragged node is permanently hovered and would wipe labels along its + * whole path (the dragged node's own label stays visible via the forceLabel + * pin in InteractionManager, on the labels canvas). So: suppress ALL hover + * drawing while a drag is in flight, keep the native pill otherwise. + * + * @param {(context, data, settings) => void} drawer + * @param {() => string|null} getDraggedNode + */ +function guardHoverDrawer(drawer, getDraggedNode) { + // Defensive: if a future sigma bundle moves the wrapped drawer off the + // instance/export we read it from, fail to "no hover" instead of throwing + // inside sigma's render loop (which would swallow the error silently). + if (typeof drawer !== "function") return () => {}; + return (context, data, settings) => { + if (getDraggedNode()) return; + // Sigma's drawDiscNodeHover hardcodes a white pill behind the label, so + // pin the FALLBACK to dark regardless of the theme-driven labelColor + // setting (dark mode flips it to a light color, unreadable on the pill). + // The attribute form keeps explicit per-element labelColor choices + // (sigma resolves data[attribute] || color). + drawer(context, data, { + ...settings, + labelColor: { attribute: "labelColor", color: "#000" }, + }); + }; +} + +/** + * Node/edge program registry (G6 type vocabulary → sigma programs). + * Nodes: circle native, square via @sigma/node-square, bordered circles via + * @sigma/node-border ("borderCircle"); every other shape — and any bordered + * non-circle or haloed node — uses the SVG texture program ("shape"). + * Edges: two parametric programs per curvature (graph_model.sigmaEdgeType + * routes): "line"/"curve" are the plain fast paths for unstyled edges; + * "styledLine"/"styledCurve" compose halo-under → body → flow overlay → + * marker heads (compound programs draw in array order: the flow pattern rides + * on the body, marker heads stay crisp on top) and are fully parameterized by + * per-edge attrs (startMarker/endMarker enum + sizes, haloWidth/haloColor, + * flowMode/flowSpeed/flowColor) — no registry growth per marker shape or + * halo/flow toggle. Off states collapse to degenerate geometry in the custom + * programs (see edge_programs.js / edge_flow_programs.js). styledCurve's flow + * sub-program forks the @sigma/edge-curve shaders via string patches + * (edge_flow_glsl.js); on anchor drift after a sigma upgrade it is dropped + * with a warning and curves render without animation. + * + * @param {() => string|null} getDraggedNode hover-guard input (see + * guardHoverDrawer); NodeSquareProgram carries its own instance drawHover + * which bypasses defaultDrawNodeHover, so it gets wrapped here. + */ +function buildProgramRegistry(getDraggedNode) { + const shapeProgram = nodeImage.createNodeImageProgram({ + size: { mode: "force", value: SHAPE_TEXTURE_RESOLUTION }, + objectFit: "contain", + drawingMode: "background", + keepWithinCircle: false, + padding: 0, + debounceTimeout: ATLAS_REGEN_DEBOUNCE_MS, + }); + // ANGLE/radeonsi intermittently fails generateMipmap on NPOT atlas + // re-uploads (GL_INVALID_OPERATION), leaving textures mipmap-incomplete — + // sampled as opaque black (the hover-after-restyle black boxes). The + // program never sets TEXTURE_MIN_FILTER, so the NEAREST_MIPMAP_LINEAR + // default requires a complete mip chain; force LINEAR, which needs none. + // 512 px rasters lose nothing visible to non-mipmapped minification. + const originalBindTextures = shapeProgram.prototype.bindTextures; + shapeProgram.prototype.bindTextures = function () { + originalBindTextures.call(this); + const gl = this.normalProgram?.gl ?? this.gl; + if (!gl) return; + for (let i = 0; i < (this.textures?.length ?? 0); i++) { + gl.activeTexture(gl.TEXTURE0 + i); + gl.bindTexture(gl.TEXTURE_2D, this.textures[i]); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + } + }; + class GuardedSquareProgram extends NodeSquareProgram { + constructor(...args) { + super(...args); + this.drawHover = guardHoverDrawer(this.drawHover, getDraggedNode); + } + } + // Bordered circles: outer ring reads borderColor/borderRatio (graph_model + // emits borderRatio = lineWidth / radius so the border scales with zoom + // like the baked textures did), the rest is filled with the node color. + // No hover guard needed: the program leaves its instance drawHover + // undefined, so sigma falls back to the guarded defaultDrawNodeHover. + const borderCircleProgram = createNodeBorderProgram({ + borders: [ + { + size: { attribute: "borderRatio", defaultValue: 0, mode: "relative" }, + color: { attribute: "borderColor" }, + }, + { size: { fill: true }, color: { attribute: "color" } }, + ], + }); + // Pie-chart nodes: one program with a fixed slice count, each slice reading + // its angle/color from the per-node pieValue{k}/pieColor{k} attrs emitted by + // graph_model (pieAttributesFromSlices). Unused slots carry value 0 + a + // transparent color, so a node with fewer categories than MAX_SLICES draws + // only its real wedges. Reuses the custom node-label drawer and the + // drag-guarded hover so pie nodes behave like every other node type. + const pie = DEFAULTS.NODE.PIE; + const pieProgram = createNodePiechartProgram({ + defaultColor: pie.DEFAULT_COLOR, + offset: { value: 0 }, + slices: Array.from({ length: pie.MAX_SLICES }, (_, k) => ({ + color: { attribute: `pieColor${k}`, defaultValue: "#00000000" }, + value: { attribute: `pieValue${k}` }, + })), + drawLabel: drawNodeLabel, + drawHover: guardHoverDrawer(drawDiscNodeHover, getDraggedNode), + }); + // One curve class serves both the plain "curve" type and the body/halo + // sub-programs of "styledCurve" (each gets its own instance + buffers). + // arrowHead stays null: end markers are drawn by the parametric marker-head + // sub-programs, oriented along the same bezier tangent. + const curveProgram = edgeCurve.createEdgeCurveProgram({ + arrowHead: null, + drawLabel: drawCurvedEdgeLabelWithSize, + }); + // Curve flow overlay: forked @sigma/edge-curve shaders (edge_flow_glsl.js + // string patches). The patchers throw when a sigma upgrade moves their GLSL + // anchors — degrade to curves WITHOUT animation rather than break curve + // rendering; straight-edge flow is unaffected. + let curveFlowProgram = null; + try { + curveFlowProgram = createCurveFlowProgram(curveProgram); + } catch (error) { + console.warn("buildProgramRegistry: curve flow overlay disabled:", error); + } + return { + nodeProgramClasses: { + square: GuardedSquareProgram, + shape: shapeProgram, + borderCircle: borderCircleProgram, + pie: pieProgram, + }, + edgeProgramClasses: { + line: EdgeRectangleProgram, + styledLine: createEdgeCompoundProgram([ + EdgeHaloProgram, + EdgeRectangleProgram, + EdgeFlowProgram, + createEdgeMarkerHeadProgram({ extremity: "source" }), + createEdgeMarkerHeadProgram({ extremity: "target" }), + ]), + curve: curveProgram, + styledCurve: createEdgeCompoundProgram( + [ + createCurveHaloProgram(curveProgram), + curveProgram, + // Flow overlay rides on the body, marker heads stay crisp on top. + ...(curveFlowProgram ? [curveFlowProgram] : []), + createEdgeMarkerHeadProgram({ extremity: "source", curved: true }), + createEdgeMarkerHeadProgram({ extremity: "target", curved: true }), + ], + drawCurvedEdgeLabelWithSize, + ), + }, + }; +} + +// Curved-edge labels reuse @sigma/edge-curve's drawer, proxying the settings +// so per-edge labelSize/labelColor (graph_model attrs) are honoured. +const drawCurvedEdgeLabelBase = edgeCurve.createDrawCurvedEdgeLabel( + edgeCurve.DEFAULT_EDGE_CURVE_PROGRAM_OPTIONS, +); +function drawCurvedEdgeLabelWithSize(context, edgeData, sourceData, targetData, settings) { + // The baked #000000 default counts as "no explicit color" so the + // theme-driven settings fallback applies (see label_renderers.js). + const explicitColor = + edgeData.labelColor && edgeData.labelColor !== BAKED_DEFAULT_LABEL_COLOR + ? edgeData.labelColor + : null; + const effective = + edgeData.labelSize != null || explicitColor != null + ? { + ...settings, + edgeLabelSize: edgeData.labelSize ?? settings.edgeLabelSize, + edgeLabelColor: explicitColor + ? { color: explicitColor } + : settings.edgeLabelColor, + } + : settings; + drawCurvedEdgeLabelBase(context, edgeData, sourceData, targetData, effective); +} + +const FIT_PADDING_PX = 80; +// Clamp fit zoom so a tiny selection (e.g. a single node) doesn't punch the +// viewport to 100x — same UX guard as the old G6 fitViewToNodes. +const MAX_FIT_ZOOM = 4; + +/** + * Temporarily override `window.devicePixelRatio`, returning a restore fn. + * @sigma/export-image reads it once to size its export canvas, so raising it + * for the duration of a single export yields a higher-DPI render of the live + * view with proportions intact. Defining an own property shadows the (often + * accessor-based, prototype-level) browser ratio; restore reinstates the + * original descriptor, or deletes the shadow when there wasn't one. + * + * @param {number} value + * @returns {() => void} restore + */ +function overrideDevicePixelRatio(value) { + const original = Object.getOwnPropertyDescriptor(window, "devicePixelRatio"); + Object.defineProperty(window, "devicePixelRatio", { configurable: true, value }); + return () => { + if (original) Object.defineProperty(window, "devicePixelRatio", original); + else delete window.devicePixelRatio; + }; +} + +// Downsample target for the blank-render probe: big enough that a couple of +// nodes anywhere in a huge frame still land a non-zero-alpha sample, small +// enough that getImageData stays negligible next to the export itself. +const BLANK_PROBE_SIDE = 32; + +/** + * Whether an exported sigma frame came back fully transparent. WebGL + * framebuffer allocation can fail without throwing (driver memory pressure, + * over-limit canvases), in which case export-image hands back a valid but + * empty PNG — detectable only by looking at the pixels. + * + * @param {ImageBitmap} bitmap + * @returns {boolean} true when every sampled pixel has alpha 0 + */ +function bitmapLooksBlank(bitmap) { + const probe = document.createElement("canvas"); + probe.width = BLANK_PROBE_SIDE; + probe.height = BLANK_PROBE_SIDE; + const ctx = probe.getContext("2d", { willReadFrequently: true }); + ctx.drawImage(bitmap, 0, 0, BLANK_PROBE_SIDE, BLANK_PROBE_SIDE); + const { data } = ctx.getImageData(0, 0, BLANK_PROBE_SIDE, BLANK_PROBE_SIDE); + for (let i = 3; i < data.length; i += 4) { + if (data[i] !== 0) return false; + } + return true; +} + +class SigmaAdapter { + /** + * @param {object} cache app cache; cache.graphData must hold the graphology graph + * @param {string|HTMLElement} container + * @param {object} opts {nodeReducer, edgeReducer, elementStates, hoverIds, settings} + */ + constructor( + cache, + container, + { nodeReducer, edgeReducer, elementStates, hoverIds = new Set(), settings = {} }, + ) { + this.cache = cache; + this.graph = cache.graphData; + this.elementStates = elementStates; + this.pendingLayout = null; + // When set, the next render() leaves node positions untouched: a workspace + // switch is mid-flight and runLayoutTransition() owns the positions (it + // tweens them from the outgoing view to the incoming one once the loading + // overlay clears). See GraphLayoutManager.changeLayout. + this.pendingLayoutTransition = false; + this.layoutTransitionCancel = null; + this.killed = false; + + const containerEl = + typeof container === "string" ? document.getElementById(container) : container; + + // Lazy read: this.interactions is assigned AFTER new Sigma(...); the + // closure only runs per hover render, by which time it exists. + const getDraggedNode = () => this.interactions?.draggedNode ?? null; + + this.sigma = new Sigma(this.graph, containerEl, { + allowInvalidContainer: true, + enableEdgeEvents: true, + zIndex: true, + nodeReducer, + edgeReducer, + ...buildProgramRegistry(getDraggedNode), + // Custom drawers honour the per-element label attrs from graph_model + // (size, color, background, placement, offsets, auto-rotate). + defaultDrawNodeLabel: drawNodeLabel, + defaultDrawEdgeLabel: drawEdgeLabel, + defaultDrawNodeHover: guardHoverDrawer(drawDiscNodeHover, getDraggedNode), + renderEdgeLabels: true, + // Label-grid thinning stays on, tuned denser than sigma's default + // (1 label per 100px cell): 50px cells show ~4x the labels and shrink + // the zone where two nearby nodes compete for one label slot. Drags + // can't pop neighbours' labels regardless — InteractionManager pins + // all on-screen labels for the duration of a drag. CFG.HIDE_LABELS + // remains the guard for huge graphs (MAX_NODES_BEFORE_HIDING_LABELS). + labelGridCellSize: 50, + ...settings, + }); + // Sigma only auto-resizes on window resize. Sidebar/bottom-bar toggles + // animate the container via CSS (0.3 s), which used to blank the graph + // until the next zoom/pan; observe the container directly instead. + this.resizeDebounce = null; + this.resizeObserver = new ResizeObserver(() => { + clearTimeout(this.resizeDebounce); + this.resizeDebounce = setTimeout(() => this.resize(), RESIZE_DEBOUNCE_MS); + }); + this.resizeObserver.observe(containerEl); + this.interactions = new InteractionManager(this, cache, hoverIds, containerEl); + // Created BEFORE BubbleSetLayer on purpose: both register with + // beforeLayer: "edges", and the earliest-created canvas sits deepest + // (see the layer-ordering note in heatmap_layer.js), keeping the + // atmospheric field under the bubble bodies. + this.heatmapLayer = new HeatmapLayer(this); + this.bubbleLayer = new BubbleSetLayer(this, cache); + this.minimap = new Minimap(this, containerEl); + this.flowAnimator = new FlowAnimator(this); + this.#syncLabelVisibility(); + } + + /** + * Keep CFG.HIDE_LABELS live (io.preProcessData flips it per + * MAX_NODES_BEFORE_HIDING_LABELS on every load). Sigma's label density + * grid stays the default thinning mechanism; HIDE_LABELS is the explicit + * override on top — but elements the user explicitly labelled (style + * pipeline emits a label attr despite HIDE_LABELS) must stay visible, + * matching the old G6 semantics. + * + * NOTE: this owns renderLabels/renderEdgeLabels — a caller-supplied value + * in constructor `settings` is overwritten here by design (CFG.HIDE_LABELS + * is the single source of truth for label visibility). + */ + #syncLabelVisibility() { + let nodeLabels = true; + let edgeLabels = true; + if (this.cache.CFG?.HIDE_LABELS) { + nodeLabels = this.graph.someNode((_, attrs) => attrs.label != null); + edgeLabels = this.graph.someEdge((_, attrs) => attrs.label != null); + } + this.sigma.setSetting("renderLabels", nodeLabels); + this.sigma.setSetting("renderEdgeLabels", edgeLabels); + } + + // ---------------------------------------------------------------- lifecycle + + /** + * G6 render = layout + draw. Runs the pending layout (if any), then the + * persisted-position choreography that used to live in core.js's G6 + * `afterlayout` handler, then a full (re-indexing) refresh. + */ + async render() { + if (this.killed) return false; + if (this.pendingLayout) await this.layout(); + await this.#applyPersistedPositions(); + this.#syncLabelVisibility(); + + this.sigma.refresh(); + + if (this.cache.EVENT_LOCKS.ONCE_AFTER_RENDER_COMPLETED) { + await this.#postRefresh(); + } else { + // First render: run the one-time post-render routine (which re-renders + // once with ONCE_AFTER_RENDER_COMPLETED set, taking the branch above). + await this.cache.gcm.initialAfterRenderEvent(); + } + return true; + } + + /** G6 draw = pure visual update; graph structure is unchanged. */ + async draw() { + if (this.killed) return false; + this.sigma.refresh({ skipIndexation: true }); + await this.#postRefresh(); + return true; + } + + /** + * Kills the sigma instance. The `killed` guard keeps in-flight async + * choreography (e.g. a draw awaited across a reload) from refreshing a + * dead renderer — sigma throws on refresh-after-kill. + */ + destroy() { + if (this.killed) return; + this.killed = true; + this.layoutTransitionCancel?.(); + this.layoutTransitionCancel = null; + clearTimeout(this.resizeDebounce); + this.resizeObserver.disconnect(); + this.flowAnimator.destroy(); + this.heatmapLayer.destroy(); + this.bubbleLayer.destroy(); + this.minimap.destroy(); + this.interactions.destroy(); + this.sigma.kill(); + } + + /** + * Container-resize entry point (ResizeObserver debounce + panel-toggle + * callers). NOT sigma.resize(): that only resizes the canvases — clearing + * their WebGL buffers — and never schedules a render, leaving the graph + * blank until the next camera move (scripts/resize_redraw_check.js). + * render() starts by resizing, so scheduling a render covers both. + */ + resize() { + if (this.killed) return; + this.sigma.scheduleRender(); + } + + /** + * Post-refresh choreography formerly driven by G6's AFTER_DRAW/AFTER_RENDER + * events: sync selection caches/UI, redraw bubble sets, drop the overlay. + */ + async #postRefresh() { + if (this.cache.EVENT_LOCKS.AFTER_DRAW_RUNNING) return; + this.cache.EVENT_LOCKS.AFTER_DRAW_RUNNING = true; + try { + await this.cache.sm.updateSelectedNodesAndEdges(); + await this.cache.bs.redrawBubbleSets(); + } finally { + this.cache.EVENT_LOCKS.AFTER_DRAW_RUNNING = false; + // Inside finally: a throw above must never strand the loading overlay. + await this.cache.ui.hideLoading(); + } + } + + /** + * Persisted positions override layout output; a fresh initial layout gets + * persisted once and its `layoutType` marker removed (see commit b6f8606: + * authored payloads with empty positions are force-laid-out). + */ + async #applyPersistedPositions() { + // A workspace switch is animating its own positions — don't snap them out + // from under the tween (runLayoutTransition consumes the flag). + if (this.pendingLayoutTransition) return; + const layout = this.cache.data.layouts?.[this.cache.data.selectedLayout]; + if (!layout) return; + + if (layout.positions.size > 0) { + for (const [id, pos] of layout.positions) { + const x = pos?.style?.x; + const y = pos?.style?.y; + if (!this.graph.hasNode(id) || !Number.isFinite(x) || !Number.isFinite(y)) continue; + // Persisted positions are app-model (y-down); graphology is y-up. + this.graph.mergeNodeAttributes(id, { x, y: flipY(y) }); + const ref = this.cache.nodeRef.get(id); + if (ref) { + ref.style.x = x; + ref.style.y = y; + } + } + } else if (layout.layoutType) { + await this.cache.lm.persistNodePositions(); + delete layout.layoutType; + this.cache.ui.debug("Initial layout positions persisted"); + } + } + + // --------------------------------------------------------------------- data + + /** G6-shaped bulk update ({nodes, edges} arrays of {id, type?, style?}). */ + async updateData({ nodes = [], edges = [] } = {}) { + await this.updateNodeData(nodes); + await this.updateEdgeData(edges); + } + + /** @param {Array<{id: string, type?: string, style?: object}>} payload */ + async updateNodeData(payload) { + for (const item of payload ?? []) { + if (!item || !this.graph.hasNode(item.id)) continue; + const ref = this.cache.nodeRef.get(item.id); + if (ref) { + if (item.type !== undefined) ref.type = item.type; + if (item.style) Object.assign(ref.style, item.style); + } + // Map from the merged ref where possible: shape/texture attrs depend on + // the full style (fill+stroke+lineWidth+size), not just the delta. + const attrs = nodeAttributesFromStyle(ref?.style ?? item.style ?? {}, ref?.type ?? item.type); + if (Object.keys(attrs).length > 0) { + this.graph.mergeNodeAttributes(item.id, attrs); + } + } + } + + /** @param {Array<{id: string, type?: string, style?: object}>} payload */ + async updateEdgeData(payload) { + for (const item of payload ?? []) { + if (!item || !this.graph.hasEdge(item.id)) continue; + const ref = this.cache.edgeRef.get(item.id); + if (ref) { + if (item.type !== undefined) ref.type = item.type; + if (item.style) Object.assign(ref.style, item.style); + } + // Merged ref: the program key depends on type + both arrow flags. + const attrs = edgeAttributesFromStyle(ref?.style ?? item.style ?? {}, ref?.type ?? item.type); + if (Object.keys(attrs).length > 0) { + this.graph.mergeEdgeAttributes(item.id, attrs); + } + } + } + + /** + * G6-shaped live node objects backed by cache.nodeRef. Callers (selection.js, + * layout.js) mutate .style.x/.style.y on the returned objects and push them + * back via updateNodeData; x/y/visibility are synced from graphology here. + * + * @param {string[]} [ids] + */ + getNodeData(ids) { + const refs = ids + ? [...ids].map((id) => this.cache.nodeRef.get(id)).filter(Boolean) + : [...this.cache.nodeRef.values()]; + const views = []; + for (const ref of refs) { + if (!this.graph.hasNode(ref.id)) continue; + const attrs = this.graph.getNodeAttributes(ref.id); + ref.style.x = attrs.x; + // Graphology is y-up; the app model (and everything persisted from it) + // stays y-down — flip on the way out, mirror of the mapper's flip in. + ref.style.y = flipY(attrs.y); + ref.style.visibility = attrs.hidden ? "hidden" : "visible"; + ref.states = [...(this.elementStates.get(ref.id) ?? [])]; + views.push(ref); + } + return views; + } + + /** @param {string[]} [ids] */ + getEdgeData(ids) { + const refs = ids + ? [...ids].map((id) => this.cache.edgeRef.get(id)).filter(Boolean) + : [...this.cache.edgeRef.values()]; + const views = []; + for (const ref of refs) { + if (!this.graph.hasEdge(ref.id)) continue; + const attrs = this.graph.getEdgeAttributes(ref.id); + ref.style.visibility = attrs.hidden ? "hidden" : "visible"; + ref.states = [...(this.elementStates.get(ref.id) ?? [])]; + views.push(ref); + } + return views; + } + + /** + * Synchronous (returns a plain object); callers `await` it for G6 parity, + * which is a no-op. Keep it sync — getNodeData/getEdgeData results are + * chained with array methods directly under `await` across the app. + */ + getData() { + return { nodes: this.getNodeData(), edges: this.getEdgeData() }; + } + + // ------------------------------------------------------------------- states + + /** @returns {string[]} copy of the element's states (callers mutate freely) */ + getElementState(id) { + return [...(this.elementStates.get(id) ?? [])]; + } + + /** + * G6 semantics: either (id, states[]) or a map of id → states[]. + * Triggers the draw choreography (selection UI sync happens there). + */ + async setElementState(mapOrId, states) { + if (typeof mapOrId === "string") { + this.#setStates(mapOrId, states ?? []); + } else { + for (const [id, elementStates] of Object.entries(mapOrId ?? {})) { + this.#setStates(id, elementStates ?? []); + } + } + await this.draw(); + } + + #setStates(id, states) { + if (states.length === 0) { + this.elementStates.delete(id); + } else { + this.elementStates.set(id, [...states]); + } + } + + // --------------------------------------------------------------- visibility + + // Both are `async` only for the G6 call-site contract; the body is fully + // synchronous (graphology writes + one skipIndexation refresh). + async showElement(ids) { + this.#setHidden(ids, false); + } + + async hideElement(ids) { + this.#setHidden(ids, true); + } + + #setHidden(ids, hidden) { + if (this.killed) return; + const visibility = hidden ? "hidden" : "visible"; + for (const id of Array.isArray(ids) ? ids : [ids]) { + if (this.graph.hasNode(id)) { + this.graph.setNodeAttribute(id, "hidden", hidden); + const ref = this.cache.nodeRef.get(id); + if (ref) ref.style.visibility = visibility; + } else if (this.graph.hasEdge(id)) { + this.graph.setEdgeAttribute(id, "hidden", hidden); + const ref = this.cache.edgeRef.get(id); + if (ref) ref.style.visibility = visibility; + } + } + this.sigma.refresh({ skipIndexation: true }); + } + + // ----------------------------------------------------------------- viewport + + async fitView() { + // Drop the bbox pinned by node dragging (see InteractionManager) so the + // normalization re-covers all current positions, then the default camera + // frames everything. + this.sigma.setCustomBBox(null); + this.sigma.getCamera().setState({ x: 0.5, y: 0.5, ratio: 1, angle: 0 }); + } + + /** + * Frame the given graph-space bounding box with padding. Replaces the old + * G6 zoom-at-non-1 workaround (antvis/G6#6373) with a direct camera fit. + */ + fitViewToBounds({ minX, minY, maxX, maxY }) { + const camera = this.sigma.getCamera(); + const { width, height } = this.sigma.getDimensions(); + const p1 = this.sigma.graphToViewport({ x: minX, y: minY }); + const p2 = this.sigma.graphToViewport({ x: maxX, y: maxY }); + const spanX = Math.abs(p2.x - p1.x) || 1; + const spanY = Math.abs(p2.y - p1.y) || 1; + const scale = Math.max( + spanX / Math.max(width - 2 * FIT_PADDING_PX, 1), + spanY / Math.max(height - 2 * FIT_PADDING_PX, 1), + ); + const ratio = Math.max(camera.getState().ratio * scale, 1 / MAX_FIT_ZOOM); + const center = this.sigma.viewportToFramedGraph( + this.sigma.graphToViewport({ x: (minX + maxX) / 2, y: (minY + maxY) / 2 }), + ); + camera.setState({ x: center.x, y: center.y, ratio }); + } + + /** G6 zoom z ↔ sigma camera ratio 1/z. */ + async zoomTo(zoom) { + if (!Number.isFinite(zoom) || zoom <= 0) return; + this.sigma.getCamera().setState({ ratio: 1 / zoom }); + } + + getZoom() { + return 1 / this.sigma.getCamera().getState().ratio; + } + + /** @param {[number, number]} offset viewport pixels */ + async translateBy([dx, dy]) { + const { width, height } = this.sigma.getDimensions(); + const target = this.sigma.viewportToFramedGraph({ + x: width / 2 - dx, + y: height / 2 - dy, + }); + this.sigma.getCamera().setState({ x: target.x, y: target.y }); + } + + /** Center the camera on the centroid of the given node/edge ids (zoom kept). */ + async focusElement(ids) { + const points = []; + for (const id of Array.isArray(ids) ? ids : [ids]) { + if (this.graph.hasNode(id)) { + const attrs = this.graph.getNodeAttributes(id); + points.push({ x: attrs.x, y: attrs.y }); + } else if (this.graph.hasEdge(id)) { + const edge = this.cache.edgeRef.get(id); + for (const nodeId of [edge?.source, edge?.target]) { + if (nodeId && this.graph.hasNode(nodeId)) { + const attrs = this.graph.getNodeAttributes(nodeId); + points.push({ x: attrs.x, y: attrs.y }); + } + } + } + } + if (points.length === 0) return; + const centroid = { + x: points.reduce((sum, p) => sum + p.x, 0) / points.length, + y: points.reduce((sum, p) => sum + p.y, 0) / points.length, + }; + const framed = this.sigma.viewportToFramedGraph(this.sigma.graphToViewport(centroid)); + this.sigma.getCamera().setState({ x: framed.x, y: framed.y }); + } + + /** @returns {[number, number]|null} graph-space position */ + getElementPosition(id) { + if (!this.graph.hasNode(id)) return null; + const attrs = this.graph.getNodeAttributes(id); + return [attrs.x, attrs.y]; + } + + /** Debug-only in callers; returns the camera center (framed coordinates). */ + getPosition() { + const state = this.sigma.getCamera().getState(); + return [state.x, state.y]; + } + + /** @returns {[number, number]} viewport size in px */ + getSize() { + const { width, height } = this.sigma.getDimensions(); + return [width, height]; + } + + /** Graph-space → viewport pixels (G6 name kept transitionally). */ + getViewportByCanvas([x, y]) { + const point = this.sigma.graphToViewport({ x, y }); + return [point.x, point.y]; + } + + // ------------------------------------------------------------------- layout + + /** Stores the layout spec; executed by layout() or the next render(). */ + async setLayout(spec) { + this.pendingLayout = spec; + } + + /** Execute the pending (or default) layout and write x/y into graphology. */ + async layout() { + const spec = this.pendingLayout ?? { type: this.cache.DEFAULTS.LAYOUT }; + this.pendingLayout = null; + await executeLayout(this.graph, spec); + } + + /** + * Tween node positions from wherever they currently sit (the outgoing + * workspace, left in place because render() skipped its snap while + * pendingLayoutTransition was set) to the incoming workspace's persisted + * positions. Consumes the flag. Reduced-motion users and large graphs get + * an instant snap instead — both still end at the exact target positions, so + * the rest of the switch (nodeRef sync, bubble redraw) is identical. + * + * @param {Map} positionsMap the + * incoming layout's persisted positions (app-model y-down). + * @returns {Promise} resolves once nodes are settled at the targets. + */ + async runLayoutTransition(positionsMap) { + this.pendingLayoutTransition = false; + if (this.killed || !positionsMap) return; + + // Build graph-space targets (y-flipped) only for nodes that still exist. + const { targets, count } = buildLayoutTransitionTargets(positionsMap, (id) => + this.graph.hasNode(id), + ); + if (count === 0) return; + + const snap = () => { + for (const [id, target] of Object.entries(targets)) { + this.graph.mergeNodeAttributes(id, target); + } + }; + + if (count > LAYOUT_TRANSITION_MAX_NODES || prefersReducedMotion()) { + snap(); + this.sigma.refresh({ skipIndexation: true }); + } else { + // A prior tween still running (rapid switches): cancel before starting a + // new one so they don't fight over the same node attributes. + this.layoutTransitionCancel?.(); + await new Promise((resolve) => { + this.layoutTransitionCancel = animateNodes( + this.graph, + targets, + { duration: LAYOUT_TRANSITION_MS, easing: "cubicInOut" }, + resolve, + ); + }); + this.layoutTransitionCancel = null; + } + + // Mirror the settled positions back into the nodeRef cache (the app-model + // store the rest of the code reads), then redraw bubble hulls at the + // final positions (they were last drawn at the outgoing view's layout). + for (const [id, pos] of positionsMap) { + const ref = this.cache.nodeRef.get(id); + if (ref && Number.isFinite(pos?.style?.x) && Number.isFinite(pos?.style?.y)) { + ref.style.x = pos.style.x; + ref.style.y = pos.style.y; + } + } + if (!this.killed) await this.cache.bs?.redrawBubbleSets?.(); + } + + // ------------------------------------------------------------- interactions + + /** @param {"drag"|"click"|"hover"|"tooltip"|"lasso"} name */ + setInteractionEnabled(name, enabled) { + this.interactions.setEnabled(name, enabled); + } + + isInteractionEnabled(name) { + return this.interactions.isEnabled(name); + } + + // ---------------------------------------------------------------- plugins + + /** + * Per-group bubble-set handle backed by the shared BubbleSetLayer (the + * old G6 plugin-instance surface: `members` Map + update/drawBubbleSets). + * core.registerPluginStates caches one per group in INSTANCES.BUBBLE_GROUPS, + * which destroyGraphAndRollBackUI resets together with this adapter. + * + * @param {string} key legacy plugin key ("bubbleSetPlugin-") or + * plain group key + */ + getPluginInstance(key) { + const group = key.startsWith("bubbleSetPlugin-") ? key.slice("bubbleSetPlugin-".length) : key; + return this.bubbleLayer.getGroupHandle(group); + } + + // ------------------------------------------------------------------- export + + /** + * PNG data URL of the current viewport. @sigma/export-image re-renders the + * scene on a temp renderer, which only carries sigma's own layers, so the + * bubble-set hulls and group labels are re-painted here at the export + * resolution (BubbleSetLayer.drawExport*) in their on-screen z-order: the + * body/outline UNDER the sigma image, the group labels OVER it. An opaque + * stage-background fill goes down first (export-image renders sigma + * transparent). The minimap is a viewport control and stays out of exports. + * + * `scale` raises the export resolution by bumping the device pixel ratio + * (see overrideDevicePixelRatio), so node/label proportions match the live + * view exactly at any factor. It is clamped to the WebGL framebuffer + * ceiling (a render past it fails SILENTLY — blank canvas, no exception, + * the old "8× exports nothing" bug) and, as a final safety net against + * driver memory pressure inside the claimed limits, a blank render steps + * the scale down and retries. Returns the data URL plus the scale actually + * applied so callers can warn on a clamp. + * + * @param {{ scale?: number }} [opts] + * @returns {Promise<{ url: string, requestedScale: number, appliedScale: number }>} + */ + async toDataURL({ scale = 1 } = {}) { + const dims = this.sigma.getDimensions(); + const dpr = window.devicePixelRatio || 1; + // The composite canvas is 2D (16384/side, ~268 MP ceilings baked into + // clampExportScale), but sigma renders through WebGL first — its + // framebuffer limit governs when it is lower. Stay a margin back from the + // probed GPU ceiling: allocating right at MAX_TEXTURE_SIZE while the + // scene's buffers are resident fails silently (blank/partial render). + const probedSide = webglMaxCanvasSide(); + const maxSide = Math.min( + probedSide != null ? probedSide * WEBGL_SAFE_SIDE_FRACTION : Infinity, + MAX_CANVAS_SIDE, + ); + let appliedScale = clampExportScale(scale, dims, dpr, { maxSide }); + const background = this.#stageBackgroundColor(); + const hasVisibleNodes = this.graph.someNode((_, attrs) => !attrs.hidden); + + let sigmaImage = await this.#renderExportBitmap(dpr, appliedScale); + // Silent-failure net: a within-limits allocation can still fail under GPU + // memory pressure, yielding a fully transparent render. Halve and retry — + // a smaller correct export beats a giant empty one. + while (hasVisibleNodes && appliedScale > 1 && bitmapLooksBlank(sigmaImage)) { + sigmaImage.close(); + appliedScale = Math.max(1, appliedScale / 2); + sigmaImage = await this.#renderExportBitmap(dpr, appliedScale); + } + + try { + const out = document.createElement("canvas"); + out.width = sigmaImage.width; + out.height = sigmaImage.height; + const ctx = out.getContext("2d"); + // Opaque stage background first: export-image renders sigma transparent, + // so without this the PNG shows through to whatever the viewer paints + // behind alpha (which reads as "dark mode" regardless of the theme). + ctx.fillStyle = background; + ctx.fillRect(0, 0, out.width, out.height); + // Re-fit + re-paint the hulls at the export resolution (the on-screen + // canvases are screen-resolution bitmaps — stretching them is what made + // scaled exports blurry, and their zoom-bucketed outlines drift from + // the freshly rendered nodes after a zoom). + const bubbleGroups = this.bubbleLayer.exportOutlines(); + this.bubbleLayer.drawExportBodies(ctx, bubbleGroups, dpr * appliedScale); + ctx.drawImage(sigmaImage, 0, 0); + // Group labels sit above sigma's node labels on screen (their own canvas + // at afterLayer "labels"); composite them last to keep that z-order. + this.bubbleLayer.drawExportLabels(ctx, bubbleGroups, dpr * appliedScale); + return { url: out.toDataURL("image/png"), requestedScale: scale, appliedScale }; + } catch (error) { + throw new Error(`Graph image export failed: ${error?.message ?? error}`); + } finally { + sigmaImage.close(); + } + } + + /** + * One sigma re-render at `dpr × scale` density, as an ImageBitmap. + * + * High-res export = the SAME framing at higher pixel density. Growing the + * temp renderer's CSS dimensions (export-image's width/height) scales node + * positions with the viewport but leaves node/label sizes in absolute px, + * so nodes shrink relative to the frame (2x → half size, 8x → invisible). + * Bumping the device pixel ratio instead scales the WHOLE pipeline + * uniformly — positions, radii, label fonts, edge widths, paddings — so + * the output is a true DPI multiple of the on-screen view. export-image + * reads window.devicePixelRatio once while building its own temp renderer + * and never re-renders the live one, so the override is invisible outside + * this call and always restored. + * + * @param {number} dpr the real device pixel ratio + * @param {number} scale export multiplier (already clamped) + * @returns {Promise} + */ + async #renderExportBitmap(dpr, scale) { + const restoreDpr = scale !== 1 ? overrideDevicePixelRatio(dpr * scale) : null; + let blob; + try { + blob = await exportImage.toBlob(this.sigma, { format: "png" }); + } finally { + restoreDpr?.(); + } + return createImageBitmap(blob); + } + + /** + * Standalone SVG document of the current viewport — true vector output + * (nodes, edges, labels, bubble hulls), so there is no resolution knob and + * no canvas ceiling to negotiate. Framing matches the live view 1:1. + * + * @returns {{ svg: string, width: number, height: number }} + */ + toSVG() { + const dims = this.sigma.getDimensions(); + const measureCtx = document.createElement("canvas").getContext("2d"); + const measureText = (text, font) => { + measureCtx.font = font; + return measureCtx.measureText(text).width; + }; + const svg = buildGraphSvg({ + sigma: this.sigma, + graph: this.graph, + dims, + background: this.#stageBackgroundColor(), + bubbleGroups: this.bubbleLayer.exportOutlines(), + measureText, + }); + return { svg, width: dims.width, height: dims.height }; + } + + /** + * The live stage background (the `--bg` token painted on the graph + * container). Falls back to opaque white so an export is never see-through. + * + * @returns {string} a CSS color usable as a 2d fillStyle + */ + #stageBackgroundColor() { + const fallback = "#ffffff"; + try { + const el = this.sigma.getContainer?.(); + if (!el || typeof getComputedStyle !== "function") return fallback; + const bg = getComputedStyle(el).backgroundColor; + // Transparent container → fall back (otherwise we'd re-introduce alpha). + if (!bg || bg === "transparent" || bg === "rgba(0, 0, 0, 0)") return fallback; + return bg; + } catch { + return fallback; + } + } +} + +export { SigmaAdapter }; diff --git a/src/graph/style.js b/src/graph/style.js index fea4b42..f60b3cc 100644 --- a/src/graph/style.js +++ b/src/graph/style.js @@ -13,10 +13,6 @@ class GraphStyleManager { if (currentLayout.nodeStyles.has(nodeId)) { currentLayout.nodeStyles.delete(nodeId); } - // Reset positions if configured - if (this.cache.CFG.RESET_SELECTION_BUTTON_RESETS_POSITIONS && currentLayout.positions.has(nodeId)) { - currentLayout.positions.delete(nodeId); - } } // Remove selected edges from the current layout's custom styles @@ -56,6 +52,7 @@ class GraphStyleManager { badges : src.badges ?? [], badgePalette : src.badgePalette ?? [], badgeFontSize: src.badgeFontSize ?? d.BADGE.FONT_SIZE, + badgeScaleWithNode: src.badgeScaleWithNode ?? d.BADGE.SCALE_WITH_NODE, } }; @@ -98,12 +95,18 @@ class GraphStyleManager { const defaultEdge = { type : edge.type ?? d.TYPE, style: { - startArrow : src.startArrow ?? d.ARROWS.START, - startArrowSize : src.startArrowSize ?? d.ARROWS.START_SIZE, - startArrowType : src.startArrowType ?? d.ARROWS.START_TYPE, - endArrow : src.endArrow ?? d.ARROWS.END, - endArrowSize : src.endArrowSize ?? d.ARROWS.END_SIZE, - endArrowType : src.endArrowType ?? d.ARROWS.END_TYPE, + startArrow : src.startArrow ?? d.ARROWS.START, + startArrowSize : src.startArrowSize ?? d.ARROWS.START_SIZE, + startArrowType : src.startArrowType ?? d.ARROWS.START_TYPE, + startArrowColor : src.startArrowColor ?? d.ARROWS.START_COLOR, + startArrowBorderColor: src.startArrowBorderColor?? d.ARROWS.START_BORDER_COLOR, + startArrowBorderSize : src.startArrowBorderSize ?? d.ARROWS.START_BORDER_SIZE, + endArrow : src.endArrow ?? d.ARROWS.END, + endArrowSize : src.endArrowSize ?? d.ARROWS.END_SIZE, + endArrowType : src.endArrowType ?? d.ARROWS.END_TYPE, + endArrowColor : src.endArrowColor ?? d.ARROWS.END_COLOR, + endArrowBorderColor : src.endArrowBorderColor ?? d.ARROWS.END_BORDER_COLOR, + endArrowBorderSize : src.endArrowBorderSize ?? d.ARROWS.END_BORDER_SIZE, lineWidth : src.lineWidth ?? d.LINE_WIDTH, lineDash : src.lineDash ?? d.LINE_DASH, @@ -112,6 +115,13 @@ class GraphStyleManager { halo : src.halo ?? d.HALO.ENABLED, haloStroke : src.haloStroke ?? d.HALO.COLOR, haloLineWidth : src.haloLineWidth ?? d.HALO.WIDTH, + + flow : src.flow ?? d.FLOW.ENABLED, + flowType : src.flowType ?? d.FLOW.TYPE, + flowSpeed : src.flowSpeed ?? d.FLOW.SPEED, + flowStroke : src.flowStroke ?? d.FLOW.COLOR, + flowOpacity : src.flowOpacity ?? d.FLOW.OPACITY, + flowDensity : src.flowDensity ?? d.FLOW.DENSITY, } }; diff --git a/src/graph/visible_graph.js b/src/graph/visible_graph.js new file mode 100644 index 0000000..598939c --- /dev/null +++ b/src/graph/visible_graph.js @@ -0,0 +1,43 @@ +// Node-safe (no DOM): shared by managers/metrics.js (centrality calculators) +// and graph/communities.js (Louvain community detection). +import {Graph} from "../lib/graphology.bundle.mjs"; + +/** + * Builds a temporary undirected multigraph from the currently visible + * subgraph so graphology algorithms can run on it. Multi because every + * visible parallel edge counts toward degree, matching the previous + * behaviour. + * + * @param {{nodeIDsToBeShown: Set, edgeIDsToBeShown: Set, edgeRef: Map}>}} cache + * @param {{weightProperty?: string|null}} [options] + * weightProperty: when set, each edge gets a numeric `weight` attribute read + * from edge.featureValues.get(weightProperty) so weighted algorithms + * (Louvain) can use it. A missing/non-finite value falls back to 1 (the + * edge still participates, just unweighted). Omit for the topology-only + * graph the centrality metrics rely on — that path is left untouched. + * @returns {Graph} + */ +function buildVisibleGraph(cache, options = {}) { + const {nodeIDsToBeShown: nodes, edgeIDsToBeShown: edges, edgeRef} = cache; + const weightProperty = options.weightProperty ?? null; + const graph = new Graph({type: 'undirected', multi: true}); + + for (const id of nodes) graph.addNode(id); + for (const edgeId of edges) { + const edge = edgeRef.get(edgeId); + if (!edge) continue; + const {source, target} = edge; + if (!graph.hasNode(source) || !graph.hasNode(target)) continue; + + if (weightProperty !== null) { + const raw = edge.featureValues?.get(weightProperty); + const weight = typeof raw === 'number' && Number.isFinite(raw) ? raw : 1; + graph.addEdgeWithKey(edgeId, source, target, {weight}); + } else { + graph.addEdgeWithKey(edgeId, source, target); + } + } + return graph; +} + +export {buildVisibleGraph}; diff --git a/src/graph/webgl_support.js b/src/graph/webgl_support.js new file mode 100644 index 0000000..cda245b --- /dev/null +++ b/src/graph/webgl_support.js @@ -0,0 +1,98 @@ +/** + * WebGL2 availability probe + persistent in-container fallback message. + * + * Sigma v3 needs a WebGL context; its createWebGLContext falls through + * webgl2 → webgl → experimental-webgl and then dereferences the result + * unchecked, so `new Sigma(...)` dies with an opaque TypeError ("Cannot read + * properties of null (reading 'blendFunc')") when none is available (GPU + * blocklist, remote desktop, disabled flags). We probe webgl2 specifically — + * sigma's shader programs assume it — and render a clear message instead. + * + * Node-safe: no sigma import; DOM access only inside the functions. + */ + +export const WEBGL2_ERROR_MESSAGE = + "Graph rendering requires WebGL2, which is not available in this browser or environment."; +export const WEBGL2_ERROR_HINT = + "Enable hardware acceleration in your browser settings (or update your GPU drivers), then reload."; + +/** + * Cheap pre-check before constructing the renderer. A passing probe does not + * guarantee sigma's own context creation succeeds (callers must still wrap + * construction), but a failing probe is definitive. + * + * @param {Document} [doc] injectable for tests; defaults to the global document + * @returns {boolean} + */ +export function isWebGL2Available(doc = globalThis.document) { + if (!doc) return false; + try { + const canvas = doc.createElement("canvas"); + return canvas.getContext("webgl2") != null; + } catch { + return false; + } +} + +// Probe result is per-GPU, not per-call: cache it for the session. +let cachedMaxSide = null; + +/** + * Largest canvas side (device px) the WebGL2 driver claims to render to. + * Sigma draws through WebGL framebuffers, whose ceiling + * (MAX_RENDERBUFFER_SIZE / MAX_TEXTURE_SIZE) is what actually governs + * high-resolution exports — Chrome's 2D-canvas limits are often higher, and + * exceeding the GL ceiling fails SILENTLY (blank render, no exception). + * + * @param {Document} [doc] injectable for tests; defaults to the global document + * @returns {number|null} the probed side limit, or null when no context exists + */ +export function webglMaxCanvasSide(doc = globalThis.document) { + if (cachedMaxSide !== null) return cachedMaxSide; + if (!doc) return null; + try { + const gl = doc.createElement("canvas").getContext("webgl2"); + if (!gl) return null; + const side = Math.min( + gl.getParameter(gl.MAX_RENDERBUFFER_SIZE), + gl.getParameter(gl.MAX_TEXTURE_SIZE), + ); + if (Number.isFinite(side) && side > 0) cachedMaxSide = side; + return cachedMaxSide; + } catch { + return null; + } +} + +/** Test hook: forget the cached probe so a fake document can be re-probed. */ +export function resetWebglMaxCanvasSideCache() { + cachedMaxSide = null; +} + +/** + * Renders the WebGL2-unavailable message into the graph container. The + * renderer is permanently dead in this session, so a transient toast is not + * enough — the message must persist where the graph would be. Clears any + * half-initialized sigma canvases first. + * + * @param {HTMLElement|null} containerEl + */ +export function renderWebGLUnavailableMessage(containerEl) { + if (!containerEl) return; + const doc = containerEl.ownerDocument; + containerEl.replaceChildren(); + + const wrapper = doc.createElement("div"); + wrapper.className = "webgl-error"; + + const title = doc.createElement("p"); + title.className = "webgl-error-title"; + title.textContent = `⛔ ${WEBGL2_ERROR_MESSAGE}`; + + const hint = doc.createElement("p"); + hint.className = "webgl-error-hint"; + hint.textContent = WEBGL2_ERROR_HINT; + + wrapper.append(title, hint); + containerEl.appendChild(wrapper); +} diff --git a/src/graph_lens_lite.html b/src/graph_lens_lite.html index 514f608..1edb178 100644 --- a/src/graph_lens_lite.html +++ b/src/graph_lens_lite.html @@ -7,11 +7,9 @@ - - - +
@@ -65,10 +63,12 @@

Graph Lens Lite

-
+
-

Loading ..

- Please wait +
+

Loading ..

+ Please wait +
@@ -83,15 +83,18 @@

-
- - - - - - +
+ + +
+
+ + + + +
+ +
@@ -124,47 +129,76 @@
Shown:

-
- -
+
-
- Selected nodes: - - - -
- Selected edges: - - -
-
-
- -
- - -
- - - - - +
+
+ Selection + + + + +
+ +
+
+ + + + +
+ +
+
Nothing selected
+
Click an element, drag a (L), or use to select by name or neighbours. The allows selection by properties.
+
+ +
+
+ 0 nodes + + + + 0 edges + + +
+ +
+ + Add to group: + + + +
+
+ +
+ Groups: + + + + +
+
+
+
Nothing selected — select nodes or edges to style them. Bubble-group styling below works without a selection.
diff --git a/src/lib/g6.min.js b/src/lib/g6.min.js deleted file mode 100644 index 9ad0874..0000000 --- a/src/lib/g6.min.js +++ /dev/null @@ -1,89 +0,0 @@ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).G6={})}(this,(function(t){"use strict";var e="undefined"!=typeof document?document.currentScript:null;function n(t){return n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},n(t)}function r(t){var e=function(t,e){if("object"!=n(t)||!t)return t;var r=t[Symbol.toPrimitive];if(void 0!==r){var i=r.call(t,e);if("object"!=n(i))return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(t,"string");return"symbol"==n(e)?e:e+""}function i(t,e,n){return(e=r(e))in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function o(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function a(t){for(var e=1;et.length)&&(e=t.length);for(var n=0,r=Array(e);n0?(v=2*Math.sqrt(g+1),t[3]=.25*v,t[0]=(h-f)/v,t[1]=(d-l)/v,t[2]=(s-u)/v):a>c&&a>p?(v=2*Math.sqrt(1+a-c-p),t[3]=(h-f)/v,t[0]=.25*v,t[1]=(s+u)/v,t[2]=(d+l)/v):c>p?(v=2*Math.sqrt(1+c-a-p),t[3]=(d-l)/v,t[0]=(s+u)/v,t[1]=.25*v,t[2]=(h+f)/v):(v=2*Math.sqrt(1+p-a-c),t[3]=(s-u)/v,t[0]=(d+l)/v,t[1]=(h+f)/v,t[2]=.25*v),t}function Q(t,e,n,r,i){var o=e[0],a=e[1],s=e[2],l=e[3],u=o+o,c=a+a,h=s+s,d=o*u,f=o*c,p=o*h,g=a*c,v=a*h,m=s*h,y=l*u,b=l*c,x=l*h,E=r[0],w=r[1],k=r[2],M=i[0],S=i[1],N=i[2],O=(1-(g+m))*E,T=(f+x)*E,C=(p-b)*E,A=(f-x)*w,P=(1-(d+m))*w,R=(v+y)*w,D=(p+b)*k,L=(v-y)*k,_=(1-(d+g))*k;return t[0]=O,t[1]=T,t[2]=C,t[3]=0,t[4]=A,t[5]=P,t[6]=R,t[7]=0,t[8]=D,t[9]=L,t[10]=_,t[11]=0,t[12]=n[0]+M-(O*M+A*S+D*N),t[13]=n[1]+S-(T*M+P*S+L*N),t[14]=n[2]+N-(C*M+R*S+_*N),t[15]=1,t}function J(t,e){var n=e[0],r=e[1],i=e[2],o=e[3],a=n+n,s=r+r,l=i+i,u=n*a,c=r*a,h=r*s,d=i*a,f=i*s,p=i*l,g=o*a,v=o*s,m=o*l;return t[0]=1-h-p,t[1]=c+m,t[2]=d-v,t[3]=0,t[4]=c-m,t[5]=1-u-p,t[6]=f+g,t[7]=0,t[8]=d+v,t[9]=f-g,t[10]=1-u-h,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t}function tt(t,e,n,r,i){var o,a=1/Math.tan(e/2);return t[0]=a/n,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=a,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[11]=-1,t[12]=0,t[13]=0,t[15]=0,null!=i&&i!==1/0?(o=1/(r-i),t[10]=(i+r)*o,t[14]=2*i*r*o):(t[10]=-1,t[14]=-2*r),t}Math.hypot||(Math.hypot=function(){for(var t=0,e=arguments.length;e--;)t+=arguments[e]*arguments[e];return Math.sqrt(t)});var et=tt;function nt(t,e,n,r,i,o,a){var s=1/(e-n),l=1/(r-i),u=1/(o-a);return t[0]=-2*s,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=-2*l,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=2*u,t[11]=0,t[12]=(e+n)*s,t[13]=(i+r)*l,t[14]=(a+o)*u,t[15]=1,t}var rt=nt;function it(t,e,n,r,i,o,a){var s=1/(e-n),l=1/(r-i),u=1/(o-a);return t[0]=-2*s,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=-2*l,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=u,t[11]=0,t[12]=(e+n)*s,t[13]=(i+r)*l,t[14]=o*u,t[15]=1,t}function ot(t,e,n,r){var i,o,a,s,l,u,c,h,d,f,p=e[0],g=e[1],v=e[2],m=r[0],y=r[1],b=r[2],x=n[0],E=n[1],w=n[2];return Math.abs(p-x)0?(n[0]=2*(s*a+c*r+l*o-u*i)/h,n[1]=2*(l*a+c*i+u*r-s*o)/h,n[2]=2*(u*a+c*o+s*i-l*r)/h):(n[0]=2*(s*a+c*r+l*o-u*i),n[1]=2*(l*a+c*i+u*r-s*o),n[2]=2*(u*a+c*o+s*i-l*r)),q(t,e,n),t},fromRotation:H,fromRotationTranslation:q,fromRotationTranslationScale:function(t,e,n,r){var i=e[0],o=e[1],a=e[2],s=e[3],l=i+i,u=o+o,c=a+a,h=i*l,d=i*u,f=i*c,p=o*u,g=o*c,v=a*c,m=s*l,y=s*u,b=s*c,x=r[0],E=r[1],w=r[2];return t[0]=(1-(p+v))*x,t[1]=(d+b)*x,t[2]=(f-y)*x,t[3]=0,t[4]=(d-b)*E,t[5]=(1-(h+v))*E,t[6]=(g+m)*E,t[7]=0,t[8]=(f+y)*w,t[9]=(g-m)*w,t[10]=(1-(h+p))*w,t[11]=0,t[12]=n[0],t[13]=n[1],t[14]=n[2],t[15]=1,t},fromRotationTranslationScaleOrigin:Q,fromScaling:W,fromTranslation:V,fromValues:P,fromXRotation:U,fromYRotation:$,fromZRotation:Y,frustum:function(t,e,n,r,i,o,a){var s=1/(n-e),l=1/(i-r),u=1/(o-a);return t[0]=2*o*s,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=2*o*l,t[6]=0,t[7]=0,t[8]=(n+e)*s,t[9]=(i+r)*l,t[10]=(a+o)*u,t[11]=-1,t[12]=0,t[13]=0,t[14]=a*o*2*u,t[15]=0,t},getRotation:Z,getScaling:K,getTranslation:X,identity:D,invert:_,lookAt:ot,mul:lt,multiply:j,multiplyScalar:function(t,e,n){return t[0]=e[0]*n,t[1]=e[1]*n,t[2]=e[2]*n,t[3]=e[3]*n,t[4]=e[4]*n,t[5]=e[5]*n,t[6]=e[6]*n,t[7]=e[7]*n,t[8]=e[8]*n,t[9]=e[9]*n,t[10]=e[10]*n,t[11]=e[11]*n,t[12]=e[12]*n,t[13]=e[13]*n,t[14]=e[14]*n,t[15]=e[15]*n,t},multiplyScalarAndAdd:function(t,e,n,r){return t[0]=e[0]+n[0]*r,t[1]=e[1]+n[1]*r,t[2]=e[2]+n[2]*r,t[3]=e[3]+n[3]*r,t[4]=e[4]+n[4]*r,t[5]=e[5]+n[5]*r,t[6]=e[6]+n[6]*r,t[7]=e[7]+n[7]*r,t[8]=e[8]+n[8]*r,t[9]=e[9]+n[9]*r,t[10]=e[10]+n[10]*r,t[11]=e[11]+n[11]*r,t[12]=e[12]+n[12]*r,t[13]=e[13]+n[13]*r,t[14]=e[14]+n[14]*r,t[15]=e[15]+n[15]*r,t},ortho:rt,orthoNO:nt,orthoZO:it,perspective:et,perspectiveFromFieldOfView:function(t,e,n,r){var i=Math.tan(e.upDegrees*Math.PI/180),o=Math.tan(e.downDegrees*Math.PI/180),a=Math.tan(e.leftDegrees*Math.PI/180),s=Math.tan(e.rightDegrees*Math.PI/180),l=2/(a+s),u=2/(i+o);return t[0]=l,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=u,t[6]=0,t[7]=0,t[8]=-(a-s)*l*.5,t[9]=(i-o)*u*.5,t[10]=r/(n-r),t[11]=-1,t[12]=0,t[13]=0,t[14]=r*n/(n-r),t[15]=0,t},perspectiveNO:tt,perspectiveZO:function(t,e,n,r,i){var o,a=1/Math.tan(e/2);return t[0]=a/n,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=a,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[11]=-1,t[12]=0,t[13]=0,t[15]=0,null!=i&&i!==1/0?(o=1/(r-i),t[10]=i*o,t[14]=i*r*o):(t[10]=-1,t[14]=-r),t},rotate:function(t,e,n,r){var i,o,a,s,l,u,c,h,d,f,p,g,v,m,y,b,x,E,w,k,M,N,O,T,C=r[0],A=r[1],P=r[2],R=Math.hypot(C,A,P);return R0&&(c*=f=1/Math.sqrt(f),h*=f,d*=f);var p=l*d-u*h,g=u*c-s*d,v=s*h-l*c;return(f=p*p+g*g+v*v)>0&&(p*=f=1/Math.sqrt(f),g*=f,v*=f),t[0]=p,t[1]=g,t[2]=v,t[3]=0,t[4]=h*v-d*g,t[5]=d*p-c*v,t[6]=c*g-h*p,t[7]=0,t[8]=c,t[9]=h,t[10]=d,t[11]=0,t[12]=i,t[13]=o,t[14]=a,t[15]=1,t},translate:B,transpose:L});function ht(){var t=new N(3);return N!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0),t}function dt(t){var e=new N(3);return e[0]=t[0],e[1]=t[1],e[2]=t[2],e}function ft(t){var e=t[0],n=t[1],r=t[2];return Math.hypot(e,n,r)}function pt(t,e,n){var r=new N(3);return r[0]=t,r[1]=e,r[2]=n,r}function gt(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t}function vt(t,e,n,r){return t[0]=e,t[1]=n,t[2]=r,t}function mt(t,e,n){return t[0]=e[0]+n[0],t[1]=e[1]+n[1],t[2]=e[2]+n[2],t}function yt(t,e,n){return t[0]=e[0]-n[0],t[1]=e[1]-n[1],t[2]=e[2]-n[2],t}function bt(t,e,n){return t[0]=e[0]*n,t[1]=e[1]*n,t[2]=e[2]*n,t}function xt(t,e){var n=e[0],r=e[1],i=e[2],o=n*n+r*r+i*i;return o>0&&(o=1/Math.sqrt(o)),t[0]=e[0]*o,t[1]=e[1]*o,t[2]=e[2]*o,t}function Et(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]}function wt(t,e,n){var r=e[0],i=e[1],o=e[2],a=n[0],s=n[1],l=n[2];return t[0]=i*l-o*s,t[1]=o*a-r*l,t[2]=r*s-i*a,t}function kt(t,e,n,r){var i=e[0],o=e[1],a=e[2];return t[0]=i+r*(n[0]-i),t[1]=o+r*(n[1]-o),t[2]=a+r*(n[2]-a),t}function Mt(t,e,n){var r=e[0],i=e[1],o=e[2],a=n[3]*r+n[7]*i+n[11]*o+n[15];return a=a||1,t[0]=(n[0]*r+n[4]*i+n[8]*o+n[12])/a,t[1]=(n[1]*r+n[5]*i+n[9]*o+n[13])/a,t[2]=(n[2]*r+n[6]*i+n[10]*o+n[14])/a,t}function St(t,e){var n=t[0],r=t[1],i=t[2],o=e[0],a=e[1],s=e[2];return Math.abs(n-o)<=S*Math.max(1,Math.abs(n),Math.abs(o))&&Math.abs(r-a)<=S*Math.max(1,Math.abs(r),Math.abs(a))&&Math.abs(i-s)<=S*Math.max(1,Math.abs(i),Math.abs(s))}var Nt=yt,Ot=function(t,e){var n=e[0]-t[0],r=e[1]-t[1],i=e[2]-t[2];return Math.hypot(n,r,i)},Tt=ft;function Ct(){var t=new N(4);return N!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0,t[3]=0),t}function At(t,e,n,r){var i=new N(4);return i[0]=t,i[1]=e,i[2]=n,i[3]=r,i}function Pt(t,e,n){var r=e[0],i=e[1],o=e[2],a=e[3];return t[0]=n[0]*r+n[4]*i+n[8]*o+n[12]*a,t[1]=n[1]*r+n[5]*i+n[9]*o+n[13]*a,t[2]=n[2]*r+n[6]*i+n[10]*o+n[14]*a,t[3]=n[3]*r+n[7]*i+n[11]*o+n[15]*a,t}function Rt(){var t=new N(4);return N!=Float32Array&&(t[0]=0,t[1]=0,t[2]=0),t[3]=1,t}function Dt(t,e,n){n*=.5;var r=Math.sin(n);return t[0]=r*e[0],t[1]=r*e[1],t[2]=r*e[2],t[3]=Math.cos(n),t}function Lt(t,e,n){var r=e[0],i=e[1],o=e[2],a=e[3],s=n[0],l=n[1],u=n[2],c=n[3];return t[0]=r*c+a*s+i*u-o*l,t[1]=i*c+a*l+o*s-r*u,t[2]=o*c+a*u+r*l-i*s,t[3]=a*c-r*s-i*l-o*u,t}function _t(t,e){var n=e[0],r=e[1],i=e[2],o=e[3],a=n*n+r*r+i*i+o*o,s=a?1/a:0;return t[0]=-n*s,t[1]=-r*s,t[2]=-i*s,t[3]=o*s,t}function It(t,e,n,r){var i=.5*Math.PI/180;e*=i,n*=i,r*=i;var o=Math.sin(e),a=Math.cos(e),s=Math.sin(n),l=Math.cos(n),u=Math.sin(r),c=Math.cos(r);return t[0]=o*l*c-a*s*u,t[1]=a*s*c+o*l*u,t[2]=a*l*u-o*s*c,t[3]=a*l*c+o*s*u,t}ht(),function(){var t=Ct()}();var jt=At,Bt=function(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t},Ft=function(t,e,n,r,i){return t[0]=e,t[1]=n,t[2]=r,t[3]=i,t},zt=Lt,Gt=function(t,e){var n=e[0],r=e[1],i=e[2],o=e[3],a=n*n+r*r+i*i+o*o;return a>0&&(a=1/Math.sqrt(a)),t[0]=n*a,t[1]=r*a,t[2]=i*a,t[3]=o*a,t};function Vt(){var t=new N(2);return N!=Float32Array&&(t[0]=0,t[1]=0),t}ht(),pt(1,0,0),pt(0,1,0),Rt(),Rt(),O(),function(){var t=Vt()}();var Wt=function(t){return null!==t&&"function"!=typeof t&&isFinite(t.length)},Ht=function(t,e){return void 0===e&&(e=[]),function(t,e){if(!Wt(t))return t;for(var n=[],r=0;r-1}(e,t)}))};function Ut(t){return"function"==typeof t}function $t(t){return null==t}function Yt(t){return Array.isArray(t)}var qt=function(t){var e=typeof t;return null!==t&&"object"===e||"function"===e};function Xt(t,e){if(t)if(Yt(t))for(var n=0,r=t.length;nn?n:t};function ae(t){return"number"==typeof t}function se(t,e,n){return void 0===n&&(n=1e-5),t===e||Math.abs(t-e)r&&(n=o,r=a)}return n}},ue=function(t,e){if(Yt(t)){for(var n,r=1/0,i=0;ii&&(r=n,a(1),++e),n[t]=o}function a(t){e=0,n=Object.create(null),t||(r=Object.create(null))}return a(),{clear:a,has:function(t){return void 0!==n[t]||void 0!==r[t]},get:function(t){var e=n[t];return void 0!==e?e:void 0!==(e=r[t])?(o(t,e),e):void 0},set:function(t,e){void 0!==n[t]?n[t]=e:o(t,e)}}}(n));var a=be.get(t);if(a.has(o))return a.get(o);var s=t.apply(this,r);return a.set(o,s),s}}function Ee(t,e){if(Object.hasOwn)return Object.hasOwn(t,e);if(null==t)throw new TypeError("Cannot convert undefined or null to object");return Object.prototype.hasOwnProperty.call(Object(t),e)}function we(t,e,n,r){for(var i in n=n||0,r=r||5,e)if(Ee(e,i)){var o=e[i];null!==o&&Jt(o)?(Jt(t[i])||(t[i]={}),ne?(r&&(clearTimeout(r),r=null),s=u,a=t.apply(i,o),r||(i=o=null)):r||!1===n.trailing||(r=setTimeout(l,c)),a};return u.cancel=function(){clearTimeout(r),s=0,r=i=o=null},u},De={},Le=function(){},_e=function(t){return t},Ie=function(t,e){return Ie=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])},Ie(t,e)};function je(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Class extends value "+String(e)+" is not a constructor or null");function n(){this.constructor=t}Ie(t,e),t.prototype=null===e?Object.create(e):(n.prototype=e.prototype,new n)}var Be=function(){return Be=Object.assign||function(t){for(var e,n=1,r=arguments.length;n=t.length&&(t=void 0),{value:t&&t[r++],done:!t}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}function Ve(t,e){var n="function"==typeof Symbol&&t[Symbol.iterator];if(!n)return t;var r,i,o=n.call(t),a=[];try{for(;(void 0===e||e-- >0)&&!(r=o.next()).done;)a.push(r.value)}catch(t){i={error:t}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return a}function We(t,e,n){if(n||2===arguments.length)for(var r,i=0,o=e.length;i7){t[n].shift();for(var r=t[n],i=n;r.length;)e[n]="A",t.splice(i+=1,0,["C"].concat(r.splice(0,6)));t.splice(n,1)}}var Ye={a:7,c:6,h:1,l:2,m:2,r:4,q:4,s:4,t:2,v:1,z:0};function qe(t){return Array.isArray(t)&&t.every((function(t){var e=t[0].toLowerCase();return Ye[e]===t.length-1&&"achlmqstvz".includes(e)}))}function Xe(t){return qe(t)&&t.every((function(t){var e=t[0];return e===e.toUpperCase()}))}function Ke(t){return Xe(t)&&t.every((function(t){var e=t[0];return"ACLMQZ".includes(e)}))}function Ze(t){for(var e=t.pathValue[t.segmentStart],n=e.toLowerCase(),r=t.data;r.length>=Ye[n]&&("m"===n&&r.length>2?(t.segments.push([e].concat(r.splice(0,2))),n="l",e="m"===e?"l":"L"):t.segments.push([e].concat(r.splice(0,Ye[n]))),Ye[n]););}function Qe(t){var e=t.index,n=t.pathValue,r=n.charCodeAt(e);return 48===r?(t.param=0,void(t.index+=1)):49===r?(t.param=1,void(t.index+=1)):void(t.err='[path-util]: invalid Arc flag "'.concat(n[e],'", expecting 0 or 1 at index ').concat(e))}function Je(t){return t>=48&&t<=57||43===t||45===t||46===t}function tn(t){return t>=48&&t<=57}function en(t){var e,n=t.max,r=t.pathValue,i=t.index,o=i,a=!1,s=!1,l=!1,u=!1;if(o>=n)t.err="[path-util]: Invalid path value at index ".concat(o,', "pathValue" is missing param');else if(43!==(e=r.charCodeAt(o))&&45!==e||(o+=1,e=r.charCodeAt(o)),tn(e)||46===e){if(46!==e){if(a=48===e,o+=1,e=r.charCodeAt(o),a&&o=5760&&[5760,6158,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8239,8287,12288,65279].includes(e));)t.index+=1}function rn(t){var e=t.max,n=t.pathValue,r=t.index,i=n.charCodeAt(r),o=Ye[n[r].toLowerCase()];if(t.segmentStart=r,function(t){switch(32|t){case 109:case 122:case 108:case 104:case 118:case 99:case 115:case 113:case 116:case 97:return!0;default:return!1}}(i))if(t.index+=1,nn(t),t.data=[],o){for(;;){for(var a=o;a>0;a-=1){if(97!=(32|i)||3!==a&&4!==a?en(t):Qe(t),t.err.length)return;t.data.push(t.param),nn(t),t.index=t.max)break;if(!Je(n.charCodeAt(t.index)))break}Ze(t)}else Ze(t);else t.err='[path-util]: Invalid path value "'.concat(n[r],'" is not a path command')}var on=function(t){this.pathValue=t,this.segments=[],this.max=t.length,this.index=0,this.param=0,this.segmentStart=0,this.data=[],this.err=""};function an(t){if(Xe(t))return[].concat(t);var e=function(t){if(qe(t))return[].concat(t);var e=new on(t);for(nn(e);e.index1&&(m*=N=Math.sqrt(N),y*=N);var O=m*m,T=y*y,C=(o===a?-1:1)*Math.sqrt(Math.abs((O*T-O*S*S-T*M*M)/(O*S*S+T*M*M)));f=C*m*S/y+(g+b)/2,p=C*-y*M/m+(v+x)/2,h=Math.asin(((v-p)/y*Math.pow(10,9)|0)/Math.pow(10,9)),d=Math.asin(((x-p)/y*Math.pow(10,9)|0)/Math.pow(10,9)),h=gd&&(h-=2*Math.PI),!a&&d>h&&(d-=2*Math.PI)}var A=d-h;if(Math.abs(A)>E){var P=d,R=b,D=x;d=h+E*(a&&d>h?1:-1),k=cn(b=f+m*Math.cos(d),x=p+y*Math.sin(d),m,y,i,0,a,R,D,[d,P,f,p])}A=d-h;var L=Math.cos(h),_=Math.sin(h),I=Math.cos(d),j=Math.sin(d),B=Math.tan(A/4),F=4/3*m*B,z=4/3*y*B,G=[g,v],V=[g+F*_,v-z*L],W=[b+F*j,x-z*I],H=[b,x];if(V[0]=2*G[0]-V[0],V[1]=2*G[1]-V[1],u)return V.concat(W,H,k);for(var U=[],$=0,Y=(k=V.concat(W,H,k)).length;$=o)a={x:n,y:r};else{var s=hn([t,e],[n,r],i/o);a={x:s[0],y:s[1]}}return{length:o,point:a,min:{x:Math.min(t,n),y:Math.min(e,r)},max:{x:Math.max(t,n),y:Math.max(e,r)}}}function mn(t,e){var n=t.x,r=t.y,i=e.x,o=e.y,a=n*i+r*o,s=Math.sqrt((Math.pow(n,2)+Math.pow(r,2))*(Math.pow(i,2)+Math.pow(o,2)));return(n*o-r*i<0?-1:1)*Math.acos(a/s)}function yn(t,e,n,r,i,o,a,s,l,u){var c=Math.abs,h=Math.sin,d=Math.cos,f=Math.sqrt,p=Math.PI,g=c(n),v=c(r),m=(i%360+360)%360*(p/180);if(t===s&&e===l)return{x:t,y:e};if(0===g||0===v)return vn(t,e,s,l,u).point;var y=(t-s)/2,b=(e-l)/2,x={x:d(m)*y+h(m)*b,y:-h(m)*y+d(m)*b},E=Math.pow(x.x,2)/Math.pow(g,2)+Math.pow(x.y,2)/Math.pow(v,2);E>1&&(g*=f(E),v*=f(E));var w=(Math.pow(g,2)*Math.pow(v,2)-Math.pow(g,2)*Math.pow(x.y,2)-Math.pow(v,2)*Math.pow(x.x,2))/(Math.pow(g,2)*Math.pow(x.y,2)+Math.pow(v,2)*Math.pow(x.x,2)),k=(o!==a?1:-1)*f(w=w<0?0:w),M=k*(g*x.y/v),S=k*(-v*x.x/g),N=d(m)*M-h(m)*S+(t+s)/2,O=h(m)*M+d(m)*S+(e+l)/2,T={x:(x.x-M)/g,y:(x.y-S)/v},C=mn({x:1,y:0},T),A=mn(T,{x:(-x.x-M)/g,y:(-x.y-S)/v});!a&&A>0?A-=2*p:a&&A<0&&(A+=2*p);var P=C+(A%=2*p)*u,R=g*d(P),D=v*h(P);return{x:d(m)*R-h(m)*D+N,y:h(m)*R+d(m)*D+O}}function bn(t,e,n,r,i,o,a,s,l,u,c){var h,d=c.bbox,f=void 0===d||d,p=c.length,g=void 0===p||p,v=c.sampleSize,m=void 0===v?30:v,y="number"==typeof u,b=t,x=e,E=0,w=[b,x,E],k=[b,x],M={x:0,y:0},S=[{x:b,y:x}];y&&u<=0&&(M={x:b,y:x});for(var N=0;N<=m;N+=1){if(b=(h=yn(t,e,n,r,i,o,a,s,l,N/m)).x,x=h.y,f&&S.push({x:b,y:x}),g&&(E+=gn(k,[b,x])),k=[b,x],y&&E>=u&&u>w[2]){var O=(E-u)/(E-w[2]);M={x:k[0]*(1-O)+w[0]*O,y:k[1]*(1-O)+w[1]*O}}w=[b,x,E]}return y&&u>=E&&(M={x:s,y:l}),{length:E,point:M,min:{x:Math.min.apply(null,S.map((function(t){return t.x}))),y:Math.min.apply(null,S.map((function(t){return t.y})))},max:{x:Math.max.apply(null,S.map((function(t){return t.x}))),y:Math.max.apply(null,S.map((function(t){return t.y})))}}}function xn(t,e,n,r,i,o,a,s,l){var u=1-l;return{x:Math.pow(u,3)*t+3*Math.pow(u,2)*l*n+3*u*Math.pow(l,2)*i+Math.pow(l,3)*a,y:Math.pow(u,3)*e+3*Math.pow(u,2)*l*r+3*u*Math.pow(l,2)*o+Math.pow(l,3)*s}}function En(t,e,n,r,i,o,a,s,l,u){var c,h=u.bbox,d=void 0===h||h,f=u.length,p=void 0===f||f,g=u.sampleSize,v=void 0===g?10:g,m="number"==typeof l,y=t,b=e,x=0,E=[y,b,x],w=[y,b],k={x:0,y:0},M=[{x:y,y:b}];m&&l<=0&&(k={x:y,y:b});for(var S=0;S<=v;S+=1){if(y=(c=xn(t,e,n,r,i,o,a,s,S/v)).x,b=c.y,d&&M.push({x:y,y:b}),p&&(x+=gn(w,[y,b])),w=[y,b],m&&x>=l&&l>E[2]){var N=(x-l)/(x-E[2]);k={x:w[0]*(1-N)+E[0]*N,y:w[1]*(1-N)+E[1]*N}}E=[y,b,x]}return m&&l>=x&&(k={x:a,y:s}),{length:x,point:k,min:{x:Math.min.apply(null,M.map((function(t){return t.x}))),y:Math.min.apply(null,M.map((function(t){return t.y})))},max:{x:Math.max.apply(null,M.map((function(t){return t.x}))),y:Math.max.apply(null,M.map((function(t){return t.y})))}}}function wn(t,e,n,r,i,o,a){var s=1-a;return{x:Math.pow(s,2)*t+2*s*a*n+Math.pow(a,2)*i,y:Math.pow(s,2)*e+2*s*a*r+Math.pow(a,2)*o}}function kn(t,e,n,r,i,o,a,s){var l,u=s.bbox,c=void 0===u||u,h=s.length,d=void 0===h||h,f=s.sampleSize,p=void 0===f?10:f,g="number"==typeof a,v=t,m=e,y=0,b=[v,m,y],x=[v,m],E={x:0,y:0},w=[{x:v,y:m}];g&&a<=0&&(E={x:v,y:m});for(var k=0;k<=p;k+=1){if(v=(l=wn(t,e,n,r,i,o,k/p)).x,m=l.y,c&&w.push({x:v,y:m}),d&&(y+=gn(x,[v,m])),x=[v,m],g&&y>=a&&a>b[2]){var M=(y-a)/(y-b[2]);E={x:x[0]*(1-M)+b[0]*M,y:x[1]*(1-M)+b[1]*M}}b=[v,m,y]}return g&&a>=y&&(E={x:i,y:o}),{length:y,point:E,min:{x:Math.min.apply(null,w.map((function(t){return t.x}))),y:Math.min.apply(null,w.map((function(t){return t.y})))},max:{x:Math.max.apply(null,w.map((function(t){return t.x}))),y:Math.max.apply(null,w.map((function(t){return t.y})))}}}function Mn(t,e,n){for(var r,i,o,a,s,l,u,c,h,d=ln(t),f="number"==typeof e,p=[],g=0,v=0,m=0,y=0,b=[],x=[],E=0,w={x:0,y:0},k=w,M=w,S=w,N=0,O=0,T=d.length;O=e&&(S=M),x.push(k),b.push(w),N+=E,g=(l="Z"!==c?h.slice(-2):[m,y])[0],v=l[1];return f&&e>=N&&(S={x:g,y:v}),{length:N,point:S,min:{x:Math.min.apply(null,b.map((function(t){return t.x}))),y:Math.min.apply(null,b.map((function(t){return t.y})))},max:{x:Math.max.apply(null,x.map((function(t){return t.x}))),y:Math.max.apply(null,x.map((function(t){return t.y})))}}}function Sn(t,e){var n=t.length-1,r=[],i=0,o=function(t){var e=t.length,n=e-1;return t.map((function(r,i){return t.map((function(r,o){var a,s=i+o;return 0===o||t[s]&&"M"===t[s][0]?(a=t[s],["M"].concat(a.slice(-2))):(s>=e&&(s-=n),t[s])}))}))}(t);return o.forEach((function(o,a){t.slice(1).forEach((function(r,o){i+=gn(t[(a+o)%n].slice(-2),e[o%n].slice(-2))})),r[a]=i,i=0})),o[r.indexOf(Math.min.apply(null,r))]}function Nn(t){return function(t){var e=0,n=0,r=0;return pn(t).map((function(t){var i;if("M"===t[0])return e=t[1],n=t[2],0;var o=t.slice(1),a=o[0],s=o[1],l=o[2],u=o[3],c=o[4],h=o[5];return r=function(t,e,n,r,i,o,a,s){return 3*((s-e)*(n+i)-(a-t)*(r+o)+r*(t-i)-n*(e-o)+s*(i+t/3)-a*(o+e/3))/20}(e,n,a,s,l,u,c,h),i=t.slice(-2),e=i[0],n=i[1],r})).reduce((function(t,e){return t+e}),0)}(t)>=0}function On(t){return t.map((function(t,e,n){var r=e&&n[e-1].slice(-2).concat(t.slice(1)),i=e?En(r[0],r[1],r[2],r[3],r[4],r[5],r[6],r[7],r[8],{bbox:!1}).length:0;return{s:t,ss:e?i?function(t,e){void 0===e&&(e=.5);var n=t.slice(0,2),r=t.slice(2,4),i=t.slice(4,6),o=t.slice(6,8),a=hn(n,r,e),s=hn(r,i,e),l=hn(i,o,e),u=hn(a,s,e),c=hn(s,l,e),h=hn(u,c,e);return[["C"].concat(a,u,h),["C"].concat(c,l,o)]}(r):[t,t]:[t],l:i}}))}function Tn(t,e,n){var r=On(t),i=On(e),o=r.length,a=i.length,s=r.filter((function(t){return t.l})).length,l=i.filter((function(t){return t.l})).length,u=r.filter((function(t){return t.l})).reduce((function(t,e){return t+e.l}),0)/s||0,c=i.filter((function(t){return t.l})).reduce((function(t,e){return t+e.l}),0)/l||0,h=n||Math.max(o,a),d=[u,c],f=[h-o,h-a],p=0,g=[r,i].map((function(t,e){return t.l===h?t.map((function(t){return t.s})):t.map((function(t,n){return p=n&&f[e]&&t.l>=d[e],f[e]-=p?1:0,p?t.ss:[t.s]})).flat()}));return g[0].length===g[1].length?g:Tn(g[0],g[1],h)}function Cn(t){var e=document.createElement("div");e.innerHTML=t;var n=e.childNodes[0];return n&&e.contains(n)&&e.removeChild(n),n}function An(){return An="undefined"!=typeof Reflect&&Reflect.get?Reflect.get.bind():function(t,e,n){var r=function(t,e){for(;!{}.hasOwnProperty.call(t,e)&&null!==(t=f(t)););return t}(t,e);if(r){var i=Object.getOwnPropertyDescriptor(r,e);return i.get?i.get.call(arguments.length<3?t:n):i.value}},An.apply(null,arguments)}function Pn(t,e,n,r){var i=An(f(t.prototype),e,n);return"function"==typeof i?function(t){return i.apply(n,t)}:i} -/*! - * @antv/g-math - * @description Geometry util - * @version 3.0.1 - * @date 5/9/2025, 8:18:51 AM - * @author AntVis - * @docs https://g.antv.antgroup.com/ - */function Rn(t,e,n,r){var i=t-n,o=e-r;return Math.sqrt(i*i+o*o)}function Dn(t,e){var n=Math.min.apply(Math,d(t)),r=Math.min.apply(Math,d(e));return{x:n,y:r,width:Math.max.apply(Math,d(t))-n,height:Math.max.apply(Math,d(e))-r}}function Ln(t,e,n,r,i,o){return n*Math.cos(i)*Math.cos(o)-r*Math.sin(i)*Math.sin(o)+t}function _n(t,e,n,r,i,o){return n*Math.sin(i)*Math.cos(o)+r*Math.cos(i)*Math.sin(o)+e}function In(t,e,n,r,i,o,a){for(var s=function(t,e,n){return Math.atan(-e/t*Math.tan(n))}(n,r,i),l=1/0,u=-1/0,c=[o,a],h=2*-Math.PI;h<=2*Math.PI;h+=Math.PI){var d=s+h;ou&&(u=p)}for(var g=function(t,e,n){return Math.atan(e/(t*Math.tan(n)))}(n,r,i),v=1/0,m=-1/0,y=[o,a],b=2*-Math.PI;b<=2*Math.PI;b+=Math.PI){var x=g+b;om&&(m=w)}return{x:l,y:v,width:u-l,height:m-v}}function jn(t,e,n,r,i,o){var a=-1,s=1/0,l=[n,r],u=20;o&&o>200&&(u=o/10);for(var c=1/u,h=c/10,f=0;f<=u;f++){var p=f*c,g=[i.apply(void 0,d(t.concat([p]))),i.apply(void 0,d(e.concat([p])))],v=Rn(l[0],l[1],g[0],g[1]);v=0&&w0&&(i=1/Math.sqrt(i)),t[0]=e[0]*i,t[1]=e[1]*i}(s,s);var l=[i-t,o-e];return Math.abs(function(t,e){return t[0]*e[0]+t[1]*e[1]}(l,s))}function Gn(t,e,n,r,i){var o=1-i;return o*o*o*t+3*e*i*o*o+3*n*i*i*o+r*i*i*i}function Vn(t,e,n,r){var i,o,a,s=-3*t+9*e-9*n+3*r,l=6*t-12*e+6*n,u=3*e-3*t,c=[];if(se(s,0))se(l,0)||(i=-u/l)>=0&&i<=1&&c.push(i);else{var h=l*l-4*s*u;se(h,0)?c.push(-l/(2*s)):h>0&&(o=(-l-(a=Math.sqrt(h)))/(2*s),(i=(-l+a)/(2*s))>=0&&i<=1&&c.push(i),o>=0&&o<=1&&c.push(o))}return c}function Wn(t,e,n,r,i,o,a,s){for(var l=[t,a],u=[e,s],c=Vn(t,n,i,a),h=Vn(e,r,o,s),d=0;d=0?[i]:[]}function qn(t,e,n,r,i,o){var a=Yn(t,n,i)[0],s=Yn(e,r,o)[0],l=[t,i],u=[e,o];return void 0!==a&&l.push($n(t,n,i,a)),void 0!==s&&u.push($n(e,r,o,s)),Dn(l,u)}function Xn(t,e,n,r,i,o,a,s){var l=function(t,e,n,r,i,o,a,s){return jn([t,n,i],[e,r,o],a,s,$n)}(t,e,n,r,i,o,a,s);return Rn(l.x,l.y,a,s)}function Kn(t,e){this.v=t,this.k=e}function Zn(t,e,n,r){var i=Object.defineProperty;try{i({},"",{})}catch(t){i=0}Zn=function(t,e,n,r){if(e)i?i(t,e,{value:n,enumerable:!r,configurable:!r,writable:!r}):t[e]=n;else{var o=function(e,n){Zn(t,e,(function(t){return this._invoke(e,n,t)}))};o("next",0),o("throw",1),o("return",2)}},Zn(t,e,n,r)}function Qn(){ -/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ -var t,e,n="function"==typeof Symbol?Symbol:{},r=n.iterator||"@@iterator",i=n.toStringTag||"@@toStringTag";function o(n,r,i,o){var l=r&&r.prototype instanceof s?r:s,u=Object.create(l.prototype);return Zn(u,"_invoke",function(n,r,i){var o,s,l,u=0,c=i||[],h=!1,d={p:0,n:0,v:t,a:f,f:f.bind(t,4),d:function(e,n){return o=e,s=0,l=t,d.n=n,a}};function f(n,r){for(s=n,l=r,e=0;!h&&u&&!i&&e3?(i=p===r)&&(l=o[(s=o[4])?5:(s=3,3)],o[4]=o[5]=t):o[0]<=f&&((i=n<2&&fr||r>p)&&(o[4]=n,o[5]=r,d.n=p,s=0))}if(i||n>1)return a;throw h=!0,r}return function(i,c,p){if(u>1)throw TypeError("Generator is already running");for(h&&1===c&&f(c,p),s=c,l=p;(e=s<2?t:l)||!h;){o||(s?s<3?(s>1&&(d.n=-1),f(s,l)):d.n=l:d.v=l);try{if(u=2,o){if(s||(i="next"),e=o[i]){if(!(e=e.call(o,l)))throw TypeError("iterator result is not an object");if(!e.done)return e;l=e.value,s<2&&(s=0)}else 1===s&&(e=o.return)&&e.call(o),s<2&&(l=TypeError("The iterator does not provide a '"+i+"' method"),s=1);o=t}else if((e=(h=d.n<0)?l:n.call(r,d))!==a)break}catch(e){o=t,s=1,l=e}finally{u=1}}return{value:e,done:h}}}(n,i,o),!0),u}var a={};function s(){}function l(){}function u(){}e=Object.getPrototypeOf;var c=[][r]?e(e([][r]())):(Zn(e={},r,(function(){return this})),e),h=u.prototype=s.prototype=Object.create(c);function d(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,u):(t.__proto__=u,Zn(t,i,"GeneratorFunction")),t.prototype=Object.create(h),t}return l.prototype=u,Zn(h,"constructor",u),Zn(u,"constructor",l),l.displayName="GeneratorFunction",Zn(u,i,"GeneratorFunction"),Zn(h),Zn(h,i,"Generator"),Zn(h,r,(function(){return this})),Zn(h,"toString",(function(){return"[object Generator]"})),(Qn=function(){return{w:o,m:d}})()}function Jn(t,e){function n(r,i,o,a){try{var s=t[r](i),l=s.value;return l instanceof Kn?e.resolve(l.v).then((function(t){n("next",t,o,a)}),(function(t){n("throw",t,o,a)})):e.resolve(l).then((function(t){s.value=t,o(s)}),(function(t){return n("throw",t,o,a)}))}catch(t){a(t)}}var r;this.next||(Zn(Jn.prototype),Zn(Jn.prototype,"function"==typeof Symbol&&Symbol.asyncIterator||"@asyncIterator",(function(){return this}))),Zn(this,"_invoke",(function(t,i,o){function a(){return new e((function(e,r){n(t,o,e,r)}))}return r=r?r.then(a,a):a()}),!0)}function tr(t,e,n,r,i){return new Jn(Qn().w(t,e,n,r),i||Promise)}function er(t,e,n,r,i){var o=tr(t,e,n,r,i);return o.next().then((function(t){return t.done?t.value:o.next()}))}function nr(t){var e=Object(t),n=[];for(var r in e)n.unshift(r);return function t(){for(;n.length;)if((r=n.pop())in e)return t.value=r,t.done=!1,t;return t.done=!0,t}}function rr(t){if(null!=t){var e=t["function"==typeof Symbol&&Symbol.iterator||"@@iterator"],r=0;if(e)return e.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length))return{next:function(){return t&&r>=t.length&&(t=void 0),{value:t&&t[r++],done:!t}}}}throw new TypeError(n(t)+" is not iterable")}function ir(){var t=Qn(),e=t.m(ir),n=(Object.getPrototypeOf?Object.getPrototypeOf(e):e.__proto__).constructor;function r(t){var e="function"==typeof t&&t.constructor;return!!e&&(e===n||"GeneratorFunction"===(e.displayName||e.name))}var i={throw:1,return:2,break:3,continue:3};function o(t){var e,n;return function(r){e||(e={stop:function(){return n(r.a,2)},catch:function(){return r.v},abrupt:function(t,e){return n(r.a,i[t],e)},delegateYield:function(t,i,o){return e.resultName=i,n(r.d,rr(t),o)},finish:function(t){return n(r.f,t)}},n=function(t,n,i){r.p=e.prev,r.n=e.next;try{return t(n,i)}finally{e.next=r.n}}),e.resultName&&(e[e.resultName]=r.v,e.resultName=void 0),e.sent=r.v,e.next=r.n;try{return t.call(this,e)}finally{r.p=e.prev,r.n=e.next}}}return(ir=function(){return{wrap:function(e,n,r,i){return t.w(o(e),n,r,i&&i.reverse())},isGeneratorFunction:r,mark:t.m,awrap:function(t,e){return new Kn(t,e)},AsyncIterator:Jn,async:function(t,e,n,i,a){return(r(e)?tr:er)(o(t),e,n,i,a)},keys:nr,values:rr}})()}function or(t,e,n,r,i,o,a){try{var s=t[o](a),l=s.value}catch(t){return void n(t)}s.done?e(l):Promise.resolve(l).then(r,i)}function ar(t){return function(){var e=this,n=arguments;return new Promise((function(r,i){var o=t.apply(e,n);function a(t){or(o,r,i,a,s,"next",t)}function s(t){or(o,r,i,a,s,"throw",t)}a(void 0)}))}}function sr(t,e){var n="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(!n){if(Array.isArray(t)||(n=h(t))||e){n&&(t=n);var r=0,i=function(){};return{s:i,n:function(){return r>=t.length?{done:!0}:{done:!1,value:t[r++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,a=!0,s=!1;return{s:function(){n=n.call(t)},n:function(){var t=n.next();return a=t.done,t},e:function(t){s=!0,o=t},f:function(){try{a||null==n.return||n.return()}finally{if(s)throw o}}}}function lr(t,e){if(null==t)return{};var n,r,i=function(t,e){if(null==t)return{};var n={};for(var r in t)if({}.hasOwnProperty.call(t,r)){if(-1!==e.indexOf(r))continue;n[r]=t[r]}return n}(t,e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(t);for(r=0;ri;){if(o-i>600){var s=o-i+1,l=r-i+1,u=Math.log(s),c=.5*Math.exp(2*u/3),h=.5*Math.sqrt(u*c*(s-c)/s)*(l-s/2<0?-1:1);e(t,r,Math.max(i,Math.floor(r-l*c/s+h)),Math.min(o,Math.floor(r+(s-l)*c/s+h)),a)}var d=t[r],f=i,p=o;for(n(t,i,r),a(t[o],d)>0&&n(t,i,o);f0;)p--}0===a(t[i],d)?n(t,i,p):n(t,++p,o),p<=r&&(i=p+1),r<=p&&(o=p-1)}}function n(t,e,n){var r=t[e];t[e]=t[n],t[n]=r}function r(t,e){return te?1:0}var i=function(t){void 0===t&&(t=9),this._maxEntries=Math.max(4,t),this._minEntries=Math.max(2,Math.ceil(.4*this._maxEntries)),this.clear()};function o(t,e,n){if(!n)return e.indexOf(t);for(var r=0;r=t.minX&&e.maxY>=t.minY}function m(t){return{children:t,height:1,leaf:!0,minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0}}function y(e,n,r,i,o){for(var a=[n,r];a.length;)if(!((r=a.pop())-(n=a.pop())<=i)){var s=n+Math.ceil((r-n)/i/2)*i;t(e,s,n,r,o),a.push(n,s,s,r)}}return i.prototype.all=function(){return this._all(this.data,[])},i.prototype.search=function(t){var e=this.data,n=[];if(!v(t,e))return n;for(var r=this.toBBox,i=[];e;){for(var o=0;o=0&&i[e].children.length>this._maxEntries;)this._split(i,e),e--;this._adjustParentBBoxes(r,i,e)},i.prototype._split=function(t,e){var n=t[e],r=n.children.length,i=this._minEntries;this._chooseSplitAxis(n,i,r);var o=this._chooseSplitIndex(n,i,r),s=m(n.children.splice(o,n.children.length-o));s.height=n.height,s.leaf=n.leaf,a(n,this.toBBox),a(s,this.toBBox),e?t[e-1].children.push(s):this._splitRoot(n,s)},i.prototype._splitRoot=function(t,e){this.data=m([t,e]),this.data.height=t.height+1,this.data.leaf=!1,a(this.data,this.toBBox)},i.prototype._chooseSplitIndex=function(t,e,n){for(var r,i=1/0,o=1/0,a=e;a<=n-e;a++){var l=s(t,0,a,this.toBBox),u=s(t,a,n,this.toBBox),c=p(l,u),d=h(l)+h(u);c=e;f--){var p=t.children[f];l(a,t.leaf?i(p):p),u+=d(a)}return u},i.prototype._adjustParentBBoxes=function(t,e,n){for(var r=n;r>=0;r--)l(e[r],t)},i.prototype._condense=function(t){for(var e=t.length-1,n=void 0;e>=0;e--)0===t[e].children.length?e>0?(n=t[e-1].children).splice(n.indexOf(t[e]),1):this.clear():a(t[e],this.toBBox)},i}()}(ur);var cr=ur.exports,hr=function(t){return t.GROUP="g",t.FRAGMENT="fragment",t.CIRCLE="circle",t.ELLIPSE="ellipse",t.IMAGE="image",t.RECT="rect",t.LINE="line",t.POLYLINE="polyline",t.POLYGON="polygon",t.TEXT="text",t.PATH="path",t.HTML="html",t.MESH="mesh",t}({}),dr=function(t){return t[t.ZERO=0]="ZERO",t[t.NEGATIVE_ONE=1]="NEGATIVE_ONE",t}({}),fr=function(){return u((function t(){s(this,t),this.plugins=[]}),[{key:"addRenderingPlugin",value:function(t){this.plugins.push(t),this.context.renderingPlugins.push(t)}},{key:"removeAllRenderingPlugins",value:function(){var t=this;this.plugins.forEach((function(e){var n=t.context.renderingPlugins.indexOf(e);n>=0&&t.context.renderingPlugins.splice(n,1)}))}}])}(),pr=function(){return u((function t(e){s(this,t),this.clipSpaceNearZ=dr.NEGATIVE_ONE,this.plugins=[],this.config=a({enableDirtyCheck:!0,enableCulling:!1,enableAutoRendering:!0,enableDirtyRectangleRendering:!0,enableDirtyRectangleRenderingDebug:!1,enableSizeAttenuation:!0,enableRenderingOptimization:!1},e)}),[{key:"registerPlugin",value:function(t){-1===this.plugins.findIndex((function(e){return e===t}))&&this.plugins.push(t)}},{key:"unregisterPlugin",value:function(t){var e=this.plugins.findIndex((function(e){return e===t}));e>-1&&this.plugins.splice(e,1)}},{key:"getPlugins",value:function(){return this.plugins}},{key:"getPlugin",value:function(t){return this.plugins.find((function(e){return e.name===t}))}},{key:"getConfig",value:function(){return this.config}},{key:"setConfig",value:function(t){Object.assign(this.config,t)}}])}(),gr=mt,vr=gt,mr=function(t,e,n){return t[0]=Math.max(e[0],n[0]),t[1]=Math.max(e[1],n[1]),t[2]=Math.max(e[2],n[2]),t},yr=function(t,e,n){return t[0]=Math.min(e[0],n[0]),t[1]=Math.min(e[1],n[1]),t[2]=Math.min(e[2],n[2]),t},br=bt,xr=Nt,Er=function(){function t(){s(this,t),this.center=[0,0,0],this.halfExtents=[0,0,0],this.min=[0,0,0],this.max=[0,0,0]}return u(t,[{key:"update",value:function(t,e){vr(this.center,t),vr(this.halfExtents,e),xr(this.min,this.center,this.halfExtents),gr(this.max,this.center,this.halfExtents)}},{key:"setMinMax",value:function(t,e){gr(this.center,e,t),br(this.center,this.center,.5),xr(this.halfExtents,e,t),br(this.halfExtents,this.halfExtents,.5),vr(this.min,t),vr(this.max,e)}},{key:"getMin",value:function(){return this.min}},{key:"getMax",value:function(){return this.max}},{key:"add",value:function(e){if(!t.isEmpty(e))if(t.isEmpty(this))this.setMinMax(e.getMin(),e.getMax());else{var n=this.center,r=n[0],i=n[1],o=n[2],a=this.halfExtents,s=a[0],l=a[1],u=a[2],c=r-s,h=r+s,d=i-l,f=i+l,p=o-u,g=o+u,v=e.center,m=v[0],y=v[1],b=v[2],x=e.halfExtents,E=x[0],w=x[1],k=x[2],M=m-E,S=m+E,N=y-w,O=y+w,T=b-k,C=b+k;Mh&&(h=S),Nf&&(f=O),Tg&&(g=C),n[0]=.5*(c+h),n[1]=.5*(d+f),n[2]=.5*(p+g),a[0]=.5*(h-c),a[1]=.5*(f-d),a[2]=.5*(g-p),this.min[0]=c,this.min[1]=d,this.min[2]=p,this.max[0]=h,this.max[1]=f,this.max[2]=g}}},{key:"setFromTransformedAABB",value:function(t,e){var n=this.center,r=this.halfExtents,i=t.center,o=t.halfExtents,a=e[0],s=e[4],l=e[8],u=e[1],c=e[5],h=e[9],d=e[2],f=e[6],p=e[10],g=Math.abs(a),v=Math.abs(s),m=Math.abs(l),y=Math.abs(u),b=Math.abs(c),x=Math.abs(h),E=Math.abs(d),w=Math.abs(f),k=Math.abs(p);n[0]=e[12]+a*i[0]+s*i[1]+l*i[2],n[1]=e[13]+u*i[0]+c*i[1]+h*i[2],n[2]=e[14]+d*i[0]+f*i[1]+p*i[2],r[0]=g*o[0]+v*o[1]+m*o[2],r[1]=y*o[0]+b*o[1]+x*o[2],r[2]=E*o[0]+w*o[1]+k*o[2],xr(this.min,n,r),gr(this.max,n,r)}},{key:"intersects",value:function(t){var e=this.getMax(),n=this.getMin(),r=t.getMax(),i=t.getMin();return n[0]<=r[0]&&e[0]>=i[0]&&n[1]<=r[1]&&e[1]>=i[1]&&n[2]<=r[2]&&e[2]>=i[2]}},{key:"intersection",value:function(e){if(!this.intersects(e))return null;var n=new t,r=mr([0,0,0],this.getMin(),e.getMin()),i=yr([0,0,0],this.getMax(),e.getMax());return n.setMinMax(r,i),n}},{key:"getNegativeFarPoint",value:function(t){return 273===t.pnVertexFlag?vr([0,0,0],this.min):272===t.pnVertexFlag?[this.min[0],this.min[1],this.max[2]]:257===t.pnVertexFlag?[this.min[0],this.max[1],this.min[2]]:256===t.pnVertexFlag?[this.min[0],this.max[1],this.max[2]]:17===t.pnVertexFlag?[this.max[0],this.min[1],this.min[2]]:16===t.pnVertexFlag?[this.max[0],this.min[1],this.max[2]]:1===t.pnVertexFlag?[this.max[0],this.max[1],this.min[2]]:[this.max[0],this.max[1],this.max[2]]}},{key:"getPositiveFarPoint",value:function(t){return 273===t.pnVertexFlag?vr([0,0,0],this.max):272===t.pnVertexFlag?[this.max[0],this.max[1],this.min[2]]:257===t.pnVertexFlag?[this.max[0],this.min[1],this.max[2]]:256===t.pnVertexFlag?[this.max[0],this.min[1],this.min[2]]:17===t.pnVertexFlag?[this.min[0],this.max[1],this.max[2]]:16===t.pnVertexFlag?[this.min[0],this.max[1],this.min[2]]:1===t.pnVertexFlag?[this.min[0],this.min[1],this.max[2]]:[this.min[0],this.min[1],this.min[2]]}}],[{key:"isEmpty",value:function(t){return!t||0===t.halfExtents[0]&&0===t.halfExtents[1]&&0===t.halfExtents[2]}}])}(),wr=function(){return u((function t(e,n){s(this,t),this.distance=e||0,this.normal=n||pt(0,1,0),this.updatePNVertexFlag()}),[{key:"updatePNVertexFlag",value:function(){this.pnVertexFlag=(Number(this.normal[0]>=0)<<8)+(Number(this.normal[1]>=0)<<4)+Number(this.normal[2]>=0)}},{key:"distanceToPoint",value:function(t){return Et(t,this.normal)-this.distance}},{key:"normalize",value:function(){var t=1/Tt(this.normal);bt(this.normal,this.normal,t),this.distance*=t}},{key:"intersectsLine",value:function(t,e,n){var r=this.distanceToPoint(t),i=r/(r-this.distanceToPoint(e)),o=i>=0&&i<=1;return o&&n&&kt(n,t,e,i),o}}])}(),kr=function(t){return t[t.OUTSIDE=4294967295]="OUTSIDE",t[t.INSIDE=0]="INSIDE",t[t.INDETERMINATE=2147483647]="INDETERMINATE",t}({}),Mr=function(){return u((function t(e){if(s(this,t),this.planes=[],e)this.planes=e;else for(var n=0;n<6;n++)this.planes.push(new wr)}),[{key:"extractFromVPMatrix",value:function(t){var e=b(t,16),n=e[0],r=e[1],i=e[2],o=e[3],a=e[4],s=e[5],l=e[6],u=e[7],c=e[8],h=e[9],d=e[10],f=e[11],p=e[12],g=e[13],v=e[14],m=e[15];vt(this.planes[0].normal,o-n,u-a,f-c),this.planes[0].distance=m-p,vt(this.planes[1].normal,o+n,u+a,f+c),this.planes[1].distance=m+p,vt(this.planes[2].normal,o+r,u+s,f+h),this.planes[2].distance=m+g,vt(this.planes[3].normal,o-r,u-s,f-h),this.planes[3].distance=m-g,vt(this.planes[4].normal,o-i,u-l,f-d),this.planes[4].distance=m-v,vt(this.planes[5].normal,o+i,u+l,f+d),this.planes[5].distance=m+v,this.planes.forEach((function(t){t.normalize(),t.updatePNVertexFlag()}))}}])}(),Sr=function(){function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;s(this,t),this.x=0,this.y=0,this.x=e,this.y=n}return u(t,[{key:"clone",value:function(){return new t(this.x,this.y)}},{key:"copyFrom",value:function(t){this.x=t.x,this.y=t.y}}])}(),Nr=function(){function t(e,n,r,i){s(this,t),this.x=e,this.y=n,this.width=r,this.height=i,this.left=e,this.right=e+r,this.top=n,this.bottom=n+i}return u(t,[{key:"toJSON",value:function(){}}],[{key:"fromRect",value:function(e){return new t(e.x,e.y,e.width,e.height)}},{key:"applyTransform",value:function(e,n){var r=At(e.x,e.y,0,1),i=At(e.x+e.width,e.y,0,1),o=At(e.x,e.y+e.height,0,1),a=At(e.x+e.width,e.y+e.height,0,1),s=Ct(),l=Ct(),u=Ct(),c=Ct();Pt(s,r,n),Pt(l,i,n),Pt(u,o,n),Pt(c,a,n);var h=Math.min(s[0],l[0],u[0],c[0]),d=Math.min(s[1],l[1],u[1],c[1]),f=Math.max(s[0],l[0],u[0],c[0]),p=Math.max(s[1],l[1],u[1],c[1]);return t.fromRect({x:h,y:d,width:f-h,height:p-d})}}])}(),Or="Method not implemented.",Tr="Use document.documentElement instead.";function Cr(t){return void 0===t?0:t>360||t<-360?t%360:t}var Ar=ht();function Pr(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,r=!(arguments.length>3&&void 0!==arguments[3])||arguments[3];return Array.isArray(t)&&3===t.length?r?dt(t):gt(Ar,t):ae(t)?r?pt(t,e,n):vt(Ar,t,e,n):r?pt(t[0],t[1]||e,t[2]||n):vt(Ar,t[0],t[1]||e,t[2]||n)}var Rr=Math.PI/180;function Dr(t){return t*Rr}var Lr=180/Math.PI;function _r(t){return t*Lr}var Ir=Math.PI/2;function jr(t,e){return 16===e.length?function(t,e){var n,r,i=b(K(ht(),e),3),o=i[0],a=i[1],s=i[2],l=Math.asin(-e[2]/o);return l-Ir?(n=Math.atan2(e[6]/a,e[10]/s),r=Math.atan2(e[1]/o,e[0]/o)):(r=0,n=-Math.atan2(e[4]/a,e[5]/a)):(r=0,n=Math.atan2(e[4]/a,e[5]/a)),t[0]=n,t[1]=l,t[2]=r,t}(t,e):function(t,e){var n=e[0],r=e[1],i=e[2],o=e[3],a=r*r,s=i*i,l=o*o,u=n*n+a+s+l,c=n*o-r*i;return c>.499995*u?(t[0]=Ir,t[1]=2*Math.atan2(r,n),t[2]=0):c<-.499995*u?(t[0]=-Ir,t[1]=2*Math.atan2(r,n),t[2]=0):(t[0]=Math.asin(2*(n*i-o*r)),t[1]=Math.atan2(2*(n*o+r*i),1-2*(s+l)),t[2]=Math.atan2(2*(n*r+i*o),1-2*(a+s))),t}(t,e)}function Br(t,e,n,r,i){var o,a,s,l,u,c,h,d,f,p,g=Math.cos(t),v=Math.sin(t);return o=r*g,a=i*v,s=0,l=-r*v,u=i*g,c=0,h=e,d=n,f=1,(p=new N(9))[0]=o,p[1]=a,p[2]=s,p[3]=l,p[4]=u,p[5]=c,p[6]=h,p[7]=d,p[8]=f,p}function Fr(t){var e=t[0],n=t[1],r=t[3],i=t[4],o=Math.sqrt(e*e+n*n),a=Math.sqrt(r*r+i*i);if(e*i-n*r<0&&(e7&&void 0!==arguments[7]&&arguments[7]?(s=-a/v,l=-m/v):(s=-(a+o)/v,l=-2*m/v),t[0]=d,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=f,t[6]=0,t[7]=0,t[8]=p,t[9]=g,t[10]=s,t[11]=-1,t[12]=0,t[13]=0,t[14]=l,t[15]=0}(this.projectionMatrix,l,l+s,o-a,o,t,this.far,this.clipSpaceNearZ===dr.ZERO),_(this.projectionMatrixInverse,this.projectionMatrix),this.triggerUpdate(),this}},{key:"setOrthographic",value:function(t,e,n,r,i,o){var a;this.projectionMode=qr.ORTHOGRAPHIC,this.rright=e,this.left=t,this.top=n,this.bottom=r,this.near=i,this.far=o;var s=(this.rright-this.left)/(2*this.zoom),l=(this.top-this.bottom)/(2*this.zoom),u=(this.rright+this.left)/2,c=(this.top+this.bottom)/2,h=u-s,d=u+s,f=c+l,p=c-l;if(null!==(a=this.view)&&void 0!==a&&a.enabled){var g=(this.rright-this.left)/this.view.fullWidth/this.zoom,v=(this.top-this.bottom)/this.view.fullHeight/this.zoom;d=(h+=g*this.view.offsetX)+g*this.view.width,p=(f-=v*this.view.offsetY)-v*this.view.height}return this.clipSpaceNearZ===dr.NEGATIVE_ONE?rt(this.projectionMatrix,h,d,f,p,i,o):it(this.projectionMatrix,h,d,f,p,i,o),_(this.projectionMatrixInverse,this.projectionMatrix),this._getOrthoMatrix(),this.triggerUpdate(),this}},{key:"setPosition",value:function(t){var e=Pr(t,arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.position[1],arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.position[2]);return this._setPosition(e),this.setFocalPoint(this.focalPoint),this.triggerUpdate(),this}},{key:"setFocalPoint",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.focalPoint[1],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.focalPoint[2],r=pt(0,1,0);if(this.focalPoint=Pr(t,e,n),this.trackingMode===Yr.CINEMATIC){var i=yt(ht(),this.focalPoint,this.position);t=i[0],e=i[1],n=i[2];var o=ft(i),a=_r(Math.asin(e/o)),s=90+_r(Math.atan2(n,t)),l=T();G(l,l,Dr(s)),z(l,l,Dr(a)),r=Mt(ht(),[0,1,0],l)}return _(this.matrix,ot(T(),this.position,this.focalPoint,r)),this._getAxes(),this._getDistance(),this._getAngles(),this.triggerUpdate(),this}},{key:"getDistance",value:function(){return this.distance}},{key:"getDistanceVector",value:function(){return this.distanceVector}},{key:"setDistance",value:function(t){if(this.distance===t||t<0)return this;this.distance=t,this.distance>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):8===n?wi(e>>24&255,e>>16&255,e>>8&255,(255&e)/255):4===n?wi(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|240&e,((15&e)<<4|15&e)/255):null):(e=hi.exec(t))?new ki(e[1],e[2],e[3],1):(e=di.exec(t))?new ki(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=fi.exec(t))?wi(e[1],e[2],e[3],e[4]):(e=pi.exec(t))?wi(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=gi.exec(t))?Ci(e[1],e[2]/100,e[3]/100,1):(e=vi.exec(t))?Ci(e[1],e[2]/100,e[3]/100,e[4]):mi.hasOwnProperty(t)?Ei(mi[t]):"transparent"===t?new ki(NaN,NaN,NaN,0):null}function Ei(t){return new ki(t>>16&255,t>>8&255,255&t,1)}function wi(t,e,n,r){return r<=0&&(t=e=n=NaN),new ki(t,e,n,r)}function ki(t,e,n,r){this.r=+t,this.g=+e,this.b=+n,this.opacity=+r}function Mi(){return`#${Ti(this.r)}${Ti(this.g)}${Ti(this.b)}`}function Si(){const t=Ni(this.opacity);return`${1===t?"rgb(":"rgba("}${Oi(this.r)}, ${Oi(this.g)}, ${Oi(this.b)}${1===t?")":`, ${t})`}`}function Ni(t){return isNaN(t)?1:Math.max(0,Math.min(1,t))}function Oi(t){return Math.max(0,Math.min(255,Math.round(t)||0))}function Ti(t){return((t=Oi(t))<16?"0":"")+t.toString(16)}function Ci(t,e,n,r){return r<=0?t=e=n=NaN:n<=0||n>=1?t=e=NaN:e<=0&&(t=NaN),new Pi(t,e,n,r)}function Ai(t){if(t instanceof Pi)return new Pi(t.h,t.s,t.l,t.opacity);if(t instanceof ii||(t=xi(t)),!t)return new Pi;if(t instanceof Pi)return t;var e=(t=t.rgb()).r/255,n=t.g/255,r=t.b/255,i=Math.min(e,n,r),o=Math.max(e,n,r),a=NaN,s=o-i,l=(o+i)/2;return s?(a=e===o?(n-r)/s+6*(n0&&l<1?0:a,new Pi(a,s,l,t.opacity)}function Pi(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}function Ri(t){return(t=(t||0)%360)<0?t+360:t}function Di(t){return Math.max(0,Math.min(1,t||0))}function Li(t,e,n){return 255*(t<60?e+(n-e)*t/60:t<180?n:t<240?e+(n-e)*(240-t)/60:e)}function _i(t,e){if("function"!=typeof t||null!=e&&"function"!=typeof e)throw new TypeError("Expected a function");var n=function(){for(var r=arguments.length,i=new Array(r),o=0;o=240?t-240:t+120,i,r),Li(t,i,r),Li(t<120?t+240:t-120,i,r),this.opacity)},clamp(){return new Pi(Ri(this.h),Di(this.s),Di(this.l),Ni(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const t=Ni(this.opacity);return`${1===t?"hsl(":"hsla("}${Ri(this.h)}, ${100*Di(this.s)}%, ${100*Di(this.l)}%${1===t?")":`, ${t})`}`}})),_i.Cache=Map,_i.cacheList=[],_i.clearCache=function(){_i.cacheList.forEach((function(t){return t.clear()}))};var Ii=function(t){return t[t.kUnknown=0]="kUnknown",t[t.kNumber=1]="kNumber",t[t.kPercentage=2]="kPercentage",t[t.kEms=3]="kEms",t[t.kPixels=4]="kPixels",t[t.kRems=5]="kRems",t[t.kDegrees=6]="kDegrees",t[t.kRadians=7]="kRadians",t[t.kGradians=8]="kGradians",t[t.kTurns=9]="kTurns",t[t.kMilliseconds=10]="kMilliseconds",t[t.kSeconds=11]="kSeconds",t[t.kInteger=12]="kInteger",t}({}),ji=function(t){return t[t.kUNumber=0]="kUNumber",t[t.kUPercent=1]="kUPercent",t[t.kULength=2]="kULength",t[t.kUAngle=3]="kUAngle",t[t.kUTime=4]="kUTime",t[t.kUOther=5]="kUOther",t}({}),Bi=function(t){return t[t.kYes=0]="kYes",t[t.kNo=1]="kNo",t}({}),Fi=function(t){return t[t.kYes=0]="kYes",t[t.kNo=1]="kNo",t}({}),zi=[{name:"em",unit_type:Ii.kEms},{name:"px",unit_type:Ii.kPixels},{name:"deg",unit_type:Ii.kDegrees},{name:"rad",unit_type:Ii.kRadians},{name:"grad",unit_type:Ii.kGradians},{name:"ms",unit_type:Ii.kMilliseconds},{name:"s",unit_type:Ii.kSeconds},{name:"rem",unit_type:Ii.kRems},{name:"turn",unit_type:Ii.kTurns}],Gi=function(t){return t[t.kUnknownType=0]="kUnknownType",t[t.kUnparsedType=1]="kUnparsedType",t[t.kKeywordType=2]="kKeywordType",t[t.kUnitType=3]="kUnitType",t[t.kSumType=4]="kSumType",t[t.kProductType=5]="kProductType",t[t.kNegateType=6]="kNegateType",t[t.kInvertType=7]="kInvertType",t[t.kMinType=8]="kMinType",t[t.kMaxType=9]="kMaxType",t[t.kClampType=10]="kClampType",t[t.kTransformType=11]="kTransformType",t[t.kPositionType=12]="kPositionType",t[t.kURLImageType=13]="kURLImageType",t[t.kColorType=14]="kColorType",t[t.kUnsupportedColorType=15]="kUnsupportedColorType",t}({}),Vi=function(t){return t?"number"===t?Ii.kNumber:"percent"===t||"%"===t?Ii.kPercentage:function(t){return zi.find((function(e){return e.name===t})).unit_type}(t):Ii.kUnknown},Wi=function(t){var e=1;switch(t){case Ii.kPixels:case Ii.kDegrees:case Ii.kSeconds:break;case Ii.kMilliseconds:e=.001;break;case Ii.kRadians:e=180/Math.PI;break;case Ii.kGradians:e=.9;break;case Ii.kTurns:e=360}return e},Hi=function(t){switch(t){case Ii.kNumber:case Ii.kInteger:return"";case Ii.kPercentage:return"%";case Ii.kEms:return"em";case Ii.kRems:return"rem";case Ii.kPixels:return"px";case Ii.kDegrees:return"deg";case Ii.kRadians:return"rad";case Ii.kGradians:return"grad";case Ii.kMilliseconds:return"ms";case Ii.kSeconds:return"s";case Ii.kTurns:return"turn"}return""},Ui=function(){return u((function t(){s(this,t)}),[{key:"toString",value:function(){return this.buildCSSText(Bi.kNo,Fi.kNo,"")}},{key:"isNumericValue",value:function(){return this.getType()>=Gi.kUnitType&&this.getType()<=Gi.kClampType}}],[{key:"isAngle",value:function(t){return t===Ii.kDegrees||t===Ii.kRadians||t===Ii.kGradians||t===Ii.kTurns}},{key:"isLength",value:function(t){return t>=Ii.kEms&&t1&&void 0!==arguments[1]?arguments[1]:Ii.kNumber;return s(this,e),n=v(this,e),r="string"==typeof i?Vi(i):i,n.unit=r,n.value=t,n}return y(e,t),u(e,[{key:"clone",value:function(){return new e(this.value,this.unit)}},{key:"equals",value:function(t){var e=t;return this.value===e.value&&this.unit===e.unit}},{key:"getType",value:function(){return Gi.kUnitType}},{key:"convertTo",value:function(t){if(this.unit===t)return new e(this.value,this.unit);var n=Ki(this.unit);if(n!==Ki(t)||n===Ii.kUnknown)return null;var r=Wi(this.unit)/Wi(t);return new e(this.value*r,t)}},{key:"buildCSSText",value:function(t,e,n){var r;switch(this.unit){case Ii.kUnknown:break;case Ii.kInteger:r=Number(this.value).toFixed(0);break;case Ii.kNumber:case Ii.kPercentage:case Ii.kEms:case Ii.kRems:case Ii.kPixels:case Ii.kDegrees:case Ii.kRadians:case Ii.kGradians:case Ii.kMilliseconds:case Ii.kSeconds:case Ii.kTurns:var i=this.value,o=Hi(this.unit);if(i<-999999||i>999999){var a=Hi(this.unit);r=!Number.isFinite(i)||Number.isNaN(i)?function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return(Number.isFinite(t)?"NaN":t>0?"infinity":"-infinity")+e}(i,a):i+(a||"")}else r="".concat(i).concat(o)}return n+=r}}])}(Ui),Qi=new Zi(0,"px");new Zi(1,"px");var Ji=new Zi(0,"deg"),to=function(t){function e(t,n,r){var i,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:1,a=arguments.length>4&&void 0!==arguments[4]&&arguments[4];return s(this,e),(i=v(this,e,["rgb"])).r=t,i.g=n,i.b=r,i.alpha=o,i.isNone=a,i}return y(e,t),u(e,[{key:"clone",value:function(){return new e(this.r,this.g,this.b,this.alpha)}},{key:"buildCSSText",value:function(t,e,n){return"".concat(n,"rgba(").concat(this.r,",").concat(this.g,",").concat(this.b,",").concat(this.alpha,")")}}])}($i),eo=new Xi("unset"),no={"":eo,unset:eo,initial:new Xi("initial"),inherit:new Xi("inherit")},ro=new to(0,0,0,0,!0),io=new to(0,0,0,0),oo=_i((function(t,e,n,r){return new to(t,e,n,r)}),(function(t,e,n,r){return"rgba(".concat(t,",").concat(e,",").concat(n,",").concat(r,")")})),ao=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:Ii.kNumber;return new Zi(t,e)};function so(t){var e=t.type,n=t.value;return"hex"===e?"#".concat(n):"literal"===e?n:"rgb"===e?"rgb(".concat(n.join(","),")"):"rgba(".concat(n.join(","),")")}new Zi(50,"%");var lo=function(){var t=/^(linear\-gradient)/i,e=/^(repeating\-linear\-gradient)/i,n=/^(radial\-gradient)/i,r=/^(repeating\-radial\-gradient)/i,i=/^(conic\-gradient)/i,o=/^to (left (top|bottom)|right (top|bottom)|top (left|right)|bottom (left|right)|left|right|top|bottom)/i,a=/^(closest\-side|closest\-corner|farthest\-side|farthest\-corner|contain|cover)/,s=/^(left|center|right|top|bottom)/i,l=/^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))px/,u=/^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))\%/,c=/^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))em/,h=/^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))deg/,d=/^\(/,f=/^\)/,p=/^,/,g=/^\#([0-9a-fA-F]+)/,v=/^([a-zA-Z]+)/,m=/^rgb/i,y=/^rgba/i,b=/^(([0-9]*\.[0-9]+)|([0-9]+\.?))/,x="";function E(t){throw new Error("".concat(x,": ").concat(t))}function w(){var t=R(k);return x.length>0&&E("Invalid input not EOF"),t}function k(){return M("linear-gradient",t,N)||M("repeating-linear-gradient",e,N)||M("radial-gradient",n,O)||M("repeating-radial-gradient",r,O)||M("conic-gradient",i,O)}function M(t,e,n){return S(e,(function(e){var r=n();return r&&(B(p)||E("Missing comma before color stops")),{type:t,orientation:r,colorStops:R(D)}}))}function S(t,e){var n=B(t);if(n){B(d)||E("Missing (");var r=e(n);return B(f)||E("Missing )"),r}}function N(){return j("directional",o,1)||j("angular",h,1)}function O(){var t,e,n=T();return n&&((t=[]).push(n),e=x,B(p)&&((n=T())?t.push(n):x=e)),t}function T(){var t=function(){var t=j("shape",/^(circle)/i,0);t&&(t.style=I()||C());return t}()||function(){var t=j("shape",/^(ellipse)/i,0);t&&(t.style=_()||C());return t}();if(t)t.at=A();else{var e=C();if(e){t=e;var n=A();n&&(t.at=n)}else{var r=P();r&&(t={type:"default-radial",at:r})}}return t}function C(){return j("extent-keyword",a,1)}function A(){if(j("position",/^at/,0)){var t=P();return t||E("Missing positioning value"),t}}function P(){var t={x:_(),y:_()};if(t.x||t.y)return{type:"position",value:t}}function R(t){var e=t(),n=[];if(e)for(n.push(e);B(p);)(e=t())?n.push(e):E("One extra comma");return n}function D(){var t=j("hex",g,1)||S(y,(function(){return{type:"rgba",value:R(L)}}))||S(m,(function(){return{type:"rgb",value:R(L)}}))||j("literal",v,0);return t||E("Expected color definition"),t.length=_(),t}function L(){return B(b)[1]}function _(){return j("%",u,1)||j("position-keyword",s,1)||I()}function I(){return j("px",l,1)||j("em",c,1)}function j(t,e,n){var r=B(e);if(r)return{type:t,value:r[n]}}function B(t){var e=/^[\n\r\t\s]+/.exec(x);e&&F(e[0].length);var n=t.exec(x);return n&&F(n[0].length),n}function F(t){x=x.substring(t)}return function(t){return x=t,w()}}();var uo=/^l\s*\(\s*([\d.]+)\s*\)\s*(.*)/i,co=/^r\s*\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*\)\s*(.*)/i,ho=/^p\s*\(\s*([axyn])\s*\)\s*(.*)/i,fo=/[\d.]+:(#[^\s]+|[^\)]+\))/gi;var po={left:180,top:-90,bottom:90,right:0,"left top":225,"top left":225,"left bottom":135,"bottom left":135,"right top":-45,"top right":-45,"right bottom":45,"bottom right":45},go=_i((function(t){var e;return e="angular"===t.type?Number(t.value):po[t.value]||0,ao(e,"deg")})),vo=_i((function(t){var e=50,n=50,r="%",i="%";if("position"===(null==t?void 0:t.type)){var o=t.value,a=o.x,s=o.y;"position-keyword"===(null==a?void 0:a.type)&&("left"===a.value?e=0:"center"===a.value?e=50:"right"===a.value?e=100:"top"===a.value?n=0:"bottom"===a.value&&(n=100)),"position-keyword"===(null==s?void 0:s.type)&&("left"===s.value?e=0:"center"===s.value?n=50:"right"===s.value?e=100:"top"===s.value?n=0:"bottom"===s.value&&(n=100)),"px"!==(null==a?void 0:a.type)&&"%"!==(null==a?void 0:a.type)&&"em"!==(null==a?void 0:a.type)||(r=null==a?void 0:a.type,e=Number(a.value)),"px"!==(null==s?void 0:s.type)&&"%"!==(null==s?void 0:s.type)&&"em"!==(null==s?void 0:s.type)||(i=null==s?void 0:s.type,n=Number(s.value))}return{cx:ao(e,r),cy:ao(n,i)}})),mo=_i((function(t){if(t.indexOf("linear")>-1||t.indexOf("radial")>-1)return lo(t).map((function(t){var e=t.type,n=t.orientation,r=t.colorStops;!function(t){var e,n,r=t.length;t[r-1].length=null!==(e=t[r-1].length)&&void 0!==e?e:{type:"%",value:"100"},r>1&&(t[0].length=null!==(n=t[0].length)&&void 0!==n?n:{type:"%",value:"0"});for(var i=0,o=Number(t[0].length.value),a=1;a=0)return ao(Number(e),"px");if("deg".search(t)>=0)return ao(Number(e),"deg")}var n=[];e=e.replace(t,(function(t){return n.push(t),"U".concat(t)}));var r="U(".concat(t.source,")");return n.map((function(t){return ao(Number(e.replace(new RegExp("U".concat(t),"g"),"").replace(new RegExp(r,"g"),"*0")),t)}))[0]}var ko=function(t){return wo(new RegExp("px","g"),t)},Mo=_i(ko);_i((function(t){return wo(new RegExp("%","g"),t)}));var So=function(t){return ae(t)||isFinite(Number(t))?ao(Number(t)||0,"px"):wo(new RegExp("px|%|em|rem","g"),t)},No=_i(So),Oo=function(t){return wo(new RegExp("deg|rad|grad|turn","g"),t)},To=_i(Oo);function Co(t,e,n,r){var i=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,o="",a=t.value||0,s=e.value||0,l=Ki(t.unit),u=t.convertTo(l),c=e.convertTo(l);return u&&c?(a=u.value,s=c.value,o=Hi(t.unit)):(Zi.isLength(t.unit)||Zi.isLength(e.unit))&&(a=Ro(t,i,n),s=Ro(e,i,n),o="px"),[a,s,function(t){return t+o}]}function Ao(t){var e=0;return t.unit===Ii.kDegrees?e=t.value:t.unit===Ii.kRadians?e=_r(Number(t.value)):t.unit===Ii.kTurns?e=360*Number(t.value):t.value&&(e=t.value),e}function Po(t,e){var n;return Array.isArray(t)?n=t.map((function(t){return Number(t)})):ne(t)?n=t.split(" ").map((function(t){return Number(t)})):ae(t)&&(n=[t]),2===e?1===n.length?[n[0],n[0]]:[n[0],n[1]]:4===e?1===n.length?[n[0],n[0],n[0],n[0]]:2===n.length?[n[0],n[1],n[0],n[1]]:3===n.length?[n[0],n[1],n[2],n[1]]:[n[0],n[1],n[2],n[3]]:"even"===e&&n.length%2==1?[].concat(d(n),d(n)):n}function Ro(t,e,n){var r=arguments.length>3&&void 0!==arguments[3]&&arguments[3];if(t.unit===Ii.kPixels)return Number(t.value);if(t.unit===Ii.kPercentage&&n){var i=n.nodeName===hr.GROUP?n.getLocalBounds():n.getGeometryBounds();return(r?i.min[e]:0)+t.value/100*i.halfExtents[e]*2}return 0}var Do=["blur","brightness","drop-shadow","contrast","grayscale","sepia","saturate","hue-rotate","invert"];function Lo(t){return t.toString()}var _o=function(t){return"number"==typeof t?ao(t):/^\s*[-+]?(\d*\.)?\d+\s*$/.test(t)?ao(Number(t)):ao(0)},Io=_i(_o);function jo(t,e){return[t,e,Lo]}function Bo(t,e){return function(n,r){return[n,r,function(n){return Lo(oe(n,t,e))}]}}function Fo(t,e){if(t.length===e.length)return[t,e,function(t){return t}]}function zo(t){var e;return 0===t.parsedStyle.d.totalLength&&(t.parsedStyle.d.totalLength=Mn(t.parsedStyle.d.absolutePath,void 0,Be(Be({},e),{bbox:!1,length:!0})).length),t.parsedStyle.d.totalLength}function Go(t,e){return t[0]===e[0]&&t[1]===e[1]}function Vo(t,e){var n=t.prePoint,r=t.currentPoint,i=t.nextPoint,o=Math.pow(r[0]-n[0],2)+Math.pow(r[1]-n[1],2),a=Math.pow(r[0]-i[0],2)+Math.pow(r[1]-i[1],2),s=Math.pow(n[0]-i[0],2)+Math.pow(n[1]-i[1],2),l=Math.acos((o+a-s)/(2*Math.sqrt(o)*Math.sqrt(a)));if(!l||0===Math.sin(l)||se(l,0))return{xExtra:0,yExtra:0};var u=Math.abs(Math.atan2(i[1]-r[1],i[0]-r[0])),c=Math.abs(Math.atan2(i[0]-r[0],i[1]-r[1]));return u=u>Math.PI/2?Math.PI-u:u,c=c>Math.PI/2?Math.PI-c:c,{xExtra:Math.cos(l/2-u)*(e/2*(1/Math.sin(l/2)))-e/2||0,yExtra:Math.cos(c-l/2)*(e/2*(1/Math.sin(l/2)))-e/2||0}}function Wo(t,e){return[e[0]+(e[0]-t[0]),e[1]+(e[1]-t[1])]}_i((function(t){return ne(t)?t.split(" ").map(Io):t.map(Io)}));var Ho=function(t,e){var n=t.x*e.x+t.y*e.y,r=Math.sqrt((Math.pow(t.x,2)+Math.pow(t.y,2))*(Math.pow(e.x,2)+Math.pow(e.y,2)));return(t.x*e.y-t.y*e.x<0?-1:1)*Math.acos(n/r)},Uo=function(t,e,n,r,i,o,a,s){e=Math.abs(e),n=Math.abs(n);var l=Dr(r=ce(r,360));if(t.x===a.x&&t.y===a.y)return{x:t.x,y:t.y,ellipticalArcAngle:0};if(0===e||0===n)return{x:0,y:0,ellipticalArcAngle:0};var u=(t.x-a.x)/2,c=(t.y-a.y)/2,h={x:Math.cos(l)*u+Math.sin(l)*c,y:-Math.sin(l)*u+Math.cos(l)*c},d=Math.pow(h.x,2)/Math.pow(e,2)+Math.pow(h.y,2)/Math.pow(n,2);d>1&&(e*=Math.sqrt(d),n*=Math.sqrt(d));var f=(Math.pow(e,2)*Math.pow(n,2)-Math.pow(e,2)*Math.pow(h.y,2)-Math.pow(n,2)*Math.pow(h.x,2))/(Math.pow(e,2)*Math.pow(h.y,2)+Math.pow(n,2)*Math.pow(h.x,2));f=f<0?0:f;var p=(i!==o?1:-1)*Math.sqrt(f),g=p*(e*h.y/n),v=p*(-n*h.x/e),m={x:Math.cos(l)*g-Math.sin(l)*v+(t.x+a.x)/2,y:Math.sin(l)*g+Math.cos(l)*v+(t.y+a.y)/2},y={x:(h.x-g)/e,y:(h.y-v)/n},b=Ho({x:1,y:0},y),x=Ho(y,{x:(-h.x-g)/e,y:(-h.y-v)/n});!o&&x>0?x-=2*Math.PI:o&&x<0&&(x+=2*Math.PI);var E=b+(x%=2*Math.PI)*s,w=e*Math.cos(E),k=n*Math.sin(E);return{x:Math.cos(l)*w-Math.sin(l)*k+m.x,y:Math.sin(l)*w+Math.cos(l)*k+m.y,ellipticalArcStartAngle:b,ellipticalArcEndAngle:b+x,ellipticalArcAngle:E,ellipticalArcCenter:m,resultantRx:e,resultantRy:n}};function $o(t,e){var n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],r=t.arcParams,i=r.rx,o=void 0===i?0:i,a=r.ry,s=void 0===a?0:a,l=r.xRotation,u=r.arcFlag,c=r.sweepFlag,h=Uo({x:t.prePoint[0],y:t.prePoint[1]},o,s,l,!!u,!!c,{x:t.currentPoint[0],y:t.currentPoint[1]},e),d=Uo({x:t.prePoint[0],y:t.prePoint[1]},o,s,l,!!u,!!c,{x:t.currentPoint[0],y:t.currentPoint[1]},n?e+.005:e-.005),f=d.x-h.x,p=d.y-h.y,g=Math.sqrt(f*f+p*p);return{x:-f/g,y:-p/g}}function Yo(t){return Math.sqrt(t[0]*t[0]+t[1]*t[1])}function qo(t,e){return Yo(t)*Yo(e)?(t[0]*e[0]+t[1]*e[1])/(Yo(t)*Yo(e)):1}function Xo(t,e){return(t[0]*e[1]1&&(n*=Math.sqrt(f),r*=Math.sqrt(f));var p=n*n*(d*d)+r*r*(h*h),g=p?Math.sqrt((n*n*(r*r)-p)/p):1;o===a&&(g*=-1),isNaN(g)&&(g=0);var v=r?g*n*d/r:0,m=n?g*-r*h/n:0,y=(s+u)/2+Math.cos(i)*v-Math.sin(i)*m,b=(l+c)/2+Math.sin(i)*v+Math.cos(i)*m,x=[(h-v)/n,(d-m)/r],E=[(-1*h-v)/n,(-1*d-m)/r],w=Xo([1,0],x),k=Xo(x,E);return qo(x,E)<=-1&&(k=Math.PI),qo(x,E)>=1&&(k=0),0===a&&k>0&&(k-=2*Math.PI),1===a&&k<0&&(k+=2*Math.PI),{cx:y,cy:b,rx:Go(t,[u,c])?0:n,ry:Go(t,[u,c])?0:r,startAngle:w,endAngle:w+k,xRotation:i,arcFlag:o,sweepFlag:a}}var Zo=function(t){if(""===t||Array.isArray(t)&&0===t.length)return{absolutePath:[],hasArc:!1,segments:[],polygons:[],polylines:[],curve:null,totalLength:0,rect:{x:0,y:0,width:0,height:0}};var e;try{e=ln(t)}catch(n){e=ln(""),console.error("[g]: Invalid SVG Path definition: ".concat(t))}!function(t){for(var e=0;e0&&n.push(r),{polygons:e,polylines:n}}(e),i=r.polygons,o=r.polylines,a=function(t){for(var e=[],n=null,r=null,i=null,o=0,a=t.length,s=0;sWr[1][2]&&(o[0]=-o[0]),Wr[0][2]>Wr[2][0]&&(o[1]=-o[1]),Wr[1][0]>Wr[0][1]&&(o[2]=-o[2])}(function(t){return 0===t.length?[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]:t.map(ca).reduce(ha)}(t),e,n,r,i,o),[[e,n,r,o,i]]}var fa=function(){function t(t,e){for(var n=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]],r=0;r<4;r++)for(var i=0;i<4;i++)for(var o=0;o<4;o++)n[r][i]+=e[r][o]*t[o][i];return n}return function(e,n,r,i,o){for(var a=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],s=0;s<4;s++)a[s][3]=o[s];for(var l=0;l<3;l++)for(var u=0;u<3;u++)a[3][l]+=e[u]*a[u][l];var c=i[0],h=i[1],d=i[2],f=i[3],p=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]];p[0][0]=1-2*(h*h+d*d),p[0][1]=2*(c*h-d*f),p[0][2]=2*(c*d+h*f),p[1][0]=2*(c*h+d*f),p[1][1]=1-2*(c*c+d*d),p[1][2]=2*(h*d-c*f),p[2][0]=2*(c*d-h*f),p[2][1]=2*(h*d+c*f),p[2][2]=1-2*(c*c+h*h),a=t(a,p);var g=[[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]];r[2]&&(g[2][1]=r[2],a=t(a,g)),r[1]&&(g[2][1]=0,g[2][0]=r[0],a=t(a,g)),r[0]&&(g[2][0]=0,g[1][0]=r[0],a=t(a,g));for(var v=0;v<3;v++)for(var m=0;m<3;m++)a[v][m]*=n[v];return function(t){return 0===t[0][2]&&0===t[0][3]&&0===t[1][2]&&0===t[1][3]&&0===t[2][0]&&0===t[2][1]&&1===t[2][2]&&0===t[2][3]&&0===t[3][2]&&1===t[3][3]}(a)?[a[0][0],a[0][1],a[1][0],a[1][1],a[3][0],a[3][1]]:a[0].concat(a[1],a[2],a[3])}}();function pa(t){return t.toFixed(6).replace(".000000","")}function ga(t,e){var n,r;return t.decompositionPair!==e&&(t.decompositionPair=e,n=da(t)),e.decompositionPair!==t&&(e.decompositionPair=t,r=da(e)),null===n[0]||null===r[0]?[[!1],[!0],function(n){return n?e[0].d:t[0].d}]:(n[0].push(0),r[0].push(1),[n,r,function(t){var e=function(t,e,n){var r=function(t,e){for(var n=0,r=0;r2&&void 0!==arguments[2]?arguments[2]:{forceUpdateGeometry:!1};Object.assign(t.attributes,e);var r=t.parsedStyle.clipPath,i=t.parsedStyle.offsetPath;!function(t,e){var n=Sa(t);for(var r in e)n.has(r)&&(t.parsedStyle[r]=e[r])}(t,e);var o=!!n.forceUpdateGeometry;if(!o)for(var s in e)if(wa.has(s)){o=!0;break}var l,u,c=Sa(t);c.has("fill")&&e.fill&&(t.parsedStyle.fill=xo(e.fill)),c.has("stroke")&&e.stroke&&(t.parsedStyle.stroke=xo(e.stroke)),c.has("shadowColor")&&e.shadowColor&&(t.parsedStyle.shadowColor=xo(e.shadowColor)),c.has("filter")&&e.filter&&(t.parsedStyle.filter=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";if("none"===(t=t.toLowerCase().trim()))return[];for(var e,n=/\s*([\w-]+)\(([^)]*)\)/g,r=[],i=0;e=n.exec(t);){if(e.index!==i)return[];if(i=e.index+e[0].length,Do.indexOf(e[1])>-1&&r.push({name:e[1],params:e[2].split(" ").map((function(t){return wo(/deg|rad|grad|turn|px|%/g,t)||xo(t)}))}),n.lastIndex===t.length)return r}return[]}(e.filter)),c.has("radius")&&!$t(e.radius)&&(t.parsedStyle.radius=Po(e.radius,4)),c.has("lineDash")&&!$t(e.lineDash)&&(t.parsedStyle.lineDash=Po(e.lineDash,"even")),c.has("points")&&e.points&&(t.parsedStyle.points=(l=e.points,u=ne(l)?l.split(" ").map((function(t){var e=b(t.split(","),2),n=e[0],r=e[1];return[Number(n),Number(r)]})):l,{points:u,totalLength:0,segments:[]})),c.has("d")&&""===e.d&&(t.parsedStyle.d=a({},ti)),c.has("d")&&e.d&&(t.parsedStyle.d=Jo(e.d)),c.has("textTransform")&&e.textTransform&&this.runtime.CSSPropertySyntaxFactory[ei.TEXT_TRANSFORM].calculator(null,null,{value:e.textTransform},t,null),c.has("clipPath")&&!ve(e.clipPath)&&this.runtime.CSSPropertySyntaxFactory[ei.DEFINED_PATH].calculator("clipPath",r,e.clipPath,t,this.runtime),c.has("offsetPath")&&e.offsetPath&&this.runtime.CSSPropertySyntaxFactory[ei.DEFINED_PATH].calculator("offsetPath",i,e.offsetPath,t,this.runtime),c.has("transform")&&e.transform&&(t.parsedStyle.transform=la(e.transform)),c.has("transformOrigin")&&e.transformOrigin&&(t.parsedStyle.transformOrigin=ba(e.transformOrigin)),c.has("markerStart")&&e.markerStart&&(t.parsedStyle.markerStart=this.runtime.CSSPropertySyntaxFactory[ei.MARKER].calculator(null,e.markerStart,e.markerStart,null,null)),c.has("markerEnd")&&e.markerEnd&&(t.parsedStyle.markerEnd=this.runtime.CSSPropertySyntaxFactory[ei.MARKER].calculator(null,e.markerEnd,e.markerEnd,null,null)),c.has("markerMid")&&e.markerMid&&(t.parsedStyle.markerMid=this.runtime.CSSPropertySyntaxFactory[ei.MARKER].calculator("",e.markerMid,e.markerMid,null,null)),c.has("zIndex")&&!$t(e.zIndex)&&this.runtime.CSSPropertySyntaxFactory[ei.Z_INDEX].postProcessor(t),c.has("offsetDistance")&&!$t(e.offsetDistance)&&this.runtime.CSSPropertySyntaxFactory[ei.OFFSET_DISTANCE].postProcessor(t),c.has("transform")&&e.transform&&this.runtime.CSSPropertySyntaxFactory[ei.TRANSFORM].postProcessor(t),c.has("transformOrigin")&&e.transformOrigin&&this.runtime.CSSPropertySyntaxFactory[ei.TRANSFORM_ORIGIN].postProcessor(t),o&&(t.geometry.dirty=!0,t.renderable.boundsDirty=!0,t.renderable.renderBoundsDirty=!0,n.forceUpdateGeometry||this.runtime.sceneGraphService.dirtifyToRoot(t))}},{key:"updateGeometry",value:function(t){var e=t.nodeName,n=this.runtime.geometryUpdaterFactory[e];if(n){var r=t.geometry;r.contentBounds||(r.contentBounds=new Er),r.renderBounds||(r.renderBounds=new Er);var i=t.parsedStyle,o=n.update(i,t),a=o.cx,s=void 0===a?0:a,l=o.cy,u=void 0===l?0:l,c=o.cz,h=void 0===c?0:c,d=o.hwidth,f=void 0===d?0:d,p=o.hheight,g=void 0===p?0:p,v=o.hdepth,m=void 0===v?0:v,y=[Math.abs(f),Math.abs(g),m],b=i.stroke,x=i.lineWidth,E=void 0===x?1:x,w=i.increasedLineWidthForHitTesting,k=void 0===w?0:w,M=i.shadowType,S=void 0===M?"outer":M,N=i.shadowColor,O=i.filter,T=void 0===O?[]:O,C=i.transformOrigin,A=[s,u,h];r.contentBounds.update(A,y);var P=e===hr.POLYLINE||e===hr.POLYGON||e===hr.PATH?Math.SQRT2:.5;if(b&&!b.isNone){var R=((E||0)+(k||0))*P;y[0]+=R,y[1]+=R}if(r.renderBounds.update(A,y),N&&S&&"inner"!==S){var D=r.renderBounds,L=D.min,_=D.max,I=i.shadowBlur||0,j=i.shadowOffsetX||0,B=i.shadowOffsetY||0,F=L[0]-I+j,z=_[0]+I+j,G=L[1]-I+B,V=_[1]+I+B;L[0]=Math.min(L[0],F),_[0]=Math.max(_[0],z),L[1]=Math.min(L[1],G),_[1]=Math.max(_[1],V),r.renderBounds.setMinMax(L,_)}T.forEach((function(t){var e=t.name,n=t.params;if("blur"===e){var i=n[0].value;r.renderBounds.update(r.renderBounds.center,mt(r.renderBounds.halfExtents,r.renderBounds.halfExtents,[i,i,0]))}else if("drop-shadow"===e){var o=n[0].value,a=n[1].value,s=n[2].value,l=r.renderBounds,u=l.min,c=l.max,h=u[0]-s+o,d=c[0]+s+o,f=u[1]-s+a,p=c[1]+s+a;u[0]=Math.min(u[0],h),c[0]=Math.max(c[0],d),u[1]=Math.min(u[1],f),c[1]=Math.max(c[1],p),r.renderBounds.setMinMax(u,c)}})),t.geometry.dirty=!1;var W=g<0,H=(f<0?-1:1)*(C?Ro(C[0],0,t,!0):0),U=(W?-1:1)*(C?Ro(C[1],1,t,!0):0);(H||U)&&t.setOrigin(H,U)}}},{key:"updateSizeAttenuation",value:function(t,e){t.style.isSizeAttenuation?(t.style.rawLineWidth||(t.style.rawLineWidth=t.style.lineWidth),t.style.lineWidth=(t.style.rawLineWidth||1)/e,t.nodeName===hr.CIRCLE&&(t.style.rawR||(t.style.rawR=t.style.r),t.style.r=(t.style.rawR||1)/e)):(t.style.rawLineWidth&&(t.style.lineWidth=t.style.rawLineWidth,delete t.style.rawLineWidth),t.nodeName===hr.CIRCLE&&t.style.rawR&&(t.style.r=t.style.rawR,delete t.style.rawR))}}])}();function Sa(t){return t.constructor.PARSED_STYLE_LIST}var Na=function(){return u((function t(){s(this,t),this.mixer=jo}),[{key:"calculator",value:function(t,e,n,r){return Ao(n)}}])}(),Oa=function(){return u((function t(){s(this,t)}),[{key:"calculator",value:function(t,e,n,r,i){return n instanceof Xi&&(n=null),i.sceneGraphService.updateDisplayObjectDependency(t,e,n,r),"clipPath"===t&&r.forEach((function(t){0===t.childNodes.length&&i.sceneGraphService.dirtifyToRoot(t)})),n}}])}(),Ta=function(){return u((function t(){s(this,t),this.parser=xo,this.mixer=Eo}),[{key:"calculator",value:function(t,e,n,r){return n instanceof Xi?"none"===n.value?ro:io:n}}])}(),Ca=function(){return u((function t(){s(this,t)}),[{key:"calculator",value:function(t,e,n){return n instanceof Xi?[]:n}}])}();function Aa(t){var e=t.parsedStyle.fontSize;return $t(e)?null:e}var Pa=function(){return u((function t(){s(this,t),this.mixer=jo}),[{key:"calculator",value:function(t,e,n,r,i){if(ae(n))return n;if(!Zi.isRelativeUnit(n.unit))return n.value;if(n.unit===Ii.kPercentage)return 0;if(n.unit===Ii.kEms){if(r.parentNode){var o=Aa(r.parentNode);if(o)return o*=n.value}return 0}if(n.unit===Ii.kRems){var a;if(null!=r&&null!==(a=r.ownerDocument)&&void 0!==a&&a.documentElement){var s=Aa(r.ownerDocument.documentElement);if(s)return s*=n.value}return 0}}}])}(),Ra=function(){return u((function t(){s(this,t),this.mixer=Fo}),[{key:"calculator",value:function(t,e,n){return n.map((function(t){return t.value}))}}])}(),Da=function(){return u((function t(){s(this,t),this.mixer=Fo}),[{key:"calculator",value:function(t,e,n){return n.map((function(t){return t.value}))}}])}(),La=function(){return u((function t(){s(this,t)}),[{key:"calculator",value:function(t,e,n,r){var i;n instanceof Xi&&(n=null);var o=null===(i=n)||void 0===i?void 0:i.cloneNode(!0);return o&&(o.style.isMarker=!0),o}}])}(),_a=function(){return u((function t(){s(this,t),this.mixer=jo}),[{key:"calculator",value:function(t,e,n){return n.value}}])}(),Ia=function(){return u((function t(){s(this,t),this.mixer=Bo(0,1)}),[{key:"calculator",value:function(t,e,n){return n.value}},{key:"postProcessor",value:function(t){var e=t.parsedStyle,n=e.offsetPath,r=e.offsetDistance;if(n){var i=n.nodeName;if(i===hr.LINE||i===hr.PATH||i===hr.POLYLINE){var o=n.getPoint(r);o&&t.setLocalPosition(o.x,o.y)}}}}])}(),ja=function(){return u((function t(){s(this,t),this.mixer=Bo(0,1)}),[{key:"calculator",value:function(t,e,n){return n.value}}])}(),Ba=function(){return u((function t(){s(this,t),this.parser=Jo,this.mixer=ta}),[{key:"calculator",value:function(t,e,n){return n instanceof Xi&&"unset"===n.value?{absolutePath:[],hasArc:!1,segments:[],polygons:[],polylines:[],curve:null,totalLength:0,rect:new Nr(0,0,0,0)}:n}}])}(),Fa=u((function t(){s(this,t),this.mixer=ea})),za=function(t){function e(){var t;s(this,e);for(var n=arguments.length,r=new Array(n),i=0;i0&&void 0!==arguments[0]?arguments[0]:"auto",e=arguments.length>1?arguments[1]:void 0,n=arguments.length>2?arguments[2]:void 0,r=!1,i=!1,o=!!e&&!e.isNone,a=!!n&&!n.isNone;return"visiblepainted"===t||"painted"===t||"auto"===t?(r=o,i=a):"visiblefill"===t||"fill"===t?r=!0:"visiblestroke"===t||"stroke"===t?i=!0:"visible"!==t&&"all"!==t||(r=!0,i=!0),[r,i]}var Ja=1,ts="object"==typeof self&&self.self===self?self:"object"==typeof global&&global.global===global?global:{},es=Date.now(),ns={},rs=Date.now(),is=function(t){if("function"!=typeof t)throw new TypeError("".concat(t," is not a function"));var e=Date.now(),n=e-rs,r=n>16?0:16-n,i=Ja++;return ns[i]=t,Object.keys(ns).length>1||setTimeout((function(){rs=e;var t=ns;ns={},Object.keys(t).forEach((function(e){return t[e](ts.performance&&"function"==typeof ts.performance.now?ts.performance.now():Date.now()-es)}))}),r),i},os=function(t){delete ns[t]},as=function(t){return"string"!=typeof t?is:""===t?ts.requestAnimationFrame:ts["".concat(t,"RequestAnimationFrame")]},ss=function(t,e){for(var n=0;void 0!==t[n];){if(e(t[n]))return t[n];n+=1}}(["","webkit","moz","ms","o"],(function(t){return!!as(t)})),ls=as(ss),us=function(t){return"string"!=typeof t?os:""===t?ts.cancelAnimationFrame:ts["".concat(t,"CancelAnimationFrame")]||ts["".concat(t,"CancelRequestAnimationFrame")]}(ss);ts.requestAnimationFrame=ls,ts.cancelAnimationFrame=us;var cs=function(){return u((function t(){s(this,t),this.callbacks=[]}),[{key:"getCallbacksNum",value:function(){return this.callbacks.length}},{key:"tapPromise",value:function(t,e){this.callbacks.push(e)}},{key:"promise",value:function(){for(var t=arguments.length,e=new Array(t),n=0;n1&&void 0!==arguments[1]&&arguments[1],r=Gs.get(this);r||(r=this.document?this:this.defaultView?this.defaultView:null===(e=this.ownerDocument)||void 0===e?void 0:e.defaultView)&&Gs.set(this,r);if(r){if(t.manager=r.getEventService(),!t.manager)return!1;t.defaultPrevented=!1,t.path?t.path.length=0:t.page=[],n||(t.target=this),t.manager.dispatchEvent(t,t.type,n)}else this.emitter.emit(t.type,t);return!t.defaultPrevented}}])}(),Ws=function(t){function e(){var t;s(this,e);for(var n=arguments.length,r=new Array(n),i=0;i0&&void 0!==arguments[0]?arguments[0]:{};return this.parentNode?this.parentNode.getRootNode(t):t.composed&&this.host?this.host.getRootNode(t):this}},{key:"hasChildNodes",value:function(){return this.childNodes.length>0}},{key:"isDefaultNamespace",value:function(t){throw new Error(Or)}},{key:"lookupNamespaceURI",value:function(t){throw new Error(Or)}},{key:"lookupPrefix",value:function(t){throw new Error(Or)}},{key:"normalize",value:function(){throw new Error(Or)}},{key:"isEqualNode",value:function(t){return this===t}},{key:"isSameNode",value:function(t){return this.isEqualNode(t)}},{key:"parent",get:function(){return this.parentNode}},{key:"parentElement",get:function(){return null}},{key:"nextSibling",get:function(){return null}},{key:"previousSibling",get:function(){return null}},{key:"firstChild",get:function(){return this.childNodes.length>0?this.childNodes[0]:null}},{key:"lastChild",get:function(){return this.childNodes.length>0?this.childNodes[this.childNodes.length-1]:null}},{key:"compareDocumentPosition",value:function(t){if(t===this)return 0;for(var n=t,r=this,i=[n],o=[r];null!==(a=n.parentNode)&&void 0!==a?a:r.parentNode;){var a;n=n.parentNode?(i.push(n.parentNode),n.parentNode):n,r=r.parentNode?(o.push(r.parentNode),r.parentNode):r}if(n!==r)return e.DOCUMENT_POSITION_DISCONNECTED|e.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC|e.DOCUMENT_POSITION_PRECEDING;var s=i.length>o.length?i:o,l=s===i?o:i;if(s[s.length-l.length]===l[0])return s===i?e.DOCUMENT_POSITION_CONTAINED_BY|e.DOCUMENT_POSITION_FOLLOWING:e.DOCUMENT_POSITION_CONTAINS|e.DOCUMENT_POSITION_PRECEDING;for(var u=s.length-l.length,c=l.length-1;c>=0;c--){var h=l[c],d=s[u+c];if(d!==h){var f=h.parentNode.childNodes;return f.indexOf(h)0&&e;)e=e.parentNode,t--;return e}},{key:"forEach",value:function(t){for(var e=[this];e.length>0;){var n=e.pop();if(!1===t(n))break;for(var r=n.childNodes.length-1;r>=0;r--)e.push(n.childNodes[r])}}}],[{key:"isNode",value:function(t){return!!t.childNodes}}])}(Vs);Ws.DOCUMENT_POSITION_DISCONNECTED=1,Ws.DOCUMENT_POSITION_PRECEDING=2,Ws.DOCUMENT_POSITION_FOLLOWING=4,Ws.DOCUMENT_POSITION_CONTAINS=8,Ws.DOCUMENT_POSITION_CONTAINED_BY=16,Ws.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC=32;var Hs=function(){return u((function t(e,n){var r=this;s(this,t),this.nativeHTMLMap=new WeakMap,this.cursor="default",this.mappingTable={},this.mappingState={trackingData:{}},this.eventPool=new Map,this.tmpMatrix=T(),this.tmpVec3=ht(),this.onPointerDown=function(t){var e=r.createPointerEvent(t);if(r.dispatchEvent(e,"pointerdown"),"touch"===e.pointerType)r.dispatchEvent(e,"touchstart");else if("mouse"===e.pointerType||"pen"===e.pointerType){var n=2===e.button;r.dispatchEvent(e,n?"rightdown":"mousedown")}r.trackingData(t.pointerId).pressTargetsByButton[t.button]=e.composedPath(),r.freeEvent(e)},this.onPointerUp=function(t){var e=Ka.now(),n=r.createPointerEvent(t,void 0,void 0,r.context.config.alwaysTriggerPointerEventOnCanvas?r.rootTarget:void 0);if(r.dispatchEvent(n,"pointerup"),"touch"===n.pointerType)r.dispatchEvent(n,"touchend");else if("mouse"===n.pointerType||"pen"===n.pointerType){var i=2===n.button;r.dispatchEvent(n,i?"rightup":"mouseup")}var o=r.trackingData(t.pointerId),a=r.findMountedTarget(o.pressTargetsByButton[t.button]),s=a;if(a&&!n.composedPath().includes(a)){for(var l=a;l&&!n.composedPath().includes(l);){if(n.currentTarget=l,r.notifyTarget(n,"pointerupoutside"),"touch"===n.pointerType)r.notifyTarget(n,"touchendoutside");else if("mouse"===n.pointerType||"pen"===n.pointerType){var u=2===n.button;r.notifyTarget(n,u?"rightupoutside":"mouseupoutside")}Ws.isNode(l)&&(l=l.parentNode)}delete o.pressTargetsByButton[t.button],s=l}if(s){var c,h=r.clonePointerEvent(n,"click");h.target=s,h.path=[],o.clicksByButton[t.button]||(o.clicksByButton[t.button]={clickCount:0,target:h.target,timeStamp:e});var d=r.context.renderingContext.root.ownerDocument.defaultView,f=o.clicksByButton[t.button];f.target===h.target&&e-f.timeStamp=1;r--)if(t.currentTarget=n[r],this.notifyTarget(t,e),t.propagationStopped||t.propagationImmediatelyStopped)return;if(t.eventPhase=t.AT_TARGET,t.currentTarget=t.target,this.notifyTarget(t,e),!t.propagationStopped&&!t.propagationImmediatelyStopped){var i=n.indexOf(t.currentTarget);t.eventPhase=t.BUBBLING_PHASE;for(var o=i+1;oi||n>o?null:!a&&this.pickHandler(t)||this.rootTarget||null}},{key:"isNativeEventFromCanvas",value:function(t,e){var n,r=null==e?void 0:e.target;if(null!==(n=r)&&void 0!==n&&n.shadowRoot&&(r=e.composedPath()[0]),r){if(r===t)return!0;if(t&&t.contains)return t.contains(r)}return!(null==e||!e.composedPath)&&e.composedPath().indexOf(t)>-1}},{key:"getExistedHTML",value:function(t){if(t.nativeEvent.composedPath)for(var e=0,n=t.nativeEvent.composedPath();e=0;n--){var r=t[n];if(!(r===this.rootTarget||Ws.isNode(r)&&r.parentNode===e))break;e=t[n]}return e}},{key:"getCursor",value:function(t){for(var e=t;e;){var n=Ua(e)&&e.getAttribute("cursor");if(n)return n;e=Ws.isNode(e)&&e.parentNode}}}])}(),Us=function(){return u((function t(){s(this,t)}),[{key:"getOrCreateCanvas",value:function(t,e){if(this.canvas)return this.canvas;if(t||Ol.offscreenCanvas)this.canvas=t||Ol.offscreenCanvas,this.context=this.canvas.getContext("2d",a({willReadFrequently:!0},e));else try{this.canvas=new window.OffscreenCanvas(0,0),this.context=this.canvas.getContext("2d",a({willReadFrequently:!0},e)),this.context&&this.context.measureText||(this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d"))}catch(t){this.canvas=document.createElement("canvas"),this.context=this.canvas.getContext("2d",a({willReadFrequently:!0},e))}return this.canvas.width=10,this.canvas.height=10,this.canvas}},{key:"getOrCreateContext",value:function(t,e){return this.context||this.getOrCreateCanvas(t,e),this.context}}],[{key:"createCanvas",value:function(){try{return new window.OffscreenCanvas(0,0)}catch(t){}try{return document.createElement("canvas")}catch(t){}return null}}])}(),$s=function(t){return t[t.CAMERA_CHANGED=0]="CAMERA_CHANGED",t[t.DISPLAY_OBJECT_CHANGED=1]="DISPLAY_OBJECT_CHANGED",t[t.NONE=2]="NONE",t}({}),Ys=function(){return u((function t(e,n){s(this,t),this.inited=!1,this.stats={total:0,rendered:0},this.zIndexCounter=0,this.hooks={init:new ds,initAsync:new cs,dirtycheck:new fs,cull:new fs,beginFrame:new ds,beforeRender:new ds,render:new ds,afterRender:new ds,endFrame:new ds,destroy:new ds,pick:new hs,pickSync:new fs,pointerDown:new ds,pointerUp:new ds,pointerMove:new ds,pointerOut:new ds,pointerOver:new ds,pointerWheel:new ds,pointerCancel:new ds,click:new ds},this.globalRuntime=e,this.context=n}),[{key:"init",value:function(t){var e=this,n=a(a({},this.globalRuntime),this.context);this.context.renderingPlugins.forEach((function(t){t.apply(n,e.globalRuntime)})),this.hooks.init.call(),0===this.hooks.initAsync.getCallbacksNum()?(this.inited=!0,t()):this.hooks.initAsync.promise().then((function(){e.inited=!0,t()})).catch((function(t){}))}},{key:"getStats",value:function(){return this.stats}},{key:"disableDirtyRectangleRendering",value:function(){return!this.context.config.renderer.getConfig().enableDirtyRectangleRendering||this.context.renderingContext.renderReasons.has($s.CAMERA_CHANGED)}},{key:"render",value:function(t,e,n){var r=this;this.stats.total=0,this.stats.rendered=0,this.zIndexCounter=0;var i=this.context.renderingContext;if(this.globalRuntime.sceneGraphService.syncHierarchy(i.root),this.globalRuntime.sceneGraphService.triggerPendingEvents(),i.renderReasons.size&&this.inited){i.dirtyRectangleRenderingDisabled=this.disableDirtyRectangleRendering();var o=1===i.renderReasons.size&&i.renderReasons.has($s.CAMERA_CHANGED),a=!t.disableRenderHooks||!(t.disableRenderHooks&&o);a&&this.renderDisplayObject(i.root,t,i),this.hooks.beginFrame.call(e),a&&i.renderListCurrentFrame.forEach((function(t){r.hooks.beforeRender.call(t),r.hooks.render.call(t),r.hooks.afterRender.call(t)})),this.hooks.endFrame.call(e),i.renderListCurrentFrame=[],i.renderReasons.clear(),n()}}},{key:"renderDisplayObject",value:function(t,e,n){var r=this,i=e.renderer.getConfig(),o=i.enableDirtyCheck,a=i.enableCulling;function s(t){var e=t.renderable,i=t.sortable,s=o?e.dirty||n.dirtyRectangleRenderingDisabled?t:null:t;if(s){var l=a?r.hooks.cull.call(s,r.context.camera):s;l&&(r.stats.rendered+=1,n.renderListCurrentFrame.push(l))}e.dirty=!1,i.renderOrder=r.zIndexCounter,r.zIndexCounter+=1,r.stats.total+=1,i.dirty&&(r.sort(t,i),i.dirty=!1,i.dirtyChildren=[],i.dirtyReason=void 0)}for(var l=[t];l.length>0;){var u,c=l.pop();s(c);for(var h=(null===(u=c.sortable)||void 0===u||null===(u=u.sorted)||void 0===u?void 0:u.length)>0?c.sortable.sorted:c.childNodes,d=h.length-1;d>=0;d--)l.push(h[d])}}},{key:"sort",value:function(t,e){var n,r;(null==e||null===(n=e.sorted)||void 0===n?void 0:n.length)>0&&e.dirtyReason!==Jr.Z_INDEX_CHANGED?e.dirtyChildren.forEach((function(n){var r=e.sorted.indexOf(n);if(r>-1&&e.sorted.splice(r,1),t.childNodes.indexOf(n)>-1)if(0===e.sorted.length)e.sorted.push(n);else{var i=function(t,e){for(var n=0,r=t.length;n>>1;$a(t[i],e)<0?n=i+1:r=i}return n}(e.sorted,n);e.sorted.splice(i,0,n)}})):e.sorted=t.childNodes.slice().sort($a),(null===(r=e.sorted)||void 0===r?void 0:r.length)>0&&0===t.childNodes.filter((function(t){return t.parsedStyle.zIndex})).length&&(e.sorted=[])}},{key:"destroy",value:function(){this.inited=!1,this.hooks.destroy.call(),this.globalRuntime.sceneGraphService.clearPendingEvents()}},{key:"dirtify",value:function(){this.context.renderingContext.renderReasons.add($s.DISPLAY_OBJECT_CHANGED)}}])}(),qs=/\[\s*(.*)=(.*)\s*\]/,Xs=function(){return u((function t(){s(this,t)}),[{key:"selectOne",value:function(t,e){var n=this;if(t.startsWith("."))return e.find((function(e){return((null==e?void 0:e.classList)||[]).indexOf(n.getIdOrClassname(t))>-1}));if(t.startsWith("#"))return e.find((function(e){return e.id===n.getIdOrClassname(t)}));if(t.startsWith("[")){var r=this.getAttribute(t),i=r.name,o=r.value;return i?e.find((function(t){return e!==t&&("name"===i?t.name===o:n.attributeToString(t,i)===o)})):null}return e.find((function(n){return e!==n&&n.nodeName===t}))}},{key:"selectAll",value:function(t,e){var n=this;if(t.startsWith("."))return e.findAll((function(r){return e!==r&&((null==r?void 0:r.classList)||[]).indexOf(n.getIdOrClassname(t))>-1}));if(t.startsWith("#"))return e.findAll((function(r){return e!==r&&r.id===n.getIdOrClassname(t)}));if(t.startsWith("[")){var r=this.getAttribute(t),i=r.name,o=r.value;return i?e.findAll((function(t){return e!==t&&("name"===i?t.name===o:n.attributeToString(t,i)===o)})):[]}return e.findAll((function(n){return e!==n&&n.nodeName===t}))}},{key:"is",value:function(t,e){if(t.startsWith("."))return e.className===this.getIdOrClassname(t);if(t.startsWith("#"))return e.id===this.getIdOrClassname(t);if(t.startsWith("[")){var n=this.getAttribute(t),r=n.name,i=n.value;return"name"===r?e.name===i:this.attributeToString(e,r)===i}return e.nodeName===t}},{key:"getIdOrClassname",value:function(t){return t.substring(1)}},{key:"getAttribute",value:function(t){var e=t.match(qs),n="",r="";return e&&e.length>2&&(n=e[1].replace(/"/g,""),r=e[2].replace(/"/g,"")),{name:n,value:r}}},{key:"attributeToString",value:function(t,e){if(!t.getAttribute)return"";var n=t.getAttribute(e);return $t(n)?"":n.toString?n.toString():""}}])}(),Ks=function(t){return t.ATTR_MODIFIED="DOMAttrModified",t.INSERTED="DOMNodeInserted",t.MOUNTED="DOMNodeInsertedIntoDocument",t.REMOVED="removed",t.UNMOUNTED="DOMNodeRemovedFromDocument",t.REPARENT="reparent",t.DESTROY="destroy",t.BOUNDS_CHANGED="bounds-changed",t.CULLED="culled",t}({}),Zs=function(t){function e(t,n,r,i,o,a,l,u){var c;return s(this,e),(c=v(this,e,[null])).relatedNode=n,c.prevValue=r,c.newValue=i,c.attrName=o,c.attrChange=a,c.prevParsedValue=l,c.newParsedValue=u,c.type=t,c}return y(e,t),u(e)}(Is);function Qs(t){var e=t.renderable;e&&(e.renderBoundsDirty=!0,e.boundsDirty=!0)}Zs.ADDITION=2,Zs.MODIFICATION=1,Zs.REMOVAL=3;var Js,tl,el,nl=new Zs(Ks.REPARENT,null,"","","",0,"",""),rl=Vt(),il=ht(),ol=pt(1,1,1),al=T(),sl=Vt(),ll=ht(),ul=T(),cl=Rt(),hl=ht(),dl=Rt(),fl=ht(),pl=ht(),gl=ht(),vl=T(),ml=Rt(),yl=Rt(),bl=Rt(),xl={affectChildren:!0},El=function(){return u((function t(e){s(this,t),this.pendingEvents=new Map,this.boundsChangedEvent=new zs(Ks.BOUNDS_CHANGED),this.displayObjectDependencyMap=new WeakMap,this.runtime=e}),[{key:"matches",value:function(t,e){return this.runtime.sceneGraphSelector.is(t,e)}},{key:"querySelector",value:function(t,e){return this.runtime.sceneGraphSelector.selectOne(t,e)}},{key:"querySelectorAll",value:function(t,e){return this.runtime.sceneGraphSelector.selectAll(t,e)}},{key:"attach",value:function(t,e,n){var r,i=!1;t.parentNode&&(i=t.parentNode!==e,this.detach(t));var o=t.nodeName===hr.FRAGMENT,a=Za(e);t.parentNode=e;var s=o?t.childNodes:[t];ae(n)?s.forEach((function(t){e.childNodes.splice(n,0,t),t.parentNode=e})):s.forEach((function(t){e.childNodes.push(t),t.parentNode=e}));var l=e.sortable;if((null!=l&&null!==(r=l.sorted)&&void 0!==r&&r.length||l.dirty||t.parsedStyle.zIndex)&&(-1===l.dirtyChildren.indexOf(t)&&l.dirtyChildren.push(t),l.dirty=!0,l.dirtyReason=Jr.ADDED),!a){if(o)this.dirtifyFragment(t);else{var u=t.transformable;u&&this.dirtifyWorld(t,u)}i&&t.dispatchEvent(nl)}}},{key:"detach",value:function(t){var e,n;if(t.parentNode){var r=t.transformable,i=t.parentNode.sortable;(null!=i&&null!==(e=i.sorted)&&void 0!==e&&e.length||null!==(n=t.style)&&void 0!==n&&n.zIndex)&&(-1===i.dirtyChildren.indexOf(t)&&i.dirtyChildren.push(t),i.dirty=!0,i.dirtyReason=Jr.REMOVED);var o=t.parentNode.childNodes.indexOf(t);o>-1&&t.parentNode.childNodes.splice(o,1),r&&this.dirtifyWorld(t,r),t.parentNode=null}}},{key:"getOrigin",value:function(t){return t.getGeometryBounds(),t.transformable.origin}},{key:"setOrigin",value:function(t,e){"number"==typeof e&&(e=[e,arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,arguments.length>3&&void 0!==arguments[3]?arguments[3]:0]);var n=t.transformable;if(e[0]!==n.origin[0]||e[1]!==n.origin[1]||e[2]!==n.origin[2]){var r=n.origin;r[0]=e[0],r[1]=e[1],r[2]=e[2]||0,this.dirtifyLocal(t,n)}}},{key:"rotate",value:function(t,e){"number"==typeof e&&(e=pt(e,arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,arguments.length>3&&void 0!==arguments[3]?arguments[3]:0));var n=t.transformable;if(null!==t.parentNode&&t.parentNode.transformable){var r=cl;It(r,e[0],e[1],e[2]);var i=this.getRotation(t),o=this.getRotation(t.parentNode);Bt(bl,o),_t(bl,bl),Lt(r,bl,r),Lt(n.localRotation,r,i),Gt(n.localRotation,n.localRotation),this.dirtifyLocal(t,n)}else this.rotateLocal(t,e)}},{key:"rotateLocal",value:function(t,e){"number"==typeof e&&(e=pt(e,arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,arguments.length>3&&void 0!==arguments[3]?arguments[3]:0));var n=t.transformable;It(yl,e[0],e[1],e[2]),zt(n.localRotation,n.localRotation,yl),this.dirtifyLocal(t,n)}},{key:"setEulerAngles",value:function(t,e){"number"==typeof e&&(e=pt(e,arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,arguments.length>3&&void 0!==arguments[3]?arguments[3]:0));var n=t.transformable;if(null!==t.parentNode&&t.parentNode.transformable){It(n.localRotation,e[0],e[1],e[2]);var r=this.getRotation(t.parentNode);Bt(ml,_t(cl,r)),zt(n.localRotation,n.localRotation,ml),this.dirtifyLocal(t,n)}else this.setLocalEulerAngles(t,e)}},{key:"setLocalEulerAngles",value:function(t,e){var n=!(arguments.length>4&&void 0!==arguments[4])||arguments[4];"number"==typeof e&&(e=pt(e,arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,arguments.length>3&&void 0!==arguments[3]?arguments[3]:0));var r=t.transformable;It(r.localRotation,e[0],e[1],e[2]),n&&this.dirtifyLocal(t,r)}},{key:"translateLocal",value:function(t,e){"number"==typeof e&&(e=pt(e,arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,arguments.length>3&&void 0!==arguments[3]?arguments[3]:0));var n=t.transformable;St(e,il)||(!function(t,e,n){var r=n[0],i=n[1],o=n[2],a=n[3],s=e[0],l=e[1],u=e[2],c=i*u-o*l,h=o*s-r*u,d=r*l-i*s,f=i*d-o*h,p=o*c-r*d,g=r*h-i*c,v=2*a;c*=v,h*=v,d*=v,f*=2,p*=2,g*=2,t[0]=s+c+f,t[1]=l+h+p,t[2]=u+d+g}(e,e,n.localRotation),mt(n.localPosition,n.localPosition,e),this.dirtifyLocal(t,n))}},{key:"setPosition",value:function(t,e){var n,r=t.transformable;if(gl[0]=e[0],gl[1]=e[1],gl[2]=null!==(n=e[2])&&void 0!==n?n:0,!St(this.getPosition(t),gl)){if(gt(r.position,gl),null!==t.parentNode&&t.parentNode.transformable){var i=t.parentNode.transformable;A(vl,i.worldTransform),_(vl,vl),Mt(r.localPosition,gl,vl)}else gt(r.localPosition,gl);this.dirtifyLocal(t,r)}}},{key:"setLocalPosition",value:function(t,e){var n,r=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],i=t.transformable;pl[0]=e[0],pl[1]=e[1],pl[2]=null!==(n=e[2])&&void 0!==n?n:0,St(i.localPosition,pl)||(gt(i.localPosition,pl),r&&this.dirtifyLocal(t,i))}},{key:"scaleLocal",value:function(t,e){var n,r=t.transformable;!function(t,e,n){t[0]=e[0]*n[0],t[1]=e[1]*n[1],t[2]=e[2]*n[2]}(r.localScale,r.localScale,vt(ll,e[0],e[1],null!==(n=e[2])&&void 0!==n?n:1)),this.dirtifyLocal(t,r)}},{key:"setLocalScale",value:function(t,e){var n,r=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],i=t.transformable;vt(ll,e[0],e[1],null!==(n=e[2])&&void 0!==n?n:i.localScale[2]),St(ll,i.localScale)||(gt(i.localScale,ll),r&&this.dirtifyLocal(t,i))}},{key:"translate",value:function(t,e){"number"==typeof e&&(e=vt(ll,e,arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,arguments.length>3&&void 0!==arguments[3]?arguments[3]:0)),St(e,il)||(mt(ll,this.getPosition(t),e),this.setPosition(t,ll))}},{key:"setRotation",value:function(t,e,n,r,i){var o=t.transformable;if("number"==typeof e&&(e=jt(e,n,r,i)),null!==t.parentNode&&t.parentNode.transformable){var a=this.getRotation(t.parentNode);Bt(cl,a),_t(cl,cl),Lt(o.localRotation,cl,e),Gt(o.localRotation,o.localRotation),this.dirtifyLocal(t,o)}else this.setLocalRotation(t,e)}},{key:"setLocalRotation",value:function(t,e,n,r,i){var o=!(arguments.length>5&&void 0!==arguments[5])||arguments[5];"number"==typeof e&&(e=Ft(cl,e,n,r,i));var a=t.transformable;Bt(a.localRotation,e),o&&this.dirtifyLocal(t,a)}},{key:"setLocalSkew",value:function(t,e,n){var r=!(arguments.length>3&&void 0!==arguments[3])||arguments[3];"number"==typeof e&&(e=function(t,e,n){return t[0]=e,t[1]=n,t}(sl,e,n));var i=t.transformable;!function(t,e){t[0]=e[0],t[1]=e[1]}(i.localSkew,e),r&&this.dirtifyLocal(t,i)}},{key:"dirtifyLocal",value:function(t,e){Za(t)||e.localDirtyFlag||(e.localDirtyFlag=!0,e.dirtyFlag||this.dirtifyWorld(t,e))}},{key:"dirtifyWorld",value:function(t,e){e.dirtyFlag||this.unfreezeParentToRoot(t),this.dirtifyWorldInternal(t,e),this.dirtifyToRoot(t,!0)}},{key:"dirtifyFragment",value:function(t){var e=t.transformable;e&&(e.frozen=!1,e.dirtyFlag=!0,e.localDirtyFlag=!0);var n=t.renderable;n&&(n.renderBoundsDirty=!0,n.boundsDirty=!0,n.dirty=!0);for(var r=t.childNodes.length,i=0;i1&&void 0!==arguments[1]&&arguments[1],n=t;for(n.renderable&&(n.renderable.dirty=!0);n;)Qs(n),n=n.parentNode;e&&t.forEach((function(t){Qs(t)})),this.informDependentDisplayObjects(t),this.pendingEvents.set(t,e)}},{key:"updateDisplayObjectDependency",value:function(t,e,n,r){if(e&&e!==n){var i=this.displayObjectDependencyMap.get(e);if(i&&i[t]){var o=i[t].indexOf(r);i[t].splice(o,1)}}if(n){var a=this.displayObjectDependencyMap.get(n);a||(this.displayObjectDependencyMap.set(n,{}),a=this.displayObjectDependencyMap.get(n)),a[t]||(a[t]=[]),a[t].push(r)}}},{key:"informDependentDisplayObjects",value:function(t){var e=this,n=this.displayObjectDependencyMap.get(t);n&&Object.keys(n).forEach((function(t){n[t].forEach((function(n){e.dirtifyToRoot(n,!0),n.dispatchEvent(new Zs(Ks.ATTR_MODIFIED,n,e,e,t,Zs.MODIFICATION,e,e)),n.isCustomElement&&n.isConnected&&n.attributeChangedCallback&&n.attributeChangedCallback(t,e,e)}))}))}},{key:"getPosition",value:function(t){var e=t.transformable;return X(e.position,this.getWorldTransform(t,e))}},{key:"getRotation",value:function(t){var e=t.transformable;return Z(e.rotation,this.getWorldTransform(t,e))}},{key:"getScale",value:function(t){var e=t.transformable;return K(e.scaling,this.getWorldTransform(t,e))}},{key:"getWorldTransform",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:t.transformable;return e.localDirtyFlag||e.dirtyFlag?(t.parentNode&&t.parentNode.transformable&&this.getWorldTransform(t.parentNode),this.sync(t,e),e.worldTransform):e.worldTransform}},{key:"getLocalPosition",value:function(t){return t.transformable.localPosition}},{key:"getLocalRotation",value:function(t){return t.transformable.localRotation}},{key:"getLocalScale",value:function(t){return t.transformable.localScale}},{key:"getLocalSkew",value:function(t){return t.transformable.localSkew}},{key:"calcLocalTransform",value:function(t){if(0!==t.localSkew[0]||0!==t.localSkew[1]){Q(t.localTransform,t.localRotation,t.localPosition,pt(1,1,1),t.origin),0===t.localSkew[0]&&0===t.localSkew[1]||(D(ul),ul[4]=Math.tan(t.localSkew[0]),ul[1]=Math.tan(t.localSkew[1]),j(t.localTransform,t.localTransform,ul));var e=Q(ul,Ft(cl,0,0,0,1),vt(ll,1,1,1),t.localScale,t.origin);j(t.localTransform,t.localTransform,e)}else{var n=t.localTransform,r=t.localPosition,i=t.localRotation,o=t.localScale,a=t.origin,s=0!==r[0]||0!==r[1]||0!==r[2],l=1!==i[3]||0!==i[0]||0!==i[1]||0!==i[2],u=1!==o[0]||1!==o[1]||1!==o[2],c=0!==a[0]||0!==a[1]||0!==a[2];l||u||c?Q(n,i,r,o,a):s?V(n,r):D(n)}}},{key:"getLocalTransform",value:function(t){var e=t.transformable;return e.localDirtyFlag&&(this.calcLocalTransform(e),e.localDirtyFlag=!1),e.localTransform}},{key:"setLocalTransform",value:function(t,e){var n=X(hl,e),r=Z(dl,e),i=K(fl,e);this.setLocalScale(t,i,!1),this.setLocalPosition(t,n,!1),this.setLocalRotation(t,r,void 0,void 0,void 0,!1),this.dirtifyLocal(t,t.transformable)}},{key:"resetLocalTransform",value:function(t){this.setLocalScale(t,ol,!1),this.setLocalPosition(t,il,!1),this.setLocalEulerAngles(t,il,void 0,void 0,!1),this.setLocalSkew(t,rl,void 0,!1),this.dirtifyLocal(t,t.transformable)}},{key:"getTransformedGeometryBounds",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=arguments.length>2?arguments[2]:void 0,r=this.getGeometryBounds(t,e);if(!Er.isEmpty(r)){var i=n||new Er;return i.setFromTransformedAABB(r,this.getWorldTransform(t)),i}return null}},{key:"getGeometryBounds",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=t.geometry;return n.dirty&&Ol.styleValueRegistry.updateGeometry(t),(e?n.renderBounds:n.contentBounds||null)||new Er}},{key:"getBounds",value:function(t){var e=this,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=t.renderable;if(!r.boundsDirty&&!n&&r.bounds)return r.bounds;if(!r.renderBoundsDirty&&n&&r.renderBounds)return r.renderBounds;var i=n?r.renderBounds:r.bounds,o=this.getTransformedGeometryBounds(t,n,i);if(t.childNodes.forEach((function(t){var r=e.getBounds(t,n);r&&(o?o.add(r):(o=i||new Er).update(r.center,r.halfExtents))})),o||(o=new Er),n){var a=Ya(t);if(a){var s=a.parsedStyle.clipPath.getBounds(n);o?s&&(o=s.intersection(o)):o.update(s.center,s.halfExtents)}}return n?(r.renderBounds=o,r.renderBoundsDirty=!1):(r.bounds=o,r.boundsDirty=!1),o}},{key:"getLocalBounds",value:function(t){if(t.parentNode){var e=al;t.parentNode.transformable&&(e=_(ul,this.getWorldTransform(t.parentNode)));var n=this.getBounds(t);if(!Er.isEmpty(n)){var r=new Er;return r.setFromTransformedAABB(n,e),r}}return this.getBounds(t)}},{key:"getBoundingClientRect",value:function(t){var e,n,r=this.getGeometryBounds(t);Er.isEmpty(r)||(n=new Er).setFromTransformedAABB(r,this.getWorldTransform(t));var i=null===(e=t.ownerDocument)||void 0===e||null===(e=e.defaultView)||void 0===e?void 0:e.getContextService().getBoundingClientRect();if(n){var o=b(n.getMin(),2),a=o[0],s=o[1],l=b(n.getMax(),2),u=l[0],c=l[1];return new Nr(a+((null==i?void 0:i.left)||0),s+((null==i?void 0:i.top)||0),u-a,c-s)}return new Nr((null==i?void 0:i.left)||0,(null==i?void 0:i.top)||0,0,0)}},{key:"dirtifyWorldInternal",value:function(t,e){var n=this;if(!e.dirtyFlag){e.dirtyFlag=!0,e.frozen=!1,t.childNodes.forEach((function(t){var e=t.transformable;e.dirtyFlag||n.dirtifyWorldInternal(t,e)}));var r=t.renderable;r&&(r.renderBoundsDirty=!0,r.boundsDirty=!0,r.dirty=!0)}}},{key:"syncHierarchy",value:function(t){var e=t.transformable;if(!e.frozen){e.frozen=!0,(e.localDirtyFlag||e.dirtyFlag)&&this.sync(t,e);for(var n=t.childNodes,r=0;rs;--d){for(var v=0;v=0;f--){var p=d[f].trim();!gs.test(p)&&ps.indexOf(p)<0&&(p='"'.concat(p,'"')),d[f]=p}return"".concat(a," ").concat(l," ").concat(c," ").concat(h," ").concat(d.join(","))}(e),x=this.measureFont(b,n);0===x.fontSize&&(x.fontSize=i,x.ascent=i);var E=this.runtime.offscreenCanvasCreator.getOrCreateContext(n);E.font=b,e.isOverflowing=!1;var w=(a?this.wordWrap(t,e,n):t).split(/(?:\r\n|\r|\n)/),k=new Array(w.length),M=0;if(!v){for(var S=0;Sr&&e>=n;)e-=1,t=t.slice(0,-1);return{lineTxt:t,txtLastCharIndex:e}}function M(t,e){if(!(w<=0||w>f))if(v[t]){var n=k(v[t],e,b+1,f-w);v[t]=n.lineTxt+p}else v[t]=p}for(var S=0;S=c){e.isOverflowing=!0,S0&&y+C>f){var A=k(v[m],S-1,b+1,f);if(A.txtLastCharIndex!==S-1){if(v[m]=A.lineTxt,A.txtLastCharIndex===g.length-1)break;S=A.txtLastCharIndex+1,N=g[S],O=g[S-1],T=g[S+1],C=E(N)}if(m+1>=c){e.isOverflowing=!0,M(m,S-1);break}if(b=S-1,y=0,v[m+=1]="",this.isBreakingSpace(N))continue;this.canBreakInLastChar(N)||(v=this.trimToBreakable(v),y=this.sumTextWidthByCache(v[m]||"",E)),this.shouldBreakByKinsokuShorui(N,T)&&(v=this.trimByKinsokuShorui(v),y+=E(O||""))}y+=C,v[m]=(v[m]||"")+N}}return v.join("\n")}},{key:"isBreakingSpace",value:function(t){return"string"==typeof t&&wl.BreakingSpaces.indexOf(t.charCodeAt(0))>=0}},{key:"isNewline",value:function(t){return"string"==typeof t&&wl.Newlines.indexOf(t.charCodeAt(0))>=0}},{key:"trimToBreakable",value:function(t){var e=d(t),n=e[e.length-2],r=this.findBreakableIndex(n);if(-1===r||!n)return e;var i=n.slice(r,r+1),o=r+1,a=r+(this.isBreakingSpace(i)?0:1);return e[e.length-1]+=n.slice(o,n.length),e[e.length-2]=n.slice(0,a),e}},{key:"canBreakInLastChar",value:function(t){return!t||!kl.test(t)}},{key:"sumTextWidthByCache",value:function(t,e){return t.split("").reduce((function(t,n){return t+e(n)}),0)}},{key:"findBreakableIndex",value:function(t){for(var e=t.length-1;e>=0;e--)if(!kl.test(t[e]))return e;return-1}},{key:"getFromCache",value:function(t,e,n,r){var i=n[t];if("number"!=typeof i){var o=t.length*e;i=r.measureText(t).width+o,n[t]=i}return i}}])}(),Ol={},Tl=(tl=new Rs,el=new Ps,i(i(i(i(i(i(i(i(i(i(Js={},hr.FRAGMENT,null),hr.CIRCLE,new Os),hr.ELLIPSE,new Ts),hr.RECT,tl),hr.IMAGE,tl),hr.GROUP,new Ls),hr.LINE,new Cs),hr.TEXT,new Ds(Ol)),hr.POLYLINE,el),hr.POLYGON,el),i(i(i(Js,hr.PATH,new As),hr.HTML,new _s),hr.MESH,null)),Cl=function(t){var e=new Ta,n=new Pa;return i(i(i(i(i(i(i(i(i(i(t={},ei.PERCENTAGE,null),ei.NUMBER,new _a),ei.ANGLE,new Na),ei.DEFINED_PATH,new Oa),ei.PAINT,e),ei.COLOR,e),ei.FILTER,new Ca),ei.LENGTH,n),ei.LENGTH_PERCENTAGE,n),ei.LENGTH_PERCENTAGE_12,new Ra),i(i(i(i(i(i(i(i(i(i(t,ei.LENGTH_PERCENTAGE_14,new Da),ei.COORDINATE,new Pa),ei.OFFSET_DISTANCE,new Ia),ei.OPACITY_VALUE,new ja),ei.PATH,new Ba),ei.LIST_OF_POINTS,new Fa),ei.SHADOW_BLUR,new za),ei.TEXT,new Ga),ei.TEXT_TRANSFORM,new Va),ei.TRANSFORM,new Ms),i(i(i(t,ei.TRANSFORM_ORIGIN,new Ss),ei.Z_INDEX,new Ns),ei.MARKER,new La)}();Ol.CameraContribution=Zr,Ol.AnimationTimeline=null,Ol.EasingFunction=null,Ol.offscreenCanvasCreator=new Us,Ol.sceneGraphSelector=new Xs,Ol.sceneGraphService=new El(Ol),Ol.textService=new Nl(Ol),Ol.geometryUpdaterFactory=Tl,Ol.CSSPropertySyntaxFactory=Cl,Ol.styleValueRegistry=new Ma(Ol),Ol.layoutRegistry=null,Ol.globalThis="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:{},Ol.enableStyleSyntax=!0,Ol.enableSizeAttenuation=!1;var Al=0,Pl=new Zs(Ks.INSERTED,null,"","","",0,"",""),Rl=new Zs(Ks.REMOVED,null,"","","",0,"",""),Dl=new zs(Ks.DESTROY),Ll=function(t){function e(){var t;s(this,e);for(var n=arguments.length,r=new Array(n),i=0;i=0;t--){var e=this.childNodes[t];this.removeChild(e)}}},{key:"destroyChildren",value:function(){for(var t=this.childNodes.length-1;t>=0;t--){var e=this.childNodes[t];e.childNodes.length>0&&e.destroyChildren(),e.destroy()}}},{key:"matches",value:function(t){return Ol.sceneGraphService.matches(t,this)}},{key:"getElementById",value:function(t){return Ol.sceneGraphService.querySelector("#".concat(t),this)}},{key:"getElementsByName",value:function(t){return Ol.sceneGraphService.querySelectorAll('[name="'.concat(t,'"]'),this)}},{key:"getElementsByClassName",value:function(t){return Ol.sceneGraphService.querySelectorAll(".".concat(t),this)}},{key:"getElementsByTagName",value:function(t){return Ol.sceneGraphService.querySelectorAll(t,this)}},{key:"querySelector",value:function(t){return Ol.sceneGraphService.querySelector(t,this)}},{key:"querySelectorAll",value:function(t){return Ol.sceneGraphService.querySelectorAll(t,this)}},{key:"closest",value:function(t){var e=this;do{if(Ol.sceneGraphService.matches(t,e))return e;e=e.parentElement}while(null!==e);return null}},{key:"find",value:function(t){var e=this,n=null;return this.forEach((function(r){return r===e||!t(r)||(n=r,!1)})),n}},{key:"findAll",value:function(t){var e=this,n=[];return this.forEach((function(r){r!==e&&t(r)&&n.push(r)})),n}},{key:"after",value:function(){var t=this;if(this.parentNode){for(var e=this.parentNode.childNodes.indexOf(this),n=arguments.length,r=new Array(n),i=0;i0&&void 0!==arguments[0]?arguments[0]:{};Ol.styleValueRegistry.processProperties(this,t,{forceUpdateGeometry:!0}),this.renderable.dirty=!0}},{key:"setAttribute",value:function(t,n){var r=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i=!(arguments.length>3&&void 0!==arguments[3])||arguments[3];ve(n)||(r||n!==this.attributes[t])&&(this.internalSetAttribute(t,n,{memoize:i}),Pn(e,"setAttribute",this)([t,n]))}},{key:"internalSetAttribute",value:function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r=this.renderable,o=this.attributes[t],a=this.parsedStyle[t];Ol.styleValueRegistry.processProperties(this,i({},t,e),n),r.dirty=!0;var s,l=this.parsedStyle[t];(this.isConnected&&(jl.relatedNode=this,jl.prevValue=o,jl.newValue=e,jl.attrName=t,jl.prevParsedValue=a,jl.newParsedValue=l,this.isMutationObserved?this.dispatchEvent(jl):(jl.target=this,this.ownerDocument.defaultView.dispatchEvent(jl,!0))),this.isCustomElement&&this.isConnected||!this.isCustomElement)&&(null===(s=this.attributeChangedCallback)||void 0===s||s.call(this,t,o,e,a,l))}},{key:"getBBox",value:function(){var t=this.getBounds(),e=b(t.getMin(),2),n=e[0],r=e[1],i=b(t.getMax(),2),o=i[0],a=i[1];return new Nr(n,r,o-n,a-r)}},{key:"setOrigin",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;return Ol.sceneGraphService.setOrigin(this,Pr(t,e,n,!1)),this}},{key:"getOrigin",value:function(){return Ol.sceneGraphService.getOrigin(this)}},{key:"setPosition",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;return Ol.sceneGraphService.setPosition(this,Pr(t,e,n,!1)),this}},{key:"setLocalPosition",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;return Ol.sceneGraphService.setLocalPosition(this,Pr(t,e,n,!1)),this}},{key:"translate",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;return Ol.sceneGraphService.translate(this,Pr(t,e,n,!1)),this}},{key:"translateLocal",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;return Ol.sceneGraphService.translateLocal(this,Pr(t,e,n,!1)),this}},{key:"getPosition",value:function(){return Ol.sceneGraphService.getPosition(this)}},{key:"getLocalPosition",value:function(){return Ol.sceneGraphService.getLocalPosition(this)}},{key:"scale",value:function(t,e,n){return this.scaleLocal(t,e,n)}},{key:"scaleLocal",value:function(t,e,n){return"number"==typeof t&&(t=Pr(t,e=e||t,n=n||t,!1)),Ol.sceneGraphService.scaleLocal(this,t),this}},{key:"setLocalScale",value:function(t,e,n){return"number"==typeof t&&(t=Pr(t,e=e||t,n=n||t,!1)),Ol.sceneGraphService.setLocalScale(this,t),this}},{key:"getLocalScale",value:function(){return Ol.sceneGraphService.getLocalScale(this)}},{key:"getScale",value:function(){return Ol.sceneGraphService.getScale(this)}},{key:"getEulerAngles",value:function(){return _r(b(jr(Bl,Ol.sceneGraphService.getWorldTransform(this)),3)[2])}},{key:"getLocalEulerAngles",value:function(){return _r(b(jr(Bl,Ol.sceneGraphService.getLocalRotation(this)),3)[2])}},{key:"setEulerAngles",value:function(t){return Ol.sceneGraphService.setEulerAngles(this,0,0,t),this}},{key:"setLocalEulerAngles",value:function(t){return Ol.sceneGraphService.setLocalEulerAngles(this,0,0,t),this}},{key:"rotateLocal",value:function(t,e,n){return $t(e)&&$t(n)?Ol.sceneGraphService.rotateLocal(this,0,0,t):Ol.sceneGraphService.rotateLocal(this,t,e,n),this}},{key:"rotate",value:function(t,e,n){return $t(e)&&$t(n)?Ol.sceneGraphService.rotate(this,0,0,t):Ol.sceneGraphService.rotate(this,t,e,n),this}},{key:"setRotation",value:function(t,e,n,r){return Ol.sceneGraphService.setRotation(this,t,e,n,r),this}},{key:"setLocalRotation",value:function(t,e,n,r){return Ol.sceneGraphService.setLocalRotation(this,t,e,n,r),this}},{key:"setLocalSkew",value:function(t,e){return Ol.sceneGraphService.setLocalSkew(this,t,e),this}},{key:"getRotation",value:function(){return Ol.sceneGraphService.getRotation(this)}},{key:"getLocalRotation",value:function(){return Ol.sceneGraphService.getLocalRotation(this)}},{key:"getLocalSkew",value:function(){return Ol.sceneGraphService.getLocalSkew(this)}},{key:"getLocalTransform",value:function(){return Ol.sceneGraphService.getLocalTransform(this)}},{key:"getWorldTransform",value:function(){return Ol.sceneGraphService.getWorldTransform(this)}},{key:"setLocalTransform",value:function(t){return Ol.sceneGraphService.setLocalTransform(this,t),this}},{key:"resetLocalTransform",value:function(){Ol.sceneGraphService.resetLocalTransform(this)}},{key:"getAnimations",value:function(){return this.activeAnimations}},{key:"animate",value:function(t,e){var n,r=null===(n=this.ownerDocument)||void 0===n?void 0:n.timeline;return r?r.play(this,t,e):null}},{key:"isVisible",value:function(){var t;return"hidden"!==(null===(t=this.parsedStyle)||void 0===t?void 0:t.visibility)}},{key:"interactive",get:function(){return this.isInteractive()},set:function(t){this.style.pointerEvents=t?"auto":"none"}},{key:"isInteractive",value:function(){var t;return"none"!==(null===(t=this.parsedStyle)||void 0===t?void 0:t.pointerEvents)}},{key:"isCulled",value:function(){return!(!this.cullable||!this.cullable.enable||this.cullable.visible)}},{key:"toFront",value:function(){return this.parentNode&&(this.style.zIndex=Math.max.apply(Math,d(this.parentNode.children.map((function(t){return Number(t.style.zIndex)}))))+1),this}},{key:"toBack",value:function(){return this.parentNode&&(this.style.zIndex=Math.min.apply(Math,d(this.parentNode.children.map((function(t){return Number(t.style.zIndex)}))))-1),this}},{key:"getConfig",value:function(){return this.config}},{key:"attr",value:function(){for(var t=this,e=arguments.length,n=new Array(e),r=0;r1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;return this.setPosition(t,e,n),this}},{key:"move",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;return this.setPosition(t,e,n),this}},{key:"setZIndex",value:function(t){return this.style.zIndex=t,this}}])}(Ll);zl.PARSED_STYLE_LIST=new Set(["class","className","clipPath","cursor","display","draggable","droppable","fill","fillOpacity","fillRule","filter","increasedLineWidthForHitTesting","lineCap","lineDash","lineDashOffset","lineJoin","lineWidth","miterLimit","hitArea","offsetDistance","offsetPath","offsetX","offsetY","opacity","pointerEvents","shadowColor","shadowType","shadowBlur","shadowOffsetX","shadowOffsetY","stroke","strokeOpacity","strokeWidth","strokeLinecap","strokeLineJoin","strokeDasharray","strokeDashoffset","transform","transformOrigin","textTransform","visibility","zIndex"]);var Gl=function(t){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return s(this,e),v(this,e,[a({type:hr.CIRCLE},t)])}return y(e,t),u(e)}(zl);Gl.PARSED_STYLE_LIST=new Set([].concat(d(zl.PARSED_STYLE_LIST),["cx","cy","cz","r","isBillboard","isSizeAttenuation"]));var Vl=["style"],Wl=function(t){function e(){var t,n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=n.style,i=lr(n,Vl);return s(this,e),(t=v(this,e,[a({style:r},i)])).isCustomElement=!0,t}return y(e,t),u(e)}(zl);Wl.PARSED_STYLE_LIST=new Set(["class","className","clipPath","cursor","draggable","droppable","opacity","pointerEvents","transform","transformOrigin","zIndex","visibility"]);var Hl=function(t){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return s(this,e),v(this,e,[a({type:hr.ELLIPSE},t)])}return y(e,t),u(e)}(zl);Hl.PARSED_STYLE_LIST=new Set([].concat(d(zl.PARSED_STYLE_LIST),["cx","cy","cz","rx","ry","isBillboard","isSizeAttenuation"])),(function(t){function e(){return s(this,e),v(this,e,[{type:hr.FRAGMENT}])}return y(e,t),u(e)}(zl)).PARSED_STYLE_LIST=new Set(["class","className"]);var Ul=function(t){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return s(this,e),v(this,e,[a({type:hr.GROUP},t)])}return y(e,t),u(e)}(zl);Ul.PARSED_STYLE_LIST=new Set(["class","className","clipPath","cursor","draggable","droppable","opacity","pointerEvents","transform","transformOrigin","zIndex","visibility"]);var $l=["style"],Yl=function(t){function e(){var t,n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=n.style,i=lr(n,$l);return s(this,e),(t=v(this,e,[a({type:hr.HTML,style:r},i)])).cullable.enable=!1,t}return y(e,t),u(e,[{key:"getDomElement",value:function(){return this.parsedStyle.$el}},{key:"getClientRects",value:function(){return[this.getBoundingClientRect()]}},{key:"getLocalBounds",value:function(){if(this.parentNode){var t=_(T(),this.parentNode.getWorldTransform()),e=this.getBounds();if(!Er.isEmpty(e)){var n=new Er;return n.setFromTransformedAABB(e,t),n}}return this.getBounds()}}])}(zl);Yl.PARSED_STYLE_LIST=new Set([].concat(d(zl.PARSED_STYLE_LIST),["x","y","$el","innerHTML","width","height"]));var ql=function(t){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return s(this,e),v(this,e,[a({type:hr.IMAGE},t)])}return y(e,t),u(e)}(zl);ql.PARSED_STYLE_LIST=new Set([].concat(d(zl.PARSED_STYLE_LIST),["x","y","z","src","width","height","isBillboard","billboardRotation","isSizeAttenuation","keepAspectRatio"]));var Xl=["style"],Kl=function(t){function e(){var t,n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=n.style,i=lr(n,Xl);s(this,e),(t=v(this,e,[a({type:hr.LINE,style:a({x1:0,y1:0,x2:0,y2:0,z1:0,z2:0},r)},i)])).markerStartAngle=0,t.markerEndAngle=0;var o=t.parsedStyle,l=o.markerStart,u=o.markerEnd;return l&&_l(l)&&(t.markerStartAngle=l.getLocalEulerAngles(),t.appendChild(l)),u&&_l(u)&&(t.markerEndAngle=u.getLocalEulerAngles(),t.appendChild(u)),t.transformMarker(!0),t.transformMarker(!1),t}return y(e,t),u(e,[{key:"attributeChangedCallback",value:function(t,e,n,r,i){"x1"===t||"y1"===t||"x2"===t||"y2"===t||"markerStartOffset"===t||"markerEndOffset"===t?(this.transformMarker(!0),this.transformMarker(!1)):"markerStart"===t?(r&&_l(r)&&(this.markerStartAngle=0,r.remove()),i&&_l(i)&&(this.markerStartAngle=i.getLocalEulerAngles(),this.appendChild(i),this.transformMarker(!0))):"markerEnd"===t&&(r&&_l(r)&&(this.markerEndAngle=0,r.remove()),i&&_l(i)&&(this.markerEndAngle=i.getLocalEulerAngles(),this.appendChild(i),this.transformMarker(!1)))}},{key:"transformMarker",value:function(t){var e=this.parsedStyle,n=e.markerStart,r=e.markerEnd,i=e.markerStartOffset,o=e.markerEndOffset,a=e.x1,s=e.x2,l=e.y1,u=e.y2,c=t?n:r;if(c&&_l(c)){var h,d,f,p,g,v,m;t?(p=a,g=l,d=s-a,f=u-l,v=i||0,m=this.markerStartAngle):(p=s,g=u,d=a-s,f=l-u,v=o||0,m=this.markerEndAngle),h=Math.atan2(f,d),c.setLocalEulerAngles(180*h/Math.PI+m),c.setLocalPosition(p+Math.cos(h)*v,g+Math.sin(h)*v)}}},{key:"getPoint",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=this.parsedStyle,r=Fn(n.x1,n.y1,n.x2,n.y2,t),i=r.x,o=r.y,a=Mt(ht(),pt(i,o,0),e?this.getWorldTransform():this.getLocalTransform());return new Sr(a[0],a[1])}},{key:"getPointAtLength",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return this.getPoint(t/this.getTotalLength(),e)}},{key:"getTotalLength",value:function(){var t=this.parsedStyle;return Bn(t.x1,t.y1,t.x2,t.y2)}}])}(zl);Kl.PARSED_STYLE_LIST=new Set([].concat(d(zl.PARSED_STYLE_LIST),["x1","y1","x2","y2","z1","z2","isBillboard","isSizeAttenuation","markerStart","markerEnd","markerStartOffset","markerEndOffset"]));var Zl=["style"],Ql=function(t){function e(){var t,n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=n.style,i=lr(n,Zl);s(this,e),(t=v(this,e,[a({type:hr.PATH,style:r,initialParsedStyle:{miterLimit:4,d:a({},ti)}},i)])).markerStartAngle=0,t.markerEndAngle=0,t.markerMidList=[];var o=t.parsedStyle,l=o.markerStart,u=o.markerEnd,c=o.markerMid;return l&&_l(l)&&(t.markerStartAngle=l.getLocalEulerAngles(),t.appendChild(l)),c&&_l(c)&&t.placeMarkerMid(c),u&&_l(u)&&(t.markerEndAngle=u.getLocalEulerAngles(),t.appendChild(u)),t.transformMarker(!0),t.transformMarker(!1),t}return y(e,t),u(e,[{key:"attributeChangedCallback",value:function(t,e,n,r,i){"d"===t?(this.transformMarker(!0),this.transformMarker(!1),this.placeMarkerMid(this.parsedStyle.markerMid)):"markerStartOffset"===t||"markerEndOffset"===t?(this.transformMarker(!0),this.transformMarker(!1)):"markerStart"===t?(r&&_l(r)&&(this.markerStartAngle=0,r.remove()),i&&_l(i)&&(this.markerStartAngle=i.getLocalEulerAngles(),this.appendChild(i),this.transformMarker(!0))):"markerEnd"===t?(r&&_l(r)&&(this.markerEndAngle=0,r.remove()),i&&_l(i)&&(this.markerEndAngle=i.getLocalEulerAngles(),this.appendChild(i),this.transformMarker(!1))):"markerMid"===t&&this.placeMarkerMid(i)}},{key:"transformMarker",value:function(t){var e=this.parsedStyle,n=e.markerStart,r=e.markerEnd,i=e.markerStartOffset,o=e.markerEndOffset,a=t?n:r;if(a&&_l(a)){var s,l,u,c,h,d,f;if(t){var p=b(this.getStartTangent(),2),g=p[0],v=p[1];c=v[0],h=v[1],l=g[0]-v[0],u=g[1]-v[1],d=i||0,f=this.markerStartAngle}else{var m=b(this.getEndTangent(),2),y=m[0],x=m[1];c=x[0],h=x[1],l=y[0]-x[0],u=y[1]-x[1],d=o||0,f=this.markerEndAngle}s=Math.atan2(u,l),a.setLocalEulerAngles(180*s/Math.PI+f),a.setLocalPosition(c+Math.cos(s)*d,h+Math.sin(s)*d)}}},{key:"placeMarkerMid",value:function(t){var e=this.parsedStyle.d.segments;if(this.markerMidList.forEach((function(t){t.remove()})),t&&_l(t))for(var n=1;n1&&void 0!==arguments[1]&&arguments[1],n=function(t,e,n){return Mn(t,e,Be(Be({},n),{bbox:!1,length:!0})).point}(this.parsedStyle.d.absolutePath,t),r=n.x,i=n.y,o=Mt(ht(),pt(r,i,0),e?this.getWorldTransform():this.getLocalTransform());return new Sr(o[0],o[1])}},{key:"getPoint",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return this.getPointAtLength(t*zo(this),e)}},{key:"getStartTangent",value:function(){var t=this.parsedStyle.d.segments,e=[];if(t.length>1){var n=t[0].currentPoint,r=t[1].currentPoint,i=t[1].startTangent;e=[],i?(e.push([n[0]-i[0],n[1]-i[1]]),e.push([n[0],n[1]])):(e.push([r[0],r[1]]),e.push([n[0],n[1]]))}return e}},{key:"getEndTangent",value:function(){var t=this.parsedStyle.d.segments,e=t.length,n=[];if(e>1){var r=t[e-2].currentPoint,i=t[e-1].currentPoint,o=t[e-1].endTangent;n=[],o?(n.push([i[0]-o[0],i[1]-o[1]]),n.push([i[0],i[1]])):(n.push([r[0],r[1]]),n.push([i[0],i[1]]))}return n}}])}(zl);Ql.PARSED_STYLE_LIST=new Set([].concat(d(zl.PARSED_STYLE_LIST),["d","markerStart","markerMid","markerEnd","markerStartOffset","markerEndOffset","isBillboard","isSizeAttenuation"]));var Jl=["style"],tu=function(t){function e(){var t,n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},r=n.style,i=lr(n,Jl);s(this,e),(t=v(this,e,[a({type:hr.POLYGON,style:r,initialParsedStyle:{points:{points:[],totalLength:0,segments:[]},miterLimit:4,isClosed:!0}},i)])).markerStartAngle=0,t.markerEndAngle=0,t.markerMidList=[];var o=t.parsedStyle,l=o.markerStart,u=o.markerEnd,c=o.markerMid;return l&&_l(l)&&(t.markerStartAngle=l.getLocalEulerAngles(),t.appendChild(l)),c&&_l(c)&&t.placeMarkerMid(c),u&&_l(u)&&(t.markerEndAngle=u.getLocalEulerAngles(),t.appendChild(u)),t.transformMarker(!0),t.transformMarker(!1),t}return y(e,t),u(e,[{key:"attributeChangedCallback",value:function(t,e,n,r,i){"points"===t?(this.transformMarker(!0),this.transformMarker(!1),this.placeMarkerMid(this.parsedStyle.markerMid)):"markerStartOffset"===t||"markerEndOffset"===t?(this.transformMarker(!0),this.transformMarker(!1)):"markerStart"===t?(r&&_l(r)&&(this.markerStartAngle=0,r.remove()),i&&_l(i)&&(this.markerStartAngle=i.getLocalEulerAngles(),this.appendChild(i),this.transformMarker(!0))):"markerEnd"===t?(r&&_l(r)&&(this.markerEndAngle=0,r.remove()),i&&_l(i)&&(this.markerEndAngle=i.getLocalEulerAngles(),this.appendChild(i),this.transformMarker(!1))):"markerMid"===t&&this.placeMarkerMid(i)}},{key:"transformMarker",value:function(t){var e=this.parsedStyle,n=e.markerStart,r=e.markerEnd,i=e.markerStartOffset,o=e.markerEndOffset,a=(e.points||{}).points,s=t?n:r;if(s&&_l(s)&&a){var l,u,c,h,d,f,p;if(h=a[0][0],d=a[0][1],t)u=a[1][0]-a[0][0],c=a[1][1]-a[0][1],f=i||0,p=this.markerStartAngle;else{var g=a.length;this.parsedStyle.isClosed?(u=a[g-1][0]-a[0][0],c=a[g-1][1]-a[0][1]):(h=a[g-1][0],d=a[g-1][1],u=a[g-2][0]-a[g-1][0],c=a[g-2][1]-a[g-1][1]),f=o||0,p=this.markerEndAngle}l=Math.atan2(c,u),s.setLocalEulerAngles(180*l/Math.PI+p),s.setLocalPosition(h+Math.cos(l)*f,d+Math.sin(l)*f)}}},{key:"placeMarkerMid",value:function(t){var e=(this.parsedStyle.points||{}).points;if(this.markerMidList.forEach((function(t){t.remove()})),this.markerMidList=[],t&&_l(t)&&e)for(var n=1;n<(this.parsedStyle.isClosed?e.length:e.length-1);n++){var r=e[n][0],i=e[n][1],o=1===n?t:t.cloneNode(!0);this.markerMidList.push(o),this.appendChild(o),o.setLocalPosition(r,i)}}}])}(zl);tu.PARSED_STYLE_LIST=new Set([].concat(d(zl.PARSED_STYLE_LIST),["points","markerStart","markerMid","markerEnd","markerStartOffset","markerEndOffset","isClosed","isBillboard","isSizeAttenuation"]));var eu=["style"],nu=function(t){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=t.style,r=lr(t,eu);return s(this,e),v(this,e,[a({type:hr.POLYLINE,style:n,initialParsedStyle:{points:{points:[],totalLength:0,segments:[]},miterLimit:4,isClosed:!1}},r)])}return y(e,t),u(e,[{key:"getTotalLength",value:function(){return 0===(t=this).parsedStyle.points.totalLength&&(t.parsedStyle.points.totalLength=Un(t.parsedStyle.points.points)),t.parsedStyle.points.totalLength;var t}},{key:"getPointAtLength",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return this.getPoint(t/this.getTotalLength(),e)}},{key:"getPoint",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=this.parsedStyle.points.points;if(0===this.parsedStyle.points.segments.length){var r,i,o=[],a=0,s=this.getTotalLength();n.forEach((function(t,e){n[e+1]&&((r=[0,0])[0]=a/s,i=Bn(t[0],t[1],n[e+1][0],n[e+1][1]),a+=i,r[1]=a/s,o.push(r))})),this.parsedStyle.points.segments=o}var l=0,u=0;this.parsedStyle.points.segments.forEach((function(e,n){t>=e[0]&&t<=e[1]&&(l=(t-e[0])/(e[1]-e[0]),u=n)}));var c=Fn(n[u][0],n[u][1],n[u+1][0],n[u+1][1],l),h=c.x,d=c.y,f=Mt(ht(),pt(h,d,0),e?this.getWorldTransform():this.getLocalTransform());return new Sr(f[0],f[1])}},{key:"getStartTangent",value:function(){var t=this.parsedStyle.points.points,e=[];return e.push([t[1][0],t[1][1]]),e.push([t[0][0],t[0][1]]),e}},{key:"getEndTangent",value:function(){var t=this.parsedStyle.points.points,e=t.length-1,n=[];return n.push([t[e-1][0],t[e-1][1]]),n.push([t[e][0],t[e][1]]),n}}])}(tu);nu.PARSED_STYLE_LIST=new Set([].concat(d(tu.PARSED_STYLE_LIST),["points","markerStart","markerMid","markerEnd","markerStartOffset","markerEndOffset","isBillboard"]));var ru=function(t){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return s(this,e),v(this,e,[a({type:hr.RECT},t)])}return y(e,t),u(e)}(zl);ru.PARSED_STYLE_LIST=new Set([].concat(d(zl.PARSED_STYLE_LIST),["x","y","z","width","height","isBillboard","isSizeAttenuation","radius"]));var iu=["style"],ou=function(t){function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=t.style,r=lr(t,iu);return s(this,e),v(this,e,[a({type:hr.TEXT,style:a({fill:"black"},n)},r)])}return y(e,t),u(e,[{key:"getComputedTextLength",value:function(){var t;return this.getGeometryBounds(),(null===(t=this.parsedStyle.metrics)||void 0===t?void 0:t.maxLineWidth)||0}},{key:"getLineBoundingRects",value:function(){var t;return this.getGeometryBounds(),(null===(t=this.parsedStyle.metrics)||void 0===t?void 0:t.lineMetrics)||[]}},{key:"isOverflowing",value:function(){return this.getGeometryBounds(),!!this.parsedStyle.isOverflowing}}])}(zl);ou.PARSED_STYLE_LIST=new Set([].concat(d(zl.PARSED_STYLE_LIST),["x","y","z","isBillboard","billboardRotation","isSizeAttenuation","text","textAlign","textBaseline","fontStyle","fontSize","fontFamily","fontWeight","fontVariant","lineHeight","letterSpacing","leading","wordWrap","wordWrapWidth","maxLines","textOverflow","isOverflowing","textPath","textDecorationLine","textDecorationColor","textDecorationStyle","textPathSide","textPathStartOffset","metrics","dx","dy"]));var au=function(){return u((function t(){s(this,t),this.registry={},this.define(hr.CIRCLE,Gl),this.define(hr.ELLIPSE,Hl),this.define(hr.RECT,ru),this.define(hr.IMAGE,ql),this.define(hr.LINE,Kl),this.define(hr.GROUP,Ul),this.define(hr.PATH,Ql),this.define(hr.POLYGON,tu),this.define(hr.POLYLINE,nu),this.define(hr.TEXT,ou),this.define(hr.HTML,Yl)}),[{key:"define",value:function(t,e){this.registry[t]=e}},{key:"get",value:function(t){return this.registry[t]}}])}(),su=function(t){function e(){var t;s(this,e),(t=v(this,e)).defaultView=null,t.ownerDocument=null,t.nodeName="document";try{t.timeline=new Ol.AnimationTimeline(t)}catch(t){}var n={};return Ea.forEach((function(t){var e=t.n,r=t.inh,i=t.d;r&&i&&(n[e]=Ut(i)?i(hr.GROUP):i)})),t.documentElement=new Ul({id:"g-root",style:n}),t.documentElement.ownerDocument=t,t.documentElement.parentNode=t,t.childNodes=[t.documentElement],t}return y(e,t),u(e,[{key:"children",get:function(){return this.childNodes}},{key:"childElementCount",get:function(){return this.childNodes.length}},{key:"firstElementChild",get:function(){return this.firstChild}},{key:"lastElementChild",get:function(){return this.lastChild}},{key:"createElement",value:function(t,e){if("svg"===t)return this.documentElement;var n=this.defaultView.customElements.get(t);n||(console.warn("Unsupported tagName: ",t),n="tspan"===t?ou:Ul);var r=new n(e);return r.ownerDocument=this,r}},{key:"createElementNS",value:function(t,e,n){return this.createElement(e,n)}},{key:"cloneNode",value:function(t){throw new Error(Or)}},{key:"destroy",value:function(){try{this.documentElement.destroyChildren(),this.timeline.destroy()}catch(t){}}},{key:"elementsFromBBox",value:function(t,e,n,r){var i=this.defaultView.context.rBushRoot.search({minX:t,minY:e,maxX:n,maxY:r}),o=[];return i.forEach((function(t){var e=t.displayObject,n=e.parsedStyle.pointerEvents,r=["auto","visiblepainted","visiblefill","visiblestroke","visible"].includes(void 0===n?"auto":n);(!r||r&&e.isVisible())&&!e.isCulled()&&e.isInteractive()&&o.push(e)})),o.sort((function(t,e){return e.sortable.renderOrder-t.sortable.renderOrder})),o}},{key:"elementFromPointSync",value:function(t,e){var n=this.defaultView.canvas2Viewport({x:t,y:e}),r=n.x,i=n.y,o=this.defaultView.getConfig(),a=o.width,s=o.height;if(r<0||i<0||r>a||i>s)return null;var l=this.defaultView.viewport2Client({x:r,y:i}),u=l.x,c=l.y,h=this.defaultView.getRenderingService().hooks.pickSync.call({topmost:!0,position:{x:t,y:e,viewportX:r,viewportY:i,clientX:u,clientY:c},picked:[]}).picked;return h&&h[0]||this.documentElement}},{key:"elementFromPoint",value:(r=ar(ir().mark((function t(e,n){var r,i,o,a,s,l,u,c,h,d,f;return ir().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(r=this.defaultView.canvas2Viewport({x:e,y:n}),i=r.x,o=r.y,a=this.defaultView.getConfig(),s=a.width,l=a.height,!(i<0||o<0||i>s||o>l)){t.next=4;break}return t.abrupt("return",null);case 4:return u=this.defaultView.viewport2Client({x:i,y:o}),c=u.x,h=u.y,t.next=7,this.defaultView.getRenderingService().hooks.pick.promise({topmost:!0,position:{x:e,y:n,viewportX:i,viewportY:o,clientX:c,clientY:h},picked:[]});case 7:return d=t.sent,f=d.picked,t.abrupt("return",f&&f[0]||this.documentElement);case 10:case"end":return t.stop()}}),t,this)}))),function(t,e){return r.apply(this,arguments)})},{key:"elementsFromPointSync",value:function(t,e){var n=this.defaultView.canvas2Viewport({x:t,y:e}),r=n.x,i=n.y,o=this.defaultView.getConfig(),a=o.width,s=o.height;if(r<0||i<0||r>a||i>s)return[];var l=this.defaultView.viewport2Client({x:r,y:i}),u=l.x,c=l.y,h=this.defaultView.getRenderingService().hooks.pickSync.call({topmost:!1,position:{x:t,y:e,viewportX:r,viewportY:i,clientX:u,clientY:c},picked:[]}).picked;return h[h.length-1]!==this.documentElement&&h.push(this.documentElement),h}},{key:"elementsFromPoint",value:(n=ar(ir().mark((function t(e,n){var r,i,o,a,s,l,u,c,h,d,f;return ir().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(r=this.defaultView.canvas2Viewport({x:e,y:n}),i=r.x,o=r.y,a=this.defaultView.getConfig(),s=a.width,l=a.height,!(i<0||o<0||i>s||o>l)){t.next=4;break}return t.abrupt("return",[]);case 4:return u=this.defaultView.viewport2Client({x:i,y:o}),c=u.x,h=u.y,t.next=7,this.defaultView.getRenderingService().hooks.pick.promise({topmost:!1,position:{x:e,y:n,viewportX:i,viewportY:o,clientX:c,clientY:h},picked:[]});case 7:return d=t.sent,(f=d.picked)[f.length-1]!==this.documentElement&&f.push(this.documentElement),t.abrupt("return",f);case 11:case"end":return t.stop()}}),t,this)}))),function(t,e){return n.apply(this,arguments)})},{key:"appendChild",value:function(t,e){throw new Error(Tr)}},{key:"insertBefore",value:function(t,e){throw new Error(Tr)}},{key:"removeChild",value:function(t,e){throw new Error(Tr)}},{key:"replaceChild",value:function(t,e,n){throw new Error(Tr)}},{key:"append",value:function(){throw new Error(Tr)}},{key:"prepend",value:function(){throw new Error(Tr)}},{key:"getElementById",value:function(t){return this.documentElement.getElementById(t)}},{key:"getElementsByName",value:function(t){return this.documentElement.getElementsByName(t)}},{key:"getElementsByTagName",value:function(t){return this.documentElement.getElementsByTagName(t)}},{key:"getElementsByClassName",value:function(t){return this.documentElement.getElementsByClassName(t)}},{key:"querySelector",value:function(t){return this.documentElement.querySelector(t)}},{key:"querySelectorAll",value:function(t){return this.documentElement.querySelectorAll(t)}},{key:"find",value:function(t){return this.documentElement.find(t)}},{key:"findAll",value:function(t){return this.documentElement.findAll(t)}}]);var n,r}(Ws),lu=function(){function t(e){s(this,t),this.strategies=e}return u(t,[{key:"apply",value:function(e){var n=e.camera,r=e.renderingService,i=e.renderingContext,o=this.strategies;r.hooks.cull.tap(t.tag,(function(t){if(t){var e=t.cullable;return 0===o.length?e.visible=i.unculledEntities.indexOf(t.entity)>-1:e.visible=o.every((function(e){return e.isVisible(n,t)})),!t.isCulled()&&t.isVisible()?t:(t.dispatchEvent(new zs(Ks.CULLED)),null)}return t})),r.hooks.afterRender.tap(t.tag,(function(t){t.cullable.visibilityPlaneMask=-1}))}}])}();lu.tag="Culling";var uu=function(){function t(){var e=this;s(this,t),this.autoPreventDefault=!1,this.rootPointerEvent=new Bs(null),this.rootWheelEvent=new Fs(null),this.onPointerMove=function(t){var n,r=null===(n=e.context.renderingContext.root)||void 0===n||null===(n=n.ownerDocument)||void 0===n?void 0:n.defaultView;if(!r.supportsTouchEvents||"touch"!==t.pointerType){var i,o=sr(e.normalizeToPointerEvent(t,r));try{for(o.s();!(i=o.n()).done;){var a=i.value,s=e.bootstrapEvent(e.rootPointerEvent,a,r,t);e.context.eventService.mapEvent(s)}}catch(t){o.e(t)}finally{o.f()}e.setCursor(e.context.eventService.cursor)}},this.onClick=function(t){var n,r,i=null===(n=e.context.renderingContext.root)||void 0===n||null===(n=n.ownerDocument)||void 0===n?void 0:n.defaultView,o=sr(e.normalizeToPointerEvent(t,i));try{for(o.s();!(r=o.n()).done;){var a=r.value,s=e.bootstrapEvent(e.rootPointerEvent,a,i,t);e.context.eventService.mapEvent(s)}}catch(t){o.e(t)}finally{o.f()}e.setCursor(e.context.eventService.cursor)}}return u(t,[{key:"apply",value:function(e){var n=this;this.context=e;var r=e.renderingService,i=this.context.renderingContext.root.ownerDocument.defaultView;this.context.eventService.setPickHandler((function(t){return n.context.renderingService.hooks.pickSync.call({position:t,picked:[],topmost:!0}).picked[0]||null})),r.hooks.pointerWheel.tap(t.tag,(function(t){var e=n.normalizeWheelEvent(t);n.context.eventService.mapEvent(e)})),r.hooks.pointerDown.tap(t.tag,(function(t){if(!i.supportsTouchEvents||"touch"!==t.pointerType){var e=n.normalizeToPointerEvent(t,i);if(n.autoPreventDefault&&e[0].isNormalized)(t.cancelable||!("cancelable"in t))&&t.preventDefault();var r,o=sr(e);try{for(o.s();!(r=o.n()).done;){var a=r.value,s=n.bootstrapEvent(n.rootPointerEvent,a,i,t);n.context.eventService.mapEvent(s)}}catch(t){o.e(t)}finally{o.f()}n.setCursor(n.context.eventService.cursor)}})),r.hooks.pointerUp.tap(t.tag,(function(t){if(!i.supportsTouchEvents||"touch"!==t.pointerType){var e,r=n.context.contextService.getDomElement(),o=n.context.eventService.isNativeEventFromCanvas(r,t)?"":"outside",a=sr(n.normalizeToPointerEvent(t,i));try{for(a.s();!(e=a.n()).done;){var s=e.value,l=n.bootstrapEvent(n.rootPointerEvent,s,i,t);l.type+=o,n.context.eventService.mapEvent(l)}}catch(t){a.e(t)}finally{a.f()}n.setCursor(n.context.eventService.cursor)}})),r.hooks.pointerMove.tap(t.tag,this.onPointerMove),r.hooks.pointerOver.tap(t.tag,this.onPointerMove),r.hooks.pointerOut.tap(t.tag,this.onPointerMove),r.hooks.click.tap(t.tag,this.onClick),r.hooks.pointerCancel.tap(t.tag,(function(t){var e,r=sr(n.normalizeToPointerEvent(t,i));try{for(r.s();!(e=r.n()).done;){var o=e.value,a=n.bootstrapEvent(n.rootPointerEvent,o,i,t);n.context.eventService.mapEvent(a)}}catch(t){r.e(t)}finally{r.f()}n.setCursor(n.context.eventService.cursor)}))}},{key:"bootstrapEvent",value:function(t,e,n,r){t.view=n,t.originalEvent=null,t.nativeEvent=r,t.pointerId=e.pointerId,t.width=e.width,t.height=e.height,t.isPrimary=e.isPrimary,t.pointerType=e.pointerType,t.pressure=e.pressure,t.tangentialPressure=e.tangentialPressure,t.tiltX=e.tiltX,t.tiltY=e.tiltY,t.twist=e.twist,this.transferMouseData(t,e);var i=this.context.eventService.client2Viewport({x:e.clientX,y:e.clientY}),o=i.x,a=i.y;t.viewport.x=o,t.viewport.y=a;var s=this.context.eventService.viewport2Canvas(t.viewport),l=s.x,u=s.y;return t.canvas.x=l,t.canvas.y=u,t.global.copyFrom(t.canvas),t.offset.copyFrom(t.canvas),t.isTrusted=r.isTrusted,"pointerleave"===t.type&&(t.type="pointerout"),t.type.startsWith("mouse")&&(t.type=t.type.replace("mouse","pointer")),t.type.startsWith("touch")&&(t.type=Xa[t.type]||t.type),t}},{key:"normalizeWheelEvent",value:function(t){var e=this.rootWheelEvent;this.transferMouseData(e,t),e.deltaMode=t.deltaMode,e.deltaX=t.deltaX,e.deltaY=t.deltaY,e.deltaZ=t.deltaZ;var n=this.context.eventService.client2Viewport({x:t.clientX,y:t.clientY}),r=n.x,i=n.y;e.viewport.x=r,e.viewport.y=i;var o=this.context.eventService.viewport2Canvas(e.viewport),a=o.x,s=o.y;return e.canvas.x=a,e.canvas.y=s,e.global.copyFrom(e.canvas),e.offset.copyFrom(e.canvas),e.nativeEvent=t,e.type=t.type,e}},{key:"transferMouseData",value:function(t,e){t.isTrusted=e.isTrusted,t.srcElement=e.srcElement,t.timeStamp=Ka.now(),t.type=e.type,t.altKey=e.altKey,t.metaKey=e.metaKey,t.shiftKey=e.shiftKey,t.ctrlKey=e.ctrlKey,t.button=e.button,t.buttons=e.buttons,t.client.x=e.clientX,t.client.y=e.clientY,t.movement.x=e.movementX,t.movement.y=e.movementY,t.page.x=e.pageX,t.page.y=e.pageY,t.screen.x=e.screenX,t.screen.y=e.screenY,t.relatedTarget=null}},{key:"setCursor",value:function(t){this.context.contextService.applyCursorStyle(t||this.context.config.cursor||"default")}},{key:"normalizeToPointerEvent",value:function(t,e){var n=[];if(e.isTouchEvent(t))for(var r=0;r-1,a=0,s=r.length;a1&&void 0!==arguments[1]&&arguments[1];if(t.isConnected){var n=t.rBushNode;n.aabb&&this.rBush.remove(n.aabb);var r=t.getRenderBounds();if(r){var i=t.renderable;e&&(i.dirtyRenderBounds||(i.dirtyRenderBounds=new Er),i.dirtyRenderBounds.update(r.center,r.halfExtents));var o=b(r.getMin(),2),a=o[0],s=o[1],l=b(r.getMax(),2),u=l[0],c=l[1];n.aabb||(n.aabb={}),n.aabb.displayObject=t,n.aabb.minX=a,n.aabb.minY=s,n.aabb.maxX=u,n.aabb.maxY=c}return n.aabb&&!(isNaN(n.aabb.maxX)||isNaN(n.aabb.maxX)||isNaN(n.aabb.minX)||isNaN(n.aabb.minY))?n.aabb:void 0}}},{key:"syncRTree",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(e||!this.syncing&&0!==this.syncTasks.size){this.syncing=!0;var n=[],r=new Set,i=function(i){if(!r.has(i)&&i.renderable){var o=t.syncNode(i,e);o&&(n.push(o),r.add(i))}};this.syncTasks.forEach((function(t,e){t&&e.forEach(i);for(var n=e;n;)i(n),n=n.parentElement})),this.rBush.load(n),n.length=0,this.syncing=!1}}}])}();du.tag="Prepare";var fu=function(t){return t.READY="ready",t.BEFORE_RENDER="beforerender",t.RERENDER="rerender",t.AFTER_RENDER="afterrender",t.BEFORE_DESTROY="beforedestroy",t.AFTER_DESTROY="afterdestroy",t.RESIZE="resize",t.DIRTY_RECTANGLE="dirtyrectangle",t.RENDERER_CHANGED="rendererchanged",t}({}),pu=new zs(Ks.MOUNTED),gu=new zs(Ks.UNMOUNTED),vu=new zs(fu.BEFORE_RENDER),mu=new zs(fu.RERENDER),yu=new zs(fu.AFTER_RENDER),bu=function(t){function e(t){var n;s(this,e),(n=v(this,e)).Element=zl,n.inited=!1,n.context={};var r=t.container,i=t.canvas,o=t.renderer,l=t.width,u=t.height,c=t.background,h=t.cursor,d=t.supportsMutipleCanvasesInOneContainer,f=t.cleanUpOnDestroy,p=void 0===f||f,g=t.offscreenCanvas,m=t.devicePixelRatio,y=t.requestAnimationFrame,b=t.cancelAnimationFrame,x=t.createImage,E=t.supportsTouchEvents,w=t.supportsPointerEvents,k=t.isTouchEvent,M=t.isMouseEvent,S=t.dblClickSpeed,N=l,O=u,T=m||Ha&&window.devicePixelRatio||1;return T=T>=1?Math.ceil(T):1,i&&(N=l||function(t){var e=qa(t,"width");return"auto"===e?t.offsetWidth:parseFloat(e)}(i)||i.width/T,O=u||function(t){var e=qa(t,"height");return"auto"===e?t.offsetHeight:parseFloat(e)}(i)||i.height/T),n.customElements=new au,n.devicePixelRatio=T,n.requestAnimationFrame=null!=y?y:ls.bind(Ol.globalThis),n.cancelAnimationFrame=null!=b?b:us.bind(Ol.globalThis),n.supportsTouchEvents=null!=E?E:"ontouchstart"in Ol.globalThis,n.supportsPointerEvents=null!=w?w:!!Ol.globalThis.PointerEvent,n.isTouchEvent=null!=k?k:function(t){return n.supportsTouchEvents&&t instanceof Ol.globalThis.TouchEvent},n.isMouseEvent=null!=M?M:function(t){return!Ol.globalThis.MouseEvent||t instanceof Ol.globalThis.MouseEvent&&(!n.supportsPointerEvents||!(t instanceof Ol.globalThis.PointerEvent))},g&&(Ol.offscreenCanvas=g),n.document=new su,n.document.defaultView=n,d||function(t,e,n){if(t){var r="string"==typeof t?document.getElementById(t):t;Wa.has(r)&&Wa.get(r).destroy(n),Wa.set(r,e)}}(r,n,p),n.initRenderingContext(a(a({},t),{},{width:N,height:O,background:null!=c?c:"transparent",cursor:null!=h?h:"default",cleanUpOnDestroy:p,devicePixelRatio:T,requestAnimationFrame:n.requestAnimationFrame,cancelAnimationFrame:n.cancelAnimationFrame,supportsTouchEvents:n.supportsTouchEvents,supportsPointerEvents:n.supportsPointerEvents,isTouchEvent:n.isTouchEvent,isMouseEvent:n.isMouseEvent,dblClickSpeed:null!=S?S:200,createImage:null!=x?x:function(){return new window.Image}})),n.initDefaultCamera(N,O,o.clipSpaceNearZ),n.initRenderer(o,!0),n}return y(e,t),u(e,[{key:"initRenderingContext",value:function(t){this.context.config=t,this.context.renderingContext={root:this.document.documentElement,renderListCurrentFrame:[],unculledEntities:[],renderReasons:new Set,force:!1,dirty:!1}}},{key:"initDefaultCamera",value:function(t,e,n){var r=this,i=new Ol.CameraContribution;i.clipSpaceNearZ=n,i.setType($r.EXPLORING,Yr.DEFAULT).setPosition(t/2,e/2,500).setFocalPoint(t/2,e/2,0).setOrthographic(t/-2,t/2,e/2,e/-2,.1,1e3),i.canvas=this,i.eventEmitter.on(Xr,(function(){r.context.renderingContext.renderReasons.add($s.CAMERA_CHANGED),Ol.enableSizeAttenuation&&r.getConfig().renderer.getConfig().enableSizeAttenuation&&r.updateSizeAttenuation()})),this.context.camera=i}},{key:"updateSizeAttenuation",value:function(){var t=this.getCamera().getZoom();this.document.documentElement.forEach((function(e){Ol.styleValueRegistry.updateSizeAttenuation(e,t)}))}},{key:"getConfig",value:function(){return this.context.config}},{key:"getRoot",value:function(){return this.document.documentElement}},{key:"getCamera",value:function(){return this.context.camera}},{key:"getContextService",value:function(){return this.context.contextService}},{key:"getEventService",value:function(){return this.context.eventService}},{key:"getRenderingService",value:function(){return this.context.renderingService}},{key:"getRenderingContext",value:function(){return this.context.renderingContext}},{key:"getStats",value:function(){return this.getRenderingService().getStats()}},{key:"ready",get:function(){var t=this;return this.readyPromise||(this.readyPromise=new Promise((function(e){t.resolveReadyPromise=function(){e(t)}})),this.inited&&this.resolveReadyPromise()),this.readyPromise}},{key:"destroy",value:function(){var t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],e=arguments.length>1?arguments[1]:void 0;_i.clearCache(),e||this.dispatchEvent(new zs(fu.BEFORE_DESTROY)),this.frameId&&this.cancelAnimationFrame(this.frameId);var n=this.getRoot();t&&(this.unmountChildren(n),this.document.destroy(),this.getEventService().destroy()),this.getRenderingService().destroy(),this.getContextService().destroy(),this.context.rBushRoot&&this.context.rBushRoot.clear(),e||this.dispatchEvent(new zs(fu.AFTER_DESTROY));var r=function(t){t.currentTarget=null,t.manager=null,t.target=null,t.relatedNode=null};r(pu),r(gu),r(vu),r(mu),r(yu),r(jl),r(Pl),r(Rl),r(Dl)}},{key:"changeSize",value:function(t,e){this.resize(t,e)}},{key:"resize",value:function(t,e){var n=this.context.config;n.width=t,n.height=e,this.getContextService().resize(t,e);var r=this.context.camera,i=r.getProjectionMode();r.setPosition(t/2,e/2,500).setFocalPoint(t/2,e/2,0),i===qr.ORTHOGRAPHIC?r.setOrthographic(t/-2,t/2,e/2,e/-2,r.getNear(),r.getFar()):r.setAspect(t/e),this.dispatchEvent(new zs(fu.RESIZE,{width:t,height:e}))}},{key:"appendChild",value:function(t,e){return this.document.documentElement.appendChild(t,e)}},{key:"insertBefore",value:function(t,e){return this.document.documentElement.insertBefore(t,e)}},{key:"removeChild",value:function(t){return this.document.documentElement.removeChild(t)}},{key:"removeChildren",value:function(){this.document.documentElement.removeChildren()}},{key:"destroyChildren",value:function(){this.document.documentElement.destroyChildren()}},{key:"render",value:function(t){var e=this;t&&(vu.detail=t,yu.detail=t),this.dispatchEvent(vu),this.getRenderingService().render(this.getConfig(),t,(function(){e.dispatchEvent(mu)})),this.dispatchEvent(yu)}},{key:"run",value:function(){var t=this,e=function(n,r){t.render(r),t.frameId=t.requestAnimationFrame(e)};e()}},{key:"initRenderer",value:function(t){var e=this,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(!t)throw new Error("Renderer is required.");this.inited=!1,this.readyPromise=void 0,this.context.rBushRoot=new cr,this.context.renderingPlugins=[],this.context.renderingPlugins.push(new uu,new du,new lu([new hu])),this.loadRendererContainerModule(t),this.context.contextService=new this.context.ContextService(a(a({},Ol),this.context)),this.context.renderingService=new Ys(Ol,this.context),this.context.eventService=new Hs(Ol,this.context),this.context.eventService.init(),this.context.contextService.init?(this.context.contextService.init(),this.initRenderingService(t,n,!0)):this.context.contextService.initAsync().then((function(){e.initRenderingService(t,n)})).catch((function(t){console.error(t)}))}},{key:"initRenderingService",value:function(t){var e=this,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=arguments.length>2&&void 0!==arguments[2]&&arguments[2];this.context.renderingService.init((function(){e.inited=!0,n?r?e.requestAnimationFrame((function(){e.dispatchEvent(new zs(fu.READY))})):e.dispatchEvent(new zs(fu.READY)):e.dispatchEvent(new zs(fu.RENDERER_CHANGED)),e.readyPromise&&e.resolveReadyPromise(),n||e.getRoot().forEach((function(t){var e=t.renderable;e&&(e.renderBoundsDirty=!0,e.boundsDirty=!0,e.dirty=!0)})),e.mountChildren(e.getRoot()),t.getConfig().enableAutoRendering&&e.run()}))}},{key:"loadRendererContainerModule",value:function(t){var e=this;t.getPlugins().forEach((function(t){t.context=e.context,t.init(Ol)}))}},{key:"setRenderer",value:function(t){var e=this.getConfig();if(e.renderer!==t){var n=e.renderer;e.renderer=t,this.destroy(!1,!0),d((null==n?void 0:n.getPlugins())||[]).reverse().forEach((function(t){t.destroy(Ol)})),this.initRenderer(t)}}},{key:"setCursor",value:function(t){this.getConfig().cursor=t,this.getContextService().applyCursorStyle(t)}},{key:"unmountChildren",value:function(t){var e=this;t.childNodes.forEach((function(t){e.unmountChildren(t)})),this.inited&&(t.isMutationObserved?t.dispatchEvent(gu):(gu.target=t,this.dispatchEvent(gu,!0)),t!==this.document.documentElement&&(t.ownerDocument=null),t.isConnected=!1),t.isCustomElement&&t.disconnectedCallback&&t.disconnectedCallback()}},{key:"mountChildren",value:function(t){var e=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:Za(t);this.inited?t.isConnected||(t.ownerDocument=this.document,t.isConnected=!0,n||(t.isMutationObserved?t.dispatchEvent(pu):(pu.target=t,this.dispatchEvent(pu,!0)))):console.warn("[g]: You are trying to call `canvas.appendChild` before canvas' initialization finished. You can either await `canvas.ready` or listen to `CanvasEvent.READY` manually.","appended child: ",t.nodeName),t.childNodes.forEach((function(t){e.mountChildren(t,n)})),t.isCustomElement&&t.connectedCallback&&t.connectedCallback()}},{key:"mountFragment",value:function(t){this.mountChildren(t,!1)}},{key:"client2Viewport",value:function(t){return this.getEventService().client2Viewport(t)}},{key:"viewport2Client",value:function(t){return this.getEventService().viewport2Client(t)}},{key:"viewport2Canvas",value:function(t){return this.getEventService().viewport2Canvas(t)}},{key:"canvas2Viewport",value:function(t){return this.getEventService().canvas2Viewport(t)}},{key:"getPointByClient",value:function(t,e){return this.client2Viewport({x:t,y:e})}},{key:"getClientByPoint",value:function(t,e){return this.viewport2Client({x:t,y:e})}}])}(Vs),xu=function(t){function e(){var t;s(this,e);for(var n=arguments.length,r=new Array(n),i=0;i90)return this;this.computeMatrix()}return this._getAxes(),this.type===$r.ORBITING||this.type===$r.EXPLORING?this._getPosition():this.type===$r.TRACKING&&this._getFocalPoint(),this._update(),this}},{key:"pan",value:function(t,e){var n=Pr(t,e,0),r=dt(this.position);return mt(r,r,bt(ht(),this.right,n[0])),mt(r,r,bt(ht(),this.up,n[1])),this._setPosition(r),this.triggerUpdate(),this}},{key:"dolly",value:function(t){var e=this.forward,n=dt(this.position),r=this.dollyingStep,i=this.distance+t*this.dollyingStep;return r=Math.max(Math.min(i,this.maxDistance),this.minDistance)-this.distance,n[0]+=r*e[0],n[1]+=r*e[1],n[2]+=r*e[2],this._setPosition(n),this.type===$r.ORBITING||this.type===$r.EXPLORING?this._getDistance():this.type===$r.TRACKING&&mt(this.focalPoint,n,this.distanceVector),this.triggerUpdate(),this}},{key:"cancelLandmarkAnimation",value:function(){void 0!==this.landmarkAnimationID&&this.canvas.cancelAnimationFrame(this.landmarkAnimationID)}},{key:"createLandmark",value:function(t){var e,n,r,i,o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},a=o.position,s=void 0===a?this.position:a,l=o.focalPoint,u=void 0===l?this.focalPoint:l,c=o.roll,h=o.zoom,d=new Ol.CameraContribution;d.setType(this.type,void 0),d.setPosition(s[0],null!==(e=s[1])&&void 0!==e?e:this.position[1],null!==(n=s[2])&&void 0!==n?n:this.position[2]),d.setFocalPoint(u[0],null!==(r=u[1])&&void 0!==r?r:this.focalPoint[1],null!==(i=u[2])&&void 0!==i?i:this.focalPoint[2]),d.setRoll(null!=c?c:this.roll),d.setZoom(null!=h?h:this.zoom);var f={name:t,matrix:C(d.getWorldTransform()),right:dt(d.right),up:dt(d.up),forward:dt(d.forward),position:dt(d.getPosition()),focalPoint:dt(d.getFocalPoint()),distanceVector:dt(d.getDistanceVector()),distance:d.getDistance(),dollyingStep:d.getDollyingStep(),azimuth:d.getAzimuth(),elevation:d.getElevation(),roll:d.getRoll(),relAzimuth:d.relAzimuth,relElevation:d.relElevation,relRoll:d.relRoll,zoom:d.getZoom()};return this.landmarks.push(f),f}},{key:"gotoLandmark",value:function(t){var e=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=ne(t)?this.landmarks.find((function(e){return e.name===t})):t;if(r){var i=ae(n)?{duration:n}:n,o=i.easing,a=void 0===o?"linear":o,s=i.duration,l=void 0===s?100:s,u=i.easingFunction,c=void 0===u?void 0:u,h=i.onfinish,d=void 0===h?void 0:h,f=i.onframe,p=void 0===f?void 0:f;this.cancelLandmarkAnimation();var g,v=r.position,m=r.focalPoint,y=r.zoom,b=r.roll,x=c||Ol.EasingFunction(a),E=function(){e.setFocalPoint(m),e.setPosition(v),e.setRoll(b),e.setZoom(y),e.computeMatrix(),e.triggerUpdate(),null==d||d()};if(0===l)return E();var w=function(t){void 0===g&&(g=t);var n=t-g;if(n>=l)E();else{var r,i,o=x(n/l),a=ht(),s=ht();if(kt(a,e.focalPoint,m,o),kt(s,e.position,v,o),i=e.roll*(1-o)+b*o,r=e.zoom*(1-o)+y*o,e.setFocalPoint(a),e.setPosition(s),e.setRoll(i),e.setZoom(r),Ot(a,m)+Ot(s,v)<=.01&&void 0===y&&void 0===b)return E();e.computeMatrix(),e.triggerUpdate(),n0&&Number(this._currentTime)>=this._totalDuration||this._playbackRate<0&&Number(this._currentTime)<=0)}},{key:"totalDuration",get:function(){return this._totalDuration}},{key:"_needsTick",get:function(){return this.pending||"running"===this.playState||!this._finishedFlag}},{key:"updatePromises",value:function(){var t;if(null!==(t=this.effect.target)&&void 0!==t&&t.destroyed)return this.readyPromise=void 0,this.finishedPromise=void 0,!1;var e=this.oldPlayState,n=this.pending?"pending":this.playState;return this.readyPromise&&n!==e&&("idle"===n?(this.rejectReadyPromise(),this.readyPromise=void 0):"pending"===e?this.resolveReadyPromise():"pending"===n&&(this.readyPromise=void 0)),this.finishedPromise&&n!==e&&("idle"===n?(this.rejectFinishedPromise(),this.finishedPromise=void 0):"finished"===n?this.resolveFinishedPromise():"finished"===e&&(this.finishedPromise=void 0)),this.oldPlayState=n,this.readyPromise||this.finishedPromise}},{key:"play",value:function(){this.updatePromises(),this._paused=!1,(this._isFinished||this._idle)&&(this.rewind(),this._startTime=null),this._finishedFlag=!1,this._idle=!1,this.ensureAlive(),this.timeline.applyDirtiedAnimation(this),-1===this.timeline.animations.indexOf(this)&&this.timeline.animations.push(this),this.updatePromises()}},{key:"pause",value:function(){this.updatePromises(),this.currentTime&&(this._holdTime=this.currentTime),this._isFinished||this._paused||this._idle?this._idle&&(this.rewind(),this._idle=!1):this.currentTimePending=!0,this._startTime=null,this._paused=!0,this.updatePromises()}},{key:"finish",value:function(){this.updatePromises(),this._idle||(this.currentTime=this._playbackRate>0?this._totalDuration:0,this._startTime=this._totalDuration-this.currentTime,this.currentTimePending=!1,this.timeline.applyDirtiedAnimation(this),this.updatePromises())}},{key:"cancel",value:function(){var t=this;if(this.updatePromises(),this._inEffect&&(this._inEffect=!1,this._idle=!0,this._paused=!1,this._finishedFlag=!0,this._currentTime=0,this._startTime=null,this.effect.update(null),this.timeline.applyDirtiedAnimation(this),this.updatePromises(),this.oncancel)){var e=new Eu(null,this,this.currentTime,null);setTimeout((function(){t.oncancel(e)}))}}},{key:"reverse",value:function(){this.updatePromises();var t=this.currentTime;this.playbackRate*=-1,this.play(),null!==t&&(this.currentTime=t),this.updatePromises()}},{key:"updatePlaybackRate",value:function(t){this.playbackRate=t}},{key:"targetAnimations",value:function(){var t;return(null===(t=this.effect)||void 0===t?void 0:t.target).getAnimations()}},{key:"markTarget",value:function(){var t=this.targetAnimations();-1===t.indexOf(this)&&t.push(this)}},{key:"unmarkTarget",value:function(){var t=this.targetAnimations(),e=t.indexOf(this);-1!==e&&t.splice(e,1)}},{key:"tick",value:function(t,e){this._idle||this._paused||(null===this._startTime?e&&(this.startTime=t-this._currentTime/this.playbackRate):this._isFinished||this.tickCurrentTime((t-this._startTime)*this.playbackRate)),e&&(this.currentTimePending=!1,this.fireEvents(t))}},{key:"rewind",value:function(){if(this.playbackRate>=0)this.currentTime=0;else{if(!(this._totalDuration<1/0))throw new Error("Unable to rewind negative playback rate animation with infinite duration");this.currentTime=this._totalDuration}}},{key:"persist",value:function(){throw new Error(Or)}},{key:"addEventListener",value:function(t,e,n){throw new Error(Or)}},{key:"removeEventListener",value:function(t,e,n){throw new Error(Or)}},{key:"dispatchEvent",value:function(t){throw new Error(Or)}},{key:"commitStyles",value:function(){throw new Error(Or)}},{key:"ensureAlive",value:function(){var t,e;this.playbackRate<0&&0===this.currentTime?this._inEffect=!(null===(t=this.effect)||void 0===t||!t.update(-1)):this._inEffect=!(null===(e=this.effect)||void 0===e||!e.update(this.currentTime));this._inTimeline||!this._inEffect&&this._finishedFlag||(this._inTimeline=!0,this.timeline.animations.push(this))}},{key:"tickCurrentTime",value:function(t,e){t!==this._currentTime&&(this._currentTime=t,this._isFinished&&!e&&(this._currentTime=this._playbackRate>0?this._totalDuration:0),this.ensureAlive())}},{key:"fireEvents",value:function(t){var e=this;if(this._isFinished){if(!this._finishedFlag){if(this.onfinish){var n=new Eu(null,this,this.currentTime,t);setTimeout((function(){e.onfinish&&e.onfinish(n)}))}this._finishedFlag=!0}}else{if(this.onframe&&"running"===this.playState){var r=new Eu(null,this,this.currentTime,t);this.onframe(r)}this._finishedFlag=!1}}}])}(),Mu=.1,Su="function"==typeof Float32Array,Nu=function(t,e){return 1-3*e+3*t},Ou=function(t,e){return 3*e-6*t},Tu=function(t){return 3*t},Cu=function(t,e,n){return((Nu(e,n)*t+Ou(e,n))*t+Tu(e))*t},Au=function(t,e,n){return 3*Nu(e,n)*t*t+2*Ou(e,n)*t+Tu(e)},Pu=function(t,e,n,r){if(!(t>=0&&t<=1&&n>=0&&n<=1))throw new Error("bezier x values must be in [0, 1] range");if(t===e&&n===r)return function(t){return t};for(var i=Su?new Float32Array(11):new Array(11),o=0;o<11;++o)i[o]=Cu(o*Mu,t,n);var a=function(e){for(var r=0,o=1;10!==o&&i[o]<=e;++o)r+=Mu;--o;var a=r+(e-i[o])/(i[o+1]-i[o])*Mu,s=Au(a,t,n);return s>=.001?function(t,e,n,r){for(var i=0;i<4;++i){var o=Au(e,n,r);if(0===o)return e;e-=(Cu(e,n,r)-t)/o}return e}(e,a,t,n):0===s?a:function(t,e,n,r,i){var o,a,s=0;do{(o=Cu(a=e+(n-e)/2,r,i)-t)>0?n=a:e=a}while(Math.abs(o)>1e-7&&++s<10);return a}(e,r,r+Mu,t,n)};return function(t){return 0===t||1===t?t:Cu(a(t),e,r)}},Ru=function(t){return Math.pow(t,2)},Du=function(t){return Math.pow(t,3)},Lu=function(t){return Math.pow(t,4)},_u=function(t){return Math.pow(t,5)},Iu=function(t){return Math.pow(t,6)},ju=function(t){return 1-Math.cos(t*Math.PI/2)},Bu=function(t){return 1-Math.sqrt(1-t*t)},Fu=function(t){return t*t*(3*t-2)},zu=function(t){for(var e,n=4;t<((e=Math.pow(2,--n))-1)/11;);return 1/Math.pow(4,3-n)-7.5625*Math.pow((3*e-2)/22-t,2)},Gu=function(t){var e=b(arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],2),n=e[0],r=void 0===n?1:n,i=e[1],o=void 0===i?.5:i,a=oe(Number(r),1,10),s=oe(Number(o),.1,2);return 0===t||1===t?t:-a*Math.pow(2,10*(t-1))*Math.sin((t-1-s/(2*Math.PI)*Math.asin(1/a))*(2*Math.PI)/s)},Vu=function(t){var e=arguments.length>2?arguments[2]:void 0,n=b(arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],4),r=n[0],i=void 0===r?1:r,o=n[1],a=void 0===o?100:o,s=n[2],l=void 0===s?10:s,u=n[3],c=void 0===u?0:u;i=oe(i,.1,1e3),a=oe(a,.1,1e3),l=oe(l,.1,1e3),c=oe(c,.1,1e3);var h=Math.sqrt(a/i),d=l/(2*Math.sqrt(a*i)),f=d<1?h*Math.sqrt(1-d*d):0,p=d<1?(d*h-c)/f:-c+h,g=e?e*t/1e3:t;return g=d<1?Math.exp(-g*d*h)*(1*Math.cos(f*g)+p*Math.sin(f*g)):(1+p*g)*Math.exp(-g*h),0===t||1===t?t:1-g},Wu=function(t){var e=b(arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],2),n=e[0],r=void 0===n?10:n;return("start"===e[1]?Math.ceil:Math.floor)(oe(t,0,1)*r)/r},Hu=function(t){var e=b(arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],4),n=e[0],r=e[1],i=e[2],o=e[3];return Pu(n,r,i,o)(t)},Uu=Pu(.42,0,1,1),$u=function(t){return function(e){return 1-t(1-e,arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],arguments.length>2?arguments[2]:void 0)}},Yu=function(t){return function(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],r=arguments.length>2?arguments[2]:void 0;return e<.5?t(2*e,n,r)/2:1-t(-2*e+2,n,r)/2}},qu=function(t){return function(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],r=arguments.length>2?arguments[2]:void 0;return e<.5?(1-t(1-2*e,n,r))/2:(t(2*e-1,n,r)+1)/2}},Xu={steps:Wu,"step-start":function(t){return Wu(t,[1,"start"])},"step-end":function(t){return Wu(t,[1,"end"])},linear:function(t){return t},"cubic-bezier":Hu,ease:function(t){return Hu(t,[.25,.1,.25,1])},in:Uu,out:$u(Uu),"in-out":Yu(Uu),"out-in":qu(Uu),"in-quad":Ru,"out-quad":$u(Ru),"in-out-quad":Yu(Ru),"out-in-quad":qu(Ru),"in-cubic":Du,"out-cubic":$u(Du),"in-out-cubic":Yu(Du),"out-in-cubic":qu(Du),"in-quart":Lu,"out-quart":$u(Lu),"in-out-quart":Yu(Lu),"out-in-quart":qu(Lu),"in-quint":_u,"out-quint":$u(_u),"in-out-quint":Yu(_u),"out-in-quint":qu(_u),"in-expo":Iu,"out-expo":$u(Iu),"in-out-expo":Yu(Iu),"out-in-expo":qu(Iu),"in-sine":ju,"out-sine":$u(ju),"in-out-sine":Yu(ju),"out-in-sine":qu(ju),"in-circ":Bu,"out-circ":$u(Bu),"in-out-circ":Yu(Bu),"out-in-circ":qu(Bu),"in-back":Fu,"out-back":$u(Fu),"in-out-back":Yu(Fu),"out-in-back":qu(Fu),"in-bounce":zu,"out-bounce":$u(zu),"in-out-bounce":Yu(zu),"out-in-bounce":qu(zu),"in-elastic":Gu,"out-elastic":$u(Gu),"in-out-elastic":Yu(Gu),"out-in-elastic":qu(Gu),spring:Vu,"spring-in":Vu,"spring-out":$u(Vu),"spring-in-out":Yu(Vu),"spring-out-in":qu(Vu)},Ku=function(t){return t};function Zu(t,e){return function(n){if(n>=1)return 1;var r=1/t;return(n+=e*r)-n%r}}var Qu="\\s*(-?\\d+\\.?\\d*|-?\\.\\d+)\\s*",Ju=new RegExp("cubic-bezier\\(".concat(Qu,",").concat(Qu,",").concat(Qu,",").concat(Qu,"\\)")),tc=/steps\(\s*(\d+)\s*\)/,ec=/steps\(\s*(\d+)\s*,\s*(start|middle|end)\s*\)/;function nc(t){var e=Ju.exec(t);if(e)return Pu.apply(void 0,d(e.slice(1).map(Number)));var n=tc.exec(t);if(n)return Zu(Number(n[1]),0);var r=ec.exec(t);return r?Zu(Number(r[1]),{start:1,middle:.5,end:0}[r[2]]):Xu[function(t){return function(t){return"-"===(t=t.replace(/([A-Z])/g,(function(t){return"-".concat(t.toLowerCase())}))).charAt(0)?t.substring(1):t}(t).replace(/^ease-/,"").replace(/(\(|\s).+/,"").toLowerCase().trim()}(t)]||Xu.linear}function rc(t){return Math.abs(function(t){var e;if(0===t.duration||0===t.iterations)return 0;return("auto"===t.duration?0:Number(t.duration))*(null!==(e=t.iterations)&&void 0!==e?e:1)}(t)/(t.playbackRate||1))}function ic(t,e,n){var r=function(t,e,n){if(null===e)return 0;var r=n.endTime;return e=Math.min(n.delay+t+n.endDelay,r)?2:3}(t,e,n),i=function(t,e,n,r,i){switch(r){case 1:return"backwards"===e||"both"===e?0:null;case 3:return n-i;case 2:return"forwards"===e||"both"===e?t:null;case 0:return null}}(t,n.fill,e,r,n.delay);if(null===i)return null;var o="auto"===n.duration?0:n.duration,a=function(t,e,n,r,i){var o=i;return 0===t?1!==e&&(o+=n):o+=r/t,o}(o,r,n.iterations,i,n.iterationStart),s=function(t,e,n,r,i,o){var a=t===1/0?e%1:t%1;return 0!==a||2!==n||0===r||0===i&&0!==o||(a=1),a}(a,n.iterationStart,r,n.iterations,i,o),l=function(t,e,n,r){return 2===t&&e===1/0?1/0:1===n?Math.floor(r)-1:Math.floor(r)}(r,n.iterations,s,a),u=function(t,e,n){var r=t;if("normal"!==t&&"reverse"!==t){var i=e;"alternate-reverse"===t&&(i+=1),r="normal",i!==1/0&&i%2!=0&&(r="reverse")}return"normal"===r?n:1-n}(n.direction,l,s);return n.currentIteration=l,n.progress=u,n.easingFunction(u)}function oc(t,e,n){var r=function(t,e){for(var n={},r=0;r=t.applyFrom&&e1)throw new Error("Keyframe offsets must be between 0 and 1.");n.computedOffset=i}}else if("composite"===r&&-1===["replace","add","accumulate","auto"].indexOf(i))throw new Error("".concat(i," compositing is not supported"));n[r]=i}return void 0===n.offset&&(n.offset=null),void 0===n.easing&&(n.easing=(null==e?void 0:e.easing)||"linear"),void 0===n.composite&&(n.composite="auto"),n})),r=!0,i=-1/0,o=0;o=0&&Number(t.offset)<=1})),r||function(){var t,e,r=n.length;n[r-1].computedOffset=Number(null!==(t=n[r-1].offset)&&void 0!==t?t:1),r>1&&(n[0].computedOffset=Number(null!==(e=n[0].offset)&&void 0!==e?e:0));for(var i=0,o=Number(n[0].computedOffset),a=1;a{console.warn(_c(t))};function jc(e){const{theme:n}=e;if(!n)return{};const r=Dc(t.ExtensionCategory.THEME,n);return r||(Ic(`The theme of ${n} is not registered.`),{})}function Bc(t,e){if(Array.isArray(t)&&0===t.length)return null;const n=Array.isArray(t)?t[0]:t,r=Array.isArray(t)?t.slice(1):e||[];return new Proxy(n,{get:(t,e)=>"function"!=typeof t[e]||["onframe","onfinish"].includes(e)?"finished"===e?Promise.all([n.finished,...r.map((t=>t.finished))]):Reflect.get(t,e):(...n)=>{t[e](...n),r.forEach((t=>{var r;return null===(r=t[e])||void 0===r?void 0:r.call(t,...n)}))},set:(t,e,n)=>(["onframe","onfinish"].includes(e)||r.forEach((t=>{t[e]=n})),Reflect.set(t,e,n))})}function Fc(t){const e=t.reduce(((t,e)=>(Object.entries(e).forEach((([e,n])=>{void 0===t[e]?t[e]=[n]:t[e].push(n)})),t)),{});Object.entries(e).forEach((([n,r])=>{(r.length!==t.length||r.some((t=>$t(t)))||r.every((t=>!["sourceNode","targetNode","childrenNode"].includes(n)&&Ne(t,r[0]))))&&delete e[n]}));const n=Object.entries(e).reduce(((t,[e,n])=>(n.forEach(((n,r)=>{t[r]?t[r][e]=n:t[r]={[e]:n}})),t)),[]);return 0!==t.length&&0===n.length&&n.push({_:0},{_:0}),n}function zc(t){switch(t){case"opacity":return 1;case"x":case"y":case"z":case"zIndex":return 0;case"visibility":return"visible";case"collapsed":return!1;case"states":return[];default:return}}function Gc(t,e){const{animation:n}=t;if(!1===n||!1===e)return!1;const r=Object.assign({},yc);return qt(n)&&Object.assign(r,n),qt(e)&&Object.assign(r,e),r}function Vc(e,n,r,i){var o,a;const{animation:s}=e;if(!1===s||!1===i)return[];const l=null===(o=null==e?void 0:e[n])||void 0===o?void 0:o.animation;if(!1===l)return[];const u=null==l?void 0:l[r];if(!1===u)return[];const c=null===(a=jc(e)[n])||void 0===a?void 0:a.animation,h=(e=[])=>function(e){if("string"==typeof e){return Dc(t.ExtensionCategory.ANIMATION,e)||(Ic(`The animation of ${e} is not registered.`),[])}return e}(e).map((t=>Object.assign(Object.assign(Object.assign(Object.assign({},bc),qt(s)&&s),t),qt(i)&&i)));if(u)return h(u);if(!c)return[];const d=c[r];return!1===d?[]:h(d)}function Wc(t,e,n,r=[]){if(!r&&0===t&&0===e&&0===n)return null;if(Array.isArray(r)){let i=-1;const o=[];for(let a=0;a{if(!n.length)return null;const[r,i]=e;let o;const a=n.map((e=>{var{fields:n,shape:a,states:s}=e,l=Fe(e,["fields","shape","states"]);const u=(e=>{var n;if(e){const o=t.getShape(e);if(!o)return null;const a=`get${de(e)}Style`,s=(null===(n=null==t?void 0:t[a])||void 0===n?void 0:n.bind(t))||(t=>t);return{shape:o,fromStyle:(null==s?void 0:s(r))||{},toStyle:(null==s?void 0:s(i))||{}}}return{shape:t,fromStyle:r,toStyle:i}})(a);if(!u)return null;const{shape:c,fromStyle:h,toStyle:d}=u,f=[{},{}];if(n.forEach((t=>{var e,n;Object.assign(f[0],{[t]:null!==(e=h[t])&&void 0!==e?e:zc(t)}),Object.assign(f[1],{[t]:null!==(n=d[t])&&void 0!==n?n:zc(t)})})),f.some((t=>Object.keys(t).some((t=>["x","y","z"].includes(t)))))){const{x:t=0,y:e=0,z:n,transform:r=""}=c.attributes||{};f.forEach((i=>{var o,a,s;i.transform=Wc(null!==(o=i.x)&&void 0!==o?o:t,null!==(a=i.y)&&void 0!==a?a:e,null!==(s=i.z)&&void 0!==s?s:n,r)}))}const p=c.animate(Fc(f),l);return void 0===a&&(o=p),p})).filter(Boolean),s=o||(null==a?void 0:a[0]);return s?Bc(s,a.filter((t=>t!=t))):null},Uc=[{fields:["x","y"]}],$c=Uc,Yc=[{fields:["sourceNode","targetNode"]}],qc=Yc,Xc=[{fields:["childrenNode","x","y"]}],Kc=Xc;function Zc(t){return t instanceof Float32Array||!(!Array.isArray(t)||2!==t.length&&3!==t.length)&&t.every((t=>"number"==typeof t))}function Qc(t,e,n){return t>=e&&t<=n}function Jc(t=0){if(Array.isArray(t)){const[e=0,n=e,r=e,i=n]=t;return[e,n,r,i]}return[t,t,t,t]}function th(t=0){const e=Jc(t);return e[0]+e[2]}function eh(t){return t.max[0]-t.min[0]}function nh(t){return t.max[1]-t.min[1]}function rh(t){return[eh(t),nh(t)]}function ih(t,e){const n=Zc(t)?oh(t):t.getShape("key").getBounds();return e?ah(n,e):n}function oh(t){const[e,n,r=0]=t,i=new Er;return i.setMinMax([e,n,r],[e,n,r]),i}function ah(t,e){const[n,r,i,o]=Jc(e),[a,s,l]=t.min,[u,c,h]=t.max,d=new Er;return d.setMinMax([a-o,s-n,l],[u+r,c+i,h]),d}function sh(t){if(0===t.length)return new Er;if(1===t.length)return t[0];const e=new Er;e.setMinMax(t[0].min,t[0].max);for(let n=1;nu[e.id]+s?(u[a]=u[e.id]+s,c[a]=[e.id]):u[a]===u[e.id]+s&&c[a].push(e.id)}))},f=0;f=this.maxStep},t.prototype.peek=function(){return this.isEmpty()?null:this.linkedList.head.value},t.prototype.push=function(t){this.linkedList.prepend(t),this.length>this.maxStep&&this.linkedList.deleteTail()},t.prototype.pop=function(){var t=this.linkedList.deleteHead();return t?t.value:null},t.prototype.toArray=function(){return this.linkedList.toArray().map((function(t){return t.value}))},t.prototype.clear=function(){for(;!this.isEmpty();)this.pop()}}();const Ch=(t,e,n)=>{var r;switch(n.type){case"degree":{const i=new Map;return null===(r=t.nodes)||void 0===r||r.forEach((t=>{const r=e(Nh(t),n.direction).length;i.set(Nh(t),r)})),i}case"betweenness":return Ph(t,n.directed,n.weightPropertyName);case"closeness":return Rh(t,n.directed,n.weightPropertyName);case"eigenvector":return Lh(t,n.directed);case"pagerank":return Dh(t,n.epsilon,n.linkProb);default:return Ah(t)}},Ah=t=>{var e;const n=new Map;return null===(e=t.nodes)||void 0===e||e.forEach((t=>{n.set(Nh(t),0)})),n},Ph=(t,e,n)=>{const r=Ah(t),{nodes:i=[]}=t;return i.forEach((o=>{i.forEach((i=>{if(o!==i){const{allPath:a}=Sh(t,Nh(o),Nh(i),e,n),s=a.length;a.flat().forEach((t=>{t!==Nh(o)&&t!==Nh(i)&&r.set(t,r.get(t)+1/s)}))}}))})),r},Rh=(t,e,n)=>{const r=new Map,{nodes:i=[]}=t;return i.forEach((o=>{const a=i.reduce(((r,i)=>{if(o!==i){const{length:a}=Sh(t,Nh(o),Nh(i),e,n);r+=a}return r}),0);r.set(Nh(o),1/a)})),r},Dh=(t,e,n)=>{var r;const i=new Map,o=function(t,e,n){"number"!=typeof e&&(e=1e-6),"number"!=typeof n&&(n=.85);for(var r,i=1,o=0,a=1e3,s=t.nodes,l=void 0===s?[]:s,u=t.edges,c=void 0===u?[]:u,h=l.length,d={},f={},p=0;p0&&i>e;){for(o=0,p=0;p0&&(r+=f[b]/x)}d[v]=n*r,o+=d[v]}}for(o=(1-o)/h,i=0,p=0;p{i.set(Nh(t),o[Nh(t)])})),i},Lh=(t,e)=>{const{nodes:n=[]}=t,r=_h(t,e),i=Ih(r,n.length),o=new Map;return n.forEach(((t,e)=>{o.set(Nh(t),i[e])})),o},_h=(t,e)=>{const{nodes:n=[],edges:r=[]}=t,i=Array(n.length).fill(null).map((()=>Array(n.length).fill(0)));return r.forEach((({source:t,target:r})=>{const o=n.findIndex((e=>Nh(e)===t)),a=n.findIndex((t=>Nh(t)===r));e?i[o][a]=1:(i[o][a]=1,i[a][o]=1)})),i},Ih=(t,e,n=100,r=1e-6)=>{let i=Array(e).fill(1),o=1/0;for(let a=0;ar;a++){const n=Array(e).fill(0);for(let r=0;rt+e*e),0));for(let t=0;tt+(e-i[n])*e),0)),i=n}return i};function jh(t,e,n,r=Ne){const i=new Map(t.map((t=>[n(t),t]))),o=new Map(e.map((t=>[n(t),t]))),a=new Set(i.keys()),s=new Set(o.keys()),l=[],u=[],c=[],h=[];return s.forEach((t=>{a.has(t)?r(i.get(t),o.get(t))?h.push(o.get(t)):u.push(o.get(t)):l.push(o.get(t))})),a.forEach((t=>{s.has(t)||c.push(i.get(t))})),{enter:l,exit:c,keep:h,update:u}}function Bh(t,e,n){t.forEach((t=>{(t=>{n&&!n(t)||(t.style.visibility=e)})(t)}))}class Fh{constructor(t){this.extensions=[],this.extensionMap={},this.context=t}setExtensions(t){const e=function(t,e,n){const r={},i=t=>(t in r||(r[t]=0),`${e}-${t}-${r[t]++}`);return n.map((e=>"string"==typeof e?{type:e,key:i(e)}:"function"==typeof e?e.call(t):e.key?e:Object.assign(Object.assign({},e),{key:i(e.type)})))}(this.context.graph,this.category,t),{enter:n,update:r,exit:i,keep:o}=jh(this.extensions,e,(t=>t.key));this.createExtensions(n),this.updateExtensions([...r,...o]),this.destroyExtensions(i),this.extensions=e}createExtension(t){const{category:e}=this,{key:n,type:r}=t,i=Dc(e,r);if(!i)return Ic(`The extension ${r} of ${e} is not registered.`);const o=new i(this.context,t);this.extensionMap[n]=o}createExtensions(t){t.forEach((t=>this.createExtension(t)))}updateExtension(t){const{key:e}=t,n=this.extensionMap[e];n&&n.update(t)}updateExtensions(t){t.forEach((t=>this.updateExtension(t)))}destroyExtension(t){const e=this.extensionMap[t];e&&(e.destroy(),delete this.extensionMap[t])}destroyExtensions(t){t.forEach((({key:t})=>this.destroyExtension(t)))}destroy(){Object.values(this.extensionMap).forEach((t=>t.destroy())),this.context={},this.extensions=[],this.extensionMap={}}}class zh{constructor(t,e){this.events=[],this.destroyed=!1,this.context=t,this.options=e}update(t){this.options=Object.assign(this.options,t)}destroy(){this.context={},this.options={},this.destroyed=!0}}class Gh extends zh{}class Vh extends Gh{constructor(t,e){super(t,Object.assign({},Vh.defaultOptions,e)),this.isOverlapping=(t,e)=>e.some((e=>t.intersects(e))),this.occupiedBounds=[],this.detectLabelCollision=t=>{const e=this.context.viewport,n={show:[],hide:[]};return this.occupiedBounds=[],t.forEach((t=>{const r=t.getShape("label").getRenderBounds();e.isInViewport(r,!0)&&!this.isOverlapping(r,this.occupiedBounds)?(n.show.push(t),this.occupiedBounds.push(ah(r,this.options.padding))):n.hide.push(t)})),n},this.hideLabelIfExceedViewport=(t,e)=>{const{exit:n}=jh(t,e,(t=>t.id));null==n||n.forEach(this.hideLabel)},this.nodeCentralities=new Map,this.sortNodesByCentrality=(t,e)=>{const{model:n}=this.context,r=n.getData(),i=n.getRelatedEdgesData.bind(n);return t.map((t=>(this.nodeCentralities.has(t.id)||(this.nodeCentralities=Ch(r,i,e)),{node:t,centrality:this.nodeCentralities.get(t.id)}))).sort(((t,e)=>e.centrality-t.centrality)).map((t=>t.node))},this.sortLabelElementsInView=t=>{const{sort:e,sortNode:n,sortCombo:r,sortEdge:i}=this.options,{model:o}=this.context;if(Ut(e))return t.sort(((t,n)=>e(o.getElementDataById(t.id),o.getElementDataById(n.id))));const{node:a=[],edge:s=[],combo:l=[]}=ie(t,(t=>t.type)),u=Ut(r)?l.sort(((t,e)=>r(...o.getComboData([t.id,e.id])))):l,c=Ut(n)?a.sort(((t,e)=>n(...o.getNodeData([t.id,e.id])))):this.sortNodesByCentrality(a,n),h=Ut(i)?s.sort(((t,e)=>i(...o.getEdgeData([t.id,e.id])))):s;return[...u,...c,...h]},this.labelElementsInView=[],this.isFirstRender=!0,this.onToggleVisibility=t=>{var e;if("zIndex"===(null===(e=t.data)||void 0===e?void 0:e.stage))return;if(!this.validate(t))return void(this.hiddenElements.size>0&&(this.hiddenElements.forEach(this.showLabel),this.hiddenElements.clear()));const n=this.isFirstRender?this.getLabelElements():this.getLabelElementsInView();this.hideLabelIfExceedViewport(this.labelElementsInView,n),this.labelElementsInView=n;const r=this.sortLabelElementsInView(this.labelElementsInView),{show:i,hide:o}=this.detectLabelCollision(r);for(let t=i.length-1;t>=0;t--)this.showLabel(i[t]);o.forEach(this.hideLabel)},this.hiddenElements=new Map,this.hideLabel=t=>{const e=t.getShape("label");e&&Bh(e,"hidden"),this.hiddenElements.set(t.id,t)},this.showLabel=t=>{const e=t.getShape("label");e&&Bh(e,"visible"),t.toFront(),this.hiddenElements.delete(t.id)},this.onTransform=Re(this.onToggleVisibility,this.options.throttle,{leading:!0}),this.enableToggle=!0,this.toggle=t=>{this.enableToggle&&this.onToggleVisibility(t)},this.onBeforeRender=()=>{this.enableToggle=!1},this.onAfterRender=t=>{this.onToggleVisibility(t),this.enableToggle=!0},this.bindEvents()}update(t){this.unbindEvents(),super.update(t),this.bindEvents(),this.onToggleVisibility({})}getLabelElements(){const{elementMap:t}=this.context.element,e=[];for(const n in t){const r=t[n];r.isVisible()&&r.getShape("label")&&e.push(r)}return e}getLabelElementsInView(){const t=this.context.viewport;return this.getLabelElements().filter((e=>t.isInViewport(e.getShape("key").getRenderBounds())))}bindEvents(){const{graph:e}=this.context;e.on(t.GraphEvent.BEFORE_RENDER,this.onBeforeRender),e.on(t.GraphEvent.AFTER_RENDER,this.onAfterRender),e.on(t.GraphEvent.AFTER_DRAW,this.toggle),e.on(t.GraphEvent.AFTER_LAYOUT,this.toggle),e.on(t.GraphEvent.AFTER_TRANSFORM,this.onTransform)}unbindEvents(){const{graph:e}=this.context;e.off(t.GraphEvent.BEFORE_RENDER,this.onBeforeRender),e.off(t.GraphEvent.AFTER_RENDER,this.onAfterRender),e.off(t.GraphEvent.AFTER_DRAW,this.toggle),e.off(t.GraphEvent.AFTER_LAYOUT,this.toggle),e.off(t.GraphEvent.AFTER_TRANSFORM,this.onTransform)}validate(t){if(this.destroyed)return!1;const{enable:e}=this.options;return Ut(e)?e(t):!!e}destroy(){this.unbindEvents(),super.destroy()}}Vh.defaultOptions={enable:!0,throttle:100,padding:0,sortNode:{type:"degree"}};const Wh=[0,0,0];function Hh(t,e){return t.map(((t,n)=>t+e[n]))}function Uh(t,e){return t.map(((t,n)=>t-e[n]))}function $h(t,e){return"number"==typeof e?t.map((t=>t*e)):t.map(((t,n)=>t*e[n]))}function Yh(t,e){return"number"==typeof e?t.map((t=>t/e)):t.map(((t,n)=>t/e[n]))}function qh(t,e){return t.map((t=>t*e))}function Xh(t,e){return Math.sqrt(t.reduce(((t,n,r)=>t+Math.pow(n-e[r]||0,2)),0))}function Kh(t,e){return t.reduce(((t,n,r)=>t+Math.abs(n-e[r])),0)}function Zh(t){const e=t.reduce(((t,e)=>t+Math.pow(e,2)),0);return t.map((t=>t/Math.sqrt(e)))}function Qh(t,e,n=!1){const r=t[0]*e[1]-t[1]*e[0];let i=Math.acos($h(t,e).reduce(((t,e)=>t+e),0)/(Xh(t,Wh)*Xh(e,Wh)));return n&&r<0&&(i=2*Math.PI-i),i}function Jh(t,e=!0){return e?[-t[1],t[0]]:[t[1],-t[0]]}function td(t,e){return t.map((t=>t%e))}function ed(t){return[t[0],t[1]]}function nd(t){return 2===t.length?[t[0],t[1],0]:t}function rd(t){const[e,n]=t;return e||n?Math.atan2(n,e):0}function id(t,e){const[n,r]=t,[i,o]=e;return function(t,e){const n=nd(t),r=nd(e);return[n[1]*r[2]-n[2]*r[1],n[2]*r[0]-n[0]*r[2],n[0]*r[1]-n[1]*r[0]]}(Uh(n,r),Uh(i,o)).every((t=>0===t))}function od(t,e,n=!1){if(id(t,e))return;const[r,i]=t,[o,a]=e,s=((r[0]-o[0])*(o[1]-a[1])-(r[1]-o[1])*(o[0]-a[0]))/((r[0]-i[0])*(o[1]-a[1])-(r[1]-i[1])*(o[0]-a[0])),l=a[0]-o[0]?(r[0]-o[0]+s*(i[0]-r[0]))/(a[0]-o[0]):(r[1]-o[1]+s*(i[1]-r[1]))/(a[1]-o[1]);return n||Qc(s,0,1)&&Qc(l,0,1)?[r[0]+s*(i[0]-r[0]),r[1]+s*(i[1]-r[1])]:void 0}function ad(t){if(Array.isArray(t))return Qc(t[0],0,1)&&Qc(t[1],0,1)?t:[.5,.5];const e=t.split("-");return[e.includes("left")?0:e.includes("right")?1:.5,e.includes("top")?0:e.includes("bottom")?1:.5]}function sd(t){const{x:e=0,y:n=0,z:r=0}=t.style||{};return[+e,+n,+r]}function ld(t){const{x:e,y:n,z:r}=t.style||{};return void 0!==e||void 0!==n||void 0!==r}function ud(t,e="center"){return function(t,e){const[n,r]=e,{min:i,max:o}=t;return[i[0]+n*(o[0]-i[0]),i[1]+r*(o[1]-i[1])]}(t,ad(e))}function cd(t){var e;return[t.x,t.y,null!==(e=t.z)&&void 0!==e?e:0]}function hd(t){var e;return{x:t[0],y:t[1],z:null!==(e=t[2])&&void 0!==e?e:0}}function dd(t,e=0){return t.map((t=>parseFloat(t.toFixed(e))))}function fd(t,e,n,r=!1){if(Ne(t,e))return t;const i=Zh(r?Uh(t,e):Uh(e,t)),o=[i[0]*n,i[1]*n];return Hh(ed(t),o)}function pd(t,e){return t[1]===e[1]}function gd(t,e,n){return id([t,e],[e,n])}function vd(t,e){return[2*e[0]-t[0],2*e[1]-t[1]]}function md(t,e,n,r=!0,i=!1){for(let o=0;o{const i=function(t,e){const n=xd(t,e);return Xh(t,n)}(t,e);i1?c=1:c<0&&(c=0);return[n+c*l,r+c*u]}function Ed(t,e=!0){const n=function(t){return Yh(t.reduce(((t,e)=>Hh(t,e)),[0,0]),t.length)}(t);return t.sort((([t,r],[i,o])=>{const a=Math.atan2(r-n[1],t-n[0]),s=Math.atan2(o-n[1],i-n[0]);return e?s-a:a-s}))}function wd(t,e){return[t,[t[0],e[1]],e,[e[0],t[1]]]}class kd{constructor(t,e,n){if(this.phase=e,this.pointerByTouch=[],this.initialDistance=null,this.emitter=t,kd.instance)return kd.callbacks[this.phase].push(n),kd.instance;this.onPointerDown=this.onPointerDown.bind(this),this.onPointerMove=this.onPointerMove.bind(this),this.onPointerUp=this.onPointerUp.bind(this),this.bindEvents(),kd.instance=this,kd.callbacks[this.phase].push(n)}bindEvents(){const{emitter:e}=this;e.on(t.CommonEvent.POINTER_DOWN,this.onPointerDown),e.on(t.CommonEvent.POINTER_MOVE,this.onPointerMove),e.on(t.CommonEvent.POINTER_UP,this.onPointerUp)}updatePointerPosition(t,e,n){const r=this.pointerByTouch.findIndex((e=>e.pointerId===t));r>=0&&(this.pointerByTouch[r]={x:e,y:n,pointerId:t})}onPointerDown(t){const{x:e,y:n}=t.client||{};if(void 0!==e&&void 0!==n&&(this.pointerByTouch.push({x:e,y:n,pointerId:t.pointerId}),"touch"===t.pointerType&&2===this.pointerByTouch.length)){kd.isPinching=!0;const e=this.pointerByTouch[0].x-this.pointerByTouch[1].x,n=this.pointerByTouch[0].y-this.pointerByTouch[1].y;this.initialDistance=Math.sqrt(e*e+n*n),kd.callbacks.pinchstart.forEach((e=>e(t,{scale:0})))}}onPointerMove(t){if(2!==this.pointerByTouch.length||null===this.initialDistance)return;const{x:e,y:n}=t.client||{};if(void 0===e||void 0===n)return;this.updatePointerPosition(t.pointerId,e,n);const r=this.pointerByTouch[0].x-this.pointerByTouch[1].x,i=this.pointerByTouch[0].y-this.pointerByTouch[1].y,o=Math.sqrt(r*r+i*i)/this.initialDistance;kd.callbacks.pinchmove.forEach((e=>e(t,{scale:5*(o-1)})))}onPointerUp(t){var e;kd.callbacks.pinchend.forEach((e=>e(t,{scale:0}))),kd.isPinching=!1,this.initialDistance=null,this.pointerByTouch=[],null===(e=kd.instance)||void 0===e||e.tryDestroy()}destroy(){this.emitter.off(t.CommonEvent.POINTER_DOWN,this.onPointerDown),this.emitter.off(t.CommonEvent.POINTER_MOVE,this.onPointerMove),this.emitter.off(t.CommonEvent.POINTER_UP,this.onPointerUp),kd.instance=null}off(t,e){const n=kd.callbacks[t].indexOf(e);n>-1&&kd.callbacks[t].splice(n,1),this.tryDestroy()}tryDestroy(){Object.values(kd.callbacks).every((t=>0===t.length))&&this.destroy()}}kd.isPinching=!1,kd.instance=null,kd.callbacks={pinchstart:[],pinchmove:[],pinchend:[]};const Md=t=>t.map((t=>ne(t)?t.toLocaleLowerCase():t));class Sd{constructor(e){this.map=new Map,this.boundHandlePinch=()=>{},this.recordKey=new Set,this.onKeyDown=t=>{(null==t?void 0:t.key)&&(this.recordKey.add(t.key),this.trigger(t))},this.onKeyUp=t=>{(null==t?void 0:t.key)&&this.recordKey.delete(t.key)},this.onWheel=e=>{this.triggerExtendKey(t.CommonEvent.WHEEL,e)},this.onDrag=e=>{this.triggerExtendKey(t.CommonEvent.DRAG,e)},this.handlePinch=(e,n)=>{this.triggerExtendKey(t.CommonEvent.PINCH,Object.assign(Object.assign({},e),n))},this.onFocus=()=>{this.recordKey.clear()},this.emitter=e,this.bindEvents()}bind(e,n){0!==e.length&&(e.includes(t.CommonEvent.PINCH)&&!this.pinchHandler&&(this.boundHandlePinch=this.handlePinch.bind(this),this.pinchHandler=new kd(this.emitter,"pinchmove",this.boundHandlePinch)),this.map.set(e,n))}unbind(t,e){this.map.forEach(((n,r)=>{Ne(r,t)&&(e&&e!==n||this.map.delete(r))}))}unbindAll(){this.map.clear()}match(t){const e=Md(Array.from(this.recordKey)).sort(),n=Md(t).sort();return Ne(e,n)}bindEvents(){var e;const{emitter:n}=this;n.on(t.CommonEvent.KEY_DOWN,this.onKeyDown),n.on(t.CommonEvent.KEY_UP,this.onKeyUp),n.on(t.CommonEvent.WHEEL,this.onWheel),n.on(t.CommonEvent.DRAG,this.onDrag),null===(e=globalThis.addEventListener)||void 0===e||e.call(globalThis,"focus",this.onFocus)}trigger(t){this.map.forEach(((e,n)=>{this.match(n)&&e(t)}))}triggerExtendKey(t,e){this.map.forEach(((n,r)=>{r.includes(t)&&Ne(Array.from(this.recordKey),r.filter((e=>e!==t)))&&n(e)}))}destroy(){var e,n;this.unbindAll(),this.emitter.off(t.CommonEvent.KEY_DOWN,this.onKeyDown),this.emitter.off(t.CommonEvent.KEY_UP,this.onKeyUp),this.emitter.off(t.CommonEvent.WHEEL,this.onWheel),this.emitter.off(t.CommonEvent.DRAG,this.onDrag),null===(e=this.pinchHandler)||void 0===e||e.off("pinchmove",this.boundHandlePinch),null===(n=globalThis.removeEventListener)||void 0===n||n.call(globalThis,"blur",this.onFocus)}}class Nd extends Gh{constructor(t,e){super(t,ke({},Nd.defaultOptions,e)),this.shortcut=new Sd(t.graph),this.onPointerDown=this.onPointerDown.bind(this),this.onPointerMove=this.onPointerMove.bind(this),this.onPointerUp=this.onPointerUp.bind(this),this.clearStates=this.clearStates.bind(this),this.bindEvents()}onPointerDown(t){if(!this.validate(t)||!this.isKeydown()||this.startPoint)return;const{canvas:e,graph:n}=this.context,r=Object.assign({},this.options.style);this.options.style.lineWidth&&(r.lineWidth=+this.options.style.lineWidth/n.getZoom()),this.rectShape=new ru({id:"g6-brush-select",style:r}),e.appendChild(this.rectShape),this.startPoint=[t.canvas.x,t.canvas.y]}onPointerMove(t){var e;if(!this.startPoint)return;const{immediately:n,mode:r}=this.options;this.endPoint=Od(t),null===(e=this.rectShape)||void 0===e||e.attr({x:Math.min(this.endPoint[0],this.startPoint[0]),y:Math.min(this.endPoint[1],this.startPoint[1]),width:Math.abs(this.endPoint[0]-this.startPoint[0]),height:Math.abs(this.endPoint[1]-this.startPoint[1])}),n&&"default"===r&&this.updateElementsStates(wd(this.startPoint,this.endPoint))}onPointerUp(t){this.startPoint&&(this.endPoint?(this.endPoint=Od(t),this.updateElementsStates(wd(this.startPoint,this.endPoint)),this.clearBrush()):this.clearBrush())}clearStates(){this.endPoint||this.clearElementsStates()}clearElementsStates(){const{graph:t}=this.context,e=Object.values(t.getData()).reduce(((t,e)=>Object.assign({},t,e.reduce(((t,e)=>{var n;const r=null===(n=e.states||[])||void 0===n?void 0:n.filter((t=>t!==this.options.state));return t[Nh(e)]=r,t}),{}))),{});t.setElementState(e,this.options.animation)}updateElementsStates(t){const{graph:e}=this.context,{enableElements:n,state:r,mode:i,onSelect:o}=this.options,a=this.selector(e,t,n);let s={};switch(i){case"union":a.forEach((t=>{s[t]=[...e.getElementState(t),r]}));break;case"diff":a.forEach((t=>{const n=e.getElementState(t);s[t]=n.includes(r)?n.filter((t=>t!==r)):[...n,r]}));break;case"intersect":a.forEach((t=>{const n=e.getElementState(t);s[t]=n.includes(r)?[r]:[]}));break;default:a.forEach((t=>{s[t]=[r]}))}Ut(o)&&(s=o(s)),e.setElementState(s,this.options.animation)}selector(t,e,n){if(!n||0===n.length)return[];const r=[],i=t.getData();if(n.forEach((n=>{i[`${n}s`].forEach((n=>{const i=Nh(n);"hidden"!==t.getElementVisibility(i)&&function(t,e,n,r){const i=t[0],o=t[1];let a=!1;void 0===n&&(n=0),void 0===r&&(r=e.length);const s=r-n;for(let t=0,r=s-1;to!=c>o&&i<(u-s)*(o-l)/(c-l)+s&&(a=!a)}return a}(t.getElementPosition(i),e)&&r.push(i)}))})),n.includes("edge")){const t=i.edges;null==t||t.forEach((t=>{const{source:e,target:n}=t;r.includes(e)&&r.includes(n)&&r.push(Nh(t))}))}return r}clearBrush(){var t;null===(t=this.rectShape)||void 0===t||t.remove(),this.rectShape=void 0,this.startPoint=void 0,this.endPoint=void 0}isKeydown(){const{trigger:t}=this.options,e=Array.isArray(t)?t:[t];return this.shortcut.match(e.filter((t=>"drag"!==t)))}validate(t){if(this.destroyed)return!1;const{enable:e}=this.options;return Ut(e)?e(t):!!e}bindEvents(){const{graph:e}=this.context;e.on(t.CommonEvent.POINTER_DOWN,this.onPointerDown),e.on(t.CommonEvent.POINTER_MOVE,this.onPointerMove),e.on(t.CommonEvent.POINTER_UP,this.onPointerUp),e.on(t.CanvasEvent.CLICK,this.clearStates)}unbindEvents(){const{graph:e}=this.context;e.off(t.CommonEvent.POINTER_DOWN,this.onPointerDown),e.off(t.CommonEvent.POINTER_MOVE,this.onPointerMove),e.off(t.CommonEvent.POINTER_UP,this.onPointerUp),e.off(t.CanvasEvent.CLICK,this.clearStates)}update(t){this.unbindEvents(),this.options=ke(this.options,t),this.bindEvents()}destroy(){this.unbindEvents(),super.destroy()}}Nd.defaultOptions={animation:!1,enable:!0,enableElements:["node","combo","edge"],immediately:!1,mode:"default",state:"selected",trigger:["shift"],style:{width:0,height:0,lineWidth:1,fill:"#1677FF",stroke:"#1677FF",fillOpacity:.1,zIndex:2,pointerEvents:"none"}};const Od=t=>[t.canvas.x,t.canvas.y],Td=.8,Cd=["node","edge","combo"];function Ad(t,e,n,r,i=0){"TB"===r&&e(t,i);const o=n(t);if(o)for(const t of o)Ad(t,e,n,r,i+1);"BT"===r&&e(t,i)}function Pd(t,e,n,r,i="both"){if("combo"===e||"node"===e)return Rd(t,n,r,i);const o=t.getEdgeData(n);if(!o)return[];const a=Rd(t,o.source,r-1,i),s=Rd(t,o.target,r-1,i);return Array.from(new Set([...a,...s,n]))}function Rd(t,e,n,r="both"){const i=new Set,o=new Set,a=new Set;return function(t,e,n){const r=[[t,0]];for(;r.length;){const[t,i]=r.shift();e(t,i);const o=n(t);if(o)for(const t of o)r.push([t,i+1])}}(e,((e,i)=>{i>n||(a.add(e),t.getRelatedEdgesData(e,r).forEach((t=>{const e=Nh(t);!o.has(e)&&it.getRelatedEdgesData(e,r).map((t=>t.source===e?t.target:t.source)).filter((t=>!i.has(t)&&(i.add(t),!0))))),Array.from(a)}function Dd(t){return t.states||[]}class Ld extends Gh{constructor(t,e){super(t,Object.assign({},Ld.defaultOptions,e)),this.onClickSelect=t=>ze(this,void 0,void 0,(function*(){var e,n;this.validate(t)&&(yield this.updateState(t),null===(n=(e=this.options).onClick)||void 0===n||n.call(e,t))})),this.onClickCanvas=t=>ze(this,void 0,void 0,(function*(){var e,n;this.validate(t)&&(yield this.clearState(),null===(n=(e=this.options).onClick)||void 0===n||n.call(e,t))})),this.shortcut=new Sd(t.graph),this.bindEvents()}bindEvents(){const{graph:e}=this.context;this.unbindEvents(),Cd.forEach((n=>{e.on(`${n}:${t.CommonEvent.CLICK}`,this.onClickSelect)})),e.on(t.CanvasEvent.CLICK,this.onClickCanvas)}get isMultipleSelect(){const{multiple:t,trigger:e}=this.options;return t&&this.shortcut.match(e)}getNeighborIds(t){const{target:e,targetType:n}=t,{graph:r}=this.context,{degree:i}=this.options;return Pd(r,n,e.id,"function"==typeof i?i(t):i).filter((t=>t!==e.id))}updateState(t){return ze(this,void 0,void 0,(function*(){const{state:e,unselectedState:n,neighborState:r,animation:i}=this.options;if(!e&&!r&&!n)return;const{target:o}=t,{graph:a}=this.context,s=Dd(a.getElementData(o.id)).includes(e)?"unselect":"select",l={},u=this.isMultipleSelect,c=[o.id],h=this.getNeighborIds(t);if(u)if(Object.assign(l,this.getDataStates()),"select"===s){const t=(t,e)=>{t.forEach((t=>{const r=new Set(a.getElementState(t));r.add(e),r.delete(n),l[t]=Array.from(r)}))};t(c,e),t(h,r),n&&Object.keys(l).forEach((t=>{const i=l[t];i.includes(e)||i.includes(r)||i.includes(n)||l[t].push(n)}))}else{const t=l[o.id];l[o.id]=t.filter((t=>t!==e&&t!==r)),t.includes(n)||l[o.id].push(n),h.forEach((t=>{l[t]=l[t].filter((t=>t!==r)),l[t].includes(e)||l[t].push(n)}))}else if("select"===s){Object.assign(l,this.getClearStates(!!n));const t=(t,e)=>{t.forEach((t=>{l[t]||(l[t]=a.getElementState(t)),l[t].push(e)}))};t(c,e),t(h,r),n&&Object.keys(l).forEach((t=>{c.includes(t)||h.includes(t)||l[t].push(n)}))}else Object.assign(l,this.getClearStates());yield a.setElementState(l,i)}))}getDataStates(){const{graph:t}=this.context,{nodes:e,edges:n,combos:r}=t.getData(),i={};return[...e,...n,...r].forEach((t=>{i[Nh(t)]=Dd(t)})),i}getClearStates(t=!1){const{graph:e}=this.context,{state:n,unselectedState:r,neighborState:i}=this.options,o=new Set([n,r,i]),{nodes:a,edges:s,combos:l}=e.getData(),u={};return[...a,...s,...l].forEach((e=>{const n=Dd(e),r=n.filter((t=>!o.has(t)));(t||r.length!==n.length)&&(u[Nh(e)]=r)})),u}clearState(){return ze(this,void 0,void 0,(function*(){const{graph:t}=this.context;yield t.setElementState(this.getClearStates(),this.options.animation)}))}validate(t){if(this.destroyed)return!1;const{enable:e}=this.options;return Ut(e)?e(t):!!e}unbindEvents(){const{graph:e}=this.context;Cd.forEach((n=>{e.off(`${n}:${t.CommonEvent.CLICK}`,this.onClickSelect)})),e.off(t.CanvasEvent.CLICK,this.onClickCanvas)}destroy(){this.unbindEvents(),super.destroy()}}function _d(t){var e;return!!(null===(e=t.style)||void 0===e?void 0:e.collapsed)}function Id(t,e){if(!t.startsWith(e))return!1;const n=t[e.length];return n>="A"&&n<="Z"}function jd(t,e,n=!0){if(!e)return t;if(!Id(t,e))return t;const r=t.slice(e.length);return n?function(t){var e=he(t);return e.charAt(0).toLowerCase()+e.substring(1)}(r):r}function Bd(t,e){const n=Object.entries(t).reduce(((t,[n,r])=>("className"===n||"class"===n||Id(n,e)&&Object.assign(t,{[jd(n,e)]:r}),t)),{});if("opacity"in t){const r=function(t,e){return`${e}${de(t)}`}("opacity",e),i=t.opacity;if(r in t){const e=t[r];Object.assign(n,{opacity:i*e})}else Object.assign(n,{opacity:i})}return n}function Fd(t,e){const n=e.length;return Object.keys(t).reduce(((r,i)=>{if(i.startsWith(e)){r[i.slice(n)]=t[i]}return r}),{})}function zd(t,e){const n="string"==typeof e?[e]:e,r={};return Object.keys(t).forEach((e=>{n.find((t=>e.startsWith(t)))||(r[e]=t[e])})),r}function Gd(t=0){if("number"==typeof t)return[t,t,t];const[e,n=e,r=e]=t;return[e,n,r]}function Vd(t,e){const{datum:n,graph:r}=e;return"function"==typeof t?t.call(r,n):Object.fromEntries(Object.entries(t).map((([t,e])=>"function"==typeof e?[t,e.call(r,n)]:[t,e])))}function Wd(t,e){const n=(null==t?void 0:t.style)||{},r=(null==e?void 0:e.style)||{};for(const t in n)t in r||(r[t]=n[t]);return Object.assign({},t,e,{style:r})}function Hd(t){if(t)return"string"==typeof t||"function"==typeof t||Array.isArray(t)?{type:"group",field:t=>t.id,color:t,invert:!1}:t}function Ud(t){const e="string"==typeof t?Dc("palette",t):t;if("function"!=typeof e)return e}function $d(t,e){let n=2*t;return"string"==typeof e?n=t*Number(e.replace("%",""))/100:"number"==typeof e&&(n=e),isNaN(n)&&(n=2*t),n}function Yd(t,e,n=1,r=!1){const i=r?n:1;return $d((t.max[0]-t.min[0])*i,e)}Ld.defaultOptions={animation:!0,enable:!0,multiple:!1,trigger:["shift"],state:"selected",neighborState:"selected",unselectedState:void 0,degree:0};class qd extends Wl{constructor(t){Kd(t.style),super(t),this.shapeMap={},this.animateMap={},this.render(this.attributes,this),this.setVisibility(),this.bindEvents()}get parsedAttributes(){return this.attributes}upsert(e,n,r,i,o){var a,s,l,u,c,h,d,f;const p=this.shapeMap[e];if(!1===r)return void(p&&(null===(a=null==o?void 0:o.beforeDestroy)||void 0===a||a.call(o,p),i.removeChild(p),delete this.shapeMap[e],null===(s=null==o?void 0:o.afterDestroy)||void 0===s||s.call(o,p)));const g="string"==typeof n?Dc(t.ExtensionCategory.SHAPE,n):n;if(!g)throw new Error(_c(`Shape ${n} not found`));if(!p||p.destroyed||!(p instanceof g)){p&&(null===(l=null==o?void 0:o.beforeDestroy)||void 0===l||l.call(o,p),null==p||p.destroy(),null===(u=null==o?void 0:o.afterDestroy)||void 0===u||u.call(o,p)),null===(c=null==o?void 0:o.beforeCreate)||void 0===c||c.call(o);const t=new g({className:e,style:r});return i.appendChild(t),this.shapeMap[e]=t,null===(h=null==o?void 0:o.afterCreate)||void 0===h||h.call(o,t),t}return null===(d=null==o?void 0:o.beforeUpdate)||void 0===d||d.call(o,p),Wg(p,r),null===(f=null==o?void 0:o.afterUpdate)||void 0===f||f.call(o,p),p}update(t={}){const e=Object.assign({},this.attributes,t);Kd(e),function(t,e){const{zIndex:n,transform:r,transformOrigin:i,visibility:o,cursor:a,clipPath:s,component:l}=e,u=Fe(e,["zIndex","transform","transformOrigin","visibility","cursor","clipPath","component"]);Object.assign(t.attributes,u),r&&t.setAttribute("transform",r);ae(n)&&t.setAttribute("zIndex",n);i&&t.setAttribute("transformOrigin",i);o&&t.setAttribute("visibility",o);a&&t.setAttribute("cursor",a);s&&t.setAttribute("clipPath",s);l&&t.setAttribute("component",l)}(this,e),this.render(e,this),this.setVisibility()}bindEvents(){}getGraphicStyle(t){return function(t){const{x:e,y:n,z:r,class:i,className:o,transform:a,transformOrigin:s,zIndex:l,visibility:u}=t;return Fe(t,["x","y","z","class","className","transform","transformOrigin","zIndex","visibility"])}(t)}get compositeShapes(){return[["badges","badge-"],["ports","port-"]]}animate(t,e){if(0===t.length)return null;const n=[];if(void 0!==t[0].x||void 0!==t[0].y||void 0!==t[0].z){const{x:e=0,y:n=0,z:r=0}=this.attributes;t.forEach((t=>{const{x:i=e,y:o=n,z:a=r}=t;Object.assign(t,{transform:a?[["translate3d",i,o,a]]:[["translate",i,o]]})}))}const r=super.animate(t,e);if(r&&(Xd(this,r),n.push(r)),Array.isArray(t)&&t.length>0){const r=["transform","transformOrigin","x","y","z","zIndex"];if(Object.keys(t[0]).some((t=>!r.includes(t)))){Object.entries(this.shapeMap).forEach((([r,i])=>{const o=this[`get${de(r)}Style`];if(Ut(o)){const r=t.map((t=>o.call(this,Object.assign(Object.assign({},this.attributes),t)))),a=i.animate(Fc(r),e);a&&(Xd(i,a),n.push(a))}}));const r=(r,i)=>{if(!Se(r)){const o=this[`get${de(i)}Style`];if(Ut(o)){const i=t.map((t=>o.call(this,Object.assign(Object.assign({},this.attributes),t))));Object.entries(i[0]).map((([t])=>{const o=i.map((e=>e[t])),a=r[t];if(a){const t=a.animate(Fc(o),e);t&&(Xd(a,t),n.push(t))}}))}}};this.compositeShapes.forEach((([t,e])=>{const n=Fd(this.shapeMap,e);r(n,t)}))}}return Bc(n)}getShape(t){return this.shapeMap[t]}setVisibility(){const{visibility:t}=this.attributes;Bh(this,t)}destroy(){this.shapeMap={},this.animateMap={},super.destroy()}}function Xd(t,e){null==e||e.finished.then((()=>{const n=t.activeAnimations.findIndex((t=>t===e));n>-1&&t.activeAnimations.splice(n,1)}))}function Kd(t){if(!t)return{};if("x"in t||"y"in t||"z"in t){const{x:e=0,y:n=0,z:r,transform:i}=t,o=Wc(e,n,r,i);o&&(t.transform=o)}return t}class Zd extends qd{constructor(t){super(Wd({style:Zd.defaultStyleProps},t))}isTextStyle(t){return Id(t,"label")}isBackgroundStyle(t){return Id(t,"background")}getTextStyle(t){const e=this.getGraphicStyle(t),{padding:n}=e;return zd(Fe(e,["padding"]),"background")}getBackgroundStyle(t){if(!1===t.background)return!1;const e=this.getGraphicStyle(t),{wordWrap:n,wordWrapWidth:r,padding:i}=e,o=Bd(e,"background"),{min:[a,s],center:[l,u],halfExtents:[c,h]}=this.shapeMap.text.getGeometryBounds(),[d,f,p,g]=Jc(i),v=2*c+g+f,{width:m,height:y}=o;m&&y?Object.assign(o,{x:l-Number(m)/2,y:u-Number(y)/2}):Object.assign(o,{x:a-g,y:s-d,width:n?Math.min(v,r+g+f):v,height:2*h+d+p});const{radius:b}=o;if("string"==typeof b&&b.endsWith("%")){const t=Number(b.replace("%",""))/100;o.radius=Math.min(+o.width,+o.height)*t}return o}render(t=this.parsedAttributes,e=this){this.upsert("text",ou,this.getTextStyle(t),e),this.upsert("background",ru,this.getBackgroundStyle(t),e)}getGeometryBounds(){return(this.getShape("background")||this.getShape("text")).getGeometryBounds()}}Zd.defaultStyleProps={padding:0,fontSize:12,fontFamily:"system-ui, sans-serif",wordWrap:!0,maxLines:1,wordWrapWidth:128,textOverflow:"...",textBaseline:"middle",backgroundOpacity:.75,backgroundZIndex:-1,backgroundLineWidth:0};class Qd extends qd{constructor(t){super(Wd({style:Qd.defaultStyleProps},t))}getBadgeStyle(t){return this.getGraphicStyle(t)}render(t=this.parsedAttributes,e=this){this.upsert("label",Zd,this.getBadgeStyle(t),e)}getGeometryBounds(){const t=this.getShape("label");return(t.getShape("background")||t.getShape("text")).getGeometryBounds()}}Qd.defaultStyleProps={padding:[2,4,2,4],fontSize:10,wordWrap:!1,backgroundRadius:"50%",backgroundOpacity:1};const Jd={M:["x","y"],m:["dx","dy"],H:["x"],h:["dx"],V:["y"],v:["dy"],L:["x","y"],l:["dx","dy"],Z:[],z:[],C:["x1","y1","x2","y2","x","y"],c:["dx1","dy1","dx2","dy2","dx","dy"],S:["x2","y2","x","y"],s:["dx2","dy2","dx","dy"],Q:["x1","y1","x","y"],q:["dx1","dy1","dx","dy"],T:["x","y"],t:["dx","dy"],A:["rx","ry","rotation","large-arc","sweep","x","y"],a:["rx","ry","rotation","large-arc","sweep","dx","dy"]};function tf(t){const e=[],n="string"==typeof t?function(t){const e=t.replace(/[\n\r]/g,"").replace(/-/g," -").replace(/(\d*\.)(\d+)(?=\.)/g,"$1$2 ").trim().split(/\s*,|\s+/),n=[];let r="",i={};for(;e.length>0;){let t=e.shift();t in Jd?r=t:e.unshift(t),i={type:r},Jd[r].forEach((n=>{t=e.shift(),i[n]=t})),"M"===r?r="L":"m"===r&&(r="l");const[o,...a]=Object.values(i);n.push([o,...a.map(Number)])}return n}(t):t;return n.forEach((t=>{const n=t[0];if("Z"!==n)if("A"!==n)for(let n=1;n{if(t.length<2)return[["M",0,0],["L",0,0]];const e=t[0],n=t[1],r=t[t.length-1],i=t[t.length-2];t.unshift(i,r),t.push(e,n);const o=[["M",r[0],r[1]]];for(let e=1;e{const n=t,r=c[(e+1)%c.length];return Ne(n,r)?null:[n,r]})).filter(Boolean),d=bd([s,l],h),f=xd([s,l],d);if(f&&d&&(u.transform=[["translate",f[0]+n,f[1]+r]],a)){const t=Math.atan((d[0][1]-d[1][1])/(d[0][0]-d[1][0]));u.transform.push(["rotate",t/Math.PI*180]),u.textAlign="center","right"!==e&&"left"!==e||(u.textBaseline=t>0?"right"===e?"bottom":"top":"right"===e?"top":"bottom")}return u}(c,a,r,i,s,t.d,o),{wordWrapWidth:Yd(c,n)},l)}getKeyStyle(t){return this.getGraphicStyle(t)}render(t,e){this.upsert("key",Ql,this.getKeyStyle(t),e),this.upsert("label",Zd,this.getLabelStyle(t),e)}}nf.defaultStyleProps={label:!0,labelPlacement:"bottom",labelCloseToPath:!0,labelAutoRotate:!0,labelOffsetX:0,labelOffsetY:0};let rf=class extends ql{constructor(t){super(t),this.onMounted=()=>{this.handleRadius()},this.onAttrModified=()=>{this.handleRadius()},af=this,this.isMutationObserved=!0,this.addEventListener(Ks.MOUNTED,this.onMounted),this.addEventListener(Ks.ATTR_MODIFIED,this.onAttrModified)}handleRadius(){const{radius:t,clipPath:e,width:n=0,height:r=0}=this.attributes;if(t&&n&&r){const[i,o]=this.getBounds().min,a={x:i,y:o,radius:t,width:n,height:r};if(e)Object.assign(this.parsedStyle.clipPath.style,a);else{const t=new ru({style:a});this.style.clipPath=t}}else e&&(this.style.clipPath=null)}};const of=new WeakMap;let af=null;const sf=t=>{if(af&&function(t){const e=[];let n=t.parentNode;for(;n;)e.push(n),n=n.parentNode;return e}(af).includes(t)){const e=of.get(t);e?e.includes(af)||e.push(af):of.set(t,[af])}},lf=t=>{const e=of.get(t);e&&e.forEach((t=>t.handleRadius()))};class uf extends qd{constructor(t){super(t)}isImage(){const{src:t}=this.attributes;return!!t}getIconStyle(t=this.attributes){const{width:e=0,height:n=0}=t,r=this.getGraphicStyle(t);return this.isImage()?Object.assign({x:-e/2,y:-n/2},r):Object.assign({textBaseline:"middle",textAlign:"center"},r)}render(t=this.attributes,e=this){this.upsert("icon",this.isImage()?rf:ou,this.getIconStyle(t),e)}}class cf extends qd{get context(){return this.config.context}get parsedAttributes(){return this.attributes}onframe(){}animate(t,e){const n=super.animate(t,e);return n&&(n.onframe=()=>this.onframe(),n.finished.then((()=>this.onframe()))),n}}class hf extends cf{constructor(t){super(Wd({style:hf.defaultStyleProps},t)),this.type="node"}getSize(t=this.attributes){const{size:e}=t;return Gd(e)}getKeyStyle(t){const e=this.getGraphicStyle(t);return Object.assign(zd(e,["label","halo","icon","badge","port"]))}getLabelStyle(t){if(!1===t.label||!t.labelText)return!1;const e=Bd(this.getGraphicStyle(t),"label"),{placement:n,maxWidth:r,offsetX:i,offsetY:o}=e,a=Fe(e,["placement","maxWidth","offsetX","offsetY"]),s=this.getShape("key").getLocalBounds();return Object.assign(Vg(s,n,i,o),{wordWrapWidth:Yd(s,r)},a)}getHaloStyle(t){if(!1===t.halo)return!1;const e=this.getKeyStyle(t),{fill:n}=e,r=Fe(e,["fill"]),i=Bd(this.getGraphicStyle(t),"halo");return Object.assign(Object.assign(Object.assign({},r),{stroke:n}),i)}getIconStyle(t){if(!1===t.icon||!t.iconText&&!t.iconSrc)return!1;const e=Bd(this.getGraphicStyle(t),"icon");return Object.assign(function(t,e){const n=Gd(t);let r={};return e.text&&!e.fontSize&&(r={fontSize:.5*Math.min(...n)}),!e.src||e.width&&e.height||(r={width:.5*n[0],height:.5*n[1]}),r}(t.size,e),e)}getBadgesStyle(t){var e;const n=Fd(this.shapeMap,"badge-"),r={};if(Object.keys(n).forEach((t=>{r[t]=!1})),!1===t.badge||!(null===(e=t.badges)||void 0===e?void 0:e.length))return r;const{badges:i=[],badgePalette:o,opacity:a=1}=t,s=Fe(t,["badges","badgePalette","opacity"]),l=Ud(o),u=Bd(this.getGraphicStyle(s),"badge");return i.forEach(((t,e)=>{r[e]=Object.assign(Object.assign({backgroundFill:l?l[e%(null==l?void 0:l.length)]:void 0,opacity:a},u),this.getBadgeStyle(t))})),r}getBadgeStyle(t){const e=this.getShape("key"),{placement:n="top",offsetX:r,offsetY:i}=t,o=Fe(t,["placement","offsetX","offsetY"]),a=Vg(e.getLocalBounds(),n,r,i,!0);return Object.assign(Object.assign({},a),o)}getPortsStyle(t){var e;const n=this.getPorts(),r={};if(Object.keys(n).forEach((t=>{r[t]=!1})),!1===t.port||!(null===(e=t.ports)||void 0===e?void 0:e.length))return r;const i=Bd(this.getGraphicStyle(t),"port"),{ports:o=[]}=t;return o.forEach(((e,n)=>{const o=e.key||n,a=Object.assign(Object.assign({},i),e);if(Ig(a))r[o]=!1;else{const[n,i]=this.getPortXY(t,e);r[o]=Object.assign({transform:[["translate",n,i]]},a)}})),r}getPortXY(t,e){const{placement:n="left"}=e,r=this.getShape("key");return Lg(function(t,e){if(!t)return e.getLocalBounds();const n=t.canvas.getLayer(),r=e.cloneNode();Bh(r,"hidden"),n.appendChild(r);const i=r.getLocalBounds();return r.destroy(),i}(this.context,r),n)}getPorts(){return Fd(this.shapeMap,"port-")}getCenter(){return this.getShape("key").getBounds().center}getIntersectPoint(t,e=!1){return function(t,e,n=!1){return md(t,ud(e,"center"),[ud(e,"left-top"),ud(e,"right-top"),ud(e,"right-bottom"),ud(e,"left-bottom")],!1,n).point}(t,this.getShape("key").getBounds(),e)}drawHaloShape(t,e){const n=this.getHaloStyle(t),r=this.getShape("key");this.upsert("halo",r.constructor,n,e)}drawIconShape(t,e){const n=this.getIconStyle(t);this.upsert("icon",uf,n,e),sf(this)}drawBadgeShapes(t,e){const n=this.getBadgesStyle(t);Object.keys(n).forEach((t=>{const r=n[t];this.upsert(`badge-${t}`,Qd,r,e)}))}drawPortShapes(t,e){const n=this.getPortsStyle(t);Object.keys(n).forEach((t=>{const r=n[t],i=`port-${t}`;this.upsert(i,Gl,r,e)}))}drawLabelShape(t,e){const n=this.getLabelStyle(t);this.upsert("label",Zd,n,e)}_drawKeyShape(t,e){return this.drawKeyShape(t,e)}render(t=this.parsedAttributes,e=this){this._drawKeyShape(t,e),this.getShape("key")&&(this.drawHaloShape(t,e),this.drawIconShape(t,e),this.drawBadgeShapes(t,e),this.drawLabelShape(t,e),this.drawPortShapes(t,e))}update(t){super.update(t),t&&("x"in t||"y"in t||"z"in t)&&lf(this)}onframe(){this.drawBadgeShapes(this.parsedAttributes,this),this.drawLabelShape(this.parsedAttributes,this)}}hf.defaultStyleProps={x:0,y:0,size:32,droppable:!0,draggable:!0,port:!0,ports:[],portZIndex:2,portLinkToCenter:!1,badge:!0,badges:[],badgeZIndex:3,halo:!1,haloDroppable:!1,haloLineDash:0,haloLineWidth:12,haloStrokeOpacity:.25,haloPointerEvents:"none",haloZIndex:-1,icon:!0,iconZIndex:1,label:!0,labelIsBillboard:!0,labelMaxWidth:"200%",labelPlacement:"bottom",labelWordWrap:!1,labelZIndex:0};let df=class t extends hf{constructor(e){super(Wd({style:t.defaultStyleProps},e))}drawKeyShape(t,e){return this.upsert("key",Gl,this.getKeyStyle(t),e)}getKeyStyle(t){const e=super.getKeyStyle(t);return Object.assign(Object.assign({},e),{r:Math.min(...this.getSize(t))/2})}getIconStyle(t){const e=super.getIconStyle(t),{r:n}=this.getShape("key").attributes,r=2*n*Td;return!!e&&Object.assign({width:r,height:r},e)}getIntersectPoint(t,e=!1){return yd(t,this.getShape("key").getBounds(),e)}};df.defaultStyleProps={size:32};class ff extends hf{constructor(t){super(t)}get parsedAttributes(){return this.attributes}drawKeyShape(t,e){return this.upsert("key",tu,this.getKeyStyle(t),e)}getKeyStyle(t){const e=super.getKeyStyle(t);return Object.assign(Object.assign({},e),{points:this.getPoints(t)})}getIntersectPoint(t,e=!1){var n,r;const{points:i}=this.getShape("key").attributes;return md(t,[+((null===(n=this.attributes)||void 0===n?void 0:n.x)||0),+((null===(r=this.attributes)||void 0===r?void 0:r.y)||0)],i,!0,e).point}}class pf extends ff{constructor(t){super(t)}getPoints(t){const[e,n]=this.getSize(t);return function(t,e){return[[0,-e/2],[t/2,0],[0,e/2],[-t/2,0]]}(e,n)}}class gf extends df{constructor(t){super(Wd({style:gf.defaultStyleProps},t))}parseOuterR(){const{size:t}=this.parsedAttributes;return Math.min(...Gd(t))/2}parseInnerR(){const{innerR:t}=this.parsedAttributes;return ne(t)?parseInt(t)/100*this.parseOuterR():t}drawDonutShape(t,e){const{donuts:n}=t;if(!(null==n?void 0:n.length))return;const r=n.map((t=>ae(t)?{value:t}:t)),i=Bd(this.getGraphicStyle(t),"donut"),o=Ud(t.donutPalette);if(!o)return;const a=r.reduce(((t,e)=>{var n;return t+(null!==(n=e.value)&&void 0!==n?n:0)}),0),s=this.parseOuterR(),l=this.parseInnerR();let u=0;r.forEach(((t,n)=>{const{value:c=0,color:h=o[n%o.length]}=t,d=Fe(t,["value","color"]),f=360*(0===a?1/r.length:c/a);this.upsert(`round${n}`,Ql,Object.assign(Object.assign(Object.assign({},i),{d:mf(s,l,u,u+f),fill:h}),d),e),u+=f}))}render(t,e=this){super.render(t,e),this.drawDonutShape(t,e)}}gf.defaultStyleProps={innerR:"50%",donuts:[],donutPalette:"tableau"};const vf=(t,e,n,r)=>[t+Math.sin(r)*n,e-Math.cos(r)*n],mf=(t=0,e=0,n,r)=>{const[i,o]=[0,0];return Math.abs(n-r)%360<1e-6?((t,e,n,r)=>r<=0||n<=r?[["M",t-n,e],["A",n,n,0,1,1,t+n,e],["A",n,n,0,1,1,t-n,e],["Z"]]:[["M",t-n,e],["A",n,n,0,1,1,t+n,e],["A",n,n,0,1,1,t-n,e],["Z"],["M",t+r,e],["A",r,r,0,1,0,t-r,e],["A",r,r,0,1,0,t+r,e],["Z"]])(i,o,t,e):((t,e,n,r,i,o)=>{const[a,s]=[i/360*2*Math.PI,o/360*2*Math.PI],l=[vf(t,e,r,a),vf(t,e,n,a),vf(t,e,n,s),vf(t,e,r,s)],u=s-a>Math.PI?1:0;return[["M",l[0][0],l[0][1]],["L",l[1][0],l[1][1]],["A",n,n,0,u,1,l[2][0],l[2][1]],["L",l[3][0],l[3][1]],["A",r,r,0,u,0,l[0][0],l[0][1]],["Z"]]})(i,o,t,e,n,r)};class yf extends hf{constructor(t){super(Wd({style:yf.defaultStyleProps},t))}drawKeyShape(t,e){return this.upsert("key",Hl,this.getKeyStyle(t),e)}getKeyStyle(t){const e=super.getKeyStyle(t),[n,r]=this.getSize(t);return Object.assign(Object.assign({},e),{rx:n/2,ry:r/2})}getIconStyle(t){const e=super.getIconStyle(t),{rx:n,ry:r}=this.getShape("key").attributes,i=2*Math.min(+n,+r)*Td;return!!e&&Object.assign({width:i,height:i},e)}getIntersectPoint(t,e=!1){return yd(t,this.getShape("key").getBounds(),e)}}yf.defaultStyleProps={size:[45,35]};class bf extends ff{constructor(t){super(t)}getOuterR(t){return t.outerR||Math.min(...this.getSize(t))/2}getPoints(t){return[[0,e=this.getOuterR(t)],[e*Math.sqrt(3)/2,e/2],[e*Math.sqrt(3)/2,-e/2],[0,-e],[-e*Math.sqrt(3)/2,-e/2],[-e*Math.sqrt(3)/2,e/2]];var e}getIconStyle(t){const e=super.getIconStyle(t),n=this.getOuterR(t)*Td;return!!e&&Object.assign({width:n,height:n},e)}} -/*! - * @antv/g-plugin-canvas-path-generator - * @description A G plugin of path generator with Canvas2D API - * @version 2.1.19 - * @date 5/9/2025, 8:19:59 AM - * @author AntVis - * @docs https://g.antv.antgroup.com/ - */function xf(t,e){var n=e.cx,r=void 0===n?0:n,i=e.cy,o=void 0===i?0:i,a=e.r;t.arc(r,o,a,0,2*Math.PI,!1)}function Ef(t,e){var n=e.cx,r=void 0===n?0:n,i=e.cy,o=void 0===i?0:i,a=e.rx,s=e.ry;if(t.ellipse)t.ellipse(r,o,a,s,0,0,2*Math.PI,!1);else{var l=a>s?a:s,u=a>s?1:a/s,c=a>s?s/a:1;t.save(),t.scale(u,c),t.arc(r,o,l,0,2*Math.PI)}}function wf(t,e){var n,r,i=e.x1,o=e.y1,a=e.x2,s=e.y2,l=e.markerStart,u=e.markerEnd,c=e.markerStartOffset,h=e.markerEndOffset,d=0,f=0,p=0,g=0,v=0;l&&_l(l)&&c&&(n=a-i,r=s-o,v=Math.atan2(r,n),d=Math.cos(v)*(c||0),f=Math.sin(v)*(c||0)),u&&_l(u)&&h&&(n=i-a,r=o-s,v=Math.atan2(r,n),p=Math.cos(v)*(h||0),g=Math.sin(v)*(h||0)),t.moveTo(i+d,o+f),t.lineTo(a+p,s+g)}function kf(t,e){var n,r,i=e.markerStart,o=e.markerEnd,a=e.markerStartOffset,s=e.markerEndOffset,l=e.d,u=l.absolutePath,c=l.segments,h=0,d=0,f=0,p=0,g=0;if(i&&_l(i)&&a){var v=b(i.parentNode.getStartTangent(),2),m=v[0],y=v[1];n=m[0]-y[0],r=m[1]-y[1],g=Math.atan2(r,n),h=Math.cos(g)*(a||0),d=Math.sin(g)*(a||0)}if(o&&_l(o)&&s){var x=b(o.parentNode.getEndTangent(),2),E=x[0],w=x[1];n=E[0]-w[0],r=E[1]-w[1],g=Math.atan2(r,n),f=Math.cos(g)*(s||0),p=Math.sin(g)*(s||0)}for(var k=0;kF?B:F,U=B>F?1:B/F,$=B>F?F/B:1;t.translate(I,j),t.rotate(V),t.scale(U,$),t.arc(0,0,H,z,G,!!(1-W)),t.scale(1/U,1/$),t.rotate(-V),t.translate(-I,-j)}T&&t.lineTo(M[6]+f,M[7]+p);break;case"Z":t.closePath()}}}function Mf(t,e){var n,r,i=e.markerStart,o=e.markerEnd,a=e.markerStartOffset,s=e.markerEndOffset,l=e.points.points,u=l.length,c=l[0][0],h=l[0][1],d=l[u-1][0],f=l[u-1][1],p=0,g=0,v=0,m=0,y=0;i&&_l(i)&&a&&(n=l[1][0]-l[0][0],r=l[1][1]-l[0][1],y=Math.atan2(r,n),p=Math.cos(y)*(a||0),g=Math.sin(y)*(a||0)),o&&_l(o)&&s&&(n=l[u-1][0]-l[0][0],r=l[u-1][1]-l[0][1],y=Math.atan2(r,n),v=Math.cos(y)*(s||0),m=Math.sin(y)*(s||0)),t.moveTo(c+(p||v),h+(g||m));for(var b=1;b0?1:-1,d=l>0?1:-1,f=h+d===0,p=b(a.map((function(t){return oe(t,0,Math.min(Math.abs(u)/2,Math.abs(c)/2))})),4),g=p[0],v=p[1],m=p[2],y=p[3];t.moveTo(h*g+r,o),t.lineTo(u-h*v+r,o),0!==v&&t.arc(u-h*v+r,d*v+o,v,-d*Math.PI/2,h>0?0:Math.PI,f),t.lineTo(u+r,c-d*m+o),0!==m&&t.arc(u-h*m+r,c-d*m+o,m,h>0?0:Math.PI,d>0?Math.PI/2:1.5*Math.PI,f),t.lineTo(h*y+r,c+o),0!==y&&t.arc(h*y+r,c-d*y+o,y,d>0?Math.PI/2:-Math.PI/2,h>0?Math.PI:0,f),t.lineTo(r,d*g+o),0!==g&&t.arc(h*g+r,d*g+o,g,h>0?Math.PI:0,d>0?1.5*Math.PI:Math.PI/2,f)}else t.rect(r,o,u,c)}var Of=function(t){function e(){var t;s(this,e);for(var n=arguments.length,r=new Array(n),i=0;i=l-m&&y<=l+m)}function Lf(t,e,n,r){return t/(n*n)+e/(r*r)}function _f(t,e,n){var r=t.parsedStyle,i=r.cx,o=void 0===i?0:i,a=r.cy,s=void 0===a?0:a,l=r.rx,u=r.ry,c=r.fill,h=r.stroke,d=r.lineWidth,f=void 0===d?1:d,p=r.increasedLineWidthForHitTesting,g=void 0===p?0:p,v=r.pointerEvents,m=void 0===v?"auto":v,y=e.x,x=e.y,E=b(Qa(m,c,h),2),w=E[0],k=E[1],M=(f+g)/2,S=(y-o)*(y-o),N=(x-s)*(x-s);return w&&k||n?Lf(S,N,l+M,u+M)<=1:w?Lf(S,N,l,u)<=1:!!k&&(Lf(S,N,l-M,u-M)>=1&&Lf(S,N,l+M,u+M)<=1)}function If(t,e,n,r,i,o){return i>=t&&i<=t+n&&o>=e&&o<=e+r}function jf(t,e,n,r,i,o,a,s){var l=(Math.atan2(s-e,a-t)+2*Math.PI)%(2*Math.PI),u={x:t+n*Math.cos(l),y:e+n*Math.sin(l)};return Rn(u.x,u.y,a,s)<=o/2}function Bf(t,e,n,r,i,o,a){var s=Math.min(t,n),l=Math.max(t,n),u=Math.min(e,r),c=Math.max(e,r),h=i/2;return o>=s-h&&o<=l+h&&a>=u-h&&a<=c+h&&zn(t,e,n,r,o,a)<=i/2}function Ff(t,e,n,r,i){var o=t.length;if(o<2)return!1;for(var a=0;a0!=zf(s[1]-n)>0&&zf(e-(n-a[1])*(a[0]-s[0])/(a[1]-s[1])-a[0])<0&&(r=!r)}return r}function Wf(t,e,n){for(var r=!1,i=0;i=i.min[0]&&e.y>=i.min[1]&&e.x<=i.max[0]&&e.y<=i.max[1]}var Zf=function(t){function e(){var t;s(this,e);for(var n=arguments.length,r=new Array(n),i=0;i0&&void 0!==arguments[0]?arguments[0]:t.api;t.rafId&&(e.cancelAnimationFrame(t.rafId),t.rafId=null)}},{key:"executeTask",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:t.api;np.length<=0&&rp.length<=0||(rp.forEach((function(t){return t()})),rp=np.splice(0,t.TASK_NUM_PER_FRAME),t.rafId=e.requestAnimationFrame((function(){t.executeTask(e)})))}},{key:"sliceImage",value:function(e,n,r,i){for(var o=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,a=arguments.length>5&&void 0!==arguments[5]?arguments[5]:t.api,s=e.naturalWidth||e.width,l=e.naturalHeight||e.height,u=n-o,c=r-o,h=Math.ceil(s/u),d=Math.ceil(l/c),f={tileSize:[n,r],gridSize:[d,h],tiles:Array(d).fill(null).map((function(){return Array(h).fill(null)}))},p=function(t){for(var o=function(o){np.push((function(){var h=o*u,d=t*c,p=[Math.min(n,s-h),Math.min(r,l-d)],g=p[0],v=p[1],m=a.createCanvas();m.width=n,m.height=r,m.getContext("2d").drawImage(e,h,d,g,v,0,0,g,v),f.tiles[t][o]={x:h,y:d,tileX:o,tileY:t,data:m},i()}))},d=0;du&&v>c,e&&("function"==typeof e.resetTransform?e.resetTransform():e.setTransform(1,0,0,1,0,0),r.clearFullScreen&&r.clearRect(e,0,0,i*n,a*n,o.background))}));var m=function(t,e){for(var i=[t];i.length>0;){var o,a=i.pop();a.isVisible()&&!a.isCulled()&&(h?r.renderDisplayObjectOptimized(a,e,r.context,Qf(r,cp)[cp],n):r.renderDisplayObject(a,e,r.context,Qf(r,cp)[cp],n));for(var s=(null===(o=a.sortable)||void 0===o||null===(o=o.sorted)||void 0===o?void 0:o.length)>0?a.sortable.sorted:a.childNodes,l=s.length-1;l>=0;l--)i.push(s[l])}};s.hooks.endFrame.tap(t.tag,(function(){if(0!==l.root.childNodes.length){h=o.renderer.getConfig().enableRenderingOptimization,Qf(r,cp)[cp]={restoreStack:[],prevObject:null,currentContext:Qf(r,cp)[cp].currentContext},Qf(r,cp)[cp].currentContext.clear(),r.clearFullScreenLastFrame=!1;var t=f.getContext(),e=f.getDPR();if(W(r.dprMatrix,[e,e,1]),j(r.vpMatrix,r.dprMatrix,a.getOrthoMatrix()),r.clearFullScreen)h?(t.save(),m(l.root,t),t.restore()):m(l.root,t),r.removedRBushNodeAABBs=[];else{var i=r.safeMergeAABB.apply(r,[r.mergeDirtyAABBs(r.renderQueue)].concat(d(r.removedRBushNodeAABBs.map((function(t){var e=t.minX,n=t.minY,r=t.maxX,i=t.maxY,o=new Er;return o.setMinMax([e,n,0],[r,i,0]),o})))));if(r.removedRBushNodeAABBs=[],Er.isEmpty(i))return void(r.renderQueue=[]);var s=r.convertAABB2Rect(i),u=s.x,c=s.y,g=s.width,v=s.height,y=Mt(r.vec3a,[u,c,0],r.vpMatrix),b=Mt(r.vec3b,[u+g,c,0],r.vpMatrix),x=Mt(r.vec3c,[u,c+v,0],r.vpMatrix),E=Mt(r.vec3d,[u+g,c+v,0],r.vpMatrix),w=Math.min(y[0],b[0],E[0],x[0]),k=Math.min(y[1],b[1],E[1],x[1]),M=Math.max(y[0],b[0],E[0],x[0]),S=Math.max(y[1],b[1],E[1],x[1]),N=Math.floor(w),O=Math.floor(k),T=Math.ceil(M-w),C=Math.ceil(S-k);t.save(),r.clearRect(t,N,O,T,C,o.background),t.beginPath(),t.rect(N,O,T,C),t.clip(),t.setTransform(r.vpMatrix[0],r.vpMatrix[1],r.vpMatrix[4],r.vpMatrix[5],r.vpMatrix[12],r.vpMatrix[13]),o.renderer.getConfig().enableDirtyRectangleRenderingDebug&&p.dispatchEvent(new zs(fu.DIRTY_RECTANGLE,{dirtyRect:{x:N,y:O,width:T,height:C}})),r.searchDirtyObjects(i).sort((function(t,e){return t.sortable.renderOrder-e.sortable.renderOrder})).forEach((function(e){e&&e.isVisible()&&!e.isCulled()&&r.renderDisplayObject(e,t,r.context,Qf(r,cp)[cp],n)})),t.restore(),r.renderQueue.forEach((function(t){r.saveDirtyAABB(t)})),r.renderQueue=[]}Qf(r,cp)[cp].restoreStack.forEach((function(){t.restore()})),Qf(r,cp)[cp].restoreStack=[]}else r.clearFullScreenLastFrame=!0})),s.hooks.render.tap(t.tag,(function(t){r.clearFullScreen||r.renderQueue.push(t)}))}},{key:"clearRect",value:function(t,e,n,r,i,o){t.clearRect(e,n,r,i),o&&(t.fillStyle=o,t.fillRect(e,n,r,i))}},{key:"renderDisplayObjectOptimized",value:function(t,e,n,r,i){var o=t.nodeName,a=!1,s=this.context.styleRendererFactory[o],l=this.pathGeneratorFactory[o],u=t.parsedStyle.clipPath;if(u){(!r.prevObject||!st(u.getWorldTransform(),r.prevObject.getWorldTransform()))&&(this.applyWorldTransform(e,u),r.prevObject=null);var c=this.pathGeneratorFactory[u.nodeName];c&&(e.save(),a=!0,e.beginPath(),c(e,u.parsedStyle),e.closePath(),e.clip())}if(s){(!r.prevObject||!st(t.getWorldTransform(),r.prevObject.getWorldTransform()))&&this.applyWorldTransform(e,t);var h=!r.prevObject;if(!h){var d=r.prevObject.nodeName;h=o===hr.TEXT?d!==hr.TEXT:o===hr.IMAGE?d!==hr.IMAGE:d===hr.TEXT||d===hr.IMAGE}s.applyStyleToContext(e,t,h,r),r.prevObject=t}l&&(e.beginPath(),l(e,t.parsedStyle),o!==hr.LINE&&o!==hr.PATH&&o!==hr.POLYLINE&&e.closePath()),s&&s.drawToContext(e,t,Qf(this,cp)[cp],this,i),a&&e.restore(),t.renderable.dirty=!1}},{key:"renderDisplayObject",value:function(t,e,n,r,i){var o=t.nodeName,a=r.restoreStack[r.restoreStack.length-1];!a||t.compareDocumentPosition(a)&Ws.DOCUMENT_POSITION_CONTAINS||(e.restore(),r.restoreStack.pop());var s=this.context.styleRendererFactory[o],l=this.pathGeneratorFactory[o],u=t.parsedStyle.clipPath;if(u){this.applyWorldTransform(e,u);var c=this.pathGeneratorFactory[u.nodeName];c&&(e.save(),r.restoreStack.push(t),e.beginPath(),c(e,u.parsedStyle),e.closePath(),e.clip())}s&&(this.applyWorldTransform(e,t),e.save(),this.applyAttributesToContext(e,t)),l&&(e.beginPath(),l(e,t.parsedStyle),o!==hr.LINE&&o!==hr.PATH&&o!==hr.POLYLINE&&e.closePath()),s&&(s.render(e,t.parsedStyle,t,n,this,i),e.restore()),t.renderable.dirty=!1}},{key:"applyAttributesToContext",value:function(t,e){var n=e.parsedStyle,r=n.stroke,i=n.fill,o=n.opacity,a=n.lineDash,s=n.lineDashOffset;a&&t.setLineDash(a),$t(s)||(t.lineDashOffset=s),$t(o)||(t.globalAlpha*=o),$t(r)||Array.isArray(r)||r.isNone||(t.strokeStyle=e.attributes.stroke),$t(i)||Array.isArray(i)||i.isNone||(t.fillStyle=e.attributes.fill)}},{key:"convertAABB2Rect",value:function(t){var e=t.getMin(),n=t.getMax(),r=Math.floor(e[0]),i=Math.floor(e[1]);return{x:r,y:i,width:Math.ceil(n[0])-r,height:Math.ceil(n[1])-i}}},{key:"mergeDirtyAABBs",value:function(t){var e=new Er;return t.forEach((function(t){var n=t.getRenderBounds();e.add(n);var r=t.renderable.dirtyRenderBounds;r&&e.add(r)})),e}},{key:"searchDirtyObjects",value:function(t){var e=b(t.getMin(),2),n=e[0],r=e[1],i=b(t.getMax(),2),o=i[0],a=i[1];return this.rBush.search({minX:n,minY:r,maxX:o,maxY:a}).map((function(t){return t.displayObject}))}},{key:"saveDirtyAABB",value:function(t){var e=t.renderable;e.dirtyRenderBounds||(e.dirtyRenderBounds=new Er);var n=t.getRenderBounds();n&&e.dirtyRenderBounds.update(n.center,n.halfExtents)}},{key:"applyWorldTransform",value:function(t,e,n){n?(A(this.tmpMat4,e.getLocalTransform()),j(this.tmpMat4,n,this.tmpMat4),j(this.tmpMat4,this.vpMatrix,this.tmpMat4)):(A(this.tmpMat4,e.getWorldTransform()),j(this.tmpMat4,this.vpMatrix,this.tmpMat4)),t.setTransform(this.tmpMat4[0],this.tmpMat4[1],this.tmpMat4[4],this.tmpMat4[5],this.tmpMat4[12],this.tmpMat4[13])}},{key:"safeMergeAABB",value:function(){for(var t=new Er,e=arguments.length,n=new Array(e),r=0;r0){if(n||e.attributes.stroke!==r.prevObject.attributes.stroke)yp(t,"strokeStyle",$t(o.stroke)||Array.isArray(o.stroke)||o.stroke.isNone?vp.strokeStyle:e.attributes.stroke,r.currentContext);(n||o.lineWidth!==i.lineWidth)&&yp(t,"lineWidth",$t(o.lineWidth)?vp.lineWidth:o.lineWidth,r.currentContext),(n||o.lineDash!==i.lineDash)&&yp(t,"lineDash",o.lineDash||vp.lineDash,r.currentContext),(n||o.lineDashOffset!==i.lineDashOffset)&&yp(t,"lineDashOffset",$t(o.lineDashOffset)?vp.lineDashOffset:o.lineDashOffset,r.currentContext);for(var u=0;u4&&void 0!==arguments[4]&&arguments[4];if(e){yp(t,"shadowColor",vp.shadowColor,r.currentContext);for(var o=0;o-1&&yp(t,"filter",s.replace(/drop-shadow\([^)]*\)/,"").trim()||vp.filter,r.currentContext)}else yp(t,"filter",vp.filter,r.currentContext)}},{key:"fillToContext",value:function(t,e,n,r,i){var o=this,a=e.parsedStyle,s=a.fill,l=a.fillRule,u=null;if(Array.isArray(s)&&s.length>0)s.forEach((function(r){var i=yp(t,"fillStyle",fp(r,e,t,o.imagePool),n.currentContext);u=null!=u?u:i,l?t.fill(l):t.fill()}));else{if(yo(s)){var c=dp(s,e,t,e.ownerDocument.defaultView.context,r,i,this.imagePool);c&&(t.fillStyle=c,u=!0)}l?t.fill(l):t.fill()}null!==u&&yp(t,"fillStyle",u,n.currentContext)}},{key:"strokeToContext",value:function(t,e,n,r,i){var o=this,a=e.parsedStyle.stroke,s=null;if(Array.isArray(a)&&a.length>0)a.forEach((function(r){var i=yp(t,"strokeStyle",fp(r,e,t,o.imagePool),n.currentContext);s=null!=s?s:i,t.stroke()}));else{if(yo(a)){var l=dp(a,e,t,e.ownerDocument.defaultView.context,r,i,this.imagePool);if(l){var u=yp(t,"strokeStyle",l,n.currentContext);s=null!=s?s:u}}t.stroke()}null!==s&&yp(t,"strokeStyle",s,n.currentContext)}},{key:"drawToContext",value:function(t,e,n,r,i){var o,a=e.nodeName,s=e.parsedStyle,l=s.opacity,u=void 0===l?vp.globalAlpha:l,c=s.fillOpacity,h=void 0===c?vp.fillOpacity:c,d=s.strokeOpacity,f=void 0===d?vp.strokeOpacity:d,p=s.lineWidth,g=void 0===p?vp.lineWidth:p,v=s.fill&&!s.fill.isNone,m=s.stroke&&!s.stroke.isNone&&g>0;if(v||m){var y=!$t(s.shadowColor)&&s.shadowBlur>0,b="inner"===s.shadowType,x=0===(null===(o=s.fill)||void 0===o?void 0:o.alpha),E=!(!s.filter||!s.filter.length),w=y&&m&&(a===hr.PATH||a===hr.LINE||a===hr.POLYLINE||x||b),k=null;if(v)w||this.applyShadowAndFilterStyleToContext(t,e,y,n),k=yp(t,"globalAlpha",u*h,n.currentContext),this.fillToContext(t,e,n,r,i),w||this.clearShadowAndFilterStyleForContext(t,y,E,n);if(m){var M=!1,S=yp(t,"globalAlpha",u*f,n.currentContext);if(k=v?k:S,w&&(this.applyShadowAndFilterStyleToContext(t,e,y,n),M=!0,b)){var N=t.globalCompositeOperation;t.globalCompositeOperation="source-atop",this.strokeToContext(t,e,n,r,i),t.globalCompositeOperation=N,this.clearShadowAndFilterStyleForContext(t,y,E,n,!0)}this.strokeToContext(t,e,n,r,i),M&&this.clearShadowAndFilterStyleForContext(t,y,E,n)}null!==k&&yp(t,"globalAlpha",k,n.currentContext)}}}])}(),xp=function(t){function e(){return s(this,e),v(this,e,arguments)}return y(e,t),u(e,[{key:"render",value:function(t,e,n,r,i,o){var a=e.fill,s=e.fillRule,l=e.opacity,u=void 0===l?1:l,c=e.fillOpacity,h=void 0===c?1:c,d=e.stroke,f=e.strokeOpacity,p=void 0===f?1:f,g=e.lineWidth,v=void 0===g?1:g,m=e.lineCap,y=e.lineJoin,b=e.shadowType,x=e.shadowColor,E=e.shadowBlur,w=e.filter,k=e.miterLimit,M=a&&!a.isNone,S=d&&!d.isNone&&v>0,N=0===(null==a?void 0:a.alpha),O=!(!w||!w.length),T=!$t(x)&&E>0,C=n.nodeName,A="inner"===b,P=S&&T&&(C===hr.PATH||C===hr.LINE||C===hr.POLYLINE||N||A);M&&(t.globalAlpha=u*h,P||Ep(n,t,T),wp(t,n,a,s,r,i,o,this.imagePool),P||this.clearShadowAndFilter(t,O,T)),S&&(t.globalAlpha=u*p,t.lineWidth=v,$t(k)||(t.miterLimit=k),$t(m)||(t.lineCap=m),$t(y)||(t.lineJoin=y),P&&(A&&(t.globalCompositeOperation="source-atop"),Ep(n,t,!0),A&&(kp(t,n,d,r,i,o,this.imagePool),t.globalCompositeOperation=vp.globalCompositeOperation,this.clearShadowAndFilter(t,O,!0))),kp(t,n,d,r,i,o,this.imagePool))}},{key:"clearShadowAndFilter",value:function(t,e,n){if(n&&(t.shadowColor="transparent",t.shadowBlur=0),e){var r=t.filter;!$t(r)&&r.indexOf("drop-shadow")>-1&&(t.filter=r.replace(/drop-shadow\([^)]*\)/,"").trim()||"none")}}}])}(bp);function Ep(t,e,n){var r=t.parsedStyle,i=r.filter,o=r.shadowColor,a=r.shadowBlur,s=r.shadowOffsetX,l=r.shadowOffsetY;i&&i.length&&(e.filter=t.style.filter),n&&(e.shadowColor=o.toString(),e.shadowBlur=a||0,e.shadowOffsetX=s||0,e.shadowOffsetY=l||0)}function wp(t,e,n,r,i,o,a,s){var l=arguments.length>8&&void 0!==arguments[8]&&arguments[8];Array.isArray(n)?n.forEach((function(n){t.fillStyle=fp(n,e,t,s),l||(r?t.fill(r):t.fill())})):(yo(n)&&(t.fillStyle=dp(n,e,t,i,o,a,s)),l||(r?t.fill(r):t.fill()))}function kp(t,e,n,r,i,o,a){var s=arguments.length>7&&void 0!==arguments[7]&&arguments[7];Array.isArray(n)?n.forEach((function(n){t.strokeStyle=fp(n,e,t,a),s||t.stroke()})):(yo(n)&&(t.strokeStyle=dp(n,e,t,r,i,o,a)),s||t.stroke())}var Mp=function(t){function e(){return s(this,e),v(this,e,arguments)}return y(e,t),u(e,[{key:"renderDownSampled",value:function(t,e,n,r){var i=r.src,o=r.imageCache;o.downSampled?t.drawImage(o.downSampled,Math.floor(r.drawRect[0]),Math.floor(r.drawRect[1]),Math.ceil(r.drawRect[2]),Math.ceil(r.drawRect[3])):this.imagePool.createDownSampledImage(i,n).then((function(){n.ownerDocument&&(n.renderable.dirty=!0,n.ownerDocument.defaultView.context.renderingService.dirtify())})).catch((function(t){console.error(t)}))}},{key:"renderTile",value:function(t,e,n,r){var i=r.src,o=r.imageCache,a=r.imageRect,s=r.drawRect,l=o.size,u=t.getTransform(),c=u.a,h=u.b,d=u.c,f=u.d,p=u.e,g=u.f;if(t.resetTransform(),null!=o&&o.gridSize){for(var v=[l[0]/a[2],l[1]/a[3]],m=[o.tileSize[0]/v[0],o.tileSize[1]/v[1]],y=[Math.floor((s[0]-a[0])/m[0]),Math.ceil((s[0]+s[2]-a[0])/m[0])],b=y[0],x=y[1],E=[Math.floor((s[1]-a[1])/m[1]),Math.ceil((s[1]+s[3]-a[1])/m[1])],w=E[1],k=E[0];k<=w;k++)for(var M=b;M<=x;M++){var S=o.tiles[k][M];if(S){var N=[Math.floor(a[0]+S.tileX*m[0]),Math.floor(a[1]+S.tileY*m[1]),Math.ceil(m[0]),Math.ceil(m[1])];t.drawImage(S.data,N[0],N[1],N[2],N[3])}}t.setTransform(c,h,d,f,p,g)}else this.imagePool.createImageTiles(i,[],(function(){n.ownerDocument&&(n.renderable.dirty=!0,n.ownerDocument.defaultView.context.renderingService.dirtify())}),n).catch((function(t){console.error(t)}))}},{key:"render",value:function(t,n,r){var i=n.x,o=void 0===i?0:i,a=n.y,s=void 0===a?0:a,l=n.width,u=n.height,c=n.src,h=n.shadowColor,d=n.shadowBlur,f=this.imagePool.getImageSync(c,r),p=null==f?void 0:f.img,g=l,v=u;if(p){var m,y,x,E,w,k,M,S,N,O,T,C,A,R,D;g||(g=p.width),v||(v=p.height),Ep(r,t,!$t(h)&&d>0);try{var L=r.ownerDocument.defaultView.getContextService().getDomElement(),_=L.width,I=L.height,j=t.getTransform(),B=j.a,F=j.b,z=function(t,e){var n=Mt(ht(),[t[0],t[1],0],e),r=Mt(ht(),[t[0]+t[2],t[1],0],e),i=Mt(ht(),[t[0],t[1]+t[3],0],e),o=Mt(ht(),[t[0]+t[2],t[1]+t[3],0],e);return[Math.min(n[0],r[0],i[0],o[0]),Math.min(n[1],r[1],i[1],o[1]),Math.max(n[0],r[0],i[0],o[0])-Math.min(n[0],r[0],i[0],o[0]),Math.max(n[1],r[1],i[1],o[1])-Math.min(n[1],r[1],i[1],o[1])]}([o,s,g,v],P(B,j.c,0,0,F,j.d,0,0,0,0,1,0,j.e,j.f,0,1)),G=(m=z,y=b([0,0,_,I],4),x=y[0],E=y[1],w=y[2],k=y[3],M=b(m,4),S=M[0],N=M[1],O=M[2],T=M[3],C=Math.max(x,S),A=Math.max(E,N),R=Math.min(x+w,S+O),D=Math.min(E+k,N+T),R<=C||D<=A?null:[C,A,R-C,D-A]);if(!G)return;if(!r.ownerDocument.defaultView.getConfig().enableLargeImageOptimization)return void e.renderFull(t,n,r,{image:p,drawRect:[o,s,g,v]});if(z[2]/f.size[0]<(f.downSamplingRate||.5))return void this.renderDownSampled(t,n,r,{src:c,imageCache:f,drawRect:[o,s,g,v]});if(!ap.isSupportTile)return void e.renderFull(t,n,r,{image:p,drawRect:[o,s,g,v]});this.renderTile(t,n,r,{src:c,imageCache:f,imageRect:z,drawRect:G})}catch(t){}}}},{key:"drawToContext",value:function(t,e,n,r,i){this.render(t,e.parsedStyle,e)}}],[{key:"renderFull",value:function(t,e,n,r){t.drawImage(r.image,Math.floor(r.drawRect[0]),Math.floor(r.drawRect[1]),Math.ceil(r.drawRect[2]),Math.ceil(r.drawRect[3]))}}])}(xp),Sp=function(t){function e(){return s(this,e),v(this,e,arguments)}return y(e,t),u(e,[{key:"render",value:function(t,e,n,r,i,o){n.getBounds();var a=e.lineWidth,s=void 0===a?1:a,l=e.textAlign,u=void 0===l?"start":l,c=e.textBaseline,h=void 0===c?"alphabetic":c,d=e.lineJoin,f=void 0===d?"miter":d,p=e.miterLimit,g=void 0===p?10:p,v=e.letterSpacing,m=void 0===v?0:v,y=e.stroke,b=e.fill,x=e.fillRule,E=e.fillOpacity,w=void 0===E?1:E,k=e.strokeOpacity,M=void 0===k?1:k,S=e.opacity,N=void 0===S?1:S,O=e.metrics,T=e.x,C=void 0===T?0:T,A=e.y,P=void 0===A?0:A,R=e.dx,D=e.dy,L=e.shadowColor,_=e.shadowBlur,I=O.font,j=O.lines,B=O.height,F=O.lineHeight,z=O.lineMetrics;t.font=I,t.lineWidth=s,t.textAlign="middle"===u?"center":u;var G=h;"alphabetic"===G&&(G="bottom"),t.lineJoin=f,$t(g)||(t.miterLimit=g);var V=P;"middle"===h?V+=-B/2-F/2:"bottom"===h||"alphabetic"===h||"ideographic"===h?V+=-B:"top"!==h&&"hanging"!==h||(V+=-F);var W=C+(R||0);V+=D||0,1===j.length&&("bottom"===G?(G="middle",V-=.5*B):"top"===G&&(G="middle",V+=.5*B)),t.textBaseline=G,Ep(n,t,!$t(L)&&_>0);for(var H=0;H0&&void 0!==arguments[0]?arguments[0]:{};return s(this,e),(t=v(this,e)).name="canvas-renderer",t.options=n,t}return y(e,t),u(e,[{key:"init",value:function(){var t,e=a({dirtyObjectNumThreshold:500,dirtyObjectRatioThreshold:.8},this.options),n=this.context.imagePool,r=new xp(n),o=(i(i(i(i(i(i(i(i(i(i(t={},hr.CIRCLE,r),hr.ELLIPSE,r),hr.RECT,r),hr.IMAGE,new Mp(n)),hr.TEXT,new Sp(n)),hr.LINE,r),hr.POLYLINE,r),hr.POLYGON,r),hr.PATH,r),hr.GROUP,void 0),i(i(i(t,hr.HTML,void 0),hr.MESH,void 0),hr.FRAGMENT,void 0));this.context.defaultStyleRendererFactory=o,this.context.styleRendererFactory=o,this.addRenderingPlugin(new hp(e))}},{key:"destroy",value:function(){this.removeAllRenderingPlugins(),delete this.context.defaultStyleRendererFactory,delete this.context.styleRendererFactory}}])}(fr),Op=function(){function t(){s(this,t)}return u(t,[{key:"apply",value:function(e,n){var r=this,i=e.renderingService,o=e.renderingContext,a=e.config;this.context=e;var s=o.root.ownerDocument.defaultView,l=function(t){i.hooks.pointerMove.call(t)},u=function(t){i.hooks.pointerUp.call(t)},c=function(t){i.hooks.pointerDown.call(t)},h=function(t){i.hooks.pointerOver.call(t)},d=function(t){i.hooks.pointerOut.call(t)},f=function(t){i.hooks.pointerCancel.call(t)},p=function(t){i.hooks.pointerWheel.call(t)},g=function(t){i.hooks.click.call(t)};i.hooks.init.tap(t.tag,(function(){var t=r.context.contextService.getDomElement();n.globalThis.navigator.msPointerEnabled?(t.style.msContentZooming="none",t.style.msTouchAction="none"):s.supportsPointerEvents&&(t.style.touchAction="none"),s.supportsPointerEvents?function(t){n.globalThis.document.addEventListener("pointermove",l,!0),t.addEventListener("pointerdown",c,!0),t.addEventListener("pointerleave",d,!0),t.addEventListener("pointerover",h,!0),n.globalThis.addEventListener("pointerup",u,!0),n.globalThis.addEventListener("pointercancel",f,!0)}(t):function(t){n.globalThis.document.addEventListener("mousemove",l,!0),t.addEventListener("mousedown",c,!0),t.addEventListener("mouseout",d,!0),t.addEventListener("mouseover",h,!0),n.globalThis.addEventListener("mouseup",u,!0)}(t),s.supportsTouchEvents&&function(t){t.addEventListener("touchstart",c,!0),t.addEventListener("touchend",u,!0),t.addEventListener("touchmove",l,!0),t.addEventListener("touchcancel",f,!0)}(t),a.useNativeClickEvent&&t.addEventListener("click",g,!0),t.addEventListener("wheel",p,{passive:!0,capture:!0})})),i.hooks.destroy.tap(t.tag,(function(){var t=r.context.contextService.getDomElement();n.globalThis.navigator.msPointerEnabled?(t.style.msContentZooming="",t.style.msTouchAction=""):s.supportsPointerEvents&&(t.style.touchAction=""),s.supportsPointerEvents?function(t){n.globalThis.document.removeEventListener("pointermove",l,!0),t.removeEventListener("pointerdown",c,!0),t.removeEventListener("pointerleave",d,!0),t.removeEventListener("pointerover",h,!0),n.globalThis.removeEventListener("pointerup",u,!0),n.globalThis.removeEventListener("pointercancel",f,!0)}(t):function(t){n.globalThis.document.removeEventListener("mousemove",l,!0),t.removeEventListener("mousedown",c,!0),t.removeEventListener("mouseout",d,!0),t.removeEventListener("mouseover",h,!0),n.globalThis.removeEventListener("mouseup",u,!0)}(t),s.supportsTouchEvents&&function(t){t.removeEventListener("touchstart",c,!0),t.removeEventListener("touchend",u,!0),t.removeEventListener("touchmove",l,!0),t.removeEventListener("touchcancel",f,!0)}(t),a.useNativeClickEvent&&t.removeEventListener("click",g,!0),t.removeEventListener("wheel",p,!0)}))}}])}();Op.tag="DOMInteraction";var Tp=function(t){function e(){var t;s(this,e);for(var n=arguments.length,r=new Array(n),i=0;i1&&void 0!==arguments[1]?arguments[1]:[0,0,0];return"matrix(".concat([t[0],t[1],t[4],t[5],t[12]+e[0],t[13]+e[1]].join(","),")")}},{key:"apply",value:function(e,n){var r=this,i=e.camera,o=e.renderingContext,a=e.renderingService;this.context=e;var s=o.root.ownerDocument.defaultView,l=s.context.eventService.nativeHTMLMap,u=function(t,e){e.style.transform=r.joinTransformMatrix(t.getWorldTransform(),t.getOrigin())},c=function(t){var e=t.target;if(e.nodeName===hr.HTML){r.$camera||(r.$camera=r.createCamera(i));var n=r.getOrCreateEl(e);r.$camera.appendChild(n),Object.keys(e.attributes).forEach((function(t){r.updateAttribute(t,e)})),u(e,n),l.set(n,e)}},h=function(t){var e=t.target;if(e.nodeName===hr.HTML&&r.$camera){var n=r.getOrCreateEl(e);n&&(n.remove(),l.delete(n))}},d=function(t){var e=t.target;if(e.nodeName===hr.HTML){var n=t.attrName;r.updateAttribute(n,e)}},f=function(t){var e=t.target;(e.nodeName===hr.FRAGMENT?e.childNodes:[e]).forEach((function(t){if(t.nodeName===hr.HTML){var e=r.getOrCreateEl(t);u(t,e)}}))},p=function(){if(r.$camera){var t=r.context.config,e=t.width,n=t.height;r.$camera.parentElement.style.width="".concat(e||0,"px"),r.$camera.parentElement.style.height="".concat(n||0,"px")}};a.hooks.init.tap(t.tag,(function(){s.addEventListener(fu.RESIZE,p),s.addEventListener(Ks.MOUNTED,c),s.addEventListener(Ks.UNMOUNTED,h),s.addEventListener(Ks.ATTR_MODIFIED,d),s.addEventListener(Ks.BOUNDS_CHANGED,f)})),a.hooks.endFrame.tap(t.tag,(function(){r.$camera&&o.renderReasons.has($s.CAMERA_CHANGED)&&(r.$camera.style.transform=r.joinTransformMatrix(i.getOrthoMatrix()))})),a.hooks.destroy.tap(t.tag,(function(){r.$camera&&r.$camera.remove(),s.removeEventListener(fu.RESIZE,p),s.removeEventListener(Ks.MOUNTED,c),s.removeEventListener(Ks.UNMOUNTED,h),s.removeEventListener(Ks.ATTR_MODIFIED,d),s.removeEventListener(Ks.BOUNDS_CHANGED,f)}))}},{key:"createCamera",value:function(t){var e=this.context.config,n=e.document,r=e.width,i=e.height,o=this.context.contextService.getDomElement(),a=o.parentNode;if(a){var s="g-canvas-camera",l=a.querySelector("#".concat(s));if(!l){var u=(n||document).createElement("div");u.style.overflow="hidden",u.style.pointerEvents="none",u.style.position="absolute",u.style.left="0px",u.style.top="0px",u.style.width="".concat(r||0,"px"),u.style.height="".concat(i||0,"px");var c=(n||document).createElement("div");l=c,c.id=s,c.style.position="absolute",c.style.left="".concat(o.offsetLeft||0,"px"),c.style.top="".concat(o.offsetTop||0,"px"),c.style.transformOrigin="left top",c.style.transform=this.joinTransformMatrix(t.getOrthoMatrix()),c.style.pointerEvents="none",c.style.width="100%",c.style.height="100%",u.appendChild(c),a.appendChild(u)}return l}return null}},{key:"getOrCreateEl",value:function(t){var e=this.context.config.document,n=this.displayObjectHTMLElementMap.get(t);return n||(n=(e||document).createElement("div"),t.parsedStyle.$el=n,this.displayObjectHTMLElementMap.set(t,n),t.id&&(n.id=t.id),t.name&&n.setAttribute("name",t.name),t.className&&(n.className=t.className),n.style.position="absolute",n.style["will-change"]="transform",n.style.transform=this.joinTransformMatrix(t.getWorldTransform(),t.getOrigin())),n}},{key:"updateAttribute",value:function(t,e){var n=this.getOrCreateEl(e);switch(t){case"innerHTML":var r=e.parsedStyle.innerHTML;ne(r)?n.innerHTML=r:(n.innerHTML="",n.appendChild(r));break;case"x":n.style.left="".concat(e.parsedStyle.x,"px");break;case"y":n.style.top="".concat(e.parsedStyle.y,"px");break;case"transformOrigin":var i=e.parsedStyle.transformOrigin;n.style["transform-origin"]="".concat(i[0].buildCSSText(null,null,"")," ").concat(i[1].buildCSSText(null,null,""));break;case"width":var o=e.parsedStyle.width;n.style.width=ae(o)?"".concat(o,"px"):o.toString();break;case"height":var a=e.parsedStyle.height;n.style.height=ae(a)?"".concat(a,"px"):a.toString();break;case"zIndex":var s=e.parsedStyle.zIndex;n.style["z-index"]="".concat(s);break;case"visibility":var l=e.parsedStyle.visibility;n.style.visibility=l;break;case"pointerEvents":var u=e.parsedStyle.pointerEvents,c=void 0===u?"auto":u;n.style.pointerEvents=c;break;case"opacity":var h=e.parsedStyle.opacity;n.style.opacity="".concat(h);break;case"fill":var d=e.parsedStyle.fill,f="";bo(d)?f=d.isNone?"transparent":e.getAttribute("fill"):Array.isArray(d)?f=e.getAttribute("fill"):yo(d),n.style.background=f;break;case"stroke":var p=e.parsedStyle.stroke,g="";bo(p)?g=p.isNone?"transparent":e.getAttribute("stroke"):Array.isArray(p)?g=e.getAttribute("stroke"):yo(p),n.style["border-color"]=g,n.style["border-style"]="solid";break;case"lineWidth":var v=e.parsedStyle.lineWidth;n.style["border-width"]="".concat(v||0,"px");break;case"lineDash":n.style["border-style"]="dashed";break;case"filter":var m=e.style.filter;n.style.filter=m;break;default:$t(e.style[t])||""===e.style[t]||(n.style[t]=e.style[t])}}}])}(); -/*! - * @antv/g-plugin-html-renderer - * @description A G plugin for rendering HTML - * @version 2.1.24 - * @date 5/9/2025, 8:20:22 AM - * @author AntVis - * @docs https://g.antv.antgroup.com/ - */Cp.tag="HTMLRendering";var Ap=function(t){function e(){var t;s(this,e);for(var n=arguments.length,r=new Array(n),i=0;i0&&void 0!==i[0]?i[0]:{}).type,r=e.encoderOptions,t.abrupt("return",this.context.canvas.toDataURL(n,r));case 3:case"end":return t.stop()}}),t,this)}))),function(){return t.apply(this,arguments)})}]);var t}(),Rp=function(t){function e(){var t;s(this,e);for(var n=arguments.length,r=new Array(n),i=0;i{const e=this.context.canvas,n=e.context.renderingContext.root.ownerDocument.defaultView;this.normalizeToPointerEvent(t,n).forEach((r=>{const i=this.bootstrapEvent(this.rootPointerEvent,r,n,t);Te(e.context.eventService,"mappingTable.pointerupoutside",[]),e.context.eventService.mapEvent(i)}))}}get eventService(){return this.context.canvas.context.eventService}get events(){return[t.CommonEvent.CLICK,t.CommonEvent.POINTER_DOWN,t.CommonEvent.POINTER_MOVE,t.CommonEvent.POINTER_UP,t.CommonEvent.POINTER_OVER,t.CommonEvent.POINTER_LEAVE]}getDomElement(){return this.getShape("key").getDomElement()}render(t=this.parsedAttributes,e=this){this.drawKeyShape(t,e),this.drawPortShapes(t,e)}getKeyStyle(t){const e=Ae(t,["dx","dy","innerHTML","pointerEvents","cursor"]),{dx:n=0,dy:r=0}=e,i=Fe(e,["dx","dy"]),[o,a]=this.getSize(t);return Object.assign(Object.assign({x:n,y:r},i),{width:o,height:a})}drawKeyShape(t,e){const n=this.getKeyStyle(t),{x:r,y:i,width:o=0,height:a=0}=n,s=this.upsert("key-container",ru,{x:r,y:i,width:o,height:a,opacity:0},e);return this.upsert("key",Yl,n,s)}connectedCallback(){if(!(this.context.canvas.getRenderer("main")instanceof Dp))return;const t=this.getDomElement();this.events.forEach((e=>{t.addEventListener(e,this.forwardEvents)}))}attributeChangedCallback(t,e,n){"zIndex"===t&&e!==n&&(this.getDomElement().style.zIndex=n)}destroy(){const t=this.getDomElement();this.events.forEach((e=>{t.removeEventListener(e,this.forwardEvents)})),super.destroy()}normalizeToPointerEvent(t,e){const n=[];if(e.isTouchEvent(t))for(let e=0;ethis.context.element.getElement(t))).filter(Boolean);if(0===r.length){const e=new Er,{x:n=0,y:r=0,size:i}=t,[o,a]=Gd(i);return e.setMinMax([n-o/2,r-a/2,0],[n+o/2,r+a/2,0]),e}const i=sh(r.map((t=>t.getBounds())));return n?ah(i,n):i}drawCollapsedMarkerShape(t,e){const n=this.getCollapsedMarkerStyle(t);this.upsert("collapsed-marker",uf,n,e),sf(this)}getCollapsedMarkerStyle(t){if(!t.collapsed||!t.collapsedMarker)return!1;const e=Bd(this.getGraphicStyle(t),"collapsedMarker"),{type:n}=e,r=Fe(e,["type"]),i=this.getShape("key"),[o,a]=ud(i.getLocalBounds(),"center"),s=Object.assign(Object.assign({},r),{x:o,y:a});if(n){const e=this.getCollapsedMarkerText(n,t);Object.assign(s,{text:e})}return s}getCollapsedMarkerText(t,e){const{childrenData:n=[]}=e,{model:r}=this.context;return"descendant-count"===t?r.getDescendantsData(this.id).length.toString():"child-count"===t?n.length.toString():"node-count"===t?r.getDescendantsData(this.id).filter((t=>"node"===r.getElementType(Nh(t)))).length.toString():Ut(t)?t(n):""}getComboPosition(t){const{x:e=0,y:n=0,collapsed:r,childrenData:i=[]}=t;if(0===i.length)return[+e,+n,0];if(r){const{model:t}=this.context,r=t.getDescendantsData(this.id).filter((e=>!t.isCombo(Nh(e))));if(r.length>0&&r.some(ld)){return Yh(r.reduce(((t,e)=>Hh(t,sd(e))),[0,0,0]),r.length)}return[+e,+n,0]}return this.getContentBBox(t).center}getComboStyle(t){const[e,n]=this.getComboPosition(t);return{x:e,y:n,transform:[["translate",e,n]]}}updateComboPosition(t){const e=this.getComboStyle(t);Object.assign(this.style,e);const{x:n,y:r}=e;this.context.model.syncNodeLikeDatum({id:this.id,style:{x:n,y:r}}),lf(this)}render(t,e=this){super.render(t,e),this.drawCollapsedMarkerShape(t,e)}update(t={}){super.update(t),this.updateComboPosition(this.parsedAttributes)}onframe(){super.onframe(),this.attributes.collapsed||this.updateComboPosition(this.parsedAttributes),this.drawKeyShape(this.parsedAttributes,this)}animate(t,e){const n=super.animate(this.attributes.collapsed?t:t.map((t=>{var{x:e,y:n,z:r,transform:i}=t;return Fe(t,["x","y","z","transform"])})),e);return n?new Proxy(n,{set:(t,e,n)=>("currentTime"===e&&Promise.resolve().then((()=>this.onframe())),Reflect.set(t,e,n))}):n}}Fp.defaultStyleProps={childrenNode:[],droppable:!0,draggable:!0,collapsed:!1,collapsedSize:32,collapsedMarker:!0,collapsedMarkerZIndex:1,collapsedMarkerFontSize:12,collapsedMarkerTextAlign:"center",collapsedMarkerTextBaseline:"middle",collapsedMarkerType:"child-count"};class zp extends Fp{constructor(t){super(t)}drawKeyShape(t,e){return this.upsert("key",Gl,this.getKeyStyle(t),e)}getKeyStyle(t){const{collapsed:e}=t,n=super.getKeyStyle(t),[r]=this.getKeySize(t);return Object.assign(Object.assign(Object.assign({},n),e&&Bd(n,"collapsed")),{r:r/2})}getCollapsedKeySize(t){const[e,n]=Gd(t.collapsedSize),r=Math.max(e,n)/2;return[2*r,2*r,0]}getExpandedKeySize(t){const e=this.getContentBBox(t),[n,r]=rh(e),i=Math.sqrt(Math.pow(n,2)+Math.pow(r,2))/2;return[2*i,2*i,0]}getIntersectPoint(t,e=!1){return yd(t,this.getShape("key").getBounds(),e)}}class Gp extends Fp{constructor(t){super(t)}drawKeyShape(t,e){return this.upsert("key",ru,this.getKeyStyle(t),e)}getKeyStyle(t){const e=super.getKeyStyle(t),[n,r]=this.getKeySize(t);return Object.assign(Object.assign(Object.assign({},e),t.collapsed&&Bd(e,"collapsed")),{width:n,height:r,x:-n/2,y:-r/2})}}const Vp={padding:10};function Wp(t,e,n,r,i,o){const{padding:a}=Object.assign(Vp,o),s=ih(n,a),l=ih(r,a),u=[t,...i,e];let c=null;const h=[];for(let t=0,e=u.length;to?"N":"S":r===o?n>i?"W":"E":null}function Yp(t,e){return"N"===e||"S"===e?nh(t):eh(t)}function qp(t,e,n){const r=[t[0],e[1]],i=[e[0],t[1]],o=$p(t,r),a=$p(t,i),s=n?Hp[n]:null,l=o===n||o!==s&&a!==n?r:i;return{points:[l],direction:$p(l,e)}}function Xp(t,e,n){if(ch(t,n)){const r=Jp(t,e,n);return{points:[r],direction:$p(r,e)}}{const r=dh(t,n),i=["left","right"].includes(hh(t,n))?[e[0],r[1]]:[r[0],e[1]];return{points:[i],direction:$p(i,e)}}}function Kp(t,e,n,r){const i=ch(e,n)?e:dh(e,n),o=[[i[0],t[1]],[t[0],i[1]]],a=o.filter((t=>function(t,e){return!lh(t,e)}(t,n)&&!uh(t,n,!0))),s=a.filter((e=>$p(e,t)!==r));if(s.length>0){const n=s.find((e=>$p(t,e)===r))||s[0];return{points:[n],direction:$p(n,e)}}{const i=fd(e,Ht(o,a)[0],Yp(n,r)/2);return{points:[Jp(i,t,n),i],direction:$p(i,e)}}}function Zp(t,e,n,r){let i=Xp(t,e,n);const o=nd(i.points[0]);if(lh(o,r)){i=Xp(e,t,r);const a=nd(i.points[0]);if(lh(a,n)){const s=fd(t,o,Yp(n,$p(t,o))/2),l=fd(e,a,Yp(r,$p(e,a))/2),u=[(s[0]+l[0])/2,(s[1]+l[1])/2],c=Xp(t,u,n),h=Kp(u,e,r,c.direction);i.points=[c.points[0],h.points[0]],i.direction=h.direction}}return i}function Qp(t,e,n,r,i){const o=.01,a=sh([n,r]),s=Xh(e,a.center)>Xh(t,a.center),[l,u]=s?[e,t]:[t,e],c=nh(a)+eh(a);let h;if(i){const t=[l[0]+c*Math.cos(Up[i]),l[1]+c*Math.sin(Up[i])];h=fd(dh(t,a),t,o)}else h=fd(dh(l,a),l,-.01);let d=Jp(h,u,a),f=[dd(h,2),dd(d,2)];if(Ne(dd(h),dd(d))){const t=Qh(Uh(h,l),[1,0,0])+Math.PI/2;d=[u[0]+c*Math.cos(t),u[1]+c*Math.sin(t),0],d=dd(fd(dh(d,a),u,-.01),2);f=[h,Jp(h,d,a),d]}return{points:s?f.reverse():f,direction:$p(s?h:d,e)}}function Jp(t,e,n){let r=[t[0],e[1]];return lh(r,n)&&(r=[e[0],t[1]]),r}function tg(t,e,n,r,i){let o="number"==typeof e?e:.5;"start"===e&&(o=0),"end"===e&&(o=.99);const a=cd(t.getPoint(o)),s=cd(t.getPoint(o+.01));let l="start"===e?"left":"end"===e?"right":"center";if(pd(a,s)||!n){const[e,n]=eg(t,o,r,i);return{transform:[["translate",e,n]],textAlign:l}}let u=Math.atan2(s[1]-a[1],s[0]-a[0]);s[0]{const r=a[n-1]||i,l=a[n+1]||o;if(!gd(r,t,l)&&e){const[n,i]=function(t,e,n,r){const i=Kh(t,e),o=Kh(n,e),a=Math.min(r,Math.min(i,o)/2),s=[e[0]-a/i*(e[0]-t[0]),e[1]-a/i*(e[1]-t[1])],l=[e[0]-a/o*(e[0]-n[0]),e[1]-a/o*(e[1]-n[1])];return[s,l]}(r,t,l,e);s.push(["L",n[0],n[1]],["Q",t[0],t[1],i[0],i[1]],["L",i[0],i[1]])}else s.push(["L",t[0],t[1]])})),s.push(["L",o[0],o[1]]),n&&s.push(["Z"]),s}function og(t,e,n,r,i){const o=ih(t),a=t.getCenter();let s=r&&jg(r),l=i&&jg(i);if(!s||!l){const r=(t=>{const e=Math.PI/2,n=nh(t)/2,r=eh(t)/2,i=Math.atan2(n,r)/2,o=Math.atan2(r,n)/2;return{top:[-e-o,-e+o],"top-right":[-e+o,-i],"right-top":[-e+o,-i],right:[-i,i],"bottom-right":[i,e-o],"right-bottom":[i,e-o],bottom:[e-o,e+o],"bottom-left":[e+o,Math.PI-i],"left-bottom":[e+o,Math.PI-i],left:[Math.PI-i,Math.PI+i],"top-left":[Math.PI+i,-e-o],"left-top":[Math.PI+i,-e-o]}})(o),i=r[e][0],u=r[e][1],[c,h]=rh(o),d=Math.max(c,h),f=Hh(a,[d*Math.cos(i),d*Math.sin(i),0]),p=Hh(a,[d*Math.cos(u),d*Math.sin(u),0]);s=Gg(t,f),l=Gg(t,p),n||([s,l]=[l,s])}return[s,l]}function ag(t,e,n,r,i,o){const a=t.getPorts()[i||o],s=t.getPorts()[o||i];let[l,u]=og(t,e,n,a,s);const c=function(t,e,n,r){const i=t.getCenter();if(Ne(e,n)){const t=Uh(e,i),o=[r*Math.sign(t[0])||r/2,r*Math.sign(t[1])||-r/2,0];return[Hh(e,o),Hh(n,$h(o,[1,-1,1]))]}return[fd(i,e,Xh(i,e)+r),fd(i,n,Xh(i,n)+r)]}(t,l,u,r);return a&&(l=zg(a,c[0])),s&&(u=zg(s,c.at(-1))),rg(l,u,c)}function sg(t,e,n,r,i,o,a){const s=_g(t),l=s[o||a],u=s[a||o];let[c,h]=og(t,n,r,l,u);const d=function(t,e,n,r){const i=[],o=ih(t);if(Ne(e,n)){switch(hh(e,o)){case"left":i.push([e[0]-r,e[1]]),i.push([e[0]-r,e[1]+r]),i.push([e[0],e[1]+r]);break;case"right":i.push([e[0]+r,e[1]]),i.push([e[0]+r,e[1]+r]),i.push([e[0],e[1]+r]);break;case"top":i.push([e[0],e[1]-r]),i.push([e[0]+r,e[1]-r]),i.push([e[0]+r,e[1]]);break;case"bottom":i.push([e[0],e[1]+r]),i.push([e[0]+r,e[1]+r]),i.push([e[0]+r,e[1]])}}else{const t=hh(e,o),a=hh(n,o);if(t===a){let o,a;switch(t){case"left":o=Math.min(e[0],n[0])-r,i.push([o,e[1]]),i.push([o,n[1]]);break;case"right":o=Math.max(e[0],n[0])+r,i.push([o,e[1]]),i.push([o,n[1]]);break;case"top":a=Math.min(e[1],n[1])-r,i.push([e[0],a]),i.push([n[0],a]);break;case"bottom":a=Math.max(e[1],n[1])+r,i.push([e[0],a]),i.push([n[0],a])}}else{const s=(t,e)=>({left:[e[0]-r,e[1]],right:[e[0]+r,e[1]],top:[e[0],e[1]-r],bottom:[e[0],e[1]+r]}[t]),l=s(t,e),u=s(a,n),c=Jp(l,u,o);i.push(l,c,u)}}return i}(t,c,h,i);return l&&(c=zg(l,d[0])),u&&(h=zg(u,d.at(-1))),ig([c,...d,h],e)}function lg(t,e){const n=new Set,r=new Set,i=new Set;return t.forEach((o=>{e(o).forEach((e=>{n.add(e),t.includes(e.source)&&t.includes(e.target)?r.add(e):i.add(e)}))})),{edges:Array.from(n),internal:Array.from(r),external:Array.from(i)}}function ug(t,e){const n=[];let r=t;for(;r;){n.push(r);const t=e(Nh(r));if(!t)break;r=t}if(n.some((t=>{var e;return null===(e=t.style)||void 0===e?void 0:e.collapsed}))){const t=n.reverse().findIndex(_d);return n[t]||n.at(-1)}return t}const cg=(t,e)=>[["M",-t/2,0],["L",t/2,-e/2],["L",t/2,e/2],["Z"]];var hg=Object.freeze({__proto__:null,circle:(t,e)=>{const n=Math.max(t,e)/2;return[["M",-t/2,0],["A",n,n,0,1,0,2*n-t/2,0],["A",n,n,0,1,0,-t/2,0],["Z"]]},diamond:(t,e)=>[["M",-t/2,0],["L",0,-e/2],["L",t/2,0],["L",0,e/2],["Z"]],rect:(t,e)=>[["M",-t/2,-e/2],["L",t/2,-e/2],["L",t/2,e/2],["L",-t/2,e/2],["Z"]],simple:(t,e)=>[["M",t/2,-e/2],["L",-t/2,0],["L",t/2,0],["L",-t/2,0],["L",t/2,e/2]],triangle:cg,triangleRect:(t,e)=>{const n=t/2,r=t/7,i=t-r;return[["M",-n,0],["L",0,-e/2],["L",0,e/2],["Z"],["M",i-n,-e/2],["L",i+r-n,-e/2],["L",i+r-n,e/2],["L",i-n,e/2],["Z"]]},vee:(t,e)=>[["M",-t/2,0],["L",t/2,-e/2],["L",4*t/5-t/2,0],["L",t/2,e/2],["Z"]]});class dg extends cf{constructor(t){super(Wd({style:dg.defaultStyleProps},t)),this.type="edge"}get sourceNode(){const{sourceNode:t}=this.parsedAttributes;return this.context.element.getElement(t)}get targetNode(){const{targetNode:t}=this.parsedAttributes;return this.context.element.getElement(t)}getKeyStyle(t){const e=this.getGraphicStyle(t),{loop:n}=e,r=Fe(e,["loop"]),{sourceNode:i,targetNode:o}=this;var a,s;const l={d:n&&(s=o,(a=i)&&s&&a===s)?this.getLoopPath(t):this.getKeyPath(t)};return Ql.PARSED_STYLE_LIST.forEach((t=>{t in r&&(l[t]=r[t])})),l}getLoopPath(t){const{sourcePort:e,targetPort:n}=t,r=this.sourceNode,i=ih(r),o=Math.max(eh(i),nh(i)),{placement:a,clockwise:s,dist:l=o}=Bd(this.getGraphicStyle(t),"loop");return ag(r,a,s,l,e,n)}getEndpoints(t,e=!0,n=[]){const{sourcePort:r,targetPort:i}=t,{sourceNode:o,targetNode:a}=this,[s,l]=function(t,e,n,r){const i=Bg(t,e,n,r),o=Bg(e,t,r,n);return[i,o]}(o,a,r,i);if(!e){return[s?jg(s):o.getCenter(),l?jg(l):a.getCenter()]}const u="function"==typeof n?n():n;return[Fg(s||o,u[0]||l||a),Fg(l||a,u[u.length-1]||s||o)]}getHaloStyle(t){if(!1===t.halo)return!1;const e=this.getKeyStyle(t),n=Bd(this.getGraphicStyle(t),"halo");return Object.assign(Object.assign({},e),n)}getLabelStyle(t){if(!1===t.label||!t.labelText)return!1;const e=Bd(this.getGraphicStyle(t),"label"),{placement:n,offsetX:r,offsetY:i,autoRotate:o,maxWidth:a}=e,s=Fe(e,["placement","offsetX","offsetY","autoRotate","maxWidth"]),l=tg(this.shapeMap.key,n,o,r,i),u=this.shapeMap.key.getLocalBounds(),c=function(t,e,n=1){return $d(Xh(t[0],t[1])*n,e)}([u.min,u.max],a);return Object.assign({wordWrapWidth:c},l,s)}getBadgeStyle(t){if(!1===t.badge||!t.badgeText)return!1;const e=Bd(t,"badge"),{offsetX:n,offsetY:r,placement:i}=e,o=Fe(e,["offsetX","offsetY","placement"]);return Object.assign(o,function(t,e,n,r,i){var o,a;const s=2*(null===(o=t.badge)||void 0===o?void 0:o.getGeometryBounds().halfExtents[0])||0,l=2*(null===(a=t.label)||void 0===a?void 0:a.getGeometryBounds().halfExtents[0])||0;return tg(t.key,n,!0,(l?(l/2+s/2)*("suffix"===e?1:-1):0)+r,i)}(this.shapeMap,i,t.labelPlacement,n,r))}drawArrow(t,e){var n;const r="start"===e,i=t["start"===e?"startArrow":"endArrow"],o=this.shapeMap.key;if(i){const e=this.getArrowStyle(t,r),[n,i,a]=r?["markerStart","markerStartOffset","startArrowOffset"]:["markerEnd","markerEndOffset","endArrowOffset"],s=o.parsedStyle[n];if(s)s.attr(e);else{const t=new(e.src?ql:Ql)({style:e});o.style[n]=t}o.style[i]=t[a]||e.width/2+ +e.lineWidth}else{const t=r?"markerStart":"markerEnd";null===(n=o.style[t])||void 0===n||n.destroy(),o.style[t]=null}}getArrowStyle(t,e){const n=this.getShape("key").attributes,r=e?"startArrow":"endArrow",i=Bd(this.getGraphicStyle(t),r),{size:o,type:a}=i,s=Fe(i,["size","type"]),[l,u]=Gd(function(t,e){return e||(t<4?10:4===t?12:2.5*t)}(n.lineWidth,o)),c=(Ut(a)?a:hg[a]||cg)(l,u);return Object.assign(Ae(n,["stroke","strokeOpacity","fillOpacity"]),{width:l,height:u},Object.assign({},c&&{d:c,fill:"simple"===a?"":n.stroke}),s)}drawLabelShape(t,e){const n=this.getLabelStyle(t);this.upsert("label",Zd,n,e)}drawHaloShape(t,e){const n=this.getHaloStyle(t);this.upsert("halo",Ql,n,e)}drawBadgeShape(t,e){const n=this.getBadgeStyle(t);this.upsert("badge",Qd,n,e)}drawSourceArrow(t){this.drawArrow(t,"start")}drawTargetArrow(t){this.drawArrow(t,"end")}drawKeyShape(t,e){const n=this.getKeyStyle(t);return this.upsert("key",Ql,n,e)}render(t=this.parsedAttributes,e=this){this.drawKeyShape(t,e),this.getShape("key")&&(this.drawSourceArrow(t),this.drawTargetArrow(t),this.drawLabelShape(t,e),this.drawHaloShape(t,e),this.drawBadgeShape(t,e))}onframe(){this.drawKeyShape(this.parsedAttributes,this),this.drawSourceArrow(this.parsedAttributes),this.drawTargetArrow(this.parsedAttributes),this.drawHaloShape(this.parsedAttributes,this),this.drawLabelShape(this.parsedAttributes,this),this.drawBadgeShape(this.parsedAttributes,this)}animate(t,e){const n=super.animate(t,e);return n?new Proxy(n,{set:(t,e,n)=>("currentTime"===e&&Promise.resolve().then((()=>this.onframe())),Reflect.set(t,e,n))}):n}}dg.defaultStyleProps={badge:!0,badgeOffsetX:0,badgeOffsetY:0,badgePlacement:"suffix",isBillboard:!0,label:!0,labelAutoRotate:!0,labelIsBillboard:!0,labelMaxWidth:"80%",labelOffsetX:4,labelOffsetY:0,labelPlacement:"center",labelTextBaseline:"middle",labelWordWrap:!1,halo:!1,haloDroppable:!1,haloLineDash:0,haloLineWidth:12,haloPointerEvents:"none",haloStrokeOpacity:.25,haloZIndex:-1,loop:!0,startArrow:!1,startArrowLineDash:0,startArrowLineJoin:"round",startArrowLineWidth:1,startArrowTransformOrigin:"center",startArrowType:"vee",endArrow:!1,endArrowLineDash:0,endArrowLineJoin:"round",endArrowLineWidth:1,endArrowTransformOrigin:"center",endArrowType:"vee",loopPlacement:"top",loopClockwise:!0};class fg extends dg{constructor(t){super(Wd({style:fg.defaultStyleProps},t))}getKeyPath(t){const[e,n]=this.getEndpoints(t),{controlPoints:r,curvePosition:i,curveOffset:o}=t,a=this.getControlPoints(e,n,function(t){return ae(t)?[t,1-t]:t}(i),function(t){return ae(t)?[t,-t]:t}(o),r);return rg(e,n,a)}getControlPoints(t,e,n,r,i){return 2===(null==i?void 0:i.length)?i:[ng(t,e,n[0],r[0]),ng(t,e,n[1],r[1])]}}fg.defaultStyleProps={curvePosition:.5,curveOffset:20};class pg extends fg{constructor(t){super(Wd({style:pg.defaultStyleProps},t))}getControlPoints(t,e,n,r){const i=e[0]-t[0];return[[t[0]+i*n[0]+r[0],t[1]],[e[0]-i*n[1]+r[1],e[1]]]}}pg.defaultStyleProps={curvePosition:[.5,.5],curveOffset:[0,0]};class gg extends fg{constructor(t){super(Wd({style:gg.defaultStyleProps},t))}get ref(){return this.context.model.getRootsData()[0]}getEndpoints(t){if(this.sourceNode.id===this.ref.id)return super.getEndpoints(t);const e=sd(this.ref);return[this.sourceNode.getIntersectPoint(e,!0),this.targetNode.getIntersectPoint(e)]}toRadialCoordinate(t){const e=sd(this.ref);return[Xh(t,e),rd(Uh(t,e))]}getControlPoints(t,e,n,r){const[i,o]=this.toRadialCoordinate(t),[a]=this.toRadialCoordinate(e),s=a-i;return[[t[0]+(s*n[0]+r[0])*Math.cos(o),t[1]+(s*n[0]+r[0])*Math.sin(o)],[e[0]-(s*n[1]-r[0])*Math.cos(o),e[1]-(s*n[1]-r[0])*Math.sin(o)]]}}gg.defaultStyleProps={curvePosition:.5,curveOffset:20};class vg extends fg{constructor(t){super(Wd({style:vg.defaultStyleProps},t))}getControlPoints(t,e,n,r){const i=e[1]-t[1];return[[t[0],t[1]+i*n[0]+r[0]],[e[0],e[1]-i*n[1]+r[1]]]}}vg.defaultStyleProps={curvePosition:[.5,.5],curveOffset:[0,0]};let mg=class t extends dg{constructor(e){super(Wd({style:t.defaultStyleProps},e))}getKeyPath(t){const[e,n]=this.getEndpoints(t);return[["M",e[0],e[1]],["L",n[0],n[1]]]}};mg.defaultStyleProps={};const yg={enableObstacleAvoidance:!1,offset:10,maxAllowedDirectionChange:Math.PI/2,maximumLoops:3e3,gridSize:5,startDirections:["top","right","bottom","left"],endDirections:["top","right","bottom","left"],directionMap:{right:{stepX:1,stepY:0},left:{stepX:-1,stepY:0},bottom:{stepX:0,stepY:1},top:{stepX:0,stepY:-1}},penalties:{0:0,90:0},distFunc:Kh},bg=t=>`${Math.round(t[0])}|||${Math.round(t[1])}`;function xg(t,e){const n=t=>Math.round(t/e);return ae(t)?n(t):t.map(n)}function Eg(t,e){const n=e[0]-t[0],r=e[1]-t[1];return n||r?Math.atan2(r,n):0}function wg(t,e,n,r){const i=Eg(t,e),o=n[bg(t)];return function(t,e){const n=Math.abs(t-e);return n>Math.PI?2*Math.PI-n:n}(Eg(o||r,t),i)}function kg(t,e,n){return Math.min(...e.map((e=>n(t,e))))}const Mg=(t,e,n,r)=>{if(!e)return[t];const{directionMap:i,offset:o}=r,a=ah(e.getRenderBounds(),o),s=Object.keys(i).reduce(((e,r)=>{if(n.includes(r)){const n=i[r],[o,s]=rh(a),l=[t[0]+n.stepX*o,t[1]+n.stepY*s],u=function(t){const{min:[e,n],max:[r,i]}=t,o=[e,i],a=[r,i],s=[r,n],l=[e,n];return[[o,a],[a,s],[s,l],[l,o]]}(a);for(let n=0;nxg(t,r.gridSize)))},Sg=(t,e,n,r,i,o,a)=>{const s=[];let l=[o[0]===r[0]?r[0]:t[0]*a,o[1]===r[1]?r[1]:t[1]*a];s.unshift(l);let u=t,c=e[bg(u)];for(;c;){const t=c,r=u;wg(t,r,e,n)&&(l=[t[0]===r[0]?l[0]:t[0]*a,t[1]===r[1]?l[1]:t[1]*a],s.unshift(l)),c=e[bg(t)],u=t}const h=i.map((t=>[t[0]*a,t[1]*a])),d=function(t,e,n){let r=t[0],i=n(t[0],e);for(let o=0;o{const{offset:n,gridSize:r}=e,i={};return t.forEach((t=>{if(!t||t.destroyed||!t.isVisible())return;const e=ah(t.getRenderBounds(),n);for(let t=xg(e.min[0],r);t<=xg(e.max[0],r);t+=1)for(let n=xg(e.min[1],r);n<=xg(e.max[1],r);n+=1)i[`${t}|||${n}`]=!0})),i})(a.enableObstacleAvoidance?n:[t,e],a),u=xg(i,s),c=xg(o,s),h=Mg(i,t,a.startDirections,a),d=Mg(o,e,a.endDirections,a);h.forEach((t=>delete l[bg(t)])),d.forEach((t=>delete l[bg(t)]));const f={},p={},g={},v={},m={},y=new Og;for(let t=0;tbg(t)));let x,E=a.maximumLoops,w=1/0;for(const[t,e]of Object.entries(f))m[t]<=w&&(w=m[t],x=e);for(;Object.keys(f).length>0&&E>0;){const t=y.minId(!1);if(!t)break;x=f[t];const e=bg(x);if(b.includes(e))return Sg(x,g,u,o,h,c,s);delete f[e],y.remove(e),p[e]=!0;for(const t of Object.values(a.directionMap)){const n=Hh(x,[t.stepX,t.stepY]),r=bg(n);if(p[r])continue;const i=wg(x,n,g,u);if(i>a.maxAllowedDirectionChange)continue;if(l[r])continue;f[r]||(f[r]=n);const o=a.penalties[i],c=a.distFunc(x,n)+(isNaN(o)?s:o),h=v[e]+c,b=v[r];b&&h>=b||(g[r]=x,v[r]=h,m[r]=h+kg(n,d,a.distFunc),y.add({id:r,value:m[r]}))}E-=1}return[]}class Og{constructor(){this.arr=[],this.map={},this.arr=[],this.map={}}_innerAdd(t,e){let n=0,r=e-1;for(;r-n>1;){const e=Math.floor((n+r)/2);if(this.arr[e].value>t.value)r=e;else{if(!(this.arr[e].value=0;e--)this.map[this.arr[e].id]?t=this.arr[e].id:this.arr.splice(e,1);return t}_findFirstId(){for(;this.arr.length;){const t=this.arr.shift();if(this.map[t.id])return t.id}}minId(t){return t?this._clearAndGetMinId():this._findFirstId()}}class Tg extends dg{constructor(t){super(Wd({style:Tg.defaultStyleProps},t))}getControlPoints(t){const{router:e}=t,{sourceNode:n,targetNode:r}=this,[i,o]=this.getEndpoints(t,!1);let a=[];if(e)if("shortest-path"===e.type){a=Ng(n,r,this.context.element.getNodes(),e),a.length||(a=Wp(i,o,n,r,t.controlPoints,{padding:e.offset}))}else"orth"===e.type&&(a=Wp(i,o,n,r,t.controlPoints,e));else a=t.controlPoints;return a}getPoints(t){const e=this.getControlPoints(t),[n,r]=this.getEndpoints(t,!0,e);return[n,...e,r]}getKeyPath(t){return ig(this.getPoints(t),t.radius)}getLoopPath(t){const{sourcePort:e,targetPort:n,radius:r}=t,i=this.sourceNode,o=ih(i),a=Math.max(eh(o),nh(o))/4,{placement:s,clockwise:l,dist:u=a}=Bd(this.getGraphicStyle(t),"loop");return sg(i,r,s,l,u,e,n)}}Tg.defaultStyleProps={radius:0,controlPoints:[],router:!1};class Cg extends dg{constructor(t){super(Wd({style:Cg.defaultStyleProps},t))}getKeyPath(t){const{curvePosition:e,curveOffset:n}=t,[r,i]=this.getEndpoints(t);return function(t,e,n){return[["M",t[0],t[1]],["Q",n[0],n[1],e[0],e[1]]]}(r,i,t.controlPoint||ng(r,i,e,n))}}function Ag(t){return t instanceof hf&&"node"===t.type}function Pg(t){return t instanceof dg}function Rg(t){return t instanceof Fp}Cg.defaultStyleProps={curvePosition:.5,curveOffset:30};const Dg={top:[.5,0],right:[1,.5],bottom:[.5,1],left:[0,.5],"left-top":[0,0],"top-left":[0,0],"left-bottom":[0,1],"bottom-left":[0,1],"right-top":[1,0],"top-right":[1,0],"right-bottom":[1,1],"bottom-right":[1,1],default:[.5,.5]};function Lg(t,e,n=Dg,r=!0){const i=[.5,.5],o=ne(e)?Oe(n,e.toLocaleLowerCase(),i):e;if(!r&&ne(e))return o;const[a,s]=o||i;return[t.min[0]+eh(t)*a,t.min[1]+nh(t)*s]}function _g(t){if(!t)return{};const e=t.getPorts();return(t.attributes.ports||[]).forEach(((n,r)=>{var i;const{key:o,placement:a}=n;Ig(n)&&(e[i=o||r]||(e[i]=ud(t.getShape("key").getBounds(),a)))})),e}function Ig(t){const{r:e}=t;return!e||0===Number(e)}function jg(t){return Zc(t)?t:t.getPosition()}function Bg(t,e,n,r){const i=_g(t);if(n)return i[n];const o=Object.values(i);if(0===o.length)return;const a=o.map((t=>jg(t))),s=function(t,e){const n=_g(t);if(e)return[jg(n[e])];const r=Object.values(n);return r.length>0?r.map((t=>jg(t))):[t.getCenter()]}(e,r),[l]=function(t,e){let n=1/0,r=[t[0],e[0]];return t.forEach((t=>{e.forEach((e=>{const i=Xh(t,e);ijg(t)===l))}function Fg(t,e){return Rg(t)||Ag(t)?Gg(t,e):zg(t,e)}function zg(t,e){if(!t||!e)return[0,0,0];if(Zc(t))return t;if(t.attributes.linkToCenter)return t.getPosition();return yd(Zc(e)?e:Ag(e)?e.getCenter():e.getPosition(),t.getBounds())}function Gg(t,e){if(!t||!e)return[0,0,0];const n=Zc(e)?e:Ag(e)?e.getCenter():e.getPosition();return t.getIntersectPoint(n)||t.getCenter()}function Vg(t,e="bottom",n=0,r=0,i=!1){const o=e.split("-"),[a,s]=ud(t,e),[l,u]=i?["bottom","top"]:["top","bottom"];return{transform:[["translate",a+n,s+r]],textBaseline:o.includes("top")?u:o.includes("bottom")?l:"middle",textAlign:o.includes("left")?"right":o.includes("right")?"left":"center"}}function Wg(t,e){"update"in t?t.update(e):t.attr(e)}function Hg(t){return Oe(t,"__to_be_destroyed__",!1)}class Ug extends Gh{constructor(t,e){super(t,Object.assign({},Ug.defaultOptions,e)),this.onCollapseExpand=t=>ze(this,void 0,void 0,(function*(){if(!this.validate(t))return;const{target:e}=t;if(!(Ag(n=e)||Pg(n)||Rg(n)))return;var n;const r=e.id,{model:i,graph:o}=this.context,a=i.getElementDataById(r);if(!a)return!1;const{onCollapse:s,onExpand:l,animation:u,align:c}=this.options;_d(a)?(yield o.expandElement(r,{animation:u,align:c}),null==l||l(r)):(yield o.collapseElement(r,{animation:u,align:c}),null==s||s(r))})),this.bindEvents()}update(t){this.unbindEvents(),super.update(t),this.bindEvents()}bindEvents(){const{graph:t}=this.context,{trigger:e}=this.options;t.on(`node:${e}`,this.onCollapseExpand),t.on(`combo:${e}`,this.onCollapseExpand)}unbindEvents(){const{graph:t}=this.context,{trigger:e}=this.options;t.off(`node:${e}`,this.onCollapseExpand),t.off(`combo:${e}`,this.onCollapseExpand)}validate(t){if(this.destroyed)return!1;const{enable:e}=this.options;return Ut(e)?e(t):!!e}destroy(){this.unbindEvents(),super.destroy()}}Ug.defaultOptions={enable:!0,animation:!0,trigger:t.CommonEvent.DBLCLICK,align:!0};const $g="g6-create-edge-assist-node-id";class Yg extends Gh{constructor(t,e){super(t,Object.assign({},Yg.defaultOptions,e)),this.drop=t=>ze(this,void 0,void 0,(function*(){const{targetType:e}=t;["combo","node"].includes(e)&&this.source?yield this.handleCreateEdge(t):yield this.cancelEdge()})),this.handleCreateEdge=t=>ze(this,void 0,void 0,(function*(){var e,n,r;if(!this.validate(t))return;const{graph:i,canvas:o,batch:a,element:s}=this.context,{style:l}=this.options;if(this.source)return this.createEdge(t),void(yield this.cancelEdge());a.startBatch(),o.setCursor("crosshair"),this.source=this.getSelectedNodeIDs([t.target.id])[0];const u=i.getElementData(this.source);i.addNodeData([{id:$g,style:{visibility:"hidden",ports:[{key:"port-1",placement:[.5,.5]}],x:null===(e=u.style)||void 0===e?void 0:e.x,y:null===(n=u.style)||void 0===n?void 0:n.y}}]),i.addEdgeData([{id:"g6-create-edge-assist-edge-id",source:this.source,target:$g,style:Object.assign({pointerEvents:"none"},l)}]),yield null===(r=s.draw({animation:!1}))||void 0===r?void 0:r.finished})),this.updateAssistEdge=t=>ze(this,void 0,void 0,(function*(){var e;if(!this.source)return;const{model:n,element:r}=this.context;n.translateNodeTo($g,[t.canvas.x,t.canvas.y]),yield null===(e=r.draw({animation:!1,silence:!0}))||void 0===e?void 0:e.finished})),this.createEdge=t=>{var e,n;const{graph:r}=this.context,{style:i,onFinish:o,onCreate:a}=this.options;if(void 0===(null===(e=t.target)||void 0===e?void 0:e.id)||void 0===this.source)return;const s=null===(n=this.getSelectedNodeIDs([t.target.id]))||void 0===n?void 0:n[0];var l;const u=a({id:`${this.source}-${s}-${De[l=l||"g"]?De[l]+=1:De[l]=1,l+De[l]}`,source:this.source,target:s,style:i});u&&(r.addEdgeData([u]),o(u))},this.cancelEdge=()=>ze(this,void 0,void 0,(function*(){var t;if(!this.source)return;const{graph:e,element:n,batch:r}=this.context;e.removeNodeData([$g]),this.source=void 0,yield null===(t=n.draw({animation:!1}))||void 0===t?void 0:t.finished,r.endBatch()})),this.bindEvents()}update(t){super.update(t),this.bindEvents()}bindEvents(){const{graph:e}=this.context,{trigger:n}=this.options;this.unbindEvents(),"click"===n?(e.on(t.NodeEvent.CLICK,this.handleCreateEdge),e.on(t.ComboEvent.CLICK,this.handleCreateEdge),e.on(t.CanvasEvent.CLICK,this.cancelEdge),e.on(t.EdgeEvent.CLICK,this.cancelEdge)):(e.on(t.NodeEvent.DRAG_START,this.handleCreateEdge),e.on(t.ComboEvent.DRAG_START,this.handleCreateEdge),e.on(t.CommonEvent.POINTER_UP,this.drop)),e.on(t.CommonEvent.POINTER_MOVE,this.updateAssistEdge)}getSelectedNodeIDs(t){return Array.from(new Set(this.context.graph.getElementDataByState("node",this.options.state).map((t=>t.id)).concat(t)))}validate(t){if(this.destroyed)return!1;const{enable:e}=this.options;return Ut(e)?e(t):!!e}unbindEvents(){const{graph:e}=this.context;e.off(t.NodeEvent.CLICK,this.handleCreateEdge),e.off(t.ComboEvent.CLICK,this.handleCreateEdge),e.off(t.CanvasEvent.CLICK,this.cancelEdge),e.off(t.EdgeEvent.CLICK,this.cancelEdge),e.off(t.NodeEvent.DRAG_START,this.handleCreateEdge),e.off(t.ComboEvent.DRAG_START,this.handleCreateEdge),e.off(t.CommonEvent.POINTER_UP,this.drop),e.off(t.CommonEvent.POINTER_MOVE,this.updateAssistEdge)}destroy(){this.unbindEvents(),super.destroy()}}Yg.defaultOptions={animation:!0,enable:!0,style:{},trigger:"drag",onCreate:t=>t,onFinish:()=>{}};class qg extends Gh{constructor(t,e){super(t,Object.assign({},qg.defaultOptions,e)),this.isDragging=!1,this.onDragStart=t=>{this.validate(t)&&(this.isDragging=!0,this.context.canvas.setCursor("grabbing"))},this.onDrag=t=>{var e,n,r,i;if(!this.isDragging||kd.isPinching)return;const o=null!==(n=null===(e=t.movement)||void 0===e?void 0:e.x)&&void 0!==n?n:t.dx,a=null!==(i=null===(r=t.movement)||void 0===r?void 0:r.y)&&void 0!==i?i:t.dy;0!==(o|a)&&this.translate([o,a],!1)},this.onDragEnd=()=>{var t,e;this.isDragging=!1,this.context.canvas.setCursor(this.defaultCursor),null===(e=(t=this.options).onFinish)||void 0===e||e.call(t)},this.invokeOnFinish=ye((()=>{var t,e;null===(e=(t=this.options).onFinish)||void 0===e||e.call(t)}),300),this.shortcut=new Sd(t.graph),this.bindEvents(),this.defaultCursor=this.context.canvas.getConfig().cursor||"default"}update(t){this.unbindEvents(),super.update(t),this.bindEvents()}bindEvents(){const{trigger:e}=this.options;if(qt(e)){const{up:t=[],down:n=[],left:r=[],right:i=[]}=e;this.shortcut.bind(t,(t=>this.onTranslate([0,1],t))),this.shortcut.bind(n,(t=>this.onTranslate([0,-1],t))),this.shortcut.bind(r,(t=>this.onTranslate([1,0],t))),this.shortcut.bind(i,(t=>this.onTranslate([-1,0],t)))}else{const{graph:e}=this.context;e.on(t.CommonEvent.DRAG_START,this.onDragStart),e.on(t.CommonEvent.DRAG,this.onDrag),e.on(t.CommonEvent.DRAG_END,this.onDragEnd)}}onTranslate(t,e){return ze(this,void 0,void 0,(function*(){if(!this.validate(e))return;const{sensitivity:n}=this.options,r=-1*n;yield this.translate($h(t,r),this.options.animation),this.invokeOnFinish()}))}translate(t,e){return ze(this,void 0,void 0,(function*(){t=this.clampByDirection(t),t=this.clampByRange(t),yield this.context.graph.translateBy(t,e)}))}clampByDirection([t,e]){const{direction:n}=this.options;return"x"===n?e=0:"y"===n&&(t=0),[t,e]}clampByRange([t,e]){const{viewport:n,canvas:r}=this.context,[i,o]=r.getSize(),[a,s,l,u]=Jc(this.options.range),c=[o*a,i*s,o*l,i*u],h=ah(oh(n.getCanvasCenter()),c),d=Uh(n.getViewportCenter(),[t,e,0]);if(!lh(d,h)){const{min:[n,r],max:[i,o]}=h;(d[0]0||d[0]>i&&t<0)&&(t=0),(d[1]0||d[1]>o&&e<0)&&(e=0)}return[t,e]}validate(t){if(this.destroyed)return!1;const{enable:e}=this.options;return"function"==typeof e?e(t):!!e}unbindEvents(){this.shortcut.unbindAll();const{graph:e}=this.context;e.off(t.CommonEvent.DRAG_START,this.onDragStart),e.off(t.CommonEvent.DRAG,this.onDrag),e.off(t.CommonEvent.DRAG_END,this.onDragEnd)}destroy(){this.shortcut.destroy(),this.unbindEvents(),this.context.canvas.setCursor(this.defaultCursor),super.destroy()}}qg.defaultOptions={enable:t=>!("targetType"in t)||"canvas"===t.targetType,sensitivity:10,direction:"both",range:1/0};class Xg extends Gh{constructor(e,n){super(e,Object.assign({},Xg.defaultOptions,n)),this.enable=!1,this.enableElements=["node","combo"],this.target=[],this.shadowOrigin=[0,0],this.hiddenEdges=[],this.isDragging=!1,this.onDrop=t=>ze(this,void 0,void 0,(function*(){var e;if("link"!==this.options.dropEffect)return;const{model:n,element:r}=this.context,i=t.target.id;this.target.forEach((t=>{const e=n.getParentData(t,Cc);e&&Nh(e)===i&&n.refreshComboData(i),n.setParent(t,i,Cc)})),yield null===(e=null==r?void 0:r.draw({animation:!0}))||void 0===e?void 0:e.finished})),this.setCursor=e=>{if(this.isDragging)return;const{type:n}=e,{canvas:r}=this.context,{cursor:i}=this.options;n===t.CommonEvent.POINTER_ENTER?r.setCursor((null==i?void 0:i.grab)||"grab"):r.setCursor((null==i?void 0:i.default)||"default")},this.onDragStart=this.onDragStart.bind(this),this.onDrag=this.onDrag.bind(this),this.onDragEnd=this.onDragEnd.bind(this),this.onDrop=this.onDrop.bind(this),this.bindEvents()}update(t){this.unbindEvents(),super.update(t),this.bindEvents()}bindEvents(){const{graph:e,canvas:n}=this.context,r=n.getLayer().getContextService().$canvas;r&&(r.addEventListener("blur",this.onDragEnd),r.addEventListener("contextmenu",this.onDragEnd)),this.enableElements.forEach((n=>{e.on(`${n}:${t.CommonEvent.DRAG_START}`,this.onDragStart),e.on(`${n}:${t.CommonEvent.DRAG}`,this.onDrag),e.on(`${n}:${t.CommonEvent.DRAG_END}`,this.onDragEnd),e.on(`${n}:${t.CommonEvent.POINTER_ENTER}`,this.setCursor),e.on(`${n}:${t.CommonEvent.POINTER_LEAVE}`,this.setCursor)})),["link"].includes(this.options.dropEffect)&&(e.on(t.ComboEvent.DROP,this.onDrop),e.on(t.CanvasEvent.DROP,this.onDrop))}getSelectedNodeIDs(t){return Array.from(new Set(this.context.graph.getElementDataByState("node",this.options.state).map((t=>t.id)).concat(t)))}getDelta(t){const e=this.context.graph.getZoom();return Yh([t.dx,t.dy],e)}onDragStart(t){var e;if(this.enable=this.validate(t),!this.enable)return;const{batch:n,canvas:r,graph:i}=this.context;r.setCursor((null===(e=this.options.cursor)||void 0===e?void 0:e.grabbing)||"grabbing"),this.isDragging=!0,n.startBatch();const o=t.target.id;i.getElementState(o).includes(this.options.state)?this.target=this.getSelectedNodeIDs([o]):this.target=[o],this.hideEdge(),this.context.graph.frontElement(this.target),this.options.shadow&&this.createShadow(this.target)}onDrag(t){if(!this.enable)return;const e=this.getDelta(t);this.options.shadow?this.moveShadow(e):this.moveElement(this.target,e)}onDragEnd(){var t,e,n;if(!this.enable)return;if(this.enable=!1,this.options.shadow){if(!this.shadow)return;this.shadow.style.visibility="hidden";const{x:t=0,y:e=0}=this.shadow.attributes,[n,r]=Uh([+t,+e],this.shadowOrigin);this.moveElement(this.target,[n,r])}this.showEdges(),null===(e=(t=this.options).onFinish)||void 0===e||e.call(t,this.target);const{batch:r,canvas:i}=this.context;r.endBatch(),i.setCursor((null===(n=this.options.cursor)||void 0===n?void 0:n.grab)||"grab"),this.isDragging=!1,this.target=[]}validate(t){if(this.destroyed)return!1;const{enable:e}=this.options;return Ut(e)?e(t):!!e}moveElement(t,e){return ze(this,void 0,void 0,(function*(){const{graph:n,model:r}=this.context,{dropEffect:i}=this.options;"move"===i&&t.forEach((t=>r.refreshComboData(t))),n.translateElementBy(Object.fromEntries(t.map((t=>[t,e]))),!1)}))}moveShadow(t){if(!this.shadow)return;const{x:e=0,y:n=0}=this.shadow.attributes,[r,i]=t;this.shadow.attr({x:+e+r,y:+n+i})}createShadow(t){const e=Bd(this.options,"shadow"),n=sh(t.map((t=>this.context.element.getElement(t).getBounds()))),[r,i]=n.min;this.shadowOrigin=[r,i];const[o,a]=rh(n),s={width:o,height:a,x:r,y:i};this.shadow?this.shadow.attr(Object.assign(Object.assign(Object.assign({},e),s),{visibility:"visible"})):(this.shadow=new ru({style:Object.assign(Object.assign(Object.assign({$layer:"transient"},e),s),{pointerEvents:"none"})}),this.context.canvas.appendChild(this.shadow))}showEdges(){this.options.shadow||0===this.hiddenEdges.length||(this.context.graph.showElement(this.hiddenEdges),this.hiddenEdges=[])}hideEdge(){const{hideEdge:t,shadow:e}=this.options;if("none"===t||e)return;const{graph:n}=this.context;this.hiddenEdges="all"===t?n.getEdgeData().map(Nh):Array.from(new Set(this.target.map((e=>n.getRelatedEdgesData(e,t).map(Nh))).flat())),n.hideElement(this.hiddenEdges)}unbindEvents(){const{graph:e,canvas:n}=this.context,r=n.getLayer().getContextService().$canvas;r&&(r.removeEventListener("blur",this.onDragEnd),r.removeEventListener("contextmenu",this.onDragEnd)),this.enableElements.forEach((n=>{e.off(`${n}:${t.CommonEvent.DRAG_START}`,this.onDragStart),e.off(`${n}:${t.CommonEvent.DRAG}`,this.onDrag),e.off(`${n}:${t.CommonEvent.DRAG_END}`,this.onDragEnd),e.off(`${n}:${t.CommonEvent.POINTER_ENTER}`,this.setCursor),e.off(`${n}:${t.CommonEvent.POINTER_LEAVE}`,this.setCursor)})),e.off(`combo:${t.CommonEvent.DROP}`,this.onDrop),e.off(`canvas:${t.CommonEvent.DROP}`,this.onDrop)}destroy(){var t;this.unbindEvents(),null===(t=this.shadow)||void 0===t||t.destroy(),super.destroy()}}Xg.defaultOptions={animation:!0,enable:t=>["node","combo"].includes(t.targetType),dropEffect:"move",state:"selected",hideEdge:"none",shadow:!1,shadowZIndex:100,shadowFill:"#F3F9FF",shadowFillOpacity:.5,shadowStroke:"#1890FF",shadowStrokeOpacity:.9,shadowLineDash:[5,5],cursor:{default:"default",grab:"grab",grabbing:"grabbing"}};var Kg=function(){function t(){this._events={}}return t.prototype.on=function(t,e,n){return this._events[t]||(this._events[t]=[]),this._events[t].push({callback:e,once:!!n}),this},t.prototype.once=function(t,e){return this.on(t,e,!0)},t.prototype.emit=function(t){for(var e=this,n=[],r=1;r{e.has(n.id)||(e.add(n.id),t.push(n))}))}return!1}function Qg(t,e,n,r){if(n(t))return!0;e.add(t.id);for(const i of r(t.id))if(!e.has(i.id)&&Qg(i,e,n,r))return!0;return!1}const Jg=()=>!0;class tv{graph;nodeFilter;edgeFilter;cacheEnabled;inEdgesMap=new Map;outEdgesMap=new Map;bothEdgesMap=new Map;allNodesMap=new Map;allEdgesMap=new Map;constructor(t){this.graph=t.graph;const e=t.nodeFilter||Jg,n=t.edgeFilter||Jg;this.nodeFilter=e,this.edgeFilter=t=>{const{source:r,target:i}=this.graph.getEdgeDetail(t.id);return!(!e(r)||!e(i))&&n(t,r,i)},"auto"===t.cache?(this.cacheEnabled=!0,this.startAutoCache()):"manual"===t.cache?this.cacheEnabled=!0:this.cacheEnabled=!1}clearCache=()=>{this.inEdgesMap.clear(),this.outEdgesMap.clear(),this.bothEdgesMap.clear(),this.allNodesMap.clear(),this.allEdgesMap.clear()};refreshCache=()=>{this.clearCache(),this.updateCache(this.graph.getAllNodes().map((t=>t.id)))};updateCache=t=>{const e=new Set;t.forEach((t=>{const n=this.bothEdgesMap.get(t);if(n&&n.forEach((t=>e.add(t.id))),this.hasNode(t)){const n=this.graph.getRelatedEdges(t,"in").filter(this.edgeFilter),r=this.graph.getRelatedEdges(t,"out").filter(this.edgeFilter),i=Array.from(new Set([...n,...r]));i.forEach((t=>e.add(t.id))),this.inEdgesMap.set(t,n),this.outEdgesMap.set(t,r),this.bothEdgesMap.set(t,i),this.allNodesMap.set(t,this.graph.getNode(t))}else this.inEdgesMap.delete(t),this.outEdgesMap.delete(t),this.bothEdgesMap.delete(t),this.allNodesMap.delete(t)})),e.forEach((t=>{this.hasEdge(t)?this.allEdgesMap.set(t,this.graph.getEdge(t)):this.allEdgesMap.delete(t)}))};startAutoCache(){this.refreshCache(),this.graph.on("changed",this.handleGraphChanged)}stopAutoCache(){this.graph.off("changed",this.handleGraphChanged)}handleGraphChanged=t=>{const e=new Set;t.changes.forEach((n=>{switch(n.type){case"NodeAdded":case"NodeRemoved":e.add(n.value.id);break;case"NodeDataUpdated":e.add(n.id);break;case"EdgeAdded":case"EdgeRemoved":e.add(n.value.source),e.add(n.value.target);break;case"EdgeUpdated":"source"!==n.propertyName&&"target"!==n.propertyName||(e.add(n.oldValue),e.add(n.newValue));break;case"EdgeDataUpdated":if(t.graph.hasEdge(n.id)){const r=t.graph.getEdge(n.id);e.add(r.source),e.add(r.target)}}})),this.updateCache(e)};checkNodeExistence(t){this.getNode(t)}hasNode(t){if(!this.graph.hasNode(t))return!1;const e=this.graph.getNode(t);return this.nodeFilter(e)}areNeighbors(t,e){return this.checkNodeExistence(t),this.getNeighbors(e).some((e=>e.id===t))}getNode(t){const e=this.graph.getNode(t);if(!this.nodeFilter(e))throw new Error("Node not found for id: "+t);return e}getRelatedEdges(t,e){if(this.checkNodeExistence(t),this.cacheEnabled)return"in"===e?this.inEdgesMap.get(t):"out"===e?this.outEdgesMap.get(t):this.bothEdgesMap.get(t);return this.graph.getRelatedEdges(t,e).filter(this.edgeFilter)}getDegree(t,e){return this.getRelatedEdges(t,e).length}getSuccessors(t){const e=this.getRelatedEdges(t,"out").map((t=>this.getNode(t.target)));return Array.from(new Set(e))}getPredecessors(t){const e=this.getRelatedEdges(t,"in").map((t=>this.getNode(t.source)));return Array.from(new Set(e))}getNeighbors(t){const e=this.getPredecessors(t),n=this.getSuccessors(t);return Array.from(new Set([...e,...n]))}hasEdge(t){if(!this.graph.hasEdge(t))return!1;const e=this.graph.getEdge(t);return this.edgeFilter(e)}getEdge(t){const e=this.graph.getEdge(t);if(!this.edgeFilter(e))throw new Error("Edge not found for id: "+t);return e}getEdgeDetail(t){const e=this.getEdge(t);return{edge:e,source:this.getNode(e.source),target:this.getNode(e.target)}}hasTreeStructure(t){return this.graph.hasTreeStructure(t)}getRoots(t){return this.graph.getRoots(t).filter(this.nodeFilter)}getChildren(t,e){return this.checkNodeExistence(t),this.graph.getChildren(t,e).filter(this.nodeFilter)}getParent(t,e){this.checkNodeExistence(t);const n=this.graph.getParent(t,e);return n&&this.nodeFilter(n)?n:null}getAllNodes(){return this.cacheEnabled?Array.from(this.allNodesMap.values()):this.graph.getAllNodes().filter(this.nodeFilter)}getAllEdges(){return this.cacheEnabled?Array.from(this.allEdgesMap.values()):this.graph.getAllEdges().filter(this.edgeFilter)}bfs(t,e,n="out"){const r={in:this.getPredecessors.bind(this),out:this.getSuccessors.bind(this),both:this.getNeighbors.bind(this)}[n];Zg([this.getNode(t)],new Set,e,r)}dfs(t,e,n="out"){const r={in:this.getPredecessors.bind(this),out:this.getSuccessors.bind(this),both:this.getNeighbors.bind(this)}[n];Qg(this.getNode(t),new Set,e,r)}}let ev=class t extends Kg{nodeMap=new Map;edgeMap=new Map;inEdgesMap=new Map;outEdgesMap=new Map;bothEdgesMap=new Map;treeIndices=new Map;changes=[];batchCount=0;onChanged=()=>{};constructor(t){super(),t&&(t.nodes&&this.addNodes(t.nodes),t.edges&&this.addEdges(t.edges),t.tree&&this.addTree(t.tree),t.onChanged&&(this.onChanged=t.onChanged))}batch=t=>{this.batchCount+=1,t(),this.batchCount-=1,this.batchCount||this.commit()};commit(){const t=this.changes;this.changes=[];const e={graph:this,changes:t};this.emit("changed",e),this.onChanged(e)}reduceChanges(t){let e=[];return t.forEach((t=>{switch(t.type){case"NodeRemoved":{let n=!1;e=e.filter((e=>{if("NodeAdded"===e.type){const r=e.value.id===t.value.id;return r&&(n=!0),!r}return"NodeDataUpdated"===e.type?e.id!==t.value.id:"TreeStructureChanged"!==e.type||e.nodeId!==t.value.id})),n||e.push(t);break}case"EdgeRemoved":{let n=!1;e=e.filter((e=>{if("EdgeAdded"===e.type){const r=e.value.id===t.value.id;return r&&(n=!0),!r}return"EdgeDataUpdated"!==e.type&&"EdgeUpdated"!==e.type||e.id!==t.value.id})),n||e.push(t);break}case"NodeDataUpdated":case"EdgeDataUpdated":case"EdgeUpdated":{const n=e.findIndex((e=>e.type===t.type&&e.id===t.id&&(void 0===t.propertyName||e.propertyName===t.propertyName))),r=e[n];r?void 0!==t.propertyName?r.newValue=t.newValue:(e.splice(n,1),e.push(t)):e.push(t);break}case"TreeStructureDetached":e=e.filter((e=>"TreeStructureAttached"===e.type?e.treeKey!==t.treeKey:"TreeStructureChanged"!==e.type||e.treeKey!==t.treeKey)),e.push(t);break;case"TreeStructureChanged":{const n=e.find((e=>"TreeStructureChanged"===e.type&&e.treeKey===t.treeKey&&e.nodeId===t.nodeId));n?n.newParentId=t.newParentId:e.push(t);break}default:e.push(t)}})),e}checkNodeExistence(t){this.getNode(t)}hasNode(t){return this.nodeMap.has(t)}areNeighbors(t,e){return this.getNeighbors(e).some((e=>e.id===t))}getNode(t){const e=this.nodeMap.get(t);if(!e)throw new Error("Node not found for id: "+t);return e}getRelatedEdges(t,e){if(this.checkNodeExistence(t),"in"===e){const e=this.inEdgesMap.get(t);return Array.from(e)}if("out"===e){const e=this.outEdgesMap.get(t);return Array.from(e)}{const e=this.bothEdgesMap.get(t);return Array.from(e)}}getDegree(t,e){return this.getRelatedEdges(t,e).length}getSuccessors(t){const e=this.getRelatedEdges(t,"out").map((t=>this.getNode(t.target)));return Array.from(new Set(e))}getPredecessors(t){const e=this.getRelatedEdges(t,"in").map((t=>this.getNode(t.source)));return Array.from(new Set(e))}getNeighbors(t){const e=this.getPredecessors(t),n=this.getSuccessors(t);return Array.from(new Set([...e,...n]))}doAddNode(t){if(this.hasNode(t.id))throw new Error("Node already exists: "+t.id);this.nodeMap.set(t.id,t),this.inEdgesMap.set(t.id,new Set),this.outEdgesMap.set(t.id,new Set),this.bothEdgesMap.set(t.id,new Set),this.treeIndices.forEach((e=>{e.childrenMap.set(t.id,new Set)})),this.changes.push({type:"NodeAdded",value:t})}addNodes(t){this.batch((()=>{for(const e of t)this.doAddNode(e)}))}addNode(t){this.addNodes([t])}doRemoveNode(t){const e=this.getNode(t),n=this.bothEdgesMap.get(t);n?.forEach((t=>this.doRemoveEdge(t.id))),this.nodeMap.delete(t),this.treeIndices.forEach((n=>{n.childrenMap.get(t)?.forEach((t=>{n.parentMap.delete(t.id)}));const r=n.parentMap.get(t);r&&n.childrenMap.get(r.id)?.delete(e),n.parentMap.delete(t),n.childrenMap.delete(t)})),this.bothEdgesMap.delete(t),this.inEdgesMap.delete(t),this.outEdgesMap.delete(t),this.changes.push({type:"NodeRemoved",value:e})}removeNodes(t){this.batch((()=>{t.forEach((t=>this.doRemoveNode(t)))}))}removeNode(t){this.removeNodes([t])}updateNodeDataProperty(t,e,n){const r=this.getNode(t);this.batch((()=>{const i=r.data[e],o=n;r.data[e]=o,this.changes.push({type:"NodeDataUpdated",id:t,propertyName:e,oldValue:i,newValue:o})}))}mergeNodeData(t,e){this.batch((()=>{Object.entries(e).forEach((([e,n])=>{this.updateNodeDataProperty(t,e,n)}))}))}updateNodeData(...t){const e=t[0],n=this.getNode(e);if("string"==typeof t[1])return void this.updateNodeDataProperty(e,t[1],t[2]);let r;if("function"==typeof t[1]){const e=t[1];r=e(n.data)}else"object"==typeof t[1]&&(r=t[1]);this.batch((()=>{const t=n.data,i=r;n.data=r,this.changes.push({type:"NodeDataUpdated",id:e,oldValue:t,newValue:i})}))}checkEdgeExistence(t){if(!this.hasEdge(t))throw new Error("Edge not found for id: "+t)}hasEdge(t){return this.edgeMap.has(t)}getEdge(t){return this.checkEdgeExistence(t),this.edgeMap.get(t)}getEdgeDetail(t){const e=this.getEdge(t);return{edge:e,source:this.getNode(e.source),target:this.getNode(e.target)}}doAddEdge(t){if(this.hasEdge(t.id))throw new Error("Edge already exists: "+t.id);this.checkNodeExistence(t.source),this.checkNodeExistence(t.target),this.edgeMap.set(t.id,t);const e=this.inEdgesMap.get(t.target),n=this.outEdgesMap.get(t.source),r=this.bothEdgesMap.get(t.source),i=this.bothEdgesMap.get(t.target);e.add(t),n.add(t),r.add(t),i.add(t),this.changes.push({type:"EdgeAdded",value:t})}addEdges(t){this.batch((()=>{for(const e of t)this.doAddEdge(e)}))}addEdge(t){this.addEdges([t])}doRemoveEdge(t){const e=this.getEdge(t),n=this.outEdgesMap.get(e.source),r=this.inEdgesMap.get(e.target),i=this.bothEdgesMap.get(e.source),o=this.bothEdgesMap.get(e.target);n.delete(e),r.delete(e),i.delete(e),o.delete(e),this.edgeMap.delete(t),this.changes.push({type:"EdgeRemoved",value:e})}removeEdges(t){this.batch((()=>{t.forEach((t=>this.doRemoveEdge(t)))}))}removeEdge(t){this.removeEdges([t])}updateEdgeSource(t,e){const n=this.getEdge(t);this.checkNodeExistence(e);const r=n.source,i=e;this.outEdgesMap.get(r).delete(n),this.bothEdgesMap.get(r).delete(n),this.outEdgesMap.get(i).add(n),this.bothEdgesMap.get(i).add(n),n.source=e,this.batch((()=>{this.changes.push({type:"EdgeUpdated",id:t,propertyName:"source",oldValue:r,newValue:i})}))}updateEdgeTarget(t,e){const n=this.getEdge(t);this.checkNodeExistence(e);const r=n.target,i=e;this.inEdgesMap.get(r).delete(n),this.bothEdgesMap.get(r).delete(n),this.inEdgesMap.get(i).add(n),this.bothEdgesMap.get(i).add(n),n.target=e,this.batch((()=>{this.changes.push({type:"EdgeUpdated",id:t,propertyName:"target",oldValue:r,newValue:i})}))}updateEdgeDataProperty(t,e,n){const r=this.getEdge(t);this.batch((()=>{const i=r.data[e],o=n;r.data[e]=o,this.changes.push({type:"EdgeDataUpdated",id:t,propertyName:e,oldValue:i,newValue:o})}))}updateEdgeData(...t){const e=t[0],n=this.getEdge(e);if("string"==typeof t[1])return void this.updateEdgeDataProperty(e,t[1],t[2]);let r;if("function"==typeof t[1]){const e=t[1];r=e(n.data)}else"object"==typeof t[1]&&(r=t[1]);this.batch((()=>{const t=n.data,i=r;n.data=r,this.changes.push({type:"EdgeDataUpdated",id:e,oldValue:t,newValue:i})}))}mergeEdgeData(t,e){this.batch((()=>{Object.entries(e).forEach((([e,n])=>{this.updateEdgeDataProperty(t,e,n)}))}))}checkTreeExistence(t){if(!this.hasTreeStructure(t))throw new Error("Tree structure not found for treeKey: "+t)}hasTreeStructure(t){return this.treeIndices.has(t)}attachTreeStructure(t){this.treeIndices.has(t)||(this.treeIndices.set(t,{parentMap:new Map,childrenMap:new Map}),this.batch((()=>{this.changes.push({type:"TreeStructureAttached",treeKey:t})})))}detachTreeStructure(t){this.checkTreeExistence(t),this.treeIndices.delete(t),this.batch((()=>{this.changes.push({type:"TreeStructureDetached",treeKey:t})}))}addTree(t,e){this.batch((()=>{this.attachTreeStructure(e);const n=[],r=Array.isArray(t)?t:[t];for(;r.length;){const t=r.shift();n.push(t),t.children&&r.push(...t.children)}this.addNodes(n),n.forEach((t=>{t.children?.forEach((n=>{this.setParent(n.id,t.id,e)}))}))}))}getRoots(t){return this.checkTreeExistence(t),this.getAllNodes().filter((e=>!this.getParent(e.id,t)))}getChildren(t,e){this.checkNodeExistence(t),this.checkTreeExistence(e);const n=this.treeIndices.get(e).childrenMap.get(t);return Array.from(n||[])}getParent(t,e){this.checkNodeExistence(t),this.checkTreeExistence(e);return this.treeIndices.get(e).parentMap.get(t)||null}getAncestors(t,e){const n=[];let r,i=this.getNode(t);for(;r=this.getParent(i.id,e);)n.push(r),i=r;return n}setParent(t,e,n){this.checkTreeExistence(n);const r=this.treeIndices.get(n);if(!r)return;const i=this.getNode(t),o=r.parentMap.get(t);if(o?.id===e)return;if(null==e)return o&&r.childrenMap.get(o.id)?.delete(i),void r.parentMap.delete(t);const a=this.getNode(e);r.parentMap.set(t,a),o&&r.childrenMap.get(o.id)?.delete(i);let s=r.childrenMap.get(a.id);s||(s=new Set,r.childrenMap.set(a.id,s)),s.add(i),this.batch((()=>{this.changes.push({type:"TreeStructureChanged",treeKey:n,nodeId:t,oldParentId:o?.id,newParentId:a.id})}))}dfsTree(t,e,n){return Qg(this.getNode(t),new Set,e,(t=>this.getChildren(t,n)))}bfsTree(t,e,n){return Zg([this.getNode(t)],new Set,e,(t=>this.getChildren(t,n)))}getAllNodes(){return Array.from(this.nodeMap.values())}getAllEdges(){return Array.from(this.edgeMap.values())}bfs(t,e,n="out"){const r={in:this.getPredecessors.bind(this),out:this.getSuccessors.bind(this),both:this.getNeighbors.bind(this)}[n];return Zg([this.getNode(t)],new Set,e,r)}dfs(t,e,n="out"){const r={in:this.getPredecessors.bind(this),out:this.getSuccessors.bind(this),both:this.getNeighbors.bind(this)}[n];return Qg(this.getNode(t),new Set,e,r)}clone(){const e=this.getAllNodes().map((t=>({...t,data:{...t.data}}))),n=this.getAllEdges().map((t=>({...t,data:{...t.data}}))),r=new t({nodes:e,edges:n});return this.treeIndices.forEach((({parentMap:t,childrenMap:e},n)=>{const i=new Map;t.forEach(((t,e)=>{i.set(e,r.getNode(t.id))}));const o=new Map;e.forEach(((t,e)=>{o.set(e,new Set(Array.from(t).map((t=>r.getNode(t.id)))))})),r.treeIndices.set(n,{parentMap:i,childrenMap:o})})),r}toJSON(){return JSON.stringify({nodes:this.getAllNodes(),edges:this.getAllEdges()})}createView(t){return new tv({graph:this,...t})}};class nv{constructor(t,e){this.context=t,this.options=e||{}}}function rv(t){const{nodes:e,edges:n}=t,r={nodes:[],edges:[],combos:[]};return e.forEach((t=>{const e=t.data._isCombo?r.combos:r.nodes,{x:n,y:i,z:o=0}=t.data;null==e||e.push({id:t.id,style:{x:n,y:i,z:o}})})),n.forEach((t=>{const{id:e,source:n,target:i,data:{points:o=[],controlPoints:a=o.slice(1,o.length-1)}}=t;r.edges.push({id:e,source:n,target:i,style:Object.assign({},(null==a?void 0:a.length)?{controlPoints:a.map(cd)}:{})})})),r}function iv(t,e,...n){if(e in t)return t[e](...n);if("instance"in t){const r=t.instance;if(e in r)return r[e](...n)}return null}function ov(t,e){if(e in t)return t[e];if("instance"in t){const n=t.instance;if(e in n)return n[e]}return null}class av extends Xg{get forceLayoutInstance(){return this.context.layout.getLayoutInstance().find((t=>["d3-force","d3-force-3d"].includes(null==t?void 0:t.id)))}validate(t){return!!this.context.layout&&(this.forceLayoutInstance?super.validate(t):(Ic("DragElementForce only works with d3-force or d3-force-3d layout"),!1))}moveElement(t,e){return ze(this,void 0,void 0,(function*(){const n=this.forceLayoutInstance;this.context.graph.getNodeData(t).forEach(((r,i)=>{const{x:o=0,y:a=0}=r.style||{};n&&iv(n,"setFixedPosition",t[i],[...Hh([+o,+a],e)])}))}))}onDragStart(t){if(this.enable=this.validate(t),!this.enable)return;this.target=this.getSelectedNodeIDs([t.target.id]),this.hideEdge(),this.context.graph.frontElement(this.target);const e=this.forceLayoutInstance;e&&ov(e,"simulation").alphaTarget(.3).restart(),this.context.graph.getNodeData(this.target).forEach((t=>{const{x:n=0,y:r=0}=t.style||{};e&&iv(e,"setFixedPosition",Nh(t),[+n,+r])}))}onDrag(t){if(!this.enable)return;const e=this.getDelta(t);this.moveElement(this.target,e)}onDragEnd(){const t=this.forceLayoutInstance;t&&ov(t,"simulation").alphaTarget(0),this.options.fixed||this.context.graph.getNodeData(this.target).forEach((e=>{t&&iv(t,"setFixedPosition",Nh(e),[null,null,null])}))}}class sv extends Gh{constructor(t,e){super(t,Object.assign({},sv.defaultOptions,e)),this.isZoomEvent=t=>Boolean(t.data&&"scale"in t.data),this.relatedEdgeToUpdate=new Set,this.zoom=this.context.graph.getZoom(),this.fixElementSize=t=>ze(this,void 0,void 0,(function*(){if(!this.validate(t))return;const{graph:e}=this.context,{state:n,nodeFilter:r,edgeFilter:i,comboFilter:o}=this.options,a=(n?e.getElementDataByState("node",n):e.getNodeData()).filter(r),s=(n?e.getElementDataByState("edge",n):e.getEdgeData()).filter(i),l=(n?e.getElementDataByState("combo",n):e.getComboData()).filter(o),u=this.isZoomEvent(t)?this.zoom=Math.max(.01,Math.min(t.data.scale,10)):this.zoom,c=[...a,...l];c.length>0&&c.forEach((t=>this.fixNodeLike(t,u))),this.updateRelatedEdges(),s.length>0&&s.forEach((t=>this.fixEdge(t,u)))})),this.cachedStyles=new Map,this.getOriginalFieldValue=(t,e,n)=>{var r;const i=this.cachedStyles.get(t)||[],o=(null===(r=i.find((t=>t.shape===e)))||void 0===r?void 0:r.style)||{};return n in o||(o[n]=e.attributes[n],this.cachedStyles.set(t,[...i.filter((t=>t.shape!==e)),{shape:e,style:o}])),o[n]},this.scaleEntireElement=(t,e,n)=>{e.setLocalScale(1/n);const r=this.cachedStyles.get(t)||[];r.push({shape:e}),this.cachedStyles.set(t,r)},this.scaleSpecificShapes=(t,e,n)=>{const r=function(t){const e=[],n=t=>{(null==t?void 0:t.children.length)&&t.children.forEach((t=>{e.push(t),n(t)}))};return n(t),e}(t);(Array.isArray(n)?n:[n]).forEach((n=>{const{shape:i,fields:o}=n,a="function"==typeof i?i(r):t.getShape(i);a&&(o?o.forEach((n=>{const r=this.getOriginalFieldValue(t.id,a,n);ae(r)&&(a.style[n]=r/e)})):this.scaleEntireElement(t.id,a,e))}))},this.skipIfExceedViewport=t=>{const{viewport:e}=this.context;return!(null==e?void 0:e.isInViewport(t.getRenderBounds(),!1,30))},this.fixNodeLike=(t,e)=>{const n=Nh(t),{element:r,model:i}=this.context,o=r.getElement(n);if(!o||this.skipIfExceedViewport(o))return;i.getRelatedEdgesData(n).forEach((t=>this.relatedEdgeToUpdate.add(Nh(t))));const a=this.options[o.type];a?this.scaleSpecificShapes(o,e,a):this.scaleEntireElement(n,o,e)},this.fixEdge=(t,e)=>{const n=Nh(t),r=this.context.element.getElement(n);if(!r||this.skipIfExceedViewport(r))return;const i=this.options.edge;if(!i)return r.style.transformOrigin="center",void this.scaleEntireElement(n,r,e);this.scaleSpecificShapes(r,e,i)},this.updateRelatedEdges=()=>{const{element:t}=this.context;this.relatedEdgeToUpdate.size>0&&this.relatedEdgeToUpdate.forEach((e=>{const n=t.getElement(e);null==n||n.update({})})),this.relatedEdgeToUpdate.clear()},this.resetTransform=t=>ze(this,void 0,void 0,(function*(){var e;(null===(e=t.data)||void 0===e?void 0:e.firstRender)||(this.options.reset?this.restoreCachedStyles():this.fixElementSize({data:{scale:this.zoom}}))})),this.bindEvents()}restoreCachedStyles(){if(this.cachedStyles.size>0){this.cachedStyles.forEach((t=>{t.forEach((({shape:t,style:e})=>{if(Se(e))t.setLocalScale(1);else{if(this.options.state)return;Object.entries(e).forEach((([e,n])=>t.style[e]=n))}}))}));const{graph:t,element:e}=this.context,n=Object.keys(Object.fromEntries(this.cachedStyles)).filter((e=>e&&"node"===t.getElementType(e)));if(n.length>0){const r=new Set;n.forEach((e=>{t.getRelatedEdgesData(e).forEach((t=>r.add(Nh(t))))})),r.forEach((t=>{const n=null==e?void 0:e.getElement(t);null==n||n.update({})}))}}}bindEvents(){const{graph:e}=this.context;e.on(t.GraphEvent.AFTER_DRAW,this.resetTransform),e.on(t.GraphEvent.AFTER_TRANSFORM,this.fixElementSize)}unbindEvents(){const{graph:e}=this.context;e.off(t.GraphEvent.AFTER_DRAW,this.resetTransform),e.off(t.GraphEvent.AFTER_TRANSFORM,this.fixElementSize)}validate(t){if(this.destroyed)return!1;const{enable:e}=this.options;return Ut(e)?e(t):!!e}destroy(){this.unbindEvents(),super.destroy()}}sv.defaultOptions={enable:t=>t.data.scale<1,nodeFilter:()=>!0,edgeFilter:()=>!0,comboFilter:()=>!0,edge:[{shape:"key",fields:["lineWidth"]},{shape:"halo",fields:["lineWidth"]},{shape:"label"}],reset:!1};class lv extends Gh{constructor(t,e){super(t,Object.assign({},lv.defaultOptions,e)),this.focus=t=>ze(this,void 0,void 0,(function*(){if(!this.validate(t))return;const{graph:e}=this.context;yield e.focusElement(t.target.id,this.options.animation)})),this.bindEvents()}bindEvents(){const{graph:e}=this.context;this.unbindEvents(),Cd.forEach((n=>{e.on(`${n}:${t.CommonEvent.CLICK}`,this.focus)}))}validate(t){if(this.destroyed)return!1;const{enable:e}=this.options;return Ut(e)?e(t):!!e}unbindEvents(){const{graph:e}=this.context;Cd.forEach((n=>{e.off(`${n}:${t.CommonEvent.CLICK}`,this.focus)}))}destroy(){this.unbindEvents(),super.destroy()}}lv.defaultOptions={animation:{easing:"ease-in",duration:500},enable:!0};class uv extends Gh{constructor(e,n){super(e,Object.assign({},uv.defaultOptions,n)),this.isFrozen=!1,this.toggleFrozen=t=>{this.isFrozen="dragstart"===t.type},this.hoverElement=e=>{if(!this.validate(e))return;const n=e.type===t.CommonEvent.POINTER_ENTER;this.updateElementsState(e,n);const{onHover:r,onHoverEnd:i}=this.options;n?null==r||r(e):null==i||i(e)},this.updateElementsState=(t,e)=>{if(!this.options.state&&!this.options.inactiveState)return;const{graph:n}=this.context,{state:r,animation:i,inactiveState:o}=this.options,a=this.getActiveIds(t),s={};if(r&&Object.assign(s,this.getElementsState(a,r,e)),o){const t=Th(n.getData(),!0).filter((t=>!a.includes(t)));Object.assign(s,this.getElementsState(t,o,e))}n.setElementState(s,i)},this.getElementsState=(t,e,n)=>{const{graph:r}=this.context,i={};return t.forEach((t=>{const o=r.getElementState(t);i[t]=n?o.includes(e)?o:[...o,e]:o.filter((t=>t!==e))})),i},this.bindEvents()}bindEvents(){const{graph:e}=this.context;this.unbindEvents(),Cd.forEach((n=>{e.on(`${n}:${t.CommonEvent.POINTER_ENTER}`,this.hoverElement),e.on(`${n}:${t.CommonEvent.POINTER_LEAVE}`,this.hoverElement)}));const n=this.context.canvas.document;n.addEventListener(`${t.CommonEvent.DRAG_START}`,this.toggleFrozen),n.addEventListener(`${t.CommonEvent.DRAG_END}`,this.toggleFrozen)}getActiveIds(t){const{graph:e}=this.context,{degree:n,direction:r}=this.options,i=t.target.id;return n?Pd(e,t.targetType,i,"function"==typeof n?n(t):n,r):[i]}validate(t){if(this.destroyed||this.isFrozen||Hg(t.target)||this.context.graph.isCollapsingExpanding)return!1;const{enable:e}=this.options;return Ut(e)?e(t):!!e}unbindEvents(){const{graph:e}=this.context;Cd.forEach((n=>{e.off(`${n}:${t.CommonEvent.POINTER_ENTER}`,this.hoverElement),e.off(`${n}:${t.CommonEvent.POINTER_LEAVE}`,this.hoverElement)}));const n=this.context.canvas.document;n.removeEventListener(`${t.CommonEvent.DRAG_START}`,this.toggleFrozen),n.removeEventListener(`${t.CommonEvent.DRAG_END}`,this.toggleFrozen)}destroy(){this.unbindEvents(),super.destroy()}}uv.defaultOptions={animation:!1,enable:!0,degree:0,direction:"both",state:"active",inactiveState:void 0};class cv extends Nd{onPointerDown(t){if(!super.validate(t)||!super.isKeydown()||this.points)return;const{canvas:e}=this.context;this.pathShape=new Ql({id:"g6-lasso-select",style:this.options.style}),e.appendChild(this.pathShape),this.points=[Od(t)]}onPointerMove(t){var e;if(!this.points)return;const{immediately:n,mode:r}=this.options;this.points.push(Od(t)),null===(e=this.pathShape)||void 0===e||e.setAttribute("d",function(t,e=!0){const n=[];return t.forEach(((t,e)=>{n.push([0===e?"M":"L",...t])})),e&&n.push(["Z"]),n}(this.points)),n&&"default"===r&&this.points.length>2&&super.updateElementsStates(this.points)}onPointerUp(){this.points&&(this.points.length<2||super.updateElementsStates(this.points),this.clearLasso())}clearLasso(){var t;null===(t=this.pathShape)||void 0===t||t.remove(),this.pathShape=void 0,this.points=void 0}}class hv extends Gh{constructor(t,e){super(t,Object.assign({},hv.defaultOptions,e)),this.hiddenShapes=[],this.isVisible=!0,this.setElementsVisibility=(t,e,n)=>{t.filter(Boolean).forEach((t=>{"hidden"!==e||t.isVisible()?"visible"===e&&this.hiddenShapes.includes(t)?this.hiddenShapes.splice(this.hiddenShapes.indexOf(t),1):Bh(t,e,n):this.hiddenShapes.push(t)}))},this.filterShapes=(t,e)=>{if(Ut(e))return n=>!e(t,n);const n=null==e?void 0:e[t];return t=>!t.className||!(null==n?void 0:n.includes(t.className))},this.hideShapes=t=>{if(!this.validate(t)||!this.isVisible)return;const{element:e}=this.context,{shapes:n={}}=this.options;this.setElementsVisibility(e.getNodes(),"hidden",this.filterShapes("node",n)),this.setElementsVisibility(e.getEdges(),"hidden",this.filterShapes("edge",n)),this.setElementsVisibility(e.getCombos(),"hidden",this.filterShapes("combo",n)),this.isVisible=!1},this.showShapes=ye((t=>{if(!this.validate(t)||this.isVisible)return;const{element:e}=this.context;this.setElementsVisibility(e.getNodes(),"visible"),this.setElementsVisibility(e.getEdges(),"visible"),this.setElementsVisibility(e.getCombos(),"visible"),this.isVisible=!0}),this.options.debounce),this.bindEvents()}bindEvents(){const{graph:e}=this.context;e.on(t.GraphEvent.BEFORE_TRANSFORM,this.hideShapes),e.on(t.GraphEvent.AFTER_TRANSFORM,this.showShapes)}unbindEvents(){const{graph:e}=this.context;e.off(t.GraphEvent.BEFORE_TRANSFORM,this.hideShapes),e.off(t.GraphEvent.AFTER_TRANSFORM,this.showShapes)}validate(t){if(this.destroyed)return!1;const{enable:e}=this.options;return Ut(e)?e(t):!!e}update(t){this.unbindEvents(),super.update(t),this.bindEvents()}destroy(){this.unbindEvents(),super.destroy()}}hv.defaultOptions={enable:!0,debounce:200,shapes:t=>"node"===t};class dv extends Gh{constructor(t,e){super(t,Object.assign({},dv.defaultOptions,e)),this.onWheel=t=>ze(this,void 0,void 0,(function*(){this.options.preventDefault&&t.preventDefault();const e=t.deltaX,n=t.deltaY;yield this.scroll([-e,-n],t)})),this.shortcut=new Sd(t.graph),this.bindEvents()}update(t){super.update(t),this.bindEvents()}bindEvents(){var e,n;const{trigger:r}=this.options;if(this.shortcut.unbindAll(),qt(r)){null===(e=this.graphDom)||void 0===e||e.removeEventListener(t.CommonEvent.WHEEL,this.onWheel);const{up:n=[],down:i=[],left:o=[],right:a=[]}=r;this.shortcut.bind(n,(t=>this.scroll([0,-10],t))),this.shortcut.bind(i,(t=>this.scroll([0,10],t))),this.shortcut.bind(o,(t=>this.scroll([-10,0],t))),this.shortcut.bind(a,(t=>this.scroll([10,0],t)))}else null===(n=this.graphDom)||void 0===n||n.addEventListener(t.CommonEvent.WHEEL,this.onWheel,{passive:!1})}get graphDom(){return this.context.graph.getCanvas().getContextService().getDomElement()}formatDisplacement(t){const{sensitivity:e}=this.options;return t=$h(t,e),t=this.clampByDirection(t),t=this.clampByRange(t)}clampByDirection([t,e]){const{direction:n}=this.options;return"x"===n?e=0:"y"===n&&(t=0),[t,e]}clampByRange([t,e]){const{viewport:n,canvas:r}=this.context,[i,o]=r.getSize(),[a,s,l,u]=Jc(this.options.range),c=[o*a,i*s,o*l,i*u],h=ah(oh(n.getCanvasCenter()),c),d=Uh(n.getViewportCenter(),[t,e,0]);if(!lh(d,h)){const{min:[n,r],max:[i,o]}=h;(d[0]0||d[0]>i&&t<0)&&(t=0),(d[1]0||d[1]>o&&e<0)&&(e=0)}return[t,e]}scroll(t,e){return ze(this,void 0,void 0,(function*(){if(!this.validate(e))return;const{onFinish:n}=this.options,r=this.context.graph,i=this.formatDisplacement(t);yield r.translateBy(i,!1),null==n||n()}))}validate(t){if(this.destroyed)return!1;const{enable:e}=this.options;return Ut(e)?e(t):!!e}destroy(){var e;this.shortcut.destroy(),null===(e=this.graphDom)||void 0===e||e.removeEventListener(t.CommonEvent.WHEEL,this.onWheel),super.destroy()}}dv.defaultOptions={enable:!0,sensitivity:1,preventDefault:!0,range:1/0};class fv extends Gh{constructor(t,e){super(t,Object.assign({},fv.defaultOptions,e)),this.zoom=(t,e,n)=>ze(this,void 0,void 0,(function*(){if(!this.validate(e))return;const{graph:r}=this.context;let i=this.options.origin;!i&&"viewport"in e&&(i=cd(e.viewport));const{sensitivity:o,onFinish:a}=this.options,s=1+oe(t,-50,50)*o/100,l=r.getZoom();yield r.zoomTo(l*s,n,i),null==a||a()})),this.onReset=()=>ze(this,void 0,void 0,(function*(){yield this.context.graph.zoomTo(1,this.options.animation)})),this.preventDefault=t=>{this.options.preventDefault&&t.preventDefault()},this.shortcut=new Sd(t.graph),this.bindEvents()}update(t){super.update(t),this.bindEvents()}bindEvents(){const{trigger:e}=this.options;if(this.shortcut.unbindAll(),Array.isArray(e))if(e.includes(t.CommonEvent.PINCH))this.shortcut.bind([t.CommonEvent.PINCH],(t=>{this.zoom(t.scale,t,!1)}));else{const n=this.context.canvas.getContainer();null==n||n.addEventListener(t.CommonEvent.WHEEL,this.preventDefault),this.shortcut.bind([...e,t.CommonEvent.WHEEL],(t=>{const{deltaX:e,deltaY:n}=t;this.zoom(-(null!=n?n:e),t,!1)}))}if("object"==typeof e){const{zoomIn:t=[],zoomOut:n=[],reset:r=[]}=e;this.shortcut.bind(t,(t=>this.zoom(10,t,this.options.animation))),this.shortcut.bind(n,(t=>this.zoom(-10,t,this.options.animation))),this.shortcut.bind(r,this.onReset)}}validate(t){if(this.destroyed)return!1;const{enable:e}=this.options;return Ut(e)?e(t):!!e}destroy(){var e;this.shortcut.destroy(),null===(e=this.context.canvas.getContainer())||void 0===e||e.removeEventListener(t.CommonEvent.WHEEL,this.preventDefault),super.destroy()}}fv.defaultOptions={animation:{duration:200},enable:!0,sensitivity:1,trigger:[],preventDefault:!0};var pv={assign:Object.assign,getHeight:function(t,e,n,r){return void 0===r&&(r="height"),"center"===n?(t[r]+e[r])/2:t.height}},gv=pv,vv={getId:function(t){return t.id||t.name},getPreH:function(t){return t.preH||0},getPreV:function(t){return t.preV||0},getHGap:function(t){return t.hgap||18},getVGap:function(t){return t.vgap||18},getChildren:function(t){return t.children},getHeight:function(t){return t.height||36},getWidth:function(t){var e=t.label||" ";return t.width||18*e.split("").length}};function mv(t,e){var n=this;if(n.vgap=n.hgap=0,t instanceof mv)return t;n.data=t;var r=e.getHGap(t),i=e.getVGap(t);return n.preH=e.getPreH(t),n.preV=e.getPreV(t),n.width=e.getWidth(t),n.height=e.getHeight(t),n.width+=n.preH,n.height+=n.preV,n.id=e.getId(t),n.x=n.y=0,n.depth=0,n.children||(n.children=[]),n.addGap(r,i),n}gv.assign(mv.prototype,{isRoot:function(){return 0===this.depth},isLeaf:function(){return 0===this.children.length},addGap:function(t,e){var n=this;n.hgap+=t,n.vgap+=e,n.width+=2*t,n.height+=2*e},eachNode:function(t){for(var e,n=[this];e=n.shift();)t(e),n=e.children.concat(n)},DFTraverse:function(t){this.eachNode(t)},BFTraverse:function(t){for(var e,n=[this];e=n.shift();)t(e),n=n.concat(e.children)},getBoundingBox:function(){var t={left:Number.MAX_VALUE,top:Number.MAX_VALUE,width:0,height:0};return this.eachNode((function(e){t.left=Math.min(t.left,e.x),t.top=Math.min(t.top,e.y),t.width=Math.max(t.width,e.x+e.width),t.height=Math.max(t.height,e.y+e.height)})),t},translate:function(t,e){void 0===t&&(t=0),void 0===e&&(e=0),this.eachNode((function(n){n.x+=t,n.y+=e,n.x+=n.preH,n.y+=n.preV}))},right2left:function(){var t=this,e=t.getBoundingBox();t.eachNode((function(t){t.x=t.x-2*(t.x-e.left)-t.width})),t.translate(e.width,0)},bottom2top:function(){var t=this,e=t.getBoundingBox();t.eachNode((function(t){t.y=t.y-2*(t.y-e.top)-t.height})),t.translate(0,e.height)}});var yv=function(t,e,n){void 0===e&&(e={});var r,i=new mv(t,e=gv.assign({},vv,e)),o=[i];if(!n&&!t.collapsed)for(;r=o.shift();)if(!r.data.collapsed){var a=e.getChildren(r.data),s=a?a.length:0;if(r.children=new Array(s),a&&s)for(var l=0;l-1}(r),-1===Pv.indexOf(r))throw new TypeError("Invalid direction: "+r);if(r===Pv[0])n(t,e);else if(r===Pv[1])n(t,e),t.right2left();else if(r===Pv[2])n(t,e);else if(r===Pv[3])n(t,e),t.bottom2top();else if(r===Pv[4]||r===Pv[5]){var i=Av(t,e),o=i.left,a=i.right;n(o,e),n(a,e),e.isHorizontal?o.right2left():o.bottom2top(),a.translate(o.x-a.x,o.y-a.y),t.x=o.x,t.y=a.y;var s=t.getBoundingBox();e.isHorizontal?s.top<0&&t.translate(0,-s.top):s.left<0&&t.translate(-s.left,0)}var l=e.fixedRoot;return void 0===l&&(l=!0),l&&t.translate(-(t.x+t.width/2+t.hgap),-(t.y+t.height/2+t.vgap)),function(t,e){if(e.radial){var n=e.isHorizontal?["x","y"]:["y","x"],r=n[0],i=n[1],o={x:1/0,y:1/0},a={x:-1/0,y:-1/0},s=0;t.DFTraverse((function(t){s++;var e=t.x,n=t.y;o.x=Math.min(o.x,e),o.y=Math.min(o.y,n),a.x=Math.max(a.x,e),a.y=Math.max(a.y,n)}));var l=a[i]-o[i];if(0===l)return;var u=2*Math.PI/s;t.DFTraverse((function(e){var n=(e[i]-o[i])/l*(2*Math.PI-u)+u,a=e[r]-t[r];e.x=Math.cos(n)*a,e.y=Math.sin(n)*a}))}}(t,e),t};function _v(t,e){return _v=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t},_v(t,e)}var Iv=function(t,e){void 0===e&&(e={});var n=e.isHorizontal;function r(t){0===t.cs?(t.el=t,t.er=t,t.msel=t.mser=0):(t.el=t.c[0].el,t.msel=t.c[0].msel,t.er=t.c[t.cs-1].er,t.mser=t.c[t.cs-1].mser)}function i(t,e,n){for(var r=t.c[e-1],i=r.mod,u=t.c[e],c=u.mod;null!==r&&null!==u;){l(r)>n.low&&(n=n.nxt);var h=i+r.prelim+r.w-(c+u.prelim);h>0&&(c+=h,o(t,e,n.index,h));var d=l(r),f=l(u);d<=f&&null!==(r=s(r))&&(i+=r.mod),d>=f&&null!==(u=a(u))&&(c+=u.mod)}!r&&u?function(t,e,n,r){var i=t.c[0].el;i.tl=n;var o=r-n.mod-t.c[0].msel;i.mod+=o,i.prelim-=o,t.c[0].el=t.c[e].el,t.c[0].msel=t.c[e].msel}(t,e,u,c):r&&!u&&function(t,e,n,r){var i=t.c[e].er;i.tr=n;var o=r-n.mod-t.c[e].mser;i.mod+=o,i.prelim-=o,t.c[e].er=t.c[e-1].er,t.c[e].mser=t.c[e-1].mser}(t,e,r,i)}function o(t,e,n,r){t.c[e].mod+=r,t.c[e].msel+=r,t.c[e].mser+=r,function(t,e,n,r){if(n!==e-1){var i=e-n;t.c[n+1].shift+=r/i,t.c[e].shift-=r/i,t.c[e].change-=r-r/i}}(t,e,n,r)}function a(t){return 0===t.cs?t.tl:t.c[0]}function s(t){return 0===t.cs?t.tr:t.c[t.cs-1]}function l(t){return t.y+t.h}function u(t,e,n){for(;null!==n&&t>=n.low;)n=n.nxt;return{low:t,index:e,nxt:n}}Ov(t,n);var c=wv.fromNode(t,n);return function t(e){if(0!==e.cs){t(e.c[0]);for(var n=u(l(e.c[0].el),0,null),o=1;or&&(r=e.depth);var n=e.children,i=n.length,o=new Wv(e.height,[]);return n.forEach((function(e,n){var r=t(e);o.children.push(r),0===n&&(o.leftChild=r),n===i-1&&(o.rightChild=r)})),o.originNode=e,o.isLeaf=e.isLeaf(),o}(t);return function t(e){if(e.isLeaf||0===e.children.length)e.drawingDepth=r;else{var n=e.children.map((function(e){return t(e)})),i=Math.min.apply(null,n);e.drawingDepth=i-1}return e.drawingDepth}(i),function t(r){r.x=r.drawingDepth*e.rankSep,r.isLeaf?(r.y=0,n&&(r.y=n.y+n.height+e.nodeSep,r.originNode.parent!==n.originNode.parent&&(r.y+=e.subTreeSep)),n=r):(r.children.forEach((function(e){t(e)})),r.y=(r.leftChild.y+r.rightChild.y)/2)}(i),Uv(i,t,e.isHorizontal),t},qv=Lv,Xv=pv,Kv=function(t){function e(){return t.apply(this,arguments)||this}var n,r;return r=t,(n=e).prototype=Object.create(r.prototype),n.prototype.constructor=n,$v(n,r),e.prototype.execute=function(){var t=this;return t.rootNode.width=0,qv(t.rootNode,t.options,Yv)},e}(Ev),Zv={};var Qv=function(t,e){return e=Xv.assign({},Zv,e),new Kv(t,e).execute()},Jv=pv;function tm(t,e){return tm=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t},tm(t,e)}var em=Ev,nm=function(t,e,n,r){var i=null;t.eachNode((function(t){!function(t,e,n,r,i){var o=("function"==typeof n?n(t):n)*t.depth;if(!r)try{if(t.id===t.parent.children[0].id)return t.x+=o,void(t.y=e?e.y:0)}catch(t){}if(t.x+=o,e){if(t.y=e.y+Jv.getHeight(e,t,i),e.parent&&t.parent.id!==e.parent.id){var a=e.parent,s=a.y+Jv.getHeight(a,t,i);t.y=s>t.y?s:t.y}}else t.y=0}(t,i,e,n,r),i=t}))},rm=Cv,im=pv,om=["LR","RL","H"],am=om[0],sm=function(t){function e(){return t.apply(this,arguments)||this}var n,r;return r=t,(n=e).prototype=Object.create(r.prototype),n.prototype.constructor=n,tm(n,r),e.prototype.execute=function(){var t=this.options,e=this.rootNode;t.isHorizontal=!0;var n=t.indent,r=void 0===n?20:n,i=t.dropCap,o=void 0===i||i,a=t.direction,s=void 0===a?am:a,l=t.align;if(s&&-1===om.indexOf(s))throw new TypeError("Invalid direction: "+s);if(s===om[0])nm(e,r,o,l);else if(s===om[1])nm(e,r,o,l),e.right2left();else if(s===om[2]){var u=rm(e,t),c=u.left,h=u.right;nm(c,r,o,l),c.right2left(),nm(h,r,o,l);var d=c.getBoundingBox();h.translate(d.width,0),e.x=h.x-e.width/2}return e},e}(em),lm={};var um=function(t,e){return e=im.assign({},lm,e),new sm(t,e).execute()},cm=pv;function hm(t,e){var n=0;return t.children.length?t.children.forEach((function(t){n+=hm(t,e)})):n=t.height,t._subTreeSep=e.getSubTreeSep(t.data),t.totalHeight=Math.max(t.height,n)+2*t._subTreeSep,t.totalHeight}function dm(t){var e=t.children,n=e.length;if(n){e.forEach((function(t){dm(t)}));var r=e[0],i=e[n-1],o=i.y-r.y+i.height,a=0;if(e.forEach((function(t){a+=t.totalHeight})),o>t.height)t.y=r.y+o/2-t.height/2;else if(1!==e.length||t.height>a){var s=t.y+(t.height-o)/2-r.y;e.forEach((function(t){t.translate(0,s)}))}else t.y=(r.y+r.height/2+i.y+i.height/2)/2-t.height/2}}var fm={getSubTreeSep:function(){return 0}};function pm(t,e){return pm=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t},pm(t,e)}var gm=function(t,e){void 0===e&&(e={}),e=cm.assign({},fm,e),t.parent={x:0,width:0,height:0,y:0},t.BFTraverse((function(t){t.x=t.parent.x+t.parent.width})),t.parent=null,hm(t,e),t.startY=0,t.y=t.totalHeight/2-t.height/2,t.eachNode((function(t){var e=t.children,n=e.length;if(n){var r=e[0];if(r.startY=t.startY+t._subTreeSep,1===n)r.y=t.y+t.height/2-r.height/2;else{r.y=r.startY+r.totalHeight/2-r.height/2;for(var i=1;i{if("next"!==t&&"prev"!==t)return e},km=t=>{t.prev.next=t.next,t.next.prev=t.prev,delete t.next,delete t.prev};let Mm=class{constructor(){const t={};t.prev=t,t.next=t.prev,this.shortcut=t}dequeue(){const t=this.shortcut,e=t.prev;if(e&&e!==t)return km(e),e}enqueue(t){const e=this.shortcut;t.prev&&t.next&&km(t),t.next=e.next,e.next.prev=t,e.next=t,t.prev=e}toString(){const t=[],e=this.shortcut;let n=e.prev;for(;n!==e;)t.push(JSON.stringify(n,wm)),n=null==n?void 0:n.prev;return`[${t.join(", ")}]`}},Sm=class extends Mm{};const Nm=()=>1,Om=(t,e,n)=>{let r=[];const i=e[e.length-1],o=e[0];let a;for(;t.getAllNodes().length;){for(;a=o.dequeue();)Tm(t,e,n,a);for(;a=i.dequeue();)Tm(t,e,n,a);if(t.getAllNodes().length)for(let i=e.length-2;i>0;--i)if(a=e[i].dequeue(),a){r=r.concat(Tm(t,e,n,a,!0));break}}return r},Tm=(t,e,n,r,i)=>{var o,a;const s=[];return t.hasNode(r.v)&&(null===(o=t.getRelatedEdges(r.v,"in"))||void 0===o||o.forEach((r=>{const o=r.data.weight,a=t.getNode(r.source);i&&s.push({v:r.source,w:r.target,in:0,out:0}),void 0===a.data.out&&(a.data.out=0),a.data.out-=o,Am(e,n,Object.assign({v:a.id},a.data))})),null===(a=t.getRelatedEdges(r.v,"out"))||void 0===a||a.forEach((r=>{const i=r.data.weight,o=r.target,a=t.getNode(o);void 0===a.data.in&&(a.data.in=0),a.data.in-=i,Am(e,n,Object.assign({v:a.id},a.data))})),t.removeNode(r.v)),i?s:void 0},Cm=(t,e)=>{const n=new ev;let r=0,i=0;t.getAllNodes().forEach((t=>{n.addNode({id:t.id,data:{v:t.id,in:0,out:0}})})),t.getAllEdges().forEach((t=>{const o=n.getRelatedEdges(t.source,"out").find((e=>e.target===t.target)),a=(null==e?void 0:e(t))||1;o?n.updateEdgeData(null==o?void 0:o.id,Object.assign(Object.assign({},o.data),{weight:o.data.weight+a})):n.addEdge({id:t.id,source:t.source,target:t.target,data:{weight:a}}),i=Math.max(i,n.getNode(t.source).data.out+=a),r=Math.max(r,n.getNode(t.target).data.in+=a)}));const o=[],a=i+r+3;for(let t=0;t{Am(o,s,Object.assign({v:t.id},n.getNode(t.id).data))})),{buckets:o,zeroIdx:s,graph:n}},Am=(t,e,n)=>{n.out?n.in?t[n.out-n.in+e].enqueue(n):t[t.length-1].enqueue(n):t[0].enqueue(n)},Pm=(t,e)=>{const n=((t,e)=>{var n;if(t.getAllNodes().length<=1)return[];const r=Cm(t,e||Nm);return null===(n=Om(r.graph,r.buckets,r.zeroIdx).map((e=>t.getRelatedEdges(e.v,"out").filter((({target:t})=>t===e.w)))))||void 0===n?void 0:n.flat()})(t,(t=>t.data.weight||1));null==n||n.forEach((e=>{const n=e.data;t.removeEdge(e.id),n.forwardName=e.data.name,n.reversed=!0,t.addEdge({id:e.id,source:e.target,target:e.source,data:Object.assign({},n)})}))},Rm=(t,e,n,r)=>{let i;do{i=`${r}${Math.random()}`}while(t.hasNode(i));return n.dummy=e,t.addNode({id:i,data:n}),i},Dm=t=>{const e=new ev;return t.getAllNodes().forEach((n=>{t.getChildren(n.id).length||e.addNode(Object.assign({},n))})),t.getAllEdges().forEach((t=>{e.addEdge(t)})),e},Lm=(t,e)=>{const n=Number(t.x),r=Number(t.y),i=Number(e.x)-n,o=Number(e.y)-r;let a,s,l=Number(t.width)/2,u=Number(t.height)/2;return i||o?(Math.abs(o)*l>Math.abs(i)*u?(o<0&&(u=-u),a=u*i/o,s=u):(i<0&&(l=-l),a=l,s=l*o/i),{x:n+a,y:r+s}):{x:0,y:0}},_m=t=>{const e=[],n=jm(t)+1;for(let t=0;t{const n=t.data.rank;void 0!==n&&e[n]&&e[n].push(t.id)}));for(let r=0;r{return r=t.getNode(e).data.order,i=t.getNode(n).data.order,Number(r)-Number(i);var r,i}));return e},Im=(t,e,n,r)=>{const i={width:0,height:0};return ae(n)&&ae(r)&&(i.rank=n,i.order=r),Rm(t,"border",i,e)},jm=t=>{let e;return t.getAllNodes().forEach((t=>{const n=t.data.rank;void 0!==n&&(void 0===e||n>e)&&(e=n)})),e||(e=0),e},Bm=(t,e)=>t.reduce(((t,n)=>e(t)>e(n)?n:t)),Fm=(t,e,n,r,i,o)=>{r.includes(e.id)||(r.push(e.id),n||o.push(e.id),i(e.id).forEach((e=>Fm(t,e,n,r,i,o))),n&&o.push(e.id))},zm=(t,e,n,r)=>{const i=Array.isArray(e)?e:[e],o=e=>t.getNeighbors(e),a=[],s=[];return i.forEach((e=>{if(!t.hasNode(e.id))throw new Error(`Graph does not have node: ${e}`);Fm(t,e,"post"===n,s,o,a)})),a},Gm=(t,e,n,r,i,o)=>{const a={rank:o,borderType:e,width:0,height:0},s=i.data[e][o-1],l=Rm(t,"border",a,n);i.data[e][o]=l,t.setParent(l,r),s&&t.addEdge({id:`e${Math.random()}`,source:s,target:l,data:{weight:1}})},Vm=t=>{t.getAllNodes().forEach((t=>{Wm(t)})),t.getAllEdges().forEach((t=>{Wm(t)}))},Wm=t=>{const e=t.data.width;t.data.width=t.data.height,t.data.height=e},Hm=t=>{t.getAllNodes().forEach((t=>{Um(t.data)})),t.getAllEdges().forEach((t=>{var e;null===(e=t.data.points)||void 0===e||e.forEach((t=>Um(t))),t.data.hasOwnProperty("y")&&Um(t.data)}))},Um=t=>{(null==t?void 0:t.y)&&(t.y=-t.y)},$m=t=>{t.getAllNodes().forEach((t=>{Ym(t.data)})),t.getAllEdges().forEach((t=>{var e;null===(e=t.data.points)||void 0===e||e.forEach((t=>Ym(t))),t.data.hasOwnProperty("x")&&Ym(t.data)}))},Ym=t=>{const e=t.x;t.x=t.y,t.y=e},qm=(t,e,n,r,i,o,a)=>{const s=t.getChildren(a);if(!(null==s?void 0:s.length))return void(a!==e&&t.addEdge({id:`e${Math.random()}`,source:e,target:a,data:{weight:0,minlen:n}}));const l=Im(t,"_bt"),u=Im(t,"_bb"),c=t.getNode(a);t.setParent(l,a),c.data.borderTop=l,t.setParent(u,a),c.data.borderBottom=u,null==s||s.forEach((s=>{qm(t,e,n,r,i,o,s.id);const c=s.data.borderTop?s.data.borderTop:s.id,h=s.data.borderBottom?s.data.borderBottom:s.id,d=s.data.borderTop?r:2*r,f=c!==h?1:i-o[a]+1;t.addEdge({id:`e${Math.random()}`,source:l,target:c,data:{minlen:f,weight:d,nestingEdge:!0}}),t.addEdge({id:`e${Math.random()}`,source:h,target:u,data:{minlen:f,weight:d,nestingEdge:!0}})})),t.getParent(a)||t.addEdge({id:`e${Math.random()}`,source:e,target:l,data:{weight:0,minlen:i+o[a]}})},Xm=t=>{const e={},n=(r,i)=>{const o=t.getChildren(r);null==o||o.forEach((t=>n(t.id,i+1))),e[r]=i};return t.getRoots().forEach((t=>n(t.id,1))),e},Km=t=>{let e=0;return t.getAllEdges().forEach((t=>{e+=t.data.weight})),e},Zm="edge-label",Qm=(t,e,n)=>{let r=e.source,i=t.getNode(r).data.rank;const o=e.target,a=t.getNode(o).data.rank,s=e.data.labelRank;if(a===i+1)return;let l,u,c;for(t.removeEdge(e.id),c=0,++i;i{let e;for(;t.hasNode(e=`_root${Math.random()}`););return e},ty=(t,e,n)=>{const r=((t,e)=>null==t?void 0:t.reduce(((t,n,r)=>(t[n]=e[r],t)),{}))(n,n.map(((t,e)=>e))),i=e.map((e=>{const n=t.getRelatedEdges(e,"out").map((t=>({pos:r[t.target]||0,weight:t.data.weight})));return null==n?void 0:n.sort(((t,e)=>t.pos-e.pos))})),o=i.flat().filter((t=>void 0!==t));let a=1;for(;a{if(t){let e=t.pos+a;l[e]+=t.weight;let n=0;for(;e>0;)e%2&&(n+=l[e+1]),e=e-1>>1,l[e]+=t.weight;u+=t.weight*n}})),u},ey=(t,e)=>{let n=0;for(let r=1;r<(null==e?void 0:e.length);r+=1)n+=ty(t,e[r-1],e[r]);return n},ny=t=>{const e={},n=t.getAllNodes(),r=n.map((t=>{var e;return null!==(e=t.data.rank)&&void 0!==e?e:-1/0})),i=Math.max(...r),o=[];for(let t=0;tt.getNode(e.id).data.rank-t.getNode(n.id).data.rank)),s=a.filter((e=>void 0!==t.getNode(e.id).data.fixorder)).sort(((e,n)=>t.getNode(e.id).data.fixorder-t.getNode(n.id).data.fixorder));return null==s||s.forEach((n=>{isNaN(t.getNode(n.id).data.rank)||o[t.getNode(n.id).data.rank].push(n.id),e[n.id]=!0})),null==a||a.forEach((n=>t.dfsTree(n.id,(t=>{if(e.hasOwnProperty(t.id))return!0;e[t.id]=!0,isNaN(t.data.rank)||o[t.data.rank].push(t.id)})))),o},ry=t=>{var e,n;const r=[];for(;null==t?void 0:t.length;){const i=t.pop();r.push(i),null===(e=i.in.reverse())||void 0===e||e.forEach((t=>{return(e=i,t=>{t.merged||(void 0===t.barycenter||void 0===e.barycenter||t.barycenter>=e.barycenter)&&iy(e,t)})(t);var e})),null===(n=i.out)||void 0===n||n.forEach((e=>{return(n=i,e=>{e.in.push(n),0===--e.indegree&&t.push(e)})(e);var n}))}const i=r.filter((t=>!t.merged)),o=["vs","i","barycenter","weight"];return i.map((t=>{const e={};return null==o||o.forEach((n=>{void 0!==t[n]&&(e[n]=t[n])})),e}))},iy=(t,e)=>{var n;let r=0,i=0;t.weight&&(r+=t.barycenter*t.weight,i+=t.weight),e.weight&&(r+=e.barycenter*e.weight,i+=e.weight),t.vs=null===(n=e.vs)||void 0===n?void 0:n.concat(t.vs),t.barycenter=r/i,t.weight=i,t.i=Math.min(e.i,t.i),e.merged=!0},oy=(t,e,n)=>{let r,i=n;for(;e.length&&(r=e[e.length-1]).i<=i;)e.pop(),null==t||t.push(r.vs),i++;return i},ay=(t,e)=>(n,r)=>{if(void 0!==n.fixorder&&void 0!==r.fixorder)return n.fixorder-r.fixorder;if(n.barycenterr.barycenter)return 1;if(e&&void 0!==n.order&&void 0!==r.order){if(n.orderr.order)return 1}return t?r.i-n.i:n.i-r.i},sy=(t,e,n,r,i,o)=>{var a,s,l,u;let c=t.getChildren(e).map((t=>t.id));const h=t.getNode(e),d=h?h.data.borderLeft:void 0,f=h?h.data.borderRight:void 0,p={};d&&(c=null==c?void 0:c.filter((t=>t!==d&&t!==f)));const g=((t,e)=>e.map((e=>{const n=t.getRelatedEdges(e,"in");if(!(null==n?void 0:n.length))return{v:e};const r={sum:0,weight:0};return null==n||n.forEach((e=>{const n=t.getNode(e.source);r.sum+=e.data.weight*n.data.order,r.weight+=e.data.weight})),{v:e,barycenter:r.sum/r.weight,weight:r.weight}})))(t,c||[]);null==g||g.forEach((e=>{var i;if(null===(i=t.getChildren(e.v))||void 0===i?void 0:i.length){const i=sy(t,e.v,n,r,o);p[e.v]=i,i.hasOwnProperty("barycenter")&&uy(e,i)}}));const v=((t,e)=>{var n,r,i;const o={};null==t||t.forEach(((t,e)=>{o[t.v]={i:e,indegree:0,in:[],out:[],vs:[t.v]};const n=o[t.v];void 0!==t.barycenter&&(n.barycenter=t.barycenter,n.weight=t.weight)})),null===(n=e.getAllEdges())||void 0===n||n.forEach((t=>{const e=o[t.source],n=o[t.target];void 0!==e&&void 0!==n&&(n.indegree++,e.out.push(o[t.target]))}));const a=null===(i=(r=Object.values(o)).filter)||void 0===i?void 0:i.call(r,(t=>!t.indegree));return ry(a)})(g,n);ly(v,p),null===(a=v.filter((t=>t.vs.length>0)))||void 0===a||a.forEach((e=>{const n=t.getNode(e.vs[0]);n&&(e.fixorder=n.data.fixorder,e.order=n.data.order)}));const m=((t,e,n,r)=>{const i=((t,e)=>{const n={lhs:[],rhs:[]};return null==t||t.forEach((t=>{e(t)?n.lhs.push(t):n.rhs.push(t)})),n})(t,(t=>{const e=t.hasOwnProperty("fixorder")&&!isNaN(t.fixorder);return r?!e&&t.hasOwnProperty("barycenter"):e||t.hasOwnProperty("barycenter")})),o=i.lhs,a=i.rhs.sort(((t,e)=>-t.i- -e.i)),s=[];let l=0,u=0,c=0;null==o||o.sort(ay(!!e,!!n)),c=oy(s,a,c),null==o||o.forEach((t=>{var e;c+=null===(e=t.vs)||void 0===e?void 0:e.length,s.push(t.vs),l+=t.barycenter*t.weight,u+=t.weight,c=oy(s,a,c)}));const h={vs:s.flat()};return u&&(h.barycenter=l/u,h.weight=u),h})(v,r,i,o);if(d&&(m.vs=[d,m.vs,f].flat(),null===(s=t.getPredecessors(d))||void 0===s?void 0:s.length)){const e=t.getNode((null===(l=t.getPredecessors(d))||void 0===l?void 0:l[0].id)||""),n=t.getNode((null===(u=t.getPredecessors(f))||void 0===u?void 0:u[0].id)||"");m.hasOwnProperty("barycenter")||(m.barycenter=0,m.weight=0),m.barycenter=(m.barycenter*m.weight+e.data.order+n.data.order)/(m.weight+2),m.weight+=2}return m},ly=(t,e)=>{null==t||t.forEach((t=>{var n;const r=null===(n=t.vs)||void 0===n?void 0:n.map((t=>e[t]?e[t].vs:t));t.vs=r.flat()}))},uy=(t,e)=>{void 0!==t.barycenter?(t.barycenter=(t.barycenter*t.weight+e.barycenter*e.weight)/(t.weight+e.weight),t.weight+=e.weight):(t.barycenter=e.barycenter,t.weight=e.weight)},cy=(t,e,n)=>e.map((e=>((t,e,n)=>{const r=Jm(t),i=new ev({tree:[{id:r,children:[],data:{}}]});return t.getAllNodes().forEach((o=>{const a=t.getParent(o.id);(o.data.rank===e||o.data.minRank<=e&&e<=o.data.maxRank)&&(i.hasNode(o.id)||i.addNode(Object.assign({},o)),(null==a?void 0:a.id)&&!i.hasNode(null==a?void 0:a.id)&&i.addNode(Object.assign({},a)),i.setParent(o.id,(null==a?void 0:a.id)||r),t.getRelatedEdges(o.id,n).forEach((e=>{const n=e.source===o.id?e.target:e.source;i.hasNode(n)||i.addNode(Object.assign({},t.getNode(n)));const r=i.getRelatedEdges(n,"out").find((({target:t})=>t===o.id)),a=void 0!==r?r.data.weight:0;r?i.updateEdgeData(r.id,Object.assign(Object.assign({},r.data),{weight:e.data.weight+a})):i.addEdge({id:e.id,source:n,target:o.id,data:{weight:e.data.weight+a}})})),o.data.hasOwnProperty("minRank")&&i.updateNodeData(o.id,Object.assign(Object.assign({},o.data),{borderLeft:o.data.borderLeft[e],borderRight:o.data.borderRight[e]})))})),i})(t,e,n))),hy=(t,e,n,r)=>{const i=new ev;null==t||t.forEach((t=>{var o;const a=t.getRoots()[0].id,s=sy(t,a,i,e,n,r);for(let e=0;e<(null===(o=s.vs)||void 0===o?void 0:o.length);e++){const n=t.getNode(s.vs[e]);n&&(n.data.order=e)}((t,e,n)=>{const r={};let i;null==n||n.forEach((n=>{let o,a,s=t.getParent(n);for(;s;){if(o=t.getParent(s.id),o?(a=r[o.id],r[o.id]=s.id):(a=i,i=s.id),a&&a!==s.id)return e.hasNode(a)||e.addNode({id:a,data:{}}),e.hasNode(s.id)||e.addNode({id:s.id,data:{}}),void(e.hasEdge(`e${a}-${s.id}`)||e.addEdge({id:`e${a}-${s.id}`,source:a,target:s.id,data:{}}));s=o}}))})(t,i,s.vs)}))},dy=(t,e)=>{null==e||e.forEach((e=>{null==e||e.forEach(((e,n)=>{t.getNode(e).data.order=n}))}))},fy=(t,e)=>{const n=(t=>{const e={};let n=0;const r=i=>{const o=n;t.getChildren(i).forEach((t=>r(t.id))),e[i]={low:o,lim:n++}};return t.getRoots().forEach((t=>r(t.id))),e})(t);e.forEach((e=>{var r,i;let o=e,a=t.getNode(o);const s=a.data.originalEdge;if(!s)return;const l=((t,e,n,r)=>{var i,o;const a=[],s=[],l=Math.min(e[n].low,e[r].low),u=Math.max(e[n].lim,e[r].lim);let c,h;c=n;do{c=null===(i=t.getParent(c))||void 0===i?void 0:i.id,a.push(c)}while(c&&(e[c].low>l||u>e[c].lim));for(h=c,c=r;c&&c!==h;)s.push(c),c=null===(o=t.getParent(c))||void 0===o?void 0:o.id;return{lca:h,path:a.concat(s.reverse())}})(t,n,s.source,s.target),u=l.path,c=l.lca;let h=0,d=u[h],f=!0;for(;o!==s.target;){if(a=t.getNode(o),f){for(;d!==c&&(null===(r=t.getNode(d))||void 0===r?void 0:r.data.maxRank){const n={};function r(e,r){const i=function(t){return JSON.stringify(t.slice(1))}(e);r.get(i)||(!function(e,r,i,o,a){var s,l;let u;for(let c=r;c{const r=t.getNode(e.id);r.data.dummy&&(r.data.ordera)&&vy(n,e.id,u)})))}(...e),r.set(i,!0))}const i=(e,n)=>{let i,o=-1,a=0;const s=new Map;return null==n||n.forEach(((l,u)=>{var c;if("border"===(null===(c=t.getNode(l))||void 0===c?void 0:c.data.dummy)){const e=t.getPredecessors(l)||[];e.length&&(i=t.getNode(e[0].id).data.order,r([n,a,u,o,i],s),a=u,o=i)}r([n,a,n.length,i,e.length],s)})),n};return(null==e?void 0:e.length)&&e.reduce(i),n},gy=(t,e)=>{var n,r;if(null===(n=t.getNode(e))||void 0===n?void 0:n.data.dummy)return null===(r=t.getPredecessors(e))||void 0===r?void 0:r.find((e=>t.getNode(e.id).data.dummy))},vy=(t,e,n)=>{let r=e,i=n;if(r>i){const t=r;r=i,i=t}let o=t[r];o||(t[r]=o={}),o[i]=!0},my=(t,e,n)=>{let r=e,i=n;if(r>n){r=n,i=e}return!!t[r]},yy=(t,e,n,r,i,o)=>{const a=new ev,s=by(r,i,o);return null==e||e.forEach((e=>{let r;null==e||e.forEach((e=>{const i=n[e];if(a.hasNode(i)||a.addNode({id:i,data:{}}),r){const o=n[r],l=a.getRelatedEdges(o,"out").find((t=>t.target===i));l?a.updateEdgeData(l.id,Object.assign(Object.assign({},l.data),{weight:Math.max(s(t,e,r),l.data.weight||0)})):a.addEdge({id:`e${Math.random()}`,source:o,target:i,data:{weight:Math.max(s(t,e,r),0)}})}r=e}))})),a};const by=(t,e,n)=>(r,i,o)=>{const a=r.getNode(i),s=r.getNode(o);let l=0,u=0;if(l+=a.data.width/2,a.data.hasOwnProperty("labelpos"))switch((a.data.labelpos||"").toLowerCase()){case"l":u=-a.data.width/2;break;case"r":u=a.data.width/2}if(u&&(l+=n?u:-u),u=0,l+=(a.data.dummy?e:t)/2,l+=(s.data.dummy?e:t)/2,l+=s.data.width/2,s.data.labelpos)switch((s.data.labelpos||"").toLowerCase()){case"l":u=s.data.width/2;break;case"r":u=-s.data.width/2}return u&&(l+=n?u:-u),u=0,l},xy=(t,e)=>t.getNode(e).data.width||0,Ey=(t,e)=>{const{align:n,nodesep:r=0,edgesep:i=0}=e||{},o=_m(t),a=Object.assign(((t,e)=>{const n={},r=(e,r)=>{let i=0,o=0;const a=e.length,s=null==r?void 0:r[(null==r?void 0:r.length)-1];return null==r||r.forEach(((e,l)=>{var u;const c=gy(t,e),h=c?t.getNode(c.id).data.order:a;(c||e===s)&&(null===(u=r.slice(o,l+1))||void 0===u||u.forEach((e=>{var r;null===(r=t.getPredecessors(e))||void 0===r||r.forEach((r=>{var o;const a=t.getNode(r.id),s=a.data.order;!(s{l="u"===e?o:Object.values(o).reverse(),["l","r"].forEach((n=>{"r"===n&&(l=l.map((t=>Object.values(t).reverse())));const o=("u"===e?t.getPredecessors:t.getSuccessors).bind(t),u=((t,e,n,r)=>{const i={},o={},a={};return null==e||e.forEach((t=>{null==t||t.forEach(((t,e)=>{i[t]=t,o[t]=t,a[t]=e}))})),null==e||e.forEach((t=>{let e=-1;null==t||t.forEach((t=>{let s=r(t).map((t=>t.id));if(s.length){s=s.sort(((t,e)=>a[t]-a[e]));const r=(s.length-1)/2;for(let l=Math.floor(r),u=Math.ceil(r);l<=u;++l){const r=s[l];o[t]===t&&e{var s;const l={},u=yy(t,e,n,i,o,a),c=a?"borderLeft":"borderRight",h=(t,e)=>{let n=u.getAllNodes(),r=n.pop();const i={};for(;r;)i[r.id]?t(r.id):(i[r.id]=!0,n.push(r),n=n.concat(e(r.id))),r=n.pop()};return h((t=>{l[t]=(u.getRelatedEdges(t,"in")||[]).reduce(((t,e)=>Math.max(t,(l[e.source]||0)+e.data.weight)),0)}),u.getPredecessors.bind(u)),h((e=>{const n=(u.getRelatedEdges(e,"out")||[]).reduce(((t,e)=>Math.min(t,(l[e.target]||0)-e.data.weight)),Number.POSITIVE_INFINITY),r=t.getNode(e);n!==Number.POSITIVE_INFINITY&&r.data.borderType!==c&&(l[e]=Math.max(l[e],n))}),u.getSuccessors.bind(u)),null===(s=Object.values(r))||void 0===s||s.forEach((t=>{l[t]=l[n[t]]})),l})(t,l,u.root,u.align,r,i,"r"===n);"r"===n&&Object.keys(c).forEach((t=>c[t]=-c[t])),s[e+n]=c}))}));const u=((t,e)=>Bm(Object.values(e),(e=>{var n;let r=Number.NEGATIVE_INFINITY,i=Number.POSITIVE_INFINITY;return null===(n=Object.keys(e))||void 0===n||n.forEach((n=>{const o=e[n],a=xy(t,n)/2;r=Math.max(o+a,r),i=Math.min(o-a,i)})),r-i})))(t,s);return u&&function(t,e){const n=Object.values(e),r=Math.min(...n),i=Math.max(...n);["u","d"].forEach((n=>{["l","r"].forEach((o=>{const a=n+o,s=t[a];let l;if(s===e)return;const u=Object.values(s);l="l"===o?r-Math.min(...u):i-Math.max(...u),l&&(t[a]={},Object.keys(s).forEach((e=>{t[a][e]=s[e]+l})))}))}))}(s,u),((t,e)=>{const n={};return Object.keys(t.ul).forEach((r=>{if(e)n[r]=t[e.toLowerCase()][r];else{const e=Object.values(t).map((t=>t[r]));n[r]=(e[0]+e[1])/2}})),n})(s,n)},wy=(t,e)=>{var n;const r=Dm(t);((t,e)=>{const{ranksep:n=0}=e||{},r=_m(t);let i=0;null==r||r.forEach((e=>{const r=e.map((e=>t.getNode(e).data.height)),o=Math.max(...r,0);null==e||e.forEach((e=>{t.getNode(e).data.y=i+o/2})),i+=o+n}))})(r,e);const i=Ey(r,e);null===(n=Object.keys(i))||void 0===n||n.forEach((t=>{r.getNode(t).data.x=i[t]}))},ky=t=>{const e={},n=r=>{var i;const o=t.getNode(r);if(!o)return 0;if(e[r])return o.data.rank;let a;return e[r]=!0,null===(i=t.getRelatedEdges(r,"out"))||void 0===i||i.forEach((t=>{const e=n(t.target)-t.data.minlen;e&&(void 0===a||e0===t.getRelatedEdges(e.id,"in").length)).forEach((t=>n(t.id)))},My=(t,e)=>t.getNode(e.target).data.rank-t.getNode(e.source).data.rank-e.data.minlen,Sy=(t,e)=>{const n=r=>{e.getRelatedEdges(r,"both").forEach((i=>{const o=i.source,a=r===o?i.target:o;t.hasNode(a)||My(e,i)||(t.addNode({id:a,data:{}}),t.addEdge({id:i.id,source:r,target:a,data:{}}),n(a))}))};return t.getAllNodes().forEach((t=>n(t.id))),t.getAllNodes().length},Ny=(t,e)=>{const n=r=>{var i;null===(i=e.getRelatedEdges(r,"both"))||void 0===i||i.forEach((i=>{const o=i.source,a=r===o?i.target:o;t.hasNode(a)||void 0===e.getNode(a).data.layer&&My(e,i)||(t.addNode({id:a,data:{}}),t.addEdge({id:i.id,source:r,target:a,data:{}}),n(a))}))};return t.getAllNodes().forEach((t=>n(t.id))),t.getAllNodes().length},Oy=(t,e)=>Bm(e.getAllEdges(),(n=>t.hasNode(n.source)!==t.hasNode(n.target)?My(e,n):1/0)),Ty=(t,e,n)=>{t.getAllNodes().forEach((t=>{const r=e.getNode(t.id);r.data.rank||(r.data.rank=0),r.data.rank+=n}))},Cy=t=>{const e=(t=>{const e=new ev;return t.getAllNodes().forEach((t=>{e.addNode(Object.assign({},t))})),t.getAllEdges().forEach((t=>{const n=e.getRelatedEdges(t.source,"out").find((e=>e.target===t.target));n?e.updateEdgeData(null==n?void 0:n.id,Object.assign(Object.assign({},n.data),{weight:n.data.weight+t.data.weight||0,minlen:Math.max(n.data.minlen,t.data.minlen||1)})):e.addEdge({id:t.id,source:t.source,target:t.target,data:{weight:t.data.weight||0,minlen:t.data.minlen||1}})})),e})(t);ky(e);const n=(t=>{const e=new ev({tree:[]}),n=t.getAllNodes()[0],r=t.getAllNodes().length;let i,o;for(e.addNode(n);Sy(e,t){let n=zm(t,t.getAllNodes(),"post");n=n.slice(0,(null==n?void 0:n.length)-1),n.forEach((n=>{Py(t,e,n)}))},Py=(t,e,n)=>{const r=t.getNode(n).data.parent;t.getRelatedEdges(n,"both").find((t=>t.target===r||t.source===r)).data.cutvalue=Ry(t,e,n)},Ry=(t,e,n)=>{const r=t.getNode(n).data.parent;let i=!0,o=e.getRelatedEdges(n,"out").find((t=>t.target===r)),a=0;return o||(i=!1,o=e.getRelatedEdges(r,"out").find((t=>t.target===n))),a=o.data.weight,e.getRelatedEdges(n,"both").forEach((e=>{const o=e.source===n,s=o?e.target:e.source;if(s!==r){const r=o===i,l=e.data.weight;if(a+=r?l:-l,Fy(t,n,s)){const e=t.getRelatedEdges(n,"both").find((t=>t.source===s||t.target===s)).data.cutvalue;a+=r?-e:e}}})),a},Dy=(t,e=t.getAllNodes()[0].id)=>{Ly(t,{},1,e)},Ly=(t,e,n,r,i)=>{var o;const a=n;let s=n;const l=t.getNode(r);return e[r]=!0,null===(o=t.getNeighbors(r))||void 0===o||o.forEach((n=>{e[n.id]||(s=Ly(t,e,s,n.id,r))})),l.data.low=a,l.data.lim=s++,i?l.data.parent=i:delete l.data.parent,s},_y=t=>t.getAllEdges().find((t=>t.data.cutvalue<0)),Iy=(t,e,n)=>{let r=n.source,i=n.target;e.getRelatedEdges(r,"out").find((t=>t.target===i))||(r=n.target,i=n.source);const o=t.getNode(r),a=t.getNode(i);let s=o,l=!1;o.data.lim>a.data.lim&&(s=a,l=!0);const u=e.getAllEdges().filter((e=>l===zy(t.getNode(e.source),s)&&l!==zy(t.getNode(e.target),s)));return Bm(u,(t=>My(e,t)))},jy=(t,e,n,r)=>{const i=t.getRelatedEdges(n.source,"both").find((t=>t.source===n.target||t.target===n.target));i&&t.removeEdge(i.id),t.addEdge({id:`e${Math.random()}`,source:r.source,target:r.target,data:{}}),Dy(t),Ay(t,e),By(t,e)},By=(t,e)=>{const n=t.getAllNodes().find((t=>!t.data.parent));let r=zm(t,n,"pre");r=r.slice(1),r.forEach((n=>{const r=t.getNode(n).data.parent;let i=e.getRelatedEdges(n,"out").find((t=>t.target===r)),o=!1;!i&&e.hasNode(r)&&(i=e.getRelatedEdges(r,"out").find((t=>t.target===n)),o=!0),e.getNode(n).data.rank=(e.hasNode(r)&&e.getNode(r).data.rank||0)+(o?null==i?void 0:i.data.minlen:-(null==i?void 0:i.data.minlen))}))},Fy=(t,e,n)=>t.getRelatedEdges(e,"both").find((t=>t.source===n||t.target===n)),zy=(t,e)=>e.data.low<=t.data.lim&&t.data.lim<=e.data.lim,Gy=ky,Vy=t=>{(t=>{const e={};let n;const r=i=>{var o;const a=t.getNode(i);if(!a)return 0;if(e[i])return a.data.rank;let s;return e[i]=!0,null===(o=t.getRelatedEdges(i,"out"))||void 0===o||o.forEach((t=>{const e=r(t.target)-t.data.minlen;e&&(void 0===s||e0===t.getRelatedEdges(e.id,"in").length)).forEach((t=>{t&&r(t.id)})),void 0===n&&(n=0);const i={},o=(e,n)=>{var r;const a=t.getNode(e),s=isNaN(a.data.layer)?n:a.data.layer;(void 0===a.data.rank||a.data.rank{o(t.target,s+t.data.minlen)})))};t.getAllNodes().forEach((t=>{const e=t.data;e&&(isNaN(e.layer)?e.rank-=n:o(t.id,e.layer))}))})(t),(t=>{const e=new ev({tree:[]}),n=t.getAllNodes()[0],r=t.getAllNodes().length;let i,o;for(e.addNode(n);Ny(e,t){Cy(t)},Hy=(t,e)=>{const{ranker:n,rankdir:r="tb",nodeOrder:i,keepNodeOrder:o,align:a,nodesep:s=50,edgesep:l=20,ranksep:u=50}=e;lb(t),Pm(t);const{nestingRoot:c,nodeRankFactor:h}=(t=>{const e=Rm(t,"root",{},"_root"),n=Xm(t);let r=Math.max(...Object.values(n));Math.abs(r)===1/0&&(r=1);const i=r-1,o=2*i+1;t.getAllEdges().forEach((t=>{t.data.minlen*=o}));const a=Km(t)+1;return t.getRoots().forEach((r=>{qm(t,e,o,a,i,n,r.id)})),{nestingRoot:e,nodeRankFactor:o}})(t);((t,e)=>{switch(e){case"network-simplex":Wy(t);break;case"tight-tree":default:Vy(t);break;case"longest-path":Gy(t)}})(Dm(t),n),tb(t),((t,e=0)=>{const n=t.getAllNodes(),r=n.filter((t=>void 0!==t.data.rank)).map((t=>t.data.rank)),i=Math.min(...r),o=[];n.forEach((t=>{const e=(t.data.rank||0)-i;o[e]||(o[e]=[]),o[e].push(t.id)}));let a=0;for(let n=0;n{const n=t.getNode(e);n&&(n.data.rank=n.data.rank||0,n.data.rank+=a)})))}})(t,h),((t,e)=>{e&&t.removeNode(e),t.getAllEdges().forEach((e=>{e.data.nestingEdge&&t.removeEdge(e.id)}))})(t,c),(t=>{const e=t.getAllNodes().filter((t=>void 0!==t.data.rank)).map((t=>t.data.rank)),n=Math.min(...e);t.getAllNodes().forEach((t=>{t.data.hasOwnProperty("rank")&&n!==1/0&&(t.data.rank-=n)}))})(t),eb(t),nb(t);const d=[];((t,e)=>{t.getAllEdges().forEach((n=>Qm(t,n,e)))})(t,d),fy(t,d),(t=>{const e=n=>{const r=t.getChildren(n),i=t.getNode(n);if((null==r?void 0:r.length)&&r.forEach((t=>e(t.id))),i.data.hasOwnProperty("minRank")){i.data.borderLeft=[],i.data.borderRight=[];for(let e=i.data.minRank,r=i.data.maxRank+1;ee(t.id)))})(t),o&&((t,e)=>{const n=t.getAllNodes().filter((e=>{var n;return!(null===(n=t.getChildren(e.id))||void 0===n?void 0:n.length)})).map((t=>t.data.rank)),r=Math.max(...n),i=[];for(let t=0;t{const n=t.getNode(e);n&&!n.data.dummy&&(isNaN(n.data.rank)||(n.data.fixorder=i[n.data.rank].length,i[n.data.rank].push(e)))}))})(t,i),((t,e)=>{const n=jm(t),r=[],i=[];for(let t=1;t-1;t--)i.push(t);const o=cy(t,r,"in"),a=cy(t,i,"out");let s=ny(t);dy(t,s);let l,u=Number.POSITIVE_INFINITY;for(let n=0,r=0;r<4;++n,++r){hy(n%2?o:a,n%4>=2,!1,e),s=_m(t);const i=ey(t,s);i=2,!0,e),s=_m(t);const i=ey(t,s);i{const n=e.toLowerCase();"lr"!==n&&"rl"!==n||Vm(t)})(t,r),wy(t,{align:a,nodesep:s,edgesep:l,ranksep:u}),cb(t),sb(t),((t,e)=>{e.forEach((e=>{let n=t.getNode(e);const{data:r}=n,i=r.originalEdge;let o;i&&t.addEdge(i);let a=e;for(;n.data.dummy;)o=t.getSuccessors(a)[0],t.removeNode(a),i.data.points.push({x:n.data.x,y:n.data.y}),n.data.dummy===Zm&&(i.data.x=n.data.x,i.data.y=n.data.y,i.data.width=n.data.width,i.data.height=n.data.height),a=o.id,n=t.getNode(a)}))})(t,d),ob(t),((t,e)=>{const n=e.toLowerCase();"bt"!==n&&"rl"!==n||Hm(t),"lr"!==n&&"rl"!==n||($m(t),Vm(t))})(t,r);const{width:f,height:p}=rb(t);return ib(t),ab(t),(t=>{t.getAllEdges().forEach((e=>{const n=e.data;if(n.reversed){t.removeEdge(e.id);const r=n.forwardName;delete n.reversed,delete n.forwardName,t.addEdge({id:e.id,source:e.target,target:e.source,data:Object.assign(Object.assign({},n),{forwardName:r})})}}))})(t),{width:f,height:p}},Uy=(t,e)=>{t.getAllNodes().forEach((n=>{const r=t.getNode(n.id);if(e.hasNode(n.id)){const t=e.getNode(n.id);r.data.fixorder=t.data._order,delete t.data._order}else delete r.data.fixorder}))},$y=(t,e)=>{t.getAllNodes().forEach((n=>{var r;const i=t.getNode(n.id);if(i){const t=e.getNode(n.id);i.data.x=t.data.x,i.data.y=t.data.y,i.data._order=t.data.order,i.data._rank=t.data.rank,(null===(r=e.getChildren(n.id))||void 0===r?void 0:r.length)&&(i.data.width=t.data.width,i.data.height=t.data.height)}})),t.getAllEdges().forEach((n=>{const r=t.getEdge(n.id),i=e.getEdge(n.id);r.data.points=i?i.data.points:[],i&&i.data.hasOwnProperty("x")&&(r.data.x=i.data.x,r.data.y=i.data.y)}))},Yy=["width","height","layer","fixorder"],qy={width:0,height:0},Xy=["minlen","weight","width","height","labeloffset"],Ky={minlen:1,weight:1,width:0,height:0,labeloffset:10,labelpos:"r"},Zy=["labelpos"],Qy=t=>{const e=new ev({tree:[]});return t.getAllNodes().forEach((n=>{const r=db(t.getNode(n.id).data),i=Object.assign(Object.assign({},qy),r),o=hb(i,Yy);e.hasNode(n.id)||e.addNode({id:n.id,data:Object.assign({},o)});const a=t.hasTreeStructure("combo")?t.getParent(n.id,"combo"):t.getParent(n.id);$t(a)||(e.hasNode(a.id)||e.addNode(Object.assign({},a)),e.setParent(n.id,a.id))})),t.getAllEdges().forEach((n=>{const r=db(t.getEdge(n.id).data),i={};null==Zy||Zy.forEach((t=>{void 0!==r[t]&&(i[t]=r[t])})),e.addEdge({id:n.id,source:n.source,target:n.target,data:Object.assign({},Ky,hb(r,Xy),i)})})),e},Jy=(t,e)=>{const{ranksep:n=0,rankdir:r}=e;return t.getAllNodes().forEach((t=>{isNaN(t.data.layer)||t.data.layer||(t.data.layer=0)})),t.getAllEdges().forEach((t=>{var e;t.data.minlen*=2,"c"!==(null===(e=t.data.labelpos)||void 0===e?void 0:e.toLowerCase())&&("TB"===r||"BT"===r?t.data.width+=t.data.labeloffset:t.data.height+=t.data.labeloffset)})),n/2},tb=t=>{t.getAllEdges().forEach((e=>{if(e.data.width&&e.data.height){const n=t.getNode(e.source),r={e:e,rank:(t.getNode(e.target).data.rank-n.data.rank)/2+n.data.rank};Rm(t,"edge-proxy",r,"_ep")}}))},eb=t=>{let e=0;return t.getAllNodes().forEach((n=>{var r,i;n.data.borderTop&&(n.data.minRank=null===(r=t.getNode(n.data.borderTop))||void 0===r?void 0:r.data.rank,n.data.maxRank=null===(i=t.getNode(n.data.borderBottom))||void 0===i?void 0:i.data.rank,e=Math.max(e,n.data.maxRank||-1/0))})),e},nb=t=>{t.getAllNodes().forEach((e=>{"edge-proxy"===e.data.dummy&&(t.getEdge(e.data.e.id).data.labelRank=e.data.rank,t.removeNode(e.id))}))},rb=(t,e)=>{let n,r,i=0,o=0;const{marginx:a=0,marginy:s=0}={},l=t=>{if(!t.data)return;const e=t.data.x,a=t.data.y,s=t.data.width,l=t.data.height;isNaN(e)||isNaN(s)||(void 0===n&&(n=e-s/2),n=Math.min(n,e-s/2),i=Math.max(i,e+s/2)),isNaN(a)||isNaN(l)||(void 0===r&&(r=a-l/2),r=Math.min(r,a-l/2),o=Math.max(o,a+l/2))};return t.getAllNodes().forEach((t=>{l(t)})),t.getAllEdges().forEach((t=>{(null==t?void 0:t.data.hasOwnProperty("x"))&&l(t)})),n-=a,r-=s,t.getAllNodes().forEach((t=>{t.data.x-=n,t.data.y-=r})),t.getAllEdges().forEach((t=>{var e;null===(e=t.data.points)||void 0===e||e.forEach((t=>{t.x-=n,t.y-=r})),t.data.hasOwnProperty("x")&&(t.data.x-=n),t.data.hasOwnProperty("y")&&(t.data.y-=r)})),{width:i-n+a,height:o-r+s}},ib=t=>{t.getAllEdges().forEach((e=>{const n=t.getNode(e.source),r=t.getNode(e.target);let i,o;e.data.points?(i=e.data.points[0],o=e.data.points[e.data.points.length-1]):(e.data.points=[],i={x:r.data.x,y:r.data.y},o={x:n.data.x,y:n.data.y}),e.data.points.unshift(Lm(n.data,i)),e.data.points.push(Lm(r.data,o))}))},ob=t=>{t.getAllEdges().forEach((t=>{if(t.data.hasOwnProperty("x"))switch("l"!==t.data.labelpos&&"r"!==t.data.labelpos||(t.data.width-=t.data.labeloffset),t.data.labelpos){case"l":t.data.x-=t.data.width/2+t.data.labeloffset;break;case"r":t.data.x+=t.data.width/2+t.data.labeloffset}}))},ab=t=>{t.getAllEdges().forEach((t=>{var e;t.data.reversed&&(null===(e=t.data.points)||void 0===e||e.reverse())}))},sb=t=>{t.getAllNodes().forEach((e=>{var n,r,i;if(null===(n=t.getChildren(e.id))||void 0===n?void 0:n.length){const n=t.getNode(e.id),o=t.getNode(n.data.borderTop),a=t.getNode(n.data.borderBottom),s=t.getNode(n.data.borderLeft[(null===(r=n.data.borderLeft)||void 0===r?void 0:r.length)-1]),l=t.getNode(n.data.borderRight[(null===(i=n.data.borderRight)||void 0===i?void 0:i.length)-1]);n.data.width=Math.abs((null==l?void 0:l.data.x)-(null==s?void 0:s.data.x))||10,n.data.height=Math.abs((null==a?void 0:a.data.y)-(null==o?void 0:o.data.y))||10,n.data.x=((null==s?void 0:s.data.x)||0)+n.data.width/2,n.data.y=((null==o?void 0:o.data.y)||0)+n.data.height/2}})),t.getAllNodes().forEach((e=>{"border"===e.data.dummy&&t.removeNode(e.id)}))},lb=t=>{t.getAllEdges().forEach((e=>{if(e.source===e.target){const n=t.getNode(e.source);n.data.selfEdges||(n.data.selfEdges=[]),n.data.selfEdges.push(e),t.removeEdge(e.id)}}))},ub=t=>{const e=_m(t);null==e||e.forEach((e=>{let n=0;null==e||e.forEach(((e,r)=>{var i;const o=t.getNode(e);o.data.order=r+n,null===(i=o.data.selfEdges)||void 0===i||i.forEach((e=>{Rm(t,"selfedge",{width:e.data.width,height:e.data.height,rank:o.data.rank,order:r+ ++n,e:e},"_se")})),delete o.data.selfEdges}))}))},cb=t=>{t.getAllNodes().forEach((e=>{const n=t.getNode(e.id);if("selfedge"===n.data.dummy){const r=t.getNode(n.data.e.source),i=r.data.x+r.data.width/2,o=r.data.y,a=n.data.x-i,s=r.data.height/2;t.hasEdge(n.data.e.id)?t.updateEdgeData(n.data.e.id,n.data.e.data):t.addEdge({id:n.data.e.id,source:n.data.e.source,target:n.data.e.target,data:n.data.e.data}),t.removeNode(e.id),n.data.e.data.points=[{x:i+2*a/3,y:o-s},{x:i+5*a/6,y:o-s},{y:o,x:i+a},{x:i+5*a/6,y:o+s},{x:i+2*a/3,y:o+s}],n.data.e.data.x=n.data.x,n.data.e.data.y=n.data.y}}))},hb=(t,e)=>{const n={};return null==e||e.forEach((e=>{void 0!==t[e]&&(n[e]=+t[e])})),n},db=(t={})=>{const e={};return Object.keys(t).forEach((n=>{e[n.toLowerCase()]=t[n]})),e},fb=Array.isArray,pb=t=>{const e=[],n=t.length;for(let r=0;re[r][t]+e[t][i]&&(e[r][i]=e[r][t]+e[t][i]);return e},gb=(t,e)=>{const{nodes:n,edges:r}=t,i=[],o={};if(!n)throw new Error("invalid nodes data!");return n&&n.forEach(((t,e)=>{o[t.id]=e;i.push([])})),null==r||r.forEach((t=>{const{source:e,target:n}=t,r=o[e],a=o[n];void 0!==r&&void 0!==a&&(i[r][a]=1,i[a][r]=1)})),i},vb=(t,e)=>Math.sqrt((t.x-e.x)*(t.x-e.x)+(t.y-e.y)*(t.y-e.y)),mb=(t,e,n,r="TB",i,o={})=>{if(!(null==e?void 0:e.length))return;const{stopBranchFn:a,stopAllFn:s}=o;for(let l=0;l{if(null===t)return t;if(t instanceof Date)return new Date(t.getTime());if(t instanceof Array){const e=[];return t.forEach((t=>{e.push(t)})),e.map((t=>yb(t)))}if("object"==typeof t){const e={};return Object.keys(t).forEach((n=>{e[n]=yb(t[n])})),e}return t},bb=(t,e)=>{const n=yb(t);return n.data=n.data||{},e&&(ae(n.data.x)||(n.data.x=Math.random()*e[0]),ae(n.data.y)||(n.data.y=Math.random()*e[1])),n};function xb(t){if(!t)return[0,0,0];if(ae(t))return[t,t,t];if(0===t.length)return[0,0,0];const[e,n=e,r=e]=t;return[e,n,r]}function Eb(t,e){let n;return n=Ut(e)?e:ae(e)?()=>e:()=>t,n}function wb(t,e,n=!0){return e||0===e?Ut(e)?e:ae(e)?()=>e:Array.isArray(e)?()=>n?Math.max(...e)||t:e:qt(e)&&e.width&&e.height?()=>n?Math.max(e.width,e.height)||t:[e.width,e.height]:()=>t:e=>{const{size:r}=e.data||{};return r?Array.isArray(r)?n?Math.max(...r)||t:r:qt(r)&&r.width&&r.height?n?Math.max(r.width,r.height)||t:[r.width,r.height]:r:t}}const kb=(t,e,n=10)=>{let r;const i="function"==typeof e?e:()=>e||0;r=t?Array.isArray(t)?e=>t:Ut(t)?t:e=>t:t=>{var e,r,i;if(null===(e=t.data)||void 0===e?void 0:e.bboxSize)return null===(r=t.data)||void 0===r?void 0:r.bboxSize;if(null===(i=t.data)||void 0===i?void 0:i.size){const e=t.data.size;return Array.isArray(e)?e:qt(e)?[e.width,e.height]:e}return n};return t=>{const e=r(t),n=i(t);return Math.max(...xb(e))+n}},Mb={rankdir:"TB",nodesep:50,ranksep:50,edgeLabelSpace:!0,ranker:"tight-tree",controlPoints:!1,radial:!1,focusNode:null};class Sb{constructor(t={}){this.options=t,this.id="antv-dagre",this.options=Object.assign(Object.assign({},Mb),t)}execute(t,e){return ze(this,void 0,void 0,(function*(){return this.genericDagreLayout(!1,t,e)}))}assign(t,e){return ze(this,void 0,void 0,(function*(){yield this.genericDagreLayout(!0,t,e)}))}genericDagreLayout(t,e,n){return ze(this,void 0,void 0,(function*(){const r=Object.assign(Object.assign({},this.options),n),{nodeSize:i,align:o,rankdir:a="TB",ranksep:s,nodesep:l,ranksepFunc:u,nodesepFunc:c,edgeLabelSpace:h,ranker:d,nodeOrder:f,begin:p,controlPoints:g,radial:v,sortByCombo:m,preset:y}=r,b=new ev({tree:[]}),x=Eb(s||50,u),E=Eb(l||50,c);let w=E,k=x;"LR"!==a&&"RL"!==a||(w=x,k=E);const M=wb(10,i,!1),S=e.getAllNodes(),N=e.getAllEdges();let O;S.forEach((t=>{const e=xb(M(t)),n=k(t),r=w(t),i=e[0]+2*r,o=e[1]+2*n,a=t.data.layer;ae(a)?b.addNode({id:t.id,data:{width:i,height:o,layer:a}}):b.addNode({id:t.id,data:{width:i,height:o}})})),m&&(b.attachTreeStructure("combo"),S.forEach((t=>{const{parentId:e}=t.data;void 0!==e&&b.hasNode(e)&&b.setParent(t.id,e,"combo")}))),N.forEach((t=>{b.addEdge({id:t.id,source:t.source,target:t.target,data:{weight:t.data.weight||1}})})),(null==y?void 0:y.length)&&(O=new ev({nodes:y})),((t,e)=>{const{edgeLabelSpace:n,keepNodeOrder:r,prevGraph:i,rankdir:o,ranksep:a}=e;!r&&i&&Uy(t,i);const s=Qy(t);let l;n&&(e.ranksep=Jy(s,{rankdir:o,ranksep:a}));try{l=Hy(s,e)}catch(t){if("Not possible to find intersection inside of the rectangle"===t.message)return void console.error("The following error may be caused by improper layer setting, please make sure your manual layer setting does not violate the graph's structure:\n",t);throw t}$y(t,s)})(b,{prevGraph:O,edgeLabelSpace:h,keepNodeOrder:!!f,nodeOrder:f||[],acyclicer:"greedy",ranker:d,rankdir:a,nodesep:l,align:o});const T=[0,0];if(p){let t=1/0,e=1/0;b.getAllNodes().forEach((n=>{t>n.data.x&&(t=n.data.x),e>n.data.y&&(e=n.data.y)})),b.getAllEdges().forEach((n=>{var r;null===(r=n.data.points)||void 0===r||r.forEach((n=>{t>n.x&&(t=n.x),e>n.y&&(e=n.y)}))})),T[0]=p[0]-t,T[1]=p[1]-e}const C="LR"===a||"RL"===a;if(v);else{const t=new Set,e="BT"===a||"RL"===a?(t,e)=>e-t:(t,e)=>t-e;b.getAllNodes().forEach((e=>{e.data.x=e.data.x+T[0],e.data.y=e.data.y+T[1],t.add(C?e.data.x:e.data.y)}));const n=Array.from(t).sort(e),r=C?(t,e)=>t.x!==e.x:(t,e)=>t.y!==e.y,i=C?(t,e,n)=>{const r=Math.max(e.y,n.y),i=Math.min(e.y,n.y);return t.filter((t=>t.y<=r&&t.y>=i))}:(t,e,n)=>{const r=Math.max(e.x,n.x),i=Math.min(e.x,n.x);return t.filter((t=>t.x<=r&&t.x>=i))};b.getAllEdges().forEach(((t,e)=>{var o;h&&g&&"loop"!==t.data.type&&(t.data.controlPoints=Nb(null===(o=t.data.points)||void 0===o?void 0:o.map((({x:t,y:e})=>({x:t+T[0],y:e+T[1]}))),b.getNode(t.source),b.getNode(t.target),n,C,r,i))}))}let A=[];A=b.getAllNodes().map((t=>bb(t)));const P=b.getAllEdges();t&&(A.forEach((t=>{e.mergeNodeData(t.id,{x:t.data.x,y:t.data.y})})),P.forEach((t=>{e.mergeEdgeData(t.id,{controlPoints:t.data.controlPoints})})));return{nodes:A,edges:P}}))}}const Nb=(t,e,n,r,i,o,a)=>{let s=(null==t?void 0:t.slice(1,t.length-1))||[];if(e&&n){let{x:t,y:l}=e.data,{x:u,y:c}=n.data;if(i&&(t=e.data.y,l=e.data.x,u=n.data.y,c=n.data.x),c!==l&&t!==u){const h=r.indexOf(l),d=r[h+1];if(d){const t=s[0],e=i?{x:(l+d)/2,y:(null==t?void 0:t.y)||u}:{x:(null==t?void 0:t.x)||u,y:(l+d)/2};t&&!o(t,e)||s.unshift(e)}const f=r.indexOf(c),p=Math.abs(f-h);if(1===p)s=a(s,e.data,n.data),s.length||s.push(i?{x:(l+c)/2,y:t}:{x:t,y:(l+c)/2});else if(p>1){const e=r[f-1];if(e){const n=s[s.length-1],r=i?{x:(c+e)/2,y:(null==n?void 0:n.y)||u}:{x:(null==n?void 0:n.x)||t,y:(c+e)/2};n&&!o(n,r)||s.push(r)}}}}return s},Ob=(t,e,n)=>{const r=t.getAllNodes(),i=t.getAllEdges();if(!(null==r?void 0:r.length)){return{nodes:[],edges:i}}if(1===r.length){e&&t.mergeNodeData(r[0].id,{x:n[0],y:n[1]});return{nodes:[Object.assign(Object.assign({},r[0]),{data:Object.assign(Object.assign({},r[0].data),{x:n[0],y:n[1]})})],edges:i}}},Tb={radius:null,startRadius:null,endRadius:null,startAngle:0,endAngle:2*Math.PI,clockwise:!0,divisions:1,ordering:null,angleRatio:1};class Cb{constructor(t={}){this.options=t,this.id="circular",this.options=Object.assign(Object.assign({},Tb),t)}execute(t,e){return ze(this,void 0,void 0,(function*(){return this.genericCircularLayout(!1,t,e)}))}assign(t,e){return ze(this,void 0,void 0,(function*(){yield this.genericCircularLayout(!0,t,e)}))}genericCircularLayout(t,e,n){return ze(this,void 0,void 0,(function*(){const r=Object.assign(Object.assign({},this.options),n),{width:i,height:o,center:a,divisions:s,startAngle:l=0,endAngle:u=2*Math.PI,angleRatio:c,ordering:h,clockwise:d,nodeSpacing:f,nodeSize:p}=r,g=e.getAllNodes(),v=e.getAllEdges(),[m,y,b]=Pb(i,o,a),x=null==g?void 0:g.length;if(!x||1===x)return Ob(e,t,b);const E=(u-l)/x;let{radius:w,startRadius:k,endRadius:M}=r;if(f){const t=Eb(10,f),e=wb(10,p);let n=-1/0;g.forEach((t=>{const r=e(t);n{r+=0===i?n||10:(t(e)||0)+(n||10)})),w=r/(2*Math.PI)}else w||k||M?!k&&M?k=M:k&&!M&&(M=k):w=Math.min(y,m)/2;const S=E*c;let N=[];N="topology"===h?Ab(e,g):"topology-directed"===h?Ab(e,g,!0):"degree"===h?function(t,e){const n=[];return e.forEach(((t,e)=>{n.push(bb(t))})),n.sort(((e,n)=>t.getDegree(e.id,"both")-t.getDegree(n.id,"both"))),n}(e,g):g.map((t=>bb(t)));const O=Math.ceil(x/s);for(let t=0;t{e.mergeNodeData(t.id,{x:t.data.x,y:t.data.y})}));return{nodes:N,edges:v}}))}}const Ab=(t,e,n=!1)=>{const r=[bb(e[0])],i={},o=e.length;i[e[0].id]=!0;let a=0;return e.forEach(((s,l)=>{if(0!==l)if(l!==o-1&&t.getDegree(s.id,"both")===t.getDegree(e[l+1].id,"both")&&!t.areNeighbors(r[a].id,s.id)||i[s.id]){const l=n?t.getSuccessors(r[a].id):t.getNeighbors(r[a].id);let u=!1;for(let e=0;e{let r=t,i=e,o=n;return r||"undefined"==typeof window||(r=window.innerWidth),i||"undefined"==typeof window||(i=window.innerHeight),o||(o=[r/2,i/2]),[r,i,o]},Rb={nodeSize:30,nodeSpacing:10,preventOverlap:!1,sweep:void 0,equidistant:!1,startAngle:1.5*Math.PI,clockwise:!0,maxLevelDiff:void 0,sortBy:"degree"};class Db{constructor(t={}){this.options=t,this.id="concentric",this.options=Object.assign(Object.assign({},Rb),t)}execute(t,e){return ze(this,void 0,void 0,(function*(){return this.genericConcentricLayout(!1,t,e)}))}assign(t,e){return ze(this,void 0,void 0,(function*(){yield this.genericConcentricLayout(!0,t,e)}))}genericConcentricLayout(t,e,n){return ze(this,void 0,void 0,(function*(){const r=Object.assign(Object.assign({},this.options),n),{center:i,width:o,height:a,sortBy:s,maxLevelDiff:l,sweep:u,clockwise:c,equidistant:h,preventOverlap:d,startAngle:f=1.5*Math.PI,nodeSize:p,nodeSpacing:g}=r,v=e.getAllNodes(),m=e.getAllEdges(),y=o||"undefined"==typeof window?o:window.innerWidth,b=a||"undefined"==typeof window?a:window.innerHeight,x=i||[y/2,b/2];if(!(null==v?void 0:v.length)||1===v.length)return Ob(e,t,x);const E=[];let w,k=0;fb(p)?w=Math.max(p[0],p[1]):Ut(p)?(w=-1/0,v.forEach((t=>{const e=Math.max(...xb(p(t)));e>w&&(w=e)}))):w=p,fb(g)?k=Math.max(g[0],g[1]):ae(g)&&(k=g),v.forEach((t=>{const e=bb(t);E.push(e);let n=w;const{data:r}=e;fb(r.size)?n=Math.max(r.size[0],r.size[1]):ae(r.size)?n=r.size:qt(r.size)&&(n=Math.max(r.size.width,r.size.height)),w=Math.max(w,n),Ut(g)&&(k=Math.max(g(t),k))}));const M={};E.forEach(((t,e)=>{M[t.id]=e}));let S=s;ne(S)&&void 0!==E[0].data[S]||(S="degree"),"degree"===S?E.sort(((t,n)=>e.getDegree(n.id,"both")-e.getDegree(t.id,"both"))):E.sort(((t,e)=>e.data[S]-t.data[S]));const N=E[0],O=(l||("degree"===S?e.getDegree(N.id,"both"):N.data[S]))/4,T=[{nodes:[]}];let C=T[0];E.forEach((t=>{if(C.nodes.length>0){const n="degree"===S?Math.abs(e.getDegree(C.nodes[0].id,"both")-e.getDegree(t.id,"both")):Math.abs(C.nodes[0].data[S]-t.data[S]);O&&n>=O&&(C={nodes:[]},T.push(C))}C.nodes.push(t)}));let A=w+k;if(!d){const t=T.length>0&&T[0].nodes.length>1,e=(Math.min(y,b)/2-A)/(T.length+(t?1:0));A=Math.min(A,e)}let P=0;if(T.forEach((t=>{const e=void 0===u?2*Math.PI-2*Math.PI/t.nodes.length:u;if(t.dTheta=e/Math.max(1,t.nodes.length-1),t.nodes.length>1&&d){const e=Math.cos(t.dTheta)-Math.cos(0),n=Math.sin(t.dTheta)-Math.sin(0),r=Math.sqrt(A*A/(e*e+n*n));P=Math.max(r,P)}t.r=P,P+=A})),h){let t=0,e=0;for(let n=0;n{0===r&&(e=n.r||0),n.r=e,e+=t}))}T.forEach((t=>{const e=t.dTheta||0,n=t.r||0;t.nodes.forEach(((t,r)=>{const i=f+(c?1:-1)*e*r;t.data.x=x[0]+n*Math.cos(i),t.data.y=x[1]+n*Math.sin(i)}))})),t&&E.forEach((t=>e.mergeNodeData(t.id,{x:t.data.x,y:t.data.y})));return{nodes:E,edges:m}}))}}function Lb(t,e,n,r){if(isNaN(e)||isNaN(n))return t;var i,o,a,s,l,u,c,h,d,f=t._root,p={data:r},g=t._x0,v=t._y0,m=t._x1,y=t._y1;if(!f)return t._root=p,t;for(;f.length;)if((u=e>=(o=(g+m)/2))?g=o:m=o,(c=n>=(a=(v+y)/2))?v=a:y=a,i=f,!(f=f[h=c<<1|u]))return i[h]=p,t;if(s=+t._x.call(null,f.data),l=+t._y.call(null,f.data),e===s&&n===l)return p.next=f,i?i[h]=p:t._root=p,t;do{i=i?i[h]=new Array(4):t._root=new Array(4),(u=e>=(o=(g+m)/2))?g=o:m=o,(c=n>=(a=(v+y)/2))?v=a:y=a}while((h=c<<1|u)==(d=(l>=a)<<1|s>=o));return i[d]=f,i[h]=p,t}function _b(t,e,n,r,i){this.node=t,this.x0=e,this.y0=n,this.x1=r,this.y1=i}function Ib(t){return t[0]}function jb(t){return t[1]}function Bb(t,e,n){var r=new Fb(null==e?Ib:e,null==n?jb:n,NaN,NaN,NaN,NaN);return null==t?r:r.addAll(t)}function Fb(t,e,n,r,i,o){this._x=t,this._y=e,this._x0=n,this._y0=r,this._x1=i,this._y1=o,this._root=void 0}function zb(t){for(var e={data:t.data},n=e;t=t.next;)n=n.next={data:t.data};return e}var Gb=Bb.prototype=Fb.prototype;function Vb(t,e,n,r,i){if(isNaN(e)||isNaN(n)||isNaN(r))return t;var o,a,s,l,u,c,h,d,f,p,g,v,m=t._root,y={data:i},b=t._x0,x=t._y0,E=t._z0,w=t._x1,k=t._y1,M=t._z1;if(!m)return t._root=y,t;for(;m.length;)if((d=e>=(a=(b+w)/2))?b=a:w=a,(f=n>=(s=(x+k)/2))?x=s:k=s,(p=r>=(l=(E+M)/2))?E=l:M=l,o=m,!(m=m[g=p<<2|f<<1|d]))return o[g]=y,t;if(u=+t._x.call(null,m.data),c=+t._y.call(null,m.data),h=+t._z.call(null,m.data),e===u&&n===c&&r===h)return y.next=m,o?o[g]=y:t._root=y,t;do{o=o?o[g]=new Array(8):t._root=new Array(8),(d=e>=(a=(b+w)/2))?b=a:w=a,(f=n>=(s=(x+k)/2))?x=s:k=s,(p=r>=(l=(E+M)/2))?E=l:M=l}while((g=p<<2|f<<1|d)==(v=(h>=l)<<2|(c>=s)<<1|u>=a));return o[v]=m,o[g]=y,t}function Wb(t,e,n,r,i,o,a){this.node=t,this.x0=e,this.y0=n,this.z0=r,this.x1=i,this.y1=o,this.z1=a}Gb.copy=function(){var t,e,n=new Fb(this._x,this._y,this._x0,this._y0,this._x1,this._y1),r=this._root;if(!r)return n;if(!r.length)return n._root=zb(r),n;for(t=[{source:r,target:n._root=new Array(4)}];r=t.pop();)for(var i=0;i<4;++i)(e=r.source[i])&&(e.length?t.push({source:e,target:r.target[i]=new Array(4)}):r.target[i]=zb(e));return n},Gb.add=function(t){const e=+this._x.call(null,t),n=+this._y.call(null,t);return Lb(this.cover(e,n),e,n,t)},Gb.addAll=function(t){var e,n,r,i,o=t.length,a=new Array(o),s=new Array(o),l=1/0,u=1/0,c=-1/0,h=-1/0;for(n=0;nc&&(c=r),ih&&(h=i));if(l>c||u>h)return this;for(this.cover(l,u).cover(c,h),n=0;nt||t>=i||r>e||e>=o;)switch(s=(ed||(o=l.y0)>f||(a=l.x1)=m)<<1|t>=v)&&(l=p[p.length-1],p[p.length-1]=p[p.length-1-u],p[p.length-1-u]=l)}else{var y=t-+this._x.call(null,g.data),b=e-+this._y.call(null,g.data),x=y*y+b*b;if(x=(s=(p+v)/2))?p=s:v=s,(c=a>=(l=(g+m)/2))?g=l:m=l,e=f,!(f=f[h=c<<1|u]))return this;if(!f.length)break;(e[h+1&3]||e[h+2&3]||e[h+3&3])&&(n=e,d=h)}for(;f.data!==t;)if(r=f,!(f=f.next))return this;return(i=f.next)&&delete f.next,r?(i?r.next=i:delete r.next,this):e?(i?e[h]=i:delete e[h],(f=e[0]||e[1]||e[2]||e[3])&&f===(e[3]||e[2]||e[1]||e[0])&&!f.length&&(n?n[d]=f:this._root=f),this):(this._root=i,this)},Gb.removeAll=function(t){for(var e=0,n=t.length;eMath.sqrt((t-r)**2+(e-i)**2+(n-o)**2);function Ub(t){return t[0]}function $b(t){return t[1]}function Yb(t){return t[2]}function qb(t,e,n,r){var i=new Xb(null==e?Ub:e,null==n?$b:n,null==r?Yb:r,NaN,NaN,NaN,NaN,NaN,NaN);return null==t?i:i.addAll(t)}function Xb(t,e,n,r,i,o,a,s,l){this._x=t,this._y=e,this._z=n,this._x0=r,this._y0=i,this._z0=o,this._x1=a,this._y1=s,this._z1=l,this._root=void 0}function Kb(t){for(var e={data:t.data},n=e;t=t.next;)n=n.next={data:t.data};return e}var Zb=qb.prototype=Xb.prototype;Zb.copy=function(){var t,e,n=new Xb(this._x,this._y,this._z,this._x0,this._y0,this._z0,this._x1,this._y1,this._z1),r=this._root;if(!r)return n;if(!r.length)return n._root=Kb(r),n;for(t=[{source:r,target:n._root=new Array(8)}];r=t.pop();)for(var i=0;i<8;++i)(e=r.source[i])&&(e.length?t.push({source:e,target:r.target[i]=new Array(8)}):r.target[i]=Kb(e));return n},Zb.add=function(t){const e=+this._x.call(null,t),n=+this._y.call(null,t),r=+this._z.call(null,t);return Vb(this.cover(e,n,r),e,n,r,t)},Zb.addAll=function(t){Array.isArray(t)||(t=Array.from(t));const e=t.length,n=new Float64Array(e),r=new Float64Array(e),i=new Float64Array(e);let o=1/0,a=1/0,s=1/0,l=-1/0,u=-1/0,c=-1/0;for(let h,d,f,p,g=0;gl&&(l=d),fu&&(u=f),pc&&(c=p));if(o>l||a>u||s>c)return this;this.cover(o,a,s).cover(l,u,c);for(let o=0;ot||t>=a||i>e||e>=s||o>n||n>=l;)switch(c=(nv||(a=h.y0)>m||(s=h.z0)>y||(l=h.x1)=k)<<2|(e>=w)<<1|t>=E)&&(h=b[b.length-1],b[b.length-1]=b[b.length-1-d],b[b.length-1-d]=h)}else{var M=t-+this._x.call(null,x.data),S=e-+this._y.call(null,x.data),N=n-+this._z.call(null,x.data),O=M*M+S*S+N*N;if(O{if(!h.length)do{const o=h.data;Hb(t,e,n,this._x(o),this._y(o),this._z(o))<=r&&i.push(o)}while(h=h.next);return d>l||f>u||p>c||g=(l=(m+x)/2))?m=l:x=l,(d=a>=(u=(y+E)/2))?y=u:E=u,(f=s>=(c=(b+w)/2))?b=c:w=c,e=v,!(v=v[p=f<<2|d<<1|h]))return this;if(!v.length)break;(e[p+1&7]||e[p+2&7]||e[p+3&7]||e[p+4&7]||e[p+5&7]||e[p+6&7]||e[p+7&7])&&(n=e,g=p)}for(;v.data!==t;)if(r=v,!(v=v.next))return this;return(i=v.next)&&delete v.next,r?(i?r.next=i:delete r.next,this):e?(i?e[p]=i:delete e[p],(v=e[0]||e[1]||e[2]||e[3]||e[4]||e[5]||e[6]||e[7])&&v===(e[7]||e[6]||e[5]||e[4]||e[3]||e[2]||e[1]||e[0])&&!v.length&&(n?n[g]=v:this._root=v),this):(this._root=i,this)},Zb.removeAll=function(t){for(var e=0,n=t.length;e{const{nodeStrength:n,x:r,y:i,z:a,size:s}=t.data;return{x:r,y:i,z:a,size:s,index:e,id:t.id,vx:0,vy:0,vz:0,weight:o*n}})),l=(2===i?Bb(s,(t=>t.x),(t=>t.y)):qb(s,(t=>t.x),(t=>t.y),(t=>t.z))).visitAfter(Jb),u=new Map;return s.forEach((t=>{u.set(t.id,t),function(t,e,n){e.visit(((e,r,i,o,a)=>tx(e,r,i,o,a,t,n)))}(t,l,i)})),s.map(((t,e)=>{const{id:n,data:i}=a[e],{mass:o=1}=i;r[n]={x:t.vx/o,y:t.vy/o,z:t.vz/o}})),r}function Jb(t){let e=0,n=0,r=0,i=0,o=0;const a=t.length;if(a){for(let s=0;s{var s;if((null===(s=t.data)||void 0===s?void 0:s.id)===o.id)return;const l=[n,r,i][a-1],u=o.x-t.x||.1,c=o.y-t.y||.1,h=o.z-t.z||.1,d=[u,c,h],f=l-e;let p=0;for(let t=0;tthis.lastOptions.minMovement||e<1)&&ethis.lastGraph.mergeNodeData(t.id,{x:t.data.x,y:t.data.y,z:3===this.options.dimensions?t.data.z:void 0}))),e}genericForceLayout(t,e,n){return ze(this,void 0,void 0,(function*(){const r=Object.assign(Object.assign({},this.options),n),i=e.getAllNodes(),o=e.getAllEdges(),a=this.formatOptions(r,e),{dimensions:s,width:l,height:u,nodeSize:c,getMass:h,nodeStrength:d,edgeStrength:f,linkDistance:p}=a,g=i.map(((t,e)=>Object.assign(Object.assign({},t),{data:Object.assign(Object.assign({},t.data),{x:ae(t.data.x)?t.data.x:Math.random()*l,y:ae(t.data.y)?t.data.y:Math.random()*u,z:ae(t.data.z)?t.data.z:Math.random()*Math.sqrt(l*u),size:c(t)||30,mass:h(t),nodeStrength:d(t)})}))),v=o.map((t=>Object.assign(Object.assign({},t),{data:Object.assign(Object.assign({},t.data),{edgeStrength:f(t),linkDistance:p(t,e.getNode(t.source),e.getNode(t.target))})})));if(!(null==i?void 0:i.length))return this.lastResult={nodes:[],edges:o},{nodes:[],edges:o};const m={};i.forEach(((t,e)=>{m[t.id]={x:0,y:0,z:0}}));const y=new ev({nodes:g,edges:v});this.formatCentripetal(a,y);const{maxIteration:b,minMovement:x,onTick:E}=a;if(this.lastLayoutNodes=g,this.lastLayoutEdges=v,this.lastAssign=t,this.lastGraph=e,this.lastCalcGraph=y,this.lastOptions=a,this.lastVelMap=m,"undefined"==typeof window)return;let w=0;return new Promise((n=>{this.timeInterval=window.setInterval((()=>{i&&this.running||n({nodes:sx(e,g),edges:o}),this.runOneStep(y,e,w,m,a),this.updatePosition(e,y,m,a),t&&g.forEach((t=>e.mergeNodeData(t.id,{x:t.data.x,y:t.data.y,z:3===s?t.data.z:void 0}))),null==E||E({nodes:sx(e,g),edges:o}),w++,(w>=b||this.judgingDistance{let n=1;ae(null==t?void 0:t.data.mass)&&(n=null==t?void 0:t.data.mass);const r=e.getDegree(t.id,"both");return!r||r<5?n:5*r*n}),n.nodeSize=kb(t.nodeSize,t.nodeSpacing);const a=t.linkDistance?Eb(1,t.linkDistance):t=>1+n.nodeSize(e.getNode(t.source))+n.nodeSize(e.getNode(t.target));return n.linkDistance=a,n.nodeStrength=Eb(1,t.nodeStrength),n.edgeStrength=Eb(1,t.edgeStrength),n}formatCentripetal(t,e){const{dimensions:n,centripetalOptions:r,center:i,clusterNodeStrength:o,leafCluster:a,clustering:s,nodeClusterBy:l}=t,u=e.getAllNodes(),c=r||{leaf:2,single:2,others:1,center:t=>({x:i[0],y:i[1],z:3===n?i[2]:void 0})};let h,d;if("function"!=typeof o&&(t.clusterNodeStrength=t=>o),a&&l&&(h=rx(e,l),d=Array.from(new Set(null==u?void 0:u.map((t=>t.data[l]))))||[],t.centripetalOptions=Object.assign(c,{single:100,leaf:e=>{const{siblingLeaves:n,sameTypeLeaves:r}=h[e.id]||{};return(null==r?void 0:r.length)===(null==n?void 0:n.length)||1===(null==d?void 0:d.length)?1:t.clusterNodeStrength(e)},others:1,center:t=>{const n=e.getDegree(t.id,"both");if(!n)return{x:100,y:100,z:0};let r;if(1===n){const{sameTypeLeaves:e=[]}=h[t.id]||{};1===e.length?r=void 0:e.length>1&&(r=ax(e))}else r=void 0;return{x:null==r?void 0:r.x,y:null==r?void 0:r.y,z:null==r?void 0:r.z}}})),s&&l){h||(h=rx(e,l)),d||(d=Array.from(new Set(u.map((t=>t.data[l]))))),d=d.filter((t=>void 0!==t));const n={};d.forEach((t=>{const r=u.filter((e=>e.data[l]===t)).map((t=>e.getNode(t.id)));n[t]=ax(r)})),t.centripetalOptions=Object.assign(c,{single:e=>t.clusterNodeStrength(e),leaf:e=>t.clusterNodeStrength(e),others:e=>t.clusterNodeStrength(e),center:t=>{const e=n[t.data[l]];return{x:null==e?void 0:e.x,y:null==e?void 0:e.y,z:null==e?void 0:e.z}}})}const{leaf:f,single:p,others:g}=t.centripetalOptions||{};f&&"function"!=typeof f&&(t.centripetalOptions.leaf=()=>f),p&&"function"!=typeof p&&(t.centripetalOptions.single=()=>p),g&&"function"!=typeof g&&(t.centripetalOptions.others=()=>g)}runOneStep(t,e,n,r,i){const o={},a=t.getAllNodes(),s=t.getAllEdges();if(!(null==a?void 0:a.length))return;const{monitor:l}=i;if(this.calRepulsive(t,o,i),s&&this.calAttractive(t,o,i),this.calGravity(t,e,o,i),this.updateVelocity(t,o,r,i),l){l({energy:this.calTotalEnergy(o,a),nodes:e.getAllNodes(),edges:e.getAllEdges(),iterations:n})}}calTotalEnergy(t,e){if(!(null==e?void 0:e.length))return 0;let n=0;return e.forEach(((e,r)=>{const i=t[e.id].x,o=t[e.id].y,a=3===this.options.dimensions?t[e.id].z:0,s=i*i+o*o+a*a,{mass:l=1}=e.data;n+=l*s*.5})),n}calRepulsive(t,e,n){const{dimensions:r,factor:i,coulombDisScale:o}=n;Qb(t,i,o*o,e,r)}calAttractive(t,e,n){const{dimensions:r,nodeSize:i}=n;t.getAllEdges().forEach(((n,o)=>{const{source:a,target:s}=n,l=t.getNode(a),u=t.getNode(s);if(!l||!u)return;let c=u.data.x-l.data.x,h=u.data.y-l.data.y,d=3===r?u.data.z-l.data.z:0;c||h||(c=.01*Math.random(),h=.01*Math.random(),3!==r||d||(d=.01*Math.random()));const f=Math.sqrt(c*c+h*h+d*d);if(f{const{id:o,data:f}=r,{mass:p,x:g,y:v,z:m}=f,y=e.getNode(o);let b=0,x=0,E=0,w=h;const k=t.getDegree(o,"in"),M=t.getDegree(o,"out"),S=t.getDegree(o,"both"),N=null==i?void 0:i(y,S);if(N){const[t,e,n]=N;b=g-t,x=v-e,w=n}else b=g-c[0],x=v-c[1],E=m-c[2];if(w&&(n[o].x-=w*b/p,n[o].y-=w*x/p,n[o].z-=w*E/p),d){const{leaf:t,single:e,others:r,center:i}=d,{x:c,y:h,z:f,centerStrength:b}=(null==i?void 0:i(y,a,s,l,u))||{x:0,y:0,z:0,centerStrength:0};if(!ae(c)||!ae(h))return;const x=(g-c)/p,E=(v-h)/p,w=(m-f)/p;if(b&&(n[o].x-=b*x,n[o].y-=b*E,n[o].z-=b*w),0===S){const t=e(y);if(!t)return;return n[o].x-=t*x,n[o].y-=t*E,void(n[o].z-=t*w)}if(0===k||0===M){const e=t(y,a,s);if(!e)return;return n[o].x-=e*x,n[o].y-=e*E,void(n[o].z-=e*w)}const N=r(y);if(!N)return;n[o].x-=N*x,n[o].y-=N*E,n[o].z-=N*w}}))}updateVelocity(t,e,n,r){const{damping:i,maxSpeed:o,interval:a,dimensions:s}=r,l=t.getAllNodes();(null==l?void 0:l.length)&&l.forEach((t=>{const{id:r}=t;let l=(n[r].x+e[r].x*a)*i||.01,u=(n[r].y+e[r].y*a)*i||.01,c=3===s?(n[r].z+e[r].z*a)*i||.01:0;const h=Math.sqrt(l*l+u*u+c*c);if(h>o){const t=o/h;l*=t,u*=t,c*=t}n[r]={x:l,y:u,z:c}}))}updatePosition(t,e,n,r){const{distanceThresholdMode:i,interval:o,dimensions:a}=r,s=e.getAllNodes();if(!(null==s?void 0:s.length))return void(this.judgingDistance=0);let l=0;"max"===i?this.judgingDistance=-1/0:"min"===i&&(this.judgingDistance=1/0),s.forEach((r=>{const{id:s}=r,u=t.getNode(s);if(ae(u.data.fx)&&ae(u.data.fy))return void e.mergeNodeData(s,{x:u.data.fx,y:u.data.fy,z:3===a?u.data.fz:void 0});const c=n[s].x*o,h=n[s].y*o,d=3===a?n[s].z*o:0;e.mergeNodeData(s,{x:r.data.x+c,y:r.data.y+h,z:r.data.z+d});const f=Math.sqrt(c*c+h*h+d*d);switch(i){case"max":this.judgingDistancef&&(this.judgingDistance=f);break;default:l+=f}})),i&&"mean"!==i||(this.judgingDistance=l/s.length)}}const rx=(t,e)=>{const n=t.getAllNodes();if(!(null==n?void 0:n.length))return{};const r={};return n.forEach(((n,i)=>{1===t.getDegree(n.id,"both")&&(r[n.id]=ix(t,"leaf",n,e))})),r},ix=(t,e,n,r)=>{const i=t.getDegree(n.id,"in"),o=t.getDegree(n.id,"out");let a=n,s=[];0===i?(a=t.getSuccessors(n.id)[0],s=t.getNeighbors(a.id)):0===o&&(a=t.getPredecessors(n.id)[0],s=t.getNeighbors(a.id)),s=s.filter((e=>0===t.getDegree(e.id,"in")||0===t.getDegree(e.id,"out")));return{coreNode:a,siblingLeaves:s,sameTypeLeaves:ox(t,e,r,n,s)}},ox=(t,e,n,r,i)=>{const o=r.data[n]||"";let a=(null==i?void 0:i.filter((t=>t.data[n]===o)))||[];return a=a.filter((e=>0===t.getDegree(e.id,"in")||0===t.getDegree(e.id,"out"))),a},ax=t=>{const e={x:0,y:0};t.forEach((t=>{const{x:n,y:r}=t.data;e.x+=n||0,e.y+=r||0}));const n=t.length||1;return{x:e.x/n,y:e.y/n}},sx=(t,e)=>e.map((e=>{const{id:n,data:r}=e,i=t.getNode(n);return Object.assign(Object.assign({},i),{data:Object.assign(Object.assign({},i.data),{x:r.x,y:r.y,z:r.z})})}));var lx={};const ux=Object.prototype.toString;function cx(t){const e=ux.call(t);return e.endsWith("Array]")&&!e.includes("Big")}var hx=w(Object.freeze({__proto__:null,isAnyArray:cx}));var dx=Object.freeze({__proto__:null,default:function(t){var e,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!cx(t))throw new TypeError("input must be an array");if(0===t.length)throw new TypeError("input must not be empty");if(void 0!==n.output){if(!cx(n.output))throw new TypeError("output option must be an array if specified");e=n.output}else e=new Array(t.length);var r=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!cx(t))throw new TypeError("input must be an array");if(0===t.length)throw new TypeError("input must not be empty");var n=e.fromIndex,r=void 0===n?0:n,i=e.toIndex,o=void 0===i?t.length:i;if(r<0||r>=t.length||!Number.isInteger(r))throw new Error("fromIndex must be a positive integer smaller than length");if(o<=r||o>t.length||!Number.isInteger(o))throw new Error("toIndex must be an integer greater than fromIndex and at most equal to length");for(var a=t[r],s=r+1;s1&&void 0!==arguments[1]?arguments[1]:{};if(!cx(t))throw new TypeError("input must be an array");if(0===t.length)throw new TypeError("input must not be empty");var n=e.fromIndex,r=void 0===n?0:n,i=e.toIndex,o=void 0===i?t.length:i;if(r<0||r>=t.length||!Number.isInteger(r))throw new Error("fromIndex must be a positive integer smaller than length");if(o<=r||o>t.length||!Number.isInteger(o))throw new Error("toIndex must be an integer greater than fromIndex and at most equal to length");for(var a=t[r],s=r+1;sa&&(a=t[s]);return a}(t);if(r===i)throw new RangeError("minimum and maximum input values are equal. Cannot rescale a constant array");var o=n.min,a=void 0===o?n.autoMinMax?r:0:o,s=n.max,l=void 0===s?n.autoMinMax?i:1:s;if(a>=l)throw new RangeError("min option must be smaller than max option");for(var u=(l-a)/(i-r),c=0;c=0&&n?` ${xx(t,e-1)}`:xx(t,e)).padEnd(e)}function xx(t,e){let n=t.toString();if(n.length<=e)return n;let r=t.toFixed(e);if(r.length>e&&(r=t.toFixed(Math.max(0,e-(r.length-e)))),r.length<=e&&!r.startsWith("0.000")&&!r.startsWith("-0.000"))return r;let i=t.toExponential(e);return i.length>e&&(i=t.toExponential(Math.max(0,e-(i.length-e)))),i.slice(0)}function Ex(t,e,n){let r=n?t.rows:t.rows-1;if(e<0||e>r)throw new RangeError("Row index out of range")}function wx(t,e,n){let r=n?t.columns:t.columns-1;if(e<0||e>r)throw new RangeError("Column index out of range")}function kx(t,e){if(e.to1DArray&&(e=e.to1DArray()),e.length!==t.columns)throw new RangeError("vector size must be the same as the number of columns");return e}function Mx(t,e){if(e.to1DArray&&(e=e.to1DArray()),e.length!==t.rows)throw new RangeError("vector size must be the same as the number of rows");return e}function Sx(t,e){if(!px.isAnyArray(e))throw new TypeError("row indices must be an array");for(let n=0;n=t.rows)throw new RangeError("row indices are out of range")}function Nx(t,e){if(!px.isAnyArray(e))throw new TypeError("column indices must be an array");for(let n=0;n=t.columns)throw new RangeError("column indices are out of range")}function Ox(t,e,n,r,i){if(5!==arguments.length)throw new RangeError("expected 4 arguments");if(Cx("startRow",e),Cx("endRow",n),Cx("startColumn",r),Cx("endColumn",i),e>n||r>i||e<0||e>=t.rows||n<0||n>=t.rows||r<0||r>=t.columns||i<0||i>=t.columns)throw new RangeError("Submatrix indices are out of range")}function Tx(t,e=0){let n=[];for(let r=0;r=i)throw new RangeError("min must be smaller than max");let a=i-r,s=new Dx(t,e);for(let n=0;nn?(i=!0,n=e):(r=!1,i=!0);t++}return r}isReducedEchelonForm(){let t=0,e=0,n=-1,r=!0,i=!1;for(;tn?(i=!0,n=e):(r=!1,i=!0);for(let n=e+1;nt.get(r,n)&&(r=i);if(0===t.get(r,n))n++;else{t.swapRows(e,r);let i=t.get(e,n);for(let r=n;r=0;)if(0===t.maxRow(r))r--;else{let i=0,o=!1;for(;it[e]&&(t[e]=this.get(e,n));return t}case"column":{const t=new Array(this.columns).fill(Number.NEGATIVE_INFINITY);for(let e=0;et[n]&&(t[n]=this.get(e,n));return t}case void 0:{let t=this.get(0,0);for(let e=0;et&&(t=this.get(e,n));return t}default:throw new Error(`invalid option: ${t}`)}}maxIndex(){Ax(this);let t=this.get(0,0),e=[0,0];for(let n=0;nt&&(t=this.get(n,r),e[0]=n,e[1]=r);return e}min(t){if(this.isEmpty())return NaN;switch(t){case"row":{const t=new Array(this.rows).fill(Number.POSITIVE_INFINITY);for(let e=0;ee&&(e=this.get(t,n));return e}maxRowIndex(t){Ex(this,t),Ax(this);let e=this.get(t,0),n=[t,0];for(let r=1;re&&(e=this.get(t,r),n[1]=r);return n}minRow(t){if(Ex(this,t),this.isEmpty())return NaN;let e=this.get(t,0);for(let n=1;ne&&(e=this.get(n,t));return e}maxColumnIndex(t){wx(this,t),Ax(this);let e=this.get(0,t),n=[0,t];for(let r=1;re&&(e=this.get(r,t),n[0]=r);return n}minColumn(t){if(wx(this,t),this.isEmpty())return NaN;let e=this.get(0,t);for(let n=1;n=1;r/=2)1&r&&(e=e.mmul(n)),n=n.mmul(n);return e}strassen2x2(t){t=Dx.checkMatrix(t);let e=new Dx(2,2);const n=this.get(0,0),r=t.get(0,0),i=this.get(0,1),o=t.get(0,1),a=this.get(1,0),s=t.get(1,0),l=this.get(1,1),u=t.get(1,1),c=(n+l)*(r+u),h=(a+l)*r,d=n*(o-u),f=l*(s-r),p=(n+i)*u,g=c+f-p+(i-l)*(s+u),v=d+p,m=h+f,y=c-h+d+(a-n)*(r+o);return e.set(0,0,g),e.set(0,1,v),e.set(1,0,m),e.set(1,1,y),e}strassen3x3(t){t=Dx.checkMatrix(t);let e=new Dx(3,3);const n=this.get(0,0),r=this.get(0,1),i=this.get(0,2),o=this.get(1,0),a=this.get(1,1),s=this.get(1,2),l=this.get(2,0),u=this.get(2,1),c=this.get(2,2),h=t.get(0,0),d=t.get(0,1),f=t.get(0,2),p=t.get(1,0),g=t.get(1,1),v=t.get(1,2),m=t.get(2,0),y=t.get(2,1),b=t.get(2,2),x=(n-o)*(-d+g),E=(-n+o+a)*(h-d+g),w=(o+a)*(-h+d),k=n*h,M=(-n+l+u)*(h-f+v),S=(-n+l)*(f-v),N=(l+u)*(-h+f),O=(-i+u+c)*(g+m-y),T=(i-c)*(g-y),C=i*m,A=(u+c)*(-m+y),P=(-i+a+s)*(v+m-b),R=(i-s)*(v-b),D=(a+s)*(-m+b),L=k+C+r*p,_=(n+r+i-o-a-u-c)*g+E+w+k+O+C+A,I=k+M+N+(n+r+i-a-s-l-u)*v+C+P+D,j=x+a*(-h+d+p-g-v-m+b)+E+k+C+P+R,B=x+E+w+k+s*y,F=C+P+R+D+o*f,z=k+M+S+u*(-h+f+p-g-v-m+y)+O+T+C,G=O+T+C+A+l*d,V=k+M+S+N+c*b;return e.set(0,0,L),e.set(0,1,_),e.set(0,2,I),e.set(1,0,j),e.set(1,1,B),e.set(1,2,F),e.set(2,0,z),e.set(2,1,G),e.set(2,2,V),e}mmulStrassen(t){t=Dx.checkMatrix(t);let e=this.clone(),n=e.rows,r=e.columns,i=t.rows,o=t.columns;function a(t,e,n){let r=t.rows,i=t.columns;if(r===e&&i===n)return t;{let r=Px.zeros(e,n);return r=r.setSubMatrix(t,0,0),r}}r!==i&&console.warn(`Multiplying ${n} x ${r} and ${i} x ${o} matrix: dimensions do not match.`);let s=Math.max(n,i),l=Math.max(r,o);return e=a(e,s,l),function t(e,n,r,i){if(r<=512||i<=512)return e.mmul(n);r%2==1&&i%2==1?(e=a(e,r+1,i+1),n=a(n,r+1,i+1)):r%2==1?(e=a(e,r+1,i),n=a(n,r+1,i)):i%2==1&&(e=a(e,r,i+1),n=a(n,r,i+1));let o=parseInt(e.rows/2,10),s=parseInt(e.columns/2,10),l=e.subMatrix(0,o-1,0,s-1),u=n.subMatrix(0,o-1,0,s-1),c=e.subMatrix(0,o-1,s,e.columns-1),h=n.subMatrix(0,o-1,s,n.columns-1),d=e.subMatrix(o,e.rows-1,0,s-1),f=n.subMatrix(o,n.rows-1,0,s-1),p=e.subMatrix(o,e.rows-1,s,e.columns-1),g=n.subMatrix(o,n.rows-1,s,n.columns-1),v=t(Px.add(l,p),Px.add(u,g),o,s),m=t(Px.add(d,p),u,o,s),y=t(l,Px.sub(h,g),o,s),b=t(p,Px.sub(f,u),o,s),x=t(Px.add(l,c),g,o,s),E=t(Px.sub(d,l),Px.add(u,h),o,s),w=t(Px.sub(c,p),Px.add(f,g),o,s),k=Px.add(v,b);k.sub(x),k.add(w);let M=Px.add(y,x),S=Px.add(m,b),N=Px.sub(v,m);N.add(y),N.add(E);let O=Px.zeros(2*k.rows,2*k.columns);return O=O.setSubMatrix(k,0,0),O=O.setSubMatrix(M,k.rows,0),O=O.setSubMatrix(S,0,k.columns),O=O.setSubMatrix(N,k.rows,k.columns),O.subMatrix(0,r-1,0,i-1)}(e,t=a(t,s,l),s,l)}scaleRows(t={}){if("object"!=typeof t)throw new TypeError("options must be an object");const{min:e=0,max:n=1}=t;if(!Number.isFinite(e))throw new TypeError("min must be a number");if(!Number.isFinite(n))throw new TypeError("max must be a number");if(e>=n)throw new RangeError("min must be smaller than max");let r=new Dx(this.rows,this.columns);for(let t=0;t0&&gx(i,{min:e,max:n,output:i}),r.setRow(t,i)}return r}scaleColumns(t={}){if("object"!=typeof t)throw new TypeError("options must be an object");const{min:e=0,max:n=1}=t;if(!Number.isFinite(e))throw new TypeError("min must be a number");if(!Number.isFinite(n))throw new TypeError("max must be a number");if(e>=n)throw new RangeError("min must be smaller than max");let r=new Dx(this.rows,this.columns);for(let t=0;tn||e<0||e>=this.columns||n<0||n>=this.columns)throw new RangeError("Argument out of range");let r=new Dx(t.length,n-e+1);for(let i=0;i=this.rows)throw new RangeError(`Row index out of range: ${t[i]}`);r.set(i,o-e,this.get(t[i],o))}return r}subMatrixColumn(t,e,n){if(void 0===e&&(e=0),void 0===n&&(n=this.rows-1),e>n||e<0||e>=this.rows||n<0||n>=this.rows)throw new RangeError("Argument out of range");let r=new Dx(n-e+1,t.length);for(let i=0;i=this.columns)throw new RangeError(`Column index out of range: ${t[i]}`);r.set(o-e,i,this.get(o,t[i]))}return r}setSubMatrix(t,e,n){if((t=Dx.checkMatrix(t)).isEmpty())return this;Ox(this,e,e+t.rows-1,n,n+t.columns-1);for(let r=0;r=0))throw new TypeError("nColumns must be a positive integer");for(let n=0;n=0)this.#t(e,n);else{if(!px.isAnyArray(e))throw new TypeError("First argument must be a positive number or an array");{const t=e;if("number"!=typeof(n=(e=t.length)?t[0].length:0))throw new TypeError("Data must be a 2D array with at least one element");this.data=[];for(let r=0;r"number"==typeof t)))throw new TypeError("Input data contains non-numeric values");this.data.push(Float64Array.from(t[r]))}this.rows=e,this.columns=n}}}set(t,e,n){return this.data[t][e]=n,this}get(t,e){return this.data[t][e]}removeRow(t){return Ex(this,t),this.data.splice(t,1),this.rows-=1,this}addRow(t,e){return void 0===e&&(e=t,t=this.rows),Ex(this,t,!0),e=Float64Array.from(kx(this,e)),this.data.splice(t,0,e),this.rows+=1,this}removeColumn(t){wx(this,t);for(let e=0;e>t);return this},t.prototype.signPropagatingRightShiftM=function(t){if(t=e.checkMatrix(t),this.rows!==t.rows||this.columns!==t.columns)throw new RangeError("Matrices dimensions must be equal");for(let e=0;e>t.get(e,n));return this},t.signPropagatingRightShift=function(t,n){return new e(t).signPropagatingRightShift(n)},t.prototype.rightShift=function(t){return"number"==typeof t?this.rightShiftS(t):this.rightShiftM(t)},t.prototype.rightShiftS=function(t){for(let e=0;e>>t);return this},t.prototype.rightShiftM=function(t){if(t=e.checkMatrix(t),this.rows!==t.rows||this.columns!==t.columns)throw new RangeError("Matrices dimensions must be equal");for(let e=0;e>>t.get(e,n));return this},t.rightShift=function(t,n){return new e(t).rightShift(n)},t.prototype.zeroFillRightShift=t.prototype.rightShift,t.prototype.zeroFillRightShiftS=t.prototype.rightShiftS,t.prototype.zeroFillRightShiftM=t.prototype.rightShiftM,t.zeroFillRightShift=t.rightShift,t.prototype.not=function(){for(let t=0;t=0)this.#e=new Dx(t,t);else if(this.#e=new Dx(t),!this.isSymmetric())throw new TypeError("not symmetric data")}clone(){const t=new Lx(this.diagonalSize);for(const[e,n,r]of this.upperRightEntries())t.set(e,n,r);return t}toMatrix(){return new Dx(this)}get(t,e){return this.#e.get(t,e)}set(t,e,n){return this.#e.set(t,e,n),this.#e.set(e,t,n),this}removeCross(t){return this.#e.removeRow(t),this.#e.removeColumn(t),this}addCross(t,e){void 0===e&&(e=t,t=this.diagonalSize);const n=e.slice();return n.splice(t,1),this.#e.addRow(t,n),this.#e.addColumn(t,e),this}applyMask(t){if(t.length!==this.diagonalSize)throw new RangeError("Mask size do not match with matrix size");const e=[];for(const[n,r]of t.entries())r||e.push(n);e.reverse();for(const t of e)this.removeCross(t);return this}toCompact(){const{diagonalSize:t}=this,e=new Array(t*(t+1)/2);for(let n=0,r=0,i=0;i=t&&(n=++r);return e}static fromCompact(t){const e=t.length,n=(Math.sqrt(8*e+1)-1)/2;if(!Number.isInteger(n))throw new TypeError(`This array is not a compact representation of a Symmetric Matrix, ${JSON.stringify(t)}`);const r=new Lx(n);for(let i=0,o=0,a=0;a=n&&(i=++o);return r}*upperRightEntries(){for(let t=0,e=0;t=this.diagonalSize&&(e=++t)}}*upperRightValues(){for(let t=0,e=0;t=this.diagonalSize&&(e=++t)}}}Lx.prototype.klassType="SymmetricMatrix";class _x extends Lx{static isDistanceMatrix(t){return Lx.isSymmetricMatrix(t)&&"DistanceMatrix"===t.klassSubType}constructor(t){if(super(t),!this.isDistance())throw new TypeError("Provided arguments do no produce a distance matrix")}set(t,e,n){return t===e&&(n=0),super.set(t,e,n)}addCross(t,e){return void 0===e&&(e=t,t=this.diagonalSize),(e=e.slice())[t]=0,super.addCross(t,e)}toSymmetricMatrix(){return new Lx(this)}clone(){const t=new _x(this.diagonalSize);for(const[e,n,r]of this.upperRightEntries())e!==n&&t.set(e,n,r);return t}toCompact(){const{diagonalSize:t}=this,e=new Array((t-1)*t/2);for(let n=1,r=0,i=0;i=t&&(n=1+ ++r);return e}static fromCompact(t){const e=t.length;if(0===e)return new this(0);const n=(Math.sqrt(8*e+1)+1)/2;if(!Number.isInteger(n))throw new TypeError(`This array is not a compact representation of a DistanceMatrix, ${JSON.stringify(t)}`);const r=new this(n);for(let i=1,o=0,a=0;a=n&&(i=1+ ++o);return r}}_x.prototype.klassSubType="DistanceMatrix";class Ix extends Px{constructor(t,e,n){super(),this.matrix=t,this.rows=e,this.columns=n}}class jx extends Ix{constructor(t,e,n){Sx(t,e),Nx(t,n),super(t,e.length,n.length),this.rowIndices=e,this.columnIndices=n}set(t,e,n){return this.matrix.set(this.rowIndices[t],this.columnIndices[e],n),this}get(t,e){return this.matrix.get(this.rowIndices[t],this.columnIndices[e])}}class Bx extends Px{constructor(t,e={}){const{rows:n=1}=e;if(t.length%n!==0)throw new Error("the data length is not divisible by the number of rows");super(),this.rows=n,this.columns=t.length/n,this.data=t}set(t,e,n){let r=this._calculateIndex(t,e);return this.data[r]=n,this}get(t,e){let n=this._calculateIndex(t,e);return this.data[n]}_calculateIndex(t,e){return t*this.columns+e}}class Fx extends Px{constructor(t){super(),this.data=t,this.rows=t.length,this.columns=t[0].length}set(t,e,n){return this.data[t][e]=n,this}get(t,e){return this.data[t][e]}}class zx{constructor(t){let e,n,r,i,o,a,s,l,u,c=(t=Fx.checkMatrix(t)).clone(),h=c.rows,d=c.columns,f=new Float64Array(h),p=1;for(e=0;eMath.abs(l[i])&&(i=e);if(i!==n){for(r=0;r=0;i--){for(r=0;re?r.set(i,e,t.get(i,e)):i===e?r.set(i,e,1):r.set(i,e,0);return r}get upperTriangularMatrix(){let t=this.LU,e=t.rows,n=t.columns,r=new Dx(e,n);for(let i=0;iMath.abs(e)?(n=e/t,Math.abs(t)*Math.sqrt(1+n*n)):0!==e?(n=t/e,Math.abs(e)*Math.sqrt(1+n*n)):0}class Vx{constructor(t){let e,n,r,i,o=(t=Fx.checkMatrix(t)).clone(),a=t.rows,s=t.columns,l=new Float64Array(s);for(r=0;r=0;o--){for(i=0;i=0;n--){for(t=0;t=0;t--)if(0!==f[t]){for(let e=t+1;e=0;t--){if(t0;){let t,e;for(t=w-2;t>=-1&&-1!==t;t--){const e=Number.MIN_VALUE+M*Math.abs(f[t]+Math.abs(f[t+1]));if(Math.abs(v[t])<=e||Number.isNaN(v[t])){v[t]=0;break}}if(t===w-2)e=4;else{let n;for(n=w-1;n>=t&&n!==t;n--){let e=(n!==w?Math.abs(v[n]):0)+(n!==t+1?Math.abs(v[n-1]):0);if(Math.abs(f[n])<=M*e){f[n]=0;break}}n===t?e=3:n===w-1?e=1:(e=2,t=n)}switch(t++,e){case 1:{let e=v[w-2];v[w-2]=0;for(let n=w-2;n>=t;n--){let i=Gx(f[n],e),o=f[n]/i,a=e/i;if(f[n]=i,n!==t&&(e=-a*v[n-1],v[n-1]=o*v[n-1]),u)for(let t=0;t=f[t+1]);){let e=f[t];if(f[t]=f[t+1],f[t+1]=e,u&&te&&i.set(o,n,t.get(o,n)/this.s[n]);let o=this.U,a=o.rows,s=o.columns,l=new Dx(n,a);for(let t=0;tt&&e++;return e}get diagonal(){return Array.from(this.s)}get threshold(){return Number.EPSILON/2*Math.max(this.m,this.n)*this.s[0]}get leftSingularVectors(){return this.U}get rightSingularVectors(){return this.V}get diagonalMatrix(){return Dx.diag(this.s)}};function Hx(t,e,n=!1){return t=Fx.checkMatrix(t),e=Fx.checkMatrix(e),n?new Wx(t).solve(e):t.isSquare()?new zx(t).solve(e):new Vx(t).solve(e)}function Ux(t,e){let n=[];for(let r=0;ri)return new Array(e.rows+1).fill(0);{let t=e.addRow(n,[0]);for(let e=0;e0;s--){for(h=0,a=0,u=0;u0&&(o=-o),e[s]=h*o,a-=i*o,n[s-1]=i-o,l=0;lu)do{for(i=n[u],h=(n[u+1]-i)/(2*e[u]),d=Gx(h,1),h<0&&(d=-d),n[u]=e[u]/(h+d),n[u+1]=e[u]*(h+d),f=n[u+1],o=i-n[u],a=u+2;a=u;a--)for(v=g,g=p,b=y,i=p*e[a],o=p*h,d=Gx(h,e[a]),e[a+1]=y*d,y=e[a]/d,p=h/d,h=p*n[a]-y*i,n[a+1]=o+y*(p*i+y*n[a]),l=0;lw*E);n[u]=n[u]+x,e[u]=0}for(a=0;a=u;s--)n[s]=e.get(s,u-1)/c,a+=n[s]*n[s];for(o=Math.sqrt(a),n[u]>0&&(o=-o),a-=n[u]*o,n[u]=n[u]-o,l=u;l=u;s--)i+=n[s]*e.get(s,l);for(i/=a,s=u;s<=d;s++)e.set(s,l,e.get(s,l)-i*n[s])}for(s=0;s<=d;s++){for(i=0,l=d;l>=u;l--)i+=n[l]*e.get(s,l);for(i/=a,l=u;l<=d;l++)e.set(s,l,e.get(s,l)-i*n[l])}n[u]=c*n[u],e.set(u,u-1,c*o)}}for(s=0;s=h+1;u--)if(0!==e.get(u,u-1)){for(s=u+1;s<=d;s++)n[s]=e.get(s,u-1);for(l=u;l<=d;l++){for(o=0,s=u;s<=d;s++)o+=n[s]*r.get(s,l);for(o=o/n[u]/e.get(u,u-1),s=u;s<=d;s++)r.set(s,l,r.get(s,l)+o*n[s])}}}(o,t,e,a),function(t,e,n,r,i){let o,a,s,l,u,c,h,d,f,p,g,v,m,y,b,x=t-1,E=0,w=t-1,k=Number.EPSILON,M=0,S=0,N=0,O=0,T=0,C=0,A=0,P=0;for(o=0;ow)&&(n[o]=i.get(o,o),e[o]=0),a=Math.max(o-1,0);a=E;){for(l=x;l>E&&(C=Math.abs(i.get(l-1,l-1))+Math.abs(i.get(l,l)),0===C&&(C=S),!(Math.abs(i.get(l,l-1))=0){for(A=N>=0?N+A:N-A,n[x-1]=d+A,n[x]=n[x-1],0!==A&&(n[x]=d-h/A),e[x-1]=0,e[x]=0,d=i.get(x,x-1),C=Math.abs(d)+Math.abs(A),N=d/C,O=A/C,T=Math.sqrt(N*N+O*O),N/=T,O/=T,a=x-1;a0)){for(C=Math.sqrt(C),f=l&&(A=i.get(u,u),T=d-A,C=f-A,N=(T*C-h)/i.get(u+1,u)+i.get(u,u+1),O=i.get(u+1,u+1)-A-T-C,T=i.get(u+2,u+1),C=Math.abs(N)+Math.abs(O)+Math.abs(T),N/=C,O/=C,T/=C,u!==l)&&!(Math.abs(i.get(u,u-1))*(Math.abs(O)+Math.abs(T))u+2&&i.set(o,o-3,0);for(s=u;s<=x-1&&(y=s!==x-1,s!==u&&(N=i.get(s,s-1),O=i.get(s+1,s-1),T=y?i.get(s+2,s-1):0,d=Math.abs(N)+Math.abs(O)+Math.abs(T),0!==d&&(N/=d,O/=d,T/=d)),0!==d);s++)if(C=Math.sqrt(N*N+O*O+T*T),N<0&&(C=-C),0!==C){for(s!==u?i.set(s,s-1,-C*d):l!==u&&i.set(s,s-1,-i.get(s,s-1)),N+=C,d=N/C,f=O/C,A=T/C,O/=N,T/=N,a=s;a=0;x--)if(N=n[x],O=e[x],0===O)for(l=x,i.set(x,x,1),o=x-1;o>=0;o--){for(h=i.get(o,o)-N,T=0,a=l;a<=x;a++)T+=i.get(o,a)*i.get(a,x);if(e[o]<0)A=h,C=T;else if(l=o,0===e[o]?i.set(o,x,0!==h?-T/h:-T/(k*S)):(d=i.get(o,o+1),f=i.get(o+1,o),O=(n[o]-N)*(n[o]-N)+e[o]*e[o],c=(d*C-A*T)/O,i.set(o,x,c),i.set(o+1,x,Math.abs(d)>Math.abs(A)?(-T-h*c)/d:(-C-f*c)/A)),c=Math.abs(i.get(o,x)),k*c*c>1)for(a=o;a<=x;a++)i.set(a,x,i.get(a,x)/c)}else if(O<0)for(l=x-1,Math.abs(i.get(x,x-1))>Math.abs(i.get(x-1,x))?(i.set(x-1,x-1,O/i.get(x,x-1)),i.set(x-1,x,-(i.get(x,x)-N)/i.get(x,x-1))):(b=qx(0,-i.get(x-1,x),i.get(x-1,x-1)-N,O),i.set(x-1,x-1,b[0]),i.set(x-1,x,b[1])),i.set(x,x-1,0),i.set(x,x,1),o=x-2;o>=0;o--){for(p=0,g=0,a=l;a<=x;a++)p+=i.get(o,a)*i.get(a,x-1),g+=i.get(o,a)*i.get(a,x);if(h=i.get(o,o)-N,e[o]<0)A=h,T=p,C=g;else if(l=o,0===e[o]?(b=qx(-p,-g,h,O),i.set(o,x-1,b[0]),i.set(o,x,b[1])):(d=i.get(o,o+1),f=i.get(o+1,o),v=(n[o]-N)*(n[o]-N)+e[o]*e[o]-O*O,m=2*(n[o]-N)*O,0===v&&0===m&&(v=k*S*(Math.abs(h)+Math.abs(O)+Math.abs(d)+Math.abs(f)+Math.abs(A))),b=qx(d*T-A*p+O*g,d*C-A*g-O*p,v,m),i.set(o,x-1,b[0]),i.set(o,x,b[1]),Math.abs(d)>Math.abs(A)+Math.abs(O)?(i.set(o+1,x-1,(-p-h*i.get(o,x-1)+O*i.get(o,x))/d),i.set(o+1,x,(-g-h*i.get(o,x)-O*i.get(o,x-1))/d)):(b=qx(-T-f*i.get(o,x-1),-C-f*i.get(o,x),A,O),i.set(o+1,x-1,b[0]),i.set(o+1,x,b[1]))),c=Math.max(Math.abs(i.get(o,x-1)),Math.abs(i.get(o,x))),k*c*c>1)for(a=o;a<=x;a++)i.set(a,x-1,i.get(a,x-1)/c),i.set(a,x,i.get(a,x)/c)}for(o=0;ow)for(a=o;a=E;a--)for(o=E;o<=w;o++){for(A=0,s=E;s<=Math.min(a,w);s++)A+=r.get(o,s)*i.get(s,a);r.set(o,a,A)}}(o,l,s,a,t)}this.n=o,this.e=l,this.d=s,this.V=a}get realEigenvalues(){return Array.from(this.d)}get imaginaryEigenvalues(){return Array.from(this.e)}get eigenvectorMatrix(){return this.V}get diagonalMatrix(){let t,e,n=this.n,r=this.e,i=this.d,o=new Dx(n,n);for(t=0;t0?o.set(t,t+1,r[t]):r[t]<0&&o.set(t,t-1,r[t])}return o}}function qx(t,e,n,r){let i,o;return Math.abs(n)>Math.abs(r)?(i=r/n,o=n+i*r,[(t+i*e)/o,(e-i*t)/o]):(i=n/r,o=r+i*n,[(i*t+e)/o,(i*e-t)/o])}class Xx{constructor(t){if(!(t=Fx.checkMatrix(t)).isSymmetric())throw new Error("Matrix is not symmetric");let e,n,r,i=t,o=i.rows,a=new Dx(o,o),s=!0;for(n=0;n0,a.set(n,n,Math.sqrt(Math.max(t,0))),r=n+1;r=0;o--)for(i=0;io;e++)u=t.transpose().mmul(a).div(a.transpose().mmul(a).get(0,0)),u=u.div(u.norm()),s=t.mmul(u).div(u.transpose().mmul(u).get(0,0)),e>0&&(h=s.clone().sub(c).pow(2).sum()),c=s.clone(),n?(l=n.transpose().mmul(s).div(s.transpose().mmul(s).get(0,0)),l=l.div(l.norm()),a=n.mmul(l).div(l.transpose().mmul(l).get(0,0))):a=s;if(n){let e=t.transpose().mmul(s).div(s.transpose().mmul(s).get(0,0));e=e.div(e.norm());let r=t.clone().sub(s.clone().mmul(e.transpose())),i=a.transpose().mmul(s).div(s.transpose().mmul(s).get(0,0)),o=n.clone().sub(s.clone().mulS(i.get(0,0)).mmul(l.transpose()));this.t=s,this.p=e.transpose(),this.w=u.transpose(),this.q=l,this.u=a,this.s=s.transpose().mmul(s),this.xResidual=r,this.yResidual=o,this.betas=i}else this.w=u.transpose(),this.s=s.transpose().mmul(s).sqrt(),this.t=r?s.clone().div(this.s.get(0,0)):s,this.xResidual=t.sub(s.mmul(u.transpose()))}}lx.AbstractMatrix=Px,lx.CHO=Xx,lx.CholeskyDecomposition=Xx,lx.DistanceMatrix=_x,lx.EVD=Yx,lx.EigenvalueDecomposition=Yx,lx.LU=zx,lx.LuDecomposition=zx;var Zx=lx.Matrix=Dx;lx.MatrixColumnSelectionView=class extends Ix{constructor(t,e){Nx(t,e),super(t,t.rows,e.length),this.columnIndices=e}set(t,e,n){return this.matrix.set(t,this.columnIndices[e],n),this}get(t,e){return this.matrix.get(t,this.columnIndices[e])}},lx.MatrixColumnView=class extends Ix{constructor(t,e){wx(t,e),super(t,t.rows,1),this.column=e}set(t,e,n){return this.matrix.set(t,this.column,n),this}get(t){return this.matrix.get(t,this.column)}},lx.MatrixFlipColumnView=class extends Ix{constructor(t){super(t,t.rows,t.columns)}set(t,e,n){return this.matrix.set(t,this.columns-e-1,n),this}get(t,e){return this.matrix.get(t,this.columns-e-1)}},lx.MatrixFlipRowView=class extends Ix{constructor(t){super(t,t.rows,t.columns)}set(t,e,n){return this.matrix.set(this.rows-t-1,e,n),this}get(t,e){return this.matrix.get(this.rows-t-1,e)}},lx.MatrixRowSelectionView=class extends Ix{constructor(t,e){Sx(t,e),super(t,e.length,t.columns),this.rowIndices=e}set(t,e,n){return this.matrix.set(this.rowIndices[t],e,n),this}get(t,e){return this.matrix.get(this.rowIndices[t],e)}},lx.MatrixRowView=class extends Ix{constructor(t,e){Ex(t,e),super(t,1,t.columns),this.row=e}set(t,e,n){return this.matrix.set(this.row,e,n),this}get(t,e){return this.matrix.get(this.row,e)}},lx.MatrixSelectionView=jx,lx.MatrixSubView=class extends Ix{constructor(t,e,n,r,i){Ox(t,e,n,r,i),super(t,n-e+1,i-r+1),this.startRow=e,this.startColumn=r}set(t,e,n){return this.matrix.set(this.startRow+t,this.startColumn+e,n),this}get(t,e){return this.matrix.get(this.startRow+t,this.startColumn+e)}},lx.MatrixTransposeView=class extends Ix{constructor(t){super(t,t.columns,t.rows)}set(t,e,n){return this.matrix.set(e,t,n),this}get(t,e){return this.matrix.get(e,t)}},lx.NIPALS=Kx,lx.Nipals=Kx,lx.QR=Vx,lx.QrDecomposition=Vx,lx.SVD=Wx;var Qx=lx.SingularValueDecomposition=Wx;lx.SymmetricMatrix=Lx,lx.WrapperMatrix1D=Bx,lx.WrapperMatrix2D=Fx,lx.correlation=function(t,e=t,n={}){t=new Dx(t);let r=!1;if("object"!=typeof e||Dx.isMatrix(e)||px.isAnyArray(e)?e=new Dx(e):(n=e,e=t,r=!0),t.rows!==e.rows)throw new TypeError("Both matrices must have the same number of rows");const{center:i=!0,scale:o=!0}=n;i&&(t.center("column"),r||e.center("column")),o&&(t.scale("column"),r||e.scale("column"));const a=t.standardDeviation("column",{unbiased:!0}),s=r?a:e.standardDeviation("column",{unbiased:!0}),l=t.transpose().mmul(e);for(let e=0;ee?o[t]=1/o[t]:o[t]=0;return i.mmul(Dx.diag(o).mmul(r.transpose()))},lx.solve=Hx,lx.wrap=function(t,e){if(px.isAnyArray(t))return t[0]&&px.isAnyArray(t[0])?new Fx(t):new Bx(t,e);throw new Error("the argument is not an array")};const tE=Zx,eE=Qx;Jx.Matrix&&Jx.Matrix;const nE={center:[0,0],linkDistance:50};class rE{constructor(t={}){this.options=t,this.id="mds",this.options=Object.assign(Object.assign({},nE),t)}execute(t,e){return ze(this,void 0,void 0,(function*(){return this.genericMDSLayout(!1,t,e)}))}assign(t,e){return ze(this,void 0,void 0,(function*(){yield this.genericMDSLayout(!0,t,e)}))}genericMDSLayout(t,e,n){return ze(this,void 0,void 0,(function*(){const r=Object.assign(Object.assign({},this.options),n),{center:i=[0,0],linkDistance:o=50}=r,a=e.getAllNodes(),s=e.getAllEdges();if(!(null==a?void 0:a.length)||1===a.length)return Ob(e,t,i);const l=gb({nodes:a,edges:s}),u=pb(l);iE(u);const c=((t,e)=>{const n=[];return t.forEach((t=>{const r=[];t.forEach((t=>{r.push(t*e)})),n.push(r)})),n})(u,o),h=oE(c),d=[];h.forEach(((t,e)=>{const n=bb(a[e]);n.data.x=t[0]+i[0],n.data.y=t[1]+i[1],d.push(n)})),t&&d.forEach((t=>e.mergeNodeData(t.id,{x:t.data.x,y:t.data.y})));return{nodes:d,edges:s}}))}}const iE=t=>{let e=-999999;t.forEach((t=>{t.forEach((t=>{t!==1/0&&e{n.forEach(((n,i)=>{n===1/0&&(t[r][i]=e)}))}))},oE=t=>{const e=tE.mul(tE.pow(t,2),-.5),n=e.mean("row"),r=e.mean("column"),i=e.mean();e.add(i).subRowVector(n).subColumnVector(r);const o=new eE(e),a=tE.sqrt(o.diagonalMatrix).diagonal();return o.leftSingularVectors.toJSON().map((t=>tE.mul([t],[a]).toJSON()[0].splice(0,2)))};function aE(t){return!!t.tick&&!!t.stop}const sE={gForce:!0,force2:!0,d3force:!0,fruchterman:!0,forceAtlas2:!0,force:!0,"graphin-force":!0},lE={center:[0,0],comboPadding:10,treeKey:"combo"};class uE{constructor(t={}){this.options=t,this.id="comboCombined",this.options=Object.assign(Object.assign({},lE),t)}execute(t,e){return ze(this,void 0,void 0,(function*(){return this.genericComboCombinedLayout(!1,t,e)}))}assign(t,e){return ze(this,void 0,void 0,(function*(){yield this.genericComboCombinedLayout(!0,t,e)}))}genericComboCombinedLayout(t,e,n){return ze(this,void 0,void 0,(function*(){const r=this.initVals(Object.assign(Object.assign({},this.options),n)),{center:i,treeKey:o,outerLayout:a}=r,s=e.getAllNodes().filter((t=>!t.data._isCombo)),l=e.getAllNodes().filter((t=>t.data._isCombo)),u=e.getAllEdges(),c=null==s?void 0:s.length;if(!c||1===c)return Ob(e,t,i);const h=[],d=new Map;s.forEach((t=>{d.set(t.id,t)}));const f=new Map;l.forEach((t=>{f.set(t.id,t)}));const p=new Map,g=this.getInnerGraphs(e,o,d,f,u,r,p);yield Promise.all(g);const v=new Map,m=[],y=new Map;let b=!0;e.getRoots(o).forEach((t=>{const n=p.get(t.id),r=f.get(t.id)||d.get(t.id),i={id:t.id,data:Object.assign(Object.assign({},t.data),{x:n.data.x||r.data.x,y:n.data.y||r.data.y,fx:n.data.fx||r.data.fx,fy:n.data.fy||r.data.fy,mass:n.data.mass||r.data.mass,size:n.data.size})};m.push(i),v.set(t.id,!0),isNaN(i.data.x)||0===i.data.x||isNaN(i.data.y)||0===i.data.y?(i.data.x=100*Math.random(),i.data.y=100*Math.random()):b=!1,mb(e,[t],(e=>{e.id!==t.id&&y.set(e.id,t.id)}),"TB",o)}));const x=[];let E;if(u.forEach((t=>{const e=y.get(t.source)||t.source,n=y.get(t.target)||t.target;e!==n&&v.has(e)&&v.has(n)&&x.push({id:t.id,source:e,target:n,data:{}})})),null==m?void 0:m.length){if(1===m.length)m[0].data.x=i[0],m[0].data.y=i[1];else{const t=new ev({nodes:m,edges:x}),e=a||new nx;if(b&&sE[e.id]){const e=m.length<100?new rE:new Db;yield e.assign(t)}const n=Object.assign({center:i,kg:5,preventOverlap:!0,animate:!1},"force"===e.id?{gravity:1,factor:4,linkDistance:(t,e,n)=>(Math.max(...e.data.size)||32)/2+(Math.max(...n.data.size)||32)/2+200}:{});E=yield cE(e,t,n)}p.forEach((t=>{var e;const n=E.nodes.find((e=>e.id===t.id));if(n){const{x:e,y:r}=n.data;t.data.visited=!0,t.data.x=e,t.data.y=r,h.push({id:t.id,data:{x:e,y:r}})}const{x:r,y:i}=t.data;null===(e=t.data.nodes)||void 0===e||e.forEach((t=>{h.push({id:t.id,data:{x:t.data.x+r,y:t.data.y+i}})}))})),p.forEach((({data:t})=>{const{x:e,y:n,visited:r,nodes:i}=t;null==i||i.forEach((t=>{if(!r){const r=h.find((e=>e.id===t.id));r.data.x+=e||0,r.data.y+=n||0}}))}))}t&&h.forEach((t=>{e.mergeNodeData(t.id,{x:t.data.x,y:t.data.y})}));return{nodes:h,edges:u}}))}initVals(t){const e=Object.assign({},t),{nodeSize:n,spacing:r,comboPadding:i}=t;let o,a,s;if(a=ae(r)?()=>r:Ut(r)?r:()=>0,e.spacing=a,n)if(Ut(n))o=t=>{const e=n(t),r=a(t);if(fb(t.size)){return((t.size[0]>t.size[1]?t.size[0]:t.size[1])+r)/2}return((e||32)+r)/2};else if(fb(n)){const t=(n[0]>n[1]?n[0]:n[1])/2;o=e=>t+a(e)/2}else{const t=n/2;o=e=>t+a(e)/2}else o=t=>{const e=a(t);if(t.size){if(fb(t.size)){return((t.size[0]>t.size[1]?t.size[0]:t.size[1])+e)/2}if(qt(t.size)){return((t.size.width>t.size.height?t.size.width:t.size.height)+e)/2}return(t.size+e)/2}return 32+e/2};return e.nodeSize=o,s=ae(i)?()=>i:fb(i)?()=>Math.max.apply(null,i):Ut(i)?i:()=>0,e.comboPadding=s,e}getInnerGraphs(t,e,n,r,i,o,a){const{nodeSize:s,comboPadding:l,spacing:u,innerLayout:c}=o,h=c||new Db({}),d={center:[0,0],preventOverlap:!0,nodeSpacing:u},f=[],p=t=>{let e=(null==l?void 0:l(t))||10;return fb(e)&&(e=Math.max(...e)),{size:e?[2*e,2*e]:[30,30],padding:e}};return t.getRoots(e).forEach((o=>{a.set(o.id,{id:o.id,data:{nodes:[],size:p(o).size}});let l=Promise.resolve();mb(t,[o],(o=>{var u;if(!o.data._isCombo)return;const{size:c,padding:f}=p(o);if(null===(u=t.getChildren(o.id,e))||void 0===u?void 0:u.length){const u=a.get(o.id);a.set(o.id,{id:o.id,data:Object.assign({nodes:[]},null==u?void 0:u.data)});const c=new Map,p=t.getChildren(o.id,e).map((t=>{if(t.data._isCombo)return a.has(t.id)||a.set(t.id,{id:t.id,data:Object.assign({},t.data)}),c.set(t.id,!0),a.get(t.id);const e=n.get(t.id)||r.get(t.id);return c.set(t.id,!0),{id:t.id,data:Object.assign(Object.assign({},e.data),t.data)}})),g={nodes:p,edges:i.filter((t=>c.has(t.source)&&c.has(t.target)))};let v=1/0;p.forEach((t=>{var e;let{size:n}=t.data;n||(n=(null===(e=a.get(t.id))||void 0===e?void 0:e.data.size)||(null==s?void 0:s(t))||[30,30]),ae(n)&&(n=[n,n]);const[r,i]=n;v>r&&(v=r),v>i&&(v=i),t.data.size=n})),l=l.then((()=>ze(this,void 0,void 0,(function*(){const t=new ev(g);yield cE(h,t,d,!0);const{minX:e,minY:n,maxX:r,maxY:i}=(t=>{let e=1/0,n=1/0,r=-1/0,i=-1/0;return t.forEach((t=>{let o=t.data.size;fb(o)?1===o.length&&(o=[o[0],o[0]]):ae(o)?o=[o,o]:(void 0===o||isNaN(o))&&(o=[30,30]);const a=[o[0]/2,o[1]/2],s=t.data.x-a[0],l=t.data.x+a[0],u=t.data.y-a[1],c=t.data.y+a[1];e>s&&(e=s),n>u&&(n=u),r{t.data.x-=s,t.data.y-=l}));const u=[Math.max(r-e,v)+2*f,Math.max(i-n,v)+2*f];a.get(o.id).data.size=u,a.get(o.id).data.nodes=p}))))}else a.set(o.id,{id:o.id,data:Object.assign(Object.assign({},o.data),{size:c})});return!0}),"BT",e),f.push(l)})),f}}function cE(t,e,n,r){var i;return ze(this,void 0,void 0,(function*(){return aE(t)?(t.execute(e,n),t.stop(),t.tick(null!==(i=n.iterations)&&void 0!==i?i:300)):r?yield t.assign(e,n):yield t.execute(e,n)}))}function hE(t,e){var n,r=1;function i(){var i,o,a=n.length,s=0,l=0;for(i=0;iu+p||oc+p||al.index){var g=u-s.x-s.vx,v=c-s.y-s.vy,m=g*g+v*v;mt.r&&(t.r=t[e].r)}function l(){if(e){var r,i,o=e.length;for(n=new Array(o),r=0;r[s(t,e,r),t])));for(a=0,i=new Array(u);a{}};function EE(){for(var t,e=0,n=arguments.length,r={};e=0&&(e=t.slice(n+1),t=t.slice(0,n)),t&&!r.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:e}}))),a=-1,s=o.length;if(!(arguments.length<2)){if(null!=e&&"function"!=typeof e)throw new Error("invalid callback: "+e);for(;++a0)for(var n,r,i=new Array(n),o=0;o=0&&e._call.call(void 0,t),e=e._next;--OE}()}finally{OE=0,function(){var t,e,n=SE,r=1/0;for(;n;)n._call?(r>n._time&&(r=n._time),t=n,n=n._next):(e=n._next,n._next=null,n=t?t._next=e:SE=e);NE=t,GE(r)}(),PE=0}}function zE(){var t=DE.now(),e=t-AE;e>1e3&&(RE-=e,AE=t)}function GE(t){OE||(TE&&(TE=clearTimeout(TE)),t-PE>24?(t<1/0&&(TE=setTimeout(FE,t-DE.now()-RE)),CE&&(CE=clearInterval(CE))):(CE||(AE=DE.now(),CE=setInterval(zE,1e3)),OE=1,LE(FE)))}jE.prototype=BE.prototype={constructor:jE,restart:function(t,e,n){if("function"!=typeof t)throw new TypeError("callback is not a function");n=(null==n?_E():+n)+(null==e?0:+e),this._next||NE===this||(NE?NE._next=this:SE=this,NE=this),this._call=t,this._time=n,GE()},stop:function(){this._call&&(this._call=null,this._time=1/0,GE())}};const VE=4294967296;function WE(t){return t.x}function HE(t){return t.y}var UE=Math.PI*(3-Math.sqrt(5));function $E(t){var e,n=1,r=.001,i=1-Math.pow(r,1/300),o=0,a=.6,s=new Map,l=BE(h),u=EE("tick","end"),c=function(){let t=1;return()=>(t=(1664525*t+1013904223)%VE)/VE}();function h(){d(),u.call("tick",e),n1?(null==n?s.delete(t):s.set(t,p(n)),e):s.get(t)},find:function(e,n,r){var i,o,a,s,l,u=0,c=t.length;for(null==r?r=1/0:r*=r,u=0;u1?(u.on(t,n),e):u.on(t)}}}function YE(){var t,e,n,r,i,o=dE(-30),a=1,s=1/0,l=.81;function u(n){var i,o=t.length,a=Bb(t,WE,HE).visitAfter(h);for(r=n,i=0;i=s)){(t.data!==e||t.next)&&(0===h&&(p+=(h=fE(n))*h),0===d&&(p+=(d=fE(n))*d),pt.id},manyBody:{},center:{x:0,y:0}},this.context={options:{},assign:!1,nodes:[],edges:[]},ke(this.options,t),this.options.forceSimulation&&(this.simulation=this.options.forceSimulation)}execute(t,e){return ze(this,void 0,void 0,(function*(){return this.genericLayout(!1,t,e)}))}assign(t,e){return ze(this,void 0,void 0,(function*(){yield this.genericLayout(!0,t,e)}))}stop(){this.simulation.stop()}tick(t){return this.simulation.tick(t),this.getResult()}restart(){this.simulation.restart()}setFixedPosition(t,e){const n=this.context.nodes.find((e=>e.id===t));n&&e.forEach(((t,e)=>{if("number"==typeof t||null===t){n[["fx","fy","fz"][e]]=t}}))}getOptions(t){var e,n;const r=ke({},this.options,t);return r.collide&&void 0===(null===(e=r.collide)||void 0===e?void 0:e.radius)&&(r.collide=r.collide||{},r.collide.radius=null!==(n=r.nodeSize)&&void 0!==n?n:10),void 0===r.iterations&&(r.link&&void 0===r.link.iterations&&(r.iterations=r.link.iterations),r.collide&&void 0===r.collide.iterations&&(r.iterations=r.collide.iterations)),this.context.options=r,r}genericLayout(t,e,n){var r;return ze(this,void 0,void 0,(function*(){const i=this.getOptions(n),o=e.getAllNodes().map((({id:t,data:e})=>Object.assign(Object.assign({id:t},e),Ae(e.data,this.config.inputNodeAttrs)))),a=e.getAllEdges().map((t=>Object.assign({},t)));Object.assign(this.context,{assign:t,nodes:o,edges:a,graph:e});const s=new Promise((t=>{this.resolver=t})),l=this.setSimulation(i);return l.nodes(o),null===(r=l.force("link"))||void 0===r||r.links(a),s}))}getResult(){const{assign:t,nodes:e,edges:n,graph:r}=this.context,i=e.map((t=>({id:t.id,data:Object.assign(Object.assign({},t.data),Ae(t,this.config.outputNodeAttrs))}))),o=n.map((({id:t,source:e,target:n,data:r})=>({id:t,source:"object"==typeof e?e.id:e,target:"object"==typeof n?n.id:n,data:r})));return t&&i.forEach((t=>r.mergeNodeData(t.id,t.data))),{nodes:i,edges:o}}initSimulation(){return $E()}setSimulation(t){const e=this.simulation||this.options.forceSimulation||this.initSimulation();return this.simulation||(this.simulation=e.on("tick",(()=>{var e;return null===(e=t.onTick)||void 0===e?void 0:e.call(t,this.getResult())})).on("end",(()=>{var t;return null===(t=this.resolver)||void 0===t?void 0:t.call(this,this.getResult())}))),QE(e,this.config.simulationAttrs.map((e=>[e,t[e]]))),Object.entries(this.forceMap).forEach((([n,r])=>{const i=n;if(t[n]){let n=e.force(i);n||(n=r(),e.force(i,n)),QE(n,Object.entries(t[i]))}else e.force(i,null)})),e}}const QE=(t,e)=>e.reduce(((e,[n,r])=>e[n]&&void 0!==r?e[n].call(t,r):e),t);var JE,tw,ew,nw,rw,iw,ow,aw,sw,lw,uw,cw,hw,dw,fw,pw,gw,vw,mw,yw,bw,xw,Ew,ww,kw,Mw,Sw,Nw,Ow,Tw,Cw,Aw,Pw,Rw,Dw,Lw,_w,Iw,jw,Bw,Fw,zw,Gw,Vw,Ww,Hw,Uw,$w,Yw,qw,Xw,Kw,Zw,Qw,Jw,tk,ek,nk,rk,ik,ok,ak,sk,lk,uk,ck,hk,dk,fk,pk,gk,vk,mk,yk,bk,xk,Ek,wk,kk,Mk,Sk,Nk,Ok,Tk,Ck,Ak,Pk,Rk,Dk,Lk,_k,Ik,jk,Bk,Fk,zk,Gk,Vk,Wk,Hk,Uk,$k,Yk,qk,Xk,Kk,Zk,Qk;function Jk(){if(nw)return ew;return nw=1,ew=function(t,e){return t===e||t!=t&&e!=e}}function tM(){if(iw)return rw;iw=1;var t=Jk();return rw=function(e,n){for(var r=e.length;r--;)if(t(e[r][0],n))return r;return-1},rw}function eM(){if(pw)return fw;pw=1;var t=tw?JE:(tw=1,JE=function(){this.__data__=[],this.size=0}),e=function(){if(aw)return ow;aw=1;var t=tM(),e=Array.prototype.splice;return ow=function(n){var r=this.__data__,i=t(r,n);return!(i<0||(i==r.length-1?r.pop():e.call(r,i,1),--this.size,0))},ow}(),n=function(){if(lw)return sw;lw=1;var t=tM();return sw=function(e){var n=this.__data__,r=t(n,e);return r<0?void 0:n[r][1]},sw}(),r=function(){if(cw)return uw;cw=1;var t=tM();return uw=function(e){return t(this.__data__,e)>-1}}(),i=function(){if(dw)return hw;dw=1;var t=tM();return hw=function(e,n){var r=this.__data__,i=t(r,e);return i<0?(++this.size,r.push([e,n])):r[i][1]=n,this},hw}();function o(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e-1&&e%1==0&&e-1&&t%1==0&&t<=9007199254740991}}function zM(){if(_M)return LM;return _M=1,LM=function(t){return function(e){return t(e)}}}var GM,VM,WM,HM,UM,$M,YM,qM,XM,KM,ZM,QM,JM,tS,eS,nS,rS,iS,oS,aS,sS,lS,uS,cS,hS,dS,fS,pS={exports:{}};function gS(){return GM||(GM=1,function(t,e){var n=nM(),r=e&&!e.nodeType&&e,i=r&&t&&!t.nodeType&&t,o=i&&i.exports===r&&n.process,a=function(){try{var t=i&&i.require&&i.require("util").types;return t||o&&o.binding&&o.binding("util")}catch(t){}}();t.exports=a}(pS,pS.exports)),pS.exports}function vS(){if(WM)return VM;WM=1;var t=function(){if(DM)return RM;DM=1;var t=oM(),e=FM(),n=wM(),r={};return r["[object Float32Array]"]=r["[object Float64Array]"]=r["[object Int8Array]"]=r["[object Int16Array]"]=r["[object Int32Array]"]=r["[object Uint8Array]"]=r["[object Uint8ClampedArray]"]=r["[object Uint16Array]"]=r["[object Uint32Array]"]=!0,r["[object Arguments]"]=r["[object Array]"]=r["[object ArrayBuffer]"]=r["[object Boolean]"]=r["[object DataView]"]=r["[object Date]"]=r["[object Error]"]=r["[object Function]"]=r["[object Map]"]=r["[object Number]"]=r["[object Object]"]=r["[object RegExp]"]=r["[object Set]"]=r["[object String]"]=r["[object WeakMap]"]=!1,RM=function(i){return n(i)&&e(i.length)&&!!r[t(i)]}}(),e=zM(),n=gS(),r=n&&n.isTypedArray,i=r?e(r):t;return VM=i}function mS(){if(UM)return HM;UM=1;var t=(Hk||(Hk=1,Wk=function(t,e){for(var n=-1,r=Array(t);++nc))return!1;var d=l.get(r),f=l.get(i);if(d&&f)return d==i&&f==r;var p=-1,g=!0,v=2&o?new t:void 0;for(l.set(r,i),l.set(i,r);++p0&&o(c)?i>1?n(c,i-1,o,a,s):t(s,c):a||(s[s.length]=c)}return s},lC}function YP(){if(fC)return dC;fC=1;var t=hC?cC:(hC=1,cC=function(t,e,n){switch(n.length){case 0:return t.call(e);case 1:return t.call(e,n[0]);case 2:return t.call(e,n[0],n[1]);case 3:return t.call(e,n[0],n[1],n[2])}return t.apply(e,n)}),e=Math.max;return dC=function(n,r,i){return r=e(void 0===r?n.length-1:r,0),function(){for(var o=arguments,a=-1,s=e(o.length-r,0),l=Array(s);++a0){if(++n>=800)return arguments[0]}else n=0;return e.apply(void 0,arguments)}},vC}(),n=e(t);return yC=n}function XP(){if(EC)return xC;EC=1;var t=lP(),e=YP(),n=qP();return xC=function(r,i){return n(e(r,i,t),r+"")}}function KP(){if(kC)return wC;return kC=1,wC=function(t,e,n,r){for(var i=t.length,o=n+(r?1:-1);r?o--:++o-1}}(),n=(DC||(DC=1,RC=function(t,e,n){for(var r=-1,i=null==t?0:t.length;++r=200){var g=s?null:i(a);if(g)return o(g);d=!1,c=r,p=new t}else p=s?[]:f;t:for(;++ua){var s=o;o=a,a=s}return o+""+a+""+(t.isUndefined(i)?"\0":i)}function a(t,e){return o(t,e.v,e.w,e.name)}return n.prototype._nodeCount=0,n.prototype._edgeCount=0,n.prototype.isDirected=function(){return this._isDirected},n.prototype.isMultigraph=function(){return this._isMultigraph},n.prototype.isCompound=function(){return this._isCompound},n.prototype.setGraph=function(t){return this._label=t,this},n.prototype.graph=function(){return this._label},n.prototype.setDefaultNodeLabel=function(e){return t.isFunction(e)||(e=t.constant(e)),this._defaultNodeLabelFn=e,this},n.prototype.nodeCount=function(){return this._nodeCount},n.prototype.nodes=function(){return t.keys(this._nodes)},n.prototype.sources=function(){var e=this;return t.filter(this.nodes(),(function(n){return t.isEmpty(e._in[n])}))},n.prototype.sinks=function(){var e=this;return t.filter(this.nodes(),(function(n){return t.isEmpty(e._out[n])}))},n.prototype.setNodes=function(e,n){var r=arguments,i=this;return t.each(e,(function(t){r.length>1?i.setNode(t,n):i.setNode(t)})),this},n.prototype.setNode=function(n,r){return t.has(this._nodes,n)?(arguments.length>1&&(this._nodes[n]=r),this):(this._nodes[n]=arguments.length>1?r:this._defaultNodeLabelFn(n),this._isCompound&&(this._parent[n]=e,this._children[n]={},this._children[e][n]=!0),this._in[n]={},this._preds[n]={},this._out[n]={},this._sucs[n]={},++this._nodeCount,this)},n.prototype.node=function(t){return this._nodes[t]},n.prototype.hasNode=function(e){return t.has(this._nodes,e)},n.prototype.removeNode=function(e){var n=this;if(t.has(this._nodes,e)){var r=function(t){n.removeEdge(n._edgeObjs[t])};delete this._nodes[e],this._isCompound&&(this._removeFromParentsChildList(e),delete this._parent[e],t.each(this.children(e),(function(t){n.setParent(t)})),delete this._children[e]),t.each(t.keys(this._in[e]),r),delete this._in[e],delete this._preds[e],t.each(t.keys(this._out[e]),r),delete this._out[e],delete this._sucs[e],--this._nodeCount}return this},n.prototype.setParent=function(n,r){if(!this._isCompound)throw new Error("Cannot set parent in a non-compound graph");if(t.isUndefined(r))r=e;else{for(var i=r+="";!t.isUndefined(i);i=this.parent(i))if(i===n)throw new Error("Setting "+r+" as parent of "+n+" would create a cycle");this.setNode(r)}return this.setNode(n),this._removeFromParentsChildList(n),this._parent[n]=r,this._children[r][n]=!0,this},n.prototype._removeFromParentsChildList=function(t){delete this._children[this._parent[t]][t]},n.prototype.parent=function(t){if(this._isCompound){var n=this._parent[t];if(n!==e)return n}},n.prototype.children=function(n){if(t.isUndefined(n)&&(n=e),this._isCompound){var r=this._children[n];if(r)return t.keys(r)}else{if(n===e)return this.nodes();if(this.hasNode(n))return[]}},n.prototype.predecessors=function(e){var n=this._preds[e];if(n)return t.keys(n)},n.prototype.successors=function(e){var n=this._sucs[e];if(n)return t.keys(n)},n.prototype.neighbors=function(e){var n=this.predecessors(e);if(n)return t.union(n,this.successors(e))},n.prototype.isLeaf=function(t){return 0===(this.isDirected()?this.successors(t):this.neighbors(t)).length},n.prototype.filterNodes=function(e){var n=new this.constructor({directed:this._isDirected,multigraph:this._isMultigraph,compound:this._isCompound});n.setGraph(this.graph());var r=this;t.each(this._nodes,(function(t,r){e(r)&&n.setNode(r,t)})),t.each(this._edgeObjs,(function(t){n.hasNode(t.v)&&n.hasNode(t.w)&&n.setEdge(t,r.edge(t))}));var i={};function o(t){var e=r.parent(t);return void 0===e||n.hasNode(e)?(i[t]=e,e):e in i?i[e]:o(e)}return this._isCompound&&t.each(n.nodes(),(function(t){n.setParent(t,o(t))})),n},n.prototype.setDefaultEdgeLabel=function(e){return t.isFunction(e)||(e=t.constant(e)),this._defaultEdgeLabelFn=e,this},n.prototype.edgeCount=function(){return this._edgeCount},n.prototype.edges=function(){return t.values(this._edgeObjs)},n.prototype.setPath=function(e,n){var r=this,i=arguments;return t.reduce(e,(function(t,e){return i.length>1?r.setEdge(t,e,n):r.setEdge(t,e),e})),this},n.prototype.setEdge=function(){var e,n,i,a,s=!1,l=arguments[0];"object"==typeof l&&null!==l&&"v"in l?(e=l.v,n=l.w,i=l.name,2===arguments.length&&(a=arguments[1],s=!0)):(e=l,n=arguments[1],i=arguments[3],arguments.length>2&&(a=arguments[2],s=!0)),e=""+e,n=""+n,t.isUndefined(i)||(i=""+i);var u=o(this._isDirected,e,n,i);if(t.has(this._edgeLabels,u))return s&&(this._edgeLabels[u]=a),this;if(!t.isUndefined(i)&&!this._isMultigraph)throw new Error("Cannot set a named edge when isMultigraph = false");this.setNode(e),this.setNode(n),this._edgeLabels[u]=s?a:this._defaultEdgeLabelFn(e,n,i);var c=function(t,e,n,r){var i=""+e,o=""+n;if(!t&&i>o){var a=i;i=o,o=a}var s={v:i,w:o};r&&(s.name=r);return s}(this._isDirected,e,n,i);return e=c.v,n=c.w,Object.freeze(c),this._edgeObjs[u]=c,r(this._preds[n],e),r(this._sucs[e],n),this._in[n][u]=c,this._out[e][u]=c,this._edgeCount++,this},n.prototype.edge=function(t,e,n){var r=1===arguments.length?a(this._isDirected,arguments[0]):o(this._isDirected,t,e,n);return this._edgeLabels[r]},n.prototype.hasEdge=function(e,n,r){var i=1===arguments.length?a(this._isDirected,arguments[0]):o(this._isDirected,e,n,r);return t.has(this._edgeLabels,i)},n.prototype.removeEdge=function(t,e,n){var r=1===arguments.length?a(this._isDirected,arguments[0]):o(this._isDirected,t,e,n),s=this._edgeObjs[r];return s&&(t=s.v,e=s.w,delete this._edgeLabels[r],delete this._edgeObjs[r],i(this._preds[e],t),i(this._sucs[t],e),delete this._in[e][r],delete this._out[t][r],this._edgeCount--),this},n.prototype.inEdges=function(e,n){var r=this._in[e];if(r){var i=t.values(r);return n?t.filter(i,(function(t){return t.v===n})):i}},n.prototype.outEdges=function(e,n){var r=this._out[e];if(r){var i=t.values(r);return n?t.filter(i,(function(t){return t.w===n})):i}},n.prototype.nodeEdges=function(t,e){var n=this.inEdges(t,e);if(n)return n.concat(this.outEdges(t,e))},KC}function oR(){return eA?tA:(eA=1,tA={Graph:iR(),version:JC?QC:(JC=1,QC="2.1.8")})}function aR(){if(rA)return nA;rA=1;var t=rR(),e=iR();function n(e){return t.map(e.nodes(),(function(n){var r=e.node(n),i=e.parent(n),o={v:n};return t.isUndefined(r)||(o.value=r),t.isUndefined(i)||(o.parent=i),o}))}function r(e){return t.map(e.edges(),(function(n){var r=e.edge(n),i={v:n.v,w:n.w};return t.isUndefined(n.name)||(i.name=n.name),t.isUndefined(r)||(i.value=r),i}))}return nA={write:function(e){var i={options:{directed:e.isDirected(),multigraph:e.isMultigraph(),compound:e.isCompound()},nodes:n(e),edges:r(e)};t.isUndefined(e.graph())||(i.value=t.clone(e.graph()));return i},read:function(n){var r=new e(n.options).setGraph(n.value);return t.each(n.nodes,(function(t){r.setNode(t.v,t.value),t.parent&&r.setParent(t.v,t.parent)})),t.each(n.edges,(function(t){r.setEdge({v:t.v,w:t.w,name:t.name},t.value)})),r}}}function sR(){if(oA)return iA;oA=1;var t=rR();return iA=function(e){var n,r={},i=[];function o(i){t.has(r,i)||(r[i]=!0,n.push(i),t.each(e.successors(i),o),t.each(e.predecessors(i),o))}return t.each(e.nodes(),(function(t){n=[],o(t),n.length&&i.push(n)})),i},iA}function lR(){if(sA)return aA;sA=1;var t=rR();function e(){this._arr=[],this._keyIndices={}}return aA=e,e.prototype.size=function(){return this._arr.length},e.prototype.keys=function(){return this._arr.map((function(t){return t.key}))},e.prototype.has=function(e){return t.has(this._keyIndices,e)},e.prototype.priority=function(t){var e=this._keyIndices[t];if(void 0!==e)return this._arr[e].priority},e.prototype.min=function(){if(0===this.size())throw new Error("Queue underflow");return this._arr[0].key},e.prototype.add=function(e,n){var r=this._keyIndices;if(e=String(e),!t.has(r,e)){var i=this._arr,o=i.length;return r[e]=o,i.push({key:e,priority:n}),this._decrease(o),!0}return!1},e.prototype.removeMin=function(){this._swap(0,this._arr.length-1);var t=this._arr.pop();return delete this._keyIndices[t.key],this._heapify(0),t.key},e.prototype.decrease=function(t,e){var n=this._keyIndices[t];if(e>this._arr[n].priority)throw new Error("New priority is greater than current priority. Key: "+t+" Old: "+this._arr[n].priority+" New: "+e);this._arr[n].priority=e,this._decrease(n)},e.prototype._heapify=function(t){var e=this._arr,n=2*t,r=n+1,i=t;n>1].priority0&&(o=l.removeMin(),(a=s[o]).distance!==Number.POSITIVE_INFINITY);)i(o).forEach(u);return s}(t,String(r),i||n,o||function(e){return t.outEdges(e)})};var n=t.constant(1);return lA}function cR(){if(hA)return cA;hA=1;var t=uR(),e=rR();return cA=function(n,r,i){return e.transform(n.nodes(),(function(e,o){e[o]=t(n,o,r,i)}),{})}}function hR(){if(fA)return dA;fA=1;var t=rR();return dA=function(e){var n=0,r=[],i={},o=[];function a(s){var l=i[s]={onStack:!0,lowlink:n,index:n++};if(r.push(s),e.successors(s).forEach((function(e){t.has(i,e)?i[e].onStack&&(l.lowlink=Math.min(l.lowlink,i[e].index)):(a(e),l.lowlink=Math.min(l.lowlink,i[e].lowlink))})),l.lowlink===l.index){var u,c=[];do{u=r.pop(),i[u].onStack=!1,c.push(u)}while(s!==u);o.push(c)}}return e.nodes().forEach((function(e){t.has(i,e)||a(e)})),o},dA}function dR(){if(gA)return pA;gA=1;var t=rR(),e=hR();return pA=function(n){return t.filter(e(n),(function(t){return t.length>1||1===t.length&&n.hasEdge(t[0],t[0])}))}}function fR(){if(mA)return vA;mA=1;var t=rR();vA=function(t,n,r){return function(t,e,n){var r={},i=t.nodes();return i.forEach((function(t){r[t]={},r[t][t]={distance:0},i.forEach((function(e){t!==e&&(r[t][e]={distance:Number.POSITIVE_INFINITY})})),n(t).forEach((function(n){var i=n.v===t?n.w:n.v,o=e(n);r[t][i]={distance:o,predecessor:t}}))})),i.forEach((function(t){var e=r[t];i.forEach((function(n){var o=r[n];i.forEach((function(n){var r=o[t],i=e[n],a=o[n],s=r.distance+i.distance;s0;){if(o=l.removeMin(),t.has(s,o))a.setEdge(o,s[o]);else{if(c)throw new Error("Input graph is not connected: "+r);c=!0}r.nodeEdges(o).forEach(u)}return a}}try{LA=function(){if(DA)return RA;DA=1;var t=oR();return RA={Graph:t.Graph,json:aR(),alg:PA?AA:(PA=1,AA={components:sR(),dijkstra:uR(),dijkstraAll:cR(),findCycles:dR(),floydWarshall:fR(),isAcyclic:gR(),postorder:mR(),preorder:yR(),prim:bR(),tarjan:hR(),topsort:pR()}),version:t.version}}()}catch(t){}LA||(LA=window.graphlib);var xR,ER,wR,kR,MR,SR,NR,OR,TR,CR,AR,PR,RR,DR,LR,_R,IR,jR,BR,FR,zR,GR,VR,WR,HR,UR,$R,YR,qR,XR,KR,ZR,QR,JR,tD,eD,nD,rD,iD,oD,aD,sD,lD,uD,cD,hD,dD,fD,pD,gD,vD,mD,yD,bD,xD,ED,wD,kD,MD,SD,ND,OD,TD,CD,AD,PD,RD,DD,LD,_D,ID,jD,BD,FD,zD,GD,VD,WD,HD,UD,$D,YD,qD,XD,KD,ZD,QD,JD,tL,eL,nL,rL,iL,oL=LA;function aL(){if(kR)return wR;kR=1;var t=Jk(),e=ES(),n=BM(),r=aM();return wR=function(i,o,a){if(!r(a))return!1;var s=typeof o;return!!("number"==s?e(a)&&n(o,a.length):"string"==s&&o in a)&&t(a[o],i)},wR}function sL(){if(PR)return AR;PR=1;var t=function(){if(CR)return TR;CR=1;var t=/\s/;return TR=function(e){for(var n=e.length;n--&&t.test(e.charAt(n)););return n},TR}(),e=/^\s+/;return AR=function(n){return n?n.slice(0,t(n)+1).replace(e,""):n}}function lL(){if(_R)return LR;_R=1;var t=function(){if(DR)return RR;DR=1;var t=sL(),e=aM(),n=wP(),r=/^[-+]0x[0-9a-f]+$/i,i=/^0b[01]+$/i,o=/^0o[0-7]+$/i,a=parseInt;return RR=function(s){if("number"==typeof s)return s;if(n(s))return NaN;if(e(s)){var l="function"==typeof s.valueOf?s.valueOf():s;s=e(l)?l+"":l}if("string"!=typeof s)return 0===s?s:+s;s=t(s);var u=i.test(s);return u||o.test(s)?a(s.slice(2),u?2:8):r.test(s)?NaN:+s}}(),e=1/0;return LR=function(n){return n?(n=t(n))===e||n===-1/0?17976931348623157e292*(n<0?-1:1):n==n?n:0:0===n?n:0}}function uL(){if(FR)return BR;FR=1;var t=KP(),e=_P(),n=function(){if(jR)return IR;jR=1;var t=lL();return IR=function(e){var n=t(e),r=n%1;return n==n?r?n-r:n:0}}(),r=Math.max;return BR=function(i,o,a){var s=null==i?0:i.length;if(!s)return-1;var l=null==a?0:n(a);return l<0&&(l=r(s+l,0)),t(i,e(o,3),l)},BR}function cL(){if(WR)return VR;WR=1;var t=$P();return VR=function(e){return(null==e?0:e.length)?t(e,1):[]}}function hL(){if(ZR)return KR;ZR=1;var t=wP();return KR=function(e,n,r){for(var i=-1,o=e.length;++in||a&&s&&u&&!l&&!c||i&&s&&u||!r&&u||!o)return 1;if(!i&&!a&&!c&&e=l?u:u*("desc"==r[i]?-1:1)}return e.index-n.index},$D}function bL(){if(XD)return qD;XD=1;var t=SP(),e=CP(),n=_P(),r=zP(),i=(WD||(WD=1,VD=function(t,e){var n=t.length;for(t.sort(e);n--;)t[n]=t[n].value;return t}),VD),o=zM(),a=yL(),s=lP(),l=MM();return qD=function(u,c,h){c=c.length?t(c,(function(t){return l(t)?function(n){return e(n,1===t.length?t[0]:t)}:t})):[s];var d=-1;c=t(c,o(n));var f=r(u,(function(e,n,r){return{criteria:t(c,(function(t){return t(e)})),index:++d,value:e}}));return i(f,(function(t,e){return a(t,e,h)}))},qD}try{iL={cloneDeep:function(){if(ER)return xR;ER=1;var t=nP();return xR=function(e){return t(e,5)}}(),constant:iP(),defaults:function(){if(SR)return MR;SR=1;var t=XP(),e=Jk(),n=aL(),r=MS(),i=Object.prototype,o=i.hasOwnProperty,a=t((function(t,a){t=Object(t);var s=-1,l=a.length,u=l>2?a[2]:void 0;for(u&&n(a[0],a[1],u)&&(l=1);++s-1?s[l?i[u]:u]:void 0}},NR}(),e=t(uL());return zR=e}(),flatten:cL(),forEach:cP(),forIn:function(){if(UR)return HR;UR=1;var t=oP(),e=uP(),n=MS();return HR=function(r,i){return null==r?r:t(r,e(i),n)}}(),has:jP(),isUndefined:FP(),last:(YR||(YR=1,$R=function(t){var e=null==t?0:t.length;return e?t[e-1]:void 0}),$R),map:GP(),mapValues:function(){if(XR)return qR;XR=1;var t=bM(),e=aP(),n=_P();return qR=function(r,i){var o={};return i=n(i,3),e(r,(function(e,n,r){t(o,n,i(e,n,r))})),o}}(),max:function(){if(eD)return tD;eD=1;var t=hL(),e=JR?QR:(JR=1,QR=function(t,e){return t>e}),n=lP();return tD=function(r){return r&&r.length?t(r,n,e):void 0}}(),merge:function(){if(mD)return vD;mD=1;var t=function(){if(fD)return dD;fD=1;var t=vM(),e=dL(),n=oP(),r=pL(),i=aM(),o=MS(),a=fL();return dD=function s(l,u,c,h,d){l!==u&&n(u,(function(n,o){if(d||(d=new t),i(n))r(l,u,o,c,s,h,d);else{var f=h?h(a(l,o),n,o+"",l,u,d):void 0;void 0===f&&(f=n),e(l,o,f)}}),o)},dD}(),e=function(){if(gD)return pD;gD=1;var t=XP(),e=aL();return pD=function(n){return t((function(t,r){var i=-1,o=r.length,a=o>1?r[o-1]:void 0,s=o>2?r[2]:void 0;for(a=n.length>3&&"function"==typeof a?(o--,a):void 0,s&&e(r[0],r[1],s)&&(a=o<3?void 0:a,o=1),t=Object(t);++i1&&r(n,i[0],i[1])?i=[]:o>2&&r(i[0],i[1],i[2])&&(i=[i[0]]),e(n,t(i,1),[])}));return KD=i}(),uniqueId:function(){if(JD)return QD;JD=1;var t=NP(),e=0;return QD=function(n){var r=++e;return t(n)+r},QD}(),values:nR(),zipObject:function(){if(rL)return nL;rL=1;var t=xM(),e=(eL||(eL=1,tL=function(t,e,n){for(var r=-1,i=t.length,o=e.length,a={};++r0;--s)if(r=e[s].dequeue()){i=i.concat(AL(t,e,n,r,!0));break}}return i}(n.graph,n.buckets,n.zeroIdx);return SL.flatten(SL.map(r,(function(e){return t.outEdges(e.v,e.w)})),!0)},CL=SL.constant(1);function AL(t,e,n,r,i){var o=i?[]:void 0;return SL.forEach(t.inEdges(r.v),(function(r){var a=t.edge(r),s=t.node(r.v);i&&o.push({v:r.v,w:r.w}),s.out-=a,PL(e,n,s)})),SL.forEach(t.outEdges(r.v),(function(r){var i=t.edge(r),o=r.w,a=t.node(o);a.in-=i,PL(e,n,a)})),t.removeNode(r.v),o}function PL(t,e,n){n.out?n.in?t[n.out-n.in+e].enqueue(n):t[t.length-1].enqueue(n):t[0].enqueue(n)}var RL=xL,DL=TL,LL={run:function(t){var e="greedy"===t.graph().acyclicer?DL(t,function(t){return function(e){return t.edge(e).weight}}(t)):function(t){var e=[],n={},r={};function i(o){RL.has(r,o)||(r[o]=!0,n[o]=!0,RL.forEach(t.outEdges(o),(function(t){RL.has(n,t.w)?e.push(t):i(t.w)})),delete n[o])}return RL.forEach(t.nodes(),i),e}(t);RL.forEach(e,(function(e){var n=t.edge(e);t.removeEdge(e),n.forwardName=e.name,n.reversed=!0,t.setEdge(e.w,e.v,n,RL.uniqueId("rev"))}))},undo:function(t){RL.forEach(t.edges(),(function(e){var n=t.edge(e);if(n.reversed){t.removeEdge(e);var r=n.forwardName;delete n.reversed,delete n.forwardName,t.setEdge(e.w,e.v,n,r)}}))}};var _L=xL,IL=oL.Graph,jL={addDummyNode:BL,simplify:function(t){var e=(new IL).setGraph(t.graph());return _L.forEach(t.nodes(),(function(n){e.setNode(n,t.node(n))})),_L.forEach(t.edges(),(function(n){var r=e.edge(n.v,n.w)||{weight:0,minlen:1},i=t.edge(n);e.setEdge(n.v,n.w,{weight:r.weight+i.weight,minlen:Math.max(r.minlen,i.minlen)})})),e},asNonCompoundGraph:function(t){var e=new IL({multigraph:t.isMultigraph()}).setGraph(t.graph());return _L.forEach(t.nodes(),(function(n){t.children(n).length||e.setNode(n,t.node(n))})),_L.forEach(t.edges(),(function(n){e.setEdge(n,t.edge(n))})),e},successorWeights:function(t){var e=_L.map(t.nodes(),(function(e){var n={};return _L.forEach(t.outEdges(e),(function(e){n[e.w]=(n[e.w]||0)+t.edge(e).weight})),n}));return _L.zipObject(t.nodes(),e)},predecessorWeights:function(t){var e=_L.map(t.nodes(),(function(e){var n={};return _L.forEach(t.inEdges(e),(function(e){n[e.v]=(n[e.v]||0)+t.edge(e).weight})),n}));return _L.zipObject(t.nodes(),e)},intersectRect:function(t,e){var n,r,i=t.x,o=t.y,a=e.x-i,s=e.y-o,l=t.width/2,u=t.height/2;if(!a&&!s)throw new Error("Not possible to find intersection inside of the rectangle");Math.abs(s)*l>Math.abs(a)*u?(s<0&&(u=-u),n=u*a/s,r=u):(a<0&&(l=-l),n=l,r=l*s/a);return{x:i+n,y:o+r}},buildLayerMatrix:function(t){var e=_L.map(_L.range(FL(t)+1),(function(){return[]}));return _L.forEach(t.nodes(),(function(n){var r=t.node(n),i=r.rank;_L.isUndefined(i)||(e[i][r.order]=n)})),e},normalizeRanks:function(t){var e=_L.min(_L.map(t.nodes(),(function(e){return t.node(e).rank})));_L.forEach(t.nodes(),(function(n){var r=t.node(n);_L.has(r,"rank")&&(r.rank-=e)}))},removeEmptyRanks:function(t){var e=_L.min(_L.map(t.nodes(),(function(e){return t.node(e).rank}))),n=[];_L.forEach(t.nodes(),(function(r){var i=t.node(r).rank-e;n[i]||(n[i]=[]),n[i].push(r)}));var r=0,i=t.graph().nodeRankFactor;_L.forEach(n,(function(e,n){_L.isUndefined(e)&&n%i!==0?--r:r&&_L.forEach(e,(function(e){t.node(e).rank+=r}))}))},addBorderNode:function(t,e,n,r){var i={width:0,height:0};arguments.length>=4&&(i.rank=n,i.order=r);return BL(t,"border",i,e)},maxRank:FL,partition:function(t,e){var n={lhs:[],rhs:[]};return _L.forEach(t,(function(t){e(t)?n.lhs.push(t):n.rhs.push(t)})),n},time:function(t,e){var n=_L.now();try{return e()}finally{console.log(t+" time: "+(_L.now()-n)+"ms")}},notime:function(t,e){return e()}};function BL(t,e,n,r){var i;do{i=_L.uniqueId(r)}while(t.hasNode(i));return n.dummy=e,t.setNode(i,n),i}function FL(t){return _L.max(_L.map(t.nodes(),(function(e){var n=t.node(e).rank;if(!_L.isUndefined(n))return n})))}var zL=xL,GL=jL,VL={run:function(t){t.graph().dummyChains=[],zL.forEach(t.edges(),(function(e){!function(t,e){var n,r,i,o=e.v,a=t.node(o).rank,s=e.w,l=t.node(s).rank,u=e.name,c=t.edge(e),h=c.labelRank;if(l===a+1)return;for(t.removeEdge(e),i=0,++a;aa.lim&&(s=a,l=!0);var u=QL.filter(e.edges(),(function(e){return l===p_(t,t.node(e.v),s)&&l!==p_(t,t.node(e.w),s)}));return QL.minBy(u,(function(t){return t_(e,t)}))}function f_(t,e,n,r){var i=n.v,o=n.w;t.removeEdge(i,o),t.setEdge(r.v,r.w,{}),u_(t),s_(t,e),function(t,e){var n=QL.find(t.nodes(),(function(t){return!e.node(t).parent})),r=n_(t,n);r=r.slice(1),QL.forEach(r,(function(n){var r=t.node(n).parent,i=e.edge(n,r),o=!1;i||(i=e.edge(r,n),o=!0),e.node(n).rank=e.node(r).rank+(o?i.minlen:-i.minlen)}))}(t,e)}function p_(t,e,n){return n.low<=e.lim&&e.lim<=n.lim}a_.initLowLimValues=u_,a_.initCutValues=s_,a_.calcCutValue=l_,a_.leaveEdge=h_,a_.enterEdge=d_,a_.exchangeEdges=f_;var g_=HL.longestPath,v_=qL,m_=o_,y_=function(t){switch(t.graph().ranker){case"network-simplex":default:x_(t);break;case"tight-tree":!function(t){g_(t),v_(t)}(t);break;case"longest-path":b_(t)}};var b_=g_;function x_(t){m_(t)}var E_=xL,w_=function(t){var e=function(t){var e={},n=0;function r(i){var o=n;E_.forEach(t.children(i),r),e[i]={low:o,lim:n++}}return E_.forEach(t.children(),r),e}(t);E_.forEach(t.graph().dummyChains,(function(n){for(var r=t.node(n),i=r.edgeObj,o=function(t,e,n,r){var i,o,a=[],s=[],l=Math.min(e[n].low,e[r].low),u=Math.max(e[n].lim,e[r].lim);i=n;do{i=t.parent(i),a.push(i)}while(i&&(e[i].low>l||u>e[i].lim));o=i,i=r;for(;(i=t.parent(i))!==o;)s.push(i);return{path:a.concat(s.reverse()),lca:o}}(t,e,i.v,i.w),a=o.path,s=o.lca,l=0,u=a[l],c=!0;n!==i.w;){if(r=t.node(n),c){for(;(u=a[l])!==s&&t.node(u).maxRank0;)e%2&&(n+=s[e+1]),s[e=e-1>>1]+=t.weight;l+=t.weight*n}))),l}var V_=xL;var W_=xL,H_=function(t,e){var n={};return W_.forEach(t,(function(t,e){var r=n[t.v]={indegree:0,in:[],out:[],vs:[t.v],i:e};W_.isUndefined(t.barycenter)||(r.barycenter=t.barycenter,r.weight=t.weight)})),W_.forEach(e.edges(),(function(t){var e=n[t.v],r=n[t.w];W_.isUndefined(e)||W_.isUndefined(r)||(r.indegree++,e.out.push(n[t.w]))})),function(t){var e=[];function n(t){return function(e){e.merged||(W_.isUndefined(e.barycenter)||W_.isUndefined(t.barycenter)||e.barycenter>=t.barycenter)&&function(t,e){var n=0,r=0;t.weight&&(n+=t.barycenter*t.weight,r+=t.weight);e.weight&&(n+=e.barycenter*e.weight,r+=e.weight);t.vs=e.vs.concat(t.vs),t.barycenter=n/r,t.weight=r,t.i=Math.min(e.i,t.i),e.merged=!0}(t,e)}}function r(e){return function(n){n.in.push(e),0===--n.indegree&&t.push(n)}}for(;t.length;){var i=t.pop();e.push(i),W_.forEach(i.in.reverse(),n(i)),W_.forEach(i.out,r(i))}return W_.map(W_.filter(e,(function(t){return!t.merged})),(function(t){return W_.pick(t,["vs","i","barycenter","weight"])}))}(W_.filter(n,(function(t){return!t.indegree})))};var U_=xL,$_=jL;function Y_(t,e,n){for(var r;e.length&&(r=U_.last(e)).i<=n;)e.pop(),t.push(r.vs),n++;return n}var q_=xL,X_=function(t,e){return V_.map(e,(function(e){var n=t.inEdges(e);if(n.length){var r=V_.reduce(n,(function(e,n){var r=t.edge(n),i=t.node(n.v);return{sum:e.sum+r.weight*i.order,weight:e.weight+r.weight}}),{sum:0,weight:0});return{v:e,barycenter:r.sum/r.weight,weight:r.weight}}return{v:e}}))},K_=H_,Z_=function(t,e){var n=$_.partition(t,(function(t){return U_.has(t,"barycenter")})),r=n.lhs,i=U_.sortBy(n.rhs,(function(t){return-t.i})),o=[],a=0,s=0,l=0;r.sort((u=!!e,function(t,e){return t.barycentere.barycenter?1:u?e.i-t.i:t.i-e.i})),l=Y_(o,i,l),U_.forEach(r,(function(t){l+=t.vs.length,o.push(t.vs),a+=t.barycenter*t.weight,s+=t.weight,l=Y_(o,i,l)}));var u;var c={vs:U_.flatten(o,!0)};s&&(c.barycenter=a/s,c.weight=s);return c},Q_=function t(e,n,r,i){var o=e.children(n),a=e.node(n),s=a?a.borderLeft:void 0,l=a?a.borderRight:void 0,u={};s&&(o=q_.filter(o,(function(t){return t!==s&&t!==l})));var c=X_(e,o);q_.forEach(c,(function(n){if(e.children(n.v).length){var o=t(e,n.v,r,i);u[n.v]=o,q_.has(o,"barycenter")&&(a=n,s=o,q_.isUndefined(a.barycenter)?(a.barycenter=s.barycenter,a.weight=s.weight):(a.barycenter=(a.barycenter*a.weight+s.barycenter*s.weight)/(a.weight+s.weight),a.weight+=s.weight))}var a,s}));var h=K_(c,r);!function(t,e){q_.forEach(t,(function(t){t.vs=q_.flatten(t.vs.map((function(t){return e[t]?e[t].vs:t})),!0)}))}(h,u);var d=Z_(h,i);if(s&&(d.vs=q_.flatten([s,d.vs,l],!0),e.predecessors(s).length)){var f=e.node(e.predecessors(s)[0]),p=e.node(e.predecessors(l)[0]);q_.has(d,"barycenter")||(d.barycenter=0,d.weight=0),d.barycenter=(d.barycenter*d.weight+f.order+p.order)/(d.weight+2),d.weight+=2}return d};var J_=xL,tI=oL.Graph,eI=function(t,e,n){var r=function(t){var e;for(;t.hasNode(e=J_.uniqueId("_root")););return e}(t),i=new tI({compound:!0}).setGraph({root:r}).setDefaultNodeLabel((function(e){return t.node(e)}));return J_.forEach(t.nodes(),(function(o){var a=t.node(o),s=t.parent(o);(a.rank===e||a.minRank<=e&&e<=a.maxRank)&&(i.setNode(o),i.setParent(o,s||r),J_.forEach(t[n](o),(function(e){var n=e.v===o?e.w:e.v,r=i.edge(n,o),a=J_.isUndefined(r)?0:r.weight;i.setEdge(n,o,{weight:t.edge(e).weight+a})})),J_.has(a,"minRank")&&i.setNode(o,{borderLeft:a.borderLeft[e],borderRight:a.borderRight[e]}))})),i};var nI=xL;var rI=xL,iI=B_,oI=z_,aI=Q_,sI=eI,lI=function(t,e,n){var r,i={};nI.forEach(n,(function(n){for(var o,a,s=t.parent(n);s;){if((o=t.parent(s))?(a=i[o],i[o]=s):(a=r,r=s),a&&a!==s)return void e.setEdge(a,s);s=o}}))},uI=oL.Graph,cI=jL,hI=function(t){var e=cI.maxRank(t),n=dI(t,rI.range(1,e+1),"inEdges"),r=dI(t,rI.range(e-1,-1,-1),"outEdges"),i=iI(t);pI(t,i);for(var o,a=Number.POSITIVE_INFINITY,s=0,l=0;l<4;++s,++l){fI(s%2?n:r,s%4>=2),i=cI.buildLayerMatrix(t);var u=oI(t,i);ua)&&bI(n,e,s)}))}))}function i(e,n){var i,o=-1,a=0;return gI.forEach(n,(function(s,l){if("border"===t.node(s).dummy){var u=t.predecessors(s);u.length&&(i=t.node(u[0]).order,r(n,a,l,o,i),a=l,o=i)}r(n,a,n.length,i,e.length)})),n}return gI.reduce(e,i),n}(t,n)),i={};gI.forEach(["u","d"],(function(o){e="u"===o?n:gI.values(n).reverse(),gI.forEach(["l","r"],(function(n){"r"===n&&(e=gI.map(e,(function(t){return gI.values(t).reverse()})));var a=("u"===o?t.predecessors:t.successors).bind(t),s=function(t,e,n,r){var i={},o={},a={};return gI.forEach(e,(function(t){gI.forEach(t,(function(t,e){i[t]=t,o[t]=t,a[t]=e}))})),gI.forEach(e,(function(t){var e=-1;gI.forEach(t,(function(t){var s=r(t);if(s.length){s=gI.sortBy(s,(function(t){return a[t]}));for(var l=(s.length-1)/2,u=Math.floor(l),c=Math.ceil(l);u<=c;++u){var h=s[u];o[t]===t&&en){var r=e;e=n,n=r}var i=t[e];i||(t[e]=i={}),i[n]=!0}function xI(t,e,n){if(e>n){var r=e;e=n,n=r}return gI.has(t[e],n)}var EI=xL,wI=jL,kI=yI,MI=function(t){(function(t){var e=wI.buildLayerMatrix(t),n=t.graph().ranksep,r=0;EI.forEach(e,(function(e){var i=EI.max(EI.map(e,(function(e){return t.node(e).height})));EI.forEach(e,(function(e){t.node(e).y=r+i/2})),r+=i+n}))})(t=wI.asNonCompoundGraph(t)),EI.forEach(kI(t),(function(e,n){t.node(n).x=e}))};var SI=xL,NI=LL,OI=VL,TI=y_,CI=jL.normalizeRanks,AI=w_,PI=jL.removeEmptyRanks,RI=S_,DI=C_,LI=R_,_I=hI,II=MI,jI=jL,BI=oL.Graph,FI=function(t,e){var n=e&&e.debugTiming?jI.time:jI.notime;n("layout",(function(){var e=n(" buildLayoutGraph",(function(){return function(t){var e=new BI({multigraph:!0,compound:!0}),n=XI(t.graph());return e.setGraph(SI.merge({},GI,qI(n,zI),SI.pick(n,VI))),SI.forEach(t.nodes(),(function(n){var r=XI(t.node(n));e.setNode(n,SI.defaults(qI(r,WI),HI)),e.setParent(n,t.parent(n))})),SI.forEach(t.edges(),(function(n){var r=XI(t.edge(n));e.setEdge(n,SI.merge({},$I,qI(r,UI),SI.pick(r,YI)))})),e}(t)}));n(" runLayout",(function(){!function(t,e){e(" makeSpaceForEdgeLabels",(function(){!function(t){var e=t.graph();e.ranksep/=2,SI.forEach(t.edges(),(function(n){var r=t.edge(n);r.minlen*=2,"c"!==r.labelpos.toLowerCase()&&("TB"===e.rankdir||"BT"===e.rankdir?r.width+=r.labeloffset:r.height+=r.labeloffset)}))}(t)})),e(" removeSelfEdges",(function(){!function(t){SI.forEach(t.edges(),(function(e){if(e.v===e.w){var n=t.node(e.v);n.selfEdges||(n.selfEdges=[]),n.selfEdges.push({e:e,label:t.edge(e)}),t.removeEdge(e)}}))}(t)})),e(" acyclic",(function(){NI.run(t)})),e(" nestingGraph.run",(function(){RI.run(t)})),e(" rank",(function(){TI(jI.asNonCompoundGraph(t))})),e(" injectEdgeLabelProxies",(function(){!function(t){SI.forEach(t.edges(),(function(e){var n=t.edge(e);if(n.width&&n.height){var r=t.node(e.v),i={rank:(t.node(e.w).rank-r.rank)/2+r.rank,e:e};jI.addDummyNode(t,"edge-proxy",i,"_ep")}}))}(t)})),e(" removeEmptyRanks",(function(){PI(t)})),e(" nestingGraph.cleanup",(function(){RI.cleanup(t)})),e(" normalizeRanks",(function(){CI(t)})),e(" assignRankMinMax",(function(){!function(t){var e=0;SI.forEach(t.nodes(),(function(n){var r=t.node(n);r.borderTop&&(r.minRank=t.node(r.borderTop).rank,r.maxRank=t.node(r.borderBottom).rank,e=SI.max(e,r.maxRank))})),t.graph().maxRank=e}(t)})),e(" removeEdgeLabelProxies",(function(){!function(t){SI.forEach(t.nodes(),(function(e){var n=t.node(e);"edge-proxy"===n.dummy&&(t.edge(n.e).labelRank=n.rank,t.removeNode(e))}))}(t)})),e(" normalize.run",(function(){OI.run(t)})),e(" parentDummyChains",(function(){AI(t)})),e(" addBorderSegments",(function(){DI(t)})),e(" order",(function(){_I(t)})),e(" insertSelfEdges",(function(){!function(t){var e=jI.buildLayerMatrix(t);SI.forEach(e,(function(e){var n=0;SI.forEach(e,(function(e,r){var i=t.node(e);i.order=r+n,SI.forEach(i.selfEdges,(function(e){jI.addDummyNode(t,"selfedge",{width:e.label.width,height:e.label.height,rank:i.rank,order:r+ ++n,e:e.e,label:e.label},"_se")})),delete i.selfEdges}))}))}(t)})),e(" adjustCoordinateSystem",(function(){LI.adjust(t)})),e(" position",(function(){II(t)})),e(" positionSelfEdges",(function(){!function(t){SI.forEach(t.nodes(),(function(e){var n=t.node(e);if("selfedge"===n.dummy){var r=t.node(n.e.v),i=r.x+r.width/2,o=r.y,a=n.x-i,s=r.height/2;t.setEdge(n.e,n.label),t.removeNode(e),n.label.points=[{x:i+2*a/3,y:o-s},{x:i+5*a/6,y:o-s},{x:i+a,y:o},{x:i+5*a/6,y:o+s},{x:i+2*a/3,y:o+s}],n.label.x=n.x,n.label.y=n.y}}))}(t)})),e(" removeBorderNodes",(function(){!function(t){SI.forEach(t.nodes(),(function(e){if(t.children(e).length){var n=t.node(e),r=t.node(n.borderTop),i=t.node(n.borderBottom),o=t.node(SI.last(n.borderLeft)),a=t.node(SI.last(n.borderRight));n.width=Math.abs(a.x-o.x),n.height=Math.abs(i.y-r.y),n.x=o.x+n.width/2,n.y=r.y+n.height/2}})),SI.forEach(t.nodes(),(function(e){"border"===t.node(e).dummy&&t.removeNode(e)}))}(t)})),e(" normalize.undo",(function(){OI.undo(t)})),e(" fixupEdgeLabelCoords",(function(){!function(t){SI.forEach(t.edges(),(function(e){var n=t.edge(e);if(SI.has(n,"x"))switch("l"!==n.labelpos&&"r"!==n.labelpos||(n.width-=n.labeloffset),n.labelpos){case"l":n.x-=n.width/2+n.labeloffset;break;case"r":n.x+=n.width/2+n.labeloffset}}))}(t)})),e(" undoCoordinateSystem",(function(){LI.undo(t)})),e(" translateGraph",(function(){!function(t){var e=Number.POSITIVE_INFINITY,n=0,r=Number.POSITIVE_INFINITY,i=0,o=t.graph(),a=o.marginx||0,s=o.marginy||0;function l(t){var o=t.x,a=t.y,s=t.width,l=t.height;e=Math.min(e,o-s/2),n=Math.max(n,o+s/2),r=Math.min(r,a-l/2),i=Math.max(i,a+l/2)}SI.forEach(t.nodes(),(function(e){l(t.node(e))})),SI.forEach(t.edges(),(function(e){var n=t.edge(e);SI.has(n,"x")&&l(n)})),e-=a,r-=s,SI.forEach(t.nodes(),(function(n){var i=t.node(n);i.x-=e,i.y-=r})),SI.forEach(t.edges(),(function(n){var i=t.edge(n);SI.forEach(i.points,(function(t){t.x-=e,t.y-=r})),SI.has(i,"x")&&(i.x-=e),SI.has(i,"y")&&(i.y-=r)})),o.width=n-e+a,o.height=i-r+s}(t)})),e(" assignNodeIntersects",(function(){!function(t){SI.forEach(t.edges(),(function(e){var n,r,i=t.edge(e),o=t.node(e.v),a=t.node(e.w);i.points?(n=i.points[0],r=i.points[i.points.length-1]):(i.points=[],n=a,r=o),i.points.unshift(jI.intersectRect(o,n)),i.points.push(jI.intersectRect(a,r))}))}(t)})),e(" reversePoints",(function(){!function(t){SI.forEach(t.edges(),(function(e){var n=t.edge(e);n.reversed&&n.points.reverse()}))}(t)})),e(" acyclic.undo",(function(){NI.undo(t)}))}(e,n)})),n(" updateInputGraph",(function(){!function(t,e){SI.forEach(t.nodes(),(function(n){var r=t.node(n),i=e.node(n);r&&(r.x=i.x,r.y=i.y,e.children(n).length&&(r.width=i.width,r.height=i.height))})),SI.forEach(t.edges(),(function(n){var r=t.edge(n),i=e.edge(n);r.points=i.points,SI.has(i,"x")&&(r.x=i.x,r.y=i.y)})),t.graph().width=e.graph().width,t.graph().height=e.graph().height}(t,e)}))}))};var zI=["nodesep","edgesep","ranksep","marginx","marginy"],GI={ranksep:50,edgesep:20,nodesep:50,rankdir:"tb"},VI=["acyclicer","ranker","rankdir","align"],WI=["width","height"],HI={width:0,height:0},UI=["minlen","weight","width","height","labeloffset"],$I={minlen:1,weight:1,width:0,height:0,labeloffset:10,labelpos:"r"},YI=["labelpos"];function qI(t,e){return SI.mapValues(SI.pick(t,e),Number)}function XI(t){var e={};return SI.forEach(t,(function(t,n){e[n.toLowerCase()]=t})),e}var KI=xL,ZI=jL,QI=oL.Graph,JI={debugOrdering:function(t){var e=ZI.buildLayerMatrix(t),n=new QI({compound:!0,multigraph:!0}).setGraph({});return KI.forEach(t.nodes(),(function(e){n.setNode(e,{label:e}),n.setParent(e,"layer"+t.node(e).rank)})),KI.forEach(t.edges(),(function(t){n.setEdge(t.v,t.w,{},t.name)})),KI.forEach(e,(function(t,e){var r="layer"+e;n.setNode(r,{rank:"same"}),KI.reduce(t,(function(t,e){return n.setEdge(t,e,{style:"invis"}),e}))})),n}};var tj={graphlib:oL,layout:FI,debug:JI,util:{time:jL.time,notime:jL.notime},version:"0.8.5"},ej=E(tj);class nj{constructor(t){this.id="dagre",this.options={},Object.assign(this.options,nj.defaultOptions,t)}execute(t,e){return ze(this,void 0,void 0,(function*(){return this.genericDagreLayout(!1,t,Object.assign(Object.assign({},this.options),e))}))}assign(t,e){return ze(this,void 0,void 0,(function*(){yield this.genericDagreLayout(!0,t,Object.assign(Object.assign({},this.options),e))}))}genericDagreLayout(t,e,n){return ze(this,void 0,void 0,(function*(){const{nodeSize:r}=n,i=new tj.graphlib.Graph;i.setGraph(n),i.setDefaultEdgeLabel((()=>({})));[...e.getAllNodes(),...e.getAllEdges()].some((({id:t})=>ae(t)))&&console.error("Dagre layout only support string id, it will convert number to string."),e.getAllNodes().forEach((t=>{const{id:e}=t,n=Object.assign({},t.data);if(void 0!==r){const[e,i]=xb(Ut(r)?r(t):r);Object.assign(n,{width:e,height:i})}i.setNode(e.toString(),n)})),e.getAllEdges().forEach((({id:t,source:e,target:n})=>{i.setEdge(e.toString(),n.toString(),{id:t})})),ej.layout(i);const o={nodes:[],edges:[]};return i.nodes().forEach((n=>{const r=i.node(n);o.nodes.push({id:n,data:r}),t&&e.mergeNodeData(n,r)})),i.edges().forEach((n=>{const r=i.edge(n),{id:a}=r,s=Fe(r,["id"]),{v:l,w:u}=n;o.edges.push({id:a,source:l,target:u,data:s}),t&&e.mergeEdgeData(a,s)})),o}))}}nj.defaultOptions={};class rj{constructor(t){this.id=t.id||0,this.rx=t.rx,this.ry=t.ry,this.fx=0,this.fy=0,this.mass=t.mass,this.degree=t.degree,this.g=t.g||0}distanceTo(t){const e=this.rx-t.rx,n=this.ry-t.ry;return Math.hypot(e,n)}setPos(t,e){this.rx=t,this.ry=e}resetForce(){this.fx=0,this.fy=0}addForce(t){const e=t.rx-this.rx,n=t.ry-this.ry;let r=Math.hypot(e,n);r=r<1e-4?1e-4:r;const i=this.g*(this.degree+1)*(t.degree+1)/r;this.fx+=i*e/r,this.fy+=i*n/r}in(t){return t.contains(this.rx,this.ry)}add(t){const e=this.mass+t.mass,n=(this.rx*this.mass+t.rx*t.mass)/e,r=(this.ry*this.mass+t.ry*t.mass)/e,i=this.degree+t.degree;return new rj({rx:n,ry:r,mass:e,degree:i})}}class ij{constructor(t){this.xmid=t.xmid,this.ymid=t.ymid,this.length=t.length,this.massCenter=t.massCenter||[0,0],this.mass=t.mass||1}getLength(){return this.length}contains(t,e){const n=this.length/2;return t<=this.xmid+n&&t>=this.xmid-n&&e<=this.ymid+n&&e>=this.ymid-n}NW(){const t=this.xmid-this.length/4,e=this.ymid+this.length/4,n=this.length/2;return new ij({xmid:t,ymid:e,length:n})}NE(){const t=this.xmid+this.length/4,e=this.ymid+this.length/4,n=this.length/2;return new ij({xmid:t,ymid:e,length:n})}SW(){const t=this.xmid-this.length/4,e=this.ymid-this.length/4,n=this.length/2;return new ij({xmid:t,ymid:e,length:n})}SE(){const t=this.xmid+this.length/4,e=this.ymid-this.length/4,n=this.length/2;return new ij({xmid:t,ymid:e,length:n})}}class oj{constructor(t){this.body=null,this.quad=null,this.NW=null,this.NE=null,this.SW=null,this.SE=null,this.theta=.5,null!=t&&(this.quad=t)}insert(t){null!=this.body?this._isExternal()?(this.quad&&(this.NW=new oj(this.quad.NW()),this.NE=new oj(this.quad.NE()),this.SW=new oj(this.quad.SW()),this.SE=new oj(this.quad.SE())),this._putBody(this.body),this._putBody(t),this.body=this.body.add(t)):(this.body=this.body.add(t),this._putBody(t)):this.body=t}_putBody(t){this.quad&&(t.in(this.quad.NW())&&this.NW?this.NW.insert(t):t.in(this.quad.NE())&&this.NE?this.NE.insert(t):t.in(this.quad.SW())&&this.SW?this.SW.insert(t):t.in(this.quad.SE())&&this.SE&&this.SE.insert(t))}_isExternal(){return null==this.NW&&null==this.NE&&null==this.SW&&null==this.SE}updateForce(t){if(null!=this.body&&t!==this.body)if(this._isExternal())t.addForce(this.body);else{(this.quad?this.quad.getLength():0)/this.body.distanceTo(t)bb(t,[a,s]))),f=r.filter((t=>{const{source:e,target:n}=t;return e!==n})),p=new ev({nodes:d,edges:f}),g=this.getSizes(p,c);if(this.run(p,e,u,g,t,o),l){for(let t=0;t250&&(n.barnesHut=!0),void 0===s&&e>100&&(n.prune=!0),0!==l||s?0===l&&s&&(n.maxIteration=100,e<=200&&e>100?n.maxIteration=500:e>200&&(n.maxIteration=950)):(n.maxIteration=250,e<=200&&e>100?n.maxIteration=1e3:e>200&&(n.maxIteration=1200)),u||(n.kr=50,e>100&&e<=500?n.kr=20:e>500&&(n.kr=1)),c||(n.kg=20,e>100&&e<=500?n.kg=10:e>500&&(n.kg=1)),n}run(t,e,n,r,i,o){const{kr:a,barnesHut:s,onTick:l}=o,u=t.getAllNodes();let c=0,h=n;const d={},f={},p={};for(let e=0;e0;)c=this.oneStep(t,{iter:h,preventOverlapIters:50,krPrime:100,sg:c,forces:d,preForces:f,bodies:p,sizes:r},o),h--,null==l||l({nodes:u,edges:e.getAllEdges()});return t}oneStep(t,e,n){const{iter:r,preventOverlapIters:i,krPrime:o,sg:a,preForces:s,bodies:l,sizes:u}=e;let{forces:c}=e;const{preventOverlap:h,barnesHut:d}=n,f=t.getAllNodes();for(let t=0;ti||!h)?this.getOptRepGraForces(t,c,l,n):this.getRepGraForces(t,r,i,c,o,u,n),this.updatePos(t,c,s,a,n)}getAttrForces(t,e,n,r,i,o){const{preventOverlap:a,dissuadeHubs:s,mode:l,prune:u}=o,c=t.getAllEdges();for(let o=0;o0&&(b=y,x=y),i[h][0]+=b*m[0],i[d][0]-=x*m[0],i[h][1]+=b*m[1],i[d][1]-=x*m[1]}return i}getOptRepGraForces(t,e,n,r){const{kg:i,center:o,prune:a}=r,s=t.getAllNodes(),l=s.length;let u=9e10,c=-9e10,h=9e10,d=-9e10;for(let e=0;e=c&&(c=i.x),i.x<=u&&(u=i.x),i.y>=d&&(d=i.y),i.y<=h&&(h=i.y))}const f=Math.max(c-u,d-h),p=new ij({xmid:(c+u)/2,ymid:(d+h)/2,length:f,massCenter:o,mass:l}),g=new oj(p);for(let e=0;e0&&(m=l*(g+1)*(c+1)/v),r[p.id][0]-=m*f[0],r[a.id][0]+=m*f[0],r[p.id][1]-=m*f[1],r[a.id][1]+=m*f[1]}const v=[p.data.x-c[0],p.data.y-c[1]],m=Math.hypot(v[0],v[1]);v[0]=v[0]/m,v[1]=v[1]/m;const y=u*(g+1);r[p.id][0]-=y*v[0],r[p.id][1]-=y*v[1]}return r}updatePos(t,e,n,r,i){const{ks:o,tao:a,prune:s,ksmax:l}=i,u=t.getAllNodes(),c=u.length,h=[],d=[];let f=0,p=0,g=r;for(let r=0;r1.5*v?1.5*v:g);for(let n=0;nf?f:c;const p=c*e[r][0],v=c*e[r][1];t.mergeNodeData(r,{x:i.x+p,y:i.y+v})}return g}}const lj={maxIteration:1e3,gravity:10,speed:5,clustering:!1,clusterGravity:10,width:300,height:300,nodeClusterBy:"cluster"};class uj{constructor(t={}){this.options=t,this.id="fruchterman",this.timeInterval=0,this.running=!1,this.options=Object.assign(Object.assign({},lj),t)}execute(t,e){return ze(this,void 0,void 0,(function*(){return this.genericFruchtermanLayout(!1,t,e)}))}assign(t,e){return ze(this,void 0,void 0,(function*(){yield this.genericFruchtermanLayout(!0,t,e)}))}stop(){this.timeInterval&&"undefined"!=typeof window&&window.clearInterval(this.timeInterval),this.running=!1}tick(t=this.options.maxIteration||1){if(this.lastResult)return this.lastResult;for(let e=0;ethis.lastGraph.mergeNodeData(t.id,{x:t.data.x,y:t.data.y,z:3===this.options.dimensions?t.data.z:void 0}))),e}genericFruchtermanLayout(t,e,n){return ze(this,void 0,void 0,(function*(){if(this.running)return;const r=this.formatOptions(n),{dimensions:i,width:o,height:a,center:s,clustering:l,nodeClusterBy:u,maxIteration:c,onTick:h}=r,d=e.getAllNodes(),f=e.getAllEdges();if(!(null==d?void 0:d.length)){const t={nodes:[],edges:f};return this.lastResult=t,t}if(1===d.length){t&&e.mergeNodeData(d[0].id,{x:s[0],y:s[1],z:3===i?s[2]:void 0});const n={nodes:[Object.assign(Object.assign({},d[0]),{data:Object.assign(Object.assign({},d[0].data),{x:s[0],y:s[1],z:3===i?s[2]:void 0})})],edges:f};return this.lastResult=n,n}const p=d.map((t=>bb(t,[o,a]))),g=new ev({nodes:p,edges:f}),v={};if(l&&p.forEach((t=>{const e=t.data[u];v[e]||(v[e]={name:e,cx:0,cy:0,count:0})})),this.lastLayoutNodes=p,this.lastLayoutEdges=f,this.lastAssign=t,this.lastGraph=g,this.lastOptions=r,this.lastClusterMap=v,"undefined"==typeof window)return;let m=0;return new Promise((n=>{this.timeInterval=window.setInterval((()=>{this.running?(this.runOneStep(g,v,r),t&&p.forEach((({id:t,data:n})=>e.mergeNodeData(t,{x:n.x,y:n.y,z:3===i?n.z:void 0}))),null==h||h({nodes:p,edges:f}),m++,m>=c&&(window.clearInterval(this.timeInterval),n({nodes:p,edges:f}))):n({nodes:p,edges:f})}),0),this.running=!0}))}))}formatOptions(t={}){const e=Object.assign(Object.assign({},this.options),t),{clustering:n,nodeClusterBy:r}=e,{center:i,width:o,height:a}=e;return e.width=o||"undefined"==typeof window?o:window.innerWidth,e.height=a||"undefined"==typeof window?a:window.innerHeight,e.center=i||[e.width/2,e.height/2],e.clustering=n&&!!r,e}runOneStep(t,e,n){const{dimensions:r,height:i,width:o,gravity:a,center:s,speed:l,clustering:u,nodeClusterBy:c,clusterGravity:h}=n,d=i*o,f=Math.sqrt(d)/10,p=t.getAllNodes(),g=d/(p.length+1),v=Math.sqrt(g),m={};if(this.applyCalculate(t,m,v,g),u){for(const t in e)e[t].cx=0,e[t].cy=0,e[t].count=0;p.forEach((t=>{const{data:n}=t,r=e[n[c]];ae(n.x)&&(r.cx+=n.x),ae(n.y)&&(r.cy+=n.y),r.count++}));for(const t in e)e[t].cx/=e[t].count,e[t].cy/=e[t].count;const t=h||a;p.forEach(((n,r)=>{const{id:i,data:o}=n;if(!ae(o.x)||!ae(o.y))return;const a=e[o[c]],s=Math.sqrt((o.x-a.cx)*(o.x-a.cx)+(o.y-a.cy)*(o.y-a.cy)),l=v*t;m[i].x-=l*(o.x-a.cx)/s,m[i].y-=l*(o.y-a.cy)/s}))}p.forEach(((t,e)=>{const{id:n,data:i}=t;if(!ae(i.x)||!ae(i.y))return;const o=.01*v*a;m[n].x-=o*(i.x-s[0]),m[n].y-=o*(i.y-s[1]),3===r&&(m[n].z-=o*(i.z-s[2]))})),p.forEach(((e,n)=>{const{id:i,data:o}=e;if(ae(o.fx)&&ae(o.fy))return o.x=o.fx,o.y=o.fy,void(3===r&&(o.z=o.fz));if(!ae(o.x)||!ae(o.y))return;const a=Math.sqrt(m[i].x*m[i].x+m[i].y*m[i].y+(3===r?m[i].z*m[i].z:0));if(a>0){const e=Math.min(f*(l/800),a);t.mergeNodeData(i,{x:o.x+m[i].x/a*e,y:o.y+m[i].y/a*e,z:3===r?o.z+m[i].z/a*e:void 0})}}))}applyCalculate(t,e,n,r){this.calRepulsive(t,e,r),this.calAttractive(t,e,n)}calRepulsive(t,e,n){const r=t.getAllNodes();r.forEach((({data:t,id:i},o)=>{e[i]={x:0,y:0,z:0},r.forEach((({data:r,id:a},s)=>{if(o<=s||!ae(t.x)||!ae(r.x)||!ae(t.y)||!ae(r.y))return;let l=t.x-r.x,u=t.y-r.y,c=3===this.options.dimensions?t.z-r.z:0,h=l*l+u*u+c*c;0===h&&(h=1,l=.01,u=.01,c=.01);const d=n/h,f=l*d,p=u*d,g=c*d;e[i].x+=f,e[i].y+=p,e[a].x-=f,e[a].y-=p,3===this.options.dimensions&&(e[i].z+=g,e[a].z-=g)}))}))}calAttractive(t,e,n){t.getAllEdges().forEach((r=>{const{source:i,target:o}=r;if(!i||!o||i===o)return;const{data:a}=t.getNode(i),{data:s}=t.getNode(o);if(!(ae(s.x)&&ae(a.x)&&ae(s.y)&&ae(a.y)))return;const l=s.x-a.x,u=s.y-a.y,c=3===this.options.dimensions?s.z-a.z:0,h=Math.sqrt(l*l+u*u+c*c)/n,d=l*h,f=u*h,p=c*h;e[i].x+=d,e[i].y+=f,e[o].x-=d,e[o].y-=f,3===this.options.dimensions&&(e[i].z+=p,e[o].z-=p)}))}}const cj={begin:[0,0],preventOverlap:!0,preventOverlapPadding:10,condense:!1,rows:void 0,cols:void 0,position:void 0,sortBy:"degree",nodeSize:30,width:300,height:300};class hj{constructor(t={}){this.options=t,this.id="grid",this.options=Object.assign(Object.assign({},cj),t)}execute(t,e){return ze(this,void 0,void 0,(function*(){return this.genericGridLayout(!1,t,e)}))}assign(t,e){return ze(this,void 0,void 0,(function*(){yield this.genericGridLayout(!0,t,e)}))}genericGridLayout(t,e,n){return ze(this,void 0,void 0,(function*(){const r=Object.assign(Object.assign({},this.options),n),{begin:i=[0,0],condense:o,preventOverlapPadding:a,preventOverlap:s,rows:l,cols:u,nodeSpacing:c,nodeSize:h,width:d,height:f,position:p}=r;let{sortBy:g}=r;const v=e.getAllNodes(),m=e.getAllEdges(),y=null==v?void 0:v.length;if(!y||1===y)return Ob(e,t,i);const b=v.map((t=>bb(t)));"id"===g||ne(g)&&void 0!==b[0].data[g]||(g="degree"),"degree"===g?b.sort(((t,n)=>e.getDegree(n.id,"both")-e.getDegree(t.id,"both"))):"id"===g?b.sort(((t,e)=>ae(e.id)&&ae(t.id)?e.id-t.id:`${t.id}`.localeCompare(`${e.id}`))):b.sort(((t,e)=>e.data[g]-t.data[g]));const x=d||"undefined"==typeof window?d:window.innerWidth,E=f||"undefined"==typeof window?f:window.innerHeight,w=y,k={rows:l,cols:u};if(null!=l&&null!=u)k.rows=l,k.cols=u;else if(null!=l&&null==u)k.rows=l,k.cols=Math.ceil(w/k.rows);else if(null==l&&null!=u)k.cols=u,k.rows=Math.ceil(w/k.cols);else{const t=Math.sqrt(w*E/x);k.rows=Math.round(t),k.cols=Math.round(x/E*t)}if(k.rows=Math.max(k.rows,1),k.cols=Math.max(k.cols,1),k.cols*k.rows>w){const t=dj(k),e=fj(k);(t-1)*e>=w?dj(k,t-1):(e-1)*t>=w&&fj(k,e-1)}else for(;k.cols*k.rows=w?fj(k,e+1):dj(k,t+1)}let M=o?0:x/k.cols,S=o?0:E/k.rows;if(s||c){const t=Eb(10,c),n=wb(30,h,!1);b.forEach((r=>{r.data.x&&r.data.y||(r.data.x=0,r.data.y=0);const i=e.getNode(r.id),[o,s]=xb(n(i)||30),l=void 0!==t?t(r):a,u=o+l,c=s+l;M=Math.max(M,u),S=Math.max(S,c)}))}const N={},O={row:0,col:0},T={};for(let t=0;t{e.mergeNodeData(t.id,{x:t.data.x,y:t.data.y})})),C}))}}const dj=(t,e)=>{let n;const r=t.rows||5,i=t.cols||5;if(null==e)n=Math.min(r,i);else{Math.min(r,i)===t.rows?t.rows=e:t.cols=e}return n},fj=(t,e)=>{let n;const r=t.rows||5,i=t.cols||5;if(null==e)n=Math.max(r,i);else{Math.max(r,i)===t.rows?t.rows=e:t.cols=e}return n},pj=(t,e)=>t[`c-${e.row}-${e.col}`]||!1,gj=(t,e)=>t[`c-${e.row}-${e.col}`]=!0,vj=(t,e)=>{const n=t.cols||5;e.col++,e.col>=n&&(e.col=0,e.row++)},mj=(t,e,n,r,i,o,a,s)=>{let l,u;const c=i[t.id];if(c)l=c.col*n+n/2+e[0],u=c.row*r+r/2+e[1];else{for(;pj(s,a);)vj(o,a);l=a.col*n+n/2+e[0],u=a.row*r+r/2+e[1],gj(s,a),vj(o,a)}t.data.x=l,t.data.y=u},yj={iterations:10,height:10,width:10,speed:100,gravity:10,k:5},bj=(t,e,n,r,i,o)=>{e.forEach(((a,s)=>{n[s]={x:0,y:0},e.forEach(((e,l)=>{if(s===l)return;if(i[s]!==i[l])return;let u=a.x-e.x,c=a.y-e.y,h=Math.sqrt(u*u+c*c);if(0===h){h=1;const t=s>l?1:-1;u=.01*t,c=.01*t}if(h{const l=o||a/10;return r&&e.forEach(((e,n)=>{const r=t[n].x-t[i].x,o=t[n].y-t[i].y,a=Math.sqrt(r*r+o*o);let s=o/a,l=-r/a;const u=Math.sqrt(e.x*e.x+e.y*e.y);let c=Math.acos((s*e.x+l*e.y)/u);c>Math.PI/2&&(c-=Math.PI/2,s*=-1,l*=-1);const h=Math.cos(c)*u;e.x=s*h,e.y=l*h})),t.forEach(((o,a)=>{if(a===i)return;const u=Math.sqrt(e[a].x*e[a].x+e[a].y*e[a].y);if(u>0&&a!==i){const c=Math.min(l*(n/800),u);if(o.x+=e[a].x/u*c,o.y+=e[a].y/u*c,r){let e=o.x-t[i].x,n=o.y-t[i].y;const r=Math.sqrt(e*e+n*n);e=e/r*s[a],n=n/r*s[a],o.x=t[i].x+e,o.y=t[i].y+n}}})),t},Ej={maxIteration:1e3,focusNode:null,unitRadius:null,linkDistance:50,preventOverlap:!1,strictRadial:!0,maxPreventOverlapIteration:200,sortStrength:10};class wj{constructor(t={}){this.options=t,this.id="radial",this.options=Object.assign(Object.assign({},Ej),t)}execute(t,e){return ze(this,void 0,void 0,(function*(){return this.genericRadialLayout(!1,t,e)}))}assign(t,e){return ze(this,void 0,void 0,(function*(){yield this.genericRadialLayout(!0,t,e)}))}genericRadialLayout(t,e,n){return ze(this,void 0,void 0,(function*(){const r=Object.assign(Object.assign({},this.options),n),{width:i,height:o,center:a,focusNode:s,unitRadius:l,nodeSize:u,nodeSpacing:c,strictRadial:h,preventOverlap:d,maxPreventOverlapIteration:f,sortBy:p,linkDistance:g=50,sortStrength:v=10,maxIteration:m=1e3}=r,y=e.getAllNodes(),b=e.getAllEdges(),x=i||"undefined"==typeof window?i:window.innerWidth,E=o||"undefined"==typeof window?o:window.innerHeight,w=a||[x/2,E/2];if(!(null==y?void 0:y.length)||1===y.length)return Ob(e,t,w);let k=y[0];if(ne(s)){for(let t=0;tw[0]?w[0]:x-w[0],A=E-w[1]>w[1]?w[1]:E-w[1];0===C&&(C=x/2),0===A&&(A=E/2);const P=Math.min(C,A),R=Math.max(...T),D=[],L=l||P/R;T.forEach(((t,e)=>{D[e]=t*L}));const _=kj(y,N,g,D,L,p,v),I=Mj(_),j=((t,e,n)=>{try{const n=tE.mul(tE.pow(e,2),-.5),r=n.mean("row"),i=n.mean("column"),o=n.mean();n.add(o).subRowVector(r).subColumnVector(i);const a=new eE(n),s=tE.sqrt(a.diagonalMatrix).diagonal();return a.leftSingularVectors.toJSON().map((e=>tE.mul([e],[s]).toJSON()[0].splice(0,t)))}catch(t){const r=[];for(let t=0;t({x:(isNaN(t)?Math.random()*g:t)-j[M][0],y:(isNaN(e)?Math.random()*g:e)-j[M][1]})));if(this.run(m,F,I,_,D,M),d){B=kb(u,c);const t={nodes:y,nodeSizeFunc:B,positions:F,radii:D,height:E,width:x,strictRadial:Boolean(h),focusIdx:M,iterations:f||200,k:F.length/4.5};F=((t,e)=>{const n=Object.assign(Object.assign({},yj),e),{positions:r,iterations:i,width:o,k:a,speed:s=100,strictRadial:l,focusIdx:u,radii:c=[],nodeSizeFunc:h}=n,d=t.getAllNodes(),f=[],p=o/10;for(let t=0;t{f[e]={x:0,y:0}})),bj(d,r,f,a,c,h),xj(r,f,s,l,u,p,o,c);return r})(e,t)}const z=[];F.forEach(((t,e)=>{const n=bb(y[e]);n.data.x=t.x+w[0],n.data.y=t.y+w[1],z.push(n)})),t&&z.forEach((t=>e.mergeNodeData(t.id,{x:t.data.x,y:t.data.y})));return{nodes:z,edges:b}}))}run(t,e,n,r,i,o){for(let a=0;a<=t;a++){const s=a/t;this.oneIteration(s,e,i,r,n,o)}}oneIteration(t,e,n,r,i,o){const a=1-t;e.forEach(((s,l)=>{const u=vb(s,{x:0,y:0}),c=0===u?0:1/u;if(l===o)return;let h=0,d=0,f=0;e.forEach(((t,e)=>{if(l===e)return;const n=vb(s,t),o=0===n?0:1/n,a=r[e][l];f+=i[l][e],h+=i[l][e]*(t.x+a*(s.x-t.x)*o),d+=i[l][e]*(t.y+a*(s.y-t.y)*o)}));const p=0===n[l]?0:1/n[l];f*=a,f+=t*p*p,h*=a,h+=t*p*s.x*c,s.x=h/f,d*=a,d+=t*p*s.y*c,s.y=d/f}))}}const kj=(t,e,n,r,i,o,a)=>{if(!t)return[];const s=[];if(e){const l={};e.forEach(((e,u)=>{const c=[];e.forEach(((e,s)=>{var h,d;if(u===s)c.push(0);else if(r[u]===r[s])if("data"===o)c.push(e*(Math.abs(u-s)*a)/(r[u]/i));else if(o){let n,f;if(l[t[u].id])n=l[t[u].id];else{const e=("id"===o?t[u].id:null===(h=t[u].data)||void 0===h?void 0:h[o])||0;n=ne(e)?e.charCodeAt(0):e,l[t[u].id]=n}if(l[t[s].id])f=l[t[s].id];else{const e=("id"===o?t[s].id:null===(d=t[s].data)||void 0===d?void 0:d[o])||0;f=ne(e)?e.charCodeAt(0):e,l[t[s].id]=f}c.push(e*(Math.abs(n-f)*a)/(r[u]/i))}else c.push(e*n/(r[u]/i));else{const t=(n+i)/2;c.push(e*t)}})),s.push(c)}))}return s},Mj=t=>{const e=t.length,n=t[0].length,r=[];for(let i=0;i{let n=-1;return t.forEach(((t,r)=>{t.id===e&&(n=r)})),Math.max(n,0)},Nj=(t,e,n)=>{const r=t.length;for(let i=0;i{let n=0;for(let r=0;rn?t[e][r]:n);return n},Tj={center:[0,0],width:300,height:300};class Cj{constructor(t={}){this.options=t,this.id="random",this.options=Object.assign(Object.assign({},Tj),t)}execute(t,e){return ze(this,void 0,void 0,(function*(){return this.genericRandomLayout(!1,t,e)}))}assign(t,e){return ze(this,void 0,void 0,(function*(){yield this.genericRandomLayout(!0,t,e)}))}genericRandomLayout(t,e,n){return ze(this,void 0,void 0,(function*(){const r=Object.assign(Object.assign({},this.options),n),{center:i,width:o,height:a}=r,s=e.getAllNodes(),l=o||"undefined"==typeof window?o:window.innerWidth,u=a||"undefined"==typeof window?a:window.innerHeight,c=i||[l/2,u/2],h=[];s&&s.forEach((t=>{h.push({id:t.id,data:{x:.9*(Math.random()-.5)*l+c[0],y:.9*(Math.random()-.5)*u+c[1]}})})),t&&h.forEach((t=>e.mergeNodeData(t.id,{x:t.data.x,y:t.data.y})));return{nodes:h,edges:e.getAllEdges()}}))}} -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */const Aj=Symbol("Comlink.proxy"),Pj=Symbol("Comlink.endpoint"),Rj=Symbol("Comlink.releaseProxy"),Dj=Symbol("Comlink.finalizer"),Lj=Symbol("Comlink.thrown"),_j=t=>"object"==typeof t&&null!==t||"function"==typeof t,Ij=new Map([["proxy",{canHandle:t=>_j(t)&&t[Aj],serialize(t){const{port1:e,port2:n}=new MessageChannel;return jj(t,e),[n,[n]]},deserialize:t=>(t.start(),Fj(t))}],["throw",{canHandle:t=>_j(t)&&Lj in t,serialize({value:t}){let e;return e=t instanceof Error?{isError:!0,value:{message:t.message,name:t.name,stack:t.stack}}:{isError:!1,value:t},[e,[]]},deserialize(t){if(t.isError)throw Object.assign(new Error(t.value.message),t.value);throw t.value}}]]);function jj(t,e=globalThis,n=["*"]){e.addEventListener("message",(function r(i){if(!i||!i.data)return;if(!function(t,e){for(const n of t){if(e===n||"*"===n)return!0;if(n instanceof RegExp&&n.test(e))return!0}return!1}(n,i.origin))return void console.warn(`Invalid origin '${i.origin}' for comlink proxy`);const{id:o,type:a,path:s}=Object.assign({path:[]},i.data),l=(i.data.argumentList||[]).map(qj);let u;try{const e=s.slice(0,-1).reduce(((t,e)=>t[e]),t),n=s.reduce(((t,e)=>t[e]),t);switch(a){case"GET":u=n;break;case"SET":e[s.slice(-1)[0]]=qj(i.data.value),u=!0;break;case"APPLY":u=n.apply(e,l);break;case"CONSTRUCT":u=function(t){return Object.assign(t,{[Aj]:!0})}(new n(...l));break;case"ENDPOINT":{const{port1:e,port2:n}=new MessageChannel;jj(t,n),u=function(t,e){return $j.set(t,e),t}(e,[e])}break;case"RELEASE":u=void 0;break;default:return}}catch(t){u={value:t,[Lj]:0}}Promise.resolve(u).catch((t=>({value:t,[Lj]:0}))).then((n=>{const[i,s]=Yj(n);e.postMessage(Object.assign(Object.assign({},i),{id:o}),s),"RELEASE"===a&&(e.removeEventListener("message",r),Bj(e),Dj in t&&"function"==typeof t[Dj]&&t[Dj]())})).catch((t=>{const[n,r]=Yj({value:new TypeError("Unserializable return value"),[Lj]:0});e.postMessage(Object.assign(Object.assign({},n),{id:o}),r)}))})),e.start&&e.start()}function Bj(t){(function(t){return"MessagePort"===t.constructor.name})(t)&&t.close()}function Fj(t,e){const n=new Map;return t.addEventListener("message",(function(t){const{data:e}=t;if(!e||!e.id)return;const r=n.get(e.id);if(r)try{r(e)}finally{n.delete(e.id)}})),Hj(t,n,[],e)}function zj(t){if(t)throw new Error("Proxy has been released and is not useable")}function Gj(t){return Xj(t,new Map,{type:"RELEASE"}).then((()=>{Bj(t)}))}const Vj=new WeakMap,Wj="FinalizationRegistry"in globalThis&&new FinalizationRegistry((t=>{const e=(Vj.get(t)||0)-1;Vj.set(t,e),0===e&&Gj(t)}));function Hj(t,e,n=[],r=function(){}){let i=!1;const o=new Proxy(r,{get(r,a){if(zj(i),a===Rj)return()=>{!function(t){Wj&&Wj.unregister(t)}(o),Gj(t),e.clear(),i=!0};if("then"===a){if(0===n.length)return{then:()=>o};const r=Xj(t,e,{type:"GET",path:n.map((t=>t.toString()))}).then(qj);return r.then.bind(r)}return Hj(t,e,[...n,a])},set(r,o,a){zj(i);const[s,l]=Yj(a);return Xj(t,e,{type:"SET",path:[...n,o].map((t=>t.toString())),value:s},l).then(qj)},apply(r,o,a){zj(i);const s=n[n.length-1];if(s===Pj)return Xj(t,e,{type:"ENDPOINT"}).then(qj);if("bind"===s)return Hj(t,e,n.slice(0,-1));const[l,u]=Uj(a);return Xj(t,e,{type:"APPLY",path:n.map((t=>t.toString())),argumentList:l},u).then(qj)},construct(r,o){zj(i);const[a,s]=Uj(o);return Xj(t,e,{type:"CONSTRUCT",path:n.map((t=>t.toString())),argumentList:a},s).then(qj)}});return function(t,e){const n=(Vj.get(e)||0)+1;Vj.set(e,n),Wj&&Wj.register(t,e,t)}(o,t),o}function Uj(t){const e=t.map(Yj);return[e.map((t=>t[0])),(n=e.map((t=>t[1])),Array.prototype.concat.apply([],n))];var n}const $j=new WeakMap;function Yj(t){for(const[e,n]of Ij)if(n.canHandle(t)){const[r,i]=n.serialize(t);return[{type:"HANDLER",name:e,value:r},i]}return[{type:"RAW",value:t},$j.get(t)||[]]}function qj(t){switch(t.type){case"HANDLER":return Ij.get(t.name).deserialize(t.value);case"RAW":return t.value}}function Xj(t,e,n,r){return new Promise((i=>{const o=new Array(4).fill(0).map((()=>Math.floor(Math.random()*Number.MAX_SAFE_INTEGER).toString(16))).join("-");e.set(o,i),t.start&&t.start(),t.postMessage(Object.assign({id:o},n),r)}))}class Kj extends Kg{constructor(t,e,n){super(),this.graph=t,this.layout=e,this.options=n,this.spawnWorker()}spawnWorker(){this.proxy=Fj(new Worker(new URL("./worker.js","undefined"==typeof document&&"undefined"==typeof location?require("url").pathToFileURL(__filename).href:"undefined"==typeof document?location.href:e&&"SCRIPT"===e.tagName.toUpperCase()&&e.src||new URL("g6.min.js",document.baseURI).href),{type:"module"})),this.running&&(this.running=!1,this.execute())}execute(){var t;return ze(this,void 0,void 0,(function*(){if(this.running)return this;this.running=!0;const e=this.layout.options,{onTick:n}=e,r=Fe(e,["onTick"]),i={};Object.keys(r).forEach((t=>{Ut(r[t])||(i[t]=r[t])}));const o={layout:{id:this.layout.id,options:i,iterations:null===(t=this.options)||void 0===t?void 0:t.iterations},nodes:this.graph.getAllNodes(),edges:this.graph.getAllEdges()},a=new Float32Array([0]),[s]=yield this.proxy.calculateLayout(o,[a]);return s}))}stop(){return this.running=!1,this.proxy.stopLayout(),this}kill(){this.proxy[Rj]()}isRunning(){return this.running}}class Zj extends nv{constructor(){super(...arguments),this.id="fishbone"}getRoot(){const t=this.context.model.getRootsData();if(!(Se(t)||t.length>2))return t[0]}formatSize(t){const e="function"==typeof t?t:()=>t;return t=>Gd(e(t))}doLayout(t,e){const{hGap:n,getRibSep:r,vGap:i,nodeSize:o,height:a}=e,{model:s}=this.context,l=this.formatSize(o);let u=l(t)[0]+r(t);const c=(t,e=0)=>{var r;return e+=n*((t.children||[]).length+1),null===(r=t.children)||void 0===r||r.forEach((t=>{var n;null===(n=s.getNodeLikeDatum(t).children)||void 0===n||n.forEach((t=>{const n=s.getNodeLikeDatum(t);e=c(n,e)}))})),e},h=t=>{if(1===t.depth)return u;const e=s.getParentData(t.id,"tree");if(tB(t)){const r=s.getParentData(e.id,"tree"),o=p(t)-p(r);return h(e)+o*n/i}{const n=(e.children||[]).indexOf(t.id),r=s.getNodeData((e.children||[]).slice(n));return d(e)-r.reduce(((t,e)=>t+c(e)),0)-l(e)[0]/2}},d=xe((t=>{if(Jj(t))return l(t)[0]/2;const e=s.getParentData(t.id,"tree");if(tB(t))return h(t)+c(t)+l(t)[0]/2;{const r=p(t)-p(e),o=n/i;return h(t)+r*o}}),(t=>t.id)),f=t=>p(s.getParentData(t,"tree")),p=xe((t=>{if(Jj(t))return a/2;if(tB(t)){const e=s.getParentData(t.id,"tree"),n=e.children.indexOf(t.id);if(0===n)return f(e.id)+i;const r=s.getNodeLikeDatum(e.children[n-1]);if(Se(r.children))return p(r)+i;const o=s.getDescendantsData(r.id);return Math.max(...o.map((t=>tB(t)?f(t.id):p(t))))+i}{if(Se(t.children))return f(t.id)+i;const e=s.getNodeLikeDatum(t.children.slice(-1)[0]);if(Se(e.children))return p(e)+i;const n=s.getDescendantsData(t.id).slice(-1)[0];return(tB(n)?f(n.id):p(n))+i}}),(t=>t.id));let g=0;const v={nodes:[],edges:[]},m=t=>{var e;null===(e=t.children)||void 0===e||e.forEach((t=>m(s.getNodeLikeDatum(t))));const n=p(t),i=d(t);if(v.nodes.push({id:t.id,x:i,y:n}),Jj(t))return;const o=s.getRelatedEdgesData(t.id,"in")[0],a=[h(t),tB(t)?n:f(t.id)];v.edges.push({id:Nh(o),controlPoints:[a],relatedNodeId:t.id}),g=Math.max(g,i+r(t)),1===t.depth&&(u=g)};return m(t),v}placeAlterative(t,e){const n=(e.children||[]).filter(((t,e)=>e%2!=0));if(0===n.length)return t;const{model:r}=this.context,i=t.nodes.find((t=>t.id===e.id)).y,o=t=>{const e=r.getAncestorsData(t,"tree");if(Se(e))return!1;const i=1===e.length?t:e[e.length-2].id;return n.includes(i)};t.nodes.forEach((t=>{o(t.id)&&(t.y=2*i-t.y)})),t.edges.forEach((t=>{o(t.relatedNodeId)&&(t.controlPoints=t.controlPoints.map((t=>[t[0],2*i-t[1]])))}))}rightToLeft(t,e){return t.nodes.forEach((t=>t.x=e.width-t.x)),t.edges.forEach((t=>{t.controlPoints=t.controlPoints.map((t=>[e.width-t[0],t[1]]))})),t}execute(t,e){return ze(this,void 0,void 0,(function*(){const n=Object.assign(Object.assign(Object.assign({},Zj.defaultOptions),this.options),e),{direction:r,nodeSize:i}=n,o=this.getRoot();if(!o)return t;const a=this.formatSize(i);n.vGap||(n.vGap=Math.max(...(t.nodes||[]).map((t=>a(t)[1])))),n.hGap||(n.hGap=Math.max(...(t.nodes||[]).map((t=>a(t)[0]))));let s=this.doLayout(o,n);this.placeAlterative(s,o),"RL"===r&&(s=this.rightToLeft(s,n));const{model:l}=this.context,u=[],c=[];return s.nodes.forEach((t=>{const{id:e,x:n,y:r}=t,i=l.getNodeLikeDatum(e);u.push(Qj(i,{x:n,y:r}))})),s.edges.forEach((t=>{const{id:e,controlPoints:n}=t,r=l.getEdgeDatum(e);c.push(Qj(r,{controlPoints:n}))})),{nodes:u,edges:c}}))}}Zj.defaultOptions={direction:"RL",getRibSep:()=>60};const Qj=(t,e)=>Object.assign(Object.assign({},t),{style:Object.assign(Object.assign({},t.style||{}),e)}),Jj=t=>0===t.depth,tB=t=>(t.depth||(t.depth=0))%2==0;class eB extends nv{constructor(){super(...arguments),this.id="snake"}formatSize(t,e){const n="function"==typeof e?e:()=>e;return t.reduce(((t,e)=>{const[r,i]=Gd(n(e))||[0,0];return[Math.max(t[0],r),Math.max(t[1],i)]}),[0,0])}validate(t){const{nodes:e=[],edges:n=[]}=t,r={},i={},o={};e.forEach((t=>{r[t.id]=0,i[t.id]=0,o[t.id]=[]})),n.forEach((t=>{r[t.target]++,i[t.source]++,o[t.source].push(t.target)}));const a=new Set,s=t=>{a.has(t)||(a.add(t),o[t].forEach(s))};if(s(e[0].id),a.size!==e.length)return!1;const l=e.filter((t=>0===r[t.id])),u=e.filter((t=>0===i[t.id]));if(1!==l.length||1!==u.length)return!1;return e.filter((t=>1===r[t.id]&&1===i[t.id])).length===e.length-2}execute(t,e){return ze(this,void 0,void 0,(function*(){var n;if(!this.validate(t))return t;const{nodeSize:r,padding:i,sortBy:o,cols:a,colGap:s,rowGap:l,clockwise:u,width:c,height:h}=Object.assign({},eB.defaultOptions,this.options,e),[d,f,p,g]=Jc(i),v=this.formatSize(t.nodes||[],r),m=Math.ceil((t.nodes||[]).length/a);let y=s||(c-g-f-a*v[0])/(a-1),b=l||(h-d-p-m*v[1])/(m-1);(b===1/0||b<0)&&(b=0),(y===1/0||y<0)&&(y=0);const x=o?null===(n=t.nodes)||void 0===n?void 0:n.sort(o):function(t){const{nodes:e=[],edges:n=[]}=t,r={},i={};e.forEach((t=>{r[t.id]=0,i[t.id]=[]})),n.forEach((t=>{r[t.target]++,i[t.source].push(t.target)}));const o=[],a=[];e.forEach((t=>{0===r[t.id]&&o.push(t.id)}));for(;o.length>0;){const t=o.shift(),n=e.find((e=>e.id===t));a.push(n),i[t].forEach((t=>{r[t]--,0===r[t]&&o.push(t)}))}return a}(t),E=(x||[]).map(((t,e)=>{const n=Math.floor(e/a),r=e%a,i=g+(u?n%2==0?r:a-1-r:n%2==0?a-1-r:r)*(v[0]+y)+v[0]/2,o=d+n*(v[1]+b)+v[1]/2;return{id:t.id,style:{x:i,y:o}}}));return{nodes:E}}))}}eB.defaultOptions={padding:0,cols:5,clockwise:!0};class nB extends zh{}function rB(t,e=!0,n){const r=document.createElement("div");return r.setAttribute("class",`g6-${t}`),Object.assign(r.style,{position:"absolute",display:"block"}),e&&Object.assign(r.style,{position:"unset",gridArea:"1 / 1 / 2 / 2",inset:"0px",height:"100%",width:"100%",overflow:"hidden",pointerEvents:"none"}),n&&Object.assign(r.style,n),r}function iB(t,e="div",n={},r="",i=document.body){const o=document.getElementById(t);o&&o.remove();const a=document.createElement(e);return a.innerHTML=r,a.id=t,Object.assign(a.style,n),i.appendChild(a),a}class oB extends nB{constructor(t,e){super(t,Object.assign({},oB.defaultOptions,e)),this.$element=rB("background");this.context.canvas.getContainer().prepend(this.$element),this.update(e)}update(t){const e=Object.create(null,{update:{get:()=>super.update}});return ze(this,void 0,void 0,(function*(){e.update.call(this,t),Object.assign(this.$element.style,Pe(this.options,["key","type"]))}))}destroy(){super.destroy(),this.$element.remove()}}function aB(t,e,n,r,i,o){const a=n-t,s=r-e;let l=i-t,u=o-e,c=l*a+u*s,h=0;c<=0?h=0:(l=a-l,u=s-u,c=l*a+u*s,h=c<=0?0:c*c/(a*a+s*s));const d=l*l+u*u-h;return d<0?0:d}function sB(t,e,n,r){return(t-n)*(t-n)+(e-r)*(e-r)}function lB(t,e,n,r,i){return sB(t,e,n,r)this.y1&&e>=this.y2)return!1;if(t>this.x1&&t>=this.x2)return!1;if(tthis.x2+n)return!1}else if(tthis.x1+n)return!1;if(this.y1this.y2+n)return!1}else if(ethis.y1+n)return!1;return!0}}var hB,dB;!function(t){t[t.POINT=1]="POINT",t[t.PARALLEL=2]="PARALLEL",t[t.COINCIDENT=3]="COINCIDENT",t[t.NONE=4]="NONE"}(hB||(hB={}));class fB{constructor(t,e=0,n=0){this.state=t,this.x=e,this.y=n}}function pB(t,e){const n=(e.x2-e.x1)*(t.y1-e.y1)-(e.y2-e.y1)*(t.x1-e.x1),r=(t.x2-t.x1)*(t.y1-e.y1)-(t.y2-t.y1)*(t.x1-e.x1),i=(e.y2-e.y1)*(t.x2-t.x1)-(e.x2-e.x1)*(t.y2-t.y1);if(i){const e=n/i,o=r/i;return 0<=e&&e<=1&&0<=o&&o<=1?new fB(hB.POINT,t.x1+e*(t.x2-t.x1),t.y1+e*(t.y2-t.y1)):new fB(hB.NONE)}return new fB(0===n||0===r?hB.COINCIDENT:hB.PARALLEL)}function gB(t,e){const n=(e.x2-e.x1)*(t.y1-e.y1)-(e.y2-e.y1)*(t.x1-e.x1),r=(t.x2-t.x1)*(t.y1-e.y1)-(t.y2-t.y1)*(t.x1-e.x1),i=(e.y2-e.y1)*(t.x2-t.x1)-(e.x2-e.x1)*(t.y2-t.y1);if(i){const t=n/i,e=r/i;if(0<=t&&t<=1&&0<=e&&e<=1)return t}return Number.POSITIVE_INFINITY}function vB(t,e,n){const r=new Set;return t.width<=0?(r.add(dB.LEFT),r.add(dB.RIGHT)):et.x+t.width&&r.add(dB.RIGHT),t.height<=0?(r.add(dB.TOP),r.add(dB.BOTTOM)):nt.y+t.height&&r.add(dB.BOTTOM),r}function mB(t,e){let n=e.x1,r=e.y1;const i=e.x2,o=e.y2,a=Array.from(vB(t,i,o));if(0===a.length)return!0;let s=vB(t,n,r);for(;0!==s.size;){for(const t of a)if(s.has(t))return!1;if(s.has(dB.RIGHT)||s.has(dB.LEFT)){let e=t.x;s.has(dB.RIGHT)&&(e+=t.width),r+=(e-n)*(o-r)/(i-n),n=e}else{let e=t.y;s.has(dB.BOTTOM)&&(e+=t.height),n+=(e-r)*(i-n)/(o-r),r=e}s=vB(t,n,r)}return!0}function yB(t,e){let n=Number.POSITIVE_INFINITY,r=0;function i(t,i,o,a){let s=gB(e,new cB(t,i,o,a));s=Math.abs(s-.5),s>=0&&s<=1&&(r++,s1?n:(i(t.x,t.y2,t.x2,t.y2),r>1?n:(i(t.x2,t.y,t.x2,t.y2),0===r?-1:n))}function bB(t,e){let n=0;const r=pB(t,new cB(e.x,e.y,e.x2,e.y));n+=r.state===hB.POINT?1:0;const i=pB(t,new cB(e.x,e.y,e.x,e.y2));n+=i.state===hB.POINT?1:0;const o=pB(t,new cB(e.x,e.y2,e.x2,e.y2));n+=o.state===hB.POINT?1:0;const a=pB(t,new cB(e.x2,e.y,e.x2,e.y2));return n+=a.state===hB.POINT?1:0,{top:r,left:i,bottom:o,right:a,count:n}}!function(t){t[t.LEFT=0]="LEFT",t[t.TOP=1]="TOP",t[t.RIGHT=2]="RIGHT",t[t.BOTTOM=3]="BOTTOM"}(dB||(dB={}));class xB{constructor(t,e,n,r){this.x=t,this.y=e,this.width=n,this.height=r}get x2(){return this.x+this.width}get y2(){return this.y+this.height}get cx(){return this.x+this.width/2}get cy(){return this.y+this.height/2}get radius(){return Math.max(this.width,this.height)/2}static from(t){return new xB(t.x,t.y,t.width,t.height)}equals(t){return this.x===t.x&&this.y===t.y&&this.width===t.width&&this.height===t.height}clone(){return new xB(this.x,this.y,this.width,this.height)}add(t){const e=Math.min(this.x,t.x),n=Math.min(this.y,t.y),r=Math.max(this.x2,t.x+t.width),i=Math.max(this.y2,t.y+t.height);this.x=e,this.y=n,this.width=r-e,this.height=i-n}addPoint(t){const e=Math.min(this.x,t.x),n=Math.min(this.y,t.y),r=Math.max(this.x2,t.x),i=Math.max(this.y2,t.y);this.x=e,this.y=n,this.width=r-e,this.height=i-n}toString(){return`Rectangle[x=${this.x}, y=${this.y}, w=${this.width}, h=${this.height}]`}draw(t){t.rect(this.x,this.y,this.width,this.height)}containsPt(t,e){return t>=this.x&&t<=this.x2&&e>=this.y&&e<=this.y2}get area(){return this.width*this.height}intersects(t){return!(this.area<=0||t.width<=0||t.height<=0)&&(t.x+t.width>this.x&&t.y+t.height>this.y&&t.x=this.width?this.width-1:t}boundY(t){return t=this.height?this.height-1:t}scaleX(t){return this.boundX(Math.floor((t-this.pixelX)/this.pixelGroup))}scaleY(t){return this.boundY(Math.floor((t-this.pixelY)/this.pixelGroup))}scale(t){const e=this.scaleX(t.x),n=this.scaleY(t.y),r=this.boundX(Math.ceil((t.x+t.width-this.pixelX)/this.pixelGroup)),i=this.boundY(Math.ceil((t.y+t.height-this.pixelY)/this.pixelGroup));return new xB(e,n,r-e,i-n)}invertScaleX(t){return Math.round(t*this.pixelGroup+this.pixelX)}invertScaleY(t){return Math.round(t*this.pixelGroup+this.pixelY)}addPadding(t,e){const n=Math.ceil(e/this.pixelGroup),r=this.boundX(t.x-n),i=this.boundY(t.y-n),o=this.boundX(t.x2+n),a=this.boundY(t.y2+n);return new xB(r,i,o-r,a-i)}get(t,e){return t<0||e<0||t>=this.width||e>=this.height?Number.NaN:this.area[t+e*this.width]}inc(t,e,n){t<0||e<0||t>=this.width||e>=this.height||(this.area[t+e*this.width]+=n)}set(t,e,n){t<0||e<0||t>=this.width||e>=this.height||(this.area[t+e*this.width]=n)}incArea(t,e){if(t.width<=0||t.height<=0||0===e)return;const n=this.width,r=t.width,i=Math.max(0,t.i),o=Math.max(0,t.j),a=Math.min(t.i+t.width,n),s=Math.min(t.j+t.height,this.height);if(!(s<=0||a<=0||i>=n||s>=this.height))for(let l=o;lMath.min(t,e)),Number.POSITIVE_INFINITY),r=this.area.reduce(((t,e)=>Math.max(t,e)),Number.NEGATIVE_INFINITY),i=t=>(t-n)/(r-n);t.scale(this.pixelGroup,this.pixelGroup);for(let e=0;ee?"black":"white",t.fillRect(n,r,1,1)}t.restore()}}}function kB(t,e){const n=t=>({x:t.x-e,y:t.y-e,width:t.width+2*e,height:t.height+2*e});return Array.isArray(t)?t.map(n):n(t)}function MB(t,e,n){return SB(Object.assign(uB(t),{distSquare:(e,n)=>aB(t.x1,t.y1,t.x2,t.y2,e,n)}),e,n)}function SB(t,e,n){const r=kB(t,n),i=e.scale(r),o=e.createSub(i,r);return function(t,e,n,r){const i=n*n;for(let o=0;ot.distSquare(e,n))),o}function NB(t,e){return{x:t,y:e}}function OB(t,e,n,r){if(0===t.length)return[];const i=function(t){if(t.length<2)return t;let e=0,n=0;return t.forEach((t=>{e+=t.cx,n+=t.cy})),e/=t.length,n/=t.length,t.map((t=>{const r=e-t.cx,i=n-t.cy;return[t,r*r+i*i]})).sort(((t,e)=>t[1]-e[1])).map((t=>t[0]))}(t);return i.map(((t,o)=>{const a=i.slice(0,o);return function(t,e,n,r,i){const o=NB(e.cx,e.cy),a=function(t,e,n){let r=Number.POSITIVE_INFINITY;return e.reduce(((e,i)=>{const o=sB(t.x,t.y,i.cx,i.cy);if(o>r)return e;const a=new cB(t.x,t.y,i.cx,i.cy),s=function(t,e){return t.reduce(((t,n)=>mB(n,e)&&function(t,e){function n(t,n,r,i){let o=gB(e,new cB(t,n,r,i));return o=Math.abs(o-.5),o>=0&&o<=1?1:0}let r=n(t.x,t.y,t.x2,t.y);return r+=n(t.x,t.y,t.x,t.y2),r>1||(r+=n(t.x,t.y2,t.x2,t.y2),r>1||(r+=n(t.x2,t.y,t.x2,t.y2),r>0))}(n,e)?t+1:t),0)}(n,a);return o*(s+1)*(s+1)0;){const t=o.pop(),n=AB(e,t),s=n?bB(t,n):null;if(!n||!s||2!==s.count){a||i.push(t);continue}let l=r,u=PB(n,l,s,!0),c=CB(u,o)||CB(u,i),h=TB(u,e);for(;!c&&h&&l>=1;)l/=1.5,u=PB(n,l,s,!0),c=CB(u,o)||CB(u,i),h=TB(u,e);if(!u||c||h||(o.push(new cB(t.x1,t.y1,u.x,u.y)),o.push(new cB(u.x,u.y,t.x2,t.y2)),a=!0),a)continue;l=r,u=PB(n,l,s,!1);let d=CB(u,o)||CB(u,i);for(h=TB(u,e);!d&&h&&l>=1;)l/=1.5,u=PB(n,l,s,!1),d=CB(u,o)||CB(u,i),h=TB(u,e);u&&!d&&(o.push(new cB(t.x1,t.y1,u.x,u.y)),o.push(new cB(u.x,u.y,t.x2,t.y2)),a=!0),a||i.push(t)}for(;o.length>0;)i.push(o.pop());return i}(new cB(o.x,o.y,a.cx,a.cy),t,r,i);return function(t,e){const n=[];for(;t.length>0;){const r=t.pop();if(0===t.length){n.push(r);break}const i=t.pop(),o=new cB(r.x1,r.y1,i.x2,i.y2);AB(e,o)?(n.push(r),t.push(i)):t.push(o)}return n}(s,t)}(e,t,a,n,r)})).flat()}function TB(t,e){return e.some((e=>e.containsPt(t.x,t.y)))}function CB(t,e){return e.some((e=>!!lB(e.x1,e.y1,t.x,t.y,.001)||!!lB(e.x2,e.y2,t.x,t.y,.001)))}function AB(t,e){let n=Number.POSITIVE_INFINITY,r=null;for(const i of t){if(!mB(i,e))continue;const t=yB(i,e);t>=0&&ts.y?NB(t.x-e,t.y-e):NB(t.x2+e,t.y-e):o.ya.x?NB(t.x-e,t.y-e):NB(t.x-e,t.y2+e):i.xs.y?NB(t.x2+e,t.y2+e):NB(t.x-e,t.y2+e):o.ya.x?NB(t.x2+e,t.y2+e):NB(t.x2+e,t.y-e):i.xr)return!1}return!0}function DB(t,e){switch(t){case-2:return(((3-e)*e-3)*e+1)/6;case-1:return((3*e-6)*e*e+4)/6;case 0:return(((-3*e+3)*e+3)*e+1)/6;case 1:return e*e*e/6;default:throw new Error("unknown error")}}class LB{constructor(t=[],e=!0){this.points=t,this.closed=e}get(t){const e=t,n=this.points.length;return t<0?this.closed?this.get(t+n):this.points[0]:t>=n?this.closed?this.get(t-n):this.points[n-1]:this.points[e]}get length(){return this.points.length}toString(t=1/0){const e=this.points;if(0===e.length)return"";const n="function"==typeof t?t:function(t){if(!Number.isFinite(t))return t=>t;if(0===t)return Math.round;const e=Math.pow(10,t);return t=>Math.round(t*e)/e}(t);let r="M";for(const t of e)r+=`${n(t.x)},${n(t.y)} L`;return r=r.slice(0,-1),this.closed&&(r+=" Z"),r}draw(t){const e=this.points;if(0!==e.length){t.beginPath(),t.moveTo(e[0].x,e[0].y);for(const n of e)t.lineTo(n.x,n.y);this.closed&&t.closePath()}}sample(t){return function(t=8){return e=>{let n=t,r=e.length;if(n>1)for(r=Math.floor(e.length/n);r<3&&n>1;)n-=1,r=Math.floor(e.length/n);const i=[];for(let t=0,o=0;o{if(t<0||e.length<3)return e;const n=[];let r=0;const i=t*t;for(;r{if(n.length<3)return n;const r=[],i=n.closed,o=n.length+3-1+(i?0:2);r.push(e(n,2-(i?0:2),0));for(let a=2-(i?0:2);ae.containsPt(t.cx,t.cy)&&this.withinArea(t.cx,t.cy)))}withinArea(t,e){if(0===this.length)return!1;let n=0;const r=this.points[0],i=new cB(r.x,r.y,r.x,r.y);for(let r=1;re?i+o:i}function o(t,e){let n=0;return n=i(t,e,n,1),n=i(t+1,e,n,2),n=i(t,e+1,n,4),n=i(t+1,e+1,n,8),Number.isNaN(n)?-1:n}let a=1;function s(e,n){let i=e,s=n,l=t.invertScaleX(i),u=t.invertScaleY(s);for(let e=0;eFB(e.raw,t)));return!(e<0)&&(this.members.splice(e,1),this.dirty.add(zB.MEMBERS),!0)}removeNonMember(t){const e=this.nonMembers.findIndex((e=>FB(e.raw,t)));return!(e<0)&&(this.nonMembers.splice(e,1),this.dirty.add(zB.NON_MEMBERS),!0)}removeEdge(t){const e=this.edges.findIndex((e=>e.obj.equals(t)));return!(e<0)&&(this.edges.splice(e,1),this.dirty.add(zB.NON_MEMBERS),!0)}pushNonMember(...t){if(0!==t.length){this.dirty.add(zB.NON_MEMBERS);for(const e of t)this.nonMembers.push({raw:e,obj:BB(e)?EB.from(e):xB.from(e),area:null})}}pushEdge(...t){if(0!==t.length){this.dirty.add(zB.EDGES);for(const e of t)this.edges.push({raw:e,obj:cB.from(e),area:null})}}update(){const t=this.dirty.has(zB.MEMBERS),e=this.dirty.has(zB.NON_MEMBERS);let n=this.dirty.has(zB.EDGES);this.dirty.clear();const r=this.members.map((t=>t.obj));if(this.o.virtualEdges&&(t||e)){const t=OB(r,this.nonMembers.map((t=>t.obj)),this.o.maxRoutingIterations,this.o.morphBuffer),e=new Map(this.virtualEdges.map((t=>[t.obj.toString(),t.area])));this.virtualEdges=t.map((t=>{var n;return{raw:t,obj:t,area:null!==(n=e.get(t.toString()))&&void 0!==n?n:null}})),n=!0}let i=!1;if(t||n){const t=function(t,e){if(0===t.length)return new xB(0,0,0,0);const n=xB.from(t[0]);for(const e of t)n.add(e);for(const t of e)n.add(uB(t));return n}(r,this.virtualEdges.concat(this.edges).map((t=>t.obj))),e=Math.max(this.o.edgeR1,this.o.nodeR1)+this.o.morphBuffer,n=xB.from(kB(t,e));n.equals(this.activeRegion)||(i=!0,this.activeRegion=n)}if(i){const t=Math.ceil(this.activeRegion.width/this.o.pixelGroup),e=Math.ceil(this.activeRegion.height/this.o.pixelGroup);this.activeRegion.x!==this.potentialArea.pixelX||this.activeRegion.y!==this.potentialArea.pixelY?(this.potentialArea=wB.fromPixelRegion(this.activeRegion,this.o.pixelGroup),this.members.forEach((t=>t.area=null)),this.nonMembers.forEach((t=>t.area=null)),this.edges.forEach((t=>t.area=null)),this.virtualEdges.forEach((t=>t.area=null))):t===this.potentialArea.width&&e===this.potentialArea.height||(this.potentialArea=wB.fromPixelRegion(this.activeRegion,this.o.pixelGroup))}const o=new Map,a=t=>{if(t.area){const e=`${t.obj.width}x${t.obj.height}x${t.obj instanceof xB?"R":"C"}`;o.set(e,t.area)}},s=t=>{if(t.area)return;const e=`${t.obj.width}x${t.obj.height}x${t.obj instanceof xB?"R":"C"}`;if(o.has(e)){const n=o.get(e);return void(t.area=this.potentialArea.copy(n,{x:t.obj.x-this.o.nodeR1,y:t.obj.y-this.o.nodeR1}))}const n=t.obj instanceof xB?function(t,e,n){const r=e.scale(t),i=e.addPadding(r,n),o=e.createSub(i,{x:t.x-n,y:t.y-n}),a=r.x-i.x,s=r.y-i.y,l=i.x2-r.x2,u=i.y2-r.y2,c=i.width-a-l,h=i.height-s-u,d=n*n;o.fillArea({x:a,y:s,width:c+1,height:h+1},d);const f=[0],p=Math.max(s,a,l,u);{const i=e.invertScaleX(r.x+r.width/2);for(let o=1;o{this.activeRegion.intersects(t.obj)?s(t):t.area=null})),this.edges.forEach((t=>{t.area||(t.area=MB(t.obj,this.potentialArea,this.o.edgeR1))})),this.virtualEdges.forEach((t=>{t.area||(t.area=MB(t.obj,this.potentialArea,this.o.edgeR1))}))}drawMembers(t){for(const e of this.members)e.obj.draw(t)}drawNonMembers(t){for(const e of this.nonMembers)e.obj.draw(t)}drawEdges(t){for(const e of this.edges)e.obj.draw(t)}drawPotentialArea(t,e=!0){this.potentialArea.draw(t,e)}compute(){if(0===this.members.length)return new LB([]);this.dirty.size>0&&this.update();const{o:t,potentialArea:e}=this,n=this.members.map((t=>t.area)),r=this.virtualEdges.concat(this.edges).map((t=>t.area)),i=this.nonMembers.filter((t=>null!=t.area)).map((t=>t.area)),o=this.members.map((t=>t.obj));return function(t,e,n,r,i,o={}){const a=Object.assign({},jB,o);let s=a.threshold,l=a.memberInfluenceFactor,u=a.edgeInfluenceFactor,c=a.nonMemberInfluenceFactor;const h=(a.nodeR0-a.nodeR1)*(a.nodeR0-a.nodeR1),d=(a.edgeR0-a.edgeR1)*(a.edgeR0-a.edgeR1);for(let o=0;o0))break;c*=.8}}return new LB([])}(e,n,r,i,(t=>t.containsElements(o)),t)}};class VB extends nB{constructor(t,e){super(t,ke({},VB.defaultOptions,e)),this.members=new Map,this.avoidMembers=new Map,this.bubbleSetOptions={},this.shallRunUpdateBubbleSetsPath=!1,this.pendingRunUpdateBubbleSetsPath=!1,this.drawBubbleSets=()=>{const{style:t,bubbleSetOptions:e}=this.parseOptions();Ne(this.bubbleSetOptions,e)||this.init(),this.bubbleSetOptions=Object.assign({},e);const n=Object.assign(Object.assign({},t),{d:this.getPath()});this.shape?this.shape.update(n):(this.shape=new nf({style:n}),this.context.canvas.appendChild(this.shape))},this.updateBubbleSetsPath=t=>{if(!this.shallRunUpdateBubbleSetsPath)return void(this.pendingRunUpdateBubbleSetsPath||(this.pendingRunUpdateBubbleSetsPath=!0,setTimeout((()=>{this.shallRunUpdateBubbleSetsPath=!0,this.updateBubbleSetsPath(t)}))));if(this.pendingRunUpdateBubbleSetsPath=!1,this.shallRunUpdateBubbleSetsPath=!1,!this.shape)return;const e=Nh(t.data);[...this.options.members,...this.options.avoidMembers].includes(e)&&this.shape.update(Object.assign(Object.assign({},this.parseOptions().style),{d:this.getPath(e)}))},this.getPath=t=>{const{graph:e}=this.context,n=this.options.members,r=[...this.members.keys()],i=this.options.avoidMembers,o=[...this.avoidMembers.keys()];if(!t&&Ne(n,r)&&Ne(i,o))return this.path;const{enter:a=[],exit:s=[]}=jh(r,n,(t=>t)),{enter:l=[],exit:u=[]}=jh(o,i,(t=>t));t&&(s.push(t),a.push(t));const c=(t,n,r)=>{t.forEach((t=>{const i=r?this.members:this.avoidMembers,o=r?"pushMember":"pushNonMember",a=r?"removeMember":"removeNonMember";if(n){let n;"edge"===e.getElementType(t)?([n]=HB(e,t),this.bubbleSets.pushEdge(n)):([n]=WB(e,t),this.bubbleSets[o](n)),i.set(t,n)}else{const n=i.get(t);n&&("edge"===e.getElementType(t)?this.bubbleSets.removeEdge(n):this.bubbleSets[a](n),i.delete(t))}}))};c(s,!1,!0),c(a,!0,!0),c(u,!1,!1),c(l,!0,!1);const h=this.bubbleSets.compute().sample(8).simplify(0).bSplines().simplify(0);return this.path=ef(h.points.map(cd)),this.path},this.bindEvents(),this.bubbleSets=new GB(this.options)}bindEvents(){this.context.graph.on(t.GraphEvent.AFTER_RENDER,this.drawBubbleSets),this.context.graph.on(t.GraphEvent.AFTER_ELEMENT_UPDATE,this.updateBubbleSetsPath)}init(){this.bubbleSets=new GB(this.options),this.members=new Map,this.avoidMembers=new Map}parseOptions(){const t=this.options,{type:e,key:n,members:r,avoidMembers:i}=t,o=Fe(t,["type","key","members","avoidMembers"]),a=Object.keys(o).reduce(((t,e)=>(e in jB?t.bubbleSetOptions[e]=o[e]:t.style[e]=o[e],t)),{style:{},bubbleSetOptions:{}});return Object.assign({type:e,key:n,members:r,avoidMembers:i},a)}addMember(t){const e=Array.isArray(t)?t:[t];e.some((t=>this.options.avoidMembers.includes(t)))&&(this.options.avoidMembers=this.options.avoidMembers.filter((t=>!e.includes(t)))),this.options.members=[...new Set([...this.options.members,...e])],this.drawBubbleSets()}removeMember(t){const e=Array.isArray(t)?t:[t];this.options.members=this.options.members.filter((t=>!e.includes(t))),this.drawBubbleSets()}updateMember(t){this.options.members=Ut(t)?t(this.options.members):t,this.drawBubbleSets()}getMember(){return this.options.members}addAvoidMember(t){const e=Array.isArray(t)?t:[t];e.some((t=>this.options.members.includes(t)))&&(this.options.members=this.options.members.filter((t=>!e.includes(t)))),this.options.avoidMembers=[...new Set([...this.options.avoidMembers,...e])],this.drawBubbleSets()}removeAvoidMember(t){const e=Array.isArray(t)?t:[t];this.options.avoidMembers.some((t=>e.includes(t)))&&(this.options.avoidMembers=this.options.avoidMembers.filter((t=>!e.includes(t))),this.drawBubbleSets())}updateAvoidMember(t){this.options.avoidMembers=Array.isArray(t)?t:[t],this.drawBubbleSets()}getAvoidMember(){return this.options.avoidMembers}destroy(){this.context.graph.off(t.GraphEvent.AFTER_RENDER,this.drawBubbleSets),this.context.graph.off(t.GraphEvent.AFTER_ELEMENT_UPDATE,this.updateBubbleSetsPath),this.shape.destroy(),super.destroy()}}VB.defaultOptions=Object.assign({members:[],avoidMembers:[],fill:"lightblue",fillOpacity:.2,stroke:"blue",strokeOpacity:.2},jB);const WB=(t,e)=>(Array.isArray(e)?e:[e]).map((e=>{const n=t.getElementRenderBounds(e);return new xB(n.min[0],n.min[1],eh(n),nh(n))})),HB=(t,e)=>(Array.isArray(e)?e:[e]).map((e=>{const n=t.getEdgeData(e),r=t.getElementPosition(n.source),i=t.getElementPosition(n.target);return cB.from({x1:r[0],y1:r[1],x2:i[0],y2:i[1]})}));class UB extends nB{constructor(t,e){super(t,Object.assign({},UB.defaultOptions,e)),this.targetElement=null,this.onTriggerEvent=t=>{var e;null===(e=t.preventDefault)||void 0===e||e.call(t),this.show(t)},this.onMenuItemClick=t=>{const{onClick:e,trigger:n}=this.options;if(t.target instanceof HTMLElement&&t.target.className.includes("g6-contextmenu-li")){const n=t.target.getAttribute("value");null==e||e(n,t.target,this.targetElement),this.hide()}"click"!==n&&this.hide()},this.initElement(),this.update(e)}initElement(){this.$element=rB("contextmenu",!1,{zIndex:"99"});const{className:t}=this.options;t&&this.$element.classList.add(t);this.context.canvas.getContainer().appendChild(this.$element),iB("g6-contextmenu-css","style",{},"\n .g6-contextmenu {\n font-size: 12px;\n background-color: rgba(255, 255, 255, 0.96);\n border-radius: 4px;\n overflow: hidden;\n box-shadow: rgba(0, 0, 0, 0.12) 0px 6px 12px 0px;\n transition: visibility 0.2s cubic-bezier(0.23, 1, 0.32, 1) 0s, left 0.4s cubic-bezier(0.23, 1, 0.32, 1) 0s, top 0.4s cubic-bezier(0.23, 1, 0.32, 1) 0s;\n }\n\n .g6-contextmenu-ul {\n max-width: 256px;\n min-width: 96px;\n list-style: none;\n padding: 0;\n margin: 0;\n }\n\n .g6-contextmenu-li {\n padding: 8px 12px;\n cursor: pointer;\n user-select: none;\n }\n\n .g6-contextmenu-li:hover {\n background-color: #f5f5f5;\n cursor: pointer;\n }\n",document.head)}show(t){return ze(this,void 0,void 0,(function*(){const{enable:e,offset:n}=this.options;if("function"==typeof e&&!e(t)||!e)return void this.hide();const r=yield this.getDOMContent(t);r instanceof HTMLElement?(this.$element.innerHTML="",this.$element.appendChild(r)):this.$element.innerHTML=r;const i=this.context.graph.getCanvas().getContainer().getBoundingClientRect();this.$element.style.left=`${t.client.x-i.left+n[0]}px`,this.$element.style.top=`${t.client.y-i.top+n[1]}px`,this.$element.style.display="block",this.targetElement=t.target}))}hide(){this.$element.style.display="none",this.targetElement=null}update(t){this.unbindEvents(),super.update(t),this.bindEvents()}destroy(){this.unbindEvents(),super.destroy(),this.$element.remove()}getDOMContent(t){return ze(this,void 0,void 0,(function*(){const{getContent:e,getItems:n}=this.options;return n?`\n
    \n ${(yield n(t)).map((t=>`
  • ${t.name}
  • `)).join("")}\n
\n `:yield e(t)}))}bindEvents(){const{graph:t}=this.context,{trigger:e}=this.options;t.on(`canvas:${e}`,this.onTriggerEvent),t.on(`node:${e}`,this.onTriggerEvent),t.on(`edge:${e}`,this.onTriggerEvent),t.on(`combo:${e}`,this.onTriggerEvent),document.addEventListener("click",this.onMenuItemClick)}unbindEvents(){const{graph:t}=this.context,{trigger:e}=this.options;t.off(`canvas:${e}`,this.onTriggerEvent),t.off(`node:${e}`,this.onTriggerEvent),t.off(`edge:${e}`,this.onTriggerEvent),t.off(`combo:${e}`,this.onTriggerEvent),document.removeEventListener("click",this.onMenuItemClick)}}UB.defaultOptions={trigger:"contextmenu",offset:[4,4],loadingContent:'
Loading...
',getContent:()=>"It is a empty context menu.",enable:()=>!0};class $B extends nB{constructor(t,e){super(t,Object.assign({},$B.defaultOptions,e)),this.edgeBundles={},this.edgePoints={},this.onBundle=()=>{const{model:t,element:e}=this.context,n=t.getEdgeData();this.divideEdges(this.options.divisions);const{cycles:r,iterRate:i,divRate:o}=this.options;let{lambda:a,divisions:s,iterations:l}=this.options;for(let t=0;t{var n;if(e.source===e.target)return;const r=Nh(e);t[r]=this.getEdgeForces(e,s,a);for(let e=0;e{const n=Nh(t),r=e.getElement(n);null==r||r.update({d:ig(this.edgePoints[n])})}))},this.bindEvents()}get nodeMap(){const t=this.context.model.getNodeData();return Object.fromEntries(t.map((t=>[Nh(t),ed(sd(t))])))}divideEdges(t){this.context.model.getEdgeData().forEach((e=>{var n;const r=Nh(e);(n=this.edgePoints)[r]||(n[r]=[]);const i=this.nodeMap[e.source],o=this.nodeMap[e.target];if(1===t)this.edgePoints[r].push(i),this.edgePoints[r].push(Yh(Hh(i,o),2)),this.edgePoints[r].push(o);else{const e=(0===this.edgePoints[r].length?Xh(i,o):JB(this.edgePoints[r]))/(t+1);let n=e;const a=[i];for(let t=1;tn;){const t=n/s,r=Hh(i,$h(Uh(o,i),t));a.push(r),s-=n,n=e}n-=s}a.push(o),this.edgePoints[r]=a}}))}getVectorPosition(t){const e=this.nodeMap[t.source],n=this.nodeMap[t.target],[r,i]=Uh(n,e);return{source:e,target:n,vx:r,vy:i,length:Xh(e,n)}}measureEdgeCompatibility(t,e){const n=this.getVectorPosition(t),r=this.getVectorPosition(e);return YB(n,r)*qB(n,r)*XB(n,r)*QB(n,r)}getEdgeBundles(){const t={},e=this.options.bundleThreshold,n=this.context.model.getEdgeData();return n.forEach(((r,i)=>{n.forEach(((n,o)=>{var a,s;if(o<=i)return;this.measureEdgeCompatibility(r,n)>=e&&(t[a=Nh(r)]||(t[a]=[]),t[Nh(r)].push(n),t[s=Nh(n)]||(t[s]=[]),t[Nh(n)].push(r))}))})),t}getSpringForce(t,e){const{pre:n,cur:r,next:i}=t;return $h(Uh(Hh(n,i),$h(r,2)),e)}getElectrostaticForce(t,e){Se(this.edgeBundles)&&(this.edgeBundles=this.getEdgeBundles());const n=this.edgeBundles[Nh(e)];let r=[0,0];return null==n||n.forEach((n=>{const i=this.edgePoints[Nh(n)][t],o=this.edgePoints[Nh(e)][t],a=Uh(i,o),s=Xh(i,o);r=Hh(r,$h(a,1/s))})),r}getEdgeForces(t,e,n){const r=this.nodeMap[t.source],i=this.nodeMap[t.target],o=this.options.K/(Xh(r,i)*(e+1)),a=[[0,0]],s=Nh(t);for(let r=1;rMath.abs(function(t,e){return t.reduce(((t,n,r)=>t+n*e[r]),0)}([t.vx,t.vy],[e.vx,e.vy])/(t.length*e.length)),qB=(t,e)=>{const n=(t.length+e.length)/2;return 2/(n/Math.min(t.length,e.length)+Math.max(t.length,e.length)/n)},XB=(t,e)=>{const n=(t.length+e.length)/2;return n/(n+Xh(Yh(Hh(t.source,t.target),2),Yh(Hh(e.source,e.target),2)))},KB=(t,e)=>{if(e.source[0]===e.target[0])return[e.source[0],t[1]];if(e.source[1]===e.target[1])return[t[0],e.source[1]];const n=(e.source[1]-e.target[1])/(e.source[0]-e.target[0]),r=(n*n*e.source[0]+n*(t[1]-e.source[1])+t[0])/(n*n+1);return[r,n*(r-e.source[0])+e.source[1]]},ZB=(t,e)=>{const n=KB(e.source,t),r=KB(e.target,t),i=Yh(Hh(n,r),2),o=Yh(Hh(t.source,t.target),2);return 0===Xh(n,r)?0:Math.max(0,1-2*Xh(o,i)/Xh(n,r))},QB=(t,e)=>Math.min(ZB(t,e),ZB(e,t)),JB=t=>{let e=0;for(let n=1;n{if("drag"===this.options.trigger&&this.isLensOn)return;const e=cd(t.canvas);this.renderLens(e),this.renderFocusElements()},this.renderLens=t=>{const e=Object.assign({},tF,this.options.style);this.isLensOn||(this.lens=new df({style:e}),this.canvas.appendChild(this.lens)),Object.assign(e,hd(t),{size:2*this.r}),this.lens.update(e)},this.getFilterData=()=>{const{filter:t}=this.options,{model:e}=this.context,n=e.getData();if(!t)return n;const{nodes:r,edges:i,combos:o}=n;return{nodes:r.filter((e=>t(Nh(e),"node"))),edges:i.filter((e=>t(Nh(e),"edge"))),combos:o.filter((e=>t(Nh(e),"combo")))}},this.getFocusElements=t=>{const{nodes:e,edges:n}=this.getFilterData(),r=e.filter((e=>Xh(sd(e),t)Nh(t)));return{nodes:r,edges:n.filter((t=>{const{source:e,target:n}=t,r=i.includes(e),o=i.includes(n);switch(this.options.nodeType){case"both":return r&&o;case"either":return r!==o;case"source":return r&&!o;case"target":return!r&&o;default:return!1}}))}},this.renderFocusElements=()=>{const{element:t,graph:e}=this.context;if(!this.isLensOn)return;const n=this.lens.getCenter(),{nodes:r,edges:i}=this.getFocusElements(n),o=new Set,a=n=>{const r=Nh(n);o.add(r);const i=t.getElement(r);if(!i)return;const a=this.shapes.get(r)||i.cloneNode();a.setPosition(i.getPosition()),a.id=i.id,this.shapes.has(r)?Object.entries(i.attributes).forEach((([t,e])=>{a.style[t]!==e&&(a.style[t]=e)})):(this.canvas.appendChild(a),this.shapes.set(r,a));const s=e.getElementType(r),l=this.getElementStyle(s,n);a.update(l)};r.forEach(a),i.forEach(a),this.shapes.forEach(((t,e)=>{o.has(e)||(t.destroy(),this.shapes.delete(e))}))},this.scaleRByWheel=t=>{var e;this.options.preventDefault&&t.preventDefault();const{clientX:n,clientY:r,deltaX:i,deltaY:o}=t,{graph:a,canvas:s}=this.context,l=a.getCanvasByClient([n,r]),u=null===(e=this.lens)||void 0===e?void 0:e.getCenter();if(!this.isLensOn||Xh(l,u)>this.r)return;const{maxR:c,minR:h}=this.options,d=i+o>0?1/.95:.95,f=Math.min(...s.getSize())/2;this.r=Math.max(h||0,Math.min(c||f,this.r*d)),this.renderLens(u),this.renderFocusElements()},this.isLensDragging=!1,this.onDragStart=t=>{var e;const n=cd(t.canvas),r=null===(e=this.lens)||void 0===e?void 0:e.getCenter();!this.isLensOn||Xh(n,r)>this.r||(this.isLensDragging=!0)},this.onDrag=t=>{if(!this.isLensDragging)return;const e=cd(t.canvas);this.renderLens(e),this.renderFocusElements()},this.onDragEnd=()=>{this.isLensDragging=!1},this.bindEvents()}get canvas(){return this.context.canvas.getLayer("transient")}get isLensOn(){return this.lens&&!this.lens.destroyed}getElementStyle(t,e){const n="node"===t?this.options.nodeStyle:this.options.edgeStyle;return"function"==typeof n?n(e):n}get graphDom(){return this.context.graph.getCanvas().getContextService().getDomElement()}bindEvents(){var e;const{graph:n}=this.context,{trigger:r,scaleRBy:i}=this.options,o=n.getCanvas().getLayer();["click","drag"].includes(r)&&o.addEventListener(t.CommonEvent.CLICK,this.onEdgeFilter),"pointermove"===r?o.addEventListener(t.CommonEvent.POINTER_MOVE,this.onEdgeFilter):"drag"===r&&(o.addEventListener(t.CommonEvent.DRAG_START,this.onDragStart),o.addEventListener(t.CommonEvent.DRAG,this.onDrag),o.addEventListener(t.CommonEvent.DRAG_END,this.onDragEnd)),"wheel"===i&&(null===(e=this.graphDom)||void 0===e||e.addEventListener(t.CommonEvent.WHEEL,this.scaleRByWheel,{passive:!1}))}unbindEvents(){var e;const{graph:n}=this.context,{trigger:r,scaleRBy:i}=this.options,o=n.getCanvas().getLayer();["click","drag"].includes(r)&&o.removeEventListener(t.CommonEvent.CLICK,this.onEdgeFilter),"pointermove"===r?o.removeEventListener(t.CommonEvent.POINTER_MOVE,this.onEdgeFilter):"drag"===r&&(o.removeEventListener(t.CommonEvent.DRAG_START,this.onDragStart),o.removeEventListener(t.CommonEvent.DRAG,this.onDrag),o.removeEventListener(t.CommonEvent.DRAG_END,this.onDragEnd)),"wheel"===i&&(null===(e=this.graphDom)||void 0===e||e.removeEventListener(t.CommonEvent.WHEEL,this.scaleRByWheel))}update(t){var e;this.unbindEvents(),super.update(t),this.r=null!==(e=t.r)&&void 0!==e?e:this.r,this.bindEvents()}destroy(){this.unbindEvents(),this.isLensOn&&this.lens.destroy(),this.shapes.forEach(((t,e)=>{t.destroy(),this.shapes.delete(e)})),super.destroy()}}eF.defaultOptions={trigger:"pointermove",r:60,nodeType:"both",filter:()=>!0,style:{lineWidth:2},nodeStyle:{label:!1},edgeStyle:{label:!0},scaleRBy:"wheel",preventDefault:!0};const nF={fill:"#ccc",fillOpacity:.1,lineWidth:2,stroke:"#000",strokeOpacity:.8,labelFontSize:12};class rF extends nB{constructor(t,e){super(t,Object.assign({},rF.defaultOptions,e)),this.r=this.options.r,this.d=this.options.d,this.onCreateFisheye=t=>{if("drag"===this.options.trigger&&this.isLensOn)return;const e=cd(t.canvas);this.onMagnify(e)},this.onMagnify=t=>{t.some(isNaN)||(this.renderLens(t),this.renderFocusElements())},this.renderLens=t=>{const e=Object.assign({},nF,this.options.style);this.isLensOn||(this.lens=new df({style:e}),this.canvas.appendChild(this.lens)),Object.assign(e,hd(t),{size:2*this.r,label:this.options.showDPercent,labelText:this.getDPercent()}),this.lens.update(e)},this.getDPercent=()=>{const{minD:t,maxD:e}=this.options;return`${Math.round((this.d-t)/(e-t)*100)}%`},this.prevMagnifiedStyleMap=new Map,this.prevOriginStyleMap=new Map,this.renderFocusElements=()=>{if(!this.isLensOn)return;const{graph:t}=this.context,e=this.lens.getCenter(),n=(this.d+1)*this.r,r=new Map,i=new Map;t.getNodeData().forEach((o=>{const a=sd(o),s=Xh(a,e);if(s>this.r)return;const l=n*s/(this.d*s+this.r),[u,c]=a,[h,d]=e,f=[h+l*((u-h)/s),d+l*((c-d)/s)],p=Nh(o),g=this.getNodeStyle(o),v=Ae(t.getElementRenderStyle(p),Object.keys(g));r.set(p,Object.assign(Object.assign({},hd(f)),g)),i.set(p,Object.assign(Object.assign({},hd(a)),v))})),this.updateStyle(r,i)},this.getNodeStyle=t=>{const{nodeStyle:e}=this.options;return"function"==typeof e?e(t):e},this.updateStyle=(t,e)=>{const{graph:n,element:r}=this.context,{enter:i,exit:o,keep:a}=jh(Array.from(this.prevMagnifiedStyleMap.keys()),Array.from(t.keys()),(t=>t)),s=new Set,l=(t,e)=>{const i=r.getElement(t);null==i||i.update(e),n.getRelatedEdgesData(t).forEach((t=>{s.add(Nh(t))}))};[...i,...a].forEach((e=>{l(e,t.get(e))})),o.forEach((t=>{l(t,this.prevOriginStyleMap.get(t)),this.prevOriginStyleMap.delete(t)})),s.forEach((t=>{const e=r.getElement(t);null==e||e.update({})})),this.prevMagnifiedStyleMap=t,e.forEach(((t,e)=>{this.prevOriginStyleMap.has(e)||this.prevOriginStyleMap.set(e,t)}))},this.isWheelValid=t=>{if(this.options.preventDefault&&t.preventDefault(),!this.isLensOn)return!1;const{clientX:e,clientY:n}=t;return!(Xh(this.context.graph.getCanvasByClient([e,n]),this.lens.getCenter())>this.r)},this.scaleR=t=>{const{maxR:e,minR:n}=this.options,r=t?1/.95:.95,i=Math.min(...this.context.canvas.getSize())/2;this.r=Math.max(n||0,Math.min(e||i,this.r*r))},this.scaleD=t=>{const{maxD:e,minD:n}=this.options,r=t?this.d+.1:this.d-.1;this.d=Math.max(n,Math.min(e,r))},this.scaleRByWheel=t=>{if(!this.isWheelValid(t))return;const{deltaX:e,deltaY:n}=t;this.scaleR(e+n>0);const r=this.lens.getCenter();this.onMagnify(r)},this.scaleDByWheel=t=>{if(!this.isWheelValid(t))return;const{deltaX:e,deltaY:n}=t;this.scaleD(e+n>0);const r=this.lens.getCenter();this.onMagnify(r)},this.isDragValid=t=>{if(this.options.preventDefault&&t.preventDefault(),!this.isLensOn)return!1;return!(Xh(cd(t.canvas),this.lens.getCenter())>this.r)},this.isLensDragging=!1,this.onDragStart=t=>{this.isDragValid(t)&&(this.isLensDragging=!0)},this.onDrag=t=>{if(!this.isLensDragging)return;const e=cd(t.canvas);this.onMagnify(e)},this.onDragEnd=()=>{this.isLensDragging=!1},this.scaleRByDrag=t=>{if(!this.isLensDragging)return;const{dx:e,dy:n}=t;this.scaleR(e-n>0);const r=this.lens.getCenter();this.onMagnify(r)},this.scaleDByDrag=t=>{if(!this.isLensDragging)return;const{dx:e,dy:n}=t;this.scaleD(e-n>0);const r=this.lens.getCenter();this.onMagnify(r)},this.bindEvents()}get canvas(){return this.context.canvas.getLayer("transient")}get isLensOn(){return this.lens&&!this.lens.destroyed}get graphDom(){return this.context.graph.getCanvas().getContextService().getDomElement()}bindEvents(){var e;const{graph:n}=this.context,{trigger:r,scaleRBy:i,scaleDBy:o}=this.options,a=n.getCanvas().getLayer();if(["click","drag"].includes(r)&&a.addEventListener(t.CommonEvent.CLICK,this.onCreateFisheye),"pointermove"===r&&a.addEventListener(t.CommonEvent.POINTER_MOVE,this.onCreateFisheye),"drag"===r||"drag"===i||"drag"===o){a.addEventListener(t.CommonEvent.DRAG_START,this.onDragStart),a.addEventListener(t.CommonEvent.DRAG_END,this.onDragEnd);const e="drag"===r?this.onDrag:"drag"===i?this.scaleRByDrag:this.scaleDByDrag;a.addEventListener(t.CommonEvent.DRAG,e)}if("wheel"===i||"wheel"===o){const n="wheel"===i?this.scaleRByWheel:this.scaleDByWheel;null===(e=this.graphDom)||void 0===e||e.addEventListener(t.CommonEvent.WHEEL,n,{passive:!1})}}unbindEvents(){var e;const{graph:n}=this.context,{trigger:r,scaleRBy:i,scaleDBy:o}=this.options,a=n.getCanvas().getLayer();if(["click","drag"].includes(r)&&a.removeEventListener(t.CommonEvent.CLICK,this.onCreateFisheye),"pointermove"===r&&a.removeEventListener(t.CommonEvent.POINTER_MOVE,this.onCreateFisheye),"drag"===r||"drag"===i||"drag"===o){a.removeEventListener(t.CommonEvent.DRAG_START,this.onDragStart),a.removeEventListener(t.CommonEvent.DRAG_END,this.onDragEnd);const e="drag"===r?this.onDrag:"drag"===i?this.scaleRByDrag:this.scaleDByDrag;a.removeEventListener(t.CommonEvent.DRAG,e)}if("wheel"===i||"wheel"===o){const n="wheel"===i?this.scaleRByWheel:this.scaleDByWheel;null===(e=this.graphDom)||void 0===e||e.removeEventListener(t.CommonEvent.WHEEL,n)}}update(t){var e,n;this.unbindEvents(),super.update(t),this.r=null!==(e=t.r)&&void 0!==e?e:this.r,this.d=null!==(n=t.d)&&void 0!==n?n:this.d,this.bindEvents()}destroy(){var t;this.unbindEvents(),this.isLensOn&&(null===(t=this.lens)||void 0===t||t.destroy()),this.prevMagnifiedStyleMap.clear(),this.prevOriginStyleMap.clear(),super.destroy()}}rF.defaultOptions={trigger:"pointermove",r:120,d:1.5,maxD:5,minD:0,showDPercent:!0,style:{},nodeStyle:{label:!0},preventDefault:!0};class iF extends nB{constructor(t,e){super(t,Object.assign({},iF.defaultOptions,e)),this.$el=this.context.canvas.getContainer(),this.graphSize=[0,0],this.onFullscreenChange=()=>{var t,e,n,r;const i=!!document.fullscreenElement;this.options.autoFit&&this.setGraphSize(i),i?null===(e=(t=this.options).onEnter)||void 0===e||e.call(t):null===(r=(n=this.options).onExit)||void 0===r||r.call(n)},this.shortcut=new Sd(t.graph),this.bindEvents(),this.style=document.createElement("style"),document.head.appendChild(this.style),this.style.innerHTML="\n :not(:root):fullscreen::backdrop {\n background: transparent;\n }\n "}bindEvents(){this.unbindEvents(),this.shortcut.unbindAll();const{request:t=[],exit:e=[]}=this.options.trigger;this.shortcut.bind(t,this.request),this.shortcut.bind(e,this.exit);["webkitfullscreenchange","mozfullscreenchange","fullscreenchange","MSFullscreenChange"].forEach((t=>{document.addEventListener(t,this.onFullscreenChange,!1)}))}unbindEvents(){this.shortcut.unbindAll();["webkitfullscreenchange","mozfullscreenchange","fullscreenchange","MSFullscreenChange"].forEach((t=>{document.removeEventListener(t,this.onFullscreenChange,!1)}))}setGraphSize(t=!0){var e,n;let r,i;t?(r=(null===(e=globalThis.screen)||void 0===e?void 0:e.width)||0,i=(null===(n=globalThis.screen)||void 0===n?void 0:n.height)||0,this.graphSize=this.context.graph.getSize()):[r,i]=this.graphSize,this.context.graph.setSize(r,i),this.context.graph.render()}request(){!document.fullscreenElement&&(document.fullscreenEnabled||Reflect.get(document,"webkitFullscreenEnabled")||Reflect.get(document,"mozFullscreenEnabled")||Reflect.get(document,"msFullscreenEnabled"))&&this.$el.requestFullscreen().catch((t=>{Ic(`Error attempting to enable full-screen: ${t.message} (${t.name})`)}))}exit(){document.fullscreenElement&&document.exitFullscreen()}update(t){this.unbindEvents(),super.update(t),this.bindEvents()}destroy(){this.exit(),this.style.remove(),super.destroy()}}iF.defaultOptions={trigger:{},autoFit:!0};class oF extends nB{constructor(t,e){super(t,Object.assign({},oF.defaultOptions,e)),this.$element=rB("grid-line",!0),this.offset=[0,0],this.currentScale=1,this.followZoom=t=>{const{data:{scale:e,origin:n}}=t;if(!e)return;const r=this.currentScale;this.currentScale=e;const i=e/r,o=$h(n||this.context.graph.getCanvasCenter(),1-i),a=this.baseSize*e,s=Hh(td($h(this.offset,i),a),o);this.$element.style.backgroundSize=`${a}px ${a}px`,this.$element.style.backgroundPosition=`${s[0]}px ${s[1]}px`,this.offset=td(s,a)},this.followTranslate=t=>{if(!this.options.follow)return;const{data:{translate:e}}=t;e&&this.updateOffset(e)},this.onTransform=t=>{const e=this.parseFollow(this.options.follow);e.zoom&&this.followZoom(t),e.translate&&this.followTranslate(t)};this.context.canvas.getContainer().prepend(this.$element),this.baseSize=this.options.size,this.updateStyle(),this.bindEvents()}update(t){super.update(t),void 0!==t.size&&(this.baseSize=t.size),this.updateStyle()}bindEvents(){const{graph:e}=this.context;e.on(t.GraphEvent.AFTER_TRANSFORM,this.onTransform)}updateStyle(){const{stroke:t,lineWidth:e,border:n,borderLineWidth:r,borderStroke:i,borderStyle:o}=this.options,a=this.baseSize*this.currentScale;Object.assign(this.$element.style,{border:n?`${r}px ${o} ${i}`:"none",backgroundImage:`linear-gradient(${t} ${e}px, transparent ${e}px), linear-gradient(90deg, ${t} ${e}px, transparent ${e}px)`,backgroundSize:`${a}px ${a}px`,backgroundRepeat:"repeat"})}updateOffset(t){const e=this.baseSize*this.currentScale;this.offset=td(Hh(this.offset,t),e),this.$element.style.backgroundPosition=`${this.offset[0]}px ${this.offset[1]}px`}parseFollow(t){var e,n;return pe(t)?{translate:t,zoom:t}:{translate:null!==(e=null==t?void 0:t.translate)&&void 0!==e&&e,zoom:null!==(n=null==t?void 0:t.zoom)&&void 0!==n&&n}}destroy(){this.context.graph.off(t.GraphEvent.AFTER_TRANSFORM,this.onTransform),this.$element.remove(),super.destroy()}}function aF(t){const e={Added:new Map,Updated:new Map,Removed:new Map};return t.forEach((t=>{const{type:n,value:r}=t,i=Nh(r);if("NodeAdded"===n||"EdgeAdded"===n||"ComboAdded"===n)e.Added.set(i,t);else if("NodeUpdated"===n||"EdgeUpdated"===n||"ComboUpdated"===n)if(e.Added.has(i))e.Added.set(i,{type:n.replace("Updated","Added"),value:r});else if(e.Updated.has(i)){const{original:t}=e.Updated.get(i);e.Updated.set(i,{type:n,value:r,original:t})}else e.Removed.has(i)||e.Updated.set(i,t);else"NodeRemoved"!==n&&"EdgeRemoved"!==n&&"ComboRemoved"!==n||(e.Added.has(i)?e.Added.delete(i):e.Updated.has(i)?(e.Updated.delete(i),e.Removed.set(i,t)):e.Removed.set(i,t))})),[...Array.from(e.Added.values()),...Array.from(e.Updated.values()),...Array.from(e.Removed.values())]}function sF(t){const{NodeAdded:e=[],NodeUpdated:n=[],NodeRemoved:r=[],EdgeAdded:i=[],EdgeUpdated:o=[],EdgeRemoved:a=[],ComboAdded:s=[],ComboUpdated:l=[],ComboRemoved:u=[]}=ie(t,(t=>t.type));return{add:{nodes:e,edges:i,combos:s},update:{nodes:n,edges:o,combos:l},remove:{nodes:r,edges:a,combos:u}}}function lF(t,e){for(const n in t)qt(t[n])&&!Array.isArray(t[n])&&null!==t[n]?(e[n]||(e[n]={}),lF(t[n],e[n])):void 0===e[n]&&(e[n]=zc(n))}function uF(t,e=!1,n){const r={animation:e,current:{add:{},update:{},remove:{}},original:{add:{},update:{},remove:{}}},{add:i,update:o,remove:a}=sF(aF(t));return["nodes","edges","combos"].forEach((t=>{o[t]&&o[t].forEach((e=>{var i,o;const a=Object.assign({},e.value);let s=Object.assign({},e.original);if(n){const t=n.graph.getElementType(Nh(e.original)),r="edge"===t?"stroke":"fill",i=n.element.getElementComputedStyle(t,e.original);s=Object.assign(Object.assign({},e.original),{style:Object.assign({[r]:i[r]},e.original.style)})}lF(a,s),(i=r.current.update)[t]||(i[t]=[]),r.current.update[t].push(a),(o=r.original.update)[t]||(o[t]=[]),r.original.update[t].push(s)})),i[t]&&i[t].forEach((e=>{var n,i;const o=Object.assign({},e.value);(n=r.current.add)[t]||(n[t]=[]),r.current.add[t].push(o),(i=r.original.remove)[t]||(i[t]=[]),r.original.remove[t].push(o)})),a[t]&&a[t].forEach((e=>{var n,i;const o=Object.assign({},e.value);(n=r.current.remove)[t]||(n[t]=[]),r.current.remove[t].push(o),(i=r.original.add)[t]||(i[t]=[]),r.original.add[t].push(o)}))})),r}oF.defaultOptions={border:!0,borderLineWidth:1,borderStroke:"#eee",borderStyle:"solid",lineWidth:1,size:20,stroke:"#eee"};class cF extends nB{constructor(e,n){super(e,Object.assign({},cF.defaultOptions,n)),this.batchChanges=null,this.batchAnimation=!1,this.undoStack=[],this.redoStack=[],this.freezed=!1,this.executeCommand=(t,e=!0)=>{var n,r,i;this.freezed=!0,null===(r=(n=this.options).executeCommand)||void 0===r||r.call(n,t);const o=e?t.original:t.current;this.context.graph.addData(o.add),this.context.graph.updateData(o.update),this.context.graph.removeData(Th(o.remove,!1)),null===(i=this.context.element)||void 0===i||i.draw({silence:!0,animation:t.animation}),this.freezed=!1},this.addCommand=e=>{var n;if(!this.freezed){if(e.type===t.GraphEvent.AFTER_DRAW){const{dataChanges:t=[],animation:r=!0}=e.data;if(null===(n=this.context.batch)||void 0===n?void 0:n.isBatching){if(!this.batchChanges)return;return this.batchChanges.push(t),void(this.batchAnimation&&(this.batchAnimation=r))}this.batchChanges=[t],this.batchAnimation=r}this.undoStackPush(uF(this.batchChanges.flat(),this.batchAnimation,this.context)),this.notify(t.HistoryEvent.ADD,this.undoStack[this.undoStack.length-1])}},this.initBatchCommand=t=>{const{initiate:e}=t.data;if(this.batchAnimation=!1,e)this.batchChanges=[];else{this.undoStack.pop()||(this.batchChanges=null)}},this.emitter=new Kg;const{graph:r}=this.context;r.on(t.GraphEvent.AFTER_DRAW,this.addCommand),r.on(t.GraphEvent.BATCH_START,this.initBatchCommand),r.on(t.GraphEvent.BATCH_END,this.addCommand)}canUndo(){return this.undoStack.length>0}canRedo(){return this.redoStack.length>0}undo(){var e,n,r,i;const o=this.undoStack.pop();if(o){this.executeCommand(o);if(!1===(null===(n=(e=this.options).beforeAddCommand)||void 0===n?void 0:n.call(e,o,!1)))return;this.redoStack.push(o),null===(i=(r=this.options).afterAddCommand)||void 0===i||i.call(r,o,!1),this.notify(t.HistoryEvent.UNDO,o)}return this}redo(){const e=this.redoStack.pop();return e&&(this.executeCommand(e,!1),this.undoStackPush(e),this.notify(t.HistoryEvent.REDO,e)),this}undoAndCancel(){const e=this.undoStack.pop();return e&&(this.executeCommand(e,!1),this.redoStack=[],this.notify(t.HistoryEvent.CANCEL,e)),this}undoStackPush(t){var e,n,r,i;const{stackSize:o}=this.options;0!==o&&this.undoStack.length>=o&&this.undoStack.shift();!1!==(null===(n=(e=this.options).beforeAddCommand)||void 0===n?void 0:n.call(e,t,!0))&&(this.undoStack.push(t),null===(i=(r=this.options).afterAddCommand)||void 0===i||i.call(r,t,!0))}clear(){this.undoStack=[],this.redoStack=[],this.batchChanges=null,this.batchAnimation=!1,this.notify(t.HistoryEvent.CLEAR,null)}notify(e,n){this.emitter.emit(e,{cmd:n}),this.emitter.emit(t.HistoryEvent.CHANGE,{cmd:n})}on(t,e){this.emitter.on(t,e)}destroy(){const{graph:e}=this.context;e.off(t.GraphEvent.AFTER_DRAW,this.addCommand),e.off(t.GraphEvent.BATCH_START,this.initBatchCommand),e.off(t.GraphEvent.BATCH_END,this.addCommand),this.emitter.off(),super.destroy(),this.undoStack=[],this.redoStack=[]}}cF.defaultOptions={stackSize:0};const hF={toXy(t,e){if(!e)return[...t];const n=e[0].slice(1),r=e[1].slice(1);return t.map((t=>[t[n],t[r]]))},fromXy(t,e){if(!e)return[...t];const n=e[0].slice(1),r=e[1].slice(1);return t.map((([t,e])=>({[n]:t,[r]:e})))}};let dF=class{constructor(t,e){this._cells=[],this._cellSize=e,this._reverseCellSize=1/e;for(const e of t){const t=this.coordToCellNum(e[0]),n=this.coordToCellNum(e[1]);this._cells[t]||(this._cells[t]=[]),this._cells[t][n]||(this._cells[t][n]=[]),this._cells[t][n].push(e)}}cellPoints(t,e){var n;return(null===(n=this._cells[t])||void 0===n?void 0:n[e])||[]}rangePoints(t){const e=this.coordToCellNum(t[0]),n=this.coordToCellNum(t[1]),r=this.coordToCellNum(t[2]),i=this.coordToCellNum(t[3]),o=[];for(let t=e;t<=r;t++)for(let e=n;e<=i;e++){const n=this.cellPoints(t,e);for(const t of n)o.push(t)}return o}removePoint(t){const e=this.coordToCellNum(t[0]),n=this.coordToCellNum(t[1]),r=this._cells[e][n],i=r.findIndex((([e,n])=>e===t[0]&&n===t[1]));return i>-1&&r.splice(i,1),r}trunc(t){return Math.trunc(t)}coordToCellNum(t){return this.trunc(t*this._reverseCellSize)}extendBbox(t,e){return[t[0]-e*this._cellSize,t[1]-e*this._cellSize,t[2]+e*this._cellSize,t[3]+e*this._cellSize]}};const fF=+(Math.pow(2,27)+1);function pF(t,e,n){const r=t*e,i=fF*t,o=i-(i-t),a=t-o,s=fF*e,l=s-(s-e),u=e-l,c=a*u-(r-o*l-a*l-o*u);return n?(n[0]=c,n[1]=r,n):[c,r]}function gF(t,e,n){const r=t+e,i=r-t,o=e-i,a=t-(r-i);return n?(n[0]=a+o,n[1]=r,n):[a+o,r]}function vF(t,e){const n=t.length;if(1===n){const n=pF(t[0],e);return n[0]?n:[n[1]]}const r=new Array(2*n),i=[.1,.1],o=[.1,.1];let a=0;pF(t[0],e,i),i[0]&&(r[a++]=i[0]);for(let s=1;s=r?(u=h,a+=1,a=r?(u=h,a+=1,a0){if(i<=0)return o;a=r+i}else{if(!(r<0))return o;if(i>=0)return o;a=-(r+i)}const s=33306690738754716e-32*a;return o>=s||o<=-s?o:kF(t,e,n)},function(t,e,n,r){const i=t[0]-r[0],o=e[0]-r[0],a=n[0]-r[0],s=t[1]-r[1],l=e[1]-r[1],u=n[1]-r[1],c=t[2]-r[2],h=e[2]-r[2],d=n[2]-r[2],f=o*u,p=a*l,g=a*s,v=i*u,m=i*l,y=o*s,b=c*(f-p)+h*(g-v)+d*(m-y),x=7771561172376103e-31*((Math.abs(f)+Math.abs(p))*Math.abs(c)+(Math.abs(g)+Math.abs(v))*Math.abs(h)+(Math.abs(m)+Math.abs(y))*Math.abs(d));return b>x||-b>x?b:MF(t,e,n,r)}];function NF(t){let e=SF[t.length];return e||(e=SF[t.length]=wF(t.length)),e.apply(void 0,...t)}var OF=function(){for(;SF.length<=5;)SF.push(wF(SF.length));const t=function(t,e,n,r,i,o,a){return function(...e){switch(e.length){case 0:case 1:return 0;case 2:return r(e[0],e[1]);case 3:return i(e[0],e[1],e[2]);case 4:return o(e[0],e[1],e[2],e[3]);case 5:return a(e[0],e[1],e[2],e[3],e[4])}return t(e)}}(void 0,NF,...SF);for(let e=0;e<=5;++e)t[e]=SF[e];return t}();const TF=OF[3];function CF(t,e,n,r){const i=OF(t,n,r),o=OF(e,n,r);if(i>0&&o>0||i<0&&o<0)return!1;const a=OF(n,t,e),s=OF(r,t,e);return!(a>0&&s>0||a<0&&s<0)&&(0!==i||0!==o||0!==a||0!==s||function(t,e,n,r){for(let i=0;i<2;++i){const o=t[i],a=e[i],[s,l]=[Math.min(o,a),Math.max(o,a)],u=n[i],c=r[i],[h,d]=[Math.min(u,c),Math.max(u,c)];if(da&&i>s&&!RF([t[0],e[l]],n)&&!RF([t[1],e[l]],n)&&(a=r,s=i,o=e[l]);return o}function _F(t,e,n,r,i){let o=!1;for(let a=0;au||n[1]>c));u>=n[0]&&c>=n[1]&&i.add(l),null!==h&&(t.splice(a+1,0,h),r.removePoint(h),o=!0)}return o?_F(t,e,n,r,i):t}function IF(t,e,n){const r=e||20,i=function(t){const e=[t[0]];let n=t[0];for(let r=1;r=0;o--)t[o][0]r&&(r=t[o][0]),t[o][1]>i&&(i=t[o][1]);return[r-e,i-n]}(i),a=[o[0]*BF,o[1]*BF],s=function(t){const e=t.length;if(e<3){const n=new Array(e);for(let t=0;tt[e][0]-t[n][0]||t[e][1]-t[n][1]));const r=[n[0],n[1]],i=[n[0],n[1]];for(let o=2;o1&&TF(t[r[s-2]],t[r[s-1]],a)<=0;)s-=1,r.pop();for(r.push(e),s=i.length;s>1&&TF(t[i[s-2]],t[i[s-1]],a)>=0;)s-=1,i.pop();i.push(e)}const o=new Array(i.length+r.length-2);let a=0;for(let t=0,e=r.length;t0;--t)o[a++]=i[t];return o}(i).reverse().map((t=>i[t]));s.push(s[0]);const l=i.filter((function(t){return s.indexOf(t)<0})),u=Math.ceil(1/(i.length/(o[0]*o[1]))),c=_F(s,Math.pow(r,2),a,function(t,e){return new dF(t,e)}(l,u),new Set);return n?hF.fromXy(c,n):c}const jF=Math.cos(90/(180/Math.PI)),BF=.6;const FF=(t,e,n)=>{if("sharp"===n)return[["M",t[0]-e,t[1]-e],["L",t[0]+e,t[1]-e],["L",t[0]+e,t[1]+e],["L",t[0]-e,t[1]+e],["Z"]];const r=[e,e,0,0,0];return[["M",t[0],t[1]-e],["A",...r,t[0],t[1]+e],["A",...r,t[0],t[1]-e]]},zF=(t,e,n)=>{const r=[e,e,0,0,0],i="sharp"===n?Hh(t[0],qh(Zh(Uh(t[0],t[1])),e)):t[0],o="sharp"===n?Hh(t[1],qh(Zh(Uh(t[1],t[0])),e)):t[1],a=qh(Zh(Jh(Uh(i,o),!1)),e),s=qh(a,-1),l=Hh(i,a),u=Hh(o,a),c=Hh(o,s),h=Hh(i,s);return"sharp"===n?[["M",l[0],l[1]],["L",u[0],u[1]],["L",c[0],c[1]],["L",h[0],h[1]],["Z"]]:[["M",l[0],l[1]],["L",u[0],u[1]],["A",...r,c[0],c[1]],["L",h[0],h[1]],["A",...r,l[0],l[1]]]},GF=(t,e)=>{const n=Ed(t).map(((n,r)=>{const i=(r-2+t.length)%t.length,o=(r-1+t.length)%t.length,a=(r+1)%t.length,s=t[i],l=t[o],u=t[a],c=Uh(s,l),h=Uh(l,n),d=Uh(n,u),f=(t,e)=>Qh(t,e,!0)qh(Zh(Jh(t,!1)),e),m=v(h);return[{p:ed(Hh(l,p?v(c):m)),concave:p&&l},{p:ed(Hh(n,g?v(d):m)),concave:g&&n}]})),r=[e,e,0,0,0],i=n.findIndex(((t,e)=>!(n[(e-1+n.length)%n.length][0].concave||n[(e-1+n.length)%n.length][1].concave||t[0].concave||t[0].concave||t[1].concave))),o=n.slice(i).concat(n.slice(0,i));let a=[];return o.flatMap(((t,e)=>{const i=[],s=o[n.length-1];return 0===e&&i.push(["M",...s[1].p]),t[0].concave?a.push(t[0].p,t[1].p):i.push(["A",...r,...t[0].p]),t[1].concave?a.unshift(t[1].p):i.push(["L",...t[1].p]),3===a.length&&(i.pop(),i.push(["C",...a.flat()]),a=[]),i}))},VF=(t,e)=>{const n=Ed(t).map(((e,n)=>({p:e,v:Zh(Uh(t[(n+1)%t.length],e))})));return n.forEach(((r,i)=>{const o=i>0?i-1:t.length-1,a=n[o].v,s=Zh(Hh(a,qh(r.v,Qh(a,r.v,!0)t.p)))},WF=(t,e)=>{const n=t.map(((n,r)=>{const i=t[0===r?t.length-1:r-1],o=nd(qh(Zh(Jh(Uh(i,n),!1)),e));return[Hh(i,o),Hh(n,o)]})),r=n.flat();return r.map(((t,e)=>{if(e%2==0)return null;return od([r[(e-1)%r.length],r[e%r.length]],[r[(e+1)%r.length],r[(e+2)%r.length]],!0)})).filter(Boolean).map(((t,e)=>[0===e?"M":"L",t[0],t[1]])).concat([["Z"]])};class HF extends nB{constructor(t,e){super(t,Object.assign({},HF.defaultOptions,e)),this.hullMemberIds=[],this.drawHull=()=>{if(this.shape){const t=!Ne(this.optionsCache,this.options);this.shape.update(this.getHullStyle(t))}else this.shape=new nf({style:this.getHullStyle()}),this.context.canvas.appendChild(this.shape);this.optionsCache=Object.assign({},this.options)},this.updateHullPath=t=>{this.shape&&this.options.members.includes(Nh(t.data))&&this.shape.update({d:this.getHullPath(!0)})},this.getHullPath=(t=!1)=>{const{graph:e}=this.context,n=this.getMember();if(0===n.length)return"";const r=n.map((t=>e.getNodeData(t))),i=IF(r.map(sd),this.options.concavity).slice(1).reverse(),o=i.flatMap((t=>r.filter((e=>Ne(sd(e),t))).map(Nh)));return Ne(o,this.hullMemberIds)&&!t||(this.hullMemberIds=o,this.path=function(t,e,n){if(1===t.length)return FF(t[0],e,n);if(2===t.length)return zF(t,e,n);if(3===t.length){const[r,i,o]=Ed(t);if(gd(r,i,o))return zF([r,o],e,n)}switch(n){case"smooth":return VF(t,e);case"sharp":return WF(t,e);default:return GF(t,e)}}(i,this.getPadding(),this.options.corner)),this.path},this.bindEvents()}bindEvents(){this.context.graph.on(t.GraphEvent.AFTER_RENDER,this.drawHull),this.context.graph.on(t.GraphEvent.AFTER_ELEMENT_UPDATE,this.updateHullPath)}getHullStyle(t){const e=this.options,{members:n,padding:r,corner:i}=e,o=Fe(e,["members","padding","corner"]);return Object.assign(Object.assign({},o),{d:this.getHullPath(t)})}getPadding(){const{graph:t}=this.context,e=this.hullMemberIds.reduce(((e,n)=>{const{halfExtents:r}=t.getElementRenderBounds(n),i=Math.max(r[0],r[1]);return Math.max(e,i)}),0);return e+this.options.padding}addMember(t){const e=Array.isArray(t)?t:[t];this.options.members=[...new Set([...this.options.members,...e])],this.shape.update({d:this.getHullPath()})}removeMember(t){const e=Array.isArray(t)?t:[t];this.options.members=this.options.members.filter((t=>!e.includes(t))),e.some((t=>this.hullMemberIds.includes(t)))&&this.shape.update({d:this.getHullPath()})}updateMember(t){this.options.members=Ut(t)?t(this.options.members):t,this.shape.update(this.getHullStyle(!0))}getMember(){return this.options.members}destroy(){this.context.graph.off(t.GraphEvent.AFTER_DRAW,this.drawHull),this.shape.destroy(),this.hullMemberIds=[],super.destroy()}}function UF(t,e){e(t),t.children&&t.children.forEach((function(t){t&&UF(t,e)}))}function $F(t){qF(t,!0)}function YF(t){qF(t,!1)}function qF(t,e){var n=e?"visible":"hidden";UF(t,(function(t){t.attr("visibility",n)}))}HF.defaultOptions={members:[],padding:10,corner:"rounded",concavity:1/0,fill:"lightblue",fillOpacity:.2,labelOpacity:1,stroke:"blue",strokeOpacity:.2};var XF=function(t){function e(){for(var e=[],n=0;n=this.left&&t<=this.right&&e>=this.top&&e<=this.bottom},t}();function ez(t,e){return Ut(t)?t.apply(void 0,We([],Ve(e),!1)):t}var nz,rz=function(t,e){var n=function(t){return"".concat(e,"-").concat(t)},r=Object.fromEntries(Object.entries(t).map((function(t){var e=Ve(t,2),r=e[0],i=e[1],o=n(i);return[r,{name:o,class:".".concat(o),id:"#".concat(o),toString:function(){return o}}]})));return Object.assign(r,{prefix:n}),r},iz=function(t,e,n,r){void 0===n&&(n=0),void 0===r&&(r=5),Object.entries(e).forEach((function(i){var o=Ve(i,2),a=o[0],s=o[1],l=t;Object.prototype.hasOwnProperty.call(e,a)&&(s?Jt(s)?(Jt(t[a])||(l[a]={}),ne&&t="A"&&n<="Z"};function Fz(t,e,n){void 0===n&&(n=!1);var r={};return Object.entries(t).forEach((function(t){var i=Ve(t,2),o=i[0],a=i[1];if("className"===o||"class"===o);else if(Bz(o,"show")&&Bz(jz(o,"show"),e)!==n)o===function(t,e){return"".concat(e).concat(Iz(t))}(e,"show")?r[o]=a:r[o.replace(new RegExp(Iz(e)),"")]=a;else if(!Bz(o,"show")&&Bz(o,e)!==n){var s=jz(o,e);"filter"===s&&"function"==typeof a||(r[s]=a)}})),r}function zz(t,e){return Object.entries(t).reduce((function(t,n){var r=Ve(n,2),i=r[0],o=r[1];return i.startsWith("show")?t["show".concat(e).concat(i.slice(4))]=o:t["".concat(e).concat(Iz(i))]=o,t}),{})}function Gz(t,e){void 0===e&&(e=["x","y","class","className"]);var n=["transform","transformOrigin","anchor","visibility","pointerEvents","zIndex","cursor","clipPath","clipPathTargets","offsetPath","offsetPathTargets","offsetDistance","draggable","droppable"],r={},i={};return Object.entries(t).forEach((function(t){var o=Ve(t,2),a=o[0],s=o[1];e.includes(a)||(-1!==n.indexOf(a)?i[a]=s:r[a]=s)})),[r,i]}function Vz(t,e){var n={YYYY:t.getFullYear(),MM:t.getMonth()+1,DD:t.getDate(),HH:t.getHours(),mm:t.getMinutes(),ss:t.getSeconds()},r=e;return Object.keys(n).forEach((function(t){var e=n[t];r=r.replace(t,"YYYY"===t?"".concat(e):"".concat(e).padStart(2,"0"))})),r}function Wz(t,e){if(e)try{var n=e.replace(/translate\(([+-]*[\d]+[%]*),[ ]*([+-]*[\d]+[%]*)\)/g,(function(e,n,r){return"translate(".concat(function(t,e,n){var r=t.getBBox(),i=r.width,o=r.height,a=Ve([e,n].map((function(t,e){var n;return t.includes("%")?parseFloat((null===(n=t.match(/[+-]?([0-9]*[.])?[0-9]+/))||void 0===n?void 0:n[0])||"0")/100*(0===e?i:o):t})),2);return[a[0],a[1]]}(t,n,r),")")}));t.attr("transform",n)}catch(t){}}var Hz=function(t,e){null!=e?t.replaceChildren?Array.isArray(e)?t.replaceChildren.apply(t,We([],Ve(e),!1)):t.replaceChildren(e):(t.innerHTML="",Array.isArray(e)?e.forEach((function(e){return t.appendChild(e)})):t.appendChild(e)):t.innerHTML=""};function Uz(){qF(this,"hidden"!==this.attributes.visibility)}var $z=function(t){function e(e,n){void 0===n&&(n={});var r=t.call(this,oz({},{style:n},e))||this;return r.initialized=!1,r._defaultOptions=n,r}return je(e,t),Object.defineProperty(e.prototype,"offscreenGroup",{get:function(){return this._offscreen||(this._offscreen=KF(this)),this._offscreen},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"defaultOptions",{get:function(){return this._defaultOptions},enumerable:!1,configurable:!0}),e.prototype.connectedCallback=function(){this.render(this.attributes,this),this.bindEvents(this.attributes,this),this.initialized=!0},e.prototype.disconnectedCallback=function(){var t;null===(t=this._offscreen)||void 0===t||t.destroy()},e.prototype.attributeChangedCallback=function(t){"visibility"===t&&Uz.call(this)},e.prototype.update=function(t,e){var n;return this.attr(oz({},this.attributes,t||{})),null===(n=this.render)||void 0===n?void 0:n.call(this,this.attributes,this,e)},e.prototype.clear=function(){this.removeChildren()},e.prototype.bindEvents=function(t,e){},e.prototype.getSubShapeStyle=function(t){return t.x,t.y,t.transform,t.transformOrigin,t.class,t.className,t.zIndex,Fe(t,["x","y","transform","transformOrigin","class","className","zIndex"])},e}(Wl),Yz=function(t,e,n){return[["M",t-n,e],["A",n,n,0,1,0,t+n,e],["A",n,n,0,1,0,t-n,e],["Z"]]},qz=Yz,Xz=function(t,e,n){return[["M",t,e+n],["L",t,e-n]]},Kz=function(t,e,n){return[["M",t-n,e],["L",t+n,e]]},Zz=Kz;var Qz=function(t,e,n){return[["M",t-n,e-n],["L",t+n,e],["L",t-n,e+n],["Z"]]};function Jz(t){var e=function(t){var e="default";if(qt(t)&&t instanceof Image)e="image";else if(Ut(t))e="symbol";else if(ne(t)){var n=new RegExp("data:(image|text)");e=t.match(n)?"base64":/^(https?:\/\/(([a-zA-Z0-9]+-?)+[a-zA-Z0-9]+\.)+[a-zA-Z]+)(:\d+)?(\/.*)?(\?.*)?(#.*)?$/.test(t)?"url":"symbol"}return e}(t);return["base64","url","image"].includes(e)?"image":t&&"symbol"===e?"path":null}var tG=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return je(e,t),e.prototype.render=function(t,n){var r=t.x,i=void 0===r?0:r,o=t.y,a=void 0===o?0:o,s=this.getSubShapeStyle(t),l=s.symbol,u=s.size,c=void 0===u?16:u,h=Fe(s,["symbol","size"]),d=Jz(l);pz(!!d,Rz(n),(function(t){t.maybeAppendByClassName("marker",d).attr("className","marker ".concat(d,"-marker")).call((function(t){if("image"===d){var n=2*c;t.styles({img:l,width:n,height:n,x:i-c,y:a-c})}else{n=c/2;var r=Ut(l)?l:e.getSymbol(l);t.styles(Be({d:null==r?void 0:r(i,a,n)},h))}}))}))},e.MARKER_SYMBOL_MAP=new Map,e.registerSymbol=function(t,n){e.MARKER_SYMBOL_MAP.set(t,n)},e.getSymbol=function(t){return e.MARKER_SYMBOL_MAP.get(t)},e.getSymbols=function(){return Array.from(e.MARKER_SYMBOL_MAP.keys())},e}($z);function eG(t,...e){return e.reduce(((t,e)=>n=>t(e(n))),t)}function nG(t,e){return e-t?n=>(n-t)/(e-t):t=>.5}tG.registerSymbol("cross",(function(t,e,n){return[["M",t-n,e-n],["L",t+n,e+n],["M",t+n,e-n],["L",t-n,e+n]]})),tG.registerSymbol("hyphen",(function(t,e,n){return[["M",t-n,e],["L",t+n,e]]})),tG.registerSymbol("line",Xz),tG.registerSymbol("plus",(function(t,e,n){return[["M",t-n,e],["L",t+n,e],["M",t,e-n],["L",t,e+n]]})),tG.registerSymbol("tick",(function(t,e,n){return[["M",t-n/2,e-n],["L",t+n/2,e-n],["M",t,e-n],["L",t,e+n],["M",t-n/2,e+n],["L",t+n/2,e+n]]})),tG.registerSymbol("circle",Yz),tG.registerSymbol("point",qz),tG.registerSymbol("bowtie",(function(t,e,n){var r=n-1.5;return[["M",t-n,e-r],["L",t+n,e+r],["L",t+n,e-r],["L",t-n,e+r],["Z"]]})),tG.registerSymbol("hexagon",(function(t,e,n){var r=n/2*Math.sqrt(3);return[["M",t,e-n],["L",t+r,e-n/2],["L",t+r,e+n/2],["L",t,e+n],["L",t-r,e+n/2],["L",t-r,e-n/2],["Z"]]})),tG.registerSymbol("square",(function(t,e,n){return[["M",t-n,e-n],["L",t+n,e-n],["L",t+n,e+n],["L",t-n,e+n],["Z"]]})),tG.registerSymbol("diamond",(function(t,e,n){return[["M",t-n,e],["L",t,e-n],["L",t+n,e],["L",t,e+n],["Z"]]})),tG.registerSymbol("triangle",(function(t,e,n){var r=n*Math.sin(1/3*Math.PI);return[["M",t-n,e+r],["L",t,e-r],["L",t+n,e+r],["Z"]]})),tG.registerSymbol("triangle-down",(function(t,e,n){var r=n*Math.sin(1/3*Math.PI);return[["M",t-n,e-r],["L",t+n,e-r],["L",t,e+r],["Z"]]})),tG.registerSymbol("line",Xz),tG.registerSymbol("dot",Kz),tG.registerSymbol("dash",Zz),tG.registerSymbol("smooth",(function(t,e,n){return[["M",t-n,e],["A",n/2,n/2,0,1,1,t,e],["A",n/2,n/2,0,1,0,t+n,e]]})),tG.registerSymbol("hv",(function(t,e,n){return[["M",t-n-1,e-2.5],["L",t,e-2.5],["L",t,e+2.5],["L",t+n+1,e+2.5]]})),tG.registerSymbol("vh",(function(t,e,n){return[["M",t-n-1,e+2.5],["L",t,e+2.5],["L",t,e-2.5],["L",t+n+1,e-2.5]]})),tG.registerSymbol("hvh",(function(t,e,n){return[["M",t-(n+1),e+2.5],["L",t-n/2,e+2.5],["L",t-n/2,e-2.5],["L",t+n/2,e-2.5],["L",t+n/2,e+2.5],["L",t+n+1,e+2.5]]})),tG.registerSymbol("vhv",(function(t,e){return[["M",t-5,e+2.5],["L",t-5,e],["L",t,e],["L",t,e-3],["L",t,e+3],["L",t+6.5,e+3]]}));const rG=Math.sqrt(50),iG=Math.sqrt(10),oG=Math.sqrt(2);function aG(t,e,n){const r=(e-t)/Math.max(0,n),i=Math.floor(Math.log(r)/Math.LN10),o=r/10**i;return i>=0?(o>=rG?10:o>=iG?5:o>=oG?2:1)*10**i:-(10**-i)/(o>=rG?10:o>=iG?5:o>=oG?2:1)}const sG=(t,e,n=5)=>{const r=[t,e];let i,o=0,a=r.length-1,s=r[o],l=r[a];return l0?(s=Math.floor(s/i)*i,l=Math.ceil(l/i)*i,i=aG(s,l,n)):i<0&&(s=Math.ceil(s*i)/i,l=Math.floor(l*i)/i,i=aG(s,l,n)),i>0?(r[o]=Math.floor(s/i)*i,r[a]=Math.ceil(l/i)*i):i<0&&(r[o]=Math.ceil(s*i)/i,r[a]=Math.floor(l*i)/i),r};function lG(t){return!(ve(t)||(e=t,null===e)||Number.isNaN(t));var e}var uG={exports:{}},cG={exports:{}},hG=function(t){return!(!t||"string"==typeof t)&&(t instanceof Array||Array.isArray(t)||t.length>=0&&(t.splice instanceof Function||Object.getOwnPropertyDescriptor(t,t.length-1)&&"String"!==t.constructor.name))},dG=Array.prototype.concat,fG=Array.prototype.slice,pG=cG.exports=function(t){for(var e=[],n=0,r=t.length;n=4&&1!==t[3]&&(e=", "+t[3]),"hwb("+t[0]+", "+t[1]+"%, "+t[2]+"%"+e+")"},EG.to.keyword=function(t){return bG[t.slice(0,3)]};var MG=E(uG.exports);function SG(t,e,n){let r=n;return r<0&&(r+=1),r>1&&(r-=1),r<1/6?t+6*(e-t)*r:r<.5?e:r<2/3?t+(e-t)*(2/3-r)*6:t}function NG(t){const e=MG.get(t);if(!e)return null;const{model:n,value:r}=e;return"rgb"===n?r:"hsl"===n?function(t){const e=t[0]/360,n=t[1]/100,r=t[2]/100,i=t[3];if(0===n)return[255*r,255*r,255*r,i];const o=r<.5?r*(1+n):r+n-r*n,a=2*r-o;return[255*SG(a,o,e+1/3),255*SG(a,o,e),255*SG(a,o,e-1/3),i]}(r):null}const OG=(t,e)=>n=>t*(1-n)+e*n,TG=(t,e)=>"number"==typeof t&&"number"==typeof e?OG(t,e):"string"==typeof t&&"string"==typeof e?((t,e)=>{const n=NG(t),r=NG(e);return null===n||null===r?n?()=>t:()=>e:t=>{const e=new Array(4);for(let i=0;i<4;i+=1){const o=n[i],a=r[i];e[i]=o*(1-t)+a*t}const[i,o,a,s]=e;return`rgba(${Math.round(i)}, ${Math.round(o)}, ${Math.round(a)}, ${s})`}})(t,e):()=>t,CG=(t,e)=>{const n=OG(t,e);return t=>Math.round(n(t))};function AG({map:t,initKey:e},n){const r=e(n);return t.has(r)?t.get(r):n}function PG(t){return"object"==typeof t?t.valueOf():t}class RG extends Map{constructor(t){if(super(),this.map=new Map,this.initKey=PG,null!==t)for(const[e,n]of t)this.set(e,n)}get(t){return super.get(AG({map:this.map,initKey:this.initKey},t))}has(t){return super.has(AG({map:this.map,initKey:this.initKey},t))}set(t,e){return super.set(function({map:t,initKey:e},n){const r=e(n);return t.has(r)?t.get(r):(t.set(r,n),n)}({map:this.map,initKey:this.initKey},t),e)}delete(t){return super.delete(function({map:t,initKey:e},n){const r=e(n);return t.has(r)&&(n=t.get(r),t.delete(r)),n}({map:this.map,initKey:this.initKey},t))}}class DG{constructor(t){this.options=ke({},this.getDefaultOptions()),this.update(t)}getOptions(){return this.options}update(t={}){this.options=ke({},this.options,t),this.rescale(t)}rescale(t){}}const LG=Symbol("defaultUnknown");function _G(t,e,n){for(let r=0;r`${t}`:"object"==typeof t?t=>JSON.stringify(t):t=>t}class BG extends DG{getDefaultOptions(){return{domain:[],range:[],unknown:LG}}constructor(t){super(t)}map(t){return 0===this.domainIndexMap.size&&_G(this.domainIndexMap,this.getDomain(),this.domainKey),IG({value:this.domainKey(t),mapper:this.domainIndexMap,from:this.getDomain(),to:this.getRange(),notFoundReturn:this.options.unknown})}invert(t){return 0===this.rangeIndexMap.size&&_G(this.rangeIndexMap,this.getRange(),this.rangeKey),IG({value:this.rangeKey(t),mapper:this.rangeIndexMap,from:this.getRange(),to:this.getDomain(),notFoundReturn:this.options.unknown})}rescale(t){const[e]=this.options.domain,[n]=this.options.range;if(this.domainKey=jG(e),this.rangeKey=jG(n),!this.rangeIndexMap)return this.rangeIndexMap=new Map,void(this.domainIndexMap=new Map);t&&!t.range||this.rangeIndexMap.clear(),(!t||t.domain||t.compare)&&(this.domainIndexMap.clear(),this.sortedDomain=void 0)}clone(){return new BG(this.options)}getRange(){return this.options.range}getDomain(){if(this.sortedDomain)return this.sortedDomain;const{domain:t,compare:e}=this.options;return this.sortedDomain=e?[...t].sort(e):t,this.sortedDomain}}function FG(t){return Math.round(1e12*t)/1e12}function zG(t){const{domain:e,range:n,paddingOuter:r,paddingInner:i,flex:o,round:a,align:s}=t,l=e.length,u=function(t,e){const n=e-t.length;return n>0?[...t,...new Array(n).fill(1)]:n<0?t.slice(0,e):t}(o,l),[c,h]=n,d=h-c,f=d/(2/l*r+1-1/l*i),p=f*i/l,g=f-l*p,v=function(t){const e=Math.min(...t);return t.map((t=>t/e))}(u),m=g/v.reduce(((t,e)=>t+e)),y=new RG(e.map(((t,e)=>{const n=v[e]*m;return[t,a?Math.floor(n):n]}))),b=new RG(e.map(((t,e)=>{const n=v[e]*m+p;return[t,a?Math.floor(n):n]}))),x=Array.from(b.values()).reduce(((t,e)=>t+e)),E=c+(d-(x-x/l*i))*s;let w=a?Math.round(E):E;const k=new Array(l);for(let t=0;t0?t:e}getPaddingOuter(){const{padding:t,paddingOuter:e}=this.options;return t>0?t:e}rescale(){super.rescale();const{align:t,domain:e,range:n,round:r,flex:i}=this.options,{adjustedRange:o,valueBandWidth:a,valueStep:s}=function(t){var e;const{domain:n}=t,r=n.length;if(0===r)return{valueBandWidth:void 0,valueStep:void 0,adjustedRange:[]};if(null===(e=t.flex)||void 0===e?void 0:e.length)return zG(t);const{range:i,paddingOuter:o,paddingInner:a,round:s,align:l}=t;let u,c,h=i[0];const d=i[1]-h,f=2*o,p=r-a;u=d/Math.max(1,f+p),s&&(u=Math.floor(u)),h+=(d-u*(r-a))*l,c=u*(1-a),s&&(h=Math.round(h),c=Math.round(c));const g=new Array(r).fill(0).map(((t,e)=>h+e*u));return{valueStep:u,valueBandWidth:c,adjustedRange:g}}({align:t,range:n,round:r,flex:i,paddingInner:this.getPaddingInner(),paddingOuter:this.getPaddingOuter(),domain:e});this.valueStep=s,this.valueBandWidth=a,this.adjustedRange=o}}const VG=(t,e,n)=>{let r,i,o=t,a=e;if(o===a&&n>0)return[o];let s=aG(o,a,n);if(0===s||!Number.isFinite(s))return[];if(s>0){o=Math.ceil(o/s),a=Math.floor(a/s),i=new Array(r=Math.ceil(a-o+1));for(let t=0;t{const[r,i]=t,[o,a]=e;let s,l;return r{const r=Math.min(t.length,e.length)-1,i=new Array(r),o=new Array(r),a=t[0]>t[r],s=a?[...t].reverse():t,l=a?[...e].reverse():e;for(let t=0;t{const n=function(t,e,n,r){let i=n,o=r||t.length;for(;ie?o=n:i=n+1}return i}(t,e,1,r)-1,a=i[n];return eG(o[n],a)(e)}},UG=(t,e,n,r)=>(Math.min(t.length,e.length)>2?HG:WG)(t,e,r?CG:n);class $G extends DG{getDefaultOptions(){return{domain:[0,1],range:[0,1],nice:!1,clamp:!1,round:!1,interpolate:OG,tickCount:5}}map(t){return lG(t)?this.output(t):this.options.unknown}invert(t){return lG(t)?this.input(t):this.options.unknown}nice(){if(!this.options.nice)return;const[t,e,n,...r]=this.getTickMethodOptions();this.options.domain=this.chooseNice()(t,e,n,...r)}getTicks(){const{tickMethod:t}=this.options,[e,n,r,...i]=this.getTickMethodOptions();return t(e,n,r,...i)}getTickMethodOptions(){const{domain:t,tickCount:e}=this.options;return[t[0],t[t.length-1],e]}chooseNice(){return sG}rescale(){this.nice();const[t,e]=this.chooseTransforms();this.composeOutput(t,this.chooseClamp(t)),this.composeInput(t,e,this.chooseClamp(e))}chooseClamp(t){const{clamp:e,range:n}=this.options,r=this.options.domain.map(t),i=Math.min(r.length,n.length);return e?function(t,e){const n=ee?t:e;return t=>Math.min(Math.max(n,t),r)}(r[0],r[i-1]):_e}composeOutput(t,e){const{domain:n,range:r,round:i,interpolate:o}=this.options,a=UG(n.map(t),r,o,i);this.output=eG(a,e,t)}composeInput(t,e,n){const{domain:r,range:i}=this.options,o=UG(i,r.map(t),OG);this.input=eG(e,n,o)}}class YG extends $G{getDefaultOptions(){return{domain:[0,1],range:[0,1],unknown:void 0,nice:!1,clamp:!1,round:!1,interpolate:TG,tickMethod:VG,tickCount:5}}chooseTransforms(){return[_e,_e]}clone(){return new YG(this.options)}}var qG=function(t){function e(e){var n=this,r=e.style,i=Fe(e,["style"]);return(n=t.call(this,ke({},{type:"column"},Be({style:r},i)))||this).columnsGroup=new Ul({name:"columns"}),n.appendChild(n.columnsGroup),n.render(),n}return je(e,t),e.prototype.render=function(){var t=this.attributes,e=t.columns,n=t.x,r=t.y;this.columnsGroup.style.transform="translate(".concat(n,", ").concat(r,")"),Rz(this.columnsGroup).selectAll(".column").data(e.flat()).join((function(t){return t.append("rect").attr("className","column").each((function(t){this.attr(t)}))}),(function(t){return t.each((function(t){this.attr(t)}))}),(function(t){return t.remove()}))},e.prototype.update=function(t){this.attr(oz({},this.attributes,t)),this.render()},e.prototype.clear=function(){this.removeChildren()},e}(zl),XG=function(t){function e(e){var n=this,r=e.style,i=Fe(e,["style"]);return(n=t.call(this,ke({},{type:"lines"},Be({style:r},i)))||this).linesGroup=n.appendChild(new Ul),n.areasGroup=n.appendChild(new Ul),n.render(),n}return je(e,t),e.prototype.render=function(){var t=this.attributes,e=t.lines,n=t.areas,r=t.x,i=t.y;this.style.transform="translate(".concat(r,", ").concat(i,")"),e&&this.renderLines(e),n&&this.renderAreas(n)},e.prototype.clear=function(){this.linesGroup.removeChildren(),this.areasGroup.removeChildren()},e.prototype.update=function(t){this.attr(oz({},this.attributes,t)),this.render()},e.prototype.renderLines=function(t){Rz(this.linesGroup).selectAll(".line").data(t).join((function(t){return t.append("path").attr("className","line").each((function(t){this.attr(t)}))}),(function(t){return t.each((function(t){this.attr(t)}))}),(function(t){return t.remove()}))},e.prototype.renderAreas=function(t){Rz(this.linesGroup).selectAll(".area").data(t).join((function(t){return t.append("path").attr("className","area").each((function(t){this.attr(t)}))}),(function(t){return t.each((function(t){this.style(t)}))}),(function(t){return t.remove()}))},e}(zl);function KG(t,e){void 0===e&&(e=!1);var n=e?t.length-1:0,r=t.map((function(t,e){return We([e===n?"M":"L"],Ve(t),!1)}));return e?r.reverse():r}function ZG(t,e){if(void 0===e&&(e=!1),t.length<=2)return KG(t);for(var n=[],r=t.length,i=0;i=0?(s[l]+=i[l],i[l]=s[l]):(s[l]+=o[l],o[l]=s[l]);return e}var eV=function(t){function e(e){return t.call(this,e,{type:"line",x:0,y:0,width:200,height:20,isStack:!1,color:["#83daad","#edbf45","#d2cef9","#e290b3","#6f63f4"],smooth:!0,lineLineWidth:1,areaOpacity:0,isGroup:!1,columnLineWidth:1,columnStroke:"#fff",scale:1,spacing:0})||this}return je(e,t),Object.defineProperty(e.prototype,"rawData",{get:function(){var t=this.attributes.data;if(!t||0===(null==t?void 0:t.length))return[[]];var e=me(t);return ae(e[0])?[e]:e},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"data",{get:function(){return this.attributes.isStack?tV(this.rawData):this.rawData},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"scales",{get:function(){return this.createScales(this.data)},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"baseline",{get:function(){var t=this.scales.y,e=Ve(t.getOptions().domain||[0,0],2),n=e[0],r=e[1];return r<0?t.map(r):t.map(n<0?0:n)},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"containerShape",{get:function(){var t=this.attributes;return{width:t.width,height:t.height}},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"linesStyle",{get:function(){var t=this,e=this.attributes,n=e.type,r=e.isStack,i=e.smooth;if("line"!==n)throw new Error("linesStyle can only be used in line type");var o=Fz(this.attributes,"area"),a=Fz(this.attributes,"line"),s=this.containerShape.width,l=this.data;if(0===l[0].length)return{lines:[],areas:[]};var u=this.scales,c=function(t,e){var n,r=e.x,i=e.y,o=Ve(i.getOptions().range||[0,0],2),a=o[0],s=o[1];return s>a&&(n=Ve([a,s],2),s=n[0],a=n[1]),t.map((function(t){return t.map((function(t,e){return[r.map(e),oe(i.map(t),s,a)]}))}))}(l,{x:u.x,y:u.y}),h=[];if(o){var d=this.baseline;h=r?i?function(t,e,n){for(var r=[],i=t.length-1;i>=0;i-=1){var o=t[i],a=ZG(o),s=void 0;if(0===i)s=QG(a,e,n);else{var l=ZG(t[i-1],!0),u=o[0];l[0][0]="L",s=We(We(We([],Ve(a),!1),Ve(l),!1),[We(["M"],Ve(u),!1),["Z"]],!1)}r.push(s)}return r}(c,s,d):function(t,e,n){for(var r=[],i=t.length-1;i>=0;i-=1){var o=KG(t[i]),a=void 0;if(0===i)a=QG(o,e,n);else{var s=KG(t[i-1],!0);s[0][0]="L",a=We(We(We([],Ve(o),!1),Ve(s),!1),[["Z"]],!1)}r.push(a)}return r}(c,s,d):function(t,e,n,r){return t.map((function(t){return QG(e?ZG(t):KG(t),n,r)}))}(c,i,s,d)}return{lines:c.map((function(e,n){return Be({stroke:t.getColor(n),d:i?ZG(e):KG(e)},a)})),areas:h.map((function(e,n){return Be({d:e,fill:t.getColor(n)},o)}))}},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"columnsStyle",{get:function(){var t=this,e=Fz(this.attributes,"column"),n=this.attributes,r=n.isStack,i=n.type,o=n.scale;if("column"!==i)throw new Error("columnsStyle can only be used in column type");var a=this.containerShape.height,s=this.rawData;if(!s)return{columns:[]};r&&(s=tV(s));var l=this.createScales(s),u=l.x,c=l.y,h=Ve(JG(s),2),d=h[0],f=h[1],p=new YG({domain:[0,f-(d>0?0:d)],range:[0,a*o]}),g=u.getBandWidth(),v=this.rawData;return{columns:s.map((function(n,i){return n.map((function(n,o){var a=g/s.length;return Be(Be({fill:t.getColor(i)},e),r?{x:u.map(o),y:c.map(n),width:g,height:p.map(v[i][o])}:{x:u.map(o)+a*i,y:n>=0?c.map(n):c.map(0),width:a,height:p.map(Math.abs(n))})}))}))}},enumerable:!1,configurable:!0}),e.prototype.render=function(t,e){var n,r,i;(n=e,r=".container",i="rect",n.querySelector(r)?Rz(n).select(r):Rz(n).append(i)).attr("className","container").node();var o=t.type,a=t.x,s=t.y,l="spark".concat(o),u=Be({x:a,y:s},"line"===o?this.linesStyle:this.columnsStyle);Rz(e).selectAll(".spark").data([o]).join((function(t){return t.append((function(t){return"line"===t?new XG({className:l,style:u}):new qG({className:l,style:u})})).attr("className","spark ".concat(l))}),(function(t){return t.update(u)}),(function(t){return t.remove()}))},e.prototype.getColor=function(t){var e=this.attributes.color;return Yt(e)?e[t%e.length]:Ut(e)?e.call(null,t):e},e.prototype.createScales=function(t){var e,n,r=this.attributes,i=r.type,o=r.scale,a=r.range,s=void 0===a?[]:a,l=r.spacing,u=this.containerShape,c=u.width,h=u.height,d=Ve(JG(t),2),f=d[0],p=d[1],g=new YG({domain:[null!==(e=s[0])&&void 0!==e?e:f,null!==(n=s[1])&&void 0!==n?n:p],range:[h,h*(1-o)]});return"line"===i?{type:i,x:new YG({domain:[0,t[0].length-1],range:[0,c]}),y:g}:{type:i,x:new GG({domain:t[0].map((function(t,e){return e})),range:[0,c],paddingInner:l,paddingOuter:l/2,align:.5}),y:g}},e.tag="sparkline",e}($z);function nV(t){if(!t)return{enter:!1,update:!1,exit:!1};var e=["enter","update","exit"],n=Object.fromEntries(Object.entries(t).filter((function(t){var n=Ve(t,1)[0];return!e.includes(n)})));return Object.fromEntries(e.map((function(e){return function(t){return"boolean"!=typeof t&&"enter"in t&&"update"in t&&"exit"in t}(t)?!1===t[e]?[e,!1]:[e,Be(Be({},t[e]),n)]:[e,n]})))}function rV(t,e){t?t.finished.then(e):e()}function iV(t,e){"update"in t?t.update(e):t.attr(e)}function oV(t,e,n){return 0===e.length?null:n?t.animate(e,n):(iV(t,{style:e.slice(-1)[0]}),null)}function aV(t,e,n){var r={},i={};return Object.entries(e).forEach((function(e){var n=Ve(e,2),o=n[0],a=n[1];if(!$t(a)){var s=t.style[o]||t.parsedStyle[o]||0;s!==a&&(r[o]=s,i[o]=a)}})),n?oV(t,[r,i],Be({fill:"both"},n)):(iV(t,i),null)}function sV(t,e){return t.style.opacity||(t.style.opacity=1),aV(t,{opacity:0},e)}var lV={fill:"#fff",lineWidth:1,radius:2,size:10,stroke:"#bfbfbf",strokeOpacity:1,zIndex:0},uV={fill:"#000",fillOpacity:.45,fontSize:12,textAlign:"center",textBaseline:"middle",zIndex:1},cV={x:0,y:0,orientation:"horizontal",showLabel:!0,type:"start"},hV=rz({foreground:"foreground",handle:"handle",selection:"selection",sparkline:"sparkline",sparklineGroup:"sparkline-group",track:"track",brushArea:"brush-area"},"slider"),dV=rz({labelGroup:"label-group",label:"label",iconGroup:"icon-group",icon:"icon",iconRect:"icon-rect",iconLine:"icon-line"},"handle"),fV=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return je(e,t),e.prototype.render=function(t,e){var n=t.x,r=t.y,i=t.size,o=void 0===i?10:i,a=t.radius,s=void 0===a?o/4:a,l=t.orientation,u=Fe(t,["x","y","size","radius","orientation"]),c=o,h=2.4*c,d=Rz(e).maybeAppendByClassName(dV.iconRect,"rect").styles(Be(Be({},u),{width:c,height:h,radius:s,x:n-c/2,y:r-h/2,transformOrigin:"center"})),f=n+1/3*c-c/2,p=n+2/3*c-c/2,g=r+1/4*h-h/2,v=r+3/4*h-h/2;d.maybeAppendByClassName("".concat(dV.iconLine,"-1"),"line").styles(Be({x1:f,x2:f,y1:g,y2:v},u)),d.maybeAppendByClassName("".concat(dV.iconLine,"-2"),"line").styles(Be({x1:p,x2:p,y1:g,y2:v},u)),"vertical"===l&&(d.node().style.transform="rotate(90)")},e}($z),pV=function(t){function e(e){return t.call(this,e,cV)||this}return je(e,t),e.prototype.renderLabel=function(t){var e=this,n=this.attributes,r=n.x,i=n.y,o=n.showLabel,a=Fz(this.attributes,"label"),s=a.x,l=void 0===s?0:s,u=a.y,c=void 0===u?0:u,h=a.transform,d=a.transformOrigin,f=Ve(Gz(Fe(a,["x","y","transform","transformOrigin"]),[]),2),p=f[0],g=f[1],v=Rz(t).maybeAppendByClassName(dV.labelGroup,"g").styles(g),m=Be(Be({},uV),p),y=m.text,b=Fe(m,["text"]);pz(!!o,v,(function(t){e.label=t.maybeAppendByClassName(dV.label,"text").styles(Be(Be({},b),{x:r+l,y:i+c,transform:h,transformOrigin:d,text:"".concat(y)})),e.label.on("mousedown",(function(t){t.stopPropagation()})),e.label.on("touchstart",(function(t){t.stopPropagation()}))}))},e.prototype.renderIcon=function(t){var e=this.attributes,n=e.x,r=e.y,i=e.orientation,o=e.type,a=Be(Be({x:n,y:r,orientation:i},lV),Fz(this.attributes,"icon")),s=this.attributes.iconShape,l=void 0===s?function(){return new fV({style:a})}:s;Rz(t).maybeAppendByClassName(dV.iconGroup,"g").selectAll(dV.icon.class).data([l]).join((function(t){return t.append("string"==typeof l?l:function(){return l(o)}).attr("className",dV.icon.name)}),(function(t){return t.update(a)}),(function(t){return t.remove()}))},e.prototype.render=function(t,e){this.renderIcon(e),this.renderLabel(e)},e}($z),gV=function(t){function e(e){var n=t.call(this,e,Be(Be(Be({x:0,y:0,animate:{duration:100,fill:"both"},brushable:!0,formatter:function(t){return t.toString()},handleSpacing:2,orientation:"horizontal",padding:0,autoFitLabel:!0,scrollable:!0,selectionFill:"#5B8FF9",selectionFillOpacity:.45,selectionZIndex:2,showHandle:!0,showLabel:!0,slidable:!0,trackFill:"#416180",trackLength:200,trackOpacity:.05,trackSize:20,trackZIndex:-1,values:[0,1],type:"range",selectionType:"select",handleIconOffset:0},zz(cV,"handle")),zz(lV,"handleIcon")),zz(uV,"handleLabel")))||this;return n.range=[0,1],n.onDragStart=function(t){return function(e){e.stopPropagation(),n.target=t,n.prevPos=n.getOrientVal(dz(e));var r=n.availableSpace,i=r.x,o=r.y,a=n.getBBox(),s=a.x,l=a.y;n.selectionStartPos=n.getRatio(n.prevPos-n.getOrientVal([i,o])-n.getOrientVal([+s,+l])),n.selectionWidth=0,document.addEventListener("pointermove",n.onDragging),document.addEventListener("pointerup",n.onDragEnd)}},n.onDragging=function(t){var e=n.attributes,r=e.slidable,i=e.brushable,o=e.type;t.stopPropagation();var a=n.getOrientVal(dz(t)),s=a-n.prevPos;if(s){var l=n.getRatio(s);switch(n.target){case"start":r&&n.setValuesOffset(l);break;case"end":r&&n.setValuesOffset(0,l);break;case"selection":r&&n.setValuesOffset(l,l);break;case"track":if(!i)return;n.selectionWidth+=l,"range"===o?n.innerSetValues([n.selectionStartPos,n.selectionStartPos+n.selectionWidth].sort(),!0):n.innerSetValues([0,n.selectionStartPos+n.selectionWidth],!0)}n.prevPos=a}},n.onDragEnd=function(){document.removeEventListener("pointermove",n.onDragging),document.removeEventListener("pointermove",n.onDragging),document.removeEventListener("pointerup",n.onDragEnd),n.target="",n.updateHandlesPosition(!1)},n.onValueChange=function(t){var e=n.attributes,r=e.onChange,i=e.type,o="range"===i?t:t[1],a="range"===i?n.getValues():n.getValues()[1],s=new zs("valuechange",{detail:{oldValue:o,value:a}});n.dispatchEvent(s),null==r||r(a)},n.selectionStartPos=0,n.selectionWidth=0,n.prevPos=0,n.target="",n}return je(e,t),Object.defineProperty(e.prototype,"values",{get:function(){return this.attributes.values},set:function(t){this.attributes.values=this.clampValues(t)},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"sparklineStyle",{get:function(){if("horizontal"!==this.attributes.orientation)return null;var t=Fz(this.attributes,"sparkline");return Be(Be({zIndex:0},this.availableSpace),t)},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"shape",{get:function(){var t=this.attributes,e=t.trackLength,n=t.trackSize,r=Ve(this.getOrientVal([[e,n],[n,e]]),2);return{width:r[0],height:r[1]}},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"availableSpace",{get:function(){var t=this.attributes;t.x,t.y;var e=Ve(Dz(t.padding),4),n=e[0],r=e[1],i=e[2],o=e[3],a=this.shape;return{x:o,y:n,width:a.width-(o+r),height:a.height-(n+i)}},enumerable:!1,configurable:!0}),e.prototype.getValues=function(){return this.values},e.prototype.setValues=function(t,e){void 0===t&&(t=[0,0]),void 0===e&&(e=!1),this.attributes.values=t;var n=!1!==e&&this.attributes.animate;this.updateSelectionArea(n),this.updateHandlesPosition(n)},e.prototype.updateSelectionArea=function(t){var e=this.calcSelectionArea();this.foregroundGroup.selectAll(hV.selection.class).each((function(n,r){aV(this,e[r],t)}))},e.prototype.updateHandlesPosition=function(t){this.attributes.showHandle&&(this.startHandle&&aV(this.startHandle,this.getHandleStyle("start"),t),this.endHandle&&aV(this.endHandle,this.getHandleStyle("end"),t))},e.prototype.innerSetValues=function(t,e){void 0===t&&(t=[0,0]),void 0===e&&(e=!1);var n=this.values,r=this.clampValues(t);this.attributes.values=r,this.setValues(r),e&&this.onValueChange(n)},e.prototype.renderTrack=function(t){var e=this.attributes,n=e.x,r=e.y,i=Fz(this.attributes,"track");this.trackShape=Rz(t).maybeAppendByClassName(hV.track,"rect").styles(Be(Be({x:n,y:r},this.shape),i))},e.prototype.renderBrushArea=function(t){var e=this.attributes,n=e.x,r=e.y,i=e.brushable;this.brushArea=Rz(t).maybeAppendByClassName(hV.brushArea,"rect").styles(Be({x:n,y:r,fill:"transparent",cursor:i?"crosshair":"default"},this.shape))},e.prototype.renderSparkline=function(t){var e=this,n=this.attributes,r=n.x,i=n.y;pz("horizontal"===n.orientation,Rz(t).maybeAppendByClassName(hV.sparklineGroup,"g"),(function(t){var n=Be(Be({},e.sparklineStyle),{x:r,y:i});t.maybeAppendByClassName(hV.sparkline,(function(){return new eV({style:n})})).update(n)}))},e.prototype.renderHandles=function(){var t,e=this,n=this.attributes,r=n.showHandle,i=n.type,o=r?"range"===i?["start","end"]:["end"]:[],a=this;null===(t=this.foregroundGroup)||void 0===t||t.selectAll(hV.handle.class).data(o.map((function(t){return{type:t}})),(function(t){return t.type})).join((function(t){return t.append((function(t){var n=t.type;return new pV({style:e.getHandleStyle(n)})})).each((function(t){var e=t.type;this.attr("class","".concat(hV.handle.name," ").concat(e,"-handle"));var n="".concat(e,"Handle");a[n]=this,this.addEventListener("pointerdown",a.onDragStart(e))}))}),(function(t){return t.each((function(t){var e=t.type;this.update(a.getHandleStyle(e))}))}),(function(t){return t.each((function(t){var e=t.type,n="".concat(e,"Handle");a[n]=void 0})).remove()}))},e.prototype.renderSelection=function(t){var e=this.attributes,n=e.x,r=e.y,i=e.type,o=e.selectionType;this.foregroundGroup=Rz(t).maybeAppendByClassName(hV.foreground,"g");var a=Fz(this.attributes,"selection"),s=function(t){return t.style("visibility",(function(t){return t.show?"visible":"hidden"})).style("cursor",(function(t){return"select"===o?"grab":"invert"===o?"crosshair":"default"})).styles(Be(Be({},a),{transform:"translate(".concat(n,", ").concat(r,")")}))},l=this;this.foregroundGroup.selectAll(hV.selection.class).data("value"===i?[]:this.calcSelectionArea().map((function(t,e){return{style:Be({},t),index:e,show:"select"===o?1===e:1!==e}})),(function(t){return t.index})).join((function(t){return t.append("rect").attr("className",hV.selection.name).call(s).each((function(t,e){var n=this;1===e?(l.selectionShape=Rz(this),this.on("pointerdown",(function(t){n.attr("cursor","grabbing"),l.onDragStart("selection")(t)})),l.dispatchCustomEvent(this,"pointerenter","selectionMouseenter"),l.dispatchCustomEvent(this,"pointerleave","selectionMouseleave"),l.dispatchCustomEvent(this,"click","selectionClick"),this.addEventListener("pointerdown",(function(){n.attr("cursor","grabbing")})),this.addEventListener("pointerup",(function(){n.attr("cursor","pointer")})),this.addEventListener("pointerover",(function(){n.attr("cursor","pointer")}))):this.on("pointerdown",l.onDragStart("track"))}))}),(function(t){return t.call(s)}),(function(t){return t.remove()})),this.updateSelectionArea(!1),this.renderHandles()},e.prototype.render=function(t,e){this.renderTrack(e),this.renderSparkline(e),this.renderBrushArea(e),this.renderSelection(e)},e.prototype.clampValues=function(t,e){var n;void 0===e&&(e=4);var r=Ve(this.range,2),i=r[0],o=r[1],a=Ve(this.getValues().map((function(t){return Mz(t,e)})),2),s=a[0],l=a[1],u=Ve(((Array.isArray(t)?t:[s,null!=t?t:l])||[s,l]).map((function(t){return Mz(t,e)})),2),c=u[0],h=u[1];if("value"===this.attributes.type)return[0,oe(h,i,o)];c>h&&(c=(n=Ve([h,c],2))[0],h=n[1]);var d=h-c;return d>o-i?[i,o]:co?l===o&&s===c?[c,o]:[o-d,o]:[c,h]},e.prototype.calcSelectionArea=function(t){var e=Ve(this.clampValues(t),2),n=e[0],r=e[1],i=this.availableSpace,o=i.x,a=i.y,s=i.width,l=i.height;return this.getOrientVal([[{y:a,height:l,x:o,width:n*s},{y:a,height:l,x:n*s+o,width:(r-n)*s},{y:a,height:l,x:r*s,width:(1-r)*s}],[{x:o,width:s,y:a,height:n*l},{x:o,width:s,y:n*l+a,height:(r-n)*l},{x:o,width:s,y:r*l,height:(1-r)*l}]])},e.prototype.calcHandlePosition=function(t){var e=this.attributes.handleIconOffset,n=this.availableSpace,r=n.x,i=n.y,o=n.width,a=n.height,s=Ve(this.clampValues(),2),l=s[0],u=s[1],c="start"===t?-e:e,h=("start"===t?l:u)*this.getOrientVal([o,a])+c;return{x:r+this.getOrientVal([h,o/2]),y:i+this.getOrientVal([a/2,h])}},e.prototype.inferTextStyle=function(t){return"horizontal"===this.attributes.orientation?{}:"start"===t?{transformOrigin:"left center",transform:"rotate(90)",textAlign:"start"}:"end"===t?{transformOrigin:"right center",transform:"rotate(90)",textAlign:"end"}:{}},e.prototype.calcHandleText=function(t){var e,n=this.attributes,r=n.type,i=n.orientation,o=n.formatter,a=n.autoFitLabel,s=Fz(this.attributes,"handle"),l=Fz(s,"label"),u=s.spacing,c=this.getHandleSize(),h=this.clampValues(),d=o("start"===t?h[0]:h[1]),f=new ZF({style:Be(Be(Be({},l),this.inferTextStyle(t)),{text:d})}),p=f.getBBox(),g=p.width,v=p.height;if(f.destroy(),!a){if("value"===r)return{text:d,x:0,y:-v-u};var m=u+c+("horizontal"===i?g/2:0);return(e={text:d})["horizontal"===i?"x":"y"]="start"===t?-m:m,e}var y=0,b=0,x=this.availableSpace,E=x.width,w=x.height,k=this.calcSelectionArea()[1],M=k.x,S=k.y,N=k.width,O=k.height,T=u+c;if("horizontal"===i){var C=T+g/2;if("start"===t)y=M-T-g>0?-C:C;else y=E-M-N-T>g?C:-C}else{var A=v+T;b="start"===t?S-c>v?-A:T:w-(S+O)-c>v?A:-T}return{x:y,y:b,text:d}},e.prototype.getHandleLabelStyle=function(t){var e=Fz(this.attributes,"handleLabel");return Be(Be(Be({},e),this.calcHandleText(t)),this.inferTextStyle(t))},e.prototype.getHandleIconStyle=function(){var t=this.attributes.handleIconShape,e=Fz(this.attributes,"handleIcon"),n=this.getOrientVal(["ew-resize","ns-resize"]),r=this.getHandleSize();return Be({cursor:n,shape:t,size:r},e)},e.prototype.getHandleStyle=function(t){var e=this.attributes,n=e.x,r=e.y,i=e.showLabel,o=e.showLabelOnInteraction,a=e.orientation,s=this.calcHandlePosition(t),l=s.x,u=s.y,c=this.calcHandleText(t),h=i;return!i&&o&&(h=!!this.target),Be(Be(Be({},zz(this.getHandleIconStyle(),"icon")),zz(Be(Be({},this.getHandleLabelStyle(t)),c),"label")),{transform:"translate(".concat(l+n,", ").concat(u+r,")"),orientation:a,showLabel:h,type:t,zIndex:3})},e.prototype.getHandleSize=function(){var t=this.attributes,e=t.handleIconSize,n=t.width,r=t.height;return e||Math.floor((this.getOrientVal([+r,+n])+4)/2.4)},e.prototype.getOrientVal=function(t){var e=Ve(t,2),n=e[0],r=e[1];return"horizontal"===this.attributes.orientation?n:r},e.prototype.setValuesOffset=function(t,e,n){void 0===e&&(e=0),void 0===n&&(n=!1);var r=this.attributes.type,i=Ve(this.getValues(),2),o=[i[0]+("range"===r?t:0),i[1]+e].sort();n?this.setValues(o):this.innerSetValues(o,!0)},e.prototype.getRatio=function(t){var e=this.availableSpace,n=e.width,r=e.height;return t/this.getOrientVal([n,r])},e.prototype.dispatchCustomEvent=function(t,e,n){var r=this;t.on(e,(function(t){t.stopPropagation(),r.dispatchEvent(new zs(n,{detail:t}))}))},e.prototype.bindEvents=function(){this.addEventListener("wheel",this.onScroll);var t=this.brushArea;this.dispatchCustomEvent(t,"click","trackClick"),this.dispatchCustomEvent(t,"pointerenter","trackMouseenter"),this.dispatchCustomEvent(t,"pointerleave","trackMouseleave"),t.on("pointerdown",this.onDragStart("track"))},e.prototype.onScroll=function(t){if(this.attributes.scrollable){var e=t.deltaX,n=t.deltaY||e,r=this.getRatio(n);this.setValuesOffset(r,r,!0)}},e.tag="slider",e}($z),vV={data:[],animate:{enter:!1,update:{duration:100,easing:"ease-in-out-sine",fill:"both"},exit:{duration:100,fill:"both"}},showArrow:!0,showGrid:!0,showLabel:!0,showLine:!0,showTick:!0,showTitle:!0,showTrunc:!1,dataThreshold:100,lineLineWidth:1,lineStroke:"black",crossPadding:10,titleFill:"black",titleFontSize:12,titlePosition:"lb",titleSpacing:0,titleTextAlign:"center",titleTextBaseline:"middle",lineArrow:function(){return new Ql({style:{d:[["M",10,10],["L",-10,0],["L",10,-10],["L",0,0],["L",10,10],["Z"]],fill:"black",transformOrigin:"center"}})},labelAlign:"parallel",labelDirection:"positive",labelFontSize:12,labelSpacing:0,gridConnect:"line",gridControlAngles:[],gridDirection:"positive",gridLength:0,gridType:"segment",lineArrowOffset:15,lineArrowSize:10,tickDirection:"positive",tickLength:5,tickLineWidth:1,tickStroke:"black",labelOverlap:[]};ke({},vV,{style:{type:"arc"}}),ke({},vV,{style:{}});var mV=rz({mainGroup:"main-group",gridGroup:"grid-group",grid:"grid",lineGroup:"line-group",line:"line",tickGroup:"tick-group",tick:"tick",tickItem:"tick-item",labelGroup:"label-group",label:"label",labelItem:"label-item",titleGroup:"title-group",title:"title",lineFirst:"line-first",lineSecond:"line-second"},"axis"),yV=rz({lineGroup:"line-group",line:"line",regionGroup:"region-group",region:"region"},"grid");function bV(t){return t.reduce((function(t,e,n){return t.push(We([0===n?"M":"L"],Ve(e),!1)),t}),[])}function xV(t,e,n){return"surround"===e.type?function(t,e,n){var r=e.connect,i=void 0===r?"line":r,o=e.center;if("line"===i)return bV(t);if(!o)return[];var a=wz(t[0],o),s=n?0:1;return t.reduce((function(t,e,n){return 0===n?t.push(We(["M"],Ve(e),!1)):t.push(We(["A",a,a,0,0,s],Ve(e),!1)),t}),[])}(t,e,n):bV(t)}function EV(t,e,n){var r=n.type,i=n.connect,o=n.center,a=n.closed?[["Z"]]:[],s=Ve([xV(t,n),xV(e.slice().reverse(),n,!0)],2),l=s[0],u=s[1],c=Ve([t[0],e.slice(-1)[0]],2),h=c[0],d=c[1],f=function(t,e){return[l,t,u,e,a].flat()};if("line"===i||"surround"===r)return f([We(["L"],Ve(d),!1)],[We(["L"],Ve(h),!1)]);if(!o)throw new Error("Arc grid need to specified center");var p=Ve([wz(d,o),wz(h,o)],2),g=p[0],v=p[1];return f([We(["A",g,g,0,0,1],Ve(d),!1),We(["L"],Ve(d),!1)],[We(["A",v,v,0,0,0],Ve(h),!1),We(["L"],Ve(h),!1)])}var wV=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return je(e,t),e.prototype.render=function(t,e){t.type,t.center,t.areaFill,t.closed;var n=Fe(t,["type","center","areaFill","closed"]),r=function(t){var e=t.data,n=void 0===e?[]:e;return t.closed?n.map((function(t){var e=t.points,n=Ve(e,1)[0];return Be(Be({},t),{points:We(We([],Ve(e),!1),[n],!1)})})):n}(t),i=Rz(e).maybeAppendByClassName(yV.lineGroup,"g"),o=Rz(e).maybeAppendByClassName(yV.regionGroup,"g"),a=function(t,e,n,r){var i=n.animate,o=n.isBillboard,a=e.map((function(t,e){return{id:t.id||"grid-line-".concat(e),d:xV(t.points,n)}}));return t.selectAll(yV.line.class).data(a,(function(t){return t.id})).join((function(t){return t.append("path").each((function(t,e){var n=ez(Cz(Be({d:t.d},r)),[t,e,a]);this.attr(Be({class:yV.line.name,stroke:"#D9D9D9",lineWidth:1,lineDash:[4,4],isBillboard:o},n))}))}),(function(t){return t.transition((function(t,e){return aV(this,ez(Cz(Be({d:t.d},r)),[t,e,a]),i.update)}))}),(function(t){return t.transition((function(){var t=this,e=sV(this,i.exit);return rV(e,(function(){return t.remove()})),e}))})).transitions()}(i,r,t,n),s=function(t,e,n){var r=n.animate,i=n.connect,o=n.areaFill;if(e.length<2||!o||!i)return[];for(var a=Array.isArray(o)?o:[o,"transparent"],s=function(t){return a[t%a.length]},l=[],u=0;u180?1:0,E=t>e?0:1;return"M".concat(p,",").concat(g,",A").concat(s,",").concat(l,",0,").concat(x,",").concat(E,",").concat(m,",").concat(y)}function LV(t,e,n,r){var i=e.startAngle,o=e.endAngle,a=e.center,s=e.radius;return t.selectAll(mV.line.class).data([{d:DV.apply(void 0,We(We([i,o],Ve(a),!1),[s],!1))}],(function(t,e){return e})).join((function(t){return t.append("path").attr("className",mV.line.name).styles(e).styles({d:function(t){return t.d}})}),(function(t){return t.transition((function(){var t=this,e=function(t,e,n,r){if(!r)return t.attr("__keyframe_data__",n),null;var i=r.duration,o=void 0===i?0:i,a=vz(e,n),s=Math.ceil(+o/16),l=new Array(s).fill(0).map((function(t,e,n){return{__keyframe_data__:a(e/(n.length-1))}}));return t.animate(l,Be({fill:"both"},r))}(this,function(t){var e=t.attributes,n=e.startAngle,r=e.endAngle,i=e.center,o=e.radius;return We(We([n,r],Ve(i),!1),[o],!1)}(this),We(We([i,o],Ve(a),!1),[s],!1),r.update);if(e){var n=function(){var e=Oe(t.attributes,"__keyframe_data__");t.style.d=DV.apply(void 0,We([],Ve(e),!1))};e.onframe=n,e.onfinish=n}return e})).styles(e)}),(function(t){return t.remove()})).styles(n).transitions()}function _V(t){var e=Ve(t,2),n=Ve(e[0],2),r=n[0],i=n[1],o=Ve(e[1],2);return{x1:r,y1:i,x2:o[0],y2:o[1]}}function IV(t,e,n,r){var i=e.showTrunc,o=e.startPos,a=e.endPos,s=e.truncRange,l=e.lineExtension,u=Ve([o,a],2),c=Ve(u[0],2),h=c[0],d=c[1],f=Ve(u[1],2),p=f[0],g=f[1],v=Ve(l?function(t,e,n){void 0===n&&(n=[0,0]);var r=Ve([t,e,n],3),i=Ve(r[0],2),o=i[0],a=i[1],s=Ve(r[1],2),l=s[0],u=s[1],c=Ve(r[2],2),h=c[0],d=c[1],f=Ve([l-o,u-a],2),p=f[0],g=f[1],v=Math.sqrt(Math.pow(p,2)+Math.pow(g,2)),m=Ve([-h/v,d/v],2),y=m[0],b=m[1];return[y*p,y*g,b*p,b*g]}(o,a,l):new Array(4).fill(0),4),m=v[0],y=v[1],b=v[2],x=v[3],E=function(e){return t.selectAll(mV.line.class).data(e,(function(t,e){return e})).join((function(t){return t.append("line").attr("className",(function(t){return"".concat(mV.line.name," ").concat(t.className)})).styles(n).transition((function(t){return aV(this,_V(t.line),!1)}))}),(function(t){return t.styles(n).transition((function(t){return aV(this,_V(t.line),r.update)}))}),(function(t){return t.remove()})).transitions()};if(!i||!s)return E([{line:[[h+m,d+y],[p+b,g+x]],className:mV.line.name}]);var w=Ve(s,2),k=w[0],M=w[1],S=p-h,N=g-d,O=Ve([h+S*k,d+N*k],2),T=O[0],C=O[1],A=Ve([h+S*M,d+N*M],2),P=A[0],R=A[1],D=E([{line:[[h+m,d+y],[T,C]],className:mV.lineFirst.name},{line:[[P,R],[p+b,g+x]],className:mV.lineSecond.name}]);return function(t,e){e.truncRange,e.truncShape,e.lineExtension}(0,e),D}function jV(t,e,n){var r,i=e.type,o=Fz(e,"line");return r="linear"===i?IV(t,e,Sz(o,"arrow"),n):LV(t,e,Sz(o,"arrow"),n),function(t,e,n,r){var i,o=n.showArrow,a=n.showTrunc,s=n.lineArrow,l=n.lineArrowOffset,u=n.lineArrowSize;if(i="arc"===e?t.select(mV.line.class):a?t.select(mV.lineSecond.class):t.select(mV.line.class),!o||!s||"arc"===n.type&&RV(n.startAngle,n.endAngle)){var c=i.node();c&&(c.style.markerEnd=void 0)}else{var h=fz(s);h.attr(r),Az(h,u),i.style("markerEnd",h).style("markerEndOffset",-l)}}(t,i,e,o),r}function BV(t){var e=t.type,n=t.gridCenter;return"linear"===e?n:n||t.center}function FV(t,e){var n=e.gridLength;return t.map((function(t,r){var i=t.value,o=Ve(CV(i,e),2),a=o[0],s=o[1],l=Ve(mz(function(t,e){return OV(t,e.gridDirection,e)}(i,e),n),2);return{id:r,points:[[a,s],[a+l[0],s+l[1]]]}}))}function zV(t,e,n,r){var i=Fz(n,"grid"),o=i.type,a=i.areaFill,s=BV(n),l=MV(e,n.gridFilter),u="segment"===o?FV(l,n):function(t,e){var n=e.gridControlAngles,r=BV(e);if(!r)throw new Error("grid center is not provide");if(t.length<2)throw new Error("Invalid grid data");if(!n||0===n.length)throw new Error("Invalid gridControlAngles");var i=Ve(r,2),o=i[0],a=i[1];return t.map((function(t,r){var i=Ve(CV(t.value,e),2),s=i[0],l=i[1],u=Ve([s-o,l-a],2),c=u[0],h=u[1],d=[];return n.forEach((function(t){var e=QF(t),n=Ve([Math.cos(e),Math.sin(e)],2),r=n[0],i=n[1],s=c*r-h*i+o,l=c*i+h*r+a;d.push([s,l])})),{points:d,id:r}}))}(l,n),c=Be(Be({},i),{center:s,areaFill:Ut(a)?l.map((function(t,e){return ez(a,[t,e,l])})):a,animate:r,data:u});return t.selectAll(mV.grid.class).data([1]).join((function(t){return t.append((function(){return new wV({style:c})})).attr("className",mV.grid.name)}),(function(t){return t.transition((function(){return this.update(c)}))}),(function(t){return t.remove()})).transitions()}var GV=function(){function t(t,e,n,r){this.set(t,e,n,r)}return Object.defineProperty(t.prototype,"left",{get:function(){return this.x1},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"top",{get:function(){return this.y1},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"right",{get:function(){return this.x2},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"bottom",{get:function(){return this.y2},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"width",{get:function(){return this.defined("x2")&&this.defined("x1")?this.x2-this.x1:void 0},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"height",{get:function(){return this.defined("y2")&&this.defined("y1")?this.y2-this.y1:void 0},enumerable:!1,configurable:!0}),t.prototype.rotatedPoints=function(t,e,n){var r=this,i=r.x1,o=r.y1,a=r.x2,s=r.y2,l=Math.cos(t),u=Math.sin(t),c=e-e*l+n*u,h=n-e*u-n*l;return[[l*i-u*s+c,u*i+l*s+h],[l*a-u*s+c,u*a+l*s+h],[l*i-u*o+c,u*i+l*o+h],[l*a-u*o+c,u*a+l*o+h]]},t.prototype.set=function(t,e,n,r){return n0,v=r-l,m=i-u,y=c*m-h*v;if(y<0===g)return!1;var b=d*m-f*v;return b<0!==g&&y>p!==g&&b>p!==g}(e,t)}))}function YV(t,e,n){var r,i,o=e.crossPadding,a=new Set,s=null,l=function(t,e){var n=t.type,r=t.labelDirection,i=t.crossSize;if(!i)return!1;if("arc"===n){var o=t.center,a=t.radius,s=Ve(o,2),l=s[0],u=s[1],c="negative"===r?0:i,h=-a-c,d=a+c,f=Ve(Dz(e),4),p=f[0],g=f[1],v=f[2],m=f[3];return new GV(l+h-m,u+h-p,l+d+g,u+d+v)}var y=Ve(t.startPos,2),b=y[0],x=y[1],E=Ve(t.endPos,2),w=E[0],k=E[1],M=Ve(PV(t)?[-e,0,e,0]:[0,e,0,-e],4),S=M[0],N=M[1],O=M[2],T=M[3],C=mz(TV(0,t),i),A=new GV(b,x,w,k);return A.x1+=T,A.y1+=S,A.x2+=N+C[0],A.y2+=O+C[1],A}(e,o),u=function(t){return!l||function(t,e,n){var r=t.x1,i=t.x2,o=t.y1,a=t.y2;return UV([[r,o],[i,o],[i,a],[r,a]],VV(e,n))}(l,t)},c=function(t,e){return!t||!t.firstChild||!function(t,e,n){var r,i,o=VV(t,n).flat(1),a=VV(e,n).flat(1),s=[[o[0],o[1],o[2],o[3]],[o[0],o[1],o[4],o[5]],[o[4],o[5],o[6],o[7]],[o[2],o[3],o[6],o[7]]];try{for(var l=Ge(s),u=l.next();!u.done;u=l.next())if($V(a,u.value))return!0}catch(t){r={error:t}}finally{try{u&&!u.done&&(i=l.return)&&i.call(l)}finally{if(r)throw r.error}}return!1}(t.firstChild,e.firstChild,Dz(n))};try{for(var h=Ge(t),d=h.next();!d.done;d=h.next()){var f=d.value;u(f)?!s||c(s,f)?s=f:(a.add(s),a.add(f)):a.add(f)}}catch(t){r={error:t}}finally{try{d&&!d.done&&(i=h.return)&&i.call(h)}finally{if(r)throw r.error}}return Array.from(a)}function qV(t,e){return void 0===e&&(e={}),$t(t)?0:"number"==typeof t?t:Math.floor(sz(t,e))}var XV=function(t,e){var n=e.seq,r=void 0===n?2:n;return t.filter((function(t,e){return!(e%r)||(YF(t),!1)}))};var KV=new Map([["hide",function(t,e,n,r){var i=t.length,o=e.keepHeader,a=e.keepTail;if(!(i<=1||2===i&&o&&a)){var s,l,u,c=XV,h=function(t){return t.forEach(r.show),t},d=2,f=t.slice(),p=t.slice(),g=Math.min.apply(Math,We([1],Ve(t.map((function(t){return t.getBBox().width}))),!1));if("linear"===n.type&&(AV(n)||PV(n))){var v=Lz(t[0]).left,m=Lz(t[i-1]).right,y=Math.abs(m-v)||1;d=Math.max(Math.floor(i*g/y),d)}for(o&&(s=f.splice(0,1)[0]),a&&(l=f.splice(-1,1)[0],f.reverse()),h(f);dg+p;x-=p){var E=b(x);if("object"==typeof E)return E.value}}}],["wrap",function(t,e,n,r,i){var o,a=e.maxLines,s=void 0===a?3:a,l=e.recoverWhenFailed,u=void 0===l||l,c=e.margin,h=void 0===c?[0,0,0,0]:c,d=ez(null!==(o=e.wordWrapWidth)&&void 0!==o?o:50,[i]),f=t.map((function(t){return t.attr("maxLines")||1})),p=Math.min.apply(Math,We([],Ve(f),!1)),g=function(){return YV(t,n,h).length<1},v=function(t){var e=t.type,n=t.labelDirection;return"linear"===e&&AV(t)?"negative"===n?"bottom":"top":"middle"}(n),m=function(e){return t.forEach((function(t,n){var i=Array.isArray(e)?e[n]:e;r.wrap(t,d,i,v)}))};if(!(p>s)){if("linear"===n.type&&AV(n)){if(m(s),g())return}else for(var y=p;y<=s;y++)if(m(y),g())return;u&&m(f)}}]]);function ZV(){for(var t=[],e=0;e=1)})(t,e,o)&&(null==a||a(t,i,e,r,n))}))}(this.node().childNodes,t,e,{hide:YF,show:$F,rotate:function(e,n){!function(t,e,n){e.setLocalEulerAngles(t);var r=eW(e.__data__.value,t,n),i=e.querySelector(mV.labelItem.class);i&&rW(i,r)}(+n,e,t)},ellipsis:function(t,e,n){t&&hz(t,e||1/0,n)},wrap:function(t,e,n){var r,i;t&&(void 0===(r=n)&&(r=2),void 0===i&&(i="top"),cz(t,{wordWrap:!0,wordWrapWidth:e,maxLines:r,textBaseline:i}))},getTextShape:function(t){return t.querySelector("text")}})}function oW(t,e,n,r,i){var o=n.indexOf(e),a=Rz(t).append(function(t,e,n,r){var i=r.labelFormatter;return Ut(i)?function(){return fz(ez(i,[t,e,n,TV(t.value,r)]))}:function(){return fz(t.label||"")}}(e,o,n,i)).attr("className",mV.labelItem.name).node(),s=Ve(Gz(kV(r,[e,o,n])),2),l=s[0],u=s[1],c=u.transform,h=Fe(u,["transform"]);Wz(a,c);var d=tW(e,a,i);return a.getLocalEulerAngles()||a.setLocalEulerAngles(d),rW(a,Be(Be({},eW(e.value,d,i)),l)),t.attr(h),a}function aW(t,e,n,r,i){var o,a,s,l=MV(e,n.labelFilter),u=Fz(n,"label"),c=t.selectAll(mV.label.class).data(l,(function(t,e){return e})).join((function(t){return t.append("g").attr("className",mV.label.name).transition((function(t){oW(this,t,e,u,n);var r=nW(t,e,n),i=r.x,o=r.y;return this.style.transform="translate(".concat(i,", ").concat(o,")"),null}))}),(function(t){return t.transition((function(t){var i=function(t,e,n,r){if(void 0===r&&(r="destroy"),function(t,e){return"text"===t.nodeName&&"text"===e.nodeName&&t.attributes.text===e.attributes.text}(t,e))return t.remove(),[null];var i=function(){"destroy"===r?t.destroy():"hide"===r&&YF(t),e.isVisible()&&$F(e)};if(!n)return i(),[null];var o=n.duration,a=void 0===o?0:o,s=n.delay,l=void 0===s?0:s,u=Math.ceil(+a/2),c=+a/4,h=Ve(t.getGeometryBounds().center,2),d=h[0],f=h[1],p=Ve(e.getGeometryBounds().center,2),g=Ve([(d+p[0])/2-d,(f+p[1])/2-f],2),v=g[0],m=g[1],y=t.style.opacity,b=void 0===y?1:y,x=e.style.opacity,E=void 0===x?1:x,w=t.style.transform||"",k=e.style.transform||"",M=t.animate([{opacity:b,transform:"translate(0, 0) ".concat(w)},{opacity:0,transform:"translate(".concat(v,", ").concat(m,") ").concat(w)}],Be(Be({fill:"both"},n),{duration:l+u+c})),S=e.animate([{opacity:0,transform:"translate(".concat(-v,", ").concat(-m,") ").concat(k),offset:.01},{opacity:E,transform:"translate(0, 0) ".concat(k)}],Be(Be({fill:"both"},n),{duration:u+c,delay:l+u-c}));return rV(S,i),[M,S]}(this.querySelector(mV.labelItem.class),oW(this,t,e,u,n),r.update),o=nW(t,e,n),a=o.x,s=o.y,l=aV(this,{transform:"translate(".concat(a,", ").concat(s,")")},r.update);return We(We([],Ve(i),!1),[l],!1)}))}),(function(t){return o=t,t.transition((function(){var t=this,e=sV(this.childNodes[0],r.exit);return rV(e,(function(){return Rz(t).remove()})),e})),o})).transitions();return s=function(){iW.call(t,n,i)},0===(a=c).length?s():Promise.all(a.map((function(t){return null==t?void 0:t.finished}))).then(s),c}function sW(t,e){return OV(t,e.tickDirection,e)}function lW(t,e,n,r,i){var o=Ve(function(t,e){var n=Ve(t,2);return[[0,0],[n[0]*e,n[1]*e]]}(r,ez(i.tickLength,[t,e,n])),2),a=Ve(o[0],2),s=a[0],l=a[1],u=Ve(o[1],2);return{x1:s,x2:u[0],y1:l,y2:u[1]}}function uW(t,e,n,r,i,o){var a=function(t,e,n,r,i){var o=i.tickFormatter,a=sW(e.value,i),s="line";return Ut(o)&&(s=function(){return ez(o,[e,n,r,a])}),t.append(s).attr("className",mV.tickItem.name)}(Rz(this),t,e,n,r);!function(t,e,n,r,i,o,a){var s=sW(t.value,o),l=lW(t,e,n,s,o),u=l.x1,c=l.x2,h=l.y1,d=l.y2,f=Ve(Gz(kV(a,[t,e,n,s])),2),p=f[0],g=f[1];"line"===r.node().nodeName&&r.styles(Be({x1:u,x2:c,y1:h,y2:d},p)),i.attr(g),r.styles(p)}(t,e,n,a,this,r,i);var s=Ve(CV(t.value,r),2),l=s[0],u=s[1];return aV(this,{transform:"translate(".concat(l,", ").concat(u,")")},o)}var cW=rz({text:"text"},"title");function hW(t){return/\S+-\S+/g.test(t)?t.split("-").map((function(t){return t[0]})):t.length>2?[t[0]]:t.split("")}function dW(t,e){var n=Object.entries(e).reduce((function(e,n){var r=Ve(n,2),i=r[0],o=r[1];return t.node().attr(i)||(e[i]=o),e}),{});t.styles(n)}var fW=function(t){function e(e){return t.call(this,e,{text:"",width:0,height:0,fill:"#4a505a",fontWeight:"bold",fontSize:12,fontFamily:"sans-serif",inset:0,spacing:0,position:"top-left"})||this}return je(e,t),e.prototype.getAvailableSpace=function(){var t=this.attributes,e=t.width,n=t.height,r=t.position,i=t.spacing,o=t.inset,a=this.querySelector(cW.text.class);if(!a)return new tz(0,0,+e,+n);var s=a.getBBox(),l=s.width,u=s.height,c=Ve(Dz(i),4),h=c[0],d=c[1],f=c[2],p=c[3],g=Ve([0,0,+e,+n],4),v=g[0],m=g[1],y=g[2],b=g[3],x=hW(r);if(x.includes("i"))return new tz(v,m,y,b);x.forEach((function(t,r){var i,o,a,s;"t"===t&&(i=Ve(0===r?[u+f,+n-u-f]:[0,+n],2),m=i[0],b=i[1]),"r"===t&&(o=Ve([+e-l-p],1),y=o[0]),"b"===t&&(a=Ve([+n-u-h],1),b=a[0]),"l"===t&&(s=Ve(0===r?[l+d,+e-l-d]:[0,+e],2),v=s[0],y=s[1])}));var E=Ve(Dz(o),4),w=E[0],k=E[1],M=E[2],S=E[3],N=Ve([S+k,w+M],2),O=N[0],T=N[1];return new tz(v+S,m+w,y-O,b-T)},e.prototype.getBBox=function(){return this.title?this.title.getBBox():new tz(0,0,0,0)},e.prototype.render=function(t,e){var n=this;t.width,t.height,t.position,t.spacing;var r=Fe(t,["width","height","position","spacing"]),i=Ve(Gz(r),1)[0],o=function(t){var e,n,r,i,o=t,a=o.width,s=o.height,l=o.position,u=Ve([+a/2,+s/2],2),c=Ve([+u[0],+u[1],"center","middle"],4),h=c[0],d=c[1],f=c[2],p=c[3],g=hW(l);return g.includes("l")&&(h=(e=Ve([0,"start"],2))[0],f=e[1]),g.includes("r")&&(h=(n=Ve([+a,"end"],2))[0],f=n[1]),g.includes("t")&&(d=(r=Ve([0,"top"],2))[0],p=r[1]),g.includes("b")&&(d=(i=Ve([+s,"bottom"],2))[0],p=i[1]),{x:h,y:d,textAlign:f,textBaseline:p}}(t),a=o.x,s=o.y,l=o.textAlign,u=o.textBaseline;pz(!!r.text,Rz(e),(function(t){n.title=t.maybeAppendByClassName(cW.text,"text").styles(i).call(dW,{x:a,y:s,textAlign:l,textBaseline:u}).node()}))},e}($z);function pW(t,e,n,r,i){var o=Ve(Gz(Fz(r,"title")),2),a=o[0],s=o[1],l=s.transform,u=s.transformOrigin,c=Fe(s,["transform","transformOrigin"]);e.styles(c);var h=l||function(t,e,n){var r=2*t.getGeometryBounds().halfExtents[1];if("vertical"===e){if("left"===n)return"rotate(-90) translate(0, ".concat(r/2,")");if("right"===n)return"rotate(-90) translate(0, -".concat(r/2,")")}return""}(t.node(),a.direction,a.position);t.styles(Be(Be({},a),{transformOrigin:u})),Wz(t.node(),h);var d=function(t,e,n){var r=n.titlePosition,i=void 0===r?"lb":r,o=n.titleSpacing,a=hW(i),s=t.node().getLocalBounds(),l=Ve(s.min,2),u=l[0],c=l[1],h=Ve(s.halfExtents,2),d=h[0],f=h[1],p=Ve(e.node().getLocalBounds().halfExtents,2),g=p[0],v=p[1],m=Ve([u+d,c+f],2),y=m[0],b=m[1],x=Ve(Dz(o),4),E=x[0],w=x[1],k=x[2],M=x[3];if(["start","end"].includes(i)&&"linear"===n.type){var S=n.startPos,N=n.endPos,O=Ve("start"===i?[S,N]:[N,S],2),T=O[0],C=O[1],A=Ve(mz(kz([-C[0]+T[0],-C[1]+T[1]]),E),2),P=A[0],R=A[1];return{x:T[0]+P,y:T[1]+R}}return a.includes("t")&&(b-=f+v+E),a.includes("r")&&(y+=d+g+w),a.includes("l")&&(y-=d+g+M),a.includes("b")&&(b+=f+v+k),{x:y,y:b}}(Rz(n._offscreen||n.querySelector(mV.mainGroup.class)),e,r),f=d.x,p=d.y;return aV(e.node(),{transform:"translate(".concat(f,", ").concat(p,")")},i)}function gW(t,e,n,r){var i=t.showLine,o=t.showTick,a=t.showLabel,s=pz(i,e.maybeAppendByClassName(mV.lineGroup,"g"),(function(e){return jV(e,t,r)}))||[],l=pz(o,e.maybeAppendByClassName(mV.tickGroup,"g"),(function(e){return function(t,e,n,r){var i=MV(e,n.tickFilter),o=Fz(n,"tick");return t.selectAll(mV.tick.class).data(i,(function(t){return t.id||t.label})).join((function(t){return t.append("g").attr("className",mV.tick.name).transition((function(t,e){return uW.call(this,t,e,i,n,o,!1)}))}),(function(t){return t.transition((function(t,e){return this.removeChildren(),uW.call(this,t,e,i,n,o,r.update)}))}),(function(t){return t.transition((function(){var t=this,e=sV(this.childNodes[0],r.exit);return rV(e,(function(){return t.remove()})),e}))})).transitions()}(e,n,t,r)}))||[],u=pz(a,e.maybeAppendByClassName(mV.labelGroup,"g"),(function(i){return aW(i,n,t,r,e.node())}))||[];return We(We(We([],Ve(s),!1),Ve(l),!1),Ve(u),!1).filter((function(t){return!!t}))}var vW=function(t){function e(e){return t.call(this,e,vV)||this}return je(e,t),e.prototype.render=function(t,e,n){var r=this,i=t.titleText,o=t.data,a=t.animate,s=t.showTitle,l=t.showGrid,u=t.dataThreshold,c=t.truncRange,h=function(t,e){if(t.length<=e)return t;for(var n=Math.floor(t.length/e),r=[],i=0;ic[0]&&e1?{width:55,height:0}:{width:0,height:0}},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"pageShape",{get:function(){var t=Ve(function(t){var e;return(null===(e=t[0])||void 0===e?void 0:e.map((function(e,n){return t.map((function(t){return t[n]}))})))||[]}(this.pageViews.map((function(t){var e=t.getBBox();return[e.width,e.height]}))).map((function(t){return Math.max.apply(Math,We([],Ve(t),!1))})),2),e=t[0],n=t[1],r=this.attributes,i=r.pageWidth,o=void 0===i?e:i,a=r.pageHeight;return{pageWidth:o,pageHeight:void 0===a?n:a}},enumerable:!1,configurable:!0}),e.prototype.getContainer=function(){return this.playWindow},Object.defineProperty(e.prototype,"totalPages",{get:function(){return this.pageViews.length},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"currPage",{get:function(){return this.innerCurrPage},enumerable:!1,configurable:!0}),e.prototype.getBBox=function(){var e=t.prototype.getBBox.call(this),n=e.x,r=e.y,i=this.controllerShape,o=this.pageShape,a=o.pageWidth,s=o.pageHeight;return new tz(n,r,a+i.width,s)},e.prototype.goTo=function(t){var e=this,n=this.attributes.animate,r=this,i=r.currPage,o=r.playState,a=r.playWindow,s=r.pageViews;if("idle"!==o||t<0||s.length<=0||t>=s.length)return null;s[i].setLocalPosition(0,0),this.prepareFollowingPage(t);var l=Ve(this.getFollowingPageDiff(t),2),u=l[0],c=l[1];this.playState="running";var h=oV(a,[{transform:"translate(0, 0)"},{transform:"translate(".concat(-u,", ").concat(-c,")")}],n);return rV(h,(function(){e.innerCurrPage=t,e.playState="idle",e.setVisiblePages([t]),e.updatePageInfo()})),h},e.prototype.prev=function(){var t=this.attributes.loop,e=this.pageViews.length,n=this.currPage;if(!t&&n<=0)return null;var r=t?(n-1+e)%e:oe(n-1,0,e);return this.goTo(r)},e.prototype.next=function(){var t=this.attributes.loop,e=this.pageViews.length,n=this.currPage;if(!t&&n>=e-1)return null;var r=t?(n+1)%e:oe(n+1,0,e);return this.goTo(r)},e.prototype.renderClipPath=function(t){var e=this.pageShape,n=e.pageWidth,r=e.pageHeight;n&&r?(this.clipPath=t.maybeAppendByClassName(mW.clipPath,"rect").styles({width:n,height:r}),this.contentGroup.attr("clipPath",this.clipPath.node())):this.contentGroup.style.clipPath=void 0},e.prototype.setVisiblePages=function(t){this.playWindow.children.forEach((function(e,n){t.includes(n)?$F(e):YF(e)}))},e.prototype.adjustControllerLayout=function(){var t=this,e=t.prevBtnGroup,n=t.nextBtnGroup,r=t.pageInfoGroup,i=this.attributes,o=i.orientation,a=i.controllerPadding,s=r.getBBox(),l=s.width;s.height;var u=Ve("horizontal"===o?[-180,0]:[-90,90],2),c=u[0],h=u[1];e.setLocalEulerAngles(c),n.setLocalEulerAngles(h);var d=e.getBBox(),f=d.width,p=d.height,g=n.getBBox(),v=g.width,m=g.height,y=Math.max(f,l,v),b="horizontal"===o?{offset:[[0,0],[f/2+a,0],[f+l+2*a,0]],textAlign:"start"}:{offset:[[y/2,-p-a],[y/2,0],[y/2,m+a]],textAlign:"center"},x=Ve(b.offset,3),E=Ve(x[0],2),w=E[0],k=E[1],M=Ve(x[1],2),S=M[0],N=M[1],O=Ve(x[2],2),T=O[0],C=O[1],A=b.textAlign,P=r.querySelector("text");P&&(P.style.textAlign=A),e.setLocalPosition(w,k),r.setLocalPosition(S,N),n.setLocalPosition(T,C)},e.prototype.updatePageInfo=function(){var t,e=this,n=e.currPage,r=e.pageViews,i=e.attributes.formatter;r.length<2||(null===(t=this.pageInfoGroup.querySelector(mW.pageInfo.class))||void 0===t||t.attr("text",i(n+1,r.length)),this.adjustControllerLayout())},e.prototype.getFollowingPageDiff=function(t){var e=this.currPage;if(e===t)return[0,0];var n=this.attributes.orientation,r=this.pageShape,i=r.pageWidth,o=r.pageHeight,a=t=2,s=t.maybeAppendByClassName(mW.controller,"g");if(qF(s.node(),a),a){var l=Fz(this.attributes,"button"),u=Fz(this.attributes,"pageNum"),c=Ve(Gz(l),2),h=c[0],d=c[1],f=h.size,p=Fe(h,["size"]),g=!s.select(mW.prevBtnGroup.class).node(),v=s.maybeAppendByClassName(mW.prevBtnGroup,"g").styles(d);this.prevBtnGroup=v.node();var m=v.maybeAppendByClassName(mW.prevBtn,"path"),y=s.maybeAppendByClassName(mW.nextBtnGroup,"g").styles(d);this.nextBtnGroup=y.node(),[m,y.maybeAppendByClassName(mW.nextBtn,"path")].forEach((function(t){t.styles(Be(Be({},p),{transformOrigin:"center"})),Az(t.node(),f)}));var b=s.maybeAppendByClassName(mW.pageInfoGroup,"g");this.pageInfoGroup=b.node(),b.maybeAppendByClassName(mW.pageInfo,"text").styles(u),this.updatePageInfo(),s.node().setLocalPosition(i+n,o/2),g&&(this.prevBtnGroup.addEventListener("click",(function(){e.prev()})),this.nextBtnGroup.addEventListener("click",(function(){e.next()})))}},e.prototype.render=function(t,e){var n=t.x,r=void 0===n?0:n,i=t.y,o=void 0===i?0:i;this.attr("transform","translate(".concat(r,", ").concat(o,")"));var a=Rz(e);this.renderClipPath(a),this.renderController(a),this.setVisiblePages([this.defaultPage]),this.goTo(this.defaultPage)},e.prototype.bindEvents=function(){var t=this,e=ye((function(){return t.render(t.attributes,t)}),50);this.playWindow.addEventListener(Ks.INSERTED,e),this.playWindow.addEventListener(Ks.REMOVED,e)},e}($z);function bW(t,e,n){return void 0===t&&(t="horizontal"),"horizontal"===t?e:n}tG.registerSymbol("hiddenHandle",(function(t,e,n){var r=1.4*n;return[["M",t-n,e-r],["L",t+n,e-r],["L",t+n,e+r],["L",t-n,e+r],["Z"]]})),tG.registerSymbol("verticalHandle",(function(t,e,n){var r=1.4*n,i=n/2,o=n/6,a=t+.4*r;return[["M",t,e],["L",a,e+i],["L",t+r,e+i],["L",t+r,e-i],["L",a,e-i],["Z"],["M",a,e+o],["L",t+r-2,e+o],["M",a,e-o],["L",t+r-2,e-o]]})),tG.registerSymbol("horizontalHandle",(function(t,e,n){var r=1.4*n,i=n/2,o=n/6,a=e+.4*r;return[["M",t,e],["L",t-i,a],["L",t-i,e+r],["L",t+i,e+r],["L",t+i,a],["Z"],["M",t-o,a],["L",t-o,e+r-2],["M",t+o,a],["L",t+o,e+r-2]]}));var xW=rz({layout:"flex",markerGroup:"marker-group",marker:"marker",labelGroup:"label-group",label:"label",valueGroup:"value-group",value:"value",backgroundGroup:"background-group",background:"background"},"legend-category-item");var EW=function(t){function e(e){return t.call(this,e,{span:[1,1],marker:function(){return new Gl({style:{r:6}})},markerSize:10,labelFill:"#646464",valueFill:"#646464",labelFontSize:12,valueFontSize:12,labelTextBaseline:"middle",valueTextBaseline:"middle"})||this}return je(e,t),Object.defineProperty(e.prototype,"showValue",{get:function(){var t=this.attributes.valueText;return!!t&&("string"==typeof t||"number"==typeof t?""!==t:"function"==typeof t||""!==t.attr("text"))},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"actualSpace",{get:function(){var t=this.labelGroup,e=this.valueGroup,n=this.attributes.markerSize,r=t.node().getBBox(),i=r.width,o=r.height,a=e.node().getBBox(),s=a.width,l=a.height;return{markerWidth:n,labelWidth:i,valueWidth:s,height:Math.max(n,o,l)}},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"span",{get:function(){var t=this.attributes.span;if(!t)return[1,1];var e=Ve(Dz(t),2),n=e[0],r=e[1],i=this.showValue?r:0,o=n+i;return[n/o,i/o]},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"shape",{get:function(){var t,e=this.attributes,n=e.markerSize,r=e.width,i=this.actualSpace,o=i.markerWidth,a=i.height,s=this.actualSpace,l=s.labelWidth,u=s.valueWidth,c=Ve(this.spacing,2),h=c[0],d=c[1];if(r){var f=r-n-h-d,p=Ve(this.span,2);l=(t=Ve([p[0]*f,p[1]*f],2))[0],u=t[1]}return{width:o+l+u+h+d,height:a,markerWidth:o,labelWidth:l,valueWidth:u}},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"spacing",{get:function(){var t=this.attributes.spacing;if(!t)return[0,0];var e=Ve(Dz(t),2),n=e[0],r=e[1];return this.showValue?[n,r]:[n,0]},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"layout",{get:function(){var t=this.shape,e=t.markerWidth,n=t.labelWidth,r=t.valueWidth,i=t.width,o=t.height,a=Ve(this.spacing,2),s=a[0];return{height:o,width:i,markerWidth:e,labelWidth:n,valueWidth:r,position:[e/2,e+s,e+n+s+a[1]]}},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"scaleSize",{get:function(){var t=function(t){var e=t.querySelector(xW.marker.class);return e?e.style:{}}(this.markerGroup.node()),e=this.attributes,n=e.markerSize,r=e.markerStrokeWidth,i=void 0===r?t.strokeWidth:r,o=e.markerLineWidth,a=void 0===o?t.lineWidth:o,s=e.markerStroke,l=void 0===s?t.stroke:s,u=+(i||a||(l?1:0))*Math.sqrt(2),c=this.markerGroup.node().getBBox(),h=c.width,d=c.height;return(1-u/Math.max(h,d))*n},enumerable:!1,configurable:!0}),e.prototype.renderMarker=function(t){var e=this,n=this.attributes.marker,r=Fz(this.attributes,"marker");this.markerGroup=t.maybeAppendByClassName(xW.markerGroup,"g").style("zIndex",0),pz(!!n,this.markerGroup,(function(){var t,i=e.markerGroup.node(),o=null===(t=i.childNodes)||void 0===t?void 0:t[0],a="string"==typeof n?new tG({style:{symbol:n},className:xW.marker.name}):n();o?a.nodeName===o.nodeName?o instanceof tG?o.update(Be(Be({},r),{symbol:n})):(!function(t,e){var n,r,i=e.attributes;try{for(var o=Ge(Object.entries(i)),a=o.next();!a.done;a=o.next()){var s=Ve(a.value,2),l=s[0],u=s[1];"id"!==l&&"className"!==l&&t.attr(l,u)}}catch(t){n={error:t}}finally{try{a&&!a.done&&(r=o.return)&&r.call(o)}finally{if(n)throw n.error}}}(o,a),Rz(o).styles(r)):(o.remove(),Rz(a).attr("className",xW.marker.name).styles(r),i.appendChild(a)):(a instanceof tG||Rz(a).attr("className",xW.marker.name).styles(r),i.appendChild(a)),e.markerGroup.node().scale(1/e.markerGroup.node().getScale()[0]);var s=Az(e.markerGroup.node(),e.scaleSize);e.markerGroup.node().style._transform="scale(".concat(s,")")}))},e.prototype.renderLabel=function(t){var e=Fz(this.attributes,"label"),n=e.text,r=Fe(e,["text"]);this.labelGroup=t.maybeAppendByClassName(xW.labelGroup,"g").style("zIndex",0),this.labelGroup.maybeAppendByClassName(xW.label,(function(){return fz(n)})).styles(r)},e.prototype.renderValue=function(t){var e=this,n=Fz(this.attributes,"value"),r=n.text,i=Fe(n,["text"]);this.valueGroup=t.maybeAppendByClassName(xW.valueGroup,"g").style("zIndex",0),pz(this.showValue,this.valueGroup,(function(){e.valueGroup.maybeAppendByClassName(xW.value,(function(){return fz(r)})).styles(i)}))},e.prototype.renderBackground=function(t){var e=this.shape,n=e.width,r=e.height,i=Fz(this.attributes,"background");this.background=t.maybeAppendByClassName(xW.backgroundGroup,"g").style("zIndex",-1),this.background.maybeAppendByClassName(xW.background,"rect").styles(Be({width:n,height:r},i))},e.prototype.adjustLayout=function(){var t=this.layout,e=t.labelWidth,n=t.valueWidth,r=t.height,i=Ve(t.position,3),o=i[0],a=i[1],s=i[2],l=r/2;this.markerGroup.styles({transform:"translate(".concat(o,", ").concat(l,")").concat(this.markerGroup.node().style._transform)}),this.labelGroup.styles({transform:"translate(".concat(a,", ").concat(l,")")}),hz(this.labelGroup.select(xW.label.class).node(),Math.ceil(e)),this.showValue&&(this.valueGroup.styles({transform:"translate(".concat(s,", ").concat(l,")")}),hz(this.valueGroup.select(xW.value.class).node(),Math.ceil(n)))},e.prototype.render=function(t,e){var n=Rz(e),r=t.x,i=void 0===r?0:r,o=t.y,a=void 0===o?0:o;n.styles({transform:"translate(".concat(i,", ").concat(a,")")}),this.renderMarker(n),this.renderLabel(n),this.renderValue(n),this.renderBackground(n),this.adjustLayout()},e}($z),wW=rz({page:"item-page",navigator:"navigator",item:"item"},"items"),kW=function(t,e,n){return void 0===n&&(n=!0),t?e(t):n},MW=function(t){function e(e){var n=t.call(this,e,{data:[],gridRow:1/0,gridCol:void 0,padding:0,width:1e3,height:100,rowPadding:0,colPadding:0,layout:"flex",orientation:"horizontal",click:Le,mouseenter:Le,mouseleave:Le})||this;return n.navigatorShape=[0,0],n}return je(e,t),Object.defineProperty(e.prototype,"pageViews",{get:function(){return this.navigator.getContainer()},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"grid",{get:function(){var t=this.attributes,e=t.gridRow,n=t.gridCol,r=t.data;if(!e&&!n)throw new Error("gridRow and gridCol can not be set null at the same time");return e&&n?[e,n]:e?[e,r.length]:[r.length,n]},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"renderData",{get:function(){var t=this.attributes,e=t.data,n=t.layout,r=Fz(this.attributes,"item"),i=e.map((function(t,i){var o=t.id,a=void 0===o?i:o,s=t.label,l=t.value;return{id:"".concat(a),index:i,style:Be({layout:n,labelText:s,valueText:l},Object.fromEntries(Object.entries(r).map((function(n){var r=Ve(n,2);return[r[0],ez(r[1],[t,i,e])]}))))}}));return i},enumerable:!1,configurable:!0}),e.prototype.getGridLayout=function(){var t=this,e=this.attributes,n=e.orientation,r=e.width,i=e.rowPadding,o=e.colPadding,a=Ve(this.navigatorShape,1)[0],s=Ve(this.grid,2),l=s[0],u=s[1],c=u*l,h=0;return this.pageViews.children.map((function(e,s){var d,f,p=Math.floor(s/c),g=s%c,v=t.ifHorizontal(u,l),m=[Math.floor(g/v),g%v];"vertical"===n&&m.reverse();var y=Ve(m,2),b=y[0],x=y[1],E=(r-a-(u-1)*o)/u,w=e.getBBox().height,k=Ve([0,0],2),M=k[0],S=k[1];return"horizontal"===n?(M=(d=Ve([h,b*(w+i)],2))[0],S=d[1],h=x===u-1?0:h+E+o):(M=(f=Ve([x*(E+o),h],2))[0],S=f[1],h=b===l-1?0:h+w+i),{page:p,index:s,row:b,col:x,pageIndex:g,width:E,height:w,x:M,y:S}}))},e.prototype.getFlexLayout=function(){var t=this.attributes,e=t.width,n=t.height,r=t.rowPadding,i=t.colPadding,o=Ve(this.navigatorShape,1)[0],a=Ve(this.grid,2),s=a[0],l=a[1],u=Ve([e-o,n],2),c=u[0],h=u[1],d=Ve([0,0,0,0,0,0,0,0],8),f=d[0],p=d[1],g=d[2],v=d[3],m=d[4],y=d[5],b=d[6],x=d[7];return this.pageViews.children.map((function(t,e){var n,o,a,u,d=t.getBBox(),E=d.width,w=d.height,k=0===b?0:i,M=b+k+E;return M<=c&&kW(m,(function(t){return t0?(this.navigatorShape=[55,0],t.call(this)):e},enumerable:!1,configurable:!0}),e.prototype.ifHorizontal=function(t,e){return bW(this.attributes.orientation,t,e)},e.prototype.flattenPage=function(t){t.querySelectorAll(wW.item.class).forEach((function(e){t.appendChild(e)})),t.querySelectorAll(wW.page.class).forEach((function(e){t.removeChild(e).destroy()}))},e.prototype.renderItems=function(t){var e=this.attributes,n=e.click,r=e.mouseenter,i=e.mouseleave;this.flattenPage(t);var o=this.dispatchCustomEvent.bind(this);Rz(t).selectAll(wW.item.class).data(this.renderData,(function(t){return t.id})).join((function(t){return t.append((function(t){var e=t.style;return new EW({style:e})})).attr("className",wW.item.name).on("click",(function(){null==n||n(this),o("itemClick",{item:this})})).on("pointerenter",(function(){null==r||r(this),o("itemMouseenter",{item:this})})).on("pointerleave",(function(){null==i||i(this),o("itemMouseleave",{item:this})}))}),(function(t){return t.each((function(t){var e=t.style;this.update(e)}))}),(function(t){return t.remove()}))},e.prototype.relayoutNavigator=function(){var t,e=this.attributes,n=e.layout,r=e.width,i=(null===(t=this.pageViews.children[0])||void 0===t?void 0:t.getBBox().height)||0,o=Ve(this.navigatorShape,2),a=o[0],s=o[1];this.navigator.update("grid"===n?{pageWidth:r-a,pageHeight:i-s}:{})},e.prototype.adjustLayout=function(){var t,e,n=this,r=Object.entries((t=this.itemsLayout,e="page",t.reduce((function(t,n){return(t[n[e]]=t[n[e]]||[]).push(n),t}),{}))).map((function(t){var e=Ve(t,2);return{page:e[0],layouts:e[1]}})),i=We([],Ve(this.navigator.getContainer().children),!1);r.forEach((function(t){var e=t.layouts,r=n.pageViews.appendChild(new Ul({className:wW.page.name}));e.forEach((function(t){var e=t.x,n=t.y,o=t.index,a=t.width,s=t.height,l=i[o];r.appendChild(l),Te(l,"__layout__",t),l.update({x:e,y:n,width:a,height:s})}))})),this.relayoutNavigator()},e.prototype.renderNavigator=function(t){var e=this.attributes.orientation,n=Fz(this.attributes,"nav"),r=oz({orientation:e},n),i=this;return t.selectAll(wW.navigator.class).data(["nav"]).join((function(t){return t.append((function(){return new yW({style:r})})).attr("className",wW.navigator.name).each((function(){i.navigator=this}))}),(function(t){return t.each((function(){this.update(r)}))}),(function(t){return t.remove()})),this.navigator},e.prototype.getBBox=function(){return this.navigator.getBBox()},e.prototype.render=function(t,e){var n=this.attributes.data;if(n&&0!==n.length){var r=this.renderNavigator(Rz(e));this.renderItems(r.getContainer()),this.adjustLayout()}},e.prototype.dispatchCustomEvent=function(t,e){var n=new zs(t,{detail:e});this.dispatchEvent(n)},e}($z),SW=rz({markerGroup:"marker-group",marker:"marker",labelGroup:"label-group",label:"label"},"handle"),NW={showLabel:!0,formatter:function(t){return t.toString()},markerSize:25,markerStroke:"#c5c5c5",markerFill:"#fff",markerLineWidth:1,labelFontSize:12,labelFill:"#c5c5c5",labelText:"",orientation:"vertical",spacing:0};!function(t){function e(e){return t.call(this,e,NW)||this}je(e,t),e.prototype.render=function(t,e){var n=Rz(e).maybeAppendByClassName(SW.markerGroup,"g");this.renderMarker(n);var r=Rz(e).maybeAppendByClassName(SW.labelGroup,"g");this.renderLabel(r)},e.prototype.renderMarker=function(t){var e=this,n=this.attributes,r=n.orientation,i=n.markerSymbol,o=void 0===i?bW(r,"horizontalHandle","verticalHandle"):i;pz(!!o,t,(function(t){var n=Fz(e.attributes,"marker"),r=Be({symbol:o},n);e.marker=t.maybeAppendByClassName(SW.marker,(function(){return new tG({style:r})})).update(r)}))},e.prototype.renderLabel=function(t){var e=this,n=this.attributes,r=n.showLabel,i=n.orientation,o=n.spacing,a=void 0===o?0:o,s=n.formatter;pz(r,t,(function(t){var n,r=Fz(e.attributes,"label"),o=r.text,l=Fe(r,["text"]),u=(null===(n=t.select(SW.marker.class))||void 0===n?void 0:n.node().getBBox())||{},c=u.width,h=void 0===c?0:c,d=u.height,f=Ve(bW(i,[0,(void 0===d?0:d)+a,"center","top"],[h+a,0,"start","middle"]),4),p=f[0],g=f[1],v=f[2],m=f[3];t.maybeAppendByClassName(SW.label,"text").styles(Be(Be({},l),{x:p,y:g,text:s(o).toString(),textAlign:v,textBaseline:m}))}))}}($z);var OW={showTitle:!0,padding:0,orientation:"horizontal",backgroundFill:"transparent",titleText:"",titleSpacing:4,titlePosition:"top-left",titleFill:"#2C3542",titleFontWeight:"bold",titleFontFamily:"sans-serif",titleFontSize:12},TW=oz({},OW,{});oz({},OW,zz(NW,"handle"),{color:["#d0e3fa","#acc7f6","#8daaf2","#6d8eea","#4d73cd","#325bb1","#5a3e75","#8c3c79","#e23455","#e7655b"],indicatorBackgroundFill:"#262626",indicatorLabelFill:"white",indicatorLabelFontSize:12,indicatorVisibility:"hidden",labelAlign:"value",labelDirection:"positive",labelSpacing:5,showHandle:!0,showIndicator:!0,showLabel:!0,slidable:!0,titleText:"",type:"continuous"});var CW=rz({title:"title",titleGroup:"title-group",items:"items",itemsGroup:"items-group",contentGroup:"content-group",ribbonGroup:"ribbon-group",ribbon:"ribbon",handlesGroup:"handles-group",handle:"handle",startHandle:"start-handle",endHandle:"end-handle",labelGroup:"label-group",label:"label",indicator:"indicator"},"legend"),AW=function(t){function e(e){return t.call(this,e,TW)||this}return je(e,t),e.prototype.renderTitle=function(t,e,n){var r=this.attributes,i=r.showTitle,o=r.titleText,a=Ve(Gz(Fz(this.attributes,"title")),2),s=a[0],l=a[1];this.titleGroup=t.maybeAppendByClassName(CW.titleGroup,"g").styles(l);var u=Be(Be({width:e,height:n},s),{text:i?o:""});this.title=this.titleGroup.maybeAppendByClassName(CW.title,(function(){return new fW({style:u})})).update(u)},e.prototype.renderItems=function(t,e){var n=e.x,r=e.y,i=e.width,o=e.height,a=Ve(Gz(Fz(this.attributes,"title",!0)),2),s=a[0],l=a[1],u=Be(Be({},s),{width:i,height:o,x:0,y:0});this.itemsGroup=t.maybeAppendByClassName(CW.itemsGroup,"g").styles(Be(Be({},l),{transform:"translate(".concat(n,", ").concat(r,")")}));var c=this;this.itemsGroup.selectAll(CW.items.class).data(["items"]).join((function(t){return t.append((function(){return new MW({style:u})})).attr("className",CW.items.name).each((function(){c.items=Rz(this)}))}),(function(t){return t.update(u)}),(function(t){return t.remove()}))},e.prototype.adjustLayout=function(){if(this.attributes.showTitle){var t=this.title.node().getAvailableSpace(),e=t.x,n=t.y;this.itemsGroup.node().style.transform="translate(".concat(e,", ").concat(n,")")}},Object.defineProperty(e.prototype,"availableSpace",{get:function(){var t=this.attributes,e=t.showTitle,n=t.width,r=t.height;return e?this.title.node().getAvailableSpace():new tz(0,0,n,r)},enumerable:!1,configurable:!0}),e.prototype.getBBox=function(){var e,n,r=null===(e=this.title)||void 0===e?void 0:e.node(),i=null===(n=this.items)||void 0===n?void 0:n.node();return r&&i?function(t,e){var n=t.attributes,r=n.position,i=n.spacing,o=n.inset,a=n.text,s=t.getBBox(),l=e.getBBox(),u=hW(r),c=Ve(Dz(a?i:0),4),h=c[0],d=c[1],f=c[2],p=c[3],g=Ve(Dz(o),4),v=g[0],m=g[1],y=g[2],b=g[3],x=Ve([p+d,h+f],2),E=x[0],w=x[1],k=Ve([b+m,v+y],2),M=k[0],S=k[1];if("l"===u[0])return new tz(s.x,s.y,l.width+s.width+E+M,Math.max(l.height+S,s.height));if("t"===u[0])return new tz(s.x,s.y,Math.max(l.width+M,s.width),l.height+s.height+w+S);var N=Ve([e.attributes.width||l.width,e.attributes.height||l.height],2),O=N[0],T=N[1];return new tz(l.x,l.y,O+s.width+E+M,T+s.height+w+S)}(r,i):t.prototype.getBBox.call(this)},e.prototype.render=function(t,e){var n=this.attributes,r=n.width,i=n.height,o=n.x,a=void 0===o?0:o,s=n.y,l=void 0===s?0:s,u=Rz(e);e.style.transform="translate(".concat(a,", ").concat(l,")"),this.renderTitle(u,r,i),this.renderItems(u,this.availableSpace),this.adjustLayout()},e}($z),PW={backgroundFill:"#262626",backgroundLineCap:"round",backgroundLineWidth:1,backgroundStroke:"#333",backgroundZIndex:-1,formatter:function(t){return t.toString()},labelFill:"#fff",labelFontSize:12,labelTextBaseline:"middle",padding:[2,4],position:"right",radius:0,zIndex:999},RW=rz({background:"background",labelGroup:"label-group",label:"label"},"indicator"),DW=function(t){function e(e){var n=t.call(this,e,PW)||this;return n.point=[0,0],n.group=n.appendChild(new Ul({})),n.isMutationObserved=!0,n}return je(e,t),e.prototype.renderBackground=function(){if(this.label){var t=this.attributes,e=t.position,n=Ve(Dz(t.padding),4),r=n[0],i=n[1],o=n[2],a=n[3],s=this.label.node().getLocalBounds(),l=s.min,u=s.max,c=new tz(l[0]-a,l[1]-r,u[0]+i-l[0]+a,u[1]+o-l[1]+r),h=this.getPath(e,c),d=Fz(this.attributes,"background");this.background=Rz(this.group).maybeAppendByClassName(RW.background,"path").styles(Be(Be({},d),{d:h})),this.group.appendChild(this.label.node())}},e.prototype.renderLabel=function(){var t=this.attributes,e=t.formatter,n=t.labelText,r=Ve(Gz(Fz(this.attributes,"label")),2),i=r[0],o=r[1];i.text;var a=Fe(i,["text"]);(this.label=Rz(this.group).maybeAppendByClassName(RW.labelGroup,"g").styles(o),n)&&this.label.maybeAppendByClassName(RW.label,(function(){return fz(e(n))})).style("text",e(n).toString()).selectAll("text").styles(a)},e.prototype.adjustLayout=function(){var t=Ve(this.point,2),e=t[0],n=t[1],r=this.attributes,i=r.x,o=r.y;this.group.attr("transform","translate(".concat(i-e,", ").concat(o-n,")"))},e.prototype.getPath=function(t,e){var n=this.attributes.radius,r=e.x,i=e.y,o=e.width,a=e.height,s=[["M",r+n,i],["L",r+o-n,i],["A",n,n,0,0,1,r+o,i+n],["L",r+o,i+a-n],["A",n,n,0,0,1,r+o-n,i+a],["L",r+n,i+a],["A",n,n,0,0,1,r,i+a-n],["L",r,i+n],["A",n,n,0,0,1,r+n,i],["Z"]],l={top:4,right:6,bottom:0,left:2}[t],u=this.createCorner([s[l].slice(-2),s[l+1].slice(-2)]);return s.splice.apply(s,We([l+1,1],Ve(u),!1)),s[0][0]="M",s},e.prototype.createCorner=function(t,e){void 0===e&&(e=10);var n=_z.apply(void 0,We([],Ve(t),!1)),r=Ve(t,2),i=Ve(r[0],2),o=i[0],a=i[1],s=Ve(r[1],2),l=s[0],u=s[1],c=Ve(n?[l-o,[o,l]]:[u-a,[a,u]],2),h=c[0],d=Ve(c[1],2),f=d[0],p=d[1],g=h/2,v=e*(h/Math.abs(h)),m=v/2,y=v*Math.sqrt(3)/2*.8,b=Ve([f,f+g-m,f+g,f+g+m,p],5),x=b[0],E=b[1],w=b[2],k=b[3],M=b[4];return n?(this.point=[w,a-y],[["L",x,a],["L",E,a],["L",w,a-y],["L",k,a],["L",M,a]]):(this.point=[o+y,w],[["L",o,x],["L",o,E],["L",o+y,w],["L",o,k],["L",o,M]])},e.prototype.applyVisibility=function(){"hidden"===this.attributes.visibility?YF(this):$F(this)},e.prototype.bindEvents=function(){this.label.on(Ks.BOUNDS_CHANGED,this.renderBackground)},e.prototype.render=function(){this.renderLabel(),this.renderBackground(),this.adjustLayout(),this.applyVisibility()},e}($z);function LW(t){return void 0===t&&(t=""),{CONTAINER:"".concat(t,"tooltip"),TITLE:"".concat(t,"tooltip-title"),LIST:"".concat(t,"tooltip-list"),LIST_ITEM:"".concat(t,"tooltip-list-item"),NAME:"".concat(t,"tooltip-list-item-name"),MARKER:"".concat(t,"tooltip-list-item-marker"),NAME_LABEL:"".concat(t,"tooltip-list-item-name-label"),VALUE:"".concat(t,"tooltip-list-item-value"),CROSSHAIR_X:"".concat(t,"tooltip-crosshair-x"),CROSSHAIR_Y:"".concat(t,"tooltip-crosshair-y")}}var _W={overflow:"hidden","white-space":"nowrap","text-overflow":"ellipsis"};function IW(t){var e;void 0===t&&(t="");var n=LW(t);return(e={})[".".concat(n.CONTAINER)]={position:"absolute",visibility:"visible","z-index":8,transition:"visibility 0.2s cubic-bezier(0.23, 1, 0.32, 1), left 0.4s cubic-bezier(0.23, 1, 0.32, 1), top 0.4s cubic-bezier(0.23, 1, 0.32, 1)","background-color":"rgba(255, 255, 255, 0.96)","box-shadow":"0 6px 12px 0 rgba(0, 0, 0, 0.12)","border-radius":"4px",color:"rgba(0, 0, 0, 0.65)","font-size":"12px","line-height":"20px",padding:"12px","min-width":"120px","max-width":"360px","font-family":"Roboto-Regular"},e[".".concat(n.TITLE)]={color:"rgba(0, 0, 0, 0.45)"},e[".".concat(n.LIST)]={margin:"0px","list-style-type":"none",padding:"0px"},e[".".concat(n.LIST_ITEM)]={"list-style-type":"none",display:"flex","line-height":"2em","align-items":"center","justify-content":"space-between","white-space":"nowrap"},e[".".concat(n.MARKER)]={width:"8px",height:"8px","border-radius":"50%",display:"inline-block","margin-right":"4px"},e[".".concat(n.NAME)]={display:"flex","align-items":"center","max-width":"216px"},e[".".concat(n.NAME_LABEL)]=Be({flex:1},_W),e[".".concat(n.VALUE)]=Be({display:"inline-block",float:"right",flex:1,"text-align":"right","min-width":"28px","margin-left":"30px",color:"rgba(0, 0, 0, 0.85)"},_W),e[".".concat(n.CROSSHAIR_X)]={position:"absolute",width:"1px","background-color":"rgba(0, 0, 0, 0.25)"},e[".".concat(n.CROSSHAIR_Y)]={position:"absolute",height:"1px","background-color":"rgba(0, 0, 0, 0.25)"},e}var jW=function(t){function e(e){var n,r,i=this,o=null===(r=null===(n=e.style)||void 0===n?void 0:n.template)||void 0===r?void 0:r.prefixCls,a=LW(o);return(i=t.call(this,e,{data:[],x:0,y:0,visibility:"visible",title:"",position:"bottom-right",offset:[5,5],enterable:!1,container:{x:0,y:0},bounding:null,template:{prefixCls:"",container:'
'),title:'
'),item:'
  • \n \n \n {name}\n \n {value}\n
  • ')},style:IW(o)})||this).timestamp=-1,i.prevCustomContentKey=i.attributes.contentKey,i.initShape(),i.render(i.attributes,i),i}return je(e,t),Object.defineProperty(e.prototype,"HTMLTooltipElement",{get:function(){return this.element},enumerable:!1,configurable:!0}),e.prototype.getContainer=function(){return this.element},Object.defineProperty(e.prototype,"elementSize",{get:function(){return{width:this.element.offsetWidth,height:this.element.offsetHeight}},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"HTMLTooltipItemsElements",{get:function(){var t=this.attributes,e=t.data,n=t.template;return e.map((function(t,e){var r=t.name,i=void 0===r?"":r,o=t.color,a=void 0===o?"black":o,s=t.index,l=Fe(t,["name","color","index"]),u=Be({name:i,color:a,index:null!=s?s:e},l);return Cn(function(t,e){return t&&e?t.replace(/\\?\{([^{}]+)\}/g,(function(t,n){return"\\"===t.charAt(0)?t.slice(1):void 0===e[n]?"":e[n]})):t}(n.item,u))}))},enumerable:!1,configurable:!0}),e.prototype.render=function(t,e){this.renderHTMLTooltipElement(),this.updatePosition()},e.prototype.destroy=function(){var e;null===(e=this.element)||void 0===e||e.remove(),t.prototype.destroy.call(this)},e.prototype.show=function(t,e){var n=this;if(void 0!==t&&void 0!==e){var r=function(){n.attributes.x=null!=t?t:n.attributes.x,n.attributes.y=null!=e?e:n.attributes.y,n.updatePosition()};"hidden"===this.element.style.visibility?this.closeTransition(r):r()}this.element.style.visibility="visible"},e.prototype.hide=function(t,e){void 0===t&&(t=0),void 0===e&&(e=0),this.attributes.enterable&&this.isCursorEntered(t,e)||(this.element.style.visibility="hidden")},e.prototype.initShape=function(){var t=this.attributes.template;this.element=Cn(t.container),this.id&&this.element.setAttribute("id",this.id)},e.prototype.renderCustomContent=function(){if(void 0===this.prevCustomContentKey||this.prevCustomContentKey!==this.attributes.contentKey){this.prevCustomContentKey=this.attributes.contentKey;var t=this.attributes.content;t&&("string"==typeof t?this.element.innerHTML=t:Hz(this.element,t))}},e.prototype.renderHTMLTooltipElement=function(){var t,e,n=this.attributes,r=n.template,i=n.title,o=n.enterable,a=n.style,s=n.content,l=LW(r.prefixCls),u=this.element;if(this.element.style.pointerEvents=o?"auto":"none",s)this.renderCustomContent();else{i?(u.innerHTML=r.title,u.getElementsByClassName(l.TITLE)[0].innerHTML=i):null===(e=null===(t=u.getElementsByClassName(l.TITLE))||void 0===t?void 0:t[0])||void 0===e||e.remove();var c=this.HTMLTooltipItemsElements,h=document.createElement("ul");h.className=l.LIST,Hz(h,c);var d=this.element.querySelector(".".concat(l.LIST));d?d.replaceWith(h):u.appendChild(h)}!function(t,e){Object.entries(e).forEach((function(e){var n=Ve(e,2),r=n[0],i=n[1];We([t],Ve(t.querySelectorAll(r)),!1).filter((function(t){return t.matches(r)})).forEach((function(t){t&&(t.style.cssText+=Object.entries(i).reduce((function(t,e){return"".concat(t).concat(e.join(":"),";")}),""))}))}))}(u,a)},e.prototype.getRelativeOffsetFromCursor=function(t){var e=this.attributes,n=e.position,r=e.offset,i=(t||n).split("-"),o={left:[-1,0],right:[1,0],top:[0,-1],bottom:[0,1]},a=this.elementSize,s=a.width,l=a.height,u=[-s/2,-l/2];return i.forEach((function(t){var e=Ve(u,2),n=e[0],i=e[1],a=Ve(o[t],2),c=a[0],h=a[1];u=[n+(s/2+r[0])*c,i+(l/2+r[1])*h]})),u},e.prototype.setOffsetPosition=function(t){var e=Ve(t,2),n=e[0],r=e[1],i=this.attributes,o=i.x,a=void 0===o?0:o,s=i.y,l=void 0===s?0:s,u=i.container,c=u.x,h=u.y;this.element.style.left="".concat(+a+c+n,"px"),this.element.style.top="".concat(+l+h+r,"px")},e.prototype.updatePosition=function(){var t=this.attributes.showDelay,e=void 0===t?60:t,n=Date.now();this.timestamp>0&&n-this.timestampv+s.width,top:pm+s.height},b=[];l.split("-").forEach((function(t){y[t]?b.push(g[t]):b.push(t)}));var x=b.join("-");return this.getRelativeOffsetFromCursor(x)},e.prototype.isCursorEntered=function(t,e){if(this.element){var n=this.element.getBoundingClientRect(),r=n.x,i=n.y,o=n.width,a=n.height;return new tz(r,i,o,a).isPointIn(t,e)}return!1},e.prototype.closeTransition=function(t){var e=this,n=this.element.style.transition;this.element.style.transition="none",t(),setTimeout((function(){e.element.style.transition=n}),10)},e.tag="tooltip",e}($z),BW=function(t){function e(n){var r=t.call(this,oz({},e.defaultOptions,n))||this;return r.hoverColor="#f5f5f5",r.selectedColor="#e6f7ff",r.background=r.appendChild(new ru({})),r.label=r.background.appendChild(new Ul({})),r}return je(e,t),Object.defineProperty(e.prototype,"padding",{get:function(){return Dz(this.style.padding)},enumerable:!1,configurable:!0}),e.prototype.renderLabel=function(){var t=this.style,e=t.label,n=t.value,r=Fz(this.attributes,"label");Rz(this.label).maybeAppend(".label",(function(){return fz(e)})).attr("className","label").styles(r),this.label.attr("__data__",n)},e.prototype.renderBackground=function(){var t=this.label.getBBox(),e=Ve(this.padding,4),n=e[0],r=e[1],i=e[2],o=e[3],a=t.width,s=t.height,l=a+o+r,u=s+n+i,c=Fz(this.attributes,"background"),h=this.style,d=h.width,f=void 0===d?0:d,p=h.height,g=void 0===p?0:p,v=h.selected;this.background.attr(Be(Be({},c),{width:Math.max(l,f),height:Math.max(u,g),fill:v?this.selectedColor:"#fff"})),this.label.attr({transform:"translate(".concat(o,", ").concat((u-s)/2,")")})},e.prototype.render=function(){this.renderLabel(),this.renderBackground()},e.prototype.bindEvents=function(){var t=this;this.addEventListener("pointerenter",(function(){t.style.selected||t.background.attr("fill",t.hoverColor)})),this.addEventListener("pointerleave",(function(){t.style.selected||t.background.attr("fill",t.style.backgroundFill)}));var e=this;this.addEventListener("click",(function(){var n=t.style,r=n.label,i=n.value,o=n.onClick;null==o||o(i,{label:r,value:i},e)}))},e.defaultOptions={style:{value:"",label:"",cursor:"pointer"}},e}($z),FW=function(t){function e(n){var r,i,o=t.call(this,oz({},e.defaultOptions,n))||this;o.currentValue=null===(r=e.defaultOptions.style)||void 0===r?void 0:r.defaultValue,o.isPointerInSelect=!1,o.select=o.appendChild(new ru({className:"select",style:{cursor:"pointer",width:0,height:0}})),o.dropdown=o.appendChild(new ru({className:"dropdown"}));var a=o.style.defaultValue;return a&&(null===(i=o.style.options)||void 0===i?void 0:i.some((function(t){return t.value===a})))&&(o.currentValue=a),o}return je(e,t),e.prototype.setValue=function(t){this.currentValue=t,this.render()},e.prototype.getValue=function(){return this.currentValue},Object.defineProperty(e.prototype,"dropdownPadding",{get:function(){return Dz(this.style.dropdownPadding)},enumerable:!1,configurable:!0}),e.prototype.renderSelect=function(){var t,e=this,n=this.style,r=n.x,i=n.y,o=n.width,a=n.height,s=n.bordered,l=n.showDropdownIcon,u=Fz(this.attributes,"select"),c=Fz(this.attributes,"placeholder");this.select.attr(Be(Be({x:r,y:i,width:o,height:a},u),{fill:"#fff",strokeWidth:s?1:0}));var h=this.dropdownPadding;l&&Rz(this.select).maybeAppend(".dropdown-icon","path").style("d","M-5,-3.5 L0,3.5 L5,-3.5").style("transform","translate(".concat(r+o-10-h[1]-h[3],", ").concat(i+a/2,")")).style("lineWidth",1).style("stroke",this.select.style.stroke);var d=null===(t=this.style.options)||void 0===t?void 0:t.find((function(t){return t.value===e.currentValue})),f=Be({x:r+h[3]},c);Rz(this.select).selectAll(".placeholder").data(d?[]:[1]).join((function(t){return t.append("text").attr("className","placeholder").styles(f).style("y",(function(){var t=this.getBBox();return i+(a-t.height)/2}))}),(function(t){return t.styles(f)}),(function(t){return t.remove()}));var p=Fz(this.attributes,"optionLabel"),g=Be({x:r+h[3]},p);Rz(this.select).selectAll(".value").data(d?[d]:[]).join((function(t){return t.append((function(t){return fz(t.label)})).attr("className","value").styles(g).style("y",(function(){var t=this.getBBox();return i+(a-t.height)/2}))}),(function(t){return t.styles(g)}),(function(t){return t.remove()}))},e.prototype.renderDropdown=function(){var t,e,n=this,r=this.style,i=r.x,o=r.y,a=r.width,s=r.height,l=r.options,u=r.onSelect,c=r.open,h=Fz(this.attributes,"dropdown"),d=Fz(this.attributes,"option"),f=this.dropdownPadding;Rz(this.dropdown).maybeAppend(".dropdown-container","g").attr("className","dropdown-container").selectAll(".dropdown-item").data(l,(function(t){return t.value})).join((function(t){return t.append((function(t){return new BW({className:"dropdown-item",style:Be(Be(Be({},t),d),{width:a-f[1]-f[3],selected:t.value===n.currentValue,onClick:function(t,e,r){n.setValue(t),null==u||u(t,e,r),n.dispatchEvent(new zs("change",{detail:{value:t,option:e,item:r}})),YF(n.dropdown)}})})})).each((function(t,e){var n,r=(null===(n=this.parentNode)||void 0===n?void 0:n.children).reduce((function(t,n,r){return re.time?1:0}))},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"space",{get:function(){var t=this.attributes,e=t.x,n=t.y,r=t.width,i=t.height,o=t.type,a=t.controllerHeight,s=oe(+i-a,0,+i),l=new tz(e,n+ +i-a,+r,a),u=0,c="time"===o?10:s;return{axisBBox:"chart"===o?new tz(e,n+s-(u=35),+r,u):new tz,controllerBBox:l,timelineBBox:new tz(e,n+("time"===o?s:s-c),+r,c-u)}},enumerable:!1,configurable:!0}),e.prototype.setBySliderValues=function(t){var e,n,r=this.data,i=Ve(Array.isArray(t)?t:[0,t],2),o=i[0],a=i[1],s=r.length,l=r[Math.floor(o*s)],u=r[Math.ceil(a*s)-(Array.isArray(t)?0:1)];this.states.values=[null!==(e=null==l?void 0:l.time)&&void 0!==e?e:r[0].time,null!==(n=null==u?void 0:u.time)&&void 0!==n?n:1/0]},e.prototype.setByTimebarValues=function(t){var e,n,r,i=this.data,o=Ve(Array.isArray(t)?t:[void 0,t],2),a=o[0],s=o[1],l=i.find((function(t){return t.time===a})),u=i.find((function(t){return t.time===s}));this.states.values=[null!==(e=null==l?void 0:l.time)&&void 0!==e?e:null===(n=i[0])||void 0===n?void 0:n.time,null!==(r=null==u?void 0:u.time)&&void 0!==r?r:1/0]},e.prototype.setByIndex=function(t){var e,n,r,i,o=this.data,a=Ve(t,2),s=a[0],l=a[1];this.states.values=[null!==(n=null===(e=o[s])||void 0===e?void 0:e.time)&&void 0!==n?n:o[0].time,null!==(i=null===(r=this.data[l])||void 0===r?void 0:r.time)&&void 0!==i?i:1/0]},Object.defineProperty(e.prototype,"sliderValues",{get:function(){var t,e=this.states,n=e.values,r=e.selectionType,i=Ve(Array.isArray(n)?n:[void 0,n],2),o=i[0],a=i[1],s=this.data,l=s.length,u="value"===r;return[(t=s.findIndex((function(t){return t.time===o})),u?0:t>-1?t/l:0),function(){if(a===1/0)return 1;var t=s.findIndex((function(t){return t.time===a}));return t>-1?t/l:u?.5:1}()]},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"values",{get:function(){var t=this.states,e=t.values,n=t.selectionType,r=Ve(Array.isArray(e)?e:[this.data[0].time,e],2),i=r[0],o=r[1];return"value"===n?o:[i,o]},enumerable:!1,configurable:!0}),e.prototype.getDatumByRatio=function(t){var e=this.data,n=e.length;return e[Math.floor(t*(n-1))]},Object.defineProperty(e.prototype,"chartHandleIconShape",{get:function(){var t=this.states.selectionType,e=this.space.timelineBBox.height;return"range"===t?function(t){return new sH({style:{type:t,height:e,iconSize:e/6}})}:function(){return new Kl({style:{x1:0,y1:-e/2,x2:0,y2:e/2,lineWidth:2,stroke:"#c8c8c8"}})}},enumerable:!1,configurable:!0}),e.prototype.getChartStyle=function(t){var e=this,n=t.x,r=t.y,i=t.width,o=t.height,a=this.states,s=a.selectionType,l=a.chartType,u=this.data,c=this.attributes,h=c.type,d=c.labelFormatter,f=Fz(this.attributes,"chart");f.type;var p=Fe(f,["type"]),g="range"===s;if("time"===h)return Be({handleIconShape:function(){return new aH({})},selectionFill:"#2e7ff8",selectionFillOpacity:1,showLabelOnInteraction:!0,handleLabelDy:g?-15:0,autoFitLabel:g,handleSpacing:g?-15:0,trackFill:"#edeeef",trackLength:i,trackOpacity:.5,trackRadius:o/2,trackSize:o/2,type:s,values:this.sliderValues,formatter:function(t){if(d)return d(t);var n=e.getDatumByRatio(t).time;return"number"==typeof n?uH(n):Vz(n,"YYYY-MM-DD HH:mm:ss")},transform:"translate(".concat(n,", ").concat(r,")"),zIndex:1},p);var v="range"===s?5:0,m=u.map((function(t){return t.value}));return Be({handleIconOffset:v,handleIconShape:this.chartHandleIconShape,selectionFill:"#fff",selectionFillOpacity:.5,selectionType:"invert",sparklineSpacing:.1,sparklineColumnLineWidth:0,sparklineColor:"#d4e5fd",sparklineAreaOpacity:1,sparklineAreaLineWidth:0,sparklineData:m,sparklineType:l,sparklineScale:.8,trackLength:i,trackSize:o,type:s,values:this.sliderValues,transform:"translate(".concat(n,", ").concat(r,")"),zIndex:1},p)},e.prototype.renderChart=function(t){void 0===t&&(t=this.space.timelineBBox),this.timeline.update(this.getChartStyle(t))},e.prototype.updateSelection=function(){this.timeline.setValues(this.sliderValues,!0),this.handleSliderChange(this.sliderValues)},e.prototype.getAxisStyle=function(t){var e=this.data,n=this.attributes,r=n.interval,i=n.labelFormatter,o=Fz(this.attributes,"axis"),a=t.x,s=t.y,l=t.width,u=We(We([],Ve(e),!1),[{time:0}],!1).map((function(t,e,n){var r=t.time;return{label:"".concat(r),value:e/(n.length-1),time:r}})),c=Be({startPos:[a,s],endPos:[a+l,s],data:u,labelFilter:function(t,e){return er?"value"===a?[0,0]:"acc"===s?[o(n),o(n)]:[0,o(i-n)]:n<0?"acc"===s?[0,o(i)]:[o(n+r-i),r]:[o(n),o(i)]}(f);return this.setByIndex(g),this.updateSelection(),g},e.prototype.internalBackward=function(t){var e,n,r=this.moveSelection("backward",t);return t||(null===(n=null===(e=this.attributes)||void 0===e?void 0:e.onBackward)||void 0===n||n.call(e),this.dispatchOnChange()),r},e.prototype.backward=function(){this.internalBackward()},e.prototype.internalPlay=function(t){var e,n,r=this,i=this.data,o=this.attributes.loop,a=this.states.speed,s=void 0===a?1:a;this.playInterval=window.setInterval((function(){r.internalForward()[1]!==i.length||o||(r.internalPause(),r.renderController())}),1e3/s),this.states.state="play",!t&&(null===(n=null===(e=this.attributes)||void 0===e?void 0:e.onPlay)||void 0===n||n.call(e))},e.prototype.play=function(){this.internalPlay()},e.prototype.internalPause=function(t){var e,n;clearInterval(this.playInterval),this.states.state="pause",!t&&(null===(n=null===(e=this.attributes)||void 0===e?void 0:e.onPause)||void 0===n||n.call(e))},e.prototype.pause=function(){this.internalPause()},e.prototype.internalForward=function(t){var e,n,r=this.moveSelection("forward",t);return t||(null===(n=null===(e=this.attributes)||void 0===e?void 0:e.onForward)||void 0===n||n.call(e),this.dispatchOnChange()),r},e.prototype.forward=function(){this.internalForward()},e.prototype.handleSpeedChange=function(t){var e,n;this.states.speed=t,"play"===this.states.state&&(this.internalPause(!0),this.internalPlay(!0)),null===(n=null===(e=this.attributes)||void 0===e?void 0:e.onSpeedChange)||void 0===n||n.call(e,t)},e.prototype.handleSelectionTypeChange=function(t){var e,n;this.states.selectionType=t,this.renderChart(),null===(n=null===(e=this.attributes)||void 0===e?void 0:e.onSelectionTypeChange)||void 0===n||n.call(e,t)},e.prototype.handleChartTypeChange=function(t){var e,n;this.states.chartType=t,this.renderChart(),null===(n=null===(e=this.attributes)||void 0===e?void 0:e.onChartTypeChange)||void 0===n||n.call(e,t)},e.prototype.render=function(){var t=this.space,e=t.axisBBox,n=t.controllerBBox,r=t.timelineBBox;this.renderController(n),this.renderAxis(e),this.renderChart(r),"play"===this.states.state&&this.internalPlay()},e.prototype.destroy=function(){t.prototype.destroy.call(this),this.internalPause(!0)},e.defaultOptions={style:{x:0,y:0,axisLabelFill:"#6e6e6e",axisLabelTextAlign:"left",axisLabelTextBaseline:"top",axisLabelTransform:"translate(5, -12)",axisLineLineWidth:1,axisLineStroke:"#cacdd1",axisTickLength:15,axisTickLineWidth:1,axisTickStroke:"#cacdd1",chartShowLabel:!1,chartType:"line",controllerAlign:"center",controllerHeight:40,data:[],interval:"day",loop:!1,playMode:"acc",selectionType:"range",type:"time"}},e}($z);function hH(t){const{width:e,height:n,renderer:r}=t,i=function(t){var e;const{container:n,className:r,graphCanvas:i}=t;if(n)return"string"==typeof n?document.getElementById(n):n;const o=rB(r,!1),{width:a,height:s,containerStyle:l}=t,[u,c]=function(t){const{width:e,height:n,placement:r,graphCanvas:i}=t,[o,a]=i.getSize(),[s,l]=ad(r);return[s*(o-e),l*(a-n)]}(t);return Object.assign(o.style,Object.assign({position:"absolute",left:u+"px",top:c+"px",width:a+"px",height:s+"px"},l)),null===(e=i.getContainer())||void 0===e||e.appendChild(o),o}(t);return[i,new bu({width:e,height:n,container:i,renderer:r||new Dp})]}class dH extends nB{constructor(e,n){super(e,Object.assign({},dH.defaultOptions,n)),this.typePrefix="__data__",this.draw=!1,this.fieldMap={node:new Map,edge:new Map,combo:new Map},this.selectedItems=[],this.bindEvents=()=>{const{graph:e}=this.context;e.on(t.GraphEvent.AFTER_DRAW,this.createElement)},this.changeState=(t,e)=>{const{graph:n}=this.context,{typePrefix:r}=this,i=Oe(t,[r,"id"]),o=Oe(t,[r,"style","labelText"]),[a]=i.split("__"),s=this.fieldMap[a].get(o)||[];n.setElementState(Object.fromEntries(null==s?void 0:s.map((t=>[t,e]))))},this.click=t=>{if("hover"===this.options.trigger)return;const e=Oe(t,[this.typePrefix,"id"]);this.selectedItems.includes(e)?(this.selectedItems=this.selectedItems.filter((t=>t!==e)),this.changeState(t,[])):(this.selectedItems.push(e),this.changeState(t,"selected"))},this.mouseleave=t=>{"click"!==this.options.trigger&&(this.selectedItems=[],this.changeState(t,[]))},this.mouseenter=t=>{if("click"===this.options.trigger)return;const e=Oe(t,[this.typePrefix,"id"]);this.selectedItems.includes(e)?this.selectedItems=this.selectedItems.filter((t=>t!==e)):(this.selectedItems.push(e),this.changeState(t,"active"))},this.setFieldMap=(t,e,n)=>{if(!t)return;const r=this.fieldMap[n];if(r)if(r.has(t)){const n=r.get(t);n&&(n.push(e),r.set(t,n))}else r.set(t,[e])},this.getEvents=()=>({mouseenter:this.mouseenter,mouseleave:this.mouseleave,click:this.click}),this.getMarkerData=(t,e)=>{if(!t)return[];const{model:n,element:r}=this.context,{nodes:i,edges:o,combos:a}=n.getData(),s={},l=e=>Ut(t)?t(e):t,u={node:"circle",edge:"line",combo:"rect"},c={circle:"circle",ellipse:"circle",image:"bowtie",rect:"square",star:"cross",triangle:"triangle",diamond:"diamond",cubic:"dot",line:"hyphen",polyline:"hyphen",quadratic:"hv","cubic-horizontal":"hyphen","cubic-vertical":"line"},h=(t,e)=>{t.forEach((t=>{const{id:n}=t,i=Oe(t,["data",l(t)]),o=(null==r?void 0:r.getElementType(e,t))||"circle",a=((t,e)=>null==r?void 0:r.getElementComputedStyle(t,e))(e,t),h=("edge"===e?null==a?void 0:a.stroke:null==a?void 0:a.fill)||"#1783ff";n&&i&&i.replace(/\s+/g,"")&&(this.setFieldMap(i,n,e),s[i]||(s[i]={id:`${e}__${n}`,label:i,marker:c[o]||u[e],elementType:e,lineWidth:1,stroke:h,fill:h}))}))};switch(e){case"node":h(i,"node");break;case"edge":h(o,"edge");break;case"combo":h(a,"combo");break;default:return[]}return Object.values(s)},this.createElement=()=>{if(this.draw)return void this.updateElement();const t=this.options,{width:e,height:n,nodeField:r,edgeField:i,comboField:o,trigger:a,position:s,container:l,containerStyle:u,className:c}=t,h=Fe(t,["width","height","nodeField","edgeField","comboField","trigger","position","container","containerStyle","className"]),d=this.getMarkerData(r,"node"),f=this.getMarkerData(i,"edge"),p=this.getMarkerData(o,"combo"),g=[...d,...p,...f],v=Object.assign({width:e,height:n,data:g,itemMarkerLineWidth:({lineWidth:t})=>t,itemMarker:({marker:t})=>t,itemMarkerStroke:({stroke:t})=>t,itemMarkerFill:({fill:t})=>t,gridCol:d.length},h,this.getEvents()),m=new AW({className:"legend",style:v});this.category=m;this.upsertCanvas().appendChild(m),this.draw=!0},this.bindEvents()}update(t){super.update(t),this.clear(),this.createElement()}clear(){var t,e;null===(t=this.canvas)||void 0===t||t.destroy(),null===(e=this.container)||void 0===e||e.remove(),this.canvas=void 0,this.container=void 0,this.draw=!1}updateElement(){this.category&&this.category.update({itemMarkerOpacity:({id:t})=>!this.selectedItems.length||this.selectedItems.includes(t)?1:.5,itemLabelOpacity:({id:t})=>!this.selectedItems.length||this.selectedItems.includes(t)?1:.5})}upsertCanvas(){if(this.canvas)return this.canvas;const t=this.context.canvas,[e,n]=t.getSize(),{width:r=e,height:i=n,position:o,container:a,containerStyle:s,className:l}=this.options,[u,c]=hH({width:r,height:i,graphCanvas:t,container:a,containerStyle:s,placement:o,className:"legend"});return this.container=u,l&&u.classList.add(l),this.canvas=c,this.canvas}destroy(){this.clear(),this.context.graph.off(t.GraphEvent.AFTER_DRAW,this.createElement),super.destroy()}}dH.defaultOptions={position:"bottom",trigger:"hover",orientation:"horizontal",layout:"flex",itemSpacing:4,rowPadding:10,colPadding:10,itemMarkerSize:16,itemLabelFontSize:16,width:240,height:160};class fH extends nB{constructor(t,e){super(t,Object.assign({},fH.defaultOptions,e)),this.onDraw=t=>{var e;(null===(e=null==t?void 0:t.data)||void 0===e?void 0:e.render)||this.onRender()},this.shapes=new Map,this.landmarkMap=new Map,this.mask=null,this.isMaskDragging=!1,this.onMaskDragStart=t=>{this.mask&&(this.isMaskDragging=!0,this.mask.setPointerCapture(t.pointerId),this.mask.addEventListener("pointermove",this.onMaskDrag),this.mask.addEventListener("pointerup",this.onMaskDragEnd),this.mask.addEventListener("pointercancel",this.onMaskDragEnd))},this.onMaskDrag=t=>{if(!this.mask||!this.isMaskDragging)return;const{size:[e,n]}=this.options,{movementX:r,movementY:i}=t,{left:o,top:a,width:s,height:l}=this.mask.style,[,,u,c]=this.maskBBox;let h=parseInt(o)+r,d=parseInt(a)+i,f=parseInt(s),p=parseInt(l);h<0&&(h=0),d<0&&(d=0),h+f>e&&(h=gH(e-f,0)),d+p>n&&(d=gH(n-p,0)),f0?(h=gH(h-r,0),f=pH(f+r,e)):r<0&&(f=pH(f-r,e))),p0?(d=gH(d-i,0),p=pH(p+i,n)):i<0&&(p=pH(p-i,n))),Object.assign(this.mask.style,{left:h+"px",top:d+"px",width:f+"px",height:p+"px"});const g=parseInt(o)-h,v=parseInt(a)-d;if(0===g&&0===v)return;const m=this.context.canvas.getCamera().getZoom()/this.canvas.getCamera().getZoom();this.context.graph.translateBy([g*m,v*m],!1)},this.onMaskDragEnd=t=>{this.mask&&(this.isMaskDragging=!1,this.mask.releasePointerCapture(t.pointerId),this.mask.removeEventListener("pointermove",this.onMaskDrag),this.mask.removeEventListener("pointerup",this.onMaskDragEnd),this.mask.removeEventListener("pointercancel",this.onMaskDragEnd))},this.onTransform=Re((()=>{this.isMaskDragging||(this.updateMask(),this.setCamera())}),32,{leading:!0}),this.setOnRender(),this.bindEvents()}update(t){this.unbindEvents(),super.update(t),"delay"in t&&this.setOnRender(),this.bindEvents()}setOnRender(){this.onRender=ye((()=>{this.renderMinimap(),this.renderMask()}),this.options.delay)}bindEvents(){const{graph:e}=this.context;e.on(t.GraphEvent.AFTER_DRAW,this.onDraw),e.on(t.GraphEvent.AFTER_RENDER,this.onRender),e.on(t.GraphEvent.AFTER_TRANSFORM,this.onTransform)}unbindEvents(){const{graph:e}=this.context;e.off(t.GraphEvent.AFTER_DRAW,this.onDraw),e.off(t.GraphEvent.AFTER_RENDER,this.onRender),e.off(t.GraphEvent.AFTER_TRANSFORM,this.onTransform)}renderMinimap(){const t=this.getElements(),e=this.initCanvas();this.setShapes(e,t)}getElements(){const{filter:t}=this.options,{model:e}=this.context,n=e.getData();if(!t)return n;const{nodes:r,edges:i,combos:o}=n;return{nodes:r.filter((e=>t(Nh(e),"node"))),edges:i.filter((e=>t(Nh(e),"edge"))),combos:o.filter((e=>t(Nh(e),"combo")))}}setShapes(t,e){const{nodes:n,edges:r,combos:i}=e,{shape:o}=this.options,{element:a}=this.context;if("key"===o){const e=new Set,o=n=>{const r=Nh(n);e.add(r);const i=a.getElement(r);if(!i)return;const o=i.getShape("key"),s=this.shapes.get(r)||o.cloneNode();s.setPosition(o.getPosition()),i.style.zIndex&&(s.style.zIndex=i.style.zIndex),s.id=i.id,this.shapes.has(r)?Object.entries(o.attributes).forEach((([t,e])=>{s.style[t]!==e&&(s.style[t]=e)})):(t.appendChild(s),this.shapes.set(r,s))};return r.forEach(o),i.forEach(o),n.forEach(o),void this.shapes.forEach(((n,r)=>{e.has(r)||(t.removeChild(n),this.shapes.delete(r))}))}const s=(t,e)=>{const n=a.getElement(t).getPosition();return e.setPosition(n),e};t.removeChildren(),r.forEach((e=>t.appendChild(o(Nh(e),"edge")))),i.forEach((e=>{t.appendChild(s(Nh(e),o(Nh(e),"combo")))})),n.forEach((e=>{t.appendChild(s(Nh(e),o(Nh(e),"node")))}))}initCanvas(){const{renderer:t,size:[e,n]}=this.options;if(this.canvas){const{width:r,height:i}=this.canvas.getConfig();e===r&&n===i||this.canvas.resize(e,n),t&&this.canvas.setRenderer(t)}else{const{className:r,position:i,container:o,containerStyle:a}=this.options,[s,l]=hH({renderer:t,width:e,height:n,placement:i,className:"minimap",container:o,containerStyle:a,graphCanvas:this.context.canvas});r&&s.classList.add(r),this.container=s,this.canvas=l}return this.setCamera(),this.canvas}createLandmark(t,e,n){const r=`${t.join(",")}-${e.join(",")}-${n}`;if(this.landmarkMap.has(r))return this.landmarkMap.get(r);const i=this.canvas.getCamera().createLandmark(r,{position:t,focalPoint:e,zoom:n});return this.landmarkMap.set(r,i),i}setCamera(){var t;const{canvas:e}=this.context,n=null===(t=this.canvas)||void 0===t?void 0:t.getCamera();if(!n)return;const{size:[r,i],padding:o}=this.options,[a,s,l,u]=Jc(o),{min:c,max:h,center:d}=e.getBounds("elements"),f=(r-u-s)/(h[0]-c[0]),p=(i-a-l)/(h[1]-c[1]),g=Math.min(f,p),v=this.createLandmark(d,d,g);n.gotoLandmark(v,0)}get maskBBox(){const{canvas:t}=this.context,e=t.getSize(),n=t.getCanvasByViewport([0,0]),r=t.getCanvasByViewport(e),i=this.canvas.canvas2Viewport(hd(n)),o=this.canvas.canvas2Viewport(hd(r)),a=o.x-i.x,s=o.y-i.y;return[i.x,i.y,a,s]}calculateMaskBBox(){const{size:[t,e]}=this.options;let[n,r,i,o]=this.maskBBox;return n<0&&(i=pH(i+n,t),n=0),r<0&&(o=pH(o+r,e),r=0),n+i>t&&(i=gH(t-n,0)),r+o>e&&(o=gH(e-r,0)),[pH(n,t),pH(r,e),gH(i,0),gH(o,0)]}renderMask(){const{maskStyle:t}=this.options;this.mask||(this.mask=document.createElement("div"),this.mask.addEventListener("pointerdown",this.onMaskDragStart),this.mask.draggable=!0,this.mask.addEventListener("dragstart",(t=>t.preventDefault&&t.preventDefault()))),this.container.appendChild(this.mask),Object.assign(this.mask.style,Object.assign(Object.assign({},t),{cursor:"move",position:"absolute",pointerEvents:"auto"})),this.updateMask()}updateMask(){if(!this.mask)return;const[t,e,n,r]=this.calculateMaskBBox();Object.assign(this.mask.style,{top:e+"px",left:t+"px",width:n+"px",height:r+"px"})}destroy(){var t;this.unbindEvents(),this.canvas.destroy(),null===(t=this.mask)||void 0===t||t.remove(),super.destroy()}}fH.defaultOptions={size:[240,160],shape:"key",padding:10,position:"right-bottom",maskStyle:{border:"1px solid #ddd",background:"rgba(0, 0, 0, 0.1)"},containerStyle:{border:"1px solid #ddd",background:"#fff"},delay:128};const pH=(t,e)=>Math.min(t,e),gH=(t,e)=>Math.max(t,e),vH={x1:0,y1:0,x2:0,y2:0,visibility:"hidden"};class mH extends nB{constructor(t,e){super(t,Object.assign({},mH.defaultOptions,e)),this.initSnapline=()=>{const t=this.context.canvas.getLayer("transient");this.horizontalLine||(this.horizontalLine=t.appendChild(new Kl({style:Object.assign(Object.assign({},vH),this.options.horizontalLineStyle)}))),this.verticalLine||(this.verticalLine=t.appendChild(new Kl({style:Object.assign(Object.assign({},vH),this.options.verticalLineStyle)})))},this.isHorizontalSticking=!1,this.isVerticalSticking=!1,this.enableStick=!0,this.autoSnapToLine=(t,e,n)=>ze(this,void 0,void 0,(function*(){const{verticalX:r,horizontalY:i}=n,{tolerance:o}=this.options,{min:[a,s],max:[l,u],center:[c,h]}=e;let d=0,f=0;null!==r&&(yH(l,r){const{target:e}=t,n=.5;if(this.isHorizontalSticking||this.isVerticalSticking){const[r,i]=this.getDelta(t);if(this.isHorizontalSticking&&this.isVerticalSticking&&Math.abs(r)<=n&&Math.abs(i)<=n)return this.context.graph.translateElementBy({[e.id]:[-r,-i]},!1),!1;if(this.isHorizontalSticking&&Math.abs(i)<=n)return this.context.graph.translateElementBy({[e.id]:[0,-i]},!1),!1;if(this.isVerticalSticking&&Math.abs(r)<=n)return this.context.graph.translateElementBy({[e.id]:[-r,0]},!1),!1;this.isHorizontalSticking=!1,this.isVerticalSticking=!1,this.enableStick=!1,setTimeout((()=>{this.enableStick=!0}),200)}return this.enableStick},this.calcSnaplineMetadata=(t,e)=>{const{tolerance:n,shape:r}=this.options,{min:[i,o],max:[a,s],center:[l,u]}=e;let c=null,h=null,d=null,f=null,p=null,g=null;return this.getNodes().some((e=>{if(Ne(t.id,e.id))return!1;const v=bH(e,r).getRenderBounds(),{min:[m,y],max:[b,x],center:[E,w]}=v;return null===c&&(yH(E,l){this.initSnapline()},this.onDrag=t=>ze(this,void 0,void 0,(function*(){const{target:e}=t;if(this.options.autoSnap){if(!this.enableSnap(t))return}const n=bH(e,this.options.shape).getRenderBounds(),r=this.calcSnaplineMetadata(e,n);this.hideSnapline(),null===r.verticalX&&null===r.horizontalY||this.updateSnapline(r),this.options.autoSnap&&(yield this.autoSnapToLine(e.id,n,r))})),this.onDragEnd=()=>{this.hideSnapline()},this.bindEvents()}getNodes(){var t;const{filter:e}=this.options,n=((null===(t=this.context.element)||void 0===t?void 0:t.getNodes())||[]).filter((t=>{var e;return"hidden"!==Oe(t,["style","visibility"])&&(null===(e=this.context.viewport)||void 0===e?void 0:e.isInViewport(t.getRenderBounds()))}));return e?n.filter((t=>e(t))):n}hideSnapline(){this.horizontalLine.style.visibility="hidden",this.verticalLine.style.visibility="hidden"}getLineWidth(t){const{lineWidth:e}=this.options[`${t}LineStyle`];return+(e||vH.lineWidth||1)/this.context.graph.getZoom()}updateSnapline(t){const{verticalX:e,verticalMinY:n,verticalMaxY:r,horizontalY:i,horizontalMinX:o,horizontalMaxX:a}=t,[s,l]=this.context.canvas.getSize(),{offset:u}=this.options;null!==i?Object.assign(this.horizontalLine.style,{x1:u===1/0?0:o-u,y1:i,x2:u===1/0?s:a+u,y2:i,visibility:"visible",lineWidth:this.getLineWidth("horizontal")}):this.horizontalLine.style.visibility="hidden",null!==e?Object.assign(this.verticalLine.style,{x1:e,y1:u===1/0?0:n-u,x2:e,y2:u===1/0?l:r+u,visibility:"visible",lineWidth:this.getLineWidth("vertical")}):this.verticalLine.style.visibility="hidden"}getDelta(t){const e=this.context.graph.getZoom();return Yh([t.dx,t.dy],e)}bindEvents(){return ze(this,void 0,void 0,(function*(){const{graph:e}=this.context;e.on(t.NodeEvent.DRAG_START,this.onDragStart),e.on(t.NodeEvent.DRAG,this.onDrag),e.on(t.NodeEvent.DRAG_END,this.onDragEnd)}))}unbindEvents(){const{graph:e}=this.context;e.off(t.NodeEvent.DRAG_START,this.onDragStart),e.off(t.NodeEvent.DRAG,this.onDrag),e.off(t.NodeEvent.DRAG_END,this.onDragEnd)}destroyElements(){var t,e;null===(t=this.horizontalLine)||void 0===t||t.destroy(),null===(e=this.verticalLine)||void 0===e||e.destroy()}destroy(){this.destroyElements(),this.unbindEvents(),super.destroy()}}mH.defaultOptions={tolerance:5,offset:20,autoSnap:!0,shape:"key",verticalLineStyle:{stroke:"#1783FF"},horizontalLineStyle:{stroke:"#1783FF"},filter:()=>!0};const yH=(t,e)=>Math.abs(t-e),bH=(t,e)=>"function"==typeof e?e(t):t.getShape(e),xH=["timestamp","time","date","datetime"];class EH extends nB{get padding(){return Jc(this.options.padding)}constructor(t,e){super(t,Object.assign({},EH.defaultOptions,e)),this.backup(),this.upsertTimebar()}play(){var t;null===(t=this.timebar)||void 0===t||t.play()}pause(){var t;null===(t=this.timebar)||void 0===t||t.pause()}forward(){var t;null===(t=this.timebar)||void 0===t||t.forward()}backward(){var t;null===(t=this.timebar)||void 0===t||t.backward()}reset(){var t;null===(t=this.timebar)||void 0===t||t.reset()}update(t){super.update(t),this.backup(),this.upsertTimebar()}backup(){this.originalData=wH(this.context.graph.getData())}upsertTimebar(){const{canvas:t}=this.context,e=this.options,{onChange:n,timebarType:r,data:i,x:o,y:a,width:s,height:l,mode:u}=e,c=Fe(e,["onChange","timebarType","data","x","y","width","height","mode"]),h=t.getSize(),[d]=this.padding;this.upsertCanvas().ready.then((()=>{var t;const e=Object.assign(Object.assign({x:h[0]/2-s/2,y:d,onChange:t=>{const e=(Yt(t)?t:[t,t]).map((t=>function(t){return t instanceof Date}(t)?t.getTime():t));"modify"===this.options.mode?this.filterElements(e):this.hiddenElements(e),null==n||n(e)}},c),{data:i.map((t=>ae(t)?{time:t,value:0}:t)),width:s,height:l,type:r});this.timebar?this.timebar.update(e):(this.timebar=new cH({style:e}),null===(t=this.canvas)||void 0===t||t.appendChild(this.timebar))}))}upsertCanvas(){if(this.canvas)return this.canvas;const{className:t,height:e,position:n}=this.options,r=this.context.canvas,[i]=r.getSize(),[o,,a]=this.padding,[s,l]=hH({width:i,height:e+o+a,graphCanvas:r,className:"timebar",placement:n});return this.container=s,t&&s.classList.add(t),this.canvas=l,this.canvas}filterElements(t){return ze(this,void 0,void 0,(function*(){var e;if(!this.originalData)return;const{elementTypes:n,getTime:r}=this.options,{graph:i,element:o}=this.context,a=wH(this.originalData);n.forEach((e=>{const n=`${e}s`;a[n]=(this.originalData[n]||[]).filter((e=>{const n=r(e);return!!kH(n,t)}))}));const s=[...a.nodes,...a.combos].map((t=>Nh(t)));a.edges=a.edges.filter((t=>{const e=t.source,n=t.target;return s.includes(e)&&s.includes(n)})),i.setData(a),yield null===(e=o.draw({animation:!1,silence:!0}))||void 0===e?void 0:e.finished}))}hiddenElements(t){const{graph:e}=this.context,{elementTypes:n,getTime:r}=this.options,i=[],o=[];n.forEach((e=>{var n;const a=`${e}s`;((null===(n=this.originalData)||void 0===n?void 0:n[a])||[]).forEach((e=>{const n=Nh(e),a=r(e);kH(a,t)?o.push(n):i.push(n)}))})),e.hideElement(i,!1),e.showElement(o,!1)}destroy(){var t,e,n;const{graph:r}=this.context;this.originalData&&r.setData(Object.assign({},this.originalData)),null===(t=this.timebar)||void 0===t||t.destroy(),null===(e=this.canvas)||void 0===e||e.destroy(),null===(n=this.container)||void 0===n||n.remove(),this.originalData=void 0,this.container=void 0,this.timebar=void 0,this.canvas=void 0,super.destroy()}}EH.defaultOptions={position:"bottom",enable:!0,timebarType:"time",className:"g6-timebar",width:450,height:60,zIndex:3,elementTypes:["node"],padding:10,mode:"modify",getTime:t=>MH(t,xH,void 0),loop:!1};const wH=t=>{const{nodes:e=[],edges:n=[],combos:r=[]}=t;return{nodes:[...e],edges:[...n],combos:[...r]}},kH=(t,e)=>{if(ae(e))return t===e;const[n,r]=e;return t>=n&&t<=r},MH=(t,e,n)=>{var r;for(let n=0;n{const{onClick:e}=this.options;if(t.target instanceof Element&&t.target.className.includes("g6-toolbar-item")){const n=t.target.getAttribute("value");null==e||e(n,t.target)}};const n=this.context.canvas.getContainer();this.$element.style.display="flex",n.appendChild(this.$element),iB("g6-toolbar-css","style",{},"\n .g6-toolbar {\n position: absolute;\n z-index: 100;\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.1);\n opacity: 0.65;\n }\n .g6-toolbar .g6-toolbar-item {\n display: inline-block;\n width: 16px;\n height: 16px;\n padding: 4px;\n cursor: pointer;\n box-sizing: content-box;\n }\n\n .g6-toolbar .g6-toolbar-item:hover {\n background-color: #f0f0f0;\n }\n\n .g6-toolbar .g6-toolbar-item svg {\n display: inline-block;\n width: 100%;\n height: 100%;\n pointer-events: none;\n }\n",document.head),iB("g6-toolbar-svgicon","div",{display:"none"},'\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n'),this.$element.addEventListener("click",this.onToolbarItemClick),this.update(e)}update(t){const e=Object.create(null,{update:{get:()=>super.update}});return ze(this,void 0,void 0,(function*(){e.update.call(this,t);const{className:n,position:r,style:i}=this.options;this.$element.className=`g6-toolbar ${n||""}`,Object.assign(this.$element.style,i,function(t){const e={top:"unset",right:"unset",bottom:"unset",left:"unset"};return t.split("-").forEach((t=>{e[t]="8px"})),e.flexDirection=t.startsWith("top")||t.startsWith("bottom")?"row":"column",e}(r)),this.$element.innerHTML=yield this.getDOMContent()}))}destroy(){this.$element.removeEventListener("click",this.onToolbarItemClick),this.$element.remove(),super.destroy()}getDOMContent(){return ze(this,void 0,void 0,(function*(){return(yield this.options.getItems()).map((t=>{var e;return`\n
    \n \n
    `})).join("")}))}}SH.defaultOptions={position:"top-left"};class NH extends nB{constructor(t,e){super(t,Object.assign({},NH.defaultOptions,e)),this.currentTarget=null,this.tooltipElement=null,this.container=null,this.isEnable=(t,e)=>{const{enable:n}=this.options;return"function"==typeof n?n(t,e):n},this.onClick=t=>{const{target:{id:e}}=t;this.currentTarget===e?this.hide(t):this.show(t)},this.onPointerMove=t=>{const{target:e}=t;this.currentTarget&&e.id!==this.currentTarget&&this.show(t)},this.onPointerLeave=t=>{this.hide(t)},this.onCanvasMove=t=>{this.hide(t)},this.onPointerEnter=t=>{this.show(t)},this.showById=t=>ze(this,void 0,void 0,(function*(){const e={target:{id:t}};yield this.show(e)})),this.getElementData=(t,e)=>{const{model:n}=this.context;switch(e){case"node":return n.getNodeData([t]);case"edge":return n.getEdgeData([t]);case"combo":return n.getComboData([t]);default:return[]}},this.show=t=>ze(this,void 0,void 0,(function*(){var e,n;const{client:r,target:{id:i}}=t;if(Hg(t.target))return;const o=this.context.graph.getElementType(i),{getContent:a,title:s}=this.options,l=this.getElementData(i,o);if(!this.tooltipElement||!this.isEnable(t,l))return;let u,c,h={};if(a){if(h.content=yield a(t,l),!h.content)return}else{const t=this.context.graph.getElementRenderStyle(i),e="node"===o?t.fill:t.stroke;h={title:s||o,data:l.map((t=>({name:"ID",value:t.id||`${t.source} -> ${t.target}`,color:e})))}}if(this.currentTarget=i,r)u=r.x,c=r.y;else{const t=Oe(l,"0.style",{x:0,y:0});u=t.x,c=t.y}null===(n=(e=this.options).onOpenChange)||void 0===n||n.call(e,!0),this.tooltipElement.update(Object.assign(Object.assign(Object.assign({},this.tooltipStyleProps),{x:u,y:c,style:{".tooltip":{visibility:"visible"}}}),h))})),this.hide=t=>{var e,n,r,i,o;if(!t)return null===(n=(e=this.options).onOpenChange)||void 0===n||n.call(e,!1),null===(r=this.tooltipElement)||void 0===r||r.hide(),void(this.currentTarget=null);if(!this.tooltipElement)return;if(!this.currentTarget)return;const{client:{x:a,y:s}}=t;null===(o=(i=this.options).onOpenChange)||void 0===o||o.call(i,!1),this.tooltipElement.hide(a,s),this.currentTarget=null},this.initTooltip=()=>{var t;const e=new jW({className:"tooltip",style:this.tooltipStyleProps});return null===(t=this.container)||void 0===t||t.appendChild(e.HTMLTooltipElement),e},this.render(),this.bindEvents()}getEvents(){return"click"===this.options.trigger?{"node:click":this.onClick,"edge:click":this.onClick,"combo:click":this.onClick,"canvas:click":this.onPointerLeave,contextmenu:this.onPointerLeave,drag:this.onPointerLeave}:{"node:pointerenter":this.onPointerEnter,"node:pointermove":this.onPointerMove,"canvas:pointermove":this.onCanvasMove,"edge:pointerenter":this.onPointerEnter,"edge:pointermove":this.onPointerMove,"combo:pointerenter":this.onPointerEnter,"combo:pointermove":this.onPointerMove,contextmenu:this.onPointerLeave,"node:drag":this.onPointerLeave}}update(t){var e;this.unbindEvents(),super.update(t),this.tooltipElement&&(null===(e=this.container)||void 0===e||e.removeChild(this.tooltipElement.HTMLTooltipElement)),this.tooltipElement=this.initTooltip(),this.bindEvents()}render(){const{canvas:t}=this.context,e=t.getContainer();e&&(this.container=e,this.tooltipElement=this.initTooltip())}unbindEvents(){const{graph:t}=this.context,e=this.getEvents();Object.keys(e).forEach((n=>{t.off(n,e[n])}))}bindEvents(){const{graph:t}=this.context,e=this.getEvents();Object.keys(e).forEach((n=>{t.on(n,e[n])}))}get tooltipStyleProps(){const{canvas:t}=this.context,{center:e}=t.getBounds(),n=t.getContainer(),{top:r,left:i}=n.getBoundingClientRect(),{style:o,position:a,enterable:s,container:l={x:-i,y:-r},title:u,offset:c}=this.options,[h,d]=e,[f,p]=t.getSize();return{x:h,y:d,container:l,title:u,bounding:{x:0,y:0,width:f,height:p},position:a,enterable:s,offset:c,style:o}}destroy(){var t;this.unbindEvents(),this.tooltipElement&&(null===(t=this.container)||void 0===t||t.removeChild(this.tooltipElement.HTMLTooltipElement)),super.destroy()}}let OH;function TH(t,e){OH||(OH=document.createElement("canvas")),OH.width=t,OH.height=e;return OH.getContext("2d").clearRect(0,0,t,e),OH}NH.defaultOptions={trigger:"hover",position:"top-right",enterable:!1,enable:!0,offset:[10,10],style:{".tooltip":{visibility:"hidden"}}};class CH extends nB{constructor(t,e){super(t,Object.assign({},CH.defaultOptions,e)),this.$element=rB("watermark");this.context.canvas.getContainer().appendChild(this.$element),this.update(e)}update(t){const e=Object.create(null,{update:{get:()=>super.update}});return ze(this,void 0,void 0,(function*(){e.update.call(this,t);const n=this.options,{width:r,height:i,text:o,imageURL:a}=n,s=Fe(n,["width","height","text","imageURL"]);Object.keys(s).forEach((e=>{e.startsWith("background")&&(this.$element.style[e]=t[e])}));const l=a?yield function(t,e,n,r){return ze(this,void 0,void 0,(function*(){const i=TH(t,e),o=i.getContext("2d"),{rotate:a,opacity:s}=r;a&&o.rotate(a),s&&(o.globalAlpha=s);const l=new Image;return l.crossOrigin="anonymous",l.src=n,new Promise((n=>{l.onload=function(){const r=t>l.width?(t-l.width)/2:0,a=e>l.height?(e-l.height)/2:0;o.drawImage(l,0,0,l.width,l.height,r,a,t-2*r,e-2*a),n(i.toDataURL())}}))}))}(r,i,a,s):yield function(t,e,n,r){return ze(this,void 0,void 0,(function*(){const i=TH(t,e),o=i.getContext("2d"),{rotate:a,opacity:s,textFill:l,textFontSize:u,textFontFamily:c,textFontVariant:h,textFontWeight:d,textAlign:f,textBaseline:p}=r;return o.textAlign=f,o.textBaseline=p,o.translate(t/2,e/2),o.font=`${u}px ${c} ${h} ${d}`,a&&o.rotate(a),s&&(o.globalAlpha=s),l&&(o.fillStyle=l,o.fillText(`${n}`,0,0)),i.toDataURL()}))}(r,i,o,s);this.$element.style.backgroundImage=`url(${l})`}))}destroy(){super.destroy(),this.$element.remove()}}CH.defaultOptions={width:200,height:100,opacity:.2,rotate:Math.PI/12,text:"",textFill:"#000",textFontSize:16,textAlign:"center",textBaseline:"middle",backgroundRepeat:"repeat"};const AH=["#7E92B5","#F4664A","#FFBE3A"],PH={type:"group",color:["#1783FF","#00C9C9","#F08F56","#D580FF","#7863FF","#DB9D0D","#60C42D","#FF80CA","#2491B3","#17C76F"]},RH={type:"group",color:["#99ADD1","#1783FF","#00C9C9","#F08F56","#D580FF","#7863FF","#DB9D0D","#60C42D","#FF80CA","#2491B3","#17C76F"]};function DH(t){const{bgColor:e,textColor:n,nodeColor:r,nodeColorDisabled:i,nodeStroke:o,nodeHaloStrokeOpacityActive:a=.15,nodeHaloStrokeOpacitySelected:s=.25,nodeOpacityDisabled:l=.06,nodeIconOpacityInactive:u=.85,nodeOpacityInactive:c=.25,nodeBadgePalette:h=AH,nodePaletteOptions:d=PH,edgeColor:f,edgeColorDisabled:p,edgePaletteOptions:g=RH,comboColor:v,comboColorDisabled:m,comboStroke:y,comboStrokeDisabled:b,edgeColorInactive:x}=t;return{background:e,node:{palette:d,style:{donutOpacity:1,badgeBackgroundOpacity:1,badgeFill:"#fff",badgeFontSize:8,badgePadding:[0,4],badgePalette:h,fill:r,fillOpacity:1,halo:!1,iconFill:"#fff",iconOpacity:1,labelBackground:!1,labelBackgroundFill:e,labelBackgroundLineWidth:0,labelBackgroundOpacity:.75,labelFill:n,labelFillOpacity:.85,labelLineHeight:16,labelPadding:[0,2],labelFontSize:12,labelFontWeight:400,labelOpacity:1,labelOffsetY:2,lineWidth:0,portFill:r,portLineWidth:1,portStroke:o,portStrokeOpacity:.65,size:32,stroke:o,strokeOpacity:1,zIndex:2},state:{selected:{halo:!0,haloLineWidth:24,haloStrokeOpacity:s,labelFontSize:12,labelFontWeight:"bold",lineWidth:4,stroke:o},active:{halo:!0,haloLineWidth:12,haloStrokeOpacity:a},highlight:{labelFontWeight:"bold",lineWidth:4,stroke:o,strokeOpacity:.85},inactive:{badgeBackgroundOpacity:c,donutOpacity:c,fillOpacity:c,iconOpacity:u,labelFill:n,labelFillOpacity:c,strokeOpacity:c},disabled:{badgeBackgroundOpacity:.25,donutOpacity:l,fill:i,fillOpacity:l,iconFill:i,iconOpacity:.25,labelFill:n,labelFillOpacity:.25,strokeOpacity:l}},animation:{enter:"fade",exit:"fade",show:"fade",hide:"fade",expand:"node-expand",collapse:"node-collapse",update:[{fields:["x","y","fill","stroke"]}],translate:[{fields:["x","y"]}]}},edge:{palette:g,style:{badgeBackgroundFill:f,badgeFill:"#fff",badgeFontSize:8,badgeOffsetX:10,fillOpacity:1,halo:!1,haloLineWidth:12,haloStrokeOpacity:1,increasedLineWidthForHitTesting:2,labelBackground:!1,labelBackgroundFill:e,labelBackgroundLineWidth:0,labelBackgroundOpacity:.75,labelBackgroundPadding:[4,4,4,4],labelFill:n,labelFontSize:12,labelFontWeight:400,labelOpacity:1,labelPlacement:"center",labelTextBaseline:"middle",lineWidth:1,stroke:f,strokeOpacity:1,zIndex:1},state:{selected:{halo:!0,haloStrokeOpacity:.25,labelFontSize:14,labelFontWeight:"bold",lineWidth:3},active:{halo:!0,haloStrokeOpacity:.15},highlight:{labelFontWeight:"bold",lineWidth:3},inactive:{stroke:x,fillOpacity:.08,labelOpacity:.25,strokeOpacity:.08,badgeBackgroundOpacity:.25},disabled:{stroke:p,fillOpacity:.45,strokeOpacity:.45,labelOpacity:.25,badgeBackgroundOpacity:.45}},animation:{enter:"fade",exit:"fade",expand:"path-in",collapse:"path-out",show:"fade",hide:"fade",update:[{fields:["sourceNode","targetNode"]},{fields:["stroke"],shape:"key"}],translate:[{fields:["sourceNode","targetNode"]}]}},combo:{style:{collapsedMarkerFill:e,collapsedMarkerFontSize:12,collapsedMarkerFillOpacity:1,collapsedSize:32,collapsedFillOpacity:1,fill:v,halo:!1,haloLineWidth:12,haloStroke:y,haloStrokeOpacity:.25,labelBackground:!1,labelBackgroundFill:e,labelBackgroundLineWidth:0,labelBackgroundOpacity:.75,labelBackgroundPadding:[2,4,2,4],labelFill:n,labelFontSize:12,labelFontWeight:400,labelOpacity:1,lineDash:0,lineWidth:1,fillOpacity:.04,strokeOpacity:1,padding:10,stroke:y},state:{selected:{halo:!0,labelFontSize:14,labelFontWeight:700,lineWidth:4},active:{halo:!0},highlight:{labelFontWeight:700,lineWidth:4},inactive:{fillOpacity:.65,labelOpacity:.25,strokeOpacity:.65},disabled:{fill:m,fillOpacity:.25,labelOpacity:.25,stroke:b,strokeOpacity:.25}},animation:{enter:"fade",exit:"fade",show:"fade",hide:"fade",expand:"combo-expand",collapse:"combo-collapse",update:[{fields:["x","y"]},{fields:["fill","stroke","lineWidth"],shape:"key"}],translate:[{fields:["x","y"]}]}}}}const LH=DH({bgColor:"#000000",comboColor:"#fdfdfd",comboColorDisabled:"#d0e4ff",comboStroke:"#99add1",comboStrokeDisabled:"#969696",edgeColor:"#637088",edgeColorDisabled:"#637088",edgeColorInactive:"#D0E4FF",edgePaletteOptions:{type:"group",color:["#637088","#0F55A6","#008383","#9C5D38","#8B53A6","#4E40A6","#8F6608","#3E801D","#A65383","#175E75","#0F8248"]},nodeColor:"#1783ff",nodeColorDisabled:"#D0E4FF",nodeHaloStrokeOpacityActive:.25,nodeHaloStrokeOpacitySelected:.45,nodeIconOpacityInactive:.45,nodeOpacityDisabled:.25,nodeOpacityInactive:.45,nodeStroke:"#d0e4ff",textColor:"#ffffff"}),_H=DH({bgColor:"#ffffff",comboColor:"#99ADD1",comboColorDisabled:"#f0f0f0",comboStroke:"#99add1",comboStrokeDisabled:"#d9d9d9",edgeColor:"#99add1",edgeColorDisabled:"#d9d9d9",edgeColorInactive:"#1B324F",nodeColor:"#1783ff",nodeColorDisabled:"#1B324F",nodeHaloStrokeOpacityActive:.15,nodeHaloStrokeOpacitySelected:.25,nodeIconOpacityInactive:.85,nodeOpacityDisabled:.06,nodeOpacityInactive:.25,nodeStroke:"#000000",textColor:"#000000"});class IH extends zh{beforeDraw(t,e){return t}afterLayout(t,e){}}function jH(t,e,n,r,i){const o=Nh(r),a=`${n}s`,s=i?r:t.add[a].get(o)||t.update[a].get(o)||t.remove[a].get(o)||r;Object.entries(t).forEach((([t,n])=>{e===t?n[a].set(o,s):n[a].delete(o)}))}function BH(t,e){return Object.keys(t).every((n=>t[n]===e[n]))}const FH=(t,e,n,r)=>{const i=`${n}s`,o=Nh(r);t.add[i].has(o)||t.update[i].has(o)||t[e][i].set(Nh(r),r)};const zH=new WeakMap;const GH=(t,e,n=2)=>{if("object"!=typeof t||"object"!=typeof e)return t===e;const r=Object.keys(t),i=Object.keys(e);if(r.length!==i.length)return!1;for(const i of r){const r=t[i],o=e[i];if(n>1&&"object"==typeof r&&"object"==typeof o){if(!GH(r,o,n-1))return!1}else if(r!==o)return!1}return!0};function VH(t,e,n){Rc[t][e]&&Ic(`The extension ${e} of ${t} has been registered before, and will be overridden.`),Object.assign(Rc[t],{[e]:n})} -/*! - * @antv/g-plugin-dragndrop - * @description A G plugin for Drag n Drop implemented with PointerEvents - * @version 2.0.35 - * @date 5/9/2025, 8:20:14 AM - * @author AntVis - * @docs https://g.antv.antgroup.com/ - */var WH=function(){function t(e){s(this,t),this.dragndropPluginOptions=e}return u(t,[{key:"apply",value:function(e){var n=this,r=e.renderingService,i=e.renderingContext.root.ownerDocument,o=i.defaultView,a=function(t){var e=t.target,r=e===i,a=r&&n.dragndropPluginOptions.isDocumentDraggable?i:e.closest&&e.closest("[draggable=true]");if(a){var s=!1,l=t.timeStamp,u=[t.clientX,t.clientY],c=null,h=[t.clientX,t.clientY],d=function(){var t=ar(ir().mark((function t(o){var d,f,p,g,v,m;return ir().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(s){t.next=8;break}if(d=o.timeStamp-l,f=gn([o.clientX,o.clientY],u),!(d<=n.dragndropPluginOptions.dragstartTimeThreshold||f<=n.dragndropPluginOptions.dragstartDistanceThreshold)){t.next=5;break}return t.abrupt("return");case 5:o.type="dragstart",a.dispatchEvent(o),s=!0;case 8:if(o.type="drag",o.dx=o.clientX-h[0],o.dy=o.clientY-h[1],a.dispatchEvent(o),h=[o.clientX,o.clientY],r){t.next=21;break}return p="pointer"===n.dragndropPluginOptions.overlap?[o.canvasX,o.canvasY]:e.getBounds().center,t.next=17,i.elementsFromPoint(p[0],p[1]);case 17:g=t.sent,v=g[g.indexOf(e)+1],m=(null==v?void 0:v.closest("[droppable=true]"))||(n.dragndropPluginOptions.isDocumentDroppable?i:null),c!==m&&(c&&(o.type="dragleave",o.target=c,c.dispatchEvent(o)),m&&(o.type="dragenter",o.target=m,m.dispatchEvent(o)),(c=m)&&(o.type="dragover",o.target=c,c.dispatchEvent(o)));case 21:case"end":return t.stop()}}),t)})));return function(e){return t.apply(this,arguments)}}();o.addEventListener("pointermove",d);var f=function(t){if(s){t.detail={preventClick:!0};var e=t.clone();c&&(e.type="drop",e.target=c,c.dispatchEvent(e)),e.type="dragend",a.dispatchEvent(e),s=!1}o.removeEventListener("pointermove",d)};e.addEventListener("pointerup",f,{once:!0}),e.addEventListener("pointerupoutside",f,{once:!0})}};r.hooks.init.tap(t.tag,(function(){o.addEventListener("pointerdown",a)})),r.hooks.destroy.tap(t.tag,(function(){o.removeEventListener("pointerdown",a)}))}}])}();WH.tag="Dragndrop";var HH=function(t){function e(){var t,n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return s(this,e),(t=v(this,e)).name="dragndrop",t.options=n,t}return y(e,t),u(e,[{key:"init",value:function(){this.addRenderingPlugin(new WH(a({overlap:"pointer",isDocumentDraggable:!1,isDocumentDroppable:!1,dragstartDistanceThreshold:0,dragstartTimeThreshold:0},this.options)))}},{key:"destroy",value:function(){this.removeAllRenderingPlugins()}},{key:"setOptions",value:function(t){Object.assign(this.plugins[0].dragndropPluginOptions,t)}}])}(fr);const UH=["main"],$H=["background","main","label","transient"];class YH{getConfig(){return this.config}getLayer(t="main"){return this.extends.layers[t]||this.getLayers().main}getLayers(){return this.extends.layers}getRenderer(t){return this.extends.renderers[t]}getCamera(t="main"){return this.getLayer(t).getCamera()}getRoot(t="main"){return this.getLayer(t).getRoot()}getContextService(t="main"){return this.getLayer(t).getContextService()}setCursor(t){this.config.cursor=t,this.getLayer().setCursor(t)}get document(){return this.getLayer().document}get context(){return this.getLayer().context}constructor(t){this.config={enableMultiLayer:!0},Object.assign(this.config,t);const e=this.config,{renderer:n,background:r,cursor:i,enableMultiLayer:o}=e,a=Fe(e,["renderer","background","cursor","enableMultiLayer"]),s=o?$H:UH,l=qH(n,s),u=Object.fromEntries(s.map((t=>[t,new bu(Object.assign(Object.assign({},a),{supportsMutipleCanvasesInOneContainer:o,renderer:l[t],background:o?"background"===t?r:void 0:r}))])));XH(u),this.extends={config:this.config,renderer:n,renderers:l,layers:u}}get ready(){return Promise.all(Object.entries(this.getLayers()).map((([,t])=>t.ready)))}resize(t,e){Object.assign(this.extends.config,{width:t,height:e}),Object.values(this.getLayers()).forEach((n=>{const r=n.getCamera(),i=r.getPosition(),o=r.getFocalPoint();n.resize(t,e),r.setPosition(i),r.setFocalPoint(o)}))}getBounds(t){return sh(Object.values(this.getLayers()).map((e=>t?e.getRoot().childNodes.find((e=>e.classList.includes(t))):e.getRoot())).filter((t=>(null==t?void 0:t.childNodes.length)>0)).map((t=>t.getBounds())))}getContainer(){const t=this.extends.config.container;return"string"==typeof t?document.getElementById(t):t}getSize(){return[this.extends.config.width||0,this.extends.config.height||0]}appendChild(t,e){var n;const r=(null===(n=t.style)||void 0===n?void 0:n.$layer)||"main";return this.getLayer(r).appendChild(t,e)}setRenderer(t){if(t===this.extends.renderer)return;const e=qH(t,this.config.enableMultiLayer?$H:UH);this.extends.renderers=e,Object.entries(e).forEach((([t,e])=>this.getLayer(t).setRenderer(e))),XH(this.getLayers())}getCanvasByViewport(t){return cd(this.getLayer().viewport2Canvas(hd(t)))}getViewportByCanvas(t){return cd(this.getLayer().canvas2Viewport(hd(t)))}getViewportByClient(t){return cd(this.getLayer().client2Viewport(hd(t)))}getClientByViewport(t){return cd(this.getLayer().viewport2Client(hd(t)))}getClientByCanvas(t){return this.getClientByViewport(this.getViewportByCanvas(t))}getCanvasByClient(t){const e=this.getLayer(),n=e.client2Viewport(hd(t));return cd(e.viewport2Canvas(n))}toDataURL(){return ze(this,arguments,void 0,(function*(t={}){const e=globalThis.devicePixelRatio||1,{mode:n="viewport"}=t,r=Fe(t,["mode"]);let[i,o,a,s]=[0,0,0,0];if("viewport"===n)[a,s]=this.getSize();else if("overall"===n){const t=this.getBounds(),e=rh(t);[i,o]=t.min,[a,s]=e}const l=Cn('
    '),u=new bu({width:a,height:s,renderer:new Dp,devicePixelRatio:e,container:l,background:this.extends.config.background});yield u.ready,u.appendChild(this.getLayer("background").getRoot().cloneNode(!0)),u.appendChild(this.getRoot().cloneNode(!0));const c=this.getLayer("label").getRoot().cloneNode(!0),h=u.viewport2Canvas({x:0,y:0}),d=this.getCanvasByViewport([0,0]);c.translate([d[0]-h.x,d[1]-h.y]),c.scale(1/this.getCamera().getZoom()),u.appendChild(c),u.appendChild(this.getLayer("transient").getRoot().cloneNode(!0));const f=this.getCamera(),p=u.getCamera();if("viewport"===n)p.setZoom(f.getZoom()),p.setPosition(f.getPosition()),p.setFocalPoint(f.getFocalPoint());else if("overall"===n){const[t,e,n]=p.getPosition(),[r,a,s]=p.getFocalPoint();p.setPosition([t+i,e+o,n]),p.setFocalPoint([r+i,a+o,s])}const g=u.getContextService();return new Promise((t=>{u.addEventListener(fu.RERENDER,(()=>ze(this,void 0,void 0,(function*(){yield new Promise((t=>setTimeout(t,300)));const e=yield g.toDataURL(r);t(e)}))))}))}))}destroy(){Object.values(this.getLayers()).forEach((t=>{t.getCamera().cancelLandmarkAnimation(),t.destroy()}))}}function qH(t,e){return Object.fromEntries(e.map((e=>{const n=(null==t?void 0:t(e))||new Dp;return n instanceof Dp&&n.setConfig({enableDirtyRectangleRendering:!1}),"main"===e?n.registerPlugin(new HH({isDocumentDraggable:!0,isDocumentDroppable:!0,dragstartDistanceThreshold:10,dragstartTimeThreshold:100})):n.unregisterPlugin(n.getPlugin("dom-interaction")),[e,n]})))}function XH(t){Object.entries(t).forEach((([t,e])=>{const n=e.getContextService().getDomElement();(null==n?void 0:n.style)&&(n.style.gridArea="1 / 1 / 2 / 2",n.style.outline="none",n.tabIndex=1,"main"!==t&&(n.style.pointerEvents="none")),(null==n?void 0:n.parentElement)&&(n.parentElement.style.display="grid")}))}const KH=t=>t?parseInt(t):0;function ZH(t){if(!t)return[0,0];let e=640,n=480;const[r,i]=function(t){const e=getComputedStyle(t),n=t.clientWidth||KH(e.width),r=t.clientHeight||KH(e.height);return[n-(KH(e.paddingLeft)+KH(e.paddingRight)),r-(KH(e.paddingTop)+KH(e.paddingBottom))]}(t);e=r||e,n=i||n;return[Math.max(ae(e)?e:1,1),Math.max(ae(n)?n:1,1)]}class QH{constructor(t){this.type=t}}class JH extends QH{constructor(t,e){super(t),this.data=e}}class tU extends QH{constructor(t,e,n,r){super(t),this.animationType=e,this.animation=n,this.data=r}}class eU extends QH{constructor(t,e,n){super(t),this.elementType=e,this.data=n}}class nU extends QH{constructor(t,e){super(t),this.data=e}}function rU(t,e){t.emit(e.type,e)}function iU(t){var e;return(null===(e=null==t?void 0:t.style)||void 0===e?void 0:e.zIndex)||0}const oU="cachedStyle",aU=t=>`__${t}__`;function sU(t,e){return Oe(t,[oU,aU(e)])}class lU{constructor(t){this.tasks=[],this.animations=new Set,this.context=t}getTasks(){const t=[...this.tasks];return this.tasks=[],t}add(t,e){this.tasks.push([t,e])}animate(t,e,n){var r,i,o;null===(r=null==e?void 0:e.before)||void 0===r||r.call(e);const a=this.getTasks().map((([e,r])=>{var i,o,a;const{element:s,elementType:l,stage:u}=e,c=Vc(this.context.options,l,u,t);null===(i=null==r?void 0:r.before)||void 0===i||i.call(r);const h=c.length?Hc(s,this.inferStyle(e,n),c):null;return h?(null===(o=null==r?void 0:r.beforeAnimate)||void 0===o||o.call(r,h),h.finished.then((()=>{var t,e;null===(t=null==r?void 0:r.afterAnimate)||void 0===t||t.call(r,h),null===(e=null==r?void 0:r.after)||void 0===e||e.call(r),this.animations.delete(h)}))):null===(a=null==r?void 0:r.after)||void 0===a||a.call(r),h})).filter(Boolean);a.forEach((t=>this.animations.add(t)));const s=Bc(a);return s?(null===(i=null==e?void 0:e.beforeAnimate)||void 0===i||i.call(e,s),s.finished.then((()=>{var t,n;null===(t=null==e?void 0:e.afterAnimate)||void 0===t||t.call(e,s),null===(n=null==e?void 0:e.after)||void 0===n||n.call(e),this.release()}))):null===(o=null==e?void 0:e.after)||void 0===o||o.call(e),s}inferStyle(t,e){var n,r;const{element:i,elementType:o,stage:a,originalStyle:s,updatedStyle:l={}}=t;t.modifiedStyle||(t.modifiedStyle=Object.assign(Object.assign({},s),l));const{modifiedStyle:u}=t,c={},h={};if("enter"===a)Object.assign(c,{opacity:0});else if("exit"===a)Object.assign(h,{opacity:0});else if("show"===a)Object.assign(c,{opacity:0}),Object.assign(h,{opacity:null!==(n=sU(i,"opacity"))&&void 0!==n?n:zc("opacity")});else if("hide"===a)Object.assign(c,{opacity:null!==(r=sU(i,"opacity"))&&void 0!==r?r:zc("opacity")}),Object.assign(h,{opacity:0});else if("collapse"===a){const{collapse:t}=e||{},{target:n,descendants:r,position:a}=t;if("node"===o){if(r.includes(i.id)){const[t,e,n]=a;Object.assign(h,{x:t,y:e,z:n})}}else if("combo"===o){if(i.id===n||r.includes(i.id)){const[t,e]=a;Object.assign(h,{x:t,y:e,childrenNode:s.childrenNode})}}else"edge"===o&&Object.assign(h,{sourceNode:u.sourceNode,targetNode:u.targetNode})}else if("expand"===a){const{expand:t}=e||{},{target:n,descendants:r,position:a}=t;if("node"===o){if(i.id===n||r.includes(i.id)){const[t,e,n]=a;Object.assign(c,{x:t,y:e,z:n})}}else if("combo"===o){if(i.id===n||r.includes(i.id)){const[t,e,n]=a;Object.assign(c,{x:t,y:e,z:n,childrenNode:u.childrenNode})}}else"edge"===o&&Object.assign(c,{sourceNode:u.sourceNode,targetNode:u.targetNode})}return[Object.keys(c).length>0?Object.assign({},s,c):s,Object.keys(h).length>0?Object.assign({},u,h):u]}stop(){this.animations.forEach((t=>t.cancel()))}clear(){this.tasks=[]}release(){var t,e;const{canvas:n}=this.context,r=null===(e=null===(t=n.document)||void 0===t?void 0:t.timeline)||void 0===e?void 0:e.animationsWithPromises;r&&(n.document.timeline.animationsWithPromises=r.filter((t=>"finished"!==t.playState)))}destroy(){this.stop(),this.animations.clear(),this.tasks=[]}}class uU{constructor(t){this.batchCount=0,this.context=t}emit(t){const{graph:e}=this.context;e.emit(t.type,t)}startBatch(e=!0){this.batchCount++,1===this.batchCount&&this.emit(new JH(t.GraphEvent.BATCH_START,{initiate:e}))}endBatch(){this.batchCount--,0===this.batchCount&&this.emit(new JH(t.GraphEvent.BATCH_END))}get isBatching(){return this.batchCount>0}destroy(){this.context=null}}class cU extends Fh{constructor(e){super(e),this.currentTarget=null,this.currentTargetType=null,this.category="behavior",this.forwardCanvasEvents=e=>{const{target:n}=e,r=function(t){if(!t)return null;if(t instanceof su)return{type:"canvas",element:t};let e=t;for(;e;){if(Ag(e))return{type:"node",element:e};if(Pg(e))return{type:"edge",element:e};if(Rg(e))return{type:"combo",element:e};e=e.parentElement}return null}(n);if(!r)return;const{graph:i,canvas:o}=this.context,{type:a,element:s}=r;if("destroyed"in s&&(Hg(s)||s.destroyed))return;const{type:l,detail:u,button:c}=e,h=Object.assign(Object.assign({},e),{target:s,targetType:a,originalTarget:n});l===t.CommonEvent.POINTER_MOVE&&(this.currentTarget!==s&&(this.currentTarget&&i.emit(`${this.currentTargetType}:${t.CommonEvent.POINTER_LEAVE}`,Object.assign(Object.assign({},h),{type:t.CommonEvent.POINTER_LEAVE,target:this.currentTarget,targetType:this.currentTargetType})),s&&(Object.assign(h,{type:t.CommonEvent.POINTER_ENTER}),i.emit(`${a}:${t.CommonEvent.POINTER_ENTER}`,h))),this.currentTarget=s,this.currentTargetType=a),l===t.CommonEvent.CLICK&&2===c||(i.emit(`${a}:${l}`,h),i.emit(l,h)),l===t.CommonEvent.CLICK&&2===u&&(Object.assign(h,{type:t.CommonEvent.DBLCLICK}),i.emit(`${a}:${t.CommonEvent.DBLCLICK}`,h),i.emit(t.CommonEvent.DBLCLICK,h)),l===t.CommonEvent.POINTER_DOWN&&2===c&&(Object.assign(h,{type:t.CommonEvent.CONTEXT_MENU,preventDefault:()=>{var e;null===(e=o.getContainer())||void 0===e||e.addEventListener(t.CommonEvent.CONTEXT_MENU,(t=>t.preventDefault()),{once:!0})}}),i.emit(`${a}:${t.CommonEvent.CONTEXT_MENU}`,h),i.emit(t.CommonEvent.CONTEXT_MENU,h))},this.forwardContainerEvents=t=>{this.context.graph.emit(t.type,t)},this.forwardEvents(),this.setBehaviors(this.context.options.behaviors||[])}setBehaviors(t){this.setExtensions(t)}forwardEvents(){const e=this.context.canvas.getContainer();e&&[t.ContainerEvent.KEY_DOWN,t.ContainerEvent.KEY_UP].forEach((t=>{e.addEventListener(t,this.forwardContainerEvents)}));const n=this.context.canvas.document;n&&[t.CommonEvent.CLICK,t.CommonEvent.DBLCLICK,t.CommonEvent.POINTER_OVER,t.CommonEvent.POINTER_LEAVE,t.CommonEvent.POINTER_ENTER,t.CommonEvent.POINTER_MOVE,t.CommonEvent.POINTER_OUT,t.CommonEvent.POINTER_DOWN,t.CommonEvent.POINTER_UP,t.CommonEvent.CONTEXT_MENU,t.CommonEvent.DRAG_START,t.CommonEvent.DRAG,t.CommonEvent.DRAG_END,t.CommonEvent.DRAG_ENTER,t.CommonEvent.DRAG_OVER,t.CommonEvent.DRAG_LEAVE,t.CommonEvent.DROP,t.CommonEvent.WHEEL].forEach((t=>{n.addEventListener(t,this.forwardCanvasEvents)}))}destroy(){const e=this.context.canvas.getContainer();e&&[t.ContainerEvent.KEY_DOWN,t.ContainerEvent.KEY_UP].forEach((t=>{e.removeEventListener(t,this.forwardContainerEvents)})),this.context.canvas.document.removeAllEventListeners(),super.destroy()}}function hU(t,e){const{data:n,style:r}=t,i=Fe(t,["data","style"]),{data:o,style:a}=e,s=Fe(e,["data","style"]),l=Object.assign(Object.assign({},i),s);return(n||o)&&Object.assign(l,{data:Object.assign(Object.assign({},n),o)}),(r||a)&&Object.assign(l,{style:Object.assign(Object.assign({},r),a)}),l}function dU(t){const{data:e,style:n}=t,r=Fe(t,["data","style"]);return e&&(r.data=Object.assign({},e)),n&&(r.style=Object.assign({},n)),r}function fU(t={},e={}){const{states:n=[],data:r={},style:i={},children:o=[]}=t,a=Fe(t,["states","data","style","children"]),{states:s=[],data:l={},style:u={},children:c=[]}=e,h=(t,e)=>t.length===e.length&&t.every(((t,n)=>t===e[n])),d=(t,e)=>{const n=Object.keys(t),r=Object.keys(e);return n.length===r.length&&n.every((n=>t[n]===e[n]))};return!!d(a,Fe(e,["states","data","style","children"]))&&(!!h(o,c)&&(!!h(n,s)&&(!!d(r,l)&&!!d(i,u))))}function pU(t){const{id:e=Nh(t),style:n,data:r}=t,i=Fe(t,["id","style","data"]),o=Object.assign(Object.assign({},t),{style:Object.assign({},n),data:Object.assign({},r)});return function(t){return"source"in t&&"target"in t}(t)?Object.assign({id:e,data:o},i):{id:e,data:o}}function gU(t){return t.data}class vU{constructor(){this.latestRemovedComboIds=new Set,this.comboIds=new Set,this.changes=[],this.batchCount=0,this.isTraceless=!1,this.enableUpdateNodeLikeHierarchy=!0,this.model=new ev}pushChange(t){if(this.isTraceless)return;const{type:e}=t;if(e===xc.NodeUpdated||e===xc.EdgeUpdated||e===xc.ComboUpdated){const{value:n,original:r}=t;this.changes.push({value:dU(n),original:dU(r),type:e})}else this.changes.push({value:dU(t.value),type:e})}getChanges(){return this.changes}clearChanges(){this.changes=[]}batch(t){this.batchCount++,this.model.batch(t),this.batchCount--}isBatching(){return this.batchCount>0}silence(t){this.isTraceless=!0,t(),this.isTraceless=!1}isCombo(t){return this.comboIds.has(t)||this.latestRemovedComboIds.has(t)}getData(){return{nodes:this.getNodeData(),edges:this.getEdgeData(),combos:this.getComboData()}}getNodeData(t){return this.model.getAllNodes().reduce(((e,n)=>{const r=gU(n);return this.isCombo(Nh(r))||(void 0===t||t.includes(Nh(r)))&&e.push(r),e}),[])}getEdgeDatum(t){return gU(this.model.getEdge(t))}getEdgeData(t){return this.model.getAllEdges().reduce(((e,n)=>{const r=gU(n);return(void 0===t||t.includes(Nh(r)))&&e.push(r),e}),[])}getComboData(t){return this.model.getAllNodes().reduce(((e,n)=>{const r=gU(n);return this.isCombo(Nh(r))?((void 0===t||t.includes(Nh(r)))&&e.push(r),e):e}),[])}getRootsData(t=Ac){return this.model.getRoots(t).map(gU)}getAncestorsData(t,e){const{model:n}=this;return n.hasNode(t)&&n.hasTreeStructure(e)?n.getAncestors(t,e).map(gU):[]}getDescendantsData(t){const e=this.getElementDataById(t),n=[];return Ad(e,(t=>{t!==e&&n.push(t)}),(t=>this.getChildrenData(Nh(t))),"TB"),n}getParentData(t,e){const{model:n}=this;if(!e)return void Ic("The hierarchy structure key is not specified");if(!n.hasNode(t)||!n.hasTreeStructure(e))return;const r=n.getParent(t,e);return r?gU(r):void 0}getChildrenData(t){const e="node"===this.getElementType(t)?Ac:Cc,{model:n}=this;return n.hasNode(t)&&n.hasTreeStructure(e)?n.getChildren(t,e).map(gU):[]}getElementsDataByType(t){return"node"===t?this.getNodeData():"edge"===t?this.getEdgeData():"combo"===t?this.getComboData():[]}getElementDataById(t){return"edge"===this.getElementType(t)?this.getEdgeDatum(t):this.getNodeLikeDatum(t)}getNodeLikeDatum(t){return gU(this.model.getNode(t))}getNodeLikeData(t){return this.model.getAllNodes().reduce(((e,n)=>{const r=gU(n);return t?t.includes(Nh(r))&&e.push(r):e.push(r),e}),[])}getElementDataByState(t,e){return this.getElementsDataByType(t).filter((t=>{var n;return null===(n=t.states)||void 0===n?void 0:n.includes(e)}))}getElementState(t){var e;return(null===(e=this.getElementDataById(t))||void 0===e?void 0:e.states)||[]}hasNode(t){return this.model.hasNode(t)&&!this.isCombo(t)}hasEdge(t){return this.model.hasEdge(t)}hasCombo(t){return this.model.hasNode(t)&&this.isCombo(t)}getRelatedEdgesData(t,e="both"){return this.model.getRelatedEdges(t,e).map(gU)}getNeighborNodesData(t){return this.model.getNeighbors(t).map(gU)}setData(t){const{nodes:e=[],edges:n=[],combos:r=[]}=t,{nodes:i,edges:o,combos:a}=this.getData(),s=jh(i,e,(t=>Nh(t)),fU),l=jh(o,n,(t=>Nh(t)),fU),u=jh(a,r,(t=>Nh(t)),fU);this.batch((()=>{const t={nodes:s.enter,edges:l.enter,combos:u.enter};this.addData(t),this.computeZIndex(t,"add",!0);const e={nodes:s.update,edges:l.update,combos:u.update};this.updateData(e),this.computeZIndex(e,"update",!0);const n={nodes:s.exit.map(Nh),edges:l.exit.map(Nh),combos:u.exit.map(Nh)};this.removeData(n)}))}addData(t){const{nodes:e,edges:n,combos:r}=t;this.batch((()=>{this.addComboData(r),this.addNodeData(e),this.addEdgeData(n)})),this.computeZIndex(t,"add")}addNodeData(t=[]){t.length&&(this.model.addNodes(t.map((t=>(this.pushChange({value:t,type:xc.NodeAdded}),pU(t))))),this.updateNodeLikeHierarchy(t),this.computeZIndex({nodes:t},"add"))}addEdgeData(t=[]){t.length&&(this.model.addEdges(t.map((t=>(this.pushChange({value:t,type:xc.EdgeAdded}),pU(t))))),this.computeZIndex({edges:t},"add"))}addComboData(t=[]){if(!t.length)return;const{model:e}=this;e.hasTreeStructure(Cc)||e.attachTreeStructure(Cc),e.addNodes(t.map((t=>(this.comboIds.add(Nh(t)),this.pushChange({value:t,type:xc.ComboAdded}),pU(t))))),this.updateNodeLikeHierarchy(t),this.computeZIndex({combos:t},"add")}addChildrenData(t,e){const n=this.getNodeLikeDatum(t),r=e.map(Nh);this.addNodeData(e),this.updateNodeData([{id:t,children:[...n.children||[],...r]}]),this.addEdgeData(r.map((e=>({source:t,target:e}))))}computeZIndex(t,e,n=!1){!n&&this.isBatching()||this.batch((()=>{const{nodes:n=[],edges:r=[],combos:i=[]}=t;i.forEach((t=>{var n,r,i;const o=Nh(t);if("add"===e&&ae(null===(n=t.style)||void 0===n?void 0:n.zIndex))return;if("update"===e&&!("combo"in t))return;const a=this.getParentData(o,Cc),s=a?(null!==(i=null===(r=a.style)||void 0===r?void 0:r.zIndex)&&void 0!==i?i:0)+1:0;this.preventUpdateNodeLikeHierarchy((()=>{this.updateComboData([{id:o,style:{zIndex:s}}])}))})),n.forEach((t=>{var n,r,i;const o=Nh(t);if("add"===e&&ae(null===(n=t.style)||void 0===n?void 0:n.zIndex))return;if("update"===e&&!("combo"in t)&&!("children"in t))return;let a=0;const s=this.getParentData(o,Cc);if(s)a=((null===(r=s.style)||void 0===r?void 0:r.zIndex)||0)+1;else{const t=this.getParentData(o,Ac);t&&(a=(null===(i=null==t?void 0:t.style)||void 0===i?void 0:i.zIndex)||0)}this.preventUpdateNodeLikeHierarchy((()=>{this.updateNodeData([{id:o,style:{zIndex:a}}])}))})),r.forEach((t=>{var e,n,r,i,o;if(ae(null===(e=t.style)||void 0===e?void 0:e.zIndex))return;let{id:a,source:s,target:l}=t;if(a){const t=this.getEdgeDatum(a);s=t.source,l=t.target}else a=Nh(t);if(!s||!l)return;const u=(null===(r=null===(n=this.getNodeLikeDatum(s))||void 0===n?void 0:n.style)||void 0===r?void 0:r.zIndex)||0,c=(null===(o=null===(i=this.getNodeLikeDatum(l))||void 0===i?void 0:i.style)||void 0===o?void 0:o.zIndex)||0;this.updateEdgeData([{id:Nh(t),style:{zIndex:Math.max(u,c)-1}}])}))}))}getFrontZIndex(t){var e;const n=this.getElementType(t),r=this.getElementDataById(t),i=this.getData();if(Object.assign(i,{[`${n}s`]:i[`${n}s`].filter((e=>Nh(e)!==t))}),"combo"===n&&!_d(r)){const e=new Set(this.getAncestorsData(t,Cc).map(Nh));i.nodes=i.nodes.filter((t=>!e.has(Nh(t)))),i.combos=i.combos.filter((t=>!e.has(Nh(t)))),i.edges=i.edges.filter((({source:t,target:n})=>!e.has(t)&&!e.has(n)))}return Math.max((null===(e=r.style)||void 0===e?void 0:e.zIndex)||0,0,...Object.values(i).flat().map((t=>{var e;return((null===(e=null==t?void 0:t.style)||void 0===e?void 0:e.zIndex)||0)+1})))}updateNodeLikeHierarchy(t){if(!this.enableUpdateNodeLikeHierarchy)return;const{model:e}=this;t.forEach((t=>{const n=Nh(t),r=Oh(t);void 0!==r&&(e.hasTreeStructure(Cc)||e.attachTreeStructure(Cc),null===r&&this.refreshComboData(n),this.setParent(n,Oh(t),Cc));const i=t.children||[];if(i.length){e.hasTreeStructure(Ac)||e.attachTreeStructure(Ac);const t=i.filter((t=>e.hasNode(t)));t.forEach((t=>this.setParent(t,n,Ac))),t.length!==i.length&&this.updateNodeData([{id:n,children:t}])}}))}preventUpdateNodeLikeHierarchy(t){this.enableUpdateNodeLikeHierarchy=!1,t(),this.enableUpdateNodeLikeHierarchy=!0}updateData(t){const{nodes:e,edges:n,combos:r}=t;this.batch((()=>{this.updateNodeData(e),this.updateComboData(r),this.updateEdgeData(n)})),this.computeZIndex(t,"update")}updateNodeData(t=[]){if(!t.length)return;const{model:e}=this;this.batch((()=>{const n=[];t.forEach((t=>{const r=Nh(t),i=gU(e.getNode(r));if(fU(i,t))return;const o=hU(i,t);this.pushChange({value:o,original:i,type:xc.NodeUpdated}),e.mergeNodeData(r,o),n.push(o)})),this.updateNodeLikeHierarchy(n)})),this.computeZIndex({nodes:t},"update")}refreshData(){const{nodes:t,edges:e,combos:n}=this.getData();t.forEach((t=>{this.pushChange({value:t,original:t,type:xc.NodeUpdated})})),e.forEach((t=>{this.pushChange({value:t,original:t,type:xc.EdgeUpdated})})),n.forEach((t=>{this.pushChange({value:t,original:t,type:xc.ComboUpdated})}))}syncNodeLikeDatum(t){const{model:e}=this,n=Nh(t);if(!e.hasNode(n))return;const r=hU(gU(e.getNode(n)),t);e.mergeNodeData(n,r)}syncEdgeDatum(t){const{model:e}=this,n=Nh(t);if(!e.hasEdge(n))return;const r=hU(gU(e.getEdge(n)),t);e.mergeEdgeData(n,r)}updateEdgeData(t=[]){if(!t.length)return;const{model:e}=this;this.batch((()=>{t.forEach((t=>{const n=Nh(t),r=gU(e.getEdge(n));if(fU(r,t))return;t.source&&r.source!==t.source&&e.updateEdgeSource(n,t.source),t.target&&r.target!==t.target&&e.updateEdgeTarget(n,t.target);const i=hU(r,t);this.pushChange({value:i,original:r,type:xc.EdgeUpdated}),e.mergeEdgeData(n,i)}))})),this.computeZIndex({edges:t},"update")}updateComboData(t=[]){if(!t.length)return;const{model:e}=this;e.batch((()=>{const n=[];t.forEach((t=>{const r=Nh(t),i=gU(e.getNode(r));if(fU(i,t))return;const o=hU(i,t);this.pushChange({value:o,original:i,type:xc.ComboUpdated}),e.mergeNodeData(r,o),n.push(o)})),this.updateNodeLikeHierarchy(n)})),this.computeZIndex({combos:t},"update")}setParent(t,e,n,r=!0){if(t===e)return;const i=Oh(this.getNodeLikeDatum(t));if(i!==e&&n===Cc){const n={id:t,combo:e};this.isCombo(t),this.syncNodeLikeDatum(n)}this.model.setParent(t,e,n),r&&n===Cc&&function(t,e){void 0===e&&(e=new Map);var n=[];if(Array.isArray(t))for(var r=0,i=t.length;r{void 0!==t&&this.refreshComboData(t)}))}refreshComboData(t){const e=this.getComboData([t])[0],n=this.getAncestorsData(t,Cc);e&&this.pushChange({value:e,original:e,type:xc.ComboUpdated}),n.forEach((t=>{this.pushChange({value:t,original:t,type:xc.ComboUpdated})}))}getElementPosition(t){return sd(this.getElementDataById(t))}translateNodeLikeBy(t,e){this.isCombo(t)?this.translateComboBy(t,e):this.translateNodeBy(t,e)}translateNodeLikeTo(t,e){this.isCombo(t)?this.translateComboTo(t,e):this.translateNodeTo(t,e)}translateNodeBy(t,e){const n=Hh(this.getElementPosition(t),[...e,0].slice(0,3));this.translateNodeTo(t,n)}translateNodeTo(t,e){const[n=0,r=0,i=0]=e;this.preventUpdateNodeLikeHierarchy((()=>{this.updateNodeData([{id:t,style:{x:n,y:r,z:i}}])}))}translateComboBy(t,e){const[n=0,r=0,i=0]=e;if([n,r,i].some(isNaN)||[n,r,i].every((t=>0===t)))return;const o=this.getComboData([t])[0];if(!o)return;const a=new Set;Ad(o,(t=>{const e=Nh(t);if(a.has(e))return;a.add(e);const[o,s,l]=sd(t),u=hU(t,{style:{x:o+n,y:s+r,z:l+i}});this.pushChange({value:u,original:t,type:this.isCombo(e)?xc.ComboUpdated:xc.NodeUpdated}),this.model.mergeNodeData(e,u)}),(t=>this.getChildrenData(Nh(t))),"BT")}translateComboTo(t,e){var n;if(e.some(isNaN))return;const[r=0,i=0,o=0]=e,a=null===(n=this.getComboData([t]))||void 0===n?void 0:n[0];if(!a)return;const[s,l,u]=sd(a),c=r-s,h=i-l,d=o-u;Ad(a,(t=>{const e=Nh(t),[n,r,i]=sd(t),o=hU(t,{style:{x:n+c,y:r+h,z:i+d}});this.pushChange({value:o,original:t,type:this.isCombo(e)?xc.ComboUpdated:xc.NodeUpdated}),this.model.mergeNodeData(e,o)}),(t=>this.getChildrenData(Nh(t))),"BT")}removeData(t){const{nodes:e,edges:n,combos:r}=t;this.batch((()=>{this.removeEdgeData(n),this.removeNodeData(e),this.removeComboData(r),this.latestRemovedComboIds=new Set(r)}))}removeNodeData(t=[]){t.length&&this.batch((()=>{t.forEach((t=>{this.removeEdgeData(this.getRelatedEdgesData(t).map(Nh)),this.pushChange({value:this.getNodeData([t])[0],type:xc.NodeRemoved}),this.removeNodeLikeHierarchy(t)})),this.model.removeNodes(t)}))}removeEdgeData(t=[]){t.length&&(t.forEach((t=>this.pushChange({value:this.getEdgeData([t])[0],type:xc.EdgeRemoved}))),this.model.removeEdges(t))}removeComboData(t=[]){t.length&&this.batch((()=>{t.forEach((t=>{this.pushChange({value:this.getComboData([t])[0],type:xc.ComboRemoved}),this.removeNodeLikeHierarchy(t),this.comboIds.delete(t)})),this.model.removeNodes(t)}))}removeNodeLikeHierarchy(t){if(this.model.hasTreeStructure(Cc)){const e=Oh(this.getNodeLikeDatum(t));this.setParent(t,void 0,Cc,!1),this.model.getChildren(t,Cc).forEach((t=>{const n=gU(t),r=Nh(n);this.setParent(Nh(n),e,Cc,!1);const i=hU(n,{id:Nh(n),combo:e});this.pushChange({value:i,original:n,type:this.isCombo(r)?xc.ComboUpdated:xc.NodeUpdated}),this.model.mergeNodeData(Nh(n),i)})),$t(e)||this.refreshComboData(e)}}getElementType(t){if(this.model.hasNode(t))return this.isCombo(t)?"combo":"node";if(this.model.hasEdge(t))return"edge";throw new Error(_c(`Unknown element type of id: ${t}`))}destroy(){const{model:t}=this,e=t.getAllNodes(),n=t.getAllEdges();t.removeEdges(n.map((t=>t.id))),t.removeNodes(e.map((t=>t.id))),this.context={}}}class mU{constructor(t){this.elementMap={},this.shapeTypeMap={},this.paletteStyle={},this.defaultStyle={},this.stateStyle={},this.visibilityCache=new WeakMap,this.context=t}init(){this.initContainer()}initContainer(){if(!this.container||this.container.destroyed){const{canvas:t}=this.context;this.container=t.appendChild(new Ul({className:"elements"}))}}emit(t,e){e.silence||rU(this.context.graph,t)}forEachElementData(t){Cd.forEach((e=>{const n=this.context.model.getElementsDataByType(e);t(e,n)}))}getElementType(t,e){var n;const{options:r,graph:i}=this.context,o=(null===(n=r[t])||void 0===n?void 0:n.type)||e.type;return o?"string"==typeof o?o:o.call(i,e):"edge"===t?"line":"circle"}getTheme(t){return jc(this.context.options)[t]||{}}getThemeStyle(t){return this.getTheme(t).style||{}}getThemeStateStyle(t,e){const{state:n={}}=this.getTheme(t);return Object.assign({},...e.map((t=>n[t]||{})))}computePaletteStyle(){const{options:t}=this.context;this.paletteStyle={},this.forEachElementData(((e,n)=>{var r,i;const o=Object.assign({},Hd(null===(r=this.getTheme(e))||void 0===r?void 0:r.palette),Hd(null===(i=t[e])||void 0===i?void 0:i.palette));(null==o?void 0:o.field)&&Object.assign(this.paletteStyle,function(t,e){if(!e)return{};const{type:n,color:r,field:i,invert:o}=e,a=t=>{const e="string"==typeof r?Dc("palette",r):r;if("function"==typeof e){const n={};return t.forEach((([t,r])=>{n[t]=e(o?1-r:r)})),n}if(Array.isArray(e)){const n=o?[...e].reverse():e,r={};return t.forEach((([t,i])=>{r[t]=n[i%e.length]})),r}return{}},s=(t,e)=>{var n;return"string"==typeof t?null===(n=e.data)||void 0===n?void 0:n[t]:null==t?void 0:t(e)};if("group"===n){const e=ie(t,(t=>{if(!i)return"default";const e=s(i,t);return e?String(e):"default"})),n=a(Object.keys(e).map(((t,e)=>[t,e]))),r={};return Object.entries(e).forEach((([t,e])=>{e.forEach((e=>{r[Nh(e)]=n[t]}))})),r}if("value"===n){const[e,n]=t.reduce((([t,e],n)=>{const r=s(i,n);if("number"!=typeof r)throw new Error(_c(`Palette field ${i} is not a number`));return[Math.min(t,r),Math.max(e,r)]}),[1/0,-1/0]),r=n-e;return a(t.map((t=>[t.id,(s(i,t)-e)/r])))}}(n,o))}))}getPaletteStyle(t,e){const n=this.paletteStyle[e];return n?"edge"===t?{stroke:n}:{fill:n}:{}}computeElementDefaultStyle(t,e){var n;const{options:r}=this.context,i=(null===(n=r[t])||void 0===n?void 0:n.style)||{};"transform"in i&&Array.isArray(i.transform)&&(i.transform=[...i.transform]),this.defaultStyle[Nh(e.datum)]=Vd(i,e)}computeElementsDefaultStyle(t){const{graph:e}=this.context;this.forEachElementData(((n,r)=>{const i=r.length;for(let o=0;othis.getElementStateStyle(t,e,n))))}computeElementsStatesStyle(t){const{graph:e}=this.context;this.forEachElementData(((n,r)=>{const i=r.length;for(let o=0;othis.elementMap[t]))}getEdges(){return this.context.model.getEdgeData().map((t=>this.elementMap[Nh(t)]))}getCombos(){return this.context.model.getComboData().map((({id:t})=>this.elementMap[t]))}getElementComputedStyle(t,e){const n=Nh(e),r=this.getThemeStyle(t),i=this.getPaletteStyle(t,n),o=e.style||{},a=this.getDefaultStyle(n),s=this.getThemeStateStyle(t,this.getElementState(n)),l=this.getStateStyle(n),u=Object.assign({},r,i,o,a,s,l);if("combo"===t){const t=this.context.model.getChildrenData(n),e=!!u.collapsed?[]:t.map(Nh).filter((t=>this.getElement(t)));Object.assign(u,{childrenNode:e,childrenData:t})}return u}getDrawData(t){this.init();const e=this.computeChangesAndDrawData(t);if(!e)return null;const{type:n="draw",stage:r=n}=t;return this.markDestroyElement(e.drawData),this.computeStyle(r),{type:n,stage:r,data:e}}draw(t={animation:!0}){const e=this.getDrawData(t);if(!e)return;const{data:{drawData:{add:n,update:r,remove:i}}}=e;return this.destroyElements(i,t),this.createElements(n,t),this.updateElements(r,t),this.setAnimationTask(t,e)}preLayoutDraw(){return ze(this,arguments,void 0,(function*(t={animation:!0}){var e,n;const r=this.getDrawData(t);if(!r)return;const{data:{drawData:i}}=r;yield null===(n=null===(e=this.context.layout)||void 0===e?void 0:e.preLayout)||void 0===n?void 0:n.call(e,i);const{add:o,update:a,remove:s}=i;return this.destroyElements(s,t),this.createElements(o,t),this.updateElements(a,t),this.setAnimationTask(t,r)}))}setAnimationTask(e,n){const{animation:r,silence:i}=e,{data:{dataChanges:o,drawData:a},stage:s,type:l}=n;return this.context.animation.animate(r,i?{}:{before:()=>this.emit(new JH(t.GraphEvent.BEFORE_DRAW,{dataChanges:o,animation:r,stage:s,render:"render"===l}),e),beforeAnimate:n=>this.emit(new tU(t.GraphEvent.BEFORE_ANIMATE,Ec.DRAW,n,a),e),afterAnimate:n=>this.emit(new tU(t.GraphEvent.AFTER_ANIMATE,Ec.DRAW,n,a),e),after:()=>this.emit(new JH(t.GraphEvent.AFTER_DRAW,{dataChanges:o,animation:r,stage:s,render:"render"===l,firstRender:!1===this.context.graph.rendered}),e)})}computeChangesAndDrawData(t){const{model:e}=this.context,n=e.getChanges(),r=aF(n);if(0===r.length)return null;const{NodeAdded:i=[],NodeUpdated:o=[],NodeRemoved:a=[],EdgeAdded:s=[],EdgeUpdated:l=[],EdgeRemoved:u=[],ComboAdded:c=[],ComboUpdated:h=[],ComboRemoved:d=[]}=ie(r,(t=>t.type)),f=t=>new Map(t.map((t=>{const e=t.value;return[Nh(e),e]}))),p={add:{nodes:f(i),edges:f(s),combos:f(c)},update:{nodes:f(o),edges:f(l),combos:f(h)},remove:{nodes:f(a),edges:f(u),combos:f(d)}},g=this.transformData(p,t);return e.clearChanges(),{dataChanges:n,drawData:g}}transformData(t,e){const n=this.context.transform.getTransformInstance();return Object.values(n).reduce(((t,n)=>n.beforeDraw(t,e)),t)}createElement(e,n,r){var i;const o=Nh(n);if(this.getElement(o))return;const a=this.getElementType(e,n),s=this.getElementComputedStyle(e,n),l=Dc(e,a);if(!l)return Ic(`The element ${a} of ${e} is not registered.`);this.emit(new eU(t.GraphEvent.BEFORE_ELEMENT_CREATE,e,n),r);const u=this.container.appendChild(new l({id:o,context:this.context,style:s}));this.shapeTypeMap[o]=a,this.elementMap[o]=u;const{stage:c="enter"}=r;null===(i=this.context.animation)||void 0===i||i.add({element:u,elementType:e,stage:c,originalStyle:Object.assign({},u.attributes),updatedStyle:s},{after:()=>{var i;this.emit(new eU(t.GraphEvent.AFTER_ELEMENT_CREATE,e,n),r),null===(i=u.onCreate)||void 0===i||i.call(u)}})}createElements(t,e){const{nodes:n,edges:r,combos:i}=t;[["node",n],["combo",i],["edge",r]].forEach((([t,n])=>{n.forEach((n=>this.createElement(t,n,e)))}))}getUpdateStageStyle(t,e,n){const{stage:r="update"}=n;if("translate"===r){if("node"===t||"combo"===t){const{style:{x:t=0,y:n=0,z:r=0}={}}=e;return{x:t,y:n,z:r}}return{}}return this.getElementComputedStyle(t,e)}updateElement(e,n,r){var i;const o=Nh(n),{stage:a="update"}=r,s=this.getElement(o);if(!s)return()=>null;this.emit(new eU(t.GraphEvent.BEFORE_ELEMENT_UPDATE,e,n),r);const l=this.getElementType(e,n),u=this.getUpdateStageStyle(e,n,r);this.shapeTypeMap[o]!==l&&(s.destroy(),delete this.shapeTypeMap[o],delete this.elementMap[o],this.createElement(e,n,{animation:!1,silence:!0}));const c="visibility"!==a?a:"hidden"===u.visibility?"hide":"show";"hide"===c&&delete u.visibility,null===(i=this.context.animation)||void 0===i||i.add({element:s,elementType:e,stage:c,originalStyle:Object.assign({},s.attributes),updatedStyle:u},{before:()=>{const t=this.elementMap[o];"collapse"!==a&&Wg(t,u),"visibility"===a&&(function(t,e){return aU(e)in(Oe(t,oU)||{})}(t,"opacity")||function(t,e){const n=Array.isArray(e)?e:[e];Oe(t,oU)||Te(t,oU,{}),n.forEach((e=>{Te(Oe(t,oU),aU(e),t.attributes[e])}))}(t,"opacity"),this.visibilityCache.set(t,"show"===c?"visible":"hidden"),"show"===c&&Bh(t,"visible"))},after:()=>{var i;const s=this.elementMap[o];"collapse"===a&&Wg(s,u),"hide"===c&&Bh(s,this.visibilityCache.get(s)),this.emit(new eU(t.GraphEvent.AFTER_ELEMENT_UPDATE,e,n),r),null===(i=s.onUpdate)||void 0===i||i.call(s)}})}updateElements(t,e){const{nodes:n,edges:r,combos:i}=t;[["node",n],["combo",i],["edge",r]].forEach((([t,n])=>{n.forEach((n=>this.updateElement(t,n,e)))}))}markDestroyElement(t){Object.values(t.remove).forEach((t=>{t.forEach((t=>{const e=Nh(t),n=this.getElement(e);n&&function(t){Te(t,"__to_be_destroyed__",!0)}(n)}))}))}destroyElement(e,n,r){var i;const{stage:o="exit"}=r,a=Nh(n),s=this.elementMap[a];if(!s)return()=>null;this.emit(new eU(t.GraphEvent.BEFORE_ELEMENT_DESTROY,e,n),r),null===(i=this.context.animation)||void 0===i||i.add({element:s,elementType:e,stage:o,originalStyle:Object.assign({},s.attributes),updatedStyle:{}},{after:()=>{var i;this.clearElement(a),s.destroy(),null===(i=s.onDestroy)||void 0===i||i.call(s),this.emit(new eU(t.GraphEvent.AFTER_ELEMENT_DESTROY,e,n),r)}})}destroyElements(t,e){const{nodes:n,edges:r,combos:i}=t;[["combo",i],["edge",r],["node",n]].forEach((([t,n])=>{n.forEach((n=>this.destroyElement(t,n,e)))}))}clearElement(t){delete this.paletteStyle[t],delete this.defaultStyle[t],delete this.stateStyle[t],delete this.elementMap[t],delete this.shapeTypeMap[t]}alignLayoutResultToElement(t,e){var n,r;const i=null===(n=t.nodes)||void 0===n?void 0:n.find((t=>Nh(t)===e));if(i){const n=Uh(sd(this.context.model.getNodeLikeDatum(e)),sd(i));null===(r=t.nodes)||void 0===r||r.forEach((t=>{var e,r,i;(null===(e=t.style)||void 0===e?void 0:e.x)&&(t.style.x+=n[0]),(null===(r=t.style)||void 0===r?void 0:r.y)&&(t.style.y+=n[1]),(null===(i=t.style)||void 0===i?void 0:i.z)&&(t.style.z+=n[2]||0)}))}}collapseNode(e,n){return ze(this,void 0,void 0,(function*(){var r;const{animation:i,align:o}=n,{model:a,layout:s}=this.context,l=this.computeChangesAndDrawData({stage:"collapse",animation:i});if(!l)return;this.markDestroyElement(l.drawData);const u=yield s.simulate();o&&this.alignLayoutResultToElement(u,e),a.updateData(u);const c=this.computeChangesAndDrawData({stage:"collapse",animation:i});if(!c)return;const{drawData:h}=c,{add:d,remove:f,update:p}=h;this.markDestroyElement(h);const g={animation:i,stage:"collapse",data:h};this.destroyElements(f,g),this.createElements(d,g),this.updateElements(p,g),yield null===(r=this.context.animation.animate(i,{beforeAnimate:e=>this.emit(new tU(t.GraphEvent.BEFORE_ANIMATE,Ec.COLLAPSE,e,h),g),afterAnimate:e=>this.emit(new tU(t.GraphEvent.AFTER_ANIMATE,Ec.COLLAPSE,e,h),g)},{collapse:{target:e,descendants:Array.from(f.nodes).map((([,t])=>Nh(t))),position:sd(p.nodes.get(e))}}))||void 0===r?void 0:r.finished}))}expandNode(e,n){return ze(this,void 0,void 0,(function*(){var r;const{model:i,layout:o}=this.context,{animation:a,align:s}=n,l=sd(i.getNodeData([e])[0]),u=this.computeChangesAndDrawData({stage:"expand",animation:a});if(!u)return;const{drawData:{add:c}}=u;this.createElements(c,{animation:!1,stage:"expand",target:e}),this.context.animation.clear();const h=yield o.simulate();s&&this.alignLayoutResultToElement(h,e),i.updateData(h),this.computeStyle("expand");const d=this.computeChangesAndDrawData({stage:"collapse",animation:a});if(!d)return;const{drawData:f}=d,{update:p}=f,g={animation:a,stage:"expand",data:f};c.edges.forEach((t=>p.edges.set(Nh(t),t))),c.nodes.forEach((t=>p.nodes.set(Nh(t),t))),this.updateElements(p,g),yield null===(r=this.context.animation.animate(a,{beforeAnimate:e=>this.emit(new tU(t.GraphEvent.BEFORE_ANIMATE,Ec.EXPAND,e,f),g),afterAnimate:e=>this.emit(new tU(t.GraphEvent.AFTER_ANIMATE,Ec.EXPAND,e,f),g)},{expand:{target:e,descendants:Array.from(c.nodes).map((([,t])=>Nh(t))),position:l}}))||void 0===r?void 0:r.finished}))}collapseCombo(e,n){return ze(this,void 0,void 0,(function*(){var r;const{model:i,element:o}=this.context;if(i.getAncestorsData(e,Cc).some((t=>_d(t))))return;const a=o.getElement(e),s=a.getComboPosition(Object.assign(Object.assign({},a.attributes),{collapsed:!0})),l=this.computeChangesAndDrawData({stage:"collapse",animation:n});if(!l)return;const{dataChanges:u,drawData:c}=l;this.markDestroyElement(c);const{update:h,remove:d}=c,f={animation:n,stage:"collapse",data:c};this.destroyElements(d,f),this.updateElements(h,f);const p=t=>Array.from(t).map((([,t])=>Nh(t)));yield null===(r=this.context.animation.animate(n,{before:()=>this.emit(new JH(t.GraphEvent.BEFORE_DRAW,{dataChanges:u,animation:n}),f),beforeAnimate:e=>this.emit(new tU(t.GraphEvent.BEFORE_ANIMATE,Ec.COLLAPSE,e,c),f),afterAnimate:e=>this.emit(new tU(t.GraphEvent.AFTER_ANIMATE,Ec.COLLAPSE,e,c),f),after:()=>this.emit(new JH(t.GraphEvent.AFTER_DRAW,{dataChanges:u,animation:n}),f)},{collapse:{target:e,descendants:[...p(d.nodes),...p(d.combos)],position:s}}))||void 0===r?void 0:r.finished}))}expandCombo(e,n){return ze(this,void 0,void 0,(function*(){var r;const{model:i}=this.context,o=sd(i.getComboData([e])[0]);this.computeStyle("expand");const a=this.computeChangesAndDrawData({stage:"expand",animation:n});if(!a)return;const{dataChanges:s,drawData:l}=a,{add:u,update:c}=l,h={animation:n,stage:"expand",data:l,target:e};this.createElements(u,h),this.updateElements(c,h);const d=t=>Array.from(t).map((([,t])=>Nh(t)));yield null===(r=this.context.animation.animate(n,{before:()=>this.emit(new JH(t.GraphEvent.BEFORE_DRAW,{dataChanges:s,animation:n}),h),beforeAnimate:e=>this.emit(new tU(t.GraphEvent.BEFORE_ANIMATE,Ec.EXPAND,e,l),h),afterAnimate:e=>this.emit(new tU(t.GraphEvent.AFTER_ANIMATE,Ec.EXPAND,e,l),h),after:()=>this.emit(new JH(t.GraphEvent.AFTER_DRAW,{dataChanges:s,animation:n}),h)},{expand:{target:e,descendants:[...d(u.nodes),...d(u.combos)],position:o}}))||void 0===r?void 0:r.finished}))}clear(){this.container.destroy(),this.initContainer(),this.elementMap={},this.shapeTypeMap={},this.defaultStyle={},this.stateStyle={},this.paletteStyle={}}destroy(){this.clear(),this.container.destroy(),this.context={}}}class yU{get presetOptions(){return{animation:!!Gc(this.context.options,!0)}}get options(){const{options:t}=this.context;return t.layout}constructor(t){this.instances=[],this.context=t}getLayoutInstance(){return this.instances}preLayout(e){return ze(this,void 0,void 0,(function*(){var n,r,i,o;const{graph:a,model:s}=this.context,{add:l}=e;rU(a,new JH(t.GraphEvent.BEFORE_LAYOUT,{type:"pre"}));const u=yield null===(n=this.context.layout)||void 0===n?void 0:n.simulate();null===(r=null==u?void 0:u.nodes)||void 0===r||r.forEach((t=>{const e=Nh(t),n=l.nodes.get(e);s.syncNodeLikeDatum(t),n&&Object.assign(n.style,t.style)})),null===(i=null==u?void 0:u.edges)||void 0===i||i.forEach((t=>{const e=Nh(t),n=l.edges.get(e);s.syncEdgeDatum(t),n&&Object.assign(n.style,t.style)})),null===(o=null==u?void 0:u.combos)||void 0===o||o.forEach((t=>{const e=Nh(t),n=l.combos.get(e);s.syncNodeLikeDatum(t),n&&Object.assign(n.style,t.style)})),rU(a,new JH(t.GraphEvent.AFTER_LAYOUT,{type:"pre"})),this.transformDataAfterLayout("pre",e)}))}postLayout(){return ze(this,arguments,void 0,(function*(e=this.options){if(!e)return;const n=Array.isArray(e)?e:[e],{graph:r}=this.context;rU(r,new JH(t.GraphEvent.BEFORE_LAYOUT,{type:"post"}));for(let e=0;en.afterLayout(t,e)))}simulate(){return ze(this,void 0,void 0,(function*(){if(!this.options)return{};const t=Array.isArray(this.options)?this.options:[this.options];let e={};for(let n=0;n{this.updateElementPosition(t,!1)}}):(a.execute(t),a.stop(),a.tick(o));const s=yield a.execute(t);if(r){const t=this.updateElementPosition(s,r);yield null==t?void 0:t.finished}return s}))}treeLayout(t,e,n){return ze(this,void 0,void 0,(function*(){const{type:n,animation:r}=e,i=Dc("layout",n);if(!i)return{};const{nodes:o=[],edges:a=[]}=t,s=new ev({nodes:o.map((t=>({id:Nh(t),data:t.data||{}}))),edges:a.map((t=>({id:Nh(t),source:t.source,target:t.target,data:t.data||{}})))});!function(t){if(t.hasTreeStructure(Ac))return;t.attachTreeStructure(Ac);const e=t.getAllEdges();for(const n of e){const{source:e,target:r}=n;t.setParent(r,e,Ac)}}(s);const l={nodes:[],edges:[]},u={nodes:[],edges:[]};s.getRoots(Ac).forEach((t=>{Ad(t,(t=>{t.children=s.getSuccessors(t.id)}),(t=>s.getSuccessors(t.id)),"TB");const n=i(t,e),{x:r,y:o,z:a=0}=n;Ad(n,(t=>{const{id:e,x:n,y:i,z:s=0}=t;l.nodes.push({id:e,style:{x:r,y:o,z:a}}),u.nodes.push({id:e,style:{x:n,y:i,z:s}})}),(t=>t.children),"TB")}));const c=this.inferTreeLayoutOffset(u);if(bU(u,c),r){bU(l,c),this.updateElementPosition(l,!1);const t=this.updateElementPosition(u,r);yield null==t?void 0:t.finished}return u}))}inferTreeLayoutOffset(t){var e;let[n,r]=[1/0,-1/0],[i,o]=[1/0,-1/0];null===(e=t.nodes)||void 0===e||e.forEach((t=>{const{x:e=0,y:a=0}=t.style||{};n=Math.min(n,e),r=Math.max(r,e),i=Math.min(i,a),o=Math.max(o,a)}));const{canvas:a}=this.context,s=a.getSize(),[l,u]=a.getCanvasByViewport([0,0]),[c,h]=a.getCanvasByViewport(s);if(n>=l&&r<=c&&i>=u&&o<=h)return[0,0];return[(l+c)/2-(n+r)/2,(u+h)/2-(i+o)/2]}stopLayout(){this.instance&&aE(this.instance)&&(this.instance.stop(),this.instance=void 0),this.supervisor&&(this.supervisor.stop(),this.supervisor=void 0),this.animationResult&&(this.animationResult.finish(),this.animationResult=void 0)}getLayoutData(t){const{nodeFilter:e=()=>!0,preLayout:n=!1,isLayoutInvisibleNodes:r=!1}=t,{nodes:i,edges:o,combos:a}=this.context.model.getData(),{element:s,model:l}=this.context,u=t=>s.getElement(t),c=n?t=>{var n;if(!r){if("hidden"===(null===(n=t.style)||void 0===n?void 0:n.visibility))return!1;if(l.getAncestorsData(t.id,Ac).some(_d))return!1;if(l.getAncestorsData(t.id,Cc).some(_d))return!1}return e(t)}:t=>{const n=Nh(t),r=u(n);return!!r&&(!Hg(r)&&e(t))},h=i.filter(c),d=new Map(h.map((t=>[Nh(t),t])));a.forEach((t=>d.set(Nh(t),t)));return{nodes:h,edges:o.filter((({source:t,target:e})=>d.has(t)&&d.has(e))),combos:a}}initGraphLayout(t){var e;const{element:n,viewport:r}=this.context,{type:i,enableWorker:o,animation:a,iterations:s}=t,l=Fe(t,["type","enableWorker","animation","iterations"]),[u,c]=r.getCanvasSize(),h=[u/2,c/2],d=null!==(e=null==t?void 0:t.nodeSize)&&void 0!==e?e:t=>{const e=null==n?void 0:n.getElement(t.id);return e?e.attributes.size:null==n?void 0:n.getElementComputedStyle("node",t).size},f=Dc("layout",i);if(!f)return Ic(`The layout of ${i} is not registered.`);const p=Object.getPrototypeOf(f.prototype)===nv.prototype?f:function(t,e){return class extends nv{constructor(e,n){if(super(e,n),this.instance=new t({}),this.id=this.instance.id,"stop"in this.instance&&"tick"in this.instance){const t=this.instance;this.stop=t.stop.bind(t),this.tick=e=>rv(t.tick(e))}}execute(t,e){return ze(this,void 0,void 0,(function*(){return rv(yield this.instance.execute(this.graphData2LayoutModel(t),this.transformOptions(ke({},this.options,e))))}))}transformOptions(t){const{onTick:e}=t;return e?(t.onTick=t=>e(rv(t)),t):t}graphData2LayoutModel(t){const{nodes:n=[],edges:r=[],combos:i=[]}=t,o=n.map((t=>{const e=Nh(t),{data:n,style:r,combo:i}=t,o=Fe(t,["data","style","combo"]),a={id:e,data:Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({},n),{data:n}),i?{parentId:i}:{}),{style:r}),o)};return(null==r?void 0:r.x)&&Object.assign(a.data,{x:r.x}),(null==r?void 0:r.y)&&Object.assign(a.data,{y:r.y}),(null==r?void 0:r.z)&&Object.assign(a.data,{z:r.z}),a})),a=new Map(o.map((t=>[t.id,t]))),s=r.filter((t=>{const{source:e,target:n}=t;return a.has(e)&&a.has(n)})).map((t=>{const{source:e,target:n,data:r,style:i}=t;return{id:Nh(t),source:e,target:n,data:Object.assign({},r),style:Object.assign({},i)}})),l=i.map((t=>({id:Nh(t),data:Object.assign({_isCombo:!0},t.data),style:Object.assign({},t.style)}))),u=new ev({nodes:[...o,...l],edges:s});return e.model.model.hasTreeStructure(Cc)&&(u.attachTreeStructure(Cc),o.forEach((t=>{const n=e.model.model.getParent(t.id,Cc);n&&u.hasNode(n.id)&&u.setParent(t.id,n.id,Cc)}))),u}}}(f,this.context),g=new p(this.context),v={nodeSize:d,width:u,height:c,center:h};switch(g.id){case"d3-force":case"d3-force-3d":Object.assign(v,{center:{x:u/2,y:c/2,z:0}})}return ke(g.options,v,l),g}updateElementPosition(t,e){const{model:n,element:r}=this.context;return r?(n.updateData(t),r.draw({animation:e,silence:!0})):null}destroy(){var t;this.stopLayout(),this.context={},null===(t=this.supervisor)||void 0===t||t.kill(),this.supervisor=void 0,this.instance=void 0,this.instances=[],this.animationResult=void 0}}const bU=(t,e)=>{var n;const[r,i]=e;null===(n=t.nodes)||void 0===n||n.forEach((t=>{if(t.style){const{x:e=0,y:n=0}=t.style;t.style.x=e+r,t.style.y=n+i}else t.style={x:r,y:i}}))};function xU(t){return t.layout?(Array.isArray(t.layout)||"preLayout"in t.layout||["antv-dagre","combo-combined","compact-box","circular","concentric","dagre","fishbone","grid","indented","mds","radial","random","snake","dendrogram","mindmap"].includes(t.layout.type)&&(t.layout.preLayout=!0),t):t}class EU extends Fh{constructor(t){super(t),this.category="plugin",this.setPlugins(this.context.options.plugins||[])}setPlugins(t){this.setExtensions(t)}getPluginInstance(t){const e=this.extensionMap[t];if(e)return e;Ic(`Cannot find the plugin ${t}, will try to find it by type.`);const n=this.extensions.find((e=>e.type===t));return n?this.extensionMap[n.key]:void 0}}const wU=["update-related-edges","collapse-expand-node","collapse-expand-combo","get-edge-actual-ends","arrange-draw-order"];class kU extends Fh{constructor(t){super(t),this.category="transform",this.setTransforms(this.context.options.transforms||[])}getTransforms(){}setTransforms(t){this.setExtensions([...wU.slice(0,wU.length-1),...t,wU[wU.length-1]])}getTransformInstance(t){return t?this.extensionMap[t]:this.extensionMap}}class MU{get padding(){return Jc(this.context.options.padding)}get paddingOffset(){const[t,e,n,r]=this.padding,[i,o,a]=[(r-e)/2,(t-n)/2,0];return[i,o,a]}constructor(t){this.landmarkCounter=0,this.context=t;const[e,n]=this.paddingOffset,{zoom:r,rotation:i,x:o=e,y:a=n}=t.options;this.transform({mode:"absolute",scale:r,translate:[o,a],rotate:i},!1)}get camera(){const{canvas:t}=this.context;return new Proxy(t.getCamera(),{get:(e,n)=>{const r=Object.entries(t.getLayers()).filter((([t])=>!["main"].includes(t))),i=r.map((([,t])=>t.getCamera())),o=e[n];if("function"==typeof o)return(...t)=>{const r=o.apply(e,t);return i.forEach((e=>{e[n].apply(e,t)})),r}}})}createLandmark(t){return this.camera.createLandmark("landmark-"+this.landmarkCounter++,t)}getAnimation(t){const e=Gc(this.context.options,t);return!!e&&Ae(Object.assign({},e),["easing","duration"])}getCanvasSize(){const{canvas:t}=this.context,{width:e=0,height:n=0}=t.getConfig();return[e,n]}getCanvasCenter(){const{canvas:t}=this.context,{width:e=0,height:n=0}=t.getConfig();return[e/2,n/2,0]}getViewportCenter(){const[t,e]=this.camera.getPosition();return[t,e,0]}getGraphCenter(){return this.context.graph.getViewportByCanvas(this.getCanvasCenter())}getZoom(){return this.camera.getZoom()}getRotation(){return this.camera.getRoll()}getTranslateOptions(t){const{camera:e}=this,{mode:n,translate:r=[]}=t,i=this.getZoom(),o=e.getPosition(),a=e.getFocalPoint(),[s,l]=this.getCanvasCenter(),[u=0,c=0,h=0]=r,d=Yh([-u,-c,-h],i);return"relative"===n?{position:Hh(o,d),focalPoint:Hh(a,d)}:{position:Hh([s,l,o[2]],d),focalPoint:Hh([s,l,a[2]],d)}}getRotateOptions(t){const{mode:e,rotate:n=0}=t;return{roll:"relative"===e?this.camera.getRoll()+n:n}}getZoomOptions(t){const{zoomRange:e}=this.context.options,n=this.camera.getZoom(),{mode:r,scale:i=1}=t;return oe("relative"===r?n*i:i,...e)}transform(e,n){return ze(this,void 0,void 0,(function*(){const{graph:r}=this.context,{translate:i,rotate:o,scale:a,origin:s}=e;this.cancelAnimation();const l=this.getAnimation(n);if(rU(r,new nU(t.GraphEvent.BEFORE_TRANSFORM,e)),!o&&a&&!i&&s&&!l)return this.camera.setZoomByViewportPoint(this.getZoomOptions(e),s),void rU(r,new nU(t.GraphEvent.AFTER_TRANSFORM,e));const u={};if(i&&Object.assign(u,this.getTranslateOptions(e)),ae(o)&&Object.assign(u,this.getRotateOptions(e)),ae(a)&&Object.assign(u,{zoom:this.getZoomOptions(e)}),l)return rU(r,new tU(t.GraphEvent.BEFORE_ANIMATE,Ec.TRANSFORM,null,e)),new Promise((n=>{this.transformResolver=n,this.camera.gotoLandmark(this.createLandmark(u),Object.assign(Object.assign({},l),{onfinish:()=>{rU(r,new tU(t.GraphEvent.AFTER_ANIMATE,Ec.TRANSFORM,null,e)),rU(r,new nU(t.GraphEvent.AFTER_TRANSFORM,e)),this.transformResolver=void 0,n()}}))}));this.camera.gotoLandmark(this.createLandmark(u),{duration:0}),rU(r,new nU(t.GraphEvent.AFTER_TRANSFORM,e))}))}fitView(t,e){return ze(this,void 0,void 0,(function*(){const[n,r,i,o]=this.padding,{when:a="always",direction:s="both"}=t||{},[l,u]=this.context.canvas.getSize(),c=l-o-r,h=u-n-i,d=this.context.canvas.getBounds(),f=this.getBBoxInViewport(d),[p,g]=rh(f);if("overflow"===a&&!("x"===s&&p>=c||"y"===s&&g>=h||"both"===s&&p>=c&&g>=h))return yield this.fitCenter({animation:e});const v=c/p,m=h/g,y="x"===s?v:"y"===s?m:Math.min(v,m),b=this.getAnimation(e);yield this.transform({mode:"relative",scale:y,translate:Hh(Uh(this.getCanvasCenter(),this.getBBoxInViewport(d).center),Yh(this.paddingOffset,y))},b)}))}fitCenter(t){return ze(this,void 0,void 0,(function*(){const e=this.context.canvas.getBounds();yield this.focus(e,t)}))}focusElements(t){return ze(this,arguments,void 0,(function*(t,e={}){const{element:n}=this.context;if(!n)return;const r=sh(t.map((t=>{return r=n.getElement(t),e.shapes?r.getShape(e.shapes).getRenderBounds():r.getRenderBounds();var r})));yield this.focus(r,e)}))}focus(t,e){return ze(this,void 0,void 0,(function*(){const n=this.context.graph.getViewportByCanvas(t.center),r=Uh(e.position||this.getCanvasCenter(),n);yield this.transform({mode:"relative",translate:Hh(r,this.paddingOffset)},e.animation)}))}getBBoxInViewport(t){const{min:e,max:n}=t,{graph:r}=this.context,[i,o]=r.getViewportByCanvas(e),[a,s]=r.getViewportByCanvas(n),l=new Er;return l.setMinMax([i,o,0],[a,s,0]),l}isInViewport(t,e=!1,n=0){const{graph:r}=this.context,i=this.getCanvasSize(),[o,a]=r.getCanvasByViewport([0,0]),[s,l]=r.getCanvasByViewport(i);let u=new Er;return u.setMinMax([o,a,0],[s,l,0]),n&&(u=ah(u,n)),Zc(t)?lh(t,u):e?function(t,e){const[n,r]=t.min,[i,o]=t.max,[a,s]=e.min,[l,u]=e.max;return n>=a&&i<=l&&r>=s&&o<=u}(t,u):u.intersects(t)}cancelAnimation(){var t,e;(null===(t=this.camera.landmarks)||void 0===t?void 0:t.length)&&this.camera.cancelLandmarkAnimation(),null===(e=this.transformResolver)||void 0===e||e.call(this)}}class SU extends Kg{constructor(t){var e;super(),this.options={},this.rendered=!1,this.destroyed=!1,this.context={model:new vU},this.isCollapsingExpanding=!1,this.onResize=ye((()=>{this.resize()}),300),this._setOptions(Object.assign({},SU.defaultOptions,t),!0),this.context.graph=this,this.options.autoResize&&(null===(e=globalThis.addEventListener)||void 0===e||e.call(globalThis,"resize",this.onResize))}getOptions(){return this.options}setOptions(t){this._setOptions(t,!1)}_setOptions(t,e){if(this.updateCanvas(t),Object.assign(this.options,function(t){return[xU].reduce(((t,e)=>e(t)),t)}(t)),e){const{data:e}=t;return void(e&&this.addData(e))}const{behaviors:n,combo:r,data:i,edge:o,layout:a,node:s,plugins:l,theme:u,transforms:c}=t;n&&this.setBehaviors(n),i&&this.setData(i),s&&this.setNode(s),o&&this.setEdge(o),r&&this.setCombo(r),a&&this.setLayout(a),u&&this.setTheme(u),l&&this.setPlugins(l),c&&this.setTransforms(c)}getSize(){return this.context.canvas?this.context.canvas.getSize():[this.options.width||0,this.options.height||0]}setSize(t,e){t&&(this.options.width=t),e&&(this.options.height=e),this.resize(t,e)}setZoomRange(t){this.options.zoomRange=t}getZoomRange(){return this.options.zoomRange}setNode(t){this.options.node=t,this.context.model.refreshData()}setEdge(t){this.options.edge=t,this.context.model.refreshData()}setCombo(t){this.options.combo=t,this.context.model.refreshData()}getTheme(){return this.options.theme}setTheme(t){this.options.theme=Ut(t)?t(this.getTheme()):t}setLayout(t){this.options.layout=Ut(t)?t(this.getLayout()):t}getLayout(){return this.options.layout}setBehaviors(t){var e;this.options.behaviors=Ut(t)?t(this.getBehaviors()):t,null===(e=this.context.behavior)||void 0===e||e.setBehaviors(this.options.behaviors)}updateBehavior(t){this.setBehaviors((e=>e.map((e=>"object"==typeof e&&e.key===t.key?Object.assign(Object.assign({},e),t):e))))}getBehaviors(){return this.options.behaviors||[]}setPlugins(t){var e;this.options.plugins=Ut(t)?t(this.getPlugins()):t,null===(e=this.context.plugin)||void 0===e||e.setPlugins(this.options.plugins)}updatePlugin(t){this.setPlugins((e=>e.map((e=>"object"==typeof e&&e.key===t.key?Object.assign(Object.assign({},e),t):e))))}getPlugins(){return this.options.plugins||[]}getPluginInstance(t){return this.context.plugin.getPluginInstance(t)}setTransforms(t){var e;this.options.transforms=Ut(t)?t(this.getTransforms()):t,null===(e=this.context.transform)||void 0===e||e.setTransforms(this.options.transforms)}updateTransform(t){this.setTransforms((e=>e.map((e=>"object"==typeof e&&e.key===t.key?Object.assign(Object.assign({},e),t):e)))),this.context.model.refreshData()}getTransforms(){return this.options.transforms||[]}getData(){return this.context.model.getData()}getElementData(t){return Array.isArray(t)?t.map((t=>this.context.model.getElementDataById(t))):this.context.model.getElementDataById(t)}getNodeData(t){return void 0===t?this.context.model.getNodeData():Array.isArray(t)?this.context.model.getNodeData(t):this.context.model.getNodeLikeDatum(t)}getEdgeData(t){return void 0===t?this.context.model.getEdgeData():Array.isArray(t)?this.context.model.getEdgeData(t):this.context.model.getEdgeDatum(t)}getComboData(t){return void 0===t?this.context.model.getComboData():Array.isArray(t)?this.context.model.getComboData(t):this.context.model.getNodeLikeDatum(t)}setData(t){this.context.model.setData(Ut(t)?t(this.getData()):t)}addData(t){this.context.model.addData(Ut(t)?t(this.getData()):t)}addNodeData(t){this.context.model.addNodeData(Ut(t)?t(this.getNodeData()):t)}addEdgeData(t){this.context.model.addEdgeData(Ut(t)?t(this.getEdgeData()):t)}addComboData(t){this.context.model.addComboData(Ut(t)?t(this.getComboData()):t)}addChildrenData(t,e){this.context.model.addChildrenData(t,e)}updateData(t){this.context.model.updateData(Ut(t)?t(this.getData()):t)}updateNodeData(t){this.context.model.updateNodeData(Ut(t)?t(this.getNodeData()):t)}updateEdgeData(t){this.context.model.updateEdgeData(Ut(t)?t(this.getEdgeData()):t)}updateComboData(t){this.context.model.updateComboData(Ut(t)?t(this.getComboData()):t)}removeData(t){this.context.model.removeData(Ut(t)?t(this.getData()):t)}removeNodeData(t){this.context.model.removeNodeData(Ut(t)?t(this.getNodeData()):t)}removeEdgeData(t){this.context.model.removeEdgeData(Ut(t)?t(this.getEdgeData()):t)}removeComboData(t){this.context.model.removeComboData(Ut(t)?t(this.getComboData()):t)}getElementType(t){return this.context.model.getElementType(t)}getRelatedEdgesData(t,e="both"){return this.context.model.getRelatedEdgesData(t,e)}getNeighborNodesData(t){return this.context.model.getNeighborNodesData(t)}getAncestorsData(t,e){return this.context.model.getAncestorsData(t,e)}getParentData(t,e){return this.context.model.getParentData(t,e)}getChildrenData(t){return this.context.model.getChildrenData(t)}getDescendantsData(t){return this.context.model.getDescendantsData(t)}getElementDataByState(t,e){return this.context.model.getElementDataByState(t,e)}initCanvas(){return ze(this,void 0,void 0,(function*(){var e;if(this.context.canvas)return yield this.context.canvas.ready;const{container:n="container",width:r,height:i,renderer:o,cursor:a,background:s,canvas:l,devicePixelRatio:u=(null!==(e=globalThis.devicePixelRatio)&&void 0!==e?e:1)}=this.options;if(n instanceof YH)this.context.canvas=n,a&&n.setCursor(a),o&&n.setRenderer(o),yield n.ready;else{const e=ne(n)?document.getElementById(n):n,c=ZH(e);this.emit(t.GraphEvent.BEFORE_CANVAS_INIT,{container:e,width:r,height:i});const h=Object.assign(Object.assign({},l),{container:e,width:r||c[0],height:i||c[1],background:s,renderer:o,cursor:a,devicePixelRatio:u}),d=new YH(h);this.context.canvas=d,yield d.ready,this.emit(t.GraphEvent.AFTER_CANVAS_INIT,{canvas:d})}}))}updateCanvas(e){var n,r;const{renderer:i,cursor:o,height:a,width:s}=e,l=this.context.canvas;l&&(i&&(this.emit(t.GraphEvent.BEFORE_RENDERER_CHANGE,{renderer:this.options.renderer}),l.setRenderer(i),this.emit(t.GraphEvent.AFTER_RENDERER_CHANGE,{renderer:i})),o&&l.setCursor(o),(ae(s)||ae(a))&&this.setSize(null!==(n=null!=s?s:this.options.width)&&void 0!==n?n:0,null!==(r=null!=a?a:this.options.height)&&void 0!==r?r:0))}initRuntime(){this.context.options=this.options,this.context.batch||(this.context.batch=new uU(this.context)),this.context.plugin||(this.context.plugin=new EU(this.context)),this.context.viewport||(this.context.viewport=new MU(this.context)),this.context.transform||(this.context.transform=new kU(this.context)),this.context.element||(this.context.element=new mU(this.context)),this.context.animation||(this.context.animation=new lU(this.context)),this.context.layout||(this.context.layout=new yU(this.context)),this.context.behavior||(this.context.behavior=new cU(this.context))}prepare(){return ze(this,void 0,void 0,(function*(){yield Promise.resolve(),this.destroyed?console.error(_c("The graph instance has been destroyed")):(yield this.initCanvas(),this.initRuntime())}))}render(){return ze(this,void 0,void 0,(function*(){if(yield this.prepare(),rU(this,new JH(t.GraphEvent.BEFORE_RENDER)),this.options.layout)if(this.rendered||(e=this.options.layout,Array.isArray(e)||!(null==e?void 0:e.preLayout))){const t=this.context.element.draw({type:"render"});yield Promise.all([null==t?void 0:t.finished,this.context.layout.postLayout()]),yield this.autoFit()}else{const t=yield this.context.element.preLayoutDraw({type:"render"});yield Promise.all([null==t?void 0:t.finished,this.autoFit()])}else{const t=this.context.element.draw({type:"render"});yield Promise.all([null==t?void 0:t.finished,this.autoFit()])}var e;this.rendered=!0,rU(this,new JH(t.GraphEvent.AFTER_RENDER))}))}draw(){return ze(this,void 0,void 0,(function*(){var t;yield this.prepare(),yield null===(t=this.context.element.draw())||void 0===t?void 0:t.finished}))}layout(t){return ze(this,void 0,void 0,(function*(){yield this.context.layout.postLayout(t)}))}stopLayout(){this.context.layout.stopLayout()}clear(){return ze(this,void 0,void 0,(function*(){const{model:t,element:e}=this.context;t.setData({}),t.clearChanges(),null==e||e.clear()}))}destroy(){var e;rU(this,new JH(t.GraphEvent.BEFORE_DESTROY));const{layout:n,animation:r,element:i,model:o,canvas:a,behavior:s,plugin:l}=this.context;null==l||l.destroy(),null==s||s.destroy(),null==n||n.destroy(),null==r||r.destroy(),null==i||i.destroy(),o.destroy(),null==a||a.destroy(),this.options={},this.context={},this.off(),null===(e=globalThis.removeEventListener)||void 0===e||e.call(globalThis,"resize",this.onResize),this.destroyed=!0,rU(this,new JH(t.GraphEvent.AFTER_DESTROY))}getCanvas(){return this.context.canvas}resize(e,n){var r;const i=ZH(null===(r=this.context.canvas)||void 0===r?void 0:r.getContainer()),o=[e||i[0],n||i[1]];if(!this.context.canvas)return;const a=this.context.canvas.getSize();Ne(o,a)||(rU(this,new JH(t.GraphEvent.BEFORE_SIZE_CHANGE,{size:o})),this.context.canvas.resize(...o),rU(this,new JH(t.GraphEvent.AFTER_SIZE_CHANGE,{size:o})))}fitView(t,e){return ze(this,void 0,void 0,(function*(){var n;yield null===(n=this.context.viewport)||void 0===n?void 0:n.fitView(t,e)}))}fitCenter(t){return ze(this,void 0,void 0,(function*(){var e;yield null===(e=this.context.viewport)||void 0===e?void 0:e.fitCenter({animation:t})}))}autoFit(){return ze(this,void 0,void 0,(function*(){const{autoFit:t}=this.context.options;if(t)if(ne(t))"view"===t?yield this.fitView():"center"===t&&(yield this.fitCenter());else{const{type:e,animation:n}=t;"view"===e?yield this.fitView(t.options,n):"center"===e&&(yield this.fitCenter(n))}}))}focusElement(t,e){return ze(this,void 0,void 0,(function*(){var n;yield null===(n=this.context.viewport)||void 0===n?void 0:n.focusElements(Array.isArray(t)?t:[t],{animation:e})}))}zoomBy(t,e,n){return ze(this,void 0,void 0,(function*(){yield this.context.viewport.transform({mode:"relative",scale:t,origin:n},e)}))}zoomTo(t,e,n){return ze(this,void 0,void 0,(function*(){yield this.context.viewport.transform({mode:"absolute",scale:t,origin:n},e)}))}getZoom(){return this.context.viewport.getZoom()}rotateBy(t,e,n){return ze(this,void 0,void 0,(function*(){yield this.context.viewport.transform({mode:"relative",rotate:t,origin:n},e)}))}rotateTo(t,e,n){return ze(this,void 0,void 0,(function*(){yield this.context.viewport.transform({mode:"absolute",rotate:t,origin:n},e)}))}getRotation(){return this.context.viewport.getRotation()}translateBy(t,e){return ze(this,void 0,void 0,(function*(){yield this.context.viewport.transform({mode:"relative",translate:t},e)}))}translateTo(t,e){return ze(this,void 0,void 0,(function*(){yield this.context.viewport.transform({mode:"absolute",translate:t},e)}))}getPosition(){return Uh([0,0],this.getCanvasByViewport([0,0]))}translateElementBy(t,e){return ze(this,arguments,void 0,(function*(t,e,n=!0){var r,i;const[o,a]=qt(t)?[t,null===(r=e)||void 0===r||r]:[{[t]:e},n];Object.entries(o).forEach((([t,e])=>this.context.model.translateNodeLikeBy(t,e))),yield null===(i=this.context.element.draw({animation:a,stage:"translate"}))||void 0===i?void 0:i.finished}))}translateElementTo(t,e){return ze(this,arguments,void 0,(function*(t,e,n=!0){var r,i;const[o,a]=qt(t)?[t,null===(r=e)||void 0===r||r]:[{[t]:e},n];Object.entries(o).forEach((([t,e])=>this.context.model.translateNodeLikeTo(t,e))),yield null===(i=this.context.element.draw({animation:a,stage:"translate"}))||void 0===i?void 0:i.finished}))}getElementPosition(t){return this.context.model.getElementPosition(t)}getElementRenderStyle(t){return Pe(this.context.element.getElement(t).attributes,["context"])}setElementVisibility(t,e){return ze(this,arguments,void 0,(function*(t,e,n=!0){var r,i;const[o,a]=qt(t)?[t,null===(r=e)||void 0===r||r]:[{[t]:e},n],s={nodes:[],edges:[],combos:[]};Object.entries(o).forEach((([t,e])=>{const n=this.getElementType(t);s[`${n}s`].push({id:t,style:{visibility:e}})}));const{model:l,element:u}=this.context;l.preventUpdateNodeLikeHierarchy((()=>{l.updateData(s)})),yield null===(i=u.draw({animation:a,stage:"visibility"}))||void 0===i?void 0:i.finished}))}showElement(t,e){return ze(this,void 0,void 0,(function*(){const n=Array.isArray(t)?t:[t];yield this.setElementVisibility(Object.fromEntries(n.map((t=>[t,"visible"]))),e)}))}hideElement(t,e){return ze(this,void 0,void 0,(function*(){const n=Array.isArray(t)?t:[t];yield this.setElementVisibility(Object.fromEntries(n.map((t=>[t,"hidden"]))),e)}))}getElementVisibility(t){var e,n;const r=this.context.element.getElement(t);return null!==(n=null===(e=null==r?void 0:r.style)||void 0===e?void 0:e.visibility)&&void 0!==n?n:"visible"}setElementZIndex(t,e){return ze(this,void 0,void 0,(function*(){var n;const r={nodes:[],edges:[],combos:[]},i=qt(t)?t:{[t]:e};Object.entries(i).forEach((([t,e])=>{const n=this.getElementType(t);r[`${n}s`].push({id:t,style:{zIndex:e}})}));const{model:o,element:a}=this.context;o.preventUpdateNodeLikeHierarchy((()=>o.updateData(r))),yield null===(n=a.draw({animation:!1,stage:"zIndex"}))||void 0===n?void 0:n.finished}))}frontElement(t){return ze(this,void 0,void 0,(function*(){const e=Array.isArray(t)?t:[t],{model:n}=this.context,r={};e.map((t=>{const e=n.getFrontZIndex(t);if("combo"===n.getElementType(t)){const i=n.getAncestorsData(t,Cc).at(-1)||this.getComboData(t),o=[i,...n.getDescendantsData(Nh(i))],a=e-iU(i);o.forEach((t=>{r[Nh(t)]=this.getElementZIndex(Nh(t))+a}));const{internal:s}=lg(o.map(Nh),(t=>n.getRelatedEdgesData(t)));s.forEach((t=>{const e=Nh(t);r[e]=this.getElementZIndex(e)+a}))}else r[t]=e})),yield this.setElementZIndex(r)}))}getElementZIndex(t){return iU(this.context.model.getElementDataById(t))}setElementState(t,e){return ze(this,arguments,void 0,(function*(t,e,n=!0){var r,i;const[o,a]=qt(t)?[t,null===(r=e)||void 0===r||r]:[{[t]:e},n],s={nodes:[],edges:[],combos:[]};Object.entries(o).forEach((([t,e])=>{const n=this.getElementType(t);var r;s[`${n}s`].push({id:t,states:(r=e,r?Array.isArray(r)?r:[r]:[])})})),this.updateData(s),yield null===(i=this.context.element.draw({animation:a,stage:"state"}))||void 0===i?void 0:i.finished}))}getElementState(t){return this.context.model.getElementState(t)}getElementRenderBounds(t){return this.context.element.getElement(t).getRenderBounds()}collapseElement(t){return ze(this,arguments,void 0,(function*(t,e=!0){const{model:n,element:r}=this.context;if(_d(n.getNodeLikeData([t])[0]))return;if(this.isCollapsingExpanding)return;"boolean"==typeof e&&(e={animation:e,align:!0});const i=n.getElementType(t);yield this.frontElement(t),this.isCollapsingExpanding=!0,this.setElementCollapsibility(t,!0),"node"===i?yield r.collapseNode(t,e):"combo"===i&&(yield r.collapseCombo(t,!!e.animation)),this.isCollapsingExpanding=!1}))}expandElement(t){return ze(this,arguments,void 0,(function*(t,e=!0){const{model:n,element:r}=this.context;if(!_d(n.getNodeLikeData([t])[0]))return;if(this.isCollapsingExpanding)return;"boolean"==typeof e&&(e={animation:e,align:!0});const i=n.getElementType(t);this.isCollapsingExpanding=!0,this.setElementCollapsibility(t,!1),"node"===i?yield r.expandNode(t,e):"combo"===i&&(yield r.expandCombo(t,!!e.animation)),this.isCollapsingExpanding=!1}))}setElementCollapsibility(t,e){const n=this.getElementType(t);"node"===n?this.updateNodeData([{id:t,style:{collapsed:e}}]):"combo"===n&&this.updateComboData([{id:t,style:{collapsed:e}}])}toDataURL(){return ze(this,arguments,void 0,(function*(t={}){return this.context.canvas.toDataURL(t)}))}getCanvasByViewport(t){return this.context.canvas.getCanvasByViewport(t)}getViewportByCanvas(t){return this.context.canvas.getViewportByCanvas(t)}getClientByCanvas(t){return this.context.canvas.getClientByCanvas(t)}getCanvasByClient(t){return this.context.canvas.getCanvasByClient(t)}getViewportCenter(){return this.context.viewport.getViewportCenter()}getCanvasCenter(){return this.context.viewport.getCanvasCenter()}on(t,e,n){return super.on(t,e,n)}once(t,e){return super.once(t,e)}off(t,e){return super.off(t,e)}}SU.defaultOptions={autoResize:!1,theme:"light",rotation:0,zoom:1,zoomRange:[.01,10]};const NU=(t,e)=>{const{source:n,target:r}=e,i=t.getElementDataById(n),o=t.getElementDataById(r),a=ug(i,(e=>t.getParentData(e,Cc))),s=ug(o,(e=>t.getParentData(e,Cc))),l={sourceNode:Nh(a),targetNode:Nh(s)};return e.style?Object.assign(e.style,l):e.style=l,e};class OU extends IH{constructor(t,e){super(t,ke({},OU.defaultOptions,e)),this.assignSizeByCentrality=(t,e,n,r,i,o)=>{const a=[e,n],s=[r[0],i[0]],l=[r[1],i[1]],u=[r[2],i[2]],c=(t,e)=>{if("function"==typeof o)return o(t,a,e);switch(o){case"linear":return((t,e,n)=>{const[r,i]=e,[o,a]=n;return i===r?o:o+(t-r)/(i-r)*(a-o)})(t,a,e);case"log":return((t,e,n)=>{const[r,i]=e,[o,a]=n;return o+Math.log(t-r+1)/Math.log(i-r+1)*(a-o)})(t,a,e);case"pow":return((t,e,n,r=2)=>{const[i,o]=e,[a,s]=n;return a+Math.pow((t-i)/(o-i),r)*(s-a)})(t,a,e,2);case"sqrt":return((t,e,n)=>{const[r,i]=e,[o,a]=n;return o+Math.sqrt((t-r)/(i-r))*(a-o)})(t,a,e);default:return e[0]}};return[c(t,s),c(t,l),c(t,u)]}}beforeDraw(t){const{model:e}=this.context,n=e.getNodeData(),r=Gd(this.options.maxSize),i=Gd(this.options.minSize),o=this.getCentralities(this.options.centrality),a=o.size>0?Math.max(...o.values()):0,s=o.size>0?Math.min(...o.values()):0;return n.forEach((e=>{var n;const l=this.assignSizeByCentrality(o.get(Nh(e))||0,s,a,i,r,this.options.scale),u=null===(n=this.context.element)||void 0===n?void 0:n.getElement(Nh(e)),c={size:l};this.assignLabelStyle(c,l,e,u),u&&BH(c,u.attributes)||jH(t,u?"update":"add","node",ke(e,{style:c}),!0)})),t}assignLabelStyle(t,e,n,r){var i;const o=r?r.config.style:null===(i=this.context.element)||void 0===i?void 0:i.getElementComputedStyle("node",n);if(Object.assign(t,Ae(o,["labelFontSize","labelLineHeight"])),this.options.mapLabelSize){const n=this.getLabelSizeByNodeSize(e,1/0,Number(t.labelFontSize));Object.assign(t,{labelFontSize:n,labelLineHeight:n+th(t.labelPadding)})}return t}getLabelSizeByNodeSize(t,e,n){const r=Math.min(...t)/2,[i,o]=Array.isArray(this.options.mapLabelSize)?this.options.mapLabelSize:[n,e];return Math.min(o,Math.max(r,i))}getCentralities(t){const{model:e}=this.context,n=e.getData();if("function"==typeof t)return t(n);const r=e.getRelatedEdgesData.bind(e);return Ch(n,r,t)}}OU.defaultOptions={centrality:{type:"degree"},maxSize:80,minSize:20,scale:"linear",mapLabelSize:!1};class TU extends IH{constructor(t,e){super(t,Object.assign({},TU.defaultOptions,e))}get ref(){return this.context.model.getRootsData()[0]}afterLayout(){var t;const e=sd(this.ref),{graph:n,model:r}=this.context;null===(t=r.getData().nodes)||void 0===t||t.forEach((t=>{var i;if(Nh(t)===Nh(this.ref))return;const o=rd(Uh(sd(t),e)),a=Math.abs(o)>Math.PI/2,s=!t.children||0===t.children.length,l=Nh(t),u=null===(i=this.context.element)||void 0===i?void 0:i.getElement(l);if(!u||!u.isVisible())return;const c=(s?1:-1)*(Gd(n.getElementRenderStyle(l).size)[0]/2+this.options.offset),h=[["translate",c*Math.cos(o),c*Math.sin(o)],["rotate",a?_r(o)+180:_r(o)]];r.updateNodeData([{id:Nh(t),style:{labelTextAlign:a===s?"right":"left",labelTextBaseline:"middle",labelTransform:h}}])})),n.draw()}}TU.defaultOptions={offset:5};const CU=["top","top-right","right","right-bottom","bottom","bottom-left","left","left-top"];class AU extends IH{constructor(t,e){super(t,Object.assign({},AU.defaultOptions,e)),this.cacheMergeStyle=new Map,this.getAffectedParallelEdges=t=>{const{add:{edges:e},update:{nodes:n,edges:r,combos:i},remove:{edges:o}}=t,{model:a}=this.context,s=new Map,l=(t,e)=>{a.getRelatedEdgesData(e).forEach((t=>!s.has(Nh(t))&&s.set(Nh(t),t)))};n.forEach(l),i.forEach(l);const u=t=>{const e=a.getEdgeData().map((t=>NU(a,t)));RU(t,e).forEach((t=>!s.has(Nh(t))&&s.set(Nh(t),t)))};if(o.size&&o.forEach(u),e.size&&e.forEach(u),r.size){const t=sF(aF(a.getChanges())).update.edges;r.forEach((e=>{var n;u(e);const r=null===(n=t.find((t=>Nh(t.value)===Nh(e))))||void 0===n?void 0:n.original;r&&!DU(e,r)&&u(r)}))}Se(this.options.edges)||s.forEach(((t,e)=>!this.options.edges.includes(e)&&s.delete(e)));const c=a.getEdgeData().map(Nh);return new Map([...s].sort(((t,e)=>c.indexOf(t[0])-c.indexOf(e[0]))))},this.applyBundlingStyle=(t,e,n)=>{const{edgeMap:r,reverses:i}=PU(e);r.forEach((e=>{e.forEach(((e,r,o)=>{var a;const s=o.length,l=e.style||{};if(e.source===e.target){const t=CU.length;l.loopPlacement=CU[r%t],l.loopDist=Math.floor(r/t)*n+50}else if(1===s)l.curveOffset=0;else{const t=(r%2==0?1:-1)*(i[`${e.source}|${e.target}|${r}`]?-1:1);l.curveOffset=s%2==1?t*Math.ceil(r/2)*n*2:t*(Math.floor(r/2)*n*2+n)}const u=Object.assign(e,{type:"quadratic",style:l}),c=null===(a=this.context.element)||void 0===a?void 0:a.getElement(Nh(e));c&&BH(u.style,c.attributes)||jH(t,c?"update":"add","edge",u,!0)}))}))},this.resetEdgeStyle=t=>{const e=t.style||{},n=this.cacheMergeStyle.get(Nh(t))||{};return Object.keys(n).forEach((r=>{Ne(e[r],n[r])&&(t[r]?e[r]=t[r]:delete e[r])})),Object.assign(t,{style:e})},this.applyMergingStyle=(t,e)=>{const{edgeMap:n,reverses:r}=PU(e);n.forEach((e=>{var n;if(1===e.length){const r=e[0],i=null===(n=this.context.element)||void 0===n?void 0:n.getElement(Nh(r)),o=this.resetEdgeStyle(r);return void(i&&BH(o,i.attributes)||jH(t,i?"update":"add","edge",o))}const i=e.map((({source:t,target:e,style:n={}},i)=>{const{startArrow:o,endArrow:a}=n,s={},[l,u]=r[`${t}|${e}|${i}`]?["endArrow","startArrow"]:["startArrow","endArrow"];return pe(o)&&(s[l]=o),pe(a)&&(s[u]=a),s})).reduce(((t,e)=>Object.assign(Object.assign({},t),e)),{});e.forEach(((e,n,r)=>{var o;if(0!==n)return void jH(t,"remove","edge",e);const a=Object.assign({},Ut(this.options.style)?this.options.style(r):this.options.style,{childrenData:r});this.cacheMergeStyle.set(Nh(e),a);const s=Object.assign(Object.assign({},e),{type:"line",style:Object.assign(Object.assign(Object.assign({},e.style),i),a)}),l=null===(o=this.context.element)||void 0===o?void 0:o.getElement(Nh(e));l&&BH(s.style,l.attributes)||jH(t,l?"update":"add","edge",s,!0)}))}))}}beforeDraw(t){const e=this.getAffectedParallelEdges(t);return 0===e.size||("bundle"===this.options.mode?this.applyBundlingStyle(t,e,this.options.distance):this.applyMergingStyle(t,e)),t}}AU.defaultOptions={mode:"bundle",distance:15};const PU=t=>{const e=new Map,n=new Set,r={},i=new Map;for(const[o,a]of t){if(n.has(o))continue;const{source:s,target:l}=a,u=`${s}-${l}`;e.has(u)||(e.set(u,[]),i.set(u,new Set));const c=e.get(u),h=i.get(u);c&&h&&!h.has(o)&&(c.push(a),h.add(o),n.add(o));for(const[c,h]of t)if(!n.has(c)&&c!==o&&DU(a,h)){const t=e.get(u),o=i.get(u);t&&o&&!o.has(c)&&(t.push(h),o.add(c),s===h.target&&l===h.source&&(r[`${h.source}|${h.target}|${t.length-1}`]=!0),n.add(c))}}return{edgeMap:e,reverses:r}},RU=(t,e,n)=>e.filter((e=>DU(e,t))),DU=(t,e)=>{const{sourceNode:n,targetNode:r}=t.style||{},{sourceNode:i,targetNode:o}=e.style||{};return n===i&&r===o||n===o&&r===i};const LU={animation:{"combo-collapse":Xc,"combo-expand":Kc,"node-collapse":Uc,"node-expand":$c,"path-in":Yc,"path-out":qc,fade:[{fields:["opacity"]}],translate:[{fields:["x","y"]}]},behavior:{"brush-select":Nd,"click-select":Ld,"collapse-expand":Ug,"create-edge":Yg,"drag-canvas":qg,"drag-element-force":av,"drag-element":Xg,"fix-element-size":sv,"focus-element":lv,"hover-activate":uv,"lasso-select":cv,"auto-adapt-label":Vh,"optimize-viewport-transform":hv,"scroll-canvas":dv,"zoom-canvas":fv},combo:{circle:zp,rect:Gp},edge:{cubic:fg,line:mg,polyline:Tg,quadratic:Cg,"cubic-horizontal":pg,"cubic-radial":gg,"cubic-vertical":vg},layout:{"antv-dagre":Sb,"combo-combined":uE,"compact-box":Em.compactBox,"d3-force":ZE,"force-atlas2":sj,circular:Cb,concentric:Db,dagre:nj,dendrogram:Em.dendrogram,fishbone:Zj,force:nx,fruchterman:uj,grid:hj,indented:Em.indented,mds:rE,mindmap:Em.mindmap,radial:wj,random:Cj,snake:eB},node:{circle:df,diamond:pf,ellipse:yf,hexagon:bf,html:Lp,image:_p,rect:Ip,star:jp,donut:gf,triangle:Bp},palette:{spectral:["rgb(158, 1, 66)","rgb(213, 62, 79)","rgb(244, 109, 67)","rgb(253, 174, 97)","rgb(254, 224, 139)","rgb(255, 255, 191)","rgb(230, 245, 152)","rgb(171, 221, 164)","rgb(102, 194, 165)","rgb(50, 136, 189)","rgb(94, 79, 162)"],tableau:["rgb(78, 121, 167)","rgb(242, 142, 44)","rgb(225, 87, 89)","rgb(118, 183, 178)","rgb(89, 161, 79)","rgb(237, 201, 73)","rgb(175, 122, 161)","rgb(255, 157, 167)","rgb(156, 117, 95)","rgb(186, 176, 171)"],oranges:["rgb(255, 245, 235)","rgb(254, 230, 206)","rgb(253, 208, 162)","rgb(253, 174, 107)","rgb(253, 141, 60)","rgb(241, 105, 19)","rgb(217, 72, 1)","rgb(166, 54, 3)","rgb(127, 39, 4)"],greens:["rgb(247, 252, 245)","rgb(229, 245, 224)","rgb(199, 233, 192)","rgb(161, 217, 155)","rgb(116, 196, 118)","rgb(65, 171, 93)","rgb(35, 139, 69)","rgb(0, 109, 44)","rgb(0, 68, 27)"],blues:["rgb(247, 251, 255)","rgb(222, 235, 247)","rgb(198, 219, 239)","rgb(158, 202, 225)","rgb(107, 174, 214)","rgb(66, 146, 198)","rgb(33, 113, 181)","rgb(8, 81, 156)","rgb(8, 48, 107)"]},theme:{dark:LH,light:_H},plugin:{"bubble-sets":VB,"edge-bundling":$B,"edge-filter-lens":eF,"grid-line":oF,background:oB,contextmenu:UB,fisheye:rF,fullscreen:iF,history:cF,hull:HF,legend:dH,minimap:fH,snapline:mH,timebar:EH,toolbar:SH,tooltip:NH,watermark:CH},transform:{"arrange-draw-order":class extends IH{beforeDraw(t){const{model:e}=this.context,n=t.add.combos,r=t=>{const n=[];return t.forEach(((t,r)=>{const i=e.getAncestorsData(r,"combo").map((t=>Nh(t))).reverse();n.push([r,t,i.length])})),new Map(n.sort((([,,t],[,,e])=>e-t)).map((([t,e])=>[t,e])))};return t.add.combos=r(n),t.update.combos=r(t.update.combos),t}},"collapse-expand-combo":class extends IH{beforeDraw(t,e){if("visibility"===e.stage)return t;if(!this.context.model.model.hasTreeStructure(Cc))return t;const{model:n}=this.context,{add:r,update:i}=t,o=[...t.update.combos.entries(),...t.add.combos.entries()];for(;o.length;){const[e,a]=o.pop();if(_d(a)){const a=n.getDescendantsData(e),s=a.map(Nh),{internal:l,external:u}=lg(s,(t=>n.getRelatedEdgesData(t)));a.forEach((e=>{const r=Nh(e),i=o.findIndex((([t])=>t===r));-1!==i&&o.splice(i,1);const a=n.getElementType(r);jH(t,"remove",a,e)})),l.forEach((e=>jH(t,"remove","edge",e))),u.forEach((t=>{var e;const n=Nh(t);(null===(e=this.context.element)||void 0===e?void 0:e.getElement(n))?i.edges.set(n,t):r.edges.set(n,t)}))}else{const r=n.getChildrenData(e),i=r.map(Nh),{edges:a}=lg(i,(t=>n.getRelatedEdgesData(t)));[...r,...a].forEach((e=>{var r;const i=Nh(e),a=n.getElementType(i),s=null===(r=this.context.element)||void 0===r?void 0:r.getElement(i);jH(t,s?"update":"add",a,e),"combo"===a&&o.push([i,e])}))}}return t}},"collapse-expand-node":class extends IH{getElement(t){return this.context.element.getElement(t)}handleExpand(t,e){if(FH(e,"add","node",t),_d(t))return;const n=Nh(t);FH(e,"add","node",t);this.context.model.getRelatedEdgesData(n,"out").forEach((t=>{jH(e,"add","edge",t)}));this.context.model.getChildrenData(n).forEach((t=>{this.handleExpand(t,e)}))}beforeDraw(t){const{graph:e,model:n}=this.context;if(!n.model.hasTreeStructure(Ac))return t;const{add:{nodes:r,edges:i},update:{nodes:o}}=t,a=new Map,s=new Map;r.forEach(((t,e)=>{_d(t)&&a.set(e,t)})),i.forEach((t=>{if("node"!==e.getElementType(t.source))return;const n=e.getNodeData(t.source);_d(n)&&a.set(t.source,n)})),o.forEach(((t,e)=>{const n=this.getElement(e);if(!n)return;const r=n.attributes.collapsed;_d(t)?r||a.set(e,t):r&&s.set(e,t)}));const l=new Set;return a.forEach(((e,r)=>{n.getDescendantsData(r).forEach((e=>{const r=Nh(e);if(l.has(r))return;jH(t,"remove","node",e);n.getRelatedEdgesData(r).forEach((e=>{jH(t,"remove","edge",e)})),l.add(r)}))})),s.forEach(((e,r)=>{n.getAncestorsData(r,Ac).some(_d)?jH(t,"remove","node",e):this.handleExpand(e,t)})),t}},"get-edge-actual-ends":class extends IH{beforeDraw(t){const{add:e,update:n}=t,{model:r}=this.context;return[...e.edges.entries(),...n.edges.entries()].forEach((([,t])=>{NU(r,t)})),t}},"map-node-size":OU,"place-radial-labels":TU,"process-parallel-edges":AU,"update-related-edges":class extends IH{beforeDraw(t,e){const{stage:n}=e;if("visibility"===n)return t;const{model:r}=this.context,{update:{nodes:i,edges:o,combos:a}}=t,s=(t,e)=>{r.getRelatedEdgesData(e).forEach((t=>!o.has(Nh(t))&&o.set(Nh(t),t)))};return i.forEach(s),a.forEach(s),t}}},shape:{circle:Gl,ellipse:Hl,group:Ul,html:Yl,image:rf,line:Kl,path:Ql,polygon:tu,polyline:nu,rect:ru,text:ou,label:Zd,badge:Qd}};Object.entries(LU).forEach((([t,e])=>{Object.entries(e).forEach((([e,n])=>{VH(t,e,n)}))}));t.AntVDagreLayout=Sb,t.AutoAdaptLabel=Vh,t.Background=oB,t.Badge=Qd,t.BaseBehavior=Gh,t.BaseCombo=Fp,t.BaseEdge=dg,t.BaseLayout=nv,t.BaseNode=hf,t.BasePlugin=nB,t.BaseShape=qd,t.BaseTransform=IH,t.BrushSelect=Nd,t.BubbleSets=VB,t.CameraSetting=class extends nB{constructor(t,e){super(t,e),this.setOptions=t=>{const e=(t,e)=>{switch(t){case"projectionMode":return"perspective"===e?1:0;case"cameraType":return{orbiting:0,exploring:1,tracking:2}[e];case"aspect":return"number"==typeof e?e:this.getCanvasAspect();default:return e}};Object.entries({cameraType:"setType",near:"setNear",far:"setFar",fov:"setFov",aspect:"setAspect",projectionMode:"setProjectionMode",distance:"setDistance",minDistance:"setMinDistance",maxDistance:"setMaxDistance",roll:"setRoll",elevation:"setElevation",azimuth:"setAzimuth"}).forEach((([n,r])=>{const i=t[n];if(void 0!==i){const t=e(n,i);this.context.canvas.getCamera()[r](t)}}))},this.bindEvents()}update(t){this.setOptions(t),super.update(t)}bindEvents(){this.context.graph.once(t.GraphEvent.BEFORE_DRAW,(()=>this.setOptions(this.options)))}getCanvasAspect(){const[t,e]=this.context.viewport.getCanvasSize();return t/e}},t.Canvas=YH,t.Circle=df,t.CircleCombo=zp,t.CircularLayout=Cb,t.ClickSelect=Ld,t.CollapseExpand=Ug,t.ComboCombinedLayout=uE,t.CompactBoxLayout=Em.compactBox,t.ConcentricLayout=Db,t.Contextmenu=UB,t.CreateEdge=Yg,t.Cubic=fg,t.CubicHorizontal=pg,t.CubicRadial=gg,t.CubicVertical=vg,t.D3ForceLayout=ZE,t.DagreLayout=nj,t.DendrogramLayout=Em.dendrogram,t.Diamond=pf,t.Donut=gf,t.DragCanvas=qg,t.DragElement=Xg,t.DragElementForce=av,t.EdgeBundling=$B,t.EdgeFilterLens=eF,t.Ellipse=yf,t.FishboneLayout=Zj,t.Fisheye=rF,t.FixElementSize=sv,t.FocusElement=lv,t.ForceAtlas2Layout=sj,t.ForceLayout=nx,t.FruchtermanLayout=uj,t.Fullscreen=iF,t.Graph=SU,t.GridLayout=hj,t.GridLine=oF,t.HTML=Lp,t.Hexagon=bf,t.History=cF,t.HoverActivate=uv,t.Hull=HF,t.Icon=uf,t.Image=_p,t.IndentedLayout=Em.indented,t.Label=Zd,t.LassoSelect=cv,t.Legend=dH,t.Line=mg,t.MDSLayout=rE,t.MapNodeSize=OU,t.MindmapLayout=Em.mindmap,t.Minimap=fH,t.OptimizeViewportTransform=hv,t.PlaceRadialLabels=TU,t.Polyline=Tg,t.ProcessParallelEdges=AU,t.Quadratic=Cg,t.RadialLayout=wj,t.RandomLayout=Cj,t.Rect=Ip,t.RectCombo=Gp,t.ScrollCanvas=dv,t.Shortcut=Sd,t.SnakeLayout=eB,t.Snapline=mH,t.Star=jp,t.Timebar=EH,t.Toolbar=SH,t.Tooltip=NH,t.Triangle=Bp,t.Watermark=CH,t.ZoomCanvas=fv,t.effect=function(t,e,n){zH.has(t)||zH.set(t,{});const r=zH.get(t);if(!r[e])return r[e]=n,!0;const i=r[e];return!GH(i,n)&&(r[e]=n,!0)},t.getExtension=Dc,t.getExtensions=function(t){return Rc[t]},t.iconfont={css:"//at.alicdn.com/t/a/font_470089_8hnbbf8n4u8.css",js:"//at.alicdn.com/t/a/font_470089_8hnbbf8n4u8.js"},t.idOf=Nh,t.invokeLayoutMethod=iv,t.isCollapsed=_d,t.omitStyleProps=zd,t.parseSize=Gd,t.positionOf=sd,t.register=VH,t.setVisibility=Bh,t.subStyleProps=Bd,t.treeToGraphData=function(t,e){const{getNodeData:n=(t,e)=>{if(t.depth=e,!t.children)return t;const{children:n}=t,r=Fe(t,["children"]);return Object.assign(Object.assign({},r),{children:n.map((t=>t.id))})},getEdgeData:r=(t,e)=>({source:t.id,target:e.id}),getChildren:i=t=>t.children||[]}=e||{},o=[],a=[];return Ad(t,((t,e)=>{o.push(n(t,e));const s=i(t);for(const e of s)a.push(r(t,e))}),(t=>i(t)),"TB"),{nodes:o,edges:a}},t.version=Lc})); diff --git a/src/lib/graphology.bundle.mjs b/src/lib/graphology.bundle.mjs new file mode 100644 index 0000000..c4c2fbd --- /dev/null +++ b/src/lib/graphology.bundle.mjs @@ -0,0 +1,43 @@ +var ox=Object.create;var zn=Object.defineProperty;var sx=Object.getOwnPropertyDescriptor;var ax=Object.getOwnPropertyNames;var ux=Object.getPrototypeOf,fx=Object.prototype.hasOwnProperty;var hd=r=>{throw TypeError(r)};var hx=(r,e,t)=>e in r?zn(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var De=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),$s=(r,e)=>{for(var t in e)zn(r,t,{get:e[t],enumerable:!0})},cx=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of ax(e))!fx.call(r,n)&&n!==t&&zn(r,n,{get:()=>e[n],enumerable:!(i=sx(e,n))||i.enumerable});return r};var et=(r,e,t)=>(t=r!=null?ox(ux(r)):{},cx(e||!r||!r.__esModule?zn(t,"default",{value:r,enumerable:!0}):t,r));var cd=(r,e,t)=>hx(r,typeof e!="symbol"?e+"":e,t),Us=(r,e,t)=>e.has(r)||hd("Cannot "+t);var At=(r,e,t)=>(Us(r,e,"read from private field"),t?t.call(r):e.get(r)),Ws=(r,e,t)=>e.has(r)?hd("Cannot add the same private member more than once"):e instanceof WeakSet?e.add(r):e.set(r,t),$n=(r,e,t,i)=>(Us(r,e,"write to private field"),i?i.call(r,t):e.set(r,t),t),Bs=(r,e,t)=>(Us(r,e,"access private method"),t);var bd=De((lC,Vs)=>{"use strict";var Li=typeof Reflect=="object"?Reflect:null,ld=Li&&typeof Li.apply=="function"?Li.apply:function(e,t,i){return Function.prototype.apply.call(e,t,i)},Un;Li&&typeof Li.ownKeys=="function"?Un=Li.ownKeys:Object.getOwnPropertySymbols?Un=function(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:Un=function(e){return Object.getOwnPropertyNames(e)};function lx(r){console&&console.warn&&console.warn(r)}var pd=Number.isNaN||function(e){return e!==e};function or(){or.init.call(this)}Vs.exports=or;Vs.exports.once=mx;or.EventEmitter=or;or.prototype._events=void 0;or.prototype._eventsCount=0;or.prototype._maxListeners=void 0;var dd=10;function Wn(r){if(typeof r!="function")throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof r)}Object.defineProperty(or,"defaultMaxListeners",{enumerable:!0,get:function(){return dd},set:function(r){if(typeof r!="number"||r<0||pd(r))throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received '+r+".");dd=r}});or.init=function(){(this._events===void 0||this._events===Object.getPrototypeOf(this)._events)&&(this._events=Object.create(null),this._eventsCount=0),this._maxListeners=this._maxListeners||void 0};or.prototype.setMaxListeners=function(e){if(typeof e!="number"||e<0||pd(e))throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received '+e+".");return this._maxListeners=e,this};function gd(r){return r._maxListeners===void 0?or.defaultMaxListeners:r._maxListeners}or.prototype.getMaxListeners=function(){return gd(this)};or.prototype.emit=function(e){for(var t=[],i=1;i0&&(s=t[0]),s instanceof Error)throw s;var a=new Error("Unhandled error."+(s?" ("+s.message+")":""));throw a.context=s,a}var h=o[e];if(h===void 0)return!1;if(typeof h=="function")ld(h,this,t);else for(var f=h.length,l=wd(h,f),i=0;i0&&s.length>n&&!s.warned){s.warned=!0;var a=new Error("Possible EventEmitter memory leak detected. "+s.length+" "+String(e)+" listeners added. Use emitter.setMaxListeners() to increase limit");a.name="MaxListenersExceededWarning",a.emitter=r,a.type=e,a.count=s.length,lx(a)}return r}or.prototype.addListener=function(e,t){return md(this,e,t,!1)};or.prototype.on=or.prototype.addListener;or.prototype.prependListener=function(e,t){return md(this,e,t,!0)};function dx(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,arguments.length===0?this.listener.call(this.target):this.listener.apply(this.target,arguments)}function yd(r,e,t){var i={fired:!1,wrapFn:void 0,target:r,type:e,listener:t},n=dx.bind(i);return n.listener=t,i.wrapFn=n,n}or.prototype.once=function(e,t){return Wn(t),this.on(e,yd(this,e,t)),this};or.prototype.prependOnceListener=function(e,t){return Wn(t),this.prependListener(e,yd(this,e,t)),this};or.prototype.removeListener=function(e,t){var i,n,o,s,a;if(Wn(t),n=this._events,n===void 0)return this;if(i=n[e],i===void 0)return this;if(i===t||i.listener===t)--this._eventsCount===0?this._events=Object.create(null):(delete n[e],n.removeListener&&this.emit("removeListener",e,i.listener||t));else if(typeof i!="function"){for(o=-1,s=i.length-1;s>=0;s--)if(i[s]===t||i[s].listener===t){a=i[s].listener,o=s;break}if(o<0)return this;o===0?i.shift():px(i,o),i.length===1&&(n[e]=i[0]),n.removeListener!==void 0&&this.emit("removeListener",e,a||t)}return this};or.prototype.off=or.prototype.removeListener;or.prototype.removeAllListeners=function(e){var t,i,n;if(i=this._events,i===void 0)return this;if(i.removeListener===void 0)return arguments.length===0?(this._events=Object.create(null),this._eventsCount=0):i[e]!==void 0&&(--this._eventsCount===0?this._events=Object.create(null):delete i[e]),this;if(arguments.length===0){var o=Object.keys(i),s;for(n=0;n=0;n--)this.removeListener(e,t[n]);return this};function _d(r,e,t){var i=r._events;if(i===void 0)return[];var n=i[e];return n===void 0?[]:typeof n=="function"?t?[n.listener||n]:[n]:t?gx(n):wd(n,n.length)}or.prototype.listeners=function(e){return _d(this,e,!0)};or.prototype.rawListeners=function(e){return _d(this,e,!1)};or.listenerCount=function(r,e){return typeof r.listenerCount=="function"?r.listenerCount(e):vd.call(r,e)};or.prototype.listenerCount=vd;function vd(r){var e=this._events;if(e!==void 0){var t=e[r];if(typeof t=="function")return 1;if(t!==void 0)return t.length}return 0}or.prototype.eventNames=function(){return this._eventsCount>0?Un(this._events):[]};function wd(r,e){for(var t=new Array(e),i=0;i{function ES(r){return!r||typeof r!="object"||typeof r=="function"||Array.isArray(r)||r instanceof Set||r instanceof Map||r instanceof RegExp||r instanceof Date}function jd(r,e){r=r||{};var t={};for(var i in e){var n=r[i],o=e[i];if(!ES(o)){t[i]=jd(n,o);continue}n===void 0?t[i]=o:t[i]=n}return t}Pd.exports=jd});var Or=De((gC,Gd)=>{Gd.exports=function(e){return e!==null&&typeof e=="object"&&typeof e.addUndirectedEdgeWithKey=="function"&&typeof e.dropNode=="function"&&typeof e.multi=="boolean"}});var $d=De((mC,zd)=>{function Nd(r){return function(e,t){return e+Math.floor(r()*(t-e+1))}}var Fd=Nd(Math.random);Fd.createRandom=Nd;zd.exports=Fd});var Vd=De((yC,Bd)=>{var xS=$d().createRandom;function Ud(r){var e=xS(r);return function(t){for(var i=t.length,n=i-1,o=-1;++o{var SS=_t(),IS=Or(),AS=Vd(),RS={attributes:{x:"x",y:"y"},center:0,hierarchyAttributes:[],rng:Math.random,scale:1};function nt(r,e,t,i,n){this.wrappedCircle=n||null,this.children={},this.countChildren=0,this.id=r||null,this.next=null,this.previous=null,this.x=e||null,this.y=t||null,n?this.r=1010101:this.r=i||999}nt.prototype.hasChildren=function(){return this.countChildren>0};nt.prototype.addChild=function(r,e){this.children[r]=e,++this.countChildren};nt.prototype.getChild=function(r){if(!this.children.hasOwnProperty(r)){var e=new nt;this.children[r]=e,++this.countChildren}return this.children[r]};nt.prototype.applyPositionToChildren=function(){if(this.hasChildren()){var r=this;for(var e in r.children){var t=r.children[e];t.x+=r.x,t.y+=r.y,t.applyPositionToChildren()}}};function Qd(r,e,t){for(var i in e.children){var n=e.children[i];n.hasChildren()?Qd(r,n,t):t[n.id]={x:n.x,y:n.y}}}function Jn(r,e){var t=r.r-e.r,i=e.x-r.x,n=e.y-r.y;return t<0||t*t0&&t*t>i*i+n*n}function Js(r,e){for(var t=0;th?(n=(f+h-o)/(2*f),a=Math.sqrt(Math.max(0,h/f-n*n)),t.x=r.x-n*i-a*s,t.y=r.y-n*s+a*i):(n=(f+o-h)/(2*f),a=Math.sqrt(Math.max(0,o/f-n*n)),t.x=e.x+n*i-a*s,t.y=e.y+n*s+a*i)):(t.x=e.x+t.r,t.y=e.y)}function Xd(r,e){var t=r.r+e.r-1e-6,i=e.x-r.x,n=e.y-r.y;return t>0&&t*t>i*i+n*n}function LS(r,e){var t=r.length;if(t===0)return 0;var i,n,o,s,a,h,f,l,g,m;if(i=r[0],i.x=0,i.y=0,t<=1)return i.r;if(n=r[1],i.x=-n.r,n.x=i.r,n.y=0,t<=2)return i.r+n.r;o=r[2],Yd(n,i,o),i=new nt(null,null,null,null,i),n=new nt(null,null,null,null,n),o=new nt(null,null,null,null,o),i.next=o.previous=n,n.next=i.previous=o,o.next=n.previous=i;e:for(h=3;h{var DS=_t(),jS=Or(),PS={dimensions:["x","y"],center:.5,scale:1};function np(r,e,t){if(!jS(e))throw new Error("graphology-layout/random: the given graph is not a valid graphology instance.");t=DS(t,PS);var i=t.dimensions;if(!Array.isArray(i)||i.length!==2)throw new Error("graphology-layout/random: given dimensions are invalid.");var n=t.center,o=t.scale,s=Math.PI*2,a=(n-.5)*o,h=e.order,f=i[0],l=i[1];function g(E,q){return q[f]=o*Math.cos(E*s/h)+a,q[l]=o*Math.sin(E*s/h)+a,q}var m=0;if(!r){var _={};return e.forEachNode(function(E){_[E]=g(m++,{})}),_}e.updateEachNodeAttributes(function(E,q){return g(m++,q),q},{attributes:i})}var op=np.bind(null,!1);op.assign=np.bind(null,!0);sp.exports=op});var cp=De((wC,hp)=>{var GS=_t(),NS=Or(),FS={dimensions:["x","y"],center:.5,rng:Math.random,scale:1};function up(r,e,t){if(!NS(e))throw new Error("graphology-layout/random: the given graph is not a valid graphology instance.");t=GS(t,FS);var i=t.dimensions;if(!Array.isArray(i)||i.length<1)throw new Error("graphology-layout/random: given dimensions are invalid.");var n=i.length,o=t.center,s=t.rng,a=t.scale,h=(o-.5)*a;function f(g){for(var m=0;m{var zS=_t(),$S=Or(),US=Math.PI/180,WS={dimensions:["x","y"],centeredOnZero:!1,degrees:!1};function lp(r,e,t,i){if(!$S(e))throw new Error("graphology-layout/rotation: the given graph is not a valid graphology instance.");i=zS(i,WS),i.degrees&&(t*=US);var n=i.dimensions;if(!Array.isArray(n)||n.length!==2)throw new Error("graphology-layout/random: given dimensions are invalid.");if(e.order===0)return r?void 0:{};var o=n[0],s=n[1],a=0,h=0;if(!i.centeredOnZero){var f=1/0,l=-1/0,g=1/0,m=-1/0;e.forEachNode(function(A,S){var I=S[o],M=S[s];Il&&(l=I),Mm&&(m=M)}),a=(f+l)/2,h=(g+m)/2}var _=Math.cos(t),E=Math.sin(t);function q(A){var S=A[o],I=A[s];return A[o]=a+(S-a)*_-(I-h)*E,A[s]=h+(S-a)*E+(I-h)*_,A}if(!r){var x={};return e.forEachNode(function(A,S){var I={};I[o]=S[o],I[s]=S[s],x[A]=q(I)}),x}e.updateEachNodeAttributes(function(A,S){return q(S),S},{attributes:n})}var dp=lp.bind(null,!1);dp.assign=lp.bind(null,!0);pp.exports=dp});var mp=De(qn=>{qn.circlepack=ip();qn.circular=ap();qn.random=cp();qn.rotation=gp()});var Gi=De(Hn=>{function BS(r){return typeof r!="number"||isNaN(r)?1:r}function VS(r,e){var t={},i=function(s){return typeof s>"u"?e:s};typeof e=="function"&&(i=e);var n=function(s){return i(s[r])},o=function(){return i(void 0)};return typeof r=="string"?(t.fromAttributes=n,t.fromGraph=function(s,a){return n(s.getNodeAttributes(a))},t.fromEntry=function(s,a){return n(a)}):typeof r=="function"?(t.fromAttributes=function(){throw new Error("graphology-utils/getters/createNodeValueGetter: irrelevant usage.")},t.fromGraph=function(s,a){return i(r(a,s.getNodeAttributes(a)))},t.fromEntry=function(s,a){return i(r(s,a))}):(t.fromAttributes=o,t.fromGraph=o,t.fromEntry=o),t}function yp(r,e){var t={},i=function(s){return typeof s>"u"?e:s};typeof e=="function"&&(i=e);var n=function(s){return i(s[r])},o=function(){return i(void 0)};return typeof r=="string"?(t.fromAttributes=n,t.fromGraph=function(s,a){return n(s.getEdgeAttributes(a))},t.fromEntry=function(s,a){return n(a)},t.fromPartialEntry=t.fromEntry,t.fromMinimalEntry=t.fromEntry):typeof r=="function"?(t.fromAttributes=function(){throw new Error("graphology-utils/getters/createEdgeValueGetter: irrelevant usage.")},t.fromGraph=function(s,a){var h=s.extremities(a);return i(r(a,s.getEdgeAttributes(a),h[0],h[1],s.getNodeAttributes(h[0]),s.getNodeAttributes(h[1]),s.isUndirected(a)))},t.fromEntry=function(s,a,h,f,l,g,m){return i(r(s,a,h,f,l,g,m))},t.fromPartialEntry=function(s,a,h,f){return i(r(s,a,h,f))},t.fromMinimalEntry=function(s,a){return i(r(s,a))}):(t.fromAttributes=o,t.fromGraph=o,t.fromEntry=o,t.fromMinimalEntry=o),t}Hn.createNodeValueGetter=VS;Hn.createEdgeValueGetter=yp;Hn.createEdgeWeightGetter=function(r){return yp(r,BS)}});var bp=De((xC,qp)=>{var Dr=0,br=1,Je=2,He=3,Yt=4,Xt=5,rr=6,_p=7,eo=8,vp=9,KS=0,YS=1,XS=2,Ur=0,vt=1,rt=2,Ai=3,Jt=4,xr=5,ot=6,Lt=7,Mt=8,wp=3,Ct=10,QS=3,Qr=9,Hs=10;qp.exports=function(e,t,i){var n,o,s,a,h,f,l,g,m,_,E=t.length,q=i.length,x=e.adjustSizes,A=e.barnesHutTheta*e.barnesHutTheta,S,I,M,D,z,O,N,j=[];for(s=0;sB?(oe-=(Oe-B)/2,me=oe+Oe):(X-=(B-Oe)/2,re=X+B),j[0+Ur]=-1,j[0+vt]=(X+re)/2,j[0+rt]=(oe+me)/2,j[0+Ai]=Math.max(re-X,me-oe),j[0+Jt]=-1,j[0+xr]=-1,j[0+ot]=0,j[0+Lt]=0,j[0+Mt]=0,n=1,s=0;s=0){t[s+Dr]=0)if(O=Math.pow(t[s+Dr]-j[o+Lt],2)+Math.pow(t[s+br]-j[o+Mt],2),_=j[o+Ai],4*_*_/O0?(N=I*t[s+rr]*j[o+ot]/O,t[s+Je]+=M*N,t[s+He]+=D*N):O<0&&(N=-I*t[s+rr]*j[o+ot]/Math.sqrt(O),t[s+Je]+=M*N,t[s+He]+=D*N):O>0&&(N=I*t[s+rr]*j[o+ot]/O,t[s+Je]+=M*N,t[s+He]+=D*N),o=j[o+Jt],o<0)break;continue}else{o=j[o+xr];continue}else{if(f=j[o+Ur],f>=0&&f!==s&&(M=t[s+Dr]-t[f+Dr],D=t[s+br]-t[f+br],O=M*M+D*D,x===!0?O>0?(N=I*t[s+rr]*t[f+rr]/O,t[s+Je]+=M*N,t[s+He]+=D*N):O<0&&(N=-I*t[s+rr]*t[f+rr]/Math.sqrt(O),t[s+Je]+=M*N,t[s+He]+=D*N):O>0&&(N=I*t[s+rr]*t[f+rr]/O,t[s+Je]+=M*N,t[s+He]+=D*N)),o=j[o+Jt],o<0)break;continue}else for(I=e.scalingRatio,a=0;a0?(N=I*t[a+rr]*t[h+rr]/O/O,t[a+Je]+=M*N,t[a+He]+=D*N,t[h+Je]-=M*N,t[h+He]-=D*N):O<0&&(N=100*I*t[a+rr]*t[h+rr],t[a+Je]+=M*N,t[a+He]+=D*N,t[h+Je]-=M*N,t[h+He]-=D*N)):(O=Math.sqrt(M*M+D*D),O>0&&(N=I*t[a+rr]*t[h+rr]/O/O,t[a+Je]+=M*N,t[a+He]+=D*N,t[h+Je]-=M*N,t[h+He]-=D*N));for(m=e.gravity/e.scalingRatio,I=e.scalingRatio,s=0;s0&&(N=I*t[s+rr]*m):O>0&&(N=I*t[s+rr]*m/O),t[s+Je]-=M*N,t[s+He]-=D*N;for(I=1*(e.outboundAttractionDistribution?S:1),l=0;l0&&(N=-I*z*Math.log(1+O)/O/t[a+rr]):O>0&&(N=-I*z*Math.log(1+O)/O):e.outboundAttractionDistribution?O>0&&(N=-I*z/t[a+rr]):O>0&&(N=-I*z)):(O=Math.sqrt(Math.pow(M,2)+Math.pow(D,2)),e.linLogMode?e.outboundAttractionDistribution?O>0&&(N=-I*z*Math.log(1+O)/O/t[a+rr]):O>0&&(N=-I*z*Math.log(1+O)/O):e.outboundAttractionDistribution?(O=1,N=-I*z/t[a+rr]):(O=1,N=-I*z)),O>0&&(t[a+Je]+=M*N,t[a+He]+=D*N,t[h+Je]-=M*N,t[h+He]-=D*N);var pr,Ze,ge,U,Ge,Z;if(x===!0)for(s=0;sHs&&(t[s+Je]=t[s+Je]*Hs/pr,t[s+He]=t[s+He]*Hs/pr),Ze=t[s+rr]*Math.sqrt((t[s+Yt]-t[s+Je])*(t[s+Yt]-t[s+Je])+(t[s+Xt]-t[s+He])*(t[s+Xt]-t[s+He])),ge=Math.sqrt((t[s+Yt]+t[s+Je])*(t[s+Yt]+t[s+Je])+(t[s+Xt]+t[s+He])*(t[s+Xt]+t[s+He]))/2,U=.1*Math.log(1+ge)/(1+Math.sqrt(Ze)),Ge=t[s+Dr]+t[s+Je]*(U/e.slowDown),t[s+Dr]=Ge,Z=t[s+br]+t[s+He]*(U/e.slowDown),t[s+br]=Z);else for(s=0;s{var bn=10,Ep=3;Ht.assign=function(r){r=r||{};var e=Array.prototype.slice.call(arguments).slice(1),t,i,n;for(t=0,n=e.length;t=0)?{message:"the `scalingRatio` setting should be a number >= 0."}:"strongGravityMode"in r&&typeof r.strongGravityMode!="boolean"?{message:"the `strongGravityMode` setting should be a boolean."}:"gravity"in r&&!(typeof r.gravity=="number"&&r.gravity>=0)?{message:"the `gravity` setting should be a number >= 0."}:"slowDown"in r&&!(typeof r.slowDown=="number"||r.slowDown>=0)?{message:"the `slowDown` setting should be a number >= 0."}:"barnesHutOptimize"in r&&typeof r.barnesHutOptimize!="boolean"?{message:"the `barnesHutOptimize` setting should be a boolean."}:"barnesHutTheta"in r&&!(typeof r.barnesHutTheta=="number"&&r.barnesHutTheta>=0)?{message:"the `barnesHutTheta` setting should be a number >= 0."}:null};Ht.graphToByteArrays=function(r,e){var t=r.order,i=r.size,n={},o,s=new Float32Array(t*bn),a=new Float32Array(i*Ep);return o=0,r.forEachNode(function(h,f){n[h]=o,s[o]=f.x,s[o+1]=f.y,s[o+2]=0,s[o+3]=0,s[o+4]=0,s[o+5]=0,s[o+6]=1,s[o+7]=1,s[o+8]=f.size||1,s[o+9]=f.fixed?1:0,o+=bn}),o=0,r.forEachEdge(function(h,f,l,g,m,_,E){var q=n[l],x=n[g],A=e(h,f,l,g,m,_,E);s[q+6]+=A,s[x+6]+=A,a[o]=q,a[o+1]=x,a[o+2]=A,o+=Ep}),{nodes:s,edges:a}};Ht.assignLayoutChanges=function(r,e,t){var i=0;r.updateEachNodeAttributes(function(n,o){return o.x=e[i],o.y=e[i+1],i+=bn,t?t(n,o):o})};Ht.readGraphPositions=function(r,e){var t=0;r.forEachNode(function(i,n){e[t]=n.x,e[t+1]=n.y,t+=bn})};Ht.collectLayoutChanges=function(r,e,t){for(var i=r.nodes(),n={},o=0,s=0,a=e.length;o{xp.exports={linLogMode:!1,outboundAttractionDistribution:!1,adjustSizes:!1,edgeWeightInfluence:1,scalingRatio:1,strongGravityMode:!1,gravity:1,slowDown:1,barnesHutOptimize:!1,barnesHutTheta:.5}});var Ap=De((AC,Ip)=>{var ZS=Or(),JS=Gi().createEdgeWeightGetter,HS=bp(),En=ea(),eI=ra();function Sp(r,e,t){if(!ZS(e))throw new Error("graphology-layout-forceatlas2: the given graph is not a valid graphology instance.");typeof t=="number"&&(t={iterations:t});var i=t.iterations;if(typeof i!="number")throw new Error("graphology-layout-forceatlas2: invalid number of iterations.");if(i<=0)throw new Error("graphology-layout-forceatlas2: you should provide a positive number of iterations.");var n=JS("getEdgeWeight"in t?t.getEdgeWeight:"weight").fromEntry,o=typeof t.outputReducer=="function"?t.outputReducer:null,s=En.assign({},eI,t.settings),a=En.validateSettings(s);if(a)throw new Error("graphology-layout-forceatlas2: "+a.message);var h=En.graphToByteArrays(e,n),f;for(f=0;f2e3,strongGravityMode:!0,gravity:.05,scalingRatio:10,slowDown:1+Math.log(e)}}var ta=Sp.bind(null,!1);ta.assign=Sp.bind(null,!0);ta.inferSettings=rI;Ip.exports=ta});var Cp=De((RC,Rp)=>{Rp.exports=function(){var e,t,i={};(function(){var o=0,s=1,a=2,h=3,f=4,l=5,g=6,m=7,_=8,E=9,q=0,x=1,A=2,S=0,I=1,M=2,D=3,z=4,O=5,N=6,j=7,X=8,re=3,oe=10,me=3,_e=9,Te=10;i.exports=function(Oe,B,pr){var Ze,ge,U,Ge,Z,W,ue,le,de,Ye,Be=B.length,wr=pr.length,er=Oe.adjustSizes,qr=Oe.barnesHutTheta*Oe.barnesHutTheta,Xe,Ae,ze,be,sr,Se,Le,ie=[];for(U=0;USt?(Tr-=(Ot-St)/2,cr=Tr+Ot):(tr-=(St-Ot)/2,ar=tr+St),ie[0+S]=-1,ie[0+I]=(tr+ar)/2,ie[0+M]=(Tr+cr)/2,ie[0+D]=Math.max(ar-tr,cr-Tr),ie[0+z]=-1,ie[0+O]=-1,ie[0+N]=0,ie[0+j]=0,ie[0+X]=0,Ze=1,U=0;U=0){B[U+o]=0)if(Se=Math.pow(B[U+o]-ie[ge+j],2)+Math.pow(B[U+s]-ie[ge+X],2),Ye=ie[ge+D],4*Ye*Ye/Se0?(Le=Ae*B[U+g]*ie[ge+N]/Se,B[U+a]+=ze*Le,B[U+h]+=be*Le):Se<0&&(Le=-Ae*B[U+g]*ie[ge+N]/Math.sqrt(Se),B[U+a]+=ze*Le,B[U+h]+=be*Le):Se>0&&(Le=Ae*B[U+g]*ie[ge+N]/Se,B[U+a]+=ze*Le,B[U+h]+=be*Le),ge=ie[ge+z],ge<0)break;continue}else{ge=ie[ge+O];continue}else{if(W=ie[ge+S],W>=0&&W!==U&&(ze=B[U+o]-B[W+o],be=B[U+s]-B[W+s],Se=ze*ze+be*be,er===!0?Se>0?(Le=Ae*B[U+g]*B[W+g]/Se,B[U+a]+=ze*Le,B[U+h]+=be*Le):Se<0&&(Le=-Ae*B[U+g]*B[W+g]/Math.sqrt(Se),B[U+a]+=ze*Le,B[U+h]+=be*Le):Se>0&&(Le=Ae*B[U+g]*B[W+g]/Se,B[U+a]+=ze*Le,B[U+h]+=be*Le)),ge=ie[ge+z],ge<0)break;continue}else for(Ae=Oe.scalingRatio,Ge=0;Ge0?(Le=Ae*B[Ge+g]*B[Z+g]/Se/Se,B[Ge+a]+=ze*Le,B[Ge+h]+=be*Le,B[Z+a]-=ze*Le,B[Z+h]-=be*Le):Se<0&&(Le=100*Ae*B[Ge+g]*B[Z+g],B[Ge+a]+=ze*Le,B[Ge+h]+=be*Le,B[Z+a]-=ze*Le,B[Z+h]-=be*Le)):(Se=Math.sqrt(ze*ze+be*be),Se>0&&(Le=Ae*B[Ge+g]*B[Z+g]/Se/Se,B[Ge+a]+=ze*Le,B[Ge+h]+=be*Le,B[Z+a]-=ze*Le,B[Z+h]-=be*Le));for(de=Oe.gravity/Oe.scalingRatio,Ae=Oe.scalingRatio,U=0;U0&&(Le=Ae*B[U+g]*de):Se>0&&(Le=Ae*B[U+g]*de/Se),B[U+a]-=ze*Le,B[U+h]-=be*Le;for(Ae=1*(Oe.outboundAttractionDistribution?Xe:1),ue=0;ue0&&(Le=-Ae*sr*Math.log(1+Se)/Se/B[Ge+g]):Se>0&&(Le=-Ae*sr*Math.log(1+Se)/Se):Oe.outboundAttractionDistribution?Se>0&&(Le=-Ae*sr/B[Ge+g]):Se>0&&(Le=-Ae*sr)):(Se=Math.sqrt(Math.pow(ze,2)+Math.pow(be,2)),Oe.linLogMode?Oe.outboundAttractionDistribution?Se>0&&(Le=-Ae*sr*Math.log(1+Se)/Se/B[Ge+g]):Se>0&&(Le=-Ae*sr*Math.log(1+Se)/Se):Oe.outboundAttractionDistribution?(Se=1,Le=-Ae*sr/B[Ge+g]):(Se=1,Le=-Ae*sr)),Se>0&&(B[Ge+a]+=ze*Le,B[Ge+h]+=be*Le,B[Z+a]-=ze*Le,B[Z+h]-=be*Le);var K,v,b,k,G,P;if(er===!0)for(U=0;UTe&&(B[U+a]=B[U+a]*Te/K,B[U+h]=B[U+h]*Te/K),v=B[U+g]*Math.sqrt((B[U+f]-B[U+a])*(B[U+f]-B[U+a])+(B[U+l]-B[U+h])*(B[U+l]-B[U+h])),b=Math.sqrt((B[U+f]+B[U+a])*(B[U+f]+B[U+a])+(B[U+l]+B[U+h])*(B[U+l]+B[U+h]))/2,k=.1*Math.log(1+b)/(1+Math.sqrt(v)),G=B[U+o]+B[U+a]*(k/Oe.slowDown),B[U+o]=G,P=B[U+s]+B[U+h]*(k/Oe.slowDown),B[U+s]=P);else for(U=0;U{var tI=Cp(),iI=Or(),nI=Gi().createEdgeWeightGetter,Ni=ea(),oI=ra();function ei(r,e){if(e=e||{},!iI(r))throw new Error("graphology-layout-forceatlas2/worker: the given graph is not a valid graphology instance.");var t=nI("getEdgeWeight"in e?e.getEdgeWeight:"weight").fromEntry,i=Ni.assign({},oI,e.settings),n=Ni.validateSettings(i);if(n)throw new Error("graphology-layout-forceatlas2/worker: "+n.message);this.worker=null,this.graph=r,this.settings=i,this.getEdgeWeight=t,this.matrices=null,this.running=!1,this.killed=!1,this.outputReducer=typeof e.outputReducer=="function"?e.outputReducer:null,this.handleMessage=this.handleMessage.bind(this);var o=void 0,s=this;this.handleGraphUpdate=function(){s.worker&&s.worker.terminate(),o&&clearTimeout(o),o=setTimeout(function(){o=void 0,s.spawnWorker()},0)},r.on("nodeAdded",this.handleGraphUpdate),r.on("edgeAdded",this.handleGraphUpdate),r.on("nodeDropped",this.handleGraphUpdate),r.on("edgeDropped",this.handleGraphUpdate),this.spawnWorker()}ei.prototype.isRunning=function(){return this.running};ei.prototype.spawnWorker=function(){this.worker&&this.worker.terminate(),this.worker=Ni.createWorker(tI),this.worker.addEventListener("message",this.handleMessage),this.running&&(this.running=!1,this.start())};ei.prototype.handleMessage=function(r){if(this.running){var e=new Float32Array(r.data.nodes);Ni.assignLayoutChanges(this.graph,e,this.outputReducer),this.outputReducer&&Ni.readGraphPositions(this.graph,e),this.matrices.nodes=e,this.askForIterations()}};ei.prototype.askForIterations=function(r){var e=this.matrices,t={settings:this.settings,nodes:e.nodes.buffer},i=[e.nodes.buffer];return r&&(t.edges=e.edges.buffer,i.push(e.edges.buffer)),this.worker.postMessage(t,i),this};ei.prototype.start=function(){if(this.killed)throw new Error("graphology-layout-forceatlas2/worker.start: layout was killed.");return this.running?this:(this.matrices=Ni.graphToByteArrays(this.graph,this.getEdgeWeight),this.running=!0,this.askForIterations(!0),this)};ei.prototype.stop=function(){return this.running=!1,this};ei.prototype.kill=function(){if(this.killed)return this;this.running=!1,this.killed=!0,this.matrices=null,this.worker.terminate(),this.graph.removeListener("nodeAdded",this.handleGraphUpdate),this.graph.removeListener("edgeAdded",this.handleGraphUpdate),this.graph.removeListener("nodeDropped",this.handleGraphUpdate),this.graph.removeListener("edgeDropped",this.handleGraphUpdate)};Tp.exports=ei});var Mp=De((TC,Lp)=>{var xn=0,Sn=1,ro=2,In=3;function sI(r,e){return r+"\xA7"+e}function kp(){return .01*(.5-Math.random())}Lp.exports=function(e,t){var i=e.margin,n=e.ratio,o=e.expansion,s=e.gridSize,a=e.speed,h,f,l,g,m,_,E=!0,q=t.length,x=q/In|0,A=new Float32Array(x),S=new Float32Array(x),I=1/0,M=1/0,D=-1/0,z=-1/0;for(h=0;h1&&W.has(Xe))&&(oe>1&&W.add(Xe),Ye=t[le+xn],wr=t[le+Sn],qr=t[le+ro],Ae=Ye-de,ze=wr-Be,be=Math.sqrt(Ae*Ae+ze*ze),sr=be0?(A[le]+=Ae/be*(1+er),S[le]+=ze/be*(1+er)):(A[le]+=O*kp(),S[le]+=N*kp())));for(h=0,f=0;h{var to=3;Fi.validateSettings=function(r){return"gridSize"in r&&typeof r.gridSize!="number"||r.gridSize<=0?{message:"the `gridSize` setting should be a positive number."}:"margin"in r&&typeof r.margin!="number"||r.margin<0?{message:"the `margin` setting should be 0 or a positive number."}:"expansion"in r&&typeof r.expansion!="number"||r.expansion<=0?{message:"the `expansion` setting should be a positive number."}:"ratio"in r&&typeof r.ratio!="number"||r.ratio<=0?{message:"the `ratio` setting should be a positive number."}:"speed"in r&&typeof r.speed!="number"||r.speed<=0?{message:"the `speed` setting should be a positive number."}:null};Fi.graphToByteArray=function(r,e){var t=r.order,i=new Float32Array(t*to),n=0;return r.forEachNode(function(o,s){typeof e=="function"&&(s=e(o,s)),i[n]=s.x,i[n+1]=s.y,i[n+2]=s.size||1,n+=to}),i};Fi.assignLayoutChanges=function(r,e,t){var i=0;r.forEachNode(function(n){var o={x:e[i],y:e[i+1]};typeof t=="function"&&(o=t(n,o)),r.mergeNodeAttributes(n,o),i+=to})};Fi.collectLayoutChanges=function(r,e,t){var i={},n=0;return r.forEachNode(function(o){var s={x:e[n],y:e[n+1]};typeof t=="function"&&(s=t(o,s)),i[o]=s,n+=to}),i};Fi.createWorker=function(e){var t=window.URL||window.webkitURL,i=e.toString(),n=t.createObjectURL(new Blob(["("+i+").call(this);"],{type:"text/javascript"})),o=new Worker(n);return t.revokeObjectURL(n),o}});var Pp=De((kC,jp)=>{jp.exports={gridSize:20,margin:5,expansion:1.1,ratio:1,speed:3}});var zp=De((LC,Fp)=>{var aI=Or(),uI=Mp(),io=Dp(),fI=Pp(),hI=500;function Gp(r,e,t){if(!aI(e))throw new Error("graphology-layout-noverlap: the given graph is not a valid graphology instance.");typeof t=="number"?t={maxIterations:t}:t=t||{};var i=t.maxIterations||hI;if(typeof i!="number"||i<=0)throw new Error("graphology-layout-force: you should provide a positive number of maximum iterations.");var n=Object.assign({},fI,t.settings),o=io.validateSettings(n);if(o)throw new Error("graphology-layout-noverlap: "+o.message);var s=io.graphToByteArray(e,t.inputReducer),a=!1,h;for(h=0;h{(function(r,e){typeof Vl=="object"&&typeof Kl<"u"?Kl.exports=e():typeof define=="function"&&define.amd?define(e):(r=typeof globalThis<"u"?globalThis:r||self,r.polygonClipping=e())})(Vl,(function(){"use strict";function r(K,v){var b={label:0,sent:function(){if(P[0]&1)throw P[1];return P[1]},trys:[],ops:[]},k,G,P,te;return te={next:J(0),throw:J(1),return:J(2)},typeof Symbol=="function"&&(te[Symbol.iterator]=function(){return this}),te;function J(ne){return function(Ee){return ae([ne,Ee])}}function ae(ne){if(k)throw new TypeError("Generator is already executing.");for(;b;)try{if(k=1,G&&(P=ne[0]&2?G.return:ne[0]?G.throw||((P=G.return)&&P.call(G),0):G.next)&&!(P=P.call(G,ne[1])).done)return P;switch(G=0,P&&(ne=[ne[0]&2,P.value]),ne[0]){case 0:case 1:P=ne;break;case 4:return b.label++,{value:ne[1],done:!1};case 5:b.label++,G=ne[1],ne=[0];continue;case 7:ne=b.ops.pop(),b.trys.pop();continue;default:if(P=b.trys,!(P=P.length>0&&P[P.length-1])&&(ne[0]===6||ne[0]===2)){b=0;continue}if(ne[0]===3&&(!P||ne[1]>P[0]&&ne[1]v?1:K0){if(v.right===null)break;if(b(K,v.right.key)>0){var J=v.right;if(v.right=J.left,J.left=v,v=J,v.right===null)break}G.right=v,G=v,v=v.right}else break}return G.right=v.left,P.left=v.right,v.left=k.right,v.right=k.left,v}function n(K,v,b,k){var G=new e(K,v);if(b===null)return G.left=G.right=null,G;b=i(K,b,k);var P=k(K,b.key);return P<0?(G.left=b.left,G.right=b,b.left=null):P>=0&&(G.right=b.right,G.left=b,b.right=null),G}function o(K,v,b){var k=null,G=null;if(v){v=i(K,v,b);var P=b(v.key,K);P===0?(k=v.left,G=v.right):P<0?(G=v.right,v.right=null,k=v):(k=v.left,v.left=null,G=v)}return{left:k,right:G}}function s(K,v,b){return v===null?K:(K===null||(v=i(K.key,v,b),v.left=K),v)}function a(K,v,b,k,G){if(K){k(""+v+(b?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ")+G(K)+` +`);var P=v+(b?" ":"\u2502 ");K.left&&a(K.left,P,!1,k,G),K.right&&a(K.right,P,!0,k,G)}}var h=(function(){function K(v){v===void 0&&(v=t),this._root=null,this._size=0,this._comparator=v}return K.prototype.insert=function(v,b){return this._size++,this._root=n(v,b,this._root,this._comparator)},K.prototype.add=function(v,b){var k=new e(v,b);this._root===null&&(k.left=k.right=null,this._size++,this._root=k);var G=this._comparator,P=i(v,this._root,G),te=G(v,P.key);return te===0?this._root=P:(te<0?(k.left=P.left,k.right=P,P.left=null):te>0&&(k.right=P.right,k.left=P,P.right=null),this._size++,this._root=k),this._root},K.prototype.remove=function(v){this._root=this._remove(v,this._root,this._comparator)},K.prototype._remove=function(v,b,k){var G;if(b===null)return null;b=i(v,b,k);var P=k(v,b.key);return P===0?(b.left===null?G=b.right:(G=i(v,b.left,k),G.right=b.right),this._size--,G):b},K.prototype.pop=function(){var v=this._root;if(v){for(;v.left;)v=v.left;return this._root=i(v.key,this._root,this._comparator),this._root=this._remove(v.key,this._root,this._comparator),{key:v.key,data:v.data}}return null},K.prototype.findStatic=function(v){for(var b=this._root,k=this._comparator;b;){var G=k(v,b.key);if(G===0)return b;G<0?b=b.left:b=b.right}return null},K.prototype.find=function(v){return this._root&&(this._root=i(v,this._root,this._comparator),this._comparator(v,this._root.key)!==0)?null:this._root},K.prototype.contains=function(v){for(var b=this._root,k=this._comparator;b;){var G=k(v,b.key);if(G===0)return!0;G<0?b=b.left:b=b.right}return!1},K.prototype.forEach=function(v,b){for(var k=this._root,G=[],P=!1;!P;)k!==null?(G.push(k),k=k.left):G.length!==0?(k=G.pop(),v.call(b,k),k=k.right):P=!0;return this},K.prototype.range=function(v,b,k,G){for(var P=[],te=this._comparator,J=this._root,ae;P.length!==0||J;)if(J)P.push(J),J=J.left;else{if(J=P.pop(),ae=te(J.key,b),ae>0)break;if(te(J.key,v)>=0&&k.call(G,J))return this;J=J.right}return this},K.prototype.keys=function(){var v=[];return this.forEach(function(b){var k=b.key;return v.push(k)}),v},K.prototype.values=function(){var v=[];return this.forEach(function(b){var k=b.data;return v.push(k)}),v},K.prototype.min=function(){return this._root?this.minNode(this._root).key:null},K.prototype.max=function(){return this._root?this.maxNode(this._root).key:null},K.prototype.minNode=function(v){if(v===void 0&&(v=this._root),v)for(;v.left;)v=v.left;return v},K.prototype.maxNode=function(v){if(v===void 0&&(v=this._root),v)for(;v.right;)v=v.right;return v},K.prototype.at=function(v){for(var b=this._root,k=!1,G=0,P=[];!k;)if(b)P.push(b),b=b.left;else if(P.length>0){if(b=P.pop(),G===v)return b;G++,b=b.right}else k=!0;return null},K.prototype.next=function(v){var b=this._root,k=null;if(v.right){for(k=v.right;k.left;)k=k.left;return k}for(var G=this._comparator;b;){var P=G(v.key,b.key);if(P===0)break;P<0?(k=b,b=b.left):b=b.right}return k},K.prototype.prev=function(v){var b=this._root,k=null;if(v.left!==null){for(k=v.left;k.right;)k=k.right;return k}for(var G=this._comparator;b;){var P=G(v.key,b.key);if(P===0)break;P<0?b=b.left:(k=b,b=b.right)}return k},K.prototype.clear=function(){return this._root=null,this._size=0,this},K.prototype.toList=function(){return g(this._root)},K.prototype.load=function(v,b,k){b===void 0&&(b=[]),k===void 0&&(k=!1);var G=v.length,P=this._comparator;if(k&&E(v,b,0,G-1,P),this._root===null)this._root=f(v,b,0,G),this._size=G;else{var te=_(this.toList(),l(v,b),P);G=this._size+G,this._root=m({head:te},0,G)}return this},K.prototype.isEmpty=function(){return this._root===null},Object.defineProperty(K.prototype,"size",{get:function(){return this._size},enumerable:!0,configurable:!0}),Object.defineProperty(K.prototype,"root",{get:function(){return this._root},enumerable:!0,configurable:!0}),K.prototype.toString=function(v){v===void 0&&(v=function(k){return String(k.key)});var b=[];return a(this._root,"",!0,function(k){return b.push(k)},v),b.join("")},K.prototype.update=function(v,b,k){var G=this._comparator,P=o(v,this._root,G),te=P.left,J=P.right;G(v,b)<0?J=n(b,k,J,G):te=n(b,k,te,G),this._root=s(te,J,G)},K.prototype.split=function(v){return o(v,this._root,this._comparator)},K.prototype[Symbol.iterator]=function(){var v,b,k;return r(this,function(G){switch(G.label){case 0:v=this._root,b=[],k=!1,G.label=1;case 1:return k?[3,6]:v===null?[3,2]:(b.push(v),v=v.left,[3,5]);case 2:return b.length===0?[3,4]:(v=b.pop(),[4,v]);case 3:return G.sent(),v=v.right,[3,5];case 4:k=!0,G.label=5;case 5:return[3,1];case 6:return[2]}})},K})();function f(K,v,b,k){var G=k-b;if(G>0){var P=b+Math.floor(G/2),te=K[P],J=v[P],ae=new e(te,J);return ae.left=f(K,v,b,P),ae.right=f(K,v,P+1,k),ae}return null}function l(K,v){for(var b=new e(null,null),k=b,G=0;G0?(v=P=P.next=b.pop(),v=v.right):k=!0;return P.next=null,G.next}function m(K,v,b){var k=b-v;if(k>0){var G=v+Math.floor(k/2),P=m(K,v,G),te=K.head;return te.left=P,K.head=K.head.next,te.right=m(K,G+1,b),te}return null}function _(K,v,b){for(var k=new e(null,null),G=k,P=K,te=v;P!==null&&te!==null;)b(P.key,te.key)<0?(G.next=P,P=P.next):(G.next=te,te=te.next),G=G.next;return P!==null?G.next=P:te!==null&&(G.next=te),k.next}function E(K,v,b,k,G){if(!(b>=k)){for(var P=K[b+k>>1],te=b-1,J=k+1;;){do te++;while(G(K[te],P)<0);do J--;while(G(K[J],P)>0);if(te>=J)break;var ae=K[te];K[te]=K[J],K[J]=ae,ae=v[te],v[te]=v[J],v[J]=ae}E(K,v,b,J,G),E(K,v,J+1,k,G)}}let q=(K,v)=>K.ll.x<=v.x&&v.x<=K.ur.x&&K.ll.y<=v.y&&v.y<=K.ur.y,x=(K,v)=>{if(v.ur.x{if(-Ane==Ee>-ne?(P=ne,ne=v[++Q]):(P=Ee,Ee=k[++fe]);let ve=0;if(Qne==Ee>-ne?(te=ne+P,J=P-(te-ne),ne=v[++Q]):(te=Ee+P,J=P-(te-Ee),Ee=k[++fe]),P=te,J!==0&&(G[ve++]=J);Qne==Ee>-ne?(te=P+ne,ae=te-P,J=P-(te-ae)+(ne-ae),ne=v[++Q]):(te=P+Ee,ae=te-P,J=P-(te-ae)+(Ee-ae),Ee=k[++fe]),P=te,J!==0&&(G[ve++]=J);for(;Q=H||-ce>=H||(Q=K-L,J=K-(L+Q)+(Q-G),Q=b-V,ne=b-(V+Q)+(Q-G),Q=v-F,ae=v-(F+Q)+(Q-P),Q=k-ee,Ee=k-(ee+Q)+(Q-P),J===0&&ae===0&&ne===0&&Ee===0)||(H=Te*te+j*Math.abs(ce),ce+=L*Ee+ee*J-(F*ne+V*ae),ce>=H||-ce>=H))return ce;d=J*ee,fe=N*J,ve=fe-(fe-J),Ce=J-ve,fe=N*ee,Me=fe-(fe-ee),w=ee-Me,y=Ce*w-(d-ve*Me-Ce*Me-ve*w),R=ae*V,fe=N*ae,ve=fe-(fe-ae),Ce=ae-ve,fe=N*V,Me=fe-(fe-V),w=V-Me,C=Ce*w-(R-ve*Me-Ce*Me-ve*w),p=y-C,Q=y-p,Ze[0]=y-(p+Q)+(Q-C),c=d+p,Q=c-d,u=d-(c-Q)+(p-Q),p=u-R,Q=u-p,Ze[1]=u-(p+Q)+(Q-R),T=c+p,Q=T-c,Ze[2]=c-(T-Q)+(p-Q),Ze[3]=T;let se=X(4,Ne,4,Ze,Oe);d=L*Ee,fe=N*L,ve=fe-(fe-L),Ce=L-ve,fe=N*Ee,Me=fe-(fe-Ee),w=Ee-Me,y=Ce*w-(d-ve*Me-Ce*Me-ve*w),R=F*ne,fe=N*F,ve=fe-(fe-F),Ce=F-ve,fe=N*ne,Me=fe-(fe-ne),w=ne-Me,C=Ce*w-(R-ve*Me-Ce*Me-ve*w),p=y-C,Q=y-p,Ze[0]=y-(p+Q)+(Q-C),c=d+p,Q=c-d,u=d-(c-Q)+(p-Q),p=u-R,Q=u-p,Ze[1]=u-(p+Q)+(Q-R),T=c+p,Q=T-c,Ze[2]=c-(T-Q)+(p-Q),Ze[3]=T;let qe=X(se,Oe,4,Ze,B);d=J*Ee,fe=N*J,ve=fe-(fe-J),Ce=J-ve,fe=N*Ee,Me=fe-(fe-Ee),w=Ee-Me,y=Ce*w-(d-ve*Me-Ce*Me-ve*w),R=ae*ne,fe=N*ae,ve=fe-(fe-ae),Ce=ae-ve,fe=N*ne,Me=fe-(fe-ne),w=ne-Me,C=Ce*w-(R-ve*Me-Ce*Me-ve*w),p=y-C,Q=y-p,Ze[0]=y-(p+Q)+(Q-C),c=d+p,Q=c-d,u=d-(c-Q)+(p-Q),p=u-R,Q=u-p,Ze[1]=u-(p+Q)+(Q-R),T=c+p,Q=T-c,Ze[2]=c-(T-Q)+(p-Q),Ze[3]=T;let $=X(qe,B,4,Ze,pr);return pr[$-1]}function U(K,v,b,k,G,P){let te=(v-P)*(b-G),J=(K-G)*(k-P),ae=te-J,ne=Math.abs(te+J);return Math.abs(ae)>=me*ne?ae:-ge(K,v,b,k,G,P,ne)}let Ge=(K,v)=>K.x*v.y-K.y*v.x,Z=(K,v)=>K.x*v.x+K.y*v.y,W=(K,v,b)=>{let k=U(K.x,K.y,v.x,v.y,b.x,b.y);return k>0?-1:k<0?1:0},ue=K=>Math.sqrt(Z(K,K)),le=(K,v,b)=>{let k={x:v.x-K.x,y:v.y-K.y},G={x:b.x-K.x,y:b.y-K.y};return Ge(G,k)/ue(G)/ue(k)},de=(K,v,b)=>{let k={x:v.x-K.x,y:v.y-K.y},G={x:b.x-K.x,y:b.y-K.y};return Z(G,k)/ue(G)/ue(k)},Ye=(K,v,b)=>v.y===0?null:{x:K.x+v.x/v.y*(b-K.y),y:b},Be=(K,v,b)=>v.x===0?null:{x:b,y:K.y+v.y/v.x*(b-K.x)},wr=(K,v,b,k)=>{if(v.x===0)return Be(b,k,K.x);if(k.x===0)return Be(K,v,b.x);if(v.y===0)return Ye(b,k,K.y);if(k.y===0)return Ye(K,v,b.y);let G=Ge(v,k);if(G==0)return null;let P={x:b.x-K.x,y:b.y-K.y},te=Ge(P,v)/G,J=Ge(P,k)/G,ae=K.x+J*v.x,ne=b.x+te*k.x,Ee=K.y+J*v.y,Q=b.y+te*k.y,fe=(ae+ne)/2,ve=(Ee+Q)/2;return{x:fe,y:ve}};class er{static compare(v,b){let k=er.comparePoints(v.point,b.point);return k!==0?k:(v.point!==b.point&&v.link(b),v.isLeft!==b.isLeft?v.isLeft?1:-1:Xe.compare(v.segment,b.segment))}static comparePoints(v,b){return v.xb.x?1:v.yb.y?1:0}constructor(v,b){v.events===void 0?v.events=[this]:v.events.push(this),this.point=v,this.isLeft=b}link(v){if(v.point===this.point)throw new Error("Tried to link already linked events");let b=v.point.events;for(let k=0,G=b.length;k{let P=G.otherSE;b.set(G,{sine:le(this.point,v.point,P.point),cosine:de(this.point,v.point,P.point)})};return(G,P)=>{b.has(G)||k(G),b.has(P)||k(P);let{sine:te,cosine:J}=b.get(G),{sine:ae,cosine:ne}=b.get(P);return te>=0&&ae>=0?Jne?-1:0:te<0&&ae<0?Jne?1:0:aete?1:0}}}let qr=0;class Xe{static compare(v,b){let k=v.leftSE.point.x,G=b.leftSE.point.x,P=v.rightSE.point.x,te=b.rightSE.point.x;if(teJ&&ae>ne)return-1;let Q=v.comparePoint(b.leftSE.point);if(Q<0)return 1;if(Q>0)return-1;let fe=b.comparePoint(v.rightSE.point);return fe!==0?fe:-1}if(k>G){if(Jae&&J>Ee)return 1;let Q=b.comparePoint(v.leftSE.point);if(Q!==0)return Q;let fe=v.comparePoint(b.rightSE.point);return fe<0?1:fe>0?-1:1}if(Jae)return 1;if(Pte){let Q=v.comparePoint(b.rightSE.point);if(Q<0)return 1;if(Q>0)return-1}if(P!==te){let Q=ne-J,fe=P-k,ve=Ee-ae,Ce=te-G;if(Q>fe&&veCe)return-1}return P>te?1:PEe?1:v.idb.id?1:0}constructor(v,b,k,G){this.id=++qr,this.leftSE=v,v.segment=this,v.otherSE=b,this.rightSE=b,b.segment=this,b.otherSE=v,this.rings=k,this.windings=G}static fromRing(v,b,k){let G,P,te,J=er.comparePoints(v,b);if(J<0)G=v,P=b,te=1;else if(J>0)G=b,P=v,te=-1;else throw new Error(`Tried to create degenerate segment at [${v.x}, ${v.y}]`);let ae=new er(G,!0),ne=new er(P,!1);return new Xe(ae,ne,[k],[te])}replaceRightSE(v){this.rightSE=v,this.rightSE.segment=this,this.rightSE.otherSE=this.leftSE,this.leftSE.otherSE=this.rightSE}bbox(){let v=this.leftSE.point.y,b=this.rightSE.point.y;return{ll:{x:this.leftSE.point.x,y:vb?v:b}}}vector(){return{x:this.rightSE.point.x-this.leftSE.point.x,y:this.rightSE.point.y-this.leftSE.point.y}}isAnEndpoint(v){return v.x===this.leftSE.point.x&&v.y===this.leftSE.point.y||v.x===this.rightSE.point.x&&v.y===this.rightSE.point.y}comparePoint(v){if(this.isAnEndpoint(v))return 0;let b=this.leftSE.point,k=this.rightSE.point,G=this.vector();if(b.x===k.x)return v.x===b.x?0:v.x0&&J.swapEvents(),er.comparePoints(this.leftSE.point,this.rightSE.point)>0&&this.swapEvents(),k&&(G.checkForConsuming(),P.checkForConsuming()),b}swapEvents(){let v=this.rightSE;this.rightSE=this.leftSE,this.leftSE=v,this.leftSE.isLeft=!0,this.rightSE.isLeft=!1;for(let b=0,k=this.windings.length;b0){let P=b;b=k,k=P}if(b.prev===k){let P=b;b=k,k=P}for(let P=0,te=k.rings.length;PG.length===1&&G[0].isSubject;this._isInResult=k(v)!==k(b);break}default:throw new Error(`Unrecognized operation type found ${cr.type}`)}return this._isInResult}}class Ae{constructor(v,b,k){if(!Array.isArray(v)||v.length===0)throw new Error("Input geometry is not a valid Polygon or MultiPolygon");if(this.poly=b,this.isExterior=k,this.segments=[],typeof v[0][0]!="number"||typeof v[0][1]!="number")throw new Error("Input geometry is not a valid Polygon or MultiPolygon");let G=z.round(v[0][0],v[0][1]);this.bbox={ll:{x:G.x,y:G.y},ur:{x:G.x,y:G.y}};let P=G;for(let te=1,J=v.length;tethis.bbox.ur.x&&(this.bbox.ur.x=ae.x),ae.y>this.bbox.ur.y&&(this.bbox.ur.y=ae.y),P=ae)}(G.x!==P.x||G.y!==P.y)&&this.segments.push(Xe.fromRing(P,G,this))}getSweepEvents(){let v=[];for(let b=0,k=this.segments.length;bthis.bbox.ur.x&&(this.bbox.ur.x=P.bbox.ur.x),P.bbox.ur.y>this.bbox.ur.y&&(this.bbox.ur.y=P.bbox.ur.y),this.interiorRings.push(P)}this.multiPoly=b}getSweepEvents(){let v=this.exteriorRing.getSweepEvents();for(let b=0,k=this.interiorRings.length;bthis.bbox.ur.x&&(this.bbox.ur.x=P.bbox.ur.x),P.bbox.ur.y>this.bbox.ur.y&&(this.bbox.ur.y=P.bbox.ur.y),this.polys.push(P)}this.isSubject=b}getSweepEvents(){let v=[];for(let b=0,k=this.polys.length;b0&&(v=te)}let b=v.segment.prevInResult(),k=b?b.prevInResult():null;for(;;){if(!b)return null;if(!k)return b.ringOut;if(k.ringOut!==b.ringOut)return k.ringOut.enclosingRing()!==b.ringOut?b.ringOut:b.ringOut.enclosingRing();b=k.prevInResult(),k=b?b.prevInResult():null}}}class Se{constructor(v){this.exteriorRing=v,v.poly=this,this.interiorRings=[]}addInterior(v){this.interiorRings.push(v),v.poly=this}getGeom(){let v=[this.exteriorRing.getGeom()];if(v[0]===null)return null;for(let b=0,k=this.interiorRings.length;b1&&arguments[1]!==void 0?arguments[1]:Xe.compare;this.queue=v,this.tree=new h(b),this.segments=[]}process(v){let b=v.segment,k=[];if(v.consumedBy)return v.isLeft?this.queue.remove(v.otherSE):this.tree.remove(b),k;let G=v.isLeft?this.tree.add(b):this.tree.find(b);if(!G)throw new Error(`Unable to find segment #${b.id} [${b.leftSE.point.x}, ${b.leftSE.point.y}] -> [${b.rightSE.point.x}, ${b.rightSE.point.y}] in SweepLine tree.`);let P=G,te=G,J,ae;for(;J===void 0;)P=this.tree.prev(P),P===null?J=null:P.key.consumedBy===void 0&&(J=P.key);for(;ae===void 0;)te=this.tree.next(te),te===null?ae=null:te.key.consumedBy===void 0&&(ae=te.key);if(v.isLeft){let ne=null;if(J){let Q=J.getIntersection(b);if(Q!==null&&(b.isAnEndpoint(Q)||(ne=Q),!J.isAnEndpoint(Q))){let fe=this._splitSafely(J,Q);for(let ve=0,Ce=fe.length;ve0?(this.tree.remove(b),k.push(v)):(this.segments.push(b),b.prev=J)}else{if(J&&ae){let ne=J.getIntersection(ae);if(ne!==null){if(!J.isAnEndpoint(ne)){let Ee=this._splitSafely(J,ne);for(let Q=0,fe=Ee.length;Qtr)throw new Error("Infinite loop when putting segment endpoints in a priority queue (queue size too big).")}let te=new ie(P),J=P.size,ae=P.pop();for(;ae;){let Q=ae.key;if(P.size===J){let ve=Q.segment;throw new Error(`Unable to pop() ${Q.isLeft?"left":"right"} SweepEvent [${Q.point.x}, ${Q.point.y}] from segment #${ve.id} [${ve.leftSE.point.x}, ${ve.leftSE.point.y}] -> [${ve.rightSE.point.x}, ${ve.rightSE.point.y}] from queue.`)}if(P.size>tr)throw new Error("Infinite loop when passing sweep line over endpoints (queue size too big).");if(te.segments.length>ar)throw new Error("Infinite loop when passing sweep line over endpoints (too many sweep line segments).");let fe=te.process(Q);for(let ve=0,Ce=fe.length;ve1?v-1:0),k=1;k1?v-1:0),k=1;k1?v-1:0),k=1;k1?v-1:0),k=1;k{var _A=Or();function pn(r,e,t,i){var n=e+"Centrality";if(!_A(t))throw new Error("graphology-centrality/"+n+": the given graph is not a valid graphology instance.");if(e!=="degree"&&t.type==="undirected")throw new Error("graphology-centrality/"+n+": cannot compute "+e+" centrality on an undirected graph.");i=i||{};var o=i.nodeCentralityAttribute||n,s=t.order-1,a=t[e].bind(t);if(r){t.updateEachNodeAttributes(function(f,l){return l[o]=a(f)/s,l},{attributes:[o]});return}var h={};return t.forEachNode(function(f){h[f]=a(f)/s}),h}var m1=pn.bind(null,!1,"degree"),y1=pn.bind(null,!1,"inDegree"),_1=pn.bind(null,!1,"outDegree");m1.assign=pn.bind(null,!0,"degree");y1.assign=pn.bind(null,!0,"inDegree");_1.assign=pn.bind(null,!0,"outDegree");Os.degreeCentrality=m1;Os.inDegreeCentrality=y1;Os.outDegreeCentrality=_1});var w1=De(Yl=>{Yl.ARRAY_BUFFER_SUPPORT=typeof ArrayBuffer<"u";Yl.SYMBOL_SUPPORT=typeof Symbol<"u"});var ks=De((YV,b1)=>{var q1=w1(),vA=q1.ARRAY_BUFFER_SUPPORT,wA=q1.SYMBOL_SUPPORT;b1.exports=function(e,t){var i,n,o,s,a;if(!e)throw new Error("obliterator/forEach: invalid iterable.");if(typeof t!="function")throw new Error("obliterator/forEach: expecting a callback.");if(Array.isArray(e)||vA&&ArrayBuffer.isView(e)||typeof e=="string"||e.toString()==="[object Arguments]"){for(o=0,s=e.length;o{var qA=Math.pow(2,8)-1,bA=Math.pow(2,16)-1,EA=Math.pow(2,32)-1,xA=Math.pow(2,7)-1,SA=Math.pow(2,15)-1,IA=Math.pow(2,31)-1;$t.getPointerArray=function(r){var e=r-1;if(e<=qA)return Uint8Array;if(e<=bA)return Uint16Array;if(e<=EA)return Uint32Array;throw new Error("mnemonist: Pointer Array of size > 4294967295 is not supported.")};$t.getSignedPointerArray=function(r){var e=r-1;return e<=xA?Int8Array:e<=SA?Int16Array:e<=IA?Int32Array:Float64Array};$t.getNumberType=function(r){return r===(r|0)?Math.sign(r)===-1?r<=127&&r>=-128?Int8Array:r<=32767&&r>=-32768?Int16Array:Int32Array:r<=255?Uint8Array:r<=65535?Uint16Array:Uint32Array:Float64Array};var AA={Uint8Array:1,Int8Array:2,Uint16Array:3,Int16Array:4,Uint32Array:5,Int32Array:6,Float32Array:7,Float64Array:8};$t.getMinimalRepresentation=function(r,e){var t=null,i=0,n,o,s,a,h;for(a=0,h=r.length;ai&&(i=n,t=o);return t};$t.isTypedArray=function(r){return typeof ArrayBuffer<"u"&&ArrayBuffer.isView(r)};$t.concat=function(){var r=0,e,t,i;for(e=0,i=arguments.length;e{var E1=ks(),x1=Ei();function RA(r){return Array.isArray(r)||x1.isTypedArray(r)}function Xl(r){if(typeof r.length=="number")return r.length;if(typeof r.size=="number")return r.size}function CA(r){var e=Xl(r),t=typeof e=="number"?new Array(e):[],i=0;return E1(r,function(n){t[i++]=n}),t}function TA(r){var e=Xl(r),t=typeof e=="number"?x1.getPointerArray(e):Array,i=typeof e=="number"?new Array(e):[],n=typeof e=="number"?new t(e):[],o=0;return E1(r,function(s){i[o]=s,n[o]=o++}),[i,n]}Dn.isArrayLike=RA;Dn.guessLength=Xl;Dn.toArray=CA;Dn.toArrayWithIndices=TA});var Oi=De((ZV,S1)=>{function Ut(r){if(typeof r!="function")throw new Error("obliterator/iterator: expecting a function!");this.next=r}typeof Symbol<"u"&&(Ut.prototype[Symbol.iterator]=function(){return this});Ut.of=function(){var r=arguments,e=r.length,t=0;return new Ut(function(){return t>=e?{done:!0}:{done:!1,value:r[t++]}})};Ut.empty=function(){var r=new Ut(function(){return{done:!0}});return r};Ut.fromSequence=function(r){var e=0,t=r.length;return new Ut(function(){return e>=t?{done:!0}:{done:!1,value:r[e++]}})};Ut.is=function(r){return r instanceof Ut?!0:typeof r=="object"&&r!==null&&typeof r.next=="function"};S1.exports=Ut});var Zl=De((JV,A1)=>{var Ql=Ls(),I1=Oi();function Lr(r,e){if(arguments.length<2)throw new Error("mnemonist/fixed-deque: expecting an Array class and a capacity.");if(typeof e!="number"||e<=0)throw new Error("mnemonist/fixed-deque: `capacity` should be a positive number.");this.ArrayClass=r,this.capacity=e,this.items=new r(this.capacity),this.clear()}Lr.prototype.clear=function(){this.start=0,this.size=0};Lr.prototype.push=function(r){if(this.size===this.capacity)throw new Error("mnemonist/fixed-deque.push: deque capacity ("+this.capacity+") exceeded!");var e=this.start+this.size;return e>=this.capacity&&(e-=this.capacity),this.items[e]=r,++this.size};Lr.prototype.unshift=function(r){if(this.size===this.capacity)throw new Error("mnemonist/fixed-deque.unshift: deque capacity ("+this.capacity+") exceeded!");var e=this.start-1;return this.start===0&&(e=this.capacity-1),this.items[e]=r,this.start=e,++this.size};Lr.prototype.pop=function(){if(this.size!==0){this.size--;var r=this.start+this.size;return r>=this.capacity&&(r-=this.capacity),this.items[r]}};Lr.prototype.shift=function(){if(this.size!==0){var r=this.start;return this.size--,this.start++,this.start===this.capacity&&(this.start=0),this.items[r]}};Lr.prototype.peekFirst=function(){if(this.size!==0)return this.items[this.start]};Lr.prototype.peekLast=function(){if(this.size!==0){var r=this.start+this.size-1;return r>=this.capacity&&(r-=this.capacity),this.items[r]}};Lr.prototype.get=function(r){if(!(this.size===0||r>=this.capacity))return r=this.start+r,r>=this.capacity&&(r-=this.capacity),this.items[r]};Lr.prototype.forEach=function(r,e){e=arguments.length>1?e:this;for(var t=this.capacity,i=this.size,n=this.start,o=0;o=t)return{done:!0};var o=r[i];return i++,n++,i===e&&(i=0),{value:o,done:!1}})};Lr.prototype.entries=function(){var r=this.items,e=this.capacity,t=this.size,i=this.start,n=0;return new I1(function(){if(n>=t)return{done:!0};var o=r[i];return i++,i===e&&(i=0),{value:[n++,o],done:!1}})};typeof Symbol<"u"&&(Lr.prototype[Symbol.iterator]=Lr.prototype.values);Lr.prototype.inspect=function(){var r=this.toArray();return r.type=this.ArrayClass.name,r.capacity=this.capacity,Object.defineProperty(r,"constructor",{value:Lr,enumerable:!1}),r};typeof Symbol<"u"&&(Lr.prototype[Symbol.for("nodejs.util.inspect.custom")]=Lr.prototype.inspect);Lr.from=function(r,e,t){if(arguments.length<3&&(t=Ql.guessLength(r),typeof t!="number"))throw new Error("mnemonist/fixed-deque.from: could not guess iterable length. Please provide desired capacity as last argument.");var i=new Lr(e,t);if(Ql.isArrayLike(r)){var n,o;for(n=0,o=r.length;n{var R1=Oi(),Jl=Ls();function zr(r,e){if(arguments.length<2)throw new Error("mnemonist/fixed-stack: expecting an Array class and a capacity.");if(typeof e!="number"||e<=0)throw new Error("mnemonist/fixed-stack: `capacity` should be a positive number.");this.capacity=e,this.ArrayClass=r,this.items=new this.ArrayClass(this.capacity),this.clear()}zr.prototype.clear=function(){this.size=0};zr.prototype.push=function(r){if(this.size===this.capacity)throw new Error("mnemonist/fixed-stack.push: stack capacity ("+this.capacity+") exceeded!");return this.items[this.size++]=r,this.size};zr.prototype.pop=function(){if(this.size!==0)return this.items[--this.size]};zr.prototype.peek=function(){return this.items[this.size-1]};zr.prototype.forEach=function(r,e){e=arguments.length>1?e:this;for(var t=0,i=this.items.length;t=e)return{done:!0};var i=r[e-t-1];return t++,{value:i,done:!1}})};zr.prototype.entries=function(){var r=this.items,e=this.size,t=0;return new R1(function(){if(t>=e)return{done:!0};var i=r[e-t-1];return{value:[t++,i],done:!1}})};typeof Symbol<"u"&&(zr.prototype[Symbol.iterator]=zr.prototype.values);zr.prototype.toString=function(){return this.toArray().join(",")};zr.prototype.toJSON=function(){return this.toArray()};zr.prototype.inspect=function(){var r=this.toArray();return r.type=this.ArrayClass.name,r.capacity=this.capacity,Object.defineProperty(r,"constructor",{value:zr,enumerable:!1}),r};typeof Symbol<"u"&&(zr.prototype[Symbol.for("nodejs.util.inspect.custom")]=zr.prototype.inspect);zr.from=function(r,e,t){if(arguments.length<3&&(t=Jl.guessLength(r),typeof t!="number"))throw new Error("mnemonist/fixed-stack.from: could not guess iterable length. Please provide desired capacity as last argument.");var i=new zr(e,t);if(Jl.isArrayLike(r)){var n,o;for(n=0,o=r.length;n{var OA=function(r,e){return re?1:0},kA=function(r,e){return re?-1:0};function LA(r){return function(e,t){return r(t,e)}}function MA(r){return r===2?function(e,t){return e[0]t[0]?1:e[1]t[1]?1:0}:function(e,t){for(var i=0;it[i])return 1;i++}return 0}}jn.DEFAULT_COMPARATOR=OA;jn.DEFAULT_REVERSE_COMPARATOR=kA;jn.reverseComparator=LA;jn.createTupleComparator=MA});var j1=De((rK,D1)=>{var Ms=ks(),k1=O1(),Wt=Ls(),js=k1.DEFAULT_COMPARATOR,Hl=k1.reverseComparator;function ed(r,e,t,i){for(var n=e[i],o,s;i>t;){if(o=i-1>>1,s=e[o],r(n,s)<0){e[i]=s,i=o;continue}break}e[i]=n}function Pn(r,e,t){for(var i=e.length,n=t,o=e[t],s=2*t+1,a;s=0&&(s=a),e[t]=e[s],t=s,s=2*t+1;e[t]=o,ed(r,e,n,t)}function L1(r,e,t){e.push(t),ed(r,e,0,e.length-1)}function rd(r,e){var t=e.pop();if(e.length!==0){var i=e[0];return e[0]=t,Pn(r,e,0),i}return t}function gn(r,e,t){if(e.length===0)throw new Error("mnemonist/heap.replace: cannot pop an empty heap.");var i=e[0];return e[0]=t,Pn(r,e,0),i}function M1(r,e,t){var i;return e.length!==0&&r(e[0],t)<0&&(i=e[0],e[0]=t,t=i,Pn(r,e,0)),t}function ki(r,e){for(var t=e.length,i=t>>1,n=i;--n>=0;)Pn(r,e,n)}function td(r,e){for(var t=e.length,i=0,n=new Array(t);i=t.length)return t.slice().sort(r);for(h=t.slice(0,e),ki(i,h),n=e,o=t.length;n0&&gn(i,h,t[n]);return h.sort(r)}var f=Wt.guessLength(t);return f!==null&&f0&&gn(i,h,l)),n++}),h.length>n&&(h.length=n),h.sort(r)}function jA(r,e,t){arguments.length===2&&(t=e,e=r,r=js);var i=Hl(r),n,o,s,a=-1/0,h;if(e===1){if(Wt.isArrayLike(t)){for(n=0,o=t.length;n0)&&(a=s);return h=new t.constructor(1),h[0]=a,h}return Ms(t,function(l){(a===-1/0||r(l,a)>0)&&(a=l)}),[a]}if(Wt.isArrayLike(t)){if(e>=t.length)return t.slice().sort(i);for(h=t.slice(0,e),ki(r,h),n=e,o=t.length;n0&&gn(r,h,t[n]);return h.sort(i)}var f=Wt.guessLength(t);return f!==null&&f0&&gn(r,h,l)),n++}),h.length>n&&(h.length=n),h.sort(i)}function nr(r){if(this.clear(),this.comparator=r||js,typeof this.comparator!="function")throw new Error("mnemonist/Heap.constructor: given comparator should be a function.")}nr.prototype.clear=function(){this.items=[],this.size=0};nr.prototype.push=function(r){return L1(this.comparator,this.items,r),++this.size};nr.prototype.peek=function(){return this.items[0]};nr.prototype.pop=function(){return this.size!==0&&this.size--,rd(this.comparator,this.items)};nr.prototype.replace=function(r){return gn(this.comparator,this.items,r)};nr.prototype.pushpop=function(r){return M1(this.comparator,this.items,r)};nr.prototype.consume=function(){return this.size=0,td(this.comparator,this.items)};nr.prototype.toArray=function(){return td(this.comparator,this.items.slice())};nr.prototype.inspect=function(){var r=this.toArray();return Object.defineProperty(r,"constructor",{value:nr,enumerable:!1}),r};typeof Symbol<"u"&&(nr.prototype[Symbol.for("nodejs.util.inspect.custom")]=nr.prototype.inspect);function Ds(r){if(this.clear(),this.comparator=r||js,typeof this.comparator!="function")throw new Error("mnemonist/MaxHeap.constructor: given comparator should be a function.");this.comparator=Hl(this.comparator)}Ds.prototype=nr.prototype;nr.from=function(r,e){var t=new nr(e),i;return Wt.isArrayLike(r)?i=r.slice():i=Wt.toArray(r),ki(t.comparator,i),t.items=i,t.size=i.length,t};Ds.from=function(r,e){var t=new Ds(e),i;return Wt.isArrayLike(r)?i=r.slice():i=Wt.toArray(r),ki(t.comparator,i),t.items=i,t.size=i.length,t};nr.siftUp=Pn;nr.siftDown=ed;nr.push=L1;nr.pop=rd;nr.replace=gn;nr.pushpop=M1;nr.heapify=ki;nr.consume=td;nr.nsmallest=DA;nr.nlargest=jA;nr.MinHeap=nr;nr.MaxHeap=Ds;D1.exports=nr});var Nn=De(id=>{var Ps=Ei(),PA=Gi().createEdgeWeightGetter;function P1(r,e){return r==="outbound"||r==="inbound"?e.directedSize+e.undirectedSize*2:r==="in"||r==="out"||r==="directed"?e.directedSize:e.undirectedSize*2}function Qt(r,e){e=e||"outbound";var t=r[e+"Neighbors"].bind(r),i=P1(e,r),n=Ps.getPointerArray(i),o=Ps.getPointerArray(r.order);this.graph=r,this.neighborhood=new o(i),this.starts=new n(r.order+1),this.nodes=r.nodes();var s={},a,h,f,l,g,m,_=0;for(a=0,h=r.order;a{var GA=Zl(),G1=T1(),NA=j1(),N1=Ei(),F1=Nn(),FA=F1.NeighborhoodIndex,zA=F1.WeightedNeighborhoodIndex;nd.createUnweightedIndexedBrandes=function(e){var t=new FA(e),i=t.neighborhood,n=t.starts,o=e.order,s=new G1(N1.getPointerArray(o),o),a=new Uint32Array(o),h=new Array(o),f=new Int32Array(o),l=new GA(Uint32Array,o),g=function(m){var _,E,q,x,A,S,I;for(S=0;Se[0]?1:r[0]e[1]?1:r[1]e[2]?1:r[2]e[3]?1:r[3]{var UA=Or(),$1=z1(),WA=_t(),BA=$1.createUnweightedIndexedBrandes,VA=$1.createDijkstraIndexedBrandes,KA={nodeCentralityAttribute:"betweennessCentrality",getEdgeWeight:"weight",normalized:!0};function U1(r,e,t){if(!UA(e))throw new Error("graphology-centrality/beetweenness-centrality: the given graph is not a valid graphology instance.");t=WA(t,KA);var i=t.nodeCentralityAttribute,n=t.normalized,o=t.getEdgeWeight?VA(e,t.getEdgeWeight):BA(e),s=e.order,a,h,f,l,g,m,_,E,q,x,A=new Float64Array(s),S=new Float64Array(s);for(m=0;m{var YA=Oi(),XA=Ei().getPointerArray;function pt(r){var e=XA(r);this.size=0,this.length=r,this.dense=new e(r),this.sparse=new e(r)}pt.prototype.clear=function(){this.size=0};pt.prototype.has=function(r){var e=this.sparse[r];return e=this.size||this.dense[e]!==r?!1:(e=this.dense[this.size-1],this.dense[this.sparse[r]]=e,this.sparse[e]=this.sparse[r],this.size--,!0)};pt.prototype.forEach=function(r,e){e=arguments.length>1?e:this;for(var t,i=0;i{var QA=Or(),ZA=_t(),JA=Zl(),HA=Y1(),eR=Nn().NeighborhoodIndex,rR={nodeCentralityAttribute:"closenessCentrality",wassermanFaust:!1};function X1(r){this.index=new eR(r,"inbound"),this.queue=new JA(Array,r.order),this.seen=new HA(r.order)}X1.prototype.fromNode=function(r){var e=this.index,t=this.queue,i=this.seen;i.clear(),t.clear(),i.add(r),t.push([r,0]);for(var n,o,s,a,h,f,l=0,g=0;t.size!==0;)for(n=t.shift(),o=n[0],s=n[1],s!==0&&(l+=s,g+=1),h=e.starts[o+1],a=e.starts[o];a0&&o>1&&(l=h/f,i&&(l*=h/(o-1))),g[s]=l;return r?n.index.assign(t.nodeCentralityAttribute,g):n.index.collect(g)}var Z1=Q1.bind(null,!1);Z1.assign=Q1.bind(null,!0);J1.exports=Z1});var iE=De((aK,tE)=>{var tR=Or(),iR=_t(),nR=Nn().WeightedNeighborhoodIndex,oR={nodeCentralityAttribute:"eigenvectorCentrality",getEdgeWeight:"weight",maxIterations:100,tolerance:1e-6};function sR(r){for(var e=0,t=0,i=0,n=r.length;ie&&(t*=e/o*(e/o),e=o),t+=o===0&&e===0?0:o/e*(o/e)}return e===1/0?1:e*Math.sqrt(t)}function eE(r,e,t){if(!tR(e))throw new Error("graphology-metrics/centrality/eigenvector: the given graph is not a valid graphology instance.");t=iR(t,oR);var i=t.maxIterations,n=t.tolerance,o=e.order,s=new nR(e,t.getEdgeWeight),a,h,f,l,g=new Float64Array(e.order);for(a=0;a{var aR=Or(),uR=_t(),fR=Nn().WeightedNeighborhoodIndex,hR={nodePagerankAttribute:"pagerank",getEdgeWeight:"weight",alpha:.85,maxIterations:100,tolerance:1e-6};function nE(r,e,t){if(!aR(e))throw new Error("graphology-metrics/centrality/pagerank: the given graph is not a valid graphology instance.");t=uR(t,hR);var i=t.alpha,n=t.maxIterations,o=t.tolerance,s=t.nodePagerankAttribute,a=e.order,h=1/a,f=new fR(e,t.getEdgeWeight),l,g,m,_,E=new Float64Array(e.order),q=new Float64Array(f.weights.length),x=[];for(l=0;l{var cR=Or();uE.exports=function(e){if(!cR(e))throw new Error("graphology-metrics/simple-size: the given graph is not a valid graphology instance.");if(!e.multi)return e.size;var t=0,i=0;function n(){t++}function o(){i++}return e.forEachNode(function(s){e.type!=="directed"&&e.forEachUndirectedNeighbor(s,n),e.type!=="undirected"&&e.forEachOutNeighbor(s,o)}),t/2+i}});var hE=De(Zt=>{var lR=Or(),dR=fE();function pR(r,e){return 2*e/(r*(r-1))}function gR(r,e){return e/(r*(r-1))}function mR(r,e){var t=r*(r-1);return e/(t+t/2)}function xi(r,e,t){var i,n;if(arguments.length>3){if(i=t,n=arguments[3],typeof i!="number"||i<0)throw new Error("graphology-metrics/density: given order is not a valid number.");if(typeof n!="number"||n<0)throw new Error("graphology-metrics/density: given size is not a valid number.")}else{if(!lR(t))throw new Error("graphology-metrics/density: given graph is not a valid graphology instance.");i=t.order,n=t.size,t.multi&&e===!1&&(n=dR(t))}if(i<2)return 0;r===null&&(r=t.type),e===null&&(e=t.multi);var o;return r==="undirected"?o=pR:r==="directed"?o=gR:o=mR,o(i,n)}Zt.abstractDensity=xi;Zt.density=xi.bind(null,null,null);Zt.directedDensity=xi.bind(null,"directed",!1);Zt.undirectedDensity=xi.bind(null,"undirected",!1);Zt.mixedDensity=xi.bind(null,"mixed",!1);Zt.multiDirectedDensity=xi.bind(null,"directed",!0);Zt.multiUndirectedDensity=xi.bind(null,"undirected",!0);Zt.multiMixedDensity=xi.bind(null,"mixed",!0)});var dE=De((cK,lE)=>{var cE=Oi(),yR=ks();function Mr(){this.clear()}Mr.prototype.clear=function(){this.items=[],this.offset=0,this.size=0};Mr.prototype.enqueue=function(r){return this.items.push(r),++this.size};Mr.prototype.dequeue=function(){if(this.size){var r=this.items[this.offset];return++this.offset*2>=this.items.length&&(this.items=this.items.slice(this.offset),this.offset=0),this.size--,r}};Mr.prototype.peek=function(){if(this.size)return this.items[this.offset]};Mr.prototype.forEach=function(r,e){e=arguments.length>1?e:this;for(var t=this.offset,i=0,n=this.items.length;t=r.length)return{done:!0};var t=r[e];return e++,{value:t,done:!1}})};Mr.prototype.entries=function(){var r=this.items,e=this.offset,t=0;return new cE(function(){if(e>=r.length)return{done:!0};var i=r[e];return e++,{value:[t++,i],done:!1}})};typeof Symbol<"u"&&(Mr.prototype[Symbol.iterator]=Mr.prototype.values);Mr.prototype.toString=function(){return this.toArray().join(",")};Mr.prototype.toJSON=function(){return this.toArray()};Mr.prototype.inspect=function(){var r=this.toArray();return Object.defineProperty(r,"constructor",{value:Mr,enumerable:!1}),r};typeof Symbol<"u"&&(Mr.prototype[Symbol.for("nodejs.util.inspect.custom")]=Mr.prototype.inspect);Mr.from=function(r){var e=new Mr;return yR(r,function(t){e.enqueue(t)}),e};Mr.of=function(){return Mr.from(arguments)};lE.exports=Mr});var gE=De((lK,pE)=>{pE.exports=function(e,t){var i=t.length;if(i!==0){var n=e.length;e.length+=i;for(var o=0;o{var od=Or(),_R=dE(),vR=gE();function wR(r,e,t){if(!od(r))throw new Error("graphology-shortest-path: invalid graphology instance.");if(arguments.length<3)throw new Error("graphology-shortest-path: invalid number of arguments. Expecting at least 3.");if(!r.hasNode(e))throw new Error('graphology-shortest-path: the "'+e+'" source node does not exist in the given graph.');if(!r.hasNode(t))throw new Error('graphology-shortest-path: the "'+t+'" target node does not exist in the given graph.');if(e=""+e,t=""+t,e===t)return[e];var i=r.inboundNeighbors.bind(r),n=r.outboundNeighbors.bind(r),o={},s={};o[e]=null,s[t]=null;var a=[e],h=[t],f,l,g,m,_,E,q,x,A=!1;e:for(;a.length&&h.length;)if(a.length<=h.length){for(f=a,a=[],_=0,q=f.length;_{var SR=Or(),IR=yE().singleSourceLength;_E.exports=function(e,t){if(!SR(e))throw new Error("graphology-metrics/eccentricity: given graph is not a valid graphology instance.");if(e.size===0)return 1/0;var i=-1/0,n=IR(e,t),o,s,a=0;for(o in n)s=n[o],s>i&&(i=s),a++;return a{var AR=Or(),RR=vE();wE.exports=function(e){if(!AR(e))throw new Error("graphology-metrics/diameter: given graph is not a valid graphology instance.");if(e.size===0)return 1/0;var t=-1/0;return e.someNode(function(i){var n=RR(e,i);return n>t&&(t=n),t===1/0}),t}});var sd=De((mK,bE)=>{var CR=Or();bE.exports=function(e){if(!CR(e))throw new Error("graphology-utils/infer-type: expecting a valid graphology instance.");var t=e.type;return t!=="mixed"?t:e.directedSize===0&&e.undirectedSize===0||e.directedSize>0&&e.undirectedSize>0?"mixed":e.directedSize>0?"directed":"undirected"}});var CE=De((yK,RE)=>{var EE=_t(),xE=Or(),SE=sd(),Si=Gi(),IE={getNodeCommunity:"community",getEdgeWeight:"weight",resolution:1};function TR(r,e){var t=new Array(r.order),i=new Float64Array(r.order),n={},o=0,s=Si.createEdgeWeightGetter(e.getEdgeWeight).fromEntry,a=Si.createNodeValueGetter(e.getNodeCommunity).fromEntry,h=0,f={};return r.forEachNode(function(l,g){f[l]=h,t[h++]=a(l,g)}),r.forEachUndirectedEdge(function(l,g,m,_,E,q,x){var A=s(l,g,m,_,E,q,x);o+=A,n[l]=A,i[f[m]]+=A,m!==_&&(i[f[_]]+=A)}),{weights:n,communities:t,weightedDegrees:i,M:o}}function OR(r,e){var t=new Array(r.order),i=new Float64Array(r.order),n=new Float64Array(r.order),o={},s=0,a=Si.createEdgeWeightGetter(e.getEdgeWeight).fromEntry,h=Si.createNodeValueGetter(e.getNodeCommunity).fromEntry,f=0,l={};return r.forEachNode(function(g,m){l[g]=f,t[f++]=h(g,m)}),r.forEachDirectedEdge(function(g,m,_,E,q,x,A){var S=a(g,m,_,E,q,x,A);s+=S,o[g]=S,n[l[_]]+=S,i[l[E]]+=S}),{weights:o,communities:t,weightedInDegrees:i,weightedOutDegrees:n,M:s}}function kR(r,e){var t=e.resolution,i=TR(r,e),n=i.communities,o=i.weightedDegrees,s=i.M,a=r.nodes(),h,f,l,g,m,_,E=0,q=s*2;for(h=0,l=r.order;h"u")throw new Error('graphology-metrics/modularity: the "'+s+'" node is not in the partition.');i[h]=0,n[h]=0}),{communities:t,totalWeights:i,internalWeights:n}}function DR(r,e){var t={},i={},n={},o={},s=Si.createNodeValueGetter(e.getNodeCommunity).fromEntry;return r.forEachNode(function(a,h){var f=s(a,h);if(t[a]=f,typeof f>"u")throw new Error('graphology-metrics/modularity: the "'+a+'" node is not in the partition.');i[f]=0,n[f]=0,o[f]=0}),{communities:t,totalInWeights:i,totalOutWeights:n,internalWeights:o}}function jR(r,e){var t=e.resolution,i=MR(r,e),n=0,o=i.totalWeights,s=i.internalWeights,a=i.communities,h=Si.createEdgeWeightGetter(e.getEdgeWeight).fromEntry;r.forEachUndirectedEdge(function(m,_,E,q,x,A,S){var I=h(m,_,E,q,x,A,S);n+=I;var M=a[E],D=a[q];o[M]+=I,o[D]+=I,M===D&&(s[M]+=I*2)});var f=0,l=n*2;for(var g in s)f+=s[g]/l-Math.pow(o[g]/l,2)*t;return f}function PR(r,e){var t=e.resolution,i=DR(r,e),n=0,o=i.totalInWeights,s=i.totalOutWeights,a=i.internalWeights,h=i.communities,f=Si.createEdgeWeightGetter(e.getEdgeWeight).fromEntry;r.forEachDirectedEdge(function(m,_,E,q,x,A,S){var I=f(m,_,E,q,x,A,S);n+=I;var M=h[E],D=h[q];s[M]+=I,o[D]+=I,M===D&&(a[M]+=I)});var l=0;for(var g in a)l+=a[g]/n-o[g]*s[g]/Math.pow(n,2)*t;return l}function GR(r,e,t,i){return i/(2*r)-e*t/(2*(r*r))}function NR(r,e,t,i,n,o){return o/r-(n*e+i*t)/(r*r)}function FR(r,e){if(!xE(r))throw new Error("graphology-metrics/modularity: given graph is not a valid graphology instance.");if(r.size===0)throw new Error("graphology-metrics/modularity: cannot compute modularity of an empty graph.");if(r.multi)throw new Error("graphology-metrics/modularity: cannot compute modularity of a multi graph. Cast it to a simple one beforehand.");var t=SE(r);if(t==="mixed")throw new Error("graphology-metrics/modularity: cannot compute modularity of a mixed graph.");return e=EE(e,IE),t==="directed"?LR(r,e):kR(r,e)}function AE(r,e){if(!xE(r))throw new Error("graphology-metrics/modularity: given graph is not a valid graphology instance.");if(r.size===0)throw new Error("graphology-metrics/modularity: cannot compute modularity of an empty graph.");if(r.multi)throw new Error("graphology-metrics/modularity: cannot compute modularity of a multi graph. Cast it to a simple one beforehand.");var t=SE(r);if(t==="mixed")throw new Error("graphology-metrics/modularity: cannot compute modularity of a mixed graph.");return e=EE(e,IE),t==="directed"?PR(r,e):jR(r,e)}var Fn=AE;Fn.sparse=AE;Fn.dense=FR;Fn.undirectedDelta=GR;Fn.directedDelta=NR;RE.exports=Fn});var OE=De((_K,TE)=>{var ad=Oi(),zR=Ei().getPointerArray;function Jr(r,e){arguments.length<2&&(e=r,r=Array);var t=zR(e);this.size=0,this.length=e,this.dense=new t(e),this.sparse=new t(e),this.vals=new r(e)}Jr.prototype.clear=function(){this.size=0};Jr.prototype.has=function(r){var e=this.sparse[r];return e=this.size||this.dense[e]!==r?!1:(e=this.dense[this.size-1],this.dense[this.sparse[r]]=e,this.sparse[e]=this.sparse[r],this.size--,!0)};Jr.prototype.forEach=function(r,e){e=arguments.length>1?e:this;for(var t=0;t{var $R=Oi(),UR=Ei().getPointerArray;function gt(r){var e=UR(r);this.start=0,this.size=0,this.capacity=r,this.dense=new e(r),this.sparse=new e(r)}gt.prototype.clear=function(){this.start=0,this.size=0};gt.prototype.has=function(r){if(this.size===0)return!1;var e=this.sparse[r],t=e=this.start&&e=this.start&&e1?e:this;for(var t=this.capacity,i=this.size,n=this.start,o=0;o=t)return{done:!0};var o=r[i];return i++,n++,i===e&&(i=0),{value:o,done:!1}})};typeof Symbol<"u"&&(gt.prototype[Symbol.iterator]=gt.prototype.values);gt.prototype.inspect=function(){var r=[];return this.forEach(function(e){r.push(e)}),Object.defineProperty(r,"constructor",{value:gt,enumerable:!1}),r.capacity=this.capacity,r};typeof Symbol<"u"&&(gt.prototype[Symbol.for("nodejs.util.inspect.custom")]=gt.prototype.inspect);kE.exports=gt});var PE=De((wK,jE)=>{function ME(r){return function(e){return typeof e!="number"&&(e=e.length),Math.floor(r()*e)}}var DE=ME(Math.random);DE.createRandomIndex=ME;jE.exports=DE});var $E=De(ud=>{var Ii=Ei(),GE=_t(),NE=Gi().createEdgeWeightGetter,FE=Symbol.for("nodejs.util.inspect.custom"),zE={getEdgeWeight:"weight",keepDendrogram:!1,resolution:1};function Cr(r,e){e=GE(e,zE);var t=e.resolution,i=NE(e.getEdgeWeight).fromEntry,n=(r.size-r.selfLoopCount)*2,o=Ii.getPointerArray(n),s=Ii.getPointerArray(r.order+1),a=e.getEdgeWeight?Float64Array:Ii.getPointerArray(r.size*2);this.C=r.order,this.M=0,this.E=n,this.U=0,this.resolution=t,this.level=0,this.graph=r,this.nodes=new Array(r.order),this.keepDendrogram=e.keepDendrogram,this.neighborhood=new s(n),this.weights=new a(n),this.loops=new a(r.order),this.starts=new o(r.order+1),this.belongings=new s(r.order),this.dendrogram=[],this.mapping=null,this.counts=new s(r.order),this.unused=new s(r.order),this.totalWeights=new a(r.order);var h={},f,l=0,g=0,m=this;r.forEachNode(function(_){m.nodes[l]=_,h[_]=l,g+=r.undirectedDegreeWithoutSelfLoops(_),m.starts[l]=g,m.belongings[l]=l,m.counts[l]=1,l++}),r.forEachEdge(function(_,E,q,x,A,S,I){if(f=i(_,E,q,x,A,S,I),q=h[q],x=h[x],m.M+=f,q===x)m.totalWeights[q]+=f*2,m.loops[q]=f*2;else{m.totalWeights[q]+=f,m.totalWeights[x]+=f;var M=--m.starts[q],D=--m.starts[x];m.neighborhood[M]=x,m.neighborhood[D]=q,m.weights[M]=f,m.weights[D]=f}}),this.starts[l]=this.E,this.keepDendrogram?this.dendrogram.push(this.belongings.slice()):this.mapping=this.belongings.slice()}Cr.prototype.isolate=function(r,e){var t=this.belongings[r];if(this.counts[t]===1)return t;var i=this.unused[--this.U],n=this.loops[r];return this.totalWeights[t]-=e+n,this.totalWeights[i]+=e+n,this.belongings[r]=i,this.counts[t]--,this.counts[i]++,i};Cr.prototype.move=function(r,e,t){var i=this.belongings[r],n=this.loops[r];this.totalWeights[i]-=e+n,this.totalWeights[t]+=e+n,this.belongings[r]=t;var o=this.counts[i]--===1;this.counts[t]++,o&&(this.unused[this.U++]=i)};Cr.prototype.computeNodeDegree=function(r){var e,t,i,n=0;for(e=this.starts[r],t=this.starts[r+1];e{var WR=_t(),BR=Or(),VR=sd(),UE=OE(),WE=LE(),BE=PE().createRandomIndex,VE=$E(),KR=VE.UndirectedLouvainIndex,YR=VE.DirectedLouvainIndex,KE={nodeCommunityAttribute:"community",getEdgeWeight:"weight",fastLocalMoves:!0,randomWalk:!0,resolution:1,rng:Math.random};function Gs(r,e,t){var i=r.get(e);typeof i>"u"&&(i=0),i+=t,r.set(e,i)}var XR=1e-10;function Ns(r,e,t,i,n){return Math.abs(i-n)r:i>n}function QR(r,e,t){var i=new KR(e,{getEdgeWeight:t.getEdgeWeight,keepDendrogram:r,resolution:t.resolution}),n=BE(t.rng),o=!0,s=!0,a,h,f=new UE(Float64Array,i.C),l,g,m,_,E,q,x,A,S,I,M,D,z,O,N,j,X=0,re=0,oe=[],me,_e;for(t.fastLocalMoves&&(l=new WE(i.C));o;){if(I=i.C,o=!1,s=!0,t.fastLocalMoves){for(_e=0,q=t.randomWalk?n(I):0,x=0;xr++}function Vt(){let r=arguments,e=null,t=-1;return{[Symbol.iterator](){return this},next(){let i=null;do{if(e===null){if(t++,t>=r.length)return{done:!0};e=r[t][Symbol.iterator]()}if(i=e.next(),i.done){e=null;continue}break}while(!0);return i}}}function Di(){return{[Symbol.iterator](){return this},next(){return{done:!0}}}}var vn=class extends Error{constructor(e){super(),this.name="GraphError",this.message=e}},Ie=class r extends vn{constructor(e){super(e),this.name="InvalidArgumentsGraphError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,r.prototype.constructor)}},we=class r extends vn{constructor(e){super(e),this.name="NotFoundGraphError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,r.prototype.constructor)}},Pe=class r extends vn{constructor(e){super(e),this.name="UsageGraphError",typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,r.prototype.constructor)}};function Rd(r,e){this.key=r,this.attributes=e,this.clear()}Rd.prototype.clear=function(){this.inDegree=0,this.outDegree=0,this.undirectedDegree=0,this.undirectedLoops=0,this.directedLoops=0,this.in={},this.out={},this.undirected={}};function Cd(r,e){this.key=r,this.attributes=e,this.clear()}Cd.prototype.clear=function(){this.inDegree=0,this.outDegree=0,this.directedLoops=0,this.in={},this.out={}};function Td(r,e){this.key=r,this.attributes=e,this.clear()}Td.prototype.clear=function(){this.undirectedDegree=0,this.undirectedLoops=0,this.undirected={}};function ji(r,e,t,i,n){this.key=e,this.attributes=n,this.undirected=r,this.source=t,this.target=i}ji.prototype.attach=function(){let r="out",e="in";this.undirected&&(r=e="undirected");let t=this.source.key,i=this.target.key;this.source[r][i]=this,!(this.undirected&&t===i)&&(this.target[e][t]=this)};ji.prototype.attachMulti=function(){let r="out",e="in",t=this.source.key,i=this.target.key;this.undirected&&(r=e="undirected");let n=this.source[r],o=n[i];if(typeof o>"u"){n[i]=this,this.undirected&&t===i||(this.target[e][t]=this);return}o.previous=this,this.next=o,n[i]=this,this.target[e][t]=this};ji.prototype.detach=function(){let r=this.source.key,e=this.target.key,t="out",i="in";this.undirected&&(t=i="undirected"),delete this.source[t][e],delete this.target[i][r]};ji.prototype.detachMulti=function(){let r=this.source.key,e=this.target.key,t="out",i="in";this.undirected&&(t=i="undirected"),this.previous===void 0?this.next===void 0?(delete this.source[t][e],delete this.target[i][r]):(this.next.previous=void 0,this.source[t][e]=this.next,this.target[i][r]=this.next):(this.previous.next=this.next,this.next!==void 0&&(this.next.previous=this.previous))};var Od=0,kd=1,wx=2,Ld=3;function Kt(r,e,t,i,n,o,s){let a,h,f,l;if(i=""+i,t===Od){if(a=r._nodes.get(i),!a)throw new we(`Graph.${e}: could not find the "${i}" node in the graph.`);f=n,l=o}else if(t===Ld){if(n=""+n,h=r._edges.get(n),!h)throw new we(`Graph.${e}: could not find the "${n}" edge in the graph.`);let g=h.source.key,m=h.target.key;if(i===g)a=h.target;else if(i===m)a=h.source;else throw new we(`Graph.${e}: the "${i}" node is not attached to the "${n}" edge (${g}, ${m}).`);f=o,l=s}else{if(h=r._edges.get(i),!h)throw new we(`Graph.${e}: could not find the "${i}" edge in the graph.`);t===kd?a=h.source:a=h.target,f=n,l=o}return[a,f,l]}function qx(r,e,t){r.prototype[e]=function(i,n,o){let[s,a]=Kt(this,e,t,i,n,o);return s.attributes[a]}}function bx(r,e,t){r.prototype[e]=function(i,n){let[o]=Kt(this,e,t,i,n);return o.attributes}}function Ex(r,e,t){r.prototype[e]=function(i,n,o){let[s,a]=Kt(this,e,t,i,n,o);return s.attributes.hasOwnProperty(a)}}function xx(r,e,t){r.prototype[e]=function(i,n,o,s){let[a,h,f]=Kt(this,e,t,i,n,o,s);return a.attributes[h]=f,this.emit("nodeAttributesUpdated",{key:a.key,type:"set",attributes:a.attributes,name:h}),this}}function Sx(r,e,t){r.prototype[e]=function(i,n,o,s){let[a,h,f]=Kt(this,e,t,i,n,o,s);if(typeof f!="function")throw new Ie(`Graph.${e}: updater should be a function.`);let l=a.attributes,g=f(l[h]);return l[h]=g,this.emit("nodeAttributesUpdated",{key:a.key,type:"set",attributes:a.attributes,name:h}),this}}function Ix(r,e,t){r.prototype[e]=function(i,n,o){let[s,a]=Kt(this,e,t,i,n,o);return delete s.attributes[a],this.emit("nodeAttributesUpdated",{key:s.key,type:"remove",attributes:s.attributes,name:a}),this}}function Ax(r,e,t){r.prototype[e]=function(i,n,o){let[s,a]=Kt(this,e,t,i,n,o);if(!Xr(a))throw new Ie(`Graph.${e}: provided attributes are not a plain object.`);return s.attributes=a,this.emit("nodeAttributesUpdated",{key:s.key,type:"replace",attributes:s.attributes}),this}}function Rx(r,e,t){r.prototype[e]=function(i,n,o){let[s,a]=Kt(this,e,t,i,n,o);if(!Xr(a))throw new Ie(`Graph.${e}: provided attributes are not a plain object.`);return Fr(s.attributes,a),this.emit("nodeAttributesUpdated",{key:s.key,type:"merge",attributes:s.attributes,data:a}),this}}function Cx(r,e,t){r.prototype[e]=function(i,n,o){let[s,a]=Kt(this,e,t,i,n,o);if(typeof a!="function")throw new Ie(`Graph.${e}: provided updater is not a function.`);return s.attributes=a(s.attributes),this.emit("nodeAttributesUpdated",{key:s.key,type:"update",attributes:s.attributes}),this}}var Tx=[{name:r=>`get${r}Attribute`,attacher:qx},{name:r=>`get${r}Attributes`,attacher:bx},{name:r=>`has${r}Attribute`,attacher:Ex},{name:r=>`set${r}Attribute`,attacher:xx},{name:r=>`update${r}Attribute`,attacher:Sx},{name:r=>`remove${r}Attribute`,attacher:Ix},{name:r=>`replace${r}Attributes`,attacher:Ax},{name:r=>`merge${r}Attributes`,attacher:Rx},{name:r=>`update${r}Attributes`,attacher:Cx}];function Ox(r){Tx.forEach(function({name:e,attacher:t}){t(r,e("Node"),Od),t(r,e("Source"),kd),t(r,e("Target"),wx),t(r,e("Opposite"),Ld)})}function kx(r,e,t){r.prototype[e]=function(i,n){let o;if(this.type!=="mixed"&&t!=="mixed"&&t!==this.type)throw new Pe(`Graph.${e}: cannot find this type of edges in your ${this.type} graph.`);if(arguments.length>2){if(this.multi)throw new Pe(`Graph.${e}: cannot use a {source,target} combo when asking about an edge's attributes in a MultiGraph since we cannot infer the one you want information about.`);let s=""+i,a=""+n;if(n=arguments[2],o=yt(this,s,a,t),!o)throw new we(`Graph.${e}: could not find an edge for the given path ("${s}" - "${a}").`)}else{if(t!=="mixed")throw new Pe(`Graph.${e}: calling this method with only a key (vs. a source and target) does not make sense since an edge with this key could have the other type.`);if(i=""+i,o=this._edges.get(i),!o)throw new we(`Graph.${e}: could not find the "${i}" edge in the graph.`)}return o.attributes[n]}}function Lx(r,e,t){r.prototype[e]=function(i){let n;if(this.type!=="mixed"&&t!=="mixed"&&t!==this.type)throw new Pe(`Graph.${e}: cannot find this type of edges in your ${this.type} graph.`);if(arguments.length>1){if(this.multi)throw new Pe(`Graph.${e}: cannot use a {source,target} combo when asking about an edge's attributes in a MultiGraph since we cannot infer the one you want information about.`);let o=""+i,s=""+arguments[1];if(n=yt(this,o,s,t),!n)throw new we(`Graph.${e}: could not find an edge for the given path ("${o}" - "${s}").`)}else{if(t!=="mixed")throw new Pe(`Graph.${e}: calling this method with only a key (vs. a source and target) does not make sense since an edge with this key could have the other type.`);if(i=""+i,n=this._edges.get(i),!n)throw new we(`Graph.${e}: could not find the "${i}" edge in the graph.`)}return n.attributes}}function Mx(r,e,t){r.prototype[e]=function(i,n){let o;if(this.type!=="mixed"&&t!=="mixed"&&t!==this.type)throw new Pe(`Graph.${e}: cannot find this type of edges in your ${this.type} graph.`);if(arguments.length>2){if(this.multi)throw new Pe(`Graph.${e}: cannot use a {source,target} combo when asking about an edge's attributes in a MultiGraph since we cannot infer the one you want information about.`);let s=""+i,a=""+n;if(n=arguments[2],o=yt(this,s,a,t),!o)throw new we(`Graph.${e}: could not find an edge for the given path ("${s}" - "${a}").`)}else{if(t!=="mixed")throw new Pe(`Graph.${e}: calling this method with only a key (vs. a source and target) does not make sense since an edge with this key could have the other type.`);if(i=""+i,o=this._edges.get(i),!o)throw new we(`Graph.${e}: could not find the "${i}" edge in the graph.`)}return o.attributes.hasOwnProperty(n)}}function Dx(r,e,t){r.prototype[e]=function(i,n,o){let s;if(this.type!=="mixed"&&t!=="mixed"&&t!==this.type)throw new Pe(`Graph.${e}: cannot find this type of edges in your ${this.type} graph.`);if(arguments.length>3){if(this.multi)throw new Pe(`Graph.${e}: cannot use a {source,target} combo when asking about an edge's attributes in a MultiGraph since we cannot infer the one you want information about.`);let a=""+i,h=""+n;if(n=arguments[2],o=arguments[3],s=yt(this,a,h,t),!s)throw new we(`Graph.${e}: could not find an edge for the given path ("${a}" - "${h}").`)}else{if(t!=="mixed")throw new Pe(`Graph.${e}: calling this method with only a key (vs. a source and target) does not make sense since an edge with this key could have the other type.`);if(i=""+i,s=this._edges.get(i),!s)throw new we(`Graph.${e}: could not find the "${i}" edge in the graph.`)}return s.attributes[n]=o,this.emit("edgeAttributesUpdated",{key:s.key,type:"set",attributes:s.attributes,name:n}),this}}function jx(r,e,t){r.prototype[e]=function(i,n,o){let s;if(this.type!=="mixed"&&t!=="mixed"&&t!==this.type)throw new Pe(`Graph.${e}: cannot find this type of edges in your ${this.type} graph.`);if(arguments.length>3){if(this.multi)throw new Pe(`Graph.${e}: cannot use a {source,target} combo when asking about an edge's attributes in a MultiGraph since we cannot infer the one you want information about.`);let a=""+i,h=""+n;if(n=arguments[2],o=arguments[3],s=yt(this,a,h,t),!s)throw new we(`Graph.${e}: could not find an edge for the given path ("${a}" - "${h}").`)}else{if(t!=="mixed")throw new Pe(`Graph.${e}: calling this method with only a key (vs. a source and target) does not make sense since an edge with this key could have the other type.`);if(i=""+i,s=this._edges.get(i),!s)throw new we(`Graph.${e}: could not find the "${i}" edge in the graph.`)}if(typeof o!="function")throw new Ie(`Graph.${e}: updater should be a function.`);return s.attributes[n]=o(s.attributes[n]),this.emit("edgeAttributesUpdated",{key:s.key,type:"set",attributes:s.attributes,name:n}),this}}function Px(r,e,t){r.prototype[e]=function(i,n){let o;if(this.type!=="mixed"&&t!=="mixed"&&t!==this.type)throw new Pe(`Graph.${e}: cannot find this type of edges in your ${this.type} graph.`);if(arguments.length>2){if(this.multi)throw new Pe(`Graph.${e}: cannot use a {source,target} combo when asking about an edge's attributes in a MultiGraph since we cannot infer the one you want information about.`);let s=""+i,a=""+n;if(n=arguments[2],o=yt(this,s,a,t),!o)throw new we(`Graph.${e}: could not find an edge for the given path ("${s}" - "${a}").`)}else{if(t!=="mixed")throw new Pe(`Graph.${e}: calling this method with only a key (vs. a source and target) does not make sense since an edge with this key could have the other type.`);if(i=""+i,o=this._edges.get(i),!o)throw new we(`Graph.${e}: could not find the "${i}" edge in the graph.`)}return delete o.attributes[n],this.emit("edgeAttributesUpdated",{key:o.key,type:"remove",attributes:o.attributes,name:n}),this}}function Gx(r,e,t){r.prototype[e]=function(i,n){let o;if(this.type!=="mixed"&&t!=="mixed"&&t!==this.type)throw new Pe(`Graph.${e}: cannot find this type of edges in your ${this.type} graph.`);if(arguments.length>2){if(this.multi)throw new Pe(`Graph.${e}: cannot use a {source,target} combo when asking about an edge's attributes in a MultiGraph since we cannot infer the one you want information about.`);let s=""+i,a=""+n;if(n=arguments[2],o=yt(this,s,a,t),!o)throw new we(`Graph.${e}: could not find an edge for the given path ("${s}" - "${a}").`)}else{if(t!=="mixed")throw new Pe(`Graph.${e}: calling this method with only a key (vs. a source and target) does not make sense since an edge with this key could have the other type.`);if(i=""+i,o=this._edges.get(i),!o)throw new we(`Graph.${e}: could not find the "${i}" edge in the graph.`)}if(!Xr(n))throw new Ie(`Graph.${e}: provided attributes are not a plain object.`);return o.attributes=n,this.emit("edgeAttributesUpdated",{key:o.key,type:"replace",attributes:o.attributes}),this}}function Nx(r,e,t){r.prototype[e]=function(i,n){let o;if(this.type!=="mixed"&&t!=="mixed"&&t!==this.type)throw new Pe(`Graph.${e}: cannot find this type of edges in your ${this.type} graph.`);if(arguments.length>2){if(this.multi)throw new Pe(`Graph.${e}: cannot use a {source,target} combo when asking about an edge's attributes in a MultiGraph since we cannot infer the one you want information about.`);let s=""+i,a=""+n;if(n=arguments[2],o=yt(this,s,a,t),!o)throw new we(`Graph.${e}: could not find an edge for the given path ("${s}" - "${a}").`)}else{if(t!=="mixed")throw new Pe(`Graph.${e}: calling this method with only a key (vs. a source and target) does not make sense since an edge with this key could have the other type.`);if(i=""+i,o=this._edges.get(i),!o)throw new we(`Graph.${e}: could not find the "${i}" edge in the graph.`)}if(!Xr(n))throw new Ie(`Graph.${e}: provided attributes are not a plain object.`);return Fr(o.attributes,n),this.emit("edgeAttributesUpdated",{key:o.key,type:"merge",attributes:o.attributes,data:n}),this}}function Fx(r,e,t){r.prototype[e]=function(i,n){let o;if(this.type!=="mixed"&&t!=="mixed"&&t!==this.type)throw new Pe(`Graph.${e}: cannot find this type of edges in your ${this.type} graph.`);if(arguments.length>2){if(this.multi)throw new Pe(`Graph.${e}: cannot use a {source,target} combo when asking about an edge's attributes in a MultiGraph since we cannot infer the one you want information about.`);let s=""+i,a=""+n;if(n=arguments[2],o=yt(this,s,a,t),!o)throw new we(`Graph.${e}: could not find an edge for the given path ("${s}" - "${a}").`)}else{if(t!=="mixed")throw new Pe(`Graph.${e}: calling this method with only a key (vs. a source and target) does not make sense since an edge with this key could have the other type.`);if(i=""+i,o=this._edges.get(i),!o)throw new we(`Graph.${e}: could not find the "${i}" edge in the graph.`)}if(typeof n!="function")throw new Ie(`Graph.${e}: provided updater is not a function.`);return o.attributes=n(o.attributes),this.emit("edgeAttributesUpdated",{key:o.key,type:"update",attributes:o.attributes}),this}}var zx=[{name:r=>`get${r}Attribute`,attacher:kx},{name:r=>`get${r}Attributes`,attacher:Lx},{name:r=>`has${r}Attribute`,attacher:Mx},{name:r=>`set${r}Attribute`,attacher:Dx},{name:r=>`update${r}Attribute`,attacher:jx},{name:r=>`remove${r}Attribute`,attacher:Px},{name:r=>`replace${r}Attributes`,attacher:Gx},{name:r=>`merge${r}Attributes`,attacher:Nx},{name:r=>`update${r}Attributes`,attacher:Fx}];function $x(r){zx.forEach(function({name:e,attacher:t}){t(r,e("Edge"),"mixed"),t(r,e("DirectedEdge"),"directed"),t(r,e("UndirectedEdge"),"undirected")})}var Ux=[{name:"edges",type:"mixed"},{name:"inEdges",type:"directed",direction:"in"},{name:"outEdges",type:"directed",direction:"out"},{name:"inboundEdges",type:"mixed",direction:"in"},{name:"outboundEdges",type:"mixed",direction:"out"},{name:"directedEdges",type:"directed"},{name:"undirectedEdges",type:"undirected"}];function Wx(r,e,t,i){let n=!1;for(let o in e){if(o===i)continue;let s=e[o];if(n=t(s.key,s.attributes,s.source.key,s.target.key,s.source.attributes,s.target.attributes,s.undirected),r&&n)return s.key}}function Bx(r,e,t,i){let n,o,s,a=!1;for(let h in e)if(h!==i){n=e[h];do{if(o=n.source,s=n.target,a=t(n.key,n.attributes,o.key,s.key,o.attributes,s.attributes,n.undirected),r&&a)return n.key;n=n.next}while(n!==void 0)}}function Ks(r,e){let t=Object.keys(r),i=t.length,n,o=0;return{[Symbol.iterator](){return this},next(){do if(n)n=n.next;else{if(o>=i)return{done:!0};let s=t[o++];if(s===e){n=void 0;continue}n=r[s]}while(!n);return{done:!1,value:{edge:n.key,attributes:n.attributes,source:n.source.key,target:n.target.key,sourceAttributes:n.source.attributes,targetAttributes:n.target.attributes,undirected:n.undirected}}}}}function Vx(r,e,t,i){let n=e[t];if(!n)return;let o=n.source,s=n.target;if(i(n.key,n.attributes,o.key,s.key,o.attributes,s.attributes,n.undirected)&&r)return n.key}function Kx(r,e,t,i){let n=e[t];if(!n)return;let o=!1;do{if(o=i(n.key,n.attributes,n.source.key,n.target.key,n.source.attributes,n.target.attributes,n.undirected),r&&o)return n.key;n=n.next}while(n!==void 0)}function Ys(r,e){let t=r[e];if(t.next!==void 0)return{[Symbol.iterator](){return this},next(){if(!t)return{done:!0};let n={edge:t.key,attributes:t.attributes,source:t.source.key,target:t.target.key,sourceAttributes:t.source.attributes,targetAttributes:t.target.attributes,undirected:t.undirected};return t=t.next,{done:!1,value:n}}};let i=!1;return{[Symbol.iterator](){return this},next(){return i===!0?{done:!0}:(i=!0,{done:!1,value:{edge:t.key,attributes:t.attributes,source:t.source.key,target:t.target.key,sourceAttributes:t.source.attributes,targetAttributes:t.target.attributes,undirected:t.undirected}})}}}function Yx(r,e){if(r.size===0)return[];if(e==="mixed"||e===r.type)return Array.from(r._edges.keys());let t=e==="undirected"?r.undirectedSize:r.directedSize,i=new Array(t),n=e==="undirected",o=r._edges.values(),s=0,a,h;for(;a=o.next(),a.done!==!0;)h=a.value,h.undirected===n&&(i[s++]=h.key);return i}function Md(r,e,t,i){if(e.size===0)return;let n=t!=="mixed"&&t!==e.type,o=t==="undirected",s,a,h=!1,f=e._edges.values();for(;s=f.next(),s.done!==!0;){if(a=s.value,n&&a.undirected!==o)continue;let{key:l,attributes:g,source:m,target:_}=a;if(h=i(l,g,m.key,_.key,m.attributes,_.attributes,a.undirected),r&&h)return l}}function Xx(r,e){if(r.size===0)return Di();let t=e!=="mixed"&&e!==r.type,i=e==="undirected",n=r._edges.values();return{[Symbol.iterator](){return this},next(){let o,s;for(;;){if(o=n.next(),o.done)return o;if(s=o.value,!(t&&s.undirected!==i))break}return{value:{edge:s.key,attributes:s.attributes,source:s.source.key,target:s.target.key,sourceAttributes:s.source.attributes,targetAttributes:s.target.attributes,undirected:s.undirected},done:!1}}}}function Xs(r,e,t,i,n,o){let s=e?Bx:Wx,a;if(t!=="undirected"&&(i!=="out"&&(a=s(r,n.in,o),r&&a)||i!=="in"&&(a=s(r,n.out,o,i?void 0:n.key),r&&a))||t!=="directed"&&(a=s(r,n.undirected,o),r&&a))return a}function Qx(r,e,t,i){let n=[];return Xs(!1,r,e,t,i,function(o){n.push(o)}),n}function Zx(r,e,t){let i=Di();return r!=="undirected"&&(e!=="out"&&typeof t.in<"u"&&(i=Vt(i,Ks(t.in))),e!=="in"&&typeof t.out<"u"&&(i=Vt(i,Ks(t.out,e?void 0:t.key)))),r!=="directed"&&typeof t.undirected<"u"&&(i=Vt(i,Ks(t.undirected))),i}function Qs(r,e,t,i,n,o,s){let a=t?Kx:Vx,h;if(e!=="undirected"&&(typeof n.in<"u"&&i!=="out"&&(h=a(r,n.in,o,s),r&&h)||typeof n.out<"u"&&i!=="in"&&(i||n.key!==o)&&(h=a(r,n.out,o,s),r&&h))||e!=="directed"&&typeof n.undirected<"u"&&(h=a(r,n.undirected,o,s),r&&h))return h}function Jx(r,e,t,i,n){let o=[];return Qs(!1,r,e,t,i,n,function(s){o.push(s)}),o}function Hx(r,e,t,i){let n=Di();return r!=="undirected"&&(typeof t.in<"u"&&e!=="out"&&i in t.in&&(n=Vt(n,Ys(t.in,i))),typeof t.out<"u"&&e!=="in"&&i in t.out&&(e||t.key!==i)&&(n=Vt(n,Ys(t.out,i)))),r!=="directed"&&typeof t.undirected<"u"&&i in t.undirected&&(n=Vt(n,Ys(t.undirected,i))),n}function eS(r,e){let{name:t,type:i,direction:n}=e;r.prototype[t]=function(o,s){if(i!=="mixed"&&this.type!=="mixed"&&i!==this.type)return[];if(!arguments.length)return Yx(this,i);if(arguments.length===1){o=""+o;let a=this._nodes.get(o);if(typeof a>"u")throw new we(`Graph.${t}: could not find the "${o}" node in the graph.`);return Qx(this.multi,i==="mixed"?this.type:i,n,a)}if(arguments.length===2){o=""+o,s=""+s;let a=this._nodes.get(o);if(!a)throw new we(`Graph.${t}: could not find the "${o}" source node in the graph.`);if(!this._nodes.has(s))throw new we(`Graph.${t}: could not find the "${s}" target node in the graph.`);return Jx(i,this.multi,n,a,s)}throw new Ie(`Graph.${t}: too many arguments (expecting 0, 1 or 2 and got ${arguments.length}).`)}}function rS(r,e){let{name:t,type:i,direction:n}=e,o="forEach"+t[0].toUpperCase()+t.slice(1,-1);r.prototype[o]=function(f,l,g){if(!(i!=="mixed"&&this.type!=="mixed"&&i!==this.type)){if(arguments.length===1)return g=f,Md(!1,this,i,g);if(arguments.length===2){f=""+f,g=l;let m=this._nodes.get(f);if(typeof m>"u")throw new we(`Graph.${o}: could not find the "${f}" node in the graph.`);return Xs(!1,this.multi,i==="mixed"?this.type:i,n,m,g)}if(arguments.length===3){f=""+f,l=""+l;let m=this._nodes.get(f);if(!m)throw new we(`Graph.${o}: could not find the "${f}" source node in the graph.`);if(!this._nodes.has(l))throw new we(`Graph.${o}: could not find the "${l}" target node in the graph.`);return Qs(!1,i,this.multi,n,m,l,g)}throw new Ie(`Graph.${o}: too many arguments (expecting 1, 2 or 3 and got ${arguments.length}).`)}};let s="map"+t[0].toUpperCase()+t.slice(1);r.prototype[s]=function(){let f=Array.prototype.slice.call(arguments),l=f.pop(),g;if(f.length===0){let m=0;i!=="directed"&&(m+=this.undirectedSize),i!=="undirected"&&(m+=this.directedSize),g=new Array(m);let _=0;f.push((E,q,x,A,S,I,M)=>{g[_++]=l(E,q,x,A,S,I,M)})}else g=[],f.push((m,_,E,q,x,A,S)=>{g.push(l(m,_,E,q,x,A,S))});return this[o].apply(this,f),g};let a="filter"+t[0].toUpperCase()+t.slice(1);r.prototype[a]=function(){let f=Array.prototype.slice.call(arguments),l=f.pop(),g=[];return f.push((m,_,E,q,x,A,S)=>{l(m,_,E,q,x,A,S)&&g.push(m)}),this[o].apply(this,f),g};let h="reduce"+t[0].toUpperCase()+t.slice(1);r.prototype[h]=function(){let f=Array.prototype.slice.call(arguments);if(f.length<2||f.length>4)throw new Ie(`Graph.${h}: invalid number of arguments (expecting 2, 3 or 4 and got ${f.length}).`);if(typeof f[f.length-1]=="function"&&typeof f[f.length-2]!="function")throw new Ie(`Graph.${h}: missing initial value. You must provide it because the callback takes more than one argument and we cannot infer the initial value from the first iteration, as you could with a simple array.`);let l,g;f.length===2?(l=f[0],g=f[1],f=[]):f.length===3?(l=f[1],g=f[2],f=[f[0]]):f.length===4&&(l=f[2],g=f[3],f=[f[0],f[1]]);let m=g;return f.push((_,E,q,x,A,S,I)=>{m=l(m,_,E,q,x,A,S,I)}),this[o].apply(this,f),m}}function tS(r,e){let{name:t,type:i,direction:n}=e,o="find"+t[0].toUpperCase()+t.slice(1,-1);r.prototype[o]=function(h,f,l){if(i!=="mixed"&&this.type!=="mixed"&&i!==this.type)return!1;if(arguments.length===1)return l=h,Md(!0,this,i,l);if(arguments.length===2){h=""+h,l=f;let g=this._nodes.get(h);if(typeof g>"u")throw new we(`Graph.${o}: could not find the "${h}" node in the graph.`);return Xs(!0,this.multi,i==="mixed"?this.type:i,n,g,l)}if(arguments.length===3){h=""+h,f=""+f;let g=this._nodes.get(h);if(!g)throw new we(`Graph.${o}: could not find the "${h}" source node in the graph.`);if(!this._nodes.has(f))throw new we(`Graph.${o}: could not find the "${f}" target node in the graph.`);return Qs(!0,i,this.multi,n,g,f,l)}throw new Ie(`Graph.${o}: too many arguments (expecting 1, 2 or 3 and got ${arguments.length}).`)};let s="some"+t[0].toUpperCase()+t.slice(1,-1);r.prototype[s]=function(){let h=Array.prototype.slice.call(arguments),f=h.pop();return h.push((g,m,_,E,q,x,A)=>f(g,m,_,E,q,x,A)),!!this[o].apply(this,h)};let a="every"+t[0].toUpperCase()+t.slice(1,-1);r.prototype[a]=function(){let h=Array.prototype.slice.call(arguments),f=h.pop();return h.push((g,m,_,E,q,x,A)=>!f(g,m,_,E,q,x,A)),!this[o].apply(this,h)}}function iS(r,e){let{name:t,type:i,direction:n}=e,o=t.slice(0,-1)+"Entries";r.prototype[o]=function(s,a){if(i!=="mixed"&&this.type!=="mixed"&&i!==this.type)return Di();if(!arguments.length)return Xx(this,i);if(arguments.length===1){s=""+s;let h=this._nodes.get(s);if(!h)throw new we(`Graph.${o}: could not find the "${s}" node in the graph.`);return Zx(i,n,h)}if(arguments.length===2){s=""+s,a=""+a;let h=this._nodes.get(s);if(!h)throw new we(`Graph.${o}: could not find the "${s}" source node in the graph.`);if(!this._nodes.has(a))throw new we(`Graph.${o}: could not find the "${a}" target node in the graph.`);return Hx(i,n,h,a)}throw new Ie(`Graph.${o}: too many arguments (expecting 0, 1 or 2 and got ${arguments.length}).`)}}function nS(r){Ux.forEach(e=>{eS(r,e),rS(r,e),tS(r,e),iS(r,e)})}var oS=[{name:"neighbors",type:"mixed"},{name:"inNeighbors",type:"directed",direction:"in"},{name:"outNeighbors",type:"directed",direction:"out"},{name:"inboundNeighbors",type:"mixed",direction:"in"},{name:"outboundNeighbors",type:"mixed",direction:"out"},{name:"directedNeighbors",type:"directed"},{name:"undirectedNeighbors",type:"undirected"}];function Zn(){this.A=null,this.B=null}Zn.prototype.wrap=function(r){this.A===null?this.A=r:this.B===null&&(this.B=r)};Zn.prototype.has=function(r){return this.A!==null&&r in this.A||this.B!==null&&r in this.B};function yn(r,e,t,i,n){for(let o in i){let s=i[o],a=s.source,h=s.target,f=a===t?h:a;if(e&&e.has(f.key))continue;let l=n(f.key,f.attributes);if(r&&l)return f.key}}function Zs(r,e,t,i,n){if(e!=="mixed"){if(e==="undirected")return yn(r,null,i,i.undirected,n);if(typeof t=="string")return yn(r,null,i,i[t],n)}let o=new Zn,s;if(e!=="undirected"){if(t!=="out"){if(s=yn(r,null,i,i.in,n),r&&s)return s;o.wrap(i.in)}if(t!=="in"){if(s=yn(r,o,i,i.out,n),r&&s)return s;o.wrap(i.out)}}if(e!=="directed"&&(s=yn(r,o,i,i.undirected,n),r&&s))return s}function sS(r,e,t){if(r!=="mixed"){if(r==="undirected")return Object.keys(t.undirected);if(typeof e=="string")return Object.keys(t[e])}let i=[];return Zs(!1,r,e,t,function(n){i.push(n)}),i}function _n(r,e,t){let i=Object.keys(t),n=i.length,o=0;return{[Symbol.iterator](){return this},next(){let s=null;do{if(o>=n)return r&&r.wrap(t),{done:!0};let a=t[i[o++]],h=a.source,f=a.target;if(s=h===e?f:h,r&&r.has(s.key)){s=null;continue}}while(s===null);return{done:!1,value:{neighbor:s.key,attributes:s.attributes}}}}}function aS(r,e,t){if(r!=="mixed"){if(r==="undirected")return _n(null,t,t.undirected);if(typeof e=="string")return _n(null,t,t[e])}let i=Di(),n=new Zn;return r!=="undirected"&&(e!=="out"&&(i=Vt(i,_n(n,t,t.in))),e!=="in"&&(i=Vt(i,_n(n,t,t.out)))),r!=="directed"&&(i=Vt(i,_n(n,t,t.undirected))),i}function uS(r,e){let{name:t,type:i,direction:n}=e;r.prototype[t]=function(o){if(i!=="mixed"&&this.type!=="mixed"&&i!==this.type)return[];o=""+o;let s=this._nodes.get(o);if(typeof s>"u")throw new we(`Graph.${t}: could not find the "${o}" node in the graph.`);return sS(i==="mixed"?this.type:i,n,s)}}function fS(r,e){let{name:t,type:i,direction:n}=e,o="forEach"+t[0].toUpperCase()+t.slice(1,-1);r.prototype[o]=function(f,l){if(i!=="mixed"&&this.type!=="mixed"&&i!==this.type)return;f=""+f;let g=this._nodes.get(f);if(typeof g>"u")throw new we(`Graph.${o}: could not find the "${f}" node in the graph.`);Zs(!1,i==="mixed"?this.type:i,n,g,l)};let s="map"+t[0].toUpperCase()+t.slice(1);r.prototype[s]=function(f,l){let g=[];return this[o](f,(m,_)=>{g.push(l(m,_))}),g};let a="filter"+t[0].toUpperCase()+t.slice(1);r.prototype[a]=function(f,l){let g=[];return this[o](f,(m,_)=>{l(m,_)&&g.push(m)}),g};let h="reduce"+t[0].toUpperCase()+t.slice(1);r.prototype[h]=function(f,l,g){if(arguments.length<3)throw new Ie(`Graph.${h}: missing initial value. You must provide it because the callback takes more than one argument and we cannot infer the initial value from the first iteration, as you could with a simple array.`);let m=g;return this[o](f,(_,E)=>{m=l(m,_,E)}),m}}function hS(r,e){let{name:t,type:i,direction:n}=e,o=t[0].toUpperCase()+t.slice(1,-1),s="find"+o;r.prototype[s]=function(f,l){if(i!=="mixed"&&this.type!=="mixed"&&i!==this.type)return;f=""+f;let g=this._nodes.get(f);if(typeof g>"u")throw new we(`Graph.${s}: could not find the "${f}" node in the graph.`);return Zs(!0,i==="mixed"?this.type:i,n,g,l)};let a="some"+o;r.prototype[a]=function(f,l){return!!this[s](f,l)};let h="every"+o;r.prototype[h]=function(f,l){return!this[s](f,(m,_)=>!l(m,_))}}function cS(r,e){let{name:t,type:i,direction:n}=e,o=t.slice(0,-1)+"Entries";r.prototype[o]=function(s){if(i!=="mixed"&&this.type!=="mixed"&&i!==this.type)return Di();s=""+s;let a=this._nodes.get(s);if(typeof a>"u")throw new we(`Graph.${o}: could not find the "${s}" node in the graph.`);return aS(i==="mixed"?this.type:i,n,a)}}function lS(r){oS.forEach(e=>{uS(r,e),fS(r,e),hS(r,e),cS(r,e)})}function Bn(r,e,t,i,n){let o=i._nodes.values(),s=i.type,a,h,f,l,g,m,_;for(;a=o.next(),a.done!==!0;){let E=!1;if(h=a.value,s!=="undirected"){l=h.out;for(f in l){g=l[f];do{if(m=g.target,E=!0,_=n(h.key,m.key,h.attributes,m.attributes,g.key,g.attributes,g.undirected),r&&_)return g;g=g.next}while(g)}}if(s!=="directed"){l=h.undirected;for(f in l)if(!(e&&h.key>f)){g=l[f];do{if(m=g.target,m.key!==f&&(m=g.source),E=!0,_=n(h.key,m.key,h.attributes,m.attributes,g.key,g.attributes,g.undirected),r&&_)return g;g=g.next}while(g)}}if(t&&!E&&(_=n(h.key,null,h.attributes,null,null,null,null),r&&_))return null}}function dS(r,e){let t={key:r};return Ad(e.attributes)||(t.attributes=Fr({},e.attributes)),t}function pS(r,e,t){let i={key:e,source:t.source.key,target:t.target.key};return Ad(t.attributes)||(i.attributes=Fr({},t.attributes)),r==="mixed"&&t.undirected&&(i.undirected=!0),i}function gS(r){if(!Xr(r))throw new Ie('Graph.import: invalid serialized node. A serialized node should be a plain object with at least a "key" property.');if(!("key"in r))throw new Ie("Graph.import: serialized node is missing its key.");if("attributes"in r&&(!Xr(r.attributes)||r.attributes===null))throw new Ie("Graph.import: invalid attributes. Attributes should be a plain object, null or omitted.")}function mS(r){if(!Xr(r))throw new Ie('Graph.import: invalid serialized edge. A serialized edge should be a plain object with at least a "source" & "target" property.');if(!("source"in r))throw new Ie("Graph.import: serialized edge is missing its source.");if(!("target"in r))throw new Ie("Graph.import: serialized edge is missing its target.");if("attributes"in r&&(!Xr(r.attributes)||r.attributes===null))throw new Ie("Graph.import: invalid attributes. Attributes should be a plain object, null or omitted.");if("undirected"in r&&typeof r.undirected!="boolean")throw new Ie("Graph.import: invalid undirectedness information. Undirected should be boolean or omitted.")}var yS=vx(),_S=new Set(["directed","undirected","mixed"]),xd=new Set(["domain","_events","_eventsCount","_maxListeners"]),vS=[{name:r=>`${r}Edge`,generateKey:!0},{name:r=>`${r}DirectedEdge`,generateKey:!0,type:"directed"},{name:r=>`${r}UndirectedEdge`,generateKey:!0,type:"undirected"},{name:r=>`${r}EdgeWithKey`},{name:r=>`${r}DirectedEdgeWithKey`,type:"directed"},{name:r=>`${r}UndirectedEdgeWithKey`,type:"undirected"}],wS={allowSelfLoops:!0,multi:!1,type:"mixed"};function qS(r,e,t){if(t&&!Xr(t))throw new Ie(`Graph.addNode: invalid attributes. Expecting an object but got "${t}"`);if(e=""+e,t=t||{},r._nodes.has(e))throw new Pe(`Graph.addNode: the "${e}" node already exist in the graph.`);let i=new r.NodeDataClass(e,t);return r._nodes.set(e,i),r.emit("nodeAdded",{key:e,attributes:t}),i}function Sd(r,e,t){let i=new r.NodeDataClass(e,t);return r._nodes.set(e,i),r.emit("nodeAdded",{key:e,attributes:t}),i}function Dd(r,e,t,i,n,o,s,a){if(!i&&r.type==="undirected")throw new Pe(`Graph.${e}: you cannot add a directed edge to an undirected graph. Use the #.addEdge or #.addUndirectedEdge instead.`);if(i&&r.type==="directed")throw new Pe(`Graph.${e}: you cannot add an undirected edge to a directed graph. Use the #.addEdge or #.addDirectedEdge instead.`);if(a&&!Xr(a))throw new Ie(`Graph.${e}: invalid attributes. Expecting an object but got "${a}"`);if(o=""+o,s=""+s,a=a||{},!r.allowSelfLoops&&o===s)throw new Pe(`Graph.${e}: source & target are the same ("${o}"), thus creating a loop explicitly forbidden by this graph 'allowSelfLoops' option set to false.`);let h=r._nodes.get(o),f=r._nodes.get(s);if(!h)throw new we(`Graph.${e}: source node "${o}" not found.`);if(!f)throw new we(`Graph.${e}: target node "${s}" not found.`);let l={key:null,undirected:i,source:o,target:s,attributes:a};if(t)n=r._edgeKeyGenerator();else if(n=""+n,r._edges.has(n))throw new Pe(`Graph.${e}: the "${n}" edge already exists in the graph.`);if(!r.multi&&(i?typeof h.undirected[s]<"u":typeof h.out[s]<"u"))throw new Pe(`Graph.${e}: an edge linking "${o}" to "${s}" already exists. If you really want to add multiple edges linking those nodes, you should create a multi graph by using the 'multi' option.`);let g=new ji(i,n,h,f,a);r._edges.set(n,g);let m=o===s;return i?(h.undirectedDegree++,f.undirectedDegree++,m&&(h.undirectedLoops++,r._undirectedSelfLoopCount++)):(h.outDegree++,f.inDegree++,m&&(h.directedLoops++,r._directedSelfLoopCount++)),r.multi?g.attachMulti():g.attach(),i?r._undirectedSize++:r._directedSize++,l.key=n,r.emit("edgeAdded",l),n}function bS(r,e,t,i,n,o,s,a,h){if(!i&&r.type==="undirected")throw new Pe(`Graph.${e}: you cannot merge/update a directed edge to an undirected graph. Use the #.mergeEdge/#.updateEdge or #.addUndirectedEdge instead.`);if(i&&r.type==="directed")throw new Pe(`Graph.${e}: you cannot merge/update an undirected edge to a directed graph. Use the #.mergeEdge/#.updateEdge or #.addDirectedEdge instead.`);if(a){if(h){if(typeof a!="function")throw new Ie(`Graph.${e}: invalid updater function. Expecting a function but got "${a}"`)}else if(!Xr(a))throw new Ie(`Graph.${e}: invalid attributes. Expecting an object but got "${a}"`)}o=""+o,s=""+s;let f;if(h&&(f=a,a=void 0),!r.allowSelfLoops&&o===s)throw new Pe(`Graph.${e}: source & target are the same ("${o}"), thus creating a loop explicitly forbidden by this graph 'allowSelfLoops' option set to false.`);let l=r._nodes.get(o),g=r._nodes.get(s),m,_;if(!t&&(m=r._edges.get(n),m)){if((m.source.key!==o||m.target.key!==s)&&(!i||m.source.key!==s||m.target.key!==o))throw new Pe(`Graph.${e}: inconsistency detected when attempting to merge the "${n}" edge with "${o}" source & "${s}" target vs. ("${m.source.key}", "${m.target.key}").`);_=m}if(!_&&!r.multi&&l&&(_=i?l.undirected[s]:l.out[s]),_){let S=[_.key,!1,!1,!1];if(h?!f:!a)return S;if(h){let I=_.attributes;_.attributes=f(I),r.emit("edgeAttributesUpdated",{type:"replace",key:_.key,attributes:_.attributes})}else Fr(_.attributes,a),r.emit("edgeAttributesUpdated",{type:"merge",key:_.key,attributes:_.attributes,data:a});return S}a=a||{},h&&f&&(a=f(a));let E={key:null,undirected:i,source:o,target:s,attributes:a};if(t)n=r._edgeKeyGenerator();else if(n=""+n,r._edges.has(n))throw new Pe(`Graph.${e}: the "${n}" edge already exists in the graph.`);let q=!1,x=!1;l||(l=Sd(r,o,{}),q=!0,o===s&&(g=l,x=!0)),g||(g=Sd(r,s,{}),x=!0),m=new ji(i,n,l,g,a),r._edges.set(n,m);let A=o===s;return i?(l.undirectedDegree++,g.undirectedDegree++,A&&(l.undirectedLoops++,r._undirectedSelfLoopCount++)):(l.outDegree++,g.inDegree++,A&&(l.directedLoops++,r._directedSelfLoopCount++)),r.multi?m.attachMulti():m.attach(),i?r._undirectedSize++:r._directedSize++,E.key=n,r.emit("edgeAdded",E),[n,!0,q,x]}function Mi(r,e){r._edges.delete(e.key);let{source:t,target:i,attributes:n}=e,o=e.undirected,s=t===i;o?(t.undirectedDegree--,i.undirectedDegree--,s&&(t.undirectedLoops--,r._undirectedSelfLoopCount--)):(t.outDegree--,i.inDegree--,s&&(t.directedLoops--,r._directedSelfLoopCount--)),r.multi?e.detachMulti():e.detach(),o?r._undirectedSize--:r._directedSize--,r.emit("edgeDropped",{key:e.key,attributes:n,source:t.key,target:i.key,undirected:o})}var fr=class r extends Id.EventEmitter{constructor(e){if(super(),e=Fr({},wS,e),typeof e.multi!="boolean")throw new Ie(`Graph.constructor: invalid 'multi' option. Expecting a boolean but got "${e.multi}".`);if(!_S.has(e.type))throw new Ie(`Graph.constructor: invalid 'type' option. Should be one of "mixed", "directed" or "undirected" but got "${e.type}".`);if(typeof e.allowSelfLoops!="boolean")throw new Ie(`Graph.constructor: invalid 'allowSelfLoops' option. Expecting a boolean but got "${e.allowSelfLoops}".`);let t=e.type==="mixed"?Rd:e.type==="directed"?Cd:Td;mt(this,"NodeDataClass",t);let i="geid_"+yS()+"_",n=0,o=()=>{let s;do s=i+n++;while(this._edges.has(s));return s};mt(this,"_attributes",{}),mt(this,"_nodes",new Map),mt(this,"_edges",new Map),mt(this,"_directedSize",0),mt(this,"_undirectedSize",0),mt(this,"_directedSelfLoopCount",0),mt(this,"_undirectedSelfLoopCount",0),mt(this,"_edgeKeyGenerator",o),mt(this,"_options",e),xd.forEach(s=>mt(this,s,this[s])),Rt(this,"order",()=>this._nodes.size),Rt(this,"size",()=>this._edges.size),Rt(this,"directedSize",()=>this._directedSize),Rt(this,"undirectedSize",()=>this._undirectedSize),Rt(this,"selfLoopCount",()=>this._directedSelfLoopCount+this._undirectedSelfLoopCount),Rt(this,"directedSelfLoopCount",()=>this._directedSelfLoopCount),Rt(this,"undirectedSelfLoopCount",()=>this._undirectedSelfLoopCount),Rt(this,"multi",this._options.multi),Rt(this,"type",this._options.type),Rt(this,"allowSelfLoops",this._options.allowSelfLoops),Rt(this,"implementation",()=>"graphology")}_resetInstanceCounters(){this._directedSize=0,this._undirectedSize=0,this._directedSelfLoopCount=0,this._undirectedSelfLoopCount=0}hasNode(e){return this._nodes.has(""+e)}hasDirectedEdge(e,t){if(this.type==="undirected")return!1;if(arguments.length===1){let i=""+e,n=this._edges.get(i);return!!n&&!n.undirected}else if(arguments.length===2){e=""+e,t=""+t;let i=this._nodes.get(e);return i?i.out.hasOwnProperty(t):!1}throw new Ie(`Graph.hasDirectedEdge: invalid arity (${arguments.length}, instead of 1 or 2). You can either ask for an edge id or for the existence of an edge between a source & a target.`)}hasUndirectedEdge(e,t){if(this.type==="directed")return!1;if(arguments.length===1){let i=""+e,n=this._edges.get(i);return!!n&&n.undirected}else if(arguments.length===2){e=""+e,t=""+t;let i=this._nodes.get(e);return i?i.undirected.hasOwnProperty(t):!1}throw new Ie(`Graph.hasDirectedEdge: invalid arity (${arguments.length}, instead of 1 or 2). You can either ask for an edge id or for the existence of an edge between a source & a target.`)}hasEdge(e,t){if(arguments.length===1){let i=""+e;return this._edges.has(i)}else if(arguments.length===2){e=""+e,t=""+t;let i=this._nodes.get(e);return i?typeof i.out<"u"&&i.out.hasOwnProperty(t)||typeof i.undirected<"u"&&i.undirected.hasOwnProperty(t):!1}throw new Ie(`Graph.hasEdge: invalid arity (${arguments.length}, instead of 1 or 2). You can either ask for an edge id or for the existence of an edge between a source & a target.`)}directedEdge(e,t){if(this.type==="undirected")return;if(e=""+e,t=""+t,this.multi)throw new Pe("Graph.directedEdge: this method is irrelevant with multigraphs since there might be multiple edges between source & target. See #.directedEdges instead.");let i=this._nodes.get(e);if(!i)throw new we(`Graph.directedEdge: could not find the "${e}" source node in the graph.`);if(!this._nodes.has(t))throw new we(`Graph.directedEdge: could not find the "${t}" target node in the graph.`);let n=i.out&&i.out[t]||void 0;if(n)return n.key}undirectedEdge(e,t){if(this.type==="directed")return;if(e=""+e,t=""+t,this.multi)throw new Pe("Graph.undirectedEdge: this method is irrelevant with multigraphs since there might be multiple edges between source & target. See #.undirectedEdges instead.");let i=this._nodes.get(e);if(!i)throw new we(`Graph.undirectedEdge: could not find the "${e}" source node in the graph.`);if(!this._nodes.has(t))throw new we(`Graph.undirectedEdge: could not find the "${t}" target node in the graph.`);let n=i.undirected&&i.undirected[t]||void 0;if(n)return n.key}edge(e,t){if(this.multi)throw new Pe("Graph.edge: this method is irrelevant with multigraphs since there might be multiple edges between source & target. See #.edges instead.");e=""+e,t=""+t;let i=this._nodes.get(e);if(!i)throw new we(`Graph.edge: could not find the "${e}" source node in the graph.`);if(!this._nodes.has(t))throw new we(`Graph.edge: could not find the "${t}" target node in the graph.`);let n=i.out&&i.out[t]||i.undirected&&i.undirected[t]||void 0;if(n)return n.key}areDirectedNeighbors(e,t){e=""+e,t=""+t;let i=this._nodes.get(e);if(!i)throw new we(`Graph.areDirectedNeighbors: could not find the "${e}" node in the graph.`);return this.type==="undirected"?!1:t in i.in||t in i.out}areOutNeighbors(e,t){e=""+e,t=""+t;let i=this._nodes.get(e);if(!i)throw new we(`Graph.areOutNeighbors: could not find the "${e}" node in the graph.`);return this.type==="undirected"?!1:t in i.out}areInNeighbors(e,t){e=""+e,t=""+t;let i=this._nodes.get(e);if(!i)throw new we(`Graph.areInNeighbors: could not find the "${e}" node in the graph.`);return this.type==="undirected"?!1:t in i.in}areUndirectedNeighbors(e,t){e=""+e,t=""+t;let i=this._nodes.get(e);if(!i)throw new we(`Graph.areUndirectedNeighbors: could not find the "${e}" node in the graph.`);return this.type==="directed"?!1:t in i.undirected}areNeighbors(e,t){e=""+e,t=""+t;let i=this._nodes.get(e);if(!i)throw new we(`Graph.areNeighbors: could not find the "${e}" node in the graph.`);return this.type!=="undirected"&&(t in i.in||t in i.out)||this.type!=="directed"&&t in i.undirected}areInboundNeighbors(e,t){e=""+e,t=""+t;let i=this._nodes.get(e);if(!i)throw new we(`Graph.areInboundNeighbors: could not find the "${e}" node in the graph.`);return this.type!=="undirected"&&t in i.in||this.type!=="directed"&&t in i.undirected}areOutboundNeighbors(e,t){e=""+e,t=""+t;let i=this._nodes.get(e);if(!i)throw new we(`Graph.areOutboundNeighbors: could not find the "${e}" node in the graph.`);return this.type!=="undirected"&&t in i.out||this.type!=="directed"&&t in i.undirected}inDegree(e){e=""+e;let t=this._nodes.get(e);if(!t)throw new we(`Graph.inDegree: could not find the "${e}" node in the graph.`);return this.type==="undirected"?0:t.inDegree}outDegree(e){e=""+e;let t=this._nodes.get(e);if(!t)throw new we(`Graph.outDegree: could not find the "${e}" node in the graph.`);return this.type==="undirected"?0:t.outDegree}directedDegree(e){e=""+e;let t=this._nodes.get(e);if(!t)throw new we(`Graph.directedDegree: could not find the "${e}" node in the graph.`);return this.type==="undirected"?0:t.inDegree+t.outDegree}undirectedDegree(e){e=""+e;let t=this._nodes.get(e);if(!t)throw new we(`Graph.undirectedDegree: could not find the "${e}" node in the graph.`);return this.type==="directed"?0:t.undirectedDegree}inboundDegree(e){e=""+e;let t=this._nodes.get(e);if(!t)throw new we(`Graph.inboundDegree: could not find the "${e}" node in the graph.`);let i=0;return this.type!=="directed"&&(i+=t.undirectedDegree),this.type!=="undirected"&&(i+=t.inDegree),i}outboundDegree(e){e=""+e;let t=this._nodes.get(e);if(!t)throw new we(`Graph.outboundDegree: could not find the "${e}" node in the graph.`);let i=0;return this.type!=="directed"&&(i+=t.undirectedDegree),this.type!=="undirected"&&(i+=t.outDegree),i}degree(e){e=""+e;let t=this._nodes.get(e);if(!t)throw new we(`Graph.degree: could not find the "${e}" node in the graph.`);let i=0;return this.type!=="directed"&&(i+=t.undirectedDegree),this.type!=="undirected"&&(i+=t.inDegree+t.outDegree),i}inDegreeWithoutSelfLoops(e){e=""+e;let t=this._nodes.get(e);if(!t)throw new we(`Graph.inDegreeWithoutSelfLoops: could not find the "${e}" node in the graph.`);return this.type==="undirected"?0:t.inDegree-t.directedLoops}outDegreeWithoutSelfLoops(e){e=""+e;let t=this._nodes.get(e);if(!t)throw new we(`Graph.outDegreeWithoutSelfLoops: could not find the "${e}" node in the graph.`);return this.type==="undirected"?0:t.outDegree-t.directedLoops}directedDegreeWithoutSelfLoops(e){e=""+e;let t=this._nodes.get(e);if(!t)throw new we(`Graph.directedDegreeWithoutSelfLoops: could not find the "${e}" node in the graph.`);return this.type==="undirected"?0:t.inDegree+t.outDegree-t.directedLoops*2}undirectedDegreeWithoutSelfLoops(e){e=""+e;let t=this._nodes.get(e);if(!t)throw new we(`Graph.undirectedDegreeWithoutSelfLoops: could not find the "${e}" node in the graph.`);return this.type==="directed"?0:t.undirectedDegree-t.undirectedLoops*2}inboundDegreeWithoutSelfLoops(e){e=""+e;let t=this._nodes.get(e);if(!t)throw new we(`Graph.inboundDegreeWithoutSelfLoops: could not find the "${e}" node in the graph.`);let i=0,n=0;return this.type!=="directed"&&(i+=t.undirectedDegree,n+=t.undirectedLoops*2),this.type!=="undirected"&&(i+=t.inDegree,n+=t.directedLoops),i-n}outboundDegreeWithoutSelfLoops(e){e=""+e;let t=this._nodes.get(e);if(!t)throw new we(`Graph.outboundDegreeWithoutSelfLoops: could not find the "${e}" node in the graph.`);let i=0,n=0;return this.type!=="directed"&&(i+=t.undirectedDegree,n+=t.undirectedLoops*2),this.type!=="undirected"&&(i+=t.outDegree,n+=t.directedLoops),i-n}degreeWithoutSelfLoops(e){e=""+e;let t=this._nodes.get(e);if(!t)throw new we(`Graph.degreeWithoutSelfLoops: could not find the "${e}" node in the graph.`);let i=0,n=0;return this.type!=="directed"&&(i+=t.undirectedDegree,n+=t.undirectedLoops*2),this.type!=="undirected"&&(i+=t.inDegree+t.outDegree,n+=t.directedLoops*2),i-n}source(e){e=""+e;let t=this._edges.get(e);if(!t)throw new we(`Graph.source: could not find the "${e}" edge in the graph.`);return t.source.key}target(e){e=""+e;let t=this._edges.get(e);if(!t)throw new we(`Graph.target: could not find the "${e}" edge in the graph.`);return t.target.key}extremities(e){e=""+e;let t=this._edges.get(e);if(!t)throw new we(`Graph.extremities: could not find the "${e}" edge in the graph.`);return[t.source.key,t.target.key]}opposite(e,t){e=""+e,t=""+t;let i=this._edges.get(t);if(!i)throw new we(`Graph.opposite: could not find the "${t}" edge in the graph.`);let n=i.source.key,o=i.target.key;if(e===n)return o;if(e===o)return n;throw new we(`Graph.opposite: the "${e}" node is not attached to the "${t}" edge (${n}, ${o}).`)}hasExtremity(e,t){e=""+e,t=""+t;let i=this._edges.get(e);if(!i)throw new we(`Graph.hasExtremity: could not find the "${e}" edge in the graph.`);return i.source.key===t||i.target.key===t}isUndirected(e){e=""+e;let t=this._edges.get(e);if(!t)throw new we(`Graph.isUndirected: could not find the "${e}" edge in the graph.`);return t.undirected}isDirected(e){e=""+e;let t=this._edges.get(e);if(!t)throw new we(`Graph.isDirected: could not find the "${e}" edge in the graph.`);return!t.undirected}isSelfLoop(e){e=""+e;let t=this._edges.get(e);if(!t)throw new we(`Graph.isSelfLoop: could not find the "${e}" edge in the graph.`);return t.source===t.target}addNode(e,t){return qS(this,e,t).key}mergeNode(e,t){if(t&&!Xr(t))throw new Ie(`Graph.mergeNode: invalid attributes. Expecting an object but got "${t}"`);e=""+e,t=t||{};let i=this._nodes.get(e);return i?(t&&(Fr(i.attributes,t),this.emit("nodeAttributesUpdated",{type:"merge",key:e,attributes:i.attributes,data:t})),[e,!1]):(i=new this.NodeDataClass(e,t),this._nodes.set(e,i),this.emit("nodeAdded",{key:e,attributes:t}),[e,!0])}updateNode(e,t){if(t&&typeof t!="function")throw new Ie(`Graph.updateNode: invalid updater function. Expecting a function but got "${t}"`);e=""+e;let i=this._nodes.get(e);if(i){if(t){let o=i.attributes;i.attributes=t(o),this.emit("nodeAttributesUpdated",{type:"replace",key:e,attributes:i.attributes})}return[e,!1]}let n=t?t({}):{};return i=new this.NodeDataClass(e,n),this._nodes.set(e,i),this.emit("nodeAdded",{key:e,attributes:n}),[e,!0]}dropNode(e){e=""+e;let t=this._nodes.get(e);if(!t)throw new we(`Graph.dropNode: could not find the "${e}" node in the graph.`);let i;if(this.type!=="undirected"){for(let n in t.out){i=t.out[n];do Mi(this,i),i=i.next;while(i)}for(let n in t.in){i=t.in[n];do Mi(this,i),i=i.next;while(i)}}if(this.type!=="directed")for(let n in t.undirected){i=t.undirected[n];do Mi(this,i),i=i.next;while(i)}this._nodes.delete(e),this.emit("nodeDropped",{key:e,attributes:t.attributes})}dropEdge(e){let t;if(arguments.length>1){let i=""+arguments[0],n=""+arguments[1];if(t=yt(this,i,n,this.type),!t)throw new we(`Graph.dropEdge: could not find the "${i}" -> "${n}" edge in the graph.`)}else if(e=""+e,t=this._edges.get(e),!t)throw new we(`Graph.dropEdge: could not find the "${e}" edge in the graph.`);return Mi(this,t),this}dropDirectedEdge(e,t){if(arguments.length<2)throw new Pe("Graph.dropDirectedEdge: it does not make sense to try and drop a directed edge by key. What if the edge with this key is undirected? Use #.dropEdge for this purpose instead.");if(this.multi)throw new Pe("Graph.dropDirectedEdge: cannot use a {source,target} combo when dropping an edge in a MultiGraph since we cannot infer the one you want to delete as there could be multiple ones.");e=""+e,t=""+t;let i=yt(this,e,t,"directed");if(!i)throw new we(`Graph.dropDirectedEdge: could not find a "${e}" -> "${t}" edge in the graph.`);return Mi(this,i),this}dropUndirectedEdge(e,t){if(arguments.length<2)throw new Pe("Graph.dropUndirectedEdge: it does not make sense to drop a directed edge by key. What if the edge with this key is undirected? Use #.dropEdge for this purpose instead.");if(this.multi)throw new Pe("Graph.dropUndirectedEdge: cannot use a {source,target} combo when dropping an edge in a MultiGraph since we cannot infer the one you want to delete as there could be multiple ones.");let i=yt(this,e,t,"undirected");if(!i)throw new we(`Graph.dropUndirectedEdge: could not find a "${e}" -> "${t}" edge in the graph.`);return Mi(this,i),this}clear(){this._edges.clear(),this._nodes.clear(),this._resetInstanceCounters(),this.emit("cleared")}clearEdges(){let e=this._nodes.values(),t;for(;t=e.next(),t.done!==!0;)t.value.clear();this._edges.clear(),this._resetInstanceCounters(),this.emit("edgesCleared")}getAttribute(e){return this._attributes[e]}getAttributes(){return this._attributes}hasAttribute(e){return this._attributes.hasOwnProperty(e)}setAttribute(e,t){return this._attributes[e]=t,this.emit("attributesUpdated",{type:"set",attributes:this._attributes,name:e}),this}updateAttribute(e,t){if(typeof t!="function")throw new Ie("Graph.updateAttribute: updater should be a function.");let i=this._attributes[e];return this._attributes[e]=t(i),this.emit("attributesUpdated",{type:"set",attributes:this._attributes,name:e}),this}removeAttribute(e){return delete this._attributes[e],this.emit("attributesUpdated",{type:"remove",attributes:this._attributes,name:e}),this}replaceAttributes(e){if(!Xr(e))throw new Ie("Graph.replaceAttributes: provided attributes are not a plain object.");return this._attributes=e,this.emit("attributesUpdated",{type:"replace",attributes:this._attributes}),this}mergeAttributes(e){if(!Xr(e))throw new Ie("Graph.mergeAttributes: provided attributes are not a plain object.");return Fr(this._attributes,e),this.emit("attributesUpdated",{type:"merge",attributes:this._attributes,data:e}),this}updateAttributes(e){if(typeof e!="function")throw new Ie("Graph.updateAttributes: provided updater is not a function.");return this._attributes=e(this._attributes),this.emit("attributesUpdated",{type:"update",attributes:this._attributes}),this}updateEachNodeAttributes(e,t){if(typeof e!="function")throw new Ie("Graph.updateEachNodeAttributes: expecting an updater function.");if(t&&!Ed(t))throw new Ie("Graph.updateEachNodeAttributes: invalid hints. Expecting an object having the following shape: {attributes?: [string]}");let i=this._nodes.values(),n,o;for(;n=i.next(),n.done!==!0;)o=n.value,o.attributes=e(o.key,o.attributes);this.emit("eachNodeAttributesUpdated",{hints:t||null})}updateEachEdgeAttributes(e,t){if(typeof e!="function")throw new Ie("Graph.updateEachEdgeAttributes: expecting an updater function.");if(t&&!Ed(t))throw new Ie("Graph.updateEachEdgeAttributes: invalid hints. Expecting an object having the following shape: {attributes?: [string]}");let i=this._edges.values(),n,o,s,a;for(;n=i.next(),n.done!==!0;)o=n.value,s=o.source,a=o.target,o.attributes=e(o.key,o.attributes,s.key,a.key,s.attributes,a.attributes,o.undirected);this.emit("eachEdgeAttributesUpdated",{hints:t||null})}forEachAdjacencyEntry(e){if(typeof e!="function")throw new Ie("Graph.forEachAdjacencyEntry: expecting a callback.");Bn(!1,!1,!1,this,e)}forEachAdjacencyEntryWithOrphans(e){if(typeof e!="function")throw new Ie("Graph.forEachAdjacencyEntryWithOrphans: expecting a callback.");Bn(!1,!1,!0,this,e)}forEachAssymetricAdjacencyEntry(e){if(typeof e!="function")throw new Ie("Graph.forEachAssymetricAdjacencyEntry: expecting a callback.");Bn(!1,!0,!1,this,e)}forEachAssymetricAdjacencyEntryWithOrphans(e){if(typeof e!="function")throw new Ie("Graph.forEachAssymetricAdjacencyEntryWithOrphans: expecting a callback.");Bn(!1,!0,!0,this,e)}nodes(){return Array.from(this._nodes.keys())}forEachNode(e){if(typeof e!="function")throw new Ie("Graph.forEachNode: expecting a callback.");let t=this._nodes.values(),i,n;for(;i=t.next(),i.done!==!0;)n=i.value,e(n.key,n.attributes)}findNode(e){if(typeof e!="function")throw new Ie("Graph.findNode: expecting a callback.");let t=this._nodes.values(),i,n;for(;i=t.next(),i.done!==!0;)if(n=i.value,e(n.key,n.attributes))return n.key}mapNodes(e){if(typeof e!="function")throw new Ie("Graph.mapNode: expecting a callback.");let t=this._nodes.values(),i,n,o=new Array(this.order),s=0;for(;i=t.next(),i.done!==!0;)n=i.value,o[s++]=e(n.key,n.attributes);return o}someNode(e){if(typeof e!="function")throw new Ie("Graph.someNode: expecting a callback.");let t=this._nodes.values(),i,n;for(;i=t.next(),i.done!==!0;)if(n=i.value,e(n.key,n.attributes))return!0;return!1}everyNode(e){if(typeof e!="function")throw new Ie("Graph.everyNode: expecting a callback.");let t=this._nodes.values(),i,n;for(;i=t.next(),i.done!==!0;)if(n=i.value,!e(n.key,n.attributes))return!1;return!0}filterNodes(e){if(typeof e!="function")throw new Ie("Graph.filterNodes: expecting a callback.");let t=this._nodes.values(),i,n,o=[];for(;i=t.next(),i.done!==!0;)n=i.value,e(n.key,n.attributes)&&o.push(n.key);return o}reduceNodes(e,t){if(typeof e!="function")throw new Ie("Graph.reduceNodes: expecting a callback.");if(arguments.length<2)throw new Ie("Graph.reduceNodes: missing initial value. You must provide it because the callback takes more than one argument and we cannot infer the initial value from the first iteration, as you could with a simple array.");let i=t,n=this._nodes.values(),o,s;for(;o=n.next(),o.done!==!0;)s=o.value,i=e(i,s.key,s.attributes);return i}nodeEntries(){let e=this._nodes.values();return{[Symbol.iterator](){return this},next(){let t=e.next();if(t.done)return t;let i=t.value;return{value:{node:i.key,attributes:i.attributes},done:!1}}}}export(){let e=new Array(this._nodes.size),t=0;this._nodes.forEach((n,o)=>{e[t++]=dS(o,n)});let i=new Array(this._edges.size);return t=0,this._edges.forEach((n,o)=>{i[t++]=pS(this.type,o,n)}),{options:{type:this.type,multi:this.multi,allowSelfLoops:this.allowSelfLoops},attributes:this.getAttributes(),nodes:e,edges:i}}import(e,t=!1){if(e instanceof r)return e.forEachNode((h,f)=>{t?this.mergeNode(h,f):this.addNode(h,f)}),e.forEachEdge((h,f,l,g,m,_,E)=>{t?E?this.mergeUndirectedEdgeWithKey(h,l,g,f):this.mergeDirectedEdgeWithKey(h,l,g,f):E?this.addUndirectedEdgeWithKey(h,l,g,f):this.addDirectedEdgeWithKey(h,l,g,f)}),this;if(!Xr(e))throw new Ie("Graph.import: invalid argument. Expecting a serialized graph or, alternatively, a Graph instance.");if(e.attributes){if(!Xr(e.attributes))throw new Ie("Graph.import: invalid attributes. Expecting a plain object.");t?this.mergeAttributes(e.attributes):this.replaceAttributes(e.attributes)}let i,n,o,s,a;if(e.nodes){if(o=e.nodes,!Array.isArray(o))throw new Ie("Graph.import: invalid nodes. Expecting an array.");for(i=0,n=o.length;i{let o=Fr({},i.attributes);i=new t.NodeDataClass(n,o),t._nodes.set(n,i)}),t}copy(e){if(e=e||{},typeof e.type=="string"&&e.type!==this.type&&e.type!=="mixed")throw new Pe(`Graph.copy: cannot create an incompatible copy from "${this.type}" type to "${e.type}" because this would mean losing information about the current graph.`);if(typeof e.multi=="boolean"&&e.multi!==this.multi&&e.multi!==!0)throw new Pe("Graph.copy: cannot create an incompatible copy by downgrading a multi graph to a simple one because this would mean losing information about the current graph.");if(typeof e.allowSelfLoops=="boolean"&&e.allowSelfLoops!==this.allowSelfLoops&&e.allowSelfLoops!==!0)throw new Pe("Graph.copy: cannot create an incompatible copy from a graph allowing self loops to one that does not because this would mean losing information about the current graph.");let t=this.emptyCopy(e),i=this._edges.values(),n,o;for(;n=i.next(),n.done!==!0;)o=n.value,Dd(t,"copy",!1,o.undirected,o.key,o.source.key,o.target.key,Fr({},o.attributes));return t}toJSON(){return this.export()}toString(){return"[object Graph]"}inspect(){let e={};this._nodes.forEach((o,s)=>{e[s]=o.attributes});let t={},i={};this._edges.forEach((o,s)=>{let a=o.undirected?"--":"->",h="",f=o.source.key,l=o.target.key,g;o.undirected&&f>l&&(g=f,f=l,l=g);let m=`(${f})${a}(${l})`;s.startsWith("geid_")?this.multi&&(typeof i[m]>"u"?i[m]=0:i[m]++,h+=`${i[m]}. `):h+=`[${s}]: `,h+=m,t[h]=o.attributes});let n={};for(let o in this)this.hasOwnProperty(o)&&!xd.has(o)&&typeof this[o]!="function"&&typeof o!="symbol"&&(n[o]=this[o]);return n.attributes=this._attributes,n.nodes=e,n.edges=t,mt(n,"constructor",this.constructor),n}};typeof Symbol<"u"&&(fr.prototype[Symbol.for("nodejs.util.inspect.custom")]=fr.prototype.inspect);vS.forEach(r=>{["add","merge","update"].forEach(e=>{let t=r.name(e),i=e==="add"?Dd:bS;r.generateKey?fr.prototype[t]=function(n,o,s){return i(this,t,!0,(r.type||this.type)==="undirected",null,n,o,s,e==="update")}:fr.prototype[t]=function(n,o,s,a){return i(this,t,!1,(r.type||this.type)==="undirected",n,o,s,a,e==="update")}})});Ox(fr);$x(fr);nS(fr);lS(fr);var Vn=class extends fr{constructor(e){let t=Fr({type:"directed"},e);if("multi"in t&&t.multi!==!1)throw new Ie("DirectedGraph.from: inconsistent indication that the graph should be multi in given options!");if(t.type!=="directed")throw new Ie('DirectedGraph.from: inconsistent "'+t.type+'" type in given options!');super(t)}},Kn=class extends fr{constructor(e){let t=Fr({type:"undirected"},e);if("multi"in t&&t.multi!==!1)throw new Ie("UndirectedGraph.from: inconsistent indication that the graph should be multi in given options!");if(t.type!=="undirected")throw new Ie('UndirectedGraph.from: inconsistent "'+t.type+'" type in given options!');super(t)}},Yn=class extends fr{constructor(e){let t=Fr({multi:!0},e);if("multi"in t&&t.multi!==!0)throw new Ie("MultiGraph.from: inconsistent indication that the graph should be simple in given options!");super(t)}},Xn=class extends fr{constructor(e){let t=Fr({type:"directed",multi:!0},e);if("multi"in t&&t.multi!==!0)throw new Ie("MultiDirectedGraph.from: inconsistent indication that the graph should be simple in given options!");if(t.type!=="directed")throw new Ie('MultiDirectedGraph.from: inconsistent "'+t.type+'" type in given options!');super(t)}},Qn=class extends fr{constructor(e){let t=Fr({type:"undirected",multi:!0},e);if("multi"in t&&t.multi!==!0)throw new Ie("MultiUndirectedGraph.from: inconsistent indication that the graph should be simple in given options!");if(t.type!=="undirected")throw new Ie('MultiUndirectedGraph.from: inconsistent "'+t.type+'" type in given options!');super(t)}};function Pi(r){r.from=function(e,t){let i=Fr({},e.options,t),n=new r(i);return n.import(e),n}}Pi(fr);Pi(Vn);Pi(Kn);Pi(Yn);Pi(Xn);Pi(Qn);fr.Graph=fr;fr.DirectedGraph=Vn;fr.UndirectedGraph=Kn;fr.MultiGraph=Yn;fr.MultiDirectedGraph=Xn;fr.MultiUndirectedGraph=Qn;fr.InvalidArgumentsGraphError=Ie;fr.NotFoundGraphError=we;fr.UsageGraphError=Pe;var zs=et(mp(),1),JR=et(Ap(),1),HR=et(Op(),1),eC=et(zp(),1);function st(r,e,t,i){function n(o){return o instanceof t?o:new t(function(s){s(o)})}return new(t||(t=Promise))(function(o,s){function a(l){try{f(i.next(l))}catch(g){s(g)}}function h(l){try{f(i.throw(l))}catch(g){s(g)}}function f(l){l.done?o(l.value):n(l.value).then(a,h)}f((i=i.apply(r,e||[])).next())})}var cI={abs:Math.abs,ceil:Math.ceil,floor:Math.floor,max:Math.max,min:Math.min,round:Math.round,sqrt:Math.sqrt,pow:Math.pow},Sr=class extends Error{constructor(e,t,i){super(e),this.position=t,this.token=i,this.name="ExpressionError"}},We;(function(r){r[r.STRING=0]="STRING",r[r.NUMBER=1]="NUMBER",r[r.BOOLEAN=2]="BOOLEAN",r[r.NULL=3]="NULL",r[r.IDENTIFIER=4]="IDENTIFIER",r[r.OPERATOR=5]="OPERATOR",r[r.FUNCTION=6]="FUNCTION",r[r.DOT=7]="DOT",r[r.BRACKET_LEFT=8]="BRACKET_LEFT",r[r.BRACKET_RIGHT=9]="BRACKET_RIGHT",r[r.PAREN_LEFT=10]="PAREN_LEFT",r[r.PAREN_RIGHT=11]="PAREN_RIGHT",r[r.COMMA=12]="COMMA",r[r.QUESTION=13]="QUESTION",r[r.COLON=14]="COLON",r[r.DOLLAR=15]="DOLLAR"})(We||(We={}));var lI=new Set([32,9,10,13]),dI=new Set([43,45,42,47,37,33,38,124,61,60,62]),pI=new Map([["true",We.BOOLEAN],["false",We.BOOLEAN],["null",We.NULL]]),ia=new Map([["===",!0],["!==",!0],["<=",!0],[">=",!0],["&&",!0],["||",!0],["+",!0],["-",!0],["*",!0],["/",!0],["%",!0],["!",!0],["<",!0],[">",!0]]),gI=new Map([[46,We.DOT],[91,We.BRACKET_LEFT],[93,We.BRACKET_RIGHT],[40,We.PAREN_LEFT],[41,We.PAREN_RIGHT],[44,We.COMMA],[63,We.QUESTION],[58,We.COLON],[36,We.DOLLAR]]),Up=new Map;for(let[r,e]of gI.entries())Up.set(r,{type:e,value:String.fromCharCode(r)});function An(r){return r>=48&&r<=57}function na(r){return r>=97&&r<=122||r>=65&&r<=90||r===95}function $p(r){return na(r)||An(r)}function mI(r){return dI.has(r)}var Er;(function(r){r[r.Program=0]="Program",r[r.Literal=1]="Literal",r[r.Identifier=2]="Identifier",r[r.MemberExpression=3]="MemberExpression",r[r.CallExpression=4]="CallExpression",r[r.BinaryExpression=5]="BinaryExpression",r[r.UnaryExpression=6]="UnaryExpression",r[r.ConditionalExpression=7]="ConditionalExpression"})(Er||(Er={}));var yI=new Map([["||",2],["&&",3],["===",4],["!==",4],[">",5],[">=",5],["<",5],["<=",5],["+",6],["-",6],["*",7],["/",7],["%",7],["!",8]]),_I={type:Er.Literal,value:null},vI={type:Er.Literal,value:!0},wI={type:Er.Literal,value:!1},qI=r=>{let e=0,t=r.length,i=()=>e>=t?null:r[e],n=()=>r[e++],o=g=>{let m=i();return m!==null&&m.type===g},s=g=>g.type===We.OPERATOR?yI.get(g.value)||-1:g.type===We.DOT||g.type===We.BRACKET_LEFT?9:g.type===We.QUESTION?1:-1,a=g=>{let m,_;if(n().type===We.DOT){if(!o(We.IDENTIFIER)){let q=i();throw new Sr("Expected property name",e,q?q.value:"")}let E=n();m={type:Er.Identifier,name:E.value},_=!1}else{if(m=f(0),!o(We.BRACKET_RIGHT)){let E=i();throw new Sr("Expected closing bracket",e,E?E.value:"")}n(),_=!0}return{type:Er.MemberExpression,object:g,property:m,computed:_}},h=()=>{let g=i();if(!g)throw new Sr("Unexpected end of input",e,"");if(g.type===We.OPERATOR&&(g.value==="!"||g.value==="-")){n();let m=h();return{type:Er.UnaryExpression,operator:g.value,argument:m,prefix:!0}}switch(g.type){case We.NUMBER:return n(),{type:Er.Literal,value:Number(g.value)};case We.STRING:return n(),{type:Er.Literal,value:g.value};case We.BOOLEAN:return n(),g.value==="true"?vI:wI;case We.NULL:return n(),_I;case We.IDENTIFIER:return n(),{type:Er.Identifier,name:g.value};case We.FUNCTION:return(()=>{let m=n(),_=[];if(!o(We.PAREN_LEFT)){let E=i();throw new Sr("Expected opening parenthesis after function name",e,E?E.value:"")}for(n();;){if(o(We.PAREN_RIGHT)){n();break}if(!i()){let q=i();throw new Sr("Expected closing parenthesis",e,q?q.value:"")}if(_.length>0){if(!o(We.COMMA)){let q=i();throw new Sr("Expected comma between function arguments",e,q?q.value:"")}n()}let E=f(0);_.push(E)}return{type:Er.CallExpression,callee:{type:Er.Identifier,name:m.value},arguments:_}})();case We.PAREN_LEFT:{n();let m=f(0);if(!o(We.PAREN_RIGHT)){let _=i();throw new Sr("Expected closing parenthesis",e,_?_.value:"")}return n(),m}default:throw new Sr(`Unexpected token: ${g.type}`,e,g.value)}},f=(g=0)=>{let m=h();for(;e")}n();let x=f(0);m={type:Er.ConditionalExpression,test:m,consequent:q,alternate:x}}}return m},l=f();return{type:Er.Program,body:l}},bI=(r,e,t)=>{let i=e;t&&(i={...e,context:{...e.context,...t}});let n=o=>{switch(o.type){case Er.Literal:return(s=>s.value)(o);case Er.Identifier:return(s=>{if(!(s.name in i.context))throw new Sr(`Undefined variable: ${s.name}`);return i.context[s.name]})(o);case Er.MemberExpression:return(s=>{let a=n(s.object);if(a==null)throw new Sr("Cannot access property of null or undefined");return a[s.computed?n(s.property):s.property.name]})(o);case Er.CallExpression:return(s=>{let a=i.functions[s.callee.name];if(!a)throw new Sr(`Undefined function: ${s.callee.name}`);return a(...s.arguments.map((h=>n(h))))})(o);case Er.BinaryExpression:return(s=>{if(s.operator==="&&"){let f=n(s.left);return f&&n(s.right)}if(s.operator==="||")return n(s.left)||n(s.right);let a=n(s.left),h=n(s.right);switch(s.operator){case"+":return a+h;case"-":return a-h;case"*":return a*h;case"/":return a/h;case"%":return a%h;case"===":return a===h;case"!==":return a!==h;case">":return a>h;case">=":return a>=h;case"<":return a{let a=n(s.argument);if(s.prefix)switch(s.operator){case"!":return!a;case"-":if(typeof a!="number")throw new Sr(`Cannot apply unary - to non-number: ${a}`);return-a;default:throw new Sr(`Unknown operator: ${s.operator}`)}throw new Sr(`Postfix operators are not supported: ${s.operator}`)})(o);case Er.ConditionalExpression:return(s=>{let a=n(s.test);return n(a?s.consequent:s.alternate)})(o);default:throw new Sr(`Evaluation error: Unsupported node type: ${o.type}`)}};return n(r.body)};function oa(r){let e=(n=>{let o=n,s=o.length,a=new Array(Math.ceil(s/3)),h=0,f=0;function l(x){let A=f+1;f++;let S="",I=!1;for(;f({context:n,functions:o}))({},cI);return(n={})=>bI(t,i,n)}function Wp(r,e={}){return oa(r)(e)}function Bp(r,e){if(typeof r!="string")return;let t=r.trim();if(t)try{return oa(t),Wp(t,e)}catch{return}}function ri(r){return typeof r=="number"}function zi(r){if(!r)return[0,0,0];if(ri(r))return[r,r,r];if(Array.isArray(r)&&r.length===0)return[0,0,0];let[e,t=e,i=e]=r;return[e,t,i]}function Vp(r){return ri(r)?!0:Array.isArray(r)?r.every(e=>ri(e)):!1}function tt(r){return r==null}function sa(r){return typeof r=="string"}function aa(r){return typeof r=="function"}function ti(r,e){if(typeof r=="function")return r;if(typeof r=="string"){let t=r;return(...i)=>{let n={};for(let o=0;or}function no(r,e,t="node"){if(tt(r))return()=>e;if(sa(r)){let i=ti(r,[t]);return n=>{let o=i(n);return ri(o)?o:e}}return aa(r)?r:ri(r)?()=>r:()=>e}function Rn(r,e=10,t="node"){if(tt(r))return()=>e;if(sa(r)){let i=ti(r,[t]);return n=>{let o=i(n);return Vp(o)?o:e}}return aa(r)?r:ri(r)?()=>r:Array.isArray(r)?()=>r:()=>e}var oo=(r,e,t=10,i=0)=>{let n=Rn(e,i),o=Rn(r,t);return s=>{let[a,h,f]=zi(o(s)),[l,g,m]=zi(n(s));return[a+l,h+g,f+m]}};function Kp(r){var e;return[r.x,r.y,(e=r.z)!==null&&e!==void 0?e:0]}var so=class{constructor(e,t={}){this.edgeIdCounter=new Map,this.nodeMap=SI(e.nodes,t.node),this.edgeMap=II(e.edges||[],t.edge,this.getEdgeId.bind(this))}data(){return{nodes:this.nodeMap,edges:this.edgeMap}}replace(e){this.nodeMap=e.nodes,this.edgeMap=e.edges,this.clearCache()}nodes(){return Array.from(this.nodeMap.values())}node(e){return this.nodeMap.get(e)}nodeAt(e){this.indexNodeCache||this.buildNodeIndexCache();let t=this.indexNodeCache.get(e);return t?this.nodeMap.get(t):void 0}nodeIndexOf(e){var t;return this.nodeIndexCache||this.buildNodeIndexCache(),(t=this.nodeIndexCache.get(e))!==null&&t!==void 0?t:-1}firstNode(){return this.nodeMap.values().next().value}forEachNode(e){let t=0;this.nodeMap.forEach(i=>e(i,t++))}originalNode(e){let t=this.nodeMap.get(e);return t?._original}nodeCount(){return this.nodeMap.size}edges(){return Array.from(this.edgeMap.values())}edge(e){return this.edgeMap.get(e)}firstEdge(){return this.edgeMap.values().next().value}forEachEdge(e){let t=0;this.edgeMap.forEach(i=>e(i,t++))}originalEdge(e){let t=this.edgeMap.get(e);return t?._original}edgeCount(){return this.edgeMap.size}getEdgeId(e){if(e.id)return e.id;let t=`${e.source}-${e.target}`,i=this.edgeIdCounter.get(t)||0,n=i===0?t:`${t}-${i}`;return this.edgeIdCounter.set(t,i+1),n}degree(e,t="both"){this.degreeCache||this.buildDegreeCache();let i=this.degreeCache.get(e);return i?i[t]:0}neighbors(e,t="both"){if((!this.outAdjacencyCache||!this.inAdjacencyCache)&&this.buildAdjacencyCache(),t==="out")return Array.from(this.outAdjacencyCache.get(e)||[]);if(t==="in")return Array.from(this.inAdjacencyCache.get(e)||[]);if(this.bothAdjacencyCache)return Array.from(this.bothAdjacencyCache.get(e)||[]);let i=this.inAdjacencyCache.get(e),n=this.outAdjacencyCache.get(e);if(!i&&!n)return[];if(!i)return Array.from(n);if(!n)return Array.from(i);let o=new Set;return i.forEach(s=>o.add(s)),n.forEach(s=>o.add(s)),Array.from(o)}successors(e){return this.neighbors(e,"out")}predecessors(e){return this.neighbors(e,"in")}setNodeOrder(e){let t=new Map;for(let i of e)t.set(i.id,i);this.nodeMap=t,this.nodeIndexCache=void 0,this.indexNodeCache=void 0}clearCache(){this.degreeCache=void 0,this.inAdjacencyCache=void 0,this.outAdjacencyCache=void 0,this.bothAdjacencyCache=void 0,this.nodeIndexCache=void 0,this.indexNodeCache=void 0}buildDegreeCache(){this.degreeCache=new Map;for(let e of this.edges()){let{source:t,target:i}=e;if(e.source===e.target)continue;this.degreeCache.has(t)||this.degreeCache.set(t,{in:0,out:0,both:0});let n=this.degreeCache.get(e.source);n&&(n.out++,n.both++),this.degreeCache.has(i)||this.degreeCache.set(i,{in:0,out:0,both:0});let o=this.degreeCache.get(e.target);o&&(o.in++,o.both++)}}buildAdjacencyCache(){this.inAdjacencyCache=new Map,this.outAdjacencyCache=new Map;for(let e of this.edges())!this.nodeMap.has(e.source)||!this.nodeMap.has(e.target)||(this.outAdjacencyCache.has(e.source)||this.outAdjacencyCache.set(e.source,new Set),this.outAdjacencyCache.get(e.source).add(e.target),this.inAdjacencyCache.has(e.target)||this.inAdjacencyCache.set(e.target,new Set),this.inAdjacencyCache.get(e.target).add(e.source))}buildNodeIndexCache(){this.nodeIndexCache=new Map,this.indexNodeCache=new Map;let e=0;this.nodeMap.forEach((t,i)=>{this.nodeIndexCache.set(i,e),this.indexNodeCache.set(e,i),e++})}destroy(){this.clearCache(),this.nodeMap.clear(),this.edgeMap.clear(),this.edgeIdCounter.clear()}},EI=["id","x","y","z","vx","vy","vz","fx","fy","fz","parentId"],xI=["id","source","target","points"];function SI(r,e){if(!r)throw new Error("Data.nodes is required");let t=new Map;for(let i of r){let n={_original:i};for(let o of EI){let s=i[o];tt(s)||(n[o]=s)}if(e){let o=e(i);for(let s in o){let a=o[s];tt(a)||(n[s]=a)}}if(tt(n.id))throw new Error("Node is missing id field");t.set(n.id,n)}return t}function II(r,e,t){let i=new Map;for(let n of r){let o={_original:n};for(let s of xI){let a=n[s];tt(a)||(o[s]=a)}if(e){let s=e(n);for(let a in s){let h=s[a];tt(h)||(o[a]=h)}}if(tt(o.source)||tt(o.target))throw new Error("Edge is missing source or target field");tt(o.id)&&(o.id=t?.(n)),i.set(o.id,o)}return i}var ao=class{constructor(e,t={}){this.graph=new so(e,t)}export(){return this.graph.data()}replace(e){this.graph.replace(e)}forEachNode(e){this.graph.forEachNode(e)}forEachEdge(e){this.graph.forEachEdge((t,i)=>{t.sourceNode=this.graph.node(t.source),t.targetNode=this.graph.node(t.target),e(t,i)})}destroy(){this.graph.destroy()}};var Xp=Symbol("Comlink.proxy"),AI=Symbol("Comlink.endpoint"),RI=Symbol("Comlink.releaseProxy"),ua=Symbol("Comlink.finalizer"),fo=Symbol("Comlink.thrown"),Qp=r=>typeof r=="object"&&r!==null||typeof r=="function",CI={canHandle:r=>Qp(r)&&r[Xp],serialize(r){let{port1:e,port2:t}=new MessageChannel;return Jp(r,e),[t,[t]]},deserialize(r){return r.start(),ha(r)}},TI={canHandle:r=>Qp(r)&&fo in r,serialize({value:r}){let e;return r instanceof Error?e={isError:!0,value:{message:r.message,name:r.name,stack:r.stack}}:e={isError:!1,value:r},[e,[]]},deserialize(r){throw r.isError?Object.assign(new Error(r.value.message),r.value):r.value}},Zp=new Map([["proxy",CI],["throw",TI]]);function OI(r,e){for(let t of r)if(e===t||t==="*"||t instanceof RegExp&&t.test(e))return!0;return!1}function Jp(r,e=globalThis,t=["*"]){e.addEventListener("message",function i(n){if(!n||!n.data)return;if(!OI(t,n.origin)){console.warn(`Invalid origin '${n.origin}' for comlink proxy`);return}let{id:o,type:s,path:a}=Object.assign({path:[]},n.data),h=(n.data.argumentList||[]).map(Ri),f;try{let l=a.slice(0,-1).reduce((m,_)=>m[_],r),g=a.reduce((m,_)=>m[_],r);switch(s){case"GET":f=g;break;case"SET":l[a.slice(-1)[0]]=Ri(n.data.value),f=!0;break;case"APPLY":f=g.apply(l,h);break;case"CONSTRUCT":{let m=new g(...h);f=PI(m)}break;case"ENDPOINT":{let{port1:m,port2:_}=new MessageChannel;Jp(r,_),f=jI(m,[m])}break;case"RELEASE":f=void 0;break;default:return}}catch(l){f={value:l,[fo]:0}}Promise.resolve(f).catch(l=>({value:l,[fo]:0})).then(l=>{let[g,m]=lo(l);e.postMessage(Object.assign(Object.assign({},g),{id:o}),m),s==="RELEASE"&&(e.removeEventListener("message",i),Hp(e),ua in r&&typeof r[ua]=="function"&&r[ua]())}).catch(l=>{let[g,m]=lo({value:new TypeError("Unserializable return value"),[fo]:0});e.postMessage(Object.assign(Object.assign({},g),{id:o}),m)})}),e.start&&e.start()}function kI(r){return r.constructor.name==="MessagePort"}function Hp(r){kI(r)&&r.close()}function ha(r,e){let t=new Map;return r.addEventListener("message",function(n){let{data:o}=n;if(!o||!o.id)return;let s=t.get(o.id);if(s)try{s(o)}finally{t.delete(o.id)}}),fa(r,t,[],e)}function uo(r){if(r)throw new Error("Proxy has been released and is not useable")}function eg(r){return $i(r,new Map,{type:"RELEASE"}).then(()=>{Hp(r)})}var ho=new WeakMap,co="FinalizationRegistry"in globalThis&&new FinalizationRegistry(r=>{let e=(ho.get(r)||0)-1;ho.set(r,e),e===0&&eg(r)});function LI(r,e){let t=(ho.get(e)||0)+1;ho.set(e,t),co&&co.register(r,e,r)}function MI(r){co&&co.unregister(r)}function fa(r,e,t=[],i=function(){}){let n=!1,o=new Proxy(i,{get(s,a){if(uo(n),a===RI)return()=>{MI(o),eg(r),e.clear(),n=!0};if(a==="then"){if(t.length===0)return{then:()=>o};let h=$i(r,e,{type:"GET",path:t.map(f=>f.toString())}).then(Ri);return h.then.bind(h)}return fa(r,e,[...t,a])},set(s,a,h){uo(n);let[f,l]=lo(h);return $i(r,e,{type:"SET",path:[...t,a].map(g=>g.toString()),value:f},l).then(Ri)},apply(s,a,h){uo(n);let f=t[t.length-1];if(f===AI)return $i(r,e,{type:"ENDPOINT"}).then(Ri);if(f==="bind")return fa(r,e,t.slice(0,-1));let[l,g]=Yp(h);return $i(r,e,{type:"APPLY",path:t.map(m=>m.toString()),argumentList:l},g).then(Ri)},construct(s,a){uo(n);let[h,f]=Yp(a);return $i(r,e,{type:"CONSTRUCT",path:t.map(l=>l.toString()),argumentList:h},f).then(Ri)}});return LI(o,r),o}function DI(r){return Array.prototype.concat.apply([],r)}function Yp(r){let e=r.map(lo);return[e.map(t=>t[0]),DI(e.map(t=>t[1]))]}var rg=new WeakMap;function jI(r,e){return rg.set(r,e),r}function PI(r){return Object.assign(r,{[Xp]:!0})}function lo(r){for(let[e,t]of Zp)if(t.canHandle(r)){let[i,n]=t.serialize(r);return[{type:"HANDLER",name:e,value:i},n]}return[{type:"RAW",value:r},rg.get(r)||[]]}function Ri(r){switch(r.type){case"HANDLER":return Zp.get(r.name).deserialize(r.value);case"RAW":return r.value}}function $i(r,e,t,i){return new Promise(n=>{let o=GI();e.set(o,n),r.start&&r.start(),r.postMessage(Object.assign({id:o},t),i)})}function GI(){return new Array(4).fill(0).map(()=>Math.floor(Math.random()*Number.MAX_SAFE_INTEGER).toString(16)).join("-")}var po=class{constructor(){this.worker=null,this.workerApi=null}execute(e,t,i){return st(this,void 0,void 0,function*(){if(this.worker||(yield this.initWorker()),!this.workerApi)throw new Error("Worker API not initialized");return yield this.workerApi.execute(e,t,i)})}destroy(){this.workerApi&&this.workerApi.destroy(),this.worker&&(this.worker.terminate(),this.worker=null,this.workerApi=null)}initWorker(){return st(this,void 0,void 0,function*(){let e=this.resolveWorkerPath(),i=e.includes("/lib/")||e.endsWith(".mjs")?"module":"classic";this.worker=new Worker(e,{type:i}),this.workerApi=ha(this.worker)})}resolveWorkerPath(){let e=(()=>{if(typeof document>"u")return null;let t=document.currentScript;if(t?.src)return t.src;let i=document.getElementsByTagName("script");for(let n=i.length-1;n>=0;n--){let o=i[n].src;if(o&&(o.includes("index.js")||o.includes("index.min.js")))return o}return null})();if(e){if(e.includes("index.js")||e.includes("index.min.js")){let n=e.replace(/index(\.min)?\.(m?js)(\?.*)?$/,"worker.js");if(n!==e)return n}let t=e.replace(/\/runtime\/[^/]+\.(m?js)(\?.*)?$/,"/worker.js");if(t!==e)return t;let i=e.replace(/\/[^/]+\.(m?js)(\?.*)?$/,"/worker.js");if(i!==e)return i}return"./worker.js"}};var Dt=class{constructor(e){this.supervisor=null,this.initialOptions=this.mergeOptions(this.getDefaultOptions(),e)}get options(){return this.runtimeOptions||this.initialOptions}mergeOptions(e,t){return Object.assign({},e,t||{})}execute(e,t){return st(this,void 0,void 0,function*(){this.runtimeOptions=this.mergeOptions(this.initialOptions,t);let{node:i,edge:n,enableWorker:o}=this.runtimeOptions;this.context=new ao(e,{node:i,edge:n}),this.model=this.context.graph,o&&typeof Worker<"u"?yield this.layoutInWorker(e,this.runtimeOptions):yield this.layout(this.runtimeOptions)})}layoutInWorker(e,t){var i;return st(this,void 0,void 0,function*(){try{this.supervisor||(this.supervisor=new po);let n=yield this.supervisor.execute(this.id,e,t);(i=this.context)===null||i===void 0||i.replace(n)}catch(n){console.error("Layout in worker failed, fallback to main thread layout.",n),yield this.layout(t)}})}forEachNode(e){this.context.forEachNode(e)}forEachEdge(e){this.context.forEachEdge(e)}destroy(){var e;(e=this.context)===null||e===void 0||e.destroy(),this.model=null,this.context=null,this.supervisor&&(this.supervisor.destroy(),this.supervisor=null)}};function tg(r){return Array.isArray(r)}function Ui(r,e,t=2){if(r.nodeCount()===1){let n=r.firstNode();n.x=e[0],n.y=e[1],t===3&&(n.z=e[2]||0)}}function ig(r,e){let t=r.nodes();return t.sort(e),r.setNodeOrder(t),r}function ng(r,e="desc"){return ig(r,(t,i)=>{let n=r.degree(t.id),o=r.degree(i.id);return e==="asc"?n-o:o-n})}function og(r,e){return ig(r,(t,i)=>{let n=r.originalNode(t.id),o=r.originalNode(i.id);return e(n,o)})}var Wi=r=>{let{width:e,height:t,center:i}=r,n=e??(typeof window<"u"?window.innerWidth:0),o=t??(typeof window<"u"?window.innerHeight:0),s=i??[n/2,o/2];return{width:n,height:o,center:s}};var go={nodeSize:30,nodeSpacing:10,preventOverlap:!1,sweep:void 0,equidistant:!1,startAngle:3/2*Math.PI,clockwise:!0,maxLevelDiff:void 0,sortBy:"degree"},mo=class extends Dt{constructor(){super(...arguments),this.id="concentric"}getDefaultOptions(){return go}layout(){return st(this,void 0,void 0,function*(){let{width:e,height:t,center:i}=Wi(this.options),n=this.model.nodeCount();if(!n||n===1){Ui(this.model,i);return}let{sortBy:o,maxLevelDiff:s,sweep:a,clockwise:h,equidistant:f,preventOverlap:l,startAngle:g=go.startAngle,nodeSize:m,nodeSpacing:_}=this.options,E=!o||o==="degree"?"degree":ti(o,["node"]);if(E==="degree")ng(this.model);else{let O=(N,j)=>{let X=E(N),re=E(j);return X===re?0:X>re?-1:1};og(this.model,O)}let q=this.model.nodes(),x=new Map;for(let O of q){let N=E==="degree"?this.model.degree(O.id):E(O._original);x.set(O.id,N)}let A=this.model.firstNode(),S=s||x.get(A.id)/4,I=oo(m,_,go.nodeSize,go.nodeSpacing),M=new Map;for(let O of q)M.set(O.id,Math.max(...I(O._original)));let D=[{nodes:[]}],z=D[0];for(let O=0;O0){let j=z.nodes[0],X=Math.abs(x.get(j.id)-x.get(N.id));S&&X>=S&&(z={nodes:[]},D.push(z))}z.nodes.push(N)}for(let O of D){let N=O.nodes.map(j=>M.get(j.id));O.nodeSizes=N,O.maxNodeSize=Math.max(...N)}if(D.forEach(O=>{let N=a===void 0?2*Math.PI-2*Math.PI/O.nodes.length:a;O.dTheta=N/Math.max(1,O.nodes.length-1)}),l){let O=0;for(let N=0;N1){let X=j.nodeSizes||[],re=0;for(let Ne=0;Ne0?re/_e:0;O=Math.max(Te,O)}if(j.r=O,N{X===0&&(N=j.r||0),j.r=N,N+=O})}D.forEach(O=>{let N=O.dTheta||0,j=O.r||0;O.nodes.forEach((X,re)=>{let oe=g+(h?1:-1)*N*re;X.x=i[0]+j*Math.cos(oe),X.y=i[1]+j*Math.sin(oe)})})})}};var sg=(function(r){var e=typeof r;return r!==null&&e==="object"||e==="function"});var ag=function(r){return typeof r=="object"&&r!==null};var NI={}.toString,yo=function(r,e){return NI.call(r)==="[object "+e+"]"};var ug=function(r){if(!ag(r)||!yo(r,"Object"))return!1;if(Object.getPrototypeOf(r)===null)return!0;for(var e=r;Object.getPrototypeOf(e)!==null;)e=Object.getPrototypeOf(e);return Object.getPrototypeOf(r)===e};var Cn=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function _o(r){return r&&r.__esModule&&Object.prototype.hasOwnProperty.call(r,"default")?r.default:r}function vo(r){if(Object.prototype.hasOwnProperty.call(r,"__esModule"))return r;var e=r.default;if(typeof e=="function"){var t=function i(){var n=!1;try{n=this instanceof i}catch{}return n?Reflect.construct(e,arguments,this.constructor):e.apply(this,arguments)};t.prototype=e.prototype}else t={};return Object.defineProperty(t,"__esModule",{value:!0}),Object.keys(r).forEach(function(i){var n=Object.getOwnPropertyDescriptor(r,i);Object.defineProperty(t,i,n.get?n:{enumerable:!0,get:function(){return r[i]}})}),t}function Bi(r){throw new Error('Could not dynamically require "'+r+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}var ca,fg;function hg(){if(fg)return ca;fg=1;function r(){this.__data__=[],this.size=0}return ca=r,ca}var la,cg;function wt(){if(cg)return la;cg=1;function r(e,t){return e===t||e!==e&&t!==t}return la=r,la}var da,lg;function ii(){if(lg)return da;lg=1;var r=wt();function e(t,i){for(var n=t.length;n--;)if(r(t[n][0],i))return n;return-1}return da=e,da}var pa,dg;function pg(){if(dg)return pa;dg=1;var r=ii(),e=Array.prototype,t=e.splice;function i(n){var o=this.__data__,s=r(o,n);if(s<0)return!1;var a=o.length-1;return s==a?o.pop():t.call(o,s,1),--this.size,!0}return pa=i,pa}var ga,gg;function mg(){if(gg)return ga;gg=1;var r=ii();function e(t){var i=this.__data__,n=r(i,t);return n<0?void 0:i[n][1]}return ga=e,ga}var ma,yg;function _g(){if(yg)return ma;yg=1;var r=ii();function e(t){return r(this.__data__,t)>-1}return ma=e,ma}var ya,vg;function wg(){if(vg)return ya;vg=1;var r=ii();function e(t,i){var n=this.__data__,o=r(n,t);return o<0?(++this.size,n.push([t,i])):n[o][1]=i,this}return ya=e,ya}var _a,qg;function ni(){if(qg)return _a;qg=1;var r=hg(),e=pg(),t=mg(),i=_g(),n=wg();function o(s){var a=-1,h=s==null?0:s.length;for(this.clear();++a-1&&i%1==0&&i-1&&t%1==0&&t<=r}return du=e,du}var pu,Wm;function Bm(){if(Wm)return pu;Wm=1;var r=at(),e=Qi(),t=jr(),i="[object Arguments]",n="[object Array]",o="[object Boolean]",s="[object Date]",a="[object Error]",h="[object Function]",f="[object Map]",l="[object Number]",g="[object Object]",m="[object RegExp]",_="[object Set]",E="[object String]",q="[object WeakMap]",x="[object ArrayBuffer]",A="[object DataView]",S="[object Float32Array]",I="[object Float64Array]",M="[object Int8Array]",D="[object Int16Array]",z="[object Int32Array]",O="[object Uint8Array]",N="[object Uint8ClampedArray]",j="[object Uint16Array]",X="[object Uint32Array]",re={};re[S]=re[I]=re[M]=re[D]=re[z]=re[O]=re[N]=re[j]=re[X]=!0,re[i]=re[n]=re[x]=re[o]=re[A]=re[s]=re[a]=re[h]=re[f]=re[l]=re[g]=re[m]=re[_]=re[E]=re[q]=!1;function oe(me){return t(me)&&e(me.length)&&!!re[r(me)]}return pu=oe,pu}var gu,Vm;function ci(){if(Vm)return gu;Vm=1;function r(e){return function(t){return e(t)}}return gu=r,gu}var Zi={exports:{}};Zi.exports;var Km;function Ji(){return Km?Zi.exports:(Km=1,(function(r,e){var t=wo(),i=e&&!e.nodeType&&e,n=i&&!0&&r&&!r.nodeType&&r,o=n&&n.exports===i,s=o&&t.process,a=(function(){try{var h=n&&n.require&&n.require("util").types;return h||s&&s.binding&&s.binding("util")}catch{}})();r.exports=a})(Zi,Zi.exports),Zi.exports)}var mu,Ym;function Nt(){if(Ym)return mu;Ym=1;var r=Bm(),e=ci(),t=Ji(),i=t&&t.isTypedArray,n=i?e(i):r;return mu=n,mu}var yu,Xm;function Eo(){if(Xm)return yu;Xm=1;var r=Lm(),e=Gt(),t=Ve(),i=bt(),n=hi(),o=Nt(),s=Object.prototype,a=s.hasOwnProperty;function h(f,l){var g=t(f),m=!g&&e(f),_=!g&&!m&&i(f),E=!g&&!m&&!_&&o(f),q=g||m||_||E,x=q?r(f.length,String):[],A=x.length;for(var S in f)(l||a.call(f,S))&&!(q&&(S=="length"||_&&(S=="offset"||S=="parent")||E&&(S=="buffer"||S=="byteLength"||S=="byteOffset")||n(S,A)))&&x.push(S);return x}return yu=h,yu}var _u,Qm;function li(){if(Qm)return _u;Qm=1;var r=Object.prototype;function e(t){var i=t&&t.constructor,n=typeof i=="function"&&i.prototype||r;return t===n}return _u=e,_u}var vu,Zm;function xo(){if(Zm)return vu;Zm=1;function r(e,t){return function(i){return e(t(i))}}return vu=r,vu}var wu,Jm;function Hm(){if(Jm)return wu;Jm=1;var r=xo(),e=r(Object.keys,Object);return wu=e,wu}var qu,ey;function Hi(){if(ey)return qu;ey=1;var r=li(),e=Hm(),t=Object.prototype,i=t.hasOwnProperty;function n(o){if(!r(o))return e(o);var s=[];for(var a in Object(o))i.call(o,a)&&a!="constructor"&&s.push(a);return s}return qu=n,qu}var bu,ry;function Wr(){if(ry)return bu;ry=1;var r=jt(),e=Qi();function t(i){return i!=null&&e(i.length)&&!r(i)}return bu=t,bu}var Eu,ty;function Zr(){if(ty)return Eu;ty=1;var r=Eo(),e=Hi(),t=Wr();function i(n){return t(n)?r(n):e(n)}return Eu=i,Eu}var xu,iy;function ny(){if(iy)return xu;iy=1;var r=Pt(),e=Zr();function t(i,n){return i&&r(n,e(n),i)}return xu=t,xu}var Su,oy;function sy(){if(oy)return Su;oy=1;function r(e){var t=[];if(e!=null)for(var i in Object(e))t.push(i);return t}return Su=r,Su}var Iu,ay;function uy(){if(ay)return Iu;ay=1;var r=_r(),e=li(),t=sy(),i=Object.prototype,n=i.hasOwnProperty;function o(s){if(!r(s))return t(s);var a=e(s),h=[];for(var f in s)f=="constructor"&&(a||!n.call(s,f))||h.push(f);return h}return Iu=o,Iu}var Au,fy;function ft(){if(fy)return Au;fy=1;var r=Eo(),e=uy(),t=Wr();function i(n){return t(n)?r(n,!0):e(n)}return Au=i,Au}var Ru,hy;function cy(){if(hy)return Ru;hy=1;var r=Pt(),e=ft();function t(i,n){return i&&r(n,e(n),i)}return Ru=t,Ru}var en={exports:{}};en.exports;var ly;function So(){return ly?en.exports:(ly=1,(function(r,e){var t=Ir(),i=e&&!e.nodeType&&e,n=i&&!0&&r&&!r.nodeType&&r,o=n&&n.exports===i,s=o?t.Buffer:void 0,a=s?s.allocUnsafe:void 0;function h(f,l){if(l)return f.slice();var g=f.length,m=a?a(g):new f.constructor(g);return f.copy(m),m}r.exports=h})(en,en.exports),en.exports)}var Cu,dy;function Io(){if(dy)return Cu;dy=1;function r(e,t){var i=-1,n=e.length;for(t||(t=Array(n));++i_))return!1;var q=g.get(s),x=g.get(a);if(q&&x)return q==a&&x==s;var A=-1,S=!0,I=h&n?new r:void 0;for(g.set(s,a),g.set(a,s);++A<_;){var M=s[A],D=a[A];if(f)var z=m?f(D,M,A,a,s,g):f(M,D,A,s,a,g);if(z!==void 0){if(z)continue;S=!1;break}if(I){if(!e(a,function(O,N){if(!t(I,N)&&(M===O||l(M,O,h,f,g)))return I.push(N)})){S=!1;break}}else if(!(M===D||l(M,D,h,f,g))){S=!1;break}}return g.delete(s),g.delete(a),S}return Sf=o,Sf}var If,O_;function k_(){if(O_)return If;O_=1;function r(e){var t=-1,i=Array(e.size);return e.forEach(function(n,o){i[++t]=[o,n]}),i}return If=r,If}var Af,L_;function un(){if(L_)return Af;L_=1;function r(e){var t=-1,i=Array(e.size);return e.forEach(function(n){i[++t]=n}),i}return Af=r,Af}var Rf,M_;function D_(){if(M_)return Rf;M_=1;var r=qt(),e=Lo(),t=wt(),i=Uo(),n=k_(),o=un(),s=1,a=2,h="[object Boolean]",f="[object Date]",l="[object Error]",g="[object Map]",m="[object Number]",_="[object RegExp]",E="[object Set]",q="[object String]",x="[object Symbol]",A="[object ArrayBuffer]",S="[object DataView]",I=r?r.prototype:void 0,M=I?I.valueOf:void 0;function D(z,O,N,j,X,re,oe){switch(N){case S:if(z.byteLength!=O.byteLength||z.byteOffset!=O.byteOffset)return!1;z=z.buffer,O=O.buffer;case A:return!(z.byteLength!=O.byteLength||!re(new e(z),new e(O)));case h:case f:case m:return t(+z,+O);case l:return z.name==O.name&&z.message==O.message;case _:case q:return z==O+"";case g:var me=n;case E:var _e=j&s;if(me||(me=o),z.size!=O.size&&!_e)return!1;var Te=oe.get(z);if(Te)return Te==O;j|=a,oe.set(z,O);var Ne=i(me(z),me(O),j,X,re,oe);return oe.delete(z),Ne;case x:if(M)return M.call(z)==M.call(O)}return!1}return Rf=D,Rf}var Cf,j_;function P_(){if(j_)return Cf;j_=1;var r=Oo(),e=1,t=Object.prototype,i=t.hasOwnProperty;function n(o,s,a,h,f,l){var g=a&e,m=r(o),_=m.length,E=r(s),q=E.length;if(_!=q&&!g)return!1;for(var x=_;x--;){var A=m[x];if(!(g?A in s:i.call(s,A)))return!1}var S=l.get(o),I=l.get(s);if(S&&I)return S==s&&I==o;var M=!0;l.set(o,s),l.set(s,o);for(var D=g;++x<_;){A=m[x];var z=o[A],O=s[A];if(h)var N=g?h(O,z,A,s,o,l):h(z,O,A,o,s,l);if(!(N===void 0?z===O||f(z,O,a,h,l):N)){M=!1;break}D||(D=A=="constructor")}if(M&&!D){var j=o.constructor,X=s.constructor;j!=X&&"constructor"in o&&"constructor"in s&&!(typeof j=="function"&&j instanceof j&&typeof X=="function"&&X instanceof X)&&(M=!1)}return l.delete(o),l.delete(s),M}return Cf=n,Cf}var Tf,G_;function N_(){if(G_)return Tf;G_=1;var r=ai(),e=Uo(),t=D_(),i=P_(),n=Et(),o=Ve(),s=bt(),a=Nt(),h=1,f="[object Arguments]",l="[object Array]",g="[object Object]",m=Object.prototype,_=m.hasOwnProperty;function E(q,x,A,S,I,M){var D=o(q),z=o(x),O=D?l:n(q),N=z?l:n(x);O=O==f?g:O,N=N==f?g:N;var j=O==g,X=N==g,re=O==N;if(re&&s(q)){if(!s(x))return!1;D=!0,j=!1}if(re&&!j)return M||(M=new r),D||a(q)?e(q,x,A,S,I,M):t(q,x,O,A,S,I,M);if(!(A&h)){var oe=j&&_.call(q,"__wrapped__"),me=X&&_.call(x,"__wrapped__");if(oe||me){var _e=oe?q.value():q,Te=me?x.value():x;return M||(M=new r),I(_e,Te,A,S,M)}}return re?(M||(M=new r),i(q,x,A,S,I,M)):!1}return Tf=E,Tf}var Of,F_;function Wo(){if(F_)return Of;F_=1;var r=N_(),e=jr();function t(i,n,o,s,a){return i===n?!0:i==null||n==null||!e(i)&&!e(n)?i!==i&&n!==n:r(i,n,o,s,t,a)}return Of=t,Of}var kf,z_;function $_(){if(z_)return kf;z_=1;var r=ai(),e=Wo(),t=1,i=2;function n(o,s,a,h){var f=a.length,l=f,g=!h;if(o==null)return!l;for(o=Object(o);f--;){var m=a[f];if(g&&m[2]?m[1]!==o[m[0]]:!(m[0]in o))return!1}for(;++f0&&o(l)?n>1?t(l,n-1,o,s,a):r(a,l):s||(a[a.length]=l)}return a}return qh=t,qh}var bh,rw;function tw(){if(rw)return bh;rw=1;function r(e,t,i){switch(i.length){case 0:return e.call(t);case 1:return e.call(t,i[0]);case 2:return e.call(t,i[0],i[1]);case 3:return e.call(t,i[0],i[1],i[2])}return e.apply(t,i)}return bh=r,bh}var Eh,iw;function is(){if(iw)return Eh;iw=1;var r=tw(),e=Math.max;function t(i,n,o){return n=e(n===void 0?i.length-1:n,0),function(){for(var s=arguments,a=-1,h=e(s.length-n,0),f=Array(h);++a0){if(++o>=r)return arguments[0]}else o=0;return n.apply(void 0,arguments)}}return Sh=i,Sh}var Ih,uw;function ns(){if(uw)return Ih;uw=1;var r=ow(),e=aw(),t=e(r);return Ih=t,Ih}var Ah,fw;function _i(){if(fw)return Ah;fw=1;var r=ht(),e=is(),t=ns();function i(n,o){return t(e(n,o,r),n+"")}return Ah=i,Ah}var Rh,hw;function os(){if(hw)return Rh;hw=1;function r(e,t,i,n){for(var o=e.length,s=i+(n?1:-1);n?s--:++s-1}return kh=e,kh}var Lh,vw;function ww(){if(vw)return Lh;vw=1;function r(e,t,i){for(var n=-1,o=e==null?0:e.length;++n=s){var A=f?null:n(h);if(A)return o(A);E=!1,m=i,x=new r}else x=f?[]:q;e:for(;++g<_;){var S=h[g],I=f?f(S):S;if(S=l||S!==0?S:0,E&&I===I){for(var M=x.length;M--;)if(x[M]===I)continue e;f&&x.push(I),q.push(S)}else m(x,I,l)||(x!==q&&x.push(I),q.push(S))}return q}return jh=a,jh}var Ph,Aw;function ss(){if(Aw)return Ph;Aw=1;var r=Wr(),e=jr();function t(i){return e(i)&&r(i)}return Ph=t,Ph}var Gh,Rw;function Cw(){if(Rw)return Gh;Rw=1;var r=hn(),e=_i(),t=Iw(),i=ss(),n=e(function(o){return t(r(o,1,i,!0))});return Gh=n,Gh}var Nh,Tw;function Ow(){if(Tw)return Nh;Tw=1;var r=gi();function e(t,i){return r(i,function(n){return t[n]})}return Nh=e,Nh}var Fh,kw;function as(){if(kw)return Fh;kw=1;var r=Ow(),e=Zr();function t(i){return i==null?[]:r(i,e(i))}return Fh=t,Fh}var zh,Lw;function vr(){if(Lw)return zh;Lw=1;var r;if(typeof Bi=="function")try{r={clone:a_(),constant:on(),each:Fo(),filter:Zo(),has:Jo(),isArray:Ve(),isEmpty:Cv(),isFunction:jt(),isUndefined:Ho(),keys:Zr(),map:rs(),reduce:ts(),size:Xv(),transform:Zv(),union:Cw(),values:as()}}catch{}return r||(r=window._),zh=r,zh}var $h,Mw;function cn(){if(Mw)return $h;Mw=1;var r=vr();$h=n;var e="\0",t="\0",i="";function n(l){this._isDirected=r.has(l,"directed")?l.directed:!0,this._isMultigraph=r.has(l,"multigraph")?l.multigraph:!1,this._isCompound=r.has(l,"compound")?l.compound:!1,this._label=void 0,this._defaultNodeLabelFn=r.constant(void 0),this._defaultEdgeLabelFn=r.constant(void 0),this._nodes={},this._isCompound&&(this._parent={},this._children={},this._children[t]={}),this._in={},this._preds={},this._out={},this._sucs={},this._edgeObjs={},this._edgeLabels={}}n.prototype._nodeCount=0,n.prototype._edgeCount=0,n.prototype.isDirected=function(){return this._isDirected},n.prototype.isMultigraph=function(){return this._isMultigraph},n.prototype.isCompound=function(){return this._isCompound},n.prototype.setGraph=function(l){return this._label=l,this},n.prototype.graph=function(){return this._label},n.prototype.setDefaultNodeLabel=function(l){return r.isFunction(l)||(l=r.constant(l)),this._defaultNodeLabelFn=l,this},n.prototype.nodeCount=function(){return this._nodeCount},n.prototype.nodes=function(){return r.keys(this._nodes)},n.prototype.sources=function(){var l=this;return r.filter(this.nodes(),function(g){return r.isEmpty(l._in[g])})},n.prototype.sinks=function(){var l=this;return r.filter(this.nodes(),function(g){return r.isEmpty(l._out[g])})},n.prototype.setNodes=function(l,g){var m=arguments,_=this;return r.each(l,function(E){m.length>1?_.setNode(E,g):_.setNode(E)}),this},n.prototype.setNode=function(l,g){return r.has(this._nodes,l)?(arguments.length>1&&(this._nodes[l]=g),this):(this._nodes[l]=arguments.length>1?g:this._defaultNodeLabelFn(l),this._isCompound&&(this._parent[l]=t,this._children[l]={},this._children[t][l]=!0),this._in[l]={},this._preds[l]={},this._out[l]={},this._sucs[l]={},++this._nodeCount,this)},n.prototype.node=function(l){return this._nodes[l]},n.prototype.hasNode=function(l){return r.has(this._nodes,l)},n.prototype.removeNode=function(l){var g=this;if(r.has(this._nodes,l)){var m=function(_){g.removeEdge(g._edgeObjs[_])};delete this._nodes[l],this._isCompound&&(this._removeFromParentsChildList(l),delete this._parent[l],r.each(this.children(l),function(_){g.setParent(_)}),delete this._children[l]),r.each(r.keys(this._in[l]),m),delete this._in[l],delete this._preds[l],r.each(r.keys(this._out[l]),m),delete this._out[l],delete this._sucs[l],--this._nodeCount}return this},n.prototype.setParent=function(l,g){if(!this._isCompound)throw new Error("Cannot set parent in a non-compound graph");if(r.isUndefined(g))g=t;else{g+="";for(var m=g;!r.isUndefined(m);m=this.parent(m))if(m===l)throw new Error("Setting "+g+" as parent of "+l+" would create a cycle");this.setNode(g)}return this.setNode(l),this._removeFromParentsChildList(l),this._parent[l]=g,this._children[g][l]=!0,this},n.prototype._removeFromParentsChildList=function(l){delete this._children[this._parent[l]][l]},n.prototype.parent=function(l){if(this._isCompound){var g=this._parent[l];if(g!==t)return g}},n.prototype.children=function(l){if(r.isUndefined(l)&&(l=t),this._isCompound){var g=this._children[l];if(g)return r.keys(g)}else{if(l===t)return this.nodes();if(this.hasNode(l))return[]}},n.prototype.predecessors=function(l){var g=this._preds[l];if(g)return r.keys(g)},n.prototype.successors=function(l){var g=this._sucs[l];if(g)return r.keys(g)},n.prototype.neighbors=function(l){var g=this.predecessors(l);if(g)return r.union(g,this.successors(l))},n.prototype.isLeaf=function(l){var g;return this.isDirected()?g=this.successors(l):g=this.neighbors(l),g.length===0},n.prototype.filterNodes=function(l){var g=new this.constructor({directed:this._isDirected,multigraph:this._isMultigraph,compound:this._isCompound});g.setGraph(this.graph());var m=this;r.each(this._nodes,function(q,x){l(x)&&g.setNode(x,q)}),r.each(this._edgeObjs,function(q){g.hasNode(q.v)&&g.hasNode(q.w)&&g.setEdge(q,m.edge(q))});var _={};function E(q){var x=m.parent(q);return x===void 0||g.hasNode(x)?(_[q]=x,x):x in _?_[x]:E(x)}return this._isCompound&&r.each(g.nodes(),function(q){g.setParent(q,E(q))}),g},n.prototype.setDefaultEdgeLabel=function(l){return r.isFunction(l)||(l=r.constant(l)),this._defaultEdgeLabelFn=l,this},n.prototype.edgeCount=function(){return this._edgeCount},n.prototype.edges=function(){return r.values(this._edgeObjs)},n.prototype.setPath=function(l,g){var m=this,_=arguments;return r.reduce(l,function(E,q){return _.length>1?m.setEdge(E,q,g):m.setEdge(E,q),q}),this},n.prototype.setEdge=function(){var l,g,m,_,E=!1,q=arguments[0];typeof q=="object"&&q!==null&&"v"in q?(l=q.v,g=q.w,m=q.name,arguments.length===2&&(_=arguments[1],E=!0)):(l=q,g=arguments[1],m=arguments[3],arguments.length>2&&(_=arguments[2],E=!0)),l=""+l,g=""+g,r.isUndefined(m)||(m=""+m);var x=a(this._isDirected,l,g,m);if(r.has(this._edgeLabels,x))return E&&(this._edgeLabels[x]=_),this;if(!r.isUndefined(m)&&!this._isMultigraph)throw new Error("Cannot set a named edge when isMultigraph = false");this.setNode(l),this.setNode(g),this._edgeLabels[x]=E?_:this._defaultEdgeLabelFn(l,g,m);var A=h(this._isDirected,l,g,m);return l=A.v,g=A.w,Object.freeze(A),this._edgeObjs[x]=A,o(this._preds[g],l),o(this._sucs[l],g),this._in[g][x]=A,this._out[l][x]=A,this._edgeCount++,this},n.prototype.edge=function(l,g,m){var _=arguments.length===1?f(this._isDirected,arguments[0]):a(this._isDirected,l,g,m);return this._edgeLabels[_]},n.prototype.hasEdge=function(l,g,m){var _=arguments.length===1?f(this._isDirected,arguments[0]):a(this._isDirected,l,g,m);return r.has(this._edgeLabels,_)},n.prototype.removeEdge=function(l,g,m){var _=arguments.length===1?f(this._isDirected,arguments[0]):a(this._isDirected,l,g,m),E=this._edgeObjs[_];return E&&(l=E.v,g=E.w,delete this._edgeLabels[_],delete this._edgeObjs[_],s(this._preds[g],l),s(this._sucs[l],g),delete this._in[g][_],delete this._out[l][_],this._edgeCount--),this},n.prototype.inEdges=function(l,g){var m=this._in[l];if(m){var _=r.values(m);return g?r.filter(_,function(E){return E.v===g}):_}},n.prototype.outEdges=function(l,g){var m=this._out[l];if(m){var _=r.values(m);return g?r.filter(_,function(E){return E.w===g}):_}},n.prototype.nodeEdges=function(l,g){var m=this.inEdges(l,g);if(m)return m.concat(this.outEdges(l,g))};function o(l,g){l[g]?l[g]++:l[g]=1}function s(l,g){--l[g]||delete l[g]}function a(l,g,m,_){var E=""+g,q=""+m;if(!l&&E>q){var x=E;E=q,q=x}return E+i+q+i+(r.isUndefined(_)?e:_)}function h(l,g,m,_){var E=""+g,q=""+m;if(!l&&E>q){var x=E;E=q,q=x}var A={v:E,w:q};return _&&(A.name=_),A}function f(l,g){return a(l,g.v,g.w,g.name)}return $h}var Uh,Dw;function jw(){return Dw||(Dw=1,Uh="2.1.8"),Uh}var Wh,Pw;function Gw(){return Pw||(Pw=1,Wh={Graph:cn(),version:jw()}),Wh}var Bh,Nw;function Fw(){if(Nw)return Bh;Nw=1;var r=vr(),e=cn();Bh={write:t,read:o};function t(s){var a={options:{directed:s.isDirected(),multigraph:s.isMultigraph(),compound:s.isCompound()},nodes:i(s),edges:n(s)};return r.isUndefined(s.graph())||(a.value=r.clone(s.graph())),a}function i(s){return r.map(s.nodes(),function(a){var h=s.node(a),f=s.parent(a),l={v:a};return r.isUndefined(h)||(l.value=h),r.isUndefined(f)||(l.parent=f),l})}function n(s){return r.map(s.edges(),function(a){var h=s.edge(a),f={v:a.v,w:a.w};return r.isUndefined(a.name)||(f.name=a.name),r.isUndefined(h)||(f.value=h),f})}function o(s){var a=new e(s.options).setGraph(s.value);return r.each(s.nodes,function(h){a.setNode(h.v,h.value),h.parent&&a.setParent(h.v,h.parent)}),r.each(s.edges,function(h){a.setEdge({v:h.v,w:h.w,name:h.name},h.value)}),a}return Bh}var Vh,zw;function $w(){if(zw)return Vh;zw=1;var r=vr();Vh=e;function e(t){var i={},n=[],o;function s(a){r.has(i,a)||(i[a]=!0,o.push(a),r.each(t.successors(a),s),r.each(t.predecessors(a),s))}return r.each(t.nodes(),function(a){o=[],s(a),o.length&&n.push(o)}),n}return Vh}var Kh,Uw;function us(){if(Uw)return Kh;Uw=1;var r=vr();Kh=e;function e(){this._arr=[],this._keyIndices={}}return e.prototype.size=function(){return this._arr.length},e.prototype.keys=function(){return this._arr.map(function(t){return t.key})},e.prototype.has=function(t){return r.has(this._keyIndices,t)},e.prototype.priority=function(t){var i=this._keyIndices[t];if(i!==void 0)return this._arr[i].priority},e.prototype.min=function(){if(this.size()===0)throw new Error("Queue underflow");return this._arr[0].key},e.prototype.add=function(t,i){var n=this._keyIndices;if(t=String(t),!r.has(n,t)){var o=this._arr,s=o.length;return n[t]=s,o.push({key:t,priority:i}),this._decrease(s),!0}return!1},e.prototype.removeMin=function(){this._swap(0,this._arr.length-1);var t=this._arr.pop();return delete this._keyIndices[t.key],this._heapify(0),t.key},e.prototype.decrease=function(t,i){var n=this._keyIndices[t];if(i>this._arr[n].priority)throw new Error("New priority is greater than current priority. Key: "+t+" Old: "+this._arr[n].priority+" New: "+i);this._arr[n].priority=i,this._decrease(n)},e.prototype._heapify=function(t){var i=this._arr,n=2*t,o=n+1,s=t;n>1,!(i[o].priority0&&(g=l.removeMin(),m=f[g],m.distance!==Number.POSITIVE_INFINITY);)h(g).forEach(_);return f}return Yh}var Xh,Bw;function Vw(){if(Bw)return Xh;Bw=1;var r=fs(),e=vr();Xh=t;function t(i,n,o){return e.transform(i.nodes(),function(s,a){s[a]=r(i,a,n,o)},{})}return Xh}var Qh,Kw;function hs(){if(Kw)return Qh;Kw=1;var r=vr();Qh=e;function e(t){var i=0,n=[],o={},s=[];function a(h){var f=o[h]={onStack:!0,lowlink:i,index:i++};if(n.push(h),t.successors(h).forEach(function(m){r.has(o,m)?o[m].onStack&&(f.lowlink=Math.min(f.lowlink,o[m].index)):(a(m),f.lowlink=Math.min(f.lowlink,o[m].lowlink))}),f.lowlink===f.index){var l=[],g;do g=n.pop(),o[g].onStack=!1,l.push(g);while(h!==g);s.push(l)}}return t.nodes().forEach(function(h){r.has(o,h)||a(h)}),s}return Qh}var Zh,Yw;function Xw(){if(Yw)return Zh;Yw=1;var r=vr(),e=hs();Zh=t;function t(i){return r.filter(e(i),function(n){return n.length>1||n.length===1&&i.hasEdge(n[0],n[0])})}return Zh}var Jh,Qw;function Zw(){if(Qw)return Jh;Qw=1;var r=vr();Jh=t;var e=r.constant(1);function t(n,o,s){return i(n,o||e,s||function(a){return n.outEdges(a)})}function i(n,o,s){var a={},h=n.nodes();return h.forEach(function(f){a[f]={},a[f][f]={distance:0},h.forEach(function(l){f!==l&&(a[f][l]={distance:Number.POSITIVE_INFINITY})}),s(f).forEach(function(l){var g=l.v===f?l.w:l.v,m=o(l);a[f][g]={distance:m,predecessor:f}})}),h.forEach(function(f){var l=a[f];h.forEach(function(g){var m=a[g];h.forEach(function(_){var E=m[f],q=l[_],x=m[_],A=E.distance+q.distance;A0;){if(f=h.removeMin(),r.has(a,f))s.setEdge(f,a[f]);else{if(g)throw new Error("Input graph is not connected: "+n);g=!0}n.nodeEdges(f).forEach(l)}return s}return nc}var oc,u0;function f0(){return u0||(u0=1,oc={components:$w(),dijkstra:fs(),dijkstraAll:Vw(),findCycles:Xw(),floydWarshall:Zw(),isAcyclic:e0(),postorder:i0(),preorder:o0(),prim:a0(),tarjan:hs(),topsort:cs()}),oc}var sc,h0;function c0(){if(h0)return sc;h0=1;var r=Gw();return sc={Graph:r.Graph,json:Fw(),alg:f0(),version:r.version},sc}var ac,l0;function kr(){if(l0)return ac;l0=1;var r;if(typeof Bi=="function")try{r=c0()}catch{}return r||(r=window.graphlib),ac=r,ac}var uc,d0;function p0(){if(d0)return uc;d0=1;var r=Po(),e=1,t=4;function i(n){return r(n,e|t)}return uc=i,uc}var fc,g0;function vi(){if(g0)return fc;g0=1;var r=wt(),e=Wr(),t=hi(),i=_r();function n(o,s,a){if(!i(a))return!1;var h=typeof s;return(h=="number"?e(a)&&t(s,a.length):h=="string"&&s in a)?r(a[s],o):!1}return fc=n,fc}var hc,m0;function y0(){if(m0)return hc;m0=1;var r=_i(),e=wt(),t=vi(),i=ft(),n=Object.prototype,o=n.hasOwnProperty,s=r(function(a,h){a=Object(a);var f=-1,l=h.length,g=l>2?h[2]:void 0;for(g&&t(h[0],h[1],g)&&(l=1);++f-1?h[f?o[l]:l]:void 0}}return cc=i,cc}var lc,w0;function q0(){if(w0)return lc;w0=1;var r=/\s/;function e(t){for(var i=t.length;i--&&r.test(t.charAt(i)););return i}return lc=e,lc}var dc,b0;function E0(){if(b0)return dc;b0=1;var r=q0(),e=/^\s+/;function t(i){return i&&i.slice(0,r(i)+1).replace(e,"")}return dc=t,dc}var pc,x0;function S0(){if(x0)return pc;x0=1;var r=E0(),e=_r(),t=xt(),i=NaN,n=/^[-+]0x[0-9a-f]+$/i,o=/^0b[01]+$/i,s=/^0o[0-7]+$/i,a=parseInt;function h(f){if(typeof f=="number")return f;if(t(f))return i;if(e(f)){var l=typeof f.valueOf=="function"?f.valueOf():f;f=e(l)?l+"":l}if(typeof f!="string")return f===0?f:+f;f=r(f);var g=o.test(f);return g||s.test(f)?a(f.slice(2),g?2:8):n.test(f)?i:+f}return pc=h,pc}var gc,I0;function ds(){if(I0)return gc;I0=1;var r=S0(),e=1/0,t=17976931348623157e292;function i(n){if(!n)return n===0?n:0;if(n=r(n),n===e||n===-e){var o=n<0?-1:1;return o*t}return n===n?n:0}return gc=i,gc}var mc,A0;function R0(){if(A0)return mc;A0=1;var r=ds();function e(t){var i=r(t),n=i%1;return i===i?n?i-n:i:0}return mc=e,mc}var yc,C0;function T0(){if(C0)return yc;C0=1;var r=os(),e=Br(),t=R0(),i=Math.max;function n(o,s,a){var h=o==null?0:o.length;if(!h)return-1;var f=a==null?0:t(a);return f<0&&(f=i(h+f,0)),r(o,e(s,3),f)}return yc=n,yc}var _c,O0;function k0(){if(O0)return _c;O0=1;var r=v0(),e=T0(),t=r(e);return _c=t,_c}var vc,L0;function ps(){if(L0)return vc;L0=1;var r=hn();function e(t){var i=t==null?0:t.length;return i?r(t,1):[]}return vc=e,vc}var wc,M0;function D0(){if(M0)return wc;M0=1;var r=sn(),e=Go(),t=ft();function i(n,o){return n==null?n:r(n,e(o),t)}return wc=i,wc}var qc,j0;function P0(){if(j0)return qc;j0=1;function r(e){var t=e==null?0:e.length;return t?e[t-1]:void 0}return qc=r,qc}var bc,G0;function N0(){if(G0)return bc;G0=1;var r=ui(),e=an(),t=Br();function i(n,o){var s={};return o=t(o,3),e(n,function(a,h,f){r(s,h,o(a,h,f))}),s}return bc=i,bc}var Ec,F0;function ln(){if(F0)return Ec;F0=1;var r=xt();function e(t,i,n){for(var o=-1,s=t.length;++ot}return xc=r,xc}var Sc,U0;function W0(){if(U0)return Sc;U0=1;var r=ln(),e=$0(),t=ht();function i(n){return n&&n.length?r(n,t,e):void 0}return Sc=i,Sc}var Ic,B0;function gs(){if(B0)return Ic;B0=1;var r=ui(),e=wt();function t(i,n,o){(o!==void 0&&!e(i[n],o)||o===void 0&&!(n in i))&&r(i,n,o)}return Ic=t,Ic}var Ac,V0;function K0(){if(V0)return Ac;V0=1;var r=at(),e=di(),t=jr(),i="[object Object]",n=Function.prototype,o=Object.prototype,s=n.toString,a=o.hasOwnProperty,h=s.call(Object);function f(l){if(!t(l)||r(l)!=i)return!1;var g=e(l);if(g===null)return!0;var m=a.call(g,"constructor")&&g.constructor;return typeof m=="function"&&m instanceof m&&s.call(m)==h}return Ac=f,Ac}var Rc,Y0;function ms(){if(Y0)return Rc;Y0=1;function r(e,t){if(!(t==="constructor"&&typeof e[t]=="function")&&t!="__proto__")return e[t]}return Rc=r,Rc}var Cc,X0;function Q0(){if(X0)return Cc;X0=1;var r=Pt(),e=ft();function t(i){return r(i,e(i))}return Cc=t,Cc}var Tc,Z0;function J0(){if(Z0)return Tc;Z0=1;var r=gs(),e=So(),t=Mo(),i=Io(),n=jo(),o=Gt(),s=Ve(),a=ss(),h=bt(),f=jt(),l=_r(),g=K0(),m=Nt(),_=ms(),E=Q0();function q(x,A,S,I,M,D,z){var O=_(x,S),N=_(A,S),j=z.get(N);if(j){r(x,S,j);return}var X=D?D(O,N,S+"",x,A,z):void 0,re=X===void 0;if(re){var oe=s(N),me=!oe&&h(N),_e=!oe&&!me&&m(N);X=N,oe||me||_e?s(O)?X=O:a(O)?X=i(O):me?(re=!1,X=e(N,!0)):_e?(re=!1,X=t(N,!0)):X=[]:g(N)||o(N)?(X=O,o(O)?X=E(O):(!l(O)||f(O))&&(X=n(N))):re=!1}re&&(z.set(N,X),M(X,N,I,D,z),z.delete(N)),r(x,S,X)}return Tc=q,Tc}var Oc,H0;function eq(){if(H0)return Oc;H0=1;var r=ai(),e=gs(),t=sn(),i=J0(),n=_r(),o=ft(),s=ms();function a(h,f,l,g,m){h!==f&&t(f,function(_,E){if(m||(m=new r),n(_))i(h,f,E,l,a,g,m);else{var q=g?g(s(h,E),_,E+"",h,f,m):void 0;q===void 0&&(q=_),e(h,E,q)}},o)}return Oc=a,Oc}var kc,rq;function tq(){if(rq)return kc;rq=1;var r=_i(),e=vi();function t(i){return r(function(n,o){var s=-1,a=o.length,h=a>1?o[a-1]:void 0,f=a>2?o[2]:void 0;for(h=i.length>3&&typeof h=="function"?(a--,h):void 0,f&&e(o[0],o[1],f)&&(h=a<3?void 0:h,a=1),n=Object(n);++si||a&&h&&l&&!f&&!g||o&&h&&l||!n&&l||!s)return 1;if(!o&&!a&&!g&&t=f)return l;var g=n[o];return l*(g=="desc"?-1:1)}}return t.index-i.index}return Yc=e,Yc}var Xc,Mq;function Dq(){if(Mq)return Xc;Mq=1;var r=gi(),e=yi(),t=Br(),i=es(),n=Cq(),o=ci(),s=Lq(),a=ht(),h=Ve();function f(l,g,m){g.length?g=r(g,function(q){return h(q)?function(x){return e(x,q.length===1?q[0]:q)}:q}):g=[a];var _=-1;g=r(g,o(t));var E=i(l,function(q,x,A){var S=r(g,function(I){return I(q)});return{criteria:S,index:++_,value:q}});return n(E,function(q,x){return s(q,x,m)})}return Xc=f,Xc}var Qc,jq;function Pq(){if(jq)return Qc;jq=1;var r=hn(),e=Dq(),t=_i(),i=vi(),n=t(function(o,s){if(o==null)return[];var a=s.length;return a>1&&i(o,s[0],s[1])?s=[]:a>2&&i(s[0],s[1],s[2])&&(s=[s[0]]),e(o,r(s,1),[])});return Qc=n,Qc}var Zc,Gq;function Nq(){if(Gq)return Zc;Gq=1;var r=Ko(),e=0;function t(i){var n=++e;return r(i)+n}return Zc=t,Zc}var Jc,Fq;function zq(){if(Fq)return Jc;Fq=1;function r(e,t,i){for(var n=-1,o=e.length,s=t.length,a={};++n0;--x)if(q=l[x].dequeue(),q){m=m.concat(s(f,l,g,q,!0));break}}}return m}function s(f,l,g,m,_){var E=_?[]:void 0;return r.forEach(f.inEdges(m.v),function(q){var x=f.edge(q),A=f.node(q.v);_&&E.push({v:q.v,w:q.w}),A.out-=x,h(l,g,A)}),r.forEach(f.outEdges(m.v),function(q){var x=f.edge(q),A=q.w,S=f.node(A);S.in-=x,h(l,g,S)}),f.removeNode(m.v),E}function a(f,l){var g=new e,m=0,_=0;r.forEach(f.nodes(),function(x){g.setNode(x,{v:x,in:0,out:0})}),r.forEach(f.edges(),function(x){var A=g.edge(x.v,x.w)||0,S=l(x),I=A+S;g.setEdge(x.v,x.w,I),_=Math.max(_,g.node(x.v).out+=S),m=Math.max(m,g.node(x.w).in+=S)});var E=r.range(_+m+3).map(function(){return new t}),q=m+1;return r.forEach(g.nodes(),function(x){h(E,q,g.node(x))}),{graph:g,buckets:E,zeroIdx:q}}function h(f,l,g){g.out?g.in?f[g.out-g.in+l].enqueue(g):f[f.length-1].enqueue(g):f[0].enqueue(g)}return tl}var il,Xq;function Qq(){if(Xq)return il;Xq=1;var r=Fe(),e=Yq();il={run:t,undo:n};function t(o){var s=o.graph().acyclicer==="greedy"?e(o,a(o)):i(o);r.forEach(s,function(h){var f=o.edge(h);o.removeEdge(h),f.forwardName=h.name,f.reversed=!0,o.setEdge(h.w,h.v,f,r.uniqueId("rev"))});function a(h){return function(f){return h.edge(f).weight}}}function i(o){var s=[],a={},h={};function f(l){r.has(h,l)||(h[l]=!0,a[l]=!0,r.forEach(o.outEdges(l),function(g){r.has(a,g.w)?s.push(g):f(g.w)}),delete a[l])}return r.forEach(o.nodes(),f),s}function n(o){r.forEach(o.edges(),function(s){var a=o.edge(s);if(a.reversed){o.removeEdge(s);var h=a.forwardName;delete a.reversed,delete a.forwardName,o.setEdge(s.w,s.v,a,h)}})}return il}var nl,Zq;function dr(){if(Zq)return nl;Zq=1;var r=Fe(),e=kr().Graph;nl={addDummyNode:t,simplify:i,asNonCompoundGraph:n,successorWeights:o,predecessorWeights:s,intersectRect:a,buildLayerMatrix:h,normalizeRanks:f,removeEmptyRanks:l,addBorderNode:g,maxRank:m,partition:_,time:E,notime:q};function t(x,A,S,I){var M;do M=r.uniqueId(I);while(x.hasNode(M));return S.dummy=A,x.setNode(M,S),M}function i(x){var A=new e().setGraph(x.graph());return r.forEach(x.nodes(),function(S){A.setNode(S,x.node(S))}),r.forEach(x.edges(),function(S){var I=A.edge(S.v,S.w)||{weight:0,minlen:1},M=x.edge(S);A.setEdge(S.v,S.w,{weight:I.weight+M.weight,minlen:Math.max(I.minlen,M.minlen)})}),A}function n(x){var A=new e({multigraph:x.isMultigraph()}).setGraph(x.graph());return r.forEach(x.nodes(),function(S){x.children(S).length||A.setNode(S,x.node(S))}),r.forEach(x.edges(),function(S){A.setEdge(S,x.edge(S))}),A}function o(x){var A=r.map(x.nodes(),function(S){var I={};return r.forEach(x.outEdges(S),function(M){I[M.w]=(I[M.w]||0)+x.edge(M).weight}),I});return r.zipObject(x.nodes(),A)}function s(x){var A=r.map(x.nodes(),function(S){var I={};return r.forEach(x.inEdges(S),function(M){I[M.v]=(I[M.v]||0)+x.edge(M).weight}),I});return r.zipObject(x.nodes(),A)}function a(x,A){var S=x.x,I=x.y,M=A.x-S,D=A.y-I,z=x.width/2,O=x.height/2;if(!M&&!D)throw new Error("Not possible to find intersection inside of the rectangle");var N,j;return Math.abs(D)*z>Math.abs(M)*O?(D<0&&(O=-O),N=O*M/D,j=O):(M<0&&(z=-z),N=z,j=z*D/M),{x:S+N,y:I+j}}function h(x){var A=r.map(r.range(m(x)+1),function(){return[]});return r.forEach(x.nodes(),function(S){var I=x.node(S),M=I.rank;r.isUndefined(M)||(A[M][I.order]=S)}),A}function f(x){var A=r.min(r.map(x.nodes(),function(S){return x.node(S).rank}));r.forEach(x.nodes(),function(S){var I=x.node(S);r.has(I,"rank")&&(I.rank-=A)})}function l(x){var A=r.min(r.map(x.nodes(),function(D){return x.node(D).rank})),S=[];r.forEach(x.nodes(),function(D){var z=x.node(D).rank-A;S[z]||(S[z]=[]),S[z].push(D)});var I=0,M=x.graph().nodeRankFactor;r.forEach(S,function(D,z){r.isUndefined(D)&&z%M!==0?--I:I&&r.forEach(D,function(O){x.node(O).rank+=I})})}function g(x,A,S,I){var M={width:0,height:0};return arguments.length>=4&&(M.rank=S,M.order=I),t(x,"border",M,A)}function m(x){return r.max(r.map(x.nodes(),function(A){var S=x.node(A).rank;if(!r.isUndefined(S))return S}))}function _(x,A){var S={lhs:[],rhs:[]};return r.forEach(x,function(I){A(I)?S.lhs.push(I):S.rhs.push(I)}),S}function E(x,A){var S=r.now();try{return A()}finally{console.log(x+" time: "+(r.now()-S)+"ms")}}function q(x,A){return A()}return nl}var ol,Jq;function Hq(){if(Jq)return ol;Jq=1;var r=Fe(),e=dr();ol={run:t,undo:n};function t(o){o.graph().dummyChains=[],r.forEach(o.edges(),function(s){i(o,s)})}function i(o,s){var a=s.v,h=o.node(a).rank,f=s.w,l=o.node(f).rank,g=s.name,m=o.edge(s),_=m.labelRank;if(l!==h+1){o.removeEdge(s);var E,q,x;for(x=0,++h;hj.lim&&(X=j,re=!0);var oe=r.filter(M.edges(),function(me){return re===S(I,I.node(me.v),X)&&re!==S(I,I.node(me.w),X)});return r.minBy(oe,function(me){return t(M,me)})}function q(I,M,D,z){var O=D.v,N=D.w;I.removeEdge(O,N),I.setEdge(z.v,z.w,{}),g(I),h(I,M),x(I,M)}function x(I,M){var D=r.find(I.nodes(),function(O){return!M.node(O).parent}),z=n(I,D);z=z.slice(1),r.forEach(z,function(O){var N=I.node(O).parent,j=M.edge(O,N),X=!1;j||(j=M.edge(N,O),X=!0),M.node(O).rank=M.node(N).rank+(X?j.minlen:-j.minlen)})}function A(I,M,D){return I.hasEdge(M,D)}function S(I,M,D){return D.low<=M.lim&&M.lim<=D.lim}return ul}var fl,nb;function ob(){if(nb)return fl;nb=1;var r=Ci(),e=r.longestPath,t=_s(),i=ib();fl=n;function n(h){switch(h.graph().ranker){case"network-simplex":a(h);break;case"tight-tree":s(h);break;case"longest-path":o(h);break;default:a(h)}}var o=e;function s(h){e(h),t(h)}function a(h){i(h)}return fl}var hl,sb;function ab(){if(sb)return hl;sb=1;var r=Fe();hl=e;function e(n){var o=i(n);r.forEach(n.graph().dummyChains,function(s){for(var a=n.node(s),h=a.edgeObj,f=t(n,o,h.v,h.w),l=f.path,g=f.lca,m=0,_=l[m],E=!0;s!==h.w;){if(a=n.node(s),E){for(;(_=l[m])!==g&&n.node(_).maxRankl||g>o[m].lim));for(_=m,m=a;(m=n.parent(m))!==_;)f.push(m);return{path:h.concat(f.reverse()),lca:_}}function i(n){var o={},s=0;function a(h){var f=s;r.forEach(n.children(h),a),o[h]={low:f,lim:s++}}return r.forEach(n.children(),a),o}return hl}var cl,ub;function fb(){if(ub)return cl;ub=1;var r=Fe(),e=dr();cl={run:t,cleanup:s};function t(a){var h=e.addDummyNode(a,"root",{},"_root"),f=n(a),l=r.max(r.values(f))-1,g=2*l+1;a.graph().nestingRoot=h,r.forEach(a.edges(),function(_){a.edge(_).minlen*=g});var m=o(a)+1;r.forEach(a.children(),function(_){i(a,h,g,m,l,f,_)}),a.graph().nodeRankFactor=g}function i(a,h,f,l,g,m,_){var E=a.children(_);if(!E.length){_!==h&&a.setEdge(h,_,{weight:0,minlen:f});return}var q=e.addBorderNode(a,"_bt"),x=e.addBorderNode(a,"_bb"),A=a.node(_);a.setParent(q,_),A.borderTop=q,a.setParent(x,_),A.borderBottom=x,r.forEach(E,function(S){i(a,h,f,l,g,m,S);var I=a.node(S),M=I.borderTop?I.borderTop:S,D=I.borderBottom?I.borderBottom:S,z=I.borderTop?l:2*l,O=M!==D?1:g-m[_]+1;a.setEdge(q,M,{weight:z,minlen:O,nestingEdge:!0}),a.setEdge(D,x,{weight:z,minlen:O,nestingEdge:!0})}),a.parent(_)||a.setEdge(h,q,{weight:0,minlen:g+m[_]})}function n(a){var h={};function f(l,g){var m=a.children(l);m&&m.length&&r.forEach(m,function(_){f(_,g+1)}),h[l]=g}return r.forEach(a.children(),function(l){f(l,1)}),h}function o(a){return r.reduce(a.edges(),function(h,f){return h+a.edge(f).weight},0)}function s(a){var h=a.graph();a.removeNode(h.nestingRoot),delete h.nestingRoot,r.forEach(a.edges(),function(f){var l=a.edge(f);l.nestingEdge&&a.removeEdge(f)})}return cl}var ll,hb;function cb(){if(hb)return ll;hb=1;var r=Fe(),e=dr();ll=t;function t(n){function o(s){var a=n.children(s),h=n.node(s);if(a.length&&r.forEach(a,o),r.has(h,"minRank")){h.borderLeft=[],h.borderRight=[];for(var f=h.minRank,l=h.maxRank+1;f0;)_%2&&(E+=l[_+1]),_=_-1>>1,l[_]+=m.weight;g+=m.weight*E})),g}return gl}var ml,_b;function vb(){if(_b)return ml;_b=1;var r=Fe();ml=e;function e(t,i){return r.map(i,function(n){var o=t.inEdges(n);if(o.length){var s=r.reduce(o,function(a,h){var f=t.edge(h),l=t.node(h.v);return{sum:a.sum+f.weight*l.order,weight:a.weight+f.weight}},{sum:0,weight:0});return{v:n,barycenter:s.sum/s.weight,weight:s.weight}}else return{v:n}})}return ml}var yl,wb;function qb(){if(wb)return yl;wb=1;var r=Fe();yl=e;function e(n,o){var s={};r.forEach(n,function(h,f){var l=s[h.v]={indegree:0,in:[],out:[],vs:[h.v],i:f};r.isUndefined(h.barycenter)||(l.barycenter=h.barycenter,l.weight=h.weight)}),r.forEach(o.edges(),function(h){var f=s[h.v],l=s[h.w];!r.isUndefined(f)&&!r.isUndefined(l)&&(l.indegree++,f.out.push(s[h.w]))});var a=r.filter(s,function(h){return!h.indegree});return t(a)}function t(n){var o=[];function s(f){return function(l){l.merged||(r.isUndefined(l.barycenter)||r.isUndefined(f.barycenter)||l.barycenter>=f.barycenter)&&i(f,l)}}function a(f){return function(l){l.in.push(f),--l.indegree===0&&n.push(l)}}for(;n.length;){var h=n.pop();o.push(h),r.forEach(h.in.reverse(),s(h)),r.forEach(h.out,a(h))}return r.map(r.filter(o,function(f){return!f.merged}),function(f){return r.pick(f,["vs","i","barycenter","weight"])})}function i(n,o){var s=0,a=0;n.weight&&(s+=n.barycenter*n.weight,a+=n.weight),o.weight&&(s+=o.barycenter*o.weight,a+=o.weight),n.vs=o.vs.concat(n.vs),n.barycenter=s/a,n.weight=a,n.i=Math.min(o.i,n.i),o.merged=!0}return yl}var _l,bb;function Eb(){if(bb)return _l;bb=1;var r=Fe(),e=dr();_l=t;function t(o,s){var a=e.partition(o,function(q){return r.has(q,"barycenter")}),h=a.lhs,f=r.sortBy(a.rhs,function(q){return-q.i}),l=[],g=0,m=0,_=0;h.sort(n(!!s)),_=i(l,f,_),r.forEach(h,function(q){_+=q.vs.length,l.push(q.vs),g+=q.barycenter*q.weight,m+=q.weight,_=i(l,f,_)});var E={vs:r.flatten(l,!0)};return m&&(E.barycenter=g/m,E.weight=m),E}function i(o,s,a){for(var h;s.length&&(h=r.last(s)).i<=a;)s.pop(),o.push(h.vs),a++;return a}function n(o){return function(s,a){return s.barycentera.barycenter?1:o?a.i-s.i:s.i-a.i}}return _l}var vl,xb;function Sb(){if(xb)return vl;xb=1;var r=Fe(),e=vb(),t=qb(),i=Eb();vl=n;function n(a,h,f,l){var g=a.children(h),m=a.node(h),_=m?m.borderLeft:void 0,E=m?m.borderRight:void 0,q={};_&&(g=r.filter(g,function(D){return D!==_&&D!==E}));var x=e(a,g);r.forEach(x,function(D){if(a.children(D.v).length){var z=n(a,D.v,f,l);q[D.v]=z,r.has(z,"barycenter")&&s(D,z)}});var A=t(x,f);o(A,q);var S=i(A,l);if(_&&(S.vs=r.flatten([_,S.vs,E],!0),a.predecessors(_).length)){var I=a.node(a.predecessors(_)[0]),M=a.node(a.predecessors(E)[0]);r.has(S,"barycenter")||(S.barycenter=0,S.weight=0),S.barycenter=(S.barycenter*S.weight+I.order+M.order)/(S.weight+2),S.weight+=2}return S}function o(a,h){r.forEach(a,function(f){f.vs=r.flatten(f.vs.map(function(l){return h[l]?h[l].vs:l}),!0)})}function s(a,h){r.isUndefined(a.barycenter)?(a.barycenter=h.barycenter,a.weight=h.weight):(a.barycenter=(a.barycenter*a.weight+h.barycenter*h.weight)/(a.weight+h.weight),a.weight+=h.weight)}return vl}var wl,Ib;function Ab(){if(Ib)return wl;Ib=1;var r=Fe(),e=kr().Graph;wl=t;function t(n,o,s){var a=i(n),h=new e({compound:!0}).setGraph({root:a}).setDefaultNodeLabel(function(f){return n.node(f)});return r.forEach(n.nodes(),function(f){var l=n.node(f),g=n.parent(f);(l.rank===o||l.minRank<=o&&o<=l.maxRank)&&(h.setNode(f),h.setParent(f,g||a),r.forEach(n[s](f),function(m){var _=m.v===f?m.w:m.v,E=h.edge(_,f),q=r.isUndefined(E)?0:E.weight;h.setEdge(_,f,{weight:n.edge(m).weight+q})}),r.has(l,"minRank")&&h.setNode(f,{borderLeft:l.borderLeft[o],borderRight:l.borderRight[o]}))}),h}function i(n){for(var o;n.hasNode(o=r.uniqueId("_root")););return o}return wl}var ql,Rb;function Cb(){if(Rb)return ql;Rb=1;var r=Fe();ql=e;function e(t,i,n){var o={},s;r.forEach(n,function(a){for(var h=t.parent(a),f,l;h;){if(f=t.parent(h),f?(l=o[f],o[f]=h):(l=s,s=h),l&&l!==h){i.setEdge(l,h);return}h=f}})}return ql}var bl,Tb;function Ob(){if(Tb)return bl;Tb=1;var r=Fe(),e=gb(),t=yb(),i=Sb(),n=Ab(),o=Cb(),s=kr().Graph,a=dr();bl=h;function h(m){var _=a.maxRank(m),E=f(m,r.range(1,_+1),"inEdges"),q=f(m,r.range(_-1,-1,-1),"outEdges"),x=e(m);g(m,x);for(var A=Number.POSITIVE_INFINITY,S,I=0,M=0;M<4;++I,++M){l(I%2?E:q,I%4>=2),x=a.buildLayerMatrix(m);var D=t(m,x);DX)&&s(I,me,re)})})}function D(z,O){var N=-1,j,X=0;return r.forEach(O,function(re,oe){if(A.node(re).dummy==="border"){var me=A.predecessors(re);me.length&&(j=A.node(me[0]).order,M(O,X,oe,N,j),X=oe,N=j)}M(O,X,O.length,j,z.length)}),O}return r.reduce(S,D),I}function o(A,S){if(A.node(S).dummy)return r.find(A.predecessors(S),function(I){return A.node(I).dummy})}function s(A,S,I){if(S>I){var M=S;S=I,I=M}var D=A[S];D||(A[S]=D={}),D[I]=!0}function a(A,S,I){if(S>I){var M=S;S=I,I=M}return r.has(A[S],I)}function h(A,S,I,M){var D={},z={},O={};return r.forEach(S,function(N){r.forEach(N,function(j,X){D[j]=j,z[j]=j,O[j]=X})}),r.forEach(S,function(N){var j=-1;r.forEach(N,function(X){var re=M(X);if(re.length){re=r.sortBy(re,function(Ne){return O[Ne]});for(var oe=(re.length-1)/2,me=Math.floor(oe),_e=Math.ceil(oe);me<=_e;++me){var Te=re[me];z[X]===X&&j({}));let t=Rn(this.options.nodeSize,0);this.model.forEachNode(_=>{let E=_._original,[q,x]=zi(t(E)),A={width:q,height:x};if(e.setNode(String(_.id),A),this.isCompound()){if(tt(_.parentId))return;e.setParent(String(_.id),String(_.parentId))}});let{edgeLabelSize:i,edgeLabelOffset:n,edgeLabelPos:o,edgeMinLen:s,edgeWeight:a}=this.options,h=Rn(i,0,"edge"),f=no(n,10,"edge"),l=typeof o=="string"?()=>o:ti(o,["edge"]),g=no(s,1,"edge"),m=no(a,1,"edge");this.model.forEachEdge(_=>{let E=_._original,[q,x]=zi(h(E)),A={width:q,height:x,labelpos:l(E),labeloffset:f(E),minlen:g(E),weight:m(E)};e.setEdge(String(_.source),String(_.target),A,String(_.id))}),Wb.layout(e),this.model.forEachNode(_=>{let E=e.node(String(_.id));E&&(_.x=E.x,_.y=E.y,_.size=[E.width,E.height])}),this.model.forEachEdge(_=>{let E=e.edge(String(_.source),String(_.target),String(_.id));if(!E)return;let{width:q,height:x,weight:A,minlen:S,labelpos:I,labeloffset:M,points:D}=E;_.labelSize=[q,x],_.weight=A,_.minLen=S,_.labelPos=I,_.labelOffset=M,_.points=D.map(Kp)})})}isCompound(){return this.isCompoundGraph!==null?this.isCompoundGraph:Bb(this.options.compound)?this.isCompoundGraph=this.options.compound:(this.isCompoundGraph=this.model.nodes().some(e=>!tt(e.parentId)),this.isCompoundGraph)}};var Ke={};var Tl={};$s(Tl,{isAnyArray:()=>wi});var zI=Object.prototype.toString;function wi(r){let e=zI.call(r);return e.endsWith("Array]")&&!e.includes("Big")}var Yb=vo(Tl);var Ol={};$s(Ol,{default:()=>$I});function Xb(r){var e=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};if(!wi(r))throw new TypeError("input must be an array");if(r.length===0)throw new TypeError("input must not be empty");var t=e.fromIndex,i=t===void 0?0:t,n=e.toIndex,o=n===void 0?r.length:n;if(i<0||i>=r.length||!Number.isInteger(i))throw new Error("fromIndex must be a positive integer smaller than length");if(o<=i||o>r.length||!Number.isInteger(o))throw new Error("toIndex must be an integer greater than fromIndex and at most equal to length");for(var s=r[i],a=i+1;as&&(s=r[a]);return s}function Qb(r){var e=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};if(!wi(r))throw new TypeError("input must be an array");if(r.length===0)throw new TypeError("input must not be empty");var t=e.fromIndex,i=t===void 0?0:t,n=e.toIndex,o=n===void 0?r.length:n;if(i<0||i>=r.length||!Number.isInteger(i))throw new Error("fromIndex must be a positive integer smaller than length");if(o<=i||o>r.length||!Number.isInteger(o))throw new Error("toIndex must be an integer greater than fromIndex and at most equal to length");for(var s=r[i],a=i+1;a1&&arguments[1]!==void 0?arguments[1]:{};if(wi(r)){if(r.length===0)throw new TypeError("input must not be empty")}else throw new TypeError("input must be an array");var t;if(e.output!==void 0){if(!wi(e.output))throw new TypeError("output option must be an array if specified");t=e.output}else t=new Array(r.length);var i=Qb(r),n=Xb(r);if(i===n)throw new RangeError("minimum and maximum input values are equal. Cannot rescale a constant array");var o=e.min,s=o===void 0?e.autoMinMax?i:0:o,a=e.max,h=a===void 0?e.autoMinMax?n:1:a;if(s>=h)throw new RangeError("min option must be smaller than max option");for(var f=(h-s)/(n-i),l=0;l=0&&c?` ${h(w,p-1)}`:h(w,p)).padEnd(p)}function h(w,p){let c=w.toString();if(c.length<=p)return c;let u=w.toFixed(p);if(u.length>p&&(u=w.toFixed(Math.max(0,p-(u.length-p)))),u.length<=p&&!u.startsWith("0.000")&&!u.startsWith("-0.000"))return u;let d=w.toExponential(p);return d.length>p&&(d=w.toExponential(Math.max(0,p-(d.length-p)))),d.slice(0)}function f(w,p){w.prototype.add=function(u){return typeof u=="number"?this.addS(u):this.addM(u)},w.prototype.addS=function(u){for(let d=0;d>u);return this},w.prototype.signPropagatingRightShiftM=function(u){if(u=p.checkMatrix(u),this.rows!==u.rows||this.columns!==u.columns)throw new RangeError("Matrices dimensions must be equal");for(let d=0;d>u.get(d,y));return this},w.signPropagatingRightShift=function(u,d){return new p(u).signPropagatingRightShift(d)},w.prototype.rightShift=function(u){return typeof u=="number"?this.rightShiftS(u):this.rightShiftM(u)},w.prototype.rightShiftS=function(u){for(let d=0;d>>u);return this},w.prototype.rightShiftM=function(u){if(u=p.checkMatrix(u),this.rows!==u.rows||this.columns!==u.columns)throw new RangeError("Matrices dimensions must be equal");for(let d=0;d>>u.get(d,y));return this},w.rightShift=function(u,d){return new p(u).rightShift(d)},w.prototype.zeroFillRightShift=w.prototype.rightShift,w.prototype.zeroFillRightShiftS=w.prototype.rightShiftS,w.prototype.zeroFillRightShiftM=w.prototype.rightShiftM,w.zeroFillRightShift=w.rightShift,w.prototype.not=function(){for(let u=0;uu)throw new RangeError("Row index out of range")}function g(w,p,c){let u=c?w.columns:w.columns-1;if(p<0||p>u)throw new RangeError("Column index out of range")}function m(w,p){if(p.to1DArray&&(p=p.to1DArray()),p.length!==w.columns)throw new RangeError("vector size must be the same as the number of columns");return p}function _(w,p){if(p.to1DArray&&(p=p.to1DArray()),p.length!==w.rows)throw new RangeError("vector size must be the same as the number of rows");return p}function E(w,p){if(!r.isAnyArray(p))throw new TypeError("row indices must be an array");for(let c=0;c=w.rows)throw new RangeError("row indices are out of range")}function q(w,p){if(!r.isAnyArray(p))throw new TypeError("column indices must be an array");for(let c=0;c=w.columns)throw new RangeError("column indices are out of range")}function x(w,p,c,u,d){if(arguments.length!==5)throw new RangeError("expected 4 arguments");if(S("startRow",p),S("endRow",c),S("startColumn",u),S("endColumn",d),p>c||u>d||p<0||p>=w.rows||c<0||c>=w.rows||u<0||u>=w.columns||d<0||d>=w.columns)throw new RangeError("Submatrix indices are out of range")}function A(w,p=0){let c=[];for(let u=0;u=y)throw new RangeError("min must be smaller than max");let C=y-d,T=new W(p,c);for(let L=0;Lu?(y=!0,u=c):(d=!1,y=!0);p++}return d}isReducedEchelonForm(){let p=0,c=0,u=-1,d=!0,y=!1;for(;pu?(y=!0,u=c):(d=!1,y=!0);for(let R=c+1;Rp.get(d,u)&&(d=y);if(p.get(d,u)===0)u++;else{p.swapRows(c,d);let y=p.get(c,u);for(let R=u;R=0;)if(p.maxRow(d)===0)d--;else{let y=0,R=!1;for(;yc[u]&&(c[u]=this.get(u,d));return c}case"column":{let c=new Array(this.columns).fill(Number.NEGATIVE_INFINITY);for(let u=0;uc[d]&&(c[d]=this.get(u,d));return c}case void 0:{let c=this.get(0,0);for(let u=0;uc&&(c=this.get(u,d));return c}default:throw new Error(`invalid option: ${p}`)}}maxIndex(){I(this);let p=this.get(0,0),c=[0,0];for(let u=0;up&&(p=this.get(u,d),c[0]=u,c[1]=d);return c}min(p){if(this.isEmpty())return NaN;switch(p){case"row":{let c=new Array(this.rows).fill(Number.POSITIVE_INFINITY);for(let u=0;uc&&(c=this.get(p,u));return c}maxRowIndex(p){l(this,p),I(this);let c=this.get(p,0),u=[p,0];for(let d=1;dc&&(c=this.get(p,d),u[1]=d);return u}minRow(p){if(l(this,p),this.isEmpty())return NaN;let c=this.get(p,0);for(let u=1;uc&&(c=this.get(u,p));return c}maxColumnIndex(p){g(this,p),I(this);let c=this.get(0,p),u=[0,p];for(let d=1;dc&&(c=this.get(d,p),u[0]=d);return u}minColumn(p){if(g(this,p),this.isEmpty())return NaN;let c=this.get(0,p);for(let u=1;u=1;d/=2)(d&1)!==0&&(c=c.mmul(u)),u=u.mmul(u);return c}strassen2x2(p){p=W.checkMatrix(p);let c=new W(2,2),u=this.get(0,0),d=p.get(0,0),y=this.get(0,1),R=p.get(0,1),C=this.get(1,0),T=p.get(1,0),L=this.get(1,1),V=p.get(1,1),F=(u+L)*(d+V),ee=(C+L)*d,ce=u*(R-V),H=L*(T-d),se=(u+y)*V,qe=(C-u)*(d+R),$=(y-L)*(T+V),ye=F+H-se+$,Re=ce+se,$e=ee+H,Ue=F-ee+ce+qe;return c.set(0,0,ye),c.set(0,1,Re),c.set(1,0,$e),c.set(1,1,Ue),c}strassen3x3(p){p=W.checkMatrix(p);let c=new W(3,3),u=this.get(0,0),d=this.get(0,1),y=this.get(0,2),R=this.get(1,0),C=this.get(1,1),T=this.get(1,2),L=this.get(2,0),V=this.get(2,1),F=this.get(2,2),ee=p.get(0,0),ce=p.get(0,1),H=p.get(0,2),se=p.get(1,0),qe=p.get(1,1),$=p.get(1,2),ye=p.get(2,0),Re=p.get(2,1),$e=p.get(2,2),Ue=(u+d+y-R-C-V-F)*qe,gr=(u-R)*(-ce+qe),ke=C*(-ee+ce+se-qe-$-ye+$e),je=(-u+R+C)*(ee-ce+qe),ur=(R+C)*(-ee+ce),Y=u*ee,he=(-u+L+V)*(ee-H+$),xe=(-u+L)*(H-$),pe=(L+V)*(-ee+H),mr=(u+d+y-C-T-L-V)*$,ir=V*(-ee+H+se-qe-$-ye+Re),lr=(-y+V+F)*(qe+ye-Re),yr=(y-F)*(qe-Re),Kr=y*ye,It=(V+F)*(-ye+Re),Gr=(-y+C+T)*($+ye-$e),kt=(y-T)*($-$e),Bt=(C+T)*(-ye+$e),Qe=d*se,Yr=T*Re,lt=R*H,dt=L*ce,Nr=F*$e,QE=Y+Kr+Qe,ZE=Ue+je+ur+Y+lr+Kr+It,JE=Y+he+pe+mr+Kr+Gr+Bt,HE=gr+ke+je+Y+Kr+Gr+kt,ex=gr+je+ur+Y+Yr,rx=Kr+Gr+kt+Bt+lt,tx=Y+he+xe+ir+lr+yr+Kr,ix=lr+yr+Kr+It+dt,nx=Y+he+xe+pe+Nr;return c.set(0,0,QE),c.set(0,1,ZE),c.set(0,2,JE),c.set(1,0,HE),c.set(1,1,ex),c.set(1,2,rx),c.set(2,0,tx),c.set(2,1,ix),c.set(2,2,nx),c}mmulStrassen(p){p=W.checkMatrix(p);let c=this.clone(),u=c.rows,d=c.columns,y=p.rows,R=p.columns;d!==y&&console.warn(`Multiplying ${u} x ${d} and ${y} x ${R} matrix: dimensions do not match.`);function C(F,ee,ce){let H=F.rows,se=F.columns;if(H===ee&&se===ce)return F;{let qe=U.zeros(ee,ce);return qe=qe.setSubMatrix(F,0,0),qe}}let T=Math.max(u,y),L=Math.max(d,R);c=C(c,T,L),p=C(p,T,L);function V(F,ee,ce,H){if(ce<=512||H<=512)return F.mmul(ee);ce%2===1&&H%2===1?(F=C(F,ce+1,H+1),ee=C(ee,ce+1,H+1)):ce%2===1?(F=C(F,ce+1,H),ee=C(ee,ce+1,H)):H%2===1&&(F=C(F,ce,H+1),ee=C(ee,ce,H+1));let se=parseInt(F.rows/2,10),qe=parseInt(F.columns/2,10),$=F.subMatrix(0,se-1,0,qe-1),ye=ee.subMatrix(0,se-1,0,qe-1),Re=F.subMatrix(0,se-1,qe,F.columns-1),$e=ee.subMatrix(0,se-1,qe,ee.columns-1),Ue=F.subMatrix(se,F.rows-1,0,qe-1),gr=ee.subMatrix(se,ee.rows-1,0,qe-1),ke=F.subMatrix(se,F.rows-1,qe,F.columns-1),je=ee.subMatrix(se,ee.rows-1,qe,ee.columns-1),ur=V(U.add($,ke),U.add(ye,je),se,qe),Y=V(U.add(Ue,ke),ye,se,qe),he=V($,U.sub($e,je),se,qe),xe=V(ke,U.sub(gr,ye),se,qe),pe=V(U.add($,Re),je,se,qe),mr=V(U.sub(Ue,$),U.add(ye,$e),se,qe),ir=V(U.sub(Re,ke),U.add(gr,je),se,qe),lr=U.add(ur,xe);lr.sub(pe),lr.add(ir);let yr=U.add(he,pe),Kr=U.add(Y,xe),It=U.sub(ur,Y);It.add(he),It.add(mr);let Gr=U.zeros(2*lr.rows,2*lr.columns);return Gr=Gr.setSubMatrix(lr,0,0),Gr=Gr.setSubMatrix(yr,lr.rows,0),Gr=Gr.setSubMatrix(Kr,0,lr.columns),Gr=Gr.setSubMatrix(It,lr.rows,lr.columns),Gr.subMatrix(0,ce-1,0,H-1)}return V(c,p,T,L)}scaleRows(p={}){if(typeof p!="object")throw new TypeError("options must be an object");let{min:c=0,max:u=1}=p;if(!Number.isFinite(c))throw new TypeError("min must be a number");if(!Number.isFinite(u))throw new TypeError("max must be a number");if(c>=u)throw new RangeError("min must be smaller than max");let d=new W(this.rows,this.columns);for(let y=0;y0&&e(R,{min:c,max:u,output:R}),d.setRow(y,R)}return d}scaleColumns(p={}){if(typeof p!="object")throw new TypeError("options must be an object");let{min:c=0,max:u=1}=p;if(!Number.isFinite(c))throw new TypeError("min must be a number");if(!Number.isFinite(u))throw new TypeError("max must be a number");if(c>=u)throw new RangeError("min must be smaller than max");let d=new W(this.rows,this.columns);for(let y=0;yu||c<0||c>=this.columns||u<0||u>=this.columns)throw new RangeError("Argument out of range");let d=new W(p.length,u-c+1);for(let y=0;y=this.rows)throw new RangeError(`Row index out of range: ${p[y]}`);d.set(y,R-c,this.get(p[y],R))}return d}subMatrixColumn(p,c,u){if(c===void 0&&(c=0),u===void 0&&(u=this.rows-1),c>u||c<0||c>=this.rows||u<0||u>=this.rows)throw new RangeError("Argument out of range");let d=new W(u-c+1,p.length);for(let y=0;y=this.columns)throw new RangeError(`Column index out of range: ${p[y]}`);d.set(R-c,y,this.get(R,p[y]))}return d}setSubMatrix(p,c,u){if(p=W.checkMatrix(p),p.isEmpty())return this;let d=c+p.rows-1,y=u+p.columns-1;x(this,c,d,u,y);for(let R=0;Rtypeof p=="number")}U.random=U.rand,U.randomInt=U.randInt,U.diagonal=U.diag,U.prototype.diagonal=U.prototype.diag,U.identity=U.eye,U.prototype.negate=U.prototype.neg,U.prototype.tensorProduct=U.prototype.kroneckerProduct;let ve=class ve extends U{constructor(c,u){super();Ws(this,Q);cd(this,"data");if(ve.isMatrix(c))Bs(this,Q,kl).call(this,c.rows,c.columns),ve.copy(c,this);else if(Number.isInteger(c)&&c>=0)Bs(this,Q,kl).call(this,c,u);else if(r.isAnyArray(c)){let d=c;if(c=d.length,u=c?d[0].length:0,typeof u!="number")throw new TypeError("Data must be a 2D array with at least one element");this.data=[];for(let y=0;y"u"&&(u=c,c=this.columns),g(this,c,!0),u=_(this,u);for(let d=0;d=0)for(let d=0;d=0)$n(this,Ce,new W(c,c));else if($n(this,Ce,new W(c)),!this.isSymmetric())throw new TypeError("not symmetric data")}get size(){return At(this,Ce).size}get rows(){return At(this,Ce).rows}get columns(){return At(this,Ce).columns}get diagonalSize(){return this.rows}static isSymmetricMatrix(c){return W.isMatrix(c)&&c.klassType==="SymmetricMatrix"}static zeros(c){return new this(c)}static ones(c){return new this(c).fill(1)}clone(){let c=new Me(this.diagonalSize);for(let[u,d,y]of this.upperRightEntries())c.set(u,d,y);return c}toMatrix(){return new W(this)}get(c,u){return At(this,Ce).get(c,u)}set(c,u,d){return At(this,Ce).set(c,u,d),At(this,Ce).set(u,c,d),this}removeCross(c){return At(this,Ce).removeRow(c),At(this,Ce).removeColumn(c),this}addCross(c,u){u===void 0&&(u=c,c=this.diagonalSize);let d=u.slice();return d.splice(c,1),At(this,Ce).addRow(c,d),At(this,Ce).addColumn(c,u),this}applyMask(c){if(c.length!==this.diagonalSize)throw new RangeError("Mask size do not match with matrix size");let u=[];for(let[d,y]of c.entries())y||u.push(d);u.reverse();for(let d of u)this.removeCross(d);return this}toCompact(){let{diagonalSize:c}=this,u=new Array(c*(c+1)/2);for(let d=0,y=0,R=0;R=c&&(d=++y);return u}static fromCompact(c){let u=c.length,d=(Math.sqrt(8*u+1)-1)/2;if(!Number.isInteger(d))throw new TypeError(`This array is not a compact representation of a Symmetric Matrix, ${JSON.stringify(c)}`);let y=new Me(d);for(let R=0,C=0,T=0;T=d&&(R=++C);return y}*upperRightEntries(){for(let c=0,u=0;c=this.diagonalSize&&(u=++c)}}*upperRightValues(){for(let c=0,u=0;c=this.diagonalSize&&(u=++c)}};Ce=new WeakMap;let ue=Me;ue.prototype.klassType="SymmetricMatrix";class le extends ue{static isDistanceMatrix(p){return ue.isSymmetricMatrix(p)&&p.klassSubType==="DistanceMatrix"}constructor(p){if(super(p),!this.isDistance())throw new TypeError("Provided arguments do no produce a distance matrix")}set(p,c,u){return p===c&&(u=0),super.set(p,c,u)}addCross(p,c){return c===void 0&&(c=p,p=this.diagonalSize),c=c.slice(),c[p]=0,super.addCross(p,c)}toSymmetricMatrix(){return new ue(this)}clone(){let p=new le(this.diagonalSize);for(let[c,u,d]of this.upperRightEntries())c!==u&&p.set(c,u,d);return p}toCompact(){let{diagonalSize:p}=this,c=(p-1)*p/2,u=new Array(c);for(let d=1,y=0,R=0;R=p&&(d=++y+1);return u}static fromCompact(p){let c=p.length;if(c===0)return new this(0);let u=(Math.sqrt(8*c+1)+1)/2;if(!Number.isInteger(u))throw new TypeError(`This array is not a compact representation of a DistanceMatrix, ${JSON.stringify(p)}`);let d=new this(u);for(let y=1,R=0,C=0;C=u&&(y=++R+1);return d}}le.prototype.klassSubType="DistanceMatrix";class de extends U{constructor(p,c,u){super(),this.matrix=p,this.rows=c,this.columns=u}}class Ye extends de{constructor(p,c){g(p,c),super(p,p.rows,1),this.column=c}set(p,c,u){return this.matrix.set(p,this.column,u),this}get(p){return this.matrix.get(p,this.column)}}class Be extends de{constructor(p,c){q(p,c),super(p,p.rows,c.length),this.columnIndices=c}set(p,c,u){return this.matrix.set(p,this.columnIndices[c],u),this}get(p,c){return this.matrix.get(p,this.columnIndices[c])}}class wr extends de{constructor(p){super(p,p.rows,p.columns)}set(p,c,u){return this.matrix.set(p,this.columns-c-1,u),this}get(p,c){return this.matrix.get(p,this.columns-c-1)}}class er extends de{constructor(p){super(p,p.rows,p.columns)}set(p,c,u){return this.matrix.set(this.rows-p-1,c,u),this}get(p,c){return this.matrix.get(this.rows-p-1,c)}}class qr extends de{constructor(p,c){l(p,c),super(p,1,p.columns),this.row=c}set(p,c,u){return this.matrix.set(this.row,c,u),this}get(p,c){return this.matrix.get(this.row,c)}}class Xe extends de{constructor(p,c){E(p,c),super(p,c.length,p.columns),this.rowIndices=c}set(p,c,u){return this.matrix.set(this.rowIndices[p],c,u),this}get(p,c){return this.matrix.get(this.rowIndices[p],c)}}class Ae extends de{constructor(p,c,u){E(p,c),q(p,u),super(p,c.length,u.length),this.rowIndices=c,this.columnIndices=u}set(p,c,u){return this.matrix.set(this.rowIndices[p],this.columnIndices[c],u),this}get(p,c){return this.matrix.get(this.rowIndices[p],this.columnIndices[c])}}class ze extends de{constructor(p,c,u,d,y){x(p,c,u,d,y),super(p,u-c+1,y-d+1),this.startRow=c,this.startColumn=d}set(p,c,u){return this.matrix.set(this.startRow+p,this.startColumn+c,u),this}get(p,c){return this.matrix.get(this.startRow+p,this.startColumn+c)}}class be extends de{constructor(p){super(p,p.columns,p.rows)}set(p,c,u){return this.matrix.set(c,p,u),this}get(p,c){return this.matrix.get(c,p)}}class sr extends U{constructor(p,c={}){let{rows:u=1}=c;if(p.length%u!==0)throw new Error("the data length is not divisible by the number of rows");super(),this.rows=u,this.columns=p.length/u,this.data=p}set(p,c,u){let d=this._calculateIndex(p,c);return this.data[d]=u,this}get(p,c){let u=this._calculateIndex(p,c);return this.data[u]}_calculateIndex(p,c){return p*this.columns+c}}class Se extends U{constructor(p){super(),this.data=p,this.rows=p.length,this.columns=p[0].length}set(p,c,u){return this.data[p][c]=u,this}get(p,c){return this.data[p][c]}}function Le(w,p){if(r.isAnyArray(w))return w[0]&&r.isAnyArray(w[0])?new Se(w):new sr(w,p);throw new Error("the argument is not an array")}class ie{constructor(p){p=Se.checkMatrix(p);let c=p.clone(),u=c.rows,d=c.columns,y=new Float64Array(u),R=1,C,T,L,V,F,ee,ce,H,se;for(C=0;CMath.abs(H[V])&&(V=C);if(V!==T){for(L=0;L=0;L--){for(T=0;TR?d.set(y,R,p.get(y,R)):y===R?d.set(y,R,1):d.set(y,R,0);return d}get upperTriangularMatrix(){let p=this.LU,c=p.rows,u=p.columns,d=new W(c,u);for(let y=0;yMath.abs(p)?(c=p/w,Math.abs(w)*Math.sqrt(1+c*c)):p!==0?(c=w/p,Math.abs(p)*Math.sqrt(1+c*c)):0}class ar{constructor(p){p=Se.checkMatrix(p);let c=p.clone(),u=p.rows,d=p.columns,y=new Float64Array(d),R,C,T,L;for(T=0;T=0;L--){for(T=0;T=0;C--){for(y=0;y=0;Y--)if(H[Y]!==0){for(let he=Y+1;he=0;Y--){if(Y0;){let Y,he;for(Y=ke-2;Y>=-1&&Y!==-1;Y--){let xe=Number.MIN_VALUE+ur*Math.abs(H[Y]+Math.abs(H[Y+1]));if(Math.abs($[Y])<=xe||Number.isNaN($[Y])){$[Y]=0;break}}if(Y===ke-2)he=4;else{let xe;for(xe=ke-1;xe>=Y&&xe!==Y;xe--){let pe=(xe!==ke?Math.abs($[xe]):0)+(xe!==Y+1?Math.abs($[xe-1]):0);if(Math.abs(H[xe])<=ur*pe){H[xe]=0;break}}xe===Y?he=3:xe===ke-1?he=1:(he=2,Y=xe)}switch(Y++,he){case 1:{let xe=$[ke-2];$[ke-2]=0;for(let pe=ke-2;pe>=Y;pe--){let mr=tr(H[pe],xe),ir=H[pe]/mr,lr=xe/mr;if(H[pe]=mr,pe!==Y&&(xe=-lr*$[pe-1],$[pe-1]=ir*$[pe-1]),L)for(let yr=0;yr=H[Y+1]);){let xe=H[Y];if(H[Y]=H[Y+1],H[Y+1]=xe,L&&Yc&&y.set(V,F,p.get(V,F)/this.s[F]);let R=this.U,C=R.rows,T=R.columns,L=new W(u,C);for(let V=0;Vp&&c++;return c}get diagonal(){return Array.from(this.s)}get threshold(){return Number.EPSILON/2*Math.max(this.m,this.n)*this.s[0]}get leftSingularVectors(){return this.U}get rightSingularVectors(){return this.V}get diagonalMatrix(){return W.diag(this.s)}}function cr(w,p=!1){return w=Se.checkMatrix(w),p?new Tr(w).inverse():$r(w,W.eye(w.rows))}function $r(w,p,c=!1){return w=Se.checkMatrix(w),p=Se.checkMatrix(p),c?new Tr(w).solve(p):w.isSquare()?new ie(w).solve(p):new ar(w).solve(p)}function Hr(w){if(w=W.checkMatrix(w),w.isSquare()){if(w.columns===0)return 1;let p,c,u,d;if(w.columns===2)return p=w.get(0,0),c=w.get(0,1),u=w.get(1,0),d=w.get(1,1),p*d-c*u;if(w.columns===3){let y,R,C;return y=new Ae(w,[1,2],[1,2]),R=new Ae(w,[1,2],[0,2]),C=new Ae(w,[1,2],[0,1]),p=w.get(0,0),c=w.get(0,1),u=w.get(0,2),p*Hr(y)-c*Hr(R)+u*Hr(C)}else return new ie(w).determinant}else throw Error("determinant can only be calculated for a square matrix")}function ct(w,p){let c=[];for(let u=0;ud)return new Array(p.rows+1).fill(0);{let y=p.addRow(c,[0]);for(let R=0;Rp?y[R]=1/y[R]:y[R]=0;return d.mmul(W.diag(y).mmul(u.transpose()))}function v(w,p=w,c={}){w=new W(w);let u=!1;if(typeof p=="object"&&!W.isMatrix(p)&&!r.isAnyArray(p)?(c=p,p=w,u=!0):p=new W(p),w.rows!==p.rows)throw new TypeError("Both matrices must have the same number of rows");let{center:d=!0}=c;d&&(w=w.center("column"),u||(p=p.center("column")));let y=w.transpose().mmul(p);for(let R=0;R0?d.set(y,y+1,c[y]):c[y]<0&&d.set(y,y-1,c[y])}return d}}function G(w,p,c,u){let d,y,R,C,T,L,V,F;for(T=0;T0;C--){for(F=0,R=0,L=0;L0&&(y=-y),p[C]=F*y,R=R-d*y,c[C-1]=d-y,T=0;TL)do{for(d=c[L],F=(c[L+1]-d)/(2*p[L]),ee=tr(F,1),F<0&&(ee=-ee),c[L]=p[L]/(F+ee),c[L+1]=p[L]*(F+ee),ce=c[L+1],y=d-c[L],R=L+2;R=L;R--)for(qe=se,se=H,Re=ye,d=H*p[R],y=H*F,ee=tr(F,p[R]),p[R+1]=ye*ee,ye=p[R]/ee,H=F/ee,F=H*c[R]-ye*d,c[R+1]=y+ye*(H*d+ye*c[R]),T=0;Tgr*Ue);c[L]=c[L]+$e,p[L]=0}for(R=0;R=F;L--)c[L]=p.get(L,F-1)/ee,T+=c[L]*c[L];for(C=Math.sqrt(T),c[F]>0&&(C=-C),T=T-c[F]*C,c[F]=c[F]-C,V=F;V=F;L--)R+=c[L]*p.get(L,V);for(R=R/T,L=F;L<=y;L++)p.set(L,V,p.get(L,V)-R*c[L])}for(L=0;L<=y;L++){for(R=0,V=y;V>=F;V--)R+=c[V]*p.get(L,V);for(R=R/T,V=F;V<=y;V++)p.set(L,V,p.get(L,V)-R*c[V])}c[F]=ee*c[F],p.set(F,F-1,ee*C)}}for(L=0;L=d+1;F--)if(p.get(F,F-1)!==0){for(L=F+1;L<=y;L++)c[L]=p.get(L,F-1);for(V=F;V<=y;V++){for(C=0,L=F;L<=y;L++)C+=c[L]*u.get(L,V);for(C=C/c[F]/p.get(F,F-1),L=F;L<=y;L++)u.set(L,V,u.get(L,V)+C*c[L])}}}function J(w,p,c,u,d){let y=w-1,R=0,C=w-1,T=Number.EPSILON,L=0,V=0,F=0,ee=0,ce=0,H=0,se=0,qe=0,$,ye,Re,$e,Ue,gr,ke,je,ur,Y,he,xe,pe,mr,ir;for($=0;$C)&&(c[$]=d.get($,$),p[$]=0),ye=Math.max($-1,0);ye=R;){for($e=y;$e>R&&(H=Math.abs(d.get($e-1,$e-1))+Math.abs(d.get($e,$e)),H===0&&(H=V),!(Math.abs(d.get($e,$e-1))=0){for(se=F>=0?F+se:F-se,c[y-1]=je+se,c[y]=c[y-1],se!==0&&(c[y]=je-ke/se),p[y-1]=0,p[y]=0,je=d.get(y,y-1),H=Math.abs(je)+Math.abs(se),F=je/H,ee=se/H,ce=Math.sqrt(F*F+ee*ee),F=F/ce,ee=ee/ce,ye=y-1;ye0)){for(H=Math.sqrt(H),ur=$e&&(se=d.get(Ue,Ue),ce=je-se,H=ur-se,F=(ce*H-ke)/d.get(Ue+1,Ue)+d.get(Ue,Ue+1),ee=d.get(Ue+1,Ue+1)-se-ce-H,ce=d.get(Ue+2,Ue+1),H=Math.abs(F)+Math.abs(ee)+Math.abs(ce),F=F/H,ee=ee/H,ce=ce/H,!(Ue===$e||Math.abs(d.get(Ue,Ue-1))*(Math.abs(ee)+Math.abs(ce))Ue+2&&d.set($,$-3,0);for(Re=Ue;Re<=y-1&&(mr=Re!==y-1,Re!==Ue&&(F=d.get(Re,Re-1),ee=d.get(Re+1,Re-1),ce=mr?d.get(Re+2,Re-1):0,je=Math.abs(F)+Math.abs(ee)+Math.abs(ce),je!==0&&(F=F/je,ee=ee/je,ce=ce/je)),je!==0);Re++)if(H=Math.sqrt(F*F+ee*ee+ce*ce),F<0&&(H=-H),H!==0){for(Re!==Ue?d.set(Re,Re-1,-H*je):$e!==Ue&&d.set(Re,Re-1,-d.get(Re,Re-1)),F=F+H,je=F/H,ur=ee/H,se=ce/H,ee=ee/F,ce=ce/F,ye=Re;ye=0;y--)if(F=c[y],ee=p[y],ee===0)for($e=y,d.set(y,y,1),$=y-1;$>=0;$--){for(ke=d.get($,$)-F,ce=0,ye=$e;ye<=y;ye++)ce=ce+d.get($,ye)*d.get(ye,y);if(p[$]<0)se=ke,H=ce;else if($e=$,p[$]===0?d.set($,y,ke!==0?-ce/ke:-ce/(T*V)):(je=d.get($,$+1),ur=d.get($+1,$),ee=(c[$]-F)*(c[$]-F)+p[$]*p[$],gr=(je*H-se*ce)/ee,d.set($,y,gr),d.set($+1,y,Math.abs(je)>Math.abs(se)?(-ce-ke*gr)/je:(-H-ur*gr)/se)),gr=Math.abs(d.get($,y)),T*gr*gr>1)for(ye=$;ye<=y;ye++)d.set(ye,y,d.get(ye,y)/gr)}else if(ee<0)for($e=y-1,Math.abs(d.get(y,y-1))>Math.abs(d.get(y-1,y))?(d.set(y-1,y-1,ee/d.get(y,y-1)),d.set(y-1,y,-(d.get(y,y)-F)/d.get(y,y-1))):(ir=ae(0,-d.get(y-1,y),d.get(y-1,y-1)-F,ee),d.set(y-1,y-1,ir[0]),d.set(y-1,y,ir[1])),d.set(y,y-1,0),d.set(y,y,1),$=y-2;$>=0;$--){for(Y=0,he=0,ye=$e;ye<=y;ye++)Y=Y+d.get($,ye)*d.get(ye,y-1),he=he+d.get($,ye)*d.get(ye,y);if(ke=d.get($,$)-F,p[$]<0)se=ke,ce=Y,H=he;else if($e=$,p[$]===0?(ir=ae(-Y,-he,ke,ee),d.set($,y-1,ir[0]),d.set($,y,ir[1])):(je=d.get($,$+1),ur=d.get($+1,$),xe=(c[$]-F)*(c[$]-F)+p[$]*p[$]-ee*ee,pe=(c[$]-F)*2*ee,xe===0&&pe===0&&(xe=T*V*(Math.abs(ke)+Math.abs(ee)+Math.abs(je)+Math.abs(ur)+Math.abs(se))),ir=ae(je*ce-se*Y+ee*he,je*H-se*he-ee*Y,xe,pe),d.set($,y-1,ir[0]),d.set($,y,ir[1]),Math.abs(je)>Math.abs(se)+Math.abs(ee)?(d.set($+1,y-1,(-Y-ke*d.get($,y-1)+ee*d.get($,y))/je),d.set($+1,y,(-he-ke*d.get($,y)-ee*d.get($,y-1))/je)):(ir=ae(-ce-ur*d.get($,y-1),-H-ur*d.get($,y),se,ee),d.set($+1,y-1,ir[0]),d.set($+1,y,ir[1]))),gr=Math.max(Math.abs(d.get($,y-1)),Math.abs(d.get($,y))),T*gr*gr>1)for(ye=$;ye<=y;ye++)d.set(ye,y-1,d.get(ye,y-1)/gr),d.set(ye,y,d.get(ye,y)/gr)}for($=0;$C)for(ye=$;ye=R;ye--)for($=R;$<=C;$++){for(se=0,Re=R;Re<=Math.min(ye,C);Re++)se=se+u.get($,Re)*d.get(Re,ye);u.set($,ye,se)}}}function ae(w,p,c,u){let d,y;return Math.abs(c)>Math.abs(u)?(d=u/c,y=c+d*u,[(w+d*p)/y,(p-d*w)/y]):(d=c/u,y=u+d*c,[(d*w+p)/y,(d*p-w)/y])}class ne{constructor(p){if(p=Se.checkMatrix(p),!p.isSymmetric())throw new Error("Matrix is not symmetric");let c=p,u=c.rows,d=new W(u,u),y=!0,R,C,T;for(C=0;C0),d.set(C,C,Math.sqrt(Math.max(L,0))),T=C+1;T=0;T--)for(C=0;CR;ce++)F=p.transpose().mmul(C).div(C.transpose().mmul(C).get(0,0)),F=F.div(F.norm()),L=p.mmul(F).div(F.transpose().mmul(F).get(0,0)),ce>0&&(T=L.clone().sub(ee).pow(2).sum()),ee=L.clone(),u?(V=u.transpose().mmul(L).div(L.transpose().mmul(L).get(0,0)),V=V.div(V.norm()),C=u.mmul(V).div(V.transpose().mmul(V).get(0,0))):C=L;if(u){let ce=p.transpose().mmul(L).div(L.transpose().mmul(L).get(0,0));ce=ce.div(ce.norm());let H=p.clone().sub(L.clone().mmul(ce.transpose())),se=C.transpose().mmul(L).div(L.transpose().mmul(L).get(0,0)),qe=u.clone().sub(L.clone().mulS(se.get(0,0)).mmul(V.transpose()));this.t=L,this.p=ce.transpose(),this.w=F.transpose(),this.q=V,this.u=C,this.s=L.transpose().mmul(L),this.xResidual=H,this.yResidual=qe,this.betas=se}else this.w=F.transpose(),this.s=L.transpose().mmul(L).sqrt(),d?this.t=L.clone().div(this.s.get(0,0)):this.t=L,this.xResidual=p.sub(L.mmul(F.transpose()))}}return Ke.AbstractMatrix=U,Ke.CHO=ne,Ke.CholeskyDecomposition=ne,Ke.DistanceMatrix=le,Ke.EVD=k,Ke.EigenvalueDecomposition=k,Ke.LU=ie,Ke.LuDecomposition=ie,Ke.Matrix=W,Ke.MatrixColumnSelectionView=Be,Ke.MatrixColumnView=Ye,Ke.MatrixFlipColumnView=wr,Ke.MatrixFlipRowView=er,Ke.MatrixRowSelectionView=Xe,Ke.MatrixRowView=qr,Ke.MatrixSelectionView=Ae,Ke.MatrixSubView=ze,Ke.MatrixTransposeView=be,Ke.NIPALS=Ee,Ke.Nipals=Ee,Ke.QR=ar,Ke.QrDecomposition=ar,Ke.SVD=Tr,Ke.SingularValueDecomposition=Tr,Ke.SymmetricMatrix=ue,Ke.WrapperMatrix1D=sr,Ke.WrapperMatrix2D=Se,Ke.correlation=b,Ke.covariance=v,Ke.default=W,Ke.determinant=Hr,Ke.inverse=cr,Ke.linearDependencies=St,Ke.pseudoInverse=K,Ke.solve=$r,Ke.wrap=Le,Ke}var Tn=Hb(),Ll=_o(Tn);var Ml=Tn.Matrix,e1=Tn.SingularValueDecomposition;Ll.Matrix?Ll.Matrix:Tn.Matrix;var ws=(r,e)=>{let t=r.nodeCount(),i=Array.from({length:t},()=>[]),n={},o=0;return r.forEachNode(s=>{n[s.id]=o++}),r.forEachEdge(s=>{let a=n[s.source],h=n[s.target];a==null||h==null||(i[a].push(h),e||i[h].push(a))}),i},r1=(r,e)=>{let t=r.length,i=new Array(t);for(let n=0;nnew Array(e).fill(1/0));for(let i=0;i0&&(this.data[0]=t,this.bubbleDown(0)),e}empty(){return this.data.length===0}bubbleUp(e){let t=this.data;for(;e>0;){let i=e-1>>1;if(t[i][0]<=t[e][0])break;[t[i],t[e]]=[t[e],t[i]],e=i}}bubbleDown(e){let t=this.data,i=t.length;for(;;){let n=e*2+1,o=e*2+2,s=e;if(n{let l=a[h++];f.x=l[0]+t[0],f.y=l[1]+t[1]})})}},WI=r=>{let e=Number.NEGATIVE_INFINITY,t=[],i=r.length;for(let n=0;n{try{let i=r.length,n=new Ml(i,i);for(let _=0;_{let t=Object.assign(Object.assign({},t1),e),{maxIteration:i,width:n,k:o,speed:s=t1.speed,strictRadial:a,focusNode:h,radiiMap:f,nodeSizeFunc:l}=t,g=o*.002,m=new Map,_=n/10;for(let E=0;E{m.set(x.id,{x:0,y:0})}),BI(r,m,o,f,l),!(VI(r,m,s,a,h,_,f){let o=0;r.forEachNode(s=>{let a=0;r.forEachNode(h=>{if(a<=o){a++;return}if(s.id===h.id||i.get(s.id)!==i.get(h.id))return;let f=s.x-h.x,l=s.y-h.y,g=Math.sqrt(f*f+l*l);if(g===0){g=1;let E=o>a?1:-1;f=.01*E,l=.01*E}let m=Math.max(...n(s._original)),_=Math.max(...n(h._original));if(g<_/2+m/2){let E=t*t/g,q=e.get(s.id),x=e.get(h.id),A=f/g*E,S=l/g*E;e.set(s.id,{x:q.x+A,y:q.y+S}),e.set(h.id,{x:x.x-A,y:x.y-S})}a++}),o++})},VI=(r,e,t,i,n,o,s)=>{i&&r.forEachNode(f=>{let l=f.x-n.x,g=f.y-n.y,m=Math.sqrt(l*l+g*g),_=g/m,E=-l/m,q=e.get(f.id),x=Math.sqrt(q.x*q.x+q.y*q.y),A=Math.acos((_*q.x+E*q.y)/x);A>Math.PI/2&&(A-=Math.PI/2,_*=-1,E*=-1);let S=Math.cos(A)*x;e.set(f.id,{x:_*S,y:E*S})});let a=0,h=0;return r.forEachNode(f=>{if(f.id===n.id)return;let l=e.get(f.id),g=Math.sqrt(l.x*l.x+l.y*l.y);if(g>0){let m=Math.min(o*(t/800),g);if(f.x+=l.x/g*m,f.y+=l.y/g*m,i){let _=f.x-n.x,E=f.y-n.y,q=Math.sqrt(_*_+E*E);_=_/q*s.get(f.id),E=E/q*s.get(f.id),f.x=n.x+_,f.y=n.y+E}a+=m,h++}}),h>0?a/h:0};var Ti={focusNode:null,linkDistance:50,maxIteration:1e3,maxPreventOverlapIteration:200,preventOverlap:!1,sortStrength:10,strictRadial:!0,unitRadius:null,nodeSize:10,nodeSpacing:0},Es=class extends Dt{constructor(){super(...arguments),this.id="radial"}getDefaultOptions(){return Ti}layout(){return st(this,void 0,void 0,function*(){let{width:e,height:t,center:i}=Wi(this.options),n=this.model.nodeCount();if(!n||n===1)return Ui(this.model,i);let{focusNode:o,linkDistance:s=Ti.linkDistance,maxIteration:a=Ti.maxIteration,maxPreventOverlapIteration:h=Ti.maxPreventOverlapIteration,nodeSize:f,nodeSpacing:l,preventOverlap:g,sortBy:m,sortStrength:_=Ti.sortStrength,strictRadial:E,unitRadius:q}=this.options,x=o&&this.model.node(o)||this.model.firstNode(),A=this.model.nodeIndexOf(x.id),S=ws(this.model,!1),I=qs(S),M=QI(I,A);XI(I,A,M+1);let D=I[A],z=(e-i[0]>i[0]?i[0]:e-i[0])||e/2,O=(t-i[1]>i[1]?i[1]:t-i[1])||t/2,N=Math.min(z,O),j=Math.max(...D),X=[],re=new Map,oe=q??N/j;D.forEach((Oe,B)=>{let pr=Oe*oe;X.push(pr),re.set(this.model.nodeAt(B).id,pr)});let me=KI(this.model,I,s,X,oe,m,_),_e=Pl(me,2,s),Te=_e[A],Ne=0;if(this.model.forEachNode(Oe=>{let B=_e[Ne];Oe.x=B[0]-Te[0],Oe.y=B[1]-Te[1],Ne++}),this.run(a,me,X,A),this.model.forEachNode(Oe=>{Oe.x+=i[0],Oe.y+=i[1]}),g){let B={nodeSizeFunc:oo(f,l,Ti.nodeSize,Ti.nodeSpacing),radiiMap:re,width:e,strictRadial:!!E,focusNode:x,maxIteration:h,k:n/4.5};i1(this.model,B)}})}run(e,t,i,n){let o=YI(t),s=this.model.nodeCount(),a=this.model.nodes(),h=new Float64Array(s),f=new Float64Array(s);for(let l=0;l{let a=e.length,h=new Array(a),f=new Array(a);for(let E=0;E{let e=r.length,t=r[0].length,i=[];for(let n=0;n{let i=r.length;for(let n=0;n{let t=r[e],i=0;for(let n=0;ndn,BubbleSets:()=>Ts,Circle:()=>Mn,Line:()=>Vr,PointPath:()=>zt,Rectangle:()=>it,addPadding:()=>Ul,boundingBox:()=>u1,calculatePotentialOutline:()=>l1,calculateVirtualEdges:()=>h1,circle:()=>iA,createGenericInfluenceArea:()=>Wl,createLineInfluenceArea:()=>Nl,createOutline:()=>yA,createRectangleInfluenceArea:()=>f1,default:()=>Ts,defaultOptions:()=>Bl,line:()=>nA,lineBoundingBox:()=>$l,point:()=>hr,rect:()=>tA,unionBoundingBox:()=>d1});function zl(r,e,t,i,n,o){let s=r,a=e,h=t-s,f=i-a,l=n-s,g=o-a,m=l*h+g*f,_=0;m<=0?_=0:(l=h-l,g=f-g,m=l*h+g*f,m<=0?_=0:_=m*m/(h*h+f*f));let E=l*l+g*g-_;return E<0?0:E}function bi(r,e,t,i){return(r-t)*(r-t)+(e-i)*(e-i)}function n1(r,e,t,i,n){return bi(r,e,t,i)t;if(r===0)return Math.round;let e=Math.pow(10,r);return t=>Math.round(t*e)/e}function $l(r){let e=Math.min(r.x1,r.x2),t=Math.max(r.x1,r.x2),i=Math.min(r.y1,r.y2),n=Math.max(r.y1,r.y2);return{x:e,y:i,x2:t,y2:n,width:t-e,height:n-i}}var Vr=class r{constructor(e,t,i,n){this.x1=e,this.y1=t,this.x2=i,this.y2=n}equals(e){return this.x1===e.x1&&this.y1===e.y1&&this.x2===e.x2&&this.y2===e.y2}draw(e){e.moveTo(this.x1,this.y1),e.lineTo(this.x2,this.y2)}toString(){return`Line(from=(${this.x1},${this.y1}),to=(${this.x2},${this.y2}))`}static from(e){return new r(e.x1,e.y1,e.x2,e.y2)}cuts(e,t){if(this.y1===this.y2||tthis.y1&&t>=this.y2||e>this.x1&&e>=this.x2)return!1;if(ethis.x2+i)return!1}else if(ethis.x1+i)return!1;if(this.y1this.y2+i)return!1}else if(tthis.y1+i)return!1;return!0}},Ar;(function(r){r[r.POINT=1]="POINT",r[r.PARALLEL=2]="PARALLEL",r[r.COINCIDENT=3]="COINCIDENT",r[r.NONE=4]="NONE"})(Ar||(Ar={}));var kn=class{constructor(e,t=0,i=0){this.state=e,this.x=t,this.y=i}};function xs(r,e){let t=(e.x2-e.x1)*(r.y1-e.y1)-(e.y2-e.y1)*(r.x1-e.x1),i=(r.x2-r.x1)*(r.y1-e.y1)-(r.y2-r.y1)*(r.x1-e.x1),n=(e.y2-e.y1)*(r.x2-r.x1)-(e.x2-e.x1)*(r.y2-r.y1);if(n){let o=t/n,s=i/n;return 0<=o&&o<=1&&0<=s&&s<=1?new kn(Ar.POINT,r.x1+o*(r.x2-r.x1),r.y1+o*(r.y2-r.y1)):new kn(Ar.NONE)}return new kn(t===0||i===0?Ar.COINCIDENT:Ar.PARALLEL)}function s1(r,e){let t=(e.x2-e.x1)*(r.y1-e.y1)-(e.y2-e.y1)*(r.x1-e.x1),i=(r.x2-r.x1)*(r.y1-e.y1)-(r.y2-r.y1)*(r.x1-e.x1),n=(e.y2-e.y1)*(r.x2-r.x1)-(e.x2-e.x1)*(r.y2-r.y1);if(n){let o=t/n,s=i/n;if(0<=o&&o<=1&&0<=s&&s<=1)return o}return Number.POSITIVE_INFINITY}function JI(r,e){function t(n,o,s,a){let h=s1(e,new Vr(n,o,s,a));return h=Math.abs(h-.5),h>=0&&h<=1?1:0}let i=t(r.x,r.y,r.x2,r.y);return i+=t(r.x,r.y,r.x,r.y2),i>1||(i+=t(r.x,r.y2,r.x2,r.y2),i>1)?!0:(i+=t(r.x2,r.y,r.x2,r.y2),i>0)}var Rr;(function(r){r[r.LEFT=0]="LEFT",r[r.TOP=1]="TOP",r[r.RIGHT=2]="RIGHT",r[r.BOTTOM=3]="BOTTOM"})(Rr||(Rr={}));function Cs(r,e,t){let i=new Set;return r.width<=0?(i.add(Rr.LEFT),i.add(Rr.RIGHT)):er.x+r.width&&i.add(Rr.RIGHT),r.height<=0?(i.add(Rr.TOP),i.add(Rr.BOTTOM)):tr.y+r.height&&i.add(Rr.BOTTOM),i}function a1(r,e){let t=e.x1,i=e.y1,n=e.x2,o=e.y2,s=Array.from(Cs(r,n,o));if(s.length===0)return!0;let a=Cs(r,t,i);for(;a.size!==0;){for(let h of s)if(a.has(h))return!1;if(a.has(Rr.RIGHT)||a.has(Rr.LEFT)){let h=r.x;a.has(Rr.RIGHT)&&(h+=r.width),i=i+(h-t)*(o-i)/(n-t),t=h}else{let h=r.y;a.has(Rr.BOTTOM)&&(h+=r.height),t=t+(h-i)*(n-t)/(o-i),i=h}a=Cs(r,t,i)}return!0}function HI(r,e){let t=Number.POSITIVE_INFINITY,i=0;function n(o,s,a,h){let f=s1(e,new Vr(o,s,a,h));f=Math.abs(f-.5),f>=0&&f<=1&&(i++,f1||(n(r.x,r.y2,r.x2,r.y2),i>1)?t:(n(r.x2,r.y,r.x2,r.y2),i===0?-1:t)}function eA(r,e){let t=0,i=xs(r,new Vr(e.x,e.y,e.x2,e.y));t+=i.state===Ar.POINT?1:0;let n=xs(r,new Vr(e.x,e.y,e.x,e.y2));t+=n.state===Ar.POINT?1:0;let o=xs(r,new Vr(e.x,e.y2,e.x2,e.y2));t+=o.state===Ar.POINT?1:0;let s=xs(r,new Vr(e.x2,e.y,e.x2,e.y2));return t+=s.state===Ar.POINT?1:0,{top:i,left:n,bottom:o,right:s,count:t}}var it=class r{constructor(e,t,i,n){this.x=e,this.y=t,this.width=i,this.height=n}get x2(){return this.x+this.width}get y2(){return this.y+this.height}get cx(){return this.x+this.width/2}get cy(){return this.y+this.height/2}get radius(){return Math.max(this.width,this.height)/2}static from(e){return new r(e.x,e.y,e.width,e.height)}equals(e){return this.x===e.x&&this.y===e.y&&this.width===e.width&&this.height===e.height}clone(){return new r(this.x,this.y,this.width,this.height)}add(e){let t=Math.min(this.x,e.x),i=Math.min(this.y,e.y),n=Math.max(this.x2,e.x+e.width),o=Math.max(this.y2,e.y+e.height);this.x=t,this.y=i,this.width=n-t,this.height=o-i}addPoint(e){let t=Math.min(this.x,e.x),i=Math.min(this.y,e.y),n=Math.max(this.x2,e.x),o=Math.max(this.y2,e.y);this.x=t,this.y=i,this.width=n-t,this.height=o-i}toString(){return`Rectangle[x=${this.x}, y=${this.y}, w=${this.width}, h=${this.height}]`}draw(e){e.rect(this.x,this.y,this.width,this.height)}containsPt(e,t){return e>=this.x&&e<=this.x2&&t>=this.y&&t<=this.y2}get area(){return this.width*this.height}intersects(e){return this.area<=0||e.width<=0||e.height<=0?!1:e.x+e.width>this.x&&e.y+e.height>this.y&&e.x=this.width?this.width-1:e}boundY(e){return e=this.height?this.height-1:e}scaleX(e){return this.boundX(Math.floor((e-this.pixelX)/this.pixelGroup))}scaleY(e){return this.boundY(Math.floor((e-this.pixelY)/this.pixelGroup))}scale(e){let t=this.scaleX(e.x),i=this.scaleY(e.y),n=this.boundX(Math.ceil((e.x+e.width-this.pixelX)/this.pixelGroup)),o=this.boundY(Math.ceil((e.y+e.height-this.pixelY)/this.pixelGroup)),s=n-t,a=o-i;return new it(t,i,s,a)}invertScaleX(e){return Math.round(e*this.pixelGroup+this.pixelX)}invertScaleY(e){return Math.round(e*this.pixelGroup+this.pixelY)}addPadding(e,t){let i=Math.ceil(t/this.pixelGroup),n=this.boundX(e.x-i),o=this.boundY(e.y-i),s=this.boundX(e.x2+i),a=this.boundY(e.y2+i),h=s-n,f=a-o;return new it(n,o,h,f)}get(e,t){return e<0||t<0||e>=this.width||t>=this.height?Number.NaN:this.area[e+t*this.width]}inc(e,t,i){e<0||t<0||e>=this.width||t>=this.height||(this.area[e+t*this.width]+=i)}set(e,t,i){e<0||t<0||e>=this.width||t>=this.height||(this.area[e+t*this.width]=i)}incArea(e,t){if(e.width<=0||e.height<=0||t===0)return;let i=this.width,n=e.width,o=Math.max(0,e.i),s=Math.max(0,e.j),a=Math.min(e.i+e.width,i),h=Math.min(e.j+e.height,this.height);if(!(h<=0||a<=0||o>=i||h>=this.height))for(let f=s;fMath.min(s,a),Number.POSITIVE_INFINITY),n=this.area.reduce((s,a)=>Math.max(s,a),Number.NEGATIVE_INFINITY),o=s=>(s-i)/(n-i);e.scale(this.pixelGroup,this.pixelGroup);for(let s=0;st?"black":"white",e.fillRect(n,o,1,1)}e.restore()}}};function Ul(r,e){let t=i=>({x:i.x-e,y:i.y-e,width:i.width+2*e,height:i.height+2*e});return Array.isArray(r)?r.map(t):t(r)}function Nl(r,e,t){return Wl(Object.assign($l(r),{distSquare:(i,n)=>zl(r.x1,r.y1,r.x2,r.y2,i,n)}),e,t)}function Wl(r,e,t){let i=Ul(r,t),n=e.scale(i),o=e.createSub(n,i);return rA(o,e,t,(s,a)=>r.distSquare(s,a)),o}function rA(r,e,t,i){let n=t*t;for(let o=0;o{let a=n.slice(0,s);return oA(e,o,a,t,i)}).flat()}function oA(r,e,t,i,n){let o=hr(e.cx,e.cy),s=uA(o,t,r);if(s==null)return[];let a=new Vr(o.x,o.y,s.cx,s.cy),h=sA(a,r,i,n);return aA(h,r)}function sA(r,e,t,i){let n=[],o=[];o.push(r);let s=!0;for(let a=0;a0;){let h=o.pop(),f=c1(e,h),l=f?eA(h,f):null;if(!f||!l||l.count!==2){s||n.push(h);continue}let g=i,m=Is(f,g,l,!0),_=qi(m,o)||qi(m,n),E=Ss(m,e);for(;!_&&E&&g>=1;)g/=1.5,m=Is(f,g,l,!0),_=qi(m,o)||qi(m,n),E=Ss(m,e);if(m&&!_&&!E&&(o.push(new Vr(h.x1,h.y1,m.x,m.y)),o.push(new Vr(m.x,m.y,h.x2,h.y2)),s=!0),s)continue;g=i,m=Is(f,g,l,!1);let q=qi(m,o)||qi(m,n);for(E=Ss(m,e);!q&&E&&g>=1;)g/=1.5,m=Is(f,g,l,!1),q=qi(m,o)||qi(m,n),E=Ss(m,e);m&&!q&&(o.push(new Vr(h.x1,h.y1,m.x,m.y)),o.push(new Vr(m.x,m.y,h.x2,h.y2)),s=!0),s||n.push(h)}for(;o.length>0;)n.push(o.pop());return n}function aA(r,e){let t=[];for(;r.length>0;){let i=r.pop();if(r.length===0){t.push(i);break}let n=r.pop(),o=new Vr(i.x1,i.y1,n.x2,n.y2);c1(e,o)?(t.push(i),r.push(n)):r.push(o)}return t}function uA(r,e,t){let i=Number.POSITIVE_INFINITY;return e.reduce((n,o)=>{let s=bi(r.x,r.y,o.cx,o.cy);if(s>i)return n;let a=new Vr(r.x,r.y,o.cx,o.cy),h=hA(t,a);return s*(h+1)*(h+1){e+=i.cx,t+=i.cy}),e/=r.length,t/=r.length,r.map(i=>{let n=e-i.cx,o=t-i.cy,s=n*n+o*o;return[i,s]}).sort((i,n)=>i[1]-n[1]).map(i=>i[0])}function Ss(r,e){return e.some(t=>t.containsPt(r.x,r.y))}function qi(r,e){return e.some(t=>!!(n1(t.x1,t.y1,r.x,r.y,.001)||n1(t.x2,t.y2,r.x,r.y,.001)))}function c1(r,e){let t=Number.POSITIVE_INFINITY,i=null;for(let n of r){if(!a1(n,e))continue;let o=HI(n,e);o>=0&&oa1(i,e)&&JI(i,e)?t+1:t,0)}function Is(r,e,t,i){let n=t.top,o=t.left,s=t.bottom,a=t.right;if(i){if(o.state===Ar.POINT){if(n.state===Ar.POINT)return hr(r.x-e,r.y-e);if(s.state===Ar.POINT)return hr(r.x-e,r.y2+e);let m=r.width*r.height;return r.width*((o.y-r.y+(a.y-r.y))*.5)a.y?hr(r.x-e,r.y-e):hr(r.x2+e,r.y-e):o.ys.x?hr(r.x-e,r.y-e):hr(r.x-e,r.y2+e):n.xa.y?hr(r.x2+e,r.y2+e):hr(r.x-e,r.y2+e):o.ys.x?hr(r.x2+e,r.y2+e):hr(r.x2+e,r.y-e):n.xi)return!1}return!0}function lA(r=0){return e=>{if(r<0||e.length<3)return e;let t=[],i=0,n=r*r;for(;i{if(s.length<3)return s;let a=[],h=s.closed,f=s.length+3-1+(h?0:2);a.push(o(s,2-(h?0:2),0));for(let l=2-(h?0:2);l{let t=r,i=e.length;if(t>1)for(i=Math.floor(e.length/t);i<3&&t>1;)t-=1,i=Math.floor(e.length/t);let n=[];for(let o=0,s=0;s=i?this.closed?this.get(e-i):this.points[i-1]:this.points[t]}get length(){return this.points.length}toString(e=1/0){let t=this.points;if(t.length===0)return"";let i=typeof e=="function"?e:ZI(e),n="M";for(let o of t)n+=`${i(o.x)},${i(o.y)} L`;return n=n.slice(0,-1),this.closed&&(n+=" Z"),n}draw(e){let t=this.points;if(t.length!==0){e.beginPath(),e.moveTo(t[0].x,t[0].y);for(let i of t)e.lineTo(i.x,i.y);this.closed&&e.closePath()}}sample(e){return gA(e)(this)}simplify(e){return lA(e)(this)}bSplines(e){return pA(e)(this)}apply(e){return e(this)}containsElements(e){let t=u1(this.points);return t?e.every(i=>t.containsPt(i.cx,i.cy)&&this.withinArea(i.cx,i.cy)):!1}withinArea(e,t){if(this.length===0)return!1;let i=0,n=this.points[0],o=new Vr(n.x,n.y,n.x,n.y);for(let s=1;se?l+g:l}function o(h,f){let l=On;return l=n(h,f,l,1),l=n(h+1,f,l,2),l=n(h,f+1,l,4),l=n(h+1,f+1,l,8),Number.isNaN(l)?-1:l}let s=As;function a(h,f){let l=h,g=f,m=r.invertScaleX(l),_=r.invertScaleY(g);for(let E=0;Eo1(i.raw,e));return t<0?!1:(this.members.splice(t,1),this.dirty.add(Tt.MEMBERS),!0)}removeNonMember(e){let t=this.nonMembers.findIndex(i=>o1(i.raw,e));return t<0?!1:(this.nonMembers.splice(t,1),this.dirty.add(Tt.NON_MEMBERS),!0)}removeEdge(e){let t=this.edges.findIndex(i=>i.obj.equals(e));return t<0?!1:(this.edges.splice(t,1),this.dirty.add(Tt.NON_MEMBERS),!0)}pushNonMember(...e){if(e.length!==0){this.dirty.add(Tt.NON_MEMBERS);for(let t of e)this.nonMembers.push({raw:t,obj:Ln(t)?Mn.from(t):it.from(t),area:null})}}pushEdge(...e){if(e.length!==0){this.dirty.add(Tt.EDGES);for(let t of e)this.edges.push({raw:t,obj:Vr.from(t),area:null})}}update(){let e=this.dirty.has(Tt.MEMBERS),t=this.dirty.has(Tt.NON_MEMBERS),i=this.dirty.has(Tt.EDGES);this.dirty.clear();let n=this.members.map(f=>f.obj);if(this.o.virtualEdges&&(e||t)){let f=this.nonMembers.map(m=>m.obj),l=h1(n,f,this.o.maxRoutingIterations,this.o.morphBuffer),g=new Map(this.virtualEdges.map(m=>[m.obj.toString(),m.area]));this.virtualEdges=l.map(m=>{var _;return{raw:m,obj:m,area:(_=g.get(m.toString()))!==null&&_!==void 0?_:null}}),i=!0}let o=!1;if(e||i){let f=this.virtualEdges.concat(this.edges).map(_=>_.obj),l=d1(n,f),g=Math.max(this.o.edgeR1,this.o.nodeR1)+this.o.morphBuffer,m=it.from(Ul(l,g));m.equals(this.activeRegion)||(o=!0,this.activeRegion=m)}if(o){let f=Math.ceil(this.activeRegion.width/this.o.pixelGroup),l=Math.ceil(this.activeRegion.height/this.o.pixelGroup);this.activeRegion.x!==this.potentialArea.pixelX||this.activeRegion.y!==this.potentialArea.pixelY?(this.potentialArea=dn.fromPixelRegion(this.activeRegion,this.o.pixelGroup),this.members.forEach(g=>g.area=null),this.nonMembers.forEach(g=>g.area=null),this.edges.forEach(g=>g.area=null),this.virtualEdges.forEach(g=>g.area=null)):(f!==this.potentialArea.width||l!==this.potentialArea.height)&&(this.potentialArea=dn.fromPixelRegion(this.activeRegion,this.o.pixelGroup))}let s=new Map,a=f=>{if(f.area){let l=`${f.obj.width}x${f.obj.height}x${f.obj instanceof it?"R":"C"}`;s.set(l,f.area)}},h=f=>{if(f.area)return;let l=`${f.obj.width}x${f.obj.height}x${f.obj instanceof it?"R":"C"}`;if(s.has(l)){let m=s.get(l);f.area=this.potentialArea.copy(m,{x:f.obj.x-this.o.nodeR1,y:f.obj.y-this.o.nodeR1});return}let g=f.obj instanceof it?f1(f.obj,this.potentialArea,this.o.nodeR1):Wl(f.obj,this.potentialArea,this.o.nodeR1);f.area=g,s.set(l,g)};this.members.forEach(a),this.nonMembers.forEach(a),this.members.forEach(h),this.nonMembers.forEach(f=>{this.activeRegion.intersects(f.obj)?h(f):f.area=null}),this.edges.forEach(f=>{f.area||(f.area=Nl(f.obj,this.potentialArea,this.o.edgeR1))}),this.virtualEdges.forEach(f=>{f.area||(f.area=Nl(f.obj,this.potentialArea,this.o.edgeR1))})}drawMembers(e){for(let t of this.members)t.obj.draw(e)}drawNonMembers(e){for(let t of this.nonMembers)t.obj.draw(e)}drawEdges(e){for(let t of this.edges)t.obj.draw(e)}drawPotentialArea(e,t=!0){this.potentialArea.draw(e,t)}compute(){if(this.members.length===0)return new zt([]);this.dirty.size>0&&this.update();let{o:e,potentialArea:t}=this,i=this.members.map(a=>a.area),n=this.virtualEdges.concat(this.edges).map(a=>a.area),o=this.nonMembers.filter(a=>a.area!=null).map(a=>a.area),s=this.members.map(a=>a.obj);return l1(t,i,n,o,a=>a.containsElements(s),e)}};function l1(r,e,t,i,n,o={}){let s=Object.assign({},Bl,o),a=s.threshold,h=s.memberInfluenceFactor,f=s.edgeInfluenceFactor,l=s.nonMemberInfluenceFactor,g=(s.nodeR0-s.nodeR1)*(s.nodeR0-s.nodeR1),m=(s.edgeR0-s.edgeR1)*(s.edgeR0-s.edgeR1);for(let _=0;_0)l*=.8;else break}return new zt([])}function d1(r,e){if(r.length===0)return new it(0,0,0,0);let t=it.from(r[0]);for(let i of r)t.add(i);for(let i of e)t.add($l(i));return t}function yA(r,e=[],t=[],i={}){if(r.length===0)return new zt([]);let n=new Ts(i);return n.pushMember(...r),n.pushNonMember(...e),n.pushEdge(...t),n.compute()}var rC=et(g1(),1),tC=et(v1(),1),iC=et(V1(),1),nC=et(H1(),1),oC=et(iE(),1),sC=et(aE(),1),aC=et(hE(),1),uC=et(qE(),1),fC=et(CE(),1),hC=et(XE(),1);var export_FA2Layout=HR.default;var export_betweennessCentrality=iC.default;var export_circlepack=zs.circlepack;var export_circular=zs.circular;var export_closenessCentrality=nC.default;var export_degreeCentrality=tC.degreeCentrality;var export_density=aC.density;var export_diameter=uC.default;var export_eigenvectorCentrality=oC.default;var export_forceAtlas2=JR.default;var export_louvain=hC.default;var export_modularity=fC.default;var export_noverlap=eC.default;var export_pagerank=sC.default;var export_polygonClipping=rC.default;var export_random=zs.random;var export_rotation=zs.rotation;export{mo as ConcentricLayout,vs as DagreLayout,export_FA2Layout as FA2Layout,fr as Graph,bs as MDSLayout,Es as RadialLayout,export_betweennessCentrality as betweennessCentrality,p1 as bubblesets,export_circlepack as circlepack,export_circular as circular,export_closenessCentrality as closenessCentrality,export_degreeCentrality as degreeCentrality,export_density as density,export_diameter as diameter,export_eigenvectorCentrality as eigenvectorCentrality,export_forceAtlas2 as forceAtlas2,export_louvain as louvain,export_modularity as modularity,export_noverlap as noverlap,export_pagerank as pagerank,export_polygonClipping as polygonClipping,export_random as random,export_rotation as rotation}; +/*! Bundled license information: + +polygon-clipping/dist/polygon-clipping.umd.js: + (** + * splaytree v3.1.2 + * Fast Splay tree for Node and browser + * + * @author Alexander Milevski + * @license MIT + * @preserve + *) + (*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** *) + +comlink/dist/esm/comlink.js: + (** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: Apache-2.0 + *) +*/ diff --git a/src/lib/layout_worker_source.js b/src/lib/layout_worker_source.js new file mode 100644 index 0000000..2591431 --- /dev/null +++ b/src/lib/layout_worker_source.js @@ -0,0 +1,11 @@ +// AUTO-GENERATED from vendor_entry_layout_worker.mjs by src/package/vendor_libs.js. +// Do not edit by hand — run `npm run vendor-libs`. +export const LAYOUT_WORKER_SOURCE = `(()=>{var Xf=Object.defineProperty;var Zf=e=>{throw TypeError(e)};var Tv=(e,t,n)=>t in e?Xf(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var Hf=(e,t)=>{for(var n in t)Xf(e,n,{get:t[n],enumerable:!0})};var ec=(e,t,n)=>Tv(e,typeof t!="symbol"?t+"":t,n),cn=(e,t,n)=>t.has(e)||Zf("Cannot "+n);var pr=(e,t,n)=>(cn(e,t,"read from private field"),n?n.call(e):t.get(e)),hn=(e,t,n)=>t.has(e)?Zf("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,n),Kt=(e,t,n,u)=>(cn(e,t,"write to private field"),u?u.call(e,n):t.set(e,n),n),ln=(e,t,n)=>(cn(e,t,"access private method"),n);function He(e,t,n,u){function s(f){return f instanceof n?f:new n(function(c){c(f)})}return new(n||(n=Promise))(function(f,c){function h(m){try{p(u.next(m))}catch(d){c(d)}}function _(m){try{p(u.throw(m))}catch(d){c(d)}}function p(m){m.done?f(m.value):s(m.value).then(h,_)}p((u=u.apply(e,t||[])).next())})}var Av={abs:Math.abs,ceil:Math.ceil,floor:Math.floor,max:Math.max,min:Math.min,round:Math.round,sqrt:Math.sqrt,pow:Math.pow},Oe=class extends Error{constructor(t,n,u){super(t),this.position=n,this.token=u,this.name="ExpressionError"}},he;(function(e){e[e.STRING=0]="STRING",e[e.NUMBER=1]="NUMBER",e[e.BOOLEAN=2]="BOOLEAN",e[e.NULL=3]="NULL",e[e.IDENTIFIER=4]="IDENTIFIER",e[e.OPERATOR=5]="OPERATOR",e[e.FUNCTION=6]="FUNCTION",e[e.DOT=7]="DOT",e[e.BRACKET_LEFT=8]="BRACKET_LEFT",e[e.BRACKET_RIGHT=9]="BRACKET_RIGHT",e[e.PAREN_LEFT=10]="PAREN_LEFT",e[e.PAREN_RIGHT=11]="PAREN_RIGHT",e[e.COMMA=12]="COMMA",e[e.QUESTION=13]="QUESTION",e[e.COLON=14]="COLON",e[e.DOLLAR=15]="DOLLAR"})(he||(he={}));var Ov=new Set([32,9,10,13]),jv=new Set([43,45,42,47,37,33,38,124,61,60,62]),kv=new Map([["true",he.BOOLEAN],["false",he.BOOLEAN],["null",he.NULL]]),pn=new Map([["===",!0],["!==",!0],["<=",!0],[">=",!0],["&&",!0],["||",!0],["+",!0],["-",!0],["*",!0],["/",!0],["%",!0],["!",!0],["<",!0],[">",!0]]),Nv=new Map([[46,he.DOT],[91,he.BRACKET_LEFT],[93,he.BRACKET_RIGHT],[40,he.PAREN_LEFT],[41,he.PAREN_RIGHT],[44,he.COMMA],[63,he.QUESTION],[58,he.COLON],[36,he.DOLLAR]]),tc=new Map;for(let[e,t]of Nv.entries())tc.set(e,{type:t,value:String.fromCharCode(e)});function Tt(e){return e>=48&&e<=57}function _n(e){return e>=97&&e<=122||e>=65&&e<=90||e===95}function rc(e){return _n(e)||Tt(e)}function Lv(e){return jv.has(e)}var Ae;(function(e){e[e.Program=0]="Program",e[e.Literal=1]="Literal",e[e.Identifier=2]="Identifier",e[e.MemberExpression=3]="MemberExpression",e[e.CallExpression=4]="CallExpression",e[e.BinaryExpression=5]="BinaryExpression",e[e.UnaryExpression=6]="UnaryExpression",e[e.ConditionalExpression=7]="ConditionalExpression"})(Ae||(Ae={}));var Pv=new Map([["||",2],["&&",3],["===",4],["!==",4],[">",5],[">=",5],["<",5],["<=",5],["+",6],["-",6],["*",7],["/",7],["%",7],["!",8]]),Fv={type:Ae.Literal,value:null},Dv={type:Ae.Literal,value:!0},Bv={type:Ae.Literal,value:!1},Gv=e=>{let t=0,n=e.length,u=()=>t>=n?null:e[t],s=()=>e[t++],f=d=>{let v=u();return v!==null&&v.type===d},c=d=>d.type===he.OPERATOR?Pv.get(d.value)||-1:d.type===he.DOT||d.type===he.BRACKET_LEFT?9:d.type===he.QUESTION?1:-1,h=d=>{let v,y;if(s().type===he.DOT){if(!f(he.IDENTIFIER)){let I=u();throw new Oe("Expected property name",t,I?I.value:"")}let S=s();v={type:Ae.Identifier,name:S.value},y=!1}else{if(v=p(0),!f(he.BRACKET_RIGHT)){let S=u();throw new Oe("Expected closing bracket",t,S?S.value:"")}s(),y=!0}return{type:Ae.MemberExpression,object:d,property:v,computed:y}},_=()=>{let d=u();if(!d)throw new Oe("Unexpected end of input",t,"");if(d.type===he.OPERATOR&&(d.value==="!"||d.value==="-")){s();let v=_();return{type:Ae.UnaryExpression,operator:d.value,argument:v,prefix:!0}}switch(d.type){case he.NUMBER:return s(),{type:Ae.Literal,value:Number(d.value)};case he.STRING:return s(),{type:Ae.Literal,value:d.value};case he.BOOLEAN:return s(),d.value==="true"?Dv:Bv;case he.NULL:return s(),Fv;case he.IDENTIFIER:return s(),{type:Ae.Identifier,name:d.value};case he.FUNCTION:return(()=>{let v=s(),y=[];if(!f(he.PAREN_LEFT)){let S=u();throw new Oe("Expected opening parenthesis after function name",t,S?S.value:"")}for(s();;){if(f(he.PAREN_RIGHT)){s();break}if(!u()){let I=u();throw new Oe("Expected closing parenthesis",t,I?I.value:"")}if(y.length>0){if(!f(he.COMMA)){let I=u();throw new Oe("Expected comma between function arguments",t,I?I.value:"")}s()}let S=p(0);y.push(S)}return{type:Ae.CallExpression,callee:{type:Ae.Identifier,name:v.value},arguments:y}})();case he.PAREN_LEFT:{s();let v=p(0);if(!f(he.PAREN_RIGHT)){let y=u();throw new Oe("Expected closing parenthesis",t,y?y.value:"")}return s(),v}default:throw new Oe(\`Unexpected token: \${d.type}\`,t,d.value)}},p=(d=0)=>{let v=_();for(;t")}s();let E=p(0);v={type:Ae.ConditionalExpression,test:v,consequent:I,alternate:E}}}return v},m=p();return{type:Ae.Program,body:m}},Uv=(e,t,n)=>{let u=t;n&&(u={...t,context:{...t.context,...n}});let s=f=>{switch(f.type){case Ae.Literal:return(c=>c.value)(f);case Ae.Identifier:return(c=>{if(!(c.name in u.context))throw new Oe(\`Undefined variable: \${c.name}\`);return u.context[c.name]})(f);case Ae.MemberExpression:return(c=>{let h=s(c.object);if(h==null)throw new Oe("Cannot access property of null or undefined");return h[c.computed?s(c.property):c.property.name]})(f);case Ae.CallExpression:return(c=>{let h=u.functions[c.callee.name];if(!h)throw new Oe(\`Undefined function: \${c.callee.name}\`);return h(...c.arguments.map((_=>s(_))))})(f);case Ae.BinaryExpression:return(c=>{if(c.operator==="&&"){let p=s(c.left);return p&&s(c.right)}if(c.operator==="||")return s(c.left)||s(c.right);let h=s(c.left),_=s(c.right);switch(c.operator){case"+":return h+_;case"-":return h-_;case"*":return h*_;case"/":return h/_;case"%":return h%_;case"===":return h===_;case"!==":return h!==_;case">":return h>_;case">=":return h>=_;case"<":return h<_;case"<=":return h<=_;default:throw new Oe(\`Unknown operator: \${c.operator}\`)}})(f);case Ae.UnaryExpression:return(c=>{let h=s(c.argument);if(c.prefix)switch(c.operator){case"!":return!h;case"-":if(typeof h!="number")throw new Oe(\`Cannot apply unary - to non-number: \${h}\`);return-h;default:throw new Oe(\`Unknown operator: \${c.operator}\`)}throw new Oe(\`Postfix operators are not supported: \${c.operator}\`)})(f);case Ae.ConditionalExpression:return(c=>{let h=s(c.test);return s(h?c.consequent:c.alternate)})(f);default:throw new Oe(\`Evaluation error: Unsupported node type: \${f.type}\`)}};return s(e.body)};function mn(e){let t=(s=>{let f=s,c=f.length,h=new Array(Math.ceil(c/3)),_=0,p=0;function m(E){let R=p+1;p++;let M="",A=!1;for(;p({context:s,functions:f}))({},Av);return(s={})=>Uv(n,u,s)}function ic(e,t={}){return mn(e)(t)}function nc(e,t){if(typeof e!="string")return;let n=e.trim();if(n)try{return mn(n),ic(n,t)}catch{return}}function Tr(e){return typeof e=="number"}function tt(e){if(!e)return[0,0,0];if(Tr(e))return[e,e,e];if(Array.isArray(e)&&e.length===0)return[0,0,0];let[t,n=t,u=t]=e;return[t,n,u]}function oc(e){return Tr(e)?!0:Array.isArray(e)?e.every(t=>Tr(t)):!1}function Ze(e){return e==null}function dn(e){return typeof e=="string"}function gn(e){return typeof e=="function"}function Ar(e,t){if(typeof e=="function")return e;if(typeof e=="string"){let n=e;return(...u)=>{let s={};for(let f=0;fe}function $t(e,t,n="node"){if(Ze(e))return()=>t;if(dn(e)){let u=Ar(e,[n]);return s=>{let f=u(s);return Tr(f)?f:t}}return gn(e)?e:Tr(e)?()=>e:()=>t}function At(e,t=10,n="node"){if(Ze(e))return()=>t;if(dn(e)){let u=Ar(e,[n]);return s=>{let f=u(s);return oc(f)?f:t}}return gn(e)?e:Tr(e)?()=>e:Array.isArray(e)?()=>e:()=>t}var Wt=(e,t,n=10,u=0)=>{let s=At(t,u),f=At(e,n);return c=>{let[h,_,p]=tt(f(c)),[m,d,v]=tt(s(c));return[h+m,_+d,p+v]}};function sc(e){var t;return[e.x,e.y,(t=e.z)!==null&&t!==void 0?t:0]}var Yt=class{constructor(t,n={}){this.edgeIdCounter=new Map,this.nodeMap=Kv(t.nodes,n.node),this.edgeMap=$v(t.edges||[],n.edge,this.getEdgeId.bind(this))}data(){return{nodes:this.nodeMap,edges:this.edgeMap}}replace(t){this.nodeMap=t.nodes,this.edgeMap=t.edges,this.clearCache()}nodes(){return Array.from(this.nodeMap.values())}node(t){return this.nodeMap.get(t)}nodeAt(t){this.indexNodeCache||this.buildNodeIndexCache();let n=this.indexNodeCache.get(t);return n?this.nodeMap.get(n):void 0}nodeIndexOf(t){var n;return this.nodeIndexCache||this.buildNodeIndexCache(),(n=this.nodeIndexCache.get(t))!==null&&n!==void 0?n:-1}firstNode(){return this.nodeMap.values().next().value}forEachNode(t){let n=0;this.nodeMap.forEach(u=>t(u,n++))}originalNode(t){let n=this.nodeMap.get(t);return n?._original}nodeCount(){return this.nodeMap.size}edges(){return Array.from(this.edgeMap.values())}edge(t){return this.edgeMap.get(t)}firstEdge(){return this.edgeMap.values().next().value}forEachEdge(t){let n=0;this.edgeMap.forEach(u=>t(u,n++))}originalEdge(t){let n=this.edgeMap.get(t);return n?._original}edgeCount(){return this.edgeMap.size}getEdgeId(t){if(t.id)return t.id;let n=\`\${t.source}-\${t.target}\`,u=this.edgeIdCounter.get(n)||0,s=u===0?n:\`\${n}-\${u}\`;return this.edgeIdCounter.set(n,u+1),s}degree(t,n="both"){this.degreeCache||this.buildDegreeCache();let u=this.degreeCache.get(t);return u?u[n]:0}neighbors(t,n="both"){if((!this.outAdjacencyCache||!this.inAdjacencyCache)&&this.buildAdjacencyCache(),n==="out")return Array.from(this.outAdjacencyCache.get(t)||[]);if(n==="in")return Array.from(this.inAdjacencyCache.get(t)||[]);if(this.bothAdjacencyCache)return Array.from(this.bothAdjacencyCache.get(t)||[]);let u=this.inAdjacencyCache.get(t),s=this.outAdjacencyCache.get(t);if(!u&&!s)return[];if(!u)return Array.from(s);if(!s)return Array.from(u);let f=new Set;return u.forEach(c=>f.add(c)),s.forEach(c=>f.add(c)),Array.from(f)}successors(t){return this.neighbors(t,"out")}predecessors(t){return this.neighbors(t,"in")}setNodeOrder(t){let n=new Map;for(let u of t)n.set(u.id,u);this.nodeMap=n,this.nodeIndexCache=void 0,this.indexNodeCache=void 0}clearCache(){this.degreeCache=void 0,this.inAdjacencyCache=void 0,this.outAdjacencyCache=void 0,this.bothAdjacencyCache=void 0,this.nodeIndexCache=void 0,this.indexNodeCache=void 0}buildDegreeCache(){this.degreeCache=new Map;for(let t of this.edges()){let{source:n,target:u}=t;if(t.source===t.target)continue;this.degreeCache.has(n)||this.degreeCache.set(n,{in:0,out:0,both:0});let s=this.degreeCache.get(t.source);s&&(s.out++,s.both++),this.degreeCache.has(u)||this.degreeCache.set(u,{in:0,out:0,both:0});let f=this.degreeCache.get(t.target);f&&(f.in++,f.both++)}}buildAdjacencyCache(){this.inAdjacencyCache=new Map,this.outAdjacencyCache=new Map;for(let t of this.edges())!this.nodeMap.has(t.source)||!this.nodeMap.has(t.target)||(this.outAdjacencyCache.has(t.source)||this.outAdjacencyCache.set(t.source,new Set),this.outAdjacencyCache.get(t.source).add(t.target),this.inAdjacencyCache.has(t.target)||this.inAdjacencyCache.set(t.target,new Set),this.inAdjacencyCache.get(t.target).add(t.source))}buildNodeIndexCache(){this.nodeIndexCache=new Map,this.indexNodeCache=new Map;let t=0;this.nodeMap.forEach((n,u)=>{this.nodeIndexCache.set(u,t),this.indexNodeCache.set(t,u),t++})}destroy(){this.clearCache(),this.nodeMap.clear(),this.edgeMap.clear(),this.edgeIdCounter.clear()}},zv=["id","x","y","z","vx","vy","vz","fx","fy","fz","parentId"],Vv=["id","source","target","points"];function Kv(e,t){if(!e)throw new Error("Data.nodes is required");let n=new Map;for(let u of e){let s={_original:u};for(let f of zv){let c=u[f];Ze(c)||(s[f]=c)}if(t){let f=t(u);for(let c in f){let h=f[c];Ze(h)||(s[c]=h)}}if(Ze(s.id))throw new Error("Node is missing id field");n.set(s.id,s)}return n}function $v(e,t,n){let u=new Map;for(let s of e){let f={_original:s};for(let c of Vv){let h=s[c];Ze(h)||(f[c]=h)}if(t){let c=t(s);for(let h in c){let _=c[h];Ze(_)||(f[h]=_)}}if(Ze(f.source)||Ze(f.target))throw new Error("Edge is missing source or target field");Ze(f.id)&&(f.id=n?.(s)),u.set(f.id,f)}return u}var Qt=class{constructor(t,n={}){this.graph=new Yt(t,n)}export(){return this.graph.data()}replace(t){this.graph.replace(t)}forEachNode(t){this.graph.forEachNode(t)}forEachEdge(t){this.graph.forEachEdge((n,u)=>{n.sourceNode=this.graph.node(n.source),n.targetNode=this.graph.node(n.target),t(n,u)})}destroy(){this.graph.destroy()}};var uc=Symbol("Comlink.proxy"),Wv=Symbol("Comlink.endpoint"),Yv=Symbol("Comlink.releaseProxy"),qn=Symbol("Comlink.finalizer"),Xt=Symbol("Comlink.thrown"),fc=e=>typeof e=="object"&&e!==null||typeof e=="function",Qv={canHandle:e=>fc(e)&&e[uc],serialize(e){let{port1:t,port2:n}=new MessageChannel;return hc(e,t),[n,[n]]},deserialize(e){return e.start(),yn(e)}},Jv={canHandle:e=>fc(e)&&Xt in e,serialize({value:e}){let t;return e instanceof Error?t={isError:!0,value:{message:e.message,name:e.name,stack:e.stack}}:t={isError:!1,value:e},[t,[]]},deserialize(e){throw e.isError?Object.assign(new Error(e.value.message),e.value):e.value}},cc=new Map([["proxy",Qv],["throw",Jv]]);function Xv(e,t){for(let n of e)if(t===n||n==="*"||n instanceof RegExp&&n.test(t))return!0;return!1}function hc(e,t=globalThis,n=["*"]){t.addEventListener("message",function u(s){if(!s||!s.data)return;if(!Xv(n,s.origin)){console.warn(\`Invalid origin '\${s.origin}' for comlink proxy\`);return}let{id:f,type:c,path:h}=Object.assign({path:[]},s.data),_=(s.data.argumentList||[]).map(Xr),p;try{let m=h.slice(0,-1).reduce((v,y)=>v[y],e),d=h.reduce((v,y)=>v[y],e);switch(c){case"GET":p=d;break;case"SET":m[h.slice(-1)[0]]=Xr(s.data.value),p=!0;break;case"APPLY":p=d.apply(m,_);break;case"CONSTRUCT":{let v=new d(..._);p=iy(v)}break;case"ENDPOINT":{let{port1:v,port2:y}=new MessageChannel;hc(e,y),p=ty(v,[v])}break;case"RELEASE":p=void 0;break;default:return}}catch(m){p={value:m,[Xt]:0}}Promise.resolve(p).catch(m=>({value:m,[Xt]:0})).then(m=>{let[d,v]=ei(m);t.postMessage(Object.assign(Object.assign({},d),{id:f}),v),c==="RELEASE"&&(t.removeEventListener("message",u),lc(t),qn in e&&typeof e[qn]=="function"&&e[qn]())}).catch(m=>{let[d,v]=ei({value:new TypeError("Unserializable return value"),[Xt]:0});t.postMessage(Object.assign(Object.assign({},d),{id:f}),v)})}),t.start&&t.start()}function Zv(e){return e.constructor.name==="MessagePort"}function lc(e){Zv(e)&&e.close()}function yn(e,t){let n=new Map;return e.addEventListener("message",function(s){let{data:f}=s;if(!f||!f.id)return;let c=n.get(f.id);if(c)try{c(f)}finally{n.delete(f.id)}}),vn(e,n,[],t)}function Jt(e){if(e)throw new Error("Proxy has been released and is not useable")}function pc(e){return it(e,new Map,{type:"RELEASE"}).then(()=>{lc(e)})}var Zt=new WeakMap,Ht="FinalizationRegistry"in globalThis&&new FinalizationRegistry(e=>{let t=(Zt.get(e)||0)-1;Zt.set(e,t),t===0&&pc(e)});function Hv(e,t){let n=(Zt.get(t)||0)+1;Zt.set(t,n),Ht&&Ht.register(e,t,e)}function ey(e){Ht&&Ht.unregister(e)}function vn(e,t,n=[],u=function(){}){let s=!1,f=new Proxy(u,{get(c,h){if(Jt(s),h===Yv)return()=>{ey(f),pc(e),t.clear(),s=!0};if(h==="then"){if(n.length===0)return{then:()=>f};let _=it(e,t,{type:"GET",path:n.map(p=>p.toString())}).then(Xr);return _.then.bind(_)}return vn(e,t,[...n,h])},set(c,h,_){Jt(s);let[p,m]=ei(_);return it(e,t,{type:"SET",path:[...n,h].map(d=>d.toString()),value:p},m).then(Xr)},apply(c,h,_){Jt(s);let p=n[n.length-1];if(p===Wv)return it(e,t,{type:"ENDPOINT"}).then(Xr);if(p==="bind")return vn(e,t,n.slice(0,-1));let[m,d]=ac(_);return it(e,t,{type:"APPLY",path:n.map(v=>v.toString()),argumentList:m},d).then(Xr)},construct(c,h){Jt(s);let[_,p]=ac(h);return it(e,t,{type:"CONSTRUCT",path:n.map(m=>m.toString()),argumentList:_},p).then(Xr)}});return Hv(f,e),f}function ry(e){return Array.prototype.concat.apply([],e)}function ac(e){let t=e.map(ei);return[t.map(n=>n[0]),ry(t.map(n=>n[1]))]}var _c=new WeakMap;function ty(e,t){return _c.set(e,t),e}function iy(e){return Object.assign(e,{[uc]:!0})}function ei(e){for(let[t,n]of cc)if(n.canHandle(e)){let[u,s]=n.serialize(e);return[{type:"HANDLER",name:t,value:u},s]}return[{type:"RAW",value:e},_c.get(e)||[]]}function Xr(e){switch(e.type){case"HANDLER":return cc.get(e.name).deserialize(e.value);case"RAW":return e.value}}function it(e,t,n,u){return new Promise(s=>{let f=ny();t.set(f,s),e.start&&e.start(),e.postMessage(Object.assign({id:f},n),u)})}function ny(){return new Array(4).fill(0).map(()=>Math.floor(Math.random()*Number.MAX_SAFE_INTEGER).toString(16)).join("-")}var ri=class{constructor(){this.worker=null,this.workerApi=null}execute(t,n,u){return He(this,void 0,void 0,function*(){if(this.worker||(yield this.initWorker()),!this.workerApi)throw new Error("Worker API not initialized");return yield this.workerApi.execute(t,n,u)})}destroy(){this.workerApi&&this.workerApi.destroy(),this.worker&&(this.worker.terminate(),this.worker=null,this.workerApi=null)}initWorker(){return He(this,void 0,void 0,function*(){let t=this.resolveWorkerPath(),u=t.includes("/lib/")||t.endsWith(".mjs")?"module":"classic";this.worker=new Worker(t,{type:u}),this.workerApi=yn(this.worker)})}resolveWorkerPath(){let t=(()=>{if(typeof document>"u")return null;let n=document.currentScript;if(n?.src)return n.src;let u=document.getElementsByTagName("script");for(let s=u.length-1;s>=0;s--){let f=u[s].src;if(f&&(f.includes("index.js")||f.includes("index.min.js")))return f}return null})();if(t){if(t.includes("index.js")||t.includes("index.min.js")){let s=t.replace(/index(\\.min)?\\.(m?js)(\\?.*)?$/,"worker.js");if(s!==t)return s}let n=t.replace(/\\/runtime\\/[^/]+\\.(m?js)(\\?.*)?$/,"/worker.js");if(n!==t)return n;let u=t.replace(/\\/[^/]+\\.(m?js)(\\?.*)?$/,"/worker.js");if(u!==t)return u}return"./worker.js"}};var gr=class{constructor(t){this.supervisor=null,this.initialOptions=this.mergeOptions(this.getDefaultOptions(),t)}get options(){return this.runtimeOptions||this.initialOptions}mergeOptions(t,n){return Object.assign({},t,n||{})}execute(t,n){return He(this,void 0,void 0,function*(){this.runtimeOptions=this.mergeOptions(this.initialOptions,n);let{node:u,edge:s,enableWorker:f}=this.runtimeOptions;this.context=new Qt(t,{node:u,edge:s}),this.model=this.context.graph,f&&typeof Worker<"u"?yield this.layoutInWorker(t,this.runtimeOptions):yield this.layout(this.runtimeOptions)})}layoutInWorker(t,n){var u;return He(this,void 0,void 0,function*(){try{this.supervisor||(this.supervisor=new ri);let s=yield this.supervisor.execute(this.id,t,n);(u=this.context)===null||u===void 0||u.replace(s)}catch(s){console.error("Layout in worker failed, fallback to main thread layout.",s),yield this.layout(n)}})}forEachNode(t){this.context.forEachNode(t)}forEachEdge(t){this.context.forEachEdge(t)}destroy(){var t;(t=this.context)===null||t===void 0||t.destroy(),this.model=null,this.context=null,this.supervisor&&(this.supervisor.destroy(),this.supervisor=null)}};function mc(e){return Array.isArray(e)}function nt(e,t,n=2){if(e.nodeCount()===1){let s=e.firstNode();s.x=t[0],s.y=t[1],n===3&&(s.z=t[2]||0)}}function dc(e,t){let n=e.nodes();return n.sort(t),e.setNodeOrder(n),e}function gc(e,t="desc"){return dc(e,(n,u)=>{let s=e.degree(n.id),f=e.degree(u.id);return t==="asc"?s-f:f-s})}function qc(e,t){return dc(e,(n,u)=>{let s=e.originalNode(n.id),f=e.originalNode(u.id);return t(s,f)})}var ot=e=>{let{width:t,height:n,center:u}=e,s=t??(typeof window<"u"?window.innerWidth:0),f=n??(typeof window<"u"?window.innerHeight:0),c=u??[s/2,f/2];return{width:s,height:f,center:c}};var ti={nodeSize:30,nodeSpacing:10,preventOverlap:!1,sweep:void 0,equidistant:!1,startAngle:3/2*Math.PI,clockwise:!0,maxLevelDiff:void 0,sortBy:"degree"},Ot=class extends gr{constructor(){super(...arguments),this.id="concentric"}getDefaultOptions(){return ti}layout(){return He(this,void 0,void 0,function*(){let{width:t,height:n,center:u}=ot(this.options),s=this.model.nodeCount();if(!s||s===1){nt(this.model,u);return}let{sortBy:f,maxLevelDiff:c,sweep:h,clockwise:_,equidistant:p,preventOverlap:m,startAngle:d=ti.startAngle,nodeSize:v,nodeSpacing:y}=this.options,S=!f||f==="degree"?"degree":Ar(f,["node"]);if(S==="degree")gc(this.model);else{let L=(B,U)=>{let z=S(B),$=S(U);return z===$?0:z>$?-1:1};qc(this.model,L)}let I=this.model.nodes(),E=new Map;for(let L of I){let B=S==="degree"?this.model.degree(L.id):S(L._original);E.set(L.id,B)}let R=this.model.firstNode(),M=c||E.get(R.id)/4,A=Wt(v,y,ti.nodeSize,ti.nodeSpacing),j=new Map;for(let L of I)j.set(L.id,Math.max(...A(L._original)));let P=[{nodes:[]}],F=P[0];for(let L=0;L0){let U=F.nodes[0],z=Math.abs(E.get(U.id)-E.get(B.id));M&&z>=M&&(F={nodes:[]},P.push(F))}F.nodes.push(B)}for(let L of P){let B=L.nodes.map(U=>j.get(U.id));L.nodeSizes=B,L.maxNodeSize=Math.max(...B)}if(P.forEach(L=>{let B=h===void 0?2*Math.PI-2*Math.PI/L.nodes.length:h;L.dTheta=B/Math.max(1,L.nodes.length-1)}),m){let L=0;for(let B=0;B1){let z=U.nodeSizes||[],$=0;for(let ve=0;ve0?$/le:0;L=Math.max(me,L)}if(U.r=L,B{z===0&&(B=U.r||0),U.r=B,B+=L})}P.forEach(L=>{let B=L.dTheta||0,U=L.r||0;L.nodes.forEach((z,$)=>{let Z=d+(_?1:-1)*B*$;z.x=u[0]+U*Math.cos(Z),z.y=u[1]+U*Math.sin(Z)})})})}};var vc=(function(e){var t=typeof e;return e!==null&&t==="object"||t==="function"});var yc=function(e){return typeof e=="object"&&e!==null};var oy={}.toString,ii=function(e,t){return oy.call(e)==="[object "+t+"]"};var wc=function(e){if(!yc(e)||!ii(e,"Object"))return!1;if(Object.getPrototypeOf(e)===null)return!0;for(var t=e;Object.getPrototypeOf(t)!==null;)t=Object.getPrototypeOf(t);return Object.getPrototypeOf(e)===t};var jt=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function ni(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function oi(e){if(Object.prototype.hasOwnProperty.call(e,"__esModule"))return e;var t=e.default;if(typeof t=="function"){var n=function u(){var s=!1;try{s=this instanceof u}catch{}return s?Reflect.construct(t,arguments,this.constructor):t.apply(this,arguments)};n.prototype=t.prototype}else n={};return Object.defineProperty(n,"__esModule",{value:!0}),Object.keys(e).forEach(function(u){var s=Object.getOwnPropertyDescriptor(e,u);Object.defineProperty(n,u,s.get?s:{enumerable:!0,get:function(){return e[u]}})}),n}function st(e){throw new Error('Could not dynamically require "'+e+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}var wn,bc;function xc(){if(bc)return wn;bc=1;function e(){this.__data__=[],this.size=0}return wn=e,wn}var bn,Ec;function sr(){if(Ec)return bn;Ec=1;function e(t,n){return t===n||t!==t&&n!==n}return bn=e,bn}var xn,Sc;function Or(){if(Sc)return xn;Sc=1;var e=sr();function t(n,u){for(var s=n.length;s--;)if(e(n[s][0],u))return s;return-1}return xn=t,xn}var En,Ic;function Rc(){if(Ic)return En;Ic=1;var e=Or(),t=Array.prototype,n=t.splice;function u(s){var f=this.__data__,c=e(f,s);if(c<0)return!1;var h=f.length-1;return c==h?f.pop():n.call(f,c,1),--this.size,!0}return En=u,En}var Sn,Mc;function Cc(){if(Mc)return Sn;Mc=1;var e=Or();function t(n){var u=this.__data__,s=e(u,n);return s<0?void 0:u[s][1]}return Sn=t,Sn}var In,Tc;function Ac(){if(Tc)return In;Tc=1;var e=Or();function t(n){return e(this.__data__,n)>-1}return In=t,In}var Rn,Oc;function jc(){if(Oc)return Rn;Oc=1;var e=Or();function t(n,u){var s=this.__data__,f=e(s,n);return f<0?(++this.size,s.push([n,u])):s[f][1]=u,this}return Rn=t,Rn}var Mn,kc;function jr(){if(kc)return Mn;kc=1;var e=xc(),t=Rc(),n=Cc(),u=Ac(),s=jc();function f(c){var h=-1,_=c==null?0:c.length;for(this.clear();++h<_;){var p=c[h];this.set(p[0],p[1])}}return f.prototype.clear=e,f.prototype.delete=t,f.prototype.get=n,f.prototype.has=u,f.prototype.set=s,Mn=f,Mn}var Cn,Nc;function Lc(){if(Nc)return Cn;Nc=1;var e=jr();function t(){this.__data__=new e,this.size=0}return Cn=t,Cn}var Tn,Pc;function Fc(){if(Pc)return Tn;Pc=1;function e(t){var n=this.__data__,u=n.delete(t);return this.size=n.size,u}return Tn=e,Tn}var An,Dc;function Bc(){if(Dc)return An;Dc=1;function e(t){return this.__data__.get(t)}return An=e,An}var On,Gc;function Uc(){if(Gc)return On;Gc=1;function e(t){return this.__data__.has(t)}return On=e,On}var jn,zc;function si(){if(zc)return jn;zc=1;var e=typeof jt=="object"&&jt&&jt.Object===Object&&jt;return jn=e,jn}var kn,Vc;function je(){if(Vc)return kn;Vc=1;var e=si(),t=typeof self=="object"&&self&&self.Object===Object&&self,n=e||t||Function("return this")();return kn=n,kn}var Nn,Kc;function ar(){if(Kc)return Nn;Kc=1;var e=je(),t=e.Symbol;return Nn=t,Nn}var Ln,$c;function Wc(){if($c)return Ln;$c=1;var e=ar(),t=Object.prototype,n=t.hasOwnProperty,u=t.toString,s=e?e.toStringTag:void 0;function f(c){var h=n.call(c,s),_=c[s];try{c[s]=void 0;var p=!0}catch{}var m=u.call(c);return p&&(h?c[s]=_:delete c[s]),m}return Ln=f,Ln}var Pn,Yc;function Qc(){if(Yc)return Pn;Yc=1;var e=Object.prototype,t=e.toString;function n(u){return t.call(u)}return Pn=n,Pn}var Fn,Jc;function er(){if(Jc)return Fn;Jc=1;var e=ar(),t=Wc(),n=Qc(),u="[object Null]",s="[object Undefined]",f=e?e.toStringTag:void 0;function c(h){return h==null?h===void 0?s:u:f&&f in Object(h)?t(h):n(h)}return Fn=c,Fn}var Dn,Xc;function Me(){if(Xc)return Dn;Xc=1;function e(t){var n=typeof t;return t!=null&&(n=="object"||n=="function")}return Dn=e,Dn}var Bn,Zc;function qr(){if(Zc)return Bn;Zc=1;var e=er(),t=Me(),n="[object AsyncFunction]",u="[object Function]",s="[object GeneratorFunction]",f="[object Proxy]";function c(h){if(!t(h))return!1;var _=e(h);return _==u||_==s||_==n||_==f}return Bn=c,Bn}var Gn,Hc;function eh(){if(Hc)return Gn;Hc=1;var e=je(),t=e["__core-js_shared__"];return Gn=t,Gn}var Un,rh;function th(){if(rh)return Un;rh=1;var e=eh(),t=(function(){var u=/[^.]+$/.exec(e&&e.keys&&e.keys.IE_PROTO||"");return u?"Symbol(src)_1."+u:""})();function n(u){return!!t&&t in u}return Un=n,Un}var zn,ih;function ai(){if(ih)return zn;ih=1;var e=Function.prototype,t=e.toString;function n(u){if(u!=null){try{return t.call(u)}catch{}try{return u+""}catch{}}return""}return zn=n,zn}var Vn,nh;function oh(){if(nh)return Vn;nh=1;var e=qr(),t=th(),n=Me(),u=ai(),s=/[\\\\^$.*+?()[\\]{}|]/g,f=/^\\[object .+?Constructor\\]$/,c=Function.prototype,h=Object.prototype,_=c.toString,p=h.hasOwnProperty,m=RegExp("^"+_.call(p).replace(s,"\\\\$&").replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g,"$1.*?")+"$");function d(v){if(!n(v)||t(v))return!1;var y=e(v)?m:f;return y.test(u(v))}return Vn=d,Vn}var Kn,sh;function ah(){if(sh)return Kn;sh=1;function e(t,n){return t?.[n]}return Kn=e,Kn}var $n,uh;function rr(){if(uh)return $n;uh=1;var e=oh(),t=ah();function n(u,s){var f=t(u,s);return e(f)?f:void 0}return $n=n,$n}var Wn,fh;function at(){if(fh)return Wn;fh=1;var e=rr(),t=je(),n=e(t,"Map");return Wn=n,Wn}var Yn,ch;function kr(){if(ch)return Yn;ch=1;var e=rr(),t=e(Object,"create");return Yn=t,Yn}var Qn,hh;function lh(){if(hh)return Qn;hh=1;var e=kr();function t(){this.__data__=e?e(null):{},this.size=0}return Qn=t,Qn}var Jn,ph;function _h(){if(ph)return Jn;ph=1;function e(t){var n=this.has(t)&&delete this.__data__[t];return this.size-=n?1:0,n}return Jn=e,Jn}var Xn,mh;function dh(){if(mh)return Xn;mh=1;var e=kr(),t="__lodash_hash_undefined__",n=Object.prototype,u=n.hasOwnProperty;function s(f){var c=this.__data__;if(e){var h=c[f];return h===t?void 0:h}return u.call(c,f)?c[f]:void 0}return Xn=s,Xn}var Zn,gh;function qh(){if(gh)return Zn;gh=1;var e=kr(),t=Object.prototype,n=t.hasOwnProperty;function u(s){var f=this.__data__;return e?f[s]!==void 0:n.call(f,s)}return Zn=u,Zn}var Hn,vh;function yh(){if(vh)return Hn;vh=1;var e=kr(),t="__lodash_hash_undefined__";function n(u,s){var f=this.__data__;return this.size+=this.has(u)?0:1,f[u]=e&&s===void 0?t:s,this}return Hn=n,Hn}var eo,wh;function bh(){if(wh)return eo;wh=1;var e=lh(),t=_h(),n=dh(),u=qh(),s=yh();function f(c){var h=-1,_=c==null?0:c.length;for(this.clear();++h<_;){var p=c[h];this.set(p[0],p[1])}}return f.prototype.clear=e,f.prototype.delete=t,f.prototype.get=n,f.prototype.has=u,f.prototype.set=s,eo=f,eo}var ro,xh;function Eh(){if(xh)return ro;xh=1;var e=bh(),t=jr(),n=at();function u(){this.size=0,this.__data__={hash:new e,map:new(n||t),string:new e}}return ro=u,ro}var to,Sh;function Ih(){if(Sh)return to;Sh=1;function e(t){var n=typeof t;return n=="string"||n=="number"||n=="symbol"||n=="boolean"?t!=="__proto__":t===null}return to=e,to}var io,Rh;function Nr(){if(Rh)return io;Rh=1;var e=Ih();function t(n,u){var s=n.__data__;return e(u)?s[typeof u=="string"?"string":"hash"]:s.map}return io=t,io}var no,Mh;function Ch(){if(Mh)return no;Mh=1;var e=Nr();function t(n){var u=e(this,n).delete(n);return this.size-=u?1:0,u}return no=t,no}var oo,Th;function Ah(){if(Th)return oo;Th=1;var e=Nr();function t(n){return e(this,n).get(n)}return oo=t,oo}var so,Oh;function jh(){if(Oh)return so;Oh=1;var e=Nr();function t(n){return e(this,n).has(n)}return so=t,so}var ao,kh;function Nh(){if(kh)return ao;kh=1;var e=Nr();function t(n,u){var s=e(this,n),f=s.size;return s.set(n,u),this.size+=s.size==f?0:1,this}return ao=t,ao}var uo,Lh;function ut(){if(Lh)return uo;Lh=1;var e=Eh(),t=Ch(),n=Ah(),u=jh(),s=Nh();function f(c){var h=-1,_=c==null?0:c.length;for(this.clear();++h<_;){var p=c[h];this.set(p[0],p[1])}}return f.prototype.clear=e,f.prototype.delete=t,f.prototype.get=n,f.prototype.has=u,f.prototype.set=s,uo=f,uo}var fo,Ph;function Fh(){if(Ph)return fo;Ph=1;var e=jr(),t=at(),n=ut(),u=200;function s(f,c){var h=this.__data__;if(h instanceof e){var _=h.__data__;if(!t||_.length-1&&u%1==0&&u-1&&n%1==0&&n<=e}return Eo=t,Eo}var So,il;function nl(){if(il)return So;il=1;var e=er(),t=ht(),n=Le(),u="[object Arguments]",s="[object Array]",f="[object Boolean]",c="[object Date]",h="[object Error]",_="[object Function]",p="[object Map]",m="[object Number]",d="[object Object]",v="[object RegExp]",y="[object Set]",S="[object String]",I="[object WeakMap]",E="[object ArrayBuffer]",R="[object DataView]",M="[object Float32Array]",A="[object Float64Array]",j="[object Int8Array]",P="[object Int16Array]",F="[object Int32Array]",L="[object Uint8Array]",B="[object Uint8ClampedArray]",U="[object Uint16Array]",z="[object Uint32Array]",$={};$[M]=$[A]=$[j]=$[P]=$[F]=$[L]=$[B]=$[U]=$[z]=!0,$[u]=$[s]=$[E]=$[f]=$[R]=$[c]=$[h]=$[_]=$[p]=$[m]=$[d]=$[v]=$[y]=$[S]=$[I]=!1;function Z(ie){return n(ie)&&t(ie.length)&&!!$[e(ie)]}return So=Z,So}var Io,ol;function Br(){if(ol)return Io;ol=1;function e(t){return function(n){return t(n)}}return Io=e,Io}var lt={exports:{}};lt.exports;var sl;function pt(){return sl?lt.exports:(sl=1,(function(e,t){var n=si(),u=t&&!t.nodeType&&t,s=u&&!0&&e&&!e.nodeType&&e,f=s&&s.exports===u,c=f&&n.process,h=(function(){try{var _=s&&s.require&&s.require("util").types;return _||c&&c.binding&&c.binding("util")}catch{}})();e.exports=h})(lt,lt.exports),lt.exports)}var Ro,al;function wr(){if(al)return Ro;al=1;var e=nl(),t=Br(),n=pt(),u=n&&n.isTypedArray,s=u?t(u):e;return Ro=s,Ro}var Mo,ul;function fi(){if(ul)return Mo;ul=1;var e=$h(),t=yr(),n=pe(),u=ur(),s=Dr(),f=wr(),c=Object.prototype,h=c.hasOwnProperty;function _(p,m){var d=n(p),v=!d&&t(p),y=!d&&!v&&u(p),S=!d&&!v&&!y&&f(p),I=d||v||y||S,E=I?e(p.length,String):[],R=E.length;for(var M in p)(m||h.call(p,M))&&!(I&&(M=="length"||y&&(M=="offset"||M=="parent")||S&&(M=="buffer"||M=="byteLength"||M=="byteOffset")||s(M,R)))&&E.push(M);return E}return Mo=_,Mo}var Co,fl;function Gr(){if(fl)return Co;fl=1;var e=Object.prototype;function t(n){var u=n&&n.constructor,s=typeof u=="function"&&u.prototype||e;return n===s}return Co=t,Co}var To,cl;function ci(){if(cl)return To;cl=1;function e(t,n){return function(u){return t(n(u))}}return To=e,To}var Ao,hl;function ll(){if(hl)return Ao;hl=1;var e=ci(),t=e(Object.keys,Object);return Ao=t,Ao}var Oo,pl;function _t(){if(pl)return Oo;pl=1;var e=Gr(),t=ll(),n=Object.prototype,u=n.hasOwnProperty;function s(f){if(!e(f))return t(f);var c=[];for(var h in Object(f))u.call(f,h)&&h!="constructor"&&c.push(h);return c}return Oo=s,Oo}var jo,_l;function Ue(){if(_l)return jo;_l=1;var e=qr(),t=ht();function n(u){return u!=null&&t(u.length)&&!e(u)}return jo=n,jo}var ko,ml;function Xe(){if(ml)return ko;ml=1;var e=fi(),t=_t(),n=Ue();function u(s){return n(s)?e(s):t(s)}return ko=u,ko}var No,dl;function gl(){if(dl)return No;dl=1;var e=vr(),t=Xe();function n(u,s){return u&&e(s,t(s),u)}return No=n,No}var Lo,ql;function vl(){if(ql)return Lo;ql=1;function e(t){var n=[];if(t!=null)for(var u in Object(t))n.push(u);return n}return Lo=e,Lo}var Po,yl;function wl(){if(yl)return Po;yl=1;var e=Me(),t=Gr(),n=vl(),u=Object.prototype,s=u.hasOwnProperty;function f(c){if(!e(c))return n(c);var h=t(c),_=[];for(var p in c)p=="constructor"&&(h||!s.call(c,p))||_.push(p);return _}return Po=f,Po}var Fo,bl;function tr(){if(bl)return Fo;bl=1;var e=fi(),t=wl(),n=Ue();function u(s){return n(s)?e(s,!0):t(s)}return Fo=u,Fo}var Do,xl;function El(){if(xl)return Do;xl=1;var e=vr(),t=tr();function n(u,s){return u&&e(s,t(s),u)}return Do=n,Do}var mt={exports:{}};mt.exports;var Sl;function hi(){return Sl?mt.exports:(Sl=1,(function(e,t){var n=je(),u=t&&!t.nodeType&&t,s=u&&!0&&e&&!e.nodeType&&e,f=s&&s.exports===u,c=f?n.Buffer:void 0,h=c?c.allocUnsafe:void 0;function _(p,m){if(m)return p.slice();var d=p.length,v=h?h(d):new p.constructor(d);return p.copy(v),v}e.exports=_})(mt,mt.exports),mt.exports)}var Bo,Il;function li(){if(Il)return Bo;Il=1;function e(t,n){var u=-1,s=t.length;for(n||(n=Array(s));++uy))return!1;var I=d.get(c),E=d.get(h);if(I&&E)return I==h&&E==c;var R=-1,M=!0,A=_&s?new e:void 0;for(d.set(c,h),d.set(h,c);++R0&&f(m)?s>1?n(m,s-1,f,c,h):e(h,m):c||(h[h.length]=m)}return h}return Aa=n,Aa}var Oa,_m;function mm(){if(_m)return Oa;_m=1;function e(t,n,u){switch(u.length){case 0:return t.call(n);case 1:return t.call(n,u[0]);case 2:return t.call(n,u[0],u[1]);case 3:return t.call(n,u[0],u[1],u[2])}return t.apply(n,u)}return Oa=e,Oa}var ja,dm;function zi(){if(dm)return ja;dm=1;var e=mm(),t=Math.max;function n(u,s,f){return s=t(s===void 0?u.length-1:s,0),function(){for(var c=arguments,h=-1,_=t(c.length-s,0),p=Array(_);++h<_;)p[h]=c[s+h];h=-1;for(var m=Array(s+1);++h0){if(++f>=e)return arguments[0]}else f=0;return s.apply(void 0,arguments)}}return Na=u,Na}var La,wm;function Vi(){if(wm)return La;wm=1;var e=qm(),t=ym(),n=t(e);return La=n,La}var Pa,bm;function Wr(){if(bm)return Pa;bm=1;var e=ir(),t=zi(),n=Vi();function u(s,f){return n(t(s,f,e),s+"")}return Pa=u,Pa}var Fa,xm;function Ki(){if(xm)return Fa;xm=1;function e(t,n,u,s){for(var f=t.length,c=u+(s?1:-1);s?c--:++c-1}return Ua=t,Ua}var za,Om;function jm(){if(Om)return za;Om=1;function e(t,n,u){for(var s=-1,f=t==null?0:t.length;++s=c){var R=p?null:s(_);if(R)return f(R);S=!1,v=u,E=new e}else E=p?[]:I;e:for(;++d1?y.setNode(S,d):y.setNode(S)}),this},s.prototype.setNode=function(m,d){return e.has(this._nodes,m)?(arguments.length>1&&(this._nodes[m]=d),this):(this._nodes[m]=arguments.length>1?d:this._defaultNodeLabelFn(m),this._isCompound&&(this._parent[m]=n,this._children[m]={},this._children[n][m]=!0),this._in[m]={},this._preds[m]={},this._out[m]={},this._sucs[m]={},++this._nodeCount,this)},s.prototype.node=function(m){return this._nodes[m]},s.prototype.hasNode=function(m){return e.has(this._nodes,m)},s.prototype.removeNode=function(m){var d=this;if(e.has(this._nodes,m)){var v=function(y){d.removeEdge(d._edgeObjs[y])};delete this._nodes[m],this._isCompound&&(this._removeFromParentsChildList(m),delete this._parent[m],e.each(this.children(m),function(y){d.setParent(y)}),delete this._children[m]),e.each(e.keys(this._in[m]),v),delete this._in[m],delete this._preds[m],e.each(e.keys(this._out[m]),v),delete this._out[m],delete this._sucs[m],--this._nodeCount}return this},s.prototype.setParent=function(m,d){if(!this._isCompound)throw new Error("Cannot set parent in a non-compound graph");if(e.isUndefined(d))d=n;else{d+="";for(var v=d;!e.isUndefined(v);v=this.parent(v))if(v===m)throw new Error("Setting "+d+" as parent of "+m+" would create a cycle");this.setNode(d)}return this.setNode(m),this._removeFromParentsChildList(m),this._parent[m]=d,this._children[d][m]=!0,this},s.prototype._removeFromParentsChildList=function(m){delete this._children[this._parent[m]][m]},s.prototype.parent=function(m){if(this._isCompound){var d=this._parent[m];if(d!==n)return d}},s.prototype.children=function(m){if(e.isUndefined(m)&&(m=n),this._isCompound){var d=this._children[m];if(d)return e.keys(d)}else{if(m===n)return this.nodes();if(this.hasNode(m))return[]}},s.prototype.predecessors=function(m){var d=this._preds[m];if(d)return e.keys(d)},s.prototype.successors=function(m){var d=this._sucs[m];if(d)return e.keys(d)},s.prototype.neighbors=function(m){var d=this.predecessors(m);if(d)return e.union(d,this.successors(m))},s.prototype.isLeaf=function(m){var d;return this.isDirected()?d=this.successors(m):d=this.neighbors(m),d.length===0},s.prototype.filterNodes=function(m){var d=new this.constructor({directed:this._isDirected,multigraph:this._isMultigraph,compound:this._isCompound});d.setGraph(this.graph());var v=this;e.each(this._nodes,function(I,E){m(E)&&d.setNode(E,I)}),e.each(this._edgeObjs,function(I){d.hasNode(I.v)&&d.hasNode(I.w)&&d.setEdge(I,v.edge(I))});var y={};function S(I){var E=v.parent(I);return E===void 0||d.hasNode(E)?(y[I]=E,E):E in y?y[E]:S(E)}return this._isCompound&&e.each(d.nodes(),function(I){d.setParent(I,S(I))}),d},s.prototype.setDefaultEdgeLabel=function(m){return e.isFunction(m)||(m=e.constant(m)),this._defaultEdgeLabelFn=m,this},s.prototype.edgeCount=function(){return this._edgeCount},s.prototype.edges=function(){return e.values(this._edgeObjs)},s.prototype.setPath=function(m,d){var v=this,y=arguments;return e.reduce(m,function(S,I){return y.length>1?v.setEdge(S,I,d):v.setEdge(S,I),I}),this},s.prototype.setEdge=function(){var m,d,v,y,S=!1,I=arguments[0];typeof I=="object"&&I!==null&&"v"in I?(m=I.v,d=I.w,v=I.name,arguments.length===2&&(y=arguments[1],S=!0)):(m=I,d=arguments[1],v=arguments[3],arguments.length>2&&(y=arguments[2],S=!0)),m=""+m,d=""+d,e.isUndefined(v)||(v=""+v);var E=h(this._isDirected,m,d,v);if(e.has(this._edgeLabels,E))return S&&(this._edgeLabels[E]=y),this;if(!e.isUndefined(v)&&!this._isMultigraph)throw new Error("Cannot set a named edge when isMultigraph = false");this.setNode(m),this.setNode(d),this._edgeLabels[E]=S?y:this._defaultEdgeLabelFn(m,d,v);var R=_(this._isDirected,m,d,v);return m=R.v,d=R.w,Object.freeze(R),this._edgeObjs[E]=R,f(this._preds[d],m),f(this._sucs[m],d),this._in[d][E]=R,this._out[m][E]=R,this._edgeCount++,this},s.prototype.edge=function(m,d,v){var y=arguments.length===1?p(this._isDirected,arguments[0]):h(this._isDirected,m,d,v);return this._edgeLabels[y]},s.prototype.hasEdge=function(m,d,v){var y=arguments.length===1?p(this._isDirected,arguments[0]):h(this._isDirected,m,d,v);return e.has(this._edgeLabels,y)},s.prototype.removeEdge=function(m,d,v){var y=arguments.length===1?p(this._isDirected,arguments[0]):h(this._isDirected,m,d,v),S=this._edgeObjs[y];return S&&(m=S.v,d=S.w,delete this._edgeLabels[y],delete this._edgeObjs[y],c(this._preds[d],m),c(this._sucs[m],d),delete this._in[d][y],delete this._out[m][y],this._edgeCount--),this},s.prototype.inEdges=function(m,d){var v=this._in[m];if(v){var y=e.values(v);return d?e.filter(y,function(S){return S.v===d}):y}},s.prototype.outEdges=function(m,d){var v=this._out[m];if(v){var y=e.values(v);return d?e.filter(y,function(S){return S.w===d}):y}},s.prototype.nodeEdges=function(m,d){var v=this.inEdges(m,d);if(v)return v.concat(this.outEdges(m,d))};function f(m,d){m[d]?m[d]++:m[d]=1}function c(m,d){--m[d]||delete m[d]}function h(m,d,v,y){var S=""+d,I=""+v;if(!m&&S>I){var E=S;S=I,I=E}return S+u+I+u+(e.isUndefined(y)?t:y)}function _(m,d,v,y){var S=""+d,I=""+v;if(!m&&S>I){var E=S;S=I,I=E}var R={v:S,w:I};return y&&(R.name=y),R}function p(m,d){return h(m,d.v,d.w,d.name)}return Za}var Ha,Ym;function Qm(){return Ym||(Ym=1,Ha="2.1.8"),Ha}var eu,Jm;function Xm(){return Jm||(Jm=1,eu={Graph:St(),version:Qm()}),eu}var ru,Zm;function Hm(){if(Zm)return ru;Zm=1;var e=Ce(),t=St();ru={write:n,read:f};function n(c){var h={options:{directed:c.isDirected(),multigraph:c.isMultigraph(),compound:c.isCompound()},nodes:u(c),edges:s(c)};return e.isUndefined(c.graph())||(h.value=e.clone(c.graph())),h}function u(c){return e.map(c.nodes(),function(h){var _=c.node(h),p=c.parent(h),m={v:h};return e.isUndefined(_)||(m.value=_),e.isUndefined(p)||(m.parent=p),m})}function s(c){return e.map(c.edges(),function(h){var _=c.edge(h),p={v:h.v,w:h.w};return e.isUndefined(h.name)||(p.name=h.name),e.isUndefined(_)||(p.value=_),p})}function f(c){var h=new t(c.options).setGraph(c.value);return e.each(c.nodes,function(_){h.setNode(_.v,_.value),_.parent&&h.setParent(_.v,_.parent)}),e.each(c.edges,function(_){h.setEdge({v:_.v,w:_.w,name:_.name},_.value)}),h}return ru}var tu,ed;function rd(){if(ed)return tu;ed=1;var e=Ce();tu=t;function t(n){var u={},s=[],f;function c(h){e.has(u,h)||(u[h]=!0,f.push(h),e.each(n.successors(h),c),e.each(n.predecessors(h),c))}return e.each(n.nodes(),function(h){f=[],c(h),f.length&&s.push(f)}),s}return tu}var iu,td;function Yi(){if(td)return iu;td=1;var e=Ce();iu=t;function t(){this._arr=[],this._keyIndices={}}return t.prototype.size=function(){return this._arr.length},t.prototype.keys=function(){return this._arr.map(function(n){return n.key})},t.prototype.has=function(n){return e.has(this._keyIndices,n)},t.prototype.priority=function(n){var u=this._keyIndices[n];if(u!==void 0)return this._arr[u].priority},t.prototype.min=function(){if(this.size()===0)throw new Error("Queue underflow");return this._arr[0].key},t.prototype.add=function(n,u){var s=this._keyIndices;if(n=String(n),!e.has(s,n)){var f=this._arr,c=f.length;return s[n]=c,f.push({key:n,priority:u}),this._decrease(c),!0}return!1},t.prototype.removeMin=function(){this._swap(0,this._arr.length-1);var n=this._arr.pop();return delete this._keyIndices[n.key],this._heapify(0),n.key},t.prototype.decrease=function(n,u){var s=this._keyIndices[n];if(u>this._arr[s].priority)throw new Error("New priority is greater than current priority. Key: "+n+" Old: "+this._arr[s].priority+" New: "+u);this._arr[s].priority=u,this._decrease(s)},t.prototype._heapify=function(n){var u=this._arr,s=2*n,f=s+1,c=n;s>1,!(u[f].priority0&&(d=m.removeMin(),v=p[d],v.distance!==Number.POSITIVE_INFINITY);)_(d).forEach(y);return p}return nu}var ou,nd;function od(){if(nd)return ou;nd=1;var e=Qi(),t=Ce();ou=n;function n(u,s,f){return t.transform(u.nodes(),function(c,h){c[h]=e(u,h,s,f)},{})}return ou}var su,sd;function Ji(){if(sd)return su;sd=1;var e=Ce();su=t;function t(n){var u=0,s=[],f={},c=[];function h(_){var p=f[_]={onStack:!0,lowlink:u,index:u++};if(s.push(_),n.successors(_).forEach(function(v){e.has(f,v)?f[v].onStack&&(p.lowlink=Math.min(p.lowlink,f[v].index)):(h(v),p.lowlink=Math.min(p.lowlink,f[v].lowlink))}),p.lowlink===p.index){var m=[],d;do d=s.pop(),f[d].onStack=!1,m.push(d);while(_!==d);c.push(m)}}return n.nodes().forEach(function(_){e.has(f,_)||h(_)}),c}return su}var au,ad;function ud(){if(ad)return au;ad=1;var e=Ce(),t=Ji();au=n;function n(u){return e.filter(t(u),function(s){return s.length>1||s.length===1&&u.hasEdge(s[0],s[0])})}return au}var uu,fd;function cd(){if(fd)return uu;fd=1;var e=Ce();uu=n;var t=e.constant(1);function n(s,f,c){return u(s,f||t,c||function(h){return s.outEdges(h)})}function u(s,f,c){var h={},_=s.nodes();return _.forEach(function(p){h[p]={},h[p][p]={distance:0},_.forEach(function(m){p!==m&&(h[p][m]={distance:Number.POSITIVE_INFINITY})}),c(p).forEach(function(m){var d=m.v===p?m.w:m.v,v=f(m);h[p][d]={distance:v,predecessor:p}})}),_.forEach(function(p){var m=h[p];_.forEach(function(d){var v=h[d];_.forEach(function(y){var S=v[p],I=m[y],E=v[y],R=S.distance+I.distance;R0;){if(p=_.removeMin(),e.has(h,p))c.setEdge(p,h[p]);else{if(d)throw new Error("Input graph is not connected: "+s);d=!0}s.nodeEdges(p).forEach(m)}return c}return _u}var mu,wd;function bd(){return wd||(wd=1,mu={components:rd(),dijkstra:Qi(),dijkstraAll:od(),findCycles:ud(),floydWarshall:cd(),isAcyclic:pd(),postorder:dd(),preorder:qd(),prim:yd(),tarjan:Ji(),topsort:Xi()}),mu}var du,xd;function Ed(){if(xd)return du;xd=1;var e=Xm();return du={Graph:e.Graph,json:Hm(),alg:bd(),version:e.version},du}var gu,Sd;function ke(){if(Sd)return gu;Sd=1;var e;if(typeof st=="function")try{e=Ed()}catch{}return e||(e=window.graphlib),gu=e,gu}var qu,Id;function Rd(){if(Id)return qu;Id=1;var e=xi(),t=1,n=4;function u(s){return e(s,t|n)}return qu=u,qu}var vu,Md;function Yr(){if(Md)return vu;Md=1;var e=sr(),t=Ue(),n=Dr(),u=Me();function s(f,c,h){if(!u(h))return!1;var _=typeof c;return(_=="number"?t(h)&&n(c,h.length):_=="string"&&c in h)?e(h[c],f):!1}return vu=s,vu}var yu,Cd;function Td(){if(Cd)return yu;Cd=1;var e=Wr(),t=sr(),n=Yr(),u=tr(),s=Object.prototype,f=s.hasOwnProperty,c=e(function(h,_){h=Object(h);var p=-1,m=_.length,d=m>2?_[2]:void 0;for(d&&n(_[0],_[1],d)&&(m=1);++p-1?_[p?f[m]:m]:void 0}}return wu=u,wu}var bu,jd;function kd(){if(jd)return bu;jd=1;var e=/\\s/;function t(n){for(var u=n.length;u--&&e.test(n.charAt(u)););return u}return bu=t,bu}var xu,Nd;function Ld(){if(Nd)return xu;Nd=1;var e=kd(),t=/^\\s+/;function n(u){return u&&u.slice(0,e(u)+1).replace(t,"")}return xu=n,xu}var Eu,Pd;function Fd(){if(Pd)return Eu;Pd=1;var e=Ld(),t=Me(),n=cr(),u=NaN,s=/^[-+]0x[0-9a-f]+$/i,f=/^0b[01]+$/i,c=/^0o[0-7]+$/i,h=parseInt;function _(p){if(typeof p=="number")return p;if(n(p))return u;if(t(p)){var m=typeof p.valueOf=="function"?p.valueOf():p;p=t(m)?m+"":m}if(typeof p!="string")return p===0?p:+p;p=e(p);var d=f.test(p);return d||c.test(p)?h(p.slice(2),d?2:8):s.test(p)?u:+p}return Eu=_,Eu}var Su,Dd;function Hi(){if(Dd)return Su;Dd=1;var e=Fd(),t=1/0,n=17976931348623157e292;function u(s){if(!s)return s===0?s:0;if(s=e(s),s===t||s===-t){var f=s<0?-1:1;return f*n}return s===s?s:0}return Su=u,Su}var Iu,Bd;function Gd(){if(Bd)return Iu;Bd=1;var e=Hi();function t(n){var u=e(n),s=u%1;return u===u?s?u-s:u:0}return Iu=t,Iu}var Ru,Ud;function zd(){if(Ud)return Ru;Ud=1;var e=Ki(),t=ze(),n=Gd(),u=Math.max;function s(f,c,h){var _=f==null?0:f.length;if(!_)return-1;var p=h==null?0:n(h);return p<0&&(p=u(_+p,0)),e(f,t(c,3),p)}return Ru=s,Ru}var Mu,Vd;function Kd(){if(Vd)return Mu;Vd=1;var e=Od(),t=zd(),n=e(t);return Mu=n,Mu}var Cu,$d;function en(){if($d)return Cu;$d=1;var e=Et();function t(n){var u=n==null?0:n.length;return u?e(n,1):[]}return Cu=t,Cu}var Tu,Wd;function Yd(){if(Wd)return Tu;Wd=1;var e=yt(),t=Ei(),n=tr();function u(s,f){return s==null?s:e(s,t(f),n)}return Tu=u,Tu}var Au,Qd;function Jd(){if(Qd)return Au;Qd=1;function e(t){var n=t==null?0:t.length;return n?t[n-1]:void 0}return Au=e,Au}var Ou,Xd;function Zd(){if(Xd)return Ou;Xd=1;var e=Pr(),t=wt(),n=ze();function u(s,f){var c={};return f=n(f,3),t(s,function(h,_,p){e(c,_,f(h,_,p))}),c}return Ou=u,Ou}var ju,Hd;function It(){if(Hd)return ju;Hd=1;var e=cr();function t(n,u,s){for(var f=-1,c=n.length;++fn}return ku=e,ku}var Nu,tg;function ig(){if(tg)return Nu;tg=1;var e=It(),t=rg(),n=ir();function u(s){return s&&s.length?e(s,n,t):void 0}return Nu=u,Nu}var Lu,ng;function rn(){if(ng)return Lu;ng=1;var e=Pr(),t=sr();function n(u,s,f){(f!==void 0&&!t(u[s],f)||f===void 0&&!(s in u))&&e(u,s,f)}return Lu=n,Lu}var Pu,og;function sg(){if(og)return Pu;og=1;var e=er(),t=Ur(),n=Le(),u="[object Object]",s=Function.prototype,f=Object.prototype,c=s.toString,h=f.hasOwnProperty,_=c.call(Object);function p(m){if(!n(m)||e(m)!=u)return!1;var d=t(m);if(d===null)return!0;var v=h.call(d,"constructor")&&d.constructor;return typeof v=="function"&&v instanceof v&&c.call(v)==_}return Pu=p,Pu}var Fu,ag;function tn(){if(ag)return Fu;ag=1;function e(t,n){if(!(n==="constructor"&&typeof t[n]=="function")&&n!="__proto__")return t[n]}return Fu=e,Fu}var Du,ug;function fg(){if(ug)return Du;ug=1;var e=vr(),t=tr();function n(u){return e(u,t(u))}return Du=n,Du}var Bu,cg;function hg(){if(cg)return Bu;cg=1;var e=rn(),t=hi(),n=yi(),u=li(),s=bi(),f=yr(),c=pe(),h=$i(),_=ur(),p=qr(),m=Me(),d=sg(),v=wr(),y=tn(),S=fg();function I(E,R,M,A,j,P,F){var L=y(E,M),B=y(R,M),U=F.get(B);if(U){e(E,M,U);return}var z=P?P(L,B,M+"",E,R,F):void 0,$=z===void 0;if($){var Z=c(B),ie=!Z&&_(B),le=!Z&&!ie&&v(B);z=B,Z||ie||le?c(L)?z=L:h(L)?z=u(L):ie?($=!1,z=t(B,!0)):le?($=!1,z=n(B,!0)):z=[]:d(B)||f(B)?(z=L,f(L)?z=S(L):(!m(L)||p(L))&&(z=s(B))):$=!1}$&&(F.set(B,z),j(z,B,A,P,F),F.delete(B)),e(E,M,z)}return Bu=I,Bu}var Gu,lg;function pg(){if(lg)return Gu;lg=1;var e=Lr(),t=rn(),n=yt(),u=hg(),s=Me(),f=tr(),c=tn();function h(_,p,m,d,v){_!==p&&n(p,function(y,S){if(v||(v=new e),s(y))u(_,p,S,m,h,d,v);else{var I=d?d(c(_,S),y,S+"",_,p,v):void 0;I===void 0&&(I=y),t(_,S,I)}},f)}return Gu=h,Gu}var Uu,_g;function mg(){if(_g)return Uu;_g=1;var e=Wr(),t=Yr();function n(u){return e(function(s,f){var c=-1,h=f.length,_=h>1?f[h-1]:void 0,p=h>2?f[2]:void 0;for(_=u.length>3&&typeof _=="function"?(h--,_):void 0,p&&t(f[0],f[1],p)&&(_=h<3?void 0:_,h=1),s=Object(s);++cu||h&&_&&m&&!p&&!d||f&&_&&m||!s&&m||!c)return 1;if(!f&&!h&&!d&&n=p)return m;var d=s[f];return m*(d=="desc"?-1:1)}}return n.index-u.index}return of=t,of}var sf,Wg;function Yg(){if(Wg)return sf;Wg=1;var e=Vr(),t=$r(),n=ze(),u=Bi(),s=Ug(),f=Br(),c=$g(),h=ir(),_=pe();function p(m,d,v){d.length?d=e(d,function(I){return _(I)?function(E){return t(E,I.length===1?I[0]:I)}:I}):d=[h];var y=-1;d=e(d,f(n));var S=u(m,function(I,E,R){var M=e(d,function(A){return A(I)});return{criteria:M,index:++y,value:I}});return s(S,function(I,E){return c(I,E,v)})}return sf=p,sf}var af,Qg;function Jg(){if(Qg)return af;Qg=1;var e=Et(),t=Yg(),n=Wr(),u=Yr(),s=n(function(f,c){if(f==null)return[];var h=c.length;return h>1&&u(f,c[0],c[1])?c=[]:h>2&&u(c[0],c[1],c[2])&&(c=[c[0]]),t(f,e(c,1),[])});return af=s,af}var uf,Xg;function Zg(){if(Xg)return uf;Xg=1;var e=ji(),t=0;function n(u){var s=++t;return e(u)+s}return uf=n,uf}var ff,Hg;function eq(){if(Hg)return ff;Hg=1;function e(t,n,u){for(var s=-1,f=t.length,c=n.length,h={};++s0;--E)if(I=m[E].dequeue(),I){v=v.concat(c(p,m,d,I,!0));break}}}return v}function c(p,m,d,v,y){var S=y?[]:void 0;return e.forEach(p.inEdges(v.v),function(I){var E=p.edge(I),R=p.node(I.v);y&&S.push({v:I.v,w:I.w}),R.out-=E,_(m,d,R)}),e.forEach(p.outEdges(v.v),function(I){var E=p.edge(I),R=I.w,M=p.node(R);M.in-=E,_(m,d,M)}),p.removeNode(v.v),S}function h(p,m){var d=new t,v=0,y=0;e.forEach(p.nodes(),function(E){d.setNode(E,{v:E,in:0,out:0})}),e.forEach(p.edges(),function(E){var R=d.edge(E.v,E.w)||0,M=m(E),A=R+M;d.setEdge(E.v,E.w,A),y=Math.max(y,d.node(E.v).out+=M),v=Math.max(v,d.node(E.w).in+=M)});var S=e.range(y+v+3).map(function(){return new n}),I=v+1;return e.forEach(d.nodes(),function(E){_(S,I,d.node(E))}),{graph:d,buckets:S,zeroIdx:I}}function _(p,m,d){d.out?d.in?p[d.out-d.in+m].enqueue(d):p[p.length-1].enqueue(d):p[0].enqueue(d)}return pf}var _f,uq;function fq(){if(uq)return _f;uq=1;var e=ae(),t=aq();_f={run:n,undo:s};function n(f){var c=f.graph().acyclicer==="greedy"?t(f,h(f)):u(f);e.forEach(c,function(_){var p=f.edge(_);f.removeEdge(_),p.forwardName=_.name,p.reversed=!0,f.setEdge(_.w,_.v,p,e.uniqueId("rev"))});function h(_){return function(p){return _.edge(p).weight}}}function u(f){var c=[],h={},_={};function p(m){e.has(_,m)||(_[m]=!0,h[m]=!0,e.forEach(f.outEdges(m),function(d){e.has(h,d.w)?c.push(d):p(d.w)}),delete h[m])}return e.forEach(f.nodes(),p),c}function s(f){e.forEach(f.edges(),function(c){var h=f.edge(c);if(h.reversed){f.removeEdge(c);var _=h.forwardName;delete h.reversed,delete h.forwardName,f.setEdge(c.w,c.v,h,_)}})}return _f}var mf,cq;function Ee(){if(cq)return mf;cq=1;var e=ae(),t=ke().Graph;mf={addDummyNode:n,simplify:u,asNonCompoundGraph:s,successorWeights:f,predecessorWeights:c,intersectRect:h,buildLayerMatrix:_,normalizeRanks:p,removeEmptyRanks:m,addBorderNode:d,maxRank:v,partition:y,time:S,notime:I};function n(E,R,M,A){var j;do j=e.uniqueId(A);while(E.hasNode(j));return M.dummy=R,E.setNode(j,M),j}function u(E){var R=new t().setGraph(E.graph());return e.forEach(E.nodes(),function(M){R.setNode(M,E.node(M))}),e.forEach(E.edges(),function(M){var A=R.edge(M.v,M.w)||{weight:0,minlen:1},j=E.edge(M);R.setEdge(M.v,M.w,{weight:A.weight+j.weight,minlen:Math.max(A.minlen,j.minlen)})}),R}function s(E){var R=new t({multigraph:E.isMultigraph()}).setGraph(E.graph());return e.forEach(E.nodes(),function(M){E.children(M).length||R.setNode(M,E.node(M))}),e.forEach(E.edges(),function(M){R.setEdge(M,E.edge(M))}),R}function f(E){var R=e.map(E.nodes(),function(M){var A={};return e.forEach(E.outEdges(M),function(j){A[j.w]=(A[j.w]||0)+E.edge(j).weight}),A});return e.zipObject(E.nodes(),R)}function c(E){var R=e.map(E.nodes(),function(M){var A={};return e.forEach(E.inEdges(M),function(j){A[j.v]=(A[j.v]||0)+E.edge(j).weight}),A});return e.zipObject(E.nodes(),R)}function h(E,R){var M=E.x,A=E.y,j=R.x-M,P=R.y-A,F=E.width/2,L=E.height/2;if(!j&&!P)throw new Error("Not possible to find intersection inside of the rectangle");var B,U;return Math.abs(P)*F>Math.abs(j)*L?(P<0&&(L=-L),B=L*j/P,U=L):(j<0&&(F=-F),B=F,U=F*P/j),{x:M+B,y:A+U}}function _(E){var R=e.map(e.range(v(E)+1),function(){return[]});return e.forEach(E.nodes(),function(M){var A=E.node(M),j=A.rank;e.isUndefined(j)||(R[j][A.order]=M)}),R}function p(E){var R=e.min(e.map(E.nodes(),function(M){return E.node(M).rank}));e.forEach(E.nodes(),function(M){var A=E.node(M);e.has(A,"rank")&&(A.rank-=R)})}function m(E){var R=e.min(e.map(E.nodes(),function(P){return E.node(P).rank})),M=[];e.forEach(E.nodes(),function(P){var F=E.node(P).rank-R;M[F]||(M[F]=[]),M[F].push(P)});var A=0,j=E.graph().nodeRankFactor;e.forEach(M,function(P,F){e.isUndefined(P)&&F%j!==0?--A:A&&e.forEach(P,function(L){E.node(L).rank+=A})})}function d(E,R,M,A){var j={width:0,height:0};return arguments.length>=4&&(j.rank=M,j.order=A),n(E,"border",j,R)}function v(E){return e.max(e.map(E.nodes(),function(R){var M=E.node(R).rank;if(!e.isUndefined(M))return M}))}function y(E,R){var M={lhs:[],rhs:[]};return e.forEach(E,function(A){R(A)?M.lhs.push(A):M.rhs.push(A)}),M}function S(E,R){var M=e.now();try{return R()}finally{console.log(E+" time: "+(e.now()-M)+"ms")}}function I(E,R){return R()}return mf}var df,hq;function lq(){if(hq)return df;hq=1;var e=ae(),t=Ee();df={run:n,undo:s};function n(f){f.graph().dummyChains=[],e.forEach(f.edges(),function(c){u(f,c)})}function u(f,c){var h=c.v,_=f.node(h).rank,p=c.w,m=f.node(p).rank,d=c.name,v=f.edge(c),y=v.labelRank;if(m!==_+1){f.removeEdge(c);var S,I,E;for(E=0,++_;_U.lim&&(z=U,$=!0);var Z=e.filter(j.edges(),function(ie){return $===M(A,A.node(ie.v),z)&&$!==M(A,A.node(ie.w),z)});return e.minBy(Z,function(ie){return n(j,ie)})}function I(A,j,P,F){var L=P.v,B=P.w;A.removeEdge(L,B),A.setEdge(F.v,F.w,{}),d(A),_(A,j),E(A,j)}function E(A,j){var P=e.find(A.nodes(),function(L){return!j.node(L).parent}),F=s(A,P);F=F.slice(1),e.forEach(F,function(L){var B=A.node(L).parent,U=j.edge(L,B),z=!1;U||(U=j.edge(B,L),z=!0),j.node(L).rank=j.node(B).rank+(z?U.minlen:-U.minlen)})}function R(A,j,P){return A.hasEdge(j,P)}function M(A,j,P){return P.low<=j.lim&&j.lim<=P.lim}return vf}var yf,gq;function qq(){if(gq)return yf;gq=1;var e=Zr(),t=e.longestPath,n=on(),u=dq();yf=s;function s(_){switch(_.graph().ranker){case"network-simplex":h(_);break;case"tight-tree":c(_);break;case"longest-path":f(_);break;default:h(_)}}var f=t;function c(_){t(_),n(_)}function h(_){u(_)}return yf}var wf,vq;function yq(){if(vq)return wf;vq=1;var e=ae();wf=t;function t(s){var f=u(s);e.forEach(s.graph().dummyChains,function(c){for(var h=s.node(c),_=h.edgeObj,p=n(s,f,_.v,_.w),m=p.path,d=p.lca,v=0,y=m[v],S=!0;c!==_.w;){if(h=s.node(c),S){for(;(y=m[v])!==d&&s.node(y).maxRankm||d>f[v].lim));for(y=v,v=h;(v=s.parent(v))!==y;)p.push(v);return{path:_.concat(p.reverse()),lca:y}}function u(s){var f={},c=0;function h(_){var p=c;e.forEach(s.children(_),h),f[_]={low:p,lim:c++}}return e.forEach(s.children(),h),f}return wf}var bf,wq;function bq(){if(wq)return bf;wq=1;var e=ae(),t=Ee();bf={run:n,cleanup:c};function n(h){var _=t.addDummyNode(h,"root",{},"_root"),p=s(h),m=e.max(e.values(p))-1,d=2*m+1;h.graph().nestingRoot=_,e.forEach(h.edges(),function(y){h.edge(y).minlen*=d});var v=f(h)+1;e.forEach(h.children(),function(y){u(h,_,d,v,m,p,y)}),h.graph().nodeRankFactor=d}function u(h,_,p,m,d,v,y){var S=h.children(y);if(!S.length){y!==_&&h.setEdge(_,y,{weight:0,minlen:p});return}var I=t.addBorderNode(h,"_bt"),E=t.addBorderNode(h,"_bb"),R=h.node(y);h.setParent(I,y),R.borderTop=I,h.setParent(E,y),R.borderBottom=E,e.forEach(S,function(M){u(h,_,p,m,d,v,M);var A=h.node(M),j=A.borderTop?A.borderTop:M,P=A.borderBottom?A.borderBottom:M,F=A.borderTop?m:2*m,L=j!==P?1:d-v[y]+1;h.setEdge(I,j,{weight:F,minlen:L,nestingEdge:!0}),h.setEdge(P,E,{weight:F,minlen:L,nestingEdge:!0})}),h.parent(y)||h.setEdge(_,I,{weight:0,minlen:d+v[y]})}function s(h){var _={};function p(m,d){var v=h.children(m);v&&v.length&&e.forEach(v,function(y){p(y,d+1)}),_[m]=d}return e.forEach(h.children(),function(m){p(m,1)}),_}function f(h){return e.reduce(h.edges(),function(_,p){return _+h.edge(p).weight},0)}function c(h){var _=h.graph();h.removeNode(_.nestingRoot),delete _.nestingRoot,e.forEach(h.edges(),function(p){var m=h.edge(p);m.nestingEdge&&h.removeEdge(p)})}return bf}var xf,xq;function Eq(){if(xq)return xf;xq=1;var e=ae(),t=Ee();xf=n;function n(s){function f(c){var h=s.children(c),_=s.node(c);if(h.length&&e.forEach(h,f),e.has(_,"minRank")){_.borderLeft=[],_.borderRight=[];for(var p=_.minRank,m=_.maxRank+1;p0;)y%2&&(S+=m[y+1]),y=y-1>>1,m[y]+=v.weight;d+=v.weight*S})),d}return If}var Rf,Aq;function Oq(){if(Aq)return Rf;Aq=1;var e=ae();Rf=t;function t(n,u){return e.map(u,function(s){var f=n.inEdges(s);if(f.length){var c=e.reduce(f,function(h,_){var p=n.edge(_),m=n.node(_.v);return{sum:h.sum+p.weight*m.order,weight:h.weight+p.weight}},{sum:0,weight:0});return{v:s,barycenter:c.sum/c.weight,weight:c.weight}}else return{v:s}})}return Rf}var Mf,jq;function kq(){if(jq)return Mf;jq=1;var e=ae();Mf=t;function t(s,f){var c={};e.forEach(s,function(_,p){var m=c[_.v]={indegree:0,in:[],out:[],vs:[_.v],i:p};e.isUndefined(_.barycenter)||(m.barycenter=_.barycenter,m.weight=_.weight)}),e.forEach(f.edges(),function(_){var p=c[_.v],m=c[_.w];!e.isUndefined(p)&&!e.isUndefined(m)&&(m.indegree++,p.out.push(c[_.w]))});var h=e.filter(c,function(_){return!_.indegree});return n(h)}function n(s){var f=[];function c(p){return function(m){m.merged||(e.isUndefined(m.barycenter)||e.isUndefined(p.barycenter)||m.barycenter>=p.barycenter)&&u(p,m)}}function h(p){return function(m){m.in.push(p),--m.indegree===0&&s.push(m)}}for(;s.length;){var _=s.pop();f.push(_),e.forEach(_.in.reverse(),c(_)),e.forEach(_.out,h(_))}return e.map(e.filter(f,function(p){return!p.merged}),function(p){return e.pick(p,["vs","i","barycenter","weight"])})}function u(s,f){var c=0,h=0;s.weight&&(c+=s.barycenter*s.weight,h+=s.weight),f.weight&&(c+=f.barycenter*f.weight,h+=f.weight),s.vs=f.vs.concat(s.vs),s.barycenter=c/h,s.weight=h,s.i=Math.min(f.i,s.i),f.merged=!0}return Mf}var Cf,Nq;function Lq(){if(Nq)return Cf;Nq=1;var e=ae(),t=Ee();Cf=n;function n(f,c){var h=t.partition(f,function(I){return e.has(I,"barycenter")}),_=h.lhs,p=e.sortBy(h.rhs,function(I){return-I.i}),m=[],d=0,v=0,y=0;_.sort(s(!!c)),y=u(m,p,y),e.forEach(_,function(I){y+=I.vs.length,m.push(I.vs),d+=I.barycenter*I.weight,v+=I.weight,y=u(m,p,y)});var S={vs:e.flatten(m,!0)};return v&&(S.barycenter=d/v,S.weight=v),S}function u(f,c,h){for(var _;c.length&&(_=e.last(c)).i<=h;)c.pop(),f.push(_.vs),h++;return h}function s(f){return function(c,h){return c.barycenterh.barycenter?1:f?h.i-c.i:c.i-h.i}}return Cf}var Tf,Pq;function Fq(){if(Pq)return Tf;Pq=1;var e=ae(),t=Oq(),n=kq(),u=Lq();Tf=s;function s(h,_,p,m){var d=h.children(_),v=h.node(_),y=v?v.borderLeft:void 0,S=v?v.borderRight:void 0,I={};y&&(d=e.filter(d,function(P){return P!==y&&P!==S}));var E=t(h,d);e.forEach(E,function(P){if(h.children(P.v).length){var F=s(h,P.v,p,m);I[P.v]=F,e.has(F,"barycenter")&&c(P,F)}});var R=n(E,p);f(R,I);var M=u(R,m);if(y&&(M.vs=e.flatten([y,M.vs,S],!0),h.predecessors(y).length)){var A=h.node(h.predecessors(y)[0]),j=h.node(h.predecessors(S)[0]);e.has(M,"barycenter")||(M.barycenter=0,M.weight=0),M.barycenter=(M.barycenter*M.weight+A.order+j.order)/(M.weight+2),M.weight+=2}return M}function f(h,_){e.forEach(h,function(p){p.vs=e.flatten(p.vs.map(function(m){return _[m]?_[m].vs:m}),!0)})}function c(h,_){e.isUndefined(h.barycenter)?(h.barycenter=_.barycenter,h.weight=_.weight):(h.barycenter=(h.barycenter*h.weight+_.barycenter*_.weight)/(h.weight+_.weight),h.weight+=_.weight)}return Tf}var Af,Dq;function Bq(){if(Dq)return Af;Dq=1;var e=ae(),t=ke().Graph;Af=n;function n(s,f,c){var h=u(s),_=new t({compound:!0}).setGraph({root:h}).setDefaultNodeLabel(function(p){return s.node(p)});return e.forEach(s.nodes(),function(p){var m=s.node(p),d=s.parent(p);(m.rank===f||m.minRank<=f&&f<=m.maxRank)&&(_.setNode(p),_.setParent(p,d||h),e.forEach(s[c](p),function(v){var y=v.v===p?v.w:v.v,S=_.edge(y,p),I=e.isUndefined(S)?0:S.weight;_.setEdge(y,p,{weight:s.edge(v).weight+I})}),e.has(m,"minRank")&&_.setNode(p,{borderLeft:m.borderLeft[f],borderRight:m.borderRight[f]}))}),_}function u(s){for(var f;s.hasNode(f=e.uniqueId("_root")););return f}return Af}var Of,Gq;function Uq(){if(Gq)return Of;Gq=1;var e=ae();Of=t;function t(n,u,s){var f={},c;e.forEach(s,function(h){for(var _=n.parent(h),p,m;_;){if(p=n.parent(_),p?(m=f[p],f[p]=_):(m=c,c=_),m&&m!==_){u.setEdge(m,_);return}_=p}})}return Of}var jf,zq;function Vq(){if(zq)return jf;zq=1;var e=ae(),t=Mq(),n=Tq(),u=Fq(),s=Bq(),f=Uq(),c=ke().Graph,h=Ee();jf=_;function _(v){var y=h.maxRank(v),S=p(v,e.range(1,y+1),"inEdges"),I=p(v,e.range(y-1,-1,-1),"outEdges"),E=t(v);d(v,E);for(var R=Number.POSITIVE_INFINITY,M,A=0,j=0;j<4;++A,++j){m(A%2?S:I,A%4>=2),E=h.buildLayerMatrix(v);var P=n(v,E);Pz)&&c(A,ie,$)})})}function P(F,L){var B=-1,U,z=0;return e.forEach(L,function($,Z){if(R.node($).dummy==="border"){var ie=R.predecessors($);ie.length&&(U=R.node(ie[0]).order,j(L,z,Z,B,U),z=Z,B=U)}j(L,z,L.length,U,F.length)}),L}return e.reduce(M,P),A}function f(R,M){if(R.node(M).dummy)return e.find(R.predecessors(M),function(A){return R.node(A).dummy})}function c(R,M,A){if(M>A){var j=M;M=A,A=j}var P=R[M];P||(R[M]=P={}),P[A]=!0}function h(R,M,A){if(M>A){var j=M;M=A,A=j}return e.has(R[M],A)}function _(R,M,A,j){var P={},F={},L={};return e.forEach(M,function(B){e.forEach(B,function(U,z){P[U]=U,F[U]=U,L[U]=z})}),e.forEach(M,function(B){var U=-1;e.forEach(B,function(z){var $=j(z);if($.length){$=e.sortBy($,function(ve){return L[ve]});for(var Z=($.length-1)/2,ie=Math.floor(Z),le=Math.ceil(Z);ie<=le;++ie){var me=$[ie];F[z]===z&&U({}));let n=At(this.options.nodeSize,0);this.model.forEachNode(y=>{let S=y._original,[I,E]=tt(n(S)),R={width:I,height:E};if(t.setNode(String(y.id),R),this.isCompound()){if(Ze(y.parentId))return;t.setParent(String(y.id),String(y.parentId))}});let{edgeLabelSize:u,edgeLabelOffset:s,edgeLabelPos:f,edgeMinLen:c,edgeWeight:h}=this.options,_=At(u,0,"edge"),p=$t(s,10,"edge"),m=typeof f=="string"?()=>f:Ar(f,["edge"]),d=$t(c,1,"edge"),v=$t(h,1,"edge");this.model.forEachEdge(y=>{let S=y._original,[I,E]=tt(_(S)),R={width:I,height:E,labelpos:m(S),labeloffset:p(S),minlen:d(S),weight:v(S)};t.setEdge(String(y.source),String(y.target),R,String(y.id))}),iv.layout(t),this.model.forEachNode(y=>{let S=t.node(String(y.id));S&&(y.x=S.x,y.y=S.y,y.size=[S.width,S.height])}),this.model.forEachEdge(y=>{let S=t.edge(String(y.source),String(y.target),String(y.id));if(!S)return;let{width:I,height:E,weight:R,minlen:M,labelpos:A,labeloffset:j,points:P}=S;y.labelSize=[I,E],y.weight=R,y.minLen=M,y.labelPos=A,y.labelOffset=j,y.points=P.map(sc)})})}isCompound(){return this.isCompoundGraph!==null?this.isCompoundGraph:nv(this.options.compound)?this.isCompoundGraph=this.options.compound:(this.isCompoundGraph=this.model.nodes().some(t=>!Ze(t.parentId)),this.isCompoundGraph)}};var _e={};var Gf={};Hf(Gf,{isAnyArray:()=>Qr});var ay=Object.prototype.toString;function Qr(e){let t=ay.call(e);return t.endsWith("Array]")&&!t.includes("Big")}var av=oi(Gf);var Uf={};Hf(Uf,{default:()=>uy});function uv(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};if(!Qr(e))throw new TypeError("input must be an array");if(e.length===0)throw new TypeError("input must not be empty");var n=t.fromIndex,u=n===void 0?0:n,s=t.toIndex,f=s===void 0?e.length:s;if(u<0||u>=e.length||!Number.isInteger(u))throw new Error("fromIndex must be a positive integer smaller than length");if(f<=u||f>e.length||!Number.isInteger(f))throw new Error("toIndex must be an integer greater than fromIndex and at most equal to length");for(var c=e[u],h=u+1;hc&&(c=e[h]);return c}function fv(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};if(!Qr(e))throw new TypeError("input must be an array");if(e.length===0)throw new TypeError("input must not be empty");var n=t.fromIndex,u=n===void 0?0:n,s=t.toIndex,f=s===void 0?e.length:s;if(u<0||u>=e.length||!Number.isInteger(u))throw new Error("fromIndex must be a positive integer smaller than length");if(f<=u||f>e.length||!Number.isInteger(f))throw new Error("toIndex must be an integer greater than fromIndex and at most equal to length");for(var c=e[u],h=u+1;h1&&arguments[1]!==void 0?arguments[1]:{};if(Qr(e)){if(e.length===0)throw new TypeError("input must not be empty")}else throw new TypeError("input must be an array");var n;if(t.output!==void 0){if(!Qr(t.output))throw new TypeError("output option must be an array if specified");n=t.output}else n=new Array(e.length);var u=fv(e),s=uv(e);if(u===s)throw new RangeError("minimum and maximum input values are equal. Cannot rescale a constant array");var f=t.min,c=f===void 0?t.autoMinMax?u:0:f,h=t.max,_=h===void 0?t.autoMinMax?s:1:h;if(c>=_)throw new RangeError("min option must be smaller than max option");for(var p=(_-c)/(s-u),m=0;m=0&&i?\` \${_(g,a-1)}\`:_(g,a)).padEnd(a)}function _(g,a){let i=g.toString();if(i.length<=a)return i;let r=g.toFixed(a);if(r.length>a&&(r=g.toFixed(Math.max(0,a-(r.length-a)))),r.length<=a&&!r.startsWith("0.000")&&!r.startsWith("-0.000"))return r;let o=g.toExponential(a);return o.length>a&&(o=g.toExponential(Math.max(0,a-(o.length-a)))),o.slice(0)}function p(g,a){g.prototype.add=function(r){return typeof r=="number"?this.addS(r):this.addM(r)},g.prototype.addS=function(r){for(let o=0;o>r);return this},g.prototype.signPropagatingRightShiftM=function(r){if(r=a.checkMatrix(r),this.rows!==r.rows||this.columns!==r.columns)throw new RangeError("Matrices dimensions must be equal");for(let o=0;o>r.get(o,l));return this},g.signPropagatingRightShift=function(r,o){return new a(r).signPropagatingRightShift(o)},g.prototype.rightShift=function(r){return typeof r=="number"?this.rightShiftS(r):this.rightShiftM(r)},g.prototype.rightShiftS=function(r){for(let o=0;o>>r);return this},g.prototype.rightShiftM=function(r){if(r=a.checkMatrix(r),this.rows!==r.rows||this.columns!==r.columns)throw new RangeError("Matrices dimensions must be equal");for(let o=0;o>>r.get(o,l));return this},g.rightShift=function(r,o){return new a(r).rightShift(o)},g.prototype.zeroFillRightShift=g.prototype.rightShift,g.prototype.zeroFillRightShiftS=g.prototype.rightShiftS,g.prototype.zeroFillRightShiftM=g.prototype.rightShiftM,g.zeroFillRightShift=g.rightShift,g.prototype.not=function(){for(let r=0;rr)throw new RangeError("Row index out of range")}function d(g,a,i){let r=i?g.columns:g.columns-1;if(a<0||a>r)throw new RangeError("Column index out of range")}function v(g,a){if(a.to1DArray&&(a=a.to1DArray()),a.length!==g.columns)throw new RangeError("vector size must be the same as the number of columns");return a}function y(g,a){if(a.to1DArray&&(a=a.to1DArray()),a.length!==g.rows)throw new RangeError("vector size must be the same as the number of rows");return a}function S(g,a){if(!e.isAnyArray(a))throw new TypeError("row indices must be an array");for(let i=0;i=g.rows)throw new RangeError("row indices are out of range")}function I(g,a){if(!e.isAnyArray(a))throw new TypeError("column indices must be an array");for(let i=0;i=g.columns)throw new RangeError("column indices are out of range")}function E(g,a,i,r,o){if(arguments.length!==5)throw new RangeError("expected 4 arguments");if(M("startRow",a),M("endRow",i),M("startColumn",r),M("endColumn",o),a>i||r>o||a<0||a>=g.rows||i<0||i>=g.rows||r<0||r>=g.columns||o<0||o>=g.columns)throw new RangeError("Submatrix indices are out of range")}function R(g,a=0){let i=[];for(let r=0;r=l)throw new RangeError("min must be smaller than max");let w=l-o,b=new N(a,i);for(let x=0;xr?(l=!0,r=i):(o=!1,l=!0);a++}return o}isReducedEchelonForm(){let a=0,i=0,r=-1,o=!0,l=!1;for(;ar?(l=!0,r=i):(o=!1,l=!0);for(let q=i+1;qa.get(o,r)&&(o=l);if(a.get(o,r)===0)r++;else{a.swapRows(i,o);let l=a.get(i,r);for(let q=r;q=0;)if(a.maxRow(o)===0)o--;else{let l=0,q=!1;for(;li[r]&&(i[r]=this.get(r,o));return i}case"column":{let i=new Array(this.columns).fill(Number.NEGATIVE_INFINITY);for(let r=0;ri[o]&&(i[o]=this.get(r,o));return i}case void 0:{let i=this.get(0,0);for(let r=0;ri&&(i=this.get(r,o));return i}default:throw new Error(\`invalid option: \${a}\`)}}maxIndex(){A(this);let a=this.get(0,0),i=[0,0];for(let r=0;ra&&(a=this.get(r,o),i[0]=r,i[1]=o);return i}min(a){if(this.isEmpty())return NaN;switch(a){case"row":{let i=new Array(this.rows).fill(Number.POSITIVE_INFINITY);for(let r=0;ri&&(i=this.get(a,r));return i}maxRowIndex(a){m(this,a),A(this);let i=this.get(a,0),r=[a,0];for(let o=1;oi&&(i=this.get(a,o),r[1]=o);return r}minRow(a){if(m(this,a),this.isEmpty())return NaN;let i=this.get(a,0);for(let r=1;ri&&(i=this.get(r,a));return i}maxColumnIndex(a){d(this,a),A(this);let i=this.get(0,a),r=[0,a];for(let o=1;oi&&(i=this.get(o,a),r[0]=o);return r}minColumn(a){if(d(this,a),this.isEmpty())return NaN;let i=this.get(0,a);for(let r=1;r=1;o/=2)(o&1)!==0&&(i=i.mmul(r)),r=r.mmul(r);return i}strassen2x2(a){a=N.checkMatrix(a);let i=new N(2,2),r=this.get(0,0),o=a.get(0,0),l=this.get(0,1),q=a.get(0,1),w=this.get(1,0),b=a.get(1,0),x=this.get(1,1),k=a.get(1,1),C=(r+x)*(o+k),G=(w+x)*o,X=r*(q-k),D=x*(b-o),K=(r+l)*k,H=(w-r)*(o+q),T=(l-x)*(b+k),J=C+D-K+T,re=X+K,ue=G+D,ce=C-G+X+H;return i.set(0,0,J),i.set(0,1,re),i.set(1,0,ue),i.set(1,1,ce),i}strassen3x3(a){a=N.checkMatrix(a);let i=new N(3,3),r=this.get(0,0),o=this.get(0,1),l=this.get(0,2),q=this.get(1,0),w=this.get(1,1),b=this.get(1,2),x=this.get(2,0),k=this.get(2,1),C=this.get(2,2),G=a.get(0,0),X=a.get(0,1),D=a.get(0,2),K=a.get(1,0),H=a.get(1,1),T=a.get(1,2),J=a.get(2,0),re=a.get(2,1),ue=a.get(2,2),ce=(r+o+l-q-w-k-C)*H,Se=(r-q)*(-X+H),ne=w*(-G+X+K-H-T-J+ue),oe=(-r+q+w)*(G-X+H),we=(q+w)*(-G+X),O=r*G,W=(-r+x+k)*(G-D+T),ee=(-r+x)*(D-T),Y=(x+k)*(-G+D),Ie=(r+o+l-w-b-x-k)*T,ye=k*(-G+D+K-H-T-J+re),xe=(-l+k+C)*(H+J-re),Re=(l-C)*(H-re),Ke=l*J,lr=(k+C)*(-J+re),Pe=(-l+w+b)*(T+J-ue),dr=(l-b)*(T-ue),Ir=(w+b)*(-J+ue),ge=o*K,$e=b*re,nr=q*D,or=x*X,Fe=C*ue,wv=O+Ke+ge,bv=ce+oe+we+O+xe+Ke+lr,xv=O+W+Y+Ie+Ke+Pe+Ir,Ev=Se+ne+oe+O+Ke+Pe+dr,Sv=Se+oe+we+O+$e,Iv=Ke+Pe+dr+Ir+nr,Rv=O+W+ee+ye+xe+Re+Ke,Mv=xe+Re+Ke+lr+or,Cv=O+W+ee+Y+Fe;return i.set(0,0,wv),i.set(0,1,bv),i.set(0,2,xv),i.set(1,0,Ev),i.set(1,1,Sv),i.set(1,2,Iv),i.set(2,0,Rv),i.set(2,1,Mv),i.set(2,2,Cv),i}mmulStrassen(a){a=N.checkMatrix(a);let i=this.clone(),r=i.rows,o=i.columns,l=a.rows,q=a.columns;o!==l&&console.warn(\`Multiplying \${r} x \${o} and \${l} x \${q} matrix: dimensions do not match.\`);function w(C,G,X){let D=C.rows,K=C.columns;if(D===G&&K===X)return C;{let H=se.zeros(G,X);return H=H.setSubMatrix(C,0,0),H}}let b=Math.max(r,l),x=Math.max(o,q);i=w(i,b,x),a=w(a,b,x);function k(C,G,X,D){if(X<=512||D<=512)return C.mmul(G);X%2===1&&D%2===1?(C=w(C,X+1,D+1),G=w(G,X+1,D+1)):X%2===1?(C=w(C,X+1,D),G=w(G,X+1,D)):D%2===1&&(C=w(C,X,D+1),G=w(G,X,D+1));let K=parseInt(C.rows/2,10),H=parseInt(C.columns/2,10),T=C.subMatrix(0,K-1,0,H-1),J=G.subMatrix(0,K-1,0,H-1),re=C.subMatrix(0,K-1,H,C.columns-1),ue=G.subMatrix(0,K-1,H,G.columns-1),ce=C.subMatrix(K,C.rows-1,0,H-1),Se=G.subMatrix(K,G.rows-1,0,H-1),ne=C.subMatrix(K,C.rows-1,H,C.columns-1),oe=G.subMatrix(K,G.rows-1,H,G.columns-1),we=k(se.add(T,ne),se.add(J,oe),K,H),O=k(se.add(ce,ne),J,K,H),W=k(T,se.sub(ue,oe),K,H),ee=k(ne,se.sub(Se,J),K,H),Y=k(se.add(T,re),oe,K,H),Ie=k(se.sub(ce,T),se.add(J,ue),K,H),ye=k(se.sub(re,ne),se.add(Se,oe),K,H),xe=se.add(we,ee);xe.sub(Y),xe.add(ye);let Re=se.add(W,Y),Ke=se.add(O,ee),lr=se.sub(we,O);lr.add(W),lr.add(Ie);let Pe=se.zeros(2*xe.rows,2*xe.columns);return Pe=Pe.setSubMatrix(xe,0,0),Pe=Pe.setSubMatrix(Re,xe.rows,0),Pe=Pe.setSubMatrix(Ke,0,xe.columns),Pe=Pe.setSubMatrix(lr,xe.rows,xe.columns),Pe.subMatrix(0,X-1,0,D-1)}return k(i,a,b,x)}scaleRows(a={}){if(typeof a!="object")throw new TypeError("options must be an object");let{min:i=0,max:r=1}=a;if(!Number.isFinite(i))throw new TypeError("min must be a number");if(!Number.isFinite(r))throw new TypeError("max must be a number");if(i>=r)throw new RangeError("min must be smaller than max");let o=new N(this.rows,this.columns);for(let l=0;l0&&t(q,{min:i,max:r,output:q}),o.setRow(l,q)}return o}scaleColumns(a={}){if(typeof a!="object")throw new TypeError("options must be an object");let{min:i=0,max:r=1}=a;if(!Number.isFinite(i))throw new TypeError("min must be a number");if(!Number.isFinite(r))throw new TypeError("max must be a number");if(i>=r)throw new RangeError("min must be smaller than max");let o=new N(this.rows,this.columns);for(let l=0;lr||i<0||i>=this.columns||r<0||r>=this.columns)throw new RangeError("Argument out of range");let o=new N(a.length,r-i+1);for(let l=0;l=this.rows)throw new RangeError(\`Row index out of range: \${a[l]}\`);o.set(l,q-i,this.get(a[l],q))}return o}subMatrixColumn(a,i,r){if(i===void 0&&(i=0),r===void 0&&(r=this.rows-1),i>r||i<0||i>=this.rows||r<0||r>=this.rows)throw new RangeError("Argument out of range");let o=new N(r-i+1,a.length);for(let l=0;l=this.columns)throw new RangeError(\`Column index out of range: \${a[l]}\`);o.set(q-i,l,this.get(q,a[l]))}return o}setSubMatrix(a,i,r){if(a=N.checkMatrix(a),a.isEmpty())return this;let o=i+a.rows-1,l=r+a.columns-1;E(this,i,o,r,l);for(let q=0;qtypeof a=="number")}se.random=se.rand,se.randomInt=se.randInt,se.diagonal=se.diag,se.prototype.diagonal=se.prototype.diag,se.identity=se.eye,se.prototype.negate=se.prototype.neg,se.prototype.tensorProduct=se.prototype.kroneckerProduct;let zt=class zt extends se{constructor(i,r){super();hn(this,Ct);ec(this,"data");if(zt.isMatrix(i))ln(this,Ct,zf).call(this,i.rows,i.columns),zt.copy(i,this);else if(Number.isInteger(i)&&i>=0)ln(this,Ct,zf).call(this,i,r);else if(e.isAnyArray(i)){let o=i;if(i=o.length,r=i?o[0].length:0,typeof r!="number")throw new TypeError("Data must be a 2D array with at least one element");this.data=[];for(let l=0;l"u"&&(r=i,i=this.columns),d(this,i,!0),r=y(this,r);for(let o=0;o=0)for(let o=0;o=0)Kt(this,Je,new N(i,i));else if(Kt(this,Je,new N(i)),!this.isSymmetric())throw new TypeError("not symmetric data")}get size(){return pr(this,Je).size}get rows(){return pr(this,Je).rows}get columns(){return pr(this,Je).columns}get diagonalSize(){return this.rows}static isSymmetricMatrix(i){return N.isMatrix(i)&&i.klassType==="SymmetricMatrix"}static zeros(i){return new this(i)}static ones(i){return new this(i).fill(1)}clone(){let i=new Vt(this.diagonalSize);for(let[r,o,l]of this.upperRightEntries())i.set(r,o,l);return i}toMatrix(){return new N(this)}get(i,r){return pr(this,Je).get(i,r)}set(i,r,o){return pr(this,Je).set(i,r,o),pr(this,Je).set(r,i,o),this}removeCross(i){return pr(this,Je).removeRow(i),pr(this,Je).removeColumn(i),this}addCross(i,r){r===void 0&&(r=i,i=this.diagonalSize);let o=r.slice();return o.splice(i,1),pr(this,Je).addRow(i,o),pr(this,Je).addColumn(i,r),this}applyMask(i){if(i.length!==this.diagonalSize)throw new RangeError("Mask size do not match with matrix size");let r=[];for(let[o,l]of i.entries())l||r.push(o);r.reverse();for(let o of r)this.removeCross(o);return this}toCompact(){let{diagonalSize:i}=this,r=new Array(i*(i+1)/2);for(let o=0,l=0,q=0;q=i&&(o=++l);return r}static fromCompact(i){let r=i.length,o=(Math.sqrt(8*r+1)-1)/2;if(!Number.isInteger(o))throw new TypeError(\`This array is not a compact representation of a Symmetric Matrix, \${JSON.stringify(i)}\`);let l=new Vt(o);for(let q=0,w=0,b=0;b=o&&(q=++w);return l}*upperRightEntries(){for(let i=0,r=0;i=this.diagonalSize&&(r=++i)}}*upperRightValues(){for(let i=0,r=0;i=this.diagonalSize&&(r=++i)}};Je=new WeakMap;let Q=Vt;Q.prototype.klassType="SymmetricMatrix";class te extends Q{static isDistanceMatrix(a){return Q.isSymmetricMatrix(a)&&a.klassSubType==="DistanceMatrix"}constructor(a){if(super(a),!this.isDistance())throw new TypeError("Provided arguments do no produce a distance matrix")}set(a,i,r){return a===i&&(r=0),super.set(a,i,r)}addCross(a,i){return i===void 0&&(i=a,a=this.diagonalSize),i=i.slice(),i[a]=0,super.addCross(a,i)}toSymmetricMatrix(){return new Q(this)}clone(){let a=new te(this.diagonalSize);for(let[i,r,o]of this.upperRightEntries())i!==r&&a.set(i,r,o);return a}toCompact(){let{diagonalSize:a}=this,i=(a-1)*a/2,r=new Array(i);for(let o=1,l=0,q=0;q=a&&(o=++l+1);return r}static fromCompact(a){let i=a.length;if(i===0)return new this(0);let r=(Math.sqrt(8*i+1)+1)/2;if(!Number.isInteger(r))throw new TypeError(\`This array is not a compact representation of a DistanceMatrix, \${JSON.stringify(a)}\`);let o=new this(r);for(let l=1,q=0,w=0;w=r&&(l=++q+1);return o}}te.prototype.klassSubType="DistanceMatrix";class fe extends se{constructor(a,i,r){super(),this.matrix=a,this.rows=i,this.columns=r}}class be extends fe{constructor(a,i){d(a,i),super(a,a.rows,1),this.column=i}set(a,i,r){return this.matrix.set(a,this.column,r),this}get(a){return this.matrix.get(a,this.column)}}class Te extends fe{constructor(a,i){I(a,i),super(a,a.rows,i.length),this.columnIndices=i}set(a,i,r){return this.matrix.set(a,this.columnIndices[i],r),this}get(a,i){return this.matrix.get(a,this.columnIndices[i])}}class Ye extends fe{constructor(a){super(a,a.rows,a.columns)}set(a,i,r){return this.matrix.set(a,this.columns-i-1,r),this}get(a,i){return this.matrix.get(a,this.columns-i-1)}}class et extends fe{constructor(a){super(a,a.rows,a.columns)}set(a,i,r){return this.matrix.set(this.rows-a-1,i,r),this}get(a,i){return this.matrix.get(this.rows-a-1,i)}}class Qe extends fe{constructor(a,i){m(a,i),super(a,1,a.columns),this.row=i}set(a,i,r){return this.matrix.set(this.row,i,r),this}get(a,i){return this.matrix.get(this.row,i)}}class De extends fe{constructor(a,i){S(a,i),super(a,i.length,a.columns),this.rowIndices=i}set(a,i,r){return this.matrix.set(this.rowIndices[a],i,r),this}get(a,i){return this.matrix.get(this.rowIndices[a],i)}}class de extends fe{constructor(a,i,r){S(a,i),I(a,r),super(a,i.length,r.length),this.rowIndices=i,this.columnIndices=r}set(a,i,r){return this.matrix.set(this.rowIndices[a],this.columnIndices[i],r),this}get(a,i){return this.matrix.get(this.rowIndices[a],this.columnIndices[i])}}class xr extends fe{constructor(a,i,r,o,l){E(a,i,r,o,l),super(a,r-i+1,l-o+1),this.startRow=i,this.startColumn=o}set(a,i,r){return this.matrix.set(this.startRow+a,this.startColumn+i,r),this}get(a,i){return this.matrix.get(this.startRow+a,this.startColumn+i)}}class qe extends fe{constructor(a){super(a,a.columns,a.rows)}set(a,i,r){return this.matrix.set(i,a,r),this}get(a,i){return this.matrix.get(i,a)}}class Er extends se{constructor(a,i={}){let{rows:r=1}=i;if(a.length%r!==0)throw new Error("the data length is not divisible by the number of rows");super(),this.rows=r,this.columns=a.length/r,this.data=a}set(a,i,r){let o=this._calculateIndex(a,i);return this.data[o]=r,this}get(a,i){let r=this._calculateIndex(a,i);return this.data[r]}_calculateIndex(a,i){return a*this.columns+i}}class Ne extends se{constructor(a){super(),this.data=a,this.rows=a.length,this.columns=a[0].length}set(a,i,r){return this.data[a][i]=r,this}get(a,i){return this.data[a][i]}}function un(g,a){if(e.isAnyArray(g))return g[0]&&e.isAnyArray(g[0])?new Ne(g):new Er(g,a);throw new Error("the argument is not an array")}class Sr{constructor(a){a=Ne.checkMatrix(a);let i=a.clone(),r=i.rows,o=i.columns,l=new Float64Array(r),q=1,w,b,x,k,C,G,X,D,K;for(w=0;wMath.abs(D[k])&&(k=w);if(k!==b){for(x=0;x=0;x--){for(b=0;bq?o.set(l,q,a.get(l,q)):l===q?o.set(l,q,1):o.set(l,q,0);return o}get upperTriangularMatrix(){let a=this.LU,i=a.rows,r=a.columns,o=new N(i,r);for(let l=0;lMath.abs(a)?(i=a/g,Math.abs(g)*Math.sqrt(1+i*i)):a!==0?(i=g/a,Math.abs(a)*Math.sqrt(1+i*i)):0}class Ge{constructor(a){a=Ne.checkMatrix(a);let i=a.clone(),r=a.rows,o=a.columns,l=new Float64Array(o),q,w,b,x;for(b=0;b=0;x--){for(b=0;b=0;w--){for(l=0;l=0;O--)if(D[O]!==0){for(let W=O+1;W=0;O--){if(O0;){let O,W;for(O=ne-2;O>=-1&&O!==-1;O--){let ee=Number.MIN_VALUE+we*Math.abs(D[O]+Math.abs(D[O+1]));if(Math.abs(T[O])<=ee||Number.isNaN(T[O])){T[O]=0;break}}if(O===ne-2)W=4;else{let ee;for(ee=ne-1;ee>=O&&ee!==O;ee--){let Y=(ee!==ne?Math.abs(T[ee]):0)+(ee!==O+1?Math.abs(T[ee-1]):0);if(Math.abs(D[ee])<=we*Y){D[ee]=0;break}}ee===O?W=3:ee===ne-1?W=1:(W=2,O=ee)}switch(O++,W){case 1:{let ee=T[ne-2];T[ne-2]=0;for(let Y=ne-2;Y>=O;Y--){let Ie=Be(D[Y],ee),ye=D[Y]/Ie,xe=ee/Ie;if(D[Y]=Ie,Y!==O&&(ee=-xe*T[Y-1],T[Y-1]=ye*T[Y-1]),x)for(let Re=0;Re=D[O+1]);){let ee=D[O];if(D[O]=D[O+1],D[O+1]=ee,x&&Oi&&l.set(k,C,a.get(k,C)/this.s[C]);let q=this.U,w=q.rows,b=q.columns,x=new N(r,w);for(let k=0;ka&&i++;return i}get diagonal(){return Array.from(this.s)}get threshold(){return Number.EPSILON/2*Math.max(this.m,this.n)*this.s[0]}get leftSingularVectors(){return this.U}get rightSingularVectors(){return this.V}get diagonalMatrix(){return N.diag(this.s)}}function rt(g,a=!1){return g=Ne.checkMatrix(g),a?new hr(g).inverse():Ft(g,N.eye(g.rows))}function Ft(g,a,i=!1){return g=Ne.checkMatrix(g),a=Ne.checkMatrix(a),i?new hr(g).solve(a):g.isSquare()?new Sr(g).solve(a):new Ge(g).solve(a)}function Jr(g){if(g=N.checkMatrix(g),g.isSquare()){if(g.columns===0)return 1;let a,i,r,o;if(g.columns===2)return a=g.get(0,0),i=g.get(0,1),r=g.get(1,0),o=g.get(1,1),a*o-i*r;if(g.columns===3){let l,q,w;return l=new de(g,[1,2],[1,2]),q=new de(g,[1,2],[0,2]),w=new de(g,[1,2],[0,1]),a=g.get(0,0),i=g.get(0,1),r=g.get(0,2),a*Jr(l)-i*Jr(q)+r*Jr(w)}else return new Sr(g).determinant}else throw Error("determinant can only be calculated for a square matrix")}function Cr(g,a){let i=[];for(let r=0;ro)return new Array(a.rows+1).fill(0);{let l=a.addRow(i,[0]);for(let q=0;qa?l[q]=1/l[q]:l[q]=0;return o.mmul(N.diag(l).mmul(r.transpose()))}function Gt(g,a=g,i={}){g=new N(g);let r=!1;if(typeof a=="object"&&!N.isMatrix(a)&&!e.isAnyArray(a)?(i=a,a=g,r=!0):a=new N(a),g.rows!==a.rows)throw new TypeError("Both matrices must have the same number of rows");let{center:o=!0}=i;o&&(g=g.center("column"),r||(a=a.center("column")));let l=g.transpose().mmul(a);for(let q=0;q0?o.set(l,l+1,i[l]):i[l]<0&&o.set(l,l-1,i[l])}return o}}function gv(g,a,i,r){let o,l,q,w,b,x,k,C;for(b=0;b0;w--){for(C=0,q=0,x=0;x0&&(l=-l),a[w]=C*l,q=q-o*l,i[w-1]=o-l,b=0;bx)do{for(o=i[x],C=(i[x+1]-o)/(2*a[x]),G=Be(C,1),C<0&&(G=-G),i[x]=a[x]/(C+G),i[x+1]=a[x]*(C+G),X=i[x+1],l=o-i[x],q=x+2;q=x;q--)for(H=K,K=D,re=J,o=D*a[q],l=D*C,G=Be(C,a[q]),a[q+1]=J*G,J=a[q]/G,D=C/G,C=D*i[q]-J*o,i[q+1]=l+J*(D*o+J*i[q]),b=0;bSe*ce);i[x]=i[x]+ue,a[x]=0}for(q=0;q=C;x--)i[x]=a.get(x,C-1)/G,b+=i[x]*i[x];for(w=Math.sqrt(b),i[C]>0&&(w=-w),b=b-i[C]*w,i[C]=i[C]-w,k=C;k=C;x--)q+=i[x]*a.get(x,k);for(q=q/b,x=C;x<=l;x++)a.set(x,k,a.get(x,k)-q*i[x])}for(x=0;x<=l;x++){for(q=0,k=l;k>=C;k--)q+=i[k]*a.get(x,k);for(q=q/b,k=C;k<=l;k++)a.set(x,k,a.get(x,k)-q*i[k])}i[C]=G*i[C],a.set(C,C-1,G*w)}}for(x=0;x=o+1;C--)if(a.get(C,C-1)!==0){for(x=C+1;x<=l;x++)i[x]=a.get(x,C-1);for(k=C;k<=l;k++){for(w=0,x=C;x<=l;x++)w+=i[x]*r.get(x,k);for(w=w/i[C]/a.get(C,C-1),x=C;x<=l;x++)r.set(x,k,r.get(x,k)+w*i[x])}}}function yv(g,a,i,r,o){let l=g-1,q=0,w=g-1,b=Number.EPSILON,x=0,k=0,C=0,G=0,X=0,D=0,K=0,H=0,T,J,re,ue,ce,Se,ne,oe,we,O,W,ee,Y,Ie,ye;for(T=0;Tw)&&(i[T]=o.get(T,T),a[T]=0),J=Math.max(T-1,0);J=q;){for(ue=l;ue>q&&(D=Math.abs(o.get(ue-1,ue-1))+Math.abs(o.get(ue,ue)),D===0&&(D=k),!(Math.abs(o.get(ue,ue-1))=0){for(K=C>=0?C+K:C-K,i[l-1]=oe+K,i[l]=i[l-1],K!==0&&(i[l]=oe-ne/K),a[l-1]=0,a[l]=0,oe=o.get(l,l-1),D=Math.abs(oe)+Math.abs(K),C=oe/D,G=K/D,X=Math.sqrt(C*C+G*G),C=C/X,G=G/X,J=l-1;J0)){for(D=Math.sqrt(D),we=ue&&(K=o.get(ce,ce),X=oe-K,D=we-K,C=(X*D-ne)/o.get(ce+1,ce)+o.get(ce,ce+1),G=o.get(ce+1,ce+1)-K-X-D,X=o.get(ce+2,ce+1),D=Math.abs(C)+Math.abs(G)+Math.abs(X),C=C/D,G=G/D,X=X/D,!(ce===ue||Math.abs(o.get(ce,ce-1))*(Math.abs(G)+Math.abs(X))ce+2&&o.set(T,T-3,0);for(re=ce;re<=l-1&&(Ie=re!==l-1,re!==ce&&(C=o.get(re,re-1),G=o.get(re+1,re-1),X=Ie?o.get(re+2,re-1):0,oe=Math.abs(C)+Math.abs(G)+Math.abs(X),oe!==0&&(C=C/oe,G=G/oe,X=X/oe)),oe!==0);re++)if(D=Math.sqrt(C*C+G*G+X*X),C<0&&(D=-D),D!==0){for(re!==ce?o.set(re,re-1,-D*oe):ue!==ce&&o.set(re,re-1,-o.get(re,re-1)),C=C+D,oe=C/D,we=G/D,K=X/D,G=G/C,X=X/C,J=re;J=0;l--)if(C=i[l],G=a[l],G===0)for(ue=l,o.set(l,l,1),T=l-1;T>=0;T--){for(ne=o.get(T,T)-C,X=0,J=ue;J<=l;J++)X=X+o.get(T,J)*o.get(J,l);if(a[T]<0)K=ne,D=X;else if(ue=T,a[T]===0?o.set(T,l,ne!==0?-X/ne:-X/(b*k)):(oe=o.get(T,T+1),we=o.get(T+1,T),G=(i[T]-C)*(i[T]-C)+a[T]*a[T],Se=(oe*D-K*X)/G,o.set(T,l,Se),o.set(T+1,l,Math.abs(oe)>Math.abs(K)?(-X-ne*Se)/oe:(-D-we*Se)/K)),Se=Math.abs(o.get(T,l)),b*Se*Se>1)for(J=T;J<=l;J++)o.set(J,l,o.get(J,l)/Se)}else if(G<0)for(ue=l-1,Math.abs(o.get(l,l-1))>Math.abs(o.get(l-1,l))?(o.set(l-1,l-1,G/o.get(l,l-1)),o.set(l-1,l,-(o.get(l,l)-C)/o.get(l,l-1))):(ye=Ut(0,-o.get(l-1,l),o.get(l-1,l-1)-C,G),o.set(l-1,l-1,ye[0]),o.set(l-1,l,ye[1])),o.set(l,l-1,0),o.set(l,l,1),T=l-2;T>=0;T--){for(O=0,W=0,J=ue;J<=l;J++)O=O+o.get(T,J)*o.get(J,l-1),W=W+o.get(T,J)*o.get(J,l);if(ne=o.get(T,T)-C,a[T]<0)K=ne,X=O,D=W;else if(ue=T,a[T]===0?(ye=Ut(-O,-W,ne,G),o.set(T,l-1,ye[0]),o.set(T,l,ye[1])):(oe=o.get(T,T+1),we=o.get(T+1,T),ee=(i[T]-C)*(i[T]-C)+a[T]*a[T]-G*G,Y=(i[T]-C)*2*G,ee===0&&Y===0&&(ee=b*k*(Math.abs(ne)+Math.abs(G)+Math.abs(oe)+Math.abs(we)+Math.abs(K))),ye=Ut(oe*X-K*O+G*W,oe*D-K*W-G*O,ee,Y),o.set(T,l-1,ye[0]),o.set(T,l,ye[1]),Math.abs(oe)>Math.abs(K)+Math.abs(G)?(o.set(T+1,l-1,(-O-ne*o.get(T,l-1)+G*o.get(T,l))/oe),o.set(T+1,l,(-W-ne*o.get(T,l)-G*o.get(T,l-1))/oe)):(ye=Ut(-X-we*o.get(T,l-1),-D-we*o.get(T,l),K,G),o.set(T+1,l-1,ye[0]),o.set(T+1,l,ye[1]))),Se=Math.max(Math.abs(o.get(T,l-1)),Math.abs(o.get(T,l))),b*Se*Se>1)for(J=T;J<=l;J++)o.set(J,l-1,o.get(J,l-1)/Se),o.set(J,l,o.get(J,l)/Se)}for(T=0;Tw)for(J=T;J=q;J--)for(T=q;T<=w;T++){for(K=0,re=q;re<=Math.min(J,w);re++)K=K+r.get(T,re)*o.get(re,J);r.set(T,J,K)}}}function Ut(g,a,i,r){let o,l;return Math.abs(i)>Math.abs(r)?(o=r/i,l=i+o*r,[(g+o*a)/l,(a-o*g)/l]):(o=i/r,l=r+o*i,[(o*g+a)/l,(o*a-g)/l])}class Qf{constructor(a){if(a=Ne.checkMatrix(a),!a.isSymmetric())throw new Error("Matrix is not symmetric");let i=a,r=i.rows,o=new N(r,r),l=!0,q,w,b;for(w=0;w0),o.set(w,w,Math.sqrt(Math.max(x,0))),b=w+1;b=0;b--)for(w=0;wq;X++)C=a.transpose().mmul(w).div(w.transpose().mmul(w).get(0,0)),C=C.div(C.norm()),x=a.mmul(C).div(C.transpose().mmul(C).get(0,0)),X>0&&(b=x.clone().sub(G).pow(2).sum()),G=x.clone(),r?(k=r.transpose().mmul(x).div(x.transpose().mmul(x).get(0,0)),k=k.div(k.norm()),w=r.mmul(k).div(k.transpose().mmul(k).get(0,0))):w=x;if(r){let X=a.transpose().mmul(x).div(x.transpose().mmul(x).get(0,0));X=X.div(X.norm());let D=a.clone().sub(x.clone().mmul(X.transpose())),K=w.transpose().mmul(x).div(x.transpose().mmul(x).get(0,0)),H=r.clone().sub(x.clone().mulS(K.get(0,0)).mmul(k.transpose()));this.t=x,this.p=X.transpose(),this.w=C.transpose(),this.q=k,this.u=w,this.s=x.transpose().mmul(x),this.xResidual=D,this.yResidual=H,this.betas=K}else this.w=C.transpose(),this.s=x.transpose().mmul(x).sqrt(),o?this.t=x.clone().div(this.s.get(0,0)):this.t=x,this.xResidual=a.sub(x.mmul(C.transpose()))}}return _e.AbstractMatrix=se,_e.CHO=Qf,_e.CholeskyDecomposition=Qf,_e.DistanceMatrix=te,_e.EVD=mr,_e.EigenvalueDecomposition=mr,_e.LU=Sr,_e.LuDecomposition=Sr,_e.Matrix=N,_e.MatrixColumnSelectionView=Te,_e.MatrixColumnView=be,_e.MatrixFlipColumnView=Ye,_e.MatrixFlipRowView=et,_e.MatrixRowSelectionView=De,_e.MatrixRowView=Qe,_e.MatrixSelectionView=de,_e.MatrixSubView=xr,_e.MatrixTransposeView=qe,_e.NIPALS=Jf,_e.Nipals=Jf,_e.QR=Ge,_e.QrDecomposition=Ge,_e.SVD=hr,_e.SingularValueDecomposition=hr,_e.SymmetricMatrix=Q,_e.WrapperMatrix1D=Er,_e.WrapperMatrix2D=Ne,_e.correlation=_r,_e.covariance=Gt,_e.default=N,_e.determinant=Jr,_e.inverse=rt,_e.linearDependencies=Bt,_e.pseudoInverse=fn,_e.solve=Ft,_e.wrap=un,_e}var Nt=lv(),Vf=ni(Nt);var Kf=Nt.Matrix,pv=Nt.SingularValueDecomposition;Vf.Matrix?Vf.Matrix:Nt.Matrix;var sn=(e,t)=>{let n=e.nodeCount(),u=Array.from({length:n},()=>[]),s={},f=0;return e.forEachNode(c=>{s[c.id]=f++}),e.forEachEdge(c=>{let h=s[c.source],_=s[c.target];h==null||_==null||(u[h].push(_),t||u[_].push(h))}),u},_v=(e,t)=>{let n=e.length,u=new Array(n);for(let s=0;snew Array(t).fill(1/0));for(let u=0;u0&&(this.data[0]=n,this.bubbleDown(0)),t}empty(){return this.data.length===0}bubbleUp(t){let n=this.data;for(;t>0;){let u=t-1>>1;if(n[u][0]<=n[t][0])break;[n[u],n[t]]=[n[t],n[u]],t=u}}bubbleDown(t){let n=this.data,u=n.length;for(;;){let s=t*2+1,f=t*2+2,c=t;if(s{let m=h[_++];p.x=m[0]+n[0],p.y=m[1]+n[1]})})}},cy=e=>{let t=Number.NEGATIVE_INFINITY,n=[],u=e.length;for(let s=0;s{try{let u=e.length,s=new Kf(u,u);for(let y=0;y{let n=Object.assign(Object.assign({},mv),t),{maxIteration:u,width:s,k:f,speed:c=mv.speed,strictRadial:h,focusNode:_,radiiMap:p,nodeSizeFunc:m}=n,d=f*.002,v=new Map,y=s/10;for(let S=0;S{v.set(E.id,{x:0,y:0})}),hy(e,v,f,p,m),!(ly(e,v,c,h,_,y,p){let f=0;e.forEachNode(c=>{let h=0;e.forEachNode(_=>{if(h<=f){h++;return}if(c.id===_.id||u.get(c.id)!==u.get(_.id))return;let p=c.x-_.x,m=c.y-_.y,d=Math.sqrt(p*p+m*m);if(d===0){d=1;let S=f>h?1:-1;p=.01*S,m=.01*S}let v=Math.max(...s(c._original)),y=Math.max(...s(_._original));if(d{u&&e.forEachNode(p=>{let m=p.x-s.x,d=p.y-s.y,v=Math.sqrt(m*m+d*d),y=d/v,S=-m/v,I=t.get(p.id),E=Math.sqrt(I.x*I.x+I.y*I.y),R=Math.acos((y*I.x+S*I.y)/E);R>Math.PI/2&&(R-=Math.PI/2,y*=-1,S*=-1);let M=Math.cos(R)*E;t.set(p.id,{x:y*M,y:S*M})});let h=0,_=0;return e.forEachNode(p=>{if(p.id===s.id)return;let m=t.get(p.id),d=Math.sqrt(m.x*m.x+m.y*m.y);if(d>0){let v=Math.min(f*(n/800),d);if(p.x+=m.x/d*v,p.y+=m.y/d*v,u){let y=p.x-s.x,S=p.y-s.y,I=Math.sqrt(y*y+S*S);y=y/I*c.get(p.id),S=S/I*c.get(p.id),p.x=s.x+y,p.y=s.y+S}h+=v,_++}}),_>0?h/_:0};var Hr={focusNode:null,linkDistance:50,maxIteration:1e3,maxPreventOverlapIteration:200,preventOverlap:!1,sortStrength:10,strictRadial:!0,unitRadius:null,nodeSize:10,nodeSpacing:0},Pt=class extends gr{constructor(){super(...arguments),this.id="radial"}getDefaultOptions(){return Hr}layout(){return He(this,void 0,void 0,function*(){let{width:t,height:n,center:u}=ot(this.options),s=this.model.nodeCount();if(!s||s===1)return nt(this.model,u);let{focusNode:f,linkDistance:c=Hr.linkDistance,maxIteration:h=Hr.maxIteration,maxPreventOverlapIteration:_=Hr.maxPreventOverlapIteration,nodeSize:p,nodeSpacing:m,preventOverlap:d,sortBy:v,sortStrength:y=Hr.sortStrength,strictRadial:S,unitRadius:I}=this.options,E=f&&this.model.node(f)||this.model.firstNode(),R=this.model.nodeIndexOf(E.id),M=sn(this.model,!1),A=an(M),j=dy(A,R);my(A,R,j+1);let P=A[R],F=(t-u[0]>u[0]?u[0]:t-u[0])||t/2,L=(n-u[1]>u[1]?u[1]:n-u[1])||n/2,B=Math.min(F,L),U=Math.max(...P),z=[],$=new Map,Z=I??B/U;P.forEach((Ve,We)=>{let Rr=Ve*Z;z.push(Rr),$.set(this.model.nodeAt(We).id,Rr)});let ie=py(this.model,A,c,z,Z,v,y),le=Yf(ie,2,c),me=le[R],ve=0;if(this.model.forEachNode(Ve=>{let We=le[ve];Ve.x=We[0]-me[0],Ve.y=We[1]-me[1],ve++}),this.run(h,ie,z,R),this.model.forEachNode(Ve=>{Ve.x+=u[0],Ve.y+=u[1]}),d){let We={nodeSizeFunc:Wt(p,m,Hr.nodeSize,Hr.nodeSpacing),radiiMap:$,width:t,strictRadial:!!S,focusNode:E,maxIteration:_,k:s/4.5};dv(this.model,We)}})}run(t,n,u,s){let f=_y(n),c=this.model.nodeCount(),h=this.model.nodes(),_=new Float64Array(c),p=new Float64Array(c);for(let m=0;m{let h=t.length,_=new Array(h),p=new Array(h);for(let S=0;S{let t=e.length,n=e[0].length,u=[];for(let s=0;s{let u=e.length;for(let s=0;s{let n=e[t],u=0;for(let s=0;s{let{type:t,options:n,nodes:u,edges:s}=e.data,f=gy[t];if(!f){self.postMessage({error:\`Unknown layout type: \${t}\`});return}let c=new f(n);try{await c.execute({nodes:u,edges:s});let h=[];c.forEachNode(({id:_,x:p,y:m})=>h.push({id:_,x:p,y:m})),self.postMessage({positions:h})}catch(h){self.postMessage({error:h&&h.message?h.message:String(h)})}finally{c.destroy()}};})(); +` diff --git a/src/lib/purify.esm.mjs b/src/lib/purify.esm.mjs index 63410bf..b81598c 100644 --- a/src/lib/purify.esm.mjs +++ b/src/lib/purify.esm.mjs @@ -1,21 +1,62 @@ -/*! @license DOMPurify 3.4.1 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.1/LICENSE */ +/*! @license DOMPurify 3.4.10 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.10/LICENSE */ -const { - entries, - setPrototypeOf, - isFrozen, - getPrototypeOf, - getOwnPropertyDescriptor -} = Object; -let { - freeze, - seal, - create -} = Object; // eslint-disable-line import/no-mutable-exports -let { - apply, - construct -} = typeof Reflect !== 'undefined' && Reflect; +function _arrayLikeToArray(r, a) { + (null == a || a > r.length) && (a = r.length); + for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; + return n; +} +function _arrayWithHoles(r) { + if (Array.isArray(r)) return r; +} +function _iterableToArrayLimit(r, l) { + var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; + if (null != t) { + var e, + n, + i, + u, + a = [], + f = true, + o = false; + try { + if (i = (t = t.call(r)).next, 0 === l) ; else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); + } catch (r) { + o = true, n = r; + } finally { + try { + if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; + } finally { + if (o) throw n; + } + } + return a; + } +} +function _nonIterableRest() { + throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); +} +function _slicedToArray(r, e) { + return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); +} +function _unsupportedIterableToArray(r, a) { + if (r) { + if ("string" == typeof r) return _arrayLikeToArray(r, a); + var t = {}.toString.call(r).slice(8, -1); + return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; + } +} + +const entries = Object.entries, + setPrototypeOf = Object.setPrototypeOf, + isFrozen = Object.isFrozen, + getPrototypeOf = Object.getPrototypeOf, + getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; +let freeze = Object.freeze, + seal = Object.seal, + create = Object.create; // eslint-disable-line import/no-mutable-exports +let _ref = typeof Reflect !== 'undefined' && Reflect, + apply = _ref.apply, + construct = _ref.construct; if (!freeze) { freeze = function freeze(x) { return x; @@ -152,7 +193,10 @@ function cleanArray(array) { */ function clone(object) { const newObject = create(null); - for (const [property, value] of entries(object)) { + for (const _ref2 of entries(object)) { + var _ref3 = _slicedToArray(_ref2, 2); + const property = _ref3[0]; + const value = _ref3[1]; const isPropertyExist = objectHasOwnProperty(object, property); if (isPropertyExist) { if (arrayIsArray(value)) { @@ -266,15 +310,14 @@ const mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mgly const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']); const text = freeze(['#text']); -const html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'exportparts', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inert', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'part', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'slot', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns']); +const html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'command', 'commandfor', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'exportparts', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inert', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'part', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'slot', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns']); const svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'exponent', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'intercept', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'mask-type', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'slope', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'tablevalues', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']); const mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnalign', 'columnlines', 'columnspacing', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lquote', 'lspace', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']); const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']); -// eslint-disable-next-line unicorn/better-regex -const MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode -const ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm); -const TMPLIT_EXPR = seal(/\$\{[\w\W]*/gm); // eslint-disable-line unicorn/better-regex +const MUSTACHE_EXPR = seal(/{{[\w\W]*|^[\w\W]*}}/g); +const ERB_EXPR = seal(/<%[\w\W]*|^[\w\W]*%>/g); +const TMPLIT_EXPR = seal(/\${[\w\W]*/g); const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); // eslint-disable-line no-useless-escape const ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape @@ -284,30 +327,32 @@ const ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205 ); const DOCTYPE_NAME = seal(/^html$/i); const CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i); - -var EXPRESSIONS = /*#__PURE__*/Object.freeze({ - __proto__: null, - ARIA_ATTR: ARIA_ATTR, - ATTR_WHITESPACE: ATTR_WHITESPACE, - CUSTOM_ELEMENT: CUSTOM_ELEMENT, - DATA_ATTR: DATA_ATTR, - DOCTYPE_NAME: DOCTYPE_NAME, - ERB_EXPR: ERB_EXPR, - IS_ALLOWED_URI: IS_ALLOWED_URI, - IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA, - MUSTACHE_EXPR: MUSTACHE_EXPR, - TMPLIT_EXPR: TMPLIT_EXPR -}); +// Markup-significant character probes used by _sanitizeElements. +// Shared module-level instances are safe despite the sticky /g flags: +// unapply() resets lastIndex for RegExp receivers before every call. +const ELEMENT_MARKUP_PROBE = seal(/<[/\w!]/g); +const COMMENT_MARKUP_PROBE = seal(/<[/\w]/g); +const FALLBACK_TAG_CLOSE = seal(/<\/no(script|embed|frames)/i); +const SELF_CLOSING_TAG = seal(/\/>/i); /* eslint-disable @typescript-eslint/indent */ // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType const NODE_TYPE = { element: 1, + attribute: 2, text: 3, + cdataSection: 4, + entityReference: 5, + // Deprecated + entityNode: 6, // Deprecated - progressingInstruction: 7, + processingInstruction: 7, comment: 8, - document: 9}; + document: 9, + documentType: 10, + documentFragment: 11, + notation: 12 // Deprecated +}; const getGlobal = function getGlobal() { return typeof window === 'undefined' ? null : window; }; @@ -362,10 +407,25 @@ const _createHooksMap = function _createHooksMap() { uponSanitizeShadowNode: [] }; }; +/** + * Resolve a set-valued configuration option: a fresh set built from + * cfg[key] when it is an own array property (seeded with a clone of + * options.base when given, case-normalized via options.transform), + * the fallback set otherwise. + * + * @param cfg the cloned, prototype-free configuration object + * @param key the configuration property to read + * @param fallback the set to use when the option is absent or not an array + * @param options transform and optional base set to merge into + * @returns the resolved set + */ +const _resolveSetOption = function _resolveSetOption(cfg, key, fallback, options) { + return objectHasOwnProperty(cfg, key) && arrayIsArray(cfg[key]) ? addToSet(options.base ? clone(options.base) : {}, cfg[key], options.transform) : fallback; +}; function createDOMPurify() { let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal(); const DOMPurify = root => createDOMPurify(root); - DOMPurify.version = '3.4.1'; + DOMPurify.version = '3.4.10'; DOMPurify.removed = []; if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) { // Not running in a browser, provide a factory function @@ -373,28 +433,29 @@ function createDOMPurify() { DOMPurify.isSupported = false; return DOMPurify; } - let { - document - } = window; + let document = window.document; const originalDocument = document; const currentScript = originalDocument.currentScript; - const { - DocumentFragment, - HTMLTemplateElement, - Node, - Element, - NodeFilter, - NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap, - HTMLFormElement, - DOMParser, - trustedTypes - } = window; + window.DocumentFragment; + const HTMLTemplateElement = window.HTMLTemplateElement, + Node = window.Node, + Element = window.Element, + NodeFilter = window.NodeFilter, + _window$NamedNodeMap = window.NamedNodeMap; + _window$NamedNodeMap === void 0 ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap; + window.HTMLFormElement; + const DOMParser = window.DOMParser, + trustedTypes = window.trustedTypes; const ElementPrototype = Element.prototype; const cloneNode = lookupGetter(ElementPrototype, 'cloneNode'); const remove = lookupGetter(ElementPrototype, 'remove'); const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling'); const getChildNodes = lookupGetter(ElementPrototype, 'childNodes'); const getParentNode = lookupGetter(ElementPrototype, 'parentNode'); + const getShadowRoot = lookupGetter(ElementPrototype, 'shadowRoot'); + const getAttributes = lookupGetter(ElementPrototype, 'attributes'); + const getNodeType = Node && Node.prototype ? lookupGetter(Node.prototype, 'nodeType') : null; + const getNodeName = Node && Node.prototype ? lookupGetter(Node.prototype, 'nodeName') : null; // As per issue #47, the web-components registry is inherited by a // new document created via createHTMLDocument. As per the spec // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries) @@ -409,33 +470,74 @@ function createDOMPurify() { } let trustedTypesPolicy; let emptyHTML = ''; - const { - implementation, - createNodeIterator, - createDocumentFragment, - getElementsByTagName - } = document; - const { - importNode - } = originalDocument; + // The instance's own internal Trusted Types policy. Unlike a caller-supplied + // `TRUSTED_TYPES_POLICY`, this is created at most once — Trusted Types throws + // on duplicate policy names — and is the only policy allowed to persist + // across configurations and survive `clearConfig()`. + let defaultTrustedTypesPolicy; + let defaultTrustedTypesPolicyResolved = false; + // Tracks whether we are already inside a call to the configured Trusted Types + // policy (`createHTML` or `createScriptURL`). If a supplied policy callback + // itself calls `DOMPurify.sanitize` (the cause of #1422), `sanitize` would + // re-enter the policy and recurse until the stack overflows. We detect that + // re-entry and throw a clear, actionable error instead. The guard is shared + // across both callbacks, because either one re-entering `sanitize` triggers + // the same unbounded recursion. + let IN_TRUSTED_TYPES_POLICY = 0; + const _assertNotInTrustedTypesPolicy = function _assertNotInTrustedTypesPolicy() { + if (IN_TRUSTED_TYPES_POLICY > 0) { + throw typeErrorCreate('A configured TRUSTED_TYPES_POLICY callback (createHTML or ' + 'createScriptURL) must not call DOMPurify.sanitize, as that causes ' + 'infinite recursion. Do not pass a policy whose callbacks wrap ' + 'DOMPurify as TRUSTED_TYPES_POLICY; see the "DOMPurify and Trusted ' + 'Types" section of the README.'); + } + }; + const _createTrustedHTML = function _createTrustedHTML(html) { + _assertNotInTrustedTypesPolicy(); + IN_TRUSTED_TYPES_POLICY++; + try { + return trustedTypesPolicy.createHTML(html); + } finally { + IN_TRUSTED_TYPES_POLICY--; + } + }; + const _createTrustedScriptURL = function _createTrustedScriptURL(scriptUrl) { + _assertNotInTrustedTypesPolicy(); + IN_TRUSTED_TYPES_POLICY++; + try { + return trustedTypesPolicy.createScriptURL(scriptUrl); + } finally { + IN_TRUSTED_TYPES_POLICY--; + } + }; + // Lazily resolve (and cache) the instance's internal default policy. + // Resolution is attempted at most once: a successful `createPolicy` cannot be + // repeated (Trusted Types throws on duplicate names), and a failed or + // unsupported attempt must not be retried on every parse. + const _getDefaultTrustedTypesPolicy = function _getDefaultTrustedTypesPolicy() { + if (!defaultTrustedTypesPolicyResolved) { + defaultTrustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript); + defaultTrustedTypesPolicyResolved = true; + } + return defaultTrustedTypesPolicy; + }; + const _document = document, + implementation = _document.implementation, + createNodeIterator = _document.createNodeIterator, + createDocumentFragment = _document.createDocumentFragment, + getElementsByTagName = _document.getElementsByTagName; + const importNode = originalDocument.importNode; let hooks = _createHooksMap(); /** * Expose whether this browser supports running the full DOMPurify. */ DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined; - const { - MUSTACHE_EXPR, - ERB_EXPR, - TMPLIT_EXPR, - DATA_ATTR, - ARIA_ATTR, - IS_SCRIPT_OR_DATA, - ATTR_WHITESPACE, - CUSTOM_ELEMENT - } = EXPRESSIONS; - let { - IS_ALLOWED_URI: IS_ALLOWED_URI$1 - } = EXPRESSIONS; + const MUSTACHE_EXPR$1 = MUSTACHE_EXPR, + ERB_EXPR$1 = ERB_EXPR, + TMPLIT_EXPR$1 = TMPLIT_EXPR, + DATA_ATTR$1 = DATA_ATTR, + ARIA_ATTR$1 = ARIA_ATTR, + IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA, + ATTR_WHITESPACE$1 = ATTR_WHITESPACE, + CUSTOM_ELEMENT$1 = CUSTOM_ELEMENT; + let IS_ALLOWED_URI$1 = IS_ALLOWED_URI; /** * We consider the elements and attributes below to be safe. Ideally * don't add any new ones but feel free to remove unwanted ones. @@ -554,7 +656,17 @@ function createDOMPurify() { let USE_PROFILES = {}; /* Tags to ignore content of when KEEP_CONTENT is true */ let FORBID_CONTENTS = null; - const DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']); + const DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', + // mirrors the selected