force-3d-graph 1.2.5 → 1.2.6

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.
@@ -92,12 +92,12 @@ class ft extends at {
92
92
  }, this.saveState = function() {
93
93
  t.target0.copy(t.target), t.position0.copy(t.object.position), t.zoom0 = t.object.zoom;
94
94
  }, this.reset = function() {
95
- t.target.copy(t.target0), t.object.position.copy(t.position0), t.object.zoom = t.zoom0, t.object.updateProjectionMatrix(), t.dispatchEvent(Pe), t.update(), i = o.NONE;
95
+ t.target.copy(t.target0), t.object.position.copy(t.position0), t.object.zoom = t.zoom0, t.object.updateProjectionMatrix(), t.dispatchEvent(Pe), t.update(), o = i.NONE;
96
96
  }, this.update = function() {
97
97
  const n = new S(), g = new Te().setFromUnitVectors(e.up, new S(0, 1, 0)), v = g.clone().invert(), w = new S(), C = new Te(), F = new S(), z = 2 * Math.PI;
98
98
  return function(it = null) {
99
99
  const Se = t.object.position;
100
- n.copy(Se).sub(t.target), n.applyQuaternion(g), r.setFromVector3(n), t.autoRotate && i === o.NONE && B(Ae(it)), t.enableDamping ? (r.theta += c.theta * t.dampingFactor, r.phi += c.phi * t.dampingFactor) : (r.theta += c.theta, r.phi += c.phi);
100
+ n.copy(Se).sub(t.target), n.applyQuaternion(g), r.setFromVector3(n), t.autoRotate && o === i.NONE && B(Ae(it)), t.enableDamping ? (r.theta += c.theta * t.dampingFactor, r.phi += c.phi * t.dampingFactor) : (r.theta += c.theta, r.phi += c.phi);
101
101
  let I = t.minAzimuthAngle, L = t.maxAzimuthAngle;
102
102
  isFinite(I) && isFinite(L) && (I < -Math.PI ? I += z : I > Math.PI && (I -= z), L < -Math.PI ? L += z : L > Math.PI && (L -= z), I <= L ? r.theta = Math.max(I, Math.min(L, r.theta)) : r.theta = r.theta > (I + L) / 2 ? Math.max(I, r.theta) : Math.min(L, r.theta)), r.phi = Math.max(t.minPolarAngle, Math.min(t.maxPolarAngle, r.phi)), r.makeSafe(), t.enableDamping === !0 ? t.target.addScaledVector(p, t.dampingFactor) : t.target.add(p), t.target.sub(t.cursor), t.target.clampLength(t.minTargetRadius, t.maxTargetRadius), t.target.add(t.cursor), t.zoomToCursor && H || t.object.isOrthographicCamera ? r.radius = ne(r.radius) : r.radius = ne(r.radius * h), n.setFromSpherical(r), n.applyQuaternion(v), Se.copy(t.target).add(n), t.object.lookAt(t.target), t.enableDamping === !0 ? (c.theta *= 1 - t.dampingFactor, c.phi *= 1 - t.dampingFactor, p.multiplyScalar(1 - t.dampingFactor)) : (c.set(0, 0, 0), p.set(0, 0, 0));
103
103
  let le = !1;
@@ -122,7 +122,7 @@ class ft extends at {
122
122
  }(), this.dispose = function() {
123
123
  t.domElement.removeEventListener("contextmenu", Ce), t.domElement.removeEventListener("pointerdown", Me), t.domElement.removeEventListener("pointercancel", K), t.domElement.removeEventListener("wheel", we), t.domElement.removeEventListener("pointermove", ae), t.domElement.removeEventListener("pointerup", K), t._domElementKeyEvents !== null && (t._domElementKeyEvents.removeEventListener("keydown", re), t._domElementKeyEvents = null);
124
124
  };
125
- const t = this, o = {
125
+ const t = this, i = {
126
126
  NONE: -1,
127
127
  ROTATE: 0,
128
128
  DOLLY: 1,
@@ -132,7 +132,7 @@ class ft extends at {
132
132
  TOUCH_DOLLY_PAN: 5,
133
133
  TOUCH_DOLLY_ROTATE: 6
134
134
  };
135
- let i = o.NONE;
135
+ let o = i.NONE;
136
136
  const a = 1e-6, r = new ze(), c = new ze();
137
137
  let h = 1;
138
138
  const p = new S(), x = new T(), m = new T(), u = new T(), f = new T(), b = new T(), M = new T(), N = new T(), O = new T(), R = new T(), Y = new S(), k = new T();
@@ -296,7 +296,7 @@ class ft extends at {
296
296
  t.enabled !== !1 && (n.pointerType === "touch" ? et(n) : We(n));
297
297
  }
298
298
  function K(n) {
299
- st(n), E.length === 0 && (t.domElement.releasePointerCapture(n.pointerId), t.domElement.removeEventListener("pointermove", ae), t.domElement.removeEventListener("pointerup", K)), t.dispatchEvent(Re), i = o.NONE;
299
+ st(n), E.length === 0 && (t.domElement.releasePointerCapture(n.pointerId), t.domElement.removeEventListener("pointermove", ae), t.domElement.removeEventListener("pointerup", K)), t.dispatchEvent(Re), o = i.NONE;
300
300
  }
301
301
  function qe(n) {
302
302
  let g;
@@ -316,49 +316,49 @@ class ft extends at {
316
316
  switch (g) {
317
317
  case $.DOLLY:
318
318
  if (t.enableZoom === !1) return;
319
- je(n), i = o.DOLLY;
319
+ je(n), o = i.DOLLY;
320
320
  break;
321
321
  case $.ROTATE:
322
322
  if (n.ctrlKey || n.metaKey || n.shiftKey) {
323
323
  if (t.enablePan === !1) return;
324
- ue(n), i = o.PAN;
324
+ ue(n), o = i.PAN;
325
325
  } else {
326
326
  if (t.enableRotate === !1) return;
327
- ge(n), i = o.ROTATE;
327
+ ge(n), o = i.ROTATE;
328
328
  }
329
329
  break;
330
330
  case $.PAN:
331
331
  if (n.ctrlKey || n.metaKey || n.shiftKey) {
332
332
  if (t.enableRotate === !1) return;
333
- ge(n), i = o.ROTATE;
333
+ ge(n), o = i.ROTATE;
334
334
  } else {
335
335
  if (t.enablePan === !1) return;
336
- ue(n), i = o.PAN;
336
+ ue(n), o = i.PAN;
337
337
  }
338
338
  break;
339
339
  default:
340
- i = o.NONE;
340
+ o = i.NONE;
341
341
  }
342
- i !== o.NONE && t.dispatchEvent(ce);
342
+ o !== i.NONE && t.dispatchEvent(ce);
343
343
  }
344
344
  function We(n) {
345
- switch (i) {
346
- case o.ROTATE:
345
+ switch (o) {
346
+ case i.ROTATE:
347
347
  if (t.enableRotate === !1) return;
348
348
  $e(n);
349
349
  break;
350
- case o.DOLLY:
350
+ case i.DOLLY:
351
351
  if (t.enableZoom === !1) return;
352
352
  Ge(n);
353
353
  break;
354
- case o.PAN:
354
+ case i.PAN:
355
355
  if (t.enablePan === !1) return;
356
356
  Ye(n);
357
357
  break;
358
358
  }
359
359
  }
360
360
  function we(n) {
361
- t.enabled === !1 || t.enableZoom === !1 || i !== o.NONE || (n.preventDefault(), t.dispatchEvent(ce), Be(Ze(n)), t.dispatchEvent(Re));
361
+ t.enabled === !1 || t.enableZoom === !1 || o !== i.NONE || (n.preventDefault(), t.dispatchEvent(ce), Be(Ze(n)), t.dispatchEvent(Re));
362
362
  }
363
363
  function Ze(n) {
364
364
  const g = n.deltaMode, v = {
@@ -391,55 +391,55 @@ class ft extends at {
391
391
  switch (t.touches.ONE) {
392
392
  case G.ROTATE:
393
393
  if (t.enableRotate === !1) return;
394
- fe(n), i = o.TOUCH_ROTATE;
394
+ fe(n), o = i.TOUCH_ROTATE;
395
395
  break;
396
396
  case G.PAN:
397
397
  if (t.enablePan === !1) return;
398
- me(n), i = o.TOUCH_PAN;
398
+ me(n), o = i.TOUCH_PAN;
399
399
  break;
400
400
  default:
401
- i = o.NONE;
401
+ o = i.NONE;
402
402
  }
403
403
  break;
404
404
  case 2:
405
405
  switch (t.touches.TWO) {
406
406
  case G.DOLLY_PAN:
407
407
  if (t.enableZoom === !1 && t.enablePan === !1) return;
408
- Ue(n), i = o.TOUCH_DOLLY_PAN;
408
+ Ue(n), o = i.TOUCH_DOLLY_PAN;
409
409
  break;
410
410
  case G.DOLLY_ROTATE:
411
411
  if (t.enableZoom === !1 && t.enableRotate === !1) return;
412
- _e(n), i = o.TOUCH_DOLLY_ROTATE;
412
+ _e(n), o = i.TOUCH_DOLLY_ROTATE;
413
413
  break;
414
414
  default:
415
- i = o.NONE;
415
+ o = i.NONE;
416
416
  }
417
417
  break;
418
418
  default:
419
- i = o.NONE;
419
+ o = i.NONE;
420
420
  }
421
- i !== o.NONE && t.dispatchEvent(ce);
421
+ o !== i.NONE && t.dispatchEvent(ce);
422
422
  }
423
423
  function et(n) {
424
- switch (Ne(n), i) {
425
- case o.TOUCH_ROTATE:
424
+ switch (Ne(n), o) {
425
+ case i.TOUCH_ROTATE:
426
426
  if (t.enableRotate === !1) return;
427
427
  xe(n), t.update();
428
428
  break;
429
- case o.TOUCH_PAN:
429
+ case i.TOUCH_PAN:
430
430
  if (t.enablePan === !1) return;
431
431
  be(n), t.update();
432
432
  break;
433
- case o.TOUCH_DOLLY_PAN:
433
+ case i.TOUCH_DOLLY_PAN:
434
434
  if (t.enableZoom === !1 && t.enablePan === !1) return;
435
435
  Xe(n), t.update();
436
436
  break;
437
- case o.TOUCH_DOLLY_ROTATE:
437
+ case i.TOUCH_DOLLY_ROTATE:
438
438
  if (t.enableZoom === !1 && t.enableRotate === !1) return;
439
439
  Ve(n), t.update();
440
440
  break;
441
441
  default:
442
- i = o.NONE;
442
+ o = i.NONE;
443
443
  }
444
444
  }
445
445
  function Ce(n) {
@@ -478,14 +478,14 @@ class mt {
478
478
  this.container = e, this.scene = new y.Scene(), this.scene.background = new y.Color(
479
479
  s.backgroundColor ?? 657930
480
480
  );
481
- const { width: t, height: o } = ke(e), i = s.cameraFov ?? 75;
482
- this.camera = new y.PerspectiveCamera(i, t / o, 0.1, 2e3);
481
+ const { width: t, height: i } = ke(e), o = s.cameraFov ?? 75;
482
+ this.camera = new y.PerspectiveCamera(o, t / i, 0.1, 2e3);
483
483
  const a = s.cameraPosition ?? { x: 0, y: 0, z: 80 };
484
484
  this.camera.position.set(a.x, a.y, a.z), this.renderer = new y.WebGLRenderer({
485
485
  antialias: !0,
486
486
  alpha: !0,
487
487
  powerPreference: "high-performance"
488
- }), this.renderer.setSize(t, o), this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)), this.renderer.toneMapping = y.ACESFilmicToneMapping, this.renderer.toneMappingExposure = 1, this.renderer.shadowMap.enabled = !0, this.renderer.shadowMap.type = y.PCFSoftShadowMap, e.appendChild(this.renderer.domElement), this.controls = new ft(this.camera, this.renderer.domElement), this.controls.enableDamping = !0, this.controls.dampingFactor = 0.05, this.controls.rotateSpeed = 0.8, this.controls.zoomSpeed = 1.2, this.controls.minDistance = 10, this.controls.maxDistance = 2e3, this.setupLighting(), this.resizeHandler = this.onWindowResize.bind(this), window.addEventListener("resize", this.resizeHandler);
488
+ }), this.renderer.setSize(t, i), this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)), this.renderer.toneMapping = y.ACESFilmicToneMapping, this.renderer.toneMappingExposure = 1, this.renderer.shadowMap.enabled = !0, this.renderer.shadowMap.type = y.PCFSoftShadowMap, e.appendChild(this.renderer.domElement), this.controls = new ft(this.camera, this.renderer.domElement), this.controls.enableDamping = !0, this.controls.dampingFactor = 0.05, this.controls.rotateSpeed = 0.8, this.controls.zoomSpeed = 1.2, this.controls.minDistance = 10, this.controls.maxDistance = 2e3, this.setupLighting(), this.resizeHandler = this.onWindowResize.bind(this), window.addEventListener("resize", this.resizeHandler);
489
489
  }
490
490
  /**
491
491
  * Sets up scene lighting for gradient glass on dark background
@@ -497,10 +497,10 @@ class mt {
497
497
  s.position.set(50, 60, 40), s.castShadow = !0, s.shadow.mapSize.width = 1024, s.shadow.mapSize.height = 1024, this.scene.add(s);
498
498
  const t = new y.DirectionalLight(16773344, 0.4);
499
499
  t.position.set(-50, 30, -40), this.scene.add(t);
500
- const o = new y.DirectionalLight(16777215, 0.3);
501
- o.position.set(0, -30, -50), this.scene.add(o);
502
- const i = new y.PointLight(16750950, 0.5, 150);
503
- i.position.set(40, 20, 40), this.scene.add(i);
500
+ const i = new y.DirectionalLight(16777215, 0.3);
501
+ i.position.set(0, -30, -50), this.scene.add(i);
502
+ const o = new y.PointLight(16750950, 0.5, 150);
503
+ o.position.set(40, 20, 40), this.scene.add(o);
504
504
  const a = new y.PointLight(16764057, 0.4, 150);
505
505
  a.position.set(-40, -20, 40), this.scene.add(a);
506
506
  const r = new y.PointLight(6724095, 0.2, 100);
@@ -588,20 +588,20 @@ const V = class V {
588
588
  return !1;
589
589
  if (this.nodes.has(e.id))
590
590
  return console.warn(`[ForceGraph3D] Node with id "${e.id}" already exists`), !1;
591
- const t = Math.max(50, Math.cbrt(V.expectedNodeCount) * 10), o = e.position ?? {
591
+ const t = Math.max(50, Math.cbrt(V.expectedNodeCount) * 10), i = e.position ?? {
592
592
  x: (Math.random() - 0.5) * t,
593
593
  y: (Math.random() - 0.5) * t,
594
594
  z: (Math.random() - 0.5) * t
595
- }, i = {
595
+ }, o = {
596
596
  ...e,
597
- position: o,
597
+ position: i,
598
598
  velocity: { x: 0, y: 0, z: 0 },
599
599
  mass: 1
600
600
  }, a = this.nodeFactory.createNode(
601
- { ...e, position: o },
601
+ { ...e, position: i },
602
602
  s
603
603
  );
604
- return this.sceneManager.add(a.group), this.nodes.set(e.id, i), this.nodeObjects.set(e.id, a), !0;
604
+ return this.sceneManager.add(a.group), this.nodes.set(e.id, o), this.nodeObjects.set(e.id, a), !0;
605
605
  }
606
606
  /**
607
607
  * Removes a node from the graph
@@ -615,17 +615,17 @@ const V = class V {
615
615
  * Updates a node's properties
616
616
  */
617
617
  updateNode(e, s) {
618
- const t = this.nodes.get(e), o = this.nodeObjects.get(e);
619
- return !t || !o ? (console.warn(`[ForceGraph3D] Node "${e}" not found`), !1) : (s.label !== void 0 && (t.label = s.label, this.nodeFactory.updateNodeLabel(o, s.label)), s.color !== void 0 && (t.color = s.color, this.nodeFactory.updateNodeColor(o, s.color)), Object.keys(s).forEach((i) => {
620
- i !== "id" && i !== "label" && i !== "color" && i !== "position" && (t[i] = s[i]);
618
+ const t = this.nodes.get(e), i = this.nodeObjects.get(e);
619
+ return !t || !i ? (console.warn(`[ForceGraph3D] Node "${e}" not found`), !1) : (s.label !== void 0 && (t.label = s.label, this.nodeFactory.updateNodeLabel(i, s.label)), s.color !== void 0 && (t.color = s.color, this.nodeFactory.updateNodeColor(i, s.color)), Object.keys(s).forEach((o) => {
620
+ o !== "id" && o !== "label" && o !== "color" && o !== "position" && (t[o] = s[o]);
621
621
  }), !0);
622
622
  }
623
623
  /**
624
624
  * Updates a node's position (called by physics engine)
625
625
  */
626
626
  updateNodePosition(e, s) {
627
- const t = this.nodes.get(e), o = this.nodeObjects.get(e);
628
- t && o && (t.position = s, o.group.position.set(s.x, s.y, s.z));
627
+ const t = this.nodes.get(e), i = this.nodeObjects.get(e);
628
+ t && i && (t.position = s, i.group.position.set(s.x, s.y, s.z));
629
629
  }
630
630
  /**
631
631
  * Updates a node's LOD level
@@ -726,14 +726,14 @@ class yt {
726
726
  const s = D(e.source, e.target);
727
727
  if (this.edgeKeySet.has(s))
728
728
  return console.warn(`[ForceGraph3D] Edge "${e.source}" -> "${e.target}" already exists`), !1;
729
- const t = this.nodeManager.getNode(e.source), o = this.nodeManager.getNode(e.target), i = this.edgeFactory.createEdge(
729
+ const t = this.nodeManager.getNode(e.source), i = this.nodeManager.getNode(e.target), o = this.edgeFactory.createEdge(
730
730
  e,
731
731
  t,
732
- o,
732
+ i,
733
733
  t.position,
734
- o.position
734
+ i.position
735
735
  );
736
- return this.sceneManager.add(i.line), this.edges.push(e), this.edgeObjects.push(i), this.edgeKeySet.add(s), !0;
736
+ return this.sceneManager.add(o.line), this.edges.push(e), this.edgeObjects.push(o), this.edgeKeySet.add(s), !0;
737
737
  }
738
738
  /**
739
739
  * Removes an edge from the graph
@@ -743,13 +743,13 @@ class yt {
743
743
  const t = D(e, s);
744
744
  if (!this.edgeKeySet.has(t))
745
745
  return !1;
746
- const o = this.edges.findIndex(
746
+ const i = this.edges.findIndex(
747
747
  (a) => D(a.source, a.target) === t
748
748
  );
749
- if (o === -1)
749
+ if (i === -1)
750
750
  return !1;
751
- const i = this.edgeObjects[o];
752
- return this.sceneManager.remove(i.line), this.edgeFactory.disposeEdge(i), this.edges.splice(o, 1), this.edgeObjects.splice(o, 1), this.edgeKeySet.delete(t), this.highlightedEdgeKey === t && (this.highlightedEdgeKey = null), !0;
751
+ const o = this.edgeObjects[i];
752
+ return this.sceneManager.remove(o.line), this.edgeFactory.disposeEdge(o), this.edges.splice(i, 1), this.edgeObjects.splice(i, 1), this.edgeKeySet.delete(t), this.highlightedEdgeKey === t && (this.highlightedEdgeKey = null), !0;
753
753
  }
754
754
  /**
755
755
  * Highlights an edge
@@ -757,10 +757,10 @@ class yt {
757
757
  highlightEdge(e, s) {
758
758
  const t = D(e, s);
759
759
  this.highlightedEdgeKey && this.highlightedEdgeKey !== t && this.unhighlightCurrentEdge();
760
- const o = this.edges.findIndex(
761
- (i) => D(i.source, i.target) === t
760
+ const i = this.edges.findIndex(
761
+ (o) => D(o.source, o.target) === t
762
762
  );
763
- o !== -1 && (this.edgeFactory.highlightEdge(this.edgeObjects[o]), this.highlightedEdgeKey = t);
763
+ i !== -1 && (this.edgeFactory.highlightEdge(this.edgeObjects[i]), this.highlightedEdgeKey = t);
764
764
  }
765
765
  /**
766
766
  * Unhighlights the currently highlighted edge
@@ -803,11 +803,11 @@ class yt {
803
803
  */
804
804
  updateEdgePositions() {
805
805
  this.edgeObjects.forEach((e, s) => {
806
- const t = this.edges[s], o = this.nodeManager.getNode(t.source), i = this.nodeManager.getNode(t.target);
807
- o && i && this.edgeFactory.updateEdgePositions(
806
+ const t = this.edges[s], i = this.nodeManager.getNode(t.source), o = this.nodeManager.getNode(t.target);
807
+ i && o && this.edgeFactory.updateEdgePositions(
808
808
  e,
809
- o.position,
810
- i.position
809
+ i.position,
810
+ o.position
811
811
  );
812
812
  });
813
813
  }
@@ -861,14 +861,36 @@ class Le {
861
861
  // Skip repulsion beyond this distance
862
862
  l(this, "REPULSION_CUTOFF_SQ");
863
863
  // Precomputed cutoff²
864
- l(this, "GRAVITY_STRENGTH", 0.02);
864
+ l(this, "GRAVITY_STRENGTH", 0.05);
865
865
  // Centering force strength
866
+ // Hub node pinning
867
+ l(this, "pinnedNodeId", null);
866
868
  // Simulation state
867
869
  l(this, "alpha", 1);
868
870
  l(this, "alphaDecay", 0.0228);
869
871
  l(this, "alphaMin", 1e-3);
870
872
  l(this, "alphaTarget", 0);
871
- this.nodes = e, this.edges = s, this.repulsionStrength = t.repulsionStrength ?? 100, this.attractionStrength = t.attractionStrength ?? 0.01, this.damping = t.damping ?? 0.9, this.useBarnesHut = t.useBarnesHut ?? !1, this.barnesHutTheta = t.barnesHutTheta ?? 0.5, this.REPULSION_CUTOFF_SQ = this.REPULSION_CUTOFF * this.REPULSION_CUTOFF;
873
+ this.nodes = e, this.edges = s, this.repulsionStrength = t.repulsionStrength ?? 100, this.attractionStrength = t.attractionStrength ?? 0.01, this.damping = t.damping ?? 0.9, this.useBarnesHut = t.useBarnesHut ?? !1, this.barnesHutTheta = t.barnesHutTheta ?? 0.5, this.REPULSION_CUTOFF_SQ = this.REPULSION_CUTOFF * this.REPULSION_CUTOFF, this.initializeNodeMassAndPin();
874
+ }
875
+ /**
876
+ * Assigns mass proportional to node degree (connection count) and
877
+ * pins the most-connected hub node at the origin.
878
+ */
879
+ initializeNodeMassAndPin() {
880
+ const e = /* @__PURE__ */ new Map();
881
+ for (const i of this.edges)
882
+ e.set(i.source, (e.get(i.source) || 0) + 1), e.set(i.target, (e.get(i.target) || 0) + 1);
883
+ let s = 0, t = null;
884
+ for (const [i, o] of e) {
885
+ o > s && (s = o, t = i);
886
+ const a = this.nodes.get(i);
887
+ a && (a.mass = 1 + Math.log2(1 + o));
888
+ }
889
+ if (t && s > 10) {
890
+ this.pinnedNodeId = t;
891
+ const i = this.nodes.get(t);
892
+ i && (i.position.x = 0, i.position.y = 0, i.position.z = 0, i.velocity.x = 0, i.velocity.y = 0, i.velocity.z = 0);
893
+ }
872
894
  }
873
895
  /**
874
896
  * Computes effective repulsion strength scaled by node count.
@@ -891,15 +913,15 @@ class Le {
891
913
  */
892
914
  calculateRepulsionBruteForce() {
893
915
  const e = Array.from(this.nodes.values()), s = e.length, t = this.getEffectiveRepulsion();
894
- for (let o = 0; o < s; o++) {
895
- const i = e[o];
896
- for (let a = o + 1; a < s; a++) {
897
- const r = e[a], c = r.position.x - i.position.x, h = r.position.y - i.position.y, p = r.position.z - i.position.z;
916
+ for (let i = 0; i < s; i++) {
917
+ const o = e[i];
918
+ for (let a = i + 1; a < s; a++) {
919
+ const r = e[a], c = r.position.x - o.position.x, h = r.position.y - o.position.y, p = r.position.z - o.position.z;
898
920
  let x = c * c + h * h + p * p;
899
921
  if (x > this.REPULSION_CUTOFF_SQ) continue;
900
922
  x < 0.01 && (x = 0.01);
901
923
  const m = Math.sqrt(x), u = t * this.alpha / x, f = c / m * u, b = h / m * u, M = p / m * u;
902
- i.velocity.x -= f / i.mass, i.velocity.y -= b / i.mass, i.velocity.z -= M / i.mass, r.velocity.x += f / r.mass, r.velocity.y += b / r.mass, r.velocity.z += M / r.mass;
924
+ o.velocity.x -= f / o.mass, o.velocity.y -= b / o.mass, o.velocity.z -= M / o.mass, r.velocity.x += f / r.mass, r.velocity.y += b / r.mass, r.velocity.z += M / r.mass;
903
925
  }
904
926
  }
905
927
  }
@@ -920,12 +942,12 @@ class Le {
920
942
  return;
921
943
  }
922
944
  if (s.mass === 0) return;
923
- const t = s.centerOfMass.x - e.position.x, o = s.centerOfMass.y - e.position.y, i = s.centerOfMass.z - e.position.z, a = t * t + o * o + i * i;
945
+ const t = s.centerOfMass.x - e.position.x, i = s.centerOfMass.y - e.position.y, o = s.centerOfMass.z - e.position.z, a = t * t + i * i + o * o;
924
946
  if (a > this.REPULSION_CUTOFF_SQ) return;
925
947
  const r = Math.sqrt(a), c = this.getEffectiveRepulsion();
926
948
  if (r > 0 && s.size / r < this.barnesHutTheta) {
927
949
  const h = Math.max(a, 0.01), p = c * this.alpha * s.mass / h;
928
- e.velocity.x -= t / r * p / e.mass, e.velocity.y -= o / r * p / e.mass, e.velocity.z -= i / r * p / e.mass;
950
+ e.velocity.x -= t / r * p / e.mass, e.velocity.y -= i / r * p / e.mass, e.velocity.z -= o / r * p / e.mass;
929
951
  } else
930
952
  for (const h of s.children)
931
953
  h && this.calculateForceFromOctree(e, h);
@@ -934,12 +956,12 @@ class Le {
934
956
  * Apply repulsion between two nodes (with cutoff)
935
957
  */
936
958
  applyRepulsionBetween(e, s) {
937
- const t = s.position.x - e.position.x, o = s.position.y - e.position.y, i = s.position.z - e.position.z;
938
- let a = t * t + o * o + i * i;
959
+ const t = s.position.x - e.position.x, i = s.position.y - e.position.y, o = s.position.z - e.position.z;
960
+ let a = t * t + i * i + o * o;
939
961
  if (a > this.REPULSION_CUTOFF_SQ) return;
940
962
  a < 0.01 && (a = 0.01);
941
963
  const r = Math.sqrt(a), h = this.getEffectiveRepulsion() * this.alpha / a;
942
- e.velocity.x -= t / r * h / e.mass, e.velocity.y -= o / r * h / e.mass, e.velocity.z -= i / r * h / e.mass;
964
+ e.velocity.x -= t / r * h / e.mass, e.velocity.y -= i / r * h / e.mass, e.velocity.z -= o / r * h / e.mass;
943
965
  }
944
966
  /**
945
967
  * Calculate attraction forces along edges
@@ -947,12 +969,12 @@ class Le {
947
969
  calculateAttraction() {
948
970
  const e = this.nodes.size, s = e > 500 ? 1 + Math.log10(e / 500) : 1;
949
971
  for (const t of this.edges) {
950
- const o = this.nodes.get(t.source), i = this.nodes.get(t.target);
951
- if (!o || !i) continue;
952
- const a = i.position.x - o.position.x, r = i.position.y - o.position.y, c = i.position.z - o.position.z, h = Math.sqrt(a * a + r * r + c * c);
972
+ const i = this.nodes.get(t.source), o = this.nodes.get(t.target);
973
+ if (!i || !o) continue;
974
+ const a = o.position.x - i.position.x, r = o.position.y - i.position.y, c = o.position.z - i.position.z, h = Math.sqrt(a * a + r * r + c * c);
953
975
  if (h < 0.01) continue;
954
976
  const x = (h - 15) * this.attractionStrength * s * this.alpha, m = a / h * x, u = r / h * x, f = c / h * x;
955
- o.velocity.x += m / o.mass, o.velocity.y += u / o.mass, o.velocity.z += f / o.mass, i.velocity.x -= m / i.mass, i.velocity.y -= u / i.mass, i.velocity.z -= f / i.mass;
977
+ i.velocity.x += m / i.mass, i.velocity.y += u / i.mass, i.velocity.z += f / i.mass, o.velocity.x -= m / o.mass, o.velocity.y -= u / o.mass, o.velocity.z -= f / o.mass;
956
978
  }
957
979
  }
958
980
  /**
@@ -969,6 +991,10 @@ class Le {
969
991
  */
970
992
  applyForces() {
971
993
  for (const e of this.nodes.values()) {
994
+ if (e.id === this.pinnedNodeId) {
995
+ e.position.x = 0, e.position.y = 0, e.position.z = 0, e.velocity.x = 0, e.velocity.y = 0, e.velocity.z = 0;
996
+ continue;
997
+ }
972
998
  e.velocity.x *= this.damping, e.velocity.y *= this.damping, e.velocity.z *= this.damping;
973
999
  const s = Math.sqrt(
974
1000
  e.velocity.x * e.velocity.x + e.velocity.y * e.velocity.y + e.velocity.z * e.velocity.z
@@ -1018,13 +1044,13 @@ class xt {
1018
1044
  max: { x: 100, y: 100, z: 100 }
1019
1045
  };
1020
1046
  const s = { x: 1 / 0, y: 1 / 0, z: 1 / 0 }, t = { x: -1 / 0, y: -1 / 0, z: -1 / 0 };
1021
- for (const i of e)
1022
- s.x = Math.min(s.x, i.position.x), s.y = Math.min(s.y, i.position.y), s.z = Math.min(s.z, i.position.z), t.x = Math.max(t.x, i.position.x), t.y = Math.max(t.y, i.position.y), t.z = Math.max(t.z, i.position.z);
1023
- const o = 10;
1024
- return s.x -= o, s.y -= o, s.z -= o, t.x += o, t.y += o, t.z += o, { min: s, max: t };
1047
+ for (const o of e)
1048
+ s.x = Math.min(s.x, o.position.x), s.y = Math.min(s.y, o.position.y), s.z = Math.min(s.z, o.position.z), t.x = Math.max(t.x, o.position.x), t.y = Math.max(t.y, o.position.y), t.z = Math.max(t.z, o.position.z);
1049
+ const i = 10;
1050
+ return s.x -= i, s.y -= i, s.z -= i, t.x += i, t.y += i, t.z += i, { min: s, max: t };
1025
1051
  }
1026
1052
  buildTree(e, s, t = 0) {
1027
- const o = Math.max(
1053
+ const i = Math.max(
1028
1054
  s.max.x - s.min.x,
1029
1055
  s.max.y - s.min.y,
1030
1056
  s.max.z - s.min.z
@@ -1032,7 +1058,7 @@ class xt {
1032
1058
  if (e.length === 0)
1033
1059
  return {
1034
1060
  bounds: s,
1035
- size: o,
1061
+ size: i,
1036
1062
  centerOfMass: { x: 0, y: 0, z: 0 },
1037
1063
  mass: 0,
1038
1064
  isLeaf: !0,
@@ -1046,7 +1072,7 @@ class xt {
1046
1072
  u += b.mass, f.x += b.position.x * b.mass, f.y += b.position.y * b.mass, f.z += b.position.z * b.mass;
1047
1073
  return u > 0 && (f.x /= u, f.y /= u, f.z /= u), {
1048
1074
  bounds: s,
1049
- size: o,
1075
+ size: i,
1050
1076
  centerOfMass: f,
1051
1077
  mass: u,
1052
1078
  isLeaf: !0,
@@ -1054,20 +1080,20 @@ class xt {
1054
1080
  children: []
1055
1081
  };
1056
1082
  }
1057
- const i = (s.min.x + s.max.x) / 2, a = (s.min.y + s.max.y) / 2, r = (s.min.z + s.max.z) / 2, c = [[], [], [], [], [], [], [], []];
1083
+ const o = (s.min.x + s.max.x) / 2, a = (s.min.y + s.max.y) / 2, r = (s.min.z + s.max.z) / 2, c = [[], [], [], [], [], [], [], []];
1058
1084
  for (const u of e) {
1059
- const f = (u.position.x >= i ? 1 : 0) + (u.position.y >= a ? 2 : 0) + (u.position.z >= r ? 4 : 0);
1085
+ const f = (u.position.x >= o ? 1 : 0) + (u.position.y >= a ? 2 : 0) + (u.position.z >= r ? 4 : 0);
1060
1086
  c[f].push(u);
1061
1087
  }
1062
1088
  const h = [
1063
- { min: { x: s.min.x, y: s.min.y, z: s.min.z }, max: { x: i, y: a, z: r } },
1064
- { min: { x: i, y: s.min.y, z: s.min.z }, max: { x: s.max.x, y: a, z: r } },
1065
- { min: { x: s.min.x, y: a, z: s.min.z }, max: { x: i, y: s.max.y, z: r } },
1066
- { min: { x: i, y: a, z: s.min.z }, max: { x: s.max.x, y: s.max.y, z: r } },
1067
- { min: { x: s.min.x, y: s.min.y, z: r }, max: { x: i, y: a, z: s.max.z } },
1068
- { min: { x: i, y: s.min.y, z: r }, max: { x: s.max.x, y: a, z: s.max.z } },
1069
- { min: { x: s.min.x, y: a, z: r }, max: { x: i, y: s.max.y, z: s.max.z } },
1070
- { min: { x: i, y: a, z: r }, max: { x: s.max.x, y: s.max.y, z: s.max.z } }
1089
+ { min: { x: s.min.x, y: s.min.y, z: s.min.z }, max: { x: o, y: a, z: r } },
1090
+ { min: { x: o, y: s.min.y, z: s.min.z }, max: { x: s.max.x, y: a, z: r } },
1091
+ { min: { x: s.min.x, y: a, z: s.min.z }, max: { x: o, y: s.max.y, z: r } },
1092
+ { min: { x: o, y: a, z: s.min.z }, max: { x: s.max.x, y: s.max.y, z: r } },
1093
+ { min: { x: s.min.x, y: s.min.y, z: r }, max: { x: o, y: a, z: s.max.z } },
1094
+ { min: { x: o, y: s.min.y, z: r }, max: { x: s.max.x, y: a, z: s.max.z } },
1095
+ { min: { x: s.min.x, y: a, z: r }, max: { x: o, y: s.max.y, z: s.max.z } },
1096
+ { min: { x: o, y: a, z: r }, max: { x: s.max.x, y: s.max.y, z: s.max.z } }
1071
1097
  ], p = [];
1072
1098
  let x = 0;
1073
1099
  const m = { x: 0, y: 0, z: 0 };
@@ -1079,7 +1105,7 @@ class xt {
1079
1105
  p.push(null);
1080
1106
  return x > 0 && (m.x /= x, m.y /= x, m.z /= x), {
1081
1107
  bounds: s,
1082
- size: o,
1108
+ size: i,
1083
1109
  centerOfMass: m,
1084
1110
  mass: x,
1085
1111
  isLeaf: !1,
@@ -1089,7 +1115,7 @@ class xt {
1089
1115
  }
1090
1116
  }
1091
1117
  class bt {
1092
- constructor(e, s, t, o = 60) {
1118
+ constructor(e, s, t, i = 60) {
1093
1119
  l(this, "sceneManager");
1094
1120
  l(this, "animationId", null);
1095
1121
  l(this, "isRunning", !1);
@@ -1114,7 +1140,7 @@ class bt {
1114
1140
  const t = e - this.fpsStartTime;
1115
1141
  t >= 1e3 && (this.currentFPS = this.frameCount / (t / 1e3), this.frameCount = 0, this.fpsStartTime = e), this.onSimulate(), this.onRender(), this.sceneManager.render();
1116
1142
  });
1117
- this.sceneManager = e, this.onSimulate = s, this.onRender = t, this.frameInterval = 1e3 / o;
1143
+ this.sceneManager = e, this.onSimulate = s, this.onRender = t, this.frameInterval = 1e3 / i;
1118
1144
  }
1119
1145
  /**
1120
1146
  * Starts the animation loop
@@ -1191,10 +1217,10 @@ class vt {
1191
1217
  { colors: ["#2d1a1a", "#1a0a0a", "#0f0505"] }
1192
1218
  // -z
1193
1219
  ];
1194
- for (const o of t) {
1195
- const i = document.createElement("canvas");
1196
- i.width = 256, i.height = 256;
1197
- const a = i.getContext("2d"), r = a.createRadialGradient(
1220
+ for (const i of t) {
1221
+ const o = document.createElement("canvas");
1222
+ o.width = 256, o.height = 256;
1223
+ const a = o.getContext("2d"), r = a.createRadialGradient(
1198
1224
  256 / 2,
1199
1225
  256 / 2,
1200
1226
  0,
@@ -1202,17 +1228,17 @@ class vt {
1202
1228
  256 / 2,
1203
1229
  256 * 0.8
1204
1230
  );
1205
- r.addColorStop(0, o.colors[0]), r.addColorStop(0.5, o.colors[1]), r.addColorStop(1, o.colors[2]), a.fillStyle = r, a.fillRect(0, 0, 256, 256);
1231
+ r.addColorStop(0, i.colors[0]), r.addColorStop(0.5, i.colors[1]), r.addColorStop(1, i.colors[2]), a.fillStyle = r, a.fillRect(0, 0, 256, 256);
1206
1232
  const c = a.getImageData(0, 0, 256, 256);
1207
1233
  for (let h = 0; h < c.data.length; h += 4) {
1208
1234
  const p = (Math.random() - 0.5) * 5;
1209
1235
  c.data[h] = Math.min(255, Math.max(0, c.data[h] + p)), c.data[h + 1] = Math.min(255, Math.max(0, c.data[h + 1] + p)), c.data[h + 2] = Math.min(255, Math.max(0, c.data[h + 2] + p));
1210
1236
  }
1211
- a.putImageData(c, 0, 0), s.push(i);
1237
+ a.putImageData(c, 0, 0), s.push(o);
1212
1238
  }
1213
- this.envMap = new y.CubeTexture(s.map((o) => {
1214
- const i = new Image();
1215
- return i.src = o.toDataURL(), i;
1239
+ this.envMap = new y.CubeTexture(s.map((i) => {
1240
+ const o = new Image();
1241
+ return o.src = i.toDataURL(), o;
1216
1242
  })), this.envMap.needsUpdate = !0;
1217
1243
  }
1218
1244
  /**
@@ -1229,9 +1255,9 @@ class vt {
1229
1255
  const t = "glass-single";
1230
1256
  if (this.materialCache.has(t))
1231
1257
  return this.materialCache.get(t).clone();
1232
- const o = new y.Color(16750950), i = new y.ShaderMaterial({
1258
+ const i = new y.Color(16750950), o = new y.ShaderMaterial({
1233
1259
  uniforms: {
1234
- uColor: { value: o },
1260
+ uColor: { value: i },
1235
1261
  uEnvMap: { value: this.envMap },
1236
1262
  uGlowColor: { value: new y.Color(16777215) },
1237
1263
  uGlowIntensity: { value: 0.8 },
@@ -1303,7 +1329,7 @@ class vt {
1303
1329
  depthWrite: !0,
1304
1330
  blending: y.NormalBlending
1305
1331
  });
1306
- return this.materialCache.set(t, i), i.clone();
1332
+ return this.materialCache.set(t, o), o.clone();
1307
1333
  }
1308
1334
  /**
1309
1335
  * Creates material for edges (light color for dark background)
@@ -1332,10 +1358,10 @@ class vt {
1332
1358
  * Creates a sprite material for labels (light text for dark background)
1333
1359
  */
1334
1360
  createLabelMaterial(e, s = 24) {
1335
- const t = document.createElement("canvas"), o = t.getContext("2d");
1336
- o.font = `600 ${s}px Inter, -apple-system, sans-serif`;
1337
- const a = o.measureText(e).width;
1338
- t.width = Math.max(128, a + 24), t.height = s + 20, o.clearRect(0, 0, t.width, t.height), o.font = `600 ${s}px Inter, -apple-system, sans-serif`, o.textAlign = "center", o.textBaseline = "middle", o.shadowColor = "rgba(0, 0, 0, 0.8)", o.shadowBlur = 4, o.shadowOffsetX = 1, o.shadowOffsetY = 1, o.fillStyle = "rgba(255, 255, 255, 0.95)", o.fillText(e, t.width / 2, t.height / 2);
1361
+ const t = document.createElement("canvas"), i = t.getContext("2d");
1362
+ i.font = `600 ${s}px Inter, -apple-system, sans-serif`;
1363
+ const a = i.measureText(e).width;
1364
+ t.width = Math.max(128, a + 24), t.height = s + 20, i.clearRect(0, 0, t.width, t.height), i.font = `600 ${s}px Inter, -apple-system, sans-serif`, i.textAlign = "center", i.textBaseline = "middle", i.shadowColor = "rgba(0, 0, 0, 0.8)", i.shadowBlur = 4, i.shadowOffsetX = 1, i.shadowOffsetY = 1, i.fillStyle = "rgba(255, 255, 255, 0.95)", i.fillText(e, t.width / 2, t.height / 2);
1339
1365
  const r = new y.CanvasTexture(t);
1340
1366
  return r.needsUpdate = !0, new y.SpriteMaterial({
1341
1367
  map: r,
@@ -1358,13 +1384,13 @@ class vt {
1358
1384
  }
1359
1385
  }
1360
1386
  class Mt {
1361
- constructor(e, s = 2, t = [32, 16, 8], o = 16750950) {
1387
+ constructor(e, s = 2, t = [32, 16, 8], i = 16750950) {
1362
1388
  l(this, "materialFactory");
1363
1389
  l(this, "geometryCache", /* @__PURE__ */ new Map());
1364
1390
  l(this, "nodeRadius");
1365
1391
  l(this, "lodSegments");
1366
1392
  l(this, "defaultNodeColor");
1367
- this.materialFactory = e, this.nodeRadius = s, this.lodSegments = t, this.defaultNodeColor = o, this.initGeometryCache();
1393
+ this.materialFactory = e, this.nodeRadius = s, this.lodSegments = t, this.defaultNodeColor = i, this.initGeometryCache();
1368
1394
  }
1369
1395
  /**
1370
1396
  * Pre-create geometries for each LOD level
@@ -1391,9 +1417,9 @@ class Mt {
1391
1417
  createNode(e, s = 0) {
1392
1418
  const t = new y.Group();
1393
1419
  t.name = `node-${e.id}`, t.userData = { nodeId: e.id, nodeData: e };
1394
- const o = this.getGeometry(s), i = this.materialFactory.createGlassMaterial(
1420
+ const i = this.getGeometry(s), o = this.materialFactory.createGlassMaterial(
1395
1421
  e.color ?? this.defaultNodeColor
1396
- ), a = new y.Mesh(o, i);
1422
+ ), a = new y.Mesh(i, o);
1397
1423
  a.castShadow = !0, a.receiveShadow = !0, t.add(a);
1398
1424
  const r = this.materialFactory.createLabelMaterial(e.label), c = new y.Sprite(r);
1399
1425
  return c.position.y = this.nodeRadius + 1.5, c.scale.set(4, 1, 1), t.add(c), e.position && t.position.set(
@@ -1467,14 +1493,14 @@ class wt {
1467
1493
  /**
1468
1494
  * Creates an edge line between two positions
1469
1495
  */
1470
- createEdge(e, s, t, o, i) {
1496
+ createEdge(e, s, t, i, o) {
1471
1497
  const a = new y.BufferGeometry(), r = new Float32Array([
1472
- o.x,
1473
- o.y,
1474
- o.z,
1475
1498
  i.x,
1476
1499
  i.y,
1477
- i.z
1500
+ i.z,
1501
+ o.x,
1502
+ o.y,
1503
+ o.z
1478
1504
  ]);
1479
1505
  a.setAttribute("position", new y.BufferAttribute(r, 3));
1480
1506
  const c = this.getDefaultMaterial().clone(), h = new y.Line(a, c);
@@ -1506,8 +1532,8 @@ class wt {
1506
1532
  * Updates an edge's positions
1507
1533
  */
1508
1534
  updateEdgePositions(e, s, t) {
1509
- const o = e.line.geometry.attributes.position, i = o.array;
1510
- i[0] = s.x, i[1] = s.y, i[2] = s.z, i[3] = t.x, i[4] = t.y, i[5] = t.z, o.needsUpdate = !0, e.line.geometry.computeBoundingSphere();
1535
+ const i = e.line.geometry.attributes.position, o = i.array;
1536
+ o[0] = s.x, o[1] = s.y, o[2] = s.z, o[3] = t.x, o[4] = t.y, o[5] = t.z, i.needsUpdate = !0, e.line.geometry.computeBoundingSphere();
1511
1537
  }
1512
1538
  /**
1513
1539
  * Disposes an edge's resources
@@ -1535,15 +1561,15 @@ class Et {
1535
1561
  getLODLevel(e) {
1536
1562
  if (!this.enabled)
1537
1563
  return X.HIGH;
1538
- const s = e.x - this.camera.position.x, t = e.y - this.camera.position.y, o = e.z - this.camera.position.z, i = Math.sqrt(s * s + t * t + o * o);
1539
- return i < this.lodDistances[0] ? X.HIGH : i < this.lodDistances[1] ? X.MEDIUM : X.LOW;
1564
+ const s = e.x - this.camera.position.x, t = e.y - this.camera.position.y, i = e.z - this.camera.position.z, o = Math.sqrt(s * s + t * t + i * i);
1565
+ return o < this.lodDistances[0] ? X.HIGH : o < this.lodDistances[1] ? X.MEDIUM : X.LOW;
1540
1566
  }
1541
1567
  /**
1542
1568
  * Checks if a node should be visible based on distance
1543
1569
  */
1544
1570
  shouldRenderNode(e, s = 500) {
1545
- const t = e.x - this.camera.position.x, o = e.y - this.camera.position.y, i = e.z - this.camera.position.z;
1546
- return Math.sqrt(t * t + o * o + i * i) < s;
1571
+ const t = e.x - this.camera.position.x, i = e.y - this.camera.position.y, o = e.z - this.camera.position.z;
1572
+ return Math.sqrt(t * t + i * i + o * o) < s;
1547
1573
  }
1548
1574
  /**
1549
1575
  * Sets the LOD distances
@@ -1599,14 +1625,14 @@ class Ct {
1599
1625
  */
1600
1626
  isLineVisible(e, s) {
1601
1627
  if (!this.enabled) return !0;
1602
- const t = new y.Vector3(e.x, e.y, e.z), o = new y.Vector3(s.x, s.y, s.z);
1603
- if (this.frustum.containsPoint(t) || this.frustum.containsPoint(o))
1628
+ const t = new y.Vector3(e.x, e.y, e.z), i = new y.Vector3(s.x, s.y, s.z);
1629
+ if (this.frustum.containsPoint(t) || this.frustum.containsPoint(i))
1604
1630
  return !0;
1605
- const i = new y.Vector3(
1631
+ const o = new y.Vector3(
1606
1632
  (e.x + s.x) / 2,
1607
1633
  (e.y + s.y) / 2,
1608
1634
  (e.z + s.z) / 2
1609
- ), a = i.distanceTo(t), r = new y.Sphere(i, a);
1635
+ ), a = o.distanceTo(t), r = new y.Sphere(o, a);
1610
1636
  return this.frustum.intersectsSphere(r);
1611
1637
  }
1612
1638
  /**
@@ -1689,23 +1715,23 @@ class Nt {
1689
1715
  this.hoveredEdgeKey !== null && this.onEdgeHover && (this.hoveredEdgeKey = null, this.onEdgeHover(null)), this.container.style.cursor = "pointer";
1690
1716
  return;
1691
1717
  }
1692
- const o = this.getIntersectedEdge(e), i = o ? `${o.edge.source}-${o.edge.target}` : null;
1693
- i !== this.hoveredEdgeKey && (this.hoveredEdgeKey = i, this.onEdgeHover && this.onEdgeHover(o)), this.container.style.cursor = o ? "pointer" : "default";
1718
+ const i = this.getIntersectedEdge(e), o = i ? `${i.edge.source}-${i.edge.target}` : null;
1719
+ o !== this.hoveredEdgeKey && (this.hoveredEdgeKey = o, this.onEdgeHover && this.onEdgeHover(i)), this.container.style.cursor = i ? "pointer" : "default";
1694
1720
  }
1695
1721
  /**
1696
1722
  * Gets the intersected node from a mouse event
1697
1723
  */
1698
1724
  getIntersectedNode(e) {
1699
- var o;
1725
+ var i;
1700
1726
  const s = this.container.getBoundingClientRect();
1701
1727
  this.mouse.x = (e.clientX - s.left) / s.width * 2 - 1, this.mouse.y = -((e.clientY - s.top) / s.height) * 2 + 1, this.raycaster.setFromCamera(this.mouse, this.sceneManager.camera);
1702
1728
  const t = this.raycaster.intersectObjects(this.nodeObjects, !0);
1703
1729
  if (t.length > 0) {
1704
- let i = t[0].object;
1705
- for (; i; ) {
1706
- if ((o = i.userData) != null && o.nodeData)
1707
- return i.userData.nodeData;
1708
- i = i.parent;
1730
+ let o = t[0].object;
1731
+ for (; o; ) {
1732
+ if ((i = o.userData) != null && i.nodeData)
1733
+ return o.userData.nodeData;
1734
+ o = o.parent;
1709
1735
  }
1710
1736
  }
1711
1737
  return null;
@@ -1718,13 +1744,13 @@ class Nt {
1718
1744
  this.mouse.x = (e.clientX - s.left) / s.width * 2 - 1, this.mouse.y = -((e.clientY - s.top) / s.height) * 2 + 1, this.raycaster.setFromCamera(this.mouse, this.sceneManager.camera);
1719
1745
  const t = this.raycaster.intersectObjects(this.edgeObjects, !1);
1720
1746
  if (t.length > 0) {
1721
- const o = t[0].object, i = o.userData;
1722
- if (i != null && i.edge && (i != null && i.sourceNode) && (i != null && i.targetNode))
1747
+ const i = t[0].object, o = i.userData;
1748
+ if (o != null && o.edge && (o != null && o.sourceNode) && (o != null && o.targetNode))
1723
1749
  return {
1724
- edge: i.edge,
1725
- sourceNode: i.sourceNode,
1726
- targetNode: i.targetNode,
1727
- edgeLine: o
1750
+ edge: o.edge,
1751
+ sourceNode: o.sourceNode,
1752
+ targetNode: o.targetNode,
1753
+ edgeLine: i
1728
1754
  };
1729
1755
  }
1730
1756
  return null;
@@ -1733,14 +1759,14 @@ class Nt {
1733
1759
  * Performs a raycast and returns the intersected node ID
1734
1760
  */
1735
1761
  getIntersectedNodeId(e, s) {
1736
- var i;
1762
+ var o;
1737
1763
  const t = this.container.getBoundingClientRect();
1738
1764
  this.mouse.x = (e - t.left) / t.width * 2 - 1, this.mouse.y = -((s - t.top) / t.height) * 2 + 1, this.raycaster.setFromCamera(this.mouse, this.sceneManager.camera);
1739
- const o = this.raycaster.intersectObjects(this.nodeObjects, !0);
1740
- if (o.length > 0) {
1741
- let a = o[0].object;
1765
+ const i = this.raycaster.intersectObjects(this.nodeObjects, !0);
1766
+ if (i.length > 0) {
1767
+ let a = i[0].object;
1742
1768
  for (; a; ) {
1743
- if ((i = a.userData) != null && i.nodeId)
1769
+ if ((o = a.userData) != null && o.nodeId)
1744
1770
  return a.userData.nodeId;
1745
1771
  a = a.parent;
1746
1772
  }
@@ -1824,10 +1850,10 @@ class St {
1824
1850
  this.currentNodeId = e.id;
1825
1851
  let t;
1826
1852
  this.panelTemplate ? t = this.panelTemplate(e, s) : t = this.generateDefaultContent(e, s), this.panel.innerHTML = t;
1827
- const o = this.panel.querySelector('[data-action="expand"]'), i = this.panel.querySelector("[data-depth-select]");
1828
- o && this.onExpand && o.addEventListener("click", () => {
1853
+ const i = this.panel.querySelector('[data-action="expand"]'), o = this.panel.querySelector("[data-depth-select]");
1854
+ i && this.onExpand && i.addEventListener("click", () => {
1829
1855
  if (this.currentNodeId) {
1830
- const r = i ? parseInt(i.value, 10) : 1;
1856
+ const r = o ? parseInt(o.value, 10) : 1;
1831
1857
  this.onExpand(this.currentNodeId, r);
1832
1858
  }
1833
1859
  });
@@ -1986,7 +2012,7 @@ class St {
1986
2012
  <div class="neighbors-section">
1987
2013
  <div class="neighbors-title">Connected To</div>
1988
2014
  ${s.slice(0, 5).map(
1989
- (o) => `<span class="neighbor-chip">${this.escapeHtml(o.label)}</span>`
2015
+ (i) => `<span class="neighbor-chip">${this.escapeHtml(i.label)}</span>`
1990
2016
  ).join("")}
1991
2017
  ${s.length > 5 ? `<span class="neighbor-chip">+${s.length - 5} more</span>` : ""}
1992
2018
  </div>
@@ -2104,10 +2130,10 @@ class zt {
2104
2130
  show(e, s, t) {
2105
2131
  if (!this.panel) return;
2106
2132
  this.currentEdgeKey = `${e.source}-${e.target}`;
2107
- let o;
2108
- this.panelTemplate ? o = this.panelTemplate(e, s, t) : o = this.generateDefaultContent(e, s, t), this.panel.innerHTML = o;
2109
- const i = this.panel.querySelector('[data-action="close"]');
2110
- i && i.addEventListener("click", () => {
2133
+ let i;
2134
+ this.panelTemplate ? i = this.panelTemplate(e, s, t) : i = this.generateDefaultContent(e, s, t), this.panel.innerHTML = i;
2135
+ const o = this.panel.querySelector('[data-action="close"]');
2136
+ o && o.addEventListener("click", () => {
2111
2137
  this.hide(), this.onClose && this.onClose();
2112
2138
  });
2113
2139
  const a = this.panel.querySelector('[data-action="goto-source"]');
@@ -2123,7 +2149,7 @@ class zt {
2123
2149
  * Generates default panel content
2124
2150
  */
2125
2151
  generateDefaultContent(e, s, t) {
2126
- const o = s.color ? `#${s.color.toString(16).padStart(6, "0")}` : "#ff9966", i = t.color ? `#${t.color.toString(16).padStart(6, "0")}` : "#ff9966", a = e.relationship || "connected to";
2152
+ const i = s.color ? `#${s.color.toString(16).padStart(6, "0")}` : "#ff9966", o = t.color ? `#${t.color.toString(16).padStart(6, "0")}` : "#ff9966", a = e.relationship || "connected to";
2127
2153
  return `
2128
2154
  <style>
2129
2155
  .force-graph-edge-panel .panel-header {
@@ -2233,7 +2259,7 @@ class zt {
2233
2259
  <div class="node-card" data-action="goto-source" title="Click to focus on ${this.escapeHtml(s.label)}">
2234
2260
  <div class="node-type">Source</div>
2235
2261
  <div class="node-card-header">
2236
- <span class="color-dot" style="background: ${o}; box-shadow: 0 0 8px ${o}80;"></span>
2262
+ <span class="color-dot" style="background: ${i}; box-shadow: 0 0 8px ${i}80;"></span>
2237
2263
  <span class="node-label">${this.escapeHtml(s.label)}</span>
2238
2264
  </div>
2239
2265
  </div>
@@ -2243,7 +2269,7 @@ class zt {
2243
2269
  <div class="node-card" data-action="goto-target" title="Click to focus on ${this.escapeHtml(t.label)}">
2244
2270
  <div class="node-type">Target</div>
2245
2271
  <div class="node-card-header">
2246
- <span class="color-dot" style="background: ${i}; box-shadow: 0 0 8px ${i}80;"></span>
2272
+ <span class="color-dot" style="background: ${o}; box-shadow: 0 0 8px ${o}80;"></span>
2247
2273
  <span class="node-label">${this.escapeHtml(t.label)}</span>
2248
2274
  </div>
2249
2275
  </div>
@@ -2331,14 +2357,14 @@ class Tt {
2331
2357
  */
2332
2358
  positionTooltip(e, s) {
2333
2359
  if (!this.tooltip) return;
2334
- const t = this.tooltip.getBoundingClientRect(), o = window.innerWidth, i = window.innerHeight;
2360
+ const t = this.tooltip.getBoundingClientRect(), i = window.innerWidth, o = window.innerHeight;
2335
2361
  let a = e + 15, r = s + 15;
2336
- a + t.width > o - 10 && (a = e - t.width - 15), r + t.height > i - 10 && (r = s - t.height - 15), a < 10 && (a = 10), r < 10 && (r = 10), this.tooltip.style.left = `${a}px`, this.tooltip.style.top = `${r}px`;
2362
+ a + t.width > i - 10 && (a = e - t.width - 15), r + t.height > o - 10 && (r = s - t.height - 15), a < 10 && (a = 10), r < 10 && (r = 10), this.tooltip.style.left = `${a}px`, this.tooltip.style.top = `${r}px`;
2337
2363
  }
2338
2364
  /**
2339
2365
  * Shows the tooltip with edge info
2340
2366
  */
2341
- show(e, s, t, o, i) {
2367
+ show(e, s, t, i, o) {
2342
2368
  if (!this.tooltip) return;
2343
2369
  const a = e.relationship || "connected to";
2344
2370
  this.tooltip.innerHTML = `
@@ -2353,7 +2379,7 @@ class Tt {
2353
2379
  <span style="font-weight: 600; color: #ff9966;">${this.escapeHtml(t.label)}</span>
2354
2380
  </div>
2355
2381
  </div>
2356
- `, this.positionTooltip(o, i), this.tooltip.style.opacity = "1", this.tooltip.style.transform = "translateY(0)", this.visible = !0;
2382
+ `, this.positionTooltip(i, o), this.tooltip.style.opacity = "1", this.tooltip.style.transform = "translateY(0)", this.visible = !0;
2357
2383
  }
2358
2384
  /**
2359
2385
  * Updates tooltip position (called externally on mouse move)
@@ -2530,25 +2556,25 @@ class kt {
2530
2556
  this.searchResults.innerHTML = '<div class="f3d-no-results">No results found</div>', this.searchResults.style.display = "block";
2531
2557
  return;
2532
2558
  }
2533
- let o = "";
2534
- s.length > 0 && (o += '<div class="f3d-search-section-header">Nodes</div>', s.slice(0, 10).forEach((i) => {
2535
- const a = i.type || "Node";
2536
- o += `
2537
- <div class="f3d-search-result-item" data-node-id="${this.escapeHtml(i.id)}">
2538
- <div class="f3d-result-label">${this.escapeHtml(i.label)}</div>
2559
+ let i = "";
2560
+ s.length > 0 && (i += '<div class="f3d-search-section-header">Nodes</div>', s.slice(0, 10).forEach((o) => {
2561
+ const a = o.type || "Node";
2562
+ i += `
2563
+ <div class="f3d-search-result-item" data-node-id="${this.escapeHtml(o.id)}">
2564
+ <div class="f3d-result-label">${this.escapeHtml(o.label)}</div>
2539
2565
  <div class="f3d-result-type">${this.escapeHtml(a)}</div>
2540
2566
  </div>
2541
2567
  `;
2542
- }), s.length > 10 && (o += `<div class="f3d-no-results">+ ${s.length - 10} more nodes</div>`)), t.length > 0 && (o += '<div class="f3d-search-section-header">Relationships</div>', t.slice(0, 5).forEach(({ edge: i, sourceNode: a, targetNode: r }) => {
2543
- o += `
2544
- <div class="f3d-search-result-item" data-node-id="${this.escapeHtml(i.source)}">
2568
+ }), s.length > 10 && (i += `<div class="f3d-no-results">+ ${s.length - 10} more nodes</div>`)), t.length > 0 && (i += '<div class="f3d-search-section-header">Relationships</div>', t.slice(0, 5).forEach(({ edge: o, sourceNode: a, targetNode: r }) => {
2569
+ i += `
2570
+ <div class="f3d-search-result-item" data-node-id="${this.escapeHtml(o.source)}">
2545
2571
  <div class="f3d-result-label">${this.escapeHtml(a.label)} → ${this.escapeHtml(r.label)}</div>
2546
- <div class="f3d-result-relationship">${this.escapeHtml(i.relationship || "connected")}</div>
2572
+ <div class="f3d-result-relationship">${this.escapeHtml(o.relationship || "connected")}</div>
2547
2573
  </div>
2548
2574
  `;
2549
- }), t.length > 5 && (o += `<div class="f3d-no-results">+ ${t.length - 5} more relationships</div>`)), this.searchResults.innerHTML = o, this.searchResults.style.display = "block", this.searchResults.querySelectorAll(".f3d-search-result-item").forEach((i) => {
2550
- i.addEventListener("click", () => {
2551
- const a = i.dataset.nodeId;
2575
+ }), t.length > 5 && (i += `<div class="f3d-no-results">+ ${t.length - 5} more relationships</div>`)), this.searchResults.innerHTML = i, this.searchResults.style.display = "block", this.searchResults.querySelectorAll(".f3d-search-result-item").forEach((o) => {
2576
+ o.addEventListener("click", () => {
2577
+ const a = o.dataset.nodeId;
2552
2578
  a && (this.onResultClick(a), this.searchResults && (this.searchResults.style.display = "none"), this.searchInput && this.searchInput.blur());
2553
2579
  });
2554
2580
  });
@@ -2706,31 +2732,31 @@ class It {
2706
2732
  setupInteractions() {
2707
2733
  this.canvas.addEventListener("wheel", (e) => {
2708
2734
  e.preventDefault();
2709
- const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left, o = e.clientY - s.top, i = e.deltaY > 0 ? 0.9 : 1.1, a = Math.max(0.1, Math.min(5, this.transform.scale * i)), r = a / this.transform.scale;
2710
- this.transform.x = t - (t - this.transform.x) * r, this.transform.y = o - (o - this.transform.y) * r, this.transform.scale = a;
2735
+ const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left, i = e.clientY - s.top, o = e.deltaY > 0 ? 0.9 : 1.1, a = Math.max(0.1, Math.min(5, this.transform.scale * o)), r = a / this.transform.scale;
2736
+ this.transform.x = t - (t - this.transform.x) * r, this.transform.y = i - (i - this.transform.y) * r, this.transform.scale = a;
2711
2737
  }), this.canvas.addEventListener("mousedown", (e) => {
2712
- const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left, o = e.clientY - s.top, i = this.screenToWorld(t, o), a = this.findNodeAt(i.x, i.y);
2738
+ const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left, i = e.clientY - s.top, o = this.screenToWorld(t, i), a = this.findNodeAt(o.x, o.y);
2713
2739
  this.dragStartPos = { x: e.clientX, y: e.clientY }, a ? (this.isDragging = !0, this.draggedNode = a, this.canvas.style.cursor = "grabbing", this.isSimulating = !0) : (this.isPanning = !0, this.canvas.style.cursor = "grabbing"), this.lastMousePos = { x: e.clientX, y: e.clientY };
2714
2740
  }), this.canvas.addEventListener("mousemove", (e) => {
2715
- const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left, o = e.clientY - s.top, i = this.screenToWorld(t, o);
2741
+ const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left, i = e.clientY - s.top, o = this.screenToWorld(t, i);
2716
2742
  if (this.isDragging && this.draggedNode)
2717
- this.draggedNode.x = i.x, this.draggedNode.y = i.y, this.draggedNode.vx = 0, this.draggedNode.vy = 0;
2743
+ this.draggedNode.x = o.x, this.draggedNode.y = o.y, this.draggedNode.vx = 0, this.draggedNode.vy = 0;
2718
2744
  else if (this.isPanning) {
2719
2745
  const a = e.clientX - this.lastMousePos.x, r = e.clientY - this.lastMousePos.y;
2720
2746
  this.transform.x += a, this.transform.y += r, this.lastMousePos = { x: e.clientX, y: e.clientY };
2721
2747
  } else {
2722
- const a = this.findNodeAt(i.x, i.y);
2748
+ const a = this.findNodeAt(o.x, o.y);
2723
2749
  if (a !== this.hoveredNode && (this.hoveredNode = a, a ? (this.hoveredEdge && (this.hoveredEdge = null, this.options.onEdgeHover && this.options.onEdgeHover(null)), this.canvas.style.cursor = "pointer", this.options.onNodeHover && this.options.onNodeHover(a.data)) : this.options.onNodeHover && this.options.onNodeHover(null)), !a) {
2724
- const r = this.findEdgeAt(i.x, i.y);
2750
+ const r = this.findEdgeAt(o.x, o.y);
2725
2751
  r !== this.hoveredEdge && (this.hoveredEdge = r, this.canvas.style.cursor = r ? "pointer" : "grab", this.options.onEdgeHover && this.options.onEdgeHover(r ? r.data : null, e));
2726
2752
  }
2727
2753
  }
2728
2754
  }), this.canvas.addEventListener("mouseup", (e) => {
2729
- const s = Math.abs(e.clientX - this.dragStartPos.x), t = Math.abs(e.clientY - this.dragStartPos.y), o = s < 5 && t < 5;
2755
+ const s = Math.abs(e.clientX - this.dragStartPos.x), t = Math.abs(e.clientY - this.dragStartPos.y), i = s < 5 && t < 5;
2730
2756
  if (this.isDragging && this.draggedNode)
2731
- o && this.options.onNodeClick && (this.selectedNode = this.draggedNode, this.options.onNodeClick(this.draggedNode.data));
2732
- else if (o) {
2733
- const i = this.canvas.getBoundingClientRect(), a = this.screenToWorld(e.clientX - i.left, e.clientY - i.top), r = this.findEdgeAt(a.x, a.y);
2757
+ i && this.options.onNodeClick && (this.selectedNode = this.draggedNode, this.options.onNodeClick(this.draggedNode.data));
2758
+ else if (i) {
2759
+ const o = this.canvas.getBoundingClientRect(), a = this.screenToWorld(e.clientX - o.left, e.clientY - o.top), r = this.findEdgeAt(a.x, a.y);
2734
2760
  r && this.options.onEdgeClick && this.options.onEdgeClick(r.data);
2735
2761
  }
2736
2762
  this.isDragging = !1, this.isPanning = !1, this.draggedNode = null, this.canvas.style.cursor = this.hoveredNode ? "pointer" : "grab";
@@ -2746,21 +2772,21 @@ class It {
2746
2772
  }
2747
2773
  findNodeAt(e, s) {
2748
2774
  for (const t of this.nodes.values()) {
2749
- const o = t.x - e, i = t.y - s;
2750
- if (Math.sqrt(o * o + i * i) < t.radius)
2775
+ const i = t.x - e, o = t.y - s;
2776
+ if (Math.sqrt(i * i + o * o) < t.radius)
2751
2777
  return t;
2752
2778
  }
2753
2779
  return null;
2754
2780
  }
2755
2781
  findEdgeAt(e, s) {
2756
- for (const o of this.edges) {
2757
- const i = this.nodes.get(o.source), a = this.nodes.get(o.target);
2758
- if (!i || !a) continue;
2759
- const r = a.x - i.x, c = a.y - i.y, h = r * r + c * c;
2782
+ for (const i of this.edges) {
2783
+ const o = this.nodes.get(i.source), a = this.nodes.get(i.target);
2784
+ if (!o || !a) continue;
2785
+ const r = a.x - o.x, c = a.y - o.y, h = r * r + c * c;
2760
2786
  if (h === 0) continue;
2761
- const p = Math.max(0, Math.min(1, ((e - i.x) * r + (s - i.y) * c) / h)), x = i.x + p * r, m = i.y + p * c, u = e - x, f = s - m;
2787
+ const p = Math.max(0, Math.min(1, ((e - o.x) * r + (s - o.y) * c) / h)), x = o.x + p * r, m = o.y + p * c, u = e - x, f = s - m;
2762
2788
  if (Math.sqrt(u * u + f * f) < 12)
2763
- return o;
2789
+ return i;
2764
2790
  }
2765
2791
  return null;
2766
2792
  }
@@ -2773,8 +2799,8 @@ class It {
2773
2799
  simulate() {
2774
2800
  const e = Array.from(this.nodes.values()), s = e.length;
2775
2801
  if (s === 0) return;
2776
- const t = 60, o = 5;
2777
- let i = 0;
2802
+ const t = 60, i = 5;
2803
+ let o = 0;
2778
2804
  for (let r = 0; r < s; r++)
2779
2805
  for (let c = r + 1; c < s; c++) {
2780
2806
  const h = e[r], p = e[c];
@@ -2798,35 +2824,35 @@ class It {
2798
2824
  if (this.draggedNode === r) continue;
2799
2825
  r.vx *= this.options.damping, r.vy *= this.options.damping;
2800
2826
  const c = Math.sqrt(r.vx * r.vx + r.vy * r.vy);
2801
- c > o && (r.vx = r.vx / c * o, r.vy = r.vy / c * o), r.x += r.vx, r.y += r.vy, i += r.vx * r.vx + r.vy * r.vy;
2827
+ c > i && (r.vx = r.vx / c * i, r.vy = r.vy / c * i), r.x += r.vx, r.y += r.vy, o += r.vx * r.vx + r.vy * r.vy;
2802
2828
  }
2803
- i < 0.01 && !this.draggedNode && (this.isSimulating = !1);
2829
+ o < 0.01 && !this.draggedNode && (this.isSimulating = !1);
2804
2830
  }
2805
2831
  render() {
2806
2832
  const e = this.ctx, s = this.canvas.width / (window.devicePixelRatio || 1), t = this.canvas.height / (window.devicePixelRatio || 1);
2807
2833
  e.fillStyle = this.options.backgroundColor, e.fillRect(0, 0, s, t), this.renderGrid(s, t), e.save(), e.translate(this.transform.x, this.transform.y), e.scale(this.transform.scale, this.transform.scale), this.renderEdges(), this.renderNodes(), e.restore();
2808
2834
  }
2809
2835
  renderGrid(e, s) {
2810
- const t = this.ctx, o = 40 * this.transform.scale, i = 1.5, a = this.transform.x % o, r = this.transform.y % o;
2836
+ const t = this.ctx, i = 40 * this.transform.scale, o = 1.5, a = this.transform.x % i, r = this.transform.y % i;
2811
2837
  t.fillStyle = this.options.gridColor;
2812
- for (let c = a; c < e; c += o)
2813
- for (let h = r; h < s; h += o)
2814
- t.beginPath(), t.arc(c, h, i, 0, Math.PI * 2), t.fill();
2838
+ for (let c = a; c < e; c += i)
2839
+ for (let h = r; h < s; h += i)
2840
+ t.beginPath(), t.arc(c, h, o, 0, Math.PI * 2), t.fill();
2815
2841
  }
2816
2842
  renderEdges() {
2817
2843
  const e = this.ctx;
2818
2844
  for (const s of this.edges) {
2819
- const t = this.nodes.get(s.source), o = this.nodes.get(s.target);
2820
- if (!t || !o) continue;
2821
- const i = s === this.hoveredEdge, a = e.createLinearGradient(t.x, t.y, o.x, o.y);
2822
- i ? (a.addColorStop(0, "rgba(255, 153, 102, 0.8)"), a.addColorStop(0.5, "rgba(255, 255, 255, 0.5)"), a.addColorStop(1, "rgba(102, 153, 255, 0.8)"), e.lineWidth = 3) : (a.addColorStop(0, "rgba(255, 153, 102, 0.3)"), a.addColorStop(0.5, "rgba(255, 255, 255, 0.15)"), a.addColorStop(1, "rgba(102, 153, 255, 0.3)"), e.lineWidth = 1.5), e.beginPath(), e.moveTo(t.x, t.y), e.lineTo(o.x, o.y), e.strokeStyle = a, e.stroke();
2845
+ const t = this.nodes.get(s.source), i = this.nodes.get(s.target);
2846
+ if (!t || !i) continue;
2847
+ const o = s === this.hoveredEdge, a = e.createLinearGradient(t.x, t.y, i.x, i.y);
2848
+ o ? (a.addColorStop(0, "rgba(255, 153, 102, 0.8)"), a.addColorStop(0.5, "rgba(255, 255, 255, 0.5)"), a.addColorStop(1, "rgba(102, 153, 255, 0.8)"), e.lineWidth = 3) : (a.addColorStop(0, "rgba(255, 153, 102, 0.3)"), a.addColorStop(0.5, "rgba(255, 255, 255, 0.15)"), a.addColorStop(1, "rgba(102, 153, 255, 0.3)"), e.lineWidth = 1.5), e.beginPath(), e.moveTo(t.x, t.y), e.lineTo(i.x, i.y), e.strokeStyle = a, e.stroke();
2823
2849
  }
2824
2850
  }
2825
2851
  renderNodes() {
2826
2852
  const e = this.ctx;
2827
2853
  for (const s of this.nodes.values()) {
2828
- const t = s === this.hoveredNode, o = s === this.selectedNode, i = this.hoveredEdge && (s.data.id === this.hoveredEdge.source || s.data.id === this.hoveredEdge.target), a = s.radius * (t ? 1.1 : 1);
2829
- if (t || o || i) {
2854
+ const t = s === this.hoveredNode, i = s === this.selectedNode, o = this.hoveredEdge && (s.data.id === this.hoveredEdge.source || s.data.id === this.hoveredEdge.target), a = s.radius * (t ? 1.1 : 1);
2855
+ if (t || i || o) {
2830
2856
  const f = e.createRadialGradient(
2831
2857
  s.x,
2832
2858
  s.y,
@@ -2834,7 +2860,7 @@ class It {
2834
2860
  s.x,
2835
2861
  s.y,
2836
2862
  a * 2
2837
- ), b = t || o ? 0.4 : 0.25;
2863
+ ), b = t || i ? 0.4 : 0.25;
2838
2864
  f.addColorStop(0, `rgba(255, 153, 102, ${b})`), f.addColorStop(1, "rgba(255, 153, 102, 0)"), e.fillStyle = f, e.beginPath(), e.arc(s.x, s.y, a * 2, 0, Math.PI * 2), e.fill();
2839
2865
  }
2840
2866
  const r = e.createRadialGradient(
@@ -2861,14 +2887,14 @@ class It {
2861
2887
  */
2862
2888
  setData(e) {
2863
2889
  this.nodes.clear(), this.edges = [], this.nodeIdToIndex.clear(), e.nodes.forEach((s, t) => {
2864
- const o = s.position || {
2890
+ const i = s.position || {
2865
2891
  x: (Math.random() - 0.5) * 300,
2866
2892
  y: (Math.random() - 0.5) * 300
2867
- }, i = {
2893
+ }, o = {
2868
2894
  id: s.id,
2869
2895
  label: s.label,
2870
- x: o.x,
2871
- y: o.y,
2896
+ x: i.x,
2897
+ y: i.y,
2872
2898
  vx: 0,
2873
2899
  vy: 0,
2874
2900
  color: s.color || 16750950,
@@ -2876,7 +2902,7 @@ class It {
2876
2902
  radius: this.options.nodeRadius,
2877
2903
  data: s
2878
2904
  };
2879
- this.nodes.set(s.id, i), this.nodeIdToIndex.set(s.id, t);
2905
+ this.nodes.set(s.id, o), this.nodeIdToIndex.set(s.id, t);
2880
2906
  }), this.edges = e.edges.map((s) => ({
2881
2907
  source: s.source,
2882
2908
  target: s.target,
@@ -2952,9 +2978,9 @@ class It {
2952
2978
  focusOnNode(e) {
2953
2979
  const s = this.nodes.get(e);
2954
2980
  if (!s) return;
2955
- const t = this.canvas.width / 2 / (window.devicePixelRatio || 1) - s.x * this.transform.scale, o = this.canvas.height / 2 / (window.devicePixelRatio || 1) - s.y * this.transform.scale, i = this.transform.x, a = this.transform.y, r = 500, c = performance.now(), h = () => {
2981
+ const t = this.canvas.width / 2 / (window.devicePixelRatio || 1) - s.x * this.transform.scale, i = this.canvas.height / 2 / (window.devicePixelRatio || 1) - s.y * this.transform.scale, o = this.transform.x, a = this.transform.y, r = 500, c = performance.now(), h = () => {
2956
2982
  const p = performance.now() - c, x = Math.min(p / r, 1), m = 1 - Math.pow(1 - x, 3);
2957
- this.transform.x = i + (t - i) * m, this.transform.y = a + (o - a) * m, x < 1 ? requestAnimationFrame(h) : this.selectedNode = s;
2983
+ this.transform.x = o + (t - o) * m, this.transform.y = a + (i - a) * m, x < 1 ? requestAnimationFrame(h) : this.selectedNode = s;
2958
2984
  };
2959
2985
  h();
2960
2986
  }
@@ -2963,8 +2989,8 @@ class It {
2963
2989
  */
2964
2990
  syncFrom3D(e) {
2965
2991
  e.forEach((s, t) => {
2966
- const o = this.nodes.get(t);
2967
- o && (o.x = s.position.x * 3, o.y = s.position.y * 3, o.vx = 0, o.vy = 0);
2992
+ const i = this.nodes.get(t);
2993
+ i && (i.x = s.position.x * 3, i.y = s.position.y * 3, i.vx = 0, i.vy = 0);
2968
2994
  }), this.isSimulating = !1;
2969
2995
  }
2970
2996
  /**
@@ -3106,8 +3132,8 @@ class Ht {
3106
3132
  onEdgeHover(e) {
3107
3133
  if (e) {
3108
3134
  this.edgeManager.highlightEdge(e.edge.source, e.edge.target);
3109
- const s = this.container.getBoundingClientRect(), t = s.left + s.width / 2, o = s.top + s.height / 2;
3110
- this.edgeTooltipManager.show(e.edge, e.sourceNode, e.targetNode, t, o), this.options.onEdgeHover && this.options.onEdgeHover(e.edge, e.sourceNode, e.targetNode), this.emit("edgeHover", e.edge, e.sourceNode, e.targetNode);
3135
+ const s = this.container.getBoundingClientRect(), t = s.left + s.width / 2, i = s.top + s.height / 2;
3136
+ this.edgeTooltipManager.show(e.edge, e.sourceNode, e.targetNode, t, i), this.options.onEdgeHover && this.options.onEdgeHover(e.edge, e.sourceNode, e.targetNode), this.emit("edgeHover", e.edge, e.sourceNode, e.targetNode);
3111
3137
  } else
3112
3138
  this.edgeManager.unhighlightCurrentEdge(), this.edgeTooltipManager.hide(), this.options.onEdgeHover && this.options.onEdgeHover(null, null, null), this.emit("edgeHover", null, null, null);
3113
3139
  }
@@ -3116,7 +3142,7 @@ class Ht {
3116
3142
  */
3117
3143
  onNodeClick(e) {
3118
3144
  this.edgePanelManager.hide();
3119
- const t = this.edgeManager.getNeighborIds(e.id).map((o) => this.nodeManager.getNode(o)).filter((o) => o !== void 0);
3145
+ const t = this.edgeManager.getNeighborIds(e.id).map((i) => this.nodeManager.getNode(i)).filter((i) => i !== void 0);
3120
3146
  this.options.showPanel !== !1 && this.panelManager.show(e, t), this.options.onNodeClick && this.options.onNodeClick(e), this.emit("nodeClick", e);
3121
3147
  }
3122
3148
  /**
@@ -3151,20 +3177,20 @@ class Ht {
3151
3177
  */
3152
3178
  setData(e) {
3153
3179
  var a;
3154
- const s = (a = e.data) != null && a.nodes ? e.data : e, o = (s.edges || s.links || []).map((r) => ({
3180
+ const s = (a = e.data) != null && a.nodes ? e.data : e, i = (s.edges || s.links || []).map((r) => ({
3155
3181
  ...r,
3156
3182
  relationship: r.relationship || r.label || "related_to"
3157
- })), i = {
3183
+ })), o = {
3158
3184
  nodes: s.nodes || [],
3159
- edges: o
3185
+ edges: i
3160
3186
  };
3161
- if (this.graphData = i, this.edgeManager.clear(), this.nodeManager.clear(), i.nodes && Array.isArray(i.nodes)) {
3162
- te.setExpectedNodeCount(i.nodes.length);
3163
- for (const r of i.nodes)
3187
+ if (this.graphData = o, this.edgeManager.clear(), this.nodeManager.clear(), o.nodes && Array.isArray(o.nodes)) {
3188
+ te.setExpectedNodeCount(o.nodes.length);
3189
+ for (const r of o.nodes)
3164
3190
  this.addNode(r);
3165
3191
  }
3166
- if (i.edges && Array.isArray(i.edges))
3167
- for (const r of i.edges)
3192
+ if (o.edges && Array.isArray(o.edges))
3193
+ for (const r of o.edges)
3168
3194
  this.addEdge(r);
3169
3195
  this.graphEngine = new Le(
3170
3196
  this.nodeManager.getAllNodes(),
@@ -3176,7 +3202,7 @@ class Ht {
3176
3202
  useBarnesHut: this.options.useBarnesHut,
3177
3203
  barnesHutTheta: this.options.barnesHutTheta
3178
3204
  }
3179
- ), this.graphEngine.restart(), this.forceGraph2D && this.forceGraph2D.setData(i);
3205
+ ), this.graphEngine.restart(), this.forceGraph2D && this.forceGraph2D.setData(o);
3180
3206
  }
3181
3207
  /**
3182
3208
  * Adds a node to the graph
@@ -3230,20 +3256,20 @@ class Ht {
3230
3256
  * @param fetchFn - Optional fetch function to override the default
3231
3257
  */
3232
3258
  async expandNode(e, s = 1, t) {
3233
- const o = t ?? this.options.onExpand;
3234
- if (!o)
3259
+ const i = t ?? this.options.onExpand;
3260
+ if (!i)
3235
3261
  return console.warn("[ForceGraph3D] No expand callback provided"), !1;
3236
3262
  try {
3237
- const i = await o(e, s);
3238
- if (i.nodes && Array.isArray(i.nodes))
3239
- for (const a of i.nodes)
3263
+ const o = await i(e, s);
3264
+ if (o.nodes && Array.isArray(o.nodes))
3265
+ for (const a of o.nodes)
3240
3266
  this.addNode(a);
3241
- if (i.edges && Array.isArray(i.edges))
3242
- for (const a of i.edges)
3267
+ if (o.edges && Array.isArray(o.edges))
3268
+ for (const a of o.edges)
3243
3269
  this.addEdge(a);
3244
- return this.panelManager.hide(), this.emit("expand", e, i), !0;
3245
- } catch (i) {
3246
- return console.error("[ForceGraph3D] Error expanding node:", i), !1;
3270
+ return this.panelManager.hide(), this.emit("expand", e, o), !0;
3271
+ } catch (o) {
3272
+ return console.error("[ForceGraph3D] Error expanding node:", o), !1;
3247
3273
  }
3248
3274
  }
3249
3275
  /**
@@ -3290,13 +3316,13 @@ class Ht {
3290
3316
  console.warn(`[ForceGraph3D] Node "${e}" not found`);
3291
3317
  return;
3292
3318
  }
3293
- const o = t.position, i = this.sceneManager.camera, a = this.sceneManager.controls, r = i.position.clone().sub(a.target).normalize(), c = {
3294
- x: o.x + r.x * s,
3295
- y: o.y + r.y * s,
3296
- z: o.z + r.z * s
3297
- }, h = { x: i.position.x, y: i.position.y, z: i.position.z }, p = { x: a.target.x, y: a.target.y, z: a.target.z }, x = 800, m = performance.now(), u = () => {
3319
+ const i = t.position, o = this.sceneManager.camera, a = this.sceneManager.controls, r = o.position.clone().sub(a.target).normalize(), c = {
3320
+ x: i.x + r.x * s,
3321
+ y: i.y + r.y * s,
3322
+ z: i.z + r.z * s
3323
+ }, h = { x: o.position.x, y: o.position.y, z: o.position.z }, p = { x: a.target.x, y: a.target.y, z: a.target.z }, x = 800, m = performance.now(), u = () => {
3298
3324
  const f = performance.now() - m, b = Math.min(f / x, 1), M = 1 - Math.pow(1 - b, 3);
3299
- i.position.x = h.x + (c.x - h.x) * M, i.position.y = h.y + (c.y - h.y) * M, i.position.z = h.z + (c.z - h.z) * M, a.target.x = p.x + (o.x - p.x) * M, a.target.y = p.y + (o.y - p.y) * M, a.target.z = p.z + (o.z - p.z) * M, a.update(), b < 1 && requestAnimationFrame(u);
3325
+ o.position.x = h.x + (c.x - h.x) * M, o.position.y = h.y + (c.y - h.y) * M, o.position.z = h.z + (c.z - h.z) * M, a.target.x = p.x + (i.x - p.x) * M, a.target.y = p.y + (i.y - p.y) * M, a.target.z = p.z + (i.z - p.z) * M, a.update(), b < 1 && requestAnimationFrame(u);
3300
3326
  };
3301
3327
  u();
3302
3328
  }
@@ -3305,16 +3331,16 @@ class Ht {
3305
3331
  * Camera targets the midpoint and zooms out enough to see both nodes
3306
3332
  */
3307
3333
  focusOnEdge(e, s, t = 1.5) {
3308
- const o = this.nodeManager.getNode(e), i = this.nodeManager.getNode(s);
3309
- if (!o || !i) {
3334
+ const i = this.nodeManager.getNode(e), o = this.nodeManager.getNode(s);
3335
+ if (!i || !o) {
3310
3336
  console.warn(`[ForceGraph3D] Could not find nodes for edge "${e}" -> "${s}"`);
3311
3337
  return;
3312
3338
  }
3313
3339
  const a = this.sceneManager.camera, r = this.sceneManager.controls, c = {
3314
- x: (o.position.x + i.position.x) / 2,
3315
- y: (o.position.y + i.position.y) / 2,
3316
- z: (o.position.z + i.position.z) / 2
3317
- }, h = i.position.x - o.position.x, p = i.position.y - o.position.y, x = i.position.z - o.position.z, m = Math.sqrt(h * h + p * p + x * x), u = Math.max(m * t, 40), f = a.position.clone().sub(r.target).normalize(), b = {
3340
+ x: (i.position.x + o.position.x) / 2,
3341
+ y: (i.position.y + o.position.y) / 2,
3342
+ z: (i.position.z + o.position.z) / 2
3343
+ }, h = o.position.x - i.position.x, p = o.position.y - i.position.y, x = o.position.z - i.position.z, m = Math.sqrt(h * h + p * p + x * x), u = Math.max(m * t, 40), f = a.position.clone().sub(r.target).normalize(), b = {
3318
3344
  x: c.x + f.x * u,
3319
3345
  y: c.y + f.y * u,
3320
3346
  z: c.z + f.z * u
@@ -3343,28 +3369,28 @@ class Ht {
3343
3369
  searchNodes(e) {
3344
3370
  if (!e || e.trim() === "")
3345
3371
  return [];
3346
- const s = e.toLowerCase().trim(), t = this.nodeManager.getAllNodes(), o = [];
3347
- return t.forEach((i) => {
3372
+ const s = e.toLowerCase().trim(), t = this.nodeManager.getAllNodes(), i = [];
3373
+ return t.forEach((o) => {
3348
3374
  var h, p, x;
3349
- const a = (h = i.label) == null ? void 0 : h.toLowerCase().includes(s), r = (p = i.id) == null ? void 0 : p.toLowerCase().includes(s), c = (x = i.type) == null ? void 0 : x.toLowerCase().includes(s);
3350
- (a || r || c) && o.push(i);
3351
- }), o;
3375
+ const a = (h = o.label) == null ? void 0 : h.toLowerCase().includes(s), r = (p = o.id) == null ? void 0 : p.toLowerCase().includes(s), c = (x = o.type) == null ? void 0 : x.toLowerCase().includes(s);
3376
+ (a || r || c) && i.push(o);
3377
+ }), i;
3352
3378
  }
3353
3379
  /**
3354
3380
  * Searches edges by relationship (case-insensitive)
3355
3381
  * @returns Array of matching edges with source/target node info
3356
3382
  */
3357
3383
  searchEdges(e) {
3358
- var i;
3384
+ var o;
3359
3385
  if (!e || e.trim() === "")
3360
3386
  return [];
3361
- const s = e.toLowerCase().trim(), t = this.edgeManager.getAllEdges(), o = [];
3387
+ const s = e.toLowerCase().trim(), t = this.edgeManager.getAllEdges(), i = [];
3362
3388
  for (const a of t)
3363
- if ((i = a.relationship) == null ? void 0 : i.toLowerCase().includes(s)) {
3389
+ if ((o = a.relationship) == null ? void 0 : o.toLowerCase().includes(s)) {
3364
3390
  const c = this.nodeManager.getNode(a.source), h = this.nodeManager.getNode(a.target);
3365
- c && h && o.push({ edge: a, sourceNode: c, targetNode: h });
3391
+ c && h && i.push({ edge: a, sourceNode: c, targetNode: h });
3366
3392
  }
3367
- return o;
3393
+ return i;
3368
3394
  }
3369
3395
  /**
3370
3396
  * Gets all nodes as an array
@@ -3406,11 +3432,11 @@ class Ht {
3406
3432
  },
3407
3433
  onEdgeHover: (s, t) => {
3408
3434
  if (s && t) {
3409
- const o = this.nodeManager.getNode(s.source), i = this.nodeManager.getNode(s.target);
3410
- o && i && this.edgeTooltipManager.show(
3435
+ const i = this.nodeManager.getNode(s.source), o = this.nodeManager.getNode(s.target);
3436
+ i && o && this.edgeTooltipManager.show(
3411
3437
  s,
3412
- o,
3413
3438
  i,
3439
+ o,
3414
3440
  t.clientX,
3415
3441
  t.clientY
3416
3442
  );
@@ -3418,8 +3444,8 @@ class Ht {
3418
3444
  this.edgeTooltipManager.hide();
3419
3445
  },
3420
3446
  onEdgeClick: (s) => {
3421
- const t = this.nodeManager.getNode(s.source), o = this.nodeManager.getNode(s.target);
3422
- t && o && this.edgePanelManager.show(s, t, o);
3447
+ const t = this.nodeManager.getNode(s.source), i = this.nodeManager.getNode(s.target);
3448
+ t && i && this.edgePanelManager.show(s, t, i);
3423
3449
  }
3424
3450
  }), this.graphData && (this.forceGraph2D.setData(this.graphData), this.forceGraph2D.syncFrom3D(this.nodeManager.getAllNodes())))) : (this.forceGraph2D && this.forceGraph2D.hide(), this.sceneManager.renderer.domElement.style.display = "block", this.rendererManager.start()), this.emit("viewChange", e));
3425
3451
  }
@@ -3434,7 +3460,7 @@ class Ht {
3434
3460
  */
3435
3461
  emit(e, ...s) {
3436
3462
  const t = this.eventCallbacks.get(e);
3437
- t && t.forEach((o) => o(...s));
3463
+ t && t.forEach((i) => i(...s));
3438
3464
  }
3439
3465
  /**
3440
3466
  * Sets physics parameters for both 3D and 2D views
@@ -3511,17 +3537,17 @@ class Ht {
3511
3537
  `, this.container.appendChild(this.devControls);
3512
3538
  const e = this.devControls.querySelector("#dev-repulsion"), s = this.devControls.querySelector("#dev-attraction"), t = this.devControls.querySelector("#dev-damping");
3513
3539
  e == null || e.addEventListener("input", () => {
3514
- const o = parseFloat(e.value);
3515
- this.setPhysicsParams({ repulsionStrength: o }), this.devControls.querySelector("#dev-repulsion-val").textContent = o.toString();
3540
+ const i = parseFloat(e.value);
3541
+ this.setPhysicsParams({ repulsionStrength: i }), this.devControls.querySelector("#dev-repulsion-val").textContent = i.toString();
3516
3542
  }), s == null || s.addEventListener("input", () => {
3517
- const o = parseFloat(s.value) / 1e3;
3518
- this.setPhysicsParams({ attractionStrength: o }), this.devControls.querySelector("#dev-attraction-val").textContent = o.toFixed(3);
3543
+ const i = parseFloat(s.value) / 1e3;
3544
+ this.setPhysicsParams({ attractionStrength: i }), this.devControls.querySelector("#dev-attraction-val").textContent = i.toFixed(3);
3519
3545
  }), t == null || t.addEventListener("input", () => {
3520
- const o = parseFloat(t.value) / 100;
3521
- this.setPhysicsParams({ damping: o }), this.devControls.querySelector("#dev-damping-val").textContent = o.toFixed(2);
3546
+ const i = parseFloat(t.value) / 100;
3547
+ this.setPhysicsParams({ damping: i }), this.devControls.querySelector("#dev-damping-val").textContent = i.toFixed(2);
3522
3548
  }), setInterval(() => {
3523
- const o = this.devControls.querySelector("#dev-node-count"), i = this.devControls.querySelector("#dev-edge-count"), a = this.devControls.querySelector("#dev-fps");
3524
- o && (o.textContent = this.getNodeCount().toString()), i && (i.textContent = this.getEdgeCount().toString()), a && (a.textContent = this.rendererManager.getFPS().toString());
3549
+ const i = this.devControls.querySelector("#dev-node-count"), o = this.devControls.querySelector("#dev-edge-count"), a = this.devControls.querySelector("#dev-fps");
3550
+ i && (i.textContent = this.getNodeCount().toString()), o && (o.textContent = this.getEdgeCount().toString()), a && (a.textContent = this.rendererManager.getFPS().toString());
3525
3551
  }, 500);
3526
3552
  }
3527
3553
  /**
@@ -3587,12 +3613,12 @@ const Oe = [
3587
3613
  ];
3588
3614
  function Dt(d = 30) {
3589
3615
  const e = [], s = [];
3590
- for (let o = 0; o < d; o++) {
3591
- const i = o < Oe.length ? Oe[o] : `Node ${o + 1}`;
3616
+ for (let i = 0; i < d; i++) {
3617
+ const o = i < Oe.length ? Oe[i] : `Node ${i + 1}`;
3592
3618
  e.push({
3593
- id: `node-${o}`,
3594
- label: i,
3595
- color: Fe[o % Fe.length],
3619
+ id: `node-${i}`,
3620
+ label: o,
3621
+ color: Fe[i % Fe.length],
3596
3622
  position: {
3597
3623
  x: (Math.random() - 0.5) * 60,
3598
3624
  y: (Math.random() - 0.5) * 60,
@@ -3600,20 +3626,20 @@ function Dt(d = 30) {
3600
3626
  }
3601
3627
  });
3602
3628
  }
3603
- for (let o = 1; o < d; o++) {
3604
- const i = Math.floor(Math.random() * o);
3629
+ for (let i = 1; i < d; i++) {
3630
+ const o = Math.floor(Math.random() * i);
3605
3631
  s.push({
3606
- source: `node-${o}`,
3607
- target: `node-${i}`,
3632
+ source: `node-${i}`,
3633
+ target: `node-${o}`,
3608
3634
  relationship: ee[Math.floor(Math.random() * ee.length)]
3609
3635
  });
3610
3636
  }
3611
3637
  const t = Math.floor(d * 0.5);
3612
- for (let o = 0; o < t; o++) {
3613
- const i = Math.floor(Math.random() * d);
3638
+ for (let i = 0; i < t; i++) {
3639
+ const o = Math.floor(Math.random() * d);
3614
3640
  let a = Math.floor(Math.random() * d);
3615
- i === a && (a = (a + 1) % d);
3616
- const r = `node-${i}`, c = `node-${a}`;
3641
+ o === a && (a = (a + 1) % d);
3642
+ const r = `node-${o}`, c = `node-${a}`;
3617
3643
  s.some(
3618
3644
  (p) => p.source === r && p.target === c || p.source === c && p.target === r
3619
3645
  ) || s.push({
@@ -3625,18 +3651,18 @@ function Dt(d = 30) {
3625
3651
  return { nodes: e, edges: s };
3626
3652
  }
3627
3653
  function At(d = 1e3) {
3628
- const e = [], s = [], t = Math.ceil(d / 50), o = [];
3629
- for (let i = 0; i < t; i++)
3630
- o.push({
3654
+ const e = [], s = [], t = Math.ceil(d / 50), i = [];
3655
+ for (let o = 0; o < t; o++)
3656
+ i.push({
3631
3657
  x: (Math.random() - 0.5) * 200,
3632
3658
  y: (Math.random() - 0.5) * 200,
3633
3659
  z: (Math.random() - 0.5) * 200
3634
3660
  });
3635
- for (let i = 0; i < d; i++) {
3636
- const a = o[i % t];
3661
+ for (let o = 0; o < d; o++) {
3662
+ const a = i[o % t];
3637
3663
  e.push({
3638
- id: `node-${i}`,
3639
- label: `N${i}`,
3664
+ id: `node-${o}`,
3665
+ label: `N${o}`,
3640
3666
  position: {
3641
3667
  x: a.x + (Math.random() - 0.5) * 40,
3642
3668
  y: a.y + (Math.random() - 0.5) * 40,
@@ -3644,16 +3670,16 @@ function At(d = 1e3) {
3644
3670
  }
3645
3671
  });
3646
3672
  }
3647
- for (let i = 1; i < d; i++) {
3648
- const a = Math.floor(i / 50) * 50, r = a === 0 ? Math.floor(Math.random() * i) : a + Math.floor(Math.random() * Math.min(i - a, 50));
3673
+ for (let o = 1; o < d; o++) {
3674
+ const a = Math.floor(o / 50) * 50, r = a === 0 ? Math.floor(Math.random() * o) : a + Math.floor(Math.random() * Math.min(o - a, 50));
3649
3675
  s.push({
3650
- source: `node-${i}`,
3651
- target: `node-${Math.min(r, i - 1)}`,
3676
+ source: `node-${o}`,
3677
+ target: `node-${Math.min(r, o - 1)}`,
3652
3678
  relationship: "links to"
3653
3679
  });
3654
3680
  }
3655
- for (let i = 1; i < t; i++) {
3656
- const a = i * 50, r = (i - 1) * 50 + Math.floor(Math.random() * 50);
3681
+ for (let o = 1; o < t; o++) {
3682
+ const a = o * 50, r = (o - 1) * 50 + Math.floor(Math.random() * 50);
3657
3683
  s.push({
3658
3684
  source: `node-${a}`,
3659
3685
  target: `node-${r}`,