force-3d-graph 1.0.2 → 1.2.0

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,9 +1,9 @@
1
1
  var st = Object.defineProperty;
2
- var it = (c, e, s) => e in c ? st(c, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : c[e] = s;
3
- var r = (c, e, s) => it(c, typeof e != "symbol" ? e + "" : e, s);
4
- import * as p from "three";
5
- import { EventDispatcher as nt, Vector3 as N, MOUSE as D, TOUCH as $, Spherical as Ne, Quaternion as Se, Vector2 as z, Ray as ot, Plane as at, MathUtils as rt } from "three";
6
- const L = {
2
+ var it = (h, e, s) => e in h ? st(h, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : h[e] = s;
3
+ var l = (h, e, s) => it(h, typeof e != "symbol" ? e + "" : e, s);
4
+ import * as m from "three";
5
+ import { EventDispatcher as ot, Vector3 as S, MOUSE as $, TOUCH as G, Spherical as Ne, Quaternion as Se, Vector2 as k, Ray as nt, Plane as at, MathUtils as rt } from "three";
6
+ const R = {
7
7
  backgroundColor: 657930,
8
8
  cameraPosition: { x: 0, y: 0, z: 80 },
9
9
  cameraFov: 75,
@@ -25,101 +25,103 @@ const L = {
25
25
  showPanel: !0,
26
26
  showSearch: !0,
27
27
  searchPlaceholder: "Search nodes or relationships...",
28
+ initialViewMode: "3d",
29
+ showViewToggle: !0,
28
30
  targetFPS: 60,
29
31
  maxVisibleNodes: 1e4
30
32
  };
31
- var U = /* @__PURE__ */ ((c) => (c[c.HIGH = 0] = "HIGH", c[c.MEDIUM = 1] = "MEDIUM", c[c.LOW = 2] = "LOW", c))(U || {});
33
+ var U = /* @__PURE__ */ ((h) => (h[h.HIGH = 0] = "HIGH", h[h.MEDIUM = 1] = "MEDIUM", h[h.LOW = 2] = "LOW", h))(U || {});
32
34
  function lt() {
33
- const c = document.createElement("div");
34
- return c.id = "force-graph-3d-container", c.style.cssText = `
35
+ const h = document.createElement("div");
36
+ return h.id = "force-graph-3d-container", h.style.cssText = `
35
37
  width: 100%;
36
38
  height: 100%;
37
39
  position: absolute;
38
40
  top: 0;
39
41
  left: 0;
40
42
  overflow: hidden;
41
- `, document.body.appendChild(c), c;
43
+ `, document.body.appendChild(h), h;
42
44
  }
43
- function ct(c) {
44
- return c && c instanceof HTMLElement ? c : (console.warn("[ForceGraph3D] No container provided, creating one automatically"), lt());
45
+ function ct(h) {
46
+ return h && h instanceof HTMLElement ? h : (console.warn("[ForceGraph3D] No container provided, creating one automatically"), lt());
45
47
  }
46
- function ze(c) {
47
- const e = c.getBoundingClientRect();
48
+ function ze(h) {
49
+ const e = h.getBoundingClientRect();
48
50
  return {
49
51
  width: e.width || window.innerWidth,
50
52
  height: e.height || window.innerHeight
51
53
  };
52
54
  }
53
- function Re(c) {
54
- if (!c || typeof c != "object")
55
+ function Oe(h) {
56
+ if (!h || typeof h != "object")
55
57
  return console.warn("[ForceGraph3D] Invalid node: must be an object"), !1;
56
- const e = c;
58
+ const e = h;
57
59
  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 && !dt(e.position) ? (console.warn("[ForceGraph3D] Invalid node: position must have x, y, z numbers"), !1) : !0;
58
60
  }
59
- function Fe(c) {
60
- if (!c || typeof c != "object")
61
+ function Fe(h) {
62
+ if (!h || typeof h != "object")
61
63
  return console.warn("[ForceGraph3D] Invalid edge: must be an object"), !1;
62
- const e = c;
64
+ const e = h;
63
65
  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;
64
66
  }
65
- function ht(c) {
66
- return typeof c != "string" || c.trim() === "" ? (console.warn("[ForceGraph3D] Invalid node ID: must be a non-empty string"), !1) : !0;
67
+ function ht(h) {
68
+ return typeof h != "string" || h.trim() === "" ? (console.warn("[ForceGraph3D] Invalid node ID: must be a non-empty string"), !1) : !0;
67
69
  }
68
- function dt(c) {
69
- if (!c || typeof c != "object") return !1;
70
- const e = c;
70
+ function dt(h) {
71
+ if (!h || typeof h != "object") return !1;
72
+ const e = h;
71
73
  return typeof e.x == "number" && typeof e.y == "number" && typeof e.z == "number";
72
74
  }
73
- function R(c, e) {
74
- return c === e ? `${c}-${e}` : c < e ? `${c}-${e}` : `${e}-${c}`;
75
+ function D(h, e) {
76
+ return h === e ? `${h}-${e}` : h < e ? `${h}-${e}` : `${e}-${h}`;
75
77
  }
76
- const Te = { type: "change" }, ae = { type: "start" }, Pe = { type: "end" }, Z = new ot(), Le = new at(), pt = Math.cos(70 * rt.DEG2RAD);
77
- class ut extends nt {
78
+ const ke = { type: "change" }, re = { type: "start" }, Pe = { type: "end" }, Q = new nt(), Te = new at(), pt = Math.cos(70 * rt.DEG2RAD);
79
+ class gt extends ot {
78
80
  constructor(e, s) {
79
- super(), this.object = e, this.domElement = s, this.domElement.style.touchAction = "none", this.enabled = !0, this.target = new N(), this.cursor = new N(), 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: D.ROTATE, MIDDLE: D.DOLLY, RIGHT: D.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() {
80
- return l.phi;
81
+ 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() {
82
+ return r.phi;
81
83
  }, this.getAzimuthalAngle = function() {
82
- return l.theta;
84
+ return r.theta;
83
85
  }, this.getDistance = function() {
84
86
  return this.object.position.distanceTo(this.target);
85
- }, this.listenToKeyEvents = function(o) {
86
- o.addEventListener("keydown", ne), this._domElementKeyEvents = o;
87
+ }, this.listenToKeyEvents = function(n) {
88
+ n.addEventListener("keydown", ne), this._domElementKeyEvents = n;
87
89
  }, this.stopListenToKeyEvents = function() {
88
90
  this._domElementKeyEvents.removeEventListener("keydown", ne), this._domElementKeyEvents = null;
89
91
  }, this.saveState = function() {
90
92
  t.target0.copy(t.target), t.position0.copy(t.object.position), t.zoom0 = t.object.zoom;
91
93
  }, this.reset = function() {
92
- t.target.copy(t.target0), t.object.position.copy(t.position0), t.object.zoom = t.zoom0, t.object.updateProjectionMatrix(), t.dispatchEvent(Te), t.update(), n = i.NONE;
94
+ t.target.copy(t.target0), t.object.position.copy(t.position0), t.object.zoom = t.zoom0, t.object.updateProjectionMatrix(), t.dispatchEvent(ke), t.update(), i = o.NONE;
93
95
  }, this.update = function() {
94
- const o = new N(), h = new Se().setFromUnitVectors(e.up, new N(0, 1, 0)), m = h.clone().invert(), x = new N(), w = new Se(), k = new N(), S = 2 * Math.PI;
96
+ const n = new S(), p = new Se().setFromUnitVectors(e.up, new S(0, 1, 0)), b = p.clone().invert(), w = new S(), C = new Se(), F = new S(), z = 2 * Math.PI;
95
97
  return function(tt = null) {
96
98
  const Ce = t.object.position;
97
- o.copy(Ce).sub(t.target), o.applyQuaternion(h), l.setFromVector3(o), t.autoRotate && n === i.NONE && K(He(tt)), t.enableDamping ? (l.theta += d.theta * t.dampingFactor, l.phi += d.phi * t.dampingFactor) : (l.theta += d.theta, l.phi += d.phi);
98
- let T = t.minAzimuthAngle, P = t.maxAzimuthAngle;
99
- isFinite(T) && isFinite(P) && (T < -Math.PI ? T += S : T > Math.PI && (T -= S), P < -Math.PI ? P += S : P > Math.PI && (P -= S), T <= P ? l.theta = Math.max(T, Math.min(P, l.theta)) : l.theta = l.theta > (T + P) / 2 ? Math.max(T, l.theta) : Math.min(P, l.theta)), l.phi = Math.max(t.minPolarAngle, Math.min(t.maxPolarAngle, l.phi)), l.makeSafe(), t.enableDamping === !0 ? t.target.addScaledVector(g, t.dampingFactor) : t.target.add(g), t.target.sub(t.cursor), t.target.clampLength(t.minTargetRadius, t.maxTargetRadius), t.target.add(t.cursor), t.zoomToCursor && _ || t.object.isOrthographicCamera ? l.radius = se(l.radius) : l.radius = se(l.radius * u), o.setFromSpherical(l), o.applyQuaternion(m), Ce.copy(t.target).add(o), t.object.lookAt(t.target), t.enableDamping === !0 ? (d.theta *= 1 - t.dampingFactor, d.phi *= 1 - t.dampingFactor, g.multiplyScalar(1 - t.dampingFactor)) : (d.set(0, 0, 0), g.set(0, 0, 0));
100
- let oe = !1;
101
- if (t.zoomToCursor && _) {
102
- let Y = null;
99
+ n.copy(Ce).sub(t.target), n.applyQuaternion(p), r.setFromVector3(n), t.autoRotate && i === o.NONE && B(He(tt)), t.enableDamping ? (r.theta += c.theta * t.dampingFactor, r.phi += c.phi * t.dampingFactor) : (r.theta += c.theta, r.phi += c.phi);
100
+ let L = t.minAzimuthAngle, I = t.maxAzimuthAngle;
101
+ isFinite(L) && isFinite(I) && (L < -Math.PI ? L += z : L > Math.PI && (L -= z), I < -Math.PI ? I += z : I > Math.PI && (I -= z), L <= I ? r.theta = Math.max(L, Math.min(I, r.theta)) : r.theta = r.theta > (L + I) / 2 ? Math.max(L, 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(g, t.dampingFactor) : t.target.add(g), t.target.sub(t.cursor), t.target.clampLength(t.minTargetRadius, t.maxTargetRadius), t.target.add(t.cursor), t.zoomToCursor && H || t.object.isOrthographicCamera ? r.radius = ie(r.radius) : r.radius = ie(r.radius * d), n.setFromSpherical(r), n.applyQuaternion(b), Ce.copy(t.target).add(n), t.object.lookAt(t.target), t.enableDamping === !0 ? (c.theta *= 1 - t.dampingFactor, c.phi *= 1 - t.dampingFactor, g.multiplyScalar(1 - t.dampingFactor)) : (c.set(0, 0, 0), g.set(0, 0, 0));
102
+ let ae = !1;
103
+ if (t.zoomToCursor && H) {
104
+ let X = null;
103
105
  if (t.object.isPerspectiveCamera) {
104
- const B = o.length();
105
- Y = se(B * u);
106
- const q = B - Y;
107
- t.object.position.addScaledVector(re, q), t.object.updateMatrixWorld();
106
+ const V = n.length();
107
+ X = ie(V * d);
108
+ const Z = V - X;
109
+ t.object.position.addScaledVector(Y, Z), t.object.updateMatrixWorld();
108
110
  } else if (t.object.isOrthographicCamera) {
109
- const B = new N(O.x, O.y, 0);
110
- B.unproject(t.object), t.object.zoom = Math.max(t.minZoom, Math.min(t.maxZoom, t.object.zoom / u)), t.object.updateProjectionMatrix(), oe = !0;
111
- const q = new N(O.x, O.y, 0);
112
- q.unproject(t.object), t.object.position.sub(q).add(B), t.object.updateMatrixWorld(), Y = o.length();
111
+ const V = new S(P.x, P.y, 0);
112
+ V.unproject(t.object), t.object.zoom = Math.max(t.minZoom, Math.min(t.maxZoom, t.object.zoom / d)), t.object.updateProjectionMatrix(), ae = !0;
113
+ const Z = new S(P.x, P.y, 0);
114
+ Z.unproject(t.object), t.object.position.sub(Z).add(V), t.object.updateMatrixWorld(), X = n.length();
113
115
  } else
114
116
  console.warn("WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled."), t.zoomToCursor = !1;
115
- Y !== null && (this.screenSpacePanning ? t.target.set(0, 0, -1).transformDirection(t.object.matrix).multiplyScalar(Y).add(t.object.position) : (Z.origin.copy(t.object.position), Z.direction.set(0, 0, -1).transformDirection(t.object.matrix), Math.abs(t.object.up.dot(Z.direction)) < pt ? e.lookAt(t.target) : (Le.setFromNormalAndCoplanarPoint(t.object.up, t.target), Z.intersectPlane(Le, t.target))));
116
- } else t.object.isOrthographicCamera && (t.object.zoom = Math.max(t.minZoom, Math.min(t.maxZoom, t.object.zoom / u)), t.object.updateProjectionMatrix(), oe = !0);
117
- return u = 1, _ = !1, oe || x.distanceToSquared(t.object.position) > a || 8 * (1 - w.dot(t.object.quaternion)) > a || k.distanceToSquared(t.target) > 0 ? (t.dispatchEvent(Te), x.copy(t.object.position), w.copy(t.object.quaternion), k.copy(t.target), !0) : !1;
117
+ X !== null && (this.screenSpacePanning ? t.target.set(0, 0, -1).transformDirection(t.object.matrix).multiplyScalar(X).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)) < pt ? e.lookAt(t.target) : (Te.setFromNormalAndCoplanarPoint(t.object.up, t.target), Q.intersectPlane(Te, t.target))));
118
+ } else t.object.isOrthographicCamera && (t.object.zoom = Math.max(t.minZoom, Math.min(t.maxZoom, t.object.zoom / d)), t.object.updateProjectionMatrix(), ae = !0);
119
+ return d = 1, H = !1, ae || w.distanceToSquared(t.object.position) > a || 8 * (1 - C.dot(t.object.quaternion)) > a || F.distanceToSquared(t.target) > 0 ? (t.dispatchEvent(ke), w.copy(t.object.position), C.copy(t.object.quaternion), F.copy(t.target), !0) : !1;
118
120
  };
119
121
  }(), this.dispose = function() {
120
- t.domElement.removeEventListener("contextmenu", we), t.domElement.removeEventListener("pointerdown", xe), t.domElement.removeEventListener("pointercancel", G), t.domElement.removeEventListener("wheel", ve), t.domElement.removeEventListener("pointermove", ie), t.domElement.removeEventListener("pointerup", G), t._domElementKeyEvents !== null && (t._domElementKeyEvents.removeEventListener("keydown", ne), t._domElementKeyEvents = null);
122
+ t.domElement.removeEventListener("contextmenu", we), t.domElement.removeEventListener("pointerdown", be), t.domElement.removeEventListener("pointercancel", K), t.domElement.removeEventListener("wheel", ve), t.domElement.removeEventListener("pointermove", oe), t.domElement.removeEventListener("pointerup", K), t._domElementKeyEvents !== null && (t._domElementKeyEvents.removeEventListener("keydown", ne), t._domElementKeyEvents = null);
121
123
  };
122
- const t = this, i = {
124
+ const t = this, o = {
123
125
  NONE: -1,
124
126
  ROTATE: 0,
125
127
  DOLLY: 1,
@@ -129,379 +131,379 @@ class ut extends nt {
129
131
  TOUCH_DOLLY_PAN: 5,
130
132
  TOUCH_DOLLY_ROTATE: 6
131
133
  };
132
- let n = i.NONE;
133
- const a = 1e-6, l = new Ne(), d = new Ne();
134
- let u = 1;
135
- const g = new N(), b = new z(), v = new z(), y = new z(), f = new z(), M = new z(), C = new z(), F = new z(), H = new z(), I = new z(), re = new N(), O = new z();
136
- let _ = !1;
137
- const E = [], V = {};
138
- let J = !1;
139
- function He(o) {
140
- return o !== null ? 2 * Math.PI / 60 * t.autoRotateSpeed * o : 2 * Math.PI / 60 / 60 * t.autoRotateSpeed;
141
- }
142
- function X(o) {
143
- const h = Math.abs(o * 0.01);
144
- return Math.pow(0.95, t.zoomSpeed * h);
145
- }
146
- function K(o) {
147
- d.theta -= o;
148
- }
149
- function W(o) {
150
- d.phi -= o;
134
+ let i = o.NONE;
135
+ const a = 1e-6, r = new Ne(), c = new Ne();
136
+ let d = 1;
137
+ const g = new S(), u = new k(), y = new k(), f = new k(), x = new k(), v = new k(), M = new k(), N = new k(), O = new k(), T = new k(), Y = new S(), P = new k();
138
+ let H = !1;
139
+ const E = [], _ = {};
140
+ let ee = !1;
141
+ function He(n) {
142
+ return n !== null ? 2 * Math.PI / 60 * t.autoRotateSpeed * n : 2 * Math.PI / 60 / 60 * t.autoRotateSpeed;
143
+ }
144
+ function q(n) {
145
+ const p = Math.abs(n * 0.01);
146
+ return Math.pow(0.95, t.zoomSpeed * p);
147
+ }
148
+ function B(n) {
149
+ c.theta -= n;
150
+ }
151
+ function W(n) {
152
+ c.phi -= n;
151
153
  }
152
154
  const le = function() {
153
- const o = new N();
154
- return function(m, x) {
155
- o.setFromMatrixColumn(x, 0), o.multiplyScalar(-m), g.add(o);
155
+ const n = new S();
156
+ return function(b, w) {
157
+ n.setFromMatrixColumn(w, 0), n.multiplyScalar(-b), g.add(n);
156
158
  };
157
159
  }(), ce = function() {
158
- const o = new N();
159
- return function(m, x) {
160
- t.screenSpacePanning === !0 ? o.setFromMatrixColumn(x, 1) : (o.setFromMatrixColumn(x, 0), o.crossVectors(t.object.up, o)), o.multiplyScalar(m), g.add(o);
160
+ const n = new S();
161
+ return function(b, w) {
162
+ t.screenSpacePanning === !0 ? n.setFromMatrixColumn(w, 1) : (n.setFromMatrixColumn(w, 0), n.crossVectors(t.object.up, n)), n.multiplyScalar(b), g.add(n);
161
163
  };
162
164
  }(), A = function() {
163
- const o = new N();
164
- return function(m, x) {
165
- const w = t.domElement;
165
+ const n = new S();
166
+ return function(b, w) {
167
+ const C = t.domElement;
166
168
  if (t.object.isPerspectiveCamera) {
167
- const k = t.object.position;
168
- o.copy(k).sub(t.target);
169
- let S = o.length();
170
- S *= Math.tan(t.object.fov / 2 * Math.PI / 180), le(2 * m * S / w.clientHeight, t.object.matrix), ce(2 * x * S / w.clientHeight, t.object.matrix);
171
- } else t.object.isOrthographicCamera ? (le(m * (t.object.right - t.object.left) / t.object.zoom / w.clientWidth, t.object.matrix), ce(x * (t.object.top - t.object.bottom) / t.object.zoom / w.clientHeight, t.object.matrix)) : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."), t.enablePan = !1);
169
+ const F = t.object.position;
170
+ n.copy(F).sub(t.target);
171
+ let z = n.length();
172
+ z *= Math.tan(t.object.fov / 2 * Math.PI / 180), le(2 * b * z / C.clientHeight, t.object.matrix), ce(2 * w * z / C.clientHeight, t.object.matrix);
173
+ } else t.object.isOrthographicCamera ? (le(b * (t.object.right - t.object.left) / t.object.zoom / C.clientWidth, t.object.matrix), ce(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
174
  };
173
175
  }();
174
- function ee(o) {
175
- t.object.isPerspectiveCamera || t.object.isOrthographicCamera ? u /= o : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."), t.enableZoom = !1);
176
+ function te(n) {
177
+ t.object.isPerspectiveCamera || t.object.isOrthographicCamera ? d /= n : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."), t.enableZoom = !1);
176
178
  }
177
- function he(o) {
178
- t.object.isPerspectiveCamera || t.object.isOrthographicCamera ? u *= o : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."), t.enableZoom = !1);
179
+ function he(n) {
180
+ t.object.isPerspectiveCamera || t.object.isOrthographicCamera ? d *= n : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."), t.enableZoom = !1);
179
181
  }
180
- function te(o, h) {
182
+ function se(n, p) {
181
183
  if (!t.zoomToCursor)
182
184
  return;
183
- _ = !0;
184
- const m = t.domElement.getBoundingClientRect(), x = o - m.left, w = h - m.top, k = m.width, S = m.height;
185
- O.x = x / k * 2 - 1, O.y = -(w / S) * 2 + 1, re.set(O.x, O.y, 1).unproject(t.object).sub(t.object.position).normalize();
185
+ H = !0;
186
+ const b = t.domElement.getBoundingClientRect(), w = n - b.left, C = p - b.top, F = b.width, z = b.height;
187
+ P.x = w / F * 2 - 1, P.y = -(C / z) * 2 + 1, Y.set(P.x, P.y, 1).unproject(t.object).sub(t.object.position).normalize();
186
188
  }
187
- function se(o) {
188
- return Math.max(t.minDistance, Math.min(t.maxDistance, o));
189
+ function ie(n) {
190
+ return Math.max(t.minDistance, Math.min(t.maxDistance, n));
189
191
  }
190
- function de(o) {
191
- b.set(o.clientX, o.clientY);
192
+ function de(n) {
193
+ u.set(n.clientX, n.clientY);
192
194
  }
193
- function Ae(o) {
194
- te(o.clientX, o.clientX), F.set(o.clientX, o.clientY);
195
+ function De(n) {
196
+ se(n.clientX, n.clientX), N.set(n.clientX, n.clientY);
195
197
  }
196
- function pe(o) {
197
- f.set(o.clientX, o.clientY);
198
+ function pe(n) {
199
+ x.set(n.clientX, n.clientY);
198
200
  }
199
- function je(o) {
200
- v.set(o.clientX, o.clientY), y.subVectors(v, b).multiplyScalar(t.rotateSpeed);
201
- const h = t.domElement;
202
- K(2 * Math.PI * y.x / h.clientHeight), W(2 * Math.PI * y.y / h.clientHeight), b.copy(v), t.update();
201
+ function Ae(n) {
202
+ y.set(n.clientX, n.clientY), f.subVectors(y, u).multiplyScalar(t.rotateSpeed);
203
+ const p = t.domElement;
204
+ B(2 * Math.PI * f.x / p.clientHeight), W(2 * Math.PI * f.y / p.clientHeight), u.copy(y), t.update();
203
205
  }
204
- function De(o) {
205
- H.set(o.clientX, o.clientY), I.subVectors(H, F), I.y > 0 ? ee(X(I.y)) : I.y < 0 && he(X(I.y)), F.copy(H), t.update();
206
+ function je(n) {
207
+ O.set(n.clientX, n.clientY), T.subVectors(O, N), T.y > 0 ? te(q(T.y)) : T.y < 0 && he(q(T.y)), N.copy(O), t.update();
206
208
  }
207
- function $e(o) {
208
- M.set(o.clientX, o.clientY), C.subVectors(M, f).multiplyScalar(t.panSpeed), A(C.x, C.y), f.copy(M), t.update();
209
+ function $e(n) {
210
+ v.set(n.clientX, n.clientY), M.subVectors(v, x).multiplyScalar(t.panSpeed), A(M.x, M.y), x.copy(v), t.update();
209
211
  }
210
- function Ke(o) {
211
- te(o.clientX, o.clientY), o.deltaY < 0 ? he(X(o.deltaY)) : o.deltaY > 0 && ee(X(o.deltaY)), t.update();
212
+ function Ge(n) {
213
+ se(n.clientX, n.clientY), n.deltaY < 0 ? he(q(n.deltaY)) : n.deltaY > 0 && te(q(n.deltaY)), t.update();
212
214
  }
213
- function Ge(o) {
214
- let h = !1;
215
- switch (o.code) {
215
+ function Ye(n) {
216
+ let p = !1;
217
+ switch (n.code) {
216
218
  case t.keys.UP:
217
- o.ctrlKey || o.metaKey || o.shiftKey ? W(2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(0, t.keyPanSpeed), h = !0;
219
+ n.ctrlKey || n.metaKey || n.shiftKey ? W(2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(0, t.keyPanSpeed), p = !0;
218
220
  break;
219
221
  case t.keys.BOTTOM:
220
- o.ctrlKey || o.metaKey || o.shiftKey ? W(-2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(0, -t.keyPanSpeed), h = !0;
222
+ n.ctrlKey || n.metaKey || n.shiftKey ? W(-2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(0, -t.keyPanSpeed), p = !0;
221
223
  break;
222
224
  case t.keys.LEFT:
223
- o.ctrlKey || o.metaKey || o.shiftKey ? K(2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(t.keyPanSpeed, 0), h = !0;
225
+ n.ctrlKey || n.metaKey || n.shiftKey ? B(2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(t.keyPanSpeed, 0), p = !0;
224
226
  break;
225
227
  case t.keys.RIGHT:
226
- o.ctrlKey || o.metaKey || o.shiftKey ? K(-2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(-t.keyPanSpeed, 0), h = !0;
228
+ n.ctrlKey || n.metaKey || n.shiftKey ? B(-2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(-t.keyPanSpeed, 0), p = !0;
227
229
  break;
228
230
  }
229
- h && (o.preventDefault(), t.update());
231
+ p && (n.preventDefault(), t.update());
230
232
  }
231
- function ue(o) {
233
+ function ge(n) {
232
234
  if (E.length === 1)
233
- b.set(o.pageX, o.pageY);
235
+ u.set(n.pageX, n.pageY);
234
236
  else {
235
- const h = j(o), m = 0.5 * (o.pageX + h.x), x = 0.5 * (o.pageY + h.y);
236
- b.set(m, x);
237
+ const p = j(n), b = 0.5 * (n.pageX + p.x), w = 0.5 * (n.pageY + p.y);
238
+ u.set(b, w);
237
239
  }
238
240
  }
239
- function ge(o) {
241
+ function ue(n) {
240
242
  if (E.length === 1)
241
- f.set(o.pageX, o.pageY);
243
+ x.set(n.pageX, n.pageY);
242
244
  else {
243
- const h = j(o), m = 0.5 * (o.pageX + h.x), x = 0.5 * (o.pageY + h.y);
244
- f.set(m, x);
245
+ const p = j(n), b = 0.5 * (n.pageX + p.x), w = 0.5 * (n.pageY + p.y);
246
+ x.set(b, w);
245
247
  }
246
248
  }
247
- function me(o) {
248
- const h = j(o), m = o.pageX - h.x, x = o.pageY - h.y, w = Math.sqrt(m * m + x * x);
249
- F.set(0, w);
249
+ function fe(n) {
250
+ const p = j(n), b = n.pageX - p.x, w = n.pageY - p.y, C = Math.sqrt(b * b + w * w);
251
+ N.set(0, C);
250
252
  }
251
- function Ye(o) {
252
- t.enableZoom && me(o), t.enablePan && ge(o);
253
+ function Be(n) {
254
+ t.enableZoom && fe(n), t.enablePan && ue(n);
253
255
  }
254
- function Be(o) {
255
- t.enableZoom && me(o), t.enableRotate && ue(o);
256
+ function Ke(n) {
257
+ t.enableZoom && fe(n), t.enableRotate && ge(n);
256
258
  }
257
- function fe(o) {
259
+ function me(n) {
258
260
  if (E.length == 1)
259
- v.set(o.pageX, o.pageY);
261
+ y.set(n.pageX, n.pageY);
260
262
  else {
261
- const m = j(o), x = 0.5 * (o.pageX + m.x), w = 0.5 * (o.pageY + m.y);
262
- v.set(x, w);
263
+ const b = j(n), w = 0.5 * (n.pageX + b.x), C = 0.5 * (n.pageY + b.y);
264
+ y.set(w, C);
263
265
  }
264
- y.subVectors(v, b).multiplyScalar(t.rotateSpeed);
265
- const h = t.domElement;
266
- K(2 * Math.PI * y.x / h.clientHeight), W(2 * Math.PI * y.y / h.clientHeight), b.copy(v);
266
+ f.subVectors(y, u).multiplyScalar(t.rotateSpeed);
267
+ const p = t.domElement;
268
+ B(2 * Math.PI * f.x / p.clientHeight), W(2 * Math.PI * f.y / p.clientHeight), u.copy(y);
267
269
  }
268
- function ye(o) {
270
+ function ye(n) {
269
271
  if (E.length === 1)
270
- M.set(o.pageX, o.pageY);
272
+ v.set(n.pageX, n.pageY);
271
273
  else {
272
- const h = j(o), m = 0.5 * (o.pageX + h.x), x = 0.5 * (o.pageY + h.y);
273
- M.set(m, x);
274
+ const p = j(n), b = 0.5 * (n.pageX + p.x), w = 0.5 * (n.pageY + p.y);
275
+ v.set(b, w);
274
276
  }
275
- C.subVectors(M, f).multiplyScalar(t.panSpeed), A(C.x, C.y), f.copy(M);
277
+ M.subVectors(v, x).multiplyScalar(t.panSpeed), A(M.x, M.y), x.copy(v);
276
278
  }
277
- function be(o) {
278
- const h = j(o), m = o.pageX - h.x, x = o.pageY - h.y, w = Math.sqrt(m * m + x * x);
279
- H.set(0, w), I.set(0, Math.pow(H.y / F.y, t.zoomSpeed)), ee(I.y), F.copy(H);
280
- const k = (o.pageX + h.x) * 0.5, S = (o.pageY + h.y) * 0.5;
281
- te(k, S);
279
+ function xe(n) {
280
+ const p = j(n), b = n.pageX - p.x, w = n.pageY - p.y, C = Math.sqrt(b * b + w * w);
281
+ O.set(0, C), T.set(0, Math.pow(O.y / N.y, t.zoomSpeed)), te(T.y), N.copy(O);
282
+ const F = (n.pageX + p.x) * 0.5, z = (n.pageY + p.y) * 0.5;
283
+ se(F, z);
282
284
  }
283
- function Ue(o) {
284
- t.enableZoom && be(o), t.enablePan && ye(o);
285
+ function Xe(n) {
286
+ t.enableZoom && xe(n), t.enablePan && ye(n);
285
287
  }
286
- function _e(o) {
287
- t.enableZoom && be(o), t.enableRotate && fe(o);
288
+ function Ve(n) {
289
+ t.enableZoom && xe(n), t.enableRotate && me(n);
288
290
  }
289
- function xe(o) {
290
- t.enabled !== !1 && (E.length === 0 && (t.domElement.setPointerCapture(o.pointerId), t.domElement.addEventListener("pointermove", ie), t.domElement.addEventListener("pointerup", G)), Je(o), o.pointerType === "touch" ? Ze(o) : Ve(o));
291
+ function be(n) {
292
+ t.enabled !== !1 && (E.length === 0 && (t.domElement.setPointerCapture(n.pointerId), t.domElement.addEventListener("pointermove", oe), t.domElement.addEventListener("pointerup", K)), Je(n), n.pointerType === "touch" ? Ze(n) : Ue(n));
291
293
  }
292
- function ie(o) {
293
- t.enabled !== !1 && (o.pointerType === "touch" ? Qe(o) : Xe(o));
294
+ function oe(n) {
295
+ t.enabled !== !1 && (n.pointerType === "touch" ? Qe(n) : _e(n));
294
296
  }
295
- function G(o) {
296
- et(o), E.length === 0 && (t.domElement.releasePointerCapture(o.pointerId), t.domElement.removeEventListener("pointermove", ie), t.domElement.removeEventListener("pointerup", G)), t.dispatchEvent(Pe), n = i.NONE;
297
+ function K(n) {
298
+ et(n), E.length === 0 && (t.domElement.releasePointerCapture(n.pointerId), t.domElement.removeEventListener("pointermove", oe), t.domElement.removeEventListener("pointerup", K)), t.dispatchEvent(Pe), i = o.NONE;
297
299
  }
298
- function Ve(o) {
299
- let h;
300
- switch (o.button) {
300
+ function Ue(n) {
301
+ let p;
302
+ switch (n.button) {
301
303
  case 0:
302
- h = t.mouseButtons.LEFT;
304
+ p = t.mouseButtons.LEFT;
303
305
  break;
304
306
  case 1:
305
- h = t.mouseButtons.MIDDLE;
307
+ p = t.mouseButtons.MIDDLE;
306
308
  break;
307
309
  case 2:
308
- h = t.mouseButtons.RIGHT;
310
+ p = t.mouseButtons.RIGHT;
309
311
  break;
310
312
  default:
311
- h = -1;
313
+ p = -1;
312
314
  }
313
- switch (h) {
314
- case D.DOLLY:
315
+ switch (p) {
316
+ case $.DOLLY:
315
317
  if (t.enableZoom === !1) return;
316
- Ae(o), n = i.DOLLY;
318
+ De(n), i = o.DOLLY;
317
319
  break;
318
- case D.ROTATE:
319
- if (o.ctrlKey || o.metaKey || o.shiftKey) {
320
+ case $.ROTATE:
321
+ if (n.ctrlKey || n.metaKey || n.shiftKey) {
320
322
  if (t.enablePan === !1) return;
321
- pe(o), n = i.PAN;
323
+ pe(n), i = o.PAN;
322
324
  } else {
323
325
  if (t.enableRotate === !1) return;
324
- de(o), n = i.ROTATE;
326
+ de(n), i = o.ROTATE;
325
327
  }
326
328
  break;
327
- case D.PAN:
328
- if (o.ctrlKey || o.metaKey || o.shiftKey) {
329
+ case $.PAN:
330
+ if (n.ctrlKey || n.metaKey || n.shiftKey) {
329
331
  if (t.enableRotate === !1) return;
330
- de(o), n = i.ROTATE;
332
+ de(n), i = o.ROTATE;
331
333
  } else {
332
334
  if (t.enablePan === !1) return;
333
- pe(o), n = i.PAN;
335
+ pe(n), i = o.PAN;
334
336
  }
335
337
  break;
336
338
  default:
337
- n = i.NONE;
339
+ i = o.NONE;
338
340
  }
339
- n !== i.NONE && t.dispatchEvent(ae);
341
+ i !== o.NONE && t.dispatchEvent(re);
340
342
  }
341
- function Xe(o) {
342
- switch (n) {
343
- case i.ROTATE:
343
+ function _e(n) {
344
+ switch (i) {
345
+ case o.ROTATE:
344
346
  if (t.enableRotate === !1) return;
345
- je(o);
347
+ Ae(n);
346
348
  break;
347
- case i.DOLLY:
349
+ case o.DOLLY:
348
350
  if (t.enableZoom === !1) return;
349
- De(o);
351
+ je(n);
350
352
  break;
351
- case i.PAN:
353
+ case o.PAN:
352
354
  if (t.enablePan === !1) return;
353
- $e(o);
355
+ $e(n);
354
356
  break;
355
357
  }
356
358
  }
357
- function ve(o) {
358
- t.enabled === !1 || t.enableZoom === !1 || n !== i.NONE || (o.preventDefault(), t.dispatchEvent(ae), Ke(We(o)), t.dispatchEvent(Pe));
359
+ function ve(n) {
360
+ t.enabled === !1 || t.enableZoom === !1 || i !== o.NONE || (n.preventDefault(), t.dispatchEvent(re), Ge(qe(n)), t.dispatchEvent(Pe));
359
361
  }
360
- function We(o) {
361
- const h = o.deltaMode, m = {
362
- clientX: o.clientX,
363
- clientY: o.clientY,
364
- deltaY: o.deltaY
362
+ function qe(n) {
363
+ const p = n.deltaMode, b = {
364
+ clientX: n.clientX,
365
+ clientY: n.clientY,
366
+ deltaY: n.deltaY
365
367
  };
366
- switch (h) {
368
+ switch (p) {
367
369
  case 1:
368
- m.deltaY *= 16;
370
+ b.deltaY *= 16;
369
371
  break;
370
372
  case 2:
371
- m.deltaY *= 100;
373
+ b.deltaY *= 100;
372
374
  break;
373
375
  }
374
- return o.ctrlKey && !J && (m.deltaY *= 10), m;
376
+ return n.ctrlKey && !ee && (b.deltaY *= 10), b;
375
377
  }
376
- function qe(o) {
377
- o.key === "Control" && (J = !0, document.addEventListener("keyup", Me, { passive: !0, capture: !0 }));
378
+ function We(n) {
379
+ n.key === "Control" && (ee = !0, document.addEventListener("keyup", Me, { passive: !0, capture: !0 }));
378
380
  }
379
- function Me(o) {
380
- o.key === "Control" && (J = !1, document.removeEventListener("keyup", Me, { passive: !0, capture: !0 }));
381
+ function Me(n) {
382
+ n.key === "Control" && (ee = !1, document.removeEventListener("keyup", Me, { passive: !0, capture: !0 }));
381
383
  }
382
- function ne(o) {
383
- t.enabled === !1 || t.enablePan === !1 || Ge(o);
384
+ function ne(n) {
385
+ t.enabled === !1 || t.enablePan === !1 || Ye(n);
384
386
  }
385
- function Ze(o) {
386
- switch (Ee(o), E.length) {
387
+ function Ze(n) {
388
+ switch (Ee(n), E.length) {
387
389
  case 1:
388
390
  switch (t.touches.ONE) {
389
- case $.ROTATE:
391
+ case G.ROTATE:
390
392
  if (t.enableRotate === !1) return;
391
- ue(o), n = i.TOUCH_ROTATE;
393
+ ge(n), i = o.TOUCH_ROTATE;
392
394
  break;
393
- case $.PAN:
395
+ case G.PAN:
394
396
  if (t.enablePan === !1) return;
395
- ge(o), n = i.TOUCH_PAN;
397
+ ue(n), i = o.TOUCH_PAN;
396
398
  break;
397
399
  default:
398
- n = i.NONE;
400
+ i = o.NONE;
399
401
  }
400
402
  break;
401
403
  case 2:
402
404
  switch (t.touches.TWO) {
403
- case $.DOLLY_PAN:
405
+ case G.DOLLY_PAN:
404
406
  if (t.enableZoom === !1 && t.enablePan === !1) return;
405
- Ye(o), n = i.TOUCH_DOLLY_PAN;
407
+ Be(n), i = o.TOUCH_DOLLY_PAN;
406
408
  break;
407
- case $.DOLLY_ROTATE:
409
+ case G.DOLLY_ROTATE:
408
410
  if (t.enableZoom === !1 && t.enableRotate === !1) return;
409
- Be(o), n = i.TOUCH_DOLLY_ROTATE;
411
+ Ke(n), i = o.TOUCH_DOLLY_ROTATE;
410
412
  break;
411
413
  default:
412
- n = i.NONE;
414
+ i = o.NONE;
413
415
  }
414
416
  break;
415
417
  default:
416
- n = i.NONE;
418
+ i = o.NONE;
417
419
  }
418
- n !== i.NONE && t.dispatchEvent(ae);
420
+ i !== o.NONE && t.dispatchEvent(re);
419
421
  }
420
- function Qe(o) {
421
- switch (Ee(o), n) {
422
- case i.TOUCH_ROTATE:
422
+ function Qe(n) {
423
+ switch (Ee(n), i) {
424
+ case o.TOUCH_ROTATE:
423
425
  if (t.enableRotate === !1) return;
424
- fe(o), t.update();
426
+ me(n), t.update();
425
427
  break;
426
- case i.TOUCH_PAN:
428
+ case o.TOUCH_PAN:
427
429
  if (t.enablePan === !1) return;
428
- ye(o), t.update();
430
+ ye(n), t.update();
429
431
  break;
430
- case i.TOUCH_DOLLY_PAN:
432
+ case o.TOUCH_DOLLY_PAN:
431
433
  if (t.enableZoom === !1 && t.enablePan === !1) return;
432
- Ue(o), t.update();
434
+ Xe(n), t.update();
433
435
  break;
434
- case i.TOUCH_DOLLY_ROTATE:
436
+ case o.TOUCH_DOLLY_ROTATE:
435
437
  if (t.enableZoom === !1 && t.enableRotate === !1) return;
436
- _e(o), t.update();
438
+ Ve(n), t.update();
437
439
  break;
438
440
  default:
439
- n = i.NONE;
441
+ i = o.NONE;
440
442
  }
441
443
  }
442
- function we(o) {
443
- t.enabled !== !1 && o.preventDefault();
444
+ function we(n) {
445
+ t.enabled !== !1 && n.preventDefault();
444
446
  }
445
- function Je(o) {
446
- E.push(o.pointerId);
447
+ function Je(n) {
448
+ E.push(n.pointerId);
447
449
  }
448
- function et(o) {
449
- delete V[o.pointerId];
450
- for (let h = 0; h < E.length; h++)
451
- if (E[h] == o.pointerId) {
452
- E.splice(h, 1);
450
+ function et(n) {
451
+ delete _[n.pointerId];
452
+ for (let p = 0; p < E.length; p++)
453
+ if (E[p] == n.pointerId) {
454
+ E.splice(p, 1);
453
455
  return;
454
456
  }
455
457
  }
456
- function Ee(o) {
457
- let h = V[o.pointerId];
458
- h === void 0 && (h = new z(), V[o.pointerId] = h), h.set(o.pageX, o.pageY);
458
+ function Ee(n) {
459
+ let p = _[n.pointerId];
460
+ p === void 0 && (p = new k(), _[n.pointerId] = p), p.set(n.pageX, n.pageY);
459
461
  }
460
- function j(o) {
461
- const h = o.pointerId === E[0] ? E[1] : E[0];
462
- return V[h];
462
+ function j(n) {
463
+ const p = n.pointerId === E[0] ? E[1] : E[0];
464
+ return _[p];
463
465
  }
464
- t.domElement.addEventListener("contextmenu", we), t.domElement.addEventListener("pointerdown", xe), t.domElement.addEventListener("pointercancel", G), t.domElement.addEventListener("wheel", ve, { passive: !1 }), document.addEventListener("keydown", qe, { passive: !0, capture: !0 }), this.update();
466
+ t.domElement.addEventListener("contextmenu", we), t.domElement.addEventListener("pointerdown", be), t.domElement.addEventListener("pointercancel", K), t.domElement.addEventListener("wheel", ve, { passive: !1 }), document.addEventListener("keydown", We, { passive: !0, capture: !0 }), this.update();
465
467
  }
466
468
  }
467
- class gt {
469
+ class ut {
468
470
  constructor(e, s) {
469
- r(this, "scene");
470
- r(this, "camera");
471
- r(this, "renderer");
472
- r(this, "controls");
473
- r(this, "container");
474
- r(this, "resizeHandler");
475
- this.container = e, this.scene = new p.Scene(), this.scene.background = new p.Color(
471
+ l(this, "scene");
472
+ l(this, "camera");
473
+ l(this, "renderer");
474
+ l(this, "controls");
475
+ l(this, "container");
476
+ l(this, "resizeHandler");
477
+ this.container = e, this.scene = new m.Scene(), this.scene.background = new m.Color(
476
478
  s.backgroundColor ?? 657930
477
479
  );
478
- const { width: t, height: i } = ze(e), n = s.cameraFov ?? 75;
479
- this.camera = new p.PerspectiveCamera(n, t / i, 0.1, 2e3);
480
+ const { width: t, height: o } = ze(e), i = s.cameraFov ?? 75;
481
+ this.camera = new m.PerspectiveCamera(i, t / o, 0.1, 2e3);
480
482
  const a = s.cameraPosition ?? { x: 0, y: 0, z: 80 };
481
- this.camera.position.set(a.x, a.y, a.z), this.renderer = new p.WebGLRenderer({
483
+ this.camera.position.set(a.x, a.y, a.z), this.renderer = new m.WebGLRenderer({
482
484
  antialias: !0,
483
485
  alpha: !0,
484
486
  powerPreference: "high-performance"
485
- }), this.renderer.setSize(t, i), this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)), this.renderer.toneMapping = p.ACESFilmicToneMapping, this.renderer.toneMappingExposure = 1, this.renderer.shadowMap.enabled = !0, this.renderer.shadowMap.type = p.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 = 500, this.setupLighting(), this.resizeHandler = this.onWindowResize.bind(this), window.addEventListener("resize", this.resizeHandler);
487
+ }), this.renderer.setSize(t, o), this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)), this.renderer.toneMapping = m.ACESFilmicToneMapping, this.renderer.toneMappingExposure = 1, this.renderer.shadowMap.enabled = !0, this.renderer.shadowMap.type = m.PCFSoftShadowMap, e.appendChild(this.renderer.domElement), this.controls = new gt(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 = 500, this.setupLighting(), this.resizeHandler = this.onWindowResize.bind(this), window.addEventListener("resize", this.resizeHandler);
486
488
  }
487
489
  /**
488
490
  * Sets up scene lighting for gradient glass on dark background
489
491
  */
490
492
  setupLighting() {
491
- const e = new p.AmbientLight(16777215, 0.4);
493
+ const e = new m.AmbientLight(16777215, 0.4);
492
494
  this.scene.add(e);
493
- const s = new p.DirectionalLight(16777215, 0.9);
495
+ const s = new m.DirectionalLight(16777215, 0.9);
494
496
  s.position.set(50, 60, 40), s.castShadow = !0, s.shadow.mapSize.width = 1024, s.shadow.mapSize.height = 1024, this.scene.add(s);
495
- const t = new p.DirectionalLight(16773344, 0.4);
497
+ const t = new m.DirectionalLight(16773344, 0.4);
496
498
  t.position.set(-50, 30, -40), this.scene.add(t);
497
- const i = new p.DirectionalLight(16777215, 0.3);
498
- i.position.set(0, -30, -50), this.scene.add(i);
499
- const n = new p.PointLight(16750950, 0.5, 150);
500
- n.position.set(40, 20, 40), this.scene.add(n);
501
- const a = new p.PointLight(16764057, 0.4, 150);
499
+ const o = new m.DirectionalLight(16777215, 0.3);
500
+ o.position.set(0, -30, -50), this.scene.add(o);
501
+ const i = new m.PointLight(16750950, 0.5, 150);
502
+ i.position.set(40, 20, 40), this.scene.add(i);
503
+ const a = new m.PointLight(16764057, 0.4, 150);
502
504
  a.position.set(-40, -20, 40), this.scene.add(a);
503
- const l = new p.PointLight(6724095, 0.2, 100);
504
- l.position.set(0, 40, -40), this.scene.add(l);
505
+ const r = new m.PointLight(6724095, 0.2, 100);
506
+ r.position.set(0, 40, -40), this.scene.add(r);
505
507
  }
506
508
  /**
507
509
  * Handle window resize
@@ -542,7 +544,7 @@ class gt {
542
544
  * Gets the camera's forward direction
543
545
  */
544
546
  getCameraDirection() {
545
- const e = new p.Vector3();
547
+ const e = new m.Vector3();
546
548
  return this.camera.getWorldDirection(e), e;
547
549
  }
548
550
  /**
@@ -555,12 +557,12 @@ class gt {
555
557
  }
556
558
  }
557
559
  }
558
- class mt {
560
+ class ft {
559
561
  constructor(e, s) {
560
- r(this, "sceneManager");
561
- r(this, "nodeFactory");
562
- r(this, "nodes", /* @__PURE__ */ new Map());
563
- r(this, "nodeObjects", /* @__PURE__ */ new Map());
562
+ l(this, "sceneManager");
563
+ l(this, "nodeFactory");
564
+ l(this, "nodes", /* @__PURE__ */ new Map());
565
+ l(this, "nodeObjects", /* @__PURE__ */ new Map());
564
566
  this.sceneManager = e, this.nodeFactory = s;
565
567
  }
566
568
  /**
@@ -574,7 +576,7 @@ class mt {
574
576
  * @returns true if added, false if node already exists or invalid
575
577
  */
576
578
  addNode(e, s = 0) {
577
- if (!Re(e))
579
+ if (!Oe(e))
578
580
  return !1;
579
581
  if (this.nodes.has(e.id))
580
582
  return console.warn(`[ForceGraph3D] Node with id "${e.id}" already exists`), !1;
@@ -582,16 +584,16 @@ class mt {
582
584
  x: (Math.random() - 0.5) * 50,
583
585
  y: (Math.random() - 0.5) * 50,
584
586
  z: (Math.random() - 0.5) * 50
585
- }, i = {
587
+ }, o = {
586
588
  ...e,
587
589
  position: t,
588
590
  velocity: { x: 0, y: 0, z: 0 },
589
591
  mass: 1
590
- }, n = this.nodeFactory.createNode(
592
+ }, i = this.nodeFactory.createNode(
591
593
  { ...e, position: t },
592
594
  s
593
595
  );
594
- return this.sceneManager.add(n.group), this.nodes.set(e.id, i), this.nodeObjects.set(e.id, n), !0;
596
+ return this.sceneManager.add(i.group), this.nodes.set(e.id, o), this.nodeObjects.set(e.id, i), !0;
595
597
  }
596
598
  /**
597
599
  * Removes a node from the graph
@@ -605,17 +607,17 @@ class mt {
605
607
  * Updates a node's properties
606
608
  */
607
609
  updateNode(e, s) {
608
- const t = this.nodes.get(e), i = this.nodeObjects.get(e);
609
- return !t || !i ? (console.warn(`[ForceGraph3D] Node "${e}" not found`), !1) : (s.label !== void 0 && (t.label = s.label, this.nodeFactory.updateNodeLabel(i, s.label)), s.color !== void 0 && (t.color = s.color, this.nodeFactory.updateNodeColor(i, s.color)), Object.keys(s).forEach((n) => {
610
- n !== "id" && n !== "label" && n !== "color" && n !== "position" && (t[n] = s[n]);
610
+ const t = this.nodes.get(e), o = this.nodeObjects.get(e);
611
+ return !t || !o ? (console.warn(`[ForceGraph3D] Node "${e}" not found`), !1) : (s.label !== void 0 && (t.label = s.label, this.nodeFactory.updateNodeLabel(o, s.label)), s.color !== void 0 && (t.color = s.color, this.nodeFactory.updateNodeColor(o, s.color)), Object.keys(s).forEach((i) => {
612
+ i !== "id" && i !== "label" && i !== "color" && i !== "position" && (t[i] = s[i]);
611
613
  }), !0);
612
614
  }
613
615
  /**
614
616
  * Updates a node's position (called by physics engine)
615
617
  */
616
618
  updateNodePosition(e, s) {
617
- const t = this.nodes.get(e), i = this.nodeObjects.get(e);
618
- t && i && (t.position = s, i.group.position.set(s.x, s.y, s.z));
619
+ const t = this.nodes.get(e), o = this.nodeObjects.get(e);
620
+ t && o && (t.position = s, o.group.position.set(s.x, s.y, s.z));
619
621
  }
620
622
  /**
621
623
  * Updates a node's LOD level
@@ -681,22 +683,22 @@ class mt {
681
683
  this.clear();
682
684
  }
683
685
  }
684
- class ft {
686
+ class mt {
685
687
  constructor(e, s, t) {
686
- r(this, "sceneManager");
687
- r(this, "nodeManager");
688
- r(this, "edgeFactory");
689
- r(this, "edges", []);
690
- r(this, "edgeObjects", []);
691
- r(this, "edgeKeySet", /* @__PURE__ */ new Set());
692
- r(this, "highlightedEdgeKey", null);
688
+ l(this, "sceneManager");
689
+ l(this, "nodeManager");
690
+ l(this, "edgeFactory");
691
+ l(this, "edges", []);
692
+ l(this, "edgeObjects", []);
693
+ l(this, "edgeKeySet", /* @__PURE__ */ new Set());
694
+ l(this, "highlightedEdgeKey", null);
693
695
  this.sceneManager = e, this.nodeManager = s, this.edgeFactory = t;
694
696
  }
695
697
  /**
696
698
  * Checks if an edge exists
697
699
  */
698
700
  hasEdge(e, s) {
699
- const t = R(e, s);
701
+ const t = D(e, s);
700
702
  return this.edgeKeySet.has(t);
701
703
  }
702
704
  /**
@@ -710,44 +712,44 @@ class ft {
710
712
  return console.warn(`[ForceGraph3D] Source node "${e.source}" does not exist`), !1;
711
713
  if (!this.nodeManager.hasNode(e.target))
712
714
  return console.warn(`[ForceGraph3D] Target node "${e.target}" does not exist`), !1;
713
- const s = R(e.source, e.target);
715
+ const s = D(e.source, e.target);
714
716
  if (this.edgeKeySet.has(s))
715
717
  return console.warn(`[ForceGraph3D] Edge "${e.source}" -> "${e.target}" already exists`), !1;
716
- const t = this.nodeManager.getNode(e.source), i = this.nodeManager.getNode(e.target), n = this.edgeFactory.createEdge(
718
+ const t = this.nodeManager.getNode(e.source), o = this.nodeManager.getNode(e.target), i = this.edgeFactory.createEdge(
717
719
  e,
718
720
  t,
719
- i,
721
+ o,
720
722
  t.position,
721
- i.position
723
+ o.position
722
724
  );
723
- return this.sceneManager.add(n.line), this.edges.push(e), this.edgeObjects.push(n), this.edgeKeySet.add(s), !0;
725
+ return this.sceneManager.add(i.line), this.edges.push(e), this.edgeObjects.push(i), this.edgeKeySet.add(s), !0;
724
726
  }
725
727
  /**
726
728
  * Removes an edge from the graph
727
729
  * @returns true if removed, false if not found
728
730
  */
729
731
  removeEdge(e, s) {
730
- const t = R(e, s);
732
+ const t = D(e, s);
731
733
  if (!this.edgeKeySet.has(t))
732
734
  return !1;
733
- const i = this.edges.findIndex(
734
- (a) => R(a.source, a.target) === t
735
+ const o = this.edges.findIndex(
736
+ (a) => D(a.source, a.target) === t
735
737
  );
736
- if (i === -1)
738
+ if (o === -1)
737
739
  return !1;
738
- const n = this.edgeObjects[i];
739
- return this.sceneManager.remove(n.line), this.edgeFactory.disposeEdge(n), this.edges.splice(i, 1), this.edgeObjects.splice(i, 1), this.edgeKeySet.delete(t), this.highlightedEdgeKey === t && (this.highlightedEdgeKey = null), !0;
740
+ const i = this.edgeObjects[o];
741
+ return this.sceneManager.remove(i.line), this.edgeFactory.disposeEdge(i), this.edges.splice(o, 1), this.edgeObjects.splice(o, 1), this.edgeKeySet.delete(t), this.highlightedEdgeKey === t && (this.highlightedEdgeKey = null), !0;
740
742
  }
741
743
  /**
742
744
  * Highlights an edge
743
745
  */
744
746
  highlightEdge(e, s) {
745
- const t = R(e, s);
747
+ const t = D(e, s);
746
748
  this.highlightedEdgeKey && this.highlightedEdgeKey !== t && this.unhighlightCurrentEdge();
747
- const i = this.edges.findIndex(
748
- (n) => R(n.source, n.target) === t
749
+ const o = this.edges.findIndex(
750
+ (i) => D(i.source, i.target) === t
749
751
  );
750
- i !== -1 && (this.edgeFactory.highlightEdge(this.edgeObjects[i]), this.highlightedEdgeKey = t);
752
+ o !== -1 && (this.edgeFactory.highlightEdge(this.edgeObjects[o]), this.highlightedEdgeKey = t);
751
753
  }
752
754
  /**
753
755
  * Unhighlights the currently highlighted edge
@@ -755,7 +757,7 @@ class ft {
755
757
  unhighlightCurrentEdge() {
756
758
  if (!this.highlightedEdgeKey) return;
757
759
  const e = this.edges.findIndex(
758
- (s) => R(s.source, s.target) === this.highlightedEdgeKey
760
+ (s) => D(s.source, s.target) === this.highlightedEdgeKey
759
761
  );
760
762
  e !== -1 && this.edgeFactory.unhighlightEdge(this.edgeObjects[e]), this.highlightedEdgeKey = null;
761
763
  }
@@ -790,11 +792,11 @@ class ft {
790
792
  */
791
793
  updateEdgePositions() {
792
794
  this.edgeObjects.forEach((e, s) => {
793
- const t = this.edges[s], i = this.nodeManager.getNode(t.source), n = this.nodeManager.getNode(t.target);
794
- i && n && this.edgeFactory.updateEdgePositions(
795
+ const t = this.edges[s], o = this.nodeManager.getNode(t.source), i = this.nodeManager.getNode(t.target);
796
+ o && i && this.edgeFactory.updateEdgePositions(
795
797
  e,
796
- i.position,
797
- n.position
798
+ o.position,
799
+ i.position
798
800
  );
799
801
  });
800
802
  }
@@ -831,21 +833,21 @@ class ft {
831
833
  this.clear();
832
834
  }
833
835
  }
834
- class Oe {
836
+ class Le {
835
837
  constructor(e, s, t = {}) {
836
- r(this, "nodes");
837
- r(this, "edges");
838
+ l(this, "nodes");
839
+ l(this, "edges");
838
840
  // Physics parameters
839
- r(this, "repulsionStrength");
840
- r(this, "attractionStrength");
841
- r(this, "damping");
842
- r(this, "useBarnesHut");
843
- r(this, "barnesHutTheta");
841
+ l(this, "repulsionStrength");
842
+ l(this, "attractionStrength");
843
+ l(this, "damping");
844
+ l(this, "useBarnesHut");
845
+ l(this, "barnesHutTheta");
844
846
  // Simulation state
845
- r(this, "alpha", 1);
846
- r(this, "alphaDecay", 0.0228);
847
- r(this, "alphaMin", 1e-3);
848
- r(this, "alphaTarget", 0);
847
+ l(this, "alpha", 1);
848
+ l(this, "alphaDecay", 0.0228);
849
+ l(this, "alphaMin", 1e-3);
850
+ l(this, "alphaTarget", 0);
849
851
  this.nodes = e, this.edges = s, this.repulsionStrength = t.repulsionStrength ?? 100, this.attractionStrength = t.attractionStrength ?? 0.01, this.damping = t.damping ?? 0.9, this.useBarnesHut = t.useBarnesHut ?? !1, this.barnesHutTheta = t.barnesHutTheta ?? 0.5;
850
852
  }
851
853
  /**
@@ -862,13 +864,13 @@ class Oe {
862
864
  calculateRepulsionBruteForce() {
863
865
  const e = Array.from(this.nodes.values()), s = e.length;
864
866
  for (let t = 0; t < s; t++) {
865
- const i = e[t];
866
- for (let n = t + 1; n < s; n++) {
867
- const a = e[n], l = a.position.x - i.position.x, d = a.position.y - i.position.y, u = a.position.z - i.position.z;
868
- let g = l * l + d * d + u * u;
867
+ const o = e[t];
868
+ for (let i = t + 1; i < s; i++) {
869
+ const a = e[i], r = a.position.x - o.position.x, c = a.position.y - o.position.y, d = a.position.z - o.position.z;
870
+ let g = r * r + c * c + d * d;
869
871
  g < 0.01 && (g = 0.01);
870
- const b = Math.sqrt(g), v = this.repulsionStrength * this.alpha / g, y = l / b * v, f = d / b * v, M = u / b * v;
871
- i.velocity.x -= y / i.mass, i.velocity.y -= f / i.mass, i.velocity.z -= M / i.mass, a.velocity.x += y / a.mass, a.velocity.y += f / a.mass, a.velocity.z += M / a.mass;
872
+ const u = Math.sqrt(g), y = this.repulsionStrength * this.alpha / g, f = r / u * y, x = c / u * y, v = d / u * y;
873
+ o.velocity.x -= f / o.mass, o.velocity.y -= x / o.mass, o.velocity.z -= v / o.mass, a.velocity.x += f / a.mass, a.velocity.y += x / a.mass, a.velocity.z += v / a.mass;
872
874
  }
873
875
  }
874
876
  }
@@ -889,23 +891,23 @@ class Oe {
889
891
  return;
890
892
  }
891
893
  if (s.mass === 0) return;
892
- const t = s.centerOfMass.x - e.position.x, i = s.centerOfMass.y - e.position.y, n = s.centerOfMass.z - e.position.z, a = Math.sqrt(t * t + i * i + n * n);
894
+ const t = s.centerOfMass.x - e.position.x, o = s.centerOfMass.y - e.position.y, i = s.centerOfMass.z - e.position.z, a = Math.sqrt(t * t + o * o + i * i);
893
895
  if (s.size / a < this.barnesHutTheta) {
894
- const l = Math.max(a * a, 0.01), d = this.repulsionStrength * this.alpha * s.mass / l;
895
- e.velocity.x -= t / a * d / e.mass, e.velocity.y -= i / a * d / e.mass, e.velocity.z -= n / a * d / e.mass;
896
+ const r = Math.max(a * a, 0.01), c = this.repulsionStrength * this.alpha * s.mass / r;
897
+ e.velocity.x -= t / a * c / e.mass, e.velocity.y -= o / a * c / e.mass, e.velocity.z -= i / a * c / e.mass;
896
898
  } else
897
- for (const l of s.children)
898
- l && this.calculateForceFromOctree(e, l);
899
+ for (const r of s.children)
900
+ r && this.calculateForceFromOctree(e, r);
899
901
  }
900
902
  /**
901
903
  * Apply repulsion between two nodes
902
904
  */
903
905
  applyRepulsionBetween(e, s) {
904
- const t = s.position.x - e.position.x, i = s.position.y - e.position.y, n = s.position.z - e.position.z;
905
- let a = t * t + i * i + n * n;
906
+ const t = s.position.x - e.position.x, o = s.position.y - e.position.y, i = s.position.z - e.position.z;
907
+ let a = t * t + o * o + i * i;
906
908
  a < 0.01 && (a = 0.01);
907
- const l = Math.sqrt(a), d = this.repulsionStrength * this.alpha / a;
908
- e.velocity.x -= t / l * d / e.mass, e.velocity.y -= i / l * d / e.mass, e.velocity.z -= n / l * d / e.mass;
909
+ const r = Math.sqrt(a), c = this.repulsionStrength * this.alpha / a;
910
+ e.velocity.x -= t / r * c / e.mass, e.velocity.y -= o / r * c / e.mass, e.velocity.z -= i / r * c / e.mass;
909
911
  }
910
912
  /**
911
913
  * Calculate attraction forces along edges
@@ -914,10 +916,10 @@ class Oe {
914
916
  for (const e of this.edges) {
915
917
  const s = this.nodes.get(e.source), t = this.nodes.get(e.target);
916
918
  if (!s || !t) continue;
917
- const i = t.position.x - s.position.x, n = t.position.y - s.position.y, a = t.position.z - s.position.z, l = Math.sqrt(i * i + n * n + a * a);
918
- if (l < 0.01) continue;
919
- const u = (l - 15) * this.attractionStrength * this.alpha, g = i / l * u, b = n / l * u, v = a / l * u;
920
- s.velocity.x += g / s.mass, s.velocity.y += b / s.mass, s.velocity.z += v / s.mass, t.velocity.x -= g / t.mass, t.velocity.y -= b / t.mass, t.velocity.z -= v / t.mass;
919
+ const o = t.position.x - s.position.x, i = t.position.y - s.position.y, a = t.position.z - s.position.z, r = Math.sqrt(o * o + i * i + a * a);
920
+ if (r < 0.01) continue;
921
+ const d = (r - 15) * this.attractionStrength * this.alpha, g = o / r * d, u = i / r * d, y = a / r * d;
922
+ s.velocity.x += g / s.mass, s.velocity.y += u / s.mass, s.velocity.z += y / s.mass, t.velocity.x -= g / t.mass, t.velocity.y -= u / t.mass, t.velocity.z -= y / t.mass;
921
923
  }
922
924
  }
923
925
  /**
@@ -954,7 +956,7 @@ class Oe {
954
956
  }
955
957
  class yt {
956
958
  constructor(e) {
957
- r(this, "root");
959
+ l(this, "root");
958
960
  const s = this.calculateBounds(e);
959
961
  this.root = this.buildTree(e, s);
960
962
  }
@@ -965,13 +967,13 @@ class yt {
965
967
  max: { x: 100, y: 100, z: 100 }
966
968
  };
967
969
  const s = { x: 1 / 0, y: 1 / 0, z: 1 / 0 }, t = { x: -1 / 0, y: -1 / 0, z: -1 / 0 };
968
- for (const n of e)
969
- s.x = Math.min(s.x, n.position.x), s.y = Math.min(s.y, n.position.y), s.z = Math.min(s.z, n.position.z), t.x = Math.max(t.x, n.position.x), t.y = Math.max(t.y, n.position.y), t.z = Math.max(t.z, n.position.z);
970
- const i = 10;
971
- return s.x -= i, s.y -= i, s.z -= i, t.x += i, t.y += i, t.z += i, { min: s, max: t };
970
+ for (const i of e)
971
+ s.x = Math.min(s.x, i.position.x), s.y = Math.min(s.y, i.position.y), s.z = Math.min(s.z, i.position.z), t.x = Math.max(t.x, i.position.x), t.y = Math.max(t.y, i.position.y), t.z = Math.max(t.z, i.position.z);
972
+ const o = 10;
973
+ return s.x -= o, s.y -= o, s.z -= o, t.x += o, t.y += o, t.z += o, { min: s, max: t };
972
974
  }
973
975
  buildTree(e, s, t = 0) {
974
- const i = Math.max(
976
+ const o = Math.max(
975
977
  s.max.x - s.min.x,
976
978
  s.max.y - s.min.y,
977
979
  s.max.z - s.min.z
@@ -979,7 +981,7 @@ class yt {
979
981
  if (e.length === 0)
980
982
  return {
981
983
  bounds: s,
982
- size: i,
984
+ size: o,
983
985
  centerOfMass: { x: 0, y: 0, z: 0 },
984
986
  mass: 0,
985
987
  isLeaf: !0,
@@ -987,71 +989,71 @@ class yt {
987
989
  children: []
988
990
  };
989
991
  if (e.length === 1 || t > 20) {
990
- let y = 0;
991
- const f = { x: 0, y: 0, z: 0 };
992
- for (const M of e)
993
- y += M.mass, f.x += M.position.x * M.mass, f.y += M.position.y * M.mass, f.z += M.position.z * M.mass;
994
- return y > 0 && (f.x /= y, f.y /= y, f.z /= y), {
992
+ let f = 0;
993
+ const x = { x: 0, y: 0, z: 0 };
994
+ for (const v of e)
995
+ f += v.mass, x.x += v.position.x * v.mass, x.y += v.position.y * v.mass, x.z += v.position.z * v.mass;
996
+ return f > 0 && (x.x /= f, x.y /= f, x.z /= f), {
995
997
  bounds: s,
996
- size: i,
997
- centerOfMass: f,
998
- mass: y,
998
+ size: o,
999
+ centerOfMass: x,
1000
+ mass: f,
999
1001
  isLeaf: !0,
1000
1002
  node: e[0],
1001
1003
  children: []
1002
1004
  };
1003
1005
  }
1004
- const n = (s.min.x + s.max.x) / 2, a = (s.min.y + s.max.y) / 2, l = (s.min.z + s.max.z) / 2, d = [[], [], [], [], [], [], [], []];
1005
- for (const y of e) {
1006
- const f = (y.position.x >= n ? 1 : 0) + (y.position.y >= a ? 2 : 0) + (y.position.z >= l ? 4 : 0);
1007
- d[f].push(y);
1008
- }
1009
- const u = [
1010
- { min: { x: s.min.x, y: s.min.y, z: s.min.z }, max: { x: n, y: a, z: l } },
1011
- { min: { x: n, y: s.min.y, z: s.min.z }, max: { x: s.max.x, y: a, z: l } },
1012
- { min: { x: s.min.x, y: a, z: s.min.z }, max: { x: n, y: s.max.y, z: l } },
1013
- { min: { x: n, y: a, z: s.min.z }, max: { x: s.max.x, y: s.max.y, z: l } },
1014
- { min: { x: s.min.x, y: s.min.y, z: l }, max: { x: n, y: a, z: s.max.z } },
1015
- { min: { x: n, y: s.min.y, z: l }, max: { x: s.max.x, y: a, z: s.max.z } },
1016
- { min: { x: s.min.x, y: a, z: l }, max: { x: n, y: s.max.y, z: s.max.z } },
1017
- { min: { x: n, y: a, z: l }, max: { x: s.max.x, y: s.max.y, z: s.max.z } }
1006
+ const i = (s.min.x + s.max.x) / 2, a = (s.min.y + s.max.y) / 2, r = (s.min.z + s.max.z) / 2, c = [[], [], [], [], [], [], [], []];
1007
+ for (const f of e) {
1008
+ const x = (f.position.x >= i ? 1 : 0) + (f.position.y >= a ? 2 : 0) + (f.position.z >= r ? 4 : 0);
1009
+ c[x].push(f);
1010
+ }
1011
+ const d = [
1012
+ { min: { x: s.min.x, y: s.min.y, z: s.min.z }, max: { x: i, y: a, z: r } },
1013
+ { min: { x: i, y: s.min.y, z: s.min.z }, max: { x: s.max.x, y: a, z: r } },
1014
+ { min: { x: s.min.x, y: a, z: s.min.z }, max: { x: i, y: s.max.y, z: r } },
1015
+ { min: { x: i, y: a, z: s.min.z }, max: { x: s.max.x, y: s.max.y, z: r } },
1016
+ { min: { x: s.min.x, y: s.min.y, z: r }, max: { x: i, y: a, z: s.max.z } },
1017
+ { min: { x: i, y: s.min.y, z: r }, max: { x: s.max.x, y: a, z: s.max.z } },
1018
+ { min: { x: s.min.x, y: a, z: r }, max: { x: i, y: s.max.y, z: s.max.z } },
1019
+ { min: { x: i, y: a, z: r }, max: { x: s.max.x, y: s.max.y, z: s.max.z } }
1018
1020
  ], g = [];
1019
- let b = 0;
1020
- const v = { x: 0, y: 0, z: 0 };
1021
- for (let y = 0; y < 8; y++)
1022
- if (d[y].length > 0) {
1023
- const f = this.buildTree(d[y], u[y], t + 1);
1024
- g.push(f), b += f.mass, v.x += f.centerOfMass.x * f.mass, v.y += f.centerOfMass.y * f.mass, v.z += f.centerOfMass.z * f.mass;
1021
+ let u = 0;
1022
+ const y = { x: 0, y: 0, z: 0 };
1023
+ for (let f = 0; f < 8; f++)
1024
+ if (c[f].length > 0) {
1025
+ const x = this.buildTree(c[f], d[f], t + 1);
1026
+ g.push(x), u += x.mass, y.x += x.centerOfMass.x * x.mass, y.y += x.centerOfMass.y * x.mass, y.z += x.centerOfMass.z * x.mass;
1025
1027
  } else
1026
1028
  g.push(null);
1027
- return b > 0 && (v.x /= b, v.y /= b, v.z /= b), {
1029
+ return u > 0 && (y.x /= u, y.y /= u, y.z /= u), {
1028
1030
  bounds: s,
1029
- size: i,
1030
- centerOfMass: v,
1031
- mass: b,
1031
+ size: o,
1032
+ centerOfMass: y,
1033
+ mass: u,
1032
1034
  isLeaf: !1,
1033
1035
  node: null,
1034
1036
  children: g
1035
1037
  };
1036
1038
  }
1037
1039
  }
1038
- class bt {
1039
- constructor(e, s, t, i = 60) {
1040
- r(this, "sceneManager");
1041
- r(this, "animationId", null);
1042
- r(this, "isRunning", !1);
1043
- r(this, "frameInterval");
1044
- r(this, "lastFrameTime", 0);
1045
- r(this, "onSimulate");
1046
- r(this, "onRender");
1040
+ class xt {
1041
+ constructor(e, s, t, o = 60) {
1042
+ l(this, "sceneManager");
1043
+ l(this, "animationId", null);
1044
+ l(this, "isRunning", !1);
1045
+ l(this, "frameInterval");
1046
+ l(this, "lastFrameTime", 0);
1047
+ l(this, "onSimulate");
1048
+ l(this, "onRender");
1047
1049
  // Performance monitoring
1048
- r(this, "frameCount", 0);
1049
- r(this, "fpsStartTime", 0);
1050
- r(this, "currentFPS", 60);
1050
+ l(this, "frameCount", 0);
1051
+ l(this, "fpsStartTime", 0);
1052
+ l(this, "currentFPS", 60);
1051
1053
  /**
1052
1054
  * Main animation loop
1053
1055
  */
1054
- r(this, "animate", () => {
1056
+ l(this, "animate", () => {
1055
1057
  if (!this.isRunning) return;
1056
1058
  this.animationId = requestAnimationFrame(this.animate);
1057
1059
  const e = performance.now(), s = e - this.lastFrameTime;
@@ -1061,7 +1063,7 @@ class bt {
1061
1063
  const t = e - this.fpsStartTime;
1062
1064
  t >= 1e3 && (this.currentFPS = this.frameCount / (t / 1e3), this.frameCount = 0, this.fpsStartTime = e), this.onSimulate(), this.onRender(), this.sceneManager.render();
1063
1065
  });
1064
- this.sceneManager = e, this.onSimulate = s, this.onRender = t, this.frameInterval = 1e3 / i;
1066
+ this.sceneManager = e, this.onSimulate = s, this.onRender = t, this.frameInterval = 1e3 / o;
1065
1067
  }
1066
1068
  /**
1067
1069
  * Starts the animation loop
@@ -1100,12 +1102,12 @@ class bt {
1100
1102
  this.stop();
1101
1103
  }
1102
1104
  }
1103
- class xt {
1105
+ class bt {
1104
1106
  constructor() {
1105
- r(this, "envMap", null);
1106
- r(this, "materialCache", /* @__PURE__ */ new Map());
1107
+ l(this, "envMap", null);
1108
+ l(this, "materialCache", /* @__PURE__ */ new Map());
1107
1109
  // Color palette - white and tangerine
1108
- r(this, "COLORS", [
1110
+ l(this, "COLORS", [
1109
1111
  16777215,
1110
1112
  // White
1111
1113
  16750950,
@@ -1138,10 +1140,10 @@ class xt {
1138
1140
  { colors: ["#2d1a1a", "#1a0a0a", "#0f0505"] }
1139
1141
  // -z
1140
1142
  ];
1141
- for (const i of t) {
1142
- const n = document.createElement("canvas");
1143
- n.width = 256, n.height = 256;
1144
- const a = n.getContext("2d"), l = a.createRadialGradient(
1143
+ for (const o of t) {
1144
+ const i = document.createElement("canvas");
1145
+ i.width = 256, i.height = 256;
1146
+ const a = i.getContext("2d"), r = a.createRadialGradient(
1145
1147
  256 / 2,
1146
1148
  256 / 2,
1147
1149
  0,
@@ -1149,17 +1151,17 @@ class xt {
1149
1151
  256 / 2,
1150
1152
  256 * 0.8
1151
1153
  );
1152
- l.addColorStop(0, i.colors[0]), l.addColorStop(0.5, i.colors[1]), l.addColorStop(1, i.colors[2]), a.fillStyle = l, a.fillRect(0, 0, 256, 256);
1153
- const d = a.getImageData(0, 0, 256, 256);
1154
- for (let u = 0; u < d.data.length; u += 4) {
1154
+ r.addColorStop(0, o.colors[0]), r.addColorStop(0.5, o.colors[1]), r.addColorStop(1, o.colors[2]), a.fillStyle = r, a.fillRect(0, 0, 256, 256);
1155
+ const c = a.getImageData(0, 0, 256, 256);
1156
+ for (let d = 0; d < c.data.length; d += 4) {
1155
1157
  const g = (Math.random() - 0.5) * 5;
1156
- d.data[u] = Math.min(255, Math.max(0, d.data[u] + g)), d.data[u + 1] = Math.min(255, Math.max(0, d.data[u + 1] + g)), d.data[u + 2] = Math.min(255, Math.max(0, d.data[u + 2] + g));
1158
+ c.data[d] = Math.min(255, Math.max(0, c.data[d] + g)), c.data[d + 1] = Math.min(255, Math.max(0, c.data[d + 1] + g)), c.data[d + 2] = Math.min(255, Math.max(0, c.data[d + 2] + g));
1157
1159
  }
1158
- a.putImageData(d, 0, 0), s.push(n);
1160
+ a.putImageData(c, 0, 0), s.push(i);
1159
1161
  }
1160
- this.envMap = new p.CubeTexture(s.map((i) => {
1161
- const n = new Image();
1162
- return n.src = i.toDataURL(), n;
1162
+ this.envMap = new m.CubeTexture(s.map((o) => {
1163
+ const i = new Image();
1164
+ return i.src = o.toDataURL(), i;
1163
1165
  })), this.envMap.needsUpdate = !0;
1164
1166
  }
1165
1167
  /**
@@ -1176,11 +1178,11 @@ class xt {
1176
1178
  const t = "glass-single";
1177
1179
  if (this.materialCache.has(t))
1178
1180
  return this.materialCache.get(t).clone();
1179
- const i = new p.Color(16750950), n = new p.ShaderMaterial({
1181
+ const o = new m.Color(16750950), i = new m.ShaderMaterial({
1180
1182
  uniforms: {
1181
- uColor: { value: i },
1183
+ uColor: { value: o },
1182
1184
  uEnvMap: { value: this.envMap },
1183
- uGlowColor: { value: new p.Color(16777215) },
1185
+ uGlowColor: { value: new m.Color(16777215) },
1184
1186
  uGlowIntensity: { value: 0.8 },
1185
1187
  uReflectivity: { value: 0.4 },
1186
1188
  uFresnelPower: { value: 2.5 }
@@ -1246,17 +1248,17 @@ class xt {
1246
1248
  }
1247
1249
  `,
1248
1250
  transparent: !0,
1249
- side: p.FrontSide,
1251
+ side: m.FrontSide,
1250
1252
  depthWrite: !0,
1251
- blending: p.NormalBlending
1253
+ blending: m.NormalBlending
1252
1254
  });
1253
- return this.materialCache.set(t, n), n.clone();
1255
+ return this.materialCache.set(t, i), i.clone();
1254
1256
  }
1255
1257
  /**
1256
1258
  * Creates material for edges (light color for dark background)
1257
1259
  */
1258
1260
  createEdgeMaterial(e = 6710886, s = 0.4) {
1259
- return new p.LineBasicMaterial({
1261
+ return new m.LineBasicMaterial({
1260
1262
  color: e,
1261
1263
  transparent: !0,
1262
1264
  opacity: s,
@@ -1267,7 +1269,7 @@ class xt {
1267
1269
  * Creates highlighted edge material
1268
1270
  */
1269
1271
  createHighlightedEdgeMaterial() {
1270
- return new p.LineBasicMaterial({
1272
+ return new m.LineBasicMaterial({
1271
1273
  color: 16750950,
1272
1274
  // Tangerine highlight
1273
1275
  transparent: !1,
@@ -1279,13 +1281,13 @@ class xt {
1279
1281
  * Creates a sprite material for labels (light text for dark background)
1280
1282
  */
1281
1283
  createLabelMaterial(e, s = 24) {
1282
- const t = document.createElement("canvas"), i = t.getContext("2d");
1283
- i.font = `600 ${s}px Inter, -apple-system, sans-serif`;
1284
- const a = i.measureText(e).width;
1285
- 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);
1286
- const l = new p.CanvasTexture(t);
1287
- return l.needsUpdate = !0, new p.SpriteMaterial({
1288
- map: l,
1284
+ const t = document.createElement("canvas"), o = t.getContext("2d");
1285
+ o.font = `600 ${s}px Inter, -apple-system, sans-serif`;
1286
+ const a = o.measureText(e).width;
1287
+ t.width = Math.max(128, a + 24), t.height = s + 20, o.clearRect(0, 0, t.width, t.height), o.font = `600 ${s}px Inter, -apple-system, sans-serif`, o.textAlign = "center", o.textBaseline = "middle", o.shadowColor = "rgba(0, 0, 0, 0.8)", o.shadowBlur = 4, o.shadowOffsetX = 1, o.shadowOffsetY = 1, o.fillStyle = "rgba(255, 255, 255, 0.95)", o.fillText(e, t.width / 2, t.height / 2);
1288
+ const r = new m.CanvasTexture(t);
1289
+ return r.needsUpdate = !0, new m.SpriteMaterial({
1290
+ map: r,
1289
1291
  transparent: !0,
1290
1292
  depthTest: !1,
1291
1293
  depthWrite: !1
@@ -1306,10 +1308,10 @@ class xt {
1306
1308
  }
1307
1309
  class vt {
1308
1310
  constructor(e, s = 2, t = [32, 16, 8]) {
1309
- r(this, "materialFactory");
1310
- r(this, "geometryCache", /* @__PURE__ */ new Map());
1311
- r(this, "nodeRadius");
1312
- r(this, "lodSegments");
1311
+ l(this, "materialFactory");
1312
+ l(this, "geometryCache", /* @__PURE__ */ new Map());
1313
+ l(this, "nodeRadius");
1314
+ l(this, "lodSegments");
1313
1315
  this.materialFactory = e, this.nodeRadius = s, this.lodSegments = t, this.initGeometryCache();
1314
1316
  }
1315
1317
  /**
@@ -1320,7 +1322,7 @@ class vt {
1320
1322
  const t = `lod-${s}`;
1321
1323
  this.geometryCache.set(
1322
1324
  t,
1323
- new p.SphereGeometry(this.nodeRadius, e, e)
1325
+ new m.SphereGeometry(this.nodeRadius, e, e)
1324
1326
  );
1325
1327
  });
1326
1328
  }
@@ -1335,21 +1337,21 @@ class vt {
1335
1337
  * Creates a node visual (glass ball + label)
1336
1338
  */
1337
1339
  createNode(e, s = 0) {
1338
- const t = new p.Group();
1340
+ const t = new m.Group();
1339
1341
  t.name = `node-${e.id}`, t.userData = { nodeId: e.id, nodeData: e };
1340
- const i = this.getGeometry(s), n = this.materialFactory.createGlassMaterial(
1342
+ const o = this.getGeometry(s), i = this.materialFactory.createGlassMaterial(
1341
1343
  e.color ?? 4886754
1342
- ), a = new p.Mesh(i, n);
1344
+ ), a = new m.Mesh(o, i);
1343
1345
  a.castShadow = !0, a.receiveShadow = !0, t.add(a);
1344
- const l = this.materialFactory.createLabelMaterial(e.label), d = new p.Sprite(l);
1345
- return d.position.y = this.nodeRadius + 1.5, d.scale.set(4, 1, 1), t.add(d), e.position && t.position.set(
1346
+ const r = this.materialFactory.createLabelMaterial(e.label), c = new m.Sprite(r);
1347
+ return c.position.y = this.nodeRadius + 1.5, c.scale.set(4, 1, 1), t.add(c), e.position && t.position.set(
1346
1348
  e.position.x,
1347
1349
  e.position.y,
1348
1350
  e.position.z
1349
1351
  ), {
1350
1352
  group: t,
1351
1353
  sphere: a,
1352
- label: d,
1354
+ label: c,
1353
1355
  lodLevel: s
1354
1356
  };
1355
1357
  }
@@ -1365,19 +1367,19 @@ class vt {
1365
1367
  * Updates the color of a node
1366
1368
  */
1367
1369
  updateNodeColor(e, s) {
1368
- e.sphere.material instanceof p.Material && e.sphere.material.dispose(), e.sphere.material = this.materialFactory.createGlassMaterial(s);
1370
+ e.sphere.material instanceof m.Material && e.sphere.material.dispose(), e.sphere.material = this.materialFactory.createGlassMaterial(s);
1369
1371
  }
1370
1372
  /**
1371
1373
  * Updates the label of a node
1372
1374
  */
1373
1375
  updateNodeLabel(e, s) {
1374
- e.label.material instanceof p.SpriteMaterial && (e.label.material.map && e.label.material.map.dispose(), e.label.material.dispose()), e.label.material = this.materialFactory.createLabelMaterial(s);
1376
+ e.label.material instanceof m.SpriteMaterial && (e.label.material.map && e.label.material.map.dispose(), e.label.material.dispose()), e.label.material = this.materialFactory.createLabelMaterial(s);
1375
1377
  }
1376
1378
  /**
1377
1379
  * Disposes a node's resources
1378
1380
  */
1379
1381
  disposeNode(e) {
1380
- e.sphere.material instanceof p.Material && e.sphere.material.dispose(), e.label.material instanceof p.SpriteMaterial && (e.label.material.map && e.label.material.map.dispose(), e.label.material.dispose());
1382
+ e.sphere.material instanceof m.Material && e.sphere.material.dispose(), e.label.material instanceof m.SpriteMaterial && (e.label.material.map && e.label.material.map.dispose(), e.label.material.dispose());
1381
1383
  }
1382
1384
  /**
1383
1385
  * Dispose factory resources
@@ -1388,11 +1390,11 @@ class vt {
1388
1390
  }
1389
1391
  class Mt {
1390
1392
  constructor(e, s = 10066329, t = 0.5) {
1391
- r(this, "materialFactory");
1392
- r(this, "edgeColor");
1393
- r(this, "edgeOpacity");
1394
- r(this, "defaultMaterial", null);
1395
- r(this, "highlightMaterial", null);
1393
+ l(this, "materialFactory");
1394
+ l(this, "edgeColor");
1395
+ l(this, "edgeOpacity");
1396
+ l(this, "defaultMaterial", null);
1397
+ l(this, "highlightMaterial", null);
1396
1398
  this.materialFactory = e, this.edgeColor = s, this.edgeOpacity = t;
1397
1399
  }
1398
1400
  /**
@@ -1413,25 +1415,25 @@ class Mt {
1413
1415
  /**
1414
1416
  * Creates an edge line between two positions
1415
1417
  */
1416
- createEdge(e, s, t, i, n) {
1417
- const a = new p.BufferGeometry(), l = new Float32Array([
1418
+ createEdge(e, s, t, o, i) {
1419
+ const a = new m.BufferGeometry(), r = new Float32Array([
1420
+ o.x,
1421
+ o.y,
1422
+ o.z,
1418
1423
  i.x,
1419
1424
  i.y,
1420
- i.z,
1421
- n.x,
1422
- n.y,
1423
- n.z
1425
+ i.z
1424
1426
  ]);
1425
- a.setAttribute("position", new p.BufferAttribute(l, 3));
1426
- const d = this.getDefaultMaterial().clone(), u = new p.Line(a, d);
1427
- return u.name = `edge-${e.source}-${e.target}`, u.userData = {
1427
+ a.setAttribute("position", new m.BufferAttribute(r, 3));
1428
+ const c = this.getDefaultMaterial().clone(), d = new m.Line(a, c);
1429
+ return d.name = `edge-${e.source}-${e.target}`, d.userData = {
1428
1430
  source: e.source,
1429
1431
  target: e.target,
1430
1432
  edge: e,
1431
1433
  sourceNode: s,
1432
1434
  targetNode: t
1433
- }, u.frustumCulled = !0, {
1434
- line: u,
1435
+ }, d.frustumCulled = !0, {
1436
+ line: d,
1435
1437
  source: e.source,
1436
1438
  target: e.target
1437
1439
  };
@@ -1440,26 +1442,26 @@ class Mt {
1440
1442
  * Highlights an edge
1441
1443
  */
1442
1444
  highlightEdge(e) {
1443
- e.line.material instanceof p.Material && e.line.material.dispose(), e.line.material = this.getHighlightMaterial().clone();
1445
+ e.line.material instanceof m.Material && e.line.material.dispose(), e.line.material = this.getHighlightMaterial().clone();
1444
1446
  }
1445
1447
  /**
1446
1448
  * Resets an edge to default appearance
1447
1449
  */
1448
1450
  unhighlightEdge(e) {
1449
- e.line.material instanceof p.Material && e.line.material.dispose(), e.line.material = this.getDefaultMaterial().clone();
1451
+ e.line.material instanceof m.Material && e.line.material.dispose(), e.line.material = this.getDefaultMaterial().clone();
1450
1452
  }
1451
1453
  /**
1452
1454
  * Updates an edge's positions
1453
1455
  */
1454
1456
  updateEdgePositions(e, s, t) {
1455
- const i = e.line.geometry.attributes.position, n = i.array;
1456
- n[0] = s.x, n[1] = s.y, n[2] = s.z, n[3] = t.x, n[4] = t.y, n[5] = t.z, i.needsUpdate = !0, e.line.geometry.computeBoundingSphere();
1457
+ const o = e.line.geometry.attributes.position, i = o.array;
1458
+ i[0] = s.x, i[1] = s.y, i[2] = s.z, i[3] = t.x, i[4] = t.y, i[5] = t.z, o.needsUpdate = !0, e.line.geometry.computeBoundingSphere();
1457
1459
  }
1458
1460
  /**
1459
1461
  * Disposes an edge's resources
1460
1462
  */
1461
1463
  disposeEdge(e) {
1462
- e.line.geometry.dispose(), e.line.material instanceof p.Material && e.line.material.dispose();
1464
+ e.line.geometry.dispose(), e.line.material instanceof m.Material && e.line.material.dispose();
1463
1465
  }
1464
1466
  /**
1465
1467
  * Dispose factory resources
@@ -1470,9 +1472,9 @@ class Mt {
1470
1472
  }
1471
1473
  class wt {
1472
1474
  constructor(e, s = [50, 100, 200], t = !0) {
1473
- r(this, "camera");
1474
- r(this, "lodDistances");
1475
- r(this, "enabled");
1475
+ l(this, "camera");
1476
+ l(this, "lodDistances");
1477
+ l(this, "enabled");
1476
1478
  this.camera = e, this.lodDistances = s, this.enabled = t;
1477
1479
  }
1478
1480
  /**
@@ -1481,15 +1483,15 @@ class wt {
1481
1483
  getLODLevel(e) {
1482
1484
  if (!this.enabled)
1483
1485
  return U.HIGH;
1484
- const s = e.x - this.camera.position.x, t = e.y - this.camera.position.y, i = e.z - this.camera.position.z, n = Math.sqrt(s * s + t * t + i * i);
1485
- return n < this.lodDistances[0] ? U.HIGH : n < this.lodDistances[1] ? U.MEDIUM : U.LOW;
1486
+ const s = e.x - this.camera.position.x, t = e.y - this.camera.position.y, o = e.z - this.camera.position.z, i = Math.sqrt(s * s + t * t + o * o);
1487
+ return i < this.lodDistances[0] ? U.HIGH : i < this.lodDistances[1] ? U.MEDIUM : U.LOW;
1486
1488
  }
1487
1489
  /**
1488
1490
  * Checks if a node should be visible based on distance
1489
1491
  */
1490
1492
  shouldRenderNode(e, s = 500) {
1491
- const t = e.x - this.camera.position.x, i = e.y - this.camera.position.y, n = e.z - this.camera.position.z;
1492
- return Math.sqrt(t * t + i * i + n * n) < s;
1493
+ const t = e.x - this.camera.position.x, o = e.y - this.camera.position.y, i = e.z - this.camera.position.z;
1494
+ return Math.sqrt(t * t + o * o + i * i) < s;
1493
1495
  }
1494
1496
  /**
1495
1497
  * Sets the LOD distances
@@ -1506,11 +1508,11 @@ class wt {
1506
1508
  }
1507
1509
  class Et {
1508
1510
  constructor(e, s = !0) {
1509
- r(this, "camera");
1510
- r(this, "frustum");
1511
- r(this, "projScreenMatrix");
1512
- r(this, "enabled");
1513
- this.camera = e, this.frustum = new p.Frustum(), this.projScreenMatrix = new p.Matrix4(), this.enabled = s;
1511
+ l(this, "camera");
1512
+ l(this, "frustum");
1513
+ l(this, "projScreenMatrix");
1514
+ l(this, "enabled");
1515
+ this.camera = e, this.frustum = new m.Frustum(), this.projScreenMatrix = new m.Matrix4(), this.enabled = s;
1514
1516
  }
1515
1517
  /**
1516
1518
  * Updates the frustum from the camera
@@ -1526,7 +1528,7 @@ class Et {
1526
1528
  */
1527
1529
  isPointVisible(e) {
1528
1530
  if (!this.enabled) return !0;
1529
- const s = new p.Vector3(e.x, e.y, e.z);
1531
+ const s = new m.Vector3(e.x, e.y, e.z);
1530
1532
  return this.frustum.containsPoint(s);
1531
1533
  }
1532
1534
  /**
@@ -1534,8 +1536,8 @@ class Et {
1534
1536
  */
1535
1537
  isSphereVisible(e, s) {
1536
1538
  if (!this.enabled) return !0;
1537
- const t = new p.Sphere(
1538
- new p.Vector3(e.x, e.y, e.z),
1539
+ const t = new m.Sphere(
1540
+ new m.Vector3(e.x, e.y, e.z),
1539
1541
  s
1540
1542
  );
1541
1543
  return this.frustum.intersectsSphere(t);
@@ -1545,15 +1547,15 @@ class Et {
1545
1547
  */
1546
1548
  isLineVisible(e, s) {
1547
1549
  if (!this.enabled) return !0;
1548
- const t = new p.Vector3(e.x, e.y, e.z), i = new p.Vector3(s.x, s.y, s.z);
1549
- if (this.frustum.containsPoint(t) || this.frustum.containsPoint(i))
1550
+ const t = new m.Vector3(e.x, e.y, e.z), o = new m.Vector3(s.x, s.y, s.z);
1551
+ if (this.frustum.containsPoint(t) || this.frustum.containsPoint(o))
1550
1552
  return !0;
1551
- const n = new p.Vector3(
1553
+ const i = new m.Vector3(
1552
1554
  (e.x + s.x) / 2,
1553
1555
  (e.y + s.y) / 2,
1554
1556
  (e.z + s.z) / 2
1555
- ), a = n.distanceTo(t), l = new p.Sphere(n, a);
1556
- return this.frustum.intersectsSphere(l);
1557
+ ), a = i.distanceTo(t), r = new m.Sphere(i, a);
1558
+ return this.frustum.intersectsSphere(r);
1557
1559
  }
1558
1560
  /**
1559
1561
  * Enables/disables frustum culling
@@ -1564,18 +1566,19 @@ class Et {
1564
1566
  }
1565
1567
  class Ct {
1566
1568
  constructor(e, s) {
1567
- r(this, "sceneManager");
1568
- r(this, "raycaster");
1569
- r(this, "mouse");
1570
- r(this, "container");
1571
- r(this, "onNodeClick", null);
1572
- r(this, "onNodeHover", null);
1573
- r(this, "onEdgeHover", null);
1574
- r(this, "hoveredNodeId", null);
1575
- r(this, "hoveredEdgeKey", null);
1576
- r(this, "nodeObjects", []);
1577
- r(this, "edgeObjects", []);
1578
- this.sceneManager = e, this.container = s, this.raycaster = new p.Raycaster(), this.raycaster.params.Line = { threshold: 0.5 }, this.mouse = new p.Vector2(), this.handleClick = this.handleClick.bind(this), this.handleMouseMove = this.handleMouseMove.bind(this), s.addEventListener("click", this.handleClick), s.addEventListener("mousemove", this.handleMouseMove);
1569
+ l(this, "sceneManager");
1570
+ l(this, "raycaster");
1571
+ l(this, "mouse");
1572
+ l(this, "container");
1573
+ l(this, "onNodeClick", null);
1574
+ l(this, "onNodeHover", null);
1575
+ l(this, "onEdgeHover", null);
1576
+ l(this, "onEdgeClick", null);
1577
+ l(this, "hoveredNodeId", null);
1578
+ l(this, "hoveredEdgeKey", null);
1579
+ l(this, "nodeObjects", []);
1580
+ l(this, "edgeObjects", []);
1581
+ this.sceneManager = e, this.container = s, this.raycaster = new m.Raycaster(), this.raycaster.params.Line = { threshold: 0.5 }, this.mouse = new m.Vector2(), this.handleClick = this.handleClick.bind(this), this.handleMouseMove = this.handleMouseMove.bind(this), s.addEventListener("click", this.handleClick), s.addEventListener("mousemove", this.handleMouseMove);
1579
1582
  }
1580
1583
  /**
1581
1584
  * Updates the list of node objects to raycast against
@@ -1607,12 +1610,23 @@ class Ct {
1607
1610
  setEdgeHoverCallback(e) {
1608
1611
  this.onEdgeHover = e;
1609
1612
  }
1613
+ /**
1614
+ * Sets the edge click callback
1615
+ */
1616
+ setEdgeClickCallback(e) {
1617
+ this.onEdgeClick = e;
1618
+ }
1610
1619
  /**
1611
1620
  * Handles click events
1612
1621
  */
1613
1622
  handleClick(e) {
1614
1623
  const s = this.getIntersectedNode(e);
1615
- s && this.onNodeClick && this.onNodeClick(s);
1624
+ if (s && this.onNodeClick) {
1625
+ this.onNodeClick(s);
1626
+ return;
1627
+ }
1628
+ const t = this.getIntersectedEdge(e);
1629
+ t && this.onEdgeClick && this.onEdgeClick(t);
1616
1630
  }
1617
1631
  /**
1618
1632
  * Handles mouse move events for hover detection
@@ -1623,23 +1637,23 @@ class Ct {
1623
1637
  this.hoveredEdgeKey !== null && this.onEdgeHover && (this.hoveredEdgeKey = null, this.onEdgeHover(null)), this.container.style.cursor = "pointer";
1624
1638
  return;
1625
1639
  }
1626
- const i = this.getIntersectedEdge(e), n = i ? `${i.edge.source}-${i.edge.target}` : null;
1627
- n !== this.hoveredEdgeKey && (this.hoveredEdgeKey = n, this.onEdgeHover && this.onEdgeHover(i)), this.container.style.cursor = i ? "pointer" : "default";
1640
+ const o = this.getIntersectedEdge(e), i = o ? `${o.edge.source}-${o.edge.target}` : null;
1641
+ i !== this.hoveredEdgeKey && (this.hoveredEdgeKey = i, this.onEdgeHover && this.onEdgeHover(o)), this.container.style.cursor = o ? "pointer" : "default";
1628
1642
  }
1629
1643
  /**
1630
1644
  * Gets the intersected node from a mouse event
1631
1645
  */
1632
1646
  getIntersectedNode(e) {
1633
- var i;
1647
+ var o;
1634
1648
  const s = this.container.getBoundingClientRect();
1635
1649
  this.mouse.x = (e.clientX - s.left) / s.width * 2 - 1, this.mouse.y = -((e.clientY - s.top) / s.height) * 2 + 1, this.raycaster.setFromCamera(this.mouse, this.sceneManager.camera);
1636
1650
  const t = this.raycaster.intersectObjects(this.nodeObjects, !0);
1637
1651
  if (t.length > 0) {
1638
- let n = t[0].object;
1639
- for (; n; ) {
1640
- if ((i = n.userData) != null && i.nodeData)
1641
- return n.userData.nodeData;
1642
- n = n.parent;
1652
+ let i = t[0].object;
1653
+ for (; i; ) {
1654
+ if ((o = i.userData) != null && o.nodeData)
1655
+ return i.userData.nodeData;
1656
+ i = i.parent;
1643
1657
  }
1644
1658
  }
1645
1659
  return null;
@@ -1652,13 +1666,13 @@ class Ct {
1652
1666
  this.mouse.x = (e.clientX - s.left) / s.width * 2 - 1, this.mouse.y = -((e.clientY - s.top) / s.height) * 2 + 1, this.raycaster.setFromCamera(this.mouse, this.sceneManager.camera);
1653
1667
  const t = this.raycaster.intersectObjects(this.edgeObjects, !1);
1654
1668
  if (t.length > 0) {
1655
- const i = t[0].object, n = i.userData;
1656
- if (n != null && n.edge && (n != null && n.sourceNode) && (n != null && n.targetNode))
1669
+ const o = t[0].object, i = o.userData;
1670
+ if (i != null && i.edge && (i != null && i.sourceNode) && (i != null && i.targetNode))
1657
1671
  return {
1658
- edge: n.edge,
1659
- sourceNode: n.sourceNode,
1660
- targetNode: n.targetNode,
1661
- edgeLine: i
1672
+ edge: i.edge,
1673
+ sourceNode: i.sourceNode,
1674
+ targetNode: i.targetNode,
1675
+ edgeLine: o
1662
1676
  };
1663
1677
  }
1664
1678
  return null;
@@ -1667,14 +1681,14 @@ class Ct {
1667
1681
  * Performs a raycast and returns the intersected node ID
1668
1682
  */
1669
1683
  getIntersectedNodeId(e, s) {
1670
- var n;
1684
+ var i;
1671
1685
  const t = this.container.getBoundingClientRect();
1672
1686
  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);
1673
- const i = this.raycaster.intersectObjects(this.nodeObjects, !0);
1674
- if (i.length > 0) {
1675
- let a = i[0].object;
1687
+ const o = this.raycaster.intersectObjects(this.nodeObjects, !0);
1688
+ if (o.length > 0) {
1689
+ let a = o[0].object;
1676
1690
  for (; a; ) {
1677
- if ((n = a.userData) != null && n.nodeId)
1691
+ if ((i = a.userData) != null && i.nodeId)
1678
1692
  return a.userData.nodeId;
1679
1693
  a = a.parent;
1680
1694
  }
@@ -1690,13 +1704,13 @@ class Ct {
1690
1704
  }
1691
1705
  class Nt {
1692
1706
  constructor(e) {
1693
- r(this, "container");
1694
- r(this, "panel", null);
1695
- r(this, "currentNodeId", null);
1696
- r(this, "visible", !1);
1697
- r(this, "panelTemplate", null);
1698
- r(this, "panelStyles", {});
1699
- r(this, "onExpand", null);
1707
+ l(this, "container");
1708
+ l(this, "panel", null);
1709
+ l(this, "currentNodeId", null);
1710
+ l(this, "visible", !1);
1711
+ l(this, "panelTemplate", null);
1712
+ l(this, "panelStyles", {});
1713
+ l(this, "onExpand", null);
1700
1714
  this.container = e, this.createPanel();
1701
1715
  }
1702
1716
  /**
@@ -1758,11 +1772,11 @@ class Nt {
1758
1772
  this.currentNodeId = e.id;
1759
1773
  let t;
1760
1774
  this.panelTemplate ? t = this.panelTemplate(e, s) : t = this.generateDefaultContent(e, s), this.panel.innerHTML = t;
1761
- const i = this.panel.querySelector('[data-action="expand"]'), n = this.panel.querySelector("[data-depth-select]");
1762
- i && this.onExpand && i.addEventListener("click", () => {
1775
+ const o = this.panel.querySelector('[data-action="expand"]'), i = this.panel.querySelector("[data-depth-select]");
1776
+ o && this.onExpand && o.addEventListener("click", () => {
1763
1777
  if (this.currentNodeId) {
1764
- const l = n ? parseInt(n.value, 10) : 1;
1765
- this.onExpand(this.currentNodeId, l);
1778
+ const r = i ? parseInt(i.value, 10) : 1;
1779
+ this.onExpand(this.currentNodeId, r);
1766
1780
  }
1767
1781
  });
1768
1782
  const a = this.panel.querySelector('[data-action="close"]');
@@ -1920,7 +1934,7 @@ class Nt {
1920
1934
  <div class="neighbors-section">
1921
1935
  <div class="neighbors-title">Connected To</div>
1922
1936
  ${s.slice(0, 5).map(
1923
- (i) => `<span class="neighbor-chip">${this.escapeHtml(i.label)}</span>`
1937
+ (o) => `<span class="neighbor-chip">${this.escapeHtml(o.label)}</span>`
1924
1938
  ).join("")}
1925
1939
  ${s.length > 5 ? `<span class="neighbor-chip">+${s.length - 5} more</span>` : ""}
1926
1940
  </div>
@@ -1975,9 +1989,254 @@ class Nt {
1975
1989
  }
1976
1990
  }
1977
1991
  class St {
1992
+ constructor(e) {
1993
+ l(this, "container");
1994
+ l(this, "panel", null);
1995
+ l(this, "currentEdgeKey", null);
1996
+ l(this, "visible", !1);
1997
+ l(this, "panelTemplate", null);
1998
+ l(this, "onClose", null);
1999
+ l(this, "onNodeClick", null);
2000
+ this.container = e, this.createPanel();
2001
+ }
2002
+ /**
2003
+ * Creates the panel element
2004
+ */
2005
+ createPanel() {
2006
+ this.panel = document.createElement("div"), this.panel.className = "force-graph-edge-panel", this.panel.style.cssText = `
2007
+ position: absolute;
2008
+ right: 20px;
2009
+ top: 50%;
2010
+ transform: translateY(-50%);
2011
+ width: 300px;
2012
+ max-height: 80vh;
2013
+ overflow-y: auto;
2014
+ background: rgba(15, 15, 25, 0.85);
2015
+ backdrop-filter: blur(20px);
2016
+ -webkit-backdrop-filter: blur(20px);
2017
+ border: 1px solid rgba(255, 255, 255, 0.1);
2018
+ border-radius: 16px;
2019
+ padding: 24px;
2020
+ color: white;
2021
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
2022
+ box-shadow:
2023
+ 0 8px 32px rgba(0, 0, 0, 0.4),
2024
+ inset 0 0 0 1px rgba(255, 255, 255, 0.05);
2025
+ z-index: 1000;
2026
+ opacity: 0;
2027
+ pointer-events: none;
2028
+ transition: opacity 0.3s ease, transform 0.3s ease;
2029
+ `, this.container.appendChild(this.panel);
2030
+ }
2031
+ /**
2032
+ * Sets the panel template function
2033
+ */
2034
+ setPanelTemplate(e) {
2035
+ this.panelTemplate = e;
2036
+ }
2037
+ /**
2038
+ * Sets the close callback
2039
+ */
2040
+ setCloseCallback(e) {
2041
+ this.onClose = e;
2042
+ }
2043
+ /**
2044
+ * Sets the node click callback (for navigating to nodes from edge panel)
2045
+ */
2046
+ setNodeClickCallback(e) {
2047
+ this.onNodeClick = e;
2048
+ }
2049
+ /**
2050
+ * Shows the panel with edge/relationship information
2051
+ */
2052
+ show(e, s, t) {
2053
+ if (!this.panel) return;
2054
+ this.currentEdgeKey = `${e.source}-${e.target}`;
2055
+ let o;
2056
+ this.panelTemplate ? o = this.panelTemplate(e, s, t) : o = this.generateDefaultContent(e, s, t), this.panel.innerHTML = o;
2057
+ const i = this.panel.querySelector('[data-action="close"]');
2058
+ i && i.addEventListener("click", () => {
2059
+ this.hide(), this.onClose && this.onClose();
2060
+ });
2061
+ const a = this.panel.querySelector('[data-action="goto-source"]');
2062
+ a && this.onNodeClick && a.addEventListener("click", () => {
2063
+ this.onNodeClick && this.onNodeClick(e.source);
2064
+ });
2065
+ const r = this.panel.querySelector('[data-action="goto-target"]');
2066
+ r && this.onNodeClick && r.addEventListener("click", () => {
2067
+ this.onNodeClick && this.onNodeClick(e.target);
2068
+ }), this.panel.style.opacity = "1", this.panel.style.pointerEvents = "auto", this.panel.style.transform = "translateY(-50%) translateX(0)", this.visible = !0;
2069
+ }
2070
+ /**
2071
+ * Generates default panel content
2072
+ */
2073
+ generateDefaultContent(e, s, t) {
2074
+ const o = s.color ? `#${s.color.toString(16).padStart(6, "0")}` : "#ff9966", i = t.color ? `#${t.color.toString(16).padStart(6, "0")}` : "#ff9966", a = e.relationship || "connected to";
2075
+ return `
2076
+ <style>
2077
+ .force-graph-edge-panel .panel-header {
2078
+ display: flex;
2079
+ align-items: center;
2080
+ justify-content: space-between;
2081
+ margin-bottom: 20px;
2082
+ }
2083
+ .force-graph-edge-panel .panel-title {
2084
+ font-size: 14px;
2085
+ text-transform: uppercase;
2086
+ letter-spacing: 1px;
2087
+ color: rgba(255, 255, 255, 0.6);
2088
+ margin: 0;
2089
+ }
2090
+ .force-graph-edge-panel .relationship-section {
2091
+ background: rgba(255, 255, 255, 0.05);
2092
+ border-radius: 12px;
2093
+ padding: 16px;
2094
+ text-align: center;
2095
+ margin-bottom: 20px;
2096
+ }
2097
+ .force-graph-edge-panel .relationship-label {
2098
+ font-size: 18px;
2099
+ font-weight: 600;
2100
+ color: #a78bfa;
2101
+ letter-spacing: 0.5px;
2102
+ }
2103
+ .force-graph-edge-panel .node-card {
2104
+ background: rgba(255, 255, 255, 0.05);
2105
+ border: 1px solid rgba(255, 255, 255, 0.1);
2106
+ border-radius: 12px;
2107
+ padding: 14px;
2108
+ margin-bottom: 12px;
2109
+ cursor: pointer;
2110
+ transition: all 0.2s ease;
2111
+ }
2112
+ .force-graph-edge-panel .node-card:hover {
2113
+ background: rgba(255, 255, 255, 0.1);
2114
+ border-color: rgba(255, 255, 255, 0.2);
2115
+ transform: translateX(4px);
2116
+ }
2117
+ .force-graph-edge-panel .node-card-header {
2118
+ display: flex;
2119
+ align-items: center;
2120
+ gap: 10px;
2121
+ margin-bottom: 6px;
2122
+ }
2123
+ .force-graph-edge-panel .node-type {
2124
+ font-size: 10px;
2125
+ text-transform: uppercase;
2126
+ letter-spacing: 1px;
2127
+ color: rgba(255, 255, 255, 0.5);
2128
+ }
2129
+ .force-graph-edge-panel .color-dot {
2130
+ width: 10px;
2131
+ height: 10px;
2132
+ border-radius: 50%;
2133
+ flex-shrink: 0;
2134
+ }
2135
+ .force-graph-edge-panel .node-label {
2136
+ font-size: 15px;
2137
+ font-weight: 500;
2138
+ color: rgba(255, 255, 255, 0.95);
2139
+ white-space: nowrap;
2140
+ overflow: hidden;
2141
+ text-overflow: ellipsis;
2142
+ }
2143
+ .force-graph-edge-panel .connection-arrow {
2144
+ text-align: center;
2145
+ color: rgba(255, 255, 255, 0.4);
2146
+ font-size: 18px;
2147
+ margin: 8px 0;
2148
+ }
2149
+ .force-graph-edge-panel .btn-close {
2150
+ width: 100%;
2151
+ padding: 12px 16px;
2152
+ border: none;
2153
+ border-radius: 8px;
2154
+ font-size: 13px;
2155
+ font-weight: 500;
2156
+ cursor: pointer;
2157
+ transition: all 0.2s ease;
2158
+ background: rgba(255, 255, 255, 0.1);
2159
+ color: rgba(255, 255, 255, 0.8);
2160
+ margin-top: 16px;
2161
+ }
2162
+ .force-graph-edge-panel .btn-close:hover {
2163
+ background: rgba(255, 255, 255, 0.15);
2164
+ }
2165
+ .force-graph-edge-panel .hint-text {
2166
+ font-size: 11px;
2167
+ color: rgba(255, 255, 255, 0.4);
2168
+ text-align: center;
2169
+ margin-top: 8px;
2170
+ }
2171
+ </style>
2172
+
2173
+ <div class="panel-header">
2174
+ <h3 class="panel-title">Relationship</h3>
2175
+ </div>
2176
+
2177
+ <div class="relationship-section">
2178
+ <span class="relationship-label">${this.escapeHtml(a)}</span>
2179
+ </div>
2180
+
2181
+ <div class="node-card" data-action="goto-source" title="Click to focus on ${this.escapeHtml(s.label)}">
2182
+ <div class="node-type">Source</div>
2183
+ <div class="node-card-header">
2184
+ <span class="color-dot" style="background: ${o}; box-shadow: 0 0 8px ${o}80;"></span>
2185
+ <span class="node-label">${this.escapeHtml(s.label)}</span>
2186
+ </div>
2187
+ </div>
2188
+
2189
+ <div class="connection-arrow">↓</div>
2190
+
2191
+ <div class="node-card" data-action="goto-target" title="Click to focus on ${this.escapeHtml(t.label)}">
2192
+ <div class="node-type">Target</div>
2193
+ <div class="node-card-header">
2194
+ <span class="color-dot" style="background: ${i}; box-shadow: 0 0 8px ${i}80;"></span>
2195
+ <span class="node-label">${this.escapeHtml(t.label)}</span>
2196
+ </div>
2197
+ </div>
2198
+
2199
+ <p class="hint-text">Click on a node to focus on it</p>
2200
+
2201
+ <button class="btn-close" data-action="close">Close</button>
2202
+ `;
2203
+ }
2204
+ /**
2205
+ * Escapes HTML to prevent XSS
2206
+ */
2207
+ escapeHtml(e) {
2208
+ const s = document.createElement("div");
2209
+ return s.textContent = e, s.innerHTML;
2210
+ }
2211
+ /**
2212
+ * Hides the panel
2213
+ */
2214
+ hide() {
2215
+ this.panel && (this.panel.style.opacity = "0", this.panel.style.pointerEvents = "none", this.panel.style.transform = "translateY(-50%) translateX(20px)", this.visible = !1, this.currentEdgeKey = null);
2216
+ }
2217
+ /**
2218
+ * Checks if the panel is visible
2219
+ */
2220
+ isVisible() {
2221
+ return this.visible;
2222
+ }
2223
+ /**
2224
+ * Gets the currently displayed edge key
2225
+ */
2226
+ getCurrentEdgeKey() {
2227
+ return this.currentEdgeKey;
2228
+ }
2229
+ /**
2230
+ * Dispose the panel
2231
+ */
2232
+ dispose() {
2233
+ this.panel && this.panel.parentNode && this.panel.parentNode.removeChild(this.panel), this.panel = null;
2234
+ }
2235
+ }
2236
+ class zt {
1978
2237
  constructor() {
1979
- r(this, "tooltip", null);
1980
- r(this, "visible", !1);
2238
+ l(this, "tooltip", null);
2239
+ l(this, "visible", !1);
1981
2240
  this.createTooltip(), this.setupMouseTracking();
1982
2241
  }
1983
2242
  /**
@@ -2020,14 +2279,14 @@ class St {
2020
2279
  */
2021
2280
  positionTooltip(e, s) {
2022
2281
  if (!this.tooltip) return;
2023
- const t = this.tooltip.getBoundingClientRect(), i = window.innerWidth, n = window.innerHeight;
2024
- let a = e + 15, l = s + 15;
2025
- a + t.width > i - 10 && (a = e - t.width - 15), l + t.height > n - 10 && (l = s - t.height - 15), a < 10 && (a = 10), l < 10 && (l = 10), this.tooltip.style.left = `${a}px`, this.tooltip.style.top = `${l}px`;
2282
+ const t = this.tooltip.getBoundingClientRect(), o = window.innerWidth, i = window.innerHeight;
2283
+ let a = e + 15, r = s + 15;
2284
+ a + t.width > o - 10 && (a = e - t.width - 15), r + t.height > i - 10 && (r = s - t.height - 15), a < 10 && (a = 10), r < 10 && (r = 10), this.tooltip.style.left = `${a}px`, this.tooltip.style.top = `${r}px`;
2026
2285
  }
2027
2286
  /**
2028
2287
  * Shows the tooltip with edge info
2029
2288
  */
2030
- show(e, s, t, i, n) {
2289
+ show(e, s, t, o, i) {
2031
2290
  if (!this.tooltip) return;
2032
2291
  const a = e.relationship || "connected to";
2033
2292
  this.tooltip.innerHTML = `
@@ -2042,7 +2301,7 @@ class St {
2042
2301
  <span style="font-weight: 600; color: #ff9966;">${this.escapeHtml(t.label)}</span>
2043
2302
  </div>
2044
2303
  </div>
2045
- `, this.positionTooltip(i, n), this.tooltip.style.opacity = "1", this.tooltip.style.transform = "translateY(0)", this.visible = !0;
2304
+ `, this.positionTooltip(o, i), this.tooltip.style.opacity = "1", this.tooltip.style.transform = "translateY(0)", this.visible = !0;
2046
2305
  }
2047
2306
  /**
2048
2307
  * Updates tooltip position (called externally on mouse move)
@@ -2076,16 +2335,16 @@ class St {
2076
2335
  this.tooltip && this.tooltip.parentNode && this.tooltip.parentNode.removeChild(this.tooltip), this.tooltip = null;
2077
2336
  }
2078
2337
  }
2079
- class zt {
2338
+ class kt {
2080
2339
  constructor(e, s) {
2081
- r(this, "container");
2082
- r(this, "searchContainer", null);
2083
- r(this, "searchInput", null);
2084
- r(this, "searchResults", null);
2085
- r(this, "searchTimeout", null);
2086
- r(this, "placeholder");
2087
- r(this, "onSearch");
2088
- r(this, "onResultClick");
2340
+ l(this, "container");
2341
+ l(this, "searchContainer", null);
2342
+ l(this, "searchInput", null);
2343
+ l(this, "searchResults", null);
2344
+ l(this, "searchTimeout", null);
2345
+ l(this, "placeholder");
2346
+ l(this, "onSearch");
2347
+ l(this, "onResultClick");
2089
2348
  this.container = e, this.placeholder = s.placeholder || "Search nodes or relationships...", this.onSearch = s.onSearch, this.onResultClick = s.onResultClick, this.init();
2090
2349
  }
2091
2350
  init() {
@@ -2095,7 +2354,8 @@ class zt {
2095
2354
  this.searchContainer = document.createElement("div"), this.searchContainer.className = "f3d-search-container", Object.assign(this.searchContainer.style, {
2096
2355
  position: "absolute",
2097
2356
  top: "20px",
2098
- left: "20px",
2357
+ left: "175px",
2358
+ // Adjusted to make room for view toggle
2099
2359
  zIndex: "100",
2100
2360
  width: "320px"
2101
2361
  });
@@ -2218,25 +2478,25 @@ class zt {
2218
2478
  this.searchResults.innerHTML = '<div class="f3d-no-results">No results found</div>', this.searchResults.style.display = "block";
2219
2479
  return;
2220
2480
  }
2221
- let i = "";
2222
- s.length > 0 && (i += '<div class="f3d-search-section-header">Nodes</div>', s.slice(0, 10).forEach((n) => {
2223
- const a = n.type || "Node";
2224
- i += `
2225
- <div class="f3d-search-result-item" data-node-id="${this.escapeHtml(n.id)}">
2226
- <div class="f3d-result-label">${this.escapeHtml(n.label)}</div>
2481
+ let o = "";
2482
+ s.length > 0 && (o += '<div class="f3d-search-section-header">Nodes</div>', s.slice(0, 10).forEach((i) => {
2483
+ const a = i.type || "Node";
2484
+ o += `
2485
+ <div class="f3d-search-result-item" data-node-id="${this.escapeHtml(i.id)}">
2486
+ <div class="f3d-result-label">${this.escapeHtml(i.label)}</div>
2227
2487
  <div class="f3d-result-type">${this.escapeHtml(a)}</div>
2228
2488
  </div>
2229
2489
  `;
2230
- }), 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: n, sourceNode: a, targetNode: l }) => {
2231
- i += `
2232
- <div class="f3d-search-result-item" data-node-id="${this.escapeHtml(n.source)}">
2233
- <div class="f3d-result-label">${this.escapeHtml(a.label)} → ${this.escapeHtml(l.label)}</div>
2234
- <div class="f3d-result-relationship">${this.escapeHtml(n.relationship || "connected")}</div>
2490
+ }), s.length > 10 && (o += `<div class="f3d-no-results">+ ${s.length - 10} more nodes</div>`)), t.length > 0 && (o += '<div class="f3d-search-section-header">Relationships</div>', t.slice(0, 5).forEach(({ edge: i, sourceNode: a, targetNode: r }) => {
2491
+ o += `
2492
+ <div class="f3d-search-result-item" data-node-id="${this.escapeHtml(i.source)}">
2493
+ <div class="f3d-result-label">${this.escapeHtml(a.label)} → ${this.escapeHtml(r.label)}</div>
2494
+ <div class="f3d-result-relationship">${this.escapeHtml(i.relationship || "connected")}</div>
2235
2495
  </div>
2236
2496
  `;
2237
- }), 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((n) => {
2238
- n.addEventListener("click", () => {
2239
- const a = n.dataset.nodeId;
2497
+ }), t.length > 5 && (o += `<div class="f3d-no-results">+ ${t.length - 5} more relationships</div>`)), this.searchResults.innerHTML = o, this.searchResults.style.display = "block", this.searchResults.querySelectorAll(".f3d-search-result-item").forEach((i) => {
2498
+ i.addEventListener("click", () => {
2499
+ const a = i.dataset.nodeId;
2240
2500
  a && (this.onResultClick(a), this.searchResults && (this.searchResults.style.display = "none"), this.searchInput && this.searchInput.blur());
2241
2501
  });
2242
2502
  });
@@ -2249,50 +2509,494 @@ class zt {
2249
2509
  this.searchContainer && this.searchContainer.parentNode && this.searchContainer.parentNode.removeChild(this.searchContainer);
2250
2510
  }
2251
2511
  }
2252
- class Ot {
2512
+ class Pt {
2513
+ constructor(e, s) {
2514
+ l(this, "container");
2515
+ l(this, "toggleContainer", null);
2516
+ l(this, "currentMode", "3d");
2517
+ l(this, "onViewChange");
2518
+ this.container = e, this.currentMode = s.initialMode || "3d", this.onViewChange = s.onViewChange, this.init();
2519
+ }
2520
+ init() {
2521
+ this.createToggleUI();
2522
+ }
2523
+ createToggleUI() {
2524
+ this.toggleContainer = document.createElement("div"), this.toggleContainer.className = "f3d-view-toggle", Object.assign(this.toggleContainer.style, {
2525
+ position: "absolute",
2526
+ top: "20px",
2527
+ left: "20px",
2528
+ zIndex: "100",
2529
+ display: "flex",
2530
+ gap: "0",
2531
+ background: "rgba(255, 255, 255, 0.08)",
2532
+ backdropFilter: "blur(20px)",
2533
+ WebkitBackdropFilter: "blur(20px)",
2534
+ border: "1px solid rgba(255, 255, 255, 0.12)",
2535
+ borderRadius: "12px",
2536
+ padding: "5px",
2537
+ boxShadow: "0 4px 20px rgba(0, 0, 0, 0.3)"
2538
+ });
2539
+ const e = this.createButton("2D", "2d"), s = this.createButton("3D", "3d");
2540
+ this.toggleContainer.appendChild(e), this.toggleContainer.appendChild(s), this.container.appendChild(this.toggleContainer), this.updateButtonStates();
2541
+ const t = document.createElement("style");
2542
+ t.textContent = `
2543
+ .f3d-view-btn {
2544
+ padding: 8px 16px;
2545
+ background: transparent;
2546
+ border: none;
2547
+ color: rgba(255, 255, 255, 0.5);
2548
+ font-size: 12px;
2549
+ font-weight: 600;
2550
+ font-family: inherit;
2551
+ letter-spacing: 0.5px;
2552
+ cursor: pointer;
2553
+ transition: all 0.2s ease;
2554
+ border-radius: 8px;
2555
+ min-width: 44px;
2556
+ }
2557
+ .f3d-view-btn:hover {
2558
+ color: rgba(255, 255, 255, 0.8);
2559
+ }
2560
+ .f3d-view-btn.active {
2561
+ background: linear-gradient(135deg, rgba(255, 153, 102, 0.3), rgba(255, 102, 153, 0.2));
2562
+ color: white;
2563
+ box-shadow: 0 0 15px rgba(255, 153, 102, 0.2);
2564
+ }
2565
+ .f3d-view-btn:focus {
2566
+ outline: none;
2567
+ }
2568
+ `, document.head.appendChild(t);
2569
+ }
2570
+ createButton(e, s) {
2571
+ const t = document.createElement("button");
2572
+ return t.className = "f3d-view-btn", t.dataset.mode = s, t.innerHTML = this.getIcon(s) + `<span style="margin-left: 4px;">${e}</span>`, t.style.display = "flex", t.style.alignItems = "center", t.style.justifyContent = "center", t.addEventListener("click", () => {
2573
+ this.currentMode !== s && (this.currentMode = s, this.updateButtonStates(), this.onViewChange(s));
2574
+ }), t;
2575
+ }
2576
+ getIcon(e) {
2577
+ return e === "2d" ? `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
2578
+ <rect x="3" y="3" width="7" height="7"></rect>
2579
+ <rect x="14" y="3" width="7" height="7"></rect>
2580
+ <rect x="14" y="14" width="7" height="7"></rect>
2581
+ <rect x="3" y="14" width="7" height="7"></rect>
2582
+ </svg>` : `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
2583
+ <path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path>
2584
+ <polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline>
2585
+ <line x1="12" y1="22.08" x2="12" y2="12"></line>
2586
+ </svg>`;
2587
+ }
2588
+ updateButtonStates() {
2589
+ if (!this.toggleContainer) return;
2590
+ this.toggleContainer.querySelectorAll(".f3d-view-btn").forEach((s) => {
2591
+ s.dataset.mode === this.currentMode ? s.classList.add("active") : s.classList.remove("active");
2592
+ });
2593
+ }
2594
+ setMode(e) {
2595
+ this.currentMode !== e && (this.currentMode = e, this.updateButtonStates());
2596
+ }
2597
+ getMode() {
2598
+ return this.currentMode;
2599
+ }
2600
+ dispose() {
2601
+ this.toggleContainer && this.toggleContainer.parentNode && this.toggleContainer.parentNode.removeChild(this.toggleContainer);
2602
+ }
2603
+ }
2604
+ const Tt = {
2605
+ backgroundColor: "#0a0a0a",
2606
+ gridColor: "rgba(255, 255, 255, 0.03)",
2607
+ nodeRadius: 24,
2608
+ edgeColor: "rgba(255, 255, 255, 0.15)",
2609
+ edgeOpacity: 0.4,
2610
+ repulsionStrength: 500,
2611
+ // Full repulsion
2612
+ attractionStrength: 1e-3,
2613
+ // Very low attraction
2614
+ damping: 0.85
2615
+ // Fast energy dissipation
2616
+ };
2617
+ class Lt {
2618
+ constructor(e, s = {}) {
2619
+ l(this, "container");
2620
+ l(this, "canvas");
2621
+ l(this, "ctx");
2622
+ l(this, "options");
2623
+ // Data
2624
+ l(this, "nodes", /* @__PURE__ */ new Map());
2625
+ l(this, "edges", []);
2626
+ l(this, "nodeIdToIndex", /* @__PURE__ */ new Map());
2627
+ // Transform state
2628
+ l(this, "transform", { x: 0, y: 0, scale: 1 });
2629
+ // Interaction state
2630
+ l(this, "isDragging", !1);
2631
+ l(this, "isPanning", !1);
2632
+ l(this, "draggedNode", null);
2633
+ l(this, "hoveredNode", null);
2634
+ l(this, "hoveredEdge", null);
2635
+ l(this, "lastMousePos", { x: 0, y: 0 });
2636
+ l(this, "dragStartPos", { x: 0, y: 0 });
2637
+ // Track initial click position
2638
+ l(this, "selectedNode", null);
2639
+ // Animation
2640
+ l(this, "animationId", null);
2641
+ l(this, "isSimulating", !0);
2642
+ // Resize handler
2643
+ l(this, "resizeHandler");
2644
+ this.container = e, this.options = { ...Tt, ...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);
2645
+ const t = this.canvas.getContext("2d");
2646
+ if (!t)
2647
+ throw new Error("Failed to get 2D context");
2648
+ this.ctx = t, this.resizeHandler = this.handleResize.bind(this), window.addEventListener("resize", this.resizeHandler), this.handleResize(), this.transform.x = this.canvas.width / 2, this.transform.y = this.canvas.height / 2, this.setupInteractions(), this.startAnimation();
2649
+ }
2650
+ handleResize() {
2651
+ const e = this.container.getBoundingClientRect(), s = window.devicePixelRatio || 1;
2652
+ this.canvas.width = e.width * s, this.canvas.height = e.height * s, this.ctx.scale(s, s);
2653
+ }
2654
+ setupInteractions() {
2655
+ this.canvas.addEventListener("wheel", (e) => {
2656
+ e.preventDefault();
2657
+ const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left, o = e.clientY - s.top, i = e.deltaY > 0 ? 0.9 : 1.1, a = Math.max(0.1, Math.min(5, this.transform.scale * i)), r = a / this.transform.scale;
2658
+ this.transform.x = t - (t - this.transform.x) * r, this.transform.y = o - (o - this.transform.y) * r, this.transform.scale = a;
2659
+ }), this.canvas.addEventListener("mousedown", (e) => {
2660
+ const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left, o = e.clientY - s.top, i = this.screenToWorld(t, o), a = this.findNodeAt(i.x, i.y);
2661
+ 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 };
2662
+ }), this.canvas.addEventListener("mousemove", (e) => {
2663
+ const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left, o = e.clientY - s.top, i = this.screenToWorld(t, o);
2664
+ if (this.isDragging && this.draggedNode)
2665
+ this.draggedNode.x = i.x, this.draggedNode.y = i.y, this.draggedNode.vx = 0, this.draggedNode.vy = 0;
2666
+ else if (this.isPanning) {
2667
+ const a = e.clientX - this.lastMousePos.x, r = e.clientY - this.lastMousePos.y;
2668
+ this.transform.x += a, this.transform.y += r, this.lastMousePos = { x: e.clientX, y: e.clientY };
2669
+ } else {
2670
+ const a = this.findNodeAt(i.x, i.y);
2671
+ 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) {
2672
+ const r = this.findEdgeAt(i.x, i.y);
2673
+ r !== this.hoveredEdge && (this.hoveredEdge = r, this.canvas.style.cursor = r ? "pointer" : "grab", this.options.onEdgeHover && this.options.onEdgeHover(r ? r.data : null, e));
2674
+ }
2675
+ }
2676
+ }), this.canvas.addEventListener("mouseup", (e) => {
2677
+ const s = Math.abs(e.clientX - this.dragStartPos.x), t = Math.abs(e.clientY - this.dragStartPos.y), o = s < 5 && t < 5;
2678
+ if (this.isDragging && this.draggedNode)
2679
+ o && this.options.onNodeClick && (this.selectedNode = this.draggedNode, this.options.onNodeClick(this.draggedNode.data));
2680
+ else if (o && !this.isPanning) {
2681
+ const i = this.canvas.getBoundingClientRect(), a = this.screenToWorld(e.clientX - i.left, e.clientY - i.top), r = this.findEdgeAt(a.x, a.y);
2682
+ r && this.options.onEdgeClick && this.options.onEdgeClick(r.data);
2683
+ }
2684
+ this.isDragging = !1, this.isPanning = !1, this.draggedNode = null, this.canvas.style.cursor = this.hoveredNode ? "pointer" : "grab";
2685
+ }), this.canvas.addEventListener("mouseleave", () => {
2686
+ this.isDragging = !1, this.isPanning = !1, this.draggedNode = null, this.hoveredNode = null, this.canvas.style.cursor = "grab";
2687
+ });
2688
+ }
2689
+ screenToWorld(e, s) {
2690
+ return {
2691
+ x: (e - this.transform.x) / this.transform.scale,
2692
+ y: (s - this.transform.y) / this.transform.scale
2693
+ };
2694
+ }
2695
+ findNodeAt(e, s) {
2696
+ for (const t of this.nodes.values()) {
2697
+ const o = t.x - e, i = t.y - s;
2698
+ if (Math.sqrt(o * o + i * i) < t.radius)
2699
+ return t;
2700
+ }
2701
+ return null;
2702
+ }
2703
+ findEdgeAt(e, s) {
2704
+ for (const o of this.edges) {
2705
+ const i = this.nodes.get(o.source), a = this.nodes.get(o.target);
2706
+ if (!i || !a) continue;
2707
+ const r = a.x - i.x, c = a.y - i.y, d = r * r + c * c;
2708
+ if (d === 0) continue;
2709
+ const g = Math.max(0, Math.min(1, ((e - i.x) * r + (s - i.y) * c) / d)), u = i.x + g * r, y = i.y + g * c, f = e - u, x = s - y;
2710
+ if (Math.sqrt(f * f + x * x) < 8)
2711
+ return o;
2712
+ }
2713
+ return null;
2714
+ }
2715
+ startAnimation() {
2716
+ const e = () => {
2717
+ this.isSimulating && this.simulate(), this.render(), this.animationId = requestAnimationFrame(e);
2718
+ };
2719
+ e();
2720
+ }
2721
+ simulate() {
2722
+ const e = Array.from(this.nodes.values()), s = e.length;
2723
+ if (s === 0) return;
2724
+ const t = 60, o = 5;
2725
+ let i = 0;
2726
+ for (let r = 0; r < s; r++)
2727
+ for (let c = r + 1; c < s; c++) {
2728
+ const d = e[r], g = e[c];
2729
+ let u = g.x - d.x, y = g.y - d.y, f = Math.sqrt(u * u + y * y);
2730
+ if (f < t * 3) {
2731
+ f < 1 && (f = 1);
2732
+ const x = this.options.repulsionStrength / (f * f), v = u / f * x, M = y / f * x;
2733
+ d.vx -= v, d.vy -= M, g.vx += v, g.vy += M;
2734
+ }
2735
+ }
2736
+ const a = 80;
2737
+ for (const r of this.edges) {
2738
+ const c = this.nodes.get(r.source), d = this.nodes.get(r.target);
2739
+ if (!c || !d) continue;
2740
+ let g = d.x - c.x, u = d.y - c.y, y = Math.sqrt(g * g + u * u);
2741
+ y < 1 && (y = 1);
2742
+ const x = (y - a) * this.options.attractionStrength, v = g / y * x, M = u / y * x;
2743
+ c.vx += v, c.vy += M, d.vx -= v, d.vy -= M;
2744
+ }
2745
+ for (const r of e) {
2746
+ if (this.draggedNode === r) continue;
2747
+ r.vx *= this.options.damping, r.vy *= this.options.damping;
2748
+ const c = Math.sqrt(r.vx * r.vx + r.vy * r.vy);
2749
+ c > o && (r.vx = r.vx / c * o, r.vy = r.vy / c * o), r.x += r.vx, r.y += r.vy, i += r.vx * r.vx + r.vy * r.vy;
2750
+ }
2751
+ i < 0.01 && !this.draggedNode && (this.isSimulating = !1);
2752
+ }
2753
+ render() {
2754
+ const e = this.ctx, s = this.canvas.width / (window.devicePixelRatio || 1), t = this.canvas.height / (window.devicePixelRatio || 1);
2755
+ 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();
2756
+ }
2757
+ renderGrid(e, s) {
2758
+ const t = this.ctx, o = 40 * this.transform.scale, i = 1.5, a = this.transform.x % o, r = this.transform.y % o;
2759
+ t.fillStyle = this.options.gridColor;
2760
+ for (let c = a; c < e; c += o)
2761
+ for (let d = r; d < s; d += o)
2762
+ t.beginPath(), t.arc(c, d, i, 0, Math.PI * 2), t.fill();
2763
+ }
2764
+ renderEdges() {
2765
+ const e = this.ctx;
2766
+ for (const s of this.edges) {
2767
+ const t = this.nodes.get(s.source), o = this.nodes.get(s.target);
2768
+ if (!t || !o) continue;
2769
+ const i = e.createLinearGradient(t.x, t.y, o.x, o.y);
2770
+ i.addColorStop(0, "rgba(255, 153, 102, 0.3)"), i.addColorStop(0.5, "rgba(255, 255, 255, 0.15)"), i.addColorStop(1, "rgba(102, 153, 255, 0.3)"), e.beginPath(), e.moveTo(t.x, t.y), e.lineTo(o.x, o.y), e.strokeStyle = i, e.lineWidth = 1.5, e.stroke();
2771
+ }
2772
+ }
2773
+ renderNodes() {
2774
+ const e = this.ctx;
2775
+ for (const s of this.nodes.values()) {
2776
+ const t = s === this.hoveredNode, o = s === this.selectedNode, i = s.radius * (t ? 1.1 : 1);
2777
+ if (t || o) {
2778
+ const f = e.createRadialGradient(
2779
+ s.x,
2780
+ s.y,
2781
+ i * 0.5,
2782
+ s.x,
2783
+ s.y,
2784
+ i * 2
2785
+ );
2786
+ f.addColorStop(0, "rgba(255, 153, 102, 0.4)"), f.addColorStop(1, "rgba(255, 153, 102, 0)"), e.fillStyle = f, e.beginPath(), e.arc(s.x, s.y, i * 2, 0, Math.PI * 2), e.fill();
2787
+ }
2788
+ const a = e.createRadialGradient(
2789
+ s.x - i * 0.3,
2790
+ s.y - i * 0.3,
2791
+ 0,
2792
+ s.x,
2793
+ s.y,
2794
+ i
2795
+ ), r = s.color >> 16 & 255, c = s.color >> 8 & 255, d = s.color & 255;
2796
+ a.addColorStop(0, `rgba(${Math.min(255, r + 60)}, ${Math.min(255, c + 60)}, ${Math.min(255, d + 60)}, 0.95)`), a.addColorStop(0.7, `rgba(${r}, ${c}, ${d}, 0.9)`), a.addColorStop(1, `rgba(${Math.max(0, r - 40)}, ${Math.max(0, c - 40)}, ${Math.max(0, d - 40)}, 0.85)`), e.beginPath(), e.arc(s.x, s.y, i, 0, Math.PI * 2), e.fillStyle = a, e.fill(), e.strokeStyle = "rgba(255, 255, 255, 0.2)", e.lineWidth = 1, e.stroke(), e.beginPath(), e.arc(s.x - i * 0.25, s.y - i * 0.25, i * 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";
2797
+ const g = i * 1.6;
2798
+ let u = s.label, y = e.measureText(u).width;
2799
+ if (y > g) {
2800
+ for (; y > g && u.length > 3; )
2801
+ u = u.slice(0, -1), y = e.measureText(u + "...").width;
2802
+ u += "...";
2803
+ }
2804
+ e.shadowColor = "rgba(0, 0, 0, 0.5)", e.shadowBlur = 3, e.fillText(u, s.x, s.y), e.shadowBlur = 0;
2805
+ }
2806
+ }
2807
+ /**
2808
+ * Sets the graph data
2809
+ */
2810
+ setData(e) {
2811
+ this.nodes.clear(), this.edges = [], this.nodeIdToIndex.clear(), e.nodes.forEach((s, t) => {
2812
+ const o = s.position || {
2813
+ x: (Math.random() - 0.5) * 300,
2814
+ y: (Math.random() - 0.5) * 300
2815
+ }, i = {
2816
+ id: s.id,
2817
+ label: s.label,
2818
+ x: o.x,
2819
+ y: o.y,
2820
+ vx: 0,
2821
+ vy: 0,
2822
+ color: s.color || 16750950,
2823
+ // Match 3D tangerine color
2824
+ radius: this.options.nodeRadius,
2825
+ data: s
2826
+ };
2827
+ this.nodes.set(s.id, i), this.nodeIdToIndex.set(s.id, t);
2828
+ }), this.edges = e.edges.map((s) => ({
2829
+ source: s.source,
2830
+ target: s.target,
2831
+ relationship: s.relationship,
2832
+ data: s
2833
+ }));
2834
+ }
2835
+ /**
2836
+ * Adds a node
2837
+ */
2838
+ addNode(e) {
2839
+ const s = e.position || {
2840
+ x: (Math.random() - 0.5) * 300,
2841
+ y: (Math.random() - 0.5) * 300
2842
+ }, t = {
2843
+ id: e.id,
2844
+ label: e.label,
2845
+ x: s.x,
2846
+ y: s.y,
2847
+ vx: 0,
2848
+ vy: 0,
2849
+ color: e.color || 16750950,
2850
+ // Match 3D tangerine color
2851
+ radius: this.options.nodeRadius,
2852
+ data: e
2853
+ };
2854
+ this.nodes.set(e.id, t);
2855
+ }
2856
+ /**
2857
+ * Adds an edge
2858
+ */
2859
+ addEdge(e) {
2860
+ this.edges.push({
2861
+ source: e.source,
2862
+ target: e.target,
2863
+ relationship: e.relationship,
2864
+ data: e
2865
+ });
2866
+ }
2867
+ /**
2868
+ * Removes a node
2869
+ */
2870
+ removeNode(e) {
2871
+ this.nodes.delete(e), this.edges = this.edges.filter((s) => s.source !== e && s.target !== e);
2872
+ }
2873
+ /**
2874
+ * Gets a node by ID
2875
+ */
2876
+ getNode(e) {
2877
+ return this.nodes.get(e);
2878
+ }
2879
+ /**
2880
+ * Gets all nodes
2881
+ */
2882
+ getAllNodes() {
2883
+ return Array.from(this.nodes.values()).map((e) => e.data);
2884
+ }
2885
+ /**
2886
+ * Gets node count
2887
+ */
2888
+ getNodeCount() {
2889
+ return this.nodes.size;
2890
+ }
2891
+ /**
2892
+ * Gets edge count
2893
+ */
2894
+ getEdgeCount() {
2895
+ return this.edges.length;
2896
+ }
2897
+ /**
2898
+ * Focuses on a node
2899
+ */
2900
+ focusOnNode(e) {
2901
+ const s = this.nodes.get(e);
2902
+ if (!s) return;
2903
+ const t = this.canvas.width / 2 / (window.devicePixelRatio || 1) - s.x * this.transform.scale, o = this.canvas.height / 2 / (window.devicePixelRatio || 1) - s.y * this.transform.scale, i = this.transform.x, a = this.transform.y, r = 500, c = performance.now(), d = () => {
2904
+ const g = performance.now() - c, u = Math.min(g / r, 1), y = 1 - Math.pow(1 - u, 3);
2905
+ this.transform.x = i + (t - i) * y, this.transform.y = a + (o - a) * y, u < 1 ? requestAnimationFrame(d) : this.selectedNode = s;
2906
+ };
2907
+ d();
2908
+ }
2909
+ /**
2910
+ * Updates node positions from 3D data
2911
+ */
2912
+ syncFrom3D(e) {
2913
+ e.forEach((s, t) => {
2914
+ const o = this.nodes.get(t);
2915
+ o && (o.x = s.position.x * 3, o.y = s.position.y * 3, o.vx = 0, o.vy = 0);
2916
+ }), this.isSimulating = !1;
2917
+ }
2918
+ /**
2919
+ * Gets 2D positions for syncing to 3D
2920
+ */
2921
+ getPositions() {
2922
+ const e = /* @__PURE__ */ new Map();
2923
+ return this.nodes.forEach((s, t) => {
2924
+ e.set(t, { x: s.x, y: s.y });
2925
+ }), e;
2926
+ }
2927
+ /**
2928
+ * Show/hide the canvas
2929
+ */
2930
+ show() {
2931
+ this.canvas.style.display = "block";
2932
+ }
2933
+ hide() {
2934
+ this.canvas.style.display = "none";
2935
+ }
2936
+ /**
2937
+ * Updates physics parameters in real-time
2938
+ */
2939
+ setPhysicsParams(e) {
2940
+ e.repulsionStrength !== void 0 && (this.options.repulsionStrength = e.repulsionStrength), e.attractionStrength !== void 0 && (this.options.attractionStrength = e.attractionStrength), e.damping !== void 0 && (this.options.damping = e.damping), this.isSimulating = !0;
2941
+ }
2942
+ /**
2943
+ * Dispose resources
2944
+ */
2945
+ dispose() {
2946
+ this.animationId && cancelAnimationFrame(this.animationId), window.removeEventListener("resize", this.resizeHandler), this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas);
2947
+ }
2948
+ }
2949
+ class Ft {
2950
+ // Store graph data for view switching
2253
2951
  constructor(e, s = {}) {
2254
2952
  // Options
2255
- r(this, "options");
2256
- r(this, "container");
2953
+ l(this, "options");
2954
+ l(this, "container");
2257
2955
  // Core components
2258
- r(this, "sceneManager");
2259
- r(this, "nodeManager");
2260
- r(this, "edgeManager");
2261
- r(this, "graphEngine");
2262
- r(this, "rendererManager");
2956
+ l(this, "sceneManager");
2957
+ l(this, "nodeManager");
2958
+ l(this, "edgeManager");
2959
+ l(this, "graphEngine");
2960
+ l(this, "rendererManager");
2263
2961
  // Factories
2264
- r(this, "materialFactory");
2265
- r(this, "nodeFactory");
2266
- r(this, "edgeFactory");
2962
+ l(this, "materialFactory");
2963
+ l(this, "nodeFactory");
2964
+ l(this, "edgeFactory");
2267
2965
  // Performance
2268
- r(this, "lodManager");
2269
- r(this, "frustumCuller");
2966
+ l(this, "lodManager");
2967
+ l(this, "frustumCuller");
2270
2968
  // Interaction
2271
- r(this, "raycasterManager");
2272
- r(this, "panelManager");
2273
- r(this, "edgeTooltipManager");
2274
- r(this, "searchManager", null);
2969
+ l(this, "raycasterManager");
2970
+ l(this, "panelManager");
2971
+ l(this, "edgePanelManager");
2972
+ l(this, "edgeTooltipManager");
2973
+ l(this, "searchManager", null);
2974
+ l(this, "viewToggleManager", null);
2975
+ // 2D Renderer
2976
+ l(this, "forceGraph2D", null);
2275
2977
  // Event system
2276
- r(this, "eventCallbacks", /* @__PURE__ */ new Map());
2978
+ l(this, "eventCallbacks", /* @__PURE__ */ new Map());
2277
2979
  // State
2278
- r(this, "initialized", !1);
2279
- r(this, "devControls", null);
2280
- this.options = { ...L, ...s }, this.container = ct(e), this.materialFactory = new xt(), this.nodeFactory = new vt(
2980
+ l(this, "initialized", !1);
2981
+ l(this, "devControls", null);
2982
+ l(this, "viewMode", "3d");
2983
+ l(this, "graphData", null);
2984
+ this.options = { ...R, ...s }, this.container = ct(e), this.materialFactory = new bt(), this.nodeFactory = new vt(
2281
2985
  this.materialFactory,
2282
- this.options.nodeRadius ?? L.nodeRadius,
2283
- this.options.lodSegments ?? L.lodSegments
2986
+ this.options.nodeRadius ?? R.nodeRadius,
2987
+ this.options.lodSegments ?? R.lodSegments
2284
2988
  ), this.edgeFactory = new Mt(
2285
2989
  this.materialFactory,
2286
- this.options.edgeColor ?? L.edgeColor,
2287
- this.options.edgeOpacity ?? L.edgeOpacity
2288
- ), this.sceneManager = new gt(this.container, this.options), this.lodManager = new wt(
2990
+ this.options.edgeColor ?? R.edgeColor,
2991
+ this.options.edgeOpacity ?? R.edgeOpacity
2992
+ ), this.sceneManager = new ut(this.container, this.options), this.lodManager = new wt(
2289
2993
  this.sceneManager.camera,
2290
- this.options.lodDistances ?? L.lodDistances,
2291
- this.options.enableLOD ?? L.enableLOD
2994
+ this.options.lodDistances ?? R.lodDistances,
2995
+ this.options.enableLOD ?? R.enableLOD
2292
2996
  ), this.frustumCuller = new Et(
2293
2997
  this.sceneManager.camera,
2294
- this.options.enableEdgeCulling ?? L.enableEdgeCulling
2295
- ), this.nodeManager = new mt(this.sceneManager, this.nodeFactory), this.edgeManager = new ft(this.sceneManager, this.nodeManager, this.edgeFactory), this.graphEngine = new Oe(
2998
+ this.options.enableEdgeCulling ?? R.enableEdgeCulling
2999
+ ), this.nodeManager = new ft(this.sceneManager, this.nodeFactory), this.edgeManager = new mt(this.sceneManager, this.nodeManager, this.edgeFactory), this.graphEngine = new Le(
2296
3000
  this.nodeManager.getAllNodes(),
2297
3001
  this.edgeManager.getAllEdges(),
2298
3002
  {
@@ -2302,12 +3006,16 @@ class Ot {
2302
3006
  useBarnesHut: this.options.useBarnesHut,
2303
3007
  barnesHutTheta: this.options.barnesHutTheta
2304
3008
  }
2305
- ), this.rendererManager = new bt(
3009
+ ), this.rendererManager = new xt(
2306
3010
  this.sceneManager,
2307
3011
  () => this.onSimulate(),
2308
3012
  () => this.onRender(),
2309
- this.options.targetFPS ?? L.targetFPS
2310
- ), this.raycasterManager = new Ct(this.sceneManager, this.container), this.panelManager = new Nt(this.container), this.edgeTooltipManager = new St(), this.options.showSearch !== !1 && (this.searchManager = new zt(this.container, {
3013
+ this.options.targetFPS ?? R.targetFPS
3014
+ ), 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) => {
3015
+ this.edgePanelManager.hide(), this.focusOnNode(t), setTimeout(() => {
3016
+ this.showNodePanel(t);
3017
+ }, 400);
3018
+ }), this.options.showSearch !== !1 && (this.searchManager = new kt(this.container, {
2311
3019
  placeholder: this.options.searchPlaceholder,
2312
3020
  onSearch: (t) => ({
2313
3021
  nodeResults: this.searchNodes(t),
@@ -2318,6 +3026,11 @@ class Ot {
2318
3026
  this.showNodePanel(t);
2319
3027
  }, 400);
2320
3028
  }
3029
+ })), this.options.showViewToggle !== !1 && (this.viewMode = this.options.initialViewMode || "3d", this.viewToggleManager = new Pt(this.container, {
3030
+ initialMode: this.viewMode,
3031
+ onViewChange: (t) => {
3032
+ this.switchView(t);
3033
+ }
2321
3034
  })), this.setupCallbacks(), this.rendererManager.start(), this.initialized = !0, this.emit("ready");
2322
3035
  }
2323
3036
  /**
@@ -2330,6 +3043,8 @@ class Ot {
2330
3043
  this.expandNode(e, s);
2331
3044
  }), this.options.panelTemplate && this.panelManager.setPanelTemplate(this.options.panelTemplate), this.options.panelStyles && this.panelManager.setPanelStyles(this.options.panelStyles), this.raycasterManager.setEdgeHoverCallback((e) => {
2332
3045
  this.onEdgeHover(e);
3046
+ }), this.raycasterManager.setEdgeClickCallback((e) => {
3047
+ this.onEdgeClick(e);
2333
3048
  });
2334
3049
  }
2335
3050
  /**
@@ -2338,8 +3053,8 @@ class Ot {
2338
3053
  onEdgeHover(e) {
2339
3054
  if (e) {
2340
3055
  this.edgeManager.highlightEdge(e.edge.source, e.edge.target);
2341
- const s = this.container.getBoundingClientRect(), t = s.left + s.width / 2, i = s.top + s.height / 2;
2342
- 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);
3056
+ const s = this.container.getBoundingClientRect(), t = s.left + s.width / 2, o = s.top + s.height / 2;
3057
+ this.edgeTooltipManager.show(e.edge, e.sourceNode, e.targetNode, t, o), this.options.onEdgeHover && this.options.onEdgeHover(e.edge, e.sourceNode, e.targetNode), this.emit("edgeHover", e.edge, e.sourceNode, e.targetNode);
2343
3058
  } else
2344
3059
  this.edgeManager.unhighlightCurrentEdge(), this.edgeTooltipManager.hide(), this.options.onEdgeHover && this.options.onEdgeHover(null, null, null), this.emit("edgeHover", null, null, null);
2345
3060
  }
@@ -2347,9 +3062,16 @@ class Ot {
2347
3062
  * Handles node click
2348
3063
  */
2349
3064
  onNodeClick(e) {
2350
- const t = this.edgeManager.getNeighborIds(e.id).map((i) => this.nodeManager.getNode(i)).filter((i) => i !== void 0);
3065
+ this.edgePanelManager.hide();
3066
+ const t = this.edgeManager.getNeighborIds(e.id).map((o) => this.nodeManager.getNode(o)).filter((o) => o !== void 0);
2351
3067
  this.options.showPanel !== !1 && this.panelManager.show(e, t), this.options.onNodeClick && this.options.onNodeClick(e), this.emit("nodeClick", e);
2352
3068
  }
3069
+ /**
3070
+ * Handles edge click
3071
+ */
3072
+ onEdgeClick(e) {
3073
+ 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);
3074
+ }
2353
3075
  /**
2354
3076
  * Called every simulation step
2355
3077
  */
@@ -2375,13 +3097,13 @@ class Ot {
2375
3097
  * Sets the graph data
2376
3098
  */
2377
3099
  setData(e) {
2378
- if (this.edgeManager.clear(), this.nodeManager.clear(), e.nodes && Array.isArray(e.nodes))
3100
+ if (this.graphData = e, this.edgeManager.clear(), this.nodeManager.clear(), e.nodes && Array.isArray(e.nodes))
2379
3101
  for (const s of e.nodes)
2380
3102
  this.addNode(s);
2381
3103
  if (e.edges && Array.isArray(e.edges))
2382
3104
  for (const s of e.edges)
2383
3105
  this.addEdge(s);
2384
- this.graphEngine = new Oe(
3106
+ this.graphEngine = new Le(
2385
3107
  this.nodeManager.getAllNodes(),
2386
3108
  this.edgeManager.getAllEdges(),
2387
3109
  {
@@ -2391,17 +3113,17 @@ class Ot {
2391
3113
  useBarnesHut: this.options.useBarnesHut,
2392
3114
  barnesHutTheta: this.options.barnesHutTheta
2393
3115
  }
2394
- ), this.graphEngine.restart();
3116
+ ), this.graphEngine.restart(), this.forceGraph2D && this.forceGraph2D.setData(e);
2395
3117
  }
2396
3118
  /**
2397
3119
  * Adds a node to the graph
2398
3120
  * @returns true if added, false if node already exists or invalid
2399
3121
  */
2400
3122
  addNode(e) {
2401
- if (!Re(e))
3123
+ if (!Oe(e))
2402
3124
  return !1;
2403
3125
  const s = this.nodeManager.addNode(e);
2404
- return s && (this.graphEngine.restart(), this.options.onNodeAdd && this.options.onNodeAdd(e), this.emit("nodeAdd", e)), s;
3126
+ return s && (this.graphEngine.restart(), this.forceGraph2D && this.forceGraph2D.addNode(e), this.options.onNodeAdd && this.options.onNodeAdd(e), this.emit("nodeAdd", e)), s;
2405
3127
  }
2406
3128
  /**
2407
3129
  * Removes a node from the graph
@@ -2428,7 +3150,7 @@ class Ot {
2428
3150
  if (!Fe(e))
2429
3151
  return !1;
2430
3152
  const s = this.edgeManager.addEdge(e);
2431
- return s && (this.graphEngine.setEdges(this.edgeManager.getAllEdges()), this.graphEngine.restart(), this.options.onEdgeAdd && this.options.onEdgeAdd(e), this.emit("edgeAdd", e)), s;
3153
+ 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)), s;
2432
3154
  }
2433
3155
  /**
2434
3156
  * Removes an edge from the graph
@@ -2445,20 +3167,20 @@ class Ot {
2445
3167
  * @param fetchFn - Optional fetch function to override the default
2446
3168
  */
2447
3169
  async expandNode(e, s = 1, t) {
2448
- const i = t ?? this.options.onExpand;
2449
- if (!i)
3170
+ const o = t ?? this.options.onExpand;
3171
+ if (!o)
2450
3172
  return console.warn("[ForceGraph3D] No expand callback provided"), !1;
2451
3173
  try {
2452
- const n = await i(e, s);
2453
- if (n.nodes && Array.isArray(n.nodes))
2454
- for (const a of n.nodes)
3174
+ const i = await o(e, s);
3175
+ if (i.nodes && Array.isArray(i.nodes))
3176
+ for (const a of i.nodes)
2455
3177
  this.addNode(a);
2456
- if (n.edges && Array.isArray(n.edges))
2457
- for (const a of n.edges)
3178
+ if (i.edges && Array.isArray(i.edges))
3179
+ for (const a of i.edges)
2458
3180
  this.addEdge(a);
2459
- return this.panelManager.hide(), this.emit("expand", e, n), !0;
2460
- } catch (n) {
2461
- return console.error("[ForceGraph3D] Error expanding node:", n), !1;
3181
+ return this.panelManager.hide(), this.emit("expand", e, i), !0;
3182
+ } catch (i) {
3183
+ return console.error("[ForceGraph3D] Error expanding node:", i), !1;
2462
3184
  }
2463
3185
  }
2464
3186
  /**
@@ -2496,20 +3218,48 @@ class Ot {
2496
3218
  * Focuses the camera on a specific node with smooth animation
2497
3219
  */
2498
3220
  focusOnNode(e, s = 30) {
3221
+ if (this.viewMode === "2d" && this.forceGraph2D) {
3222
+ this.forceGraph2D.focusOnNode(e);
3223
+ return;
3224
+ }
2499
3225
  const t = this.nodeManager.getNode(e);
2500
3226
  if (!t) {
2501
3227
  console.warn(`[ForceGraph3D] Node "${e}" not found`);
2502
3228
  return;
2503
3229
  }
2504
- const i = t.position, n = this.sceneManager.camera, a = this.sceneManager.controls, l = n.position.clone().sub(a.target).normalize(), d = {
2505
- x: i.x + l.x * s,
2506
- y: i.y + l.y * s,
2507
- z: i.z + l.z * s
2508
- }, u = { x: n.position.x, y: n.position.y, z: n.position.z }, g = { x: a.target.x, y: a.target.y, z: a.target.z }, b = 800, v = performance.now(), y = () => {
2509
- const f = performance.now() - v, M = Math.min(f / b, 1), C = 1 - Math.pow(1 - M, 3);
2510
- n.position.x = u.x + (d.x - u.x) * C, n.position.y = u.y + (d.y - u.y) * C, n.position.z = u.z + (d.z - u.z) * C, a.target.x = g.x + (i.x - g.x) * C, a.target.y = g.y + (i.y - g.y) * C, a.target.z = g.z + (i.z - g.z) * C, a.update(), M < 1 && requestAnimationFrame(y);
3230
+ const o = t.position, i = this.sceneManager.camera, a = this.sceneManager.controls, r = i.position.clone().sub(a.target).normalize(), c = {
3231
+ x: o.x + r.x * s,
3232
+ y: o.y + r.y * s,
3233
+ z: o.z + r.z * s
3234
+ }, d = { x: i.position.x, y: i.position.y, z: i.position.z }, g = { x: a.target.x, y: a.target.y, z: a.target.z }, u = 800, y = performance.now(), f = () => {
3235
+ const x = performance.now() - y, v = Math.min(x / u, 1), M = 1 - Math.pow(1 - v, 3);
3236
+ i.position.x = d.x + (c.x - d.x) * M, i.position.y = d.y + (c.y - d.y) * M, i.position.z = d.z + (c.z - d.z) * M, a.target.x = g.x + (o.x - g.x) * M, a.target.y = g.y + (o.y - g.y) * M, a.target.z = g.z + (o.z - g.z) * M, a.update(), v < 1 && requestAnimationFrame(f);
3237
+ };
3238
+ f();
3239
+ }
3240
+ /**
3241
+ * Focuses the camera on an edge (both source and target nodes) with smooth animation
3242
+ * Camera targets the midpoint and zooms out enough to see both nodes
3243
+ */
3244
+ focusOnEdge(e, s, t = 1.5) {
3245
+ const o = this.nodeManager.getNode(e), i = this.nodeManager.getNode(s);
3246
+ if (!o || !i) {
3247
+ console.warn(`[ForceGraph3D] Could not find nodes for edge "${e}" -> "${s}"`);
3248
+ return;
3249
+ }
3250
+ const a = this.sceneManager.camera, r = this.sceneManager.controls, c = {
3251
+ x: (o.position.x + i.position.x) / 2,
3252
+ y: (o.position.y + i.position.y) / 2,
3253
+ z: (o.position.z + i.position.z) / 2
3254
+ }, d = i.position.x - o.position.x, g = i.position.y - o.position.y, u = i.position.z - o.position.z, y = Math.sqrt(d * d + g * g + u * u), f = Math.max(y * t, 40), x = a.position.clone().sub(r.target).normalize(), v = {
3255
+ x: c.x + x.x * f,
3256
+ y: c.y + x.y * f,
3257
+ z: c.z + x.z * f
3258
+ }, 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, T = performance.now(), Y = () => {
3259
+ const P = performance.now() - T, H = Math.min(P / O, 1), E = 1 - Math.pow(1 - H, 3);
3260
+ a.position.x = M.x + (v.x - M.x) * E, a.position.y = M.y + (v.y - M.y) * E, a.position.z = M.z + (v.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(), H < 1 && requestAnimationFrame(Y);
2511
3261
  };
2512
- y();
3262
+ Y();
2513
3263
  }
2514
3264
  /**
2515
3265
  * Shows the info panel for a specific node
@@ -2530,28 +3280,28 @@ class Ot {
2530
3280
  searchNodes(e) {
2531
3281
  if (!e || e.trim() === "")
2532
3282
  return [];
2533
- const s = e.toLowerCase().trim(), t = this.nodeManager.getAllNodes(), i = [];
2534
- return t.forEach((n) => {
2535
- var u, g, b;
2536
- const a = (u = n.label) == null ? void 0 : u.toLowerCase().includes(s), l = (g = n.id) == null ? void 0 : g.toLowerCase().includes(s), d = (b = n.type) == null ? void 0 : b.toLowerCase().includes(s);
2537
- (a || l || d) && i.push(n);
2538
- }), i;
3283
+ const s = e.toLowerCase().trim(), t = this.nodeManager.getAllNodes(), o = [];
3284
+ return t.forEach((i) => {
3285
+ var d, g, u;
3286
+ const a = (d = i.label) == null ? void 0 : d.toLowerCase().includes(s), r = (g = i.id) == null ? void 0 : g.toLowerCase().includes(s), c = (u = i.type) == null ? void 0 : u.toLowerCase().includes(s);
3287
+ (a || r || c) && o.push(i);
3288
+ }), o;
2539
3289
  }
2540
3290
  /**
2541
3291
  * Searches edges by relationship (case-insensitive)
2542
3292
  * @returns Array of matching edges with source/target node info
2543
3293
  */
2544
3294
  searchEdges(e) {
2545
- var n;
3295
+ var i;
2546
3296
  if (!e || e.trim() === "")
2547
3297
  return [];
2548
- const s = e.toLowerCase().trim(), t = this.edgeManager.getAllEdges(), i = [];
3298
+ const s = e.toLowerCase().trim(), t = this.edgeManager.getAllEdges(), o = [];
2549
3299
  for (const a of t)
2550
- if ((n = a.relationship) == null ? void 0 : n.toLowerCase().includes(s)) {
2551
- const d = this.nodeManager.getNode(a.source), u = this.nodeManager.getNode(a.target);
2552
- d && u && i.push({ edge: a, sourceNode: d, targetNode: u });
3300
+ if ((i = a.relationship) == null ? void 0 : i.toLowerCase().includes(s)) {
3301
+ const c = this.nodeManager.getNode(a.source), d = this.nodeManager.getNode(a.target);
3302
+ c && d && o.push({ edge: a, sourceNode: c, targetNode: d });
2553
3303
  }
2554
- return i;
3304
+ return o;
2555
3305
  }
2556
3306
  /**
2557
3307
  * Gets all nodes as an array
@@ -2572,6 +3322,44 @@ class Ot {
2572
3322
  isInitialized() {
2573
3323
  return this.initialized;
2574
3324
  }
3325
+ /**
3326
+ * Gets the current view mode
3327
+ */
3328
+ getViewMode() {
3329
+ return this.viewMode;
3330
+ }
3331
+ /**
3332
+ * Switches between 2D and 3D view modes
3333
+ */
3334
+ switchView(e) {
3335
+ 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 Lt(this.container, {
3336
+ backgroundColor: "#0a0a0a",
3337
+ nodeRadius: 24,
3338
+ onNodeClick: (s) => {
3339
+ this.onNodeClick(s);
3340
+ },
3341
+ onNodeHover: (s) => {
3342
+ this.options.onNodeHover && this.options.onNodeHover(s);
3343
+ },
3344
+ onEdgeHover: (s, t) => {
3345
+ if (s && t) {
3346
+ const o = this.nodeManager.getNode(s.source), i = this.nodeManager.getNode(s.target);
3347
+ o && i && this.edgeTooltipManager.show(
3348
+ s,
3349
+ o,
3350
+ i,
3351
+ t.clientX,
3352
+ t.clientY
3353
+ );
3354
+ } else
3355
+ this.edgeTooltipManager.hide();
3356
+ },
3357
+ onEdgeClick: (s) => {
3358
+ const t = this.nodeManager.getNode(s.source), o = this.nodeManager.getNode(s.target);
3359
+ t && o && this.edgePanelManager.show(s, t, o);
3360
+ }
3361
+ }), 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));
3362
+ }
2575
3363
  /**
2576
3364
  * Registers an event listener
2577
3365
  */
@@ -2583,13 +3371,13 @@ class Ot {
2583
3371
  */
2584
3372
  emit(e, ...s) {
2585
3373
  const t = this.eventCallbacks.get(e);
2586
- t && t.forEach((i) => i(...s));
3374
+ t && t.forEach((o) => o(...s));
2587
3375
  }
2588
3376
  /**
2589
- * Sets physics parameters
3377
+ * Sets physics parameters for both 3D and 2D views
2590
3378
  */
2591
3379
  setPhysicsParams(e) {
2592
- this.graphEngine.setPhysicsParams(e), this.graphEngine.restart();
3380
+ this.graphEngine.setPhysicsParams(e), this.graphEngine.restart(), this.forceGraph2D && this.forceGraph2D.setPhysicsParams(e);
2593
3381
  }
2594
3382
  /**
2595
3383
  * Creates dev mode controls (only in development)
@@ -2660,27 +3448,27 @@ class Ot {
2660
3448
  `, this.container.appendChild(this.devControls);
2661
3449
  const e = this.devControls.querySelector("#dev-repulsion"), s = this.devControls.querySelector("#dev-attraction"), t = this.devControls.querySelector("#dev-damping");
2662
3450
  e == null || e.addEventListener("input", () => {
2663
- const i = parseFloat(e.value);
2664
- this.setPhysicsParams({ repulsionStrength: i }), this.devControls.querySelector("#dev-repulsion-val").textContent = i.toString();
3451
+ const o = parseFloat(e.value);
3452
+ this.setPhysicsParams({ repulsionStrength: o }), this.devControls.querySelector("#dev-repulsion-val").textContent = o.toString();
2665
3453
  }), s == null || s.addEventListener("input", () => {
2666
- const i = parseFloat(s.value) / 1e3;
2667
- this.setPhysicsParams({ attractionStrength: i }), this.devControls.querySelector("#dev-attraction-val").textContent = i.toFixed(3);
3454
+ const o = parseFloat(s.value) / 1e3;
3455
+ this.setPhysicsParams({ attractionStrength: o }), this.devControls.querySelector("#dev-attraction-val").textContent = o.toFixed(3);
2668
3456
  }), t == null || t.addEventListener("input", () => {
2669
- const i = parseFloat(t.value) / 100;
2670
- this.setPhysicsParams({ damping: i }), this.devControls.querySelector("#dev-damping-val").textContent = i.toFixed(2);
3457
+ const o = parseFloat(t.value) / 100;
3458
+ this.setPhysicsParams({ damping: o }), this.devControls.querySelector("#dev-damping-val").textContent = o.toFixed(2);
2671
3459
  }), setInterval(() => {
2672
- const i = this.devControls.querySelector("#dev-node-count"), n = this.devControls.querySelector("#dev-edge-count"), a = this.devControls.querySelector("#dev-fps");
2673
- i && (i.textContent = this.getNodeCount().toString()), n && (n.textContent = this.getEdgeCount().toString()), a && (a.textContent = this.rendererManager.getFPS().toString());
3460
+ const o = this.devControls.querySelector("#dev-node-count"), i = this.devControls.querySelector("#dev-edge-count"), a = this.devControls.querySelector("#dev-fps");
3461
+ o && (o.textContent = this.getNodeCount().toString()), i && (i.textContent = this.getEdgeCount().toString()), a && (a.textContent = this.rendererManager.getFPS().toString());
2674
3462
  }, 500);
2675
3463
  }
2676
3464
  /**
2677
3465
  * Destroys the graph and releases all resources
2678
3466
  */
2679
3467
  destroy() {
2680
- this.rendererManager.dispose(), this.panelManager.dispose(), this.raycasterManager.dispose(), this.edgeTooltipManager.dispose(), this.searchManager && this.searchManager.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;
3468
+ this.rendererManager.dispose(), this.panelManager.dispose(), this.raycasterManager.dispose(), this.edgeTooltipManager.dispose(), this.searchManager && this.searchManager.dispose(), this.viewToggleManager && this.viewToggleManager.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;
2681
3469
  }
2682
3470
  }
2683
- const ke = [
3471
+ const Ie = [
2684
3472
  "Alpha",
2685
3473
  "Beta",
2686
3474
  "Gamma",
@@ -2711,7 +3499,7 @@ const ke = [
2711
3499
  "Link",
2712
3500
  "Point",
2713
3501
  "Vertex"
2714
- ], Q = [
3502
+ ], J = [
2715
3503
  "connects to",
2716
3504
  "links with",
2717
3505
  "relates to",
@@ -2722,7 +3510,7 @@ const ke = [
2722
3510
  "partners with",
2723
3511
  "collaborates with",
2724
3512
  "supports"
2725
- ], Ie = [
3513
+ ], Re = [
2726
3514
  16777215,
2727
3515
  // White
2728
3516
  16750950,
@@ -2734,14 +3522,14 @@ const ke = [
2734
3522
  16746564
2735
3523
  // Darker tangerine
2736
3524
  ];
2737
- function kt(c = 30) {
3525
+ function Ht(h = 30) {
2738
3526
  const e = [], s = [];
2739
- for (let i = 0; i < c; i++) {
2740
- const n = i < ke.length ? ke[i] : `Node ${i + 1}`;
3527
+ for (let o = 0; o < h; o++) {
3528
+ const i = o < Ie.length ? Ie[o] : `Node ${o + 1}`;
2741
3529
  e.push({
2742
- id: `node-${i}`,
2743
- label: n,
2744
- color: Ie[i % Ie.length],
3530
+ id: `node-${o}`,
3531
+ label: i,
3532
+ color: Re[o % Re.length],
2745
3533
  position: {
2746
3534
  x: (Math.random() - 0.5) * 60,
2747
3535
  y: (Math.random() - 0.5) * 60,
@@ -2749,43 +3537,43 @@ function kt(c = 30) {
2749
3537
  }
2750
3538
  });
2751
3539
  }
2752
- for (let i = 1; i < c; i++) {
2753
- const n = Math.floor(Math.random() * i);
3540
+ for (let o = 1; o < h; o++) {
3541
+ const i = Math.floor(Math.random() * o);
2754
3542
  s.push({
2755
- source: `node-${i}`,
2756
- target: `node-${n}`,
2757
- relationship: Q[Math.floor(Math.random() * Q.length)]
3543
+ source: `node-${o}`,
3544
+ target: `node-${i}`,
3545
+ relationship: J[Math.floor(Math.random() * J.length)]
2758
3546
  });
2759
3547
  }
2760
- const t = Math.floor(c * 0.5);
2761
- for (let i = 0; i < t; i++) {
2762
- const n = Math.floor(Math.random() * c);
2763
- let a = Math.floor(Math.random() * c);
2764
- n === a && (a = (a + 1) % c);
2765
- const l = `node-${n}`, d = `node-${a}`;
3548
+ const t = Math.floor(h * 0.5);
3549
+ for (let o = 0; o < t; o++) {
3550
+ const i = Math.floor(Math.random() * h);
3551
+ let a = Math.floor(Math.random() * h);
3552
+ i === a && (a = (a + 1) % h);
3553
+ const r = `node-${i}`, c = `node-${a}`;
2766
3554
  s.some(
2767
- (g) => g.source === l && g.target === d || g.source === d && g.target === l
3555
+ (g) => g.source === r && g.target === c || g.source === c && g.target === r
2768
3556
  ) || s.push({
2769
- source: l,
2770
- target: d,
2771
- relationship: Q[Math.floor(Math.random() * Q.length)]
3557
+ source: r,
3558
+ target: c,
3559
+ relationship: J[Math.floor(Math.random() * J.length)]
2772
3560
  });
2773
3561
  }
2774
3562
  return { nodes: e, edges: s };
2775
3563
  }
2776
- function It(c = 1e3) {
2777
- const e = [], s = [], t = Math.ceil(c / 50), i = [];
2778
- for (let n = 0; n < t; n++)
2779
- i.push({
3564
+ function Dt(h = 1e3) {
3565
+ const e = [], s = [], t = Math.ceil(h / 50), o = [];
3566
+ for (let i = 0; i < t; i++)
3567
+ o.push({
2780
3568
  x: (Math.random() - 0.5) * 200,
2781
3569
  y: (Math.random() - 0.5) * 200,
2782
3570
  z: (Math.random() - 0.5) * 200
2783
3571
  });
2784
- for (let n = 0; n < c; n++) {
2785
- const a = i[n % t];
3572
+ for (let i = 0; i < h; i++) {
3573
+ const a = o[i % t];
2786
3574
  e.push({
2787
- id: `node-${n}`,
2788
- label: `N${n}`,
3575
+ id: `node-${i}`,
3576
+ label: `N${i}`,
2789
3577
  position: {
2790
3578
  x: a.x + (Math.random() - 0.5) * 40,
2791
3579
  y: a.y + (Math.random() - 0.5) * 40,
@@ -2793,32 +3581,32 @@ function It(c = 1e3) {
2793
3581
  }
2794
3582
  });
2795
3583
  }
2796
- for (let n = 1; n < c; n++) {
2797
- const a = Math.floor(n / 50) * 50, l = a === 0 ? Math.floor(Math.random() * n) : a + Math.floor(Math.random() * Math.min(n - a, 50));
3584
+ for (let i = 1; i < h; i++) {
3585
+ const a = Math.floor(i / 50) * 50, r = a === 0 ? Math.floor(Math.random() * i) : a + Math.floor(Math.random() * Math.min(i - a, 50));
2798
3586
  s.push({
2799
- source: `node-${n}`,
2800
- target: `node-${Math.min(l, n - 1)}`,
3587
+ source: `node-${i}`,
3588
+ target: `node-${Math.min(r, i - 1)}`,
2801
3589
  relationship: "links to"
2802
3590
  });
2803
3591
  }
2804
- for (let n = 1; n < t; n++) {
2805
- const a = n * 50, l = (n - 1) * 50 + Math.floor(Math.random() * 50);
3592
+ for (let i = 1; i < t; i++) {
3593
+ const a = i * 50, r = (i - 1) * 50 + Math.floor(Math.random() * 50);
2806
3594
  s.push({
2807
3595
  source: `node-${a}`,
2808
- target: `node-${l}`,
3596
+ target: `node-${r}`,
2809
3597
  relationship: "bridges to"
2810
3598
  });
2811
3599
  }
2812
3600
  return { nodes: e, edges: s };
2813
3601
  }
2814
3602
  export {
2815
- L as DEFAULT_OPTIONS,
2816
- Ot as ForceGraph3D,
3603
+ R as DEFAULT_OPTIONS,
3604
+ Ft as ForceGraph3D,
2817
3605
  U as LODLevel,
2818
- R as createEdgeKey,
2819
- It as generateLargeSampleData,
2820
- kt as generateSampleData,
3606
+ D as createEdgeKey,
3607
+ Dt as generateLargeSampleData,
3608
+ Ht as generateSampleData,
2821
3609
  Fe as validateEdgeData,
2822
- Re as validateNodeData
3610
+ Oe as validateNodeData
2823
3611
  };
2824
3612
  //# sourceMappingURL=force-3d-graph.js.map