@elixpo/lixsketch 5.5.10 → 5.5.11

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.
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/core/AIRenderer.js"],
4
- "sourcesContent": ["/* eslint-disable */\n/**\n * AIRenderer - Converts diagram JSON into shapes on the canvas.\n *\n * Two entry points:\n * 1. renderAIDiagram(diagram) - from AI text-to-diagram response\n * 2. window.__mermaidRenderer(src) - direct algorithmic Mermaid parser\n *\n * Smart edge routing:\n * - Straight arrows/lines for vertically or horizontally aligned nodes\n * - Curved arrows for diagonal connections or when edges would overlap\n * - Elbow connections for right-angle routing when appropriate\n *\n * All created shapes belong to a Frame with auto-attachment so\n * moving nodes keeps edges connected.\n */\n\nconst PADDING = 80;\nconst NODE_W = 160;\nconst NODE_H = 60;\nconst H_SPACING = 260;\nconst V_SPACING = 180;\nconst NS = 'http://www.w3.org/2000/svg';\n\n// Alignment threshold \u2014 if nodes are within this many pixels\n// of being aligned, treat them as aligned (use straight edge)\nconst ALIGN_THRESHOLD = 30;\n\n// ============================================================\n// MERMAID PARSER\n// ============================================================\n\nexport function parseMermaid(src) {\n const lines = src.trim().split('\\n').map(l => l.trim()).filter(l => l && !l.startsWith('%%'));\n if (lines.length === 0) return null;\n\n const headerMatch = lines[0].match(/^(graph|flowchart)\\s+(TD|TB|LR|RL|BT)/i);\n const direction = headerMatch ? headerMatch[2].toUpperCase() : 'TD';\n const isHorizontal = direction === 'LR' || direction === 'RL';\n const startIdx = headerMatch ? 1 : 0;\n\n const nodesMap = new Map();\n const edges = [];\n const classDefs = new Map(); // classDef name -> { fill, stroke, strokeWidth }\n const classAssigns = []; // { nodeIds: [...], className }\n\n // Clean <br/> and <br> tags in labels \u2192 newline marker\n function cleanLabel(label) {\n return label.replace(/<br\\s*\\/?>/gi, '\\n').replace(/\"/g, '');\n }\n\n function parseNodeRef(raw) {\n raw = raw.trim();\n if (!raw) return null;\n let id, label, type;\n\n // Circle: id((label))\n let m = raw.match(/^(\\w+)\\(\\((.+?)\\)\\)$/);\n if (m) { id = m[1]; label = m[2]; type = 'circle'; }\n // Diamond: id{label}\n if (!m) { m = raw.match(/^(\\w+)\\{(.+?)\\}$/); if (m) { id = m[1]; label = m[2]; type = 'diamond'; } }\n // Asymmetric/flag: id>label]\n if (!m) { m = raw.match(/^(\\w+)>(.+?)\\]$/); if (m) { id = m[1]; label = m[2]; type = 'asymmetric'; } }\n // Rounded rect: id(label)\n if (!m) { m = raw.match(/^(\\w+)\\((.+?)\\)$/); if (m) { id = m[1]; label = m[2]; type = 'roundrect'; } }\n // Rectangle: id[label]\n if (!m) { m = raw.match(/^(\\w+)\\[(.+?)\\]$/); if (m) { id = m[1]; label = m[2]; type = 'rectangle'; } }\n // Plain id\n if (!m) { id = raw; label = raw; type = 'rectangle'; }\n\n label = cleanLabel(label);\n\n if (!nodesMap.has(id)) {\n nodesMap.set(id, { id, type, label });\n } else if (label !== id) {\n nodesMap.get(id).label = label;\n nodesMap.get(id).type = type;\n }\n return id;\n }\n\n // Parse subgraphs\n const subgraphs = [];\n let currentSubgraph = null;\n\n for (let i = startIdx; i < lines.length; i++) {\n const line = lines[i].replace(/;$/, '').trim();\n if (!line) continue;\n\n // classDef: classDef green fill:#9f6,stroke:#333,stroke-width:2px;\n const classDefMatch = line.match(/^classDef\\s+(\\w+)\\s+(.+)$/i);\n if (classDefMatch) {\n const name = classDefMatch[1];\n const propsStr = classDefMatch[2].replace(/;$/, '');\n const props = {};\n for (const part of propsStr.split(',')) {\n const [key, val] = part.split(':').map(s => s.trim());\n if (key === 'fill') props.fill = val;\n else if (key === 'stroke') props.stroke = val;\n else if (key === 'stroke-width') props.strokeWidth = parseFloat(val);\n }\n classDefs.set(name, props);\n continue;\n }\n\n // class assignment: class sq,e green\n const classMatch = line.match(/^class\\s+(.+?)\\s+(\\w+)$/i);\n if (classMatch) {\n const nodeIds = classMatch[1].split(',').map(s => s.trim());\n classAssigns.push({ nodeIds, className: classMatch[2] });\n continue;\n }\n\n // Subgraph start: subgraph ID [\"Label\"]\n const sgMatch = line.match(/^subgraph\\s+(\\w+)(?:\\s*\\[?\"?(.+?)\"?\\]?)?$/i);\n if (sgMatch) {\n currentSubgraph = {\n id: sgMatch[1],\n label: sgMatch[2] || sgMatch[1],\n nodeIds: [],\n };\n continue;\n }\n\n // Subgraph end\n if (line.toLowerCase() === 'end' && currentSubgraph) {\n subgraphs.push(currentSubgraph);\n currentSubgraph = null;\n continue;\n }\n\n // Helper to add edge nodes to current subgraph\n function addToSubgraph(fromId, toId) {\n if (currentSubgraph) {\n if (fromId && !currentSubgraph.nodeIds.includes(fromId)) currentSubgraph.nodeIds.push(fromId);\n if (toId && !currentSubgraph.nodeIds.includes(toId)) currentSubgraph.nodeIds.push(toId);\n }\n }\n\n // Labeled edge: A -- text --> B\n let match = line.match(/^(.+?)\\s*--\\s*(.+?)\\s*-->\\s*(.+)$/);\n if (match) {\n const fromId = parseNodeRef(match[1].trim());\n const toId = parseNodeRef(match[3].trim());\n if (fromId && toId) edges.push({ from: fromId, to: toId, label: cleanLabel(match[2].trim()), directed: true, style: 'normal' });\n addToSubgraph(fromId, toId);\n continue;\n }\n\n // Dotted arrow: A -.-> B (with optional |label|)\n match = line.match(/^(.+?)\\s*-\\.->?\\s*(?:\\|([^|]*)\\|)?\\s*(.+)$/);\n if (match) {\n const fromId = parseNodeRef(match[1].trim());\n const toId = parseNodeRef(match[3].trim());\n const edgeLabel = match[2] ? cleanLabel(match[2].trim()) : undefined;\n if (fromId && toId) edges.push({ from: fromId, to: toId, label: edgeLabel, directed: true, style: 'dotted' });\n addToSubgraph(fromId, toId);\n continue;\n }\n\n // Thick arrow: A ==> B (with optional |label|)\n match = line.match(/^(.+?)\\s*==>\\s*(?:\\|([^|]*)\\|)?\\s*(.+)$/);\n if (match) {\n const fromId = parseNodeRef(match[1].trim());\n const toId = parseNodeRef(match[3].trim());\n const edgeLabel = match[2] ? cleanLabel(match[2].trim()) : undefined;\n if (fromId && toId) edges.push({ from: fromId, to: toId, label: edgeLabel, directed: true, style: 'thick' });\n addToSubgraph(fromId, toId);\n continue;\n }\n\n // Undirected line: A --- B\n match = line.match(/^(.+?)\\s*(-{3,})\\s*(?:\\|([^|]*)\\|)?\\s*(.+)$/);\n if (match && !match[2].includes('>')) {\n const fromId = parseNodeRef(match[1].trim());\n const toId = parseNodeRef(match[4].trim());\n const edgeLabel = match[3] ? cleanLabel(match[3].trim()) : undefined;\n if (fromId && toId) edges.push({ from: fromId, to: toId, label: edgeLabel, directed: false, style: 'normal' });\n addToSubgraph(fromId, toId);\n continue;\n }\n\n // Directed edge: A --> B (with optional |label|)\n match = line.match(/^(.+?)\\s*(-{1,2}>|-->)\\s*(?:\\|([^|]*)\\|)?\\s*(.+)$/);\n if (match) {\n const fromId = parseNodeRef(match[1].trim());\n const toId = parseNodeRef(match[4].trim());\n const edgeLabel = match[3] ? cleanLabel(match[3].trim()) : undefined;\n if (fromId && toId) edges.push({ from: fromId, to: toId, label: edgeLabel, directed: true, style: 'normal' });\n addToSubgraph(fromId, toId);\n continue;\n }\n\n // Plain node reference\n const nodeId = parseNodeRef(line);\n if (nodeId && currentSubgraph) {\n if (!currentSubgraph.nodeIds.includes(nodeId)) currentSubgraph.nodeIds.push(nodeId);\n }\n }\n\n if (nodesMap.size === 0) return null;\n\n // Apply classDef styles to nodes\n for (const assign of classAssigns) {\n const style = classDefs.get(assign.className);\n if (!style) continue;\n for (const nid of assign.nodeIds) {\n const node = nodesMap.get(nid);\n if (node) {\n if (style.fill) node.fill = style.fill;\n if (style.stroke) node.stroke = style.stroke;\n if (style.strokeWidth) node.strokeWidth = style.strokeWidth;\n }\n }\n }\n\n // Topological BFS layering\n const nodeIds = Array.from(nodesMap.keys());\n const children = new Map();\n const parents = new Map();\n nodeIds.forEach(id => { children.set(id, []); parents.set(id, []); });\n edges.forEach(e => {\n if (children.has(e.from)) children.get(e.from).push(e.to);\n if (parents.has(e.to)) parents.get(e.to).push(e.from);\n });\n\n const layers = new Map();\n const roots = nodeIds.filter(id => parents.get(id).length === 0);\n if (roots.length === 0) roots.push(nodeIds[0]);\n\n const queue = roots.map(id => ({ id, layer: 0 }));\n const visited = new Set();\n while (queue.length > 0) {\n const { id, layer } = queue.shift();\n if (visited.has(id)) { if (layer > (layers.get(id) || 0)) layers.set(id, layer); continue; }\n visited.add(id);\n layers.set(id, Math.max(layer, layers.get(id) || 0));\n for (const child of children.get(id) || []) queue.push({ id: child, layer: layer + 1 });\n }\n nodeIds.forEach(id => { if (!visited.has(id)) layers.set(id, 0); });\n\n const layerGroups = new Map();\n layers.forEach((layer, id) => {\n if (!layerGroups.has(layer)) layerGroups.set(layer, []);\n layerGroups.get(layer).push(id);\n });\n\n // Compute dynamic node sizes based on label length\n const nodes = [];\n Array.from(layerGroups.keys()).sort((a, b) => a - b).forEach((layerIdx, li) => {\n const group = layerGroups.get(layerIdx);\n const startOffset = -(group.length * H_SPACING) / 2 + H_SPACING / 2;\n group.forEach((id, gi) => {\n const nd = nodesMap.get(id);\n const x = isHorizontal ? li * H_SPACING : startOffset + gi * H_SPACING;\n const y = isHorizontal ? startOffset + gi * V_SPACING : li * V_SPACING;\n // Compute node size based on label lines\n const labelLines = (nd.label || '').split('\\n');\n const maxLineLen = Math.max(...labelLines.map(l => l.length));\n const nw = Math.max(NODE_W, maxLineLen * 10 + 40);\n const nh = Math.max(NODE_H, labelLines.length * 20 + 20);\n nodes.push({\n id: nd.id, type: nd.type, label: nd.label,\n x, y, width: nw, height: nh,\n fill: nd.fill, stroke: nd.stroke, strokeWidth: nd.strokeWidth,\n });\n });\n });\n\n return {\n title: 'Mermaid Diagram',\n direction,\n nodes,\n edges: edges.map(e => ({\n from: e.from, to: e.to, label: e.label,\n directed: e.directed !== false,\n style: e.style || 'normal',\n })),\n subgraphs: subgraphs.length > 0 ? subgraphs.map(sg => ({\n id: sg.id, label: sg.label, nodes: sg.nodeIds,\n })) : undefined,\n };\n}\n\n// ============================================================\n// RENDER\n// ============================================================\n\nexport function renderAIDiagram(diagram) {\n if (!diagram?.nodes?.length) { console.error('[AIRenderer] Invalid diagram'); return false; }\n\n const nodes = diagram.nodes;\n const edges = diagram.edges || [];\n const title = diagram.title || 'AI Diagram';\n\n if (!window.svg || !window.Frame || !window.Rectangle) {\n console.error('[AIRenderer] Engine not initialized');\n return false;\n }\n\n // Viewport center\n const vb = window.currentViewBox || { x: 0, y: 0, width: window.innerWidth, height: window.innerHeight };\n const vcx = vb.x + vb.width / 2;\n const vcy = vb.y + vb.height / 2;\n\n // Diagram bounds\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n nodes.forEach(n => {\n minX = Math.min(minX, n.x);\n minY = Math.min(minY, n.y);\n maxX = Math.max(maxX, n.x + (n.width || NODE_W));\n maxY = Math.max(maxY, n.y + (n.height || NODE_H));\n });\n\n const dw = maxX - minX, dh = maxY - minY;\n const ox = vcx - dw / 2 - minX;\n const oy = vcy - dh / 2 - minY;\n\n // Phase 5 (issue #22): no outer wrapper frame. Each generated shape\n // (node, edge, subgraph container) gets the same `groupId` so the whole\n // diagram behaves as one selectable group via Selection.js's existing\n // group-expansion path. Drops the \"solid background frame\" symptom and\n // makes the rendered content as interactive as user-drawn shapes.\n const groupId = `aidiag-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`;\n // Kept under the same name `frame` to minimise the diff inside this\n // 600-line function \u2014 it's now a thin shim that catches `addShapeToFrame`\n // calls and re-routes them to a groupId assignment. `selectFrame` /\n // `removeSelection` no-op; selection is on the first node below.\n const frame = {\n addShapeToFrame(s) { if (s) s.groupId = groupId; },\n selectFrame() {},\n removeSelection() {},\n shapeName: 'frame',\n };\n\n const nodeMap = new Map();\n\n // --- NODES ---\n for (const node of nodes) {\n const nx = node.x + ox, ny = node.y + oy;\n const nw = node.width || NODE_W, nh = node.height || NODE_H;\n const cx = nx + nw / 2, cy = ny + nh / 2;\n let shape = null;\n\n // Build style options from AI-specified properties (with defaults)\n const nodeOpts = {\n stroke: node.stroke || '#e0e0e0',\n strokeWidth: node.strokeWidth ?? 1.5,\n fill: node.fill || 'transparent',\n fillStyle: node.fillStyle || 'none',\n roughness: node.roughness ?? 1,\n strokeDasharray: node.strokeDasharray || '',\n // Shading support\n shadeColor: node.shadeColor || null,\n shadeOpacity: node.shadeOpacity !== undefined ? node.shadeOpacity : 0.15,\n shadeDirection: node.shadeDirection || 'bottom',\n // Label styling\n labelColor: node.labelColor || undefined,\n labelFontSize: node.labelFontSize || undefined,\n };\n\n try {\n if (node.type === 'icon' && node.iconKeyword) {\n // Icon nodes are placed asynchronously \u2014 create a placeholder rectangle\n // and kick off icon fetch in the background\n shape = new window.Rectangle(nx, ny, nw, nh, {\n ...nodeOpts, stroke: nodeOpts.stroke, strokeDasharray: '4 3',\n });\n // Async fetch & replace with actual icon\n fetchAndPlaceIcon(node.iconKeyword, nx, ny, nw, nh, shape, frame);\n } else if (node.type === 'circle' && window.Circle) {\n shape = new window.Circle(cx, cy, nw / 2, nh / 2, nodeOpts);\n } else if (node.type === 'diamond' && window.Rectangle) {\n const sz = Math.max(nw, nh) * 0.7;\n shape = new window.Rectangle(cx - sz / 2, cy - sz / 2, sz, sz, nodeOpts);\n shape.rotation = 45;\n shape.draw();\n } else if (node.type === 'roundrect' && window.Rectangle) {\n shape = new window.Rectangle(nx, ny, nw, nh, { ...nodeOpts, cornerRadius: Math.min(nw, nh) * 0.2 });\n } else if (window.Rectangle) {\n shape = new window.Rectangle(nx, ny, nw, nh, nodeOpts);\n }\n } catch (err) {\n console.warn('[AIRenderer] Node creation failed:', node.id, err);\n continue;\n }\n\n if (!shape) continue;\n\n // Apply rotation if specified (skip for diamonds \u2014 they already have rotation=45)\n if (node.rotation && shape.rotation !== undefined && node.type !== 'diamond') {\n shape.rotation = node.rotation;\n }\n\n window.shapes.push(shape);\n if (window.pushCreateAction) window.pushCreateAction(shape);\n if (frame.addShapeToFrame) frame.addShapeToFrame(shape);\n\n nodeMap.set(node.id, { shape, x: nx, y: ny, width: nw, height: nh, centerX: cx, centerY: cy });\n\n // Node label \u2014 use embedded label for rect/circle, separate TextShape for icons\n if (node.label) {\n let labelColor = node.labelColor || node.stroke || '#e0e0e0';\n if (isColorTooDark(labelColor)) {\n labelColor = '#e0e0e0';\n }\n const labelFontSize = node.labelFontSize || 14;\n\n if (node.type === 'icon') {\n // Icons: place label below the icon as a separate TextShape\n const labelY = cy + nh / 2 + 18;\n createLabel(node.label, cx, labelY, labelFontSize, labelColor, frame);\n } else if (shape && typeof shape.setLabel === 'function') {\n // Rectangles, circles, diamonds: use embedded label\n shape.setLabel(node.label, labelColor, labelFontSize);\n } else {\n // Fallback: separate TextShape\n createLabel(node.label, cx, cy, labelFontSize, labelColor, frame);\n }\n }\n }\n\n // --- EDGES ---\n // Pre-compute fan-out counts per source node so we can spread edges\n const fanOut = new Map();\n const fanIdx = new Map();\n edges.forEach(e => {\n fanOut.set(e.from, (fanOut.get(e.from) || 0) + 1);\n fanIdx.set(e, fanOut.get(e.from) - 1);\n });\n\n // Collect all node bounds for overlap checking\n const allNodeBounds = [];\n nodeMap.forEach(n => {\n allNodeBounds.push({ x: n.x, y: n.y, width: n.width, height: n.height });\n });\n\n for (const edge of edges) {\n const from = nodeMap.get(edge.from), to = nodeMap.get(edge.to);\n if (!from || !to) continue;\n\n const count = fanOut.get(edge.from) || 1;\n const idx = fanIdx.get(edge);\n const isDirected = edge.directed !== false;\n\n // Determine edge routing style based on node alignment and context\n const edgeStyle = chooseEdgeStyle(from, to, count, idx, allNodeBounds, nodeMap, edges);\n\n // Spread connection ports along the exit edge when fan-out > 1\n const sp = getSpreadEdgePoint(from, to, count, idx);\n const ep = getEdgePoint(to, from);\n\n // Nudge slightly away from node boundaries\n const adx = ep.x - sp.x, ady = ep.y - sp.y;\n const alen = Math.sqrt(adx * adx + ady * ady) || 1;\n const nudge = 6;\n const spN = { x: sp.x + (adx / alen) * nudge, y: sp.y + (ady / alen) * nudge };\n const epN = { x: ep.x - (adx / alen) * nudge, y: ep.y - (ady / alen) * nudge };\n\n let connector = null;\n\n // Edge style from AI (with defaults)\n const edgeStroke = edge.stroke || '#e0e0e0';\n const edgeStrokeWidth = edge.strokeWidth ?? 1.5;\n const edgeLineStyle = edge.lineStyle || 'solid';\n\n // Map lineStyle to arrowOutlineStyle / strokeDasharray\n const dashMap = { solid: '', dashed: '5 3', dotted: '2 2' };\n const dashValue = dashMap[edgeLineStyle] || '';\n\n if (isDirected && window.Arrow) {\n // Use Arrow for directed edges\n try {\n const opts = {\n stroke: edgeStroke, strokeWidth: edgeStrokeWidth, roughness: 1,\n arrowOutlineStyle: edgeLineStyle,\n arrowHeadStyle: edge.arrowHeadStyle || 'default',\n };\n\n if (edgeStyle.type === 'curved') {\n opts.arrowCurved = 'curved';\n opts.arrowCurveAmount = edgeStyle.curveAmount;\n } else if (edgeStyle.type === 'elbow') {\n opts.arrowCurved = 'elbow';\n }\n // 'straight' \u2014 no arrowCurved needed (default)\n\n connector = new window.Arrow(spN, epN, opts);\n window.shapes.push(connector);\n if (window.pushCreateAction) window.pushCreateAction(connector);\n if (frame.addShapeToFrame) frame.addShapeToFrame(connector);\n\n // Auto-attach arrow to source and target shapes\n autoAttach(connector, from.shape, true, sp);\n autoAttach(connector, to.shape, false, ep);\n } catch (err) {\n console.warn('[AIRenderer] Arrow creation failed:', edge, err);\n }\n } else if (!isDirected && window.Line) {\n // Use Line for undirected edges\n try {\n const opts = {\n stroke: edgeStroke, strokeWidth: edgeStrokeWidth, roughness: 1,\n strokeDasharray: dashValue,\n };\n\n connector = new window.Line(spN, epN, opts);\n\n if (edgeStyle.type === 'curved') {\n connector.isCurved = true;\n if (typeof connector.initializeCurveControlPoint === 'function') {\n connector.initializeCurveControlPoint();\n }\n // Re-draw with curve since constructor drew it straight\n if (typeof connector.draw === 'function') connector.draw();\n }\n\n window.shapes.push(connector);\n if (window.pushCreateAction) window.pushCreateAction(connector);\n if (frame.addShapeToFrame) frame.addShapeToFrame(connector);\n } catch (err) {\n console.warn('[AIRenderer] Line creation failed:', edge, err);\n }\n } else if (window.Arrow) {\n // Fallback: use Arrow if Line not available\n try {\n connector = new window.Arrow(spN, epN, {\n stroke: edgeStroke, strokeWidth: edgeStrokeWidth, roughness: 1,\n });\n window.shapes.push(connector);\n if (window.pushCreateAction) window.pushCreateAction(connector);\n if (frame.addShapeToFrame) frame.addShapeToFrame(connector);\n } catch (err) {\n console.warn('[AIRenderer] Fallback arrow creation failed:', edge, err);\n }\n }\n\n // Edge label \u2014 use embedded label on connector if available\n if (edge.label && connector) {\n const edgeLabelColor = edgeStroke === '#e0e0e0' ? '#a0a0b0' : edgeStroke;\n if (typeof connector.setLabel === 'function') {\n connector.setLabel(edge.label, edgeLabelColor, 11);\n } else {\n // Fallback: separate TextShape\n const mx = (spN.x + epN.x) / 2;\n const my = (spN.y + epN.y) / 2 - 18;\n createLabel(edge.label, mx, my, 11, edgeLabelColor, frame);\n }\n }\n }\n\n // --- SUBGRAPHS ---\n const subgraphs = diagram.subgraphs || [];\n for (const sg of subgraphs) {\n if (!sg.nodes || sg.nodes.length === 0) continue;\n\n // Compute bounds of all nodes in this subgraph\n let sgMinX = Infinity, sgMinY = Infinity, sgMaxX = -Infinity, sgMaxY = -Infinity;\n let hasNodes = false;\n for (const nid of sg.nodes) {\n const n = nodeMap.get(nid);\n if (!n) continue;\n hasNodes = true;\n sgMinX = Math.min(sgMinX, n.x);\n sgMinY = Math.min(sgMinY, n.y);\n sgMaxX = Math.max(sgMaxX, n.x + n.width);\n sgMaxY = Math.max(sgMaxY, n.y + n.height);\n }\n if (!hasNodes) continue;\n\n const sgPad = 30;\n try {\n const subFrame = new window.Frame(\n sgMinX - sgPad, sgMinY - sgPad - 20,\n (sgMaxX - sgMinX) + sgPad * 2, (sgMaxY - sgMinY) + sgPad * 2 + 20,\n {\n stroke: sg.stroke || '#555',\n strokeWidth: 1,\n fill: 'transparent',\n opacity: 0.6,\n frameName: sg.label || sg.id,\n }\n );\n window.shapes.push(subFrame);\n if (window.pushCreateAction) window.pushCreateAction(subFrame);\n if (frame.addShapeToFrame) frame.addShapeToFrame(subFrame);\n\n // Add nodes to the sub-frame\n for (const nid of sg.nodes) {\n const n = nodeMap.get(nid);\n if (n && n.shape && subFrame.addShapeToFrame) {\n subFrame.addShapeToFrame(n.shape);\n }\n }\n } catch (err) {\n console.warn('[AIRenderer] Subgraph frame failed:', sg.id, err);\n }\n }\n\n // Phase 5: select the first generated node \u2014 group expansion in\n // Selection.js will pick up the rest via the shared groupId.\n const first = nodeMap.values().next().value;\n if (first && first.shape) {\n window.currentShape = first.shape;\n if (typeof first.shape.selectShape === 'function') first.shape.selectShape();\n }\n\n console.log(`[AIRenderer] Done: ${nodes.length} nodes, ${edges.length} edges, ${subgraphs.length} subgraphs \u2192 \"${title}\" (groupId=${groupId})`);\n return true;\n}\n\n// ============================================================\n// SMART EDGE ROUTING\n// ============================================================\n\n/**\n * Choose the best edge style based on node positions and context.\n * Returns { type: 'straight'|'curved'|'elbow', curveAmount?: number }\n */\nfunction chooseEdgeStyle(from, to, fanCount, fanIdx, allNodeBounds, nodeMap, edges) {\n const dx = Math.abs(from.centerX - to.centerX);\n const dy = Math.abs(from.centerY - to.centerY);\n\n // Multiple edges from same source \u2014 must curve to avoid overlap\n if (fanCount > 1) {\n const curveAmount = 40 + (fanIdx - (fanCount - 1) / 2) * 35;\n return { type: 'curved', curveAmount };\n }\n\n // Check if nodes are aligned (horizontally or vertically)\n const isHAligned = dx < ALIGN_THRESHOLD;\n const isVAligned = dy < ALIGN_THRESHOLD;\n\n // If aligned on either axis, use straight line\n if (isHAligned || isVAligned) {\n // But check if a straight line would cross through any other node\n const sp = getEdgePoint(from, to);\n const ep = getEdgePoint(to, from);\n const blocked = wouldCrossNode(sp, ep, from, to, allNodeBounds);\n\n if (blocked) {\n // Use curved to route around\n return { type: 'curved', curveAmount: 40 };\n }\n return { type: 'straight' };\n }\n\n // Diagonal connection \u2014 check if elbow or curve is better\n // Elbow works well when nodes are in a grid-like arrangement\n const isGridLike = (dx > ALIGN_THRESHOLD * 2) && (dy > ALIGN_THRESHOLD * 2);\n\n if (isGridLike) {\n // Check if elbow would cross another node\n // Elbow goes horizontal then vertical (or vice versa)\n const elbowMidX = to.centerX;\n const elbowMidY = from.centerY;\n const elbowMid = { x: elbowMidX, y: elbowMidY };\n\n const seg1Blocked = wouldCrossNode(\n { x: from.centerX, y: from.centerY }, elbowMid, from, to, allNodeBounds\n );\n const seg2Blocked = wouldCrossNode(\n elbowMid, { x: to.centerX, y: to.centerY }, from, to, allNodeBounds\n );\n\n if (!seg1Blocked && !seg2Blocked) {\n return { type: 'elbow' };\n }\n }\n\n // Default: gentle curve for diagonal connections\n return { type: 'curved', curveAmount: 25 };\n}\n\n/**\n * Check if a straight line between two points would cross through any node\n * (excluding the source and target nodes themselves).\n */\nfunction wouldCrossNode(p1, p2, fromNode, toNode, allNodeBounds) {\n const margin = 10;\n for (const bounds of allNodeBounds) {\n // Skip source and target nodes\n if (bounds.x === fromNode.x && bounds.y === fromNode.y) continue;\n if (bounds.x === toNode.x && bounds.y === toNode.y) continue;\n\n // Inflate node bounds slightly for margin\n const bx = bounds.x - margin;\n const by = bounds.y - margin;\n const bw = bounds.width + margin * 2;\n const bh = bounds.height + margin * 2;\n\n if (lineIntersectsRect(p1.x, p1.y, p2.x, p2.y, bx, by, bw, bh)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Check if a line segment intersects a rectangle.\n */\nfunction lineIntersectsRect(x1, y1, x2, y2, rx, ry, rw, rh) {\n // Check if line segment intersects any of the 4 edges of the rect\n const left = rx, right = rx + rw, top = ry, bottom = ry + rh;\n\n // Quick bounding box rejection\n if (Math.max(x1, x2) < left || Math.min(x1, x2) > right) return false;\n if (Math.max(y1, y2) < top || Math.min(y1, y2) > bottom) return false;\n\n // Check if either endpoint is inside the rect\n if (x1 >= left && x1 <= right && y1 >= top && y1 <= bottom) return true;\n if (x2 >= left && x2 <= right && y2 >= top && y2 <= bottom) return true;\n\n // Check line intersection with each edge\n return (\n segmentsIntersect(x1, y1, x2, y2, left, top, right, top) ||\n segmentsIntersect(x1, y1, x2, y2, right, top, right, bottom) ||\n segmentsIntersect(x1, y1, x2, y2, left, bottom, right, bottom) ||\n segmentsIntersect(x1, y1, x2, y2, left, top, left, bottom)\n );\n}\n\nfunction segmentsIntersect(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2) {\n const d1 = cross(bx1, by1, bx2, by2, ax1, ay1);\n const d2 = cross(bx1, by1, bx2, by2, ax2, ay2);\n const d3 = cross(ax1, ay1, ax2, ay2, bx1, by1);\n const d4 = cross(ax1, ay1, ax2, ay2, bx2, by2);\n\n if (((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) &&\n ((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0))) {\n return true;\n }\n return false;\n}\n\nfunction cross(ax, ay, bx, by, cx, cy) {\n return (bx - ax) * (cy - ay) - (by - ay) * (cx - ax);\n}\n\n// ============================================================\n// AUTO-ATTACHMENT\n// ============================================================\n\n/**\n * Automatically attach an arrow endpoint to a shape.\n * This makes edges follow nodes when they're moved.\n */\nexport function autoAttach(arrow, shape, isStart, contactPoint) {\n if (!arrow || !shape) return;\n if (typeof arrow.attachToShape !== 'function') return;\n\n try {\n // Determine attachment side based on contact point relative to shape\n let side, offset;\n\n if (shape.shapeName === 'rectangle' || shape.shapeName === 'frame') {\n const sx = shape.x, sy = shape.y, sw = shape.width, sh = shape.height;\n const cx = sx + sw / 2, cy = sy + sh / 2;\n\n // Determine which edge the contact point is closest to\n const distTop = Math.abs(contactPoint.y - sy);\n const distBottom = Math.abs(contactPoint.y - (sy + sh));\n const distLeft = Math.abs(contactPoint.x - sx);\n const distRight = Math.abs(contactPoint.x - (sx + sw));\n const minDist = Math.min(distTop, distBottom, distLeft, distRight);\n\n if (minDist === distTop) {\n side = 'top';\n offset = { x: contactPoint.x - sx, y: 0, side: 'top' };\n } else if (minDist === distBottom) {\n side = 'bottom';\n offset = { x: contactPoint.x - sx, y: sh, side: 'bottom' };\n } else if (minDist === distLeft) {\n side = 'left';\n offset = { x: 0, y: contactPoint.y - sy, side: 'left' };\n } else {\n side = 'right';\n offset = { x: sw, y: contactPoint.y - sy, side: 'right' };\n }\n\n const attachment = { side, point: contactPoint, offset };\n arrow.attachToShape(isStart, shape, attachment);\n } else if (shape.shapeName === 'circle') {\n const angle = Math.atan2(\n contactPoint.y - shape.y,\n contactPoint.x - shape.x\n );\n const attachment = {\n side: 'perimeter',\n point: contactPoint,\n offset: { angle, side: 'perimeter' },\n };\n arrow.attachToShape(isStart, shape, attachment);\n }\n } catch (err) {\n // Attachment is optional \u2014 don't fail the render\n console.warn('[AIRenderer] Auto-attach failed:', err);\n }\n}\n\n// ============================================================\n// ICON FETCHING\n// ============================================================\n\n/**\n * Fetch an icon by keyword from the icon API and replace the placeholder shape.\n * Runs asynchronously so it doesn't block diagram rendering.\n */\nasync function fetchAndPlaceIcon(keyword, x, y, w, h, placeholderShape, frame) {\n try {\n const res = await fetch(`/api/icons/search?q=${encodeURIComponent(keyword)}&inline=1`);\n if (!res.ok) return;\n const data = await res.json();\n const results = data.results;\n if (!results || results.length === 0 || !results[0].svg) return;\n\n const svgContent = results[0].svg;\n\n // Use the engine's icon placement bridge if available\n if (window.svg && window.IconShape) {\n const svg = window.svg;\n\n // Parse SVG to extract paths\n const parser = new DOMParser();\n const doc = parser.parseFromString(svgContent, 'image/svg+xml');\n const svgEl = doc.querySelector('svg');\n if (!svgEl) return;\n\n const vbWidth = parseFloat(svgEl.getAttribute('width') || svgEl.viewBox?.baseVal?.width || 24);\n const vbHeight = parseFloat(svgEl.getAttribute('height') || svgEl.viewBox?.baseVal?.height || 24);\n const scale = Math.min(w / vbWidth, h / vbHeight);\n\n // Create icon group\n const g = document.createElementNS(NS, 'g');\n g.setAttribute('type', 'icon');\n g.setAttribute('x', x);\n g.setAttribute('y', y);\n g.setAttribute('width', w);\n g.setAttribute('height', h);\n g.setAttribute('data-shape-x', x);\n g.setAttribute('data-shape-y', y);\n g.setAttribute('data-shape-width', w);\n g.setAttribute('data-shape-height', h);\n g.setAttribute('data-shape-rotation', '0');\n g.setAttribute('data-viewbox-width', vbWidth);\n g.setAttribute('data-viewbox-height', vbHeight);\n g.setAttribute('transform', `translate(${x}, ${y}) scale(${scale})`);\n\n // Copy SVG content into group, apply white fill\n const children = svgEl.querySelectorAll('path, circle, rect, polygon, polyline, line, ellipse');\n children.forEach(child => {\n const clone = child.cloneNode(true);\n // Make visible on dark canvas\n if (!clone.getAttribute('fill') || clone.getAttribute('fill') === 'none' || clone.getAttribute('fill') === 'black' || clone.getAttribute('fill') === '#000' || clone.getAttribute('fill') === '#000000') {\n clone.setAttribute('fill', '#ffffff');\n }\n if (clone.getAttribute('stroke') === 'black' || clone.getAttribute('stroke') === '#000' || clone.getAttribute('stroke') === '#000000') {\n clone.setAttribute('stroke', '#ffffff');\n }\n g.appendChild(clone);\n });\n\n // Add hit detection rect\n const hitRect = document.createElementNS(NS, 'rect');\n hitRect.setAttribute('x', '0');\n hitRect.setAttribute('y', '0');\n hitRect.setAttribute('width', vbWidth);\n hitRect.setAttribute('height', vbHeight);\n hitRect.setAttribute('fill', 'transparent');\n hitRect.setAttribute('stroke', 'none');\n g.insertBefore(hitRect, g.firstChild);\n\n svg.appendChild(g);\n\n // Wrap as IconShape\n const iconShape = new window.IconShape(g);\n window.shapes.push(iconShape);\n if (window.pushCreateAction) window.pushCreateAction(iconShape);\n if (frame?.addShapeToFrame) frame.addShapeToFrame(iconShape);\n\n // Remove placeholder\n if (placeholderShape) {\n const idx = window.shapes.indexOf(placeholderShape);\n if (idx !== -1) window.shapes.splice(idx, 1);\n if (placeholderShape.group && placeholderShape.group.parentNode) {\n placeholderShape.group.parentNode.removeChild(placeholderShape.group);\n }\n }\n }\n } catch (err) {\n console.warn('[AIRenderer] Icon fetch failed for keyword:', keyword, err);\n // Placeholder rectangle remains visible as fallback\n }\n}\n\n// ============================================================\n// HELPERS\n// ============================================================\n\n/**\n * Create an interactive TextShape label at (x, y) and add it to the frame.\n * Sets data-type=\"text-group\" so the text tool recognizes it for\n * click-to-select and double-click-to-edit.\n */\nfunction createLabel(text, x, y, fontSize, fill, frame) {\n const svg = window.svg;\n if (!svg || !window.TextShape) return null;\n\n try {\n const g = document.createElementNS(NS, 'g');\n g.setAttribute('data-type', 'text-group');\n g.setAttribute('transform', `translate(${x}, ${y})`);\n g.setAttribute('data-x', x);\n g.setAttribute('data-y', y);\n\n const t = document.createElementNS(NS, 'text');\n t.setAttribute('x', 0);\n t.setAttribute('y', 0);\n t.setAttribute('text-anchor', 'middle');\n t.setAttribute('dominant-baseline', 'central');\n t.setAttribute('fill', fill);\n t.setAttribute('font-size', fontSize);\n t.setAttribute('font-family', 'lixFont, sans-serif');\n t.setAttribute('data-initial-font', 'lixFont');\n t.setAttribute('data-initial-color', fill);\n t.setAttribute('data-initial-size', fontSize + 'px');\n t.textContent = text;\n\n g.appendChild(t);\n svg.appendChild(g);\n\n const shape = new window.TextShape(g);\n window.shapes.push(shape);\n if (window.pushCreateAction) window.pushCreateAction(shape);\n if (frame?.addShapeToFrame) frame.addShapeToFrame(shape);\n return shape;\n } catch (err) {\n console.warn('[AIRenderer] Label creation failed:', err);\n return null;\n }\n}\n\n/**\n * Like getEdgePoint but spreads multiple connections along the exit edge.\n * count = total edges leaving this side, idx = 0-based index of this edge.\n */\nfunction getSpreadEdgePoint(node, targetNode, count, idx) {\n if (count <= 1) return getEdgePoint(node, targetNode);\n\n const dx = targetNode.centerX - node.centerX;\n const dy = targetNode.centerY - node.centerY;\n const hw = node.width / 2;\n const hh = node.height / 2;\n\n // Spread ratio: distribute along 60% of the edge length\n const spread = 0.6;\n const t = count === 1 ? 0.5 : idx / (count - 1);\n const offset = (t - 0.5) * spread;\n\n if (Math.abs(dx) < 0.001 || Math.abs(dy) * hw > Math.abs(dx) * hh) {\n const px = node.centerX + offset * node.width;\n const py = dy > 0 ? node.y + node.height : node.y;\n return { x: px, y: py };\n }\n const px = dx > 0 ? node.x + node.width : node.x;\n const py = node.centerY + offset * node.height;\n return { x: px, y: py };\n}\n\n/**\n * Get the connection point on a node's boundary toward another node.\n * Uses the angle between centers to pick the closest edge (top/bottom/left/right).\n */\nfunction getEdgePoint(node, targetNode) {\n const dx = targetNode.centerX - node.centerX;\n const dy = targetNode.centerY - node.centerY;\n const hw = node.width / 2;\n const hh = node.height / 2;\n\n if (Math.abs(dx) < 0.001 || Math.abs(dy) * hw > Math.abs(dx) * hh) {\n if (dy > 0) return { x: node.centerX, y: node.y + node.height };\n return { x: node.centerX, y: node.y };\n }\n if (dx > 0) return { x: node.x + node.width, y: node.centerY };\n return { x: node.x, y: node.centerY };\n}\n\n// ============================================================\n// PREVIEW (for AI Modal)\n// ============================================================\n\n/**\n * Generate a simple SVG preview string from a diagram JSON.\n * Used inside the AI modal before placing on canvas.\n */\nexport function generatePreviewSVG(diagram, width = 500, height = 350) {\n if (!diagram?.nodes?.length) return '';\n\n const nodes = diagram.nodes;\n const edges = diagram.edges || [];\n\n // Compute bounds\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n nodes.forEach(n => {\n minX = Math.min(minX, n.x);\n minY = Math.min(minY, n.y);\n maxX = Math.max(maxX, n.x + (n.width || NODE_W));\n maxY = Math.max(maxY, n.y + (n.height || NODE_H));\n });\n\n const dw = maxX - minX || 1;\n const dh = maxY - minY || 1;\n const pad = 40;\n const scale = Math.min((width - pad * 2) / dw, (height - pad * 2) / dh, 1.5);\n const offX = (width - dw * scale) / 2 - minX * scale;\n const offY = (height - dh * scale) / 2 - minY * scale;\n\n // Build node lookup for edge rendering\n const nodeById = new Map();\n nodes.forEach(n => {\n const nx = n.x * scale + offX;\n const ny = n.y * scale + offY;\n const nw = (n.width || NODE_W) * scale;\n const nh = (n.height || NODE_H) * scale;\n nodeById.set(n.id, { x: nx, y: ny, w: nw, h: nh, cx: nx + nw / 2, cy: ny + nh / 2 });\n });\n\n let svgContent = '';\n\n // Draw edges\n edges.forEach(e => {\n const f = nodeById.get(e.from);\n const t = nodeById.get(e.to);\n if (!f || !t) return;\n\n const directed = e.directed !== false;\n const eColor = e.stroke || '#666';\n const markerId = directed ? `url(#preview-arrow-${eColor.replace('#', '')})` : '';\n\n // Add a per-color marker if needed\n if (directed && !svgContent.includes(`id=\"preview-arrow-${eColor.replace('#', '')}\"`)) {\n svgContent = `<marker id=\"preview-arrow-${eColor.replace('#', '')}\" markerWidth=\"8\" markerHeight=\"6\" refX=\"8\" refY=\"3\" orient=\"auto\"><path d=\"M0,0 L8,3 L0,6\" fill=\"none\" stroke=\"${eColor}\" stroke-width=\"1\" /></marker>` + svgContent;\n }\n\n const eDash = e.lineStyle === 'dashed' ? ' stroke-dasharray=\"5 3\"' : e.lineStyle === 'dotted' ? ' stroke-dasharray=\"2 2\"' : '';\n\n // Render curved path if nodes aren't aligned (creates a natural curve)\n const dx = t.cx - f.cx;\n const dy = t.cy - f.cy;\n const dist = Math.sqrt(dx * dx + dy * dy);\n let mx = (f.cx + t.cx) / 2;\n let my = (f.cy + t.cy) / 2;\n\n if (dist > 0 && Math.abs(dy) > 10 && Math.abs(dx) > 10) {\n // Curved edge: perpendicular offset for a quadratic Bezier\n const perpX = -dy / dist;\n const perpY = dx / dist;\n const curveAmt = dist * 0.15;\n const cpx = mx + perpX * curveAmt;\n const cpy = my + perpY * curveAmt;\n // Quadratic bezier midpoint for label\n mx = 0.25 * f.cx + 0.5 * cpx + 0.25 * t.cx;\n my = 0.25 * f.cy + 0.5 * cpy + 0.25 * t.cy;\n svgContent += `<path d=\"M ${f.cx} ${f.cy} Q ${cpx} ${cpy} ${t.cx} ${t.cy}\" fill=\"none\" stroke=\"${eColor}\" stroke-width=\"1.5\"${eDash} marker-end=\"${markerId}\" />`;\n } else {\n svgContent += `<line x1=\"${f.cx}\" y1=\"${f.cy}\" x2=\"${t.cx}\" y2=\"${t.cy}\" stroke=\"${eColor}\" stroke-width=\"1.5\"${eDash} marker-end=\"${markerId}\" />`;\n }\n\n if (e.label) {\n svgContent += `<text x=\"${mx}\" y=\"${my - 8}\" text-anchor=\"middle\" fill=\"${eColor === '#666' ? '#888' : eColor}\" font-size=\"9\" font-family=\"lixFont, sans-serif\">${escapeXml(e.label)}</text>`;\n }\n });\n\n // Draw nodes\n nodes.forEach(n => {\n const d = nodeById.get(n.id);\n if (!d) return;\n\n const nStroke = n.stroke || '#9090c0';\n const nFill = n.fill || 'transparent';\n const nDash = n.strokeDasharray ? ` stroke-dasharray=\"${n.strokeDasharray}\"` : '';\n\n if (n.type === 'circle') {\n svgContent += `<ellipse cx=\"${d.cx}\" cy=\"${d.cy}\" rx=\"${d.w / 2}\" ry=\"${d.h / 2}\" fill=\"${nFill}\" stroke=\"${nStroke}\" stroke-width=\"1.5\"${nDash} />`;\n } else if (n.type === 'diamond') {\n const sz = Math.min(d.w, d.h) * 0.7;\n svgContent += `<rect x=\"${d.cx - sz / 2}\" y=\"${d.cy - sz / 2}\" width=\"${sz}\" height=\"${sz}\" fill=\"${nFill}\" stroke=\"${nStroke}\" stroke-width=\"1.5\"${nDash} transform=\"rotate(45, ${d.cx}, ${d.cy})\" />`;\n } else if (n.type === 'roundrect') {\n svgContent += `<rect x=\"${d.x}\" y=\"${d.y}\" width=\"${d.w}\" height=\"${d.h}\" rx=\"${Math.min(d.w, d.h) * 0.2}\" fill=\"${nFill}\" stroke=\"${nStroke}\" stroke-width=\"1.5\"${nDash} />`;\n } else {\n svgContent += `<rect x=\"${d.x}\" y=\"${d.y}\" width=\"${d.w}\" height=\"${d.h}\" rx=\"4\" fill=\"${nFill}\" stroke=\"${nStroke}\" stroke-width=\"1.5\"${nDash} />`;\n }\n\n // Label \u2014 ensure readable color\n if (n.label) {\n const fontSize = Math.max(8, Math.min(12, 11 * scale));\n let labelFill = nStroke === '#9090c0' ? '#d0d0d0' : nStroke;\n if (isColorTooDark(labelFill)) labelFill = '#d0d0d0';\n // Icon nodes: label below the icon\n const labelY = n.type === 'icon' ? d.cy + d.h / 2 + 12 * scale : d.cy;\n svgContent += `<text x=\"${d.cx}\" y=\"${labelY}\" text-anchor=\"middle\" dominant-baseline=\"central\" fill=\"${labelFill}\" font-size=\"${fontSize}\" font-family=\"lixFont, sans-serif\">${escapeXml(n.label)}</text>`;\n }\n });\n\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\" viewBox=\"0 0 ${width} ${height}\">\n <defs>${svgContent.match(/<marker[^]*?<\\/marker>/g)?.join('') || ''}</defs>\n ${svgContent.replace(/<marker[^]*?<\\/marker>/g, '')}\n</svg>`;\n}\n\nfunction escapeXml(str) {\n return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n}\n\n/**\n * Check if a hex color is too dark to read on a dark canvas (#1a1a2e).\n * Returns true if perceived luminance is below threshold.\n */\nfunction isColorTooDark(hex) {\n if (!hex || hex === 'transparent' || hex === 'none') return false;\n const c = hex.replace('#', '');\n if (c.length < 6) return false;\n const r = parseInt(c.substring(0, 2), 16);\n const g = parseInt(c.substring(2, 4), 16);\n const b = parseInt(c.substring(4, 6), 16);\n // Relative luminance (perceived brightness)\n const lum = (0.299 * r + 0.587 * g + 0.114 * b);\n return lum < 80; // Below ~31% brightness \u2014 unreadable on dark bg\n}\n\n/**\n * Generate a preview SVG from an existing Frame's DOM contents.\n * Used when the user opens the AI edit dialog for a frame \u2014\n * shows the current state of the frame as an SVG preview.\n */\nexport function generateFramePreviewSVG(frame, width = 500, height = 350) {\n if (!frame || !frame.clipGroup) return '';\n\n const fx = frame.x, fy = frame.y, fw = frame.width, fh = frame.height;\n if (fw <= 0 || fh <= 0) return '';\n\n const pad = 30;\n const scale = Math.min((width - pad * 2) / fw, (height - pad * 2) / fh, 1.5);\n const offX = (width - fw * scale) / 2 - fx * scale;\n const offY = (height - fh * scale) / 2 - fy * scale;\n\n let svgContent = '';\n\n // Frame border\n svgContent += `<rect x=\"${fx * scale + offX}\" y=\"${fy * scale + offY}\" width=\"${fw * scale}\" height=\"${fh * scale}\" rx=\"6\" fill=\"transparent\" stroke=\"#555\" stroke-width=\"1.5\" stroke-dasharray=\"6 3\" />`;\n\n // Frame label\n if (frame.frameName) {\n svgContent += `<text x=\"${fx * scale + offX + 10}\" y=\"${fy * scale + offY + 16}\" fill=\"#888\" font-size=\"11\" font-family=\"lixFont, sans-serif\">${escapeXml(frame.frameName)}</text>`;\n }\n\n // Render contained shapes\n if (frame.containedShapes) {\n frame.containedShapes.forEach(shape => {\n if (!shape) return;\n\n if (shape.shapeName === 'rectangle') {\n const sx = shape.x * scale + offX;\n const sy = shape.y * scale + offY;\n const sw = shape.width * scale;\n const sh = shape.height * scale;\n const stroke = shape.options?.stroke || '#e0e0e0';\n const fill = shape.options?.fill || 'transparent';\n if (shape.rotation === 45) {\n const sz = Math.min(sw, sh) * 0.7;\n const rcx = sx + sw / 2, rcy = sy + sh / 2;\n svgContent += `<rect x=\"${rcx - sz / 2}\" y=\"${rcy - sz / 2}\" width=\"${sz}\" height=\"${sz}\" fill=\"${fill}\" stroke=\"${stroke}\" stroke-width=\"1.5\" transform=\"rotate(45, ${rcx}, ${rcy})\" />`;\n // Embedded label for diamond\n if (shape.label) {\n let lf = shape.labelColor || stroke;\n if (isColorTooDark(lf)) lf = '#d0d0d0';\n const fs = Math.max(8, (shape.labelFontSize || 14) * scale);\n svgContent += `<text x=\"${rcx}\" y=\"${rcy}\" text-anchor=\"middle\" dominant-baseline=\"central\" fill=\"${lf}\" font-size=\"${fs}\" font-family=\"lixFont, sans-serif\">${escapeXml(shape.label)}</text>`;\n }\n } else {\n svgContent += `<rect x=\"${sx}\" y=\"${sy}\" width=\"${sw}\" height=\"${sh}\" rx=\"4\" fill=\"${fill}\" stroke=\"${stroke}\" stroke-width=\"1.5\" />`;\n // Embedded label\n if (shape.label) {\n let lf = shape.labelColor || stroke;\n if (isColorTooDark(lf)) lf = '#d0d0d0';\n const fs = Math.max(8, (shape.labelFontSize || 14) * scale);\n svgContent += `<text x=\"${sx + sw / 2}\" y=\"${sy + sh / 2}\" text-anchor=\"middle\" dominant-baseline=\"central\" fill=\"${lf}\" font-size=\"${fs}\" font-family=\"lixFont, sans-serif\">${escapeXml(shape.label)}</text>`;\n }\n }\n } else if (shape.shapeName === 'circle') {\n const ccx = shape.x * scale + offX;\n const ccy = shape.y * scale + offY;\n const crx = (shape.rx || 30) * scale;\n const cry = (shape.ry || 30) * scale;\n const stroke = shape.options?.stroke || '#e0e0e0';\n const fill = shape.options?.fill || 'transparent';\n svgContent += `<ellipse cx=\"${ccx}\" cy=\"${ccy}\" rx=\"${crx}\" ry=\"${cry}\" fill=\"${fill}\" stroke=\"${stroke}\" stroke-width=\"1.5\" />`;\n // Embedded label\n if (shape.label) {\n let lf = shape.labelColor || stroke;\n if (isColorTooDark(lf)) lf = '#d0d0d0';\n const fs = Math.max(8, (shape.labelFontSize || 14) * scale);\n svgContent += `<text x=\"${ccx}\" y=\"${ccy}\" text-anchor=\"middle\" dominant-baseline=\"central\" fill=\"${lf}\" font-size=\"${fs}\" font-family=\"lixFont, sans-serif\">${escapeXml(shape.label)}</text>`;\n }\n } else if (shape.shapeName === 'text') {\n const textEl = shape.group?.querySelector('text');\n if (textEl) {\n const tx = parseFloat(shape.group.getAttribute('data-x') || '0');\n const ty = parseFloat(shape.group.getAttribute('data-y') || '0');\n const fill = textEl.getAttribute('fill') || '#e0e0e0';\n const fontSize = Math.max(8, (parseFloat(textEl.getAttribute('font-size')) || 14) * scale);\n const text = textEl.textContent || '';\n let labelFill = fill;\n if (isColorTooDark(labelFill)) labelFill = '#d0d0d0';\n svgContent += `<text x=\"${tx * scale + offX}\" y=\"${ty * scale + offY}\" text-anchor=\"middle\" dominant-baseline=\"central\" fill=\"${labelFill}\" font-size=\"${fontSize}\" font-family=\"lixFont, sans-serif\">${escapeXml(text)}</text>`;\n }\n } else if (shape.shapeName === 'arrow') {\n const sp = shape.startPoint, ep = shape.endPoint;\n if (sp && ep) {\n const stroke = shape.options?.stroke || '#e0e0e0';\n const sx1 = sp.x * scale + offX, sy1 = sp.y * scale + offY;\n const sx2 = ep.x * scale + offX, sy2 = ep.y * scale + offY;\n // Render curved if arrow has control points\n if (shape.arrowCurved === 'curved' && shape.controlPoint1 && shape.controlPoint2) {\n const cp1x = shape.controlPoint1.x * scale + offX;\n const cp1y = shape.controlPoint1.y * scale + offY;\n const cp2x = shape.controlPoint2.x * scale + offX;\n const cp2y = shape.controlPoint2.y * scale + offY;\n svgContent += `<path d=\"M ${sx1} ${sy1} C ${cp1x} ${cp1y}, ${cp2x} ${cp2y}, ${sx2} ${sy2}\" fill=\"none\" stroke=\"${stroke}\" stroke-width=\"1.5\" marker-end=\"url(#frame-preview-arrow)\" />`;\n } else {\n svgContent += `<line x1=\"${sx1}\" y1=\"${sy1}\" x2=\"${sx2}\" y2=\"${sy2}\" stroke=\"${stroke}\" stroke-width=\"1.5\" marker-end=\"url(#frame-preview-arrow)\" />`;\n }\n // Arrow label\n if (shape.label) {\n const amx = (sx1 + sx2) / 2, amy = (sy1 + sy2) / 2 - 8;\n const afs = Math.max(7, (shape.labelFontSize || 11) * scale);\n svgContent += `<text x=\"${amx}\" y=\"${amy}\" text-anchor=\"middle\" fill=\"${shape.labelColor || stroke}\" font-size=\"${afs}\" font-family=\"lixFont, sans-serif\">${escapeXml(shape.label)}</text>`;\n }\n }\n } else if (shape.shapeName === 'line') {\n const sp = shape.startPoint, ep = shape.endPoint;\n if (sp && ep) {\n const stroke = shape.options?.stroke || '#e0e0e0';\n const sx1 = sp.x * scale + offX, sy1 = sp.y * scale + offY;\n const sx2 = ep.x * scale + offX, sy2 = ep.y * scale + offY;\n // Render curved if line has control point\n if (shape.isCurved && shape.controlPoint) {\n const cpx = shape.controlPoint.x * scale + offX;\n const cpy = shape.controlPoint.y * scale + offY;\n svgContent += `<path d=\"M ${sx1} ${sy1} Q ${cpx} ${cpy} ${sx2} ${sy2}\" fill=\"none\" stroke=\"${stroke}\" stroke-width=\"1.5\" />`;\n } else {\n svgContent += `<line x1=\"${sx1}\" y1=\"${sy1}\" x2=\"${sx2}\" y2=\"${sy2}\" stroke=\"${stroke}\" stroke-width=\"1.5\" />`;\n }\n // Line label\n if (shape.label) {\n const lmx = (sx1 + sx2) / 2, lmy = (sy1 + sy2) / 2 - 8;\n const lfs = Math.max(7, (shape.labelFontSize || 11) * scale);\n svgContent += `<text x=\"${lmx}\" y=\"${lmy}\" text-anchor=\"middle\" fill=\"${shape.labelColor || stroke}\" font-size=\"${lfs}\" font-family=\"lixFont, sans-serif\">${escapeXml(shape.label)}</text>`;\n }\n }\n } else if (shape.shapeName === 'icon') {\n const ix = parseFloat(shape.group?.getAttribute('data-shape-x') || '0');\n const iy = parseFloat(shape.group?.getAttribute('data-shape-y') || '0');\n const iw = parseFloat(shape.group?.getAttribute('data-shape-width') || '40');\n const ih = parseFloat(shape.group?.getAttribute('data-shape-height') || '40');\n const pix = ix * scale + offX;\n const piy = iy * scale + offY;\n const piw = iw * scale;\n const pih = ih * scale;\n\n // Try to extract actual icon SVG paths from the shape's group\n const iconPaths = shape.group?.querySelectorAll('path, circle, rect, polygon, polyline, line, ellipse');\n if (iconPaths && iconPaths.length > 0) {\n // Get viewbox dimensions for proper scaling\n const vbW = parseFloat(shape.group?.getAttribute('data-viewbox-width') || iw);\n const vbH = parseFloat(shape.group?.getAttribute('data-viewbox-height') || ih);\n const iconScale = Math.min(piw / vbW, pih / vbH);\n svgContent += `<g transform=\"translate(${pix}, ${piy}) scale(${iconScale})\">`;\n iconPaths.forEach(p => {\n // Skip hit-detection rects (transparent fill, no stroke)\n if (p.tagName === 'rect' && p.getAttribute('fill') === 'transparent' && p.getAttribute('stroke') === 'none') return;\n const clone = p.cloneNode(true);\n svgContent += clone.outerHTML;\n });\n svgContent += `</g>`;\n } else {\n // Fallback: dashed bounding box with \"icon\" text\n svgContent += `<rect x=\"${pix}\" y=\"${piy}\" width=\"${piw}\" height=\"${pih}\" rx=\"4\" fill=\"transparent\" stroke=\"#9090c0\" stroke-width=\"1\" stroke-dasharray=\"3 2\" />`;\n svgContent += `<text x=\"${pix + piw / 2}\" y=\"${piy + pih / 2}\" text-anchor=\"middle\" dominant-baseline=\"central\" fill=\"#9090c0\" font-size=\"9\" font-family=\"lixFont\">icon</text>`;\n }\n } else if (shape.shapeName === 'frame') {\n // Sub-frame\n const sx = shape.x * scale + offX;\n const sy = shape.y * scale + offY;\n const sw = shape.width * scale;\n const sh = shape.height * scale;\n svgContent += `<rect x=\"${sx}\" y=\"${sy}\" width=\"${sw}\" height=\"${sh}\" rx=\"4\" fill=\"transparent\" stroke=\"${shape.options?.stroke || '#555'}\" stroke-width=\"1\" stroke-dasharray=\"4 2\" opacity=\"0.6\" />`;\n if (shape.frameName) {\n svgContent += `<text x=\"${sx + 6}\" y=\"${sy + 12}\" fill=\"#888\" font-size=\"9\" font-family=\"lixFont\">${escapeXml(shape.frameName)}</text>`;\n }\n }\n });\n }\n\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\" viewBox=\"0 0 ${width} ${height}\">\n <defs><marker id=\"frame-preview-arrow\" markerWidth=\"8\" markerHeight=\"6\" refX=\"8\" refY=\"3\" orient=\"auto\"><path d=\"M0,0 L8,3 L0,6\" fill=\"none\" stroke=\"#e0e0e0\" stroke-width=\"1\" /></marker></defs>\n ${svgContent}\n</svg>`;\n}\n\n// ============================================================\n// INIT\n// ============================================================\n\nexport function initAIRenderer() {\n // Expose the autoAttach helper so sibling renderers (Mermaid flowchart,\n // Graph, LixScript) can wire arrow endpoints into shapes without\n // import-cycling through this large module.\n window.__autoAttach = autoAttach;\n\n // Lazy-load sequence renderer\n let _seqParser = null;\n let _seqPreview = null;\n let _seqCanvas = null;\n\n // Lazy-load flowchart renderer\n let _fcPreview = null;\n let _fcCanvas = null;\n\n async function loadSequenceRenderer() {\n if (_seqParser) return;\n const mod = await import('./MermaidSequenceParser.js');\n const rend = await import('./MermaidSequenceRenderer.js');\n _seqParser = mod.parseSequenceDiagram;\n _seqPreview = rend.renderSequencePreviewSVG;\n _seqCanvas = rend.renderSequenceOnCanvas;\n }\n\n async function loadFlowchartRenderer() {\n if (_fcPreview) return;\n const mod = await import('./MermaidFlowchartRenderer.js');\n _fcPreview = mod.renderFlowchartPreviewSVG;\n _fcCanvas = mod.renderFlowchartOnCanvas;\n }\n\n // Detect if source is a sequence diagram\n function isSequenceDiagram(src) {\n return src.trim().split('\\n')[0].trim().toLowerCase() === 'sequencediagram';\n }\n\n window.__aiRenderer = renderAIDiagram;\n window.__aiPreview = generatePreviewSVG;\n window.__aiFramePreview = generateFramePreviewSVG;\n\n // Unified mermaid parser: supports graph/flowchart + sequenceDiagram\n window.__mermaidParser = (src) => {\n if (isSequenceDiagram(src)) {\n try {\n if (_seqParser) return _seqParser(src);\n loadSequenceRenderer();\n return { _pendingSequence: true, src };\n } catch {\n return null;\n }\n }\n return parseMermaid(src);\n };\n\n // Unified mermaid preview: returns SVG for both flowchart and sequence\n window.__mermaidPreview = async (src) => {\n if (isSequenceDiagram(src)) {\n await loadSequenceRenderer();\n const diagram = _seqParser(src);\n if (!diagram) return '';\n return _seqPreview(diagram);\n }\n // Flowchart: use unified flowchart renderer\n await loadFlowchartRenderer();\n const diagram = parseMermaid(src);\n if (!diagram) return '';\n return _fcPreview(diagram);\n };\n\n // Unified mermaid renderer: places on canvas\n window.__mermaidRenderer = async (src) => {\n if (isSequenceDiagram(src)) {\n await loadSequenceRenderer();\n const diagram = _seqParser(src);\n if (!diagram) { console.error('[AIRenderer] Sequence parse failed'); return false; }\n return _seqCanvas(diagram);\n }\n // Flowchart: use unified flowchart renderer (same SVG as preview)\n await loadFlowchartRenderer();\n const diagram = parseMermaid(src);\n if (!diagram) { console.error('[AIRenderer] Mermaid parse failed'); return false; }\n return _fcCanvas(diagram);\n };\n\n // Pre-load renderers so they're ready\n loadSequenceRenderer();\n loadFlowchartRenderer();\n}\n"],
5
- "mappings": "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",
6
- "names": ["nodeIds", "px", "py", "diagram"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/core/MermaidFlowchartRenderer.js"],
4
- "sourcesContent": ["/* eslint-disable */\n/**\n * MermaidFlowchartRenderer - Renders parsed flowchart diagrams as high-quality SVG.\n *\n * One renderer for both preview and canvas \u2014 ensures they always match.\n * Supports: rectangle [], rounded rectangle (), circle (()), diamond/rhombus {},\n * directed/undirected edges with labels, subgraphs, all directions (TD/TB/LR/RL/BT).\n *\n * Dark theme matching the app aesthetic.\n */\n\n// Layout constants\nconst NODE_W = 150;\nconst NODE_H = 50;\nconst H_SPACING = 200;\nconst V_SPACING = 120;\nconst SIDE_MARGIN = 50;\nconst TOP_MARGIN = 40;\nconst FONT_FAMILY = 'lixFont, sans-serif';\n\n// Issue #38 follow-up: theme-aware stroke / fill. Resolved at draw time\n// so a single render call uses whichever palette is active.\nfunction isThemeDark() {\n if (typeof document === 'undefined') return true;\n return !!(document.body && document.body.classList.contains('theme-dark'));\n}\nfunction nodeStrokeColor() { return isThemeDark() ? '#fff' : '#1a1a2e'; }\nfunction edgeStrokeColor() { return isThemeDark() ? '#888' : '#444'; }\n\n// Theme colors (dark theme \u2014 used by the SVG-string preview path only)\nconst THEME = {\n bg: '#1e1e28',\n nodeBg: 'transparent',\n nodeStroke: '#9090c0',\n nodeText: '#e0e0e0',\n edgeStroke: '#888',\n edgeText: '#a0a0b0',\n subgraphBg: 'rgba(80,80,120,0.08)',\n subgraphBorder: '#555',\n subgraphLabel: '#888',\n};\n\nfunction escapeXml(str) {\n return String(str)\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;');\n}\n\nfunction measureText(text, fontSize) {\n return text.length * fontSize * 0.55;\n}\n\n/**\n * Render a parsed flowchart diagram to SVG markup.\n *\n * @param {Object} diagram - Parsed from parseMermaid()\n * @param {Object} opts - { width?, height?, fitToContent? }\n * @returns {string} SVG markup string\n */\nexport function renderFlowchartSVG(diagram, opts = {}) {\n if (!diagram || !diagram.nodes || diagram.nodes.length === 0) return '';\n\n const nodes = diagram.nodes;\n const edges = diagram.edges || [];\n const subgraphs = diagram.subgraphs || [];\n const direction = diagram.direction || 'TD';\n\n // Compute bounds of laid-out nodes\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n nodes.forEach(n => {\n const nw = n.width || NODE_W;\n const nh = n.height || NODE_H;\n minX = Math.min(minX, n.x);\n minY = Math.min(minY, n.y);\n maxX = Math.max(maxX, n.x + nw);\n maxY = Math.max(maxY, n.y + nh);\n });\n\n const dw = maxX - minX || 1;\n const dh = maxY - minY || 1;\n\n // If fitToContent or explicit size, scale to fit\n const targetW = opts.width || dw + SIDE_MARGIN * 2;\n const targetH = opts.height || dh + TOP_MARGIN * 2;\n\n let scale, offX, offY;\n if (opts.width || opts.height) {\n const pad = 40;\n scale = Math.min(\n (targetW - pad * 2) / dw,\n (targetH - pad * 2) / dh,\n 1.8\n );\n offX = (targetW - dw * scale) / 2 - minX * scale;\n offY = (targetH - dh * scale) / 2 - minY * scale;\n } else {\n scale = 1;\n offX = SIDE_MARGIN - minX;\n offY = TOP_MARGIN - minY;\n }\n\n const totalWidth = opts.width || Math.round(dw * scale + SIDE_MARGIN * 2);\n const totalHeight = opts.height || Math.round(dh * scale + TOP_MARGIN * 2);\n\n // Build node lookup for edge rendering\n const nodeById = new Map();\n nodes.forEach(n => {\n const nw = (n.width || NODE_W) * scale;\n const nh = (n.height || NODE_H) * scale;\n const nx = n.x * scale + offX;\n const ny = n.y * scale + offY;\n nodeById.set(n.id, {\n x: nx, y: ny, w: nw, h: nh,\n cx: nx + nw / 2, cy: ny + nh / 2,\n type: n.type, label: n.label,\n fill: n.fill, stroke: n.stroke, strokeWidth: n.strokeWidth,\n });\n });\n\n let svg = '';\n const defs = [];\n\n // Arrow markers (normal, dotted, thick)\n defs.push(`<marker id=\"fc-arrow\" markerWidth=\"10\" markerHeight=\"7\" refX=\"9\" refY=\"3.5\" orient=\"auto\">\n <path d=\"M1,1 L9,3.5 L1,6\" fill=\"none\" stroke=\"${THEME.edgeStroke}\" stroke-width=\"1.5\" stroke-linejoin=\"round\" />\n </marker>`);\n defs.push(`<marker id=\"fc-arrow-thick\" markerWidth=\"12\" markerHeight=\"9\" refX=\"11\" refY=\"4.5\" orient=\"auto\">\n <path d=\"M1,1 L11,4.5 L1,8\" fill=\"none\" stroke=\"${THEME.edgeStroke}\" stroke-width=\"2\" stroke-linejoin=\"round\" />\n </marker>`);\n\n // Background\n svg += `<rect x=\"0\" y=\"0\" width=\"${totalWidth}\" height=\"${totalHeight}\" fill=\"${THEME.bg}\" rx=\"8\" />`;\n\n // --- Subgraphs (rendered first, behind everything) ---\n for (const sg of subgraphs) {\n if (!sg.nodes || sg.nodes.length === 0) continue;\n\n let sgMinX = Infinity, sgMinY = Infinity, sgMaxX = -Infinity, sgMaxY = -Infinity;\n let hasNodes = false;\n for (const nid of sg.nodes) {\n const nd = nodeById.get(nid);\n if (!nd) continue;\n hasNodes = true;\n sgMinX = Math.min(sgMinX, nd.x);\n sgMinY = Math.min(sgMinY, nd.y);\n sgMaxX = Math.max(sgMaxX, nd.x + nd.w);\n sgMaxY = Math.max(sgMaxY, nd.y + nd.h);\n }\n if (!hasNodes) continue;\n\n const sgPad = 20 * scale;\n const sgX = sgMinX - sgPad;\n const sgY = sgMinY - sgPad - 16 * scale;\n const sgW = (sgMaxX - sgMinX) + sgPad * 2;\n const sgH = (sgMaxY - sgMinY) + sgPad * 2 + 16 * scale;\n\n svg += `<g data-fc-type=\"subgraph\" data-fc-id=\"${escapeXml(sg.id)}\">`;\n svg += `<rect x=\"${sgX}\" y=\"${sgY}\" width=\"${sgW}\" height=\"${sgH}\" rx=\"6\" fill=\"${THEME.subgraphBg}\" stroke=\"${THEME.subgraphBorder}\" stroke-width=\"1\" stroke-dasharray=\"4 2\" />`;\n if (sg.label) {\n svg += `<text x=\"${sgX + 8}\" y=\"${sgY + 14}\" fill=\"${THEME.subgraphLabel}\" font-size=\"${Math.max(9, 11 * scale)}\" font-family=\"${FONT_FAMILY}\">${escapeXml(sg.label)}</text>`;\n }\n svg += `</g>`;\n }\n\n // --- Edges ---\n edges.forEach(e => {\n const f = nodeById.get(e.from);\n const t = nodeById.get(e.to);\n if (!f || !t) return;\n\n const directed = e.directed !== false;\n const edgeStyle = e.style || 'normal';\n let strokeW, dashArr, markerRef;\n if (edgeStyle === 'thick') {\n strokeW = 3;\n dashArr = '';\n markerRef = directed ? ' marker-end=\"url(#fc-arrow-thick)\"' : '';\n } else if (edgeStyle === 'dotted') {\n strokeW = 1.5;\n dashArr = ' stroke-dasharray=\"5 3\"';\n markerRef = directed ? ' marker-end=\"url(#fc-arrow)\"' : '';\n } else {\n strokeW = 1.5;\n dashArr = '';\n markerRef = directed ? ' marker-end=\"url(#fc-arrow)\"' : '';\n }\n const eStroke = e.stroke || THEME.edgeStroke;\n\n // Compute connection points\n const sp = getEdgePoint(f, t);\n const ep = getEdgePoint(t, f);\n\n // Determine if we should curve\n const dx = t.cx - f.cx;\n const dy = t.cy - f.cy;\n const dist = Math.sqrt(dx * dx + dy * dy);\n let mx = (sp.x + ep.x) / 2;\n let my = (sp.y + ep.y) / 2;\n\n svg += `<g data-fc-type=\"edge\" data-fc-from=\"${escapeXml(e.from)}\" data-fc-to=\"${escapeXml(e.to)}\">`;\n\n if (dist > 0 && Math.abs(dy) > 15 && Math.abs(dx) > 15) {\n // Curved edge\n const perpX = -dy / dist;\n const perpY = dx / dist;\n const curveAmt = dist * 0.12;\n const cpx = mx + perpX * curveAmt;\n const cpy = my + perpY * curveAmt;\n mx = 0.25 * sp.x + 0.5 * cpx + 0.25 * ep.x;\n my = 0.25 * sp.y + 0.5 * cpy + 0.25 * ep.y;\n svg += `<path d=\"M ${sp.x} ${sp.y} Q ${cpx} ${cpy} ${ep.x} ${ep.y}\" fill=\"none\" stroke=\"${eStroke}\" stroke-width=\"${strokeW}\"${dashArr}${markerRef} />`;\n } else {\n svg += `<line x1=\"${sp.x}\" y1=\"${sp.y}\" x2=\"${ep.x}\" y2=\"${ep.y}\" stroke=\"${eStroke}\" stroke-width=\"${strokeW}\"${dashArr}${markerRef} />`;\n }\n\n // Edge label (supports multi-line via \\n)\n if (e.label) {\n const labelFontSize = Math.max(8, 10 * scale);\n const labelLines = e.label.split('\\n');\n const maxLineW = Math.max(...labelLines.map(l => measureText(l, labelFontSize)));\n const labelW = maxLineW + 12;\n const labelH = labelLines.length * (labelFontSize + 3) + 6;\n svg += `<rect x=\"${mx - labelW / 2}\" y=\"${my - labelH / 2}\" width=\"${labelW}\" height=\"${labelH}\" rx=\"3\" fill=\"${THEME.bg}\" opacity=\"0.85\" />`;\n if (labelLines.length === 1) {\n svg += `<text x=\"${mx}\" y=\"${my + 1}\" text-anchor=\"middle\" dominant-baseline=\"central\" fill=\"${THEME.edgeText}\" font-size=\"${labelFontSize}\" font-family=\"${FONT_FAMILY}\">${escapeXml(e.label)}</text>`;\n } else {\n const startY = my - ((labelLines.length - 1) * (labelFontSize + 3)) / 2;\n svg += `<text x=\"${mx}\" text-anchor=\"middle\" fill=\"${THEME.edgeText}\" font-size=\"${labelFontSize}\" font-family=\"${FONT_FAMILY}\">`;\n labelLines.forEach((ln, idx) => {\n svg += `<tspan x=\"${mx}\" dy=\"${idx === 0 ? 0 : labelFontSize + 3}\" y=\"${idx === 0 ? startY : ''}\">${escapeXml(ln)}</tspan>`;\n });\n svg += `</text>`;\n }\n }\n\n svg += `</g>`;\n });\n\n // --- Nodes ---\n nodes.forEach(n => {\n const d = nodeById.get(n.id);\n if (!d) return;\n\n const nStroke = n.stroke || THEME.nodeStroke;\n const nFill = n.fill || THEME.nodeBg;\n const nStrokeWidth = n.strokeWidth || 1.8;\n const fontSize = Math.max(9, Math.min(13, 12 * scale));\n\n svg += `<g data-fc-type=\"node\" data-fc-id=\"${escapeXml(n.id)}\">`;\n\n if (n.type === 'circle') {\n const r = Math.min(d.w, d.h) / 2;\n svg += `<circle cx=\"${d.cx}\" cy=\"${d.cy}\" r=\"${r}\" fill=\"${nFill}\" stroke=\"${nStroke}\" stroke-width=\"${nStrokeWidth}\" />`;\n } else if (n.type === 'diamond') {\n const hw = d.w / 2 * 0.85;\n const hh = d.h / 2 * 0.85;\n svg += `<polygon points=\"${d.cx},${d.cy - hh} ${d.cx + hw},${d.cy} ${d.cx},${d.cy + hh} ${d.cx - hw},${d.cy}\" fill=\"${nFill}\" stroke=\"${nStroke}\" stroke-width=\"${nStrokeWidth}\" />`;\n } else if (n.type === 'asymmetric') {\n // Flag/asymmetric shape: pointed left, flat right\n const notchX = d.x + 15 * scale;\n svg += `<polygon points=\"${d.x},${d.y} ${d.x + d.w},${d.y} ${d.x + d.w},${d.y + d.h} ${d.x},${d.y + d.h} ${notchX},${d.cy}\" fill=\"${nFill}\" stroke=\"${nStroke}\" stroke-width=\"${nStrokeWidth}\" />`;\n } else if (n.type === 'roundrect') {\n svg += `<rect x=\"${d.x}\" y=\"${d.y}\" width=\"${d.w}\" height=\"${d.h}\" rx=\"${12 * scale}\" fill=\"${nFill}\" stroke=\"${nStroke}\" stroke-width=\"${nStrokeWidth}\" />`;\n } else {\n svg += `<rect x=\"${d.x}\" y=\"${d.y}\" width=\"${d.w}\" height=\"${d.h}\" rx=\"${3 * scale}\" fill=\"${nFill}\" stroke=\"${nStroke}\" stroke-width=\"${nStrokeWidth}\" />`;\n }\n\n // Node label (supports multi-line via \\n)\n if (n.label) {\n let labelFill = nFill && nFill !== 'transparent' && nFill !== THEME.nodeBg ? getContrastColor(nFill) : nStroke;\n if (isColorTooDark(labelFill)) labelFill = '#d0d0d0';\n\n const labelLines = n.label.split('\\n');\n if (labelLines.length === 1) {\n svg += `<text x=\"${d.cx}\" y=\"${d.cy}\" text-anchor=\"middle\" dominant-baseline=\"central\" fill=\"${labelFill}\" font-size=\"${fontSize}\" font-family=\"${FONT_FAMILY}\" font-weight=\"500\">${escapeXml(n.label)}</text>`;\n } else {\n const lineH = fontSize + 3;\n const startY = d.cy - ((labelLines.length - 1) * lineH) / 2;\n svg += `<text text-anchor=\"middle\" fill=\"${labelFill}\" font-size=\"${fontSize}\" font-family=\"${FONT_FAMILY}\" font-weight=\"500\">`;\n labelLines.forEach((ln, idx) => {\n svg += `<tspan x=\"${d.cx}\" y=\"${startY + idx * lineH}\">${escapeXml(ln)}</tspan>`;\n });\n svg += `</text>`;\n }\n }\n\n svg += `</g>`;\n });\n\n // Build final SVG\n const defsStr = defs.length > 0 ? `<defs>${defs.join('')}</defs>` : '';\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${totalWidth}\" height=\"${totalHeight}\" viewBox=\"0 0 ${totalWidth} ${totalHeight}\">${defsStr}${svg}</svg>`;\n}\n\n/**\n * Get the connection point on a node's boundary toward another node.\n */\nfunction getEdgePoint(node, target) {\n const dx = target.cx - node.cx;\n const dy = target.cy - node.cy;\n\n if (node.type === 'circle') {\n const r = Math.min(node.w, node.h) / 2;\n const dist = Math.sqrt(dx * dx + dy * dy) || 1;\n return { x: node.cx + (dx / dist) * r, y: node.cy + (dy / dist) * r };\n }\n\n if (node.type === 'diamond') {\n // Diamond edge intersection\n const hw = node.w / 2 * 0.85;\n const hh = node.h / 2 * 0.85;\n const adx = Math.abs(dx) || 0.001;\n const ady = Math.abs(dy) || 0.001;\n const t = Math.min(hw / adx, hh / ady);\n return { x: node.cx + dx * t * 0.95, y: node.cy + dy * t * 0.95 };\n }\n\n // Rectangle / rounded rect / asymmetric - exit from edges\n const hw = node.w / 2;\n const hh = node.h / 2;\n\n if (Math.abs(dx) < 0.001 || Math.abs(dy) * hw > Math.abs(dx) * hh) {\n if (dy > 0) return { x: node.cx, y: node.y + node.h };\n return { x: node.cx, y: node.y };\n }\n if (dx > 0) return { x: node.x + node.w, y: node.cy };\n return { x: node.x, y: node.cy };\n}\n\nfunction isColorTooDark(hex) {\n if (!hex || hex === 'transparent' || hex === 'none') return false;\n const rgb = parseColor(hex);\n if (!rgb) return false;\n return (0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b) < 80;\n}\n\nfunction parseColor(hex) {\n if (!hex || hex === 'transparent' || hex === 'none') return null;\n let c = hex.replace('#', '');\n // Support 3-char shorthand (#9f6 \u2192 #99ff66)\n if (c.length === 3) c = c[0] + c[0] + c[1] + c[1] + c[2] + c[2];\n if (c.length < 6) return null;\n return {\n r: parseInt(c.substring(0, 2), 16),\n g: parseInt(c.substring(2, 4), 16),\n b: parseInt(c.substring(4, 6), 16),\n };\n}\n\nfunction getLuminance(hex) {\n const rgb = parseColor(hex);\n if (!rgb) return 0;\n return 0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b;\n}\n\nfunction getContrastColor(bgHex) {\n // Pick dark or light text based on background luminance\n return getLuminance(bgHex) > 140 ? '#1a1a2e' : '#f0f0f0';\n}\n\n/**\n * Generate preview SVG for the modal.\n */\nexport function renderFlowchartPreviewSVG(diagram) {\n return renderFlowchartSVG(diagram, { width: 600, height: 450 });\n}\n\n/**\n * Render a flowchart diagram onto the canvas as a real engine `Frame`\n * containing independent shapes \u2014 Rectangle nodes (with embedded labels)\n * joined by Arrow edges. Each child is fully independent for click /\n * drag / resize / colour-change, exactly like a user-drawn shape; the\n * Frame's `_diagramType` marker means deleting it pulls every child with\n * it (so the diagram behaves as one logical unit when you're done with\n * it) \u2014 see Frame.destroy().\n *\n * Issue #34 bug #3 (follow-up to #22 phase 5): drops the shared `groupId`\n * glue that made selecting one shape select the whole diagram; the Frame\n * is the explicit container instead.\n */\nexport function renderFlowchartOnCanvas(diagram) {\n if (!diagram || !diagram.nodes || diagram.nodes.length === 0) return false;\n if (!window.svg || !window.Rectangle || !window.Frame) {\n console.error('[FlowchartRenderer] Engine not initialized');\n return false;\n }\n\n const nodes = diagram.nodes;\n const edges = diagram.edges || [];\n\n // Diagram bounds (in the renderer's natural coordinate space)\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n nodes.forEach((n) => {\n const nw = n.width || 140;\n const nh = n.height || 60;\n minX = Math.min(minX, n.x);\n minY = Math.min(minY, n.y);\n maxX = Math.max(maxX, n.x + nw);\n maxY = Math.max(maxY, n.y + nh);\n });\n const dw = (maxX - minX) || 1;\n const dh = (maxY - minY) || 1;\n\n // Center on the current viewport\n const vb = window.currentViewBox || { x: 0, y: 0, width: window.innerWidth, height: window.innerHeight };\n const vcx = vb.x + vb.width / 2;\n const vcy = vb.y + vb.height / 2;\n const ox = vcx - dw / 2 - minX;\n const oy = vcy - dh / 2 - minY;\n\n // \u2500\u2500 Wrapper frame \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Created up-front so we can call addShapeToFrame as each child is\n // built. _diagramType marks it so Frame.destroy() takes the children\n // along on delete (issue #34 bug #3).\n //\n // PADDING bumped from 40 \u2192 90 so edge labels, rotated diamond nodes,\n // and arrow heads near the diagram boundary stay inside the frame\n // instead of getting clipped at the corners.\n const PADDING = 90;\n const frameTitle = diagram.title || 'Mermaid diagram';\n const frame = new window.Frame(\n vcx - dw / 2 - PADDING,\n vcy - dh / 2 - PADDING,\n dw + PADDING * 2,\n dh + PADDING * 2,\n {\n stroke: '#888',\n strokeWidth: 1,\n fill: 'transparent',\n opacity: 0.7,\n frameName: frameTitle,\n }\n );\n frame._diagramType = 'mermaid-flowchart';\n window.shapes.push(frame);\n if (window.pushCreateAction) window.pushCreateAction(frame);\n\n const nodeMap = new Map(); // id \u2192 shape\n\n // \u2500\u2500 Nodes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n for (const n of nodes) {\n const nw = n.width || 140;\n const nh = n.height || 60;\n const nx = n.x + ox;\n const ny = n.y + oy;\n const cx = nx + nw / 2;\n const cy = ny + nh / 2;\n\n const opts = {\n stroke: n.stroke || nodeStrokeColor(),\n strokeWidth: n.strokeWidth ?? 1.5,\n fill: n.fill || 'transparent',\n fillStyle: n.fill && n.fill !== 'transparent' ? 'solid' : 'none',\n roughness: 1,\n label: n.label || '',\n labelColor: n.labelColor || nodeStrokeColor(),\n };\n\n let shape = null;\n try {\n if (n.type === 'circle' && window.Circle) {\n shape = new window.Circle(cx, cy, nw / 2, nh / 2, opts);\n } else if (n.type === 'diamond') {\n const sz = Math.max(nw, nh) * 0.75;\n shape = new window.Rectangle(cx - sz / 2, cy - sz / 2, sz, sz, opts);\n shape.rotation = 45;\n if (typeof shape.draw === 'function') shape.draw();\n } else if (n.type === 'roundrect') {\n shape = new window.Rectangle(nx, ny, nw, nh, { ...opts, cornerRadius: Math.min(nw, nh) * 0.2 });\n } else {\n shape = new window.Rectangle(nx, ny, nw, nh, opts);\n }\n } catch (err) {\n console.warn('[FlowchartRenderer] Node creation failed:', n.id, err);\n continue;\n }\n if (!shape) continue;\n\n window.shapes.push(shape);\n if (window.pushCreateAction) window.pushCreateAction(shape);\n frame.addShapeToFrame(shape);\n\n nodeMap.set(n.id, { shape, x: nx, y: ny, width: nw, height: nh, centerX: cx, centerY: cy });\n }\n\n // \u2500\u2500 Edges \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n for (const e of edges) {\n const fromNode = nodeMap.get(e.from);\n const toNode = nodeMap.get(e.to);\n if (!fromNode || !toNode) continue;\n\n // Connect from the source center to the target center \u2014 autoAttach\n // will snap each endpoint to the appropriate edge of the shape.\n const sp = { x: fromNode.centerX, y: fromNode.centerY };\n const ep = { x: toNode.centerX, y: toNode.centerY };\n\n const directed = e.directed !== false;\n const style = e.style || 'normal';\n const isThick = style === 'thick';\n const isDotted = style === 'dotted';\n\n const opts = {\n stroke: e.stroke || edgeStrokeColor(),\n strokeWidth: isThick ? 3 : 1.5,\n roughness: 1,\n strokeDasharray: isDotted ? '5 3' : '',\n label: e.label || '',\n labelColor: e.labelColor || edgeStrokeColor(),\n };\n\n let connector = null;\n try {\n if (directed && window.Arrow) {\n connector = new window.Arrow(sp, ep, opts);\n } else if (window.Line) {\n connector = new window.Line(sp, ep, opts);\n } else if (window.Arrow) {\n connector = new window.Arrow(sp, ep, opts);\n }\n } catch (err) {\n console.warn('[FlowchartRenderer] Edge creation failed:', e, err);\n continue;\n }\n if (!connector) continue;\n\n window.shapes.push(connector);\n if (window.pushCreateAction) window.pushCreateAction(connector);\n frame.addShapeToFrame(connector);\n\n // Wire arrow endpoints into the source/target shapes so moving a\n // node drags its connections along. window.__autoAttach is set up\n // by AIRenderer.initAIRenderer() during engine init.\n if (directed && connector.shapeName === 'arrow' && typeof window.__autoAttach === 'function') {\n try {\n window.__autoAttach(connector, fromNode.shape, true, sp);\n window.__autoAttach(connector, toNode.shape, false, ep);\n } catch (err) {\n console.warn('[FlowchartRenderer] autoAttach failed:', err);\n }\n }\n }\n\n // Select the first node so the user has feedback that something\n // landed. Selecting a child (not the frame) reinforces the\n // \"independent shapes inside a frame\" model.\n const first = nodeMap.values().next().value;\n if (first) {\n window.currentShape = first.shape;\n if (typeof first.shape.selectShape === 'function') first.shape.selectShape();\n }\n\n return true;\n}\n"],
5
- "mappings": "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",
6
- "names": ["hw", "hh"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/core/MermaidSequenceRenderer.js"],
4
- "sourcesContent": ["/* eslint-disable */\n/**\n * MermaidSequenceRenderer - Renders parsed sequence diagrams as high-quality SVG.\n *\n * One renderer for both preview and canvas \u2014 ensures they always match.\n * The canvas renderer inserts the SVG into a frame; elements inside are\n * individually editable (each participant box, message label, note, etc.\n * is its own SVG group with data attributes for the editor).\n *\n * Design follows the reference image: dark theme, clean lines,\n * participant boxes at top and bottom, dashed lifelines, arrow styles.\n */\n\nimport { parseSequenceDiagram } from './MermaidSequenceParser.js';\n\n// Layout constants\nconst PARTICIPANT_W = 100;\nconst PARTICIPANT_H = 36;\nconst PARTICIPANT_GAP = 140;\nconst MSG_ROW_HEIGHT = 50;\nconst NOTE_PAD = 10;\nconst NOTE_MAX_W = 160;\nconst TOP_MARGIN = 30;\nconst BOTTOM_MARGIN = 30;\nconst SIDE_MARGIN = 40;\nconst FONT_FAMILY = 'lixFont, sans-serif';\nconst CODE_FONT = 'lixCode, monospace';\n\n// Issue #38 follow-up: theme-aware palette. The on-canvas renderer reads\n// `themeColors()` at draw time so a single render call gets whichever\n// palette is active. The dark THEME object below is kept for the SVG-\n// string preview path (`renderSequenceSVG`), which is rendered inside\n// the modal's preview pane.\nfunction themeColors() {\n const isDark = typeof document !== 'undefined'\n && document.body\n && document.body.classList.contains('theme-dark');\n if (isDark) return THEME;\n return {\n bg: '#fbfaf6',\n participantBg: '#ffffff',\n participantBorder: '#9c9c9c',\n participantText: '#38384e',\n lifeline: '#b0b0b8',\n messageLine: '#62627a',\n messageDash: '#888',\n messageText: '#38384e',\n noteBg: '#fffce0',\n noteBorder: '#c0b870',\n noteText: '#5e5230',\n blockBg: 'rgba(80,80,120,0.08)',\n blockBorder: '#9c9c9c',\n blockLabel: '#62627a',\n crossColor: '#c2483a',\n };\n}\n\n// Theme colors (dark theme \u2014 preview/SVG-string path).\nconst THEME = {\n bg: '#1e1e28',\n participantBg: '#232329',\n participantBorder: '#555',\n participantText: '#e8e8ee',\n lifeline: '#444',\n messageLine: '#888',\n messageDash: '#666',\n messageText: '#e0e0e0',\n noteBg: '#3a3520',\n noteBorder: '#665e30',\n noteText: '#d4c870',\n blockBg: 'rgba(80,80,120,0.12)',\n blockBorder: '#555',\n blockLabel: '#a0a0b0',\n crossColor: '#e74c3c',\n};\n\nfunction escapeXml(str) {\n return String(str)\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;');\n}\n\n/**\n * Measure approximate text width (since we can't use DOM measurement in pure SVG generation).\n * Uses a rough character-width heuristic.\n */\nfunction measureText(text, fontSize) {\n const avgCharWidth = fontSize * 0.55;\n return text.length * avgCharWidth;\n}\n\n/**\n * Word-wrap text into lines that fit within maxWidth.\n */\nfunction wrapText(text, fontSize, maxWidth) {\n // Handle <br/> tags\n const segments = text.split(/<br\\s*\\/?>/i);\n const lines = [];\n for (const segment of segments) {\n const words = segment.split(/\\s+/);\n let currentLine = '';\n for (const word of words) {\n const testLine = currentLine ? currentLine + ' ' + word : word;\n if (measureText(testLine, fontSize) > maxWidth && currentLine) {\n lines.push(currentLine);\n currentLine = word;\n } else {\n currentLine = testLine;\n }\n }\n if (currentLine) lines.push(currentLine);\n }\n return lines.length > 0 ? lines : [''];\n}\n\n/**\n * Render a parsed sequence diagram to SVG markup.\n *\n * @param {Object} diagram - Parsed from parseSequenceDiagram()\n * @param {Object} opts - { width?, fitToContent? }\n * @returns {string} SVG markup string\n */\nexport function renderSequenceSVG(diagram, opts = {}) {\n if (!diagram || diagram.type !== 'sequenceDiagram') return '';\n\n const participants = diagram.participants;\n const messages = diagram.messages;\n const notes = diagram.notes;\n const blocks = diagram.blocks || [];\n\n const pCount = participants.length;\n if (pCount === 0) return '';\n\n // Build participant index map\n const pIndex = new Map();\n participants.forEach((p, i) => pIndex.set(p.name, i));\n\n // Calculate total width\n const contentWidth = (pCount - 1) * PARTICIPANT_GAP + PARTICIPANT_W;\n const totalWidth = opts.width || Math.max(contentWidth + SIDE_MARGIN * 2, 400);\n const startX = (totalWidth - contentWidth) / 2;\n\n // Participant X centers\n const pCenters = participants.map((_, i) => startX + i * PARTICIPANT_GAP + PARTICIPANT_W / 2);\n\n // Pre-calculate note heights to account for row expansion\n const noteAtMsg = new Map(); // msgIndex -> [{note, height}]\n for (const note of notes) {\n const fontSize = 11;\n const lines = wrapText(note.text, fontSize, NOTE_MAX_W - NOTE_PAD * 2);\n const h = lines.length * (fontSize + 4) + NOTE_PAD * 2;\n if (!noteAtMsg.has(note.atMessage)) noteAtMsg.set(note.atMessage, []);\n noteAtMsg.get(note.atMessage).push({ ...note, lines, height: h });\n }\n\n // Calculate message Y positions (accounting for notes that expand rows)\n const topBoxBottom = TOP_MARGIN + PARTICIPANT_H;\n let currentY = topBoxBottom + 30; // gap after top participant boxes\n\n const msgYPositions = [];\n for (let mi = 0; mi < messages.length; mi++) {\n // Check if notes appear before this message\n const notesBefore = noteAtMsg.get(mi);\n if (notesBefore) {\n const maxNoteH = Math.max(...notesBefore.map(n => n.height));\n currentY += maxNoteH + 10;\n }\n msgYPositions.push(currentY);\n currentY += MSG_ROW_HEIGHT;\n }\n\n // Notes after last message\n const notesAfterLast = noteAtMsg.get(messages.length);\n if (notesAfterLast) {\n const maxNoteH = Math.max(...notesAfterLast.map(n => n.height));\n currentY += maxNoteH + 10;\n }\n\n const bottomBoxTop = currentY + 20;\n const totalHeight = bottomBoxTop + PARTICIPANT_H + BOTTOM_MARGIN;\n\n // Start building SVG\n let svg = '';\n const defs = [];\n\n // Arrow markers\n defs.push(`<marker id=\"seq-arrow-open\" markerWidth=\"10\" markerHeight=\"7\" refX=\"9\" refY=\"3.5\" orient=\"auto\">\n <polyline points=\"1,1 9,3.5 1,6\" fill=\"none\" stroke=\"${THEME.messageLine}\" stroke-width=\"1.5\" stroke-linejoin=\"round\" />\n </marker>`);\n defs.push(`<marker id=\"seq-arrow-filled\" markerWidth=\"10\" markerHeight=\"7\" refX=\"9\" refY=\"3.5\" orient=\"auto\">\n <polygon points=\"1,1 9,3.5 1,6\" fill=\"${THEME.messageLine}\" stroke=\"none\" />\n </marker>`);\n\n // Background\n svg += `<rect x=\"0\" y=\"0\" width=\"${totalWidth}\" height=\"${totalHeight}\" fill=\"${THEME.bg}\" rx=\"8\" />`;\n\n // Title\n if (diagram.title) {\n svg += `<text x=\"${totalWidth / 2}\" y=\"${TOP_MARGIN - 8}\" text-anchor=\"middle\" fill=\"${THEME.participantText}\" font-size=\"14\" font-family=\"${FONT_FAMILY}\" font-weight=\"600\">${escapeXml(diagram.title)}</text>`;\n }\n\n // --- Lifelines (dashed vertical lines) ---\n for (let pi = 0; pi < pCount; pi++) {\n const cx = pCenters[pi];\n svg += `<line x1=\"${cx}\" y1=\"${topBoxBottom}\" x2=\"${cx}\" y2=\"${bottomBoxTop}\" stroke=\"${THEME.lifeline}\" stroke-width=\"1\" stroke-dasharray=\"6 4\" />`;\n }\n\n // --- Participant boxes (top) ---\n for (let pi = 0; pi < pCount; pi++) {\n const cx = pCenters[pi];\n const bx = cx - PARTICIPANT_W / 2;\n const by = TOP_MARGIN;\n svg += `<g data-seq-type=\"participant\" data-seq-id=\"${escapeXml(participants[pi].name)}\" data-seq-pos=\"top\">`;\n svg += `<rect x=\"${bx}\" y=\"${by}\" width=\"${PARTICIPANT_W}\" height=\"${PARTICIPANT_H}\" rx=\"4\" fill=\"${THEME.participantBg}\" stroke=\"${THEME.participantBorder}\" stroke-width=\"1.5\" />`;\n svg += `<text x=\"${cx}\" y=\"${by + PARTICIPANT_H / 2 + 1}\" text-anchor=\"middle\" dominant-baseline=\"central\" fill=\"${THEME.participantText}\" font-size=\"13\" font-family=\"${FONT_FAMILY}\">${escapeXml(participants[pi].name)}</text>`;\n svg += `</g>`;\n }\n\n // --- Participant boxes (bottom) ---\n for (let pi = 0; pi < pCount; pi++) {\n const cx = pCenters[pi];\n const bx = cx - PARTICIPANT_W / 2;\n const by = bottomBoxTop;\n svg += `<g data-seq-type=\"participant\" data-seq-id=\"${escapeXml(participants[pi].name)}\" data-seq-pos=\"bottom\">`;\n svg += `<rect x=\"${bx}\" y=\"${by}\" width=\"${PARTICIPANT_W}\" height=\"${PARTICIPANT_H}\" rx=\"4\" fill=\"${THEME.participantBg}\" stroke=\"${THEME.participantBorder}\" stroke-width=\"1.5\" />`;\n svg += `<text x=\"${cx}\" y=\"${by + PARTICIPANT_H / 2 + 1}\" text-anchor=\"middle\" dominant-baseline=\"central\" fill=\"${THEME.participantText}\" font-size=\"13\" font-family=\"${FONT_FAMILY}\">${escapeXml(participants[pi].name)}</text>`;\n svg += `</g>`;\n }\n\n // --- Blocks (alt/loop/opt etc.) ---\n for (const block of blocks) {\n const startY = block.startMsg < msgYPositions.length\n ? msgYPositions[block.startMsg] - 20\n : topBoxBottom + 20;\n const endY = block.endMsg <= msgYPositions.length\n ? (block.endMsg < msgYPositions.length ? msgYPositions[block.endMsg] - 10 : currentY)\n : currentY;\n\n const blockX = startX - 15;\n const blockW = contentWidth + 30;\n\n svg += `<g data-seq-type=\"block\" data-block-type=\"${block.type}\">`;\n svg += `<rect x=\"${blockX}\" y=\"${startY}\" width=\"${blockW}\" height=\"${endY - startY}\" rx=\"4\" fill=\"${THEME.blockBg}\" stroke=\"${THEME.blockBorder}\" stroke-width=\"1\" stroke-dasharray=\"4 2\" />`;\n // Type label in top-left corner\n svg += `<rect x=\"${blockX}\" y=\"${startY}\" width=\"${measureText(block.type, 10) + 12}\" height=\"18\" rx=\"3\" fill=\"${THEME.blockBorder}\" />`;\n svg += `<text x=\"${blockX + 6}\" y=\"${startY + 12}\" fill=\"${THEME.bg}\" font-size=\"10\" font-family=\"${FONT_FAMILY}\" font-weight=\"600\">${escapeXml(block.type)}</text>`;\n // Condition label\n if (block.label) {\n svg += `<text x=\"${blockX + measureText(block.type, 10) + 20}\" y=\"${startY + 12}\" fill=\"${THEME.blockLabel}\" font-size=\"10\" font-family=\"${FONT_FAMILY}\" font-style=\"italic\">[${escapeXml(block.label)}]</text>`;\n }\n\n // Section dividers (else sections)\n for (let si = 1; si < block.sections.length; si++) {\n const section = block.sections[si];\n const secY = section.startMsg < msgYPositions.length\n ? msgYPositions[section.startMsg] - 15\n : endY - 10;\n svg += `<line x1=\"${blockX}\" y1=\"${secY}\" x2=\"${blockX + blockW}\" y2=\"${secY}\" stroke=\"${THEME.blockBorder}\" stroke-width=\"1\" stroke-dasharray=\"4 2\" />`;\n if (section.label) {\n svg += `<text x=\"${blockX + 8}\" y=\"${secY + 13}\" fill=\"${THEME.blockLabel}\" font-size=\"10\" font-family=\"${FONT_FAMILY}\" font-style=\"italic\">[${escapeXml(section.label)}]</text>`;\n }\n }\n svg += `</g>`;\n }\n\n // --- Messages ---\n for (let mi = 0; mi < messages.length; mi++) {\n const msg = messages[mi];\n const y = msgYPositions[mi];\n const fromIdx = pIndex.get(msg.from);\n const toIdx = pIndex.get(msg.to);\n if (fromIdx === undefined || toIdx === undefined) continue;\n\n const fromX = pCenters[fromIdx];\n const toX = pCenters[toIdx];\n const isSelf = fromIdx === toIdx;\n\n svg += `<g data-seq-type=\"message\" data-seq-idx=\"${mi}\">`;\n\n if (isSelf) {\n // Self-message: loop arrow to the right\n const loopW = 40;\n const loopH = 25;\n const dash = msg.solid ? '' : ` stroke-dasharray=\"6 3\"`;\n svg += `<path d=\"M ${fromX} ${y} L ${fromX + loopW} ${y} L ${fromX + loopW} ${y + loopH} L ${fromX + 4} ${y + loopH}\" fill=\"none\" stroke=\"${THEME.messageLine}\" stroke-width=\"1.5\"${dash} marker-end=\"url(#seq-arrow-open)\" />`;\n if (msg.text) {\n svg += `<text x=\"${fromX + loopW + 6}\" y=\"${y + loopH / 2 + 1}\" dominant-baseline=\"central\" fill=\"${THEME.messageText}\" font-size=\"12\" font-family=\"${FONT_FAMILY}\">${escapeXml(msg.text)}</text>`;\n }\n } else {\n const isLeft = toX < fromX;\n const lineEndX = isLeft ? toX + 4 : toX - 4;\n const dash = msg.solid ? '' : ` stroke-dasharray=\"6 3\"`;\n\n // Arrow line\n const markerId = msg.arrowHead === 'filled' ? 'seq-arrow-filled' : 'seq-arrow-open';\n\n if (msg.cross) {\n // Cross at end (lost message)\n svg += `<line x1=\"${fromX}\" y1=\"${y}\" x2=\"${lineEndX}\" y2=\"${y}\" stroke=\"${THEME.messageLine}\" stroke-width=\"1.5\"${dash} />`;\n // X mark\n const xSize = 6;\n svg += `<line x1=\"${toX - xSize}\" y1=\"${y - xSize}\" x2=\"${toX + xSize}\" y2=\"${y + xSize}\" stroke=\"${THEME.crossColor}\" stroke-width=\"2\" />`;\n svg += `<line x1=\"${toX + xSize}\" y1=\"${y - xSize}\" x2=\"${toX - xSize}\" y2=\"${y + xSize}\" stroke=\"${THEME.crossColor}\" stroke-width=\"2\" />`;\n } else {\n svg += `<line x1=\"${fromX}\" y1=\"${y}\" x2=\"${lineEndX}\" y2=\"${y}\" stroke=\"${THEME.messageLine}\" stroke-width=\"1.5\"${dash} marker-end=\"url(#${markerId})\" />`;\n }\n\n // Message text (centered above the line)\n if (msg.text) {\n const midX = (fromX + toX) / 2;\n const textContent = msg.number ? `${msg.number}. ${msg.text}` : msg.text;\n svg += `<text x=\"${midX}\" y=\"${y - 8}\" text-anchor=\"middle\" fill=\"${THEME.messageText}\" font-size=\"12\" font-family=\"${FONT_FAMILY}\">${escapeXml(textContent)}</text>`;\n }\n }\n\n svg += `</g>`;\n }\n\n // --- Notes ---\n for (const [msgIdx, noteGroup] of noteAtMsg.entries()) {\n const baseY = msgIdx < msgYPositions.length\n ? msgYPositions[msgIdx] - 15\n : (msgIdx > 0 ? msgYPositions[msgIdx - 1] + MSG_ROW_HEIGHT - 15 : topBoxBottom + 30);\n\n for (const note of noteGroup) {\n const targetIdxs = note.targets.map(t => pIndex.get(t)).filter(i => i !== undefined);\n if (targetIdxs.length === 0) continue;\n\n const fontSize = 11;\n const lineH = fontSize + 4;\n const noteH = note.lines.length * lineH + NOTE_PAD * 2;\n const noteW = Math.min(\n NOTE_MAX_W,\n Math.max(...note.lines.map(l => measureText(l, fontSize))) + NOTE_PAD * 2 + 10\n );\n\n let noteX;\n if (note.position === 'left of') {\n const px = pCenters[targetIdxs[0]];\n noteX = px - PARTICIPANT_W / 2 - noteW - 8;\n } else if (note.position === 'right of') {\n const px = pCenters[targetIdxs[0]];\n noteX = px + PARTICIPANT_W / 2 + 8;\n } else {\n // 'over' - center between targets\n if (targetIdxs.length >= 2) {\n const minP = Math.min(...targetIdxs);\n const maxP = Math.max(...targetIdxs);\n const center = (pCenters[minP] + pCenters[maxP]) / 2;\n noteX = center - noteW / 2;\n } else {\n noteX = pCenters[targetIdxs[0]] - noteW / 2;\n }\n }\n\n const noteY = baseY - noteH;\n\n svg += `<g data-seq-type=\"note\">`;\n svg += `<rect x=\"${noteX}\" y=\"${noteY}\" width=\"${noteW}\" height=\"${noteH}\" rx=\"3\" fill=\"${THEME.noteBg}\" stroke=\"${THEME.noteBorder}\" stroke-width=\"1\" />`;\n // Render wrapped text lines\n note.lines.forEach((line, li) => {\n svg += `<text x=\"${noteX + NOTE_PAD}\" y=\"${noteY + NOTE_PAD + li * lineH + fontSize}\" fill=\"${THEME.noteText}\" font-size=\"${fontSize}\" font-family=\"${FONT_FAMILY}\">${escapeXml(line)}</text>`;\n });\n svg += `</g>`;\n }\n }\n\n // Build final SVG\n const defsStr = defs.length > 0 ? `<defs>${defs.join('')}</defs>` : '';\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${totalWidth}\" height=\"${totalHeight}\" viewBox=\"0 0 ${totalWidth} ${totalHeight}\">${defsStr}${svg}</svg>`;\n}\n\n/**\n * Generate preview SVG for the modal (fixed width).\n */\nexport function renderSequencePreviewSVG(diagram) {\n return renderSequenceSVG(diagram, { width: 620 });\n}\n\n/**\n * Parse raw mermaid source and render sequence SVG.\n * Returns SVG string or empty string if not a sequence diagram.\n */\nexport function parseAndRenderSequence(src) {\n const diagram = parseSequenceDiagram(src);\n if (!diagram) return '';\n return renderSequenceSVG(diagram);\n}\n\n/**\n * Render a sequence diagram onto the canvas as a real engine `Frame`\n * containing independent shapes \u2014 top + bottom participant boxes,\n * dashed lifelines, and a real Arrow (or Line for `--x`/`-x`) per\n * message. Each child is fully independent for click / drag / resize;\n * the Frame's `_diagramType` marker makes Frame.destroy() pull the\n * children along on delete, so the diagram still behaves as one\n * logical unit when discarded.\n *\n * Issue #34 bug #3 (follow-up to #24 per-actor split): drops the shared\n * `groupId` glue so clicking one shape selects only that shape.\n *\n * Notes and block-frames (alt/opt/loop) are skipped for now \u2014 they'd\n * either need their own shape types or a richer label model. Self-\n * messages are also skipped (would need a curved arrow).\n */\nexport function renderSequenceOnCanvas(diagram) {\n if (!diagram || diagram.type !== 'sequenceDiagram') return false;\n if (!window.svg || !window.Rectangle || !window.Line || !window.Arrow) {\n console.error('[SequenceRenderer] Engine not initialized (Rectangle / Line / Arrow missing)');\n return false;\n }\n\n const participants = diagram.participants || [];\n const messages = diagram.messages || [];\n if (participants.length === 0) return false;\n\n // Mirror the layout math from renderSequenceSVG so the canvas layout\n // matches the modal preview.\n const pCount = participants.length;\n const contentWidth = (pCount - 1) * PARTICIPANT_GAP + PARTICIPANT_W;\n const totalWidth = Math.max(contentWidth + SIDE_MARGIN * 2, 400);\n const startX = (totalWidth - contentWidth) / 2;\n const pCenters = participants.map((_, i) => startX + i * PARTICIPANT_GAP + PARTICIPANT_W / 2);\n\n const topBoxBottom = TOP_MARGIN + PARTICIPANT_H;\n const msgYPositions = [];\n let currentY = topBoxBottom + 30;\n for (let mi = 0; mi < messages.length; mi++) {\n msgYPositions.push(currentY);\n currentY += MSG_ROW_HEIGHT;\n }\n const bottomBoxTop = currentY + 20;\n const totalHeight = bottomBoxTop + PARTICIPANT_H + BOTTOM_MARGIN;\n\n // Centre the diagram on the current viewport so the user sees it\n // right where they invoked the renderer.\n const vb = window.currentViewBox || { x: 0, y: 0, width: window.innerWidth, height: window.innerHeight };\n const ox = vb.x + vb.width / 2 - totalWidth / 2;\n const oy = vb.y + vb.height / 2 - totalHeight / 2;\n\n // \u2500\u2500 Wrapper frame \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Issue #34 bug #3: drop the shared groupId glue. Each child is\n // independent for click / drag / resize. The Frame's `_diagramType`\n // marker makes Frame.destroy() pull the children along on delete,\n // so the diagram still behaves as one logical unit when discarded.\n if (!window.Frame) {\n console.error('[SequenceRenderer] window.Frame missing \u2014 cannot wrap diagram');\n return false;\n }\n // Padding bumped 24 \u2192 60 so participant labels + message text near\n // the frame's edges stay inside on the new wider light canvas.\n const PADDING = 60;\n const TK = themeColors();\n const frameTitle = diagram.title || 'Sequence diagram';\n const frame = new window.Frame(\n ox - PADDING,\n oy - PADDING,\n totalWidth + PADDING * 2,\n totalHeight + PADDING * 2,\n {\n stroke: TK.blockBorder,\n strokeWidth: 1,\n fill: 'transparent',\n opacity: 0.7,\n frameName: frameTitle,\n }\n );\n frame._diagramType = 'mermaid-sequence';\n window.shapes.push(frame);\n if (window.pushCreateAction) window.pushCreateAction(frame);\n\n const created = [];\n\n // \u2500\u2500 Participants: top box + lifeline (and bottom box) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const pIndex = new Map();\n for (let pi = 0; pi < pCount; pi++) {\n const p = participants[pi];\n pIndex.set(p.name, pi);\n const cx = pCenters[pi] + ox;\n const bx = cx - PARTICIPANT_W / 2;\n\n try {\n // Top participant box\n const topBox = new window.Rectangle(bx, TOP_MARGIN + oy, PARTICIPANT_W, PARTICIPANT_H, {\n stroke: TK.participantBorder,\n strokeWidth: 1.5,\n fill: TK.participantBg,\n fillStyle: 'solid',\n roughness: 1,\n label: p.name,\n labelColor: TK.participantText,\n });\n window.shapes.push(topBox);\n if (window.pushCreateAction) window.pushCreateAction(topBox);\n frame.addShapeToFrame(topBox);\n created.push(topBox);\n\n // Lifeline (dashed vertical line spanning the diagram height)\n const lifeline = new window.Line(\n { x: cx, y: topBoxBottom + oy },\n { x: cx, y: bottomBoxTop + oy },\n {\n stroke: TK.lifeline,\n strokeWidth: 1,\n strokeDasharray: '6 4',\n roughness: 0,\n }\n );\n window.shapes.push(lifeline);\n if (window.pushCreateAction) window.pushCreateAction(lifeline);\n frame.addShapeToFrame(lifeline);\n created.push(lifeline);\n\n // Bottom participant box (mirrors top \u2014 Mermaid convention)\n const bottomBox = new window.Rectangle(bx, bottomBoxTop + oy, PARTICIPANT_W, PARTICIPANT_H, {\n stroke: TK.participantBorder,\n strokeWidth: 1.5,\n fill: TK.participantBg,\n fillStyle: 'solid',\n roughness: 1,\n label: p.name,\n labelColor: TK.participantText,\n });\n window.shapes.push(bottomBox);\n if (window.pushCreateAction) window.pushCreateAction(bottomBox);\n frame.addShapeToFrame(bottomBox);\n created.push(bottomBox);\n } catch (err) {\n console.warn('[SequenceRenderer] Participant creation failed:', p.name, err);\n }\n }\n\n // \u2500\u2500 Messages: arrow (or line for --x style) per row \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n for (let mi = 0; mi < messages.length; mi++) {\n const m = messages[mi];\n const fromI = pIndex.get(m.from);\n const toI = pIndex.get(m.to);\n if (fromI == null || toI == null) continue;\n if (fromI === toI) continue; // skip self-messages (v1 limitation)\n\n const fromCx = pCenters[fromI] + ox;\n const toCx = pCenters[toI] + ox;\n const y = msgYPositions[mi] + oy;\n\n const labelText = m.number ? `${m.number}. ${m.text}` : m.text;\n\n // Solid vs dashed (sync vs async response). `cross` style (-x)\n // would render as a line with an X at the head \u2014 fall back to a\n // line for that, arrow otherwise.\n const isCross = !!m.cross && m.arrowHead === 'cross';\n const opts = {\n stroke: TK.messageLine,\n strokeWidth: 1.5,\n roughness: 0,\n strokeDasharray: m.solid ? '' : '6 4',\n label: labelText || '',\n labelColor: TK.messageText,\n };\n\n try {\n const sp = { x: fromCx, y };\n const ep = { x: toCx, y };\n const connector = isCross\n ? new window.Line(sp, ep, opts)\n : new window.Arrow(sp, ep, opts);\n window.shapes.push(connector);\n if (window.pushCreateAction) window.pushCreateAction(connector);\n frame.addShapeToFrame(connector);\n created.push(connector);\n } catch (err) {\n console.warn('[SequenceRenderer] Message creation failed:', m, err);\n }\n }\n\n // Auto-select the first node so the user has feedback that the\n // diagram landed. Selecting a child (not the frame) reinforces the\n // \"independent shapes inside a frame\" model from issue #34 bug #3.\n const first = created[0];\n if (first) {\n window.currentShape = first;\n if (typeof first.selectShape === 'function') first.selectShape();\n }\n\n console.log(`[SequenceRenderer] Done: ${pCount} participants, ${messages.length} messages`);\n return true;\n}\n\n"],
5
- "mappings": ";;;;;;AAgBA,IAAM,gBAAgB;AACtB,IAAM,gBAAgB;AACtB,IAAM,kBAAkB;AACxB,IAAM,iBAAiB;AACvB,IAAM,WAAW;AACjB,IAAM,aAAa;AACnB,IAAM,aAAa;AACnB,IAAM,gBAAgB;AACtB,IAAM,cAAc;AACpB,IAAM,cAAc;AAQpB,SAAS,cAAc;AACnB,QAAM,SAAS,OAAO,aAAa,eAC5B,SAAS,QACT,SAAS,KAAK,UAAU,SAAS,YAAY;AACpD,MAAI,OAAQ,QAAO;AACnB,SAAO;AAAA,IACH,IAAI;AAAA,IACJ,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,iBAAiB;AAAA,IACjB,UAAU;AAAA,IACV,aAAa;AAAA,IACb,aAAa;AAAA,IACb,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,SAAS;AAAA,IACT,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,YAAY;AAAA,EAChB;AACJ;AAGA,IAAM,QAAQ;AAAA,EACV,IAAI;AAAA,EACJ,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,UAAU;AAAA,EACV,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,SAAS;AAAA,EACT,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,YAAY;AAChB;AAEA,SAAS,UAAU,KAAK;AACpB,SAAO,OAAO,GAAG,EACZ,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,QAAQ;AAC/B;AAMA,SAAS,YAAY,MAAM,UAAU;AACjC,QAAM,eAAe,WAAW;AAChC,SAAO,KAAK,SAAS;AACzB;AAKA,SAAS,SAAS,MAAM,UAAU,UAAU;AAExC,QAAM,WAAW,KAAK,MAAM,aAAa;AACzC,QAAM,QAAQ,CAAC;AACf,aAAW,WAAW,UAAU;AAC5B,UAAM,QAAQ,QAAQ,MAAM,KAAK;AACjC,QAAI,cAAc;AAClB,eAAW,QAAQ,OAAO;AACtB,YAAM,WAAW,cAAc,cAAc,MAAM,OAAO;AAC1D,UAAI,YAAY,UAAU,QAAQ,IAAI,YAAY,aAAa;AAC3D,cAAM,KAAK,WAAW;AACtB,sBAAc;AAAA,MAClB,OAAO;AACH,sBAAc;AAAA,MAClB;AAAA,IACJ;AACA,QAAI,YAAa,OAAM,KAAK,WAAW;AAAA,EAC3C;AACA,SAAO,MAAM,SAAS,IAAI,QAAQ,CAAC,EAAE;AACzC;AASO,SAAS,kBAAkB,SAAS,OAAO,CAAC,GAAG;AAClD,MAAI,CAAC,WAAW,QAAQ,SAAS,kBAAmB,QAAO;AAE3D,QAAM,eAAe,QAAQ;AAC7B,QAAM,WAAW,QAAQ;AACzB,QAAM,QAAQ,QAAQ;AACtB,QAAM,SAAS,QAAQ,UAAU,CAAC;AAElC,QAAM,SAAS,aAAa;AAC5B,MAAI,WAAW,EAAG,QAAO;AAGzB,QAAM,SAAS,oBAAI,IAAI;AACvB,eAAa,QAAQ,CAAC,GAAG,MAAM,OAAO,IAAI,EAAE,MAAM,CAAC,CAAC;AAGpD,QAAM,gBAAgB,SAAS,KAAK,kBAAkB;AACtD,QAAM,aAAa,KAAK,SAAS,KAAK,IAAI,eAAe,cAAc,GAAG,GAAG;AAC7E,QAAM,UAAU,aAAa,gBAAgB;AAG7C,QAAM,WAAW,aAAa,IAAI,CAAC,GAAG,MAAM,SAAS,IAAI,kBAAkB,gBAAgB,CAAC;AAG5F,QAAM,YAAY,oBAAI,IAAI;AAC1B,aAAW,QAAQ,OAAO;AACtB,UAAM,WAAW;AACjB,UAAM,QAAQ,SAAS,KAAK,MAAM,UAAU,aAAa,WAAW,CAAC;AACrE,UAAM,IAAI,MAAM,UAAU,WAAW,KAAK,WAAW;AACrD,QAAI,CAAC,UAAU,IAAI,KAAK,SAAS,EAAG,WAAU,IAAI,KAAK,WAAW,CAAC,CAAC;AACpE,cAAU,IAAI,KAAK,SAAS,EAAE,KAAK,EAAE,GAAG,MAAM,OAAO,QAAQ,EAAE,CAAC;AAAA,EACpE;AAGA,QAAM,eAAe,aAAa;AAClC,MAAI,WAAW,eAAe;AAE9B,QAAM,gBAAgB,CAAC;AACvB,WAAS,KAAK,GAAG,KAAK,SAAS,QAAQ,MAAM;AAEzC,UAAM,cAAc,UAAU,IAAI,EAAE;AACpC,QAAI,aAAa;AACb,YAAM,WAAW,KAAK,IAAI,GAAG,YAAY,IAAI,OAAK,EAAE,MAAM,CAAC;AAC3D,kBAAY,WAAW;AAAA,IAC3B;AACA,kBAAc,KAAK,QAAQ;AAC3B,gBAAY;AAAA,EAChB;AAGA,QAAM,iBAAiB,UAAU,IAAI,SAAS,MAAM;AACpD,MAAI,gBAAgB;AAChB,UAAM,WAAW,KAAK,IAAI,GAAG,eAAe,IAAI,OAAK,EAAE,MAAM,CAAC;AAC9D,gBAAY,WAAW;AAAA,EAC3B;AAEA,QAAM,eAAe,WAAW;AAChC,QAAM,cAAc,eAAe,gBAAgB;AAGnD,MAAI,MAAM;AACV,QAAM,OAAO,CAAC;AAGd,OAAK,KAAK;AAAA,6DAC+C,MAAM,WAAW;AAAA,cAChE;AACV,OAAK,KAAK;AAAA,8CACgC,MAAM,WAAW;AAAA,cACjD;AAGV,SAAO,4BAA4B,UAAU,aAAa,WAAW,WAAW,MAAM,EAAE;AAGxF,MAAI,QAAQ,OAAO;AACf,WAAO,YAAY,aAAa,CAAC,QAAQ,aAAa,CAAC,gCAAgC,MAAM,eAAe,iCAAiC,WAAW,uBAAuB,UAAU,QAAQ,KAAK,CAAC;AAAA,EAC3M;AAGA,WAAS,KAAK,GAAG,KAAK,QAAQ,MAAM;AAChC,UAAM,KAAK,SAAS,EAAE;AACtB,WAAO,aAAa,EAAE,SAAS,YAAY,SAAS,EAAE,SAAS,YAAY,aAAa,MAAM,QAAQ;AAAA,EAC1G;AAGA,WAAS,KAAK,GAAG,KAAK,QAAQ,MAAM;AAChC,UAAM,KAAK,SAAS,EAAE;AACtB,UAAM,KAAK,KAAK,gBAAgB;AAChC,UAAM,KAAK;AACX,WAAO,+CAA+C,UAAU,aAAa,EAAE,EAAE,IAAI,CAAC;AACtF,WAAO,YAAY,EAAE,QAAQ,EAAE,YAAY,aAAa,aAAa,aAAa,kBAAkB,MAAM,aAAa,aAAa,MAAM,iBAAiB;AAC3J,WAAO,YAAY,EAAE,QAAQ,KAAK,gBAAgB,IAAI,CAAC,4DAA4D,MAAM,eAAe,iCAAiC,WAAW,KAAK,UAAU,aAAa,EAAE,EAAE,IAAI,CAAC;AACzN,WAAO;AAAA,EACX;AAGA,WAAS,KAAK,GAAG,KAAK,QAAQ,MAAM;AAChC,UAAM,KAAK,SAAS,EAAE;AACtB,UAAM,KAAK,KAAK,gBAAgB;AAChC,UAAM,KAAK;AACX,WAAO,+CAA+C,UAAU,aAAa,EAAE,EAAE,IAAI,CAAC;AACtF,WAAO,YAAY,EAAE,QAAQ,EAAE,YAAY,aAAa,aAAa,aAAa,kBAAkB,MAAM,aAAa,aAAa,MAAM,iBAAiB;AAC3J,WAAO,YAAY,EAAE,QAAQ,KAAK,gBAAgB,IAAI,CAAC,4DAA4D,MAAM,eAAe,iCAAiC,WAAW,KAAK,UAAU,aAAa,EAAE,EAAE,IAAI,CAAC;AACzN,WAAO;AAAA,EACX;AAGA,aAAW,SAAS,QAAQ;AACxB,UAAM,SAAS,MAAM,WAAW,cAAc,SACxC,cAAc,MAAM,QAAQ,IAAI,KAChC,eAAe;AACrB,UAAM,OAAO,MAAM,UAAU,cAAc,SACpC,MAAM,SAAS,cAAc,SAAS,cAAc,MAAM,MAAM,IAAI,KAAK,WAC1E;AAEN,UAAM,SAAS,SAAS;AACxB,UAAM,SAAS,eAAe;AAE9B,WAAO,6CAA6C,MAAM,IAAI;AAC9D,WAAO,YAAY,MAAM,QAAQ,MAAM,YAAY,MAAM,aAAa,OAAO,MAAM,kBAAkB,MAAM,OAAO,aAAa,MAAM,WAAW;AAEhJ,WAAO,YAAY,MAAM,QAAQ,MAAM,YAAY,YAAY,MAAM,MAAM,EAAE,IAAI,EAAE,8BAA8B,MAAM,WAAW;AAClI,WAAO,YAAY,SAAS,CAAC,QAAQ,SAAS,EAAE,WAAW,MAAM,EAAE,iCAAiC,WAAW,uBAAuB,UAAU,MAAM,IAAI,CAAC;AAE3J,QAAI,MAAM,OAAO;AACb,aAAO,YAAY,SAAS,YAAY,MAAM,MAAM,EAAE,IAAI,EAAE,QAAQ,SAAS,EAAE,WAAW,MAAM,UAAU,iCAAiC,WAAW,0BAA0B,UAAU,MAAM,KAAK,CAAC;AAAA,IAC1M;AAGA,aAAS,KAAK,GAAG,KAAK,MAAM,SAAS,QAAQ,MAAM;AAC/C,YAAM,UAAU,MAAM,SAAS,EAAE;AACjC,YAAM,OAAO,QAAQ,WAAW,cAAc,SACxC,cAAc,QAAQ,QAAQ,IAAI,KAClC,OAAO;AACb,aAAO,aAAa,MAAM,SAAS,IAAI,SAAS,SAAS,MAAM,SAAS,IAAI,aAAa,MAAM,WAAW;AAC1G,UAAI,QAAQ,OAAO;AACf,eAAO,YAAY,SAAS,CAAC,QAAQ,OAAO,EAAE,WAAW,MAAM,UAAU,iCAAiC,WAAW,0BAA0B,UAAU,QAAQ,KAAK,CAAC;AAAA,MAC3K;AAAA,IACJ;AACA,WAAO;AAAA,EACX;AAGA,WAAS,KAAK,GAAG,KAAK,SAAS,QAAQ,MAAM;AACzC,UAAM,MAAM,SAAS,EAAE;AACvB,UAAM,IAAI,cAAc,EAAE;AAC1B,UAAM,UAAU,OAAO,IAAI,IAAI,IAAI;AACnC,UAAM,QAAQ,OAAO,IAAI,IAAI,EAAE;AAC/B,QAAI,YAAY,UAAa,UAAU,OAAW;AAElD,UAAM,QAAQ,SAAS,OAAO;AAC9B,UAAM,MAAM,SAAS,KAAK;AAC1B,UAAM,SAAS,YAAY;AAE3B,WAAO,4CAA4C,EAAE;AAErD,QAAI,QAAQ;AAER,YAAM,QAAQ;AACd,YAAM,QAAQ;AACd,YAAM,OAAO,IAAI,QAAQ,KAAK;AAC9B,aAAO,cAAc,KAAK,IAAI,CAAC,MAAM,QAAQ,KAAK,IAAI,CAAC,MAAM,QAAQ,KAAK,IAAI,IAAI,KAAK,MAAM,QAAQ,CAAC,IAAI,IAAI,KAAK,yBAAyB,MAAM,WAAW,uBAAuB,IAAI;AACxL,UAAI,IAAI,MAAM;AACV,eAAO,YAAY,QAAQ,QAAQ,CAAC,QAAQ,IAAI,QAAQ,IAAI,CAAC,uCAAuC,MAAM,WAAW,iCAAiC,WAAW,KAAK,UAAU,IAAI,IAAI,CAAC;AAAA,MAC7L;AAAA,IACJ,OAAO;AACH,YAAM,SAAS,MAAM;AACrB,YAAM,WAAW,SAAS,MAAM,IAAI,MAAM;AAC1C,YAAM,OAAO,IAAI,QAAQ,KAAK;AAG9B,YAAM,WAAW,IAAI,cAAc,WAAW,qBAAqB;AAEnE,UAAI,IAAI,OAAO;AAEX,eAAO,aAAa,KAAK,SAAS,CAAC,SAAS,QAAQ,SAAS,CAAC,aAAa,MAAM,WAAW,uBAAuB,IAAI;AAEvH,cAAM,QAAQ;AACd,eAAO,aAAa,MAAM,KAAK,SAAS,IAAI,KAAK,SAAS,MAAM,KAAK,SAAS,IAAI,KAAK,aAAa,MAAM,UAAU;AACpH,eAAO,aAAa,MAAM,KAAK,SAAS,IAAI,KAAK,SAAS,MAAM,KAAK,SAAS,IAAI,KAAK,aAAa,MAAM,UAAU;AAAA,MACxH,OAAO;AACH,eAAO,aAAa,KAAK,SAAS,CAAC,SAAS,QAAQ,SAAS,CAAC,aAAa,MAAM,WAAW,uBAAuB,IAAI,qBAAqB,QAAQ;AAAA,MACxJ;AAGA,UAAI,IAAI,MAAM;AACV,cAAM,QAAQ,QAAQ,OAAO;AAC7B,cAAM,cAAc,IAAI,SAAS,GAAG,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,IAAI;AACpE,eAAO,YAAY,IAAI,QAAQ,IAAI,CAAC,gCAAgC,MAAM,WAAW,iCAAiC,WAAW,KAAK,UAAU,WAAW,CAAC;AAAA,MAChK;AAAA,IACJ;AAEA,WAAO;AAAA,EACX;AAGA,aAAW,CAAC,QAAQ,SAAS,KAAK,UAAU,QAAQ,GAAG;AACnD,UAAM,QAAQ,SAAS,cAAc,SAC/B,cAAc,MAAM,IAAI,KACvB,SAAS,IAAI,cAAc,SAAS,CAAC,IAAI,iBAAiB,KAAK,eAAe;AAErF,eAAW,QAAQ,WAAW;AAC1B,YAAM,aAAa,KAAK,QAAQ,IAAI,OAAK,OAAO,IAAI,CAAC,CAAC,EAAE,OAAO,OAAK,MAAM,MAAS;AACnF,UAAI,WAAW,WAAW,EAAG;AAE7B,YAAM,WAAW;AACjB,YAAM,QAAQ,WAAW;AACzB,YAAM,QAAQ,KAAK,MAAM,SAAS,QAAQ,WAAW;AACrD,YAAM,QAAQ,KAAK;AAAA,QACf;AAAA,QACA,KAAK,IAAI,GAAG,KAAK,MAAM,IAAI,OAAK,YAAY,GAAG,QAAQ,CAAC,CAAC,IAAI,WAAW,IAAI;AAAA,MAChF;AAEA,UAAI;AACJ,UAAI,KAAK,aAAa,WAAW;AAC7B,cAAM,KAAK,SAAS,WAAW,CAAC,CAAC;AACjC,gBAAQ,KAAK,gBAAgB,IAAI,QAAQ;AAAA,MAC7C,WAAW,KAAK,aAAa,YAAY;AACrC,cAAM,KAAK,SAAS,WAAW,CAAC,CAAC;AACjC,gBAAQ,KAAK,gBAAgB,IAAI;AAAA,MACrC,OAAO;AAEH,YAAI,WAAW,UAAU,GAAG;AACxB,gBAAM,OAAO,KAAK,IAAI,GAAG,UAAU;AACnC,gBAAM,OAAO,KAAK,IAAI,GAAG,UAAU;AACnC,gBAAM,UAAU,SAAS,IAAI,IAAI,SAAS,IAAI,KAAK;AACnD,kBAAQ,SAAS,QAAQ;AAAA,QAC7B,OAAO;AACH,kBAAQ,SAAS,WAAW,CAAC,CAAC,IAAI,QAAQ;AAAA,QAC9C;AAAA,MACJ;AAEA,YAAM,QAAQ,QAAQ;AAEtB,aAAO;AACP,aAAO,YAAY,KAAK,QAAQ,KAAK,YAAY,KAAK,aAAa,KAAK,kBAAkB,MAAM,MAAM,aAAa,MAAM,UAAU;AAEnI,WAAK,MAAM,QAAQ,CAAC,MAAM,OAAO;AAC7B,eAAO,YAAY,QAAQ,QAAQ,QAAQ,QAAQ,WAAW,KAAK,QAAQ,QAAQ,WAAW,MAAM,QAAQ,gBAAgB,QAAQ,kBAAkB,WAAW,KAAK,UAAU,IAAI,CAAC;AAAA,MACzL,CAAC;AACD,aAAO;AAAA,IACX;AAAA,EACJ;AAGA,QAAM,UAAU,KAAK,SAAS,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC,YAAY;AACpE,SAAO,kDAAkD,UAAU,aAAa,WAAW,kBAAkB,UAAU,IAAI,WAAW,KAAK,OAAO,GAAG,GAAG;AAC5J;AAKO,SAAS,yBAAyB,SAAS;AAC9C,SAAO,kBAAkB,SAAS,EAAE,OAAO,IAAI,CAAC;AACpD;AAMO,SAAS,uBAAuB,KAAK;AACxC,QAAM,UAAU,qBAAqB,GAAG;AACxC,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,kBAAkB,OAAO;AACpC;AAkBO,SAAS,uBAAuB,SAAS;AAC5C,MAAI,CAAC,WAAW,QAAQ,SAAS,kBAAmB,QAAO;AAC3D,MAAI,CAAC,OAAO,OAAO,CAAC,OAAO,aAAa,CAAC,OAAO,QAAQ,CAAC,OAAO,OAAO;AACnE,YAAQ,MAAM,8EAA8E;AAC5F,WAAO;AAAA,EACX;AAEA,QAAM,eAAe,QAAQ,gBAAgB,CAAC;AAC9C,QAAM,WAAW,QAAQ,YAAY,CAAC;AACtC,MAAI,aAAa,WAAW,EAAG,QAAO;AAItC,QAAM,SAAS,aAAa;AAC5B,QAAM,gBAAgB,SAAS,KAAK,kBAAkB;AACtD,QAAM,aAAa,KAAK,IAAI,eAAe,cAAc,GAAG,GAAG;AAC/D,QAAM,UAAU,aAAa,gBAAgB;AAC7C,QAAM,WAAW,aAAa,IAAI,CAAC,GAAG,MAAM,SAAS,IAAI,kBAAkB,gBAAgB,CAAC;AAE5F,QAAM,eAAe,aAAa;AAClC,QAAM,gBAAgB,CAAC;AACvB,MAAI,WAAW,eAAe;AAC9B,WAAS,KAAK,GAAG,KAAK,SAAS,QAAQ,MAAM;AACzC,kBAAc,KAAK,QAAQ;AAC3B,gBAAY;AAAA,EAChB;AACA,QAAM,eAAe,WAAW;AAChC,QAAM,cAAc,eAAe,gBAAgB;AAInD,QAAM,KAAK,OAAO,kBAAkB,EAAE,GAAG,GAAG,GAAG,GAAG,OAAO,OAAO,YAAY,QAAQ,OAAO,YAAY;AACvG,QAAM,KAAK,GAAG,IAAI,GAAG,QAAQ,IAAI,aAAa;AAC9C,QAAM,KAAK,GAAG,IAAI,GAAG,SAAS,IAAI,cAAc;AAOhD,MAAI,CAAC,OAAO,OAAO;AACf,YAAQ,MAAM,oEAA+D;AAC7E,WAAO;AAAA,EACX;AAGA,QAAM,UAAU;AAChB,QAAM,KAAK,YAAY;AACvB,QAAM,aAAa,QAAQ,SAAS;AACpC,QAAM,QAAQ,IAAI,OAAO;AAAA,IACrB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,aAAa,UAAU;AAAA,IACvB,cAAc,UAAU;AAAA,IACxB;AAAA,MACI,QAAQ,GAAG;AAAA,MACX,aAAa;AAAA,MACb,MAAM;AAAA,MACN,SAAS;AAAA,MACT,WAAW;AAAA,IACf;AAAA,EACJ;AACA,QAAM,eAAe;AACrB,SAAO,OAAO,KAAK,KAAK;AACxB,MAAI,OAAO,iBAAkB,QAAO,iBAAiB,KAAK;AAE1D,QAAM,UAAU,CAAC;AAGjB,QAAM,SAAS,oBAAI,IAAI;AACvB,WAAS,KAAK,GAAG,KAAK,QAAQ,MAAM;AAChC,UAAM,IAAI,aAAa,EAAE;AACzB,WAAO,IAAI,EAAE,MAAM,EAAE;AACrB,UAAM,KAAK,SAAS,EAAE,IAAI;AAC1B,UAAM,KAAK,KAAK,gBAAgB;AAEhC,QAAI;AAEA,YAAM,SAAS,IAAI,OAAO,UAAU,IAAI,aAAa,IAAI,eAAe,eAAe;AAAA,QACnF,QAAQ,GAAG;AAAA,QACX,aAAa;AAAA,QACb,MAAM,GAAG;AAAA,QACT,WAAW;AAAA,QACX,WAAW;AAAA,QACX,OAAO,EAAE;AAAA,QACT,YAAY,GAAG;AAAA,MACnB,CAAC;AACD,aAAO,OAAO,KAAK,MAAM;AACzB,UAAI,OAAO,iBAAkB,QAAO,iBAAiB,MAAM;AAC3D,YAAM,gBAAgB,MAAM;AAC5B,cAAQ,KAAK,MAAM;AAGnB,YAAM,WAAW,IAAI,OAAO;AAAA,QACxB,EAAE,GAAG,IAAI,GAAG,eAAe,GAAG;AAAA,QAC9B,EAAE,GAAG,IAAI,GAAG,eAAe,GAAG;AAAA,QAC9B;AAAA,UACI,QAAQ,GAAG;AAAA,UACX,aAAa;AAAA,UACb,iBAAiB;AAAA,UACjB,WAAW;AAAA,QACf;AAAA,MACJ;AACA,aAAO,OAAO,KAAK,QAAQ;AAC3B,UAAI,OAAO,iBAAkB,QAAO,iBAAiB,QAAQ;AAC7D,YAAM,gBAAgB,QAAQ;AAC9B,cAAQ,KAAK,QAAQ;AAGrB,YAAM,YAAY,IAAI,OAAO,UAAU,IAAI,eAAe,IAAI,eAAe,eAAe;AAAA,QACxF,QAAQ,GAAG;AAAA,QACX,aAAa;AAAA,QACb,MAAM,GAAG;AAAA,QACT,WAAW;AAAA,QACX,WAAW;AAAA,QACX,OAAO,EAAE;AAAA,QACT,YAAY,GAAG;AAAA,MACnB,CAAC;AACD,aAAO,OAAO,KAAK,SAAS;AAC5B,UAAI,OAAO,iBAAkB,QAAO,iBAAiB,SAAS;AAC9D,YAAM,gBAAgB,SAAS;AAC/B,cAAQ,KAAK,SAAS;AAAA,IAC1B,SAAS,KAAK;AACV,cAAQ,KAAK,mDAAmD,EAAE,MAAM,GAAG;AAAA,IAC/E;AAAA,EACJ;AAGA,WAAS,KAAK,GAAG,KAAK,SAAS,QAAQ,MAAM;AACzC,UAAM,IAAI,SAAS,EAAE;AACrB,UAAM,QAAQ,OAAO,IAAI,EAAE,IAAI;AAC/B,UAAM,MAAM,OAAO,IAAI,EAAE,EAAE;AAC3B,QAAI,SAAS,QAAQ,OAAO,KAAM;AAClC,QAAI,UAAU,IAAK;AAEnB,UAAM,SAAS,SAAS,KAAK,IAAI;AACjC,UAAM,OAAO,SAAS,GAAG,IAAI;AAC7B,UAAM,IAAI,cAAc,EAAE,IAAI;AAE9B,UAAM,YAAY,EAAE,SAAS,GAAG,EAAE,MAAM,KAAK,EAAE,IAAI,KAAK,EAAE;AAK1D,UAAM,UAAU,CAAC,CAAC,EAAE,SAAS,EAAE,cAAc;AAC7C,UAAM,OAAO;AAAA,MACT,QAAQ,GAAG;AAAA,MACX,aAAa;AAAA,MACb,WAAW;AAAA,MACX,iBAAiB,EAAE,QAAQ,KAAK;AAAA,MAChC,OAAO,aAAa;AAAA,MACpB,YAAY,GAAG;AAAA,IACnB;AAEA,QAAI;AACA,YAAM,KAAK,EAAE,GAAG,QAAQ,EAAE;AAC1B,YAAM,KAAK,EAAE,GAAG,MAAM,EAAE;AACxB,YAAM,YAAY,UACZ,IAAI,OAAO,KAAK,IAAI,IAAI,IAAI,IAC5B,IAAI,OAAO,MAAM,IAAI,IAAI,IAAI;AACnC,aAAO,OAAO,KAAK,SAAS;AAC5B,UAAI,OAAO,iBAAkB,QAAO,iBAAiB,SAAS;AAC9D,YAAM,gBAAgB,SAAS;AAC/B,cAAQ,KAAK,SAAS;AAAA,IAC1B,SAAS,KAAK;AACV,cAAQ,KAAK,+CAA+C,GAAG,GAAG;AAAA,IACtE;AAAA,EACJ;AAKA,QAAM,QAAQ,QAAQ,CAAC;AACvB,MAAI,OAAO;AACP,WAAO,eAAe;AACtB,QAAI,OAAO,MAAM,gBAAgB,WAAY,OAAM,YAAY;AAAA,EACnE;AAEA,UAAQ,IAAI,4BAA4B,MAAM,kBAAkB,SAAS,MAAM,WAAW;AAC1F,SAAO;AACX;",
6
- "names": []
7
- }