OR-1 dataflow CPU sketch

feat: wire up SVG and PNG export buttons

Orual cb0eb08f dc2a12a5

+16 -1
+6 -1
dfgraph/frontend/index.html
··· 9 9 body { font-family: system-ui, sans-serif; height: 100vh; display: flex; flex-direction: column; } 10 10 #toolbar { padding: 8px 16px; background: #1a1a2e; color: #eee; display: flex; align-items: center; gap: 12px; } 11 11 #toolbar h1 { font-size: 14px; font-weight: 600; } 12 - #view-toggle { padding: 6px 12px; background: #5c6bc0; color: #eee; border: none; border-radius: 4px; cursor: pointer; font-size: 12px; font-weight: 500; } 12 + #toolbar button { background: #2a2a4a; color: #eee; border: 1px solid #444; padding: 4px 12px; border-radius: 4px; cursor: pointer; font-size: 12px; } 13 + #toolbar button:hover { background: #3a3a5a; } 14 + #view-toggle { background: #5c6bc0; border: none; font-weight: 500; } 13 15 #view-toggle:hover { background: #3f51b5; } 14 16 #graph { flex: 1; position: relative; } 15 17 #error-panel { ··· 66 68 <div id="toolbar"> 67 69 <h1>dfgraph</h1> 68 70 <button id="view-toggle">Physical View</button> 71 + <button id="export-svg">Export SVG</button> 72 + <button id="export-png">Export PNG</button> 73 + <button id="copy-png">Copy PNG</button> 69 74 </div> 70 75 <div id="graph"> 71 76 <div id="parse-error-overlay" aria-live="polite"></div>
+10
dfgraph/frontend/src/main.ts
··· 1 1 import cytoscape from "cytoscape"; 2 2 import dagre from "cytoscape-dagre"; 3 + import svg from "cytoscape-svg"; 3 4 import type { GraphUpdate, GraphNode, GraphEdge, GraphRegion } from "./types"; 4 5 import { stylesheet } from "./style"; 5 6 import { logicalLayout, physicalLayout } from "./layout"; 7 + import { exportSvg, exportPng, copyPng } from "./export"; 6 8 7 9 cytoscape.use(dagre); 10 + cytoscape.use(svg); 8 11 9 12 const ROUTING_CATEGORY = "routing"; 10 13 ··· 271 274 } 272 275 } 273 276 277 + function setupExportButtons(): void { 278 + document.getElementById("export-svg")?.addEventListener("click", () => exportSvg(cy)); 279 + document.getElementById("export-png")?.addEventListener("click", () => exportPng(cy)); 280 + document.getElementById("copy-png")?.addEventListener("click", () => copyPng(cy)); 281 + } 282 + 274 283 function connect(): void { 275 284 const protocol = location.protocol === "https:" ? "wss:" : "ws:"; 276 285 const ws = new WebSocket(`${protocol}//${location.host}/ws`); ··· 288 297 } 289 298 290 299 setupToggleButton(); 300 + setupExportButtons(); 291 301 connect();