@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.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
- if (list.length < 2) continue;
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\u9694 = Math.min(ENDPOINT_FAN_STEP, \u4F7F\u3048\u308B\u5E452 / (list.length - 1));
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 \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));
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
- e.d = \u5DEE\u66FF;
8433
- if (countEdgeCrossings(edges).count > \u524D\u306E\u4EA4\u5DEE) e.d = \u524D;
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,12 @@ 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 \u6298\u308C1 = { x: last.x2 + ux * ENDPOINT_FAN_RUNUP, y: last.y2 + uy * ENDPOINT_FAN_RUNUP };
8576
+ const head = segs[0];
8577
+ 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;
8578
+ const \u52A9\u8D70\u4E0A\u9650 = \u6700\u5F8C\u306E\u533A\u9593\u304C\u8D77\u70B9\u3092\u542B\u3080 ? \u9577\u3055 - EDGE_STUB_OUT : \u9577\u3055;
8579
+ const \u4E38\u3081\u305F\u52A9\u8D70 = Math.min(\u52A9\u8D70, \u52A9\u8D70\u4E0A\u9650);
8580
+ if (\u4E38\u3081\u305F\u52A9\u8D70 < ENDPOINT_FAN_RUNUP) return null;
8581
+ const \u6298\u308C1 = { x: last.x2 + ux * \u4E38\u3081\u305F\u52A9\u8D70, y: last.y2 + uy * \u4E38\u3081\u305F\u52A9\u8D70 };
8460
8582
  const \u6298\u308C2 = \u6A2A ? { x: \u6298\u308C1.x, y: \u6298\u308C1.y + d } : { x: \u6298\u308C1.x + d, y: \u6298\u308C1.y };
8461
8583
  const \u7D42\u70B9 = \u6A2A ? { x: last.x2, y: last.y2 + d } : { x: last.x2 + d, y: last.y2 };
8462
8584
  const \u65B0\u533A\u9593 = [
@@ -8467,7 +8589,6 @@ function \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \
8467
8589
  if (nodes.some((n) => n.id !== e.from && n.id !== e.to && segmentsCrossRect(\u65B0\u533A\u9593, nodeRect(n)))) {
8468
8590
  return null;
8469
8591
  }
8470
- const head = segs[0];
8471
8592
  const parts = [`M ${head.x1} ${head.y1}`];
8472
8593
  for (let i = 0; i < segs.length - 1; i++) {
8473
8594
  const s = segs[i];
@@ -8478,7 +8599,8 @@ function \u672B\u5C3E\u3092\u8FBA\u306B\u6CBF\u3063\u3066\u305A\u3089\u3059(e, \
8478
8599
  }
8479
8600
  parts.push(`L ${s.x2} ${s.y2}`);
8480
8601
  }
8481
- parts.push(`L ${round1(\u6298\u308C1.x)} ${round1(\u6298\u308C1.y)}`);
8602
+ 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;
8603
+ if (!\u6298\u308C1\u306F\u76F4\u524D\u306E\u6298\u308C) parts.push(`L ${round1(\u6298\u308C1.x)} ${round1(\u6298\u308C1.y)}`);
8482
8604
  parts.push(`L ${round1(\u6298\u308C2.x)} ${round1(\u6298\u308C2.y)}`);
8483
8605
  parts.push(`L ${round1(\u7D42\u70B9.x)} ${round1(\u7D42\u70B9.y)}`);
8484
8606
  return parts.join(" ");
@@ -8961,6 +9083,7 @@ function layout(diag) {
8961
9083
  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
9084
  );
8963
9085
  bowSharedStraightPaths(edges, nodesFinal, positionedEdgeIds);
9086
+ pullOutgoingFirstCorner(edges, nodesFinal);
8964
9087
  fanIncomingEndpoints(edges, nodesFinal);
8965
9088
  separateSharedStraightRuns(edges, nodesFinal);
8966
9089
  hopEdgeCrossings(edges);