force-3d-graph 1.0.0 → 1.0.2

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
- var ot = Object.defineProperty;
2
- var nt = (c, e, o) => e in c ? ot(c, e, { enumerable: !0, configurable: !0, writable: !0, value: o }) : c[e] = o;
3
- var r = (c, e, o) => nt(c, typeof e != "symbol" ? e + "" : e, o);
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
4
  import * as p from "three";
5
- import { EventDispatcher as it, Vector3 as N, MOUSE as H, TOUCH as K, Spherical as Ne, Quaternion as ze, Vector2 as S, Ray as st, Plane as at, MathUtils as rt } from "three";
6
- const O = {
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 = {
7
7
  backgroundColor: 657930,
8
8
  cameraPosition: { x: 0, y: 0, z: 80 },
9
9
  cameraFov: 75,
@@ -23,10 +23,12 @@ const O = {
23
23
  edgeOpacity: 0.4,
24
24
  enableEdgeCulling: !0,
25
25
  showPanel: !0,
26
+ showSearch: !0,
27
+ searchPlaceholder: "Search nodes or relationships...",
26
28
  targetFPS: 60,
27
29
  maxVisibleNodes: 1e4
28
30
  };
29
- var _ = /* @__PURE__ */ ((c) => (c[c.HIGH = 0] = "HIGH", c[c.MEDIUM = 1] = "MEDIUM", c[c.LOW = 2] = "LOW", c))(_ || {});
31
+ var U = /* @__PURE__ */ ((c) => (c[c.HIGH = 0] = "HIGH", c[c.MEDIUM = 1] = "MEDIUM", c[c.LOW = 2] = "LOW", c))(U || {});
30
32
  function lt() {
31
33
  const c = document.createElement("div");
32
34
  return c.id = "force-graph-3d-container", c.style.cssText = `
@@ -41,20 +43,20 @@ function lt() {
41
43
  function ct(c) {
42
44
  return c && c instanceof HTMLElement ? c : (console.warn("[ForceGraph3D] No container provided, creating one automatically"), lt());
43
45
  }
44
- function Se(c) {
46
+ function ze(c) {
45
47
  const e = c.getBoundingClientRect();
46
48
  return {
47
49
  width: e.width || window.innerWidth,
48
50
  height: e.height || window.innerHeight
49
51
  };
50
52
  }
51
- function Ie(c) {
53
+ function Re(c) {
52
54
  if (!c || typeof c != "object")
53
55
  return console.warn("[ForceGraph3D] Invalid node: must be an object"), !1;
54
56
  const e = c;
55
57
  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;
56
58
  }
57
- function Re(c) {
59
+ function Fe(c) {
58
60
  if (!c || typeof c != "object")
59
61
  return console.warn("[ForceGraph3D] Invalid edge: must be an object"), !1;
60
62
  const e = c;
@@ -68,56 +70,56 @@ function dt(c) {
68
70
  const e = c;
69
71
  return typeof e.x == "number" && typeof e.y == "number" && typeof e.z == "number";
70
72
  }
71
- function I(c, e) {
73
+ function R(c, e) {
72
74
  return c === e ? `${c}-${e}` : c < e ? `${c}-${e}` : `${e}-${c}`;
73
75
  }
74
- const Pe = { type: "change" }, ae = { type: "start" }, Te = { type: "end" }, Z = new st(), Oe = new at(), pt = Math.cos(70 * rt.DEG2RAD);
75
- class gt extends it {
76
- constructor(e, o) {
77
- super(), this.object = e, this.domElement = o, 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: H.ROTATE, MIDDLE: H.DOLLY, RIGHT: H.PAN }, this.touches = { ONE: K.ROTATE, TWO: K.DOLLY_PAN }, this.target0 = this.target.clone(), this.position0 = this.object.position.clone(), this.zoom0 = this.object.zoom, this._domElementKeyEvents = null, this.getPolarAngle = function() {
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
+ 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() {
78
80
  return l.phi;
79
81
  }, this.getAzimuthalAngle = function() {
80
82
  return l.theta;
81
83
  }, this.getDistance = function() {
82
84
  return this.object.position.distanceTo(this.target);
83
- }, this.listenToKeyEvents = function(s) {
84
- s.addEventListener("keydown", ie), this._domElementKeyEvents = s;
85
+ }, this.listenToKeyEvents = function(o) {
86
+ o.addEventListener("keydown", ne), this._domElementKeyEvents = o;
85
87
  }, this.stopListenToKeyEvents = function() {
86
- this._domElementKeyEvents.removeEventListener("keydown", ie), this._domElementKeyEvents = null;
88
+ this._domElementKeyEvents.removeEventListener("keydown", ne), this._domElementKeyEvents = null;
87
89
  }, this.saveState = function() {
88
90
  t.target0.copy(t.target), t.position0.copy(t.object.position), t.zoom0 = t.object.zoom;
89
91
  }, this.reset = function() {
90
- t.target.copy(t.target0), t.object.position.copy(t.position0), t.object.zoom = t.zoom0, t.object.updateProjectionMatrix(), t.dispatchEvent(Pe), t.update(), i = n.NONE;
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;
91
93
  }, this.update = function() {
92
- const s = new N(), h = new ze().setFromUnitVectors(e.up, new N(0, 1, 0)), m = h.clone().invert(), b = new N(), E = new ze(), F = new N(), z = 2 * Math.PI;
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;
93
95
  return function(tt = null) {
94
96
  const Ce = t.object.position;
95
- s.copy(Ce).sub(t.target), s.applyQuaternion(h), l.setFromVector3(s), t.autoRotate && i === n.NONE && G(Ae(tt)), t.enableDamping ? (l.theta += d.theta * t.dampingFactor, l.phi += d.phi * t.dampingFactor) : (l.theta += d.theta, l.phi += d.phi);
96
- let P = t.minAzimuthAngle, T = t.maxAzimuthAngle;
97
- isFinite(P) && isFinite(T) && (P < -Math.PI ? P += z : P > Math.PI && (P -= z), T < -Math.PI ? T += z : T > Math.PI && (T -= z), P <= T ? l.theta = Math.max(P, Math.min(T, l.theta)) : l.theta = l.theta > (P + T) / 2 ? Math.max(P, l.theta) : Math.min(T, l.theta)), l.phi = Math.max(t.minPolarAngle, Math.min(t.maxPolarAngle, l.phi)), l.makeSafe(), t.enableDamping === !0 ? t.target.addScaledVector(u, t.dampingFactor) : t.target.add(u), t.target.sub(t.cursor), t.target.clampLength(t.minTargetRadius, t.maxTargetRadius), t.target.add(t.cursor), t.zoomToCursor && U || t.object.isOrthographicCamera ? l.radius = oe(l.radius) : l.radius = oe(l.radius * g), s.setFromSpherical(l), s.applyQuaternion(m), Ce.copy(t.target).add(s), t.object.lookAt(t.target), t.enableDamping === !0 ? (d.theta *= 1 - t.dampingFactor, d.phi *= 1 - t.dampingFactor, u.multiplyScalar(1 - t.dampingFactor)) : (d.set(0, 0, 0), u.set(0, 0, 0));
98
- let se = !1;
99
- if (t.zoomToCursor && U) {
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 && _) {
100
102
  let Y = null;
101
103
  if (t.object.isPerspectiveCamera) {
102
- const B = s.length();
103
- Y = oe(B * g);
104
+ const B = o.length();
105
+ Y = se(B * u);
104
106
  const q = B - Y;
105
107
  t.object.position.addScaledVector(re, q), t.object.updateMatrixWorld();
106
108
  } else if (t.object.isOrthographicCamera) {
107
- const B = new N(L.x, L.y, 0);
108
- B.unproject(t.object), t.object.zoom = Math.max(t.minZoom, Math.min(t.maxZoom, t.object.zoom / g)), t.object.updateProjectionMatrix(), se = !0;
109
- const q = new N(L.x, L.y, 0);
110
- q.unproject(t.object), t.object.position.sub(q).add(B), t.object.updateMatrixWorld(), Y = s.length();
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
113
  } else
112
114
  console.warn("WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled."), t.zoomToCursor = !1;
113
- 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) : (Oe.setFromNormalAndCoplanarPoint(t.object.up, t.target), Z.intersectPlane(Oe, t.target))));
114
- } else t.object.isOrthographicCamera && (t.object.zoom = Math.max(t.minZoom, Math.min(t.maxZoom, t.object.zoom / g)), t.object.updateProjectionMatrix(), se = !0);
115
- return g = 1, U = !1, se || b.distanceToSquared(t.object.position) > a || 8 * (1 - E.dot(t.object.quaternion)) > a || F.distanceToSquared(t.target) > 0 ? (t.dispatchEvent(Pe), b.copy(t.object.position), E.copy(t.object.quaternion), F.copy(t.target), !0) : !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;
116
118
  };
117
119
  }(), this.dispose = function() {
118
- t.domElement.removeEventListener("contextmenu", Ee), t.domElement.removeEventListener("pointerdown", be), t.domElement.removeEventListener("pointercancel", $), t.domElement.removeEventListener("wheel", ve), t.domElement.removeEventListener("pointermove", ne), t.domElement.removeEventListener("pointerup", $), t._domElementKeyEvents !== null && (t._domElementKeyEvents.removeEventListener("keydown", ie), t._domElementKeyEvents = null);
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);
119
121
  };
120
- const t = this, n = {
122
+ const t = this, i = {
121
123
  NONE: -1,
122
124
  ROTATE: 0,
123
125
  DOLLY: 1,
@@ -127,175 +129,175 @@ class gt extends it {
127
129
  TOUCH_DOLLY_PAN: 5,
128
130
  TOUCH_DOLLY_ROTATE: 6
129
131
  };
130
- let i = n.NONE;
132
+ let n = i.NONE;
131
133
  const a = 1e-6, l = new Ne(), d = new Ne();
132
- let g = 1;
133
- const u = new N(), x = new S(), v = new S(), y = new S(), f = new S(), M = new S(), C = new S(), R = new S(), A = new S(), k = new S(), re = new N(), L = new S();
134
- let U = !1;
135
- const w = [], V = {};
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 = {};
136
138
  let J = !1;
137
- function Ae(s) {
138
- return s !== null ? 2 * Math.PI / 60 * t.autoRotateSpeed * s : 2 * Math.PI / 60 / 60 * t.autoRotateSpeed;
139
+ function He(o) {
140
+ return o !== null ? 2 * Math.PI / 60 * t.autoRotateSpeed * o : 2 * Math.PI / 60 / 60 * t.autoRotateSpeed;
139
141
  }
140
- function X(s) {
141
- const h = Math.abs(s * 0.01);
142
+ function X(o) {
143
+ const h = Math.abs(o * 0.01);
142
144
  return Math.pow(0.95, t.zoomSpeed * h);
143
145
  }
144
- function G(s) {
145
- d.theta -= s;
146
+ function K(o) {
147
+ d.theta -= o;
146
148
  }
147
- function W(s) {
148
- d.phi -= s;
149
+ function W(o) {
150
+ d.phi -= o;
149
151
  }
150
152
  const le = function() {
151
- const s = new N();
152
- return function(m, b) {
153
- s.setFromMatrixColumn(b, 0), s.multiplyScalar(-m), u.add(s);
153
+ const o = new N();
154
+ return function(m, x) {
155
+ o.setFromMatrixColumn(x, 0), o.multiplyScalar(-m), g.add(o);
154
156
  };
155
157
  }(), ce = function() {
156
- const s = new N();
157
- return function(m, b) {
158
- t.screenSpacePanning === !0 ? s.setFromMatrixColumn(b, 1) : (s.setFromMatrixColumn(b, 0), s.crossVectors(t.object.up, s)), s.multiplyScalar(m), u.add(s);
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);
159
161
  };
160
- }(), j = function() {
161
- const s = new N();
162
- return function(m, b) {
163
- const E = t.domElement;
162
+ }(), A = function() {
163
+ const o = new N();
164
+ return function(m, x) {
165
+ const w = t.domElement;
164
166
  if (t.object.isPerspectiveCamera) {
165
- const F = t.object.position;
166
- s.copy(F).sub(t.target);
167
- let z = s.length();
168
- z *= Math.tan(t.object.fov / 2 * Math.PI / 180), le(2 * m * z / E.clientHeight, t.object.matrix), ce(2 * b * z / E.clientHeight, t.object.matrix);
169
- } else t.object.isOrthographicCamera ? (le(m * (t.object.right - t.object.left) / t.object.zoom / E.clientWidth, t.object.matrix), ce(b * (t.object.top - t.object.bottom) / t.object.zoom / E.clientHeight, t.object.matrix)) : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."), t.enablePan = !1);
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);
170
172
  };
171
173
  }();
172
- function ee(s) {
173
- t.object.isPerspectiveCamera || t.object.isOrthographicCamera ? g /= s : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."), t.enableZoom = !1);
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);
174
176
  }
175
- function he(s) {
176
- t.object.isPerspectiveCamera || t.object.isOrthographicCamera ? g *= s : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."), t.enableZoom = !1);
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);
177
179
  }
178
- function te(s, h) {
180
+ function te(o, h) {
179
181
  if (!t.zoomToCursor)
180
182
  return;
181
- U = !0;
182
- const m = t.domElement.getBoundingClientRect(), b = s - m.left, E = h - m.top, F = m.width, z = m.height;
183
- L.x = b / F * 2 - 1, L.y = -(E / z) * 2 + 1, re.set(L.x, L.y, 1).unproject(t.object).sub(t.object.position).normalize();
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();
184
186
  }
185
- function oe(s) {
186
- return Math.max(t.minDistance, Math.min(t.maxDistance, s));
187
+ function se(o) {
188
+ return Math.max(t.minDistance, Math.min(t.maxDistance, o));
187
189
  }
188
- function de(s) {
189
- x.set(s.clientX, s.clientY);
190
+ function de(o) {
191
+ b.set(o.clientX, o.clientY);
190
192
  }
191
- function je(s) {
192
- te(s.clientX, s.clientX), R.set(s.clientX, s.clientY);
193
+ function Ae(o) {
194
+ te(o.clientX, o.clientX), F.set(o.clientX, o.clientY);
193
195
  }
194
- function pe(s) {
195
- f.set(s.clientX, s.clientY);
196
+ function pe(o) {
197
+ f.set(o.clientX, o.clientY);
196
198
  }
197
- function De(s) {
198
- v.set(s.clientX, s.clientY), y.subVectors(v, x).multiplyScalar(t.rotateSpeed);
199
+ function je(o) {
200
+ v.set(o.clientX, o.clientY), y.subVectors(v, b).multiplyScalar(t.rotateSpeed);
199
201
  const h = t.domElement;
200
- G(2 * Math.PI * y.x / h.clientHeight), W(2 * Math.PI * y.y / h.clientHeight), x.copy(v), t.update();
202
+ K(2 * Math.PI * y.x / h.clientHeight), W(2 * Math.PI * y.y / h.clientHeight), b.copy(v), t.update();
201
203
  }
202
- function He(s) {
203
- A.set(s.clientX, s.clientY), k.subVectors(A, R), k.y > 0 ? ee(X(k.y)) : k.y < 0 && he(X(k.y)), R.copy(A), t.update();
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();
204
206
  }
205
- function Ke(s) {
206
- M.set(s.clientX, s.clientY), C.subVectors(M, f).multiplyScalar(t.panSpeed), j(C.x, C.y), f.copy(M), t.update();
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();
207
209
  }
208
- function Ge(s) {
209
- te(s.clientX, s.clientY), s.deltaY < 0 ? he(X(s.deltaY)) : s.deltaY > 0 && ee(X(s.deltaY)), t.update();
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();
210
212
  }
211
- function $e(s) {
213
+ function Ge(o) {
212
214
  let h = !1;
213
- switch (s.code) {
215
+ switch (o.code) {
214
216
  case t.keys.UP:
215
- s.ctrlKey || s.metaKey || s.shiftKey ? W(2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : j(0, t.keyPanSpeed), h = !0;
217
+ o.ctrlKey || o.metaKey || o.shiftKey ? W(2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(0, t.keyPanSpeed), h = !0;
216
218
  break;
217
219
  case t.keys.BOTTOM:
218
- s.ctrlKey || s.metaKey || s.shiftKey ? W(-2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : j(0, -t.keyPanSpeed), h = !0;
220
+ o.ctrlKey || o.metaKey || o.shiftKey ? W(-2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(0, -t.keyPanSpeed), h = !0;
219
221
  break;
220
222
  case t.keys.LEFT:
221
- s.ctrlKey || s.metaKey || s.shiftKey ? G(2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : j(t.keyPanSpeed, 0), h = !0;
223
+ o.ctrlKey || o.metaKey || o.shiftKey ? K(2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(t.keyPanSpeed, 0), h = !0;
222
224
  break;
223
225
  case t.keys.RIGHT:
224
- s.ctrlKey || s.metaKey || s.shiftKey ? G(-2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : j(-t.keyPanSpeed, 0), h = !0;
226
+ o.ctrlKey || o.metaKey || o.shiftKey ? K(-2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(-t.keyPanSpeed, 0), h = !0;
225
227
  break;
226
228
  }
227
- h && (s.preventDefault(), t.update());
229
+ h && (o.preventDefault(), t.update());
228
230
  }
229
- function ge(s) {
230
- if (w.length === 1)
231
- x.set(s.pageX, s.pageY);
231
+ function ue(o) {
232
+ if (E.length === 1)
233
+ b.set(o.pageX, o.pageY);
232
234
  else {
233
- const h = D(s), m = 0.5 * (s.pageX + h.x), b = 0.5 * (s.pageY + h.y);
234
- x.set(m, b);
235
+ const h = j(o), m = 0.5 * (o.pageX + h.x), x = 0.5 * (o.pageY + h.y);
236
+ b.set(m, x);
235
237
  }
236
238
  }
237
- function ue(s) {
238
- if (w.length === 1)
239
- f.set(s.pageX, s.pageY);
239
+ function ge(o) {
240
+ if (E.length === 1)
241
+ f.set(o.pageX, o.pageY);
240
242
  else {
241
- const h = D(s), m = 0.5 * (s.pageX + h.x), b = 0.5 * (s.pageY + h.y);
242
- f.set(m, b);
243
+ const h = j(o), m = 0.5 * (o.pageX + h.x), x = 0.5 * (o.pageY + h.y);
244
+ f.set(m, x);
243
245
  }
244
246
  }
245
- function me(s) {
246
- const h = D(s), m = s.pageX - h.x, b = s.pageY - h.y, E = Math.sqrt(m * m + b * b);
247
- R.set(0, E);
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);
248
250
  }
249
- function Ye(s) {
250
- t.enableZoom && me(s), t.enablePan && ue(s);
251
+ function Ye(o) {
252
+ t.enableZoom && me(o), t.enablePan && ge(o);
251
253
  }
252
- function Be(s) {
253
- t.enableZoom && me(s), t.enableRotate && ge(s);
254
+ function Be(o) {
255
+ t.enableZoom && me(o), t.enableRotate && ue(o);
254
256
  }
255
- function fe(s) {
256
- if (w.length == 1)
257
- v.set(s.pageX, s.pageY);
257
+ function fe(o) {
258
+ if (E.length == 1)
259
+ v.set(o.pageX, o.pageY);
258
260
  else {
259
- const m = D(s), b = 0.5 * (s.pageX + m.x), E = 0.5 * (s.pageY + m.y);
260
- v.set(b, E);
261
+ const m = j(o), x = 0.5 * (o.pageX + m.x), w = 0.5 * (o.pageY + m.y);
262
+ v.set(x, w);
261
263
  }
262
- y.subVectors(v, x).multiplyScalar(t.rotateSpeed);
264
+ y.subVectors(v, b).multiplyScalar(t.rotateSpeed);
263
265
  const h = t.domElement;
264
- G(2 * Math.PI * y.x / h.clientHeight), W(2 * Math.PI * y.y / h.clientHeight), x.copy(v);
266
+ K(2 * Math.PI * y.x / h.clientHeight), W(2 * Math.PI * y.y / h.clientHeight), b.copy(v);
265
267
  }
266
- function ye(s) {
267
- if (w.length === 1)
268
- M.set(s.pageX, s.pageY);
268
+ function ye(o) {
269
+ if (E.length === 1)
270
+ M.set(o.pageX, o.pageY);
269
271
  else {
270
- const h = D(s), m = 0.5 * (s.pageX + h.x), b = 0.5 * (s.pageY + h.y);
271
- M.set(m, b);
272
+ const h = j(o), m = 0.5 * (o.pageX + h.x), x = 0.5 * (o.pageY + h.y);
273
+ M.set(m, x);
272
274
  }
273
- C.subVectors(M, f).multiplyScalar(t.panSpeed), j(C.x, C.y), f.copy(M);
275
+ C.subVectors(M, f).multiplyScalar(t.panSpeed), A(C.x, C.y), f.copy(M);
274
276
  }
275
- function xe(s) {
276
- const h = D(s), m = s.pageX - h.x, b = s.pageY - h.y, E = Math.sqrt(m * m + b * b);
277
- A.set(0, E), k.set(0, Math.pow(A.y / R.y, t.zoomSpeed)), ee(k.y), R.copy(A);
278
- const F = (s.pageX + h.x) * 0.5, z = (s.pageY + h.y) * 0.5;
279
- te(F, z);
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);
280
282
  }
281
- function _e(s) {
282
- t.enableZoom && xe(s), t.enablePan && ye(s);
283
+ function Ue(o) {
284
+ t.enableZoom && be(o), t.enablePan && ye(o);
283
285
  }
284
- function Ue(s) {
285
- t.enableZoom && xe(s), t.enableRotate && fe(s);
286
+ function _e(o) {
287
+ t.enableZoom && be(o), t.enableRotate && fe(o);
286
288
  }
287
- function be(s) {
288
- t.enabled !== !1 && (w.length === 0 && (t.domElement.setPointerCapture(s.pointerId), t.domElement.addEventListener("pointermove", ne), t.domElement.addEventListener("pointerup", $)), Je(s), s.pointerType === "touch" ? Ze(s) : Ve(s));
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));
289
291
  }
290
- function ne(s) {
291
- t.enabled !== !1 && (s.pointerType === "touch" ? Qe(s) : Xe(s));
292
+ function ie(o) {
293
+ t.enabled !== !1 && (o.pointerType === "touch" ? Qe(o) : Xe(o));
292
294
  }
293
- function $(s) {
294
- et(s), w.length === 0 && (t.domElement.releasePointerCapture(s.pointerId), t.domElement.removeEventListener("pointermove", ne), t.domElement.removeEventListener("pointerup", $)), t.dispatchEvent(Te), i = n.NONE;
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;
295
297
  }
296
- function Ve(s) {
298
+ function Ve(o) {
297
299
  let h;
298
- switch (s.button) {
300
+ switch (o.button) {
299
301
  case 0:
300
302
  h = t.mouseButtons.LEFT;
301
303
  break;
@@ -309,57 +311,57 @@ class gt extends it {
309
311
  h = -1;
310
312
  }
311
313
  switch (h) {
312
- case H.DOLLY:
314
+ case D.DOLLY:
313
315
  if (t.enableZoom === !1) return;
314
- je(s), i = n.DOLLY;
316
+ Ae(o), n = i.DOLLY;
315
317
  break;
316
- case H.ROTATE:
317
- if (s.ctrlKey || s.metaKey || s.shiftKey) {
318
+ case D.ROTATE:
319
+ if (o.ctrlKey || o.metaKey || o.shiftKey) {
318
320
  if (t.enablePan === !1) return;
319
- pe(s), i = n.PAN;
321
+ pe(o), n = i.PAN;
320
322
  } else {
321
323
  if (t.enableRotate === !1) return;
322
- de(s), i = n.ROTATE;
324
+ de(o), n = i.ROTATE;
323
325
  }
324
326
  break;
325
- case H.PAN:
326
- if (s.ctrlKey || s.metaKey || s.shiftKey) {
327
+ case D.PAN:
328
+ if (o.ctrlKey || o.metaKey || o.shiftKey) {
327
329
  if (t.enableRotate === !1) return;
328
- de(s), i = n.ROTATE;
330
+ de(o), n = i.ROTATE;
329
331
  } else {
330
332
  if (t.enablePan === !1) return;
331
- pe(s), i = n.PAN;
333
+ pe(o), n = i.PAN;
332
334
  }
333
335
  break;
334
336
  default:
335
- i = n.NONE;
337
+ n = i.NONE;
336
338
  }
337
- i !== n.NONE && t.dispatchEvent(ae);
339
+ n !== i.NONE && t.dispatchEvent(ae);
338
340
  }
339
- function Xe(s) {
340
- switch (i) {
341
- case n.ROTATE:
341
+ function Xe(o) {
342
+ switch (n) {
343
+ case i.ROTATE:
342
344
  if (t.enableRotate === !1) return;
343
- De(s);
345
+ je(o);
344
346
  break;
345
- case n.DOLLY:
347
+ case i.DOLLY:
346
348
  if (t.enableZoom === !1) return;
347
- He(s);
349
+ De(o);
348
350
  break;
349
- case n.PAN:
351
+ case i.PAN:
350
352
  if (t.enablePan === !1) return;
351
- Ke(s);
353
+ $e(o);
352
354
  break;
353
355
  }
354
356
  }
355
- function ve(s) {
356
- t.enabled === !1 || t.enableZoom === !1 || i !== n.NONE || (s.preventDefault(), t.dispatchEvent(ae), Ge(We(s)), t.dispatchEvent(Te));
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));
357
359
  }
358
- function We(s) {
359
- const h = s.deltaMode, m = {
360
- clientX: s.clientX,
361
- clientY: s.clientY,
362
- deltaY: s.deltaY
360
+ function We(o) {
361
+ const h = o.deltaMode, m = {
362
+ clientX: o.clientX,
363
+ clientY: o.clientY,
364
+ deltaY: o.deltaY
363
365
  };
364
366
  switch (h) {
365
367
  case 1:
@@ -369,101 +371,101 @@ class gt extends it {
369
371
  m.deltaY *= 100;
370
372
  break;
371
373
  }
372
- return s.ctrlKey && !J && (m.deltaY *= 10), m;
374
+ return o.ctrlKey && !J && (m.deltaY *= 10), m;
373
375
  }
374
- function qe(s) {
375
- s.key === "Control" && (J = !0, document.addEventListener("keyup", Me, { passive: !0, capture: !0 }));
376
+ function qe(o) {
377
+ o.key === "Control" && (J = !0, document.addEventListener("keyup", Me, { passive: !0, capture: !0 }));
376
378
  }
377
- function Me(s) {
378
- s.key === "Control" && (J = !1, document.removeEventListener("keyup", Me, { passive: !0, capture: !0 }));
379
+ function Me(o) {
380
+ o.key === "Control" && (J = !1, document.removeEventListener("keyup", Me, { passive: !0, capture: !0 }));
379
381
  }
380
- function ie(s) {
381
- t.enabled === !1 || t.enablePan === !1 || $e(s);
382
+ function ne(o) {
383
+ t.enabled === !1 || t.enablePan === !1 || Ge(o);
382
384
  }
383
- function Ze(s) {
384
- switch (we(s), w.length) {
385
+ function Ze(o) {
386
+ switch (Ee(o), E.length) {
385
387
  case 1:
386
388
  switch (t.touches.ONE) {
387
- case K.ROTATE:
389
+ case $.ROTATE:
388
390
  if (t.enableRotate === !1) return;
389
- ge(s), i = n.TOUCH_ROTATE;
391
+ ue(o), n = i.TOUCH_ROTATE;
390
392
  break;
391
- case K.PAN:
393
+ case $.PAN:
392
394
  if (t.enablePan === !1) return;
393
- ue(s), i = n.TOUCH_PAN;
395
+ ge(o), n = i.TOUCH_PAN;
394
396
  break;
395
397
  default:
396
- i = n.NONE;
398
+ n = i.NONE;
397
399
  }
398
400
  break;
399
401
  case 2:
400
402
  switch (t.touches.TWO) {
401
- case K.DOLLY_PAN:
403
+ case $.DOLLY_PAN:
402
404
  if (t.enableZoom === !1 && t.enablePan === !1) return;
403
- Ye(s), i = n.TOUCH_DOLLY_PAN;
405
+ Ye(o), n = i.TOUCH_DOLLY_PAN;
404
406
  break;
405
- case K.DOLLY_ROTATE:
407
+ case $.DOLLY_ROTATE:
406
408
  if (t.enableZoom === !1 && t.enableRotate === !1) return;
407
- Be(s), i = n.TOUCH_DOLLY_ROTATE;
409
+ Be(o), n = i.TOUCH_DOLLY_ROTATE;
408
410
  break;
409
411
  default:
410
- i = n.NONE;
412
+ n = i.NONE;
411
413
  }
412
414
  break;
413
415
  default:
414
- i = n.NONE;
416
+ n = i.NONE;
415
417
  }
416
- i !== n.NONE && t.dispatchEvent(ae);
418
+ n !== i.NONE && t.dispatchEvent(ae);
417
419
  }
418
- function Qe(s) {
419
- switch (we(s), i) {
420
- case n.TOUCH_ROTATE:
420
+ function Qe(o) {
421
+ switch (Ee(o), n) {
422
+ case i.TOUCH_ROTATE:
421
423
  if (t.enableRotate === !1) return;
422
- fe(s), t.update();
424
+ fe(o), t.update();
423
425
  break;
424
- case n.TOUCH_PAN:
426
+ case i.TOUCH_PAN:
425
427
  if (t.enablePan === !1) return;
426
- ye(s), t.update();
428
+ ye(o), t.update();
427
429
  break;
428
- case n.TOUCH_DOLLY_PAN:
430
+ case i.TOUCH_DOLLY_PAN:
429
431
  if (t.enableZoom === !1 && t.enablePan === !1) return;
430
- _e(s), t.update();
432
+ Ue(o), t.update();
431
433
  break;
432
- case n.TOUCH_DOLLY_ROTATE:
434
+ case i.TOUCH_DOLLY_ROTATE:
433
435
  if (t.enableZoom === !1 && t.enableRotate === !1) return;
434
- Ue(s), t.update();
436
+ _e(o), t.update();
435
437
  break;
436
438
  default:
437
- i = n.NONE;
439
+ n = i.NONE;
438
440
  }
439
441
  }
440
- function Ee(s) {
441
- t.enabled !== !1 && s.preventDefault();
442
+ function we(o) {
443
+ t.enabled !== !1 && o.preventDefault();
442
444
  }
443
- function Je(s) {
444
- w.push(s.pointerId);
445
+ function Je(o) {
446
+ E.push(o.pointerId);
445
447
  }
446
- function et(s) {
447
- delete V[s.pointerId];
448
- for (let h = 0; h < w.length; h++)
449
- if (w[h] == s.pointerId) {
450
- w.splice(h, 1);
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);
451
453
  return;
452
454
  }
453
455
  }
454
- function we(s) {
455
- let h = V[s.pointerId];
456
- h === void 0 && (h = new S(), V[s.pointerId] = h), h.set(s.pageX, s.pageY);
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);
457
459
  }
458
- function D(s) {
459
- const h = s.pointerId === w[0] ? w[1] : w[0];
460
+ function j(o) {
461
+ const h = o.pointerId === E[0] ? E[1] : E[0];
460
462
  return V[h];
461
463
  }
462
- t.domElement.addEventListener("contextmenu", Ee), t.domElement.addEventListener("pointerdown", be), t.domElement.addEventListener("pointercancel", $), t.domElement.addEventListener("wheel", ve, { passive: !1 }), document.addEventListener("keydown", qe, { passive: !0, capture: !0 }), this.update();
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();
463
465
  }
464
466
  }
465
- class ut {
466
- constructor(e, o) {
467
+ class gt {
468
+ constructor(e, s) {
467
469
  r(this, "scene");
468
470
  r(this, "camera");
469
471
  r(this, "renderer");
@@ -471,16 +473,16 @@ class ut {
471
473
  r(this, "container");
472
474
  r(this, "resizeHandler");
473
475
  this.container = e, this.scene = new p.Scene(), this.scene.background = new p.Color(
474
- o.backgroundColor ?? 657930
476
+ s.backgroundColor ?? 657930
475
477
  );
476
- const { width: t, height: n } = Se(e), i = o.cameraFov ?? 75;
477
- this.camera = new p.PerspectiveCamera(i, t / n, 0.1, 2e3);
478
- const a = o.cameraPosition ?? { x: 0, y: 0, z: 80 };
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 a = s.cameraPosition ?? { x: 0, y: 0, z: 80 };
479
481
  this.camera.position.set(a.x, a.y, a.z), this.renderer = new p.WebGLRenderer({
480
482
  antialias: !0,
481
483
  alpha: !0,
482
484
  powerPreference: "high-performance"
483
- }), this.renderer.setSize(t, n), 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 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);
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);
484
486
  }
485
487
  /**
486
488
  * Sets up scene lighting for gradient glass on dark background
@@ -488,14 +490,14 @@ class ut {
488
490
  setupLighting() {
489
491
  const e = new p.AmbientLight(16777215, 0.4);
490
492
  this.scene.add(e);
491
- const o = new p.DirectionalLight(16777215, 0.9);
492
- o.position.set(50, 60, 40), o.castShadow = !0, o.shadow.mapSize.width = 1024, o.shadow.mapSize.height = 1024, this.scene.add(o);
493
+ const s = new p.DirectionalLight(16777215, 0.9);
494
+ s.position.set(50, 60, 40), s.castShadow = !0, s.shadow.mapSize.width = 1024, s.shadow.mapSize.height = 1024, this.scene.add(s);
493
495
  const t = new p.DirectionalLight(16773344, 0.4);
494
496
  t.position.set(-50, 30, -40), this.scene.add(t);
495
- const n = new p.DirectionalLight(16777215, 0.3);
496
- n.position.set(0, -30, -50), this.scene.add(n);
497
- const i = new p.PointLight(16750950, 0.5, 150);
498
- i.position.set(40, 20, 40), this.scene.add(i);
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);
499
501
  const a = new p.PointLight(16764057, 0.4, 150);
500
502
  a.position.set(-40, -20, 40), this.scene.add(a);
501
503
  const l = new p.PointLight(6724095, 0.2, 100);
@@ -505,8 +507,8 @@ class ut {
505
507
  * Handle window resize
506
508
  */
507
509
  onWindowResize() {
508
- const { width: e, height: o } = Se(this.container);
509
- this.camera.aspect = e / o, this.camera.updateProjectionMatrix(), this.renderer.setSize(e, o);
510
+ const { width: e, height: s } = ze(this.container);
511
+ this.camera.aspect = e / s, this.camera.updateProjectionMatrix(), this.renderer.setSize(e, s);
510
512
  }
511
513
  /**
512
514
  * Adds an object to the scene
@@ -554,12 +556,12 @@ class ut {
554
556
  }
555
557
  }
556
558
  class mt {
557
- constructor(e, o) {
559
+ constructor(e, s) {
558
560
  r(this, "sceneManager");
559
561
  r(this, "nodeFactory");
560
562
  r(this, "nodes", /* @__PURE__ */ new Map());
561
563
  r(this, "nodeObjects", /* @__PURE__ */ new Map());
562
- this.sceneManager = e, this.nodeFactory = o;
564
+ this.sceneManager = e, this.nodeFactory = s;
563
565
  }
564
566
  /**
565
567
  * Checks if a node exists
@@ -571,8 +573,8 @@ class mt {
571
573
  * Adds a node to the graph
572
574
  * @returns true if added, false if node already exists or invalid
573
575
  */
574
- addNode(e, o = 0) {
575
- if (!Ie(e))
576
+ addNode(e, s = 0) {
577
+ if (!Re(e))
576
578
  return !1;
577
579
  if (this.nodes.has(e.id))
578
580
  return console.warn(`[ForceGraph3D] Node with id "${e.id}" already exists`), !1;
@@ -580,47 +582,47 @@ class mt {
580
582
  x: (Math.random() - 0.5) * 50,
581
583
  y: (Math.random() - 0.5) * 50,
582
584
  z: (Math.random() - 0.5) * 50
583
- }, n = {
585
+ }, i = {
584
586
  ...e,
585
587
  position: t,
586
588
  velocity: { x: 0, y: 0, z: 0 },
587
589
  mass: 1
588
- }, i = this.nodeFactory.createNode(
590
+ }, n = this.nodeFactory.createNode(
589
591
  { ...e, position: t },
590
- o
592
+ s
591
593
  );
592
- return this.sceneManager.add(i.group), this.nodes.set(e.id, n), this.nodeObjects.set(e.id, i), !0;
594
+ return this.sceneManager.add(n.group), this.nodes.set(e.id, i), this.nodeObjects.set(e.id, n), !0;
593
595
  }
594
596
  /**
595
597
  * Removes a node from the graph
596
598
  * @returns true if removed, false if not found
597
599
  */
598
600
  removeNode(e) {
599
- const o = this.nodes.get(e), t = this.nodeObjects.get(e);
600
- return !o || !t ? !1 : (this.sceneManager.remove(t.group), this.nodeFactory.disposeNode(t), this.nodes.delete(e), this.nodeObjects.delete(e), !0);
601
+ const s = this.nodes.get(e), t = this.nodeObjects.get(e);
602
+ return !s || !t ? !1 : (this.sceneManager.remove(t.group), this.nodeFactory.disposeNode(t), this.nodes.delete(e), this.nodeObjects.delete(e), !0);
601
603
  }
602
604
  /**
603
605
  * Updates a node's properties
604
606
  */
605
- updateNode(e, o) {
606
- const t = this.nodes.get(e), n = this.nodeObjects.get(e);
607
- return !t || !n ? (console.warn(`[ForceGraph3D] Node "${e}" not found`), !1) : (o.label !== void 0 && (t.label = o.label, this.nodeFactory.updateNodeLabel(n, o.label)), o.color !== void 0 && (t.color = o.color, this.nodeFactory.updateNodeColor(n, o.color)), Object.keys(o).forEach((i) => {
608
- i !== "id" && i !== "label" && i !== "color" && i !== "position" && (t[i] = o[i]);
607
+ 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]);
609
611
  }), !0);
610
612
  }
611
613
  /**
612
614
  * Updates a node's position (called by physics engine)
613
615
  */
614
- updateNodePosition(e, o) {
615
- const t = this.nodes.get(e), n = this.nodeObjects.get(e);
616
- t && n && (t.position = o, n.group.position.set(o.x, o.y, o.z));
616
+ 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));
617
619
  }
618
620
  /**
619
621
  * Updates a node's LOD level
620
622
  */
621
- updateNodeLOD(e, o) {
623
+ updateNodeLOD(e, s) {
622
624
  const t = this.nodeObjects.get(e);
623
- t && this.nodeFactory.updateNodeLOD(t, o);
625
+ t && this.nodeFactory.updateNodeLOD(t, s);
624
626
  }
625
627
  /**
626
628
  * Gets a node by ID
@@ -645,8 +647,8 @@ class mt {
645
647
  */
646
648
  getAllNodeObjects() {
647
649
  const e = [];
648
- return this.nodeObjects.forEach((o) => {
649
- e.push(o.group);
650
+ return this.nodeObjects.forEach((s) => {
651
+ e.push(s.group);
650
652
  }), e;
651
653
  }
652
654
  /**
@@ -654,8 +656,8 @@ class mt {
654
656
  */
655
657
  getAllSpheres() {
656
658
  const e = [];
657
- return this.nodeObjects.forEach((o) => {
658
- e.push(o.sphere);
659
+ return this.nodeObjects.forEach((s) => {
660
+ e.push(s.sphere);
659
661
  }), e;
660
662
  }
661
663
  /**
@@ -668,8 +670,8 @@ class mt {
668
670
  * Clears all nodes
669
671
  */
670
672
  clear() {
671
- this.nodes.forEach((e, o) => {
672
- this.removeNode(o);
673
+ this.nodes.forEach((e, s) => {
674
+ this.removeNode(s);
673
675
  });
674
676
  }
675
677
  /**
@@ -680,7 +682,7 @@ class mt {
680
682
  }
681
683
  }
682
684
  class ft {
683
- constructor(e, o, t) {
685
+ constructor(e, s, t) {
684
686
  r(this, "sceneManager");
685
687
  r(this, "nodeManager");
686
688
  r(this, "edgeFactory");
@@ -688,13 +690,13 @@ class ft {
688
690
  r(this, "edgeObjects", []);
689
691
  r(this, "edgeKeySet", /* @__PURE__ */ new Set());
690
692
  r(this, "highlightedEdgeKey", null);
691
- this.sceneManager = e, this.nodeManager = o, this.edgeFactory = t;
693
+ this.sceneManager = e, this.nodeManager = s, this.edgeFactory = t;
692
694
  }
693
695
  /**
694
696
  * Checks if an edge exists
695
697
  */
696
- hasEdge(e, o) {
697
- const t = I(e, o);
698
+ hasEdge(e, s) {
699
+ const t = R(e, s);
698
700
  return this.edgeKeySet.has(t);
699
701
  }
700
702
  /**
@@ -702,50 +704,50 @@ class ft {
702
704
  * @returns true if added, false if edge already exists or nodes don't exist
703
705
  */
704
706
  addEdge(e) {
705
- if (!Re(e))
707
+ if (!Fe(e))
706
708
  return !1;
707
709
  if (!this.nodeManager.hasNode(e.source))
708
710
  return console.warn(`[ForceGraph3D] Source node "${e.source}" does not exist`), !1;
709
711
  if (!this.nodeManager.hasNode(e.target))
710
712
  return console.warn(`[ForceGraph3D] Target node "${e.target}" does not exist`), !1;
711
- const o = I(e.source, e.target);
712
- if (this.edgeKeySet.has(o))
713
+ const s = R(e.source, e.target);
714
+ if (this.edgeKeySet.has(s))
713
715
  return console.warn(`[ForceGraph3D] Edge "${e.source}" -> "${e.target}" already exists`), !1;
714
- const t = this.nodeManager.getNode(e.source), n = this.nodeManager.getNode(e.target), i = this.edgeFactory.createEdge(
716
+ const t = this.nodeManager.getNode(e.source), i = this.nodeManager.getNode(e.target), n = this.edgeFactory.createEdge(
715
717
  e,
716
718
  t,
717
- n,
719
+ i,
718
720
  t.position,
719
- n.position
721
+ i.position
720
722
  );
721
- return this.sceneManager.add(i.line), this.edges.push(e), this.edgeObjects.push(i), this.edgeKeySet.add(o), !0;
723
+ return this.sceneManager.add(n.line), this.edges.push(e), this.edgeObjects.push(n), this.edgeKeySet.add(s), !0;
722
724
  }
723
725
  /**
724
726
  * Removes an edge from the graph
725
727
  * @returns true if removed, false if not found
726
728
  */
727
- removeEdge(e, o) {
728
- const t = I(e, o);
729
+ removeEdge(e, s) {
730
+ const t = R(e, s);
729
731
  if (!this.edgeKeySet.has(t))
730
732
  return !1;
731
- const n = this.edges.findIndex(
732
- (a) => I(a.source, a.target) === t
733
+ const i = this.edges.findIndex(
734
+ (a) => R(a.source, a.target) === t
733
735
  );
734
- if (n === -1)
736
+ if (i === -1)
735
737
  return !1;
736
- const i = this.edgeObjects[n];
737
- return this.sceneManager.remove(i.line), this.edgeFactory.disposeEdge(i), this.edges.splice(n, 1), this.edgeObjects.splice(n, 1), this.edgeKeySet.delete(t), this.highlightedEdgeKey === t && (this.highlightedEdgeKey = null), !0;
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;
738
740
  }
739
741
  /**
740
742
  * Highlights an edge
741
743
  */
742
- highlightEdge(e, o) {
743
- const t = I(e, o);
744
+ highlightEdge(e, s) {
745
+ const t = R(e, s);
744
746
  this.highlightedEdgeKey && this.highlightedEdgeKey !== t && this.unhighlightCurrentEdge();
745
- const n = this.edges.findIndex(
746
- (i) => I(i.source, i.target) === t
747
+ const i = this.edges.findIndex(
748
+ (n) => R(n.source, n.target) === t
747
749
  );
748
- n !== -1 && (this.edgeFactory.highlightEdge(this.edgeObjects[n]), this.highlightedEdgeKey = t);
750
+ i !== -1 && (this.edgeFactory.highlightEdge(this.edgeObjects[i]), this.highlightedEdgeKey = t);
749
751
  }
750
752
  /**
751
753
  * Unhighlights the currently highlighted edge
@@ -753,7 +755,7 @@ class ft {
753
755
  unhighlightCurrentEdge() {
754
756
  if (!this.highlightedEdgeKey) return;
755
757
  const e = this.edges.findIndex(
756
- (o) => I(o.source, o.target) === this.highlightedEdgeKey
758
+ (s) => R(s.source, s.target) === this.highlightedEdgeKey
757
759
  );
758
760
  e !== -1 && this.edgeFactory.unhighlightEdge(this.edgeObjects[e]), this.highlightedEdgeKey = null;
759
761
  }
@@ -761,10 +763,10 @@ class ft {
761
763
  * Removes all edges connected to a node
762
764
  */
763
765
  removeEdgesForNode(e) {
764
- const o = [];
766
+ const s = [];
765
767
  this.edges.forEach((t) => {
766
- (t.source === e || t.target === e) && o.push({ source: t.source, target: t.target });
767
- }), o.forEach((t) => {
768
+ (t.source === e || t.target === e) && s.push({ source: t.source, target: t.target });
769
+ }), s.forEach((t) => {
768
770
  this.removeEdge(t.source, t.target);
769
771
  });
770
772
  }
@@ -772,27 +774,27 @@ class ft {
772
774
  * Gets all edges for a node
773
775
  */
774
776
  getEdgesForNode(e) {
775
- return this.edges.filter((o) => o.source === e || o.target === e);
777
+ return this.edges.filter((s) => s.source === e || s.target === e);
776
778
  }
777
779
  /**
778
780
  * Gets neighbor node IDs for a node
779
781
  */
780
782
  getNeighborIds(e) {
781
- const o = [];
783
+ const s = [];
782
784
  return this.edges.forEach((t) => {
783
- t.source === e ? o.push(t.target) : t.target === e && o.push(t.source);
784
- }), [...new Set(o)];
785
+ t.source === e ? s.push(t.target) : t.target === e && s.push(t.source);
786
+ }), [...new Set(s)];
785
787
  }
786
788
  /**
787
789
  * Updates all edge positions based on current node positions
788
790
  */
789
791
  updateEdgePositions() {
790
- this.edgeObjects.forEach((e, o) => {
791
- const t = this.edges[o], n = this.nodeManager.getNode(t.source), i = this.nodeManager.getNode(t.target);
792
- n && i && this.edgeFactory.updateEdgePositions(
792
+ 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(
793
795
  e,
794
- n.position,
795
- i.position
796
+ i.position,
797
+ n.position
796
798
  );
797
799
  });
798
800
  }
@@ -829,8 +831,8 @@ class ft {
829
831
  this.clear();
830
832
  }
831
833
  }
832
- class Le {
833
- constructor(e, o, t = {}) {
834
+ class Oe {
835
+ constructor(e, s, t = {}) {
834
836
  r(this, "nodes");
835
837
  r(this, "edges");
836
838
  // Physics parameters
@@ -844,7 +846,7 @@ class Le {
844
846
  r(this, "alphaDecay", 0.0228);
845
847
  r(this, "alphaMin", 1e-3);
846
848
  r(this, "alphaTarget", 0);
847
- this.nodes = e, this.edges = o, 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;
849
+ 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;
848
850
  }
849
851
  /**
850
852
  * Runs one simulation step
@@ -858,15 +860,15 @@ class Le {
858
860
  * Brute force repulsion - O(n²)
859
861
  */
860
862
  calculateRepulsionBruteForce() {
861
- const e = Array.from(this.nodes.values()), o = e.length;
862
- for (let t = 0; t < o; t++) {
863
- const n = e[t];
864
- for (let i = t + 1; i < o; i++) {
865
- const a = e[i], l = a.position.x - n.position.x, d = a.position.y - n.position.y, g = a.position.z - n.position.z;
866
- let u = l * l + d * d + g * g;
867
- u < 0.01 && (u = 0.01);
868
- const x = Math.sqrt(u), v = this.repulsionStrength * this.alpha / u, y = l / x * v, f = d / x * v, M = g / x * v;
869
- n.velocity.x -= y / n.mass, n.velocity.y -= f / n.mass, n.velocity.z -= M / n.mass, a.velocity.x += y / a.mass, a.velocity.y += f / a.mass, a.velocity.z += M / a.mass;
863
+ const e = Array.from(this.nodes.values()), s = e.length;
864
+ 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;
869
+ 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;
870
872
  }
871
873
  }
872
874
  }
@@ -874,48 +876,48 @@ class Le {
874
876
  * Barnes-Hut approximation - O(n log n)
875
877
  */
876
878
  calculateRepulsionBarnesHut() {
877
- const e = Array.from(this.nodes.values()), o = new yt(e);
879
+ const e = Array.from(this.nodes.values()), s = new yt(e);
878
880
  for (const t of e)
879
- this.calculateForceFromOctree(t, o.root);
881
+ this.calculateForceFromOctree(t, s.root);
880
882
  }
881
883
  /**
882
884
  * Recursive force calculation using octree
883
885
  */
884
- calculateForceFromOctree(e, o) {
885
- if (o.isLeaf) {
886
- o.node && o.node.id !== e.id && this.applyRepulsionBetween(e, o.node);
886
+ calculateForceFromOctree(e, s) {
887
+ if (s.isLeaf) {
888
+ s.node && s.node.id !== e.id && this.applyRepulsionBetween(e, s.node);
887
889
  return;
888
890
  }
889
- if (o.mass === 0) return;
890
- const t = o.centerOfMass.x - e.position.x, n = o.centerOfMass.y - e.position.y, i = o.centerOfMass.z - e.position.z, a = Math.sqrt(t * t + n * n + i * i);
891
- if (o.size / a < this.barnesHutTheta) {
892
- const l = Math.max(a * a, 0.01), d = this.repulsionStrength * this.alpha * o.mass / l;
893
- e.velocity.x -= t / a * d / e.mass, e.velocity.y -= n / a * d / e.mass, e.velocity.z -= i / a * d / e.mass;
891
+ 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);
893
+ 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;
894
896
  } else
895
- for (const l of o.children)
897
+ for (const l of s.children)
896
898
  l && this.calculateForceFromOctree(e, l);
897
899
  }
898
900
  /**
899
901
  * Apply repulsion between two nodes
900
902
  */
901
- applyRepulsionBetween(e, o) {
902
- const t = o.position.x - e.position.x, n = o.position.y - e.position.y, i = o.position.z - e.position.z;
903
- let a = t * t + n * n + i * i;
903
+ 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;
904
906
  a < 0.01 && (a = 0.01);
905
907
  const l = Math.sqrt(a), d = this.repulsionStrength * this.alpha / a;
906
- e.velocity.x -= t / l * d / e.mass, e.velocity.y -= n / l * d / e.mass, e.velocity.z -= i / l * d / e.mass;
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;
907
909
  }
908
910
  /**
909
911
  * Calculate attraction forces along edges
910
912
  */
911
913
  calculateAttraction() {
912
914
  for (const e of this.edges) {
913
- const o = this.nodes.get(e.source), t = this.nodes.get(e.target);
914
- if (!o || !t) continue;
915
- const n = t.position.x - o.position.x, i = t.position.y - o.position.y, a = t.position.z - o.position.z, l = Math.sqrt(n * n + i * i + a * a);
915
+ const s = this.nodes.get(e.source), t = this.nodes.get(e.target);
916
+ 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);
916
918
  if (l < 0.01) continue;
917
- const g = (l - 15) * this.attractionStrength * this.alpha, u = n / l * g, x = i / l * g, v = a / l * g;
918
- o.velocity.x += u / o.mass, o.velocity.y += x / o.mass, o.velocity.z += v / o.mass, t.velocity.x -= u / t.mass, t.velocity.y -= x / t.mass, t.velocity.z -= v / t.mass;
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
921
  }
920
922
  }
921
923
  /**
@@ -953,8 +955,8 @@ class Le {
953
955
  class yt {
954
956
  constructor(e) {
955
957
  r(this, "root");
956
- const o = this.calculateBounds(e);
957
- this.root = this.buildTree(e, o);
958
+ const s = this.calculateBounds(e);
959
+ this.root = this.buildTree(e, s);
958
960
  }
959
961
  calculateBounds(e) {
960
962
  if (e.length === 0)
@@ -962,22 +964,22 @@ class yt {
962
964
  min: { x: -100, y: -100, z: -100 },
963
965
  max: { x: 100, y: 100, z: 100 }
964
966
  };
965
- const o = { x: 1 / 0, y: 1 / 0, z: 1 / 0 }, t = { x: -1 / 0, y: -1 / 0, z: -1 / 0 };
966
- for (const i of e)
967
- o.x = Math.min(o.x, i.position.x), o.y = Math.min(o.y, i.position.y), o.z = Math.min(o.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);
968
- const n = 10;
969
- return o.x -= n, o.y -= n, o.z -= n, t.x += n, t.y += n, t.z += n, { min: o, max: t };
970
- }
971
- buildTree(e, o, t = 0) {
972
- const n = Math.max(
973
- o.max.x - o.min.x,
974
- o.max.y - o.min.y,
975
- o.max.z - o.min.z
967
+ 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 };
972
+ }
973
+ buildTree(e, s, t = 0) {
974
+ const i = Math.max(
975
+ s.max.x - s.min.x,
976
+ s.max.y - s.min.y,
977
+ s.max.z - s.min.z
976
978
  );
977
979
  if (e.length === 0)
978
980
  return {
979
- bounds: o,
980
- size: n,
981
+ bounds: s,
982
+ size: i,
981
983
  centerOfMass: { x: 0, y: 0, z: 0 },
982
984
  mass: 0,
983
985
  isLeaf: !0,
@@ -990,8 +992,8 @@ class yt {
990
992
  for (const M of e)
991
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;
992
994
  return y > 0 && (f.x /= y, f.y /= y, f.z /= y), {
993
- bounds: o,
994
- size: n,
995
+ bounds: s,
996
+ size: i,
995
997
  centerOfMass: f,
996
998
  mass: y,
997
999
  isLeaf: !0,
@@ -999,42 +1001,42 @@ class yt {
999
1001
  children: []
1000
1002
  };
1001
1003
  }
1002
- const i = (o.min.x + o.max.x) / 2, a = (o.min.y + o.max.y) / 2, l = (o.min.z + o.max.z) / 2, d = [[], [], [], [], [], [], [], []];
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 = [[], [], [], [], [], [], [], []];
1003
1005
  for (const y of e) {
1004
- const f = (y.position.x >= i ? 1 : 0) + (y.position.y >= a ? 2 : 0) + (y.position.z >= l ? 4 : 0);
1006
+ const f = (y.position.x >= n ? 1 : 0) + (y.position.y >= a ? 2 : 0) + (y.position.z >= l ? 4 : 0);
1005
1007
  d[f].push(y);
1006
1008
  }
1007
- const g = [
1008
- { min: { x: o.min.x, y: o.min.y, z: o.min.z }, max: { x: i, y: a, z: l } },
1009
- { min: { x: i, y: o.min.y, z: o.min.z }, max: { x: o.max.x, y: a, z: l } },
1010
- { min: { x: o.min.x, y: a, z: o.min.z }, max: { x: i, y: o.max.y, z: l } },
1011
- { min: { x: i, y: a, z: o.min.z }, max: { x: o.max.x, y: o.max.y, z: l } },
1012
- { min: { x: o.min.x, y: o.min.y, z: l }, max: { x: i, y: a, z: o.max.z } },
1013
- { min: { x: i, y: o.min.y, z: l }, max: { x: o.max.x, y: a, z: o.max.z } },
1014
- { min: { x: o.min.x, y: a, z: l }, max: { x: i, y: o.max.y, z: o.max.z } },
1015
- { min: { x: i, y: a, z: l }, max: { x: o.max.x, y: o.max.y, z: o.max.z } }
1016
- ], u = [];
1017
- let x = 0;
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 } }
1018
+ ], g = [];
1019
+ let b = 0;
1018
1020
  const v = { x: 0, y: 0, z: 0 };
1019
1021
  for (let y = 0; y < 8; y++)
1020
1022
  if (d[y].length > 0) {
1021
- const f = this.buildTree(d[y], g[y], t + 1);
1022
- u.push(f), x += f.mass, v.x += f.centerOfMass.x * f.mass, v.y += f.centerOfMass.y * f.mass, v.z += f.centerOfMass.z * f.mass;
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;
1023
1025
  } else
1024
- u.push(null);
1025
- return x > 0 && (v.x /= x, v.y /= x, v.z /= x), {
1026
- bounds: o,
1027
- size: n,
1026
+ g.push(null);
1027
+ return b > 0 && (v.x /= b, v.y /= b, v.z /= b), {
1028
+ bounds: s,
1029
+ size: i,
1028
1030
  centerOfMass: v,
1029
- mass: x,
1031
+ mass: b,
1030
1032
  isLeaf: !1,
1031
1033
  node: null,
1032
- children: u
1034
+ children: g
1033
1035
  };
1034
1036
  }
1035
1037
  }
1036
- class xt {
1037
- constructor(e, o, t, n = 60) {
1038
+ class bt {
1039
+ constructor(e, s, t, i = 60) {
1038
1040
  r(this, "sceneManager");
1039
1041
  r(this, "animationId", null);
1040
1042
  r(this, "isRunning", !1);
@@ -1052,14 +1054,14 @@ class xt {
1052
1054
  r(this, "animate", () => {
1053
1055
  if (!this.isRunning) return;
1054
1056
  this.animationId = requestAnimationFrame(this.animate);
1055
- const e = performance.now(), o = e - this.lastFrameTime;
1056
- if (o < this.frameInterval)
1057
+ const e = performance.now(), s = e - this.lastFrameTime;
1058
+ if (s < this.frameInterval)
1057
1059
  return;
1058
- this.lastFrameTime = e - o % this.frameInterval, this.frameCount++;
1060
+ this.lastFrameTime = e - s % this.frameInterval, this.frameCount++;
1059
1061
  const t = e - this.fpsStartTime;
1060
1062
  t >= 1e3 && (this.currentFPS = this.frameCount / (t / 1e3), this.frameCount = 0, this.fpsStartTime = e), this.onSimulate(), this.onRender(), this.sceneManager.render();
1061
1063
  });
1062
- this.sceneManager = e, this.onSimulate = o, this.onRender = t, this.frameInterval = 1e3 / n;
1064
+ this.sceneManager = e, this.onSimulate = s, this.onRender = t, this.frameInterval = 1e3 / i;
1063
1065
  }
1064
1066
  /**
1065
1067
  * Starts the animation loop
@@ -1098,7 +1100,7 @@ class xt {
1098
1100
  this.stop();
1099
1101
  }
1100
1102
  }
1101
- class bt {
1103
+ class xt {
1102
1104
  constructor() {
1103
1105
  r(this, "envMap", null);
1104
1106
  r(this, "materialCache", /* @__PURE__ */ new Map());
@@ -1121,7 +1123,7 @@ class bt {
1121
1123
  * Creates environment map for glass reflections on dark background
1122
1124
  */
1123
1125
  createEnvironmentMap() {
1124
- const o = [], t = [
1126
+ const s = [], t = [
1125
1127
  // Subtle colored gradients for interesting reflections
1126
1128
  { colors: ["#1a1a2e", "#16213e", "#0f3460"] },
1127
1129
  // +x
@@ -1136,10 +1138,10 @@ class bt {
1136
1138
  { colors: ["#2d1a1a", "#1a0a0a", "#0f0505"] }
1137
1139
  // -z
1138
1140
  ];
1139
- for (const n of t) {
1140
- const i = document.createElement("canvas");
1141
- i.width = 256, i.height = 256;
1142
- const a = i.getContext("2d"), l = a.createRadialGradient(
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
1145
  256 / 2,
1144
1146
  256 / 2,
1145
1147
  0,
@@ -1147,17 +1149,17 @@ class bt {
1147
1149
  256 / 2,
1148
1150
  256 * 0.8
1149
1151
  );
1150
- l.addColorStop(0, n.colors[0]), l.addColorStop(0.5, n.colors[1]), l.addColorStop(1, n.colors[2]), a.fillStyle = l, a.fillRect(0, 0, 256, 256);
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);
1151
1153
  const d = a.getImageData(0, 0, 256, 256);
1152
- for (let g = 0; g < d.data.length; g += 4) {
1153
- const u = (Math.random() - 0.5) * 5;
1154
- d.data[g] = Math.min(255, Math.max(0, d.data[g] + u)), d.data[g + 1] = Math.min(255, Math.max(0, d.data[g + 1] + u)), d.data[g + 2] = Math.min(255, Math.max(0, d.data[g + 2] + u));
1154
+ for (let u = 0; u < d.data.length; u += 4) {
1155
+ 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));
1155
1157
  }
1156
- a.putImageData(d, 0, 0), o.push(i);
1158
+ a.putImageData(d, 0, 0), s.push(n);
1157
1159
  }
1158
- this.envMap = new p.CubeTexture(o.map((n) => {
1159
- const i = new Image();
1160
- return i.src = n.toDataURL(), i;
1160
+ this.envMap = new p.CubeTexture(s.map((i) => {
1161
+ const n = new Image();
1162
+ return n.src = i.toDataURL(), n;
1161
1163
  })), this.envMap.needsUpdate = !0;
1162
1164
  }
1163
1165
  /**
@@ -1174,9 +1176,9 @@ class bt {
1174
1176
  const t = "glass-single";
1175
1177
  if (this.materialCache.has(t))
1176
1178
  return this.materialCache.get(t).clone();
1177
- const n = new p.Color(16750950), i = new p.ShaderMaterial({
1179
+ const i = new p.Color(16750950), n = new p.ShaderMaterial({
1178
1180
  uniforms: {
1179
- uColor: { value: n },
1181
+ uColor: { value: i },
1180
1182
  uEnvMap: { value: this.envMap },
1181
1183
  uGlowColor: { value: new p.Color(16777215) },
1182
1184
  uGlowIntensity: { value: 0.8 },
@@ -1248,16 +1250,16 @@ class bt {
1248
1250
  depthWrite: !0,
1249
1251
  blending: p.NormalBlending
1250
1252
  });
1251
- return this.materialCache.set(t, i), i.clone();
1253
+ return this.materialCache.set(t, n), n.clone();
1252
1254
  }
1253
1255
  /**
1254
1256
  * Creates material for edges (light color for dark background)
1255
1257
  */
1256
- createEdgeMaterial(e = 6710886, o = 0.4) {
1258
+ createEdgeMaterial(e = 6710886, s = 0.4) {
1257
1259
  return new p.LineBasicMaterial({
1258
1260
  color: e,
1259
1261
  transparent: !0,
1260
- opacity: o,
1262
+ opacity: s,
1261
1263
  linewidth: 1
1262
1264
  });
1263
1265
  }
@@ -1276,11 +1278,11 @@ class bt {
1276
1278
  /**
1277
1279
  * Creates a sprite material for labels (light text for dark background)
1278
1280
  */
1279
- createLabelMaterial(e, o = 24) {
1280
- const t = document.createElement("canvas"), n = t.getContext("2d");
1281
- n.font = `600 ${o}px Inter, -apple-system, sans-serif`;
1282
- const a = n.measureText(e).width;
1283
- t.width = Math.max(128, a + 24), t.height = o + 20, n.clearRect(0, 0, t.width, t.height), n.font = `600 ${o}px Inter, -apple-system, sans-serif`, n.textAlign = "center", n.textBaseline = "middle", n.shadowColor = "rgba(0, 0, 0, 0.8)", n.shadowBlur = 4, n.shadowOffsetX = 1, n.shadowOffsetY = 1, n.fillStyle = "rgba(255, 255, 255, 0.95)", n.fillText(e, t.width / 2, t.height / 2);
1281
+ 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);
1284
1286
  const l = new p.CanvasTexture(t);
1285
1287
  return l.needsUpdate = !0, new p.SpriteMaterial({
1286
1288
  map: l,
@@ -1303,19 +1305,19 @@ class bt {
1303
1305
  }
1304
1306
  }
1305
1307
  class vt {
1306
- constructor(e, o = 2, t = [32, 16, 8]) {
1308
+ constructor(e, s = 2, t = [32, 16, 8]) {
1307
1309
  r(this, "materialFactory");
1308
1310
  r(this, "geometryCache", /* @__PURE__ */ new Map());
1309
1311
  r(this, "nodeRadius");
1310
1312
  r(this, "lodSegments");
1311
- this.materialFactory = e, this.nodeRadius = o, this.lodSegments = t, this.initGeometryCache();
1313
+ this.materialFactory = e, this.nodeRadius = s, this.lodSegments = t, this.initGeometryCache();
1312
1314
  }
1313
1315
  /**
1314
1316
  * Pre-create geometries for each LOD level
1315
1317
  */
1316
1318
  initGeometryCache() {
1317
- this.lodSegments.forEach((e, o) => {
1318
- const t = `lod-${o}`;
1319
+ this.lodSegments.forEach((e, s) => {
1320
+ const t = `lod-${s}`;
1319
1321
  this.geometryCache.set(
1320
1322
  t,
1321
1323
  new p.SphereGeometry(this.nodeRadius, e, e)
@@ -1326,18 +1328,18 @@ class vt {
1326
1328
  * Gets geometry for the specified LOD level
1327
1329
  */
1328
1330
  getGeometry(e) {
1329
- const o = `lod-${e}`;
1330
- return this.geometryCache.has(o) ? this.geometryCache.get(o) : this.geometryCache.get("lod-0");
1331
+ const s = `lod-${e}`;
1332
+ return this.geometryCache.has(s) ? this.geometryCache.get(s) : this.geometryCache.get("lod-0");
1331
1333
  }
1332
1334
  /**
1333
1335
  * Creates a node visual (glass ball + label)
1334
1336
  */
1335
- createNode(e, o = 0) {
1337
+ createNode(e, s = 0) {
1336
1338
  const t = new p.Group();
1337
1339
  t.name = `node-${e.id}`, t.userData = { nodeId: e.id, nodeData: e };
1338
- const n = this.getGeometry(o), i = this.materialFactory.createGlassMaterial(
1340
+ const i = this.getGeometry(s), n = this.materialFactory.createGlassMaterial(
1339
1341
  e.color ?? 4886754
1340
- ), a = new p.Mesh(n, i);
1342
+ ), a = new p.Mesh(i, n);
1341
1343
  a.castShadow = !0, a.receiveShadow = !0, t.add(a);
1342
1344
  const l = this.materialFactory.createLabelMaterial(e.label), d = new p.Sprite(l);
1343
1345
  return d.position.y = this.nodeRadius + 1.5, d.scale.set(4, 1, 1), t.add(d), e.position && t.position.set(
@@ -1348,28 +1350,28 @@ class vt {
1348
1350
  group: t,
1349
1351
  sphere: a,
1350
1352
  label: d,
1351
- lodLevel: o
1353
+ lodLevel: s
1352
1354
  };
1353
1355
  }
1354
1356
  /**
1355
1357
  * Updates the LOD level of a node
1356
1358
  */
1357
- updateNodeLOD(e, o) {
1358
- if (e.lodLevel === o) return;
1359
- const t = this.getGeometry(o);
1360
- e.sphere.geometry = t, e.lodLevel = o;
1359
+ updateNodeLOD(e, s) {
1360
+ if (e.lodLevel === s) return;
1361
+ const t = this.getGeometry(s);
1362
+ e.sphere.geometry = t, e.lodLevel = s;
1361
1363
  }
1362
1364
  /**
1363
1365
  * Updates the color of a node
1364
1366
  */
1365
- updateNodeColor(e, o) {
1366
- e.sphere.material instanceof p.Material && e.sphere.material.dispose(), e.sphere.material = this.materialFactory.createGlassMaterial(o);
1367
+ updateNodeColor(e, s) {
1368
+ e.sphere.material instanceof p.Material && e.sphere.material.dispose(), e.sphere.material = this.materialFactory.createGlassMaterial(s);
1367
1369
  }
1368
1370
  /**
1369
1371
  * Updates the label of a node
1370
1372
  */
1371
- updateNodeLabel(e, o) {
1372
- 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(o);
1373
+ 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);
1373
1375
  }
1374
1376
  /**
1375
1377
  * Disposes a node's resources
@@ -1385,13 +1387,13 @@ class vt {
1385
1387
  }
1386
1388
  }
1387
1389
  class Mt {
1388
- constructor(e, o = 10066329, t = 0.5) {
1390
+ constructor(e, s = 10066329, t = 0.5) {
1389
1391
  r(this, "materialFactory");
1390
1392
  r(this, "edgeColor");
1391
1393
  r(this, "edgeOpacity");
1392
1394
  r(this, "defaultMaterial", null);
1393
1395
  r(this, "highlightMaterial", null);
1394
- this.materialFactory = e, this.edgeColor = o, this.edgeOpacity = t;
1396
+ this.materialFactory = e, this.edgeColor = s, this.edgeOpacity = t;
1395
1397
  }
1396
1398
  /**
1397
1399
  * Gets or creates the default edge material
@@ -1411,25 +1413,25 @@ class Mt {
1411
1413
  /**
1412
1414
  * Creates an edge line between two positions
1413
1415
  */
1414
- createEdge(e, o, t, n, i) {
1416
+ createEdge(e, s, t, i, n) {
1415
1417
  const a = new p.BufferGeometry(), l = new Float32Array([
1416
- n.x,
1417
- n.y,
1418
- n.z,
1419
1418
  i.x,
1420
1419
  i.y,
1421
- i.z
1420
+ i.z,
1421
+ n.x,
1422
+ n.y,
1423
+ n.z
1422
1424
  ]);
1423
1425
  a.setAttribute("position", new p.BufferAttribute(l, 3));
1424
- const d = this.getDefaultMaterial().clone(), g = new p.Line(a, d);
1425
- return g.name = `edge-${e.source}-${e.target}`, g.userData = {
1426
+ const d = this.getDefaultMaterial().clone(), u = new p.Line(a, d);
1427
+ return u.name = `edge-${e.source}-${e.target}`, u.userData = {
1426
1428
  source: e.source,
1427
1429
  target: e.target,
1428
1430
  edge: e,
1429
- sourceNode: o,
1431
+ sourceNode: s,
1430
1432
  targetNode: t
1431
- }, g.frustumCulled = !0, {
1432
- line: g,
1433
+ }, u.frustumCulled = !0, {
1434
+ line: u,
1433
1435
  source: e.source,
1434
1436
  target: e.target
1435
1437
  };
@@ -1449,9 +1451,9 @@ class Mt {
1449
1451
  /**
1450
1452
  * Updates an edge's positions
1451
1453
  */
1452
- updateEdgePositions(e, o, t) {
1453
- const n = e.line.geometry.attributes.position, i = n.array;
1454
- i[0] = o.x, i[1] = o.y, i[2] = o.z, i[3] = t.x, i[4] = t.y, i[5] = t.z, n.needsUpdate = !0, e.line.geometry.computeBoundingSphere();
1454
+ 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();
1455
1457
  }
1456
1458
  /**
1457
1459
  * Disposes an edge's resources
@@ -1466,28 +1468,28 @@ class Mt {
1466
1468
  this.defaultMaterial && this.defaultMaterial.dispose(), this.highlightMaterial && this.highlightMaterial.dispose();
1467
1469
  }
1468
1470
  }
1469
- class Et {
1470
- constructor(e, o = [50, 100, 200], t = !0) {
1471
+ class wt {
1472
+ constructor(e, s = [50, 100, 200], t = !0) {
1471
1473
  r(this, "camera");
1472
1474
  r(this, "lodDistances");
1473
1475
  r(this, "enabled");
1474
- this.camera = e, this.lodDistances = o, this.enabled = t;
1476
+ this.camera = e, this.lodDistances = s, this.enabled = t;
1475
1477
  }
1476
1478
  /**
1477
1479
  * Gets the LOD level for a position based on distance from camera
1478
1480
  */
1479
1481
  getLODLevel(e) {
1480
1482
  if (!this.enabled)
1481
- return _.HIGH;
1482
- const o = e.x - this.camera.position.x, t = e.y - this.camera.position.y, n = e.z - this.camera.position.z, i = Math.sqrt(o * o + t * t + n * n);
1483
- return i < this.lodDistances[0] ? _.HIGH : i < this.lodDistances[1] ? _.MEDIUM : _.LOW;
1483
+ 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;
1484
1486
  }
1485
1487
  /**
1486
1488
  * Checks if a node should be visible based on distance
1487
1489
  */
1488
- shouldRenderNode(e, o = 500) {
1489
- const t = e.x - this.camera.position.x, n = e.y - this.camera.position.y, i = e.z - this.camera.position.z;
1490
- return Math.sqrt(t * t + n * n + i * i) < o;
1490
+ 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;
1491
1493
  }
1492
1494
  /**
1493
1495
  * Sets the LOD distances
@@ -1502,13 +1504,13 @@ class Et {
1502
1504
  this.enabled = e;
1503
1505
  }
1504
1506
  }
1505
- class wt {
1506
- constructor(e, o = !0) {
1507
+ class Et {
1508
+ constructor(e, s = !0) {
1507
1509
  r(this, "camera");
1508
1510
  r(this, "frustum");
1509
1511
  r(this, "projScreenMatrix");
1510
1512
  r(this, "enabled");
1511
- this.camera = e, this.frustum = new p.Frustum(), this.projScreenMatrix = new p.Matrix4(), this.enabled = o;
1513
+ this.camera = e, this.frustum = new p.Frustum(), this.projScreenMatrix = new p.Matrix4(), this.enabled = s;
1512
1514
  }
1513
1515
  /**
1514
1516
  * Updates the frustum from the camera
@@ -1524,33 +1526,33 @@ class wt {
1524
1526
  */
1525
1527
  isPointVisible(e) {
1526
1528
  if (!this.enabled) return !0;
1527
- const o = new p.Vector3(e.x, e.y, e.z);
1528
- return this.frustum.containsPoint(o);
1529
+ const s = new p.Vector3(e.x, e.y, e.z);
1530
+ return this.frustum.containsPoint(s);
1529
1531
  }
1530
1532
  /**
1531
1533
  * Checks if a sphere is inside or intersects the frustum
1532
1534
  */
1533
- isSphereVisible(e, o) {
1535
+ isSphereVisible(e, s) {
1534
1536
  if (!this.enabled) return !0;
1535
1537
  const t = new p.Sphere(
1536
1538
  new p.Vector3(e.x, e.y, e.z),
1537
- o
1539
+ s
1538
1540
  );
1539
1541
  return this.frustum.intersectsSphere(t);
1540
1542
  }
1541
1543
  /**
1542
1544
  * Checks if a line segment is potentially visible
1543
1545
  */
1544
- isLineVisible(e, o) {
1546
+ isLineVisible(e, s) {
1545
1547
  if (!this.enabled) return !0;
1546
- const t = new p.Vector3(e.x, e.y, e.z), n = new p.Vector3(o.x, o.y, o.z);
1547
- if (this.frustum.containsPoint(t) || this.frustum.containsPoint(n))
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))
1548
1550
  return !0;
1549
- const i = new p.Vector3(
1550
- (e.x + o.x) / 2,
1551
- (e.y + o.y) / 2,
1552
- (e.z + o.z) / 2
1553
- ), a = i.distanceTo(t), l = new p.Sphere(i, a);
1551
+ const n = new p.Vector3(
1552
+ (e.x + s.x) / 2,
1553
+ (e.y + s.y) / 2,
1554
+ (e.z + s.z) / 2
1555
+ ), a = n.distanceTo(t), l = new p.Sphere(n, a);
1554
1556
  return this.frustum.intersectsSphere(l);
1555
1557
  }
1556
1558
  /**
@@ -1561,7 +1563,7 @@ class wt {
1561
1563
  }
1562
1564
  }
1563
1565
  class Ct {
1564
- constructor(e, o) {
1566
+ constructor(e, s) {
1565
1567
  r(this, "sceneManager");
1566
1568
  r(this, "raycaster");
1567
1569
  r(this, "mouse");
@@ -1573,7 +1575,7 @@ class Ct {
1573
1575
  r(this, "hoveredEdgeKey", null);
1574
1576
  r(this, "nodeObjects", []);
1575
1577
  r(this, "edgeObjects", []);
1576
- this.sceneManager = e, this.container = o, 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), o.addEventListener("click", this.handleClick), o.addEventListener("mousemove", this.handleMouseMove);
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);
1577
1579
  }
1578
1580
  /**
1579
1581
  * Updates the list of node objects to raycast against
@@ -1609,35 +1611,35 @@ class Ct {
1609
1611
  * Handles click events
1610
1612
  */
1611
1613
  handleClick(e) {
1612
- const o = this.getIntersectedNode(e);
1613
- o && this.onNodeClick && this.onNodeClick(o);
1614
+ const s = this.getIntersectedNode(e);
1615
+ s && this.onNodeClick && this.onNodeClick(s);
1614
1616
  }
1615
1617
  /**
1616
1618
  * Handles mouse move events for hover detection
1617
1619
  */
1618
1620
  handleMouseMove(e) {
1619
- const o = this.getIntersectedNode(e), t = (o == null ? void 0 : o.id) ?? null;
1620
- if (t !== this.hoveredNodeId && (this.hoveredNodeId = t, this.onNodeHover && this.onNodeHover(o)), o) {
1621
+ const s = this.getIntersectedNode(e), t = (s == null ? void 0 : s.id) ?? null;
1622
+ if (t !== this.hoveredNodeId && (this.hoveredNodeId = t, this.onNodeHover && this.onNodeHover(s)), s) {
1621
1623
  this.hoveredEdgeKey !== null && this.onEdgeHover && (this.hoveredEdgeKey = null, this.onEdgeHover(null)), this.container.style.cursor = "pointer";
1622
1624
  return;
1623
1625
  }
1624
- const n = this.getIntersectedEdge(e), i = n ? `${n.edge.source}-${n.edge.target}` : null;
1625
- i !== this.hoveredEdgeKey && (this.hoveredEdgeKey = i, this.onEdgeHover && this.onEdgeHover(n)), this.container.style.cursor = n ? "pointer" : "default";
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";
1626
1628
  }
1627
1629
  /**
1628
1630
  * Gets the intersected node from a mouse event
1629
1631
  */
1630
1632
  getIntersectedNode(e) {
1631
- var n;
1632
- const o = this.container.getBoundingClientRect();
1633
- this.mouse.x = (e.clientX - o.left) / o.width * 2 - 1, this.mouse.y = -((e.clientY - o.top) / o.height) * 2 + 1, this.raycaster.setFromCamera(this.mouse, this.sceneManager.camera);
1633
+ var i;
1634
+ const s = this.container.getBoundingClientRect();
1635
+ 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);
1634
1636
  const t = this.raycaster.intersectObjects(this.nodeObjects, !0);
1635
1637
  if (t.length > 0) {
1636
- let i = t[0].object;
1637
- for (; i; ) {
1638
- if ((n = i.userData) != null && n.nodeData)
1639
- return i.userData.nodeData;
1640
- i = i.parent;
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;
1641
1643
  }
1642
1644
  }
1643
1645
  return null;
@@ -1646,17 +1648,17 @@ class Ct {
1646
1648
  * Gets the intersected edge from a mouse event
1647
1649
  */
1648
1650
  getIntersectedEdge(e) {
1649
- const o = this.container.getBoundingClientRect();
1650
- this.mouse.x = (e.clientX - o.left) / o.width * 2 - 1, this.mouse.y = -((e.clientY - o.top) / o.height) * 2 + 1, this.raycaster.setFromCamera(this.mouse, this.sceneManager.camera);
1651
+ const s = this.container.getBoundingClientRect();
1652
+ 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);
1651
1653
  const t = this.raycaster.intersectObjects(this.edgeObjects, !1);
1652
1654
  if (t.length > 0) {
1653
- const n = t[0].object, i = n.userData;
1654
- if (i != null && i.edge && (i != null && i.sourceNode) && (i != null && i.targetNode))
1655
+ const i = t[0].object, n = i.userData;
1656
+ if (n != null && n.edge && (n != null && n.sourceNode) && (n != null && n.targetNode))
1655
1657
  return {
1656
- edge: i.edge,
1657
- sourceNode: i.sourceNode,
1658
- targetNode: i.targetNode,
1659
- edgeLine: n
1658
+ edge: n.edge,
1659
+ sourceNode: n.sourceNode,
1660
+ targetNode: n.targetNode,
1661
+ edgeLine: i
1660
1662
  };
1661
1663
  }
1662
1664
  return null;
@@ -1664,15 +1666,15 @@ class Ct {
1664
1666
  /**
1665
1667
  * Performs a raycast and returns the intersected node ID
1666
1668
  */
1667
- getIntersectedNodeId(e, o) {
1668
- var i;
1669
+ getIntersectedNodeId(e, s) {
1670
+ var n;
1669
1671
  const t = this.container.getBoundingClientRect();
1670
- this.mouse.x = (e - t.left) / t.width * 2 - 1, this.mouse.y = -((o - t.top) / t.height) * 2 + 1, this.raycaster.setFromCamera(this.mouse, this.sceneManager.camera);
1671
- const n = this.raycaster.intersectObjects(this.nodeObjects, !0);
1672
- if (n.length > 0) {
1673
- let a = n[0].object;
1672
+ 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;
1674
1676
  for (; a; ) {
1675
- if ((i = a.userData) != null && i.nodeId)
1677
+ if ((n = a.userData) != null && n.nodeId)
1676
1678
  return a.userData.nodeId;
1677
1679
  a = a.parent;
1678
1680
  }
@@ -1724,8 +1726,8 @@ class Nt {
1724
1726
  opacity: 0;
1725
1727
  pointer-events: none;
1726
1728
  transition: opacity 0.3s ease, transform 0.3s ease;
1727
- `, Object.entries(this.panelStyles).forEach(([e, o]) => {
1728
- this.panel.style.setProperty(e, o);
1729
+ `, Object.entries(this.panelStyles).forEach(([e, s]) => {
1730
+ this.panel.style.setProperty(e, s);
1729
1731
  }), this.container.appendChild(this.panel);
1730
1732
  }
1731
1733
  /**
@@ -1738,8 +1740,8 @@ class Nt {
1738
1740
  * Sets custom panel styles
1739
1741
  */
1740
1742
  setPanelStyles(e) {
1741
- this.panelStyles = e, this.panel && Object.entries(e).forEach(([o, t]) => {
1742
- this.panel.style.setProperty(o, t);
1743
+ this.panelStyles = e, this.panel && Object.entries(e).forEach(([s, t]) => {
1744
+ this.panel.style.setProperty(s, t);
1743
1745
  });
1744
1746
  }
1745
1747
  /**
@@ -1751,15 +1753,15 @@ class Nt {
1751
1753
  /**
1752
1754
  * Shows the panel with node information
1753
1755
  */
1754
- show(e, o) {
1756
+ show(e, s) {
1755
1757
  if (!this.panel) return;
1756
1758
  this.currentNodeId = e.id;
1757
1759
  let t;
1758
- this.panelTemplate ? t = this.panelTemplate(e, o) : t = this.generateDefaultContent(e, o), this.panel.innerHTML = t;
1759
- const n = this.panel.querySelector('[data-action="expand"]'), i = this.panel.querySelector("[data-depth-select]");
1760
- n && this.onExpand && n.addEventListener("click", () => {
1760
+ 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", () => {
1761
1763
  if (this.currentNodeId) {
1762
- const l = i ? parseInt(i.value, 10) : 1;
1764
+ const l = n ? parseInt(n.value, 10) : 1;
1763
1765
  this.onExpand(this.currentNodeId, l);
1764
1766
  }
1765
1767
  });
@@ -1771,7 +1773,7 @@ class Nt {
1771
1773
  /**
1772
1774
  * Generates default panel content
1773
1775
  */
1774
- generateDefaultContent(e, o) {
1776
+ generateDefaultContent(e, s) {
1775
1777
  const t = e.color ? `#${e.color.toString(16).padStart(6, "0")}` : "#4A90E2";
1776
1778
  return `
1777
1779
  <style>
@@ -1783,6 +1785,13 @@ class Nt {
1783
1785
  display: flex;
1784
1786
  align-items: center;
1785
1787
  gap: 10px;
1788
+ overflow: hidden;
1789
+ }
1790
+ .force-graph-panel .node-label-text {
1791
+ white-space: nowrap;
1792
+ overflow: hidden;
1793
+ text-overflow: ellipsis;
1794
+ flex: 1;
1786
1795
  }
1787
1796
  .force-graph-panel .color-dot {
1788
1797
  width: 12px;
@@ -1807,6 +1816,11 @@ class Nt {
1807
1816
  .force-graph-panel .info-value {
1808
1817
  color: rgba(255, 255, 255, 0.95);
1809
1818
  font-weight: 500;
1819
+ white-space: nowrap;
1820
+ overflow: hidden;
1821
+ text-overflow: ellipsis;
1822
+ max-width: 180px;
1823
+ text-align: right;
1810
1824
  }
1811
1825
  .force-graph-panel .neighbors-section {
1812
1826
  margin-top: 16px;
@@ -1889,26 +1903,26 @@ class Nt {
1889
1903
 
1890
1904
  <h2>
1891
1905
  <span class="color-dot"></span>
1892
- ${this.escapeHtml(e.label)}
1906
+ <span class="node-label-text">${this.escapeHtml(e.label)}</span>
1893
1907
  </h2>
1894
1908
 
1895
1909
  <div class="info-row">
1896
1910
  <span class="info-label">ID</span>
1897
- <span class="info-value">${this.escapeHtml(e.id)}</span>
1911
+ <span class="info-value" title="${this.escapeHtml(e.id)}">${this.escapeHtml(e.id)}</span>
1898
1912
  </div>
1899
1913
 
1900
1914
  <div class="info-row">
1901
1915
  <span class="info-label">Connections</span>
1902
- <span class="info-value">${o.length}</span>
1916
+ <span class="info-value">${s.length}</span>
1903
1917
  </div>
1904
1918
 
1905
- ${o.length > 0 ? `
1919
+ ${s.length > 0 ? `
1906
1920
  <div class="neighbors-section">
1907
1921
  <div class="neighbors-title">Connected To</div>
1908
- ${o.slice(0, 5).map(
1909
- (n) => `<span class="neighbor-chip">${this.escapeHtml(n.label)}</span>`
1922
+ ${s.slice(0, 5).map(
1923
+ (i) => `<span class="neighbor-chip">${this.escapeHtml(i.label)}</span>`
1910
1924
  ).join("")}
1911
- ${o.length > 5 ? `<span class="neighbor-chip">+${o.length - 5} more</span>` : ""}
1925
+ ${s.length > 5 ? `<span class="neighbor-chip">+${s.length - 5} more</span>` : ""}
1912
1926
  </div>
1913
1927
  ` : ""}
1914
1928
 
@@ -1932,8 +1946,8 @@ class Nt {
1932
1946
  * Escapes HTML to prevent XSS
1933
1947
  */
1934
1948
  escapeHtml(e) {
1935
- const o = document.createElement("div");
1936
- return o.textContent = e, o.innerHTML;
1949
+ const s = document.createElement("div");
1950
+ return s.textContent = e, s.innerHTML;
1937
1951
  }
1938
1952
  /**
1939
1953
  * Hides the panel
@@ -1960,7 +1974,7 @@ class Nt {
1960
1974
  this.panel && this.panel.parentNode && this.panel.parentNode.removeChild(this.panel), this.panel = null;
1961
1975
  }
1962
1976
  }
1963
- class zt {
1977
+ class St {
1964
1978
  constructor() {
1965
1979
  r(this, "tooltip", null);
1966
1980
  r(this, "visible", !1);
@@ -2004,22 +2018,22 @@ class zt {
2004
2018
  /**
2005
2019
  * Positions the tooltip near the mouse
2006
2020
  */
2007
- positionTooltip(e, o) {
2021
+ positionTooltip(e, s) {
2008
2022
  if (!this.tooltip) return;
2009
- const t = this.tooltip.getBoundingClientRect(), n = window.innerWidth, i = window.innerHeight;
2010
- let a = e + 15, l = o + 15;
2011
- a + t.width > n - 10 && (a = e - t.width - 15), l + t.height > i - 10 && (l = o - t.height - 15), a < 10 && (a = 10), l < 10 && (l = 10), this.tooltip.style.left = `${a}px`, this.tooltip.style.top = `${l}px`;
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`;
2012
2026
  }
2013
2027
  /**
2014
2028
  * Shows the tooltip with edge info
2015
2029
  */
2016
- show(e, o, t, n, i) {
2030
+ show(e, s, t, i, n) {
2017
2031
  if (!this.tooltip) return;
2018
2032
  const a = e.relationship || "connected to";
2019
2033
  this.tooltip.innerHTML = `
2020
2034
  <div style="display: flex; flex-direction: column; gap: 4px;">
2021
2035
  <div style="display: flex; align-items: center; gap: 6px; flex-wrap: wrap;">
2022
- <span style="font-weight: 600; color: #ff9966;">${this.escapeHtml(o.label)}</span>
2036
+ <span style="font-weight: 600; color: #ff9966;">${this.escapeHtml(s.label)}</span>
2023
2037
  </div>
2024
2038
  <div style="color: rgba(255, 255, 255, 0.6); font-style: italic; font-size: 12px; padding-left: 8px;">
2025
2039
  ↳ ${this.escapeHtml(a)}
@@ -2028,13 +2042,13 @@ class zt {
2028
2042
  <span style="font-weight: 600; color: #ff9966;">${this.escapeHtml(t.label)}</span>
2029
2043
  </div>
2030
2044
  </div>
2031
- `, this.positionTooltip(n, i), this.tooltip.style.opacity = "1", this.tooltip.style.transform = "translateY(0)", this.visible = !0;
2045
+ `, this.positionTooltip(i, n), this.tooltip.style.opacity = "1", this.tooltip.style.transform = "translateY(0)", this.visible = !0;
2032
2046
  }
2033
2047
  /**
2034
2048
  * Updates tooltip position (called externally on mouse move)
2035
2049
  */
2036
- updatePosition(e, o) {
2037
- this.visible && this.positionTooltip(e, o);
2050
+ updatePosition(e, s) {
2051
+ this.visible && this.positionTooltip(e, s);
2038
2052
  }
2039
2053
  /**
2040
2054
  * Hides the tooltip
@@ -2052,8 +2066,8 @@ class zt {
2052
2066
  * Escapes HTML to prevent XSS
2053
2067
  */
2054
2068
  escapeHtml(e) {
2055
- const o = document.createElement("div");
2056
- return o.textContent = e, o.innerHTML;
2069
+ const s = document.createElement("div");
2070
+ return s.textContent = e, s.innerHTML;
2057
2071
  }
2058
2072
  /**
2059
2073
  * Dispose the tooltip
@@ -2062,8 +2076,181 @@ class zt {
2062
2076
  this.tooltip && this.tooltip.parentNode && this.tooltip.parentNode.removeChild(this.tooltip), this.tooltip = null;
2063
2077
  }
2064
2078
  }
2079
+ class zt {
2080
+ 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");
2089
+ this.container = e, this.placeholder = s.placeholder || "Search nodes or relationships...", this.onSearch = s.onSearch, this.onResultClick = s.onResultClick, this.init();
2090
+ }
2091
+ init() {
2092
+ this.createSearchUI(), this.addEventListeners();
2093
+ }
2094
+ createSearchUI() {
2095
+ this.searchContainer = document.createElement("div"), this.searchContainer.className = "f3d-search-container", Object.assign(this.searchContainer.style, {
2096
+ position: "absolute",
2097
+ top: "20px",
2098
+ left: "20px",
2099
+ zIndex: "100",
2100
+ width: "320px"
2101
+ });
2102
+ const e = document.createElement("div");
2103
+ e.className = "f3d-search-input-wrapper", Object.assign(e.style, {
2104
+ position: "relative",
2105
+ display: "flex",
2106
+ alignItems: "center"
2107
+ }), e.innerHTML = `
2108
+ <svg class="f3d-search-icon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor"
2109
+ stroke-width="2" style="position: absolute; left: 14px; z-index: 10; color: rgba(255, 255, 255, 0.5); pointer-events: none;">
2110
+ <circle cx="11" cy="11" r="8"></circle>
2111
+ <path d="m21 21-4.35-4.35"></path>
2112
+ </svg>
2113
+ `, this.searchInput = document.createElement("input"), this.searchInput.type = "text", this.searchInput.className = "f3d-search-input", this.searchInput.placeholder = this.placeholder, this.searchInput.autocomplete = "off", Object.assign(this.searchInput.style, {
2114
+ width: "100%",
2115
+ padding: "12px 16px 12px 42px",
2116
+ background: "rgba(255, 255, 255, 0.08)",
2117
+ backdropFilter: "blur(20px)",
2118
+ webkitBackdropFilter: "blur(20px)",
2119
+ border: "1px solid rgba(255, 255, 255, 0.12)",
2120
+ borderRadius: "12px",
2121
+ color: "white",
2122
+ fontSize: "14px",
2123
+ fontFamily: "inherit",
2124
+ outline: "none",
2125
+ transition: "all 0.2s ease"
2126
+ }), this.searchInput.addEventListener("focus", () => {
2127
+ this.searchInput && (this.searchInput.style.background = "rgba(255, 255, 255, 0.12)", this.searchInput.style.borderColor = "rgba(255, 153, 102, 0.5)", this.searchInput.style.boxShadow = "0 0 20px rgba(255, 153, 102, 0.15)");
2128
+ }), this.searchInput.addEventListener("blur", () => {
2129
+ this.searchInput && (this.searchInput.style.background = "rgba(255, 255, 255, 0.08)", this.searchInput.style.borderColor = "rgba(255, 255, 255, 0.12)", this.searchInput.style.boxShadow = "none");
2130
+ }), this.searchResults = document.createElement("div"), this.searchResults.className = "f3d-search-results", Object.assign(this.searchResults.style, {
2131
+ position: "absolute",
2132
+ top: "100%",
2133
+ left: "0",
2134
+ right: "0",
2135
+ marginTop: "8px",
2136
+ background: "rgba(20, 20, 25, 0.95)",
2137
+ backdropFilter: "blur(20px)",
2138
+ webkitBackdropFilter: "blur(20px)",
2139
+ border: "1px solid rgba(255, 255, 255, 0.1)",
2140
+ borderRadius: "12px",
2141
+ maxHeight: "300px",
2142
+ overflowY: "auto",
2143
+ display: "none",
2144
+ boxShadow: "0 10px 40px rgba(0, 0, 0, 0.4)"
2145
+ }), e.appendChild(this.searchInput), this.searchContainer.appendChild(e), this.searchContainer.appendChild(this.searchResults), this.container.appendChild(this.searchContainer);
2146
+ const s = document.createElement("style");
2147
+ s.textContent = `
2148
+ .f3d-search-result-item {
2149
+ padding: 10px 14px;
2150
+ cursor: pointer;
2151
+ border-bottom: 1px solid rgba(255, 255, 255, 0.05);
2152
+ transition: background 0.15s ease;
2153
+ }
2154
+ .f3d-search-result-item:hover {
2155
+ background: rgba(255, 153, 102, 0.15);
2156
+ }
2157
+ .f3d-search-result-item:last-child {
2158
+ border-bottom: none;
2159
+ }
2160
+ .f3d-result-label {
2161
+ color: white;
2162
+ font-size: 13px;
2163
+ font-weight: 500;
2164
+ margin-bottom: 2px;
2165
+ }
2166
+ .f3d-result-type {
2167
+ color: rgba(255, 153, 102, 0.8);
2168
+ font-size: 11px;
2169
+ text-transform: uppercase;
2170
+ letter-spacing: 0.5px;
2171
+ }
2172
+ .f3d-result-relationship {
2173
+ color: rgba(255, 255, 255, 0.5);
2174
+ font-size: 11px;
2175
+ font-style: italic;
2176
+ }
2177
+ .f3d-no-results {
2178
+ padding: 14px;
2179
+ color: rgba(255, 255, 255, 0.4);
2180
+ font-size: 13px;
2181
+ text-align: center;
2182
+ }
2183
+ .f3d-search-section-header {
2184
+ padding: 8px 14px 6px;
2185
+ color: rgba(255, 255, 255, 0.3);
2186
+ font-size: 10px;
2187
+ text-transform: uppercase;
2188
+ letter-spacing: 1px;
2189
+ font-weight: 600;
2190
+ background: rgba(0, 0, 0, 0.2);
2191
+ }
2192
+ .f3d-search-results::-webkit-scrollbar { width: 6px; }
2193
+ .f3d-search-results::-webkit-scrollbar-track { background: transparent; }
2194
+ .f3d-search-results::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.15); border-radius: 3px; }
2195
+ .f3d-search-results::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.25); }
2196
+ `, document.head.appendChild(s);
2197
+ }
2198
+ addEventListeners() {
2199
+ !this.searchInput || !this.searchResults || (this.searchInput.addEventListener("input", (e) => {
2200
+ const s = e.target.value;
2201
+ this.searchTimeout && window.clearTimeout(this.searchTimeout), this.searchTimeout = window.setTimeout(() => {
2202
+ this.performSearch(s);
2203
+ }, 150);
2204
+ }), this.searchInput.addEventListener("focus", () => {
2205
+ this.searchInput && this.searchInput.value.length > 0 && (this.searchResults.style.display = "block");
2206
+ }), document.addEventListener("click", (e) => {
2207
+ this.searchContainer && !this.searchContainer.contains(e.target) && this.searchResults && (this.searchResults.style.display = "none");
2208
+ }));
2209
+ }
2210
+ performSearch(e) {
2211
+ if (!this.searchResults) return;
2212
+ if (e.trim().length === 0) {
2213
+ this.searchResults.style.display = "none";
2214
+ return;
2215
+ }
2216
+ const { nodeResults: s, edgeResults: t } = this.onSearch(e);
2217
+ if (s.length === 0 && t.length === 0) {
2218
+ this.searchResults.innerHTML = '<div class="f3d-no-results">No results found</div>', this.searchResults.style.display = "block";
2219
+ return;
2220
+ }
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>
2227
+ <div class="f3d-result-type">${this.escapeHtml(a)}</div>
2228
+ </div>
2229
+ `;
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>
2235
+ </div>
2236
+ `;
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;
2240
+ a && (this.onResultClick(a), this.searchResults && (this.searchResults.style.display = "none"), this.searchInput && this.searchInput.blur());
2241
+ });
2242
+ });
2243
+ }
2244
+ escapeHtml(e) {
2245
+ const s = document.createElement("div");
2246
+ return s.textContent = e, s.innerHTML;
2247
+ }
2248
+ dispose() {
2249
+ this.searchContainer && this.searchContainer.parentNode && this.searchContainer.parentNode.removeChild(this.searchContainer);
2250
+ }
2251
+ }
2065
2252
  class Ot {
2066
- constructor(e, o = {}) {
2253
+ constructor(e, s = {}) {
2067
2254
  // Options
2068
2255
  r(this, "options");
2069
2256
  r(this, "container");
@@ -2084,27 +2271,28 @@ class Ot {
2084
2271
  r(this, "raycasterManager");
2085
2272
  r(this, "panelManager");
2086
2273
  r(this, "edgeTooltipManager");
2274
+ r(this, "searchManager", null);
2087
2275
  // Event system
2088
2276
  r(this, "eventCallbacks", /* @__PURE__ */ new Map());
2089
2277
  // State
2090
2278
  r(this, "initialized", !1);
2091
2279
  r(this, "devControls", null);
2092
- this.options = { ...O, ...o }, this.container = ct(e), this.materialFactory = new bt(), this.nodeFactory = new vt(
2280
+ this.options = { ...L, ...s }, this.container = ct(e), this.materialFactory = new xt(), this.nodeFactory = new vt(
2093
2281
  this.materialFactory,
2094
- this.options.nodeRadius ?? O.nodeRadius,
2095
- this.options.lodSegments ?? O.lodSegments
2282
+ this.options.nodeRadius ?? L.nodeRadius,
2283
+ this.options.lodSegments ?? L.lodSegments
2096
2284
  ), this.edgeFactory = new Mt(
2097
2285
  this.materialFactory,
2098
- this.options.edgeColor ?? O.edgeColor,
2099
- this.options.edgeOpacity ?? O.edgeOpacity
2100
- ), this.sceneManager = new ut(this.container, this.options), this.lodManager = new Et(
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(
2101
2289
  this.sceneManager.camera,
2102
- this.options.lodDistances ?? O.lodDistances,
2103
- this.options.enableLOD ?? O.enableLOD
2104
- ), this.frustumCuller = new wt(
2290
+ this.options.lodDistances ?? L.lodDistances,
2291
+ this.options.enableLOD ?? L.enableLOD
2292
+ ), this.frustumCuller = new Et(
2105
2293
  this.sceneManager.camera,
2106
- this.options.enableEdgeCulling ?? O.enableEdgeCulling
2107
- ), this.nodeManager = new mt(this.sceneManager, this.nodeFactory), this.edgeManager = new ft(this.sceneManager, this.nodeManager, this.edgeFactory), this.graphEngine = new Le(
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(
2108
2296
  this.nodeManager.getAllNodes(),
2109
2297
  this.edgeManager.getAllEdges(),
2110
2298
  {
@@ -2114,12 +2302,23 @@ class Ot {
2114
2302
  useBarnesHut: this.options.useBarnesHut,
2115
2303
  barnesHutTheta: this.options.barnesHutTheta
2116
2304
  }
2117
- ), this.rendererManager = new xt(
2305
+ ), this.rendererManager = new bt(
2118
2306
  this.sceneManager,
2119
2307
  () => this.onSimulate(),
2120
2308
  () => this.onRender(),
2121
- this.options.targetFPS ?? O.targetFPS
2122
- ), this.raycasterManager = new Ct(this.sceneManager, this.container), this.panelManager = new Nt(this.container), this.edgeTooltipManager = new zt(), this.setupCallbacks(), this.rendererManager.start(), this.initialized = !0, this.emit("ready");
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, {
2311
+ placeholder: this.options.searchPlaceholder,
2312
+ onSearch: (t) => ({
2313
+ nodeResults: this.searchNodes(t),
2314
+ edgeResults: this.searchEdges(t)
2315
+ }),
2316
+ onResultClick: (t) => {
2317
+ this.focusOnNode(t), setTimeout(() => {
2318
+ this.showNodePanel(t);
2319
+ }, 400);
2320
+ }
2321
+ })), this.setupCallbacks(), this.rendererManager.start(), this.initialized = !0, this.emit("ready");
2123
2322
  }
2124
2323
  /**
2125
2324
  * Sets up internal callbacks
@@ -2127,8 +2326,8 @@ class Ot {
2127
2326
  setupCallbacks() {
2128
2327
  this.raycasterManager.setClickCallback((e) => {
2129
2328
  this.onNodeClick(e);
2130
- }), this.options.onNodeHover && this.raycasterManager.setHoverCallback(this.options.onNodeHover), this.panelManager.setExpandCallback((e, o) => {
2131
- this.expandNode(e, o);
2329
+ }), this.options.onNodeHover && this.raycasterManager.setHoverCallback(this.options.onNodeHover), this.panelManager.setExpandCallback((e, s) => {
2330
+ this.expandNode(e, s);
2132
2331
  }), this.options.panelTemplate && this.panelManager.setPanelTemplate(this.options.panelTemplate), this.options.panelStyles && this.panelManager.setPanelStyles(this.options.panelStyles), this.raycasterManager.setEdgeHoverCallback((e) => {
2133
2332
  this.onEdgeHover(e);
2134
2333
  });
@@ -2139,8 +2338,8 @@ class Ot {
2139
2338
  onEdgeHover(e) {
2140
2339
  if (e) {
2141
2340
  this.edgeManager.highlightEdge(e.edge.source, e.edge.target);
2142
- const o = this.container.getBoundingClientRect(), t = o.left + o.width / 2, n = o.top + o.height / 2;
2143
- this.edgeTooltipManager.show(e.edge, e.sourceNode, e.targetNode, t, n), this.options.onEdgeHover && this.options.onEdgeHover(e.edge, e.sourceNode, e.targetNode), this.emit("edgeHover", e.edge, e.sourceNode, e.targetNode);
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);
2144
2343
  } else
2145
2344
  this.edgeManager.unhighlightCurrentEdge(), this.edgeTooltipManager.hide(), this.options.onEdgeHover && this.options.onEdgeHover(null, null, null), this.emit("edgeHover", null, null, null);
2146
2345
  }
@@ -2148,7 +2347,7 @@ class Ot {
2148
2347
  * Handles node click
2149
2348
  */
2150
2349
  onNodeClick(e) {
2151
- const t = this.edgeManager.getNeighborIds(e.id).map((n) => this.nodeManager.getNode(n)).filter((n) => n !== void 0);
2350
+ const t = this.edgeManager.getNeighborIds(e.id).map((i) => this.nodeManager.getNode(i)).filter((i) => i !== void 0);
2152
2351
  this.options.showPanel !== !1 && this.panelManager.show(e, t), this.options.onNodeClick && this.options.onNodeClick(e), this.emit("nodeClick", e);
2153
2352
  }
2154
2353
  /**
@@ -2156,9 +2355,9 @@ class Ot {
2156
2355
  */
2157
2356
  onSimulate() {
2158
2357
  this.graphEngine.simulate();
2159
- for (const [e, o] of this.nodeManager.getAllNodes())
2160
- if (this.nodeManager.updateNodePosition(e, o.position), this.options.enableLOD) {
2161
- const t = this.lodManager.getLODLevel(o.position);
2358
+ for (const [e, s] of this.nodeManager.getAllNodes())
2359
+ if (this.nodeManager.updateNodePosition(e, s.position), this.options.enableLOD) {
2360
+ const t = this.lodManager.getLODLevel(s.position);
2162
2361
  this.nodeManager.updateNodeLOD(e, t);
2163
2362
  }
2164
2363
  this.edgeManager.updateEdgePositions();
@@ -2177,12 +2376,12 @@ class Ot {
2177
2376
  */
2178
2377
  setData(e) {
2179
2378
  if (this.edgeManager.clear(), this.nodeManager.clear(), e.nodes && Array.isArray(e.nodes))
2180
- for (const o of e.nodes)
2181
- this.addNode(o);
2379
+ for (const s of e.nodes)
2380
+ this.addNode(s);
2182
2381
  if (e.edges && Array.isArray(e.edges))
2183
- for (const o of e.edges)
2184
- this.addEdge(o);
2185
- this.graphEngine = new Le(
2382
+ for (const s of e.edges)
2383
+ this.addEdge(s);
2384
+ this.graphEngine = new Oe(
2186
2385
  this.nodeManager.getAllNodes(),
2187
2386
  this.edgeManager.getAllEdges(),
2188
2387
  {
@@ -2199,10 +2398,10 @@ class Ot {
2199
2398
  * @returns true if added, false if node already exists or invalid
2200
2399
  */
2201
2400
  addNode(e) {
2202
- if (!Ie(e))
2401
+ if (!Re(e))
2203
2402
  return !1;
2204
- const o = this.nodeManager.addNode(e);
2205
- return o && (this.graphEngine.restart(), this.options.onNodeAdd && this.options.onNodeAdd(e), this.emit("nodeAdd", e)), o;
2403
+ const s = this.nodeManager.addNode(e);
2404
+ return s && (this.graphEngine.restart(), this.options.onNodeAdd && this.options.onNodeAdd(e), this.emit("nodeAdd", e)), s;
2206
2405
  }
2207
2406
  /**
2208
2407
  * Removes a node from the graph
@@ -2212,32 +2411,32 @@ class Ot {
2212
2411
  if (!ht(e))
2213
2412
  return !1;
2214
2413
  this.edgeManager.removeEdgesForNode(e);
2215
- const o = this.nodeManager.removeNode(e);
2216
- return o && (this.graphEngine.restart(), this.options.onNodeRemove && this.options.onNodeRemove(e), this.emit("nodeRemove", e), this.panelManager.getCurrentNodeId() === e && this.panelManager.hide()), o;
2414
+ const s = this.nodeManager.removeNode(e);
2415
+ return s && (this.graphEngine.restart(), this.options.onNodeRemove && this.options.onNodeRemove(e), this.emit("nodeRemove", e), this.panelManager.getCurrentNodeId() === e && this.panelManager.hide()), s;
2217
2416
  }
2218
2417
  /**
2219
2418
  * Updates a node's properties
2220
2419
  */
2221
- updateNode(e, o) {
2222
- return this.nodeManager.updateNode(e, o);
2420
+ updateNode(e, s) {
2421
+ return this.nodeManager.updateNode(e, s);
2223
2422
  }
2224
2423
  /**
2225
2424
  * Adds an edge to the graph
2226
2425
  * @returns true if added, false if edge already exists or nodes don't exist
2227
2426
  */
2228
2427
  addEdge(e) {
2229
- if (!Re(e))
2428
+ if (!Fe(e))
2230
2429
  return !1;
2231
- const o = this.edgeManager.addEdge(e);
2232
- return o && (this.graphEngine.setEdges(this.edgeManager.getAllEdges()), this.graphEngine.restart(), this.options.onEdgeAdd && this.options.onEdgeAdd(e), this.emit("edgeAdd", e)), o;
2430
+ 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;
2233
2432
  }
2234
2433
  /**
2235
2434
  * Removes an edge from the graph
2236
2435
  * @returns true if removed, false if not found
2237
2436
  */
2238
- removeEdge(e, o) {
2239
- const t = this.edgeManager.removeEdge(e, o);
2240
- return t && (this.graphEngine.setEdges(this.edgeManager.getAllEdges()), this.options.onEdgeRemove && this.options.onEdgeRemove({ source: e, target: o }), this.emit("edgeRemove", { source: e, target: o })), t;
2437
+ removeEdge(e, s) {
2438
+ const t = this.edgeManager.removeEdge(e, s);
2439
+ return t && (this.graphEngine.setEdges(this.edgeManager.getAllEdges()), this.options.onEdgeRemove && this.options.onEdgeRemove({ source: e, target: s }), this.emit("edgeRemove", { source: e, target: s })), t;
2241
2440
  }
2242
2441
  /**
2243
2442
  * Expands a node by fetching more data
@@ -2245,21 +2444,21 @@ class Ot {
2245
2444
  * @param depth - The depth of expansion (1-3 levels, default 1)
2246
2445
  * @param fetchFn - Optional fetch function to override the default
2247
2446
  */
2248
- async expandNode(e, o = 1, t) {
2249
- const n = t ?? this.options.onExpand;
2250
- if (!n)
2447
+ async expandNode(e, s = 1, t) {
2448
+ const i = t ?? this.options.onExpand;
2449
+ if (!i)
2251
2450
  return console.warn("[ForceGraph3D] No expand callback provided"), !1;
2252
2451
  try {
2253
- const i = await n(e, o);
2254
- if (i.nodes && Array.isArray(i.nodes))
2255
- for (const a of i.nodes)
2452
+ const n = await i(e, s);
2453
+ if (n.nodes && Array.isArray(n.nodes))
2454
+ for (const a of n.nodes)
2256
2455
  this.addNode(a);
2257
- if (i.edges && Array.isArray(i.edges))
2258
- for (const a of i.edges)
2456
+ if (n.edges && Array.isArray(n.edges))
2457
+ for (const a of n.edges)
2259
2458
  this.addEdge(a);
2260
- return this.panelManager.hide(), this.emit("expand", e, i), !0;
2261
- } catch (i) {
2262
- return console.error("[ForceGraph3D] Error expanding node:", i), !1;
2459
+ return this.panelManager.hide(), this.emit("expand", e, n), !0;
2460
+ } catch (n) {
2461
+ return console.error("[ForceGraph3D] Error expanding node:", n), !1;
2263
2462
  }
2264
2463
  }
2265
2464
  /**
@@ -2296,19 +2495,19 @@ class Ot {
2296
2495
  /**
2297
2496
  * Focuses the camera on a specific node with smooth animation
2298
2497
  */
2299
- focusOnNode(e, o = 30) {
2498
+ focusOnNode(e, s = 30) {
2300
2499
  const t = this.nodeManager.getNode(e);
2301
2500
  if (!t) {
2302
2501
  console.warn(`[ForceGraph3D] Node "${e}" not found`);
2303
2502
  return;
2304
2503
  }
2305
- const n = t.position, i = this.sceneManager.camera, a = this.sceneManager.controls, l = i.position.clone().sub(a.target).normalize(), d = {
2306
- x: n.x + l.x * o,
2307
- y: n.y + l.y * o,
2308
- z: n.z + l.z * o
2309
- }, g = { x: i.position.x, y: i.position.y, z: i.position.z }, u = { x: a.target.x, y: a.target.y, z: a.target.z }, x = 800, v = performance.now(), y = () => {
2310
- const f = performance.now() - v, M = Math.min(f / x, 1), C = 1 - Math.pow(1 - M, 3);
2311
- i.position.x = g.x + (d.x - g.x) * C, i.position.y = g.y + (d.y - g.y) * C, i.position.z = g.z + (d.z - g.z) * C, a.target.x = u.x + (n.x - u.x) * C, a.target.y = u.y + (n.y - u.y) * C, a.target.z = u.z + (n.z - u.z) * C, a.update(), M < 1 && requestAnimationFrame(y);
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);
2312
2511
  };
2313
2512
  y();
2314
2513
  }
@@ -2316,13 +2515,13 @@ class Ot {
2316
2515
  * Shows the info panel for a specific node
2317
2516
  */
2318
2517
  showNodePanel(e) {
2319
- const o = this.nodeManager.getNode(e);
2320
- if (!o) {
2518
+ const s = this.nodeManager.getNode(e);
2519
+ if (!s) {
2321
2520
  console.warn(`[ForceGraph3D] Node "${e}" not found`);
2322
2521
  return;
2323
2522
  }
2324
2523
  const t = this.getNeighbors(e);
2325
- this.panelManager.show(o, t);
2524
+ this.panelManager.show(s, t);
2326
2525
  }
2327
2526
  /**
2328
2527
  * Searches nodes by label or ID (case-insensitive)
@@ -2331,28 +2530,28 @@ class Ot {
2331
2530
  searchNodes(e) {
2332
2531
  if (!e || e.trim() === "")
2333
2532
  return [];
2334
- const o = e.toLowerCase().trim(), t = this.nodeManager.getAllNodes(), n = [];
2335
- return t.forEach((i) => {
2336
- var g, u, x;
2337
- const a = (g = i.label) == null ? void 0 : g.toLowerCase().includes(o), l = (u = i.id) == null ? void 0 : u.toLowerCase().includes(o), d = (x = i.type) == null ? void 0 : x.toLowerCase().includes(o);
2338
- (a || l || d) && n.push(i);
2339
- }), n;
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;
2340
2539
  }
2341
2540
  /**
2342
2541
  * Searches edges by relationship (case-insensitive)
2343
2542
  * @returns Array of matching edges with source/target node info
2344
2543
  */
2345
2544
  searchEdges(e) {
2346
- var i;
2545
+ var n;
2347
2546
  if (!e || e.trim() === "")
2348
2547
  return [];
2349
- const o = e.toLowerCase().trim(), t = this.edgeManager.getAllEdges(), n = [];
2548
+ const s = e.toLowerCase().trim(), t = this.edgeManager.getAllEdges(), i = [];
2350
2549
  for (const a of t)
2351
- if ((i = a.relationship) == null ? void 0 : i.toLowerCase().includes(o)) {
2352
- const d = this.nodeManager.getNode(a.source), g = this.nodeManager.getNode(a.target);
2353
- d && g && n.push({ edge: a, sourceNode: d, targetNode: g });
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 });
2354
2553
  }
2355
- return n;
2554
+ return i;
2356
2555
  }
2357
2556
  /**
2358
2557
  * Gets all nodes as an array
@@ -2376,15 +2575,15 @@ class Ot {
2376
2575
  /**
2377
2576
  * Registers an event listener
2378
2577
  */
2379
- on(e, o) {
2380
- this.eventCallbacks.has(e) || this.eventCallbacks.set(e, []), this.eventCallbacks.get(e).push(o);
2578
+ on(e, s) {
2579
+ this.eventCallbacks.has(e) || this.eventCallbacks.set(e, []), this.eventCallbacks.get(e).push(s);
2381
2580
  }
2382
2581
  /**
2383
2582
  * Emits an event
2384
2583
  */
2385
- emit(e, ...o) {
2584
+ emit(e, ...s) {
2386
2585
  const t = this.eventCallbacks.get(e);
2387
- t && t.forEach((n) => n(...o));
2586
+ t && t.forEach((i) => i(...s));
2388
2587
  }
2389
2588
  /**
2390
2589
  * Sets physics parameters
@@ -2459,29 +2658,29 @@ class Ot {
2459
2658
  <div>FPS: <span class="value" id="dev-fps">60</span></div>
2460
2659
  </div>
2461
2660
  `, this.container.appendChild(this.devControls);
2462
- const e = this.devControls.querySelector("#dev-repulsion"), o = this.devControls.querySelector("#dev-attraction"), t = this.devControls.querySelector("#dev-damping");
2661
+ const e = this.devControls.querySelector("#dev-repulsion"), s = this.devControls.querySelector("#dev-attraction"), t = this.devControls.querySelector("#dev-damping");
2463
2662
  e == null || e.addEventListener("input", () => {
2464
- const n = parseFloat(e.value);
2465
- this.setPhysicsParams({ repulsionStrength: n }), this.devControls.querySelector("#dev-repulsion-val").textContent = n.toString();
2466
- }), o == null || o.addEventListener("input", () => {
2467
- const n = parseFloat(o.value) / 1e3;
2468
- this.setPhysicsParams({ attractionStrength: n }), this.devControls.querySelector("#dev-attraction-val").textContent = n.toFixed(3);
2663
+ const i = parseFloat(e.value);
2664
+ this.setPhysicsParams({ repulsionStrength: i }), this.devControls.querySelector("#dev-repulsion-val").textContent = i.toString();
2665
+ }), 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);
2469
2668
  }), t == null || t.addEventListener("input", () => {
2470
- const n = parseFloat(t.value) / 100;
2471
- this.setPhysicsParams({ damping: n }), this.devControls.querySelector("#dev-damping-val").textContent = n.toFixed(2);
2669
+ const i = parseFloat(t.value) / 100;
2670
+ this.setPhysicsParams({ damping: i }), this.devControls.querySelector("#dev-damping-val").textContent = i.toFixed(2);
2472
2671
  }), setInterval(() => {
2473
- const n = this.devControls.querySelector("#dev-node-count"), i = this.devControls.querySelector("#dev-edge-count"), a = this.devControls.querySelector("#dev-fps");
2474
- n && (n.textContent = this.getNodeCount().toString()), i && (i.textContent = this.getEdgeCount().toString()), a && (a.textContent = this.rendererManager.getFPS().toString());
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());
2475
2674
  }, 500);
2476
2675
  }
2477
2676
  /**
2478
2677
  * Destroys the graph and releases all resources
2479
2678
  */
2480
2679
  destroy() {
2481
- this.rendererManager.dispose(), this.panelManager.dispose(), this.raycasterManager.dispose(), this.edgeTooltipManager.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;
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;
2482
2681
  }
2483
2682
  }
2484
- const Fe = [
2683
+ const ke = [
2485
2684
  "Alpha",
2486
2685
  "Beta",
2487
2686
  "Gamma",
@@ -2523,7 +2722,7 @@ const Fe = [
2523
2722
  "partners with",
2524
2723
  "collaborates with",
2525
2724
  "supports"
2526
- ], ke = [
2725
+ ], Ie = [
2527
2726
  16777215,
2528
2727
  // White
2529
2728
  16750950,
@@ -2535,14 +2734,14 @@ const Fe = [
2535
2734
  16746564
2536
2735
  // Darker tangerine
2537
2736
  ];
2538
- function Lt(c = 30) {
2539
- const e = [], o = [];
2540
- for (let n = 0; n < c; n++) {
2541
- const i = n < Fe.length ? Fe[n] : `Node ${n + 1}`;
2737
+ function kt(c = 30) {
2738
+ const e = [], s = [];
2739
+ for (let i = 0; i < c; i++) {
2740
+ const n = i < ke.length ? ke[i] : `Node ${i + 1}`;
2542
2741
  e.push({
2543
- id: `node-${n}`,
2544
- label: i,
2545
- color: ke[n % ke.length],
2742
+ id: `node-${i}`,
2743
+ label: n,
2744
+ color: Ie[i % Ie.length],
2546
2745
  position: {
2547
2746
  x: (Math.random() - 0.5) * 60,
2548
2747
  y: (Math.random() - 0.5) * 60,
@@ -2550,43 +2749,43 @@ function Lt(c = 30) {
2550
2749
  }
2551
2750
  });
2552
2751
  }
2553
- for (let n = 1; n < c; n++) {
2554
- const i = Math.floor(Math.random() * n);
2555
- o.push({
2556
- source: `node-${n}`,
2557
- target: `node-${i}`,
2752
+ for (let i = 1; i < c; i++) {
2753
+ const n = Math.floor(Math.random() * i);
2754
+ s.push({
2755
+ source: `node-${i}`,
2756
+ target: `node-${n}`,
2558
2757
  relationship: Q[Math.floor(Math.random() * Q.length)]
2559
2758
  });
2560
2759
  }
2561
2760
  const t = Math.floor(c * 0.5);
2562
- for (let n = 0; n < t; n++) {
2563
- const i = Math.floor(Math.random() * c);
2761
+ for (let i = 0; i < t; i++) {
2762
+ const n = Math.floor(Math.random() * c);
2564
2763
  let a = Math.floor(Math.random() * c);
2565
- i === a && (a = (a + 1) % c);
2566
- const l = `node-${i}`, d = `node-${a}`;
2567
- o.some(
2568
- (u) => u.source === l && u.target === d || u.source === d && u.target === l
2569
- ) || o.push({
2764
+ n === a && (a = (a + 1) % c);
2765
+ const l = `node-${n}`, d = `node-${a}`;
2766
+ s.some(
2767
+ (g) => g.source === l && g.target === d || g.source === d && g.target === l
2768
+ ) || s.push({
2570
2769
  source: l,
2571
2770
  target: d,
2572
2771
  relationship: Q[Math.floor(Math.random() * Q.length)]
2573
2772
  });
2574
2773
  }
2575
- return { nodes: e, edges: o };
2774
+ return { nodes: e, edges: s };
2576
2775
  }
2577
- function Ft(c = 1e3) {
2578
- const e = [], o = [], t = Math.ceil(c / 50), n = [];
2579
- for (let i = 0; i < t; i++)
2580
- n.push({
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({
2581
2780
  x: (Math.random() - 0.5) * 200,
2582
2781
  y: (Math.random() - 0.5) * 200,
2583
2782
  z: (Math.random() - 0.5) * 200
2584
2783
  });
2585
- for (let i = 0; i < c; i++) {
2586
- const a = n[i % t];
2784
+ for (let n = 0; n < c; n++) {
2785
+ const a = i[n % t];
2587
2786
  e.push({
2588
- id: `node-${i}`,
2589
- label: `N${i}`,
2787
+ id: `node-${n}`,
2788
+ label: `N${n}`,
2590
2789
  position: {
2591
2790
  x: a.x + (Math.random() - 0.5) * 40,
2592
2791
  y: a.y + (Math.random() - 0.5) * 40,
@@ -2594,32 +2793,32 @@ function Ft(c = 1e3) {
2594
2793
  }
2595
2794
  });
2596
2795
  }
2597
- for (let i = 1; i < c; i++) {
2598
- const a = Math.floor(i / 50) * 50, l = a === 0 ? Math.floor(Math.random() * i) : a + Math.floor(Math.random() * Math.min(i - a, 50));
2599
- o.push({
2600
- source: `node-${i}`,
2601
- target: `node-${Math.min(l, i - 1)}`,
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));
2798
+ s.push({
2799
+ source: `node-${n}`,
2800
+ target: `node-${Math.min(l, n - 1)}`,
2602
2801
  relationship: "links to"
2603
2802
  });
2604
2803
  }
2605
- for (let i = 1; i < t; i++) {
2606
- const a = i * 50, l = (i - 1) * 50 + Math.floor(Math.random() * 50);
2607
- o.push({
2804
+ for (let n = 1; n < t; n++) {
2805
+ const a = n * 50, l = (n - 1) * 50 + Math.floor(Math.random() * 50);
2806
+ s.push({
2608
2807
  source: `node-${a}`,
2609
2808
  target: `node-${l}`,
2610
2809
  relationship: "bridges to"
2611
2810
  });
2612
2811
  }
2613
- return { nodes: e, edges: o };
2812
+ return { nodes: e, edges: s };
2614
2813
  }
2615
2814
  export {
2616
- O as DEFAULT_OPTIONS,
2815
+ L as DEFAULT_OPTIONS,
2617
2816
  Ot as ForceGraph3D,
2618
- _ as LODLevel,
2619
- I as createEdgeKey,
2620
- Ft as generateLargeSampleData,
2621
- Lt as generateSampleData,
2622
- Re as validateEdgeData,
2623
- Ie as validateNodeData
2817
+ U as LODLevel,
2818
+ R as createEdgeKey,
2819
+ It as generateLargeSampleData,
2820
+ kt as generateSampleData,
2821
+ Fe as validateEdgeData,
2822
+ Re as validateNodeData
2624
2823
  };
2625
2824
  //# sourceMappingURL=force-3d-graph.js.map