@diagrammo/dgmo 0.33.0 → 0.34.0

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/dist/advanced.cjs CHANGED
@@ -29183,63 +29183,6 @@ function ensureArrowMarkers(defs, colors) {
29183
29183
  ).attr("fill", color);
29184
29184
  }
29185
29185
  }
29186
- function edgePolylineMidpoint(points) {
29187
- if (points.length === 0) return { x: 0, y: 0 };
29188
- if (points.length === 1) return { x: points[0].x, y: points[0].y };
29189
- let total = 0;
29190
- const segLen = [];
29191
- for (let k = 1; k < points.length; k++) {
29192
- const len = Math.hypot(
29193
- points[k].x - points[k - 1].x,
29194
- points[k].y - points[k - 1].y
29195
- );
29196
- segLen.push(len);
29197
- total += len;
29198
- }
29199
- let half = total / 2;
29200
- for (let k = 1; k < points.length; k++) {
29201
- const len = segLen[k - 1];
29202
- if (half <= len || k === points.length - 1) {
29203
- const t = len === 0 ? 0 : Math.min(1, half / len);
29204
- return {
29205
- x: points[k - 1].x + (points[k].x - points[k - 1].x) * t,
29206
- y: points[k - 1].y + (points[k].y - points[k - 1].y) * t
29207
- };
29208
- }
29209
- half -= len;
29210
- }
29211
- const last = points[points.length - 1];
29212
- return { x: last.x, y: last.y };
29213
- }
29214
- function resolveEdgeLabelOverlaps(labels) {
29215
- const MAX_PASSES = 8;
29216
- const PAD = 4;
29217
- for (let pass = 0; pass < MAX_PASSES; pass++) {
29218
- let moved = false;
29219
- for (let i = 0; i < labels.length; i++) {
29220
- for (let j = i + 1; j < labels.length; j++) {
29221
- const a = labels[i];
29222
- const b = labels[j];
29223
- const dx = Math.abs(a.x - b.x);
29224
- const dy = Math.abs(a.y - b.y);
29225
- const overlapX = (a.width + b.width) / 2 + PAD - dx;
29226
- const overlapY = (a.height + b.height) / 2 + PAD - dy;
29227
- if (overlapX > 0 && overlapY > 0) {
29228
- const shift = overlapY / 2 + 1;
29229
- if (a.y < b.y) {
29230
- a.y -= shift;
29231
- b.y += shift;
29232
- } else {
29233
- a.y += shift;
29234
- b.y -= shift;
29235
- }
29236
- moved = true;
29237
- }
29238
- }
29239
- }
29240
- if (!moved) break;
29241
- }
29242
- }
29243
29186
  function renderBoxesAndLines(container, parsed, layout, palette, isDark, options) {
29244
29187
  const {
29245
29188
  onClickItem,
@@ -29446,8 +29389,6 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
29446
29389
  groupG.append("text").attr("class", "bl-group-label").attr("x", gx + group.width / 2).attr("y", gy + 18).attr("text-anchor", "middle").attr("font-family", FONT_FAMILY).attr("font-size", sGroupLabelFontSize).attr("font-weight", "600").attr("fill", palette.text).text(group.label);
29447
29390
  }
29448
29391
  }
29449
- const labelPositions = [];
29450
- const edgeGroups = /* @__PURE__ */ new Map();
29451
29392
  for (let i = 0; i < layout.edges.length; i++) {
29452
29393
  const le = layout.edges[i];
29453
29394
  const color = edgeColorMap.get(i) ?? palette.textMuted;
@@ -29466,7 +29407,6 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
29466
29407
  const nodeLayout = layoutNodeMap.get(le.source);
29467
29408
  if (nodeLayout) {
29468
29409
  const edgeG2 = diagramG.append("g").attr("class", "bl-edge-group").attr("data-line-number", String(le.lineNumber));
29469
- edgeGroups.set(i, edgeG2);
29470
29410
  const markerId2 = `bl-arrow-${color.replace("#", "")}`;
29471
29411
  const cx = nodeLayout.x;
29472
29412
  const cy = nodeLayout.y;
@@ -29515,7 +29455,6 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
29515
29455
  }
29516
29456
  if (points.length < 2) continue;
29517
29457
  const edgeG = diagramG.append("g").attr("class", "bl-edge-group").attr("data-line-number", String(le.lineNumber));
29518
- edgeGroups.set(i, edgeG);
29519
29458
  const markerId = `bl-arrow-${color.replace("#", "")}`;
29520
29459
  const gen = le.straight ? lineGeneratorStraight : parsed.direction === "TB" ? lineGeneratorTB : lineGeneratorLR;
29521
29460
  const path = edgeG.append("path").attr("class", "bl-edge").attr("d", gen(points) ?? "").attr("fill", "none").attr("stroke", color).attr("stroke-width", sEdgeStrokeWidth).attr("marker-end", `url(#${markerId})`);
@@ -29523,31 +29462,6 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
29523
29462
  const revId = `bl-arrow-rev-${color.replace("#", "")}`;
29524
29463
  path.attr("marker-start", `url(#${revId})`);
29525
29464
  }
29526
- if (le.label && le.points.length > 0) {
29527
- const lw = measureText(le.label, sEdgeLabelFontSize);
29528
- const labelH = sEdgeLabelFontSize + 6;
29529
- const mid = edgePolylineMidpoint(le.points);
29530
- let ly = mid.y;
29531
- if (le.parallelCount > 1 && le.yOffset !== 0) {
29532
- ly += (le.yOffset < 0 ? -labelH : labelH) * 0.5;
29533
- }
29534
- labelPositions.push({
29535
- x: mid.x,
29536
- y: ly,
29537
- width: lw + 8,
29538
- height: labelH,
29539
- idx: i
29540
- });
29541
- }
29542
- }
29543
- resolveEdgeLabelOverlaps(labelPositions);
29544
- for (const lp of labelPositions) {
29545
- const le = layout.edges[lp.idx];
29546
- if (!le.label) continue;
29547
- const edgeG = edgeGroups.get(lp.idx);
29548
- const target = edgeG ?? diagramG;
29549
- target.append("rect").attr("x", lp.x - lp.width / 2).attr("y", lp.y - lp.height / 2).attr("width", lp.width).attr("height", lp.height).attr("rx", 3).attr("fill", palette.bg).attr("opacity", 0.85);
29550
- target.append("text").attr("x", lp.x).attr("y", lp.y + sEdgeLabelFontSize / 3).attr("text-anchor", "middle").attr("font-size", sEdgeLabelFontSize).attr("fill", palette.textMuted).text(le.label);
29551
29465
  }
29552
29466
  for (const ln of layout.nodes) {
29553
29467
  const node = nodeMap.get(ln.label);
@@ -29598,8 +29512,8 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
29598
29512
  nodeG.append("rect").attr("x", x).attr("y", y).attr("width", ln.width).attr("height", ln.height).attr("rx", NODE_RX).attr("ry", NODE_RX).attr("fill", colors.fill).attr("stroke", colors.stroke).attr("stroke-width", sNodeStrokeWidth);
29599
29513
  const desc = node.description;
29600
29514
  if (desc && desc.length > 0 && !hideDescriptions) {
29601
- const MAX_LABEL_LINES3 = 3;
29602
- const fitted = fitLabelToHeader(node.label, ln.width, MAX_LABEL_LINES3);
29515
+ const MAX_LABEL_LINES4 = 3;
29516
+ const fitted = fitLabelToHeader(node.label, ln.width, MAX_LABEL_LINES4);
29603
29517
  const labelLines = fitted.lines;
29604
29518
  const labelLineH = fitted.fontSize * 1.3;
29605
29519
  const labelTotalH = labelLines.length * labelLineH;
@@ -29733,6 +29647,35 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
29733
29647
  }
29734
29648
  }
29735
29649
  }
29650
+ const labelLayer = diagramG.append("g").attr("class", "bl-edge-labels");
29651
+ const labelLineHeight = sEdgeLabelFontSize * 1.3;
29652
+ for (const le of layout.edges) {
29653
+ if (!le.labelLines || le.labelLines.length === 0) continue;
29654
+ if (le.labelX === void 0 || le.labelY === void 0) continue;
29655
+ const lx = le.labelX;
29656
+ const ly = le.labelY;
29657
+ if (hidden.size > 0) {
29658
+ let isHidden = false;
29659
+ for (const [groupKey2, hiddenVals] of hidden) {
29660
+ const val = le.metadata[groupKey2];
29661
+ if (val && hiddenVals.has(val.toLowerCase())) {
29662
+ isHidden = true;
29663
+ break;
29664
+ }
29665
+ }
29666
+ if (isHidden) continue;
29667
+ }
29668
+ const lw = le.labelWidth ?? 0;
29669
+ const lh = le.labelHeight ?? sEdgeLabelFontSize + 6;
29670
+ const lines = le.labelLines;
29671
+ const labelG = labelLayer.append("g").attr("class", "bl-edge-label").attr("data-line-number", String(le.lineNumber));
29672
+ labelG.append("rect").attr("x", lx - lw / 2).attr("y", ly - lh / 2).attr("width", lw).attr("height", lh).attr("rx", 3).attr("fill", palette.bg).attr("opacity", 0.72);
29673
+ const text = labelG.append("text").attr("x", lx).attr("text-anchor", "middle").attr("font-family", FONT_FAMILY).attr("font-size", sEdgeLabelFontSize).attr("fill", palette.textMuted);
29674
+ const firstY = ly - (lines.length - 1) / 2 * labelLineHeight + sEdgeLabelFontSize / 3;
29675
+ lines.forEach((line11, k) => {
29676
+ text.append("tspan").attr("x", lx).attr("y", firstY + k * labelLineHeight).text(line11);
29677
+ });
29678
+ }
29736
29679
  const hasDescriptions = parsed.nodes.some(
29737
29680
  (n) => n.description && n.description.length > 0
29738
29681
  );
@@ -29849,6 +29792,222 @@ var init_renderer6 = __esm({
29849
29792
  }
29850
29793
  });
29851
29794
 
29795
+ // src/boxes-and-lines/label-placement.ts
29796
+ function measureEdgeLabel(label, fontSize = EDGE_LABEL_FONT_SIZE6, maxWidth = LABEL_MAX_WIDTH) {
29797
+ let lines = wrapTextToWidth(label, fontSize, maxWidth, { hardBreak: true });
29798
+ if (lines.length > MAX_LABEL_LINES) {
29799
+ const kept = lines.slice(0, MAX_LABEL_LINES - 1);
29800
+ const rest = lines.slice(MAX_LABEL_LINES - 1).join(" ");
29801
+ kept.push(truncateText(rest, fontSize, maxWidth));
29802
+ lines = kept;
29803
+ }
29804
+ let textW = 0;
29805
+ for (const ln of lines) {
29806
+ const w = measureText(ln, fontSize);
29807
+ if (w > textW) textW = w;
29808
+ }
29809
+ return {
29810
+ lines,
29811
+ width: textW + 2 * H_PAD,
29812
+ height: lines.length * fontSize * LABEL_LINE_HEIGHT + 2 * V_PAD
29813
+ };
29814
+ }
29815
+ function edgePolylineMidpoint(points) {
29816
+ return pointAtArcFraction(points, 0.5).p;
29817
+ }
29818
+ function pointAtArcFraction(points, t) {
29819
+ if (points.length === 0) return { p: { x: 0, y: 0 }, nx: 0, ny: 1 };
29820
+ if (points.length === 1)
29821
+ return { p: { x: points[0].x, y: points[0].y }, nx: 0, ny: 1 };
29822
+ const segLen = [];
29823
+ let total = 0;
29824
+ for (let k = 1; k < points.length; k++) {
29825
+ const len = Math.hypot(
29826
+ points[k].x - points[k - 1].x,
29827
+ points[k].y - points[k - 1].y
29828
+ );
29829
+ segLen.push(len);
29830
+ total += len;
29831
+ }
29832
+ let want = total * Math.max(0, Math.min(1, t));
29833
+ for (let k = 1; k < points.length; k++) {
29834
+ const len = segLen[k - 1];
29835
+ if (want <= len || k === points.length - 1) {
29836
+ const f = len === 0 ? 0 : Math.min(1, want / len);
29837
+ const ax = points[k - 1].x;
29838
+ const ay = points[k - 1].y;
29839
+ const bx = points[k].x;
29840
+ const by = points[k].y;
29841
+ const dx = bx - ax;
29842
+ const dy = by - ay;
29843
+ const dlen = Math.hypot(dx, dy) || 1;
29844
+ return {
29845
+ p: { x: ax + dx * f, y: ay + dy * f },
29846
+ nx: -dy / dlen,
29847
+ ny: dx / dlen
29848
+ };
29849
+ }
29850
+ want -= len;
29851
+ }
29852
+ const last = points[points.length - 1];
29853
+ return { p: { x: last.x, y: last.y }, nx: 0, ny: 1 };
29854
+ }
29855
+ function rectFromCenter(cx, cy, w, h) {
29856
+ return {
29857
+ minX: cx - w / 2,
29858
+ minY: cy - h / 2,
29859
+ maxX: cx + w / 2,
29860
+ maxY: cy + h / 2
29861
+ };
29862
+ }
29863
+ function overlapsAny(cx, cy, w, h, obstacles, pad2) {
29864
+ const minX = cx - w / 2 - pad2;
29865
+ const minY = cy - h / 2 - pad2;
29866
+ const maxX = cx + w / 2 + pad2;
29867
+ const maxY = cy + h / 2 + pad2;
29868
+ for (const o of obstacles) {
29869
+ if (minX < o.maxX && maxX > o.minX && minY < o.maxY && maxY > o.minY)
29870
+ return true;
29871
+ }
29872
+ return false;
29873
+ }
29874
+ function slideFractions() {
29875
+ const out = [0.5];
29876
+ for (let k = 1; k <= SLIDE_SAMPLES; k++) {
29877
+ const off = k * 0.08;
29878
+ if (0.5 - off >= 0.12) out.push(0.5 - off);
29879
+ if (0.5 + off <= 0.88) out.push(0.5 + off);
29880
+ }
29881
+ return out;
29882
+ }
29883
+ function findClearPosition(w, h, points, obstacles) {
29884
+ const ts = slideFractions();
29885
+ for (const t of ts) {
29886
+ const { p } = pointAtArcFraction(points, t);
29887
+ if (!overlapsAny(p.x, p.y, w, h, obstacles, BOX_CLEAR_PAD)) return p;
29888
+ }
29889
+ for (let mag = PERP_STEP; mag <= PERP_MAX; mag += PERP_STEP) {
29890
+ for (const t of ts) {
29891
+ const { p, nx, ny } = pointAtArcFraction(points, t);
29892
+ for (const sign of [-1, 1]) {
29893
+ const x = p.x + nx * mag * sign;
29894
+ const y = p.y + ny * mag * sign;
29895
+ if (!overlapsAny(x, y, w, h, obstacles, BOX_CLEAR_PAD)) return { x, y };
29896
+ }
29897
+ }
29898
+ }
29899
+ return null;
29900
+ }
29901
+ function resolveLabelOverlaps(boxes) {
29902
+ const MAX_PASSES = 8;
29903
+ const PAD = 4;
29904
+ for (let pass = 0; pass < MAX_PASSES; pass++) {
29905
+ let moved = false;
29906
+ for (let i = 0; i < boxes.length; i++) {
29907
+ for (let j = i + 1; j < boxes.length; j++) {
29908
+ const a = boxes[i];
29909
+ const b = boxes[j];
29910
+ const dx = Math.abs(a.cx - b.cx);
29911
+ const dy = Math.abs(a.cy - b.cy);
29912
+ const overlapX = (a.w + b.w) / 2 + PAD - dx;
29913
+ const overlapY = (a.h + b.h) / 2 + PAD - dy;
29914
+ if (overlapX > 0 && overlapY > 0) {
29915
+ const shift = overlapY / 2 + 1;
29916
+ if (a.cy < b.cy) {
29917
+ a.cy -= shift;
29918
+ b.cy += shift;
29919
+ } else {
29920
+ a.cy += shift;
29921
+ b.cy -= shift;
29922
+ }
29923
+ moved = true;
29924
+ }
29925
+ }
29926
+ }
29927
+ if (!moved) break;
29928
+ }
29929
+ }
29930
+ function placeEdgeLabels(layout, opts) {
29931
+ const fontSize = opts?.fontSize ?? EDGE_LABEL_FONT_SIZE6;
29932
+ const maxWidth = opts?.maxWidth ?? LABEL_MAX_WIDTH;
29933
+ const obstacles = [];
29934
+ for (const n of layout.nodes)
29935
+ obstacles.push(rectFromCenter(n.x, n.y, n.width, n.height));
29936
+ for (const g of layout.groups)
29937
+ if (g.collapsed)
29938
+ obstacles.push(rectFromCenter(g.x, g.y, g.width, g.height));
29939
+ const boxes = [];
29940
+ layout.edges.forEach((e, idx) => {
29941
+ if (!e.label || e.points.length < 2) return;
29942
+ const m = measureEdgeLabel(e.label, fontSize, maxWidth);
29943
+ const mid = edgePolylineMidpoint(e.points);
29944
+ let cy = mid.y;
29945
+ if (e.parallelCount > 1 && e.yOffset !== 0)
29946
+ cy += (e.yOffset < 0 ? -1 : 1) * (m.height / 2);
29947
+ boxes.push({
29948
+ edgeIdx: idx,
29949
+ cx: mid.x,
29950
+ cy,
29951
+ w: m.width,
29952
+ h: m.height,
29953
+ lines: m.lines,
29954
+ resolved: true
29955
+ });
29956
+ });
29957
+ for (const box of boxes) {
29958
+ if (!overlapsAny(box.cx, box.cy, box.w, box.h, obstacles, BOX_CLEAR_PAD))
29959
+ continue;
29960
+ const e = layout.edges[box.edgeIdx];
29961
+ const clear = findClearPosition(box.w, box.h, e.points, obstacles);
29962
+ if (clear) {
29963
+ box.cx = clear.x;
29964
+ box.cy = clear.y;
29965
+ } else {
29966
+ box.resolved = false;
29967
+ }
29968
+ }
29969
+ resolveLabelOverlaps(boxes);
29970
+ for (const box of boxes) {
29971
+ if (overlapsAny(box.cx, box.cy, box.w, box.h, obstacles, BOX_CLEAR_PAD))
29972
+ box.resolved = false;
29973
+ }
29974
+ const boxByIdx = /* @__PURE__ */ new Map();
29975
+ for (const b of boxes) boxByIdx.set(b.edgeIdx, b);
29976
+ const edges = layout.edges.map((e, idx) => {
29977
+ const b = boxByIdx.get(idx);
29978
+ if (!b) return e;
29979
+ return {
29980
+ ...e,
29981
+ labelX: b.cx,
29982
+ labelY: b.cy,
29983
+ labelWidth: b.w,
29984
+ labelHeight: b.h,
29985
+ labelLines: b.lines
29986
+ };
29987
+ });
29988
+ return {
29989
+ layout: { ...layout, edges },
29990
+ unresolved: boxes.filter((b) => !b.resolved).map((b) => b.edgeIdx)
29991
+ };
29992
+ }
29993
+ var EDGE_LABEL_FONT_SIZE6, LABEL_MAX_WIDTH, MAX_LABEL_LINES, LABEL_LINE_HEIGHT, H_PAD, V_PAD, BOX_CLEAR_PAD, PERP_STEP, PERP_MAX, SLIDE_SAMPLES;
29994
+ var init_label_placement = __esm({
29995
+ "src/boxes-and-lines/label-placement.ts"() {
29996
+ "use strict";
29997
+ init_text_measure();
29998
+ EDGE_LABEL_FONT_SIZE6 = 11;
29999
+ LABEL_MAX_WIDTH = 160;
30000
+ MAX_LABEL_LINES = 3;
30001
+ LABEL_LINE_HEIGHT = 1.3;
30002
+ H_PAD = 6;
30003
+ V_PAD = 3;
30004
+ BOX_CLEAR_PAD = 4;
30005
+ PERP_STEP = 8;
30006
+ PERP_MAX = 40;
30007
+ SLIDE_SAMPLES = 9;
30008
+ }
30009
+ });
30010
+
29852
30011
  // src/boxes-and-lines/layout-layered.ts
29853
30012
  function rng(s) {
29854
30013
  return () => {
@@ -31636,6 +31795,7 @@ function edgeLength(layout) {
31636
31795
  }
31637
31796
  async function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
31638
31797
  const hideDescriptions = opts?.hideDescriptions ?? false;
31798
+ const reserveEdgeLabels = opts?.reserveEdgeLabels ?? false;
31639
31799
  const onProgress = opts?.onProgress;
31640
31800
  const tick = onProgress ? () => new Promise((r) => setTimeout(r)) : () => void 0;
31641
31801
  const collapsedGroupLabels = /* @__PURE__ */ new Set();
@@ -31928,8 +32088,14 @@ async function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
31928
32088
  for (const e of ord(parsed.edges)) {
31929
32089
  const s = srcRep(e.source);
31930
32090
  const t = tgtRep(e.target);
31931
- if (s !== t && g.hasNode(s) && g.hasNode(t))
31932
- g.setEdge(s, t, {}, edgeKey(e));
32091
+ if (s !== t && g.hasNode(s) && g.hasNode(t)) {
32092
+ let edgeLabel = {};
32093
+ if (reserveEdgeLabels && e.label) {
32094
+ const m = measureEdgeLabel(e.label, EDGE_LABEL_FONT_SIZE6);
32095
+ edgeLabel = { width: m.width, height: m.height, labelpos: "c" };
32096
+ }
32097
+ g.setEdge(s, t, edgeLabel, edgeKey(e));
32098
+ }
31933
32099
  }
31934
32100
  import_dagre4.default.layout(g);
31935
32101
  const nodes = parsed.nodes.map((n2) => {
@@ -32160,6 +32326,7 @@ var init_layout_search = __esm({
32160
32326
  init_layout5();
32161
32327
  init_layout_layered();
32162
32328
  init_layout_grouped();
32329
+ init_label_placement();
32163
32330
  DEFAULT_LAMBDA = 4;
32164
32331
  ESCALATE_THRESHOLD = 4;
32165
32332
  ESCALATE_MAX_N = 45;
@@ -32218,9 +32385,9 @@ function estimateLabelLines(label, nodeWidth = NODE_WIDTH) {
32218
32385
  current = word;
32219
32386
  }
32220
32387
  }
32221
- if (lines <= MAX_LABEL_LINES) return Math.min(lines, MAX_LABEL_LINES);
32388
+ if (lines <= MAX_LABEL_LINES2) return Math.min(lines, MAX_LABEL_LINES2);
32222
32389
  }
32223
- return MAX_LABEL_LINES;
32390
+ return MAX_LABEL_LINES2;
32224
32391
  }
32225
32392
  function computeNodeSize(node, reserveValueRow) {
32226
32393
  if (!node.description || node.description.length === 0) {
@@ -32228,7 +32395,7 @@ function computeNodeSize(node, reserveValueRow) {
32228
32395
  }
32229
32396
  const w = DESC_NODE_WIDTH;
32230
32397
  const labelLines = estimateLabelLines(node.label, w);
32231
- const labelHeight = labelLines * 13 * LABEL_LINE_HEIGHT + LABEL_PAD;
32398
+ const labelHeight = labelLines * 13 * LABEL_LINE_HEIGHT2 + LABEL_PAD;
32232
32399
  const maxTextWidth = w - 24;
32233
32400
  let totalRenderedLines = 0;
32234
32401
  for (const line11 of node.description) {
@@ -32252,7 +32419,7 @@ function computeNodeSize(node, reserveValueRow) {
32252
32419
  }
32253
32420
  async function layoutBoxesAndLines(parsed, collapseInfo, layoutOptions) {
32254
32421
  const { layoutBoxesAndLinesSearch: layoutBoxesAndLinesSearch2 } = await Promise.resolve().then(() => (init_layout_search(), layout_search_exports));
32255
- const searched = await layoutBoxesAndLinesSearch2(parsed, collapseInfo, {
32422
+ const searchOpts = {
32256
32423
  ...layoutOptions?.hideDescriptions !== void 0 && {
32257
32424
  hideDescriptions: layoutOptions.hideDescriptions
32258
32425
  },
@@ -32262,12 +32429,23 @@ async function layoutBoxesAndLines(parsed, collapseInfo, layoutOptions) {
32262
32429
  ...layoutOptions?.onProgress !== void 0 && {
32263
32430
  onProgress: layoutOptions.onProgress
32264
32431
  }
32265
- });
32266
- return attachNotes(
32267
- applyParallelEdgeOffsets(searched),
32432
+ };
32433
+ const searched = await layoutBoxesAndLinesSearch2(
32268
32434
  parsed,
32269
- layoutOptions?.collapsedNotes
32435
+ collapseInfo,
32436
+ searchOpts
32270
32437
  );
32438
+ let placed = placeEdgeLabels(applyParallelEdgeOffsets(searched));
32439
+ if (placed.unresolved.length > 0) {
32440
+ const relaid = await layoutBoxesAndLinesSearch2(parsed, collapseInfo, {
32441
+ ...searchOpts,
32442
+ reserveEdgeLabels: true
32443
+ });
32444
+ const relaidPlaced = placeEdgeLabels(applyParallelEdgeOffsets(relaid));
32445
+ if (relaidPlaced.unresolved.length < placed.unresolved.length)
32446
+ placed = relaidPlaced;
32447
+ }
32448
+ return attachNotes(placed.layout, parsed, layoutOptions?.collapsedNotes);
32271
32449
  }
32272
32450
  function attachNotes(layout, parsed, collapsedNotes) {
32273
32451
  const notesSuppressed = parsed.options?.["no-notes"] === "on";
@@ -32335,6 +32513,7 @@ function attachNotes(layout, parsed, collapsedNotes) {
32335
32513
  points: e.points.map((pt) => ({ x: pt.x + shiftX, y: pt.y + shiftY })),
32336
32514
  ...e.labelX !== void 0 && { labelX: e.labelX + shiftX },
32337
32515
  ...e.labelY !== void 0 && { labelY: e.labelY + shiftY }
32516
+ // labelWidth/labelHeight/labelLines are shift-invariant — carried via spread.
32338
32517
  })) : layout.edges;
32339
32518
  const finalGroups = shifted ? layout.groups.map((grp) => ({
32340
32519
  ...grp,
@@ -32379,11 +32558,12 @@ function applyParallelEdgeOffsets(layout) {
32379
32558
  }))
32380
32559
  };
32381
32560
  }
32382
- var MARGIN5, MAX_PARALLEL_EDGES, PARALLEL_SPACING, PHI, NODE_HEIGHT, NODE_WIDTH, DESC_NODE_WIDTH, DESC_FONT_SIZE2, DESC_LINE_HEIGHT2, DESC_PADDING, SEPARATOR_GAP4, MAX_DESC_LINES2, MAX_LABEL_LINES, LABEL_LINE_HEIGHT, LABEL_PAD, VALUE_ROW_FONT, VALUE_ROW_H;
32561
+ var MARGIN5, MAX_PARALLEL_EDGES, PARALLEL_SPACING, PHI, NODE_HEIGHT, NODE_WIDTH, DESC_NODE_WIDTH, DESC_FONT_SIZE2, DESC_LINE_HEIGHT2, DESC_PADDING, SEPARATOR_GAP4, MAX_DESC_LINES2, MAX_LABEL_LINES2, LABEL_LINE_HEIGHT2, LABEL_PAD, VALUE_ROW_FONT, VALUE_ROW_H;
32383
32562
  var init_layout5 = __esm({
32384
32563
  "src/boxes-and-lines/layout.ts"() {
32385
32564
  "use strict";
32386
32565
  init_text_measure();
32566
+ init_label_placement();
32387
32567
  init_notes();
32388
32568
  MARGIN5 = 40;
32389
32569
  MAX_PARALLEL_EDGES = 5;
@@ -32397,8 +32577,8 @@ var init_layout5 = __esm({
32397
32577
  DESC_PADDING = 8;
32398
32578
  SEPARATOR_GAP4 = 4;
32399
32579
  MAX_DESC_LINES2 = 6;
32400
- MAX_LABEL_LINES = 3;
32401
- LABEL_LINE_HEIGHT = 1.3;
32580
+ MAX_LABEL_LINES2 = 3;
32581
+ LABEL_LINE_HEIGHT2 = 1.3;
32402
32582
  LABEL_PAD = 12;
32403
32583
  VALUE_ROW_FONT = 11;
32404
32584
  VALUE_ROW_H = SEPARATOR_GAP4 + VALUE_ROW_FONT * DESC_LINE_HEIGHT2 + DESC_PADDING;
@@ -32417,7 +32597,7 @@ function tokenize(text) {
32417
32597
  return tokens;
32418
32598
  }
32419
32599
  function tryWrap(tokens, maxWidth, fontSize, maxLines) {
32420
- const availWidth = maxWidth - H_PAD;
32600
+ const availWidth = maxWidth - H_PAD2;
32421
32601
  const lines = [];
32422
32602
  let currentLine = "";
32423
32603
  for (const token of tokens) {
@@ -32442,7 +32622,7 @@ function tryWrap(tokens, maxWidth, fontSize, maxLines) {
32442
32622
  return lines;
32443
32623
  }
32444
32624
  function truncateLastLine(lines, maxWidth, fontSize) {
32445
- const availWidth = maxWidth - H_PAD;
32625
+ const availWidth = maxWidth - H_PAD2;
32446
32626
  const result = [...lines];
32447
32627
  const last = result[result.length - 1];
32448
32628
  if (measureText(last, fontSize) > availWidth) {
@@ -32450,7 +32630,7 @@ function truncateLastLine(lines, maxWidth, fontSize) {
32450
32630
  }
32451
32631
  return result;
32452
32632
  }
32453
- function wrapText(text, maxWidth, baseFontSize, minFontSize, maxLines = MAX_LABEL_LINES2) {
32633
+ function wrapText(text, maxWidth, baseFontSize, minFontSize, maxLines = MAX_LABEL_LINES3) {
32454
32634
  if (!text) return { lines: [""], fontSize: baseFontSize };
32455
32635
  const tokens = tokenize(text);
32456
32636
  for (let fs = baseFontSize; fs >= minFontSize; fs--) {
@@ -32465,7 +32645,7 @@ function wrapText(text, maxWidth, baseFontSize, minFontSize, maxLines = MAX_LABE
32465
32645
  if (allLines.length > maxLines) {
32466
32646
  const last = truncated[truncated.length - 1];
32467
32647
  if (!last.endsWith("\u2026")) {
32468
- const availWidth = maxWidth - H_PAD;
32648
+ const availWidth = maxWidth - H_PAD2;
32469
32649
  if (measureText(last + "\u2026", minFontSize) > availWidth) {
32470
32650
  truncated[truncated.length - 1] = truncateText(
32471
32651
  last,
@@ -32492,7 +32672,7 @@ function computeNodeText(label, description, depth, nodeWidth, hideDescriptions)
32492
32672
  nodeWidth,
32493
32673
  baseFontSize,
32494
32674
  MIN_FONT_SIZE,
32495
- MAX_LABEL_LINES2
32675
+ MAX_LABEL_LINES3
32496
32676
  );
32497
32677
  const descLines = [];
32498
32678
  let descFontSize = DESC_FONT_SIZE3;
@@ -32520,14 +32700,14 @@ function computeNodeText(label, description, depth, nodeWidth, hideDescriptions)
32520
32700
  descFontSize
32521
32701
  };
32522
32702
  }
32523
- var H_PAD, MAX_LABEL_LINES2, MAX_DESC_LINES3, ROOT_FONT_SIZE, MIN_FONT_SIZE, FONT_STEP, DESC_FONT_SIZE3;
32703
+ var H_PAD2, MAX_LABEL_LINES3, MAX_DESC_LINES3, ROOT_FONT_SIZE, MIN_FONT_SIZE, FONT_STEP, DESC_FONT_SIZE3;
32524
32704
  var init_text_wrap = __esm({
32525
32705
  "src/mindmap/text-wrap.ts"() {
32526
32706
  "use strict";
32527
32707
  init_description_helpers();
32528
32708
  init_text_measure();
32529
- H_PAD = 16;
32530
- MAX_LABEL_LINES2 = 3;
32709
+ H_PAD2 = 16;
32710
+ MAX_LABEL_LINES3 = 3;
32531
32711
  MAX_DESC_LINES3 = 2;
32532
32712
  ROOT_FONT_SIZE = 17;
32533
32713
  MIN_FONT_SIZE = 9;
@@ -32914,7 +33094,7 @@ function nodeHeightS(node, hideDescriptions, sc) {
32914
33094
  hideDescriptions
32915
33095
  );
32916
33096
  const labelLineCount = text.labelLines.length;
32917
- const labelH = labelLineCount <= 1 ? SINGLE_LABEL_HEIGHT : LABEL_LINE_HEIGHT2 * labelLineCount;
33097
+ const labelH = labelLineCount <= 1 ? SINGLE_LABEL_HEIGHT : LABEL_LINE_HEIGHT3 * labelLineCount;
32918
33098
  let h = labelH + NODE_V_PAD;
32919
33099
  if (text.descLines.length > 0) {
32920
33100
  h += DESC_LINE_HEIGHT3 * text.descLines.length + 4;
@@ -32934,7 +33114,7 @@ function populateDepthCache(roots) {
32934
33114
  };
32935
33115
  walk(roots, 0);
32936
33116
  }
32937
- var ROOT_WIDTH, DEPTH1_WIDTH, LEAF_WIDTH, SINGLE_LABEL_HEIGHT, LABEL_LINE_HEIGHT2, DESC_LINE_HEIGHT3, NODE_V_PAD, H_GAP2, V_GAP2, MARGIN6, MULTI_ROOT_GAP, nodeDepthCache;
33117
+ var ROOT_WIDTH, DEPTH1_WIDTH, LEAF_WIDTH, SINGLE_LABEL_HEIGHT, LABEL_LINE_HEIGHT3, DESC_LINE_HEIGHT3, NODE_V_PAD, H_GAP2, V_GAP2, MARGIN6, MULTI_ROOT_GAP, nodeDepthCache;
32938
33118
  var init_layout6 = __esm({
32939
33119
  "src/mindmap/layout.ts"() {
32940
33120
  "use strict";
@@ -32945,7 +33125,7 @@ var init_layout6 = __esm({
32945
33125
  DEPTH1_WIDTH = 150;
32946
33126
  LEAF_WIDTH = 120;
32947
33127
  SINGLE_LABEL_HEIGHT = 28;
32948
- LABEL_LINE_HEIGHT2 = 18;
33128
+ LABEL_LINE_HEIGHT3 = 18;
32949
33129
  DESC_LINE_HEIGHT3 = 14;
32950
33130
  NODE_V_PAD = 10;
32951
33131
  H_GAP2 = 40;
@@ -33236,18 +33416,18 @@ function renderMindmap(container, parsed, layout, palette, isDark, onClickItem,
33236
33416
  descFontSize
33237
33417
  } = textLayout;
33238
33418
  const labelLineCount = labelLines.length;
33239
- const labelZoneH = labelLineCount <= 1 ? SINGLE_LABEL_HEIGHT2 : LABEL_LINE_HEIGHT3 * labelLineCount;
33419
+ const labelZoneH = labelLineCount <= 1 ? SINGLE_LABEL_HEIGHT2 : LABEL_LINE_HEIGHT4 * labelLineCount;
33240
33420
  const labelZoneHeight = showDesc ? labelZoneH : node.height;
33241
33421
  const centerX = node.x + node.width / 2;
33242
33422
  if (labelLineCount <= 1) {
33243
33423
  const labelY = node.y + labelZoneHeight / 2 + fontSize * 0.35;
33244
33424
  nodeG.append("text").attr("x", centerX).attr("y", labelY).attr("text-anchor", "middle").attr("font-size", fontSize).attr("font-weight", isRoot ? "bold" : "normal").attr("fill", onFillText).text(labelLines[0]);
33245
33425
  } else {
33246
- const blockH = LABEL_LINE_HEIGHT3 * (labelLineCount - 1);
33426
+ const blockH = LABEL_LINE_HEIGHT4 * (labelLineCount - 1);
33247
33427
  const firstBaselineY = node.y + labelZoneHeight / 2 - blockH / 2 + fontSize * 0.35;
33248
33428
  const textEl = nodeG.append("text").attr("x", centerX).attr("text-anchor", "middle").attr("font-size", fontSize).attr("font-weight", isRoot ? "bold" : "normal").attr("fill", onFillText);
33249
33429
  for (let i = 0; i < labelLines.length; i++) {
33250
- textEl.append("tspan").attr("x", centerX).attr("y", firstBaselineY + i * LABEL_LINE_HEIGHT3).text(labelLines[i]);
33430
+ textEl.append("tspan").attr("x", centerX).attr("y", firstBaselineY + i * LABEL_LINE_HEIGHT4).text(labelLines[i]);
33251
33431
  }
33252
33432
  }
33253
33433
  if (labelLines.length > 1 || labelLines[0] !== node.label) {
@@ -33322,7 +33502,7 @@ function renderMindmapForExport(content, theme, palette) {
33322
33502
  return extractExportSvg(container, theme);
33323
33503
  });
33324
33504
  }
33325
- var d3Selection12, DIAGRAM_PADDING7, TITLE_HEIGHT4, SINGLE_LABEL_HEIGHT2, LABEL_LINE_HEIGHT3, DESC_LINE_HEIGHT4, NODE_RADIUS, ROOT_STROKE_WIDTH, DEPTH_COLOR_KEYS;
33505
+ var d3Selection12, DIAGRAM_PADDING7, TITLE_HEIGHT4, SINGLE_LABEL_HEIGHT2, LABEL_LINE_HEIGHT4, DESC_LINE_HEIGHT4, NODE_RADIUS, ROOT_STROKE_WIDTH, DEPTH_COLOR_KEYS;
33326
33506
  var init_renderer7 = __esm({
33327
33507
  "src/mindmap/renderer.ts"() {
33328
33508
  "use strict";
@@ -33345,7 +33525,7 @@ var init_renderer7 = __esm({
33345
33525
  DIAGRAM_PADDING7 = 20;
33346
33526
  TITLE_HEIGHT4 = 30;
33347
33527
  SINGLE_LABEL_HEIGHT2 = 28;
33348
- LABEL_LINE_HEIGHT3 = 18;
33528
+ LABEL_LINE_HEIGHT4 = 18;
33349
33529
  DESC_LINE_HEIGHT4 = 14;
33350
33530
  NODE_RADIUS = 6;
33351
33531
  ROOT_STROKE_WIDTH = 2.5;
@@ -36012,7 +36192,7 @@ function renderC4Context(container, parsed, layout, palette, isDark, onClickItem
36012
36192
  const labelText = edge.label ?? "";
36013
36193
  const techText = edge.technology ? `[${edge.technology}]` : "";
36014
36194
  const textW = Math.max(
36015
- measureText(labelText, EDGE_LABEL_FONT_SIZE6),
36195
+ measureText(labelText, EDGE_LABEL_FONT_SIZE7),
36016
36196
  measureText(techText, TECH_FONT_SIZE)
36017
36197
  );
36018
36198
  const bgW = textW + 12;
@@ -36023,7 +36203,7 @@ function renderC4Context(container, parsed, layout, palette, isDark, onClickItem
36023
36203
  textY = midPt.y - 4;
36024
36204
  }
36025
36205
  if (labelText) {
36026
- edgeG.append("text").attr("x", midPt.x).attr("y", textY + 4).attr("text-anchor", "middle").attr("fill", edgeColor3).attr("font-size", EDGE_LABEL_FONT_SIZE6).attr("class", "c4-edge-label").text(labelText);
36206
+ edgeG.append("text").attr("x", midPt.x).attr("y", textY + 4).attr("text-anchor", "middle").attr("fill", edgeColor3).attr("font-size", EDGE_LABEL_FONT_SIZE7).attr("class", "c4-edge-label").text(labelText);
36027
36207
  }
36028
36208
  if (techText) {
36029
36209
  edgeG.append("text").attr("x", midPt.x).attr("y", labelText ? textY + 18 : textY + 4).attr("text-anchor", "middle").attr("fill", edgeColor3).attr("font-size", TECH_FONT_SIZE).attr("font-style", "italic").attr("class", "c4-edge-tech").text(techText);
@@ -36207,7 +36387,7 @@ function renderEdges(contentG, edges, palette, onClickItem, obstacleRects) {
36207
36387
  const labelText = edge.label ?? "";
36208
36388
  const techText = edge.technology ? `[${edge.technology}]` : "";
36209
36389
  const textW = Math.max(
36210
- measureText(labelText, EDGE_LABEL_FONT_SIZE6),
36390
+ measureText(labelText, EDGE_LABEL_FONT_SIZE7),
36211
36391
  measureText(techText, TECH_FONT_SIZE)
36212
36392
  );
36213
36393
  const bgW = textW + 12;
@@ -36225,7 +36405,7 @@ function renderEdges(contentG, edges, palette, onClickItem, obstacleRects) {
36225
36405
  });
36226
36406
  }
36227
36407
  }
36228
- placeEdgeLabels(pendingLabels, edges, obstacleRects);
36408
+ placeEdgeLabels2(pendingLabels, edges, obstacleRects);
36229
36409
  for (const lbl of pendingLabels) {
36230
36410
  lbl.edgeG.append("rect").attr("x", lbl.x - lbl.bgW / 2).attr("y", lbl.y - lbl.bgH / 2).attr("width", lbl.bgW).attr("height", lbl.bgH).attr("rx", 3).attr("fill", palette.bg).attr("opacity", 0.9).attr("class", "c4-edge-label-bg");
36231
36411
  let textY = lbl.y;
@@ -36233,7 +36413,7 @@ function renderEdges(contentG, edges, palette, onClickItem, obstacleRects) {
36233
36413
  textY = lbl.y - 4;
36234
36414
  }
36235
36415
  if (lbl.labelText) {
36236
- lbl.edgeG.append("text").attr("x", lbl.x).attr("y", textY + 4).attr("text-anchor", "middle").attr("fill", lbl.edgeColor).attr("font-size", EDGE_LABEL_FONT_SIZE6).attr("class", "c4-edge-label").text(lbl.labelText);
36416
+ lbl.edgeG.append("text").attr("x", lbl.x).attr("y", textY + 4).attr("text-anchor", "middle").attr("fill", lbl.edgeColor).attr("font-size", EDGE_LABEL_FONT_SIZE7).attr("class", "c4-edge-label").text(lbl.labelText);
36237
36417
  }
36238
36418
  if (lbl.techText) {
36239
36419
  lbl.edgeG.append("text").attr("x", lbl.x).attr("y", lbl.labelText ? textY + 18 : textY + 4).attr("text-anchor", "middle").attr("fill", lbl.edgeColor).attr("font-size", TECH_FONT_SIZE).attr("font-style", "italic").attr("class", "c4-edge-tech").text(lbl.techText);
@@ -36314,7 +36494,7 @@ function tangentAt(points, t) {
36314
36494
  }
36315
36495
  return { x: 0, y: 1 };
36316
36496
  }
36317
- function placeEdgeLabels(labels, edges, obstacleRects) {
36497
+ function placeEdgeLabels2(labels, edges, obstacleRects) {
36318
36498
  if (labels.length === 0) return;
36319
36499
  const allPaths = edges.map((e) => e.points);
36320
36500
  const placedRects = [];
@@ -36852,7 +37032,7 @@ function renderC4DeploymentForExport(content, theme, palette) {
36852
37032
  document.body.removeChild(el);
36853
37033
  }
36854
37034
  }
36855
- var d3Selection14, d3Shape6, DIAGRAM_PADDING8, MAX_SCALE5, TITLE_HEIGHT6, TYPE_FONT_SIZE, NAME_FONT_SIZE2, DESC_FONT_SIZE5, DESC_LINE_HEIGHT6, EDGE_LABEL_FONT_SIZE6, TECH_FONT_SIZE, CARD_H_PAD4, CARD_V_PAD4, TYPE_LABEL_HEIGHT2, DIVIDER_GAP2, NAME_HEIGHT2, BOUNDARY_LABEL_FONT_SIZE, BOUNDARY_STROKE_WIDTH, BOUNDARY_RADIUS, DRILL_BAR_HEIGHT, CYLINDER_RY, PERSON_HEAD_R, PERSON_ARM_SPAN, PERSON_LEG_SPAN, PERSON_ICON_W, PERSON_SW, lineGenerator4;
37035
+ var d3Selection14, d3Shape6, DIAGRAM_PADDING8, MAX_SCALE5, TITLE_HEIGHT6, TYPE_FONT_SIZE, NAME_FONT_SIZE2, DESC_FONT_SIZE5, DESC_LINE_HEIGHT6, EDGE_LABEL_FONT_SIZE7, TECH_FONT_SIZE, CARD_H_PAD4, CARD_V_PAD4, TYPE_LABEL_HEIGHT2, DIVIDER_GAP2, NAME_HEIGHT2, BOUNDARY_LABEL_FONT_SIZE, BOUNDARY_STROKE_WIDTH, BOUNDARY_RADIUS, DRILL_BAR_HEIGHT, CYLINDER_RY, PERSON_HEAD_R, PERSON_ARM_SPAN, PERSON_LEG_SPAN, PERSON_ICON_W, PERSON_SW, lineGenerator4;
36856
37036
  var init_renderer9 = __esm({
36857
37037
  "src/c4/renderer.ts"() {
36858
37038
  "use strict";
@@ -36877,7 +37057,7 @@ var init_renderer9 = __esm({
36877
37057
  NAME_FONT_SIZE2 = 14;
36878
37058
  DESC_FONT_SIZE5 = 11;
36879
37059
  DESC_LINE_HEIGHT6 = 16;
36880
- EDGE_LABEL_FONT_SIZE6 = 11;
37060
+ EDGE_LABEL_FONT_SIZE7 = 11;
36881
37061
  TECH_FONT_SIZE = 10;
36882
37062
  CARD_H_PAD4 = 20;
36883
37063
  CARD_V_PAD4 = 14;
@@ -37501,7 +37681,7 @@ function renderFlowchart(container, graph, layout, palette, isDark, onClickItem,
37501
37681
  const sTitleFontSize = ctx.text(TITLE_FONT_SIZE);
37502
37682
  const sTitleY = ctx.structural(TITLE_Y);
37503
37683
  const sNodeFontSize = ctx.text(NODE_FONT_SIZE2);
37504
- const sEdgeLabelFontSize = ctx.text(EDGE_LABEL_FONT_SIZE7);
37684
+ const sEdgeLabelFontSize = ctx.text(EDGE_LABEL_FONT_SIZE8);
37505
37685
  const sEdgeStrokeWidth = ctx.structural(EDGE_STROKE_WIDTH);
37506
37686
  const sNodeStrokeWidth = ctx.structural(NODE_STROKE_WIDTH);
37507
37687
  const sArrowheadW = ctx.structural(ARROWHEAD_W3);
@@ -37727,7 +37907,7 @@ function renderFlowchartForExport(content, theme, palette) {
37727
37907
  document.body.removeChild(container);
37728
37908
  }
37729
37909
  }
37730
- var d3Selection15, DIAGRAM_PADDING9, MAX_SCALE6, NODE_FONT_SIZE2, EDGE_LABEL_FONT_SIZE7, ARROWHEAD_W3, ARROWHEAD_H3, IO_SKEW, SUBROUTINE_INSET, DOC_WAVE_HEIGHT;
37910
+ var d3Selection15, DIAGRAM_PADDING9, MAX_SCALE6, NODE_FONT_SIZE2, EDGE_LABEL_FONT_SIZE8, ARROWHEAD_W3, ARROWHEAD_H3, IO_SKEW, SUBROUTINE_INSET, DOC_WAVE_HEIGHT;
37731
37911
  var init_flowchart_renderer = __esm({
37732
37912
  "src/graph/flowchart-renderer.ts"() {
37733
37913
  "use strict";
@@ -37747,7 +37927,7 @@ var init_flowchart_renderer = __esm({
37747
37927
  DIAGRAM_PADDING9 = 20;
37748
37928
  MAX_SCALE6 = 3;
37749
37929
  NODE_FONT_SIZE2 = 13;
37750
- EDGE_LABEL_FONT_SIZE7 = 11;
37930
+ EDGE_LABEL_FONT_SIZE8 = 11;
37751
37931
  ARROWHEAD_W3 = 10;
37752
37932
  ARROWHEAD_H3 = 7;
37753
37933
  IO_SKEW = 15;
@@ -39181,7 +39361,7 @@ function layoutInfra(computed, expandedNodeIds, collapsedNodes) {
39181
39361
  const midIdx = Math.floor(edge.points.length / 2);
39182
39362
  const midPt = edge.points[midIdx];
39183
39363
  if (midPt) {
39184
- const halfWidth = (measureText(edge.label, EDGE_LABEL_FONT_SIZE8) + 8) / 2;
39364
+ const halfWidth = (measureText(edge.label, EDGE_LABEL_FONT_SIZE9) + 8) / 2;
39185
39365
  if (midPt.x - halfWidth < minX) minX = midPt.x - halfWidth;
39186
39366
  if (midPt.x + halfWidth > maxX) maxX = midPt.x + halfWidth;
39187
39367
  }
@@ -39215,7 +39395,7 @@ function layoutInfra(computed, expandedNodeIds, collapsedNodes) {
39215
39395
  height: totalHeight
39216
39396
  };
39217
39397
  }
39218
- var import_dagre7, MIN_NODE_WIDTH2, NODE_HEADER_HEIGHT, META_LINE_HEIGHT5, NODE_SEPARATOR_GAP, NODE_PAD_BOTTOM, ROLE_DOT_ROW, COLLAPSE_BAR_HEIGHT3, NODE_FONT_SIZE3, META_FONT_SIZE5, EDGE_LABEL_FONT_SIZE8, PADDING_X3, GROUP_PADDING2, GROUP_HEADER_HEIGHT, EDGE_MARGIN, DISPLAY_KEYS, DISPLAY_NAMES, GROUP_GAP2;
39398
+ var import_dagre7, MIN_NODE_WIDTH2, NODE_HEADER_HEIGHT, META_LINE_HEIGHT5, NODE_SEPARATOR_GAP, NODE_PAD_BOTTOM, ROLE_DOT_ROW, COLLAPSE_BAR_HEIGHT3, NODE_FONT_SIZE3, META_FONT_SIZE5, EDGE_LABEL_FONT_SIZE9, PADDING_X3, GROUP_PADDING2, GROUP_HEADER_HEIGHT, EDGE_MARGIN, DISPLAY_KEYS, DISPLAY_NAMES, GROUP_GAP2;
39219
39399
  var init_layout10 = __esm({
39220
39400
  "src/infra/layout.ts"() {
39221
39401
  "use strict";
@@ -39230,7 +39410,7 @@ var init_layout10 = __esm({
39230
39410
  COLLAPSE_BAR_HEIGHT3 = 6;
39231
39411
  NODE_FONT_SIZE3 = 13;
39232
39412
  META_FONT_SIZE5 = 10;
39233
- EDGE_LABEL_FONT_SIZE8 = 11;
39413
+ EDGE_LABEL_FONT_SIZE9 = 11;
39234
39414
  PADDING_X3 = 24;
39235
39415
  GROUP_PADDING2 = 20;
39236
39416
  GROUP_HEADER_HEIGHT = 24;
@@ -39335,7 +39515,7 @@ function buildScaledConstants(ctx) {
39335
39515
  sNodeFontSize: ctx.text(NODE_FONT_SIZE4),
39336
39516
  sMetaFontSize: ctx.text(META_FONT_SIZE6),
39337
39517
  sMetaLineHeight: ctx.structural(META_LINE_HEIGHT6),
39338
- sEdgeLabelFontSize: ctx.text(EDGE_LABEL_FONT_SIZE9),
39518
+ sEdgeLabelFontSize: ctx.text(EDGE_LABEL_FONT_SIZE10),
39339
39519
  sGroupLabelFontSize: ctx.text(GROUP_LABEL_FONT_SIZE2),
39340
39520
  sNodeBorderRadius: ctx.structural(NODE_BORDER_RADIUS),
39341
39521
  sEdgeStrokeWidth: ctx.structural(EDGE_STROKE_WIDTH),
@@ -40064,7 +40244,7 @@ function renderEdgeLabels(svg, edges, nodes, groups, palette, _isDark, animate,
40064
40244
  if (!midPt) continue;
40065
40245
  const labelText = edge.label;
40066
40246
  const g = svg.append("g").attr("class", animate ? "infra-edge-label" : "");
40067
- const textWidth = measureText(labelText, EDGE_LABEL_FONT_SIZE9) + 8;
40247
+ const textWidth = measureText(labelText, EDGE_LABEL_FONT_SIZE10) + 8;
40068
40248
  g.append("rect").attr("x", midPt.x - textWidth / 2).attr("y", midPt.y - 8).attr("width", textWidth).attr("height", 16).attr("rx", 3).attr("fill", palette.bg).attr("opacity", 0.9);
40069
40249
  g.append("text").attr("x", midPt.x).attr("y", midPt.y + 4).attr("text-anchor", "middle").attr("font-family", FONT_FAMILY).attr("font-size", sc.sEdgeLabelFontSize).attr("fill", palette.textMuted).text(labelText);
40070
40250
  if (animate) {
@@ -40674,7 +40854,7 @@ function parseAndLayoutInfra(content) {
40674
40854
  const layout = layoutInfra(computed);
40675
40855
  return { parsed, computed, layout };
40676
40856
  }
40677
- var d3Selection16, d3Shape8, NODE_FONT_SIZE4, META_FONT_SIZE6, META_LINE_HEIGHT6, EDGE_LABEL_FONT_SIZE9, GROUP_LABEL_FONT_SIZE2, NODE_BORDER_RADIUS, OVERLOAD_STROKE_WIDTH, ROLE_DOT_RADIUS, NODE_HEADER_HEIGHT2, NODE_SEPARATOR_GAP2, NODE_PAD_BOTTOM2, LEGEND_FIXED_GAP3, SPEED_BADGE_H_PAD, SPEED_BADGE_V_PAD, SPEED_BADGE_GAP, COLOR_HEALTHY, COLOR_WARNING, COLOR_OVERLOADED, FLOW_SPEED_MIN, FLOW_SPEED_MAX, PARTICLE_R, PARTICLE_COUNT_MIN, PARTICLE_COUNT_MAX, NODE_PULSE_SPEED, NODE_PULSE_OVERLOAD, REJECT_DROP_DISTANCE, REJECT_DURATION_MIN, REJECT_DURATION_MAX, REJECT_COUNT_MIN, REJECT_COUNT_MAX, PROP_DISPLAY, DESC_MAX_CHARS, DESC_MAX_WIDTH, RPS_FORMAT_KEYS, MS_FORMAT_KEYS, PCT_FORMAT_KEYS;
40857
+ var d3Selection16, d3Shape8, NODE_FONT_SIZE4, META_FONT_SIZE6, META_LINE_HEIGHT6, EDGE_LABEL_FONT_SIZE10, GROUP_LABEL_FONT_SIZE2, NODE_BORDER_RADIUS, OVERLOAD_STROKE_WIDTH, ROLE_DOT_RADIUS, NODE_HEADER_HEIGHT2, NODE_SEPARATOR_GAP2, NODE_PAD_BOTTOM2, LEGEND_FIXED_GAP3, SPEED_BADGE_H_PAD, SPEED_BADGE_V_PAD, SPEED_BADGE_GAP, COLOR_HEALTHY, COLOR_WARNING, COLOR_OVERLOADED, FLOW_SPEED_MIN, FLOW_SPEED_MAX, PARTICLE_R, PARTICLE_COUNT_MIN, PARTICLE_COUNT_MAX, NODE_PULSE_SPEED, NODE_PULSE_OVERLOAD, REJECT_DROP_DISTANCE, REJECT_DURATION_MIN, REJECT_DURATION_MAX, REJECT_COUNT_MIN, REJECT_COUNT_MAX, PROP_DISPLAY, DESC_MAX_CHARS, DESC_MAX_WIDTH, RPS_FORMAT_KEYS, MS_FORMAT_KEYS, PCT_FORMAT_KEYS;
40678
40858
  var init_renderer10 = __esm({
40679
40859
  "src/infra/renderer.ts"() {
40680
40860
  "use strict";
@@ -40700,7 +40880,7 @@ var init_renderer10 = __esm({
40700
40880
  NODE_FONT_SIZE4 = 13;
40701
40881
  META_FONT_SIZE6 = 10;
40702
40882
  META_LINE_HEIGHT6 = 14;
40703
- EDGE_LABEL_FONT_SIZE9 = 11;
40883
+ EDGE_LABEL_FONT_SIZE10 = 11;
40704
40884
  GROUP_LABEL_FONT_SIZE2 = 14;
40705
40885
  NODE_BORDER_RADIUS = 8;
40706
40886
  OVERLOAD_STROKE_WIDTH = 3;
@@ -47091,7 +47271,7 @@ function renderState(container, graph, layout, palette, isDark, onClickItem, exp
47091
47271
  const sTitleFontSize = ctx.text(TITLE_FONT_SIZE);
47092
47272
  const sTitleY = ctx.structural(TITLE_Y);
47093
47273
  const sNodeFontSize = ctx.text(NODE_FONT_SIZE6);
47094
- const sEdgeLabelFontSize = ctx.text(EDGE_LABEL_FONT_SIZE10);
47274
+ const sEdgeLabelFontSize = ctx.text(EDGE_LABEL_FONT_SIZE11);
47095
47275
  const sGroupLabelFontSize = ctx.text(GROUP_LABEL_FONT_SIZE3);
47096
47276
  const sEdgeStrokeWidth = ctx.structural(EDGE_STROKE_WIDTH);
47097
47277
  const sNodeStrokeWidth = ctx.structural(NODE_STROKE_WIDTH);
@@ -47371,7 +47551,7 @@ function renderStateForExport(content, theme, palette) {
47371
47551
  document.body.removeChild(container);
47372
47552
  }
47373
47553
  }
47374
- var d3Selection19, DIAGRAM_PADDING12, MAX_SCALE7, NODE_FONT_SIZE6, EDGE_LABEL_FONT_SIZE10, GROUP_LABEL_FONT_SIZE3, ARROWHEAD_W5, ARROWHEAD_H5, PSEUDOSTATE_RADIUS, STATE_CORNER_RADIUS, GROUP_EXTRA_PADDING;
47554
+ var d3Selection19, DIAGRAM_PADDING12, MAX_SCALE7, NODE_FONT_SIZE6, EDGE_LABEL_FONT_SIZE11, GROUP_LABEL_FONT_SIZE3, ARROWHEAD_W5, ARROWHEAD_H5, PSEUDOSTATE_RADIUS, STATE_CORNER_RADIUS, GROUP_EXTRA_PADDING;
47375
47555
  var init_state_renderer = __esm({
47376
47556
  "src/graph/state-renderer.ts"() {
47377
47557
  "use strict";
@@ -47391,7 +47571,7 @@ var init_state_renderer = __esm({
47391
47571
  DIAGRAM_PADDING12 = 20;
47392
47572
  MAX_SCALE7 = 3;
47393
47573
  NODE_FONT_SIZE6 = 13;
47394
- EDGE_LABEL_FONT_SIZE10 = 11;
47574
+ EDGE_LABEL_FONT_SIZE11 = 11;
47395
47575
  GROUP_LABEL_FONT_SIZE3 = 11;
47396
47576
  ARROWHEAD_W5 = 10;
47397
47577
  ARROWHEAD_H5 = 7;
@@ -50433,10 +50613,10 @@ function renderedDescNodeHeight(numLines, scale) {
50433
50613
  return headerH + textBlockH + bottomPad;
50434
50614
  }
50435
50615
  function wrapEdgeLabelText(label, description, maxWidth = EDGE_LABEL_MAX_WIDTH) {
50436
- const labelLines = label ? wrapTextToWidth(label, EDGE_LABEL_FONT_SIZE11, maxWidth) : [];
50616
+ const labelLines = label ? wrapTextToWidth(label, EDGE_LABEL_FONT_SIZE12, maxWidth) : [];
50437
50617
  const descLines = [];
50438
50618
  for (const d of description) {
50439
- descLines.push(...wrapTextToWidth(d, EDGE_LABEL_FONT_SIZE11, maxWidth));
50619
+ descLines.push(...wrapTextToWidth(d, EDGE_LABEL_FONT_SIZE12, maxWidth));
50440
50620
  }
50441
50621
  return { labelLines, descLines };
50442
50622
  }
@@ -50574,9 +50754,9 @@ function computeEdgePaths(layoutNodes, parsed, cx, cy, radius, isClockwise) {
50574
50754
  const lineCount = labelLines.length + descLines.length;
50575
50755
  let labelPxW = 0;
50576
50756
  for (const l of labelLines)
50577
- labelPxW = Math.max(labelPxW, measureText(l, EDGE_LABEL_FONT_SIZE11));
50757
+ labelPxW = Math.max(labelPxW, measureText(l, EDGE_LABEL_FONT_SIZE12));
50578
50758
  for (const l of descLines)
50579
- labelPxW = Math.max(labelPxW, measureText(l, EDGE_LABEL_FONT_SIZE11));
50759
+ labelPxW = Math.max(labelPxW, measureText(l, EDGE_LABEL_FONT_SIZE12));
50580
50760
  const { labelX, labelY, labelAngle } = computeEdgeLabelPosition(
50581
50761
  midAngle,
50582
50762
  radius,
@@ -50678,9 +50858,9 @@ function fitToCanvas(nodes, edges, parsed, _cx, _cy, radius, width, height, _isC
50678
50858
  );
50679
50859
  let textWidth = 0;
50680
50860
  for (const l of labelLines)
50681
- textWidth = Math.max(textWidth, measureText(l, EDGE_LABEL_FONT_SIZE11));
50861
+ textWidth = Math.max(textWidth, measureText(l, EDGE_LABEL_FONT_SIZE12));
50682
50862
  for (const l of descLines)
50683
- textWidth = Math.max(textWidth, measureText(l, EDGE_LABEL_FONT_SIZE11));
50863
+ textWidth = Math.max(textWidth, measureText(l, EDGE_LABEL_FONT_SIZE12));
50684
50864
  if (textWidth === 0) continue;
50685
50865
  const normAngle = (le.labelAngle % (2 * Math.PI) + 2 * Math.PI) % (2 * Math.PI);
50686
50866
  const isRight = normAngle < Math.PI * 0.4 || normAngle > Math.PI * 1.6;
@@ -50754,7 +50934,7 @@ function buildEdgeArc(src, tgt, cx, cy, radius, isClockwise, arrowLength = 0) {
50754
50934
  const midAngle = srcExitAngle + dir * visibleSweep / 2;
50755
50935
  return { path, midAngle };
50756
50936
  }
50757
- var MIN_ARC_ANGLE, LABEL_FONT_SIZE4, CIRCLE_LABEL_FONT_SIZE, DESC_FONT_SIZE6, EDGE_LABEL_FONT_SIZE11, MIN_NODE_WIDTH4, MAX_NODE_WIDTH3, DESC_MIN_WIDTH, DESC_WIDTH_STEP, DESC_TARGET_RATIO, PLAIN_NODE_HEIGHT, HEADER_HEIGHT4, DESC_LINE_HEIGHT7, DESC_PAD_Y, NODE_PAD_X, MIN_CIRCLE_RADIUS, CIRCLE_PAD, RENDERER_DESC_FONT, RENDERER_DESC_FONT_MIN, RENDERER_DESC_LINE_H, RENDERER_DESC_LINE_H_MIN, EDGE_LABEL_MAX_WIDTH;
50937
+ var MIN_ARC_ANGLE, LABEL_FONT_SIZE4, CIRCLE_LABEL_FONT_SIZE, DESC_FONT_SIZE6, EDGE_LABEL_FONT_SIZE12, MIN_NODE_WIDTH4, MAX_NODE_WIDTH3, DESC_MIN_WIDTH, DESC_WIDTH_STEP, DESC_TARGET_RATIO, PLAIN_NODE_HEIGHT, HEADER_HEIGHT4, DESC_LINE_HEIGHT7, DESC_PAD_Y, NODE_PAD_X, MIN_CIRCLE_RADIUS, CIRCLE_PAD, RENDERER_DESC_FONT, RENDERER_DESC_FONT_MIN, RENDERER_DESC_LINE_H, RENDERER_DESC_LINE_H_MIN, EDGE_LABEL_MAX_WIDTH;
50758
50938
  var init_layout14 = __esm({
50759
50939
  "src/cycle/layout.ts"() {
50760
50940
  "use strict";
@@ -50765,7 +50945,7 @@ var init_layout14 = __esm({
50765
50945
  LABEL_FONT_SIZE4 = 13;
50766
50946
  CIRCLE_LABEL_FONT_SIZE = 16;
50767
50947
  DESC_FONT_SIZE6 = 11;
50768
- EDGE_LABEL_FONT_SIZE11 = 11;
50948
+ EDGE_LABEL_FONT_SIZE12 = 11;
50769
50949
  MIN_NODE_WIDTH4 = 70;
50770
50950
  MAX_NODE_WIDTH3 = 260;
50771
50951
  DESC_MIN_WIDTH = 140;
@@ -50910,7 +51090,7 @@ function renderCycle(container, parsed, palette, isDark, onClickItem, exportDims
50910
51090
  const scaledNodeFont = Math.max(6, Math.round(NODE_FONT_SIZE7 * layout.scale));
50911
51091
  const scaledEdgeLabelFont = Math.max(
50912
51092
  6,
50913
- Math.round(EDGE_LABEL_FONT_SIZE12 * layout.scale)
51093
+ Math.round(EDGE_LABEL_FONT_SIZE13 * layout.scale)
50914
51094
  );
50915
51095
  const CIRCLE_LABEL_FONT_SIZE2 = 16;
50916
51096
  const scaledCircleLabelFont = Math.max(
@@ -51073,7 +51253,7 @@ function ensureArrowMarker(defs, color, strokeWidth) {
51073
51253
  const mh = Math.max(1.5, mw * 0.5);
51074
51254
  defs.append("marker").attr("id", id).attr("viewBox", `0 0 ${mw} ${mh}`).attr("refX", mw * 0.1).attr("refY", mh / 2).attr("markerWidth", mw).attr("markerHeight", mh).attr("orient", "auto").append("polygon").attr("points", `0,0 ${mw},${mh / 2} 0,${mh}`).attr("fill", color);
51075
51255
  }
51076
- var d3Selection22, NODE_FONT_SIZE7, DESC_FONT_SIZE7, EDGE_LABEL_FONT_SIZE12, DESC_LINE_HEIGHT8, TITLE_AREA_HEIGHT;
51256
+ var d3Selection22, NODE_FONT_SIZE7, DESC_FONT_SIZE7, EDGE_LABEL_FONT_SIZE13, DESC_LINE_HEIGHT8, TITLE_AREA_HEIGHT;
51077
51257
  var init_renderer15 = __esm({
51078
51258
  "src/cycle/renderer.ts"() {
51079
51259
  "use strict";
@@ -51091,7 +51271,7 @@ var init_renderer15 = __esm({
51091
51271
  init_text_measure();
51092
51272
  NODE_FONT_SIZE7 = 13;
51093
51273
  DESC_FONT_SIZE7 = 11;
51094
- EDGE_LABEL_FONT_SIZE12 = 11;
51274
+ EDGE_LABEL_FONT_SIZE13 = 11;
51095
51275
  DESC_LINE_HEIGHT8 = 15;
51096
51276
  TITLE_AREA_HEIGHT = 50;
51097
51277
  }