@cardenelabs/cdl 0.28.0 → 0.30.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 +84 -1
- package/dist/index.cjs +155 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +155 -30
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +135 -12
- 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 +135 -12
- package/dist/react.js.map +1 -1
- package/dist/{render-ViWKnlu1.d.cts → render-CabTMeao.d.cts} +13 -0
- package/dist/{render-ViWKnlu1.d.ts → render-CabTMeao.d.ts} +13 -0
- package/package.json +1 -1
- package/src/builder.ts +6 -0
- package/src/layout/edges.ts +167 -13
- package/src/layout.ts +6 -0
- package/src/presets.ts +18 -18
- package/src/render/stage.tsx +1 -0
- package/src/types.ts +13 -0
package/dist/react.cjs
CHANGED
|
@@ -8393,16 +8393,112 @@ function separateSharedStraightRuns(edges, nodes) {
|
|
|
8393
8393
|
e.d = verticesToPath(verts.get(e.id));
|
|
8394
8394
|
}
|
|
8395
8395
|
}
|
|
8396
|
+
function pullOutgoingFirstCorner(edges, nodes) {
|
|
8397
|
+
if (edges.length < 2) return;
|
|
8398
|
+
const \u675F = /* @__PURE__ */ new Map();
|
|
8399
|
+
const \u540C\u3058\u7D44\u306E\u6570 = /* @__PURE__ */ new Map();
|
|
8400
|
+
for (const e of edges) {
|
|
8401
|
+
const key = `${e.from}::${e.fromSide}`;
|
|
8402
|
+
const list = \u675F.get(key) ?? [];
|
|
8403
|
+
list.push(e);
|
|
8404
|
+
\u675F.set(key, list);
|
|
8405
|
+
const pair = `${e.from}->${e.to}`;
|
|
8406
|
+
\u540C\u3058\u7D44\u306E\u6570.set(pair, (\u540C\u3058\u7D44\u306E\u6570.get(pair) ?? 0) + 1);
|
|
8407
|
+
}
|
|
8408
|
+
let \u672D\u3092\u65E7\u7D4C\u8DEF\u3078\u8FFD\u5F93\u6E08\u307F = false;
|
|
8409
|
+
for (const list of \u675F.values()) {
|
|
8410
|
+
if (list.length < 2) continue;
|
|
8411
|
+
const \u4E26\u3073 = list.flatMap((e) => {
|
|
8412
|
+
const pts = pathVertices(e.d);
|
|
8413
|
+
if (!pts || pts.length < 2) return [];
|
|
8414
|
+
return [{ e, pts, \u6700\u521D\u306E\u9577\u3055: Math.hypot(pts[1].x - pts[0].x, pts[1].y - pts[0].y) }];
|
|
8415
|
+
}).sort((a, b) => b.\u6700\u521D\u306E\u9577\u3055 - a.\u6700\u521D\u306E\u9577\u3055);
|
|
8416
|
+
for (const { e, pts, \u6700\u521D\u306E\u9577\u3055 } of \u4E26\u3073.slice(1)) {
|
|
8417
|
+
if ((\u540C\u3058\u7D44\u306E\u6570.get(`${e.from}->${e.to}`) ?? 0) > 1) continue;
|
|
8418
|
+
if (pts.length < 3 || \u6700\u521D\u306E\u9577\u3055 <= EDGE_STUB_OUT + VERTICAL_DETOUR_CORNER) continue;
|
|
8419
|
+
const \u6A2A = e.fromSide === "left" || e.fromSide === "right";
|
|
8420
|
+
if (!runIsAligned(pts, 0, \u6A2A ? 1 : 0)) continue;
|
|
8421
|
+
const \u79FB\u52D5\u91CF = \u6700\u521D\u306E\u9577\u3055 - (EDGE_STUB_OUT + VERTICAL_DETOUR_CORNER);
|
|
8422
|
+
const ux = (pts[1].x - pts[0].x) / \u6700\u521D\u306E\u9577\u3055;
|
|
8423
|
+
const uy = (pts[1].y - pts[0].y) / \u6700\u521D\u306E\u9577\u3055;
|
|
8424
|
+
const \u8A66\u3057 = pts.map(
|
|
8425
|
+
(p, i) => i === 1 || i === 2 ? { x: p.x - ux * \u79FB\u52D5\u91CF, y: p.y - uy * \u79FB\u52D5\u91CF } : p
|
|
8426
|
+
);
|
|
8427
|
+
const \u8A66\u3057D = verticesToPath(\u8A66\u3057);
|
|
8428
|
+
const \u8A66\u3057\u533A\u9593 = flattenPathSegments(extractPathSegments(\u8A66\u3057D));
|
|
8429
|
+
if (nodes.some(
|
|
8430
|
+
(n) => n.id !== e.from && n.id !== e.to && segmentsCrossRect(\u8A66\u3057\u533A\u9593, nodeRect(n))
|
|
8431
|
+
)) {
|
|
8432
|
+
continue;
|
|
8433
|
+
}
|
|
8434
|
+
const \u524D = e.d;
|
|
8435
|
+
const \u524D\u306E\u4EA4\u5DEE = countEdgeCrossings(edges).count;
|
|
8436
|
+
e.d = \u8A66\u3057D;
|
|
8437
|
+
if (countEdgeCrossings(edges).count > \u524D\u306E\u4EA4\u5DEE) {
|
|
8438
|
+
e.d = \u524D;
|
|
8439
|
+
continue;
|
|
8440
|
+
}
|
|
8441
|
+
e.d = \u524D;
|
|
8442
|
+
if (!\u672D\u3092\u65E7\u7D4C\u8DEF\u3078\u8FFD\u5F93\u6E08\u307F) {
|
|
8443
|
+
slideLabelsAlongOwnPath(edges, nodes);
|
|
8444
|
+
\u672D\u3092\u65E7\u7D4C\u8DEF\u3078\u8FFD\u5F93\u6E08\u307F = true;
|
|
8445
|
+
}
|
|
8446
|
+
const labelBox = computeLabelBBoxWorld(e);
|
|
8447
|
+
const label = { x: labelBox.x + labelBox.w / 2, y: labelBox.y + labelBox.h / 2 };
|
|
8448
|
+
const \u7DDA\u5206\u307E\u3067\u306E\u8DDD\u96E22 = (a, b) => {
|
|
8449
|
+
const dx = b.x - a.x;
|
|
8450
|
+
const dy = b.y - a.y;
|
|
8451
|
+
const len2 = dx * dx + dy * dy;
|
|
8452
|
+
const t = len2 === 0 ? 0 : Math.max(0, Math.min(1, ((label.x - a.x) * dx + (label.y - a.y) * dy) / len2));
|
|
8453
|
+
return (label.x - (a.x + dx * t)) ** 2 + (label.y - (a.y + dy * t)) ** 2;
|
|
8454
|
+
};
|
|
8455
|
+
const \u52D5\u304F\u533A\u9593\u3078\u306E\u8DDD\u96E2 = \u7DDA\u5206\u307E\u3067\u306E\u8DDD\u96E22(pts[1], pts[2]);
|
|
8456
|
+
const label\u3082\u52D5\u304B\u3059 = pts.slice(0, -1).every((p, i) => \u7DDA\u5206\u307E\u3067\u306E\u8DDD\u96E22(p, pts[i + 1]) >= \u52D5\u304F\u533A\u9593\u3078\u306E\u8DDD\u96E2 - 1e-6);
|
|
8457
|
+
e.d = \u8A66\u3057D;
|
|
8458
|
+
if (label\u3082\u52D5\u304B\u3059) {
|
|
8459
|
+
e.labelX -= ux * \u79FB\u52D5\u91CF;
|
|
8460
|
+
e.labelY -= uy * \u79FB\u52D5\u91CF;
|
|
8461
|
+
}
|
|
8462
|
+
}
|
|
8463
|
+
}
|
|
8464
|
+
}
|
|
8396
8465
|
var ENDPOINT_FAN_STEP = 56;
|
|
8397
8466
|
var ENDPOINT_FAN_MIN = 20;
|
|
8398
8467
|
var ENDPOINT_FAN_RUNUP = 40;
|
|
8468
|
+
var MIXED_ROOT_OVERLAP_MIN = 24;
|
|
8399
8469
|
function fanIncomingEndpoints(edges, nodes) {
|
|
8400
8470
|
if (edges.length < 2) return;
|
|
8401
8471
|
const nmap = new Map(nodes.map((n) => [n.id, n]));
|
|
8472
|
+
const \u5E73\u5766\u306A\u533A\u9593 = new Map(edges.map((e) => [e.id, flattenPathSegments(extractPathSegments(e.d))]));
|
|
8473
|
+
const \u8EF8\u306B\u5E73\u884C\u306A\u91CD\u306A\u308A\u9577\u3055 = (\u4E00\u65B9, \u4ED6\u65B9) => {
|
|
8474
|
+
let \u5408\u8A08 = 0;
|
|
8475
|
+
for (const a of \u5E73\u5766\u306A\u533A\u9593.get(\u4E00\u65B9.id) ?? []) {
|
|
8476
|
+
const a\u306F\u6C34\u5E73 = Math.abs(a.y2 - a.y1) <= 1;
|
|
8477
|
+
const a\u306F\u5782\u76F4 = Math.abs(a.x2 - a.x1) <= 1;
|
|
8478
|
+
for (const b of \u5E73\u5766\u306A\u533A\u9593.get(\u4ED6\u65B9.id) ?? []) {
|
|
8479
|
+
const b\u306F\u6C34\u5E73 = Math.abs(b.y2 - b.y1) <= 1;
|
|
8480
|
+
const b\u306F\u5782\u76F4 = Math.abs(b.x2 - b.x1) <= 1;
|
|
8481
|
+
if (a\u306F\u6C34\u5E73 && b\u306F\u6C34\u5E73 && Math.abs(a.y1 - b.y1) <= 1) {
|
|
8482
|
+
\u5408\u8A08 += Math.max(0, Math.min(Math.max(a.x1, a.x2), Math.max(b.x1, b.x2)) - Math.max(Math.min(a.x1, a.x2), Math.min(b.x1, b.x2)));
|
|
8483
|
+
}
|
|
8484
|
+
if (a\u306F\u5782\u76F4 && b\u306F\u5782\u76F4 && Math.abs(a.x1 - b.x1) <= 1) {
|
|
8485
|
+
\u5408\u8A08 += Math.max(0, Math.min(Math.max(a.y1, a.y2), Math.max(b.y1, b.y2)) - Math.max(Math.min(a.y1, a.y2), Math.min(b.y1, b.y2)));
|
|
8486
|
+
}
|
|
8487
|
+
}
|
|
8488
|
+
}
|
|
8489
|
+
return \u5408\u8A08;
|
|
8490
|
+
};
|
|
8402
8491
|
const \u540C\u3058\u7D44\u306E\u6570 = /* @__PURE__ */ new Map();
|
|
8403
8492
|
for (const e of edges) \u540C\u3058\u7D44\u306E\u6570.set(`${e.from}->${e.to}`, (\u540C\u3058\u7D44\u306E\u6570.get(`${e.from}->${e.to}`) ?? 0) + 1);
|
|
8404
8493
|
const \u675F = /* @__PURE__ */ new Map();
|
|
8494
|
+
const \u51FA\u308B\u7DDA = /* @__PURE__ */ new Map();
|
|
8405
8495
|
for (const e of edges) {
|
|
8496
|
+
if (nmap.has(e.from)) {
|
|
8497
|
+
const key2 = `${e.from}::${e.fromSide}`;
|
|
8498
|
+
const list2 = \u51FA\u308B\u7DDA.get(key2) ?? [];
|
|
8499
|
+
list2.push(e);
|
|
8500
|
+
\u51FA\u308B\u7DDA.set(key2, list2);
|
|
8501
|
+
}
|
|
8406
8502
|
if (!nmap.has(e.to)) continue;
|
|
8407
8503
|
if ((\u540C\u3058\u7D44\u306E\u6570.get(`${e.from}->${e.to}`) ?? 0) > 1) continue;
|
|
8408
8504
|
const key = `${e.to}::${e.toSide}`;
|
|
@@ -8410,27 +8506,48 @@ function fanIncomingEndpoints(edges, nodes) {
|
|
|
8410
8506
|
list.push(e);
|
|
8411
8507
|
\u675F.set(key, list);
|
|
8412
8508
|
}
|
|
8413
|
-
for (const [, list] of \u675F) {
|
|
8414
|
-
|
|
8509
|
+
for (const [key, list] of \u675F) {
|
|
8510
|
+
const \u4E2D\u592E\u304C\u585E\u304C\u3063\u3066\u3044\u308B = (\u51FA\u308B\u7DDA.get(key) ?? []).some(
|
|
8511
|
+
(\u51FA\u7DDA) => list.some(
|
|
8512
|
+
(\u5165\u7DDA) => !(\u5165\u7DDA.from === \u51FA\u7DDA.to && \u5165\u7DDA.to === \u51FA\u7DDA.from) && \u8EF8\u306B\u5E73\u884C\u306A\u91CD\u306A\u308A\u9577\u3055(\u5165\u7DDA, \u51FA\u7DDA) >= MIXED_ROOT_OVERLAP_MIN
|
|
8513
|
+
)
|
|
8514
|
+
);
|
|
8515
|
+
if (list.length < 2 && !\u4E2D\u592E\u304C\u585E\u304C\u3063\u3066\u3044\u308B) continue;
|
|
8415
8516
|
const n = nmap.get(list[0].to);
|
|
8416
8517
|
const \u6A2A = list[0].toSide === "left" || list[0].toSide === "right";
|
|
8417
8518
|
const \u8FBA\u306E\u9577\u3055 = \u6A2A ? n.h : n.w;
|
|
8418
8519
|
const \u4F7F\u3048\u308B\u5E452 = \u8FBA\u306E\u9577\u3055 - 2 * ARROW_ENDPOINT_CENTER_TOL;
|
|
8419
8520
|
if (\u4F7F\u3048\u308B\u5E452 <= 0) continue;
|
|
8420
|
-
const \u9593
|
|
8521
|
+
const \u5E2D\u306E\u9593 = \u4E2D\u592E\u304C\u585E\u304C\u3063\u3066\u3044\u308B ? list.length : list.length - 1;
|
|
8522
|
+
const \u9593\u9694 = Math.min(ENDPOINT_FAN_STEP, \u4F7F\u3048\u308B\u5E452 / \u5E2D\u306E\u9593);
|
|
8421
8523
|
if (\u9593\u9694 < ENDPOINT_FAN_MIN) continue;
|
|
8422
|
-
const \
|
|
8524
|
+
const \u8FBA\u306E\u4E2D\u5FC3 = \u6A2A ? n.cy : n.cx;
|
|
8525
|
+
const \u4E26\u3073 = list.map((e) => {
|
|
8526
|
+
const \u533A\u9593 = extractPathSegments(e.d);
|
|
8527
|
+
const last = \u533A\u9593[\u533A\u9593.length - 1];
|
|
8528
|
+
const \u9577\u3044\u52A9\u8D70 = last === void 0 ? 0 : Math.hypot(last.x2 - last.x1, last.y2 - last.y1);
|
|
8529
|
+
const \u4E2D\u5FC3\u3092\u88DC\u3046 = \u4E2D\u592E\u304C\u585E\u304C\u3063\u3066\u3044\u308B || list.length === 2;
|
|
8530
|
+
const \u6DF1\u3055 = \u8FBA\u304B\u3089\u96E2\u308C\u305F\u5074\u306E\u4F4D\u7F6E(e, \u6A2A) ?? (\u4E2D\u5FC3\u3092\u88DC\u3046 ? \u8FBA\u306E\u4E2D\u5FC3 : 0);
|
|
8531
|
+
return { e, \u9577\u3044\u52A9\u8D70, \u6DF1\u3055 };
|
|
8532
|
+
}).sort((a, b) => a.\u6DF1\u3055 - b.\u6DF1\u3055 || (a.e.id < b.e.id ? -1 : 1));
|
|
8423
8533
|
const \u4E2D\u5FC3 = (\u4E26\u3073.length - 1) * \u9593\u9694 / 2;
|
|
8534
|
+
let \u8CA0\u5074\u306E\u5E2D = 0;
|
|
8535
|
+
let \u6B63\u5074\u306E\u5E2D = 0;
|
|
8424
8536
|
for (let k = 0; k < \u4E26\u3073.length; k++) {
|
|
8425
|
-
const d = k * \u9593\u9694 - \u4E2D\u5FC3;
|
|
8537
|
+
const d = \u4E2D\u592E\u304C\u585E\u304C\u3063\u3066\u3044\u308B ? \u4E26\u3073[k].\u6DF1\u3055 < \u8FBA\u306E\u4E2D\u5FC3 ? -(++\u8CA0\u5074\u306E\u5E2D * \u9593\u9694) : ++\u6B63\u5074\u306E\u5E2D * \u9593\u9694 : k * \u9593\u9694 - \u4E2D\u5FC3;
|
|
8426
8538
|
if (Math.abs(d) < 1e-3) continue;
|
|
8427
8539
|
const e = \u4E26\u3073[k].e;
|
|
8428
|
-
const \u5DEE\u66FF = \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \u6A2A, d, nodes);
|
|
8429
|
-
if (\u5DEE\u66FF === null) continue;
|
|
8430
8540
|
const \u524D = e.d;
|
|
8431
8541
|
const \u524D\u306E\u4EA4\u5DEE = countEdgeCrossings(edges).count;
|
|
8432
|
-
|
|
8433
|
-
|
|
8542
|
+
const \u9577\u3044\u52A9\u8D70 = \u4E26\u3073[k].\u9577\u3044\u52A9\u8D70;
|
|
8543
|
+
for (const \u52A9\u8D70 of [\u9577\u3044\u52A9\u8D70, ENDPOINT_FAN_RUNUP]) {
|
|
8544
|
+
e.d = \u524D;
|
|
8545
|
+
const \u5DEE\u66FF = \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \u6A2A, d, \u52A9\u8D70, nodes);
|
|
8546
|
+
if (\u5DEE\u66FF === null) continue;
|
|
8547
|
+
e.d = \u5DEE\u66FF;
|
|
8548
|
+
if (countEdgeCrossings(edges).count <= \u524D\u306E\u4EA4\u5DEE) break;
|
|
8549
|
+
e.d = \u524D;
|
|
8550
|
+
}
|
|
8434
8551
|
}
|
|
8435
8552
|
}
|
|
8436
8553
|
}
|
|
@@ -8443,7 +8560,7 @@ function \u8FBA\u304B\u3089\u96E2\u308C\u305F\u5074\u306E\u4F4D\u7F6E(e, \u6A2A)
|
|
|
8443
8560
|
}
|
|
8444
8561
|
return null;
|
|
8445
8562
|
}
|
|
8446
|
-
function \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \u6A2A, d, nodes) {
|
|
8563
|
+
function \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \u6A2A, d, \u52A9\u8D70, nodes) {
|
|
8447
8564
|
if ((e.d.match(/M/g) ?? []).length !== 1) return null;
|
|
8448
8565
|
const segs = extractPathSegments(e.d);
|
|
8449
8566
|
if (segs.length === 0) return null;
|
|
@@ -8456,7 +8573,8 @@ function \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \
|
|
|
8456
8573
|
if (\u9577\u3055 < ENDPOINT_FAN_RUNUP + 1) return null;
|
|
8457
8574
|
const ux = (last.x1 - last.x2) / \u9577\u3055;
|
|
8458
8575
|
const uy = (last.y1 - last.y2) / \u9577\u3055;
|
|
8459
|
-
const \
|
|
8576
|
+
const \u4E38\u3081\u305F\u52A9\u8D70 = Math.min(\u52A9\u8D70, \u9577\u3055);
|
|
8577
|
+
const \u6298\u308C1 = { x: last.x2 + ux * \u4E38\u3081\u305F\u52A9\u8D70, y: last.y2 + uy * \u4E38\u3081\u305F\u52A9\u8D70 };
|
|
8460
8578
|
const \u6298\u308C2 = \u6A2A ? { x: \u6298\u308C1.x, y: \u6298\u308C1.y + d } : { x: \u6298\u308C1.x + d, y: \u6298\u308C1.y };
|
|
8461
8579
|
const \u7D42\u70B9 = \u6A2A ? { x: last.x2, y: last.y2 + d } : { x: last.x2 + d, y: last.y2 };
|
|
8462
8580
|
const \u65B0\u533A\u9593 = [
|
|
@@ -8478,7 +8596,8 @@ function \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \
|
|
|
8478
8596
|
}
|
|
8479
8597
|
parts.push(`L ${s.x2} ${s.y2}`);
|
|
8480
8598
|
}
|
|
8481
|
-
|
|
8599
|
+
const \u6298\u308C1\u306F\u76F4\u524D\u306E\u6298\u308C = Math.abs(\u6298\u308C1.x - last.x1) <= 0.5 && Math.abs(\u6298\u308C1.y - last.y1) <= 0.5;
|
|
8600
|
+
if (!\u6298\u308C1\u306F\u76F4\u524D\u306E\u6298\u308C) parts.push(`L ${round1(\u6298\u308C1.x)} ${round1(\u6298\u308C1.y)}`);
|
|
8482
8601
|
parts.push(`L ${round1(\u6298\u308C2.x)} ${round1(\u6298\u308C2.y)}`);
|
|
8483
8602
|
parts.push(`L ${round1(\u7D42\u70B9.x)} ${round1(\u7D42\u70B9.y)}`);
|
|
8484
8603
|
return parts.join(" ");
|
|
@@ -8961,6 +9080,7 @@ function layout(diag) {
|
|
|
8961
9080
|
diag.edges.filter((e) => e.posX1 !== void 0 && e.posY1 !== void 0 && e.posX2 !== void 0 && e.posY2 !== void 0).map((e) => e.id)
|
|
8962
9081
|
);
|
|
8963
9082
|
bowSharedStraightPaths(edges, nodesFinal, positionedEdgeIds);
|
|
9083
|
+
pullOutgoingFirstCorner(edges, nodesFinal);
|
|
8964
9084
|
fanIncomingEndpoints(edges, nodesFinal);
|
|
8965
9085
|
separateSharedStraightRuns(edges, nodesFinal);
|
|
8966
9086
|
hopEdgeCrossings(edges);
|
|
@@ -9002,6 +9122,8 @@ function layout(diag) {
|
|
|
9002
9122
|
// **遮断はここだけに置く**。 描画は必ず組み立てを通り、組み立て API も `er` も
|
|
9003
9123
|
// 素通しにしてある。 上流にも置くと、どの入力でも通らない分岐が残る
|
|
9004
9124
|
...diag.palette ? { palette: diag.palette } : {},
|
|
9125
|
+
// 種類も配色と同じく空の目印を出さない。 遮断をここに揃えると手書きの図にも効く
|
|
9126
|
+
...diag.type ? { type: diag.type } : {},
|
|
9005
9127
|
bboxes,
|
|
9006
9128
|
collisions,
|
|
9007
9129
|
nearCollisions,
|
|
@@ -17204,6 +17326,7 @@ function CdlStage({
|
|
|
17204
17326
|
"data-cdl-stage": "",
|
|
17205
17327
|
"data-cdl-scale": diagramScale === 1 ? void 0 : diagramScale,
|
|
17206
17328
|
"data-cdl-palette": laid.palette,
|
|
17329
|
+
"data-cdl-type": laid.type,
|
|
17207
17330
|
children: [
|
|
17208
17331
|
/* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
|
|
17209
17332
|
Object.entries(TONE).flatMap(
|