@kekonic/diagrams 1.0.0-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +92 -0
- package/dist/index.d.mts +173 -0
- package/dist/index.mjs +1642 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +67 -0
- package/theme.css +373 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["applyCrossingTreatment","parse","compile","measureGraph","analyzeDiagramTopology","merge","layoutAndRouteWithElk","ELK_ROUTER_ALGORITHM","ELK_LAYOUT_ALGORITHM","mergePresentationOptions","resolvePresentation","preloadIcons","collectIconIds","renderSvg","#catalog","#current","#playing","#timeMs","#durationMs","#loop","#speed","#listeners","#teardownVisuals","#svg","#graph","#rebuildCatalog","#timed","#notify","#select","#applyAt","#lastTick","#armRaf","#cancelRaf","#clearEmphasis","inferAutoAnimation","#raf","#tick","#flowLayer","#nodeEls","#emphasizeEdgeId","#edgeEls","#emphasizeEdgeLabels","#applySequenceChrome","#paintFlows","#edgeElsById","#diagramContent","#paintFlowOnto","#edgePathDs","#edgeStroke","STATEMENT_KEYWORDS","EDGE_OPS","BUILTIN_KIND_CATALOG","BUILTIN_SHAPE_IDS","listBuiltinIconIds","listDefaultCollections","ELK_LAYOUT_ALGORITHM","ELK_ROUTER_ALGORITHM","formatSource","getThemeTokens","THEME_CSS"],"sources":["../src/pipeline/finalize-edges.ts","../src/quality.ts","../src/pipeline/render.ts","../src/animation/player.ts","../src/capabilities.ts","../src/index.ts"],"sourcesContent":["import type { GraphModel, Point, Rect, RoutingOptions } from \"@kekonic/diagrams-core\";\nimport { isPureCardinalityLabel, rectsOverlap } from \"@kekonic/diagrams-core\";\nimport {\n type LayoutResult,\n type LayoutEdgePath,\n snapErdEdgeEndpoints,\n defaultMeasurer,\n DEFAULT_FONT_FAMILY,\n type TextMeasurer,\n} from \"@kekonic/diagrams-layout\";\nimport {\n applyCrossingTreatment,\n detectCrossingPoints,\n trimEdgeEndpoints,\n ARROW_ENDPOINT_INSET,\n CARDINALITY_ENDPOINT_INSET,\n EDGE_ENDPOINT_INSET,\n type EdgeLabelPlacement,\n type TreatedEdge,\n type RoutedEdge,\n EDGE_LABEL_ICON,\n EDGE_LABEL_ICON_GAP,\n EDGE_LABEL_PAD_X,\n} from \"@kekonic/diagrams-routing\";\n\nexport type FinalizeElkEdgesInput = {\n graph: GraphModel;\n layout: LayoutResult;\n edgePaths: LayoutEdgePath[];\n routingOpts: RoutingOptions;\n measurer?: TextMeasurer;\n};\n\nexport type FinalizeElkEdgesResult = {\n labels: EdgeLabelPlacement[];\n treatedEdges: TreatedEdge[];\n routingEdges: RoutedEdge[];\n};\n\n/** Match `.flow-edge-label-text` theme (11px / 700). */\nconst EDGE_LABEL_FONT = {\n fontSize: 11,\n fontFamily: DEFAULT_FONT_FAMILY,\n fontWeight: \"700\",\n} as const;\n\nconst EDGE_LABEL_PAD_Y = 5;\n/** Prefer anchors this far from path ends / arrowheads. */\nconst ENDPOINT_SOFT_CLEARANCE = 36;\n/** Prefer anchors this far from polyline bends. */\nconst BEND_SOFT_CLEARANCE = 28;\n/** Prefer anchors this far from edge crossings. */\nconst CROSSING_SOFT_CLEARANCE = 24;\n\nfunction pathsToRouted(paths: LayoutEdgePath[]): RoutedEdge[] {\n return paths.map((path) => {\n const points = path.points;\n const segments: Array<{ from: Point; to: Point }> = [];\n for (let i = 0; i < points.length - 1; i++) {\n segments.push({ from: points[i]!, to: points[i + 1]! });\n }\n return { edgeId: path.edgeId, points, segments };\n });\n}\n\nfunction measureLabelSize(\n text: string,\n hasIcon: boolean,\n measurer: TextMeasurer,\n): { width: number; height: number } {\n const metrics =\n text.length > 0\n ? measurer.measureText(text, EDGE_LABEL_FONT)\n : { width: 0, height: EDGE_LABEL_FONT.fontSize * 1.2 };\n const iconGutter = hasIcon ? EDGE_LABEL_ICON + (text.length > 0 ? EDGE_LABEL_ICON_GAP : 0) : 0;\n const min = hasIcon && text.length === 0 ? 22 : 28;\n const width = Math.max(min, metrics.width + iconGutter + EDGE_LABEL_PAD_X * 2);\n const height = Math.max(18, Math.ceil(metrics.height) + EDGE_LABEL_PAD_Y * 2);\n return { width, height };\n}\n\nexport { EDGE_LABEL_ICON, EDGE_LABEL_ICON_GAP, EDGE_LABEL_PAD_X };\n\nfunction overlapArea(a: Rect, b: Rect): number {\n const x0 = Math.max(a.x, b.x);\n const y0 = Math.max(a.y, b.y);\n const x1 = Math.min(a.x + a.width, b.x + b.width);\n const y1 = Math.min(a.y + a.height, b.y + b.height);\n if (x1 <= x0 || y1 <= y0) return 0;\n return (x1 - x0) * (y1 - y0);\n}\n\nfunction distPoint(a: Point, b: Point): number {\n return Math.hypot(a.x - b.x, a.y - b.y);\n}\n\nfunction distPointToRect(p: Point, r: Rect): number {\n const cx = Math.min(Math.max(p.x, r.x), r.x + r.width);\n const cy = Math.min(Math.max(p.y, r.y), r.y + r.height);\n return distPoint(p, { x: cx, y: cy });\n}\n\nfunction pathLength(points: Point[]): number {\n let len = 0;\n for (let i = 1; i < points.length; i++) {\n const a = points[i - 1]!;\n const b = points[i]!;\n len += Math.abs(b.x - a.x) + Math.abs(b.y - a.y);\n }\n return len;\n}\n\n/** Nearest point on an orthogonal polyline to `p`. */\nfunction nearestOnPath(points: Point[], p: Point): Point {\n let best = points[0] ?? p;\n let bestD = Infinity;\n for (let i = 0; i < points.length - 1; i++) {\n const a = points[i]!;\n const b = points[i + 1]!;\n let q: Point;\n if (Math.abs(a.x - b.x) < 0.5) {\n const y = Math.min(Math.max(p.y, Math.min(a.y, b.y)), Math.max(a.y, b.y));\n q = { x: a.x, y };\n } else if (Math.abs(a.y - b.y) < 0.5) {\n const x = Math.min(Math.max(p.x, Math.min(a.x, b.x)), Math.max(a.x, b.x));\n q = { x, y: a.y };\n } else {\n const x = Math.min(Math.max(p.x, Math.min(a.x, b.x)), Math.max(a.x, b.x));\n const y = Math.min(Math.max(p.y, Math.min(a.y, b.y)), Math.max(a.y, b.y));\n q = { x, y };\n }\n const d = distPoint(p, q);\n if (d < bestD) {\n bestD = d;\n best = q;\n }\n }\n return best;\n}\n\n/** Gap between label pill and the stroke — keep pills hugging the path. */\nfunction pathClearance(bounds: Rect, points: Point[]): number {\n const cx = bounds.x + bounds.width / 2;\n const cy = bounds.y + bounds.height / 2;\n const onPath = nearestOnPath(points, { x: cx, y: cy });\n const clamped = {\n x: Math.min(Math.max(onPath.x, bounds.x), bounds.x + bounds.width),\n y: Math.min(Math.max(onPath.y, bounds.y), bounds.y + bounds.height),\n };\n return distPoint(onPath, clamped);\n}\n\nfunction scoreLabelCandidate(\n bounds: Rect,\n anchor: Point,\n obstacles: Rect[],\n points: Point[],\n crossings: Point[],\n alongFrac: number,\n position: \"start\" | \"middle\" | \"end\" | undefined,\n authoredPosition: boolean,\n): number {\n let score = 0;\n for (const obs of obstacles) {\n const area = overlapArea(bounds, obs);\n if (area > 0) score += area * 10;\n else if (rectsOverlap(bounds, obs, 4)) score += 4;\n }\n\n if (points.length >= 2) {\n const start = points[0]!;\n const end = points[points.length - 1]!;\n const dStart = distPoint(anchor, start);\n const dEnd = distPoint(anchor, end);\n if (dStart < ENDPOINT_SOFT_CLEARANCE) score += (ENDPOINT_SOFT_CLEARANCE - dStart) * 2;\n if (dEnd < ENDPOINT_SOFT_CLEARANCE) score += (ENDPOINT_SOFT_CLEARANCE - dEnd) * 2;\n\n for (let i = 1; i < points.length - 1; i++) {\n const d = distPoint(anchor, points[i]!);\n if (d < BEND_SOFT_CLEARANCE) score += (BEND_SOFT_CLEARANCE - d) * 1.5;\n }\n }\n\n for (const c of crossings) {\n const d = distPointToRect(c, bounds);\n if (d < CROSSING_SOFT_CLEARANCE) score += (CROSSING_SOFT_CLEARANCE - d) * 3;\n }\n\n // Bias along the whole polyline (not just the longest segment). Default is a\n // mild middle preference; authored labelPosition uses a stronger weight.\n const preferred = position === \"start\" ? 0.22 : position === \"end\" ? 0.78 : 0.5;\n const total = Math.max(1, pathLength(points));\n const weight = authoredPosition ? 3.4 : 0.55;\n score += Math.abs(alongFrac - preferred) * total * weight;\n\n // Prefer pills that sit beside the stroke — floating gutter parks score poorly.\n const clearance = pathClearance(bounds, points);\n if (clearance > 2) score += (clearance - 2) * 6;\n\n return score;\n}\n\nexport type PlaceEdgeLabelOptions = {\n hasIcon?: boolean;\n measurer?: TextMeasurer;\n crossings?: Point[];\n /** Along-path preference (`start` | `middle` | `end`). Default soft-middle. */\n position?: \"start\" | \"middle\" | \"end\";\n /** True when `position` came from authored DSL (stronger bias). */\n authoredPosition?: boolean;\n};\n\n/**\n * Place an edge label near a free path segment, preferring positions that miss\n * node cards, corners, endpoints/arrowheads, and crossings.\n */\nexport function placeEdgeLabel(\n edgeId: string,\n text: string,\n points: Point[],\n obstacles: Rect[],\n endpoints: Rect[] = [],\n options: PlaceEdgeLabelOptions = {},\n): EdgeLabelPlacement {\n const measurer = options.measurer ?? defaultMeasurer;\n const crossings = options.crossings ?? [];\n const position = options.position ?? \"middle\";\n const authoredPosition = options.authoredPosition === true;\n const { width: w, height: h } = measureLabelSize(text, options.hasIcon === true, measurer);\n const midFallback = points[Math.floor(points.length / 2)] ?? { x: 0, y: 0 };\n const totalLen = Math.max(1, pathLength(points));\n\n type Candidate = { anchor: Point; bounds: Rect; score: number; length: number };\n const candidates: Candidate[] = [];\n\n const pushCandidate = (anchor: Point, bounds: Rect, length: number, alongFrac: number) => {\n candidates.push({\n anchor,\n bounds,\n score: scoreLabelCandidate(\n bounds,\n anchor,\n obstacles,\n points,\n crossings,\n alongFrac,\n position,\n authoredPosition,\n ),\n length,\n });\n };\n\n let walked = 0;\n // Keep the pill snug beside the stroke (was 8–12px + diagonal parks).\n const GAP = 4;\n for (let i = 0; i < points.length - 1; i++) {\n const a = points[i]!;\n const b = points[i + 1]!;\n const length = Math.abs(a.x - b.x) + Math.abs(a.y - b.y);\n const fracs = length > 40 ? [0.2, 0.35, 0.5, 0.65, 0.8] : [0.5];\n for (const t of fracs) {\n const anchor = { x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t };\n const alongFrac = (walked + t * length) / totalLen;\n const vertical = Math.abs(a.x - b.x) < 0.5;\n const offsets = vertical\n ? [\n { dx: GAP, dy: -h / 2 },\n { dx: -w - GAP, dy: -h / 2 },\n { dx: GAP, dy: -h - GAP },\n { dx: -w - GAP, dy: -h - GAP },\n { dx: GAP, dy: GAP },\n { dx: -w - GAP, dy: GAP },\n ]\n : [\n { dx: -w / 2, dy: -h - GAP },\n { dx: -w / 2, dy: GAP },\n { dx: -w / 2, dy: -h / 2 },\n { dx: -w - GAP, dy: -h / 2 },\n { dx: GAP, dy: -h / 2 },\n ];\n for (const { dx, dy } of offsets) {\n pushCandidate(\n anchor,\n { x: anchor.x + dx, y: anchor.y + dy, width: w, height: h },\n length,\n alongFrac,\n );\n }\n }\n walked += length;\n }\n\n // Last resort when the corridor is crushed — park beside a path point, not in\n // the empty AABB middle of a long cross-column hop.\n const cluster = endpoints.length ? endpoints : obstacles;\n if (cluster.length && points.length >= 2) {\n const midFrac = position === \"start\" ? 0.22 : position === \"end\" ? 0.78 : 0.5;\n let along = 0;\n const target = midFrac * totalLen;\n let parkOn = points[0]!;\n for (let i = 0; i < points.length - 1; i++) {\n const a = points[i]!;\n const b = points[i + 1]!;\n const seg = Math.abs(a.x - b.x) + Math.abs(a.y - b.y);\n if (along + seg >= target || i === points.length - 2) {\n const t = seg > 0 ? Math.min(1, Math.max(0, (target - along) / seg)) : 0.5;\n parkOn = { x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t };\n break;\n }\n along += seg;\n }\n const top = Math.min(...cluster.map((o) => o.y));\n const bottom = Math.max(...cluster.map((o) => o.y + o.height));\n pushCandidate(\n parkOn,\n { x: parkOn.x - w / 2, y: top - h - GAP, width: w, height: h },\n 1,\n midFrac,\n );\n pushCandidate(\n parkOn,\n { x: parkOn.x - w / 2, y: bottom + GAP, width: w, height: h },\n 1,\n midFrac,\n );\n pushCandidate(\n parkOn,\n { x: parkOn.x + GAP, y: parkOn.y - h / 2, width: w, height: h },\n 1,\n midFrac,\n );\n pushCandidate(\n parkOn,\n { x: parkOn.x - w - GAP, y: parkOn.y - h / 2, width: w, height: h },\n 1,\n midFrac,\n );\n }\n\n candidates.sort((c, d) => c.score - d.score || d.length - c.length);\n const best = candidates[0];\n if (best) {\n // Anchor on the stroke nearest the pill so render can draw a short leader.\n const anchor = nearestOnPath(points, {\n x: best.bounds.x + best.bounds.width / 2,\n y: best.bounds.y + best.bounds.height / 2,\n });\n return { edgeId, text, bounds: best.bounds, anchor };\n }\n\n return {\n edgeId,\n text,\n bounds: { x: midFallback.x - w / 2, y: midFallback.y - h - 6, width: w, height: h },\n anchor: midFallback,\n };\n}\n\n/** ELK labels + ERD column snap + marker inset (silhouette attach already ran in layout). */\nexport function finalizeElkEdges(input: FinalizeElkEdgesInput): FinalizeElkEdgesResult {\n const { graph, layout, edgePaths, routingOpts } = input;\n\n // Sequence messages are already laid out; skip ELK crossing polish / ERD snap.\n if (graph.diagramKind === \"sequence\" || layout.sequence) {\n const routingEdges = pathsToRouted(edgePaths);\n const treatedEdges: TreatedEdge[] = routingEdges.map((e) => ({\n edgeId: e.edgeId,\n segments: e.segments.map((s) => ({ type: \"line\" as const, from: s.from, to: s.to })),\n }));\n const labels: EdgeLabelPlacement[] = (layout.edgeLabels ?? []).map((l) => ({\n edgeId: l.edgeId,\n text: l.text,\n bounds: l.bounds,\n anchor: l.anchor,\n }));\n return { labels, treatedEdges, routingEdges };\n }\n\n const measurer = input.measurer ?? defaultMeasurer;\n const snappedPaths = snapErdEdgeEndpoints(graph, layout, edgePaths);\n const routingEdges = pathsToRouted(snappedPaths);\n const crossings = detectCrossingPoints(routingEdges);\n const nodeBounds = new Map(layout.nodes.map((n) => [n.nodeId, n.bounds]));\n const obstacles = layout.nodes.map((n) => n.bounds);\n\n const labels: EdgeLabelPlacement[] = [];\n const labelObstacles: Rect[] = [];\n for (const edge of graph.edges) {\n const path = snappedPaths.find((p) => p.edgeId === edge.id);\n if (!path || path.points.length < 2) continue;\n\n const pureCard = Boolean(edge.cardinality && isPureCardinalityLabel(edge.label));\n\n let text: string | undefined;\n if (edge.fromColumn || edge.toColumn) {\n // Schema relationships rely on crow's-foot markers + column anchors.\n // Skip auto \"fk → pk\" pills; keep only explicit author text.\n if (edge.label && !pureCard) text = edge.label;\n } else if (edge.label && !pureCard) {\n text = edge.label;\n }\n\n const hasIcon = Boolean(edge.icon && edge.icon !== \"none\");\n\n // Fall back to ELK label placement if we have text but no KDiagram path text.\n if (!text && !hasIcon) {\n const elk = layout.edgeLabels.find((l) => l.edgeId === edge.id);\n if (elk && !pureCard) {\n labels.push({\n edgeId: elk.edgeId,\n text: elk.text,\n bounds: elk.bounds,\n anchor: elk.anchor,\n });\n labelObstacles.push(elk.bounds);\n }\n continue;\n }\n\n const endpoints = [nodeBounds.get(edge.from), nodeBounds.get(edge.to)].filter(\n (b): b is Rect => b != null,\n );\n const placed = placeEdgeLabel(\n edge.id,\n text ?? \"\",\n path.points,\n [...obstacles, ...labelObstacles],\n endpoints,\n {\n hasIcon,\n measurer,\n crossings,\n position: edge.labelPosition,\n authoredPosition: edge.labelPosition != null,\n },\n );\n labels.push(placed);\n labelObstacles.push(placed.bounds);\n }\n\n const treated = applyCrossingTreatment(routingEdges, routingOpts.crossings ?? \"none\");\n const showArrowheads = routingOpts.arrowheads !== false;\n const trimmed = trimEdgeEndpoints(treated, {\n sourceInset: (edgeId) => {\n const edge = graph.edges.find((e) => e.id === edgeId);\n return edge?.cardinality ? CARDINALITY_ENDPOINT_INSET : EDGE_ENDPOINT_INSET;\n },\n targetInset: (edgeId) => {\n const edge = graph.edges.find((e) => e.id === edgeId);\n if (edge?.cardinality) return CARDINALITY_ENDPOINT_INSET;\n const hasArrow =\n showArrowheads &&\n edge != null &&\n (edge.kind === \"sync\" ||\n edge.kind === \"async\" ||\n edge.kind === \"eventual\" ||\n edge.kind === \"failure\");\n return hasArrow ? ARROW_ENDPOINT_INSET : EDGE_ENDPOINT_INSET;\n },\n });\n\n return { labels, treatedEdges: trimmed, routingEdges };\n}\n","import type { Diagnostic, GraphModel } from \"@kekonic/diagrams-core\";\nimport type { LayoutResult } from \"@kekonic/diagrams-layout\";\nimport { detectCrossingPoints, type RoutingResult } from \"@kekonic/diagrams-routing\";\n\nexport const DEFAULT_TARGET_ASPECT_RATIO = 16 / 9;\nexport const QUALITY_CHECKS = [\n \"extreme-aspect-ratio\",\n \"canvas-spanning-edges\",\n \"excessive-edge-crossings\",\n \"reverse-layout-flow\",\n \"edge-label-pressure\",\n] as const;\n\nexport type QualityCheck = (typeof QUALITY_CHECKS)[number];\nexport type DiagramQualityMetrics = {\n width: number;\n height: number;\n aspectRatio: number;\n targetAspectRatio: number;\n targetAspectRatioDifference: number;\n edgeCrossings: number;\n canvasSpanningEdges: number;\n reverseFlowEdges: number;\n labeledEdges: number;\n};\n\nexport type DiagramQualityAnalysis = {\n metrics: DiagramQualityMetrics;\n diagnostics: Diagnostic[];\n};\n\nconst QUALITY_RANGE = {\n start: { line: 1, column: 1, offset: 0 },\n end: { line: 1, column: 1, offset: 0 },\n};\n\n/** Measure rendered geometry and return evidence plus actionable, human-readable diagnostics. */\nexport function analyzeDiagramQuality(\n graph: GraphModel,\n layout: LayoutResult,\n routedEdges: RoutingResult[\"edges\"],\n): DiagramQualityAnalysis {\n const aspectRatio = layout.width / Math.max(1, layout.height);\n const crossings = detectCrossingPoints(routedEdges).length;\n const canvasSpanningEdges = layout.edgePaths.filter((path) => {\n if (path.points.length < 2) return false;\n const xs = path.points.map((point) => point.x);\n const ys = path.points.map((point) => point.y);\n const spanX = Math.max(...xs) - Math.min(...xs);\n const spanY = Math.max(...ys) - Math.min(...ys);\n let length = 0;\n for (let index = 1; index < path.points.length; index++) {\n const previous = path.points[index - 1]!;\n const current = path.points[index]!;\n length += Math.abs(current.x - previous.x) + Math.abs(current.y - previous.y);\n }\n return (\n Math.max(spanX / Math.max(1, layout.width), spanY / Math.max(1, layout.height)) > 0.72 &&\n length > 0.8 * (layout.width + layout.height)\n );\n }).length;\n\n const nodeBounds = new Map(layout.nodes.map((node) => [node.nodeId, node.bounds]));\n const horizontal = layout.direction === \"LR\" || layout.direction === \"RL\";\n const reverseFlowEdges = graph.edges.filter((edge) => {\n const from = nodeBounds.get(edge.from);\n const to = nodeBounds.get(edge.to);\n if (!from || !to) return false;\n const fromPrimary = horizontal ? from.x + from.width / 2 : from.y + from.height / 2;\n const toPrimary = horizontal ? to.x + to.width / 2 : to.y + to.height / 2;\n const sign = layout.direction === \"RL\" || layout.direction === \"BT\" ? -1 : 1;\n return (fromPrimary - toPrimary) * sign > 24;\n }).length;\n const labeledEdges = graph.edges.filter((edge) => edge.label?.trim()).length;\n const metrics: DiagramQualityMetrics = {\n width: layout.width,\n height: layout.height,\n aspectRatio: Number(aspectRatio.toFixed(3)),\n targetAspectRatio: Number(DEFAULT_TARGET_ASPECT_RATIO.toFixed(3)),\n targetAspectRatioDifference: Number(\n Math.abs(aspectRatio - DEFAULT_TARGET_ASPECT_RATIO).toFixed(3),\n ),\n edgeCrossings: crossings,\n canvasSpanningEdges,\n reverseFlowEdges,\n labeledEdges,\n };\n if (graph.nodes.length < 6) return { metrics, diagnostics: [] };\n\n const diagnostics: Diagnostic[] = [];\n const silhouetteRatio = Math.max(aspectRatio, 1 / Math.max(0.001, aspectRatio));\n if (silhouetteRatio > 3) {\n diagnostics.push({\n severity: \"warning\",\n code: \"extreme-aspect-ratio\",\n message: `Diagram canvas is extremely ${layout.width > layout.height ? \"wide\" : \"tall\"} (${silhouetteRatio.toFixed(1)}:1)`,\n range: QUALITY_RANGE,\n hint: \"Aim near 16:9 by trying another direction, a bounded grid, shorter labels, or multiple views.\",\n });\n }\n if (canvasSpanningEdges >= 3) {\n diagnostics.push({\n severity: \"warning\",\n code: \"canvas-spanning-edges\",\n message: `${canvasSpanningEdges} edges span most of the canvas`,\n range: QUALITY_RANGE,\n hint: \"Separate feedback behavior, reduce cross-region relationships, or use progressive views.\",\n });\n }\n if (crossings >= Math.max(5, Math.ceil(graph.edges.length / 3))) {\n diagnostics.push({\n severity: \"warning\",\n code: \"excessive-edge-crossings\",\n message: `Diagram contains ${crossings} edge crossings`,\n range: QUALITY_RANGE,\n hint: \"Reorder regions, choose a different layout, or split secondary relationships into another view.\",\n });\n }\n if (reverseFlowEdges >= Math.max(3, Math.ceil(graph.edges.length * 0.2))) {\n diagnostics.push({\n severity: \"warning\",\n code: \"reverse-layout-flow\",\n message: `${reverseFlowEdges} transitions run against the primary layout direction`,\n range: QUALITY_RANGE,\n hint: \"Move retry behavior to a focused view or use responsibility lanes and explicit stages.\",\n });\n }\n if (graph.edges.length > graph.nodes.length * 1.6 && labeledEdges >= 12) {\n diagnostics.push({\n severity: \"warning\",\n code: \"edge-label-pressure\",\n message: \"Edge-label pressure is high for the number of nodes\",\n range: QUALITY_RANGE,\n hint: \"Keep the primary story and move secondary conditions or event catalogs into another view.\",\n });\n }\n return { metrics, diagnostics };\n}\n","import { compile } from \"@kekonic/diagrams-core\";\nimport { parse } from \"@kekonic/diagrams-core\";\nimport { resolvePresentation } from \"@kekonic/diagrams-core\";\nimport {\n measureGraph,\n measurerUsedApproximationFallback,\n layoutAndRouteWithElk,\n ELK_LAYOUT_ALGORITHM,\n ELK_ROUTER_ALGORITHM,\n analyzeDiagramTopology,\n} from \"@kekonic/diagrams-layout\";\nimport { collectIconIds, preloadIcons } from \"@kekonic/diagrams-icons\";\nimport { renderSvg } from \"@kekonic/diagrams-render-svg\";\nimport { finalizeElkEdges } from \"./finalize-edges.ts\";\nimport type {\n CompileResult,\n Diagnostic,\n GraphModel,\n Direction,\n LayoutOptions,\n ParseResult,\n RenderOptions,\n RenderResult,\n RenderStats,\n RoutingOptions,\n} from \"@kekonic/diagrams-core\";\nimport { mergeOptions as merge, mergePresentationOptions } from \"@kekonic/diagrams-core\";\nimport type { LayoutResult } from \"@kekonic/diagrams-layout\";\nimport type { RoutingResult } from \"@kekonic/diagrams-routing\";\nimport type { EdgeLabelPlacement } from \"@kekonic/diagrams-routing\";\nimport type { TreatedEdge } from \"@kekonic/diagrams-routing\";\nimport type { MeasuredGraph, LaidOutGraph, RoutedGraph, FinalizedGraph } from \"./artifacts.ts\";\nimport { analyzeDiagramQuality } from \"../quality.ts\";\n\nexport type PipelineRenderResult = Omit<RenderResult, \"layout\" | \"routing\"> & {\n layout?: LayoutResult;\n routing?: RoutingResult;\n /** KDiagram-placed edge label boxes (post-ELK). */\n labels?: EdgeLabelPlacement[];\n};\n\nconst DEFAULT_LAYOUT: LayoutOptions = {\n direction: \"LR\",\n density: \"normal\",\n spacingScale: 1.1,\n algorithmVersion: \"elk-layered-v1\",\n groupLayout: \"compound\",\n nodePlacement: \"balanced\",\n};\n\nconst DEFAULT_ROUTING: RoutingOptions = {\n route: \"metro\",\n crossings: \"gaps\",\n arrowheads: true,\n};\n\nconst DEFAULT_RENDER: RenderOptions = {\n theme: \"dark\",\n shadows: false,\n roundedCorners: false,\n};\n\nexport function parseSource(source: string): ParseResult {\n const ast = parse(source);\n return { ast, diagnostics: ast.diagnostics };\n}\n\nexport function compileSource(source: string, diagramIndex = 0): CompileResult {\n const { ast } = parseSource(source);\n return compile(ast, diagramIndex);\n}\n\nexport function measureFromGraph(graph: GraphModel, direction: Direction = \"LR\"): MeasuredGraph {\n const measured = measureGraph(graph);\n const topology = analyzeDiagramTopology(graph, direction);\n return { graph, measured: measured.nodes, topology, diagnostics: [] };\n}\n\nexport async function layoutFromGraph(\n graph: GraphModel,\n layoutOpts: LayoutOptions = {},\n): Promise<LayoutResult> {\n const opts = merge(DEFAULT_LAYOUT, layoutOpts);\n const measured = measureGraph(graph);\n const result = await layoutAndRouteWithElk(graph, measured.nodes, opts);\n return result.layout;\n}\n\nexport async function layoutMeasuredGraph(\n measuredGraph: MeasuredGraph,\n layoutOpts: LayoutOptions = {},\n): Promise<LaidOutGraph> {\n const opts = merge(DEFAULT_LAYOUT, layoutOpts);\n const result = await layoutAndRouteWithElk(measuredGraph.graph, measuredGraph.measured, opts);\n return { ...measuredGraph, layout: result.layout };\n}\n\nexport type RouteFromLayoutResult = {\n labels: EdgeLabelPlacement[];\n treatedEdges: TreatedEdge[];\n routing: RoutingResult;\n};\n\n/**\n * Finalize labels + endpoint trim from ELK edge paths on `layout`.\n * Does not re-run layout — ELK already owned routing in `layoutFromGraph` / `layoutMeasuredGraph`.\n */\nexport function routeFromLayout(\n graph: GraphModel,\n layout: LayoutResult,\n routingOpts: RoutingOptions = {},\n): RouteFromLayoutResult {\n const opts = merge(DEFAULT_ROUTING, routingOpts);\n const t0 = performance.now();\n const finalized = finalizeElkEdges({\n graph,\n layout,\n edgePaths: layout.edgePaths,\n routingOpts: opts,\n });\n return {\n labels: finalized.labels,\n treatedEdges: finalized.treatedEdges,\n routing: {\n edges: finalized.routingEdges,\n algorithmVersion: ELK_ROUTER_ALGORITHM,\n routeMs: performance.now() - t0,\n diagnostics: [],\n },\n };\n}\n\nexport function routeLaidOutGraph(\n laidOut: LaidOutGraph,\n routingOpts: RoutingOptions = {},\n): RoutedGraph {\n const routed = routeFromLayout(laidOut.graph, laidOut.layout, routingOpts);\n return {\n ...laidOut,\n routing: routed.routing,\n };\n}\n\nexport function finalizeRoutedGraph(\n routed: RoutedGraph,\n routingOpts: RoutingOptions = {},\n): FinalizedGraph {\n const opts = merge(DEFAULT_ROUTING, routingOpts);\n const finalized = finalizeElkEdges({\n graph: routed.graph,\n layout: routed.layout,\n edgePaths: routed.layout.edgePaths,\n routingOpts: opts,\n });\n return {\n ...routed,\n routing: {\n ...routed.routing,\n edges: finalized.routingEdges,\n },\n labels: finalized.labels,\n treatedEdges: finalized.treatedEdges,\n };\n}\n\nexport async function renderPipeline(\n source: string,\n options: RenderOptions & { layout?: LayoutOptions; edges?: RoutingOptions } = {},\n): Promise<PipelineRenderResult> {\n const t0 = performance.now();\n const diagnostics: Diagnostic[] = [];\n\n const tParse = performance.now();\n const { ast, diagnostics: parseDiags } = parseSource(source);\n diagnostics.push(...parseDiags);\n const parseMs = performance.now() - tParse;\n\n const tCompile = performance.now();\n const compiled = compile(ast);\n diagnostics.push(...compiled.diagnostics);\n const graph = compiled.graph;\n const compileMs = performance.now() - tCompile;\n\n const hasErrors = diagnostics.some((d) => d.severity === \"error\");\n if (hasErrors) {\n return emptyResult(diagnostics, {\n parseMs,\n compileMs,\n measureMs: 0,\n layoutMs: 0,\n routeMs: 0,\n renderMs: 0,\n totalMs: performance.now() - t0,\n nodeCount: graph.nodes.length,\n edgeCount: graph.edges.length,\n layoutAlgorithm: ELK_LAYOUT_ALGORITHM,\n routerAlgorithm: ELK_ROUTER_ALGORITHM,\n });\n }\n\n const layoutOpts = merge(DEFAULT_LAYOUT, compiled.layoutHints, options.layout);\n const routingOpts = merge(DEFAULT_ROUTING, compiled.routingHints, options.edges);\n const renderOpts = merge(DEFAULT_RENDER, compiled.renderHints, options);\n renderOpts.presentation = mergePresentationOptions(\n compiled.renderHints.presentation,\n options.presentation,\n );\n const presentation = resolvePresentation(renderOpts.presentation, graph.title);\n\n // Resolve icon viewBoxes before measure so card columns use real aspect widths.\n await preloadIcons(collectIconIds([...graph.nodes, ...graph.edges, ...graph.groups]));\n\n const tMeasure = performance.now();\n const measured = measureGraph(graph, undefined, {\n reserveKindSubtitles: presentation.showKindSubtitles,\n });\n const measureMs = performance.now() - tMeasure;\n if (measurerUsedApproximationFallback()) {\n diagnostics.push({\n severity: \"warning\",\n code: \"FM210\",\n message: \"Text measurement using approximation fallback; bundled font unavailable\",\n range: { start: { line: 1, column: 1, offset: 0 }, end: { line: 1, column: 1, offset: 0 } },\n hint: \"Install @fontsource/inter for shared CLI/browser metrics\",\n });\n }\n\n const tLayout = performance.now();\n const elk = await layoutAndRouteWithElk(graph, measured.nodes, layoutOpts);\n const layout = elk.layout;\n const layoutMs = performance.now() - tLayout;\n\n const tRoute = performance.now();\n const finalized = finalizeElkEdges({\n graph,\n layout,\n edgePaths: layout.edgePaths,\n routingOpts,\n });\n diagnostics.push(...analyzeDiagramQuality(graph, layout, finalized.routingEdges).diagnostics);\n const routeMs = performance.now() - tRoute;\n\n const routing: RoutingResult = {\n edges: finalized.routingEdges,\n algorithmVersion: elk.routerAlgorithm,\n routeMs,\n diagnostics: [],\n };\n\n const tRender = performance.now();\n const renderInput = {\n graph,\n layout,\n measured: measured.nodes,\n treatedEdges: finalized.treatedEdges,\n labels: finalized.labels,\n options: renderOpts,\n routingOptions: {\n route: routingOpts.route ?? \"orthogonal\",\n cornerRadius: routingOpts.cornerRadius,\n arrowheads: routingOpts.arrowheads,\n },\n };\n\n const svg = renderSvg(renderInput);\n const renderMs = performance.now() - tRender;\n\n const stats: RenderStats = {\n parseMs,\n compileMs,\n measureMs,\n layoutMs,\n routeMs,\n renderMs,\n totalMs: performance.now() - t0,\n nodeCount: graph.nodes.length,\n edgeCount: graph.edges.length,\n layoutAlgorithm: layout.algorithmVersion,\n routerAlgorithm: routing.algorithmVersion,\n };\n\n return {\n ok: true,\n svg,\n ast,\n graph,\n layout,\n routing,\n labels: finalized.labels,\n diagnostics,\n stats,\n };\n}\n\nfunction emptyResult(diagnostics: Diagnostic[], stats: RenderStats): PipelineRenderResult {\n return { ok: false, diagnostics, stats };\n}\n","import {\n bindSequenceFlowEdgeIds,\n flowHopEdgeId,\n inferAutoAnimation,\n type AnimationController,\n type AnimationCue,\n type AnimationDefinition,\n type AnimationListItem,\n type AnimationPlayerState,\n type AnimationTarget,\n type GraphModel,\n} from \"@kekonic/diagrams-core\";\n\nexport type TimedCue = {\n startMs: number;\n endMs: number;\n cue: AnimationCue;\n};\n\n/** In-flight or sticky flow paint state. */\nexport type ActiveFlow = {\n path: string[];\n progress: number;\n edgeId?: string;\n edgeIds?: string[];\n};\n\nfunction prefersReducedMotion(): boolean {\n if (typeof matchMedia !== \"function\") return false;\n return matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n}\n\nexport function buildTimeline(cues: AnimationCue[]): { timed: TimedCue[]; durationMs: number } {\n const timed: TimedCue[] = [];\n let t = 0;\n\n const appendCue = (cue: AnimationCue, at: number): number => {\n if (cue.op === \"dim\" || cue.op === \"activate\") {\n timed.push({ startMs: at, endMs: at, cue });\n return 0;\n }\n if (cue.op === \"wait\" || cue.op === \"pulse\" || cue.op === \"flow\") {\n const durationMs = Math.max(0, cue.durationMs);\n timed.push({ startMs: at, endMs: at + durationMs, cue });\n return durationMs;\n }\n if (cue.op === \"parallel\") {\n let maxDur = 0;\n for (const child of cue.cues) {\n maxDur = Math.max(maxDur, appendCue(child, at));\n }\n return maxDur;\n }\n return 0;\n };\n\n for (const cue of cues) {\n t += appendCue(cue, t);\n }\n return { timed, durationMs: t };\n}\n\nexport type PlaybackEmphasis = {\n dimAll: boolean;\n activeNodes: Set<string>;\n activeEdges: Set<string>;\n /** Concrete edge/message ids — preferred on sequence diagrams. */\n activeEdgeIds: Set<string>;\n pulseTargets: AnimationTarget[];\n flows: ActiveFlow[];\n};\n\n/**\n * Resolve which nodes/edges are dimmed vs active at `timeMs`.\n * `dim *` starts a new focus chapter: prior activate/flow stickiness is cleared.\n */\nexport function resolvePlaybackEmphasis(\n timed: TimedCue[],\n timeMs: number,\n allNodeIds: Iterable<string>,\n reducedMotion = false,\n): PlaybackEmphasis {\n let dimAll = false;\n const activeNodes = new Set<string>();\n const activeEdges = new Set<string>();\n const activeEdgeIds = new Set<string>();\n const pulseTargets: AnimationTarget[] = [];\n const flows: ActiveFlow[] = [];\n\n const markFlowHop = (cue: Extract<AnimationCue, { op: \"flow\" }>, hopIndex: number) => {\n const from = cue.path[hopIndex]!;\n const to = cue.path[hopIndex + 1]!;\n activeEdges.add(`${from}->${to}`);\n const id = flowHopEdgeId(hopIndex, cue);\n if (id) activeEdgeIds.add(id);\n };\n\n for (const item of timed) {\n if (item.startMs > timeMs) break;\n const cue = item.cue;\n if (cue.op === \"dim\") {\n for (const t of cue.targets) {\n if (t.type === \"all\") {\n dimAll = true;\n // Chapter / story reset — off-path highlights from earlier cues drop out.\n activeNodes.clear();\n activeEdges.clear();\n activeEdgeIds.clear();\n pulseTargets.length = 0;\n flows.length = 0;\n }\n }\n } else if (cue.op === \"activate\") {\n for (const t of cue.targets) {\n if (t.type === \"all\") {\n for (const id of allNodeIds) activeNodes.add(id);\n } else if (t.type === \"node\") {\n activeNodes.add(t.id);\n } else {\n activeEdges.add(`${t.from}->${t.to}`);\n }\n }\n } else if (cue.op === \"pulse\") {\n if (timeMs >= item.startMs && timeMs <= item.endMs && !reducedMotion) {\n pulseTargets.push(...cue.targets);\n for (const t of cue.targets) {\n if (t.type === \"node\") activeNodes.add(t.id);\n if (t.type === \"edge\") activeEdges.add(`${t.from}->${t.to}`);\n }\n }\n } else if (cue.op === \"flow\") {\n if (timeMs >= item.startMs && timeMs <= item.endMs) {\n const span = Math.max(1, item.endMs - item.startMs);\n const flowProgress = reducedMotion ? 1 : (timeMs - item.startMs) / span;\n flows.push({\n path: cue.path,\n progress: flowProgress,\n edgeId: cue.edgeId,\n edgeIds: cue.edgeIds,\n });\n const edgeCount = Math.max(1, cue.path.length - 1);\n for (let i = 0; i < cue.path.length; i++) {\n if (flowProgress >= i / edgeCount - 0.001) activeNodes.add(cue.path[i]!);\n if (cue.path[i + 1] && flowProgress >= i / edgeCount) markFlowHop(cue, i);\n }\n } else if (timeMs > item.endMs) {\n for (const nodeId of cue.path) activeNodes.add(nodeId);\n for (let i = 0; i < cue.path.length - 1; i++) markFlowHop(cue, i);\n }\n }\n }\n\n return { dimAll, activeNodes, activeEdges, activeEdgeIds, pulseTargets, flows };\n}\n\n/**\n * Interactive SVG animation player bound to a mounted KDiagram diagram.\n */\nexport class AnimationPlayer implements AnimationController {\n #svg: SVGSVGElement | null = null;\n #graph: GraphModel | null = null;\n #catalog: AnimationDefinition[] = [];\n #current: AnimationDefinition | null = null;\n #timed: TimedCue[] = [];\n #durationMs = 0;\n #timeMs = 0;\n #playing = false;\n #loop = false;\n #speed = 1;\n #raf: number | null = null;\n #lastTick = 0;\n #listeners = new Set<(state: AnimationPlayerState) => void>();\n #flowLayer: SVGGElement | null = null;\n\n list(): AnimationListItem[] {\n return this.#catalog.map((a) => ({ id: a.id, name: a.name, source: a.source }));\n }\n\n getState(): AnimationPlayerState {\n return {\n id: this.#current?.id ?? null,\n playing: this.#playing,\n timeMs: this.#timeMs,\n durationMs: this.#durationMs,\n loop: this.#loop,\n speed: this.#speed,\n };\n }\n\n subscribe(listener: (state: AnimationPlayerState) => void): () => void {\n this.#listeners.add(listener);\n listener(this.getState());\n return () => this.#listeners.delete(listener);\n }\n\n /** Rebind after SVG replace. Preserves current animation id and time when possible. */\n rebind(svg: SVGSVGElement | null, graph: GraphModel | null): void {\n const prevId = this.#current?.id ?? null;\n const prevTime = this.#timeMs;\n const wasPlaying = this.#playing;\n const prevLoop = this.#loop;\n const prevSpeed = this.#speed;\n this.#teardownVisuals();\n this.#svg = svg;\n this.#graph = graph;\n this.#rebuildCatalog();\n if (!svg || !graph) {\n this.#current = null;\n this.#timed = [];\n this.#durationMs = 0;\n this.#timeMs = 0;\n this.#playing = false;\n this.#notify();\n return;\n }\n const next = (prevId && this.#catalog.find((a) => a.id === prevId)) || this.#catalog[0] || null;\n this.#select(next, false);\n // Keep user loop/speed toggles across SVG rebuilds when still on the same clip.\n if (next && prevId === next.id) this.#loop = prevLoop;\n this.#speed = prevSpeed;\n if (next) {\n this.seek(Math.min(prevTime, this.#durationMs));\n if (wasPlaying) this.play();\n } else {\n this.#notify();\n }\n }\n\n play(id?: string): void {\n if (id) {\n const found = this.#catalog.find((a) => a.id === id);\n if (found) this.#select(found, true);\n } else if (!this.#current) {\n this.#select(this.#catalog[0] ?? null, true);\n }\n if (!this.#current || this.#durationMs <= 0) {\n this.#applyAt(0);\n this.#notify();\n return;\n }\n if (this.#timeMs >= this.#durationMs) this.#timeMs = 0;\n this.#playing = true;\n this.#lastTick = performance.now();\n this.#armRaf();\n this.#notify();\n }\n\n pause(): void {\n this.#playing = false;\n this.#cancelRaf();\n this.#notify();\n }\n\n stop(): void {\n this.#playing = false;\n this.#cancelRaf();\n this.#timeMs = 0;\n this.#clearEmphasis();\n this.#notify();\n }\n\n seek(ms: number): void {\n this.#timeMs = Math.max(0, Math.min(this.#durationMs, ms));\n this.#applyAt(this.#timeMs);\n this.#notify();\n }\n\n step(delta: -1 | 1): void {\n if (this.#timed.length === 0) return;\n const boundaries = [...new Set(this.#timed.flatMap((t) => [t.startMs, t.endMs]))].sort(\n (a, b) => a - b,\n );\n if (delta > 0) {\n const next = boundaries.find((b) => b > this.#timeMs + 0.5);\n this.seek(next ?? this.#durationMs);\n } else {\n const prev = [...boundaries].reverse().find((b) => b < this.#timeMs - 0.5);\n this.seek(prev ?? 0);\n }\n }\n\n setLoop(on: boolean): void {\n this.#loop = on;\n this.#notify();\n }\n\n setSpeed(rate: number): void {\n if (!Number.isFinite(rate)) return;\n this.#speed = Math.min(2, Math.max(0.5, rate));\n this.#notify();\n }\n\n destroy(): void {\n this.stop();\n this.#listeners.clear();\n this.#svg = null;\n this.#graph = null;\n this.#catalog = [];\n }\n\n #rebuildCatalog(): void {\n if (!this.#graph) {\n this.#catalog = [];\n return;\n }\n const authored = this.#graph.animations ?? [];\n const catalog: AnimationDefinition[] = [];\n for (const anim of authored) {\n if (anim.source === \"auto\") {\n const inferred = inferAutoAnimation(this.#graph);\n if (!inferred) continue;\n catalog.push({\n ...inferred,\n id: anim.id,\n name: anim.name,\n loop: anim.loop,\n source: \"auto\",\n });\n continue;\n }\n catalog.push({\n ...anim,\n cues: bindSequenceFlowEdgeIds(this.#graph, anim.cues),\n });\n }\n this.#catalog = catalog;\n }\n\n #select(anim: AnimationDefinition | null, resetTime: boolean): void {\n this.#current = anim;\n if (!anim) {\n this.#timed = [];\n this.#durationMs = 0;\n this.#timeMs = 0;\n this.#loop = false;\n this.#clearEmphasis();\n return;\n }\n const built = buildTimeline(anim.cues);\n this.#timed = built.timed;\n this.#durationMs = built.durationMs;\n this.#loop = anim.loop;\n if (resetTime) this.#timeMs = 0;\n this.#applyAt(this.#timeMs);\n }\n\n #notify(): void {\n const state = this.getState();\n for (const listener of this.#listeners) listener(state);\n }\n\n #armRaf(): void {\n this.#cancelRaf();\n this.#raf = requestAnimationFrame(this.#tick);\n }\n\n #cancelRaf(): void {\n if (this.#raf != null) {\n cancelAnimationFrame(this.#raf);\n this.#raf = null;\n }\n }\n\n #tick = (now: number): void => {\n if (!this.#playing) return;\n const dt = (now - this.#lastTick) * this.#speed;\n this.#lastTick = now;\n this.#timeMs += dt;\n if (this.#timeMs >= this.#durationMs) {\n if (this.#loop && this.#durationMs > 0) {\n this.#timeMs = this.#timeMs % this.#durationMs;\n } else {\n this.#timeMs = this.#durationMs;\n this.#playing = false;\n this.#applyAt(this.#timeMs);\n this.#notify();\n return;\n }\n }\n this.#applyAt(this.#timeMs);\n this.#notify();\n this.#armRaf();\n };\n\n #teardownVisuals(): void {\n this.#cancelRaf();\n this.#clearEmphasis();\n }\n\n #clearEmphasis(): void {\n if (!this.#svg) return;\n for (const el of this.#svg.querySelectorAll(\n \".flow-anim-dim, .flow-anim-active, .flow-anim-pulse\",\n )) {\n el.classList.remove(\"flow-anim-dim\", \"flow-anim-active\", \"flow-anim-pulse\");\n }\n this.#flowLayer?.remove();\n this.#flowLayer = null;\n }\n\n #applyAt(timeMs: number): void {\n if (!this.#svg || !this.#graph) return;\n this.#clearEmphasis();\n\n const reduced = prefersReducedMotion();\n const { dimAll, activeNodes, activeEdges, activeEdgeIds, pulseTargets, flows } =\n resolvePlaybackEmphasis(\n this.#timed,\n timeMs,\n this.#graph.nodes.map((n) => n.id),\n reduced,\n );\n\n // Dim the rest of the world while a story is in progress — keep actives crisp.\n if (dimAll) {\n for (const el of this.#svg.querySelectorAll(\n \"[data-node-id], g.flow-edge[data-edge-id], .flow-sequence-activation, g.flow-sequence-fragment, .flow-sequence-fragment-operand, g.flow-sequence-note, g.flow-sequence-divider\",\n )) {\n el.classList.add(\"flow-anim-dim\");\n }\n for (const el of this.#svg.querySelectorAll(\"g.flow-edge-label\")) {\n el.classList.add(\"flow-anim-dim\");\n }\n }\n\n for (const id of activeNodes) {\n for (const el of this.#nodeEls(id)) {\n el.classList.remove(\"flow-anim-dim\");\n el.classList.add(\"flow-anim-active\");\n }\n }\n\n // Sequence messages share from→to pairs; always activate by concrete edge id.\n if (this.#graph.sequence) {\n for (const id of activeEdgeIds) this.#emphasizeEdgeId(id);\n } else {\n for (const key of activeEdges) {\n const [from, to] = key.split(\"->\");\n if (!from || !to) continue;\n for (const el of this.#edgeEls(from, to)) {\n el.classList.remove(\"flow-anim-dim\");\n el.classList.add(\"flow-anim-active\");\n const edgeId = el.getAttribute(\"data-edge-id\");\n if (edgeId) this.#emphasizeEdgeLabels(edgeId);\n }\n }\n }\n\n this.#applySequenceChrome(dimAll, activeEdgeIds);\n\n if (pulseTargets.length) {\n for (const t of pulseTargets) {\n if (t.type === \"node\") {\n this.#nodeEls(t.id).forEach((el) => el.classList.add(\"flow-anim-pulse\"));\n } else if (t.type === \"edge\") {\n this.#edgeEls(t.from, t.to).forEach((el) => el.classList.add(\"flow-anim-pulse\"));\n }\n }\n }\n\n if (flows.length && !reduced) {\n this.#paintFlows(flows);\n }\n }\n\n /**\n * Sequence chrome: highlight activation bars + fragments covering active message orders.\n * Orders come only from concrete message edge ids (never bare from→to).\n */\n #applySequenceChrome(dimAll: boolean, activeEdgeIds: Set<string>): void {\n if (!this.#svg || !this.#graph?.sequence) return;\n\n const focusOrders = new Set<number>();\n for (const id of activeEdgeIds) {\n for (const el of this.#edgeElsById(id)) {\n const raw = el.getAttribute(\"data-sequence-order\");\n if (raw == null) continue;\n const order = Number(raw);\n if (Number.isFinite(order)) focusOrders.add(order);\n }\n }\n\n if (focusOrders.size === 0 && !dimAll) return;\n\n const emphasizeSpan = (el: Element) => {\n const start = Number(el.getAttribute(\"data-start-order\"));\n const end = Number(el.getAttribute(\"data-end-order\"));\n if (!Number.isFinite(start) || !Number.isFinite(end)) return;\n let live = false;\n for (const order of focusOrders) {\n if (start <= order && order <= end) {\n live = true;\n break;\n }\n }\n if (live) {\n el.classList.remove(\"flow-anim-dim\");\n el.classList.add(\"flow-anim-active\");\n } else if (dimAll) {\n el.classList.add(\"flow-anim-dim\");\n el.classList.remove(\"flow-anim-active\");\n }\n };\n\n for (const el of this.#svg.querySelectorAll(\".flow-sequence-activation\")) {\n emphasizeSpan(el);\n }\n for (const el of this.#svg.querySelectorAll(\"g.flow-sequence-fragment\")) {\n emphasizeSpan(el);\n }\n for (const el of this.#svg.querySelectorAll(\".flow-sequence-fragment-operand\")) {\n emphasizeSpan(el);\n }\n }\n\n #emphasizeEdgeId(edgeId: string): void {\n for (const el of this.#edgeElsById(edgeId)) {\n el.classList.remove(\"flow-anim-dim\");\n el.classList.add(\"flow-anim-active\");\n }\n this.#emphasizeEdgeLabels(edgeId);\n }\n\n #emphasizeEdgeLabels(edgeId: string): void {\n if (!this.#svg) return;\n for (const label of this.#svg.querySelectorAll(\n `g.flow-edge-label[data-edge-id=\"${cssEscape(edgeId)}\"]`,\n )) {\n label.classList.remove(\"flow-anim-dim\");\n label.classList.add(\"flow-anim-active\");\n }\n }\n\n #edgeElsById(edgeId: string): Element[] {\n if (!this.#svg) return [];\n return [...this.#svg.querySelectorAll(`g.flow-edge[data-edge-id=\"${cssEscape(edgeId)}\"]`)];\n }\n\n #nodeEls(id: string): Element[] {\n if (!this.#svg) return [];\n return [...this.#svg.querySelectorAll(`[data-node-id=\"${cssEscape(id)}\"]`)];\n }\n\n #edgeEls(from: string, to: string, edgeId?: string): Element[] {\n if (!this.#svg) return [];\n if (edgeId) {\n const exact = this.#edgeElsById(edgeId);\n if (exact.length) return exact;\n }\n return [\n ...this.#svg.querySelectorAll(\n `g.flow-edge[data-edge-from=\"${cssEscape(from)}\"][data-edge-to=\"${cssEscape(to)}\"]`,\n ),\n ];\n }\n\n /** Collect routed path `d` values for an edge (main strokes + jumps). */\n #edgePathDs(from: string, to: string, edgeId?: string): string[] {\n const edge = this.#edgeEls(from, to, edgeId)[0];\n if (!edge) return [];\n const ds: string[] = [];\n for (const p of edge.querySelectorAll(\"path.flow-edge-path, path.flow-edge-jump\")) {\n const d = p.getAttribute(\"d\");\n if (d) ds.push(d);\n }\n return ds;\n }\n\n /** Resolved paint of an edge — keeps yes/no/kind color on the flow bead. */\n #edgeStroke(from: string, to: string, edgeId?: string): string | null {\n const edge = this.#edgeEls(from, to, edgeId)[0];\n const path = edge?.querySelector(\"path.flow-edge-path, path.flow-edge-jump\");\n if (!path) return null;\n const stroke = getComputedStyle(path).stroke;\n if (!stroke || stroke === \"none\") return null;\n return stroke;\n }\n\n /**\n * Diagram geometry lives under `.flow-diagram-content` (translated for padding).\n * Flow overlays must mount there or they sit at a parallel offset from real edges.\n */\n #diagramContent(): SVGElement {\n const content = this.#svg?.querySelector(\"g.flow-diagram-content\");\n return (content as SVGElement | null) ?? this.#svg!;\n }\n\n #paintFlows(flows: ActiveFlow[]): void {\n if (!this.#svg) return;\n const mount = this.#diagramContent();\n const layer = document.createElementNS(\"http://www.w3.org/2000/svg\", \"g\");\n layer.setAttribute(\"class\", \"flow-anim-flow-layer\");\n layer.style.pointerEvents = \"none\";\n let painted = false;\n for (const flow of flows) {\n if (flow.path.length < 2) continue;\n if (this.#paintFlowOnto(layer, mount, flow)) painted = true;\n }\n if (!painted) return;\n mount.appendChild(layer);\n this.#flowLayer = layer;\n }\n\n /**\n * Paint one flow bead/trail into `layer`. Probes are attached to `mount` temporarily\n * for getTotalLength. Returns true when any geometry was drawn.\n */\n #paintFlowOnto(layer: SVGGElement, mount: SVGElement, flow: ActiveFlow): boolean {\n const { path, progress } = flow;\n // One hop = one authored edge (may include several path/jump strokes).\n // Keep a slot even when the edge isn't found so hop timing stays aligned with #applyAt.\n type Seg = { d: string; len: number; probe: SVGPathElement };\n type Hop = { stroke: string | null; segs: Seg[] };\n const hops: Hop[] = [];\n for (let i = 0; i < path.length - 1; i++) {\n const from = path[i]!;\n const to = path[i + 1]!;\n const hopId = flowHopEdgeId(i, flow);\n const ds = this.#edgePathDs(from, to, hopId);\n const segs: Seg[] = [];\n for (const d of ds) {\n const probe = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n probe.setAttribute(\"d\", d);\n // Must be in the tree for reliable getTotalLength in some engines.\n probe.setAttribute(\"visibility\", \"hidden\");\n mount.appendChild(probe);\n segs.push({ d, len: probe.getTotalLength?.() ?? 0, probe });\n }\n hops.push({ stroke: this.#edgeStroke(from, to, hopId), segs });\n }\n if (!hops.some((h) => h.segs.length > 0)) {\n for (const hop of hops) for (const seg of hop.segs) seg.probe.remove();\n return false;\n }\n\n // Equal time per hop (not per path-length). Longer edges move faster geometrically\n // so each edge gets the same beat of the cue — matches activate timing in #applyAt.\n const p = Math.max(0, Math.min(1, progress));\n const hopCount = hops.length;\n const scaled = p * hopCount;\n const hopIdx = p >= 1 ? hopCount - 1 : Math.min(hopCount - 1, Math.floor(scaled));\n const localT = p >= 1 ? 1 : scaled - hopIdx;\n\n let headPoint: DOMPoint | null = null;\n let headStroke: string | null = null;\n\n for (let h = 0; h < hopCount; h++) {\n const hop = hops[h]!;\n const segs = hop.segs;\n const hopLen = segs.reduce((sum, s) => sum + s.len, 0);\n const revealInHop =\n h < hopIdx ? hopLen : h > hopIdx ? 0 : Math.max(0, Math.min(hopLen, localT * hopLen));\n\n let walked = 0;\n for (const seg of segs) {\n const localReveal = Math.max(0, Math.min(seg.len, revealInHop - walked));\n if (localReveal > 0 && seg.len > 0) {\n // Trail only — never paint a full ghost of the remaining edge (looks like a redraw).\n const track = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n track.setAttribute(\"class\", \"flow-anim-flow-track\");\n track.setAttribute(\"d\", seg.d);\n track.style.strokeDasharray = `${seg.len}`;\n track.style.strokeDashoffset = `${seg.len - localReveal}`;\n if (hop.stroke) {\n track.style.stroke = `color-mix(in srgb, ${hop.stroke} 40%, transparent)`;\n }\n layer.appendChild(track);\n\n const overlay = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n overlay.setAttribute(\"class\", \"flow-anim-flow-overlay\");\n overlay.setAttribute(\"d\", seg.d);\n overlay.style.strokeDasharray = `${seg.len}`;\n overlay.style.strokeDashoffset = `${seg.len - localReveal}`;\n if (hop.stroke) overlay.style.stroke = hop.stroke;\n layer.appendChild(overlay);\n\n const core = document.createElementNS(\"http://www.w3.org/2000/svg\", \"path\");\n core.setAttribute(\"class\", \"flow-anim-flow-core\");\n core.setAttribute(\"d\", seg.d);\n core.style.strokeDasharray = `${seg.len}`;\n core.style.strokeDashoffset = `${seg.len - localReveal}`;\n if (hop.stroke) {\n core.style.stroke = `color-mix(in srgb, ${hop.stroke} 35%, white)`;\n }\n layer.appendChild(core);\n\n if (revealInHop >= walked && revealInHop <= walked + seg.len) {\n headPoint = seg.probe.getPointAtLength(localReveal);\n headStroke = hop.stroke;\n } else if (revealInHop > walked + seg.len) {\n headPoint = seg.probe.getPointAtLength(seg.len);\n headStroke = hop.stroke;\n }\n }\n walked += seg.len;\n }\n }\n\n for (const hop of hops) for (const seg of hop.segs) seg.probe.remove();\n\n if (headPoint && p > 0 && p < 1) {\n const head = document.createElementNS(\"http://www.w3.org/2000/svg\", \"circle\");\n head.setAttribute(\"class\", \"flow-anim-flow-head\");\n head.setAttribute(\"cx\", String(headPoint.x));\n head.setAttribute(\"cy\", String(headPoint.y));\n head.setAttribute(\"r\", \"5.5\");\n if (headStroke) {\n head.style.fill = `color-mix(in srgb, ${headStroke} 35%, white)`;\n head.style.stroke = headStroke;\n }\n layer.appendChild(head);\n }\n return true;\n }\n}\n\nfunction cssEscape(value: string): string {\n if (typeof CSS !== \"undefined\" && typeof CSS.escape === \"function\") return CSS.escape(value);\n return value.replace(/[\"\\\\]/g, \"\\\\$&\");\n}\n","import {\n BUILTIN_KIND_CATALOG,\n BUILTIN_SHAPE_IDS,\n EDGE_OPS,\n STATEMENT_KEYWORDS,\n} from \"@kekonic/diagrams-core\";\nimport { listBuiltinIconIds, listDefaultCollections } from \"@kekonic/diagrams-icons\";\nimport { ELK_LAYOUT_ALGORITHM, ELK_ROUTER_ALGORITHM } from \"@kekonic/diagrams-layout\";\nimport { QUALITY_CHECKS } from \"./quality.ts\";\n\nexport const KDIAGRAM_CAPABILITIES_VERSION = 1 as const;\n\nexport type KDiagramCapabilities = {\n version: 1;\n registryScope: \"built-in\";\n language: {\n version: 1;\n diagramFamilies: readonly [\"flow\", \"state\", \"sequence\"];\n statementKeywords: string[];\n edgeOperators: string[];\n };\n nodes: Array<{\n id: string;\n category: string;\n shape: string;\n subtitle: string;\n capabilities: string[];\n defaultIcon?: string;\n }>;\n shapes: string[];\n icons: { builtin: string[]; collections: string[] };\n layout: {\n algorithm: string;\n router: string;\n directions: readonly [\"LR\", \"RL\", \"TD\", \"BT\"];\n densities: readonly [\"compact\", \"normal\", \"spacious\"];\n groupLayouts: readonly [\"compound\", \"swimlane\"];\n regionArrangements: readonly [\"stack\", \"row\", \"grid\"];\n };\n presentation: {\n themes: readonly [\"dark\", \"light\"];\n exportFormats: readonly [\"svg\"];\n themeModes: readonly [\"snapshot\", \"live\"];\n };\n qualityChecks: string[];\n};\n\n/** Deterministic, JSON-safe description of the active built-in KDiagram surface. */\nexport function getCapabilities(): KDiagramCapabilities {\n return {\n version: KDIAGRAM_CAPABILITIES_VERSION,\n registryScope: \"built-in\",\n language: {\n version: 1,\n diagramFamilies: [\"flow\", \"state\", \"sequence\"],\n statementKeywords: [...STATEMENT_KEYWORDS].sort(),\n edgeOperators: [...EDGE_OPS],\n },\n nodes: Object.entries(BUILTIN_KIND_CATALOG)\n .map(([id, kind]) => ({\n id,\n category: kind.category,\n shape: kind.shape,\n subtitle: kind.subtitle,\n capabilities: [...kind.capabilities].sort(),\n ...(kind.icon ? { defaultIcon: kind.icon } : {}),\n }))\n .sort((left, right) => left.id.localeCompare(right.id)),\n shapes: [...BUILTIN_SHAPE_IDS].sort(),\n icons: {\n builtin: listBuiltinIconIds().sort(),\n collections: listDefaultCollections().sort(),\n },\n layout: {\n algorithm: ELK_LAYOUT_ALGORITHM,\n router: ELK_ROUTER_ALGORITHM,\n directions: [\"LR\", \"RL\", \"TD\", \"BT\"],\n densities: [\"compact\", \"normal\", \"spacious\"],\n groupLayouts: [\"compound\", \"swimlane\"],\n regionArrangements: [\"stack\", \"row\", \"grid\"],\n },\n presentation: {\n themes: [\"dark\", \"light\"],\n exportFormats: [\"svg\"],\n themeModes: [\"snapshot\", \"live\"],\n },\n qualityChecks: [...QUALITY_CHECKS],\n };\n}\n","import { formatSource } from \"@kekonic/diagrams-core\";\nimport {\n ensureBrowserFonts,\n resetDefaultMeasurer,\n type LayoutResult,\n} from \"@kekonic/diagrams-layout\";\nimport { getThemeTokens, THEME_CSS } from \"@kekonic/diagrams-theme\";\nimport {\n compileSource,\n layoutFromGraph,\n parseSource,\n renderPipeline,\n routeFromLayout,\n} from \"./pipeline/index.ts\";\nimport type {\n CompileResult,\n GraphModel,\n InteractiveRenderOptions,\n LayoutOptions,\n ParseResult,\n RenderController,\n RenderOptions,\n RenderResult,\n RoutingOptions,\n ThemeMode,\n} from \"@kekonic/diagrams-core\";\nimport type { RouteFromLayoutResult } from \"./pipeline/index.ts\";\nimport { AnimationPlayer } from \"./animation/player.ts\";\nexport {\n KDIAGRAM_CAPABILITIES_VERSION,\n getCapabilities,\n type KDiagramCapabilities,\n} from \"./capabilities.ts\";\nexport {\n analyzeDiagramQuality,\n DEFAULT_TARGET_ASPECT_RATIO,\n QUALITY_CHECKS,\n type DiagramQualityAnalysis,\n type DiagramQualityMetrics,\n type QualityCheck,\n} from \"./quality.ts\";\n\nexport type * from \"@kekonic/diagrams-core\";\nexport {\n parse,\n compile,\n getKindDefaults,\n isBuiltinKind,\n BUILTIN_KIND_LIST,\n BUILTIN_KIND_CATALOG,\n kindHasCapability,\n kindSubtitle,\n listKindsByCategory,\n listGeometryKinds,\n isGeometryKind,\n normalizeShapeId,\n isKnownShapeId,\n BUILTIN_SHAPE_IDS,\n formatSource,\n mergeOptions,\n resolvePresentation,\n mergePresentationOptions,\n formatLabelText,\n displayLabelCase,\n EDGE_OPS,\n edgeOpsPattern,\n STATEMENT_KEYWORDS,\n inferAutoAnimation,\n planAutoWalk,\n enumerateAutoPaths,\n traceDeclarationPath,\n animationIdFromName,\n} from \"@kekonic/diagrams-core\";\nexport { AnimationPlayer } from \"./animation/player.ts\";\nexport type {\n PresentationOptions,\n ResolvedPresentation,\n EdgeOperator,\n AutoWalkStep,\n} from \"@kekonic/diagrams-core\";\nexport type {\n LayoutResult,\n LaidOutNode,\n LaidOutGroup,\n DiagramTopology,\n LayoutEdgePath,\n} from \"@kekonic/diagrams-layout\";\nexport {\n measureGraph,\n layoutAndRouteWithElk,\n analyzeDiagramTopology,\n ELK_LAYOUT_ALGORITHM,\n ELK_ROUTER_ALGORITHM,\n} from \"@kekonic/diagrams-layout\";\nexport type {\n RoutingResult,\n RoutedEdge,\n TreatedEdge,\n EdgeLabelPlacement,\n} from \"@kekonic/diagrams-routing\";\nexport { applyCrossingTreatment, attachPointOnPerimeter } from \"@kekonic/diagrams-routing\";\nexport { renderSvg } from \"@kekonic/diagrams-render-svg\";\nexport {\n resolveShapeGeometry,\n registerShape,\n registerNodeType,\n getNodeTypeDefinition,\n resolveNodeTypeGeometry,\n listRegisteredNodeTypeIds,\n buildNodeBoundsModel,\n listRegisteredShapeIds,\n type ShapeGeometry,\n type NodeBoundsModel,\n type NodeTypeDefinition,\n} from \"@kekonic/diagrams-geometry\";\nexport { registerTheme, getThemeTokens, themeToCss, THEME_CSS } from \"@kekonic/diagrams-theme\";\nexport {\n normalizeIconId,\n parseIconId,\n preloadIcons,\n preloadCollections,\n collectIconIds,\n resolveIcon,\n renderIconById,\n registerIcon,\n registerCollection,\n registerCollectionLoader,\n setIconifyApiBaseUrl,\n listBuiltinIconIds,\n listDefaultCollections,\n BUILTIN_ICON_ALIASES,\n} from \"@kekonic/diagrams-icons\";\nexport {\n parseSource,\n compileSource,\n measureFromGraph,\n layoutFromGraph,\n layoutMeasuredGraph,\n routeFromLayout,\n routeLaidOutGraph,\n finalizeRoutedGraph,\n renderPipeline,\n finalizeElkEdges,\n type RouteFromLayoutResult,\n type FinalizeElkEdgesInput,\n type FinalizeElkEdgesResult,\n type MeasuredGraph,\n type LaidOutGraph,\n type RoutedGraph,\n type FinalizedGraph,\n} from \"./pipeline/index.ts\";\n\nexport type {\n CompileResult,\n GraphModel,\n InteractiveRenderOptions,\n LayoutOptions,\n ParseResult,\n RenderController,\n RenderOptions,\n RenderResult,\n RoutingOptions,\n ThemeMode,\n};\n\nexport const KDiagram = {\n parse(source: string): ParseResult {\n return parseSource(source);\n },\n\n compile(source: string, _options?: Record<string, never>): CompileResult {\n return compileSource(source);\n },\n\n async layout(graph: GraphModel, options?: LayoutOptions): Promise<LayoutResult> {\n return layoutFromGraph(graph, options);\n },\n\n route(graph: GraphModel, layout: LayoutResult, options?: RoutingOptions): RouteFromLayoutResult {\n return routeFromLayout(graph, layout, options);\n },\n\n format(source: string): string {\n return formatSource(source);\n },\n\n async ensureFonts(): Promise<void> {\n const { default: interFontUrl } =\n await import(\"@fontsource/inter/files/inter-latin-500-normal.woff?url\");\n await ensureBrowserFonts(interFontUrl);\n resetDefaultMeasurer();\n },\n\n async renderToSvg(\n source: string,\n options?: RenderOptions & { layout?: LayoutOptions; edges?: RoutingOptions },\n ): Promise<RenderResult> {\n return renderPipeline(source, options);\n },\n\n renderToElement(\n source: string,\n container: HTMLElement,\n options?: InteractiveRenderOptions,\n ): RenderController {\n let currentTheme: ThemeMode = options?.theme ?? \"dark\";\n let currentOptions: InteractiveRenderOptions = { ...options };\n type ViewBox = { x: number; y: number; w: number; h: number };\n let naturalView: ViewBox = { x: 0, y: 0, w: 1, h: 1 };\n let viewport: ViewBox = { ...naturalView };\n let isPanning = false;\n let panOrigin: ViewBox = { x: 0, y: 0, w: 0, h: 0 };\n let panPointer = { x: 0, y: 0 };\n let hasPainted = false;\n let resizeObserver: ResizeObserver | null = null;\n\n const MIN_ZOOM = 0.15;\n const MAX_ZOOM = 4;\n\n const wrapper = document.createElement(\"div\");\n wrapper.className = `kdiagram-viewport kdiagram-theme-${currentTheme}`;\n wrapper.style.cssText =\n \"width:100%;height:100%;overflow:hidden;position:relative;cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none;\";\n const applyLiveThemeTokens = () => {\n for (const [property, value] of Object.entries(getThemeTokens(currentTheme))) {\n wrapper.style.setProperty(property, value);\n }\n };\n applyLiveThemeTokens();\n const inner = document.createElement(\"div\");\n inner.className = \"kdiagram-canvas\";\n inner.style.cssText = \"width:100%;height:100%;user-select:none;-webkit-user-select:none;\";\n wrapper.appendChild(inner);\n container.innerHTML = \"\";\n container.appendChild(wrapper);\n\n const themeCssText = `${THEME_CSS}\n.kdiagram-viewport, .kdiagram-viewport svg, .kdiagram-viewport text {\n user-select: none;\n -webkit-user-select: none;\n}\n.kdiagram-viewport svg { display:block; width:100%; height:100%; }`;\n let themeStyle = document.getElementById(\"kdiagram-theme-css\") as HTMLStyleElement | null;\n if (!themeStyle) {\n themeStyle = document.createElement(\"style\");\n themeStyle.id = \"kdiagram-theme-css\";\n document.head.appendChild(themeStyle);\n }\n themeStyle.textContent = themeCssText;\n\n let lastSource = source;\n const animationPlayer = new AnimationPlayer();\n\n const parseViewBox = (svg: SVGSVGElement): ViewBox => {\n const parts = (svg.getAttribute(\"viewBox\") ?? \"0 0 1 1\").trim().split(/\\s+/).map(Number);\n return {\n x: parts[0] ?? 0,\n y: parts[1] ?? 0,\n w: parts[2] ?? 1,\n h: parts[3] ?? 1,\n };\n };\n\n const applyView = () => {\n const svg = inner.querySelector(\"svg\");\n if (!svg) return;\n svg.setAttribute(\"viewBox\", `${viewport.x} ${viewport.y} ${viewport.w} ${viewport.h}`);\n svg.setAttribute(\"preserveAspectRatio\", \"xMidYMid meet\");\n svg.style.width = \"100%\";\n svg.style.height = \"100%\";\n svg.style.display = \"block\";\n };\n\n const clientToView = (clientX: number, clientY: number): { x: number; y: number } => {\n const rect = wrapper.getBoundingClientRect();\n const nx = (clientX - rect.left) / rect.width;\n const ny = (clientY - rect.top) / rect.height;\n return {\n x: viewport.x + nx * viewport.w,\n y: viewport.y + ny * viewport.h,\n };\n };\n\n const zoomAt = (clientX: number, clientY: number, factor: number) => {\n const pt = clientToView(clientX, clientY);\n const minW = naturalView.w / MAX_ZOOM;\n const maxW = naturalView.w / MIN_ZOOM;\n const nextW = Math.min(maxW, Math.max(minW, viewport.w * factor));\n const ratio = nextW / viewport.w;\n const nextH = viewport.h * ratio;\n viewport = {\n x: pt.x - (pt.x - viewport.x) * ratio,\n y: pt.y - (pt.y - viewport.y) * ratio,\n w: nextW,\n h: nextH,\n };\n applyView();\n };\n\n const fitView = () => {\n const cw = wrapper.clientWidth;\n const ch = wrapper.clientHeight;\n if (!cw || !ch) return;\n const pad = 0.06;\n const contentW = naturalView.w * (1 + pad * 2);\n const contentH = naturalView.h * (1 + pad * 2);\n const contentAspect = contentW / contentH;\n const containerAspect = cw / ch;\n let w: number;\n let h: number;\n if (contentAspect > containerAspect) {\n w = contentW;\n h = w / containerAspect;\n } else {\n h = contentH;\n w = h * containerAspect;\n }\n viewport = {\n x: naturalView.x + naturalView.w / 2 - w / 2,\n y: naturalView.y + naturalView.h / 2 - h / 2,\n w,\n h,\n };\n applyView();\n };\n\n const render = async (src: string, opts?: Partial<InteractiveRenderOptions>) => {\n lastSource = src;\n if (opts) currentOptions = { ...currentOptions, ...opts };\n const prevRatio = hasPainted && naturalView.w > 0 ? viewport.w / naturalView.w : 1;\n const centerX = viewport.x + viewport.w / 2;\n const centerY = viewport.y + viewport.h / 2;\n const result = await renderPipeline(src, {\n ...currentOptions,\n theme: currentTheme,\n });\n inner.innerHTML = result.svg ?? \"\";\n const svg = inner.querySelector(\"svg\");\n animationPlayer.rebind(svg, result.graph ?? null);\n if (svg) {\n naturalView = parseViewBox(svg);\n if (!hasPainted) {\n hasPainted = true;\n // First paint: fit content to host (avoids 1×1 placeholder centering bug).\n fitView();\n if (\n (!wrapper.clientWidth || !wrapper.clientHeight) &&\n typeof ResizeObserver !== \"undefined\"\n ) {\n resizeObserver = new ResizeObserver(() => {\n if (wrapper.clientWidth && wrapper.clientHeight) {\n fitView();\n resizeObserver?.disconnect();\n resizeObserver = null;\n }\n });\n resizeObserver.observe(wrapper);\n }\n } else {\n const w = naturalView.w * prevRatio;\n const h = naturalView.h * prevRatio;\n viewport = {\n x: centerX - w / 2,\n y: centerY - h / 2,\n w,\n h,\n };\n applyView();\n }\n }\n return result;\n };\n\n const onWheel = (e: WheelEvent) => {\n if (!inner.querySelector(\"svg\")) return;\n e.preventDefault();\n const factor = e.deltaY > 0 ? 1.1 : 1 / 1.1;\n zoomAt(e.clientX, e.clientY, factor);\n };\n\n const onPointerDown = (e: PointerEvent) => {\n if (e.button === 0 || e.button === 1) {\n e.preventDefault();\n window.getSelection()?.removeAllRanges();\n isPanning = true;\n panOrigin = { ...viewport };\n panPointer = { x: e.clientX, y: e.clientY };\n wrapper.style.cursor = \"grabbing\";\n wrapper.setPointerCapture(e.pointerId);\n }\n };\n\n const onPointerMove = (e: PointerEvent) => {\n if (!isPanning) return;\n e.preventDefault();\n const dx = ((e.clientX - panPointer.x) / wrapper.clientWidth) * viewport.w;\n const dy = ((e.clientY - panPointer.y) / wrapper.clientHeight) * viewport.h;\n viewport = {\n ...viewport,\n x: panOrigin.x - dx,\n y: panOrigin.y - dy,\n };\n applyView();\n };\n\n const onPointerUp = (e: PointerEvent) => {\n if (isPanning) {\n isPanning = false;\n wrapper.style.cursor = \"grab\";\n wrapper.releasePointerCapture(e.pointerId);\n }\n };\n\n const onSelectStart = (e: Event) => {\n e.preventDefault();\n };\n\n wrapper.addEventListener(\"wheel\", onWheel, { passive: false });\n wrapper.addEventListener(\"pointerdown\", onPointerDown);\n wrapper.addEventListener(\"pointermove\", onPointerMove);\n wrapper.addEventListener(\"pointerup\", onPointerUp);\n wrapper.addEventListener(\"pointercancel\", onPointerUp);\n wrapper.addEventListener(\"selectstart\", onSelectStart);\n\n const readyPromise = render(source, options);\n\n return {\n async update(src: string, opts?: Partial<InteractiveRenderOptions>): Promise<RenderResult> {\n return render(src, opts);\n },\n async setTheme(theme: ThemeMode): Promise<RenderResult> {\n currentTheme = theme;\n wrapper.className = `kdiagram-viewport kdiagram-theme-${theme}`;\n applyLiveThemeTokens();\n return render(lastSource);\n },\n ready() {\n return readyPromise;\n },\n fit() {\n fitView();\n },\n zoomIn() {\n const rect = wrapper.getBoundingClientRect();\n zoomAt(rect.left + rect.width / 2, rect.top + rect.height / 2, 1 / 1.2);\n },\n zoomOut() {\n const rect = wrapper.getBoundingClientRect();\n zoomAt(rect.left + rect.width / 2, rect.top + rect.height / 2, 1.2);\n },\n resetView() {\n fitView();\n },\n animations: animationPlayer,\n destroy() {\n animationPlayer.destroy();\n resizeObserver?.disconnect();\n resizeObserver = null;\n wrapper.removeEventListener(\"wheel\", onWheel);\n wrapper.removeEventListener(\"pointerdown\", onPointerDown);\n wrapper.removeEventListener(\"pointermove\", onPointerMove);\n wrapper.removeEventListener(\"pointerup\", onPointerUp);\n wrapper.removeEventListener(\"pointercancel\", onPointerUp);\n wrapper.removeEventListener(\"selectstart\", onSelectStart);\n wrapper.remove();\n },\n };\n },\n};\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kekonic/diagrams",
|
|
3
|
+
"version": "1.0.0-rc.4",
|
|
4
|
+
"description": "Text-to-diagram SDK for architecture, events, workflows, sequences, and ERDs with measured automatic layout.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"architecture",
|
|
7
|
+
"diagram",
|
|
8
|
+
"elk",
|
|
9
|
+
"erd",
|
|
10
|
+
"sequence-diagram",
|
|
11
|
+
"svg",
|
|
12
|
+
"workflow"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://github.com/kekonic/diagrams#readme",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/kekonic/diagrams/issues"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/kekonic/diagrams.git",
|
|
22
|
+
"directory": "packages/diagrams"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"theme.css"
|
|
27
|
+
],
|
|
28
|
+
"type": "module",
|
|
29
|
+
"exports": {
|
|
30
|
+
".": {
|
|
31
|
+
"types": "./dist/index.d.mts",
|
|
32
|
+
"import": "./dist/index.mjs"
|
|
33
|
+
},
|
|
34
|
+
"./theme.css": "./theme.css"
|
|
35
|
+
},
|
|
36
|
+
"publishConfig": {
|
|
37
|
+
"access": "public"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@fontsource/inter": "^5.2.5",
|
|
41
|
+
"@iconify-json/carbon": "^1.2.25",
|
|
42
|
+
"@iconify-json/logos": "^1.2.12",
|
|
43
|
+
"@iconify-json/lucide": "^1.2.68",
|
|
44
|
+
"@iconify-json/mdi": "^1.2.3",
|
|
45
|
+
"@iconify-json/simple-icons": "^1.2.53",
|
|
46
|
+
"@kekonic/diagrams-core": "1.0.0-rc.4",
|
|
47
|
+
"@kekonic/diagrams-geometry": "1.0.0-rc.4",
|
|
48
|
+
"@kekonic/diagrams-icons": "1.0.0-rc.4",
|
|
49
|
+
"@kekonic/diagrams-layout": "1.0.0-rc.4",
|
|
50
|
+
"@kekonic/diagrams-render-svg": "1.0.0-rc.4",
|
|
51
|
+
"@kekonic/diagrams-routing": "1.0.0-rc.4",
|
|
52
|
+
"@kekonic/diagrams-theme": "1.0.0-rc.4"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@types/node": "^26",
|
|
56
|
+
"happy-dom": "^20.11.1",
|
|
57
|
+
"typescript": "^5",
|
|
58
|
+
"vitest": "^4"
|
|
59
|
+
},
|
|
60
|
+
"engines": {
|
|
61
|
+
"node": ">=22.18.0"
|
|
62
|
+
},
|
|
63
|
+
"scripts": {
|
|
64
|
+
"build": "vp pack",
|
|
65
|
+
"test": "vp test"
|
|
66
|
+
}
|
|
67
|
+
}
|