@cardenelabs/cdl 0.21.0 → 0.21.2

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,40 @@ CDL (Chainome Diagram Language) の主要変更履歴。
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.21.2] - 2026-08-30
9
+
10
+ ### Fixed
11
+
12
+ - **雲の字を絵の芯に合わせた** (#588)
13
+
14
+ 雲は 5 つの円で描き、箱の上へ 0.11 はみ出し下は 0.15 手前で終わる = **絵の芯が箱の芯より
15
+ 上にある**。 字を箱の芯に合わせていたので、絵に対して下へ寄って見えていた
16
+ (実測で上 71.5 / 下 27.9、差 43.6)。 直して 49 / 51.5 になる。
17
+
18
+ 円の中心と半径を `layout/spec.ts` の表に移し、描き手と字を置く側が同じ表から引く。
19
+ 絵の芯もその表から出すので、円を動かせば字も追随する。
20
+
21
+ ひし形 (`decision`) は箱と絵の芯が同じなので動かない。
22
+
23
+ ## [0.21.1] - 2026-08-29
24
+
25
+ ### Fixed
26
+
27
+ - **線の縦区間に張り付いた説明を離すようにした** (#594)
28
+
29
+ 説明が別の線の縦区間の真下に居る形で、隙間が 0 のまま残っていた。
30
+
31
+ 線の押し出しは発火している。 ただし安全判定 (`pathShiftIsSafe`) は「経路を壊さないか」
32
+ しか見ないので、**離れない向きへ動かして終わる**。 その時「線で逃がせた」 と数えるため、
33
+ cardene777/cdl#592 で入れた逃がし (説明の側を動かす) にも回らなかった。 繰り返しを 12 回まで
34
+ 回しても隙間は 0 のままだと実測した。
35
+
36
+ 押し出しは今までどおり出したまま、**離れなかった時は「逃がせた」 と数えない**。
37
+ 出さない形にすると、離れないなりに効いていた押し出しが消えて別の 3 図が壊れる。
38
+
39
+ 逃がす向きは **行き先を線ごとに確かめて** 選ぶ。 全体の最小距離だけで比べると、いま 0 の
40
+ 線が離れるぶん別の線が 0 になっても「悪くなっていない」 と読める。
41
+
8
42
  ## [0.21.0] - 2026-08-29
9
43
 
10
44
  ### Fixed
@@ -1061,7 +1095,9 @@ Initial OSS release.
1061
1095
  使わない = annotated tag を push しても GitHub Release は作られず、 Release を作っていない版で
1062
1096
  行き止まりになる。
1063
1097
 
1064
- [Unreleased]: https://github.com/cardene777/cdl/compare/v0.21.0...HEAD
1098
+ [Unreleased]: https://github.com/cardene777/cdl/compare/v0.21.2...HEAD
1099
+ [0.21.2]: https://github.com/cardene777/cdl/compare/v0.21.1...v0.21.2
1100
+ [0.21.1]: https://github.com/cardene777/cdl/compare/v0.21.0...v0.21.1
1065
1101
  [0.21.0]: https://github.com/cardene777/cdl/compare/v0.20.1...v0.21.0
1066
1102
  [0.20.1]: https://github.com/cardene777/cdl/compare/v0.20.0...v0.20.1
1067
1103
  [0.20.0]: https://github.com/cardene777/cdl/compare/v0.19.0...v0.20.0
package/dist/index.cjs CHANGED
@@ -12026,6 +12026,18 @@ function \u4E2D\u8EAB\u304B\u3089\u51FA\u3059\u9AD8\u3055(kind, \u6E80\u8F09h, \
12026
12026
  return Math.max(MIN_BOX_H, \u6E80\u8F09h - \u5F15\u304F);
12027
12027
  }
12028
12028
  var MIN_BOX_H = 44;
12029
+ var CLOUD_CIRCLES = [
12030
+ { cx: -0.8, cy: -0.05 + 0.08, r: 0.32 },
12031
+ { cx: -0.4, cy: -0.05 - 0.05, r: 0.4 },
12032
+ { cx: 0, cy: -0.05 - 0.1, r: 0.46 },
12033
+ { cx: 0.4, cy: -0.05 - 0.05, r: 0.4 },
12034
+ { cx: 0.8, cy: -0.05 + 0.08, r: 0.32 }
12035
+ ];
12036
+ var CLOUD_ART_CENTER_RISE = (() => {
12037
+ const \u4E0A = Math.min(...CLOUD_CIRCLES.map((c) => c.cy - c.r));
12038
+ const \u4E0B = Math.max(...CLOUD_CIRCLES.map((c) => c.cy + c.r));
12039
+ return -(\u4E0A + \u4E0B) / 2;
12040
+ })();
12029
12041
 
12030
12042
  // src/layout/footer-shape.ts
12031
12043
  var SHAPE_DRAW_UP_EXTENT = {
@@ -13092,8 +13104,12 @@ function resolveEdgeLabelOverlapsWithChainAndPropagate(edges, obstacles, minClea
13092
13104
  for (const { p } of ordered) {
13093
13105
  const axis = p.axis;
13094
13106
  if (!pathShiftIsSafe(e.id, axis, p.sign, amount)) continue;
13107
+ const \u52D5\u304B\u3057\u305F\u5F8C = measurePathLabelGapSegs(
13108
+ simulateShiftedSegments(e, axis === "x" ? p.sign * amount : 0, axis === "y" ? p.sign * amount : 0),
13109
+ label
13110
+ );
13095
13111
  out.push({ target: { kind: "edge-path", id: e.id }, axis, sign: p.sign, amount });
13096
- \u7DDA\u3092\u52D5\u304B\u305B\u305F = true;
13112
+ \u7DDA\u3092\u52D5\u304B\u305B\u305F = \u52D5\u304B\u3057\u305F\u5F8C > gap;
13097
13113
  break;
13098
13114
  }
13099
13115
  if (!\u7DDA\u3092\u52D5\u304B\u305B\u305F) {
@@ -13116,16 +13132,49 @@ function resolveEdgeLabelOverlapsWithChainAndPropagate(edges, obstacles, minClea
13116
13132
  if (\u8FD1\u3044\u70B9) {
13117
13133
  const dx = \u82AF.x - \u8FD1\u3044\u70B9.x;
13118
13134
  const dy = \u82AF.y - \u8FD1\u3044\u70B9.y;
13119
- const axis = Math.abs(dx) >= Math.abs(dy) ? "x" : "y";
13120
- const \u5411\u304D = axis === "x" ? dx : dy;
13121
- const sign = \u5411\u304D >= 0 ? 1 : -1;
13122
- out.push({
13123
- target: { kind: "label", id: label.id },
13124
- axis,
13125
- sign,
13126
- amount: pathLabelClearance - gap + NEAR_MISS_MARGIN,
13127
- chain: false
13135
+ const \u91CF = pathLabelClearance - gap + NEAR_MISS_MARGIN;
13136
+ const \u5019\u88DC = Math.abs(dx) >= Math.abs(dy) ? [
13137
+ { axis: "x", sign: dx >= 0 ? 1 : -1 },
13138
+ { axis: "y", sign: dy >= 0 ? 1 : -1 }
13139
+ ] : [
13140
+ { axis: "y", sign: dy >= 0 ? 1 : -1 },
13141
+ { axis: "x", sign: dx >= 0 ? 1 : -1 }
13142
+ ];
13143
+ const \u52D5\u304B\u3057\u305F\u7BB1 = (axis, sign) => ({
13144
+ ...label,
13145
+ x: label.x + (axis === "x" ? sign * \u91CF : 0),
13146
+ y: label.y + (axis === "y" ? sign * \u91CF : 0)
13128
13147
  });
13148
+ const \u7DDA\u3054\u3068\u306E\u8DDD\u96E2 = (\u7BB1) => {
13149
+ const \u51FA = /* @__PURE__ */ new Map();
13150
+ for (const \u4ED6 of edges) {
13151
+ if (\u4ED6.id === label.id) continue;
13152
+ const segs2 = segmentsExcludingOwnPath(shiftedSegments(\u4ED6.id, \u4ED6.d), ownSegsOf(label.id));
13153
+ if (segs2.length === 0) continue;
13154
+ \u51FA.set(\u4ED6.id, measurePathLabelGapSegs(segs2, \u7BB1));
13155
+ }
13156
+ return \u51FA;
13157
+ };
13158
+ const \u3044\u307E\u306E\u8DDD\u96E2 = \u7DDA\u3054\u3068\u306E\u8DDD\u96E2(label);
13159
+ const \u60AA\u304F\u3059\u308B = (\u7BB1) => {
13160
+ const \u5F8C = \u7DDA\u3054\u3068\u306E\u8DDD\u96E2(\u7BB1);
13161
+ for (const [id, \u524D\u306E\u5024] of \u3044\u307E\u306E\u8DDD\u96E2) {
13162
+ const \u5F8C\u306E\u5024 = \u5F8C.get(id) ?? Infinity;
13163
+ if (\u5F8C\u306E\u5024 < Math.min(\u524D\u306E\u5024, pathLabelClearance)) return true;
13164
+ }
13165
+ return false;
13166
+ };
13167
+ for (const \u5019 of \u5019\u88DC) {
13168
+ if (\u60AA\u304F\u3059\u308B(\u52D5\u304B\u3057\u305F\u7BB1(\u5019.axis, \u5019.sign))) continue;
13169
+ out.push({
13170
+ target: { kind: "label", id: label.id },
13171
+ axis: \u5019.axis,
13172
+ sign: \u5019.sign,
13173
+ amount: \u91CF,
13174
+ chain: false
13175
+ });
13176
+ break;
13177
+ }
13129
13178
  }
13130
13179
  }
13131
13180
  }
@@ -22467,21 +22516,12 @@ function GenericNode({
22467
22516
  if (shape === "cloud") {
22468
22517
  const cx = w / 2;
22469
22518
  const cy = h / 2;
22470
- const cloudCenterY = cy - h * 0.05;
22471
- const usableW = w * 0.85;
22472
- const halfW = usableW / 2;
22473
- const circles = [
22474
- { cx: cx - halfW * 0.8, cy: cloudCenterY + h * 0.08, r: h * 0.32 },
22475
- // 左端
22476
- { cx: cx - halfW * 0.4, cy: cloudCenterY - h * 0.05, r: h * 0.4 },
22477
- // 左
22478
- { cx, cy: cloudCenterY - h * 0.1, r: h * 0.46 },
22479
- // 中央 (最大)
22480
- { cx: cx + halfW * 0.4, cy: cloudCenterY - h * 0.05, r: h * 0.4 },
22481
- // 右
22482
- { cx: cx + halfW * 0.8, cy: cloudCenterY + h * 0.08, r: h * 0.32 }
22483
- // 右端
22484
- ];
22519
+ const halfW = w * 0.85 / 2;
22520
+ const circles = CLOUD_CIRCLES.map((c) => ({
22521
+ cx: cx + halfW * c.cx,
22522
+ cy: cy + h * c.cy,
22523
+ r: h * c.r
22524
+ }));
22485
22525
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
22486
22526
  circles.map((c, i) => /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: c.cx, cy: c.cy, r: c.r, fill: "var(--cdl-node-fill, #ffffff)" }, `fill-${i}`)),
22487
22527
  circles.map((c, i) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -22520,11 +22560,12 @@ function GenericNode({
22520
22560
  const textX = centered ? w / 2 : 20;
22521
22561
  const cylinderShift = genericTextShift(node.kind);
22522
22562
  const \u7E70\u308A\u4E0A\u3052 = node.eyebrow || centered ? 0 : \u76EE\u5370\u306A\u3057\u306E\u7E70\u308A\u4E0A\u3052(node.kind, hasRows);
22523
- const eyebrowY = centered ? h / 2 - 26 : 32 + cylinderShift;
22524
- const titleY = genericTitleBaselineY(node.kind, h, hasRows) - \u7E70\u308A\u4E0A\u3052;
22525
- const subtitleY = centered ? h / 2 + 28 : 96 + cylinderShift - \u7E70\u308A\u4E0A\u3052;
22563
+ const \u7D75\u306E\u82AF = centered && STYLES[node.kind]?.shape === "cloud" ? h * CLOUD_ART_CENTER_RISE : 0;
22564
+ const eyebrowY = centered ? h / 2 - 26 - \u7D75\u306E\u82AF : 32 + cylinderShift;
22565
+ const titleY = genericTitleBaselineY(node.kind, h, hasRows) - \u7E70\u308A\u4E0A\u3052 - \u7D75\u306E\u82AF;
22566
+ const subtitleY = centered ? h / 2 + 28 - \u7D75\u306E\u82AF : 96 + cylinderShift - \u7E70\u308A\u4E0A\u3052;
22526
22567
  const iconX = centered ? w / 2 + 40 : w - 48;
22527
- const iconY = centered ? h / 2 - 44 : 18 + cylinderShift;
22568
+ const iconY = centered ? h / 2 - 44 - \u7D75\u306E\u82AF : 18 + cylinderShift;
22528
22569
  const dominantBaseline = centered ? "middle" : void 0;
22529
22570
  return /* @__PURE__ */ jsxRuntime.jsxs("g", { transform: `translate(${x} ${y})`, "data-cdl-role": "node-body", children: [
22530
22571
  shapeEl,