force-3d-graph 1.3.6 → 1.3.7

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.
@@ -1,8 +1,8 @@
1
- var ot = Object.defineProperty;
2
- var nt = (h, e, s) => e in h ? ot(h, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : h[e] = s;
3
- var l = (h, e, s) => nt(h, typeof e != "symbol" ? e + "" : e, s);
4
- import * as y from "three";
5
- import { EventDispatcher as at, Vector3 as S, MOUSE as $, TOUCH as G, Spherical as ze, Quaternion as ke, Vector2 as k, Ray as rt, Plane as lt, MathUtils as ct } from "three";
1
+ var it = Object.defineProperty;
2
+ var ot = (h, e, s) => e in h ? it(h, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : h[e] = s;
3
+ var l = (h, e, s) => ot(h, typeof e != "symbol" ? e + "" : e, s);
4
+ import * as x from "three";
5
+ import { EventDispatcher as nt, Vector3 as S, MOUSE as j, TOUCH as $, Spherical as Se, Quaternion as ze, Vector2 as k, Ray as at, Plane as rt, MathUtils as lt } from "three";
6
6
  const P = {
7
7
  backgroundColor: 657930,
8
8
  cameraPosition: { x: 0, y: 0, z: 80 },
@@ -32,8 +32,8 @@ const P = {
32
32
  targetFPS: 60,
33
33
  maxVisibleNodes: 1e4
34
34
  };
35
- var X = /* @__PURE__ */ ((h) => (h[h.HIGH = 0] = "HIGH", h[h.MEDIUM = 1] = "MEDIUM", h[h.LOW = 2] = "LOW", h))(X || {});
36
- function dt() {
35
+ var _ = /* @__PURE__ */ ((h) => (h[h.HIGH = 0] = "HIGH", h[h.MEDIUM = 1] = "MEDIUM", h[h.LOW = 2] = "LOW", h))(_ || {});
36
+ function ct() {
37
37
  const h = document.createElement("div");
38
38
  return h.id = "force-graph-3d-container", h.style.cssText = `
39
39
  width: 100%;
@@ -44,84 +44,84 @@ function dt() {
44
44
  overflow: hidden;
45
45
  `, document.body.appendChild(h), h;
46
46
  }
47
- function ht(h) {
48
- return h && h instanceof HTMLElement ? h : (console.warn("[ForceGraph3D] No container provided, creating one automatically"), dt());
47
+ function dt(h) {
48
+ return h && h instanceof HTMLElement ? h : (console.warn("[ForceGraph3D] No container provided, creating one automatically"), ct());
49
49
  }
50
- function Te(h) {
50
+ function ke(h) {
51
51
  const e = h.getBoundingClientRect();
52
52
  return {
53
53
  width: e.width || window.innerWidth,
54
54
  height: e.height || window.innerHeight
55
55
  };
56
56
  }
57
- function De(h) {
57
+ function Fe(h) {
58
58
  if (!h || typeof h != "object")
59
59
  return console.warn("[ForceGraph3D] Invalid node: must be an object"), !1;
60
60
  const e = h;
61
- return typeof e.id != "string" || e.id.trim() === "" ? (console.warn("[ForceGraph3D] Invalid node: id must be a non-empty string"), !1) : typeof e.label != "string" ? (console.warn("[ForceGraph3D] Invalid node: label must be a string"), !1) : e.color !== void 0 && typeof e.color != "number" ? (console.warn("[ForceGraph3D] Invalid node: color must be a number (hex)"), !1) : e.position !== void 0 && !gt(e.position) ? (console.warn("[ForceGraph3D] Invalid node: position must have x, y, z numbers"), !1) : !0;
61
+ return typeof e.id != "string" || e.id.trim() === "" ? (console.warn("[ForceGraph3D] Invalid node: id must be a non-empty string"), !1) : typeof e.label != "string" ? (console.warn("[ForceGraph3D] Invalid node: label must be a string"), !1) : e.color !== void 0 && typeof e.color != "number" ? (console.warn("[ForceGraph3D] Invalid node: color must be a number (hex)"), !1) : e.position !== void 0 && !pt(e.position) ? (console.warn("[ForceGraph3D] Invalid node: position must have x, y, z numbers"), !1) : !0;
62
62
  }
63
- function He(h) {
63
+ function De(h) {
64
64
  if (!h || typeof h != "object")
65
65
  return console.warn("[ForceGraph3D] Invalid edge: must be an object"), !1;
66
66
  const e = h;
67
67
  return typeof e.source != "string" || e.source.trim() === "" ? (console.warn("[ForceGraph3D] Invalid edge: source must be a non-empty string"), !1) : typeof e.target != "string" || e.target.trim() === "" ? (console.warn("[ForceGraph3D] Invalid edge: target must be a non-empty string"), !1) : !0;
68
68
  }
69
- function pt(h) {
69
+ function ht(h) {
70
70
  return typeof h != "string" || h.trim() === "" ? (console.warn("[ForceGraph3D] Invalid node ID: must be a non-empty string"), !1) : !0;
71
71
  }
72
- function gt(h) {
72
+ function pt(h) {
73
73
  if (!h || typeof h != "object") return !1;
74
74
  const e = h;
75
75
  return typeof e.x == "number" && typeof e.y == "number" && typeof e.z == "number";
76
76
  }
77
- function H(h, e) {
77
+ function Dt(h, e) {
78
78
  return h === e ? `${h}-${e}` : h < e ? `${h}-${e}` : `${e}-${h}`;
79
79
  }
80
- const Pe = { type: "change" }, ce = { type: "start" }, Le = { type: "end" }, J = new rt(), Re = new lt(), ut = Math.cos(70 * ct.DEG2RAD);
81
- class ft extends at {
80
+ const Te = { type: "change" }, le = { type: "start" }, Pe = { type: "end" }, Q = new at(), Le = new rt(), gt = Math.cos(70 * lt.DEG2RAD);
81
+ class ut extends nt {
82
82
  constructor(e, s) {
83
- super(), this.object = e, this.domElement = s, this.domElement.style.touchAction = "none", this.enabled = !0, this.target = new S(), this.cursor = new S(), this.minDistance = 0, this.maxDistance = 1 / 0, this.minZoom = 0, this.maxZoom = 1 / 0, this.minTargetRadius = 0, this.maxTargetRadius = 1 / 0, this.minPolarAngle = 0, this.maxPolarAngle = Math.PI, this.minAzimuthAngle = -1 / 0, this.maxAzimuthAngle = 1 / 0, this.enableDamping = !1, this.dampingFactor = 0.05, this.enableZoom = !0, this.zoomSpeed = 1, this.enableRotate = !0, this.rotateSpeed = 1, this.enablePan = !0, this.panSpeed = 1, this.screenSpacePanning = !0, this.keyPanSpeed = 7, this.zoomToCursor = !1, this.autoRotate = !1, this.autoRotateSpeed = 2, this.keys = { LEFT: "ArrowLeft", UP: "ArrowUp", RIGHT: "ArrowRight", BOTTOM: "ArrowDown" }, this.mouseButtons = { LEFT: $.ROTATE, MIDDLE: $.DOLLY, RIGHT: $.PAN }, this.touches = { ONE: G.ROTATE, TWO: G.DOLLY_PAN }, this.target0 = this.target.clone(), this.position0 = this.object.position.clone(), this.zoom0 = this.object.zoom, this._domElementKeyEvents = null, this.getPolarAngle = function() {
83
+ super(), this.object = e, this.domElement = s, this.domElement.style.touchAction = "none", this.enabled = !0, this.target = new S(), this.cursor = new S(), this.minDistance = 0, this.maxDistance = 1 / 0, this.minZoom = 0, this.maxZoom = 1 / 0, this.minTargetRadius = 0, this.maxTargetRadius = 1 / 0, this.minPolarAngle = 0, this.maxPolarAngle = Math.PI, this.minAzimuthAngle = -1 / 0, this.maxAzimuthAngle = 1 / 0, this.enableDamping = !1, this.dampingFactor = 0.05, this.enableZoom = !0, this.zoomSpeed = 1, this.enableRotate = !0, this.rotateSpeed = 1, this.enablePan = !0, this.panSpeed = 1, this.screenSpacePanning = !0, this.keyPanSpeed = 7, this.zoomToCursor = !1, this.autoRotate = !1, this.autoRotateSpeed = 2, this.keys = { LEFT: "ArrowLeft", UP: "ArrowUp", RIGHT: "ArrowRight", BOTTOM: "ArrowDown" }, this.mouseButtons = { LEFT: j.ROTATE, MIDDLE: j.DOLLY, RIGHT: j.PAN }, this.touches = { ONE: $.ROTATE, TWO: $.DOLLY_PAN }, this.target0 = this.target.clone(), this.position0 = this.object.position.clone(), this.zoom0 = this.object.zoom, this._domElementKeyEvents = null, this.getPolarAngle = function() {
84
84
  return r.phi;
85
85
  }, this.getAzimuthalAngle = function() {
86
86
  return r.theta;
87
87
  }, this.getDistance = function() {
88
88
  return this.object.position.distanceTo(this.target);
89
- }, this.listenToKeyEvents = function(n) {
90
- n.addEventListener("keydown", re), this._domElementKeyEvents = n;
89
+ }, this.listenToKeyEvents = function(a) {
90
+ a.addEventListener("keydown", ae), this._domElementKeyEvents = a;
91
91
  }, this.stopListenToKeyEvents = function() {
92
- this._domElementKeyEvents.removeEventListener("keydown", re), this._domElementKeyEvents = null;
92
+ this._domElementKeyEvents.removeEventListener("keydown", ae), this._domElementKeyEvents = null;
93
93
  }, this.saveState = function() {
94
94
  t.target0.copy(t.target), t.position0.copy(t.object.position), t.zoom0 = t.object.zoom;
95
95
  }, this.reset = function() {
96
- 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
+ t.target.copy(t.target0), t.object.position.copy(t.position0), t.object.zoom = t.zoom0, t.object.updateProjectionMatrix(), t.dispatchEvent(Te), t.update(), o = i.NONE;
97
97
  }, this.update = function() {
98
- const n = new S(), g = new ke().setFromUnitVectors(e.up, new S(0, 1, 0)), v = g.clone().invert(), w = new S(), C = new ke(), F = new S(), z = 2 * Math.PI;
99
- return function(it = null) {
100
- const Se = t.object.position;
101
- 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);
98
+ const a = new S(), g = new ze().setFromUnitVectors(e.up, new S(0, 1, 0)), v = g.clone().invert(), M = new S(), C = new ze(), F = new S(), z = 2 * Math.PI;
99
+ return function(st = null) {
100
+ const Ne = t.object.position;
101
+ a.copy(Ne).sub(t.target), a.applyQuaternion(g), r.setFromVector3(a), t.autoRotate && o === i.NONE && Y(He(st)), t.enableDamping ? (r.theta += d.theta * t.dampingFactor, r.phi += d.phi * t.dampingFactor) : (r.theta += d.theta, r.phi += d.phi);
102
102
  let R = t.minAzimuthAngle, I = t.maxAzimuthAngle;
103
- isFinite(R) && isFinite(I) && (R < -Math.PI ? R += z : R > Math.PI && (R -= z), I < -Math.PI ? I += z : I > Math.PI && (I -= z), R <= I ? r.theta = Math.max(R, Math.min(I, r.theta)) : r.theta = r.theta > (R + I) / 2 ? Math.max(R, r.theta) : Math.min(I, 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 && D || t.object.isOrthographicCamera ? r.radius = ne(r.radius) : r.radius = ne(r.radius * d), 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));
104
- let le = !1;
103
+ isFinite(R) && isFinite(I) && (R < -Math.PI ? R += z : R > Math.PI && (R -= z), I < -Math.PI ? I += z : I > Math.PI && (I -= z), R <= I ? r.theta = Math.max(R, Math.min(I, r.theta)) : r.theta = r.theta > (R + I) / 2 ? Math.max(R, r.theta) : Math.min(I, 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 && D || t.object.isOrthographicCamera ? r.radius = oe(r.radius) : r.radius = oe(r.radius * c), a.setFromSpherical(r), a.applyQuaternion(v), Ne.copy(t.target).add(a), t.object.lookAt(t.target), t.enableDamping === !0 ? (d.theta *= 1 - t.dampingFactor, d.phi *= 1 - t.dampingFactor, p.multiplyScalar(1 - t.dampingFactor)) : (d.set(0, 0, 0), p.set(0, 0, 0));
104
+ let re = !1;
105
105
  if (t.zoomToCursor && D) {
106
- let U = null;
106
+ let K = null;
107
107
  if (t.object.isPerspectiveCamera) {
108
- const _ = n.length();
109
- U = ne(_ * d);
110
- const Q = _ - U;
111
- t.object.position.addScaledVector(Y, Q), t.object.updateMatrixWorld();
108
+ const U = a.length();
109
+ K = oe(U * c);
110
+ const Z = U - K;
111
+ t.object.position.addScaledVector(G, Z), t.object.updateMatrixWorld();
112
112
  } else if (t.object.isOrthographicCamera) {
113
- const _ = new S(T.x, T.y, 0);
114
- _.unproject(t.object), t.object.zoom = Math.max(t.minZoom, Math.min(t.maxZoom, t.object.zoom / d)), t.object.updateProjectionMatrix(), le = !0;
115
- const Q = new S(T.x, T.y, 0);
116
- Q.unproject(t.object), t.object.position.sub(Q).add(_), t.object.updateMatrixWorld(), U = n.length();
113
+ const U = new S(T.x, T.y, 0);
114
+ U.unproject(t.object), t.object.zoom = Math.max(t.minZoom, Math.min(t.maxZoom, t.object.zoom / c)), t.object.updateProjectionMatrix(), re = !0;
115
+ const Z = new S(T.x, T.y, 0);
116
+ Z.unproject(t.object), t.object.position.sub(Z).add(U), t.object.updateMatrixWorld(), K = a.length();
117
117
  } else
118
118
  console.warn("WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled."), t.zoomToCursor = !1;
119
- U !== null && (this.screenSpacePanning ? t.target.set(0, 0, -1).transformDirection(t.object.matrix).multiplyScalar(U).add(t.object.position) : (J.origin.copy(t.object.position), J.direction.set(0, 0, -1).transformDirection(t.object.matrix), Math.abs(t.object.up.dot(J.direction)) < ut ? e.lookAt(t.target) : (Re.setFromNormalAndCoplanarPoint(t.object.up, t.target), J.intersectPlane(Re, t.target))));
120
- } else t.object.isOrthographicCamera && (t.object.zoom = Math.max(t.minZoom, Math.min(t.maxZoom, t.object.zoom / d)), t.object.updateProjectionMatrix(), le = !0);
121
- return d = 1, D = !1, le || w.distanceToSquared(t.object.position) > a || 8 * (1 - C.dot(t.object.quaternion)) > a || F.distanceToSquared(t.target) > 0 ? (t.dispatchEvent(Pe), w.copy(t.object.position), C.copy(t.object.quaternion), F.copy(t.target), !0) : !1;
119
+ K !== null && (this.screenSpacePanning ? t.target.set(0, 0, -1).transformDirection(t.object.matrix).multiplyScalar(K).add(t.object.position) : (Q.origin.copy(t.object.position), Q.direction.set(0, 0, -1).transformDirection(t.object.matrix), Math.abs(t.object.up.dot(Q.direction)) < gt ? e.lookAt(t.target) : (Le.setFromNormalAndCoplanarPoint(t.object.up, t.target), Q.intersectPlane(Le, t.target))));
120
+ } else t.object.isOrthographicCamera && (t.object.zoom = Math.max(t.minZoom, Math.min(t.maxZoom, t.object.zoom / c)), t.object.updateProjectionMatrix(), re = !0);
121
+ return c = 1, D = !1, re || M.distanceToSquared(t.object.position) > n || 8 * (1 - C.dot(t.object.quaternion)) > n || F.distanceToSquared(t.target) > 0 ? (t.dispatchEvent(Te), M.copy(t.object.position), C.copy(t.object.quaternion), F.copy(t.target), !0) : !1;
122
122
  };
123
123
  }(), this.dispose = function() {
124
- 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
+ t.domElement.removeEventListener("contextmenu", Ee), t.domElement.removeEventListener("pointerdown", ve), t.domElement.removeEventListener("pointercancel", B), t.domElement.removeEventListener("wheel", we), t.domElement.removeEventListener("pointermove", ne), t.domElement.removeEventListener("pointerup", B), t._domElementKeyEvents !== null && (t._domElementKeyEvents.removeEventListener("keydown", ae), t._domElementKeyEvents = null);
125
125
  };
126
126
  const t = this, i = {
127
127
  NONE: -1,
@@ -134,174 +134,174 @@ class ft extends at {
134
134
  TOUCH_DOLLY_ROTATE: 6
135
135
  };
136
136
  let o = i.NONE;
137
- const a = 1e-6, r = new ze(), c = new ze();
138
- let d = 1;
139
- const p = new S(), x = new k(), m = new k(), u = new k(), f = new k(), b = new k(), M = new k(), N = new k(), O = new k(), L = new k(), Y = new S(), T = new k();
137
+ const n = 1e-6, r = new Se(), d = new Se();
138
+ let c = 1;
139
+ const p = new S(), f = new k(), m = new k(), u = new k(), y = new k(), b = new k(), w = new k(), N = new k(), O = new k(), L = new k(), G = new S(), T = new k();
140
140
  let D = !1;
141
- const E = [], q = {};
142
- let se = !1;
143
- function Ae(n) {
144
- return n !== null ? 2 * Math.PI / 60 * t.autoRotateSpeed * n : 2 * Math.PI / 60 / 60 * t.autoRotateSpeed;
141
+ const E = [], V = {};
142
+ let te = !1;
143
+ function He(a) {
144
+ return a !== null ? 2 * Math.PI / 60 * t.autoRotateSpeed * a : 2 * Math.PI / 60 / 60 * t.autoRotateSpeed;
145
145
  }
146
- function W(n) {
147
- const g = Math.abs(n * 0.01);
146
+ function q(a) {
147
+ const g = Math.abs(a * 0.01);
148
148
  return Math.pow(0.95, t.zoomSpeed * g);
149
149
  }
150
- function B(n) {
151
- c.theta -= n;
150
+ function Y(a) {
151
+ d.theta -= a;
152
152
  }
153
- function Z(n) {
154
- c.phi -= n;
153
+ function W(a) {
154
+ d.phi -= a;
155
155
  }
156
- const de = function() {
157
- const n = new S();
158
- return function(v, w) {
159
- n.setFromMatrixColumn(w, 0), n.multiplyScalar(-v), p.add(n);
156
+ const ce = function() {
157
+ const a = new S();
158
+ return function(v, M) {
159
+ a.setFromMatrixColumn(M, 0), a.multiplyScalar(-v), p.add(a);
160
160
  };
161
- }(), he = function() {
162
- const n = new S();
163
- return function(v, w) {
164
- t.screenSpacePanning === !0 ? n.setFromMatrixColumn(w, 1) : (n.setFromMatrixColumn(w, 0), n.crossVectors(t.object.up, n)), n.multiplyScalar(v), p.add(n);
161
+ }(), de = function() {
162
+ const a = new S();
163
+ return function(v, M) {
164
+ t.screenSpacePanning === !0 ? a.setFromMatrixColumn(M, 1) : (a.setFromMatrixColumn(M, 0), a.crossVectors(t.object.up, a)), a.multiplyScalar(v), p.add(a);
165
165
  };
166
- }(), A = function() {
167
- const n = new S();
168
- return function(v, w) {
166
+ }(), H = function() {
167
+ const a = new S();
168
+ return function(v, M) {
169
169
  const C = t.domElement;
170
170
  if (t.object.isPerspectiveCamera) {
171
171
  const F = t.object.position;
172
- n.copy(F).sub(t.target);
173
- let z = n.length();
174
- z *= Math.tan(t.object.fov / 2 * Math.PI / 180), de(2 * v * z / C.clientHeight, t.object.matrix), he(2 * w * z / C.clientHeight, t.object.matrix);
175
- } else t.object.isOrthographicCamera ? (de(v * (t.object.right - t.object.left) / t.object.zoom / C.clientWidth, t.object.matrix), he(w * (t.object.top - t.object.bottom) / t.object.zoom / C.clientHeight, t.object.matrix)) : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."), t.enablePan = !1);
172
+ a.copy(F).sub(t.target);
173
+ let z = a.length();
174
+ z *= Math.tan(t.object.fov / 2 * Math.PI / 180), ce(2 * v * z / C.clientHeight, t.object.matrix), de(2 * M * z / C.clientHeight, t.object.matrix);
175
+ } else t.object.isOrthographicCamera ? (ce(v * (t.object.right - t.object.left) / t.object.zoom / C.clientWidth, t.object.matrix), de(M * (t.object.top - t.object.bottom) / t.object.zoom / C.clientHeight, t.object.matrix)) : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."), t.enablePan = !1);
176
176
  };
177
177
  }();
178
- function ie(n) {
179
- t.object.isPerspectiveCamera || t.object.isOrthographicCamera ? d /= n : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."), t.enableZoom = !1);
178
+ function se(a) {
179
+ t.object.isPerspectiveCamera || t.object.isOrthographicCamera ? c /= a : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."), t.enableZoom = !1);
180
180
  }
181
- function pe(n) {
182
- t.object.isPerspectiveCamera || t.object.isOrthographicCamera ? d *= n : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."), t.enableZoom = !1);
181
+ function he(a) {
182
+ t.object.isPerspectiveCamera || t.object.isOrthographicCamera ? c *= a : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."), t.enableZoom = !1);
183
183
  }
184
- function oe(n, g) {
184
+ function ie(a, g) {
185
185
  if (!t.zoomToCursor)
186
186
  return;
187
187
  D = !0;
188
- const v = t.domElement.getBoundingClientRect(), w = n - v.left, C = g - v.top, F = v.width, z = v.height;
189
- T.x = w / F * 2 - 1, T.y = -(C / z) * 2 + 1, Y.set(T.x, T.y, 1).unproject(t.object).sub(t.object.position).normalize();
188
+ const v = t.domElement.getBoundingClientRect(), M = a - v.left, C = g - v.top, F = v.width, z = v.height;
189
+ T.x = M / F * 2 - 1, T.y = -(C / z) * 2 + 1, G.set(T.x, T.y, 1).unproject(t.object).sub(t.object.position).normalize();
190
190
  }
191
- function ne(n) {
192
- return Math.max(t.minDistance, Math.min(t.maxDistance, n));
191
+ function oe(a) {
192
+ return Math.max(t.minDistance, Math.min(t.maxDistance, a));
193
193
  }
194
- function ge(n) {
195
- x.set(n.clientX, n.clientY);
194
+ function pe(a) {
195
+ f.set(a.clientX, a.clientY);
196
196
  }
197
- function je(n) {
198
- oe(n.clientX, n.clientX), N.set(n.clientX, n.clientY);
197
+ function Ae(a) {
198
+ ie(a.clientX, a.clientX), N.set(a.clientX, a.clientY);
199
199
  }
200
- function ue(n) {
201
- f.set(n.clientX, n.clientY);
200
+ function ge(a) {
201
+ y.set(a.clientX, a.clientY);
202
202
  }
203
- function $e(n) {
204
- m.set(n.clientX, n.clientY), u.subVectors(m, x).multiplyScalar(t.rotateSpeed);
203
+ function je(a) {
204
+ m.set(a.clientX, a.clientY), u.subVectors(m, f).multiplyScalar(t.rotateSpeed);
205
205
  const g = t.domElement;
206
- B(2 * Math.PI * u.x / g.clientHeight), Z(2 * Math.PI * u.y / g.clientHeight), x.copy(m), t.update();
206
+ Y(2 * Math.PI * u.x / g.clientHeight), W(2 * Math.PI * u.y / g.clientHeight), f.copy(m), t.update();
207
207
  }
208
- function Ge(n) {
209
- O.set(n.clientX, n.clientY), L.subVectors(O, N), L.y > 0 ? ie(W(L.y)) : L.y < 0 && pe(W(L.y)), N.copy(O), t.update();
208
+ function $e(a) {
209
+ O.set(a.clientX, a.clientY), L.subVectors(O, N), L.y > 0 ? se(q(L.y)) : L.y < 0 && he(q(L.y)), N.copy(O), t.update();
210
210
  }
211
- function Ye(n) {
212
- b.set(n.clientX, n.clientY), M.subVectors(b, f).multiplyScalar(t.panSpeed), A(M.x, M.y), f.copy(b), t.update();
211
+ function Ge(a) {
212
+ b.set(a.clientX, a.clientY), w.subVectors(b, y).multiplyScalar(t.panSpeed), H(w.x, w.y), y.copy(b), t.update();
213
213
  }
214
- function Be(n) {
215
- oe(n.clientX, n.clientY), n.deltaY < 0 ? pe(W(n.deltaY)) : n.deltaY > 0 && ie(W(n.deltaY)), t.update();
214
+ function Ye(a) {
215
+ ie(a.clientX, a.clientY), a.deltaY < 0 ? he(q(a.deltaY)) : a.deltaY > 0 && se(q(a.deltaY)), t.update();
216
216
  }
217
- function Ke(n) {
217
+ function Be(a) {
218
218
  let g = !1;
219
- switch (n.code) {
219
+ switch (a.code) {
220
220
  case t.keys.UP:
221
- n.ctrlKey || n.metaKey || n.shiftKey ? Z(2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(0, t.keyPanSpeed), g = !0;
221
+ a.ctrlKey || a.metaKey || a.shiftKey ? W(2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : H(0, t.keyPanSpeed), g = !0;
222
222
  break;
223
223
  case t.keys.BOTTOM:
224
- n.ctrlKey || n.metaKey || n.shiftKey ? Z(-2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(0, -t.keyPanSpeed), g = !0;
224
+ a.ctrlKey || a.metaKey || a.shiftKey ? W(-2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : H(0, -t.keyPanSpeed), g = !0;
225
225
  break;
226
226
  case t.keys.LEFT:
227
- n.ctrlKey || n.metaKey || n.shiftKey ? B(2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(t.keyPanSpeed, 0), g = !0;
227
+ a.ctrlKey || a.metaKey || a.shiftKey ? Y(2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : H(t.keyPanSpeed, 0), g = !0;
228
228
  break;
229
229
  case t.keys.RIGHT:
230
- n.ctrlKey || n.metaKey || n.shiftKey ? B(-2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(-t.keyPanSpeed, 0), g = !0;
230
+ a.ctrlKey || a.metaKey || a.shiftKey ? Y(-2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : H(-t.keyPanSpeed, 0), g = !0;
231
231
  break;
232
232
  }
233
- g && (n.preventDefault(), t.update());
233
+ g && (a.preventDefault(), t.update());
234
234
  }
235
- function fe(n) {
235
+ function ue(a) {
236
236
  if (E.length === 1)
237
- x.set(n.pageX, n.pageY);
237
+ f.set(a.pageX, a.pageY);
238
238
  else {
239
- const g = j(n), v = 0.5 * (n.pageX + g.x), w = 0.5 * (n.pageY + g.y);
240
- x.set(v, w);
239
+ const g = A(a), v = 0.5 * (a.pageX + g.x), M = 0.5 * (a.pageY + g.y);
240
+ f.set(v, M);
241
241
  }
242
242
  }
243
- function me(n) {
243
+ function fe(a) {
244
244
  if (E.length === 1)
245
- f.set(n.pageX, n.pageY);
245
+ y.set(a.pageX, a.pageY);
246
246
  else {
247
- const g = j(n), v = 0.5 * (n.pageX + g.x), w = 0.5 * (n.pageY + g.y);
248
- f.set(v, w);
247
+ const g = A(a), v = 0.5 * (a.pageX + g.x), M = 0.5 * (a.pageY + g.y);
248
+ y.set(v, M);
249
249
  }
250
250
  }
251
- function ye(n) {
252
- const g = j(n), v = n.pageX - g.x, w = n.pageY - g.y, C = Math.sqrt(v * v + w * w);
251
+ function me(a) {
252
+ const g = A(a), v = a.pageX - g.x, M = a.pageY - g.y, C = Math.sqrt(v * v + M * M);
253
253
  N.set(0, C);
254
254
  }
255
- function Ue(n) {
256
- t.enableZoom && ye(n), t.enablePan && me(n);
255
+ function Ke(a) {
256
+ t.enableZoom && me(a), t.enablePan && fe(a);
257
257
  }
258
- function _e(n) {
259
- t.enableZoom && ye(n), t.enableRotate && fe(n);
258
+ function Ue(a) {
259
+ t.enableZoom && me(a), t.enableRotate && ue(a);
260
260
  }
261
- function xe(n) {
261
+ function ye(a) {
262
262
  if (E.length == 1)
263
- m.set(n.pageX, n.pageY);
263
+ m.set(a.pageX, a.pageY);
264
264
  else {
265
- const v = j(n), w = 0.5 * (n.pageX + v.x), C = 0.5 * (n.pageY + v.y);
266
- m.set(w, C);
265
+ const v = A(a), M = 0.5 * (a.pageX + v.x), C = 0.5 * (a.pageY + v.y);
266
+ m.set(M, C);
267
267
  }
268
- u.subVectors(m, x).multiplyScalar(t.rotateSpeed);
268
+ u.subVectors(m, f).multiplyScalar(t.rotateSpeed);
269
269
  const g = t.domElement;
270
- B(2 * Math.PI * u.x / g.clientHeight), Z(2 * Math.PI * u.y / g.clientHeight), x.copy(m);
270
+ Y(2 * Math.PI * u.x / g.clientHeight), W(2 * Math.PI * u.y / g.clientHeight), f.copy(m);
271
271
  }
272
- function be(n) {
272
+ function xe(a) {
273
273
  if (E.length === 1)
274
- b.set(n.pageX, n.pageY);
274
+ b.set(a.pageX, a.pageY);
275
275
  else {
276
- const g = j(n), v = 0.5 * (n.pageX + g.x), w = 0.5 * (n.pageY + g.y);
277
- b.set(v, w);
276
+ const g = A(a), v = 0.5 * (a.pageX + g.x), M = 0.5 * (a.pageY + g.y);
277
+ b.set(v, M);
278
278
  }
279
- M.subVectors(b, f).multiplyScalar(t.panSpeed), A(M.x, M.y), f.copy(b);
279
+ w.subVectors(b, y).multiplyScalar(t.panSpeed), H(w.x, w.y), y.copy(b);
280
280
  }
281
- function ve(n) {
282
- const g = j(n), v = n.pageX - g.x, w = n.pageY - g.y, C = Math.sqrt(v * v + w * w);
283
- O.set(0, C), L.set(0, Math.pow(O.y / N.y, t.zoomSpeed)), ie(L.y), N.copy(O);
284
- const F = (n.pageX + g.x) * 0.5, z = (n.pageY + g.y) * 0.5;
285
- oe(F, z);
281
+ function be(a) {
282
+ const g = A(a), v = a.pageX - g.x, M = a.pageY - g.y, C = Math.sqrt(v * v + M * M);
283
+ O.set(0, C), L.set(0, Math.pow(O.y / N.y, t.zoomSpeed)), se(L.y), N.copy(O);
284
+ const F = (a.pageX + g.x) * 0.5, z = (a.pageY + g.y) * 0.5;
285
+ ie(F, z);
286
286
  }
287
- function Xe(n) {
288
- t.enableZoom && ve(n), t.enablePan && be(n);
287
+ function _e(a) {
288
+ t.enableZoom && be(a), t.enablePan && xe(a);
289
289
  }
290
- function Ve(n) {
291
- t.enableZoom && ve(n), t.enableRotate && xe(n);
290
+ function Xe(a) {
291
+ t.enableZoom && be(a), t.enableRotate && ye(a);
292
292
  }
293
- function Me(n) {
294
- t.enabled !== !1 && (E.length === 0 && (t.domElement.setPointerCapture(n.pointerId), t.domElement.addEventListener("pointermove", ae), t.domElement.addEventListener("pointerup", K)), tt(n), n.pointerType === "touch" ? Je(n) : qe(n));
293
+ function ve(a) {
294
+ t.enabled !== !1 && (E.length === 0 && (t.domElement.setPointerCapture(a.pointerId), t.domElement.addEventListener("pointermove", ne), t.domElement.addEventListener("pointerup", B)), et(a), a.pointerType === "touch" ? Qe(a) : Ve(a));
295
295
  }
296
- function ae(n) {
297
- t.enabled !== !1 && (n.pointerType === "touch" ? et(n) : We(n));
296
+ function ne(a) {
297
+ t.enabled !== !1 && (a.pointerType === "touch" ? Je(a) : qe(a));
298
298
  }
299
- function K(n) {
300
- st(n), E.length === 0 && (t.domElement.releasePointerCapture(n.pointerId), t.domElement.removeEventListener("pointermove", ae), t.domElement.removeEventListener("pointerup", K)), t.dispatchEvent(Le), o = i.NONE;
299
+ function B(a) {
300
+ tt(a), E.length === 0 && (t.domElement.releasePointerCapture(a.pointerId), t.domElement.removeEventListener("pointermove", ne), t.domElement.removeEventListener("pointerup", B)), t.dispatchEvent(Pe), o = i.NONE;
301
301
  }
302
- function qe(n) {
302
+ function Ve(a) {
303
303
  let g;
304
- switch (n.button) {
304
+ switch (a.button) {
305
305
  case 0:
306
306
  g = t.mouseButtons.LEFT;
307
307
  break;
@@ -315,57 +315,57 @@ class ft extends at {
315
315
  g = -1;
316
316
  }
317
317
  switch (g) {
318
- case $.DOLLY:
318
+ case j.DOLLY:
319
319
  if (t.enableZoom === !1) return;
320
- je(n), o = i.DOLLY;
320
+ Ae(a), o = i.DOLLY;
321
321
  break;
322
- case $.ROTATE:
323
- if (n.ctrlKey || n.metaKey || n.shiftKey) {
322
+ case j.ROTATE:
323
+ if (a.ctrlKey || a.metaKey || a.shiftKey) {
324
324
  if (t.enablePan === !1) return;
325
- ue(n), o = i.PAN;
325
+ ge(a), o = i.PAN;
326
326
  } else {
327
327
  if (t.enableRotate === !1) return;
328
- ge(n), o = i.ROTATE;
328
+ pe(a), o = i.ROTATE;
329
329
  }
330
330
  break;
331
- case $.PAN:
332
- if (n.ctrlKey || n.metaKey || n.shiftKey) {
331
+ case j.PAN:
332
+ if (a.ctrlKey || a.metaKey || a.shiftKey) {
333
333
  if (t.enableRotate === !1) return;
334
- ge(n), o = i.ROTATE;
334
+ pe(a), o = i.ROTATE;
335
335
  } else {
336
336
  if (t.enablePan === !1) return;
337
- ue(n), o = i.PAN;
337
+ ge(a), o = i.PAN;
338
338
  }
339
339
  break;
340
340
  default:
341
341
  o = i.NONE;
342
342
  }
343
- o !== i.NONE && t.dispatchEvent(ce);
343
+ o !== i.NONE && t.dispatchEvent(le);
344
344
  }
345
- function We(n) {
345
+ function qe(a) {
346
346
  switch (o) {
347
347
  case i.ROTATE:
348
348
  if (t.enableRotate === !1) return;
349
- $e(n);
349
+ je(a);
350
350
  break;
351
351
  case i.DOLLY:
352
352
  if (t.enableZoom === !1) return;
353
- Ge(n);
353
+ $e(a);
354
354
  break;
355
355
  case i.PAN:
356
356
  if (t.enablePan === !1) return;
357
- Ye(n);
357
+ Ge(a);
358
358
  break;
359
359
  }
360
360
  }
361
- function we(n) {
362
- t.enabled === !1 || t.enableZoom === !1 || o !== i.NONE || (n.preventDefault(), t.dispatchEvent(ce), Be(Ze(n)), t.dispatchEvent(Le));
361
+ function we(a) {
362
+ t.enabled === !1 || t.enableZoom === !1 || o !== i.NONE || (a.preventDefault(), t.dispatchEvent(le), Ye(We(a)), t.dispatchEvent(Pe));
363
363
  }
364
- function Ze(n) {
365
- const g = n.deltaMode, v = {
366
- clientX: n.clientX,
367
- clientY: n.clientY,
368
- deltaY: n.deltaY
364
+ function We(a) {
365
+ const g = a.deltaMode, v = {
366
+ clientX: a.clientX,
367
+ clientY: a.clientY,
368
+ deltaY: a.deltaY
369
369
  };
370
370
  switch (g) {
371
371
  case 1:
@@ -375,28 +375,28 @@ class ft extends at {
375
375
  v.deltaY *= 100;
376
376
  break;
377
377
  }
378
- return n.ctrlKey && !se && (v.deltaY *= 10), v;
378
+ return a.ctrlKey && !te && (v.deltaY *= 10), v;
379
379
  }
380
- function Qe(n) {
381
- n.key === "Control" && (se = !0, document.addEventListener("keyup", Ee, { passive: !0, capture: !0 }));
380
+ function Ze(a) {
381
+ a.key === "Control" && (te = !0, document.addEventListener("keyup", Me, { passive: !0, capture: !0 }));
382
382
  }
383
- function Ee(n) {
384
- n.key === "Control" && (se = !1, document.removeEventListener("keyup", Ee, { passive: !0, capture: !0 }));
383
+ function Me(a) {
384
+ a.key === "Control" && (te = !1, document.removeEventListener("keyup", Me, { passive: !0, capture: !0 }));
385
385
  }
386
- function re(n) {
387
- t.enabled === !1 || t.enablePan === !1 || Ke(n);
386
+ function ae(a) {
387
+ t.enabled === !1 || t.enablePan === !1 || Be(a);
388
388
  }
389
- function Je(n) {
390
- switch (Ne(n), E.length) {
389
+ function Qe(a) {
390
+ switch (Ce(a), E.length) {
391
391
  case 1:
392
392
  switch (t.touches.ONE) {
393
- case G.ROTATE:
393
+ case $.ROTATE:
394
394
  if (t.enableRotate === !1) return;
395
- fe(n), o = i.TOUCH_ROTATE;
395
+ ue(a), o = i.TOUCH_ROTATE;
396
396
  break;
397
- case G.PAN:
397
+ case $.PAN:
398
398
  if (t.enablePan === !1) return;
399
- me(n), o = i.TOUCH_PAN;
399
+ fe(a), o = i.TOUCH_PAN;
400
400
  break;
401
401
  default:
402
402
  o = i.NONE;
@@ -404,13 +404,13 @@ class ft extends at {
404
404
  break;
405
405
  case 2:
406
406
  switch (t.touches.TWO) {
407
- case G.DOLLY_PAN:
407
+ case $.DOLLY_PAN:
408
408
  if (t.enableZoom === !1 && t.enablePan === !1) return;
409
- Ue(n), o = i.TOUCH_DOLLY_PAN;
409
+ Ke(a), o = i.TOUCH_DOLLY_PAN;
410
410
  break;
411
- case G.DOLLY_ROTATE:
411
+ case $.DOLLY_ROTATE:
412
412
  if (t.enableZoom === !1 && t.enableRotate === !1) return;
413
- _e(n), o = i.TOUCH_DOLLY_ROTATE;
413
+ Ue(a), o = i.TOUCH_DOLLY_ROTATE;
414
414
  break;
415
415
  default:
416
416
  o = i.NONE;
@@ -419,56 +419,56 @@ class ft extends at {
419
419
  default:
420
420
  o = i.NONE;
421
421
  }
422
- o !== i.NONE && t.dispatchEvent(ce);
422
+ o !== i.NONE && t.dispatchEvent(le);
423
423
  }
424
- function et(n) {
425
- switch (Ne(n), o) {
424
+ function Je(a) {
425
+ switch (Ce(a), o) {
426
426
  case i.TOUCH_ROTATE:
427
427
  if (t.enableRotate === !1) return;
428
- xe(n), t.update();
428
+ ye(a), t.update();
429
429
  break;
430
430
  case i.TOUCH_PAN:
431
431
  if (t.enablePan === !1) return;
432
- be(n), t.update();
432
+ xe(a), t.update();
433
433
  break;
434
434
  case i.TOUCH_DOLLY_PAN:
435
435
  if (t.enableZoom === !1 && t.enablePan === !1) return;
436
- Xe(n), t.update();
436
+ _e(a), t.update();
437
437
  break;
438
438
  case i.TOUCH_DOLLY_ROTATE:
439
439
  if (t.enableZoom === !1 && t.enableRotate === !1) return;
440
- Ve(n), t.update();
440
+ Xe(a), t.update();
441
441
  break;
442
442
  default:
443
443
  o = i.NONE;
444
444
  }
445
445
  }
446
- function Ce(n) {
447
- t.enabled !== !1 && n.preventDefault();
446
+ function Ee(a) {
447
+ t.enabled !== !1 && a.preventDefault();
448
448
  }
449
- function tt(n) {
450
- E.push(n.pointerId);
449
+ function et(a) {
450
+ E.push(a.pointerId);
451
451
  }
452
- function st(n) {
453
- delete q[n.pointerId];
452
+ function tt(a) {
453
+ delete V[a.pointerId];
454
454
  for (let g = 0; g < E.length; g++)
455
- if (E[g] == n.pointerId) {
455
+ if (E[g] == a.pointerId) {
456
456
  E.splice(g, 1);
457
457
  return;
458
458
  }
459
459
  }
460
- function Ne(n) {
461
- let g = q[n.pointerId];
462
- g === void 0 && (g = new k(), q[n.pointerId] = g), g.set(n.pageX, n.pageY);
460
+ function Ce(a) {
461
+ let g = V[a.pointerId];
462
+ g === void 0 && (g = new k(), V[a.pointerId] = g), g.set(a.pageX, a.pageY);
463
463
  }
464
- function j(n) {
465
- const g = n.pointerId === E[0] ? E[1] : E[0];
466
- return q[g];
464
+ function A(a) {
465
+ const g = a.pointerId === E[0] ? E[1] : E[0];
466
+ return V[g];
467
467
  }
468
- t.domElement.addEventListener("contextmenu", Ce), t.domElement.addEventListener("pointerdown", Me), t.domElement.addEventListener("pointercancel", K), t.domElement.addEventListener("wheel", we, { passive: !1 }), document.addEventListener("keydown", Qe, { passive: !0, capture: !0 }), this.update();
468
+ t.domElement.addEventListener("contextmenu", Ee), t.domElement.addEventListener("pointerdown", ve), t.domElement.addEventListener("pointercancel", B), t.domElement.addEventListener("wheel", we, { passive: !1 }), document.addEventListener("keydown", Ze, { passive: !0, capture: !0 }), this.update();
469
469
  }
470
470
  }
471
- class mt {
471
+ class ft {
472
472
  constructor(e, s) {
473
473
  l(this, "scene");
474
474
  l(this, "camera");
@@ -476,42 +476,42 @@ class mt {
476
476
  l(this, "controls");
477
477
  l(this, "container");
478
478
  l(this, "resizeHandler");
479
- this.container = e, this.scene = new y.Scene(), this.scene.background = new y.Color(
479
+ this.container = e, this.scene = new x.Scene(), this.scene.background = new x.Color(
480
480
  s.backgroundColor ?? 657930
481
481
  );
482
- const { width: t, height: i } = Te(e), o = s.cameraFov ?? 75;
483
- this.camera = new y.PerspectiveCamera(o, t / i, 0.1, 2e3);
484
- const a = s.cameraPosition ?? { x: 0, y: 0, z: 80 };
485
- this.camera.position.set(a.x, a.y, a.z), this.renderer = new y.WebGLRenderer({
482
+ const { width: t, height: i } = ke(e), o = s.cameraFov ?? 75;
483
+ this.camera = new x.PerspectiveCamera(o, t / i, 0.1, 2e3);
484
+ const n = s.cameraPosition ?? { x: 0, y: 0, z: 80 };
485
+ this.camera.position.set(n.x, n.y, n.z), this.renderer = new x.WebGLRenderer({
486
486
  antialias: !0,
487
487
  alpha: !0,
488
488
  powerPreference: "high-performance"
489
- }), 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
+ }), this.renderer.setSize(t, i), this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)), this.renderer.toneMapping = x.ACESFilmicToneMapping, this.renderer.toneMappingExposure = 1, this.renderer.shadowMap.enabled = !0, this.renderer.shadowMap.type = x.PCFSoftShadowMap, e.appendChild(this.renderer.domElement), this.controls = new ut(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);
490
490
  }
491
491
  /**
492
492
  * Sets up scene lighting for gradient glass on dark background
493
493
  */
494
494
  setupLighting() {
495
- const e = new y.AmbientLight(16777215, 0.4);
495
+ const e = new x.AmbientLight(16777215, 0.4);
496
496
  this.scene.add(e);
497
- const s = new y.DirectionalLight(16777215, 0.9);
497
+ const s = new x.DirectionalLight(16777215, 0.9);
498
498
  s.position.set(50, 60, 40), s.castShadow = !0, s.shadow.mapSize.width = 1024, s.shadow.mapSize.height = 1024, this.scene.add(s);
499
- const t = new y.DirectionalLight(16773344, 0.4);
499
+ const t = new x.DirectionalLight(16773344, 0.4);
500
500
  t.position.set(-50, 30, -40), this.scene.add(t);
501
- const i = new y.DirectionalLight(16777215, 0.3);
501
+ const i = new x.DirectionalLight(16777215, 0.3);
502
502
  i.position.set(0, -30, -50), this.scene.add(i);
503
- const o = new y.PointLight(16750950, 0.5, 150);
503
+ const o = new x.PointLight(16750950, 0.5, 150);
504
504
  o.position.set(40, 20, 40), this.scene.add(o);
505
- const a = new y.PointLight(16764057, 0.4, 150);
506
- a.position.set(-40, -20, 40), this.scene.add(a);
507
- const r = new y.PointLight(6724095, 0.2, 100);
505
+ const n = new x.PointLight(16764057, 0.4, 150);
506
+ n.position.set(-40, -20, 40), this.scene.add(n);
507
+ const r = new x.PointLight(6724095, 0.2, 100);
508
508
  r.position.set(0, 40, -40), this.scene.add(r);
509
509
  }
510
510
  /**
511
511
  * Handle window resize
512
512
  */
513
513
  onWindowResize() {
514
- const { width: e, height: s } = Te(this.container);
514
+ const { width: e, height: s } = ke(this.container);
515
515
  this.camera.aspect = e / s, this.camera.updateProjectionMatrix(), this.renderer.setSize(e, s);
516
516
  }
517
517
  /**
@@ -546,7 +546,7 @@ class mt {
546
546
  * Gets the camera's forward direction
547
547
  */
548
548
  getCameraDirection() {
549
- const e = new y.Vector3();
549
+ const e = new x.Vector3();
550
550
  return this.camera.getWorldDirection(e), e;
551
551
  }
552
552
  /**
@@ -559,7 +559,7 @@ class mt {
559
559
  }
560
560
  }
561
561
  }
562
- const V = class V {
562
+ const X = class X {
563
563
  constructor(e, s) {
564
564
  l(this, "sceneManager");
565
565
  l(this, "nodeFactory");
@@ -578,18 +578,18 @@ const V = class V {
578
578
  * Call this before adding nodes in bulk.
579
579
  */
580
580
  static setExpectedNodeCount(e) {
581
- V.expectedNodeCount = e;
581
+ X.expectedNodeCount = e;
582
582
  }
583
583
  /**
584
584
  * Adds a node to the graph
585
585
  * @returns true if added, false if node already exists or invalid
586
586
  */
587
587
  addNode(e, s = 0) {
588
- if (!De(e))
588
+ if (!Fe(e))
589
589
  return !1;
590
590
  if (this.nodes.has(e.id))
591
591
  return console.warn(`[ForceGraph3D] Node with id "${e.id}" already exists`), !1;
592
- const t = Math.max(50, Math.cbrt(V.expectedNodeCount) * 10), i = e.position ?? {
592
+ const t = Math.max(50, Math.cbrt(X.expectedNodeCount) * 10), i = e.position ?? {
593
593
  x: (Math.random() - 0.5) * t,
594
594
  y: (Math.random() - 0.5) * t,
595
595
  z: (Math.random() - 0.5) * t
@@ -598,11 +598,11 @@ const V = class V {
598
598
  position: i,
599
599
  velocity: { x: 0, y: 0, z: 0 },
600
600
  mass: 1
601
- }, a = this.nodeFactory.createNode(
601
+ }, n = this.nodeFactory.createNode(
602
602
  { ...e, position: i },
603
603
  s
604
604
  );
605
- return this.sceneManager.add(a.group), this.nodes.set(e.id, o), this.nodeObjects.set(e.id, a), !0;
605
+ return this.sceneManager.add(n.group), this.nodes.set(e.id, o), this.nodeObjects.set(e.id, n), !0;
606
606
  }
607
607
  /**
608
608
  * Removes a node from the graph
@@ -693,16 +693,23 @@ const V = class V {
693
693
  }
694
694
  };
695
695
  // Scale spawn volume with expected graph size
696
- l(V, "expectedNodeCount", 100);
697
- let te = V;
698
- class yt {
696
+ l(X, "expectedNodeCount", 100);
697
+ let ee = X;
698
+ class mt {
699
699
  constructor(e, s, t) {
700
700
  l(this, "sceneManager");
701
701
  l(this, "nodeManager");
702
702
  l(this, "edgeFactory");
703
+ // Full relationship list (includes duplicates between same pair)
703
704
  l(this, "edges", []);
705
+ // One visual line per directed pair (source -> target)
704
706
  l(this, "edgeObjects", []);
707
+ // Tracks which directed pairs currently have at least one relationship
705
708
  l(this, "edgeKeySet", /* @__PURE__ */ new Set());
709
+ // Maps directed pair key to the relationship list for that pair
710
+ l(this, "edgeGroups", /* @__PURE__ */ new Map());
711
+ // Maps directed pair key to the corresponding visual line
712
+ l(this, "edgeObjectMap", /* @__PURE__ */ new Map());
706
713
  l(this, "highlightedEdgeKey", null);
707
714
  this.sceneManager = e, this.nodeManager = s, this.edgeFactory = t;
708
715
  }
@@ -710,68 +717,92 @@ class yt {
710
717
  * Checks if an edge exists
711
718
  */
712
719
  hasEdge(e, s) {
713
- const t = H(e, s);
720
+ const t = this.createDirectedEdgeKey(e, s);
714
721
  return this.edgeKeySet.has(t);
715
722
  }
716
723
  /**
717
724
  * Adds an edge to the graph
718
- * @returns true if added, false if edge already exists or nodes don't exist
725
+ * @returns true if added, false if invalid or nodes don't exist
719
726
  */
720
727
  addEdge(e) {
721
- if (!He(e))
728
+ if (!De(e))
722
729
  return !1;
723
730
  if (!this.nodeManager.hasNode(e.source))
724
731
  return console.warn(`[ForceGraph3D] Source node "${e.source}" does not exist`), !1;
725
732
  if (!this.nodeManager.hasNode(e.target))
726
733
  return console.warn(`[ForceGraph3D] Target node "${e.target}" does not exist`), !1;
727
- const s = H(e.source, e.target);
728
- if (this.edgeKeySet.has(s))
729
- return console.warn(`[ForceGraph3D] Edge "${e.source}" -> "${e.target}" already exists`), !1;
730
- const t = this.nodeManager.getNode(e.source), i = this.nodeManager.getNode(e.target), o = this.edgeFactory.createEdge(
734
+ const s = this.nodeManager.getNode(e.source), t = this.nodeManager.getNode(e.target), i = this.createDirectedEdgeKey(e.source, e.target);
735
+ this.edges.push(e);
736
+ const o = this.edgeGroups.get(i);
737
+ if (o) {
738
+ o.push(e);
739
+ const r = this.edgeObjectMap.get(i);
740
+ return r && this.updateEdgeUserData(r, o, s, t), !0;
741
+ }
742
+ const n = this.edgeFactory.createEdge(
731
743
  e,
744
+ s,
732
745
  t,
733
- i,
734
- t.position,
735
- i.position
746
+ s.position,
747
+ t.position
736
748
  );
737
- return this.sceneManager.add(o.line), this.edges.push(e), this.edgeObjects.push(o), this.edgeKeySet.add(s), !0;
749
+ return this.sceneManager.add(n.line), this.edgeGroups.set(i, [e]), this.edgeObjectMap.set(i, n), this.edgeObjects.push(n), this.edgeKeySet.add(i), this.updateEdgeUserData(n, [e], s, t), !0;
738
750
  }
739
751
  /**
740
752
  * Removes an edge from the graph
753
+ * Removes one relationship instance for source -> target.
741
754
  * @returns true if removed, false if not found
742
755
  */
743
756
  removeEdge(e, s) {
744
- const t = H(e, s);
757
+ const t = this.createDirectedEdgeKey(e, s);
745
758
  if (!this.edgeKeySet.has(t))
746
759
  return !1;
747
760
  const i = this.edges.findIndex(
748
- (a) => H(a.source, a.target) === t
761
+ (c) => c.source === e && c.target === s
749
762
  );
750
763
  if (i === -1)
751
764
  return !1;
752
- const o = this.edgeObjects[i];
753
- 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;
765
+ const o = this.edges[i];
766
+ this.edges.splice(i, 1);
767
+ const n = this.edgeGroups.get(t);
768
+ if (!n)
769
+ return !0;
770
+ const r = n.findIndex((c) => c === o);
771
+ if (r !== -1)
772
+ n.splice(r, 1);
773
+ else {
774
+ const c = n.findIndex((p) => p.source === e && p.target === s);
775
+ c !== -1 && n.splice(c, 1);
776
+ }
777
+ const d = this.edgeObjectMap.get(t);
778
+ if (!d)
779
+ return !0;
780
+ if (n.length === 0) {
781
+ this.sceneManager.remove(d.line), this.edgeFactory.disposeEdge(d);
782
+ const c = this.edgeObjects.findIndex((p) => p === d);
783
+ c !== -1 && this.edgeObjects.splice(c, 1), this.edgeGroups.delete(t), this.edgeObjectMap.delete(t), this.edgeKeySet.delete(t), this.highlightedEdgeKey === t && (this.highlightedEdgeKey = null);
784
+ } else {
785
+ const c = this.nodeManager.getNode(e), p = this.nodeManager.getNode(s);
786
+ c && p && this.updateEdgeUserData(d, n, c, p);
787
+ }
788
+ return !0;
754
789
  }
755
790
  /**
756
791
  * Highlights an edge
757
792
  */
758
793
  highlightEdge(e, s) {
759
- const t = H(e, s);
794
+ const t = this.createDirectedEdgeKey(e, s);
760
795
  this.highlightedEdgeKey && this.highlightedEdgeKey !== t && this.unhighlightCurrentEdge();
761
- const i = this.edges.findIndex(
762
- (o) => H(o.source, o.target) === t
763
- );
764
- i !== -1 && (this.edgeFactory.highlightEdge(this.edgeObjects[i]), this.highlightedEdgeKey = t);
796
+ const i = this.edgeObjectMap.get(t);
797
+ i && (this.edgeFactory.highlightEdge(i), this.highlightedEdgeKey = t);
765
798
  }
766
799
  /**
767
800
  * Unhighlights the currently highlighted edge
768
801
  */
769
802
  unhighlightCurrentEdge() {
770
803
  if (!this.highlightedEdgeKey) return;
771
- const e = this.edges.findIndex(
772
- (s) => H(s.source, s.target) === this.highlightedEdgeKey
773
- );
774
- e !== -1 && this.edgeFactory.unhighlightEdge(this.edgeObjects[e]), this.highlightedEdgeKey = null;
804
+ const e = this.edgeObjectMap.get(this.highlightedEdgeKey);
805
+ e && this.edgeFactory.unhighlightEdge(e), this.highlightedEdgeKey = null;
775
806
  }
776
807
  /**
777
808
  * Removes all edges connected to a node
@@ -803,12 +834,12 @@ class yt {
803
834
  * Updates all edge positions based on current node positions
804
835
  */
805
836
  updateEdgePositions() {
806
- this.edgeObjects.forEach((e, s) => {
807
- const t = this.edges[s], i = this.nodeManager.getNode(t.source), o = this.nodeManager.getNode(t.target);
808
- i && o && this.edgeFactory.updateEdgePositions(
837
+ this.edgeObjects.forEach((e) => {
838
+ const s = this.nodeManager.getNode(e.source), t = this.nodeManager.getNode(e.target);
839
+ s && t && this.edgeFactory.updateEdgePositions(
809
840
  e,
810
- i.position,
811
- o.position
841
+ s.position,
842
+ t.position
812
843
  );
813
844
  });
814
845
  }
@@ -836,7 +867,29 @@ class yt {
836
867
  clear() {
837
868
  this.edgeObjects.forEach((e) => {
838
869
  this.sceneManager.remove(e.line), this.edgeFactory.disposeEdge(e);
839
- }), this.edges = [], this.edgeObjects = [], this.edgeKeySet.clear(), this.highlightedEdgeKey = null;
870
+ }), this.edges = [], this.edgeObjects = [], this.edgeKeySet.clear(), this.edgeGroups.clear(), this.edgeObjectMap.clear(), this.highlightedEdgeKey = null;
871
+ }
872
+ /**
873
+ * Creates a directed key (source -> target)
874
+ */
875
+ createDirectedEdgeKey(e, s) {
876
+ return `${e}->${s}`;
877
+ }
878
+ /**
879
+ * Syncs relationship metadata to the line for hover/click UI
880
+ */
881
+ updateEdgeUserData(e, s, t, i) {
882
+ const o = s[0];
883
+ e.line.userData = {
884
+ ...e.line.userData,
885
+ source: e.source,
886
+ target: e.target,
887
+ edge: o,
888
+ relationships: [...s],
889
+ relationshipCount: s.length,
890
+ sourceNode: t,
891
+ targetNode: i
892
+ };
840
893
  }
841
894
  /**
842
895
  * Dispose resources
@@ -845,7 +898,7 @@ class yt {
845
898
  this.clear();
846
899
  }
847
900
  }
848
- class Ie {
901
+ class Re {
849
902
  constructor(e, s, t = {}) {
850
903
  l(this, "nodes");
851
904
  l(this, "edges");
@@ -885,8 +938,8 @@ class Ie {
885
938
  let s = 0, t = null;
886
939
  for (const [i, o] of e) {
887
940
  o > s && (s = o, t = i);
888
- const a = this.nodes.get(i);
889
- a && (a.mass = 1 + Math.log2(1 + o));
941
+ const n = this.nodes.get(i);
942
+ n && (n.mass = 1 + Math.log2(1 + o));
890
943
  }
891
944
  if (console.log(`[ForceGraph3D] Hub detected: id="${t}", degree=${s}, threshold=10`), t && s > 10) {
892
945
  this.pinnedNodeId = t;
@@ -918,13 +971,13 @@ class Ie {
918
971
  const e = Array.from(this.nodes.values()), s = e.length, t = this.getEffectiveRepulsion();
919
972
  for (let i = 0; i < s; i++) {
920
973
  const o = e[i];
921
- for (let a = i + 1; a < s; a++) {
922
- const r = e[a], c = r.position.x - o.position.x, d = r.position.y - o.position.y, p = r.position.z - o.position.z;
923
- let x = c * c + d * d + p * p;
924
- if (x > this.REPULSION_CUTOFF_SQ) continue;
925
- x < 0.01 && (x = 0.01);
926
- const m = Math.sqrt(x), u = t * this.alpha / x, f = c / m * u, b = d / m * u, M = p / m * u;
927
- 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;
974
+ for (let n = i + 1; n < s; n++) {
975
+ const r = e[n], d = r.position.x - o.position.x, c = r.position.y - o.position.y, p = r.position.z - o.position.z;
976
+ let f = d * d + c * c + p * p;
977
+ if (f > this.REPULSION_CUTOFF_SQ) continue;
978
+ f < 0.01 && (f = 0.01);
979
+ const m = Math.sqrt(f), u = t * this.alpha / f, y = d / m * u, b = c / m * u, w = p / m * u;
980
+ o.velocity.x -= y / o.mass, o.velocity.y -= b / o.mass, o.velocity.z -= w / o.mass, r.velocity.x += y / r.mass, r.velocity.y += b / r.mass, r.velocity.z += w / r.mass;
928
981
  }
929
982
  }
930
983
  }
@@ -932,7 +985,7 @@ class Ie {
932
985
  * Barnes-Hut approximation - O(n log n)
933
986
  */
934
987
  calculateRepulsionBarnesHut() {
935
- const e = Array.from(this.nodes.values()), s = new xt(e);
988
+ const e = Array.from(this.nodes.values()), s = new yt(e);
936
989
  for (const t of e)
937
990
  this.calculateForceFromOctree(t, s.root);
938
991
  }
@@ -945,26 +998,26 @@ class Ie {
945
998
  return;
946
999
  }
947
1000
  if (s.mass === 0) return;
948
- 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;
949
- if (a > this.REPULSION_CUTOFF_SQ) return;
950
- const r = Math.sqrt(a), c = this.getEffectiveRepulsion();
1001
+ const t = s.centerOfMass.x - e.position.x, i = s.centerOfMass.y - e.position.y, o = s.centerOfMass.z - e.position.z, n = t * t + i * i + o * o;
1002
+ if (n > this.REPULSION_CUTOFF_SQ) return;
1003
+ const r = Math.sqrt(n), d = this.getEffectiveRepulsion();
951
1004
  if (r > 0 && s.size / r < this.barnesHutTheta) {
952
- const d = Math.max(a, 0.01), p = c * this.alpha * s.mass / d;
1005
+ const c = Math.max(n, 0.01), p = d * this.alpha * s.mass / c;
953
1006
  e.velocity.x -= t / r * p / e.mass, e.velocity.y -= i / r * p / e.mass, e.velocity.z -= o / r * p / e.mass;
954
1007
  } else
955
- for (const d of s.children)
956
- d && this.calculateForceFromOctree(e, d);
1008
+ for (const c of s.children)
1009
+ c && this.calculateForceFromOctree(e, c);
957
1010
  }
958
1011
  /**
959
1012
  * Apply repulsion between two nodes (with cutoff)
960
1013
  */
961
1014
  applyRepulsionBetween(e, s) {
962
1015
  const t = s.position.x - e.position.x, i = s.position.y - e.position.y, o = s.position.z - e.position.z;
963
- let a = t * t + i * i + o * o;
964
- if (a > this.REPULSION_CUTOFF_SQ) return;
965
- a < 0.01 && (a = 0.01);
966
- const r = Math.sqrt(a), d = this.getEffectiveRepulsion() * this.alpha / a;
967
- e.velocity.x -= t / r * d / e.mass, e.velocity.y -= i / r * d / e.mass, e.velocity.z -= o / r * d / e.mass;
1016
+ let n = t * t + i * i + o * o;
1017
+ if (n > this.REPULSION_CUTOFF_SQ) return;
1018
+ n < 0.01 && (n = 0.01);
1019
+ const r = Math.sqrt(n), c = this.getEffectiveRepulsion() * this.alpha / n;
1020
+ e.velocity.x -= t / r * c / e.mass, e.velocity.y -= i / r * c / e.mass, e.velocity.z -= o / r * c / e.mass;
968
1021
  }
969
1022
  /**
970
1023
  * Calculate attraction forces along edges
@@ -974,10 +1027,10 @@ class Ie {
974
1027
  for (const t of this.edges) {
975
1028
  const i = this.nodes.get(t.source), o = this.nodes.get(t.target);
976
1029
  if (!i || !o) continue;
977
- const a = o.position.x - i.position.x, r = o.position.y - i.position.y, c = o.position.z - i.position.z, d = Math.sqrt(a * a + r * r + c * c);
978
- if (d < 0.01) continue;
979
- const x = (d - 15) * this.attractionStrength * s * this.alpha, m = a / d * x, u = r / d * x, f = c / d * x;
980
- 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;
1030
+ const n = o.position.x - i.position.x, r = o.position.y - i.position.y, d = o.position.z - i.position.z, c = Math.sqrt(n * n + r * r + d * d);
1031
+ if (c < 0.01) continue;
1032
+ const f = (c - 15) * this.attractionStrength * s * this.alpha, m = n / c * f, u = r / c * f, y = d / c * f;
1033
+ i.velocity.x += m / i.mass, i.velocity.y += u / i.mass, i.velocity.z += y / i.mass, o.velocity.x -= m / o.mass, o.velocity.y -= u / o.mass, o.velocity.z -= y / o.mass;
981
1034
  }
982
1035
  }
983
1036
  /**
@@ -1034,7 +1087,7 @@ class Ie {
1034
1087
  e.repulsionStrength !== void 0 && (this.repulsionStrength = e.repulsionStrength), e.attractionStrength !== void 0 && (this.attractionStrength = e.attractionStrength), e.damping !== void 0 && (this.damping = e.damping);
1035
1088
  }
1036
1089
  }
1037
- class xt {
1090
+ class yt {
1038
1091
  constructor(e) {
1039
1092
  l(this, "root");
1040
1093
  const s = this.calculateBounds(e);
@@ -1070,54 +1123,54 @@ class xt {
1070
1123
  };
1071
1124
  if (e.length === 1 || t > 20) {
1072
1125
  let u = 0;
1073
- const f = { x: 0, y: 0, z: 0 };
1126
+ const y = { x: 0, y: 0, z: 0 };
1074
1127
  for (const b of e)
1075
- u += b.mass, f.x += b.position.x * b.mass, f.y += b.position.y * b.mass, f.z += b.position.z * b.mass;
1076
- return u > 0 && (f.x /= u, f.y /= u, f.z /= u), {
1128
+ u += b.mass, y.x += b.position.x * b.mass, y.y += b.position.y * b.mass, y.z += b.position.z * b.mass;
1129
+ return u > 0 && (y.x /= u, y.y /= u, y.z /= u), {
1077
1130
  bounds: s,
1078
1131
  size: i,
1079
- centerOfMass: f,
1132
+ centerOfMass: y,
1080
1133
  mass: u,
1081
1134
  isLeaf: !0,
1082
1135
  node: e[0],
1083
1136
  children: []
1084
1137
  };
1085
1138
  }
1086
- 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 = [[], [], [], [], [], [], [], []];
1139
+ const o = (s.min.x + s.max.x) / 2, n = (s.min.y + s.max.y) / 2, r = (s.min.z + s.max.z) / 2, d = [[], [], [], [], [], [], [], []];
1087
1140
  for (const u of e) {
1088
- const f = (u.position.x >= o ? 1 : 0) + (u.position.y >= a ? 2 : 0) + (u.position.z >= r ? 4 : 0);
1089
- c[f].push(u);
1090
- }
1091
- const d = [
1092
- { min: { x: s.min.x, y: s.min.y, z: s.min.z }, max: { x: o, y: a, z: r } },
1093
- { min: { x: o, y: s.min.y, z: s.min.z }, max: { x: s.max.x, y: a, z: r } },
1094
- { min: { x: s.min.x, y: a, z: s.min.z }, max: { x: o, y: s.max.y, z: r } },
1095
- { min: { x: o, y: a, z: s.min.z }, max: { x: s.max.x, y: s.max.y, z: r } },
1096
- { min: { x: s.min.x, y: s.min.y, z: r }, max: { x: o, y: a, z: s.max.z } },
1097
- { min: { x: o, y: s.min.y, z: r }, max: { x: s.max.x, y: a, z: s.max.z } },
1098
- { min: { x: s.min.x, y: a, z: r }, max: { x: o, y: s.max.y, z: s.max.z } },
1099
- { min: { x: o, y: a, z: r }, max: { x: s.max.x, y: s.max.y, z: s.max.z } }
1141
+ const y = (u.position.x >= o ? 1 : 0) + (u.position.y >= n ? 2 : 0) + (u.position.z >= r ? 4 : 0);
1142
+ d[y].push(u);
1143
+ }
1144
+ const c = [
1145
+ { min: { x: s.min.x, y: s.min.y, z: s.min.z }, max: { x: o, y: n, z: r } },
1146
+ { min: { x: o, y: s.min.y, z: s.min.z }, max: { x: s.max.x, y: n, z: r } },
1147
+ { min: { x: s.min.x, y: n, z: s.min.z }, max: { x: o, y: s.max.y, z: r } },
1148
+ { min: { x: o, y: n, z: s.min.z }, max: { x: s.max.x, y: s.max.y, z: r } },
1149
+ { min: { x: s.min.x, y: s.min.y, z: r }, max: { x: o, y: n, z: s.max.z } },
1150
+ { min: { x: o, y: s.min.y, z: r }, max: { x: s.max.x, y: n, z: s.max.z } },
1151
+ { min: { x: s.min.x, y: n, z: r }, max: { x: o, y: s.max.y, z: s.max.z } },
1152
+ { min: { x: o, y: n, z: r }, max: { x: s.max.x, y: s.max.y, z: s.max.z } }
1100
1153
  ], p = [];
1101
- let x = 0;
1154
+ let f = 0;
1102
1155
  const m = { x: 0, y: 0, z: 0 };
1103
1156
  for (let u = 0; u < 8; u++)
1104
- if (c[u].length > 0) {
1105
- const f = this.buildTree(c[u], d[u], t + 1);
1106
- p.push(f), x += f.mass, m.x += f.centerOfMass.x * f.mass, m.y += f.centerOfMass.y * f.mass, m.z += f.centerOfMass.z * f.mass;
1157
+ if (d[u].length > 0) {
1158
+ const y = this.buildTree(d[u], c[u], t + 1);
1159
+ p.push(y), f += y.mass, m.x += y.centerOfMass.x * y.mass, m.y += y.centerOfMass.y * y.mass, m.z += y.centerOfMass.z * y.mass;
1107
1160
  } else
1108
1161
  p.push(null);
1109
- return x > 0 && (m.x /= x, m.y /= x, m.z /= x), {
1162
+ return f > 0 && (m.x /= f, m.y /= f, m.z /= f), {
1110
1163
  bounds: s,
1111
1164
  size: i,
1112
1165
  centerOfMass: m,
1113
- mass: x,
1166
+ mass: f,
1114
1167
  isLeaf: !1,
1115
1168
  node: null,
1116
1169
  children: p
1117
1170
  };
1118
1171
  }
1119
1172
  }
1120
- class bt {
1173
+ class xt {
1121
1174
  constructor(e, s, t, i = 60) {
1122
1175
  l(this, "sceneManager");
1123
1176
  l(this, "animationId", null);
@@ -1182,7 +1235,7 @@ class bt {
1182
1235
  this.stop();
1183
1236
  }
1184
1237
  }
1185
- class vt {
1238
+ class bt {
1186
1239
  constructor() {
1187
1240
  l(this, "envMap", null);
1188
1241
  l(this, "materialCache", /* @__PURE__ */ new Map());
@@ -1223,7 +1276,7 @@ class vt {
1223
1276
  for (const i of t) {
1224
1277
  const o = document.createElement("canvas");
1225
1278
  o.width = 256, o.height = 256;
1226
- const a = o.getContext("2d"), r = a.createRadialGradient(
1279
+ const n = o.getContext("2d"), r = n.createRadialGradient(
1227
1280
  256 / 2,
1228
1281
  256 / 2,
1229
1282
  0,
@@ -1231,15 +1284,15 @@ class vt {
1231
1284
  256 / 2,
1232
1285
  256 * 0.8
1233
1286
  );
1234
- 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);
1235
- const c = a.getImageData(0, 0, 256, 256);
1236
- for (let d = 0; d < c.data.length; d += 4) {
1287
+ r.addColorStop(0, i.colors[0]), r.addColorStop(0.5, i.colors[1]), r.addColorStop(1, i.colors[2]), n.fillStyle = r, n.fillRect(0, 0, 256, 256);
1288
+ const d = n.getImageData(0, 0, 256, 256);
1289
+ for (let c = 0; c < d.data.length; c += 4) {
1237
1290
  const p = (Math.random() - 0.5) * 5;
1238
- c.data[d] = Math.min(255, Math.max(0, c.data[d] + p)), c.data[d + 1] = Math.min(255, Math.max(0, c.data[d + 1] + p)), c.data[d + 2] = Math.min(255, Math.max(0, c.data[d + 2] + p));
1291
+ d.data[c] = Math.min(255, Math.max(0, d.data[c] + p)), d.data[c + 1] = Math.min(255, Math.max(0, d.data[c + 1] + p)), d.data[c + 2] = Math.min(255, Math.max(0, d.data[c + 2] + p));
1239
1292
  }
1240
- a.putImageData(c, 0, 0), s.push(o);
1293
+ n.putImageData(d, 0, 0), s.push(o);
1241
1294
  }
1242
- this.envMap = new y.CubeTexture(s.map((i) => {
1295
+ this.envMap = new x.CubeTexture(s.map((i) => {
1243
1296
  const o = new Image();
1244
1297
  return o.src = i.toDataURL(), o;
1245
1298
  })), this.envMap.needsUpdate = !0;
@@ -1258,11 +1311,11 @@ class vt {
1258
1311
  const t = "glass-single";
1259
1312
  if (this.materialCache.has(t))
1260
1313
  return this.materialCache.get(t).clone();
1261
- const i = new y.Color(16750950), o = new y.ShaderMaterial({
1314
+ const i = new x.Color(16750950), o = new x.ShaderMaterial({
1262
1315
  uniforms: {
1263
1316
  uColor: { value: i },
1264
1317
  uEnvMap: { value: this.envMap },
1265
- uGlowColor: { value: new y.Color(16777215) },
1318
+ uGlowColor: { value: new x.Color(16777215) },
1266
1319
  uGlowIntensity: { value: 0.8 },
1267
1320
  uReflectivity: { value: 0.4 },
1268
1321
  uFresnelPower: { value: 2.5 }
@@ -1328,9 +1381,9 @@ class vt {
1328
1381
  }
1329
1382
  `,
1330
1383
  transparent: !0,
1331
- side: y.FrontSide,
1384
+ side: x.FrontSide,
1332
1385
  depthWrite: !0,
1333
- blending: y.NormalBlending
1386
+ blending: x.NormalBlending
1334
1387
  });
1335
1388
  return this.materialCache.set(t, o), o.clone();
1336
1389
  }
@@ -1338,7 +1391,7 @@ class vt {
1338
1391
  * Creates material for edges (light color for dark background)
1339
1392
  */
1340
1393
  createEdgeMaterial(e = 6710886, s = 0.4) {
1341
- return new y.LineBasicMaterial({
1394
+ return new x.LineBasicMaterial({
1342
1395
  color: e,
1343
1396
  transparent: !0,
1344
1397
  opacity: s,
@@ -1349,7 +1402,7 @@ class vt {
1349
1402
  * Creates highlighted edge material
1350
1403
  */
1351
1404
  createHighlightedEdgeMaterial() {
1352
- return new y.LineBasicMaterial({
1405
+ return new x.LineBasicMaterial({
1353
1406
  color: 16750950,
1354
1407
  // Tangerine highlight
1355
1408
  transparent: !1,
@@ -1363,10 +1416,10 @@ class vt {
1363
1416
  createLabelMaterial(e, s = 24) {
1364
1417
  const t = document.createElement("canvas"), i = t.getContext("2d");
1365
1418
  i.font = `600 ${s}px Inter, -apple-system, sans-serif`;
1366
- const a = i.measureText(e).width;
1367
- 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);
1368
- const r = new y.CanvasTexture(t);
1369
- return r.needsUpdate = !0, new y.SpriteMaterial({
1419
+ const n = i.measureText(e).width;
1420
+ t.width = Math.max(128, n + 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);
1421
+ const r = new x.CanvasTexture(t);
1422
+ return r.needsUpdate = !0, new x.SpriteMaterial({
1370
1423
  map: r,
1371
1424
  transparent: !0,
1372
1425
  depthTest: !1,
@@ -1386,7 +1439,7 @@ class vt {
1386
1439
  this.materialCache.forEach((e) => e.dispose()), this.materialCache.clear(), this.envMap && this.envMap.dispose();
1387
1440
  }
1388
1441
  }
1389
- class Mt {
1442
+ class vt {
1390
1443
  constructor(e, s = 2, t = [32, 16, 8], i = 16750950) {
1391
1444
  l(this, "materialFactory");
1392
1445
  l(this, "geometryCache", /* @__PURE__ */ new Map());
@@ -1403,7 +1456,7 @@ class Mt {
1403
1456
  const t = `lod-${s}`;
1404
1457
  this.geometryCache.set(
1405
1458
  t,
1406
- new y.SphereGeometry(this.nodeRadius, e, e)
1459
+ new x.SphereGeometry(this.nodeRadius, e, e)
1407
1460
  );
1408
1461
  });
1409
1462
  }
@@ -1418,21 +1471,21 @@ class Mt {
1418
1471
  * Creates a node visual (glass ball + label)
1419
1472
  */
1420
1473
  createNode(e, s = 0) {
1421
- const t = new y.Group();
1474
+ const t = new x.Group();
1422
1475
  t.name = `node-${e.id}`, t.userData = { nodeId: e.id, nodeData: e };
1423
1476
  const i = this.getGeometry(s), o = this.materialFactory.createGlassMaterial(
1424
1477
  e.color ?? this.defaultNodeColor
1425
- ), a = new y.Mesh(i, o);
1426
- a.castShadow = !0, a.receiveShadow = !0, t.add(a);
1427
- const r = this.materialFactory.createLabelMaterial(e.label), c = new y.Sprite(r);
1428
- return c.position.y = this.nodeRadius + 1.5, c.scale.set(4, 1, 1), t.add(c), e.position && t.position.set(
1478
+ ), n = new x.Mesh(i, o);
1479
+ n.castShadow = !0, n.receiveShadow = !0, t.add(n);
1480
+ const r = this.materialFactory.createLabelMaterial(e.label), d = new x.Sprite(r);
1481
+ return d.position.y = this.nodeRadius + 1.5, d.scale.set(4, 1, 1), t.add(d), e.position && t.position.set(
1429
1482
  e.position.x,
1430
1483
  e.position.y,
1431
1484
  e.position.z
1432
1485
  ), {
1433
1486
  group: t,
1434
- sphere: a,
1435
- label: c,
1487
+ sphere: n,
1488
+ label: d,
1436
1489
  lodLevel: s
1437
1490
  };
1438
1491
  }
@@ -1448,19 +1501,19 @@ class Mt {
1448
1501
  * Updates the color of a node
1449
1502
  */
1450
1503
  updateNodeColor(e, s) {
1451
- e.sphere.material instanceof y.Material && e.sphere.material.dispose(), e.sphere.material = this.materialFactory.createGlassMaterial(s);
1504
+ e.sphere.material instanceof x.Material && e.sphere.material.dispose(), e.sphere.material = this.materialFactory.createGlassMaterial(s);
1452
1505
  }
1453
1506
  /**
1454
1507
  * Updates the label of a node
1455
1508
  */
1456
1509
  updateNodeLabel(e, s) {
1457
- e.label.material instanceof y.SpriteMaterial && (e.label.material.map && e.label.material.map.dispose(), e.label.material.dispose()), e.label.material = this.materialFactory.createLabelMaterial(s);
1510
+ e.label.material instanceof x.SpriteMaterial && (e.label.material.map && e.label.material.map.dispose(), e.label.material.dispose()), e.label.material = this.materialFactory.createLabelMaterial(s);
1458
1511
  }
1459
1512
  /**
1460
1513
  * Disposes a node's resources
1461
1514
  */
1462
1515
  disposeNode(e) {
1463
- e.sphere.material instanceof y.Material && e.sphere.material.dispose(), e.label.material instanceof y.SpriteMaterial && (e.label.material.map && e.label.material.map.dispose(), e.label.material.dispose());
1516
+ e.sphere.material instanceof x.Material && e.sphere.material.dispose(), e.label.material instanceof x.SpriteMaterial && (e.label.material.map && e.label.material.map.dispose(), e.label.material.dispose());
1464
1517
  }
1465
1518
  /**
1466
1519
  * Dispose factory resources
@@ -1497,7 +1550,7 @@ class wt {
1497
1550
  * Creates an edge line between two positions
1498
1551
  */
1499
1552
  createEdge(e, s, t, i, o) {
1500
- const a = new y.BufferGeometry(), r = new Float32Array([
1553
+ const n = new x.BufferGeometry(), r = new Float32Array([
1501
1554
  i.x,
1502
1555
  i.y,
1503
1556
  i.z,
@@ -1505,16 +1558,16 @@ class wt {
1505
1558
  o.y,
1506
1559
  o.z
1507
1560
  ]);
1508
- a.setAttribute("position", new y.BufferAttribute(r, 3));
1509
- const c = this.getDefaultMaterial().clone(), d = new y.Line(a, c);
1510
- return d.name = `edge-${e.source}-${e.target}`, d.userData = {
1561
+ n.setAttribute("position", new x.BufferAttribute(r, 3));
1562
+ const d = this.getDefaultMaterial().clone(), c = new x.Line(n, d);
1563
+ return c.name = `edge-${e.source}-${e.target}`, c.userData = {
1511
1564
  source: e.source,
1512
1565
  target: e.target,
1513
1566
  edge: e,
1514
1567
  sourceNode: s,
1515
1568
  targetNode: t
1516
- }, d.frustumCulled = !0, {
1517
- line: d,
1569
+ }, c.frustumCulled = !0, {
1570
+ line: c,
1518
1571
  source: e.source,
1519
1572
  target: e.target
1520
1573
  };
@@ -1523,13 +1576,13 @@ class wt {
1523
1576
  * Highlights an edge
1524
1577
  */
1525
1578
  highlightEdge(e) {
1526
- e.line.material instanceof y.Material && e.line.material.dispose(), e.line.material = this.getHighlightMaterial().clone();
1579
+ e.line.material instanceof x.Material && e.line.material.dispose(), e.line.material = this.getHighlightMaterial().clone();
1527
1580
  }
1528
1581
  /**
1529
1582
  * Resets an edge to default appearance
1530
1583
  */
1531
1584
  unhighlightEdge(e) {
1532
- e.line.material instanceof y.Material && e.line.material.dispose(), e.line.material = this.getDefaultMaterial().clone();
1585
+ e.line.material instanceof x.Material && e.line.material.dispose(), e.line.material = this.getDefaultMaterial().clone();
1533
1586
  }
1534
1587
  /**
1535
1588
  * Updates an edge's positions
@@ -1542,7 +1595,7 @@ class wt {
1542
1595
  * Disposes an edge's resources
1543
1596
  */
1544
1597
  disposeEdge(e) {
1545
- e.line.geometry.dispose(), e.line.material instanceof y.Material && e.line.material.dispose();
1598
+ e.line.geometry.dispose(), e.line.material instanceof x.Material && e.line.material.dispose();
1546
1599
  }
1547
1600
  /**
1548
1601
  * Dispose factory resources
@@ -1551,7 +1604,7 @@ class wt {
1551
1604
  this.defaultMaterial && this.defaultMaterial.dispose(), this.highlightMaterial && this.highlightMaterial.dispose();
1552
1605
  }
1553
1606
  }
1554
- class Et {
1607
+ class Mt {
1555
1608
  constructor(e, s = [50, 100, 200], t = !0) {
1556
1609
  l(this, "camera");
1557
1610
  l(this, "lodDistances");
@@ -1563,9 +1616,9 @@ class Et {
1563
1616
  */
1564
1617
  getLODLevel(e) {
1565
1618
  if (!this.enabled)
1566
- return X.HIGH;
1619
+ return _.HIGH;
1567
1620
  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);
1568
- return o < this.lodDistances[0] ? X.HIGH : o < this.lodDistances[1] ? X.MEDIUM : X.LOW;
1621
+ return o < this.lodDistances[0] ? _.HIGH : o < this.lodDistances[1] ? _.MEDIUM : _.LOW;
1569
1622
  }
1570
1623
  /**
1571
1624
  * Checks if a node should be visible based on distance
@@ -1587,13 +1640,13 @@ class Et {
1587
1640
  this.enabled = e;
1588
1641
  }
1589
1642
  }
1590
- class Ct {
1643
+ class Et {
1591
1644
  constructor(e, s = !0) {
1592
1645
  l(this, "camera");
1593
1646
  l(this, "frustum");
1594
1647
  l(this, "projScreenMatrix");
1595
1648
  l(this, "enabled");
1596
- this.camera = e, this.frustum = new y.Frustum(), this.projScreenMatrix = new y.Matrix4(), this.enabled = s;
1649
+ this.camera = e, this.frustum = new x.Frustum(), this.projScreenMatrix = new x.Matrix4(), this.enabled = s;
1597
1650
  }
1598
1651
  /**
1599
1652
  * Updates the frustum from the camera
@@ -1609,7 +1662,7 @@ class Ct {
1609
1662
  */
1610
1663
  isPointVisible(e) {
1611
1664
  if (!this.enabled) return !0;
1612
- const s = new y.Vector3(e.x, e.y, e.z);
1665
+ const s = new x.Vector3(e.x, e.y, e.z);
1613
1666
  return this.frustum.containsPoint(s);
1614
1667
  }
1615
1668
  /**
@@ -1617,8 +1670,8 @@ class Ct {
1617
1670
  */
1618
1671
  isSphereVisible(e, s) {
1619
1672
  if (!this.enabled) return !0;
1620
- const t = new y.Sphere(
1621
- new y.Vector3(e.x, e.y, e.z),
1673
+ const t = new x.Sphere(
1674
+ new x.Vector3(e.x, e.y, e.z),
1622
1675
  s
1623
1676
  );
1624
1677
  return this.frustum.intersectsSphere(t);
@@ -1628,14 +1681,14 @@ class Ct {
1628
1681
  */
1629
1682
  isLineVisible(e, s) {
1630
1683
  if (!this.enabled) return !0;
1631
- const t = new y.Vector3(e.x, e.y, e.z), i = new y.Vector3(s.x, s.y, s.z);
1684
+ const t = new x.Vector3(e.x, e.y, e.z), i = new x.Vector3(s.x, s.y, s.z);
1632
1685
  if (this.frustum.containsPoint(t) || this.frustum.containsPoint(i))
1633
1686
  return !0;
1634
- const o = new y.Vector3(
1687
+ const o = new x.Vector3(
1635
1688
  (e.x + s.x) / 2,
1636
1689
  (e.y + s.y) / 2,
1637
1690
  (e.z + s.z) / 2
1638
- ), a = o.distanceTo(t), r = new y.Sphere(o, a);
1691
+ ), n = o.distanceTo(t), r = new x.Sphere(o, n);
1639
1692
  return this.frustum.intersectsSphere(r);
1640
1693
  }
1641
1694
  /**
@@ -1645,7 +1698,7 @@ class Ct {
1645
1698
  this.enabled = e;
1646
1699
  }
1647
1700
  }
1648
- class Nt {
1701
+ class Ct {
1649
1702
  constructor(e, s) {
1650
1703
  l(this, "sceneManager");
1651
1704
  l(this, "raycaster");
@@ -1659,7 +1712,7 @@ class Nt {
1659
1712
  l(this, "hoveredEdgeKey", null);
1660
1713
  l(this, "nodeObjects", []);
1661
1714
  l(this, "edgeObjects", []);
1662
- this.sceneManager = e, this.container = s, this.raycaster = new y.Raycaster(), this.raycaster.params.Line = { threshold: 1.5 }, this.mouse = new y.Vector2(), this.handleClick = this.handleClick.bind(this), this.handleMouseMove = this.handleMouseMove.bind(this), s.addEventListener("click", this.handleClick), s.addEventListener("mousemove", this.handleMouseMove);
1715
+ this.sceneManager = e, this.container = s, this.raycaster = new x.Raycaster(), this.raycaster.params.Line = { threshold: 1.5 }, this.mouse = new x.Vector2(), this.handleClick = this.handleClick.bind(this), this.handleMouseMove = this.handleMouseMove.bind(this), s.addEventListener("click", this.handleClick), s.addEventListener("mousemove", this.handleMouseMove);
1663
1716
  }
1664
1717
  /**
1665
1718
  * Updates the list of node objects to raycast against
@@ -1748,13 +1801,17 @@ class Nt {
1748
1801
  const t = this.raycaster.intersectObjects(this.edgeObjects, !1);
1749
1802
  if (t.length > 0) {
1750
1803
  const i = t[0].object, o = i.userData;
1751
- if (o != null && o.edge && (o != null && o.sourceNode) && (o != null && o.targetNode))
1804
+ if (o != null && o.edge && (o != null && o.sourceNode) && (o != null && o.targetNode)) {
1805
+ const n = Array.isArray(o.relationships) ? o.relationships : [o.edge];
1752
1806
  return {
1753
1807
  edge: o.edge,
1808
+ relationships: n,
1809
+ relationshipCount: typeof o.relationshipCount == "number" ? o.relationshipCount : n.length,
1754
1810
  sourceNode: o.sourceNode,
1755
1811
  targetNode: o.targetNode,
1756
1812
  edgeLine: i
1757
1813
  };
1814
+ }
1758
1815
  }
1759
1816
  return null;
1760
1817
  }
@@ -1767,11 +1824,11 @@ class Nt {
1767
1824
  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);
1768
1825
  const i = this.raycaster.intersectObjects(this.nodeObjects, !0);
1769
1826
  if (i.length > 0) {
1770
- let a = i[0].object;
1771
- for (; a; ) {
1772
- if ((o = a.userData) != null && o.nodeId)
1773
- return a.userData.nodeId;
1774
- a = a.parent;
1827
+ let n = i[0].object;
1828
+ for (; n; ) {
1829
+ if ((o = n.userData) != null && o.nodeId)
1830
+ return n.userData.nodeId;
1831
+ n = n.parent;
1775
1832
  }
1776
1833
  }
1777
1834
  return null;
@@ -1783,7 +1840,7 @@ class Nt {
1783
1840
  this.container.removeEventListener("click", this.handleClick), this.container.removeEventListener("mousemove", this.handleMouseMove);
1784
1841
  }
1785
1842
  }
1786
- class St {
1843
+ class Nt {
1787
1844
  constructor(e) {
1788
1845
  l(this, "container");
1789
1846
  l(this, "panel", null);
@@ -1806,17 +1863,15 @@ class St {
1806
1863
  width: 280px;
1807
1864
  max-height: 80vh;
1808
1865
  overflow-y: auto;
1809
- background: rgba(15, 15, 25, 0.85);
1866
+ background: rgba(255, 255, 255, 0.08);
1810
1867
  backdrop-filter: blur(20px);
1811
1868
  -webkit-backdrop-filter: blur(20px);
1812
- border: 1px solid rgba(255, 255, 255, 0.1);
1813
- border-radius: 16px;
1869
+ border: 1px solid rgba(255, 255, 255, 0.12);
1870
+ border-radius: 12px;
1814
1871
  padding: 24px;
1815
1872
  color: white;
1816
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
1817
- box-shadow:
1818
- 0 8px 32px rgba(0, 0, 0, 0.4),
1819
- inset 0 0 0 1px rgba(255, 255, 255, 0.05);
1873
+ font-family: inherit;
1874
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
1820
1875
  z-index: 1000;
1821
1876
  opacity: 0;
1822
1877
  pointer-events: none;
@@ -1860,8 +1915,8 @@ class St {
1860
1915
  this.onExpand(this.currentNodeId, r);
1861
1916
  }
1862
1917
  });
1863
- const a = this.panel.querySelector('[data-action="close"]');
1864
- a && a.addEventListener("click", () => {
1918
+ const n = this.panel.querySelector('[data-action="close"]');
1919
+ n && n.addEventListener("click", () => {
1865
1920
  this.hide();
1866
1921
  }), this.panel.style.opacity = "1", this.panel.style.pointerEvents = "auto", this.panel.style.transform = "translateY(-50%) translateX(0)", this.visible = !0;
1867
1922
  }
@@ -1874,8 +1929,8 @@ class St {
1874
1929
  <style>
1875
1930
  .force-graph-panel h2 {
1876
1931
  margin: 0 0 16px 0;
1877
- font-size: 20px;
1878
- font-weight: 600;
1932
+ font-size: 19px;
1933
+ font-weight: 650;
1879
1934
  letter-spacing: -0.5px;
1880
1935
  display: flex;
1881
1936
  align-items: center;
@@ -1893,13 +1948,13 @@ class St {
1893
1948
  height: 12px;
1894
1949
  border-radius: 50%;
1895
1950
  background: ${t};
1896
- box-shadow: 0 0 10px ${t}80;
1951
+ box-shadow: 0 0 12px ${t}80;
1897
1952
  }
1898
1953
  .force-graph-panel .info-row {
1899
1954
  display: flex;
1900
1955
  justify-content: space-between;
1901
1956
  padding: 8px 0;
1902
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
1957
+ border-bottom: 1px solid rgba(255, 255, 255, 0.08);
1903
1958
  font-size: 13px;
1904
1959
  }
1905
1960
  .force-graph-panel .info-row:last-child {
@@ -1919,19 +1974,24 @@ class St {
1919
1974
  }
1920
1975
  .force-graph-panel .neighbors-section {
1921
1976
  margin-top: 16px;
1977
+ padding: 10px;
1978
+ background: rgba(255, 255, 255, 0.04);
1979
+ border: 1px solid rgba(255, 255, 255, 0.08);
1980
+ border-radius: 10px;
1922
1981
  }
1923
1982
  .force-graph-panel .neighbors-title {
1924
1983
  font-size: 12px;
1925
1984
  text-transform: uppercase;
1926
1985
  letter-spacing: 1px;
1927
- color: rgba(255, 255, 255, 0.5);
1986
+ color: rgba(255, 255, 255, 0.55);
1928
1987
  margin-bottom: 8px;
1929
1988
  }
1930
1989
  .force-graph-panel .neighbor-chip {
1931
1990
  display: inline-block;
1932
1991
  padding: 4px 10px;
1933
1992
  margin: 2px;
1934
- background: rgba(255, 255, 255, 0.1);
1993
+ background: rgba(255, 255, 255, 0.08);
1994
+ border: 1px solid rgba(255, 255, 255, 0.12);
1935
1995
  border-radius: 12px;
1936
1996
  font-size: 12px;
1937
1997
  }
@@ -1941,7 +2001,7 @@ class St {
1941
2001
  }
1942
2002
  .force-graph-panel .depth-label {
1943
2003
  font-size: 12px;
1944
- color: rgba(255, 255, 255, 0.6);
2004
+ color: rgba(255, 255, 255, 0.65);
1945
2005
  margin-bottom: 6px;
1946
2006
  text-transform: uppercase;
1947
2007
  letter-spacing: 0.5px;
@@ -1949,9 +2009,9 @@ class St {
1949
2009
  .force-graph-panel select {
1950
2010
  width: 100%;
1951
2011
  padding: 8px 12px;
1952
- background: rgba(255, 255, 255, 0.1);
1953
- border: 1px solid rgba(255, 255, 255, 0.15);
1954
- border-radius: 6px;
2012
+ background: rgba(255, 255, 255, 0.08);
2013
+ border: 1px solid rgba(255, 255, 255, 0.12);
2014
+ border-radius: 8px;
1955
2015
  color: white;
1956
2016
  font-size: 13px;
1957
2017
  cursor: pointer;
@@ -1959,10 +2019,11 @@ class St {
1959
2019
  transition: all 0.2s ease;
1960
2020
  }
1961
2021
  .force-graph-panel select:hover {
1962
- background: rgba(255, 255, 255, 0.15);
2022
+ background: rgba(255, 255, 255, 0.12);
1963
2023
  }
1964
2024
  .force-graph-panel select:focus {
1965
- border-color: rgba(96, 165, 250, 0.5);
2025
+ border-color: rgba(255, 153, 102, 0.5);
2026
+ box-shadow: 0 0 20px rgba(255, 153, 102, 0.15);
1966
2027
  }
1967
2028
  .force-graph-panel .btn-row {
1968
2029
  display: flex;
@@ -1972,28 +2033,33 @@ class St {
1972
2033
  .force-graph-panel button {
1973
2034
  flex: 1;
1974
2035
  padding: 10px 16px;
1975
- border: none;
2036
+ border: 1px solid rgba(255, 255, 255, 0.12);
1976
2037
  border-radius: 8px;
1977
2038
  font-size: 13px;
1978
- font-weight: 500;
2039
+ font-weight: 600;
1979
2040
  cursor: pointer;
1980
2041
  transition: all 0.2s ease;
1981
2042
  }
1982
2043
  .force-graph-panel .btn-expand {
1983
- background: linear-gradient(135deg, #60a5fa, #a78bfa);
2044
+ background: linear-gradient(135deg, rgba(255, 153, 102, 0.3), rgba(255, 102, 153, 0.2));
2045
+ border-color: rgba(255, 153, 102, 0.35);
1984
2046
  color: white;
1985
2047
  }
1986
2048
  .force-graph-panel .btn-expand:hover {
1987
2049
  transform: translateY(-1px);
1988
- box-shadow: 0 4px 12px rgba(96, 165, 250, 0.4);
2050
+ box-shadow: 0 0 15px rgba(255, 153, 102, 0.2);
1989
2051
  }
1990
2052
  .force-graph-panel .btn-close {
1991
- background: rgba(255, 255, 255, 0.1);
2053
+ background: rgba(255, 255, 255, 0.08);
1992
2054
  color: rgba(255, 255, 255, 0.8);
1993
2055
  }
1994
2056
  .force-graph-panel .btn-close:hover {
1995
- background: rgba(255, 255, 255, 0.15);
2057
+ background: rgba(255, 255, 255, 0.12);
1996
2058
  }
2059
+ .force-graph-panel::-webkit-scrollbar { width: 6px; }
2060
+ .force-graph-panel::-webkit-scrollbar-track { background: transparent; }
2061
+ .force-graph-panel::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.15); border-radius: 3px; }
2062
+ .force-graph-panel::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.25); }
1997
2063
  </style>
1998
2064
 
1999
2065
  <h2>
@@ -2069,7 +2135,7 @@ class St {
2069
2135
  this.panel && this.panel.parentNode && this.panel.parentNode.removeChild(this.panel), this.panel = null;
2070
2136
  }
2071
2137
  }
2072
- class zt {
2138
+ class St {
2073
2139
  constructor(e) {
2074
2140
  l(this, "container");
2075
2141
  l(this, "panel", null);
@@ -2092,17 +2158,15 @@ class zt {
2092
2158
  width: 300px;
2093
2159
  max-height: 80vh;
2094
2160
  overflow-y: auto;
2095
- background: rgba(15, 15, 25, 0.85);
2161
+ background: rgba(255, 255, 255, 0.08);
2096
2162
  backdrop-filter: blur(20px);
2097
2163
  -webkit-backdrop-filter: blur(20px);
2098
- border: 1px solid rgba(255, 255, 255, 0.1);
2099
- border-radius: 16px;
2164
+ border: 1px solid rgba(255, 255, 255, 0.12);
2165
+ border-radius: 12px;
2100
2166
  padding: 24px;
2101
2167
  color: white;
2102
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
2103
- box-shadow:
2104
- 0 8px 32px rgba(0, 0, 0, 0.4),
2105
- inset 0 0 0 1px rgba(255, 255, 255, 0.05);
2168
+ font-family: inherit;
2169
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
2106
2170
  z-index: 1000;
2107
2171
  opacity: 0;
2108
2172
  pointer-events: none;
@@ -2130,29 +2194,34 @@ class zt {
2130
2194
  /**
2131
2195
  * Shows the panel with edge/relationship information
2132
2196
  */
2133
- show(e, s, t) {
2197
+ show(e, s, t, i = [e]) {
2134
2198
  if (!this.panel) return;
2135
2199
  this.currentEdgeKey = `${e.source}-${e.target}`;
2136
- let i;
2137
- this.panelTemplate ? i = this.panelTemplate(e, s, t) : i = this.generateDefaultContent(e, s, t), this.panel.innerHTML = i;
2138
- const o = this.panel.querySelector('[data-action="close"]');
2139
- o && o.addEventListener("click", () => {
2200
+ let o;
2201
+ this.panelTemplate ? o = this.panelTemplate(e, s, t) : o = this.generateDefaultContent(e, s, t, i), this.panel.innerHTML = o;
2202
+ const n = this.panel.querySelector('[data-action="close"]');
2203
+ n && n.addEventListener("click", () => {
2140
2204
  this.hide(), this.onClose && this.onClose();
2141
2205
  });
2142
- const a = this.panel.querySelector('[data-action="goto-source"]');
2143
- a && this.onNodeClick && a.addEventListener("click", () => {
2206
+ const r = this.panel.querySelector('[data-action="goto-source"]');
2207
+ r && this.onNodeClick && r.addEventListener("click", () => {
2144
2208
  this.onNodeClick && this.onNodeClick(e.source);
2145
2209
  });
2146
- const r = this.panel.querySelector('[data-action="goto-target"]');
2147
- r && this.onNodeClick && r.addEventListener("click", () => {
2210
+ const d = this.panel.querySelector('[data-action="goto-target"]');
2211
+ d && this.onNodeClick && d.addEventListener("click", () => {
2148
2212
  this.onNodeClick && this.onNodeClick(e.target);
2149
2213
  }), this.panel.style.opacity = "1", this.panel.style.pointerEvents = "auto", this.panel.style.transform = "translateY(-50%) translateX(0)", this.visible = !0;
2150
2214
  }
2151
2215
  /**
2152
2216
  * Generates default panel content
2153
2217
  */
2154
- generateDefaultContent(e, s, t) {
2155
- 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";
2218
+ generateDefaultContent(e, s, t, i = [e]) {
2219
+ const o = s.color ? `#${s.color.toString(16).padStart(6, "0")}` : "#ff9966", n = t.color ? `#${t.color.toString(16).padStart(6, "0")}` : "#ff9966", r = this.getRelationshipLabel(e), d = i.length > 0 ? i : [e], c = this.summarizeRelationships(d), p = c.slice(0, 10).map((m) => `
2220
+ <div class="relationship-item">
2221
+ <span class="relationship-item-label">${this.escapeHtml(m.label)}</span>
2222
+ <span class="relationship-item-count">${m.count}</span>
2223
+ </div>
2224
+ `).join(""), f = c.length - Math.min(c.length, 10);
2156
2225
  return `
2157
2226
  <style>
2158
2227
  .force-graph-edge-panel .panel-header {
@@ -2162,28 +2231,72 @@ class zt {
2162
2231
  margin-bottom: 20px;
2163
2232
  }
2164
2233
  .force-graph-edge-panel .panel-title {
2165
- font-size: 14px;
2234
+ font-size: 12px;
2166
2235
  text-transform: uppercase;
2167
2236
  letter-spacing: 1px;
2168
- color: rgba(255, 255, 255, 0.6);
2237
+ color: rgba(255, 255, 255, 0.55);
2169
2238
  margin: 0;
2170
2239
  }
2171
2240
  .force-graph-edge-panel .relationship-section {
2172
- background: rgba(255, 255, 255, 0.05);
2241
+ background: rgba(255, 255, 255, 0.04);
2242
+ border: 1px solid rgba(255, 255, 255, 0.08);
2173
2243
  border-radius: 12px;
2174
2244
  padding: 16px;
2175
2245
  text-align: center;
2176
- margin-bottom: 20px;
2246
+ margin-bottom: 14px;
2177
2247
  }
2178
2248
  .force-graph-edge-panel .relationship-label {
2179
2249
  font-size: 18px;
2180
2250
  font-weight: 600;
2181
- color: #a78bfa;
2251
+ color: rgba(255, 153, 102, 0.95);
2182
2252
  letter-spacing: 0.5px;
2183
2253
  }
2254
+ .force-graph-edge-panel .relationship-count {
2255
+ margin-top: 6px;
2256
+ font-size: 11px;
2257
+ text-transform: uppercase;
2258
+ letter-spacing: 0.8px;
2259
+ color: rgba(255, 255, 255, 0.6);
2260
+ }
2261
+ .force-graph-edge-panel .relationship-list {
2262
+ margin-bottom: 16px;
2263
+ max-height: 190px;
2264
+ overflow-y: auto;
2265
+ padding-right: 4px;
2266
+ }
2267
+ .force-graph-edge-panel .relationship-item {
2268
+ display: flex;
2269
+ justify-content: space-between;
2270
+ gap: 12px;
2271
+ padding: 8px 10px;
2272
+ background: rgba(255, 255, 255, 0.04);
2273
+ border: 1px solid rgba(255, 255, 255, 0.08);
2274
+ border-radius: 8px;
2275
+ margin-bottom: 6px;
2276
+ }
2277
+ .force-graph-edge-panel .relationship-item-label {
2278
+ font-size: 12px;
2279
+ color: rgba(255, 255, 255, 0.88);
2280
+ overflow: hidden;
2281
+ text-overflow: ellipsis;
2282
+ white-space: nowrap;
2283
+ }
2284
+ .force-graph-edge-panel .relationship-item-count {
2285
+ font-size: 12px;
2286
+ font-weight: 700;
2287
+ color: rgba(255, 153, 102, 0.95);
2288
+ min-width: 24px;
2289
+ text-align: right;
2290
+ }
2291
+ .force-graph-edge-panel .relationship-more {
2292
+ font-size: 11px;
2293
+ color: rgba(255, 255, 255, 0.45);
2294
+ text-align: center;
2295
+ margin-top: 2px;
2296
+ }
2184
2297
  .force-graph-edge-panel .node-card {
2185
- background: rgba(255, 255, 255, 0.05);
2186
- border: 1px solid rgba(255, 255, 255, 0.1);
2298
+ background: rgba(255, 255, 255, 0.06);
2299
+ border: 1px solid rgba(255, 255, 255, 0.12);
2187
2300
  border-radius: 12px;
2188
2301
  padding: 14px;
2189
2302
  margin-bottom: 12px;
@@ -2192,8 +2305,9 @@ class zt {
2192
2305
  }
2193
2306
  .force-graph-edge-panel .node-card:hover {
2194
2307
  background: rgba(255, 255, 255, 0.1);
2195
- border-color: rgba(255, 255, 255, 0.2);
2308
+ border-color: rgba(255, 153, 102, 0.35);
2196
2309
  transform: translateX(4px);
2310
+ box-shadow: 0 0 15px rgba(255, 153, 102, 0.15);
2197
2311
  }
2198
2312
  .force-graph-edge-panel .node-card-header {
2199
2313
  display: flex;
@@ -2230,18 +2344,18 @@ class zt {
2230
2344
  .force-graph-edge-panel .btn-close {
2231
2345
  width: 100%;
2232
2346
  padding: 12px 16px;
2233
- border: none;
2347
+ border: 1px solid rgba(255, 255, 255, 0.12);
2234
2348
  border-radius: 8px;
2235
2349
  font-size: 13px;
2236
- font-weight: 500;
2350
+ font-weight: 600;
2237
2351
  cursor: pointer;
2238
2352
  transition: all 0.2s ease;
2239
- background: rgba(255, 255, 255, 0.1);
2353
+ background: rgba(255, 255, 255, 0.08);
2240
2354
  color: rgba(255, 255, 255, 0.8);
2241
2355
  margin-top: 16px;
2242
2356
  }
2243
2357
  .force-graph-edge-panel .btn-close:hover {
2244
- background: rgba(255, 255, 255, 0.15);
2358
+ background: rgba(255, 255, 255, 0.12);
2245
2359
  }
2246
2360
  .force-graph-edge-panel .hint-text {
2247
2361
  font-size: 11px;
@@ -2249,6 +2363,10 @@ class zt {
2249
2363
  text-align: center;
2250
2364
  margin-top: 8px;
2251
2365
  }
2366
+ .force-graph-edge-panel .relationship-list::-webkit-scrollbar { width: 6px; }
2367
+ .force-graph-edge-panel .relationship-list::-webkit-scrollbar-track { background: transparent; }
2368
+ .force-graph-edge-panel .relationship-list::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.15); border-radius: 3px; }
2369
+ .force-graph-edge-panel .relationship-list::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.25); }
2252
2370
  </style>
2253
2371
 
2254
2372
  <div class="panel-header">
@@ -2256,13 +2374,19 @@ class zt {
2256
2374
  </div>
2257
2375
 
2258
2376
  <div class="relationship-section">
2259
- <span class="relationship-label">${this.escapeHtml(a)}</span>
2377
+ <span class="relationship-label">${this.escapeHtml(r)}</span>
2378
+ <div class="relationship-count">${d.length} relationships</div>
2379
+ </div>
2380
+
2381
+ <div class="relationship-list">
2382
+ ${p}
2383
+ ${f > 0 ? `<div class="relationship-more">+ ${f} more</div>` : ""}
2260
2384
  </div>
2261
2385
 
2262
2386
  <div class="node-card" data-action="goto-source" title="Click to focus on ${this.escapeHtml(s.label)}">
2263
2387
  <div class="node-type">Source</div>
2264
2388
  <div class="node-card-header">
2265
- <span class="color-dot" style="background: ${i}; box-shadow: 0 0 8px ${i}80;"></span>
2389
+ <span class="color-dot" style="background: ${o}; box-shadow: 0 0 8px ${o}80;"></span>
2266
2390
  <span class="node-label">${this.escapeHtml(s.label)}</span>
2267
2391
  </div>
2268
2392
  </div>
@@ -2272,7 +2396,7 @@ class zt {
2272
2396
  <div class="node-card" data-action="goto-target" title="Click to focus on ${this.escapeHtml(t.label)}">
2273
2397
  <div class="node-type">Target</div>
2274
2398
  <div class="node-card-header">
2275
- <span class="color-dot" style="background: ${o}; box-shadow: 0 0 8px ${o}80;"></span>
2399
+ <span class="color-dot" style="background: ${n}; box-shadow: 0 0 8px ${n}80;"></span>
2276
2400
  <span class="node-label">${this.escapeHtml(t.label)}</span>
2277
2401
  </div>
2278
2402
  </div>
@@ -2289,6 +2413,17 @@ class zt {
2289
2413
  const s = document.createElement("div");
2290
2414
  return s.textContent = e, s.innerHTML;
2291
2415
  }
2416
+ getRelationshipLabel(e) {
2417
+ return e.relationship || e.label || "connected to";
2418
+ }
2419
+ summarizeRelationships(e) {
2420
+ const s = /* @__PURE__ */ new Map();
2421
+ for (const t of e) {
2422
+ const i = this.getRelationshipLabel(t);
2423
+ s.set(i, (s.get(i) || 0) + 1);
2424
+ }
2425
+ return Array.from(s.entries()).map(([t, i]) => ({ label: t, count: i })).sort((t, i) => i.count - t.count);
2426
+ }
2292
2427
  /**
2293
2428
  * Hides the panel
2294
2429
  */
@@ -2314,7 +2449,7 @@ class zt {
2314
2449
  this.panel && this.panel.parentNode && this.panel.parentNode.removeChild(this.panel), this.panel = null;
2315
2450
  }
2316
2451
  }
2317
- class kt {
2452
+ class zt {
2318
2453
  constructor() {
2319
2454
  l(this, "tooltip", null);
2320
2455
  l(this, "visible", !1);
@@ -2361,28 +2496,51 @@ class kt {
2361
2496
  positionTooltip(e, s) {
2362
2497
  if (!this.tooltip) return;
2363
2498
  const t = this.tooltip.getBoundingClientRect(), i = window.innerWidth, o = window.innerHeight;
2364
- let a = e + 15, r = s + 15;
2365
- 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`;
2499
+ let n = e + 15, r = s + 15;
2500
+ n + t.width > i - 10 && (n = e - t.width - 15), r + t.height > o - 10 && (r = s - t.height - 15), n < 10 && (n = 10), r < 10 && (r = 10), this.tooltip.style.left = `${n}px`, this.tooltip.style.top = `${r}px`;
2366
2501
  }
2367
2502
  /**
2368
2503
  * Shows the tooltip with edge info
2369
2504
  */
2370
- show(e, s, t, i, o) {
2505
+ show(e, s, t, i, o, n = [e]) {
2371
2506
  if (!this.tooltip) return;
2372
- const a = e.relationship || "connected to";
2373
- this.tooltip.innerHTML = `
2374
- <div style="display: flex; flex-direction: column; gap: 4px;">
2375
- <div style="display: flex; align-items: center; gap: 6px; flex-wrap: wrap;">
2376
- <span style="font-weight: 600; color: #ff9966;">${this.escapeHtml(s.label)}</span>
2377
- </div>
2378
- <div style="color: rgba(255, 255, 255, 0.6); font-style: italic; font-size: 12px; padding-left: 8px;">
2379
- ↳ ${this.escapeHtml(a)}
2507
+ const r = n.length > 0 ? n : [e], d = this.summarizeRelationships(r), c = r.length;
2508
+ if (c <= 1) {
2509
+ const p = this.getRelationshipLabel(r[0]);
2510
+ this.tooltip.innerHTML = `
2511
+ <div style="display: flex; flex-direction: column; gap: 4px;">
2512
+ <div style="display: flex; align-items: center; gap: 6px; flex-wrap: wrap;">
2513
+ <span style="font-weight: 600; color: #ff9966;">${this.escapeHtml(s.label)}</span>
2514
+ </div>
2515
+ <div style="color: rgba(255, 255, 255, 0.6); font-style: italic; font-size: 12px; padding-left: 8px;">
2516
+ ↳ ${this.escapeHtml(p)}
2517
+ </div>
2518
+ <div style="display: flex; align-items: center; gap: 6px; flex-wrap: wrap;">
2519
+ <span style="font-weight: 600; color: #ff9966;">${this.escapeHtml(t.label)}</span>
2520
+ </div>
2380
2521
  </div>
2381
- <div style="display: flex; align-items: center; gap: 6px; flex-wrap: wrap;">
2382
- <span style="font-weight: 600; color: #ff9966;">${this.escapeHtml(t.label)}</span>
2522
+ `;
2523
+ } else {
2524
+ const p = d.slice(0, 4), f = d.length - p.length, m = p.map((u) => `<div style="display:flex; justify-content:space-between; gap:10px; font-size:12px; color: rgba(255,255,255,0.8);">
2525
+ <span style="overflow:hidden; text-overflow:ellipsis; white-space:nowrap;">${this.escapeHtml(u.label)}</span>
2526
+ <span style="color: rgba(255,153,102,0.9); font-weight:600;">${u.count}</span>
2527
+ </div>`).join("");
2528
+ this.tooltip.innerHTML = `
2529
+ <div style="display:flex; flex-direction:column; gap:8px; min-width:220px;">
2530
+ <div style="font-size:13px; font-weight:600; color:#ff9966;">
2531
+ ${this.escapeHtml(s.label)} → ${this.escapeHtml(t.label)}
2532
+ </div>
2533
+ <div style="font-size:11px; letter-spacing:0.4px; text-transform:uppercase; color: rgba(255,255,255,0.6);">
2534
+ ${c} relationships
2535
+ </div>
2536
+ <div style="display:flex; flex-direction:column; gap:4px;">
2537
+ ${m}
2538
+ </div>
2539
+ ${f > 0 ? `<div style="font-size:11px; color: rgba(255,255,255,0.45);">+ ${f} more</div>` : ""}
2383
2540
  </div>
2384
- </div>
2385
- `, this.positionTooltip(i, o), this.tooltip.style.opacity = "1", this.tooltip.style.transform = "translateY(0)", this.visible = !0;
2541
+ `;
2542
+ }
2543
+ this.positionTooltip(i, o), this.tooltip.style.opacity = "1", this.tooltip.style.transform = "translateY(0)", this.visible = !0;
2386
2544
  }
2387
2545
  /**
2388
2546
  * Updates tooltip position (called externally on mouse move)
@@ -2409,6 +2567,17 @@ class kt {
2409
2567
  const s = document.createElement("div");
2410
2568
  return s.textContent = e, s.innerHTML;
2411
2569
  }
2570
+ getRelationshipLabel(e) {
2571
+ return e.relationship || e.label || "connected to";
2572
+ }
2573
+ summarizeRelationships(e) {
2574
+ const s = /* @__PURE__ */ new Map();
2575
+ for (const t of e) {
2576
+ const i = this.getRelationshipLabel(t);
2577
+ s.set(i, (s.get(i) || 0) + 1);
2578
+ }
2579
+ return Array.from(s.entries()).map(([t, i]) => ({ label: t, count: i })).sort((t, i) => i.count - t.count);
2580
+ }
2412
2581
  /**
2413
2582
  * Dispose the tooltip
2414
2583
  */
@@ -2416,7 +2585,7 @@ class kt {
2416
2585
  this.tooltip && this.tooltip.parentNode && this.tooltip.parentNode.removeChild(this.tooltip), this.tooltip = null;
2417
2586
  }
2418
2587
  }
2419
- class Tt {
2588
+ class kt {
2420
2589
  constructor(e, s) {
2421
2590
  l(this, "container");
2422
2591
  l(this, "searchContainer", null);
@@ -2561,24 +2730,24 @@ class Tt {
2561
2730
  }
2562
2731
  let i = "";
2563
2732
  s.length > 0 && (i += '<div class="f3d-search-section-header">Nodes</div>', s.slice(0, 10).forEach((o) => {
2564
- const a = o.type || "Node";
2733
+ const n = o.type || "Node";
2565
2734
  i += `
2566
2735
  <div class="f3d-search-result-item" data-node-id="${this.escapeHtml(o.id)}">
2567
2736
  <div class="f3d-result-label">${this.escapeHtml(o.label)}</div>
2568
- <div class="f3d-result-type">${this.escapeHtml(a)}</div>
2737
+ <div class="f3d-result-type">${this.escapeHtml(n)}</div>
2569
2738
  </div>
2570
2739
  `;
2571
- }), 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 }) => {
2740
+ }), 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: n, targetNode: r }) => {
2572
2741
  i += `
2573
2742
  <div class="f3d-search-result-item" data-node-id="${this.escapeHtml(o.source)}">
2574
- <div class="f3d-result-label">${this.escapeHtml(a.label)} → ${this.escapeHtml(r.label)}</div>
2743
+ <div class="f3d-result-label">${this.escapeHtml(n.label)} → ${this.escapeHtml(r.label)}</div>
2575
2744
  <div class="f3d-result-relationship">${this.escapeHtml(o.relationship || "connected")}</div>
2576
2745
  </div>
2577
2746
  `;
2578
2747
  }), 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) => {
2579
2748
  o.addEventListener("click", () => {
2580
- const a = o.dataset.nodeId;
2581
- a && (this.onResultClick(a), this.searchResults && (this.searchResults.style.display = "none"), this.searchInput && this.searchInput.blur());
2749
+ const n = o.dataset.nodeId;
2750
+ n && (this.onResultClick(n), this.searchResults && (this.searchResults.style.display = "none"), this.searchInput && this.searchInput.blur());
2582
2751
  });
2583
2752
  });
2584
2753
  }
@@ -2590,7 +2759,7 @@ class Tt {
2590
2759
  this.searchContainer && this.searchContainer.parentNode && this.searchContainer.parentNode.removeChild(this.searchContainer);
2591
2760
  }
2592
2761
  }
2593
- class Pt {
2762
+ class Tt {
2594
2763
  constructor(e, s) {
2595
2764
  l(this, "container");
2596
2765
  l(this, "toggleContainer", null);
@@ -2682,7 +2851,7 @@ class Pt {
2682
2851
  this.toggleContainer && this.toggleContainer.parentNode && this.toggleContainer.parentNode.removeChild(this.toggleContainer);
2683
2852
  }
2684
2853
  }
2685
- class Lt {
2854
+ class Pt {
2686
2855
  constructor(e) {
2687
2856
  l(this, "container");
2688
2857
  l(this, "legendContainer", null);
@@ -2765,7 +2934,7 @@ class Lt {
2765
2934
  this.legendContainer && this.legendContainer.parentNode && this.legendContainer.parentNode.removeChild(this.legendContainer);
2766
2935
  }
2767
2936
  }
2768
- const Rt = {
2937
+ const Lt = {
2769
2938
  backgroundColor: "#0a0a0a",
2770
2939
  gridColor: "rgba(255, 255, 255, 0.03)",
2771
2940
  nodeRadius: 24,
@@ -2778,7 +2947,7 @@ const Rt = {
2778
2947
  damping: 0.85
2779
2948
  // Fast energy dissipation
2780
2949
  };
2781
- class It {
2950
+ class Rt {
2782
2951
  constructor(e, s = {}) {
2783
2952
  l(this, "container");
2784
2953
  l(this, "canvas");
@@ -2805,7 +2974,7 @@ class It {
2805
2974
  l(this, "isSimulating", !0);
2806
2975
  // Resize handler
2807
2976
  l(this, "resizeHandler");
2808
- this.container = e, this.options = { ...Rt, ...s }, this.canvas = document.createElement("canvas"), this.canvas.style.position = "absolute", this.canvas.style.top = "0", this.canvas.style.left = "0", this.canvas.style.width = "100%", this.canvas.style.height = "100%", this.canvas.style.cursor = "grab", e.appendChild(this.canvas);
2977
+ this.container = e, this.options = { ...Lt, ...s }, this.canvas = document.createElement("canvas"), this.canvas.style.position = "absolute", this.canvas.style.top = "0", this.canvas.style.left = "0", this.canvas.style.width = "100%", this.canvas.style.height = "100%", this.canvas.style.cursor = "grab", e.appendChild(this.canvas);
2809
2978
  const t = this.canvas.getContext("2d");
2810
2979
  if (!t)
2811
2980
  throw new Error("Failed to get 2D context");
@@ -2818,21 +2987,21 @@ class It {
2818
2987
  setupInteractions() {
2819
2988
  this.canvas.addEventListener("wheel", (e) => {
2820
2989
  e.preventDefault();
2821
- 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;
2822
- this.transform.x = t - (t - this.transform.x) * r, this.transform.y = i - (i - this.transform.y) * r, this.transform.scale = a;
2990
+ const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left, i = e.clientY - s.top, o = e.deltaY > 0 ? 0.9 : 1.1, n = Math.max(0.1, Math.min(5, this.transform.scale * o)), r = n / this.transform.scale;
2991
+ this.transform.x = t - (t - this.transform.x) * r, this.transform.y = i - (i - this.transform.y) * r, this.transform.scale = n;
2823
2992
  }), this.canvas.addEventListener("mousedown", (e) => {
2824
- 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);
2825
- 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 };
2993
+ const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left, i = e.clientY - s.top, o = this.screenToWorld(t, i), n = this.findNodeAt(o.x, o.y);
2994
+ this.dragStartPos = { x: e.clientX, y: e.clientY }, n ? (this.isDragging = !0, this.draggedNode = n, this.canvas.style.cursor = "grabbing", this.isSimulating = !0) : (this.isPanning = !0, this.canvas.style.cursor = "grabbing"), this.lastMousePos = { x: e.clientX, y: e.clientY };
2826
2995
  }), this.canvas.addEventListener("mousemove", (e) => {
2827
2996
  const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left, i = e.clientY - s.top, o = this.screenToWorld(t, i);
2828
2997
  if (this.isDragging && this.draggedNode)
2829
2998
  this.draggedNode.x = o.x, this.draggedNode.y = o.y, this.draggedNode.vx = 0, this.draggedNode.vy = 0;
2830
2999
  else if (this.isPanning) {
2831
- const a = e.clientX - this.lastMousePos.x, r = e.clientY - this.lastMousePos.y;
2832
- this.transform.x += a, this.transform.y += r, this.lastMousePos = { x: e.clientX, y: e.clientY };
3000
+ const n = e.clientX - this.lastMousePos.x, r = e.clientY - this.lastMousePos.y;
3001
+ this.transform.x += n, this.transform.y += r, this.lastMousePos = { x: e.clientX, y: e.clientY };
2833
3002
  } else {
2834
- const a = this.findNodeAt(o.x, o.y);
2835
- 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) {
3003
+ const n = this.findNodeAt(o.x, o.y);
3004
+ if (n !== this.hoveredNode && (this.hoveredNode = n, n ? (this.hoveredEdge && (this.hoveredEdge = null, this.options.onEdgeHover && this.options.onEdgeHover(null)), this.canvas.style.cursor = "pointer", this.options.onNodeHover && this.options.onNodeHover(n.data)) : this.options.onNodeHover && this.options.onNodeHover(null)), !n) {
2836
3005
  const r = this.findEdgeAt(o.x, o.y);
2837
3006
  r !== this.hoveredEdge && (this.hoveredEdge = r, this.canvas.style.cursor = r ? "pointer" : "grab", this.options.onEdgeHover && this.options.onEdgeHover(r ? r.data : null, e));
2838
3007
  }
@@ -2842,7 +3011,7 @@ class It {
2842
3011
  if (this.isDragging && this.draggedNode)
2843
3012
  i && this.options.onNodeClick && (this.selectedNode = this.draggedNode, this.options.onNodeClick(this.draggedNode.data));
2844
3013
  else if (i) {
2845
- const o = this.canvas.getBoundingClientRect(), a = this.screenToWorld(e.clientX - o.left, e.clientY - o.top), r = this.findEdgeAt(a.x, a.y);
3014
+ const o = this.canvas.getBoundingClientRect(), n = this.screenToWorld(e.clientX - o.left, e.clientY - o.top), r = this.findEdgeAt(n.x, n.y);
2846
3015
  r && this.options.onEdgeClick && this.options.onEdgeClick(r.data);
2847
3016
  }
2848
3017
  this.isDragging = !1, this.isPanning = !1, this.draggedNode = null, this.canvas.style.cursor = this.hoveredNode ? "pointer" : "grab";
@@ -2866,12 +3035,12 @@ class It {
2866
3035
  }
2867
3036
  findEdgeAt(e, s) {
2868
3037
  for (const i of this.edges) {
2869
- const o = this.nodes.get(i.source), a = this.nodes.get(i.target);
2870
- if (!o || !a) continue;
2871
- const r = a.x - o.x, c = a.y - o.y, d = r * r + c * c;
2872
- if (d === 0) continue;
2873
- const p = Math.max(0, Math.min(1, ((e - o.x) * r + (s - o.y) * c) / d)), x = o.x + p * r, m = o.y + p * c, u = e - x, f = s - m;
2874
- if (Math.sqrt(u * u + f * f) < 12)
3038
+ const o = this.nodes.get(i.source), n = this.nodes.get(i.target);
3039
+ if (!o || !n) continue;
3040
+ const r = n.x - o.x, d = n.y - o.y, c = r * r + d * d;
3041
+ if (c === 0) continue;
3042
+ const p = Math.max(0, Math.min(1, ((e - o.x) * r + (s - o.y) * d) / c)), f = o.x + p * r, m = o.y + p * d, u = e - f, y = s - m;
3043
+ if (Math.sqrt(u * u + y * y) < 12)
2875
3044
  return i;
2876
3045
  }
2877
3046
  return null;
@@ -2888,29 +3057,29 @@ class It {
2888
3057
  const t = 60, i = 5;
2889
3058
  let o = 0;
2890
3059
  for (let r = 0; r < s; r++)
2891
- for (let c = r + 1; c < s; c++) {
2892
- const d = e[r], p = e[c];
2893
- let x = p.x - d.x, m = p.y - d.y, u = Math.sqrt(x * x + m * m);
3060
+ for (let d = r + 1; d < s; d++) {
3061
+ const c = e[r], p = e[d];
3062
+ let f = p.x - c.x, m = p.y - c.y, u = Math.sqrt(f * f + m * m);
2894
3063
  if (u < t * 3) {
2895
3064
  u < 1 && (u = 1);
2896
- const f = this.options.repulsionStrength / (u * u), b = x / u * f, M = m / u * f;
2897
- d.vx -= b, d.vy -= M, p.vx += b, p.vy += M;
3065
+ const y = this.options.repulsionStrength / (u * u), b = f / u * y, w = m / u * y;
3066
+ c.vx -= b, c.vy -= w, p.vx += b, p.vy += w;
2898
3067
  }
2899
3068
  }
2900
- const a = 80;
3069
+ const n = 80;
2901
3070
  for (const r of this.edges) {
2902
- const c = this.nodes.get(r.source), d = this.nodes.get(r.target);
2903
- if (!c || !d) continue;
2904
- let p = d.x - c.x, x = d.y - c.y, m = Math.sqrt(p * p + x * x);
3071
+ const d = this.nodes.get(r.source), c = this.nodes.get(r.target);
3072
+ if (!d || !c) continue;
3073
+ let p = c.x - d.x, f = c.y - d.y, m = Math.sqrt(p * p + f * f);
2905
3074
  m < 1 && (m = 1);
2906
- const f = (m - a) * this.options.attractionStrength, b = p / m * f, M = x / m * f;
2907
- c.vx += b, c.vy += M, d.vx -= b, d.vy -= M;
3075
+ const y = (m - n) * this.options.attractionStrength, b = p / m * y, w = f / m * y;
3076
+ d.vx += b, d.vy += w, c.vx -= b, c.vy -= w;
2908
3077
  }
2909
3078
  for (const r of e) {
2910
3079
  if (this.draggedNode === r) continue;
2911
3080
  r.vx *= this.options.damping, r.vy *= this.options.damping;
2912
- const c = Math.sqrt(r.vx * r.vx + r.vy * r.vy);
2913
- 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;
3081
+ const d = Math.sqrt(r.vx * r.vx + r.vy * r.vy);
3082
+ d > i && (r.vx = r.vx / d * i, r.vy = r.vy / d * i), r.x += r.vx, r.y += r.vy, o += r.vx * r.vx + r.vy * r.vy;
2914
3083
  }
2915
3084
  o < 0.01 && !this.draggedNode && (this.isSimulating = !1);
2916
3085
  }
@@ -2919,49 +3088,49 @@ class It {
2919
3088
  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();
2920
3089
  }
2921
3090
  renderGrid(e, s) {
2922
- const t = this.ctx, i = 40 * this.transform.scale, o = 1.5, a = this.transform.x % i, r = this.transform.y % i;
3091
+ const t = this.ctx, i = 40 * this.transform.scale, o = 1.5, n = this.transform.x % i, r = this.transform.y % i;
2923
3092
  t.fillStyle = this.options.gridColor;
2924
- for (let c = a; c < e; c += i)
2925
- for (let d = r; d < s; d += i)
2926
- t.beginPath(), t.arc(c, d, o, 0, Math.PI * 2), t.fill();
3093
+ for (let d = n; d < e; d += i)
3094
+ for (let c = r; c < s; c += i)
3095
+ t.beginPath(), t.arc(d, c, o, 0, Math.PI * 2), t.fill();
2927
3096
  }
2928
3097
  renderEdges() {
2929
3098
  const e = this.ctx;
2930
3099
  for (const s of this.edges) {
2931
3100
  const t = this.nodes.get(s.source), i = this.nodes.get(s.target);
2932
3101
  if (!t || !i) continue;
2933
- const o = s === this.hoveredEdge, a = e.createLinearGradient(t.x, t.y, i.x, i.y);
2934
- 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();
3102
+ const o = s === this.hoveredEdge, n = e.createLinearGradient(t.x, t.y, i.x, i.y);
3103
+ o ? (n.addColorStop(0, "rgba(255, 153, 102, 0.8)"), n.addColorStop(0.5, "rgba(255, 255, 255, 0.5)"), n.addColorStop(1, "rgba(102, 153, 255, 0.8)"), e.lineWidth = 3) : (n.addColorStop(0, "rgba(255, 153, 102, 0.3)"), n.addColorStop(0.5, "rgba(255, 255, 255, 0.15)"), n.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 = n, e.stroke();
2935
3104
  }
2936
3105
  }
2937
3106
  renderNodes() {
2938
3107
  const e = this.ctx;
2939
3108
  for (const s of this.nodes.values()) {
2940
- 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);
3109
+ const t = s === this.hoveredNode, i = s === this.selectedNode, o = this.hoveredEdge && (s.data.id === this.hoveredEdge.source || s.data.id === this.hoveredEdge.target), n = s.radius * (t ? 1.1 : 1);
2941
3110
  if (t || i || o) {
2942
- const f = e.createRadialGradient(
3111
+ const y = e.createRadialGradient(
2943
3112
  s.x,
2944
3113
  s.y,
2945
- a * 0.5,
3114
+ n * 0.5,
2946
3115
  s.x,
2947
3116
  s.y,
2948
- a * 2
3117
+ n * 2
2949
3118
  ), b = t || i ? 0.4 : 0.25;
2950
- 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();
3119
+ y.addColorStop(0, `rgba(255, 153, 102, ${b})`), y.addColorStop(1, "rgba(255, 153, 102, 0)"), e.fillStyle = y, e.beginPath(), e.arc(s.x, s.y, n * 2, 0, Math.PI * 2), e.fill();
2951
3120
  }
2952
3121
  const r = e.createRadialGradient(
2953
- s.x - a * 0.3,
2954
- s.y - a * 0.3,
3122
+ s.x - n * 0.3,
3123
+ s.y - n * 0.3,
2955
3124
  0,
2956
3125
  s.x,
2957
3126
  s.y,
2958
- a
2959
- ), c = s.color >> 16 & 255, d = s.color >> 8 & 255, p = s.color & 255;
2960
- r.addColorStop(0, `rgba(${Math.min(255, c + 60)}, ${Math.min(255, d + 60)}, ${Math.min(255, p + 60)}, 0.95)`), r.addColorStop(0.7, `rgba(${c}, ${d}, ${p}, 0.9)`), r.addColorStop(1, `rgba(${Math.max(0, c - 40)}, ${Math.max(0, d - 40)}, ${Math.max(0, p - 40)}, 0.85)`), e.beginPath(), e.arc(s.x, s.y, a, 0, Math.PI * 2), e.fillStyle = r, e.fill(), e.strokeStyle = "rgba(255, 255, 255, 0.2)", e.lineWidth = 1, e.stroke(), e.beginPath(), e.arc(s.x - a * 0.25, s.y - a * 0.25, a * 0.3, 0, Math.PI * 2), e.fillStyle = "rgba(255, 255, 255, 0.15)", e.fill(), e.fillStyle = "white", e.font = "600 11px Inter, -apple-system, BlinkMacSystemFont, sans-serif", e.textAlign = "center", e.textBaseline = "middle";
2961
- const x = a * 1.6;
3127
+ n
3128
+ ), d = s.color >> 16 & 255, c = s.color >> 8 & 255, p = s.color & 255;
3129
+ r.addColorStop(0, `rgba(${Math.min(255, d + 60)}, ${Math.min(255, c + 60)}, ${Math.min(255, p + 60)}, 0.95)`), r.addColorStop(0.7, `rgba(${d}, ${c}, ${p}, 0.9)`), r.addColorStop(1, `rgba(${Math.max(0, d - 40)}, ${Math.max(0, c - 40)}, ${Math.max(0, p - 40)}, 0.85)`), e.beginPath(), e.arc(s.x, s.y, n, 0, Math.PI * 2), e.fillStyle = r, e.fill(), e.strokeStyle = "rgba(255, 255, 255, 0.2)", e.lineWidth = 1, e.stroke(), e.beginPath(), e.arc(s.x - n * 0.25, s.y - n * 0.25, n * 0.3, 0, Math.PI * 2), e.fillStyle = "rgba(255, 255, 255, 0.15)", e.fill(), e.fillStyle = "white", e.font = "600 11px Inter, -apple-system, BlinkMacSystemFont, sans-serif", e.textAlign = "center", e.textBaseline = "middle";
3130
+ const f = n * 1.6;
2962
3131
  let m = s.label, u = e.measureText(m).width;
2963
- if (u > x) {
2964
- for (; u > x && m.length > 3; )
3132
+ if (u > f) {
3133
+ for (; u > f && m.length > 3; )
2965
3134
  m = m.slice(0, -1), u = e.measureText(m + "...").width;
2966
3135
  m += "...";
2967
3136
  }
@@ -3064,11 +3233,11 @@ class It {
3064
3233
  focusOnNode(e) {
3065
3234
  const s = this.nodes.get(e);
3066
3235
  if (!s) return;
3067
- 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(), d = () => {
3068
- const p = performance.now() - c, x = Math.min(p / r, 1), m = 1 - Math.pow(1 - x, 3);
3069
- this.transform.x = o + (t - o) * m, this.transform.y = a + (i - a) * m, x < 1 ? requestAnimationFrame(d) : this.selectedNode = s;
3236
+ 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, n = this.transform.y, r = 500, d = performance.now(), c = () => {
3237
+ const p = performance.now() - d, f = Math.min(p / r, 1), m = 1 - Math.pow(1 - f, 3);
3238
+ this.transform.x = o + (t - o) * m, this.transform.y = n + (i - n) * m, f < 1 ? requestAnimationFrame(c) : this.selectedNode = s;
3070
3239
  };
3071
- d();
3240
+ c();
3072
3241
  }
3073
3242
  /**
3074
3243
  * Updates node positions from 3D data
@@ -3146,7 +3315,7 @@ class Ht {
3146
3315
  l(this, "devControls", null);
3147
3316
  l(this, "viewMode", "3d");
3148
3317
  l(this, "graphData", null);
3149
- this.options = { ...P, ...s }, this.container = ht(e), this.materialFactory = new vt(), this.nodeFactory = new Mt(
3318
+ this.options = { ...P, ...s }, this.container = dt(e), this.materialFactory = new bt(), this.nodeFactory = new vt(
3150
3319
  this.materialFactory,
3151
3320
  this.options.nodeRadius ?? P.nodeRadius,
3152
3321
  this.options.lodSegments ?? P.lodSegments,
@@ -3155,14 +3324,14 @@ class Ht {
3155
3324
  this.materialFactory,
3156
3325
  this.options.edgeColor ?? P.edgeColor,
3157
3326
  this.options.edgeOpacity ?? P.edgeOpacity
3158
- ), this.sceneManager = new mt(this.container, this.options), this.lodManager = new Et(
3327
+ ), this.sceneManager = new ft(this.container, this.options), this.lodManager = new Mt(
3159
3328
  this.sceneManager.camera,
3160
3329
  this.options.lodDistances ?? P.lodDistances,
3161
3330
  this.options.enableLOD ?? P.enableLOD
3162
- ), this.frustumCuller = new Ct(
3331
+ ), this.frustumCuller = new Et(
3163
3332
  this.sceneManager.camera,
3164
3333
  this.options.enableEdgeCulling ?? P.enableEdgeCulling
3165
- ), this.nodeManager = new te(this.sceneManager, this.nodeFactory), this.edgeManager = new yt(this.sceneManager, this.nodeManager, this.edgeFactory), this.graphEngine = new Ie(
3334
+ ), this.nodeManager = new ee(this.sceneManager, this.nodeFactory), this.edgeManager = new mt(this.sceneManager, this.nodeManager, this.edgeFactory), this.graphEngine = new Re(
3166
3335
  this.nodeManager.getAllNodes(),
3167
3336
  this.edgeManager.getAllEdges(),
3168
3337
  {
@@ -3172,16 +3341,16 @@ class Ht {
3172
3341
  useBarnesHut: this.options.useBarnesHut,
3173
3342
  barnesHutTheta: this.options.barnesHutTheta
3174
3343
  }
3175
- ), this.rendererManager = new bt(
3344
+ ), this.rendererManager = new xt(
3176
3345
  this.sceneManager,
3177
3346
  () => this.onSimulate(),
3178
3347
  () => this.onRender(),
3179
3348
  this.options.targetFPS ?? P.targetFPS
3180
- ), this.raycasterManager = new Nt(this.sceneManager, this.container), this.panelManager = new St(this.container), this.edgePanelManager = new zt(this.container), this.edgeTooltipManager = new kt(), this.edgePanelManager.setNodeClickCallback((t) => {
3349
+ ), this.raycasterManager = new Ct(this.sceneManager, this.container), this.panelManager = new Nt(this.container), this.edgePanelManager = new St(this.container), this.edgeTooltipManager = new zt(), this.edgePanelManager.setNodeClickCallback((t) => {
3181
3350
  this.edgePanelManager.hide(), this.focusOnNode(t), setTimeout(() => {
3182
3351
  this.showNodePanel(t);
3183
3352
  }, 400);
3184
- }), this.options.showSearch !== !1 && (this.searchManager = new Tt(this.container, {
3353
+ }), this.options.showSearch !== !1 && (this.searchManager = new kt(this.container, {
3185
3354
  placeholder: this.options.searchPlaceholder,
3186
3355
  onSearch: (t) => ({
3187
3356
  nodeResults: this.searchNodes(t),
@@ -3192,12 +3361,12 @@ class Ht {
3192
3361
  this.showNodePanel(t);
3193
3362
  }, 400);
3194
3363
  }
3195
- })), this.options.showViewToggle !== !1 && (this.viewMode = this.options.initialViewMode || "3d", this.viewToggleManager = new Pt(this.container, {
3364
+ })), this.options.showViewToggle !== !1 && (this.viewMode = this.options.initialViewMode || "3d", this.viewToggleManager = new Tt(this.container, {
3196
3365
  initialMode: this.viewMode,
3197
3366
  onViewChange: (t) => {
3198
3367
  this.switchView(t);
3199
3368
  }
3200
- })), this.options.showLegend !== !1 && (this.legendManager = new Lt(this.container), this.updateLegendCounts()), this.setupCallbacks(), this.rendererManager.start(), this.initialized = !0, this.emit("ready");
3369
+ })), this.options.showLegend !== !1 && (this.legendManager = new Pt(this.container), this.updateLegendCounts()), this.setupCallbacks(), this.rendererManager.start(), this.initialized = !0, this.emit("ready");
3201
3370
  }
3202
3371
  /**
3203
3372
  * Sets up internal callbacks
@@ -3220,7 +3389,14 @@ class Ht {
3220
3389
  if (e) {
3221
3390
  this.edgeManager.highlightEdge(e.edge.source, e.edge.target);
3222
3391
  const s = this.container.getBoundingClientRect(), t = s.left + s.width / 2, i = s.top + s.height / 2;
3223
- 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);
3392
+ this.edgeTooltipManager.show(
3393
+ e.edge,
3394
+ e.sourceNode,
3395
+ e.targetNode,
3396
+ t,
3397
+ i,
3398
+ e.relationships
3399
+ ), this.options.onEdgeHover && this.options.onEdgeHover(e.edge, e.sourceNode, e.targetNode), this.emit("edgeHover", e.edge, e.sourceNode, e.targetNode);
3224
3400
  } else
3225
3401
  this.edgeManager.unhighlightCurrentEdge(), this.edgeTooltipManager.hide(), this.options.onEdgeHover && this.options.onEdgeHover(null, null, null), this.emit("edgeHover", null, null, null);
3226
3402
  }
@@ -3236,7 +3412,7 @@ class Ht {
3236
3412
  * Handles edge click
3237
3413
  */
3238
3414
  onEdgeClick(e) {
3239
- this.panelManager.hide(), this.edgeTooltipManager.hide(), this.edgeManager.highlightEdge(e.edge.source, e.edge.target), this.edgePanelManager.show(e.edge, e.sourceNode, e.targetNode), this.focusOnEdge(e.edge.source, e.edge.target), this.emit("edgeClick", e.edge, e.sourceNode, e.targetNode);
3415
+ this.panelManager.hide(), this.edgeTooltipManager.hide(), this.edgeManager.highlightEdge(e.edge.source, e.edge.target), this.edgePanelManager.show(e.edge, e.sourceNode, e.targetNode, e.relationships), this.focusOnEdge(e.edge.source, e.edge.target), this.emit("edgeClick", e.edge, e.sourceNode, e.targetNode);
3240
3416
  }
3241
3417
  /**
3242
3418
  * Called every simulation step
@@ -3269,8 +3445,8 @@ class Ht {
3269
3445
  * Sets the graph data
3270
3446
  */
3271
3447
  setData(e) {
3272
- var a;
3273
- const s = (a = e.data) != null && a.nodes ? e.data : e, i = (s.edges || s.links || []).map((r) => ({
3448
+ var n;
3449
+ const s = (n = e.data) != null && n.nodes ? e.data : e, i = (s.edges || s.links || []).map((r) => ({
3274
3450
  ...r,
3275
3451
  relationship: r.relationship || r.label || "related_to"
3276
3452
  })), o = {
@@ -3278,14 +3454,14 @@ class Ht {
3278
3454
  edges: i
3279
3455
  };
3280
3456
  if (this.graphData = o, this.edgeManager.clear(), this.nodeManager.clear(), o.nodes && Array.isArray(o.nodes)) {
3281
- te.setExpectedNodeCount(o.nodes.length);
3457
+ ee.setExpectedNodeCount(o.nodes.length);
3282
3458
  for (const r of o.nodes)
3283
3459
  this.addNode(r);
3284
3460
  }
3285
3461
  if (o.edges && Array.isArray(o.edges))
3286
3462
  for (const r of o.edges)
3287
3463
  this.addEdge(r);
3288
- this.graphEngine = new Ie(
3464
+ this.graphEngine = new Re(
3289
3465
  this.nodeManager.getAllNodes(),
3290
3466
  this.edgeManager.getAllEdges(),
3291
3467
  {
@@ -3302,7 +3478,7 @@ class Ht {
3302
3478
  * @returns true if added, false if node already exists or invalid
3303
3479
  */
3304
3480
  addNode(e) {
3305
- if (!De(e))
3481
+ if (!Fe(e))
3306
3482
  return !1;
3307
3483
  const s = this.nodeManager.addNode(e);
3308
3484
  return s && (this.graphEngine.restart(), this.forceGraph2D && this.forceGraph2D.addNode(e), this.options.onNodeAdd && this.options.onNodeAdd(e), this.emit("nodeAdd", e), this.updateLegendCounts()), s;
@@ -3312,7 +3488,7 @@ class Ht {
3312
3488
  * @returns true if removed, false if not found
3313
3489
  */
3314
3490
  removeNode(e) {
3315
- if (!pt(e))
3491
+ if (!ht(e))
3316
3492
  return !1;
3317
3493
  this.edgeManager.removeEdgesForNode(e);
3318
3494
  const s = this.nodeManager.removeNode(e);
@@ -3326,10 +3502,10 @@ class Ht {
3326
3502
  }
3327
3503
  /**
3328
3504
  * Adds an edge to the graph
3329
- * @returns true if added, false if edge already exists or nodes don't exist
3505
+ * @returns true if added, false if invalid or nodes don't exist
3330
3506
  */
3331
3507
  addEdge(e) {
3332
- if (!He(e))
3508
+ if (!De(e))
3333
3509
  return !1;
3334
3510
  const s = this.edgeManager.addEdge(e);
3335
3511
  return s && (this.graphEngine.setEdges(this.edgeManager.getAllEdges()), this.graphEngine.restart(), this.forceGraph2D && this.forceGraph2D.addEdge(e), this.options.onEdgeAdd && this.options.onEdgeAdd(e), this.emit("edgeAdd", e), this.updateLegendCounts()), s;
@@ -3355,11 +3531,11 @@ class Ht {
3355
3531
  try {
3356
3532
  const o = await i(e, s);
3357
3533
  if (o.nodes && Array.isArray(o.nodes))
3358
- for (const a of o.nodes)
3359
- this.addNode(a);
3534
+ for (const n of o.nodes)
3535
+ this.addNode(n);
3360
3536
  if (o.edges && Array.isArray(o.edges))
3361
- for (const a of o.edges)
3362
- this.addEdge(a);
3537
+ for (const n of o.edges)
3538
+ this.addEdge(n);
3363
3539
  return this.panelManager.hide(), this.emit("expand", e, o), !0;
3364
3540
  } catch (o) {
3365
3541
  return console.error("[ForceGraph3D] Error expanding node:", o), !1;
@@ -3409,13 +3585,13 @@ class Ht {
3409
3585
  console.warn(`[ForceGraph3D] Node "${e}" not found`);
3410
3586
  return;
3411
3587
  }
3412
- const i = t.position, o = this.sceneManager.camera, a = this.sceneManager.controls, r = o.position.clone().sub(a.target).normalize(), c = {
3588
+ const i = t.position, o = this.sceneManager.camera, n = this.sceneManager.controls, r = o.position.clone().sub(n.target).normalize(), d = {
3413
3589
  x: i.x + r.x * s,
3414
3590
  y: i.y + r.y * s,
3415
3591
  z: i.z + r.z * s
3416
- }, d = { 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 = () => {
3417
- const f = performance.now() - m, b = Math.min(f / x, 1), M = 1 - Math.pow(1 - b, 3);
3418
- o.position.x = d.x + (c.x - d.x) * M, o.position.y = d.y + (c.y - d.y) * M, o.position.z = d.z + (c.z - d.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);
3592
+ }, c = { x: o.position.x, y: o.position.y, z: o.position.z }, p = { x: n.target.x, y: n.target.y, z: n.target.z }, f = 800, m = performance.now(), u = () => {
3593
+ const y = performance.now() - m, b = Math.min(y / f, 1), w = 1 - Math.pow(1 - b, 3);
3594
+ o.position.x = c.x + (d.x - c.x) * w, o.position.y = c.y + (d.y - c.y) * w, o.position.z = c.z + (d.z - c.z) * w, n.target.x = p.x + (i.x - p.x) * w, n.target.y = p.y + (i.y - p.y) * w, n.target.z = p.z + (i.z - p.z) * w, n.update(), b < 1 && requestAnimationFrame(u);
3419
3595
  };
3420
3596
  u();
3421
3597
  }
@@ -3429,19 +3605,19 @@ class Ht {
3429
3605
  console.warn(`[ForceGraph3D] Could not find nodes for edge "${e}" -> "${s}"`);
3430
3606
  return;
3431
3607
  }
3432
- const a = this.sceneManager.camera, r = this.sceneManager.controls, c = {
3608
+ const n = this.sceneManager.camera, r = this.sceneManager.controls, d = {
3433
3609
  x: (i.position.x + o.position.x) / 2,
3434
3610
  y: (i.position.y + o.position.y) / 2,
3435
3611
  z: (i.position.z + o.position.z) / 2
3436
- }, d = o.position.x - i.position.x, p = o.position.y - i.position.y, x = o.position.z - i.position.z, m = Math.sqrt(d * d + p * p + x * x), u = Math.max(m * t, 40), f = a.position.clone().sub(r.target).normalize(), b = {
3437
- x: c.x + f.x * u,
3438
- y: c.y + f.y * u,
3439
- z: c.z + f.z * u
3440
- }, M = { x: a.position.x, y: a.position.y, z: a.position.z }, N = { x: r.target.x, y: r.target.y, z: r.target.z }, O = 800, L = performance.now(), Y = () => {
3612
+ }, c = o.position.x - i.position.x, p = o.position.y - i.position.y, f = o.position.z - i.position.z, m = Math.sqrt(c * c + p * p + f * f), u = Math.max(m * t, 40), y = n.position.clone().sub(r.target).normalize(), b = {
3613
+ x: d.x + y.x * u,
3614
+ y: d.y + y.y * u,
3615
+ z: d.z + y.z * u
3616
+ }, w = { x: n.position.x, y: n.position.y, z: n.position.z }, N = { x: r.target.x, y: r.target.y, z: r.target.z }, O = 800, L = performance.now(), G = () => {
3441
3617
  const T = performance.now() - L, D = Math.min(T / O, 1), E = 1 - Math.pow(1 - D, 3);
3442
- a.position.x = M.x + (b.x - M.x) * E, a.position.y = M.y + (b.y - M.y) * E, a.position.z = M.z + (b.z - M.z) * E, r.target.x = N.x + (c.x - N.x) * E, r.target.y = N.y + (c.y - N.y) * E, r.target.z = N.z + (c.z - N.z) * E, r.update(), D < 1 && requestAnimationFrame(Y);
3618
+ n.position.x = w.x + (b.x - w.x) * E, n.position.y = w.y + (b.y - w.y) * E, n.position.z = w.z + (b.z - w.z) * E, r.target.x = N.x + (d.x - N.x) * E, r.target.y = N.y + (d.y - N.y) * E, r.target.z = N.z + (d.z - N.z) * E, r.update(), D < 1 && requestAnimationFrame(G);
3443
3619
  };
3444
- Y();
3620
+ G();
3445
3621
  }
3446
3622
  /**
3447
3623
  * Shows the info panel for a specific node
@@ -3464,9 +3640,9 @@ class Ht {
3464
3640
  return [];
3465
3641
  const s = e.toLowerCase().trim(), t = this.nodeManager.getAllNodes(), i = [];
3466
3642
  return t.forEach((o) => {
3467
- var d, p, x;
3468
- const a = (d = o.label) == null ? void 0 : d.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);
3469
- (a || r || c) && i.push(o);
3643
+ var c, p, f;
3644
+ const n = (c = o.label) == null ? void 0 : c.toLowerCase().includes(s), r = (p = o.id) == null ? void 0 : p.toLowerCase().includes(s), d = (f = o.type) == null ? void 0 : f.toLowerCase().includes(s);
3645
+ (n || r || d) && i.push(o);
3470
3646
  }), i;
3471
3647
  }
3472
3648
  /**
@@ -3478,10 +3654,10 @@ class Ht {
3478
3654
  if (!e || e.trim() === "")
3479
3655
  return [];
3480
3656
  const s = e.toLowerCase().trim(), t = this.edgeManager.getAllEdges(), i = [];
3481
- for (const a of t)
3482
- if ((o = a.relationship) == null ? void 0 : o.toLowerCase().includes(s)) {
3483
- const c = this.nodeManager.getNode(a.source), d = this.nodeManager.getNode(a.target);
3484
- c && d && i.push({ edge: a, sourceNode: c, targetNode: d });
3657
+ for (const n of t)
3658
+ if ((o = n.relationship) == null ? void 0 : o.toLowerCase().includes(s)) {
3659
+ const d = this.nodeManager.getNode(n.source), c = this.nodeManager.getNode(n.target);
3660
+ d && c && i.push({ edge: n, sourceNode: d, targetNode: c });
3485
3661
  }
3486
3662
  return i;
3487
3663
  }
@@ -3514,7 +3690,7 @@ class Ht {
3514
3690
  * Switches between 2D and 3D view modes
3515
3691
  */
3516
3692
  switchView(e) {
3517
- this.viewMode !== e && (this.viewMode = e, this.panelManager.hide(), this.edgePanelManager.hide(), this.edgeTooltipManager.hide(), e === "2d" ? (this.sceneManager.renderer.domElement.style.display = "none", this.rendererManager.stop(), this.forceGraph2D ? (this.forceGraph2D.show(), this.forceGraph2D.syncFrom3D(this.nodeManager.getAllNodes())) : (this.forceGraph2D = new It(this.container, {
3693
+ this.viewMode !== e && (this.viewMode = e, this.panelManager.hide(), this.edgePanelManager.hide(), this.edgeTooltipManager.hide(), e === "2d" ? (this.sceneManager.renderer.domElement.style.display = "none", this.rendererManager.stop(), this.forceGraph2D ? (this.forceGraph2D.show(), this.forceGraph2D.syncFrom3D(this.nodeManager.getAllNodes())) : (this.forceGraph2D = new Rt(this.container, {
3518
3694
  backgroundColor: "#0a0a0a",
3519
3695
  nodeRadius: 24,
3520
3696
  onNodeClick: (s) => {
@@ -3526,19 +3702,31 @@ class Ht {
3526
3702
  onEdgeHover: (s, t) => {
3527
3703
  if (s && t) {
3528
3704
  const i = this.nodeManager.getNode(s.source), o = this.nodeManager.getNode(s.target);
3529
- i && o && this.edgeTooltipManager.show(
3530
- s,
3531
- i,
3532
- o,
3533
- t.clientX,
3534
- t.clientY
3535
- );
3705
+ if (i && o) {
3706
+ const n = this.edgeManager.getAllEdges().filter((r) => r.source === s.source && r.target === s.target);
3707
+ this.edgeTooltipManager.show(
3708
+ s,
3709
+ i,
3710
+ o,
3711
+ t.clientX,
3712
+ t.clientY,
3713
+ n.length > 0 ? n : [s]
3714
+ );
3715
+ }
3536
3716
  } else
3537
3717
  this.edgeTooltipManager.hide();
3538
3718
  },
3539
3719
  onEdgeClick: (s) => {
3540
3720
  const t = this.nodeManager.getNode(s.source), i = this.nodeManager.getNode(s.target);
3541
- t && i && this.edgePanelManager.show(s, t, i);
3721
+ if (t && i) {
3722
+ const o = this.edgeManager.getAllEdges().filter((n) => n.source === s.source && n.target === s.target);
3723
+ this.edgePanelManager.show(
3724
+ s,
3725
+ t,
3726
+ i,
3727
+ o.length > 0 ? o : [s]
3728
+ );
3729
+ }
3542
3730
  }
3543
3731
  }), 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));
3544
3732
  }
@@ -3639,8 +3827,8 @@ class Ht {
3639
3827
  const i = parseFloat(t.value) / 100;
3640
3828
  this.setPhysicsParams({ damping: i }), this.devControls.querySelector("#dev-damping-val").textContent = i.toFixed(2);
3641
3829
  }), setInterval(() => {
3642
- const i = this.devControls.querySelector("#dev-node-count"), o = this.devControls.querySelector("#dev-edge-count"), a = this.devControls.querySelector("#dev-fps");
3643
- i && (i.textContent = this.getNodeCount().toString()), o && (o.textContent = this.getEdgeCount().toString()), a && (a.textContent = this.rendererManager.getFPS().toString());
3830
+ const i = this.devControls.querySelector("#dev-node-count"), o = this.devControls.querySelector("#dev-edge-count"), n = this.devControls.querySelector("#dev-fps");
3831
+ i && (i.textContent = this.getNodeCount().toString()), o && (o.textContent = this.getEdgeCount().toString()), n && (n.textContent = this.rendererManager.getFPS().toString());
3644
3832
  }, 500);
3645
3833
  }
3646
3834
  /**
@@ -3650,7 +3838,7 @@ class Ht {
3650
3838
  this.rendererManager.dispose(), this.panelManager.dispose(), this.raycasterManager.dispose(), this.edgeTooltipManager.dispose(), this.searchManager && this.searchManager.dispose(), this.viewToggleManager && this.viewToggleManager.dispose(), this.legendManager && this.legendManager.dispose(), this.forceGraph2D && this.forceGraph2D.dispose(), this.edgeManager.dispose(), this.nodeManager.dispose(), this.nodeFactory.dispose(), this.materialFactory.dispose(), this.sceneManager.dispose(), this.devControls && this.devControls.parentNode && this.devControls.parentNode.removeChild(this.devControls), this.eventCallbacks.clear(), this.initialized = !1;
3651
3839
  }
3652
3840
  }
3653
- const Oe = [
3841
+ const Ie = [
3654
3842
  "Alpha",
3655
3843
  "Beta",
3656
3844
  "Gamma",
@@ -3681,7 +3869,7 @@ const Oe = [
3681
3869
  "Link",
3682
3870
  "Point",
3683
3871
  "Vertex"
3684
- ], ee = [
3872
+ ], J = [
3685
3873
  "connects to",
3686
3874
  "links with",
3687
3875
  "relates to",
@@ -3692,7 +3880,7 @@ const Oe = [
3692
3880
  "partners with",
3693
3881
  "collaborates with",
3694
3882
  "supports"
3695
- ], Fe = [
3883
+ ], Oe = [
3696
3884
  16777215,
3697
3885
  // White
3698
3886
  16750950,
@@ -3707,11 +3895,11 @@ const Oe = [
3707
3895
  function At(h = 30) {
3708
3896
  const e = [], s = [];
3709
3897
  for (let i = 0; i < h; i++) {
3710
- const o = i < Oe.length ? Oe[i] : `Node ${i + 1}`;
3898
+ const o = i < Ie.length ? Ie[i] : `Node ${i + 1}`;
3711
3899
  e.push({
3712
3900
  id: `node-${i}`,
3713
3901
  label: o,
3714
- color: Fe[i % Fe.length],
3902
+ color: Oe[i % Oe.length],
3715
3903
  position: {
3716
3904
  x: (Math.random() - 0.5) * 60,
3717
3905
  y: (Math.random() - 0.5) * 60,
@@ -3724,21 +3912,21 @@ function At(h = 30) {
3724
3912
  s.push({
3725
3913
  source: `node-${i}`,
3726
3914
  target: `node-${o}`,
3727
- relationship: ee[Math.floor(Math.random() * ee.length)]
3915
+ relationship: J[Math.floor(Math.random() * J.length)]
3728
3916
  });
3729
3917
  }
3730
3918
  const t = Math.floor(h * 0.5);
3731
3919
  for (let i = 0; i < t; i++) {
3732
3920
  const o = Math.floor(Math.random() * h);
3733
- let a = Math.floor(Math.random() * h);
3734
- o === a && (a = (a + 1) % h);
3735
- const r = `node-${o}`, c = `node-${a}`;
3921
+ let n = Math.floor(Math.random() * h);
3922
+ o === n && (n = (n + 1) % h);
3923
+ const r = `node-${o}`, d = `node-${n}`;
3736
3924
  s.some(
3737
- (p) => p.source === r && p.target === c || p.source === c && p.target === r
3925
+ (p) => p.source === r && p.target === d || p.source === d && p.target === r
3738
3926
  ) || s.push({
3739
3927
  source: r,
3740
- target: c,
3741
- relationship: ee[Math.floor(Math.random() * ee.length)]
3928
+ target: d,
3929
+ relationship: J[Math.floor(Math.random() * J.length)]
3742
3930
  });
3743
3931
  }
3744
3932
  return { nodes: e, edges: s };
@@ -3752,19 +3940,19 @@ function jt(h = 1e3) {
3752
3940
  z: (Math.random() - 0.5) * 200
3753
3941
  });
3754
3942
  for (let o = 0; o < h; o++) {
3755
- const a = i[o % t];
3943
+ const n = i[o % t];
3756
3944
  e.push({
3757
3945
  id: `node-${o}`,
3758
3946
  label: `N${o}`,
3759
3947
  position: {
3760
- x: a.x + (Math.random() - 0.5) * 40,
3761
- y: a.y + (Math.random() - 0.5) * 40,
3762
- z: a.z + (Math.random() - 0.5) * 40
3948
+ x: n.x + (Math.random() - 0.5) * 40,
3949
+ y: n.y + (Math.random() - 0.5) * 40,
3950
+ z: n.z + (Math.random() - 0.5) * 40
3763
3951
  }
3764
3952
  });
3765
3953
  }
3766
3954
  for (let o = 1; o < h; o++) {
3767
- 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));
3955
+ const n = Math.floor(o / 50) * 50, r = n === 0 ? Math.floor(Math.random() * o) : n + Math.floor(Math.random() * Math.min(o - n, 50));
3768
3956
  s.push({
3769
3957
  source: `node-${o}`,
3770
3958
  target: `node-${Math.min(r, o - 1)}`,
@@ -3772,9 +3960,9 @@ function jt(h = 1e3) {
3772
3960
  });
3773
3961
  }
3774
3962
  for (let o = 1; o < t; o++) {
3775
- const a = o * 50, r = (o - 1) * 50 + Math.floor(Math.random() * 50);
3963
+ const n = o * 50, r = (o - 1) * 50 + Math.floor(Math.random() * 50);
3776
3964
  s.push({
3777
- source: `node-${a}`,
3965
+ source: `node-${n}`,
3778
3966
  target: `node-${r}`,
3779
3967
  relationship: "bridges to"
3780
3968
  });
@@ -3784,11 +3972,11 @@ function jt(h = 1e3) {
3784
3972
  export {
3785
3973
  P as DEFAULT_OPTIONS,
3786
3974
  Ht as ForceGraph3D,
3787
- X as LODLevel,
3788
- H as createEdgeKey,
3975
+ _ as LODLevel,
3976
+ Dt as createEdgeKey,
3789
3977
  jt as generateLargeSampleData,
3790
3978
  At as generateSampleData,
3791
- He as validateEdgeData,
3792
- De as validateNodeData
3979
+ De as validateEdgeData,
3980
+ Fe as validateNodeData
3793
3981
  };
3794
3982
  //# sourceMappingURL=force-3d-graph.js.map