@antv/layout 2.0.0-alpha.2 → 2.0.0-alpha.4

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.
Files changed (38) hide show
  1. package/dist/index.js +1207 -1247
  2. package/dist/index.js.map +1 -1
  3. package/dist/index.min.js +2 -2
  4. package/dist/index.min.js.map +1 -1
  5. package/dist/worker.js +1 -1
  6. package/dist/worker.js.map +1 -1
  7. package/lib/algorithm/antv-dagre/index.js +10 -8
  8. package/lib/algorithm/antv-dagre/index.js.map +1 -1
  9. package/lib/algorithm/antv-dagre/types.d.ts +25 -3
  10. package/lib/algorithm/base-layout.d.ts +1 -0
  11. package/lib/algorithm/base-layout.js +5 -3
  12. package/lib/algorithm/base-layout.js.map +1 -1
  13. package/lib/algorithm/circular/index.js +2 -2
  14. package/lib/algorithm/circular/index.js.map +1 -1
  15. package/lib/algorithm/combo-combined/index.js +4 -4
  16. package/lib/algorithm/combo-combined/index.js.map +1 -1
  17. package/lib/algorithm/d3-force/index.d.ts +2 -2
  18. package/lib/algorithm/d3-force/index.js +60 -104
  19. package/lib/algorithm/d3-force/index.js.map +1 -1
  20. package/lib/index.d.ts +1 -1
  21. package/lib/index.js +1 -1
  22. package/lib/util/object.d.ts +1 -2
  23. package/lib/util/object.js +1 -4
  24. package/lib/util/object.js.map +1 -1
  25. package/lib/util/order.d.ts +1 -1
  26. package/lib/util/order.js +4 -1
  27. package/lib/util/order.js.map +1 -1
  28. package/lib/worker.js +768 -807
  29. package/lib/worker.js.map +1 -1
  30. package/package.json +1 -1
  31. package/src/algorithm/antv-dagre/index.ts +11 -12
  32. package/src/algorithm/antv-dagre/types.ts +25 -3
  33. package/src/algorithm/base-layout.ts +13 -8
  34. package/src/algorithm/circular/index.ts +2 -2
  35. package/src/algorithm/combo-combined/index.ts +5 -5
  36. package/src/algorithm/d3-force/index.ts +69 -122
  37. package/src/util/object.ts +0 -4
  38. package/src/util/order.ts +4 -0
package/dist/index.js CHANGED
@@ -357,1195 +357,1260 @@
357
357
  return result;
358
358
  });
359
359
 
360
- class GraphLib {
361
- constructor(data, options = {}) {
362
- this.edgeIdCounter = new Map();
363
- this.nodeMap = extractNodeData(data.nodes, options.node);
364
- this.edgeMap = extractEdgeData(data.edges || [], options.edge, this.getEdgeId.bind(this));
365
- }
366
- data() {
367
- return { nodes: this.nodeMap, edges: this.edgeMap };
368
- }
369
- replace(result) {
370
- this.nodeMap = result.nodes;
371
- this.edgeMap = result.edges;
372
- this.clearCache();
373
- }
374
- nodes() {
375
- return Array.from(this.nodeMap.values());
376
- }
377
- node(id) {
378
- return this.nodeMap.get(id);
379
- }
380
- nodeAt(index) {
381
- if (!this.indexNodeCache) {
382
- this.buildNodeIndexCache();
383
- }
384
- const nodeId = this.indexNodeCache.get(index);
385
- return nodeId ? this.nodeMap.get(nodeId) : undefined;
386
- }
387
- nodeIndexOf(id) {
388
- var _a;
389
- if (!this.nodeIndexCache) {
390
- this.buildNodeIndexCache();
391
- }
392
- return (_a = this.nodeIndexCache.get(id)) !== null && _a !== void 0 ? _a : -1;
393
- }
394
- firstNode() {
395
- return this.nodeMap.values().next().value;
396
- }
397
- forEachNode(callback) {
398
- let i = 0;
399
- this.nodeMap.forEach((node) => callback(node, i++));
400
- }
401
- originalNode(id) {
402
- const node = this.nodeMap.get(id);
403
- return node === null || node === void 0 ? void 0 : node._original;
404
- }
405
- nodeCount() {
406
- return this.nodeMap.size;
407
- }
408
- edges() {
409
- return Array.from(this.edgeMap.values());
410
- }
411
- edge(id) {
412
- return this.edgeMap.get(id);
413
- }
414
- firstEdge() {
415
- return this.edgeMap.values().next().value;
416
- }
417
- forEachEdge(callback) {
418
- let i = 0;
419
- this.edgeMap.forEach((edge) => callback(edge, i++));
420
- }
421
- originalEdge(id) {
422
- const edge = this.edgeMap.get(id);
423
- return edge === null || edge === void 0 ? void 0 : edge._original;
424
- }
425
- edgeCount() {
426
- return this.edgeMap.size;
427
- }
428
- getEdgeId(edge) {
429
- if (edge.id)
430
- return edge.id;
431
- const baseId = `${edge.source}-${edge.target}`;
432
- const count = this.edgeIdCounter.get(baseId) || 0;
433
- const id = count === 0 ? baseId : `${baseId}-${count}`;
434
- this.edgeIdCounter.set(baseId, count + 1);
435
- return id;
436
- }
437
- degree(nodeId, direction = 'both') {
438
- if (!this.degreeCache) {
439
- this.buildDegreeCache();
440
- }
441
- const degree = this.degreeCache.get(nodeId);
442
- if (!degree)
443
- return 0;
444
- return degree[direction];
445
- }
446
- neighbors(nodeId, direction = 'both') {
447
- if (!this.outAdjacencyCache || !this.inAdjacencyCache) {
448
- this.buildAdjacencyCache();
449
- }
450
- if (direction === 'out') {
451
- return Array.from(this.outAdjacencyCache.get(nodeId) || []);
452
- }
453
- if (direction === 'in') {
454
- return Array.from(this.inAdjacencyCache.get(nodeId) || []);
455
- }
456
- if (this.bothAdjacencyCache) {
457
- return Array.from(this.bothAdjacencyCache.get(nodeId) || []);
458
- }
459
- const inSet = this.inAdjacencyCache.get(nodeId);
460
- const outSet = this.outAdjacencyCache.get(nodeId);
461
- if (!inSet && !outSet)
462
- return [];
463
- if (!inSet)
464
- return Array.from(outSet);
465
- if (!outSet)
466
- return Array.from(inSet);
467
- const merged = new Set();
468
- inSet.forEach((id) => merged.add(id));
469
- outSet.forEach((id) => merged.add(id));
470
- return Array.from(merged);
471
- }
472
- successors(nodeId) {
473
- return this.neighbors(nodeId, 'out');
474
- }
475
- predecessors(nodeId) {
476
- return this.neighbors(nodeId, 'in');
477
- }
478
- setNodeOrder(nodes) {
479
- const next = new Map();
480
- for (const node of nodes)
481
- next.set(node.id, node);
482
- this.nodeMap = next;
483
- this.nodeIndexCache = undefined;
484
- this.indexNodeCache = undefined;
485
- }
486
- clearCache() {
487
- this.degreeCache = undefined;
488
- this.inAdjacencyCache = undefined;
489
- this.outAdjacencyCache = undefined;
490
- this.bothAdjacencyCache = undefined;
491
- this.nodeIndexCache = undefined;
492
- this.indexNodeCache = undefined;
493
- }
494
- buildDegreeCache() {
495
- this.degreeCache = new Map();
496
- for (const edge of this.edges()) {
497
- const { source, target } = edge;
498
- if (edge.source === edge.target)
499
- continue;
500
- if (!this.degreeCache.has(source)) {
501
- this.degreeCache.set(source, { in: 0, out: 0, both: 0 });
502
- }
503
- const sourceDeg = this.degreeCache.get(edge.source);
504
- if (sourceDeg) {
505
- sourceDeg.out++;
506
- sourceDeg.both++;
507
- }
508
- if (!this.degreeCache.has(target)) {
509
- this.degreeCache.set(target, { in: 0, out: 0, both: 0 });
510
- }
511
- const targetDeg = this.degreeCache.get(edge.target);
512
- if (targetDeg) {
513
- targetDeg.in++;
514
- targetDeg.both++;
515
- }
516
- }
517
- }
518
- buildAdjacencyCache() {
519
- this.inAdjacencyCache = new Map();
520
- this.outAdjacencyCache = new Map();
521
- for (const edge of this.edges()) {
522
- if (!this.nodeMap.has(edge.source) || !this.nodeMap.has(edge.target))
523
- continue;
524
- if (!this.outAdjacencyCache.has(edge.source)) {
525
- this.outAdjacencyCache.set(edge.source, new Set());
526
- }
527
- this.outAdjacencyCache.get(edge.source).add(edge.target);
528
- if (!this.inAdjacencyCache.has(edge.target)) {
529
- this.inAdjacencyCache.set(edge.target, new Set());
530
- }
531
- this.inAdjacencyCache.get(edge.target).add(edge.source);
360
+ const isArray = Array.isArray;
361
+
362
+ /**
363
+ * Return the layout result for a graph with zero or one node.
364
+ * @param graph original graph
365
+ * @param center the layout center
366
+ * @returns layout result
367
+ */
368
+ function applySingleNodeLayout(model, center, dimensions = 2) {
369
+ const n = model.nodeCount();
370
+ if (n === 1) {
371
+ const first = model.firstNode();
372
+ first.x = center[0];
373
+ first.y = center[1];
374
+ if (dimensions === 3) {
375
+ first.z = center[2] || 0;
532
376
  }
533
377
  }
534
- buildNodeIndexCache() {
535
- this.nodeIndexCache = new Map();
536
- this.indexNodeCache = new Map();
537
- let index = 0;
538
- this.nodeMap.forEach((_node, nodeId) => {
539
- this.nodeIndexCache.set(nodeId, index);
540
- this.indexNodeCache.set(index, nodeId);
541
- index++;
542
- });
543
- }
544
- destroy() {
545
- this.clearCache();
546
- this.nodeMap.clear();
547
- this.edgeMap.clear();
548
- this.edgeIdCounter.clear();
549
- }
550
378
  }
551
- const nodeFields = [
552
- 'id',
553
- 'x',
554
- 'y',
555
- 'z',
556
- 'vx',
557
- 'vy',
558
- 'vz',
559
- 'fx',
560
- 'fy',
561
- 'fz',
562
- 'parentId',
563
- ];
564
- const edgeFields = ['id', 'source', 'target', 'points'];
565
- function extractNodeData(nodes, node) {
566
- if (!nodes) {
567
- throw new Error('Data.nodes is required');
568
- }
569
- const result = new Map();
570
- for (const datum of nodes) {
571
- const nodeData = { _original: datum };
572
- for (const field of nodeFields) {
573
- const value = datum[field];
574
- if (isNil(value))
575
- continue;
576
- nodeData[field] = value;
577
- }
578
- if (node) {
579
- const customFields = node(datum);
580
- for (const key in customFields) {
581
- const value = customFields[key];
582
- if (isNil(value))
583
- continue;
584
- nodeData[key] = value;
585
- }
586
- }
587
- if (isNil(nodeData.id)) {
588
- throw new Error(`Node is missing id field`);
379
+
380
+ /**
381
+ * Floyd-Warshall algorithm to find shortest paths (but with no negative cycles).
382
+ */
383
+ const floydWarshall = (adjMatrix) => {
384
+ // initialize
385
+ const n = adjMatrix.length;
386
+ const dist = Array.from({ length: n }, () => new Array(n));
387
+ for (let i = 0; i < n; i++) {
388
+ const row = adjMatrix[i];
389
+ const drow = dist[i];
390
+ for (let j = 0; j < n; j++) {
391
+ drow[j] = i === j ? 0 : row[j] > 0 ? row[j] : Infinity;
589
392
  }
590
- result.set(nodeData.id, nodeData);
591
393
  }
592
- return result;
593
- }
594
- function extractEdgeData(edges, edge, getEdgeId) {
595
- const result = new Map();
596
- for (const datum of edges) {
597
- const edgeData = { _original: datum };
598
- for (const field of edgeFields) {
599
- const value = datum[field];
600
- if (isNil(value))
394
+ // floyd
395
+ for (let k = 0; k < n; k++) {
396
+ const dk = dist[k];
397
+ for (let i = 0; i < n; i++) {
398
+ const di = dist[i];
399
+ const dik = di[k];
400
+ if (dik === Infinity)
601
401
  continue;
602
- edgeData[field] = value;
603
- }
604
- if (edge) {
605
- const customFields = edge(datum);
606
- for (const key in customFields) {
607
- const value = customFields[key];
608
- if (isNil(value))
402
+ for (let j = 0; j < n; j++) {
403
+ const dkj = dk[j];
404
+ if (dkj === Infinity)
609
405
  continue;
610
- edgeData[key] = value;
406
+ const next = dik + dkj;
407
+ if (next < di[j]) {
408
+ di[j] = next;
409
+ }
611
410
  }
612
411
  }
613
- if (isNil(edgeData.source) || isNil(edgeData.target)) {
614
- throw new Error(`Edge is missing source or target field`);
615
- }
616
- if (isNil(edgeData.id)) {
617
- edgeData.id = getEdgeId === null || getEdgeId === void 0 ? void 0 : getEdgeId(datum);
618
- }
619
- result.set(edgeData.id, edgeData);
620
412
  }
621
- return result;
622
- }
623
- function initNodePosition(model, width, height, dimensions = 2) {
413
+ return dist;
414
+ };
415
+ /**
416
+ * Get the adjacency matrix of the graph model.
417
+ */
418
+ const getAdjMatrix = (model, directed) => {
419
+ const n = model.nodeCount();
420
+ const matrix = Array.from({ length: n }, () => new Array(n));
421
+ // map node with index in data.nodes
422
+ const nodeMap = {};
423
+ let i = 0;
624
424
  model.forEachNode((node) => {
625
- if (isNil(node.x)) {
626
- node.x = Math.random() * width;
627
- }
628
- if (isNil(node.y)) {
629
- node.y = Math.random() * height;
630
- }
631
- if (dimensions === 3 && isNil(node.z)) {
632
- node.z = Math.random() * Math.min(width, height);
425
+ nodeMap[node.id] = i++;
426
+ });
427
+ model.forEachEdge((e) => {
428
+ const sIndex = nodeMap[e.source];
429
+ const tIndex = nodeMap[e.target];
430
+ if (sIndex === undefined || tIndex === undefined)
431
+ return;
432
+ matrix[sIndex][tIndex] = 1;
433
+ if (!directed) {
434
+ matrix[tIndex][sIndex] = 1;
633
435
  }
634
436
  });
635
- }
636
-
637
- class RuntimeContext {
638
- constructor(data, options = {}) {
639
- this.graph = new GraphLib(data, options);
640
- }
641
- export() {
642
- return this.graph.data();
643
- }
644
- replace(result) {
645
- this.graph.replace(result);
646
- }
647
- forEachNode(callback) {
648
- this.graph.forEachNode(callback);
649
- }
650
- forEachEdge(callback) {
651
- this.graph.forEachEdge((edge, i) => {
652
- edge.sourceNode = this.graph.node(edge.source);
653
- edge.targetNode = this.graph.node(edge.target);
654
- callback(edge, i);
655
- });
656
- }
657
- destroy() {
658
- this.graph.destroy();
659
- }
660
- }
661
-
437
+ return matrix;
438
+ };
662
439
  /**
663
- * @license
664
- * Copyright 2019 Google LLC
665
- * SPDX-License-Identifier: Apache-2.0
440
+ * Get the adjacency list of the graph model.
666
441
  */
667
- const proxyMarker = Symbol("Comlink.proxy");
668
- const createEndpoint = Symbol("Comlink.endpoint");
669
- const releaseProxy = Symbol("Comlink.releaseProxy");
670
- const finalizer = Symbol("Comlink.finalizer");
671
- const throwMarker = Symbol("Comlink.thrown");
672
- const isObject = (val) => (typeof val === "object" && val !== null) || typeof val === "function";
442
+ const getAdjList = (model, directed) => {
443
+ const n = model.nodeCount();
444
+ const adjList = Array.from({ length: n }, () => []);
445
+ // map node with index
446
+ const nodeMap = {};
447
+ let idx = 0;
448
+ model.forEachNode((node) => {
449
+ nodeMap[node.id] = idx++;
450
+ });
451
+ model.forEachEdge((e) => {
452
+ const s = nodeMap[e.source];
453
+ const t = nodeMap[e.target];
454
+ if (s == null || t == null)
455
+ return;
456
+ adjList[s].push(t);
457
+ if (!directed)
458
+ adjList[t].push(s);
459
+ });
460
+ return adjList;
461
+ };
673
462
  /**
674
- * Internal transfer handle to handle objects marked to proxy.
463
+ * scale matrix
464
+ * @param matrix [ [], [], [] ]
465
+ * @param ratio
675
466
  */
676
- const proxyTransferHandler = {
677
- canHandle: (val) => isObject(val) && val[proxyMarker],
678
- serialize(obj) {
679
- const { port1, port2 } = new MessageChannel();
680
- expose(obj, port1);
681
- return [port2, [port2]];
682
- },
683
- deserialize(port) {
684
- port.start();
685
- return wrap(port);
686
- },
467
+ const scaleMatrix = (matrix, ratio) => {
468
+ const n = matrix.length;
469
+ const result = new Array(n);
470
+ for (let i = 0; i < n; i++) {
471
+ const row = matrix[i];
472
+ const m = row.length;
473
+ const newRow = new Array(m);
474
+ for (let j = 0; j < m; j++) {
475
+ newRow[j] = row[j] * ratio;
476
+ }
477
+ result[i] = newRow;
478
+ }
479
+ return result;
687
480
  };
688
481
  /**
689
- * Internal transfer handler to handle thrown exceptions.
482
+ * calculate the bounding box for the nodes according to their x, y, and size
483
+ * @param nodes nodes in the layout
484
+ * @returns
690
485
  */
691
- const throwTransferHandler = {
692
- canHandle: (value) => isObject(value) && throwMarker in value,
693
- serialize({ value }) {
694
- let serialized;
695
- if (value instanceof Error) {
696
- serialized = {
697
- isError: true,
698
- value: {
699
- message: value.message,
700
- name: value.name,
701
- stack: value.stack,
702
- },
703
- };
486
+ const getLayoutBBox = (nodes) => {
487
+ let minX = Infinity;
488
+ let minY = Infinity;
489
+ let maxX = -Infinity;
490
+ let maxY = -Infinity;
491
+ nodes.forEach((node) => {
492
+ let size = node.data.size;
493
+ if (isArray(size)) {
494
+ if (size.length === 1)
495
+ size = [size[0], size[0]];
704
496
  }
705
- else {
706
- serialized = { isError: false, value };
497
+ else if (size === undefined || isNaN(size)) {
498
+ size = [30, 30];
707
499
  }
708
- return [serialized, []];
709
- },
710
- deserialize(serialized) {
711
- if (serialized.isError) {
712
- throw Object.assign(new Error(serialized.value.message), serialized.value);
500
+ else if (isNumber(size)) {
501
+ size = [size, size];
713
502
  }
714
- throw serialized.value;
715
- },
503
+ const halfSize = [size[0] / 2, size[1] / 2];
504
+ const left = node.data.x - halfSize[0];
505
+ const right = node.data.x + halfSize[0];
506
+ const top = node.data.y - halfSize[1];
507
+ const bottom = node.data.y + halfSize[1];
508
+ if (minX > left)
509
+ minX = left;
510
+ if (minY > top)
511
+ minY = top;
512
+ if (maxX < right)
513
+ maxX = right;
514
+ if (maxY < bottom)
515
+ maxY = bottom;
516
+ });
517
+ return { minX, minY, maxX, maxY };
716
518
  };
717
519
  /**
718
- * Allows customizing the serialization of certain values.
520
+ * calculate the euclidean distance form p1 to p2
521
+ * @param p1
522
+ * @param p2
523
+ * @returns
524
+ */
525
+ const getEuclideanDistance = (p1, p2) => Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
526
+ /**
527
+ * Depth first search begin from nodes in graphCore data.
528
+ * @param graphCore graphlib data structure
529
+ * @param nodes begin nodes
530
+ * @param fn will be called while visiting each node
531
+ * @param mode 'TB' - visit from top to bottom; 'BT' - visit from bottom to top;
532
+ * @returns
533
+ */
534
+ const graphTreeDfs = (graph, nodes, fn, mode = 'TB', treeKey, stopFns = {}) => {
535
+ if (!(nodes === null || nodes === void 0 ? void 0 : nodes.length))
536
+ return;
537
+ const { stopBranchFn, stopAllFn } = stopFns;
538
+ for (let i = 0; i < nodes.length; i++) {
539
+ const node = nodes[i];
540
+ if (!graph.hasNode(node.id))
541
+ continue;
542
+ if (stopBranchFn === null || stopBranchFn === void 0 ? void 0 : stopBranchFn(node))
543
+ continue; // Stop this branch
544
+ if (stopAllFn === null || stopAllFn === void 0 ? void 0 : stopAllFn(node))
545
+ return; // Stop all
546
+ if (mode === 'TB')
547
+ fn(node); // Traverse from top to bottom
548
+ graphTreeDfs(graph, graph.getChildren(node.id, treeKey), fn, mode, treeKey, stopFns);
549
+ if (mode !== 'TB')
550
+ fn(node); // Traverse from bottom to top
551
+ }
552
+ };
553
+ /**
554
+ * Use Johnson + Dijkstra to compute APSP for sparse graph.
555
+ * Fully compatible with floydWarshall(adjMatrix).
556
+ */
557
+ function johnson(adjList) {
558
+ const n = adjList.length;
559
+ // Step 1: add a dummy node q connected to all nodes with weight 0
560
+ new Array(n).fill(0);
561
+ // Bellman-Ford to compute potentials h(v)
562
+ // 因为权重全是 1,无负边,可直接跳过 BF,h 全 0 即可
563
+ // Step 2: reweight edges
564
+ // 因为 h(u)=h(v)=0,reweight 后仍然是 1,省略 reweight 过程
565
+ // Step 3: run Dijkstra from each node
566
+ const distAll = Array.from({ length: n }, () => new Array(n).fill(Infinity));
567
+ for (let s = 0; s < n; s++) {
568
+ distAll[s] = dijkstra(adjList, s);
569
+ }
570
+ return distAll;
571
+ }
572
+ /**
573
+ * Dijkstra algorithm to find shortest paths from source to all nodes.
719
574
  */
720
- const transferHandlers = new Map([
721
- ["proxy", proxyTransferHandler],
722
- ["throw", throwTransferHandler],
723
- ]);
724
- function isAllowedOrigin(allowedOrigins, origin) {
725
- for (const allowedOrigin of allowedOrigins) {
726
- if (origin === allowedOrigin || allowedOrigin === "*") {
727
- return true;
728
- }
729
- if (allowedOrigin instanceof RegExp && allowedOrigin.test(origin)) {
730
- return true;
575
+ function dijkstra(adjList, source) {
576
+ const n = adjList.length;
577
+ const dist = new Array(n).fill(Infinity);
578
+ dist[source] = 0;
579
+ // Minimal binary heap
580
+ const heap = new MinHeap();
581
+ heap.push([0, source]); // [distance, node]
582
+ while (!heap.empty()) {
583
+ const [d, u] = heap.pop();
584
+ if (d !== dist[u])
585
+ continue;
586
+ const neighbors = adjList[u];
587
+ for (let i = 0; i < neighbors.length; i++) {
588
+ const v = neighbors[i];
589
+ const nd = d + 1;
590
+ if (nd < dist[v]) {
591
+ dist[v] = nd;
592
+ heap.push([nd, v]);
593
+ }
731
594
  }
732
595
  }
733
- return false;
596
+ return dist;
734
597
  }
735
- function expose(obj, ep = globalThis, allowedOrigins = ["*"]) {
736
- ep.addEventListener("message", function callback(ev) {
737
- if (!ev || !ev.data) {
738
- return;
739
- }
740
- if (!isAllowedOrigin(allowedOrigins, ev.origin)) {
741
- console.warn(`Invalid origin '${ev.origin}' for comlink proxy`);
742
- return;
598
+ class MinHeap {
599
+ constructor() {
600
+ this.data = [];
601
+ }
602
+ push(item) {
603
+ this.data.push(item);
604
+ this.bubbleUp(this.data.length - 1);
605
+ }
606
+ pop() {
607
+ const top = this.data[0];
608
+ const end = this.data.pop();
609
+ if (this.data.length > 0) {
610
+ this.data[0] = end;
611
+ this.bubbleDown(0);
743
612
  }
744
- const { id, type, path } = Object.assign({ path: [] }, ev.data);
745
- const argumentList = (ev.data.argumentList || []).map(fromWireValue);
746
- let returnValue;
747
- try {
748
- const parent = path.slice(0, -1).reduce((obj, prop) => obj[prop], obj);
749
- const rawValue = path.reduce((obj, prop) => obj[prop], obj);
750
- switch (type) {
751
- case "GET" /* MessageType.GET */:
752
- {
753
- returnValue = rawValue;
754
- }
755
- break;
756
- case "SET" /* MessageType.SET */:
757
- {
758
- parent[path.slice(-1)[0]] = fromWireValue(ev.data.value);
759
- returnValue = true;
760
- }
761
- break;
762
- case "APPLY" /* MessageType.APPLY */:
763
- {
764
- returnValue = rawValue.apply(parent, argumentList);
765
- }
766
- break;
767
- case "CONSTRUCT" /* MessageType.CONSTRUCT */:
768
- {
769
- const value = new rawValue(...argumentList);
770
- returnValue = proxy(value);
771
- }
772
- break;
773
- case "ENDPOINT" /* MessageType.ENDPOINT */:
774
- {
775
- const { port1, port2 } = new MessageChannel();
776
- expose(obj, port2);
777
- returnValue = transfer(port1, [port1]);
778
- }
779
- break;
780
- case "RELEASE" /* MessageType.RELEASE */:
781
- {
782
- returnValue = undefined;
783
- }
784
- break;
785
- default:
786
- return;
787
- }
613
+ return top;
614
+ }
615
+ empty() {
616
+ return this.data.length === 0;
617
+ }
618
+ bubbleUp(pos) {
619
+ const data = this.data;
620
+ while (pos > 0) {
621
+ const parent = (pos - 1) >> 1;
622
+ if (data[parent][0] <= data[pos][0])
623
+ break;
624
+ [data[parent], data[pos]] = [data[pos], data[parent]];
625
+ pos = parent;
788
626
  }
789
- catch (value) {
790
- returnValue = { value, [throwMarker]: 0 };
627
+ }
628
+ bubbleDown(pos) {
629
+ const data = this.data;
630
+ const length = data.length;
631
+ while (true) {
632
+ const left = pos * 2 + 1;
633
+ const right = pos * 2 + 2;
634
+ let min = pos;
635
+ if (left < length && data[left][0] < data[min][0])
636
+ min = left;
637
+ if (right < length && data[right][0] < data[min][0])
638
+ min = right;
639
+ if (min === pos)
640
+ break;
641
+ [data[pos], data[min]] = [data[min], data[pos]];
642
+ pos = min;
791
643
  }
792
- Promise.resolve(returnValue)
793
- .catch((value) => {
794
- return { value, [throwMarker]: 0 };
795
- })
796
- .then((returnValue) => {
797
- const [wireValue, transferables] = toWireValue(returnValue);
798
- ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);
799
- if (type === "RELEASE" /* MessageType.RELEASE */) {
800
- // detach and deactive after sending release response above.
801
- ep.removeEventListener("message", callback);
802
- closeEndPoint(ep);
803
- if (finalizer in obj && typeof obj[finalizer] === "function") {
804
- obj[finalizer]();
805
- }
806
- }
807
- })
808
- .catch((error) => {
809
- // Send Serialization Error To Caller
810
- const [wireValue, transferables] = toWireValue({
811
- value: new TypeError("Unserializable return value"),
812
- [throwMarker]: 0,
813
- });
814
- ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);
815
- });
816
- });
817
- if (ep.start) {
818
- ep.start();
819
644
  }
820
645
  }
821
- function isMessagePort(endpoint) {
822
- return endpoint.constructor.name === "MessagePort";
646
+
647
+ /**
648
+ * Get nested property value
649
+ * For example: getNestedValue(obj, 'a.b.c') will return obj.a.b.c
650
+ */
651
+ function getNestedValue(obj, path) {
652
+ const keys = String(path).split('.');
653
+ return get$1(obj, keys);
823
654
  }
824
- function closeEndPoint(endpoint) {
825
- if (isMessagePort(endpoint))
826
- endpoint.close();
655
+ /**
656
+ * Set nested property value
657
+ * For example: setNestedValue(obj, 'a.b.c', value) will set obj.a.b.c = value
658
+ */
659
+ function setNestedValue(obj, path, value) {
660
+ const keys = String(path).split('.');
661
+ set$1(obj, keys, value);
827
662
  }
828
- function wrap(ep, target) {
829
- const pendingListeners = new Map();
830
- ep.addEventListener("message", function handleMessage(ev) {
831
- const { data } = ev;
832
- if (!data || !data.id) {
833
- return;
834
- }
835
- const resolver = pendingListeners.get(data.id);
836
- if (!resolver) {
837
- return;
838
- }
839
- try {
840
- resolver(data);
841
- }
842
- finally {
843
- pendingListeners.delete(data.id);
663
+ /**
664
+ * Merge objects, but undefined values in source objects will not override existing values
665
+ * @param target - The target object
666
+ * @param sources - Source objects to merge
667
+ * @returns A new merged object
668
+ *
669
+ * @example
670
+ * assignDefined({ a: 1, b: 2 }, { b: undefined, c: 3 })
671
+ * // Returns: { a: 1, b: 2, c: 3 }
672
+ */
673
+ function assignDefined(target, ...sources) {
674
+ sources.forEach((source) => {
675
+ if (source) {
676
+ Object.keys(source).forEach((key) => {
677
+ const value = source[key];
678
+ if (value !== undefined) {
679
+ target[key] = value;
680
+ }
681
+ });
844
682
  }
845
683
  });
846
- return createProxy(ep, pendingListeners, [], target);
684
+ return target;
847
685
  }
848
- function throwIfProxyReleased(isReleased) {
849
- if (isReleased) {
850
- throw new Error("Proxy has been released and is not useable");
851
- }
686
+
687
+ /**
688
+ * 通用排序核心函数
689
+ */
690
+ function sort$1(model, compareFn) {
691
+ const nodes = model.nodes();
692
+ nodes.sort(compareFn);
693
+ model.setNodeOrder(nodes);
694
+ return model;
852
695
  }
853
- function releaseEndpoint(ep) {
854
- return requestResponseMessage(ep, new Map(), {
855
- type: "RELEASE" /* MessageType.RELEASE */,
856
- }).then(() => {
857
- closeEndPoint(ep);
696
+ function orderByDegree(model, order = 'desc') {
697
+ return sort$1(model, (nodeA, nodeB) => {
698
+ const degreeA = model.degree(nodeA.id);
699
+ const degreeB = model.degree(nodeB.id);
700
+ if (order === 'asc') {
701
+ return degreeA - degreeB; // ascending order
702
+ }
703
+ return degreeB - degreeA; // descending order
858
704
  });
859
705
  }
860
- const proxyCounter = new WeakMap();
861
- const proxyFinalizers = "FinalizationRegistry" in globalThis &&
862
- new FinalizationRegistry((ep) => {
863
- const newCount = (proxyCounter.get(ep) || 0) - 1;
864
- proxyCounter.set(ep, newCount);
865
- if (newCount === 0) {
866
- releaseEndpoint(ep);
706
+ /**
707
+ * ID 排序
708
+ */
709
+ function orderById(model) {
710
+ return sort$1(model, (nodeA, nodeB) => {
711
+ const idA = nodeA.id;
712
+ const idB = nodeB.id;
713
+ if (typeof idA === 'number' && typeof idB === 'number') {
714
+ return idA - idB;
867
715
  }
716
+ return String(idA).localeCompare(String(idB));
868
717
  });
869
- function registerProxy(proxy, ep) {
870
- const newCount = (proxyCounter.get(ep) || 0) + 1;
871
- proxyCounter.set(ep, newCount);
872
- if (proxyFinalizers) {
873
- proxyFinalizers.register(proxy, ep, proxy);
874
- }
875
718
  }
876
- function unregisterProxy(proxy) {
877
- if (proxyFinalizers) {
878
- proxyFinalizers.unregister(proxy);
879
- }
719
+ /**
720
+ * 按自定义比较函数排序
721
+ */
722
+ function orderBySorter(model, sorter) {
723
+ return sort$1(model, (nodeA, nodeB) => {
724
+ const a = model.originalNode(nodeA.id);
725
+ const b = model.originalNode(nodeB.id);
726
+ return sorter(a, b);
727
+ });
880
728
  }
881
- function createProxy(ep, pendingListeners, path = [], target = function () { }) {
882
- let isProxyReleased = false;
883
- const proxy = new Proxy(target, {
884
- get(_target, prop) {
885
- throwIfProxyReleased(isProxyReleased);
886
- if (prop === releaseProxy) {
887
- return () => {
888
- unregisterProxy(proxy);
889
- releaseEndpoint(ep);
890
- pendingListeners.clear();
891
- isProxyReleased = true;
892
- };
729
+ /**
730
+ * Order nodes according to graph topology
731
+ */
732
+ function orderByTopology(model, directed = false) {
733
+ const n = model.nodeCount();
734
+ if (n === 0)
735
+ return model;
736
+ const nodes = model.nodes();
737
+ const orderedNodes = [nodes[0]];
738
+ const pickFlags = {};
739
+ pickFlags[nodes[0].id] = true;
740
+ let k = 0;
741
+ let i = 0;
742
+ model.forEachNode((node) => {
743
+ if (i !== 0) {
744
+ const currentDegree = model.degree(node.id, 'both');
745
+ const nextDegree = i < n - 1 ? model.degree(nodes[i + 1].id, 'both') : 0;
746
+ const currentNodeId = orderedNodes[k].id;
747
+ const isNeighbor = model
748
+ .neighbors(currentNodeId, 'both')
749
+ .includes(node.id);
750
+ if ((i === n - 1 || currentDegree !== nextDegree || isNeighbor) &&
751
+ !pickFlags[node.id]) {
752
+ orderedNodes.push(node);
753
+ pickFlags[node.id] = true;
754
+ k++;
893
755
  }
894
- if (prop === "then") {
895
- if (path.length === 0) {
896
- return { then: () => proxy };
756
+ else {
757
+ const children = directed
758
+ ? model.successors(currentNodeId)
759
+ : model.neighbors(currentNodeId);
760
+ let foundChild = false;
761
+ for (let j = 0; j < children.length; j++) {
762
+ const childId = children[j];
763
+ const child = model.node(childId);
764
+ if (child &&
765
+ model.degree(childId) === model.degree(node.id) &&
766
+ !pickFlags[childId]) {
767
+ orderedNodes.push(child);
768
+ pickFlags[childId] = true;
769
+ foundChild = true;
770
+ break;
771
+ }
772
+ }
773
+ let ii = 0;
774
+ while (!foundChild) {
775
+ if (!pickFlags[nodes[ii].id]) {
776
+ orderedNodes.push(nodes[ii]);
777
+ pickFlags[nodes[ii].id] = true;
778
+ foundChild = true;
779
+ }
780
+ ii++;
781
+ if (ii === n) {
782
+ break;
783
+ }
897
784
  }
898
- const r = requestResponseMessage(ep, pendingListeners, {
899
- type: "GET" /* MessageType.GET */,
900
- path: path.map((p) => p.toString()),
901
- }).then(fromWireValue);
902
- return r.then.bind(r);
903
- }
904
- return createProxy(ep, pendingListeners, [...path, prop]);
905
- },
906
- set(_target, prop, rawValue) {
907
- throwIfProxyReleased(isProxyReleased);
908
- // FIXME: ES6 Proxy Handler `set` methods are supposed to return a
909
- // boolean. To show good will, we return true asynchronously ¯\_(ツ)_/¯
910
- const [value, transferables] = toWireValue(rawValue);
911
- return requestResponseMessage(ep, pendingListeners, {
912
- type: "SET" /* MessageType.SET */,
913
- path: [...path, prop].map((p) => p.toString()),
914
- value,
915
- }, transferables).then(fromWireValue);
916
- },
917
- apply(_target, _thisArg, rawArgumentList) {
918
- throwIfProxyReleased(isProxyReleased);
919
- const last = path[path.length - 1];
920
- if (last === createEndpoint) {
921
- return requestResponseMessage(ep, pendingListeners, {
922
- type: "ENDPOINT" /* MessageType.ENDPOINT */,
923
- }).then(fromWireValue);
924
- }
925
- // We just pretend that `bind()` didn’t happen.
926
- if (last === "bind") {
927
- return createProxy(ep, pendingListeners, path.slice(0, -1));
928
785
  }
929
- const [argumentList, transferables] = processArguments(rawArgumentList);
930
- return requestResponseMessage(ep, pendingListeners, {
931
- type: "APPLY" /* MessageType.APPLY */,
932
- path: path.map((p) => p.toString()),
933
- argumentList,
934
- }, transferables).then(fromWireValue);
935
- },
936
- construct(_target, rawArgumentList) {
937
- throwIfProxyReleased(isProxyReleased);
938
- const [argumentList, transferables] = processArguments(rawArgumentList);
939
- return requestResponseMessage(ep, pendingListeners, {
940
- type: "CONSTRUCT" /* MessageType.CONSTRUCT */,
941
- path: path.map((p) => p.toString()),
942
- argumentList,
943
- }, transferables).then(fromWireValue);
944
- },
786
+ }
787
+ i++;
945
788
  });
946
- registerProxy(proxy, ep);
947
- return proxy;
948
- }
949
- function myFlat(arr) {
950
- return Array.prototype.concat.apply([], arr);
789
+ // Update model with ordered nodes
790
+ model.setNodeOrder(orderedNodes);
791
+ return model;
951
792
  }
952
- function processArguments(argumentList) {
953
- const processed = argumentList.map(toWireValue);
954
- return [processed.map((v) => v[0]), myFlat(processed.map((v) => v[1]))];
793
+
794
+ function parsePoint(point) {
795
+ var _a;
796
+ return [point.x, point.y, (_a = point.z) !== null && _a !== void 0 ? _a : 0];
955
797
  }
956
- const transferCache = new WeakMap();
957
- function transfer(obj, transfers) {
958
- transferCache.set(obj, transfers);
959
- return obj;
798
+ function toPointObject(point) {
799
+ var _a;
800
+ return { x: point[0], y: point[1], z: (_a = point[2]) !== null && _a !== void 0 ? _a : 0 };
960
801
  }
961
- function proxy(obj) {
962
- return Object.assign(obj, { [proxyMarker]: true });
802
+
803
+ function parseSize(size) {
804
+ if (!size)
805
+ return [0, 0, 0];
806
+ if (isNumber(size))
807
+ return [size, size, size];
808
+ else if (Array.isArray(size) && size.length === 0)
809
+ return [0, 0, 0];
810
+ const [x, y = x, z = x] = size;
811
+ return [x, y, z];
963
812
  }
964
- function toWireValue(value) {
965
- for (const [name, handler] of transferHandlers) {
966
- if (handler.canHandle(value)) {
967
- const [serializedValue, transferables] = handler.serialize(value);
968
- return [
969
- {
970
- type: "HANDLER" /* WireValueType.HANDLER */,
971
- name,
972
- value: serializedValue,
973
- },
974
- transferables,
975
- ];
976
- }
813
+
814
+ /**
815
+ * Viewport configuration such as width, height and center point.
816
+ */
817
+ const normalizeViewport = (options) => {
818
+ const { width, height, center } = options;
819
+ const normalizedWidth = width !== null && width !== void 0 ? width : (typeof window !== 'undefined' ? window.innerWidth : 0);
820
+ const normalizedHeight = height !== null && height !== void 0 ? height : (typeof window !== 'undefined' ? window.innerHeight : 0);
821
+ const centerPoint = center !== null && center !== void 0 ? center : [normalizedWidth / 2, normalizedHeight / 2];
822
+ return {
823
+ width: normalizedWidth,
824
+ height: normalizedHeight,
825
+ center: centerPoint,
826
+ };
827
+ };
828
+
829
+ /**
830
+ * Format value with multiple types into a function that returns a number
831
+ * @param value The value to be formatted
832
+ * @param defaultValue The default value when value is invalid
833
+ * @returns A function that returns a number
834
+ */
835
+ function formatNumberFn(value, defaultValue) {
836
+ // If value is a function, return it directly
837
+ if (isFunction(value)) {
838
+ return value;
977
839
  }
978
- return [
979
- {
980
- type: "RAW" /* WireValueType.RAW */,
981
- value,
982
- },
983
- transferCache.get(value) || [],
984
- ];
840
+ // If value is a number, return a function that returns this number
841
+ if (isNumber(value)) {
842
+ return () => value;
843
+ }
844
+ // For other cases (undefined or invalid values), return default value function
845
+ return () => defaultValue;
985
846
  }
986
- function fromWireValue(value) {
987
- switch (value.type) {
988
- case "HANDLER" /* WireValueType.HANDLER */:
989
- return transferHandlers.get(value.name).deserialize(value.value);
990
- case "RAW" /* WireValueType.RAW */:
991
- return value.value;
847
+ /**
848
+ * Format size config with multiple types into a function that returns a size
849
+ * @param value The value to be formatted
850
+ * @param defaultValue The default value when value is invalid
851
+ * @param resultIsNumber Whether to return a number (max of width/height) or size array
852
+ * @returns A function that returns a size
853
+ */
854
+ function formatSizeFn(value, defaultValue = 10) {
855
+ // If value is undefined, return default value function
856
+ if (!value) {
857
+ return () => defaultValue;
858
+ }
859
+ // If value is a function, return it directly
860
+ if (isFunction(value)) {
861
+ return value;
862
+ }
863
+ // If value is a number, return a function that returns this number
864
+ if (isNumber(value)) {
865
+ return () => value;
992
866
  }
867
+ // If value is an array, return max or the array itself
868
+ if (Array.isArray(value)) {
869
+ return () => value;
870
+ }
871
+ // If value is an object with width and height
872
+ if (isObject$1(value) && value.width && value.height) {
873
+ return () => [value.width, value.height];
874
+ }
875
+ return () => defaultValue;
993
876
  }
994
- function requestResponseMessage(ep, pendingListeners, msg, transfers) {
995
- return new Promise((resolve) => {
996
- const id = generateUUID();
997
- pendingListeners.set(id, resolve);
998
- if (ep.start) {
999
- ep.start();
1000
- }
1001
- ep.postMessage(Object.assign({ id }, msg), transfers);
1002
- });
1003
- }
1004
- function generateUUID() {
1005
- return new Array(4)
1006
- .fill(0)
1007
- .map(() => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16))
1008
- .join("-");
1009
- }
877
+ /**
878
+ * Format nodeSize and nodeSpacing into a function that returns the total size
879
+ * @param nodeSize The size of the node
880
+ * @param nodeSpacing The spacing around the node
881
+ * @param defaultNodeSize The default node size when value is invalid
882
+ * @returns A function that returns the total size (node size + spacing)
883
+ */
884
+ const formatNodeSizeFn = (nodeSize, nodeSpacing, defaultNodeSize = 10) => {
885
+ const nodeSpacingFunc = formatNumberFn(nodeSpacing, 0);
886
+ const nodeSizeFunc = formatSizeFn(nodeSize, defaultNodeSize);
887
+ return (node) => {
888
+ const size = nodeSizeFunc(node);
889
+ const spacing = nodeSpacingFunc(node);
890
+ return Math.max(...parseSize(size)) + spacing;
891
+ };
892
+ };
1010
893
 
1011
- class Supervisor {
1012
- constructor() {
1013
- this.worker = null;
1014
- this.workerApi = null;
894
+ class GraphLib {
895
+ constructor(data, options = {}) {
896
+ this.edgeIdCounter = new Map();
897
+ this.nodeMap = extractNodeData(data.nodes, options.node);
898
+ this.edgeMap = extractEdgeData(data.edges || [], options.edge, this.getEdgeId.bind(this));
1015
899
  }
1016
- /**
1017
- * Execute layout in worker
1018
- */
1019
- execute(layoutId, data, options) {
1020
- return __awaiter(this, void 0, void 0, function* () {
1021
- if (!this.worker) {
1022
- yield this.initWorker();
1023
- }
1024
- if (!this.workerApi) {
1025
- throw new Error('Worker API not initialized');
1026
- }
1027
- return yield this.workerApi.execute(layoutId, data, options);
1028
- });
900
+ data() {
901
+ return { nodes: this.nodeMap, edges: this.edgeMap };
1029
902
  }
1030
- /**
1031
- * Destroy worker
1032
- */
1033
- destroy() {
1034
- if (this.workerApi) {
1035
- this.workerApi.destroy();
903
+ replace(result) {
904
+ this.nodeMap = result.nodes;
905
+ this.edgeMap = result.edges;
906
+ this.clearCache();
907
+ }
908
+ nodes() {
909
+ return Array.from(this.nodeMap.values());
910
+ }
911
+ node(id) {
912
+ return this.nodeMap.get(id);
913
+ }
914
+ nodeAt(index) {
915
+ if (!this.indexNodeCache) {
916
+ this.buildNodeIndexCache();
1036
917
  }
1037
- if (this.worker) {
1038
- this.worker.terminate();
1039
- this.worker = null;
1040
- this.workerApi = null;
918
+ const nodeId = this.indexNodeCache.get(index);
919
+ return nodeId ? this.nodeMap.get(nodeId) : undefined;
920
+ }
921
+ nodeIndexOf(id) {
922
+ var _a;
923
+ if (!this.nodeIndexCache) {
924
+ this.buildNodeIndexCache();
1041
925
  }
926
+ return (_a = this.nodeIndexCache.get(id)) !== null && _a !== void 0 ? _a : -1;
1042
927
  }
1043
- /**
1044
- * Initialize worker
1045
- */
1046
- initWorker() {
1047
- return __awaiter(this, void 0, void 0, function* () {
1048
- const workerPath = this.resolveWorkerPath();
1049
- const isESM = workerPath.includes('/lib/') || workerPath.endsWith('.mjs');
1050
- const type = isESM ? 'module' : 'classic';
1051
- this.worker = new Worker(workerPath, { type });
1052
- this.workerApi = wrap(this.worker);
1053
- });
928
+ firstNode() {
929
+ return this.nodeMap.values().next().value;
1054
930
  }
1055
- /**
1056
- * Resolve worker script path which works in both ESM and UMD environments
1057
- */
1058
- resolveWorkerPath() {
1059
- if (typeof ({ url: (typeof document === 'undefined' && typeof location === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : typeof document === 'undefined' ? location.href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.js', document.baseURI).href)) }) !== 'undefined' && (typeof document === 'undefined' && typeof location === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : typeof document === 'undefined' ? location.href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.js', document.baseURI).href))) {
1060
- const currentUrl = new URL((typeof document === 'undefined' && typeof location === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : typeof document === 'undefined' ? location.href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.js', document.baseURI).href)));
1061
- // e.g. `.../lib/runtime/supervisor.js` -> `.../lib/worker.js`
1062
- const asRoot = currentUrl.href.replace(/\/runtime\/[^/]+\.js$/, '/worker.js');
1063
- if (asRoot !== currentUrl.href)
1064
- return asRoot;
1065
- // Fallback: keep legacy behavior (same directory)
1066
- return currentUrl.href.replace(/\/[^/]+\.js$/, '/worker.js');
931
+ forEachNode(callback) {
932
+ let i = 0;
933
+ this.nodeMap.forEach((node) => callback(node, i++));
934
+ }
935
+ originalNode(id) {
936
+ const node = this.nodeMap.get(id);
937
+ return node === null || node === void 0 ? void 0 : node._original;
938
+ }
939
+ nodeCount() {
940
+ return this.nodeMap.size;
941
+ }
942
+ edges() {
943
+ return Array.from(this.edgeMap.values());
944
+ }
945
+ edge(id) {
946
+ return this.edgeMap.get(id);
947
+ }
948
+ firstEdge() {
949
+ return this.edgeMap.values().next().value;
950
+ }
951
+ forEachEdge(callback) {
952
+ let i = 0;
953
+ this.edgeMap.forEach((edge) => callback(edge, i++));
954
+ }
955
+ originalEdge(id) {
956
+ const edge = this.edgeMap.get(id);
957
+ return edge === null || edge === void 0 ? void 0 : edge._original;
958
+ }
959
+ edgeCount() {
960
+ return this.edgeMap.size;
961
+ }
962
+ getEdgeId(edge) {
963
+ if (edge.id)
964
+ return edge.id;
965
+ const baseId = `${edge.source}-${edge.target}`;
966
+ const count = this.edgeIdCounter.get(baseId) || 0;
967
+ const id = count === 0 ? baseId : `${baseId}-${count}`;
968
+ this.edgeIdCounter.set(baseId, count + 1);
969
+ return id;
970
+ }
971
+ degree(nodeId, direction = 'both') {
972
+ if (!this.degreeCache) {
973
+ this.buildDegreeCache();
1067
974
  }
1068
- if (typeof document !== 'undefined') {
1069
- const scripts = document.getElementsByTagName('script');
1070
- for (let i = scripts.length - 1; i >= 0; i--) {
1071
- const src = scripts[i].src;
1072
- if (src && (src.includes('index.js') || src.includes('index.min.js'))) {
1073
- return src.replace(/index(\.min)?\.js/, 'worker.js');
1074
- }
975
+ const degree = this.degreeCache.get(nodeId);
976
+ if (!degree)
977
+ return 0;
978
+ return degree[direction];
979
+ }
980
+ neighbors(nodeId, direction = 'both') {
981
+ if (!this.outAdjacencyCache || !this.inAdjacencyCache) {
982
+ this.buildAdjacencyCache();
983
+ }
984
+ if (direction === 'out') {
985
+ return Array.from(this.outAdjacencyCache.get(nodeId) || []);
986
+ }
987
+ if (direction === 'in') {
988
+ return Array.from(this.inAdjacencyCache.get(nodeId) || []);
989
+ }
990
+ if (this.bothAdjacencyCache) {
991
+ return Array.from(this.bothAdjacencyCache.get(nodeId) || []);
992
+ }
993
+ const inSet = this.inAdjacencyCache.get(nodeId);
994
+ const outSet = this.outAdjacencyCache.get(nodeId);
995
+ if (!inSet && !outSet)
996
+ return [];
997
+ if (!inSet)
998
+ return Array.from(outSet);
999
+ if (!outSet)
1000
+ return Array.from(inSet);
1001
+ const merged = new Set();
1002
+ inSet.forEach((id) => merged.add(id));
1003
+ outSet.forEach((id) => merged.add(id));
1004
+ return Array.from(merged);
1005
+ }
1006
+ successors(nodeId) {
1007
+ return this.neighbors(nodeId, 'out');
1008
+ }
1009
+ predecessors(nodeId) {
1010
+ return this.neighbors(nodeId, 'in');
1011
+ }
1012
+ setNodeOrder(nodes) {
1013
+ const next = new Map();
1014
+ for (const node of nodes)
1015
+ next.set(node.id, node);
1016
+ this.nodeMap = next;
1017
+ this.nodeIndexCache = undefined;
1018
+ this.indexNodeCache = undefined;
1019
+ }
1020
+ clearCache() {
1021
+ this.degreeCache = undefined;
1022
+ this.inAdjacencyCache = undefined;
1023
+ this.outAdjacencyCache = undefined;
1024
+ this.bothAdjacencyCache = undefined;
1025
+ this.nodeIndexCache = undefined;
1026
+ this.indexNodeCache = undefined;
1027
+ }
1028
+ buildDegreeCache() {
1029
+ this.degreeCache = new Map();
1030
+ for (const edge of this.edges()) {
1031
+ const { source, target } = edge;
1032
+ if (edge.source === edge.target)
1033
+ continue;
1034
+ if (!this.degreeCache.has(source)) {
1035
+ this.degreeCache.set(source, { in: 0, out: 0, both: 0 });
1036
+ }
1037
+ const sourceDeg = this.degreeCache.get(edge.source);
1038
+ if (sourceDeg) {
1039
+ sourceDeg.out++;
1040
+ sourceDeg.both++;
1041
+ }
1042
+ if (!this.degreeCache.has(target)) {
1043
+ this.degreeCache.set(target, { in: 0, out: 0, both: 0 });
1044
+ }
1045
+ const targetDeg = this.degreeCache.get(edge.target);
1046
+ if (targetDeg) {
1047
+ targetDeg.in++;
1048
+ targetDeg.both++;
1049
+ }
1050
+ }
1051
+ }
1052
+ buildAdjacencyCache() {
1053
+ this.inAdjacencyCache = new Map();
1054
+ this.outAdjacencyCache = new Map();
1055
+ for (const edge of this.edges()) {
1056
+ if (!this.nodeMap.has(edge.source) || !this.nodeMap.has(edge.target))
1057
+ continue;
1058
+ if (!this.outAdjacencyCache.has(edge.source)) {
1059
+ this.outAdjacencyCache.set(edge.source, new Set());
1060
+ }
1061
+ this.outAdjacencyCache.get(edge.source).add(edge.target);
1062
+ if (!this.inAdjacencyCache.has(edge.target)) {
1063
+ this.inAdjacencyCache.set(edge.target, new Set());
1075
1064
  }
1065
+ this.inAdjacencyCache.get(edge.target).add(edge.source);
1076
1066
  }
1077
- return './worker.js';
1078
1067
  }
1079
- }
1080
-
1081
- const isArray = Array.isArray;
1082
-
1083
- /**
1084
- * Return the layout result for a graph with zero or one node.
1085
- * @param graph original graph
1086
- * @param center the layout center
1087
- * @returns layout result
1088
- */
1089
- function applySingleNodeLayout(model, center, dimensions = 2) {
1090
- const n = model.nodeCount();
1091
- if (n === 1) {
1092
- const first = model.firstNode();
1093
- first.x = center[0];
1094
- first.y = center[1];
1095
- if (dimensions === 3) {
1096
- first.z = center[2] || 0;
1097
- }
1068
+ buildNodeIndexCache() {
1069
+ this.nodeIndexCache = new Map();
1070
+ this.indexNodeCache = new Map();
1071
+ let index = 0;
1072
+ this.nodeMap.forEach((_node, nodeId) => {
1073
+ this.nodeIndexCache.set(nodeId, index);
1074
+ this.indexNodeCache.set(index, nodeId);
1075
+ index++;
1076
+ });
1077
+ }
1078
+ destroy() {
1079
+ this.clearCache();
1080
+ this.nodeMap.clear();
1081
+ this.edgeMap.clear();
1082
+ this.edgeIdCounter.clear();
1098
1083
  }
1099
1084
  }
1100
-
1101
- /**
1102
- * Floyd-Warshall algorithm to find shortest paths (but with no negative cycles).
1103
- */
1104
- const floydWarshall = (adjMatrix) => {
1105
- // initialize
1106
- const n = adjMatrix.length;
1107
- const dist = Array.from({ length: n }, () => new Array(n));
1108
- for (let i = 0; i < n; i++) {
1109
- const row = adjMatrix[i];
1110
- const drow = dist[i];
1111
- for (let j = 0; j < n; j++) {
1112
- drow[j] = i === j ? 0 : row[j] > 0 ? row[j] : Infinity;
1113
- }
1085
+ const nodeFields = [
1086
+ 'id',
1087
+ 'x',
1088
+ 'y',
1089
+ 'z',
1090
+ 'vx',
1091
+ 'vy',
1092
+ 'vz',
1093
+ 'fx',
1094
+ 'fy',
1095
+ 'fz',
1096
+ 'parentId',
1097
+ ];
1098
+ const edgeFields = ['id', 'source', 'target', 'points'];
1099
+ function extractNodeData(nodes, node) {
1100
+ if (!nodes) {
1101
+ throw new Error('Data.nodes is required');
1114
1102
  }
1115
- // floyd
1116
- for (let k = 0; k < n; k++) {
1117
- const dk = dist[k];
1118
- for (let i = 0; i < n; i++) {
1119
- const di = dist[i];
1120
- const dik = di[k];
1121
- if (dik === Infinity)
1103
+ const result = new Map();
1104
+ for (const datum of nodes) {
1105
+ const nodeData = { _original: datum };
1106
+ for (const field of nodeFields) {
1107
+ const value = datum[field];
1108
+ if (isNil(value))
1122
1109
  continue;
1123
- for (let j = 0; j < n; j++) {
1124
- const dkj = dk[j];
1125
- if (dkj === Infinity)
1110
+ nodeData[field] = value;
1111
+ }
1112
+ if (node) {
1113
+ const customFields = node(datum);
1114
+ for (const key in customFields) {
1115
+ const value = customFields[key];
1116
+ if (isNil(value))
1126
1117
  continue;
1127
- const next = dik + dkj;
1128
- if (next < di[j]) {
1129
- di[j] = next;
1130
- }
1118
+ nodeData[key] = value;
1131
1119
  }
1132
1120
  }
1121
+ if (isNil(nodeData.id)) {
1122
+ throw new Error(`Node is missing id field`);
1123
+ }
1124
+ result.set(nodeData.id, nodeData);
1133
1125
  }
1134
- return dist;
1135
- };
1136
- /**
1137
- * Get the adjacency matrix of the graph model.
1138
- */
1139
- const getAdjMatrix = (model, directed) => {
1140
- const n = model.nodeCount();
1141
- const matrix = Array.from({ length: n }, () => new Array(n));
1142
- // map node with index in data.nodes
1143
- const nodeMap = {};
1144
- let i = 0;
1145
- model.forEachNode((node) => {
1146
- nodeMap[node.id] = i++;
1147
- });
1148
- model.forEachEdge((e) => {
1149
- const sIndex = nodeMap[e.source];
1150
- const tIndex = nodeMap[e.target];
1151
- if (sIndex === undefined || tIndex === undefined)
1152
- return;
1153
- matrix[sIndex][tIndex] = 1;
1154
- if (!directed) {
1155
- matrix[tIndex][sIndex] = 1;
1126
+ return result;
1127
+ }
1128
+ function extractEdgeData(edges, edge, getEdgeId) {
1129
+ const result = new Map();
1130
+ for (const datum of edges) {
1131
+ const edgeData = { _original: datum };
1132
+ for (const field of edgeFields) {
1133
+ const value = datum[field];
1134
+ if (isNil(value))
1135
+ continue;
1136
+ edgeData[field] = value;
1156
1137
  }
1157
- });
1158
- return matrix;
1159
- };
1160
- /**
1161
- * Get the adjacency list of the graph model.
1162
- */
1163
- const getAdjList = (model, directed) => {
1164
- const n = model.nodeCount();
1165
- const adjList = Array.from({ length: n }, () => []);
1166
- // map node with index
1167
- const nodeMap = {};
1168
- let idx = 0;
1169
- model.forEachNode((node) => {
1170
- nodeMap[node.id] = idx++;
1171
- });
1172
- model.forEachEdge((e) => {
1173
- const s = nodeMap[e.source];
1174
- const t = nodeMap[e.target];
1175
- if (s == null || t == null)
1176
- return;
1177
- adjList[s].push(t);
1178
- if (!directed)
1179
- adjList[t].push(s);
1180
- });
1181
- return adjList;
1182
- };
1183
- /**
1184
- * scale matrix
1185
- * @param matrix [ [], [], [] ]
1186
- * @param ratio
1187
- */
1188
- const scaleMatrix = (matrix, ratio) => {
1189
- const n = matrix.length;
1190
- const result = new Array(n);
1191
- for (let i = 0; i < n; i++) {
1192
- const row = matrix[i];
1193
- const m = row.length;
1194
- const newRow = new Array(m);
1195
- for (let j = 0; j < m; j++) {
1196
- newRow[j] = row[j] * ratio;
1138
+ if (edge) {
1139
+ const customFields = edge(datum);
1140
+ for (const key in customFields) {
1141
+ const value = customFields[key];
1142
+ if (isNil(value))
1143
+ continue;
1144
+ edgeData[key] = value;
1145
+ }
1197
1146
  }
1198
- result[i] = newRow;
1147
+ if (isNil(edgeData.source) || isNil(edgeData.target)) {
1148
+ throw new Error(`Edge is missing source or target field`);
1149
+ }
1150
+ if (isNil(edgeData.id)) {
1151
+ edgeData.id = getEdgeId === null || getEdgeId === void 0 ? void 0 : getEdgeId(datum);
1152
+ }
1153
+ result.set(edgeData.id, edgeData);
1199
1154
  }
1200
1155
  return result;
1201
- };
1202
- /**
1203
- * calculate the bounding box for the nodes according to their x, y, and size
1204
- * @param nodes nodes in the layout
1205
- * @returns
1206
- */
1207
- const getLayoutBBox = (nodes) => {
1208
- let minX = Infinity;
1209
- let minY = Infinity;
1210
- let maxX = -Infinity;
1211
- let maxY = -Infinity;
1212
- nodes.forEach((node) => {
1213
- let size = node.data.size;
1214
- if (isArray(size)) {
1215
- if (size.length === 1)
1216
- size = [size[0], size[0]];
1156
+ }
1157
+ function initNodePosition(model, width, height, dimensions = 2) {
1158
+ model.forEachNode((node) => {
1159
+ if (isNil(node.x)) {
1160
+ node.x = Math.random() * width;
1217
1161
  }
1218
- else if (size === undefined || isNaN(size)) {
1219
- size = [30, 30];
1162
+ if (isNil(node.y)) {
1163
+ node.y = Math.random() * height;
1220
1164
  }
1221
- else if (isNumber(size)) {
1222
- size = [size, size];
1165
+ if (dimensions === 3 && isNil(node.z)) {
1166
+ node.z = Math.random() * Math.min(width, height);
1223
1167
  }
1224
- const halfSize = [size[0] / 2, size[1] / 2];
1225
- const left = node.data.x - halfSize[0];
1226
- const right = node.data.x + halfSize[0];
1227
- const top = node.data.y - halfSize[1];
1228
- const bottom = node.data.y + halfSize[1];
1229
- if (minX > left)
1230
- minX = left;
1231
- if (minY > top)
1232
- minY = top;
1233
- if (maxX < right)
1234
- maxX = right;
1235
- if (maxY < bottom)
1236
- maxY = bottom;
1237
1168
  });
1238
- return { minX, minY, maxX, maxY };
1239
- };
1169
+ }
1170
+
1171
+ class RuntimeContext {
1172
+ constructor(data, options = {}) {
1173
+ this.graph = new GraphLib(data, options);
1174
+ }
1175
+ export() {
1176
+ return this.graph.data();
1177
+ }
1178
+ replace(result) {
1179
+ this.graph.replace(result);
1180
+ }
1181
+ forEachNode(callback) {
1182
+ this.graph.forEachNode(callback);
1183
+ }
1184
+ forEachEdge(callback) {
1185
+ this.graph.forEachEdge((edge, i) => {
1186
+ edge.sourceNode = this.graph.node(edge.source);
1187
+ edge.targetNode = this.graph.node(edge.target);
1188
+ callback(edge, i);
1189
+ });
1190
+ }
1191
+ destroy() {
1192
+ this.graph.destroy();
1193
+ }
1194
+ }
1195
+
1240
1196
  /**
1241
- * calculate the euclidean distance form p1 to p2
1242
- * @param p1
1243
- * @param p2
1244
- * @returns
1197
+ * @license
1198
+ * Copyright 2019 Google LLC
1199
+ * SPDX-License-Identifier: Apache-2.0
1245
1200
  */
1246
- const getEuclideanDistance = (p1, p2) => Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
1201
+ const proxyMarker = Symbol("Comlink.proxy");
1202
+ const createEndpoint = Symbol("Comlink.endpoint");
1203
+ const releaseProxy = Symbol("Comlink.releaseProxy");
1204
+ const finalizer = Symbol("Comlink.finalizer");
1205
+ const throwMarker = Symbol("Comlink.thrown");
1206
+ const isObject = (val) => (typeof val === "object" && val !== null) || typeof val === "function";
1247
1207
  /**
1248
- * Depth first search begin from nodes in graphCore data.
1249
- * @param graphCore graphlib data structure
1250
- * @param nodes begin nodes
1251
- * @param fn will be called while visiting each node
1252
- * @param mode 'TB' - visit from top to bottom; 'BT' - visit from bottom to top;
1253
- * @returns
1208
+ * Internal transfer handle to handle objects marked to proxy.
1254
1209
  */
1255
- const graphTreeDfs = (graph, nodes, fn, mode = 'TB', treeKey, stopFns = {}) => {
1256
- if (!(nodes === null || nodes === void 0 ? void 0 : nodes.length))
1257
- return;
1258
- const { stopBranchFn, stopAllFn } = stopFns;
1259
- for (let i = 0; i < nodes.length; i++) {
1260
- const node = nodes[i];
1261
- if (!graph.hasNode(node.id))
1262
- continue;
1263
- if (stopBranchFn === null || stopBranchFn === void 0 ? void 0 : stopBranchFn(node))
1264
- continue; // Stop this branch
1265
- if (stopAllFn === null || stopAllFn === void 0 ? void 0 : stopAllFn(node))
1266
- return; // Stop all
1267
- if (mode === 'TB')
1268
- fn(node); // Traverse from top to bottom
1269
- graphTreeDfs(graph, graph.getChildren(node.id, treeKey), fn, mode, treeKey, stopFns);
1270
- if (mode !== 'TB')
1271
- fn(node); // Traverse from bottom to top
1272
- }
1210
+ const proxyTransferHandler = {
1211
+ canHandle: (val) => isObject(val) && val[proxyMarker],
1212
+ serialize(obj) {
1213
+ const { port1, port2 } = new MessageChannel();
1214
+ expose(obj, port1);
1215
+ return [port2, [port2]];
1216
+ },
1217
+ deserialize(port) {
1218
+ port.start();
1219
+ return wrap(port);
1220
+ },
1273
1221
  };
1274
1222
  /**
1275
- * Use Johnson + Dijkstra to compute APSP for sparse graph.
1276
- * Fully compatible with floydWarshall(adjMatrix).
1223
+ * Internal transfer handler to handle thrown exceptions.
1277
1224
  */
1278
- function johnson(adjList) {
1279
- const n = adjList.length;
1280
- // Step 1: add a dummy node q connected to all nodes with weight 0
1281
- new Array(n).fill(0);
1282
- // Bellman-Ford to compute potentials h(v)
1283
- // 因为权重全是 1,无负边,可直接跳过 BF,h 全 0 即可
1284
- // Step 2: reweight edges
1285
- // 因为 h(u)=h(v)=0,reweight 后仍然是 1,省略 reweight 过程
1286
- // Step 3: run Dijkstra from each node
1287
- const distAll = Array.from({ length: n }, () => new Array(n).fill(Infinity));
1288
- for (let s = 0; s < n; s++) {
1289
- distAll[s] = dijkstra(adjList, s);
1290
- }
1291
- return distAll;
1292
- }
1225
+ const throwTransferHandler = {
1226
+ canHandle: (value) => isObject(value) && throwMarker in value,
1227
+ serialize({ value }) {
1228
+ let serialized;
1229
+ if (value instanceof Error) {
1230
+ serialized = {
1231
+ isError: true,
1232
+ value: {
1233
+ message: value.message,
1234
+ name: value.name,
1235
+ stack: value.stack,
1236
+ },
1237
+ };
1238
+ }
1239
+ else {
1240
+ serialized = { isError: false, value };
1241
+ }
1242
+ return [serialized, []];
1243
+ },
1244
+ deserialize(serialized) {
1245
+ if (serialized.isError) {
1246
+ throw Object.assign(new Error(serialized.value.message), serialized.value);
1247
+ }
1248
+ throw serialized.value;
1249
+ },
1250
+ };
1293
1251
  /**
1294
- * Dijkstra algorithm to find shortest paths from source to all nodes.
1252
+ * Allows customizing the serialization of certain values.
1295
1253
  */
1296
- function dijkstra(adjList, source) {
1297
- const n = adjList.length;
1298
- const dist = new Array(n).fill(Infinity);
1299
- dist[source] = 0;
1300
- // Minimal binary heap
1301
- const heap = new MinHeap();
1302
- heap.push([0, source]); // [distance, node]
1303
- while (!heap.empty()) {
1304
- const [d, u] = heap.pop();
1305
- if (d !== dist[u])
1306
- continue;
1307
- const neighbors = adjList[u];
1308
- for (let i = 0; i < neighbors.length; i++) {
1309
- const v = neighbors[i];
1310
- const nd = d + 1;
1311
- if (nd < dist[v]) {
1312
- dist[v] = nd;
1313
- heap.push([nd, v]);
1314
- }
1254
+ const transferHandlers = new Map([
1255
+ ["proxy", proxyTransferHandler],
1256
+ ["throw", throwTransferHandler],
1257
+ ]);
1258
+ function isAllowedOrigin(allowedOrigins, origin) {
1259
+ for (const allowedOrigin of allowedOrigins) {
1260
+ if (origin === allowedOrigin || allowedOrigin === "*") {
1261
+ return true;
1262
+ }
1263
+ if (allowedOrigin instanceof RegExp && allowedOrigin.test(origin)) {
1264
+ return true;
1315
1265
  }
1316
1266
  }
1317
- return dist;
1267
+ return false;
1318
1268
  }
1319
- class MinHeap {
1320
- constructor() {
1321
- this.data = [];
1322
- }
1323
- push(item) {
1324
- this.data.push(item);
1325
- this.bubbleUp(this.data.length - 1);
1326
- }
1327
- pop() {
1328
- const top = this.data[0];
1329
- const end = this.data.pop();
1330
- if (this.data.length > 0) {
1331
- this.data[0] = end;
1332
- this.bubbleDown(0);
1269
+ function expose(obj, ep = globalThis, allowedOrigins = ["*"]) {
1270
+ ep.addEventListener("message", function callback(ev) {
1271
+ if (!ev || !ev.data) {
1272
+ return;
1333
1273
  }
1334
- return top;
1335
- }
1336
- empty() {
1337
- return this.data.length === 0;
1338
- }
1339
- bubbleUp(pos) {
1340
- const data = this.data;
1341
- while (pos > 0) {
1342
- const parent = (pos - 1) >> 1;
1343
- if (data[parent][0] <= data[pos][0])
1344
- break;
1345
- [data[parent], data[pos]] = [data[pos], data[parent]];
1346
- pos = parent;
1274
+ if (!isAllowedOrigin(allowedOrigins, ev.origin)) {
1275
+ console.warn(`Invalid origin '${ev.origin}' for comlink proxy`);
1276
+ return;
1347
1277
  }
1348
- }
1349
- bubbleDown(pos) {
1350
- const data = this.data;
1351
- const length = data.length;
1352
- while (true) {
1353
- const left = pos * 2 + 1;
1354
- const right = pos * 2 + 2;
1355
- let min = pos;
1356
- if (left < length && data[left][0] < data[min][0])
1357
- min = left;
1358
- if (right < length && data[right][0] < data[min][0])
1359
- min = right;
1360
- if (min === pos)
1361
- break;
1362
- [data[pos], data[min]] = [data[min], data[pos]];
1363
- pos = min;
1278
+ const { id, type, path } = Object.assign({ path: [] }, ev.data);
1279
+ const argumentList = (ev.data.argumentList || []).map(fromWireValue);
1280
+ let returnValue;
1281
+ try {
1282
+ const parent = path.slice(0, -1).reduce((obj, prop) => obj[prop], obj);
1283
+ const rawValue = path.reduce((obj, prop) => obj[prop], obj);
1284
+ switch (type) {
1285
+ case "GET" /* MessageType.GET */:
1286
+ {
1287
+ returnValue = rawValue;
1288
+ }
1289
+ break;
1290
+ case "SET" /* MessageType.SET */:
1291
+ {
1292
+ parent[path.slice(-1)[0]] = fromWireValue(ev.data.value);
1293
+ returnValue = true;
1294
+ }
1295
+ break;
1296
+ case "APPLY" /* MessageType.APPLY */:
1297
+ {
1298
+ returnValue = rawValue.apply(parent, argumentList);
1299
+ }
1300
+ break;
1301
+ case "CONSTRUCT" /* MessageType.CONSTRUCT */:
1302
+ {
1303
+ const value = new rawValue(...argumentList);
1304
+ returnValue = proxy(value);
1305
+ }
1306
+ break;
1307
+ case "ENDPOINT" /* MessageType.ENDPOINT */:
1308
+ {
1309
+ const { port1, port2 } = new MessageChannel();
1310
+ expose(obj, port2);
1311
+ returnValue = transfer(port1, [port1]);
1312
+ }
1313
+ break;
1314
+ case "RELEASE" /* MessageType.RELEASE */:
1315
+ {
1316
+ returnValue = undefined;
1317
+ }
1318
+ break;
1319
+ default:
1320
+ return;
1321
+ }
1322
+ }
1323
+ catch (value) {
1324
+ returnValue = { value, [throwMarker]: 0 };
1364
1325
  }
1326
+ Promise.resolve(returnValue)
1327
+ .catch((value) => {
1328
+ return { value, [throwMarker]: 0 };
1329
+ })
1330
+ .then((returnValue) => {
1331
+ const [wireValue, transferables] = toWireValue(returnValue);
1332
+ ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);
1333
+ if (type === "RELEASE" /* MessageType.RELEASE */) {
1334
+ // detach and deactive after sending release response above.
1335
+ ep.removeEventListener("message", callback);
1336
+ closeEndPoint(ep);
1337
+ if (finalizer in obj && typeof obj[finalizer] === "function") {
1338
+ obj[finalizer]();
1339
+ }
1340
+ }
1341
+ })
1342
+ .catch((error) => {
1343
+ // Send Serialization Error To Caller
1344
+ const [wireValue, transferables] = toWireValue({
1345
+ value: new TypeError("Unserializable return value"),
1346
+ [throwMarker]: 0,
1347
+ });
1348
+ ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);
1349
+ });
1350
+ });
1351
+ if (ep.start) {
1352
+ ep.start();
1365
1353
  }
1366
1354
  }
1367
-
1368
- /**
1369
- * Get nested property value
1370
- * For example: getNestedValue(obj, 'a.b.c') will return obj.a.b.c
1371
- */
1372
- function getNestedValue(obj, path) {
1373
- const keys = String(path).split('.');
1374
- return get$1(obj, keys);
1355
+ function isMessagePort(endpoint) {
1356
+ return endpoint.constructor.name === "MessagePort";
1375
1357
  }
1376
- /**
1377
- * Set nested property value
1378
- * For example: setNestedValue(obj, 'a.b.c', value) will set obj.a.b.c = value
1379
- */
1380
- function setNestedValue(obj, path, value) {
1381
- const keys = String(path).split('.');
1382
- set$1(obj, keys, value);
1358
+ function closeEndPoint(endpoint) {
1359
+ if (isMessagePort(endpoint))
1360
+ endpoint.close();
1383
1361
  }
1384
- /**
1385
- * Merge objects, but undefined values in source objects will not override existing values
1386
- * @param target - The target object
1387
- * @param sources - Source objects to merge
1388
- * @returns A new merged object
1389
- *
1390
- * @example
1391
- * assignDefined({ a: 1, b: 2 }, { b: undefined, c: 3 })
1392
- * // Returns: { a: 1, b: 2, c: 3 }
1393
- */
1394
- function assignDefined(target, ...sources) {
1395
- sources.forEach((source) => {
1396
- if (source) {
1397
- Object.keys(source).forEach((key) => {
1398
- const value = source[key];
1399
- if (value !== undefined) {
1400
- target[key] = value;
1401
- }
1402
- });
1362
+ function wrap(ep, target) {
1363
+ const pendingListeners = new Map();
1364
+ ep.addEventListener("message", function handleMessage(ev) {
1365
+ const { data } = ev;
1366
+ if (!data || !data.id) {
1367
+ return;
1368
+ }
1369
+ const resolver = pendingListeners.get(data.id);
1370
+ if (!resolver) {
1371
+ return;
1372
+ }
1373
+ try {
1374
+ resolver(data);
1375
+ }
1376
+ finally {
1377
+ pendingListeners.delete(data.id);
1403
1378
  }
1404
1379
  });
1405
- return target;
1406
- }
1407
- function mergeOptions(base, patch) {
1408
- return Object.assign({}, base, patch || {});
1380
+ return createProxy(ep, pendingListeners, [], target);
1409
1381
  }
1410
-
1411
- /**
1412
- * 通用排序核心函数
1413
- */
1414
- function sort$1(model, compareFn) {
1415
- const nodes = model.nodes();
1416
- nodes.sort(compareFn);
1417
- model.setNodeOrder(nodes);
1418
- return model;
1382
+ function throwIfProxyReleased(isReleased) {
1383
+ if (isReleased) {
1384
+ throw new Error("Proxy has been released and is not useable");
1385
+ }
1419
1386
  }
1420
- function orderByDegree(model) {
1421
- return sort$1(model, (nodeA, nodeB) => {
1422
- const degreeA = model.degree(nodeA.id);
1423
- const degreeB = model.degree(nodeB.id);
1424
- return degreeB - degreeA; // descending order
1387
+ function releaseEndpoint(ep) {
1388
+ return requestResponseMessage(ep, new Map(), {
1389
+ type: "RELEASE" /* MessageType.RELEASE */,
1390
+ }).then(() => {
1391
+ closeEndPoint(ep);
1425
1392
  });
1426
1393
  }
1427
- /**
1428
- * ID 排序
1429
- */
1430
- function orderById(model) {
1431
- return sort$1(model, (nodeA, nodeB) => {
1432
- const idA = nodeA.id;
1433
- const idB = nodeB.id;
1434
- if (typeof idA === 'number' && typeof idB === 'number') {
1435
- return idA - idB;
1394
+ const proxyCounter = new WeakMap();
1395
+ const proxyFinalizers = "FinalizationRegistry" in globalThis &&
1396
+ new FinalizationRegistry((ep) => {
1397
+ const newCount = (proxyCounter.get(ep) || 0) - 1;
1398
+ proxyCounter.set(ep, newCount);
1399
+ if (newCount === 0) {
1400
+ releaseEndpoint(ep);
1436
1401
  }
1437
- return String(idA).localeCompare(String(idB));
1438
1402
  });
1403
+ function registerProxy(proxy, ep) {
1404
+ const newCount = (proxyCounter.get(ep) || 0) + 1;
1405
+ proxyCounter.set(ep, newCount);
1406
+ if (proxyFinalizers) {
1407
+ proxyFinalizers.register(proxy, ep, proxy);
1408
+ }
1439
1409
  }
1440
- /**
1441
- * 按自定义比较函数排序
1442
- */
1443
- function orderBySorter(model, sorter) {
1444
- return sort$1(model, (nodeA, nodeB) => {
1445
- const a = model.originalNode(nodeA.id);
1446
- const b = model.originalNode(nodeB.id);
1447
- return sorter(a, b);
1448
- });
1410
+ function unregisterProxy(proxy) {
1411
+ if (proxyFinalizers) {
1412
+ proxyFinalizers.unregister(proxy);
1413
+ }
1449
1414
  }
1450
- /**
1451
- * Order nodes according to graph topology
1452
- */
1453
- function orderByTopology(model, directed = false) {
1454
- const n = model.nodeCount();
1455
- if (n === 0)
1456
- return model;
1457
- const nodes = model.nodes();
1458
- const orderedNodes = [nodes[0]];
1459
- const pickFlags = {};
1460
- pickFlags[nodes[0].id] = true;
1461
- let k = 0;
1462
- let i = 0;
1463
- model.forEachNode((node) => {
1464
- if (i !== 0) {
1465
- const currentDegree = model.degree(node.id, 'both');
1466
- const nextDegree = i < n - 1 ? model.degree(nodes[i + 1].id, 'both') : 0;
1467
- const currentNodeId = orderedNodes[k].id;
1468
- const isNeighbor = model
1469
- .neighbors(currentNodeId, 'both')
1470
- .includes(node.id);
1471
- if ((i === n - 1 || currentDegree !== nextDegree || isNeighbor) &&
1472
- !pickFlags[node.id]) {
1473
- orderedNodes.push(node);
1474
- pickFlags[node.id] = true;
1475
- k++;
1415
+ function createProxy(ep, pendingListeners, path = [], target = function () { }) {
1416
+ let isProxyReleased = false;
1417
+ const proxy = new Proxy(target, {
1418
+ get(_target, prop) {
1419
+ throwIfProxyReleased(isProxyReleased);
1420
+ if (prop === releaseProxy) {
1421
+ return () => {
1422
+ unregisterProxy(proxy);
1423
+ releaseEndpoint(ep);
1424
+ pendingListeners.clear();
1425
+ isProxyReleased = true;
1426
+ };
1476
1427
  }
1477
- else {
1478
- const children = directed
1479
- ? model.successors(currentNodeId)
1480
- : model.neighbors(currentNodeId);
1481
- let foundChild = false;
1482
- for (let j = 0; j < children.length; j++) {
1483
- const childId = children[j];
1484
- const child = model.node(childId);
1485
- if (child &&
1486
- model.degree(childId) === model.degree(node.id) &&
1487
- !pickFlags[childId]) {
1488
- orderedNodes.push(child);
1489
- pickFlags[childId] = true;
1490
- foundChild = true;
1491
- break;
1492
- }
1493
- }
1494
- let ii = 0;
1495
- while (!foundChild) {
1496
- if (!pickFlags[nodes[ii].id]) {
1497
- orderedNodes.push(nodes[ii]);
1498
- pickFlags[nodes[ii].id] = true;
1499
- foundChild = true;
1500
- }
1501
- ii++;
1502
- if (ii === n) {
1503
- break;
1504
- }
1428
+ if (prop === "then") {
1429
+ if (path.length === 0) {
1430
+ return { then: () => proxy };
1505
1431
  }
1432
+ const r = requestResponseMessage(ep, pendingListeners, {
1433
+ type: "GET" /* MessageType.GET */,
1434
+ path: path.map((p) => p.toString()),
1435
+ }).then(fromWireValue);
1436
+ return r.then.bind(r);
1437
+ }
1438
+ return createProxy(ep, pendingListeners, [...path, prop]);
1439
+ },
1440
+ set(_target, prop, rawValue) {
1441
+ throwIfProxyReleased(isProxyReleased);
1442
+ // FIXME: ES6 Proxy Handler `set` methods are supposed to return a
1443
+ // boolean. To show good will, we return true asynchronously ¯\_(ツ)_/¯
1444
+ const [value, transferables] = toWireValue(rawValue);
1445
+ return requestResponseMessage(ep, pendingListeners, {
1446
+ type: "SET" /* MessageType.SET */,
1447
+ path: [...path, prop].map((p) => p.toString()),
1448
+ value,
1449
+ }, transferables).then(fromWireValue);
1450
+ },
1451
+ apply(_target, _thisArg, rawArgumentList) {
1452
+ throwIfProxyReleased(isProxyReleased);
1453
+ const last = path[path.length - 1];
1454
+ if (last === createEndpoint) {
1455
+ return requestResponseMessage(ep, pendingListeners, {
1456
+ type: "ENDPOINT" /* MessageType.ENDPOINT */,
1457
+ }).then(fromWireValue);
1458
+ }
1459
+ // We just pretend that `bind()` didn’t happen.
1460
+ if (last === "bind") {
1461
+ return createProxy(ep, pendingListeners, path.slice(0, -1));
1506
1462
  }
1463
+ const [argumentList, transferables] = processArguments(rawArgumentList);
1464
+ return requestResponseMessage(ep, pendingListeners, {
1465
+ type: "APPLY" /* MessageType.APPLY */,
1466
+ path: path.map((p) => p.toString()),
1467
+ argumentList,
1468
+ }, transferables).then(fromWireValue);
1469
+ },
1470
+ construct(_target, rawArgumentList) {
1471
+ throwIfProxyReleased(isProxyReleased);
1472
+ const [argumentList, transferables] = processArguments(rawArgumentList);
1473
+ return requestResponseMessage(ep, pendingListeners, {
1474
+ type: "CONSTRUCT" /* MessageType.CONSTRUCT */,
1475
+ path: path.map((p) => p.toString()),
1476
+ argumentList,
1477
+ }, transferables).then(fromWireValue);
1478
+ },
1479
+ });
1480
+ registerProxy(proxy, ep);
1481
+ return proxy;
1482
+ }
1483
+ function myFlat(arr) {
1484
+ return Array.prototype.concat.apply([], arr);
1485
+ }
1486
+ function processArguments(argumentList) {
1487
+ const processed = argumentList.map(toWireValue);
1488
+ return [processed.map((v) => v[0]), myFlat(processed.map((v) => v[1]))];
1489
+ }
1490
+ const transferCache = new WeakMap();
1491
+ function transfer(obj, transfers) {
1492
+ transferCache.set(obj, transfers);
1493
+ return obj;
1494
+ }
1495
+ function proxy(obj) {
1496
+ return Object.assign(obj, { [proxyMarker]: true });
1497
+ }
1498
+ function toWireValue(value) {
1499
+ for (const [name, handler] of transferHandlers) {
1500
+ if (handler.canHandle(value)) {
1501
+ const [serializedValue, transferables] = handler.serialize(value);
1502
+ return [
1503
+ {
1504
+ type: "HANDLER" /* WireValueType.HANDLER */,
1505
+ name,
1506
+ value: serializedValue,
1507
+ },
1508
+ transferables,
1509
+ ];
1507
1510
  }
1508
- i++;
1509
- });
1510
- // Update model with ordered nodes
1511
- model.setNodeOrder(orderedNodes);
1512
- return model;
1511
+ }
1512
+ return [
1513
+ {
1514
+ type: "RAW" /* WireValueType.RAW */,
1515
+ value,
1516
+ },
1517
+ transferCache.get(value) || [],
1518
+ ];
1513
1519
  }
1514
-
1515
- function parsePoint(point) {
1516
- var _a;
1517
- return [point.x, point.y, (_a = point.z) !== null && _a !== void 0 ? _a : 0];
1520
+ function fromWireValue(value) {
1521
+ switch (value.type) {
1522
+ case "HANDLER" /* WireValueType.HANDLER */:
1523
+ return transferHandlers.get(value.name).deserialize(value.value);
1524
+ case "RAW" /* WireValueType.RAW */:
1525
+ return value.value;
1526
+ }
1518
1527
  }
1519
- function toPointObject(point) {
1520
- var _a;
1521
- return { x: point[0], y: point[1], z: (_a = point[2]) !== null && _a !== void 0 ? _a : 0 };
1528
+ function requestResponseMessage(ep, pendingListeners, msg, transfers) {
1529
+ return new Promise((resolve) => {
1530
+ const id = generateUUID();
1531
+ pendingListeners.set(id, resolve);
1532
+ if (ep.start) {
1533
+ ep.start();
1534
+ }
1535
+ ep.postMessage(Object.assign({ id }, msg), transfers);
1536
+ });
1522
1537
  }
1523
-
1524
- function parseSize(size) {
1525
- if (!size)
1526
- return [0, 0, 0];
1527
- if (isNumber(size))
1528
- return [size, size, size];
1529
- else if (Array.isArray(size) && size.length === 0)
1530
- return [0, 0, 0];
1531
- const [x, y = x, z = x] = size;
1532
- return [x, y, z];
1538
+ function generateUUID() {
1539
+ return new Array(4)
1540
+ .fill(0)
1541
+ .map(() => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16))
1542
+ .join("-");
1533
1543
  }
1534
1544
 
1535
- /**
1536
- * Viewport configuration such as width, height and center point.
1537
- */
1538
- const normalizeViewport = (options) => {
1539
- const { width, height, center } = options;
1540
- const normalizedWidth = width !== null && width !== void 0 ? width : (typeof window !== 'undefined' ? window.innerWidth : 0);
1541
- const normalizedHeight = height !== null && height !== void 0 ? height : (typeof window !== 'undefined' ? window.innerHeight : 0);
1542
- const centerPoint = center !== null && center !== void 0 ? center : [normalizedWidth / 2, normalizedHeight / 2];
1543
- return {
1544
- width: normalizedWidth,
1545
- height: normalizedHeight,
1546
- center: centerPoint,
1547
- };
1548
- };
1545
+ class Supervisor {
1546
+ constructor() {
1547
+ this.worker = null;
1548
+ this.workerApi = null;
1549
+ }
1550
+ /**
1551
+ * Execute layout in worker
1552
+ */
1553
+ execute(layoutId, data, options) {
1554
+ return __awaiter(this, void 0, void 0, function* () {
1555
+ if (!this.worker) {
1556
+ yield this.initWorker();
1557
+ }
1558
+ if (!this.workerApi) {
1559
+ throw new Error('Worker API not initialized');
1560
+ }
1561
+ return yield this.workerApi.execute(layoutId, data, options);
1562
+ });
1563
+ }
1564
+ /**
1565
+ * Destroy worker
1566
+ */
1567
+ destroy() {
1568
+ if (this.workerApi) {
1569
+ this.workerApi.destroy();
1570
+ }
1571
+ if (this.worker) {
1572
+ this.worker.terminate();
1573
+ this.worker = null;
1574
+ this.workerApi = null;
1575
+ }
1576
+ }
1577
+ /**
1578
+ * Initialize worker
1579
+ */
1580
+ initWorker() {
1581
+ return __awaiter(this, void 0, void 0, function* () {
1582
+ const workerPath = this.resolveWorkerPath();
1583
+ const isESM = workerPath.includes('/lib/') || workerPath.endsWith('.mjs');
1584
+ const type = isESM ? 'module' : 'classic';
1585
+ this.worker = new Worker(workerPath, { type });
1586
+ this.workerApi = wrap(this.worker);
1587
+ });
1588
+ }
1589
+ /**
1590
+ * Resolve worker script path which works in both ESM and UMD environments
1591
+ */
1592
+ resolveWorkerPath() {
1593
+ if (typeof ({ url: (typeof document === 'undefined' && typeof location === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : typeof document === 'undefined' ? location.href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.js', document.baseURI).href)) }) !== 'undefined' && (typeof document === 'undefined' && typeof location === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : typeof document === 'undefined' ? location.href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.js', document.baseURI).href))) {
1594
+ const currentUrl = new URL((typeof document === 'undefined' && typeof location === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : typeof document === 'undefined' ? location.href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.js', document.baseURI).href)));
1595
+ // e.g. `.../lib/runtime/supervisor.js` -> `.../lib/worker.js`
1596
+ const asRoot = currentUrl.href.replace(/\/runtime\/[^/]+\.js$/, '/worker.js');
1597
+ if (asRoot !== currentUrl.href)
1598
+ return asRoot;
1599
+ // Fallback: keep legacy behavior (same directory)
1600
+ return currentUrl.href.replace(/\/[^/]+\.js$/, '/worker.js');
1601
+ }
1602
+ if (typeof document !== 'undefined') {
1603
+ const scripts = document.getElementsByTagName('script');
1604
+ for (let i = scripts.length - 1; i >= 0; i--) {
1605
+ const src = scripts[i].src;
1606
+ if (src && (src.includes('index.js') || src.includes('index.min.js'))) {
1607
+ return src.replace(/index(\.min)?\.js/, 'worker.js');
1608
+ }
1609
+ }
1610
+ }
1611
+ return './worker.js';
1612
+ }
1613
+ }
1549
1614
 
1550
1615
  /**
1551
1616
  * <zh/> 布局基类
@@ -1555,14 +1620,17 @@
1555
1620
  class BaseLayout {
1556
1621
  constructor(options) {
1557
1622
  this.supervisor = null;
1558
- this.initialOptions = mergeOptions(this.getDefaultOptions(), options);
1623
+ this.initialOptions = this.mergeOptions(this.getDefaultOptions(), options);
1559
1624
  }
1560
1625
  get options() {
1561
1626
  return this.runtimeOptions || this.initialOptions;
1562
1627
  }
1628
+ mergeOptions(base, patch) {
1629
+ return Object.assign({}, base, patch || {});
1630
+ }
1563
1631
  execute(data, userOptions) {
1564
1632
  return __awaiter(this, void 0, void 0, function* () {
1565
- this.runtimeOptions = mergeOptions(this.initialOptions, userOptions);
1633
+ this.runtimeOptions = this.mergeOptions(this.initialOptions, userOptions);
1566
1634
  const { node, edge, enableWorker } = this.runtimeOptions;
1567
1635
  this.context = new RuntimeContext(data, { node, edge });
1568
1636
  this.model = this.context.graph;
@@ -1627,71 +1695,6 @@
1627
1695
  return !!layout.tick && !!layout.stop;
1628
1696
  }
1629
1697
 
1630
- /**
1631
- * Format value with multiple types into a function that returns a number
1632
- * @param value The value to be formatted
1633
- * @param defaultValue The default value when value is invalid
1634
- * @returns A function that returns a number
1635
- */
1636
- function formatNumberFn(value, defaultValue) {
1637
- // If value is a function, return it directly
1638
- if (isFunction(value)) {
1639
- return value;
1640
- }
1641
- // If value is a number, return a function that returns this number
1642
- if (isNumber(value)) {
1643
- return () => value;
1644
- }
1645
- // For other cases (undefined or invalid values), return default value function
1646
- return () => defaultValue;
1647
- }
1648
- /**
1649
- * Format size config with multiple types into a function that returns a size
1650
- * @param value The value to be formatted
1651
- * @param defaultValue The default value when value is invalid
1652
- * @param resultIsNumber Whether to return a number (max of width/height) or size array
1653
- * @returns A function that returns a size
1654
- */
1655
- function formatSizeFn(value, defaultValue = 10) {
1656
- // If value is undefined, return default value function
1657
- if (!value) {
1658
- return () => defaultValue;
1659
- }
1660
- // If value is a function, return it directly
1661
- if (isFunction(value)) {
1662
- return value;
1663
- }
1664
- // If value is a number, return a function that returns this number
1665
- if (isNumber(value)) {
1666
- return () => value;
1667
- }
1668
- // If value is an array, return max or the array itself
1669
- if (Array.isArray(value)) {
1670
- return () => value;
1671
- }
1672
- // If value is an object with width and height
1673
- if (isObject$1(value) && value.width && value.height) {
1674
- return () => [value.width, value.height];
1675
- }
1676
- return () => defaultValue;
1677
- }
1678
- /**
1679
- * Format nodeSize and nodeSpacing into a function that returns the total size
1680
- * @param nodeSize The size of the node
1681
- * @param nodeSpacing The spacing around the node
1682
- * @param defaultNodeSize The default node size when value is invalid
1683
- * @returns A function that returns the total size (node size + spacing)
1684
- */
1685
- const formatNodeSizeFn = (nodeSize, nodeSpacing, defaultNodeSize = 10) => {
1686
- const nodeSpacingFunc = formatNumberFn(nodeSpacing, 0);
1687
- const nodeSizeFunc = formatSizeFn(nodeSize, defaultNodeSize);
1688
- return (node) => {
1689
- const size = nodeSizeFunc(node);
1690
- const spacing = nodeSpacingFunc(node);
1691
- return Math.max(...parseSize(size)) + spacing;
1692
- };
1693
- };
1694
-
1695
1698
  /**
1696
1699
  * <zh/> 内部图数据结构,用于 antv-dagre 布局算法
1697
1700
  *
@@ -5131,9 +5134,9 @@
5131
5134
  return __awaiter(this, void 0, void 0, function* () {
5132
5135
  const { nodeSize, align, rankdir = 'TB', ranksep, nodesep, edgeLabelSpace, ranker = 'tight-tree', nodeOrder, begin, controlPoints, radial, sortByCombo,
5133
5136
  // focusNode,
5134
- preset, } = options;
5135
- const ranksepfunc = formatNumberFn(ranksep, DEFAULTS_LAYOUT_OPTIONS$8.ranksep);
5136
- const nodesepfunc = formatNumberFn(nodesep, DEFAULTS_LAYOUT_OPTIONS$8.nodesep);
5137
+ preset, ranksepFunc, nodesepFunc, } = options;
5138
+ const ranksepfunc = formatNumberFn(ranksepFunc, ranksep !== null && ranksep !== void 0 ? ranksep : 50);
5139
+ const nodesepfunc = formatNumberFn(nodesepFunc, nodesep !== null && nodesep !== void 0 ? nodesep : 50);
5137
5140
  let horisep = nodesepfunc;
5138
5141
  let vertisep = ranksepfunc;
5139
5142
  if (rankdir === 'LR' || rankdir === 'RL') {
@@ -5148,9 +5151,10 @@
5148
5151
  const edges = this.model.edges();
5149
5152
  nodes.forEach((node) => {
5150
5153
  var _a;
5151
- const size = parseSize(nodeSizeFunc(node));
5152
- const verti = vertisep(node);
5153
- const hori = horisep(node);
5154
+ const raw = node._original;
5155
+ const size = parseSize(nodeSizeFunc(raw));
5156
+ const verti = vertisep(raw);
5157
+ const hori = horisep(raw);
5154
5158
  const width = size[0] + 2 * hori;
5155
5159
  const height = size[1] + 2 * verti;
5156
5160
  const layer = (_a = node.data) === null || _a === void 0 ? void 0 : _a.layer;
@@ -5216,6 +5220,7 @@
5216
5220
  acyclicer: 'greedy',
5217
5221
  ranker,
5218
5222
  rankdir,
5223
+ nodesep,
5219
5224
  align,
5220
5225
  });
5221
5226
  const layoutTopLeft = [0, 0];
@@ -5474,7 +5479,7 @@
5474
5479
  }
5475
5480
  else if (ordering === 'degree') {
5476
5481
  // layout according to the descent order of degrees
5477
- orderByDegree(this.model);
5482
+ orderByDegree(this.model, 'asc');
5478
5483
  }
5479
5484
  let { radius, startRadius, endRadius } = this.options;
5480
5485
  const nodes = this.model.nodes();
@@ -7320,25 +7325,17 @@
7320
7325
  }
7321
7326
 
7322
7327
  const DEFAULTS_LAYOUT_OPTIONS$6 = {
7323
- centerStrength: 1,
7324
- edgeId: (d) => String(d.id),
7325
- linkDistance: 30,
7326
- edgeStrength: undefined,
7327
- edgeIterations: 1,
7328
+ link: {
7329
+ id: (d) => String(d.id),
7330
+ },
7331
+ manyBody: {
7332
+ strength: -30,
7333
+ },
7328
7334
  preventOverlap: false,
7329
7335
  nodeSize: 10,
7330
7336
  nodeSpacing: 0,
7331
- collideStrength: 1,
7332
- collideIterations: 1,
7333
- nodeStrength: -30,
7334
- distanceMin: undefined,
7335
- distanceMax: undefined,
7336
- theta: undefined,
7337
- alpha: 1,
7338
- alphaMin: 0.001,
7339
- alphaDecay: 1 - Math.pow(0.001, 1 / 300),
7340
- alphaTarget: 0,
7341
- velocityDecay: 0.4,
7337
+ x: false,
7338
+ y: false,
7342
7339
  clustering: false,
7343
7340
  clusterNodeStrength: -1,
7344
7341
  clusterEdgeStrength: 0.1,
@@ -7453,14 +7450,7 @@
7453
7450
  });
7454
7451
  }
7455
7452
  parseOptions(options) {
7456
- var _a, _b;
7457
7453
  const _ = options;
7458
- // process nodeSize
7459
- if (_.collide && ((_a = _.collide) === null || _a === void 0 ? void 0 : _a.radius) === undefined) {
7460
- _.collide = _.collide || {};
7461
- // @ts-ignore
7462
- _.collide.radius = (_b = _.nodeSize) !== null && _b !== void 0 ? _b : 10;
7463
- }
7464
7454
  // process iterations
7465
7455
  if (_.iterations === undefined) {
7466
7456
  if (_.link && _.link.iterations === undefined) {
@@ -7555,20 +7545,17 @@
7555
7545
  this.setupClusterForce(simulation, options);
7556
7546
  }
7557
7547
  getCenterOptions(options) {
7558
- if (!options.width ||
7559
- !options.height ||
7560
- options.centerStrength !== undefined) {
7561
- const viewport = normalizeViewport({
7562
- width: options.width,
7563
- height: options.height,
7564
- });
7565
- return assignDefined({}, options.center || {}, {
7566
- x: viewport.width / 2,
7567
- y: viewport.height / 2,
7568
- strength: options.centerStrength,
7569
- });
7570
- }
7571
- return undefined;
7548
+ if (options.center === false)
7549
+ return undefined;
7550
+ const viewport = normalizeViewport({
7551
+ width: options.width,
7552
+ height: options.height,
7553
+ });
7554
+ return assignDefined({}, options.center || {}, {
7555
+ x: viewport.width / 2,
7556
+ y: viewport.height / 2,
7557
+ strength: options.centerStrength,
7558
+ });
7572
7559
  }
7573
7560
  setupCenterForce(simulation, options) {
7574
7561
  const center = this.getCenterOptions(options);
@@ -7592,19 +7579,14 @@
7592
7579
  }
7593
7580
  }
7594
7581
  getManyBodyOptions(options) {
7595
- if (options.manyBody !== undefined ||
7596
- options.nodeStrength !== undefined ||
7597
- options.distanceMin !== undefined ||
7598
- options.distanceMax !== undefined ||
7599
- options.theta !== undefined) {
7600
- return assignDefined({}, options.manyBody || {}, {
7601
- strength: options.nodeStrength,
7602
- distanceMin: options.distanceMin,
7603
- distanceMax: options.distanceMax,
7604
- theta: options.theta,
7605
- });
7606
- }
7607
- return undefined;
7582
+ if (options.manyBody === false)
7583
+ return undefined;
7584
+ return assignDefined({}, options.manyBody || {}, {
7585
+ strength: options.nodeStrength,
7586
+ distanceMin: options.distanceMin,
7587
+ distanceMax: options.distanceMax,
7588
+ theta: options.theta,
7589
+ });
7608
7590
  }
7609
7591
  setupManyBodyForce(simulation, options) {
7610
7592
  const manyBody = this.getManyBodyOptions(options);
@@ -7630,19 +7612,14 @@
7630
7612
  }
7631
7613
  }
7632
7614
  getLinkOptions(options) {
7633
- if (options.link ||
7634
- options.edgeId !== undefined ||
7635
- options.linkDistance !== undefined ||
7636
- options.edgeStrength !== undefined ||
7637
- options.edgeIterations !== undefined) {
7638
- return assignDefined({}, options.link || {}, {
7639
- id: options.edgeId,
7640
- distance: options.linkDistance,
7641
- strength: options.edgeStrength,
7642
- iterations: options.edgeIterations,
7643
- });
7644
- }
7645
- return undefined;
7615
+ if (options.link === false)
7616
+ return undefined;
7617
+ return assignDefined({}, options.link || {}, {
7618
+ id: options.edgeId,
7619
+ distance: options.linkDistance,
7620
+ strength: options.edgeStrength,
7621
+ iterations: options.edgeIterations,
7622
+ });
7646
7623
  }
7647
7624
  setupLinkForce(simulation, options) {
7648
7625
  const edges = this.model.edges();
@@ -7669,23 +7646,17 @@
7669
7646
  }
7670
7647
  }
7671
7648
  getCollisionOptions(options) {
7672
- if (!options.preventOverlap)
7649
+ if (options.preventOverlap === false &&
7650
+ (options.collide === false || options.collide === undefined))
7673
7651
  return undefined;
7674
- if (options.collide !== undefined ||
7675
- options.nodeSize !== undefined ||
7676
- options.nodeSpacing !== undefined ||
7677
- options.collideStrength !== undefined ||
7678
- options.collideIterations !== undefined) {
7679
- const radius = options.nodeSize || options.nodeSpacing
7680
- ? (d) => formatNodeSizeFn(options.nodeSize, options.nodeSpacing)(d._original) / 2
7681
- : undefined;
7682
- return assignDefined({}, options.collide || {}, {
7683
- radius,
7684
- strength: options.collideStrength,
7685
- iterations: options.collideIterations,
7686
- });
7687
- }
7688
- return undefined;
7652
+ const radius = options.nodeSize || options.nodeSpacing
7653
+ ? (d) => formatNodeSizeFn(options.nodeSize, options.nodeSpacing)(d._original) / 2
7654
+ : undefined;
7655
+ return assignDefined({}, options.collide || {}, {
7656
+ radius: (options.collide && options.collide.radius) || radius,
7657
+ strength: options.collideStrength,
7658
+ iterations: options.collideIterations,
7659
+ });
7689
7660
  }
7690
7661
  setupCollisionForce(simulation, options) {
7691
7662
  const collide = this.getCollisionOptions(options);
@@ -7710,18 +7681,13 @@
7710
7681
  }
7711
7682
  getXForceOptions(options) {
7712
7683
  var _a;
7713
- if (options.x !== undefined ||
7714
- options.forceXPosition !== undefined ||
7715
- options.forceXStrength !== undefined ||
7716
- options.width !== undefined ||
7717
- options.height !== undefined) {
7718
- const center = this.getCenterOptions(options);
7719
- return assignDefined({}, options.x || {}, {
7720
- x: (_a = options.forceXPosition) !== null && _a !== void 0 ? _a : (center && center.x),
7721
- strength: options.forceXStrength,
7722
- });
7723
- }
7724
- return undefined;
7684
+ if (options.x === false)
7685
+ return undefined;
7686
+ const center = this.getCenterOptions(options);
7687
+ return assignDefined({}, options.x || {}, {
7688
+ x: (_a = options.forceXPosition) !== null && _a !== void 0 ? _a : (center && center.x),
7689
+ strength: options.forceXStrength,
7690
+ });
7725
7691
  }
7726
7692
  setupXForce(simulation, options) {
7727
7693
  const x = this.getXForceOptions(options);
@@ -7744,18 +7710,13 @@
7744
7710
  }
7745
7711
  getYForceOptions(options) {
7746
7712
  var _a;
7747
- if (options.y !== undefined ||
7748
- options.forceYPosition !== undefined ||
7749
- options.forceYStrength !== undefined ||
7750
- options.width !== undefined ||
7751
- options.height !== undefined) {
7752
- const center = this.getCenterOptions(options);
7753
- return assignDefined({}, options.y || {}, {
7754
- y: (_a = options.forceYPosition) !== null && _a !== void 0 ? _a : (center && center.y),
7755
- strength: options.forceYStrength,
7756
- });
7757
- }
7758
- return undefined;
7713
+ if (options.y === false)
7714
+ return undefined;
7715
+ const center = this.getCenterOptions(options);
7716
+ return assignDefined({}, options.y || {}, {
7717
+ y: (_a = options.forceYPosition) !== null && _a !== void 0 ? _a : (center && center.y),
7718
+ strength: options.forceYStrength,
7719
+ });
7759
7720
  }
7760
7721
  setupYForce(simulation, options) {
7761
7722
  const y = this.getYForceOptions(options);
@@ -32479,9 +32440,9 @@ ${indent}columns: ${matrix.columns}
32479
32440
  ? { type: 'force', preventOverlap: true }
32480
32441
  : { type: 'concentric', preventOverlap: true },
32481
32442
  nodeSize: 20,
32482
- nodeSpacing: 10,
32483
- comboPadding: 20,
32484
- comboSpacing: 80,
32443
+ nodeSpacing: 0,
32444
+ comboPadding: 10,
32445
+ comboSpacing: 0,
32485
32446
  };
32486
32447
  const ROOT_ID = 'root';
32487
32448
  /**
@@ -32799,7 +32760,6 @@ ${indent}columns: ${matrix.columns}
32799
32760
  exports.isArray = isArray;
32800
32761
  exports.isLayoutWithIterations = isLayoutWithIterations;
32801
32762
  exports.johnson = johnson;
32802
- exports.mergeOptions = mergeOptions;
32803
32763
  exports.normalizeViewport = normalizeViewport;
32804
32764
  exports.orderByDegree = orderByDegree;
32805
32765
  exports.orderById = orderById;