@cardenelabs/cdl 0.29.0 → 0.30.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.js CHANGED
@@ -8391,16 +8391,112 @@ function separateSharedStraightRuns(edges, nodes) {
8391
8391
  e.d = verticesToPath(verts.get(e.id));
8392
8392
  }
8393
8393
  }
8394
+ function pullOutgoingFirstCorner(edges, nodes) {
8395
+ if (edges.length < 2) return;
8396
+ const \u675F = /* @__PURE__ */ new Map();
8397
+ const \u540C\u3058\u7D44\u306E\u6570 = /* @__PURE__ */ new Map();
8398
+ for (const e of edges) {
8399
+ const key = `${e.from}::${e.fromSide}`;
8400
+ const list = \u675F.get(key) ?? [];
8401
+ list.push(e);
8402
+ \u675F.set(key, list);
8403
+ const pair = `${e.from}->${e.to}`;
8404
+ \u540C\u3058\u7D44\u306E\u6570.set(pair, (\u540C\u3058\u7D44\u306E\u6570.get(pair) ?? 0) + 1);
8405
+ }
8406
+ let \u672D\u3092\u65E7\u7D4C\u8DEF\u3078\u8FFD\u5F93\u6E08\u307F = false;
8407
+ for (const list of \u675F.values()) {
8408
+ if (list.length < 2) continue;
8409
+ const \u4E26\u3073 = list.flatMap((e) => {
8410
+ const pts = pathVertices(e.d);
8411
+ if (!pts || pts.length < 2) return [];
8412
+ return [{ e, pts, \u6700\u521D\u306E\u9577\u3055: Math.hypot(pts[1].x - pts[0].x, pts[1].y - pts[0].y) }];
8413
+ }).sort((a, b) => b.\u6700\u521D\u306E\u9577\u3055 - a.\u6700\u521D\u306E\u9577\u3055);
8414
+ for (const { e, pts, \u6700\u521D\u306E\u9577\u3055 } of \u4E26\u3073.slice(1)) {
8415
+ if ((\u540C\u3058\u7D44\u306E\u6570.get(`${e.from}->${e.to}`) ?? 0) > 1) continue;
8416
+ if (pts.length < 3 || \u6700\u521D\u306E\u9577\u3055 <= EDGE_STUB_OUT + VERTICAL_DETOUR_CORNER) continue;
8417
+ const \u6A2A = e.fromSide === "left" || e.fromSide === "right";
8418
+ if (!runIsAligned(pts, 0, \u6A2A ? 1 : 0)) continue;
8419
+ const \u79FB\u52D5\u91CF = \u6700\u521D\u306E\u9577\u3055 - (EDGE_STUB_OUT + VERTICAL_DETOUR_CORNER);
8420
+ const ux = (pts[1].x - pts[0].x) / \u6700\u521D\u306E\u9577\u3055;
8421
+ const uy = (pts[1].y - pts[0].y) / \u6700\u521D\u306E\u9577\u3055;
8422
+ const \u8A66\u3057 = pts.map(
8423
+ (p, i) => i === 1 || i === 2 ? { x: p.x - ux * \u79FB\u52D5\u91CF, y: p.y - uy * \u79FB\u52D5\u91CF } : p
8424
+ );
8425
+ const \u8A66\u3057D = verticesToPath(\u8A66\u3057);
8426
+ const \u8A66\u3057\u533A\u9593 = flattenPathSegments(extractPathSegments(\u8A66\u3057D));
8427
+ if (nodes.some(
8428
+ (n) => n.id !== e.from && n.id !== e.to && segmentsCrossRect(\u8A66\u3057\u533A\u9593, nodeRect(n))
8429
+ )) {
8430
+ continue;
8431
+ }
8432
+ const \u524D = e.d;
8433
+ const \u524D\u306E\u4EA4\u5DEE = countEdgeCrossings(edges).count;
8434
+ e.d = \u8A66\u3057D;
8435
+ if (countEdgeCrossings(edges).count > \u524D\u306E\u4EA4\u5DEE) {
8436
+ e.d = \u524D;
8437
+ continue;
8438
+ }
8439
+ e.d = \u524D;
8440
+ if (!\u672D\u3092\u65E7\u7D4C\u8DEF\u3078\u8FFD\u5F93\u6E08\u307F) {
8441
+ slideLabelsAlongOwnPath(edges, nodes);
8442
+ \u672D\u3092\u65E7\u7D4C\u8DEF\u3078\u8FFD\u5F93\u6E08\u307F = true;
8443
+ }
8444
+ const labelBox = computeLabelBBoxWorld(e);
8445
+ const label = { x: labelBox.x + labelBox.w / 2, y: labelBox.y + labelBox.h / 2 };
8446
+ const \u7DDA\u5206\u307E\u3067\u306E\u8DDD\u96E22 = (a, b) => {
8447
+ const dx = b.x - a.x;
8448
+ const dy = b.y - a.y;
8449
+ const len2 = dx * dx + dy * dy;
8450
+ const t = len2 === 0 ? 0 : Math.max(0, Math.min(1, ((label.x - a.x) * dx + (label.y - a.y) * dy) / len2));
8451
+ return (label.x - (a.x + dx * t)) ** 2 + (label.y - (a.y + dy * t)) ** 2;
8452
+ };
8453
+ const \u52D5\u304F\u533A\u9593\u3078\u306E\u8DDD\u96E2 = \u7DDA\u5206\u307E\u3067\u306E\u8DDD\u96E22(pts[1], pts[2]);
8454
+ 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);
8455
+ e.d = \u8A66\u3057D;
8456
+ if (label\u3082\u52D5\u304B\u3059) {
8457
+ e.labelX -= ux * \u79FB\u52D5\u91CF;
8458
+ e.labelY -= uy * \u79FB\u52D5\u91CF;
8459
+ }
8460
+ }
8461
+ }
8462
+ }
8394
8463
  var ENDPOINT_FAN_STEP = 56;
8395
8464
  var ENDPOINT_FAN_MIN = 20;
8396
8465
  var ENDPOINT_FAN_RUNUP = 40;
8466
+ var MIXED_ROOT_OVERLAP_MIN = 24;
8397
8467
  function fanIncomingEndpoints(edges, nodes) {
8398
8468
  if (edges.length < 2) return;
8399
8469
  const nmap = new Map(nodes.map((n) => [n.id, n]));
8470
+ const \u5E73\u5766\u306A\u533A\u9593 = new Map(edges.map((e) => [e.id, flattenPathSegments(extractPathSegments(e.d))]));
8471
+ const \u8EF8\u306B\u5E73\u884C\u306A\u91CD\u306A\u308A\u9577\u3055 = (\u4E00\u65B9, \u4ED6\u65B9) => {
8472
+ let \u5408\u8A08 = 0;
8473
+ for (const a of \u5E73\u5766\u306A\u533A\u9593.get(\u4E00\u65B9.id) ?? []) {
8474
+ const a\u306F\u6C34\u5E73 = Math.abs(a.y2 - a.y1) <= 1;
8475
+ const a\u306F\u5782\u76F4 = Math.abs(a.x2 - a.x1) <= 1;
8476
+ for (const b of \u5E73\u5766\u306A\u533A\u9593.get(\u4ED6\u65B9.id) ?? []) {
8477
+ const b\u306F\u6C34\u5E73 = Math.abs(b.y2 - b.y1) <= 1;
8478
+ const b\u306F\u5782\u76F4 = Math.abs(b.x2 - b.x1) <= 1;
8479
+ if (a\u306F\u6C34\u5E73 && b\u306F\u6C34\u5E73 && Math.abs(a.y1 - b.y1) <= 1) {
8480
+ \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)));
8481
+ }
8482
+ if (a\u306F\u5782\u76F4 && b\u306F\u5782\u76F4 && Math.abs(a.x1 - b.x1) <= 1) {
8483
+ \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)));
8484
+ }
8485
+ }
8486
+ }
8487
+ return \u5408\u8A08;
8488
+ };
8400
8489
  const \u540C\u3058\u7D44\u306E\u6570 = /* @__PURE__ */ new Map();
8401
8490
  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);
8402
8491
  const \u675F = /* @__PURE__ */ new Map();
8492
+ const \u51FA\u308B\u7DDA = /* @__PURE__ */ new Map();
8403
8493
  for (const e of edges) {
8494
+ if (nmap.has(e.from)) {
8495
+ const key2 = `${e.from}::${e.fromSide}`;
8496
+ const list2 = \u51FA\u308B\u7DDA.get(key2) ?? [];
8497
+ list2.push(e);
8498
+ \u51FA\u308B\u7DDA.set(key2, list2);
8499
+ }
8404
8500
  if (!nmap.has(e.to)) continue;
8405
8501
  if ((\u540C\u3058\u7D44\u306E\u6570.get(`${e.from}->${e.to}`) ?? 0) > 1) continue;
8406
8502
  const key = `${e.to}::${e.toSide}`;
@@ -8408,27 +8504,48 @@ function fanIncomingEndpoints(edges, nodes) {
8408
8504
  list.push(e);
8409
8505
  \u675F.set(key, list);
8410
8506
  }
8411
- for (const [, list] of \u675F) {
8412
- if (list.length < 2) continue;
8507
+ for (const [key, list] of \u675F) {
8508
+ const \u4E2D\u592E\u304C\u585E\u304C\u3063\u3066\u3044\u308B = (\u51FA\u308B\u7DDA.get(key) ?? []).some(
8509
+ (\u51FA\u7DDA) => list.some(
8510
+ (\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
8511
+ )
8512
+ );
8513
+ if (list.length < 2 && !\u4E2D\u592E\u304C\u585E\u304C\u3063\u3066\u3044\u308B) continue;
8413
8514
  const n = nmap.get(list[0].to);
8414
8515
  const \u6A2A = list[0].toSide === "left" || list[0].toSide === "right";
8415
8516
  const \u8FBA\u306E\u9577\u3055 = \u6A2A ? n.h : n.w;
8416
8517
  const \u4F7F\u3048\u308B\u5E452 = \u8FBA\u306E\u9577\u3055 - 2 * ARROW_ENDPOINT_CENTER_TOL;
8417
8518
  if (\u4F7F\u3048\u308B\u5E452 <= 0) continue;
8418
- const \u9593\u9694 = Math.min(ENDPOINT_FAN_STEP, \u4F7F\u3048\u308B\u5E452 / (list.length - 1));
8519
+ const \u5E2D\u306E\u9593 = \u4E2D\u592E\u304C\u585E\u304C\u3063\u3066\u3044\u308B ? list.length : list.length - 1;
8520
+ const \u9593\u9694 = Math.min(ENDPOINT_FAN_STEP, \u4F7F\u3048\u308B\u5E452 / \u5E2D\u306E\u9593);
8419
8521
  if (\u9593\u9694 < ENDPOINT_FAN_MIN) continue;
8420
- const \u4E26\u3073 = list.map((e) => ({ e, \u6DF1\u3055: \u8FBA\u304B\u3089\u96E2\u308C\u305F\u5074\u306E\u4F4D\u7F6E(e, \u6A2A) ?? 0 })).sort((a, b) => a.\u6DF1\u3055 - b.\u6DF1\u3055 || (a.e.id < b.e.id ? -1 : 1));
8522
+ const \u8FBA\u306E\u4E2D\u5FC3 = \u6A2A ? n.cy : n.cx;
8523
+ const \u4E26\u3073 = list.map((e) => {
8524
+ const \u533A\u9593 = extractPathSegments(e.d);
8525
+ const last = \u533A\u9593[\u533A\u9593.length - 1];
8526
+ const \u9577\u3044\u52A9\u8D70 = last === void 0 ? 0 : Math.hypot(last.x2 - last.x1, last.y2 - last.y1);
8527
+ const \u4E2D\u5FC3\u3092\u88DC\u3046 = \u4E2D\u592E\u304C\u585E\u304C\u3063\u3066\u3044\u308B || list.length === 2;
8528
+ 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);
8529
+ return { e, \u9577\u3044\u52A9\u8D70, \u6DF1\u3055 };
8530
+ }).sort((a, b) => a.\u6DF1\u3055 - b.\u6DF1\u3055 || (a.e.id < b.e.id ? -1 : 1));
8421
8531
  const \u4E2D\u5FC3 = (\u4E26\u3073.length - 1) * \u9593\u9694 / 2;
8532
+ let \u8CA0\u5074\u306E\u5E2D = 0;
8533
+ let \u6B63\u5074\u306E\u5E2D = 0;
8422
8534
  for (let k = 0; k < \u4E26\u3073.length; k++) {
8423
- const d = k * \u9593\u9694 - \u4E2D\u5FC3;
8535
+ 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;
8424
8536
  if (Math.abs(d) < 1e-3) continue;
8425
8537
  const e = \u4E26\u3073[k].e;
8426
- const \u5DEE\u66FF = \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \u6A2A, d, nodes);
8427
- if (\u5DEE\u66FF === null) continue;
8428
8538
  const \u524D = e.d;
8429
8539
  const \u524D\u306E\u4EA4\u5DEE = countEdgeCrossings(edges).count;
8430
- e.d = \u5DEE\u66FF;
8431
- if (countEdgeCrossings(edges).count > \u524D\u306E\u4EA4\u5DEE) e.d = \u524D;
8540
+ const \u9577\u3044\u52A9\u8D70 = \u4E26\u3073[k].\u9577\u3044\u52A9\u8D70;
8541
+ for (const \u52A9\u8D70 of [\u9577\u3044\u52A9\u8D70, ENDPOINT_FAN_RUNUP]) {
8542
+ e.d = \u524D;
8543
+ const \u5DEE\u66FF = \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \u6A2A, d, \u52A9\u8D70, nodes);
8544
+ if (\u5DEE\u66FF === null) continue;
8545
+ e.d = \u5DEE\u66FF;
8546
+ if (countEdgeCrossings(edges).count <= \u524D\u306E\u4EA4\u5DEE) break;
8547
+ e.d = \u524D;
8548
+ }
8432
8549
  }
8433
8550
  }
8434
8551
  }
@@ -8441,7 +8558,7 @@ function \u8FBA\u304B\u3089\u96E2\u308C\u305F\u5074\u306E\u4F4D\u7F6E(e, \u6A2A)
8441
8558
  }
8442
8559
  return null;
8443
8560
  }
8444
- function \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \u6A2A, d, nodes) {
8561
+ function \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \u6A2A, d, \u52A9\u8D70, nodes) {
8445
8562
  if ((e.d.match(/M/g) ?? []).length !== 1) return null;
8446
8563
  const segs = extractPathSegments(e.d);
8447
8564
  if (segs.length === 0) return null;
@@ -8454,7 +8571,12 @@ function \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \
8454
8571
  if (\u9577\u3055 < ENDPOINT_FAN_RUNUP + 1) return null;
8455
8572
  const ux = (last.x1 - last.x2) / \u9577\u3055;
8456
8573
  const uy = (last.y1 - last.y2) / \u9577\u3055;
8457
- const \u6298\u308C1 = { x: last.x2 + ux * ENDPOINT_FAN_RUNUP, y: last.y2 + uy * ENDPOINT_FAN_RUNUP };
8574
+ const head = segs[0];
8575
+ const \u6700\u5F8C\u306E\u533A\u9593\u304C\u8D77\u70B9\u3092\u542B\u3080 = Math.abs(last.x1 - head.x1) <= 0.5 && Math.abs(last.y1 - head.y1) <= 0.5;
8576
+ const \u52A9\u8D70\u4E0A\u9650 = \u6700\u5F8C\u306E\u533A\u9593\u304C\u8D77\u70B9\u3092\u542B\u3080 ? \u9577\u3055 - EDGE_STUB_OUT : \u9577\u3055;
8577
+ const \u4E38\u3081\u305F\u52A9\u8D70 = Math.min(\u52A9\u8D70, \u52A9\u8D70\u4E0A\u9650);
8578
+ if (\u4E38\u3081\u305F\u52A9\u8D70 < ENDPOINT_FAN_RUNUP) return null;
8579
+ const \u6298\u308C1 = { x: last.x2 + ux * \u4E38\u3081\u305F\u52A9\u8D70, y: last.y2 + uy * \u4E38\u3081\u305F\u52A9\u8D70 };
8458
8580
  const \u6298\u308C2 = \u6A2A ? { x: \u6298\u308C1.x, y: \u6298\u308C1.y + d } : { x: \u6298\u308C1.x + d, y: \u6298\u308C1.y };
8459
8581
  const \u7D42\u70B9 = \u6A2A ? { x: last.x2, y: last.y2 + d } : { x: last.x2 + d, y: last.y2 };
8460
8582
  const \u65B0\u533A\u9593 = [
@@ -8465,7 +8587,6 @@ function \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \
8465
8587
  if (nodes.some((n) => n.id !== e.from && n.id !== e.to && segmentsCrossRect(\u65B0\u533A\u9593, nodeRect(n)))) {
8466
8588
  return null;
8467
8589
  }
8468
- const head = segs[0];
8469
8590
  const parts = [`M ${head.x1} ${head.y1}`];
8470
8591
  for (let i = 0; i < segs.length - 1; i++) {
8471
8592
  const s = segs[i];
@@ -8476,7 +8597,8 @@ function \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \
8476
8597
  }
8477
8598
  parts.push(`L ${s.x2} ${s.y2}`);
8478
8599
  }
8479
- parts.push(`L ${round1(\u6298\u308C1.x)} ${round1(\u6298\u308C1.y)}`);
8600
+ 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;
8601
+ if (!\u6298\u308C1\u306F\u76F4\u524D\u306E\u6298\u308C) parts.push(`L ${round1(\u6298\u308C1.x)} ${round1(\u6298\u308C1.y)}`);
8480
8602
  parts.push(`L ${round1(\u6298\u308C2.x)} ${round1(\u6298\u308C2.y)}`);
8481
8603
  parts.push(`L ${round1(\u7D42\u70B9.x)} ${round1(\u7D42\u70B9.y)}`);
8482
8604
  return parts.join(" ");
@@ -8959,6 +9081,7 @@ function layout(diag) {
8959
9081
  diag.edges.filter((e) => e.posX1 !== void 0 && e.posY1 !== void 0 && e.posX2 !== void 0 && e.posY2 !== void 0).map((e) => e.id)
8960
9082
  );
8961
9083
  bowSharedStraightPaths(edges, nodesFinal, positionedEdgeIds);
9084
+ pullOutgoingFirstCorner(edges, nodesFinal);
8962
9085
  fanIncomingEndpoints(edges, nodesFinal);
8963
9086
  separateSharedStraightRuns(edges, nodesFinal);
8964
9087
  hopEdgeCrossings(edges);