@aact/view 3.0.0-beta.23 → 3.0.0-beta.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -5
- package/dist/index.d.ts +8 -0
- package/dist/index.js +46 -4
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +15 -0
- package/dist/server.js +23 -10
- package/dist/server.js.map +1 -1
- package/dist/ui/assets/index-BR_xeaLb.js +2 -0
- package/dist/ui/assets/index-BR_xeaLb.js.map +1 -0
- package/dist/ui/assets/index-CK7Lun-6.css +1 -0
- package/dist/ui/index.html +2 -2
- package/package.json +3 -3
- package/dist/ui/assets/index-D2ZA0Nkz.js +0 -4
- package/dist/ui/assets/index-D2ZA0Nkz.js.map +0 -1
- package/dist/ui/assets/index-DFjT4EUS.css +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-BR_xeaLb.js","names":[],"sources":["../../../ui/src/actions.ts","../../../ui/src/BoundaryNode.svelte","../../../ui/src/DatabaseNode.svelte","../../../ui/src/ElementNode.svelte","../../../ui/src/PersonNode.svelte","../../../ui/src/QueueNode.svelte","../../../ui/src/layoutWorkerClient.ts","../../../ui/src/layout.ts","../../../ui/src/App.svelte","../../../ui/src/main.ts"],"sourcesContent":["/**\n * Bridge between custom Svelte Flow nodes (which can't receive\n * props from App.svelte directly — Svelte Flow only forwards\n * `data` / `selected` / `dragging`) and the app-level state.\n *\n * App.svelte registers a `ViewActions` object via `setContext`.\n * Node components read it via `getContext` and call back when\n * the user interacts. Decoupling actions from data keeps the\n * `data` payload serialisable and avoids node re-renders when\n * the parent re-assigns a callback identity.\n */\nexport interface ViewActions {\n selectElement(name: string): void;\n selectBoundary(name: string): void;\n /** Drill-mode descent — replace the current scope with this\n * boundary's children. */\n enterBoundary(name: string, label: string): void;\n /** Expand-mode toggle — open/close the boundary inline without\n * hiding parent siblings. No-op outside Expand mode. */\n toggleBoundary(name: string, label: string): void;\n}\n\nexport const VIEW_ACTIONS = Symbol(\"aact-view:actions\");\n","<script lang=\"ts\">\n import { getContext } from \"svelte\";\n\n import { Handle, Position, type NodeProps } from \"@xyflow/svelte\";\n\n import { VIEW_ACTIONS, type ViewActions } from \"./actions.ts\";\n\n interface BoundaryNodeData {\n name: string;\n label: string;\n kind: string;\n childCount: number;\n expanded: boolean;\n canExpand: boolean;\n }\n\n let { data, selected }: NodeProps<{ data: BoundaryNodeData }> = $props();\n\n const actions = getContext<ViewActions>(VIEW_ACTIONS);\n\n // Boundary borders follow the same C4 progression as the elements\n // they wrap, just dashed and translucent so they read as containers\n // not as solid shapes.\n const palette: Record<string, string> = {\n Enterprise: \"#0b3b6c\",\n System: \"#1168bd\",\n Container: \"#438dd5\",\n Component: \"#85bbf0\",\n };\n const accent = $derived(palette[data.kind] ?? \"#94a3b8\");\n\n const onClick = (event: MouseEvent): void => {\n // Boundary headers absorb clicks; ignore clicks that bubble up\n // from interactive children (controls, child nodes) so we don't\n // double-fire selection.\n if (event.target !== event.currentTarget) {\n const isHeader = (event.target as HTMLElement).closest(\".header\");\n if (!isHeader) return;\n }\n actions?.selectBoundary(data.name);\n };\n\n const onDblClick = (event: MouseEvent): void => {\n event.stopPropagation();\n if (data.canExpand) {\n actions?.toggleBoundary(data.name, data.label);\n } else {\n actions?.enterBoundary(data.name, data.label);\n }\n };\n\n const onKeydown = (event: KeyboardEvent): void => {\n if (event.key === \"Enter\") {\n actions?.selectBoundary(data.name);\n return;\n }\n if (event.key !== \" \") return;\n event.preventDefault();\n if (data.canExpand) {\n actions?.toggleBoundary(data.name, data.label);\n } else {\n actions?.enterBoundary(data.name, data.label);\n }\n };\n</script>\n\n<div\n class=\"boundary\"\n class:expanded={data.expanded}\n class:is-selected={selected}\n style:--accent={accent}\n role=\"button\"\n tabindex=\"0\"\n aria-label={`${data.kind} boundary: ${data.label}`}\n onclick={onClick}\n ondblclick={onDblClick}\n onkeydown={onKeydown}\n>\n <Handle type=\"target\" position={Position.Left} />\n <header class=\"header\">\n <span class=\"kind\">{data.kind} boundary</span>\n <span class=\"label\">{data.label}</span>\n {#if !data.expanded}\n <span class=\"meta\">\n {data.childCount} · double-click to {data.canExpand ? \"expand\" : \"enter\"}\n </span>\n {/if}\n </header>\n <Handle type=\"source\" position={Position.Right} />\n</div>\n\n<style>\n .boundary {\n display: flex;\n flex-direction: column;\n border-radius: 16px;\n border: 2px dashed var(--accent, #94a3b8);\n background: color-mix(in srgb, var(--accent, #94a3b8) 8%, transparent);\n color: #e2e8f0;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n cursor: pointer;\n transition:\n background 120ms ease,\n box-shadow 120ms ease;\n backdrop-filter: blur(2px);\n }\n .boundary:hover {\n background: color-mix(in srgb, var(--accent, #94a3b8) 14%, transparent);\n }\n .boundary.expanded {\n cursor: default;\n }\n .boundary.is-selected {\n box-shadow:\n 0 0 0 1px var(--accent),\n 0 0 0 4px color-mix(in srgb, var(--accent) 30%, transparent);\n }\n .header {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 8px 12px 10px;\n border-bottom: 1px dashed\n color-mix(in srgb, var(--accent) 40%, transparent);\n background: color-mix(in srgb, var(--accent) 10%, transparent);\n border-radius: 14px 14px 0 0;\n }\n .kind {\n font-size: 9.5px;\n letter-spacing: 0.12em;\n text-transform: uppercase;\n color: color-mix(in srgb, var(--accent) 65%, #cbd5e1);\n font-weight: 500;\n }\n .label {\n font-size: 13px;\n font-weight: 600;\n line-height: 1.2;\n color: #f8fafc;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n letter-spacing: -0.005em;\n }\n .meta {\n font-size: 10px;\n color: rgba(226, 232, 240, 0.45);\n letter-spacing: 0.01em;\n }\n</style>\n","<script lang=\"ts\">\n import { getContext } from \"svelte\";\n\n import { Handle, Position, type NodeProps } from \"@xyflow/svelte\";\n\n import { VIEW_ACTIONS, type ViewActions } from \"./actions.ts\";\n\n interface DatabaseNodeData {\n name: string;\n label: string;\n kind: string;\n description: string;\n external: boolean;\n technology: string;\n }\n\n let { data, selected }: NodeProps<{ data: DatabaseNodeData }> = $props();\n\n const actions = getContext<ViewActions>(VIEW_ACTIONS);\n\n // Database fill follows the C4 container/system gradient. Externals\n // drop to neutral grey per Simon Brown's reference palette so the\n // \"ours vs theirs\" distinction stays at a glance.\n const fill = $derived(data.external ? \"#475569\" : \"#1168bd\");\n</script>\n\n<div\n class=\"db\"\n class:external={data.external}\n class:is-selected={selected}\n style:--fill={fill}\n role=\"button\"\n tabindex=\"0\"\n onclick={() => actions?.selectElement(data.name)}\n onkeydown={(event) => {\n if (event.key === \"Enter\") actions?.selectElement(data.name);\n }}\n>\n <Handle type=\"target\" position={Position.Left} />\n <div class=\"cyl-top\" aria-hidden=\"true\"></div>\n <div class=\"body\">\n <span class=\"kind\">{data.kind}</span>\n <span class=\"label\">{data.label}</span>\n {#if data.technology}\n <span class=\"tech\">[{data.technology}]</span>\n {/if}\n {#if data.description}\n <span class=\"desc\">{data.description}</span>\n {/if}\n </div>\n <Handle type=\"source\" position={Position.Right} />\n</div>\n\n<style>\n .db {\n position: relative;\n display: grid;\n grid-template-rows: 14px 1fr;\n padding: 0;\n border-radius: 14px 14px 22px 22px / 14px 14px 30px 30px;\n background: linear-gradient(\n 180deg,\n var(--fill) 0%,\n color-mix(in srgb, var(--fill) 80%, black) 100%\n );\n color: #f8fafc;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n cursor: pointer;\n box-shadow:\n 0 10px 28px -18px color-mix(in srgb, var(--fill) 70%, transparent),\n inset 0 1px 0 rgba(255, 255, 255, 0.1);\n transition:\n transform 120ms ease,\n box-shadow 120ms ease;\n }\n .db:hover {\n transform: translateY(-1px);\n }\n .db.is-selected {\n outline: 2px solid #38bdf8;\n outline-offset: 2px;\n }\n .cyl-top {\n height: 14px;\n background: rgba(0, 0, 0, 0.18);\n border-radius: 14px 14px 50% 50% / 14px 14px 100% 100%;\n border-bottom: 1px solid rgba(255, 255, 255, 0.15);\n }\n .body {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 10px 14px 14px;\n overflow: hidden;\n }\n .kind {\n font-size: 9px;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: rgba(248, 250, 252, 0.78);\n font-weight: 700;\n }\n .label {\n font-size: 13px;\n font-weight: 700;\n line-height: 1.15;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n }\n .tech {\n font-size: 10px;\n color: rgba(248, 250, 252, 0.85);\n font-style: italic;\n }\n .desc {\n font-size: 11px;\n line-height: 1.3;\n color: rgba(248, 250, 252, 0.75);\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n }\n</style>\n","<script lang=\"ts\">\n import { getContext } from \"svelte\";\n\n import { Handle, Position, type NodeProps } from \"@xyflow/svelte\";\n\n import { VIEW_ACTIONS, type ViewActions } from \"./actions.ts\";\n\n interface ElementNodeData {\n name: string;\n label: string;\n kind: string;\n description: string;\n external: boolean;\n technology: string;\n }\n\n let { data, selected }: NodeProps<{ data: ElementNodeData }> = $props();\n\n const actions = getContext<ViewActions>(VIEW_ACTIONS);\n\n // Simon Brown / c4model.com canonical palette: deeper blue for\n // higher-level abstractions, fading to lighter shades as we drill\n // down. Externals collapse to neutral slate so they read as\n // \"someone else's box.\"\n const palette = (kind: string, external: boolean): string => {\n if (external) return \"#475569\";\n if (kind === \"System\") return \"#1168bd\";\n if (kind === \"Container\") return \"#438dd5\";\n if (kind === \"Component\") return \"#85bbf0\";\n return \"#1168bd\";\n };\n const fill = $derived(palette(data.kind, data.external));\n const textColor = $derived(\n data.kind === \"Component\" && !data.external ? \"#0f172a\" : \"#f8fafc\",\n );\n</script>\n\n<div\n class=\"el\"\n class:external={data.external}\n class:is-selected={selected}\n style:--fill={fill}\n style:--text={textColor}\n role=\"button\"\n tabindex=\"0\"\n onclick={() => actions?.selectElement(data.name)}\n onkeydown={(event) => {\n if (event.key === \"Enter\") actions?.selectElement(data.name);\n }}\n>\n <Handle type=\"target\" position={Position.Left} />\n <div class=\"head\">\n <span class=\"kind\">{data.kind}{data.external ? \" · external\" : \"\"}</span>\n </div>\n <span class=\"label\">{data.label}</span>\n {#if data.technology}\n <span class=\"tech\">[{data.technology}]</span>\n {/if}\n {#if data.description}\n <span class=\"desc\">{data.description}</span>\n {/if}\n <Handle type=\"source\" position={Position.Right} />\n</div>\n\n<style>\n .el {\n display: flex;\n flex-direction: column;\n gap: 3px;\n padding: 10px 12px 12px;\n border-radius: 6px;\n background: var(--fill);\n color: var(--text, #f8fafc);\n border: 1px solid color-mix(in srgb, var(--fill) 60%, black);\n box-sizing: border-box;\n width: 100%;\n height: 100%;\n cursor: pointer;\n transition: filter 100ms ease, border-color 100ms ease;\n }\n .el:hover {\n filter: brightness(1.08);\n }\n .el.is-selected {\n border-color: #7dd3fc;\n box-shadow: 0 0 0 1px #7dd3fc inset;\n }\n .head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n .kind {\n font-size: 9.5px;\n letter-spacing: 0.12em;\n text-transform: uppercase;\n color: color-mix(in srgb, var(--text) 65%, transparent);\n font-weight: 500;\n }\n .label {\n font-size: 13px;\n font-weight: 600;\n line-height: 1.2;\n letter-spacing: -0.005em;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n }\n .tech {\n font-size: 10px;\n color: color-mix(in srgb, var(--text) 75%, transparent);\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n }\n .desc {\n font-size: 11px;\n line-height: 1.35;\n color: color-mix(in srgb, var(--text) 70%, transparent);\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n }\n</style>\n","<script lang=\"ts\">\n import { getContext } from \"svelte\";\n\n import { Handle, Position, type NodeProps } from \"@xyflow/svelte\";\n\n import { VIEW_ACTIONS, type ViewActions } from \"./actions.ts\";\n\n interface PersonNodeData {\n name: string;\n label: string;\n description: string;\n external: boolean;\n technology: string;\n }\n\n let { data, selected }: NodeProps<{ data: PersonNodeData }> = $props();\n\n const actions = getContext<ViewActions>(VIEW_ACTIONS);\n</script>\n\n<div\n class=\"person\"\n class:external={data.external}\n class:is-selected={selected}\n role=\"button\"\n tabindex=\"0\"\n onclick={() => actions?.selectElement(data.name)}\n onkeydown={(event) => {\n if (event.key === \"Enter\") actions?.selectElement(data.name);\n }}\n>\n <Handle type=\"target\" position={Position.Left} />\n <div class=\"head\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" class=\"silhouette\" xmlns=\"http://www.w3.org/2000/svg\">\n <!-- Head + shoulders silhouette. Two distinct shapes so it\n reads as a person at a glance, with no overlap between\n the head circle and the rounded shoulders below. -->\n <circle cx=\"12\" cy=\"7\" r=\"4\" />\n <path d=\"M4 21c0-4.42 3.58-8 8-8s8 3.58 8 8\" />\n </svg>\n </div>\n <div class=\"body\">\n <span class=\"kind\">Person</span>\n <span class=\"label\">{data.label}</span>\n {#if data.description}\n <span class=\"desc\">{data.description}</span>\n {/if}\n </div>\n <Handle type=\"source\" position={Position.Right} />\n</div>\n\n<style>\n .person {\n display: grid;\n grid-template-rows: 36px 1fr;\n gap: 6px;\n padding: 12px 14px 14px;\n border-radius: 14px;\n background: linear-gradient(180deg, #08427b 0%, #073768 100%);\n color: #f8fafc;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n cursor: pointer;\n box-shadow:\n 0 10px 30px -18px rgba(8, 66, 123, 0.85),\n inset 0 1px 0 rgba(255, 255, 255, 0.08);\n transition:\n transform 120ms ease,\n box-shadow 120ms ease;\n }\n .person:hover {\n transform: translateY(-1px);\n box-shadow:\n 0 14px 40px -16px rgba(8, 66, 123, 0.95),\n inset 0 1px 0 rgba(255, 255, 255, 0.12);\n }\n .person.is-selected {\n outline: 2px solid #38bdf8;\n outline-offset: 2px;\n }\n .person.external {\n background: linear-gradient(180deg, #475569 0%, #334155 100%);\n }\n .head {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n .silhouette {\n width: 28px;\n height: 28px;\n color: #f8fafc;\n opacity: 0.92;\n }\n .silhouette circle {\n fill: currentColor;\n }\n .silhouette path {\n fill: none;\n stroke: currentColor;\n stroke-width: 2;\n stroke-linecap: round;\n }\n .body {\n display: flex;\n flex-direction: column;\n gap: 2px;\n align-items: center;\n text-align: center;\n }\n .kind {\n font-size: 9px;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: rgba(248, 250, 252, 0.75);\n font-weight: 700;\n }\n .label {\n font-size: 14px;\n font-weight: 700;\n line-height: 1.15;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n }\n .desc {\n font-size: 11px;\n line-height: 1.25;\n color: rgba(248, 250, 252, 0.7);\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n }\n</style>\n","<script lang=\"ts\">\n import { getContext } from \"svelte\";\n\n import { Handle, Position, type NodeProps } from \"@xyflow/svelte\";\n\n import { VIEW_ACTIONS, type ViewActions } from \"./actions.ts\";\n\n interface QueueNodeData {\n name: string;\n label: string;\n kind: string;\n description: string;\n external: boolean;\n technology: string;\n }\n\n let { data, selected }: NodeProps<{ data: QueueNodeData }> = $props();\n\n const actions = getContext<ViewActions>(VIEW_ACTIONS);\n\n const fill = $derived(data.external ? \"#475569\" : \"#1168bd\");\n</script>\n\n<div\n class=\"q\"\n class:external={data.external}\n class:is-selected={selected}\n style:--fill={fill}\n role=\"button\"\n tabindex=\"0\"\n onclick={() => actions?.selectElement(data.name)}\n onkeydown={(event) => {\n if (event.key === \"Enter\") actions?.selectElement(data.name);\n }}\n>\n <Handle type=\"target\" position={Position.Left} />\n <div class=\"body\">\n <span class=\"kind\">{data.kind}</span>\n <span class=\"label\">{data.label}</span>\n {#if data.technology}\n <span class=\"tech\">[{data.technology}]</span>\n {/if}\n {#if data.description}\n <span class=\"desc\">{data.description}</span>\n {/if}\n </div>\n <Handle type=\"source\" position={Position.Right} />\n</div>\n\n<style>\n .q {\n display: flex;\n flex-direction: column;\n gap: 0;\n padding: 0;\n /* Pipe / capsule end-caps so it reads as a queue at a glance. */\n border-radius: 999px;\n background: linear-gradient(\n 180deg,\n var(--fill) 0%,\n color-mix(in srgb, var(--fill) 80%, black) 100%\n );\n color: #f8fafc;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n cursor: pointer;\n box-shadow:\n 0 10px 28px -18px color-mix(in srgb, var(--fill) 70%, transparent),\n inset 0 1px 0 rgba(255, 255, 255, 0.1);\n transition: transform 120ms ease;\n }\n .q:hover {\n transform: translateY(-1px);\n }\n .q.is-selected {\n outline: 2px solid #38bdf8;\n outline-offset: 2px;\n }\n .body {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 14px 22px;\n overflow: hidden;\n height: 100%;\n justify-content: center;\n }\n .kind {\n font-size: 9px;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: rgba(248, 250, 252, 0.78);\n font-weight: 700;\n }\n .label {\n font-size: 13px;\n font-weight: 700;\n line-height: 1.15;\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n }\n .tech {\n font-size: 10px;\n color: rgba(248, 250, 252, 0.85);\n font-style: italic;\n }\n .desc {\n font-size: 11px;\n line-height: 1.3;\n color: rgba(248, 250, 252, 0.75);\n overflow: hidden;\n text-overflow: ellipsis;\n display: -webkit-box;\n -webkit-line-clamp: 1;\n -webkit-box-orient: vertical;\n }\n</style>\n","import ELK from \"elkjs/lib/elk.bundled.js\";\n\n/**\n * Why ELK runs on the main thread:\n *\n * `elkjs/lib/elk.bundled.js` internally spawns its own compute\n * kernel as a Web Worker via `require('./elk-worker.min.js')`.\n * That `require()` is dynamic UMD plumbing which Vite cannot\n * trace through, so when we wrap ELK in our OWN Worker the\n * bundled output ends up with `e('./elk-worker.min.js').Worker`\n * resolving to undefined → `new undefined()` → `TypeError: o is\n * not a constructor` at runtime. We tried `worker.format: \"es\"`\n * + `?worker` import; same failure.\n *\n * Layout performance for the model sizes aact view targets (50\n * nodes / 100 relations sub-second) doesn't justify the extra\n * infra to inline ELK's nested worker. If we ever need it we'll\n * either ship `elk-worker.min.js` as a separately-served asset\n * (`?url` import + `new ELK({ workerUrl })`) or vendor the\n * synchronous Java→JS fallback path. For now: in-process.\n */\nconst elk = new ELK();\n\nexport const runElkLayout = <T>(graph: unknown): Promise<T> =>\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- ELK input types are deeply structural; the call sites already pass typed nodes/edges\n elk.layout(graph as any) as Promise<T>;\n","import { MarkerType, type Edge, type Node } from \"@xyflow/svelte\";\n\nimport type { Boundary, Element, Model } from \"./types.ts\";\nimport { runElkLayout } from \"./layoutWorkerClient.ts\";\n\n/**\n * Three layout strategies sharing one ELK pipeline:\n *\n * - `layoutScope` — Drill mode. Flat layout for the current\n * breadcrumb level; siblings only, parents are\n * replaced as the user descends.\n *\n * - `layoutNested` — Expand-in-place mode. Boundaries the user\n * toggles open render inline as containers,\n * with their children visible alongside parent\n * siblings.\n *\n * - `layoutFlat` — Full hierarchy. Every boundary in the model\n * starts expanded; user sees the whole tree at\n * once. Useful for an overview or print.\n *\n * Nested and Flat both share the same ELK `INCLUDE_CHILDREN` tree\n * and `parentId` flattening — Flat is just \"expanded = every\n * boundary name\" preconfigured.\n *\n * The id-prefix convention (`b:` for boundaries, `e:` for elements)\n * is exported so node components and click handlers can decode IDs.\n */\nconst LEAF_WIDTH = 220;\nconst LEAF_HEIGHT = 110;\nconst PERSON_WIDTH = 200;\nconst PERSON_HEIGHT = 130;\nconst BOUNDARY_MIN_WIDTH = 260;\nconst BOUNDARY_MIN_HEIGHT = 160;\n\nexport const elementId = (name: string): string => `e:${name}`;\nexport const boundaryId = (name: string): string => `b:${name}`;\n\nconst leafSize = (kind: Element[\"kind\"]): { width: number; height: number } =>\n kind === \"Person\"\n ? { width: PERSON_WIDTH, height: PERSON_HEIGHT }\n : { width: LEAF_WIDTH, height: LEAF_HEIGHT };\n\nconst elementNodeType = (kind: Element[\"kind\"]): string => {\n if (kind === \"Person\") return \"person\";\n if (kind === \"SystemDb\" || kind === \"ContainerDb\" || kind === \"ComponentDb\")\n return \"database\";\n if (\n kind === \"SystemQueue\" ||\n kind === \"ContainerQueue\" ||\n kind === \"ComponentQueue\"\n )\n return \"queue\";\n return \"element\";\n};\n\nconst elementNodeData = (e: Element): Record<string, unknown> => ({\n name: e.name,\n label: e.label,\n kind: e.kind,\n description: e.description ?? \"\",\n external: e.external,\n technology: e.technology ?? \"\",\n tags: e.tags,\n});\n\nconst boundaryNodeData = (\n b: Boundary,\n options: { expanded: boolean; canExpand: boolean },\n): Record<string, unknown> => ({\n name: b.name,\n label: b.label,\n kind: b.kind,\n childCount: b.elementNames.length + b.boundaryNames.length,\n expanded: options.expanded,\n canExpand: options.canExpand,\n});\n\nexport interface LayoutScope {\n readonly elements: readonly Element[];\n readonly boundaries: readonly Boundary[];\n readonly relations: ReadonlyArray<{\n readonly from: string;\n readonly to: string;\n readonly label?: string;\n readonly count?: number;\n readonly fromKind?: \"element\" | \"boundary\";\n readonly toKind?: \"element\" | \"boundary\";\n }>;\n}\n\nexport interface LayoutResult {\n readonly nodes: Node[];\n readonly edges: Edge[];\n}\n\n// Dense C4 landscapes routinely have 50+ relations passing through a\n// shared API gateway. Bumping `edgeEdge` / `edgeNode` spacing keeps\n// parallel edges visually separated while letting ELK pick the\n// routing strategy that works for the node layout. The xyflow-side\n// edge type (bezier / smoothstep / step) is chosen by the user from\n// the topbar — see `EdgeStyle` in App.svelte.\nconst layeredOptions = {\n \"elk.algorithm\": \"layered\",\n \"elk.direction\": \"RIGHT\",\n \"elk.layered.spacing.nodeNodeBetweenLayers\": \"90\",\n \"elk.spacing.nodeNode\": \"50\",\n \"elk.spacing.edgeEdge\": \"20\",\n \"elk.spacing.edgeNode\": \"30\",\n \"elk.layered.spacing.edgeEdgeBetweenLayers\": \"20\",\n \"elk.layered.spacing.edgeNodeBetweenLayers\": \"30\",\n \"elk.padding\": \"[top=48, left=44, bottom=44, right=44]\",\n};\n\nconst formatEdgeLabel = (\n label: string | undefined,\n count: number | undefined,\n): string | undefined => {\n if (!count || count <= 1) return label;\n return label ? `${label} · ×${count}` : `×${count}`;\n};\n\n/** ----------------------------------------------------------------\n * Drill mode (existing behaviour). One scope, flat layout.\n * ---------------------------------------------------------------- */\n\nexport const layoutScope = async (\n scope: LayoutScope,\n): Promise<LayoutResult> => {\n const edgeId = (\n r: LayoutScope[\"relations\"][number],\n ): { source: string; target: string } => ({\n source: r.fromKind === \"boundary\" ? boundaryId(r.from) : elementId(r.from),\n target: r.toKind === \"boundary\" ? boundaryId(r.to) : elementId(r.to),\n });\n\n const elkChildren = [\n ...scope.boundaries.map((b) => ({\n id: boundaryId(b.name),\n width: BOUNDARY_MIN_WIDTH,\n height: BOUNDARY_MIN_HEIGHT,\n })),\n ...scope.elements.map((e) => ({\n id: elementId(e.name),\n ...leafSize(e.kind),\n })),\n ];\n const elkEdges = scope.relations.map((r, index) => {\n const { source, target } = edgeId(r);\n return { id: `edge-${index}`, sources: [source], targets: [target] };\n });\n\n const result = await runElkLayout<ElkResultNode>({\n id: \"root\",\n layoutOptions: layeredOptions,\n children: elkChildren,\n edges: elkEdges,\n });\n\n const nodes: Node[] = [];\n for (const b of scope.boundaries) {\n const id = boundaryId(b.name);\n const laid = result.children?.find((c) => c.id === id);\n nodes.push({\n id,\n type: \"boundary\",\n position: { x: laid?.x ?? 0, y: laid?.y ?? 0 },\n data: boundaryNodeData(b, { expanded: false, canExpand: false }),\n style: `width: ${laid?.width ?? BOUNDARY_MIN_WIDTH}px; height: ${laid?.height ?? BOUNDARY_MIN_HEIGHT}px;`,\n });\n }\n for (const e of scope.elements) {\n const id = elementId(e.name);\n const laid = result.children?.find((c) => c.id === id);\n const { width, height } = leafSize(e.kind);\n nodes.push({\n id,\n type: elementNodeType(e.kind),\n position: { x: laid?.x ?? 0, y: laid?.y ?? 0 },\n data: elementNodeData(e),\n style: `width: ${width}px; height: ${height}px;`,\n });\n }\n\n const edges: Edge[] = scope.relations.map((r, index) => {\n const { source, target } = edgeId(r);\n return {\n id: `edge-${index}`,\n source,\n target,\n label: formatEdgeLabel(r.label, r.count),\n type: \"default\",\n animated: false,\n // Drill mode aggregates by construction — every surviving\n // relation crosses a Bounded Context boundary (intra-boundary\n // relations were filtered out by buildScopeRelations).\n data: { crossBoundary: true },\n markerEnd: {\n type: MarkerType.ArrowClosed,\n width: 24,\n height: 24,\n color: \"#cbd5e1\",\n },\n // @xyflow/svelte 1.x renders the label as an HTML <div>, so\n // styling goes through CSS / CSS variables (see App.svelte).\n // The SVG-era `labelBgStyle` / `labelBgPadding` props are\n // no-ops here — omitting them keeps the edge payload clean.\n style: \"stroke: #94a3b8; stroke-width: 1.8;\",\n };\n });\n\n return { nodes, edges };\n};\n\n/** ----------------------------------------------------------------\n * Shared ownership infrastructure (Drill aggregation + Nested\n * endpoint resolution).\n * ---------------------------------------------------------------- */\n\nconst buildParentMap = (model: Model): Map<string, string> => {\n const parent = new Map<string, string>();\n for (const b of Object.values(model.boundaries)) {\n for (const child of b.boundaryNames) parent.set(child, b.name);\n for (const el of b.elementNames) parent.set(el, b.name);\n }\n return parent;\n};\n\nconst buildOwnership = (\n model: Model,\n visibleBoundaryNames: ReadonlySet<string>,\n visibleElementNames: ReadonlySet<string>,\n): Map<string, { kind: \"element\" | \"boundary\"; name: string }> => {\n const owner = new Map<\n string,\n { kind: \"element\" | \"boundary\"; name: string }\n >();\n\n for (const name of visibleElementNames) {\n owner.set(name, { kind: \"element\", name });\n }\n\n const walk = (b: Boundary, top: Boundary): void => {\n for (const n of b.elementNames) {\n if (!owner.has(n)) {\n owner.set(n, { kind: \"boundary\", name: top.name });\n }\n }\n for (const child of b.boundaryNames) {\n const cb = model.boundaries[child];\n if (!cb) continue;\n walk(cb, top);\n }\n };\n for (const name of visibleBoundaryNames) {\n const b = model.boundaries[name];\n if (b) walk(b, b);\n }\n\n return owner;\n};\n\nconst buildScopeRelations = (\n model: Model,\n owner: ReadonlyMap<string, { kind: \"element\" | \"boundary\"; name: string }>,\n): LayoutScope[\"relations\"] => {\n const out = new Map<string, LayoutScope[\"relations\"][number]>();\n for (const el of Object.values(model.elements)) {\n for (const rel of el.relations) {\n const fromOwner = owner.get(el.name);\n const toOwner = owner.get(rel.to);\n if (!fromOwner || !toOwner) continue;\n const fromKey =\n fromOwner.kind === \"boundary\"\n ? boundaryId(fromOwner.name)\n : elementId(fromOwner.name);\n const toKey =\n toOwner.kind === \"boundary\"\n ? boundaryId(toOwner.name)\n : elementId(toOwner.name);\n if (fromKey === toKey) continue;\n const key = `${fromKey}->${toKey}`;\n const existing = out.get(key);\n if (existing) {\n out.set(key, {\n ...existing,\n count: (existing.count ?? 1) + 1,\n });\n continue;\n }\n out.set(key, {\n from: fromOwner.name,\n to: toOwner.name,\n label:\n fromOwner.kind === \"boundary\" || toOwner.kind === \"boundary\"\n ? undefined\n : rel.description,\n fromKind: fromOwner.kind,\n toKind: toOwner.kind,\n count: 1,\n });\n }\n }\n return [...out.values()];\n};\n\nexport const sliceModel = (\n model: Model,\n breadcrumb: readonly {\n readonly kind: \"landscape\" | \"boundary\";\n readonly name?: string;\n }[],\n): LayoutScope => {\n const top = breadcrumb[breadcrumb.length - 1] ?? { kind: \"landscape\" };\n\n if (top.kind === \"landscape\") {\n const rootBoundaries = (model.rootBoundaryNames ?? [])\n .map((n) => model.boundaries[n])\n .filter((b): b is Boundary => Boolean(b));\n const visibleBoundaryNames = new Set(rootBoundaries.map((b) => b.name));\n const bounded = new Set<string>();\n const walk = (b: Boundary): void => {\n for (const n of b.elementNames) bounded.add(n);\n for (const child of b.boundaryNames) {\n const cb = model.boundaries[child];\n if (cb) walk(cb);\n }\n };\n for (const b of rootBoundaries) walk(b);\n const standalone = Object.values(model.elements).filter(\n (e) => !bounded.has(e.name),\n );\n const visibleElementNames = new Set(standalone.map((e) => e.name));\n const owner = buildOwnership(\n model,\n visibleBoundaryNames,\n visibleElementNames,\n );\n return {\n boundaries: rootBoundaries,\n elements: standalone,\n relations: buildScopeRelations(model, owner),\n };\n }\n\n const b = top.name ? model.boundaries[top.name] : undefined;\n if (!b) return { boundaries: [], elements: [], relations: [] };\n\n const elements = b.elementNames\n .map((n) => model.elements[n])\n .filter((e): e is Element => Boolean(e));\n const boundaries = b.boundaryNames\n .map((n) => model.boundaries[n])\n .filter((nb): nb is Boundary => Boolean(nb));\n const visibleBoundaryNames = new Set(boundaries.map((nb) => nb.name));\n const visibleElementNames = new Set(elements.map((e) => e.name));\n const owner = buildOwnership(\n model,\n visibleBoundaryNames,\n visibleElementNames,\n );\n return {\n boundaries,\n elements,\n relations: buildScopeRelations(model, owner),\n };\n};\n\n/** ----------------------------------------------------------------\n * Nested / Flat modes — hierarchical layout with `parentId`.\n * ---------------------------------------------------------------- */\n\ninterface ElkInputNode {\n id: string;\n width?: number;\n height?: number;\n children?: ElkInputNode[];\n edges?: ElkInputEdge[];\n layoutOptions?: Record<string, string>;\n}\n\n// Expanded boundaries reserve extra top-padding so children render\n// below the BoundaryNode's header (kind chip + label + meta line)\n// instead of being painted on top of it. The header is ~76px tall —\n// 96 gives a clean margin.\nconst containerLayoutOptions: Record<string, string> = {\n ...layeredOptions,\n \"elk.padding\": \"[top=96, left=44, bottom=44, right=44]\",\n};\n\ninterface ElkInputEdge {\n id: string;\n sources: string[];\n targets: string[];\n}\n\nconst buildNestedTree = (\n model: Model,\n expanded: ReadonlySet<string>,\n rootBoundaries: readonly Boundary[],\n standalone: readonly Element[],\n edges: readonly ElkInputEdge[],\n): ElkInputNode => {\n const renderBoundary = (b: Boundary): ElkInputNode => {\n if (!expanded.has(b.name)) {\n return {\n id: boundaryId(b.name),\n width: BOUNDARY_MIN_WIDTH,\n height: BOUNDARY_MIN_HEIGHT,\n };\n }\n const children: ElkInputNode[] = [];\n for (const childName of b.boundaryNames) {\n const child = model.boundaries[childName];\n if (child) children.push(renderBoundary(child));\n }\n for (const childName of b.elementNames) {\n const child = model.elements[childName];\n if (child) {\n children.push({\n id: elementId(child.name),\n ...leafSize(child.kind),\n });\n }\n }\n return {\n id: boundaryId(b.name),\n children,\n layoutOptions: containerLayoutOptions,\n };\n };\n\n return {\n id: \"root\",\n layoutOptions: {\n ...layeredOptions,\n // INCLUDE_CHILDREN lets edges cross hierarchy levels — without\n // it `layered` errors on edges that span containers. With\n // edges in the input, ELK has the dependency data it needs to\n // build proper left-to-right layers; otherwise it stacks\n // everything in a single column.\n \"elk.hierarchyHandling\": \"INCLUDE_CHILDREN\",\n },\n children: [\n ...rootBoundaries.map(renderBoundary),\n ...standalone.map((e) => ({\n id: elementId(e.name),\n ...leafSize(e.kind),\n })),\n ],\n edges: [...edges],\n };\n};\n\n/**\n * Resolve a relation endpoint to the deepest visible node id.\n * Walks up the parent chain; if a parent isn't expanded, the\n * collapsed parent becomes the visible endpoint instead.\n */\nconst visibleEndpoint = (\n name: string,\n kindHint: \"element\" | \"boundary\",\n expanded: ReadonlySet<string>,\n parentMap: ReadonlyMap<string, string>,\n): { id: string; kind: \"element\" | \"boundary\"; name: string } => {\n let current = name;\n let kind: \"element\" | \"boundary\" = kindHint;\n for (;;) {\n const parent = parentMap.get(current);\n if (parent === undefined || expanded.has(parent)) {\n return {\n id: kind === \"boundary\" ? boundaryId(current) : elementId(current),\n kind,\n name: current,\n };\n }\n current = parent;\n kind = \"boundary\";\n }\n};\n\ninterface ElkResultNode {\n id: string;\n x?: number;\n y?: number;\n width?: number;\n height?: number;\n children?: readonly ElkResultNode[];\n}\n\n/**\n * Flatten ELK's nested result into Svelte Flow nodes. ELK returns\n * child positions relative to their parent — exactly what\n * `parentId` + `extent: \"parent\"` expects.\n */\nconst flattenElkResult = (\n results: readonly ElkResultNode[],\n model: Model,\n expanded: ReadonlySet<string>,\n parentId: string | undefined,\n): Node[] => {\n const out: Node[] = [];\n for (const r of results) {\n const x = r.x ?? 0;\n const y = r.y ?? 0;\n const width = r.width ?? 0;\n const height = r.height ?? 0;\n const isBoundary = r.id.startsWith(\"b:\");\n const name = r.id.slice(2);\n if (isBoundary) {\n const b = model.boundaries[name];\n if (!b) continue;\n const isExpanded = expanded.has(name);\n const node: Node = {\n id: r.id,\n type: \"boundary\",\n position: { x, y },\n data: boundaryNodeData(b, { expanded: isExpanded, canExpand: true }),\n style: `width: ${width}px; height: ${height}px;`,\n };\n if (parentId) {\n node.parentId = parentId;\n node.extent = \"parent\";\n }\n out.push(node);\n if (isExpanded && r.children?.length) {\n out.push(...flattenElkResult(r.children, model, expanded, r.id));\n }\n } else {\n const el = model.elements[name];\n if (!el) continue;\n const { width: dw, height: dh } = leafSize(el.kind);\n const node: Node = {\n id: r.id,\n type: elementNodeType(el.kind),\n position: { x, y },\n data: elementNodeData(el),\n style: `width: ${width || dw}px; height: ${height || dh}px;`,\n };\n if (parentId) {\n node.parentId = parentId;\n node.extent = \"parent\";\n }\n out.push(node);\n }\n }\n return out;\n};\n\n/**\n * \"Cross-boundary\" is a property of the original relation, not of\n * its visible-endpoint resolution. We compute it from the elements'\n * immediate boundary parents:\n * - both elements share a non-null immediate parent → intra\n * - everything else (different parents, one at root) → cross\n *\n * The flag travels with the edge as `data.crossBoundary` so\n * App.svelte's \"cross-boundary only\" filter can dim intra edges\n * without re-running ELK.\n */\nconst isCrossBoundary = (\n fromName: string,\n toName: string,\n parentMap: ReadonlyMap<string, string>,\n): boolean => {\n const fp = parentMap.get(fromName) ?? null;\n const tp = parentMap.get(toName) ?? null;\n return fp === null || tp === null || fp !== tp;\n};\n\nconst collectVisibleEdges = (\n model: Model,\n expanded: ReadonlySet<string>,\n parentMap: ReadonlyMap<string, string>,\n): Edge[] => {\n const seen = new Map<string, Edge>();\n let index = 0;\n for (const el of Object.values(model.elements)) {\n for (const rel of el.relations) {\n const from = visibleEndpoint(el.name, \"element\", expanded, parentMap);\n const to = visibleEndpoint(rel.to, \"element\", expanded, parentMap);\n if (from.id === to.id) continue;\n const key = `${from.id}->${to.id}`;\n const crossBoundary = isCrossBoundary(el.name, rel.to, parentMap);\n const existing = seen.get(key);\n if (existing) {\n const data = existing.data as\n | {\n readonly crossBoundary?: boolean;\n readonly primaryLabel?: string;\n readonly relationCount?: number;\n }\n | undefined;\n const relationCount = (data?.relationCount ?? 1) + 1;\n seen.set(key, {\n ...existing,\n label: formatEdgeLabel(data?.primaryLabel, relationCount),\n data: {\n ...data,\n crossBoundary: Boolean(data?.crossBoundary) || crossBoundary,\n relationCount,\n },\n });\n continue;\n }\n const primaryLabel =\n from.kind === \"element\" && to.kind === \"element\"\n ? rel.description\n : undefined;\n seen.set(key, {\n id: `edge-${index++}`,\n source: from.id,\n target: to.id,\n label: primaryLabel,\n type: \"default\",\n animated: false,\n data: { crossBoundary, primaryLabel, relationCount: 1 },\n markerEnd: {\n type: MarkerType.ArrowClosed,\n width: 24,\n height: 24,\n color: \"#cbd5e1\",\n },\n style: \"stroke: #94a3b8; stroke-width: 1.8;\",\n });\n }\n }\n return [...seen.values()];\n};\n\nconst collectStandaloneAndRoots = (\n model: Model,\n): { rootBoundaries: Boundary[]; standalone: Element[] } => {\n const rootBoundaries = (model.rootBoundaryNames ?? [])\n .map((n) => model.boundaries[n])\n .filter((b): b is Boundary => Boolean(b));\n const bounded = new Set<string>();\n const walk = (b: Boundary): void => {\n for (const n of b.elementNames) bounded.add(n);\n for (const child of b.boundaryNames) {\n const cb = model.boundaries[child];\n if (cb) walk(cb);\n }\n };\n for (const b of rootBoundaries) walk(b);\n const standalone = Object.values(model.elements).filter(\n (e) => !bounded.has(e.name),\n );\n return { rootBoundaries, standalone };\n};\n\nexport const layoutNested = async (\n model: Model,\n expanded: ReadonlySet<string>,\n): Promise<LayoutResult> => {\n const { rootBoundaries, standalone } = collectStandaloneAndRoots(model);\n const parentMap = buildParentMap(model);\n const edges = collectVisibleEdges(model, expanded, parentMap);\n\n // ELK and Svelte Flow share the same edge identity. ELK uses the\n // edges to compute layers (without them the layered algorithm\n // collapses to a single vertical column); Svelte Flow uses them\n // to render the lines after we hand back the layout result.\n const elkEdges: ElkInputEdge[] = edges.map((e) => ({\n id: e.id,\n sources: [e.source],\n targets: [e.target],\n }));\n\n const tree = buildNestedTree(\n model,\n expanded,\n rootBoundaries,\n standalone,\n elkEdges,\n );\n const result = await runElkLayout<ElkResultNode>(tree);\n const nodes = flattenElkResult(\n result.children ?? [],\n model,\n expanded,\n undefined,\n );\n return { nodes, edges };\n};\n\n/**\n * Flat mode = every boundary in the model is expanded from the\n * start. Use this for a single overview rendering of the full\n * tree (good for print / read-only big-picture view).\n */\nexport const layoutFlat = (model: Model): Promise<LayoutResult> => {\n const everyBoundary = new Set(Object.keys(model.boundaries));\n return layoutNested(model, everyBoundary);\n};\n","<script lang=\"ts\">\n import { setContext } from \"svelte\";\n\n import {\n SvelteFlow,\n SvelteFlowProvider,\n Background,\n Controls,\n MiniMap,\n MarkerType,\n type Node,\n type Edge,\n } from \"@xyflow/svelte\";\n import \"@xyflow/svelte/dist/style.css\";\n\n import BoundaryNode from \"./BoundaryNode.svelte\";\n import DatabaseNode from \"./DatabaseNode.svelte\";\n import ElementNode from \"./ElementNode.svelte\";\n import PersonNode from \"./PersonNode.svelte\";\n import QueueNode from \"./QueueNode.svelte\";\n import {\n layoutFlat,\n layoutNested,\n layoutScope,\n sliceModel,\n } from \"./layout.ts\";\n import type {\n BreadcrumbEntry,\n ChangeAction,\n DiffChange,\n DiffChangeGroup,\n Element,\n Boundary,\n ModelIssue,\n ModelEnvelope,\n Relation,\n ServerMessage,\n ViewError,\n } from \"./types.ts\";\n import { VIEW_ACTIONS, type ViewActions } from \"./actions.ts\";\n\n type ViewMode = \"drill\" | \"expand\" | \"flat\";\n type EdgeStyle = \"bezier\" | \"smoothstep\" | \"step\";\n type EdgeFilter = \"all\" | \"cross-boundary\";\n interface IncomingRelation {\n readonly from: string;\n readonly relation: Relation;\n }\n\n // Persist edge-style + edge-filter + analyze-overlay choices across\n // page reloads — all three are personal preferences with no model\n // coupling, so we bring them back next session instead of resetting.\n const EDGE_STYLE_KEY = \"aact-view:edge-style\";\n const EDGE_FILTER_KEY = \"aact-view:edge-filter\";\n const ANALYZE_KEY = \"aact-view:analyze\";\n const initialEdgeStyle =\n (typeof localStorage !== \"undefined\" &&\n (localStorage.getItem(EDGE_STYLE_KEY) as EdgeStyle | null)) ||\n \"bezier\";\n const initialEdgeFilter =\n (typeof localStorage !== \"undefined\" &&\n (localStorage.getItem(EDGE_FILTER_KEY) as EdgeFilter | null)) ||\n \"all\";\n const initialAnalyzeOn =\n typeof localStorage !== \"undefined\" &&\n localStorage.getItem(ANALYZE_KEY) === \"on\";\n\n let envelope = $state<ModelEnvelope | null>(null);\n let mode = $state<ViewMode>(\"drill\");\n let edgeStyle = $state<EdgeStyle>(initialEdgeStyle);\n let edgeFilter = $state<EdgeFilter>(initialEdgeFilter);\n let analyzeOn = $state<boolean>(initialAnalyzeOn);\n let breadcrumb = $state<BreadcrumbEntry[]>([{ kind: \"landscape\" }]);\n let expanded = $state<Set<string>>(new Set());\n let selected = $state<\n | { kind: \"element\"; name: string }\n | { kind: \"boundary\"; name: string }\n | null\n >(null);\n let hoveredNodeId = $state<string | null>(null);\n let nodes = $state<Node[]>([]);\n let edges = $state<Edge[]>([]);\n let status = $state<\"connecting\" | \"live\" | \"lost\" | \"error\">(\n \"connecting\",\n );\n let loadError = $state<ViewError | null>(null);\n let layoutError = $state<ViewError | null>(null);\n\n const nodeTypes = {\n element: ElementNode,\n person: PersonNode,\n database: DatabaseNode,\n queue: QueueNode,\n boundary: BoundaryNode,\n } as const;\n\n const clientError = (error: unknown): ViewError => ({\n message: error instanceof Error ? error.message : String(error),\n source: envelope?.meta.source ?? null,\n configPath: envelope?.meta.configPath ?? null,\n durationMs: 0,\n at: new Date().toISOString(),\n });\n\n // Re-layout whenever model, mode, breadcrumb, or expanded set\n // changes. Each branch hands a different ELK invocation back the\n // same `{nodes, edges}` shape so the render code stays uniform.\n $effect(() => {\n if (!envelope) return;\n let cancelled = false;\n const run = async (): Promise<void> => {\n if (mode === \"drill\") {\n const scope = sliceModel(envelope!.data.model, breadcrumb);\n const result = await layoutScope(scope);\n if (cancelled) return;\n nodes = result.nodes;\n edges = result.edges;\n } else if (mode === \"expand\") {\n const result = await layoutNested(envelope!.data.model, expanded);\n if (cancelled) return;\n nodes = result.nodes;\n edges = result.edges;\n } else {\n const result = await layoutFlat(envelope!.data.model);\n if (cancelled) return;\n nodes = result.nodes;\n edges = result.edges;\n }\n layoutError = null;\n if (!loadError && status === \"error\") status = \"live\";\n };\n void run().catch((error: unknown) => {\n if (cancelled) return;\n layoutError = clientError(error);\n status = \"error\";\n });\n return () => {\n cancelled = true;\n };\n });\n\n const sessionToken =\n typeof location !== \"undefined\"\n ? new URLSearchParams(location.search).get(\"token\")\n : null;\n\n const withSessionToken = (path: string): string =>\n sessionToken ? `${path}?token=${encodeURIComponent(sessionToken)}` : path;\n\n const fetchModel = async (): Promise<ModelEnvelope> => {\n const res = await fetch(withSessionToken(\"/api/model\"));\n if (!res.ok) throw new Error(`/api/model returned ${res.status}`);\n return (await res.json()) as ModelEnvelope;\n };\n\n let diffAutoModeApplied = $state(false);\n const acceptEnvelope = (env: ModelEnvelope): void => {\n envelope = env;\n if (!diffAutoModeApplied && env.data.diff) {\n mode = \"flat\";\n selected = null;\n breadcrumb = [{ kind: \"landscape\" }];\n diffAutoModeApplied = true;\n }\n };\n\n const wsUrl = (() => {\n const proto = location.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n return `${proto}//${location.host}${withSessionToken(\"/api/ws\")}`;\n })();\n\n const connect = (): void => {\n const ws = new WebSocket(wsUrl);\n ws.addEventListener(\"open\", () => {\n if (!loadError && !layoutError) status = \"live\";\n });\n ws.addEventListener(\"message\", (ev) => {\n try {\n const payload = JSON.parse(ev.data) as ServerMessage;\n if (payload.type === \"model-update\") {\n acceptEnvelope(payload.envelope);\n loadError = null;\n if (!layoutError) status = \"live\";\n }\n if (payload.type === \"model-error\") {\n loadError = payload.error;\n status = \"error\";\n }\n } catch {\n // ignore malformed payloads — server won't emit any\n }\n });\n ws.addEventListener(\"close\", () => {\n status = \"lost\";\n setTimeout(connect, 1000);\n });\n ws.addEventListener(\"error\", () => ws.close());\n };\n\n void fetchModel().then((env) => {\n acceptEnvelope(env);\n loadError = null;\n connect();\n }).catch((error: unknown) => {\n loadError = clientError(error);\n status = \"error\";\n connect();\n });\n\n const onnodeclick = ({ node }: { node: Node }): void => {\n if (node.type === \"boundary\") {\n selected = { kind: \"boundary\", name: String(node.data.name) };\n } else {\n selected = { kind: \"element\", name: String(node.data.name) };\n }\n };\n\n // @xyflow/svelte 1.x exposes pointer events on the SvelteFlow\n // component as callback props. Pointer events fire for both mouse\n // and touch, so they cover the \"trace a relation\" UX better than\n // the deprecated mouse-only equivalents.\n const onnodepointerenter = ({ node }: { node: Node }): void => {\n hoveredNodeId = node.id;\n };\n const onnodepointerleave = (): void => {\n hoveredNodeId = null;\n };\n\n const actions: ViewActions = {\n selectElement: (name) => {\n selected = { kind: \"element\", name };\n },\n selectBoundary: (name) => {\n selected = { kind: \"boundary\", name };\n },\n enterBoundary: (name, label) => {\n // Drill-down only makes sense in Drill mode; in Expand mode\n // this is mapped to \"toggle\" by the BoundaryNode itself.\n if (mode !== \"drill\") return;\n breadcrumb = [...breadcrumb, { kind: \"boundary\", name, label }];\n selected = null;\n },\n toggleBoundary: (name) => {\n if (mode !== \"expand\") return;\n const next = new Set(expanded);\n if (next.has(name)) next.delete(name);\n else next.add(name);\n expanded = next;\n },\n };\n setContext(VIEW_ACTIONS, actions);\n\n const breadcrumbClick = (index: number): void => {\n breadcrumb = breadcrumb.slice(0, index + 1);\n selected = null;\n };\n\n const setMode = (next: ViewMode): void => {\n mode = next;\n // Mode change resets selection / breadcrumb so users don't\n // chase the wrong context when switching strategies.\n selected = null;\n if (next === \"drill\") {\n breadcrumb = [{ kind: \"landscape\" }];\n }\n if (next === \"expand\") {\n expanded = new Set();\n }\n };\n\n const collapseAll = (): void => {\n expanded = new Set();\n };\n const expandAll = (): void => {\n if (!envelope) return;\n expanded = new Set(Object.keys(envelope.data.model.boundaries));\n };\n\n const selectedElement = $derived<Element | null>(\n selected?.kind === \"element\" && envelope\n ? (envelope.data.model.elements[selected.name] ?? null)\n : null,\n );\n const selectedBoundary = $derived<Boundary | null>(\n selected?.kind === \"boundary\" && envelope\n ? (envelope.data.model.boundaries[selected.name] ?? null)\n : null,\n );\n const incomingRelations = $derived<readonly IncomingRelation[]>(\n selectedElement && envelope\n ? Object.values(envelope.data.model.elements).flatMap((el) =>\n el.relations\n .filter((rel) => rel.to === selectedElement.name)\n .map((relation) => ({ from: el.name, relation })),\n )\n : [],\n );\n const selectedIssues = $derived<readonly ModelIssue[]>(\n selected && envelope\n ? envelope.data.issues.filter((issue) =>\n selected.kind === \"element\"\n ? issue.element === selected.name\n : issue.boundary === selected.name,\n )\n : [],\n );\n\n const setEdgeStyle = (next: EdgeStyle): void => {\n edgeStyle = next;\n if (typeof localStorage !== \"undefined\") {\n localStorage.setItem(EDGE_STYLE_KEY, next);\n }\n };\n const setEdgeFilter = (next: EdgeFilter): void => {\n edgeFilter = next;\n if (typeof localStorage !== \"undefined\") {\n localStorage.setItem(EDGE_FILTER_KEY, next);\n }\n };\n const setAnalyze = (next: boolean): void => {\n analyzeOn = next;\n if (typeof localStorage !== \"undefined\") {\n localStorage.setItem(ANALYZE_KEY, next ? \"on\" : \"off\");\n }\n };\n\n /** Set of element names participating in the smallest detected\n * cycle, used by the cycles-overlay to outline nodes + thicken\n * edges. Empty when analyze is off, no cycles exist, or the\n * envelope hasn't loaded yet. */\n const cycleMembers = $derived<Set<string>>(\n analyzeOn && envelope?.data.analysis.cycles.smallest\n ? new Set(envelope.data.analysis.cycles.smallest)\n : new Set(),\n );\n\n const diffData = $derived(envelope?.data.diff?.data ?? null);\n const diffGroups = $derived<readonly DiffChangeGroup[]>(\n diffData?.groups ?? [],\n );\n const topDiffChanges = $derived<readonly DiffChange[]>(\n (diffData?.changes ?? []).slice(0, 10),\n );\n\n /** Whether we're in diff mode — set by the server when the\n * workbench was booted with `aact view --diff <baseline>`. */\n const diffMode = $derived<boolean>(diffData !== null);\n\n /** Element-name → diff status. Only entries for elements that\n * changed; unchanged elements are not in the map. Both `added` and\n * `renamed` keys land here under the *current* name (so the graph\n * node renders coloured); `removed` keys carry the baseline name\n * and stay visible in the sidebar list. */\n const elementDiffStatus = $derived.by<Map<string, ChangeAction>>(() => {\n const out = new Map<string, ChangeAction>();\n for (const change of diffData?.changes ?? []) {\n if (change.entity !== \"element\") continue;\n out.set(change.name, change.action);\n }\n return out;\n });\n\n /** Boundary-name → diff status. Same pattern as `elementDiffStatus`\n * but for boundary nodes (Bounded Contexts). */\n const boundaryDiffStatus = $derived.by<Map<string, ChangeAction>>(() => {\n const out = new Map<string, ChangeAction>();\n for (const change of diffData?.changes ?? []) {\n if (change.entity !== \"boundary\") continue;\n out.set(change.name, change.action);\n }\n return out;\n });\n\n const relationDiffKey = (from: string, to: string): string => `${from}->${to}`;\n\n /** Relation address (`from->to`) → diff status. Edges use this to\n * pick up the status colour without re-walking the diff every\n * render. Address includes technology only when relations are\n * multiset-distinguished by it; we drop the tech qualifier here\n * because the edge model in the graph already collapses by\n * `(from, to)`. */\n const relationDiffStatus = $derived.by<Map<string, ChangeAction>>(() => {\n const out = new Map<string, ChangeAction>();\n for (const change of diffData?.changes ?? []) {\n if (change.entity !== \"relation\") continue;\n out.set(relationDiffKey(change.from, change.to), change.action);\n }\n return out;\n });\n\n /** Colour mapping for diff status overlays. Tied to the bordering\n * style in `decoratedNodes` / `decoratedEdges` below — keep in\n * sync with the visual key shown next to the diff banner. */\n // Desaturated diff palette derived from Zed's One Dark token set —\n // each hue is paired with a glyph (see diffGlyph) so the signal\n // survives colour-blindness and dark-mode shifts.\n const DIFF_COLOR: Readonly<Record<ChangeAction, string>> = {\n added: \"#a1c181\",\n removed: \"#d07277\",\n modified: \"#dec184\",\n renamed: \"#7dd3fc\",\n moved: \"#b6a4d7\",\n };\n\n const diffGlyph = (action: ChangeAction): string => {\n switch (action) {\n case \"added\":\n return \"+\";\n case \"removed\":\n return \"−\";\n case \"modified\":\n return \"~\";\n case \"renamed\":\n return \"↦\";\n case \"moved\":\n return \"⇄\";\n }\n };\n\n const nodeDiffStatus = (node: Node): ChangeAction | undefined => {\n const name = node.id.slice(2);\n if (node.id.startsWith(\"e:\")) return elementDiffStatus.get(name);\n if (node.id.startsWith(\"b:\")) return boundaryDiffStatus.get(name);\n return undefined;\n };\n\n const edgeDiffStatus = (edge: Edge): ChangeAction | undefined => {\n if (!edge.source.startsWith(\"e:\") || !edge.target.startsWith(\"e:\")) {\n return undefined;\n }\n return relationDiffStatus.get(\n relationDiffKey(edge.source.slice(2), edge.target.slice(2)),\n );\n };\n\n const evidenceString = (value: unknown): string | null =>\n typeof value === \"string\" && value.length > 0 ? value : null;\n\n const groupSubtitle = (group: DiffChangeGroup): string => {\n const ev = group.evidence ?? {};\n const service = evidenceString(ev.service);\n const repository = evidenceString(ev.repository);\n const database = evidenceString(ev.database);\n if (service && repository && database) {\n return `${service} → ${repository} → ${database}`;\n }\n const from = evidenceString(ev.from);\n const to = evidenceString(ev.to);\n const before = evidenceString(ev.before);\n const after = evidenceString(ev.after);\n if (from && to && before && after) {\n return `${from} → ${to}: ${before} → ${after}`;\n }\n return `${group.changeAddresses.length} change${group.changeAddresses.length === 1 ? \"\" : \"s\"}`;\n };\n\n const changeTitle = (change: DiffChange): string => {\n switch (change.entity) {\n case \"element\":\n return `${change.name}${change.previousName ? ` ← ${change.previousName}` : \"\"}`;\n case \"boundary\":\n return `${change.name}${change.previousName ? ` ← ${change.previousName}` : \"\"}`;\n case \"relation\":\n return `${change.from} → ${change.to}`;\n case \"workspace\":\n return \"workspace\";\n }\n };\n\n const changeSubtitle = (change: DiffChange): string =>\n change.fields.length\n ? change.fields.map((f) => f.field).join(\", \")\n : change.severity;\n\n // Dim edges that aren't incident to the hovered node so the user\n // can trace a single dependency through a crowded canvas. Strip\n // labels from non-incident edges as well — at 30+ relations the\n // label chips pile up faster than the lines do. Re-write\n // markerEnd color explicitly because SVG markers don't inherit\n // `stroke` from the referencing path. Override `type` so the\n // topbar style toggle applies to every edge without re-running\n // ELK.\n const isCross = (e: Edge): boolean =>\n Boolean((e.data as { crossBoundary?: boolean } | undefined)?.crossBoundary);\n\n /** Decorate nodes with overlays. Diff-mode status wins over cycle\n * highlight when both apply (diff is the user's primary signal —\n * they booted with `--diff`); analyze-mode cycle highlight applies\n * when the node isn't already diff-coloured. Reactive Flow's node\n * `style` field accepts CSS as a string. */\n const decoratedNodes = $derived<Node[]>(\n nodes.map((n) => {\n const existingStyle = typeof n.style === \"string\" ? n.style : \"\";\n const diffStatus = nodeDiffStatus(n);\n if (diffStatus) {\n const color = DIFF_COLOR[diffStatus];\n return {\n ...n,\n data: {\n ...(n.data as Record<string, unknown> | undefined),\n diffAction: diffStatus,\n },\n style: `${existingStyle} outline: 3px solid ${color}; outline-offset: 5px; border-radius: 8px;`,\n };\n }\n if (cycleMembers.has(n.id)) {\n return {\n ...n,\n style: `${existingStyle} box-shadow: 0 0 0 3px #ef4444; border-radius: 8px;`,\n };\n }\n return n;\n }),\n );\n\n const decoratedEdges = $derived<Edge[]>(\n edges.map((e) => {\n const incident =\n hoveredNodeId !== null &&\n (e.source === hoveredNodeId || e.target === hoveredNodeId);\n const filterActive = edgeFilter === \"cross-boundary\";\n const cross = isCross(e);\n const intraInFilter = filterActive && !cross;\n const crossInFilter = filterActive && cross;\n const inCycle =\n cycleMembers.has(e.source) && cycleMembers.has(e.target);\n const diffStatus = edgeDiffStatus(e);\n\n // Diff status wins when present — the user booted with `--diff`\n // explicitly to spot architecture deltas. Hover/filter still\n // takes over for incident edges so dependency tracing keeps\n // working when the user wants to inspect a specific node.\n if (diffStatus && !incident) {\n const color = DIFF_COLOR[diffStatus];\n return {\n ...e,\n type: edgeStyle,\n animated: diffStatus !== \"removed\",\n data: {\n ...(e.data as Record<string, unknown> | undefined),\n diffAction: diffStatus,\n },\n style: `stroke: ${color}; stroke-width: 2.8; opacity: 1;`,\n markerEnd: {\n type: MarkerType.ArrowClosed,\n width: 26,\n height: 26,\n color,\n },\n };\n }\n\n // Cycle edges win over filter/hover decoration — distributed\n // monolith is the top signal the user toggled Analyze to spot.\n if (inCycle && !incident) {\n return {\n ...e,\n type: edgeStyle,\n animated: false,\n style: \"stroke: #ef4444; stroke-width: 2.4; opacity: 1;\",\n markerEnd: {\n type: MarkerType.ArrowClosed,\n width: 24,\n height: 24,\n color: \"#ef4444\",\n },\n };\n }\n\n // Filter overrides default rendering: intra disappears almost\n // entirely, cross gets thicker bright stroke so it visibly\n // \"lights up\" as the interesting subgraph. Hover still wins\n // for incident edges so dependency tracing keeps working.\n if (intraInFilter && !incident) {\n return {\n ...e,\n type: edgeStyle,\n animated: false,\n label: undefined,\n style: \"stroke: #1e293b; stroke-width: 0.8; opacity: 0.12;\",\n markerEnd: {\n type: MarkerType.ArrowClosed,\n width: 16,\n height: 16,\n color: \"#1e293b\",\n },\n };\n }\n if (crossInFilter && !hoveredNodeId) {\n return {\n ...e,\n type: edgeStyle,\n animated: false,\n style: \"stroke: #38bdf8; stroke-width: 2.2; opacity: 1;\",\n markerEnd: {\n type: MarkerType.ArrowClosed,\n width: 26,\n height: 26,\n color: \"#38bdf8\",\n },\n };\n }\n if (!hoveredNodeId) {\n return { ...e, type: edgeStyle };\n }\n const color = incident ? \"#38bdf8\" : \"#475569\";\n return {\n ...e,\n type: edgeStyle,\n animated: incident,\n label: incident ? e.label : undefined,\n style: incident\n ? \"stroke: #38bdf8; stroke-width: 2.4; opacity: 1;\"\n : \"stroke: #475569; stroke-width: 1.2; opacity: 0.35;\",\n markerEnd: {\n type: MarkerType.ArrowClosed,\n width: 24,\n height: 24,\n color,\n },\n };\n }),\n );\n\n const summary = $derived<{\n elements: number;\n boundaries: number;\n relations: number;\n issues: number;\n } | null>(\n envelope\n ? {\n elements: Object.keys(envelope.data.model.elements).length,\n boundaries: Object.keys(envelope.data.model.boundaries).length,\n relations: Object.values(envelope.data.model.elements).reduce(\n (acc, el) => acc + el.relations.length,\n 0,\n ),\n issues: envelope.data.issues.length,\n }\n : null,\n );\n const activeError = $derived<ViewError | null>(loadError ?? layoutError);\n const activeErrorTitle = $derived<string>(\n loadError ? \"Reload failed\" : \"Layout failed\",\n );\n\n // Translate a SourceLocation into a deep link the OS knows. Vendor\n // schemes match aact's CLI link format so the IDE the user already\n // configured for `aact check` handles the click here too.\n const sourceUrl = (\n file: string,\n line: number,\n col: number,\n ): string => {\n const opener =\n (typeof window !== \"undefined\" &&\n (window as { __AACT_OPENER__?: string }).__AACT_OPENER__) ||\n \"vscode\";\n const encodedFile = file\n .split(\"/\")\n .map((segment) => encodeURIComponent(segment))\n .join(\"/\");\n return `${opener}://file/${encodedFile}:${line}:${col}`;\n };\n\n const propertyEntries = (\n properties: Readonly<Record<string, string>> | undefined,\n ): readonly (readonly [string, string])[] => Object.entries(properties ?? {});\n\n const issueMessage = (issue: ModelIssue): string =>\n issue.message ? `${issue.kind}: ${issue.message}` : issue.kind;\n\n const minimapNodeColor = (node: Node): string => {\n const diffAction = (node.data as { diffAction?: ChangeAction } | undefined)\n ?.diffAction;\n if (diffAction) return DIFF_COLOR[diffAction];\n const kind = String((node.data as { kind?: string } | undefined)?.kind);\n const external = Boolean(\n (node.data as { external?: boolean } | undefined)?.external,\n );\n if (node.type === \"person\") return \"#08427b\";\n if (external) return \"#475569\";\n if (kind === \"System\") return \"#1168bd\";\n if (kind === \"Container\") return \"#438dd5\";\n if (kind === \"Component\") return \"#85bbf0\";\n return \"#64748b\";\n };\n</script>\n\n<svelte:head>\n <title>aact view</title>\n</svelte:head>\n\n<div class=\"app\">\n <header class=\"topbar\">\n <div class=\"brand\">\n <span class=\"logo\">aact</span>\n <span class=\"sep\" aria-hidden=\"true\">·</span>\n <span class=\"title\">view</span>\n {#if envelope?.data.model.workspace?.name}\n <span class=\"sep\" aria-hidden=\"true\">·</span>\n <span class=\"workspace\" title={envelope.data.model.workspace.description ?? \"\"}>\n {envelope.data.model.workspace.name}\n </span>\n {/if}\n <span class=\"status status-{status}\">\n {#if status === \"live\"}● live\n {:else if status === \"error\"}● reload error\n {:else if status === \"lost\"}● disconnected — retrying\n {:else}● connecting\n {/if}\n </span>\n {#if diffMode && envelope?.data.diff}\n <span class=\"sep\" aria-hidden=\"true\">·</span>\n <span class=\"diff-pill\" title={envelope.data.diff.data.summary.headline}>\n diff: {envelope.data.diff.data.summary.headline}\n </span>\n {/if}\n </div>\n\n <div class=\"topbar-controls\">\n <div class=\"modes\" role=\"tablist\" aria-label=\"View mode\">\n <button\n role=\"tab\"\n class:active={mode === \"drill\"}\n aria-selected={mode === \"drill\"}\n onclick={() => setMode(\"drill\")}\n title=\"Replace the canvas with the boundary you double-click\"\n >Drill</button>\n <button\n role=\"tab\"\n class:active={mode === \"expand\"}\n aria-selected={mode === \"expand\"}\n onclick={() => setMode(\"expand\")}\n title=\"Open boundaries inline — parents stay visible\"\n >Expand</button>\n <button\n role=\"tab\"\n class:active={mode === \"flat\"}\n aria-selected={mode === \"flat\"}\n onclick={() => setMode(\"flat\")}\n title=\"Render every level of the hierarchy at once\"\n >Flat</button>\n </div>\n <div class=\"modes edge-modes\" role=\"tablist\" aria-label=\"Edge style\">\n <button\n role=\"tab\"\n class:active={edgeStyle === \"bezier\"}\n aria-selected={edgeStyle === \"bezier\"}\n onclick={() => setEdgeStyle(\"bezier\")}\n title=\"Smooth bezier curves\"\n >Curve</button>\n <button\n role=\"tab\"\n class:active={edgeStyle === \"smoothstep\"}\n aria-selected={edgeStyle === \"smoothstep\"}\n onclick={() => setEdgeStyle(\"smoothstep\")}\n title=\"Rounded 90° corners — Structurizr-style\"\n >Smooth</button>\n <button\n role=\"tab\"\n class:active={edgeStyle === \"step\"}\n aria-selected={edgeStyle === \"step\"}\n onclick={() => setEdgeStyle(\"step\")}\n title=\"Sharp 90° corners\"\n >Step</button>\n </div>\n <div class=\"modes edge-modes\" role=\"tablist\" aria-label=\"Edge filter\">\n <button\n role=\"tab\"\n class:active={edgeFilter === \"all\"}\n aria-selected={edgeFilter === \"all\"}\n onclick={() => setEdgeFilter(\"all\")}\n title=\"Show every relation\"\n >All</button>\n <button\n role=\"tab\"\n class:active={edgeFilter === \"cross-boundary\"}\n aria-selected={edgeFilter === \"cross-boundary\"}\n onclick={() => setEdgeFilter(\"cross-boundary\")}\n title=\"Highlight relations that cross a Bounded Context; intra-boundary stays faint\"\n >Cross-BC</button>\n </div>\n <div class=\"modes analyze-toggle\" role=\"tablist\" aria-label=\"Analyze overlay\">\n <button\n role=\"tab\"\n class:active={analyzeOn}\n aria-selected={analyzeOn}\n onclick={() => setAnalyze(!analyzeOn)}\n title=\"Highlight cycles on the graph and show architecture metrics in the sidebar\"\n >Analyze</button>\n </div>\n </div>\n\n <div class=\"context\">\n {#if mode === \"drill\"}\n <nav class=\"breadcrumb\" aria-label=\"Drill path\">\n {#each breadcrumb as crumb, i (i)}\n {#if i > 0}<span class=\"bsep\" aria-hidden=\"true\">/</span>{/if}\n <button class=\"bcrumb\" onclick={() => breadcrumbClick(i)}>\n {crumb.kind === \"landscape\" ? \"Landscape\" : crumb.label}\n </button>\n {/each}\n </nav>\n {:else if mode === \"expand\"}\n <div class=\"expand-controls\">\n <button class=\"ghost\" onclick={expandAll}>Expand all</button>\n <button class=\"ghost\" onclick={collapseAll}>Collapse all</button>\n <span class=\"hint\">double-click a boundary to toggle</span>\n </div>\n {:else}\n <span class=\"hint\">full hierarchy — read-only overview</span>\n {/if}\n </div>\n </header>\n\n <main>\n <div class=\"graph\">\n <SvelteFlowProvider>\n <SvelteFlow\n nodes={decoratedNodes}\n edges={decoratedEdges}\n {nodeTypes}\n {onnodeclick}\n {onnodepointerenter}\n {onnodepointerleave}\n fitView\n fitViewOptions={{ padding: 0.18, duration: 400 }}\n nodesDraggable={false}\n nodesConnectable={false}\n elementsSelectable\n panOnDrag\n zoomOnDoubleClick={false}\n minZoom={0.1}\n maxZoom={2}\n defaultEdgeOptions={{ type: edgeStyle, animated: false }}\n >\n <Background />\n <Controls />\n <MiniMap\n pannable\n zoomable\n nodeColor={minimapNodeColor}\n maskColor=\"rgba(15, 23, 42, 0.7)\"\n style=\"background: #0b1220;\"\n />\n </SvelteFlow>\n </SvelteFlowProvider>\n\n <aside class=\"legend\" aria-label=\"C4 element palette\">\n <span class=\"legend-row\"><span class=\"swatch\" style=\"background: #08427b;\"></span>Person</span>\n <span class=\"legend-row\"><span class=\"swatch\" style=\"background: #1168bd;\"></span>System</span>\n <span class=\"legend-row\"><span class=\"swatch\" style=\"background: #438dd5;\"></span>Container</span>\n <span class=\"legend-row\"><span class=\"swatch\" style=\"background: #85bbf0;\"></span>Component</span>\n <span class=\"legend-row\"><span class=\"swatch\" style=\"background: #475569;\"></span>External</span>\n {#if diffMode}\n <span class=\"legend-rule\"></span>\n <span class=\"legend-row\"><span class=\"swatch\" style=\"background: #a1c181;\"></span>Added</span>\n <span class=\"legend-row\"><span class=\"swatch\" style=\"background: #dec184;\"></span>Modified</span>\n <span class=\"legend-row\"><span class=\"swatch\" style=\"background: #d07277;\"></span>Removed</span>\n <span class=\"legend-row\"><span class=\"swatch\" style=\"background: #7dd3fc;\"></span>Renamed</span>\n <span class=\"legend-row\"><span class=\"swatch\" style=\"background: #b6a4d7;\"></span>Moved</span>\n {/if}\n </aside>\n\n {#if activeError}\n <aside class=\"error-overlay\" role=\"status\" aria-live=\"polite\">\n <span class=\"error-kicker\">{activeErrorTitle}</span>\n <p>{activeError.message}</p>\n <div class=\"error-meta\">\n {#if activeError.source}<span>{activeError.source}</span>{/if}\n <span>{new Date(activeError.at).toLocaleTimeString()}</span>\n {#if activeError.durationMs > 0}<span>{activeError.durationMs} ms</span>{/if}\n </div>\n </aside>\n {/if}\n </div>\n\n <aside class=\"details\">\n {#if selectedElement}\n <h2>{selectedElement.kind}{selectedElement.external ? \" · external\" : \"\"}</h2>\n <h3 class=\"title\">{selectedElement.label}</h3>\n {#if selectedElement.technology}\n <p class=\"tech\">[{selectedElement.technology}]</p>\n {/if}\n {#if selectedElement.description}\n <p class=\"desc\">{selectedElement.description}</p>\n {/if}\n {#if selectedElement.tags.length}\n <div class=\"field\">\n <span class=\"k\">tags</span>\n <span class=\"v\">\n {#each selectedElement.tags as t (t)}\n <span class=\"tag\">{t}</span>\n {/each}\n </span>\n </div>\n {/if}\n {#if propertyEntries(selectedElement.properties).length}\n <div class=\"field\">\n <span class=\"k\">props</span>\n <span class=\"v props\">\n {#each propertyEntries(selectedElement.properties) as [key, value] (key)}\n <span class=\"prop\"><span class=\"prop-key\">{key}</span>{value}</span>\n {/each}\n </span>\n </div>\n {/if}\n {#if selectedElement.sourceLocation}\n <div class=\"field\">\n <span class=\"k\">source</span>\n <span class=\"v\">\n <a href={sourceUrl(selectedElement.sourceLocation.file, selectedElement.sourceLocation.start.line, selectedElement.sourceLocation.start.col)}>\n {selectedElement.sourceLocation.file.split(\"/\").pop()}:{selectedElement.sourceLocation.start.line}:{selectedElement.sourceLocation.start.col}\n </a>\n </span>\n </div>\n {/if}\n {#if selectedIssues.length}\n <h4>Issues</h4>\n <ul class=\"issues\">\n {#each selectedIssues as issue, i (i)}\n <li>{issueMessage(issue)}</li>\n {/each}\n </ul>\n {/if}\n {#if selectedElement.relations.length}\n <h4>Outgoing relations</h4>\n <ul class=\"relations\">\n {#each selectedElement.relations as rel, i (i)}\n <li>\n <span class=\"arrow\">→</span>\n <span class=\"to\">{rel.to}</span>\n {#if rel.description}<span class=\"rdesc\">{rel.description}</span>{/if}\n {#if rel.technology}<span class=\"rmeta\">[{rel.technology}]</span>{/if}\n </li>\n {/each}\n </ul>\n {/if}\n {#if incomingRelations.length}\n <h4>Incoming relations</h4>\n <ul class=\"relations\">\n {#each incomingRelations as item, i (i)}\n <li>\n <span class=\"arrow\">←</span>\n <span class=\"to\">{item.from}</span>\n {#if item.relation.description}<span class=\"rdesc\">{item.relation.description}</span>{/if}\n {#if item.relation.technology}<span class=\"rmeta\">[{item.relation.technology}]</span>{/if}\n </li>\n {/each}\n </ul>\n {/if}\n {:else if selectedBoundary}\n <h2>{selectedBoundary.kind} boundary</h2>\n <h3 class=\"title\">{selectedBoundary.label}</h3>\n {#if selectedBoundary.description}\n <p class=\"desc\">{selectedBoundary.description}</p>\n {/if}\n <div class=\"field\">\n <span class=\"k\">children</span>\n <span class=\"v\">{selectedBoundary.elementNames.length} elements · {selectedBoundary.boundaryNames.length} boundaries</span>\n </div>\n {#if selectedBoundary.tags.length}\n <div class=\"field\">\n <span class=\"k\">tags</span>\n <span class=\"v\">\n {#each selectedBoundary.tags as t (t)}\n <span class=\"tag\">{t}</span>\n {/each}\n </span>\n </div>\n {/if}\n {#if propertyEntries(selectedBoundary.properties).length}\n <div class=\"field\">\n <span class=\"k\">props</span>\n <span class=\"v props\">\n {#each propertyEntries(selectedBoundary.properties) as [key, value] (key)}\n <span class=\"prop\"><span class=\"prop-key\">{key}</span>{value}</span>\n {/each}\n </span>\n </div>\n {/if}\n {#if selectedBoundary.sourceLocation}\n <div class=\"field\">\n <span class=\"k\">source</span>\n <span class=\"v\">\n <a href={sourceUrl(selectedBoundary.sourceLocation.file, selectedBoundary.sourceLocation.start.line, selectedBoundary.sourceLocation.start.col)}>\n {selectedBoundary.sourceLocation.file.split(\"/\").pop()}:{selectedBoundary.sourceLocation.start.line}:{selectedBoundary.sourceLocation.start.col}\n </a>\n </span>\n </div>\n {/if}\n {#if selectedIssues.length}\n <h4>Issues</h4>\n <ul class=\"issues\">\n {#each selectedIssues as issue, i (i)}\n <li>{issueMessage(issue)}</li>\n {/each}\n </ul>\n {/if}\n <p class=\"hint\">\n {#if mode === \"drill\"}Double-click to enter this boundary.\n {:else if mode === \"expand\"}Double-click to {expanded.has(selectedBoundary.name) ? \"collapse\" : \"expand\"} this boundary.\n {:else}This boundary is part of the full hierarchy.\n {/if}\n </p>\n {:else if diffData}\n <h4>Diff</h4>\n <p class=\"diff-headline\">{diffData.summary.headline}</p>\n <dl class=\"info-line\">\n <div><dt>structural</dt><dd>{diffData.summary.bySeverity.structural}</dd></div>\n <div><dt>semantic</dt><dd>{diffData.summary.bySeverity.semantic}</dd></div>\n <div><dt>cosmetic</dt><dd>{diffData.summary.bySeverity.cosmetic}</dd></div>\n <div><dt>total</dt><dd>{diffData.changes.length}</dd></div>\n </dl>\n {#if diffGroups.length}\n <h4>Groups</h4>\n <ul class=\"change-list\">\n {#each diffGroups as group (group.id)}\n <li class=\"change-row\" style=\"border-left-color: #38bdf8;\">\n <span class=\"change-title\">{group.title}</span>\n <span class=\"change-subtitle\">{groupSubtitle(group)} · {Math.round(group.confidence * 100)}% confidence</span>\n </li>\n {/each}\n </ul>\n {/if}\n {#if topDiffChanges.length}\n <h4>Changes</h4>\n <ul class=\"change-list\">\n {#each topDiffChanges as change (change.address)}\n <li class=\"change-row\" style={`border-left-color: ${DIFF_COLOR[change.action]};`}>\n <span class=\"change-title\"><span class=\"change-glyph\" style={`color: ${DIFF_COLOR[change.action]};`}>{diffGlyph(change.action)}</span> {changeTitle(change)}</span>\n <span class=\"change-subtitle\">{change.entity} · {changeSubtitle(change)}</span>\n </li>\n {/each}\n </ul>\n {/if}\n {:else if analyzeOn && envelope}\n {@const a = envelope.data.analysis}\n <h4>Metrics</h4>\n <dl class=\"info-line\">\n <div><dt>elements</dt><dd>{a.elementsCount}</dd></div>\n <div><dt>databases</dt><dd>{a.databases.count}</dd></div>\n <div><dt>relations</dt><dd>{a.relationsByStyle.sync + a.relationsByStyle.async + a.relationsByStyle.unspecified}</dd></div>\n {#if a.cycles.count > 0}\n <div class=\"warn\"><dt>cycles</dt><dd>{a.cycles.count}</dd></div>\n {/if}\n </dl>\n {#if Object.keys(a.elementsByKind).length}\n <h4>By kind</h4>\n <ul class=\"metrics\">\n {#each Object.entries(a.elementsByKind).sort((x, y) => x[0].localeCompare(y[0])) as [kind, count] (kind)}\n <li><span class=\"k\">{kind}</span><span class=\"v\">{count}</span></li>\n {/each}\n </ul>\n {/if}\n <h4>Relations by style</h4>\n <ul class=\"metrics\">\n <li><span class=\"k\">sync</span><span class=\"v\">{a.relationsByStyle.sync}</span></li>\n <li><span class=\"k\">async</span><span class=\"v\">{a.relationsByStyle.async}</span></li>\n <li><span class=\"k\">unspecified</span><span class=\"v\">{a.relationsByStyle.unspecified}</span></li>\n </ul>\n {#if a.cycles.count > 0 && a.cycles.smallest}\n <h4 class=\"warn-h\">Cycles</h4>\n <p class=\"cycle-list\">\n <span class=\"cycle-trail\">{a.cycles.smallest.join(\" → \")}</span>\n </p>\n {/if}\n {#if a.fanOut.length}\n <h4>Top fan-out</h4>\n <ul class=\"metrics\">\n {#each a.fanOut as it (it.name)}\n <li><span class=\"k\">{it.name}</span><span class=\"v\">{it.count}</span></li>\n {/each}\n </ul>\n {/if}\n {#if a.fanIn.length}\n <h4>Top fan-in</h4>\n <ul class=\"metrics\">\n {#each a.fanIn as it (it.name)}\n <li><span class=\"k\">{it.name}</span><span class=\"v\">{it.count}</span></li>\n {/each}\n </ul>\n {/if}\n {:else if envelope?.data.model.workspace}\n <h4>Workspace</h4>\n <h3 class=\"title\">{envelope.data.model.workspace.name ?? \"(unnamed)\"}</h3>\n {#if envelope.data.model.workspace.description}\n <p class=\"desc\">{envelope.data.model.workspace.description}</p>\n {/if}\n {#if summary}\n <dl class=\"info-line\">\n <div><dt>elements</dt><dd>{summary.elements}</dd></div>\n <div><dt>boundaries</dt><dd>{summary.boundaries}</dd></div>\n <div><dt>relations</dt><dd>{summary.relations}</dd></div>\n {#if summary.issues > 0}\n <div class=\"warn\"><dt>issues</dt><dd>{summary.issues}</dd></div>\n {/if}\n </dl>\n {/if}\n {#if envelope.data.issues.length}\n <h4>Loader issues</h4>\n <ul class=\"issues\">\n {#each envelope.data.issues as issue, i (i)}\n <li>{issueMessage(issue)}</li>\n {/each}\n </ul>\n {/if}\n {:else}\n <p class=\"hint\">Loading model…</p>\n {/if}\n </aside>\n </main>\n</div>\n\n<style>\n :global(html, body) {\n margin: 0;\n height: 100%;\n background: #0b1220;\n color: #e2e8f0;\n font-family:\n -apple-system, BlinkMacSystemFont, \"Segoe UI\", Inter, Roboto, sans-serif;\n }\n :global(body) {\n overflow: hidden;\n }\n .app {\n display: grid;\n grid-template-rows: auto 1fr;\n height: 100vh;\n }\n .topbar {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n align-items: center;\n gap: 16px;\n padding: 8px 14px;\n background: #0d1424;\n border-bottom: 1px solid rgba(148, 163, 184, 0.10);\n }\n .brand {\n display: flex;\n align-items: baseline;\n gap: 8px;\n min-width: 0;\n }\n .logo {\n font-size: 13px;\n font-weight: 700;\n letter-spacing: -0.01em;\n color: #f8fafc;\n }\n .title {\n font-size: 12px;\n color: #64748b;\n font-weight: 500;\n letter-spacing: 0.01em;\n }\n .workspace {\n font-size: 12px;\n color: #cbd5e1;\n font-weight: 500;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 340px;\n }\n .sep {\n color: #334155;\n font-size: 10px;\n }\n .status {\n font-size: 10.5px;\n margin-left: 4px;\n color: #64748b;\n font-feature-settings: \"tnum\";\n letter-spacing: 0.02em;\n }\n .status-live {\n color: #34d399;\n }\n .status-lost {\n color: #f87171;\n }\n .status-error {\n color: #fbbf24;\n }\n .diff-pill {\n display: inline-block;\n max-width: 360px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 11px;\n font-weight: 600;\n color: #fbbf24;\n letter-spacing: 0.01em;\n }\n .topbar-controls {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n }\n .modes {\n display: inline-flex;\n background: transparent;\n border: 1px solid rgba(148, 163, 184, 0.14);\n border-radius: 5px;\n padding: 0;\n overflow: hidden;\n }\n .modes button + button {\n border-left: 1px solid rgba(148, 163, 184, 0.10);\n }\n .edge-modes button {\n padding: 5px 10px;\n font-size: 11px;\n }\n .modes button {\n appearance: none;\n border: 0;\n background: transparent;\n color: #94a3b8;\n padding: 5px 12px;\n font-size: 11.5px;\n font-weight: 500;\n border-radius: 0;\n cursor: pointer;\n letter-spacing: 0.01em;\n transition: background 80ms ease, color 80ms ease;\n }\n .modes button:hover {\n background: rgba(255, 255, 255, 0.03);\n color: #e2e8f0;\n }\n .modes button.active {\n background: rgba(56, 189, 248, 0.12);\n color: #7dd3fc;\n }\n .context {\n justify-self: end;\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 12px;\n min-width: 0;\n }\n .breadcrumb {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-wrap: wrap;\n }\n .bcrumb {\n appearance: none;\n border: 0;\n background: transparent;\n color: #7dd3fc;\n cursor: pointer;\n font-size: 11.5px;\n padding: 2px 5px;\n border-radius: 3px;\n letter-spacing: 0.01em;\n }\n .bcrumb:hover {\n background: rgba(56, 189, 248, 0.08);\n }\n .bsep {\n color: #334155;\n }\n .expand-controls {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n .ghost {\n appearance: none;\n border: 1px solid rgba(148, 163, 184, 0.14);\n background: transparent;\n color: #cbd5e1;\n padding: 4px 10px;\n border-radius: 4px;\n font-size: 11px;\n font-weight: 500;\n cursor: pointer;\n letter-spacing: 0.01em;\n transition: background 80ms ease, color 80ms ease;\n }\n .ghost:hover {\n background: rgba(255, 255, 255, 0.04);\n color: #f8fafc;\n }\n .hint {\n color: #64748b;\n font-size: 10.5px;\n letter-spacing: 0.01em;\n }\n\n main {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 360px;\n background: #0b1220;\n overflow: hidden;\n }\n .graph {\n background: #0b1220;\n overflow: hidden;\n position: relative;\n }\n .details {\n overflow: auto;\n }\n\n .legend {\n position: absolute;\n bottom: 14px;\n left: 14px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding: 8px 10px;\n background: #0d1424;\n border: 1px solid rgba(148, 163, 184, 0.14);\n border-radius: 4px;\n font-size: 11px;\n color: #cbd5e1;\n z-index: 4;\n letter-spacing: 0.01em;\n }\n .legend-row {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n .swatch {\n width: 10px;\n height: 10px;\n border-radius: 2px;\n }\n .legend-rule {\n display: block;\n height: 1px;\n margin: 4px 0;\n background: rgba(148, 163, 184, 0.10);\n }\n .error-overlay {\n position: absolute;\n top: 18px;\n left: 18px;\n z-index: 5;\n max-width: min(520px, calc(100% - 36px));\n padding: 14px 16px;\n border-radius: 8px;\n border: 1px solid #b45309;\n background: rgba(69, 26, 3, 0.92);\n box-shadow: 0 18px 50px -28px rgba(0, 0, 0, 0.8);\n backdrop-filter: blur(6px);\n }\n .error-kicker {\n display: block;\n margin-bottom: 6px;\n font-size: 10px;\n font-weight: 800;\n letter-spacing: 0.14em;\n text-transform: uppercase;\n color: #fbbf24;\n }\n .error-overlay p {\n margin: 0;\n color: #fff7ed;\n font-size: 13px;\n line-height: 1.4;\n overflow-wrap: anywhere;\n }\n .error-meta {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n margin-top: 8px;\n font-size: 10px;\n color: #fed7aa;\n }\n\n .details {\n padding: 16px 18px 20px;\n overflow: auto;\n background: #0d1424;\n border-left: 1px solid rgba(148, 163, 184, 0.10);\n }\n .details h2 {\n margin: 0 0 6px;\n font-size: 10.5px;\n font-weight: 500;\n letter-spacing: 0.10em;\n text-transform: uppercase;\n color: #64748b;\n }\n .details h3 {\n margin: 2px 0 12px;\n font-size: 15px;\n font-weight: 600;\n line-height: 1.25;\n color: #f8fafc;\n letter-spacing: -0.005em;\n }\n .details h4 {\n margin: 16px 0 6px;\n font-size: 10.5px;\n font-weight: 500;\n letter-spacing: 0.10em;\n text-transform: uppercase;\n color: #64748b;\n }\n .tech {\n margin: 0 0 10px;\n font-size: 12px;\n font-style: italic;\n color: #94a3b8;\n }\n .desc {\n margin: 0 0 14px;\n font-size: 13px;\n line-height: 1.45;\n color: #cbd5e1;\n }\n .field {\n display: flex;\n gap: 8px;\n margin-bottom: 6px;\n font-size: 12px;\n color: #cbd5e1;\n }\n .field .k {\n color: #64748b;\n min-width: 70px;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n font-size: 10px;\n padding-top: 2px;\n }\n .field a {\n color: #38bdf8;\n text-decoration: none;\n }\n .field a:hover {\n text-decoration: underline;\n }\n .tag {\n display: inline-block;\n font-size: 10px;\n padding: 1px 6px;\n border-radius: 3px;\n background: rgba(148, 163, 184, 0.10);\n color: #cbd5e1;\n margin-right: 4px;\n letter-spacing: 0.01em;\n }\n .props {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n }\n .prop {\n display: inline-flex;\n gap: 5px;\n max-width: 100%;\n padding: 2px 6px;\n border-radius: 3px;\n background: transparent;\n color: #cbd5e1;\n border: 1px solid rgba(148, 163, 184, 0.14);\n font-size: 10px;\n overflow-wrap: anywhere;\n }\n .prop-key {\n color: #7dd3fc;\n font-weight: 600;\n }\n .relations {\n list-style: none;\n padding: 0;\n margin: 0;\n font-size: 12px;\n }\n .relations li {\n display: flex;\n gap: 6px;\n align-items: baseline;\n padding: 4px 0;\n color: #cbd5e1;\n }\n .arrow {\n color: #38bdf8;\n }\n .to {\n font-weight: 700;\n color: #e2e8f0;\n }\n .rdesc {\n color: #94a3b8;\n }\n .rmeta {\n font-size: 10px;\n color: #64748b;\n font-style: italic;\n }\n .issues {\n list-style: none;\n padding: 0;\n margin: 0;\n font-size: 12px;\n }\n .issues li {\n margin: 6px 0;\n padding: 7px 9px;\n border-radius: 4px;\n border-left: 2px solid #dec184;\n background: rgba(222, 193, 132, 0.06);\n color: #e2c896;\n line-height: 1.35;\n overflow-wrap: anywhere;\n }\n .change-list {\n list-style: none;\n padding: 0;\n margin: 0;\n display: grid;\n gap: 8px;\n }\n .change-row {\n display: grid;\n grid-template-columns: minmax(0, 1fr);\n gap: 2px;\n align-items: start;\n padding: 6px 0 6px 10px;\n border-left: 2px solid var(--diff-tint, rgba(148, 163, 184, 0.40));\n background: transparent;\n }\n .change-row:hover {\n background: rgba(255, 255, 255, 0.02);\n }\n .change-title {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: #e2e8f0;\n font-size: 12px;\n font-weight: 500;\n }\n .change-glyph {\n display: inline-block;\n width: 12px;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-weight: 700;\n font-size: 11px;\n text-align: center;\n }\n .change-subtitle {\n overflow-wrap: anywhere;\n color: #64748b;\n font-size: 11px;\n line-height: 1.35;\n font-variant-numeric: tabular-nums;\n }\n .info-line {\n display: flex;\n flex-wrap: wrap;\n gap: 14px 18px;\n margin: 8px 0 4px;\n padding: 0;\n font-size: 11px;\n color: #64748b;\n font-variant-numeric: tabular-nums;\n }\n .info-line > div {\n display: flex;\n align-items: baseline;\n gap: 5px;\n }\n .info-line dt {\n color: #64748b;\n letter-spacing: 0.01em;\n }\n .info-line dd {\n margin: 0;\n color: #e2e8f0;\n font-weight: 500;\n font-size: 13px;\n }\n .info-line .warn dd {\n color: #dec184;\n }\n .info-line .warn dt {\n color: #dec184;\n }\n :global(.svelte-flow) {\n background: #0b1220;\n /* xyflow exposes edge styling via CSS variables. Setting them\n here overrides the defaults baked into\n @xyflow/svelte/dist/style.css regardless of which template\n (default / smoothstep / straight) renders the edge.\n Edge labels are HTML <div>s, not SVG <text>, so they need\n HTML CSS background / color — labelBgStyle prop is ignored\n in @xyflow/svelte 1.x. */\n --xy-edge-stroke-default: #94a3b8;\n --xy-edge-stroke-selected-default: #38bdf8;\n --xy-edge-stroke-width-default: 1.8;\n --xy-connectionline-stroke-default: #38bdf8;\n --xy-edge-label-color-default: #f8fafc;\n --xy-edge-label-background-color-default: #1e293b;\n }\n :global(.svelte-flow__edge-label) {\n background: #1e293b;\n color: #f8fafc;\n padding: 3px 8px;\n border-radius: 6px;\n border: 1px solid #475569;\n font-size: 11px;\n font-weight: 700;\n box-shadow: 0 4px 12px -8px rgba(0, 0, 0, 0.6);\n white-space: nowrap;\n max-width: 240px;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n :global(.svelte-flow__background) {\n background-color: #0b1220;\n }\n :global(.svelte-flow__edge-path) {\n stroke: #94a3b8;\n stroke-width: 1.8;\n }\n :global(.svelte-flow__edge.selected .svelte-flow__edge-path) {\n stroke: #38bdf8;\n stroke-width: 2.4;\n }\n :global(.svelte-flow__edge-text) {\n fill: #f8fafc;\n font-size: 11px;\n font-weight: 700;\n }\n :global(.svelte-flow__edge-textbg) {\n fill: #1e293b;\n stroke: #475569;\n stroke-width: 1;\n }\n :global(.svelte-flow__arrowhead polyline),\n :global(.svelte-flow__arrowhead path) {\n fill: #cbd5e1;\n stroke: #cbd5e1;\n }\n /* Hide connection handles. xyflow still needs the <Handle>\n components to compute edge endpoints, but the default `o` dot\n visually competes with the arrowhead at the node border. We\n keep size > 0 so the layout math is intact, just invisible. */\n :global(.svelte-flow__handle) {\n width: 6px;\n height: 6px;\n background: transparent;\n border: 0;\n min-width: 0;\n min-height: 0;\n opacity: 0;\n pointer-events: none;\n }\n :global(.svelte-flow__controls) {\n background: #0d1424;\n border: 1px solid rgba(148, 163, 184, 0.14);\n border-radius: 4px;\n overflow: hidden;\n }\n :global(.svelte-flow__controls-button) {\n background: #0d1424;\n border-bottom: 1px solid rgba(148, 163, 184, 0.10);\n color: #cbd5e1;\n }\n :global(.svelte-flow__controls-button:hover) {\n background: rgba(255, 255, 255, 0.04);\n }\n :global(.svelte-flow__minimap) {\n border: 1px solid rgba(148, 163, 184, 0.14);\n border-radius: 4px;\n overflow: hidden;\n }\n\n /* Analyze overlay — toggle button + sidebar metrics list. */\n .analyze-toggle button.active {\n /* Red tint ties the toggle to the cycle-highlight color on the\n graph — distinct from mode/edge accents which use sky blue. */\n background: rgba(239, 68, 68, 0.14);\n color: #fca5a5;\n }\n .metrics {\n list-style: none;\n padding: 0;\n margin: 0 0 10px 0;\n font-size: 12px;\n }\n .metrics li {\n display: flex;\n justify-content: space-between;\n padding: 3px 0;\n border-bottom: 1px solid rgba(148, 163, 184, 0.06);\n }\n .metrics li:last-child {\n border-bottom: none;\n }\n .metrics .k {\n color: #94a3b8;\n }\n .metrics .v {\n color: #e2e8f0;\n font-variant-numeric: tabular-nums;\n font-weight: 500;\n }\n .warn-h {\n color: #dec184;\n }\n .cycle-list {\n font-size: 12px;\n color: #94a3b8;\n margin: 4px 0 12px 0;\n }\n .cycle-trail {\n display: block;\n margin-top: 4px;\n padding: 6px 8px;\n background: rgba(222, 193, 132, 0.06);\n border-left: 2px solid #dec184;\n color: #e2c896;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 11px;\n word-break: break-all;\n }\n</style>\n","import { mount } from \"svelte\";\n\nimport App from \"./App.svelte\";\n\nconst target = document.querySelector(\"#app\");\nif (!target) {\n throw new Error(\"aact view: #app mount point missing in index.html\");\n}\nmount(App, { target });\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.boundary.svelte-11zjl56{border:2px dashed var(--accent,#94a3b8);background:color-mix(in srgb, var(--accent,#94a3b8) 8%, transparent);color:#e2e8f0;box-sizing:border-box;cursor:pointer;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);border-radius:16px;flex-direction:column;width:100%;height:100%;transition:background .12s,box-shadow .12s;display:flex}.boundary.svelte-11zjl56:hover{background:color-mix(in srgb, var(--accent,#94a3b8) 14%, transparent)}.boundary.expanded.svelte-11zjl56{cursor:default}.boundary.is-selected.svelte-11zjl56{box-shadow:0 0 0 1px var(--accent), 0 0 0 4px color-mix(in srgb, var(--accent) 30%, transparent)}.header.svelte-11zjl56{border-bottom:1px dashed color-mix(in srgb, var(--accent) 40%, transparent);background:color-mix(in srgb, var(--accent) 10%, transparent);border-radius:14px 14px 0 0;flex-direction:column;gap:2px;padding:8px 12px 10px;display:flex}.kind.svelte-11zjl56{letter-spacing:.12em;text-transform:uppercase;color:color-mix(in srgb, var(--accent) 65%, #cbd5e1);font-size:9.5px;font-weight:500}.label.svelte-11zjl56{color:#f8fafc;text-overflow:ellipsis;white-space:nowrap;letter-spacing:-.005em;font-size:13px;font-weight:600;line-height:1.2;overflow:hidden}.meta.svelte-11zjl56{color:#e2e8f073;letter-spacing:.01em;font-size:10px}.db.svelte-1okyz27{background:linear-gradient(180deg, var(--fill) 0%, color-mix(in srgb, var(--fill) 80%, black) 100%);color:#f8fafc;box-sizing:border-box;cursor:pointer;width:100%;height:100%;box-shadow:0 10px 28px -18px color-mix(in srgb, var(--fill) 70%, transparent), inset 0 1px 0 #ffffff1a;border-radius:14px 14px 22px 22px/14px 14px 30px 30px;grid-template-rows:14px 1fr;padding:0;transition:transform .12s,box-shadow .12s;display:grid;position:relative}.db.svelte-1okyz27:hover{transform:translateY(-1px)}.db.is-selected.svelte-1okyz27{outline-offset:2px;outline:2px solid #38bdf8}.cyl-top.svelte-1okyz27{background:#0000002e;border-bottom:1px solid #ffffff26;border-radius:14px 14px 50% 50%/14px 14px 100% 100%;height:14px}.body.svelte-1okyz27{flex-direction:column;gap:2px;padding:10px 14px 14px;display:flex;overflow:hidden}.kind.svelte-1okyz27{letter-spacing:.14em;text-transform:uppercase;color:#f8fafcc7;font-size:9px;font-weight:700}.label.svelte-1okyz27{text-overflow:ellipsis;-webkit-line-clamp:2;-webkit-box-orient:vertical;font-size:13px;font-weight:700;line-height:1.15;display:-webkit-box;overflow:hidden}.tech.svelte-1okyz27{color:#f8fafcd9;font-size:10px;font-style:italic}.desc.svelte-1okyz27{color:#f8fafcbf;text-overflow:ellipsis;-webkit-line-clamp:2;-webkit-box-orient:vertical;font-size:11px;line-height:1.3;display:-webkit-box;overflow:hidden}.el.svelte-698jog{background:var(--fill);color:var(--text,#f8fafc);border:1px solid color-mix(in srgb, var(--fill) 60%, black);box-sizing:border-box;cursor:pointer;border-radius:6px;flex-direction:column;gap:3px;width:100%;height:100%;padding:10px 12px 12px;transition:filter .1s,border-color .1s;display:flex}.el.svelte-698jog:hover{filter:brightness(1.08)}.el.is-selected.svelte-698jog{border-color:#7dd3fc;box-shadow:inset 0 0 0 1px #7dd3fc}.head.svelte-698jog{justify-content:space-between;align-items:center;display:flex}.kind.svelte-698jog{letter-spacing:.12em;text-transform:uppercase;color:color-mix(in srgb, var(--text) 65%, transparent);font-size:9.5px;font-weight:500}.label.svelte-698jog{letter-spacing:-.005em;text-overflow:ellipsis;-webkit-line-clamp:2;-webkit-box-orient:vertical;font-size:13px;font-weight:600;line-height:1.2;display:-webkit-box;overflow:hidden}.tech.svelte-698jog{color:color-mix(in srgb, var(--text) 75%, transparent);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:10px}.desc.svelte-698jog{color:color-mix(in srgb, var(--text) 70%, transparent);text-overflow:ellipsis;-webkit-line-clamp:2;-webkit-box-orient:vertical;font-size:11px;line-height:1.35;display:-webkit-box;overflow:hidden}.person.svelte-64vle7{color:#f8fafc;box-sizing:border-box;cursor:pointer;background:linear-gradient(#08427b 0%,#073768 100%);border-radius:14px;grid-template-rows:36px 1fr;gap:6px;width:100%;height:100%;padding:12px 14px 14px;transition:transform .12s,box-shadow .12s;display:grid;box-shadow:0 10px 30px -18px #08427bd9,inset 0 1px #ffffff14}.person.svelte-64vle7:hover{transform:translateY(-1px);box-shadow:0 14px 40px -16px #08427bf2,inset 0 1px #ffffff1f}.person.is-selected.svelte-64vle7{outline-offset:2px;outline:2px solid #38bdf8}.person.external.svelte-64vle7{background:linear-gradient(#475569 0%,#334155 100%)}.head.svelte-64vle7{justify-content:center;align-items:center;display:flex}.silhouette.svelte-64vle7{color:#f8fafc;opacity:.92;width:28px;height:28px}.silhouette.svelte-64vle7 circle:where(.svelte-64vle7){fill:currentColor}.silhouette.svelte-64vle7 path:where(.svelte-64vle7){fill:none;stroke:currentColor;stroke-width:2px;stroke-linecap:round}.body.svelte-64vle7{text-align:center;flex-direction:column;align-items:center;gap:2px;display:flex}.kind.svelte-64vle7{letter-spacing:.14em;text-transform:uppercase;color:#f8fafcbf;font-size:9px;font-weight:700}.label.svelte-64vle7{text-overflow:ellipsis;-webkit-line-clamp:2;-webkit-box-orient:vertical;font-size:14px;font-weight:700;line-height:1.15;display:-webkit-box;overflow:hidden}.desc.svelte-64vle7{color:#f8fafcb3;text-overflow:ellipsis;-webkit-line-clamp:2;-webkit-box-orient:vertical;font-size:11px;line-height:1.25;display:-webkit-box;overflow:hidden}.q.svelte-1s4sqjz{background:linear-gradient(180deg, var(--fill) 0%, color-mix(in srgb, var(--fill) 80%, black) 100%);color:#f8fafc;box-sizing:border-box;cursor:pointer;width:100%;height:100%;box-shadow:0 10px 28px -18px color-mix(in srgb, var(--fill) 70%, transparent), inset 0 1px 0 #ffffff1a;border-radius:999px;flex-direction:column;gap:0;padding:0;transition:transform .12s;display:flex}.q.svelte-1s4sqjz:hover{transform:translateY(-1px)}.q.is-selected.svelte-1s4sqjz{outline-offset:2px;outline:2px solid #38bdf8}.body.svelte-1s4sqjz{flex-direction:column;justify-content:center;gap:2px;height:100%;padding:14px 22px;display:flex;overflow:hidden}.kind.svelte-1s4sqjz{letter-spacing:.14em;text-transform:uppercase;color:#f8fafcc7;font-size:9px;font-weight:700}.label.svelte-1s4sqjz{text-overflow:ellipsis;-webkit-line-clamp:2;-webkit-box-orient:vertical;font-size:13px;font-weight:700;line-height:1.15;display:-webkit-box;overflow:hidden}.tech.svelte-1s4sqjz{color:#f8fafcd9;font-size:10px;font-style:italic}.desc.svelte-1s4sqjz{color:#f8fafcbf;text-overflow:ellipsis;-webkit-line-clamp:1;-webkit-box-orient:vertical;font-size:11px;line-height:1.3;display:-webkit-box;overflow:hidden}html,body{color:#e2e8f0;background:#0b1220;height:100%;margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Inter,Roboto,sans-serif}body{overflow:hidden}.app.svelte-1r8vfx3{grid-template-rows:auto 1fr;height:100vh;display:grid}.topbar.svelte-1r8vfx3{background:#0d1424;border-bottom:1px solid #94a3b81a;grid-template-columns:1fr auto 1fr;align-items:center;gap:16px;padding:8px 14px;display:grid}.brand.svelte-1r8vfx3{align-items:baseline;gap:8px;min-width:0;display:flex}.logo.svelte-1r8vfx3{letter-spacing:-.01em;color:#f8fafc;font-size:13px;font-weight:700}.title.svelte-1r8vfx3{color:#64748b;letter-spacing:.01em;font-size:12px;font-weight:500}.workspace.svelte-1r8vfx3{color:#cbd5e1;text-overflow:ellipsis;white-space:nowrap;max-width:340px;font-size:12px;font-weight:500;overflow:hidden}.sep.svelte-1r8vfx3{color:#334155;font-size:10px}.status.svelte-1r8vfx3{color:#64748b;font-feature-settings:"tnum";letter-spacing:.02em;margin-left:4px;font-size:10.5px}.status-live.svelte-1r8vfx3{color:#34d399}.status-lost.svelte-1r8vfx3{color:#f87171}.status-error.svelte-1r8vfx3{color:#fbbf24}.diff-pill.svelte-1r8vfx3{text-overflow:ellipsis;white-space:nowrap;color:#fbbf24;letter-spacing:.01em;max-width:360px;font-size:11px;font-weight:600;display:inline-block;overflow:hidden}.topbar-controls.svelte-1r8vfx3{align-items:center;gap:6px;display:inline-flex}.modes.svelte-1r8vfx3{background:0 0;border:1px solid #94a3b824;border-radius:5px;padding:0;display:inline-flex;overflow:hidden}.modes.svelte-1r8vfx3 button:where(.svelte-1r8vfx3)+button:where(.svelte-1r8vfx3){border-left:1px solid #94a3b81a}.edge-modes.svelte-1r8vfx3 button:where(.svelte-1r8vfx3){padding:5px 10px;font-size:11px}.modes.svelte-1r8vfx3 button:where(.svelte-1r8vfx3){appearance:none;color:#94a3b8;cursor:pointer;letter-spacing:.01em;background:0 0;border:0;border-radius:0;padding:5px 12px;font-size:11.5px;font-weight:500;transition:background 80ms,color 80ms}.modes.svelte-1r8vfx3 button:where(.svelte-1r8vfx3):hover{color:#e2e8f0;background:#ffffff08}.modes.svelte-1r8vfx3 button.active:where(.svelte-1r8vfx3){color:#7dd3fc;background:#38bdf81f}.context.svelte-1r8vfx3{justify-self:end;align-items:center;gap:10px;min-width:0;font-size:12px;display:flex}.breadcrumb.svelte-1r8vfx3{flex-wrap:wrap;align-items:center;gap:4px;display:flex}.bcrumb.svelte-1r8vfx3{appearance:none;color:#7dd3fc;cursor:pointer;letter-spacing:.01em;background:0 0;border:0;border-radius:3px;padding:2px 5px;font-size:11.5px}.bcrumb.svelte-1r8vfx3:hover{background:#38bdf814}.bsep.svelte-1r8vfx3{color:#334155}.expand-controls.svelte-1r8vfx3{align-items:center;gap:6px;display:flex}.ghost.svelte-1r8vfx3{appearance:none;color:#cbd5e1;cursor:pointer;letter-spacing:.01em;background:0 0;border:1px solid #94a3b824;border-radius:4px;padding:4px 10px;font-size:11px;font-weight:500;transition:background 80ms,color 80ms}.ghost.svelte-1r8vfx3:hover{color:#f8fafc;background:#ffffff0a}.hint.svelte-1r8vfx3{color:#64748b;letter-spacing:.01em;font-size:10.5px}main.svelte-1r8vfx3{background:#0b1220;grid-template-columns:minmax(0,1fr) 360px;display:grid;overflow:hidden}.graph.svelte-1r8vfx3{background:#0b1220;position:relative;overflow:hidden}.details.svelte-1r8vfx3{overflow:auto}.legend.svelte-1r8vfx3{color:#cbd5e1;z-index:4;letter-spacing:.01em;background:#0d1424;border:1px solid #94a3b824;border-radius:4px;flex-direction:column;gap:4px;padding:8px 10px;font-size:11px;display:flex;position:absolute;bottom:14px;left:14px}.legend-row.svelte-1r8vfx3{align-items:center;gap:8px;display:flex}.swatch.svelte-1r8vfx3{border-radius:2px;width:10px;height:10px}.legend-rule.svelte-1r8vfx3{background:#94a3b81a;height:1px;margin:4px 0;display:block}.error-overlay.svelte-1r8vfx3{z-index:5;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);background:#451a03eb;border:1px solid #b45309;border-radius:8px;max-width:min(520px,100% - 36px);padding:14px 16px;position:absolute;top:18px;left:18px;box-shadow:0 18px 50px -28px #000c}.error-kicker.svelte-1r8vfx3{letter-spacing:.14em;text-transform:uppercase;color:#fbbf24;margin-bottom:6px;font-size:10px;font-weight:800;display:block}.error-overlay.svelte-1r8vfx3 p:where(.svelte-1r8vfx3){color:#fff7ed;overflow-wrap:anywhere;margin:0;font-size:13px;line-height:1.4}.error-meta.svelte-1r8vfx3{color:#fed7aa;flex-wrap:wrap;gap:8px;margin-top:8px;font-size:10px;display:flex}.details.svelte-1r8vfx3{background:#0d1424;border-left:1px solid #94a3b81a;padding:16px 18px 20px;overflow:auto}.details.svelte-1r8vfx3 h2:where(.svelte-1r8vfx3){letter-spacing:.1em;text-transform:uppercase;color:#64748b;margin:0 0 6px;font-size:10.5px;font-weight:500}.details.svelte-1r8vfx3 h3:where(.svelte-1r8vfx3){color:#f8fafc;letter-spacing:-.005em;margin:2px 0 12px;font-size:15px;font-weight:600;line-height:1.25}.details.svelte-1r8vfx3 h4:where(.svelte-1r8vfx3){letter-spacing:.1em;text-transform:uppercase;color:#64748b;margin:16px 0 6px;font-size:10.5px;font-weight:500}.tech.svelte-1r8vfx3{color:#94a3b8;margin:0 0 10px;font-size:12px;font-style:italic}.desc.svelte-1r8vfx3{color:#cbd5e1;margin:0 0 14px;font-size:13px;line-height:1.45}.field.svelte-1r8vfx3{color:#cbd5e1;gap:8px;margin-bottom:6px;font-size:12px;display:flex}.field.svelte-1r8vfx3 .k:where(.svelte-1r8vfx3){color:#64748b;letter-spacing:.08em;text-transform:uppercase;min-width:70px;padding-top:2px;font-size:10px}.field.svelte-1r8vfx3 a:where(.svelte-1r8vfx3){color:#38bdf8;text-decoration:none}.field.svelte-1r8vfx3 a:where(.svelte-1r8vfx3):hover{text-decoration:underline}.tag.svelte-1r8vfx3{color:#cbd5e1;letter-spacing:.01em;background:#94a3b81a;border-radius:3px;margin-right:4px;padding:1px 6px;font-size:10px;display:inline-block}.props.svelte-1r8vfx3{flex-wrap:wrap;gap:4px;display:flex}.prop.svelte-1r8vfx3{color:#cbd5e1;overflow-wrap:anywhere;background:0 0;border:1px solid #94a3b824;border-radius:3px;gap:5px;max-width:100%;padding:2px 6px;font-size:10px;display:inline-flex}.prop-key.svelte-1r8vfx3{color:#7dd3fc;font-weight:600}.relations.svelte-1r8vfx3{margin:0;padding:0;font-size:12px;list-style:none}.relations.svelte-1r8vfx3 li:where(.svelte-1r8vfx3){color:#cbd5e1;align-items:baseline;gap:6px;padding:4px 0;display:flex}.arrow.svelte-1r8vfx3{color:#38bdf8}.to.svelte-1r8vfx3{color:#e2e8f0;font-weight:700}.rdesc.svelte-1r8vfx3{color:#94a3b8}.rmeta.svelte-1r8vfx3{color:#64748b;font-size:10px;font-style:italic}.issues.svelte-1r8vfx3{margin:0;padding:0;font-size:12px;list-style:none}.issues.svelte-1r8vfx3 li:where(.svelte-1r8vfx3){color:#e2c896;overflow-wrap:anywhere;background:#dec1840f;border-left:2px solid #dec184;border-radius:4px;margin:6px 0;padding:7px 9px;line-height:1.35}.change-list.svelte-1r8vfx3{gap:8px;margin:0;padding:0;list-style:none;display:grid}.change-row.svelte-1r8vfx3{border-left:2px solid var(--diff-tint,#94a3b866);background:0 0;grid-template-columns:minmax(0,1fr);align-items:start;gap:2px;padding:6px 0 6px 10px;display:grid}.change-row.svelte-1r8vfx3:hover{background:#ffffff05}.change-title.svelte-1r8vfx3{text-overflow:ellipsis;white-space:nowrap;color:#e2e8f0;font-size:12px;font-weight:500;overflow:hidden}.change-glyph.svelte-1r8vfx3{text-align:center;width:12px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;font-weight:700;display:inline-block}.change-subtitle.svelte-1r8vfx3{overflow-wrap:anywhere;color:#64748b;font-variant-numeric:tabular-nums;font-size:11px;line-height:1.35}.info-line.svelte-1r8vfx3{color:#64748b;font-variant-numeric:tabular-nums;flex-wrap:wrap;gap:14px 18px;margin:8px 0 4px;padding:0;font-size:11px;display:flex}.info-line.svelte-1r8vfx3>div:where(.svelte-1r8vfx3){align-items:baseline;gap:5px;display:flex}.info-line.svelte-1r8vfx3 dt:where(.svelte-1r8vfx3){color:#64748b;letter-spacing:.01em}.info-line.svelte-1r8vfx3 dd:where(.svelte-1r8vfx3){color:#e2e8f0;margin:0;font-size:13px;font-weight:500}.info-line.svelte-1r8vfx3 .warn:where(.svelte-1r8vfx3) dd:where(.svelte-1r8vfx3),.info-line.svelte-1r8vfx3 .warn:where(.svelte-1r8vfx3) dt:where(.svelte-1r8vfx3){color:#dec184}.svelte-flow{--xy-edge-stroke-default:#94a3b8;--xy-edge-stroke-selected-default:#38bdf8;--xy-edge-stroke-width-default:1.8;--xy-connectionline-stroke-default:#38bdf8;--xy-edge-label-color-default:#f8fafc;--xy-edge-label-background-color-default:#1e293b;background:#0b1220}.svelte-flow__edge-label{color:#f8fafc;white-space:nowrap;text-overflow:ellipsis;background:#1e293b;border:1px solid #475569;border-radius:6px;max-width:240px;padding:3px 8px;font-size:11px;font-weight:700;overflow:hidden;box-shadow:0 4px 12px -8px #0009}.svelte-flow__background{background-color:#0b1220}.svelte-flow__edge-path{stroke:#94a3b8;stroke-width:1.8px}.svelte-flow__edge.selected .svelte-flow__edge-path{stroke:#38bdf8;stroke-width:2.4px}.svelte-flow__edge-text{fill:#f8fafc;font-size:11px;font-weight:700}.svelte-flow__edge-textbg{fill:#1e293b;stroke:#475569;stroke-width:1px}.svelte-flow__arrowhead polyline,.svelte-flow__arrowhead path{fill:#cbd5e1;stroke:#cbd5e1}.svelte-flow__handle{opacity:0;pointer-events:none;background:0 0;border:0;width:6px;min-width:0;height:6px;min-height:0}.svelte-flow__controls{background:#0d1424;border:1px solid #94a3b824;border-radius:4px;overflow:hidden}.svelte-flow__controls-button{color:#cbd5e1;background:#0d1424;border-bottom:1px solid #94a3b81a}.svelte-flow__controls-button:hover{background:#ffffff0a}.svelte-flow__minimap{border:1px solid #94a3b824;border-radius:4px;overflow:hidden}.analyze-toggle.svelte-1r8vfx3 button.active:where(.svelte-1r8vfx3){color:#fca5a5;background:#ef444424}.metrics.svelte-1r8vfx3{margin:0 0 10px;padding:0;font-size:12px;list-style:none}.metrics.svelte-1r8vfx3 li:where(.svelte-1r8vfx3){border-bottom:1px solid #94a3b80f;justify-content:space-between;padding:3px 0;display:flex}.metrics.svelte-1r8vfx3 li:where(.svelte-1r8vfx3):last-child{border-bottom:none}.metrics.svelte-1r8vfx3 .k:where(.svelte-1r8vfx3){color:#94a3b8}.metrics.svelte-1r8vfx3 .v:where(.svelte-1r8vfx3){color:#e2e8f0;font-variant-numeric:tabular-nums;font-weight:500}.warn-h.svelte-1r8vfx3{color:#dec184}.cycle-list.svelte-1r8vfx3{color:#94a3b8;margin:4px 0 12px;font-size:12px}.cycle-trail.svelte-1r8vfx3{color:#e2c896;word-break:break-all;background:#dec1840f;border-left:2px solid #dec184;margin-top:4px;padding:6px 8px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;display:block}
|
package/dist/ui/index.html
CHANGED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
6
|
<title>aact view</title>
|
|
7
|
-
<script type="module" crossorigin src="./assets/index-
|
|
7
|
+
<script type="module" crossorigin src="./assets/index-BR_xeaLb.js"></script>
|
|
8
8
|
<link rel="modulepreload" crossorigin href="./assets/rolldown-runtime-CkqCuyE9.js">
|
|
9
9
|
<link rel="modulepreload" crossorigin href="./assets/svelte-DegjF43v.js">
|
|
10
10
|
<link rel="modulepreload" crossorigin href="./assets/xyflow-BjlDntcZ.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="./assets/elk-B440gP8v.js">
|
|
12
12
|
<link rel="stylesheet" crossorigin href="./assets/xyflow-na7JlWeF.css">
|
|
13
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
13
|
+
<link rel="stylesheet" crossorigin href="./assets/index-CK7Lun-6.css">
|
|
14
14
|
</head>
|
|
15
15
|
<body>
|
|
16
16
|
<div id="app"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aact/view",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.24",
|
|
4
4
|
"description": "Local architecture workbench for aact — browser-based live viewer of the normalised C4 Model.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "GPL-3.0",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"dist"
|
|
35
35
|
],
|
|
36
36
|
"peerDependencies": {
|
|
37
|
-
"aact": "^3.0.0-beta.
|
|
37
|
+
"aact": "^3.0.0-beta.24"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@sveltejs/vite-plugin-svelte": "^7.1.2",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"svelte": "^5.55.8",
|
|
43
43
|
"typescript": "5.9.3",
|
|
44
44
|
"vite": "^8.0.13",
|
|
45
|
-
"aact": "^3.0.0-beta.
|
|
45
|
+
"aact": "^3.0.0-beta.24"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@xyflow/svelte": "^1.5.2",
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import{r as e}from"./rolldown-runtime-CkqCuyE9.js";import{$ as t,A as n,B as r,C as i,E as a,F as o,G as s,H as c,J as l,K as u,L as d,M as f,O as p,T as m,W as h,X as g,Y as _,Z as v,_ as y,b,ct as x,et as S,f as C,it as w,j as T,m as E,p as D,q as O,rt as k,tt as A,w as j,x as M,z as N}from"./svelte-DegjF43v.js";import{a as ee,c as P,i as te,n as ne,o as F,r as re,s as I,t as ie}from"./xyflow-BjlDntcZ.js";import{t as L}from"./elk-B440gP8v.js";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var R=Symbol(`aact-view:actions`),z=p(`<span class="meta svelte-11zjl56"> </span>`),B=p(`<div role="button" tabindex="0"><!> <header class="header svelte-11zjl56"><span class="chip svelte-11zjl56"> </span> <span class="label svelte-11zjl56"> </span> <!></header> <!></div>`);function ae(e,n){S(n,!0);let r=v(R),s={Enterprise:`#0b3b6c`,System:`#1168bd`,Container:`#438dd5`,Component:`#85bbf0`},c=g(()=>s[n.data.kind]??`#94a3b8`),l=e=>{e.target!==e.currentTarget&&!e.target.closest(`.header`)||r?.selectBoundary(n.data.name)},d=e=>{e.stopPropagation(),n.data.canExpand?r?.toggleBoundary(n.data.name,n.data.label):r?.enterBoundary(n.data.name,n.data.label)},p=e=>{if(e.key===`Enter`){r?.selectBoundary(n.data.name);return}e.key===` `&&(e.preventDefault(),n.data.canExpand?r?.toggleBoundary(n.data.name,n.data.label):r?.enterBoundary(n.data.name,n.data.label))};var _=B();let y,b;var x=h(_);F(x,{type:`target`,get position(){return P.Left}});var T=u(x,2),O=h(T),k=h(O);w(O);var A=u(O,2),j=h(A,!0);w(A);var M=u(A,2),ee=e=>{var t=z(),r=h(t);w(t),N(()=>m(r,`${n.data.childCount??``} child${n.data.childCount===1?``:`ren`} · dblclick to
|
|
2
|
-
${n.data.canExpand?`expand`:`enter`}`)),a(e,t)};i(M,e=>{n.data.expanded||e(ee)}),w(T),F(u(T,2),{type:`source`,get position(){return P.Right}}),w(_),N(()=>{y=E(_,1,`boundary svelte-11zjl56`,null,y,{expanded:n.data.expanded,"is-selected":n.selected}),C(_,`aria-label`,`${n.data.kind} boundary: ${n.data.label}`),b=D(_,``,b,{"--accent":o(c)}),m(k,`${n.data.kind??``} boundary`),m(j,n.data.label)}),f(`click`,_,l),f(`dblclick`,_,d),f(`keydown`,_,p),a(e,_),t()}T([`click`,`dblclick`,`keydown`]);var V=p(`<span class="tech svelte-1okyz27"> </span>`),H=p(`<span class="desc svelte-1okyz27"> </span>`),U=p(`<div role="button" tabindex="0"><!> <div class="cyl-top svelte-1okyz27" aria-hidden="true"></div> <div class="body svelte-1okyz27"><span class="kind svelte-1okyz27"> </span> <span class="label svelte-1okyz27"> </span> <!> <!></div> <!></div>`);function oe(e,n){S(n,!0);let r=v(R),s=g(()=>n.data.external?`#475569`:`#1168bd`);var c=U();let l,d;var p=h(c);F(p,{type:`target`,get position(){return P.Left}});var _=u(p,4),y=h(_),b=h(y,!0);w(y);var x=u(y,2),C=h(x,!0);w(x);var T=u(x,2),O=e=>{var t=V(),r=h(t);w(t),N(()=>m(r,`[${n.data.technology??``}]`)),a(e,t)};i(T,e=>{n.data.technology&&e(O)});var k=u(T,2),A=e=>{var t=H(),r=h(t,!0);w(t),N(()=>m(r,n.data.description)),a(e,t)};i(k,e=>{n.data.description&&e(A)}),w(_),F(u(_,2),{type:`source`,get position(){return P.Right}}),w(c),N(()=>{l=E(c,1,`db svelte-1okyz27`,null,l,{external:n.data.external,"is-selected":n.selected}),d=D(c,``,d,{"--fill":o(s)}),m(b,n.data.kind),m(C,n.data.label)}),f(`click`,c,()=>r?.selectElement(n.data.name)),f(`keydown`,c,e=>{e.key===`Enter`&&r?.selectElement(n.data.name)}),a(e,c),t()}T([`click`,`keydown`]);var se=p(`<span class="tech svelte-698jog"> </span>`),ce=p(`<span class="desc svelte-698jog"> </span>`),W=p(`<div role="button" tabindex="0"><!> <div class="head svelte-698jog"><span class="kind svelte-698jog"> </span></div> <span class="label svelte-698jog"> </span> <!> <!> <!></div>`);function le(e,n){S(n,!0);let r=v(R),s=(e,t)=>t?`#475569`:e===`System`?`#1168bd`:e===`Container`?`#438dd5`:e===`Component`?`#85bbf0`:`#1168bd`,c=g(()=>s(n.data.kind,n.data.external)),l=g(()=>n.data.kind===`Component`&&!n.data.external?`#0f172a`:`#f8fafc`);var d=W();let p,_;var y=h(d);F(y,{type:`target`,get position(){return P.Left}});var b=u(y,2),x=h(b),C=h(x);w(x),w(b);var T=u(b,2),O=h(T,!0);w(T);var k=u(T,2),A=e=>{var t=se(),r=h(t);w(t),N(()=>m(r,`[${n.data.technology??``}]`)),a(e,t)};i(k,e=>{n.data.technology&&e(A)});var j=u(k,2),M=e=>{var t=ce(),r=h(t,!0);w(t),N(()=>m(r,n.data.description)),a(e,t)};i(j,e=>{n.data.description&&e(M)}),F(u(j,2),{type:`source`,get position(){return P.Right}}),w(d),N(()=>{p=E(d,1,`el svelte-698jog`,null,p,{external:n.data.external,"is-selected":n.selected}),_=D(d,``,_,{"--fill":o(c),"--text":o(l)}),m(C,`${n.data.kind??``}${n.data.external?` · external`:``}`),m(O,n.data.label)}),f(`click`,d,()=>r?.selectElement(n.data.name)),f(`keydown`,d,e=>{e.key===`Enter`&&r?.selectElement(n.data.name)}),a(e,d),t()}T([`click`,`keydown`]);var G=p(`<span class="desc svelte-64vle7"> </span>`),ue=p(`<div role="button" tabindex="0"><!> <div class="head svelte-64vle7" aria-hidden="true"><svg viewBox="0 0 24 24" class="silhouette svelte-64vle7" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="7" r="4" class="svelte-64vle7"></circle><path d="M4 21c0-4.42 3.58-8 8-8s8 3.58 8 8" class="svelte-64vle7"></path></svg></div> <div class="body svelte-64vle7"><span class="kind svelte-64vle7">Person</span> <span class="label svelte-64vle7"> </span> <!></div> <!></div>`);function de(e,n){S(n,!0);let r=v(R);var o=ue();let s;var c=h(o);F(c,{type:`target`,get position(){return P.Left}});var l=u(c,4),d=u(h(l),2),p=h(d,!0);w(d);var g=u(d,2),_=e=>{var t=G(),r=h(t,!0);w(t),N(()=>m(r,n.data.description)),a(e,t)};i(g,e=>{n.data.description&&e(_)}),w(l),F(u(l,2),{type:`source`,get position(){return P.Right}}),w(o),N(()=>{s=E(o,1,`person svelte-64vle7`,null,s,{external:n.data.external,"is-selected":n.selected}),m(p,n.data.label)}),f(`click`,o,()=>r?.selectElement(n.data.name)),f(`keydown`,o,e=>{e.key===`Enter`&&r?.selectElement(n.data.name)}),a(e,o),t()}T([`click`,`keydown`]);var fe=p(`<span class="tech svelte-1s4sqjz"> </span>`),pe=p(`<span class="desc svelte-1s4sqjz"> </span>`),me=p(`<div role="button" tabindex="0"><!> <div class="body svelte-1s4sqjz"><span class="kind svelte-1s4sqjz"> </span> <span class="label svelte-1s4sqjz"> </span> <!> <!></div> <!></div>`);function he(e,n){S(n,!0);let r=v(R),s=g(()=>n.data.external?`#475569`:`#1168bd`);var c=me();let l,d;var p=h(c);F(p,{type:`target`,get position(){return P.Left}});var _=u(p,2),y=h(_),b=h(y,!0);w(y);var x=u(y,2),C=h(x,!0);w(x);var T=u(x,2),O=e=>{var t=fe(),r=h(t);w(t),N(()=>m(r,`[${n.data.technology??``}]`)),a(e,t)};i(T,e=>{n.data.technology&&e(O)});var k=u(T,2),A=e=>{var t=pe(),r=h(t,!0);w(t),N(()=>m(r,n.data.description)),a(e,t)};i(k,e=>{n.data.description&&e(A)}),w(_),F(u(_,2),{type:`source`,get position(){return P.Right}}),w(c),N(()=>{l=E(c,1,`q svelte-1s4sqjz`,null,l,{external:n.data.external,"is-selected":n.selected}),d=D(c,``,d,{"--fill":o(s)}),m(b,n.data.kind),m(C,n.data.label)}),f(`click`,c,()=>r?.selectElement(n.data.name)),f(`keydown`,c,e=>{e.key===`Enter`&&r?.selectElement(n.data.name)}),a(e,c),t()}T([`click`,`keydown`]);var ge=new(e(L(),1)).default,_e=e=>ge.layout(e),ve=220,ye=110,be=200,xe=130,Se=260,K=160,q=e=>`e:${e}`,J=e=>`b:${e}`,Y=e=>e===`Person`?{width:be,height:xe}:{width:ve,height:ye},X=e=>e===`Person`?`person`:e===`SystemDb`||e===`ContainerDb`||e===`ComponentDb`?`database`:e===`SystemQueue`||e===`ContainerQueue`||e===`ComponentQueue`?`queue`:`element`,Ce=e=>({name:e.name,label:e.label,kind:e.kind,description:e.description??``,external:e.external,technology:e.technology??``,tags:e.tags}),Z=(e,t)=>({name:e.name,label:e.label,kind:e.kind,childCount:e.elementNames.length+e.boundaryNames.length,expanded:t.expanded,canExpand:t.canExpand}),Q={"elk.algorithm":`layered`,"elk.direction":`RIGHT`,"elk.layered.spacing.nodeNodeBetweenLayers":`90`,"elk.spacing.nodeNode":`50`,"elk.spacing.edgeEdge":`20`,"elk.spacing.edgeNode":`30`,"elk.layered.spacing.edgeEdgeBetweenLayers":`20`,"elk.layered.spacing.edgeNodeBetweenLayers":`30`,"elk.padding":`[top=48, left=44, bottom=44, right=44]`},we=(e,t)=>!t||t<=1?e:e?`${e} · ×${t}`:`×${t}`,Te=async e=>{let t=e=>({source:e.fromKind===`boundary`?J(e.from):q(e.from),target:e.toKind===`boundary`?J(e.to):q(e.to)}),n=await _e({id:`root`,layoutOptions:Q,children:[...e.boundaries.map(e=>({id:J(e.name),width:Se,height:K})),...e.elements.map(e=>({id:q(e.name),...Y(e.kind)}))],edges:e.relations.map((e,n)=>{let{source:r,target:i}=t(e);return{id:`edge-${n}`,sources:[r],targets:[i]}})}),r=[];for(let t of e.boundaries){let e=J(t.name),i=n.children?.find(t=>t.id===e);r.push({id:e,type:`boundary`,position:{x:i?.x??0,y:i?.y??0},data:Z(t,{expanded:!1,canExpand:!1}),style:`width: ${i?.width??Se}px; height: ${i?.height??K}px;`})}for(let t of e.elements){let e=q(t.name),i=n.children?.find(t=>t.id===e),{width:a,height:o}=Y(t.kind);r.push({id:e,type:X(t.kind),position:{x:i?.x??0,y:i?.y??0},data:Ce(t),style:`width: ${a}px; height: ${o}px;`})}return{nodes:r,edges:e.relations.map((e,n)=>{let{source:r,target:i}=t(e);return{id:`edge-${n}`,source:r,target:i,label:we(e.label,e.count),type:`default`,animated:!1,data:{crossBoundary:!0},markerEnd:{type:I.ArrowClosed,width:24,height:24,color:`#cbd5e1`},style:`stroke: #94a3b8; stroke-width: 1.8;`}})}},Ee=e=>{let t=new Map;for(let n of Object.values(e.boundaries)){for(let e of n.boundaryNames)t.set(e,n.name);for(let e of n.elementNames)t.set(e,n.name)}return t},De=(e,t,n)=>{let r=new Map;for(let e of n)r.set(e,{kind:`element`,name:e});let i=(t,n)=>{for(let e of t.elementNames)r.has(e)||r.set(e,{kind:`boundary`,name:n.name});for(let r of t.boundaryNames){let t=e.boundaries[r];t&&i(t,n)}};for(let n of t){let t=e.boundaries[n];t&&i(t,t)}return r},$=(e,t)=>{let n=new Map;for(let r of Object.values(e.elements))for(let e of r.relations){let i=t.get(r.name),a=t.get(e.to);if(!i||!a)continue;let o=i.kind===`boundary`?J(i.name):q(i.name),s=a.kind===`boundary`?J(a.name):q(a.name);if(o===s)continue;let c=`${o}->${s}`,l=n.get(c);if(l){n.set(c,{...l,count:(l.count??1)+1});continue}n.set(c,{from:i.name,to:a.name,label:i.kind===`boundary`||a.kind===`boundary`?void 0:e.description,fromKind:i.kind,toKind:a.kind,count:1})}return[...n.values()]},Oe=(e,t)=>{let n=t[t.length-1]??{kind:`landscape`};if(n.kind===`landscape`){let t=(e.rootBoundaryNames??[]).map(t=>e.boundaries[t]).filter(e=>!!e),n=new Set(t.map(e=>e.name)),r=new Set,i=t=>{for(let e of t.elementNames)r.add(e);for(let n of t.boundaryNames){let t=e.boundaries[n];t&&i(t)}};for(let e of t)i(e);let a=Object.values(e.elements).filter(e=>!r.has(e.name));return{boundaries:t,elements:a,relations:$(e,De(e,n,new Set(a.map(e=>e.name))))}}let r=n.name?e.boundaries[n.name]:void 0;if(!r)return{boundaries:[],elements:[],relations:[]};let i=r.elementNames.map(t=>e.elements[t]).filter(e=>!!e),a=r.boundaryNames.map(t=>e.boundaries[t]).filter(e=>!!e);return{boundaries:a,elements:i,relations:$(e,De(e,new Set(a.map(e=>e.name)),new Set(i.map(e=>e.name))))}},ke={...Q,"elk.padding":`[top=96, left=44, bottom=44, right=44]`},Ae=(e,t,n,r,i)=>{let a=n=>{if(!t.has(n.name))return{id:J(n.name),width:Se,height:K};let r=[];for(let t of n.boundaryNames){let n=e.boundaries[t];n&&r.push(a(n))}for(let t of n.elementNames){let n=e.elements[t];n&&r.push({id:q(n.name),...Y(n.kind)})}return{id:J(n.name),children:r,layoutOptions:ke}};return{id:`root`,layoutOptions:{...Q,"elk.hierarchyHandling":`INCLUDE_CHILDREN`},children:[...n.map(a),...r.map(e=>({id:q(e.name),...Y(e.kind)}))],edges:[...i]}},je=(e,t,n,r)=>{let i=e,a=t;for(;;){let e=r.get(i);if(e===void 0||n.has(e))return{id:a===`boundary`?J(i):q(i),kind:a,name:i};i=e,a=`boundary`}},Me=(e,t,n,r)=>{let i=[];for(let a of e){let e=a.x??0,o=a.y??0,s=a.width??0,c=a.height??0,l=a.id.startsWith(`b:`),u=a.id.slice(2);if(l){let l=t.boundaries[u];if(!l)continue;let d=n.has(u),f={id:a.id,type:`boundary`,position:{x:e,y:o},data:Z(l,{expanded:d,canExpand:!0}),style:`width: ${s}px; height: ${c}px;`};r&&(f.parentId=r,f.extent=`parent`),i.push(f),d&&a.children?.length&&i.push(...Me(a.children,t,n,a.id))}else{let n=t.elements[u];if(!n)continue;let{width:l,height:d}=Y(n.kind),f={id:a.id,type:X(n.kind),position:{x:e,y:o},data:Ce(n),style:`width: ${s||l}px; height: ${c||d}px;`};r&&(f.parentId=r,f.extent=`parent`),i.push(f)}}return i},Ne=(e,t,n)=>{let r=n.get(e)??null,i=n.get(t)??null;return r===null||i===null||r!==i},Pe=(e,t,n)=>{let r=new Map,i=0;for(let a of Object.values(e.elements))for(let e of a.relations){let o=je(a.name,`element`,t,n),s=je(e.to,`element`,t,n);if(o.id===s.id)continue;let c=`${o.id}->${s.id}`,l=Ne(a.name,e.to,n),u=r.get(c);if(u){let e=u.data,t=(e?.relationCount??1)+1;r.set(c,{...u,label:we(e?.primaryLabel,t),data:{...e,crossBoundary:!!e?.crossBoundary||l,relationCount:t}});continue}let d=o.kind===`element`&&s.kind===`element`?e.description:void 0;r.set(c,{id:`edge-${i++}`,source:o.id,target:s.id,label:d,type:`default`,animated:!1,data:{crossBoundary:l,primaryLabel:d,relationCount:1},markerEnd:{type:I.ArrowClosed,width:24,height:24,color:`#cbd5e1`},style:`stroke: #94a3b8; stroke-width: 1.8;`})}return[...r.values()]},Fe=e=>{let t=(e.rootBoundaryNames??[]).map(t=>e.boundaries[t]).filter(e=>!!e),n=new Set,r=t=>{for(let e of t.elementNames)n.add(e);for(let n of t.boundaryNames){let t=e.boundaries[n];t&&r(t)}};for(let e of t)r(e);return{rootBoundaries:t,standalone:Object.values(e.elements).filter(e=>!n.has(e.name))}},Ie=async(e,t)=>{let{rootBoundaries:n,standalone:r}=Fe(e),i=Pe(e,t,Ee(e));return{nodes:Me((await _e(Ae(e,t,n,r,i.map(e=>({id:e.id,sources:[e.source],targets:[e.target]}))))).children??[],e,t,void 0),edges:i}},Le=e=>Ie(e,new Set(Object.keys(e.boundaries))),Re=p(`<span class="sep svelte-1r8vfx3" aria-hidden="true">·</span> <span class="workspace svelte-1r8vfx3"> </span>`,1),ze=p(`<span class="bsep svelte-1r8vfx3" aria-hidden="true">/</span>`),Be=p(`<!> <button class="bcrumb svelte-1r8vfx3"> </button>`,1),Ve=p(`<nav class="breadcrumb svelte-1r8vfx3" aria-label="Drill path"></nav>`),He=p(`<div class="expand-controls svelte-1r8vfx3"><button class="ghost svelte-1r8vfx3">Expand all</button> <button class="ghost svelte-1r8vfx3">Collapse all</button> <span class="hint svelte-1r8vfx3">double-click a boundary to toggle</span></div>`),Ue=p(`<span class="hint svelte-1r8vfx3">full hierarchy — read-only overview</span>`),We=p(`<!> <!> <!>`,1),Ge=p(`<span> </span>`),Ke=p(`<span> </span>`),qe=p(`<aside class="error-overlay svelte-1r8vfx3" role="status" aria-live="polite"><span class="error-kicker svelte-1r8vfx3">Reload failed</span> <p class="svelte-1r8vfx3"> </p> <div class="error-meta svelte-1r8vfx3"><!> <span> </span> <!></div></aside>`),Je=p(`<p class="tech svelte-1r8vfx3"> </p>`),Ye=p(`<p class="desc svelte-1r8vfx3"> </p>`),Xe=p(`<span class="tag svelte-1r8vfx3"> </span>`),Ze=p(`<div class="field svelte-1r8vfx3"><span class="k svelte-1r8vfx3">tags</span> <span class="v"></span></div>`),Qe=p(`<span class="prop svelte-1r8vfx3"><span class="prop-key svelte-1r8vfx3"> </span> </span>`),$e=p(`<div class="field svelte-1r8vfx3"><span class="k svelte-1r8vfx3">props</span> <span class="v props svelte-1r8vfx3"></span></div>`),et=p(`<div class="field svelte-1r8vfx3"><span class="k svelte-1r8vfx3">source</span> <span class="v"><a class="svelte-1r8vfx3"> </a></span></div>`),tt=p(`<li class="svelte-1r8vfx3"> </li>`),nt=p(`<h4 class="svelte-1r8vfx3">Issues</h4> <ul class="issues svelte-1r8vfx3"></ul>`,1),rt=p(`<span class="rdesc svelte-1r8vfx3"> </span>`),it=p(`<span class="rmeta svelte-1r8vfx3"> </span>`),at=p(`<li class="svelte-1r8vfx3"><span class="arrow svelte-1r8vfx3">→</span> <span class="to svelte-1r8vfx3"> </span> <!> <!></li>`),ot=p(`<h4 class="svelte-1r8vfx3">Outgoing relations</h4> <ul class="relations svelte-1r8vfx3"></ul>`,1),st=p(`<span class="rdesc svelte-1r8vfx3"> </span>`),ct=p(`<span class="rmeta svelte-1r8vfx3"> </span>`),lt=p(`<li class="svelte-1r8vfx3"><span class="arrow svelte-1r8vfx3">←</span> <span class="to svelte-1r8vfx3"> </span> <!> <!></li>`),ut=p(`<h4 class="svelte-1r8vfx3">Incoming relations</h4> <ul class="relations svelte-1r8vfx3"></ul>`,1),dt=p(`<h2 class="svelte-1r8vfx3"> </h2> <h3 class="title svelte-1r8vfx3"> </h3> <!> <!> <!> <!> <!> <!> <!> <!>`,1),ft=p(`<p class="desc svelte-1r8vfx3"> </p>`),pt=p(`<span class="tag svelte-1r8vfx3"> </span>`),mt=p(`<div class="field svelte-1r8vfx3"><span class="k svelte-1r8vfx3">tags</span> <span class="v"></span></div>`),ht=p(`<span class="prop svelte-1r8vfx3"><span class="prop-key svelte-1r8vfx3"> </span> </span>`),gt=p(`<div class="field svelte-1r8vfx3"><span class="k svelte-1r8vfx3">props</span> <span class="v props svelte-1r8vfx3"></span></div>`),_t=p(`<div class="field svelte-1r8vfx3"><span class="k svelte-1r8vfx3">source</span> <span class="v"><a class="svelte-1r8vfx3"> </a></span></div>`),vt=p(`<li class="svelte-1r8vfx3"> </li>`),yt=p(`<h4 class="svelte-1r8vfx3">Issues</h4> <ul class="issues svelte-1r8vfx3"></ul>`,1),bt=p(`<h2 class="svelte-1r8vfx3"> </h2> <h3 class="title svelte-1r8vfx3"> </h3> <!> <div class="field svelte-1r8vfx3"><span class="k svelte-1r8vfx3">children</span> <span class="v"> </span></div> <!> <!> <!> <!> <p class="hint svelte-1r8vfx3"><!></p>`,1),xt=p(`<p class="desc svelte-1r8vfx3"> </p>`),St=p(`<div class="warn svelte-1r8vfx3"><span class="num svelte-1r8vfx3"> </span> loader issues</div>`),Ct=p(`<div class="stats svelte-1r8vfx3"><div class="svelte-1r8vfx3"><span class="num svelte-1r8vfx3"> </span> elements</div> <div class="svelte-1r8vfx3"><span class="num svelte-1r8vfx3"> </span> boundaries</div> <div class="svelte-1r8vfx3"><span class="num svelte-1r8vfx3"> </span> relations</div> <!></div>`),wt=p(`<li class="svelte-1r8vfx3"> </li>`),Tt=p(`<h4 class="svelte-1r8vfx3">Loader issues</h4> <ul class="issues svelte-1r8vfx3"></ul>`,1),Et=p(`<h2 class="svelte-1r8vfx3">Workspace</h2> <h3 class="title svelte-1r8vfx3"> </h3> <!> <!> <!> <p class="hint svelte-1r8vfx3">Click a node to inspect. Switch modes in the top bar to
|
|
3
|
-
change how the hierarchy unfolds.</p>`,1),Dt=p(`<p class="hint svelte-1r8vfx3">Loading model…</p>`),Ot=p(`<div class="app svelte-1r8vfx3"><header class="topbar svelte-1r8vfx3"><div class="brand svelte-1r8vfx3"><span class="logo svelte-1r8vfx3">aact</span> <span class="sep svelte-1r8vfx3" aria-hidden="true">·</span> <span class="title svelte-1r8vfx3">view</span> <!> <span><!></span></div> <div class="topbar-controls svelte-1r8vfx3"><div class="modes svelte-1r8vfx3" role="tablist" aria-label="View mode"><button role="tab" title="Replace the canvas with the boundary you double-click">Drill</button> <button role="tab" title="Open boundaries inline — parents stay visible">Expand</button> <button role="tab" title="Render every level of the hierarchy at once">Flat</button></div> <div class="modes edge-modes svelte-1r8vfx3" role="tablist" aria-label="Edge style"><button role="tab" title="Smooth bezier curves">Curve</button> <button role="tab" title="Rounded 90° corners — Structurizr-style">Smooth</button> <button role="tab" title="Sharp 90° corners">Step</button></div> <div class="modes edge-modes svelte-1r8vfx3" role="tablist" aria-label="Edge filter"><button role="tab" title="Show every relation">All</button> <button role="tab" title="Highlight relations that cross a Bounded Context; intra-boundary stays faint">Cross-BC</button></div></div> <div class="context svelte-1r8vfx3"><!></div></header> <main class="svelte-1r8vfx3"><div class="graph svelte-1r8vfx3"><!> <aside class="legend svelte-1r8vfx3" aria-label="C4 element palette"><span class="legend-row svelte-1r8vfx3"><span class="swatch svelte-1r8vfx3" style="background: #08427b;"></span>Person</span> <span class="legend-row svelte-1r8vfx3"><span class="swatch svelte-1r8vfx3" style="background: #1168bd;"></span>System</span> <span class="legend-row svelte-1r8vfx3"><span class="swatch svelte-1r8vfx3" style="background: #438dd5;"></span>Container</span> <span class="legend-row svelte-1r8vfx3"><span class="swatch svelte-1r8vfx3" style="background: #85bbf0;"></span>Component</span> <span class="legend-row svelte-1r8vfx3"><span class="swatch svelte-1r8vfx3" style="background: #475569;"></span>External</span></aside> <!></div> <aside class="details svelte-1r8vfx3"><!></aside></main></div>`);function kt(e,p){S(p,!0);let v=`aact-view:edge-style`,T=`aact-view:edge-filter`,D=typeof localStorage<`u`&&localStorage.getItem(v)||`bezier`,j=typeof localStorage<`u`&&localStorage.getItem(T)||`all`,P=_(null),F=_(`drill`),L=_(O(D)),z=_(O(j)),B=_(O([{kind:`landscape`}])),V=_(O(new Set)),H=_(null),U=_(null),se=_(O([])),ce=_(O([])),W=_(`connecting`),G=_(null),ue={element:le,person:de,database:oe,queue:he,boundary:ae};r(()=>{if(!o(P))return;let e=!1;return(async()=>{if(o(F)===`drill`){let t=await Te(Oe(o(P).data.model,o(B)));if(e)return;l(se,t.nodes,!0),l(ce,t.edges,!0)}else if(o(F)===`expand`){let t=await Ie(o(P).data.model,o(V));if(e)return;l(se,t.nodes,!0),l(ce,t.edges,!0)}else{let t=await Le(o(P).data.model);if(e)return;l(se,t.nodes,!0),l(ce,t.edges,!0)}})(),()=>{e=!0}});let fe=typeof location<`u`?new URLSearchParams(location.search).get(`token`):null,pe=e=>fe?`${e}?token=${encodeURIComponent(fe)}`:e,me=async()=>{let e=await fetch(pe(`/api/model`));if(!e.ok)throw Error(`/api/model returned ${e.status}`);return await e.json()},ge=`${location.protocol===`https:`?`wss:`:`ws:`}//${location.host}${pe(`/api/ws`)}`,_e=e=>({message:e instanceof Error?e.message:String(e),source:o(P)?.meta.source??null,configPath:o(P)?.meta.configPath??null,durationMs:0,at:new Date().toISOString()}),ve=()=>{let e=new WebSocket(ge);e.addEventListener(`open`,()=>{l(W,`live`)}),e.addEventListener(`message`,e=>{try{let t=JSON.parse(e.data);t.type===`model-update`&&(l(P,t.envelope,!0),l(G,null),l(W,`live`)),t.type===`model-error`&&(l(G,t.error,!0),l(W,`error`))}catch{}}),e.addEventListener(`close`,()=>{l(W,`lost`),setTimeout(ve,1e3)}),e.addEventListener(`error`,()=>e.close())};me().then(e=>{l(P,e,!0),l(G,null),ve()}).catch(e=>{l(G,_e(e),!0),l(W,`error`),ve()});let ye=({node:e})=>{e.type===`boundary`?l(H,{kind:`boundary`,name:String(e.data.name)},!0):l(H,{kind:`element`,name:String(e.data.name)},!0)},be=({node:e})=>{l(U,e.id,!0)},xe=()=>{l(U,null)};A(R,{selectElement:e=>{l(H,{kind:`element`,name:e},!0)},selectBoundary:e=>{l(H,{kind:`boundary`,name:e},!0)},enterBoundary:(e,t)=>{o(F)===`drill`&&(l(B,[...o(B),{kind:`boundary`,name:e,label:t}],!0),l(H,null))},toggleBoundary:e=>{if(o(F)!==`expand`)return;let t=new Set(o(V));t.has(e)?t.delete(e):t.add(e),l(V,t,!0)}});let Se=e=>{l(B,o(B).slice(0,e+1),!0),l(H,null)},K=e=>{l(F,e,!0),l(H,null),e===`drill`&&l(B,[{kind:`landscape`}],!0),e===`expand`&&l(V,new Set,!0)},q=()=>{l(V,new Set,!0)},J=()=>{o(P)&&l(V,new Set(Object.keys(o(P).data.model.boundaries)),!0)},Y=g(()=>o(H)?.kind===`element`&&o(P)?o(P).data.model.elements[o(H).name]??null:null),X=g(()=>o(H)?.kind===`boundary`&&o(P)?o(P).data.model.boundaries[o(H).name]??null:null),Ce=g(()=>o(Y)&&o(P)?Object.values(o(P).data.model.elements).flatMap(e=>e.relations.filter(e=>e.to===o(Y).name).map(t=>({from:e.name,relation:t}))):[]),Z=g(()=>o(H)&&o(P)?o(P).data.issues.filter(e=>o(H).kind===`element`?e.element===o(H).name:e.boundary===o(H).name):[]),Q=e=>{l(L,e,!0),typeof localStorage<`u`&&localStorage.setItem(v,e)},we=e=>{l(z,e,!0),typeof localStorage<`u`&&localStorage.setItem(T,e)},Ee=e=>!!e.data?.crossBoundary,De=g(()=>o(ce).map(e=>{let t=o(U)!==null&&(e.source===o(U)||e.target===o(U)),n=o(z)===`cross-boundary`,r=Ee(e),i=n&&!r,a=n&&r;if(i&&!t)return{...e,type:o(L),animated:!1,label:void 0,style:`stroke: #1e293b; stroke-width: 0.8; opacity: 0.12;`,markerEnd:{type:I.ArrowClosed,width:16,height:16,color:`#1e293b`}};if(a&&!o(U))return{...e,type:o(L),animated:!1,style:`stroke: #38bdf8; stroke-width: 2.2; opacity: 1;`,markerEnd:{type:I.ArrowClosed,width:26,height:26,color:`#38bdf8`}};if(!o(U))return{...e,type:o(L)};let s=t?`#38bdf8`:`#475569`;return{...e,type:o(L),animated:t,label:t?e.label:void 0,style:t?`stroke: #38bdf8; stroke-width: 2.4; opacity: 1;`:`stroke: #475569; stroke-width: 1.2; opacity: 0.35;`,markerEnd:{type:I.ArrowClosed,width:24,height:24,color:s}}})),$=g(()=>o(P)?{elements:Object.keys(o(P).data.model.elements).length,boundaries:Object.keys(o(P).data.model.boundaries).length,relations:Object.values(o(P).data.model.elements).reduce((e,t)=>e+t.relations.length,0),issues:o(P).data.issues.length}:null),ke=(e,t,n)=>`${typeof window<`u`&&window.__AACT_OPENER__||`vscode`}://file/${e.split(`/`).map(e=>encodeURIComponent(e)).join(`/`)}:${t}:${n}`,Ae=e=>Object.entries(e??{}),je=e=>e.message?`${e.kind}: ${e.message}`:e.kind,Me=e=>{let t=String(e.data?.kind),n=!!e.data?.external;return e.type===`person`?`#08427b`:n?`#475569`:t===`System`?`#1168bd`:t===`Container`?`#438dd5`:t===`Component`?`#85bbf0`:`#64748b`};var Ne=Ot();y(`1r8vfx3`,e=>{d(()=>{c.title=`aact view`})});var Pe=h(Ne),Fe=h(Pe),kt=u(h(Fe),6),At=e=>{var t=Re(),n=u(s(t),2),r=h(n,!0);w(n),N(()=>{C(n,`title`,o(P).data.model.workspace.description??``),m(r,o(P).data.model.workspace.name)}),a(e,t)};i(kt,e=>{o(P)?.data.model.workspace?.name&&e(At)});var jt=u(kt,2),Mt=h(jt),Nt=e=>{a(e,n(`● live`))},Pt=e=>{a(e,n(`● reload error`))},Ft=e=>{a(e,n(`● disconnected — retrying`))},It=e=>{a(e,n(`● connecting`))};i(Mt,e=>{o(W)===`live`?e(Nt):o(W)===`error`?e(Pt,1):o(W)===`lost`?e(Ft,2):e(It,-1)}),w(jt),w(Fe);var Lt=u(Fe,2),Rt=h(Lt),zt=h(Rt);let Bt;var Vt=u(zt,2);let Ht;var Ut=u(Vt,2);let Wt;w(Rt);var Gt=u(Rt,2),Kt=h(Gt);let qt;var Jt=u(Kt,2);let Yt;var Xt=u(Jt,2);let Zt;w(Gt);var Qt=u(Gt,2),$t=h(Qt);let en;var tn=u($t,2);let nn;w(Qt),w(Lt);var rn=u(Lt,2),an=h(rn),on=e=>{var t=Ve();b(t,21,()=>o(B),M,(e,t,n)=>{var r=Be(),c=s(r),l=e=>{a(e,ze())};i(c,e=>{n>0&&e(l)});var d=u(c,2),p=h(d,!0);w(d),N(()=>m(p,o(t).kind===`landscape`?`Landscape`:o(t).label)),f(`click`,d,()=>Se(n)),a(e,r)}),w(t),a(e,t)},sn=e=>{var t=He(),n=h(t),r=u(n,2);k(2),w(t),f(`click`,n,J),f(`click`,r,q),a(e,t)},cn=e=>{a(e,Ue())};i(an,e=>{o(F)===`drill`?e(on):o(F)===`expand`?e(sn,1):e(cn,-1)}),w(rn),w(Pe);var ln=u(Pe,2),un=h(ln),dn=h(un);te(dn,{children:(e,t)=>{{let t=g(()=>({type:o(L),animated:!1}));ee(e,{get nodes(){return o(se)},get edges(){return o(De)},get nodeTypes(){return ue},onnodeclick:ye,onnodepointerenter:be,onnodepointerleave:xe,fitView:!0,fitViewOptions:{padding:.18,duration:400},nodesDraggable:!1,nodesConnectable:!1,elementsSelectable:!0,panOnDrag:!0,zoomOnDoubleClick:!1,minZoom:.1,maxZoom:2,get defaultEdgeOptions(){return o(t)},children:(e,t)=>{var n=We(),r=s(n);ne(r,{});var i=u(r,2);re(i,{}),ie(u(i,2),{pannable:!0,zoomable:!0,nodeColor:Me,maskColor:`rgba(15, 23, 42, 0.7)`,style:`background: #0b1220;`}),a(e,n)},$$slots:{default:!0}})}},$$slots:{default:!0}});var fn=u(dn,4),pn=e=>{var t=qe(),n=u(h(t),2),r=h(n,!0);w(n);var s=u(n,2),c=h(s),l=e=>{var t=Ge(),n=h(t,!0);w(t),N(()=>m(n,o(G).source)),a(e,t)};i(c,e=>{o(G).source&&e(l)});var d=u(c,2),f=h(d,!0);w(d);var p=u(d,2),g=e=>{var t=Ke(),n=h(t);w(t),N(()=>m(n,`${o(G).durationMs??``} ms`)),a(e,t)};i(p,e=>{o(G).durationMs>0&&e(g)}),w(s),w(t),N(e=>{m(r,o(G).message),m(f,e)},[()=>new Date(o(G).at).toLocaleTimeString()]),a(e,t)};i(fn,e=>{o(G)&&e(pn)}),w(un);var mn=u(un,2),hn=h(mn),gn=e=>{var t=dt(),n=s(t),r=h(n);w(n);var c=u(n,2),l=h(c,!0);w(c);var d=u(c,2),f=e=>{var t=Je(),n=h(t);w(t),N(()=>m(n,`[${o(Y).technology??``}]`)),a(e,t)};i(d,e=>{o(Y).technology&&e(f)});var p=u(d,2),_=e=>{var t=Ye(),n=h(t,!0);w(t),N(()=>m(n,o(Y).description)),a(e,t)};i(p,e=>{o(Y).description&&e(_)});var v=u(p,2),y=e=>{var t=Ze(),n=u(h(t),2);b(n,20,()=>o(Y).tags,e=>e,(e,t)=>{var n=Xe(),r=h(n,!0);w(n),N(()=>m(r,t)),a(e,n)}),w(n),w(t),a(e,t)};i(v,e=>{o(Y).tags.length&&e(y)});var S=u(v,2),T=e=>{var t=$e(),n=u(h(t),2);b(n,21,()=>Ae(o(Y).properties),([e,t])=>e,(e,t)=>{var n=g(()=>x(o(t),2));let r=()=>o(n)[0],i=()=>o(n)[1];var s=Qe(),c=h(s),l=h(c,!0);w(c);var d=u(c,1,!0);w(s),N(()=>{m(l,r()),m(d,i())}),a(e,s)}),w(n),w(t),a(e,t)},E=g(()=>Ae(o(Y).properties).length);i(S,e=>{o(E)&&e(T)});var D=u(S,2),O=e=>{var t=et(),n=u(h(t),2),r=h(n),i=h(r);w(r),w(n),w(t),N((e,t)=>{C(r,`href`,e),m(i,`${t??``}:${o(Y).sourceLocation.start.line??``}:${o(Y).sourceLocation.start.col??``}`)},[()=>ke(o(Y).sourceLocation.file,o(Y).sourceLocation.start.line,o(Y).sourceLocation.start.col),()=>o(Y).sourceLocation.file.split(`/`).pop()]),a(e,t)};i(D,e=>{o(Y).sourceLocation&&e(O)});var k=u(D,2),A=e=>{var t=nt(),n=u(s(t),2);b(n,21,()=>o(Z),M,(e,t)=>{var n=tt(),r=h(n,!0);w(n),N(e=>m(r,e),[()=>je(o(t))]),a(e,n)}),w(n),a(e,t)};i(k,e=>{o(Z).length&&e(A)});var j=u(k,2),ee=e=>{var t=ot(),n=u(s(t),2);b(n,21,()=>o(Y).relations,M,(e,t)=>{var n=at(),r=u(h(n),2),s=h(r,!0);w(r);var c=u(r,2),l=e=>{var n=rt(),r=h(n,!0);w(n),N(()=>m(r,o(t).description)),a(e,n)};i(c,e=>{o(t).description&&e(l)});var d=u(c,2),f=e=>{var n=it(),r=h(n);w(n),N(()=>m(r,`[${o(t).technology??``}]`)),a(e,n)};i(d,e=>{o(t).technology&&e(f)}),w(n),N(()=>m(s,o(t).to)),a(e,n)}),w(n),a(e,t)};i(j,e=>{o(Y).relations.length&&e(ee)});var P=u(j,2),te=e=>{var t=ut(),n=u(s(t),2);b(n,21,()=>o(Ce),M,(e,t)=>{var n=lt(),r=u(h(n),2),s=h(r,!0);w(r);var c=u(r,2),l=e=>{var n=st(),r=h(n,!0);w(n),N(()=>m(r,o(t).relation.description)),a(e,n)};i(c,e=>{o(t).relation.description&&e(l)});var d=u(c,2),f=e=>{var n=ct(),r=h(n);w(n),N(()=>m(r,`[${o(t).relation.technology??``}]`)),a(e,n)};i(d,e=>{o(t).relation.technology&&e(f)}),w(n),N(()=>m(s,o(t).from)),a(e,n)}),w(n),a(e,t)};i(P,e=>{o(Ce).length&&e(te)}),N(()=>{m(r,`${o(Y).kind??``}${o(Y).external?` · external`:``}`),m(l,o(Y).label)}),a(e,t)},_n=e=>{var t=bt(),r=s(t),c=h(r);w(r);var l=u(r,2),d=h(l,!0);w(l);var f=u(l,2),p=e=>{var t=ft(),n=h(t,!0);w(t),N(()=>m(n,o(X).description)),a(e,t)};i(f,e=>{o(X).description&&e(p)});var _=u(f,2),v=u(h(_),2),y=h(v);w(v),w(_);var S=u(_,2),T=e=>{var t=mt(),n=u(h(t),2);b(n,20,()=>o(X).tags,e=>e,(e,t)=>{var n=pt(),r=h(n,!0);w(n),N(()=>m(r,t)),a(e,n)}),w(n),w(t),a(e,t)};i(S,e=>{o(X).tags.length&&e(T)});var E=u(S,2),D=e=>{var t=gt(),n=u(h(t),2);b(n,21,()=>Ae(o(X).properties),([e,t])=>e,(e,t)=>{var n=g(()=>x(o(t),2));let r=()=>o(n)[0],i=()=>o(n)[1];var s=ht(),c=h(s),l=h(c,!0);w(c);var d=u(c,1,!0);w(s),N(()=>{m(l,r()),m(d,i())}),a(e,s)}),w(n),w(t),a(e,t)},O=g(()=>Ae(o(X).properties).length);i(E,e=>{o(O)&&e(D)});var k=u(E,2),A=e=>{var t=_t(),n=u(h(t),2),r=h(n),i=h(r);w(r),w(n),w(t),N((e,t)=>{C(r,`href`,e),m(i,`${t??``}:${o(X).sourceLocation.start.line??``}:${o(X).sourceLocation.start.col??``}`)},[()=>ke(o(X).sourceLocation.file,o(X).sourceLocation.start.line,o(X).sourceLocation.start.col),()=>o(X).sourceLocation.file.split(`/`).pop()]),a(e,t)};i(k,e=>{o(X).sourceLocation&&e(A)});var j=u(k,2),ee=e=>{var t=yt(),n=u(s(t),2);b(n,21,()=>o(Z),M,(e,t)=>{var n=vt(),r=h(n,!0);w(n),N(e=>m(r,e),[()=>je(o(t))]),a(e,n)}),w(n),a(e,t)};i(j,e=>{o(Z).length&&e(ee)});var P=u(j,2),te=h(P),ne=e=>{a(e,n(`Double-click to enter this boundary.`))},re=e=>{var t=n();N(e=>m(t,`Double-click to ${e??``} this boundary.`),[()=>o(V).has(o(X).name)?`collapse`:`expand`]),a(e,t)},I=e=>{a(e,n(`This boundary is part of the full hierarchy.`))};i(te,e=>{o(F)===`drill`?e(ne):o(F)===`expand`?e(re,1):e(I,-1)}),w(P),N(()=>{m(c,`${o(X).kind??``} boundary`),m(d,o(X).label),m(y,`${o(X).elementNames.length??``} elements · ${o(X).boundaryNames.length??``} boundaries`)}),a(e,t)},vn=e=>{var t=Et(),n=u(s(t),2),r=h(n,!0);w(n);var c=u(n,2),l=e=>{var t=xt(),n=h(t,!0);w(t),N(()=>m(n,o(P).data.model.workspace.description)),a(e,t)};i(c,e=>{o(P).data.model.workspace.description&&e(l)});var d=u(c,2),f=e=>{var t=Ct(),n=h(t),r=h(n),s=h(r,!0);w(r),k(),w(n);var c=u(n,2),l=h(c),d=h(l,!0);w(l),k(),w(c);var f=u(c,2),p=h(f),g=h(p,!0);w(p),k(),w(f);var _=u(f,2),v=e=>{var t=St(),n=h(t),r=h(n,!0);w(n),k(),w(t),N(()=>m(r,o($).issues)),a(e,t)};i(_,e=>{o($).issues>0&&e(v)}),w(t),N(()=>{m(s,o($).elements),m(d,o($).boundaries),m(g,o($).relations)}),a(e,t)};i(d,e=>{o($)&&e(f)});var p=u(d,2),g=e=>{var t=Tt(),n=u(s(t),2);b(n,21,()=>o(P).data.issues,M,(e,t)=>{var n=wt(),r=h(n,!0);w(n),N(e=>m(r,e),[()=>je(o(t))]),a(e,n)}),w(n),a(e,t)};i(p,e=>{o(P).data.issues.length&&e(g)}),k(2),N(()=>m(r,o(P).data.model.workspace.name??`(unnamed)`)),a(e,t)},yn=e=>{a(e,Dt())};i(hn,e=>{o(Y)?e(gn):o(X)?e(_n,1):o(P)?.data.model.workspace?e(vn,2):e(yn,-1)}),w(mn),w(ln),w(Ne),N(()=>{E(jt,1,`status status-${o(W)??``}`,`svelte-1r8vfx3`),C(zt,`aria-selected`,o(F)===`drill`),Bt=E(zt,1,`svelte-1r8vfx3`,null,Bt,{active:o(F)===`drill`}),C(Vt,`aria-selected`,o(F)===`expand`),Ht=E(Vt,1,`svelte-1r8vfx3`,null,Ht,{active:o(F)===`expand`}),C(Ut,`aria-selected`,o(F)===`flat`),Wt=E(Ut,1,`svelte-1r8vfx3`,null,Wt,{active:o(F)===`flat`}),C(Kt,`aria-selected`,o(L)===`bezier`),qt=E(Kt,1,`svelte-1r8vfx3`,null,qt,{active:o(L)===`bezier`}),C(Jt,`aria-selected`,o(L)===`smoothstep`),Yt=E(Jt,1,`svelte-1r8vfx3`,null,Yt,{active:o(L)===`smoothstep`}),C(Xt,`aria-selected`,o(L)===`step`),Zt=E(Xt,1,`svelte-1r8vfx3`,null,Zt,{active:o(L)===`step`}),C($t,`aria-selected`,o(z)===`all`),en=E($t,1,`svelte-1r8vfx3`,null,en,{active:o(z)===`all`}),C(tn,`aria-selected`,o(z)===`cross-boundary`),nn=E(tn,1,`svelte-1r8vfx3`,null,nn,{active:o(z)===`cross-boundary`})}),f(`click`,zt,()=>K(`drill`)),f(`click`,Vt,()=>K(`expand`)),f(`click`,Ut,()=>K(`flat`)),f(`click`,Kt,()=>Q(`bezier`)),f(`click`,Jt,()=>Q(`smoothstep`)),f(`click`,Xt,()=>Q(`step`)),f(`click`,$t,()=>we(`all`)),f(`click`,tn,()=>we(`cross-boundary`)),a(e,Ne),t()}T([`click`]);var At=document.querySelector(`#app`);if(!At)throw Error(`aact view: #app mount point missing in index.html`);j(kt,{target:At});
|
|
4
|
-
//# sourceMappingURL=index-D2ZA0Nkz.js.map
|