@cardenelabs/cdl 0.18.0 → 0.19.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.18.0",
3
+ "version": "0.19.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",
@@ -27,10 +27,12 @@ function autoStorageHeight(
27
27
  if (n.kind !== "storage") return n.h ?? defaultH;
28
28
  if (n.h != null) return n.h;
29
29
  // rows なし storage は title + divider のみで render されるため、 default h=240 では空白過大。
30
- // title block (130px) + bottom padding (20px) = 150px に縮める。
30
+ //
31
+ // 上下の余白を揃える (#586)。 実測で 150 のとき上 21 / 下 55.9 と下だけ 35 空いていた。
32
+ // 字の高さ 73.2 に上の余白 21 を上下ぶん足して 115 にする。
31
33
  const 印あり = n.rowMarks !== undefined;
32
34
  const 呼び名の分 = 印あり && n.subtitle ? SUBTITLE_ROW_SHIFT : 0;
33
- if (!n.rows || n.rows.length === 0) return 150 + 呼び名の分;
35
+ if (!n.rows || n.rows.length === 0) return 115 + 呼び名の分;
34
36
  const 必要 = requiredRowsHeight("storage", n.rows.length) ?? defaultH;
35
37
  // 行頭の印を持つ箱は **中身の足し算だけ** で高さを決める (#578)。 下限を残すと、行が
36
38
  // 1 つしか無い箱が 4 行の箱と同じ高さになり、下が空いたまま並ぶ。
@@ -17,35 +17,35 @@ export const TOKENS = {
17
17
 
18
18
  // node sizes (kind ごと、 unified row h は engine が max() で算出)
19
19
  node: {
20
- actor: { w: 340, h: 200 },
21
- function: { w: 380, h: 170 },
20
+ actor: { w: 340, h: 165 },
21
+ function: { w: 380, h: 151 },
22
22
  storage: { w: 400, h: 240 },
23
- event: { w: 360, h: 200 },
23
+ event: { w: 360, h: 156 },
24
24
  card: { w: 320, h: 150 },
25
25
  // 人系
26
- person: { w: 280, h: 180 },
27
- "user-group": { w: 320, h: 180 },
28
- admin: { w: 280, h: 180 },
29
- developer: { w: 280, h: 180 },
30
- "external-user": { w: 300, h: 180 },
26
+ person: { w: 280, h: 116 },
27
+ "user-group": { w: 320, h: 116 },
28
+ admin: { w: 280, h: 116 },
29
+ developer: { w: 280, h: 116 },
30
+ "external-user": { w: 300, h: 116 },
31
31
  // インフラ
32
- database: { w: 320, h: 200 },
33
- cache: { w: 280, h: 160 },
34
- queue: { w: 340, h: 140 },
35
- "message-bus": { w: 380, h: 140 },
32
+ database: { w: 320, h: 172 },
33
+ cache: { w: 280, h: 116 },
34
+ queue: { w: 340, h: 116 },
35
+ "message-bus": { w: 380, h: 116 },
36
36
  cloud: { w: 320, h: 180 },
37
- cdn: { w: 320, h: 160 },
37
+ cdn: { w: 320, h: 116 },
38
38
  // アプリ系
39
- service: { w: 320, h: 180 },
40
- api: { w: 320, h: 160 },
41
- frontend: { w: 320, h: 180 },
42
- backend: { w: 320, h: 180 },
43
- webhook: { w: 320, h: 160 },
44
- microservice: { w: 320, h: 180 },
39
+ service: { w: 320, h: 116 },
40
+ api: { w: 320, h: 116 },
41
+ frontend: { w: 320, h: 116 },
42
+ backend: { w: 320, h: 116 },
43
+ webhook: { w: 320, h: 116 },
44
+ microservice: { w: 320, h: 116 },
45
45
  // データ / 判定
46
- signer: { w: 300, h: 180 },
47
- oracle: { w: 320, h: 180 },
48
- "merkle-tree": { w: 340, h: 220 },
46
+ signer: { w: 300, h: 116 },
47
+ oracle: { w: 320, h: 116 },
48
+ "merkle-tree": { w: 340, h: 116 },
49
49
  decision: { w: 300, h: 180 },
50
50
  // Chart 系 (CAR-994 Phase A) ... 1 node に datum 配列を持ち、 kind 内で SVG geometry 描画。
51
51
  // 実際の w/h は preset chart() が w/h override で指定 (default fallback は preset 未指定時のみ)。
@@ -23,11 +23,19 @@ function labelTextOpacity(line: EdgeLabelLine): number | undefined {
23
23
  export function CdlEdgeView({
24
24
  edge,
25
25
  active,
26
+ drawing,
26
27
  progress,
27
28
  stateValues,
28
29
  }: {
29
30
  edge: LaidEdge;
30
31
  active: boolean;
32
+ /**
33
+ * この段でこの矢印が **初めて出る** か (#584)。
34
+ *
35
+ * 真の時だけ起点から伸ばす。 光っているかで引くと、光り続ける図で段が変わるたびに引き直され、
36
+ * 既に見えている線が毎回動く (user 実機確認)。 「増えた」 のは 1 度だけなので、動くのも 1 度。
37
+ */
38
+ drawing: boolean;
31
39
  progress: number;
32
40
  stateValues?: Record<string, string>;
33
41
  }): JSX.Element {
@@ -77,6 +85,7 @@ export function CdlEdgeView({
77
85
  data-cdl-from={edge.from}
78
86
  data-cdl-to={edge.to}
79
87
  data-cdl-active={active ? "true" : "false"}
88
+ data-cdl-drawing={drawing ? "true" : "false"}
80
89
  data-cdl-path-d={edge.d}
81
90
  data-cdl-label-x={edge.labelX}
82
91
  data-cdl-label-y={edge.labelY}
@@ -106,6 +115,7 @@ export function CdlEdgeView({
106
115
  <SolidEdgePath
107
116
  edge={edge}
108
117
  active={active}
118
+ drawing={drawing}
109
119
  progress={progress}
110
120
  color={color}
111
121
  marker={marker}
@@ -130,13 +140,17 @@ export function CdlEdgeView({
130
140
  }
131
141
 
132
142
  /**
133
- * SolidEdgePath ... solid edge の path を progress 連動で「phase 開始時 0 → 進行と共に伸びる」 動きで描画。
143
+ * SolidEdgePath ... solid edge の path を progress 連動で「段の始まりで 0 → 進行と共に伸びる」 動きで描画。
134
144
  * pathSubpath(d, progress) で d 自体を progress * totalLength の地点まで切り詰めて、
135
145
  * SVG <path d=... markerEnd=...> で marker を path 末端 (= 現在進行位置) に atomic 配置。
146
+ *
147
+ * **伸ばすのは初めて出る段だけ** (#584)。 光っているかで引くと、段をまたいで光り続ける図で
148
+ * 既に見えている線が毎段引き直される。
136
149
  */
137
150
  function SolidEdgePath({
138
151
  edge,
139
152
  active,
153
+ drawing,
140
154
  progress,
141
155
  color,
142
156
  marker,
@@ -146,6 +160,7 @@ function SolidEdgePath({
146
160
  }: {
147
161
  edge: LaidEdge;
148
162
  active: boolean;
163
+ drawing: boolean;
149
164
  progress: number;
150
165
  color: string;
151
166
  marker: string | undefined;
@@ -153,7 +168,8 @@ function SolidEdgePath({
153
168
  dashed: boolean;
154
169
  stateValues?: Record<string, string>;
155
170
  }): JSX.Element {
156
- const visibleD = active ? pathSubpath(edge.d, progress) : edge.d;
171
+ // 伸ばすのは初めて出る段だけ (#584) 光っているかで引くと、光り続ける図で毎段引き直される
172
+ const visibleD = drawing ? pathSubpath(edge.d, progress) : edge.d;
157
173
  // signal binding: widthBind / strokeBind / dashOffsetBind (CAR edge-signal-binding)
158
174
  const defaultWidth = active ? 5 : 2.5;
159
175
  const boundWidth = edge.widthBind && stateValues
@@ -47,20 +47,37 @@ export function CdlStage({
47
47
  *
48
48
  * 著者が `edgeReveal: "all"` と書いた図では隠さない。
49
49
  */
50
- const 出番の来た矢印 = useMemo(() => {
51
- // 著者が「最初から全部見せる」 と書いた図では隠さない (#582)
52
- if ((laid.edgeReveal ?? EDGE_REVEAL_DEFAULT) === "all") return () => true;
50
+ const 矢印の出番 = useMemo(() => {
53
51
  const 初出 = new Map<string, number>();
54
52
  laid.phases.forEach((p, i) => {
55
53
  for (const id of p.activate ?? []) if (!初出.has(id)) 初出.set(id, i);
56
54
  });
57
55
  const 今 = currentPhase === undefined ? -1 : laid.phases.findIndex((p) => p.id === currentPhase.id);
58
- return (edgeId: string): boolean => {
59
- const first = 初出.get(edgeId);
60
- if (first === undefined) return true;
61
- return < 0 || 今 >= first;
56
+ // 著者が「最初から全部見せる」 と書いた図では隠さない (#582)
57
+ const 隠す = (laid.edgeReveal ?? EDGE_REVEAL_DEFAULT) !== "all";
58
+ return {
59
+ 出るか: (edgeId: string): boolean => {
60
+ if (!隠す) return true;
61
+ const first = 初出.get(edgeId);
62
+ if (first === undefined) return true;
63
+ return 今 < 0 || 今 >= first;
64
+ },
65
+ /*
66
+ * この段で初めて出るか (#584)。
67
+ *
68
+ * 起点から伸ばすのはこの段だけ。 光っているかで引くと、段をまたいで光り続ける図で
69
+ * 既に見えている線が毎段引き直される (実測 = 表の図で 3 本とも段が変わるたびに伸び直した)。
70
+ *
71
+ * **隠さない図でも初出は数える**。 `all` は「最初から見せる」 だけの指定で、
72
+ * 伸びる動きまで毎段繰り返してよいという意味ではない。
73
+ */
74
+ 伸ばすか: (edgeId: string): boolean => {
75
+ const first = 初出.get(edgeId);
76
+ if (first === undefined) return false;
77
+ return 今 === first;
78
+ },
62
79
  };
63
- }, [laid.phases, currentPhase]);
80
+ }, [laid.phases, currentPhase, laid.edgeReveal]);
64
81
  // この phase で左の起点から描き始める node (cdl#512)。 `activate` とは別集合で持つ =
65
82
  // 焦点が当たり続ける図で毎 phase 引き直すことになるため、 光っているかを引き金にしない
66
83
  const drawSet = new Set(currentPhase?.draw ?? []);
@@ -265,8 +282,15 @@ export function CdlStage({
265
282
  ))}
266
283
 
267
284
  {/* edges (1st pass) */}
268
- {laid.edges.filter((edge) => 出番の来た矢印(edge.id)).map((edge) => (
269
- <CdlEdgeView key={edge.id} edge={edge} active={activeSet.has(edge.id)} progress={progress} stateValues={stateValues} />
285
+ {laid.edges.filter((edge) => 矢印の出番.出るか(edge.id)).map((edge) => (
286
+ <CdlEdgeView
287
+ key={edge.id}
288
+ edge={edge}
289
+ active={activeSet.has(edge.id)}
290
+ drawing={矢印の出番.伸ばすか(edge.id)}
291
+ progress={progress}
292
+ stateValues={stateValues}
293
+ />
270
294
  ))}
271
295
 
272
296
  {/* nodes (2nd pass) */}
@@ -290,13 +314,13 @@ export function CdlStage({
290
314
 
291
315
  {/* 経由 node 貫通する dotted-flow edge の進行点 glow (3rd pass) */}
292
316
  {laid.edges
293
- .filter((edge) => Boolean(edge.dThrough) && 出番の来た矢印(edge.id))
317
+ .filter((edge) => Boolean(edge.dThrough) && 矢印の出番.出るか(edge.id))
294
318
  .map((edge) => (
295
319
  <CdlEdgeGlowView key={`glow-${edge.id}`} edge={edge} active={activeSet.has(edge.id)} />
296
320
  ))}
297
321
 
298
322
  {/* edge labels (3rd pass) ... 全 edge の label を最前面に描画 */}
299
- {laid.edges.filter((edge) => 出番の来た矢印(edge.id)).map((edge) => (
323
+ {laid.edges.filter((edge) => 矢印の出番.出るか(edge.id)).map((edge) => (
300
324
  <CdlEdgeLabelView
301
325
  key={`label-${edge.id}`}
302
326
  edge={edge}