@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.cjs CHANGED
@@ -717,6 +717,11 @@ function \u5B57\u3092\u5DEE\u3057\u8FBC\u3080(template, values) {
717
717
  return template.replace(/\{(\w+)\}/g, (whole, name) => name in values ? String(values[name]) : whole);
718
718
  }
719
719
 
720
+ // src/text-metrics.ts
721
+ function resolveTextMetrics(value) {
722
+ return value === "monospace" ? "monospace" : "proportional";
723
+ }
724
+
720
725
  // src/layout/clearance-constants.ts
721
726
  var CLEARANCE_NODE_LABEL = 32;
722
727
  var CLEARANCE_LANE_LABEL = 24;
@@ -878,10 +883,10 @@ function defaultAdvanceEm(ch, code) {
878
883
  if (ch >= "0" && ch <= "9") return 0.72;
879
884
  return 0.65;
880
885
  }
881
- function measureTextWidth(text, opts = {}) {
886
+ function measureAdvanceWidth(text, opts = {}) {
882
887
  const fontSize = opts.fontSize ?? 22;
883
888
  const letterSpacing = opts.letterSpacing ?? 0;
884
- const fontFamily = opts.fontFamily ?? "sans";
889
+ const fontFamily = opts.textMetrics === "monospace" ? "mono" : opts.fontFamily ?? "sans";
885
890
  const bound = opts.bound ?? "layout";
886
891
  let advanceEmSum = 0;
887
892
  let charCount = 0;
@@ -889,7 +894,7 @@ function measureTextWidth(text, opts = {}) {
889
894
  for (const ch of \u6587\u5B57\u5217) {
890
895
  charCount++;
891
896
  const code = ch.codePointAt(0) ?? 0;
892
- const \u5272\u308A\u623B\u3057 = bound === "drawn" && !isEmojiGrapheme(ch, code) ? isAscii(code) ? DRAWN_ASCII_RATIO : isCJK(code) ? DRAWN_CJK_RATIO : 1 : 1;
897
+ const \u5272\u308A\u623B\u3057 = bound === "drawn" && !isEmojiGrapheme(ch, code) ? isAscii(code) && fontFamily !== "mono" ? DRAWN_ASCII_RATIO : isCJK(code) ? DRAWN_CJK_RATIO : 1 : 1;
893
898
  if (isEmojiGrapheme(ch, code)) {
894
899
  advanceEmSum += fontFamily === "mono" ? MONO_EMOJI_ADVANCE_EM : EMOJI_ADVANCE_EM;
895
900
  continue;
@@ -905,7 +910,12 @@ function measureTextWidth(text, opts = {}) {
905
910
  const table = ch.length === 1 ? INTER_BOLD_ADVANCE_EM[ch] : void 0;
906
911
  advanceEmSum += (table !== void 0 ? table : defaultAdvanceEm(ch, code)) / \u5272\u308A\u623B\u3057;
907
912
  }
908
- const w = advanceEmSum * fontSize + letterSpacing * charCount;
913
+ return advanceEmSum * fontSize + letterSpacing * charCount;
914
+ }
915
+ function measureTextWidth(text, opts = {}) {
916
+ const fontSize = opts.fontSize ?? 22;
917
+ const bound = opts.bound ?? "layout";
918
+ const w = measureAdvanceWidth(text, opts);
909
919
  return bound === "drawn" ? w : Math.max(w, fontSize * 1.2);
910
920
  }
911
921
  function \u53CE\u3081\u308B\u500D\u7387(text, opts, \u5E45) {
@@ -988,6 +998,7 @@ var KINDS_DRAWING_TITLE_OUTSIDE = /* @__PURE__ */ new Set([
988
998
  "dyn-arc",
989
999
  "dyn-wave",
990
1000
  "dyn-polygon",
1001
+ "station",
991
1002
  ...KINDS_DRAWING_OWN_PAYLOAD
992
1003
  ]);
993
1004
  function drawsTitleOutsideBox(kind) {
@@ -995,7 +1006,7 @@ function drawsTitleOutsideBox(kind) {
995
1006
  }
996
1007
  var TITLE_FONT_SIZE_DEFAULT = 18;
997
1008
  var TITLE_FONT_SIZE = new Map([
998
- ...["dyn-rect", "dyn-circle", "dyn-arc", "dyn-wave", "dyn-polygon"].map(
1009
+ ...["dyn-rect", "dyn-circle", "dyn-arc", "dyn-wave", "dyn-polygon", "station"].map(
999
1010
  (k) => [k, 13]
1000
1011
  ),
1001
1012
  ...[
@@ -1046,6 +1057,10 @@ var TITLE_FONT_SIZE = new Map([
1046
1057
  function titleFontSize(kind) {
1047
1058
  return TITLE_FONT_SIZE.get(kind ?? "") ?? TITLE_FONT_SIZE_DEFAULT;
1048
1059
  }
1060
+ var KINDS_WITH_TITLE_WIDTH_OUTSIDE_NODE = /* @__PURE__ */ new Set(["station"]);
1061
+ function skipsNodeTitleWidthCheck(kind) {
1062
+ return KINDS_WITH_TITLE_WIDTH_OUTSIDE_NODE.has(kind ?? "");
1063
+ }
1049
1064
  var TITLE_BOX_PADDING = 52;
1050
1065
  var KINDS_SCALING_TITLE_WHEN_LOW = /* @__PURE__ */ new Set(["actor", "event", "function", "storage"]);
1051
1066
  var KINDS_SCALING_TITLE_ALWAYS = /* @__PURE__ */ new Set([
@@ -1128,7 +1143,8 @@ var KINDS_DRAWING_ONLY_SHAPE = [
1128
1143
  "dyn-circle",
1129
1144
  "dyn-arc",
1130
1145
  "dyn-wave",
1131
- "dyn-polygon"
1146
+ "dyn-polygon",
1147
+ "station"
1132
1148
  ];
1133
1149
  var KINDS_WITHOUT_EYEBROW_TEXT = /* @__PURE__ */ new Set([
1134
1150
  ...KINDS_DRAWING_ONLY_SHAPE,
@@ -1267,15 +1283,22 @@ function requiredVerticalLabelGap(pillHs) {
1267
1283
  const step = parallelLabelStepY(pillHs);
1268
1284
  return (pillHs.length - 1) * step + Math.max(first, last) + CLEARANCE_NODE_LABEL * 2;
1269
1285
  }
1270
- function computeLabelBoxW(label, sub) {
1271
- const mainW = measureTextWidth(label ?? "", { fontSize: EDGE_LABEL_TEXT.main.fontSize });
1272
- const subW = sub ? measureTextWidth(sub, { fontSize: EDGE_LABEL_TEXT.sub.fontSize, fontFamily: "mono" }) : 0;
1286
+ function computeLabelBoxW(label, sub, textMetrics = "proportional") {
1287
+ const mainW = measureTextWidth(label ?? "", {
1288
+ fontSize: EDGE_LABEL_TEXT.main.fontSize,
1289
+ textMetrics
1290
+ });
1291
+ const subW = sub ? measureTextWidth(sub, {
1292
+ fontSize: EDGE_LABEL_TEXT.sub.fontSize,
1293
+ fontFamily: "mono",
1294
+ textMetrics
1295
+ }) : 0;
1273
1296
  const raw = Math.max(mainW, subW) + LABEL_PILL_PAD_X * 2;
1274
1297
  const EPSILON = 1e-6;
1275
1298
  return Math.ceil((raw - EPSILON) / 2) * 2;
1276
1299
  }
1277
- function computeLabelBBoxWorld(edge) {
1278
- const boxW = computeLabelBoxW(edge.label, edge.sub);
1300
+ function computeLabelBBoxWorld(edge, textMetrics = "proportional") {
1301
+ const boxW = computeLabelBoxW(edge.label, edge.sub, textMetrics);
1279
1302
  const boxH = edge.sub ? LABEL_PILL_H_WITH_SUB : LABEL_PILL_H_MAIN_ONLY;
1280
1303
  const anchor = edge.labelAnchor;
1281
1304
  const boxLeftX = anchor === "start" ? 0 : anchor === "end" ? -boxW : -boxW / 2;
@@ -1499,7 +1522,7 @@ function footerShapeDrawTop(node) {
1499
1522
  // src/layout/collisions.ts
1500
1523
  var LANE_LABEL_CLEARANCE_MARGIN = 2;
1501
1524
  var NEAR_MISS_MARGIN = LANE_LABEL_CLEARANCE_MARGIN;
1502
- function collectBBoxes(lanes, nodes, edges) {
1525
+ function collectBBoxes(lanes, nodes, edges, textMetrics = "proportional") {
1503
1526
  const out = [];
1504
1527
  for (const lane of lanes) {
1505
1528
  if (!lane.label) continue;
@@ -1508,7 +1531,7 @@ function collectBBoxes(lanes, nodes, edges) {
1508
1531
  id: lane.id,
1509
1532
  x: lane.x + 16,
1510
1533
  y: lane.y + 8,
1511
- w: measureTextWidth(lane.label, { fontSize: 20, letterSpacing: 2 }) + 24,
1534
+ w: measureTextWidth(lane.label, { fontSize: 20, letterSpacing: 2, textMetrics }) + 24,
1512
1535
  h: 28
1513
1536
  });
1514
1537
  }
@@ -1526,7 +1549,7 @@ function collectBBoxes(lanes, nodes, edges) {
1526
1549
  }
1527
1550
  for (const e of edges) {
1528
1551
  if (!hasRenderedLabel(e)) continue;
1529
- const bbox = computeLabelBBoxWorld(e);
1552
+ const bbox = computeLabelBBoxWorld(e, textMetrics);
1530
1553
  out.push({
1531
1554
  kind: "edge-label",
1532
1555
  id: e.id,
@@ -1831,13 +1854,13 @@ function detectCollisions(bboxes, edges) {
1831
1854
  }
1832
1855
  function extractPathSegments(d) {
1833
1856
  const segs = [];
1834
- const commandRegex = /([MLCQZmlcqz])([^MLCQZmlcqz]*)/g;
1857
+ const commandRegex = /([MLCQAZmlcqaz])([^MLCQAZmlcqaz]*)/g;
1835
1858
  let cur = { x: 0, y: 0 };
1836
1859
  let m;
1837
1860
  while ((m = commandRegex.exec(d)) !== null) {
1838
1861
  const cmd = m[1];
1839
1862
  const args = (m[2] ?? "").trim().split(/[\s,]+/).filter(Boolean).map(parseFloat);
1840
- const need = cmd === "M" || cmd === "L" ? 2 : cmd === "Q" ? 4 : cmd === "C" ? 6 : 0;
1863
+ const need = cmd === "M" || cmd === "L" ? 2 : cmd === "Q" ? 4 : cmd === "C" ? 6 : cmd === "A" ? 7 : 0;
1841
1864
  if (need > 0 && (args.length < need || !args.slice(0, need).every(Number.isFinite))) continue;
1842
1865
  if (cmd === "M") {
1843
1866
  cur = { x: args[0], y: args[1] };
@@ -1867,6 +1890,10 @@ function extractPathSegments(d) {
1867
1890
  ctrl: [{ x: args[0], y: args[1] }, { x: args[2], y: args[3] }]
1868
1891
  });
1869
1892
  cur = next;
1893
+ } else if (cmd === "A") {
1894
+ const next = { x: args[5], y: args[6] };
1895
+ segs.push({ x1: cur.x, y1: cur.y, x2: next.x, y2: next.y, cmd: "A" });
1896
+ cur = next;
1870
1897
  }
1871
1898
  }
1872
1899
  return segs;
@@ -2166,7 +2193,7 @@ function clampShiftMagnitude(shift, maxMagnitude) {
2166
2193
  };
2167
2194
  return { dx: clampAxis(shift.dx), dy: clampAxis(shift.dy) };
2168
2195
  }
2169
- function resolveEdgeLabelOverlapsWithChainAndPropagate(edges, obstacles, minClearance = 16, maxIter = 20, pathLabelClearance = LABEL_TO_PATH_CLEARANCE) {
2196
+ function resolveEdgeLabelOverlapsWithChainAndPropagate(edges, obstacles, minClearance = 16, maxIter = 20, pathLabelClearance = LABEL_TO_PATH_CLEARANCE, textMetrics = "proportional") {
2170
2197
  if (edges.length === 0) {
2171
2198
  return {
2172
2199
  edges,
@@ -2177,7 +2204,7 @@ function resolveEdgeLabelOverlapsWithChainAndPropagate(edges, obstacles, minClea
2177
2204
  }
2178
2205
  const MAX_ACCUMULATED_SHIFT = CHAIN_SHIFT_MAX_ACCUMULATED;
2179
2206
  const labelBBox = (e, offsetX, offsetY) => {
2180
- const base = computeLabelBBoxWorld(e);
2207
+ const base = computeLabelBBoxWorld(e, textMetrics);
2181
2208
  return {
2182
2209
  kind: "edge-label",
2183
2210
  id: e.id,
@@ -2778,11 +2805,15 @@ var \u5411\u304D\u306E\u9806 = [
2778
2805
  { axis: "x", sign: -1, \u540D\u524D: "\u5DE6" },
2779
2806
  { axis: "x", sign: 1, \u540D\u524D: "\u53F3" }
2780
2807
  ];
2781
- function \u672D\u304C\u52D5\u3051\u306A\u3044\u7406\u7531(labelId, \u76F8\u624B, edges, obstacles) {
2808
+ function \u672D\u304C\u52D5\u3051\u306A\u3044\u7406\u7531(labelId, \u76F8\u624B, edges, obstacles, textMetrics = "proportional") {
2782
2809
  const edgeById = new Map(edges.map((e) => [e.id, e]));
2783
2810
  const \u81EA\u5206 = edgeById.get(labelId);
2784
2811
  if (!\u81EA\u5206) return null;
2785
- const labels = edges.filter((e) => e.label?.trim() || e.sub?.trim()).map((e) => ({ kind: "edge-label", id: e.id, ...computeLabelBBoxWorld(e) }));
2812
+ const labels = edges.filter((e) => e.label?.trim() || e.sub?.trim()).map((e) => ({
2813
+ kind: "edge-label",
2814
+ id: e.id,
2815
+ ...computeLabelBBoxWorld(e, textMetrics)
2816
+ }));
2786
2817
  const label = labels.find((l) => l.id === labelId);
2787
2818
  if (!label) return null;
2788
2819
  const \u6E2C\u308A\u65B9 = \u7DDA\u306E\u6E2C\u308A\u65B9\u3092\u4F5C\u308B();
@@ -2824,7 +2855,7 @@ function \u672D\u304C\u52D5\u3051\u306A\u3044\u7406\u7531(labelId, \u76F8\u624B,
2824
2855
  }
2825
2856
  return `\u9003\u3052\u5834\u306A\u3057: ${\u7406\u7531.sort((a, b) => a.\u9806 - b.\u9806).map((r) => r.\u6587).join(" / ")}`;
2826
2857
  }
2827
- function resolveLabelClearanceAfterPathPasses(edges, obstacles, maxIter = 8) {
2858
+ function resolveLabelClearanceAfterPathPasses(edges, obstacles, maxIter = 8, textMetrics = "proportional") {
2828
2859
  if (edges.length === 0) return edges;
2829
2860
  const labeledIds = new Set(
2830
2861
  edges.filter((e) => e.label?.trim() || e.sub?.trim()).map((e) => e.id)
@@ -2842,7 +2873,7 @@ function resolveLabelClearanceAfterPathPasses(edges, obstacles, maxIter = 8) {
2842
2873
  const out = [];
2843
2874
  for (const e of edges) {
2844
2875
  if (!labeledIds.has(e.id)) continue;
2845
- const base = computeLabelBBoxWorld(e);
2876
+ const base = computeLabelBBoxWorld(e, textMetrics);
2846
2877
  const s = getShift(e.id);
2847
2878
  out.push({ kind: "edge-label", id: e.id, x: base.x + s.dx, y: base.y + s.dy, w: base.w, h: base.h });
2848
2879
  }
@@ -2973,6 +3004,232 @@ function applyEdgeLabelAndPathShifts(edges, labelShiftMap, edgePathShiftMap) {
2973
3004
  });
2974
3005
  }
2975
3006
 
3007
+ // src/layout/curve-path.ts
3008
+ var SAME_HEIGHT_THRESHOLD = 1;
3009
+ function curvePath(from, to, edge, labelMarginExtra = 0, textMetrics = "proportional") {
3010
+ const fromLeft = from.cx - from.w / 2;
3011
+ const fromRight = from.cx + from.w / 2;
3012
+ const toLeft = to.cx - to.w / 2;
3013
+ const toRight = to.cx + to.w / 2;
3014
+ let fromSide;
3015
+ let toSide;
3016
+ let x1;
3017
+ let x2;
3018
+ if (toLeft >= fromRight) {
3019
+ fromSide = "right";
3020
+ toSide = "left";
3021
+ x1 = fromRight;
3022
+ x2 = toLeft;
3023
+ } else if (toRight <= fromLeft) {
3024
+ fromSide = "left";
3025
+ toSide = "right";
3026
+ x1 = fromLeft;
3027
+ x2 = toRight;
3028
+ } else {
3029
+ fromSide = "right";
3030
+ toSide = "right";
3031
+ x1 = fromRight;
3032
+ x2 = toRight;
3033
+ }
3034
+ const y1 = from.cy;
3035
+ const y2 = to.cy;
3036
+ const sameHeight = Math.abs(y2 - y1) < SAME_HEIGHT_THRESHOLD;
3037
+ let d;
3038
+ let midX;
3039
+ let midY;
3040
+ let tangentX;
3041
+ let tangentY;
3042
+ if (sameHeight) {
3043
+ d = `M ${x1} ${y1} L ${x2} ${y2}`;
3044
+ midX = (x1 + x2) / 2;
3045
+ midY = (y1 + y2) / 2;
3046
+ tangentX = x2 - x1;
3047
+ tangentY = y2 - y1;
3048
+ } else {
3049
+ let c1x;
3050
+ let c2x;
3051
+ if (fromSide !== toSide) {
3052
+ const direction = x2 > x1 ? 1 : -1;
3053
+ const bulge = Math.max(Math.abs(x2 - x1) / 2, EDGE_STUB_OUT);
3054
+ c1x = x1 + direction * bulge;
3055
+ c2x = x2 - direction * bulge;
3056
+ } else {
3057
+ const bulgeX = Math.max(x1, x2) + EDGE_STUB_OUT;
3058
+ c1x = bulgeX;
3059
+ c2x = bulgeX;
3060
+ }
3061
+ d = `M ${x1} ${y1} C ${c1x} ${y1}, ${c2x} ${y2}, ${x2} ${y2}`;
3062
+ midX = (x1 + 3 * c1x + 3 * c2x + x2) / 8;
3063
+ midY = (y1 + 3 * y1 + 3 * y2 + y2) / 8;
3064
+ tangentX = x2 + c2x - c1x - x1;
3065
+ tangentY = y2 + y2 - y1 - y1;
3066
+ }
3067
+ if (edge?.overlay) {
3068
+ return { d, fromSide, toSide, labelX: midX, labelY: midY, labelAnchor: "middle" };
3069
+ }
3070
+ const tangentLength = Math.hypot(tangentX, tangentY);
3071
+ let normalX = tangentY / tangentLength;
3072
+ let normalY = -tangentX / tangentLength;
3073
+ if (normalY > Number.EPSILON || Math.abs(normalY) <= Number.EPSILON && normalX < 0) {
3074
+ normalX *= -1;
3075
+ normalY *= -1;
3076
+ }
3077
+ const labelW = computeLabelBoxW(edge?.label, edge?.sub, textMetrics);
3078
+ const labelH = labelPillH(edge?.sub);
3079
+ const distance = labelPathClearanceHorizontal(edge) + (Math.abs(normalX) * labelW + Math.abs(normalY) * labelH) / 2 + labelMarginExtra;
3080
+ return {
3081
+ d,
3082
+ fromSide,
3083
+ toSide,
3084
+ labelX: midX + normalX * distance,
3085
+ labelY: midY + normalY * distance,
3086
+ labelAnchor: "middle"
3087
+ };
3088
+ }
3089
+
3090
+ // src/layout/metro-path.ts
3091
+ var METRO_CORNER_RADIUS = 24;
3092
+ var T = Math.SQRT2 - 1;
3093
+ function round2(v) {
3094
+ return Math.round(v * 100) / 100;
3095
+ }
3096
+ function point(p) {
3097
+ return `${round2(p.x)} ${round2(p.y)}`;
3098
+ }
3099
+ function add(p, v, scale) {
3100
+ return { x: p.x + v.x * scale, y: p.y + v.y * scale };
3101
+ }
3102
+ function polyline(points) {
3103
+ const distinct = points.filter((p, i) => {
3104
+ const previous = points[i - 1];
3105
+ return previous === void 0 || p.x !== previous.x || p.y !== previous.y;
3106
+ });
3107
+ return distinct.map((p, i) => `${i === 0 ? "M" : "L"} ${point(p)}`).join(" ");
3108
+ }
3109
+ function metroPath(from, to, edge, labelMarginExtra = 0, textMetrics = "proportional") {
3110
+ const fromLeft = from.cx - from.w / 2;
3111
+ const fromRight = from.cx + from.w / 2;
3112
+ const toLeft = to.cx - to.w / 2;
3113
+ const toRight = to.cx + to.w / 2;
3114
+ let fromSide;
3115
+ let toSide;
3116
+ let x1;
3117
+ let x2;
3118
+ let dir;
3119
+ if (toLeft >= fromRight) {
3120
+ fromSide = "right";
3121
+ toSide = "left";
3122
+ x1 = fromRight;
3123
+ x2 = toLeft;
3124
+ dir = 1;
3125
+ } else if (toRight <= fromLeft) {
3126
+ fromSide = "left";
3127
+ toSide = "right";
3128
+ x1 = fromLeft;
3129
+ x2 = toRight;
3130
+ dir = -1;
3131
+ } else {
3132
+ fromSide = "right";
3133
+ toSide = "right";
3134
+ x1 = fromRight;
3135
+ x2 = toRight;
3136
+ dir = 1;
3137
+ }
3138
+ const y1 = from.cy;
3139
+ const y2 = to.cy;
3140
+ const dy = y2 - y1;
3141
+ const sgn = Math.sign(dy);
3142
+ let d;
3143
+ let mid;
3144
+ let tangent;
3145
+ if (Math.abs(dy) < SAME_HEIGHT_THRESHOLD) {
3146
+ d = `M ${point({ x: x1, y: y1 })} L ${point({ x: x2, y: y2 })}`;
3147
+ mid = { x: (x1 + x2) / 2, y: (y1 + y2) / 2 };
3148
+ tangent = { x: x2 - x1, y: y2 - y1 };
3149
+ } else if (fromSide !== toSide && Math.abs(x2 - x1) >= Math.abs(dy)) {
3150
+ const horizontal = Math.abs(x2 - x1);
3151
+ const s = (horizontal - Math.abs(dy)) / 2;
3152
+ const p0 = { x: x1, y: y1 };
3153
+ const p1 = { x: x1 + dir * s, y: y1 };
3154
+ const p2 = { x: x2 - dir * s, y: y2 };
3155
+ const p3 = { x: x2, y: y2 };
3156
+ const u = { x: dir, y: 0 };
3157
+ const w = { x: dir / Math.SQRT2, y: sgn / Math.SQRT2 };
3158
+ const r = Math.min(
3159
+ METRO_CORNER_RADIUS,
3160
+ s / T,
3161
+ Math.SQRT2 * Math.abs(dy) / (2 * T)
3162
+ );
3163
+ const t = r * T;
3164
+ if (r >= 0.5) {
3165
+ const f1 = dir * sgn > 0 ? 1 : 0;
3166
+ d = [
3167
+ `M ${point(p0)}`,
3168
+ `L ${point(add(p1, u, -t))}`,
3169
+ `A ${round2(r)} ${round2(r)} 0 0 ${f1} ${point(add(p1, w, t))}`,
3170
+ `L ${point(add(p2, w, -t))}`,
3171
+ `A ${round2(r)} ${round2(r)} 0 0 ${1 - f1} ${point(add(p2, u, t))}`,
3172
+ `L ${point(p3)}`
3173
+ ].join(" ");
3174
+ } else {
3175
+ d = polyline([p0, p1, p2, p3]);
3176
+ }
3177
+ mid = { x: (x1 + x2) / 2, y: (y1 + y2) / 2 };
3178
+ tangent = w;
3179
+ } else {
3180
+ fromSide = "right";
3181
+ toSide = "right";
3182
+ x1 = fromRight;
3183
+ x2 = toRight;
3184
+ const xa = Math.max(x1, x2) + EDGE_STUB_OUT;
3185
+ const h = Math.abs(dy) / 2;
3186
+ const p0 = { x: x1, y: y1 };
3187
+ const p1 = { x: xa, y: y1 };
3188
+ const p2 = { x: xa + h, y: y1 + sgn * h };
3189
+ const p3 = { x: xa, y: y2 };
3190
+ const p4 = { x: x2, y: y2 };
3191
+ const u = { x: 1, y: 0 };
3192
+ const w1 = { x: 1 / Math.SQRT2, y: sgn / Math.SQRT2 };
3193
+ const w2 = { x: -1 / Math.SQRT2, y: sgn / Math.SQRT2 };
3194
+ const r = Math.min(METRO_CORNER_RADIUS, h);
3195
+ const t = r * T;
3196
+ const sweep = sgn > 0 ? 1 : 0;
3197
+ d = [
3198
+ `M ${point(p0)}`,
3199
+ `L ${point(add(p1, u, -t))}`,
3200
+ `A ${round2(r)} ${round2(r)} 0 0 ${sweep} ${point(add(p1, w1, t))}`,
3201
+ `L ${point(add(p2, w1, -r))}`,
3202
+ `A ${round2(r)} ${round2(r)} 0 0 ${sweep} ${point(add(p2, w2, r))}`,
3203
+ `L ${point(add(p3, w2, -t))}`,
3204
+ `A ${round2(r)} ${round2(r)} 0 0 ${sweep} ${point(add(p3, u, -t))}`,
3205
+ `L ${point(p4)}`
3206
+ ].join(" ");
3207
+ mid = { x: p2.x - T * r, y: p2.y };
3208
+ tangent = { x: 0, y: sgn };
3209
+ }
3210
+ if (edge?.overlay) {
3211
+ return { d, fromSide, toSide, labelX: mid.x, labelY: mid.y, labelAnchor: "middle" };
3212
+ }
3213
+ const tangentLength = Math.hypot(tangent.x, tangent.y);
3214
+ let normalX = tangent.y / tangentLength;
3215
+ let normalY = -tangent.x / tangentLength;
3216
+ if (normalY > Number.EPSILON || Math.abs(normalY) <= Number.EPSILON && normalX < 0) {
3217
+ normalX *= -1;
3218
+ normalY *= -1;
3219
+ }
3220
+ const labelW = computeLabelBoxW(edge?.label, edge?.sub, textMetrics);
3221
+ const labelH = labelPillH(edge?.sub);
3222
+ const distance = labelPathClearanceHorizontal(edge) + (Math.abs(normalX) * labelW + Math.abs(normalY) * labelH) / 2 + labelMarginExtra;
3223
+ return {
3224
+ d,
3225
+ fromSide,
3226
+ toSide,
3227
+ labelX: mid.x + normalX * distance,
3228
+ labelY: mid.y + normalY * distance,
3229
+ labelAnchor: "middle"
3230
+ };
3231
+ }
3232
+
2976
3233
  // src/types.ts
2977
3234
  var TONES = ["accent", "teal", "success", "error", "warning", "info"];
2978
3235
  var NODE_KINDS = [
@@ -3100,6 +3357,8 @@ var NODE_KINDS = [
3100
3357
  // 状態遷移図が使う。 印そのものが意味を持つので文字は描かない
3101
3358
  "mark-start",
3102
3359
  "mark-end",
3360
+ // 路線図の駅 (#996) ... 線路上の点を小さな丸で示し、名前と説明は丸の外に置く
3361
+ "station",
3103
3362
  // 時系列のやり取り (#578) ... 1 つの箱が図を丸ごと描く。 縦が時間で、参加者は箱を持たない
3104
3363
  "sequence-board"
3105
3364
  ];
@@ -3127,7 +3386,14 @@ var NARROW_RATIO = 0.37;
3127
3386
  var ASCII_RATIO = 0.86;
3128
3387
  var WIDE_CHARS = "W@%Mm";
3129
3388
  var NARROW_CHARS = "ijlI.,:;'! ";
3130
- function textWidth(s, size, \u5B57\u9001\u308A = 0) {
3389
+ function textWidth(s, size, \u5B57\u9001\u308A = 0, textMetrics = "proportional") {
3390
+ if (textMetrics === "monospace") {
3391
+ return measureAdvanceWidth(s, {
3392
+ fontSize: size,
3393
+ letterSpacing: \u5B57\u9001\u308A,
3394
+ fontFamily: "mono"
3395
+ });
3396
+ }
3131
3397
  let \u5E45 = 0;
3132
3398
  let \u5B57\u6570 = 0;
3133
3399
  for (const c of s) {
@@ -3164,8 +3430,8 @@ function splitRow(row) {
3164
3430
  }
3165
3431
  return { left: row.trim(), right: "", split: false };
3166
3432
  }
3167
- function rowColumnWidth(text, size, mono) {
3168
- return mono ? displayWidth(text) * size * MONO_ADVANCE_RATIO : textWidth(text, size);
3433
+ function rowColumnWidth(text, size, mono, textMetrics = "proportional") {
3434
+ return mono ? displayWidth(text) * size * MONO_ADVANCE_RATIO : textWidth(text, size, 0, textMetrics);
3169
3435
  }
3170
3436
  function displayWidth(text) {
3171
3437
  let w = 0;
@@ -3191,12 +3457,12 @@ function \u6841\u3067\u7701\u304F(text, \u4E0A\u9650) {
3191
3457
  if (displayWidth(text) <= \u4E0A\u9650) return text;
3192
3458
  return `${\u6841\u3067\u5272\u308B(text, \u4E0A\u9650 - 1)[0]}\u2026`;
3193
3459
  }
3194
- function requiredRowsWidth(rows, kind) {
3460
+ function requiredRowsWidth(rows, kind, textMetrics = "proportional") {
3195
3461
  if (!rows || rows.length === 0) return 0;
3196
3462
  const splits = rows.map(splitRow);
3197
3463
  const \u4E00\u756A\u5E83\u3044 = (\u53D6\u308B) => splits.reduce((m, s) => Math.max(m, \u53D6\u308B(s)), 0);
3198
- 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;
3199
- 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;
3464
+ 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;
3465
+ 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;
3200
3466
  if (kind === void 0) return Math.ceil(Math.max(storage, generic));
3201
3467
  return Math.ceil(kind === "storage" ? storage : generic);
3202
3468
  }
@@ -3261,7 +3527,10 @@ var \u5DE6\u53F3\u306E\u4F59\u767D = 8;
3261
3527
  function \u4F7F\u3048\u308B\u5E45(\u7BB1\u306E\u5E45) {
3262
3528
  return \u7BB1\u306E\u5E45 - \u5DE6\u53F3\u306E\u4F59\u767D * 2;
3263
3529
  }
3264
- function \u5E45\u3067\u5207\u308B(text, fontSize, \u4F7F\u3048\u308B\u5E452, \u6E2C\u308B = textWidth) {
3530
+ function \u7BB1\u306E\u5B57\u3092\u6E2C\u308B(textMetrics = "proportional") {
3531
+ return (text, fontSize) => textWidth(text, fontSize, 0, textMetrics);
3532
+ }
3533
+ function \u5E45\u3067\u5207\u308B(text, fontSize, \u4F7F\u3048\u308B\u5E452, \u6E2C\u308B) {
3265
3534
  if (\u4F7F\u3048\u308B\u5E452 <= 0) return "";
3266
3535
  if (\u6E2C\u308B(text, fontSize) <= \u4F7F\u3048\u308B\u5E452) return text;
3267
3536
  const \u7701\u7565 = "\u2026";
@@ -3278,7 +3547,7 @@ function \u5E45\u3067\u5207\u308B(text, fontSize, \u4F7F\u3048\u308B\u5E452, \u6
3278
3547
  return `${\u51FA}${\u7701\u7565}`;
3279
3548
  }
3280
3549
  var \u7E2E\u3081\u306E\u4E0B\u9650 = MIN_TEXT_SIZE;
3281
- function \u5E45\u306B\u53CE\u3081\u308B(text, fontSize, \u4F7F\u3048\u308B\u5E452, \u6E2C\u308B = textWidth) {
3550
+ function \u5E45\u306B\u53CE\u3081\u308B(text, fontSize, \u4F7F\u3048\u308B\u5E452, \u6E2C\u308B) {
3282
3551
  let size = fontSize;
3283
3552
  while (size > \u7E2E\u3081\u306E\u4E0B\u9650 && \u6E2C\u308B(text, size) > \u4F7F\u3048\u308B\u5E452) size -= 1;
3284
3553
  return { text: \u5E45\u3067\u5207\u308B(text, size, \u4F7F\u3048\u308B\u5E452, \u6E2C\u308B), fontSize: size };
@@ -3288,7 +3557,7 @@ function \u66F8\u8A18\u7D20\u306B\u5206\u3051\u308B(text) {
3288
3557
  if (typeof \u533A\u5207\u308A !== "function") return [...text];
3289
3558
  return [...new \u533A\u5207\u308A(void 0, { granularity: "grapheme" }).segment(text)].map((g) => g.segment);
3290
3559
  }
3291
- function \u7BB1\u306B\u7A4D\u3080(\u884C, \u7BB1\u306E\u5E45, \u7BB1\u306E\u9AD8\u30553) {
3560
+ function \u7BB1\u306B\u7A4D\u3080(\u884C, \u7BB1\u306E\u5E45, \u7BB1\u306E\u9AD8\u30553, \u6E2C\u308B) {
3292
3561
  const \u5019\u88DC = \u884C.filter((r, i) => i === 0 || r.text.trim() !== "");
3293
3562
  if (\u5019\u88DC.length === 0) return [];
3294
3563
  const \u4F7F\u3048\u308B\u9AD8\u3055 = \u7BB1\u306E\u9AD8\u30553 - \u4E0A\u4E0B\u306E\u4F59\u767D * 2;
@@ -3296,7 +3565,7 @@ function \u7BB1\u306B\u7A4D\u3080(\u884C, \u7BB1\u306E\u5E45, \u7BB1\u306E\u9AD8
3296
3565
  const \u6B8B\u3059 = [...\u5019\u88DC];
3297
3566
  while (\u6B8B\u3059.length > 1 && \u9AD8\u3055(\u6B8B\u3059) > \u4F7F\u3048\u308B\u9AD8\u3055) \u6B8B\u3059.pop();
3298
3567
  const \u5E45 = \u4F7F\u3048\u308B\u5E45(\u7BB1\u306E\u5E45);
3299
- const \u53CE\u3081\u305F = \u6B8B\u3059.map((r) => ({ ...r, ...\u5E45\u306B\u53CE\u3081\u308B(r.text, r.fontSize, \u5E45) }));
3568
+ const \u53CE\u3081\u305F = \u6B8B\u3059.map((r) => ({ ...r, ...\u5E45\u306B\u53CE\u3081\u308B(r.text, r.fontSize, \u5E45, \u6E2C\u308B) }));
3300
3569
  const \u7DCF\u9AD8 = \u9AD8\u3055(\u53CE\u3081\u305F);
3301
3570
  let \u7A4D\u307F = -\u7DCF\u9AD8 / 2;
3302
3571
  return \u53CE\u3081\u305F.map((r) => {
@@ -3309,9 +3578,9 @@ function \u66F8\u3044\u305F\u5024\u304B\u63A7\u3048(\u66F8\u3044\u305F, \u63A7\u
3309
3578
  const v = (\u66F8\u3044\u305F ?? "").trim();
3310
3579
  return v === "" ? \u63A7\u3048 : v;
3311
3580
  }
3312
- function \u5E45\u306E\u500D\u7387(text, size, letterSpacing, \u5E45) {
3581
+ function \u5E45\u306E\u500D\u7387(text, size, letterSpacing, \u5E45, textMetrics = "proportional") {
3313
3582
  if (!(\u5E45 > 0) || !(size > 0)) return 1;
3314
- const \u5B9F\u5E45 = textWidth(text, size, letterSpacing);
3583
+ const \u5B9F\u5E45 = textWidth(text, size, letterSpacing, textMetrics);
3315
3584
  return \u5B9F\u5E45 > \u5E45 ? \u5E45 / \u5B9F\u5E45 : 1;
3316
3585
  }
3317
3586
  function \u8AAD\u3081\u308B\u4E0B\u9650\u306E\u500D\u7387(\u5927\u304D\u3055) {
@@ -3526,13 +3795,13 @@ function fitArt(region, extent, art) {
3526
3795
  );
3527
3796
  }
3528
3797
  var \u5E2F\u306E\u9AD8\u3055\u306B\u5BFE\u3059\u308B\u4E0A\u9650 = 0.8;
3529
- function \u7D75\u306E\u4E2D\u306E\u5B57\u306E\u5E45(text, size, letterSpacing = 0) {
3798
+ function \u7D75\u306E\u4E2D\u306E\u5B57\u306E\u5E45(text, size, letterSpacing = 0, textMetrics = "proportional") {
3530
3799
  return Math.max(
3531
3800
  displayWidth(text) * size * MONO_ADVANCE_RATIO,
3532
- textWidth(text, size, letterSpacing)
3801
+ textWidth(text, size, letterSpacing, textMetrics)
3533
3802
  );
3534
3803
  }
3535
- function \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u5B57\u3089) {
3804
+ function \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u5B57\u3089, textMetrics = "proportional") {
3536
3805
  const \u623B\u3057 = Number.isFinite(\u500D\u7387) && \u500D\u7387 > 0 ? 1 / \u500D\u7387 : 1;
3537
3806
  let \u4E0A\u9650 = Number.POSITIVE_INFINITY;
3538
3807
  for (const \u5B572 of \u5B57\u3089) {
@@ -3541,7 +3810,7 @@ function \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u5B57\u3089)
3541
3810
  if (Number.isFinite(\u9AD8\u3055) && \u9AD8\u3055 > 0) {
3542
3811
  \u4E0A\u9650 = Math.min(\u4E0A\u9650, \u9AD8\u3055 * \u5E2F\u306E\u9AD8\u3055\u306B\u5BFE\u3059\u308B\u4E0A\u9650 / \u5B572.size);
3543
3812
  }
3544
- const \u5B9F\u5E45 = \u7D75\u306E\u4E2D\u306E\u5B57\u306E\u5E45(\u5B572.text, \u5B572.size, \u5B572.letterSpacing ?? 0);
3813
+ const \u5B9F\u5E45 = \u7D75\u306E\u4E2D\u306E\u5B57\u306E\u5E45(\u5B572.text, \u5B572.size, \u5B572.letterSpacing ?? 0, textMetrics);
3545
3814
  if (Number.isFinite(\u5E45) && \u5E45 > 0 && \u5B9F\u5E45 > 0) {
3546
3815
  \u4E0A\u9650 = Math.min(\u4E0A\u9650, \u5E45 / \u5B9F\u5E45);
3547
3816
  }
@@ -4736,9 +5005,14 @@ var PAD_LEFT = 24;
4736
5005
  var \u7BB1\u306E\u6700\u5927\u5E45 = 140;
4737
5006
  var \u7BB1\u306E\u6700\u5927\u9AD8\u3055 = 38;
4738
5007
  var \u6728\u306E\u679D\u306E\u592A\u3055 = (\u6BB5) => Math.max(1.1, 2.6 - \u6BB5 * 0.45);
4739
- function \u6728\u306E\u4E2D\u8EAB(node, stateValues = {}) {
5008
+ function \u6728\u306E\u4E2D\u8EAB(node, stateValues = {}, textMetrics = "proportional") {
4740
5009
  const treeNodes = resolveTreeData(node.treeData ?? [], stateValues);
4741
- return computeTreeLayout(treeNodes, node.w - PAD_LEFT - PAD_RIGHT, node.h - PAD_TOP - PAD_BOTTOM);
5010
+ return computeTreeLayout(
5011
+ treeNodes,
5012
+ node.w - PAD_LEFT - PAD_RIGHT,
5013
+ node.h - PAD_TOP - PAD_BOTTOM,
5014
+ textMetrics
5015
+ );
4742
5016
  }
4743
5017
  function \u6728\u306E\u884C(n) {
4744
5018
  return [
@@ -4751,12 +5025,14 @@ function TreeNode({
4751
5025
  active,
4752
5026
  stateValues = {},
4753
5027
  drawing = false,
4754
- progress = 1
5028
+ progress = 1,
5029
+ textMetrics = "proportional"
4755
5030
  }) {
4756
5031
  const x0 = node.cx - node.w / 2;
4757
5032
  const y0 = node.cy - node.h / 2;
4758
5033
  const gradientId = `tree-root-grad-${node.id}`;
4759
- const layout2 = \u6728\u306E\u4E2D\u8EAB(node, stateValues);
5034
+ const layout2 = \u6728\u306E\u4E2D\u8EAB(node, stateValues, textMetrics);
5035
+ const \u6E2C\u308B = \u7BB1\u306E\u5B57\u3092\u6E2C\u308B(textMetrics);
4760
5036
  const \u4F38\u3073 = \u9032\u307F\u3092\u7573\u3080(drawing, progress);
4761
5037
  const \u6700\u5927\u6DF1\u3055 = layout2.nodes.reduce((m, n) => Math.max(m, n.depth), 0);
4762
5038
  const \u7BB1\u304C\u51FA\u308B = (\u6DF1\u3055) => !drawing || \u6BB5\u306E\u4F38\u3073(\u4F38\u3073, \u6DF1\u3055, \u6700\u5927\u6DF1\u3055) >= 1;
@@ -4810,10 +5086,10 @@ function TreeNode({
4810
5086
  const accent = depthColors[Math.min(n.depth, depthColors.length - 1)] ?? depthColors[0];
4811
5087
  const isRoot = n.depth === 0;
4812
5088
  const \u6750\u6599 = \u6728\u306E\u884C(n);
4813
- const \u884C = \u7BB1\u306B\u7A4D\u3080(\u6750\u6599, n.w, n.h);
5089
+ const \u884C = \u7BB1\u306B\u7A4D\u3080(\u6750\u6599, n.w, n.h, \u6E2C\u308B);
4814
5090
  const \u88DC\u8DB3\u3042\u308A = (n.subtitle ?? "").trim() !== "";
4815
5091
  const \u540D\u524D = \u6750\u6599[0];
4816
- 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));
5092
+ 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);
4817
5093
  return /* @__PURE__ */ jsxRuntime.jsx(
4818
5094
  "g",
4819
5095
  {
@@ -4895,7 +5171,7 @@ function TreeNode({
4895
5171
  })
4896
5172
  ] });
4897
5173
  }
4898
- function computeTreeLayout(treeNodes, canvasW, canvasH) {
5174
+ function computeTreeLayout(treeNodes, canvasW, canvasH, textMetrics = "proportional") {
4899
5175
  const ids = new Set(treeNodes.map((n) => n.id));
4900
5176
  const childrenOf = /* @__PURE__ */ new Map();
4901
5177
  for (const n of treeNodes) {
@@ -4943,7 +5219,7 @@ function computeTreeLayout(treeNodes, canvasW, canvasH) {
4943
5219
  const \u7BB1\u306E\u5E45 = (n, depth) => {
4944
5220
  const \u6750\u6599 = \u6728\u306E\u884C({ ...n, depth });
4945
5221
  const \u540D\u524D = \u6750\u6599[0];
4946
- const \u8981\u308B = measureTextWidth(\u540D\u524D.text, { fontSize: \u540D\u524D.fontSize}) + (nodeW - \u4F7F\u3048\u308B\u5E45(nodeW));
5222
+ const \u8981\u308B = measureTextWidth(\u540D\u524D.text, { fontSize: \u540D\u524D.fontSize, textMetrics }) + (nodeW - \u4F7F\u3048\u308B\u5E45(nodeW));
4947
5223
  return Math.min(Math.max(\u8981\u308B, nodeW), slotW * 0.92);
4948
5224
  };
4949
5225
  const \u8449\u306E\u4E26\u3073 = [];
@@ -5047,7 +5323,7 @@ var BRANCH_BOX_H_MAX = 48;
5047
5323
  var SUB_BOX_H_MAX = 40;
5048
5324
  var \u7E26\u306E\u9593\u9694\u306E\u4E0A\u9650 = (\u679D\u306E\u6A2A\u306E\u4F38\u3073) => \u679D\u306E\u6A2A\u306E\u4F38\u3073;
5049
5325
  var MIND_PAD = 40;
5050
- function \u653E\u5C04\u306E\u4E2D\u8EAB(node, stateValues = {}) {
5326
+ function \u653E\u5C04\u306E\u4E2D\u8EAB(node, stateValues = {}, textMetrics = "proportional") {
5051
5327
  const mindData = node.mindData ? resolveMindData(node.mindData, stateValues) : void 0;
5052
5328
  if (!mindData) return void 0;
5053
5329
  return computeMindMapLayout(
@@ -5055,7 +5331,8 @@ function \u653E\u5C04\u306E\u4E2D\u8EAB(node, stateValues = {}) {
5055
5331
  node.w / 2,
5056
5332
  node.h / 2,
5057
5333
  node.w - MIND_PAD * 2,
5058
- node.h - MIND_PAD * 2
5334
+ node.h - MIND_PAD * 2,
5335
+ textMetrics
5059
5336
  );
5060
5337
  }
5061
5338
  function \u653E\u5C04\u306E\u884C(n) {
@@ -5069,12 +5346,14 @@ function MindMapNode({
5069
5346
  active,
5070
5347
  stateValues = {},
5071
5348
  drawing = false,
5072
- progress = 1
5349
+ progress = 1,
5350
+ textMetrics = "proportional"
5073
5351
  }) {
5074
5352
  const x0 = node.cx - node.w / 2;
5075
5353
  const y0 = node.cy - node.h / 2;
5076
- const layout2 = \u653E\u5C04\u306E\u4E2D\u8EAB(node, stateValues);
5354
+ const layout2 = \u653E\u5C04\u306E\u4E2D\u8EAB(node, stateValues, textMetrics);
5077
5355
  if (!layout2) return /* @__PURE__ */ jsxRuntime.jsx("g", { transform: `translate(${x0} ${y0})` });
5356
+ const \u6E2C\u308B = \u7BB1\u306E\u5B57\u3092\u6E2C\u308B(textMetrics);
5078
5357
  const \u4F38\u3073 = \u9032\u307F\u3092\u7573\u3080(drawing, progress);
5079
5358
  const \u6700\u5927\u6DF1\u3055 = layout2.nodes.reduce((m, n) => Math.max(m, n.depth), 0);
5080
5359
  const \u7BB1\u304C\u51FA\u308B = (\u6DF1\u3055) => !drawing || \u6BB5\u306E\u4F38\u3073(\u4F38\u3073, \u6DF1\u3055, \u6700\u5927\u6DF1\u3055) >= 1;
@@ -5121,8 +5400,13 @@ function MindMapNode({
5121
5400
  const \u6587\u5B57\u306E\u5BC4\u305B = \u67A0\u306A\u3057 ? \u5916\u3078 ? "start" : "end" : "middle";
5122
5401
  const \u63CF\u753B\u57DF\u306E\u7AEF = \u5916\u3078 ? node.w - MIND_PAD : MIND_PAD;
5123
5402
  const \u4F7F\u3048\u308B = \u67A0\u306A\u3057 ? Math.abs(\u63CF\u753B\u57DF\u306E\u7AEF - \u6587\u5B57\u306Ex) : \u4F7F\u3048\u308B\u5E45(n.w);
5124
- 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);
5125
- 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);
5403
+ 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);
5404
+ const \u884C = \u7BB1\u306B\u7A4D\u3080(
5405
+ \u6750\u6599,
5406
+ \u67A0\u306A\u3057 ? \u4F7F\u3048\u308B + (n.w - \u4F7F\u3048\u308B\u5E45(n.w)) : n.w,
5407
+ n.h,
5408
+ \u6E2C\u308B
5409
+ );
5126
5410
  const \u6587\u5B57\u306E\u8272 = n.isRoot ? "var(--cdl-text-on-tone, #ffffff)" : "var(--cdl-chip-text, #1a1f2a)";
5127
5411
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { "data-cdl-unresolved": n.unresolved ? "true" : void 0, children: [
5128
5412
  \u67A0\u306A\u3057 ? null : /* @__PURE__ */ jsxRuntime.jsx(
@@ -5174,14 +5458,14 @@ function MindMapNode({
5174
5458
  })
5175
5459
  ] });
5176
5460
  }
5177
- function \u63CF\u304F\u6A2A\u306E\u7AEF(n) {
5461
+ function \u63CF\u304F\u6A2A\u306E\u7AEF(n, textMetrics = "proportional") {
5178
5462
  if (n.isRoot || !n.isLeaf) return [n.x - n.w / 2, n.x + n.w / 2];
5179
5463
  const \u8D77\u70B9 = n.x + (n.side === "right" ? -n.w / 2 : n.w / 2);
5180
5464
  const \u540D\u524D = \u653E\u5C04\u306E\u884C(n)[0];
5181
- const \u5E45 = textWidth(\u540D\u524D.text, \u540D\u524D.fontSize);
5465
+ const \u5E45 = textWidth(\u540D\u524D.text, \u540D\u524D.fontSize, 0, textMetrics);
5182
5466
  return n.side === "right" ? [\u8D77\u70B9, \u8D77\u70B9 + \u5E45] : [\u8D77\u70B9 - \u5E45, \u8D77\u70B9];
5183
5467
  }
5184
- function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
5468
+ function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH, textMetrics = "proportional") {
5185
5469
  const nodes = [];
5186
5470
  const edges = [];
5187
5471
  const rootW = 120;
@@ -5259,7 +5543,7 @@ function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
5259
5543
  const PREFERRED_GAP = MIND_BOX_GAP;
5260
5544
  const \u679D\u306E\u540D\u524D\u306E\u5E45 = (title) => {
5261
5545
  const \u540D\u524D = \u653E\u5C04\u306E\u884C({ title, isRoot: false })[0];
5262
- return textWidth(\u540D\u524D.text, \u540D\u524D.fontSize);
5546
+ return textWidth(\u540D\u524D.text, \u540D\u524D.fontSize, 0, textMetrics);
5263
5547
  };
5264
5548
  const \u679D\u306E\u6A2A\u3092\u6C7A\u3081\u308B = (br) => {
5265
5549
  const maxSubDepth = subDepthOf(br.id, /* @__PURE__ */ new Set());
@@ -5377,7 +5661,7 @@ function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
5377
5661
  let maxExtentX = rootW / 2;
5378
5662
  let maxExtentY = rootH / 2;
5379
5663
  for (const n of nodes) {
5380
- const [\u5DE6, \u53F3] = \u63CF\u304F\u6A2A\u306E\u7AEF(n);
5664
+ const [\u5DE6, \u53F3] = \u63CF\u304F\u6A2A\u306E\u7AEF(n, textMetrics);
5381
5665
  maxExtentX = Math.max(maxExtentX, Math.abs(\u5DE6 - cx), Math.abs(\u53F3 - cx));
5382
5666
  maxExtentY = Math.max(maxExtentY, Math.abs(n.y - cy) + n.h / 2);
5383
5667
  }
@@ -5397,7 +5681,7 @@ function computeMindMapLayout(mindData, cx, cy, canvasW, canvasH) {
5397
5681
  let \u5DE6\u7AEF = Number.POSITIVE_INFINITY;
5398
5682
  let \u53F3\u7AEF = Number.NEGATIVE_INFINITY;
5399
5683
  for (const n of nodes) {
5400
- const [l, r] = \u63CF\u304F\u6A2A\u306E\u7AEF(n);
5684
+ const [l, r] = \u63CF\u304F\u6A2A\u306E\u7AEF(n, textMetrics);
5401
5685
  \u5DE6\u7AEF = Math.min(\u5DE6\u7AEF, l);
5402
5686
  \u53F3\u7AEF = Math.max(\u53F3\u7AEF, r);
5403
5687
  }
@@ -5619,10 +5903,16 @@ function emptyCounts() {
5619
5903
  "validation-interrupted": 0
5620
5904
  };
5621
5905
  }
5622
- function \u7A4D\u3080\u7BB1\u3092\u96C6\u3081\u308B(n) {
5623
- const \u7BB1 = (b, \u884C) => ({ \u884C, w: b.w, h: b.h });
5624
- if (n.kind === "tree-hierarchy") return \u6728\u306E\u4E2D\u8EAB(n).nodes.map((b) => \u7BB1(b, \u6728\u306E\u884C(b)));
5625
- if (n.kind === "mind-map") return (\u653E\u5C04\u306E\u4E2D\u8EAB(n)?.nodes ?? []).map((b) => \u7BB1(b, \u653E\u5C04\u306E\u884C(b)));
5906
+ function \u7A4D\u3080\u7BB1\u3092\u96C6\u3081\u308B(n, textMetrics = "proportional") {
5907
+ const \u7BB1 = (b, \u884C, \u6E2C\u308B) => ({ \u884C, w: b.w, h: b.h, \u6E2C\u308B });
5908
+ if (n.kind === "tree-hierarchy") {
5909
+ const \u6E2C\u308B = \u7BB1\u306E\u5B57\u3092\u6E2C\u308B(textMetrics);
5910
+ return \u6728\u306E\u4E2D\u8EAB(n, {}, textMetrics).nodes.map((b) => \u7BB1(b, \u6728\u306E\u884C(b), \u6E2C\u308B));
5911
+ }
5912
+ if (n.kind === "mind-map") {
5913
+ const \u6E2C\u308B = \u7BB1\u306E\u5B57\u3092\u6E2C\u308B(textMetrics);
5914
+ return (\u653E\u5C04\u306E\u4E2D\u8EAB(n, {}, textMetrics)?.nodes ?? []).map((b) => \u7BB1(b, \u653E\u5C04\u306E\u884C(b), \u6E2C\u308B));
5915
+ }
5626
5916
  return [];
5627
5917
  }
5628
5918
  function measureStubOut(segs) {
@@ -6256,9 +6546,11 @@ function \u4F4D\u7F6E\u3092\u624B\u3067\u66F8\u3044\u305F(n) {
6256
6546
  return n.posX !== void 0 && n.posY !== void 0;
6257
6547
  }
6258
6548
  function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5668) {
6549
+ const textMetrics = laid.textMetrics ?? "proportional";
6259
6550
  const LIFELINE_W_THRESHOLD = 8;
6260
6551
  for (const n of laid.nodes) {
6261
6552
  if (n.w < LIFELINE_W_THRESHOLD) continue;
6553
+ if (n.kind === "station") continue;
6262
6554
  if (n.w < MIN_NODE_W || n.h < MIN_NODE_H) {
6263
6555
  push(
6264
6556
  "node-visibility",
@@ -6266,7 +6558,7 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
6266
6558
  );
6267
6559
  }
6268
6560
  }
6269
- const bboxes = collectBBoxes(laid.lanes, laid.nodes, laid.edges);
6561
+ const bboxes = collectBBoxes(laid.lanes, laid.nodes, laid.edges, textMetrics);
6270
6562
  const collisions = detectCollisions(bboxes, laid.edges);
6271
6563
  for (const c of collisions) {
6272
6564
  const involvesEdgeLabel = c.a.kind === "edge-label" || c.b.kind === "edge-label";
@@ -6280,12 +6572,17 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
6280
6572
  if (n.id.endsWith("-spacer")) continue;
6281
6573
  if (!rendersTitleText(n.kind)) continue;
6282
6574
  if (fitsOwnTitleWidth(n.kind)) continue;
6575
+ if (skipsNodeTitleWidthCheck(n.kind)) continue;
6283
6576
  if (!isRenderedNode(n)) continue;
6284
6577
  const titleTrimmed = n.title?.trim() ?? "";
6285
6578
  if (!titleTrimmed) continue;
6286
6579
  const \u4F59\u767D = drawsTitleOutsideBox(n.kind) ? 0 : TITLE_BOX_PADDING;
6287
6580
  const \u4F7F\u3048\u308B\u5E452 = n.w - \u4F59\u767D;
6288
- const \u5B9F\u5E45 = measureTextWidth(titleTrimmed, { fontSize: titleFontSize(n.kind), bound: "drawn" });
6581
+ const \u5B9F\u5E45 = measureTextWidth(titleTrimmed, {
6582
+ fontSize: titleFontSize(n.kind),
6583
+ bound: "drawn",
6584
+ textMetrics
6585
+ });
6289
6586
  if (titleScalesToFit(n.kind, n.h)) {
6290
6587
  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);
6291
6588
  if (\u7E2E\u3081\u305F\u5927\u304D\u3055 < MIN_TITLE_FONT_SIZE) {
@@ -6353,7 +6650,13 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
6353
6650
  const b\u306F\u672D = n.b.kind === "edge-label";
6354
6651
  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;
6355
6652
  const \u76F8\u624B = \u52D5\u304B\u3059 === n.a ? n.b : n.a;
6356
- 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;
6653
+ const reason = \u52D5\u304B\u3059 !== null ? \u672D\u304C\u52D5\u3051\u306A\u3044\u7406\u7531(
6654
+ \u52D5\u304B\u3059.id,
6655
+ \u76F8\u624B,
6656
+ laid.edges,
6657
+ \u672D\u306E\u969C\u5BB3\u7269,
6658
+ textMetrics
6659
+ ) ?? void 0 : void 0;
6357
6660
  push(
6358
6661
  "clearance",
6359
6662
  `${n.a.kind}:${n.a.id} \u2194 ${n.b.kind}:${n.b.id} gap=${n.gap.toFixed(1)}px (need ${n.required}px)`,
@@ -6367,7 +6670,10 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
6367
6670
  if (!hasRenderedLabel(e)) continue;
6368
6671
  const segs = extractPathSegments(e.d);
6369
6672
  if (segs.length === 0) continue;
6370
- const minDist = measurePathLabelGapSegs(flattenPathSegments(segs), computeLabelBBoxWorld(e));
6673
+ const minDist = measurePathLabelGapSegs(
6674
+ flattenPathSegments(segs),
6675
+ computeLabelBBoxWorld(e, textMetrics)
6676
+ );
6371
6677
  if (!Number.isFinite(minDist)) continue;
6372
6678
  if (minDist > PROXIMITY_ERROR_THRESHOLD) {
6373
6679
  push(
@@ -6417,8 +6723,15 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
6417
6723
  }
6418
6724
  for (const e of laid.edges) {
6419
6725
  if (!hasRenderedLabel(e)) continue;
6420
- const mainW = measureTextWidth(e.label ?? "", { fontSize: EDGE_LABEL_TEXT.main.fontSize });
6421
- const subW = e.sub ? measureTextWidth(e.sub, { fontSize: EDGE_LABEL_TEXT.sub.fontSize, fontFamily: "mono" }) : 0;
6726
+ const mainW = measureTextWidth(e.label ?? "", {
6727
+ fontSize: EDGE_LABEL_TEXT.main.fontSize,
6728
+ textMetrics
6729
+ });
6730
+ const subW = e.sub ? measureTextWidth(e.sub, {
6731
+ fontSize: EDGE_LABEL_TEXT.sub.fontSize,
6732
+ fontFamily: "mono",
6733
+ textMetrics
6734
+ }) : 0;
6422
6735
  const expectedBoxW = Math.max(mainW, subW) + LABEL_PILL_PAD_X * 2;
6423
6736
  const bbox = bboxes.find((b) => b.kind === "edge-label" && b.id === e.id);
6424
6737
  if (!bbox) continue;
@@ -6560,7 +6873,9 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
6560
6873
  }
6561
6874
  }
6562
6875
  for (const n of laid.nodes) {
6563
- const \u843D\u3068\u3057\u305F = labelPlan(n).\u843D\u3068\u3057\u305F.filter((line) => droppedLineIsHidden(n.kind, line));
6876
+ const \u843D\u3068\u3057\u305F = labelPlan(n).\u843D\u3068\u3057\u305F.filter(
6877
+ (line) => droppedLineIsHidden(n.kind, line)
6878
+ );
6564
6879
  if (\u843D\u3068\u3057\u305F.length === 0) continue;
6565
6880
  push(
6566
6881
  "shape-label-dropped",
@@ -6569,7 +6884,7 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
6569
6884
  );
6570
6885
  }
6571
6886
  for (const n of laid.nodes) {
6572
- const \u7BB1 = \u7A4D\u3080\u7BB1\u3092\u96C6\u3081\u308B(n);
6887
+ const \u7BB1 = \u7A4D\u3080\u7BB1\u3092\u96C6\u3081\u308B(n, textMetrics);
6573
6888
  if (\u7BB1.length === 0) continue;
6574
6889
  let \u5BFE\u8C61 = 0;
6575
6890
  const \u843D\u3061\u305F = [];
@@ -6577,7 +6892,7 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
6577
6892
  const \u5BA3\u8A00 = b.\u884C.slice(1).filter((r) => r.text.trim() !== "");
6578
6893
  if (\u5BA3\u8A00.length === 0) continue;
6579
6894
  \u5BFE\u8C61 += 1;
6580
- const \u6B8B\u3063\u305F = new Set(\u7BB1\u306B\u7A4D\u3080(b.\u884C, b.w, b.h).map((r) => r.\u5F79\u5272));
6895
+ const \u6B8B\u3063\u305F = new Set(\u7BB1\u306B\u7A4D\u3080(b.\u884C, b.w, b.h, b.\u6E2C\u308B).map((r) => r.\u5F79\u5272));
6581
6896
  if (\u5BA3\u8A00.every((r) => \u6B8B\u3063\u305F.has(r.\u5F79\u5272))) continue;
6582
6897
  \u843D\u3061\u305F.push({ title: b.\u884C[0]?.text ?? "", h: b.h });
6583
6898
  }
@@ -6884,6 +7199,9 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
6884
7199
  for (let i = 0; i + 1 < sorted.length; i++) {
6885
7200
  const upper = sorted[i];
6886
7201
  const lower = sorted[i + 1];
7202
+ if (upper.cx + upper.w / 2 <= lower.cx - lower.w / 2 || lower.cx + lower.w / 2 <= upper.cx - upper.w / 2) {
7203
+ continue;
7204
+ }
6887
7205
  const upperBottom = upper.cy + upper.h / 2;
6888
7206
  const lowerTop = lower.cy - lower.h / 2;
6889
7207
  const gap = lowerTop - upperBottom;
@@ -7515,11 +7833,18 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
7515
7833
  {
7516
7834
  const crestSpans = (segs, peakY) => {
7517
7835
  const out = [];
7836
+ let \u5186\u5F27\u306E\u59CB\u70B9 = null;
7518
7837
  for (const s of segs) {
7519
- if (Math.abs(s.y1 - s.y2) > 1) continue;
7520
- if (Math.abs(s.y1 - peakY) > 1) continue;
7838
+ if (s.cmd === "A") {
7839
+ \u5186\u5F27\u306E\u59CB\u70B9 ??= { x: s.x1, y: s.y1 };
7840
+ continue;
7841
+ }
7842
+ const \u59CB\u70B9 = \u5186\u5F27\u306E\u59CB\u70B9 ?? { x: s.x1, y: s.y1 };
7843
+ \u5186\u5F27\u306E\u59CB\u70B9 = null;
7844
+ if (Math.abs(\u59CB\u70B9.y - s.y2) > 1) continue;
7845
+ if (Math.abs(\u59CB\u70B9.y - peakY) > 1) continue;
7521
7846
  if (s.cmd !== "L" && !(s.ctrl ?? []).every((c) => Math.abs(c.y - peakY) <= 1)) continue;
7522
- out.push({ minX: Math.min(s.x1, s.x2), maxX: Math.max(s.x1, s.x2) });
7847
+ out.push({ minX: Math.min(\u59CB\u70B9.x, s.x2), maxX: Math.max(\u59CB\u70B9.x, s.x2) });
7523
7848
  }
7524
7849
  return out;
7525
7850
  };
@@ -7630,7 +7955,7 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
7630
7955
  const allowedLanes = /* @__PURE__ */ new Set();
7631
7956
  if (fromNode) allowedLanes.add(fromNode.lane);
7632
7957
  if (toNode) allowedLanes.add(toNode.lane);
7633
- const box = computeLabelBBoxWorld(e);
7958
+ const box = computeLabelBBoxWorld(e, textMetrics);
7634
7959
  for (const lane of laid.lanes) {
7635
7960
  if (allowedLanes.has(lane.id)) continue;
7636
7961
  const side = rectCrossesLaneBorder(box, lane, rangeByLane.get(lane.id));
@@ -7754,7 +8079,7 @@ function pickFreeSides(occupied, count) {
7754
8079
  const \u4F7F\u3046 = \u7A7A\u304D.length > 0 ? \u7A7A\u304D : [SELF_LOOP_SIDE_FALLBACK];
7755
8080
  return Array.from({ length: count }, (_, i) => \u4F7F\u3046[i % \u4F7F\u3046.length]);
7756
8081
  }
7757
- function routeSelfLoopGroup(edges, node, side) {
8082
+ function routeSelfLoopGroup(edges, node, side, textMetrics = "proportional") {
7758
8083
  const horizontal = side === "left" || side === "right";
7759
8084
  const g = sideGeometry(node, side);
7760
8085
  const span = fitSpan(horizontal ? node.h : node.w, SELF_LOOP_SPAN);
@@ -7763,7 +8088,7 @@ function routeSelfLoopGroup(edges, node, side) {
7763
8088
  const \u6700\u5916 = controlOffset(SELF_LOOP_OUT + (edges.length - 1) * SELF_LOOP_STAGGER);
7764
8089
  const \u8A9E\u307E\u3067 = \u6700\u5916 + LABEL_TO_PATH_CLEARANCE;
7765
8090
  const \u8A9E\u5E45 = edges.map(
7766
- (e) => horizontal ? labelPillH(e.sub) : computeLabelBoxW(e.label, e.sub)
8091
+ (e) => horizontal ? labelPillH(e.sub) : computeLabelBoxW(e.label, e.sub, textMetrics)
7767
8092
  );
7768
8093
  const \u4F4D\u7F6E = [];
7769
8094
  let \u7A4D = 0;
@@ -7793,7 +8118,7 @@ function routeSelfLoopGroup(edges, node, side) {
7793
8118
  function isSelfLoop(e) {
7794
8119
  return e.from === e.to;
7795
8120
  }
7796
- function layoutSelfLoops(edges, nodes, occupiedBySide) {
8121
+ function layoutSelfLoops(edges, nodes, occupiedBySide, textMetrics = "proportional") {
7797
8122
  const \u5272\u5F53 = /* @__PURE__ */ new Map();
7798
8123
  for (const edge of edges) {
7799
8124
  if (edge.side) continue;
@@ -7820,7 +8145,7 @@ function layoutSelfLoops(edges, nodes, occupiedBySide) {
7820
8145
  if (\u65E2) \u65E2.edges.push(edge);
7821
8146
  else \u675F.set(key, { node, side, edges: [edge] });
7822
8147
  }
7823
- return [...\u675F.values()].flatMap((b) => routeSelfLoopGroup(b.edges, b.node, b.side));
8148
+ return [...\u675F.values()].flatMap((b) => routeSelfLoopGroup(b.edges, b.node, b.side, textMetrics));
7824
8149
  }
7825
8150
 
7826
8151
  // src/layout/tokens.ts
@@ -7956,6 +8281,8 @@ var TOKENS = {
7956
8281
  // 箱としての最小 (80x40) より大きく、名前を持つ箱 (card 320x150) よりは明らかに小さい
7957
8282
  "mark-start": { w: 96, h: 96 },
7958
8283
  "mark-end": { w: 96, h: 96 },
8284
+ // 路線図の駅 (#996) ... 正方形にして小さな丸が縦横どちらにも歪まないようにする。
8285
+ station: { w: 24, h: 24 },
7959
8286
  // 時系列のやり取り (#578)。 実寸は中身から決まる (`sequenceBoardMetrics`) ので、
7960
8287
  // ここは書かなかった時の受け皿
7961
8288
  "sequence-board": { w: 960, h: 640 }
@@ -7980,6 +8307,7 @@ var LANE_PAD_MIN = 25;
7980
8307
  // src/layout/edges.ts
7981
8308
  var VERTICAL_DETOUR_GAP = 50;
7982
8309
  var VERTICAL_DETOUR_CORNER = 14;
8310
+ var OVERLAY_LABEL_ON_PATH_TOLERANCE = 1;
7983
8311
  function verticalCornerDir(from, to) {
7984
8312
  return to < from ? -1 : 1;
7985
8313
  }
@@ -8035,7 +8363,7 @@ function verticalDetourBlockers(A, B, obstacles) {
8035
8363
  function detourColumnFor(blockers, side) {
8036
8364
  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;
8037
8365
  }
8038
- function layoutEdges(diag, nodes, lanes = []) {
8366
+ function layoutEdges(diag, nodes, lanes = [], textMetrics = "proportional") {
8039
8367
  const labelMarginExtra = (diag.viewport?.labelMargin ?? diag.viewport?.gap ?? DEFAULT_LABEL_MARGIN) - DEFAULT_LABEL_MARGIN;
8040
8368
  const nmap = new Map(nodes.map((n) => [n.id, n]));
8041
8369
  const lmap = new Map(lanes.map((l) => [l.id, l]));
@@ -8063,6 +8391,36 @@ function layoutEdges(diag, nodes, lanes = []) {
8063
8391
  });
8064
8392
  } else if (isSelfLoop(e)) {
8065
8393
  selfLoopEdges.push(e);
8394
+ } else if (e.routing === "curve") {
8395
+ const from = nmap.get(e.from);
8396
+ const to = nmap.get(e.to);
8397
+ if (!from) throw new Error(`cdl layout: edge "${e.id}" \u306E from "${e.from}" \u304C node \u306B\u7121\u3044`);
8398
+ if (!to) throw new Error(`cdl layout: edge "${e.id}" \u306E to "${e.to}" \u304C node \u306B\u7121\u3044`);
8399
+ const c = curvePath(from, to, e, labelMarginExtra, textMetrics);
8400
+ positionedEdges.push({
8401
+ ...e,
8402
+ d: c.d,
8403
+ fromSide: c.fromSide,
8404
+ toSide: c.toSide,
8405
+ labelX: c.labelX + (e.labelOffsetX ?? 0),
8406
+ labelY: c.labelY + (e.labelOffsetY ?? 0),
8407
+ labelAnchor: c.labelAnchor
8408
+ });
8409
+ } else if (e.routing === "metro") {
8410
+ const from = nmap.get(e.from);
8411
+ const to = nmap.get(e.to);
8412
+ if (!from) throw new Error(`cdl layout: edge "${e.id}" \u306E from "${e.from}" \u304C node \u306B\u7121\u3044`);
8413
+ if (!to) throw new Error(`cdl layout: edge "${e.id}" \u306E to "${e.to}" \u304C node \u306B\u7121\u3044`);
8414
+ const m = metroPath(from, to, e, labelMarginExtra, textMetrics);
8415
+ positionedEdges.push({
8416
+ ...e,
8417
+ d: m.d,
8418
+ fromSide: m.fromSide,
8419
+ toSide: m.toSide,
8420
+ labelX: m.labelX + (e.labelOffsetX ?? 0),
8421
+ labelY: m.labelY + (e.labelOffsetY ?? 0),
8422
+ labelAnchor: m.labelAnchor
8423
+ });
8066
8424
  } else {
8067
8425
  autoEdges.push(e);
8068
8426
  }
@@ -8101,7 +8459,7 @@ function layoutEdges(diag, nodes, lanes = []) {
8101
8459
  \u4F7F\u3046(le.from, le.fromSide);
8102
8460
  \u4F7F\u3046(le.to, le.toSide);
8103
8461
  }
8104
- const loopEdges = layoutSelfLoops(selfLoopEdges, nmap, occupiedBySide);
8462
+ const loopEdges = layoutSelfLoops(selfLoopEdges, nmap, occupiedBySide, textMetrics);
8105
8463
  const labelOffsetsByEdgeId = /* @__PURE__ */ new Map();
8106
8464
  const parallelKey = (p) => p.e.from < p.e.to ? `${p.e.from}::${p.e.to}` : `${p.e.to}::${p.e.from}`;
8107
8465
  const byParallel = /* @__PURE__ */ new Map();
@@ -8255,7 +8613,7 @@ function layoutEdges(diag, nodes, lanes = []) {
8255
8613
  const others = nodes.filter((n) => n.id !== c.from && n.id !== c.to);
8256
8614
  if (others.some((n) => segmentsCrossRect(segs, nodeRect(n)))) return true;
8257
8615
  if (!hasRenderedLabel(c.e)) return false;
8258
- const boxW = computeLabelBoxW(c.e.label, c.e.sub);
8616
+ const boxW = computeLabelBoxW(c.e.label, c.e.sub, textMetrics);
8259
8617
  const boxH = labelPillH(c.e.sub);
8260
8618
  const centerX = columnX - (labelPathClearanceHorizontal(c.e) + boxW / 2);
8261
8619
  const pill = { x: centerX - boxW / 2, y: (exitY + returnY) / 2 - boxH / 2, w: boxW, h: boxH };
@@ -8370,7 +8728,8 @@ function layoutEdges(diag, nodes, lanes = []) {
8370
8728
  allOtherNodes,
8371
8729
  { x: endpointOffset.fromDx, y: endpointOffset.fromDy },
8372
8730
  { x: endpointOffset.toDx, y: endpointOffset.toDy },
8373
- avoidRects
8731
+ avoidRects,
8732
+ textMetrics
8374
8733
  );
8375
8734
  const routed1 = route([]);
8376
8735
  const { d, labelX, labelY, labelAnchor, labelAltX } = routed1;
@@ -8426,13 +8785,13 @@ function layoutEdges(diag, nodes, lanes = []) {
8426
8785
  const pillById = /* @__PURE__ */ new Map();
8427
8786
  for (const r of list) {
8428
8787
  if (!hasRenderedLabel(r.e)) continue;
8429
- const w = computeLabelBoxW(r.e.label, r.e.sub);
8788
+ const w = computeLabelBoxW(r.e.label, r.e.sub, textMetrics);
8430
8789
  const h = labelPillH(r.e.sub);
8431
8790
  pillById.set(r.e.id, { x: r.baseLabelX - w / 2, y: r.baseLabelY - h / 2, w, h });
8432
8791
  }
8433
8792
  for (const le of positionedEdges) {
8434
8793
  if (!hasRenderedLabel(le)) continue;
8435
- const w = computeLabelBoxW(le.label, le.sub);
8794
+ const w = computeLabelBoxW(le.label, le.sub, textMetrics);
8436
8795
  const h = labelPillH(le.sub);
8437
8796
  pillById.set(le.id, { x: le.labelX - w / 2, y: le.labelY - h / 2, w, h });
8438
8797
  }
@@ -8462,7 +8821,7 @@ function layoutEdges(diag, nodes, lanes = []) {
8462
8821
  const laneOfNode = new Map(nodes.map((n) => [n.id, n.lane]));
8463
8822
  for (const r of flippable) {
8464
8823
  const ownSegs = segsByEdgeId.get(r.e.id);
8465
- const boxW = computeLabelBoxW(r.e.label, r.e.sub);
8824
+ const boxW = computeLabelBoxW(r.e.label, r.e.sub, textMetrics);
8466
8825
  const boxH = labelPillH(r.e.sub);
8467
8826
  const pillAt = (centerX) => ({
8468
8827
  x: centerX - boxW / 2,
@@ -8507,7 +8866,7 @@ function layoutEdges(diag, nodes, lanes = []) {
8507
8866
  if (list.length < 2) continue;
8508
8867
  const boxes = list.map((r) => ({
8509
8868
  cx: r.baseLabelX,
8510
- halfW: computeLabelBoxW(r.e.label, r.e.sub) / 2
8869
+ halfW: computeLabelBoxW(r.e.label, r.e.sub, textMetrics) / 2
8511
8870
  }));
8512
8871
  const overlapsX = (i, j) => Math.abs(boxes[i].cx - boxes[j].cx) < boxes[i].halfW + boxes[j].halfW + CLEARANCE_LABEL_LABEL;
8513
8872
  const componentOf = list.map((_, i) => i);
@@ -8557,7 +8916,7 @@ function layoutEdges(diag, nodes, lanes = []) {
8557
8916
  r,
8558
8917
  baseX: r.baseLabelX,
8559
8918
  baseY: r.baseLabelY,
8560
- w: computeLabelBoxW(r.e.label, r.e.sub),
8919
+ w: computeLabelBoxW(r.e.label, r.e.sub, textMetrics),
8561
8920
  h: labelPillH(r.e.sub)
8562
8921
  }));
8563
8922
  items.sort((a, b) => a.baseX - b.baseX);
@@ -8669,7 +9028,7 @@ function singleStraightSegment(d) {
8669
9028
  if (x1 === x2 && y1 === y2) return null;
8670
9029
  return { x1, y1, x2, y2 };
8671
9030
  }
8672
- function bowSharedStraightPaths(edges, nodes, skipIds) {
9031
+ function bowSharedStraightPaths(edges, nodes, skipIds, textMetrics = "proportional") {
8673
9032
  const groups = /* @__PURE__ */ new Map();
8674
9033
  for (const e of edges) {
8675
9034
  if (skipIds.has(e.id)) continue;
@@ -8705,7 +9064,7 @@ function bowSharedStraightPaths(edges, nodes, skipIds) {
8705
9064
  )
8706
9065
  );
8707
9066
  const groupIds = new Set(group.map((g) => g.e.id));
8708
- const labelRects = edges.filter((x) => hasRenderedLabel(x) && !groupIds.has(x.id)).map((x) => computeLabelBBoxWorld(x));
9067
+ const labelRects = edges.filter((x) => hasRenderedLabel(x) && !groupIds.has(x.id)).map((x) => computeLabelBBoxWorld(x, textMetrics));
8709
9068
  const nodeRects = nodes.map((n) => ({ x: n.cx - n.w / 2, y: n.cy - n.h / 2, w: n.w, h: n.h }));
8710
9069
  const build = (seg, offset) => {
8711
9070
  const cx = midX + nx * offset * 2;
@@ -8825,8 +9184,8 @@ function sidePoint(n, side) {
8825
9184
  return { x: n.cx + n.w / 2, y: n.cy };
8826
9185
  }
8827
9186
  }
8828
- function routePath(from, to, fromSide, toSide, obstacles = [], detourSide, _fromLane, _toLane, edge, labelObstacles = obstacles, fromOffset = { x: 0, y: 0 }, toOffset = { x: 0, y: 0 }, avoidRects = []) {
8829
- const labelBoxW = edge ? computeLabelBoxW(edge.label, edge.sub) : 0;
9187
+ 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") {
9188
+ const labelBoxW = edge ? computeLabelBoxW(edge.label, edge.sub, textMetrics) : 0;
8830
9189
  const labelHalfW = labelBoxW / 2;
8831
9190
  const labelInit = labelInitClearance(edge);
8832
9191
  const verticalPair = fromSide === "bottom" && toSide === "top" || fromSide === "top" && toSide === "bottom";
@@ -9225,7 +9584,7 @@ function routePath(from, to, fromSide, toSide, obstacles = [], detourSide, _from
9225
9584
  labelAnchor: "middle"
9226
9585
  };
9227
9586
  }
9228
- function repositionParallelLabels(edges, nodes) {
9587
+ function repositionParallelLabels(edges, nodes, textMetrics = "proportional") {
9229
9588
  const allSegs = new Map(
9230
9589
  edges.map((e) => [e.id, flattenPathSegments(extractPathSegments(e.d))])
9231
9590
  );
@@ -9250,7 +9609,7 @@ function repositionParallelLabels(edges, nodes) {
9250
9609
  for (const pair of byPair.values()) {
9251
9610
  if (pair.length < 2) continue;
9252
9611
  const pairOrder = [...pair].sort(compareSharedPairOrder);
9253
- const boxes = pair.map((e) => computeLabelBBoxWorld(e));
9612
+ const boxes = pair.map((e) => computeLabelBBoxWorld(e, textMetrics));
9254
9613
  const componentOf = pair.map((_, i) => i);
9255
9614
  for (let i = 0; i < pair.length; i++) {
9256
9615
  for (let j = i + 1; j < pair.length; j++) {
@@ -9275,17 +9634,27 @@ function repositionParallelLabels(edges, nodes) {
9275
9634
  nodes,
9276
9635
  allEdges: edges,
9277
9636
  allSegs,
9278
- xRange
9637
+ xRange,
9638
+ textMetrics
9279
9639
  });
9280
9640
  for (let i = 0; i < members.length; i++) members[i].labelY = placed[i];
9281
9641
  }
9282
9642
  }
9283
9643
  }
9284
9644
  function placeAvoidingSiblingPaths(args) {
9285
- const { members, pair, pairOrder, nodes, allEdges, allSegs, xRange } = args;
9645
+ const {
9646
+ members,
9647
+ pair,
9648
+ pairOrder,
9649
+ nodes,
9650
+ allEdges,
9651
+ allSegs,
9652
+ xRange,
9653
+ textMetrics = "proportional"
9654
+ } = args;
9286
9655
  const sizes = members.map((e) => labelPillH(e.sub));
9287
9656
  const wants = members.map((e) => e.labelY);
9288
- const boxes = members.map((e) => computeLabelBBoxWorld(e));
9657
+ const boxes = members.map((e) => computeLabelBBoxWorld(e, textMetrics));
9289
9658
  const all = members.map((_, i) => i);
9290
9659
  const spread = (idx) => spreadWithMinimalShift(
9291
9660
  idx.map((i) => ({ want: wants[i], size: sizes[i] })),
@@ -9476,14 +9845,14 @@ function labelRectAt(cx, cy, w, h) {
9476
9845
  function inflate(r, pad) {
9477
9846
  return { x: r.x - pad, y: r.y - pad, w: r.w + pad * 2, h: r.h + pad * 2 };
9478
9847
  }
9479
- function slideLabelsAlongOwnPath(edges, nodes) {
9848
+ function slideLabelsAlongOwnPath(edges, nodes, textMetrics = "proportional") {
9480
9849
  const withLabel = edges.filter((e) => hasRenderedLabel(e));
9481
9850
  if (withLabel.length === 0) return;
9482
9851
  const segsById = /* @__PURE__ */ new Map();
9483
9852
  for (const e of edges) segsById.set(e.id, flattenPathSegments(extractPathSegments(e.d)));
9484
9853
  const nodeRects = nodes.map(nodeRect);
9485
9854
  for (const e of withLabel) {
9486
- const w = computeLabelBoxW(e.label, e.sub);
9855
+ const w = computeLabelBoxW(e.label, e.sub, textMetrics);
9487
9856
  const h = labelPillH(e.sub);
9488
9857
  if (w === 0 || h === 0) continue;
9489
9858
  const own = segsById.get(e.id) ?? [];
@@ -9567,9 +9936,11 @@ function hopEdgeCrossings(edges) {
9567
9936
  ends.set(e.id, pathEnds(segs));
9568
9937
  }
9569
9938
  for (const e of edges) {
9939
+ if (e.routing === "metro") continue;
9570
9940
  if ((e.d.match(/M/g) ?? []).length !== 1) continue;
9571
9941
  const own = extractPathSegments(e.d);
9572
9942
  if (own.length === 0) continue;
9943
+ if (own.some((s) => s.cmd === "A")) continue;
9573
9944
  const myEnds = ends.get(e.id) ?? [];
9574
9945
  const hops = /* @__PURE__ */ new Map();
9575
9946
  for (let i = 0; i < own.length; i++) {
@@ -9657,7 +10028,7 @@ function pathVertices(d) {
9657
10028
  const out = [{ x: first.x1, y: first.y1 }];
9658
10029
  for (let i = 0; i < segs.length; i++) {
9659
10030
  const s = segs[i];
9660
- if (s.cmd === "C") return null;
10031
+ if (s.cmd === "C" || s.cmd === "A") return null;
9661
10032
  if (s.cmd === "Q") {
9662
10033
  const c = s.ctrl?.[0];
9663
10034
  if (!c) return null;
@@ -9720,7 +10091,7 @@ function separateSharedStraightRuns(edges, nodes) {
9720
10091
  const v = pathVertices(e.d);
9721
10092
  if (v && v.length >= 2) verts.set(e.id, v);
9722
10093
  }
9723
- if (verts.size < 2) return;
10094
+ if (verts.size === 0) return;
9724
10095
  const moved = /* @__PURE__ */ new Set();
9725
10096
  const fits = (e, pts, k, ax, delta) => {
9726
10097
  const \u8A66\u3057 = pts.map(
@@ -9738,33 +10109,40 @@ function separateSharedStraightRuns(edges, nodes) {
9738
10109
  for (let j = i + 1; j < edges.length; j++) {
9739
10110
  const \u524D = edges[i];
9740
10111
  const \u5F8C = edges[j];
9741
- const A = verts.get(\u524D.id);
9742
- const B = verts.get(\u5F8C.id);
9743
- if (!A || !B) continue;
9744
- if (\u524D.from === \u5F8C.from) continue;
10112
+ if (\u524D.routing === "metro" && \u5F8C.routing === "metro") continue;
10113
+ const \u56FA\u5B9A = \u5F8C.routing === "metro" ? \u5F8C : \u524D;
10114
+ const \u52D5\u304B\u3059 = \u5F8C.routing === "metro" ? \u524D : \u5F8C;
10115
+ const B = verts.get(\u52D5\u304B\u3059.id);
10116
+ if (!B) continue;
10117
+ const \u56FA\u5B9A\u306E\u89D2 = verts.get(\u56FA\u5B9A.id);
10118
+ 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 }]) : [];
10119
+ if (\u56FA\u5B9A\u306E\u7D4C\u8DEF.length === 0) continue;
10120
+ if (\u56FA\u5B9A.from === \u52D5\u304B\u3059.from) continue;
9745
10121
  for (const ax of [0, 1]) {
9746
- for (let ka = 0; ka + 1 < A.length; ka++) {
9747
- if (!runIsAligned(A, ka, ax)) continue;
9748
- for (let kb = 0; kb + 1 < B.length; kb++) {
9749
- if (!runIsAligned(B, kb, ax)) continue;
9750
- if (kb === 0 || kb + 1 === B.length - 1) continue;
9751
- const \u5EA7\u6A19A = ax === 0 ? A[ka].x : A[ka].y;
9752
- const \u5EA7\u6A19B = ax === 0 ? B[kb].x : B[kb].y;
9753
- if (Math.abs(\u5EA7\u6A19A - \u5EA7\u6A19B) > SHARED_RUN_EPS) continue;
9754
- const sa = runSpan(A, ka, ax);
9755
- const sb = runSpan(B, kb, ax);
9756
- if (Math.min(sa.hi, sb.hi) - Math.max(sa.lo, sb.lo) < SHARED_RUN_MIN) continue;
9757
- for (const delta of [SHARED_RUN_SEPARATION, -SHARED_RUN_SEPARATION]) {
9758
- if (!fits(\u5F8C, B, kb, ax, delta)) continue;
9759
- if (ax === 0) {
9760
- B[kb].x += delta;
9761
- B[kb + 1].x += delta;
9762
- } else {
9763
- B[kb].y += delta;
9764
- B[kb + 1].y += delta;
10122
+ for (const A of \u56FA\u5B9A\u306E\u7D4C\u8DEF) {
10123
+ for (let ka = 0; ka + 1 < A.length; ka++) {
10124
+ if (!runIsAligned(A, ka, ax)) continue;
10125
+ for (let kb = 0; kb + 1 < B.length; kb++) {
10126
+ if (!runIsAligned(B, kb, ax)) continue;
10127
+ if (kb === 0 || kb + 1 === B.length - 1) continue;
10128
+ const \u5EA7\u6A19A = ax === 0 ? A[ka].x : A[ka].y;
10129
+ const \u5EA7\u6A19B = ax === 0 ? B[kb].x : B[kb].y;
10130
+ if (Math.abs(\u5EA7\u6A19A - \u5EA7\u6A19B) > SHARED_RUN_EPS) continue;
10131
+ const sa = runSpan(A, ka, ax);
10132
+ const sb = runSpan(B, kb, ax);
10133
+ if (Math.min(sa.hi, sb.hi) - Math.max(sa.lo, sb.lo) < SHARED_RUN_MIN) continue;
10134
+ for (const delta of [SHARED_RUN_SEPARATION, -SHARED_RUN_SEPARATION]) {
10135
+ if (!fits(\u52D5\u304B\u3059, B, kb, ax, delta)) continue;
10136
+ if (ax === 0) {
10137
+ B[kb].x += delta;
10138
+ B[kb + 1].x += delta;
10139
+ } else {
10140
+ B[kb].y += delta;
10141
+ B[kb + 1].y += delta;
10142
+ }
10143
+ moved.add(\u52D5\u304B\u3059.id);
10144
+ break;
9765
10145
  }
9766
- moved.add(\u5F8C.id);
9767
- break;
9768
10146
  }
9769
10147
  }
9770
10148
  }
@@ -9776,7 +10154,7 @@ function separateSharedStraightRuns(edges, nodes) {
9776
10154
  e.d = verticesToPath(verts.get(e.id));
9777
10155
  }
9778
10156
  }
9779
- function pullOutgoingFirstCorner(edges, nodes) {
10157
+ function pullOutgoingFirstCorner(edges, nodes, textMetrics = "proportional") {
9780
10158
  if (edges.length < 2) return;
9781
10159
  const \u675F = /* @__PURE__ */ new Map();
9782
10160
  const \u540C\u3058\u7D44\u306E\u6570 = /* @__PURE__ */ new Map();
@@ -9791,12 +10169,19 @@ function pullOutgoingFirstCorner(edges, nodes) {
9791
10169
  let \u672D\u3092\u65E7\u7D4C\u8DEF\u3078\u8FFD\u5F93\u6E08\u307F = false;
9792
10170
  for (const list of \u675F.values()) {
9793
10171
  if (list.length < 2) continue;
9794
- const \u4E26\u3073 = list.flatMap((e) => {
10172
+ const \u4E26\u3073 = list.map((e) => {
9795
10173
  const pts = pathVertices(e.d);
9796
- if (!pts || pts.length < 2) return [];
9797
- return [{ e, pts, \u6700\u521D\u306E\u9577\u3055: Math.hypot(pts[1].x - pts[0].x, pts[1].y - pts[0].y) }];
9798
- }).sort((a, b) => b.\u6700\u521D\u306E\u9577\u3055 - a.\u6700\u521D\u306E\u9577\u3055);
10174
+ if (pts && pts.length >= 2) {
10175
+ return { e, pts, \u6700\u521D\u306E\u9577\u3055: Math.hypot(pts[1].x - pts[0].x, pts[1].y - pts[0].y) };
10176
+ }
10177
+ if (e.routing !== "metro") return null;
10178
+ const first = extractPathSegments(e.d)[0];
10179
+ if (!first) return null;
10180
+ return { e, pts: null, \u6700\u521D\u306E\u9577\u3055: Math.hypot(first.x2 - first.x1, first.y2 - first.y1) };
10181
+ }).filter((x) => x !== null).sort((a, b) => b.\u6700\u521D\u306E\u9577\u3055 - a.\u6700\u521D\u306E\u9577\u3055);
9799
10182
  for (const { e, pts, \u6700\u521D\u306E\u9577\u3055 } of \u4E26\u3073.slice(1)) {
10183
+ if (e.routing === "metro") continue;
10184
+ if (!pts) continue;
9800
10185
  if ((\u540C\u3058\u7D44\u306E\u6570.get(`${e.from}->${e.to}`) ?? 0) > 1) continue;
9801
10186
  if (pts.length < 3 || \u6700\u521D\u306E\u9577\u3055 <= EDGE_STUB_OUT + VERTICAL_DETOUR_CORNER) continue;
9802
10187
  const \u6A2A = e.fromSide === "left" || e.fromSide === "right";
@@ -9823,10 +10208,10 @@ function pullOutgoingFirstCorner(edges, nodes) {
9823
10208
  }
9824
10209
  e.d = \u524D;
9825
10210
  if (!\u672D\u3092\u65E7\u7D4C\u8DEF\u3078\u8FFD\u5F93\u6E08\u307F) {
9826
- slideLabelsAlongOwnPath(edges, nodes);
10211
+ slideLabelsAlongOwnPath(edges, nodes, textMetrics);
9827
10212
  \u672D\u3092\u65E7\u7D4C\u8DEF\u3078\u8FFD\u5F93\u6E08\u307F = true;
9828
10213
  }
9829
- const labelBox = computeLabelBBoxWorld(e);
10214
+ const labelBox = computeLabelBBoxWorld(e, textMetrics);
9830
10215
  const label = { x: labelBox.x + labelBox.w / 2, y: labelBox.y + labelBox.h / 2 };
9831
10216
  const \u7DDA\u5206\u307E\u3067\u306E\u8DDD\u96E22 = (a, b) => {
9832
10217
  const dx = b.x - a.x;
@@ -9850,7 +10235,8 @@ var ENDPOINT_FAN_MIN = 20;
9850
10235
  var ENDPOINT_FAN_RUNUP = 40;
9851
10236
  var MIXED_ROOT_OVERLAP_MIN = 24;
9852
10237
  function fanIncomingEndpoints(edges, nodes) {
9853
- if (edges.length < 2) return;
10238
+ const \u7D42\u70B9\u306E\u79FB\u52D5 = /* @__PURE__ */ new Map();
10239
+ if (edges.length < 2) return \u7D42\u70B9\u306E\u79FB\u52D5;
9854
10240
  const nmap = new Map(nodes.map((n) => [n.id, n]));
9855
10241
  const \u5E73\u5766\u306A\u533A\u9593 = new Map(edges.map((e) => [e.id, flattenPathSegments(extractPathSegments(e.d))]));
9856
10242
  const \u8EF8\u306B\u5E73\u884C\u306A\u91CD\u306A\u308A\u9577\u3055 = (\u4E00\u65B9, \u4ED6\u65B9) => {
@@ -9920,6 +10306,7 @@ function fanIncomingEndpoints(edges, nodes) {
9920
10306
  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;
9921
10307
  if (Math.abs(d) < 1e-3) continue;
9922
10308
  const e = \u4E26\u3073[k].e;
10309
+ if (e.routing === "metro") continue;
9923
10310
  const \u524D = e.d;
9924
10311
  const \u524D\u306E\u4EA4\u5DEE = countEdgeCrossings(edges).count;
9925
10312
  const \u9577\u3044\u52A9\u8D70 = \u4E26\u3073[k].\u9577\u3044\u52A9\u8D70;
@@ -9931,6 +10318,72 @@ function fanIncomingEndpoints(edges, nodes) {
9931
10318
  if (countEdgeCrossings(edges).count <= \u524D\u306E\u4EA4\u5DEE) break;
9932
10319
  e.d = \u524D;
9933
10320
  }
10321
+ if (e.d !== \u524D) \u7D42\u70B9\u306E\u79FB\u52D5.set(e.id, \u6A2A ? { dx: 0, dy: d } : { dx: d, dy: 0 });
10322
+ }
10323
+ }
10324
+ return \u7D42\u70B9\u306E\u79FB\u52D5;
10325
+ }
10326
+ function followLabelsToFannedTails(edges, obstacles, shifts, textMetrics = "proportional") {
10327
+ if (shifts.size === 0) return;
10328
+ const \u6E2C\u308A\u65B9 = \u7DDA\u306E\u6E2C\u308A\u65B9\u3092\u4F5C\u308B();
10329
+ const labels = edges.filter(hasRenderedLabel).map((e) => ({
10330
+ kind: "edge-label",
10331
+ id: e.id,
10332
+ ...computeLabelBBoxWorld(e, textMetrics)
10333
+ }));
10334
+ const labelIndexByEdgeId = new Map(labels.map((label, index) => [label.id, index]));
10335
+ const edgeById = new Map(edges.map((e) => [e.id, e]));
10336
+ const \u5468\u308A = {
10337
+ \u7BB1\u305F\u3061: obstacles.filter((o) => o.kind === "node" || o.kind === "lane-label"),
10338
+ labels,
10339
+ edges,
10340
+ edgeById,
10341
+ \u6E2C\u308A\u65B9
10342
+ };
10343
+ for (const e of edges) {
10344
+ const \u79FB\u52D5 = shifts.get(e.id);
10345
+ if (!\u79FB\u52D5 || !hasRenderedLabel(e)) continue;
10346
+ const labelIndex = labelIndexByEdgeId.get(e.id);
10347
+ if (labelIndex === void 0) continue;
10348
+ const \u5143\u306E\u672D = labels[labelIndex];
10349
+ const \u81EA\u5206\u306E\u533A\u9593 = \u6E2C\u308A\u65B9.\u533A\u9593(e.id, e.d);
10350
+ if (e.overlay && measurePathLabelGapSegs(\u81EA\u5206\u306E\u533A\u9593, {
10351
+ x: \u5143\u306E\u672D.x + \u5143\u306E\u672D.w / 2,
10352
+ y: \u5143\u306E\u672D.y + \u5143\u306E\u672D.h / 2,
10353
+ w: 0,
10354
+ h: 0
10355
+ }) <= OVERLAY_LABEL_ON_PATH_TOLERANCE) continue;
10356
+ const \u6700\u5F8C = \u81EA\u5206\u306E\u533A\u9593.at(-1);
10357
+ if (!\u6700\u5F8C) continue;
10358
+ if (!segmentsCrossRect([\u6700\u5F8C], \u5143\u306E\u672D)) continue;
10359
+ const \u5019\u88DCa = {
10360
+ labelX: e.labelX + \u79FB\u52D5.dx,
10361
+ labelY: e.labelY + \u79FB\u52D5.dy,
10362
+ labelAnchor: e.labelAnchor
10363
+ };
10364
+ const \u5019\u88DCa\u306E\u7BB1 = computeLabelBBoxWorld({ ...e, ...\u5019\u88DCa }, textMetrics);
10365
+ const \u6700\u5F8C\u306F\u7E26 = Math.abs(\u6700\u5F8C.x2 - \u6700\u5F8C.x1) <= Math.abs(\u6700\u5F8C.y2 - \u6700\u5F8C.y1);
10366
+ const \u5019\u88DC = [
10367
+ \u5019\u88DCa,
10368
+ {
10369
+ 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,
10370
+ 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),
10371
+ labelAnchor: "middle"
10372
+ }
10373
+ ];
10374
+ for (const c of \u5019\u88DC) {
10375
+ const \u672D = {
10376
+ kind: "edge-label",
10377
+ id: e.id,
10378
+ ...computeLabelBBoxWorld({ ...e, ...c }, textMetrics)
10379
+ };
10380
+ if (segmentsCrossRect([\u6700\u5F8C], \u672D)) continue;
10381
+ if (\u672D\u306E\u79FB\u52D5\u3092\u585E\u3050\u76F8\u624B\u3092\u63A2\u3059(\u5468\u308A, \u5143\u306E\u672D, \u672D) !== null) continue;
10382
+ e.labelX = c.labelX;
10383
+ e.labelY = c.labelY;
10384
+ e.labelAnchor = c.labelAnchor;
10385
+ labels[labelIndex] = \u672D;
10386
+ break;
9934
10387
  }
9935
10388
  }
9936
10389
  }
@@ -9947,7 +10400,7 @@ function \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \
9947
10400
  if ((e.d.match(/M/g) ?? []).length !== 1) return null;
9948
10401
  const segs = extractPathSegments(e.d);
9949
10402
  if (segs.length === 0) return null;
9950
- if (segs.some((s) => s.cmd === "C")) return null;
10403
+ if (segs.some((s) => s.cmd === "C" || s.cmd === "A")) return null;
9951
10404
  const last = segs[segs.length - 1];
9952
10405
  if (last.cmd !== "L") return null;
9953
10406
  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;
@@ -10117,7 +10570,7 @@ function expandLanesForNodes(lanes, nodes) {
10117
10570
  };
10118
10571
  });
10119
10572
  }
10120
- function expandLaneGapsForEdgeLabels(lanes, nodes, edges) {
10573
+ function expandLaneGapsForEdgeLabels(lanes, nodes, edges, textMetrics = "proportional") {
10121
10574
  if (lanes.length < 2) return lanes;
10122
10575
  const layoutedLanes = lanes.filter((l) => !(l.posX !== void 0 && l.posY !== void 0));
10123
10576
  if (layoutedLanes.length < 2) return lanes;
@@ -10133,7 +10586,7 @@ function expandLaneGapsForEdgeLabels(lanes, nodes, edges) {
10133
10586
  const fi = laneIndexById.get(fromLane);
10134
10587
  const ti = laneIndexById.get(toLane);
10135
10588
  if (fi === void 0 || ti === void 0 || fi === ti) continue;
10136
- const labelBoxW = computeLabelBoxW(edge.label, edge.sub);
10589
+ const labelBoxW = computeLabelBoxW(edge.label, edge.sub, textMetrics);
10137
10590
  if (labelBoxW === 0) continue;
10138
10591
  const lo = Math.min(fi, ti);
10139
10592
  const hi = Math.max(fi, ti);
@@ -10238,13 +10691,16 @@ function \u5411\u304D\u3092\u53D6\u308B(end, \u5019\u88DC) {
10238
10691
  }
10239
10692
  return null;
10240
10693
  }
10241
- function \u7AEF\u3067\u306E\u5411\u304D(d, \u7AEF) {
10694
+ function \u7DDA\u306E\u7AEF\u306E\u5411\u304D(d, \u7AEF) {
10242
10695
  const segs = extractPathSegments(d);
10243
10696
  if (segs.length === 0) return null;
10244
10697
  if (\u7AEF === "head") {
10245
10698
  const last = segs[segs.length - 1];
10246
10699
  const end2 = { x: last.x2, y: last.y2 };
10247
- 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 }]);
10700
+ const \u5019\u88DC2 = segs.slice().reverse().flatMap((s) => {
10701
+ const \u5236\u5FA1\u70B9 = s.cmd === "C" ? [s.ctrl?.[1], s.ctrl?.[0]] : s.cmd === "Q" ? [s.ctrl?.[0]] : [];
10702
+ return [...\u5236\u5FA1\u70B9, { x: s.x1, y: s.y1 }];
10703
+ });
10248
10704
  return \u5411\u304D\u3092\u53D6\u308B(end2, \u5019\u88DC2);
10249
10705
  }
10250
10706
  const first = segs[0];
@@ -10252,10 +10708,10 @@ function \u7AEF\u3067\u306E\u5411\u304D(d, \u7AEF) {
10252
10708
  const \u5019\u88DC = segs.flatMap((s) => [...s.ctrl ?? [], { x: s.x2, y: s.y2 }]);
10253
10709
  return \u5411\u304D\u3092\u53D6\u308B(end, \u5019\u88DC);
10254
10710
  }
10255
- function \u7AEF\u306E\u5B57\u3092\u7F6E\u304F(edge, \u7AEF = "head") {
10711
+ function \u7AEF\u306E\u5B57\u3092\u7F6E\u304F(edge, \u7AEF = "head", textMetrics = "proportional") {
10256
10712
  const text = (\u7AEF === "head" ? edge.headLabel : edge.tailLabel)?.trim();
10257
10713
  if (!text) return null;
10258
- const \u5411\u304D = \u7AEF\u3067\u306E\u5411\u304D(edge.d, \u7AEF);
10714
+ const \u5411\u304D = \u7DDA\u306E\u7AEF\u306E\u5411\u304D(edge.d, \u7AEF);
10259
10715
  if (!\u5411\u304D) return null;
10260
10716
  const { end, ux, uy } = \u5411\u304D;
10261
10717
  const bx = end.x - ux * \u7AEF\u306E\u5B57\u3092\u623B\u3059\u8DDD\u96E2;
@@ -10263,7 +10719,8 @@ function \u7AEF\u306E\u5B57\u3092\u7F6E\u304F(edge, \u7AEF = "head") {
10263
10719
  const w = measureTextWidth(text, {
10264
10720
  fontSize: \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055,
10265
10721
  fontWeight: EDGE_LABEL_TEXT.sub.fontWeight,
10266
- fontFamily: "mono"
10722
+ fontFamily: "mono",
10723
+ textMetrics
10267
10724
  });
10268
10725
  const h = \u7BB1\u306E\u9AD8\u3055;
10269
10726
  const \u672D = hasRenderedLabel(edge) && edge.labelX !== void 0 && edge.labelY !== void 0 ? { x: edge.labelX, y: edge.labelY } : null;
@@ -10312,10 +10769,10 @@ function autoStorageHeight(n, defaultH) {
10312
10769
  }
10313
10770
  return Math.max(defaultH, \u5FC5\u8981);
10314
10771
  }
10315
- function autoRowsWidth(n, defaultW) {
10772
+ function autoRowsWidth(n, defaultW, textMetrics = "proportional") {
10316
10773
  if (n.w != null) return n.w;
10317
10774
  if (!n.rows || n.rows.length === 0) return defaultW;
10318
- const required = requiredRowsWidth(n.rows, n.kind);
10775
+ const required = requiredRowsWidth(n.rows, n.kind, textMetrics);
10319
10776
  return Math.max(defaultW, required);
10320
10777
  }
10321
10778
  function \u7BB1\u306E\u9AD8\u30552(n, \u65E2\u5B9Ah) {
@@ -10353,7 +10810,7 @@ function requiredStackGapForEdgeLabels(diag, allStacks) {
10353
10810
  }
10354
10811
  return required;
10355
10812
  }
10356
- function layoutNodes(diag, lanes) {
10813
+ function layoutNodes(diag, lanes, textMetrics) {
10357
10814
  const laneMap = new Map(lanes.map((l) => [l.id, l]));
10358
10815
  const allStacks = Array.from(new Set(diag.nodes.map((n) => n.stack))).sort((a, b) => a - b);
10359
10816
  const rowH = /* @__PURE__ */ new Map();
@@ -10397,7 +10854,7 @@ function layoutNodes(diag, lanes) {
10397
10854
  }
10398
10855
  const size = NODE_SIZE[n.kind];
10399
10856
  if (n.posX !== void 0 && n.posY !== void 0) {
10400
- const w2 = n.posW ?? n.w ?? autoRowsWidth(n, size.w);
10857
+ const w2 = n.posW ?? n.w ?? autoRowsWidth(n, size.w, textMetrics);
10401
10858
  const h2 = n.posH ?? n.h ?? rowH.get(n.stack) ?? size.h;
10402
10859
  out.push({
10403
10860
  ...n,
@@ -10415,7 +10872,7 @@ function layoutNodes(diag, lanes) {
10415
10872
  const \u81EA\u524D\u306E\u9AD8\u3055 = n.rowMarks !== void 0;
10416
10873
  const h = n.h ?? (\u81EA\u524D\u306E\u9AD8\u3055 ? \u7BB1\u306E\u9AD8\u30552(n, size.h) : \u6BB5\u306E\u9AD8\u3055);
10417
10874
  const cy = \u6BB5\u306E\u82AF;
10418
- const w = autoRowsWidth(n, size.w);
10875
+ const w = autoRowsWidth(n, size.w, textMetrics);
10419
10876
  out.push({
10420
10877
  ...n,
10421
10878
  cx,
@@ -10535,10 +10992,16 @@ function applyRowLevelNodeShifts(nodes, lanes, nodeShifts) {
10535
10992
  return moved ? { nodes: outNodes, lanes: outLanes } : null;
10536
10993
  }
10537
10994
  function layout(diag) {
10995
+ const textMetrics = resolveTextMetrics(diag.textMetrics);
10538
10996
  const lanes = layoutLanes(diag);
10539
- const rawNodes = applyFooterShapeDrops(lanes, layoutNodes(diag, lanes));
10997
+ const rawNodes = applyFooterShapeDrops(lanes, layoutNodes(diag, lanes, textMetrics));
10540
10998
  const expandedLanes = expandLanesForNodes(lanes, rawNodes);
10541
- const gapExpandedLanes = expandLaneGapsForEdgeLabels(expandedLanes, rawNodes, diag.edges);
10999
+ const gapExpandedLanes = expandLaneGapsForEdgeLabels(
11000
+ expandedLanes,
11001
+ rawNodes,
11002
+ diag.edges,
11003
+ textMetrics
11004
+ );
10542
11005
  const nodes = rawNodes.map((n) => {
10543
11006
  if (n.posX !== void 0 && n.posY !== void 0) return n;
10544
11007
  const oldLane = lanes.find((l) => l.id === n.lane);
@@ -10547,13 +11010,13 @@ function layout(diag) {
10547
11010
  return { ...n, cx: newLane.x + newLane.width / 2 };
10548
11011
  });
10549
11012
  const containedLanesPre = recomputeContainedLanes(gapExpandedLanes, nodes);
10550
- const edgesPre = layoutEdges(diag, nodes, containedLanesPre);
10551
- const bboxesPre = collectBBoxes(containedLanesPre, nodes, edgesPre);
11013
+ const edgesPre = layoutEdges(diag, nodes, containedLanesPre, textMetrics);
11014
+ const bboxesPre = collectBBoxes(containedLanesPre, nodes, edgesPre, textMetrics);
10552
11015
  const collisionsPre = detectCollisions(bboxesPre, edgesPre);
10553
11016
  const nodesResolved = resolveOverlaps(nodes, collisionsPre);
10554
11017
  const moved = nodesResolved !== nodes;
10555
11018
  const containedLanes = moved ? recomputeContainedLanes(gapExpandedLanes, nodesResolved) : containedLanesPre;
10556
- const edgesAfterMove = moved ? layoutEdges(diag, nodesResolved, containedLanes) : edgesPre;
11019
+ const edgesAfterMove = moved ? layoutEdges(diag, nodesResolved, containedLanes, textMetrics) : edgesPre;
10557
11020
  const chainShiftClearance = Math.max(CLEARANCE_LABEL_LABEL, CLEARANCE_NODE_LABEL);
10558
11021
  let edges;
10559
11022
  let nodesFinal = nodesResolved;
@@ -10564,10 +11027,13 @@ function layout(diag) {
10564
11027
  } else {
10565
11028
  const propagateResult = resolveEdgeLabelOverlapsWithChainAndPropagate(
10566
11029
  edgesAfterMove,
10567
- collectBBoxes(containedLanes, nodesResolved, []).filter(
11030
+ collectBBoxes(containedLanes, nodesResolved, [], textMetrics).filter(
10568
11031
  (b) => b.kind === "node" || b.kind === "lane-label"
10569
11032
  ),
10570
- chainShiftClearance
11033
+ chainShiftClearance,
11034
+ void 0,
11035
+ void 0,
11036
+ textMetrics
10571
11037
  );
10572
11038
  edges = propagateResult.edges;
10573
11039
  if (propagateResult.nodeShifts.size > 0) {
@@ -10579,28 +11045,39 @@ function layout(diag) {
10579
11045
  }
10580
11046
  if (nodesFinal !== nodesResolved) {
10581
11047
  containedLanesFinal = recomputeContainedLanes(laneShiftedBase, nodesFinal);
10582
- edges = layoutEdges(diag, nodesFinal, containedLanesFinal);
11048
+ edges = layoutEdges(diag, nodesFinal, containedLanesFinal, textMetrics);
10583
11049
  }
10584
11050
  }
10585
11051
  const positionedEdgeIds = new Set(
10586
- diag.edges.filter((e) => e.posX1 !== void 0 && e.posY1 !== void 0 && e.posX2 !== void 0 && e.posY2 !== void 0).map((e) => e.id)
11052
+ diag.edges.filter(
11053
+ (e) => e.routing === "curve" || e.routing === "metro" || e.posX1 !== void 0 && e.posY1 !== void 0 && e.posX2 !== void 0 && e.posY2 !== void 0
11054
+ ).map((e) => e.id)
10587
11055
  );
10588
- bowSharedStraightPaths(edges, nodesFinal, positionedEdgeIds);
10589
- pullOutgoingFirstCorner(edges, nodesFinal);
10590
- fanIncomingEndpoints(edges, nodesFinal);
11056
+ bowSharedStraightPaths(edges, nodesFinal, positionedEdgeIds, textMetrics);
11057
+ pullOutgoingFirstCorner(edges, nodesFinal, textMetrics);
11058
+ const fannedTailShifts = fanIncomingEndpoints(edges, nodesFinal);
10591
11059
  separateSharedStraightRuns(edges, nodesFinal);
10592
11060
  hopEdgeCrossings(edges);
10593
- repositionParallelLabels(edges, nodesFinal);
10594
- slideLabelsAlongOwnPath(edges, nodesFinal);
11061
+ const labelClearanceObstacles = collectBBoxes(
11062
+ containedLanesFinal,
11063
+ nodesFinal,
11064
+ [],
11065
+ textMetrics
11066
+ ).filter(
11067
+ (b) => b.kind === "node" || b.kind === "lane-label"
11068
+ );
11069
+ followLabelsToFannedTails(edges, labelClearanceObstacles, fannedTailShifts, textMetrics);
11070
+ repositionParallelLabels(edges, nodesFinal, textMetrics);
11071
+ slideLabelsAlongOwnPath(edges, nodesFinal, textMetrics);
10595
11072
  if (!isChainEdgeLabelDisabled()) {
10596
11073
  edges = resolveLabelClearanceAfterPathPasses(
10597
11074
  edges,
10598
- collectBBoxes(containedLanesFinal, nodesFinal, []).filter(
10599
- (b) => b.kind === "node" || b.kind === "lane-label"
10600
- )
11075
+ labelClearanceObstacles,
11076
+ void 0,
11077
+ textMetrics
10601
11078
  );
10602
11079
  }
10603
- const bboxes = collectBBoxes(containedLanesFinal, nodesFinal, edges);
11080
+ const bboxes = collectBBoxes(containedLanesFinal, nodesFinal, edges, textMetrics);
10604
11081
  const collisions = detectCollisions(bboxes, edges);
10605
11082
  const nearCollisions = detectNearCollisions(bboxes, edges);
10606
11083
  if (collisions.length > 0) {
@@ -10640,6 +11117,8 @@ function layout(diag) {
10640
11117
  // 描画側の固定の字の言語 (#847)。 既定 (`en`) と型の外の値は持たせない = 配置の結果の形を
10641
11118
  // 変更前と揃え、記法の書き損じで一部の字だけ日本語になる形を作らない
10642
11119
  ...resolveLang(diag.lang) === "ja" ? { lang: "ja" } : {},
11120
+ // 既定は持ち越さない。既存の LaidDiagram の形を変えず、等幅の図だけ描画へ伝える
11121
+ ...textMetrics === "monospace" ? { textMetrics: "monospace" } : {},
10643
11122
  // 種類も配色と同じく空の目印を出さない。 遮断をここに揃えると手書きの図にも効く
10644
11123
  ...diag.type ? { type: diag.type } : {},
10645
11124
  bboxes,
@@ -11536,6 +12015,7 @@ function CdlEdgeView({
11536
12015
  "g",
11537
12016
  {
11538
12017
  "data-cdl-edge": edge.id,
12018
+ "data-cdl-routing": edge.routing === "metro" ? "metro" : void 0,
11539
12019
  "data-cdl-from": edge.from,
11540
12020
  "data-cdl-to": edge.to,
11541
12021
  "data-cdl-active": active ? "true" : "false",
@@ -11547,6 +12027,7 @@ function CdlEdgeView({
11547
12027
  "data-cdl-edge-label": edge.label,
11548
12028
  "data-cdl-edge-sub": edge.sub ?? "",
11549
12029
  "data-cdl-tone": edge.tone,
12030
+ "data-cdl-edge-role": edge.role,
11550
12031
  children: [
11551
12032
  isDotted ? /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
11552
12033
  /* @__PURE__ */ jsxRuntime.jsx("path", { id: glowPathId, d: glowPathD, fill: "none", stroke: "none" }),
@@ -11698,11 +12179,12 @@ function CdlEdgeGlowView({
11698
12179
  }
11699
12180
  function CdlEdgeLabelView({
11700
12181
  edge,
11701
- active
12182
+ active,
12183
+ textMetrics = "proportional"
11702
12184
  }) {
11703
12185
  if (!hasRenderedLabel(edge)) return null;
11704
12186
  const color = edgeColor(edge);
11705
- const bbox = computeLabelBBoxWorld(edge);
12187
+ const bbox = computeLabelBBoxWorld(edge, textMetrics);
11706
12188
  const boxW = bbox.w;
11707
12189
  const boxH = bbox.h;
11708
12190
  const boxLeftX = bbox.x - edge.labelX;
@@ -11718,6 +12200,8 @@ function CdlEdgeLabelView({
11718
12200
  "data-cdl-edge-label-for": edge.id,
11719
12201
  "data-cdl-edge-label-text": edge.label,
11720
12202
  "data-cdl-edge-sub-text": edge.sub ?? "",
12203
+ "data-cdl-tone": edge.tone,
12204
+ "data-cdl-edge-role": edge.role,
11721
12205
  children: [
11722
12206
  edge.labelPlate !== false && /* @__PURE__ */ jsxRuntime.jsx(
11723
12207
  "rect",
@@ -11771,9 +12255,10 @@ function CdlEdgeLabelView({
11771
12255
  function CdlEdgeEndLabelView({
11772
12256
  edge,
11773
12257
  active,
11774
- \u7AEF
12258
+ \u7AEF,
12259
+ textMetrics = "proportional"
11775
12260
  }) {
11776
- const \u7F6E\u304D\u5834\u6240 = \u7AEF\u306E\u5B57\u3092\u7F6E\u304F(edge, \u7AEF);
12261
+ const \u7F6E\u304D\u5834\u6240 = \u7AEF\u306E\u5B57\u3092\u7F6E\u304F(edge, \u7AEF, textMetrics);
11777
12262
  if (!\u7F6E\u304D\u5834\u6240) return null;
11778
12263
  const color = edgeColor(edge);
11779
12264
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -11782,6 +12267,8 @@ function CdlEdgeEndLabelView({
11782
12267
  "data-cdl-role": "edge-end-label",
11783
12268
  "data-cdl-edge-end-label-for": edge.id,
11784
12269
  "data-cdl-edge-end": \u7AEF,
12270
+ "data-cdl-tone": edge.tone,
12271
+ "data-cdl-edge-role": edge.role,
11785
12272
  x: \u7F6E\u304D\u5834\u6240.x,
11786
12273
  y: \u7F6E\u304D\u5834\u6240.y,
11787
12274
  fontSize: \u7AEF\u306E\u5B57\u306E\u5927\u304D\u3055,
@@ -12026,12 +12513,18 @@ var SEQ_DOT = 7;
12026
12513
  var SEQ_SELF_W = 52;
12027
12514
  var SEQ_COL_MIN = 200;
12028
12515
  var g4 = (v) => Math.round(v / 4) * 4;
12029
- function sequenceBoardMetrics(data) {
12516
+ function sequenceBoardMetrics(data, textMetrics = "proportional") {
12030
12517
  const \u540D\u5E45 = data.actors.map(
12031
- (a) => Math.max(textWidth(a.name, SEQ_NAME), a.subtitle ? textWidth(a.subtitle, SEQ_SUB) : 0)
12518
+ (a) => Math.max(
12519
+ textWidth(a.name, SEQ_NAME, 0, textMetrics),
12520
+ a.subtitle ? textWidth(a.subtitle, SEQ_SUB, 0, textMetrics) : 0
12521
+ )
12032
12522
  );
12033
12523
  const colW = g4(Math.max(SEQ_COL_MIN, Math.max(0, ...\u540D\u5E45) + SEQ_COL_PAD));
12034
- const \u8A9E\u5E45 = Math.max(0, ...data.messages.map((m) => textWidth(m.label, SEQ_LABEL)));
12524
+ const \u8A9E\u5E45 = Math.max(
12525
+ 0,
12526
+ ...data.messages.map((m) => textWidth(m.label, SEQ_LABEL, 0, textMetrics))
12527
+ );
12035
12528
  const gutter = g4(SEQ_EDGE + SEQ_GUTTER_PAD + \u8A9E\u5E45 + SEQ_GUTTER_GAP);
12036
12529
  const headY = SEQ_EDGE + SEQ_HEAD;
12037
12530
  const rowY = (i) => headY + SEQ_ROW_PAD + i * SEQ_ROW;
@@ -12044,11 +12537,12 @@ function sequenceBoardMetrics(data) {
12044
12537
  }
12045
12538
  function SequenceBoardNode({
12046
12539
  node,
12047
- stateValues
12540
+ stateValues,
12541
+ textMetrics = "proportional"
12048
12542
  }) {
12049
12543
  const data = node.sequenceData;
12050
12544
  if (!data) return /* @__PURE__ */ jsxRuntime.jsx("g", { "data-cdl-role": "sequence-board" });
12051
- const m = sequenceBoardMetrics(data);
12545
+ const m = sequenceBoardMetrics(data, textMetrics);
12052
12546
  const x = node.cx - node.w / 2;
12053
12547
  const y = node.cy - node.h / 2;
12054
12548
  const \u73FE\u5728 = (() => {
@@ -12699,7 +13193,8 @@ function GenericNode({
12699
13193
  active,
12700
13194
  value,
12701
13195
  stateValues,
12702
- \u5024\u306E\u540D\u524D
13196
+ \u5024\u306E\u540D\u524D,
13197
+ textMetrics = "proportional"
12703
13198
  }) {
12704
13199
  const base = STYLES[node.kind] ?? FALLBACK;
12705
13200
  const toned = toneColor3(node.tone);
@@ -12838,7 +13333,7 @@ function GenericNode({
12838
13333
  const resolved = node.rows.map((row) => interpolate(row, stateValues, \u5024\u306E\u540D\u524D));
12839
13334
  const splits = resolved.map(splitRow);
12840
13335
  const leftMaxWidth = splits.reduce(
12841
- (m, s) => Math.max(m, rowColumnWidth(s.left, GENERIC_ROW_LEFT_SIZE_PX, false)),
13336
+ (m, s) => Math.max(m, rowColumnWidth(s.left, GENERIC_ROW_LEFT_SIZE_PX, false, textMetrics)),
12842
13337
  0
12843
13338
  );
12844
13339
  const rightColX = ROW_PAD_X_PX + leftMaxWidth + ROW_COL_GAP_PX;
@@ -12964,17 +13459,22 @@ function DynShapeNode({
12964
13459
  return renderPolygon(shape, cx, cy, stateValues, fillColor, strokeColor, activeOpacity);
12965
13460
  }
12966
13461
  })();
13462
+ const \u63C3\u3048 = \u7BB1\u3044\u3063\u3071\u3044\u306B\u63CF\u304F2(shape.kind) ? "start" : "middle";
13463
+ return renderShapeWithOutsideLabels(\u5F62, node, \u63C3\u3048);
13464
+ }
13465
+ function renderShapeWithOutsideLabels(\u5F62, node, \u63C3\u3048) {
13466
+ const cx = node.cx;
13467
+ const y = node.cy - node.h / 2;
12967
13468
  const \u540D\u524D = (node.title ?? "").trim();
12968
13469
  const \u5024 = (node.subtitle ?? "").trim();
12969
13470
  if (\u540D\u524D === "" && \u5024 === "") return \u5F62;
12970
- const \u63C3\u3048 = \u7BB1\u3044\u3063\u3071\u3044\u306B\u63CF\u304F2(shape.kind) ? "start" : "middle";
12971
13471
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
12972
13472
  \u5F62,
12973
13473
  \u540D\u524D !== "" && /* @__PURE__ */ jsxRuntime.jsx(
12974
13474
  "text",
12975
13475
  {
12976
13476
  "data-cdl-role": "shape-name",
12977
- x: \u63C3\u3048 === "start" ? x : cx,
13477
+ x: \u63C3\u3048 === "start" ? node.cx - node.w / 2 : cx,
12978
13478
  y: y - NAME_GAP,
12979
13479
  textAnchor: \u63C3\u3048,
12980
13480
  fontSize: 13,
@@ -12988,7 +13488,7 @@ function DynShapeNode({
12988
13488
  {
12989
13489
  "data-cdl-role": "shape-value",
12990
13490
  x: cx,
12991
- y: y + h + VALUE_GAP,
13491
+ y: y + node.h + VALUE_GAP,
12992
13492
  textAnchor: "middle",
12993
13493
  fontSize: 12,
12994
13494
  fill: "var(--cdl-text-dim, #5a6270)",
@@ -13238,6 +13738,27 @@ function interpolateColor(template, stateValues, fallback) {
13238
13738
  if (!template) return fallback;
13239
13739
  return interpolate(template, stateValues);
13240
13740
  }
13741
+ var STATION_STROKE_ACTIVE = 4;
13742
+ var STATION_STROKE_IDLE = 3;
13743
+ var STATION_DEFAULT = "var(--cdl-tone-accent, #2d6a8f)";
13744
+ function StationNode({ node, active }) {
13745
+ const strokeWidth = active ? STATION_STROKE_ACTIVE : STATION_STROKE_IDLE;
13746
+ const radius = Math.max(0, Math.min(node.w, node.h) / 2 - strokeWidth / 2);
13747
+ const \u5F62 = /* @__PURE__ */ jsxRuntime.jsx(
13748
+ "circle",
13749
+ {
13750
+ "data-cdl-role": "node-body",
13751
+ "data-cdl-mark": "station",
13752
+ cx: node.cx,
13753
+ cy: node.cy,
13754
+ r: radius,
13755
+ fill: "var(--cdl-node-fill, #ffffff)",
13756
+ stroke: nodeAccent(node, STATION_DEFAULT),
13757
+ strokeWidth
13758
+ }
13759
+ );
13760
+ return renderShapeWithOutsideLabels(\u5F62, node, "middle");
13761
+ }
13241
13762
 
13242
13763
  // src/kinds/label-stack.ts
13243
13764
  function \u540D\u672D\u306E\u6BB5\u3092\u307B\u3069\u304F(\u771F\u306Ey, \u9593\u9694, \u4E0A\u9650, \u4E0B\u9650) {
@@ -13296,8 +13817,8 @@ function \u5024\u3068\u5272\u5408\u306E\u6587\u5B57(\u5024, \u5272\u5408, \u5408
13296
13817
  return \u7D44.\u5024 === null ? \u7D44.\u5272\u5408 : `${\u7D44.\u5024} ${\u7D44.\u5272\u5408}`;
13297
13818
  }
13298
13819
  var \u7A74\u306B\u5BFE\u3059\u308B\u4E0A\u9650 = 0.8;
13299
- function \u4E2D\u592E\u306E\u5B57(\u6BD4\u4F8B\u3057\u305F\u5927\u304D\u3055, \u7A74\u306E\u534A\u5F84, \u6587) {
13300
- 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);
13820
+ function \u4E2D\u592E\u306E\u5B57(\u6BD4\u4F8B\u3057\u305F\u5927\u304D\u3055, \u7A74\u306E\u534A\u5F84, \u6587, textMetrics = "proportional") {
13821
+ 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);
13301
13822
  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);
13302
13823
  }
13303
13824
  function ChartPieNode({
@@ -13305,7 +13826,8 @@ function ChartPieNode({
13305
13826
  active,
13306
13827
  stateValues = {},
13307
13828
  drawing = false,
13308
- progress = 1
13829
+ progress = 1,
13830
+ textMetrics = "proportional"
13309
13831
  }) {
13310
13832
  const instanceId = react.useId().replace(/[^A-Za-z0-9_-]/g, "");
13311
13833
  const x0 = node.cx - node.w / 2;
@@ -13336,15 +13858,26 @@ function ChartPieNode({
13336
13858
  return `${\u5B9F\u5024\u8868\u8A18(d.value)}%` === \u5272\u5408\u306E\u6587\u5B57[i] ? \u540D : `${\u540D} ${\u5B9F\u5024\u8868\u8A18(d.value)}`;
13337
13859
  });
13338
13860
  if (\u5F62 !== "ring") {
13339
- const \u5171\u901A = { node, active, data, \u5272\u5408: \u4ECA\u306E\u5272\u5408, x0, y0, drawing, progress, instanceId };
13861
+ const \u5171\u901A = {
13862
+ node,
13863
+ active,
13864
+ data,
13865
+ \u5272\u5408: \u4ECA\u306E\u5272\u5408,
13866
+ x0,
13867
+ y0,
13868
+ drawing,
13869
+ progress,
13870
+ instanceId,
13871
+ textMetrics
13872
+ };
13340
13873
  return \u5F62 === "arcs" ? \u5F27\u306E\u5F62(\u5171\u901A) : \u8868\u306E\u5F62(\u5171\u901A);
13341
13874
  }
13342
13875
  const \u540D\u672D\u5E45 = Math.max(
13343
13876
  0,
13344
13877
  ...data.map(
13345
13878
  (_d, i) => Math.max(
13346
- textWidth(\u5272\u5408\u306E\u6587\u5B57[i] ?? "", \u5272\u5408\u306E\u7D1A),
13347
- textWidth(\u540D\u524D\u306E\u6587\u5B57[i] ?? "", \u540D\u524D\u306E\u7D1A)
13879
+ textWidth(\u5272\u5408\u306E\u6587\u5B57[i] ?? "", \u5272\u5408\u306E\u7D1A, 0, textMetrics),
13880
+ textWidth(\u540D\u524D\u306E\u6587\u5B57[i] ?? "", \u540D\u524D\u306E\u7D1A, 0, textMetrics)
13348
13881
  )
13349
13882
  )
13350
13883
  );
@@ -13359,8 +13892,8 @@ function ChartPieNode({
13359
13892
  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) : [];
13360
13893
  const \u7A74 = \u524D\u3042\u308A ? \u524D\u306E\u5185\u534A\u5F84 : \u5916\u306E\u5185\u534A\u5F84;
13361
13894
  const \u5408\u8A08\u306E\u6587 = \u5B9F\u5024\u8868\u8A18(Math.round(\u524D\u3042\u308A ? \u4ECA\u306E\u5408\u8A08 : total));
13362
- const \u5408\u8A08\u306E\u5B57 = \u4E2D\u592E\u306E\u5B57(Math.round(radius * 0.26), \u7A74, \u5408\u8A08\u306E\u6587);
13363
- const \u898B\u51FA\u3057\u306E\u5B572 = \u4E2D\u592E\u306E\u5B57(Math.round(radius * 0.12), \u7A74, "\u5408\u8A08");
13895
+ const \u5408\u8A08\u306E\u5B57 = \u4E2D\u592E\u306E\u5B57(Math.round(radius * 0.26), \u7A74, \u5408\u8A08\u306E\u6587, textMetrics);
13896
+ const \u898B\u51FA\u3057\u306E\u5B572 = \u4E2D\u592E\u306E\u5B57(Math.round(radius * 0.12), \u7A74, "\u5408\u8A08", textMetrics);
13364
13897
  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);
13365
13898
  const slices = \u8F2A\u3092\u7D44\u3080(data, cx, cy, radius, \u5916\u306E\u5185\u534A\u5F84, \u4ECA\u306E\u5272\u5408);
13366
13899
  const \u958B\u304D = \u9032\u307F\u3092\u7573\u3080(drawing, progress);
@@ -13543,14 +14076,24 @@ function \u67A0(node, active) {
13543
14076
  }
13544
14077
  );
13545
14078
  }
13546
- function \u5F27\u306E\u5F62({ node, active, data, \u5272\u5408, x0, y0, drawing, progress }) {
14079
+ function \u5F27\u306E\u5F62({
14080
+ node,
14081
+ active,
14082
+ data,
14083
+ \u5272\u5408,
14084
+ x0,
14085
+ y0,
14086
+ drawing,
14087
+ progress,
14088
+ textMetrics
14089
+ }) {
13547
14090
  const PAD = 20;
13548
14091
  const \u540D\u524D\u306E\u7D1A = 14;
13549
14092
  const \u5272\u5408\u306E\u7D1A = 24;
13550
14093
  const \u5370\u304B\u3089\u540D\u524D\u307E\u30672 = 18;
13551
14094
  const \u540D\u524D\u304B\u3089\u5272\u5408\u307E\u3067 = 24;
13552
14095
  const \u5272\u5408\u306E\u6587\u5B57 = \u5272\u5408.map(\u5272\u5408\u8868\u8A18);
13553
- 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)));
14096
+ 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)));
13554
14097
  const \u7E26\u304B\u3089 = (node.h - PAD * 2) / 2;
13555
14098
  const \u6A2A\u304B\u3089 = (node.w - PAD * 2 - \u4E00\u89A7\u5E45 - 28) / 2;
13556
14099
  const R = Math.max(24, Math.min(\u7E26\u304B\u3089, \u6A2A\u304B\u3089));
@@ -13636,7 +14179,18 @@ function \u5F27\u306E\u5F62({ node, active, data, \u5272\u5408, x0, y0, drawing,
13636
14179
  })
13637
14180
  ] });
13638
14181
  }
13639
- function \u8868\u306E\u5F62({ node, active, data, \u5272\u5408, x0, y0, drawing, progress, instanceId }) {
14182
+ function \u8868\u306E\u5F62({
14183
+ node,
14184
+ active,
14185
+ data,
14186
+ \u5272\u5408,
14187
+ x0,
14188
+ y0,
14189
+ drawing,
14190
+ progress,
14191
+ instanceId,
14192
+ textMetrics
14193
+ }) {
13640
14194
  const PAD = 20;
13641
14195
  const \u898B\u51FA\u3057\u306E\u7D1A = 11;
13642
14196
  const \u540D\u524D\u306E\u7D1A = 15;
@@ -13645,9 +14199,18 @@ function \u8868\u306E\u5F62({ node, active, data, \u5272\u5408, x0, y0, drawing,
13645
14199
  const \u5370\u304B\u3089\u540D\u524D\u307E\u30672 = 18;
13646
14200
  const \u5272\u5408\u306E\u6587\u5B57 = \u5272\u5408.map(\u5272\u5408\u8868\u8A18);
13647
14201
  const \u5B9F\u6570\u306E\u6587\u5B57 = data.map((d) => \u5B9F\u5024\u8868\u8A18(d.value));
13648
- const \u540D\u524D\u5E45 = Math.max(0, ...data.map((d) => textWidth(d.label ?? "", \u540D\u524D\u306E\u7D1A)));
13649
- 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)));
13650
- 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)));
14202
+ const \u540D\u524D\u5E45 = Math.max(
14203
+ 0,
14204
+ ...data.map((d) => textWidth(d.label ?? "", \u540D\u524D\u306E\u7D1A, 0, textMetrics))
14205
+ );
14206
+ const \u5272\u5408\u5E45 = Math.max(
14207
+ textWidth("\u5272\u5408", \u898B\u51FA\u3057\u306E\u7D1A, 0, textMetrics),
14208
+ ...\u5272\u5408\u306E\u6587\u5B57.map((t) => textWidth(t, \u5272\u5408\u306E\u7D1A, 0, textMetrics))
14209
+ );
14210
+ const \u5B9F\u6570\u5E45 = Math.max(
14211
+ textWidth("\u5024", \u898B\u51FA\u3057\u306E\u7D1A, 0, textMetrics),
14212
+ ...\u5B9F\u6570\u306E\u6587\u5B57.map((t) => textWidth(t, \u5B9F\u6570\u306E\u7D1A, 0, textMetrics))
14213
+ );
13651
14214
  const \u8868\u5E45 = 10 + \u5370\u304B\u3089\u540D\u524D\u307E\u30672 + \u540D\u524D\u5E45 + 28 + \u5272\u5408\u5E45 + 24 + \u5B9F\u6570\u5E45;
13652
14215
  const \u7E26\u304B\u3089 = (node.h - PAD * 2) / 2;
13653
14216
  const \u6A2A\u304B\u3089 = (node.w - PAD * 2 - \u8868\u5E45 - 28) / 2;
@@ -13656,8 +14219,8 @@ function \u8868\u306E\u5F62({ node, active, data, \u5272\u5408, x0, y0, drawing,
13656
14219
  const cx = PAD + R;
13657
14220
  const cy = node.h / 2;
13658
14221
  const \u5408\u8A08\u306E\u6587 = \u5B9F\u5024\u8868\u8A18(Math.round(data.reduce((acc, d) => acc + d.value, 0)));
13659
- const \u5408\u8A08\u306E\u5B57 = \u4E2D\u592E\u306E\u5B57(Math.round(R * 0.26), \u5185\u534A\u5F84, \u5408\u8A08\u306E\u6587);
13660
- const \u898B\u51FA\u3057\u306E\u5B572 = \u4E2D\u592E\u306E\u5B57(Math.round(R * 0.12), \u5185\u534A\u5F84, "\u5408\u8A08");
14222
+ const \u5408\u8A08\u306E\u5B57 = \u4E2D\u592E\u306E\u5B57(Math.round(R * 0.26), \u5185\u534A\u5F84, \u5408\u8A08\u306E\u6587, textMetrics);
14223
+ const \u898B\u51FA\u3057\u306E\u5B572 = \u4E2D\u592E\u306E\u5B57(Math.round(R * 0.12), \u5185\u534A\u5F84, "\u5408\u8A08", textMetrics);
13661
14224
  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);
13662
14225
  const \u8868\u5DE6 = node.w - PAD - \u8868\u5E45;
13663
14226
  const \u53F3\u7AEF = node.w - PAD;
@@ -13788,7 +14351,8 @@ function ChartGaugeNode({
13788
14351
  active,
13789
14352
  stateValues = {},
13790
14353
  drawing = false,
13791
- progress = 1
14354
+ progress = 1,
14355
+ textMetrics = "proportional"
13792
14356
  }) {
13793
14357
  const x0 = node.cx - node.w / 2;
13794
14358
  const y0 = node.cy - node.h / 2;
@@ -13807,7 +14371,10 @@ function ChartGaugeNode({
13807
14371
  const \u533A\u753B\u306E\u9593 = 12;
13808
14372
  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);
13809
14373
  const \u5272\u308A\u4ED8\u3051\u308B = (\u4EF6\u305F\u3061) => {
13810
- 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;
14374
+ const \u5E45 = Math.max(
14375
+ \u5370\u306E\u5E452,
14376
+ ...\u4EF6\u305F\u3061.map((d) => textWidth(\u6570\u5024\u306E\u884C(d), \u6570\u5024\u306E\u7D1A, 0, textMetrics))
14377
+ ) + \u533A\u753B\u306E\u9593;
13811
14378
  const \u884C\u306E\u4EF6\u65702 = Math.min(
13812
14379
  Math.max(1, Math.floor(\u4F7F\u3048\u308B\u5E452 / Math.max(\u5E45, 1))),
13813
14380
  Math.max(\u4EF6\u305F\u3061.length, 1)
@@ -13882,7 +14449,7 @@ function ChartGaugeNode({
13882
14449
  return { d, frac, path: \u6247\u306E\u9053(a0, a1, \u524D\u306E\u5185\u534A\u5F84, \u524D\u306E\u5916\u534A\u5F84) };
13883
14450
  });
13884
14451
  const \u5408\u8A08\u306E\u6587\u5B57 = \u5B9F\u5024\u8868\u8A18(Math.round(total));
13885
- const \u5358\u4F4D\u5E45 = Math.max(textWidth(\u5408\u8A08\u306E\u6587\u5B57, 100), 1) / 100;
14452
+ const \u5358\u4F4D\u5E45 = Math.max(textWidth(\u5408\u8A08\u306E\u6587\u5B57, 100, 0, textMetrics), 1) / 100;
13886
14453
  const \u7D1A\u306E\u5019\u88DC = Math.min(
13887
14454
  // 横 = 字の上の角が内側の円に入る大きさ
13888
14455
  \u5185\u534A\u5F84 / Math.sqrt((\u5358\u4F4D\u5E45 / 2) ** 2 + 1.25 ** 2),
@@ -13975,7 +14542,7 @@ function ChartGaugeNode({
13975
14542
  const y = \u5185\u8A33\u306Ey + \u6BB5\u306E\u9AD8\u3055 * \u6BB5;
13976
14543
  const \u53CE\u307E\u308B\u5E45 = \u5185\u8A33\u306E\u5E45 - \u533A\u753B\u306E\u9593;
13977
14544
  const \u6570\u306E\u884C = \u5185\u8A33\u306E\u6570\u5024[idx] ?? "";
13978
- const \u5207\u3063\u305F\u6570\u306E\u884C = \u5207\u308A\u8A70\u3081\u308B(\u6570\u306E\u884C, \u53CE\u307E\u308B\u5E45, \u6570\u5024\u306E\u7D1A);
14545
+ const \u5207\u3063\u305F\u6570\u306E\u884C = \u5207\u308A\u8A70\u3081\u308B(\u6570\u306E\u884C, \u53CE\u307E\u308B\u5E45, \u6570\u5024\u306E\u7D1A, textMetrics);
13979
14546
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { "data-cdl-role": "chart-gauge-item", children: [
13980
14547
  /* @__PURE__ */ jsxRuntime.jsx(
13981
14548
  "rect",
@@ -13996,7 +14563,7 @@ function ChartGaugeNode({
13996
14563
  fontSize: \u540D\u524D\u306E\u7D1A,
13997
14564
  fontWeight: 700,
13998
14565
  fill: "var(--cdl-text, #1a1f2a)",
13999
- children: \u5207\u308A\u8A70\u3081\u308B(d.label ?? "", \u53CE\u307E\u308B\u5E45, \u540D\u524D\u306E\u7D1A)
14566
+ children: \u5207\u308A\u8A70\u3081\u308B(d.label ?? "", \u53CE\u307E\u308B\u5E45, \u540D\u524D\u306E\u7D1A, textMetrics)
14000
14567
  }
14001
14568
  ),
14002
14569
  /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx(
@@ -14014,12 +14581,12 @@ function ChartGaugeNode({
14014
14581
  function \u6975(cx, cy, r, a) {
14015
14582
  return { x: cx + r * Math.cos(a), y: cy + r * Math.sin(a) };
14016
14583
  }
14017
- function \u5207\u308A\u8A70\u3081\u308B(s, \u4E0A\u9650, \u7D1A) {
14018
- if (\u4E0A\u9650 <= 0 || textWidth(s, \u7D1A) <= \u4E0A\u9650) return s;
14019
- const \u8A18\u53F7\u5E45 = textWidth("\u2026", \u7D1A);
14584
+ function \u5207\u308A\u8A70\u3081\u308B(s, \u4E0A\u9650, \u7D1A, textMetrics = "proportional") {
14585
+ if (\u4E0A\u9650 <= 0 || textWidth(s, \u7D1A, 0, textMetrics) <= \u4E0A\u9650) return s;
14586
+ const \u8A18\u53F7\u5E45 = textWidth("\u2026", \u7D1A, 0, textMetrics);
14020
14587
  let out = "";
14021
14588
  for (const c of s) {
14022
- if (textWidth(out + c, \u7D1A) + \u8A18\u53F7\u5E45 > \u4E0A\u9650) break;
14589
+ if (textWidth(out + c, \u7D1A, 0, textMetrics) + \u8A18\u53F7\u5E45 > \u4E0A\u9650) break;
14023
14590
  out += c;
14024
14591
  }
14025
14592
  return `${out}\u2026`;
@@ -14033,7 +14600,8 @@ function ChartRadialNode({
14033
14600
  active,
14034
14601
  stateValues = {},
14035
14602
  drawing = false,
14036
- progress = 1
14603
+ progress = 1,
14604
+ textMetrics = "proportional"
14037
14605
  }) {
14038
14606
  const x0 = node.cx - node.w / 2;
14039
14607
  const y0 = node.cy - node.h / 2;
@@ -14051,7 +14619,10 @@ function ChartRadialNode({
14051
14619
  const \u4E00\u89A7\u306E\u5E45 = \u5370\u306E\u5E45 + Math.max(
14052
14620
  0,
14053
14621
  ...data.map(
14054
- (d, i) => Math.max(textWidth(d.label ?? "", \u540D\u524D\u306E\u7D1A), textWidth(\u6570\u5024\u306E\u6587\u5B57[i] ?? "", \u6570\u5024\u306E\u7D1A))
14622
+ (d, i) => Math.max(
14623
+ textWidth(d.label ?? "", \u540D\u524D\u306E\u7D1A, 0, textMetrics),
14624
+ textWidth(\u6570\u5024\u306E\u6587\u5B57[i] ?? "", \u6570\u5024\u306E\u7D1A, 0, textMetrics)
14625
+ )
14055
14626
  )
14056
14627
  );
14057
14628
  const \u5F27\u306B\u4F7F\u3048\u308B\u5E45 = node.w - PAD * 2 - \u4E00\u89A7\u306E\u5E45 - \u4E00\u89A7\u3068\u5F27\u306E\u9593;
@@ -14198,7 +14769,8 @@ function arcColor2(tone, idx) {
14198
14769
  function ChartStatNode({
14199
14770
  node,
14200
14771
  active,
14201
- stateValues = {}
14772
+ stateValues = {},
14773
+ textMetrics = "proportional"
14202
14774
  }) {
14203
14775
  const x0 = node.cx - node.w / 2;
14204
14776
  const y0 = node.cy - node.h / 2;
@@ -14227,7 +14799,13 @@ function ChartStatNode({
14227
14799
  const frac = total > 0 ? d.value / total : 0;
14228
14800
  const \u8272 = \u5370\u306E\u8272(d.tone, idx);
14229
14801
  const \u6570\u5024 = \u5B9F\u5024\u8868\u8A18(d.value);
14230
- 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);
14802
+ const \u6570\u5024\u306E\u7D1A = \u53CE\u3081\u308B\u7D1A(
14803
+ \u6570\u5024,
14804
+ \u67A02.w - \u533A\u753B.\u4F59\u767D * 2,
14805
+ \u533A\u753B.\u6570\u5024\u306E\u7D1A,
14806
+ \u533A\u753B.\u540D\u524D\u306E\u7D1A + 1,
14807
+ textMetrics
14808
+ );
14231
14809
  return /* @__PURE__ */ jsxRuntime.jsxs(
14232
14810
  "g",
14233
14811
  {
@@ -14284,7 +14862,8 @@ function ChartStatNode({
14284
14862
  `\u524D ${\u5B9F\u5024\u8868\u8A18(d.previous)}`,
14285
14863
  \u67A02.w - \u533A\u753B.\u4F59\u767D * 2,
14286
14864
  \u533A\u753B.\u524D\u306E\u7D1A,
14287
- 8
14865
+ 8,
14866
+ textMetrics
14288
14867
  ),
14289
14868
  textAnchor: "middle",
14290
14869
  fill: "var(--cdl-text-dim, #5a6270)",
@@ -14373,9 +14952,9 @@ function \u533A\u753B\u306E\u5272\u4ED8(w, h, \u4EF6\u6570, \u524D\u3092\u51FA\u
14373
14952
  \u67A0: (idx) => ({ x: \u5E45 * idx, y: 0, w: \u5E45, h })
14374
14953
  };
14375
14954
  }
14376
- function \u53CE\u3081\u308B\u7D1A(\u5B572, \u4F7F\u3048\u308B\u5E452, \u521D\u671F, \u4E0B\u9650) {
14955
+ function \u53CE\u3081\u308B\u7D1A(\u5B572, \u4F7F\u3048\u308B\u5E452, \u521D\u671F, \u4E0B\u9650, textMetrics = "proportional") {
14377
14956
  let \u7D1A = \u521D\u671F;
14378
- while (\u7D1A > \u4E0B\u9650 && textWidth(\u5B572, \u7D1A) > \u4F7F\u3048\u308B\u5E452) \u7D1A -= 1;
14957
+ while (\u7D1A > \u4E0B\u9650 && textWidth(\u5B572, \u7D1A, 0, textMetrics) > \u4F7F\u3048\u308B\u5E452) \u7D1A -= 1;
14379
14958
  return \u7D1A;
14380
14959
  }
14381
14960
  function \u5F27\u306E\u90533(cx, cy, r, \u5272\u5408) {
@@ -14410,7 +14989,8 @@ function ChartWaffleNode({
14410
14989
  active,
14411
14990
  stateValues = {},
14412
14991
  drawing = false,
14413
- progress = 1
14992
+ progress = 1,
14993
+ textMetrics = "proportional"
14414
14994
  }) {
14415
14995
  const x0 = node.cx - node.w / 2;
14416
14996
  const y0 = node.cy - node.h / 2;
@@ -14429,7 +15009,10 @@ function ChartWaffleNode({
14429
15009
  const \u4E00\u89A7\u306E\u5E45 = \u5370\u306E\u5E452 + Math.max(
14430
15010
  0,
14431
15011
  ...data.map(
14432
- (d, i) => Math.max(textWidth(d.label ?? "", \u540D\u524D\u306E\u7D1A), textWidth(\u6570\u5024\u306E\u6587\u5B57[i] ?? "", \u6570\u5024\u306E\u7D1A))
15012
+ (d, i) => Math.max(
15013
+ textWidth(d.label ?? "", \u540D\u524D\u306E\u7D1A, 0, textMetrics),
15014
+ textWidth(\u6570\u5024\u306E\u6587\u5B57[i] ?? "", \u6570\u5024\u306E\u7D1A, 0, textMetrics)
15015
+ )
14433
15016
  )
14434
15017
  );
14435
15018
  const \u4F7F\u3048\u308B\u9AD8\u3055 = node.h - PAD * 2;
@@ -14531,7 +15114,8 @@ function ChartStackedBarNode({
14531
15114
  active,
14532
15115
  stateValues = {},
14533
15116
  drawing = false,
14534
- progress = 1
15117
+ progress = 1,
15118
+ textMetrics = "proportional"
14535
15119
  }) {
14536
15120
  const x0 = node.cx - node.w / 2;
14537
15121
  const y0 = node.cy - node.h / 2;
@@ -14541,7 +15125,7 @@ function ChartStackedBarNode({
14541
15125
  const \u540D\u524D\u306E\u7D1A = 13;
14542
15126
  const \u533A\u753B\u306E\u7D1A = 12;
14543
15127
  const \u6642\u70B9\u306E\u7D1A = 13;
14544
- 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);
15128
+ 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);
14545
15129
  const \u5E2F\u306E\u5DE6 = PAD + \u6642\u70B9\u306E\u5E45;
14546
15130
  const \u5E2F\u306E\u5E45 = Math.max(40, node.w - \u5E2F\u306E\u5DE6 - PAD);
14547
15131
  const \u5E2F\u306E\u9AD8\u3055 = 44;
@@ -14634,7 +15218,7 @@ function ChartStackedBarNode({
14634
15218
  })()
14635
15219
  ] }, `bar-${\u6BB5}`);
14636
15220
  }),
14637
- \u4E00\u89A7\u306E\u4E26\u3073(data, \u5E2F\u306E\u5DE6, node.w - PAD, \u540D\u524D\u306E\u7D1A).map(({ d, idx, x, \u884C }) => {
15221
+ \u4E00\u89A7\u306E\u4E26\u3073(data, \u5E2F\u306E\u5DE6, node.w - PAD, \u540D\u524D\u306E\u7D1A, textMetrics).map(({ d, idx, x, \u884C }) => {
14638
15222
  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;
14639
15223
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { "data-cdl-role": "chart-stacked-bar-legend", children: [
14640
15224
  /* @__PURE__ */ jsxRuntime.jsx("rect", { x, y: y - 5, width: 10, height: 10, rx: 2, fill: \u5370\u306E\u82723(d.tone, idx) }),
@@ -14669,12 +15253,12 @@ function \u5370\u306E\u82723(tone, idx) {
14669
15253
  }
14670
15254
  var \u5370\u304B\u3089\u540D\u524D\u307E\u3067 = 16;
14671
15255
  var \u4EF6\u306E\u9593 = 10;
14672
- function \u4E00\u89A7\u306E\u4E26\u3073(data, \u5DE6, \u53F3\u7AEF, \u7D1A) {
15256
+ function \u4E00\u89A7\u306E\u4E26\u3073(data, \u5DE6, \u53F3\u7AEF, \u7D1A, textMetrics = "proportional") {
14673
15257
  const out = [];
14674
15258
  let x = \u5DE6;
14675
15259
  let \u884C = 0;
14676
15260
  data.forEach((d, idx) => {
14677
- const \u5E45 = \u5370\u304B\u3089\u540D\u524D\u307E\u3067 + textWidth(d.label ?? "", \u7D1A);
15261
+ const \u5E45 = \u5370\u304B\u3089\u540D\u524D\u307E\u3067 + textWidth(d.label ?? "", \u7D1A, 0, textMetrics);
14678
15262
  if (x > \u5DE6 && x + \u5E45 > \u53F3\u7AEF) {
14679
15263
  \u884C += 1;
14680
15264
  x = \u5DE6;
@@ -14690,7 +15274,8 @@ function ChartSlopeNode({
14690
15274
  active,
14691
15275
  stateValues = {},
14692
15276
  drawing = false,
14693
- progress = 1
15277
+ progress = 1,
15278
+ textMetrics = "proportional"
14694
15279
  }) {
14695
15280
  const x0 = node.cx - node.w / 2;
14696
15281
  const y0 = node.cy - node.h / 2;
@@ -14733,16 +15318,22 @@ function ChartSlopeNode({
14733
15318
  const \u53F3\u306E\u5B57 = \u7CFB\u5217\u305F\u3061.map(
14734
15319
  (s) => \u5F62 === "delta" ? \u5897\u6E1B\u8868\u8A18(s.\u524D, s.\u4ECA) : \u5B9F\u5024\u8868\u8A18(s.\u4ECA)
14735
15320
  );
14736
- const \u5DE6\u5024\u5E45 = Math.max(0, ...\u5DE6\u306E\u5B57.map((t) => textWidth(t, \u5024\u306E\u7D1A)));
14737
- const \u53F3\u5024\u5E45 = Math.max(0, ...\u53F3\u306E\u5B57.map((t) => textWidth(t, \u5024\u306E\u7D1A)));
15321
+ const \u5DE6\u5024\u5E45 = Math.max(0, ...\u5DE6\u306E\u5B57.map((t) => textWidth(t, \u5024\u306E\u7D1A, 0, textMetrics)));
15322
+ const \u53F3\u5024\u5E45 = Math.max(0, ...\u53F3\u306E\u5B57.map((t) => textWidth(t, \u5024\u306E\u7D1A, 0, textMetrics)));
14738
15323
  const \u540D\u524D\u306B\u4F7F\u3048\u308B = Math.max(
14739
15324
  0,
14740
15325
  (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
14741
15326
  );
14742
- 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);
15327
+ const \u540D\u524D\u306E\u7D1A = \u53CE\u3081\u308B\u7D1A2(
15328
+ \u7CFB\u5217\u305F\u3061.map((s) => s.\u540D\u524D),
15329
+ \u540D\u524D\u306B\u4F7F\u3048\u308B,
15330
+ \u540D\u524D\u306E\u4E0A\u9650\u7D1A,
15331
+ \u540D\u524D\u306E\u4E0B\u9650\u7D1A,
15332
+ textMetrics
15333
+ );
14743
15334
  const \u540D\u524D\u5E45 = Math.min(
14744
15335
  \u540D\u524D\u306B\u4F7F\u3048\u308B,
14745
- Math.max(0, ...\u7CFB\u5217\u305F\u3061.map((s) => textWidth(s.\u540D\u524D, \u540D\u524D\u306E\u7D1A)))
15336
+ Math.max(0, ...\u7CFB\u5217\u305F\u3061.map((s) => textWidth(s.\u540D\u524D, \u540D\u524D\u306E\u7D1A, 0, textMetrics)))
14746
15337
  );
14747
15338
  const \u5DE6\u306E\u4F59\u767D = \u540D\u524D\u5E45 + \u5024\u304B\u3089\u540D\u524D\u307E\u3067 + \u5DE6\u5024\u5E45 + \u8EF8\u304B\u3089\u5024\u307E\u3067;
14748
15339
  const \u53F3\u306E\u4F59\u767D = \u8EF8\u304B\u3089\u5024\u307E\u3067 + \u53F3\u5024\u5E45 + \u5024\u304B\u3089\u540D\u524D\u307E\u3067 + \u540D\u524D\u5E45;
@@ -14928,10 +15519,12 @@ function \u5370\u306E\u82724(tone, idx) {
14928
15519
  if (tone) return TONE[tone];
14929
15520
  return chartSeriesColor(idx);
14930
15521
  }
14931
- function \u53CE\u3081\u308B\u7D1A2(\u540D\u524D\u305F\u3061, \u5E45, \u4E0A\u9650, \u4E0B\u9650) {
15522
+ function \u53CE\u3081\u308B\u7D1A2(\u540D\u524D\u305F\u3061, \u5E45, \u4E0A\u9650, \u4E0B\u9650, textMetrics = "proportional") {
14932
15523
  if (\u540D\u524D\u305F\u3061.length === 0) return \u4E0A\u9650;
14933
15524
  let \u7D1A = \u4E0A\u9650;
14934
- while (\u7D1A > \u4E0B\u9650 && Math.max(...\u540D\u524D\u305F\u3061.map((n) => textWidth(n, \u7D1A))) > \u5E45) \u7D1A -= 1;
15525
+ while (\u7D1A > \u4E0B\u9650 && Math.max(...\u540D\u524D\u305F\u3061.map((n) => textWidth(n, \u7D1A, 0, textMetrics))) > \u5E45) {
15526
+ \u7D1A -= 1;
15527
+ }
14935
15528
  return \u7D1A;
14936
15529
  }
14937
15530
  function \u5C0F\u6570\u306E\u6841(n) {
@@ -14979,6 +15572,7 @@ function ChartBarNode({
14979
15572
  return { y: yAt(v), value: v };
14980
15573
  });
14981
15574
  const \u6FC3\u3055 = (v) => vMax > 0 ? v >= vMax ? 1 : 0.45 : 0.9;
15575
+ const \u4E3B\u5F79\u306E\u68D2\u304B = (v) => vMax > 0 && v >= vMax;
14982
15576
  const \u89D2\u4E38 = Math.min(barW * 0.06, 8);
14983
15577
  const \u4F38\u3073 = \u9032\u307F\u3092\u7573\u3080(drawing, progress);
14984
15578
  const \u6A2A\u8EF8\u306Ey = PAD_TOP2 + canvasH;
@@ -15045,6 +15639,7 @@ function ChartBarNode({
15045
15639
  {
15046
15640
  "data-cdl-role": "chart-bar",
15047
15641
  "data-cdl-unresolved": d.unresolved ? "true" : void 0,
15642
+ "data-cdl-emphasis": \u4E3B\u5F79\u306E\u68D2\u304B(d.value) ? "primary" : void 0,
15048
15643
  x: bx,
15049
15644
  y: by,
15050
15645
  width: barW,
@@ -15391,7 +15986,8 @@ function FunnelNode({
15391
15986
  active,
15392
15987
  stateValues = {},
15393
15988
  drawing = false,
15394
- progress = 1
15989
+ progress = 1,
15990
+ textMetrics = "proportional"
15395
15991
  }) {
15396
15992
  const x0 = node.cx - node.w / 2;
15397
15993
  const y0 = node.cy - node.h / 2;
@@ -15440,7 +16036,11 @@ function FunnelNode({
15440
16036
  const \u540D\u524D\u306E\u5B9F\u5B57 = \u540D\u524D\u306E\u5B57 * \u7E26\u500D;
15441
16037
  const \u88DC\u8DB3\u306E\u67A0\u5B57 = \u88DC\u8DB3\u306E\u5B57 * \u7E26\u500D;
15442
16038
  const \u53CE\u307E\u308B\u5E45 = Math.max(0, bottomW - 16);
15443
- 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);
16039
+ const \u88DC\u8DB3\u306E\u5B9F\u5B57 = \u88DC\u8DB3\u306E\u67A0\u5B57 * \u53CE\u3081\u308B\u500D\u7387(
16040
+ \u88DC\u8DB3,
16041
+ { fontSize: \u88DC\u8DB3\u306E\u67A0\u5B57, fontWeight: 500, textMetrics },
16042
+ \u53CE\u307E\u308B\u5E45
16043
+ );
15444
16044
  const \u584A\u306E\u4E0A = y + stageH / 2 - (\u540D\u524D\u306E\u5B9F\u5B57 * 1.2 + \u88DC\u8DB3\u306E\u67A0\u5B57 * 1.25) / 2;
15445
16045
  const \u540D\u524D\u306Ey = \u88DC\u8DB3\u3042\u308A ? \u584A\u306E\u4E0A + \u540D\u524D\u306E\u5B9F\u5B57 * 0.95 : y + stageH / 2 + 5;
15446
16046
  const \u88DC\u8DB3\u306Ey = \u584A\u306E\u4E0A + \u540D\u524D\u306E\u5B9F\u5B57 * 1.2 + \u88DC\u8DB3\u306E\u67A0\u5B57 * 0.95;
@@ -15543,7 +16143,8 @@ function \u7573\u3093\u3060\u6587(\u4EF6\u6570) {
15543
16143
  function QuadrantNode({
15544
16144
  node,
15545
16145
  active,
15546
- stateValues = {}
16146
+ stateValues = {},
16147
+ textMetrics = "proportional"
15547
16148
  }) {
15548
16149
  const x0 = node.cx - node.w / 2;
15549
16150
  const y0 = node.cy - node.h / 2;
@@ -15562,7 +16163,10 @@ function QuadrantNode({
15562
16163
  const SUB_FONT = 10;
15563
16164
  const axisLabelPad = (text) => Math.max(
15564
16165
  PAD_MIN,
15565
- measureTextWidth(`\u2190 ${text}`, { fontSize: AXIS_LABEL_FONT}) + 12
16166
+ measureTextWidth(`\u2190 ${text}`, {
16167
+ fontSize: AXIS_LABEL_FONT,
16168
+ textMetrics
16169
+ }) + 12
15566
16170
  );
15567
16171
  const padBudget = Math.max(0, node.w * 0.5 - PAD_MIN * 2);
15568
16172
  const wantLeft = axisLabelPad(data.xAxis.left) - PAD_MIN;
@@ -15816,7 +16420,11 @@ function QuadrantNode({
15816
16420
  ITEM_MIN_W,
15817
16421
  Math.max(
15818
16422
  ...\u884C\u30892.map(
15819
- (r) => measureTextWidth(r.text, { fontSize: r.size, fontWeight: r.weight })
16423
+ (r) => measureTextWidth(r.text, {
16424
+ fontSize: r.size,
16425
+ fontWeight: r.weight,
16426
+ textMetrics
16427
+ })
15820
16428
  )
15821
16429
  ) + ITEM_PAD_X * 2
15822
16430
  )
@@ -15842,7 +16450,7 @@ function QuadrantNode({
15842
16450
  const \u88DC\u8DB3 = (it.subtitle ?? "").trim();
15843
16451
  const \u88DC\u8DB3\u306E\u5B57 = SUB_FONT * \u53CE\u3081\u308B\u500D\u7387(
15844
16452
  \u88DC\u8DB3,
15845
- { fontSize: SUB_FONT, fontWeight: 500 },
16453
+ { fontSize: SUB_FONT, fontWeight: 500, textMetrics },
15846
16454
  Math.max(0, \u5E45 - ITEM_PAD_X * 2)
15847
16455
  );
15848
16456
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
@@ -16246,24 +16854,30 @@ var EYEBROW_GAP2 = 8;
16246
16854
  var EYEBROW_TRACKING = 2;
16247
16855
  var SUB_SIZE = 11;
16248
16856
  var SUB_GAP = 4;
16249
- function labelBlock(node, pos, size, band) {
16857
+ function labelBlock(node, pos, size, band, textMetrics = "proportional") {
16250
16858
  const \u4E0A = node.eyebrow ? size + EYEBROW_GAP2 + EYEBROW_SIZE2 * ASCENT2 : size * ASCENT2;
16251
16859
  const \u4E0B = node.subtitle ? size + SUB_GAP + SUB_SIZE * DESCENT2 : size * DESCENT2;
16252
16860
  const \u5E45 = Math.max(
16253
- textWidth(node.title ?? "", size),
16254
- node.eyebrow ? textWidth(node.eyebrow, EYEBROW_SIZE2, EYEBROW_TRACKING) : 0,
16255
- node.subtitle ? textWidth(node.subtitle, SUB_SIZE) : 0
16861
+ textWidth(node.title ?? "", size, 0, textMetrics),
16862
+ node.eyebrow ? textWidth(node.eyebrow, EYEBROW_SIZE2, EYEBROW_TRACKING, textMetrics) : 0,
16863
+ node.subtitle ? textWidth(node.subtitle, SUB_SIZE, 0, textMetrics) : 0
16256
16864
  );
16257
- const \u984C\u5E45 = textWidth(node.title ?? "", size);
16258
- const \u4E0B\u9650 = \u984C\u5E45 >= \u5E45 ? \u5207\u3063\u3066\u53CE\u307E\u308B\u4E0B\u9650(node.title ?? "", size, 0, band.w, textWidth) : 0;
16865
+ const \u984C\u5E45 = textWidth(node.title ?? "", size, 0, textMetrics);
16866
+ const \u6E2C\u308B = (t, s, ls) => textWidth(t, s, ls, textMetrics);
16867
+ const \u4E0B\u9650 = \u984C\u5E45 >= \u5E45 ? \u5207\u3063\u3066\u53CE\u307E\u308B\u4E0B\u9650(node.title ?? "", size, 0, band.w, \u6E2C\u308B) : 0;
16259
16868
  const { k, x, y: baseline } = fitLabel(band, { \u4E0A, \u4E0B, \u5E45 }, pos, \u4E0B\u9650);
16260
16869
  return { k, x, baseline, \u4E0A\u7AEF: baseline - \u4E0A * k, \u4E0B\u7AEF: baseline + \u4E0B * k };
16261
16870
  }
16262
- function commonLabel(node, pos, size, band) {
16263
- const \u584A = labelBlock(node, pos, size, band);
16871
+ function commonLabel(node, pos, size, band, textMetrics = "proportional") {
16872
+ const \u584A = labelBlock(node, pos, size, band, textMetrics);
16264
16873
  const k = \u584A.k;
16265
16874
  const x = \u584A.x;
16266
- 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));
16875
+ const \u5207\u308B = (t, \u5927\u304D\u3055, \u5B57\u9593 = 0) => \u5E2F\u3067\u5207\u308B(
16876
+ t,
16877
+ \u5927\u304D\u3055 * k,
16878
+ band.w,
16879
+ (u, f) => textWidth(u, f, \u5B57\u9593 * k, textMetrics)
16880
+ );
16267
16881
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
16268
16882
  node.eyebrow && /* @__PURE__ */ jsxRuntime.jsx(
16269
16883
  "text",
@@ -16314,7 +16928,7 @@ var RULE_GAP_RATIO = 0.1;
16314
16928
  var RULE_PAD_MAX = 20;
16315
16929
  var RULE_PAD_RATIO = 0.14;
16316
16930
  var RULE_SHRINK_RATIO = 0.055;
16317
- function ShapeFileNode({ node, active }) {
16931
+ function ShapeFileNode({ node, active, textMetrics = "proportional" }) {
16318
16932
  const \u5E2F = bodyBand(node, { \u5F71ry: SHADOW_RY });
16319
16933
  const \u7D19h = \u5E2F.h;
16320
16934
  const \u7D19w = Math.min(\u5E2F.w, \u7D19h * 0.72);
@@ -16334,7 +16948,7 @@ function ShapeFileNode({ node, active }) {
16334
16948
  const foldTriangle = `M ${x + \u7D19w - fold} ${y} L ${x + \u7D19w} ${y + fold} L ${x + \u7D19w - fold} ${y + fold} Z`;
16335
16949
  const \u540D\u524D\u5E2F = { x, y, w: \u7D19w, h: \u7D19h };
16336
16950
  const \u540D\u524D\u4F4D\u7F6E = { x: \u5E2F.cx, y: node.cy + node.h * 0.12 };
16337
- const \u540D\u524D = labelBlock(node, \u540D\u524D\u4F4D\u7F6E, 16, \u540D\u524D\u5E2F);
16951
+ const \u540D\u524D = labelBlock(node, \u540D\u524D\u4F4D\u7F6E, 16, \u540D\u524D\u5E2F, textMetrics);
16338
16952
  const \u9593\u9694 = Math.min(RULE_GAP_MAX, \u7D19h * RULE_GAP_RATIO);
16339
16953
  const \u7DDA\u4F59\u767D = Math.min(RULE_PAD_MAX, \u7D19w * RULE_PAD_RATIO);
16340
16954
  const textLines = [0, 1, 2].map((i) => ({ i, ly: y + fold + \u9593\u9694 * (i + 1) })).filter(({ ly }) => ly < \u540D\u524D.\u4E0A\u7AEF);
@@ -16366,12 +16980,12 @@ function ShapeFileNode({ node, active }) {
16366
16980
  i
16367
16981
  );
16368
16982
  }),
16369
- commonLabel(node, \u540D\u524D\u4F4D\u7F6E, 16, \u540D\u524D\u5E2F)
16983
+ commonLabel(node, \u540D\u524D\u4F4D\u7F6E, 16, \u540D\u524D\u5E2F, textMetrics)
16370
16984
  ] });
16371
16985
  }
16372
16986
  var TAB_H_MAX = 22;
16373
16987
  var TAB_H_RATIO = 0.3;
16374
- function ShapeFolderNode({ node, active }) {
16988
+ function ShapeFolderNode({ node, active, textMetrics = "proportional" }) {
16375
16989
  const \u5E2F = bodyBand(node, { \u5F71ry: SHADOW_RY });
16376
16990
  const x = \u5E2F.x;
16377
16991
  const y = \u5E2F.y;
@@ -16392,7 +17006,7 @@ function ShapeFolderNode({ node, active }) {
16392
17006
  const \u5883\u754Cy = y + tabH + Math.min(8, (\u5E2F.h - tabH) * 0.2);
16393
17007
  const \u7AEF = Math.min(6, \u5E2F.w * 0.1);
16394
17008
  const \u540D\u524D\u4F4D\u7F6E = { x: \u5E2F.cx, y: node.cy + 18 };
16395
- const \u540D\u524D = labelBlock(node, \u540D\u524D\u4F4D\u7F6E, 16, \u5E2F);
17009
+ const \u540D\u524D = labelBlock(node, \u540D\u524D\u4F4D\u7F6E, 16, \u5E2F, textMetrics);
16396
17010
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
16397
17011
  dropShadow(\u5E2F.cx, \u5E2F.\u5E95, \u5E2F.w * 0.44),
16398
17012
  /* @__PURE__ */ jsxRuntime.jsx("path", { "data-cdl-role": "node-body", d: bodyPath, ...frame, strokeLinejoin: "round" }),
@@ -16408,13 +17022,13 @@ function ShapeFolderNode({ node, active }) {
16408
17022
  opacity: 0.35
16409
17023
  }
16410
17024
  ),
16411
- commonLabel(node, \u540D\u524D\u4F4D\u7F6E, 16, \u5E2F)
17025
+ commonLabel(node, \u540D\u524D\u4F4D\u7F6E, 16, \u5E2F, textMetrics)
16412
17026
  ] });
16413
17027
  }
16414
17028
  var CLOUD_VB_W = 640;
16415
17029
  var CLOUD_VB_H = 512;
16416
17030
  var CLOUD_W_RATIO = 0.9;
16417
- function ShapeCloudNode({ node, active }) {
17031
+ function ShapeCloudNode({ node, active, textMetrics = "proportional" }) {
16418
17032
  const \u5E2F = bodyBand(node, { \u5F71ry: SHADOW_RY });
16419
17033
  const frame = commonFrame(active);
16420
17034
  const \u7D20\u306E\u500D\u7387 = Math.min(\u5E2F.h / CLOUD_VB_H, \u5E2F.w * CLOUD_W_RATIO / CLOUD_VB_W);
@@ -16437,13 +17051,13 @@ function ShapeCloudNode({ node, active }) {
16437
17051
  strokeLinejoin: "round"
16438
17052
  }
16439
17053
  ) }),
16440
- commonLabel(node, { x: \u5E2F.cx, y: node.cy + node.h * 0.05 }, 16, \u5E2F)
17054
+ commonLabel(node, { x: \u5E2F.cx, y: node.cy + node.h * 0.05 }, 16, \u5E2F, textMetrics)
16441
17055
  ] });
16442
17056
  }
16443
17057
  var CYLINDER_RY_MAX = 18;
16444
17058
  var CYLINDER_RY_RATIO = 0.1;
16445
17059
  var CYLINDER_DISKS = [0.3, 0.55, 0.8];
16446
- function ShapeCylinderNode({ node, active }) {
17060
+ function ShapeCylinderNode({ node, active, textMetrics = "proportional" }) {
16447
17061
  const \u5E2F = bodyBand(node, { \u5F71ry: CYLINDER_SHADOW_RY });
16448
17062
  const x = \u5E2F.x;
16449
17063
  const y = \u5E2F.y;
@@ -16460,7 +17074,7 @@ function ShapeCylinderNode({ node, active }) {
16460
17074
  const \u84CB\u5E95 = y + ry * 2;
16461
17075
  const \u540D\u524D\u4F4D\u7F6E = { x: \u5E2F.cx, y: node.cy + 6 };
16462
17076
  const \u540D\u524D\u5E2F = { x: \u5E2F.x, y: \u84CB\u5E95, w: \u5E2F.w, h: Math.max(0, \u5E2F.\u5E95 - \u84CB\u5E95) };
16463
- const \u540D\u524D = labelBlock(node, \u540D\u524D\u4F4D\u7F6E, 15, \u540D\u524D\u5E2F);
17077
+ const \u540D\u524D = labelBlock(node, \u540D\u524D\u4F4D\u7F6E, 15, \u540D\u524D\u5E2F, textMetrics);
16464
17078
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
16465
17079
  dropShadow(\u5E2F.cx, \u5E2F.\u5E95, rx * 0.85, CYLINDER_SHADOW_RY),
16466
17080
  /* @__PURE__ */ jsxRuntime.jsx("path", { "data-cdl-role": "node-body", d: bodyPath, ...frame, strokeLinejoin: "round" }),
@@ -16484,11 +17098,11 @@ function ShapeCylinderNode({ node, active }) {
16484
17098
  },
16485
17099
  i
16486
17100
  )),
16487
- commonLabel(node, \u540D\u524D\u4F4D\u7F6E, 15, \u540D\u524D\u5E2F)
17101
+ commonLabel(node, \u540D\u524D\u4F4D\u7F6E, 15, \u540D\u524D\u5E2F, textMetrics)
16488
17102
  ] });
16489
17103
  }
16490
17104
  var HEX_DOT_R = 2.5;
16491
- function ShapeHexagonNode({ node, active }) {
17105
+ function ShapeHexagonNode({ node, active, textMetrics = "proportional" }) {
16492
17106
  const \u5E2F = bodyBand(node, { \u5F71ry: SHADOW_RY, \u5916: Math.max(HEX_DOT_R, FRAME_HALF) });
16493
17107
  const cx = \u5E2F.cx;
16494
17108
  const cy = \u5E2F.cy;
@@ -16511,11 +17125,12 @@ function ShapeHexagonNode({ node, active }) {
16511
17125
  node,
16512
17126
  { x: cx, y: node.cy + 6 },
16513
17127
  16,
16514
- { x: \u5E2F.x + cut, y: \u5E2F.y, w: Math.max(0, \u5E2F.w - cut * 2), h: \u5E2F.h }
17128
+ { x: \u5E2F.x + cut, y: \u5E2F.y, w: Math.max(0, \u5E2F.w - cut * 2), h: \u5E2F.h },
17129
+ textMetrics
16515
17130
  )
16516
17131
  ] });
16517
17132
  }
16518
- function ShapeDiamondNode({ node, active }) {
17133
+ function ShapeDiamondNode({ node, active, textMetrics = "proportional" }) {
16519
17134
  const \u5E2F = bodyBand(node, { \u5F71ry: SHADOW_RY });
16520
17135
  const cx = \u5E2F.cx;
16521
17136
  const cy = \u5E2F.cy;
@@ -16556,13 +17171,14 @@ function ShapeDiamondNode({ node, active }) {
16556
17171
  y: cy - \u5E2F.h * innerScale / 4,
16557
17172
  w: \u5E2F.w * innerScale / 2,
16558
17173
  h: \u5E2F.h * innerScale / 2
16559
- }
17174
+ },
17175
+ textMetrics
16560
17176
  )
16561
17177
  ] });
16562
17178
  }
16563
17179
  var STACK_OFFSET_MAX = 12;
16564
17180
  var STACK_OFFSET_RATIO = 0.15;
16565
- function ShapeStackNode({ node, active }) {
17181
+ function ShapeStackNode({ node, active, textMetrics = "proportional" }) {
16566
17182
  const \u5E2F = bodyBand(node, { \u5F71ry: SHADOW_RY });
16567
17183
  const x = \u5E2F.x;
16568
17184
  const y = \u5E2F.y;
@@ -16616,7 +17232,8 @@ function ShapeStackNode({ node, active }) {
16616
17232
  node,
16617
17233
  { x: \u624B\u524Dcx, y: node.cy + \u305A\u308C + 6 },
16618
17234
  15,
16619
- { x, y: y + \u305A\u308C * 2, w: cardW, h: cardH }
17235
+ { x, y: y + \u305A\u308C * 2, w: cardW, h: cardH },
17236
+ textMetrics
16620
17237
  )
16621
17238
  ] });
16622
17239
  }
@@ -16628,16 +17245,22 @@ var PERSON_BODY_LEN = 90;
16628
17245
  var PERSON_SHADOW_DY = 20;
16629
17246
  var PERSON_SHADOW_RY = 4;
16630
17247
  var PERSON_SHADOW_RX = 55;
16631
- function planLabel(node, cx, \u5E45\u4E0A\u9650, plan) {
17248
+ function planLabel(node, cx, \u5E45\u4E0A\u9650, plan, textMetrics = "proportional") {
16632
17249
  const \u5E45 = Math.max(
16633
- textWidth(node.title ?? "", plan.\u540D\u524D.size),
16634
- node.eyebrow && plan.\u80A9\u66F8 ? textWidth(node.eyebrow, plan.\u80A9\u66F8.size, EYEBROW_TRACKING) : 0,
16635
- node.subtitle && plan.\u8AAC\u660E ? textWidth(node.subtitle, plan.\u8AAC\u660E.size) : 0
17250
+ textWidth(node.title ?? "", plan.\u540D\u524D.size, 0, textMetrics),
17251
+ node.eyebrow && plan.\u80A9\u66F8 ? textWidth(node.eyebrow, plan.\u80A9\u66F8.size, EYEBROW_TRACKING, textMetrics) : 0,
17252
+ node.subtitle && plan.\u8AAC\u660E ? textWidth(node.subtitle, plan.\u8AAC\u660E.size, 0, textMetrics) : 0
16636
17253
  );
16637
- const \u984C\u5E45 = textWidth(node.title ?? "", plan.\u540D\u524D.size);
16638
- 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;
17254
+ const \u984C\u5E45 = textWidth(node.title ?? "", plan.\u540D\u524D.size, 0, textMetrics);
17255
+ const \u6E2C\u308B = (t, s, ls) => textWidth(t, s, ls, textMetrics);
17256
+ 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;
16639
17257
  const k = \u5E45 > 0 && \u5E45\u4E0A\u9650 > 0 ? Math.min(1, Math.max(\u5E45\u4E0A\u9650 / \u5E45, \u4E0B\u9650)) : 1;
16640
- 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));
17258
+ const \u5207\u308B = (t, \u5927\u304D\u3055, \u5B57\u9593 = 0) => \u5E2F\u3067\u5207\u308B(
17259
+ t,
17260
+ \u5927\u304D\u3055 * k,
17261
+ \u5E45\u4E0A\u9650,
17262
+ (u, f) => textWidth(u, f, \u5B57\u9593 * k, textMetrics)
17263
+ );
16641
17264
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
16642
17265
  node.eyebrow && plan.\u80A9\u66F8 && /* @__PURE__ */ jsxRuntime.jsx(
16643
17266
  "text",
@@ -16678,7 +17301,7 @@ function planLabel(node, cx, \u5E45\u4E0A\u9650, plan) {
16678
17301
  )
16679
17302
  ] });
16680
17303
  }
16681
- function ShapePersonNode({ node, active }) {
17304
+ function ShapePersonNode({ node, active, textMetrics = "proportional" }) {
16682
17305
  const r = shapeRegion(node);
16683
17306
  const cx = r.cx;
16684
17307
  const strokeColor = active ? "var(--cdl-tone-accent, #2d6a8f)" : "var(--cdl-divider, #d4d4d8)";
@@ -16740,7 +17363,7 @@ function ShapePersonNode({ node, active }) {
16740
17363
  )
16741
17364
  ] })
16742
17365
  ),
16743
- planLabel(node, r.cx, Math.max(0, node.w), r.label)
17366
+ planLabel(node, r.cx, Math.max(0, node.w), r.label, textMetrics)
16744
17367
  ] });
16745
17368
  }
16746
17369
  var commonFrame2 = (active) => ({
@@ -16990,7 +17613,12 @@ function ShapeTerminalNode({ node, active, lang }) {
16990
17613
  )
16991
17614
  ] });
16992
17615
  }
16993
- function ShapeCodeBlockNode({ node, active, lang }) {
17616
+ function ShapeCodeBlockNode({
17617
+ node,
17618
+ active,
17619
+ lang,
17620
+ textMetrics = "proportional"
17621
+ }) {
16994
17622
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
16995
17623
  const frame = commonFrame2(active);
16996
17624
  const \u7DDA = frame.strokeWidth / 2;
@@ -17001,7 +17629,10 @@ function ShapeCodeBlockNode({ node, active, lang }) {
17001
17629
  const lineFont = "ui-monospace, SFMono-Regular, Menlo, monospace";
17002
17630
  const \u672D = \u66F8\u3044\u305F\u5024\u304B\u63A7\u3048(node.subtitle, \u5B57\u5F15("codeBlock.fileName"));
17003
17631
  const \u672D\u306E\u5B57 = 11;
17004
- const \u30BF\u30D6\u5E45 = Math.min(Math.max(100, textWidth(\u672D, \u672D\u306E\u5B57, 0) + 24), Math.max(0, w));
17632
+ const \u30BF\u30D6\u5E45 = Math.min(
17633
+ Math.max(100, textWidth(\u672D, \u672D\u306E\u5B57, 0, textMetrics) + 24),
17634
+ Math.max(0, w)
17635
+ );
17005
17636
  const \u30BF\u30D6\u9AD8 = 24;
17006
17637
  const \u89D2 = 10;
17007
17638
  const \u6E9D = 32;
@@ -17041,7 +17672,7 @@ function ShapeCodeBlockNode({ node, active, lang }) {
17041
17672
  { text: \u672D, size: \u672D\u306E\u5B57, \u5E2F: { \u5E45: \u30BF\u30D6\u5E45, \u9AD8\u3055: \u30BF\u30D6\u9AD8 } },
17042
17673
  { text: "1", size: \u884C\u756A\u53F7\u306E\u5B57, \u5E2F: { \u5E45: \u6E9D - \u6301\u3061\u4E0A\u3052, \u9AD8\u3055: \u884C\u9593 } }
17043
17674
  ];
17044
- const \u500D\u8FD4\u3057 = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D, \u6253\u3061\u6D88\u3059\u5B57\u3089);
17675
+ const \u500D\u8FD4\u3057 = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D, \u6253\u3061\u6D88\u3059\u5B57\u3089, textMetrics);
17045
17676
  const tabW = \u30BF\u30D6\u5E45 * \u500D;
17046
17677
  const tabH = \u30BF\u30D6\u9AD8 * \u500D;
17047
17678
  const \u4E38 = \u89D2 * \u500D;
@@ -17080,7 +17711,7 @@ function ShapeCodeBlockNode({ node, active, lang }) {
17080
17711
  "data-cdl-counter-scaled": "1",
17081
17712
  x: x + tabW / 2,
17082
17713
  y: y + tabH / 2 + 4 * \u500D,
17083
- fontSize: \u672D\u306E\u5B57 * \u500D * \u500D\u8FD4\u3057 * \u5E45\u306E\u500D\u7387(\u672D, \u672D\u306E\u5B57 * \u500D * \u500D\u8FD4\u3057, 0, tabW),
17714
+ fontSize: \u672D\u306E\u5B57 * \u500D * \u500D\u8FD4\u3057 * \u5E45\u306E\u500D\u7387(\u672D, \u672D\u306E\u5B57 * \u500D * \u500D\u8FD4\u3057, 0, tabW, textMetrics),
17084
17715
  fontFamily: lineFont,
17085
17716
  textAnchor: "middle",
17086
17717
  fill: "#e6edf3",
@@ -17162,7 +17793,12 @@ function ShapeCodeBlockNode({ node, active, lang }) {
17162
17793
  )
17163
17794
  ] });
17164
17795
  }
17165
- function ShapeKanbanCardNode({ node, active, lang }) {
17796
+ function ShapeKanbanCardNode({
17797
+ node,
17798
+ active,
17799
+ lang,
17800
+ textMetrics = "proportional"
17801
+ }) {
17166
17802
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
17167
17803
  const frame = commonFrame2(active);
17168
17804
  const \u7DDA = frame.strokeWidth / 2;
@@ -17216,7 +17852,7 @@ function ShapeKanbanCardNode({ node, active, lang }) {
17216
17852
  );
17217
17853
  const \u8AAC\u660E = \u66F8\u3044\u305F\u5024\u304B\u63A7\u3048(node.subtitle, \u5B57\u5F15("kanbanCard.task"));
17218
17854
  const \u72B6\u614B = \u66F8\u3044\u305F\u5024\u304B\u63A7\u3048(node.eyebrow, \u5B57\u5F15("kanbanCard.status"));
17219
- const \u72B6\u614B\u306E\u500D\u7387 = \u5E45\u306E\u500D\u7387(\u72B6\u614B, PILL\u5B57, PILL\u5B57\u9593, PILL\u5B57\u5E45);
17855
+ const \u72B6\u614B\u306E\u500D\u7387 = \u5E45\u306E\u500D\u7387(\u72B6\u614B, PILL\u5B57, PILL\u5B57\u9593, PILL\u5B57\u5E45, textMetrics);
17220
17856
  const \u8AAC\u660E\u306E\u5B57 = \u540D\u524D.size * \u8AAC\u660E\u5B57\u6BD4;
17221
17857
  const \u4F7F\u3048\u308B\u5E452 = Math.max(0, w - \u5DE6\u53F3\u4F59\u767D * \u500D * 2);
17222
17858
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
@@ -17303,7 +17939,7 @@ function ShapeKanbanCardNode({ node, active, lang }) {
17303
17939
  {
17304
17940
  x: x + w / 2,
17305
17941
  y: \u540D\u524D.y + \u540D\u524D.size * \u8AAC\u660E\u57FA\u6E96\u6BD4,
17306
- fontSize: \u8AAC\u660E\u306E\u5B57 * \u5E45\u306E\u500D\u7387(\u8AAC\u660E, \u8AAC\u660E\u306E\u5B57, 0, \u4F7F\u3048\u308B\u5E452),
17942
+ fontSize: \u8AAC\u660E\u306E\u5B57 * \u5E45\u306E\u500D\u7387(\u8AAC\u660E, \u8AAC\u660E\u306E\u5B57, 0, \u4F7F\u3048\u308B\u5E452, textMetrics),
17307
17943
  textAnchor: "middle",
17308
17944
  fill: "var(--cdl-text-dim, #5a6270)",
17309
17945
  children: \u8AAC\u660E
@@ -17594,18 +18230,33 @@ var externalLabel = (node, cx, bottomY) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRu
17594
18230
  )
17595
18231
  ] });
17596
18232
  var LABEL_EYEBROW_SPACING = 2;
17597
- function \u5E45\u306B\u53CE\u3081\u308B2(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45, \u984C\u304B = false) {
17598
- const \u5E45 = textWidth(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593);
17599
- 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;
18233
+ function \u5E45\u306B\u53CE\u3081\u308B2(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45, \u984C\u304B = false, textMetrics = "proportional") {
18234
+ const \u6E2C\u308B = (t, s, ls) => textWidth(t, s, ls, textMetrics);
18235
+ const \u5E45 = \u6E2C\u308B(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593);
18236
+ 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;
17600
18237
  const \u500D\u7387 = \u5E45 > 0 && \u7BB1\u5E45 > 0 ? Math.min(1, Math.max(\u7BB1\u5E45 / \u5E45, \u4E0B\u9650)) : 1;
17601
18238
  const size = \u5927\u304D\u3055 * \u500D\u7387;
17602
18239
  const spacing = \u5B57\u9593 * \u500D\u7387;
17603
- return { size, spacing, text: \u5E2F\u3067\u5207\u308B(\u6587\u5B57\u5217, size, \u7BB1\u5E45, (u, f) => textWidth(u, f, spacing)) };
17604
- }
17605
- function bottomLabel(node, cx, plan) {
17606
- const \u80A9 = \u5E45\u306B\u53CE\u3081\u308B2(node.eyebrow ?? "", plan.\u80A9\u66F8?.size ?? 0, LABEL_EYEBROW_SPACING, node.w);
17607
- const \u540D = \u5E45\u306B\u53CE\u3081\u308B2(node.title ?? "", plan.\u540D\u524D.size, 0, node.w, true);
17608
- const \u8AAC = \u5E45\u306B\u53CE\u3081\u308B2(node.subtitle ?? "", plan.\u8AAC\u660E?.size ?? 0, 0, node.w);
18240
+ return { size, spacing, text: \u5E2F\u3067\u5207\u308B(\u6587\u5B57\u5217, size, \u7BB1\u5E45, (u, f) => \u6E2C\u308B(u, f, spacing)) };
18241
+ }
18242
+ function bottomLabel(node, cx, plan, textMetrics = "proportional") {
18243
+ const \u80A9 = \u5E45\u306B\u53CE\u3081\u308B2(
18244
+ node.eyebrow ?? "",
18245
+ plan.\u80A9\u66F8?.size ?? 0,
18246
+ LABEL_EYEBROW_SPACING,
18247
+ node.w,
18248
+ false,
18249
+ textMetrics
18250
+ );
18251
+ const \u540D = \u5E45\u306B\u53CE\u3081\u308B2(node.title ?? "", plan.\u540D\u524D.size, 0, node.w, true, textMetrics);
18252
+ const \u8AAC = \u5E45\u306B\u53CE\u3081\u308B2(
18253
+ node.subtitle ?? "",
18254
+ plan.\u8AAC\u660E?.size ?? 0,
18255
+ 0,
18256
+ node.w,
18257
+ false,
18258
+ textMetrics
18259
+ );
17609
18260
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
17610
18261
  node.eyebrow && plan.\u80A9\u66F8 && /* @__PURE__ */ jsxRuntime.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 }),
17611
18262
  /* @__PURE__ */ jsxRuntime.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 }),
@@ -17619,7 +18270,7 @@ var RACK_SLOT_N = 4;
17619
18270
  var RACK_BOTTOM = 8;
17620
18271
  var RACK_H = RACK_SLOT_TOP + RACK_SLOT_N * RACK_SLOT_H + (RACK_SLOT_N - 1) * RACK_SLOT_GAP + RACK_BOTTOM;
17621
18272
  var RACK_W_MIN = 120;
17622
- function ShapeServerRackNode({ node, active }) {
18273
+ function ShapeServerRackNode({ node, active, textMetrics = "proportional" }) {
17623
18274
  const r = shapeRegion(node);
17624
18275
  const frame = commonFrame3(active);
17625
18276
  const \u7DDA = frame.strokeWidth / 2;
@@ -17701,7 +18352,7 @@ function ShapeServerRackNode({ node, active }) {
17701
18352
  ] }, i);
17702
18353
  })
17703
18354
  ] })),
17704
- bottomLabel(node, r.cx, r.label)
18355
+ bottomLabel(node, r.cx, r.label, textMetrics)
17705
18356
  ] });
17706
18357
  }
17707
18358
  var HUB_R = 30;
@@ -17709,7 +18360,7 @@ var ARM_LEN = 68;
17709
18360
  var END_R = 7;
17710
18361
  var WIFI_ARC_R = [10, 16, 22];
17711
18362
  var WIFI_BASE_Y = 5;
17712
- function ShapeNetworkNodeNode({ node, active }) {
18363
+ function ShapeNetworkNodeNode({ node, active, textMetrics = "proportional" }) {
17713
18364
  const r = shapeRegion(node);
17714
18365
  const cx = r.cx;
17715
18366
  const cy = r.cy;
@@ -17785,12 +18436,12 @@ function ShapeNetworkNodeNode({ node, active }) {
17785
18436
  )),
17786
18437
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx, cy: cy + WIFI_BASE_Y + 3, r: 2.5, fill: "var(--cdl-tone-accent, #2d6a8f)", stroke: "none" })
17787
18438
  ] })),
17788
- bottomLabel(node, r.cx, r.label)
18439
+ bottomLabel(node, r.cx, r.label, textMetrics)
17789
18440
  ] });
17790
18441
  }
17791
18442
  var PHONE_H = 240;
17792
18443
  var PHONE_W = 110;
17793
- function ShapeMobileDeviceNode({ node, active }) {
18444
+ function ShapeMobileDeviceNode({ node, active, textMetrics = "proportional" }) {
17794
18445
  const r = shapeRegion(node);
17795
18446
  const frame = commonFrame3(active);
17796
18447
  const \u7DDA = frame.strokeWidth / 2;
@@ -17857,7 +18508,7 @@ function ShapeMobileDeviceNode({ node, active }) {
17857
18508
  }
17858
18509
  )
17859
18510
  ] })),
17860
- bottomLabel(node, r.cx, r.label)
18511
+ bottomLabel(node, r.cx, r.label, textMetrics)
17861
18512
  ] });
17862
18513
  }
17863
18514
  function ShapeIotSensorNode({ node, active }) {
@@ -18128,7 +18779,7 @@ var SAT_DISH_R = 12;
18128
18779
  var SAT_DISH_STEM = 12;
18129
18780
  var SAT_MAST_LEN = 22;
18130
18781
  var SAT_MAST_TIP_R = 4;
18131
- function ShapeSatelliteNode({ node, active }) {
18782
+ function ShapeSatelliteNode({ node, active, textMetrics = "proportional" }) {
18132
18783
  const r = shapeRegion(node);
18133
18784
  const cx = r.cx;
18134
18785
  const cy = r.cy;
@@ -18317,7 +18968,7 @@ function ShapeSatelliteNode({ node, active }) {
18317
18968
  ),
18318
18969
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx, cy: cy - bodyH / 2 - SAT_MAST_LEN, r: 2, fill: "#ff5f56", stroke: "none", children: /* @__PURE__ */ jsxRuntime.jsx("animate", { attributeName: "opacity", values: "0.4;1;0.4", dur: "1.4s", repeatCount: "indefinite" }) })
18319
18970
  ] })),
18320
- bottomLabel(node, r.cx, r.label)
18971
+ bottomLabel(node, r.cx, r.label, textMetrics)
18321
18972
  ] });
18322
18973
  }
18323
18974
  var FRAME_SW_ACTIVE = 3;
@@ -18403,9 +19054,9 @@ function blockchainNodeExtent(strokeWidth) {
18403
19054
  const \u6A2A = (NODE_PEER_DIST + NODE_PEER_R) * Math.cos(Math.PI / 6) + \u7DDA;
18404
19055
  return { \u4E0A: \u7E26, \u4E0B: \u7E26, \u5DE6: \u6A2A, \u53F3: \u6A2A };
18405
19056
  }
18406
- function bottomLabel2(node, cx, plan) {
19057
+ function bottomLabel2(node, cx, plan, textMetrics = "proportional") {
18407
19058
  const \u53CE\u3081\u308B = (t, \u5927\u304D\u3055, \u5B57\u9593, \u984C\u304B = false) => {
18408
- const \u6E2C\u308B = (u, f, ls) => \u5B57\u306E\u5E45(u, f) + ls * [...u].length;
19059
+ const \u6E2C\u308B = (u, f, ls) => \u5B57\u306E\u5E45(u, f, textMetrics) + ls * [...u].length;
18409
19060
  const \u7D20\u306E\u5E45 = \u6E2C\u308B(t, \u5927\u304D\u3055, \u5B57\u9593);
18410
19061
  const \u53CE\u307E\u308B = \u7D20\u306E\u5E45 > node.w && node.w > 0 ? node.w / \u7D20\u306E\u5E45 : 1;
18411
19062
  const \u4E0B\u9650 = \u984C\u304B ? \u5207\u3063\u3066\u53CE\u307E\u308B\u4E0B\u9650(t, \u5927\u304D\u3055, \u5B57\u9593, node.w, \u6E2C\u308B) : 0;
@@ -18438,7 +19089,12 @@ function EthereumDiamond({ cx, cy, h, colors }) {
18438
19089
  /* @__PURE__ */ jsxRuntime.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" })
18439
19090
  ] });
18440
19091
  }
18441
- function ShapeSmartContractNode({ node, active, lang }) {
19092
+ function ShapeSmartContractNode({
19093
+ node,
19094
+ active,
19095
+ lang,
19096
+ textMetrics = "proportional"
19097
+ }) {
18442
19098
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
18443
19099
  const frame = commonFrame4(active);
18444
19100
  const r = shapeRegion(node);
@@ -18479,7 +19135,7 @@ function ShapeSmartContractNode({ node, active, lang }) {
18479
19135
  }
18480
19136
  ];
18481
19137
  const art = (\u500D\u7387) => {
18482
- const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089);
19138
+ const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089, textMetrics);
18483
19139
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
18484
19140
  /* @__PURE__ */ jsxRuntime.jsx("path", { "data-cdl-role": "node-body", d: path, ...frame, strokeLinejoin: "round" }),
18485
19141
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: foldPath, fill: "none", stroke: frame.stroke, strokeWidth: frame.strokeWidth, strokeLinejoin: "round" }),
@@ -18501,10 +19157,10 @@ function ShapeSmartContractNode({ node, active, lang }) {
18501
19157
  };
18502
19158
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
18503
19159
  fitArt(r, smartContractExtent(frame.strokeWidth), art),
18504
- bottomLabel2(node, r.cx, r.label)
19160
+ bottomLabel2(node, r.cx, r.label, textMetrics)
18505
19161
  ] });
18506
19162
  }
18507
- var \u5B57\u306E\u5E45 = (text, size) => \u7D75\u306E\u4E2D\u306E\u5B57\u306E\u5E45(text, size);
19163
+ var \u5B57\u306E\u5E45 = (text, size, textMetrics = "proportional") => \u7D75\u306E\u4E2D\u306E\u5B57\u306E\u5E45(text, size, 0, textMetrics);
18508
19164
  var BLOCK_DEFAULT_FIELDS = [
18509
19165
  { key: "hash", label: "blockchainBlock.hash", value: { text: "0xaf31..." } },
18510
19166
  { key: "prev", label: "blockchainBlock.prev", value: { text: "0x7b3f..." } },
@@ -18512,10 +19168,16 @@ var BLOCK_DEFAULT_FIELDS = [
18512
19168
  { key: "nonce", label: "blockchainBlock.nonce", value: { text: "82,914" } },
18513
19169
  { key: "tx", label: "blockchainBlock.tx", value: { \u8F9E\u66F8: "blockchainBlock.txCount" } }
18514
19170
  ];
18515
- function ShapeBlockchainBlockNode({ node, active, lang }) {
19171
+ function ShapeBlockchainBlockNode({
19172
+ node,
19173
+ active,
19174
+ lang,
19175
+ textMetrics = "proportional"
19176
+ }) {
18516
19177
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
18517
19178
  const frame = commonFrame4(active);
18518
19179
  const r = shapeRegion(node);
19180
+ const \u6E2C\u308B\u5B57 = (text, size) => \u5B57\u306E\u5E45(text, size, textMetrics);
18519
19181
  const bw = BLOCK_W;
18520
19182
  const bh = BLOCK_H;
18521
19183
  const cx = r.cx;
@@ -18536,9 +19198,9 @@ function ShapeBlockchainBlockNode({ node, active, lang }) {
18536
19198
  const \u5E2F\u306E\u6B8B\u308A = bw - 14 - 30;
18537
19199
  const \u80A9\u66F8\u306E\u9699\u9593 = 8;
18538
19200
  const \u80A9\u66F8\u306E\u4E0A\u9650 = (\u5E2F\u306E\u6B8B\u308A - \u80A9\u66F8\u306E\u9699\u9593) / 2;
18539
- 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);
19201
+ 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);
18540
19202
  const \u80A9\u66F8\u306E\u6307\u5B9A = \u80A9\u66F8\u306E\u5B57 * \u80A9\u66F8\u306E\u500D\u7387;
18541
- const \u80A9\u66F8\u306E\u5E45 = \u80A9\u66F8 === "" ? 0 : \u5B57\u306E\u5E45(\u80A9\u66F8, \u80A9\u66F8\u306E\u6307\u5B9A);
19203
+ const \u80A9\u66F8\u306E\u5E45 = \u80A9\u66F8 === "" ? 0 : \u6E2C\u308B\u5B57(\u80A9\u66F8, \u80A9\u66F8\u306E\u6307\u5B9A);
18542
19204
  const \u898B\u51FA\u3057\u306E\u5E45 = \u5E2F\u306E\u6B8B\u308A - (\u80A9\u66F8 === "" ? 0 : \u80A9\u66F8\u306E\u5E45 + \u80A9\u66F8\u306E\u9699\u9593);
18543
19205
  const \u6253\u3061\u6D88\u3059\u5B57\u3089 = [
18544
19206
  { text: \u898B\u51FA\u3057, size: \u898B\u51FA\u3057\u306E\u5B57, \u5E2F: { \u5E45: \u898B\u51FA\u3057\u306E\u5E45, \u9AD8\u3055: \u898B\u51FA\u3057\u306E\u5E2F } },
@@ -18549,12 +19211,12 @@ function ShapeBlockchainBlockNode({ node, active, lang }) {
18549
19211
  {
18550
19212
  text: f.value,
18551
19213
  size: \u5024\u306E\u5B57,
18552
- \u5E2F: { \u5E45: bw - 28 - \u5B57\u306E\u5E45(f.label, \u540D\u306E\u5B57) - 8, \u9AD8\u3055: \u884C\u306E\u9593\u9694 }
19214
+ \u5E2F: { \u5E45: bw - 28 - \u6E2C\u308B\u5B57(f.label, \u540D\u306E\u5B57) - 8, \u9AD8\u3055: \u884C\u306E\u9593\u9694 }
18553
19215
  }
18554
19216
  ])
18555
19217
  ];
18556
19218
  const art = (\u500D\u7387) => {
18557
- const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089);
19219
+ const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089, textMetrics);
18558
19220
  const \u984C\u306E\u5927\u304D\u3055 = \u898B\u51FA\u3057\u306E\u5B57 * \u500D;
18559
19221
  const \u80A9\u66F8\u306E\u5927\u304D\u3055 = \u80A9\u66F8\u306E\u6307\u5B9A * \u500D;
18560
19222
  const \u540D\u306E\u5927\u304D\u3055 = \u540D\u306E\u5B57 * \u500D;
@@ -18563,7 +19225,7 @@ function ShapeBlockchainBlockNode({ node, active, lang }) {
18563
19225
  /* @__PURE__ */ jsxRuntime.jsx("rect", { x: x + 6, y: y + 6, width: bw, height: bh, rx: 8, fill: frame.stroke, opacity: 0.2, stroke: "none" }),
18564
19226
  /* @__PURE__ */ jsxRuntime.jsx("rect", { "data-cdl-role": "node-body", x, y, width: bw, height: bh, rx: 8, ...frame }),
18565
19227
  /* @__PURE__ */ jsxRuntime.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" }),
18566
- /* @__PURE__ */ jsxRuntime.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) }),
19228
+ /* @__PURE__ */ jsxRuntime.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) }),
18567
19229
  \u80A9\u66F8 !== "" && /* @__PURE__ */ jsxRuntime.jsx(
18568
19230
  "text",
18569
19231
  {
@@ -18583,7 +19245,12 @@ function ShapeBlockchainBlockNode({ node, active, lang }) {
18583
19245
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: x + bw - 16, cy: y + 16, r: 5.5, fill: "#7cd88f", stroke: "#ffffff", strokeWidth: 1.5 }),
18584
19246
  fields.map((f, i) => /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
18585
19247
  /* @__PURE__ */ jsxRuntime.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 }),
18586
- /* @__PURE__ */ jsxRuntime.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) }),
19248
+ /* @__PURE__ */ jsxRuntime.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(
19249
+ f.value,
19250
+ \u5024\u306E\u5927\u304D\u3055,
19251
+ bw - 28 - \u6E2C\u308B\u5B57(f.label, \u540D\u306E\u5927\u304D\u3055) - 8,
19252
+ \u6E2C\u308B\u5B57
19253
+ ) }),
18587
19254
  /* @__PURE__ */ jsxRuntime.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 })
18588
19255
  ] }, i)),
18589
19256
  /* @__PURE__ */ jsxRuntime.jsxs("g", { transform: `translate(${cx - 32}, ${y + bh - 26})`, children: [
@@ -18595,7 +19262,11 @@ function ShapeBlockchainBlockNode({ node, active, lang }) {
18595
19262
  };
18596
19263
  return /* @__PURE__ */ jsxRuntime.jsx("g", { children: fitArt(r, blockchainBlockExtent(frame.strokeWidth), art) });
18597
19264
  }
18598
- function ShapeBlockchainNode({ node, active }) {
19265
+ function ShapeBlockchainNode({
19266
+ node,
19267
+ active,
19268
+ textMetrics = "proportional"
19269
+ }) {
18599
19270
  const frame = commonFrame4(active);
18600
19271
  const r = shapeRegion(node);
18601
19272
  const cx = r.cx;
@@ -18611,7 +19282,7 @@ function ShapeBlockchainNode({ node, active }) {
18611
19282
  { text: "0x\u2026", size: CHAIN_HASH_SIZE, \u5E2F: { \u5E45: CHAIN_TEXT_W, \u9AD8\u3055: CHAIN_ROW_GAP } }
18612
19283
  ];
18613
19284
  const art = (\u500D\u7387) => {
18614
- const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089);
19285
+ const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089, textMetrics);
18615
19286
  return /* @__PURE__ */ jsxRuntime.jsx("g", { children: Array.from({ length: blockCount }, (_, i) => i).map((i) => {
18616
19287
  const bx = startX + i * (blockW + linkW);
18617
19288
  const isCurrent = i === blockCount - 1;
@@ -18647,10 +19318,14 @@ function ShapeBlockchainNode({ node, active }) {
18647
19318
  };
18648
19319
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
18649
19320
  fitArt(r, chainExtent(), art),
18650
- bottomLabel2(node, r.cx, r.label)
19321
+ bottomLabel2(node, r.cx, r.label, textMetrics)
18651
19322
  ] });
18652
19323
  }
18653
- function ShapeBitcoinChainNode({ node, active }) {
19324
+ function ShapeBitcoinChainNode({
19325
+ node,
19326
+ active,
19327
+ textMetrics = "proportional"
19328
+ }) {
18654
19329
  const frame = commonFrame4(active);
18655
19330
  const r = shapeRegion(node);
18656
19331
  const cx = r.cx;
@@ -18666,7 +19341,7 @@ function ShapeBitcoinChainNode({ node, active }) {
18666
19341
  { text: "#820", size: BTC_NO_SIZE, \u5E2F: { \u5E45: CHAIN_TEXT_W, \u9AD8\u3055: 20 } }
18667
19342
  ];
18668
19343
  const art = (\u500D\u7387) => {
18669
- const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089);
19344
+ const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089, textMetrics);
18670
19345
  return /* @__PURE__ */ jsxRuntime.jsx("g", { children: Array.from({ length: blockCount }, (_, i) => i).map((i) => {
18671
19346
  const bx = startX + i * (blockW + linkW);
18672
19347
  const isCurrent = i === blockCount - 1;
@@ -18697,10 +19372,14 @@ function ShapeBitcoinChainNode({ node, active }) {
18697
19372
  };
18698
19373
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
18699
19374
  fitArt(r, chainExtent(), art),
18700
- bottomLabel2(node, r.cx, r.label)
19375
+ bottomLabel2(node, r.cx, r.label, textMetrics)
18701
19376
  ] });
18702
19377
  }
18703
- function ShapeEthereumChainNode({ node, active }) {
19378
+ function ShapeEthereumChainNode({
19379
+ node,
19380
+ active,
19381
+ textMetrics = "proportional"
19382
+ }) {
18704
19383
  const frame = commonFrame4(active);
18705
19384
  const r = shapeRegion(node);
18706
19385
  const cx = r.cx;
@@ -18716,7 +19395,7 @@ function ShapeEthereumChainNode({ node, active }) {
18716
19395
  { text: "#214", size: ETH_NO_SIZE, \u5E2F: { \u5E45: CHAIN_TEXT_W, \u9AD8\u3055: 20 } }
18717
19396
  ];
18718
19397
  const art = (\u500D\u7387) => {
18719
- const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089);
19398
+ const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089, textMetrics);
18720
19399
  return /* @__PURE__ */ jsxRuntime.jsx("g", { children: Array.from({ length: blockCount }, (_, i) => i).map((i) => {
18721
19400
  const bx = startX + i * (blockW + linkW);
18722
19401
  const isCurrent = i === blockCount - 1;
@@ -18748,10 +19427,14 @@ function ShapeEthereumChainNode({ node, active }) {
18748
19427
  };
18749
19428
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
18750
19429
  fitArt(r, chainExtent(), art),
18751
- bottomLabel2(node, r.cx, r.label)
19430
+ bottomLabel2(node, r.cx, r.label, textMetrics)
18752
19431
  ] });
18753
19432
  }
18754
- function ShapeBlockchainNodeNode({ node, active }) {
19433
+ function ShapeBlockchainNodeNode({
19434
+ node,
19435
+ active,
19436
+ textMetrics = "proportional"
19437
+ }) {
18755
19438
  const frame = commonFrame4(active);
18756
19439
  const r = shapeRegion(node);
18757
19440
  const cx = r.cx;
@@ -18805,10 +19488,15 @@ function ShapeBlockchainNodeNode({ node, active }) {
18805
19488
  ] });
18806
19489
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
18807
19490
  fitArt(r, blockchainNodeExtent(frame.strokeWidth), art),
18808
- bottomLabel2(node, r.cx, r.label)
19491
+ bottomLabel2(node, r.cx, r.label, textMetrics)
18809
19492
  ] });
18810
19493
  }
18811
- function ShapeRpcNodeNode({ node, active, lang }) {
19494
+ function ShapeRpcNodeNode({
19495
+ node,
19496
+ active,
19497
+ lang,
19498
+ textMetrics = "proportional"
19499
+ }) {
18812
19500
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
18813
19501
  const frame = commonFrame4(active);
18814
19502
  const r = shapeRegion(node);
@@ -18827,10 +19515,10 @@ function ShapeRpcNodeNode({ node, active, lang }) {
18827
19515
  /* @__PURE__ */ jsxRuntime.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" }),
18828
19516
  /* @__PURE__ */ jsxRuntime.jsx("rect", { x: x + 16, y: y + bh - 24, width: bw - 32, height: 8, rx: 4, fill: "#0f1419", stroke: "none" }),
18829
19517
  /* @__PURE__ */ jsxRuntime.jsx("rect", { x: x + 16, y: y + bh - 24, width: (bw - 32) * 0.92, height: 8, rx: 4, fill: "#27c93f", stroke: "none", children: /* @__PURE__ */ jsxRuntime.jsx("animate", { attributeName: "width", values: `${(bw - 32) * 0.86};${(bw - 32) * 0.96};${(bw - 32) * 0.86}`, dur: "3s", repeatCount: "indefinite" }) }),
18830
- bottomLabel2(node, r.cx, r.label)
19518
+ bottomLabel2(node, r.cx, r.label, textMetrics)
18831
19519
  ] });
18832
19520
  }
18833
- function ShapeWalletNode({ node, active }) {
19521
+ function ShapeWalletNode({ node, active, textMetrics = "proportional" }) {
18834
19522
  const frame = commonFrame4(active);
18835
19523
  const r = shapeRegion(node);
18836
19524
  const cx = r.cx;
@@ -18904,10 +19592,10 @@ function ShapeWalletNode({ node, active }) {
18904
19592
  /* @__PURE__ */ jsxRuntime.jsx("text", { x: cx, y: foldY + 3, fontSize: 9, fontWeight: 700, fill: "#5a3a10", textAnchor: "middle", opacity: 0.8, children: "\u039E" }),
18905
19593
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: `M ${x + 2} ${y + 6} L ${x + w - 2} ${y + 6}`, fill: "none", stroke: "#ffffff", strokeWidth: 1, opacity: 0.4 })
18906
19594
  ] }),
18907
- bottomLabel2(node, r.cx, r.label)
19595
+ bottomLabel2(node, r.cx, r.label, textMetrics)
18908
19596
  ] });
18909
19597
  }
18910
- function ShapeNftNode({ node, active }) {
19598
+ function ShapeNftNode({ node, active, textMetrics = "proportional" }) {
18911
19599
  const frame = commonFrame4(active);
18912
19600
  const r = shapeRegion(node);
18913
19601
  const cx = r.cx;
@@ -18923,7 +19611,7 @@ function ShapeNftNode({ node, active }) {
18923
19611
  { text: "#1024", size: NFT_ID_SIZE, \u5E2F: { \u5E45: cardW - 16 - 34, \u9AD8\u3055: cardH - artH } }
18924
19612
  ];
18925
19613
  const art = (\u500D\u7387) => {
18926
- const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089);
19614
+ const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089, textMetrics);
18927
19615
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
18928
19616
  /* @__PURE__ */ jsxRuntime.jsx("rect", { x: x + 4, y: y + 4, width: cardW, height: cardH, rx: 14, fill: frame.stroke, opacity: 0.2, stroke: "none" }),
18929
19617
  /* @__PURE__ */ jsxRuntime.jsx("rect", { "data-cdl-role": "node-body", x, y, width: cardW, height: cardH, rx: 14, ...frame }),
@@ -18961,10 +19649,10 @@ function ShapeNftNode({ node, active }) {
18961
19649
  };
18962
19650
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
18963
19651
  fitArt(r, nftExtent(frame.strokeWidth), art),
18964
- bottomLabel2(node, r.cx, r.label)
19652
+ bottomLabel2(node, r.cx, r.label, textMetrics)
18965
19653
  ] });
18966
19654
  }
18967
- function ShapeTokenNode({ node, active }) {
19655
+ function ShapeTokenNode({ node, active, textMetrics = "proportional" }) {
18968
19656
  const frame = commonFrame4(active);
18969
19657
  const r = shapeRegion(node);
18970
19658
  const cx = r.cx;
@@ -19001,7 +19689,7 @@ function ShapeTokenNode({ node, active }) {
19001
19689
  }
19002
19690
  }
19003
19691
  ),
19004
- bottomLabel2(node, r.cx, r.label)
19692
+ bottomLabel2(node, r.cx, r.label, textMetrics)
19005
19693
  ] });
19006
19694
  }
19007
19695
  var commonFrame5 = (active) => ({
@@ -19020,7 +19708,8 @@ function \u5B57\u306E\u6BD4(c) {
19020
19708
  if (\u5E83\u5B57.has(c)) return \u5E83\u5B57\u6BD4;
19021
19709
  return (c.codePointAt(0) ?? 0) < 128 ? \u4E26\u5B57\u6BD4 : \u5E83\u5B57\u6BD4;
19022
19710
  }
19023
- function \u5B57\u5E45(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593) {
19711
+ function \u5B57\u5E45(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, textMetrics = "proportional") {
19712
+ if (textMetrics === "monospace") return textWidth(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, textMetrics);
19024
19713
  let \u5E45 = 0;
19025
19714
  let \u5B57\u6570 = 0;
19026
19715
  for (const c of \u6587\u5B57\u5217) {
@@ -19029,18 +19718,33 @@ function \u5B57\u5E45(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593) {
19029
19718
  }
19030
19719
  return \u5E45 + \u5B57\u9593 * \u5B57\u6570;
19031
19720
  }
19032
- function \u5E45\u306B\u53CE\u3081\u308B3(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45, \u984C\u304B = false) {
19033
- const \u5E45 = \u5B57\u5E45(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593);
19034
- 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;
19721
+ function \u5E45\u306B\u53CE\u3081\u308B3(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45, \u984C\u304B = false, textMetrics = "proportional") {
19722
+ const \u6E2C\u308B = (t, s, ls) => \u5B57\u5E45(t, s, ls, textMetrics);
19723
+ const \u5E45 = \u6E2C\u308B(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593);
19724
+ 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;
19035
19725
  const \u500D\u7387 = \u5E45 > 0 && \u7BB1\u5E45 > 0 ? Math.min(1, Math.max(\u7BB1\u5E45 / \u5E45, \u4E0B\u9650)) : 1;
19036
19726
  const size = \u5927\u304D\u3055 * \u500D\u7387;
19037
19727
  const spacing = \u5B57\u9593 * \u500D\u7387;
19038
- return { size, spacing, text: \u5E2F\u3067\u5207\u308B(\u6587\u5B57\u5217, size, \u7BB1\u5E45, (u, f) => \u5B57\u5E45(u, f, spacing)) };
19039
- }
19040
- function bottomLabel3(node, cx, plan) {
19041
- const \u80A9 = \u5E45\u306B\u53CE\u3081\u308B3(node.eyebrow ?? "", plan.\u80A9\u66F8?.size ?? 0, LABEL_EYEBROW_SPACING2, node.w);
19042
- const \u540D = \u5E45\u306B\u53CE\u3081\u308B3(node.title ?? "", plan.\u540D\u524D.size, 0, node.w, true);
19043
- const \u8AAC = \u5E45\u306B\u53CE\u3081\u308B3(node.subtitle ?? "", plan.\u8AAC\u660E?.size ?? 0, 0, node.w);
19728
+ return { size, spacing, text: \u5E2F\u3067\u5207\u308B(\u6587\u5B57\u5217, size, \u7BB1\u5E45, (u, f) => \u6E2C\u308B(u, f, spacing)) };
19729
+ }
19730
+ function bottomLabel3(node, cx, plan, textMetrics = "proportional") {
19731
+ const \u80A9 = \u5E45\u306B\u53CE\u3081\u308B3(
19732
+ node.eyebrow ?? "",
19733
+ plan.\u80A9\u66F8?.size ?? 0,
19734
+ LABEL_EYEBROW_SPACING2,
19735
+ node.w,
19736
+ false,
19737
+ textMetrics
19738
+ );
19739
+ const \u540D = \u5E45\u306B\u53CE\u3081\u308B3(node.title ?? "", plan.\u540D\u524D.size, 0, node.w, true, textMetrics);
19740
+ const \u8AAC = \u5E45\u306B\u53CE\u3081\u308B3(
19741
+ node.subtitle ?? "",
19742
+ plan.\u8AAC\u660E?.size ?? 0,
19743
+ 0,
19744
+ node.w,
19745
+ false,
19746
+ textMetrics
19747
+ );
19044
19748
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
19045
19749
  node.eyebrow && plan.\u80A9\u66F8 && /* @__PURE__ */ jsxRuntime.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 }),
19046
19750
  /* @__PURE__ */ jsxRuntime.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 }),
@@ -19059,7 +19763,7 @@ var BANK_STEP_SW = 1;
19059
19763
  var BANK_COLUMN_MIN = 24;
19060
19764
  var BANK_BLD_W_MIN = 120;
19061
19765
  var BANK_BLD_W_MAX = 280;
19062
- function ShapeBankNode({ node, active }) {
19766
+ function ShapeBankNode({ node, active, textMetrics = "proportional" }) {
19063
19767
  const frame = commonFrame5(active);
19064
19768
  const r = shapeRegion(node);
19065
19769
  const \u7DDA = frame.strokeWidth / 2;
@@ -19106,7 +19810,7 @@ function ShapeBankNode({ node, active }) {
19106
19810
  ] });
19107
19811
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
19108
19812
  fitArt(r, \u5E83\u304C\u308A, \u7D75),
19109
- bottomLabel3(node, r.cx, r.label)
19813
+ bottomLabel3(node, r.cx, r.label, textMetrics)
19110
19814
  ] });
19111
19815
  }
19112
19816
  var TRUST_CROWN_RISE = 4;
@@ -19118,7 +19822,12 @@ var TRUST_BASE_H = 14;
19118
19822
  var TRUST_BODY_OUT = 8;
19119
19823
  var TRUST_BLD_W_MIN = 140;
19120
19824
  var TRUST_BLD_W_MAX = 280;
19121
- function ShapeTrustBankNode({ node, active, lang }) {
19825
+ function ShapeTrustBankNode({
19826
+ node,
19827
+ active,
19828
+ lang,
19829
+ textMetrics = "proportional"
19830
+ }) {
19122
19831
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
19123
19832
  const frame = commonFrame5(active);
19124
19833
  const r = shapeRegion(node);
@@ -19172,10 +19881,15 @@ function ShapeTrustBankNode({ node, active, lang }) {
19172
19881
  ] });
19173
19882
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
19174
19883
  fitArt(r, \u5E83\u304C\u308A, \u7D75),
19175
- bottomLabel3(node, r.cx, r.label)
19884
+ bottomLabel3(node, r.cx, r.label, textMetrics)
19176
19885
  ] });
19177
19886
  }
19178
- function ShapePaymentProviderNode({ node, active, lang }) {
19887
+ function ShapePaymentProviderNode({
19888
+ node,
19889
+ active,
19890
+ lang,
19891
+ textMetrics = "proportional"
19892
+ }) {
19179
19893
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
19180
19894
  const frame = commonFrame5(active);
19181
19895
  const r = shapeRegion(node);
@@ -19200,10 +19914,14 @@ function ShapePaymentProviderNode({ node, active, lang }) {
19200
19914
  /* @__PURE__ */ jsxRuntime.jsx("text", { x: cx, y: cy + 9, fontSize: 13, fontWeight: 700, textAnchor: "middle", fill: accentDarker, fontFamily: "Georgia, serif", children: "$" })
19201
19915
  ] }),
19202
19916
  /* @__PURE__ */ jsxRuntime.jsx("text", { x: cx, y: y + boxH - 16, fontSize: 11, fontWeight: 700, letterSpacing: 2, textAnchor: "middle", fill: "#a4b5f2", children: \u5B57\u5F15("paymentProvider.status") }),
19203
- bottomLabel3(node, r.cx, r.label)
19917
+ bottomLabel3(node, r.cx, r.label, textMetrics)
19204
19918
  ] });
19205
19919
  }
19206
- function ShapeCreditCardNode({ node, active }) {
19920
+ function ShapeCreditCardNode({
19921
+ node,
19922
+ active,
19923
+ textMetrics = "proportional"
19924
+ }) {
19207
19925
  const frame = commonFrame5(active);
19208
19926
  const r = shapeRegion(node);
19209
19927
  const cardW = Math.min(r.availW - 30, 260);
@@ -19225,7 +19943,7 @@ function ShapeCreditCardNode({ node, active }) {
19225
19943
  [0, 1, 2, 3].map((block) => /* @__PURE__ */ jsxRuntime.jsx("g", { children: [0, 1, 2, 3].map((dot) => /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: x + 32 + block * (cardW - 64) / 4 + dot * 8, cy: y + cardH - 40, r: 2.8, fill: "#ffffff", stroke: "none" }, dot)) }, block)),
19226
19944
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: x + cardW - 48, cy: y + cardH - 24, r: 15, fill: "#c9302c", opacity: 0.9, stroke: "none" }),
19227
19945
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: x + cardW - 30, cy: y + cardH - 24, r: 15, fill: "#e5c07b", opacity: 0.9, stroke: "none" }),
19228
- bottomLabel3(node, r.cx, r.label)
19946
+ bottomLabel3(node, r.cx, r.label, textMetrics)
19229
19947
  ] });
19230
19948
  }
19231
19949
  var BROKERAGE_TICK_H = 18;
@@ -19250,7 +19968,12 @@ var BROKERAGE_SHADE_OUT = 2;
19250
19968
  var BROKERAGE_W_MIN = BROKERAGE_COLS * BROKERAGE_CELL_W + (BROKERAGE_COLS - 1) * BROKERAGE_GAP_X + 6;
19251
19969
  var BROKERAGE_W_MAX = 140;
19252
19970
  var BROKERAGE_H_MIN = BROKERAGE_TICK_H + BROKERAGE_LOGO_H + BROKERAGE_BASE_H;
19253
- function ShapeBrokerageNode({ node, active, lang }) {
19971
+ function ShapeBrokerageNode({
19972
+ node,
19973
+ active,
19974
+ lang,
19975
+ textMetrics = "proportional"
19976
+ }) {
19254
19977
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
19255
19978
  const frame = commonFrame5(active);
19256
19979
  const r = shapeRegion(node);
@@ -19289,7 +20012,7 @@ function ShapeBrokerageNode({ node, active, lang }) {
19289
20012
  }
19290
20013
  ];
19291
20014
  const \u7D75 = (\u500D\u7387) => {
19292
- const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089);
20015
+ const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089, textMetrics);
19293
20016
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
19294
20017
  /* @__PURE__ */ jsxRuntime.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" }),
19295
20018
  /* @__PURE__ */ jsxRuntime.jsx("rect", { "data-cdl-role": "node-body", x, y, width: w, height: h, fill: "#255a7a", stroke: accentDarker, strokeWidth: frame.strokeWidth }),
@@ -19317,12 +20040,17 @@ function ShapeBrokerageNode({ node, active, lang }) {
19317
20040
  };
19318
20041
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
19319
20042
  fitArt(r, \u5E83\u304C\u308A, \u7D75),
19320
- bottomLabel3(node, r.cx, r.label)
20043
+ bottomLabel3(node, r.cx, r.label, textMetrics)
19321
20044
  ] });
19322
20045
  }
19323
20046
  var EXCHANGE_SUB_SIZE = 11;
19324
20047
  var EXCHANGE_HEX_R = 52;
19325
- function ShapeExchangeNode({ node, active, lang }) {
20048
+ function ShapeExchangeNode({
20049
+ node,
20050
+ active,
20051
+ lang,
20052
+ textMetrics = "proportional"
20053
+ }) {
19326
20054
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
19327
20055
  const frame = commonFrame5(active);
19328
20056
  const r = shapeRegion(node);
@@ -19367,7 +20095,7 @@ function ShapeExchangeNode({ node, active, lang }) {
19367
20095
  }
19368
20096
  ];
19369
20097
  const \u7D75 = (\u500D\u7387) => {
19370
- const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089);
20098
+ const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089, textMetrics);
19371
20099
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
19372
20100
  nodes.map((n, i) => /* @__PURE__ */ jsxRuntime.jsx("line", { x1: cx, y1: cy, x2: n.cx, y2: n.cy, stroke: accentDarker, strokeWidth: 1.5, strokeDasharray: "3 2" }, `l${i}`)),
19373
20101
  nodes.map((n, i) => {
@@ -19386,7 +20114,7 @@ function ShapeExchangeNode({ node, active, lang }) {
19386
20114
  };
19387
20115
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
19388
20116
  fitArt(r, \u5E83\u304C\u308A, \u7D75),
19389
- bottomLabel3(node, r.cx, r.label)
20117
+ bottomLabel3(node, r.cx, r.label, textMetrics)
19390
20118
  ] });
19391
20119
  }
19392
20120
  var ATM_SIGN_H = 26;
@@ -19403,7 +20131,12 @@ var ATM_PANEL_H = 146;
19403
20131
  var ATM_W_MIN = 100;
19404
20132
  var ATM_W_MAX = ATM_PANEL_W;
19405
20133
  var ATM_H_MIN = ATM_SIGN_H + ATM_SIGN_GAP + 30 + ATM_FLOOR_RESERVE;
19406
- function ShapeAtmNode({ node, active, lang }) {
20134
+ function ShapeAtmNode({
20135
+ node,
20136
+ active,
20137
+ lang,
20138
+ textMetrics = "proportional"
20139
+ }) {
19407
20140
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
19408
20141
  const frame = commonFrame5(active);
19409
20142
  const r = shapeRegion(node);
@@ -19487,7 +20220,7 @@ function ShapeAtmNode({ node, active, lang }) {
19487
20220
  ] });
19488
20221
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
19489
20222
  fitArt(r, \u5E83\u304C\u308A, \u7D75),
19490
- bottomLabel3(node, r.cx, r.label)
20223
+ bottomLabel3(node, r.cx, r.label, textMetrics)
19491
20224
  ] });
19492
20225
  }
19493
20226
  var commonFrame6 = (active) => ({
@@ -19506,7 +20239,8 @@ function \u5B57\u306E\u6BD42(c) {
19506
20239
  if (\u5E83\u5B572.has(c)) return \u5E83\u5B57\u6BD42;
19507
20240
  return (c.codePointAt(0) ?? 0) < 128 ? \u4E26\u5B57\u6BD42 : \u5E83\u5B57\u6BD42;
19508
20241
  }
19509
- function \u5B57\u5E452(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593) {
20242
+ function \u5B57\u5E452(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, textMetrics = "proportional") {
20243
+ if (textMetrics === "monospace") return textWidth(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, textMetrics);
19510
20244
  let \u5E45 = 0;
19511
20245
  let \u5B57\u6570 = 0;
19512
20246
  for (const c of \u6587\u5B57\u5217) {
@@ -19515,18 +20249,33 @@ function \u5B57\u5E452(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593) {
19515
20249
  }
19516
20250
  return \u5E45 + \u5B57\u9593 * \u5B57\u6570;
19517
20251
  }
19518
- function \u5E45\u306B\u53CE\u3081\u308B4(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45, \u984C\u304B = false) {
19519
- const \u5E45 = \u5B57\u5E452(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593);
19520
- 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;
20252
+ function \u5E45\u306B\u53CE\u3081\u308B4(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593, \u7BB1\u5E45, \u984C\u304B = false, textMetrics = "proportional") {
20253
+ const \u6E2C\u308B = (t, s, ls) => \u5B57\u5E452(t, s, ls, textMetrics);
20254
+ const \u5E45 = \u6E2C\u308B(\u6587\u5B57\u5217, \u5927\u304D\u3055, \u5B57\u9593);
20255
+ 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;
19521
20256
  const \u500D\u7387 = \u5E45 > 0 && \u7BB1\u5E45 > 0 ? Math.min(1, Math.max(\u7BB1\u5E45 / \u5E45, \u4E0B\u9650)) : 1;
19522
20257
  const size = \u5927\u304D\u3055 * \u500D\u7387;
19523
20258
  const spacing = \u5B57\u9593 * \u500D\u7387;
19524
- return { size, spacing, text: \u5E2F\u3067\u5207\u308B(\u6587\u5B57\u5217, size, \u7BB1\u5E45, (u, f) => \u5B57\u5E452(u, f, spacing)) };
19525
- }
19526
- function bottomLabel4(node, cx, plan) {
19527
- const \u80A9 = \u5E45\u306B\u53CE\u3081\u308B4(node.eyebrow ?? "", plan.\u80A9\u66F8?.size ?? 0, LABEL_EYEBROW_SPACING3, node.w);
19528
- const \u540D = \u5E45\u306B\u53CE\u3081\u308B4(node.title ?? "", plan.\u540D\u524D.size, 0, node.w, true);
19529
- const \u8AAC = \u5E45\u306B\u53CE\u3081\u308B4(node.subtitle ?? "", plan.\u8AAC\u660E?.size ?? 0, 0, node.w);
20259
+ return { size, spacing, text: \u5E2F\u3067\u5207\u308B(\u6587\u5B57\u5217, size, \u7BB1\u5E45, (u, f) => \u6E2C\u308B(u, f, spacing)) };
20260
+ }
20261
+ function bottomLabel4(node, cx, plan, textMetrics = "proportional") {
20262
+ const \u80A9 = \u5E45\u306B\u53CE\u3081\u308B4(
20263
+ node.eyebrow ?? "",
20264
+ plan.\u80A9\u66F8?.size ?? 0,
20265
+ LABEL_EYEBROW_SPACING3,
20266
+ node.w,
20267
+ false,
20268
+ textMetrics
20269
+ );
20270
+ const \u540D = \u5E45\u306B\u53CE\u3081\u308B4(node.title ?? "", plan.\u540D\u524D.size, 0, node.w, true, textMetrics);
20271
+ const \u8AAC = \u5E45\u306B\u53CE\u3081\u308B4(
20272
+ node.subtitle ?? "",
20273
+ plan.\u8AAC\u660E?.size ?? 0,
20274
+ 0,
20275
+ node.w,
20276
+ false,
20277
+ textMetrics
20278
+ );
19530
20279
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
19531
20280
  node.eyebrow && plan.\u80A9\u66F8 && /* @__PURE__ */ jsxRuntime.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 }),
19532
20281
  /* @__PURE__ */ jsxRuntime.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 }),
@@ -19538,7 +20287,7 @@ var WEBSITE_BAR_H = 32;
19538
20287
  var WEBSITE_H_MIN = WEBSITE_BAR_H + 98;
19539
20288
  var WEBSITE_W_MIN = 160;
19540
20289
  var WEBSITE_W_MAX = 280;
19541
- function ShapeWebsiteNode({ node, active }) {
20290
+ function ShapeWebsiteNode({ node, active, textMetrics = "proportional" }) {
19542
20291
  const frame = commonFrame6(active);
19543
20292
  const r = shapeRegion(node);
19544
20293
  const cx = r.cx;
@@ -19564,10 +20313,10 @@ function ShapeWebsiteNode({ node, active }) {
19564
20313
  ] });
19565
20314
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
19566
20315
  fitArt(r, \u5E83\u304C\u308A, \u7D75),
19567
- bottomLabel4(node, r.cx, r.label)
20316
+ bottomLabel4(node, r.cx, r.label, textMetrics)
19568
20317
  ] });
19569
20318
  }
19570
- function ShapeStorefrontNode({ node, active, lang }) {
20319
+ function ShapeStorefrontNode({ node, active, lang, textMetrics = "proportional" }) {
19571
20320
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
19572
20321
  const frame = commonFrame6(active);
19573
20322
  const r = shapeRegion(node);
@@ -19612,7 +20361,7 @@ function ShapeStorefrontNode({ node, active, lang }) {
19612
20361
  /* @__PURE__ */ jsxRuntime.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") }),
19613
20362
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: doorX + 6, cy: doorY + doorH * 0.55, r: 1.5, fill: "#c15a4a" }),
19614
20363
  /* @__PURE__ */ jsxRuntime.jsx("rect", { x: x - 6, y: y + bh - 6, width: bw + 12, height: 8, fill: "#5a6270", stroke: "none" }),
19615
- bottomLabel4(node, r.cx, r.label)
20364
+ bottomLabel4(node, r.cx, r.label, textMetrics)
19616
20365
  ] });
19617
20366
  }
19618
20367
  var WAREHOUSE_ROOF_H = 18;
@@ -19626,7 +20375,7 @@ var WAREHOUSE_SHADOW_RX_RATIO = 0.5;
19626
20375
  var WAREHOUSE_H_MIN = WAREHOUSE_ROOF_H + WAREHOUSE_SIGN_H + 68;
19627
20376
  var WAREHOUSE_W_MIN = 160;
19628
20377
  var WAREHOUSE_W_MAX = 240;
19629
- function ShapeWarehouseNode({ node, active, lang }) {
20378
+ function ShapeWarehouseNode({ node, active, lang, textMetrics = "proportional" }) {
19630
20379
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
19631
20380
  const frame = commonFrame6(active);
19632
20381
  const r = shapeRegion(node);
@@ -19679,13 +20428,13 @@ function ShapeWarehouseNode({ node, active, lang }) {
19679
20428
  ] });
19680
20429
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
19681
20430
  fitArt(r, \u5E83\u304C\u308A, \u7D75),
19682
- bottomLabel4(node, r.cx, r.label)
20431
+ bottomLabel4(node, r.cx, r.label, textMetrics)
19683
20432
  ] });
19684
20433
  }
19685
20434
  var HANDLE_GRIP_X = 118;
19686
20435
  var HANDLE_GRIP_R = 4;
19687
20436
  var CART_SHADOW_RX = 80;
19688
- function ShapeOnlineShopNode({ node, active }) {
20437
+ function ShapeOnlineShopNode({ node, active, textMetrics = "proportional" }) {
19689
20438
  const frame = commonFrame6(active);
19690
20439
  const r = shapeRegion(node);
19691
20440
  const cy = r.cy + 10;
@@ -19741,10 +20490,10 @@ function ShapeOnlineShopNode({ node, active }) {
19741
20490
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: wheelR, cy: wheelY, r: 16 * s, fill: "#0f1830", stroke: "#000", strokeWidth: 2 * s }),
19742
20491
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: wheelR, cy: wheelY, r: 8 * s, fill: "#5a6270", stroke: "#0f1830", strokeWidth: 1.5 * s }),
19743
20492
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: wheelR, cy: wheelY, r: 2 * s, fill: "#0f1830" }),
19744
- bottomLabel4(node, r.cx, r.label)
20493
+ bottomLabel4(node, r.cx, r.label, textMetrics)
19745
20494
  ] });
19746
20495
  }
19747
- function ShapeCdnEdgeNode({ node, active }) {
20496
+ function ShapeCdnEdgeNode({ node, active, textMetrics = "proportional" }) {
19748
20497
  const frame = commonFrame6(active);
19749
20498
  const r = shapeRegion(node);
19750
20499
  const cx = r.cx;
@@ -19807,7 +20556,7 @@ function ShapeCdnEdgeNode({ node, active }) {
19807
20556
  ] });
19808
20557
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
19809
20558
  fitArt(r, { \u4E0A: \u5E83\u304C\u308A, \u4E0B: \u5E83\u304C\u308A, \u5DE6: \u5E83\u304C\u308A, \u53F3: \u5E83\u304C\u308A }, \u7D75),
19810
- bottomLabel4(node, r.cx, r.label)
20559
+ bottomLabel4(node, r.cx, r.label, textMetrics)
19811
20560
  ] });
19812
20561
  }
19813
20562
  var API_ROW_TOP = 52;
@@ -19822,7 +20571,7 @@ var API_METHOD_BOX_W = 54;
19822
20571
  var API_METHOD_TEXT_W = 48;
19823
20572
  var API_W_MIN = 200;
19824
20573
  var API_W_MAX = 300;
19825
- function ShapeApiGatewayNode({ node, active, lang }) {
20574
+ function ShapeApiGatewayNode({ node, active, lang, textMetrics = "proportional" }) {
19826
20575
  const \u5B57\u5F15 = \u5B57\u5F15\u304D\u3092\u4F5C\u308B(lang);
19827
20576
  const frame = commonFrame6(active);
19828
20577
  const r = shapeRegion(node);
@@ -19834,7 +20583,13 @@ function ShapeApiGatewayNode({ node, active, lang }) {
19834
20583
  const x = cx - bw / 2;
19835
20584
  const y = r.cy - \u7E26 / 2 + \u4F59\u767D;
19836
20585
  const \u5E83\u304C\u308A = { \u4E0A: \u7E26 / 2, \u4E0B: \u7E26 / 2, \u5DE6: bw / 2 + \u4F59\u767D, \u53F3: bw / 2 + \u4F59\u767D };
19837
- 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)));
20586
+ const \u7A2E\u985E\u306E\u5B57 = (s) => Math.min(
20587
+ 11,
20588
+ 11 * API_METHOD_TEXT_W / Math.max(
20589
+ displayWidth(s) * 11 * MONO_ADVANCE_RATIO,
20590
+ textWidth(s, 11, 0, textMetrics)
20591
+ )
20592
+ );
19838
20593
  const rowPitch = Math.max(
19839
20594
  API_ROW_PITCH_MIN,
19840
20595
  (bh - API_ROW_TOP - API_ROW_H - API_ROW_BOTTOM_PAD) / (API_ROWS - 1)
@@ -19850,7 +20605,7 @@ function ShapeApiGatewayNode({ node, active, lang }) {
19850
20605
  \u5E2F: { \u5E45: bw - 32 - 64 - 16, \u9AD8\u3055: API_ROW_H }
19851
20606
  }));
19852
20607
  const \u7D75 = (\u500D\u7387) => {
19853
- const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089);
20608
+ const \u500D = \u6253\u3061\u6D88\u3057\u306E\u500D\u7387(\u500D\u7387, \u6253\u3061\u6D88\u3059\u5B57\u3089, textMetrics);
19854
20609
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
19855
20610
  /* @__PURE__ */ jsxRuntime.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" }),
19856
20611
  /* @__PURE__ */ jsxRuntime.jsx("rect", { "data-cdl-role": "node-body", x, y, width: bw, height: bh, rx: 10, fill: "#1a2332", stroke: frame.stroke, strokeWidth: frame.strokeWidth }),
@@ -19867,7 +20622,7 @@ function ShapeApiGatewayNode({ node, active, lang }) {
19867
20622
  };
19868
20623
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
19869
20624
  fitArt(r, \u5E83\u304C\u308A, \u7D75),
19870
- bottomLabel4(node, r.cx, r.label)
20625
+ bottomLabel4(node, r.cx, r.label, textMetrics)
19871
20626
  ] });
19872
20627
  }
19873
20628
  function bottomLabel5(node, cx, plan) {
@@ -20167,6 +20922,7 @@ function CdlNodeView({
20167
20922
  chartLineScale,
20168
20923
  \u95A2\u4FC2\u306E\u53D7\u3051\u53E3,
20169
20924
  lang,
20925
+ textMetrics,
20170
20926
  \u5024\u306E\u540D\u524D
20171
20927
  }) {
20172
20928
  const value = node.value ? interpolate(node.value, stateValues, \u5024\u306E\u540D\u524D) : void 0;
@@ -20211,7 +20967,14 @@ function CdlNodeView({
20211
20967
  return /* @__PURE__ */ jsxRuntime.jsx(CardNode, { node: resolvedNode, active });
20212
20968
  // 時系列のやり取り (#578)。 1 つの箱が図を丸ごと描く = 縦が時間で、参加者は箱を持たない
20213
20969
  case "sequence-board":
20214
- return /* @__PURE__ */ jsxRuntime.jsx(SequenceBoardNode, { node: resolvedNode, stateValues });
20970
+ return /* @__PURE__ */ jsxRuntime.jsx(
20971
+ SequenceBoardNode,
20972
+ {
20973
+ node: resolvedNode,
20974
+ stateValues,
20975
+ textMetrics
20976
+ }
20977
+ );
20215
20978
  // 図表 9 種は payload が `{signal}` を取れるので stateValues を渡す
20216
20979
  // (`render/payload-binding.ts` が描画直前に解決する)。 取れる欄は種別で違い、
20217
20980
  // 数と語を取る 7 種に対し、mind-map / tree-hierarchy は **名前だけ** を取る (#467)。
@@ -20236,7 +20999,8 @@ function CdlNodeView({
20236
20999
  active,
20237
21000
  stateValues,
20238
21001
  drawing,
20239
- progress
21002
+ progress,
21003
+ textMetrics
20240
21004
  }
20241
21005
  );
20242
21006
  case "chart-gauge":
@@ -20247,7 +21011,8 @@ function CdlNodeView({
20247
21011
  active,
20248
21012
  stateValues,
20249
21013
  drawing,
20250
- progress
21014
+ progress,
21015
+ textMetrics
20251
21016
  }
20252
21017
  );
20253
21018
  case "chart-stacked-bar":
@@ -20258,7 +21023,8 @@ function CdlNodeView({
20258
21023
  active,
20259
21024
  stateValues,
20260
21025
  drawing,
20261
- progress
21026
+ progress,
21027
+ textMetrics
20262
21028
  }
20263
21029
  );
20264
21030
  case "chart-slope":
@@ -20269,7 +21035,8 @@ function CdlNodeView({
20269
21035
  active,
20270
21036
  stateValues,
20271
21037
  drawing,
20272
- progress
21038
+ progress,
21039
+ textMetrics
20273
21040
  }
20274
21041
  );
20275
21042
  case "chart-waffle":
@@ -20280,11 +21047,20 @@ function CdlNodeView({
20280
21047
  active,
20281
21048
  stateValues,
20282
21049
  drawing,
20283
- progress
21050
+ progress,
21051
+ textMetrics
20284
21052
  }
20285
21053
  );
20286
21054
  case "chart-stat":
20287
- return /* @__PURE__ */ jsxRuntime.jsx(ChartStatNode, { node: resolvedNode, active, stateValues });
21055
+ return /* @__PURE__ */ jsxRuntime.jsx(
21056
+ ChartStatNode,
21057
+ {
21058
+ node: resolvedNode,
21059
+ active,
21060
+ stateValues,
21061
+ textMetrics
21062
+ }
21063
+ );
20288
21064
  case "chart-radial":
20289
21065
  return /* @__PURE__ */ jsxRuntime.jsx(
20290
21066
  ChartRadialNode,
@@ -20293,7 +21069,8 @@ function CdlNodeView({
20293
21069
  active,
20294
21070
  stateValues,
20295
21071
  drawing,
20296
- progress
21072
+ progress,
21073
+ textMetrics
20297
21074
  }
20298
21075
  );
20299
21076
  case "chart-bar":
@@ -20326,7 +21103,8 @@ function CdlNodeView({
20326
21103
  active,
20327
21104
  stateValues,
20328
21105
  drawing,
20329
- progress
21106
+ progress,
21107
+ textMetrics
20330
21108
  }
20331
21109
  );
20332
21110
  case "funnel-stages":
@@ -20337,11 +21115,20 @@ function CdlNodeView({
20337
21115
  active,
20338
21116
  stateValues,
20339
21117
  drawing,
20340
- progress
21118
+ progress,
21119
+ textMetrics
20341
21120
  }
20342
21121
  );
20343
21122
  case "quadrant-matrix":
20344
- return /* @__PURE__ */ jsxRuntime.jsx(QuadrantNode, { node: resolvedNode, active, stateValues });
21123
+ return /* @__PURE__ */ jsxRuntime.jsx(
21124
+ QuadrantNode,
21125
+ {
21126
+ node: resolvedNode,
21127
+ active,
21128
+ stateValues,
21129
+ textMetrics
21130
+ }
21131
+ );
20345
21132
  case "tree-hierarchy":
20346
21133
  return /* @__PURE__ */ jsxRuntime.jsx(
20347
21134
  TreeNode,
@@ -20350,7 +21137,8 @@ function CdlNodeView({
20350
21137
  active,
20351
21138
  stateValues,
20352
21139
  drawing,
20353
- progress
21140
+ progress,
21141
+ textMetrics
20354
21142
  }
20355
21143
  );
20356
21144
  case "journey-map":
@@ -20365,91 +21153,91 @@ function CdlNodeView({
20365
21153
  }
20366
21154
  );
20367
21155
  case "shape-file":
20368
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeFileNode, { node: resolvedNode, active });
21156
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeFileNode, { node: resolvedNode, active, textMetrics });
20369
21157
  case "shape-folder":
20370
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeFolderNode, { node: resolvedNode, active });
21158
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeFolderNode, { node: resolvedNode, active, textMetrics });
20371
21159
  case "shape-cloud":
20372
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeCloudNode, { node: resolvedNode, active });
21160
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeCloudNode, { node: resolvedNode, active, textMetrics });
20373
21161
  case "shape-cylinder":
20374
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeCylinderNode, { node: resolvedNode, active });
21162
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeCylinderNode, { node: resolvedNode, active, textMetrics });
20375
21163
  case "shape-hexagon":
20376
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeHexagonNode, { node: resolvedNode, active });
21164
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeHexagonNode, { node: resolvedNode, active, textMetrics });
20377
21165
  case "shape-diamond":
20378
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeDiamondNode, { node: resolvedNode, active });
21166
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeDiamondNode, { node: resolvedNode, active, textMetrics });
20379
21167
  case "shape-stack":
20380
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeStackNode, { node: resolvedNode, active });
21168
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeStackNode, { node: resolvedNode, active, textMetrics });
20381
21169
  case "shape-person":
20382
- return /* @__PURE__ */ jsxRuntime.jsx(ShapePersonNode, { node: resolvedNode, active });
21170
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapePersonNode, { node: resolvedNode, active, textMetrics });
20383
21171
  case "shape-window":
20384
21172
  return /* @__PURE__ */ jsxRuntime.jsx(ShapeWindowNode, { node: resolvedNode, active });
20385
21173
  case "shape-terminal":
20386
21174
  return /* @__PURE__ */ jsxRuntime.jsx(ShapeTerminalNode, { node: resolvedNode, active, lang });
20387
21175
  case "shape-code-block":
20388
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeCodeBlockNode, { node: resolvedNode, active, lang });
21176
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeCodeBlockNode, { node: resolvedNode, active, lang, textMetrics });
20389
21177
  case "shape-kanban-card":
20390
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeKanbanCardNode, { node: resolvedNode, active, lang });
21178
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeKanbanCardNode, { node: resolvedNode, active, lang, textMetrics });
20391
21179
  case "shape-message-bubble":
20392
21180
  return /* @__PURE__ */ jsxRuntime.jsx(ShapeMessageBubbleNode, { node: resolvedNode, active });
20393
21181
  case "shape-gear":
20394
21182
  return /* @__PURE__ */ jsxRuntime.jsx(ShapeGearNode, { node: resolvedNode, active });
20395
21183
  case "shape-server-rack":
20396
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeServerRackNode, { node: resolvedNode, active });
21184
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeServerRackNode, { node: resolvedNode, active, textMetrics });
20397
21185
  case "shape-network-node":
20398
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeNetworkNodeNode, { node: resolvedNode, active });
21186
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeNetworkNodeNode, { node: resolvedNode, active, textMetrics });
20399
21187
  case "shape-mobile-device":
20400
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeMobileDeviceNode, { node: resolvedNode, active });
21188
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeMobileDeviceNode, { node: resolvedNode, active, textMetrics });
20401
21189
  case "shape-iot-sensor":
20402
21190
  return /* @__PURE__ */ jsxRuntime.jsx(ShapeIotSensorNode, { node: resolvedNode, active });
20403
21191
  case "shape-robot-arm":
20404
21192
  return /* @__PURE__ */ jsxRuntime.jsx(ShapeRobotArmNode, { node: resolvedNode, active });
20405
21193
  case "shape-satellite":
20406
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeSatelliteNode, { node: resolvedNode, active });
21194
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeSatelliteNode, { node: resolvedNode, active, textMetrics });
20407
21195
  case "shape-smart-contract":
20408
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeSmartContractNode, { node: resolvedNode, active, lang });
21196
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeSmartContractNode, { node: resolvedNode, active, lang, textMetrics });
20409
21197
  case "shape-blockchain-block":
20410
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeBlockchainBlockNode, { node: resolvedNode, active, lang });
21198
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeBlockchainBlockNode, { node: resolvedNode, active, lang, textMetrics });
20411
21199
  case "shape-rpc-node":
20412
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeRpcNodeNode, { node: resolvedNode, active, lang });
21200
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeRpcNodeNode, { node: resolvedNode, active, lang, textMetrics });
20413
21201
  case "shape-wallet":
20414
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeWalletNode, { node: resolvedNode, active });
21202
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeWalletNode, { node: resolvedNode, active, textMetrics });
20415
21203
  case "shape-nft":
20416
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeNftNode, { node: resolvedNode, active });
21204
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeNftNode, { node: resolvedNode, active, textMetrics });
20417
21205
  case "shape-token":
20418
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeTokenNode, { node: resolvedNode, active });
21206
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeTokenNode, { node: resolvedNode, active, textMetrics });
20419
21207
  case "shape-blockchain":
20420
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeBlockchainNode, { node: resolvedNode, active });
21208
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeBlockchainNode, { node: resolvedNode, active, textMetrics });
20421
21209
  case "shape-bitcoin-chain":
20422
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeBitcoinChainNode, { node: resolvedNode, active });
21210
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeBitcoinChainNode, { node: resolvedNode, active, textMetrics });
20423
21211
  case "shape-ethereum-chain":
20424
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeEthereumChainNode, { node: resolvedNode, active });
21212
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeEthereumChainNode, { node: resolvedNode, active, textMetrics });
20425
21213
  case "shape-blockchain-node":
20426
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeBlockchainNodeNode, { node: resolvedNode, active });
21214
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeBlockchainNodeNode, { node: resolvedNode, active, textMetrics });
20427
21215
  case "shape-bank":
20428
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeBankNode, { node: resolvedNode, active });
21216
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeBankNode, { node: resolvedNode, active, textMetrics });
20429
21217
  case "shape-trust-bank":
20430
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeTrustBankNode, { node: resolvedNode, active, lang });
21218
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeTrustBankNode, { node: resolvedNode, active, lang, textMetrics });
20431
21219
  case "shape-payment-provider":
20432
- return /* @__PURE__ */ jsxRuntime.jsx(ShapePaymentProviderNode, { node: resolvedNode, active, lang });
21220
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapePaymentProviderNode, { node: resolvedNode, active, lang, textMetrics });
20433
21221
  case "shape-credit-card":
20434
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeCreditCardNode, { node: resolvedNode, active });
21222
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeCreditCardNode, { node: resolvedNode, active, textMetrics });
20435
21223
  case "shape-brokerage":
20436
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeBrokerageNode, { node: resolvedNode, active, lang });
21224
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeBrokerageNode, { node: resolvedNode, active, lang, textMetrics });
20437
21225
  case "shape-exchange":
20438
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeExchangeNode, { node: resolvedNode, active, lang });
21226
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeExchangeNode, { node: resolvedNode, active, lang, textMetrics });
20439
21227
  case "shape-atm":
20440
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeAtmNode, { node: resolvedNode, active, lang });
21228
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeAtmNode, { node: resolvedNode, active, lang, textMetrics });
20441
21229
  case "shape-website":
20442
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeWebsiteNode, { node: resolvedNode, active });
21230
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeWebsiteNode, { node: resolvedNode, active, textMetrics });
20443
21231
  case "shape-storefront":
20444
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeStorefrontNode, { node: resolvedNode, active, lang });
21232
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeStorefrontNode, { node: resolvedNode, active, lang, textMetrics });
20445
21233
  case "shape-warehouse":
20446
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeWarehouseNode, { node: resolvedNode, active, lang });
21234
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeWarehouseNode, { node: resolvedNode, active, lang, textMetrics });
20447
21235
  case "shape-online-shop":
20448
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeOnlineShopNode, { node: resolvedNode, active });
21236
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeOnlineShopNode, { node: resolvedNode, active, textMetrics });
20449
21237
  case "shape-cdn-edge":
20450
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeCdnEdgeNode, { node: resolvedNode, active });
21238
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeCdnEdgeNode, { node: resolvedNode, active, textMetrics });
20451
21239
  case "shape-api-gateway":
20452
- return /* @__PURE__ */ jsxRuntime.jsx(ShapeApiGatewayNode, { node: resolvedNode, active, lang });
21240
+ return /* @__PURE__ */ jsxRuntime.jsx(ShapeApiGatewayNode, { node: resolvedNode, active, lang, textMetrics });
20453
21241
  case "shape-auditor":
20454
21242
  return /* @__PURE__ */ jsxRuntime.jsx(ShapeAuditorNode, { node: resolvedNode, active });
20455
21243
  case "shape-regulator":
@@ -20466,8 +21254,20 @@ function CdlNodeView({
20466
21254
  return /* @__PURE__ */ jsxRuntime.jsx(MarkStartNode, { node: resolvedNode, active });
20467
21255
  case "mark-end":
20468
21256
  return /* @__PURE__ */ jsxRuntime.jsx(MarkEndNode, { node: resolvedNode, active });
21257
+ case "station":
21258
+ return /* @__PURE__ */ jsxRuntime.jsx(StationNode, { node: resolvedNode, active });
20469
21259
  default:
20470
- return /* @__PURE__ */ jsxRuntime.jsx(GenericNode, { node: resolvedNode, active, value: node.value, stateValues, \u5024\u306E\u540D\u524D });
21260
+ return /* @__PURE__ */ jsxRuntime.jsx(
21261
+ GenericNode,
21262
+ {
21263
+ node: resolvedNode,
21264
+ active,
21265
+ value: node.value,
21266
+ stateValues,
21267
+ \u5024\u306E\u540D\u524D,
21268
+ textMetrics
21269
+ }
21270
+ );
20471
21271
  }
20472
21272
  })();
20473
21273
  const offsetX = node.renderOffsetX !== void 0 ? resolveNumericAttr(node.renderOffsetX, stateValues, 0) : 0;
@@ -20528,7 +21328,7 @@ function CdlNodeView({
20528
21328
  }
20529
21329
  ),
20530
21330
  inner,
20531
- \u7BB1\u306E\u4E0A\u306E\u8A9E(resolvedNode)
21331
+ \u7BB1\u306E\u4E0A\u306E\u8A9E(resolvedNode, textMetrics ?? "proportional")
20532
21332
  ]
20533
21333
  }
20534
21334
  );
@@ -20537,17 +21337,17 @@ var FIGURE_TITLE_GAP = 10;
20537
21337
  var FIGURE_TITLE_SIZE = 15;
20538
21338
  var FIGURE_EYEBROW_SIZE = 11;
20539
21339
  var FIGURE_EYEBROW_LIFT = 1.1;
20540
- function \u5E45\u306B\u53CE\u3081\u305F\u5927\u304D\u3055(\u8A9E, \u7D20\u306E\u5927\u304D\u3055, \u5E45) {
20541
- const \u5B9F\u5E45 = textWidth(\u8A9E, \u7D20\u306E\u5927\u304D\u3055, 0);
21340
+ function \u5E45\u306B\u53CE\u3081\u305F\u5927\u304D\u3055(\u8A9E, \u7D20\u306E\u5927\u304D\u3055, \u5E45, textMetrics = "proportional") {
21341
+ const \u5B9F\u5E45 = textWidth(\u8A9E, \u7D20\u306E\u5927\u304D\u3055, 0, textMetrics);
20542
21342
  return \u5B9F\u5E45 > \u5E45 ? \u7D20\u306E\u5927\u304D\u3055 * \u5E45 / \u5B9F\u5E45 : \u7D20\u306E\u5927\u304D\u3055;
20543
21343
  }
20544
- function \u7BB1\u306E\u4E0A\u306E\u8A9E(node) {
21344
+ function \u7BB1\u306E\u4E0A\u306E\u8A9E(node, textMetrics = "proportional") {
20545
21345
  if (!drawsFigureTitle(node.kind)) return null;
20546
21346
  const \u540D\u524D = (node.title ?? "").trim();
20547
21347
  const \u5C0F\u898B\u51FA\u3057 = (node.eyebrow ?? "").trim();
20548
21348
  if (\u540D\u524D === "" && \u5C0F\u898B\u51FA\u3057 === "") return null;
20549
21349
  const \u984C\u306Ey = node.cy - node.h / 2 - FIGURE_TITLE_GAP;
20550
- const \u984C\u306E\u5927\u304D\u3055 = \u5E45\u306B\u53CE\u3081\u305F\u5927\u304D\u3055(\u540D\u524D, FIGURE_TITLE_SIZE, node.w);
21350
+ const \u984C\u306E\u5927\u304D\u3055 = \u5E45\u306B\u53CE\u3081\u305F\u5927\u304D\u3055(\u540D\u524D, FIGURE_TITLE_SIZE, node.w, textMetrics);
20551
21351
  const \u5C0F\u898B\u51FA\u3057\u306Ey = \u540D\u524D === "" ? \u984C\u306Ey : \u984C\u306Ey - \u984C\u306E\u5927\u304D\u3055 * FIGURE_EYEBROW_LIFT;
20552
21352
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
20553
21353
  \u5C0F\u898B\u51FA\u3057 !== "" && /* @__PURE__ */ jsxRuntime.jsx(
@@ -20557,7 +21357,7 @@ function \u7BB1\u306E\u4E0A\u306E\u8A9E(node) {
20557
21357
  x: node.cx,
20558
21358
  y: \u5C0F\u898B\u51FA\u3057\u306Ey,
20559
21359
  textAnchor: "middle",
20560
- fontSize: \u5E45\u306B\u53CE\u3081\u305F\u5927\u304D\u3055(\u5C0F\u898B\u51FA\u3057, FIGURE_EYEBROW_SIZE, node.w),
21360
+ fontSize: \u5E45\u306B\u53CE\u3081\u305F\u5927\u304D\u3055(\u5C0F\u898B\u51FA\u3057, FIGURE_EYEBROW_SIZE, node.w, textMetrics),
20561
21361
  fontWeight: 600,
20562
21362
  letterSpacing: 0.6,
20563
21363
  fill: "var(--cdl-text-dim, #5a6270)",
@@ -20698,15 +21498,15 @@ function CdlStage({
20698
21498
  }, [laid]);
20699
21499
  const edgeHeadMarkers = react.useMemo(() => {
20700
21500
  const referenced = /* @__PURE__ */ new Set();
20701
- const add = (tone, head, fill) => {
21501
+ const add2 = (tone, head, fill) => {
20702
21502
  for (const small of [false, true]) {
20703
21503
  const id = edgeHeadMarkerName(tone, head, small, fill);
20704
21504
  if (id !== void 0) referenced.add(id);
20705
21505
  }
20706
21506
  };
20707
21507
  for (const edge of laid.edges) {
20708
- add(edge.tone, edge.head, edge.headFill);
20709
- if (edge.tailHead !== void 0) add(edge.tone, edge.tailHead, edge.tailHeadFill);
21508
+ add2(edge.tone, edge.head, edge.headFill);
21509
+ if (edge.tailHead !== void 0) add2(edge.tone, edge.tailHead, edge.tailHeadFill);
20710
21510
  }
20711
21511
  return Object.entries(TONE).flatMap(
20712
21512
  ([tone, color]) => [
@@ -20882,6 +21682,7 @@ function CdlStage({
20882
21682
  node,
20883
21683
  active: activeSet.has(node.id),
20884
21684
  lang: laid.lang,
21685
+ textMetrics: laid.textMetrics,
20885
21686
  \u95A2\u4FC2\u306E\u53D7\u3051\u53E3: \u7BB1\u306E\u53D7\u3051\u53E3,
20886
21687
  drawing: \u63CF\u304F,
20887
21688
  progress: \u63CF\u304F ? \u63CF\u304F\u9032\u307F : progress,
@@ -20898,7 +21699,8 @@ function CdlStage({
20898
21699
  CdlEdgeLabelView,
20899
21700
  {
20900
21701
  edge,
20901
- active: activeSet.has(edge.id)
21702
+ active: activeSet.has(edge.id),
21703
+ textMetrics: laid.textMetrics
20902
21704
  },
20903
21705
  `label-${edge.id}`
20904
21706
  )),
@@ -20908,7 +21710,8 @@ function CdlStage({
20908
21710
  {
20909
21711
  edge,
20910
21712
  active: activeSet.has(edge.id),
20911
- \u7AEF
21713
+ \u7AEF,
21714
+ textMetrics: laid.textMetrics
20912
21715
  },
20913
21716
  `${\u7AEF}-label-${edge.id}`
20914
21717
  ))
@@ -21973,7 +22776,15 @@ function useInteractiveIntegration(diagram, options = {}) {
21973
22776
  f.id
21974
22777
  )) }),
21975
22778
  scrolls.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cdl-ip-group", children: scrolls.map((s) => /* @__PURE__ */ jsxRuntime.jsx(ScrollReadout, { id: s.id, name: s.label || s.id, progress: stateOverrides[s.id] }, s.id)) }),
21976
- readouts.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cdl-ip-group", children: readouts.map((r) => /* @__PURE__ */ jsxRuntime.jsx(ReadoutWidget, { readout: r, stateOverrides: mergedStateValues }, r.id)) })
22779
+ readouts.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cdl-ip-group", children: readouts.map((r) => /* @__PURE__ */ jsxRuntime.jsx(
22780
+ ReadoutWidget,
22781
+ {
22782
+ readout: r,
22783
+ stateOverrides: mergedStateValues,
22784
+ textMetrics: resolveTextMetrics(diagram.textMetrics)
22785
+ },
22786
+ r.id
22787
+ )) })
21977
22788
  ] }) })
21978
22789
  );
21979
22790
  }, [diagram, signals, stateOverrides, mergedStateValues]);
@@ -22394,7 +23205,8 @@ function StepperWidget({
22394
23205
  }
22395
23206
  function ReadoutWidget({
22396
23207
  readout,
22397
- stateOverrides
23208
+ stateOverrides,
23209
+ textMetrics = "proportional"
22398
23210
  }) {
22399
23211
  const rawValue = "source" in readout ? stateOverrides[readout.source] : void 0;
22400
23212
  const numericValue = typeof rawValue === "number" ? rawValue : typeof rawValue === "string" ? Number(rawValue) : Number.NaN;
@@ -22642,7 +23454,8 @@ function ReadoutWidget({
22642
23454
  max: readout.max,
22643
23455
  viewW: readout.viewW ?? 280,
22644
23456
  viewH: readout.viewH ?? 60,
22645
- color: readout.color ?? "#2563eb"
23457
+ color: readout.color ?? "#2563eb",
23458
+ textMetrics
22646
23459
  }
22647
23460
  );
22648
23461
  case "radar": {
@@ -23458,7 +24271,8 @@ function ReadoutWidget({
23458
24271
  { status: "idle", color: "#94a3b8" },
23459
24272
  { status: "error", color: "#ef4444" }
23460
24273
  ],
23461
- max: readout.max ?? 10
24274
+ max: readout.max ?? 10,
24275
+ textMetrics
23462
24276
  }
23463
24277
  );
23464
24278
  case "calendar-week":
@@ -24602,8 +25416,8 @@ function ProgressGroupReadout({
24602
25416
  }) })
24603
25417
  ] });
24604
25418
  }
24605
- function sequenceLabelAnchor(x, name, fontSize, viewW) {
24606
- const half = textWidth(name, fontSize) / 2;
25419
+ function sequenceLabelAnchor(x, name, fontSize, viewW, textMetrics = "proportional") {
25420
+ const half = textWidth(name, fontSize, 0, textMetrics) / 2;
24607
25421
  if (x - half < 0) return "start";
24608
25422
  if (x + half > viewW) return "end";
24609
25423
  return "middle";
@@ -24616,7 +25430,8 @@ function SequenceTimelineReadout({
24616
25430
  max,
24617
25431
  viewW,
24618
25432
  viewH,
24619
- color
25433
+ color,
25434
+ textMetrics = "proportional"
24620
25435
  }) {
24621
25436
  const events = [];
24622
25437
  const trimmed = value.trim();
@@ -24659,7 +25474,17 @@ function SequenceTimelineReadout({
24659
25474
  const x = xFor(e.t);
24660
25475
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { "data-cdl-event-marker": e.name, children: [
24661
25476
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: x, cy: trackY, r: 5, fill: color, stroke: "#fff", strokeWidth: 1.5, children: /* @__PURE__ */ jsxRuntime.jsx(\u5B57\u306E\u898B\u51FA\u3057, { k: "readout.sequenceTimeline.title", v: { name: e.name, t: e.t } }) }),
24662
- /* @__PURE__ */ jsxRuntime.jsx("text", { x, y: trackY - 12, textAnchor: sequenceLabelAnchor(x, e.name, 10, viewW), fontSize: 10, fill: "var(--v4-ink, #1a1f2a)", children: e.name }),
25477
+ /* @__PURE__ */ jsxRuntime.jsx(
25478
+ "text",
25479
+ {
25480
+ x,
25481
+ y: trackY - 12,
25482
+ textAnchor: sequenceLabelAnchor(x, e.name, 10, viewW, textMetrics),
25483
+ fontSize: 10,
25484
+ fill: "var(--v4-ink, #1a1f2a)",
25485
+ children: e.name
25486
+ }
25487
+ ),
24663
25488
  /* @__PURE__ */ jsxRuntime.jsx("text", { x, y: trackY + 18, textAnchor: "middle", fontSize: 9, fill: "var(--v4-mute, #64748b)", children: e.t })
24664
25489
  ] }, i);
24665
25490
  })
@@ -27736,7 +28561,8 @@ function StatusTimelineReadout({
27736
28561
  label,
27737
28562
  value,
27738
28563
  colorMap,
27739
- max
28564
+ max,
28565
+ textMetrics = "proportional"
27740
28566
  }) {
27741
28567
  const events = [];
27742
28568
  const trimmed = value.trim();
@@ -27761,6 +28587,7 @@ function StatusTimelineReadout({
27761
28587
  const cellW = shown.length > 0 ? (width - 20) / shown.length : 0;
27762
28588
  const height = stripHeight + 40;
27763
28589
  const \u533A\u9593\u306E\u5B57 = (status) => status === "active" || status === "idle" || status === "error" ? \u5F15\u304F(`readout.statusTimeline.${status}`) : status.toUpperCase();
28590
+ const \u6E2C\u308B = \u7BB1\u306E\u5B57\u3092\u6E2C\u308B(textMetrics);
27764
28591
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cdl-ip-item cdl-ip-readout-status-timeline", "data-cdl-readout": id, children: [
27765
28592
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cdl-ip-label", children: label }),
27766
28593
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -27774,7 +28601,7 @@ function StatusTimelineReadout({
27774
28601
  const x = 10 + i * cellW;
27775
28602
  const c = colorLookup.get(ev.status) ?? "#cbd5e1";
27776
28603
  const \u5B572 = \u533A\u9593\u306E\u5B57(ev.status);
27777
- const \u63CF\u304F\u5B57 = \u5E45\u3067\u5207\u308B(\u5B572, 10, cellW - 8);
28604
+ const \u63CF\u304F\u5B57 = \u5E45\u3067\u5207\u308B(\u5B572, 10, cellW - 8, \u6E2C\u308B);
27778
28605
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { "data-cdl-status-event": i, "data-cdl-status": ev.status, children: [
27779
28606
  /* @__PURE__ */ jsxRuntime.jsx("rect", { x, y: 10, width: cellW - 2, height: stripHeight, fill: c, rx: 2 }),
27780
28607
  /* @__PURE__ */ jsxRuntime.jsxs(