@cardenelabs/cdl 0.121.0 → 0.123.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.
Files changed (69) hide show
  1. package/CHANGELOG.md +51 -1
  2. package/README.md +137 -0
  3. package/SPEC.md +1 -1
  4. package/dist/index.cjs +1513 -667
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.d.cts +51 -33
  7. package/dist/index.d.ts +51 -33
  8. package/dist/index.js +1513 -668
  9. package/dist/index.js.map +1 -1
  10. package/dist/react.cjs +1271 -444
  11. package/dist/react.cjs.map +1 -1
  12. package/dist/react.d.cts +1 -1
  13. package/dist/react.d.ts +1 -1
  14. package/dist/react.js +1271 -444
  15. package/dist/react.js.map +1 -1
  16. package/dist/{render-A5AKjNuy.d.cts → render-CVczwfRb.d.cts} +40 -7
  17. package/dist/{render-A5AKjNuy.d.ts → render-CVczwfRb.d.ts} +40 -7
  18. package/package.json +9 -12
  19. package/src/builder.ts +8 -2
  20. package/src/index.ts +3 -0
  21. package/src/kinds/box-lines.ts +17 -4
  22. package/src/kinds/chart-bar.tsx +4 -0
  23. package/src/kinds/chart-gauge.tsx +20 -9
  24. package/src/kinds/chart-pie.tsx +67 -17
  25. package/src/kinds/chart-radial.tsx +7 -2
  26. package/src/kinds/chart-slope.tsx +26 -7
  27. package/src/kinds/chart-stacked-bar.tsx +8 -4
  28. package/src/kinds/chart-stat.tsx +19 -4
  29. package/src/kinds/chart-waffle.tsx +7 -2
  30. package/src/kinds/dyn-shape.tsx +22 -9
  31. package/src/kinds/funnel.tsx +9 -2
  32. package/src/kinds/generic.tsx +5 -2
  33. package/src/kinds/mind-map.tsx +26 -10
  34. package/src/kinds/quadrant.tsx +14 -4
  35. package/src/kinds/row-align.ts +19 -7
  36. package/src/kinds/sequence-board-metrics.ts +13 -3
  37. package/src/kinds/sequence-board.tsx +4 -2
  38. package/src/kinds/shape-basement.tsx +57 -32
  39. package/src/kinds/shape-blockchain.tsx +83 -34
  40. package/src/kinds/shape-commerce.tsx +65 -24
  41. package/src/kinds/shape-finance.tsx +90 -26
  42. package/src/kinds/shape-hardware.tsx +48 -17
  43. package/src/kinds/shape-region.tsx +16 -6
  44. package/src/kinds/shape-software.tsx +30 -8
  45. package/src/kinds/station.tsx +29 -0
  46. package/src/kinds/text-width.ts +17 -3
  47. package/src/kinds/tree.tsx +25 -7
  48. package/src/layout/collisions.ts +50 -28
  49. package/src/layout/curve-path.ts +126 -0
  50. package/src/layout/edges.ts +271 -58
  51. package/src/layout/head-label.ts +11 -5
  52. package/src/layout/lanes.ts +3 -2
  53. package/src/layout/metro-path.ts +185 -0
  54. package/src/layout/nodes.ts +14 -6
  55. package/src/layout/predict-bbox.ts +6 -3
  56. package/src/layout/self-loop.ts +10 -4
  57. package/src/layout/spec.ts +36 -7
  58. package/src/layout/text-width.ts +25 -8
  59. package/src/layout/tokens.ts +2 -0
  60. package/src/layout-with-validation.ts +10 -5
  61. package/src/layout.ts +55 -21
  62. package/src/presets.ts +69 -43
  63. package/src/render/edges.tsx +19 -3
  64. package/src/render/interactive-panel.tsx +34 -7
  65. package/src/render/nodes.tsx +100 -48
  66. package/src/render/stage.tsx +3 -0
  67. package/src/text-metrics.ts +9 -0
  68. package/src/types.ts +41 -4
  69. package/src/visual-validate.ts +91 -21
package/dist/react.js CHANGED
@@ -715,6 +715,11 @@ function \u5B57\u3092\u5DEE\u3057\u8FBC\u3080(template, values) {
715
715
  return template.replace(/\{(\w+)\}/g, (whole, name) => name in values ? String(values[name]) : whole);
716
716
  }
717
717
 
718
+ // src/text-metrics.ts
719
+ function resolveTextMetrics(value) {
720
+ return value === "monospace" ? "monospace" : "proportional";
721
+ }
722
+
718
723
  // src/layout/clearance-constants.ts
719
724
  var CLEARANCE_NODE_LABEL = 32;
720
725
  var CLEARANCE_LANE_LABEL = 24;
@@ -876,10 +881,10 @@ function defaultAdvanceEm(ch, code) {
876
881
  if (ch >= "0" && ch <= "9") return 0.72;
877
882
  return 0.65;
878
883
  }
879
- function measureTextWidth(text, opts = {}) {
884
+ function measureAdvanceWidth(text, opts = {}) {
880
885
  const fontSize = opts.fontSize ?? 22;
881
886
  const letterSpacing = opts.letterSpacing ?? 0;
882
- const fontFamily = opts.fontFamily ?? "sans";
887
+ const fontFamily = opts.textMetrics === "monospace" ? "mono" : opts.fontFamily ?? "sans";
883
888
  const bound = opts.bound ?? "layout";
884
889
  let advanceEmSum = 0;
885
890
  let charCount = 0;
@@ -887,7 +892,7 @@ function measureTextWidth(text, opts = {}) {
887
892
  for (const ch of \u6587\u5B57\u5217) {
888
893
  charCount++;
889
894
  const code = ch.codePointAt(0) ?? 0;
890
- const \u5272\u308A\u623B\u3057 = bound === "drawn" && !isEmojiGrapheme(ch, code) ? isAscii(code) ? DRAWN_ASCII_RATIO : isCJK(code) ? DRAWN_CJK_RATIO : 1 : 1;
895
+ const \u5272\u308A\u623B\u3057 = bound === "drawn" && !isEmojiGrapheme(ch, code) ? isAscii(code) && fontFamily !== "mono" ? DRAWN_ASCII_RATIO : isCJK(code) ? DRAWN_CJK_RATIO : 1 : 1;
891
896
  if (isEmojiGrapheme(ch, code)) {
892
897
  advanceEmSum += fontFamily === "mono" ? MONO_EMOJI_ADVANCE_EM : EMOJI_ADVANCE_EM;
893
898
  continue;
@@ -903,7 +908,12 @@ function measureTextWidth(text, opts = {}) {
903
908
  const table = ch.length === 1 ? INTER_BOLD_ADVANCE_EM[ch] : void 0;
904
909
  advanceEmSum += (table !== void 0 ? table : defaultAdvanceEm(ch, code)) / \u5272\u308A\u623B\u3057;
905
910
  }
906
- const w = advanceEmSum * fontSize + letterSpacing * charCount;
911
+ return advanceEmSum * fontSize + letterSpacing * charCount;
912
+ }
913
+ function measureTextWidth(text, opts = {}) {
914
+ const fontSize = opts.fontSize ?? 22;
915
+ const bound = opts.bound ?? "layout";
916
+ const w = measureAdvanceWidth(text, opts);
907
917
  return bound === "drawn" ? w : Math.max(w, fontSize * 1.2);
908
918
  }
909
919
  function \u53CE\u3081\u308B\u500D\u7387(text, opts, \u5E45) {
@@ -986,6 +996,7 @@ var KINDS_DRAWING_TITLE_OUTSIDE = /* @__PURE__ */ new Set([
986
996
  "dyn-arc",
987
997
  "dyn-wave",
988
998
  "dyn-polygon",
999
+ "station",
989
1000
  ...KINDS_DRAWING_OWN_PAYLOAD
990
1001
  ]);
991
1002
  function drawsTitleOutsideBox(kind) {
@@ -993,7 +1004,7 @@ function drawsTitleOutsideBox(kind) {
993
1004
  }
994
1005
  var TITLE_FONT_SIZE_DEFAULT = 18;
995
1006
  var TITLE_FONT_SIZE = new Map([
996
- ...["dyn-rect", "dyn-circle", "dyn-arc", "dyn-wave", "dyn-polygon"].map(
1007
+ ...["dyn-rect", "dyn-circle", "dyn-arc", "dyn-wave", "dyn-polygon", "station"].map(
997
1008
  (k) => [k, 13]
998
1009
  ),
999
1010
  ...[
@@ -1044,6 +1055,10 @@ var TITLE_FONT_SIZE = new Map([
1044
1055
  function titleFontSize(kind) {
1045
1056
  return TITLE_FONT_SIZE.get(kind ?? "") ?? TITLE_FONT_SIZE_DEFAULT;
1046
1057
  }
1058
+ var KINDS_WITH_TITLE_WIDTH_OUTSIDE_NODE = /* @__PURE__ */ new Set(["station"]);
1059
+ function skipsNodeTitleWidthCheck(kind) {
1060
+ return KINDS_WITH_TITLE_WIDTH_OUTSIDE_NODE.has(kind ?? "");
1061
+ }
1047
1062
  var TITLE_BOX_PADDING = 52;
1048
1063
  var KINDS_SCALING_TITLE_WHEN_LOW = /* @__PURE__ */ new Set(["actor", "event", "function", "storage"]);
1049
1064
  var KINDS_SCALING_TITLE_ALWAYS = /* @__PURE__ */ new Set([
@@ -1126,7 +1141,8 @@ var KINDS_DRAWING_ONLY_SHAPE = [
1126
1141
  "dyn-circle",
1127
1142
  "dyn-arc",
1128
1143
  "dyn-wave",
1129
- "dyn-polygon"
1144
+ "dyn-polygon",
1145
+ "station"
1130
1146
  ];
1131
1147
  var KINDS_WITHOUT_EYEBROW_TEXT = /* @__PURE__ */ new Set([
1132
1148
  ...KINDS_DRAWING_ONLY_SHAPE,
@@ -1265,15 +1281,22 @@ function requiredVerticalLabelGap(pillHs) {
1265
1281
  const step = parallelLabelStepY(pillHs);
1266
1282
  return (pillHs.length - 1) * step + Math.max(first, last) + CLEARANCE_NODE_LABEL * 2;
1267
1283
  }
1268
- function computeLabelBoxW(label, sub) {
1269
- const mainW = measureTextWidth(label ?? "", { fontSize: EDGE_LABEL_TEXT.main.fontSize });
1270
- const subW = sub ? measureTextWidth(sub, { fontSize: EDGE_LABEL_TEXT.sub.fontSize, fontFamily: "mono" }) : 0;
1284
+ function computeLabelBoxW(label, sub, textMetrics = "proportional") {
1285
+ const mainW = measureTextWidth(label ?? "", {
1286
+ fontSize: EDGE_LABEL_TEXT.main.fontSize,
1287
+ textMetrics
1288
+ });
1289
+ const subW = sub ? measureTextWidth(sub, {
1290
+ fontSize: EDGE_LABEL_TEXT.sub.fontSize,
1291
+ fontFamily: "mono",
1292
+ textMetrics
1293
+ }) : 0;
1271
1294
  const raw = Math.max(mainW, subW) + LABEL_PILL_PAD_X * 2;
1272
1295
  const EPSILON = 1e-6;
1273
1296
  return Math.ceil((raw - EPSILON) / 2) * 2;
1274
1297
  }
1275
- function computeLabelBBoxWorld(edge) {
1276
- const boxW = computeLabelBoxW(edge.label, edge.sub);
1298
+ function computeLabelBBoxWorld(edge, textMetrics = "proportional") {
1299
+ const boxW = computeLabelBoxW(edge.label, edge.sub, textMetrics);
1277
1300
  const boxH = edge.sub ? LABEL_PILL_H_WITH_SUB : LABEL_PILL_H_MAIN_ONLY;
1278
1301
  const anchor = edge.labelAnchor;
1279
1302
  const boxLeftX = anchor === "start" ? 0 : anchor === "end" ? -boxW : -boxW / 2;
@@ -1497,7 +1520,7 @@ function footerShapeDrawTop(node) {
1497
1520
  // src/layout/collisions.ts
1498
1521
  var LANE_LABEL_CLEARANCE_MARGIN = 2;
1499
1522
  var NEAR_MISS_MARGIN = LANE_LABEL_CLEARANCE_MARGIN;
1500
- function collectBBoxes(lanes, nodes, edges) {
1523
+ function collectBBoxes(lanes, nodes, edges, textMetrics = "proportional") {
1501
1524
  const out = [];
1502
1525
  for (const lane of lanes) {
1503
1526
  if (!lane.label) continue;
@@ -1506,7 +1529,7 @@ function collectBBoxes(lanes, nodes, edges) {
1506
1529
  id: lane.id,
1507
1530
  x: lane.x + 16,
1508
1531
  y: lane.y + 8,
1509
- w: measureTextWidth(lane.label, { fontSize: 20, letterSpacing: 2 }) + 24,
1532
+ w: measureTextWidth(lane.label, { fontSize: 20, letterSpacing: 2, textMetrics }) + 24,
1510
1533
  h: 28
1511
1534
  });
1512
1535
  }
@@ -1524,7 +1547,7 @@ function collectBBoxes(lanes, nodes, edges) {
1524
1547
  }
1525
1548
  for (const e of edges) {
1526
1549
  if (!hasRenderedLabel(e)) continue;
1527
- const bbox = computeLabelBBoxWorld(e);
1550
+ const bbox = computeLabelBBoxWorld(e, textMetrics);
1528
1551
  out.push({
1529
1552
  kind: "edge-label",
1530
1553
  id: e.id,
@@ -1829,13 +1852,13 @@ function detectCollisions(bboxes, edges) {
1829
1852
  }
1830
1853
  function extractPathSegments(d) {
1831
1854
  const segs = [];
1832
- const commandRegex = /([MLCQZmlcqz])([^MLCQZmlcqz]*)/g;
1855
+ const commandRegex = /([MLCQAZmlcqaz])([^MLCQAZmlcqaz]*)/g;
1833
1856
  let cur = { x: 0, y: 0 };
1834
1857
  let m;
1835
1858
  while ((m = commandRegex.exec(d)) !== null) {
1836
1859
  const cmd = m[1];
1837
1860
  const args = (m[2] ?? "").trim().split(/[\s,]+/).filter(Boolean).map(parseFloat);
1838
- const need = cmd === "M" || cmd === "L" ? 2 : cmd === "Q" ? 4 : cmd === "C" ? 6 : 0;
1861
+ const need = cmd === "M" || cmd === "L" ? 2 : cmd === "Q" ? 4 : cmd === "C" ? 6 : cmd === "A" ? 7 : 0;
1839
1862
  if (need > 0 && (args.length < need || !args.slice(0, need).every(Number.isFinite))) continue;
1840
1863
  if (cmd === "M") {
1841
1864
  cur = { x: args[0], y: args[1] };
@@ -1865,6 +1888,10 @@ function extractPathSegments(d) {
1865
1888
  ctrl: [{ x: args[0], y: args[1] }, { x: args[2], y: args[3] }]
1866
1889
  });
1867
1890
  cur = next;
1891
+ } else if (cmd === "A") {
1892
+ const next = { x: args[5], y: args[6] };
1893
+ segs.push({ x1: cur.x, y1: cur.y, x2: next.x, y2: next.y, cmd: "A" });
1894
+ cur = next;
1868
1895
  }
1869
1896
  }
1870
1897
  return segs;
@@ -2164,7 +2191,7 @@ function clampShiftMagnitude(shift, maxMagnitude) {
2164
2191
  };
2165
2192
  return { dx: clampAxis(shift.dx), dy: clampAxis(shift.dy) };
2166
2193
  }
2167
- function resolveEdgeLabelOverlapsWithChainAndPropagate(edges, obstacles, minClearance = 16, maxIter = 20, pathLabelClearance = LABEL_TO_PATH_CLEARANCE) {
2194
+ function resolveEdgeLabelOverlapsWithChainAndPropagate(edges, obstacles, minClearance = 16, maxIter = 20, pathLabelClearance = LABEL_TO_PATH_CLEARANCE, textMetrics = "proportional") {
2168
2195
  if (edges.length === 0) {
2169
2196
  return {
2170
2197
  edges,
@@ -2175,7 +2202,7 @@ function resolveEdgeLabelOverlapsWithChainAndPropagate(edges, obstacles, minClea
2175
2202
  }
2176
2203
  const MAX_ACCUMULATED_SHIFT = CHAIN_SHIFT_MAX_ACCUMULATED;
2177
2204
  const labelBBox = (e, offsetX, offsetY) => {
2178
- const base = computeLabelBBoxWorld(e);
2205
+ const base = computeLabelBBoxWorld(e, textMetrics);
2179
2206
  return {
2180
2207
  kind: "edge-label",
2181
2208
  id: e.id,
@@ -2776,11 +2803,15 @@ var \u5411\u304D\u306E\u9806 = [
2776
2803
  { axis: "x", sign: -1, \u540D\u524D: "\u5DE6" },
2777
2804
  { axis: "x", sign: 1, \u540D\u524D: "\u53F3" }
2778
2805
  ];
2779
- function \u672D\u304C\u52D5\u3051\u306A\u3044\u7406\u7531(labelId, \u76F8\u624B, edges, obstacles) {
2806
+ function \u672D\u304C\u52D5\u3051\u306A\u3044\u7406\u7531(labelId, \u76F8\u624B, edges, obstacles, textMetrics = "proportional") {
2780
2807
  const edgeById = new Map(edges.map((e) => [e.id, e]));
2781
2808
  const \u81EA\u5206 = edgeById.get(labelId);
2782
2809
  if (!\u81EA\u5206) return null;
2783
- const labels = edges.filter((e) => e.label?.trim() || e.sub?.trim()).map((e) => ({ kind: "edge-label", id: e.id, ...computeLabelBBoxWorld(e) }));
2810
+ const labels = edges.filter((e) => e.label?.trim() || e.sub?.trim()).map((e) => ({
2811
+ kind: "edge-label",
2812
+ id: e.id,
2813
+ ...computeLabelBBoxWorld(e, textMetrics)
2814
+ }));
2784
2815
  const label = labels.find((l) => l.id === labelId);
2785
2816
  if (!label) return null;
2786
2817
  const \u6E2C\u308A\u65B9 = \u7DDA\u306E\u6E2C\u308A\u65B9\u3092\u4F5C\u308B();
@@ -2822,7 +2853,7 @@ function \u672D\u304C\u52D5\u3051\u306A\u3044\u7406\u7531(labelId, \u76F8\u624B,
2822
2853
  }
2823
2854
  return `\u9003\u3052\u5834\u306A\u3057: ${\u7406\u7531.sort((a, b) => a.\u9806 - b.\u9806).map((r) => r.\u6587).join(" / ")}`;
2824
2855
  }
2825
- function resolveLabelClearanceAfterPathPasses(edges, obstacles, maxIter = 8) {
2856
+ function resolveLabelClearanceAfterPathPasses(edges, obstacles, maxIter = 8, textMetrics = "proportional") {
2826
2857
  if (edges.length === 0) return edges;
2827
2858
  const labeledIds = new Set(
2828
2859
  edges.filter((e) => e.label?.trim() || e.sub?.trim()).map((e) => e.id)
@@ -2840,7 +2871,7 @@ function resolveLabelClearanceAfterPathPasses(edges, obstacles, maxIter = 8) {
2840
2871
  const out = [];
2841
2872
  for (const e of edges) {
2842
2873
  if (!labeledIds.has(e.id)) continue;
2843
- const base = computeLabelBBoxWorld(e);
2874
+ const base = computeLabelBBoxWorld(e, textMetrics);
2844
2875
  const s = getShift(e.id);
2845
2876
  out.push({ kind: "edge-label", id: e.id, x: base.x + s.dx, y: base.y + s.dy, w: base.w, h: base.h });
2846
2877
  }
@@ -2971,6 +3002,232 @@ function applyEdgeLabelAndPathShifts(edges, labelShiftMap, edgePathShiftMap) {
2971
3002
  });
2972
3003
  }
2973
3004
 
3005
+ // src/layout/curve-path.ts
3006
+ var SAME_HEIGHT_THRESHOLD = 1;
3007
+ function curvePath(from, to, edge, labelMarginExtra = 0, textMetrics = "proportional") {
3008
+ const fromLeft = from.cx - from.w / 2;
3009
+ const fromRight = from.cx + from.w / 2;
3010
+ const toLeft = to.cx - to.w / 2;
3011
+ const toRight = to.cx + to.w / 2;
3012
+ let fromSide;
3013
+ let toSide;
3014
+ let x1;
3015
+ let x2;
3016
+ if (toLeft >= fromRight) {
3017
+ fromSide = "right";
3018
+ toSide = "left";
3019
+ x1 = fromRight;
3020
+ x2 = toLeft;
3021
+ } else if (toRight <= fromLeft) {
3022
+ fromSide = "left";
3023
+ toSide = "right";
3024
+ x1 = fromLeft;
3025
+ x2 = toRight;
3026
+ } else {
3027
+ fromSide = "right";
3028
+ toSide = "right";
3029
+ x1 = fromRight;
3030
+ x2 = toRight;
3031
+ }
3032
+ const y1 = from.cy;
3033
+ const y2 = to.cy;
3034
+ const sameHeight = Math.abs(y2 - y1) < SAME_HEIGHT_THRESHOLD;
3035
+ let d;
3036
+ let midX;
3037
+ let midY;
3038
+ let tangentX;
3039
+ let tangentY;
3040
+ if (sameHeight) {
3041
+ d = `M ${x1} ${y1} L ${x2} ${y2}`;
3042
+ midX = (x1 + x2) / 2;
3043
+ midY = (y1 + y2) / 2;
3044
+ tangentX = x2 - x1;
3045
+ tangentY = y2 - y1;
3046
+ } else {
3047
+ let c1x;
3048
+ let c2x;
3049
+ if (fromSide !== toSide) {
3050
+ const direction = x2 > x1 ? 1 : -1;
3051
+ const bulge = Math.max(Math.abs(x2 - x1) / 2, EDGE_STUB_OUT);
3052
+ c1x = x1 + direction * bulge;
3053
+ c2x = x2 - direction * bulge;
3054
+ } else {
3055
+ const bulgeX = Math.max(x1, x2) + EDGE_STUB_OUT;
3056
+ c1x = bulgeX;
3057
+ c2x = bulgeX;
3058
+ }
3059
+ d = `M ${x1} ${y1} C ${c1x} ${y1}, ${c2x} ${y2}, ${x2} ${y2}`;
3060
+ midX = (x1 + 3 * c1x + 3 * c2x + x2) / 8;
3061
+ midY = (y1 + 3 * y1 + 3 * y2 + y2) / 8;
3062
+ tangentX = x2 + c2x - c1x - x1;
3063
+ tangentY = y2 + y2 - y1 - y1;
3064
+ }
3065
+ if (edge?.overlay) {
3066
+ return { d, fromSide, toSide, labelX: midX, labelY: midY, labelAnchor: "middle" };
3067
+ }
3068
+ const tangentLength = Math.hypot(tangentX, tangentY);
3069
+ let normalX = tangentY / tangentLength;
3070
+ let normalY = -tangentX / tangentLength;
3071
+ if (normalY > Number.EPSILON || Math.abs(normalY) <= Number.EPSILON && normalX < 0) {
3072
+ normalX *= -1;
3073
+ normalY *= -1;
3074
+ }
3075
+ const labelW = computeLabelBoxW(edge?.label, edge?.sub, textMetrics);
3076
+ const labelH = labelPillH(edge?.sub);
3077
+ const distance = labelPathClearanceHorizontal(edge) + (Math.abs(normalX) * labelW + Math.abs(normalY) * labelH) / 2 + labelMarginExtra;
3078
+ return {
3079
+ d,
3080
+ fromSide,
3081
+ toSide,
3082
+ labelX: midX + normalX * distance,
3083
+ labelY: midY + normalY * distance,
3084
+ labelAnchor: "middle"
3085
+ };
3086
+ }
3087
+
3088
+ // src/layout/metro-path.ts
3089
+ var METRO_CORNER_RADIUS = 24;
3090
+ var T = Math.SQRT2 - 1;
3091
+ function round2(v) {
3092
+ return Math.round(v * 100) / 100;
3093
+ }
3094
+ function point(p) {
3095
+ return `${round2(p.x)} ${round2(p.y)}`;
3096
+ }
3097
+ function add(p, v, scale) {
3098
+ return { x: p.x + v.x * scale, y: p.y + v.y * scale };
3099
+ }
3100
+ function polyline(points) {
3101
+ const distinct = points.filter((p, i) => {
3102
+ const previous = points[i - 1];
3103
+ return previous === void 0 || p.x !== previous.x || p.y !== previous.y;
3104
+ });
3105
+ return distinct.map((p, i) => `${i === 0 ? "M" : "L"} ${point(p)}`).join(" ");
3106
+ }
3107
+ function metroPath(from, to, edge, labelMarginExtra = 0, textMetrics = "proportional") {
3108
+ const fromLeft = from.cx - from.w / 2;
3109
+ const fromRight = from.cx + from.w / 2;
3110
+ const toLeft = to.cx - to.w / 2;
3111
+ const toRight = to.cx + to.w / 2;
3112
+ let fromSide;
3113
+ let toSide;
3114
+ let x1;
3115
+ let x2;
3116
+ let dir;
3117
+ if (toLeft >= fromRight) {
3118
+ fromSide = "right";
3119
+ toSide = "left";
3120
+ x1 = fromRight;
3121
+ x2 = toLeft;
3122
+ dir = 1;
3123
+ } else if (toRight <= fromLeft) {
3124
+ fromSide = "left";
3125
+ toSide = "right";
3126
+ x1 = fromLeft;
3127
+ x2 = toRight;
3128
+ dir = -1;
3129
+ } else {
3130
+ fromSide = "right";
3131
+ toSide = "right";
3132
+ x1 = fromRight;
3133
+ x2 = toRight;
3134
+ dir = 1;
3135
+ }
3136
+ const y1 = from.cy;
3137
+ const y2 = to.cy;
3138
+ const dy = y2 - y1;
3139
+ const sgn = Math.sign(dy);
3140
+ let d;
3141
+ let mid;
3142
+ let tangent;
3143
+ if (Math.abs(dy) < SAME_HEIGHT_THRESHOLD) {
3144
+ d = `M ${point({ x: x1, y: y1 })} L ${point({ x: x2, y: y2 })}`;
3145
+ mid = { x: (x1 + x2) / 2, y: (y1 + y2) / 2 };
3146
+ tangent = { x: x2 - x1, y: y2 - y1 };
3147
+ } else if (fromSide !== toSide && Math.abs(x2 - x1) >= Math.abs(dy)) {
3148
+ const horizontal = Math.abs(x2 - x1);
3149
+ const s = (horizontal - Math.abs(dy)) / 2;
3150
+ const p0 = { x: x1, y: y1 };
3151
+ const p1 = { x: x1 + dir * s, y: y1 };
3152
+ const p2 = { x: x2 - dir * s, y: y2 };
3153
+ const p3 = { x: x2, y: y2 };
3154
+ const u = { x: dir, y: 0 };
3155
+ const w = { x: dir / Math.SQRT2, y: sgn / Math.SQRT2 };
3156
+ const r = Math.min(
3157
+ METRO_CORNER_RADIUS,
3158
+ s / T,
3159
+ Math.SQRT2 * Math.abs(dy) / (2 * T)
3160
+ );
3161
+ const t = r * T;
3162
+ if (r >= 0.5) {
3163
+ const f1 = dir * sgn > 0 ? 1 : 0;
3164
+ d = [
3165
+ `M ${point(p0)}`,
3166
+ `L ${point(add(p1, u, -t))}`,
3167
+ `A ${round2(r)} ${round2(r)} 0 0 ${f1} ${point(add(p1, w, t))}`,
3168
+ `L ${point(add(p2, w, -t))}`,
3169
+ `A ${round2(r)} ${round2(r)} 0 0 ${1 - f1} ${point(add(p2, u, t))}`,
3170
+ `L ${point(p3)}`
3171
+ ].join(" ");
3172
+ } else {
3173
+ d = polyline([p0, p1, p2, p3]);
3174
+ }
3175
+ mid = { x: (x1 + x2) / 2, y: (y1 + y2) / 2 };
3176
+ tangent = w;
3177
+ } else {
3178
+ fromSide = "right";
3179
+ toSide = "right";
3180
+ x1 = fromRight;
3181
+ x2 = toRight;
3182
+ const xa = Math.max(x1, x2) + EDGE_STUB_OUT;
3183
+ const h = Math.abs(dy) / 2;
3184
+ const p0 = { x: x1, y: y1 };
3185
+ const p1 = { x: xa, y: y1 };
3186
+ const p2 = { x: xa + h, y: y1 + sgn * h };
3187
+ const p3 = { x: xa, y: y2 };
3188
+ const p4 = { x: x2, y: y2 };
3189
+ const u = { x: 1, y: 0 };
3190
+ const w1 = { x: 1 / Math.SQRT2, y: sgn / Math.SQRT2 };
3191
+ const w2 = { x: -1 / Math.SQRT2, y: sgn / Math.SQRT2 };
3192
+ const r = Math.min(METRO_CORNER_RADIUS, h);
3193
+ const t = r * T;
3194
+ const sweep = sgn > 0 ? 1 : 0;
3195
+ d = [
3196
+ `M ${point(p0)}`,
3197
+ `L ${point(add(p1, u, -t))}`,
3198
+ `A ${round2(r)} ${round2(r)} 0 0 ${sweep} ${point(add(p1, w1, t))}`,
3199
+ `L ${point(add(p2, w1, -r))}`,
3200
+ `A ${round2(r)} ${round2(r)} 0 0 ${sweep} ${point(add(p2, w2, r))}`,
3201
+ `L ${point(add(p3, w2, -t))}`,
3202
+ `A ${round2(r)} ${round2(r)} 0 0 ${sweep} ${point(add(p3, u, -t))}`,
3203
+ `L ${point(p4)}`
3204
+ ].join(" ");
3205
+ mid = { x: p2.x - T * r, y: p2.y };
3206
+ tangent = { x: 0, y: sgn };
3207
+ }
3208
+ if (edge?.overlay) {
3209
+ return { d, fromSide, toSide, labelX: mid.x, labelY: mid.y, labelAnchor: "middle" };
3210
+ }
3211
+ const tangentLength = Math.hypot(tangent.x, tangent.y);
3212
+ let normalX = tangent.y / tangentLength;
3213
+ let normalY = -tangent.x / tangentLength;
3214
+ if (normalY > Number.EPSILON || Math.abs(normalY) <= Number.EPSILON && normalX < 0) {
3215
+ normalX *= -1;
3216
+ normalY *= -1;
3217
+ }
3218
+ const labelW = computeLabelBoxW(edge?.label, edge?.sub, textMetrics);
3219
+ const labelH = labelPillH(edge?.sub);
3220
+ const distance = labelPathClearanceHorizontal(edge) + (Math.abs(normalX) * labelW + Math.abs(normalY) * labelH) / 2 + labelMarginExtra;
3221
+ return {
3222
+ d,
3223
+ fromSide,
3224
+ toSide,
3225
+ labelX: mid.x + normalX * distance,
3226
+ labelY: mid.y + normalY * distance,
3227
+ labelAnchor: "middle"
3228
+ };
3229
+ }
3230
+
2974
3231
  // src/types.ts
2975
3232
  var TONES = ["accent", "teal", "success", "error", "warning", "info"];
2976
3233
  var NODE_KINDS = [
@@ -3098,6 +3355,8 @@ var NODE_KINDS = [
3098
3355
  // 状態遷移図が使う。 印そのものが意味を持つので文字は描かない
3099
3356
  "mark-start",
3100
3357
  "mark-end",
3358
+ // 路線図の駅 (#996) ... 線路上の点を小さな丸で示し、名前と説明は丸の外に置く
3359
+ "station",
3101
3360
  // 時系列のやり取り (#578) ... 1 つの箱が図を丸ごと描く。 縦が時間で、参加者は箱を持たない
3102
3361
  "sequence-board"
3103
3362
  ];
@@ -3125,7 +3384,14 @@ var NARROW_RATIO = 0.37;
3125
3384
  var ASCII_RATIO = 0.86;
3126
3385
  var WIDE_CHARS = "W@%Mm";
3127
3386
  var NARROW_CHARS = "ijlI.,:;'! ";
3128
- function textWidth(s, size, \u5B57\u9001\u308A = 0) {
3387
+ function textWidth(s, size, \u5B57\u9001\u308A = 0, textMetrics = "proportional") {
3388
+ if (textMetrics === "monospace") {
3389
+ return measureAdvanceWidth(s, {
3390
+ fontSize: size,
3391
+ letterSpacing: \u5B57\u9001\u308A,
3392
+ fontFamily: "mono"
3393
+ });
3394
+ }
3129
3395
  let \u5E45 = 0;
3130
3396
  let \u5B57\u6570 = 0;
3131
3397
  for (const c of s) {
@@ -3162,8 +3428,8 @@ function splitRow(row) {
3162
3428
  }
3163
3429
  return { left: row.trim(), right: "", split: false };
3164
3430
  }
3165
- function rowColumnWidth(text, size, mono) {
3166
- return mono ? displayWidth(text) * size * MONO_ADVANCE_RATIO : textWidth(text, size);
3431
+ function rowColumnWidth(text, size, mono, textMetrics = "proportional") {
3432
+ return mono ? displayWidth(text) * size * MONO_ADVANCE_RATIO : textWidth(text, size, 0, textMetrics);
3167
3433
  }
3168
3434
  function displayWidth(text) {
3169
3435
  let w = 0;
@@ -3189,12 +3455,12 @@ function \u6841\u3067\u7701\u304F(text, \u4E0A\u9650) {
3189
3455
  if (displayWidth(text) <= \u4E0A\u9650) return text;
3190
3456
  return `${\u6841\u3067\u5272\u308B(text, \u4E0A\u9650 - 1)[0]}\u2026`;
3191
3457
  }
3192
- function requiredRowsWidth(rows, kind) {
3458
+ function requiredRowsWidth(rows, kind, textMetrics = "proportional") {
3193
3459
  if (!rows || rows.length === 0) return 0;
3194
3460
  const splits = rows.map(splitRow);
3195
3461
  const \u4E00\u756A\u5E83\u3044 = (\u53D6\u308B) => splits.reduce((m, s) => Math.max(m, \u53D6\u308B(s)), 0);
3196
- const storage = ROW_PAD_X_PX + \u4E00\u756A\u5E83\u3044((s) => rowColumnWidth(s.left, 26, true)) + STORAGE_COL_GAP_PX + \u4E00\u756A\u5E83\u3044((s) => rowColumnWidth(s.right, 26, true)) + ROW_RIGHT_PAD_PX;
3197
- const generic = ROW_PAD_X_PX + \u4E00\u756A\u5E83\u3044((s) => rowColumnWidth(s.left, GENERIC_ROW_LEFT_SIZE_PX, false)) + ROW_COL_GAP_PX + \u4E00\u756A\u5E83\u3044((s) => rowColumnWidth(s.right, GENERIC_ROW_RIGHT_SIZE_PX, true)) + ROW_RIGHT_PAD_PX;
3462
+ const storage = ROW_PAD_X_PX + \u4E00\u756A\u5E83\u3044((s) => rowColumnWidth(s.left, 26, true, textMetrics)) + STORAGE_COL_GAP_PX + \u4E00\u756A\u5E83\u3044((s) => rowColumnWidth(s.right, 26, true, textMetrics)) + ROW_RIGHT_PAD_PX;
3463
+ const generic = ROW_PAD_X_PX + \u4E00\u756A\u5E83\u3044((s) => rowColumnWidth(s.left, GENERIC_ROW_LEFT_SIZE_PX, false, textMetrics)) + ROW_COL_GAP_PX + \u4E00\u756A\u5E83\u3044((s) => rowColumnWidth(s.right, GENERIC_ROW_RIGHT_SIZE_PX, true, textMetrics)) + ROW_RIGHT_PAD_PX;
3198
3464
  if (kind === void 0) return Math.ceil(Math.max(storage, generic));
3199
3465
  return Math.ceil(kind === "storage" ? storage : generic);
3200
3466
  }
@@ -3259,7 +3525,10 @@ var \u5DE6\u53F3\u306E\u4F59\u767D = 8;
3259
3525
  function \u4F7F\u3048\u308B\u5E45(\u7BB1\u306E\u5E45) {
3260
3526
  return \u7BB1\u306E\u5E45 - \u5DE6\u53F3\u306E\u4F59\u767D * 2;
3261
3527
  }
3262
- function \u5E45\u3067\u5207\u308B(text, fontSize, \u4F7F\u3048\u308B\u5E452, \u6E2C\u308B = textWidth) {
3528
+ function \u7BB1\u306E\u5B57\u3092\u6E2C\u308B(textMetrics = "proportional") {
3529
+ return (text, fontSize) => textWidth(text, fontSize, 0, textMetrics);
3530
+ }
3531
+ function \u5E45\u3067\u5207\u308B(text, fontSize, \u4F7F\u3048\u308B\u5E452, \u6E2C\u308B) {
3263
3532
  if (\u4F7F\u3048\u308B\u5E452 <= 0) return "";
3264
3533
  if (\u6E2C\u308B(text, fontSize) <= \u4F7F\u3048\u308B\u5E452) return text;
3265
3534
  const \u7701\u7565 = "\u2026";
@@ -3276,7 +3545,7 @@ function \u5E45\u3067\u5207\u308B(text, fontSize, \u4F7F\u3048\u308B\u5E452, \u6
3276
3545
  return `${\u51FA}${\u7701\u7565}`;
3277
3546
  }
3278
3547
  var \u7E2E\u3081\u306E\u4E0B\u9650 = MIN_TEXT_SIZE;
3279
- function \u5E45\u306B\u53CE\u3081\u308B(text, fontSize, \u4F7F\u3048\u308B\u5E452, \u6E2C\u308B = textWidth) {
3548
+ function \u5E45\u306B\u53CE\u3081\u308B(text, fontSize, \u4F7F\u3048\u308B\u5E452, \u6E2C\u308B) {
3280
3549
  let size = fontSize;
3281
3550
  while (size > \u7E2E\u3081\u306E\u4E0B\u9650 && \u6E2C\u308B(text, size) > \u4F7F\u3048\u308B\u5E452) size -= 1;
3282
3551
  return { text: \u5E45\u3067\u5207\u308B(text, size, \u4F7F\u3048\u308B\u5E452, \u6E2C\u308B), fontSize: size };
@@ -3286,7 +3555,7 @@ function \u66F8\u8A18\u7D20\u306B\u5206\u3051\u308B(text) {
3286
3555
  if (typeof \u533A\u5207\u308A !== "function") return [...text];
3287
3556
  return [...new \u533A\u5207\u308A(void 0, { granularity: "grapheme" }).segment(text)].map((g) => g.segment);
3288
3557
  }
3289
- function \u7BB1\u306B\u7A4D\u3080(\u884C, \u7BB1\u306E\u5E45, \u7BB1\u306E\u9AD8\u30553) {
3558
+ function \u7BB1\u306B\u7A4D\u3080(\u884C, \u7BB1\u306E\u5E45, \u7BB1\u306E\u9AD8\u30553, \u6E2C\u308B) {
3290
3559
  const \u5019\u88DC = \u884C.filter((r, i) => i === 0 || r.text.trim() !== "");
3291
3560
  if (\u5019\u88DC.length === 0) return [];
3292
3561
  const \u4F7F\u3048\u308B\u9AD8\u3055 = \u7BB1\u306E\u9AD8\u30553 - \u4E0A\u4E0B\u306E\u4F59\u767D * 2;
@@ -3294,7 +3563,7 @@ function \u7BB1\u306B\u7A4D\u3080(\u884C, \u7BB1\u306E\u5E45, \u7BB1\u306E\u9AD8
3294
3563
  const \u6B8B\u3059 = [...\u5019\u88DC];
3295
3564
  while (\u6B8B\u3059.length > 1 && \u9AD8\u3055(\u6B8B\u3059) > \u4F7F\u3048\u308B\u9AD8\u3055) \u6B8B\u3059.pop();
3296
3565
  const \u5E45 = \u4F7F\u3048\u308B\u5E45(\u7BB1\u306E\u5E45);
3297
- const \u53CE\u3081\u305F = \u6B8B\u3059.map((r) => ({ ...r, ...\u5E45\u306B\u53CE\u3081\u308B(r.text, r.fontSize, \u5E45) }));
3566
+ const \u53CE\u3081\u305F = \u6B8B\u3059.map((r) => ({ ...r, ...\u5E45\u306B\u53CE\u3081\u308B(r.text, r.fontSize, \u5E45, \u6E2C\u308B) }));
3298
3567
  const \u7DCF\u9AD8 = \u9AD8\u3055(\u53CE\u3081\u305F);
3299
3568
  let \u7A4D\u307F = -\u7DCF\u9AD8 / 2;
3300
3569
  return \u53CE\u3081\u305F.map((r) => {
@@ -3307,9 +3576,9 @@ function \u66F8\u3044\u305F\u5024\u304B\u63A7\u3048(\u66F8\u3044\u305F, \u63A7\u
3307
3576
  const v = (\u66F8\u3044\u305F ?? "").trim();
3308
3577
  return v === "" ? \u63A7\u3048 : v;
3309
3578
  }
3310
- function \u5E45\u306E\u500D\u7387(text, size, letterSpacing, \u5E45) {
3579
+ function \u5E45\u306E\u500D\u7387(text, size, letterSpacing, \u5E45, textMetrics = "proportional") {
3311
3580
  if (!(\u5E45 > 0) || !(size > 0)) return 1;
3312
- const \u5B9F\u5E45 = textWidth(text, size, letterSpacing);
3581
+ const \u5B9F\u5E45 = textWidth(text, size, letterSpacing, textMetrics);
3313
3582
  return \u5B9F\u5E45 > \u5E45 ? \u5E45 / \u5B9F\u5E45 : 1;
3314
3583
  }
3315
3584
  function \u8AAD\u3081\u308B\u4E0B\u9650\u306E\u500D\u7387(\u5927\u304D\u3055) {
@@ -3524,13 +3793,13 @@ function fitArt(region, extent, art) {
3524
3793
  );
3525
3794
  }
3526
3795
  var \u5E2F\u306E\u9AD8\u3055\u306B\u5BFE\u3059\u308B\u4E0A\u9650 = 0.8;
3527
- function \u7D75\u306E\u4E2D\u306E\u5B57\u306E\u5E45(text, size, letterSpacing = 0) {
3796
+ function \u7D75\u306E\u4E2D\u306E\u5B57\u306E\u5E45(text, size, letterSpacing = 0, textMetrics = "proportional") {
3528
3797
  return Math.max(
3529
3798
  displayWidth(text) * size * MONO_ADVANCE_RATIO,
3530
- textWidth(text, size, letterSpacing)
3799
+ textWidth(text, size, letterSpacing, textMetrics)
3531
3800
  );
3532
3801
  }
3533
- function \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u5B57\u3089) {
3802
+ function \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u5B57\u3089, textMetrics = "proportional") {
3534
3803
  const \u623B\u3057 = Number.isFinite(\u500D\u7387) && \u500D\u7387 > 0 ? 1 / \u500D\u7387 : 1;
3535
3804
  let \u4E0A\u9650 = Number.POSITIVE_INFINITY;
3536
3805
  for (const \u5B572 of \u5B57\u3089) {
@@ -3539,7 +3808,7 @@ function \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u5B57\u3089)
3539
3808
  if (Number.isFinite(\u9AD8\u3055) && \u9AD8\u3055 > 0) {
3540
3809
  \u4E0A\u9650 = Math.min(\u4E0A\u9650, \u9AD8\u3055 * \u5E2F\u306E\u9AD8\u3055\u306B\u5BFE\u3059\u308B\u4E0A\u9650 / \u5B572.size);
3541
3810
  }
3542
- const \u5B9F\u5E45 = \u7D75\u306E\u4E2D\u306E\u5B57\u306E\u5E45(\u5B572.text, \u5B572.size, \u5B572.letterSpacing ?? 0);
3811
+ const \u5B9F\u5E45 = \u7D75\u306E\u4E2D\u306E\u5B57\u306E\u5E45(\u5B572.text, \u5B572.size, \u5B572.letterSpacing ?? 0, textMetrics);
3543
3812
  if (Number.isFinite(\u5E45) && \u5E45 > 0 && \u5B9F\u5E45 > 0) {
3544
3813
  \u4E0A\u9650 = Math.min(\u4E0A\u9650, \u5E45 / \u5B9F\u5E45);
3545
3814
  }
@@ -4734,9 +5003,14 @@ var PAD_LEFT = 24;
4734
5003
  var \u7BB1\u306E\u6700\u5927\u5E45 = 140;
4735
5004
  var \u7BB1\u306E\u6700\u5927\u9AD8\u3055 = 38;
4736
5005
  var \u6728\u306E\u679D\u306E\u592A\u3055 = (\u6BB5) => Math.max(1.1, 2.6 - \u6BB5 * 0.45);
4737
- function \u6728\u306E\u4E2D\u8EAB(node, stateValues = {}) {
5006
+ function \u6728\u306E\u4E2D\u8EAB(node, stateValues = {}, textMetrics = "proportional") {
4738
5007
  const treeNodes = resolveTreeData(node.treeData ?? [], stateValues);
4739
- return computeTreeLayout(treeNodes, node.w - PAD_LEFT - PAD_RIGHT, node.h - PAD_TOP - PAD_BOTTOM);
5008
+ return computeTreeLayout(
5009
+ treeNodes,
5010
+ node.w - PAD_LEFT - PAD_RIGHT,
5011
+ node.h - PAD_TOP - PAD_BOTTOM,
5012
+ textMetrics
5013
+ );
4740
5014
  }
4741
5015
  function \u6728\u306E\u884C(n) {
4742
5016
  return [
@@ -4749,12 +5023,14 @@ function TreeNode({
4749
5023
  active,
4750
5024
  stateValues = {},
4751
5025
  drawing = false,
4752
- progress = 1
5026
+ progress = 1,
5027
+ textMetrics = "proportional"
4753
5028
  }) {
4754
5029
  const x0 = node.cx - node.w / 2;
4755
5030
  const y0 = node.cy - node.h / 2;
4756
5031
  const gradientId = `tree-root-grad-${node.id}`;
4757
- const layout2 = \u6728\u306E\u4E2D\u8EAB(node, stateValues);
5032
+ const layout2 = \u6728\u306E\u4E2D\u8EAB(node, stateValues, textMetrics);
5033
+ const \u6E2C\u308B = \u7BB1\u306E\u5B57\u3092\u6E2C\u308B(textMetrics);
4758
5034
  const \u4F38\u3073 = \u9032\u307F\u3092\u7573\u3080(drawing, progress);
4759
5035
  const \u6700\u5927\u6DF1\u3055 = layout2.nodes.reduce((m, n) => Math.max(m, n.depth), 0);
4760
5036
  const \u7BB1\u304C\u51FA\u308B = (\u6DF1\u3055) => !drawing || \u6BB5\u306E\u4F38\u3073(\u4F38\u3073, \u6DF1\u3055, \u6700\u5927\u6DF1\u3055) >= 1;
@@ -4808,10 +5084,10 @@ function TreeNode({
4808
5084
  const accent = depthColors[Math.min(n.depth, depthColors.length - 1)] ?? depthColors[0];
4809
5085
  const isRoot = n.depth === 0;
4810
5086
  const \u6750\u6599 = \u6728\u306E\u884C(n);
4811
- const \u884C = \u7BB1\u306B\u7A4D\u3080(\u6750\u6599, n.w, n.h);
5087
+ const \u884C = \u7BB1\u306B\u7A4D\u3080(\u6750\u6599, n.w, n.h, \u6E2C\u308B);
4812
5088
  const \u88DC\u8DB3\u3042\u308A = (n.subtitle ?? "").trim() !== "";
4813
5089
  const \u540D\u524D = \u6750\u6599[0];
4814
- const \u53CE\u3081\u305F\u540D\u524D = \u88DC\u8DB3\u3042\u308A ? void 0 : \u5E45\u306B\u53CE\u3081\u308B(\u540D\u524D.text, \u540D\u524D.fontSize, \u4F7F\u3048\u308B\u5E45(n.w));
5090
+ const \u53CE\u3081\u305F\u540D\u524D = \u88DC\u8DB3\u3042\u308A ? void 0 : \u5E45\u306B\u53CE\u3081\u308B(\u540D\u524D.text, \u540D\u524D.fontSize, \u4F7F\u3048\u308B\u5E45(n.w), \u6E2C\u308B);
4815
5091
  return /* @__PURE__ */ jsx(
4816
5092
  "g",
4817
5093
  {
@@ -4893,7 +5169,7 @@ function TreeNode({
4893
5169
  })
4894
5170
  ] });
4895
5171
  }
4896
- function computeTreeLayout(treeNodes, canvasW, canvasH) {
5172
+ function computeTreeLayout(treeNodes, canvasW, canvasH, textMetrics = "proportional") {
4897
5173
  const ids = new Set(treeNodes.map((n) => n.id));
4898
5174
  const childrenOf = /* @__PURE__ */ new Map();
4899
5175
  for (const n of treeNodes) {
@@ -4941,7 +5217,7 @@ function computeTreeLayout(treeNodes, canvasW, canvasH) {
4941
5217
  const \u7BB1\u306E\u5E45 = (n, depth) => {
4942
5218
  const \u6750\u6599 = \u6728\u306E\u884C({ ...n, depth });
4943
5219
  const \u540D\u524D = \u6750\u6599[0];
4944
- const \u8981\u308B = measureTextWidth(\u540D\u524D.text, { fontSize: \u540D\u524D.fontSize}) + (nodeW - \u4F7F\u3048\u308B\u5E45(nodeW));
5220
+ const \u8981\u308B = measureTextWidth(\u540D\u524D.text, { fontSize: \u540D\u524D.fontSize, textMetrics }) + (nodeW - \u4F7F\u3048\u308B\u5E45(nodeW));
4945
5221
  return Math.min(Math.max(\u8981\u308B, nodeW), slotW * 0.92);
4946
5222
  };
4947
5223
  const \u8449\u306E\u4E26\u3073 = [];
@@ -5045,7 +5321,7 @@ var BRANCH_BOX_H_MAX = 48;
5045
5321
  var SUB_BOX_H_MAX = 40;
5046
5322
  var \u7E26\u306E\u9593\u9694\u306E\u4E0A\u9650 = (\u679D\u306E\u6A2A\u306E\u4F38\u3073) => \u679D\u306E\u6A2A\u306E\u4F38\u3073;
5047
5323
  var MIND_PAD = 40;
5048
- function \u653E\u5C04\u306E\u4E2D\u8EAB(node, stateValues = {}) {
5324
+ function \u653E\u5C04\u306E\u4E2D\u8EAB(node, stateValues = {}, textMetrics = "proportional") {
5049
5325
  const mindData = node.mindData ? resolveMindData(node.mindData, stateValues) : void 0;
5050
5326
  if (!mindData) return void 0;
5051
5327
  return computeMindMapLayout(
@@ -5053,7 +5329,8 @@ function \u653E\u5C04\u306E\u4E2D\u8EAB(node, stateValues = {}) {
5053
5329
  node.w / 2,
5054
5330
  node.h / 2,
5055
5331
  node.w - MIND_PAD * 2,
5056
- node.h - MIND_PAD * 2
5332
+ node.h - MIND_PAD * 2,
5333
+ textMetrics
5057
5334
  );
5058
5335
  }
5059
5336
  function \u653E\u5C04\u306E\u884C(n) {
@@ -5067,12 +5344,14 @@ function MindMapNode({
5067
5344
  active,
5068
5345
  stateValues = {},
5069
5346
  drawing = false,
5070
- progress = 1
5347
+ progress = 1,
5348
+ textMetrics = "proportional"
5071
5349
  }) {
5072
5350
  const x0 = node.cx - node.w / 2;
5073
5351
  const y0 = node.cy - node.h / 2;
5074
- const layout2 = \u653E\u5C04\u306E\u4E2D\u8EAB(node, stateValues);
5352
+ const layout2 = \u653E\u5C04\u306E\u4E2D\u8EAB(node, stateValues, textMetrics);
5075
5353
  if (!layout2) return /* @__PURE__ */ jsx("g", { transform: `translate(${x0} ${y0})` });
5354
+ const \u6E2C\u308B = \u7BB1\u306E\u5B57\u3092\u6E2C\u308B(textMetrics);
5076
5355
  const \u4F38\u3073 = \u9032\u307F\u3092\u7573\u3080(drawing, progress);
5077
5356
  const \u6700\u5927\u6DF1\u3055 = layout2.nodes.reduce((m, n) => Math.max(m, n.depth), 0);
5078
5357
  const \u7BB1\u304C\u51FA\u308B = (\u6DF1\u3055) => !drawing || \u6BB5\u306E\u4F38\u3073(\u4F38\u3073, \u6DF1\u3055, \u6700\u5927\u6DF1\u3055) >= 1;
@@ -5119,8 +5398,13 @@ function MindMapNode({
5119
5398
  const \u6587\u5B57\u306E\u5BC4\u305B = \u67A0\u306A\u3057 ? \u5916\u3078 ? "start" : "end" : "middle";
5120
5399
  const \u63CF\u753B\u57DF\u306E\u7AEF = \u5916\u3078 ? node.w - MIND_PAD : MIND_PAD;
5121
5400
  const \u4F7F\u3048\u308B = \u67A0\u306A\u3057 ? Math.abs(\u63CF\u753B\u57DF\u306E\u7AEF - \u6587\u5B57\u306Ex) : \u4F7F\u3048\u308B\u5E45(n.w);
5122
- const \u53CE\u3081\u305F\u540D\u524D = \u88DC\u8DB3\u3042\u308A ? void 0 : \u5E45\u306B\u53CE\u3081\u308B(\u540D\u524D.text, \u540D\u524D.fontSize, \u4F7F\u3048\u308B);
5123
- const \u884C = \u7BB1\u306B\u7A4D\u3080(\u6750\u6599, \u67A0\u306A\u3057 ? \u4F7F\u3048\u308B + (n.w - \u4F7F\u3048\u308B\u5E45(n.w)) : n.w, n.h);
5401
+ const \u53CE\u3081\u305F\u540D\u524D = \u88DC\u8DB3\u3042\u308A ? void 0 : \u5E45\u306B\u53CE\u3081\u308B(\u540D\u524D.text, \u540D\u524D.fontSize, \u4F7F\u3048\u308B, \u6E2C\u308B);
5402
+ const \u884C = \u7BB1\u306B\u7A4D\u3080(
5403
+ \u6750\u6599,
5404
+ \u67A0\u306A\u3057 ? \u4F7F\u3048\u308B + (n.w - \u4F7F\u3048\u308B\u5E45(n.w)) : n.w,
5405
+ n.h,
5406
+ \u6E2C\u308B
5407
+ );
5124
5408
  const \u6587\u5B57\u306E\u8272 = n.isRoot ? "var(--cdl-text-on-tone, #ffffff)" : "var(--cdl-chip-text, #1a1f2a)";
5125
5409
  return /* @__PURE__ */ jsxs("g", { "data-cdl-unresolved": n.unresolved ? "true" : void 0, children: [
5126
5410
  \u67A0\u306A\u3057 ? null : /* @__PURE__ */ jsx(
@@ -5172,14 +5456,14 @@ function MindMapNode({
5172
5456
  })
5173
5457
  ] });
5174
5458
  }
5175
- function \u63CF\u304F\u6A2A\u306E\u7AEF(n) {
5459
+ function \u63CF\u304F\u6A2A\u306E\u7AEF(n, textMetrics = "proportional") {
5176
5460
  if (n.isRoot || !n.isLeaf) return [n.x - n.w / 2, n.x + n.w / 2];
5177
5461
  const \u8D77\u70B9 = n.x + (n.side === "right" ? -n.w / 2 : n.w / 2);
5178
5462
  const \u540D\u524D = \u653E\u5C04\u306E\u884C(n)[0];
5179
- const \u5E45 = textWidth(\u540D\u524D.text, \u540D\u524D.fontSize);
5463
+ const \u5E45 = textWidth(\u540D\u524D.text, \u540D\u524D.fontSize, 0, textMetrics);
5180
5464
  return n.side === "right" ? [\u8D77\u70B9, \u8D77\u70B9 + \u5E45] : [\u8D77\u70B9 - \u5E45, \u8D77\u70B9];
5181
5465
  }
5182
- function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
5466
+ function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH, textMetrics = "proportional") {
5183
5467
  const nodes = [];
5184
5468
  const edges = [];
5185
5469
  const rootW = 120;
@@ -5257,7 +5541,7 @@ function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
5257
5541
  const PREFERRED_GAP = MIND_BOX_GAP;
5258
5542
  const \u679D\u306E\u540D\u524D\u306E\u5E45 = (title) => {
5259
5543
  const \u540D\u524D = \u653E\u5C04\u306E\u884C({ title, isRoot: false })[0];
5260
- return textWidth(\u540D\u524D.text, \u540D\u524D.fontSize);
5544
+ return textWidth(\u540D\u524D.text, \u540D\u524D.fontSize, 0, textMetrics);
5261
5545
  };
5262
5546
  const \u679D\u306E\u6A2A\u3092\u6C7A\u3081\u308B = (br) => {
5263
5547
  const maxSubDepth = subDepthOf(br.id, /* @__PURE__ */ new Set());
@@ -5375,7 +5659,7 @@ function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
5375
5659
  let maxExtentX = rootW / 2;
5376
5660
  let maxExtentY = rootH / 2;
5377
5661
  for (const n of nodes) {
5378
- const [\u5DE6, \u53F3] = \u63CF\u304F\u6A2A\u306E\u7AEF(n);
5662
+ const [\u5DE6, \u53F3] = \u63CF\u304F\u6A2A\u306E\u7AEF(n, textMetrics);
5379
5663
  maxExtentX = Math.max(maxExtentX, Math.abs(\u5DE6 - cx), Math.abs(\u53F3 - cx));
5380
5664
  maxExtentY = Math.max(maxExtentY, Math.abs(n.y - cy) + n.h / 2);
5381
5665
  }
@@ -5395,7 +5679,7 @@ function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
5395
5679
  let \u5DE6\u7AEF = Number.POSITIVE_INFINITY;
5396
5680
  let \u53F3\u7AEF = Number.NEGATIVE_INFINITY;
5397
5681
  for (const n of nodes) {
5398
- const [l, r] = \u63CF\u304F\u6A2A\u306E\u7AEF(n);
5682
+ const [l, r] = \u63CF\u304F\u6A2A\u306E\u7AEF(n, textMetrics);
5399
5683
  \u5DE6\u7AEF = Math.min(\u5DE6\u7AEF, l);
5400
5684
  \u53F3\u7AEF = Math.max(\u53F3\u7AEF, r);
5401
5685
  }
@@ -5617,10 +5901,16 @@ function emptyCounts() {
5617
5901
  "validation-interrupted": 0
5618
5902
  };
5619
5903
  }
5620
- function \u7A4D\u3080\u7BB1\u3092\u96C6\u3081\u308B(n) {
5621
- const \u7BB1 = (b, \u884C) => ({ \u884C, w: b.w, h: b.h });
5622
- if (n.kind === "tree-hierarchy") return \u6728\u306E\u4E2D\u8EAB(n).nodes.map((b) => \u7BB1(b, \u6728\u306E\u884C(b)));
5623
- if (n.kind === "mind-map") return (\u653E\u5C04\u306E\u4E2D\u8EAB(n)?.nodes ?? []).map((b) => \u7BB1(b, \u653E\u5C04\u306E\u884C(b)));
5904
+ function \u7A4D\u3080\u7BB1\u3092\u96C6\u3081\u308B(n, textMetrics = "proportional") {
5905
+ const \u7BB1 = (b, \u884C, \u6E2C\u308B) => ({ \u884C, w: b.w, h: b.h, \u6E2C\u308B });
5906
+ if (n.kind === "tree-hierarchy") {
5907
+ const \u6E2C\u308B = \u7BB1\u306E\u5B57\u3092\u6E2C\u308B(textMetrics);
5908
+ return \u6728\u306E\u4E2D\u8EAB(n, {}, textMetrics).nodes.map((b) => \u7BB1(b, \u6728\u306E\u884C(b), \u6E2C\u308B));
5909
+ }
5910
+ if (n.kind === "mind-map") {
5911
+ const \u6E2C\u308B = \u7BB1\u306E\u5B57\u3092\u6E2C\u308B(textMetrics);
5912
+ return (\u653E\u5C04\u306E\u4E2D\u8EAB(n, {}, textMetrics)?.nodes ?? []).map((b) => \u7BB1(b, \u653E\u5C04\u306E\u884C(b), \u6E2C\u308B));
5913
+ }
5624
5914
  return [];
5625
5915
  }
5626
5916
  function measureStubOut(segs) {
@@ -6254,9 +6544,11 @@ function \u4F4D\u7F6E\u3092\u624B\u3067\u66F8\u3044\u305F(n) {
6254
6544
  return n.posX !== void 0 && n.posY !== void 0;
6255
6545
  }
6256
6546
  function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5668) {
6547
+ const textMetrics = laid.textMetrics ?? "proportional";
6257
6548
  const LIFELINE_W_THRESHOLD = 8;
6258
6549
  for (const n of laid.nodes) {
6259
6550
  if (n.w < LIFELINE_W_THRESHOLD) continue;
6551
+ if (n.kind === "station") continue;
6260
6552
  if (n.w < MIN_NODE_W || n.h < MIN_NODE_H) {
6261
6553
  push(
6262
6554
  "node-visibility",
@@ -6264,7 +6556,7 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
6264
6556
  );
6265
6557
  }
6266
6558
  }
6267
- const bboxes = collectBBoxes(laid.lanes, laid.nodes, laid.edges);
6559
+ const bboxes = collectBBoxes(laid.lanes, laid.nodes, laid.edges, textMetrics);
6268
6560
  const collisions = detectCollisions(bboxes, laid.edges);
6269
6561
  for (const c of collisions) {
6270
6562
  const involvesEdgeLabel = c.a.kind === "edge-label" || c.b.kind === "edge-label";
@@ -6278,12 +6570,17 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
6278
6570
  if (n.id.endsWith("-spacer")) continue;
6279
6571
  if (!rendersTitleText(n.kind)) continue;
6280
6572
  if (fitsOwnTitleWidth(n.kind)) continue;
6573
+ if (skipsNodeTitleWidthCheck(n.kind)) continue;
6281
6574
  if (!isRenderedNode(n)) continue;
6282
6575
  const titleTrimmed = n.title?.trim() ?? "";
6283
6576
  if (!titleTrimmed) continue;
6284
6577
  const \u4F59\u767D = drawsTitleOutsideBox(n.kind) ? 0 : TITLE_BOX_PADDING;
6285
6578
  const \u4F7F\u3048\u308B\u5E452 = n.w - \u4F59\u767D;
6286
- const \u5B9F\u5E45 = measureTextWidth(titleTrimmed, { fontSize: titleFontSize(n.kind), bound: "drawn" });
6579
+ const \u5B9F\u5E45 = measureTextWidth(titleTrimmed, {
6580
+ fontSize: titleFontSize(n.kind),
6581
+ bound: "drawn",
6582
+ textMetrics
6583
+ });
6287
6584
  if (titleScalesToFit(n.kind, n.h)) {
6288
6585
  const \u7E2E\u3081\u305F\u5927\u304D\u3055 = \u5B9F\u5E45 > 0 ? titleFontSize(n.kind) * Math.min(1, \u4F7F\u3048\u308B\u5E452 / \u5B9F\u5E45) : titleFontSize(n.kind);
6289
6586
  if (\u7E2E\u3081\u305F\u5927\u304D\u3055 < MIN_TITLE_FONT_SIZE) {
@@ -6351,7 +6648,13 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
6351
6648
  const b\u306F\u672D = n.b.kind === "edge-label";
6352
6649
  const \u52D5\u304B\u3059 = a\u306F\u672D && b\u306F\u672D ? (\u8FBA\u306E\u9806.get(n.a.id) ?? 0) > (\u8FBA\u306E\u9806.get(n.b.id) ?? 0) ? n.a : n.b : a\u306F\u672D ? n.a : b\u306F\u672D ? n.b : null;
6353
6650
  const \u76F8\u624B = \u52D5\u304B\u3059 === n.a ? n.b : n.a;
6354
- const reason = \u52D5\u304B\u3059 !== null ? \u672D\u304C\u52D5\u3051\u306A\u3044\u7406\u7531(\u52D5\u304B\u3059.id, \u76F8\u624B, laid.edges, \u672D\u306E\u969C\u5BB3\u7269) ?? void 0 : void 0;
6651
+ const reason = \u52D5\u304B\u3059 !== null ? \u672D\u304C\u52D5\u3051\u306A\u3044\u7406\u7531(
6652
+ \u52D5\u304B\u3059.id,
6653
+ \u76F8\u624B,
6654
+ laid.edges,
6655
+ \u672D\u306E\u969C\u5BB3\u7269,
6656
+ textMetrics
6657
+ ) ?? void 0 : void 0;
6355
6658
  push(
6356
6659
  "clearance",
6357
6660
  `${n.a.kind}:${n.a.id} \u2194 ${n.b.kind}:${n.b.id} gap=${n.gap.toFixed(1)}px (need ${n.required}px)`,
@@ -6365,7 +6668,10 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
6365
6668
  if (!hasRenderedLabel(e)) continue;
6366
6669
  const segs = extractPathSegments(e.d);
6367
6670
  if (segs.length === 0) continue;
6368
- const minDist = measurePathLabelGapSegs(flattenPathSegments(segs), computeLabelBBoxWorld(e));
6671
+ const minDist = measurePathLabelGapSegs(
6672
+ flattenPathSegments(segs),
6673
+ computeLabelBBoxWorld(e, textMetrics)
6674
+ );
6369
6675
  if (!Number.isFinite(minDist)) continue;
6370
6676
  if (minDist > PROXIMITY_ERROR_THRESHOLD) {
6371
6677
  push(
@@ -6415,8 +6721,15 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
6415
6721
  }
6416
6722
  for (const e of laid.edges) {
6417
6723
  if (!hasRenderedLabel(e)) continue;
6418
- const mainW = measureTextWidth(e.label ?? "", { fontSize: EDGE_LABEL_TEXT.main.fontSize });
6419
- const subW = e.sub ? measureTextWidth(e.sub, { fontSize: EDGE_LABEL_TEXT.sub.fontSize, fontFamily: "mono" }) : 0;
6724
+ const mainW = measureTextWidth(e.label ?? "", {
6725
+ fontSize: EDGE_LABEL_TEXT.main.fontSize,
6726
+ textMetrics
6727
+ });
6728
+ const subW = e.sub ? measureTextWidth(e.sub, {
6729
+ fontSize: EDGE_LABEL_TEXT.sub.fontSize,
6730
+ fontFamily: "mono",
6731
+ textMetrics
6732
+ }) : 0;
6420
6733
  const expectedBoxW = Math.max(mainW, subW) + LABEL_PILL_PAD_X * 2;
6421
6734
  const bbox = bboxes.find((b) => b.kind === "edge-label" && b.id === e.id);
6422
6735
  if (!bbox) continue;
@@ -6558,7 +6871,9 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
6558
6871
  }
6559
6872
  }
6560
6873
  for (const n of laid.nodes) {
6561
- const \u843D\u3068\u3057\u305F = labelPlan(n).\u843D\u3068\u3057\u305F.filter((line) => droppedLineIsHidden(n.kind, line));
6874
+ const \u843D\u3068\u3057\u305F = labelPlan(n).\u843D\u3068\u3057\u305F.filter(
6875
+ (line) => droppedLineIsHidden(n.kind, line)
6876
+ );
6562
6877
  if (\u843D\u3068\u3057\u305F.length === 0) continue;
6563
6878
  push(
6564
6879
  "shape-label-dropped",
@@ -6567,7 +6882,7 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
6567
6882
  );
6568
6883
  }
6569
6884
  for (const n of laid.nodes) {
6570
- const \u7BB1 = \u7A4D\u3080\u7BB1\u3092\u96C6\u3081\u308B(n);
6885
+ const \u7BB1 = \u7A4D\u3080\u7BB1\u3092\u96C6\u3081\u308B(n, textMetrics);
6571
6886
  if (\u7BB1.length === 0) continue;
6572
6887
  let \u5BFE\u8C61 = 0;
6573
6888
  const \u843D\u3061\u305F = [];
@@ -6575,7 +6890,7 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
6575
6890
  const \u5BA3\u8A00 = b.\u884C.slice(1).filter((r) => r.text.trim() !== "");
6576
6891
  if (\u5BA3\u8A00.length === 0) continue;
6577
6892
  \u5BFE\u8C61 += 1;
6578
- const \u6B8B\u3063\u305F = new Set(\u7BB1\u306B\u7A4D\u3080(b.\u884C, b.w, b.h).map((r) => r.\u5F79\u5272));
6893
+ const \u6B8B\u3063\u305F = new Set(\u7BB1\u306B\u7A4D\u3080(b.\u884C, b.w, b.h, b.\u6E2C\u308B).map((r) => r.\u5F79\u5272));
6579
6894
  if (\u5BA3\u8A00.every((r) => \u6B8B\u3063\u305F.has(r.\u5F79\u5272))) continue;
6580
6895
  \u843D\u3061\u305F.push({ title: b.\u884C[0]?.text ?? "", h: b.h });
6581
6896
  }
@@ -6882,6 +7197,9 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
6882
7197
  for (let i = 0; i + 1 < sorted.length; i++) {
6883
7198
  const upper = sorted[i];
6884
7199
  const lower = sorted[i + 1];
7200
+ if (upper.cx + upper.w / 2 <= lower.cx - lower.w / 2 || lower.cx + lower.w / 2 <= upper.cx - upper.w / 2) {
7201
+ continue;
7202
+ }
6885
7203
  const upperBottom = upper.cy + upper.h / 2;
6886
7204
  const lowerTop = lower.cy - lower.h / 2;
6887
7205
  const gap = lowerTop - upperBottom;
@@ -7513,11 +7831,18 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
7513
7831
  {
7514
7832
  const crestSpans = (segs, peakY) => {
7515
7833
  const out = [];
7834
+ let \u5186\u5F27\u306E\u59CB\u70B9 = null;
7516
7835
  for (const s of segs) {
7517
- if (Math.abs(s.y1 - s.y2) > 1) continue;
7518
- if (Math.abs(s.y1 - peakY) > 1) continue;
7836
+ if (s.cmd === "A") {
7837
+ \u5186\u5F27\u306E\u59CB\u70B9 ??= { x: s.x1, y: s.y1 };
7838
+ continue;
7839
+ }
7840
+ const \u59CB\u70B9 = \u5186\u5F27\u306E\u59CB\u70B9 ?? { x: s.x1, y: s.y1 };
7841
+ \u5186\u5F27\u306E\u59CB\u70B9 = null;
7842
+ if (Math.abs(\u59CB\u70B9.y - s.y2) > 1) continue;
7843
+ if (Math.abs(\u59CB\u70B9.y - peakY) > 1) continue;
7519
7844
  if (s.cmd !== "L" && !(s.ctrl ?? []).every((c) => Math.abs(c.y - peakY) <= 1)) continue;
7520
- out.push({ minX: Math.min(s.x1, s.x2), maxX: Math.max(s.x1, s.x2) });
7845
+ out.push({ minX: Math.min(\u59CB\u70B9.x, s.x2), maxX: Math.max(\u59CB\u70B9.x, s.x2) });
7521
7846
  }
7522
7847
  return out;
7523
7848
  };
@@ -7628,7 +7953,7 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
7628
7953
  const allowedLanes = /* @__PURE__ */ new Set();
7629
7954
  if (fromNode) allowedLanes.add(fromNode.lane);
7630
7955
  if (toNode) allowedLanes.add(toNode.lane);
7631
- const box = computeLabelBBoxWorld(e);
7956
+ const box = computeLabelBBoxWorld(e, textMetrics);
7632
7957
  for (const lane of laid.lanes) {
7633
7958
  if (allowedLanes.has(lane.id)) continue;
7634
7959
  const side = rectCrossesLaneBorder(box, lane, rangeByLane.get(lane.id));
@@ -7752,7 +8077,7 @@ function pickFreeSides(occupied, count) {
7752
8077
  const \u4F7F\u3046 = \u7A7A\u304D.length > 0 ? \u7A7A\u304D : [SELF_LOOP_SIDE_FALLBACK];
7753
8078
  return Array.from({ length: count }, (_, i) => \u4F7F\u3046[i % \u4F7F\u3046.length]);
7754
8079
  }
7755
- function routeSelfLoopGroup(edges, node, side) {
8080
+ function routeSelfLoopGroup(edges, node, side, textMetrics = "proportional") {
7756
8081
  const horizontal = side === "left" || side === "right";
7757
8082
  const g = sideGeometry(node, side);
7758
8083
  const span = fitSpan(horizontal ? node.h : node.w, SELF_LOOP_SPAN);
@@ -7761,7 +8086,7 @@ function routeSelfLoopGroup(edges, node, side) {
7761
8086
  const \u6700\u5916 = controlOffset(SELF_LOOP_OUT + (edges.length - 1) * SELF_LOOP_STAGGER);
7762
8087
  const \u8A9E\u307E\u3067 = \u6700\u5916 + LABEL_TO_PATH_CLEARANCE;
7763
8088
  const \u8A9E\u5E45 = edges.map(
7764
- (e) => horizontal ? labelPillH(e.sub) : computeLabelBoxW(e.label, e.sub)
8089
+ (e) => horizontal ? labelPillH(e.sub) : computeLabelBoxW(e.label, e.sub, textMetrics)
7765
8090
  );
7766
8091
  const \u4F4D\u7F6E = [];
7767
8092
  let \u7A4D = 0;
@@ -7791,7 +8116,7 @@ function routeSelfLoopGroup(edges, node, side) {
7791
8116
  function isSelfLoop(e) {
7792
8117
  return e.from === e.to;
7793
8118
  }
7794
- function layoutSelfLoops(edges, nodes, occupiedBySide) {
8119
+ function layoutSelfLoops(edges, nodes, occupiedBySide, textMetrics = "proportional") {
7795
8120
  const \u5272\u5F53 = /* @__PURE__ */ new Map();
7796
8121
  for (const edge of edges) {
7797
8122
  if (edge.side) continue;
@@ -7818,7 +8143,7 @@ function layoutSelfLoops(edges, nodes, occupiedBySide) {
7818
8143
  if (\u65E2) \u65E2.edges.push(edge);
7819
8144
  else \u675F.set(key, { node, side, edges: [edge] });
7820
8145
  }
7821
- return [...\u675F.values()].flatMap((b) => routeSelfLoopGroup(b.edges, b.node, b.side));
8146
+ return [...\u675F.values()].flatMap((b) => routeSelfLoopGroup(b.edges, b.node, b.side, textMetrics));
7822
8147
  }
7823
8148
 
7824
8149
  // src/layout/tokens.ts
@@ -7954,6 +8279,8 @@ var TOKENS = {
7954
8279
  // 箱としての最小 (80x40) より大きく、名前を持つ箱 (card 320x150) よりは明らかに小さい
7955
8280
  "mark-start": { w: 96, h: 96 },
7956
8281
  "mark-end": { w: 96, h: 96 },
8282
+ // 路線図の駅 (#996) ... 正方形にして小さな丸が縦横どちらにも歪まないようにする。
8283
+ station: { w: 24, h: 24 },
7957
8284
  // 時系列のやり取り (#578)。 実寸は中身から決まる (`sequenceBoardMetrics`) ので、
7958
8285
  // ここは書かなかった時の受け皿
7959
8286
  "sequence-board": { w: 960, h: 640 }
@@ -7978,6 +8305,7 @@ var LANE_PAD_MIN = 25;
7978
8305
  // src/layout/edges.ts
7979
8306
  var VERTICAL_DETOUR_GAP = 50;
7980
8307
  var VERTICAL_DETOUR_CORNER = 14;
8308
+ var OVERLAY_LABEL_ON_PATH_TOLERANCE = 1;
7981
8309
  function verticalCornerDir(from, to) {
7982
8310
  return to < from ? -1 : 1;
7983
8311
  }
@@ -8033,7 +8361,7 @@ function verticalDetourBlockers(A, B, obstacles) {
8033
8361
  function detourColumnFor(blockers, side) {
8034
8362
  return side === "left" ? Math.min(...blockers.map((n) => n.cx - n.w / 2)) - VERTICAL_DETOUR_GAP : Math.max(...blockers.map((n) => n.cx + n.w / 2)) + VERTICAL_DETOUR_GAP;
8035
8363
  }
8036
- function layoutEdges(diag, nodes, lanes = []) {
8364
+ function layoutEdges(diag, nodes, lanes = [], textMetrics = "proportional") {
8037
8365
  const labelMarginExtra = (diag.viewport?.labelMargin ?? diag.viewport?.gap ?? DEFAULT_LABEL_MARGIN) - DEFAULT_LABEL_MARGIN;
8038
8366
  const nmap = new Map(nodes.map((n) => [n.id, n]));
8039
8367
  const lmap = new Map(lanes.map((l) => [l.id, l]));
@@ -8061,6 +8389,36 @@ function layoutEdges(diag, nodes, lanes = []) {
8061
8389
  });
8062
8390
  } else if (isSelfLoop(e)) {
8063
8391
  selfLoopEdges.push(e);
8392
+ } else if (e.routing === "curve") {
8393
+ const from = nmap.get(e.from);
8394
+ const to = nmap.get(e.to);
8395
+ if (!from) throw new Error(`cdl layout: edge "${e.id}" \u306E from "${e.from}" \u304C node \u306B\u7121\u3044`);
8396
+ if (!to) throw new Error(`cdl layout: edge "${e.id}" \u306E to "${e.to}" \u304C node \u306B\u7121\u3044`);
8397
+ const c = curvePath(from, to, e, labelMarginExtra, textMetrics);
8398
+ positionedEdges.push({
8399
+ ...e,
8400
+ d: c.d,
8401
+ fromSide: c.fromSide,
8402
+ toSide: c.toSide,
8403
+ labelX: c.labelX + (e.labelOffsetX ?? 0),
8404
+ labelY: c.labelY + (e.labelOffsetY ?? 0),
8405
+ labelAnchor: c.labelAnchor
8406
+ });
8407
+ } else if (e.routing === "metro") {
8408
+ const from = nmap.get(e.from);
8409
+ const to = nmap.get(e.to);
8410
+ if (!from) throw new Error(`cdl layout: edge "${e.id}" \u306E from "${e.from}" \u304C node \u306B\u7121\u3044`);
8411
+ if (!to) throw new Error(`cdl layout: edge "${e.id}" \u306E to "${e.to}" \u304C node \u306B\u7121\u3044`);
8412
+ const m = metroPath(from, to, e, labelMarginExtra, textMetrics);
8413
+ positionedEdges.push({
8414
+ ...e,
8415
+ d: m.d,
8416
+ fromSide: m.fromSide,
8417
+ toSide: m.toSide,
8418
+ labelX: m.labelX + (e.labelOffsetX ?? 0),
8419
+ labelY: m.labelY + (e.labelOffsetY ?? 0),
8420
+ labelAnchor: m.labelAnchor
8421
+ });
8064
8422
  } else {
8065
8423
  autoEdges.push(e);
8066
8424
  }
@@ -8099,7 +8457,7 @@ function layoutEdges(diag, nodes, lanes = []) {
8099
8457
  \u4F7F\u3046(le.from, le.fromSide);
8100
8458
  \u4F7F\u3046(le.to, le.toSide);
8101
8459
  }
8102
- const loopEdges = layoutSelfLoops(selfLoopEdges, nmap, occupiedBySide);
8460
+ const loopEdges = layoutSelfLoops(selfLoopEdges, nmap, occupiedBySide, textMetrics);
8103
8461
  const labelOffsetsByEdgeId = /* @__PURE__ */ new Map();
8104
8462
  const parallelKey = (p) => p.e.from < p.e.to ? `${p.e.from}::${p.e.to}` : `${p.e.to}::${p.e.from}`;
8105
8463
  const byParallel = /* @__PURE__ */ new Map();
@@ -8253,7 +8611,7 @@ function layoutEdges(diag, nodes, lanes = []) {
8253
8611
  const others = nodes.filter((n) => n.id !== c.from && n.id !== c.to);
8254
8612
  if (others.some((n) => segmentsCrossRect(segs, nodeRect(n)))) return true;
8255
8613
  if (!hasRenderedLabel(c.e)) return false;
8256
- const boxW = computeLabelBoxW(c.e.label, c.e.sub);
8614
+ const boxW = computeLabelBoxW(c.e.label, c.e.sub, textMetrics);
8257
8615
  const boxH = labelPillH(c.e.sub);
8258
8616
  const centerX = columnX - (labelPathClearanceHorizontal(c.e) + boxW / 2);
8259
8617
  const pill = { x: centerX - boxW / 2, y: (exitY + returnY) / 2 - boxH / 2, w: boxW, h: boxH };
@@ -8368,7 +8726,8 @@ function layoutEdges(diag, nodes, lanes = []) {
8368
8726
  allOtherNodes,
8369
8727
  { x: endpointOffset.fromDx, y: endpointOffset.fromDy },
8370
8728
  { x: endpointOffset.toDx, y: endpointOffset.toDy },
8371
- avoidRects
8729
+ avoidRects,
8730
+ textMetrics
8372
8731
  );
8373
8732
  const routed1 = route([]);
8374
8733
  const { d, labelX, labelY, labelAnchor, labelAltX } = routed1;
@@ -8424,13 +8783,13 @@ function layoutEdges(diag, nodes, lanes = []) {
8424
8783
  const pillById = /* @__PURE__ */ new Map();
8425
8784
  for (const r of list) {
8426
8785
  if (!hasRenderedLabel(r.e)) continue;
8427
- const w = computeLabelBoxW(r.e.label, r.e.sub);
8786
+ const w = computeLabelBoxW(r.e.label, r.e.sub, textMetrics);
8428
8787
  const h = labelPillH(r.e.sub);
8429
8788
  pillById.set(r.e.id, { x: r.baseLabelX - w / 2, y: r.baseLabelY - h / 2, w, h });
8430
8789
  }
8431
8790
  for (const le of positionedEdges) {
8432
8791
  if (!hasRenderedLabel(le)) continue;
8433
- const w = computeLabelBoxW(le.label, le.sub);
8792
+ const w = computeLabelBoxW(le.label, le.sub, textMetrics);
8434
8793
  const h = labelPillH(le.sub);
8435
8794
  pillById.set(le.id, { x: le.labelX - w / 2, y: le.labelY - h / 2, w, h });
8436
8795
  }
@@ -8460,7 +8819,7 @@ function layoutEdges(diag, nodes, lanes = []) {
8460
8819
  const laneOfNode = new Map(nodes.map((n) => [n.id, n.lane]));
8461
8820
  for (const r of flippable) {
8462
8821
  const ownSegs = segsByEdgeId.get(r.e.id);
8463
- const boxW = computeLabelBoxW(r.e.label, r.e.sub);
8822
+ const boxW = computeLabelBoxW(r.e.label, r.e.sub, textMetrics);
8464
8823
  const boxH = labelPillH(r.e.sub);
8465
8824
  const pillAt = (centerX) => ({
8466
8825
  x: centerX - boxW / 2,
@@ -8505,7 +8864,7 @@ function layoutEdges(diag, nodes, lanes = []) {
8505
8864
  if (list.length < 2) continue;
8506
8865
  const boxes = list.map((r) => ({
8507
8866
  cx: r.baseLabelX,
8508
- halfW: computeLabelBoxW(r.e.label, r.e.sub) / 2
8867
+ halfW: computeLabelBoxW(r.e.label, r.e.sub, textMetrics) / 2
8509
8868
  }));
8510
8869
  const overlapsX = (i, j) => Math.abs(boxes[i].cx - boxes[j].cx) < boxes[i].halfW + boxes[j].halfW + CLEARANCE_LABEL_LABEL;
8511
8870
  const componentOf = list.map((_, i) => i);
@@ -8555,7 +8914,7 @@ function layoutEdges(diag, nodes, lanes = []) {
8555
8914
  r,
8556
8915
  baseX: r.baseLabelX,
8557
8916
  baseY: r.baseLabelY,
8558
- w: computeLabelBoxW(r.e.label, r.e.sub),
8917
+ w: computeLabelBoxW(r.e.label, r.e.sub, textMetrics),
8559
8918
  h: labelPillH(r.e.sub)
8560
8919
  }));
8561
8920
  items.sort((a, b) => a.baseX - b.baseX);
@@ -8667,7 +9026,7 @@ function singleStraightSegment(d) {
8667
9026
  if (x1 === x2 && y1 === y2) return null;
8668
9027
  return { x1, y1, x2, y2 };
8669
9028
  }
8670
- function bowSharedStraightPaths(edges, nodes, skipIds) {
9029
+ function bowSharedStraightPaths(edges, nodes, skipIds, textMetrics = "proportional") {
8671
9030
  const groups = /* @__PURE__ */ new Map();
8672
9031
  for (const e of edges) {
8673
9032
  if (skipIds.has(e.id)) continue;
@@ -8703,7 +9062,7 @@ function bowSharedStraightPaths(edges, nodes, skipIds) {
8703
9062
  )
8704
9063
  );
8705
9064
  const groupIds = new Set(group.map((g) => g.e.id));
8706
- const labelRects = edges.filter((x) => hasRenderedLabel(x) && !groupIds.has(x.id)).map((x) => computeLabelBBoxWorld(x));
9065
+ const labelRects = edges.filter((x) => hasRenderedLabel(x) && !groupIds.has(x.id)).map((x) => computeLabelBBoxWorld(x, textMetrics));
8707
9066
  const nodeRects = nodes.map((n) => ({ x: n.cx - n.w / 2, y: n.cy - n.h / 2, w: n.w, h: n.h }));
8708
9067
  const build = (seg, offset) => {
8709
9068
  const cx = midX + nx * offset * 2;
@@ -8823,8 +9182,8 @@ function sidePoint(n, side) {
8823
9182
  return { x: n.cx + n.w / 2, y: n.cy };
8824
9183
  }
8825
9184
  }
8826
- function routePath(from, to, fromSide, toSide, obstacles = [], detourSide, _fromLane, _toLane, edge, labelObstacles = obstacles, fromOffset = { x: 0, y: 0 }, toOffset = { x: 0, y: 0 }, avoidRects = []) {
8827
- const labelBoxW = edge ? computeLabelBoxW(edge.label, edge.sub) : 0;
9185
+ function routePath(from, to, fromSide, toSide, obstacles = [], detourSide, _fromLane, _toLane, edge, labelObstacles = obstacles, fromOffset = { x: 0, y: 0 }, toOffset = { x: 0, y: 0 }, avoidRects = [], textMetrics = "proportional") {
9186
+ const labelBoxW = edge ? computeLabelBoxW(edge.label, edge.sub, textMetrics) : 0;
8828
9187
  const labelHalfW = labelBoxW / 2;
8829
9188
  const labelInit = labelInitClearance(edge);
8830
9189
  const verticalPair = fromSide === "bottom" && toSide === "top" || fromSide === "top" && toSide === "bottom";
@@ -9223,7 +9582,7 @@ function routePath(from, to, fromSide, toSide, obstacles = [], detourSide, _from
9223
9582
  labelAnchor: "middle"
9224
9583
  };
9225
9584
  }
9226
- function repositionParallelLabels(edges, nodes) {
9585
+ function repositionParallelLabels(edges, nodes, textMetrics = "proportional") {
9227
9586
  const allSegs = new Map(
9228
9587
  edges.map((e) => [e.id, flattenPathSegments(extractPathSegments(e.d))])
9229
9588
  );
@@ -9248,7 +9607,7 @@ function repositionParallelLabels(edges, nodes) {
9248
9607
  for (const pair of byPair.values()) {
9249
9608
  if (pair.length < 2) continue;
9250
9609
  const pairOrder = [...pair].sort(compareSharedPairOrder);
9251
- const boxes = pair.map((e) => computeLabelBBoxWorld(e));
9610
+ const boxes = pair.map((e) => computeLabelBBoxWorld(e, textMetrics));
9252
9611
  const componentOf = pair.map((_, i) => i);
9253
9612
  for (let i = 0; i < pair.length; i++) {
9254
9613
  for (let j = i + 1; j < pair.length; j++) {
@@ -9273,17 +9632,27 @@ function repositionParallelLabels(edges, nodes) {
9273
9632
  nodes,
9274
9633
  allEdges: edges,
9275
9634
  allSegs,
9276
- xRange
9635
+ xRange,
9636
+ textMetrics
9277
9637
  });
9278
9638
  for (let i = 0; i < members.length; i++) members[i].labelY = placed[i];
9279
9639
  }
9280
9640
  }
9281
9641
  }
9282
9642
  function placeAvoidingSiblingPaths(args) {
9283
- const { members, pair, pairOrder, nodes, allEdges, allSegs, xRange } = args;
9643
+ const {
9644
+ members,
9645
+ pair,
9646
+ pairOrder,
9647
+ nodes,
9648
+ allEdges,
9649
+ allSegs,
9650
+ xRange,
9651
+ textMetrics = "proportional"
9652
+ } = args;
9284
9653
  const sizes = members.map((e) => labelPillH(e.sub));
9285
9654
  const wants = members.map((e) => e.labelY);
9286
- const boxes = members.map((e) => computeLabelBBoxWorld(e));
9655
+ const boxes = members.map((e) => computeLabelBBoxWorld(e, textMetrics));
9287
9656
  const all = members.map((_, i) => i);
9288
9657
  const spread = (idx) => spreadWithMinimalShift(
9289
9658
  idx.map((i) => ({ want: wants[i], size: sizes[i] })),
@@ -9474,14 +9843,14 @@ function labelRectAt(cx, cy, w, h) {
9474
9843
  function inflate(r, pad) {
9475
9844
  return { x: r.x - pad, y: r.y - pad, w: r.w + pad * 2, h: r.h + pad * 2 };
9476
9845
  }
9477
- function slideLabelsAlongOwnPath(edges, nodes) {
9846
+ function slideLabelsAlongOwnPath(edges, nodes, textMetrics = "proportional") {
9478
9847
  const withLabel = edges.filter((e) => hasRenderedLabel(e));
9479
9848
  if (withLabel.length === 0) return;
9480
9849
  const segsById = /* @__PURE__ */ new Map();
9481
9850
  for (const e of edges) segsById.set(e.id, flattenPathSegments(extractPathSegments(e.d)));
9482
9851
  const nodeRects = nodes.map(nodeRect);
9483
9852
  for (const e of withLabel) {
9484
- const w = computeLabelBoxW(e.label, e.sub);
9853
+ const w = computeLabelBoxW(e.label, e.sub, textMetrics);
9485
9854
  const h = labelPillH(e.sub);
9486
9855
  if (w === 0 || h === 0) continue;
9487
9856
  const own = segsById.get(e.id) ?? [];
@@ -9565,9 +9934,11 @@ function hopEdgeCrossings(edges) {
9565
9934
  ends.set(e.id, pathEnds(segs));
9566
9935
  }
9567
9936
  for (const e of edges) {
9937
+ if (e.routing === "metro") continue;
9568
9938
  if ((e.d.match(/M/g) ?? []).length !== 1) continue;
9569
9939
  const own = extractPathSegments(e.d);
9570
9940
  if (own.length === 0) continue;
9941
+ if (own.some((s) => s.cmd === "A")) continue;
9571
9942
  const myEnds = ends.get(e.id) ?? [];
9572
9943
  const hops = /* @__PURE__ */ new Map();
9573
9944
  for (let i = 0; i < own.length; i++) {
@@ -9655,7 +10026,7 @@ function pathVertices(d) {
9655
10026
  const out = [{ x: first.x1, y: first.y1 }];
9656
10027
  for (let i = 0; i < segs.length; i++) {
9657
10028
  const s = segs[i];
9658
- if (s.cmd === "C") return null;
10029
+ if (s.cmd === "C" || s.cmd === "A") return null;
9659
10030
  if (s.cmd === "Q") {
9660
10031
  const c = s.ctrl?.[0];
9661
10032
  if (!c) return null;
@@ -9718,7 +10089,7 @@ function separateSharedStraightRuns(edges, nodes) {
9718
10089
  const v = pathVertices(e.d);
9719
10090
  if (v && v.length >= 2) verts.set(e.id, v);
9720
10091
  }
9721
- if (verts.size < 2) return;
10092
+ if (verts.size === 0) return;
9722
10093
  const moved = /* @__PURE__ */ new Set();
9723
10094
  const fits = (e, pts, k, ax, delta) => {
9724
10095
  const \u8A66\u3057 = pts.map(
@@ -9736,33 +10107,40 @@ function separateSharedStraightRuns(edges, nodes) {
9736
10107
  for (let j = i + 1; j < edges.length; j++) {
9737
10108
  const \u524D = edges[i];
9738
10109
  const \u5F8C = edges[j];
9739
- const A = verts.get(\u524D.id);
9740
- const B = verts.get(\u5F8C.id);
9741
- if (!A || !B) continue;
9742
- if (\u524D.from === \u5F8C.from) continue;
10110
+ if (\u524D.routing === "metro" && \u5F8C.routing === "metro") continue;
10111
+ const \u56FA\u5B9A = \u5F8C.routing === "metro" ? \u5F8C : \u524D;
10112
+ const \u52D5\u304B\u3059 = \u5F8C.routing === "metro" ? \u524D : \u5F8C;
10113
+ const B = verts.get(\u52D5\u304B\u3059.id);
10114
+ if (!B) continue;
10115
+ const \u56FA\u5B9A\u306E\u89D2 = verts.get(\u56FA\u5B9A.id);
10116
+ const \u56FA\u5B9A\u306E\u7D4C\u8DEF = \u56FA\u5B9A\u306E\u89D2 ? [\u56FA\u5B9A\u306E\u89D2] : \u56FA\u5B9A.routing === "metro" ? extractPathSegments(\u56FA\u5B9A.d).filter((s) => s.cmd === "L").map((s) => [{ x: s.x1, y: s.y1 }, { x: s.x2, y: s.y2 }]) : [];
10117
+ if (\u56FA\u5B9A\u306E\u7D4C\u8DEF.length === 0) continue;
10118
+ if (\u56FA\u5B9A.from === \u52D5\u304B\u3059.from) continue;
9743
10119
  for (const ax of [0, 1]) {
9744
- for (let ka = 0; ka + 1 < A.length; ka++) {
9745
- if (!runIsAligned(A, ka, ax)) continue;
9746
- for (let kb = 0; kb + 1 < B.length; kb++) {
9747
- if (!runIsAligned(B, kb, ax)) continue;
9748
- if (kb === 0 || kb + 1 === B.length - 1) continue;
9749
- const \u5EA7\u6A19A = ax === 0 ? A[ka].x : A[ka].y;
9750
- const \u5EA7\u6A19B = ax === 0 ? B[kb].x : B[kb].y;
9751
- if (Math.abs(\u5EA7\u6A19A - \u5EA7\u6A19B) > SHARED_RUN_EPS) continue;
9752
- const sa = runSpan(A, ka, ax);
9753
- const sb = runSpan(B, kb, ax);
9754
- if (Math.min(sa.hi, sb.hi) - Math.max(sa.lo, sb.lo) < SHARED_RUN_MIN) continue;
9755
- for (const delta of [SHARED_RUN_SEPARATION, -SHARED_RUN_SEPARATION]) {
9756
- if (!fits(\u5F8C, B, kb, ax, delta)) continue;
9757
- if (ax === 0) {
9758
- B[kb].x += delta;
9759
- B[kb + 1].x += delta;
9760
- } else {
9761
- B[kb].y += delta;
9762
- B[kb + 1].y += delta;
10120
+ for (const A of \u56FA\u5B9A\u306E\u7D4C\u8DEF) {
10121
+ for (let ka = 0; ka + 1 < A.length; ka++) {
10122
+ if (!runIsAligned(A, ka, ax)) continue;
10123
+ for (let kb = 0; kb + 1 < B.length; kb++) {
10124
+ if (!runIsAligned(B, kb, ax)) continue;
10125
+ if (kb === 0 || kb + 1 === B.length - 1) continue;
10126
+ const \u5EA7\u6A19A = ax === 0 ? A[ka].x : A[ka].y;
10127
+ const \u5EA7\u6A19B = ax === 0 ? B[kb].x : B[kb].y;
10128
+ if (Math.abs(\u5EA7\u6A19A - \u5EA7\u6A19B) > SHARED_RUN_EPS) continue;
10129
+ const sa = runSpan(A, ka, ax);
10130
+ const sb = runSpan(B, kb, ax);
10131
+ if (Math.min(sa.hi, sb.hi) - Math.max(sa.lo, sb.lo) < SHARED_RUN_MIN) continue;
10132
+ for (const delta of [SHARED_RUN_SEPARATION, -SHARED_RUN_SEPARATION]) {
10133
+ if (!fits(\u52D5\u304B\u3059, B, kb, ax, delta)) continue;
10134
+ if (ax === 0) {
10135
+ B[kb].x += delta;
10136
+ B[kb + 1].x += delta;
10137
+ } else {
10138
+ B[kb].y += delta;
10139
+ B[kb + 1].y += delta;
10140
+ }
10141
+ moved.add(\u52D5\u304B\u3059.id);
10142
+ break;
9763
10143
  }
9764
- moved.add(\u5F8C.id);
9765
- break;
9766
10144
  }
9767
10145
  }
9768
10146
  }
@@ -9774,7 +10152,7 @@ function separateSharedStraightRuns(edges, nodes) {
9774
10152
  e.d = verticesToPath(verts.get(e.id));
9775
10153
  }
9776
10154
  }
9777
- function pullOutgoingFirstCorner(edges, nodes) {
10155
+ function pullOutgoingFirstCorner(edges, nodes, textMetrics = "proportional") {
9778
10156
  if (edges.length < 2) return;
9779
10157
  const \u675F = /* @__PURE__ */ new Map();
9780
10158
  const \u540C\u3058\u7D44\u306E\u6570 = /* @__PURE__ */ new Map();
@@ -9789,12 +10167,19 @@ function pullOutgoingFirstCorner(edges, nodes) {
9789
10167
  let \u672D\u3092\u65E7\u7D4C\u8DEF\u3078\u8FFD\u5F93\u6E08\u307F = false;
9790
10168
  for (const list of \u675F.values()) {
9791
10169
  if (list.length < 2) continue;
9792
- const \u4E26\u3073 = list.flatMap((e) => {
10170
+ const \u4E26\u3073 = list.map((e) => {
9793
10171
  const pts = pathVertices(e.d);
9794
- if (!pts || pts.length < 2) return [];
9795
- return [{ e, pts, \u6700\u521D\u306E\u9577\u3055: Math.hypot(pts[1].x - pts[0].x, pts[1].y - pts[0].y) }];
9796
- }).sort((a, b) => b.\u6700\u521D\u306E\u9577\u3055 - a.\u6700\u521D\u306E\u9577\u3055);
10172
+ if (pts && pts.length >= 2) {
10173
+ return { e, pts, \u6700\u521D\u306E\u9577\u3055: Math.hypot(pts[1].x - pts[0].x, pts[1].y - pts[0].y) };
10174
+ }
10175
+ if (e.routing !== "metro") return null;
10176
+ const first = extractPathSegments(e.d)[0];
10177
+ if (!first) return null;
10178
+ return { e, pts: null, \u6700\u521D\u306E\u9577\u3055: Math.hypot(first.x2 - first.x1, first.y2 - first.y1) };
10179
+ }).filter((x) => x !== null).sort((a, b) => b.\u6700\u521D\u306E\u9577\u3055 - a.\u6700\u521D\u306E\u9577\u3055);
9797
10180
  for (const { e, pts, \u6700\u521D\u306E\u9577\u3055 } of \u4E26\u3073.slice(1)) {
10181
+ if (e.routing === "metro") continue;
10182
+ if (!pts) continue;
9798
10183
  if ((\u540C\u3058\u7D44\u306E\u6570.get(`${e.from}->${e.to}`) ?? 0) > 1) continue;
9799
10184
  if (pts.length < 3 || \u6700\u521D\u306E\u9577\u3055 <= EDGE_STUB_OUT + VERTICAL_DETOUR_CORNER) continue;
9800
10185
  const \u6A2A = e.fromSide === "left" || e.fromSide === "right";
@@ -9821,10 +10206,10 @@ function pullOutgoingFirstCorner(edges, nodes) {
9821
10206
  }
9822
10207
  e.d = \u524D;
9823
10208
  if (!\u672D\u3092\u65E7\u7D4C\u8DEF\u3078\u8FFD\u5F93\u6E08\u307F) {
9824
- slideLabelsAlongOwnPath(edges, nodes);
10209
+ slideLabelsAlongOwnPath(edges, nodes, textMetrics);
9825
10210
  \u672D\u3092\u65E7\u7D4C\u8DEF\u3078\u8FFD\u5F93\u6E08\u307F = true;
9826
10211
  }
9827
- const labelBox = computeLabelBBoxWorld(e);
10212
+ const labelBox = computeLabelBBoxWorld(e, textMetrics);
9828
10213
  const label = { x: labelBox.x + labelBox.w / 2, y: labelBox.y + labelBox.h / 2 };
9829
10214
  const \u7DDA\u5206\u307E\u3067\u306E\u8DDD\u96E22 = (a, b) => {
9830
10215
  const dx = b.x - a.x;
@@ -9848,7 +10233,8 @@ var ENDPOINT_FAN_MIN = 20;
9848
10233
  var ENDPOINT_FAN_RUNUP = 40;
9849
10234
  var MIXED_ROOT_OVERLAP_MIN = 24;
9850
10235
  function fanIncomingEndpoints(edges, nodes) {
9851
- if (edges.length < 2) return;
10236
+ const \u7D42\u70B9\u306E\u79FB\u52D5 = /* @__PURE__ */ new Map();
10237
+ if (edges.length < 2) return \u7D42\u70B9\u306E\u79FB\u52D5;
9852
10238
  const nmap = new Map(nodes.map((n) => [n.id, n]));
9853
10239
  const \u5E73\u5766\u306A\u533A\u9593 = new Map(edges.map((e) => [e.id, flattenPathSegments(extractPathSegments(e.d))]));
9854
10240
  const \u8EF8\u306B\u5E73\u884C\u306A\u91CD\u306A\u308A\u9577\u3055 = (\u4E00\u65B9, \u4ED6\u65B9) => {
@@ -9918,6 +10304,7 @@ function fanIncomingEndpoints(edges, nodes) {
9918
10304
  const d = \u4E2D\u592E\u304C\u585E\u304C\u3063\u3066\u3044\u308B ? \u4E26\u3073[k].\u6DF1\u3055 < \u8FBA\u306E\u4E2D\u5FC3 ? -(++\u8CA0\u5074\u306E\u5E2D * \u9593\u9694) : ++\u6B63\u5074\u306E\u5E2D * \u9593\u9694 : k * \u9593\u9694 - \u4E2D\u5FC3;
9919
10305
  if (Math.abs(d) < 1e-3) continue;
9920
10306
  const e = \u4E26\u3073[k].e;
10307
+ if (e.routing === "metro") continue;
9921
10308
  const \u524D = e.d;
9922
10309
  const \u524D\u306E\u4EA4\u5DEE = countEdgeCrossings(edges).count;
9923
10310
  const \u9577\u3044\u52A9\u8D70 = \u4E26\u3073[k].\u9577\u3044\u52A9\u8D70;
@@ -9929,6 +10316,72 @@ function fanIncomingEndpoints(edges, nodes) {
9929
10316
  if (countEdgeCrossings(edges).count <= \u524D\u306E\u4EA4\u5DEE) break;
9930
10317
  e.d = \u524D;
9931
10318
  }
10319
+ if (e.d !== \u524D) \u7D42\u70B9\u306E\u79FB\u52D5.set(e.id, \u6A2A ? { dx: 0, dy: d } : { dx: d, dy: 0 });
10320
+ }
10321
+ }
10322
+ return \u7D42\u70B9\u306E\u79FB\u52D5;
10323
+ }
10324
+ function followLabelsToFannedTails(edges, obstacles, shifts, textMetrics = "proportional") {
10325
+ if (shifts.size === 0) return;
10326
+ const \u6E2C\u308A\u65B9 = \u7DDA\u306E\u6E2C\u308A\u65B9\u3092\u4F5C\u308B();
10327
+ const labels = edges.filter(hasRenderedLabel).map((e) => ({
10328
+ kind: "edge-label",
10329
+ id: e.id,
10330
+ ...computeLabelBBoxWorld(e, textMetrics)
10331
+ }));
10332
+ const labelIndexByEdgeId = new Map(labels.map((label, index) => [label.id, index]));
10333
+ const edgeById = new Map(edges.map((e) => [e.id, e]));
10334
+ const \u5468\u308A = {
10335
+ \u7BB1\u305F\u3061: obstacles.filter((o) => o.kind === "node" || o.kind === "lane-label"),
10336
+ labels,
10337
+ edges,
10338
+ edgeById,
10339
+ \u6E2C\u308A\u65B9
10340
+ };
10341
+ for (const e of edges) {
10342
+ const \u79FB\u52D5 = shifts.get(e.id);
10343
+ if (!\u79FB\u52D5 || !hasRenderedLabel(e)) continue;
10344
+ const labelIndex = labelIndexByEdgeId.get(e.id);
10345
+ if (labelIndex === void 0) continue;
10346
+ const \u5143\u306E\u672D = labels[labelIndex];
10347
+ const \u81EA\u5206\u306E\u533A\u9593 = \u6E2C\u308A\u65B9.\u533A\u9593(e.id, e.d);
10348
+ if (e.overlay && measurePathLabelGapSegs(\u81EA\u5206\u306E\u533A\u9593, {
10349
+ x: \u5143\u306E\u672D.x + \u5143\u306E\u672D.w / 2,
10350
+ y: \u5143\u306E\u672D.y + \u5143\u306E\u672D.h / 2,
10351
+ w: 0,
10352
+ h: 0
10353
+ }) <= OVERLAY_LABEL_ON_PATH_TOLERANCE) continue;
10354
+ const \u6700\u5F8C = \u81EA\u5206\u306E\u533A\u9593.at(-1);
10355
+ if (!\u6700\u5F8C) continue;
10356
+ if (!segmentsCrossRect([\u6700\u5F8C], \u5143\u306E\u672D)) continue;
10357
+ const \u5019\u88DCa = {
10358
+ labelX: e.labelX + \u79FB\u52D5.dx,
10359
+ labelY: e.labelY + \u79FB\u52D5.dy,
10360
+ labelAnchor: e.labelAnchor
10361
+ };
10362
+ const \u5019\u88DCa\u306E\u7BB1 = computeLabelBBoxWorld({ ...e, ...\u5019\u88DCa }, textMetrics);
10363
+ const \u6700\u5F8C\u306F\u7E26 = Math.abs(\u6700\u5F8C.x2 - \u6700\u5F8C.x1) <= Math.abs(\u6700\u5F8C.y2 - \u6700\u5F8C.y1);
10364
+ const \u5019\u88DC = [
10365
+ \u5019\u88DCa,
10366
+ {
10367
+ labelX: \u6700\u5F8C\u306F\u7E26 ? \u6700\u5F8C.x1 * 2 - (\u5019\u88DCa\u306E\u7BB1.x + \u5019\u88DCa\u306E\u7BB1.w / 2) : \u5019\u88DCa\u306E\u7BB1.x + \u5019\u88DCa\u306E\u7BB1.w / 2,
10368
+ labelY: \u6700\u5F8C\u306F\u7E26 ? \u5019\u88DCa\u306E\u7BB1.y + \u5019\u88DCa\u306E\u7BB1.h / 2 : \u6700\u5F8C.y1 * 2 - (\u5019\u88DCa\u306E\u7BB1.y + \u5019\u88DCa\u306E\u7BB1.h / 2),
10369
+ labelAnchor: "middle"
10370
+ }
10371
+ ];
10372
+ for (const c of \u5019\u88DC) {
10373
+ const \u672D = {
10374
+ kind: "edge-label",
10375
+ id: e.id,
10376
+ ...computeLabelBBoxWorld({ ...e, ...c }, textMetrics)
10377
+ };
10378
+ if (segmentsCrossRect([\u6700\u5F8C], \u672D)) continue;
10379
+ if (\u672D\u306E\u79FB\u52D5\u3092\u585E\u3050\u76F8\u624B\u3092\u63A2\u3059(\u5468\u308A, \u5143\u306E\u672D, \u672D) !== null) continue;
10380
+ e.labelX = c.labelX;
10381
+ e.labelY = c.labelY;
10382
+ e.labelAnchor = c.labelAnchor;
10383
+ labels[labelIndex] = \u672D;
10384
+ break;
9932
10385
  }
9933
10386
  }
9934
10387
  }
@@ -9945,7 +10398,7 @@ function \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \
9945
10398
  if ((e.d.match(/M/g) ?? []).length !== 1) return null;
9946
10399
  const segs = extractPathSegments(e.d);
9947
10400
  if (segs.length === 0) return null;
9948
- if (segs.some((s) => s.cmd === "C")) return null;
10401
+ if (segs.some((s) => s.cmd === "C" || s.cmd === "A")) return null;
9949
10402
  const last = segs[segs.length - 1];
9950
10403
  if (last.cmd !== "L") return null;
9951
10404
  const \u5782\u76F4\u306B\u5165\u308B = \u6A2A ? Math.abs(last.y2 - last.y1) < 0.5 && Math.abs(last.x2 - last.x1) > 0.5 : Math.abs(last.x2 - last.x1) < 0.5 && Math.abs(last.y2 - last.y1) > 0.5;
@@ -10115,7 +10568,7 @@ function expandLanesForNodes(lanes, nodes) {
10115
10568
  };
10116
10569
  });
10117
10570
  }
10118
- function expandLaneGapsForEdgeLabels(lanes, nodes, edges) {
10571
+ function expandLaneGapsForEdgeLabels(lanes, nodes, edges, textMetrics = "proportional") {
10119
10572
  if (lanes.length < 2) return lanes;
10120
10573
  const layoutedLanes = lanes.filter((l) => !(l.posX !== void 0 && l.posY !== void 0));
10121
10574
  if (layoutedLanes.length < 2) return lanes;
@@ -10131,7 +10584,7 @@ function expandLaneGapsForEdgeLabels(lanes, nodes, edges) {
10131
10584
  const fi = laneIndexById.get(fromLane);
10132
10585
  const ti = laneIndexById.get(toLane);
10133
10586
  if (fi === void 0 || ti === void 0 || fi === ti) continue;
10134
- const labelBoxW = computeLabelBoxW(edge.label, edge.sub);
10587
+ const labelBoxW = computeLabelBoxW(edge.label, edge.sub, textMetrics);
10135
10588
  if (labelBoxW === 0) continue;
10136
10589
  const lo = Math.min(fi, ti);
10137
10590
  const hi = Math.max(fi, ti);
@@ -10236,13 +10689,16 @@ function \u5411\u304D\u3092\u53D6\u308B(end, \u5019\u88DC) {
10236
10689
  }
10237
10690
  return null;
10238
10691
  }
10239
- function \u7AEF\u3067\u306E\u5411\u304D(d, \u7AEF) {
10692
+ function \u7DDA\u306E\u7AEF\u306E\u5411\u304D(d, \u7AEF) {
10240
10693
  const segs = extractPathSegments(d);
10241
10694
  if (segs.length === 0) return null;
10242
10695
  if (\u7AEF === "head") {
10243
10696
  const last = segs[segs.length - 1];
10244
10697
  const end2 = { x: last.x2, y: last.y2 };
10245
- const \u5019\u88DC2 = segs.slice().reverse().flatMap((s) => [s.cmd === "Q" ? s.ctrl?.[0] : s.cmd === "C" ? s.ctrl?.[1] : void 0, { x: s.x1, y: s.y1 }]);
10698
+ const \u5019\u88DC2 = segs.slice().reverse().flatMap((s) => {
10699
+ const \u5236\u5FA1\u70B9 = s.cmd === "C" ? [s.ctrl?.[1], s.ctrl?.[0]] : s.cmd === "Q" ? [s.ctrl?.[0]] : [];
10700
+ return [...\u5236\u5FA1\u70B9, { x: s.x1, y: s.y1 }];
10701
+ });
10246
10702
  return \u5411\u304D\u3092\u53D6\u308B(end2, \u5019\u88DC2);
10247
10703
  }
10248
10704
  const first = segs[0];
@@ -10250,10 +10706,10 @@ function \u7AEF\u3067\u306E\u5411\u304D(d, \u7AEF) {
10250
10706
  const \u5019\u88DC = segs.flatMap((s) => [...s.ctrl ?? [], { x: s.x2, y: s.y2 }]);
10251
10707
  return \u5411\u304D\u3092\u53D6\u308B(end, \u5019\u88DC);
10252
10708
  }
10253
- function \u7AEF\u306E\u5B57\u3092\u7F6E\u304F(edge, \u7AEF = "head") {
10709
+ function \u7AEF\u306E\u5B57\u3092\u7F6E\u304F(edge, \u7AEF = "head", textMetrics = "proportional") {
10254
10710
  const text = (\u7AEF === "head" ? edge.headLabel : edge.tailLabel)?.trim();
10255
10711
  if (!text) return null;
10256
- const \u5411\u304D = \u7AEF\u3067\u306E\u5411\u304D(edge.d, \u7AEF);
10712
+ const \u5411\u304D = \u7DDA\u306E\u7AEF\u306E\u5411\u304D(edge.d, \u7AEF);
10257
10713
  if (!\u5411\u304D) return null;
10258
10714
  const { end, ux, uy } = \u5411\u304D;
10259
10715
  const bx = end.x - ux * \u7AEF\u306E\u5B57\u3092\u623B\u3059\u8DDD\u96E2;
@@ -10261,7 +10717,8 @@ function \u7AEF\u306E\u5B57\u3092\u7F6E\u304F(edge, \u7AEF = "head") {
10261
10717
  const w = measureTextWidth(text, {
10262
10718
  fontSize: \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055,
10263
10719
  fontWeight: EDGE_LABEL_TEXT.sub.fontWeight,
10264
- fontFamily: "mono"
10720
+ fontFamily: "mono",
10721
+ textMetrics
10265
10722
  });
10266
10723
  const h = \u7BB1\u306E\u9AD8\u3055;
10267
10724
  const \u672D = hasRenderedLabel(edge) && edge.labelX !== void 0 && edge.labelY !== void 0 ? { x: edge.labelX, y: edge.labelY } : null;
@@ -10310,10 +10767,10 @@ function autoStorageHeight(n, defaultH) {
10310
10767
  }
10311
10768
  return Math.max(defaultH, \u5FC5\u8981);
10312
10769
  }
10313
- function autoRowsWidth(n, defaultW) {
10770
+ function autoRowsWidth(n, defaultW, textMetrics = "proportional") {
10314
10771
  if (n.w != null) return n.w;
10315
10772
  if (!n.rows || n.rows.length === 0) return defaultW;
10316
- const required = requiredRowsWidth(n.rows, n.kind);
10773
+ const required = requiredRowsWidth(n.rows, n.kind, textMetrics);
10317
10774
  return Math.max(defaultW, required);
10318
10775
  }
10319
10776
  function \u7BB1\u306E\u9AD8\u30552(n, \u65E2\u5B9Ah) {
@@ -10351,7 +10808,7 @@ function requiredStackGapForEdgeLabels(diag, allStacks) {
10351
10808
  }
10352
10809
  return required;
10353
10810
  }
10354
- function layoutNodes(diag, lanes) {
10811
+ function layoutNodes(diag, lanes, textMetrics) {
10355
10812
  const laneMap = new Map(lanes.map((l) => [l.id, l]));
10356
10813
  const allStacks = Array.from(new Set(diag.nodes.map((n) => n.stack))).sort((a, b) => a - b);
10357
10814
  const rowH = /* @__PURE__ */ new Map();
@@ -10395,7 +10852,7 @@ function layoutNodes(diag, lanes) {
10395
10852
  }
10396
10853
  const size = NODE_SIZE[n.kind];
10397
10854
  if (n.posX !== void 0 && n.posY !== void 0) {
10398
- const w2 = n.posW ?? n.w ?? autoRowsWidth(n, size.w);
10855
+ const w2 = n.posW ?? n.w ?? autoRowsWidth(n, size.w, textMetrics);
10399
10856
  const h2 = n.posH ?? n.h ?? rowH.get(n.stack) ?? size.h;
10400
10857
  out.push({
10401
10858
  ...n,
@@ -10413,7 +10870,7 @@ function layoutNodes(diag, lanes) {
10413
10870
  const \u81EA\u524D\u306E\u9AD8\u3055 = n.rowMarks !== void 0;
10414
10871
  const h = n.h ?? (\u81EA\u524D\u306E\u9AD8\u3055 ? \u7BB1\u306E\u9AD8\u30552(n, size.h) : \u6BB5\u306E\u9AD8\u3055);
10415
10872
  const cy = \u6BB5\u306E\u82AF;
10416
- const w = autoRowsWidth(n, size.w);
10873
+ const w = autoRowsWidth(n, size.w, textMetrics);
10417
10874
  out.push({
10418
10875
  ...n,
10419
10876
  cx,
@@ -10533,10 +10990,16 @@ function applyRowLevelNodeShifts(nodes, lanes, nodeShifts) {
10533
10990
  return moved ? { nodes: outNodes, lanes: outLanes } : null;
10534
10991
  }
10535
10992
  function layout(diag) {
10993
+ const textMetrics = resolveTextMetrics(diag.textMetrics);
10536
10994
  const lanes = layoutLanes(diag);
10537
- const rawNodes = applyFooterShapeDrops(lanes, layoutNodes(diag, lanes));
10995
+ const rawNodes = applyFooterShapeDrops(lanes, layoutNodes(diag, lanes, textMetrics));
10538
10996
  const expandedLanes = expandLanesForNodes(lanes, rawNodes);
10539
- const gapExpandedLanes = expandLaneGapsForEdgeLabels(expandedLanes, rawNodes, diag.edges);
10997
+ const gapExpandedLanes = expandLaneGapsForEdgeLabels(
10998
+ expandedLanes,
10999
+ rawNodes,
11000
+ diag.edges,
11001
+ textMetrics
11002
+ );
10540
11003
  const nodes = rawNodes.map((n) => {
10541
11004
  if (n.posX !== void 0 && n.posY !== void 0) return n;
10542
11005
  const oldLane = lanes.find((l) => l.id === n.lane);
@@ -10545,13 +11008,13 @@ function layout(diag) {
10545
11008
  return { ...n, cx: newLane.x + newLane.width / 2 };
10546
11009
  });
10547
11010
  const containedLanesPre = recomputeContainedLanes(gapExpandedLanes, nodes);
10548
- const edgesPre = layoutEdges(diag, nodes, containedLanesPre);
10549
- const bboxesPre = collectBBoxes(containedLanesPre, nodes, edgesPre);
11011
+ const edgesPre = layoutEdges(diag, nodes, containedLanesPre, textMetrics);
11012
+ const bboxesPre = collectBBoxes(containedLanesPre, nodes, edgesPre, textMetrics);
10550
11013
  const collisionsPre = detectCollisions(bboxesPre, edgesPre);
10551
11014
  const nodesResolved = resolveOverlaps(nodes, collisionsPre);
10552
11015
  const moved = nodesResolved !== nodes;
10553
11016
  const containedLanes = moved ? recomputeContainedLanes(gapExpandedLanes, nodesResolved) : containedLanesPre;
10554
- const edgesAfterMove = moved ? layoutEdges(diag, nodesResolved, containedLanes) : edgesPre;
11017
+ const edgesAfterMove = moved ? layoutEdges(diag, nodesResolved, containedLanes, textMetrics) : edgesPre;
10555
11018
  const chainShiftClearance = Math.max(CLEARANCE_LABEL_LABEL, CLEARANCE_NODE_LABEL);
10556
11019
  let edges;
10557
11020
  let nodesFinal = nodesResolved;
@@ -10562,10 +11025,13 @@ function layout(diag) {
10562
11025
  } else {
10563
11026
  const propagateResult = resolveEdgeLabelOverlapsWithChainAndPropagate(
10564
11027
  edgesAfterMove,
10565
- collectBBoxes(containedLanes, nodesResolved, []).filter(
11028
+ collectBBoxes(containedLanes, nodesResolved, [], textMetrics).filter(
10566
11029
  (b) => b.kind === "node" || b.kind === "lane-label"
10567
11030
  ),
10568
- chainShiftClearance
11031
+ chainShiftClearance,
11032
+ void 0,
11033
+ void 0,
11034
+ textMetrics
10569
11035
  );
10570
11036
  edges = propagateResult.edges;
10571
11037
  if (propagateResult.nodeShifts.size > 0) {
@@ -10577,28 +11043,39 @@ function layout(diag) {
10577
11043
  }
10578
11044
  if (nodesFinal !== nodesResolved) {
10579
11045
  containedLanesFinal = recomputeContainedLanes(laneShiftedBase, nodesFinal);
10580
- edges = layoutEdges(diag, nodesFinal, containedLanesFinal);
11046
+ edges = layoutEdges(diag, nodesFinal, containedLanesFinal, textMetrics);
10581
11047
  }
10582
11048
  }
10583
11049
  const positionedEdgeIds = new Set(
10584
- diag.edges.filter((e) => e.posX1 !== void 0 && e.posY1 !== void 0 && e.posX2 !== void 0 && e.posY2 !== void 0).map((e) => e.id)
11050
+ diag.edges.filter(
11051
+ (e) => e.routing === "curve" || e.routing === "metro" || e.posX1 !== void 0 && e.posY1 !== void 0 && e.posX2 !== void 0 && e.posY2 !== void 0
11052
+ ).map((e) => e.id)
10585
11053
  );
10586
- bowSharedStraightPaths(edges, nodesFinal, positionedEdgeIds);
10587
- pullOutgoingFirstCorner(edges, nodesFinal);
10588
- fanIncomingEndpoints(edges, nodesFinal);
11054
+ bowSharedStraightPaths(edges, nodesFinal, positionedEdgeIds, textMetrics);
11055
+ pullOutgoingFirstCorner(edges, nodesFinal, textMetrics);
11056
+ const fannedTailShifts = fanIncomingEndpoints(edges, nodesFinal);
10589
11057
  separateSharedStraightRuns(edges, nodesFinal);
10590
11058
  hopEdgeCrossings(edges);
10591
- repositionParallelLabels(edges, nodesFinal);
10592
- slideLabelsAlongOwnPath(edges, nodesFinal);
11059
+ const labelClearanceObstacles = collectBBoxes(
11060
+ containedLanesFinal,
11061
+ nodesFinal,
11062
+ [],
11063
+ textMetrics
11064
+ ).filter(
11065
+ (b) => b.kind === "node" || b.kind === "lane-label"
11066
+ );
11067
+ followLabelsToFannedTails(edges, labelClearanceObstacles, fannedTailShifts, textMetrics);
11068
+ repositionParallelLabels(edges, nodesFinal, textMetrics);
11069
+ slideLabelsAlongOwnPath(edges, nodesFinal, textMetrics);
10593
11070
  if (!isChainEdgeLabelDisabled()) {
10594
11071
  edges = resolveLabelClearanceAfterPathPasses(
10595
11072
  edges,
10596
- collectBBoxes(containedLanesFinal, nodesFinal, []).filter(
10597
- (b) => b.kind === "node" || b.kind === "lane-label"
10598
- )
11073
+ labelClearanceObstacles,
11074
+ void 0,
11075
+ textMetrics
10599
11076
  );
10600
11077
  }
10601
- const bboxes = collectBBoxes(containedLanesFinal, nodesFinal, edges);
11078
+ const bboxes = collectBBoxes(containedLanesFinal, nodesFinal, edges, textMetrics);
10602
11079
  const collisions = detectCollisions(bboxes, edges);
10603
11080
  const nearCollisions = detectNearCollisions(bboxes, edges);
10604
11081
  if (collisions.length > 0) {
@@ -10638,6 +11115,8 @@ function layout(diag) {
10638
11115
  // 描画側の固定の字の言語 (#847)。 既定 (`en`) と型の外の値は持たせない = 配置の結果の形を
10639
11116
  // 変更前と揃え、記法の書き損じで一部の字だけ日本語になる形を作らない
10640
11117
  ...resolveLang(diag.lang) === "ja" ? { lang: "ja" } : {},
11118
+ // 既定は持ち越さない。既存の LaidDiagram の形を変えず、等幅の図だけ描画へ伝える
11119
+ ...textMetrics === "monospace" ? { textMetrics: "monospace" } : {},
10641
11120
  // 種類も配色と同じく空の目印を出さない。 遮断をここに揃えると手書きの図にも効く
10642
11121
  ...diag.type ? { type: diag.type } : {},
10643
11122
  bboxes,
@@ -11534,6 +12013,7 @@ function CdlEdgeView({
11534
12013
  "g",
11535
12014
  {
11536
12015
  "data-cdl-edge": edge.id,
12016
+ "data-cdl-routing": edge.routing === "metro" ? "metro" : void 0,
11537
12017
  "data-cdl-from": edge.from,
11538
12018
  "data-cdl-to": edge.to,
11539
12019
  "data-cdl-active": active ? "true" : "false",
@@ -11545,6 +12025,7 @@ function CdlEdgeView({
11545
12025
  "data-cdl-edge-label": edge.label,
11546
12026
  "data-cdl-edge-sub": edge.sub ?? "",
11547
12027
  "data-cdl-tone": edge.tone,
12028
+ "data-cdl-edge-role": edge.role,
11548
12029
  children: [
11549
12030
  isDotted ? /* @__PURE__ */ jsxs("g", { children: [
11550
12031
  /* @__PURE__ */ jsx("path", { id: glowPathId, d: glowPathD, fill: "none", stroke: "none" }),
@@ -11696,11 +12177,12 @@ function CdlEdgeGlowView({
11696
12177
  }
11697
12178
  function CdlEdgeLabelView({
11698
12179
  edge,
11699
- active
12180
+ active,
12181
+ textMetrics = "proportional"
11700
12182
  }) {
11701
12183
  if (!hasRenderedLabel(edge)) return null;
11702
12184
  const color = edgeColor(edge);
11703
- const bbox = computeLabelBBoxWorld(edge);
12185
+ const bbox = computeLabelBBoxWorld(edge, textMetrics);
11704
12186
  const boxW = bbox.w;
11705
12187
  const boxH = bbox.h;
11706
12188
  const boxLeftX = bbox.x - edge.labelX;
@@ -11716,6 +12198,8 @@ function CdlEdgeLabelView({
11716
12198
  "data-cdl-edge-label-for": edge.id,
11717
12199
  "data-cdl-edge-label-text": edge.label,
11718
12200
  "data-cdl-edge-sub-text": edge.sub ?? "",
12201
+ "data-cdl-tone": edge.tone,
12202
+ "data-cdl-edge-role": edge.role,
11719
12203
  children: [
11720
12204
  edge.labelPlate !== false && /* @__PURE__ */ jsx(
11721
12205
  "rect",
@@ -11769,9 +12253,10 @@ function CdlEdgeLabelView({
11769
12253
  function CdlEdgeEndLabelView({
11770
12254
  edge,
11771
12255
  active,
11772
- \u7AEF
12256
+ \u7AEF,
12257
+ textMetrics = "proportional"
11773
12258
  }) {
11774
- const \u7F6E\u304D\u5834\u6240 = \u7AEF\u306E\u5B57\u3092\u7F6E\u304F(edge, \u7AEF);
12259
+ const \u7F6E\u304D\u5834\u6240 = \u7AEF\u306E\u5B57\u3092\u7F6E\u304F(edge, \u7AEF, textMetrics);
11775
12260
  if (!\u7F6E\u304D\u5834\u6240) return null;
11776
12261
  const color = edgeColor(edge);
11777
12262
  return /* @__PURE__ */ jsx(
@@ -11780,6 +12265,8 @@ function CdlEdgeEndLabelView({
11780
12265
  "data-cdl-role": "edge-end-label",
11781
12266
  "data-cdl-edge-end-label-for": edge.id,
11782
12267
  "data-cdl-edge-end": \u7AEF,
12268
+ "data-cdl-tone": edge.tone,
12269
+ "data-cdl-edge-role": edge.role,
11783
12270
  x: \u7F6E\u304D\u5834\u6240.x,
11784
12271
  y: \u7F6E\u304D\u5834\u6240.y,
11785
12272
  fontSize: \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055,
@@ -12024,12 +12511,18 @@ var SEQ_DOT = 7;
12024
12511
  var SEQ_SELF_W = 52;
12025
12512
  var SEQ_COL_MIN = 200;
12026
12513
  var g4 = (v) => Math.round(v / 4) * 4;
12027
- function sequenceBoardMetrics(data) {
12514
+ function sequenceBoardMetrics(data, textMetrics = "proportional") {
12028
12515
  const \u540D\u5E45 = data.actors.map(
12029
- (a) => Math.max(textWidth(a.name, SEQ_NAME), a.subtitle ? textWidth(a.subtitle, SEQ_SUB) : 0)
12516
+ (a) => Math.max(
12517
+ textWidth(a.name, SEQ_NAME, 0, textMetrics),
12518
+ a.subtitle ? textWidth(a.subtitle, SEQ_SUB, 0, textMetrics) : 0
12519
+ )
12030
12520
  );
12031
12521
  const colW = g4(Math.max(SEQ_COL_MIN, Math.max(0, ...\u540D\u5E45) + SEQ_COL_PAD));
12032
- const \u8A9E\u5E45 = Math.max(0, ...data.messages.map((m) => textWidth(m.label, SEQ_LABEL)));
12522
+ const \u8A9E\u5E45 = Math.max(
12523
+ 0,
12524
+ ...data.messages.map((m) => textWidth(m.label, SEQ_LABEL, 0, textMetrics))
12525
+ );
12033
12526
  const gutter = g4(SEQ_EDGE + SEQ_GUTTER_PAD + \u8A9E\u5E45 + SEQ_GUTTER_GAP);
12034
12527
  const headY = SEQ_EDGE + SEQ_HEAD;
12035
12528
  const rowY = (i) => headY + SEQ_ROW_PAD + i * SEQ_ROW;
@@ -12042,11 +12535,12 @@ function sequenceBoardMetrics(data) {
12042
12535
  }
12043
12536
  function SequenceBoardNode({
12044
12537
  node,
12045
- stateValues
12538
+ stateValues,
12539
+ textMetrics = "proportional"
12046
12540
  }) {
12047
12541
  const data = node.sequenceData;
12048
12542
  if (!data) return /* @__PURE__ */ jsx("g", { "data-cdl-role": "sequence-board" });
12049
- const m = sequenceBoardMetrics(data);
12543
+ const m = sequenceBoardMetrics(data, textMetrics);
12050
12544
  const x = node.cx - node.w / 2;
12051
12545
  const y = node.cy - node.h / 2;
12052
12546
  const \u73FE\u5728 = (() => {
@@ -12697,7 +13191,8 @@ function GenericNode({
12697
13191
  active,
12698
13192
  value,
12699
13193
  stateValues,
12700
- \u5024\u306E\u540D\u524D
13194
+ \u5024\u306E\u540D\u524D,
13195
+ textMetrics = "proportional"
12701
13196
  }) {
12702
13197
  const base = STYLES[node.kind] ?? FALLBACK;
12703
13198
  const toned = toneColor3(node.tone);
@@ -12836,7 +13331,7 @@ function GenericNode({
12836
13331
  const resolved = node.rows.map((row) => interpolate(row, stateValues, \u5024\u306E\u540D\u524D));
12837
13332
  const splits = resolved.map(splitRow);
12838
13333
  const leftMaxWidth = splits.reduce(
12839
- (m, s) => Math.max(m, rowColumnWidth(s.left, GENERIC_ROW_LEFT_SIZE_PX, false)),
13334
+ (m, s) => Math.max(m, rowColumnWidth(s.left, GENERIC_ROW_LEFT_SIZE_PX, false, textMetrics)),
12840
13335
  0
12841
13336
  );
12842
13337
  const rightColX = ROW_PAD_X_PX + leftMaxWidth + ROW_COL_GAP_PX;
@@ -12962,17 +13457,22 @@ function DynShapeNode({
12962
13457
  return renderPolygon(shape, cx, cy, stateValues, fillColor, strokeColor, activeOpacity);
12963
13458
  }
12964
13459
  })();
13460
+ const \u63C3\u3048 = \u7BB1\u3044\u3063\u3071\u3044\u306B\u63CF\u304F2(shape.kind) ? "start" : "middle";
13461
+ return renderShapeWithOutsideLabels(\u5F62, node, \u63C3\u3048);
13462
+ }
13463
+ function renderShapeWithOutsideLabels(\u5F62, node, \u63C3\u3048) {
13464
+ const cx = node.cx;
13465
+ const y = node.cy - node.h / 2;
12965
13466
  const \u540D\u524D = (node.title ?? "").trim();
12966
13467
  const \u5024 = (node.subtitle ?? "").trim();
12967
13468
  if (\u540D\u524D === "" && \u5024 === "") return \u5F62;
12968
- const \u63C3\u3048 = \u7BB1\u3044\u3063\u3071\u3044\u306B\u63CF\u304F2(shape.kind) ? "start" : "middle";
12969
13469
  return /* @__PURE__ */ jsxs("g", { children: [
12970
13470
  \u5F62,
12971
13471
  \u540D\u524D !== "" && /* @__PURE__ */ jsx(
12972
13472
  "text",
12973
13473
  {
12974
13474
  "data-cdl-role": "shape-name",
12975
- x: \u63C3\u3048 === "start" ? x : cx,
13475
+ x: \u63C3\u3048 === "start" ? node.cx - node.w / 2 : cx,
12976
13476
  y: y - NAME_GAP,
12977
13477
  textAnchor: \u63C3\u3048,
12978
13478
  fontSize: 13,
@@ -12986,7 +13486,7 @@ function DynShapeNode({
12986
13486
  {
12987
13487
  "data-cdl-role": "shape-value",
12988
13488
  x: cx,
12989
- y: y + h + VALUE_GAP,
13489
+ y: y + node.h + VALUE_GAP,
12990
13490
  textAnchor: "middle",
12991
13491
  fontSize: 12,
12992
13492
  fill: "var(--cdl-text-dim, #5a6270)",
@@ -13236,6 +13736,27 @@ function interpolateColor(template, stateValues, fallback) {
13236
13736
  if (!template) return fallback;
13237
13737
  return interpolate(template, stateValues);
13238
13738
  }
13739
+ var STATION_STROKE_ACTIVE = 4;
13740
+ var STATION_STROKE_IDLE = 3;
13741
+ var STATION_DEFAULT = "var(--cdl-tone-accent, #2d6a8f)";
13742
+ function StationNode({ node, active }) {
13743
+ const strokeWidth = active ? STATION_STROKE_ACTIVE : STATION_STROKE_IDLE;
13744
+ const radius = Math.max(0, Math.min(node.w, node.h) / 2 - strokeWidth / 2);
13745
+ const \u5F62 = /* @__PURE__ */ jsx(
13746
+ "circle",
13747
+ {
13748
+ "data-cdl-role": "node-body",
13749
+ "data-cdl-mark": "station",
13750
+ cx: node.cx,
13751
+ cy: node.cy,
13752
+ r: radius,
13753
+ fill: "var(--cdl-node-fill, #ffffff)",
13754
+ stroke: nodeAccent(node, STATION_DEFAULT),
13755
+ strokeWidth
13756
+ }
13757
+ );
13758
+ return renderShapeWithOutsideLabels(\u5F62, node, "middle");
13759
+ }
13239
13760
 
13240
13761
  // src/kinds/label-stack.ts
13241
13762
  function \u540D\u672D\u306E\u6BB5\u3092\u307B\u3069\u304F(\u771F\u306Ey, \u9593\u9694, \u4E0A\u9650, \u4E0B\u9650) {
@@ -13294,8 +13815,8 @@ function \u5024\u3068\u5272\u5408\u306E\u6587\u5B57(\u5024, \u5272\u5408, \u5408
13294
13815
  return \u7D44.\u5024 === null ? \u7D44.\u5272\u5408 : `${\u7D44.\u5024} ${\u7D44.\u5272\u5408}`;
13295
13816
  }
13296
13817
  var \u7A74\u306B\u5BFE\u3059\u308B\u4E0A\u9650 = 0.8;
13297
- function \u4E2D\u592E\u306E\u5B57(\u6BD4\u4F8B\u3057\u305F\u5927\u304D\u3055, \u7A74\u306E\u534A\u5F84, \u6587) {
13298
- const \u5165\u308B\u5927\u304D\u3055 = \u7A74\u306E\u534A\u5F84 * 2 * \u7A74\u306B\u5BFE\u3059\u308B\u4E0A\u9650 / Math.max(textWidth(\u6587, 1), 1e-6);
13818
+ function \u4E2D\u592E\u306E\u5B57(\u6BD4\u4F8B\u3057\u305F\u5927\u304D\u3055, \u7A74\u306E\u534A\u5F84, \u6587, textMetrics = "proportional") {
13819
+ const \u5165\u308B\u5927\u304D\u3055 = \u7A74\u306E\u534A\u5F84 * 2 * \u7A74\u306B\u5BFE\u3059\u308B\u4E0A\u9650 / Math.max(textWidth(\u6587, 1, 0, textMetrics), 1e-6);
13299
13820
  return Math.min(Math.max(\u6BD4\u4F8B\u3057\u305F\u5927\u304D\u3055, \u7E2E\u3093\u3060\u7D75\u306E\u5B57\u306E\u4E0B\u9650), \u5165\u308B\u5927\u304D\u3055);
13300
13821
  }
13301
13822
  function ChartPieNode({
@@ -13303,7 +13824,8 @@ function ChartPieNode({
13303
13824
  active,
13304
13825
  stateValues = {},
13305
13826
  drawing = false,
13306
- progress = 1
13827
+ progress = 1,
13828
+ textMetrics = "proportional"
13307
13829
  }) {
13308
13830
  const instanceId = useId().replace(/[^A-Za-z0-9_-]/g, "");
13309
13831
  const x0 = node.cx - node.w / 2;
@@ -13334,15 +13856,26 @@ function ChartPieNode({
13334
13856
  return `${\u5B9F\u5024\u8868\u8A18(d.value)}%` === \u5272\u5408\u306E\u6587\u5B57[i] ? \u540D : `${\u540D} ${\u5B9F\u5024\u8868\u8A18(d.value)}`;
13335
13857
  });
13336
13858
  if (\u5F62 !== "ring") {
13337
- const \u5171\u901A = { node, active, data, \u5272\u5408: \u4ECA\u306E\u5272\u5408, x0, y0, drawing, progress, instanceId };
13859
+ const \u5171\u901A = {
13860
+ node,
13861
+ active,
13862
+ data,
13863
+ \u5272\u5408: \u4ECA\u306E\u5272\u5408,
13864
+ x0,
13865
+ y0,
13866
+ drawing,
13867
+ progress,
13868
+ instanceId,
13869
+ textMetrics
13870
+ };
13338
13871
  return \u5F62 === "arcs" ? \u5F27\u306E\u5F62(\u5171\u901A) : \u8868\u306E\u5F62(\u5171\u901A);
13339
13872
  }
13340
13873
  const \u540D\u672D\u5E45 = Math.max(
13341
13874
  0,
13342
13875
  ...data.map(
13343
13876
  (_d, i) => Math.max(
13344
- textWidth(\u5272\u5408\u306E\u6587\u5B57[i] ?? "", \u5272\u5408\u306E\u7D1A),
13345
- textWidth(\u540D\u524D\u306E\u6587\u5B57[i] ?? "", \u540D\u524D\u306E\u7D1A)
13877
+ textWidth(\u5272\u5408\u306E\u6587\u5B57[i] ?? "", \u5272\u5408\u306E\u7D1A, 0, textMetrics),
13878
+ textWidth(\u540D\u524D\u306E\u6587\u5B57[i] ?? "", \u540D\u524D\u306E\u7D1A, 0, textMetrics)
13346
13879
  )
13347
13880
  )
13348
13881
  );
@@ -13357,8 +13890,8 @@ function ChartPieNode({
13357
13890
  const \u524D\u306Eslices = \u524D\u3042\u308A ? \u8F2A\u3092\u7D44\u3080(data, cx, cy, \u524D\u306E\u5916\u534A\u5F84, \u524D\u306E\u5185\u534A\u5F84, \u524D\u306E\u5272\u5408) : [];
13358
13891
  const \u7A74 = \u524D\u3042\u308A ? \u524D\u306E\u5185\u534A\u5F84 : \u5916\u306E\u5185\u534A\u5F84;
13359
13892
  const \u5408\u8A08\u306E\u6587 = \u5B9F\u5024\u8868\u8A18(Math.round(\u524D\u3042\u308A ? \u4ECA\u306E\u5408\u8A08 : total));
13360
- const \u5408\u8A08\u306E\u5B57 = \u4E2D\u592E\u306E\u5B57(Math.round(radius * 0.26), \u7A74, \u5408\u8A08\u306E\u6587);
13361
- const \u898B\u51FA\u3057\u306E\u5B572 = \u4E2D\u592E\u306E\u5B57(Math.round(radius * 0.12), \u7A74, "\u5408\u8A08");
13893
+ const \u5408\u8A08\u306E\u5B57 = \u4E2D\u592E\u306E\u5B57(Math.round(radius * 0.26), \u7A74, \u5408\u8A08\u306E\u6587, textMetrics);
13894
+ const \u898B\u51FA\u3057\u306E\u5B572 = \u4E2D\u592E\u306E\u5B57(Math.round(radius * 0.12), \u7A74, "\u5408\u8A08", textMetrics);
13362
13895
  const \u5408\u8A08\u306E\u4E0B = Math.max(Math.round(radius * 0.2), \u5408\u8A08\u306E\u5B57 * 0.25 + \u898B\u51FA\u3057\u306E\u5B572 * 0.8);
13363
13896
  const slices = \u8F2A\u3092\u7D44\u3080(data, cx, cy, radius, \u5916\u306E\u5185\u534A\u5F84, \u4ECA\u306E\u5272\u5408);
13364
13897
  const \u958B\u304D = \u9032\u307F\u3092\u7573\u3080(drawing, progress);
@@ -13541,14 +14074,24 @@ function \u67A0(node, active) {
13541
14074
  }
13542
14075
  );
13543
14076
  }
13544
- function \u5F27\u306E\u5F62({ node, active, data, \u5272\u5408, x0, y0, drawing, progress }) {
14077
+ function \u5F27\u306E\u5F62({
14078
+ node,
14079
+ active,
14080
+ data,
14081
+ \u5272\u5408,
14082
+ x0,
14083
+ y0,
14084
+ drawing,
14085
+ progress,
14086
+ textMetrics
14087
+ }) {
13545
14088
  const PAD = 20;
13546
14089
  const \u540D\u524D\u306E\u7D1A = 14;
13547
14090
  const \u5272\u5408\u306E\u7D1A = 24;
13548
14091
  const \u5370\u304B\u3089\u540D\u524D\u307E\u30672 = 18;
13549
14092
  const \u540D\u524D\u304B\u3089\u5272\u5408\u307E\u3067 = 24;
13550
14093
  const \u5272\u5408\u306E\u6587\u5B57 = \u5272\u5408.map(\u5272\u5408\u8868\u8A18);
13551
- const \u4E00\u89A7\u5E45 = 10 + \u5370\u304B\u3089\u540D\u524D\u307E\u30672 + Math.max(0, ...data.map((d) => textWidth(d.label ?? "", \u540D\u524D\u306E\u7D1A))) + \u540D\u524D\u304B\u3089\u5272\u5408\u307E\u3067 + Math.max(0, ...\u5272\u5408\u306E\u6587\u5B57.map((t) => textWidth(t, \u5272\u5408\u306E\u7D1A)));
14094
+ const \u4E00\u89A7\u5E45 = 10 + \u5370\u304B\u3089\u540D\u524D\u307E\u30672 + Math.max(0, ...data.map((d) => textWidth(d.label ?? "", \u540D\u524D\u306E\u7D1A, 0, textMetrics))) + \u540D\u524D\u304B\u3089\u5272\u5408\u307E\u3067 + Math.max(0, ...\u5272\u5408\u306E\u6587\u5B57.map((t) => textWidth(t, \u5272\u5408\u306E\u7D1A, 0, textMetrics)));
13552
14095
  const \u7E26\u304B\u3089 = (node.h - PAD * 2) / 2;
13553
14096
  const \u6A2A\u304B\u3089 = (node.w - PAD * 2 - \u4E00\u89A7\u5E45 - 28) / 2;
13554
14097
  const R = Math.max(24, Math.min(\u7E26\u304B\u3089, \u6A2A\u304B\u3089));
@@ -13634,7 +14177,18 @@ function \u5F27\u306E\u5F62({ node, active, data, \u5272\u5408, x0, y0, drawing,
13634
14177
  })
13635
14178
  ] });
13636
14179
  }
13637
- function \u8868\u306E\u5F62({ node, active, data, \u5272\u5408, x0, y0, drawing, progress, instanceId }) {
14180
+ function \u8868\u306E\u5F62({
14181
+ node,
14182
+ active,
14183
+ data,
14184
+ \u5272\u5408,
14185
+ x0,
14186
+ y0,
14187
+ drawing,
14188
+ progress,
14189
+ instanceId,
14190
+ textMetrics
14191
+ }) {
13638
14192
  const PAD = 20;
13639
14193
  const \u898B\u51FA\u3057\u306E\u7D1A = 11;
13640
14194
  const \u540D\u524D\u306E\u7D1A = 15;
@@ -13643,9 +14197,18 @@ function \u8868\u306E\u5F62({ node, active, data, \u5272\u5408, x0, y0, drawing,
13643
14197
  const \u5370\u304B\u3089\u540D\u524D\u307E\u30672 = 18;
13644
14198
  const \u5272\u5408\u306E\u6587\u5B57 = \u5272\u5408.map(\u5272\u5408\u8868\u8A18);
13645
14199
  const \u5B9F\u6570\u306E\u6587\u5B57 = data.map((d) => \u5B9F\u5024\u8868\u8A18(d.value));
13646
- const \u540D\u524D\u5E45 = Math.max(0, ...data.map((d) => textWidth(d.label ?? "", \u540D\u524D\u306E\u7D1A)));
13647
- const \u5272\u5408\u5E45 = Math.max(textWidth("\u5272\u5408", \u898B\u51FA\u3057\u306E\u7D1A), ...\u5272\u5408\u306E\u6587\u5B57.map((t) => textWidth(t, \u5272\u5408\u306E\u7D1A)));
13648
- const \u5B9F\u6570\u5E45 = Math.max(textWidth("\u5024", \u898B\u51FA\u3057\u306E\u7D1A), ...\u5B9F\u6570\u306E\u6587\u5B57.map((t) => textWidth(t, \u5B9F\u6570\u306E\u7D1A)));
14200
+ const \u540D\u524D\u5E45 = Math.max(
14201
+ 0,
14202
+ ...data.map((d) => textWidth(d.label ?? "", \u540D\u524D\u306E\u7D1A, 0, textMetrics))
14203
+ );
14204
+ const \u5272\u5408\u5E45 = Math.max(
14205
+ textWidth("\u5272\u5408", \u898B\u51FA\u3057\u306E\u7D1A, 0, textMetrics),
14206
+ ...\u5272\u5408\u306E\u6587\u5B57.map((t) => textWidth(t, \u5272\u5408\u306E\u7D1A, 0, textMetrics))
14207
+ );
14208
+ const \u5B9F\u6570\u5E45 = Math.max(
14209
+ textWidth("\u5024", \u898B\u51FA\u3057\u306E\u7D1A, 0, textMetrics),
14210
+ ...\u5B9F\u6570\u306E\u6587\u5B57.map((t) => textWidth(t, \u5B9F\u6570\u306E\u7D1A, 0, textMetrics))
14211
+ );
13649
14212
  const \u8868\u5E45 = 10 + \u5370\u304B\u3089\u540D\u524D\u307E\u30672 + \u540D\u524D\u5E45 + 28 + \u5272\u5408\u5E45 + 24 + \u5B9F\u6570\u5E45;
13650
14213
  const \u7E26\u304B\u3089 = (node.h - PAD * 2) / 2;
13651
14214
  const \u6A2A\u304B\u3089 = (node.w - PAD * 2 - \u8868\u5E45 - 28) / 2;
@@ -13654,8 +14217,8 @@ function \u8868\u306E\u5F62({ node, active, data, \u5272\u5408, x0, y0, drawing,
13654
14217
  const cx = PAD + R;
13655
14218
  const cy = node.h / 2;
13656
14219
  const \u5408\u8A08\u306E\u6587 = \u5B9F\u5024\u8868\u8A18(Math.round(data.reduce((acc, d) => acc + d.value, 0)));
13657
- const \u5408\u8A08\u306E\u5B57 = \u4E2D\u592E\u306E\u5B57(Math.round(R * 0.26), \u5185\u534A\u5F84, \u5408\u8A08\u306E\u6587);
13658
- const \u898B\u51FA\u3057\u306E\u5B572 = \u4E2D\u592E\u306E\u5B57(Math.round(R * 0.12), \u5185\u534A\u5F84, "\u5408\u8A08");
14220
+ const \u5408\u8A08\u306E\u5B57 = \u4E2D\u592E\u306E\u5B57(Math.round(R * 0.26), \u5185\u534A\u5F84, \u5408\u8A08\u306E\u6587, textMetrics);
14221
+ const \u898B\u51FA\u3057\u306E\u5B572 = \u4E2D\u592E\u306E\u5B57(Math.round(R * 0.12), \u5185\u534A\u5F84, "\u5408\u8A08", textMetrics);
13659
14222
  const \u5408\u8A08\u306E\u4E0B = Math.max(Math.round(R * 0.2), \u5408\u8A08\u306E\u5B57 * 0.25 + \u898B\u51FA\u3057\u306E\u5B572 * 0.8);
13660
14223
  const \u8868\u5DE6 = node.w - PAD - \u8868\u5E45;
13661
14224
  const \u53F3\u7AEF = node.w - PAD;
@@ -13786,7 +14349,8 @@ function ChartGaugeNode({
13786
14349
  active,
13787
14350
  stateValues = {},
13788
14351
  drawing = false,
13789
- progress = 1
14352
+ progress = 1,
14353
+ textMetrics = "proportional"
13790
14354
  }) {
13791
14355
  const x0 = node.cx - node.w / 2;
13792
14356
  const y0 = node.cy - node.h / 2;
@@ -13805,7 +14369,10 @@ function ChartGaugeNode({
13805
14369
  const \u533A\u753B\u306E\u9593 = 12;
13806
14370
  const \u6570\u5024\u306E\u884C = (d) => \u5024\u3068\u5272\u5408\u306E\u6587\u5B57(\u5B9F\u5024\u8868\u8A18(d.value), \u5272\u5408\u8868\u8A18(d.value / total), total);
13807
14371
  const \u5272\u308A\u4ED8\u3051\u308B = (\u4EF6\u305F\u3061) => {
13808
- const \u5E45 = Math.max(\u5370\u306E\u5E452, ...\u4EF6\u305F\u3061.map((d) => textWidth(\u6570\u5024\u306E\u884C(d), \u6570\u5024\u306E\u7D1A))) + \u533A\u753B\u306E\u9593;
14372
+ const \u5E45 = Math.max(
14373
+ \u5370\u306E\u5E452,
14374
+ ...\u4EF6\u305F\u3061.map((d) => textWidth(\u6570\u5024\u306E\u884C(d), \u6570\u5024\u306E\u7D1A, 0, textMetrics))
14375
+ ) + \u533A\u753B\u306E\u9593;
13809
14376
  const \u884C\u306E\u4EF6\u65702 = Math.min(
13810
14377
  Math.max(1, Math.floor(\u4F7F\u3048\u308B\u5E452 / Math.max(\u5E45, 1))),
13811
14378
  Math.max(\u4EF6\u305F\u3061.length, 1)
@@ -13880,7 +14447,7 @@ function ChartGaugeNode({
13880
14447
  return { d, frac, path: \u6247\u306E\u9053(a0, a1, \u524D\u306E\u5185\u534A\u5F84, \u524D\u306E\u5916\u534A\u5F84) };
13881
14448
  });
13882
14449
  const \u5408\u8A08\u306E\u6587\u5B57 = \u5B9F\u5024\u8868\u8A18(Math.round(total));
13883
- const \u5358\u4F4D\u5E45 = Math.max(textWidth(\u5408\u8A08\u306E\u6587\u5B57, 100), 1) / 100;
14450
+ const \u5358\u4F4D\u5E45 = Math.max(textWidth(\u5408\u8A08\u306E\u6587\u5B57, 100, 0, textMetrics), 1) / 100;
13884
14451
  const \u7D1A\u306E\u5019\u88DC = Math.min(
13885
14452
  // 横 = 字の上の角が内側の円に入る大きさ
13886
14453
  \u5185\u534A\u5F84 / Math.sqrt((\u5358\u4F4D\u5E45 / 2) ** 2 + 1.25 ** 2),
@@ -13973,7 +14540,7 @@ function ChartGaugeNode({
13973
14540
  const y = \u5185\u8A33\u306Ey + \u6BB5\u306E\u9AD8\u3055 * \u6BB5;
13974
14541
  const \u53CE\u307E\u308B\u5E45 = \u5185\u8A33\u306E\u5E45 - \u533A\u753B\u306E\u9593;
13975
14542
  const \u6570\u306E\u884C = \u5185\u8A33\u306E\u6570\u5024[idx] ?? "";
13976
- const \u5207\u3063\u305F\u6570\u306E\u884C = \u5207\u308A\u8A70\u3081\u308B(\u6570\u306E\u884C, \u53CE\u307E\u308B\u5E45, \u6570\u5024\u306E\u7D1A);
14543
+ const \u5207\u3063\u305F\u6570\u306E\u884C = \u5207\u308A\u8A70\u3081\u308B(\u6570\u306E\u884C, \u53CE\u307E\u308B\u5E45, \u6570\u5024\u306E\u7D1A, textMetrics);
13977
14544
  return /* @__PURE__ */ jsxs("g", { "data-cdl-role": "chart-gauge-item", children: [
13978
14545
  /* @__PURE__ */ jsx(
13979
14546
  "rect",
@@ -13994,7 +14561,7 @@ function ChartGaugeNode({
13994
14561
  fontSize: \u540D\u524D\u306E\u7D1A,
13995
14562
  fontWeight: 700,
13996
14563
  fill: "var(--cdl-text, #1a1f2a)",
13997
- children: \u5207\u308A\u8A70\u3081\u308B(d.label ?? "", \u53CE\u307E\u308B\u5E45, \u540D\u524D\u306E\u7D1A)
14564
+ children: \u5207\u308A\u8A70\u3081\u308B(d.label ?? "", \u53CE\u307E\u308B\u5E45, \u540D\u524D\u306E\u7D1A, textMetrics)
13998
14565
  }
13999
14566
  ),
14000
14567
  /* @__PURE__ */ jsx("text", { x, y: y + 46, fontSize: \u6570\u5024\u306E\u7D1A, fill: "var(--cdl-text-dim, #5a6270)", children: \u5207\u3063\u305F\u6570\u306E\u884C === \u6570\u306E\u884C ? /* @__PURE__ */ jsx(
@@ -14012,12 +14579,12 @@ function ChartGaugeNode({
14012
14579
  function \u6975(cx, cy, r, a) {
14013
14580
  return { x: cx + r * Math.cos(a), y: cy + r * Math.sin(a) };
14014
14581
  }
14015
- function \u5207\u308A\u8A70\u3081\u308B(s, \u4E0A\u9650, \u7D1A) {
14016
- if (\u4E0A\u9650 <= 0 || textWidth(s, \u7D1A) <= \u4E0A\u9650) return s;
14017
- const \u8A18\u53F7\u5E45 = textWidth("\u2026", \u7D1A);
14582
+ function \u5207\u308A\u8A70\u3081\u308B(s, \u4E0A\u9650, \u7D1A, textMetrics = "proportional") {
14583
+ if (\u4E0A\u9650 <= 0 || textWidth(s, \u7D1A, 0, textMetrics) <= \u4E0A\u9650) return s;
14584
+ const \u8A18\u53F7\u5E45 = textWidth("\u2026", \u7D1A, 0, textMetrics);
14018
14585
  let out = "";
14019
14586
  for (const c of s) {
14020
- if (textWidth(out + c, \u7D1A) + \u8A18\u53F7\u5E45 > \u4E0A\u9650) break;
14587
+ if (textWidth(out + c, \u7D1A, 0, textMetrics) + \u8A18\u53F7\u5E45 > \u4E0A\u9650) break;
14021
14588
  out += c;
14022
14589
  }
14023
14590
  return `${out}\u2026`;
@@ -14031,7 +14598,8 @@ function ChartRadialNode({
14031
14598
  active,
14032
14599
  stateValues = {},
14033
14600
  drawing = false,
14034
- progress = 1
14601
+ progress = 1,
14602
+ textMetrics = "proportional"
14035
14603
  }) {
14036
14604
  const x0 = node.cx - node.w / 2;
14037
14605
  const y0 = node.cy - node.h / 2;
@@ -14049,7 +14617,10 @@ function ChartRadialNode({
14049
14617
  const \u4E00\u89A7\u306E\u5E45 = \u5370\u306E\u5E45 + Math.max(
14050
14618
  0,
14051
14619
  ...data.map(
14052
- (d, i) => Math.max(textWidth(d.label ?? "", \u540D\u524D\u306E\u7D1A), textWidth(\u6570\u5024\u306E\u6587\u5B57[i] ?? "", \u6570\u5024\u306E\u7D1A))
14620
+ (d, i) => Math.max(
14621
+ textWidth(d.label ?? "", \u540D\u524D\u306E\u7D1A, 0, textMetrics),
14622
+ textWidth(\u6570\u5024\u306E\u6587\u5B57[i] ?? "", \u6570\u5024\u306E\u7D1A, 0, textMetrics)
14623
+ )
14053
14624
  )
14054
14625
  );
14055
14626
  const \u5F27\u306B\u4F7F\u3048\u308B\u5E45 = node.w - PAD * 2 - \u4E00\u89A7\u306E\u5E45 - \u4E00\u89A7\u3068\u5F27\u306E\u9593;
@@ -14196,7 +14767,8 @@ function arcColor2(tone, idx) {
14196
14767
  function ChartStatNode({
14197
14768
  node,
14198
14769
  active,
14199
- stateValues = {}
14770
+ stateValues = {},
14771
+ textMetrics = "proportional"
14200
14772
  }) {
14201
14773
  const x0 = node.cx - node.w / 2;
14202
14774
  const y0 = node.cy - node.h / 2;
@@ -14225,7 +14797,13 @@ function ChartStatNode({
14225
14797
  const frac = total > 0 ? d.value / total : 0;
14226
14798
  const \u8272 = \u5370\u306E\u8272(d.tone, idx);
14227
14799
  const \u6570\u5024 = \u5B9F\u5024\u8868\u8A18(d.value);
14228
- const \u6570\u5024\u306E\u7D1A = \u53CE\u3081\u308B\u7D1A(\u6570\u5024, \u67A02.w - \u533A\u753B.\u4F59\u767D * 2, \u533A\u753B.\u6570\u5024\u306E\u7D1A, \u533A\u753B.\u540D\u524D\u306E\u7D1A + 1);
14800
+ const \u6570\u5024\u306E\u7D1A = \u53CE\u3081\u308B\u7D1A(
14801
+ \u6570\u5024,
14802
+ \u67A02.w - \u533A\u753B.\u4F59\u767D * 2,
14803
+ \u533A\u753B.\u6570\u5024\u306E\u7D1A,
14804
+ \u533A\u753B.\u540D\u524D\u306E\u7D1A + 1,
14805
+ textMetrics
14806
+ );
14229
14807
  return /* @__PURE__ */ jsxs(
14230
14808
  "g",
14231
14809
  {
@@ -14282,7 +14860,8 @@ function ChartStatNode({
14282
14860
  `\u524D ${\u5B9F\u5024\u8868\u8A18(d.previous)}`,
14283
14861
  \u67A02.w - \u533A\u753B.\u4F59\u767D * 2,
14284
14862
  \u533A\u753B.\u524D\u306E\u7D1A,
14285
- 8
14863
+ 8,
14864
+ textMetrics
14286
14865
  ),
14287
14866
  textAnchor: "middle",
14288
14867
  fill: "var(--cdl-text-dim, #5a6270)",
@@ -14371,9 +14950,9 @@ function \u533A\u753B\u306E\u5272\u4ED8(w, h, \u4EF6\u6570, \u524D\u3092\u51FA\u
14371
14950
  \u67A0: (idx) => ({ x: \u5E45 * idx, y: 0, w: \u5E45, h })
14372
14951
  };
14373
14952
  }
14374
- function \u53CE\u3081\u308B\u7D1A(\u5B572, \u4F7F\u3048\u308B\u5E452, \u521D\u671F, \u4E0B\u9650) {
14953
+ function \u53CE\u3081\u308B\u7D1A(\u5B572, \u4F7F\u3048\u308B\u5E452, \u521D\u671F, \u4E0B\u9650, textMetrics = "proportional") {
14375
14954
  let \u7D1A = \u521D\u671F;
14376
- while (\u7D1A > \u4E0B\u9650 && textWidth(\u5B572, \u7D1A) > \u4F7F\u3048\u308B\u5E452) \u7D1A -= 1;
14955
+ while (\u7D1A > \u4E0B\u9650 && textWidth(\u5B572, \u7D1A, 0, textMetrics) > \u4F7F\u3048\u308B\u5E452) \u7D1A -= 1;
14377
14956
  return \u7D1A;
14378
14957
  }
14379
14958
  function \u5F27\u306E\u90533(cx, cy, r, \u5272\u5408) {
@@ -14408,7 +14987,8 @@ function ChartWaffleNode({
14408
14987
  active,
14409
14988
  stateValues = {},
14410
14989
  drawing = false,
14411
- progress = 1
14990
+ progress = 1,
14991
+ textMetrics = "proportional"
14412
14992
  }) {
14413
14993
  const x0 = node.cx - node.w / 2;
14414
14994
  const y0 = node.cy - node.h / 2;
@@ -14427,7 +15007,10 @@ function ChartWaffleNode({
14427
15007
  const \u4E00\u89A7\u306E\u5E45 = \u5370\u306E\u5E452 + Math.max(
14428
15008
  0,
14429
15009
  ...data.map(
14430
- (d, i) => Math.max(textWidth(d.label ?? "", \u540D\u524D\u306E\u7D1A), textWidth(\u6570\u5024\u306E\u6587\u5B57[i] ?? "", \u6570\u5024\u306E\u7D1A))
15010
+ (d, i) => Math.max(
15011
+ textWidth(d.label ?? "", \u540D\u524D\u306E\u7D1A, 0, textMetrics),
15012
+ textWidth(\u6570\u5024\u306E\u6587\u5B57[i] ?? "", \u6570\u5024\u306E\u7D1A, 0, textMetrics)
15013
+ )
14431
15014
  )
14432
15015
  );
14433
15016
  const \u4F7F\u3048\u308B\u9AD8\u3055 = node.h - PAD * 2;
@@ -14529,7 +15112,8 @@ function ChartStackedBarNode({
14529
15112
  active,
14530
15113
  stateValues = {},
14531
15114
  drawing = false,
14532
- progress = 1
15115
+ progress = 1,
15116
+ textMetrics = "proportional"
14533
15117
  }) {
14534
15118
  const x0 = node.cx - node.w / 2;
14535
15119
  const y0 = node.cy - node.h / 2;
@@ -14539,7 +15123,7 @@ function ChartStackedBarNode({
14539
15123
  const \u540D\u524D\u306E\u7D1A = 13;
14540
15124
  const \u533A\u753B\u306E\u7D1A = 12;
14541
15125
  const \u6642\u70B9\u306E\u7D1A = 13;
14542
- const \u6642\u70B9\u306E\u5E45 = Math.max(0, ...\u5E2F\u305F\u3061.map((b) => textWidth(b.\u540D\u524D, \u6642\u70B9\u306E\u7D1A))) + (\u5E2F\u305F\u3061.length > 1 ? 16 : 0);
15126
+ const \u6642\u70B9\u306E\u5E45 = Math.max(0, ...\u5E2F\u305F\u3061.map((b) => textWidth(b.\u540D\u524D, \u6642\u70B9\u306E\u7D1A, 0, textMetrics))) + (\u5E2F\u305F\u3061.length > 1 ? 16 : 0);
14543
15127
  const \u5E2F\u306E\u5DE6 = PAD + \u6642\u70B9\u306E\u5E45;
14544
15128
  const \u5E2F\u306E\u5E45 = Math.max(40, node.w - \u5E2F\u306E\u5DE6 - PAD);
14545
15129
  const \u5E2F\u306E\u9AD8\u3055 = 44;
@@ -14632,7 +15216,7 @@ function ChartStackedBarNode({
14632
15216
  })()
14633
15217
  ] }, `bar-${\u6BB5}`);
14634
15218
  }),
14635
- \u4E00\u89A7\u306E\u4E26\u3073(data, \u5E2F\u306E\u5DE6, node.w - PAD, \u540D\u524D\u306E\u7D1A).map(({ d, idx, x, \u884C }) => {
15219
+ \u4E00\u89A7\u306E\u4E26\u3073(data, \u5E2F\u306E\u5DE6, node.w - PAD, \u540D\u524D\u306E\u7D1A, textMetrics).map(({ d, idx, x, \u884C }) => {
14636
15220
  const y = \u4E0A\u7AEF + \u5E2F\u305F\u3061.length * (\u5E2F\u306E\u9AD8\u3055 + \u5E2F\u306E\u9593) - \u5E2F\u306E\u9593 + 16 + \u4E00\u89A7\u306E\u9AD8\u3055 / 2 + \u884C * \u4E00\u89A7\u306E\u9AD8\u3055;
14637
15221
  return /* @__PURE__ */ jsxs("g", { "data-cdl-role": "chart-stacked-bar-legend", children: [
14638
15222
  /* @__PURE__ */ jsx("rect", { x, y: y - 5, width: 10, height: 10, rx: 2, fill: \u5370\u306E\u82723(d.tone, idx) }),
@@ -14667,12 +15251,12 @@ function \u5370\u306E\u82723(tone, idx) {
14667
15251
  }
14668
15252
  var \u5370\u304B\u3089\u540D\u524D\u307E\u3067 = 16;
14669
15253
  var \u4EF6\u306E\u9593 = 10;
14670
- function \u4E00\u89A7\u306E\u4E26\u3073(data, \u5DE6, \u53F3\u7AEF, \u7D1A) {
15254
+ function \u4E00\u89A7\u306E\u4E26\u3073(data, \u5DE6, \u53F3\u7AEF, \u7D1A, textMetrics = "proportional") {
14671
15255
  const out = [];
14672
15256
  let x = \u5DE6;
14673
15257
  let \u884C = 0;
14674
15258
  data.forEach((d, idx) => {
14675
- const \u5E45 = \u5370\u304B\u3089\u540D\u524D\u307E\u3067 + textWidth(d.label ?? "", \u7D1A);
15259
+ const \u5E45 = \u5370\u304B\u3089\u540D\u524D\u307E\u3067 + textWidth(d.label ?? "", \u7D1A, 0, textMetrics);
14676
15260
  if (x > \u5DE6 && x + \u5E45 > \u53F3\u7AEF) {
14677
15261
  \u884C += 1;
14678
15262
  x = \u5DE6;
@@ -14688,7 +15272,8 @@ function ChartSlopeNode({
14688
15272
  active,
14689
15273
  stateValues = {},
14690
15274
  drawing = false,
14691
- progress = 1
15275
+ progress = 1,
15276
+ textMetrics = "proportional"
14692
15277
  }) {
14693
15278
  const x0 = node.cx - node.w / 2;
14694
15279
  const y0 = node.cy - node.h / 2;
@@ -14731,16 +15316,22 @@ function ChartSlopeNode({
14731
15316
  const \u53F3\u306E\u5B57 = \u7CFB\u5217\u305F\u3061.map(
14732
15317
  (s) => \u5F62 === "delta" ? \u5897\u6E1B\u8868\u8A18(s.\u524D, s.\u4ECA) : \u5B9F\u5024\u8868\u8A18(s.\u4ECA)
14733
15318
  );
14734
- const \u5DE6\u5024\u5E45 = Math.max(0, ...\u5DE6\u306E\u5B57.map((t) => textWidth(t, \u5024\u306E\u7D1A)));
14735
- const \u53F3\u5024\u5E45 = Math.max(0, ...\u53F3\u306E\u5B57.map((t) => textWidth(t, \u5024\u306E\u7D1A)));
15319
+ const \u5DE6\u5024\u5E45 = Math.max(0, ...\u5DE6\u306E\u5B57.map((t) => textWidth(t, \u5024\u306E\u7D1A, 0, textMetrics)));
15320
+ const \u53F3\u5024\u5E45 = Math.max(0, ...\u53F3\u306E\u5B57.map((t) => textWidth(t, \u5024\u306E\u7D1A, 0, textMetrics)));
14736
15321
  const \u540D\u524D\u306B\u4F7F\u3048\u308B = Math.max(
14737
15322
  0,
14738
15323
  (node.w - PAD * 2 - \u7DDA\u306E\u6700\u5C0F\u5E45 - (\u5DE6\u5024\u5E45 + \u8EF8\u304B\u3089\u5024\u307E\u3067 + \u5024\u304B\u3089\u540D\u524D\u307E\u3067) - (\u53F3\u5024\u5E45 + \u8EF8\u304B\u3089\u5024\u307E\u3067 + \u5024\u304B\u3089\u540D\u524D\u307E\u3067)) / 2
14739
15324
  );
14740
- const \u540D\u524D\u306E\u7D1A = \u53CE\u3081\u308B\u7D1A2(\u7CFB\u5217\u305F\u3061.map((s) => s.\u540D\u524D), \u540D\u524D\u306B\u4F7F\u3048\u308B, \u540D\u524D\u306E\u4E0A\u9650\u7D1A, \u540D\u524D\u306E\u4E0B\u9650\u7D1A);
15325
+ const \u540D\u524D\u306E\u7D1A = \u53CE\u3081\u308B\u7D1A2(
15326
+ \u7CFB\u5217\u305F\u3061.map((s) => s.\u540D\u524D),
15327
+ \u540D\u524D\u306B\u4F7F\u3048\u308B,
15328
+ \u540D\u524D\u306E\u4E0A\u9650\u7D1A,
15329
+ \u540D\u524D\u306E\u4E0B\u9650\u7D1A,
15330
+ textMetrics
15331
+ );
14741
15332
  const \u540D\u524D\u5E45 = Math.min(
14742
15333
  \u540D\u524D\u306B\u4F7F\u3048\u308B,
14743
- Math.max(0, ...\u7CFB\u5217\u305F\u3061.map((s) => textWidth(s.\u540D\u524D, \u540D\u524D\u306E\u7D1A)))
15334
+ Math.max(0, ...\u7CFB\u5217\u305F\u3061.map((s) => textWidth(s.\u540D\u524D, \u540D\u524D\u306E\u7D1A, 0, textMetrics)))
14744
15335
  );
14745
15336
  const \u5DE6\u306E\u4F59\u767D = \u540D\u524D\u5E45 + \u5024\u304B\u3089\u540D\u524D\u307E\u3067 + \u5DE6\u5024\u5E45 + \u8EF8\u304B\u3089\u5024\u307E\u3067;
14746
15337
  const \u53F3\u306E\u4F59\u767D = \u8EF8\u304B\u3089\u5024\u307E\u3067 + \u53F3\u5024\u5E45 + \u5024\u304B\u3089\u540D\u524D\u307E\u3067 + \u540D\u524D\u5E45;
@@ -14926,10 +15517,12 @@ function \u5370\u306E\u82724(tone, idx) {
14926
15517
  if (tone) return TONE[tone];
14927
15518
  return chartSeriesColor(idx);
14928
15519
  }
14929
- function \u53CE\u3081\u308B\u7D1A2(\u540D\u524D\u305F\u3061, \u5E45, \u4E0A\u9650, \u4E0B\u9650) {
15520
+ function \u53CE\u3081\u308B\u7D1A2(\u540D\u524D\u305F\u3061, \u5E45, \u4E0A\u9650, \u4E0B\u9650, textMetrics = "proportional") {
14930
15521
  if (\u540D\u524D\u305F\u3061.length === 0) return \u4E0A\u9650;
14931
15522
  let \u7D1A = \u4E0A\u9650;
14932
- while (\u7D1A > \u4E0B\u9650 && Math.max(...\u540D\u524D\u305F\u3061.map((n) => textWidth(n, \u7D1A))) > \u5E45) \u7D1A -= 1;
15523
+ while (\u7D1A > \u4E0B\u9650 && Math.max(...\u540D\u524D\u305F\u3061.map((n) => textWidth(n, \u7D1A, 0, textMetrics))) > \u5E45) {
15524
+ \u7D1A -= 1;
15525
+ }
14933
15526
  return \u7D1A;
14934
15527
  }
14935
15528
  function \u5C0F\u6570\u306E\u6841(n) {
@@ -14977,6 +15570,7 @@ function ChartBarNode({
14977
15570
  return { y: yAt(v), value: v };
14978
15571
  });
14979
15572
  const \u6FC3\u3055 = (v) => vMax > 0 ? v >= vMax ? 1 : 0.45 : 0.9;
15573
+ const \u4E3B\u5F79\u306E\u68D2\u304B = (v) => vMax > 0 && v >= vMax;
14980
15574
  const \u89D2\u4E38 = Math.min(barW * 0.06, 8);
14981
15575
  const \u4F38\u3073 = \u9032\u307F\u3092\u7573\u3080(drawing, progress);
14982
15576
  const \u6A2A\u8EF8\u306Ey = PAD_TOP2 + canvasH;
@@ -15043,6 +15637,7 @@ function ChartBarNode({
15043
15637
  {
15044
15638
  "data-cdl-role": "chart-bar",
15045
15639
  "data-cdl-unresolved": d.unresolved ? "true" : void 0,
15640
+ "data-cdl-emphasis": \u4E3B\u5F79\u306E\u68D2\u304B(d.value) ? "primary" : void 0,
15046
15641
  x: bx,
15047
15642
  y: by,
15048
15643
  width: barW,
@@ -15389,7 +15984,8 @@ function FunnelNode({
15389
15984
  active,
15390
15985
  stateValues = {},
15391
15986
  drawing = false,
15392
- progress = 1
15987
+ progress = 1,
15988
+ textMetrics = "proportional"
15393
15989
  }) {
15394
15990
  const x0 = node.cx - node.w / 2;
15395
15991
  const y0 = node.cy - node.h / 2;
@@ -15438,7 +16034,11 @@ function FunnelNode({
15438
16034
  const \u540D\u524D\u306E\u5B9F\u5B57 = \u540D\u524D\u306E\u5B57 * \u7E26\u500D;
15439
16035
  const \u88DC\u8DB3\u306E\u67A0\u5B57 = \u88DC\u8DB3\u306E\u5B57 * \u7E26\u500D;
15440
16036
  const \u53CE\u307E\u308B\u5E45 = Math.max(0, bottomW - 16);
15441
- const \u88DC\u8DB3\u306E\u5B9F\u5B57 = \u88DC\u8DB3\u306E\u67A0\u5B57 * \u53CE\u3081\u308B\u500D\u7387(\u88DC\u8DB3, { fontSize: \u88DC\u8DB3\u306E\u67A0\u5B57, fontWeight: 500 }, \u53CE\u307E\u308B\u5E45);
16037
+ const \u88DC\u8DB3\u306E\u5B9F\u5B57 = \u88DC\u8DB3\u306E\u67A0\u5B57 * \u53CE\u3081\u308B\u500D\u7387(
16038
+ \u88DC\u8DB3,
16039
+ { fontSize: \u88DC\u8DB3\u306E\u67A0\u5B57, fontWeight: 500, textMetrics },
16040
+ \u53CE\u307E\u308B\u5E45
16041
+ );
15442
16042
  const \u584A\u306E\u4E0A = y + stageH / 2 - (\u540D\u524D\u306E\u5B9F\u5B57 * 1.2 + \u88DC\u8DB3\u306E\u67A0\u5B57 * 1.25) / 2;
15443
16043
  const \u540D\u524D\u306Ey = \u88DC\u8DB3\u3042\u308A ? \u584A\u306E\u4E0A + \u540D\u524D\u306E\u5B9F\u5B57 * 0.95 : y + stageH / 2 + 5;
15444
16044
  const \u88DC\u8DB3\u306Ey = \u584A\u306E\u4E0A + \u540D\u524D\u306E\u5B9F\u5B57 * 1.2 + \u88DC\u8DB3\u306E\u67A0\u5B57 * 0.95;
@@ -15541,7 +16141,8 @@ function \u7573\u3093\u3060\u6587(\u4EF6\u6570) {
15541
16141
  function QuadrantNode({
15542
16142
  node,
15543
16143
  active,
15544
- stateValues = {}
16144
+ stateValues = {},
16145
+ textMetrics = "proportional"
15545
16146
  }) {
15546
16147
  const x0 = node.cx - node.w / 2;
15547
16148
  const y0 = node.cy - node.h / 2;
@@ -15560,7 +16161,10 @@ function QuadrantNode({
15560
16161
  const SUB_FONT = 10;
15561
16162
  const axisLabelPad = (text) => Math.max(
15562
16163
  PAD_MIN,
15563
- measureTextWidth(`\u2190 ${text}`, { fontSize: AXIS_LABEL_FONT}) + 12
16164
+ measureTextWidth(`\u2190 ${text}`, {
16165
+ fontSize: AXIS_LABEL_FONT,
16166
+ textMetrics
16167
+ }) + 12
15564
16168
  );
15565
16169
  const padBudget = Math.max(0, node.w * 0.5 - PAD_MIN * 2);
15566
16170
  const wantLeft = axisLabelPad(data.xAxis.left) - PAD_MIN;
@@ -15814,7 +16418,11 @@ function QuadrantNode({
15814
16418
  ITEM_MIN_W,
15815
16419
  Math.max(
15816
16420
  ...\u884C\u30892.map(
15817
- (r) => measureTextWidth(r.text, { fontSize: r.size, fontWeight: r.weight })
16421
+ (r) => measureTextWidth(r.text, {
16422
+ fontSize: r.size,
16423
+ fontWeight: r.weight,
16424
+ textMetrics
16425
+ })
15818
16426
  )
15819
16427
  ) + ITEM_PAD_X * 2
15820
16428
  )
@@ -15840,7 +16448,7 @@ function QuadrantNode({
15840
16448
  const \u88DC\u8DB3 = (it.subtitle ?? "").trim();
15841
16449
  const \u88DC\u8DB3\u306E\u5B57 = SUB_FONT * \u53CE\u3081\u308B\u500D\u7387(
15842
16450
  \u88DC\u8DB3,
15843
- { fontSize: SUB_FONT, fontWeight: 500 },
16451
+ { fontSize: SUB_FONT, fontWeight: 500, textMetrics },
15844
16452
  Math.max(0, \u5E45 - ITEM_PAD_X * 2)
15845
16453
  );
15846
16454
  return /* @__PURE__ */ jsxs("g", { children: [
@@ -16244,24 +16852,30 @@ var EYEBROW_GAP2 = 8;
16244
16852
  var EYEBROW_TRACKING = 2;
16245
16853
  var SUB_SIZE = 11;
16246
16854
  var SUB_GAP = 4;
16247
- function labelBlock(node, pos, size, band) {
16855
+ function labelBlock(node, pos, size, band, textMetrics = "proportional") {
16248
16856
  const \u4E0A = node.eyebrow ? size + EYEBROW_GAP2 + EYEBROW_SIZE2 * ASCENT2 : size * ASCENT2;
16249
16857
  const \u4E0B = node.subtitle ? size + SUB_GAP + SUB_SIZE * DESCENT2 : size * DESCENT2;
16250
16858
  const \u5E45 = Math.max(
16251
- textWidth(node.title ?? "", size),
16252
- node.eyebrow ? textWidth(node.eyebrow, EYEBROW_SIZE2, EYEBROW_TRACKING) : 0,
16253
- node.subtitle ? textWidth(node.subtitle, SUB_SIZE) : 0
16859
+ textWidth(node.title ?? "", size, 0, textMetrics),
16860
+ node.eyebrow ? textWidth(node.eyebrow, EYEBROW_SIZE2, EYEBROW_TRACKING, textMetrics) : 0,
16861
+ node.subtitle ? textWidth(node.subtitle, SUB_SIZE, 0, textMetrics) : 0
16254
16862
  );
16255
- const \u984C\u5E45 = textWidth(node.title ?? "", size);
16256
- const \u4E0B\u9650 = \u984C\u5E45 >= \u5E45 ? \u5207\u3063\u3066\u53CE\u307E\u308B\u4E0B\u9650(node.title ?? "", size, 0, band.w, textWidth) : 0;
16863
+ const \u984C\u5E45 = textWidth(node.title ?? "", size, 0, textMetrics);
16864
+ const \u6E2C\u308B = (t, s, ls) => textWidth(t, s, ls, textMetrics);
16865
+ const \u4E0B\u9650 = \u984C\u5E45 >= \u5E45 ? \u5207\u3063\u3066\u53CE\u307E\u308B\u4E0B\u9650(node.title ?? "", size, 0, band.w, \u6E2C\u308B) : 0;
16257
16866
  const { k, x, y: baseline } = fitLabel(band, { \u4E0A, \u4E0B, \u5E45 }, pos, \u4E0B\u9650);
16258
16867
  return { k, x, baseline, \u4E0A\u7AEF: baseline - \u4E0A * k, \u4E0B\u7AEF: baseline + \u4E0B * k };
16259
16868
  }
16260
- function commonLabel(node, pos, size, band) {
16261
- const \u584A = labelBlock(node, pos, size, band);
16869
+ function commonLabel(node, pos, size, band, textMetrics = "proportional") {
16870
+ const \u584A = labelBlock(node, pos, size, band, textMetrics);
16262
16871
  const k = \u584A.k;
16263
16872
  const x = \u584A.x;
16264
- const \u5207\u308B = (t, \u5927\u304D\u3055, \u5B57\u9593 = 0) => \u5E2F\u3067\u5207\u308B(t, \u5927\u304D\u3055 * k, band.w, (u, f) => textWidth(u, f, \u5B57\u9593 * k));
16873
+ const \u5207\u308B = (t, \u5927\u304D\u3055, \u5B57\u9593 = 0) => \u5E2F\u3067\u5207\u308B(
16874
+ t,
16875
+ \u5927\u304D\u3055 * k,
16876
+ band.w,
16877
+ (u, f) => textWidth(u, f, \u5B57\u9593 * k, textMetrics)
16878
+ );
16265
16879
  return /* @__PURE__ */ jsxs(Fragment, { children: [
16266
16880
  node.eyebrow && /* @__PURE__ */ jsx(
16267
16881
  "text",
@@ -16312,7 +16926,7 @@ var RULE_GAP_RATIO = 0.1;
16312
16926
  var RULE_PAD_MAX = 20;
16313
16927
  var RULE_PAD_RATIO = 0.14;
16314
16928
  var RULE_SHRINK_RATIO = 0.055;
16315
- function ShapeFileNode({ node, active }) {
16929
+ function ShapeFileNode({ node, active, textMetrics = "proportional" }) {
16316
16930
  const \u5E2F = bodyBand(node, { \u5F71ry: SHADOW_RY });
16317
16931
  const \u7D19h = \u5E2F.h;
16318
16932
  const \u7D19w = Math.min(\u5E2F.w, \u7D19h * 0.72);
@@ -16332,7 +16946,7 @@ function ShapeFileNode({ node, active }) {
16332
16946
  const foldTriangle = `M ${x + \u7D19w - fold} ${y} L ${x + \u7D19w} ${y + fold} L ${x + \u7D19w - fold} ${y + fold} Z`;
16333
16947
  const \u540D\u524D\u5E2F = { x, y, w: \u7D19w, h: \u7D19h };
16334
16948
  const \u540D\u524D\u4F4D\u7F6E = { x: \u5E2F.cx, y: node.cy + node.h * 0.12 };
16335
- const \u540D\u524D = labelBlock(node, \u540D\u524D\u4F4D\u7F6E, 16, \u540D\u524D\u5E2F);
16949
+ const \u540D\u524D = labelBlock(node, \u540D\u524D\u4F4D\u7F6E, 16, \u540D\u524D\u5E2F, textMetrics);
16336
16950
  const \u9593\u9694 = Math.min(RULE_GAP_MAX, \u7D19h * RULE_GAP_RATIO);
16337
16951
  const \u7DDA\u4F59\u767D = Math.min(RULE_PAD_MAX, \u7D19w * RULE_PAD_RATIO);
16338
16952
  const textLines = [0, 1, 2].map((i) => ({ i, ly: y + fold + \u9593\u9694 * (i + 1) })).filter(({ ly }) => ly < \u540D\u524D.\u4E0A\u7AEF);
@@ -16364,12 +16978,12 @@ function ShapeFileNode({ node, active }) {
16364
16978
  i
16365
16979
  );
16366
16980
  }),
16367
- commonLabel(node, \u540D\u524D\u4F4D\u7F6E, 16, \u540D\u524D\u5E2F)
16981
+ commonLabel(node, \u540D\u524D\u4F4D\u7F6E, 16, \u540D\u524D\u5E2F, textMetrics)
16368
16982
  ] });
16369
16983
  }
16370
16984
  var TAB_H_MAX = 22;
16371
16985
  var TAB_H_RATIO = 0.3;
16372
- function ShapeFolderNode({ node, active }) {
16986
+ function ShapeFolderNode({ node, active, textMetrics = "proportional" }) {
16373
16987
  const \u5E2F = bodyBand(node, { \u5F71ry: SHADOW_RY });
16374
16988
  const x = \u5E2F.x;
16375
16989
  const y = \u5E2F.y;
@@ -16390,7 +17004,7 @@ function ShapeFolderNode({ node, active }) {
16390
17004
  const \u5883\u754Cy = y + tabH + Math.min(8, (\u5E2F.h - tabH) * 0.2);
16391
17005
  const \u7AEF = Math.min(6, \u5E2F.w * 0.1);
16392
17006
  const \u540D\u524D\u4F4D\u7F6E = { x: \u5E2F.cx, y: node.cy + 18 };
16393
- const \u540D\u524D = labelBlock(node, \u540D\u524D\u4F4D\u7F6E, 16, \u5E2F);
17007
+ const \u540D\u524D = labelBlock(node, \u540D\u524D\u4F4D\u7F6E, 16, \u5E2F, textMetrics);
16394
17008
  return /* @__PURE__ */ jsxs("g", { children: [
16395
17009
  dropShadow(\u5E2F.cx, \u5E2F.\u5E95, \u5E2F.w * 0.44),
16396
17010
  /* @__PURE__ */ jsx("path", { "data-cdl-role": "node-body", d: bodyPath, ...frame, strokeLinejoin: "round" }),
@@ -16406,13 +17020,13 @@ function ShapeFolderNode({ node, active }) {
16406
17020
  opacity: 0.35
16407
17021
  }
16408
17022
  ),
16409
- commonLabel(node, \u540D\u524D\u4F4D\u7F6E, 16, \u5E2F)
17023
+ commonLabel(node, \u540D\u524D\u4F4D\u7F6E, 16, \u5E2F, textMetrics)
16410
17024
  ] });
16411
17025
  }
16412
17026
  var CLOUD_VB_W = 640;
16413
17027
  var CLOUD_VB_H = 512;
16414
17028
  var CLOUD_W_RATIO = 0.9;
16415
- function ShapeCloudNode({ node, active }) {
17029
+ function ShapeCloudNode({ node, active, textMetrics = "proportional" }) {
16416
17030
  const \u5E2F = bodyBand(node, { \u5F71ry: SHADOW_RY });
16417
17031
  const frame = commonFrame(active);
16418
17032
  const \u7D20\u306E\u500D\u7387 = Math.min(\u5E2F.h / CLOUD_VB_H, \u5E2F.w * CLOUD_W_RATIO / CLOUD_VB_W);
@@ -16435,13 +17049,13 @@ function ShapeCloudNode({ node, active }) {
16435
17049
  strokeLinejoin: "round"
16436
17050
  }
16437
17051
  ) }),
16438
- commonLabel(node, { x: \u5E2F.cx, y: node.cy + node.h * 0.05 }, 16, \u5E2F)
17052
+ commonLabel(node, { x: \u5E2F.cx, y: node.cy + node.h * 0.05 }, 16, \u5E2F, textMetrics)
16439
17053
  ] });
16440
17054
  }
16441
17055
  var CYLINDER_RY_MAX = 18;
16442
17056
  var CYLINDER_RY_RATIO = 0.1;
16443
17057
  var CYLINDER_DISKS = [0.3, 0.55, 0.8];
16444
- function ShapeCylinderNode({ node, active }) {
17058
+ function ShapeCylinderNode({ node, active, textMetrics = "proportional" }) {
16445
17059
  const \u5E2F = bodyBand(node, { \u5F71ry: CYLINDER_SHADOW_RY });
16446
17060
  const x = \u5E2F.x;
16447
17061
  const y = \u5E2F.y;
@@ -16458,7 +17072,7 @@ function ShapeCylinderNode({ node, active }) {
16458
17072
  const \u84CB\u5E95 = y + ry * 2;
16459
17073
  const \u540D\u524D\u4F4D\u7F6E = { x: \u5E2F.cx, y: node.cy + 6 };
16460
17074
  const \u540D\u524D\u5E2F = { x: \u5E2F.x, y: \u84CB\u5E95, w: \u5E2F.w, h: Math.max(0, \u5E2F.\u5E95 - \u84CB\u5E95) };
16461
- const \u540D\u524D = labelBlock(node, \u540D\u524D\u4F4D\u7F6E, 15, \u540D\u524D\u5E2F);
17075
+ const \u540D\u524D = labelBlock(node, \u540D\u524D\u4F4D\u7F6E, 15, \u540D\u524D\u5E2F, textMetrics);
16462
17076
  return /* @__PURE__ */ jsxs("g", { children: [
16463
17077
  dropShadow(\u5E2F.cx, \u5E2F.\u5E95, rx * 0.85, CYLINDER_SHADOW_RY),
16464
17078
  /* @__PURE__ */ jsx("path", { "data-cdl-role": "node-body", d: bodyPath, ...frame, strokeLinejoin: "round" }),
@@ -16482,11 +17096,11 @@ function ShapeCylinderNode({ node, active }) {
16482
17096
  },
16483
17097
  i
16484
17098
  )),
16485
- commonLabel(node, \u540D\u524D\u4F4D\u7F6E, 15, \u540D\u524D\u5E2F)
17099
+ commonLabel(node, \u540D\u524D\u4F4D\u7F6E, 15, \u540D\u524D\u5E2F, textMetrics)
16486
17100
  ] });
16487
17101
  }
16488
17102
  var HEX_DOT_R = 2.5;
16489
- function ShapeHexagonNode({ node, active }) {
17103
+ function ShapeHexagonNode({ node, active, textMetrics = "proportional" }) {
16490
17104
  const \u5E2F = bodyBand(node, { \u5F71ry: SHADOW_RY, \u5916: Math.max(HEX_DOT_R, FRAME_HALF) });
16491
17105
  const cx = \u5E2F.cx;
16492
17106
  const cy = \u5E2F.cy;
@@ -16509,11 +17123,12 @@ function ShapeHexagonNode({ node, active }) {
16509
17123
  node,
16510
17124
  { x: cx, y: node.cy + 6 },
16511
17125
  16,
16512
- { x: \u5E2F.x + cut, y: \u5E2F.y, w: Math.max(0, \u5E2F.w - cut * 2), h: \u5E2F.h }
17126
+ { x: \u5E2F.x + cut, y: \u5E2F.y, w: Math.max(0, \u5E2F.w - cut * 2), h: \u5E2F.h },
17127
+ textMetrics
16513
17128
  )
16514
17129
  ] });
16515
17130
  }
16516
- function ShapeDiamondNode({ node, active }) {
17131
+ function ShapeDiamondNode({ node, active, textMetrics = "proportional" }) {
16517
17132
  const \u5E2F = bodyBand(node, { \u5F71ry: SHADOW_RY });
16518
17133
  const cx = \u5E2F.cx;
16519
17134
  const cy = \u5E2F.cy;
@@ -16554,13 +17169,14 @@ function ShapeDiamondNode({ node, active }) {
16554
17169
  y: cy - \u5E2F.h * innerScale / 4,
16555
17170
  w: \u5E2F.w * innerScale / 2,
16556
17171
  h: \u5E2F.h * innerScale / 2
16557
- }
17172
+ },
17173
+ textMetrics
16558
17174
  )
16559
17175
  ] });
16560
17176
  }
16561
17177
  var STACK_OFFSET_MAX = 12;
16562
17178
  var STACK_OFFSET_RATIO = 0.15;
16563
- function ShapeStackNode({ node, active }) {
17179
+ function ShapeStackNode({ node, active, textMetrics = "proportional" }) {
16564
17180
  const \u5E2F = bodyBand(node, { \u5F71ry: SHADOW_RY });
16565
17181
  const x = \u5E2F.x;
16566
17182
  const y = \u5E2F.y;
@@ -16614,7 +17230,8 @@ function ShapeStackNode({ node, active }) {
16614
17230
  node,
16615
17231
  { x: \u624B\u524Dcx, y: node.cy + \u305A\u308C + 6 },
16616
17232
  15,
16617
- { x, y: y + \u305A\u308C * 2, w: cardW, h: cardH }
17233
+ { x, y: y + \u305A\u308C * 2, w: cardW, h: cardH },
17234
+ textMetrics
16618
17235
  )
16619
17236
  ] });
16620
17237
  }
@@ -16626,16 +17243,22 @@ var PERSON_BODY_LEN = 90;
16626
17243
  var PERSON_SHADOW_DY = 20;
16627
17244
  var PERSON_SHADOW_RY = 4;
16628
17245
  var PERSON_SHADOW_RX = 55;
16629
- function planLabel(node, cx, \u5E45\u4E0A\u9650, plan) {
17246
+ function planLabel(node, cx, \u5E45\u4E0A\u9650, plan, textMetrics = "proportional") {
16630
17247
  const \u5E45 = Math.max(
16631
- textWidth(node.title ?? "", plan.\u540D\u524D.size),
16632
- node.eyebrow && plan.\u80A9\u66F8 ? textWidth(node.eyebrow, plan.\u80A9\u66F8.size, EYEBROW_TRACKING) : 0,
16633
- node.subtitle && plan.\u8AAC\u660E ? textWidth(node.subtitle, plan.\u8AAC\u660E.size) : 0
17248
+ textWidth(node.title ?? "", plan.\u540D\u524D.size, 0, textMetrics),
17249
+ node.eyebrow && plan.\u80A9\u66F8 ? textWidth(node.eyebrow, plan.\u80A9\u66F8.size, EYEBROW_TRACKING, textMetrics) : 0,
17250
+ node.subtitle && plan.\u8AAC\u660E ? textWidth(node.subtitle, plan.\u8AAC\u660E.size, 0, textMetrics) : 0
16634
17251
  );
16635
- const \u984C\u5E45 = textWidth(node.title ?? "", plan.\u540D\u524D.size);
16636
- const \u4E0B\u9650 = \u984C\u5E45 >= \u5E45 ? \u5207\u3063\u3066\u53CE\u307E\u308B\u4E0B\u9650(node.title ?? "", plan.\u540D\u524D.size, 0, \u5E45\u4E0A\u9650, textWidth) : 0;
17252
+ const \u984C\u5E45 = textWidth(node.title ?? "", plan.\u540D\u524D.size, 0, textMetrics);
17253
+ const \u6E2C\u308B = (t, s, ls) => textWidth(t, s, ls, textMetrics);
17254
+ const \u4E0B\u9650 = \u984C\u5E45 >= \u5E45 ? \u5207\u3063\u3066\u53CE\u307E\u308B\u4E0B\u9650(node.title ?? "", plan.\u540D\u524D.size, 0, \u5E45\u4E0A\u9650, \u6E2C\u308B) : 0;
16637
17255
  const k = \u5E45 > 0 && \u5E45\u4E0A\u9650 > 0 ? Math.min(1, Math.max(\u5E45\u4E0A\u9650 / \u5E45, \u4E0B\u9650)) : 1;
16638
- const \u5207\u308B = (t, \u5927\u304D\u3055, \u5B57\u9593 = 0) => \u5E2F\u3067\u5207\u308B(t, \u5927\u304D\u3055 * k, \u5E45\u4E0A\u9650, (u, f) => textWidth(u, f, \u5B57\u9593 * k));
17256
+ const \u5207\u308B = (t, \u5927\u304D\u3055, \u5B57\u9593 = 0) => \u5E2F\u3067\u5207\u308B(
17257
+ t,
17258
+ \u5927\u304D\u3055 * k,
17259
+ \u5E45\u4E0A\u9650,
17260
+ (u, f) => textWidth(u, f, \u5B57\u9593 * k, textMetrics)
17261
+ );
16639
17262
  return /* @__PURE__ */ jsxs(Fragment, { children: [
16640
17263
  node.eyebrow && plan.\u80A9\u66F8 && /* @__PURE__ */ jsx(
16641
17264
  "text",
@@ -16676,7 +17299,7 @@ function planLabel(node, cx, \u5E45\u4E0A\u9650, plan) {
16676
17299
  )
16677
17300
  ] });
16678
17301
  }
16679
- function ShapePersonNode({ node, active }) {
17302
+ function ShapePersonNode({ node, active, textMetrics = "proportional" }) {
16680
17303
  const r = shapeRegion(node);
16681
17304
  const cx = r.cx;
16682
17305
  const strokeColor = active ? "var(--cdl-tone-accent, #2d6a8f)" : "var(--cdl-divider, #d4d4d8)";
@@ -16738,7 +17361,7 @@ function ShapePersonNode({ node, active }) {
16738
17361
  )
16739
17362
  ] })
16740
17363
  ),
16741
- planLabel(node, r.cx, Math.max(0, node.w), r.label)
17364
+ planLabel(node, r.cx, Math.max(0, node.w), r.label, textMetrics)
16742
17365
  ] });
16743
17366
  }
16744
17367
  var commonFrame2 = (active) => ({
@@ -16988,7 +17611,12 @@ function ShapeTerminalNode({ node, active, lang }) {
16988
17611
  )
16989
17612
  ] });
16990
17613
  }
16991
- function ShapeCodeBlockNode({ node, active, lang }) {
17614
+ function ShapeCodeBlockNode({
17615
+ node,
17616
+ active,
17617
+ lang,
17618
+ textMetrics = "proportional"
17619
+ }) {
16992
17620
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
16993
17621
  const frame = commonFrame2(active);
16994
17622
  const \u7DDA = frame.strokeWidth / 2;
@@ -16999,7 +17627,10 @@ function ShapeCodeBlockNode({ node, active, lang }) {
16999
17627
  const lineFont = "ui-monospace, SFMono-Regular, Menlo, monospace";
17000
17628
  const \u672D = \u66F8\u3044\u305F\u5024\u304B\u63A7\u3048(node.subtitle, \u5B57\u5F15("codeBlock.fileName"));
17001
17629
  const \u672D\u306E\u5B57 = 11;
17002
- const \u30BF\u30D6\u5E45 = Math.min(Math.max(100, textWidth(\u672D, \u672D\u306E\u5B57, 0) + 24), Math.max(0, w));
17630
+ const \u30BF\u30D6\u5E45 = Math.min(
17631
+ Math.max(100, textWidth(\u672D, \u672D\u306E\u5B57, 0, textMetrics) + 24),
17632
+ Math.max(0, w)
17633
+ );
17003
17634
  const \u30BF\u30D6\u9AD8 = 24;
17004
17635
  const \u89D2 = 10;
17005
17636
  const \u6E9D = 32;
@@ -17039,7 +17670,7 @@ function ShapeCodeBlockNode({ node, active, lang }) {
17039
17670
  { text: \u672D, size: \u672D\u306E\u5B57, \u5E2F: { \u5E45: \u30BF\u30D6\u5E45, \u9AD8\u3055: \u30BF\u30D6\u9AD8 } },
17040
17671
  { text: "1", size: \u884C\u756A\u53F7\u306E\u5B57, \u5E2F: { \u5E45: \u6E9D - \u6301\u3061\u4E0A\u3052, \u9AD8\u3055: \u884C\u9593 } }
17041
17672
  ];
17042
- const \u500D\u8FD4\u3057 = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D, \u6253\u3061\u6D88\u3059\u5B57\u3089);
17673
+ const \u500D\u8FD4\u3057 = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D, \u6253\u3061\u6D88\u3059\u5B57\u3089, textMetrics);
17043
17674
  const tabW = \u30BF\u30D6\u5E45 * \u500D;
17044
17675
  const tabH = \u30BF\u30D6\u9AD8 * \u500D;
17045
17676
  const \u4E38 = \u89D2 * \u500D;
@@ -17078,7 +17709,7 @@ function ShapeCodeBlockNode({ node, active, lang }) {
17078
17709
  "data-cdl-counter-scaled": "1",
17079
17710
  x: x + tabW / 2,
17080
17711
  y: y + tabH / 2 + 4 * \u500D,
17081
- fontSize: \u672D\u306E\u5B57 * \u500D * \u500D\u8FD4\u3057 * \u5E45\u306E\u500D\u7387(\u672D, \u672D\u306E\u5B57 * \u500D * \u500D\u8FD4\u3057, 0, tabW),
17712
+ fontSize: \u672D\u306E\u5B57 * \u500D * \u500D\u8FD4\u3057 * \u5E45\u306E\u500D\u7387(\u672D, \u672D\u306E\u5B57 * \u500D * \u500D\u8FD4\u3057, 0, tabW, textMetrics),
17082
17713
  fontFamily: lineFont,
17083
17714
  textAnchor: "middle",
17084
17715
  fill: "#e6edf3",
@@ -17160,7 +17791,12 @@ function ShapeCodeBlockNode({ node, active, lang }) {
17160
17791
  )
17161
17792
  ] });
17162
17793
  }
17163
- function ShapeKanbanCardNode({ node, active, lang }) {
17794
+ function ShapeKanbanCardNode({
17795
+ node,
17796
+ active,
17797
+ lang,
17798
+ textMetrics = "proportional"
17799
+ }) {
17164
17800
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
17165
17801
  const frame = commonFrame2(active);
17166
17802
  const \u7DDA = frame.strokeWidth / 2;
@@ -17214,7 +17850,7 @@ function ShapeKanbanCardNode({ node, active, lang }) {
17214
17850
  );
17215
17851
  const \u8AAC\u660E = \u66F8\u3044\u305F\u5024\u304B\u63A7\u3048(node.subtitle, \u5B57\u5F15("kanbanCard.task"));
17216
17852
  const \u72B6\u614B = \u66F8\u3044\u305F\u5024\u304B\u63A7\u3048(node.eyebrow, \u5B57\u5F15("kanbanCard.status"));
17217
- const \u72B6\u614B\u306E\u500D\u7387 = \u5E45\u306E\u500D\u7387(\u72B6\u614B, PILL\u5B57, PILL\u5B57\u9593, PILL\u5B57\u5E45);
17853
+ const \u72B6\u614B\u306E\u500D\u7387 = \u5E45\u306E\u500D\u7387(\u72B6\u614B, PILL\u5B57, PILL\u5B57\u9593, PILL\u5B57\u5E45, textMetrics);
17218
17854
  const \u8AAC\u660E\u306E\u5B57 = \u540D\u524D.size * \u8AAC\u660E\u5B57\u6BD4;
17219
17855
  const \u4F7F\u3048\u308B\u5E452 = Math.max(0, w - \u5DE6\u53F3\u4F59\u767D * \u500D * 2);
17220
17856
  return /* @__PURE__ */ jsxs("g", { children: [
@@ -17301,7 +17937,7 @@ function ShapeKanbanCardNode({ node, active, lang }) {
17301
17937
  {
17302
17938
  x: x + w / 2,
17303
17939
  y: \u540D\u524D.y + \u540D\u524D.size * \u8AAC\u660E\u57FA\u6E96\u6BD4,
17304
- fontSize: \u8AAC\u660E\u306E\u5B57 * \u5E45\u306E\u500D\u7387(\u8AAC\u660E, \u8AAC\u660E\u306E\u5B57, 0, \u4F7F\u3048\u308B\u5E452),
17940
+ fontSize: \u8AAC\u660E\u306E\u5B57 * \u5E45\u306E\u500D\u7387(\u8AAC\u660E, \u8AAC\u660E\u306E\u5B57, 0, \u4F7F\u3048\u308B\u5E452, textMetrics),
17305
17941
  textAnchor: "middle",
17306
17942
  fill: "var(--cdl-text-dim, #5a6270)",
17307
17943
  children: \u8AAC\u660E
@@ -17592,18 +18228,33 @@ var externalLabel = (node, cx, bottomY) => /* @__PURE__ */ jsxs(Fragment, { chil
17592
18228
  )
17593
18229
  ] });
17594
18230
  var LABEL_EYEBROW_SPACING = 2;
17595
- function \u5E45\u306B\u53CE\u3081\u308B2(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45, \u984C\u304B = false) {
17596
- const \u5E45 = textWidth(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593);
17597
- const \u4E0B\u9650 = \u984C\u304B ? \u5207\u3063\u3066\u53CE\u307E\u308B\u4E0B\u9650(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45, textWidth) : 0;
18231
+ function \u5E45\u306B\u53CE\u3081\u308B2(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45, \u984C\u304B = false, textMetrics = "proportional") {
18232
+ const \u6E2C\u308B = (t, s, ls) => textWidth(t, s, ls, textMetrics);
18233
+ const \u5E45 = \u6E2C\u308B(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593);
18234
+ const \u4E0B\u9650 = \u984C\u304B ? \u5207\u3063\u3066\u53CE\u307E\u308B\u4E0B\u9650(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45, \u6E2C\u308B) : 0;
17598
18235
  const \u500D\u7387 = \u5E45 > 0 && \u7BB1\u5E45 > 0 ? Math.min(1, Math.max(\u7BB1\u5E45 / \u5E45, \u4E0B\u9650)) : 1;
17599
18236
  const size = \u5927\u304D\u3055 * \u500D\u7387;
17600
18237
  const spacing = \u5B57\u9593 * \u500D\u7387;
17601
- return { size, spacing, text: \u5E2F\u3067\u5207\u308B(\u6587\u5B57\u5217, size, \u7BB1\u5E45, (u, f) => textWidth(u, f, spacing)) };
17602
- }
17603
- function bottomLabel(node, cx, plan) {
17604
- const \u80A9 = \u5E45\u306B\u53CE\u3081\u308B2(node.eyebrow ?? "", plan.\u80A9\u66F8?.size ?? 0, LABEL_EYEBROW_SPACING, node.w);
17605
- const \u540D = \u5E45\u306B\u53CE\u3081\u308B2(node.title ?? "", plan.\u540D\u524D.size, 0, node.w, true);
17606
- const \u8AAC = \u5E45\u306B\u53CE\u3081\u308B2(node.subtitle ?? "", plan.\u8AAC\u660E?.size ?? 0, 0, node.w);
18238
+ return { size, spacing, text: \u5E2F\u3067\u5207\u308B(\u6587\u5B57\u5217, size, \u7BB1\u5E45, (u, f) => \u6E2C\u308B(u, f, spacing)) };
18239
+ }
18240
+ function bottomLabel(node, cx, plan, textMetrics = "proportional") {
18241
+ const \u80A9 = \u5E45\u306B\u53CE\u3081\u308B2(
18242
+ node.eyebrow ?? "",
18243
+ plan.\u80A9\u66F8?.size ?? 0,
18244
+ LABEL_EYEBROW_SPACING,
18245
+ node.w,
18246
+ false,
18247
+ textMetrics
18248
+ );
18249
+ const \u540D = \u5E45\u306B\u53CE\u3081\u308B2(node.title ?? "", plan.\u540D\u524D.size, 0, node.w, true, textMetrics);
18250
+ const \u8AAC = \u5E45\u306B\u53CE\u3081\u308B2(
18251
+ node.subtitle ?? "",
18252
+ plan.\u8AAC\u660E?.size ?? 0,
18253
+ 0,
18254
+ node.w,
18255
+ false,
18256
+ textMetrics
18257
+ );
17607
18258
  return /* @__PURE__ */ jsxs(Fragment, { children: [
17608
18259
  node.eyebrow && plan.\u80A9\u66F8 && /* @__PURE__ */ jsx("text", { x: cx, y: plan.\u80A9\u66F8.y, fontSize: \u80A9.size, fontWeight: 700, letterSpacing: \u80A9.spacing, textAnchor: "middle", fill: "var(--cdl-tone-accent, #2d6a8f)", children: \u80A9.text }),
17609
18260
  /* @__PURE__ */ jsx("text", { "data-cdl-role": "node-label", x: cx, y: plan.\u540D\u524D.y, fontSize: \u540D.size, fontWeight: 700, textAnchor: "middle", fill: "var(--cdl-text, #1a1f2a)", children: \u540D.text }),
@@ -17617,7 +18268,7 @@ var RACK_SLOT_N = 4;
17617
18268
  var RACK_BOTTOM = 8;
17618
18269
  var RACK_H = RACK_SLOT_TOP + RACK_SLOT_N * RACK_SLOT_H + (RACK_SLOT_N - 1) * RACK_SLOT_GAP + RACK_BOTTOM;
17619
18270
  var RACK_W_MIN = 120;
17620
- function ShapeServerRackNode({ node, active }) {
18271
+ function ShapeServerRackNode({ node, active, textMetrics = "proportional" }) {
17621
18272
  const r = shapeRegion(node);
17622
18273
  const frame = commonFrame3(active);
17623
18274
  const \u7DDA = frame.strokeWidth / 2;
@@ -17699,7 +18350,7 @@ function ShapeServerRackNode({ node, active }) {
17699
18350
  ] }, i);
17700
18351
  })
17701
18352
  ] })),
17702
- bottomLabel(node, r.cx, r.label)
18353
+ bottomLabel(node, r.cx, r.label, textMetrics)
17703
18354
  ] });
17704
18355
  }
17705
18356
  var HUB_R = 30;
@@ -17707,7 +18358,7 @@ var ARM_LEN = 68;
17707
18358
  var END_R = 7;
17708
18359
  var WIFI_ARC_R = [10, 16, 22];
17709
18360
  var WIFI_BASE_Y = 5;
17710
- function ShapeNetworkNodeNode({ node, active }) {
18361
+ function ShapeNetworkNodeNode({ node, active, textMetrics = "proportional" }) {
17711
18362
  const r = shapeRegion(node);
17712
18363
  const cx = r.cx;
17713
18364
  const cy = r.cy;
@@ -17783,12 +18434,12 @@ function ShapeNetworkNodeNode({ node, active }) {
17783
18434
  )),
17784
18435
  /* @__PURE__ */ jsx("circle", { cx, cy: cy + WIFI_BASE_Y + 3, r: 2.5, fill: "var(--cdl-tone-accent, #2d6a8f)", stroke: "none" })
17785
18436
  ] })),
17786
- bottomLabel(node, r.cx, r.label)
18437
+ bottomLabel(node, r.cx, r.label, textMetrics)
17787
18438
  ] });
17788
18439
  }
17789
18440
  var PHONE_H = 240;
17790
18441
  var PHONE_W = 110;
17791
- function ShapeMobileDeviceNode({ node, active }) {
18442
+ function ShapeMobileDeviceNode({ node, active, textMetrics = "proportional" }) {
17792
18443
  const r = shapeRegion(node);
17793
18444
  const frame = commonFrame3(active);
17794
18445
  const \u7DDA = frame.strokeWidth / 2;
@@ -17855,7 +18506,7 @@ function ShapeMobileDeviceNode({ node, active }) {
17855
18506
  }
17856
18507
  )
17857
18508
  ] })),
17858
- bottomLabel(node, r.cx, r.label)
18509
+ bottomLabel(node, r.cx, r.label, textMetrics)
17859
18510
  ] });
17860
18511
  }
17861
18512
  function ShapeIotSensorNode({ node, active }) {
@@ -18126,7 +18777,7 @@ var SAT_DISH_R = 12;
18126
18777
  var SAT_DISH_STEM = 12;
18127
18778
  var SAT_MAST_LEN = 22;
18128
18779
  var SAT_MAST_TIP_R = 4;
18129
- function ShapeSatelliteNode({ node, active }) {
18780
+ function ShapeSatelliteNode({ node, active, textMetrics = "proportional" }) {
18130
18781
  const r = shapeRegion(node);
18131
18782
  const cx = r.cx;
18132
18783
  const cy = r.cy;
@@ -18315,7 +18966,7 @@ function ShapeSatelliteNode({ node, active }) {
18315
18966
  ),
18316
18967
  /* @__PURE__ */ jsx("circle", { cx, cy: cy - bodyH / 2 - SAT_MAST_LEN, r: 2, fill: "#ff5f56", stroke: "none", children: /* @__PURE__ */ jsx("animate", { attributeName: "opacity", values: "0.4;1;0.4", dur: "1.4s", repeatCount: "indefinite" }) })
18317
18968
  ] })),
18318
- bottomLabel(node, r.cx, r.label)
18969
+ bottomLabel(node, r.cx, r.label, textMetrics)
18319
18970
  ] });
18320
18971
  }
18321
18972
  var FRAME_SW_ACTIVE = 3;
@@ -18401,9 +19052,9 @@ function blockchainNodeExtent(strokeWidth) {
18401
19052
  const \u6A2A = (NODE_PEER_DIST + NODE_PEER_R) * Math.cos(Math.PI / 6) + \u7DDA;
18402
19053
  return { \u4E0A: \u7E26, \u4E0B: \u7E26, \u5DE6: \u6A2A, \u53F3: \u6A2A };
18403
19054
  }
18404
- function bottomLabel2(node, cx, plan) {
19055
+ function bottomLabel2(node, cx, plan, textMetrics = "proportional") {
18405
19056
  const \u53CE\u3081\u308B = (t, \u5927\u304D\u3055, \u5B57\u9593, \u984C\u304B = false) => {
18406
- const \u6E2C\u308B = (u, f, ls) => \u5B57\u306E\u5E45(u, f) + ls * [...u].length;
19057
+ const \u6E2C\u308B = (u, f, ls) => \u5B57\u306E\u5E45(u, f, textMetrics) + ls * [...u].length;
18407
19058
  const \u7D20\u306E\u5E45 = \u6E2C\u308B(t, \u5927\u304D\u3055, \u5B57\u9593);
18408
19059
  const \u53CE\u307E\u308B = \u7D20\u306E\u5E45 > node.w && node.w > 0 ? node.w / \u7D20\u306E\u5E45 : 1;
18409
19060
  const \u4E0B\u9650 = \u984C\u304B ? \u5207\u3063\u3066\u53CE\u307E\u308B\u4E0B\u9650(t, \u5927\u304D\u3055, \u5B57\u9593, node.w, \u6E2C\u308B) : 0;
@@ -18436,7 +19087,12 @@ function EthereumDiamond({ cx, cy, h, colors }) {
18436
19087
  /* @__PURE__ */ jsx("path", { d: `M ${cx} ${midY} L ${cx + w} ${cy + h * 0.05} L ${cx} ${lowerBotY} Z`, fill: c.dark, stroke: c.stroke, strokeWidth: 0.6, strokeLinejoin: "round" })
18437
19088
  ] });
18438
19089
  }
18439
- function ShapeSmartContractNode({ node, active, lang }) {
19090
+ function ShapeSmartContractNode({
19091
+ node,
19092
+ active,
19093
+ lang,
19094
+ textMetrics = "proportional"
19095
+ }) {
18440
19096
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
18441
19097
  const frame = commonFrame4(active);
18442
19098
  const r = shapeRegion(node);
@@ -18477,7 +19133,7 @@ function ShapeSmartContractNode({ node, active, lang }) {
18477
19133
  }
18478
19134
  ];
18479
19135
  const art = (\u500D\u7387) => {
18480
- const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089);
19136
+ const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089, textMetrics);
18481
19137
  return /* @__PURE__ */ jsxs("g", { children: [
18482
19138
  /* @__PURE__ */ jsx("path", { "data-cdl-role": "node-body", d: path, ...frame, strokeLinejoin: "round" }),
18483
19139
  /* @__PURE__ */ jsx("path", { d: foldPath, fill: "none", stroke: frame.stroke, strokeWidth: frame.strokeWidth, strokeLinejoin: "round" }),
@@ -18499,10 +19155,10 @@ function ShapeSmartContractNode({ node, active, lang }) {
18499
19155
  };
18500
19156
  return /* @__PURE__ */ jsxs("g", { children: [
18501
19157
  fitArt(r, smartContractExtent(frame.strokeWidth), art),
18502
- bottomLabel2(node, r.cx, r.label)
19158
+ bottomLabel2(node, r.cx, r.label, textMetrics)
18503
19159
  ] });
18504
19160
  }
18505
- var \u5B57\u306E\u5E45 = (text, size) => \u7D75\u306E\u4E2D\u306E\u5B57\u306E\u5E45(text, size);
19161
+ var \u5B57\u306E\u5E45 = (text, size, textMetrics = "proportional") => \u7D75\u306E\u4E2D\u306E\u5B57\u306E\u5E45(text, size, 0, textMetrics);
18506
19162
  var BLOCK_DEFAULT_FIELDS = [
18507
19163
  { key: "hash", label: "blockchainBlock.hash", value: { text: "0xaf31..." } },
18508
19164
  { key: "prev", label: "blockchainBlock.prev", value: { text: "0x7b3f..." } },
@@ -18510,10 +19166,16 @@ var BLOCK_DEFAULT_FIELDS = [
18510
19166
  { key: "nonce", label: "blockchainBlock.nonce", value: { text: "82,914" } },
18511
19167
  { key: "tx", label: "blockchainBlock.tx", value: { \u8F9E\u66F8: "blockchainBlock.txCount" } }
18512
19168
  ];
18513
- function ShapeBlockchainBlockNode({ node, active, lang }) {
19169
+ function ShapeBlockchainBlockNode({
19170
+ node,
19171
+ active,
19172
+ lang,
19173
+ textMetrics = "proportional"
19174
+ }) {
18514
19175
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
18515
19176
  const frame = commonFrame4(active);
18516
19177
  const r = shapeRegion(node);
19178
+ const \u6E2C\u308B\u5B57 = (text, size) => \u5B57\u306E\u5E45(text, size, textMetrics);
18517
19179
  const bw = BLOCK_W;
18518
19180
  const bh = BLOCK_H;
18519
19181
  const cx = r.cx;
@@ -18534,9 +19196,9 @@ function ShapeBlockchainBlockNode({ node, active, lang }) {
18534
19196
  const \u5E2F\u306E\u6B8B\u308A = bw - 14 - 30;
18535
19197
  const \u80A9\u66F8\u306E\u9699\u9593 = 8;
18536
19198
  const \u80A9\u66F8\u306E\u4E0A\u9650 = (\u5E2F\u306E\u6B8B\u308A - \u80A9\u66F8\u306E\u9699\u9593) / 2;
18537
- const \u80A9\u66F8\u306E\u500D\u7387 = \u80A9\u66F8 === "" ? 1 : \u5E45\u306E\u500D\u7387(\u80A9\u66F8, \u80A9\u66F8\u306E\u5B57, 0, \u80A9\u66F8\u306E\u4E0A\u9650);
19199
+ const \u80A9\u66F8\u306E\u500D\u7387 = \u80A9\u66F8 === "" ? 1 : \u5E45\u306E\u500D\u7387(\u80A9\u66F8, \u80A9\u66F8\u306E\u5B57, 0, \u80A9\u66F8\u306E\u4E0A\u9650, textMetrics);
18538
19200
  const \u80A9\u66F8\u306E\u6307\u5B9A = \u80A9\u66F8\u306E\u5B57 * \u80A9\u66F8\u306E\u500D\u7387;
18539
- const \u80A9\u66F8\u306E\u5E45 = \u80A9\u66F8 === "" ? 0 : \u5B57\u306E\u5E45(\u80A9\u66F8, \u80A9\u66F8\u306E\u6307\u5B9A);
19201
+ const \u80A9\u66F8\u306E\u5E45 = \u80A9\u66F8 === "" ? 0 : \u6E2C\u308B\u5B57(\u80A9\u66F8, \u80A9\u66F8\u306E\u6307\u5B9A);
18540
19202
  const \u898B\u51FA\u3057\u306E\u5E45 = \u5E2F\u306E\u6B8B\u308A - (\u80A9\u66F8 === "" ? 0 : \u80A9\u66F8\u306E\u5E45 + \u80A9\u66F8\u306E\u9699\u9593);
18541
19203
  const \u6253\u3061\u6D88\u3059\u5B57\u3089 = [
18542
19204
  { text: \u898B\u51FA\u3057, size: \u898B\u51FA\u3057\u306E\u5B57, \u5E2F: { \u5E45: \u898B\u51FA\u3057\u306E\u5E45, \u9AD8\u3055: \u898B\u51FA\u3057\u306E\u5E2F } },
@@ -18547,12 +19209,12 @@ function ShapeBlockchainBlockNode({ node, active, lang }) {
18547
19209
  {
18548
19210
  text: f.value,
18549
19211
  size: \u5024\u306E\u5B57,
18550
- \u5E2F: { \u5E45: bw - 28 - \u5B57\u306E\u5E45(f.label, \u540D\u306E\u5B57) - 8, \u9AD8\u3055: \u884C\u306E\u9593\u9694 }
19212
+ \u5E2F: { \u5E45: bw - 28 - \u6E2C\u308B\u5B57(f.label, \u540D\u306E\u5B57) - 8, \u9AD8\u3055: \u884C\u306E\u9593\u9694 }
18551
19213
  }
18552
19214
  ])
18553
19215
  ];
18554
19216
  const art = (\u500D\u7387) => {
18555
- const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089);
19217
+ const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089, textMetrics);
18556
19218
  const \u984C\u306E\u5927\u304D\u3055 = \u898B\u51FA\u3057\u306E\u5B57 * \u500D;
18557
19219
  const \u80A9\u66F8\u306E\u5927\u304D\u3055 = \u80A9\u66F8\u306E\u6307\u5B9A * \u500D;
18558
19220
  const \u540D\u306E\u5927\u304D\u3055 = \u540D\u306E\u5B57 * \u500D;
@@ -18561,7 +19223,7 @@ function ShapeBlockchainBlockNode({ node, active, lang }) {
18561
19223
  /* @__PURE__ */ jsx("rect", { x: x + 6, y: y + 6, width: bw, height: bh, rx: 8, fill: frame.stroke, opacity: 0.2, stroke: "none" }),
18562
19224
  /* @__PURE__ */ jsx("rect", { "data-cdl-role": "node-body", x, y, width: bw, height: bh, rx: 8, ...frame }),
18563
19225
  /* @__PURE__ */ jsx("path", { d: `M ${x} ${y + 32} L ${x} ${y + 8} Q ${x} ${y}, ${x + 8} ${y} L ${x + bw - 8} ${y} Q ${x + bw} ${y}, ${x + bw} ${y + 8} L ${x + bw} ${y + 32} Z`, fill: "var(--cdl-tone-accent, #2d6a8f)", fillOpacity: 0.9, stroke: "none" }),
18564
- /* @__PURE__ */ jsx("text", { "data-cdl-role": "blockchain-block-title", "data-cdl-counter-scaled": "1", x: x + 14, y: y + 22, fontSize: \u984C\u306E\u5927\u304D\u3055, fontWeight: 700, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fill: "#ffffff", children: \u5E45\u3067\u5207\u308B(\u898B\u51FA\u3057, \u984C\u306E\u5927\u304D\u3055, \u898B\u51FA\u3057\u306E\u5E45, \u5B57\u306E\u5E45) }),
19226
+ /* @__PURE__ */ jsx("text", { "data-cdl-role": "blockchain-block-title", "data-cdl-counter-scaled": "1", x: x + 14, y: y + 22, fontSize: \u984C\u306E\u5927\u304D\u3055, fontWeight: 700, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fill: "#ffffff", children: \u5E45\u3067\u5207\u308B(\u898B\u51FA\u3057, \u984C\u306E\u5927\u304D\u3055, \u898B\u51FA\u3057\u306E\u5E45, \u6E2C\u308B\u5B57) }),
18565
19227
  \u80A9\u66F8 !== "" && /* @__PURE__ */ jsx(
18566
19228
  "text",
18567
19229
  {
@@ -18581,7 +19243,12 @@ function ShapeBlockchainBlockNode({ node, active, lang }) {
18581
19243
  /* @__PURE__ */ jsx("circle", { cx: x + bw - 16, cy: y + 16, r: 5.5, fill: "#7cd88f", stroke: "#ffffff", strokeWidth: 1.5 }),
18582
19244
  fields.map((f, i) => /* @__PURE__ */ jsxs("g", { children: [
18583
19245
  /* @__PURE__ */ jsx("text", { "data-cdl-counter-scaled": "1", x: x + 14, y: y + 54 + i * \u884C\u306E\u9593\u9694, fontSize: \u540D\u306E\u5927\u304D\u3055, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fill: "var(--cdl-text-dim, #5a6270)", children: f.label }),
18584
- /* @__PURE__ */ jsx("text", { "data-cdl-role": `blockchain-block-${f.key}`, "data-cdl-counter-scaled": "1", x: x + bw - 14, y: y + 54 + i * \u884C\u306E\u9593\u9694, fontSize: \u5024\u306E\u5927\u304D\u3055, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontWeight: 600, textAnchor: "end", fill: "var(--cdl-text, #1a1f2a)", children: \u5E45\u3067\u5207\u308B(f.value, \u5024\u306E\u5927\u304D\u3055, bw - 28 - \u5B57\u306E\u5E45(f.label, \u540D\u306E\u5927\u304D\u3055) - 8, \u5B57\u306E\u5E45) }),
19246
+ /* @__PURE__ */ jsx("text", { "data-cdl-role": `blockchain-block-${f.key}`, "data-cdl-counter-scaled": "1", x: x + bw - 14, y: y + 54 + i * \u884C\u306E\u9593\u9694, fontSize: \u5024\u306E\u5927\u304D\u3055, fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontWeight: 600, textAnchor: "end", fill: "var(--cdl-text, #1a1f2a)", children: \u5E45\u3067\u5207\u308B(
19247
+ f.value,
19248
+ \u5024\u306E\u5927\u304D\u3055,
19249
+ bw - 28 - \u6E2C\u308B\u5B57(f.label, \u540D\u306E\u5927\u304D\u3055) - 8,
19250
+ \u6E2C\u308B\u5B57
19251
+ ) }),
18585
19252
  /* @__PURE__ */ jsx("line", { x1: x + 14, y1: y + 60 + i * \u884C\u306E\u9593\u9694, x2: x + bw - 14, y2: y + 60 + i * \u884C\u306E\u9593\u9694, stroke: "var(--cdl-divider, #d4d4d8)", strokeWidth: 0.5, opacity: 0.5 })
18586
19253
  ] }, i)),
18587
19254
  /* @__PURE__ */ jsxs("g", { transform: `translate(${cx - 32}, ${y + bh - 26})`, children: [
@@ -18593,7 +19260,11 @@ function ShapeBlockchainBlockNode({ node, active, lang }) {
18593
19260
  };
18594
19261
  return /* @__PURE__ */ jsx("g", { children: fitArt(r, blockchainBlockExtent(frame.strokeWidth), art) });
18595
19262
  }
18596
- function ShapeBlockchainNode({ node, active }) {
19263
+ function ShapeBlockchainNode({
19264
+ node,
19265
+ active,
19266
+ textMetrics = "proportional"
19267
+ }) {
18597
19268
  const frame = commonFrame4(active);
18598
19269
  const r = shapeRegion(node);
18599
19270
  const cx = r.cx;
@@ -18609,7 +19280,7 @@ function ShapeBlockchainNode({ node, active }) {
18609
19280
  { text: "0x\u2026", size: CHAIN_HASH_SIZE, \u5E2F: { \u5E45: CHAIN_TEXT_W, \u9AD8\u3055: CHAIN_ROW_GAP } }
18610
19281
  ];
18611
19282
  const art = (\u500D\u7387) => {
18612
- const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089);
19283
+ const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089, textMetrics);
18613
19284
  return /* @__PURE__ */ jsx("g", { children: Array.from({ length: blockCount }, (_, i) => i).map((i) => {
18614
19285
  const bx = startX + i * (blockW + linkW);
18615
19286
  const isCurrent = i === blockCount - 1;
@@ -18645,10 +19316,14 @@ function ShapeBlockchainNode({ node, active }) {
18645
19316
  };
18646
19317
  return /* @__PURE__ */ jsxs("g", { children: [
18647
19318
  fitArt(r, chainExtent(), art),
18648
- bottomLabel2(node, r.cx, r.label)
19319
+ bottomLabel2(node, r.cx, r.label, textMetrics)
18649
19320
  ] });
18650
19321
  }
18651
- function ShapeBitcoinChainNode({ node, active }) {
19322
+ function ShapeBitcoinChainNode({
19323
+ node,
19324
+ active,
19325
+ textMetrics = "proportional"
19326
+ }) {
18652
19327
  const frame = commonFrame4(active);
18653
19328
  const r = shapeRegion(node);
18654
19329
  const cx = r.cx;
@@ -18664,7 +19339,7 @@ function ShapeBitcoinChainNode({ node, active }) {
18664
19339
  { text: "#820", size: BTC_NO_SIZE, \u5E2F: { \u5E45: CHAIN_TEXT_W, \u9AD8\u3055: 20 } }
18665
19340
  ];
18666
19341
  const art = (\u500D\u7387) => {
18667
- const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089);
19342
+ const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089, textMetrics);
18668
19343
  return /* @__PURE__ */ jsx("g", { children: Array.from({ length: blockCount }, (_, i) => i).map((i) => {
18669
19344
  const bx = startX + i * (blockW + linkW);
18670
19345
  const isCurrent = i === blockCount - 1;
@@ -18695,10 +19370,14 @@ function ShapeBitcoinChainNode({ node, active }) {
18695
19370
  };
18696
19371
  return /* @__PURE__ */ jsxs("g", { children: [
18697
19372
  fitArt(r, chainExtent(), art),
18698
- bottomLabel2(node, r.cx, r.label)
19373
+ bottomLabel2(node, r.cx, r.label, textMetrics)
18699
19374
  ] });
18700
19375
  }
18701
- function ShapeEthereumChainNode({ node, active }) {
19376
+ function ShapeEthereumChainNode({
19377
+ node,
19378
+ active,
19379
+ textMetrics = "proportional"
19380
+ }) {
18702
19381
  const frame = commonFrame4(active);
18703
19382
  const r = shapeRegion(node);
18704
19383
  const cx = r.cx;
@@ -18714,7 +19393,7 @@ function ShapeEthereumChainNode({ node, active }) {
18714
19393
  { text: "#214", size: ETH_NO_SIZE, \u5E2F: { \u5E45: CHAIN_TEXT_W, \u9AD8\u3055: 20 } }
18715
19394
  ];
18716
19395
  const art = (\u500D\u7387) => {
18717
- const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089);
19396
+ const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089, textMetrics);
18718
19397
  return /* @__PURE__ */ jsx("g", { children: Array.from({ length: blockCount }, (_, i) => i).map((i) => {
18719
19398
  const bx = startX + i * (blockW + linkW);
18720
19399
  const isCurrent = i === blockCount - 1;
@@ -18746,10 +19425,14 @@ function ShapeEthereumChainNode({ node, active }) {
18746
19425
  };
18747
19426
  return /* @__PURE__ */ jsxs("g", { children: [
18748
19427
  fitArt(r, chainExtent(), art),
18749
- bottomLabel2(node, r.cx, r.label)
19428
+ bottomLabel2(node, r.cx, r.label, textMetrics)
18750
19429
  ] });
18751
19430
  }
18752
- function ShapeBlockchainNodeNode({ node, active }) {
19431
+ function ShapeBlockchainNodeNode({
19432
+ node,
19433
+ active,
19434
+ textMetrics = "proportional"
19435
+ }) {
18753
19436
  const frame = commonFrame4(active);
18754
19437
  const r = shapeRegion(node);
18755
19438
  const cx = r.cx;
@@ -18803,10 +19486,15 @@ function ShapeBlockchainNodeNode({ node, active }) {
18803
19486
  ] });
18804
19487
  return /* @__PURE__ */ jsxs("g", { children: [
18805
19488
  fitArt(r, blockchainNodeExtent(frame.strokeWidth), art),
18806
- bottomLabel2(node, r.cx, r.label)
19489
+ bottomLabel2(node, r.cx, r.label, textMetrics)
18807
19490
  ] });
18808
19491
  }
18809
- function ShapeRpcNodeNode({ node, active, lang }) {
19492
+ function ShapeRpcNodeNode({
19493
+ node,
19494
+ active,
19495
+ lang,
19496
+ textMetrics = "proportional"
19497
+ }) {
18810
19498
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
18811
19499
  const frame = commonFrame4(active);
18812
19500
  const r = shapeRegion(node);
@@ -18825,10 +19513,10 @@ function ShapeRpcNodeNode({ node, active, lang }) {
18825
19513
  /* @__PURE__ */ jsx("text", { x: cx, y: cy + 26, fontSize: 11, textAnchor: "middle", fill: "#7a8290", fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", children: "JSON-RPC 2.0" }),
18826
19514
  /* @__PURE__ */ jsx("rect", { x: x + 16, y: y + bh - 24, width: bw - 32, height: 8, rx: 4, fill: "#0f1419", stroke: "none" }),
18827
19515
  /* @__PURE__ */ jsx("rect", { x: x + 16, y: y + bh - 24, width: (bw - 32) * 0.92, height: 8, rx: 4, fill: "#27c93f", stroke: "none", children: /* @__PURE__ */ jsx("animate", { attributeName: "width", values: `${(bw - 32) * 0.86};${(bw - 32) * 0.96};${(bw - 32) * 0.86}`, dur: "3s", repeatCount: "indefinite" }) }),
18828
- bottomLabel2(node, r.cx, r.label)
19516
+ bottomLabel2(node, r.cx, r.label, textMetrics)
18829
19517
  ] });
18830
19518
  }
18831
- function ShapeWalletNode({ node, active }) {
19519
+ function ShapeWalletNode({ node, active, textMetrics = "proportional" }) {
18832
19520
  const frame = commonFrame4(active);
18833
19521
  const r = shapeRegion(node);
18834
19522
  const cx = r.cx;
@@ -18902,10 +19590,10 @@ function ShapeWalletNode({ node, active }) {
18902
19590
  /* @__PURE__ */ jsx("text", { x: cx, y: foldY + 3, fontSize: 9, fontWeight: 700, fill: "#5a3a10", textAnchor: "middle", opacity: 0.8, children: "\u039E" }),
18903
19591
  /* @__PURE__ */ jsx("path", { d: `M ${x + 2} ${y + 6} L ${x + w - 2} ${y + 6}`, fill: "none", stroke: "#ffffff", strokeWidth: 1, opacity: 0.4 })
18904
19592
  ] }),
18905
- bottomLabel2(node, r.cx, r.label)
19593
+ bottomLabel2(node, r.cx, r.label, textMetrics)
18906
19594
  ] });
18907
19595
  }
18908
- function ShapeNftNode({ node, active }) {
19596
+ function ShapeNftNode({ node, active, textMetrics = "proportional" }) {
18909
19597
  const frame = commonFrame4(active);
18910
19598
  const r = shapeRegion(node);
18911
19599
  const cx = r.cx;
@@ -18921,7 +19609,7 @@ function ShapeNftNode({ node, active }) {
18921
19609
  { text: "#1024", size: NFT_ID_SIZE, \u5E2F: { \u5E45: cardW - 16 - 34, \u9AD8\u3055: cardH - artH } }
18922
19610
  ];
18923
19611
  const art = (\u500D\u7387) => {
18924
- const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089);
19612
+ const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089, textMetrics);
18925
19613
  return /* @__PURE__ */ jsxs("g", { children: [
18926
19614
  /* @__PURE__ */ jsx("rect", { x: x + 4, y: y + 4, width: cardW, height: cardH, rx: 14, fill: frame.stroke, opacity: 0.2, stroke: "none" }),
18927
19615
  /* @__PURE__ */ jsx("rect", { "data-cdl-role": "node-body", x, y, width: cardW, height: cardH, rx: 14, ...frame }),
@@ -18959,10 +19647,10 @@ function ShapeNftNode({ node, active }) {
18959
19647
  };
18960
19648
  return /* @__PURE__ */ jsxs("g", { children: [
18961
19649
  fitArt(r, nftExtent(frame.strokeWidth), art),
18962
- bottomLabel2(node, r.cx, r.label)
19650
+ bottomLabel2(node, r.cx, r.label, textMetrics)
18963
19651
  ] });
18964
19652
  }
18965
- function ShapeTokenNode({ node, active }) {
19653
+ function ShapeTokenNode({ node, active, textMetrics = "proportional" }) {
18966
19654
  const frame = commonFrame4(active);
18967
19655
  const r = shapeRegion(node);
18968
19656
  const cx = r.cx;
@@ -18999,7 +19687,7 @@ function ShapeTokenNode({ node, active }) {
18999
19687
  }
19000
19688
  }
19001
19689
  ),
19002
- bottomLabel2(node, r.cx, r.label)
19690
+ bottomLabel2(node, r.cx, r.label, textMetrics)
19003
19691
  ] });
19004
19692
  }
19005
19693
  var commonFrame5 = (active) => ({
@@ -19018,7 +19706,8 @@ function \u5B57\u306E\u6BD4(c) {
19018
19706
  if (\u5E83\u5B57.has(c)) return \u5E83\u5B57\u6BD4;
19019
19707
  return (c.codePointAt(0) ?? 0) < 128 ? \u4E26\u5B57\u6BD4 : \u5E83\u5B57\u6BD4;
19020
19708
  }
19021
- function \u5B57\u5E45(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593) {
19709
+ function \u5B57\u5E45(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, textMetrics = "proportional") {
19710
+ if (textMetrics === "monospace") return textWidth(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, textMetrics);
19022
19711
  let \u5E45 = 0;
19023
19712
  let \u5B57\u6570 = 0;
19024
19713
  for (const c of \u6587\u5B57\u5217) {
@@ -19027,18 +19716,33 @@ function \u5B57\u5E45(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593) {
19027
19716
  }
19028
19717
  return \u5E45 + \u5B57\u9593 * \u5B57\u6570;
19029
19718
  }
19030
- function \u5E45\u306B\u53CE\u3081\u308B3(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45, \u984C\u304B = false) {
19031
- const \u5E45 = \u5B57\u5E45(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593);
19032
- const \u4E0B\u9650 = \u984C\u304B ? \u5207\u3063\u3066\u53CE\u307E\u308B\u4E0B\u9650(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45, \u5B57\u5E45) : 0;
19719
+ function \u5E45\u306B\u53CE\u3081\u308B3(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45, \u984C\u304B = false, textMetrics = "proportional") {
19720
+ const \u6E2C\u308B = (t, s, ls) => \u5B57\u5E45(t, s, ls, textMetrics);
19721
+ const \u5E45 = \u6E2C\u308B(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593);
19722
+ const \u4E0B\u9650 = \u984C\u304B ? \u5207\u3063\u3066\u53CE\u307E\u308B\u4E0B\u9650(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45, \u6E2C\u308B) : 0;
19033
19723
  const \u500D\u7387 = \u5E45 > 0 && \u7BB1\u5E45 > 0 ? Math.min(1, Math.max(\u7BB1\u5E45 / \u5E45, \u4E0B\u9650)) : 1;
19034
19724
  const size = \u5927\u304D\u3055 * \u500D\u7387;
19035
19725
  const spacing = \u5B57\u9593 * \u500D\u7387;
19036
- return { size, spacing, text: \u5E2F\u3067\u5207\u308B(\u6587\u5B57\u5217, size, \u7BB1\u5E45, (u, f) => \u5B57\u5E45(u, f, spacing)) };
19037
- }
19038
- function bottomLabel3(node, cx, plan) {
19039
- const \u80A9 = \u5E45\u306B\u53CE\u3081\u308B3(node.eyebrow ?? "", plan.\u80A9\u66F8?.size ?? 0, LABEL_EYEBROW_SPACING2, node.w);
19040
- const \u540D = \u5E45\u306B\u53CE\u3081\u308B3(node.title ?? "", plan.\u540D\u524D.size, 0, node.w, true);
19041
- const \u8AAC = \u5E45\u306B\u53CE\u3081\u308B3(node.subtitle ?? "", plan.\u8AAC\u660E?.size ?? 0, 0, node.w);
19726
+ return { size, spacing, text: \u5E2F\u3067\u5207\u308B(\u6587\u5B57\u5217, size, \u7BB1\u5E45, (u, f) => \u6E2C\u308B(u, f, spacing)) };
19727
+ }
19728
+ function bottomLabel3(node, cx, plan, textMetrics = "proportional") {
19729
+ const \u80A9 = \u5E45\u306B\u53CE\u3081\u308B3(
19730
+ node.eyebrow ?? "",
19731
+ plan.\u80A9\u66F8?.size ?? 0,
19732
+ LABEL_EYEBROW_SPACING2,
19733
+ node.w,
19734
+ false,
19735
+ textMetrics
19736
+ );
19737
+ const \u540D = \u5E45\u306B\u53CE\u3081\u308B3(node.title ?? "", plan.\u540D\u524D.size, 0, node.w, true, textMetrics);
19738
+ const \u8AAC = \u5E45\u306B\u53CE\u3081\u308B3(
19739
+ node.subtitle ?? "",
19740
+ plan.\u8AAC\u660E?.size ?? 0,
19741
+ 0,
19742
+ node.w,
19743
+ false,
19744
+ textMetrics
19745
+ );
19042
19746
  return /* @__PURE__ */ jsxs(Fragment, { children: [
19043
19747
  node.eyebrow && plan.\u80A9\u66F8 && /* @__PURE__ */ jsx("text", { x: cx, y: plan.\u80A9\u66F8.y, fontSize: \u80A9.size, fontWeight: 700, letterSpacing: \u80A9.spacing, textAnchor: "middle", fill: "var(--cdl-tone-accent, #2d6a8f)", children: \u80A9.text }),
19044
19748
  /* @__PURE__ */ jsx("text", { "data-cdl-role": "node-label", x: cx, y: plan.\u540D\u524D.y, fontSize: \u540D.size, fontWeight: 700, textAnchor: "middle", fill: "var(--cdl-text, #1a1f2a)", children: \u540D.text }),
@@ -19057,7 +19761,7 @@ var BANK_STEP_SW = 1;
19057
19761
  var BANK_COLUMN_MIN = 24;
19058
19762
  var BANK_BLD_W_MIN = 120;
19059
19763
  var BANK_BLD_W_MAX = 280;
19060
- function ShapeBankNode({ node, active }) {
19764
+ function ShapeBankNode({ node, active, textMetrics = "proportional" }) {
19061
19765
  const frame = commonFrame5(active);
19062
19766
  const r = shapeRegion(node);
19063
19767
  const \u7DDA = frame.strokeWidth / 2;
@@ -19104,7 +19808,7 @@ function ShapeBankNode({ node, active }) {
19104
19808
  ] });
19105
19809
  return /* @__PURE__ */ jsxs("g", { children: [
19106
19810
  fitArt(r, \u5E83\u304C\u308A, \u7D75),
19107
- bottomLabel3(node, r.cx, r.label)
19811
+ bottomLabel3(node, r.cx, r.label, textMetrics)
19108
19812
  ] });
19109
19813
  }
19110
19814
  var TRUST_CROWN_RISE = 4;
@@ -19116,7 +19820,12 @@ var TRUST_BASE_H = 14;
19116
19820
  var TRUST_BODY_OUT = 8;
19117
19821
  var TRUST_BLD_W_MIN = 140;
19118
19822
  var TRUST_BLD_W_MAX = 280;
19119
- function ShapeTrustBankNode({ node, active, lang }) {
19823
+ function ShapeTrustBankNode({
19824
+ node,
19825
+ active,
19826
+ lang,
19827
+ textMetrics = "proportional"
19828
+ }) {
19120
19829
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
19121
19830
  const frame = commonFrame5(active);
19122
19831
  const r = shapeRegion(node);
@@ -19170,10 +19879,15 @@ function ShapeTrustBankNode({ node, active, lang }) {
19170
19879
  ] });
19171
19880
  return /* @__PURE__ */ jsxs("g", { children: [
19172
19881
  fitArt(r, \u5E83\u304C\u308A, \u7D75),
19173
- bottomLabel3(node, r.cx, r.label)
19882
+ bottomLabel3(node, r.cx, r.label, textMetrics)
19174
19883
  ] });
19175
19884
  }
19176
- function ShapePaymentProviderNode({ node, active, lang }) {
19885
+ function ShapePaymentProviderNode({
19886
+ node,
19887
+ active,
19888
+ lang,
19889
+ textMetrics = "proportional"
19890
+ }) {
19177
19891
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
19178
19892
  const frame = commonFrame5(active);
19179
19893
  const r = shapeRegion(node);
@@ -19198,10 +19912,14 @@ function ShapePaymentProviderNode({ node, active, lang }) {
19198
19912
  /* @__PURE__ */ jsx("text", { x: cx, y: cy + 9, fontSize: 13, fontWeight: 700, textAnchor: "middle", fill: accentDarker, fontFamily: "Georgia, serif", children: "$" })
19199
19913
  ] }),
19200
19914
  /* @__PURE__ */ jsx("text", { x: cx, y: y + boxH - 16, fontSize: 11, fontWeight: 700, letterSpacing: 2, textAnchor: "middle", fill: "#a4b5f2", children: \u5B57\u5F15("paymentProvider.status") }),
19201
- bottomLabel3(node, r.cx, r.label)
19915
+ bottomLabel3(node, r.cx, r.label, textMetrics)
19202
19916
  ] });
19203
19917
  }
19204
- function ShapeCreditCardNode({ node, active }) {
19918
+ function ShapeCreditCardNode({
19919
+ node,
19920
+ active,
19921
+ textMetrics = "proportional"
19922
+ }) {
19205
19923
  const frame = commonFrame5(active);
19206
19924
  const r = shapeRegion(node);
19207
19925
  const cardW = Math.min(r.availW - 30, 260);
@@ -19223,7 +19941,7 @@ function ShapeCreditCardNode({ node, active }) {
19223
19941
  [0, 1, 2, 3].map((block) => /* @__PURE__ */ jsx("g", { children: [0, 1, 2, 3].map((dot) => /* @__PURE__ */ jsx("circle", { cx: x + 32 + block * (cardW - 64) / 4 + dot * 8, cy: y + cardH - 40, r: 2.8, fill: "#ffffff", stroke: "none" }, dot)) }, block)),
19224
19942
  /* @__PURE__ */ jsx("circle", { cx: x + cardW - 48, cy: y + cardH - 24, r: 15, fill: "#c9302c", opacity: 0.9, stroke: "none" }),
19225
19943
  /* @__PURE__ */ jsx("circle", { cx: x + cardW - 30, cy: y + cardH - 24, r: 15, fill: "#e5c07b", opacity: 0.9, stroke: "none" }),
19226
- bottomLabel3(node, r.cx, r.label)
19944
+ bottomLabel3(node, r.cx, r.label, textMetrics)
19227
19945
  ] });
19228
19946
  }
19229
19947
  var BROKERAGE_TICK_H = 18;
@@ -19248,7 +19966,12 @@ var BROKERAGE_SHADE_OUT = 2;
19248
19966
  var BROKERAGE_W_MIN = BROKERAGE_COLS * BROKERAGE_CELL_W + (BROKERAGE_COLS - 1) * BROKERAGE_GAP_X + 6;
19249
19967
  var BROKERAGE_W_MAX = 140;
19250
19968
  var BROKERAGE_H_MIN = BROKERAGE_TICK_H + BROKERAGE_LOGO_H + BROKERAGE_BASE_H;
19251
- function ShapeBrokerageNode({ node, active, lang }) {
19969
+ function ShapeBrokerageNode({
19970
+ node,
19971
+ active,
19972
+ lang,
19973
+ textMetrics = "proportional"
19974
+ }) {
19252
19975
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
19253
19976
  const frame = commonFrame5(active);
19254
19977
  const r = shapeRegion(node);
@@ -19287,7 +20010,7 @@ function ShapeBrokerageNode({ node, active, lang }) {
19287
20010
  }
19288
20011
  ];
19289
20012
  const \u7D75 = (\u500D\u7387) => {
19290
- const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089);
20013
+ const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089, textMetrics);
19291
20014
  return /* @__PURE__ */ jsxs("g", { children: [
19292
20015
  /* @__PURE__ */ jsx("ellipse", { cx, cy: y + h + BROKERAGE_SHADOW_DY, rx: w * BROKERAGE_SHADOW_RX_RATIO, ry: BROKERAGE_SHADOW_RY, fill: frame.stroke, opacity: 0.2, stroke: "none" }),
19293
20016
  /* @__PURE__ */ jsx("rect", { "data-cdl-role": "node-body", x, y, width: w, height: h, fill: "#255a7a", stroke: accentDarker, strokeWidth: frame.strokeWidth }),
@@ -19315,12 +20038,17 @@ function ShapeBrokerageNode({ node, active, lang }) {
19315
20038
  };
19316
20039
  return /* @__PURE__ */ jsxs("g", { children: [
19317
20040
  fitArt(r, \u5E83\u304C\u308A, \u7D75),
19318
- bottomLabel3(node, r.cx, r.label)
20041
+ bottomLabel3(node, r.cx, r.label, textMetrics)
19319
20042
  ] });
19320
20043
  }
19321
20044
  var EXCHANGE_SUB_SIZE = 11;
19322
20045
  var EXCHANGE_HEX_R = 52;
19323
- function ShapeExchangeNode({ node, active, lang }) {
20046
+ function ShapeExchangeNode({
20047
+ node,
20048
+ active,
20049
+ lang,
20050
+ textMetrics = "proportional"
20051
+ }) {
19324
20052
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
19325
20053
  const frame = commonFrame5(active);
19326
20054
  const r = shapeRegion(node);
@@ -19365,7 +20093,7 @@ function ShapeExchangeNode({ node, active, lang }) {
19365
20093
  }
19366
20094
  ];
19367
20095
  const \u7D75 = (\u500D\u7387) => {
19368
- const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089);
20096
+ const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089, textMetrics);
19369
20097
  return /* @__PURE__ */ jsxs("g", { children: [
19370
20098
  nodes.map((n, i) => /* @__PURE__ */ jsx("line", { x1: cx, y1: cy, x2: n.cx, y2: n.cy, stroke: accentDarker, strokeWidth: 1.5, strokeDasharray: "3 2" }, `l${i}`)),
19371
20099
  nodes.map((n, i) => {
@@ -19384,7 +20112,7 @@ function ShapeExchangeNode({ node, active, lang }) {
19384
20112
  };
19385
20113
  return /* @__PURE__ */ jsxs("g", { children: [
19386
20114
  fitArt(r, \u5E83\u304C\u308A, \u7D75),
19387
- bottomLabel3(node, r.cx, r.label)
20115
+ bottomLabel3(node, r.cx, r.label, textMetrics)
19388
20116
  ] });
19389
20117
  }
19390
20118
  var ATM_SIGN_H = 26;
@@ -19401,7 +20129,12 @@ var ATM_PANEL_H = 146;
19401
20129
  var ATM_W_MIN = 100;
19402
20130
  var ATM_W_MAX = ATM_PANEL_W;
19403
20131
  var ATM_H_MIN = ATM_SIGN_H + ATM_SIGN_GAP + 30 + ATM_FLOOR_RESERVE;
19404
- function ShapeAtmNode({ node, active, lang }) {
20132
+ function ShapeAtmNode({
20133
+ node,
20134
+ active,
20135
+ lang,
20136
+ textMetrics = "proportional"
20137
+ }) {
19405
20138
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
19406
20139
  const frame = commonFrame5(active);
19407
20140
  const r = shapeRegion(node);
@@ -19485,7 +20218,7 @@ function ShapeAtmNode({ node, active, lang }) {
19485
20218
  ] });
19486
20219
  return /* @__PURE__ */ jsxs("g", { children: [
19487
20220
  fitArt(r, \u5E83\u304C\u308A, \u7D75),
19488
- bottomLabel3(node, r.cx, r.label)
20221
+ bottomLabel3(node, r.cx, r.label, textMetrics)
19489
20222
  ] });
19490
20223
  }
19491
20224
  var commonFrame6 = (active) => ({
@@ -19504,7 +20237,8 @@ function \u5B57\u306E\u6BD42(c) {
19504
20237
  if (\u5E83\u5B572.has(c)) return \u5E83\u5B57\u6BD42;
19505
20238
  return (c.codePointAt(0) ?? 0) < 128 ? \u4E26\u5B57\u6BD42 : \u5E83\u5B57\u6BD42;
19506
20239
  }
19507
- function \u5B57\u5E452(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593) {
20240
+ function \u5B57\u5E452(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, textMetrics = "proportional") {
20241
+ if (textMetrics === "monospace") return textWidth(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, textMetrics);
19508
20242
  let \u5E45 = 0;
19509
20243
  let \u5B57\u6570 = 0;
19510
20244
  for (const c of \u6587\u5B57\u5217) {
@@ -19513,18 +20247,33 @@ function \u5B57\u5E452(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593) {
19513
20247
  }
19514
20248
  return \u5E45 + \u5B57\u9593 * \u5B57\u6570;
19515
20249
  }
19516
- function \u5E45\u306B\u53CE\u3081\u308B4(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45, \u984C\u304B = false) {
19517
- const \u5E45 = \u5B57\u5E452(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593);
19518
- const \u4E0B\u9650 = \u984C\u304B ? \u5207\u3063\u3066\u53CE\u307E\u308B\u4E0B\u9650(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45, \u5B57\u5E452) : 0;
20250
+ function \u5E45\u306B\u53CE\u3081\u308B4(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45, \u984C\u304B = false, textMetrics = "proportional") {
20251
+ const \u6E2C\u308B = (t, s, ls) => \u5B57\u5E452(t, s, ls, textMetrics);
20252
+ const \u5E45 = \u6E2C\u308B(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593);
20253
+ const \u4E0B\u9650 = \u984C\u304B ? \u5207\u3063\u3066\u53CE\u307E\u308B\u4E0B\u9650(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45, \u6E2C\u308B) : 0;
19519
20254
  const \u500D\u7387 = \u5E45 > 0 && \u7BB1\u5E45 > 0 ? Math.min(1, Math.max(\u7BB1\u5E45 / \u5E45, \u4E0B\u9650)) : 1;
19520
20255
  const size = \u5927\u304D\u3055 * \u500D\u7387;
19521
20256
  const spacing = \u5B57\u9593 * \u500D\u7387;
19522
- return { size, spacing, text: \u5E2F\u3067\u5207\u308B(\u6587\u5B57\u5217, size, \u7BB1\u5E45, (u, f) => \u5B57\u5E452(u, f, spacing)) };
19523
- }
19524
- function bottomLabel4(node, cx, plan) {
19525
- const \u80A9 = \u5E45\u306B\u53CE\u3081\u308B4(node.eyebrow ?? "", plan.\u80A9\u66F8?.size ?? 0, LABEL_EYEBROW_SPACING3, node.w);
19526
- const \u540D = \u5E45\u306B\u53CE\u3081\u308B4(node.title ?? "", plan.\u540D\u524D.size, 0, node.w, true);
19527
- const \u8AAC = \u5E45\u306B\u53CE\u3081\u308B4(node.subtitle ?? "", plan.\u8AAC\u660E?.size ?? 0, 0, node.w);
20257
+ return { size, spacing, text: \u5E2F\u3067\u5207\u308B(\u6587\u5B57\u5217, size, \u7BB1\u5E45, (u, f) => \u6E2C\u308B(u, f, spacing)) };
20258
+ }
20259
+ function bottomLabel4(node, cx, plan, textMetrics = "proportional") {
20260
+ const \u80A9 = \u5E45\u306B\u53CE\u3081\u308B4(
20261
+ node.eyebrow ?? "",
20262
+ plan.\u80A9\u66F8?.size ?? 0,
20263
+ LABEL_EYEBROW_SPACING3,
20264
+ node.w,
20265
+ false,
20266
+ textMetrics
20267
+ );
20268
+ const \u540D = \u5E45\u306B\u53CE\u3081\u308B4(node.title ?? "", plan.\u540D\u524D.size, 0, node.w, true, textMetrics);
20269
+ const \u8AAC = \u5E45\u306B\u53CE\u3081\u308B4(
20270
+ node.subtitle ?? "",
20271
+ plan.\u8AAC\u660E?.size ?? 0,
20272
+ 0,
20273
+ node.w,
20274
+ false,
20275
+ textMetrics
20276
+ );
19528
20277
  return /* @__PURE__ */ jsxs(Fragment, { children: [
19529
20278
  node.eyebrow && plan.\u80A9\u66F8 && /* @__PURE__ */ jsx("text", { x: cx, y: plan.\u80A9\u66F8.y, fontSize: \u80A9.size, fontWeight: 700, letterSpacing: \u80A9.spacing, textAnchor: "middle", fill: "var(--cdl-tone-accent, #2d6a8f)", children: \u80A9.text }),
19530
20279
  /* @__PURE__ */ jsx("text", { "data-cdl-role": "node-label", x: cx, y: plan.\u540D\u524D.y, fontSize: \u540D.size, fontWeight: 700, textAnchor: "middle", fill: "var(--cdl-text, #1a1f2a)", children: \u540D.text }),
@@ -19536,7 +20285,7 @@ var WEBSITE_BAR_H = 32;
19536
20285
  var WEBSITE_H_MIN = WEBSITE_BAR_H + 98;
19537
20286
  var WEBSITE_W_MIN = 160;
19538
20287
  var WEBSITE_W_MAX = 280;
19539
- function ShapeWebsiteNode({ node, active }) {
20288
+ function ShapeWebsiteNode({ node, active, textMetrics = "proportional" }) {
19540
20289
  const frame = commonFrame6(active);
19541
20290
  const r = shapeRegion(node);
19542
20291
  const cx = r.cx;
@@ -19562,10 +20311,10 @@ function ShapeWebsiteNode({ node, active }) {
19562
20311
  ] });
19563
20312
  return /* @__PURE__ */ jsxs("g", { children: [
19564
20313
  fitArt(r, \u5E83\u304C\u308A, \u7D75),
19565
- bottomLabel4(node, r.cx, r.label)
20314
+ bottomLabel4(node, r.cx, r.label, textMetrics)
19566
20315
  ] });
19567
20316
  }
19568
- function ShapeStorefrontNode({ node, active, lang }) {
20317
+ function ShapeStorefrontNode({ node, active, lang, textMetrics = "proportional" }) {
19569
20318
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
19570
20319
  const frame = commonFrame6(active);
19571
20320
  const r = shapeRegion(node);
@@ -19610,7 +20359,7 @@ function ShapeStorefrontNode({ node, active, lang }) {
19610
20359
  /* @__PURE__ */ jsx("text", { x: doorX + doorW / 2, y: doorY + doorH * 0.85 + 11, fontSize: 11, fontWeight: 700, letterSpacing: 1, textAnchor: "middle", fill: "#5a3a10", children: \u5B57\u5F15("storefront.open") }),
19611
20360
  /* @__PURE__ */ jsx("circle", { cx: doorX + 6, cy: doorY + doorH * 0.55, r: 1.5, fill: "#c15a4a" }),
19612
20361
  /* @__PURE__ */ jsx("rect", { x: x - 6, y: y + bh - 6, width: bw + 12, height: 8, fill: "#5a6270", stroke: "none" }),
19613
- bottomLabel4(node, r.cx, r.label)
20362
+ bottomLabel4(node, r.cx, r.label, textMetrics)
19614
20363
  ] });
19615
20364
  }
19616
20365
  var WAREHOUSE_ROOF_H = 18;
@@ -19624,7 +20373,7 @@ var WAREHOUSE_SHADOW_RX_RATIO = 0.5;
19624
20373
  var WAREHOUSE_H_MIN = WAREHOUSE_ROOF_H + WAREHOUSE_SIGN_H + 68;
19625
20374
  var WAREHOUSE_W_MIN = 160;
19626
20375
  var WAREHOUSE_W_MAX = 240;
19627
- function ShapeWarehouseNode({ node, active, lang }) {
20376
+ function ShapeWarehouseNode({ node, active, lang, textMetrics = "proportional" }) {
19628
20377
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
19629
20378
  const frame = commonFrame6(active);
19630
20379
  const r = shapeRegion(node);
@@ -19677,13 +20426,13 @@ function ShapeWarehouseNode({ node, active, lang }) {
19677
20426
  ] });
19678
20427
  return /* @__PURE__ */ jsxs("g", { children: [
19679
20428
  fitArt(r, \u5E83\u304C\u308A, \u7D75),
19680
- bottomLabel4(node, r.cx, r.label)
20429
+ bottomLabel4(node, r.cx, r.label, textMetrics)
19681
20430
  ] });
19682
20431
  }
19683
20432
  var HANDLE_GRIP_X = 118;
19684
20433
  var HANDLE_GRIP_R = 4;
19685
20434
  var CART_SHADOW_RX = 80;
19686
- function ShapeOnlineShopNode({ node, active }) {
20435
+ function ShapeOnlineShopNode({ node, active, textMetrics = "proportional" }) {
19687
20436
  const frame = commonFrame6(active);
19688
20437
  const r = shapeRegion(node);
19689
20438
  const cy = r.cy + 10;
@@ -19739,10 +20488,10 @@ function ShapeOnlineShopNode({ node, active }) {
19739
20488
  /* @__PURE__ */ jsx("circle", { cx: wheelR, cy: wheelY, r: 16 * s, fill: "#0f1830", stroke: "#000", strokeWidth: 2 * s }),
19740
20489
  /* @__PURE__ */ jsx("circle", { cx: wheelR, cy: wheelY, r: 8 * s, fill: "#5a6270", stroke: "#0f1830", strokeWidth: 1.5 * s }),
19741
20490
  /* @__PURE__ */ jsx("circle", { cx: wheelR, cy: wheelY, r: 2 * s, fill: "#0f1830" }),
19742
- bottomLabel4(node, r.cx, r.label)
20491
+ bottomLabel4(node, r.cx, r.label, textMetrics)
19743
20492
  ] });
19744
20493
  }
19745
- function ShapeCdnEdgeNode({ node, active }) {
20494
+ function ShapeCdnEdgeNode({ node, active, textMetrics = "proportional" }) {
19746
20495
  const frame = commonFrame6(active);
19747
20496
  const r = shapeRegion(node);
19748
20497
  const cx = r.cx;
@@ -19805,7 +20554,7 @@ function ShapeCdnEdgeNode({ node, active }) {
19805
20554
  ] });
19806
20555
  return /* @__PURE__ */ jsxs("g", { children: [
19807
20556
  fitArt(r, { \u4E0A: \u5E83\u304C\u308A, \u4E0B: \u5E83\u304C\u308A, \u5DE6: \u5E83\u304C\u308A, \u53F3: \u5E83\u304C\u308A }, \u7D75),
19808
- bottomLabel4(node, r.cx, r.label)
20557
+ bottomLabel4(node, r.cx, r.label, textMetrics)
19809
20558
  ] });
19810
20559
  }
19811
20560
  var API_ROW_TOP = 52;
@@ -19820,7 +20569,7 @@ var API_METHOD_BOX_W = 54;
19820
20569
  var API_METHOD_TEXT_W = 48;
19821
20570
  var API_W_MIN = 200;
19822
20571
  var API_W_MAX = 300;
19823
- function ShapeApiGatewayNode({ node, active, lang }) {
20572
+ function ShapeApiGatewayNode({ node, active, lang, textMetrics = "proportional" }) {
19824
20573
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
19825
20574
  const frame = commonFrame6(active);
19826
20575
  const r = shapeRegion(node);
@@ -19832,7 +20581,13 @@ function ShapeApiGatewayNode({ node, active, lang }) {
19832
20581
  const x = cx - bw / 2;
19833
20582
  const y = r.cy - \u7E26 / 2 + \u4F59\u767D;
19834
20583
  const \u5E83\u304C\u308A = { \u4E0A: \u7E26 / 2, \u4E0B: \u7E26 / 2, \u5DE6: bw / 2 + \u4F59\u767D, \u53F3: bw / 2 + \u4F59\u767D };
19835
- const \u7A2E\u985E\u306E\u5B57 = (s) => Math.min(11, 11 * API_METHOD_TEXT_W / Math.max(displayWidth(s) * 11 * MONO_ADVANCE_RATIO, textWidth(s, 11)));
20584
+ const \u7A2E\u985E\u306E\u5B57 = (s) => Math.min(
20585
+ 11,
20586
+ 11 * API_METHOD_TEXT_W / Math.max(
20587
+ displayWidth(s) * 11 * MONO_ADVANCE_RATIO,
20588
+ textWidth(s, 11, 0, textMetrics)
20589
+ )
20590
+ );
19836
20591
  const rowPitch = Math.max(
19837
20592
  API_ROW_PITCH_MIN,
19838
20593
  (bh - API_ROW_TOP - API_ROW_H - API_ROW_BOTTOM_PAD) / (API_ROWS - 1)
@@ -19848,7 +20603,7 @@ function ShapeApiGatewayNode({ node, active, lang }) {
19848
20603
  \u5E2F: { \u5E45: bw - 32 - 64 - 16, \u9AD8\u3055: API_ROW_H }
19849
20604
  }));
19850
20605
  const \u7D75 = (\u500D\u7387) => {
19851
- const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089);
20606
+ const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089, textMetrics);
19852
20607
  return /* @__PURE__ */ jsxs("g", { children: [
19853
20608
  /* @__PURE__ */ jsx("rect", { x: x + DROP_SHADOW_D, y: y + DROP_SHADOW_D, width: bw, height: bh, rx: 10, fill: frame.stroke, opacity: 0.2, stroke: "none" }),
19854
20609
  /* @__PURE__ */ jsx("rect", { "data-cdl-role": "node-body", x, y, width: bw, height: bh, rx: 10, fill: "#1a2332", stroke: frame.stroke, strokeWidth: frame.strokeWidth }),
@@ -19865,7 +20620,7 @@ function ShapeApiGatewayNode({ node, active, lang }) {
19865
20620
  };
19866
20621
  return /* @__PURE__ */ jsxs("g", { children: [
19867
20622
  fitArt(r, \u5E83\u304C\u308A, \u7D75),
19868
- bottomLabel4(node, r.cx, r.label)
20623
+ bottomLabel4(node, r.cx, r.label, textMetrics)
19869
20624
  ] });
19870
20625
  }
19871
20626
  function bottomLabel5(node, cx, plan) {
@@ -20165,6 +20920,7 @@ function CdlNodeView({
20165
20920
  chartLineScale,
20166
20921
  \u95A2\u4FC2\u306E\u53D7\u3051\u53E3,
20167
20922
  lang,
20923
+ textMetrics,
20168
20924
  \u5024\u306E\u540D\u524D
20169
20925
  }) {
20170
20926
  const value = node.value ? interpolate(node.value, stateValues, \u5024\u306E\u540D\u524D) : void 0;
@@ -20209,7 +20965,14 @@ function CdlNodeView({
20209
20965
  return /* @__PURE__ */ jsx(CardNode, { node: resolvedNode, active });
20210
20966
  // 時系列のやり取り (#578)。 1 つの箱が図を丸ごと描く = 縦が時間で、参加者は箱を持たない
20211
20967
  case "sequence-board":
20212
- return /* @__PURE__ */ jsx(SequenceBoardNode, { node: resolvedNode, stateValues });
20968
+ return /* @__PURE__ */ jsx(
20969
+ SequenceBoardNode,
20970
+ {
20971
+ node: resolvedNode,
20972
+ stateValues,
20973
+ textMetrics
20974
+ }
20975
+ );
20213
20976
  // 図表 9 種は payload が `{signal}` を取れるので stateValues を渡す
20214
20977
  // (`render/payload-binding.ts` が描画直前に解決する)。 取れる欄は種別で違い、
20215
20978
  // 数と語を取る 7 種に対し、mind-map / tree-hierarchy は **名前だけ** を取る (#467)。
@@ -20234,7 +20997,8 @@ function CdlNodeView({
20234
20997
  active,
20235
20998
  stateValues,
20236
20999
  drawing,
20237
- progress
21000
+ progress,
21001
+ textMetrics
20238
21002
  }
20239
21003
  );
20240
21004
  case "chart-gauge":
@@ -20245,7 +21009,8 @@ function CdlNodeView({
20245
21009
  active,
20246
21010
  stateValues,
20247
21011
  drawing,
20248
- progress
21012
+ progress,
21013
+ textMetrics
20249
21014
  }
20250
21015
  );
20251
21016
  case "chart-stacked-bar":
@@ -20256,7 +21021,8 @@ function CdlNodeView({
20256
21021
  active,
20257
21022
  stateValues,
20258
21023
  drawing,
20259
- progress
21024
+ progress,
21025
+ textMetrics
20260
21026
  }
20261
21027
  );
20262
21028
  case "chart-slope":
@@ -20267,7 +21033,8 @@ function CdlNodeView({
20267
21033
  active,
20268
21034
  stateValues,
20269
21035
  drawing,
20270
- progress
21036
+ progress,
21037
+ textMetrics
20271
21038
  }
20272
21039
  );
20273
21040
  case "chart-waffle":
@@ -20278,11 +21045,20 @@ function CdlNodeView({
20278
21045
  active,
20279
21046
  stateValues,
20280
21047
  drawing,
20281
- progress
21048
+ progress,
21049
+ textMetrics
20282
21050
  }
20283
21051
  );
20284
21052
  case "chart-stat":
20285
- return /* @__PURE__ */ jsx(ChartStatNode, { node: resolvedNode, active, stateValues });
21053
+ return /* @__PURE__ */ jsx(
21054
+ ChartStatNode,
21055
+ {
21056
+ node: resolvedNode,
21057
+ active,
21058
+ stateValues,
21059
+ textMetrics
21060
+ }
21061
+ );
20286
21062
  case "chart-radial":
20287
21063
  return /* @__PURE__ */ jsx(
20288
21064
  ChartRadialNode,
@@ -20291,7 +21067,8 @@ function CdlNodeView({
20291
21067
  active,
20292
21068
  stateValues,
20293
21069
  drawing,
20294
- progress
21070
+ progress,
21071
+ textMetrics
20295
21072
  }
20296
21073
  );
20297
21074
  case "chart-bar":
@@ -20324,7 +21101,8 @@ function CdlNodeView({
20324
21101
  active,
20325
21102
  stateValues,
20326
21103
  drawing,
20327
- progress
21104
+ progress,
21105
+ textMetrics
20328
21106
  }
20329
21107
  );
20330
21108
  case "funnel-stages":
@@ -20335,11 +21113,20 @@ function CdlNodeView({
20335
21113
  active,
20336
21114
  stateValues,
20337
21115
  drawing,
20338
- progress
21116
+ progress,
21117
+ textMetrics
20339
21118
  }
20340
21119
  );
20341
21120
  case "quadrant-matrix":
20342
- return /* @__PURE__ */ jsx(QuadrantNode, { node: resolvedNode, active, stateValues });
21121
+ return /* @__PURE__ */ jsx(
21122
+ QuadrantNode,
21123
+ {
21124
+ node: resolvedNode,
21125
+ active,
21126
+ stateValues,
21127
+ textMetrics
21128
+ }
21129
+ );
20343
21130
  case "tree-hierarchy":
20344
21131
  return /* @__PURE__ */ jsx(
20345
21132
  TreeNode,
@@ -20348,7 +21135,8 @@ function CdlNodeView({
20348
21135
  active,
20349
21136
  stateValues,
20350
21137
  drawing,
20351
- progress
21138
+ progress,
21139
+ textMetrics
20352
21140
  }
20353
21141
  );
20354
21142
  case "journey-map":
@@ -20363,91 +21151,91 @@ function CdlNodeView({
20363
21151
  }
20364
21152
  );
20365
21153
  case "shape-file":
20366
- return /* @__PURE__ */ jsx(ShapeFileNode, { node: resolvedNode, active });
21154
+ return /* @__PURE__ */ jsx(ShapeFileNode, { node: resolvedNode, active, textMetrics });
20367
21155
  case "shape-folder":
20368
- return /* @__PURE__ */ jsx(ShapeFolderNode, { node: resolvedNode, active });
21156
+ return /* @__PURE__ */ jsx(ShapeFolderNode, { node: resolvedNode, active, textMetrics });
20369
21157
  case "shape-cloud":
20370
- return /* @__PURE__ */ jsx(ShapeCloudNode, { node: resolvedNode, active });
21158
+ return /* @__PURE__ */ jsx(ShapeCloudNode, { node: resolvedNode, active, textMetrics });
20371
21159
  case "shape-cylinder":
20372
- return /* @__PURE__ */ jsx(ShapeCylinderNode, { node: resolvedNode, active });
21160
+ return /* @__PURE__ */ jsx(ShapeCylinderNode, { node: resolvedNode, active, textMetrics });
20373
21161
  case "shape-hexagon":
20374
- return /* @__PURE__ */ jsx(ShapeHexagonNode, { node: resolvedNode, active });
21162
+ return /* @__PURE__ */ jsx(ShapeHexagonNode, { node: resolvedNode, active, textMetrics });
20375
21163
  case "shape-diamond":
20376
- return /* @__PURE__ */ jsx(ShapeDiamondNode, { node: resolvedNode, active });
21164
+ return /* @__PURE__ */ jsx(ShapeDiamondNode, { node: resolvedNode, active, textMetrics });
20377
21165
  case "shape-stack":
20378
- return /* @__PURE__ */ jsx(ShapeStackNode, { node: resolvedNode, active });
21166
+ return /* @__PURE__ */ jsx(ShapeStackNode, { node: resolvedNode, active, textMetrics });
20379
21167
  case "shape-person":
20380
- return /* @__PURE__ */ jsx(ShapePersonNode, { node: resolvedNode, active });
21168
+ return /* @__PURE__ */ jsx(ShapePersonNode, { node: resolvedNode, active, textMetrics });
20381
21169
  case "shape-window":
20382
21170
  return /* @__PURE__ */ jsx(ShapeWindowNode, { node: resolvedNode, active });
20383
21171
  case "shape-terminal":
20384
21172
  return /* @__PURE__ */ jsx(ShapeTerminalNode, { node: resolvedNode, active, lang });
20385
21173
  case "shape-code-block":
20386
- return /* @__PURE__ */ jsx(ShapeCodeBlockNode, { node: resolvedNode, active, lang });
21174
+ return /* @__PURE__ */ jsx(ShapeCodeBlockNode, { node: resolvedNode, active, lang, textMetrics });
20387
21175
  case "shape-kanban-card":
20388
- return /* @__PURE__ */ jsx(ShapeKanbanCardNode, { node: resolvedNode, active, lang });
21176
+ return /* @__PURE__ */ jsx(ShapeKanbanCardNode, { node: resolvedNode, active, lang, textMetrics });
20389
21177
  case "shape-message-bubble":
20390
21178
  return /* @__PURE__ */ jsx(ShapeMessageBubbleNode, { node: resolvedNode, active });
20391
21179
  case "shape-gear":
20392
21180
  return /* @__PURE__ */ jsx(ShapeGearNode, { node: resolvedNode, active });
20393
21181
  case "shape-server-rack":
20394
- return /* @__PURE__ */ jsx(ShapeServerRackNode, { node: resolvedNode, active });
21182
+ return /* @__PURE__ */ jsx(ShapeServerRackNode, { node: resolvedNode, active, textMetrics });
20395
21183
  case "shape-network-node":
20396
- return /* @__PURE__ */ jsx(ShapeNetworkNodeNode, { node: resolvedNode, active });
21184
+ return /* @__PURE__ */ jsx(ShapeNetworkNodeNode, { node: resolvedNode, active, textMetrics });
20397
21185
  case "shape-mobile-device":
20398
- return /* @__PURE__ */ jsx(ShapeMobileDeviceNode, { node: resolvedNode, active });
21186
+ return /* @__PURE__ */ jsx(ShapeMobileDeviceNode, { node: resolvedNode, active, textMetrics });
20399
21187
  case "shape-iot-sensor":
20400
21188
  return /* @__PURE__ */ jsx(ShapeIotSensorNode, { node: resolvedNode, active });
20401
21189
  case "shape-robot-arm":
20402
21190
  return /* @__PURE__ */ jsx(ShapeRobotArmNode, { node: resolvedNode, active });
20403
21191
  case "shape-satellite":
20404
- return /* @__PURE__ */ jsx(ShapeSatelliteNode, { node: resolvedNode, active });
21192
+ return /* @__PURE__ */ jsx(ShapeSatelliteNode, { node: resolvedNode, active, textMetrics });
20405
21193
  case "shape-smart-contract":
20406
- return /* @__PURE__ */ jsx(ShapeSmartContractNode, { node: resolvedNode, active, lang });
21194
+ return /* @__PURE__ */ jsx(ShapeSmartContractNode, { node: resolvedNode, active, lang, textMetrics });
20407
21195
  case "shape-blockchain-block":
20408
- return /* @__PURE__ */ jsx(ShapeBlockchainBlockNode, { node: resolvedNode, active, lang });
21196
+ return /* @__PURE__ */ jsx(ShapeBlockchainBlockNode, { node: resolvedNode, active, lang, textMetrics });
20409
21197
  case "shape-rpc-node":
20410
- return /* @__PURE__ */ jsx(ShapeRpcNodeNode, { node: resolvedNode, active, lang });
21198
+ return /* @__PURE__ */ jsx(ShapeRpcNodeNode, { node: resolvedNode, active, lang, textMetrics });
20411
21199
  case "shape-wallet":
20412
- return /* @__PURE__ */ jsx(ShapeWalletNode, { node: resolvedNode, active });
21200
+ return /* @__PURE__ */ jsx(ShapeWalletNode, { node: resolvedNode, active, textMetrics });
20413
21201
  case "shape-nft":
20414
- return /* @__PURE__ */ jsx(ShapeNftNode, { node: resolvedNode, active });
21202
+ return /* @__PURE__ */ jsx(ShapeNftNode, { node: resolvedNode, active, textMetrics });
20415
21203
  case "shape-token":
20416
- return /* @__PURE__ */ jsx(ShapeTokenNode, { node: resolvedNode, active });
21204
+ return /* @__PURE__ */ jsx(ShapeTokenNode, { node: resolvedNode, active, textMetrics });
20417
21205
  case "shape-blockchain":
20418
- return /* @__PURE__ */ jsx(ShapeBlockchainNode, { node: resolvedNode, active });
21206
+ return /* @__PURE__ */ jsx(ShapeBlockchainNode, { node: resolvedNode, active, textMetrics });
20419
21207
  case "shape-bitcoin-chain":
20420
- return /* @__PURE__ */ jsx(ShapeBitcoinChainNode, { node: resolvedNode, active });
21208
+ return /* @__PURE__ */ jsx(ShapeBitcoinChainNode, { node: resolvedNode, active, textMetrics });
20421
21209
  case "shape-ethereum-chain":
20422
- return /* @__PURE__ */ jsx(ShapeEthereumChainNode, { node: resolvedNode, active });
21210
+ return /* @__PURE__ */ jsx(ShapeEthereumChainNode, { node: resolvedNode, active, textMetrics });
20423
21211
  case "shape-blockchain-node":
20424
- return /* @__PURE__ */ jsx(ShapeBlockchainNodeNode, { node: resolvedNode, active });
21212
+ return /* @__PURE__ */ jsx(ShapeBlockchainNodeNode, { node: resolvedNode, active, textMetrics });
20425
21213
  case "shape-bank":
20426
- return /* @__PURE__ */ jsx(ShapeBankNode, { node: resolvedNode, active });
21214
+ return /* @__PURE__ */ jsx(ShapeBankNode, { node: resolvedNode, active, textMetrics });
20427
21215
  case "shape-trust-bank":
20428
- return /* @__PURE__ */ jsx(ShapeTrustBankNode, { node: resolvedNode, active, lang });
21216
+ return /* @__PURE__ */ jsx(ShapeTrustBankNode, { node: resolvedNode, active, lang, textMetrics });
20429
21217
  case "shape-payment-provider":
20430
- return /* @__PURE__ */ jsx(ShapePaymentProviderNode, { node: resolvedNode, active, lang });
21218
+ return /* @__PURE__ */ jsx(ShapePaymentProviderNode, { node: resolvedNode, active, lang, textMetrics });
20431
21219
  case "shape-credit-card":
20432
- return /* @__PURE__ */ jsx(ShapeCreditCardNode, { node: resolvedNode, active });
21220
+ return /* @__PURE__ */ jsx(ShapeCreditCardNode, { node: resolvedNode, active, textMetrics });
20433
21221
  case "shape-brokerage":
20434
- return /* @__PURE__ */ jsx(ShapeBrokerageNode, { node: resolvedNode, active, lang });
21222
+ return /* @__PURE__ */ jsx(ShapeBrokerageNode, { node: resolvedNode, active, lang, textMetrics });
20435
21223
  case "shape-exchange":
20436
- return /* @__PURE__ */ jsx(ShapeExchangeNode, { node: resolvedNode, active, lang });
21224
+ return /* @__PURE__ */ jsx(ShapeExchangeNode, { node: resolvedNode, active, lang, textMetrics });
20437
21225
  case "shape-atm":
20438
- return /* @__PURE__ */ jsx(ShapeAtmNode, { node: resolvedNode, active, lang });
21226
+ return /* @__PURE__ */ jsx(ShapeAtmNode, { node: resolvedNode, active, lang, textMetrics });
20439
21227
  case "shape-website":
20440
- return /* @__PURE__ */ jsx(ShapeWebsiteNode, { node: resolvedNode, active });
21228
+ return /* @__PURE__ */ jsx(ShapeWebsiteNode, { node: resolvedNode, active, textMetrics });
20441
21229
  case "shape-storefront":
20442
- return /* @__PURE__ */ jsx(ShapeStorefrontNode, { node: resolvedNode, active, lang });
21230
+ return /* @__PURE__ */ jsx(ShapeStorefrontNode, { node: resolvedNode, active, lang, textMetrics });
20443
21231
  case "shape-warehouse":
20444
- return /* @__PURE__ */ jsx(ShapeWarehouseNode, { node: resolvedNode, active, lang });
21232
+ return /* @__PURE__ */ jsx(ShapeWarehouseNode, { node: resolvedNode, active, lang, textMetrics });
20445
21233
  case "shape-online-shop":
20446
- return /* @__PURE__ */ jsx(ShapeOnlineShopNode, { node: resolvedNode, active });
21234
+ return /* @__PURE__ */ jsx(ShapeOnlineShopNode, { node: resolvedNode, active, textMetrics });
20447
21235
  case "shape-cdn-edge":
20448
- return /* @__PURE__ */ jsx(ShapeCdnEdgeNode, { node: resolvedNode, active });
21236
+ return /* @__PURE__ */ jsx(ShapeCdnEdgeNode, { node: resolvedNode, active, textMetrics });
20449
21237
  case "shape-api-gateway":
20450
- return /* @__PURE__ */ jsx(ShapeApiGatewayNode, { node: resolvedNode, active, lang });
21238
+ return /* @__PURE__ */ jsx(ShapeApiGatewayNode, { node: resolvedNode, active, lang, textMetrics });
20451
21239
  case "shape-auditor":
20452
21240
  return /* @__PURE__ */ jsx(ShapeAuditorNode, { node: resolvedNode, active });
20453
21241
  case "shape-regulator":
@@ -20464,8 +21252,20 @@ function CdlNodeView({
20464
21252
  return /* @__PURE__ */ jsx(MarkStartNode, { node: resolvedNode, active });
20465
21253
  case "mark-end":
20466
21254
  return /* @__PURE__ */ jsx(MarkEndNode, { node: resolvedNode, active });
21255
+ case "station":
21256
+ return /* @__PURE__ */ jsx(StationNode, { node: resolvedNode, active });
20467
21257
  default:
20468
- return /* @__PURE__ */ jsx(GenericNode, { node: resolvedNode, active, value: node.value, stateValues, \u5024\u306E\u540D\u524D });
21258
+ return /* @__PURE__ */ jsx(
21259
+ GenericNode,
21260
+ {
21261
+ node: resolvedNode,
21262
+ active,
21263
+ value: node.value,
21264
+ stateValues,
21265
+ \u5024\u306E\u540D\u524D,
21266
+ textMetrics
21267
+ }
21268
+ );
20469
21269
  }
20470
21270
  })();
20471
21271
  const offsetX = node.renderOffsetX !== void 0 ? resolveNumericAttr(node.renderOffsetX, stateValues, 0) : 0;
@@ -20526,7 +21326,7 @@ function CdlNodeView({
20526
21326
  }
20527
21327
  ),
20528
21328
  inner,
20529
- \u7BB1\u306E\u4E0A\u306E\u8A9E(resolvedNode)
21329
+ \u7BB1\u306E\u4E0A\u306E\u8A9E(resolvedNode, textMetrics ?? "proportional")
20530
21330
  ]
20531
21331
  }
20532
21332
  );
@@ -20535,17 +21335,17 @@ var FIGURE_TITLE_GAP = 10;
20535
21335
  var FIGURE_TITLE_SIZE = 15;
20536
21336
  var FIGURE_EYEBROW_SIZE = 11;
20537
21337
  var FIGURE_EYEBROW_LIFT = 1.1;
20538
- function \u5E45\u306B\u53CE\u3081\u305F\u5927\u304D\u3055(\u8A9E, \u7D20\u306E\u5927\u304D\u3055, \u5E45) {
20539
- const \u5B9F\u5E45 = textWidth(\u8A9E, \u7D20\u306E\u5927\u304D\u3055, 0);
21338
+ function \u5E45\u306B\u53CE\u3081\u305F\u5927\u304D\u3055(\u8A9E, \u7D20\u306E\u5927\u304D\u3055, \u5E45, textMetrics = "proportional") {
21339
+ const \u5B9F\u5E45 = textWidth(\u8A9E, \u7D20\u306E\u5927\u304D\u3055, 0, textMetrics);
20540
21340
  return \u5B9F\u5E45 > \u5E45 ? \u7D20\u306E\u5927\u304D\u3055 * \u5E45 / \u5B9F\u5E45 : \u7D20\u306E\u5927\u304D\u3055;
20541
21341
  }
20542
- function \u7BB1\u306E\u4E0A\u306E\u8A9E(node) {
21342
+ function \u7BB1\u306E\u4E0A\u306E\u8A9E(node, textMetrics = "proportional") {
20543
21343
  if (!drawsFigureTitle(node.kind)) return null;
20544
21344
  const \u540D\u524D = (node.title ?? "").trim();
20545
21345
  const \u5C0F\u898B\u51FA\u3057 = (node.eyebrow ?? "").trim();
20546
21346
  if (\u540D\u524D === "" && \u5C0F\u898B\u51FA\u3057 === "") return null;
20547
21347
  const \u984C\u306Ey = node.cy - node.h / 2 - FIGURE_TITLE_GAP;
20548
- const \u984C\u306E\u5927\u304D\u3055 = \u5E45\u306B\u53CE\u3081\u305F\u5927\u304D\u3055(\u540D\u524D, FIGURE_TITLE_SIZE, node.w);
21348
+ const \u984C\u306E\u5927\u304D\u3055 = \u5E45\u306B\u53CE\u3081\u305F\u5927\u304D\u3055(\u540D\u524D, FIGURE_TITLE_SIZE, node.w, textMetrics);
20549
21349
  const \u5C0F\u898B\u51FA\u3057\u306Ey = \u540D\u524D === "" ? \u984C\u306Ey : \u984C\u306Ey - \u984C\u306E\u5927\u304D\u3055 * FIGURE_EYEBROW_LIFT;
20550
21350
  return /* @__PURE__ */ jsxs(Fragment, { children: [
20551
21351
  \u5C0F\u898B\u51FA\u3057 !== "" && /* @__PURE__ */ jsx(
@@ -20555,7 +21355,7 @@ function \u7BB1\u306E\u4E0A\u306E\u8A9E(node) {
20555
21355
  x: node.cx,
20556
21356
  y: \u5C0F\u898B\u51FA\u3057\u306Ey,
20557
21357
  textAnchor: "middle",
20558
- fontSize: \u5E45\u306B\u53CE\u3081\u305F\u5927\u304D\u3055(\u5C0F\u898B\u51FA\u3057, FIGURE_EYEBROW_SIZE, node.w),
21358
+ fontSize: \u5E45\u306B\u53CE\u3081\u305F\u5927\u304D\u3055(\u5C0F\u898B\u51FA\u3057, FIGURE_EYEBROW_SIZE, node.w, textMetrics),
20559
21359
  fontWeight: 600,
20560
21360
  letterSpacing: 0.6,
20561
21361
  fill: "var(--cdl-text-dim, #5a6270)",
@@ -20696,15 +21496,15 @@ function CdlStage({
20696
21496
  }, [laid]);
20697
21497
  const edgeHeadMarkers = useMemo(() => {
20698
21498
  const referenced = /* @__PURE__ */ new Set();
20699
- const add = (tone, head, fill) => {
21499
+ const add2 = (tone, head, fill) => {
20700
21500
  for (const small of [false, true]) {
20701
21501
  const id = edgeHeadMarkerName(tone, head, small, fill);
20702
21502
  if (id !== void 0) referenced.add(id);
20703
21503
  }
20704
21504
  };
20705
21505
  for (const edge of laid.edges) {
20706
- add(edge.tone, edge.head, edge.headFill);
20707
- if (edge.tailHead !== void 0) add(edge.tone, edge.tailHead, edge.tailHeadFill);
21506
+ add2(edge.tone, edge.head, edge.headFill);
21507
+ if (edge.tailHead !== void 0) add2(edge.tone, edge.tailHead, edge.tailHeadFill);
20708
21508
  }
20709
21509
  return Object.entries(TONE).flatMap(
20710
21510
  ([tone, color]) => [
@@ -20880,6 +21680,7 @@ function CdlStage({
20880
21680
  node,
20881
21681
  active: activeSet.has(node.id),
20882
21682
  lang: laid.lang,
21683
+ textMetrics: laid.textMetrics,
20883
21684
  \u95A2\u4FC2\u306E\u53D7\u3051\u53E3: \u7BB1\u306E\u53D7\u3051\u53E3,
20884
21685
  drawing: \u63CF\u304F,
20885
21686
  progress: \u63CF\u304F ? \u63CF\u304F\u9032\u307F : progress,
@@ -20896,7 +21697,8 @@ function CdlStage({
20896
21697
  CdlEdgeLabelView,
20897
21698
  {
20898
21699
  edge,
20899
- active: activeSet.has(edge.id)
21700
+ active: activeSet.has(edge.id),
21701
+ textMetrics: laid.textMetrics
20900
21702
  },
20901
21703
  `label-${edge.id}`
20902
21704
  )),
@@ -20906,7 +21708,8 @@ function CdlStage({
20906
21708
  {
20907
21709
  edge,
20908
21710
  active: activeSet.has(edge.id),
20909
- \u7AEF
21711
+ \u7AEF,
21712
+ textMetrics: laid.textMetrics
20910
21713
  },
20911
21714
  `${\u7AEF}-label-${edge.id}`
20912
21715
  ))
@@ -21971,7 +22774,15 @@ function useInteractiveIntegration(diagram, options = {}) {
21971
22774
  f.id
21972
22775
  )) }),
21973
22776
  scrolls.length > 0 && /* @__PURE__ */ jsx("div", { className: "cdl-ip-group", children: scrolls.map((s) => /* @__PURE__ */ jsx(ScrollReadout, { id: s.id, name: s.label || s.id, progress: stateOverrides[s.id] }, s.id)) }),
21974
- readouts.length > 0 && /* @__PURE__ */ jsx("div", { className: "cdl-ip-group", children: readouts.map((r) => /* @__PURE__ */ jsx(ReadoutWidget, { readout: r, stateOverrides: mergedStateValues }, r.id)) })
22777
+ readouts.length > 0 && /* @__PURE__ */ jsx("div", { className: "cdl-ip-group", children: readouts.map((r) => /* @__PURE__ */ jsx(
22778
+ ReadoutWidget,
22779
+ {
22780
+ readout: r,
22781
+ stateOverrides: mergedStateValues,
22782
+ textMetrics: resolveTextMetrics(diagram.textMetrics)
22783
+ },
22784
+ r.id
22785
+ )) })
21975
22786
  ] }) })
21976
22787
  );
21977
22788
  }, [diagram, signals, stateOverrides, mergedStateValues]);
@@ -22392,7 +23203,8 @@ function StepperWidget({
22392
23203
  }
22393
23204
  function ReadoutWidget({
22394
23205
  readout,
22395
- stateOverrides
23206
+ stateOverrides,
23207
+ textMetrics = "proportional"
22396
23208
  }) {
22397
23209
  const rawValue = "source" in readout ? stateOverrides[readout.source] : void 0;
22398
23210
  const numericValue = typeof rawValue === "number" ? rawValue : typeof rawValue === "string" ? Number(rawValue) : Number.NaN;
@@ -22640,7 +23452,8 @@ function ReadoutWidget({
22640
23452
  max: readout.max,
22641
23453
  viewW: readout.viewW ?? 280,
22642
23454
  viewH: readout.viewH ?? 60,
22643
- color: readout.color ?? "#2563eb"
23455
+ color: readout.color ?? "#2563eb",
23456
+ textMetrics
22644
23457
  }
22645
23458
  );
22646
23459
  case "radar": {
@@ -23456,7 +24269,8 @@ function ReadoutWidget({
23456
24269
  { status: "idle", color: "#94a3b8" },
23457
24270
  { status: "error", color: "#ef4444" }
23458
24271
  ],
23459
- max: readout.max ?? 10
24272
+ max: readout.max ?? 10,
24273
+ textMetrics
23460
24274
  }
23461
24275
  );
23462
24276
  case "calendar-week":
@@ -24600,8 +25414,8 @@ function ProgressGroupReadout({
24600
25414
  }) })
24601
25415
  ] });
24602
25416
  }
24603
- function sequenceLabelAnchor(x, name, fontSize, viewW) {
24604
- const half = textWidth(name, fontSize) / 2;
25417
+ function sequenceLabelAnchor(x, name, fontSize, viewW, textMetrics = "proportional") {
25418
+ const half = textWidth(name, fontSize, 0, textMetrics) / 2;
24605
25419
  if (x - half < 0) return "start";
24606
25420
  if (x + half > viewW) return "end";
24607
25421
  return "middle";
@@ -24614,7 +25428,8 @@ function SequenceTimelineReadout({
24614
25428
  max,
24615
25429
  viewW,
24616
25430
  viewH,
24617
- color
25431
+ color,
25432
+ textMetrics = "proportional"
24618
25433
  }) {
24619
25434
  const events = [];
24620
25435
  const trimmed = value.trim();
@@ -24657,7 +25472,17 @@ function SequenceTimelineReadout({
24657
25472
  const x = xFor(e.t);
24658
25473
  return /* @__PURE__ */ jsxs("g", { "data-cdl-event-marker": e.name, children: [
24659
25474
  /* @__PURE__ */ jsx("circle", { cx: x, cy: trackY, r: 5, fill: color, stroke: "#fff", strokeWidth: 1.5, children: /* @__PURE__ */ jsx(\u5B57\u306E\u898B\u51FA\u3057, { k: "readout.sequenceTimeline.title", v: { name: e.name, t: e.t } }) }),
24660
- /* @__PURE__ */ jsx("text", { x, y: trackY - 12, textAnchor: sequenceLabelAnchor(x, e.name, 10, viewW), fontSize: 10, fill: "var(--v4-ink, #1a1f2a)", children: e.name }),
25475
+ /* @__PURE__ */ jsx(
25476
+ "text",
25477
+ {
25478
+ x,
25479
+ y: trackY - 12,
25480
+ textAnchor: sequenceLabelAnchor(x, e.name, 10, viewW, textMetrics),
25481
+ fontSize: 10,
25482
+ fill: "var(--v4-ink, #1a1f2a)",
25483
+ children: e.name
25484
+ }
25485
+ ),
24661
25486
  /* @__PURE__ */ jsx("text", { x, y: trackY + 18, textAnchor: "middle", fontSize: 9, fill: "var(--v4-mute, #64748b)", children: e.t })
24662
25487
  ] }, i);
24663
25488
  })
@@ -27734,7 +28559,8 @@ function StatusTimelineReadout({
27734
28559
  label,
27735
28560
  value,
27736
28561
  colorMap,
27737
- max
28562
+ max,
28563
+ textMetrics = "proportional"
27738
28564
  }) {
27739
28565
  const events = [];
27740
28566
  const trimmed = value.trim();
@@ -27759,6 +28585,7 @@ function StatusTimelineReadout({
27759
28585
  const cellW = shown.length > 0 ? (width - 20) / shown.length : 0;
27760
28586
  const height = stripHeight + 40;
27761
28587
  const \u533A\u9593\u306E\u5B57 = (status) => status === "active" || status === "idle" || status === "error" ? \u5F15\u304F(`readout.statusTimeline.${status}`) : status.toUpperCase();
28588
+ const \u6E2C\u308B = \u7BB1\u306E\u5B57\u3092\u6E2C\u308B(textMetrics);
27762
28589
  return /* @__PURE__ */ jsxs("div", { className: "cdl-ip-item cdl-ip-readout-status-timeline", "data-cdl-readout": id, children: [
27763
28590
  /* @__PURE__ */ jsx("span", { className: "cdl-ip-label", children: label }),
27764
28591
  /* @__PURE__ */ jsx(
@@ -27772,7 +28599,7 @@ function StatusTimelineReadout({
27772
28599
  const x = 10 + i * cellW;
27773
28600
  const c = colorLookup.get(ev.status) ?? "#cbd5e1";
27774
28601
  const \u5B572 = \u533A\u9593\u306E\u5B57(ev.status);
27775
- const \u63CF\u304F\u5B57 = \u5E45\u3067\u5207\u308B(\u5B572, 10, cellW - 8);
28602
+ const \u63CF\u304F\u5B57 = \u5E45\u3067\u5207\u308B(\u5B572, 10, cellW - 8, \u6E2C\u308B);
27776
28603
  return /* @__PURE__ */ jsxs("g", { "data-cdl-status-event": i, "data-cdl-status": ev.status, children: [
27777
28604
  /* @__PURE__ */ jsx("rect", { x, y: 10, width: cellW - 2, height: stripHeight, fill: c, rx: 2 }),
27778
28605
  /* @__PURE__ */ jsxs(