@cardenelabs/cdl 0.124.0 → 0.125.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +43 -1
- package/README.md +8 -0
- package/dist/index.cjs +873 -142
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +873 -143
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +858 -142
- 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 +858 -142
- package/dist/react.js.map +1 -1
- package/dist/{render-U6omSNH2.d.cts → render-7yEHIUK1.d.cts} +57 -3
- package/dist/{render-U6omSNH2.d.ts → render-7yEHIUK1.d.ts} +57 -3
- package/package.json +12 -9
- package/src/builder.ts +6 -0
- package/src/index.ts +4 -0
- package/src/kinds/card.tsx +12 -4
- package/src/kinds/generic.tsx +19 -9
- package/src/kinds/station.tsx +105 -19
- package/src/kinds/terminal-mark.tsx +36 -9
- package/src/layout/edges.ts +77 -24
- package/src/layout/lanes.ts +69 -5
- package/src/layout/legend.ts +68 -0
- package/src/layout/metro-path.ts +123 -30
- package/src/layout/nodes.ts +13 -2
- package/src/layout/spec.ts +17 -1
- package/src/layout/tokens.ts +8 -1
- package/src/layout.ts +20 -2
- package/src/render/edge-head.ts +6 -0
- package/src/render/edges.tsx +27 -6
- package/src/render/legend.tsx +120 -0
- package/src/render/nodes.tsx +21 -5
- package/src/render/stage.tsx +255 -10
- package/src/render/template-fields.ts +2 -0
- package/src/types.ts +106 -5
- package/src/validate.ts +5 -0
- package/src/visual-validate.ts +7 -7
package/dist/index.cjs
CHANGED
|
@@ -12332,6 +12332,8 @@ function diagram(id, options) {
|
|
|
12332
12332
|
...options.textMetrics !== void 0 ? { textMetrics: options.textMetrics } : {},
|
|
12333
12333
|
// 種類の名前も同じ経路で渡し、空文字の扱いを `layout` の 1 箇所に揃える
|
|
12334
12334
|
...options.type !== void 0 ? { type: options.type } : {},
|
|
12335
|
+
// 空の並びは書かなかった図と同じ形にする。 凡例なしの JSON と配置を変えない
|
|
12336
|
+
...options.legend && options.legend.length > 0 ? { legend: options.legend.map((item) => ({ ...item })) } : {},
|
|
12335
12337
|
// inputs / formulas / scrollTriggers / eventBindings は空なら省略 (static diagram の JSON 形状維持)
|
|
12336
12338
|
...inputs.length > 0 ? { inputs: [...inputs] } : {},
|
|
12337
12339
|
...formulas.length > 0 ? { formulas: [...formulas] } : {},
|
|
@@ -12444,7 +12446,7 @@ function drawsTitleOutsideBox(kind) {
|
|
|
12444
12446
|
}
|
|
12445
12447
|
var TITLE_FONT_SIZE_DEFAULT = 18;
|
|
12446
12448
|
var TITLE_FONT_SIZE = new Map([
|
|
12447
|
-
...["dyn-rect", "dyn-circle", "dyn-arc", "dyn-wave", "dyn-polygon"
|
|
12449
|
+
...["dyn-rect", "dyn-circle", "dyn-arc", "dyn-wave", "dyn-polygon"].map(
|
|
12448
12450
|
(k) => [k, 13]
|
|
12449
12451
|
),
|
|
12450
12452
|
...[
|
|
@@ -12489,8 +12491,10 @@ var TITLE_FONT_SIZE = new Map([
|
|
|
12489
12491
|
"webhook"
|
|
12490
12492
|
].map((k) => [k, 20]),
|
|
12491
12493
|
...["card", "event", "function"].map((k) => [k, 24]),
|
|
12494
|
+
["station", 25],
|
|
12492
12495
|
["actor", 32],
|
|
12493
|
-
["storage", 34]
|
|
12496
|
+
["storage", 34],
|
|
12497
|
+
["timeline-number", 18]
|
|
12494
12498
|
]);
|
|
12495
12499
|
function titleFontSize(kind) {
|
|
12496
12500
|
return TITLE_FONT_SIZE.get(kind ?? "") ?? TITLE_FONT_SIZE_DEFAULT;
|
|
@@ -12500,9 +12504,17 @@ function skipsNodeTitleWidthCheck(kind) {
|
|
|
12500
12504
|
return KINDS_WITH_TITLE_WIDTH_OUTSIDE_NODE.has(kind ?? "");
|
|
12501
12505
|
}
|
|
12502
12506
|
var TITLE_BOX_PADDING = 52;
|
|
12507
|
+
var TIMELINE_NUMBER_STROKE = 4;
|
|
12508
|
+
function titleUsableWidth(kind, w, h) {
|
|
12509
|
+
if (kind === "timeline-number") {
|
|
12510
|
+
return Math.min(w, h) - 2 * TIMELINE_NUMBER_STROKE;
|
|
12511
|
+
}
|
|
12512
|
+
return w - (drawsTitleOutsideBox(kind) ? 0 : TITLE_BOX_PADDING);
|
|
12513
|
+
}
|
|
12503
12514
|
var KINDS_SCALING_TITLE_WHEN_LOW = /* @__PURE__ */ new Set(["actor", "event", "function", "storage"]);
|
|
12504
12515
|
var KINDS_SCALING_TITLE_ALWAYS = /* @__PURE__ */ new Set([
|
|
12505
12516
|
"card",
|
|
12517
|
+
"timeline-number",
|
|
12506
12518
|
"shape-file",
|
|
12507
12519
|
"shape-folder",
|
|
12508
12520
|
"shape-cloud",
|
|
@@ -12586,14 +12598,16 @@ var KINDS_DRAWING_ONLY_SHAPE = [
|
|
|
12586
12598
|
];
|
|
12587
12599
|
var KINDS_WITHOUT_EYEBROW_TEXT = /* @__PURE__ */ new Set([
|
|
12588
12600
|
...KINDS_DRAWING_ONLY_SHAPE,
|
|
12589
|
-
...KINDS_WITHOUT_TITLE_TEXT
|
|
12601
|
+
...KINDS_WITHOUT_TITLE_TEXT,
|
|
12602
|
+
"timeline-number"
|
|
12590
12603
|
]);
|
|
12591
12604
|
function rendersEyebrow(kind) {
|
|
12592
12605
|
return !KINDS_WITHOUT_EYEBROW_TEXT.has(kind ?? "");
|
|
12593
12606
|
}
|
|
12594
12607
|
var KINDS_WITHOUT_SUBTITLE_TEXT = /* @__PURE__ */ new Set([
|
|
12595
12608
|
...KINDS_DRAWING_OWN_PAYLOAD,
|
|
12596
|
-
...KINDS_WITHOUT_TITLE_TEXT
|
|
12609
|
+
...KINDS_WITHOUT_TITLE_TEXT,
|
|
12610
|
+
"timeline-number"
|
|
12597
12611
|
]);
|
|
12598
12612
|
function rendersSubtitle(kind) {
|
|
12599
12613
|
return !KINDS_WITHOUT_SUBTITLE_TEXT.has(kind ?? "");
|
|
@@ -14700,6 +14714,14 @@ function curvePath(from, to, edge, labelMarginExtra = 0, textMetrics = "proporti
|
|
|
14700
14714
|
|
|
14701
14715
|
// src/layout/metro-path.ts
|
|
14702
14716
|
var METRO_CORNER_RADIUS = 24;
|
|
14717
|
+
var METRO_BRANCH_CORNER_RADIUS = 22;
|
|
14718
|
+
var METRO_BRANCH_STUB = 30;
|
|
14719
|
+
var METRO_DECISION_HEIGHT = 88;
|
|
14720
|
+
var METRO_DECISION_WIDTH = 116;
|
|
14721
|
+
var METRO_RETURN_END_OFFSET = 43;
|
|
14722
|
+
var METRO_RETURN_START_OFFSET = 24;
|
|
14723
|
+
var METRO_LINE_WIDTH = 10;
|
|
14724
|
+
var METRO_LINE_WIDTH_CSS = `var(--cdl-metro-line-width, ${METRO_LINE_WIDTH}px)`;
|
|
14703
14725
|
var T = Math.SQRT2 - 1;
|
|
14704
14726
|
function round2(v) {
|
|
14705
14727
|
return Math.round(v * 100) / 100;
|
|
@@ -14717,7 +14739,63 @@ function polyline(points) {
|
|
|
14717
14739
|
});
|
|
14718
14740
|
return distinct.map((p, i) => `${i === 0 ? "M" : "L"} ${point(p)}`).join(" ");
|
|
14719
14741
|
}
|
|
14720
|
-
function
|
|
14742
|
+
function quadraticCornerPath(start, corner, end, radius) {
|
|
14743
|
+
const horizontalDir = Math.sign(corner.x - start.x);
|
|
14744
|
+
const verticalDir = Math.sign(end.y - corner.y);
|
|
14745
|
+
const r = Math.min(
|
|
14746
|
+
radius,
|
|
14747
|
+
Math.abs(corner.x - start.x),
|
|
14748
|
+
Math.abs(end.y - corner.y)
|
|
14749
|
+
);
|
|
14750
|
+
const before = { x: corner.x - horizontalDir * r, y: corner.y };
|
|
14751
|
+
const after = { x: corner.x, y: corner.y + verticalDir * r };
|
|
14752
|
+
return [
|
|
14753
|
+
`M ${point(start)}`,
|
|
14754
|
+
`L ${point(before)}`,
|
|
14755
|
+
`Q ${point(corner)} ${point(after)}`,
|
|
14756
|
+
`L ${point(end)}`
|
|
14757
|
+
].join(" ");
|
|
14758
|
+
}
|
|
14759
|
+
function decisionBranchPath(start, end) {
|
|
14760
|
+
const horizontalDir = Math.sign(end.x - start.x);
|
|
14761
|
+
const verticalDir = Math.sign(end.y - start.y);
|
|
14762
|
+
const turnX = start.x + horizontalDir * (METRO_BRANCH_STUB + METRO_BRANCH_CORNER_RADIUS);
|
|
14763
|
+
const radius = Math.min(
|
|
14764
|
+
METRO_BRANCH_CORNER_RADIUS,
|
|
14765
|
+
Math.abs(end.y - start.y) / 2,
|
|
14766
|
+
Math.abs(end.x - turnX)
|
|
14767
|
+
);
|
|
14768
|
+
const firstCorner = { x: turnX, y: start.y };
|
|
14769
|
+
const secondCorner = { x: turnX, y: end.y };
|
|
14770
|
+
const beforeFirst = {
|
|
14771
|
+
x: turnX - horizontalDir * radius,
|
|
14772
|
+
y: start.y
|
|
14773
|
+
};
|
|
14774
|
+
const afterFirst = {
|
|
14775
|
+
x: turnX,
|
|
14776
|
+
y: start.y + verticalDir * radius
|
|
14777
|
+
};
|
|
14778
|
+
const beforeSecond = {
|
|
14779
|
+
x: turnX,
|
|
14780
|
+
y: end.y - verticalDir * radius
|
|
14781
|
+
};
|
|
14782
|
+
const afterSecond = {
|
|
14783
|
+
x: turnX + horizontalDir * radius,
|
|
14784
|
+
y: end.y
|
|
14785
|
+
};
|
|
14786
|
+
return {
|
|
14787
|
+
d: [
|
|
14788
|
+
`M ${point(start)}`,
|
|
14789
|
+
`L ${point(beforeFirst)}`,
|
|
14790
|
+
`Q ${point(firstCorner)} ${point(afterFirst)}`,
|
|
14791
|
+
`L ${point(beforeSecond)}`,
|
|
14792
|
+
`Q ${point(secondCorner)} ${point(afterSecond)}`,
|
|
14793
|
+
`L ${point(end)}`
|
|
14794
|
+
].join(" "),
|
|
14795
|
+
turnX
|
|
14796
|
+
};
|
|
14797
|
+
}
|
|
14798
|
+
function metroPath(from, to, edge, _labelMarginExtra = 0, _textMetrics = "proportional") {
|
|
14721
14799
|
const fromLeft = from.cx - from.w / 2;
|
|
14722
14800
|
const fromRight = from.cx + from.w / 2;
|
|
14723
14801
|
const toLeft = to.cx - to.w / 2;
|
|
@@ -14752,11 +14830,45 @@ function metroPath(from, to, edge, labelMarginExtra = 0, textMetrics = "proporti
|
|
|
14752
14830
|
const sgn = Math.sign(dy);
|
|
14753
14831
|
let d;
|
|
14754
14832
|
let mid;
|
|
14755
|
-
let
|
|
14756
|
-
if (Math.abs(dy)
|
|
14833
|
+
let metroReturn = false;
|
|
14834
|
+
if (from.kind === "decision" && Math.abs(dy) >= SAME_HEIGHT_THRESHOLD) {
|
|
14835
|
+
const verticalDir = Math.sign(dy);
|
|
14836
|
+
if (Math.abs(to.cx - from.cx) < SAME_HEIGHT_THRESHOLD) {
|
|
14837
|
+
const start = { x: from.cx, y: from.cy + verticalDir * from.h / 2 };
|
|
14838
|
+
const end = { x: to.cx, y: to.cy };
|
|
14839
|
+
d = polyline([start, end]);
|
|
14840
|
+
fromSide = verticalDir < 0 ? "top" : "bottom";
|
|
14841
|
+
toSide = verticalDir < 0 ? "bottom" : "top";
|
|
14842
|
+
mid = { x: start.x, y: (start.y + end.y) / 2 };
|
|
14843
|
+
} else {
|
|
14844
|
+
const horizontalDir = Math.sign(to.cx - from.cx);
|
|
14845
|
+
const start = {
|
|
14846
|
+
x: from.cx + horizontalDir * from.w / 2,
|
|
14847
|
+
y: from.cy
|
|
14848
|
+
};
|
|
14849
|
+
const end = {
|
|
14850
|
+
x: to.cx - horizontalDir * to.w / 2,
|
|
14851
|
+
y: to.cy
|
|
14852
|
+
};
|
|
14853
|
+
const branch = decisionBranchPath(start, end);
|
|
14854
|
+
d = branch.d;
|
|
14855
|
+
fromSide = horizontalDir > 0 ? "right" : "left";
|
|
14856
|
+
toSide = horizontalDir > 0 ? "left" : "right";
|
|
14857
|
+
mid = { x: branch.turnX, y: (start.y + end.y) / 2 };
|
|
14858
|
+
}
|
|
14859
|
+
} else if (edge?.style === "dashed" && from.kind === "station" && to.kind === "station" && to.cx < from.cx && Math.abs(dy) >= SAME_HEIGHT_THRESHOLD) {
|
|
14860
|
+
const verticalDir = Math.sign(to.cy - from.cy);
|
|
14861
|
+
const start = { x: from.cx - METRO_RETURN_START_OFFSET, y: from.cy };
|
|
14862
|
+
const end = { x: to.cx, y: to.cy - verticalDir * METRO_RETURN_END_OFFSET };
|
|
14863
|
+
const corner = { x: end.x, y: start.y };
|
|
14864
|
+
fromSide = "left";
|
|
14865
|
+
toSide = verticalDir < 0 ? "bottom" : "top";
|
|
14866
|
+
d = quadraticCornerPath(start, corner, end, METRO_BRANCH_CORNER_RADIUS);
|
|
14867
|
+
mid = { x: (start.x + corner.x) / 2, y: start.y };
|
|
14868
|
+
metroReturn = true;
|
|
14869
|
+
} else if (Math.abs(dy) < SAME_HEIGHT_THRESHOLD) {
|
|
14757
14870
|
d = `M ${point({ x: x1, y: y1 })} L ${point({ x: x2, y: y2 })}`;
|
|
14758
14871
|
mid = { x: (x1 + x2) / 2, y: (y1 + y2) / 2 };
|
|
14759
|
-
tangent = { x: x2 - x1, y: y2 - y1 };
|
|
14760
14872
|
} else if (fromSide !== toSide && Math.abs(x2 - x1) >= Math.abs(dy)) {
|
|
14761
14873
|
const horizontal = Math.abs(x2 - x1);
|
|
14762
14874
|
const s = (horizontal - Math.abs(dy)) / 2;
|
|
@@ -14786,7 +14898,6 @@ function metroPath(from, to, edge, labelMarginExtra = 0, textMetrics = "proporti
|
|
|
14786
14898
|
d = polyline([p0, p1, p2, p3]);
|
|
14787
14899
|
}
|
|
14788
14900
|
mid = { x: (x1 + x2) / 2, y: (y1 + y2) / 2 };
|
|
14789
|
-
tangent = w;
|
|
14790
14901
|
} else {
|
|
14791
14902
|
fromSide = "right";
|
|
14792
14903
|
toSide = "right";
|
|
@@ -14816,33 +14927,32 @@ function metroPath(from, to, edge, labelMarginExtra = 0, textMetrics = "proporti
|
|
|
14816
14927
|
`L ${point(p4)}`
|
|
14817
14928
|
].join(" ");
|
|
14818
14929
|
mid = { x: p2.x - T * r, y: p2.y };
|
|
14819
|
-
tangent = { x: 0, y: sgn };
|
|
14820
|
-
}
|
|
14821
|
-
if (edge?.overlay) {
|
|
14822
|
-
return { d, fromSide, toSide, labelX: mid.x, labelY: mid.y, labelAnchor: "middle" };
|
|
14823
|
-
}
|
|
14824
|
-
const tangentLength = Math.hypot(tangent.x, tangent.y);
|
|
14825
|
-
let normalX = tangent.y / tangentLength;
|
|
14826
|
-
let normalY = -tangent.x / tangentLength;
|
|
14827
|
-
if (normalY > Number.EPSILON || Math.abs(normalY) <= Number.EPSILON && normalX < 0) {
|
|
14828
|
-
normalX *= -1;
|
|
14829
|
-
normalY *= -1;
|
|
14830
14930
|
}
|
|
14831
|
-
const labelW = computeLabelBoxW(edge?.label, edge?.sub, textMetrics);
|
|
14832
|
-
const labelH = labelPillH(edge?.sub);
|
|
14833
|
-
const distance = labelPathClearanceHorizontal(edge) + (Math.abs(normalX) * labelW + Math.abs(normalY) * labelH) / 2 + labelMarginExtra;
|
|
14834
14931
|
return {
|
|
14835
14932
|
d,
|
|
14836
14933
|
fromSide,
|
|
14837
14934
|
toSide,
|
|
14838
|
-
labelX: mid.x
|
|
14839
|
-
labelY: mid.y
|
|
14840
|
-
labelAnchor: "middle"
|
|
14935
|
+
labelX: mid.x,
|
|
14936
|
+
labelY: mid.y,
|
|
14937
|
+
labelAnchor: "middle",
|
|
14938
|
+
...metroReturn ? { metroReturn: true } : {}
|
|
14841
14939
|
};
|
|
14842
14940
|
}
|
|
14843
14941
|
|
|
14844
14942
|
// src/types.ts
|
|
14845
14943
|
var TONES = ["accent", "teal", "success", "error", "warning", "info"];
|
|
14944
|
+
var LEGEND_MARKS = [
|
|
14945
|
+
"diamond",
|
|
14946
|
+
"filled-circle",
|
|
14947
|
+
"double-circle",
|
|
14948
|
+
"dotted-line",
|
|
14949
|
+
"solid-line",
|
|
14950
|
+
"curved-line",
|
|
14951
|
+
"rounded-label",
|
|
14952
|
+
"numbered-circle",
|
|
14953
|
+
"station",
|
|
14954
|
+
"arrow"
|
|
14955
|
+
];
|
|
14846
14956
|
var NODE_KINDS = [
|
|
14847
14957
|
// dynamic shape (CAR: shape primitive) ... signal 値で内部 fill / radius / angle 等が
|
|
14848
14958
|
// リアルタイム変化する汎用 container、 shape spec は node.shape に格納
|
|
@@ -14964,12 +15074,14 @@ var NODE_KINDS = [
|
|
|
14964
15074
|
"shape-lawyer",
|
|
14965
15075
|
"shape-trader",
|
|
14966
15076
|
"shape-customer-service",
|
|
14967
|
-
// 流れの始まりと終わりの印 2 種 (#560) ...
|
|
14968
|
-
//
|
|
15077
|
+
// 流れの始まりと終わりの印 2 種 (#560) ... 始点と終点は線の端から推測せず、著者が
|
|
15078
|
+
// `kind: "mark-start"` / `kind: "mark-end"` の node を明示する。印は文字を描かない
|
|
14969
15079
|
"mark-start",
|
|
14970
15080
|
"mark-end",
|
|
14971
15081
|
// 路線図の駅 (#996) ... 線路上の点を小さな丸で示し、名前と説明は丸の外に置く
|
|
14972
15082
|
"station",
|
|
15083
|
+
// 時間軸の番号 (#1017) ... 実線の軸上に番号を入れた丸を置く。路線図の駅とは別の意味を持つ。
|
|
15084
|
+
"timeline-number",
|
|
14973
15085
|
// 時系列のやり取り (#578) ... 1 つの箱が図を丸ごと描く。 縦が時間で、参加者は箱を持たない
|
|
14974
15086
|
"sequence-board"
|
|
14975
15087
|
];
|
|
@@ -17703,7 +17815,7 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
|
|
|
17703
17815
|
const LIFELINE_W_THRESHOLD = 8;
|
|
17704
17816
|
for (const n of laid.nodes) {
|
|
17705
17817
|
if (n.w < LIFELINE_W_THRESHOLD) continue;
|
|
17706
|
-
if (n.kind === "station") continue;
|
|
17818
|
+
if (n.kind === "station" || n.kind === "timeline-number") continue;
|
|
17707
17819
|
if (n.w < MIN_NODE_W || n.h < MIN_NODE_H) {
|
|
17708
17820
|
push(
|
|
17709
17821
|
"node-visibility",
|
|
@@ -17729,8 +17841,7 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
|
|
|
17729
17841
|
if (!isRenderedNode(n)) continue;
|
|
17730
17842
|
const titleTrimmed = n.title?.trim() ?? "";
|
|
17731
17843
|
if (!titleTrimmed) continue;
|
|
17732
|
-
const \
|
|
17733
|
-
const \u4F7F\u3048\u308B\u5E452 = n.w - \u4F59\u767D;
|
|
17844
|
+
const \u4F7F\u3048\u308B\u5E452 = titleUsableWidth(n.kind, n.w, n.h);
|
|
17734
17845
|
const \u5B9F\u5E45 = measureTextWidth(titleTrimmed, {
|
|
17735
17846
|
fontSize: titleFontSize(n.kind),
|
|
17736
17847
|
bound: "drawn",
|
|
@@ -17749,7 +17860,7 @@ function runAxes(laid, diag, violations, counts, push, profile, skippedAxes, \u5
|
|
|
17749
17860
|
push(
|
|
17750
17861
|
"text-readability",
|
|
17751
17862
|
// 字ごとの実幅は小数になるので、読む人に出す時だけ丸める (判定は丸めない)
|
|
17752
|
-
`node "${n.id}" title "${n.title}" \u304C node \u5E45 ${n.w}px \u3092\u8D85\u904E\u3059\u308B\u53EF\u80FD\u6027 (\u671F\u5F85 ${Math.round(\u5B9F\u5E45 + \
|
|
17863
|
+
`node "${n.id}" title "${n.title}" \u304C node \u5E45 ${n.w}px \u3092\u8D85\u904E\u3059\u308B\u53EF\u80FD\u6027 (\u671F\u5F85 ${Math.round(\u5B9F\u5E45 + (n.w - \u4F7F\u3048\u308B\u5E452))}px)`,
|
|
17753
17864
|
"warn"
|
|
17754
17865
|
);
|
|
17755
17866
|
}
|
|
@@ -19563,6 +19674,8 @@ var TOKENS = {
|
|
|
19563
19674
|
lane_label_h: 40,
|
|
19564
19675
|
lane_top_pad: 100,
|
|
19565
19676
|
contain_pad: 28,
|
|
19677
|
+
stage_column_gap: 48,
|
|
19678
|
+
stage_card_text_inset: 18,
|
|
19566
19679
|
// node sizes (kind ごと、 unified row h は engine が max() で算出)
|
|
19567
19680
|
node: {
|
|
19568
19681
|
actor: { w: 340, h: 165 },
|
|
@@ -19689,7 +19802,10 @@ var TOKENS = {
|
|
|
19689
19802
|
"mark-start": { w: 96, h: 96 },
|
|
19690
19803
|
"mark-end": { w: 96, h: 96 },
|
|
19691
19804
|
// 路線図の駅 (#996) ... 正方形にして小さな丸が縦横どちらにも歪まないようにする。
|
|
19692
|
-
|
|
19805
|
+
// 半径 16 と縁 6 の外径を、線路との接点を含めて収める。
|
|
19806
|
+
station: { w: 38, h: 38 },
|
|
19807
|
+
// 時間軸の番号 (#1017) ... 半径 24 の丸と太さ 4 の縁を収める。
|
|
19808
|
+
"timeline-number": { w: 52, h: 52 },
|
|
19693
19809
|
// 時系列のやり取り (#578)。 実寸は中身から決まる (`sequenceBoardMetrics`) ので、
|
|
19694
19810
|
// ここは書かなかった時の受け皿
|
|
19695
19811
|
"sequence-board": { w: 960, h: 640 }
|
|
@@ -19704,6 +19820,8 @@ var LANE_TOP_PAD = TOKENS.lane_top_pad;
|
|
|
19704
19820
|
var STACK_GAP = TOKENS.row_gap;
|
|
19705
19821
|
var NODE_SIZE = TOKENS.node;
|
|
19706
19822
|
var CONTAIN_PAD = TOKENS.contain_pad;
|
|
19823
|
+
var STAGE_COLUMN_GAP = TOKENS.stage_column_gap;
|
|
19824
|
+
var STAGE_CARD_TEXT_INSET = TOKENS.stage_card_text_inset;
|
|
19707
19825
|
var VIEW_PAD = TOKENS.view_pad;
|
|
19708
19826
|
var HEADER_RESERVE = TOKENS.header_reserve;
|
|
19709
19827
|
var DEFAULT_LANE_GAP = 80;
|
|
@@ -19804,12 +19922,24 @@ function layoutEdges(diag, nodes, lanes = [], textMetrics = "proportional") {
|
|
|
19804
19922
|
if (!from) throw new Error(`cdl layout: edge "${e.id}" \u306E from "${e.from}" \u304C node \u306B\u7121\u3044`);
|
|
19805
19923
|
if (!to) throw new Error(`cdl layout: edge "${e.id}" \u306E to "${e.to}" \u304C node \u306B\u7121\u3044`);
|
|
19806
19924
|
const c = curvePath(from, to, e, labelMarginExtra, textMetrics);
|
|
19925
|
+
const fromLane = lmap.get(from.lane);
|
|
19926
|
+
const toLane = lmap.get(to.lane);
|
|
19927
|
+
let labelX = c.labelX;
|
|
19928
|
+
if (fromLane?.stage !== void 0 && toLane?.stage !== void 0 && fromLane.id !== toLane.id && (e.label || e.sub)) {
|
|
19929
|
+
const [leftLane, rightLane] = fromLane.x <= toLane.x ? [fromLane, toLane] : [toLane, fromLane];
|
|
19930
|
+
const gapLeft = leftLane.x + leftLane.width - STAGE_COLUMN_GAP / 2;
|
|
19931
|
+
const gapRight = rightLane.x + STAGE_COLUMN_GAP / 2;
|
|
19932
|
+
const labelHalfWidth = computeLabelBoxW(e.label, e.sub, textMetrics) / 2;
|
|
19933
|
+
const minX = gapLeft + labelHalfWidth;
|
|
19934
|
+
const maxX = gapRight - labelHalfWidth;
|
|
19935
|
+
if (minX <= maxX) labelX = Math.min(maxX, Math.max(minX, labelX));
|
|
19936
|
+
}
|
|
19807
19937
|
positionedEdges.push({
|
|
19808
19938
|
...e,
|
|
19809
19939
|
d: c.d,
|
|
19810
19940
|
fromSide: c.fromSide,
|
|
19811
19941
|
toSide: c.toSide,
|
|
19812
|
-
labelX:
|
|
19942
|
+
labelX: labelX + (e.labelOffsetX ?? 0),
|
|
19813
19943
|
labelY: c.labelY + (e.labelOffsetY ?? 0),
|
|
19814
19944
|
labelAnchor: c.labelAnchor
|
|
19815
19945
|
});
|
|
@@ -19826,7 +19956,8 @@ function layoutEdges(diag, nodes, lanes = [], textMetrics = "proportional") {
|
|
|
19826
19956
|
toSide: m.toSide,
|
|
19827
19957
|
labelX: m.labelX + (e.labelOffsetX ?? 0),
|
|
19828
19958
|
labelY: m.labelY + (e.labelOffsetY ?? 0),
|
|
19829
|
-
labelAnchor: m.labelAnchor
|
|
19959
|
+
labelAnchor: m.labelAnchor,
|
|
19960
|
+
...m.metroReturn ? { metroReturn: true } : {}
|
|
19830
19961
|
});
|
|
19831
19962
|
} else {
|
|
19832
19963
|
autoEdges.push(e);
|
|
@@ -20518,20 +20649,22 @@ function countPathObstacleCrossings(d, obstacles) {
|
|
|
20518
20649
|
const segments = flattenPathSegments(extractPathSegments(d));
|
|
20519
20650
|
return obstacles.filter((obstacle) => segmentsCrossRect(segments, nodeRect(obstacle))).length;
|
|
20520
20651
|
}
|
|
20521
|
-
function makeBackDetourCandidate(A, B, from, to, obstacles, detourY, side) {
|
|
20652
|
+
function makeBackDetourCandidate(A, B, from, to, obstacles, detourY, side, columnXOverride) {
|
|
20522
20653
|
const lowIsA = A.y >= B.y;
|
|
20523
20654
|
const low = lowIsA ? A : B;
|
|
20524
20655
|
const lowBendY = low.y - VERTICAL_DETOUR_EXIT;
|
|
20525
20656
|
const bandTop = Math.min(detourY, lowBendY);
|
|
20526
20657
|
const bandBottom = Math.max(detourY, lowBendY);
|
|
20527
20658
|
const bandObstacles = obstacles.map(nodeRect).filter((rect) => rect.y + rect.h >= bandTop && rect.y <= bandBottom);
|
|
20528
|
-
let columnX = detourColumnFor([from, to], side);
|
|
20529
|
-
|
|
20530
|
-
|
|
20531
|
-
|
|
20532
|
-
|
|
20533
|
-
|
|
20534
|
-
|
|
20659
|
+
let columnX = columnXOverride ?? detourColumnFor([from, to], side);
|
|
20660
|
+
if (columnXOverride === void 0) {
|
|
20661
|
+
while (true) {
|
|
20662
|
+
const blockers = bandObstacles.filter(
|
|
20663
|
+
(rect) => rect.x - VERTICAL_DETOUR_GAP < columnX && columnX < rect.x + rect.w + VERTICAL_DETOUR_GAP
|
|
20664
|
+
);
|
|
20665
|
+
if (blockers.length === 0) break;
|
|
20666
|
+
columnX = side === "left" ? Math.min(...blockers.map((rect) => rect.x - VERTICAL_DETOUR_GAP)) : Math.max(...blockers.map((rect) => rect.x + rect.w + VERTICAL_DETOUR_GAP));
|
|
20667
|
+
}
|
|
20535
20668
|
}
|
|
20536
20669
|
const bendAY = lowIsA ? lowBendY : detourY;
|
|
20537
20670
|
const bendBY = lowIsA ? detourY : lowBendY;
|
|
@@ -20640,7 +20773,7 @@ function sidePoint(n, side) {
|
|
|
20640
20773
|
return { x: n.cx + n.w / 2, y: n.cy };
|
|
20641
20774
|
}
|
|
20642
20775
|
}
|
|
20643
|
-
function routePath(from, to, fromSide, toSide, obstacles = [], detourSide,
|
|
20776
|
+
function routePath(from, to, fromSide, toSide, obstacles = [], detourSide, fromLane, toLane, edge, labelObstacles = obstacles, fromOffset = { x: 0, y: 0 }, toOffset = { x: 0, y: 0 }, avoidRects = [], textMetrics = "proportional") {
|
|
20644
20777
|
const labelBoxW = edge ? computeLabelBoxW(edge.label, edge.sub, textMetrics) : 0;
|
|
20645
20778
|
const labelHalfW = labelBoxW / 2;
|
|
20646
20779
|
const labelInit = labelInitClearance(edge);
|
|
@@ -21010,17 +21143,27 @@ function routePath(from, to, fromSide, toSide, obstacles = [], detourSide, _from
|
|
|
21010
21143
|
};
|
|
21011
21144
|
}
|
|
21012
21145
|
if (topTopPair) {
|
|
21013
|
-
const
|
|
21146
|
+
const stagePoint = (point2, node, lane) => lane?.stage === void 0 ? point2 : {
|
|
21147
|
+
x: Math.min(node.cx + node.w / 2 - 24, lane.x + lane.width - 24),
|
|
21148
|
+
y: point2.y
|
|
21149
|
+
};
|
|
21150
|
+
const backA = stagePoint(A, from, fromLane);
|
|
21151
|
+
const backB = stagePoint(B, to, toLane);
|
|
21152
|
+
const stageTops = [fromLane, toLane].filter((lane) => lane?.stage !== void 0).map((lane) => lane.y);
|
|
21153
|
+
const detourY = Math.min(
|
|
21154
|
+
Math.min(backA.y, backB.y) - 100,
|
|
21155
|
+
...stageTops.map((top) => top - VERTICAL_DETOUR_GAP)
|
|
21156
|
+
);
|
|
21014
21157
|
const corner = 14;
|
|
21015
|
-
const xDir =
|
|
21158
|
+
const xDir = backB.x > backA.x ? 1 : -1;
|
|
21016
21159
|
const existing = {
|
|
21017
|
-
d: `M ${
|
|
21018
|
-
L ${
|
|
21019
|
-
Q ${
|
|
21020
|
-
L ${
|
|
21021
|
-
Q ${
|
|
21022
|
-
L ${
|
|
21023
|
-
labelX: (
|
|
21160
|
+
d: `M ${backA.x} ${backA.y}
|
|
21161
|
+
L ${backA.x} ${detourY + corner}
|
|
21162
|
+
Q ${backA.x} ${detourY}, ${backA.x + xDir * corner} ${detourY}
|
|
21163
|
+
L ${backB.x - xDir * corner} ${detourY}
|
|
21164
|
+
Q ${backB.x} ${detourY}, ${backB.x} ${detourY + corner}
|
|
21165
|
+
L ${backB.x} ${backB.y}`,
|
|
21166
|
+
labelX: (backA.x + backB.x) / 2,
|
|
21024
21167
|
// CAR-468 SSOT ... 旧 detourY - 30 magic number を LABEL_INIT_CLEARANCE (26、 CAR-570 で 34 → 26 縮小) に置換。
|
|
21025
21168
|
// CAR-518 SSOT ... dotted-flow は 62 world (marker glow radius 分拡張) を labelInit で参照。
|
|
21026
21169
|
// top-top detour の水平 segment 上方 labelInit world = spec 準拠距離。
|
|
@@ -21029,7 +21172,16 @@ function routePath(from, to, fromSide, toSide, obstacles = [], detourSide, _from
|
|
|
21029
21172
|
};
|
|
21030
21173
|
const existingCrossings = countPathObstacleCrossings(existing.d, obstacles);
|
|
21031
21174
|
if (existingCrossings === 0) return existing;
|
|
21032
|
-
const candidate =
|
|
21175
|
+
const candidate = from.lane === to.lane && fromLane?.stage !== void 0 ? makeBackDetourCandidate(
|
|
21176
|
+
backA,
|
|
21177
|
+
backB,
|
|
21178
|
+
from,
|
|
21179
|
+
to,
|
|
21180
|
+
obstacles,
|
|
21181
|
+
detourY,
|
|
21182
|
+
"right",
|
|
21183
|
+
fromLane.x + fromLane.width
|
|
21184
|
+
) : chooseBackDetourCandidate(backA, backB, from, to, obstacles, detourY);
|
|
21033
21185
|
if (candidate.crossings >= existingCrossings) return existing;
|
|
21034
21186
|
return {
|
|
21035
21187
|
d: candidate.d,
|
|
@@ -21963,12 +22115,56 @@ function \u76F4\u524D\u306E\u6298\u308C\u3054\u3068\u305A\u3089\u3059(segs, \u6A
|
|
|
21963
22115
|
return parts.join(" ");
|
|
21964
22116
|
}
|
|
21965
22117
|
|
|
22118
|
+
// src/layout/legend.ts
|
|
22119
|
+
var LEGEND_FONT_SIZE = 17;
|
|
22120
|
+
var LEGEND_MARK_SCALE = LEGEND_FONT_SIZE / 21;
|
|
22121
|
+
var LEGEND_MARK_REFERENCE_WIDTH = 46;
|
|
22122
|
+
var LEGEND_MARK_WIDTH = LEGEND_MARK_REFERENCE_WIDTH * LEGEND_MARK_SCALE;
|
|
22123
|
+
var LEGEND_MARK_TEXT_GAP = 12 * LEGEND_MARK_SCALE;
|
|
22124
|
+
var LEGEND_ITEM_GAP_RATIO = 0.07;
|
|
22125
|
+
var LEGEND_BASELINE_GAP = 32;
|
|
22126
|
+
var LEGEND_BOTTOM_EXTENT = 10;
|
|
22127
|
+
function layoutLegend(items, viewBox, textMetrics, nodes) {
|
|
22128
|
+
const renderedNodes = nodes.filter(isRenderedNode);
|
|
22129
|
+
const startX = renderedNodes.length > 0 ? Math.min(...renderedNodes.map((node) => node.cx - node.w / 2)) : viewBox.x + VIEW_PAD;
|
|
22130
|
+
const diagramRight = renderedNodes.length > 0 ? Math.max(...renderedNodes.map((node) => node.cx + node.w / 2)) : viewBox.x + viewBox.w - VIEW_PAD;
|
|
22131
|
+
const itemGap = (diagramRight - startX) * LEGEND_ITEM_GAP_RATIO;
|
|
22132
|
+
const y = viewBox.y + viewBox.h - VIEW_PAD + LEGEND_BASELINE_GAP;
|
|
22133
|
+
let x = startX;
|
|
22134
|
+
const legend = items.map((item) => {
|
|
22135
|
+
const laid = { ...item, x, y };
|
|
22136
|
+
x += LEGEND_MARK_WIDTH + LEGEND_MARK_TEXT_GAP + textWidth(item.text, LEGEND_FONT_SIZE, 0, textMetrics) + itemGap;
|
|
22137
|
+
return laid;
|
|
22138
|
+
});
|
|
22139
|
+
const right = x - itemGap;
|
|
22140
|
+
const bottom = y + LEGEND_BOTTOM_EXTENT + VIEW_PAD;
|
|
22141
|
+
return {
|
|
22142
|
+
legend,
|
|
22143
|
+
viewBox: {
|
|
22144
|
+
...viewBox,
|
|
22145
|
+
w: Math.max(viewBox.w, right + VIEW_PAD - viewBox.x),
|
|
22146
|
+
h: Math.max(viewBox.h, bottom - viewBox.y)
|
|
22147
|
+
}
|
|
22148
|
+
};
|
|
22149
|
+
}
|
|
22150
|
+
|
|
21966
22151
|
// src/layout/lanes.ts
|
|
21967
22152
|
var LANE_POSITION_EPSILON = 1e-9;
|
|
22153
|
+
function equalizeStageColumns(lanes, nodes = []) {
|
|
22154
|
+
const stages = lanes.filter((lane) => lane.stage !== void 0);
|
|
22155
|
+
if (stages.length === 0) return lanes;
|
|
22156
|
+
const top = Math.min(...stages.map((lane) => lane.y));
|
|
22157
|
+
const stageIds = new Set(stages.map((lane) => lane.id));
|
|
22158
|
+
const nodeBottoms = nodes.filter((node) => stageIds.has(node.lane)).map((node) => node.cy + node.h / 2 + CONTAIN_PAD);
|
|
22159
|
+
const bottom = Math.max(...stages.map((lane) => lane.y + lane.height), ...nodeBottoms);
|
|
22160
|
+
return lanes.map(
|
|
22161
|
+
(lane) => lane.stage === void 0 ? lane : { ...lane, y: top, height: bottom - top }
|
|
22162
|
+
);
|
|
22163
|
+
}
|
|
21968
22164
|
function layoutLanes(diag) {
|
|
21969
22165
|
const laneGap = diag.viewport?.laneGap ?? diag.viewport?.gap ?? DEFAULT_LANE_GAP;
|
|
21970
22166
|
let cursorX = 0;
|
|
21971
|
-
|
|
22167
|
+
const lanes = diag.lanes.map((lane, index) => {
|
|
21972
22168
|
if (lane.posX !== void 0 && lane.posY !== void 0) {
|
|
21973
22169
|
return {
|
|
21974
22170
|
...lane,
|
|
@@ -21979,7 +22175,9 @@ function layoutLanes(diag) {
|
|
|
21979
22175
|
};
|
|
21980
22176
|
}
|
|
21981
22177
|
const resolvedX = lane.x ?? cursorX;
|
|
21982
|
-
|
|
22178
|
+
const nextLane = diag.lanes[index + 1];
|
|
22179
|
+
const gapAfter = lane.stage !== void 0 && nextLane?.stage !== void 0 ? 0 : laneGap;
|
|
22180
|
+
cursorX = resolvedX + lane.width + gapAfter;
|
|
21983
22181
|
return {
|
|
21984
22182
|
...lane,
|
|
21985
22183
|
x: resolvedX,
|
|
@@ -21987,6 +22185,7 @@ function layoutLanes(diag) {
|
|
|
21987
22185
|
height: LANE_LABEL_H
|
|
21988
22186
|
};
|
|
21989
22187
|
});
|
|
22188
|
+
return equalizeStageColumns(lanes);
|
|
21990
22189
|
}
|
|
21991
22190
|
function expandLanesForNodes(lanes, nodes) {
|
|
21992
22191
|
const targetNodeGap = targetNodeNodeClearance();
|
|
@@ -22015,7 +22214,8 @@ function expandLanesForNodes(lanes, nodes) {
|
|
|
22015
22214
|
if (lane.posX !== void 0 && lane.posY !== void 0) continue;
|
|
22016
22215
|
const inside = nodes.filter((n) => n.lane === lane.id);
|
|
22017
22216
|
const maxNodeW = inside.length > 0 ? Math.max(...inside.map((n) => n.w)) : 0;
|
|
22018
|
-
const
|
|
22217
|
+
const stageMinWidth = lane.stage === void 0 ? 0 : maxNodeW + CONTAIN_PAD + STAGE_COLUMN_GAP;
|
|
22218
|
+
const newWidth = Math.max(lane.width, maxNodeW + padFor(lane) * 2, stageMinWidth);
|
|
22019
22219
|
widthOf.set(lane.id, newWidth);
|
|
22020
22220
|
deltaOf.set(lane.id, newWidth - lane.width);
|
|
22021
22221
|
}
|
|
@@ -22040,6 +22240,34 @@ function expandLaneGapsForEdgeLabels(lanes, nodes, edges, textMetrics = "proport
|
|
|
22040
22240
|
if (lanes.length < 2) return lanes;
|
|
22041
22241
|
const layoutedLanes = lanes.filter((l) => !(l.posX !== void 0 && l.posY !== void 0));
|
|
22042
22242
|
if (layoutedLanes.length < 2) return lanes;
|
|
22243
|
+
if (layoutedLanes.length === lanes.length && layoutedLanes.every((lane) => lane.stage !== void 0)) {
|
|
22244
|
+
const sortedStages = [...layoutedLanes].sort((a, b) => a.x - b.x);
|
|
22245
|
+
const stageIndexById = new Map(sortedStages.map((lane, index) => [lane.id, index]));
|
|
22246
|
+
const nodeLaneById = new Map(nodes.map((node) => [node.id, node.lane]));
|
|
22247
|
+
const requiredSurfaceGaps = new Array(sortedStages.length - 1).fill(STAGE_COLUMN_GAP);
|
|
22248
|
+
for (const edge of edges) {
|
|
22249
|
+
if (edge.routing !== "curve" || !edge.label && !edge.sub) continue;
|
|
22250
|
+
const fromIndex = stageIndexById.get(nodeLaneById.get(edge.from) ?? "");
|
|
22251
|
+
const toIndex = stageIndexById.get(nodeLaneById.get(edge.to) ?? "");
|
|
22252
|
+
if (fromIndex === void 0 || toIndex === void 0 || fromIndex === toIndex) continue;
|
|
22253
|
+
const lo = Math.min(fromIndex, toIndex);
|
|
22254
|
+
const hi = Math.max(fromIndex, toIndex);
|
|
22255
|
+
const labelWidth = computeLabelBoxW(edge.label, edge.sub, textMetrics);
|
|
22256
|
+
for (let pair = lo; pair < hi; pair++) {
|
|
22257
|
+
requiredSurfaceGaps[pair] = Math.max(requiredSurfaceGaps[pair], labelWidth);
|
|
22258
|
+
}
|
|
22259
|
+
}
|
|
22260
|
+
const shiftedXById2 = /* @__PURE__ */ new Map([[sortedStages[0].id, sortedStages[0].x]]);
|
|
22261
|
+
for (let index = 1; index < sortedStages.length; index++) {
|
|
22262
|
+
const previous = sortedStages[index - 1];
|
|
22263
|
+
const lane = sortedStages[index];
|
|
22264
|
+
const previousX = shiftedXById2.get(previous.id);
|
|
22265
|
+
const authoredGap = Math.max(0, lane.x - (previous.x + previous.width));
|
|
22266
|
+
const laneGap = Math.max(authoredGap, requiredSurfaceGaps[index - 1] - STAGE_COLUMN_GAP);
|
|
22267
|
+
shiftedXById2.set(lane.id, previousX + previous.width + laneGap);
|
|
22268
|
+
}
|
|
22269
|
+
return lanes.map((lane) => ({ ...lane, x: shiftedXById2.get(lane.id) ?? lane.x }));
|
|
22270
|
+
}
|
|
22043
22271
|
const nodeById = new Map(nodes.map((n) => [n.id, n]));
|
|
22044
22272
|
const sortedByX = [...layoutedLanes].sort((a, b) => a.x - b.x);
|
|
22045
22273
|
const laneIndexById = new Map(sortedByX.map((lane, i) => [lane.id, i]));
|
|
@@ -22111,7 +22339,7 @@ function recomputeContainedLanes(lanes, nodes) {
|
|
|
22111
22339
|
lifelineBottom = Math.max(lifelineBottom, bottom);
|
|
22112
22340
|
}
|
|
22113
22341
|
}
|
|
22114
|
-
|
|
22342
|
+
const contained = lanes.map((lane) => {
|
|
22115
22343
|
if (lane.lifeline) {
|
|
22116
22344
|
return {
|
|
22117
22345
|
...lane,
|
|
@@ -22129,6 +22357,7 @@ function recomputeContainedLanes(lanes, nodes) {
|
|
|
22129
22357
|
height: bottom - top + CONTAIN_PAD * 2 + LANE_LABEL_H
|
|
22130
22358
|
};
|
|
22131
22359
|
});
|
|
22360
|
+
return equalizeStageColumns(contained, nodes);
|
|
22132
22361
|
}
|
|
22133
22362
|
|
|
22134
22363
|
// src/layout/head-label.ts
|
|
@@ -22278,11 +22507,15 @@ function requiredStackGapForEdgeLabels(diag, allStacks) {
|
|
|
22278
22507
|
}
|
|
22279
22508
|
function layoutNodes(diag, lanes, textMetrics) {
|
|
22280
22509
|
const laneMap = new Map(lanes.map((l) => [l.id, l]));
|
|
22510
|
+
const metroDecisionIds = new Set(
|
|
22511
|
+
diag.edges.filter((edge) => edge.routing === "metro").flatMap((edge) => [edge.from, edge.to]).filter((id) => diag.nodes.some((node) => node.id === id && node.kind === "decision"))
|
|
22512
|
+
);
|
|
22513
|
+
const nodeSize = (node) => metroDecisionIds.has(node.id) ? { w: METRO_DECISION_WIDTH, h: METRO_DECISION_HEIGHT } : NODE_SIZE[node.kind];
|
|
22281
22514
|
const allStacks = Array.from(new Set(diag.nodes.map((n) => n.stack))).sort((a, b) => a - b);
|
|
22282
22515
|
const rowH = /* @__PURE__ */ new Map();
|
|
22283
22516
|
for (const stack of allStacks) {
|
|
22284
22517
|
const nodesAtStack = diag.nodes.filter((n) => n.stack === stack);
|
|
22285
|
-
const h = Math.max(...nodesAtStack.map((n) => \u7BB1\u306E\u9AD8\u30552(n,
|
|
22518
|
+
const h = Math.max(...nodesAtStack.map((n) => \u7BB1\u306E\u9AD8\u30552(n, nodeSize(n).h)));
|
|
22286
22519
|
rowH.set(stack, h);
|
|
22287
22520
|
}
|
|
22288
22521
|
const rowCy = /* @__PURE__ */ new Map();
|
|
@@ -22318,7 +22551,7 @@ function layoutNodes(diag, lanes, textMetrics) {
|
|
|
22318
22551
|
if (!lane) {
|
|
22319
22552
|
throw new Error(`cdl layout: node "${n.id}" \u306E lane "${n.lane}" \u304C\u5B9A\u7FA9\u3055\u308C\u3066\u3044\u306A\u3044`);
|
|
22320
22553
|
}
|
|
22321
|
-
const size =
|
|
22554
|
+
const size = nodeSize(n);
|
|
22322
22555
|
if (n.posX !== void 0 && n.posY !== void 0) {
|
|
22323
22556
|
const w2 = n.posW ?? n.w ?? autoRowsWidth(n, size.w, textMetrics);
|
|
22324
22557
|
const h2 = n.posH ?? n.h ?? rowH.get(n.stack) ?? size.h;
|
|
@@ -22441,6 +22674,9 @@ function dropUnsafeLaneDx(dxByLane, nodes) {
|
|
|
22441
22674
|
function applyRowLevelNodeShifts(nodes, lanes, nodeShifts) {
|
|
22442
22675
|
const dyByStack = aggregateRowDy(nodes, nodeShifts);
|
|
22443
22676
|
const dxByLane = dropUnsafeLaneDx(aggregateLaneDx(nodes, nodeShifts), nodes);
|
|
22677
|
+
for (const lane of lanes) {
|
|
22678
|
+
if (lane.stage !== void 0) dxByLane.delete(lane.id);
|
|
22679
|
+
}
|
|
22444
22680
|
let moved = false;
|
|
22445
22681
|
const outNodes = nodes.map((n) => {
|
|
22446
22682
|
const dx = dxByLane.get(n.lane) ?? 0;
|
|
@@ -22560,7 +22796,15 @@ function layout(diag) {
|
|
|
22560
22796
|
);
|
|
22561
22797
|
}
|
|
22562
22798
|
}
|
|
22563
|
-
const
|
|
22799
|
+
const contentViewBox = computeViewBox(
|
|
22800
|
+
containedLanesFinal,
|
|
22801
|
+
nodesFinal,
|
|
22802
|
+
edges,
|
|
22803
|
+
bboxes,
|
|
22804
|
+
diag.viewport
|
|
22805
|
+
);
|
|
22806
|
+
const legendLayout = diag.legend?.length ? layoutLegend(diag.legend, contentViewBox, textMetrics, nodesFinal) : void 0;
|
|
22807
|
+
const viewBox = legendLayout?.viewBox ?? contentViewBox;
|
|
22564
22808
|
return {
|
|
22565
22809
|
id: diag.id,
|
|
22566
22810
|
topic: diag.topic,
|
|
@@ -22587,6 +22831,7 @@ function layout(diag) {
|
|
|
22587
22831
|
...textMetrics === "monospace" ? { textMetrics: "monospace" } : {},
|
|
22588
22832
|
// 種類も配色と同じく空の目印を出さない。 遮断をここに揃えると手書きの図にも効く
|
|
22589
22833
|
...diag.type ? { type: diag.type } : {},
|
|
22834
|
+
...legendLayout ? { legend: legendLayout.legend } : {},
|
|
22590
22835
|
bboxes,
|
|
22591
22836
|
collisions,
|
|
22592
22837
|
nearCollisions,
|
|
@@ -22775,6 +23020,11 @@ function validate(diag) {
|
|
|
22775
23020
|
\u2192 \u4FEE\u6B63\u4F8B: .lane("${n.lane}", { x: 0, width: 400 }) \u3092 node \u5BA3\u8A00\u524D\u306B\u8FFD\u52A0`
|
|
22776
23021
|
);
|
|
22777
23022
|
}
|
|
23023
|
+
if (n.leaderTo !== void 0 && !nodeIds.has(n.leaderTo)) {
|
|
23024
|
+
errors.push(
|
|
23025
|
+
`[cdl] unknown-ref: node "${n.id}" \u306E leaderTo "${n.leaderTo}" \u304C node \u306B\u5B58\u5728\u3057\u307E\u305B\u3093${suggest(n.leaderTo, nodeIds, "node")}`
|
|
23026
|
+
);
|
|
23027
|
+
}
|
|
22778
23028
|
}
|
|
22779
23029
|
for (const e of diag.edges) {
|
|
22780
23030
|
if (!nodeIds.has(e.from)) {
|
|
@@ -24610,6 +24860,10 @@ function uniformLifelineEndY(lanes, nodes, starts = lifelineStartYs(nodes)) {
|
|
|
24610
24860
|
|
|
24611
24861
|
// src/render/edge-head.ts
|
|
24612
24862
|
var EDGE_HEAD_MUTED_MARKER_ID = "cdl-arrow-muted";
|
|
24863
|
+
var METRO_RETURN_ARROW_D = "M 21 0 L 4 9.5 L 4 -9.5 Z";
|
|
24864
|
+
function metroReturnArrowMarkerId(tone) {
|
|
24865
|
+
return `cdl-metro-return-arrow-${tone}`;
|
|
24866
|
+
}
|
|
24613
24867
|
var EDGE_HEAD_SHAPE = {
|
|
24614
24868
|
// 何も描かない端。 marker 自体を出さないので `d` は読まれない
|
|
24615
24869
|
none: { d: "", w: 10, h: 10, refX: 0, filled: false },
|
|
@@ -24664,6 +24918,7 @@ function \u7B49\u5E45\u306E\u5B57(text, fontSize) {
|
|
|
24664
24918
|
});
|
|
24665
24919
|
return out;
|
|
24666
24920
|
}
|
|
24921
|
+
var METRO_PENDING_ATTRIBUTE = "data-cdl-pending";
|
|
24667
24922
|
function defaultEdgeWidth(active) {
|
|
24668
24923
|
return active ? 2.5 : 1.25;
|
|
24669
24924
|
}
|
|
@@ -24682,12 +24937,14 @@ function CdlEdgeView({
|
|
|
24682
24937
|
drawing,
|
|
24683
24938
|
progress,
|
|
24684
24939
|
stateValues,
|
|
24685
|
-
flowing = false
|
|
24940
|
+
flowing = false,
|
|
24941
|
+
pending = false
|
|
24686
24942
|
}) {
|
|
24687
24943
|
const color = edgeColor(edge);
|
|
24688
|
-
const marker = edgeHeadMarkerName(edge.tone, edge.head, !active, edge.headFill);
|
|
24689
|
-
const tailMarker = edge.tailHead === void 0 ? void 0 : edgeHeadMarkerName(edge.tone, edge.tailHead, !active, edge.tailHeadFill);
|
|
24690
24944
|
const style = edge.style ?? "solid";
|
|
24945
|
+
const isMetroReturn = edge.metroReturn === true;
|
|
24946
|
+
const marker = isMetroReturn ? metroReturnArrowMarkerId(edge.tone) : edgeHeadMarkerName(edge.tone, edge.head, !active, edge.headFill);
|
|
24947
|
+
const tailMarker = edge.tailHead === void 0 ? void 0 : edgeHeadMarkerName(edge.tone, edge.tailHead, !active, edge.tailHeadFill);
|
|
24691
24948
|
const isDotted = style === "dotted-flow";
|
|
24692
24949
|
const isPassThrough = isDotted && Boolean(edge.dThrough);
|
|
24693
24950
|
const lineDotsD = isDotted ? shrinkPathEnd(edge.d, 12) : edge.d;
|
|
@@ -24697,6 +24954,7 @@ function CdlEdgeView({
|
|
|
24697
24954
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
24698
24955
|
"g",
|
|
24699
24956
|
{
|
|
24957
|
+
...pending ? { [METRO_PENDING_ATTRIBUTE]: "true" } : {},
|
|
24700
24958
|
"data-cdl-edge": edge.id,
|
|
24701
24959
|
"data-cdl-routing": edge.routing === "metro" ? "metro" : void 0,
|
|
24702
24960
|
"data-cdl-from": edge.from,
|
|
@@ -24722,11 +24980,12 @@ function CdlEdgeView({
|
|
|
24722
24980
|
fill: "none",
|
|
24723
24981
|
stroke: color,
|
|
24724
24982
|
strokeOpacity: active ? 0.95 : 0.9,
|
|
24725
|
-
strokeWidth: active ? 5 : 4,
|
|
24983
|
+
strokeWidth: edge.routing === "metro" ? METRO_LINE_WIDTH : active ? 5 : 4,
|
|
24726
24984
|
strokeDasharray: "0 18",
|
|
24727
24985
|
strokeLinecap: "round",
|
|
24728
24986
|
style: {
|
|
24729
|
-
transition: "stroke 280ms ease, stroke-opacity 280ms ease, stroke-width 280ms ease"
|
|
24987
|
+
transition: "stroke 280ms ease, stroke-opacity 280ms ease, stroke-width 280ms ease",
|
|
24988
|
+
strokeWidth: edge.routing === "metro" ? METRO_LINE_WIDTH_CSS : void 0
|
|
24730
24989
|
}
|
|
24731
24990
|
}
|
|
24732
24991
|
),
|
|
@@ -24781,7 +25040,9 @@ function SolidEdgePath({
|
|
|
24781
25040
|
const boundWidth = edge.widthBind && stateValues ? resolveNumericAttr(edge.widthBind, stateValues, defaultWidth) : defaultWidth;
|
|
24782
25041
|
const boundStroke = edge.strokeBind && stateValues ? interpolate(edge.strokeBind, stateValues) : color;
|
|
24783
25042
|
const boundDashOffset = edge.dashOffsetBind && stateValues ? resolveNumericAttr(edge.dashOffsetBind, stateValues, 0) : void 0;
|
|
24784
|
-
const
|
|
25043
|
+
const strokeWidth = edge.routing === "metro" && edge.widthBind === void 0 ? edge.metroReturn ? 6 : METRO_LINE_WIDTH : boundWidth;
|
|
25044
|
+
const strokeWidthCss = edge.routing === "metro" && !edge.metroReturn ? edge.widthBind === void 0 ? METRO_LINE_WIDTH_CSS : `var(--cdl-metro-line-width, ${strokeWidth}px)` : void 0;
|
|
25045
|
+
const dashArray = dashed ? edge.metroReturn ? "0 9.6" : "10 8" : active ? boundDashOffset !== void 0 ? "8 6" : void 0 : "4 5";
|
|
24785
25046
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
24786
25047
|
"path",
|
|
24787
25048
|
{
|
|
@@ -24790,14 +25051,15 @@ function SolidEdgePath({
|
|
|
24790
25051
|
fill: "none",
|
|
24791
25052
|
stroke: boundStroke,
|
|
24792
25053
|
strokeOpacity: active ? 0.95 : 0.9,
|
|
24793
|
-
strokeWidth
|
|
25054
|
+
strokeWidth,
|
|
24794
25055
|
strokeDasharray: dashArray,
|
|
24795
25056
|
strokeDashoffset: boundDashOffset,
|
|
24796
25057
|
strokeLinecap: "round",
|
|
24797
25058
|
markerEnd: marker === void 0 ? void 0 : `url(#${marker})`,
|
|
24798
25059
|
markerStart: tailMarker === void 0 ? void 0 : `url(#${tailMarker})`,
|
|
24799
25060
|
style: {
|
|
24800
|
-
transition: "stroke 280ms ease, stroke-opacity 280ms ease, stroke-width 280ms ease"
|
|
25061
|
+
transition: "stroke 280ms ease, stroke-opacity 280ms ease, stroke-width 280ms ease",
|
|
25062
|
+
strokeWidth: strokeWidthCss
|
|
24801
25063
|
}
|
|
24802
25064
|
}
|
|
24803
25065
|
);
|
|
@@ -25094,7 +25356,11 @@ function \u5272\u308B\u5019\u88DC(text) {
|
|
|
25094
25356
|
function \u5165\u3063\u3066\u3044\u308B([\u5DE6, \u53F3]) {
|
|
25095
25357
|
return \u5DE6 !== "" && \u53F3 !== "";
|
|
25096
25358
|
}
|
|
25097
|
-
function CardNode({
|
|
25359
|
+
function CardNode({
|
|
25360
|
+
node,
|
|
25361
|
+
active,
|
|
25362
|
+
compactTitleInset
|
|
25363
|
+
}) {
|
|
25098
25364
|
const accent = nodeAccent(node, "var(--cdl-tone-accent, #2d6a8f)");
|
|
25099
25365
|
const x = node.cx - node.w / 2;
|
|
25100
25366
|
const y = node.cy - node.h / 2;
|
|
@@ -25112,12 +25378,12 @@ function CardNode({ node, active }) {
|
|
|
25112
25378
|
});
|
|
25113
25379
|
const \u305A\u3089\u3057 = \u7E70\u308A\u4E0A\u3052 - \u4F59\u308A;
|
|
25114
25380
|
const titleY = compact ? \u5C0F\u578B\u306B\u547C\u3073\u540D ? node.h / 2 - 2 : node.h / 2 + 8 : 86 - \u305A\u3089\u3057;
|
|
25115
|
-
const titleX = compact ? node.w / 2 : 26;
|
|
25116
|
-
const paddingX = compact ?
|
|
25381
|
+
const titleX = compact ? compactTitleInset ?? node.w / 2 : 26;
|
|
25382
|
+
const paddingX = compact ? (compactTitleInset ?? 8) * 2 : 52;
|
|
25117
25383
|
const availableW = node.w - paddingX;
|
|
25118
25384
|
const initialTitleSize = compact ? 20 : 24;
|
|
25119
25385
|
const titleSize = fitTextSize(node.title, availableW, initialTitleSize, 11);
|
|
25120
|
-
const textAnchor = compact ? "middle" : "start";
|
|
25386
|
+
const textAnchor = compact && compactTitleInset === void 0 ? "middle" : "start";
|
|
25121
25387
|
const subtitleY = 124 - \u305A\u3089\u3057;
|
|
25122
25388
|
const \u6700\u5927\u306E\u884C\u9001\u308A = SUBTITLE_SIZE * \u884C\u9001\u308A\u306E\u500D\u7387;
|
|
25123
25389
|
const \u4E8C\u884C\u304C\u5165\u308B = !compact && subtitleY - \u6700\u5927\u306E\u884C\u9001\u308A / 2 - SUBTITLE_SIZE * ASCENT > titleY + titleSize * DESCENT && subtitleY + \u6700\u5927\u306E\u884C\u9001\u308A / 2 + SUBTITLE_SIZE * DESCENT <= node.h - 4;
|
|
@@ -25880,7 +26146,9 @@ function GenericNode({
|
|
|
25880
26146
|
value,
|
|
25881
26147
|
stateValues,
|
|
25882
26148
|
\u5024\u306E\u540D\u524D,
|
|
25883
|
-
textMetrics = "proportional"
|
|
26149
|
+
textMetrics = "proportional",
|
|
26150
|
+
showKindIcon = true,
|
|
26151
|
+
metroDecision = false
|
|
25884
26152
|
}) {
|
|
25885
26153
|
const base = STYLES[node.kind] ?? FALLBACK;
|
|
25886
26154
|
const toned = toneColor3(node.tone);
|
|
@@ -25911,14 +26179,14 @@ function GenericNode({
|
|
|
25911
26179
|
if (shape === "diamond") {
|
|
25912
26180
|
const cx = w / 2;
|
|
25913
26181
|
const cy = h / 2;
|
|
25914
|
-
const pad = 8;
|
|
26182
|
+
const pad = metroDecision ? 0 : 8;
|
|
25915
26183
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
25916
26184
|
"path",
|
|
25917
26185
|
{
|
|
25918
26186
|
d: `M ${cx} ${pad} L ${w - pad} ${cy} L ${cx} ${h - pad} L ${pad} ${cy} Z`,
|
|
25919
26187
|
fill: "var(--cdl-node-fill, #ffffff)",
|
|
25920
26188
|
stroke: active ? style.accent : "var(--cdl-divider, #d4d4d8)",
|
|
25921
|
-
strokeWidth: active ? 3 : 1.25
|
|
26189
|
+
strokeWidth: metroDecision ? 1.5 : active ? 3 : 1.25
|
|
25922
26190
|
}
|
|
25923
26191
|
);
|
|
25924
26192
|
}
|
|
@@ -25982,11 +26250,11 @@ function GenericNode({
|
|
|
25982
26250
|
const \u305A\u3089\u3057 = \u7E70\u308A\u4E0A\u3052 - \u4F59\u308A;
|
|
25983
26251
|
const \u7D75\u306E\u82AF = centered && STYLES[node.kind]?.shape === "cloud" ? h * CLOUD_ART_CENTER_RISE : 0;
|
|
25984
26252
|
const eyebrowY = centered ? h / 2 - 26 - \u7D75\u306E\u82AF : 32 + cylinderShift + \u4F59\u308A;
|
|
25985
|
-
const titleY = genericTitleBaselineY(node.kind, h, hasRows) - \u305A\u3089\u3057 - \u7D75\u306E\u82AF;
|
|
26253
|
+
const titleY = metroDecision ? h / 2 + 9 : genericTitleBaselineY(node.kind, h, hasRows) - \u305A\u3089\u3057 - \u7D75\u306E\u82AF;
|
|
25986
26254
|
const subtitleY = centered ? h / 2 + 28 - \u7D75\u306E\u82AF : 96 + cylinderShift - \u305A\u3089\u3057;
|
|
25987
26255
|
const iconX = centered ? w / 2 + 40 : w - 48;
|
|
25988
26256
|
const iconY = centered ? h / 2 - 44 - \u7D75\u306E\u82AF : 18 + cylinderShift;
|
|
25989
|
-
const dominantBaseline = centered ? "middle" : void 0;
|
|
26257
|
+
const dominantBaseline = centered && !metroDecision ? "middle" : void 0;
|
|
25990
26258
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
25991
26259
|
"g",
|
|
25992
26260
|
{
|
|
@@ -25995,12 +26263,12 @@ function GenericNode({
|
|
|
25995
26263
|
"data-cdl-look": style.look,
|
|
25996
26264
|
children: [
|
|
25997
26265
|
shapeEl,
|
|
25998
|
-
/* @__PURE__ */ jsxRuntime.jsxs("g", { transform: `translate(${iconX} ${iconY}) scale(1)`, "data-cdl-role": "node-kind-icon", children: [
|
|
26266
|
+
showKindIcon && /* @__PURE__ */ jsxRuntime.jsxs("g", { transform: `translate(${iconX} ${iconY}) scale(1)`, "data-cdl-role": "node-kind-icon", children: [
|
|
25999
26267
|
/* @__PURE__ */ jsxRuntime.jsx("rect", { width: 24, height: 24, fill: "transparent" }),
|
|
26000
26268
|
/* @__PURE__ */ jsxRuntime.jsx("path", { d: style.icon, fill: style.eyebrowColor, opacity: 0.7, transform: "scale(1)" })
|
|
26001
26269
|
] }),
|
|
26002
26270
|
node.eyebrow && /* @__PURE__ */ jsxRuntime.jsx("text", { x: textX, y: eyebrowY, fontSize: 17, fontWeight: 700, letterSpacing: 1.5, fill: paint.onSolid ? "var(--cdl-node-fill, #ffffff)" : style.eyebrowColor, textAnchor, dominantBaseline, children: node.eyebrow }),
|
|
26003
|
-
/* @__PURE__ */ jsxRuntime.jsx("text", { "data-cdl-role": "node-label", x: textX, y: titleY, fontSize: 20, fontWeight: 700, fill: paint.onSolid ? "var(--cdl-node-fill, #ffffff)" : "var(--cdl-text, #1a1f2a)", textAnchor, dominantBaseline, style: node.kind === "function" || node.kind === "api" ? { fontFamily: "'JetBrains Mono', monospace" } : void 0, children: node.kind === "function" || node.kind === "api" ? \u7B49\u5E45\u306E\u5B57(node.title, 20) : node.title }),
|
|
26271
|
+
/* @__PURE__ */ jsxRuntime.jsx("text", { "data-cdl-role": "node-label", x: textX, y: titleY, fontSize: metroDecision ? 26 : 20, fontWeight: 700, fill: paint.onSolid ? "var(--cdl-node-fill, #ffffff)" : "var(--cdl-text, #1a1f2a)", textAnchor, dominantBaseline, style: node.kind === "function" || node.kind === "api" ? { fontFamily: "'JetBrains Mono', monospace" } : void 0, children: node.kind === "function" || node.kind === "api" ? \u7B49\u5E45\u306E\u5B57(node.title, 20) : node.title }),
|
|
26004
26272
|
node.subtitle && /* @__PURE__ */ jsxRuntime.jsx("text", { x: textX, y: subtitleY, fontSize: 17, fill: paint.onSolid ? "var(--cdl-node-fill, #ffffff)" : "var(--cdl-text-dim, #5a6270)", textAnchor, dominantBaseline, style: { fontFamily: "'JetBrains Mono', monospace" }, children: \u7B49\u5E45\u306E\u5B57(node.subtitle, 17) }),
|
|
26005
26273
|
resolvedValue && /* @__PURE__ */ jsxRuntime.jsx(
|
|
26006
26274
|
"text",
|
|
@@ -26049,50 +26317,176 @@ function GenericNode({
|
|
|
26049
26317
|
var MARK_INNER_RATIO = 0.56;
|
|
26050
26318
|
var RING_WIDTH_ACTIVE = 6;
|
|
26051
26319
|
var RING_WIDTH_IDLE = 4;
|
|
26320
|
+
var METRO_START_RADIUS = 17;
|
|
26321
|
+
var METRO_END_RADIUS = 19;
|
|
26322
|
+
var METRO_END_RING_WIDTH = 3.5;
|
|
26323
|
+
var METRO_END_INNER_RADIUS = 10;
|
|
26052
26324
|
var MARK_DEFAULT = "var(--cdl-tone-accent, #2d6a8f)";
|
|
26053
26325
|
function markRadius(node) {
|
|
26054
26326
|
return Math.min(node.w, node.h) / 2;
|
|
26055
26327
|
}
|
|
26056
|
-
function MarkStartNode({
|
|
26328
|
+
function MarkStartNode({
|
|
26329
|
+
node,
|
|
26330
|
+
metro = false
|
|
26331
|
+
}) {
|
|
26057
26332
|
const \u8272 = nodeAccent(node, MARK_DEFAULT);
|
|
26058
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
26059
|
-
"
|
|
26333
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
26334
|
+
"g",
|
|
26060
26335
|
{
|
|
26061
|
-
"data-cdl-role": "
|
|
26062
|
-
|
|
26063
|
-
|
|
26064
|
-
|
|
26065
|
-
|
|
26066
|
-
|
|
26336
|
+
"data-cdl-role": metro ? "mark-start" : void 0,
|
|
26337
|
+
transform: `translate(${node.cx - node.w / 2} ${node.cy - node.h / 2})`,
|
|
26338
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
26339
|
+
"circle",
|
|
26340
|
+
{
|
|
26341
|
+
"data-cdl-role": "node-body",
|
|
26342
|
+
"data-cdl-mark": "start",
|
|
26343
|
+
cx: node.w / 2,
|
|
26344
|
+
cy: node.h / 2,
|
|
26345
|
+
r: metro ? METRO_START_RADIUS : markRadius(node),
|
|
26346
|
+
fill: \u8272
|
|
26347
|
+
}
|
|
26348
|
+
)
|
|
26067
26349
|
}
|
|
26068
|
-
)
|
|
26350
|
+
);
|
|
26069
26351
|
}
|
|
26070
|
-
function MarkEndNode({
|
|
26352
|
+
function MarkEndNode({
|
|
26353
|
+
node,
|
|
26354
|
+
active,
|
|
26355
|
+
metro = false
|
|
26356
|
+
}) {
|
|
26071
26357
|
const \u8272 = nodeAccent(node, MARK_DEFAULT);
|
|
26072
|
-
const r = markRadius(node);
|
|
26073
|
-
const \u8F2A\u306E\u592A\u3055 = active ? RING_WIDTH_ACTIVE : RING_WIDTH_IDLE;
|
|
26074
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
26358
|
+
const r = metro ? METRO_END_RADIUS : markRadius(node);
|
|
26359
|
+
const \u8F2A\u306E\u592A\u3055 = metro ? METRO_END_RING_WIDTH : active ? RING_WIDTH_ACTIVE : RING_WIDTH_IDLE;
|
|
26360
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
26361
|
+
"g",
|
|
26362
|
+
{
|
|
26363
|
+
"data-cdl-role": metro ? "mark-end" : void 0,
|
|
26364
|
+
transform: `translate(${node.cx - node.w / 2} ${node.cy - node.h / 2})`,
|
|
26365
|
+
children: [
|
|
26366
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
26367
|
+
"circle",
|
|
26368
|
+
{
|
|
26369
|
+
"data-cdl-role": "node-body",
|
|
26370
|
+
"data-cdl-mark": "end",
|
|
26371
|
+
cx: node.w / 2,
|
|
26372
|
+
cy: node.h / 2,
|
|
26373
|
+
r: metro ? r : Math.max(0, r - \u8F2A\u306E\u592A\u3055 / 2),
|
|
26374
|
+
fill: "var(--cdl-node-fill, #ffffff)",
|
|
26375
|
+
stroke: \u8272,
|
|
26376
|
+
strokeWidth: \u8F2A\u306E\u592A\u3055
|
|
26377
|
+
}
|
|
26378
|
+
),
|
|
26379
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
26380
|
+
"circle",
|
|
26381
|
+
{
|
|
26382
|
+
"data-cdl-role": "node-inner",
|
|
26383
|
+
cx: node.w / 2,
|
|
26384
|
+
cy: node.h / 2,
|
|
26385
|
+
r: metro ? METRO_END_INNER_RADIUS : Math.max(0, r * MARK_INNER_RATIO),
|
|
26386
|
+
fill: \u8272
|
|
26387
|
+
}
|
|
26388
|
+
)
|
|
26389
|
+
]
|
|
26390
|
+
}
|
|
26391
|
+
);
|
|
26392
|
+
}
|
|
26393
|
+
var METRO_STATION_RADIUS = 16;
|
|
26394
|
+
var METRO_STATION_STROKE_WIDTH = 6;
|
|
26395
|
+
var METRO_STATION_RADIUS_CSS = `var(--cdl-metro-station-radius, ${METRO_STATION_RADIUS}px)`;
|
|
26396
|
+
var METRO_STATION_STROKE_WIDTH_CSS = `var(--cdl-metro-station-stroke-width, ${METRO_STATION_STROKE_WIDTH}px)`;
|
|
26397
|
+
var STATION_DEFAULT = "var(--cdl-tone-accent, #2d6a8f)";
|
|
26398
|
+
var STATION_NAME_FONT_SIZE = 25;
|
|
26399
|
+
var STATION_NAME_GAP = 18;
|
|
26400
|
+
var STATION_NAME_RIGHT_GAP = 32;
|
|
26401
|
+
var STATION_NAME_RIGHT_BASELINE = 9;
|
|
26402
|
+
var STATION_SUBTITLE_FONT_SIZE = 18;
|
|
26403
|
+
var STATION_SUBTITLE_GAP = 22;
|
|
26404
|
+
function StationNode({
|
|
26405
|
+
node,
|
|
26406
|
+
nameRight = false
|
|
26407
|
+
}) {
|
|
26408
|
+
const name = node.title.trim();
|
|
26409
|
+
const subtitle = node.subtitle?.trim() ?? "";
|
|
26410
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
|
|
26075
26411
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
26076
26412
|
"circle",
|
|
26077
26413
|
{
|
|
26078
26414
|
"data-cdl-role": "node-body",
|
|
26079
|
-
"data-cdl-mark": "
|
|
26080
|
-
cx: node.
|
|
26081
|
-
cy: node.
|
|
26082
|
-
r:
|
|
26415
|
+
"data-cdl-mark": "station",
|
|
26416
|
+
cx: node.cx,
|
|
26417
|
+
cy: node.cy,
|
|
26418
|
+
r: METRO_STATION_RADIUS,
|
|
26083
26419
|
fill: "var(--cdl-node-fill, #ffffff)",
|
|
26084
|
-
stroke:
|
|
26085
|
-
strokeWidth:
|
|
26420
|
+
stroke: nodeAccent(node, STATION_DEFAULT),
|
|
26421
|
+
strokeWidth: METRO_STATION_STROKE_WIDTH,
|
|
26422
|
+
style: { r: METRO_STATION_RADIUS_CSS, strokeWidth: METRO_STATION_STROKE_WIDTH_CSS }
|
|
26086
26423
|
}
|
|
26087
26424
|
),
|
|
26425
|
+
name !== "" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
26426
|
+
"text",
|
|
26427
|
+
{
|
|
26428
|
+
"data-cdl-role": "shape-name",
|
|
26429
|
+
x: nameRight ? node.cx + STATION_NAME_RIGHT_GAP : node.cx,
|
|
26430
|
+
y: nameRight ? node.cy + STATION_NAME_RIGHT_BASELINE : node.cy - METRO_STATION_RADIUS - STATION_NAME_GAP,
|
|
26431
|
+
textAnchor: nameRight ? "start" : "middle",
|
|
26432
|
+
fontSize: STATION_NAME_FONT_SIZE,
|
|
26433
|
+
fontWeight: 700,
|
|
26434
|
+
fill: "var(--cdl-text, #23201b)",
|
|
26435
|
+
stroke: "var(--cdl-node-fill, #ffffff)",
|
|
26436
|
+
strokeWidth: 8,
|
|
26437
|
+
strokeLinejoin: "round",
|
|
26438
|
+
paintOrder: "stroke",
|
|
26439
|
+
children: name
|
|
26440
|
+
}
|
|
26441
|
+
),
|
|
26442
|
+
subtitle !== "" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
26443
|
+
"text",
|
|
26444
|
+
{
|
|
26445
|
+
"data-cdl-role": "shape-value",
|
|
26446
|
+
x: node.cx,
|
|
26447
|
+
y: node.cy + METRO_STATION_RADIUS + STATION_SUBTITLE_GAP,
|
|
26448
|
+
textAnchor: "middle",
|
|
26449
|
+
fontSize: STATION_SUBTITLE_FONT_SIZE,
|
|
26450
|
+
fill: "var(--cdl-text-dim, #5a6270)",
|
|
26451
|
+
children: subtitle
|
|
26452
|
+
}
|
|
26453
|
+
)
|
|
26454
|
+
] });
|
|
26455
|
+
}
|
|
26456
|
+
function TimelineNumberNode({ node }) {
|
|
26457
|
+
const radius = Math.max(0, Math.min(node.w, node.h) / 2 - TIMELINE_NUMBER_STROKE / 2);
|
|
26458
|
+
const fontSize = fitTextSize(
|
|
26459
|
+
node.title,
|
|
26460
|
+
titleUsableWidth(node.kind, node.w, node.h),
|
|
26461
|
+
18,
|
|
26462
|
+
MIN_TEXT_SIZE
|
|
26463
|
+
);
|
|
26464
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
26088
26465
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
26089
26466
|
"circle",
|
|
26090
26467
|
{
|
|
26091
|
-
"data-cdl-role": "node-
|
|
26092
|
-
|
|
26093
|
-
|
|
26094
|
-
|
|
26095
|
-
|
|
26468
|
+
"data-cdl-role": "node-body",
|
|
26469
|
+
"data-cdl-mark": "timeline-number",
|
|
26470
|
+
cx: node.cx,
|
|
26471
|
+
cy: node.cy,
|
|
26472
|
+
r: radius,
|
|
26473
|
+
fill: "var(--cdl-node-fill, #ffffff)",
|
|
26474
|
+
stroke: nodeAccent(node, STATION_DEFAULT),
|
|
26475
|
+
strokeWidth: TIMELINE_NUMBER_STROKE
|
|
26476
|
+
}
|
|
26477
|
+
),
|
|
26478
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
26479
|
+
"text",
|
|
26480
|
+
{
|
|
26481
|
+
"data-cdl-role": "node-label",
|
|
26482
|
+
x: node.cx,
|
|
26483
|
+
y: node.cy,
|
|
26484
|
+
textAnchor: "middle",
|
|
26485
|
+
dominantBaseline: "central",
|
|
26486
|
+
fontSize,
|
|
26487
|
+
fontWeight: 700,
|
|
26488
|
+
fill: "var(--cdl-text, #1a1f2a)",
|
|
26489
|
+
children: node.title
|
|
26096
26490
|
}
|
|
26097
26491
|
)
|
|
26098
26492
|
] });
|
|
@@ -26424,27 +26818,6 @@ function interpolateColor(template, stateValues, fallback) {
|
|
|
26424
26818
|
if (!template) return fallback;
|
|
26425
26819
|
return interpolate(template, stateValues);
|
|
26426
26820
|
}
|
|
26427
|
-
var STATION_STROKE_ACTIVE = 4;
|
|
26428
|
-
var STATION_STROKE_IDLE = 3;
|
|
26429
|
-
var STATION_DEFAULT = "var(--cdl-tone-accent, #2d6a8f)";
|
|
26430
|
-
function StationNode({ node, active }) {
|
|
26431
|
-
const strokeWidth = active ? STATION_STROKE_ACTIVE : STATION_STROKE_IDLE;
|
|
26432
|
-
const radius = Math.max(0, Math.min(node.w, node.h) / 2 - strokeWidth / 2);
|
|
26433
|
-
const \u5F62 = /* @__PURE__ */ jsxRuntime.jsx(
|
|
26434
|
-
"circle",
|
|
26435
|
-
{
|
|
26436
|
-
"data-cdl-role": "node-body",
|
|
26437
|
-
"data-cdl-mark": "station",
|
|
26438
|
-
cx: node.cx,
|
|
26439
|
-
cy: node.cy,
|
|
26440
|
-
r: radius,
|
|
26441
|
-
fill: "var(--cdl-node-fill, #ffffff)",
|
|
26442
|
-
stroke: nodeAccent(node, STATION_DEFAULT),
|
|
26443
|
-
strokeWidth
|
|
26444
|
-
}
|
|
26445
|
-
);
|
|
26446
|
-
return renderShapeWithOutsideLabels(\u5F62, node, "middle");
|
|
26447
|
-
}
|
|
26448
26821
|
|
|
26449
26822
|
// src/kinds/label-stack.ts
|
|
26450
26823
|
function \u540D\u672D\u306E\u6BB5\u3092\u307B\u3069\u304F(\u771F\u306Ey, \u9593\u9694, \u4E0A\u9650, \u4E0B\u9650) {
|
|
@@ -33606,10 +33979,14 @@ function CdlNodeView({
|
|
|
33606
33979
|
stateValues,
|
|
33607
33980
|
currentPhaseId,
|
|
33608
33981
|
chartLineScale,
|
|
33982
|
+
compactTitleInset,
|
|
33609
33983
|
\u95A2\u4FC2\u306E\u53D7\u3051\u53E3,
|
|
33610
33984
|
lang,
|
|
33611
33985
|
textMetrics,
|
|
33612
|
-
\u5024\u306E\u540D\u524D
|
|
33986
|
+
\u5024\u306E\u540D\u524D,
|
|
33987
|
+
metroDiagram = false,
|
|
33988
|
+
metroDecision = false,
|
|
33989
|
+
stationNameRight = false
|
|
33613
33990
|
}) {
|
|
33614
33991
|
const value = node.value ? interpolate(node.value, stateValues, \u5024\u306E\u540D\u524D) : void 0;
|
|
33615
33992
|
const rows = (node.rows ?? []).map((r) => interpolate(r, stateValues, \u5024\u306E\u540D\u524D));
|
|
@@ -33650,7 +34027,7 @@ function CdlNodeView({
|
|
|
33650
34027
|
case "event":
|
|
33651
34028
|
return /* @__PURE__ */ jsxRuntime.jsx(EventNode, { node: resolvedNode, active, progress });
|
|
33652
34029
|
case "card":
|
|
33653
|
-
return /* @__PURE__ */ jsxRuntime.jsx(CardNode, { node: resolvedNode, active });
|
|
34030
|
+
return /* @__PURE__ */ jsxRuntime.jsx(CardNode, { node: resolvedNode, active, compactTitleInset });
|
|
33654
34031
|
// 時系列のやり取り (#578)。 1 つの箱が図を丸ごと描く = 縦が時間で、参加者は箱を持たない
|
|
33655
34032
|
case "sequence-board":
|
|
33656
34033
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -33937,11 +34314,13 @@ function CdlNodeView({
|
|
|
33937
34314
|
case "shape-customer-service":
|
|
33938
34315
|
return /* @__PURE__ */ jsxRuntime.jsx(ShapeCustomerServiceNode, { node: resolvedNode, active });
|
|
33939
34316
|
case "mark-start":
|
|
33940
|
-
return /* @__PURE__ */ jsxRuntime.jsx(MarkStartNode, { node: resolvedNode, active });
|
|
34317
|
+
return /* @__PURE__ */ jsxRuntime.jsx(MarkStartNode, { node: resolvedNode, active, metro: metroDiagram });
|
|
33941
34318
|
case "mark-end":
|
|
33942
|
-
return /* @__PURE__ */ jsxRuntime.jsx(MarkEndNode, { node: resolvedNode, active });
|
|
34319
|
+
return /* @__PURE__ */ jsxRuntime.jsx(MarkEndNode, { node: resolvedNode, active, metro: metroDiagram });
|
|
33943
34320
|
case "station":
|
|
33944
|
-
return /* @__PURE__ */ jsxRuntime.jsx(StationNode, { node: resolvedNode, active });
|
|
34321
|
+
return /* @__PURE__ */ jsxRuntime.jsx(StationNode, { node: resolvedNode, active, nameRight: stationNameRight });
|
|
34322
|
+
case "timeline-number":
|
|
34323
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TimelineNumberNode, { node: resolvedNode });
|
|
33945
34324
|
default:
|
|
33946
34325
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
33947
34326
|
GenericNode,
|
|
@@ -33951,7 +34330,9 @@ function CdlNodeView({
|
|
|
33951
34330
|
value: node.value,
|
|
33952
34331
|
stateValues,
|
|
33953
34332
|
\u5024\u306E\u540D\u524D,
|
|
33954
|
-
textMetrics
|
|
34333
|
+
textMetrics,
|
|
34334
|
+
showKindIcon: !(metroDiagram && node.kind === "decision"),
|
|
34335
|
+
metroDecision
|
|
33955
34336
|
}
|
|
33956
34337
|
);
|
|
33957
34338
|
}
|
|
@@ -34065,6 +34446,112 @@ function \u7BB1\u306E\u4E0A\u306E\u8A9E(node, textMetrics = "proportional") {
|
|
|
34065
34446
|
)
|
|
34066
34447
|
] });
|
|
34067
34448
|
}
|
|
34449
|
+
var ink = "var(--cdl-text-accent, #143a52)";
|
|
34450
|
+
var paper = "var(--cdl-stage-bg, #f8fafc)";
|
|
34451
|
+
var LEGEND_MARK_RENDERERS = {
|
|
34452
|
+
diamond: () => /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M 23 -26 L 46 -8 L 23 10 L 0 -8 Z", fill: "none", stroke: ink, strokeWidth: 2 }),
|
|
34453
|
+
"filled-circle": () => /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: 23, cy: -8, r: 11, fill: ink }),
|
|
34454
|
+
"double-circle": () => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
34455
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: 23, cy: -8, r: 12, fill: "none", stroke: ink, strokeWidth: 2.5 }),
|
|
34456
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: 23, cy: -8, r: 6, fill: ink })
|
|
34457
|
+
] }),
|
|
34458
|
+
"dotted-line": () => /* @__PURE__ */ jsxRuntime.jsx(
|
|
34459
|
+
"path",
|
|
34460
|
+
{
|
|
34461
|
+
d: `M 0 -8 H ${LEGEND_MARK_REFERENCE_WIDTH}`,
|
|
34462
|
+
fill: "none",
|
|
34463
|
+
stroke: ink,
|
|
34464
|
+
strokeWidth: 6,
|
|
34465
|
+
strokeLinecap: "round",
|
|
34466
|
+
strokeDasharray: "0 9.6"
|
|
34467
|
+
}
|
|
34468
|
+
),
|
|
34469
|
+
"solid-line": () => /* @__PURE__ */ jsxRuntime.jsx(
|
|
34470
|
+
"path",
|
|
34471
|
+
{
|
|
34472
|
+
d: `M 0 -8 H ${LEGEND_MARK_REFERENCE_WIDTH}`,
|
|
34473
|
+
fill: "none",
|
|
34474
|
+
stroke: ink,
|
|
34475
|
+
strokeWidth: 4,
|
|
34476
|
+
strokeLinecap: "round"
|
|
34477
|
+
}
|
|
34478
|
+
),
|
|
34479
|
+
"curved-line": () => /* @__PURE__ */ jsxRuntime.jsx(
|
|
34480
|
+
"path",
|
|
34481
|
+
{
|
|
34482
|
+
d: `M 0 6 C 12 -22, 34 -22, ${LEGEND_MARK_REFERENCE_WIDTH} 6`,
|
|
34483
|
+
fill: "none",
|
|
34484
|
+
stroke: ink,
|
|
34485
|
+
strokeWidth: 4,
|
|
34486
|
+
strokeLinecap: "round"
|
|
34487
|
+
}
|
|
34488
|
+
),
|
|
34489
|
+
"rounded-label": () => /* @__PURE__ */ jsxRuntime.jsx(
|
|
34490
|
+
"rect",
|
|
34491
|
+
{
|
|
34492
|
+
x: 0,
|
|
34493
|
+
y: -23,
|
|
34494
|
+
width: LEGEND_MARK_REFERENCE_WIDTH,
|
|
34495
|
+
height: 30,
|
|
34496
|
+
rx: 9,
|
|
34497
|
+
fill: paper,
|
|
34498
|
+
stroke: ink,
|
|
34499
|
+
strokeWidth: 2
|
|
34500
|
+
}
|
|
34501
|
+
),
|
|
34502
|
+
"numbered-circle": () => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
34503
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: 23, cy: -8, r: 13, fill: paper, stroke: ink, strokeWidth: 2.5 }),
|
|
34504
|
+
/* @__PURE__ */ jsxRuntime.jsx("text", { x: 23, y: -2, textAnchor: "middle", fontSize: 17, fontWeight: 700, fill: ink, children: "1" })
|
|
34505
|
+
] }),
|
|
34506
|
+
station: () => /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: 23, cy: -8, r: 11, fill: paper, stroke: ink, strokeWidth: 4 }),
|
|
34507
|
+
arrow: () => /* @__PURE__ */ jsxRuntime.jsx(
|
|
34508
|
+
"path",
|
|
34509
|
+
{
|
|
34510
|
+
d: `M 0 -8 H 42 M 32 -18 L ${LEGEND_MARK_REFERENCE_WIDTH} -8 L 32 2`,
|
|
34511
|
+
fill: "none",
|
|
34512
|
+
stroke: ink,
|
|
34513
|
+
strokeWidth: 3,
|
|
34514
|
+
strokeLinecap: "round",
|
|
34515
|
+
strokeLinejoin: "round"
|
|
34516
|
+
}
|
|
34517
|
+
)
|
|
34518
|
+
};
|
|
34519
|
+
function CdlLegend({ items }) {
|
|
34520
|
+
return /* @__PURE__ */ jsxRuntime.jsx("g", { "data-cdl-role": "legend", children: items.map((item, index) => {
|
|
34521
|
+
const Mark = LEGEND_MARK_RENDERERS[item.mark];
|
|
34522
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
34523
|
+
"g",
|
|
34524
|
+
{
|
|
34525
|
+
"data-cdl-role": "legend-item",
|
|
34526
|
+
"data-cdl-y": item.y,
|
|
34527
|
+
transform: `translate(${item.x} ${item.y})`,
|
|
34528
|
+
children: [
|
|
34529
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
34530
|
+
"g",
|
|
34531
|
+
{
|
|
34532
|
+
"data-cdl-role": "legend-mark",
|
|
34533
|
+
"data-cdl-legend-mark": item.mark,
|
|
34534
|
+
transform: `scale(${LEGEND_MARK_SCALE})`,
|
|
34535
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Mark, {})
|
|
34536
|
+
}
|
|
34537
|
+
),
|
|
34538
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
34539
|
+
"text",
|
|
34540
|
+
{
|
|
34541
|
+
"data-cdl-role": "legend-text",
|
|
34542
|
+
x: LEGEND_MARK_WIDTH + LEGEND_MARK_TEXT_GAP,
|
|
34543
|
+
y: 0,
|
|
34544
|
+
fontSize: LEGEND_FONT_SIZE,
|
|
34545
|
+
fill: "var(--cdl-text-mute, #4d7187)",
|
|
34546
|
+
children: item.text
|
|
34547
|
+
}
|
|
34548
|
+
)
|
|
34549
|
+
]
|
|
34550
|
+
},
|
|
34551
|
+
`${item.mark}-${index}`
|
|
34552
|
+
);
|
|
34553
|
+
}) });
|
|
34554
|
+
}
|
|
34068
34555
|
|
|
34069
34556
|
// src/render/relation-focus.ts
|
|
34070
34557
|
function relatedFocusSet(edges, nodeId) {
|
|
@@ -34077,10 +34564,17 @@ function relatedFocusSet(edges, nodeId) {
|
|
|
34077
34564
|
}
|
|
34078
34565
|
return \u96C6\u5408;
|
|
34079
34566
|
}
|
|
34567
|
+
var METRO_LANE_BADGE_WIDTH = 200;
|
|
34568
|
+
var METRO_LANE_BADGE_HEIGHT = 88;
|
|
34569
|
+
var METRO_LANE_BADGE_INSET = 24;
|
|
34570
|
+
var METRO_LANE_GUIDE_GAP = 24;
|
|
34080
34571
|
function \u63CF\u304F\u3082\u306E\u304C\u3042\u308B(laid) {
|
|
34572
|
+
if (laid.legend && laid.legend.length > 0) return true;
|
|
34081
34573
|
if (laid.edges.length > 0) return true;
|
|
34082
34574
|
if (laid.nodes.some((n) => isRenderedNode(n))) return true;
|
|
34083
|
-
return laid.lanes.some(
|
|
34575
|
+
return laid.lanes.some(
|
|
34576
|
+
(l) => l.contain === true || l.lifeline === true || Boolean(l.label) || l.stage !== void 0 || l.metro !== void 0
|
|
34577
|
+
);
|
|
34084
34578
|
}
|
|
34085
34579
|
function CdlStage({
|
|
34086
34580
|
laid,
|
|
@@ -34121,6 +34615,7 @@ function CdlStage({
|
|
|
34121
34615
|
[\u95A2\u4FC2\u3092\u5149\u3089\u305B\u308B, \u7126\u70B9, laid.edges]
|
|
34122
34616
|
);
|
|
34123
34617
|
const activeSet = \u7126\u70B9\u306E\u96C6\u5408 ?? new Set(currentPhase?.activate ?? []);
|
|
34618
|
+
const \u8DEF\u7DDA\u56F3 = laid.edges.some((edge) => edge.routing === "metro") && laid.nodes.some((node) => node.kind === "station");
|
|
34124
34619
|
const \u7BB1\u306E\u53D7\u3051\u53E3 = \u95A2\u4FC2\u3092\u5149\u3089\u305B\u308B ? { \u89E6\u308C\u305F, \u96E2\u308C\u305F, \u62BC\u3057\u305F, \u7126\u70B9: \u7126\u70B9?.id ?? null } : void 0;
|
|
34125
34620
|
const \u77E2\u5370\u306E\u51FA\u756A = react.useMemo(() => {
|
|
34126
34621
|
const \u521D\u51FA = /* @__PURE__ */ new Map();
|
|
@@ -34149,9 +34644,15 @@ function CdlStage({
|
|
|
34149
34644
|
const first = \u521D\u51FA.get(edgeId);
|
|
34150
34645
|
if (first === void 0) return false;
|
|
34151
34646
|
return \u4ECA === first;
|
|
34647
|
+
},
|
|
34648
|
+
/** 初出の段より前にある区間だけを、通過前として選べるようにする。 */
|
|
34649
|
+
\u307E\u3060\u304B: (edgeId) => {
|
|
34650
|
+
const first = \u521D\u51FA.get(edgeId);
|
|
34651
|
+
return first !== void 0 && \u4ECA >= 0 && \u4ECA < first;
|
|
34152
34652
|
}
|
|
34153
34653
|
};
|
|
34154
34654
|
}, [laid.phases, currentPhase, laid.edgeReveal]);
|
|
34655
|
+
const \u7DDA\u3092\u63CF\u304F = (edge) => edge.routing === "metro" || \u77E2\u5370\u306E\u51FA\u756A.\u51FA\u308B\u304B(edge.id);
|
|
34155
34656
|
const drawSet = new Set(currentPhase?.draw ?? []);
|
|
34156
34657
|
const chartLineScales = react.useMemo(() => {
|
|
34157
34658
|
const nodes = laid.nodes.filter((node) => node.kind === "chart-line");
|
|
@@ -34239,7 +34740,53 @@ function CdlStage({
|
|
|
34239
34740
|
)
|
|
34240
34741
|
);
|
|
34241
34742
|
}, [laid]);
|
|
34743
|
+
const metroReturnArrowMarkers = react.useMemo(() => {
|
|
34744
|
+
const tones = new Set(
|
|
34745
|
+
laid.edges.filter((edge) => edge.metroReturn === true).map((edge) => edge.tone)
|
|
34746
|
+
);
|
|
34747
|
+
return [...tones].map((tone) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
34748
|
+
"marker",
|
|
34749
|
+
{
|
|
34750
|
+
id: metroReturnArrowMarkerId(tone),
|
|
34751
|
+
viewBox: "0 -9.5 21 19",
|
|
34752
|
+
refX: "0",
|
|
34753
|
+
refY: "0",
|
|
34754
|
+
markerWidth: "21",
|
|
34755
|
+
markerHeight: "19",
|
|
34756
|
+
markerUnits: "userSpaceOnUse",
|
|
34757
|
+
orient: "auto",
|
|
34758
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
34759
|
+
"path",
|
|
34760
|
+
{
|
|
34761
|
+
"data-cdl-role": "edge-arrowhead",
|
|
34762
|
+
"data-cdl-mark": "metro-return-arrow",
|
|
34763
|
+
d: METRO_RETURN_ARROW_D,
|
|
34764
|
+
fill: TONE[tone]
|
|
34765
|
+
}
|
|
34766
|
+
)
|
|
34767
|
+
},
|
|
34768
|
+
tone
|
|
34769
|
+
));
|
|
34770
|
+
}, [laid.edges]);
|
|
34242
34771
|
const diagramScale = laid.diagramScale ?? 1;
|
|
34772
|
+
const stageLaneIds = new Set(
|
|
34773
|
+
laid.lanes.filter((lane) => lane.stage !== void 0).map((lane) => lane.id)
|
|
34774
|
+
);
|
|
34775
|
+
const stageNoteNodes = laid.nodes.filter(
|
|
34776
|
+
(node) => node.kind === "card" && (stageLaneIds.has(node.lane) || node.leaderTo !== void 0) && isRenderedNode(node) && Boolean(node.subtitle)
|
|
34777
|
+
);
|
|
34778
|
+
const stageNoteNodeIds = new Set(stageNoteNodes.map((node) => node.id));
|
|
34779
|
+
const nodesById = new Map(laid.nodes.map((node) => [node.id, node]));
|
|
34780
|
+
const metroDecisionIds = /* @__PURE__ */ new Set();
|
|
34781
|
+
const stationNamesRight = /* @__PURE__ */ new Set();
|
|
34782
|
+
for (const edge of laid.edges) {
|
|
34783
|
+
if (edge.routing !== "metro") continue;
|
|
34784
|
+
if (nodesById.get(edge.from)?.kind === "decision") metroDecisionIds.add(edge.from);
|
|
34785
|
+
if (nodesById.get(edge.to)?.kind === "decision") metroDecisionIds.add(edge.to);
|
|
34786
|
+
if (edge.toSide === "top" && nodesById.get(edge.to)?.kind === "station") {
|
|
34787
|
+
stationNamesRight.add(edge.to);
|
|
34788
|
+
}
|
|
34789
|
+
}
|
|
34243
34790
|
if (!\u63CF\u304F\u3082\u306E\u304C\u3042\u308B(laid)) return null;
|
|
34244
34791
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: compact ? "px-3 py-3" : "px-6 py-6", style: compact ? void 0 : { minHeight: 460 }, children: [
|
|
34245
34792
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -34259,6 +34806,7 @@ function CdlStage({
|
|
|
34259
34806
|
children: [
|
|
34260
34807
|
/* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
|
|
34261
34808
|
edgeHeadMarkers,
|
|
34809
|
+
metroReturnArrowMarkers,
|
|
34262
34810
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
34263
34811
|
"marker",
|
|
34264
34812
|
{
|
|
@@ -34295,7 +34843,61 @@ function CdlStage({
|
|
|
34295
34843
|
pointerEvents: "none"
|
|
34296
34844
|
}
|
|
34297
34845
|
),
|
|
34298
|
-
lane.
|
|
34846
|
+
lane.stage && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
34847
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
34848
|
+
"rect",
|
|
34849
|
+
{
|
|
34850
|
+
"data-cdl-role": "stage-column",
|
|
34851
|
+
x: lane.x + STAGE_COLUMN_GAP / 2,
|
|
34852
|
+
y: lane.y,
|
|
34853
|
+
width: lane.width - STAGE_COLUMN_GAP,
|
|
34854
|
+
height: lane.height,
|
|
34855
|
+
rx: 16,
|
|
34856
|
+
fill: "var(--cdl-stage-bg, #fafafa)",
|
|
34857
|
+
fillOpacity: 0.5,
|
|
34858
|
+
stroke: "var(--cdl-text-mute, #8a8678)",
|
|
34859
|
+
strokeWidth: 1.5
|
|
34860
|
+
}
|
|
34861
|
+
),
|
|
34862
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
34863
|
+
"text",
|
|
34864
|
+
{
|
|
34865
|
+
"data-cdl-role": "stage-number",
|
|
34866
|
+
x: lane.x + STAGE_COLUMN_GAP / 2 + 20,
|
|
34867
|
+
y: lane.y + 24,
|
|
34868
|
+
fontSize: 14,
|
|
34869
|
+
fontWeight: 500,
|
|
34870
|
+
letterSpacing: 1.5,
|
|
34871
|
+
fill: "var(--cdl-text-mute, #8a8678)",
|
|
34872
|
+
children: `\u6BB5\u968E ${lane.stage.number}`
|
|
34873
|
+
}
|
|
34874
|
+
),
|
|
34875
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
34876
|
+
"text",
|
|
34877
|
+
{
|
|
34878
|
+
"data-cdl-role": "stage-name",
|
|
34879
|
+
x: lane.x + STAGE_COLUMN_GAP / 2 + 20,
|
|
34880
|
+
y: lane.y + 55,
|
|
34881
|
+
fontSize: 22,
|
|
34882
|
+
fontWeight: 700,
|
|
34883
|
+
fill: "var(--cdl-text, #1a1f2a)",
|
|
34884
|
+
children: lane.stage.name
|
|
34885
|
+
}
|
|
34886
|
+
),
|
|
34887
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
34888
|
+
"line",
|
|
34889
|
+
{
|
|
34890
|
+
"data-cdl-role": "stage-divider",
|
|
34891
|
+
x1: lane.x + STAGE_COLUMN_GAP / 2,
|
|
34892
|
+
y1: lane.y + 72,
|
|
34893
|
+
x2: lane.x + lane.width - STAGE_COLUMN_GAP / 2,
|
|
34894
|
+
y2: lane.y + 72,
|
|
34895
|
+
stroke: "var(--cdl-divider, #d4d4d8)",
|
|
34896
|
+
strokeWidth: 1.5
|
|
34897
|
+
}
|
|
34898
|
+
)
|
|
34899
|
+
] }),
|
|
34900
|
+
lane.contain && lane.stage === void 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
34299
34901
|
"rect",
|
|
34300
34902
|
{
|
|
34301
34903
|
"data-cdl-role": "lane-container",
|
|
@@ -34331,7 +34933,85 @@ function CdlStage({
|
|
|
34331
34933
|
}
|
|
34332
34934
|
);
|
|
34333
34935
|
})(),
|
|
34334
|
-
lane.
|
|
34936
|
+
lane.timelineAxis && (() => {
|
|
34937
|
+
const ys = laid.nodes.filter((node) => node.lane === lane.id && isRenderedNode(node)).map((node) => node.cy);
|
|
34938
|
+
if (ys.length < 2) return null;
|
|
34939
|
+
const y1 = Math.min(...ys);
|
|
34940
|
+
const y2 = Math.max(...ys);
|
|
34941
|
+
if (y2 <= y1) return null;
|
|
34942
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
34943
|
+
"line",
|
|
34944
|
+
{
|
|
34945
|
+
"data-cdl-role": "timeline-axis",
|
|
34946
|
+
x1: lane.x + lane.width / 2,
|
|
34947
|
+
y1,
|
|
34948
|
+
x2: lane.x + lane.width / 2,
|
|
34949
|
+
y2,
|
|
34950
|
+
stroke: "var(--cdl-tone-accent, #2d6a8f)",
|
|
34951
|
+
strokeWidth: TIMELINE_NUMBER_STROKE
|
|
34952
|
+
}
|
|
34953
|
+
);
|
|
34954
|
+
})(),
|
|
34955
|
+
lane.metro !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
34956
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
34957
|
+
"line",
|
|
34958
|
+
{
|
|
34959
|
+
"data-cdl-role": "metro-lane-guide",
|
|
34960
|
+
x1: lane.x + METRO_LANE_BADGE_INSET + METRO_LANE_BADGE_WIDTH + METRO_LANE_GUIDE_GAP,
|
|
34961
|
+
y1: lane.y + lane.height / 2,
|
|
34962
|
+
x2: lane.x + lane.width - METRO_LANE_BADGE_INSET,
|
|
34963
|
+
y2: lane.y + lane.height / 2,
|
|
34964
|
+
stroke: "var(--cdl-line-mute, #a89d8f)",
|
|
34965
|
+
strokeWidth: 2,
|
|
34966
|
+
strokeDasharray: "22 7 5 7",
|
|
34967
|
+
opacity: 0.45
|
|
34968
|
+
}
|
|
34969
|
+
),
|
|
34970
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
34971
|
+
"g",
|
|
34972
|
+
{
|
|
34973
|
+
"data-cdl-role": "metro-lane-badge",
|
|
34974
|
+
transform: `translate(${lane.x + METRO_LANE_BADGE_INSET} ${lane.y + lane.height / 2 - METRO_LANE_BADGE_HEIGHT / 2})`,
|
|
34975
|
+
children: [
|
|
34976
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
34977
|
+
"rect",
|
|
34978
|
+
{
|
|
34979
|
+
width: METRO_LANE_BADGE_WIDTH,
|
|
34980
|
+
height: METRO_LANE_BADGE_HEIGHT,
|
|
34981
|
+
rx: 12,
|
|
34982
|
+
fill: "var(--cdl-node-fill, #ffffff)",
|
|
34983
|
+
stroke: "var(--cdl-tone-accent, #2d6a8f)",
|
|
34984
|
+
strokeWidth: 1.25
|
|
34985
|
+
}
|
|
34986
|
+
),
|
|
34987
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
34988
|
+
"text",
|
|
34989
|
+
{
|
|
34990
|
+
x: METRO_LANE_BADGE_WIDTH / 2,
|
|
34991
|
+
y: lane.metro.subtitle ? 37 : 53,
|
|
34992
|
+
fontSize: 26,
|
|
34993
|
+
fontWeight: 700,
|
|
34994
|
+
fill: "var(--cdl-text, #1a1f2a)",
|
|
34995
|
+
textAnchor: "middle",
|
|
34996
|
+
children: lane.label
|
|
34997
|
+
}
|
|
34998
|
+
),
|
|
34999
|
+
lane.metro.subtitle && /* @__PURE__ */ jsxRuntime.jsx(
|
|
35000
|
+
"text",
|
|
35001
|
+
{
|
|
35002
|
+
x: METRO_LANE_BADGE_WIDTH / 2,
|
|
35003
|
+
y: 67,
|
|
35004
|
+
fontSize: 18,
|
|
35005
|
+
fill: "var(--cdl-text-dim, #5a6270)",
|
|
35006
|
+
textAnchor: "middle",
|
|
35007
|
+
children: lane.metro.subtitle
|
|
35008
|
+
}
|
|
35009
|
+
)
|
|
35010
|
+
]
|
|
35011
|
+
}
|
|
35012
|
+
)
|
|
35013
|
+
] }),
|
|
35014
|
+
lane.label && lane.metro === void 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
34335
35015
|
"text",
|
|
34336
35016
|
{
|
|
34337
35017
|
"data-cdl-role": "lane-label",
|
|
@@ -34348,7 +35028,34 @@ function CdlStage({
|
|
|
34348
35028
|
},
|
|
34349
35029
|
lane.id
|
|
34350
35030
|
)),
|
|
34351
|
-
laid.
|
|
35031
|
+
laid.nodes.map((node) => {
|
|
35032
|
+
if (node.leaderTo === void 0) return null;
|
|
35033
|
+
const target = nodesById.get(node.leaderTo);
|
|
35034
|
+
if (target === void 0) return null;
|
|
35035
|
+
if (!isRenderedNode(node) || !isRenderedNode(target)) return null;
|
|
35036
|
+
const targetIsRight = target.cx >= node.cx;
|
|
35037
|
+
const x1 = node.cx + (targetIsRight ? node.w / 2 : -node.w / 2);
|
|
35038
|
+
const x2 = target.cx + (targetIsRight ? -target.w / 2 : target.w / 2);
|
|
35039
|
+
if (targetIsRight ? x2 <= x1 : x1 <= x2) return null;
|
|
35040
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
35041
|
+
"line",
|
|
35042
|
+
{
|
|
35043
|
+
"data-cdl-role": "timeline-leader",
|
|
35044
|
+
"data-cdl-leader-from": node.id,
|
|
35045
|
+
"data-cdl-leader-to": node.leaderTo,
|
|
35046
|
+
x1,
|
|
35047
|
+
y1: node.cy,
|
|
35048
|
+
x2,
|
|
35049
|
+
y2: target.cy,
|
|
35050
|
+
stroke: "var(--cdl-line-mute, #a89d8f)",
|
|
35051
|
+
strokeWidth: 1.5,
|
|
35052
|
+
strokeDasharray: "2 4",
|
|
35053
|
+
strokeLinecap: "round"
|
|
35054
|
+
},
|
|
35055
|
+
`timeline-leader-${node.id}`
|
|
35056
|
+
);
|
|
35057
|
+
}),
|
|
35058
|
+
laid.edges.filter(\u7DDA\u3092\u63CF\u304F).map((edge) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
34352
35059
|
CdlEdgeView,
|
|
34353
35060
|
{
|
|
34354
35061
|
edge,
|
|
@@ -34356,16 +35063,19 @@ function CdlStage({
|
|
|
34356
35063
|
flowing: \u7126\u70B9\u306E\u96C6\u5408?.has(edge.id) === true && !\u52D5\u304D\u3092\u63A7\u3048\u308B,
|
|
34357
35064
|
drawing: \u77E2\u5370\u306E\u51FA\u756A.\u4F38\u3070\u3059\u304B(edge.id),
|
|
34358
35065
|
progress: \u77E2\u5370\u306E\u51FA\u756A.\u4F38\u3070\u3059\u304B(edge.id) ? \u63CF\u304F\u9032\u307F : progress,
|
|
34359
|
-
stateValues
|
|
35066
|
+
stateValues,
|
|
35067
|
+
pending: edge.routing === "metro" && \u77E2\u5370\u306E\u51FA\u756A.\u307E\u3060\u304B(edge.id)
|
|
34360
35068
|
},
|
|
34361
35069
|
edge.id
|
|
34362
35070
|
)),
|
|
34363
35071
|
laid.nodes.map((node) => {
|
|
34364
35072
|
const \u63CF\u304F = drawSet.has(node.id);
|
|
35073
|
+
const \u6BB5\u968E\u306E\u88DC\u8DB3 = stageNoteNodeIds.has(node.id);
|
|
34365
35074
|
const view = /* @__PURE__ */ jsxRuntime.jsx(
|
|
34366
35075
|
CdlNodeView,
|
|
34367
35076
|
{
|
|
34368
|
-
node,
|
|
35077
|
+
node: \u6BB5\u968E\u306E\u88DC\u8DB3 ? { ...node, subtitle: void 0 } : node,
|
|
35078
|
+
compactTitleInset: \u6BB5\u968E\u306E\u88DC\u8DB3 ? STAGE_CARD_TEXT_INSET : void 0,
|
|
34369
35079
|
active: activeSet.has(node.id),
|
|
34370
35080
|
lang: laid.lang,
|
|
34371
35081
|
textMetrics: laid.textMetrics,
|
|
@@ -34375,13 +35085,32 @@ function CdlStage({
|
|
|
34375
35085
|
stateValues,
|
|
34376
35086
|
\u5024\u306E\u540D\u524D,
|
|
34377
35087
|
currentPhaseId: currentPhase?.id,
|
|
34378
|
-
chartLineScale: chartLineScales.get(node.id)
|
|
35088
|
+
chartLineScale: chartLineScales.get(node.id),
|
|
35089
|
+
metroDiagram: \u8DEF\u7DDA\u56F3,
|
|
35090
|
+
metroDecision: metroDecisionIds.has(node.id),
|
|
35091
|
+
stationNameRight: stationNamesRight.has(node.id)
|
|
34379
35092
|
}
|
|
34380
35093
|
);
|
|
34381
35094
|
return /* @__PURE__ */ jsxRuntime.jsx("g", { children: view }, node.id);
|
|
34382
35095
|
}),
|
|
34383
|
-
|
|
34384
|
-
|
|
35096
|
+
stageNoteNodes.map((node) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
35097
|
+
"text",
|
|
35098
|
+
{
|
|
35099
|
+
"data-cdl-role": "stage-note",
|
|
35100
|
+
"data-cdl-stage-node": node.id,
|
|
35101
|
+
x: node.cx + node.w / 2 - STAGE_CARD_TEXT_INSET,
|
|
35102
|
+
y: node.cy + 1,
|
|
35103
|
+
fontSize: 14,
|
|
35104
|
+
fontWeight: 500,
|
|
35105
|
+
textAnchor: "end",
|
|
35106
|
+
dominantBaseline: "middle",
|
|
35107
|
+
fill: "var(--cdl-text-mute, #8a8678)",
|
|
35108
|
+
children: interpolate(node.subtitle, stateValues, \u5024\u306E\u540D\u524D)
|
|
35109
|
+
},
|
|
35110
|
+
`stage-note-${node.id}`
|
|
35111
|
+
)),
|
|
35112
|
+
laid.edges.filter((edge) => Boolean(edge.dThrough) && \u7DDA\u3092\u63CF\u304F(edge)).map((edge) => /* @__PURE__ */ jsxRuntime.jsx(CdlEdgeGlowView, { edge, active: activeSet.has(edge.id) }, `glow-${edge.id}`)),
|
|
35113
|
+
laid.edges.filter(\u7DDA\u3092\u63CF\u304F).map((edge) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
34385
35114
|
CdlEdgeLabelView,
|
|
34386
35115
|
{
|
|
34387
35116
|
edge,
|
|
@@ -34390,7 +35119,7 @@ function CdlStage({
|
|
|
34390
35119
|
},
|
|
34391
35120
|
`label-${edge.id}`
|
|
34392
35121
|
)),
|
|
34393
|
-
laid.edges.filter((edge) => (edge.headLabel || edge.tailLabel) && \
|
|
35122
|
+
laid.edges.filter((edge) => (edge.headLabel || edge.tailLabel) && \u7DDA\u3092\u63CF\u304F(edge)).flatMap(
|
|
34394
35123
|
(edge) => ["head", "tail"].map((\u7AEF) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
34395
35124
|
CdlEdgeEndLabelView,
|
|
34396
35125
|
{
|
|
@@ -34402,6 +35131,7 @@ function CdlStage({
|
|
|
34402
35131
|
`${\u7AEF}-label-${edge.id}`
|
|
34403
35132
|
))
|
|
34404
35133
|
),
|
|
35134
|
+
laid.legend && /* @__PURE__ */ jsxRuntime.jsx(CdlLegend, { items: laid.legend }),
|
|
34405
35135
|
debug && /* @__PURE__ */ jsxRuntime.jsxs("g", { pointerEvents: "none", children: [
|
|
34406
35136
|
laid.bboxes.map((bbox, idx) => {
|
|
34407
35137
|
const color = bbox.kind === "node" ? "#3b82f6" : bbox.kind === "lane-label" ? "#a855f7" : bbox.kind === "edge-label" ? "#10b981" : "#f59e0b";
|
|
@@ -36066,6 +36796,7 @@ exports.LABEL_INIT_CLEARANCE_DOTTED_FLOW = LABEL_INIT_CLEARANCE_DOTTED_FLOW;
|
|
|
36066
36796
|
exports.LABEL_SIZE_TOLERANCE_WORLD = LABEL_SIZE_TOLERANCE_WORLD;
|
|
36067
36797
|
exports.LABEL_TO_PATH_CLEARANCE = LABEL_TO_PATH_CLEARANCE;
|
|
36068
36798
|
exports.LANE_BORDER_CLEARANCE_TOL = LANE_BORDER_CLEARANCE_TOL;
|
|
36799
|
+
exports.LEGEND_MARKS = LEGEND_MARKS;
|
|
36069
36800
|
exports.MARKER_GLOW_RADIUS = MARKER_GLOW_RADIUS;
|
|
36070
36801
|
exports.MIN_COLUMN_ALIGNMENT_TOLERANCE = MIN_COLUMN_ALIGNMENT_TOLERANCE;
|
|
36071
36802
|
exports.MIN_ROW_ALIGNMENT_TOLERANCE = MIN_ROW_ALIGNMENT_TOLERANCE;
|