@cardenelabs/cdl 0.16.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.
- package/CHANGELOG.md +49 -1
- package/dist/index.cjs +736 -193
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +222 -10
- package/dist/index.d.ts +222 -10
- package/dist/index.js +728 -194
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +458 -60
- 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 +458 -60
- package/dist/react.js.map +1 -1
- package/dist/{render-BS1E6Mlo.d.cts → render-Dc5Pdf7e.d.cts} +175 -4
- package/dist/{render-BS1E6Mlo.d.ts → render-Dc5Pdf7e.d.ts} +175 -4
- package/package.json +1 -1
- package/src/builder.ts +19 -0
- package/src/index.ts +21 -1
- package/src/kinds/card.tsx +15 -1
- package/src/kinds/sequence-board-metrics.ts +118 -0
- package/src/kinds/sequence-board.tsx +289 -0
- package/src/kinds/storage.tsx +137 -11
- package/src/layout/nodes.ts +32 -6
- package/src/layout/spec.ts +14 -1
- package/src/layout/tokens.ts +3 -0
- package/src/presets.ts +563 -183
- package/src/render/edge-head.ts +72 -8
- package/src/render/edges.tsx +30 -9
- package/src/render/nodes.tsx +4 -0
- package/src/render/stage.tsx +40 -29
- package/src/render/template-fields.ts +6 -2
- package/src/types.ts +156 -3
- package/src/visual-validate.ts +29 -2
package/dist/index.cjs
CHANGED
|
@@ -9494,6 +9494,9 @@ function diagram(id, options) {
|
|
|
9494
9494
|
side: opts.side,
|
|
9495
9495
|
style: opts.style,
|
|
9496
9496
|
head: opts.head,
|
|
9497
|
+
headFill: opts.headFill,
|
|
9498
|
+
tailHead: opts.tailHead,
|
|
9499
|
+
tailHeadFill: opts.tailHeadFill,
|
|
9497
9500
|
guard: opts.guard,
|
|
9498
9501
|
cardinality: opts.cardinality,
|
|
9499
9502
|
labelOffsetX: opts.labelOffsetX,
|
|
@@ -9617,6 +9620,9 @@ function diagram(id, options) {
|
|
|
9617
9620
|
side: d.side,
|
|
9618
9621
|
style: d.style,
|
|
9619
9622
|
head: d.head,
|
|
9623
|
+
headFill: d.headFill,
|
|
9624
|
+
tailHead: d.tailHead,
|
|
9625
|
+
tailHeadFill: d.tailHeadFill,
|
|
9620
9626
|
guard: d.guard,
|
|
9621
9627
|
cardinality: d.cardinality,
|
|
9622
9628
|
labelOffsetX: d.labelOffsetX,
|
|
@@ -11718,6 +11724,9 @@ function hasRenderedLabel(e) {
|
|
|
11718
11724
|
return Boolean(e.label?.trim() || e.sub?.trim());
|
|
11719
11725
|
}
|
|
11720
11726
|
var KINDS_WITHOUT_TITLE_TEXT = /* @__PURE__ */ new Set([
|
|
11727
|
+
// 時系列のやり取り (#578)。 図を丸ごと描く種別で、描くのは面々の名前と言づての語。
|
|
11728
|
+
// 箱の `title` は使わない
|
|
11729
|
+
"sequence-board",
|
|
11721
11730
|
// 形だけを描く (DynShapeNode)
|
|
11722
11731
|
"dyn-rect",
|
|
11723
11732
|
"dyn-circle",
|
|
@@ -11806,6 +11815,7 @@ var GLYPH_CAP_RATIO = 0.72;
|
|
|
11806
11815
|
var ROW_FONT_STORAGE = 26;
|
|
11807
11816
|
var ROW_FONT_GENERIC = 21;
|
|
11808
11817
|
var STORAGE_TITLE_BASELINE = 78;
|
|
11818
|
+
var SUBTITLE_ROW_SHIFT = 46;
|
|
11809
11819
|
var STORAGE_ROW_DIVIDER_Y = Math.round(
|
|
11810
11820
|
(STORAGE_TITLE_BASELINE + (ROW_TOP_STORAGE - ROW_FONT_STORAGE * GLYPH_CAP_RATIO)) / 2
|
|
11811
11821
|
);
|
|
@@ -13409,7 +13419,10 @@ var TOKENS = {
|
|
|
13409
13419
|
// 印は箱いっぱいに描く (線が箱の縁で止まるため) ので、この値が丸の直径になる。
|
|
13410
13420
|
// 箱としての最小 (80x40) より大きく、名前を持つ箱 (card 320x150) よりは明らかに小さい
|
|
13411
13421
|
"mark-start": { w: 96, h: 96 },
|
|
13412
|
-
"mark-end": { w: 96, h: 96 }
|
|
13422
|
+
"mark-end": { w: 96, h: 96 },
|
|
13423
|
+
// 時系列のやり取り (#578)。 実寸は中身から決まる (`sequenceBoardMetrics`) ので、
|
|
13424
|
+
// ここは書かなかった時の受け皿
|
|
13425
|
+
"sequence-board": { w: 960, h: 640 }
|
|
13413
13426
|
},
|
|
13414
13427
|
// row gap (stack 間の vertical gap、 lane 内 / 跨ぎ共通)
|
|
13415
13428
|
// edge label が node の上 36 px に配置されるため、 boxH 68 + 36 + 余裕 = 100 必要。
|
|
@@ -15072,8 +15085,12 @@ function requiredRowsWidth(rows, kind) {
|
|
|
15072
15085
|
function autoStorageHeight(n, defaultH) {
|
|
15073
15086
|
if (n.kind !== "storage") return n.h ?? defaultH;
|
|
15074
15087
|
if (n.h != null) return n.h;
|
|
15075
|
-
|
|
15076
|
-
|
|
15088
|
+
const \u5370\u3042\u308A = n.rowMarks !== void 0;
|
|
15089
|
+
const \u547C\u3073\u540D\u306E\u5206 = \u5370\u3042\u308A && n.subtitle ? SUBTITLE_ROW_SHIFT : 0;
|
|
15090
|
+
if (!n.rows || n.rows.length === 0) return 150 + \u547C\u3073\u540D\u306E\u5206;
|
|
15091
|
+
const \u5FC5\u8981 = requiredRowsHeight("storage", n.rows.length) ?? defaultH;
|
|
15092
|
+
if (\u5370\u3042\u308A) return \u5FC5\u8981 + \u547C\u3073\u540D\u306E\u5206;
|
|
15093
|
+
return Math.max(defaultH, \u5FC5\u8981);
|
|
15077
15094
|
}
|
|
15078
15095
|
function autoRowsWidth(n, defaultW) {
|
|
15079
15096
|
if (n.w != null) return n.w;
|
|
@@ -15161,8 +15178,11 @@ function layoutNodes(diag, lanes) {
|
|
|
15161
15178
|
continue;
|
|
15162
15179
|
}
|
|
15163
15180
|
const cx = lane.x + lane.width / 2;
|
|
15164
|
-
const
|
|
15165
|
-
const
|
|
15181
|
+
const \u6BB5\u306E\u82AF = rowCy.get(n.stack);
|
|
15182
|
+
const \u6BB5\u306E\u9AD8\u3055 = rowH.get(n.stack);
|
|
15183
|
+
const \u81EA\u524D\u306E\u9AD8\u3055 = n.rowMarks !== void 0;
|
|
15184
|
+
const h = n.h ?? (\u81EA\u524D\u306E\u9AD8\u3055 ? autoStorageHeight(n, size.h) : \u6BB5\u306E\u9AD8\u3055);
|
|
15185
|
+
const cy = \u81EA\u524D\u306E\u9AD8\u3055 ? \u6BB5\u306E\u82AF - \u6BB5\u306E\u9AD8\u3055 / 2 + h / 2 : \u6BB5\u306E\u82AF;
|
|
15166
15186
|
const w = autoRowsWidth(n, size.w);
|
|
15167
15187
|
out.push({
|
|
15168
15188
|
...n,
|
|
@@ -15491,10 +15511,25 @@ var NODE_KINDS = [
|
|
|
15491
15511
|
// 流れの始まりと終わりの印 2 種 (#560) ... 塗った丸と輪で囲んだ丸。
|
|
15492
15512
|
// 状態遷移図が使う。 印そのものが意味を持つので文字は描かない
|
|
15493
15513
|
"mark-start",
|
|
15494
|
-
"mark-end"
|
|
15514
|
+
"mark-end",
|
|
15515
|
+
// 時系列のやり取り (#578) ... 1 つの箱が図を丸ごと描く。 縦が時間で、参加者は箱を持たない
|
|
15516
|
+
"sequence-board"
|
|
15495
15517
|
];
|
|
15518
|
+
var EDGE_STYLES = ["solid", "dotted-flow", "dashed"];
|
|
15496
15519
|
var EDGE_HEAD_DEFAULT = "triangle";
|
|
15497
|
-
var EDGE_HEADS = [
|
|
15520
|
+
var EDGE_HEADS = [
|
|
15521
|
+
"none",
|
|
15522
|
+
"triangle",
|
|
15523
|
+
"diamond",
|
|
15524
|
+
"open",
|
|
15525
|
+
"crow",
|
|
15526
|
+
"one",
|
|
15527
|
+
"zero-one",
|
|
15528
|
+
"many",
|
|
15529
|
+
"zero-many"
|
|
15530
|
+
];
|
|
15531
|
+
var EDGE_HEAD_FILL_DEFAULT = "solid";
|
|
15532
|
+
var EDGE_HEAD_FILLS = ["solid", "hollow"];
|
|
15498
15533
|
|
|
15499
15534
|
// src/anim/core/easing.ts
|
|
15500
15535
|
function cubicBezier(x1, y1, x2, y2) {
|
|
@@ -15989,7 +16024,7 @@ function pathSubpath(d, progress) {
|
|
|
15989
16024
|
}
|
|
15990
16025
|
|
|
15991
16026
|
// src/render/template-fields.ts
|
|
15992
|
-
var TEXT_FIELDS = ["title", "eyebrow", "subtitle", "value", "wBind", "hBind", "visibleIf"];
|
|
16027
|
+
var TEXT_FIELDS = ["title", "eyebrow", "subtitle", "value", "wBind", "hBind", "visibleIf", "sequenceStep"];
|
|
15993
16028
|
var LIST_FIELDS = ["rows"];
|
|
15994
16029
|
var NUMERIC_FIELDS = ["opacity", "renderOffsetX", "renderOffsetY"];
|
|
15995
16030
|
var SHAPE_TEMPLATE_FIELDS = ["source", "radius", "fillProgress", "angle", "level", "rotation", "fill"];
|
|
@@ -18314,6 +18349,7 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes) {
|
|
|
18314
18349
|
if (!isRenderedNode(n)) continue;
|
|
18315
18350
|
for (const row of n.rows) {
|
|
18316
18351
|
if (DIVIDER_ONLY.test(row)) continue;
|
|
18352
|
+
if (n.rowMarks !== void 0) continue;
|
|
18317
18353
|
if (!ROW_FORMAT.test(row)) {
|
|
18318
18354
|
push("row-format", `node "${n.id}" row "${row}" \u304C "key: value" \u5F62\u5F0F\u3067\u306A\u3044`);
|
|
18319
18355
|
}
|
|
@@ -18645,9 +18681,11 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes) {
|
|
|
18645
18681
|
for (const [stack, group] of byStack) {
|
|
18646
18682
|
if (group.length < 2) continue;
|
|
18647
18683
|
const cy0 = group[0].cy;
|
|
18684
|
+
const top0 = cy0 - (group[0].h ?? 0) / 2;
|
|
18648
18685
|
for (const n of group.slice(1)) {
|
|
18649
18686
|
const diff = Math.abs(n.cy - cy0);
|
|
18650
|
-
|
|
18687
|
+
const topDiff = Math.abs(n.cy - (n.h ?? 0) / 2 - top0);
|
|
18688
|
+
if (diff > MIN_ROW_ALIGNMENT_TOLERANCE && topDiff > MIN_ROW_ALIGNMENT_TOLERANCE) {
|
|
18651
18689
|
push(
|
|
18652
18690
|
"row-alignment",
|
|
18653
18691
|
`stack=${stack} row \u5185 node "${n.id}" cy=${n.cy.toFixed(1)} \u304C row \u57FA\u6E96 cy=${cy0.toFixed(1)} \u3068 ${diff.toFixed(1)} world \u5DEE (\u8A31\u5BB9 ${MIN_ROW_ALIGNMENT_TOLERANCE})`
|
|
@@ -19696,15 +19734,18 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes) {
|
|
|
19696
19734
|
if (group.length < 3) continue;
|
|
19697
19735
|
const sorted = [...group].sort((a, b) => a.cy - b.cy);
|
|
19698
19736
|
const gaps = [];
|
|
19737
|
+
const tops = [];
|
|
19699
19738
|
for (let i = 1; i < sorted.length; i++) {
|
|
19700
19739
|
const prev = sorted[i - 1];
|
|
19701
19740
|
const cur = sorted[i];
|
|
19702
19741
|
gaps.push(cur.cy - cur.h / 2 - (prev.cy + prev.h / 2));
|
|
19742
|
+
tops.push(cur.cy - cur.h / 2 - (prev.cy - prev.h / 2));
|
|
19703
19743
|
}
|
|
19704
19744
|
const maxGap = Math.max(...gaps);
|
|
19705
19745
|
const minGap = Math.min(...gaps);
|
|
19706
19746
|
const variance = maxGap - minGap;
|
|
19707
|
-
|
|
19747
|
+
const topVariance = Math.max(...tops) - Math.min(...tops);
|
|
19748
|
+
if (variance > COLUMN_GAP_VARIANCE_TOL && topVariance > COLUMN_GAP_VARIANCE_TOL) {
|
|
19708
19749
|
push(
|
|
19709
19750
|
"column-gap-uniform",
|
|
19710
19751
|
`lane "${laneId}" \u5185 node \u9593\u306E\u7AEF\u9593 gap variance ${variance.toFixed(1)} world \u304C spec ${COLUMN_GAP_VARIANCE_TOL} \u8D85\u904E (min=${minGap.toFixed(0)} max=${maxGap.toFixed(0)})`
|
|
@@ -21178,14 +21219,42 @@ function StateDiffCard({
|
|
|
21178
21219
|
|
|
21179
21220
|
// src/render/edge-head.ts
|
|
21180
21221
|
var EDGE_HEAD_SHAPE = {
|
|
21181
|
-
|
|
21182
|
-
|
|
21183
|
-
|
|
21184
|
-
|
|
21222
|
+
// 何も描かない端。 marker 自体を出さないので `d` は読まれない
|
|
21223
|
+
none: { d: "", w: 10, h: 10, refX: 0, filled: false },
|
|
21224
|
+
triangle: { d: "M 0 0 L 10 5 L 0 10 z", w: 10, h: 10, refX: 9, filled: true },
|
|
21225
|
+
diamond: { d: "M 0 5 L 5 0 L 10 5 L 5 10 z", w: 10, h: 10, refX: 9, filled: true },
|
|
21226
|
+
open: { d: "M 1 0 L 9 5 L 1 10", w: 10, h: 10, refX: 9, filled: false },
|
|
21227
|
+
crow: { d: "M 10 0 L 0 5 M 10 5 L 0 5 M 10 10 L 0 5", w: 10, h: 10, refX: 10, filled: false },
|
|
21228
|
+
// ER の端。 **箱に近い側 (x が大きい側) が個数、その外側が任意か** (#578)。
|
|
21229
|
+
//
|
|
21230
|
+
// 枠は 24 × 10 で、線の先端に合わせるのは x=24 = 箱の縁。 marker は経路の向きに回るので、
|
|
21231
|
+
// 行き先側でも出どころ側でも「箱に近い側」 が同じ端になる。
|
|
21232
|
+
//
|
|
21233
|
+
// 三又の真ん中の枝は **関係の線そのもの** が兼ねる。 別に引くと同じ所に 2 本重なって太く見える
|
|
21234
|
+
one: { d: "M 16 0 L 16 10 M 4 0 L 4 10", w: 24, h: 10, refX: 24, scale: 1.8, filled: false },
|
|
21235
|
+
"zero-one": { d: "M 16 0 L 16 10 M 7 5 a 3 3 0 1 0 -6 0 a 3 3 0 1 0 6 0", w: 24, h: 10, refX: 24, scale: 1.8, filled: false },
|
|
21236
|
+
many: { d: "M 24 0 L 13 5 L 24 10 M 4 0 L 4 10", w: 24, h: 10, refX: 24, scale: 1.8, filled: false },
|
|
21237
|
+
"zero-many": {
|
|
21238
|
+
d: "M 24 0 L 13 5 L 24 10 M 7 5 a 3 3 0 1 0 -6 0 a 3 3 0 1 0 6 0",
|
|
21239
|
+
w: 24,
|
|
21240
|
+
h: 10,
|
|
21241
|
+
refX: 24,
|
|
21242
|
+
scale: 1.8,
|
|
21243
|
+
filled: false
|
|
21244
|
+
}
|
|
21185
21245
|
};
|
|
21186
|
-
function edgeHeadMarkerId(tone, head, small) {
|
|
21246
|
+
function edgeHeadMarkerId(tone, head, small, fill = EDGE_HEAD_FILL_DEFAULT) {
|
|
21187
21247
|
const \u5C0F = small ? "-sm" : "";
|
|
21188
|
-
|
|
21248
|
+
const \u5857 = fill === EDGE_HEAD_FILL_DEFAULT || !EDGE_HEAD_SHAPE[head].filled ? "" : `-${fill}`;
|
|
21249
|
+
return head === EDGE_HEAD_DEFAULT && \u5857 === "" ? `cdl-arrow-${tone}${\u5C0F}` : `cdl-arrow-${tone}-${head}${\u5857}${\u5C0F}`;
|
|
21250
|
+
}
|
|
21251
|
+
function edgeHeadPaint(head, fill, color) {
|
|
21252
|
+
const \u5F62 = EDGE_HEAD_SHAPE[head];
|
|
21253
|
+
if (!\u5F62.filled) return { fill: "none", stroke: color, strokeWidth: 1.6 };
|
|
21254
|
+
if (fill === "hollow") {
|
|
21255
|
+
return { fill: "var(--cdl-node-fill, #ffffff)", stroke: color, strokeWidth: 1.4 };
|
|
21256
|
+
}
|
|
21257
|
+
return { fill: color, stroke: "none" };
|
|
21189
21258
|
}
|
|
21190
21259
|
function opacityAttr(opacity) {
|
|
21191
21260
|
return opacity < 1 ? opacity : void 0;
|
|
@@ -21200,7 +21269,13 @@ function CdlEdgeView({
|
|
|
21200
21269
|
stateValues
|
|
21201
21270
|
}) {
|
|
21202
21271
|
const color = toneColor(edge.tone);
|
|
21203
|
-
const
|
|
21272
|
+
const \u7AEF\u306E\u540D\u524D = (h, f) => {
|
|
21273
|
+
const \u5F62 = h ?? EDGE_HEAD_DEFAULT;
|
|
21274
|
+
if (\u5F62 === "none") return void 0;
|
|
21275
|
+
return hasTone(edge.tone) ? edgeHeadMarkerId(edge.tone, \u5F62, !active, f ?? EDGE_HEAD_FILL_DEFAULT) : "cdl-arrow-muted";
|
|
21276
|
+
};
|
|
21277
|
+
const marker = \u7AEF\u306E\u540D\u524D(edge.head, edge.headFill);
|
|
21278
|
+
const tailMarker = edge.tailHead === void 0 ? void 0 : \u7AEF\u306E\u540D\u524D(edge.tailHead, edge.tailHeadFill);
|
|
21204
21279
|
const style = edge.style ?? "solid";
|
|
21205
21280
|
const isDotted = style === "dotted-flow";
|
|
21206
21281
|
const isPassThrough = isDotted && Boolean(edge.dThrough);
|
|
@@ -21248,6 +21323,8 @@ function CdlEdgeView({
|
|
|
21248
21323
|
progress,
|
|
21249
21324
|
color,
|
|
21250
21325
|
marker,
|
|
21326
|
+
tailMarker,
|
|
21327
|
+
dashed: style === "dashed",
|
|
21251
21328
|
stateValues
|
|
21252
21329
|
}
|
|
21253
21330
|
),
|
|
@@ -21273,6 +21350,8 @@ function SolidEdgePath({
|
|
|
21273
21350
|
progress,
|
|
21274
21351
|
color,
|
|
21275
21352
|
marker,
|
|
21353
|
+
tailMarker,
|
|
21354
|
+
dashed,
|
|
21276
21355
|
stateValues
|
|
21277
21356
|
}) {
|
|
21278
21357
|
const visibleD = active ? pathSubpath(edge.d, progress) : edge.d;
|
|
@@ -21280,7 +21359,7 @@ function SolidEdgePath({
|
|
|
21280
21359
|
const boundWidth = edge.widthBind && stateValues ? resolveNumericAttr(edge.widthBind, stateValues, defaultWidth) : defaultWidth;
|
|
21281
21360
|
const boundStroke = edge.strokeBind && stateValues ? interpolate(edge.strokeBind, stateValues) : color;
|
|
21282
21361
|
const boundDashOffset = edge.dashOffsetBind && stateValues ? resolveNumericAttr(edge.dashOffsetBind, stateValues, 0) : void 0;
|
|
21283
|
-
const dashArray = active ? boundDashOffset !== void 0 ? "8 6" : void 0 : "4 5";
|
|
21362
|
+
const dashArray = dashed ? "10 8" : active ? boundDashOffset !== void 0 ? "8 6" : void 0 : "4 5";
|
|
21284
21363
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21285
21364
|
"path",
|
|
21286
21365
|
{
|
|
@@ -21293,7 +21372,8 @@ function SolidEdgePath({
|
|
|
21293
21372
|
strokeDasharray: dashArray,
|
|
21294
21373
|
strokeDashoffset: boundDashOffset,
|
|
21295
21374
|
strokeLinecap: "round",
|
|
21296
|
-
markerEnd: `url(#${marker})`,
|
|
21375
|
+
markerEnd: marker === void 0 ? void 0 : `url(#${marker})`,
|
|
21376
|
+
markerStart: tailMarker === void 0 ? void 0 : `url(#${tailMarker})`,
|
|
21297
21377
|
style: {
|
|
21298
21378
|
transition: "stroke 280ms ease, stroke-opacity 280ms ease, stroke-width 280ms ease"
|
|
21299
21379
|
}
|
|
@@ -21505,7 +21585,8 @@ function CardNode({ node, active }) {
|
|
|
21505
21585
|
return /* @__PURE__ */ jsxRuntime.jsx("g", { transform: `translate(${x} ${y})` });
|
|
21506
21586
|
}
|
|
21507
21587
|
const compact = isCompactBox(node.h);
|
|
21508
|
-
const
|
|
21588
|
+
const \u5C0F\u578B\u306B\u547C\u3073\u540D = compact && Boolean(node.subtitle);
|
|
21589
|
+
const titleY = compact ? \u5C0F\u578B\u306B\u547C\u3073\u540D ? node.h / 2 - 2 : node.h / 2 + 8 : 86;
|
|
21509
21590
|
const titleX = compact ? node.w / 2 : 26;
|
|
21510
21591
|
const paddingX = compact ? 16 : 52;
|
|
21511
21592
|
const availableW = node.w - paddingX;
|
|
@@ -21542,9 +21623,262 @@ function CardNode({ node, active }) {
|
|
|
21542
21623
|
children: node.title
|
|
21543
21624
|
}
|
|
21544
21625
|
),
|
|
21545
|
-
!compact && node.subtitle && /* @__PURE__ */ jsxRuntime.jsx("text", { x: 26, y: 124, fontSize: subtitleSize, fill: "var(--cdl-text-dim, #5a6270)", children: node.subtitle })
|
|
21626
|
+
!compact && node.subtitle && /* @__PURE__ */ jsxRuntime.jsx("text", { x: 26, y: 124, fontSize: subtitleSize, fill: "var(--cdl-text-dim, #5a6270)", children: node.subtitle }),
|
|
21627
|
+
\u5C0F\u578B\u306B\u547C\u3073\u540D && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21628
|
+
"text",
|
|
21629
|
+
{
|
|
21630
|
+
"data-cdl-role": "node-subtitle",
|
|
21631
|
+
x: node.w / 2,
|
|
21632
|
+
y: node.h / 2 + 24,
|
|
21633
|
+
fontSize: Math.min(subtitleSize, 18),
|
|
21634
|
+
textAnchor: "middle",
|
|
21635
|
+
fill: "var(--cdl-text-dim, #5a6270)",
|
|
21636
|
+
children: node.subtitle
|
|
21637
|
+
}
|
|
21638
|
+
)
|
|
21639
|
+
] });
|
|
21640
|
+
}
|
|
21641
|
+
|
|
21642
|
+
// src/kinds/sequence-board-metrics.ts
|
|
21643
|
+
var SEQ_EDGE = 16;
|
|
21644
|
+
var SEQ_ROW = 64;
|
|
21645
|
+
var SEQ_GUTTER_PAD = 40;
|
|
21646
|
+
var SEQ_GUTTER_GAP = 40;
|
|
21647
|
+
var SEQ_HEAD = 96;
|
|
21648
|
+
var SEQ_ROW_PAD = 56;
|
|
21649
|
+
var SEQ_COL_PAD = 80;
|
|
21650
|
+
var SEQ_BAND_W = 52;
|
|
21651
|
+
var SEQ_BAND_PAD = 24;
|
|
21652
|
+
var SEQ_NAME = 24;
|
|
21653
|
+
var SEQ_SUB = 20;
|
|
21654
|
+
var SEQ_LABEL = 26;
|
|
21655
|
+
var SEQ_DOT = 7;
|
|
21656
|
+
var SEQ_SELF_W = 52;
|
|
21657
|
+
var SEQ_COL_MIN = 200;
|
|
21658
|
+
var g4 = (v) => Math.round(v / 4) * 4;
|
|
21659
|
+
function sequenceStepId() {
|
|
21660
|
+
return "seq_step";
|
|
21661
|
+
}
|
|
21662
|
+
function sequenceBoardMetrics(data) {
|
|
21663
|
+
const \u540D\u5E45 = data.actors.map(
|
|
21664
|
+
(a) => Math.max(textWidth(a.name, SEQ_NAME), a.subtitle ? textWidth(a.subtitle, SEQ_SUB) : 0)
|
|
21665
|
+
);
|
|
21666
|
+
const colW = g4(Math.max(SEQ_COL_MIN, Math.max(0, ...\u540D\u5E45) + SEQ_COL_PAD));
|
|
21667
|
+
const \u8A9E\u5E45 = Math.max(0, ...data.messages.map((m) => textWidth(m.label, SEQ_LABEL)));
|
|
21668
|
+
const gutter = g4(SEQ_EDGE + SEQ_GUTTER_PAD + \u8A9E\u5E45 + SEQ_GUTTER_GAP);
|
|
21669
|
+
const headY = SEQ_EDGE + SEQ_HEAD;
|
|
21670
|
+
const rowY = (i) => headY + SEQ_ROW_PAD + i * SEQ_ROW;
|
|
21671
|
+
const \u6700\u7D42 = data.messages.length > 0 ? rowY(data.messages.length - 1) : headY;
|
|
21672
|
+
const bottom = \u6700\u7D42 + SEQ_ROW_PAD;
|
|
21673
|
+
const cx = (i) => gutter + colW / 2 + i * colW;
|
|
21674
|
+
const w = g4(cx(Math.max(0, data.actors.length - 1)) + colW / 2 + SEQ_EDGE);
|
|
21675
|
+
const h = g4(bottom + SEQ_EDGE);
|
|
21676
|
+
return { w, h, gutter, colW, headY, cx, rowY, bottom };
|
|
21677
|
+
}
|
|
21678
|
+
function SequenceBoardNode({
|
|
21679
|
+
node,
|
|
21680
|
+
stateValues
|
|
21681
|
+
}) {
|
|
21682
|
+
const data = node.sequenceData;
|
|
21683
|
+
if (!data) return /* @__PURE__ */ jsxRuntime.jsx("g", { "data-cdl-role": "sequence-board" });
|
|
21684
|
+
const m = sequenceBoardMetrics(data);
|
|
21685
|
+
const x = node.cx - node.w / 2;
|
|
21686
|
+
const y = node.cy - node.h / 2;
|
|
21687
|
+
const \u73FE\u5728 = (() => {
|
|
21688
|
+
if (!node.sequenceStep) return null;
|
|
21689
|
+
const v = Number.parseInt(interpolate(node.sequenceStep, stateValues ?? {}).trim(), 10);
|
|
21690
|
+
return Number.isFinite(v) ? v : null;
|
|
21691
|
+
})();
|
|
21692
|
+
const \u6731 = "var(--cdl-tone-accent, #2d6a8f)";
|
|
21693
|
+
const \u58A8 = "var(--cdl-text-2, #4a5162)";
|
|
21694
|
+
const \u898B\u305F\u76EE = (i) => {
|
|
21695
|
+
if (\u73FE\u5728 === null) return { opacity: 1, color: \u6731 };
|
|
21696
|
+
if (i > \u73FE\u5728) return { opacity: 0, color: \u6731 };
|
|
21697
|
+
return i === \u73FE\u5728 ? { opacity: 1, color: \u6731 } : { opacity: 1, color: \u58A8 };
|
|
21698
|
+
};
|
|
21699
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("g", { "data-cdl-role": "sequence-board", transform: `translate(${x} ${y})`, children: [
|
|
21700
|
+
data.bands.map((b, i) => {
|
|
21701
|
+
if (\u73FE\u5728 !== null && b.from > \u73FE\u5728) return null;
|
|
21702
|
+
const \u4E0B = \u73FE\u5728 === null ? b.to : Math.min(b.to, \u73FE\u5728);
|
|
21703
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21704
|
+
"rect",
|
|
21705
|
+
{
|
|
21706
|
+
"data-cdl-role": "sequence-band",
|
|
21707
|
+
x: m.cx(b.actor) - SEQ_BAND_W / 2,
|
|
21708
|
+
y: m.rowY(b.from) - SEQ_BAND_PAD / 2,
|
|
21709
|
+
width: SEQ_BAND_W,
|
|
21710
|
+
height: m.rowY(\u4E0B) - m.rowY(b.from) + SEQ_BAND_PAD,
|
|
21711
|
+
rx: 4,
|
|
21712
|
+
fill: \u6731,
|
|
21713
|
+
fillOpacity: 0.12
|
|
21714
|
+
},
|
|
21715
|
+
`band-${i}`
|
|
21716
|
+
);
|
|
21717
|
+
}),
|
|
21718
|
+
data.actors.map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
21719
|
+
"line",
|
|
21720
|
+
{
|
|
21721
|
+
"data-cdl-role": "sequence-thread",
|
|
21722
|
+
x1: m.cx(i),
|
|
21723
|
+
y1: m.headY,
|
|
21724
|
+
x2: m.cx(i),
|
|
21725
|
+
y2: m.bottom,
|
|
21726
|
+
stroke: "var(--cdl-divider, #d4d4d8)",
|
|
21727
|
+
strokeWidth: 3
|
|
21728
|
+
},
|
|
21729
|
+
`thread-${i}`
|
|
21730
|
+
)),
|
|
21731
|
+
data.actors.map((a, i) => /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
|
|
21732
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21733
|
+
"text",
|
|
21734
|
+
{
|
|
21735
|
+
"data-cdl-role": "sequence-actor",
|
|
21736
|
+
x: m.cx(i),
|
|
21737
|
+
y: SEQ_EDGE + 44,
|
|
21738
|
+
fontSize: SEQ_NAME,
|
|
21739
|
+
fontWeight: 700,
|
|
21740
|
+
textAnchor: "middle",
|
|
21741
|
+
fill: "var(--cdl-text, #1a1f2a)",
|
|
21742
|
+
style: { fontFamily: "'JetBrains Mono', monospace" },
|
|
21743
|
+
children: a.name
|
|
21744
|
+
}
|
|
21745
|
+
),
|
|
21746
|
+
a.subtitle && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21747
|
+
"text",
|
|
21748
|
+
{
|
|
21749
|
+
"data-cdl-role": "sequence-actor-subtitle",
|
|
21750
|
+
x: m.cx(i),
|
|
21751
|
+
y: SEQ_EDGE + 76,
|
|
21752
|
+
fontSize: SEQ_SUB,
|
|
21753
|
+
textAnchor: "middle",
|
|
21754
|
+
fill: "var(--cdl-text-dim, #5a6270)",
|
|
21755
|
+
children: a.subtitle
|
|
21756
|
+
}
|
|
21757
|
+
)
|
|
21758
|
+
] }, `head-${i}`)),
|
|
21759
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21760
|
+
"line",
|
|
21761
|
+
{
|
|
21762
|
+
"data-cdl-role": "sequence-rule",
|
|
21763
|
+
x1: SEQ_EDGE,
|
|
21764
|
+
y1: m.headY,
|
|
21765
|
+
x2: m.w - SEQ_EDGE,
|
|
21766
|
+
y2: m.headY,
|
|
21767
|
+
stroke: "var(--cdl-divider, #d4d4d8)",
|
|
21768
|
+
strokeWidth: 2
|
|
21769
|
+
}
|
|
21770
|
+
),
|
|
21771
|
+
data.messages.map((msg, i) => /* @__PURE__ */ jsxRuntime.jsx(SequenceRow, { msg, yy: m.rowY(i), cx: m.cx, ...\u898B\u305F\u76EE(i) }, `msg-${i}`))
|
|
21772
|
+
] });
|
|
21773
|
+
}
|
|
21774
|
+
function SequenceRow({
|
|
21775
|
+
msg,
|
|
21776
|
+
yy,
|
|
21777
|
+
cx,
|
|
21778
|
+
opacity,
|
|
21779
|
+
color
|
|
21780
|
+
}) {
|
|
21781
|
+
const \u7834 = msg.kind === "return";
|
|
21782
|
+
const \u5857\u308B = msg.kind === "call";
|
|
21783
|
+
const \u51FA = cx(msg.from);
|
|
21784
|
+
const \u81EA\u5206\u3078 = msg.from === msg.to;
|
|
21785
|
+
const dir = \u81EA\u5206\u3078 ? 1 : Math.sign(cx(msg.to) - \u51FA);
|
|
21786
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("g", { "data-cdl-role": "sequence-message", "data-cdl-message-kind": msg.kind, opacity, children: [
|
|
21787
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21788
|
+
"text",
|
|
21789
|
+
{
|
|
21790
|
+
"data-cdl-role": "sequence-label",
|
|
21791
|
+
x: SEQ_EDGE + SEQ_GUTTER_PAD,
|
|
21792
|
+
y: yy + 8,
|
|
21793
|
+
fontSize: SEQ_LABEL,
|
|
21794
|
+
fontWeight: 500,
|
|
21795
|
+
fill: "var(--cdl-text, #1a1f2a)",
|
|
21796
|
+
children: msg.label
|
|
21797
|
+
}
|
|
21798
|
+
),
|
|
21799
|
+
\u81EA\u5206\u3078 ? (
|
|
21800
|
+
// 自分宛て。 相手がいないので糸の右へ小さく回して戻る
|
|
21801
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21802
|
+
"path",
|
|
21803
|
+
{
|
|
21804
|
+
"data-cdl-role": "sequence-line",
|
|
21805
|
+
d: `M ${\u51FA + 10} ${yy - 16} H ${\u51FA + SEQ_SELF_W - 16} Q ${\u51FA + SEQ_SELF_W} ${yy - 16} ${\u51FA + SEQ_SELF_W} ${yy} Q ${\u51FA + SEQ_SELF_W} ${yy + 16} ${\u51FA + SEQ_SELF_W - 16} ${yy + 16} H ${\u51FA + 22}`,
|
|
21806
|
+
fill: "none",
|
|
21807
|
+
stroke: color,
|
|
21808
|
+
strokeWidth: 2.5,
|
|
21809
|
+
strokeLinecap: "round"
|
|
21810
|
+
}
|
|
21811
|
+
)
|
|
21812
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
21813
|
+
"path",
|
|
21814
|
+
{
|
|
21815
|
+
"data-cdl-role": "sequence-line",
|
|
21816
|
+
d: `M ${\u51FA + dir * 12} ${yy} H ${cx(msg.to) - dir * 14}`,
|
|
21817
|
+
fill: "none",
|
|
21818
|
+
stroke: color,
|
|
21819
|
+
strokeWidth: 2.5,
|
|
21820
|
+
strokeLinecap: "round",
|
|
21821
|
+
strokeDasharray: \u7834 ? "10 8" : void 0
|
|
21822
|
+
}
|
|
21823
|
+
),
|
|
21824
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21825
|
+
Arrow,
|
|
21826
|
+
{
|
|
21827
|
+
x: \u81EA\u5206\u3078 ? \u51FA + 14 : cx(msg.to),
|
|
21828
|
+
y: \u81EA\u5206\u3078 ? yy + 16 : yy,
|
|
21829
|
+
dir: \u81EA\u5206\u3078 ? -1 : dir,
|
|
21830
|
+
filled: \u5857\u308B,
|
|
21831
|
+
color
|
|
21832
|
+
}
|
|
21833
|
+
),
|
|
21834
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21835
|
+
"circle",
|
|
21836
|
+
{
|
|
21837
|
+
"data-cdl-role": "sequence-source",
|
|
21838
|
+
cx: \u51FA,
|
|
21839
|
+
cy: \u81EA\u5206\u3078 ? yy - 16 : yy,
|
|
21840
|
+
r: SEQ_DOT,
|
|
21841
|
+
fill: color
|
|
21842
|
+
}
|
|
21843
|
+
)
|
|
21546
21844
|
] });
|
|
21547
21845
|
}
|
|
21846
|
+
function Arrow({
|
|
21847
|
+
x,
|
|
21848
|
+
y,
|
|
21849
|
+
dir,
|
|
21850
|
+
filled,
|
|
21851
|
+
color
|
|
21852
|
+
}) {
|
|
21853
|
+
const \u4E08 = 18;
|
|
21854
|
+
const \u534A = 8.5;
|
|
21855
|
+
const \u5148 = x;
|
|
21856
|
+
const \u80F4 = x - dir * \u4E08;
|
|
21857
|
+
return filled ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
21858
|
+
"path",
|
|
21859
|
+
{
|
|
21860
|
+
"data-cdl-role": "sequence-head",
|
|
21861
|
+
"data-cdl-head-fill": "solid",
|
|
21862
|
+
d: `M ${\u5148} ${y} L ${\u80F4} ${y - \u534A} L ${\u80F4} ${y + \u534A} Z`,
|
|
21863
|
+
fill: color,
|
|
21864
|
+
stroke: color,
|
|
21865
|
+
strokeWidth: 3,
|
|
21866
|
+
strokeLinejoin: "round"
|
|
21867
|
+
}
|
|
21868
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
21869
|
+
"path",
|
|
21870
|
+
{
|
|
21871
|
+
"data-cdl-role": "sequence-head",
|
|
21872
|
+
"data-cdl-head-fill": "open",
|
|
21873
|
+
d: `M ${\u80F4} ${y - \u534A} L ${\u5148} ${y} L ${\u80F4} ${y + \u534A}`,
|
|
21874
|
+
fill: "none",
|
|
21875
|
+
stroke: color,
|
|
21876
|
+
strokeWidth: 2.5,
|
|
21877
|
+
strokeLinecap: "round",
|
|
21878
|
+
strokeLinejoin: "round"
|
|
21879
|
+
}
|
|
21880
|
+
);
|
|
21881
|
+
}
|
|
21548
21882
|
function EventNode({
|
|
21549
21883
|
node,
|
|
21550
21884
|
active,
|
|
@@ -21646,6 +21980,29 @@ function FunctionNode({ node, active }) {
|
|
|
21646
21980
|
node.subtitle && /* @__PURE__ */ jsxRuntime.jsx("text", { x: 26, y: 126, fontSize: 20, fill: "var(--cdl-text-dim, #5a6270)", children: node.subtitle })
|
|
21647
21981
|
] });
|
|
21648
21982
|
}
|
|
21983
|
+
var ROW_GLYPH_HALF = 7;
|
|
21984
|
+
var ROW_GLYPH_CX = ROW_PAD_X_PX + ROW_GLYPH_HALF + 1;
|
|
21985
|
+
var ROW_GLYPH_LEAD = 40;
|
|
21986
|
+
var ROW_TYPE_FONT = 24;
|
|
21987
|
+
var SUBTITLE_BASELINE = 108;
|
|
21988
|
+
var SUBTITLE_FONT = 22;
|
|
21989
|
+
var UNDERLINE_DROP = 7;
|
|
21990
|
+
function RowGlyph({ mark, x, y, color }) {
|
|
21991
|
+
const \u534A = ROW_GLYPH_HALF;
|
|
21992
|
+
const d = mark.shape === "square" ? `M ${x - \u534A} ${y - \u534A} H ${x + \u534A} V ${y + \u534A} H ${x - \u534A} Z` : `M ${x - \u534A} ${y - \u534A} L ${x + \u534A} ${y} L ${x - \u534A} ${y + \u534A} Z`;
|
|
21993
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21994
|
+
"path",
|
|
21995
|
+
{
|
|
21996
|
+
"data-cdl-role": "node-row-glyph",
|
|
21997
|
+
"data-cdl-row-glyph": `${mark.shape}-${mark.filled ? "filled" : "hollow"}`,
|
|
21998
|
+
d,
|
|
21999
|
+
fill: mark.filled ? color : "var(--cdl-node-fill, #ffffff)",
|
|
22000
|
+
stroke: color,
|
|
22001
|
+
strokeWidth: mark.filled ? 0 : 2.4,
|
|
22002
|
+
strokeLinejoin: "round"
|
|
22003
|
+
}
|
|
22004
|
+
);
|
|
22005
|
+
}
|
|
21649
22006
|
function StorageNode({
|
|
21650
22007
|
node,
|
|
21651
22008
|
active,
|
|
@@ -21663,6 +22020,8 @@ function StorageNode({
|
|
|
21663
22020
|
const leftEndDrawn = ROW_PAD_X_PX + leftMaxWidth * STORAGE_CHAR_ADVANCE_PX;
|
|
21664
22021
|
const columnDividerX = (leftEndDrawn + rightColX) / 2;
|
|
21665
22022
|
const columnDividerFits = columnDividerX <= node.w - ROW_PAD_X_PX;
|
|
22023
|
+
const \u5370\u3067\u5206\u3051\u308B = node.rowMarks !== void 0;
|
|
22024
|
+
const \u884C\u306E\u4E0B\u3052 = \u5370\u3067\u5206\u3051\u308B && node.subtitle ? SUBTITLE_ROW_SHIFT : 0;
|
|
21666
22025
|
const lastRowBottom = Math.min(
|
|
21667
22026
|
ROW_TOP_STORAGE + (rows.length - 1) * ROW_PITCH_STORAGE + (rowGlyphDepth("storage") ?? 0),
|
|
21668
22027
|
node.h - ROW_PAD_X_PX
|
|
@@ -21683,6 +22042,19 @@ function StorageNode({
|
|
|
21683
22042
|
}
|
|
21684
22043
|
),
|
|
21685
22044
|
node.eyebrow && /* @__PURE__ */ jsxRuntime.jsx("text", { x: 26, y: 38, fontSize: 18, fontWeight: 700, letterSpacing: 2, fill: accent, children: node.eyebrow }),
|
|
22045
|
+
\u5370\u3067\u5206\u3051\u308B && node.subtitle && // 呼び名は **印で分ける箱でだけ** 出す (#578)。 従来の箱は題の下に区切り線が来るので
|
|
22046
|
+
// 置き場が無い
|
|
22047
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
22048
|
+
"text",
|
|
22049
|
+
{
|
|
22050
|
+
"data-cdl-role": "node-subtitle",
|
|
22051
|
+
x: ROW_PAD_X_PX,
|
|
22052
|
+
y: SUBTITLE_BASELINE,
|
|
22053
|
+
fontSize: SUBTITLE_FONT,
|
|
22054
|
+
fill: "var(--cdl-text-dim, #5a6270)",
|
|
22055
|
+
children: node.subtitle
|
|
22056
|
+
}
|
|
22057
|
+
),
|
|
21686
22058
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21687
22059
|
"text",
|
|
21688
22060
|
{
|
|
@@ -21697,7 +22069,7 @@ function StorageNode({
|
|
|
21697
22069
|
children: node.title
|
|
21698
22070
|
}
|
|
21699
22071
|
),
|
|
21700
|
-
rows.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
22072
|
+
rows.length > 0 && !\u5370\u3067\u5206\u3051\u308B && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21701
22073
|
"line",
|
|
21702
22074
|
{
|
|
21703
22075
|
"data-cdl-role": "node-row-divider",
|
|
@@ -21709,7 +22081,7 @@ function StorageNode({
|
|
|
21709
22081
|
strokeWidth: 1.25
|
|
21710
22082
|
}
|
|
21711
22083
|
),
|
|
21712
|
-
rows.length > 0 && hasRightColumn && columnDividerFits && /* @__PURE__ */ jsxRuntime.jsx(
|
|
22084
|
+
rows.length > 0 && hasRightColumn && columnDividerFits && !\u5370\u3067\u5206\u3051\u308B && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21713
22085
|
"line",
|
|
21714
22086
|
{
|
|
21715
22087
|
"data-cdl-role": "node-column-divider",
|
|
@@ -21722,15 +22094,37 @@ function StorageNode({
|
|
|
21722
22094
|
}
|
|
21723
22095
|
),
|
|
21724
22096
|
splits.map((s, idx) => {
|
|
21725
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("g", { transform: `translate(0 ${rowBaselineY("storage", idx)})`, children: [
|
|
22097
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("g", { transform: `translate(0 ${(rowBaselineY("storage", idx) ?? 0) + \u884C\u306E\u4E0B\u3052})`, children: [
|
|
22098
|
+
\u5370\u3067\u5206\u3051\u308B && node.rowMarks?.[idx] != null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
22099
|
+
RowGlyph,
|
|
22100
|
+
{
|
|
22101
|
+
mark: node.rowMarks[idx],
|
|
22102
|
+
x: ROW_GLYPH_CX,
|
|
22103
|
+
y: -8,
|
|
22104
|
+
color: "var(--cdl-text, #1a1f2a)"
|
|
22105
|
+
}
|
|
22106
|
+
),
|
|
22107
|
+
\u5370\u3067\u5206\u3051\u308B && node.rowMarks?.[idx]?.underline === true && // 主キーの下線 (#578)。 印の 2 軸とは別の段に載るので、外部キーの山形と重ねられる
|
|
22108
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
22109
|
+
"line",
|
|
22110
|
+
{
|
|
22111
|
+
"data-cdl-role": "node-row-underline",
|
|
22112
|
+
x1: ROW_PAD_X_PX + ROW_GLYPH_LEAD,
|
|
22113
|
+
y1: UNDERLINE_DROP,
|
|
22114
|
+
x2: ROW_PAD_X_PX + ROW_GLYPH_LEAD + displayWidth(s.left) * STORAGE_CHAR_ADVANCE_PX,
|
|
22115
|
+
y2: UNDERLINE_DROP,
|
|
22116
|
+
stroke: "var(--cdl-text, #1a1f2a)",
|
|
22117
|
+
strokeWidth: 2
|
|
22118
|
+
}
|
|
22119
|
+
),
|
|
21726
22120
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21727
22121
|
"text",
|
|
21728
22122
|
{
|
|
21729
22123
|
"data-cdl-role": "node-row",
|
|
21730
22124
|
"data-cdl-row-index": idx,
|
|
21731
|
-
x: ROW_PAD_X_PX,
|
|
22125
|
+
x: \u5370\u3067\u5206\u3051\u308B ? ROW_PAD_X_PX + ROW_GLYPH_LEAD : ROW_PAD_X_PX,
|
|
21732
22126
|
fontSize: 26,
|
|
21733
|
-
fontWeight: 600,
|
|
22127
|
+
fontWeight: \u5370\u3067\u5206\u3051\u308B ? 500 : 600,
|
|
21734
22128
|
fill: "var(--cdl-text, #1a1f2a)",
|
|
21735
22129
|
style: { fontFamily: "'JetBrains Mono', monospace" },
|
|
21736
22130
|
children: s.left
|
|
@@ -21741,11 +22135,11 @@ function StorageNode({
|
|
|
21741
22135
|
{
|
|
21742
22136
|
"data-cdl-role": "node-row",
|
|
21743
22137
|
"data-cdl-row-index": idx,
|
|
21744
|
-
x: rightColX,
|
|
21745
|
-
fontSize: 26,
|
|
21746
|
-
fontWeight: highlightRows ? 700 : 600,
|
|
21747
|
-
textAnchor: "start",
|
|
21748
|
-
fill: highlightRows ? accent : "var(--cdl-text, #1a1f2a)",
|
|
22138
|
+
x: \u5370\u3067\u5206\u3051\u308B ? node.w - ROW_PAD_X_PX : rightColX,
|
|
22139
|
+
fontSize: \u5370\u3067\u5206\u3051\u308B ? ROW_TYPE_FONT : 26,
|
|
22140
|
+
fontWeight: \u5370\u3067\u5206\u3051\u308B ? 500 : highlightRows ? 700 : 600,
|
|
22141
|
+
textAnchor: \u5370\u3067\u5206\u3051\u308B ? "end" : "start",
|
|
22142
|
+
fill: \u5370\u3067\u5206\u3051\u308B ? "var(--cdl-text-dim, #5a6270)" : highlightRows ? accent : "var(--cdl-text, #1a1f2a)",
|
|
21749
22143
|
style: { fontFamily: "'JetBrains Mono', monospace" },
|
|
21750
22144
|
children: s.right
|
|
21751
22145
|
}
|
|
@@ -28101,6 +28495,9 @@ function CdlNodeView({
|
|
|
28101
28495
|
return /* @__PURE__ */ jsxRuntime.jsx(EventNode, { node: resolvedNode, active, progress });
|
|
28102
28496
|
case "card":
|
|
28103
28497
|
return /* @__PURE__ */ jsxRuntime.jsx(CardNode, { node: resolvedNode, active });
|
|
28498
|
+
// 時系列のやり取り (#578)。 1 つの箱が図を丸ごと描く = 縦が時間で、参加者は箱を持たない
|
|
28499
|
+
case "sequence-board":
|
|
28500
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SequenceBoardNode, { node: resolvedNode, stateValues });
|
|
28104
28501
|
// 図表 9 種は payload が `{signal}` を取れるので stateValues を渡す
|
|
28105
28502
|
// (`render/payload-binding.ts` が描画直前に解決する)。 取れる欄は種別で違い、
|
|
28106
28503
|
// 数と語を取る 7 種に対し、mind-map / tree-hierarchy は **名前だけ** を取る (#467)。
|
|
@@ -28428,36 +28825,47 @@ function CdlStage({
|
|
|
28428
28825
|
/* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
|
|
28429
28826
|
Object.entries(TONE).flatMap(
|
|
28430
28827
|
([tone, color]) => [["", 14], ["-sm", 10]].flatMap(
|
|
28431
|
-
([suffix, size]) => EDGE_HEADS.
|
|
28432
|
-
|
|
28433
|
-
|
|
28434
|
-
|
|
28435
|
-
{
|
|
28436
|
-
|
|
28437
|
-
|
|
28438
|
-
|
|
28439
|
-
|
|
28440
|
-
|
|
28441
|
-
|
|
28442
|
-
|
|
28443
|
-
orient: "auto-start-reverse",
|
|
28444
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
28445
|
-
"path",
|
|
28828
|
+
([suffix, size]) => EDGE_HEADS.flatMap(
|
|
28829
|
+
(head) => (
|
|
28830
|
+
// 塗り方は形と別の軸 (#578)。 塗らない形では 2 つが同じ名前に畳まれるので、
|
|
28831
|
+
// `edgeHeadMarkerId` が返す名前で重複を外す
|
|
28832
|
+
EDGE_HEAD_FILLS.map((fill) => {
|
|
28833
|
+
const \u5F62 = EDGE_HEAD_SHAPE[head];
|
|
28834
|
+
const id = edgeHeadMarkerId(tone, head, suffix === "-sm", fill);
|
|
28835
|
+
if (\u5F62.d === "") return null;
|
|
28836
|
+
if (fill !== EDGE_HEAD_FILL_DEFAULT && !\u5F62.filled) return null;
|
|
28837
|
+
const \u5857 = edgeHeadPaint(head, fill, color);
|
|
28838
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
28839
|
+
"marker",
|
|
28446
28840
|
{
|
|
28447
|
-
|
|
28448
|
-
|
|
28449
|
-
|
|
28450
|
-
|
|
28451
|
-
|
|
28452
|
-
|
|
28453
|
-
|
|
28454
|
-
|
|
28455
|
-
|
|
28456
|
-
|
|
28457
|
-
|
|
28458
|
-
|
|
28459
|
-
|
|
28460
|
-
|
|
28841
|
+
id,
|
|
28842
|
+
viewBox: `0 0 ${\u5F62.w} ${\u5F62.h}`,
|
|
28843
|
+
refX: \u5F62.refX,
|
|
28844
|
+
refY: \u5F62.h / 2,
|
|
28845
|
+
markerWidth: size * (\u5F62.scale ?? 1) * \u5F62.w / \u5F62.h,
|
|
28846
|
+
markerHeight: size * (\u5F62.scale ?? 1),
|
|
28847
|
+
markerUnits: "userSpaceOnUse",
|
|
28848
|
+
orient: "auto-start-reverse",
|
|
28849
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
28850
|
+
"path",
|
|
28851
|
+
{
|
|
28852
|
+
"data-cdl-role": "edge-arrowhead",
|
|
28853
|
+
"data-cdl-edge-head": head,
|
|
28854
|
+
"data-cdl-edge-head-fill": fill,
|
|
28855
|
+
d: \u5F62.d,
|
|
28856
|
+
fill: \u5857.fill,
|
|
28857
|
+
stroke: \u5857.stroke,
|
|
28858
|
+
strokeWidth: \u5857.strokeWidth,
|
|
28859
|
+
strokeLinecap: \u5857.strokeWidth === void 0 ? void 0 : "round",
|
|
28860
|
+
strokeLinejoin: \u5857.strokeWidth === void 0 ? void 0 : "round"
|
|
28861
|
+
}
|
|
28862
|
+
)
|
|
28863
|
+
},
|
|
28864
|
+
id
|
|
28865
|
+
);
|
|
28866
|
+
})
|
|
28867
|
+
)
|
|
28868
|
+
)
|
|
28461
28869
|
)
|
|
28462
28870
|
),
|
|
28463
28871
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -29146,65 +29554,58 @@ function flow(preset) {
|
|
|
29146
29554
|
};
|
|
29147
29555
|
return api;
|
|
29148
29556
|
}
|
|
29557
|
+
var SEQUENCE_MESSAGE_LOOK = {
|
|
29558
|
+
call: { style: "solid", head: "triangle" },
|
|
29559
|
+
return: { style: "dashed", head: "open" },
|
|
29560
|
+
fire: { style: "solid", head: "open" }
|
|
29561
|
+
};
|
|
29149
29562
|
function sequence(preset) {
|
|
29150
|
-
const laneW = preset.laneWidth ?? 340;
|
|
29151
29563
|
const tone = preset.defaultTone ?? "accent";
|
|
29152
|
-
const style = preset.defaultStyle ?? "solid";
|
|
29153
29564
|
const b = diagram(preset.id, { topic: preset.topic });
|
|
29154
|
-
const
|
|
29155
|
-
|
|
29156
|
-
|
|
29157
|
-
|
|
29158
|
-
|
|
29159
|
-
|
|
29160
|
-
|
|
29161
|
-
const actorW = Math.max(140, label.length * 22 + 52);
|
|
29162
|
-
const headerId = `${id}-header`;
|
|
29163
|
-
b.node(headerId, { lane: id, stack: 0, kind: "card", title: label, w: actorW, h: 72 });
|
|
29164
|
-
headerNodeIds.push(headerId);
|
|
29165
|
-
const spacerId = `${id}-spacer`;
|
|
29166
|
-
b.node(spacerId, { lane: id, stack: 1, kind: "card", title: "", w: 2, h: 40 });
|
|
29565
|
+
const \u9762\u3005 = preset.actors.map(
|
|
29566
|
+
(a) => typeof a === "string" ? { name: a } : { name: a.name, ...a.subtitle ? { subtitle: a.subtitle } : {} }
|
|
29567
|
+
);
|
|
29568
|
+
const \u756A\u53F7 = /* @__PURE__ */ new Map();
|
|
29569
|
+
\u9762\u3005.forEach((a, i) => {
|
|
29570
|
+
\u756A\u53F7.set(a.name, i);
|
|
29571
|
+
\u756A\u53F7.set(slugify(a.name) || `actor-${i}`, i);
|
|
29167
29572
|
});
|
|
29168
|
-
const
|
|
29169
|
-
|
|
29573
|
+
const \u8A00\u3065\u3066 = [];
|
|
29574
|
+
const \u8A9E = /* @__PURE__ */ new Map();
|
|
29170
29575
|
const api = {
|
|
29171
|
-
step(
|
|
29172
|
-
const
|
|
29173
|
-
const
|
|
29174
|
-
const
|
|
29175
|
-
|
|
29176
|
-
|
|
29177
|
-
b.node(fromBoxId, { lane: fromLaneId, stack, kind: "card", title: "", w: 2, h: 2 });
|
|
29178
|
-
if (fromLaneId !== toLaneId) {
|
|
29179
|
-
b.node(toBoxId, { lane: toLaneId, stack, kind: "card", title: "", w: 2, h: 2 });
|
|
29180
|
-
}
|
|
29181
|
-
const edgeId = `e${stepIdx}-${fromLaneId}-${toLaneId}`;
|
|
29182
|
-
b.edge(fromBoxId, fromLaneId === toLaneId ? fromBoxId : toBoxId, {
|
|
29183
|
-
id: edgeId,
|
|
29184
|
-
label: s.label,
|
|
29185
|
-
...s.sub ? { sub: s.sub } : {},
|
|
29186
|
-
tone: s.tone ?? tone,
|
|
29187
|
-
style: s.style ?? style
|
|
29188
|
-
});
|
|
29189
|
-
phaseActivate.push(fromBoxId);
|
|
29190
|
-
if (fromLaneId !== toLaneId) phaseActivate.push(toBoxId);
|
|
29191
|
-
phaseActivate.push(edgeId);
|
|
29192
|
-
stepIdx += 1;
|
|
29576
|
+
step(s2) {
|
|
29577
|
+
const from = \u756A\u53F7.get(s2.from) ?? 0;
|
|
29578
|
+
const to = \u756A\u53F7.get(s2.to) ?? 0;
|
|
29579
|
+
const kind = s2.kind ?? ((s2.style ?? preset.defaultStyle) === "dotted-flow" ? "return" : "call");
|
|
29580
|
+
\u8A00\u3065\u3066.push({ label: s2.label, from, to, kind });
|
|
29581
|
+
if (s2.sub) \u8A9E.set(\u8A00\u3065\u3066.length - 1, s2.sub);
|
|
29193
29582
|
return api;
|
|
29194
29583
|
},
|
|
29195
29584
|
build() {
|
|
29196
|
-
const
|
|
29197
|
-
|
|
29198
|
-
|
|
29199
|
-
|
|
29200
|
-
|
|
29201
|
-
|
|
29202
|
-
|
|
29585
|
+
const \u5E2F = preset.bands ? preset.bands.map((x) => ({ actor: \u756A\u53F7.get(x.actor) ?? 0, from: x.from, to: x.to })) : \u9762\u3005.map((_, i) => {
|
|
29586
|
+
const \u51FA\u756A = \u8A00\u3065\u3066.map((m2, idx) => m2.from === i || m2.to === i ? idx : -1).filter((idx) => idx >= 0);
|
|
29587
|
+
return \u51FA\u756A.length > 0 ? { actor: i, from: \u51FA\u756A[0], to: \u51FA\u756A[\u51FA\u756A.length - 1] } : null;
|
|
29588
|
+
}).filter((x) => x !== null);
|
|
29589
|
+
const data = { actors: \u9762\u3005, messages: \u8A00\u3065\u3066, bands: \u5E2F };
|
|
29590
|
+
const m = sequenceBoardMetrics(data);
|
|
29591
|
+
const laneId = "seq";
|
|
29592
|
+
b.lane(laneId, { width: m.w + LANE_PAD_MIN * 2 });
|
|
29593
|
+
b.node(preset.id, {
|
|
29594
|
+
lane: laneId,
|
|
29595
|
+
stack: 0,
|
|
29596
|
+
kind: "sequence-board",
|
|
29597
|
+
w: m.w,
|
|
29598
|
+
h: m.h,
|
|
29599
|
+
title: "",
|
|
29600
|
+
sequenceData: data,
|
|
29601
|
+
// 段が進むと濃さが移る。 書かない図では全部を濃く出す
|
|
29602
|
+
sequenceStep: `{${sequenceStepId()}}`,
|
|
29603
|
+
tone
|
|
29203
29604
|
});
|
|
29204
29605
|
b.phase(
|
|
29205
|
-
"
|
|
29606
|
+
"sequence",
|
|
29206
29607
|
{ duration: 2400, title: preset.topic, body: "sequence \u306E\u5168 message \u3092\u6642\u7CFB\u5217\u5C55\u958B\u3002" },
|
|
29207
|
-
(p) => p.activate(
|
|
29608
|
+
(p) => p.activate(preset.id).badge("sequence")
|
|
29208
29609
|
);
|
|
29209
29610
|
return b.build();
|
|
29210
29611
|
}
|
|
@@ -29272,6 +29673,14 @@ function topology(preset) {
|
|
|
29272
29673
|
};
|
|
29273
29674
|
return api;
|
|
29274
29675
|
}
|
|
29676
|
+
var ER_CARDINALITY_HEAD = {
|
|
29677
|
+
"1:1": { tail: "one", head: "one" },
|
|
29678
|
+
"1:N": { tail: "one", head: "many" },
|
|
29679
|
+
"N:1": { tail: "many", head: "one" },
|
|
29680
|
+
"N:M": { tail: "many", head: "many" },
|
|
29681
|
+
"0..1": { tail: "one", head: "zero-one" },
|
|
29682
|
+
"1..*": { tail: "one", head: "many" }
|
|
29683
|
+
};
|
|
29275
29684
|
function er(preset) {
|
|
29276
29685
|
const entityW = resolveStorageBoxW(preset.entityWidth, "er", "entityWidth");
|
|
29277
29686
|
const tone = preset.defaultTone ?? "info";
|
|
@@ -29282,7 +29691,27 @@ function er(preset) {
|
|
|
29282
29691
|
const api = {
|
|
29283
29692
|
entity(e) {
|
|
29284
29693
|
const laneId = `lane-${e.id}`;
|
|
29285
|
-
const
|
|
29694
|
+
const \u9375 = (e.columns ?? []).filter((c) => c.pk === true);
|
|
29695
|
+
const \u5024 = (e.columns ?? []).filter((c) => c.pk !== true);
|
|
29696
|
+
const \u884C = [];
|
|
29697
|
+
const \u5370 = [];
|
|
29698
|
+
const \u8DB3\u3059 = (c) => {
|
|
29699
|
+
\u884C.push(`${c.name}: ${c.type}`);
|
|
29700
|
+
\u5370.push({
|
|
29701
|
+
shape: c.fk === true ? "chevron" : "square",
|
|
29702
|
+
filled: c.optional !== true,
|
|
29703
|
+
...c.pk === true ? { underline: true } : {}
|
|
29704
|
+
});
|
|
29705
|
+
};
|
|
29706
|
+
\u9375.forEach(\u8DB3\u3059);
|
|
29707
|
+
if (\u9375.length > 0 && \u5024.length > 0) {
|
|
29708
|
+
\u884C.push("");
|
|
29709
|
+
\u5370.push(null);
|
|
29710
|
+
}
|
|
29711
|
+
\u5024.forEach(\u8DB3\u3059);
|
|
29712
|
+
const \u8A2D\u8A08\u306E\u5F62 = \u884C.length > 0;
|
|
29713
|
+
const rows = \u8A2D\u8A08\u306E\u5F62 ? \u884C : e.rows ?? [];
|
|
29714
|
+
const boxW = fitRowsWidth(entityW, rows);
|
|
29286
29715
|
b.lane(laneId, { width: boxLaneW(boxW) });
|
|
29287
29716
|
b.node(e.id, {
|
|
29288
29717
|
lane: laneId,
|
|
@@ -29290,8 +29719,12 @@ function er(preset) {
|
|
|
29290
29719
|
kind: "storage",
|
|
29291
29720
|
w: boxW,
|
|
29292
29721
|
title: e.title,
|
|
29293
|
-
|
|
29294
|
-
|
|
29722
|
+
// 種類の札は設計の形では出さない (#578)。 「エンティティ」 と書いた札は全ての箱に
|
|
29723
|
+
// 同じ字が並ぶだけで、代わりに表の呼び名を題の下へ置く
|
|
29724
|
+
...\u8A2D\u8A08\u306E\u5F62 ? {} : { eyebrow: "\u30A8\u30F3\u30C6\u30A3\u30C6\u30A3" },
|
|
29725
|
+
...\u8A2D\u8A08\u306E\u5F62 && e.subtitle ? { subtitle: e.subtitle } : {},
|
|
29726
|
+
rows,
|
|
29727
|
+
...\u8A2D\u8A08\u306E\u5F62 ? { rowMarks: \u5370 } : {}
|
|
29295
29728
|
});
|
|
29296
29729
|
entities.push(e.id);
|
|
29297
29730
|
phaseActivate.push(e.id);
|
|
@@ -29300,14 +29733,19 @@ function er(preset) {
|
|
|
29300
29733
|
relation(r) {
|
|
29301
29734
|
const currentIdx = relIdx++;
|
|
29302
29735
|
const edgeId = `rel-${currentIdx}-${r.from}-${r.to}`;
|
|
29303
|
-
const label = r.label ?? r.cardinality;
|
|
29304
|
-
const
|
|
29736
|
+
const label = r.label ?? r.cardinality ?? "";
|
|
29737
|
+
const \u5370\u304C\u793A\u3059 = r.tailHead !== void 0 || r.head !== void 0;
|
|
29738
|
+
const sub = r.label && r.cardinality && !\u5370\u304C\u793A\u3059 ? r.cardinality : void 0;
|
|
29739
|
+
const \u65E2\u5B9A = r.cardinality ? ER_CARDINALITY_HEAD[r.cardinality] : void 0;
|
|
29305
29740
|
b.edge(r.from, r.to, {
|
|
29306
29741
|
id: edgeId,
|
|
29307
29742
|
label,
|
|
29308
29743
|
...sub ? { sub } : {},
|
|
29309
29744
|
tone: r.tone ?? tone,
|
|
29310
|
-
style: "solid"
|
|
29745
|
+
style: r.style ?? "solid",
|
|
29746
|
+
// 端の印は両端に立つ (#578)。 箱に近い側が個数、その外側が任意か
|
|
29747
|
+
...r.head ?? \u65E2\u5B9A?.head ? { head: r.head ?? \u65E2\u5B9A.head } : {},
|
|
29748
|
+
...r.tailHead ?? \u65E2\u5B9A?.tail ? { tailHead: r.tailHead ?? \u65E2\u5B9A.tail } : {}
|
|
29311
29749
|
});
|
|
29312
29750
|
phaseActivate.push(edgeId);
|
|
29313
29751
|
return api;
|
|
@@ -29323,49 +29761,114 @@ function er(preset) {
|
|
|
29323
29761
|
};
|
|
29324
29762
|
return api;
|
|
29325
29763
|
}
|
|
29764
|
+
var MARK_BOX = 96;
|
|
29765
|
+
var FSM_ACTION_MARK = {
|
|
29766
|
+
entry: { shape: "chevron", filled: true },
|
|
29767
|
+
exit: { shape: "chevron", filled: false },
|
|
29768
|
+
do: { shape: "square", filled: true },
|
|
29769
|
+
internal: { shape: "square", filled: false }
|
|
29770
|
+
};
|
|
29326
29771
|
function stateMachine(preset) {
|
|
29327
29772
|
const stateW = resolveStateW(preset.stateWidth, "stateMachine");
|
|
29328
|
-
const laneW = boxLaneW(stateW);
|
|
29329
29773
|
const tone = preset.defaultTone ?? "accent";
|
|
29330
29774
|
const b = diagram(preset.id, { topic: preset.topic });
|
|
29331
29775
|
const phaseActivate = [];
|
|
29332
|
-
let transIdx = 0;
|
|
29333
29776
|
const stateOrder = /* @__PURE__ */ new Map();
|
|
29777
|
+
const \u72B6\u614B = [];
|
|
29778
|
+
const \u7BC0\u70B9 = [];
|
|
29779
|
+
const \u9077\u79FB = [];
|
|
29780
|
+
const \u4E26\u3073 = [];
|
|
29334
29781
|
const api = {
|
|
29335
29782
|
state(s) {
|
|
29336
|
-
|
|
29337
|
-
|
|
29338
|
-
const eyebrow = s.initial ? "\u521D\u671F" : s.final ? "\u6700\u7D42" : "\u72B6\u614B";
|
|
29339
|
-
b.node(s.id, {
|
|
29340
|
-
lane: laneId,
|
|
29341
|
-
stack: 0,
|
|
29342
|
-
kind: "card",
|
|
29343
|
-
w: stateW,
|
|
29344
|
-
title: s.title,
|
|
29345
|
-
eyebrow
|
|
29346
|
-
});
|
|
29783
|
+
\u4E26\u3073.push({ \u7A2E: "\u72B6\u614B", i: \u72B6\u614B.length });
|
|
29784
|
+
\u72B6\u614B.push(s);
|
|
29347
29785
|
stateOrder.set(s.id, stateOrder.size);
|
|
29348
|
-
|
|
29786
|
+
return api;
|
|
29787
|
+
},
|
|
29788
|
+
mark(m) {
|
|
29789
|
+
\u4E26\u3073.push({ \u7A2E: "\u7BC0\u70B9", i: \u7BC0\u70B9.length });
|
|
29790
|
+
\u7BC0\u70B9.push(m);
|
|
29791
|
+
stateOrder.set(m.id, stateOrder.size);
|
|
29349
29792
|
return api;
|
|
29350
29793
|
},
|
|
29351
29794
|
transition(t) {
|
|
29352
|
-
|
|
29353
|
-
const edgeId = `t${currentIdx}-${t.from}-${t.to}`;
|
|
29354
|
-
const fromIdx = stateOrder.get(t.from) ?? 0;
|
|
29355
|
-
const toIdx = stateOrder.get(t.to) ?? 0;
|
|
29356
|
-
const isBack = toIdx < fromIdx;
|
|
29357
|
-
b.edge(t.from, t.to, {
|
|
29358
|
-
id: edgeId,
|
|
29359
|
-
label: t.trigger,
|
|
29360
|
-
...t.guard ? { sub: t.guard } : {},
|
|
29361
|
-
tone: t.tone ?? tone,
|
|
29362
|
-
style: "solid",
|
|
29363
|
-
...isBack ? { routing: "back-detour" } : {}
|
|
29364
|
-
});
|
|
29365
|
-
phaseActivate.push(edgeId);
|
|
29795
|
+
\u9077\u79FB.push(t);
|
|
29366
29796
|
return api;
|
|
29367
29797
|
},
|
|
29368
29798
|
build() {
|
|
29799
|
+
const \u8A2D\u8A08\u306E\u5F62 = \u72B6\u614B.some((s) => s.actions !== void 0 || s.subtitle !== void 0) || \u7BC0\u70B9.length > 0;
|
|
29800
|
+
const \u683C\u5B50 = \u72B6\u614B.some((s) => s.col !== void 0) || \u7BC0\u70B9.some((m) => m.col !== void 0);
|
|
29801
|
+
const \u4E2D\u8EAB = \u72B6\u614B.map((s) => {
|
|
29802
|
+
const \u884C = (s.actions ?? []).map((a) => a.note ? `${a.label}: ${a.note}` : a.label);
|
|
29803
|
+
const \u5370 = (s.actions ?? []).map((a) => FSM_ACTION_MARK[a.when]);
|
|
29804
|
+
const laneId = \u683C\u5B50 && s.col !== void 0 ? `col-${s.col}` : `lane-${s.id}`;
|
|
29805
|
+
const boxW = \u8A2D\u8A08\u306E\u5F62 ? fitRowsWidth(stateW, \u884C) : stateW;
|
|
29806
|
+
return { s, \u884C, \u5370, laneId, boxW, stack: \u683C\u5B50 ? s.row ?? 0 : 0 };
|
|
29807
|
+
});
|
|
29808
|
+
const \u7BC0\u70B9\u306E\u4E2D\u8EAB = \u7BC0\u70B9.map((m) => ({
|
|
29809
|
+
m,
|
|
29810
|
+
laneId: \u683C\u5B50 && m.col !== void 0 ? `col-${m.col}` : `lane-${m.id}`,
|
|
29811
|
+
stack: \u683C\u5B50 ? m.row ?? 0 : 0
|
|
29812
|
+
}));
|
|
29813
|
+
const \u5E2F\u5E45 = /* @__PURE__ */ new Map();
|
|
29814
|
+
for (const c of \u4E2D\u8EAB) \u5E2F\u5E45.set(c.laneId, Math.max(\u5E2F\u5E45.get(c.laneId) ?? 0, c.boxW));
|
|
29815
|
+
for (const c of \u7BC0\u70B9\u306E\u4E2D\u8EAB) \u5E2F\u5E45.set(c.laneId, Math.max(\u5E2F\u5E45.get(c.laneId) ?? 0, MARK_BOX));
|
|
29816
|
+
const \u6E08 = /* @__PURE__ */ new Set();
|
|
29817
|
+
const \u5E2F\u3092\u4F5C\u308B = (laneId) => {
|
|
29818
|
+
if (\u6E08.has(laneId)) return;
|
|
29819
|
+
\u6E08.add(laneId);
|
|
29820
|
+
b.lane(laneId, { width: boxLaneW(\u5E2F\u5E45.get(laneId) ?? stateW) });
|
|
29821
|
+
};
|
|
29822
|
+
for (const c of \u7BC0\u70B9\u306E\u4E2D\u8EAB) if (c.stack === 0) \u5E2F\u3092\u4F5C\u308B(c.laneId);
|
|
29823
|
+
for (const c of \u4E2D\u8EAB) \u5E2F\u3092\u4F5C\u308B(c.laneId);
|
|
29824
|
+
for (const c of \u7BC0\u70B9\u306E\u4E2D\u8EAB) \u5E2F\u3092\u4F5C\u308B(c.laneId);
|
|
29825
|
+
for (const o of \u4E26\u3073) {
|
|
29826
|
+
if (o.\u7A2E === "\u7BC0\u70B9") {
|
|
29827
|
+
const c2 = \u7BC0\u70B9\u306E\u4E2D\u8EAB[o.i];
|
|
29828
|
+
b.node(c2.m.id, {
|
|
29829
|
+
lane: c2.laneId,
|
|
29830
|
+
stack: c2.stack,
|
|
29831
|
+
kind: c2.m.kind === "start" ? "mark-start" : "mark-end",
|
|
29832
|
+
w: MARK_BOX,
|
|
29833
|
+
h: MARK_BOX,
|
|
29834
|
+
title: ""
|
|
29835
|
+
});
|
|
29836
|
+
phaseActivate.push(c2.m.id);
|
|
29837
|
+
continue;
|
|
29838
|
+
}
|
|
29839
|
+
const c = \u4E2D\u8EAB[o.i];
|
|
29840
|
+
const eyebrow = \u7BC0\u70B9.length > 0 ? void 0 : c.s.initial ? "\u521D\u671F" : c.s.final ? "\u6700\u7D42" : "\u72B6\u614B";
|
|
29841
|
+
b.node(c.s.id, {
|
|
29842
|
+
lane: c.laneId,
|
|
29843
|
+
stack: c.stack,
|
|
29844
|
+
kind: \u8A2D\u8A08\u306E\u5F62 ? "storage" : "card",
|
|
29845
|
+
w: c.boxW,
|
|
29846
|
+
title: c.s.title,
|
|
29847
|
+
...eyebrow ? { eyebrow } : {},
|
|
29848
|
+
...c.s.subtitle ? { subtitle: c.s.subtitle } : {},
|
|
29849
|
+
// 行を持たない状態でも欄を書く (#578)。 書かないとその箱だけ従来の意匠に落ち、
|
|
29850
|
+
// 呼び名が消える
|
|
29851
|
+
...\u8A2D\u8A08\u306E\u5F62 ? { rows: c.\u884C, rowMarks: c.\u5370 } : {}
|
|
29852
|
+
});
|
|
29853
|
+
phaseActivate.push(c.s.id);
|
|
29854
|
+
}
|
|
29855
|
+
\u9077\u79FB.forEach((t, currentIdx) => {
|
|
29856
|
+
const edgeId = `t${currentIdx}-${t.from}-${t.to}`;
|
|
29857
|
+
const fromIdx = stateOrder.get(t.from) ?? 0;
|
|
29858
|
+
const toIdx = stateOrder.get(t.to) ?? 0;
|
|
29859
|
+
const isBack = toIdx < fromIdx;
|
|
29860
|
+
b.edge(t.from, t.to, {
|
|
29861
|
+
id: edgeId,
|
|
29862
|
+
label: t.trigger,
|
|
29863
|
+
...t.guard ? { sub: t.guard } : {},
|
|
29864
|
+
tone: t.tone ?? tone,
|
|
29865
|
+
style: "solid",
|
|
29866
|
+
// 遷移の印は 1 種類だけ = 実線に開いた矢 (#578)。 線と印が分かれず、違いは語の中に入る
|
|
29867
|
+
head: t.head ?? "open",
|
|
29868
|
+
...isBack ? { routing: "back-detour" } : {}
|
|
29869
|
+
});
|
|
29870
|
+
phaseActivate.push(edgeId);
|
|
29871
|
+
});
|
|
29369
29872
|
b.phase(
|
|
29370
29873
|
"fsm",
|
|
29371
29874
|
{ duration: 2400, title: preset.topic, body: "FSM \u306E\u5168 state + transition \u3092 visible \u5316\u3002" },
|
|
@@ -29429,72 +29932,103 @@ function infrastructure(preset) {
|
|
|
29429
29932
|
};
|
|
29430
29933
|
return api;
|
|
29431
29934
|
}
|
|
29432
|
-
var
|
|
29433
|
-
extends: "triangle",
|
|
29434
|
-
implements: "triangle",
|
|
29435
|
-
|
|
29436
|
-
|
|
29437
|
-
|
|
29935
|
+
var CLASS_RELATION_LOOK = {
|
|
29936
|
+
extends: { head: "triangle", fill: "hollow", tailHead: "none", tailFill: "solid", style: "solid" },
|
|
29937
|
+
implements: { head: "triangle", fill: "hollow", tailHead: "none", tailFill: "solid", style: "dashed" },
|
|
29938
|
+
aggregates: { head: "none", fill: "solid", tailHead: "diamond", tailFill: "hollow", style: "solid" },
|
|
29939
|
+
composes: { head: "none", fill: "solid", tailHead: "diamond", tailFill: "solid", style: "solid" },
|
|
29940
|
+
associates: { head: "open", fill: "solid", tailHead: "none", tailFill: "solid", style: "solid" },
|
|
29941
|
+
uses: { head: "open", fill: "solid", tailHead: "none", tailFill: "solid", style: "dashed" }
|
|
29438
29942
|
};
|
|
29943
|
+
Object.fromEntries(
|
|
29944
|
+
Object.entries(CLASS_RELATION_LOOK).map(([k, v]) => [k, v.head])
|
|
29945
|
+
);
|
|
29946
|
+
function isPublic(row) {
|
|
29947
|
+
return !row.startsWith("-") && !row.startsWith("#");
|
|
29948
|
+
}
|
|
29949
|
+
function stripAccess(row) {
|
|
29950
|
+
const \u672C\u4F53 = isPublic(row) && !row.startsWith("+") ? row : row.slice(1);
|
|
29951
|
+
return \u672C\u4F53.replace("()", "");
|
|
29952
|
+
}
|
|
29439
29953
|
function classDiagram(preset) {
|
|
29440
29954
|
const classW = resolveStorageBoxW(preset.classWidth, "classDiagram", "classWidth");
|
|
29441
29955
|
const tone = preset.defaultTone ?? "info";
|
|
29442
29956
|
const b = diagram(preset.id, { topic: preset.topic });
|
|
29443
29957
|
const classes = [];
|
|
29444
29958
|
const phaseActivate = [];
|
|
29445
|
-
|
|
29959
|
+
const \u7BB1 = [];
|
|
29960
|
+
const \u95A2\u4FC2 = [];
|
|
29446
29961
|
const api = {
|
|
29447
29962
|
class(c) {
|
|
29448
|
-
|
|
29449
|
-
const rows = [];
|
|
29450
|
-
if (c.attributes && c.attributes.length > 0) {
|
|
29451
|
-
rows.push(...c.attributes);
|
|
29452
|
-
}
|
|
29453
|
-
if (c.methods && c.methods.length > 0) {
|
|
29454
|
-
if (rows.length > 0) rows.push("\u2500\u2500\u2500");
|
|
29455
|
-
rows.push(...c.methods);
|
|
29456
|
-
}
|
|
29457
|
-
const boxW = fitRowsWidth(classW, rows);
|
|
29458
|
-
b.lane(laneId, { width: boxLaneW(boxW) });
|
|
29459
|
-
b.node(c.id, {
|
|
29460
|
-
lane: laneId,
|
|
29461
|
-
stack: 0,
|
|
29462
|
-
kind: "storage",
|
|
29463
|
-
w: boxW,
|
|
29464
|
-
title: c.title,
|
|
29465
|
-
eyebrow: c.stereotype ?? "\u30AF\u30E9\u30B9",
|
|
29466
|
-
...rows.length > 0 ? { rows } : {}
|
|
29467
|
-
});
|
|
29468
|
-
classes.push(c.id);
|
|
29469
|
-
phaseActivate.push(c.id);
|
|
29963
|
+
\u7BB1.push(c);
|
|
29470
29964
|
return api;
|
|
29471
29965
|
},
|
|
29472
29966
|
relation(r) {
|
|
29473
|
-
|
|
29474
|
-
const edgeId = `cr-${currentIdx}-${r.from}-${r.to}`;
|
|
29475
|
-
const label = r.label ?? r.type;
|
|
29476
|
-
const sub = r.cardinality;
|
|
29477
|
-
b.edge(r.from, r.to, {
|
|
29478
|
-
id: edgeId,
|
|
29479
|
-
label,
|
|
29480
|
-
...sub ? { sub } : {},
|
|
29481
|
-
tone: r.tone ?? tone,
|
|
29482
|
-
style: "solid",
|
|
29483
|
-
// 関係の種類から端の形を決める (cdl#574)。 書いた形が勝つ
|
|
29484
|
-
head: r.head ?? CLASS_RELATION_HEAD[r.type]
|
|
29485
|
-
// CAR-531 SSOT ... 旧実装は `labelOffsetY: currentIdx % 2 === 0 ? -60 : 60` で
|
|
29486
|
-
// 複数 relation label の path 沿い集中を強制分散していた。 CAR-430 で導入した
|
|
29487
|
-
// engine 側 fan offset (FAN_STEP 40 world) が同 from / to 群を自動分散する現在、
|
|
29488
|
-
// author 指定 ±60 は engine 分散と二重発火して extends label が SSOT
|
|
29489
|
-
// LABEL_INIT_CLEARANCE (34、 CAR-630 で 26 → 34 復帰) を大幅に超える 114 world 離れる bug の直接原因になっていた。
|
|
29490
|
-
// author 指定 offset を削除、 engine 側の LABEL_INIT_CLEARANCE + fan offset に一任する。
|
|
29491
|
-
// 個別 relation で offset を再導入したい author は future extension (UmlRelation に
|
|
29492
|
-
// labelOffsetY? を追加) で明示的に指定する経路を残す。
|
|
29493
|
-
});
|
|
29494
|
-
phaseActivate.push(edgeId);
|
|
29967
|
+
\u95A2\u4FC2.push(r);
|
|
29495
29968
|
return api;
|
|
29496
29969
|
},
|
|
29497
29970
|
build() {
|
|
29971
|
+
const \u4E2D\u8EAB = \u7BB1.map((c) => {
|
|
29972
|
+
const rows = [];
|
|
29973
|
+
const rowMarks = [];
|
|
29974
|
+
for (const a of c.attributes ?? []) {
|
|
29975
|
+
rows.push(stripAccess(a));
|
|
29976
|
+
rowMarks.push({ shape: "square", filled: isPublic(a) });
|
|
29977
|
+
}
|
|
29978
|
+
if ((c.attributes?.length ?? 0) > 0 && (c.methods?.length ?? 0) > 0) {
|
|
29979
|
+
rows.push("");
|
|
29980
|
+
rowMarks.push(null);
|
|
29981
|
+
}
|
|
29982
|
+
for (const m of c.methods ?? []) {
|
|
29983
|
+
rows.push(stripAccess(m));
|
|
29984
|
+
rowMarks.push({ shape: "chevron", filled: isPublic(m) });
|
|
29985
|
+
}
|
|
29986
|
+
const boxW = fitRowsWidth(classW, rows);
|
|
29987
|
+
const laneId = c.col !== void 0 ? `col-${c.col}` : `lane-${c.id}`;
|
|
29988
|
+
return { c, rows, rowMarks, boxW, laneId, stack: c.col !== void 0 ? c.row ?? 0 : 0 };
|
|
29989
|
+
});
|
|
29990
|
+
const \u5E2F\u5E45 = /* @__PURE__ */ new Map();
|
|
29991
|
+
for (const m of \u4E2D\u8EAB) \u5E2F\u5E45.set(m.laneId, Math.max(\u5E2F\u5E45.get(m.laneId) ?? 0, m.boxW));
|
|
29992
|
+
const \u6E08 = /* @__PURE__ */ new Set();
|
|
29993
|
+
for (const m of \u4E2D\u8EAB) {
|
|
29994
|
+
if (\u6E08.has(m.laneId)) continue;
|
|
29995
|
+
\u6E08.add(m.laneId);
|
|
29996
|
+
b.lane(m.laneId, { width: boxLaneW(\u5E2F\u5E45.get(m.laneId) ?? m.boxW) });
|
|
29997
|
+
}
|
|
29998
|
+
for (const m of \u4E2D\u8EAB) {
|
|
29999
|
+
b.node(m.c.id, {
|
|
30000
|
+
lane: m.laneId,
|
|
30001
|
+
stack: m.stack,
|
|
30002
|
+
kind: "storage",
|
|
30003
|
+
w: m.boxW,
|
|
30004
|
+
title: m.c.title,
|
|
30005
|
+
// 種類の札は **書いた時だけ** 出す (#578)。 「クラス」 と書いた札は箱がクラスで
|
|
30006
|
+
// あることしか言わず、図の中の全ての箱に同じ字が並ぶ
|
|
30007
|
+
...m.c.stereotype ? { eyebrow: m.c.stereotype } : {},
|
|
30008
|
+
...m.rows.length > 0 ? { rows: m.rows, rowMarks: m.rowMarks } : {}
|
|
30009
|
+
});
|
|
30010
|
+
classes.push(m.c.id);
|
|
30011
|
+
phaseActivate.push(m.c.id);
|
|
30012
|
+
}
|
|
30013
|
+
\u95A2\u4FC2.forEach((r, currentIdx) => {
|
|
30014
|
+
const edgeId = `cr-${currentIdx}-${r.from}-${r.to}`;
|
|
30015
|
+
const \u898B\u305F\u76EE = CLASS_RELATION_LOOK[r.type];
|
|
30016
|
+
b.edge(r.from, r.to, {
|
|
30017
|
+
id: edgeId,
|
|
30018
|
+
label: r.label ?? r.type,
|
|
30019
|
+
...r.cardinality ? { sub: r.cardinality } : {},
|
|
30020
|
+
tone: r.tone ?? tone,
|
|
30021
|
+
// 関係の種類から線と端の形を決める (cdl#574 / #578)。 書いた値が勝つ
|
|
30022
|
+
style: r.style ?? \u898B\u305F\u76EE.style,
|
|
30023
|
+
head: r.head ?? \u898B\u305F\u76EE.head,
|
|
30024
|
+
headFill: r.headFill ?? \u898B\u305F\u76EE.fill,
|
|
30025
|
+
tailHead: r.tailHead ?? \u898B\u305F\u76EE.tailHead,
|
|
30026
|
+
tailHeadFill: \u898B\u305F\u76EE.tailFill
|
|
30027
|
+
// CAR-531 SSOT ... label の分散は engine 側 (LABEL_INIT_CLEARANCE + fan offset) に
|
|
30028
|
+
// 一任する。 author 指定 ±60 は engine 分散と二重発火して label が大きく離れる
|
|
30029
|
+
});
|
|
30030
|
+
phaseActivate.push(edgeId);
|
|
30031
|
+
});
|
|
29498
30032
|
b.phase(
|
|
29499
30033
|
"class",
|
|
29500
30034
|
{ duration: 2400, title: preset.topic, body: "UML class \u5168 class + relation \u3092 visible \u5316\u3002" },
|
|
@@ -30009,6 +30543,7 @@ exports.ARROW_ENDPOINT_CENTER_TOL = ARROW_ENDPOINT_CENTER_TOL;
|
|
|
30009
30543
|
exports.CHAIN_MIN_CLEARANCE = CHAIN_MIN_CLEARANCE;
|
|
30010
30544
|
exports.CHAIN_SHIFT_MAX_ACCUMULATED = CHAIN_SHIFT_MAX_ACCUMULATED;
|
|
30011
30545
|
exports.CHAIN_SHIFT_MAX_ITER = CHAIN_SHIFT_MAX_ITER;
|
|
30546
|
+
exports.CLASS_RELATION_LOOK = CLASS_RELATION_LOOK;
|
|
30012
30547
|
exports.CLEARANCE_LABEL_LABEL = CLEARANCE_LABEL_LABEL;
|
|
30013
30548
|
exports.CLEARANCE_LANE_LABEL = CLEARANCE_LANE_LABEL;
|
|
30014
30549
|
exports.CLEARANCE_NODE_LABEL = CLEARANCE_NODE_LABEL;
|
|
@@ -30022,10 +30557,15 @@ exports.DIST_LABEL_PATH_MAX = DIST_LABEL_PATH_MAX;
|
|
|
30022
30557
|
exports.DIST_LABEL_PATH_MIN = DIST_LABEL_PATH_MIN;
|
|
30023
30558
|
exports.EDGE_HEADS = EDGE_HEADS;
|
|
30024
30559
|
exports.EDGE_HEAD_DEFAULT = EDGE_HEAD_DEFAULT;
|
|
30560
|
+
exports.EDGE_HEAD_FILLS = EDGE_HEAD_FILLS;
|
|
30561
|
+
exports.EDGE_HEAD_FILL_DEFAULT = EDGE_HEAD_FILL_DEFAULT;
|
|
30025
30562
|
exports.EDGE_LABEL_TEXT = EDGE_LABEL_TEXT;
|
|
30026
30563
|
exports.EDGE_STUB_OUT = EDGE_STUB_OUT;
|
|
30564
|
+
exports.EDGE_STYLES = EDGE_STYLES;
|
|
30565
|
+
exports.ER_CARDINALITY_HEAD = ER_CARDINALITY_HEAD;
|
|
30027
30566
|
exports.FAN_GAP = FAN_GAP;
|
|
30028
30567
|
exports.FONT_RENDER_TOLERANCE_WORLD = FONT_RENDER_TOLERANCE_WORLD;
|
|
30568
|
+
exports.FSM_ACTION_MARK = FSM_ACTION_MARK;
|
|
30029
30569
|
exports.LABEL_INIT_CLEARANCE = LABEL_INIT_CLEARANCE;
|
|
30030
30570
|
exports.LABEL_INIT_CLEARANCE_DOTTED_FLOW = LABEL_INIT_CLEARANCE_DOTTED_FLOW;
|
|
30031
30571
|
exports.LABEL_SIZE_TOLERANCE_WORLD = LABEL_SIZE_TOLERANCE_WORLD;
|
|
@@ -30039,6 +30579,7 @@ exports.NEAR_COLLISION_POLICY = NEAR_COLLISION_POLICY;
|
|
|
30039
30579
|
exports.NODE_FRAME_SELECTOR = NODE_FRAME_SELECTOR;
|
|
30040
30580
|
exports.NODE_KINDS = NODE_KINDS;
|
|
30041
30581
|
exports.ROW_GAP_VARIANCE_TOL = ROW_GAP_VARIANCE_TOL;
|
|
30582
|
+
exports.SEQUENCE_MESSAGE_LOOK = SEQUENCE_MESSAGE_LOOK;
|
|
30042
30583
|
exports.SPEC_CLEARANCE_POLICY = SPEC_CLEARANCE_POLICY;
|
|
30043
30584
|
exports.STAGE_SVG_SELECTOR = STAGE_SVG_SELECTOR;
|
|
30044
30585
|
exports.TARGET_LABEL_PATH_DIST = TARGET_LABEL_PATH_DIST;
|
|
@@ -30113,6 +30654,8 @@ exports.resolveTarget = resolveTarget;
|
|
|
30113
30654
|
exports.resolveTargetAll = resolveTargetAll;
|
|
30114
30655
|
exports.segmentsIntersect = segmentsIntersect2;
|
|
30115
30656
|
exports.sequence = sequence;
|
|
30657
|
+
exports.sequenceBoardMetrics = sequenceBoardMetrics;
|
|
30658
|
+
exports.sequenceStepId = sequenceStepId;
|
|
30116
30659
|
exports.signal = signal;
|
|
30117
30660
|
exports.stateMachine = stateMachine;
|
|
30118
30661
|
exports.stateMachine2 = stateMachine2;
|