@cardenelabs/cdl 0.15.0 → 0.17.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.
@@ -29,11 +29,72 @@ interface Computed<T> {
29
29
  }
30
30
  declare function computed<T>(fn: () => T): Computed<T>;
31
31
 
32
+ /**
33
+ * 段が進むと濃さが移るための、状態の名前 (#578)。
34
+ *
35
+ * **記号を落とす**。 `{名前}` の中で読めるのは `\w` だけ (`template-name.ts`) で、`-` を
36
+ * 含む名前は 1 度も置換されない = 濃さが動かないまま緑になる (実測)。
37
+ *
38
+ * 見本の側 (`withSteps` の `sets`) と描く側 (`sequenceStep`) が同じ名前を引く必要があるので、
39
+ * 導き方をここに置いて両方から呼ぶ。
40
+ *
41
+ * **図の id からは導かない**。 記法は id を書けず名前から導く規則を持つため、同じ図を
42
+ * 記法から書くと状態の名前だけがずれる (実測)。 図の中に順序図の箱は 1 つしか無く、状態は
43
+ * 図ごとに閉じているので、決め打ちで足りる。
44
+ */
45
+ declare function sequenceStepId(): string;
46
+ type SequenceBoardActor = {
47
+ name: string;
48
+ subtitle?: string;
49
+ };
50
+ type SequenceBoardMessageKind = "call" | "return" | "fire";
51
+ type SequenceBoardMessage = {
52
+ label: string;
53
+ /** 出どころの面の番号 */
54
+ from: number;
55
+ /** 着き先の面の番号。 `from` と同じなら自分宛て */
56
+ to: number;
57
+ kind: SequenceBoardMessageKind;
58
+ };
59
+ /** 動いている間の帯。 段の番号で持つ (途中で手が空く面があるので区間の並び) */
60
+ type SequenceBoardBand = {
61
+ actor: number;
62
+ from: number;
63
+ to: number;
64
+ };
65
+ type SequenceBoardData = {
66
+ actors: readonly SequenceBoardActor[];
67
+ messages: readonly SequenceBoardMessage[];
68
+ bands: readonly SequenceBoardBand[];
69
+ };
70
+ type SequenceBoardMetrics = {
71
+ w: number;
72
+ h: number;
73
+ /** 語を置く左の桁の幅 = 最初の糸の x */
74
+ gutter: number;
75
+ colW: number;
76
+ /** 横罫の y */
77
+ headY: number;
78
+ /** 面 i の糸の x */
79
+ cx: (i: number) => number;
80
+ /** 段 i の y */
81
+ rowY: (i: number) => number;
82
+ /** 糸の下端 */
83
+ bottom: number;
84
+ };
85
+ /**
86
+ * 中身から寸法を出す。
87
+ *
88
+ * 幅は **語の桁 + 列 × 面の数**。 語を線の脇ではなく左の桁に置くので、線の長さが語の長さに
89
+ * 引きずられない = 面の数だけで横幅が決まる。
90
+ */
91
+ declare function sequenceBoardMetrics(data: SequenceBoardData): SequenceBoardMetrics;
92
+
32
93
  /** 意味付きの色の名前。 検査・描画・test はこの 1 つの列を出所にする。 */
33
94
  declare const TONES: readonly ["accent", "teal", "success", "error", "warning", "info"];
34
95
  type Tone = (typeof TONES)[number];
35
96
  /** 描画できる箱の種類。 検査・記法一覧・型はこの 1 つの列を出所にする。 */
36
- declare const NODE_KINDS: readonly ["dyn-rect", "dyn-circle", "dyn-arc", "dyn-wave", "dyn-polygon", "actor", "function", "storage", "event", "card", "person", "user-group", "admin", "developer", "external-user", "database", "cache", "queue", "message-bus", "cloud", "cdn", "service", "api", "frontend", "backend", "webhook", "microservice", "signer", "oracle", "merkle-tree", "decision", "chart-pie", "chart-line", "chart-bar", "chart-gauge", "chart-radial", "chart-stat", "chart-waffle", "chart-stacked-bar", "gantt-timeline", "mind-map", "funnel-stages", "quadrant-matrix", "tree-hierarchy", "journey-map", "shape-file", "shape-folder", "shape-cloud", "shape-cylinder", "shape-hexagon", "shape-diamond", "shape-stack", "shape-person", "shape-window", "shape-terminal", "shape-code-block", "shape-kanban-card", "shape-message-bubble", "shape-gear", "shape-server-rack", "shape-network-node", "shape-mobile-device", "shape-iot-sensor", "shape-robot-arm", "shape-satellite", "shape-smart-contract", "shape-blockchain-block", "shape-rpc-node", "shape-wallet", "shape-nft", "shape-token", "shape-blockchain", "shape-bitcoin-chain", "shape-ethereum-chain", "shape-blockchain-node", "shape-bank", "shape-trust-bank", "shape-payment-provider", "shape-credit-card", "shape-brokerage", "shape-exchange", "shape-atm", "shape-website", "shape-storefront", "shape-warehouse", "shape-online-shop", "shape-cdn-edge", "shape-api-gateway", "shape-auditor", "shape-regulator", "shape-notary", "shape-lawyer", "shape-trader", "shape-customer-service", "mark-start", "mark-end"];
97
+ declare const NODE_KINDS: readonly ["dyn-rect", "dyn-circle", "dyn-arc", "dyn-wave", "dyn-polygon", "actor", "function", "storage", "event", "card", "person", "user-group", "admin", "developer", "external-user", "database", "cache", "queue", "message-bus", "cloud", "cdn", "service", "api", "frontend", "backend", "webhook", "microservice", "signer", "oracle", "merkle-tree", "decision", "chart-pie", "chart-line", "chart-bar", "chart-gauge", "chart-radial", "chart-stat", "chart-waffle", "chart-stacked-bar", "gantt-timeline", "mind-map", "funnel-stages", "quadrant-matrix", "tree-hierarchy", "journey-map", "shape-file", "shape-folder", "shape-cloud", "shape-cylinder", "shape-hexagon", "shape-diamond", "shape-stack", "shape-person", "shape-window", "shape-terminal", "shape-code-block", "shape-kanban-card", "shape-message-bubble", "shape-gear", "shape-server-rack", "shape-network-node", "shape-mobile-device", "shape-iot-sensor", "shape-robot-arm", "shape-satellite", "shape-smart-contract", "shape-blockchain-block", "shape-rpc-node", "shape-wallet", "shape-nft", "shape-token", "shape-blockchain", "shape-bitcoin-chain", "shape-ethereum-chain", "shape-blockchain-node", "shape-bank", "shape-trust-bank", "shape-payment-provider", "shape-credit-card", "shape-brokerage", "shape-exchange", "shape-atm", "shape-website", "shape-storefront", "shape-warehouse", "shape-online-shop", "shape-cdn-edge", "shape-api-gateway", "shape-auditor", "shape-regulator", "shape-notary", "shape-lawyer", "shape-trader", "shape-customer-service", "mark-start", "mark-end", "sequence-board"];
37
98
  type NodeKind = (typeof NODE_KINDS)[number];
38
99
  type Side = "top" | "right" | "bottom" | "left";
39
100
  /**
@@ -41,25 +102,97 @@ type Side = "top" | "right" | "bottom" | "left";
41
102
  * - "solid" (default) ... 実線 + 矢頭、 inactive は dashed grey
42
103
  * - "dotted-flow" ... 点線 + active phase で粒子が path 沿いに流れる。
43
104
  * path が経由 node を貫通する場合は自動で粒子が node 中心を貫通する動きに切替。
105
+ * - "dashed" ... 刻んだ線。 **光っていても刻みのまま**。
106
+ *
107
+ * `"dashed"` が要るのは、`"solid"` の刻みが「光っていない」 を表す合図に使われているため。
108
+ * 光ると実線に戻るので、線の種類として刻みを持たせられない。 UML の「満たす」 と「使う」、
109
+ * ER の「識別しない」 のように **刻みが意味を持つ関係** はこちらを使う。
110
+ */
111
+ type EdgeStyle = "solid" | "dotted-flow" | "dashed";
112
+ /**
113
+ * 線の種類の全種 (#578)。 **型だけでなく実体を持つ**。
114
+ *
115
+ * 利用側 (dragon の記法) は受理する語を手で並べており、種類を足した時に取り残されていた
116
+ * (実測 = `dashed` を足した後、記法に書くと「線種が読めません」 で落ちた)。 一覧をここから
117
+ * 導けば、足した時点で書けるようになる。
44
118
  */
45
- type EdgeStyle = "solid" | "dotted-flow";
119
+ declare const EDGE_STYLES: readonly EdgeStyle[];
46
120
  /**
47
121
  * 関係の **端の形** (#560)。 線の種類 (`EdgeStyle`) とは別の軸で、線の先端に何を置くかを決める。
48
122
  *
123
+ * - `"none"` ... 何も描かない。 **端の 1 つに印を置かない関係** に使う (#578)
49
124
  * - `"triangle"` ... 塗った三角。 **既定**。 書かなければこれになる
50
125
  * - `"diamond"` ... 塗った菱。 「持っている」 側を指す
51
126
  * - `"open"` ... 閉じない 2 本の腕。 向きだけを示し、待たない
52
127
  * - `"crow"` ... 三又。 「多」 を示す (ER の鳥の足)
53
128
  *
129
+ * ER の端は **2 つの記号が重なってできている** (#578)。 箱に近い側が個数 (棒 = 1 /
130
+ * 三又 = 多)、その外側が任意か (棒 = 必須 / 丸 = 任意)。 2 × 2 の 4 通りを 1 つの形として持つ。
131
+ *
132
+ * - `"one"` ... 棒が 2 本。 ちょうど 1 つ
133
+ * - `"zero-one"` ... 棒に丸。 1 つ、または無い
134
+ * - `"many"` ... 三又に棒。 少なくとも 1 つ
135
+ * - `"zero-many"` ... 三又に丸。 いくつでも、無くてもよい
136
+ *
137
+ * 4 通りを 2 つの欄に分けないのは、**端の印は 1 つの記号として読まれる**ため。 欄を分けると
138
+ * 片方だけ書いた形 (個数はあるが任意かが無い) を許すことになり、描けない組み合わせが増える。
139
+ *
54
140
  * 線の種類と分けて持つのは、両者が独立に組み合わさるため。 実線 × 三角 (継ぐ) と
55
141
  * 破線 × 三角 (満たす) は線種で分かれ、実線 × 三角 (継ぐ) と実線 × 菱 (持つ) は端で分かれる。
56
142
  * 1 つの欄に畳むと 2 軸の積を名前で列挙することになり、組合せが増えるたびに語が増える。
57
143
  */
58
- type EdgeHead = "triangle" | "diamond" | "open" | "crow";
144
+ type EdgeHead = "none" | "triangle" | "diamond" | "open" | "crow" | "one" | "zero-one" | "many" | "zero-many";
59
145
  /** 書かなかった時の端の形。 既存の図はすべてこれで描かれている */
60
146
  declare const EDGE_HEAD_DEFAULT: EdgeHead;
61
147
  /** 端の形の全種。 marker の定義と検査の走査がこの並びを引く (書き写すとずれる) */
62
148
  declare const EDGE_HEADS: readonly EdgeHead[];
149
+ /**
150
+ * 端の印の **塗り方** (#578)。 形 (`EdgeHead`) とは別の軸。
151
+ *
152
+ * - `"solid"` ... 墨で塗る。 **既定**。 書かなければ形ごとの既定 (`EDGE_HEAD_SHAPE.filled`) に従う
153
+ * - `"hollow"` ... 紙の色で塗り、輪郭だけを線で描く
154
+ *
155
+ * UML は同じ形を塗りで分ける = 白抜きの菱が「持つ」、塗った菱が「抱える」 (命が同じ)。
156
+ * 形を増やして表そうとすると、塗りの軸を持つ全ての形について語が倍になる。
157
+ *
158
+ * 塗らない形 (`"open"` / `"crow"`) には効かない。 元から輪郭しか無いため。
159
+ */
160
+ type EdgeHeadFill = "solid" | "hollow";
161
+ /** 書かなかった時の塗り方 */
162
+ declare const EDGE_HEAD_FILL_DEFAULT: EdgeHeadFill;
163
+ /** 塗り方の全種。 marker の定義と検査の走査がこの並びを引く */
164
+ declare const EDGE_HEAD_FILLS: readonly EdgeHeadFill[];
165
+ /**
166
+ * 行き先と出どころの **両端に印を置ける** (#578)。
167
+ *
168
+ * `head` が行き先、`tailHead` が出どころ。 どちらも `"none"` を書けばその端には何も描かない。
169
+ *
170
+ * 側が種類で割れるのが要点。 三角は「この先が親」 を指すので行き先に立ち、菱は
171
+ * 「この箱が持っている」 を指すので出どころに立つ。 ER は端ごとに違う個数を示すので両端に要る。
172
+ * 1 つの欄で「どちら側か」 を持つ形にすると、両端に置く関係が書けない。
173
+ */
174
+ /**
175
+ * 行頭の印 (#578)。 **形 × 塗り の 2 軸**で 4 通りを分ける。
176
+ *
177
+ * 軸の意味は図の種類が決める = クラス図は 持ち物/振る舞い × 公開/非公開、
178
+ * ER 図は 値/外部キー × 必須/任意、状態遷移図は 状態の中/出入り × 続く/瞬間。
179
+ * 描画側が持つのは形だけで、意味は持たない。
180
+ *
181
+ * 印を持つ行は **区切り線を引かない**。 印が群を分けるので、線と印で二重に分けることになる。
182
+ */
183
+ type RowMark = {
184
+ /** 四角 (`"square"`) か山形 (`"chevron"`) か */
185
+ shape: "square" | "chevron";
186
+ /** 塗るか。 塗らない印は輪郭だけを描く */
187
+ filled: boolean;
188
+ /**
189
+ * 名前に下線を引くか (#578)。 ER の主キーに使う。
190
+ *
191
+ * **印の 2 軸とは別の段**に置く。 3 つ目の軸を印に足すと 4 通りが 8 通りになって
192
+ * 見分けが付かなくなるので、下線を重ねる形にした = 外部キーの山形と重ねられる。
193
+ */
194
+ underline?: boolean;
195
+ };
63
196
  type CdlLane = {
64
197
  id: string;
65
198
  /** lane の x 座標 (optional、 未指定なら engine が前 lane 右端 + gap で auto 計算) */
@@ -143,6 +276,29 @@ type CdlNode = {
143
276
  value?: string;
144
277
  /** kind=storage 時の行 (各 mono、 state 参照可) */
145
278
  rows?: string[];
279
+ /**
280
+ * 行頭の印 (#578)。 `rows` と同じ並びで、`null` の位置には印を描かない。
281
+ *
282
+ * **印を持つ行は書き方そのものが変わる**。 区切り線 2 本を引かず、名前を印の右に置き、
283
+ * 型を箱の右端へ薄く右揃えで置く。 線で分けるのをやめて印で分ける形なので、両方は要らない。
284
+ *
285
+ * 空文字の行と `null` の印を組にすると **群の間** になる (持ち物と振る舞いの間など)。
286
+ */
287
+ rowMarks?: readonly (RowMark | null)[];
288
+ /**
289
+ * 時系列のやり取りの中身 (#578)。 `sequence-board` 種別が読む。
290
+ *
291
+ * 面々と言づてと帯を 1 つの箱に持たせ、内側の配置は種別が決める。 図表の種別
292
+ * (`gantt-timeline` 等) と同じ持ち方。
293
+ */
294
+ sequenceData?: SequenceBoardData;
295
+ /**
296
+ * いま何番目の言づてを見ているか (#578)。 `"{seq}"` のように状態から取る。
297
+ *
298
+ * 書かない図では全部を濃く出す = 段を持たない使い方 (縮小見本 / 静止画) で薄い絵にすると、
299
+ * 読み手には壊れて見える。
300
+ */
301
+ sequenceStep?: string;
146
302
  /** width override (default は NodeKind 別 NODE_SIZE)、 catalog thumbnail 用に縮小可 */
147
303
  w?: number;
148
304
  /** height override */
@@ -412,6 +568,21 @@ type CdlEdge = {
412
568
  style?: EdgeStyle;
413
569
  /** 端の形、 default "triangle" (#560)。 線の種類とは別の軸 */
414
570
  head?: EdgeHead;
571
+ /**
572
+ * 端の印の塗り方 (#578)。 書かなければ形ごとの既定。 塗らない形には効かない。
573
+ *
574
+ * 形と分けて持つのは、UML が同じ形を塗りで分けるため (白抜きの菱 = 持つ /
575
+ * 塗った菱 = 抱える)。
576
+ */
577
+ headFill?: EdgeHeadFill;
578
+ /**
579
+ * **出どころ側**の端の印 (#578)。 書かなければ何も描かない。
580
+ *
581
+ * 行き先側は `head`。 両方に置けるので、ER のように端ごとに違う個数を示す関係が書ける。
582
+ */
583
+ tailHead?: EdgeHead;
584
+ /** 出どころ側の印の塗り (#578)。 書かなければ形ごとの既定 */
585
+ tailHeadFill?: EdgeHeadFill;
415
586
  /**
416
587
  * FSM transition の guard 条件 (例 "if validated")。
417
588
  * stateMachine preset では sub に併合される、 text-dsl v0.5 では guard 単独で渡せる。
@@ -2615,4 +2786,4 @@ type CdlDiagramViewProps = {
2615
2786
  };
2616
2787
  declare function CdlDiagramView({ diagram, laid: laidProp, hideHeader, hideMiniPhaseIndicator, focusPhaseId, debug, emitGeometryWarn, headingLevel, interactiveHandlers }: CdlDiagramViewProps): JSX.Element;
2617
2788
 
2618
- export { computeEventBindingKey as A, type BBox as B, type CdlDiagram as C, computeFormulaKey as D, type EdgeStyle as E, computeInputSignalKey as F, computeScrollTriggerKey as G, computed as H, type InteractiveHandlerMap as I, type JourneyEmotion as J, createInteractiveSignalsAccessor as K, type LaidDiagram as L, createScrollProgressHandle as M, type NodeKind as N, createScrollProgressSignals as O, hasInteractivePrimitives as P, type QuadrantKey as Q, signal as R, type Signal as S, type Tone as T, type CdlInput as a, type CdlLane as b, type CdlNode as c, type Side as d, type EdgeHead as e, type CdlState as f, type CdlEventTarget as g, type Computed as h, type CdlDerivedValue as i, type CdlScrollTrigger as j, type CdlDiagramViewProps as k, type LaidEdge as l, type LaidNode as m, type CdlEdge as n, CdlDiagramView as o, type CdlEventBinding as p, type CdlEventKind as q, type CdlFormula as r, type CdlPhase as s, EDGE_HEADS as t, EDGE_HEAD_DEFAULT as u, type InteractiveSignalsAccessor as v, type LaidLane as w, NODE_KINDS as x, type ScrollProgressHandle as y, TONES as z };
2789
+ export { type LaidLane as A, type BBox as B, type CdlDiagram as C, NODE_KINDS as D, type EdgeStyle as E, type ScrollProgressHandle as F, TONES as G, computeEventBindingKey as H, type InteractiveHandlerMap as I, type JourneyEmotion as J, computeFormulaKey as K, type LaidDiagram as L, computeInputSignalKey as M, type NodeKind as N, computeScrollTriggerKey as O, computed as P, type QuadrantKey as Q, type RowMark as R, type Signal as S, type Tone as T, createInteractiveSignalsAccessor as U, createScrollProgressHandle as V, createScrollProgressSignals as W, hasInteractivePrimitives as X, sequenceBoardMetrics as Y, sequenceStepId as Z, signal as _, type CdlInput as a, type CdlLane as b, type CdlNode as c, type Side as d, type EdgeHead as e, type EdgeHeadFill as f, type CdlState as g, type CdlEventTarget as h, type Computed as i, type CdlDerivedValue as j, type CdlScrollTrigger as k, type CdlDiagramViewProps as l, type LaidEdge as m, type LaidNode as n, type CdlEdge as o, CdlDiagramView as p, type CdlEventBinding as q, type CdlEventKind as r, type CdlFormula as s, type CdlPhase as t, EDGE_HEADS as u, EDGE_HEAD_DEFAULT as v, EDGE_HEAD_FILLS as w, EDGE_HEAD_FILL_DEFAULT as x, EDGE_STYLES as y, type InteractiveSignalsAccessor as z };
@@ -29,11 +29,72 @@ interface Computed<T> {
29
29
  }
30
30
  declare function computed<T>(fn: () => T): Computed<T>;
31
31
 
32
+ /**
33
+ * 段が進むと濃さが移るための、状態の名前 (#578)。
34
+ *
35
+ * **記号を落とす**。 `{名前}` の中で読めるのは `\w` だけ (`template-name.ts`) で、`-` を
36
+ * 含む名前は 1 度も置換されない = 濃さが動かないまま緑になる (実測)。
37
+ *
38
+ * 見本の側 (`withSteps` の `sets`) と描く側 (`sequenceStep`) が同じ名前を引く必要があるので、
39
+ * 導き方をここに置いて両方から呼ぶ。
40
+ *
41
+ * **図の id からは導かない**。 記法は id を書けず名前から導く規則を持つため、同じ図を
42
+ * 記法から書くと状態の名前だけがずれる (実測)。 図の中に順序図の箱は 1 つしか無く、状態は
43
+ * 図ごとに閉じているので、決め打ちで足りる。
44
+ */
45
+ declare function sequenceStepId(): string;
46
+ type SequenceBoardActor = {
47
+ name: string;
48
+ subtitle?: string;
49
+ };
50
+ type SequenceBoardMessageKind = "call" | "return" | "fire";
51
+ type SequenceBoardMessage = {
52
+ label: string;
53
+ /** 出どころの面の番号 */
54
+ from: number;
55
+ /** 着き先の面の番号。 `from` と同じなら自分宛て */
56
+ to: number;
57
+ kind: SequenceBoardMessageKind;
58
+ };
59
+ /** 動いている間の帯。 段の番号で持つ (途中で手が空く面があるので区間の並び) */
60
+ type SequenceBoardBand = {
61
+ actor: number;
62
+ from: number;
63
+ to: number;
64
+ };
65
+ type SequenceBoardData = {
66
+ actors: readonly SequenceBoardActor[];
67
+ messages: readonly SequenceBoardMessage[];
68
+ bands: readonly SequenceBoardBand[];
69
+ };
70
+ type SequenceBoardMetrics = {
71
+ w: number;
72
+ h: number;
73
+ /** 語を置く左の桁の幅 = 最初の糸の x */
74
+ gutter: number;
75
+ colW: number;
76
+ /** 横罫の y */
77
+ headY: number;
78
+ /** 面 i の糸の x */
79
+ cx: (i: number) => number;
80
+ /** 段 i の y */
81
+ rowY: (i: number) => number;
82
+ /** 糸の下端 */
83
+ bottom: number;
84
+ };
85
+ /**
86
+ * 中身から寸法を出す。
87
+ *
88
+ * 幅は **語の桁 + 列 × 面の数**。 語を線の脇ではなく左の桁に置くので、線の長さが語の長さに
89
+ * 引きずられない = 面の数だけで横幅が決まる。
90
+ */
91
+ declare function sequenceBoardMetrics(data: SequenceBoardData): SequenceBoardMetrics;
92
+
32
93
  /** 意味付きの色の名前。 検査・描画・test はこの 1 つの列を出所にする。 */
33
94
  declare const TONES: readonly ["accent", "teal", "success", "error", "warning", "info"];
34
95
  type Tone = (typeof TONES)[number];
35
96
  /** 描画できる箱の種類。 検査・記法一覧・型はこの 1 つの列を出所にする。 */
36
- declare const NODE_KINDS: readonly ["dyn-rect", "dyn-circle", "dyn-arc", "dyn-wave", "dyn-polygon", "actor", "function", "storage", "event", "card", "person", "user-group", "admin", "developer", "external-user", "database", "cache", "queue", "message-bus", "cloud", "cdn", "service", "api", "frontend", "backend", "webhook", "microservice", "signer", "oracle", "merkle-tree", "decision", "chart-pie", "chart-line", "chart-bar", "chart-gauge", "chart-radial", "chart-stat", "chart-waffle", "chart-stacked-bar", "gantt-timeline", "mind-map", "funnel-stages", "quadrant-matrix", "tree-hierarchy", "journey-map", "shape-file", "shape-folder", "shape-cloud", "shape-cylinder", "shape-hexagon", "shape-diamond", "shape-stack", "shape-person", "shape-window", "shape-terminal", "shape-code-block", "shape-kanban-card", "shape-message-bubble", "shape-gear", "shape-server-rack", "shape-network-node", "shape-mobile-device", "shape-iot-sensor", "shape-robot-arm", "shape-satellite", "shape-smart-contract", "shape-blockchain-block", "shape-rpc-node", "shape-wallet", "shape-nft", "shape-token", "shape-blockchain", "shape-bitcoin-chain", "shape-ethereum-chain", "shape-blockchain-node", "shape-bank", "shape-trust-bank", "shape-payment-provider", "shape-credit-card", "shape-brokerage", "shape-exchange", "shape-atm", "shape-website", "shape-storefront", "shape-warehouse", "shape-online-shop", "shape-cdn-edge", "shape-api-gateway", "shape-auditor", "shape-regulator", "shape-notary", "shape-lawyer", "shape-trader", "shape-customer-service", "mark-start", "mark-end"];
97
+ declare const NODE_KINDS: readonly ["dyn-rect", "dyn-circle", "dyn-arc", "dyn-wave", "dyn-polygon", "actor", "function", "storage", "event", "card", "person", "user-group", "admin", "developer", "external-user", "database", "cache", "queue", "message-bus", "cloud", "cdn", "service", "api", "frontend", "backend", "webhook", "microservice", "signer", "oracle", "merkle-tree", "decision", "chart-pie", "chart-line", "chart-bar", "chart-gauge", "chart-radial", "chart-stat", "chart-waffle", "chart-stacked-bar", "gantt-timeline", "mind-map", "funnel-stages", "quadrant-matrix", "tree-hierarchy", "journey-map", "shape-file", "shape-folder", "shape-cloud", "shape-cylinder", "shape-hexagon", "shape-diamond", "shape-stack", "shape-person", "shape-window", "shape-terminal", "shape-code-block", "shape-kanban-card", "shape-message-bubble", "shape-gear", "shape-server-rack", "shape-network-node", "shape-mobile-device", "shape-iot-sensor", "shape-robot-arm", "shape-satellite", "shape-smart-contract", "shape-blockchain-block", "shape-rpc-node", "shape-wallet", "shape-nft", "shape-token", "shape-blockchain", "shape-bitcoin-chain", "shape-ethereum-chain", "shape-blockchain-node", "shape-bank", "shape-trust-bank", "shape-payment-provider", "shape-credit-card", "shape-brokerage", "shape-exchange", "shape-atm", "shape-website", "shape-storefront", "shape-warehouse", "shape-online-shop", "shape-cdn-edge", "shape-api-gateway", "shape-auditor", "shape-regulator", "shape-notary", "shape-lawyer", "shape-trader", "shape-customer-service", "mark-start", "mark-end", "sequence-board"];
37
98
  type NodeKind = (typeof NODE_KINDS)[number];
38
99
  type Side = "top" | "right" | "bottom" | "left";
39
100
  /**
@@ -41,25 +102,97 @@ type Side = "top" | "right" | "bottom" | "left";
41
102
  * - "solid" (default) ... 実線 + 矢頭、 inactive は dashed grey
42
103
  * - "dotted-flow" ... 点線 + active phase で粒子が path 沿いに流れる。
43
104
  * path が経由 node を貫通する場合は自動で粒子が node 中心を貫通する動きに切替。
105
+ * - "dashed" ... 刻んだ線。 **光っていても刻みのまま**。
106
+ *
107
+ * `"dashed"` が要るのは、`"solid"` の刻みが「光っていない」 を表す合図に使われているため。
108
+ * 光ると実線に戻るので、線の種類として刻みを持たせられない。 UML の「満たす」 と「使う」、
109
+ * ER の「識別しない」 のように **刻みが意味を持つ関係** はこちらを使う。
110
+ */
111
+ type EdgeStyle = "solid" | "dotted-flow" | "dashed";
112
+ /**
113
+ * 線の種類の全種 (#578)。 **型だけでなく実体を持つ**。
114
+ *
115
+ * 利用側 (dragon の記法) は受理する語を手で並べており、種類を足した時に取り残されていた
116
+ * (実測 = `dashed` を足した後、記法に書くと「線種が読めません」 で落ちた)。 一覧をここから
117
+ * 導けば、足した時点で書けるようになる。
44
118
  */
45
- type EdgeStyle = "solid" | "dotted-flow";
119
+ declare const EDGE_STYLES: readonly EdgeStyle[];
46
120
  /**
47
121
  * 関係の **端の形** (#560)。 線の種類 (`EdgeStyle`) とは別の軸で、線の先端に何を置くかを決める。
48
122
  *
123
+ * - `"none"` ... 何も描かない。 **端の 1 つに印を置かない関係** に使う (#578)
49
124
  * - `"triangle"` ... 塗った三角。 **既定**。 書かなければこれになる
50
125
  * - `"diamond"` ... 塗った菱。 「持っている」 側を指す
51
126
  * - `"open"` ... 閉じない 2 本の腕。 向きだけを示し、待たない
52
127
  * - `"crow"` ... 三又。 「多」 を示す (ER の鳥の足)
53
128
  *
129
+ * ER の端は **2 つの記号が重なってできている** (#578)。 箱に近い側が個数 (棒 = 1 /
130
+ * 三又 = 多)、その外側が任意か (棒 = 必須 / 丸 = 任意)。 2 × 2 の 4 通りを 1 つの形として持つ。
131
+ *
132
+ * - `"one"` ... 棒が 2 本。 ちょうど 1 つ
133
+ * - `"zero-one"` ... 棒に丸。 1 つ、または無い
134
+ * - `"many"` ... 三又に棒。 少なくとも 1 つ
135
+ * - `"zero-many"` ... 三又に丸。 いくつでも、無くてもよい
136
+ *
137
+ * 4 通りを 2 つの欄に分けないのは、**端の印は 1 つの記号として読まれる**ため。 欄を分けると
138
+ * 片方だけ書いた形 (個数はあるが任意かが無い) を許すことになり、描けない組み合わせが増える。
139
+ *
54
140
  * 線の種類と分けて持つのは、両者が独立に組み合わさるため。 実線 × 三角 (継ぐ) と
55
141
  * 破線 × 三角 (満たす) は線種で分かれ、実線 × 三角 (継ぐ) と実線 × 菱 (持つ) は端で分かれる。
56
142
  * 1 つの欄に畳むと 2 軸の積を名前で列挙することになり、組合せが増えるたびに語が増える。
57
143
  */
58
- type EdgeHead = "triangle" | "diamond" | "open" | "crow";
144
+ type EdgeHead = "none" | "triangle" | "diamond" | "open" | "crow" | "one" | "zero-one" | "many" | "zero-many";
59
145
  /** 書かなかった時の端の形。 既存の図はすべてこれで描かれている */
60
146
  declare const EDGE_HEAD_DEFAULT: EdgeHead;
61
147
  /** 端の形の全種。 marker の定義と検査の走査がこの並びを引く (書き写すとずれる) */
62
148
  declare const EDGE_HEADS: readonly EdgeHead[];
149
+ /**
150
+ * 端の印の **塗り方** (#578)。 形 (`EdgeHead`) とは別の軸。
151
+ *
152
+ * - `"solid"` ... 墨で塗る。 **既定**。 書かなければ形ごとの既定 (`EDGE_HEAD_SHAPE.filled`) に従う
153
+ * - `"hollow"` ... 紙の色で塗り、輪郭だけを線で描く
154
+ *
155
+ * UML は同じ形を塗りで分ける = 白抜きの菱が「持つ」、塗った菱が「抱える」 (命が同じ)。
156
+ * 形を増やして表そうとすると、塗りの軸を持つ全ての形について語が倍になる。
157
+ *
158
+ * 塗らない形 (`"open"` / `"crow"`) には効かない。 元から輪郭しか無いため。
159
+ */
160
+ type EdgeHeadFill = "solid" | "hollow";
161
+ /** 書かなかった時の塗り方 */
162
+ declare const EDGE_HEAD_FILL_DEFAULT: EdgeHeadFill;
163
+ /** 塗り方の全種。 marker の定義と検査の走査がこの並びを引く */
164
+ declare const EDGE_HEAD_FILLS: readonly EdgeHeadFill[];
165
+ /**
166
+ * 行き先と出どころの **両端に印を置ける** (#578)。
167
+ *
168
+ * `head` が行き先、`tailHead` が出どころ。 どちらも `"none"` を書けばその端には何も描かない。
169
+ *
170
+ * 側が種類で割れるのが要点。 三角は「この先が親」 を指すので行き先に立ち、菱は
171
+ * 「この箱が持っている」 を指すので出どころに立つ。 ER は端ごとに違う個数を示すので両端に要る。
172
+ * 1 つの欄で「どちら側か」 を持つ形にすると、両端に置く関係が書けない。
173
+ */
174
+ /**
175
+ * 行頭の印 (#578)。 **形 × 塗り の 2 軸**で 4 通りを分ける。
176
+ *
177
+ * 軸の意味は図の種類が決める = クラス図は 持ち物/振る舞い × 公開/非公開、
178
+ * ER 図は 値/外部キー × 必須/任意、状態遷移図は 状態の中/出入り × 続く/瞬間。
179
+ * 描画側が持つのは形だけで、意味は持たない。
180
+ *
181
+ * 印を持つ行は **区切り線を引かない**。 印が群を分けるので、線と印で二重に分けることになる。
182
+ */
183
+ type RowMark = {
184
+ /** 四角 (`"square"`) か山形 (`"chevron"`) か */
185
+ shape: "square" | "chevron";
186
+ /** 塗るか。 塗らない印は輪郭だけを描く */
187
+ filled: boolean;
188
+ /**
189
+ * 名前に下線を引くか (#578)。 ER の主キーに使う。
190
+ *
191
+ * **印の 2 軸とは別の段**に置く。 3 つ目の軸を印に足すと 4 通りが 8 通りになって
192
+ * 見分けが付かなくなるので、下線を重ねる形にした = 外部キーの山形と重ねられる。
193
+ */
194
+ underline?: boolean;
195
+ };
63
196
  type CdlLane = {
64
197
  id: string;
65
198
  /** lane の x 座標 (optional、 未指定なら engine が前 lane 右端 + gap で auto 計算) */
@@ -143,6 +276,29 @@ type CdlNode = {
143
276
  value?: string;
144
277
  /** kind=storage 時の行 (各 mono、 state 参照可) */
145
278
  rows?: string[];
279
+ /**
280
+ * 行頭の印 (#578)。 `rows` と同じ並びで、`null` の位置には印を描かない。
281
+ *
282
+ * **印を持つ行は書き方そのものが変わる**。 区切り線 2 本を引かず、名前を印の右に置き、
283
+ * 型を箱の右端へ薄く右揃えで置く。 線で分けるのをやめて印で分ける形なので、両方は要らない。
284
+ *
285
+ * 空文字の行と `null` の印を組にすると **群の間** になる (持ち物と振る舞いの間など)。
286
+ */
287
+ rowMarks?: readonly (RowMark | null)[];
288
+ /**
289
+ * 時系列のやり取りの中身 (#578)。 `sequence-board` 種別が読む。
290
+ *
291
+ * 面々と言づてと帯を 1 つの箱に持たせ、内側の配置は種別が決める。 図表の種別
292
+ * (`gantt-timeline` 等) と同じ持ち方。
293
+ */
294
+ sequenceData?: SequenceBoardData;
295
+ /**
296
+ * いま何番目の言づてを見ているか (#578)。 `"{seq}"` のように状態から取る。
297
+ *
298
+ * 書かない図では全部を濃く出す = 段を持たない使い方 (縮小見本 / 静止画) で薄い絵にすると、
299
+ * 読み手には壊れて見える。
300
+ */
301
+ sequenceStep?: string;
146
302
  /** width override (default は NodeKind 別 NODE_SIZE)、 catalog thumbnail 用に縮小可 */
147
303
  w?: number;
148
304
  /** height override */
@@ -412,6 +568,21 @@ type CdlEdge = {
412
568
  style?: EdgeStyle;
413
569
  /** 端の形、 default "triangle" (#560)。 線の種類とは別の軸 */
414
570
  head?: EdgeHead;
571
+ /**
572
+ * 端の印の塗り方 (#578)。 書かなければ形ごとの既定。 塗らない形には効かない。
573
+ *
574
+ * 形と分けて持つのは、UML が同じ形を塗りで分けるため (白抜きの菱 = 持つ /
575
+ * 塗った菱 = 抱える)。
576
+ */
577
+ headFill?: EdgeHeadFill;
578
+ /**
579
+ * **出どころ側**の端の印 (#578)。 書かなければ何も描かない。
580
+ *
581
+ * 行き先側は `head`。 両方に置けるので、ER のように端ごとに違う個数を示す関係が書ける。
582
+ */
583
+ tailHead?: EdgeHead;
584
+ /** 出どころ側の印の塗り (#578)。 書かなければ形ごとの既定 */
585
+ tailHeadFill?: EdgeHeadFill;
415
586
  /**
416
587
  * FSM transition の guard 条件 (例 "if validated")。
417
588
  * stateMachine preset では sub に併合される、 text-dsl v0.5 では guard 単独で渡せる。
@@ -2615,4 +2786,4 @@ type CdlDiagramViewProps = {
2615
2786
  };
2616
2787
  declare function CdlDiagramView({ diagram, laid: laidProp, hideHeader, hideMiniPhaseIndicator, focusPhaseId, debug, emitGeometryWarn, headingLevel, interactiveHandlers }: CdlDiagramViewProps): JSX.Element;
2617
2788
 
2618
- export { computeEventBindingKey as A, type BBox as B, type CdlDiagram as C, computeFormulaKey as D, type EdgeStyle as E, computeInputSignalKey as F, computeScrollTriggerKey as G, computed as H, type InteractiveHandlerMap as I, type JourneyEmotion as J, createInteractiveSignalsAccessor as K, type LaidDiagram as L, createScrollProgressHandle as M, type NodeKind as N, createScrollProgressSignals as O, hasInteractivePrimitives as P, type QuadrantKey as Q, signal as R, type Signal as S, type Tone as T, type CdlInput as a, type CdlLane as b, type CdlNode as c, type Side as d, type EdgeHead as e, type CdlState as f, type CdlEventTarget as g, type Computed as h, type CdlDerivedValue as i, type CdlScrollTrigger as j, type CdlDiagramViewProps as k, type LaidEdge as l, type LaidNode as m, type CdlEdge as n, CdlDiagramView as o, type CdlEventBinding as p, type CdlEventKind as q, type CdlFormula as r, type CdlPhase as s, EDGE_HEADS as t, EDGE_HEAD_DEFAULT as u, type InteractiveSignalsAccessor as v, type LaidLane as w, NODE_KINDS as x, type ScrollProgressHandle as y, TONES as z };
2789
+ export { type LaidLane as A, type BBox as B, type CdlDiagram as C, NODE_KINDS as D, type EdgeStyle as E, type ScrollProgressHandle as F, TONES as G, computeEventBindingKey as H, type InteractiveHandlerMap as I, type JourneyEmotion as J, computeFormulaKey as K, type LaidDiagram as L, computeInputSignalKey as M, type NodeKind as N, computeScrollTriggerKey as O, computed as P, type QuadrantKey as Q, type RowMark as R, type Signal as S, type Tone as T, createInteractiveSignalsAccessor as U, createScrollProgressHandle as V, createScrollProgressSignals as W, hasInteractivePrimitives as X, sequenceBoardMetrics as Y, sequenceStepId as Z, signal as _, type CdlInput as a, type CdlLane as b, type CdlNode as c, type Side as d, type EdgeHead as e, type EdgeHeadFill as f, type CdlState as g, type CdlEventTarget as h, type Computed as i, type CdlDerivedValue as j, type CdlScrollTrigger as k, type CdlDiagramViewProps as l, type LaidEdge as m, type LaidNode as n, type CdlEdge as o, CdlDiagramView as p, type CdlEventBinding as q, type CdlEventKind as r, type CdlFormula as s, type CdlPhase as t, EDGE_HEADS as u, EDGE_HEAD_DEFAULT as v, EDGE_HEAD_FILLS as w, EDGE_HEAD_FILL_DEFAULT as x, EDGE_STYLES as y, type InteractiveSignalsAccessor as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cardenelabs/cdl",
3
- "version": "0.15.0",
3
+ "version": "0.17.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",
package/src/builder.ts CHANGED
@@ -13,6 +13,7 @@ import type {
13
13
  CdlScrollTrigger,
14
14
  CdlState,
15
15
  EdgeHead,
16
+ EdgeHeadFill,
16
17
  EdgeStyle,
17
18
  NodeKind,
18
19
  Side,
@@ -1436,6 +1437,12 @@ export type DiagramBuilder = {
1436
1437
  style?: EdgeStyle;
1437
1438
  /** 端の形 (#560)、 既定は塗った三角。 線の種類とは別の軸 */
1438
1439
  head?: EdgeHead;
1440
+ /** 端の印の塗り (#578)。 書かなければ形ごとの既定 */
1441
+ headFill?: EdgeHeadFill;
1442
+ /** 出どころ側の端の印 (#578)。 書かなければ何も描かない */
1443
+ tailHead?: EdgeHead;
1444
+ /** 出どころ側の印の塗り (#578) */
1445
+ tailHeadFill?: EdgeHeadFill;
1439
1446
  /** FSM guard 条件、 text-dsl v0.5 inline option (`guard: "..."`) を CdlEdge.guard へ透過 */
1440
1447
  guard?: string;
1441
1448
  /** ER 関係 cardinality、 text-dsl v0.5 inline option (`cardinality: "1:N"`) を CdlEdge.cardinality へ透過 */
@@ -1540,6 +1547,12 @@ export type DiagramBuilder = {
1540
1547
  style?: EdgeStyle;
1541
1548
  /** 端の形 (#560)、 既定は塗った三角 */
1542
1549
  head?: EdgeHead;
1550
+ /** 端の印の塗り (#578)。 書かなければ形ごとの既定 */
1551
+ headFill?: EdgeHeadFill;
1552
+ /** 出どころ側の端の印 (#578)。 書かなければ何も描かない */
1553
+ tailHead?: EdgeHead;
1554
+ /** 出どころ側の印の塗り (#578) */
1555
+ tailHeadFill?: EdgeHeadFill;
1543
1556
  guard?: string;
1544
1557
  cardinality?: string;
1545
1558
  labelOffsetX?: number;
@@ -1743,6 +1756,9 @@ export function diagram(
1743
1756
  side: opts.side,
1744
1757
  style: opts.style,
1745
1758
  head: opts.head,
1759
+ headFill: opts.headFill,
1760
+ tailHead: opts.tailHead,
1761
+ tailHeadFill: opts.tailHeadFill,
1746
1762
  guard: opts.guard,
1747
1763
  cardinality: opts.cardinality,
1748
1764
  labelOffsetX: opts.labelOffsetX,
@@ -1874,6 +1890,9 @@ export function diagram(
1874
1890
  side: d.side,
1875
1891
  style: d.style,
1876
1892
  head: d.head,
1893
+ headFill: d.headFill,
1894
+ tailHead: d.tailHead,
1895
+ tailHeadFill: d.tailHeadFill,
1877
1896
  guard: d.guard,
1878
1897
  cardinality: d.cardinality,
1879
1898
  labelOffsetX: d.labelOffsetX,
package/src/index.ts CHANGED
@@ -194,6 +194,11 @@ export {
194
194
  bboxDiffWorld,
195
195
  } from "./layout/predict-bbox";
196
196
  export { swimlane, flow, sequence, topology, er, stateMachine, infrastructure, classDiagram, tree, userJourney, mindMap, funnel, quadrant, chart, gantt, flowchart, network, stateMachine2 } from "./presets";
197
+ // 意匠の表 (#578)。 図の種類ごとに「何をどう描くか」 を持つ SSOT で、見本と検査が同じ表を引く
198
+ export { CLASS_RELATION_LOOK, ER_CARDINALITY_HEAD, FSM_ACTION_MARK, SEQUENCE_MESSAGE_LOOK } from "./presets";
199
+ // 時系列のやり取りの図が引く名前と寸法 (#578)。 **組み立て器ではない** ので presets からは出さない
200
+ // (`mermaid-parity` が presets の公開関数を組み立て器として数える)
201
+ export { sequenceStepId, sequenceBoardMetrics } from "./kinds/sequence-board-metrics";
197
202
  // Text DSL は @cardenelabs/dragon に切出済 (cdl は engine only)
198
203
  export type {
199
204
  SwimlanePreset,
@@ -203,6 +208,8 @@ export type {
203
208
  SequencePreset,
204
209
  SequenceBuilder,
205
210
  SequenceStep,
211
+ SequenceActor,
212
+ SequenceMessageKind,
206
213
  TopologyPreset,
207
214
  TopologyBuilder,
208
215
  TopologyGroupBuilder,
@@ -211,11 +218,14 @@ export type {
211
218
  ErPreset,
212
219
  ErBuilder,
213
220
  ErEntity,
221
+ ErColumn,
214
222
  ErRelation,
215
223
  ErRelationCardinality,
216
224
  StateMachinePreset,
217
225
  StateMachineBuilder,
218
226
  FsmState,
227
+ FsmStateAction,
228
+ FsmMark,
219
229
  FsmTransition,
220
230
  InfrastructurePreset,
221
231
  InfrastructureBuilder,
@@ -273,6 +283,8 @@ export type {
273
283
  CdlPhase,
274
284
  CdlState,
275
285
  EdgeHead,
286
+ EdgeHeadFill,
287
+ RowMark,
276
288
  EdgeStyle,
277
289
  LaidDiagram,
278
290
  LaidEdge,
@@ -286,7 +298,15 @@ export type {
286
298
  // 手書きせずに済ませるため公開する。
287
299
  // 値としての tone / kind 一覧。 downstream (dragon の記法一覧 / parser 等) が
288
300
  // 受理できる値の集合を手書きせずに済ませるため公開する。
289
- export { TONES, NODE_KINDS, EDGE_HEADS, EDGE_HEAD_DEFAULT } from "./types";
301
+ export {
302
+ TONES,
303
+ NODE_KINDS,
304
+ EDGE_HEADS,
305
+ EDGE_HEAD_DEFAULT,
306
+ EDGE_HEAD_FILLS,
307
+ EDGE_HEAD_FILL_DEFAULT,
308
+ EDGE_STYLES,
309
+ } from "./types";
290
310
 
291
311
  /**
292
312
  * 段ごとの実効値を出す 2 つ。 downstream が「この段で箱に何の字が出るか」 を
@@ -14,7 +14,9 @@ export function CardNode({ node, active }: { node: LaidNode; active: boolean }):
14
14
  // compact card (h<100) は中央揃え (sequence header 等の小型 card 用)。
15
15
  // 高さの境界は `compact-title.ts` が持つ = 4 種と同じ値を使う (#416)
16
16
  const compact = isCompactBox(node.h);
17
- const titleY = compact ? node.h / 2 + 8 : 86;
17
+ // 小型の箱でも呼び名を出す (#578)。 出す時は題を上へ寄せて、2 行を箱の中で釣り合わせる
18
+ const 小型に呼び名 = compact && Boolean(node.subtitle);
19
+ const titleY = compact ? (小型に呼び名 ? node.h / 2 - 2 : node.h / 2 + 8) : 86;
18
20
  const titleX = compact ? node.w / 2 : 26;
19
21
  const paddingX = compact ? 16 : 52;
20
22
  const availableW = node.w - paddingX;
@@ -56,6 +58,18 @@ export function CardNode({ node, active }: { node: LaidNode; active: boolean }):
56
58
  {node.subtitle}
57
59
  </text>
58
60
  )}
61
+ {小型に呼び名 && (
62
+ <text
63
+ data-cdl-role="node-subtitle"
64
+ x={node.w / 2}
65
+ y={node.h / 2 + 24}
66
+ fontSize={Math.min(subtitleSize, 18)}
67
+ textAnchor="middle"
68
+ fill="var(--cdl-text-dim, #5a6270)"
69
+ >
70
+ {node.subtitle}
71
+ </text>
72
+ )}
59
73
  </g>
60
74
  );
61
75
  }