@cardenelabs/cdl 0.123.0 → 0.125.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 +55 -1
- package/README.md +14 -1
- package/dist/index.cjs +924 -134
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +924 -135
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +909 -134
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +909 -134
- package/dist/react.js.map +1 -1
- package/dist/{render-CVczwfRb.d.cts → render-7yEHIUK1.d.cts} +60 -5
- package/dist/{render-CVczwfRb.d.ts → render-7yEHIUK1.d.ts} +60 -5
- package/package.json +12 -9
- package/src/builder.ts +6 -0
- package/src/index.ts +4 -0
- package/src/kinds/card.tsx +12 -4
- package/src/kinds/generic.tsx +19 -9
- package/src/kinds/station.tsx +105 -19
- package/src/kinds/terminal-mark.tsx +36 -9
- package/src/layout/edges.ts +169 -17
- package/src/layout/lanes.ts +69 -5
- package/src/layout/legend.ts +68 -0
- package/src/layout/metro-path.ts +123 -30
- package/src/layout/nodes.ts +13 -2
- package/src/layout/spec.ts +17 -1
- package/src/layout/tokens.ts +8 -1
- package/src/layout.ts +20 -2
- package/src/render/edge-head.ts +6 -0
- package/src/render/edges.tsx +27 -6
- package/src/render/legend.tsx +120 -0
- package/src/render/nodes.tsx +21 -5
- package/src/render/stage.tsx +255 -10
- package/src/render/template-fields.ts +2 -0
- package/src/types.ts +109 -7
- package/src/validate.ts +5 -0
- package/src/visual-validate.ts +7 -7
package/src/types.ts
CHANGED
|
@@ -30,7 +30,7 @@ export type Tone = (typeof TONES)[number];
|
|
|
30
30
|
export type CdlTextMetrics = "proportional" | "monospace";
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
* cdl SVG に付与される data-cdl-role attribute の SSOT
|
|
33
|
+
* cdl SVG に付与される data-cdl-role attribute の SSOT 型。
|
|
34
34
|
* consumer app (dragon 等) は `[data-cdl-role="<role>"]` selector で CSS を宛てる。 role を追加する時は本 union と該当 render 箇所 (kinds/*.tsx、
|
|
35
35
|
* render/edges.tsx、 render/stage.tsx) を同時に更新する。
|
|
36
36
|
*
|
|
@@ -54,6 +54,21 @@ export type CdlTextMetrics = "proportional" | "monospace";
|
|
|
54
54
|
* - "lane-container" ... lane.contain=true の boundary rect
|
|
55
55
|
* - "lane-lifeline" ... lane.lifeline=true の縦点線 line
|
|
56
56
|
* - "lane-label" ... lane 見出し text
|
|
57
|
+
* - "metro-lane-badge" ... 路線用 lane の担当を示す名札
|
|
58
|
+
* - "metro-lane-guide" ... 路線用 lane の名札から右へ伸びる案内線
|
|
59
|
+
* - "mark-start" ... 路線図の始まりの印
|
|
60
|
+
* - "mark-end" ... 路線図の終わりの印
|
|
61
|
+
* - "legend" ... 図の下へ横一列に置く凡例全体
|
|
62
|
+
* - "legend-item" ... 凡例の 1 項目
|
|
63
|
+
* - "legend-mark" ... 凡例項目の印
|
|
64
|
+
* - "legend-text" ... 凡例項目の文字
|
|
65
|
+
* - "stage-column" ... lane.stage を持つ段階列の面
|
|
66
|
+
* - "stage-number" ... 段階列の見出しに出す番号
|
|
67
|
+
* - "stage-name" ... 段階列の見出しに出す名前
|
|
68
|
+
* - "stage-divider" ... 段階列の見出しと中身を分ける線
|
|
69
|
+
* - "stage-note" ... 段階列にある札か、補助線を持つ札の右側へ置く補足
|
|
70
|
+
* - "timeline-axis" ... lane.timelineAxis=true の縦実線
|
|
71
|
+
* - "timeline-leader" ... node.leaderTo で札から時間軸の番号へ結ぶ矢印なしの補助線
|
|
57
72
|
*/
|
|
58
73
|
export type CdlRole =
|
|
59
74
|
| "node-body"
|
|
@@ -67,7 +82,44 @@ export type CdlRole =
|
|
|
67
82
|
| "edge-label"
|
|
68
83
|
| "lane-container"
|
|
69
84
|
| "lane-lifeline"
|
|
70
|
-
| "lane-label"
|
|
85
|
+
| "lane-label"
|
|
86
|
+
| "metro-lane-badge"
|
|
87
|
+
| "metro-lane-guide"
|
|
88
|
+
| "mark-start"
|
|
89
|
+
| "mark-end"
|
|
90
|
+
| "legend"
|
|
91
|
+
| "legend-item"
|
|
92
|
+
| "legend-mark"
|
|
93
|
+
| "legend-text"
|
|
94
|
+
| "stage-column"
|
|
95
|
+
| "stage-number"
|
|
96
|
+
| "stage-name"
|
|
97
|
+
| "stage-divider"
|
|
98
|
+
| "stage-note"
|
|
99
|
+
| "timeline-axis"
|
|
100
|
+
| "timeline-leader";
|
|
101
|
+
|
|
102
|
+
/** 凡例に描ける印。 配置・描画・検査はこの 1 つの列を出所にする。 */
|
|
103
|
+
export const LEGEND_MARKS = [
|
|
104
|
+
"diamond",
|
|
105
|
+
"filled-circle",
|
|
106
|
+
"double-circle",
|
|
107
|
+
"dotted-line",
|
|
108
|
+
"solid-line",
|
|
109
|
+
"curved-line",
|
|
110
|
+
"rounded-label",
|
|
111
|
+
"numbered-circle",
|
|
112
|
+
"station",
|
|
113
|
+
"arrow",
|
|
114
|
+
] as const;
|
|
115
|
+
|
|
116
|
+
export type LegendMark = (typeof LEGEND_MARKS)[number];
|
|
117
|
+
|
|
118
|
+
/** 図の下へ置く凡例の 1 項目。 */
|
|
119
|
+
export type CdlLegendItem = {
|
|
120
|
+
mark: LegendMark;
|
|
121
|
+
text: string;
|
|
122
|
+
};
|
|
71
123
|
|
|
72
124
|
/** 描画できる箱の種類。 検査・記法一覧・型はこの 1 つの列を出所にする。 */
|
|
73
125
|
export const NODE_KINDS = [
|
|
@@ -191,12 +243,14 @@ export const NODE_KINDS = [
|
|
|
191
243
|
"shape-lawyer",
|
|
192
244
|
"shape-trader",
|
|
193
245
|
"shape-customer-service",
|
|
194
|
-
// 流れの始まりと終わりの印 2 種 (#560) ...
|
|
195
|
-
//
|
|
246
|
+
// 流れの始まりと終わりの印 2 種 (#560) ... 始点と終点は線の端から推測せず、著者が
|
|
247
|
+
// `kind: "mark-start"` / `kind: "mark-end"` の node を明示する。印は文字を描かない
|
|
196
248
|
"mark-start",
|
|
197
249
|
"mark-end",
|
|
198
250
|
// 路線図の駅 (#996) ... 線路上の点を小さな丸で示し、名前と説明は丸の外に置く
|
|
199
251
|
"station",
|
|
252
|
+
// 時間軸の番号 (#1017) ... 実線の軸上に番号を入れた丸を置く。路線図の駅とは別の意味を持つ。
|
|
253
|
+
"timeline-number",
|
|
200
254
|
// 時系列のやり取り (#578) ... 1 つの箱が図を丸ごと描く。 縦が時間で、参加者は箱を持たない
|
|
201
255
|
"sequence-board",
|
|
202
256
|
] as const;
|
|
@@ -222,10 +276,12 @@ export type EdgeStyle = "solid" | "dotted-flow" | "dashed";
|
|
|
222
276
|
* 線の道筋。
|
|
223
277
|
*
|
|
224
278
|
* - `"default"` ... 自動。 箱を避け、角を丸めた直角の線を引く。 書かない時も同じ
|
|
225
|
-
* - `"back-detour"` ...
|
|
279
|
+
* - `"back-detour"` ... 箱の上を回って前の箱へ戻り、途中の箱と交わる時は外側を回る
|
|
226
280
|
* - `"curve"` ... 始点から水平に出て終点へ水平に入る 3 次曲線。 途中の箱は避けず、
|
|
227
281
|
* 2 点が同じ高さなら直線になる。 終点の矢印は水平を向く
|
|
228
|
-
* - `"metro"` ...
|
|
282
|
+
* - `"metro"` ... 通常は横線と傾き ±1 の斜線で結び、角を円弧で丸める。
|
|
283
|
+
* `decision` からの枝は、行き先が同じ横位置なら上下の角から真っ直ぐ、右にあれば右の角から出て曲がる。
|
|
284
|
+
* 左へ戻る `dashed` は行き先側へ横に出して駅の上下へ入る。
|
|
229
285
|
* 途中の箱は避けず、2 点が同じ高さなら横 1 本になる
|
|
230
286
|
*/
|
|
231
287
|
export type EdgeRouting = "default" | "back-detour" | "curve" | "metro";
|
|
@@ -407,7 +463,29 @@ export type CdlLane = {
|
|
|
407
463
|
*/
|
|
408
464
|
width: number;
|
|
409
465
|
label?: string;
|
|
466
|
+
/**
|
|
467
|
+
* 路線図の担当として描く lane。 `label` を名札の名前、`subtitle` をその補足に使う。
|
|
468
|
+
*
|
|
469
|
+
* 書いた lane だけが名札と案内線を出す。書かない lane の出力は変わらない。
|
|
470
|
+
*/
|
|
471
|
+
metro?: {
|
|
472
|
+
subtitle?: string;
|
|
473
|
+
};
|
|
410
474
|
contain?: boolean;
|
|
475
|
+
/**
|
|
476
|
+
* lane を同じ上端・高さの段階列として描く時の見出し。
|
|
477
|
+
*
|
|
478
|
+
* `number` と `name` は別の SVG text に出るため、利用側は `stage-number` と `stage-name` を
|
|
479
|
+
* 個別に選べる。この lane にある `card` node の `subtitle` は、札の右側へ `stage-note` として
|
|
480
|
+
* 描き、通常の card の補足位置には出さない。
|
|
481
|
+
* `leaderTo` を持つ `card` も、段階列の内外にかかわらず同じ `stage-note` を使う。
|
|
482
|
+
*
|
|
483
|
+
* 書かない lane は既存の縦列のままで、`lane-container` / `lane-label` の入力と出力は変わらない。
|
|
484
|
+
*/
|
|
485
|
+
stage?: {
|
|
486
|
+
number: string;
|
|
487
|
+
name: string;
|
|
488
|
+
};
|
|
411
489
|
/**
|
|
412
490
|
* この lane を何のために置いているか (既定 = `"column"`)。
|
|
413
491
|
*
|
|
@@ -427,6 +505,12 @@ export type CdlLane = {
|
|
|
427
505
|
role?: "column" | "overlay";
|
|
428
506
|
/** UML sequence diagram の lifeline (= lane の中央 x に縦の点線を描画) */
|
|
429
507
|
lifeline?: boolean;
|
|
508
|
+
/**
|
|
509
|
+
* lane の中央 x に時間軸の実線を描く。線はこの lane にある描画対象 node の中心間を結ぶ。
|
|
510
|
+
*
|
|
511
|
+
* `lifeline` の点線とは独立しており、両方を書いた lane では両方を描く。
|
|
512
|
+
*/
|
|
513
|
+
timelineAxis?: boolean;
|
|
430
514
|
/**
|
|
431
515
|
* 明示指定した座標。 `posX` と `posY` の **両方**が揃った lane は「置いた位置に置く」
|
|
432
516
|
* 扱いになる。 片方だけでは何も変わらない。
|
|
@@ -453,6 +537,11 @@ export type CdlNode = {
|
|
|
453
537
|
title: string;
|
|
454
538
|
eyebrow?: string;
|
|
455
539
|
subtitle?: string;
|
|
540
|
+
/**
|
|
541
|
+
* この箱から指定した node へ矢印なしの補助線を引く。edge ではないため `laid.edges` には入らない。
|
|
542
|
+
* `card` の `subtitle` は札の右側へ `stage-note` として描き、通常の補足位置には出さない。
|
|
543
|
+
*/
|
|
544
|
+
leaderTo?: string;
|
|
456
545
|
/** mono 数値表示用、 `{stateId}` を含めれば state 値で動的置換 */
|
|
457
546
|
value?: string;
|
|
458
547
|
/** kind=storage 時の行 (各 mono、 state 参照可) */
|
|
@@ -891,7 +980,8 @@ export type CdlEdge = {
|
|
|
891
980
|
/** label の y 方向 fine offset (default 0、 + で下、 - で上) */
|
|
892
981
|
labelOffsetY?: number;
|
|
893
982
|
/**
|
|
894
|
-
* 線の道筋。 `default` は箱を避ける自動経路、 `back-detour`
|
|
983
|
+
* 線の道筋。 `default` は箱を避ける自動経路、 `back-detour` は箱の上を回り、途中の箱と
|
|
984
|
+
* 交わる時は外側を回る戻り線、
|
|
895
985
|
* `curve` は途中の箱を避けず、両端で水平になる 3 次曲線。 `metro` は途中の箱を避けず、
|
|
896
986
|
* 横線と傾き ±1 の斜線を半径 r の円弧で結ぶ。2 点が同じ高さなら横 1 本。書かなければ `default`。
|
|
897
987
|
*/
|
|
@@ -2782,6 +2872,8 @@ export type CdlDiagram = {
|
|
|
2782
2872
|
* 種類を書いていない図にも当たる。
|
|
2783
2873
|
*/
|
|
2784
2874
|
type?: string;
|
|
2875
|
+
/** SVG 内の図の下へ、指定順の横一列で置く凡例。 */
|
|
2876
|
+
legend?: readonly CdlLegendItem[];
|
|
2785
2877
|
/**
|
|
2786
2878
|
* 矢印をいつ出すか (既定 = `"phase"`、 #582)。
|
|
2787
2879
|
*
|
|
@@ -2972,6 +3064,14 @@ export type LaidEdge = CdlEdge & {
|
|
|
2972
3064
|
labelX: number;
|
|
2973
3065
|
labelY: number;
|
|
2974
3066
|
labelAnchor: "start" | "middle" | "end";
|
|
3067
|
+
/** 前の station へ戻る metro 線だけが持つ、専用の点線と矢印を描く目印。 */
|
|
3068
|
+
metroReturn?: true;
|
|
3069
|
+
};
|
|
3070
|
+
|
|
3071
|
+
export type LaidLegendItem = CdlLegendItem & {
|
|
3072
|
+
x: number;
|
|
3073
|
+
/** 文字の baseline。 印はこの値を基準に同じ行へ揃える。 */
|
|
3074
|
+
y: number;
|
|
2975
3075
|
};
|
|
2976
3076
|
|
|
2977
3077
|
/**
|
|
@@ -3007,6 +3107,8 @@ export type LaidDiagram = {
|
|
|
3007
3107
|
textMetrics?: "monospace";
|
|
3008
3108
|
/** どの種類の図か (#645)。 `CdlDiagram.type` をそのまま持ち越す */
|
|
3009
3109
|
type?: string;
|
|
3110
|
+
/** 指定がある図だけが持つ、配置済みの凡例。 */
|
|
3111
|
+
legend?: readonly LaidLegendItem[];
|
|
3010
3112
|
viewBox: { x: number; y: number; w: number; h: number };
|
|
3011
3113
|
/**
|
|
3012
3114
|
* 図全体の倍率 (`CdlViewport.scale` を正規化した値)。
|
package/src/validate.ts
CHANGED
|
@@ -191,6 +191,11 @@ export function validate(diag: CdlDiagram): void {
|
|
|
191
191
|
`[cdl] unknown-ref: node "${n.id}" の lane "${n.lane}" が未定義です${suggest(n.lane, laneIds)}\n → 修正例: .lane("${n.lane}", { x: 0, width: 400 }) を node 宣言前に追加`,
|
|
192
192
|
);
|
|
193
193
|
}
|
|
194
|
+
if (n.leaderTo !== undefined && !nodeIds.has(n.leaderTo)) {
|
|
195
|
+
errors.push(
|
|
196
|
+
`[cdl] unknown-ref: node "${n.id}" の leaderTo "${n.leaderTo}" が node に存在しません${suggest(n.leaderTo, nodeIds, "node")}`,
|
|
197
|
+
);
|
|
198
|
+
}
|
|
194
199
|
}
|
|
195
200
|
for (const e of diag.edges) {
|
|
196
201
|
if (!nodeIds.has(e.from)) {
|
package/src/visual-validate.ts
CHANGED
|
@@ -151,11 +151,10 @@ import {
|
|
|
151
151
|
rendersTitleText,
|
|
152
152
|
fitsOwnTitleWidth,
|
|
153
153
|
skipsNodeTitleWidthCheck,
|
|
154
|
-
drawsTitleOutsideBox,
|
|
155
154
|
titleScalesToFit,
|
|
156
155
|
MIN_TITLE_FONT_SIZE,
|
|
157
156
|
titleFontSize,
|
|
158
|
-
|
|
157
|
+
titleUsableWidth,
|
|
159
158
|
rowBaselineY,
|
|
160
159
|
rowGlyphDepth,
|
|
161
160
|
laneVerticalRange,
|
|
@@ -2007,8 +2006,10 @@ function runAxes(
|
|
|
2007
2006
|
const LIFELINE_W_THRESHOLD = 8;
|
|
2008
2007
|
for (const n of laid.nodes) {
|
|
2009
2008
|
if (n.w < LIFELINE_W_THRESHOLD) continue;
|
|
2010
|
-
//
|
|
2011
|
-
|
|
2009
|
+
// 駅と丸い番号は文字を収める箱ではなく軸上の印なので、箱向けの最小寸法を要求しない。
|
|
2010
|
+
// 丸い番号は見本の半径 24 と縁 4 から大きさが決まり、80×40 を求めると軸より太くなる。
|
|
2011
|
+
// 番号の字が読めるかは軸 3 (text-readability) が引き続き見る。
|
|
2012
|
+
if (n.kind === "station" || n.kind === "timeline-number") continue;
|
|
2012
2013
|
if (n.w < MIN_NODE_W || n.h < MIN_NODE_H) {
|
|
2013
2014
|
push(
|
|
2014
2015
|
"node-visibility",
|
|
@@ -2065,8 +2066,7 @@ function runAxes(
|
|
|
2065
2066
|
//
|
|
2066
2067
|
// 箱の内側の余白 (52) は、題を箱の中に描く種別にだけ足す。 箱の外に描く種別 (`dyn-*` の
|
|
2067
2068
|
// 名前と図表の題) は内側の余白に縛られないので、足すと収まっている題まで挙がる。
|
|
2068
|
-
const
|
|
2069
|
-
const 使える幅 = n.w - 余白;
|
|
2069
|
+
const 使える幅 = titleUsableWidth(n.kind, n.w, n.h);
|
|
2070
2070
|
const 実幅 = measureTextWidth(titleTrimmed, {
|
|
2071
2071
|
fontSize: titleFontSize(n.kind),
|
|
2072
2072
|
bound: "drawn",
|
|
@@ -2089,7 +2089,7 @@ function runAxes(
|
|
|
2089
2089
|
push(
|
|
2090
2090
|
"text-readability",
|
|
2091
2091
|
// 字ごとの実幅は小数になるので、読む人に出す時だけ丸める (判定は丸めない)
|
|
2092
|
-
`node "${n.id}" title "${n.title}" が node 幅 ${n.w}px を超過する可能性 (期待 ${Math.round(実幅 +
|
|
2092
|
+
`node "${n.id}" title "${n.title}" が node 幅 ${n.w}px を超過する可能性 (期待 ${Math.round(実幅 + (n.w - 使える幅))}px)`,
|
|
2093
2093
|
"warn",
|
|
2094
2094
|
);
|
|
2095
2095
|
}
|