@cardenelabs/cdl 0.114.0 → 0.115.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cardenelabs/cdl",
3
- "version": "0.114.0",
3
+ "version": "0.115.0",
4
4
  "description": "CDL (Chainome Diagram Language). Mermaid-like declarative DSL that compiles to animated SVG diagrams. Built for blockchain / Solidity flows, generic enough for sequence / flow / state / ER / topology diagrams.",
5
5
  "license": "MIT",
6
6
  "author": "cardene777",
@@ -409,6 +409,53 @@ export function computeTreeLayout(
409
409
  return Math.min(Math.max(要る, nodeW), slotW * 0.92);
410
410
  };
411
411
 
412
+ /*
413
+ 置く前に、葉の並びと段を先に出す (#968)。
414
+
415
+ 端の葉の箱がどれだけ幅を取るかが判らないと、箱の辺を描画域の端へ合わせられない。
416
+ 箱の幅は名前と段から決まる (`箱の幅`) ので、位置より先に出せる。
417
+
418
+ 走査の順は `place` と同じ (同じ `childrenOf` を同じ順に辿り、既訪で打ち切る)。
419
+ */
420
+ const 葉の並び: string[] = [];
421
+ const 段の表 = new Map<string, number>();
422
+ const 幅の表 = new Map<string, number>();
423
+ {
424
+ const 見た = new Set<string>();
425
+ const 下見 = (n: TreeNodePayload, depth: number): void => {
426
+ 見た.add(n.id);
427
+ 段の表.set(n.id, depth);
428
+ 幅の表.set(n.id, 箱の幅(n, depth));
429
+ const kids = (childrenOf.get(n.id) ?? []).filter((k) => !見た.has(k.id));
430
+ if (kids.length === 0) {
431
+ 葉の並び.push(n.id);
432
+ return;
433
+ }
434
+ for (const k of kids) 下見(k, depth + 1);
435
+ };
436
+ for (const r of roots) if (!見た.has(r.id)) 下見(r, 0);
437
+ }
438
+
439
+ /*
440
+ 葉と葉の隙間を、**段と段の隙間に揃える** (#968)。
441
+
442
+ それまでは葉を `canvasW / 葉の数` で等分した区画の中央に置いていた。
443
+ 葉が少ない図では区画が箱よりずっと広くなり、兄弟どうしが遠くへ離れる
444
+ (実測 = 葉 2 枚の図で箱の縁の間が 196 空き、段の隙間 95 の 2 倍になった)。
445
+
446
+ 木は根から下へ辿る図なので、横の隙間だけが縦の 2 倍あると、離れた 2 本の列に見える。
447
+ 横の隙間を縦の隙間と同じにすれば、図の中の間隔が 1 つの調子で揃う。
448
+
449
+ **今より広げない** (`Math.min(slotW, ...)`)。 葉が多い図では区画の方が狭いので、
450
+ そちらが効いて位置は 1 ポイントも動かない。
451
+ */
452
+ const 葉の数 = Math.max(葉の並び.length, 1);
453
+ const 段の隙間 = depthGap - nodeH;
454
+ const 葉の間隔 = Math.min(slotW, nodeW + 段の隙間);
455
+ /** 葉の列全体を描画域の真ん中に置く。 葉が 1 枚なら間隔が要らない */
456
+ const 葉のx = (i: number): number =>
457
+ canvasW / 2 - ((葉の数 - 1) * 葉の間隔) / 2 + i * 葉の間隔;
458
+
412
459
  const posOf = new Map<string, { x: number; y: number }>();
413
460
  const nodes: LayoutNode[] = [];
414
461
  const placed = new Set<string>();
@@ -420,7 +467,7 @@ export function computeTreeLayout(
420
467
  const kids = (childrenOf.get(n.id) ?? []).filter((k) => !placed.has(k.id));
421
468
  let x: number;
422
469
  if (kids.length === 0) {
423
- x = leafCursor * slotW + slotW / 2;
470
+ x = 葉のx(leafCursor);
424
471
  leafCursor += 1;
425
472
  } else {
426
473
  const xs = kids.map((k) => place(k, depth + 1));
@@ -434,7 +481,7 @@ export function computeTreeLayout(
434
481
  ...(n.subtitle !== undefined ? { subtitle: n.subtitle } : {}),
435
482
  x,
436
483
  y,
437
- w: 箱の幅(n, depth),
484
+ w: 幅の表.get(n.id) ?? 箱の幅(n, depth),
438
485
  h: nodeH,
439
486
  depth,
440
487
  ...((n as { unresolved?: true }).unresolved ? { unresolved: true as const } : {}),