@zukhruf/diagram 0.3.33 → 0.3.34

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.
Files changed (117) hide show
  1. package/README.md +98 -52
  2. package/dist/index.d.ts +5 -3
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +1 -0
  5. package/dist/index.js.map +1 -1
  6. package/dist/lib/compiler/diagram-compile.d.ts +3 -4
  7. package/dist/lib/compiler/diagram-compile.d.ts.map +1 -1
  8. package/dist/lib/compiler/diagram-compile.js +85 -370
  9. package/dist/lib/compiler/diagram-compile.js.map +1 -1
  10. package/dist/lib/layouts/graph/attach.d.ts.map +1 -1
  11. package/dist/lib/layouts/graph/attach.js +64 -8
  12. package/dist/lib/layouts/graph/attach.js.map +1 -1
  13. package/dist/lib/layouts/graph/connections.d.ts +11 -4
  14. package/dist/lib/layouts/graph/connections.d.ts.map +1 -1
  15. package/dist/lib/layouts/graph/connections.js +43 -17
  16. package/dist/lib/layouts/graph/connections.js.map +1 -1
  17. package/dist/lib/layouts/graph/graph-layout-result.d.ts +4 -2
  18. package/dist/lib/layouts/graph/graph-layout-result.d.ts.map +1 -1
  19. package/dist/lib/layouts/graph/graph-layout-result.js.map +1 -1
  20. package/dist/lib/layouts/graph/gutters.js +40 -21
  21. package/dist/lib/layouts/graph/gutters.js.map +1 -1
  22. package/dist/lib/layouts/graph/labels.d.ts +16 -9
  23. package/dist/lib/layouts/graph/labels.d.ts.map +1 -1
  24. package/dist/lib/layouts/graph/labels.js +62 -18
  25. package/dist/lib/layouts/graph/labels.js.map +1 -1
  26. package/dist/lib/layouts/graph/layout.d.ts +1 -1
  27. package/dist/lib/layouts/graph/layout.d.ts.map +1 -1
  28. package/dist/lib/layouts/graph/layout.js +6 -3
  29. package/dist/lib/layouts/graph/layout.js.map +1 -1
  30. package/dist/lib/layouts/graph/measure.d.ts +8 -5
  31. package/dist/lib/layouts/graph/measure.d.ts.map +1 -1
  32. package/dist/lib/layouts/graph/measure.js +47 -9
  33. package/dist/lib/layouts/graph/measure.js.map +1 -1
  34. package/dist/lib/layouts/graph/min-heap.d.ts +1 -5
  35. package/dist/lib/layouts/graph/min-heap.d.ts.map +1 -1
  36. package/dist/lib/layouts/graph/min-heap.js +1 -5
  37. package/dist/lib/layouts/graph/min-heap.js.map +1 -1
  38. package/dist/lib/layouts/graph/node-content.d.ts +1 -1
  39. package/dist/lib/layouts/graph/node-content.d.ts.map +1 -1
  40. package/dist/lib/layouts/graph/node-content.js +26 -7
  41. package/dist/lib/layouts/graph/node-content.js.map +1 -1
  42. package/dist/lib/layouts/graph/path.d.ts +2 -10
  43. package/dist/lib/layouts/graph/path.d.ts.map +1 -1
  44. package/dist/lib/layouts/graph/path.js +11 -13
  45. package/dist/lib/layouts/graph/path.js.map +1 -1
  46. package/dist/lib/layouts/graph/round.d.ts +11 -0
  47. package/dist/lib/layouts/graph/round.d.ts.map +1 -0
  48. package/dist/lib/layouts/graph/round.js +181 -0
  49. package/dist/lib/layouts/graph/round.js.map +1 -0
  50. package/dist/lib/layouts/graph/route.d.ts +10 -6
  51. package/dist/lib/layouts/graph/route.d.ts.map +1 -1
  52. package/dist/lib/layouts/graph/route.js +68 -33
  53. package/dist/lib/layouts/graph/route.js.map +1 -1
  54. package/dist/lib/layouts/graph/sides.d.ts +10 -5
  55. package/dist/lib/layouts/graph/sides.d.ts.map +1 -1
  56. package/dist/lib/layouts/graph/sides.js +14 -7
  57. package/dist/lib/layouts/graph/sides.js.map +1 -1
  58. package/dist/lib/layouts/timeline/timeline-layout.d.ts +2 -1
  59. package/dist/lib/layouts/timeline/timeline-layout.d.ts.map +1 -1
  60. package/dist/lib/layouts/timeline/timeline-layout.js +9 -4
  61. package/dist/lib/layouts/timeline/timeline-layout.js.map +1 -1
  62. package/dist/lib/model/diagram-ir.d.ts +19 -156
  63. package/dist/lib/model/diagram-ir.d.ts.map +1 -1
  64. package/dist/lib/model/diagram-ir.js.map +1 -1
  65. package/dist/lib/model/validate-graph.d.ts +7 -0
  66. package/dist/lib/model/validate-graph.d.ts.map +1 -0
  67. package/dist/lib/model/validate-graph.js +54 -0
  68. package/dist/lib/model/validate-graph.js.map +1 -0
  69. package/dist/lib/react/Diagram.d.ts +3 -9
  70. package/dist/lib/react/Diagram.d.ts.map +1 -1
  71. package/dist/lib/react/Diagram.js +1 -13
  72. package/dist/lib/react/Diagram.js.map +1 -1
  73. package/dist/lib/react/diagram-types.d.ts +17 -46
  74. package/dist/lib/react/diagram-types.d.ts.map +1 -1
  75. package/dist/lib/react/diagram-types.js.map +1 -1
  76. package/dist/lib/renderers/canvas/graph-canvas.d.ts +2 -5
  77. package/dist/lib/renderers/canvas/graph-canvas.d.ts.map +1 -1
  78. package/dist/lib/renderers/canvas/graph-canvas.js +68 -43
  79. package/dist/lib/renderers/canvas/graph-canvas.js.map +1 -1
  80. package/dist/lib/renderers/html/graph-html.d.ts +2 -3
  81. package/dist/lib/renderers/html/graph-html.d.ts.map +1 -1
  82. package/dist/lib/renderers/html/graph-html.js +298 -289
  83. package/dist/lib/renderers/html/graph-html.js.map +1 -1
  84. package/dist/lib/renderers/shared/graph-parts.d.ts +3 -1
  85. package/dist/lib/renderers/shared/graph-parts.d.ts.map +1 -1
  86. package/dist/lib/renderers/shared/graph-parts.js +350 -418
  87. package/dist/lib/renderers/shared/graph-parts.js.map +1 -1
  88. package/dist/lib/renderers/shared/node-parts.d.ts +5 -6
  89. package/dist/lib/renderers/shared/node-parts.d.ts.map +1 -1
  90. package/dist/lib/renderers/shared/node-parts.js +112 -190
  91. package/dist/lib/renderers/shared/node-parts.js.map +1 -1
  92. package/dist/lib/renderers/shared/run-spans.js +2 -2
  93. package/dist/lib/renderers/shared/run-spans.js.map +1 -1
  94. package/dist/lib/renderers/shared/text-runs.d.ts +0 -6
  95. package/dist/lib/renderers/shared/text-runs.d.ts.map +1 -1
  96. package/dist/lib/renderers/shared/text-runs.js +0 -12
  97. package/dist/lib/renderers/shared/text-runs.js.map +1 -1
  98. package/dist/lib/renderers/svg/graph-svg.d.ts +1 -3
  99. package/dist/lib/renderers/svg/graph-svg.d.ts.map +1 -1
  100. package/dist/lib/renderers/svg/graph-svg.js +66 -80
  101. package/dist/lib/renderers/svg/graph-svg.js.map +1 -1
  102. package/dist/lib/renderers/svg/timeline-svg.d.ts.map +1 -1
  103. package/dist/lib/renderers/svg/timeline-svg.js +7 -5
  104. package/dist/lib/renderers/svg/timeline-svg.js.map +1 -1
  105. package/package.json +1 -1
  106. package/dist/lib/layouts/graph/graph-layout.d.ts +0 -154
  107. package/dist/lib/layouts/graph/graph-layout.d.ts.map +0 -1
  108. package/dist/lib/layouts/graph/graph-layout.js +0 -2340
  109. package/dist/lib/layouts/graph/graph-layout.js.map +0 -1
  110. package/dist/lib/layouts/graph/legacy-graph-layout.d.ts +0 -6
  111. package/dist/lib/layouts/graph/legacy-graph-layout.d.ts.map +0 -1
  112. package/dist/lib/layouts/graph/legacy-graph-layout.js +0 -542
  113. package/dist/lib/layouts/graph/legacy-graph-layout.js.map +0 -1
  114. package/dist/lib/layouts/text-metrics.d.ts +0 -7
  115. package/dist/lib/layouts/text-metrics.d.ts.map +0 -1
  116. package/dist/lib/layouts/text-metrics.js +0 -40
  117. package/dist/lib/layouts/text-metrics.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"node-content.js","names":["labelLines","textBlock","LAYOUT_TOKENS","CONNECTOR_PAD","x","y","CONNECTOR_MIN_HEIGHT","NOTHING","text","bullets","nodeContent","node","kind","junctionContent","markerContent","connectorContent","applianceContent","noteContent","boxContent","pad","frame","LABEL_GAP","PAD_X","PAD_Y","isCard","textAlign","description","undefined","items","length","cardContent","icon","iconRowContent","lines","label","textColor","fonts","boxLabel","w","h","place","inner","centreX","centredTop","ICON","ICON_GAP","title","Math","max","size","BLOCK_GAP","BULLET_INDENT","body","iconW","headerH","sections","filter","section","bulletRise","map","reduce","sum","top","next","at","headerTop","descriptionTop","itemsTop","itemRuns","run","note","MARKER_ICON","marker","gap","cx","CONNECTOR_ICON","connector","cy","JUNCTION","APPLIANCE","appliance","glyph","applianceGlyph","bodyX","bodyY","min","bodyW","bodyH","slant","mastX","antenna","jackCount","floor","appliancePorts","jackSpacing","jacks","Array","from","_","index","face","parts","box"],"sources":["../../../../src/lib/layouts/graph/node-content.ts"],"sourcesContent":["import type { Box, DiagramNode, Point } from '../../model/diagram-ir.ts';\nimport type { NodeLayout } from './graph-layout-result.ts';\nimport { labelLines, textBlock } from './text-block.ts';\nimport { LAYOUT_TOKENS } from './tokens.ts';\n\nexport type ContentPlacement = Pick<NodeLayout, 'text' | 'bullets'> &\n Partial<Pick<NodeLayout, 'icon' | 'appliance'>>;\n\n/** What a node draws inside its frame: its measured size, the padding around it, and where it goes. */\nexport type NodeContent = {\n w: number;\n h: number;\n pad: { x: number; y: number };\n place(inner: Box): ContentPlacement;\n};\n\n/** Mirrors the connector pill drawn before content sizing: 10px side inset, 4px above and below the text, 28px tall at least. */\nconst CONNECTOR_PAD = { x: 10, y: 4 };\nconst CONNECTOR_MIN_HEIGHT = 28;\n\nconst NOTHING: ContentPlacement = { text: [], bullets: [] };\n\nexport function nodeContent(node: DiagramNode): NodeContent {\n switch (node.kind) {\n case 'junction':\n return junctionContent();\n case 'marker':\n return markerContent(node);\n case 'connector':\n return connectorContent(node);\n case 'appliance':\n return applianceContent(node);\n case 'note':\n return noteContent(node);\n default:\n return boxContent(node);\n }\n}\n\nfunction boxContent(node: DiagramNode): NodeContent {\n const pad =\n node.frame === 'none'\n ? { x: LAYOUT_TOKENS.LABEL_GAP, y: LAYOUT_TOKENS.LABEL_GAP }\n : { x: LAYOUT_TOKENS.PAD_X, y: LAYOUT_TOKENS.PAD_Y };\n const isCard =\n node.textAlign === 'start' ||\n node.description !== undefined ||\n (node.items?.length ?? 0) > 0;\n if (isCard) return { ...cardContent(node), pad };\n if (node.icon) return { ...iconRowContent(node), pad };\n const lines = textBlock(\n labelLines(node.label, node.textColor),\n LAYOUT_TOKENS.fonts.boxLabel,\n );\n return {\n w: lines.w,\n h: lines.h,\n pad,\n place: (inner) => ({\n text: lines.place(centreX(inner), centredTop(inner, lines.h), 'middle'),\n bullets: [],\n }),\n };\n}\n\nfunction iconRowContent(node: DiagramNode): Omit<NodeContent, 'pad'> {\n const { ICON, ICON_GAP } = LAYOUT_TOKENS;\n const title = textBlock(\n labelLines(node.label, node.textColor),\n LAYOUT_TOKENS.fonts.title,\n );\n const w = title.w > 0 ? ICON + ICON_GAP + title.w : ICON;\n const h = Math.max(ICON, title.h);\n return {\n w,\n h,\n place: (inner) => {\n const x = inner.x + (inner.w - w) / 2;\n const y = centredTop(inner, h);\n return {\n icon: { x, y: y + (h - ICON) / 2, size: ICON },\n text: title.place(x + ICON + ICON_GAP, y + (h - title.h) / 2, 'start'),\n bullets: [],\n };\n },\n };\n}\n\nfunction cardContent(node: DiagramNode): Omit<NodeContent, 'pad'> {\n const { ICON, ICON_GAP, BLOCK_GAP, BULLET_INDENT } = LAYOUT_TOKENS;\n const title = textBlock(\n labelLines(node.label, node.textColor),\n LAYOUT_TOKENS.fonts.title,\n );\n const description = textBlock(\n labelLines(node.description, node.textColor),\n LAYOUT_TOKENS.fonts.body,\n );\n const items = textBlock(\n labelLines(node.items, node.textColor),\n LAYOUT_TOKENS.fonts.body,\n );\n let iconW = 0;\n if (node.icon) iconW = title.w > 0 ? ICON + ICON_GAP : ICON;\n const headerH = Math.max(node.icon ? ICON : 0, title.h);\n const sections = [\n { h: headerH, w: iconW + title.w },\n { h: description.h, w: description.w },\n { h: items.h, w: items.h > 0 ? BULLET_INDENT + items.w : 0 },\n ].filter((section) => section.h > 0);\n const bulletRise = LAYOUT_TOKENS.fonts.body.size * 0.3;\n return {\n w: Math.max(0, ...sections.map((section) => section.w)),\n h:\n sections.reduce((sum, section) => sum + section.h, 0) +\n Math.max(0, sections.length - 1) * BLOCK_GAP,\n place: (inner) => {\n let top = inner.y;\n const next = (h: number) => {\n const at = top;\n if (h > 0) top += h + BLOCK_GAP;\n return at;\n };\n const headerTop = next(headerH);\n const descriptionTop = next(description.h);\n const itemsTop = next(items.h);\n const itemRuns = items.place(inner.x + BULLET_INDENT, itemsTop, 'start');\n return {\n ...(node.icon\n ? {\n icon: {\n x: inner.x,\n y: headerTop + (headerH - ICON) / 2,\n size: ICON,\n },\n }\n : {}),\n text: [\n ...title.place(\n inner.x + iconW,\n headerTop + (headerH - title.h) / 2,\n 'start',\n ),\n ...description.place(inner.x, descriptionTop, 'start'),\n ...itemRuns,\n ],\n bullets: itemRuns.map((run) => ({\n x: inner.x + BULLET_INDENT / 4,\n y: run.y - bulletRise,\n })),\n };\n },\n };\n}\n\nfunction noteContent(node: DiagramNode): NodeContent {\n const lines = textBlock(\n labelLines(node.label, node.textColor ?? 'dim'),\n LAYOUT_TOKENS.fonts.note,\n );\n return {\n w: lines.w,\n h: lines.h,\n pad: { x: LAYOUT_TOKENS.LABEL_GAP, y: LAYOUT_TOKENS.LABEL_GAP },\n place: (inner) => ({\n text: lines.place(inner.x, inner.y, 'start'),\n bullets: [],\n }),\n };\n}\n\nfunction markerContent(node: DiagramNode): NodeContent {\n const { MARKER_ICON, BLOCK_GAP } = LAYOUT_TOKENS;\n const lines = textBlock(\n labelLines(node.label, node.textColor),\n LAYOUT_TOKENS.fonts.marker,\n );\n const gap = lines.h > 0 ? BLOCK_GAP : 0;\n const h = MARKER_ICON + gap + lines.h;\n return {\n w: Math.max(MARKER_ICON, lines.w),\n h,\n pad: { x: LAYOUT_TOKENS.LABEL_GAP, y: LAYOUT_TOKENS.LABEL_GAP },\n place: (inner) => {\n const top = centredTop(inner, h);\n const cx = centreX(inner);\n return {\n icon: { x: cx - MARKER_ICON / 2, y: top, size: MARKER_ICON },\n text: lines.place(cx, top + MARKER_ICON + gap, 'middle'),\n bullets: [],\n };\n },\n };\n}\n\nfunction connectorContent(node: DiagramNode): NodeContent {\n const { CONNECTOR_ICON, BLOCK_GAP } = LAYOUT_TOKENS;\n const lines = textBlock(\n labelLines(node.label, node.textColor),\n LAYOUT_TOKENS.fonts.connector,\n );\n const iconW = node.icon ? CONNECTOR_ICON + (lines.w > 0 ? BLOCK_GAP : 0) : 0;\n const h = Math.max(CONNECTOR_MIN_HEIGHT - 2 * CONNECTOR_PAD.y, lines.h);\n return {\n w: iconW + lines.w,\n h,\n pad: CONNECTOR_PAD,\n place: (inner) => {\n const cy = inner.y + inner.h / 2;\n const top = cy - lines.h / 2;\n if (!node.icon) {\n return {\n text: lines.place(centreX(inner), top, 'middle'),\n bullets: [],\n };\n }\n return {\n icon: { x: inner.x, y: cy - CONNECTOR_ICON / 2, size: CONNECTOR_ICON },\n text: lines.place(inner.x + iconW, top, 'start'),\n bullets: [],\n };\n },\n };\n}\n\nfunction junctionContent(): NodeContent {\n return {\n w: LAYOUT_TOKENS.JUNCTION,\n h: LAYOUT_TOKENS.JUNCTION,\n pad: { x: 0, y: 0 },\n place: () => NOTHING,\n };\n}\n\nfunction applianceContent(node: DiagramNode): NodeContent {\n const { APPLIANCE, LABEL_GAP } = LAYOUT_TOKENS;\n const lines = textBlock(\n labelLines(node.label, node.textColor),\n LAYOUT_TOKENS.fonts.appliance,\n );\n return {\n w: Math.max(APPLIANCE.w, lines.w + 2 * LABEL_GAP),\n h: APPLIANCE.h + (lines.h > 0 ? lines.h + LABEL_GAP : 0),\n pad: { x: 0, y: 0 },\n place: (inner) => {\n const glyph = {\n x: centreX(inner) - APPLIANCE.w / 2,\n y: inner.y,\n ...APPLIANCE,\n };\n return {\n appliance: applianceGlyph(node, glyph),\n text: lines.place(centreX(inner), glyph.y + glyph.h, 'middle'),\n bullets: [],\n };\n },\n };\n}\n\n/** The router glyph: a slanted body, an optional antenna and a row of jacks, as the renderers drew it before content sizing. */\nfunction applianceGlyph(\n node: DiagramNode,\n glyph: Box,\n): NonNullable<NodeLayout['appliance']> {\n const bodyX = glyph.x + 4;\n const bodyY = glyph.y + Math.max(12, Math.min(22, glyph.h * 0.28));\n const bodyW = glyph.w - 8;\n const bodyH = glyph.h - (bodyY - glyph.y) - 12;\n const slant = Math.max(4, Math.min(16, bodyW * 0.28, bodyH * 0.75));\n const body: Point[] = [\n { x: bodyX + slant, y: bodyY },\n { x: bodyX + bodyW, y: bodyY + 6 },\n { x: bodyX + bodyW - slant, y: bodyY + bodyH },\n { x: bodyX, y: bodyY + bodyH - 6 },\n ];\n const mastX = bodyX + slant + bodyW * 0.2;\n const antenna: [Point, Point][] =\n (node.antenna ?? true)\n ? [\n [\n { x: bodyX + slant + bodyW * 0.18, y: bodyY + 1 },\n { x: mastX - 3, y: glyph.y + 3 },\n ],\n [\n { x: mastX + 1, y: bodyY + 2 },\n { x: mastX + 1, y: glyph.y + 8 },\n ],\n ]\n : [];\n const jackCount = Math.max(0, Math.floor(node.appliancePorts ?? 4));\n const jackSpacing = Math.min(\n 13,\n Math.max(8, (bodyW - slant - 42) / Math.max(jackCount, 1)),\n );\n const jacks = Array.from({ length: jackCount }, (_, index) => ({\n x: bodyX + slant + 16 + index * jackSpacing,\n y: bodyY + bodyH - 15,\n w: 5,\n h: 12,\n }));\n const face: [Point, Point] = [\n { x: bodyX + slant, y: bodyY + bodyH - 1 },\n { x: bodyX + bodyW - slant, y: bodyY + bodyH + 3 },\n ];\n // Through a variable, not a literal, so the return skips the excess-property check against NodeLayout['appliance'].\n const parts = { body, face, antenna, jacks };\n return parts;\n}\n\nfunction centreX(box: Box): number {\n return box.x + box.w / 2;\n}\n\nfunction centredTop(box: Box, h: number): number {\n return box.y + (box.h - h) / 2;\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"node-content.js","names":["labelLines","textBlock","LAYOUT_TOKENS","CONNECTOR_PAD","x","y","CONNECTOR_MIN_HEIGHT","NOTHING","text","bullets","nodeContent","node","kind","junctionContent","markerContent","connectorContent","applianceContent","noteContent","boxContent","pad","frame","LABEL_GAP","PAD_X","PAD_Y","isCard","textAlign","description","undefined","items","length","cardContent","icon","iconRowContent","labelContent","content","withReactContent","size","lines","label","textColor","fonts","boxLabel","w","h","place","inner","centreX","centredTop","gap","BLOCK_GAP","Math","max","contentBox","ICON","ICON_GAP","title","BULLET_INDENT","body","iconW","headerH","sections","filter","section","bulletRise","map","reduce","sum","top","next","at","headerTop","descriptionTop","itemsTop","itemRuns","run","note","MARKER_ICON","marker","cx","CONNECTOR_ICON","connector","cy","JUNCTION","APPLIANCE","appliance","glyph","applianceGlyph","bodyX","bodyY","min","bodyW","bodyH","slant","mastX","antenna","jackCount","floor","appliancePorts","jackSpacing","jacks","Array","from","_","index","face","parts","box"],"sources":["../../../../src/lib/layouts/graph/node-content.ts"],"sourcesContent":["import type { Box, DiagramNode, Point } from '../../model/diagram-ir.ts';\nimport type { NodeLayout } from './graph-layout-result.ts';\nimport { labelLines, textBlock } from './text-block.ts';\nimport { LAYOUT_TOKENS } from './tokens.ts';\n\nexport type ContentPlacement = Pick<NodeLayout, 'text' | 'bullets'> &\n Partial<Pick<NodeLayout, 'icon' | 'appliance' | 'contentBox'>>;\n\n/** What a node draws inside its frame: its measured size, the padding around it, and where it goes. */\nexport type NodeContent = {\n w: number;\n h: number;\n pad: { x: number; y: number };\n place(inner: Box): ContentPlacement;\n};\n\n/** Mirrors the connector pill drawn before content sizing: 10px side inset, 4px above and below the text, 28px tall at least. */\nconst CONNECTOR_PAD = { x: 10, y: 4 };\nconst CONNECTOR_MIN_HEIGHT = 28;\n\nconst NOTHING: ContentPlacement = { text: [], bullets: [] };\n\nexport function nodeContent(node: DiagramNode): NodeContent {\n switch (node.kind) {\n case 'junction':\n return junctionContent();\n case 'marker':\n return markerContent(node);\n case 'connector':\n return connectorContent(node);\n case 'appliance':\n return applianceContent(node);\n case 'note':\n return noteContent(node);\n default:\n return boxContent(node);\n }\n}\n\nfunction boxContent(node: DiagramNode): NodeContent {\n const pad =\n node.frame === 'none'\n ? { x: LAYOUT_TOKENS.LABEL_GAP, y: LAYOUT_TOKENS.LABEL_GAP }\n : { x: LAYOUT_TOKENS.PAD_X, y: LAYOUT_TOKENS.PAD_Y };\n const isCard =\n node.textAlign === 'start' ||\n node.description !== undefined ||\n (node.items?.length ?? 0) > 0;\n let text: Omit<NodeContent, 'pad'>;\n if (isCard) text = cardContent(node);\n else if (node.icon) text = iconRowContent(node);\n else text = labelContent(node);\n return {\n ...(node.content ? withReactContent(text, node.content.size) : text),\n pad,\n };\n}\n\nfunction labelContent(node: DiagramNode): Omit<NodeContent, 'pad'> {\n const lines = textBlock(\n labelLines(node.label, node.textColor),\n LAYOUT_TOKENS.fonts.boxLabel,\n );\n return {\n w: lines.w,\n h: lines.h,\n place: (inner) => ({\n text: lines.place(centreX(inner), centredTop(inner, lines.h), 'middle'),\n bullets: [],\n }),\n };\n}\n\n/** The author's React content goes under the text, centred, in a box of the size the author gives. */\nfunction withReactContent(\n text: Omit<NodeContent, 'pad'>,\n size: { w: number; h: number },\n): Omit<NodeContent, 'pad'> {\n const gap = text.h > 0 ? LAYOUT_TOKENS.BLOCK_GAP : 0;\n return {\n w: Math.max(text.w, size.w),\n h: text.h + gap + size.h,\n place: (inner) => ({\n ...text.place({ ...inner, h: inner.h - gap - size.h }),\n contentBox: {\n x: centreX(inner) - size.w / 2,\n y: inner.y + inner.h - size.h,\n ...size,\n },\n }),\n };\n}\n\nfunction iconRowContent(node: DiagramNode): Omit<NodeContent, 'pad'> {\n const { ICON, ICON_GAP } = LAYOUT_TOKENS;\n const title = textBlock(\n labelLines(node.label, node.textColor),\n LAYOUT_TOKENS.fonts.title,\n );\n const w = title.w > 0 ? ICON + ICON_GAP + title.w : ICON;\n const h = Math.max(ICON, title.h);\n return {\n w,\n h,\n place: (inner) => {\n const x = inner.x + (inner.w - w) / 2;\n const y = centredTop(inner, h);\n return {\n icon: { x, y: y + (h - ICON) / 2, size: ICON },\n text: title.place(x + ICON + ICON_GAP, y + (h - title.h) / 2, 'start'),\n bullets: [],\n };\n },\n };\n}\n\nfunction cardContent(node: DiagramNode): Omit<NodeContent, 'pad'> {\n const { ICON, ICON_GAP, BLOCK_GAP, BULLET_INDENT } = LAYOUT_TOKENS;\n const title = textBlock(\n labelLines(node.label, node.textColor),\n LAYOUT_TOKENS.fonts.title,\n );\n const description = textBlock(\n labelLines(node.description, node.textColor),\n LAYOUT_TOKENS.fonts.body,\n );\n const items = textBlock(\n labelLines(node.items, node.textColor),\n LAYOUT_TOKENS.fonts.body,\n );\n let iconW = 0;\n if (node.icon) iconW = title.w > 0 ? ICON + ICON_GAP : ICON;\n const headerH = Math.max(node.icon ? ICON : 0, title.h);\n const sections = [\n { h: headerH, w: iconW + title.w },\n { h: description.h, w: description.w },\n { h: items.h, w: items.h > 0 ? BULLET_INDENT + items.w : 0 },\n ].filter((section) => section.h > 0);\n const bulletRise = LAYOUT_TOKENS.fonts.body.size * 0.3;\n return {\n w: Math.max(0, ...sections.map((section) => section.w)),\n h:\n sections.reduce((sum, section) => sum + section.h, 0) +\n Math.max(0, sections.length - 1) * BLOCK_GAP,\n place: (inner) => {\n let top = inner.y;\n const next = (h: number) => {\n const at = top;\n if (h > 0) top += h + BLOCK_GAP;\n return at;\n };\n const headerTop = next(headerH);\n const descriptionTop = next(description.h);\n const itemsTop = next(items.h);\n const itemRuns = items.place(inner.x + BULLET_INDENT, itemsTop, 'start');\n return {\n ...(node.icon\n ? {\n icon: {\n x: inner.x,\n y: headerTop + (headerH - ICON) / 2,\n size: ICON,\n },\n }\n : {}),\n text: [\n ...title.place(\n inner.x + iconW,\n headerTop + (headerH - title.h) / 2,\n 'start',\n ),\n ...description.place(inner.x, descriptionTop, 'start'),\n ...itemRuns,\n ],\n bullets: itemRuns.map((run) => ({\n x: inner.x + BULLET_INDENT / 4,\n y: run.y - bulletRise,\n })),\n };\n },\n };\n}\n\nfunction noteContent(node: DiagramNode): NodeContent {\n const lines = textBlock(\n labelLines(node.label, node.textColor ?? 'dim'),\n LAYOUT_TOKENS.fonts.note,\n );\n return {\n w: lines.w,\n h: lines.h,\n pad: { x: LAYOUT_TOKENS.LABEL_GAP, y: LAYOUT_TOKENS.LABEL_GAP },\n place: (inner) => ({\n text: lines.place(inner.x, inner.y, 'start'),\n bullets: [],\n }),\n };\n}\n\nfunction markerContent(node: DiagramNode): NodeContent {\n const { MARKER_ICON, BLOCK_GAP } = LAYOUT_TOKENS;\n const lines = textBlock(\n labelLines(node.label, node.textColor),\n LAYOUT_TOKENS.fonts.marker,\n );\n const gap = lines.h > 0 ? BLOCK_GAP : 0;\n const h = MARKER_ICON + gap + lines.h;\n return {\n w: Math.max(MARKER_ICON, lines.w),\n h,\n pad: { x: LAYOUT_TOKENS.LABEL_GAP, y: LAYOUT_TOKENS.LABEL_GAP },\n place: (inner) => {\n const top = centredTop(inner, h);\n const cx = centreX(inner);\n return {\n icon: { x: cx - MARKER_ICON / 2, y: top, size: MARKER_ICON },\n text: lines.place(cx, top + MARKER_ICON + gap, 'middle'),\n bullets: [],\n };\n },\n };\n}\n\nfunction connectorContent(node: DiagramNode): NodeContent {\n const { CONNECTOR_ICON, BLOCK_GAP } = LAYOUT_TOKENS;\n const lines = textBlock(\n labelLines(node.label, node.textColor),\n LAYOUT_TOKENS.fonts.connector,\n );\n const iconW = node.icon ? CONNECTOR_ICON + (lines.w > 0 ? BLOCK_GAP : 0) : 0;\n const h = Math.max(CONNECTOR_MIN_HEIGHT - 2 * CONNECTOR_PAD.y, lines.h);\n return {\n w: iconW + lines.w,\n h,\n pad: CONNECTOR_PAD,\n place: (inner) => {\n const cy = inner.y + inner.h / 2;\n const top = cy - lines.h / 2;\n if (!node.icon) {\n return {\n text: lines.place(centreX(inner), top, 'middle'),\n bullets: [],\n };\n }\n return {\n icon: { x: inner.x, y: cy - CONNECTOR_ICON / 2, size: CONNECTOR_ICON },\n text: lines.place(inner.x + iconW, top, 'start'),\n bullets: [],\n };\n },\n };\n}\n\nfunction junctionContent(): NodeContent {\n return {\n w: LAYOUT_TOKENS.JUNCTION,\n h: LAYOUT_TOKENS.JUNCTION,\n pad: { x: 0, y: 0 },\n place: () => NOTHING,\n };\n}\n\nfunction applianceContent(node: DiagramNode): NodeContent {\n const { APPLIANCE, LABEL_GAP } = LAYOUT_TOKENS;\n const lines = textBlock(\n labelLines(node.label, node.textColor),\n LAYOUT_TOKENS.fonts.appliance,\n );\n return {\n w: Math.max(APPLIANCE.w, lines.w + 2 * LABEL_GAP),\n h: APPLIANCE.h + (lines.h > 0 ? lines.h + LABEL_GAP : 0),\n pad: { x: 0, y: 0 },\n place: (inner) => {\n const glyph = {\n x: centreX(inner) - APPLIANCE.w / 2,\n y: inner.y,\n ...APPLIANCE,\n };\n return {\n appliance: applianceGlyph(node, glyph),\n text: lines.place(centreX(inner), glyph.y + glyph.h, 'middle'),\n bullets: [],\n };\n },\n };\n}\n\n/** The router glyph: a slanted body, an optional antenna and a row of jacks, as the renderers drew it before content sizing. */\nfunction applianceGlyph(\n node: DiagramNode,\n glyph: Box,\n): NonNullable<NodeLayout['appliance']> {\n const bodyX = glyph.x + 4;\n const bodyY = glyph.y + Math.max(12, Math.min(22, glyph.h * 0.28));\n const bodyW = glyph.w - 8;\n const bodyH = glyph.h - (bodyY - glyph.y) - 12;\n const slant = Math.max(4, Math.min(16, bodyW * 0.28, bodyH * 0.75));\n const body: Point[] = [\n { x: bodyX + slant, y: bodyY },\n { x: bodyX + bodyW, y: bodyY + 6 },\n { x: bodyX + bodyW - slant, y: bodyY + bodyH },\n { x: bodyX, y: bodyY + bodyH - 6 },\n ];\n const mastX = bodyX + slant + bodyW * 0.2;\n const antenna: [Point, Point][] =\n (node.antenna ?? true)\n ? [\n [\n { x: bodyX + slant + bodyW * 0.18, y: bodyY + 1 },\n { x: mastX - 3, y: glyph.y + 3 },\n ],\n [\n { x: mastX + 1, y: bodyY + 2 },\n { x: mastX + 1, y: glyph.y + 8 },\n ],\n ]\n : [];\n const jackCount = Math.max(0, Math.floor(node.appliancePorts ?? 4));\n const jackSpacing = Math.min(\n 13,\n Math.max(8, (bodyW - slant - 42) / Math.max(jackCount, 1)),\n );\n const jacks = Array.from({ length: jackCount }, (_, index) => ({\n x: bodyX + slant + 16 + index * jackSpacing,\n y: bodyY + bodyH - 15,\n w: 5,\n h: 12,\n }));\n const face: [Point, Point] = [\n { x: bodyX + slant, y: bodyY + bodyH - 1 },\n { x: bodyX + bodyW - slant, y: bodyY + bodyH + 3 },\n ];\n // Through a variable, not a literal, so the return skips the excess-property check against NodeLayout['appliance'].\n const parts = { body, face, antenna, jacks };\n return parts;\n}\n\nfunction centreX(box: Box): number {\n return box.x + box.w / 2;\n}\n\nfunction centredTop(box: Box, h: number): number {\n return box.y + (box.h - h) / 2;\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,14 +1,6 @@
1
1
  import type { Point } from '../../model/diagram-ir.ts';
2
- /**
3
- * Drops every point that lies on the straight line through its neighbours.
4
- *
5
- * Moved from graph-layout.ts, whose copy step 6 deletes with the old engine.
6
- */
2
+ /** Drops every point that lies on the straight line through its neighbours. */
7
3
  export declare function simplifyPath(path: Point[]): Point[];
8
- /**
9
- * An SVG path through the points, with each bend rounded.
10
- *
11
- * Moved from graph-layout.ts, whose copy step 6 deletes with the old engine.
12
- */
4
+ /** An SVG path through the points, with each bend rounded, and each number to the layout's precision. */
13
5
  export declare function pathToSvg(points: Point[]): string;
14
6
  //# sourceMappingURL=path.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../../../src/lib/layouts/graph/path.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAKvD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,CAanD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAwBjD"}
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../../../src/lib/layouts/graph/path.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAMvD,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,CAanD;AAED,yGAAyG;AACzG,wBAAgB,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAsBjD"}
@@ -1,11 +1,9 @@
1
+ import { round } from "./round.js";
2
+
1
3
  /** The radius of the rounded corner the SVG path draws at each bend. */
2
4
  const CORNER_RADIUS = 8;
3
5
 
4
- /**
5
- * Drops every point that lies on the straight line through its neighbours.
6
- *
7
- * Moved from graph-layout.ts, whose copy step 6 deletes with the old engine.
8
- */
6
+ /** Drops every point that lies on the straight line through its neighbours. */
9
7
  export function simplifyPath(path) {
10
8
  if (path.length < 3) return path;
11
9
  const result = [path[0]];
@@ -19,15 +17,15 @@ export function simplifyPath(path) {
19
17
  return result;
20
18
  }
21
19
 
22
- /**
23
- * An SVG path through the points, with each bend rounded.
24
- *
25
- * Moved from graph-layout.ts, whose copy step 6 deletes with the old engine.
26
- */
20
+ /** An SVG path through the points, with each bend rounded, and each number to the layout's precision. */
27
21
  export function pathToSvg(points) {
28
22
  const [first, ...rest] = points;
29
23
  if (!first) return '';
30
- const parts = [`M ${first.x} ${first.y}`];
24
+ const at = ({
25
+ x,
26
+ y
27
+ }) => `${round(x)} ${round(y)}`;
28
+ const parts = [`M ${at(first)}`];
31
29
  for (const [index, current] of rest.slice(0, -1).entries()) {
32
30
  const previous = points[index];
33
31
  const next = points[index + 2];
@@ -46,10 +44,10 @@ export function pathToSvg(points) {
46
44
  x: current.x + dnx / ln * r,
47
45
  y: current.y + dny / ln * r
48
46
  };
49
- parts.push(`L ${cs.x} ${cs.y}`, `Q ${current.x} ${current.y} ${ce.x} ${ce.y}`);
47
+ parts.push(`L ${at(cs)}`, `Q ${at(current)} ${at(ce)}`);
50
48
  }
51
49
  const last = rest.at(-1);
52
- if (last) parts.push(`L ${last.x} ${last.y}`);
50
+ if (last) parts.push(`L ${at(last)}`);
53
51
  return parts.join(' ');
54
52
  }
55
53
  //# sourceMappingURL=path.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"path.js","names":["CORNER_RADIUS","simplifyPath","path","length","result","index","current","slice","entries","previous","at","next","cross","x","y","push","pathToSvg","points","first","rest","parts","dpx","dpy","dnx","dny","lp","Math","hypot","ln","r","min","cs","ce","last","join"],"sources":["../../../../src/lib/layouts/graph/path.ts"],"sourcesContent":["import type { Point } from '../../model/diagram-ir.ts';\n\n/** The radius of the rounded corner the SVG path draws at each bend. */\nconst CORNER_RADIUS = 8;\n\n/**\n * Drops every point that lies on the straight line through its neighbours.\n *\n * Moved from graph-layout.ts, whose copy step 6 deletes with the old engine.\n */\nexport function simplifyPath(path: Point[]): Point[] {\n if (path.length < 3) return path;\n const result: Point[] = [path[0]!];\n for (const [index, current] of path.slice(1, -1).entries()) {\n const previous = result.at(-1)!;\n const next = path[index + 2]!;\n const cross =\n (current.x - previous.x) * (next.y - current.y) -\n (current.y - previous.y) * (next.x - current.x);\n if (cross !== 0) result.push(current);\n }\n result.push(path.at(-1)!);\n return result;\n}\n\n/**\n * An SVG path through the points, with each bend rounded.\n *\n * Moved from graph-layout.ts, whose copy step 6 deletes with the old engine.\n */\nexport function pathToSvg(points: Point[]): string {\n const [first, ...rest] = points;\n if (!first) return '';\n const parts = [`M ${first.x} ${first.y}`];\n for (const [index, current] of rest.slice(0, -1).entries()) {\n const previous = points[index]!;\n const next = points[index + 2]!;\n const dpx = current.x - previous.x;\n const dpy = current.y - previous.y;\n const dnx = next.x - current.x;\n const dny = next.y - current.y;\n const lp = Math.hypot(dpx, dpy);\n const ln = Math.hypot(dnx, dny);\n const r = Math.min(CORNER_RADIUS, lp / 2, ln / 2);\n const cs = { x: current.x - (dpx / lp) * r, y: current.y - (dpy / lp) * r };\n const ce = { x: current.x + (dnx / ln) * r, y: current.y + (dny / ln) * r };\n parts.push(\n `L ${cs.x} ${cs.y}`,\n `Q ${current.x} ${current.y} ${ce.x} ${ce.y}`,\n );\n }\n const last = rest.at(-1);\n if (last) parts.push(`L ${last.x} ${last.y}`);\n return parts.join(' ');\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"path.js","names":["round","CORNER_RADIUS","simplifyPath","path","length","result","index","current","slice","entries","previous","at","next","cross","x","y","push","pathToSvg","points","first","rest","parts","dpx","dpy","dnx","dny","lp","Math","hypot","ln","r","min","cs","ce","last","join"],"sources":["../../../../src/lib/layouts/graph/path.ts"],"sourcesContent":["import type { Point } from '../../model/diagram-ir.ts';\nimport { round } from './round.ts';\n\n/** The radius of the rounded corner the SVG path draws at each bend. */\nconst CORNER_RADIUS = 8;\n\n/** Drops every point that lies on the straight line through its neighbours. */\nexport function simplifyPath(path: Point[]): Point[] {\n if (path.length < 3) return path;\n const result: Point[] = [path[0]!];\n for (const [index, current] of path.slice(1, -1).entries()) {\n const previous = result.at(-1)!;\n const next = path[index + 2]!;\n const cross =\n (current.x - previous.x) * (next.y - current.y) -\n (current.y - previous.y) * (next.x - current.x);\n if (cross !== 0) result.push(current);\n }\n result.push(path.at(-1)!);\n return result;\n}\n\n/** An SVG path through the points, with each bend rounded, and each number to the layout's precision. */\nexport function pathToSvg(points: Point[]): string {\n const [first, ...rest] = points;\n if (!first) return '';\n const at = ({ x, y }: Point) => `${round(x)} ${round(y)}`;\n const parts = [`M ${at(first)}`];\n for (const [index, current] of rest.slice(0, -1).entries()) {\n const previous = points[index]!;\n const next = points[index + 2]!;\n const dpx = current.x - previous.x;\n const dpy = current.y - previous.y;\n const dnx = next.x - current.x;\n const dny = next.y - current.y;\n const lp = Math.hypot(dpx, dpy);\n const ln = Math.hypot(dnx, dny);\n const r = Math.min(CORNER_RADIUS, lp / 2, ln / 2);\n const cs = { x: current.x - (dpx / lp) * r, y: current.y - (dpy / lp) * r };\n const ce = { x: current.x + (dnx / ln) * r, y: current.y + (dny / ln) * r };\n parts.push(`L ${at(cs)}`, `Q ${at(current)} ${at(ce)}`);\n }\n const last = rest.at(-1);\n if (last) parts.push(`L ${at(last)}`);\n return parts.join(' ');\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,11 @@
1
+ import type { GraphLayout } from './graph-layout-result.ts';
2
+ import type { RoutedGraph } from './route.ts';
3
+ /** The value to DECIMALS decimals; `+ 0` turns a rounded -0 into 0. */
4
+ export declare function round(value: number): number;
5
+ /**
6
+ * The layout with every coordinate rounded to DECIMALS decimals, and each
7
+ * path drawn through the rounded points. The geometry before it keeps full
8
+ * precision, so the rounding happens once and does not drift.
9
+ */
10
+ export declare function roundLayout(layout: Omit<GraphLayout, keyof RoutedGraph> & RoutedGraph): GraphLayout;
11
+ //# sourceMappingURL=round.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"round.d.ts","sourceRoot":"","sources":["../../../../src/lib/layouts/graph/round.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,WAAW,EAMZ,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAM9C,uEAAuE;AACvE,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,WAAW,CAAC,GAAG,WAAW,GACzD,WAAW,CAQb"}
@@ -0,0 +1,181 @@
1
+ import { pathToSvg } from "./path.js";
2
+ /** How many decimals every coordinate the layout returns keeps. */
3
+ const DECIMALS = 2;
4
+ const SCALE = 10 ** DECIMALS;
5
+
6
+ /** The value to DECIMALS decimals; `+ 0` turns a rounded -0 into 0. */
7
+ export function round(value) {
8
+ return Math.round(value * SCALE) / SCALE + 0;
9
+ }
10
+
11
+ /**
12
+ * The layout with every coordinate rounded to DECIMALS decimals, and each
13
+ * path drawn through the rounded points. The geometry before it keeps full
14
+ * precision, so the rounding happens once and does not drift.
15
+ */
16
+ export function roundLayout(layout) {
17
+ return {
18
+ nodes: layout.nodes.map(roundNode),
19
+ groups: layout.groups.map(roundGroup),
20
+ edges: layout.edges.map(roundEdge),
21
+ leaders: layout.leaders.map(roundLeader),
22
+ viewBox: roundBox(layout.viewBox)
23
+ };
24
+ }
25
+ function roundEdge({
26
+ points,
27
+ label,
28
+ badge,
29
+ ...edge
30
+ }) {
31
+ const rounded = points.map(roundPoint);
32
+ return {
33
+ ...edge,
34
+ points: rounded,
35
+ d: pathToSvg(rounded),
36
+ ...(label && {
37
+ label: {
38
+ box: roundBox(label.box),
39
+ text: label.text.map(roundRun)
40
+ }
41
+ }),
42
+ ...(badge && {
43
+ badge: {
44
+ box: roundBox(badge.box),
45
+ ...(badge.icon && {
46
+ icon: roundBox(badge.icon)
47
+ }),
48
+ text: badge.text.map(roundRun)
49
+ }
50
+ })
51
+ };
52
+ }
53
+ function roundLeader({
54
+ points,
55
+ ...leader
56
+ }) {
57
+ const rounded = points.map(roundPoint);
58
+ return {
59
+ ...leader,
60
+ points: rounded,
61
+ d: pathToSvg(rounded)
62
+ };
63
+ }
64
+ function roundNode({
65
+ box,
66
+ visual,
67
+ frames,
68
+ icon,
69
+ text,
70
+ bullets,
71
+ contentBox,
72
+ caption,
73
+ ports,
74
+ appliance,
75
+ ...node
76
+ }) {
77
+ return {
78
+ ...node,
79
+ box: roundBox(box),
80
+ visual: roundBox(visual),
81
+ frames: frames.map(roundBox),
82
+ ...(icon && {
83
+ icon: {
84
+ x: round(icon.x),
85
+ y: round(icon.y),
86
+ size: round(icon.size)
87
+ }
88
+ }),
89
+ text: text.map(roundRun),
90
+ bullets: bullets.map(roundPoint),
91
+ ...(contentBox && {
92
+ contentBox: roundBox(contentBox)
93
+ }),
94
+ ...(caption && {
95
+ caption: {
96
+ box: roundBox(caption.box),
97
+ framed: caption.framed,
98
+ text: caption.text.map(roundRun)
99
+ }
100
+ }),
101
+ ports: ports.map(roundPort),
102
+ ...(appliance && {
103
+ appliance: {
104
+ body: appliance.body.map(roundPoint),
105
+ face: roundLine(appliance.face),
106
+ antenna: appliance.antenna.map(roundLine),
107
+ jacks: appliance.jacks.map(roundBox)
108
+ }
109
+ })
110
+ };
111
+ }
112
+ function roundGroup({
113
+ rect,
114
+ band,
115
+ separator,
116
+ label,
117
+ dividers,
118
+ ports,
119
+ ...group
120
+ }) {
121
+ return {
122
+ ...group,
123
+ rect: roundBox(rect),
124
+ ...(band && {
125
+ band: roundBox(band)
126
+ }),
127
+ ...(separator && {
128
+ separator: roundLine(separator)
129
+ }),
130
+ label: label.map(roundRun),
131
+ dividers: dividers.map(roundLine),
132
+ ports: ports.map(roundPort)
133
+ };
134
+ }
135
+ function roundPort({
136
+ point,
137
+ label,
138
+ ...port
139
+ }) {
140
+ return {
141
+ ...port,
142
+ point: roundPoint(point),
143
+ ...(label && {
144
+ label: roundRun(label)
145
+ })
146
+ };
147
+ }
148
+ function roundRun(run) {
149
+ return {
150
+ ...run,
151
+ x: round(run.x),
152
+ y: round(run.y),
153
+ bounds: roundBox(run.bounds)
154
+ };
155
+ }
156
+ function roundLine([a, b]) {
157
+ return [roundPoint(a), roundPoint(b)];
158
+ }
159
+ function roundPoint({
160
+ x,
161
+ y
162
+ }) {
163
+ return {
164
+ x: round(x),
165
+ y: round(y)
166
+ };
167
+ }
168
+ function roundBox({
169
+ x,
170
+ y,
171
+ w,
172
+ h
173
+ }) {
174
+ return {
175
+ x: round(x),
176
+ y: round(y),
177
+ w: round(w),
178
+ h: round(h)
179
+ };
180
+ }
181
+ //# sourceMappingURL=round.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"round.js","names":["pathToSvg","DECIMALS","SCALE","round","value","Math","roundLayout","layout","nodes","map","roundNode","groups","roundGroup","edges","roundEdge","leaders","roundLeader","viewBox","roundBox","points","label","badge","edge","rounded","roundPoint","d","box","text","roundRun","icon","leader","visual","frames","bullets","contentBox","caption","ports","appliance","node","x","y","size","framed","roundPort","body","face","roundLine","antenna","jacks","rect","band","separator","dividers","group","point","port","run","bounds","a","b","w","h"],"sources":["../../../../src/lib/layouts/graph/round.ts"],"sourcesContent":["import type { Box, Point } from '../../model/diagram-ir.ts';\nimport type {\n EdgeLayout,\n GraphLayout,\n GroupLayout,\n LeaderLayout,\n NodeLayout,\n PortLayout,\n TextRun,\n} from './graph-layout-result.ts';\nimport { pathToSvg } from './path.ts';\nimport type { RoutedGraph } from './route.ts';\n\n/** How many decimals every coordinate the layout returns keeps. */\nconst DECIMALS = 2;\nconst SCALE = 10 ** DECIMALS;\n\n/** The value to DECIMALS decimals; `+ 0` turns a rounded -0 into 0. */\nexport function round(value: number): number {\n return Math.round(value * SCALE) / SCALE + 0;\n}\n\n/**\n * The layout with every coordinate rounded to DECIMALS decimals, and each\n * path drawn through the rounded points. The geometry before it keeps full\n * precision, so the rounding happens once and does not drift.\n */\nexport function roundLayout(\n layout: Omit<GraphLayout, keyof RoutedGraph> & RoutedGraph,\n): GraphLayout {\n return {\n nodes: layout.nodes.map(roundNode),\n groups: layout.groups.map(roundGroup),\n edges: layout.edges.map(roundEdge),\n leaders: layout.leaders.map(roundLeader),\n viewBox: roundBox(layout.viewBox),\n };\n}\n\nfunction roundEdge({\n points,\n label,\n badge,\n ...edge\n}: RoutedGraph['edges'][number]): EdgeLayout {\n const rounded = points.map(roundPoint);\n return {\n ...edge,\n points: rounded,\n d: pathToSvg(rounded),\n ...(label && {\n label: { box: roundBox(label.box), text: label.text.map(roundRun) },\n }),\n ...(badge && {\n badge: {\n box: roundBox(badge.box),\n ...(badge.icon && { icon: roundBox(badge.icon) }),\n text: badge.text.map(roundRun),\n },\n }),\n };\n}\n\nfunction roundLeader({\n points,\n ...leader\n}: RoutedGraph['leaders'][number]): LeaderLayout {\n const rounded = points.map(roundPoint);\n return { ...leader, points: rounded, d: pathToSvg(rounded) };\n}\n\nfunction roundNode({\n box,\n visual,\n frames,\n icon,\n text,\n bullets,\n contentBox,\n caption,\n ports,\n appliance,\n ...node\n}: NodeLayout): NodeLayout {\n return {\n ...node,\n box: roundBox(box),\n visual: roundBox(visual),\n frames: frames.map(roundBox),\n ...(icon && {\n icon: { x: round(icon.x), y: round(icon.y), size: round(icon.size) },\n }),\n text: text.map(roundRun),\n bullets: bullets.map(roundPoint),\n ...(contentBox && { contentBox: roundBox(contentBox) }),\n ...(caption && {\n caption: {\n box: roundBox(caption.box),\n framed: caption.framed,\n text: caption.text.map(roundRun),\n },\n }),\n ports: ports.map(roundPort),\n ...(appliance && {\n appliance: {\n body: appliance.body.map(roundPoint),\n face: roundLine(appliance.face),\n antenna: appliance.antenna.map(roundLine),\n jacks: appliance.jacks.map(roundBox),\n },\n }),\n };\n}\n\nfunction roundGroup({\n rect,\n band,\n separator,\n label,\n dividers,\n ports,\n ...group\n}: GroupLayout): GroupLayout {\n return {\n ...group,\n rect: roundBox(rect),\n ...(band && { band: roundBox(band) }),\n ...(separator && { separator: roundLine(separator) }),\n label: label.map(roundRun),\n dividers: dividers.map(roundLine),\n ports: ports.map(roundPort),\n };\n}\n\nfunction roundPort({ point, label, ...port }: PortLayout): PortLayout {\n return {\n ...port,\n point: roundPoint(point),\n ...(label && { label: roundRun(label) }),\n };\n}\n\nfunction roundRun(run: TextRun): TextRun {\n return {\n ...run,\n x: round(run.x),\n y: round(run.y),\n bounds: roundBox(run.bounds),\n };\n}\n\nfunction roundLine([a, b]: [Point, Point]): [Point, Point] {\n return [roundPoint(a), roundPoint(b)];\n}\n\nfunction roundPoint({ x, y }: Point): Point {\n return { x: round(x), y: round(y) };\n}\n\nfunction roundBox({ x, y, w, h }: Box): Box {\n return { x: round(x), y: round(y), w: round(w), h: round(h) };\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,16 +1,20 @@
1
1
  import type { DiagramGraphIR } from '../../model/diagram-ir.ts';
2
2
  import type { GridAreas } from './areas.ts';
3
3
  import type { EdgeLayout, GroupLayout, LeaderLayout, NodeLayout } from './graph-layout-result.ts';
4
+ /** The routes, before the layout rounds them and draws their paths. */
5
+ export type RoutedGraph = {
6
+ edges: Omit<EdgeLayout, 'd'>[];
7
+ leaders: Omit<LeaderLayout, 'd'>[];
8
+ };
4
9
  /**
5
10
  * Routes every edge and note leader orthogonally, nearest cells first, and
6
11
  * places each edge's label and badge before the next edge routes around
7
- * them. It throws when a route or a label has no room; it never draws a
8
- * diagonal or straight line through what is in the way.
12
+ * them. A connection with no route takes its next choice of sides, and
13
+ * everything routes again. It throws when a connection has no choice left,
14
+ * or a label has no room; it never draws a diagonal or straight line
15
+ * through what is in the way.
9
16
  */
10
17
  export declare function routeGraph(ir: DiagramGraphIR, nodes: NodeLayout[], groups: GroupLayout[], areas: GridAreas,
11
18
  /** How far beyond the bounding box of its two shapes a route first searches. */
12
- searchMargin: number): {
13
- edges: EdgeLayout[];
14
- leaders: LeaderLayout[];
15
- };
19
+ searchMargin: number): RoutedGraph;
16
20
  //# sourceMappingURL=route.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../src/lib/layouts/graph/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAO,cAAc,EAAS,MAAM,2BAA2B,CAAC;AAC5E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAO5C,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,YAAY,EACZ,UAAU,EACX,MAAM,0BAA0B,CAAC;AAmBlC;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,EAAE,EAAE,cAAc,EAClB,KAAK,EAAE,UAAU,EAAE,EACnB,MAAM,EAAE,WAAW,EAAE,EACrB,KAAK,EAAE,SAAS;AAChB,gFAAgF;AAChF,YAAY,EAAE,MAAM,GACnB;IAAE,KAAK,EAAE,UAAU,EAAE,CAAC;IAAC,OAAO,EAAE,YAAY,EAAE,CAAA;CAAE,CA2KlD"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../../src/lib/layouts/graph/route.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAO,cAAc,EAAS,MAAM,2BAA2B,CAAC;AAC5E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAO5C,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,YAAY,EACZ,UAAU,EACX,MAAM,0BAA0B,CAAC;AAalC,uEAAuE;AACvE,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,EAAE,CAAC;IAC/B,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC,EAAE,CAAC;CACpC,CAAC;AAQF;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,EAAE,EAAE,cAAc,EAClB,KAAK,EAAE,UAAU,EAAE,EACnB,MAAM,EAAE,WAAW,EAAE,EACrB,KAAK,EAAE,SAAS;AAChB,gFAAgF;AAChF,YAAY,EAAE,MAAM,GACnB,WAAW,CAiBb"}
@@ -1,8 +1,8 @@
1
1
  import { attachConnections } from "./attach.js";
2
2
  import { graphConnections } from "./connections.js";
3
3
  import { tagPosition } from "./labels.js";
4
- import { measureEdgeBadge, measureEdgeLabel } from "./measure.js";
5
- import { pathToSvg, simplifyPath } from "./path.js";
4
+ import { measureEdgeTags } from "./measure.js";
5
+ import { simplifyPath } from "./path.js";
6
6
  import { searchRoute } from "./route-search.js";
7
7
  import { OPPOSITE, OUTWARD } from "./sides.js";
8
8
  import { LAYOUT_TOKENS } from "./tokens.js";
@@ -11,15 +11,36 @@ import { LAYOUT_TOKENS } from "./tokens.js";
11
11
  const ROUTING_MARGIN = 64;
12
12
  /** How far a route keeps from a node that it does not connect. */
13
13
  const NODE_CLEARANCE = 8;
14
+
15
+ /** The routes, before the layout rounds them and draws their paths. */
16
+
14
17
  /**
15
18
  * Routes every edge and note leader orthogonally, nearest cells first, and
16
19
  * places each edge's label and badge before the next edge routes around
17
- * them. It throws when a route or a label has no room; it never draws a
18
- * diagonal or straight line through what is in the way.
20
+ * them. A connection with no route takes its next choice of sides, and
21
+ * everything routes again. It throws when a connection has no choice left,
22
+ * or a label has no room; it never draws a diagonal or straight line
23
+ * through what is in the way.
19
24
  */
20
25
  export function routeGraph(ir, nodes, groups, areas, /** How far beyond the bounding box of its two shapes a route first searches. */
21
26
  searchMargin) {
22
- const connections = graphConnections(ir, nodes, groups, areas);
27
+ const candidates = graphConnections(ir, nodes, groups, areas);
28
+ const choices = candidates.map(() => 0);
29
+ for (;;) {
30
+ const routed = routeConnections(ir, candidates.map((options, index) => options[choices[index]]), nodes, groups, searchMargin);
31
+ if (!('unrouted' in routed)) return routed;
32
+ const options = candidates[routed.unrouted];
33
+ const next = choices[routed.unrouted] + 1;
34
+ if (next === options.length) throw noRoute(options[0]);
35
+ choices[routed.unrouted] = next;
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Routes one choice of sides for every connection, or names the first
41
+ * connection, in routing order, that has no route.
42
+ */
43
+ function routeConnections(ir, connections, nodes, groups, searchMargin) {
23
44
  if (connections.length === 0) return {
24
45
  edges: [],
25
46
  leaders: []
@@ -98,10 +119,9 @@ searchMargin) {
98
119
  });
99
120
  const near = intersection(inflate(union([from.shape.box, to.shape.box, spanOf(startStub, endStub)]), searchMargin), bounds);
100
121
  const found = stubsClear ? search(near) ?? search(bounds) : undefined;
101
- if (!found) {
102
- const advice = connection.edge === undefined ? 'Move the note or its target.' : 'Change exitSide/entrySide or move a node.';
103
- throw new Error(`Diagram ${connection.name}: no orthogonal route from ${endName(from)} to ${endName(to)} avoids the nodes and labels. ${advice}`);
104
- }
122
+ if (!found) return {
123
+ unrouted: index
124
+ };
105
125
  const points = simplifyPath([start, ...found, end]);
106
126
  paths.set(connection, points);
107
127
  if (connection.edge !== undefined) {
@@ -113,30 +133,38 @@ searchMargin) {
113
133
  band,
114
134
  label
115
135
  }) => !(band && intersects(box, band)) && label.every(run => !intersects(box, run.bounds)) && !(intersects(box, rect) && !contains(rect, box))) && tags.every(tag => !intersects(box, tag)) && [...routed.flatMap(route => segments(route.points)), ...(ownSegments ? segments(points) : [])].every(([a, b]) => !crosses(a, b, box));
136
+ const measured = measureEdgeTags(edge);
137
+ const {
138
+ label,
139
+ badge
140
+ } = measured;
116
141
  const placed = {};
117
- if (edge.label?.length) {
118
- const measured = measureEdgeLabel(edge);
119
- const position = tagPosition(measured, points, 'beside', box => isFree(box, true));
120
- if (!position) {
121
- throw new Error(`Diagram ${connection.name}: label "${edge.label.join(' / ')}" (${Math.ceil(measured.w)}×${Math.ceil(measured.h)}) has no free position beside its route.`);
142
+ if (label || badge) {
143
+ const boxes = tagPosition(measured, points, (candidate, kind) => isFree(candidate, kind === 'label'));
144
+ if (!boxes) {
145
+ const named = [];
146
+ if (label) {
147
+ named.push(`label "${edge.label.join(' / ')}" (${Math.ceil(label.w)}×${Math.ceil(label.h)})`);
148
+ }
149
+ if (badge) {
150
+ named.push(`badge "${(edge.badgeLabel ?? []).join(' / ')}" (${Math.ceil(badge.w)}×${Math.ceil(badge.h)})`);
151
+ }
152
+ throw new Error(`Diagram ${connection.name}: ${named.join(' and ')} ${named.length > 1 ? 'have' : 'has'} no free position ${badge ? 'on' : 'beside'} its route.`);
122
153
  }
123
- placed.label = {
124
- ...position,
125
- text: measured.place(position.box)
126
- };
127
- tags.push(position.box);
128
- }
129
- if (edge.badgeIcon || edge.badgeLabel?.length) {
130
- const measured = measureEdgeBadge(edge);
131
- const position = tagPosition(measured, points, 'on', box => isFree(box, false));
132
- if (!position) {
133
- throw new Error(`Diagram ${connection.name}: badge "${(edge.badgeLabel ?? []).join(' / ')}" (${Math.ceil(measured.w)}×${Math.ceil(measured.h)}) has no free position on its route.`);
154
+ if (label && boxes.label) {
155
+ placed.label = {
156
+ box: boxes.label,
157
+ text: label.place(boxes.label)
158
+ };
159
+ tags.push(boxes.label);
160
+ }
161
+ if (badge && boxes.badge) {
162
+ placed.badge = {
163
+ box: boxes.badge,
164
+ ...badge.place(boxes.badge)
165
+ };
166
+ tags.push(boxes.badge);
134
167
  }
135
- placed.badge = {
136
- box: position.box,
137
- ...measured.place(position.box)
138
- };
139
- tags.push(position.box);
140
168
  }
141
169
  labels.set(connection, placed);
142
170
  }
@@ -153,8 +181,7 @@ searchMargin) {
153
181
  leaders.push({
154
182
  note: connection.from.shape.id,
155
183
  target: connection.to.shape.id,
156
- points,
157
- d: pathToSvg(points)
184
+ points
158
185
  });
159
186
  continue;
160
187
  }
@@ -163,7 +190,6 @@ searchMargin) {
163
190
  exitSide: connection.from.side,
164
191
  entrySide: connection.to.side,
165
192
  points,
166
- d: pathToSvg(points),
167
193
  ...labels.get(connection)
168
194
  });
169
195
  }
@@ -172,6 +198,15 @@ searchMargin) {
172
198
  leaders
173
199
  };
174
200
  }
201
+ function noRoute({
202
+ name,
203
+ edge,
204
+ from,
205
+ to
206
+ }) {
207
+ const advice = edge === undefined ? 'Move the note or its target.' : 'Change exitSide/entrySide or move a node.';
208
+ return new Error(`Diagram ${name}: no orthogonal route from ${endName(from)} to ${endName(to)} avoids the nodes and labels. ${advice}`);
209
+ }
175
210
  function endName({
176
211
  shape,
177
212
  side,