@yuneta/gobj-ui 7.23.154 → 7.23.156

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/README.md CHANGED
@@ -1419,7 +1419,8 @@ layouts by three thin adapters in `c_g6_nodes_tree.js`:
1419
1419
  gained nothing on a whole level opened with the stepper, where every parent
1420
1420
  still needed the row of its children beside it. Against `tree`: regions
1421
1421
  only 10% of the width, one region open with a 24-device hall 21%, a whole
1422
- level open 41%. The tree grows taller instead; read it with elbow edges.
1422
+ level open 41%. The tree grows taller instead; with elbow edges or curves
1423
+ alike, since `7.23.155` a curve keeps off the cards too.
1423
1424
  - **`radial`** (`treedb-radial`) — the root in the middle, a ring per depth,
1424
1425
  every subtree an angular **sector** proportional to its leaves, and the
1425
1426
  radius of each ring the largest of three: one `ranksep` out from the ring
@@ -1429,7 +1430,15 @@ layouts by three thin adapters in `c_g6_nodes_tree.js`:
1429
1430
  cards touching, where the tidy tree's `ranksep` is a gap between COLUMNS
1430
1431
  and a column carries its own width. A fan that cannot overlap by
1431
1432
  construction, across the ring or along the radius; several roots share the
1432
- circle around an empty centre.
1433
+ circle around an empty centre. Since `7.23.156` a run of three or more
1434
+ **leaf** children is **stacked**, as in the compact tree: it asks its ring
1435
+ for one row of about the square root of its cards instead of one slot per
1436
+ leaf, and lays them in rows going outward, each as full as its room allows
1437
+ — rings round the parent when it is alone, a fan inside its sector when
1438
+ not. Measured over the arc it covers (a card is wider slanted), and a
1439
+ neighbour of the outer rings by the angle it covers, so nothing overlaps.
1440
+ On a real-shaped treedb it is 53–63% of the radial it was; `stack: false`
1441
+ keeps the old one.
1433
1442
 
1434
1443
  **Elbow edges** (`7.23.149`) are an option of the edges, not a layout: the
1435
1444
  toolbar's `GRAPH_EDGE_ELBOW` toggle sets `edge_shape` to `elbow`, and every
@@ -1481,7 +1490,16 @@ port run. Only the stub at the port is shared. Into a lower row of a stack of
1481
1490
  the compact tree an edge runs a **comb** (`7.23.154`): along the channel to a
1482
1491
  lane of its own in the stack's corridor, down it, and into the gap above its
1483
1492
  card; lanes go outermost first by row, so none crosses another, and a comb is
1484
- drawn as laid out, never routed. G6's `shortest-path` router is not used: it is
1493
+ drawn as laid out, never routed.
1494
+
1495
+ **Curved edges keep off the cards as well** (`7.23.155`). On a layout with
1496
+ rows a curve is `treedb-curve-v` / `-h`, a subclass of G6's cubic: the cubic
1497
+ as before, unless that very curve — the path G6 would draw, sampled, not the
1498
+ rectangle round it — would cross a card other than its own two, or the edge
1499
+ does not run forward and so would cross its own. Then it takes the way its
1500
+ elbow would (comb, detour, route, the same lanes and staggered turns) with
1501
+ corners rounded to 24px. On a layout with no rows the edges stay G6's plain
1502
+ cubic. G6's `shortest-path` router is not used: it is
1485
1503
  not exported, it
1486
1504
  falls back in silence to a route that crosses cards, and it rewrites its
1487
1505
  module defaults with every config it is given.
@@ -29423,6 +29423,56 @@ function stack_trunk_width(k) {
29423
29423
  let lanes = Math.max(0, k - 2);
29424
29424
  return Math.max(36, 20 + Math.max(0, lanes - 1) * 6);
29425
29425
  }
29426
+ /************************************************************
29427
+ * The children of every node, with each run of STACK_MIN_RUN or
29428
+ * more consecutive LEAF children replaced by one STACK. Runs, not
29429
+ * all the leaves of a parent: the children keep their order. A
29430
+ * stack's key is an OBJECT, so it can never be taken for a node id,
29431
+ * which is a string. Shared by the compact tree and the radial.
29432
+ *
29433
+ * Returns {kids_of: Map<id, [id | stack]>, stacks: Map<stack, {ids, depth}>}
29434
+ ************************************************************/
29435
+ function leaf_runs(t) {
29436
+ let kids_of = /* @__PURE__ */ new Map();
29437
+ let stacks = /* @__PURE__ */ new Map();
29438
+ for (let [id, kids] of t.children) {
29439
+ let out = [];
29440
+ let run = [];
29441
+ let flush = () => {
29442
+ if (run.length >= 3) {
29443
+ let key = { stack: stacks.size };
29444
+ stacks.set(key, {
29445
+ ids: run,
29446
+ depth: t.depth.get(run[0])
29447
+ });
29448
+ out.push(key);
29449
+ } else out.push(...run);
29450
+ run = [];
29451
+ };
29452
+ for (let kid of kids) if ((t.children.get(kid) || []).length === 0) run.push(kid);
29453
+ else {
29454
+ flush();
29455
+ out.push(kid);
29456
+ }
29457
+ flush();
29458
+ kids_of.set(id, out);
29459
+ }
29460
+ return {
29461
+ kids_of,
29462
+ stacks
29463
+ };
29464
+ }
29465
+ function stacked_order(t, kids_of) {
29466
+ let order = [];
29467
+ let todo = t.roots.slice().reverse();
29468
+ while (todo.length) {
29469
+ let id = todo.pop();
29470
+ order.push(id);
29471
+ let kids = kids_of.get(id) || [];
29472
+ for (let i = kids.length - 1; i >= 0; i--) todo.push(kids[i]);
29473
+ }
29474
+ return order;
29475
+ }
29426
29476
  function stack_geometry(t, st, col_x, col_w) {
29427
29477
  let d = st.depth;
29428
29478
  let k = st.ids.length;
@@ -29462,38 +29512,8 @@ function place_stack(t, st, g, top, pos) {
29462
29512
  function compact_tree_lr(nodes, edges, o) {
29463
29513
  let t = spanning_tree(nodes, edges);
29464
29514
  let pos = /* @__PURE__ */ new Map();
29465
- let kids_of = /* @__PURE__ */ new Map();
29466
- let stacks = /* @__PURE__ */ new Map();
29467
- for (let [id, kids] of t.children) {
29468
- let out = [];
29469
- let run = [];
29470
- let flush = () => {
29471
- if (run.length >= 3) {
29472
- let key = { stack: stacks.size };
29473
- stacks.set(key, {
29474
- ids: run,
29475
- depth: t.depth.get(run[0])
29476
- });
29477
- out.push(key);
29478
- } else out.push(...run);
29479
- run = [];
29480
- };
29481
- for (let kid of kids) if ((t.children.get(kid) || []).length === 0) run.push(kid);
29482
- else {
29483
- flush();
29484
- out.push(kid);
29485
- }
29486
- flush();
29487
- kids_of.set(id, out);
29488
- }
29489
- let order = [];
29490
- let todo = t.roots.slice().reverse();
29491
- while (todo.length) {
29492
- let id = todo.pop();
29493
- order.push(id);
29494
- let kids = kids_of.get(id) || [];
29495
- for (let i = kids.length - 1; i >= 0; i--) todo.push(kids[i]);
29496
- }
29515
+ let { kids_of, stacks } = leaf_runs(t);
29516
+ let order = stacked_order(t, kids_of);
29497
29517
  let col_w = [];
29498
29518
  for (let [id, d] of t.depth) col_w[d] = Math.max(col_w[d] || 0, t.by_id.get(id).w);
29499
29519
  let col_x = [];
@@ -29630,56 +29650,103 @@ function extent_at(n, a) {
29630
29650
  *
29631
29651
  * ranksep the step between rings
29632
29652
  * nodesep the gap between neighbours on a ring
29653
+ * stack (default true) a run of three or more LEAF children
29654
+ * is a STACK, as in the compact tree: it asks its
29655
+ * ring for one row of about the square root of its
29656
+ * cards, not for every leaf -- a hall with a hundred
29657
+ * devices no longer blows the ring up -- and lays
29658
+ * them in rows going OUTWARD, each row as full as
29659
+ * the room it has: rings round the parent when it is
29660
+ * alone, a fan inside its sector when it is not.
29661
+ * false keeps every leaf on the ring.
29633
29662
  ************************************************************/
29634
29663
  function layout_radial(nodes, edges, opts) {
29635
- let o = Object.assign({}, DEFAULTS, opts || {});
29664
+ let o = Object.assign({}, DEFAULTS, { stack: true }, opts || {});
29636
29665
  let t = spanning_tree(nodes, edges);
29637
29666
  let pos = /* @__PURE__ */ new Map();
29638
29667
  if (!t.roots.length) return pos;
29639
- let order = walk_order(t);
29640
- let leaves = /* @__PURE__ */ new Map();
29668
+ let runs = o.stack ? leaf_runs(t) : {
29669
+ kids_of: t.children,
29670
+ stacks: /* @__PURE__ */ new Map()
29671
+ };
29672
+ let kids_of = runs.kids_of;
29673
+ let stacks = runs.stacks;
29674
+ let order = stacked_order(t, kids_of);
29675
+ for (let st of stacks.values()) {
29676
+ st.per_row = Math.ceil(Math.sqrt(st.ids.length));
29677
+ st.cards = st.ids.map((id) => t.by_id.get(id));
29678
+ }
29679
+ let stack_across = (st, a) => {
29680
+ let w = 0;
29681
+ for (let c of st.cards) w = Math.max(w, extent_at(c, a + Math.PI / 2));
29682
+ return {
29683
+ card: w,
29684
+ row: st.per_row * w + (st.per_row - 1) * o.nodesep
29685
+ };
29686
+ };
29687
+ let widest_along = (cards, a, half) => {
29688
+ let e = 0;
29689
+ for (let k = 0; k <= 16; k++) {
29690
+ let th = a - half + 2 * half * k / 16;
29691
+ for (let c of cards) e = Math.max(e, extent_at(c, th));
29692
+ }
29693
+ return e;
29694
+ };
29695
+ let depth_of = (id) => stacks.has(id) ? stacks.get(id).depth : t.depth.get(id);
29696
+ let circ = (a, b) => {
29697
+ let d = Math.abs(a - b) % (2 * Math.PI);
29698
+ return d > Math.PI ? 2 * Math.PI - d : d;
29699
+ };
29700
+ let weight = /* @__PURE__ */ new Map();
29641
29701
  for (let i = order.length - 1; i >= 0; i--) {
29642
29702
  let id = order[i];
29643
- let kids = t.children.get(id) || [];
29703
+ let st = stacks.get(id);
29704
+ if (st) {
29705
+ weight.set(id, st.per_row);
29706
+ continue;
29707
+ }
29708
+ let kids = kids_of.get(id) || [];
29644
29709
  if (!kids.length) {
29645
- leaves.set(id, 1);
29710
+ weight.set(id, 1);
29646
29711
  continue;
29647
29712
  }
29648
29713
  let n = 0;
29649
- for (let kid of kids) n += leaves.get(kid);
29650
- leaves.set(id, n);
29714
+ for (let kid of kids) n += weight.get(kid);
29715
+ weight.set(id, n);
29651
29716
  }
29652
29717
  let total = 0;
29653
- for (let root of t.roots) total += leaves.get(root);
29718
+ for (let root of t.roots) total += weight.get(root);
29654
29719
  let single = t.roots.length === 1;
29655
- let ring_of = (id) => t.depth.get(id) + (single ? 0 : 1);
29720
+ let ring_of = (id) => depth_of(id) + (single ? 0 : 1);
29656
29721
  let angle = /* @__PURE__ */ new Map();
29657
29722
  let rings = [];
29658
29723
  let sector = (root_id, root_from, root_span, root_parent) => {
29659
- let stack = [{
29724
+ let todo = [{
29660
29725
  id: root_id,
29661
29726
  from: root_from,
29662
29727
  span: root_span,
29663
29728
  parent: root_parent
29664
29729
  }];
29665
- while (stack.length) {
29666
- let { id, from, span, parent } = stack.pop();
29730
+ while (todo.length) {
29731
+ let { id, from, span, parent } = todo.pop();
29667
29732
  let a = from + span / 2;
29668
29733
  angle.set(id, a);
29669
29734
  let ring = ring_of(id);
29670
29735
  if (!rings[ring]) rings[ring] = [];
29671
- let n = t.by_id.get(id);
29736
+ let st = stacks.get(id);
29737
+ let n = st ? null : t.by_id.get(id);
29672
29738
  rings[ring].push({
29673
29739
  id,
29674
29740
  angle: a,
29675
- diag: Math.hypot(n.w, n.h),
29676
- ext: extent_at(n, a),
29677
- parent_ext: parent ? extent_at(t.by_id.get(parent), a) : 0
29741
+ span,
29742
+ diag: st ? stack_across(st, a).row : Math.hypot(n.w, n.h),
29743
+ ext: st ? widest_along(st.cards, a, Math.min(span / 2, Math.PI)) : extent_at(n, a),
29744
+ parent_ext: !parent ? 0 : st ? widest_along([t.by_id.get(parent)], a, Math.min(span / 2, Math.PI)) : extent_at(t.by_id.get(parent), a)
29678
29745
  });
29679
29746
  let cursor = from;
29680
- for (let kid of t.children.get(id) || []) {
29681
- let part = span * leaves.get(kid) / leaves.get(id);
29682
- stack.push({
29747
+ for (let kid of kids_of.get(id) || []) {
29748
+ let part = span * weight.get(kid) / weight.get(id);
29749
+ todo.push({
29683
29750
  id: kid,
29684
29751
  from: cursor,
29685
29752
  span: part,
@@ -29693,38 +29760,120 @@ function layout_radial(nodes, edges, opts) {
29693
29760
  let root = t.roots[0];
29694
29761
  angle.set(root, 0);
29695
29762
  let cursor = -Math.PI / 2;
29696
- for (let kid of t.children.get(root) || []) {
29697
- let part = 2 * Math.PI * leaves.get(kid) / leaves.get(root);
29763
+ for (let kid of kids_of.get(root) || []) {
29764
+ let part = 2 * Math.PI * weight.get(kid) / weight.get(root);
29698
29765
  sector(kid, cursor, part, root);
29699
29766
  cursor += part;
29700
29767
  }
29701
29768
  } else {
29702
29769
  let cursor = -Math.PI / 2;
29703
29770
  for (let root of t.roots) {
29704
- let part = 2 * Math.PI * leaves.get(root) / total;
29771
+ let part = 2 * Math.PI * weight.get(root) / total;
29705
29772
  sector(root, cursor, part, null);
29706
29773
  cursor += part;
29707
29774
  }
29708
29775
  }
29776
+ let fit = (list, r0) => {
29777
+ let r = r0;
29778
+ let sorted = list.slice().sort((a, b) => a.angle - b.angle);
29779
+ for (let i = 0; i < sorted.length && sorted.length > 1; i++) {
29780
+ let a = sorted[i];
29781
+ let b = sorted[(i + 1) % sorted.length];
29782
+ let gap = i + 1 < sorted.length ? b.angle - a.angle : b.angle + 2 * Math.PI - a.angle;
29783
+ if (gap > 1e-9) r = Math.max(r, (a.diag / 2 + b.diag / 2 + o.nodesep) / gap);
29784
+ }
29785
+ return r;
29786
+ };
29709
29787
  let radius = [0];
29788
+ let reaching = [];
29710
29789
  for (let ring = 1; ring < rings.length; ring++) {
29790
+ let members = rings[ring] || [];
29711
29791
  let r = radius[ring - 1] + o.ranksep;
29712
- for (let n of rings[ring] || []) r = Math.max(r, radius[ring - 1] + (n.parent_ext + n.ext) / 2 + o.nodesep);
29713
- let list = (rings[ring] || []).slice().sort((a, b) => a.angle - b.angle);
29714
- for (let i = 0; i < list.length && list.length > 1; i++) {
29715
- let a = list[i];
29716
- let b = list[(i + 1) % list.length];
29717
- let gap = i + 1 < list.length ? b.angle - a.angle : b.angle + 2 * Math.PI - a.angle;
29718
- if (gap > 1e-9) r = Math.max(r, (a.diag / 2 + b.diag / 2 + o.nodesep) / gap);
29792
+ let band = 0;
29793
+ for (let n of members) {
29794
+ r = Math.max(r, radius[ring - 1] + (n.parent_ext + n.ext) / 2 + o.nodesep);
29795
+ band = Math.max(band, n.ext);
29796
+ }
29797
+ r = fit(members, r);
29798
+ for (let pass = 0; pass < 2; pass++) for (let g of reaching) {
29799
+ if (g.reach < r - band / 2 - o.nodesep) continue;
29800
+ for (let m of members) {
29801
+ let d = circ(g.angle, m.angle);
29802
+ if (d > g.half + 1e-9) r = Math.max(r, (m.diag / 2 + o.nodesep) / (d - g.half));
29803
+ else r = Math.max(r, g.reach + m.ext / 2 + o.nodesep);
29804
+ }
29719
29805
  }
29720
29806
  radius[ring] = r;
29807
+ let sorted = members.slice().sort((a, b) => a.angle - b.angle);
29808
+ for (let i = 0; i < sorted.length; i++) {
29809
+ let m = sorted[i];
29810
+ let st = stacks.get(m.id);
29811
+ if (!st) continue;
29812
+ let room = m.span / 2;
29813
+ if (sorted.length > 1) {
29814
+ let left = sorted[(i - 1 + sorted.length) % sorted.length];
29815
+ let right = sorted[(i + 1) % sorted.length];
29816
+ room = Math.min(room, circ(m.angle, left.angle) - (left.diag / 2 + o.nodesep) / r, circ(m.angle, right.angle) - (right.diag / 2 + o.nodesep) / r);
29817
+ }
29818
+ room = Math.min(room, Math.PI);
29819
+ let across = 0;
29820
+ let along = 0;
29821
+ for (let k = 0; k <= 16; k++) {
29822
+ let th = m.angle - room + 2 * room * k / 16;
29823
+ for (let c of st.cards) {
29824
+ across = Math.max(across, extent_at(c, th + Math.PI / 2));
29825
+ along = Math.max(along, extent_at(c, th));
29826
+ }
29827
+ }
29828
+ let rows = [];
29829
+ let left_to_place = st.ids.length;
29830
+ let rr = r;
29831
+ let half = 0;
29832
+ while (left_to_place > 0) {
29833
+ let fits = Math.floor(2 * room * rr / (across + o.nodesep));
29834
+ let cnt = Math.max(1, Math.min(left_to_place, fits));
29835
+ rows.push({
29836
+ rr,
29837
+ cnt
29838
+ });
29839
+ half = Math.max(half, (cnt * (across + o.nodesep) - o.nodesep) / 2 / rr);
29840
+ left_to_place -= cnt;
29841
+ rr += along + 40;
29842
+ }
29843
+ st.plan = {
29844
+ angle: m.angle,
29845
+ across,
29846
+ rows
29847
+ };
29848
+ reaching.push({
29849
+ angle: m.angle,
29850
+ half,
29851
+ reach: rows[rows.length - 1].rr + along / 2
29852
+ });
29853
+ }
29721
29854
  }
29722
29855
  for (let [id, a] of angle) {
29723
- let r = radius[ring_of(id)] || 0;
29724
- pos.set(id, {
29725
- x: r * Math.cos(a),
29726
- y: r * Math.sin(a)
29727
- });
29856
+ let st = stacks.get(id);
29857
+ if (!st) {
29858
+ let r0 = radius[ring_of(id)] || 0;
29859
+ pos.set(id, {
29860
+ x: r0 * Math.cos(a),
29861
+ y: r0 * Math.sin(a)
29862
+ });
29863
+ continue;
29864
+ }
29865
+ let i = 0;
29866
+ for (let row of st.plan.rows) {
29867
+ let step = (st.plan.across + o.nodesep) / row.rr;
29868
+ for (let j = 0; j < row.cnt; j++) {
29869
+ let th = a + (j - (row.cnt - 1) / 2) * step;
29870
+ pos.set(st.ids[i], {
29871
+ x: row.rr * Math.cos(th),
29872
+ y: row.rr * Math.sin(th)
29873
+ });
29874
+ i++;
29875
+ }
29876
+ }
29728
29877
  }
29729
29878
  return pos;
29730
29879
  }
@@ -30168,6 +30317,112 @@ function elbow_route(s, t, box_s, box_t, lane, vertical, boxes, stagger) {
30168
30317
  if (!route && near.length < others.length) route = orth_search(a, z, others.map((b) => box_expand(b, m)));
30169
30318
  return route || simple;
30170
30319
  }
30320
+ function path_points(path) {
30321
+ let pts = [];
30322
+ let cur = null;
30323
+ for (let c of path) if (c[0] === "M" || c[0] === "L") {
30324
+ cur = [c[1], c[2]];
30325
+ pts.push(cur);
30326
+ } else if (c[0] === "C" && cur) {
30327
+ let [x0, y0] = cur;
30328
+ for (let k = 1; k <= 16; k++) {
30329
+ let u = k / 16;
30330
+ let v = 1 - u;
30331
+ pts.push([v * v * v * x0 + 3 * v * v * u * c[1] + 3 * v * u * u * c[3] + u * u * u * c[5], v * v * v * y0 + 3 * v * v * u * c[2] + 3 * v * u * u * c[4] + u * u * u * c[6]]);
30332
+ }
30333
+ cur = [c[5], c[6]];
30334
+ } else if (c[0] === "Q" && cur) {
30335
+ let [x0, y0] = cur;
30336
+ for (let k = 1; k <= 16; k++) {
30337
+ let u = k / 16;
30338
+ let v = 1 - u;
30339
+ pts.push([v * v * x0 + 2 * v * u * c[1] + u * u * c[3], v * v * y0 + 2 * v * u * c[2] + u * u * c[4]]);
30340
+ }
30341
+ cur = [c[3], c[4]];
30342
+ }
30343
+ return pts;
30344
+ }
30345
+ /************************************************************
30346
+ * Does the G6 path `path` of a curved edge cross a card other than
30347
+ * its own two? Measured on the curve itself -- the path G6 would
30348
+ * draw, sampled -- and not on the rectangle round it, which took
30349
+ * every card the curve merely passed near: the ports of a row
30350
+ * stick well into the space above it. Its own two cards are left
30351
+ * out: the curve starts and ends on their ports.
30352
+ ************************************************************/
30353
+ function curve_hits(path, boxes, box_s, box_t) {
30354
+ let pts = path_points(path);
30355
+ if (pts.length < 2) return false;
30356
+ let bb = {
30357
+ x1: Infinity,
30358
+ y1: Infinity,
30359
+ x2: -Infinity,
30360
+ y2: -Infinity
30361
+ };
30362
+ for (let p of pts) {
30363
+ bb.x1 = Math.min(bb.x1, p[0]);
30364
+ bb.y1 = Math.min(bb.y1, p[1]);
30365
+ bb.x2 = Math.max(bb.x2, p[0]);
30366
+ bb.y2 = Math.max(bb.y2, p[1]);
30367
+ }
30368
+ for (let b of boxes || []) {
30369
+ if (same_box(b, box_s) || same_box(b, box_t) || !box_overlaps(b, box_expand(bb, 1))) continue;
30370
+ let inner = box_expand(b, -1);
30371
+ for (let k = 0; k + 1 < pts.length; k++) if (segment_hits(pts[k], pts[k + 1], inner)) return true;
30372
+ }
30373
+ return false;
30374
+ }
30375
+ /************************************************************
30376
+ * A G6 path (['M'|'L'|'Q', ...]) along `points` with every corner
30377
+ * rounded -- by `radius`, or by half the shorter of its two
30378
+ * segments, so a short run is never overshot. The rounding is the
30379
+ * quadratic G6's own polyline uses.
30380
+ ************************************************************/
30381
+ function rounded_path(points, radius) {
30382
+ let path = [[
30383
+ "M",
30384
+ points[0][0],
30385
+ points[0][1]
30386
+ ]];
30387
+ for (let i = 1; i + 1 < points.length; i++) {
30388
+ let a = points[i - 1];
30389
+ let m = points[i];
30390
+ let b = points[i + 1];
30391
+ let len_in = Math.hypot(m[0] - a[0], m[1] - a[1]);
30392
+ let len_out = Math.hypot(b[0] - m[0], b[1] - m[1]);
30393
+ let r = Math.min(radius, len_in / 2, len_out / 2);
30394
+ let collinear = Math.abs((m[0] - a[0]) * (b[1] - m[1]) - (m[1] - a[1]) * (b[0] - m[0])) < 1e-9;
30395
+ if (r <= 0 || collinear) {
30396
+ path.push([
30397
+ "L",
30398
+ m[0],
30399
+ m[1]
30400
+ ]);
30401
+ continue;
30402
+ }
30403
+ let p1 = [m[0] - (m[0] - a[0]) / len_in * r, m[1] - (m[1] - a[1]) / len_in * r];
30404
+ let p2 = [m[0] + (b[0] - m[0]) / len_out * r, m[1] + (b[1] - m[1]) / len_out * r];
30405
+ path.push([
30406
+ "L",
30407
+ p1[0],
30408
+ p1[1]
30409
+ ]);
30410
+ path.push([
30411
+ "Q",
30412
+ m[0],
30413
+ m[1],
30414
+ p2[0],
30415
+ p2[1]
30416
+ ]);
30417
+ }
30418
+ let last = points[points.length - 1];
30419
+ path.push([
30420
+ "L",
30421
+ last[0],
30422
+ last[1]
30423
+ ]);
30424
+ return path;
30425
+ }
30171
30426
  //#endregion
30172
30427
  //#region node_modules/@babel/runtime/helpers/esm/typeof.js
30173
30428
  function _typeof(o) {
@@ -55055,7 +55310,7 @@ Easing Functions from anime.js, they are tried and true, so, its better to use t
55055
55310
  var Quad = function Quad(t) {
55056
55311
  return Math.pow(t, 2);
55057
55312
  };
55058
- var Cubic = function Cubic(t) {
55313
+ var Cubic$1 = function Cubic(t) {
55059
55314
  return Math.pow(t, 3);
55060
55315
  };
55061
55316
  var Quart = function Quart(t) {
@@ -55192,10 +55447,10 @@ var EasingFunctions = {
55192
55447
  "out-quad": EaseOut(Quad),
55193
55448
  "in-out-quad": EaseInOut(Quad),
55194
55449
  "out-in-quad": EaseOutIn(Quad),
55195
- "in-cubic": Cubic,
55196
- "out-cubic": EaseOut(Cubic),
55197
- "in-out-cubic": EaseInOut(Cubic),
55198
- "out-in-cubic": EaseOutIn(Cubic),
55450
+ "in-cubic": Cubic$1,
55451
+ "out-cubic": EaseOut(Cubic$1),
55452
+ "in-out-cubic": EaseInOut(Cubic$1),
55453
+ "out-in-cubic": EaseOutIn(Cubic$1),
55199
55454
  "in-quart": Quart,
55200
55455
  "out-quart": EaseOut(Quart),
55201
55456
  "in-out-quart": EaseInOut(Quart),
@@ -57368,6 +57623,8 @@ function register_layouts(gobj) {
57368
57623
  (0, _antv_g6.register)(_antv_g6.ExtensionCategory.LAYOUT, "treedb-compact", TreedbCompactLayout);
57369
57624
  (0, _antv_g6.register)(_antv_g6.ExtensionCategory.EDGE, "treedb-elbow-v", TreedbElbowV);
57370
57625
  (0, _antv_g6.register)(_antv_g6.ExtensionCategory.EDGE, "treedb-elbow-h", TreedbElbowH);
57626
+ (0, _antv_g6.register)(_antv_g6.ExtensionCategory.EDGE, "treedb-curve-v", TreedbCurveV);
57627
+ (0, _antv_g6.register)(_antv_g6.ExtensionCategory.EDGE, "treedb-curve-h", TreedbCurveH);
57371
57628
  (0, _antv_g6.register)(_antv_g6.ExtensionCategory.LAYOUT, "treedb-radial", TreedbRadialLayout);
57372
57629
  (0, _antv_g6.register)(_antv_g6.ExtensionCategory.NODE, "light", LightNode);
57373
57630
  (0, _antv_g6.register)(_antv_g6.ExtensionCategory.NODE, "treedb-card", TreedbCard);
@@ -58062,7 +58319,9 @@ function layout_direction(gobj) {
58062
58319
  function edge_type_for(gobj) {
58063
58320
  let lr = layout_direction(gobj) === "LR";
58064
58321
  let rowless = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "rowless_layouts") || [];
58065
- if ((0, _yuneta_gobj_js.gobj_read_str_attr)(gobj, "edge_shape") === "elbow" && !(0, _yuneta_gobj_js.str_in_list)(rowless, gobj.priv.layout)) return lr ? "treedb-elbow-h" : "treedb-elbow-v";
58322
+ let rows = !(0, _yuneta_gobj_js.str_in_list)(rowless, gobj.priv.layout);
58323
+ if (rows && (0, _yuneta_gobj_js.gobj_read_str_attr)(gobj, "edge_shape") === "elbow") return lr ? "treedb-elbow-h" : "treedb-elbow-v";
58324
+ if (rows) return lr ? "treedb-curve-h" : "treedb-curve-v";
58066
58325
  return lr ? "cubic-horizontal" : "cubic";
58067
58326
  }
58068
58327
  /************************************************************
@@ -59666,6 +59925,40 @@ var TreedbElbowH = class extends _antv_g6.Polyline {
59666
59925
  return super.getKeyPath(Object.assign({}, attributes, { radius: attributes.radius || ELBOW_RADIUS }));
59667
59926
  }
59668
59927
  };
59928
+ /************************************************************
59929
+ * A CURVED edge that keeps off the cards. G6's cubic, as before,
59930
+ * unless that very curve -- sampled, not guessed from the
59931
+ * rectangle round it -- would cross a card other than its own two,
59932
+ * or when it does not run forward and so would cross its own:
59933
+ * the card above a lower row of a stack, a row between a parent
59934
+ * and a far child. Then it goes the way an elbow would (the comb,
59935
+ * the detour, the route: the same lanes and staggered turns) with
59936
+ * round corners, so it still reads as a curve. `-v` for rows
59937
+ * stacked top to bottom, `-h` for columns.
59938
+ ************************************************************/
59939
+ function curve_key_path(edge, attributes, vertical, plain) {
59940
+ let [s, t] = edge.getEndpoints(attributes, false);
59941
+ let along = vertical ? 1 : 0;
59942
+ let box_s = elbow_box(edge.sourceNode);
59943
+ let box_t = elbow_box(edge.targetNode);
59944
+ let boxes = elbow_obstacles(edge);
59945
+ if (t[along] - s[along] > 20 && !curve_hits(plain, boxes, box_s, box_t)) return plain;
59946
+ return rounded_path([
59947
+ s,
59948
+ ...elbow_route(s, t, box_s, box_t, elbow_lane_of(edge), vertical, boxes, elbow_stagger_of(edge, vertical)),
59949
+ t
59950
+ ], 24);
59951
+ }
59952
+ var TreedbCurveV = class extends _antv_g6.Cubic {
59953
+ getKeyPath(attributes) {
59954
+ return curve_key_path(this, attributes, true, super.getKeyPath(attributes));
59955
+ }
59956
+ };
59957
+ var TreedbCurveH = class extends _antv_g6.CubicHorizontal {
59958
+ getKeyPath(attributes) {
59959
+ return curve_key_path(this, attributes, false, super.getKeyPath(attributes));
59960
+ }
59961
+ };
59669
59962
  var TreedbCompactLayout = class extends _antv_g6.BaseLayout {
59670
59963
  async execute(data, options) {
59671
59964
  let input = treedb_layout_input(data);