@cardenelabs/cdl 0.123.0 → 0.124.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 +13 -1
- package/README.md +6 -1
- package/dist/index.cjs +60 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +60 -1
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +60 -1
- 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 +60 -1
- package/dist/react.js.map +1 -1
- package/dist/{render-CVczwfRb.d.cts → render-U6omSNH2.d.cts} +3 -2
- package/dist/{render-CVczwfRb.d.ts → render-U6omSNH2.d.ts} +3 -2
- package/package.json +1 -1
- package/src/layout/edges.ts +103 -4
- package/src/types.ts +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,17 @@ CDL (Chainome Diagram Language) の主要変更履歴。
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [0.124.0] - 2026-10-06
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- **箱の上を回る戻り線が、途中の箱を貫かない道筋を選べるようにした** (#1014)
|
|
13
|
+
|
|
14
|
+
上へ回る今までの道筋が両端以外の箱と交わる時だけ、左右の外側の列を通る道筋に替え、交わる箱が少なく短い方を選ぶ。
|
|
15
|
+
両端は今までどおり上辺から出て、上辺へ入る。
|
|
16
|
+
1 段前へ戻る線と間に箱が無い戻り線の座標は変わらない。
|
|
17
|
+
外側を回っても避けられない箱は `edge-node-cross` として検査結果に残る。
|
|
18
|
+
|
|
8
19
|
## [0.123.0] - 2026-10-05
|
|
9
20
|
|
|
10
21
|
### Added
|
|
@@ -4864,7 +4875,8 @@ Initial OSS release.
|
|
|
4864
4875
|
使わない = annotated tag を push しても GitHub Release は作られず、 Release を作っていない版で
|
|
4865
4876
|
行き止まりになる。
|
|
4866
4877
|
|
|
4867
|
-
[Unreleased]: https://github.com/cardene777/cdl/compare/v0.
|
|
4878
|
+
[Unreleased]: https://github.com/cardene777/cdl/compare/v0.124.0...HEAD
|
|
4879
|
+
[0.124.0]: https://github.com/cardene777/cdl/compare/v0.123.0...v0.124.0
|
|
4868
4880
|
[0.123.0]: https://github.com/cardene777/cdl/compare/v0.122.0...v0.123.0
|
|
4869
4881
|
[0.122.0]: https://github.com/cardene777/cdl/compare/v0.121.0...v0.122.0
|
|
4870
4882
|
[0.121.0]: https://github.com/cardene777/cdl/compare/v0.120.0...v0.121.0
|
package/README.md
CHANGED
|
@@ -268,10 +268,15 @@ export const custom = diagram("custom", { topic: "Custom" })
|
|
|
268
268
|
| 値 | 道筋 | 向く場面 |
|
|
269
269
|
|---|---|---|
|
|
270
270
|
| `default` | 箱を避け、角を丸めた直角の線 | 箱を避けたい図、直角の線に揃えたい図 |
|
|
271
|
-
| `back-detour` |
|
|
271
|
+
| `back-detour` | 箱の上を回って戻り、途中の箱と交わる時は外側を回る線 | 前の箱へ戻る関係 |
|
|
272
272
|
| `curve` | 両端で水平になる 3 次曲線 | 段や列をまたぐ関係を柔らかくつなぐ図 |
|
|
273
273
|
| `metro` | 横線と傾き ±1 の斜線を円弧で結ぶ線 | 路線図の線路と乗り換え |
|
|
274
274
|
|
|
275
|
+
`back-detour` は始点と終点の上辺を結び、両端より 100 上を横に渡る。
|
|
276
|
+
途中の箱と交わる時だけ、縦に並ぶ箱を避けた最も近い外側の列を通り、交わる箱が少なく短い方を選ぶ。
|
|
277
|
+
両端は外側へ回る時も上辺から出て、上辺へ入る。
|
|
278
|
+
外側を回っても避けられない箱は `edge-node-cross` として検査結果に残る。
|
|
279
|
+
|
|
275
280
|
`curve` は、行き先が右なら始点の右辺から終点の左辺へ、左なら始点の左辺から終点の右辺へ結ぶ。
|
|
276
281
|
2 つの箱の横の範囲が重なる時は、両方の右辺を結ぶ。
|
|
277
282
|
2 点の高さが同じなら直線になる。
|
package/dist/index.cjs
CHANGED
|
@@ -20514,6 +20514,55 @@ function bowSharedStraightPaths(edges, nodes, skipIds, textMetrics = "proportion
|
|
|
20514
20514
|
function nodeRect(n) {
|
|
20515
20515
|
return { x: n.cx - n.w / 2, y: n.cy - n.h / 2, w: n.w, h: n.h };
|
|
20516
20516
|
}
|
|
20517
|
+
function countPathObstacleCrossings(d, obstacles) {
|
|
20518
|
+
const segments = flattenPathSegments(extractPathSegments(d));
|
|
20519
|
+
return obstacles.filter((obstacle) => segmentsCrossRect(segments, nodeRect(obstacle))).length;
|
|
20520
|
+
}
|
|
20521
|
+
function makeBackDetourCandidate(A, B, from, to, obstacles, detourY, side) {
|
|
20522
|
+
const lowIsA = A.y >= B.y;
|
|
20523
|
+
const low = lowIsA ? A : B;
|
|
20524
|
+
const lowBendY = low.y - VERTICAL_DETOUR_EXIT;
|
|
20525
|
+
const bandTop = Math.min(detourY, lowBendY);
|
|
20526
|
+
const bandBottom = Math.max(detourY, lowBendY);
|
|
20527
|
+
const bandObstacles = obstacles.map(nodeRect).filter((rect) => rect.y + rect.h >= bandTop && rect.y <= bandBottom);
|
|
20528
|
+
let columnX = detourColumnFor([from, to], side);
|
|
20529
|
+
while (true) {
|
|
20530
|
+
const blockers = bandObstacles.filter(
|
|
20531
|
+
(rect) => rect.x - VERTICAL_DETOUR_GAP < columnX && columnX < rect.x + rect.w + VERTICAL_DETOUR_GAP
|
|
20532
|
+
);
|
|
20533
|
+
if (blockers.length === 0) break;
|
|
20534
|
+
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));
|
|
20535
|
+
}
|
|
20536
|
+
const bendAY = lowIsA ? lowBendY : detourY;
|
|
20537
|
+
const bendBY = lowIsA ? detourY : lowBendY;
|
|
20538
|
+
const vertices = [
|
|
20539
|
+
A,
|
|
20540
|
+
{ x: A.x, y: bendAY },
|
|
20541
|
+
{ x: columnX, y: bendAY },
|
|
20542
|
+
{ x: columnX, y: bendBY },
|
|
20543
|
+
{ x: B.x, y: bendBY },
|
|
20544
|
+
B
|
|
20545
|
+
];
|
|
20546
|
+
const d = verticesToPath(vertices);
|
|
20547
|
+
const high = lowIsA ? B : A;
|
|
20548
|
+
return {
|
|
20549
|
+
d,
|
|
20550
|
+
labelX: (high.x + columnX) / 2,
|
|
20551
|
+
crossings: countPathObstacleCrossings(d, obstacles),
|
|
20552
|
+
length: vertices.slice(1).reduce((sum, vertex, index) => {
|
|
20553
|
+
const previous = vertices[index];
|
|
20554
|
+
return sum + Math.hypot(vertex.x - previous.x, vertex.y - previous.y);
|
|
20555
|
+
}, 0)
|
|
20556
|
+
};
|
|
20557
|
+
}
|
|
20558
|
+
function chooseBackDetourCandidate(A, B, from, to, obstacles, detourY) {
|
|
20559
|
+
const left = makeBackDetourCandidate(A, B, from, to, obstacles, detourY, "left");
|
|
20560
|
+
const right = makeBackDetourCandidate(A, B, from, to, obstacles, detourY, "right");
|
|
20561
|
+
if (left.crossings !== right.crossings) return left.crossings < right.crossings ? left : right;
|
|
20562
|
+
if (Math.abs(left.length - right.length) >= 0.5) return left.length < right.length ? left : right;
|
|
20563
|
+
const preferred = Math.abs(A.x - B.x) < 0.5 ? "right" : A.x < B.x ? "left" : "right";
|
|
20564
|
+
return preferred === "left" ? left : right;
|
|
20565
|
+
}
|
|
20517
20566
|
function rectGap(a, b) {
|
|
20518
20567
|
const dx = Math.max(0, a.x - (b.x + b.w), b.x - (a.x + a.w));
|
|
20519
20568
|
const dy = Math.max(0, a.y - (b.y + b.h), b.y - (a.y + a.h));
|
|
@@ -20964,7 +21013,7 @@ function routePath(from, to, fromSide, toSide, obstacles = [], detourSide, _from
|
|
|
20964
21013
|
const detourY = Math.min(A.y, B.y) - 100;
|
|
20965
21014
|
const corner = 14;
|
|
20966
21015
|
const xDir = B.x > A.x ? 1 : -1;
|
|
20967
|
-
|
|
21016
|
+
const existing = {
|
|
20968
21017
|
d: `M ${A.x} ${A.y}
|
|
20969
21018
|
L ${A.x} ${detourY + corner}
|
|
20970
21019
|
Q ${A.x} ${detourY}, ${A.x + xDir * corner} ${detourY}
|
|
@@ -20978,6 +21027,16 @@ function routePath(from, to, fromSide, toSide, obstacles = [], detourSide, _from
|
|
|
20978
21027
|
labelY: detourY - labelInit,
|
|
20979
21028
|
labelAnchor: "middle"
|
|
20980
21029
|
};
|
|
21030
|
+
const existingCrossings = countPathObstacleCrossings(existing.d, obstacles);
|
|
21031
|
+
if (existingCrossings === 0) return existing;
|
|
21032
|
+
const candidate = chooseBackDetourCandidate(A, B, from, to, obstacles, detourY);
|
|
21033
|
+
if (candidate.crossings >= existingCrossings) return existing;
|
|
21034
|
+
return {
|
|
21035
|
+
d: candidate.d,
|
|
21036
|
+
labelX: candidate.labelX,
|
|
21037
|
+
labelY: detourY - labelInit,
|
|
21038
|
+
labelAnchor: "middle"
|
|
21039
|
+
};
|
|
20981
21040
|
}
|
|
20982
21041
|
const midX = fromSide === "left" || fromSide === "right" ? B.x : A.x;
|
|
20983
21042
|
const midY = fromSide === "top" || fromSide === "bottom" ? B.y : A.y;
|