@cardenelabs/cdl 0.16.0 → 0.17.1
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 +98 -1
- package/dist/index.cjs +743 -195
- 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 +735 -196
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +465 -62
- 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 +465 -62
- 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 +297 -0
- package/src/kinds/storage.tsx +139 -12
- package/src/layout/nodes.ts +33 -6
- package/src/layout/spec.ts +36 -5
- 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 +33 -1
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",
|
|
@@ -11794,7 +11803,7 @@ function genericTextCentered(kind, hasRows) {
|
|
|
11794
11803
|
function genericTitleBaselineY(kind, h, hasRows) {
|
|
11795
11804
|
return genericTextCentered(kind, hasRows) ? h / 2 + GENERIC_TITLE_CENTER_OFFSET : GENERIC_TITLE_TOP + genericTextShift(kind);
|
|
11796
11805
|
}
|
|
11797
|
-
var ROW_TOP_STORAGE =
|
|
11806
|
+
var ROW_TOP_STORAGE = 152;
|
|
11798
11807
|
var ROW_PITCH_STORAGE = 56;
|
|
11799
11808
|
var ROW_TOP_GENERIC = 100;
|
|
11800
11809
|
var ROW_PITCH_GENERIC = 28;
|
|
@@ -11805,7 +11814,9 @@ var GENERIC_TITLE_FONT = 20;
|
|
|
11805
11814
|
var GLYPH_CAP_RATIO = 0.72;
|
|
11806
11815
|
var ROW_FONT_STORAGE = 26;
|
|
11807
11816
|
var ROW_FONT_GENERIC = 21;
|
|
11808
|
-
var STORAGE_TITLE_BASELINE =
|
|
11817
|
+
var STORAGE_TITLE_BASELINE = 86;
|
|
11818
|
+
var STORAGE_TITLE_FONT = 34;
|
|
11819
|
+
var SUBTITLE_ROW_SHIFT = 46;
|
|
11809
11820
|
var STORAGE_ROW_DIVIDER_Y = Math.round(
|
|
11810
11821
|
(STORAGE_TITLE_BASELINE + (ROW_TOP_STORAGE - ROW_FONT_STORAGE * GLYPH_CAP_RATIO)) / 2
|
|
11811
11822
|
);
|
|
@@ -13409,7 +13420,10 @@ var TOKENS = {
|
|
|
13409
13420
|
// 印は箱いっぱいに描く (線が箱の縁で止まるため) ので、この値が丸の直径になる。
|
|
13410
13421
|
// 箱としての最小 (80x40) より大きく、名前を持つ箱 (card 320x150) よりは明らかに小さい
|
|
13411
13422
|
"mark-start": { w: 96, h: 96 },
|
|
13412
|
-
"mark-end": { w: 96, h: 96 }
|
|
13423
|
+
"mark-end": { w: 96, h: 96 },
|
|
13424
|
+
// 時系列のやり取り (#578)。 実寸は中身から決まる (`sequenceBoardMetrics`) ので、
|
|
13425
|
+
// ここは書かなかった時の受け皿
|
|
13426
|
+
"sequence-board": { w: 960, h: 640 }
|
|
13413
13427
|
},
|
|
13414
13428
|
// row gap (stack 間の vertical gap、 lane 内 / 跨ぎ共通)
|
|
13415
13429
|
// edge label が node の上 36 px に配置されるため、 boxH 68 + 36 + 余裕 = 100 必要。
|
|
@@ -15072,8 +15086,12 @@ function requiredRowsWidth(rows, kind) {
|
|
|
15072
15086
|
function autoStorageHeight(n, defaultH) {
|
|
15073
15087
|
if (n.kind !== "storage") return n.h ?? defaultH;
|
|
15074
15088
|
if (n.h != null) return n.h;
|
|
15075
|
-
|
|
15076
|
-
|
|
15089
|
+
const \u5370\u3042\u308A = n.rowMarks !== void 0;
|
|
15090
|
+
const \u547C\u3073\u540D\u306E\u5206 = \u5370\u3042\u308A && n.subtitle ? SUBTITLE_ROW_SHIFT : 0;
|
|
15091
|
+
if (!n.rows || n.rows.length === 0) return 150 + \u547C\u3073\u540D\u306E\u5206;
|
|
15092
|
+
const \u5FC5\u8981 = requiredRowsHeight("storage", n.rows.length) ?? defaultH;
|
|
15093
|
+
if (\u5370\u3042\u308A) return \u5FC5\u8981 + \u547C\u3073\u540D\u306E\u5206;
|
|
15094
|
+
return Math.max(defaultH, \u5FC5\u8981);
|
|
15077
15095
|
}
|
|
15078
15096
|
function autoRowsWidth(n, defaultW) {
|
|
15079
15097
|
if (n.w != null) return n.w;
|
|
@@ -15161,8 +15179,11 @@ function layoutNodes(diag, lanes) {
|
|
|
15161
15179
|
continue;
|
|
15162
15180
|
}
|
|
15163
15181
|
const cx = lane.x + lane.width / 2;
|
|
15164
|
-
const
|
|
15165
|
-
const
|
|
15182
|
+
const \u6BB5\u306E\u82AF = rowCy.get(n.stack);
|
|
15183
|
+
const \u6BB5\u306E\u9AD8\u3055 = rowH.get(n.stack);
|
|
15184
|
+
const \u81EA\u524D\u306E\u9AD8\u3055 = n.rowMarks !== void 0;
|
|
15185
|
+
const h = n.h ?? (\u81EA\u524D\u306E\u9AD8\u3055 ? autoStorageHeight(n, size.h) : \u6BB5\u306E\u9AD8\u3055);
|
|
15186
|
+
const cy = \u6BB5\u306E\u82AF;
|
|
15166
15187
|
const w = autoRowsWidth(n, size.w);
|
|
15167
15188
|
out.push({
|
|
15168
15189
|
...n,
|
|
@@ -15491,10 +15512,25 @@ var NODE_KINDS = [
|
|
|
15491
15512
|
// 流れの始まりと終わりの印 2 種 (#560) ... 塗った丸と輪で囲んだ丸。
|
|
15492
15513
|
// 状態遷移図が使う。 印そのものが意味を持つので文字は描かない
|
|
15493
15514
|
"mark-start",
|
|
15494
|
-
"mark-end"
|
|
15515
|
+
"mark-end",
|
|
15516
|
+
// 時系列のやり取り (#578) ... 1 つの箱が図を丸ごと描く。 縦が時間で、参加者は箱を持たない
|
|
15517
|
+
"sequence-board"
|
|
15495
15518
|
];
|
|
15519
|
+
var EDGE_STYLES = ["solid", "dotted-flow", "dashed"];
|
|
15496
15520
|
var EDGE_HEAD_DEFAULT = "triangle";
|
|
15497
|
-
var EDGE_HEADS = [
|
|
15521
|
+
var EDGE_HEADS = [
|
|
15522
|
+
"none",
|
|
15523
|
+
"triangle",
|
|
15524
|
+
"diamond",
|
|
15525
|
+
"open",
|
|
15526
|
+
"crow",
|
|
15527
|
+
"one",
|
|
15528
|
+
"zero-one",
|
|
15529
|
+
"many",
|
|
15530
|
+
"zero-many"
|
|
15531
|
+
];
|
|
15532
|
+
var EDGE_HEAD_FILL_DEFAULT = "solid";
|
|
15533
|
+
var EDGE_HEAD_FILLS = ["solid", "hollow"];
|
|
15498
15534
|
|
|
15499
15535
|
// src/anim/core/easing.ts
|
|
15500
15536
|
function cubicBezier(x1, y1, x2, y2) {
|
|
@@ -15989,7 +16025,7 @@ function pathSubpath(d, progress) {
|
|
|
15989
16025
|
}
|
|
15990
16026
|
|
|
15991
16027
|
// src/render/template-fields.ts
|
|
15992
|
-
var TEXT_FIELDS = ["title", "eyebrow", "subtitle", "value", "wBind", "hBind", "visibleIf"];
|
|
16028
|
+
var TEXT_FIELDS = ["title", "eyebrow", "subtitle", "value", "wBind", "hBind", "visibleIf", "sequenceStep"];
|
|
15993
16029
|
var LIST_FIELDS = ["rows"];
|
|
15994
16030
|
var NUMERIC_FIELDS = ["opacity", "renderOffsetX", "renderOffsetY"];
|
|
15995
16031
|
var SHAPE_TEMPLATE_FIELDS = ["source", "radius", "fillProgress", "angle", "level", "rotation", "fill"];
|
|
@@ -18314,6 +18350,7 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes) {
|
|
|
18314
18350
|
if (!isRenderedNode(n)) continue;
|
|
18315
18351
|
for (const row of n.rows) {
|
|
18316
18352
|
if (DIVIDER_ONLY.test(row)) continue;
|
|
18353
|
+
if (n.rowMarks !== void 0) continue;
|
|
18317
18354
|
if (!ROW_FORMAT.test(row)) {
|
|
18318
18355
|
push("row-format", `node "${n.id}" row "${row}" \u304C "key: value" \u5F62\u5F0F\u3067\u306A\u3044`);
|
|
18319
18356
|
}
|
|
@@ -19704,7 +19741,16 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes) {
|
|
|
19704
19741
|
const maxGap = Math.max(...gaps);
|
|
19705
19742
|
const minGap = Math.min(...gaps);
|
|
19706
19743
|
const variance = maxGap - minGap;
|
|
19707
|
-
|
|
19744
|
+
const \u683C\u5B50\u306B\u7F6E\u304F = group.every((n) => n.rowMarks !== void 0);
|
|
19745
|
+
const \u7AEF\u304C\u8DB3\u308A\u3066\u3044\u308B = minGap >= requiredNearClearance("node", "node");
|
|
19746
|
+
if (\u683C\u5B50\u306B\u7F6E\u304F) {
|
|
19747
|
+
if (!\u7AEF\u304C\u8DB3\u308A\u3066\u3044\u308B) {
|
|
19748
|
+
push(
|
|
19749
|
+
"column-gap-uniform",
|
|
19750
|
+
`lane "${laneId}" \u5185 node \u9593\u306E\u7AEF\u9593 gap ${minGap.toFixed(0)} world \u304C\u4E0B\u9650 ${requiredNearClearance("node", "node")} \u3092\u5272\u308B`
|
|
19751
|
+
);
|
|
19752
|
+
}
|
|
19753
|
+
} else if (variance > COLUMN_GAP_VARIANCE_TOL) {
|
|
19708
19754
|
push(
|
|
19709
19755
|
"column-gap-uniform",
|
|
19710
19756
|
`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 +21224,42 @@ function StateDiffCard({
|
|
|
21178
21224
|
|
|
21179
21225
|
// src/render/edge-head.ts
|
|
21180
21226
|
var EDGE_HEAD_SHAPE = {
|
|
21181
|
-
|
|
21182
|
-
|
|
21183
|
-
|
|
21184
|
-
|
|
21227
|
+
// 何も描かない端。 marker 自体を出さないので `d` は読まれない
|
|
21228
|
+
none: { d: "", w: 10, h: 10, refX: 0, filled: false },
|
|
21229
|
+
triangle: { d: "M 0 0 L 10 5 L 0 10 z", w: 10, h: 10, refX: 9, filled: true },
|
|
21230
|
+
diamond: { d: "M 0 5 L 5 0 L 10 5 L 5 10 z", w: 10, h: 10, refX: 9, filled: true },
|
|
21231
|
+
open: { d: "M 1 0 L 9 5 L 1 10", w: 10, h: 10, refX: 9, filled: false },
|
|
21232
|
+
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 },
|
|
21233
|
+
// ER の端。 **箱に近い側 (x が大きい側) が個数、その外側が任意か** (#578)。
|
|
21234
|
+
//
|
|
21235
|
+
// 枠は 24 × 10 で、線の先端に合わせるのは x=24 = 箱の縁。 marker は経路の向きに回るので、
|
|
21236
|
+
// 行き先側でも出どころ側でも「箱に近い側」 が同じ端になる。
|
|
21237
|
+
//
|
|
21238
|
+
// 三又の真ん中の枝は **関係の線そのもの** が兼ねる。 別に引くと同じ所に 2 本重なって太く見える
|
|
21239
|
+
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 },
|
|
21240
|
+
"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 },
|
|
21241
|
+
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 },
|
|
21242
|
+
"zero-many": {
|
|
21243
|
+
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",
|
|
21244
|
+
w: 24,
|
|
21245
|
+
h: 10,
|
|
21246
|
+
refX: 24,
|
|
21247
|
+
scale: 1.8,
|
|
21248
|
+
filled: false
|
|
21249
|
+
}
|
|
21185
21250
|
};
|
|
21186
|
-
function edgeHeadMarkerId(tone, head, small) {
|
|
21251
|
+
function edgeHeadMarkerId(tone, head, small, fill = EDGE_HEAD_FILL_DEFAULT) {
|
|
21187
21252
|
const \u5C0F = small ? "-sm" : "";
|
|
21188
|
-
|
|
21253
|
+
const \u5857 = fill === EDGE_HEAD_FILL_DEFAULT || !EDGE_HEAD_SHAPE[head].filled ? "" : `-${fill}`;
|
|
21254
|
+
return head === EDGE_HEAD_DEFAULT && \u5857 === "" ? `cdl-arrow-${tone}${\u5C0F}` : `cdl-arrow-${tone}-${head}${\u5857}${\u5C0F}`;
|
|
21255
|
+
}
|
|
21256
|
+
function edgeHeadPaint(head, fill, color) {
|
|
21257
|
+
const \u5F62 = EDGE_HEAD_SHAPE[head];
|
|
21258
|
+
if (!\u5F62.filled) return { fill: "none", stroke: color, strokeWidth: 1.6 };
|
|
21259
|
+
if (fill === "hollow") {
|
|
21260
|
+
return { fill: "var(--cdl-node-fill, #ffffff)", stroke: color, strokeWidth: 1.4 };
|
|
21261
|
+
}
|
|
21262
|
+
return { fill: color, stroke: "none" };
|
|
21189
21263
|
}
|
|
21190
21264
|
function opacityAttr(opacity) {
|
|
21191
21265
|
return opacity < 1 ? opacity : void 0;
|
|
@@ -21200,7 +21274,13 @@ function CdlEdgeView({
|
|
|
21200
21274
|
stateValues
|
|
21201
21275
|
}) {
|
|
21202
21276
|
const color = toneColor(edge.tone);
|
|
21203
|
-
const
|
|
21277
|
+
const \u7AEF\u306E\u540D\u524D = (h, f) => {
|
|
21278
|
+
const \u5F62 = h ?? EDGE_HEAD_DEFAULT;
|
|
21279
|
+
if (\u5F62 === "none") return void 0;
|
|
21280
|
+
return hasTone(edge.tone) ? edgeHeadMarkerId(edge.tone, \u5F62, !active, f ?? EDGE_HEAD_FILL_DEFAULT) : "cdl-arrow-muted";
|
|
21281
|
+
};
|
|
21282
|
+
const marker = \u7AEF\u306E\u540D\u524D(edge.head, edge.headFill);
|
|
21283
|
+
const tailMarker = edge.tailHead === void 0 ? void 0 : \u7AEF\u306E\u540D\u524D(edge.tailHead, edge.tailHeadFill);
|
|
21204
21284
|
const style = edge.style ?? "solid";
|
|
21205
21285
|
const isDotted = style === "dotted-flow";
|
|
21206
21286
|
const isPassThrough = isDotted && Boolean(edge.dThrough);
|
|
@@ -21248,6 +21328,8 @@ function CdlEdgeView({
|
|
|
21248
21328
|
progress,
|
|
21249
21329
|
color,
|
|
21250
21330
|
marker,
|
|
21331
|
+
tailMarker,
|
|
21332
|
+
dashed: style === "dashed",
|
|
21251
21333
|
stateValues
|
|
21252
21334
|
}
|
|
21253
21335
|
),
|
|
@@ -21273,6 +21355,8 @@ function SolidEdgePath({
|
|
|
21273
21355
|
progress,
|
|
21274
21356
|
color,
|
|
21275
21357
|
marker,
|
|
21358
|
+
tailMarker,
|
|
21359
|
+
dashed,
|
|
21276
21360
|
stateValues
|
|
21277
21361
|
}) {
|
|
21278
21362
|
const visibleD = active ? pathSubpath(edge.d, progress) : edge.d;
|
|
@@ -21280,7 +21364,7 @@ function SolidEdgePath({
|
|
|
21280
21364
|
const boundWidth = edge.widthBind && stateValues ? resolveNumericAttr(edge.widthBind, stateValues, defaultWidth) : defaultWidth;
|
|
21281
21365
|
const boundStroke = edge.strokeBind && stateValues ? interpolate(edge.strokeBind, stateValues) : color;
|
|
21282
21366
|
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";
|
|
21367
|
+
const dashArray = dashed ? "10 8" : active ? boundDashOffset !== void 0 ? "8 6" : void 0 : "4 5";
|
|
21284
21368
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21285
21369
|
"path",
|
|
21286
21370
|
{
|
|
@@ -21293,7 +21377,8 @@ function SolidEdgePath({
|
|
|
21293
21377
|
strokeDasharray: dashArray,
|
|
21294
21378
|
strokeDashoffset: boundDashOffset,
|
|
21295
21379
|
strokeLinecap: "round",
|
|
21296
|
-
markerEnd: `url(#${marker})`,
|
|
21380
|
+
markerEnd: marker === void 0 ? void 0 : `url(#${marker})`,
|
|
21381
|
+
markerStart: tailMarker === void 0 ? void 0 : `url(#${tailMarker})`,
|
|
21297
21382
|
style: {
|
|
21298
21383
|
transition: "stroke 280ms ease, stroke-opacity 280ms ease, stroke-width 280ms ease"
|
|
21299
21384
|
}
|
|
@@ -21505,7 +21590,8 @@ function CardNode({ node, active }) {
|
|
|
21505
21590
|
return /* @__PURE__ */ jsxRuntime.jsx("g", { transform: `translate(${x} ${y})` });
|
|
21506
21591
|
}
|
|
21507
21592
|
const compact = isCompactBox(node.h);
|
|
21508
|
-
const
|
|
21593
|
+
const \u5C0F\u578B\u306B\u547C\u3073\u540D = compact && Boolean(node.subtitle);
|
|
21594
|
+
const titleY = compact ? \u5C0F\u578B\u306B\u547C\u3073\u540D ? node.h / 2 - 2 : node.h / 2 + 8 : 86;
|
|
21509
21595
|
const titleX = compact ? node.w / 2 : 26;
|
|
21510
21596
|
const paddingX = compact ? 16 : 52;
|
|
21511
21597
|
const availableW = node.w - paddingX;
|
|
@@ -21542,9 +21628,262 @@ function CardNode({ node, active }) {
|
|
|
21542
21628
|
children: node.title
|
|
21543
21629
|
}
|
|
21544
21630
|
),
|
|
21545
|
-
!compact && node.subtitle && /* @__PURE__ */ jsxRuntime.jsx("text", { x: 26, y: 124, fontSize: subtitleSize, fill: "var(--cdl-text-dim, #5a6270)", children: node.subtitle })
|
|
21631
|
+
!compact && node.subtitle && /* @__PURE__ */ jsxRuntime.jsx("text", { x: 26, y: 124, fontSize: subtitleSize, fill: "var(--cdl-text-dim, #5a6270)", children: node.subtitle }),
|
|
21632
|
+
\u5C0F\u578B\u306B\u547C\u3073\u540D && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21633
|
+
"text",
|
|
21634
|
+
{
|
|
21635
|
+
"data-cdl-role": "node-subtitle",
|
|
21636
|
+
x: node.w / 2,
|
|
21637
|
+
y: node.h / 2 + 24,
|
|
21638
|
+
fontSize: Math.min(subtitleSize, 18),
|
|
21639
|
+
textAnchor: "middle",
|
|
21640
|
+
fill: "var(--cdl-text-dim, #5a6270)",
|
|
21641
|
+
children: node.subtitle
|
|
21642
|
+
}
|
|
21643
|
+
)
|
|
21546
21644
|
] });
|
|
21547
21645
|
}
|
|
21646
|
+
|
|
21647
|
+
// src/kinds/sequence-board-metrics.ts
|
|
21648
|
+
var SEQ_EDGE = 16;
|
|
21649
|
+
var SEQ_ROW = 64;
|
|
21650
|
+
var SEQ_GUTTER_PAD = 40;
|
|
21651
|
+
var SEQ_GUTTER_GAP = 40;
|
|
21652
|
+
var SEQ_HEAD = 96;
|
|
21653
|
+
var SEQ_ROW_PAD = 56;
|
|
21654
|
+
var SEQ_COL_PAD = 80;
|
|
21655
|
+
var SEQ_BAND_W = 52;
|
|
21656
|
+
var SEQ_BAND_PAD = 24;
|
|
21657
|
+
var SEQ_NAME = 24;
|
|
21658
|
+
var SEQ_SUB = 20;
|
|
21659
|
+
var SEQ_LABEL = 26;
|
|
21660
|
+
var SEQ_DOT = 7;
|
|
21661
|
+
var SEQ_SELF_W = 52;
|
|
21662
|
+
var SEQ_COL_MIN = 200;
|
|
21663
|
+
var g4 = (v) => Math.round(v / 4) * 4;
|
|
21664
|
+
function sequenceStepId() {
|
|
21665
|
+
return "seq_step";
|
|
21666
|
+
}
|
|
21667
|
+
function sequenceBoardMetrics(data) {
|
|
21668
|
+
const \u540D\u5E45 = data.actors.map(
|
|
21669
|
+
(a) => Math.max(textWidth(a.name, SEQ_NAME), a.subtitle ? textWidth(a.subtitle, SEQ_SUB) : 0)
|
|
21670
|
+
);
|
|
21671
|
+
const colW = g4(Math.max(SEQ_COL_MIN, Math.max(0, ...\u540D\u5E45) + SEQ_COL_PAD));
|
|
21672
|
+
const \u8A9E\u5E45 = Math.max(0, ...data.messages.map((m) => textWidth(m.label, SEQ_LABEL)));
|
|
21673
|
+
const gutter = g4(SEQ_EDGE + SEQ_GUTTER_PAD + \u8A9E\u5E45 + SEQ_GUTTER_GAP);
|
|
21674
|
+
const headY = SEQ_EDGE + SEQ_HEAD;
|
|
21675
|
+
const rowY = (i) => headY + SEQ_ROW_PAD + i * SEQ_ROW;
|
|
21676
|
+
const \u6700\u7D42 = data.messages.length > 0 ? rowY(data.messages.length - 1) : headY;
|
|
21677
|
+
const bottom = \u6700\u7D42 + SEQ_ROW_PAD;
|
|
21678
|
+
const cx = (i) => gutter + colW / 2 + i * colW;
|
|
21679
|
+
const w = g4(cx(Math.max(0, data.actors.length - 1)) + colW / 2 + SEQ_EDGE);
|
|
21680
|
+
const h = g4(bottom + SEQ_EDGE);
|
|
21681
|
+
return { w, h, gutter, colW, headY, cx, rowY, bottom };
|
|
21682
|
+
}
|
|
21683
|
+
function SequenceBoardNode({
|
|
21684
|
+
node,
|
|
21685
|
+
stateValues
|
|
21686
|
+
}) {
|
|
21687
|
+
const data = node.sequenceData;
|
|
21688
|
+
if (!data) return /* @__PURE__ */ jsxRuntime.jsx("g", { "data-cdl-role": "sequence-board" });
|
|
21689
|
+
const m = sequenceBoardMetrics(data);
|
|
21690
|
+
const x = node.cx - node.w / 2;
|
|
21691
|
+
const y = node.cy - node.h / 2;
|
|
21692
|
+
const \u73FE\u5728 = (() => {
|
|
21693
|
+
if (!node.sequenceStep) return null;
|
|
21694
|
+
const v = Number.parseInt(interpolate(node.sequenceStep, stateValues ?? {}).trim(), 10);
|
|
21695
|
+
return Number.isFinite(v) ? v : null;
|
|
21696
|
+
})();
|
|
21697
|
+
const \u6731 = "var(--cdl-now, var(--cdl-tone-accent, #2d6a8f))";
|
|
21698
|
+
const \u58A8 = "var(--cdl-text-2, #4a5162)";
|
|
21699
|
+
const \u898B\u305F\u76EE = (i) => {
|
|
21700
|
+
if (\u73FE\u5728 === null) return { opacity: 1, color: \u6731 };
|
|
21701
|
+
if (i > \u73FE\u5728) return { opacity: 0, color: \u6731 };
|
|
21702
|
+
return i === \u73FE\u5728 ? { opacity: 1, color: \u6731 } : { opacity: 1, color: \u58A8 };
|
|
21703
|
+
};
|
|
21704
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("g", { "data-cdl-role": "sequence-board", transform: `translate(${x} ${y})`, children: [
|
|
21705
|
+
data.bands.map((b, i) => {
|
|
21706
|
+
if (\u73FE\u5728 !== null && b.from > \u73FE\u5728) return null;
|
|
21707
|
+
const \u4E0B = \u73FE\u5728 === null ? b.to : Math.min(b.to, \u73FE\u5728);
|
|
21708
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21709
|
+
"rect",
|
|
21710
|
+
{
|
|
21711
|
+
"data-cdl-role": "sequence-band",
|
|
21712
|
+
x: m.cx(b.actor) - SEQ_BAND_W / 2,
|
|
21713
|
+
y: m.rowY(b.from) - SEQ_BAND_PAD / 2,
|
|
21714
|
+
width: SEQ_BAND_W,
|
|
21715
|
+
height: m.rowY(\u4E0B) - m.rowY(b.from) + SEQ_BAND_PAD,
|
|
21716
|
+
rx: 4,
|
|
21717
|
+
fill: \u6731,
|
|
21718
|
+
fillOpacity: 0.12
|
|
21719
|
+
},
|
|
21720
|
+
`band-${i}`
|
|
21721
|
+
);
|
|
21722
|
+
}),
|
|
21723
|
+
data.actors.map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
21724
|
+
"line",
|
|
21725
|
+
{
|
|
21726
|
+
"data-cdl-role": "sequence-thread",
|
|
21727
|
+
x1: m.cx(i),
|
|
21728
|
+
y1: m.headY,
|
|
21729
|
+
x2: m.cx(i),
|
|
21730
|
+
y2: m.bottom,
|
|
21731
|
+
stroke: "var(--cdl-divider, #d4d4d8)",
|
|
21732
|
+
strokeWidth: 3
|
|
21733
|
+
},
|
|
21734
|
+
`thread-${i}`
|
|
21735
|
+
)),
|
|
21736
|
+
data.actors.map((a, i) => /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
|
|
21737
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21738
|
+
"text",
|
|
21739
|
+
{
|
|
21740
|
+
"data-cdl-role": "sequence-actor",
|
|
21741
|
+
x: m.cx(i),
|
|
21742
|
+
y: SEQ_EDGE + 44,
|
|
21743
|
+
fontSize: SEQ_NAME,
|
|
21744
|
+
fontWeight: 700,
|
|
21745
|
+
textAnchor: "middle",
|
|
21746
|
+
fill: "var(--cdl-text, #1a1f2a)",
|
|
21747
|
+
style: { fontFamily: "'JetBrains Mono', monospace" },
|
|
21748
|
+
children: a.name
|
|
21749
|
+
}
|
|
21750
|
+
),
|
|
21751
|
+
a.subtitle && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21752
|
+
"text",
|
|
21753
|
+
{
|
|
21754
|
+
"data-cdl-role": "sequence-actor-subtitle",
|
|
21755
|
+
x: m.cx(i),
|
|
21756
|
+
y: SEQ_EDGE + 76,
|
|
21757
|
+
fontSize: SEQ_SUB,
|
|
21758
|
+
textAnchor: "middle",
|
|
21759
|
+
fill: "var(--cdl-text-dim, #5a6270)",
|
|
21760
|
+
children: a.subtitle
|
|
21761
|
+
}
|
|
21762
|
+
)
|
|
21763
|
+
] }, `head-${i}`)),
|
|
21764
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21765
|
+
"line",
|
|
21766
|
+
{
|
|
21767
|
+
"data-cdl-role": "sequence-rule",
|
|
21768
|
+
x1: SEQ_EDGE,
|
|
21769
|
+
y1: m.headY,
|
|
21770
|
+
x2: m.w - SEQ_EDGE,
|
|
21771
|
+
y2: m.headY,
|
|
21772
|
+
stroke: "var(--cdl-divider, #d4d4d8)",
|
|
21773
|
+
strokeWidth: 2
|
|
21774
|
+
}
|
|
21775
|
+
),
|
|
21776
|
+
data.messages.map((msg, i) => /* @__PURE__ */ jsxRuntime.jsx(SequenceRow, { msg, yy: m.rowY(i), cx: m.cx, ...\u898B\u305F\u76EE(i) }, `msg-${i}`))
|
|
21777
|
+
] });
|
|
21778
|
+
}
|
|
21779
|
+
function SequenceRow({
|
|
21780
|
+
msg,
|
|
21781
|
+
yy,
|
|
21782
|
+
cx,
|
|
21783
|
+
opacity,
|
|
21784
|
+
color
|
|
21785
|
+
}) {
|
|
21786
|
+
const \u7834 = msg.kind === "return";
|
|
21787
|
+
const \u5857\u308B = msg.kind === "call";
|
|
21788
|
+
const \u51FA = cx(msg.from);
|
|
21789
|
+
const \u81EA\u5206\u3078 = msg.from === msg.to;
|
|
21790
|
+
const dir = \u81EA\u5206\u3078 ? 1 : Math.sign(cx(msg.to) - \u51FA);
|
|
21791
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("g", { "data-cdl-role": "sequence-message", "data-cdl-message-kind": msg.kind, opacity, children: [
|
|
21792
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21793
|
+
"text",
|
|
21794
|
+
{
|
|
21795
|
+
"data-cdl-role": "sequence-label",
|
|
21796
|
+
x: SEQ_EDGE + SEQ_GUTTER_PAD,
|
|
21797
|
+
y: yy + 8,
|
|
21798
|
+
fontSize: SEQ_LABEL,
|
|
21799
|
+
fontWeight: 500,
|
|
21800
|
+
fill: "var(--cdl-text, #1a1f2a)",
|
|
21801
|
+
children: msg.label
|
|
21802
|
+
}
|
|
21803
|
+
),
|
|
21804
|
+
\u81EA\u5206\u3078 ? (
|
|
21805
|
+
// 自分宛て。 相手がいないので糸の右へ小さく回して戻る
|
|
21806
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21807
|
+
"path",
|
|
21808
|
+
{
|
|
21809
|
+
"data-cdl-role": "sequence-line",
|
|
21810
|
+
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}`,
|
|
21811
|
+
fill: "none",
|
|
21812
|
+
stroke: color,
|
|
21813
|
+
strokeWidth: 2.5,
|
|
21814
|
+
strokeLinecap: "round"
|
|
21815
|
+
}
|
|
21816
|
+
)
|
|
21817
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
21818
|
+
"path",
|
|
21819
|
+
{
|
|
21820
|
+
"data-cdl-role": "sequence-line",
|
|
21821
|
+
d: `M ${\u51FA + dir * 12} ${yy} H ${cx(msg.to) - dir * 14}`,
|
|
21822
|
+
fill: "none",
|
|
21823
|
+
stroke: color,
|
|
21824
|
+
strokeWidth: 2.5,
|
|
21825
|
+
strokeLinecap: "round",
|
|
21826
|
+
strokeDasharray: \u7834 ? "10 8" : void 0
|
|
21827
|
+
}
|
|
21828
|
+
),
|
|
21829
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21830
|
+
Arrow,
|
|
21831
|
+
{
|
|
21832
|
+
x: \u81EA\u5206\u3078 ? \u51FA + 14 : cx(msg.to),
|
|
21833
|
+
y: \u81EA\u5206\u3078 ? yy + 16 : yy,
|
|
21834
|
+
dir: \u81EA\u5206\u3078 ? -1 : dir,
|
|
21835
|
+
filled: \u5857\u308B,
|
|
21836
|
+
color
|
|
21837
|
+
}
|
|
21838
|
+
),
|
|
21839
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21840
|
+
"circle",
|
|
21841
|
+
{
|
|
21842
|
+
"data-cdl-role": "sequence-source",
|
|
21843
|
+
cx: \u51FA,
|
|
21844
|
+
cy: \u81EA\u5206\u3078 ? yy - 16 : yy,
|
|
21845
|
+
r: SEQ_DOT,
|
|
21846
|
+
fill: color
|
|
21847
|
+
}
|
|
21848
|
+
)
|
|
21849
|
+
] });
|
|
21850
|
+
}
|
|
21851
|
+
function Arrow({
|
|
21852
|
+
x,
|
|
21853
|
+
y,
|
|
21854
|
+
dir,
|
|
21855
|
+
filled,
|
|
21856
|
+
color
|
|
21857
|
+
}) {
|
|
21858
|
+
const \u4E08 = 18;
|
|
21859
|
+
const \u534A = 8.5;
|
|
21860
|
+
const \u5148 = x;
|
|
21861
|
+
const \u80F4 = x - dir * \u4E08;
|
|
21862
|
+
return filled ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
21863
|
+
"path",
|
|
21864
|
+
{
|
|
21865
|
+
"data-cdl-role": "sequence-head",
|
|
21866
|
+
"data-cdl-head-fill": "solid",
|
|
21867
|
+
d: `M ${\u5148} ${y} L ${\u80F4} ${y - \u534A} L ${\u80F4} ${y + \u534A} Z`,
|
|
21868
|
+
fill: color,
|
|
21869
|
+
stroke: color,
|
|
21870
|
+
strokeWidth: 3,
|
|
21871
|
+
strokeLinejoin: "round"
|
|
21872
|
+
}
|
|
21873
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
21874
|
+
"path",
|
|
21875
|
+
{
|
|
21876
|
+
"data-cdl-role": "sequence-head",
|
|
21877
|
+
"data-cdl-head-fill": "open",
|
|
21878
|
+
d: `M ${\u80F4} ${y - \u534A} L ${\u5148} ${y} L ${\u80F4} ${y + \u534A}`,
|
|
21879
|
+
fill: "none",
|
|
21880
|
+
stroke: color,
|
|
21881
|
+
strokeWidth: 2.5,
|
|
21882
|
+
strokeLinecap: "round",
|
|
21883
|
+
strokeLinejoin: "round"
|
|
21884
|
+
}
|
|
21885
|
+
);
|
|
21886
|
+
}
|
|
21548
21887
|
function EventNode({
|
|
21549
21888
|
node,
|
|
21550
21889
|
active,
|
|
@@ -21646,6 +21985,29 @@ function FunctionNode({ node, active }) {
|
|
|
21646
21985
|
node.subtitle && /* @__PURE__ */ jsxRuntime.jsx("text", { x: 26, y: 126, fontSize: 20, fill: "var(--cdl-text-dim, #5a6270)", children: node.subtitle })
|
|
21647
21986
|
] });
|
|
21648
21987
|
}
|
|
21988
|
+
var ROW_GLYPH_HALF = 7;
|
|
21989
|
+
var ROW_GLYPH_CX = ROW_PAD_X_PX + ROW_GLYPH_HALF + 1;
|
|
21990
|
+
var ROW_GLYPH_LEAD = 40;
|
|
21991
|
+
var ROW_TYPE_FONT = 22;
|
|
21992
|
+
var SUBTITLE_BASELINE = 118;
|
|
21993
|
+
var SUBTITLE_FONT = 20;
|
|
21994
|
+
var UNDERLINE_DROP = 7;
|
|
21995
|
+
function RowGlyph({ mark, x, y, color }) {
|
|
21996
|
+
const \u534A = ROW_GLYPH_HALF;
|
|
21997
|
+
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`;
|
|
21998
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
21999
|
+
"path",
|
|
22000
|
+
{
|
|
22001
|
+
"data-cdl-role": "node-row-glyph",
|
|
22002
|
+
"data-cdl-row-glyph": `${mark.shape}-${mark.filled ? "filled" : "hollow"}`,
|
|
22003
|
+
d,
|
|
22004
|
+
fill: mark.filled ? color : "var(--cdl-node-fill, #ffffff)",
|
|
22005
|
+
stroke: color,
|
|
22006
|
+
strokeWidth: mark.filled ? 0 : 2.4,
|
|
22007
|
+
strokeLinejoin: "round"
|
|
22008
|
+
}
|
|
22009
|
+
);
|
|
22010
|
+
}
|
|
21649
22011
|
function StorageNode({
|
|
21650
22012
|
node,
|
|
21651
22013
|
active,
|
|
@@ -21655,7 +22017,7 @@ function StorageNode({
|
|
|
21655
22017
|
const accent = nodeAccent(node, "var(--cdl-tone-accent, #2d6a8f)");
|
|
21656
22018
|
const x = node.cx - node.w / 2;
|
|
21657
22019
|
const y = node.cy - node.h / 2;
|
|
21658
|
-
const \u540D\u524D = titlePlacement(node, { x: 26, y: STORAGE_TITLE_BASELINE, size:
|
|
22020
|
+
const \u540D\u524D = titlePlacement(node, { x: 26, y: STORAGE_TITLE_BASELINE, size: STORAGE_TITLE_FONT }, { hasEyebrow: Boolean(node.eyebrow) });
|
|
21659
22021
|
const splits = rows.map((r) => splitRow(r));
|
|
21660
22022
|
const leftMaxWidth = splits.reduce((m, s) => Math.max(m, displayWidth(s.left)), 0);
|
|
21661
22023
|
const rightColX = ROW_PAD_X_PX + leftMaxWidth * STORAGE_CHAR_ADVANCE_PX + STORAGE_COL_GAP_PX;
|
|
@@ -21663,6 +22025,8 @@ function StorageNode({
|
|
|
21663
22025
|
const leftEndDrawn = ROW_PAD_X_PX + leftMaxWidth * STORAGE_CHAR_ADVANCE_PX;
|
|
21664
22026
|
const columnDividerX = (leftEndDrawn + rightColX) / 2;
|
|
21665
22027
|
const columnDividerFits = columnDividerX <= node.w - ROW_PAD_X_PX;
|
|
22028
|
+
const \u5370\u3067\u5206\u3051\u308B = node.rowMarks !== void 0;
|
|
22029
|
+
const \u884C\u306E\u4E0B\u3052 = \u5370\u3067\u5206\u3051\u308B && node.subtitle ? SUBTITLE_ROW_SHIFT : 0;
|
|
21666
22030
|
const lastRowBottom = Math.min(
|
|
21667
22031
|
ROW_TOP_STORAGE + (rows.length - 1) * ROW_PITCH_STORAGE + (rowGlyphDepth("storage") ?? 0),
|
|
21668
22032
|
node.h - ROW_PAD_X_PX
|
|
@@ -21683,6 +22047,19 @@ function StorageNode({
|
|
|
21683
22047
|
}
|
|
21684
22048
|
),
|
|
21685
22049
|
node.eyebrow && /* @__PURE__ */ jsxRuntime.jsx("text", { x: 26, y: 38, fontSize: 18, fontWeight: 700, letterSpacing: 2, fill: accent, children: node.eyebrow }),
|
|
22050
|
+
\u5370\u3067\u5206\u3051\u308B && node.subtitle && // 呼び名は **印で分ける箱でだけ** 出す (#578)。 従来の箱は題の下に区切り線が来るので
|
|
22051
|
+
// 置き場が無い
|
|
22052
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
22053
|
+
"text",
|
|
22054
|
+
{
|
|
22055
|
+
"data-cdl-role": "node-subtitle",
|
|
22056
|
+
x: ROW_PAD_X_PX,
|
|
22057
|
+
y: SUBTITLE_BASELINE,
|
|
22058
|
+
fontSize: SUBTITLE_FONT,
|
|
22059
|
+
fill: "var(--cdl-text-dim, #5a6270)",
|
|
22060
|
+
children: node.subtitle
|
|
22061
|
+
}
|
|
22062
|
+
),
|
|
21686
22063
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21687
22064
|
"text",
|
|
21688
22065
|
{
|
|
@@ -21697,7 +22074,7 @@ function StorageNode({
|
|
|
21697
22074
|
children: node.title
|
|
21698
22075
|
}
|
|
21699
22076
|
),
|
|
21700
|
-
rows.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
22077
|
+
rows.length > 0 && !\u5370\u3067\u5206\u3051\u308B && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21701
22078
|
"line",
|
|
21702
22079
|
{
|
|
21703
22080
|
"data-cdl-role": "node-row-divider",
|
|
@@ -21709,7 +22086,7 @@ function StorageNode({
|
|
|
21709
22086
|
strokeWidth: 1.25
|
|
21710
22087
|
}
|
|
21711
22088
|
),
|
|
21712
|
-
rows.length > 0 && hasRightColumn && columnDividerFits && /* @__PURE__ */ jsxRuntime.jsx(
|
|
22089
|
+
rows.length > 0 && hasRightColumn && columnDividerFits && !\u5370\u3067\u5206\u3051\u308B && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21713
22090
|
"line",
|
|
21714
22091
|
{
|
|
21715
22092
|
"data-cdl-role": "node-column-divider",
|
|
@@ -21722,15 +22099,37 @@ function StorageNode({
|
|
|
21722
22099
|
}
|
|
21723
22100
|
),
|
|
21724
22101
|
splits.map((s, idx) => {
|
|
21725
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("g", { transform: `translate(0 ${rowBaselineY("storage", idx)})`, children: [
|
|
22102
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("g", { transform: `translate(0 ${(rowBaselineY("storage", idx) ?? 0) + \u884C\u306E\u4E0B\u3052})`, children: [
|
|
22103
|
+
\u5370\u3067\u5206\u3051\u308B && node.rowMarks?.[idx] != null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
22104
|
+
RowGlyph,
|
|
22105
|
+
{
|
|
22106
|
+
mark: node.rowMarks[idx],
|
|
22107
|
+
x: ROW_GLYPH_CX,
|
|
22108
|
+
y: -8,
|
|
22109
|
+
color: "var(--cdl-text, #1a1f2a)"
|
|
22110
|
+
}
|
|
22111
|
+
),
|
|
22112
|
+
\u5370\u3067\u5206\u3051\u308B && node.rowMarks?.[idx]?.underline === true && // 主キーの下線 (#578)。 印の 2 軸とは別の段に載るので、外部キーの山形と重ねられる
|
|
22113
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
22114
|
+
"line",
|
|
22115
|
+
{
|
|
22116
|
+
"data-cdl-role": "node-row-underline",
|
|
22117
|
+
x1: ROW_PAD_X_PX + ROW_GLYPH_LEAD,
|
|
22118
|
+
y1: UNDERLINE_DROP,
|
|
22119
|
+
x2: ROW_PAD_X_PX + ROW_GLYPH_LEAD + displayWidth(s.left) * STORAGE_CHAR_ADVANCE_PX,
|
|
22120
|
+
y2: UNDERLINE_DROP,
|
|
22121
|
+
stroke: "var(--cdl-text, #1a1f2a)",
|
|
22122
|
+
strokeWidth: 2
|
|
22123
|
+
}
|
|
22124
|
+
),
|
|
21726
22125
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21727
22126
|
"text",
|
|
21728
22127
|
{
|
|
21729
22128
|
"data-cdl-role": "node-row",
|
|
21730
22129
|
"data-cdl-row-index": idx,
|
|
21731
|
-
x: ROW_PAD_X_PX,
|
|
22130
|
+
x: \u5370\u3067\u5206\u3051\u308B ? ROW_PAD_X_PX + ROW_GLYPH_LEAD : ROW_PAD_X_PX,
|
|
21732
22131
|
fontSize: 26,
|
|
21733
|
-
fontWeight: 600,
|
|
22132
|
+
fontWeight: \u5370\u3067\u5206\u3051\u308B ? 500 : 600,
|
|
21734
22133
|
fill: "var(--cdl-text, #1a1f2a)",
|
|
21735
22134
|
style: { fontFamily: "'JetBrains Mono', monospace" },
|
|
21736
22135
|
children: s.left
|
|
@@ -21741,11 +22140,11 @@ function StorageNode({
|
|
|
21741
22140
|
{
|
|
21742
22141
|
"data-cdl-role": "node-row",
|
|
21743
22142
|
"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)",
|
|
22143
|
+
x: \u5370\u3067\u5206\u3051\u308B ? node.w - ROW_PAD_X_PX : rightColX,
|
|
22144
|
+
fontSize: \u5370\u3067\u5206\u3051\u308B ? ROW_TYPE_FONT : 26,
|
|
22145
|
+
fontWeight: \u5370\u3067\u5206\u3051\u308B ? 500 : highlightRows ? 700 : 600,
|
|
22146
|
+
textAnchor: \u5370\u3067\u5206\u3051\u308B ? "end" : "start",
|
|
22147
|
+
fill: \u5370\u3067\u5206\u3051\u308B ? "var(--cdl-text-dim, #5a6270)" : highlightRows ? accent : "var(--cdl-text, #1a1f2a)",
|
|
21749
22148
|
style: { fontFamily: "'JetBrains Mono', monospace" },
|
|
21750
22149
|
children: s.right
|
|
21751
22150
|
}
|
|
@@ -28101,6 +28500,9 @@ function CdlNodeView({
|
|
|
28101
28500
|
return /* @__PURE__ */ jsxRuntime.jsx(EventNode, { node: resolvedNode, active, progress });
|
|
28102
28501
|
case "card":
|
|
28103
28502
|
return /* @__PURE__ */ jsxRuntime.jsx(CardNode, { node: resolvedNode, active });
|
|
28503
|
+
// 時系列のやり取り (#578)。 1 つの箱が図を丸ごと描く = 縦が時間で、参加者は箱を持たない
|
|
28504
|
+
case "sequence-board":
|
|
28505
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SequenceBoardNode, { node: resolvedNode, stateValues });
|
|
28104
28506
|
// 図表 9 種は payload が `{signal}` を取れるので stateValues を渡す
|
|
28105
28507
|
// (`render/payload-binding.ts` が描画直前に解決する)。 取れる欄は種別で違い、
|
|
28106
28508
|
// 数と語を取る 7 種に対し、mind-map / tree-hierarchy は **名前だけ** を取る (#467)。
|
|
@@ -28428,36 +28830,47 @@ function CdlStage({
|
|
|
28428
28830
|
/* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
|
|
28429
28831
|
Object.entries(TONE).flatMap(
|
|
28430
28832
|
([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",
|
|
28833
|
+
([suffix, size]) => EDGE_HEADS.flatMap(
|
|
28834
|
+
(head) => (
|
|
28835
|
+
// 塗り方は形と別の軸 (#578)。 塗らない形では 2 つが同じ名前に畳まれるので、
|
|
28836
|
+
// `edgeHeadMarkerId` が返す名前で重複を外す
|
|
28837
|
+
EDGE_HEAD_FILLS.map((fill) => {
|
|
28838
|
+
const \u5F62 = EDGE_HEAD_SHAPE[head];
|
|
28839
|
+
const id = edgeHeadMarkerId(tone, head, suffix === "-sm", fill);
|
|
28840
|
+
if (\u5F62.d === "") return null;
|
|
28841
|
+
if (fill !== EDGE_HEAD_FILL_DEFAULT && !\u5F62.filled) return null;
|
|
28842
|
+
const \u5857 = edgeHeadPaint(head, fill, color);
|
|
28843
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
28844
|
+
"marker",
|
|
28446
28845
|
{
|
|
28447
|
-
|
|
28448
|
-
|
|
28449
|
-
|
|
28450
|
-
|
|
28451
|
-
|
|
28452
|
-
|
|
28453
|
-
|
|
28454
|
-
|
|
28455
|
-
|
|
28456
|
-
|
|
28457
|
-
|
|
28458
|
-
|
|
28459
|
-
|
|
28460
|
-
|
|
28846
|
+
id,
|
|
28847
|
+
viewBox: `0 0 ${\u5F62.w} ${\u5F62.h}`,
|
|
28848
|
+
refX: \u5F62.refX,
|
|
28849
|
+
refY: \u5F62.h / 2,
|
|
28850
|
+
markerWidth: size * (\u5F62.scale ?? 1) * \u5F62.w / \u5F62.h,
|
|
28851
|
+
markerHeight: size * (\u5F62.scale ?? 1),
|
|
28852
|
+
markerUnits: "userSpaceOnUse",
|
|
28853
|
+
orient: "auto-start-reverse",
|
|
28854
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
28855
|
+
"path",
|
|
28856
|
+
{
|
|
28857
|
+
"data-cdl-role": "edge-arrowhead",
|
|
28858
|
+
"data-cdl-edge-head": head,
|
|
28859
|
+
"data-cdl-edge-head-fill": fill,
|
|
28860
|
+
d: \u5F62.d,
|
|
28861
|
+
fill: \u5857.fill,
|
|
28862
|
+
stroke: \u5857.stroke,
|
|
28863
|
+
strokeWidth: \u5857.strokeWidth,
|
|
28864
|
+
strokeLinecap: \u5857.strokeWidth === void 0 ? void 0 : "round",
|
|
28865
|
+
strokeLinejoin: \u5857.strokeWidth === void 0 ? void 0 : "round"
|
|
28866
|
+
}
|
|
28867
|
+
)
|
|
28868
|
+
},
|
|
28869
|
+
id
|
|
28870
|
+
);
|
|
28871
|
+
})
|
|
28872
|
+
)
|
|
28873
|
+
)
|
|
28461
28874
|
)
|
|
28462
28875
|
),
|
|
28463
28876
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -29146,65 +29559,58 @@ function flow(preset) {
|
|
|
29146
29559
|
};
|
|
29147
29560
|
return api;
|
|
29148
29561
|
}
|
|
29562
|
+
var SEQUENCE_MESSAGE_LOOK = {
|
|
29563
|
+
call: { style: "solid", head: "triangle" },
|
|
29564
|
+
return: { style: "dashed", head: "open" },
|
|
29565
|
+
fire: { style: "solid", head: "open" }
|
|
29566
|
+
};
|
|
29149
29567
|
function sequence(preset) {
|
|
29150
|
-
const laneW = preset.laneWidth ?? 340;
|
|
29151
29568
|
const tone = preset.defaultTone ?? "accent";
|
|
29152
|
-
const style = preset.defaultStyle ?? "solid";
|
|
29153
29569
|
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 });
|
|
29570
|
+
const \u9762\u3005 = preset.actors.map(
|
|
29571
|
+
(a) => typeof a === "string" ? { name: a } : { name: a.name, ...a.subtitle ? { subtitle: a.subtitle } : {} }
|
|
29572
|
+
);
|
|
29573
|
+
const \u756A\u53F7 = /* @__PURE__ */ new Map();
|
|
29574
|
+
\u9762\u3005.forEach((a, i) => {
|
|
29575
|
+
\u756A\u53F7.set(a.name, i);
|
|
29576
|
+
\u756A\u53F7.set(slugify(a.name) || `actor-${i}`, i);
|
|
29167
29577
|
});
|
|
29168
|
-
const
|
|
29169
|
-
|
|
29578
|
+
const \u8A00\u3065\u3066 = [];
|
|
29579
|
+
const \u8A9E = /* @__PURE__ */ new Map();
|
|
29170
29580
|
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;
|
|
29581
|
+
step(s2) {
|
|
29582
|
+
const from = \u756A\u53F7.get(s2.from) ?? 0;
|
|
29583
|
+
const to = \u756A\u53F7.get(s2.to) ?? 0;
|
|
29584
|
+
const kind = s2.kind ?? ((s2.style ?? preset.defaultStyle) === "dotted-flow" ? "return" : "call");
|
|
29585
|
+
\u8A00\u3065\u3066.push({ label: s2.label, from, to, kind });
|
|
29586
|
+
if (s2.sub) \u8A9E.set(\u8A00\u3065\u3066.length - 1, s2.sub);
|
|
29193
29587
|
return api;
|
|
29194
29588
|
},
|
|
29195
29589
|
build() {
|
|
29196
|
-
const
|
|
29197
|
-
|
|
29198
|
-
|
|
29199
|
-
|
|
29200
|
-
|
|
29201
|
-
|
|
29202
|
-
|
|
29590
|
+
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) => {
|
|
29591
|
+
const \u51FA\u756A = \u8A00\u3065\u3066.map((m2, idx) => m2.from === i || m2.to === i ? idx : -1).filter((idx) => idx >= 0);
|
|
29592
|
+
return \u51FA\u756A.length > 0 ? { actor: i, from: \u51FA\u756A[0], to: \u51FA\u756A[\u51FA\u756A.length - 1] } : null;
|
|
29593
|
+
}).filter((x) => x !== null);
|
|
29594
|
+
const data = { actors: \u9762\u3005, messages: \u8A00\u3065\u3066, bands: \u5E2F };
|
|
29595
|
+
const m = sequenceBoardMetrics(data);
|
|
29596
|
+
const laneId = "seq";
|
|
29597
|
+
b.lane(laneId, { width: m.w + LANE_PAD_MIN * 2 });
|
|
29598
|
+
b.node(preset.id, {
|
|
29599
|
+
lane: laneId,
|
|
29600
|
+
stack: 0,
|
|
29601
|
+
kind: "sequence-board",
|
|
29602
|
+
w: m.w,
|
|
29603
|
+
h: m.h,
|
|
29604
|
+
title: "",
|
|
29605
|
+
sequenceData: data,
|
|
29606
|
+
// 段が進むと濃さが移る。 書かない図では全部を濃く出す
|
|
29607
|
+
sequenceStep: `{${sequenceStepId()}}`,
|
|
29608
|
+
tone
|
|
29203
29609
|
});
|
|
29204
29610
|
b.phase(
|
|
29205
|
-
"
|
|
29611
|
+
"sequence",
|
|
29206
29612
|
{ duration: 2400, title: preset.topic, body: "sequence \u306E\u5168 message \u3092\u6642\u7CFB\u5217\u5C55\u958B\u3002" },
|
|
29207
|
-
(p) => p.activate(
|
|
29613
|
+
(p) => p.activate(preset.id).badge("sequence")
|
|
29208
29614
|
);
|
|
29209
29615
|
return b.build();
|
|
29210
29616
|
}
|
|
@@ -29272,6 +29678,14 @@ function topology(preset) {
|
|
|
29272
29678
|
};
|
|
29273
29679
|
return api;
|
|
29274
29680
|
}
|
|
29681
|
+
var ER_CARDINALITY_HEAD = {
|
|
29682
|
+
"1:1": { tail: "one", head: "one" },
|
|
29683
|
+
"1:N": { tail: "one", head: "many" },
|
|
29684
|
+
"N:1": { tail: "many", head: "one" },
|
|
29685
|
+
"N:M": { tail: "many", head: "many" },
|
|
29686
|
+
"0..1": { tail: "one", head: "zero-one" },
|
|
29687
|
+
"1..*": { tail: "one", head: "many" }
|
|
29688
|
+
};
|
|
29275
29689
|
function er(preset) {
|
|
29276
29690
|
const entityW = resolveStorageBoxW(preset.entityWidth, "er", "entityWidth");
|
|
29277
29691
|
const tone = preset.defaultTone ?? "info";
|
|
@@ -29282,7 +29696,27 @@ function er(preset) {
|
|
|
29282
29696
|
const api = {
|
|
29283
29697
|
entity(e) {
|
|
29284
29698
|
const laneId = `lane-${e.id}`;
|
|
29285
|
-
const
|
|
29699
|
+
const \u9375 = (e.columns ?? []).filter((c) => c.pk === true);
|
|
29700
|
+
const \u5024 = (e.columns ?? []).filter((c) => c.pk !== true);
|
|
29701
|
+
const \u884C = [];
|
|
29702
|
+
const \u5370 = [];
|
|
29703
|
+
const \u8DB3\u3059 = (c) => {
|
|
29704
|
+
\u884C.push(`${c.name}: ${c.type}`);
|
|
29705
|
+
\u5370.push({
|
|
29706
|
+
shape: c.fk === true ? "chevron" : "square",
|
|
29707
|
+
filled: c.optional !== true,
|
|
29708
|
+
...c.pk === true ? { underline: true } : {}
|
|
29709
|
+
});
|
|
29710
|
+
};
|
|
29711
|
+
\u9375.forEach(\u8DB3\u3059);
|
|
29712
|
+
if (\u9375.length > 0 && \u5024.length > 0) {
|
|
29713
|
+
\u884C.push("");
|
|
29714
|
+
\u5370.push(null);
|
|
29715
|
+
}
|
|
29716
|
+
\u5024.forEach(\u8DB3\u3059);
|
|
29717
|
+
const \u8A2D\u8A08\u306E\u5F62 = \u884C.length > 0;
|
|
29718
|
+
const rows = \u8A2D\u8A08\u306E\u5F62 ? \u884C : e.rows ?? [];
|
|
29719
|
+
const boxW = fitRowsWidth(entityW, rows);
|
|
29286
29720
|
b.lane(laneId, { width: boxLaneW(boxW) });
|
|
29287
29721
|
b.node(e.id, {
|
|
29288
29722
|
lane: laneId,
|
|
@@ -29290,8 +29724,12 @@ function er(preset) {
|
|
|
29290
29724
|
kind: "storage",
|
|
29291
29725
|
w: boxW,
|
|
29292
29726
|
title: e.title,
|
|
29293
|
-
|
|
29294
|
-
|
|
29727
|
+
// 種類の札は設計の形では出さない (#578)。 「エンティティ」 と書いた札は全ての箱に
|
|
29728
|
+
// 同じ字が並ぶだけで、代わりに表の呼び名を題の下へ置く
|
|
29729
|
+
...\u8A2D\u8A08\u306E\u5F62 ? {} : { eyebrow: "\u30A8\u30F3\u30C6\u30A3\u30C6\u30A3" },
|
|
29730
|
+
...\u8A2D\u8A08\u306E\u5F62 && e.subtitle ? { subtitle: e.subtitle } : {},
|
|
29731
|
+
rows,
|
|
29732
|
+
...\u8A2D\u8A08\u306E\u5F62 ? { rowMarks: \u5370 } : {}
|
|
29295
29733
|
});
|
|
29296
29734
|
entities.push(e.id);
|
|
29297
29735
|
phaseActivate.push(e.id);
|
|
@@ -29300,14 +29738,19 @@ function er(preset) {
|
|
|
29300
29738
|
relation(r) {
|
|
29301
29739
|
const currentIdx = relIdx++;
|
|
29302
29740
|
const edgeId = `rel-${currentIdx}-${r.from}-${r.to}`;
|
|
29303
|
-
const label = r.label ?? r.cardinality;
|
|
29304
|
-
const
|
|
29741
|
+
const label = r.label ?? r.cardinality ?? "";
|
|
29742
|
+
const \u5370\u304C\u793A\u3059 = r.tailHead !== void 0 || r.head !== void 0;
|
|
29743
|
+
const sub = r.label && r.cardinality && !\u5370\u304C\u793A\u3059 ? r.cardinality : void 0;
|
|
29744
|
+
const \u65E2\u5B9A = r.cardinality ? ER_CARDINALITY_HEAD[r.cardinality] : void 0;
|
|
29305
29745
|
b.edge(r.from, r.to, {
|
|
29306
29746
|
id: edgeId,
|
|
29307
29747
|
label,
|
|
29308
29748
|
...sub ? { sub } : {},
|
|
29309
29749
|
tone: r.tone ?? tone,
|
|
29310
|
-
style: "solid"
|
|
29750
|
+
style: r.style ?? "solid",
|
|
29751
|
+
// 端の印は両端に立つ (#578)。 箱に近い側が個数、その外側が任意か
|
|
29752
|
+
...r.head ?? \u65E2\u5B9A?.head ? { head: r.head ?? \u65E2\u5B9A.head } : {},
|
|
29753
|
+
...r.tailHead ?? \u65E2\u5B9A?.tail ? { tailHead: r.tailHead ?? \u65E2\u5B9A.tail } : {}
|
|
29311
29754
|
});
|
|
29312
29755
|
phaseActivate.push(edgeId);
|
|
29313
29756
|
return api;
|
|
@@ -29323,49 +29766,114 @@ function er(preset) {
|
|
|
29323
29766
|
};
|
|
29324
29767
|
return api;
|
|
29325
29768
|
}
|
|
29769
|
+
var MARK_BOX = 96;
|
|
29770
|
+
var FSM_ACTION_MARK = {
|
|
29771
|
+
entry: { shape: "chevron", filled: true },
|
|
29772
|
+
exit: { shape: "chevron", filled: false },
|
|
29773
|
+
do: { shape: "square", filled: true },
|
|
29774
|
+
internal: { shape: "square", filled: false }
|
|
29775
|
+
};
|
|
29326
29776
|
function stateMachine(preset) {
|
|
29327
29777
|
const stateW = resolveStateW(preset.stateWidth, "stateMachine");
|
|
29328
|
-
const laneW = boxLaneW(stateW);
|
|
29329
29778
|
const tone = preset.defaultTone ?? "accent";
|
|
29330
29779
|
const b = diagram(preset.id, { topic: preset.topic });
|
|
29331
29780
|
const phaseActivate = [];
|
|
29332
|
-
let transIdx = 0;
|
|
29333
29781
|
const stateOrder = /* @__PURE__ */ new Map();
|
|
29782
|
+
const \u72B6\u614B = [];
|
|
29783
|
+
const \u7BC0\u70B9 = [];
|
|
29784
|
+
const \u9077\u79FB = [];
|
|
29785
|
+
const \u4E26\u3073 = [];
|
|
29334
29786
|
const api = {
|
|
29335
29787
|
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
|
-
});
|
|
29788
|
+
\u4E26\u3073.push({ \u7A2E: "\u72B6\u614B", i: \u72B6\u614B.length });
|
|
29789
|
+
\u72B6\u614B.push(s);
|
|
29347
29790
|
stateOrder.set(s.id, stateOrder.size);
|
|
29348
|
-
|
|
29791
|
+
return api;
|
|
29792
|
+
},
|
|
29793
|
+
mark(m) {
|
|
29794
|
+
\u4E26\u3073.push({ \u7A2E: "\u7BC0\u70B9", i: \u7BC0\u70B9.length });
|
|
29795
|
+
\u7BC0\u70B9.push(m);
|
|
29796
|
+
stateOrder.set(m.id, stateOrder.size);
|
|
29349
29797
|
return api;
|
|
29350
29798
|
},
|
|
29351
29799
|
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);
|
|
29800
|
+
\u9077\u79FB.push(t);
|
|
29366
29801
|
return api;
|
|
29367
29802
|
},
|
|
29368
29803
|
build() {
|
|
29804
|
+
const \u8A2D\u8A08\u306E\u5F62 = \u72B6\u614B.some((s) => s.actions !== void 0 || s.subtitle !== void 0) || \u7BC0\u70B9.length > 0;
|
|
29805
|
+
const \u683C\u5B50 = \u72B6\u614B.some((s) => s.col !== void 0) || \u7BC0\u70B9.some((m) => m.col !== void 0);
|
|
29806
|
+
const \u4E2D\u8EAB = \u72B6\u614B.map((s) => {
|
|
29807
|
+
const \u884C = (s.actions ?? []).map((a) => a.note ? `${a.label}: ${a.note}` : a.label);
|
|
29808
|
+
const \u5370 = (s.actions ?? []).map((a) => FSM_ACTION_MARK[a.when]);
|
|
29809
|
+
const laneId = \u683C\u5B50 && s.col !== void 0 ? `col-${s.col}` : `lane-${s.id}`;
|
|
29810
|
+
const boxW = \u8A2D\u8A08\u306E\u5F62 ? fitRowsWidth(stateW, \u884C) : stateW;
|
|
29811
|
+
return { s, \u884C, \u5370, laneId, boxW, stack: \u683C\u5B50 ? s.row ?? 0 : 0 };
|
|
29812
|
+
});
|
|
29813
|
+
const \u7BC0\u70B9\u306E\u4E2D\u8EAB = \u7BC0\u70B9.map((m) => ({
|
|
29814
|
+
m,
|
|
29815
|
+
laneId: \u683C\u5B50 && m.col !== void 0 ? `col-${m.col}` : `lane-${m.id}`,
|
|
29816
|
+
stack: \u683C\u5B50 ? m.row ?? 0 : 0
|
|
29817
|
+
}));
|
|
29818
|
+
const \u5E2F\u5E45 = /* @__PURE__ */ new Map();
|
|
29819
|
+
for (const c of \u4E2D\u8EAB) \u5E2F\u5E45.set(c.laneId, Math.max(\u5E2F\u5E45.get(c.laneId) ?? 0, c.boxW));
|
|
29820
|
+
for (const c of \u7BC0\u70B9\u306E\u4E2D\u8EAB) \u5E2F\u5E45.set(c.laneId, Math.max(\u5E2F\u5E45.get(c.laneId) ?? 0, MARK_BOX));
|
|
29821
|
+
const \u6E08 = /* @__PURE__ */ new Set();
|
|
29822
|
+
const \u5E2F\u3092\u4F5C\u308B = (laneId) => {
|
|
29823
|
+
if (\u6E08.has(laneId)) return;
|
|
29824
|
+
\u6E08.add(laneId);
|
|
29825
|
+
b.lane(laneId, { width: boxLaneW(\u5E2F\u5E45.get(laneId) ?? stateW) });
|
|
29826
|
+
};
|
|
29827
|
+
for (const c of \u7BC0\u70B9\u306E\u4E2D\u8EAB) if (c.stack === 0) \u5E2F\u3092\u4F5C\u308B(c.laneId);
|
|
29828
|
+
for (const c of \u4E2D\u8EAB) \u5E2F\u3092\u4F5C\u308B(c.laneId);
|
|
29829
|
+
for (const c of \u7BC0\u70B9\u306E\u4E2D\u8EAB) \u5E2F\u3092\u4F5C\u308B(c.laneId);
|
|
29830
|
+
for (const o of \u4E26\u3073) {
|
|
29831
|
+
if (o.\u7A2E === "\u7BC0\u70B9") {
|
|
29832
|
+
const c2 = \u7BC0\u70B9\u306E\u4E2D\u8EAB[o.i];
|
|
29833
|
+
b.node(c2.m.id, {
|
|
29834
|
+
lane: c2.laneId,
|
|
29835
|
+
stack: c2.stack,
|
|
29836
|
+
kind: c2.m.kind === "start" ? "mark-start" : "mark-end",
|
|
29837
|
+
w: MARK_BOX,
|
|
29838
|
+
h: MARK_BOX,
|
|
29839
|
+
title: ""
|
|
29840
|
+
});
|
|
29841
|
+
phaseActivate.push(c2.m.id);
|
|
29842
|
+
continue;
|
|
29843
|
+
}
|
|
29844
|
+
const c = \u4E2D\u8EAB[o.i];
|
|
29845
|
+
const eyebrow = \u7BC0\u70B9.length > 0 ? void 0 : c.s.initial ? "\u521D\u671F" : c.s.final ? "\u6700\u7D42" : "\u72B6\u614B";
|
|
29846
|
+
b.node(c.s.id, {
|
|
29847
|
+
lane: c.laneId,
|
|
29848
|
+
stack: c.stack,
|
|
29849
|
+
kind: \u8A2D\u8A08\u306E\u5F62 ? "storage" : "card",
|
|
29850
|
+
w: c.boxW,
|
|
29851
|
+
title: c.s.title,
|
|
29852
|
+
...eyebrow ? { eyebrow } : {},
|
|
29853
|
+
...c.s.subtitle ? { subtitle: c.s.subtitle } : {},
|
|
29854
|
+
// 行を持たない状態でも欄を書く (#578)。 書かないとその箱だけ従来の意匠に落ち、
|
|
29855
|
+
// 呼び名が消える
|
|
29856
|
+
...\u8A2D\u8A08\u306E\u5F62 ? { rows: c.\u884C, rowMarks: c.\u5370 } : {}
|
|
29857
|
+
});
|
|
29858
|
+
phaseActivate.push(c.s.id);
|
|
29859
|
+
}
|
|
29860
|
+
\u9077\u79FB.forEach((t, currentIdx) => {
|
|
29861
|
+
const edgeId = `t${currentIdx}-${t.from}-${t.to}`;
|
|
29862
|
+
const fromIdx = stateOrder.get(t.from) ?? 0;
|
|
29863
|
+
const toIdx = stateOrder.get(t.to) ?? 0;
|
|
29864
|
+
const isBack = toIdx < fromIdx;
|
|
29865
|
+
b.edge(t.from, t.to, {
|
|
29866
|
+
id: edgeId,
|
|
29867
|
+
label: t.trigger,
|
|
29868
|
+
...t.guard ? { sub: t.guard } : {},
|
|
29869
|
+
tone: t.tone ?? tone,
|
|
29870
|
+
style: "solid",
|
|
29871
|
+
// 遷移の印は 1 種類だけ = 実線に開いた矢 (#578)。 線と印が分かれず、違いは語の中に入る
|
|
29872
|
+
head: t.head ?? "open",
|
|
29873
|
+
...isBack ? { routing: "back-detour" } : {}
|
|
29874
|
+
});
|
|
29875
|
+
phaseActivate.push(edgeId);
|
|
29876
|
+
});
|
|
29369
29877
|
b.phase(
|
|
29370
29878
|
"fsm",
|
|
29371
29879
|
{ duration: 2400, title: preset.topic, body: "FSM \u306E\u5168 state + transition \u3092 visible \u5316\u3002" },
|
|
@@ -29429,72 +29937,103 @@ function infrastructure(preset) {
|
|
|
29429
29937
|
};
|
|
29430
29938
|
return api;
|
|
29431
29939
|
}
|
|
29432
|
-
var
|
|
29433
|
-
extends: "triangle",
|
|
29434
|
-
implements: "triangle",
|
|
29435
|
-
|
|
29436
|
-
|
|
29437
|
-
|
|
29940
|
+
var CLASS_RELATION_LOOK = {
|
|
29941
|
+
extends: { head: "triangle", fill: "hollow", tailHead: "none", tailFill: "solid", style: "solid" },
|
|
29942
|
+
implements: { head: "triangle", fill: "hollow", tailHead: "none", tailFill: "solid", style: "dashed" },
|
|
29943
|
+
aggregates: { head: "none", fill: "solid", tailHead: "diamond", tailFill: "hollow", style: "solid" },
|
|
29944
|
+
composes: { head: "none", fill: "solid", tailHead: "diamond", tailFill: "solid", style: "solid" },
|
|
29945
|
+
associates: { head: "open", fill: "solid", tailHead: "none", tailFill: "solid", style: "solid" },
|
|
29946
|
+
uses: { head: "open", fill: "solid", tailHead: "none", tailFill: "solid", style: "dashed" }
|
|
29438
29947
|
};
|
|
29948
|
+
Object.fromEntries(
|
|
29949
|
+
Object.entries(CLASS_RELATION_LOOK).map(([k, v]) => [k, v.head])
|
|
29950
|
+
);
|
|
29951
|
+
function isPublic(row) {
|
|
29952
|
+
return !row.startsWith("-") && !row.startsWith("#");
|
|
29953
|
+
}
|
|
29954
|
+
function stripAccess(row) {
|
|
29955
|
+
const \u672C\u4F53 = isPublic(row) && !row.startsWith("+") ? row : row.slice(1);
|
|
29956
|
+
return \u672C\u4F53.replace("()", "");
|
|
29957
|
+
}
|
|
29439
29958
|
function classDiagram(preset) {
|
|
29440
29959
|
const classW = resolveStorageBoxW(preset.classWidth, "classDiagram", "classWidth");
|
|
29441
29960
|
const tone = preset.defaultTone ?? "info";
|
|
29442
29961
|
const b = diagram(preset.id, { topic: preset.topic });
|
|
29443
29962
|
const classes = [];
|
|
29444
29963
|
const phaseActivate = [];
|
|
29445
|
-
|
|
29964
|
+
const \u7BB1 = [];
|
|
29965
|
+
const \u95A2\u4FC2 = [];
|
|
29446
29966
|
const api = {
|
|
29447
29967
|
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);
|
|
29968
|
+
\u7BB1.push(c);
|
|
29470
29969
|
return api;
|
|
29471
29970
|
},
|
|
29472
29971
|
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);
|
|
29972
|
+
\u95A2\u4FC2.push(r);
|
|
29495
29973
|
return api;
|
|
29496
29974
|
},
|
|
29497
29975
|
build() {
|
|
29976
|
+
const \u4E2D\u8EAB = \u7BB1.map((c) => {
|
|
29977
|
+
const rows = [];
|
|
29978
|
+
const rowMarks = [];
|
|
29979
|
+
for (const a of c.attributes ?? []) {
|
|
29980
|
+
rows.push(stripAccess(a));
|
|
29981
|
+
rowMarks.push({ shape: "square", filled: isPublic(a) });
|
|
29982
|
+
}
|
|
29983
|
+
if ((c.attributes?.length ?? 0) > 0 && (c.methods?.length ?? 0) > 0) {
|
|
29984
|
+
rows.push("");
|
|
29985
|
+
rowMarks.push(null);
|
|
29986
|
+
}
|
|
29987
|
+
for (const m of c.methods ?? []) {
|
|
29988
|
+
rows.push(stripAccess(m));
|
|
29989
|
+
rowMarks.push({ shape: "chevron", filled: isPublic(m) });
|
|
29990
|
+
}
|
|
29991
|
+
const boxW = fitRowsWidth(classW, rows);
|
|
29992
|
+
const laneId = c.col !== void 0 ? `col-${c.col}` : `lane-${c.id}`;
|
|
29993
|
+
return { c, rows, rowMarks, boxW, laneId, stack: c.col !== void 0 ? c.row ?? 0 : 0 };
|
|
29994
|
+
});
|
|
29995
|
+
const \u5E2F\u5E45 = /* @__PURE__ */ new Map();
|
|
29996
|
+
for (const m of \u4E2D\u8EAB) \u5E2F\u5E45.set(m.laneId, Math.max(\u5E2F\u5E45.get(m.laneId) ?? 0, m.boxW));
|
|
29997
|
+
const \u6E08 = /* @__PURE__ */ new Set();
|
|
29998
|
+
for (const m of \u4E2D\u8EAB) {
|
|
29999
|
+
if (\u6E08.has(m.laneId)) continue;
|
|
30000
|
+
\u6E08.add(m.laneId);
|
|
30001
|
+
b.lane(m.laneId, { width: boxLaneW(\u5E2F\u5E45.get(m.laneId) ?? m.boxW) });
|
|
30002
|
+
}
|
|
30003
|
+
for (const m of \u4E2D\u8EAB) {
|
|
30004
|
+
b.node(m.c.id, {
|
|
30005
|
+
lane: m.laneId,
|
|
30006
|
+
stack: m.stack,
|
|
30007
|
+
kind: "storage",
|
|
30008
|
+
w: m.boxW,
|
|
30009
|
+
title: m.c.title,
|
|
30010
|
+
// 種類の札は **書いた時だけ** 出す (#578)。 「クラス」 と書いた札は箱がクラスで
|
|
30011
|
+
// あることしか言わず、図の中の全ての箱に同じ字が並ぶ
|
|
30012
|
+
...m.c.stereotype ? { eyebrow: m.c.stereotype } : {},
|
|
30013
|
+
...m.rows.length > 0 ? { rows: m.rows, rowMarks: m.rowMarks } : {}
|
|
30014
|
+
});
|
|
30015
|
+
classes.push(m.c.id);
|
|
30016
|
+
phaseActivate.push(m.c.id);
|
|
30017
|
+
}
|
|
30018
|
+
\u95A2\u4FC2.forEach((r, currentIdx) => {
|
|
30019
|
+
const edgeId = `cr-${currentIdx}-${r.from}-${r.to}`;
|
|
30020
|
+
const \u898B\u305F\u76EE = CLASS_RELATION_LOOK[r.type];
|
|
30021
|
+
b.edge(r.from, r.to, {
|
|
30022
|
+
id: edgeId,
|
|
30023
|
+
label: r.label ?? r.type,
|
|
30024
|
+
...r.cardinality ? { sub: r.cardinality } : {},
|
|
30025
|
+
tone: r.tone ?? tone,
|
|
30026
|
+
// 関係の種類から線と端の形を決める (cdl#574 / #578)。 書いた値が勝つ
|
|
30027
|
+
style: r.style ?? \u898B\u305F\u76EE.style,
|
|
30028
|
+
head: r.head ?? \u898B\u305F\u76EE.head,
|
|
30029
|
+
headFill: r.headFill ?? \u898B\u305F\u76EE.fill,
|
|
30030
|
+
tailHead: r.tailHead ?? \u898B\u305F\u76EE.tailHead,
|
|
30031
|
+
tailHeadFill: \u898B\u305F\u76EE.tailFill
|
|
30032
|
+
// CAR-531 SSOT ... label の分散は engine 側 (LABEL_INIT_CLEARANCE + fan offset) に
|
|
30033
|
+
// 一任する。 author 指定 ±60 は engine 分散と二重発火して label が大きく離れる
|
|
30034
|
+
});
|
|
30035
|
+
phaseActivate.push(edgeId);
|
|
30036
|
+
});
|
|
29498
30037
|
b.phase(
|
|
29499
30038
|
"class",
|
|
29500
30039
|
{ duration: 2400, title: preset.topic, body: "UML class \u5168 class + relation \u3092 visible \u5316\u3002" },
|
|
@@ -30009,6 +30548,7 @@ exports.ARROW_ENDPOINT_CENTER_TOL = ARROW_ENDPOINT_CENTER_TOL;
|
|
|
30009
30548
|
exports.CHAIN_MIN_CLEARANCE = CHAIN_MIN_CLEARANCE;
|
|
30010
30549
|
exports.CHAIN_SHIFT_MAX_ACCUMULATED = CHAIN_SHIFT_MAX_ACCUMULATED;
|
|
30011
30550
|
exports.CHAIN_SHIFT_MAX_ITER = CHAIN_SHIFT_MAX_ITER;
|
|
30551
|
+
exports.CLASS_RELATION_LOOK = CLASS_RELATION_LOOK;
|
|
30012
30552
|
exports.CLEARANCE_LABEL_LABEL = CLEARANCE_LABEL_LABEL;
|
|
30013
30553
|
exports.CLEARANCE_LANE_LABEL = CLEARANCE_LANE_LABEL;
|
|
30014
30554
|
exports.CLEARANCE_NODE_LABEL = CLEARANCE_NODE_LABEL;
|
|
@@ -30022,10 +30562,15 @@ exports.DIST_LABEL_PATH_MAX = DIST_LABEL_PATH_MAX;
|
|
|
30022
30562
|
exports.DIST_LABEL_PATH_MIN = DIST_LABEL_PATH_MIN;
|
|
30023
30563
|
exports.EDGE_HEADS = EDGE_HEADS;
|
|
30024
30564
|
exports.EDGE_HEAD_DEFAULT = EDGE_HEAD_DEFAULT;
|
|
30565
|
+
exports.EDGE_HEAD_FILLS = EDGE_HEAD_FILLS;
|
|
30566
|
+
exports.EDGE_HEAD_FILL_DEFAULT = EDGE_HEAD_FILL_DEFAULT;
|
|
30025
30567
|
exports.EDGE_LABEL_TEXT = EDGE_LABEL_TEXT;
|
|
30026
30568
|
exports.EDGE_STUB_OUT = EDGE_STUB_OUT;
|
|
30569
|
+
exports.EDGE_STYLES = EDGE_STYLES;
|
|
30570
|
+
exports.ER_CARDINALITY_HEAD = ER_CARDINALITY_HEAD;
|
|
30027
30571
|
exports.FAN_GAP = FAN_GAP;
|
|
30028
30572
|
exports.FONT_RENDER_TOLERANCE_WORLD = FONT_RENDER_TOLERANCE_WORLD;
|
|
30573
|
+
exports.FSM_ACTION_MARK = FSM_ACTION_MARK;
|
|
30029
30574
|
exports.LABEL_INIT_CLEARANCE = LABEL_INIT_CLEARANCE;
|
|
30030
30575
|
exports.LABEL_INIT_CLEARANCE_DOTTED_FLOW = LABEL_INIT_CLEARANCE_DOTTED_FLOW;
|
|
30031
30576
|
exports.LABEL_SIZE_TOLERANCE_WORLD = LABEL_SIZE_TOLERANCE_WORLD;
|
|
@@ -30039,6 +30584,7 @@ exports.NEAR_COLLISION_POLICY = NEAR_COLLISION_POLICY;
|
|
|
30039
30584
|
exports.NODE_FRAME_SELECTOR = NODE_FRAME_SELECTOR;
|
|
30040
30585
|
exports.NODE_KINDS = NODE_KINDS;
|
|
30041
30586
|
exports.ROW_GAP_VARIANCE_TOL = ROW_GAP_VARIANCE_TOL;
|
|
30587
|
+
exports.SEQUENCE_MESSAGE_LOOK = SEQUENCE_MESSAGE_LOOK;
|
|
30042
30588
|
exports.SPEC_CLEARANCE_POLICY = SPEC_CLEARANCE_POLICY;
|
|
30043
30589
|
exports.STAGE_SVG_SELECTOR = STAGE_SVG_SELECTOR;
|
|
30044
30590
|
exports.TARGET_LABEL_PATH_DIST = TARGET_LABEL_PATH_DIST;
|
|
@@ -30113,6 +30659,8 @@ exports.resolveTarget = resolveTarget;
|
|
|
30113
30659
|
exports.resolveTargetAll = resolveTargetAll;
|
|
30114
30660
|
exports.segmentsIntersect = segmentsIntersect2;
|
|
30115
30661
|
exports.sequence = sequence;
|
|
30662
|
+
exports.sequenceBoardMetrics = sequenceBoardMetrics;
|
|
30663
|
+
exports.sequenceStepId = sequenceStepId;
|
|
30116
30664
|
exports.signal = signal;
|
|
30117
30665
|
exports.stateMachine = stateMachine;
|
|
30118
30666
|
exports.stateMachine2 = stateMachine2;
|