@cardenelabs/cdl 0.19.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,48 @@ CDL (Chainome Diagram Language) の主要変更履歴。
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.20.0] - 2026-08-29
9
+
10
+ ### Changed
11
+
12
+ - **箱の高さを書いた段の数から決めるようにした** (#589)
13
+
14
+ 高さが中身に依らず種別ごとの固定値で、小見出し + 名前 + 説明の 3 段が入る前提だった。
15
+ 名前 1 語だけの箱も 3 段ぶんの高さになり、実測で `function` は 151 に対し字が 29 しか
16
+ 無かった。
17
+
18
+ 空きは上下の両方に出ていた。 小見出しを書かないと、そのために空けた帯が上に残る。
19
+ 説明を書かないと、説明の段が下に残る。
20
+
21
+ 2 つを組み合わせて直した。 小見出しが無い時は字の塊を上へ繰り上げ、高さは最後の段の
22
+ 下端から出す。 繰り上げ量は `layout/spec.ts` が持ち、描き手と layout が同じ値を引く。
23
+
24
+ **3 段を書いた箱の高さは変わらない**。 書かなかった段のぶんだけ引く形なので、既存の図で
25
+ 3 段そろっているものは 1 も動かない。
26
+
27
+ 実測 (名前だけの箱)。 `actor` 165 → 73、`function` 151 → 67、`event` 156 → 72、
28
+ `card` 150 → 68、`storage` 115 → 79、`service` 等 21 種別 116 → 54。
29
+
30
+ 4 つの書き方 (名前だけ / 小見出し + 名前 / 名前 + 説明 / 3 段) × 9 種別の 36 通りで、
31
+ 上と下の余白の差は最大 5 に収まる。
32
+
33
+ 行を持つ箱と、値を持つ箱と、字を中央へ寄せる 2 種別 (`cloud` / `decision`) は対象外。
34
+ 行は上端から数えて置かれ、値は下端から置かれるので、繰り上げると重なる。
35
+
36
+ ### Fixed
37
+
38
+ - **形の違う線が混ざる扇でも、同じ形どうしは説明を離すようにした** (#589)
39
+
40
+ 扇状に広がる線の説明を横へ逃がす処理が、線の形 (迂回するかどうか) が混ざる群では
41
+ **丸ごと止まって** いた。 その結果、同じ形どうしの重なりまで残っていた。
42
+
43
+ 形ごとに分けてから逃がす。 実測 = 4 段の網の図で、迂回する 2 本の説明が 25 しか離れず
44
+ `clearance` が error を出していた (要る間隔は 36)。
45
+
46
+ 逃がす時の間隔も、検査が要求する値 (`CLEARANCE_LABEL_LABEL` = 36) そのものにした。
47
+ 20 を独自に持っていた間、逃がした結果が要求に届かず 32 で止まっていた = 掃く側と見る側で
48
+ 別の値を持つと、掃いても落ちる。
49
+
8
50
  ## [0.19.0] - 2026-08-29
9
51
 
10
52
  ### Changed
@@ -984,7 +1026,8 @@ Initial OSS release.
984
1026
  使わない = annotated tag を push しても GitHub Release は作られず、 Release を作っていない版で
985
1027
  行き止まりになる。
986
1028
 
987
- [Unreleased]: https://github.com/cardene777/cdl/compare/v0.19.0...HEAD
1029
+ [Unreleased]: https://github.com/cardene777/cdl/compare/v0.20.0...HEAD
1030
+ [0.20.0]: https://github.com/cardene777/cdl/compare/v0.19.0...v0.20.0
988
1031
  [0.19.0]: https://github.com/cardene777/cdl/compare/v0.18.1...v0.19.0
989
1032
  [0.18.1]: https://github.com/cardene777/cdl/compare/v0.18.0...v0.18.1
990
1033
  [0.18.0]: https://github.com/cardene777/cdl/compare/v0.17.1...v0.18.0
package/dist/index.cjs CHANGED
@@ -11978,6 +11978,54 @@ function buildDiagramAltText(topic, phase) {
11978
11978
  else if (body) parts.push(body);
11979
11979
  return parts.join(" ");
11980
11980
  }
11981
+ var \u6BB5\u306E\u4F4D\u7F6E = {
11982
+ actor: { \u76EE\u5370: { y: 38, size: 18 }, \u540D\u524D: { y: 86, size: 32 }, \u8AAC\u660E: { y: 140, size: 20 } },
11983
+ function: { \u76EE\u5370: { y: 38, size: 18 }, \u540D\u524D: { y: 86, size: 24 }, \u8AAC\u660E: { y: 126, size: 20 } },
11984
+ event: { \u76EE\u5370: { y: 38, size: 18 }, \u540D\u524D: { y: 88, size: 26 }, \u8AAC\u660E: { y: 128, size: 21 } },
11985
+ card: { \u76EE\u5370: { y: 38, size: 18 }, \u540D\u524D: { y: 86, size: 24 }, \u8AAC\u660E: { y: 124, size: 21 } },
11986
+ storage: {
11987
+ \u76EE\u5370: { y: 38, size: 18 },
11988
+ \u540D\u524D: { y: STORAGE_TITLE_BASELINE, size: STORAGE_TITLE_FONT },
11989
+ \u8AAC\u660E: { y: 118, size: 20 }
11990
+ }
11991
+ };
11992
+ var \u6C4E\u7528\u306E\u6BB5 = {
11993
+ \u76EE\u5370: { y: 32, size: 17 },
11994
+ \u540D\u524D: { y: GENERIC_TITLE_TOP, size: GENERIC_TITLE_FONT },
11995
+ \u8AAC\u660E: { y: 96, size: 17 }
11996
+ };
11997
+ function \u6BB5\u3092\u7A4D\u3080\u7BB1\u304B(kind, hasRows) {
11998
+ if (hasRows) return false;
11999
+ if (kind === void 0) return false;
12000
+ if (genericTextCentered(kind, false)) return false;
12001
+ return kind in \u6BB5\u306E\u4F4D\u7F6E || rendersRows(kind);
12002
+ }
12003
+ function \u6BB5\u3092\u5F15\u304F(kind) {
12004
+ const \u56FA\u6709 = \u6BB5\u306E\u4F4D\u7F6E[kind];
12005
+ if (\u56FA\u6709) return \u56FA\u6709;
12006
+ if (rendersRows(kind)) return \u6C4E\u7528\u306E\u6BB5;
12007
+ return null;
12008
+ }
12009
+ function \u76EE\u5370\u306A\u3057\u306E\u7E70\u308A\u4E0A\u3052(kind, hasRows = false) {
12010
+ if (!\u6BB5\u3092\u7A4D\u3080\u7BB1\u304B(kind, hasRows)) return 0;
12011
+ const \u6BB5 = \u6BB5\u3092\u5F15\u304F(kind);
12012
+ if (!\u6BB5) return 0;
12013
+ const \u4E0A\u3052\u308B = \u6BB5.\u540D\u524D.y - \u6BB5.\u76EE\u5370.y + (\u6BB5.\u76EE\u5370.size - \u6BB5.\u540D\u524D.size) * GLYPH_CAP_RATIO;
12014
+ return Math.max(0, Math.round(\u4E0A\u3052\u308B));
12015
+ }
12016
+ function \u8AAC\u660E\u306A\u3057\u3067\u7E2E\u3080\u91CF(kind, hasRows = false) {
12017
+ if (!\u6BB5\u3092\u7A4D\u3080\u7BB1\u304B(kind, hasRows)) return 0;
12018
+ const \u6BB5 = \u6BB5\u3092\u5F15\u304F(kind);
12019
+ if (!\u6BB5) return 0;
12020
+ return Math.max(0, \u6BB5.\u8AAC\u660E.y - \u6BB5.\u540D\u524D.y);
12021
+ }
12022
+ function \u4E2D\u8EAB\u304B\u3089\u51FA\u3059\u9AD8\u3055(kind, \u6E80\u8F09h, \u4E2D\u8EAB) {
12023
+ if (!\u6BB5\u3092\u7A4D\u3080\u7BB1\u304B(kind, \u4E2D\u8EAB.hasRows)) return \u6E80\u8F09h;
12024
+ if (\u4E2D\u8EAB.hasValue) return \u6E80\u8F09h;
12025
+ const \u5F15\u304F = (\u4E2D\u8EAB.hasEyebrow ? 0 : \u76EE\u5370\u306A\u3057\u306E\u7E70\u308A\u4E0A\u3052(kind)) + (\u4E2D\u8EAB.hasSubtitle ? 0 : \u8AAC\u660E\u306A\u3057\u3067\u7E2E\u3080\u91CF(kind));
12026
+ return Math.max(MIN_BOX_H, \u6E80\u8F09h - \u5F15\u304F);
12027
+ }
12028
+ var MIN_BOX_H = 44;
11981
12029
 
11982
12030
  // src/layout/footer-shape.ts
11983
12031
  var SHAPE_DRAW_UP_EXTENT = {
@@ -13605,7 +13653,7 @@ function layoutEdges(diag, nodes, lanes = []) {
13605
13653
  for (const p of list) parallelGroupedIds.add(p.e.id);
13606
13654
  }
13607
13655
  const distributedInParallel = /* @__PURE__ */ new Set();
13608
- const FAN_LABEL_GAP = 20;
13656
+ const FAN_LABEL_GAP = CLEARANCE_LABEL_LABEL;
13609
13657
  const computeEffectiveSides = (p) => {
13610
13658
  if (p.e.routing === "back-detour") {
13611
13659
  return { effFromSide: "top", effToSide: "top" };
@@ -13995,7 +14043,17 @@ function layoutEdges(diag, nodes, lanes = []) {
13995
14043
  const applyFanDispersion = (list, tracked) => {
13996
14044
  if (list.length < 2) return;
13997
14045
  const obstaclePatterns = new Set(list.map((r) => detectsBlockingObstacle(r.p)));
13998
- if (obstaclePatterns.size > 1) return;
14046
+ if (obstaclePatterns.size > 1) {
14047
+ const \u5F62\u3054\u3068 = /* @__PURE__ */ new Map();
14048
+ for (const r of list) {
14049
+ const \u5F62 = detectsBlockingObstacle(r.p);
14050
+ \u5F62\u3054\u3068.set(\u5F62, [...\u5F62\u3054\u3068.get(\u5F62) ?? [], r]);
14051
+ }
14052
+ for (const \u540C\u3058\u5F62 of \u5F62\u3054\u3068.values()) {
14053
+ if (\u540C\u3058\u5F62.length < list.length) applyFanDispersion(\u540C\u3058\u5F62, tracked);
14054
+ }
14055
+ return;
14056
+ }
13999
14057
  if (list.some((r) => r.e.overlay)) return;
14000
14058
  const items = list.map((r) => ({
14001
14059
  r,
@@ -15088,7 +15146,8 @@ function autoStorageHeight(n, defaultH) {
15088
15146
  if (n.h != null) return n.h;
15089
15147
  const \u5370\u3042\u308A = n.rowMarks !== void 0;
15090
15148
  const \u547C\u3073\u540D\u306E\u5206 = \u5370\u3042\u308A && n.subtitle ? SUBTITLE_ROW_SHIFT : 0;
15091
- if (!n.rows || n.rows.length === 0) return 115 + \u547C\u3073\u540D\u306E\u5206;
15149
+ const \u7E70\u308A\u4E0A\u3052 = n.eyebrow ? 0 : \u76EE\u5370\u306A\u3057\u306E\u7E70\u308A\u4E0A\u3052("storage");
15150
+ if (!n.rows || n.rows.length === 0) return 115 + \u547C\u3073\u540D\u306E\u5206 - \u7E70\u308A\u4E0A\u3052;
15092
15151
  const \u5FC5\u8981 = requiredRowsHeight("storage", n.rows.length) ?? defaultH;
15093
15152
  if (\u5370\u3042\u308A) return \u5FC5\u8981 + \u547C\u3073\u540D\u306E\u5206;
15094
15153
  return Math.max(defaultH, \u5FC5\u8981);
@@ -15099,6 +15158,16 @@ function autoRowsWidth(n, defaultW) {
15099
15158
  const required = requiredRowsWidth(n.rows, n.kind);
15100
15159
  return Math.max(defaultW, required);
15101
15160
  }
15161
+ function \u7BB1\u306E\u9AD8\u3055(n, \u65E2\u5B9Ah) {
15162
+ if (n.h != null) return n.h;
15163
+ if (n.kind === "storage") return autoStorageHeight(n, \u65E2\u5B9Ah);
15164
+ return \u4E2D\u8EAB\u304B\u3089\u51FA\u3059\u9AD8\u3055(n.kind, \u65E2\u5B9Ah, {
15165
+ hasEyebrow: Boolean(n.eyebrow),
15166
+ hasSubtitle: Boolean(n.subtitle),
15167
+ hasValue: Boolean(n.value),
15168
+ hasRows: (n.rows?.length ?? 0) > 0
15169
+ });
15170
+ }
15102
15171
  function requiredStackGapForEdgeLabels(diag, allStacks) {
15103
15172
  const byId = new Map(diag.nodes.map((n) => [n.id, n]));
15104
15173
  const rankOf = new Map(allStacks.map((stack, i) => [stack, i]));
@@ -15128,7 +15197,7 @@ function layoutNodes(diag, lanes) {
15128
15197
  const rowH = /* @__PURE__ */ new Map();
15129
15198
  for (const stack of allStacks) {
15130
15199
  const nodesAtStack = diag.nodes.filter((n) => n.stack === stack);
15131
- const h = Math.max(...nodesAtStack.map((n) => autoStorageHeight(n, NODE_SIZE[n.kind].h)));
15200
+ const h = Math.max(...nodesAtStack.map((n) => \u7BB1\u306E\u9AD8\u3055(n, NODE_SIZE[n.kind].h)));
15132
15201
  rowH.set(stack, h);
15133
15202
  }
15134
15203
  const rowCy = /* @__PURE__ */ new Map();
@@ -15181,8 +15250,8 @@ function layoutNodes(diag, lanes) {
15181
15250
  const cx = lane.x + lane.width / 2;
15182
15251
  const \u6BB5\u306E\u82AF = rowCy.get(n.stack);
15183
15252
  const \u6BB5\u306E\u9AD8\u3055 = rowH.get(n.stack);
15184
- const \u81EA\u524D\u306E\u9AD8\u3055 = n.rowMarks !== void 0;
15185
- const h = n.h ?? (\u81EA\u524D\u306E\u9AD8\u3055 ? autoStorageHeight(n, size.h) : \u6BB5\u306E\u9AD8\u3055);
15253
+ const \u81EA\u524D\u306E\u9AD8\u3055 = n.rowMarks !== void 0 || \u6BB5\u3092\u7A4D\u3080\u7BB1\u304B(n.kind, (n.rows?.length ?? 0) > 0);
15254
+ const h = n.h ?? (\u81EA\u524D\u306E\u9AD8\u3055 ? \u7BB1\u306E\u9AD8\u3055(n, size.h) : \u6BB5\u306E\u9AD8\u3055);
15186
15255
  const cy = \u6BB5\u306E\u82AF;
15187
15256
  const w = autoRowsWidth(n, size.w);
15188
15257
  out.push({
@@ -16623,10 +16692,10 @@ function \u66F8\u8A18\u7D20\u306B\u5206\u3051\u308B(text) {
16623
16692
  if (typeof \u533A\u5207\u308A !== "function") return [...text];
16624
16693
  return [...new \u533A\u5207\u308A(void 0, { granularity: "grapheme" }).segment(text)].map((g) => g.segment);
16625
16694
  }
16626
- function \u7BB1\u306B\u7A4D\u3080(\u884C, \u7BB1\u306E\u5E45, \u7BB1\u306E\u9AD8\u3055) {
16695
+ function \u7BB1\u306B\u7A4D\u3080(\u884C, \u7BB1\u306E\u5E45, \u7BB1\u306E\u9AD8\u30552) {
16627
16696
  const \u5019\u88DC = \u884C.filter((r, i) => i === 0 || r.text.trim() !== "");
16628
16697
  if (\u5019\u88DC.length === 0) return [];
16629
- const \u4F7F\u3048\u308B\u9AD8\u3055 = \u7BB1\u306E\u9AD8\u3055 - \u4E0A\u4E0B\u306E\u4F59\u767D * 2;
16698
+ const \u4F7F\u3048\u308B\u9AD8\u3055 = \u7BB1\u306E\u9AD8\u30552 - \u4E0A\u4E0B\u306E\u4F59\u767D * 2;
16630
16699
  const \u9AD8\u3055 = (rs) => rs.reduce((a, r) => a + r.fontSize * \u884C\u9001\u308A\u306E\u6BD4, 0);
16631
16700
  const \u6B8B\u3059 = [...\u5019\u88DC];
16632
16701
  while (\u6B8B\u3059.length > 1 && \u9AD8\u3055(\u6B8B\u3059) > \u4F7F\u3048\u308B\u9AD8\u3055) \u6B8B\u3059.pop();
@@ -16845,7 +16914,7 @@ function \u30D9\u30B8\u30A8\u306E\u7D2F\u7A4D\u5272\u5408(\u70B9, \u5236\u5FA1\u
16845
16914
  function \u7BB1\u306E\u6587\u5B57({
16846
16915
  \u884C,
16847
16916
  x,
16848
- \u7BB1\u306E\u9AD8\u3055,
16917
+ \u7BB1\u306E\u9AD8\u3055: \u7BB1\u306E\u9AD8\u30552,
16849
16918
  fill,
16850
16919
  \u540D\u524D\u306E\u592A\u3055
16851
16920
  }) {
@@ -16854,7 +16923,7 @@ function \u7BB1\u306E\u6587\u5B57({
16854
16923
  {
16855
16924
  "data-cdl-role": r.\u5F79\u5272 === "subtitle" ? "tree-node-subtitle" : void 0,
16856
16925
  x,
16857
- y: \u7BB1\u306E\u9AD8\u3055 / 2 + r.dy,
16926
+ y: \u7BB1\u306E\u9AD8\u30552 / 2 + r.dy,
16858
16927
  fontSize: r.fontSize,
16859
16928
  fontWeight: r.\u5F79\u5272 === "title" ? \u540D\u524D\u306E\u592A\u3055 : 500,
16860
16929
  textAnchor: "middle",
@@ -21533,7 +21602,8 @@ function ActorNode({ node, active, value }) {
21533
21602
  const accent = nodeAccent(node, "var(--cdl-tone-accent, #2d6a8f)");
21534
21603
  const x = node.cx - node.w / 2;
21535
21604
  const y = node.cy - node.h / 2;
21536
- const \u540D\u524D = titlePlacement(node, { x: 26, y: 86, size: 32 }, { hasEyebrow: Boolean(node.eyebrow) });
21605
+ const \u7E70\u308A\u4E0A\u3052 = node.eyebrow ? 0 : \u76EE\u5370\u306A\u3057\u306E\u7E70\u308A\u4E0A\u3052("actor");
21606
+ const \u540D\u524D = titlePlacement(node, { x: 26, y: 86 - \u7E70\u308A\u4E0A\u3052, size: 32 }, { hasEyebrow: Boolean(node.eyebrow) });
21537
21607
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { transform: `translate(${x} ${y})`, children: [
21538
21608
  /* @__PURE__ */ jsxRuntime.jsx(
21539
21609
  "rect",
@@ -21568,13 +21638,13 @@ function ActorNode({ node, active, value }) {
21568
21638
  {
21569
21639
  "data-cdl-role": "node-row-divider",
21570
21640
  x1: 26,
21571
- y1: 110,
21641
+ y1: 110 - \u7E70\u308A\u4E0A\u3052,
21572
21642
  x2: node.w - 26,
21573
- y2: 110,
21643
+ y2: 110 - \u7E70\u308A\u4E0A\u3052,
21574
21644
  stroke: "var(--cdl-row-divider, #7e848e)"
21575
21645
  }
21576
21646
  ),
21577
- node.subtitle && /* @__PURE__ */ jsxRuntime.jsx("text", { x: 26, y: 140, fontSize: 20, fill: "var(--cdl-text-dim, #5a6270)", children: node.subtitle }),
21647
+ node.subtitle && /* @__PURE__ */ jsxRuntime.jsx("text", { x: 26, y: 140 - \u7E70\u308A\u4E0A\u3052, fontSize: 20, fill: "var(--cdl-text-dim, #5a6270)", children: node.subtitle }),
21578
21648
  value && /* @__PURE__ */ jsxRuntime.jsx(
21579
21649
  "text",
21580
21650
  {
@@ -21599,7 +21669,8 @@ function CardNode({ node, active }) {
21599
21669
  }
21600
21670
  const compact = isCompactBox(node.h);
21601
21671
  const \u5C0F\u578B\u306B\u547C\u3073\u540D = compact && Boolean(node.subtitle);
21602
- const titleY = compact ? \u5C0F\u578B\u306B\u547C\u3073\u540D ? node.h / 2 - 2 : node.h / 2 + 8 : 86;
21672
+ const \u7E70\u308A\u4E0A\u3052 = node.eyebrow ? 0 : \u76EE\u5370\u306A\u3057\u306E\u7E70\u308A\u4E0A\u3052("card");
21673
+ const titleY = compact ? \u5C0F\u578B\u306B\u547C\u3073\u540D ? node.h / 2 - 2 : node.h / 2 + 8 : 86 - \u7E70\u308A\u4E0A\u3052;
21603
21674
  const titleX = compact ? node.w / 2 : 26;
21604
21675
  const paddingX = compact ? 16 : 52;
21605
21676
  const availableW = node.w - paddingX;
@@ -21636,7 +21707,7 @@ function CardNode({ node, active }) {
21636
21707
  children: node.title
21637
21708
  }
21638
21709
  ),
21639
- !compact && node.subtitle && /* @__PURE__ */ jsxRuntime.jsx("text", { x: 26, y: 124, fontSize: subtitleSize, fill: "var(--cdl-text-dim, #5a6270)", children: node.subtitle }),
21710
+ !compact && node.subtitle && /* @__PURE__ */ jsxRuntime.jsx("text", { x: 26, y: 124 - \u7E70\u308A\u4E0A\u3052, fontSize: subtitleSize, fill: "var(--cdl-text-dim, #5a6270)", children: node.subtitle }),
21640
21711
  \u5C0F\u578B\u306B\u547C\u3073\u540D && /* @__PURE__ */ jsxRuntime.jsx(
21641
21712
  "text",
21642
21713
  {
@@ -21900,7 +21971,8 @@ function EventNode({
21900
21971
  const accent = nodeAccent(node, "var(--cdl-tone-success, #4ea36a)");
21901
21972
  const x = node.cx - node.w / 2;
21902
21973
  const y = node.cy - node.h / 2;
21903
- const \u540D\u524D = titlePlacement(node, { x: 26, y: 88, size: 26 }, { hasEyebrow: Boolean(node.eyebrow) });
21974
+ const \u7E70\u308A\u4E0A\u3052 = node.eyebrow ? 0 : \u76EE\u5370\u306A\u3057\u306E\u7E70\u308A\u4E0A\u3052("event");
21975
+ const \u540D\u524D = titlePlacement(node, { x: 26, y: 88 - \u7E70\u308A\u4E0A\u3052, size: 26 }, { hasEyebrow: Boolean(node.eyebrow) });
21904
21976
  const scale = active ? 0.78 + 0.22 * progress : 0.92;
21905
21977
  const opacity = active ? 0.5 + 0.5 * progress : 0.65;
21906
21978
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -21942,7 +22014,7 @@ function EventNode({
21942
22014
  "text",
21943
22015
  {
21944
22016
  x: 26,
21945
- y: 128,
22017
+ y: 128 - \u7E70\u308A\u4E0A\u3052,
21946
22018
  fontSize: 21,
21947
22019
  fill: "var(--cdl-text-dim, #5a6270)",
21948
22020
  style: { fontFamily: "'JetBrains Mono', monospace" },
@@ -21958,7 +22030,8 @@ function FunctionNode({ node, active }) {
21958
22030
  const stroke = nodeAccent(node, active ? "var(--cdl-tone-accent, #2d6a8f)" : "var(--cdl-tone-teal, #2f8770)");
21959
22031
  const x = node.cx - node.w / 2;
21960
22032
  const y = node.cy - node.h / 2;
21961
- const \u540D\u524D = titlePlacement(node, { x: 26, y: 86, size: 24 }, { hasEyebrow: Boolean(node.eyebrow) });
22033
+ const \u7E70\u308A\u4E0A\u3052 = node.eyebrow ? 0 : \u76EE\u5370\u306A\u3057\u306E\u7E70\u308A\u4E0A\u3052("function");
22034
+ const \u540D\u524D = titlePlacement(node, { x: 26, y: 86 - \u7E70\u308A\u4E0A\u3052, size: 24 }, { hasEyebrow: Boolean(node.eyebrow) });
21962
22035
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { transform: `translate(${x} ${y})`, children: [
21963
22036
  /* @__PURE__ */ jsxRuntime.jsx(
21964
22037
  "rect",
@@ -21990,7 +22063,7 @@ function FunctionNode({ node, active }) {
21990
22063
  children: node.title
21991
22064
  }
21992
22065
  ),
21993
- node.subtitle && /* @__PURE__ */ jsxRuntime.jsx("text", { x: 26, y: 126, fontSize: 20, fill: "var(--cdl-text-dim, #5a6270)", children: node.subtitle })
22066
+ node.subtitle && /* @__PURE__ */ jsxRuntime.jsx("text", { x: 26, y: 126 - \u7E70\u308A\u4E0A\u3052, fontSize: 20, fill: "var(--cdl-text-dim, #5a6270)", children: node.subtitle })
21994
22067
  ] });
21995
22068
  }
21996
22069
  var ROW_GLYPH_HALF = 7;
@@ -22025,7 +22098,8 @@ function StorageNode({
22025
22098
  const accent = nodeAccent(node, "var(--cdl-tone-accent, #2d6a8f)");
22026
22099
  const x = node.cx - node.w / 2;
22027
22100
  const y = node.cy - node.h / 2;
22028
- const \u540D\u524D = titlePlacement(node, { x: 26, y: STORAGE_TITLE_BASELINE, size: STORAGE_TITLE_FONT }, { hasEyebrow: Boolean(node.eyebrow) });
22101
+ const \u7E70\u308A\u4E0A\u3052 = node.eyebrow || rows.length > 0 ? 0 : \u76EE\u5370\u306A\u3057\u306E\u7E70\u308A\u4E0A\u3052("storage");
22102
+ const \u540D\u524D = titlePlacement(node, { x: 26, y: STORAGE_TITLE_BASELINE - \u7E70\u308A\u4E0A\u3052, size: STORAGE_TITLE_FONT }, { hasEyebrow: Boolean(node.eyebrow) });
22029
22103
  const splits = rows.map((r) => splitRow(r));
22030
22104
  const leftMaxWidth = splits.reduce((m, s) => Math.max(m, displayWidth(s.left)), 0);
22031
22105
  const rightColX = ROW_PAD_X_PX + leftMaxWidth * STORAGE_CHAR_ADVANCE_PX + STORAGE_COL_GAP_PX;
@@ -22062,7 +22136,7 @@ function StorageNode({
22062
22136
  {
22063
22137
  "data-cdl-role": "node-subtitle",
22064
22138
  x: ROW_PAD_X_PX,
22065
- y: SUBTITLE_BASELINE,
22139
+ y: SUBTITLE_BASELINE - \u7E70\u308A\u4E0A\u3052,
22066
22140
  fontSize: SUBTITLE_FONT,
22067
22141
  fill: "var(--cdl-text-dim, #5a6270)",
22068
22142
  children: node.subtitle
@@ -22380,9 +22454,10 @@ function GenericNode({
22380
22454
  const textAnchor = centered ? "middle" : "start";
22381
22455
  const textX = centered ? w / 2 : 20;
22382
22456
  const cylinderShift = genericTextShift(node.kind);
22457
+ const \u7E70\u308A\u4E0A\u3052 = node.eyebrow || centered ? 0 : \u76EE\u5370\u306A\u3057\u306E\u7E70\u308A\u4E0A\u3052(node.kind, hasRows);
22383
22458
  const eyebrowY = centered ? h / 2 - 26 : 32 + cylinderShift;
22384
- const titleY = genericTitleBaselineY(node.kind, h, hasRows);
22385
- const subtitleY = centered ? h / 2 + 28 : 96 + cylinderShift;
22459
+ const titleY = genericTitleBaselineY(node.kind, h, hasRows) - \u7E70\u308A\u4E0A\u3052;
22460
+ const subtitleY = centered ? h / 2 + 28 : 96 + cylinderShift - \u7E70\u308A\u4E0A\u3052;
22386
22461
  const iconX = centered ? w / 2 + 40 : w - 48;
22387
22462
  const iconY = centered ? h / 2 - 44 : 18 + cylinderShift;
22388
22463
  const dominantBaseline = centered ? "middle" : void 0;