force-3d-graph 1.2.4 → 1.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,11 @@
1
- (function(N,u){typeof exports=="object"&&typeof module<"u"?u(exports,require("three")):typeof define=="function"&&define.amd?define(["exports","three"],u):(N=typeof globalThis<"u"?globalThis:N||self,u(N.ForceGraph3D={},N.THREE))})(this,function(N,u){"use strict";var St=Object.defineProperty;var zt=(N,u,R)=>u in N?St(N,u,{enumerable:!0,configurable:!0,writable:!0,value:R}):N[u]=R;var l=(N,u,R)=>zt(N,typeof u!="symbol"?u+"":u,R);function R(h){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(h){for(const s in h)if(s!=="default"){const t=Object.getOwnPropertyDescriptor(h,s);Object.defineProperty(e,s,t.get?t:{enumerable:!0,get:()=>h[s]})}}return e.default=h,Object.freeze(e)}const m=R(u),P={backgroundColor:657930,cameraPosition:{x:0,y:0,z:80},cameraFov:75,repulsionStrength:200,attractionStrength:.008,damping:.95,useBarnesHut:!0,barnesHutTheta:.5,defaultNodeColor:16750950,nodeRadius:2,nodeSegments:32,enableLOD:!0,lodDistances:[50,100,200],lodSegments:[32,16,8],edgeColor:8947848,edgeOpacity:.4,enableEdgeCulling:!0,showPanel:!0,showSearch:!0,searchPlaceholder:"Search nodes or relationships...",initialViewMode:"3d",showViewToggle:!0,targetFPS:60,maxVisibleNodes:1e4};var H=(h=>(h[h.HIGH=0]="HIGH",h[h.MEDIUM=1]="MEDIUM",h[h.LOW=2]="LOW",h))(H||{});function Ie(){const h=document.createElement("div");return h.id="force-graph-3d-container",h.style.cssText=`
1
+ (function(N,u){typeof exports=="object"&&typeof module<"u"?u(exports,require("three")):typeof define=="function"&&define.amd?define(["exports","three"],u):(N=typeof globalThis<"u"?globalThis:N||self,u(N.ForceGraph3D={},N.THREE))})(this,function(N,u){"use strict";var zt=Object.defineProperty;var Pt=(N,u,j)=>u in N?zt(N,u,{enumerable:!0,configurable:!0,writable:!0,value:j}):N[u]=j;var l=(N,u,j)=>Pt(N,typeof u!="symbol"?u+"":u,j);function j(d){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(d){for(const s in d)if(s!=="default"){const t=Object.getOwnPropertyDescriptor(d,s);Object.defineProperty(e,s,t.get?t:{enumerable:!0,get:()=>d[s]})}}return e.default=d,Object.freeze(e)}const y=j(u),k={backgroundColor:657930,cameraPosition:{x:0,y:0,z:80},cameraFov:75,repulsionStrength:200,attractionStrength:.008,damping:.95,useBarnesHut:!0,barnesHutTheta:.5,defaultNodeColor:16750950,nodeRadius:2,nodeSegments:32,enableLOD:!0,lodDistances:[50,100,200],lodSegments:[32,16,8],edgeColor:8947848,edgeOpacity:.4,enableEdgeCulling:!0,showPanel:!0,showSearch:!0,searchPlaceholder:"Search nodes or relationships...",initialViewMode:"3d",showViewToggle:!0,targetFPS:60,maxVisibleNodes:1e4};var H=(d=>(d[d.HIGH=0]="HIGH",d[d.MEDIUM=1]="MEDIUM",d[d.LOW=2]="LOW",d))(H||{});function De(){const d=document.createElement("div");return d.id="force-graph-3d-container",d.style.cssText=`
2
2
  width: 100%;
3
3
  height: 100%;
4
4
  position: absolute;
5
5
  top: 0;
6
6
  left: 0;
7
7
  overflow: hidden;
8
- `,document.body.appendChild(h),h}function De(h){return h&&h instanceof HTMLElement?h:(console.warn("[ForceGraph3D] No container provided, creating one automatically"),Ie())}function ce(h){const e=h.getBoundingClientRect();return{width:e.width||window.innerWidth,height:e.height||window.innerHeight}}function J(h){if(!h||typeof h!="object")return console.warn("[ForceGraph3D] Invalid node: must be an object"),!1;const e=h;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&&!Ae(e.position)?(console.warn("[ForceGraph3D] Invalid node: position must have x, y, z numbers"),!1):!0}function ee(h){if(!h||typeof h!="object")return console.warn("[ForceGraph3D] Invalid edge: must be an object"),!1;const e=h;return typeof e.source!="string"||e.source.trim()===""?(console.warn("[ForceGraph3D] Invalid edge: source must be a non-empty string"),!1):typeof e.target!="string"||e.target.trim()===""?(console.warn("[ForceGraph3D] Invalid edge: target must be a non-empty string"),!1):!0}function Fe(h){return typeof h!="string"||h.trim()===""?(console.warn("[ForceGraph3D] Invalid node ID: must be a non-empty string"),!1):!0}function Ae(h){if(!h||typeof h!="object")return!1;const e=h;return typeof e.x=="number"&&typeof e.y=="number"&&typeof e.z=="number"}function D(h,e){return h===e?`${h}-${e}`:h<e?`${h}-${e}`:`${e}-${h}`}const he={type:"change"},te={type:"start"},de={type:"end"},X=new u.Ray,pe=new u.Plane,je=Math.cos(70*u.MathUtils.DEG2RAD);class Re extends u.EventDispatcher{constructor(e,s){super(),this.object=e,this.domElement=s,this.domElement.style.touchAction="none",this.enabled=!0,this.target=new u.Vector3,this.cursor=new u.Vector3,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=.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:u.MOUSE.ROTATE,MIDDLE:u.MOUSE.DOLLY,RIGHT:u.MOUSE.PAN},this.touches={ONE:u.TOUCH.ROTATE,TWO:u.TOUCH.DOLLY_PAN},this.target0=this.target.clone(),this.position0=this.object.position.clone(),this.zoom0=this.object.zoom,this._domElementKeyEvents=null,this.getPolarAngle=function(){return r.phi},this.getAzimuthalAngle=function(){return r.theta},this.getDistance=function(){return this.object.position.distanceTo(this.target)},this.listenToKeyEvents=function(n){n.addEventListener("keydown",re),this._domElementKeyEvents=n},this.stopListenToKeyEvents=function(){this._domElementKeyEvents.removeEventListener("keydown",re),this._domElementKeyEvents=null},this.saveState=function(){t.target0.copy(t.target),t.position0.copy(t.object.position),t.zoom0=t.object.zoom},this.reset=function(){t.target.copy(t.target0),t.object.position.copy(t.position0),t.object.zoom=t.zoom0,t.object.updateProjectionMatrix(),t.dispatchEvent(he),t.update(),o=i.NONE},this.update=function(){const n=new u.Vector3,g=new u.Quaternion().setFromUnitVectors(e.up,new u.Vector3(0,1,0)),M=g.clone().invert(),C=new u.Vector3,S=new u.Quaternion,A=new u.Vector3,k=2*Math.PI;return function(Nt=null){const Le=t.object.position;n.copy(Le).sub(t.target),n.applyQuaternion(g),r.setFromVector3(n),t.autoRotate&&o===i.NONE&&B(at(Nt)),t.enableDamping?(r.theta+=c.theta*t.dampingFactor,r.phi+=c.phi*t.dampingFactor):(r.theta+=c.theta,r.phi+=c.phi);let L=t.minAzimuthAngle,I=t.maxAzimuthAngle;isFinite(L)&&isFinite(I)&&(L<-Math.PI?L+=k:L>Math.PI&&(L-=k),I<-Math.PI?I+=k:I>Math.PI&&(I-=k),L<=I?r.theta=Math.max(L,Math.min(I,r.theta)):r.theta=r.theta>(L+I)/2?Math.max(L,r.theta):Math.min(I,r.theta)),r.phi=Math.max(t.minPolarAngle,Math.min(t.maxPolarAngle,r.phi)),r.makeSafe(),t.enableDamping===!0?t.target.addScaledVector(p,t.dampingFactor):t.target.add(p),t.target.sub(t.cursor),t.target.clampLength(t.minTargetRadius,t.maxTargetRadius),t.target.add(t.cursor),t.zoomToCursor&&j||t.object.isOrthographicCamera?r.radius=ne(r.radius):r.radius=ne(r.radius*d),n.setFromSpherical(r),n.applyQuaternion(M),Le.copy(t.target).add(n),t.object.lookAt(t.target),t.enableDamping===!0?(c.theta*=1-t.dampingFactor,c.phi*=1-t.dampingFactor,p.multiplyScalar(1-t.dampingFactor)):(c.set(0,0,0),p.set(0,0,0));let le=!1;if(t.zoomToCursor&&j){let K=null;if(t.object.isPerspectiveCamera){const U=n.length();K=ne(U*d);const Q=U-K;t.object.position.addScaledVector(Y,Q),t.object.updateMatrixWorld()}else if(t.object.isOrthographicCamera){const U=new u.Vector3(T.x,T.y,0);U.unproject(t.object),t.object.zoom=Math.max(t.minZoom,Math.min(t.maxZoom,t.object.zoom/d)),t.object.updateProjectionMatrix(),le=!0;const Q=new u.Vector3(T.x,T.y,0);Q.unproject(t.object),t.object.position.sub(Q).add(U),t.object.updateMatrixWorld(),K=n.length()}else console.warn("WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled."),t.zoomToCursor=!1;K!==null&&(this.screenSpacePanning?t.target.set(0,0,-1).transformDirection(t.object.matrix).multiplyScalar(K).add(t.object.position):(X.origin.copy(t.object.position),X.direction.set(0,0,-1).transformDirection(t.object.matrix),Math.abs(t.object.up.dot(X.direction))<je?e.lookAt(t.target):(pe.setFromNormalAndCoplanarPoint(t.object.up,t.target),X.intersectPlane(pe,t.target))))}else t.object.isOrthographicCamera&&(t.object.zoom=Math.max(t.minZoom,Math.min(t.maxZoom,t.object.zoom/d)),t.object.updateProjectionMatrix(),le=!0);return d=1,j=!1,le||C.distanceToSquared(t.object.position)>a||8*(1-S.dot(t.object.quaternion))>a||A.distanceToSquared(t.target)>0?(t.dispatchEvent(he),C.copy(t.object.position),S.copy(t.object.quaternion),A.copy(t.target),!0):!1}}(),this.dispose=function(){t.domElement.removeEventListener("contextmenu",Te),t.domElement.removeEventListener("pointerdown",ze),t.domElement.removeEventListener("pointercancel",V),t.domElement.removeEventListener("wheel",ke),t.domElement.removeEventListener("pointermove",ae),t.domElement.removeEventListener("pointerup",V),t._domElementKeyEvents!==null&&(t._domElementKeyEvents.removeEventListener("keydown",re),t._domElementKeyEvents=null)};const t=this,i={NONE:-1,ROTATE:0,DOLLY:1,PAN:2,TOUCH_ROTATE:3,TOUCH_PAN:4,TOUCH_DOLLY_PAN:5,TOUCH_DOLLY_ROTATE:6};let o=i.NONE;const a=1e-6,r=new u.Spherical,c=new u.Spherical;let d=1;const p=new u.Vector3,b=new u.Vector2,y=new u.Vector2,f=new u.Vector2,x=new u.Vector2,v=new u.Vector2,w=new u.Vector2,z=new u.Vector2,F=new u.Vector2,O=new u.Vector2,Y=new u.Vector3,T=new u.Vector2;let j=!1;const E=[],q={};let se=!1;function at(n){return n!==null?2*Math.PI/60*t.autoRotateSpeed*n:2*Math.PI/60/60*t.autoRotateSpeed}function W(n){const g=Math.abs(n*.01);return Math.pow(.95,t.zoomSpeed*g)}function B(n){c.theta-=n}function Z(n){c.phi-=n}const me=function(){const n=new u.Vector3;return function(M,C){n.setFromMatrixColumn(C,0),n.multiplyScalar(-M),p.add(n)}}(),ye=function(){const n=new u.Vector3;return function(M,C){t.screenSpacePanning===!0?n.setFromMatrixColumn(C,1):(n.setFromMatrixColumn(C,0),n.crossVectors(t.object.up,n)),n.multiplyScalar(M),p.add(n)}}(),$=function(){const n=new u.Vector3;return function(M,C){const S=t.domElement;if(t.object.isPerspectiveCamera){const A=t.object.position;n.copy(A).sub(t.target);let k=n.length();k*=Math.tan(t.object.fov/2*Math.PI/180),me(2*M*k/S.clientHeight,t.object.matrix),ye(2*C*k/S.clientHeight,t.object.matrix)}else t.object.isOrthographicCamera?(me(M*(t.object.right-t.object.left)/t.object.zoom/S.clientWidth,t.object.matrix),ye(C*(t.object.top-t.object.bottom)/t.object.zoom/S.clientHeight,t.object.matrix)):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."),t.enablePan=!1)}}();function ie(n){t.object.isPerspectiveCamera||t.object.isOrthographicCamera?d/=n:(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),t.enableZoom=!1)}function xe(n){t.object.isPerspectiveCamera||t.object.isOrthographicCamera?d*=n:(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),t.enableZoom=!1)}function oe(n,g){if(!t.zoomToCursor)return;j=!0;const M=t.domElement.getBoundingClientRect(),C=n-M.left,S=g-M.top,A=M.width,k=M.height;T.x=C/A*2-1,T.y=-(S/k)*2+1,Y.set(T.x,T.y,1).unproject(t.object).sub(t.object.position).normalize()}function ne(n){return Math.max(t.minDistance,Math.min(t.maxDistance,n))}function be(n){b.set(n.clientX,n.clientY)}function rt(n){oe(n.clientX,n.clientX),z.set(n.clientX,n.clientY)}function ve(n){x.set(n.clientX,n.clientY)}function lt(n){y.set(n.clientX,n.clientY),f.subVectors(y,b).multiplyScalar(t.rotateSpeed);const g=t.domElement;B(2*Math.PI*f.x/g.clientHeight),Z(2*Math.PI*f.y/g.clientHeight),b.copy(y),t.update()}function ct(n){F.set(n.clientX,n.clientY),O.subVectors(F,z),O.y>0?ie(W(O.y)):O.y<0&&xe(W(O.y)),z.copy(F),t.update()}function ht(n){v.set(n.clientX,n.clientY),w.subVectors(v,x).multiplyScalar(t.panSpeed),$(w.x,w.y),x.copy(v),t.update()}function dt(n){oe(n.clientX,n.clientY),n.deltaY<0?xe(W(n.deltaY)):n.deltaY>0&&ie(W(n.deltaY)),t.update()}function pt(n){let g=!1;switch(n.code){case t.keys.UP:n.ctrlKey||n.metaKey||n.shiftKey?Z(2*Math.PI*t.rotateSpeed/t.domElement.clientHeight):$(0,t.keyPanSpeed),g=!0;break;case t.keys.BOTTOM:n.ctrlKey||n.metaKey||n.shiftKey?Z(-2*Math.PI*t.rotateSpeed/t.domElement.clientHeight):$(0,-t.keyPanSpeed),g=!0;break;case t.keys.LEFT:n.ctrlKey||n.metaKey||n.shiftKey?B(2*Math.PI*t.rotateSpeed/t.domElement.clientHeight):$(t.keyPanSpeed,0),g=!0;break;case t.keys.RIGHT:n.ctrlKey||n.metaKey||n.shiftKey?B(-2*Math.PI*t.rotateSpeed/t.domElement.clientHeight):$(-t.keyPanSpeed,0),g=!0;break}g&&(n.preventDefault(),t.update())}function Me(n){if(E.length===1)b.set(n.pageX,n.pageY);else{const g=G(n),M=.5*(n.pageX+g.x),C=.5*(n.pageY+g.y);b.set(M,C)}}function we(n){if(E.length===1)x.set(n.pageX,n.pageY);else{const g=G(n),M=.5*(n.pageX+g.x),C=.5*(n.pageY+g.y);x.set(M,C)}}function Ce(n){const g=G(n),M=n.pageX-g.x,C=n.pageY-g.y,S=Math.sqrt(M*M+C*C);z.set(0,S)}function gt(n){t.enableZoom&&Ce(n),t.enablePan&&we(n)}function ut(n){t.enableZoom&&Ce(n),t.enableRotate&&Me(n)}function Ee(n){if(E.length==1)y.set(n.pageX,n.pageY);else{const M=G(n),C=.5*(n.pageX+M.x),S=.5*(n.pageY+M.y);y.set(C,S)}f.subVectors(y,b).multiplyScalar(t.rotateSpeed);const g=t.domElement;B(2*Math.PI*f.x/g.clientHeight),Z(2*Math.PI*f.y/g.clientHeight),b.copy(y)}function Ne(n){if(E.length===1)v.set(n.pageX,n.pageY);else{const g=G(n),M=.5*(n.pageX+g.x),C=.5*(n.pageY+g.y);v.set(M,C)}w.subVectors(v,x).multiplyScalar(t.panSpeed),$(w.x,w.y),x.copy(v)}function Se(n){const g=G(n),M=n.pageX-g.x,C=n.pageY-g.y,S=Math.sqrt(M*M+C*C);F.set(0,S),O.set(0,Math.pow(F.y/z.y,t.zoomSpeed)),ie(O.y),z.copy(F);const A=(n.pageX+g.x)*.5,k=(n.pageY+g.y)*.5;oe(A,k)}function ft(n){t.enableZoom&&Se(n),t.enablePan&&Ne(n)}function mt(n){t.enableZoom&&Se(n),t.enableRotate&&Ee(n)}function ze(n){t.enabled!==!1&&(E.length===0&&(t.domElement.setPointerCapture(n.pointerId),t.domElement.addEventListener("pointermove",ae),t.domElement.addEventListener("pointerup",V)),Ct(n),n.pointerType==="touch"?Mt(n):yt(n))}function ae(n){t.enabled!==!1&&(n.pointerType==="touch"?wt(n):xt(n))}function V(n){Et(n),E.length===0&&(t.domElement.releasePointerCapture(n.pointerId),t.domElement.removeEventListener("pointermove",ae),t.domElement.removeEventListener("pointerup",V)),t.dispatchEvent(de),o=i.NONE}function yt(n){let g;switch(n.button){case 0:g=t.mouseButtons.LEFT;break;case 1:g=t.mouseButtons.MIDDLE;break;case 2:g=t.mouseButtons.RIGHT;break;default:g=-1}switch(g){case u.MOUSE.DOLLY:if(t.enableZoom===!1)return;rt(n),o=i.DOLLY;break;case u.MOUSE.ROTATE:if(n.ctrlKey||n.metaKey||n.shiftKey){if(t.enablePan===!1)return;ve(n),o=i.PAN}else{if(t.enableRotate===!1)return;be(n),o=i.ROTATE}break;case u.MOUSE.PAN:if(n.ctrlKey||n.metaKey||n.shiftKey){if(t.enableRotate===!1)return;be(n),o=i.ROTATE}else{if(t.enablePan===!1)return;ve(n),o=i.PAN}break;default:o=i.NONE}o!==i.NONE&&t.dispatchEvent(te)}function xt(n){switch(o){case i.ROTATE:if(t.enableRotate===!1)return;lt(n);break;case i.DOLLY:if(t.enableZoom===!1)return;ct(n);break;case i.PAN:if(t.enablePan===!1)return;ht(n);break}}function ke(n){t.enabled===!1||t.enableZoom===!1||o!==i.NONE||(n.preventDefault(),t.dispatchEvent(te),dt(bt(n)),t.dispatchEvent(de))}function bt(n){const g=n.deltaMode,M={clientX:n.clientX,clientY:n.clientY,deltaY:n.deltaY};switch(g){case 1:M.deltaY*=16;break;case 2:M.deltaY*=100;break}return n.ctrlKey&&!se&&(M.deltaY*=10),M}function vt(n){n.key==="Control"&&(se=!0,document.addEventListener("keyup",Pe,{passive:!0,capture:!0}))}function Pe(n){n.key==="Control"&&(se=!1,document.removeEventListener("keyup",Pe,{passive:!0,capture:!0}))}function re(n){t.enabled===!1||t.enablePan===!1||pt(n)}function Mt(n){switch(Oe(n),E.length){case 1:switch(t.touches.ONE){case u.TOUCH.ROTATE:if(t.enableRotate===!1)return;Me(n),o=i.TOUCH_ROTATE;break;case u.TOUCH.PAN:if(t.enablePan===!1)return;we(n),o=i.TOUCH_PAN;break;default:o=i.NONE}break;case 2:switch(t.touches.TWO){case u.TOUCH.DOLLY_PAN:if(t.enableZoom===!1&&t.enablePan===!1)return;gt(n),o=i.TOUCH_DOLLY_PAN;break;case u.TOUCH.DOLLY_ROTATE:if(t.enableZoom===!1&&t.enableRotate===!1)return;ut(n),o=i.TOUCH_DOLLY_ROTATE;break;default:o=i.NONE}break;default:o=i.NONE}o!==i.NONE&&t.dispatchEvent(te)}function wt(n){switch(Oe(n),o){case i.TOUCH_ROTATE:if(t.enableRotate===!1)return;Ee(n),t.update();break;case i.TOUCH_PAN:if(t.enablePan===!1)return;Ne(n),t.update();break;case i.TOUCH_DOLLY_PAN:if(t.enableZoom===!1&&t.enablePan===!1)return;ft(n),t.update();break;case i.TOUCH_DOLLY_ROTATE:if(t.enableZoom===!1&&t.enableRotate===!1)return;mt(n),t.update();break;default:o=i.NONE}}function Te(n){t.enabled!==!1&&n.preventDefault()}function Ct(n){E.push(n.pointerId)}function Et(n){delete q[n.pointerId];for(let g=0;g<E.length;g++)if(E[g]==n.pointerId){E.splice(g,1);return}}function Oe(n){let g=q[n.pointerId];g===void 0&&(g=new u.Vector2,q[n.pointerId]=g),g.set(n.pageX,n.pageY)}function G(n){const g=n.pointerId===E[0]?E[1]:E[0];return q[g]}t.domElement.addEventListener("contextmenu",Te),t.domElement.addEventListener("pointerdown",ze),t.domElement.addEventListener("pointercancel",V),t.domElement.addEventListener("wheel",ke,{passive:!1}),document.addEventListener("keydown",vt,{passive:!0,capture:!0}),this.update()}}class He{constructor(e,s){l(this,"scene");l(this,"camera");l(this,"renderer");l(this,"controls");l(this,"container");l(this,"resizeHandler");this.container=e,this.scene=new m.Scene,this.scene.background=new m.Color(s.backgroundColor??657930);const{width:t,height:i}=ce(e),o=s.cameraFov??75;this.camera=new m.PerspectiveCamera(o,t/i,.1,2e3);const a=s.cameraPosition??{x:0,y:0,z:80};this.camera.position.set(a.x,a.y,a.z),this.renderer=new m.WebGLRenderer({antialias:!0,alpha:!0,powerPreference:"high-performance"}),this.renderer.setSize(t,i),this.renderer.setPixelRatio(Math.min(window.devicePixelRatio,2)),this.renderer.toneMapping=m.ACESFilmicToneMapping,this.renderer.toneMappingExposure=1,this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=m.PCFSoftShadowMap,e.appendChild(this.renderer.domElement),this.controls=new Re(this.camera,this.renderer.domElement),this.controls.enableDamping=!0,this.controls.dampingFactor=.05,this.controls.rotateSpeed=.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)}setupLighting(){const e=new m.AmbientLight(16777215,.4);this.scene.add(e);const s=new m.DirectionalLight(16777215,.9);s.position.set(50,60,40),s.castShadow=!0,s.shadow.mapSize.width=1024,s.shadow.mapSize.height=1024,this.scene.add(s);const t=new m.DirectionalLight(16773344,.4);t.position.set(-50,30,-40),this.scene.add(t);const i=new m.DirectionalLight(16777215,.3);i.position.set(0,-30,-50),this.scene.add(i);const o=new m.PointLight(16750950,.5,150);o.position.set(40,20,40),this.scene.add(o);const a=new m.PointLight(16764057,.4,150);a.position.set(-40,-20,40),this.scene.add(a);const r=new m.PointLight(6724095,.2,100);r.position.set(0,40,-40),this.scene.add(r)}onWindowResize(){const{width:e,height:s}=ce(this.container);this.camera.aspect=e/s,this.camera.updateProjectionMatrix(),this.renderer.setSize(e,s)}add(e){this.scene.add(e)}remove(e){this.scene.remove(e)}render(){this.controls.update(),this.renderer.render(this.scene,this.camera)}getCameraPosition(){return{x:this.camera.position.x,y:this.camera.position.y,z:this.camera.position.z}}getCameraDirection(){const e=new m.Vector3;return this.camera.getWorldDirection(e),e}dispose(){for(window.removeEventListener("resize",this.resizeHandler),this.controls.dispose(),this.renderer.dispose(),this.renderer.domElement.parentNode&&this.renderer.domElement.parentNode.removeChild(this.renderer.domElement);this.scene.children.length>0;){const e=this.scene.children[0];this.scene.remove(e)}}}class $e{constructor(e,s){l(this,"sceneManager");l(this,"nodeFactory");l(this,"nodes",new Map);l(this,"nodeObjects",new Map);this.sceneManager=e,this.nodeFactory=s}hasNode(e){return this.nodes.has(e)}addNode(e,s=0){if(!J(e))return!1;if(this.nodes.has(e.id))return console.warn(`[ForceGraph3D] Node with id "${e.id}" already exists`),!1;const t=e.position??{x:(Math.random()-.5)*50,y:(Math.random()-.5)*50,z:(Math.random()-.5)*50},i={...e,position:t,velocity:{x:0,y:0,z:0},mass:1},o=this.nodeFactory.createNode({...e,position:t},s);return this.sceneManager.add(o.group),this.nodes.set(e.id,i),this.nodeObjects.set(e.id,o),!0}removeNode(e){const s=this.nodes.get(e),t=this.nodeObjects.get(e);return!s||!t?!1:(this.sceneManager.remove(t.group),this.nodeFactory.disposeNode(t),this.nodes.delete(e),this.nodeObjects.delete(e),!0)}updateNode(e,s){const t=this.nodes.get(e),i=this.nodeObjects.get(e);return!t||!i?(console.warn(`[ForceGraph3D] Node "${e}" not found`),!1):(s.label!==void 0&&(t.label=s.label,this.nodeFactory.updateNodeLabel(i,s.label)),s.color!==void 0&&(t.color=s.color,this.nodeFactory.updateNodeColor(i,s.color)),Object.keys(s).forEach(o=>{o!=="id"&&o!=="label"&&o!=="color"&&o!=="position"&&(t[o]=s[o])}),!0)}updateNodePosition(e,s){const t=this.nodes.get(e),i=this.nodeObjects.get(e);t&&i&&(t.position=s,i.group.position.set(s.x,s.y,s.z))}updateNodeLOD(e,s){const t=this.nodeObjects.get(e);t&&this.nodeFactory.updateNodeLOD(t,s)}getNode(e){return this.nodes.get(e)}getNodeObject(e){return this.nodeObjects.get(e)}getAllNodes(){return this.nodes}getAllNodeObjects(){const e=[];return this.nodeObjects.forEach(s=>{e.push(s.group)}),e}getAllSpheres(){const e=[];return this.nodeObjects.forEach(s=>{e.push(s.sphere)}),e}getNodeCount(){return this.nodes.size}clear(){this.nodes.forEach((e,s)=>{this.removeNode(s)})}dispose(){this.clear()}}class Ge{constructor(e,s,t){l(this,"sceneManager");l(this,"nodeManager");l(this,"edgeFactory");l(this,"edges",[]);l(this,"edgeObjects",[]);l(this,"edgeKeySet",new Set);l(this,"highlightedEdgeKey",null);this.sceneManager=e,this.nodeManager=s,this.edgeFactory=t}hasEdge(e,s){const t=D(e,s);return this.edgeKeySet.has(t)}addEdge(e){if(!ee(e))return!1;if(!this.nodeManager.hasNode(e.source))return console.warn(`[ForceGraph3D] Source node "${e.source}" does not exist`),!1;if(!this.nodeManager.hasNode(e.target))return console.warn(`[ForceGraph3D] Target node "${e.target}" does not exist`),!1;const s=D(e.source,e.target);if(this.edgeKeySet.has(s))return console.warn(`[ForceGraph3D] Edge "${e.source}" -> "${e.target}" already exists`),!1;const t=this.nodeManager.getNode(e.source),i=this.nodeManager.getNode(e.target),o=this.edgeFactory.createEdge(e,t,i,t.position,i.position);return this.sceneManager.add(o.line),this.edges.push(e),this.edgeObjects.push(o),this.edgeKeySet.add(s),!0}removeEdge(e,s){const t=D(e,s);if(!this.edgeKeySet.has(t))return!1;const i=this.edges.findIndex(a=>D(a.source,a.target)===t);if(i===-1)return!1;const o=this.edgeObjects[i];return this.sceneManager.remove(o.line),this.edgeFactory.disposeEdge(o),this.edges.splice(i,1),this.edgeObjects.splice(i,1),this.edgeKeySet.delete(t),this.highlightedEdgeKey===t&&(this.highlightedEdgeKey=null),!0}highlightEdge(e,s){const t=D(e,s);this.highlightedEdgeKey&&this.highlightedEdgeKey!==t&&this.unhighlightCurrentEdge();const i=this.edges.findIndex(o=>D(o.source,o.target)===t);i!==-1&&(this.edgeFactory.highlightEdge(this.edgeObjects[i]),this.highlightedEdgeKey=t)}unhighlightCurrentEdge(){if(!this.highlightedEdgeKey)return;const e=this.edges.findIndex(s=>D(s.source,s.target)===this.highlightedEdgeKey);e!==-1&&this.edgeFactory.unhighlightEdge(this.edgeObjects[e]),this.highlightedEdgeKey=null}removeEdgesForNode(e){const s=[];this.edges.forEach(t=>{(t.source===e||t.target===e)&&s.push({source:t.source,target:t.target})}),s.forEach(t=>{this.removeEdge(t.source,t.target)})}getEdgesForNode(e){return this.edges.filter(s=>s.source===e||s.target===e)}getNeighborIds(e){const s=[];return this.edges.forEach(t=>{t.source===e?s.push(t.target):t.target===e&&s.push(t.source)}),[...new Set(s)]}updateEdgePositions(){this.edgeObjects.forEach((e,s)=>{const t=this.edges[s],i=this.nodeManager.getNode(t.source),o=this.nodeManager.getNode(t.target);i&&o&&this.edgeFactory.updateEdgePositions(e,i.position,o.position)})}getAllEdges(){return this.edges}getAllEdgeLines(){return this.edgeObjects.map(e=>e.line)}getEdgeCount(){return this.edges.length}clear(){this.edgeObjects.forEach(e=>{this.sceneManager.remove(e.line),this.edgeFactory.disposeEdge(e)}),this.edges=[],this.edgeObjects=[],this.edgeKeySet.clear(),this.highlightedEdgeKey=null}dispose(){this.clear()}}class ge{constructor(e,s,t={}){l(this,"nodes");l(this,"edges");l(this,"repulsionStrength");l(this,"attractionStrength");l(this,"damping");l(this,"useBarnesHut");l(this,"barnesHutTheta");l(this,"alpha",1);l(this,"alphaDecay",.0228);l(this,"alphaMin",.001);l(this,"alphaTarget",0);this.nodes=e,this.edges=s,this.repulsionStrength=t.repulsionStrength??100,this.attractionStrength=t.attractionStrength??.01,this.damping=t.damping??.9,this.useBarnesHut=t.useBarnesHut??!1,this.barnesHutTheta=t.barnesHutTheta??.5}simulate(){if(this.alpha<this.alphaMin)return;const e=this.nodes.size;(this.useBarnesHut||e>=1e3)&&e>=100?this.calculateRepulsionBarnesHut():this.calculateRepulsionBruteForce(),this.calculateAttraction(),this.applyForces(),this.alpha+=(this.alphaTarget-this.alpha)*this.alphaDecay}calculateRepulsionBruteForce(){const e=Array.from(this.nodes.values()),s=e.length;for(let t=0;t<s;t++){const i=e[t];for(let o=t+1;o<s;o++){const a=e[o],r=a.position.x-i.position.x,c=a.position.y-i.position.y,d=a.position.z-i.position.z;let p=r*r+c*c+d*d;p<.01&&(p=.01);const b=Math.sqrt(p),y=this.repulsionStrength*this.alpha/p,f=r/b*y,x=c/b*y,v=d/b*y;i.velocity.x-=f/i.mass,i.velocity.y-=x/i.mass,i.velocity.z-=v/i.mass,a.velocity.x+=f/a.mass,a.velocity.y+=x/a.mass,a.velocity.z+=v/a.mass}}}calculateRepulsionBarnesHut(){const e=Array.from(this.nodes.values()),s=new Ye(e);for(const t of e)this.calculateForceFromOctree(t,s.root)}calculateForceFromOctree(e,s){if(s.isLeaf){s.node&&s.node.id!==e.id&&this.applyRepulsionBetween(e,s.node);return}if(s.mass===0)return;const t=s.centerOfMass.x-e.position.x,i=s.centerOfMass.y-e.position.y,o=s.centerOfMass.z-e.position.z,a=Math.sqrt(t*t+i*i+o*o);if(s.size/a<this.barnesHutTheta){const r=Math.max(a*a,.01),c=this.repulsionStrength*this.alpha*s.mass/r;e.velocity.x-=t/a*c/e.mass,e.velocity.y-=i/a*c/e.mass,e.velocity.z-=o/a*c/e.mass}else for(const r of s.children)r&&this.calculateForceFromOctree(e,r)}applyRepulsionBetween(e,s){const t=s.position.x-e.position.x,i=s.position.y-e.position.y,o=s.position.z-e.position.z;let a=t*t+i*i+o*o;a<.01&&(a=.01);const r=Math.sqrt(a),c=this.repulsionStrength*this.alpha/a;e.velocity.x-=t/r*c/e.mass,e.velocity.y-=i/r*c/e.mass,e.velocity.z-=o/r*c/e.mass}calculateAttraction(){for(const e of this.edges){const s=this.nodes.get(e.source),t=this.nodes.get(e.target);if(!s||!t)continue;const i=t.position.x-s.position.x,o=t.position.y-s.position.y,a=t.position.z-s.position.z,r=Math.sqrt(i*i+o*o+a*a);if(r<.01)continue;const d=(r-15)*this.attractionStrength*this.alpha,p=i/r*d,b=o/r*d,y=a/r*d;s.velocity.x+=p/s.mass,s.velocity.y+=b/s.mass,s.velocity.z+=y/s.mass,t.velocity.x-=p/t.mass,t.velocity.y-=b/t.mass,t.velocity.z-=y/t.mass}}applyForces(){for(const e of this.nodes.values())e.velocity.x*=this.damping,e.velocity.y*=this.damping,e.velocity.z*=this.damping,e.position.x+=e.velocity.x,e.position.y+=e.velocity.y,e.position.z+=e.velocity.z}setEdges(e){this.edges=e}restart(){this.alpha=1}getAlpha(){return this.alpha}setPhysicsParams(e){e.repulsionStrength!==void 0&&(this.repulsionStrength=e.repulsionStrength),e.attractionStrength!==void 0&&(this.attractionStrength=e.attractionStrength),e.damping!==void 0&&(this.damping=e.damping)}}class Ye{constructor(e){l(this,"root");const s=this.calculateBounds(e);this.root=this.buildTree(e,s)}calculateBounds(e){if(e.length===0)return{min:{x:-100,y:-100,z:-100},max:{x:100,y:100,z:100}};const s={x:1/0,y:1/0,z:1/0},t={x:-1/0,y:-1/0,z:-1/0};for(const o of e)s.x=Math.min(s.x,o.position.x),s.y=Math.min(s.y,o.position.y),s.z=Math.min(s.z,o.position.z),t.x=Math.max(t.x,o.position.x),t.y=Math.max(t.y,o.position.y),t.z=Math.max(t.z,o.position.z);const i=10;return s.x-=i,s.y-=i,s.z-=i,t.x+=i,t.y+=i,t.z+=i,{min:s,max:t}}buildTree(e,s,t=0){const i=Math.max(s.max.x-s.min.x,s.max.y-s.min.y,s.max.z-s.min.z);if(e.length===0)return{bounds:s,size:i,centerOfMass:{x:0,y:0,z:0},mass:0,isLeaf:!0,node:null,children:[]};if(e.length===1||t>20){let f=0;const x={x:0,y:0,z:0};for(const v of e)f+=v.mass,x.x+=v.position.x*v.mass,x.y+=v.position.y*v.mass,x.z+=v.position.z*v.mass;return f>0&&(x.x/=f,x.y/=f,x.z/=f),{bounds:s,size:i,centerOfMass:x,mass:f,isLeaf:!0,node:e[0],children:[]}}const o=(s.min.x+s.max.x)/2,a=(s.min.y+s.max.y)/2,r=(s.min.z+s.max.z)/2,c=[[],[],[],[],[],[],[],[]];for(const f of e){const x=(f.position.x>=o?1:0)+(f.position.y>=a?2:0)+(f.position.z>=r?4:0);c[x].push(f)}const d=[{min:{x:s.min.x,y:s.min.y,z:s.min.z},max:{x:o,y:a,z:r}},{min:{x:o,y:s.min.y,z:s.min.z},max:{x:s.max.x,y:a,z:r}},{min:{x:s.min.x,y:a,z:s.min.z},max:{x:o,y:s.max.y,z:r}},{min:{x:o,y:a,z:s.min.z},max:{x:s.max.x,y:s.max.y,z:r}},{min:{x:s.min.x,y:s.min.y,z:r},max:{x:o,y:a,z:s.max.z}},{min:{x:o,y:s.min.y,z:r},max:{x:s.max.x,y:a,z:s.max.z}},{min:{x:s.min.x,y:a,z:r},max:{x:o,y:s.max.y,z:s.max.z}},{min:{x:o,y:a,z:r},max:{x:s.max.x,y:s.max.y,z:s.max.z}}],p=[];let b=0;const y={x:0,y:0,z:0};for(let f=0;f<8;f++)if(c[f].length>0){const x=this.buildTree(c[f],d[f],t+1);p.push(x),b+=x.mass,y.x+=x.centerOfMass.x*x.mass,y.y+=x.centerOfMass.y*x.mass,y.z+=x.centerOfMass.z*x.mass}else p.push(null);return b>0&&(y.x/=b,y.y/=b,y.z/=b),{bounds:s,size:i,centerOfMass:y,mass:b,isLeaf:!1,node:null,children:p}}}class Be{constructor(e,s,t,i=60){l(this,"sceneManager");l(this,"animationId",null);l(this,"isRunning",!1);l(this,"frameInterval");l(this,"lastFrameTime",0);l(this,"onSimulate");l(this,"onRender");l(this,"frameCount",0);l(this,"fpsStartTime",0);l(this,"currentFPS",60);l(this,"animate",()=>{if(!this.isRunning)return;this.animationId=requestAnimationFrame(this.animate);const e=performance.now(),s=e-this.lastFrameTime;if(s<this.frameInterval)return;this.lastFrameTime=e-s%this.frameInterval,this.frameCount++;const t=e-this.fpsStartTime;t>=1e3&&(this.currentFPS=this.frameCount/(t/1e3),this.frameCount=0,this.fpsStartTime=e),this.onSimulate(),this.onRender(),this.sceneManager.render()});this.sceneManager=e,this.onSimulate=s,this.onRender=t,this.frameInterval=1e3/i}start(){this.isRunning||(this.isRunning=!0,this.lastFrameTime=performance.now(),this.fpsStartTime=performance.now(),this.frameCount=0,this.animate())}stop(){this.isRunning=!1,this.animationId!==null&&(cancelAnimationFrame(this.animationId),this.animationId=null)}getFPS(){return Math.round(this.currentFPS)}setTargetFPS(e){this.frameInterval=1e3/e}isAnimating(){return this.isRunning}dispose(){this.stop()}}class Ve{constructor(){l(this,"envMap",null);l(this,"materialCache",new Map);l(this,"COLORS",[16777215,16750950,16764057,16772829,16746564]);this.createEnvironmentMap()}createEnvironmentMap(){const s=[],t=[{colors:["#1a1a2e","#16213e","#0f3460"]},{colors:["#2d1f1f","#1a1a1a","#0f0f0f"]},{colors:["#1f2d2d","#1a1a2e","#101020"]},{colors:["#0a0a0a","#050505","#000000"]},{colors:["#1a1a2e","#0f1a2a","#0a0a15"]},{colors:["#2d1a1a","#1a0a0a","#0f0505"]}];for(const i of t){const o=document.createElement("canvas");o.width=256,o.height=256;const a=o.getContext("2d"),r=a.createRadialGradient(256/2,256/2,0,256/2,256/2,256*.8);r.addColorStop(0,i.colors[0]),r.addColorStop(.5,i.colors[1]),r.addColorStop(1,i.colors[2]),a.fillStyle=r,a.fillRect(0,0,256,256);const c=a.getImageData(0,0,256,256);for(let d=0;d<c.data.length;d+=4){const p=(Math.random()-.5)*5;c.data[d]=Math.min(255,Math.max(0,c.data[d]+p)),c.data[d+1]=Math.min(255,Math.max(0,c.data[d+1]+p)),c.data[d+2]=Math.min(255,Math.max(0,c.data[d+2]+p))}a.putImageData(c,0,0),s.push(o)}this.envMap=new m.CubeTexture(s.map(i=>{const o=new Image;return o.src=i.toDataURL(),o})),this.envMap.needsUpdate=!0}getRandomColor(){return this.COLORS[Math.floor(Math.random()*this.COLORS.length)]}createGlassMaterial(e){const t="glass-single";if(this.materialCache.has(t))return this.materialCache.get(t).clone();const i=new m.Color(16750950),o=new m.ShaderMaterial({uniforms:{uColor:{value:i},uEnvMap:{value:this.envMap},uGlowColor:{value:new m.Color(16777215)},uGlowIntensity:{value:.8},uReflectivity:{value:.4},uFresnelPower:{value:2.5}},vertexShader:`
8
+ `,document.body.appendChild(d),d}function Ae(d){return d&&d instanceof HTMLElement?d:(console.warn("[ForceGraph3D] No container provided, creating one automatically"),De())}function de(d){const e=d.getBoundingClientRect();return{width:e.width||window.innerWidth,height:e.height||window.innerHeight}}function te(d){if(!d||typeof d!="object")return console.warn("[ForceGraph3D] Invalid node: must be an object"),!1;const e=d;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&&!je(e.position)?(console.warn("[ForceGraph3D] Invalid node: position must have x, y, z numbers"),!1):!0}function se(d){if(!d||typeof d!="object")return console.warn("[ForceGraph3D] Invalid edge: must be an object"),!1;const e=d;return typeof e.source!="string"||e.source.trim()===""?(console.warn("[ForceGraph3D] Invalid edge: source must be a non-empty string"),!1):typeof e.target!="string"||e.target.trim()===""?(console.warn("[ForceGraph3D] Invalid edge: target must be a non-empty string"),!1):!0}function Re(d){return typeof d!="string"||d.trim()===""?(console.warn("[ForceGraph3D] Invalid node ID: must be a non-empty string"),!1):!0}function je(d){if(!d||typeof d!="object")return!1;const e=d;return typeof e.x=="number"&&typeof e.y=="number"&&typeof e.z=="number"}function F(d,e){return d===e?`${d}-${e}`:d<e?`${d}-${e}`:`${e}-${d}`}const pe={type:"change"},ie={type:"start"},ge={type:"end"},X=new u.Ray,ue=new u.Plane,He=Math.cos(70*u.MathUtils.DEG2RAD);class Ge extends u.EventDispatcher{constructor(e,s){super(),this.object=e,this.domElement=s,this.domElement.style.touchAction="none",this.enabled=!0,this.target=new u.Vector3,this.cursor=new u.Vector3,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=.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:u.MOUSE.ROTATE,MIDDLE:u.MOUSE.DOLLY,RIGHT:u.MOUSE.PAN},this.touches={ONE:u.TOUCH.ROTATE,TWO:u.TOUCH.DOLLY_PAN},this.target0=this.target.clone(),this.position0=this.object.position.clone(),this.zoom0=this.object.zoom,this._domElementKeyEvents=null,this.getPolarAngle=function(){return r.phi},this.getAzimuthalAngle=function(){return r.theta},this.getDistance=function(){return this.object.position.distanceTo(this.target)},this.listenToKeyEvents=function(n){n.addEventListener("keydown",ce),this._domElementKeyEvents=n},this.stopListenToKeyEvents=function(){this._domElementKeyEvents.removeEventListener("keydown",ce),this._domElementKeyEvents=null},this.saveState=function(){t.target0.copy(t.target),t.position0.copy(t.object.position),t.zoom0=t.object.zoom},this.reset=function(){t.target.copy(t.target0),t.object.position.copy(t.position0),t.object.zoom=t.zoom0,t.object.updateProjectionMatrix(),t.dispatchEvent(pe),t.update(),o=i.NONE},this.update=function(){const n=new u.Vector3,g=new u.Quaternion().setFromUnitVectors(e.up,new u.Vector3(0,1,0)),M=g.clone().invert(),C=new u.Vector3,S=new u.Quaternion,A=new u.Vector3,P=2*Math.PI;return function(St=null){const Fe=t.object.position;n.copy(Fe).sub(t.target),n.applyQuaternion(g),r.setFromVector3(n),t.autoRotate&&o===i.NONE&&V(rt(St)),t.enableDamping?(r.theta+=c.theta*t.dampingFactor,r.phi+=c.phi*t.dampingFactor):(r.theta+=c.theta,r.phi+=c.phi);let I=t.minAzimuthAngle,L=t.maxAzimuthAngle;isFinite(I)&&isFinite(L)&&(I<-Math.PI?I+=P:I>Math.PI&&(I-=P),L<-Math.PI?L+=P:L>Math.PI&&(L-=P),I<=L?r.theta=Math.max(I,Math.min(L,r.theta)):r.theta=r.theta>(I+L)/2?Math.max(I,r.theta):Math.min(L,r.theta)),r.phi=Math.max(t.minPolarAngle,Math.min(t.maxPolarAngle,r.phi)),r.makeSafe(),t.enableDamping===!0?t.target.addScaledVector(p,t.dampingFactor):t.target.add(p),t.target.sub(t.cursor),t.target.clampLength(t.minTargetRadius,t.maxTargetRadius),t.target.add(t.cursor),t.zoomToCursor&&R||t.object.isOrthographicCamera?r.radius=re(r.radius):r.radius=re(r.radius*h),n.setFromSpherical(r),n.applyQuaternion(M),Fe.copy(t.target).add(n),t.object.lookAt(t.target),t.enableDamping===!0?(c.theta*=1-t.dampingFactor,c.phi*=1-t.dampingFactor,p.multiplyScalar(1-t.dampingFactor)):(c.set(0,0,0),p.set(0,0,0));let he=!1;if(t.zoomToCursor&&R){let K=null;if(t.object.isPerspectiveCamera){const _=n.length();K=re(_*h);const ee=_-K;t.object.position.addScaledVector(B,ee),t.object.updateMatrixWorld()}else if(t.object.isOrthographicCamera){const _=new u.Vector3(O.x,O.y,0);_.unproject(t.object),t.object.zoom=Math.max(t.minZoom,Math.min(t.maxZoom,t.object.zoom/h)),t.object.updateProjectionMatrix(),he=!0;const ee=new u.Vector3(O.x,O.y,0);ee.unproject(t.object),t.object.position.sub(ee).add(_),t.object.updateMatrixWorld(),K=n.length()}else console.warn("WARNING: OrbitControls.js encountered an unknown camera type - zoom to cursor disabled."),t.zoomToCursor=!1;K!==null&&(this.screenSpacePanning?t.target.set(0,0,-1).transformDirection(t.object.matrix).multiplyScalar(K).add(t.object.position):(X.origin.copy(t.object.position),X.direction.set(0,0,-1).transformDirection(t.object.matrix),Math.abs(t.object.up.dot(X.direction))<He?e.lookAt(t.target):(ue.setFromNormalAndCoplanarPoint(t.object.up,t.target),X.intersectPlane(ue,t.target))))}else t.object.isOrthographicCamera&&(t.object.zoom=Math.max(t.minZoom,Math.min(t.maxZoom,t.object.zoom/h)),t.object.updateProjectionMatrix(),he=!0);return h=1,R=!1,he||C.distanceToSquared(t.object.position)>a||8*(1-S.dot(t.object.quaternion))>a||A.distanceToSquared(t.target)>0?(t.dispatchEvent(pe),C.copy(t.object.position),S.copy(t.object.quaternion),A.copy(t.target),!0):!1}}(),this.dispose=function(){t.domElement.removeEventListener("contextmenu",Ie),t.domElement.removeEventListener("pointerdown",ke),t.domElement.removeEventListener("pointercancel",U),t.domElement.removeEventListener("wheel",Oe),t.domElement.removeEventListener("pointermove",le),t.domElement.removeEventListener("pointerup",U),t._domElementKeyEvents!==null&&(t._domElementKeyEvents.removeEventListener("keydown",ce),t._domElementKeyEvents=null)};const t=this,i={NONE:-1,ROTATE:0,DOLLY:1,PAN:2,TOUCH_ROTATE:3,TOUCH_PAN:4,TOUCH_DOLLY_PAN:5,TOUCH_DOLLY_ROTATE:6};let o=i.NONE;const a=1e-6,r=new u.Spherical,c=new u.Spherical;let h=1;const p=new u.Vector3,b=new u.Vector2,x=new u.Vector2,f=new u.Vector2,m=new u.Vector2,v=new u.Vector2,w=new u.Vector2,z=new u.Vector2,D=new u.Vector2,T=new u.Vector2,B=new u.Vector3,O=new u.Vector2;let R=!1;const E=[],Z={};let oe=!1;function rt(n){return n!==null?2*Math.PI/60*t.autoRotateSpeed*n:2*Math.PI/60/60*t.autoRotateSpeed}function Q(n){const g=Math.abs(n*.01);return Math.pow(.95,t.zoomSpeed*g)}function V(n){c.theta-=n}function J(n){c.phi-=n}const xe=function(){const n=new u.Vector3;return function(M,C){n.setFromMatrixColumn(C,0),n.multiplyScalar(-M),p.add(n)}}(),be=function(){const n=new u.Vector3;return function(M,C){t.screenSpacePanning===!0?n.setFromMatrixColumn(C,1):(n.setFromMatrixColumn(C,0),n.crossVectors(t.object.up,n)),n.multiplyScalar(M),p.add(n)}}(),G=function(){const n=new u.Vector3;return function(M,C){const S=t.domElement;if(t.object.isPerspectiveCamera){const A=t.object.position;n.copy(A).sub(t.target);let P=n.length();P*=Math.tan(t.object.fov/2*Math.PI/180),xe(2*M*P/S.clientHeight,t.object.matrix),be(2*C*P/S.clientHeight,t.object.matrix)}else t.object.isOrthographicCamera?(xe(M*(t.object.right-t.object.left)/t.object.zoom/S.clientWidth,t.object.matrix),be(C*(t.object.top-t.object.bottom)/t.object.zoom/S.clientHeight,t.object.matrix)):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."),t.enablePan=!1)}}();function ne(n){t.object.isPerspectiveCamera||t.object.isOrthographicCamera?h/=n:(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),t.enableZoom=!1)}function ve(n){t.object.isPerspectiveCamera||t.object.isOrthographicCamera?h*=n:(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),t.enableZoom=!1)}function ae(n,g){if(!t.zoomToCursor)return;R=!0;const M=t.domElement.getBoundingClientRect(),C=n-M.left,S=g-M.top,A=M.width,P=M.height;O.x=C/A*2-1,O.y=-(S/P)*2+1,B.set(O.x,O.y,1).unproject(t.object).sub(t.object.position).normalize()}function re(n){return Math.max(t.minDistance,Math.min(t.maxDistance,n))}function Me(n){b.set(n.clientX,n.clientY)}function lt(n){ae(n.clientX,n.clientX),z.set(n.clientX,n.clientY)}function we(n){m.set(n.clientX,n.clientY)}function ct(n){x.set(n.clientX,n.clientY),f.subVectors(x,b).multiplyScalar(t.rotateSpeed);const g=t.domElement;V(2*Math.PI*f.x/g.clientHeight),J(2*Math.PI*f.y/g.clientHeight),b.copy(x),t.update()}function ht(n){D.set(n.clientX,n.clientY),T.subVectors(D,z),T.y>0?ne(Q(T.y)):T.y<0&&ve(Q(T.y)),z.copy(D),t.update()}function dt(n){v.set(n.clientX,n.clientY),w.subVectors(v,m).multiplyScalar(t.panSpeed),G(w.x,w.y),m.copy(v),t.update()}function pt(n){ae(n.clientX,n.clientY),n.deltaY<0?ve(Q(n.deltaY)):n.deltaY>0&&ne(Q(n.deltaY)),t.update()}function gt(n){let g=!1;switch(n.code){case t.keys.UP:n.ctrlKey||n.metaKey||n.shiftKey?J(2*Math.PI*t.rotateSpeed/t.domElement.clientHeight):G(0,t.keyPanSpeed),g=!0;break;case t.keys.BOTTOM:n.ctrlKey||n.metaKey||n.shiftKey?J(-2*Math.PI*t.rotateSpeed/t.domElement.clientHeight):G(0,-t.keyPanSpeed),g=!0;break;case t.keys.LEFT:n.ctrlKey||n.metaKey||n.shiftKey?V(2*Math.PI*t.rotateSpeed/t.domElement.clientHeight):G(t.keyPanSpeed,0),g=!0;break;case t.keys.RIGHT:n.ctrlKey||n.metaKey||n.shiftKey?V(-2*Math.PI*t.rotateSpeed/t.domElement.clientHeight):G(-t.keyPanSpeed,0),g=!0;break}g&&(n.preventDefault(),t.update())}function Ce(n){if(E.length===1)b.set(n.pageX,n.pageY);else{const g=$(n),M=.5*(n.pageX+g.x),C=.5*(n.pageY+g.y);b.set(M,C)}}function Ee(n){if(E.length===1)m.set(n.pageX,n.pageY);else{const g=$(n),M=.5*(n.pageX+g.x),C=.5*(n.pageY+g.y);m.set(M,C)}}function Ne(n){const g=$(n),M=n.pageX-g.x,C=n.pageY-g.y,S=Math.sqrt(M*M+C*C);z.set(0,S)}function ut(n){t.enableZoom&&Ne(n),t.enablePan&&Ee(n)}function ft(n){t.enableZoom&&Ne(n),t.enableRotate&&Ce(n)}function Se(n){if(E.length==1)x.set(n.pageX,n.pageY);else{const M=$(n),C=.5*(n.pageX+M.x),S=.5*(n.pageY+M.y);x.set(C,S)}f.subVectors(x,b).multiplyScalar(t.rotateSpeed);const g=t.domElement;V(2*Math.PI*f.x/g.clientHeight),J(2*Math.PI*f.y/g.clientHeight),b.copy(x)}function ze(n){if(E.length===1)v.set(n.pageX,n.pageY);else{const g=$(n),M=.5*(n.pageX+g.x),C=.5*(n.pageY+g.y);v.set(M,C)}w.subVectors(v,m).multiplyScalar(t.panSpeed),G(w.x,w.y),m.copy(v)}function Pe(n){const g=$(n),M=n.pageX-g.x,C=n.pageY-g.y,S=Math.sqrt(M*M+C*C);D.set(0,S),T.set(0,Math.pow(D.y/z.y,t.zoomSpeed)),ne(T.y),z.copy(D);const A=(n.pageX+g.x)*.5,P=(n.pageY+g.y)*.5;ae(A,P)}function mt(n){t.enableZoom&&Pe(n),t.enablePan&&ze(n)}function yt(n){t.enableZoom&&Pe(n),t.enableRotate&&Se(n)}function ke(n){t.enabled!==!1&&(E.length===0&&(t.domElement.setPointerCapture(n.pointerId),t.domElement.addEventListener("pointermove",le),t.domElement.addEventListener("pointerup",U)),Et(n),n.pointerType==="touch"?wt(n):xt(n))}function le(n){t.enabled!==!1&&(n.pointerType==="touch"?Ct(n):bt(n))}function U(n){Nt(n),E.length===0&&(t.domElement.releasePointerCapture(n.pointerId),t.domElement.removeEventListener("pointermove",le),t.domElement.removeEventListener("pointerup",U)),t.dispatchEvent(ge),o=i.NONE}function xt(n){let g;switch(n.button){case 0:g=t.mouseButtons.LEFT;break;case 1:g=t.mouseButtons.MIDDLE;break;case 2:g=t.mouseButtons.RIGHT;break;default:g=-1}switch(g){case u.MOUSE.DOLLY:if(t.enableZoom===!1)return;lt(n),o=i.DOLLY;break;case u.MOUSE.ROTATE:if(n.ctrlKey||n.metaKey||n.shiftKey){if(t.enablePan===!1)return;we(n),o=i.PAN}else{if(t.enableRotate===!1)return;Me(n),o=i.ROTATE}break;case u.MOUSE.PAN:if(n.ctrlKey||n.metaKey||n.shiftKey){if(t.enableRotate===!1)return;Me(n),o=i.ROTATE}else{if(t.enablePan===!1)return;we(n),o=i.PAN}break;default:o=i.NONE}o!==i.NONE&&t.dispatchEvent(ie)}function bt(n){switch(o){case i.ROTATE:if(t.enableRotate===!1)return;ct(n);break;case i.DOLLY:if(t.enableZoom===!1)return;ht(n);break;case i.PAN:if(t.enablePan===!1)return;dt(n);break}}function Oe(n){t.enabled===!1||t.enableZoom===!1||o!==i.NONE||(n.preventDefault(),t.dispatchEvent(ie),pt(vt(n)),t.dispatchEvent(ge))}function vt(n){const g=n.deltaMode,M={clientX:n.clientX,clientY:n.clientY,deltaY:n.deltaY};switch(g){case 1:M.deltaY*=16;break;case 2:M.deltaY*=100;break}return n.ctrlKey&&!oe&&(M.deltaY*=10),M}function Mt(n){n.key==="Control"&&(oe=!0,document.addEventListener("keyup",Te,{passive:!0,capture:!0}))}function Te(n){n.key==="Control"&&(oe=!1,document.removeEventListener("keyup",Te,{passive:!0,capture:!0}))}function ce(n){t.enabled===!1||t.enablePan===!1||gt(n)}function wt(n){switch(Le(n),E.length){case 1:switch(t.touches.ONE){case u.TOUCH.ROTATE:if(t.enableRotate===!1)return;Ce(n),o=i.TOUCH_ROTATE;break;case u.TOUCH.PAN:if(t.enablePan===!1)return;Ee(n),o=i.TOUCH_PAN;break;default:o=i.NONE}break;case 2:switch(t.touches.TWO){case u.TOUCH.DOLLY_PAN:if(t.enableZoom===!1&&t.enablePan===!1)return;ut(n),o=i.TOUCH_DOLLY_PAN;break;case u.TOUCH.DOLLY_ROTATE:if(t.enableZoom===!1&&t.enableRotate===!1)return;ft(n),o=i.TOUCH_DOLLY_ROTATE;break;default:o=i.NONE}break;default:o=i.NONE}o!==i.NONE&&t.dispatchEvent(ie)}function Ct(n){switch(Le(n),o){case i.TOUCH_ROTATE:if(t.enableRotate===!1)return;Se(n),t.update();break;case i.TOUCH_PAN:if(t.enablePan===!1)return;ze(n),t.update();break;case i.TOUCH_DOLLY_PAN:if(t.enableZoom===!1&&t.enablePan===!1)return;mt(n),t.update();break;case i.TOUCH_DOLLY_ROTATE:if(t.enableZoom===!1&&t.enableRotate===!1)return;yt(n),t.update();break;default:o=i.NONE}}function Ie(n){t.enabled!==!1&&n.preventDefault()}function Et(n){E.push(n.pointerId)}function Nt(n){delete Z[n.pointerId];for(let g=0;g<E.length;g++)if(E[g]==n.pointerId){E.splice(g,1);return}}function Le(n){let g=Z[n.pointerId];g===void 0&&(g=new u.Vector2,Z[n.pointerId]=g),g.set(n.pageX,n.pageY)}function $(n){const g=n.pointerId===E[0]?E[1]:E[0];return Z[g]}t.domElement.addEventListener("contextmenu",Ie),t.domElement.addEventListener("pointerdown",ke),t.domElement.addEventListener("pointercancel",U),t.domElement.addEventListener("wheel",Oe,{passive:!1}),document.addEventListener("keydown",Mt,{passive:!0,capture:!0}),this.update()}}class $e{constructor(e,s){l(this,"scene");l(this,"camera");l(this,"renderer");l(this,"controls");l(this,"container");l(this,"resizeHandler");this.container=e,this.scene=new y.Scene,this.scene.background=new y.Color(s.backgroundColor??657930);const{width:t,height:i}=de(e),o=s.cameraFov??75;this.camera=new y.PerspectiveCamera(o,t/i,.1,2e3);const a=s.cameraPosition??{x:0,y:0,z:80};this.camera.position.set(a.x,a.y,a.z),this.renderer=new y.WebGLRenderer({antialias:!0,alpha:!0,powerPreference:"high-performance"}),this.renderer.setSize(t,i),this.renderer.setPixelRatio(Math.min(window.devicePixelRatio,2)),this.renderer.toneMapping=y.ACESFilmicToneMapping,this.renderer.toneMappingExposure=1,this.renderer.shadowMap.enabled=!0,this.renderer.shadowMap.type=y.PCFSoftShadowMap,e.appendChild(this.renderer.domElement),this.controls=new Ge(this.camera,this.renderer.domElement),this.controls.enableDamping=!0,this.controls.dampingFactor=.05,this.controls.rotateSpeed=.8,this.controls.zoomSpeed=1.2,this.controls.minDistance=10,this.controls.maxDistance=2e3,this.setupLighting(),this.resizeHandler=this.onWindowResize.bind(this),window.addEventListener("resize",this.resizeHandler)}setupLighting(){const e=new y.AmbientLight(16777215,.4);this.scene.add(e);const s=new y.DirectionalLight(16777215,.9);s.position.set(50,60,40),s.castShadow=!0,s.shadow.mapSize.width=1024,s.shadow.mapSize.height=1024,this.scene.add(s);const t=new y.DirectionalLight(16773344,.4);t.position.set(-50,30,-40),this.scene.add(t);const i=new y.DirectionalLight(16777215,.3);i.position.set(0,-30,-50),this.scene.add(i);const o=new y.PointLight(16750950,.5,150);o.position.set(40,20,40),this.scene.add(o);const a=new y.PointLight(16764057,.4,150);a.position.set(-40,-20,40),this.scene.add(a);const r=new y.PointLight(6724095,.2,100);r.position.set(0,40,-40),this.scene.add(r)}onWindowResize(){const{width:e,height:s}=de(this.container);this.camera.aspect=e/s,this.camera.updateProjectionMatrix(),this.renderer.setSize(e,s)}add(e){this.scene.add(e)}remove(e){this.scene.remove(e)}render(){this.controls.update(),this.renderer.render(this.scene,this.camera)}getCameraPosition(){return{x:this.camera.position.x,y:this.camera.position.y,z:this.camera.position.z}}getCameraDirection(){const e=new y.Vector3;return this.camera.getWorldDirection(e),e}dispose(){for(window.removeEventListener("resize",this.resizeHandler),this.controls.dispose(),this.renderer.dispose(),this.renderer.domElement.parentNode&&this.renderer.domElement.parentNode.removeChild(this.renderer.domElement);this.scene.children.length>0;){const e=this.scene.children[0];this.scene.remove(e)}}}const Y=class Y{constructor(e,s){l(this,"sceneManager");l(this,"nodeFactory");l(this,"nodes",new Map);l(this,"nodeObjects",new Map);this.sceneManager=e,this.nodeFactory=s}hasNode(e){return this.nodes.has(e)}static setExpectedNodeCount(e){Y.expectedNodeCount=e}addNode(e,s=0){if(!te(e))return!1;if(this.nodes.has(e.id))return console.warn(`[ForceGraph3D] Node with id "${e.id}" already exists`),!1;const t=Math.max(50,Math.cbrt(Y.expectedNodeCount)*10),i=e.position??{x:(Math.random()-.5)*t,y:(Math.random()-.5)*t,z:(Math.random()-.5)*t},o={...e,position:i,velocity:{x:0,y:0,z:0},mass:1},a=this.nodeFactory.createNode({...e,position:i},s);return this.sceneManager.add(a.group),this.nodes.set(e.id,o),this.nodeObjects.set(e.id,a),!0}removeNode(e){const s=this.nodes.get(e),t=this.nodeObjects.get(e);return!s||!t?!1:(this.sceneManager.remove(t.group),this.nodeFactory.disposeNode(t),this.nodes.delete(e),this.nodeObjects.delete(e),!0)}updateNode(e,s){const t=this.nodes.get(e),i=this.nodeObjects.get(e);return!t||!i?(console.warn(`[ForceGraph3D] Node "${e}" not found`),!1):(s.label!==void 0&&(t.label=s.label,this.nodeFactory.updateNodeLabel(i,s.label)),s.color!==void 0&&(t.color=s.color,this.nodeFactory.updateNodeColor(i,s.color)),Object.keys(s).forEach(o=>{o!=="id"&&o!=="label"&&o!=="color"&&o!=="position"&&(t[o]=s[o])}),!0)}updateNodePosition(e,s){const t=this.nodes.get(e),i=this.nodeObjects.get(e);t&&i&&(t.position=s,i.group.position.set(s.x,s.y,s.z))}updateNodeLOD(e,s){const t=this.nodeObjects.get(e);t&&this.nodeFactory.updateNodeLOD(t,s)}getNode(e){return this.nodes.get(e)}getNodeObject(e){return this.nodeObjects.get(e)}getAllNodes(){return this.nodes}getAllNodeObjects(){const e=[];return this.nodeObjects.forEach(s=>{e.push(s.group)}),e}getAllSpheres(){const e=[];return this.nodeObjects.forEach(s=>{e.push(s.sphere)}),e}getNodeCount(){return this.nodes.size}clear(){this.nodes.forEach((e,s)=>{this.removeNode(s)})}dispose(){this.clear()}};l(Y,"expectedNodeCount",100);let q=Y;class Ye{constructor(e,s,t){l(this,"sceneManager");l(this,"nodeManager");l(this,"edgeFactory");l(this,"edges",[]);l(this,"edgeObjects",[]);l(this,"edgeKeySet",new Set);l(this,"highlightedEdgeKey",null);this.sceneManager=e,this.nodeManager=s,this.edgeFactory=t}hasEdge(e,s){const t=F(e,s);return this.edgeKeySet.has(t)}addEdge(e){if(!se(e))return!1;if(!this.nodeManager.hasNode(e.source))return console.warn(`[ForceGraph3D] Source node "${e.source}" does not exist`),!1;if(!this.nodeManager.hasNode(e.target))return console.warn(`[ForceGraph3D] Target node "${e.target}" does not exist`),!1;const s=F(e.source,e.target);if(this.edgeKeySet.has(s))return console.warn(`[ForceGraph3D] Edge "${e.source}" -> "${e.target}" already exists`),!1;const t=this.nodeManager.getNode(e.source),i=this.nodeManager.getNode(e.target),o=this.edgeFactory.createEdge(e,t,i,t.position,i.position);return this.sceneManager.add(o.line),this.edges.push(e),this.edgeObjects.push(o),this.edgeKeySet.add(s),!0}removeEdge(e,s){const t=F(e,s);if(!this.edgeKeySet.has(t))return!1;const i=this.edges.findIndex(a=>F(a.source,a.target)===t);if(i===-1)return!1;const o=this.edgeObjects[i];return this.sceneManager.remove(o.line),this.edgeFactory.disposeEdge(o),this.edges.splice(i,1),this.edgeObjects.splice(i,1),this.edgeKeySet.delete(t),this.highlightedEdgeKey===t&&(this.highlightedEdgeKey=null),!0}highlightEdge(e,s){const t=F(e,s);this.highlightedEdgeKey&&this.highlightedEdgeKey!==t&&this.unhighlightCurrentEdge();const i=this.edges.findIndex(o=>F(o.source,o.target)===t);i!==-1&&(this.edgeFactory.highlightEdge(this.edgeObjects[i]),this.highlightedEdgeKey=t)}unhighlightCurrentEdge(){if(!this.highlightedEdgeKey)return;const e=this.edges.findIndex(s=>F(s.source,s.target)===this.highlightedEdgeKey);e!==-1&&this.edgeFactory.unhighlightEdge(this.edgeObjects[e]),this.highlightedEdgeKey=null}removeEdgesForNode(e){const s=[];this.edges.forEach(t=>{(t.source===e||t.target===e)&&s.push({source:t.source,target:t.target})}),s.forEach(t=>{this.removeEdge(t.source,t.target)})}getEdgesForNode(e){return this.edges.filter(s=>s.source===e||s.target===e)}getNeighborIds(e){const s=[];return this.edges.forEach(t=>{t.source===e?s.push(t.target):t.target===e&&s.push(t.source)}),[...new Set(s)]}updateEdgePositions(){this.edgeObjects.forEach((e,s)=>{const t=this.edges[s],i=this.nodeManager.getNode(t.source),o=this.nodeManager.getNode(t.target);i&&o&&this.edgeFactory.updateEdgePositions(e,i.position,o.position)})}getAllEdges(){return this.edges}getAllEdgeLines(){return this.edgeObjects.map(e=>e.line)}getEdgeCount(){return this.edges.length}clear(){this.edgeObjects.forEach(e=>{this.sceneManager.remove(e.line),this.edgeFactory.disposeEdge(e)}),this.edges=[],this.edgeObjects=[],this.edgeKeySet.clear(),this.highlightedEdgeKey=null}dispose(){this.clear()}}class fe{constructor(e,s,t={}){l(this,"nodes");l(this,"edges");l(this,"repulsionStrength");l(this,"attractionStrength");l(this,"damping");l(this,"useBarnesHut");l(this,"barnesHutTheta");l(this,"MAX_VELOCITY",5);l(this,"REPULSION_CUTOFF",200);l(this,"REPULSION_CUTOFF_SQ");l(this,"GRAVITY_STRENGTH",.05);l(this,"pinnedNodeId",null);l(this,"alpha",1);l(this,"alphaDecay",.0228);l(this,"alphaMin",.001);l(this,"alphaTarget",0);this.nodes=e,this.edges=s,this.repulsionStrength=t.repulsionStrength??100,this.attractionStrength=t.attractionStrength??.01,this.damping=t.damping??.9,this.useBarnesHut=t.useBarnesHut??!1,this.barnesHutTheta=t.barnesHutTheta??.5,this.REPULSION_CUTOFF_SQ=this.REPULSION_CUTOFF*this.REPULSION_CUTOFF,this.initializeNodeMassAndPin()}initializeNodeMassAndPin(){const e=new Map;for(const i of this.edges)e.set(i.source,(e.get(i.source)||0)+1),e.set(i.target,(e.get(i.target)||0)+1);let s=0,t=null;for(const[i,o]of e){o>s&&(s=o,t=i);const a=this.nodes.get(i);a&&(a.mass=1+Math.log2(1+o))}if(t&&s>10){this.pinnedNodeId=t;const i=this.nodes.get(t);i&&(i.position.x=0,i.position.y=0,i.position.z=0,i.velocity.x=0,i.velocity.y=0,i.velocity.z=0)}}getEffectiveRepulsion(){const e=this.nodes.size;return e<=500?this.repulsionStrength:this.repulsionStrength*Math.sqrt(500)/Math.sqrt(e)}simulate(){if(this.alpha<this.alphaMin)return;const e=this.nodes.size;(this.useBarnesHut||e>=1e3)&&e>=100?this.calculateRepulsionBarnesHut():this.calculateRepulsionBruteForce(),this.calculateAttraction(),this.applyCenteringForce(),this.applyForces(),this.alpha+=(this.alphaTarget-this.alpha)*this.alphaDecay}calculateRepulsionBruteForce(){const e=Array.from(this.nodes.values()),s=e.length,t=this.getEffectiveRepulsion();for(let i=0;i<s;i++){const o=e[i];for(let a=i+1;a<s;a++){const r=e[a],c=r.position.x-o.position.x,h=r.position.y-o.position.y,p=r.position.z-o.position.z;let b=c*c+h*h+p*p;if(b>this.REPULSION_CUTOFF_SQ)continue;b<.01&&(b=.01);const x=Math.sqrt(b),f=t*this.alpha/b,m=c/x*f,v=h/x*f,w=p/x*f;o.velocity.x-=m/o.mass,o.velocity.y-=v/o.mass,o.velocity.z-=w/o.mass,r.velocity.x+=m/r.mass,r.velocity.y+=v/r.mass,r.velocity.z+=w/r.mass}}}calculateRepulsionBarnesHut(){const e=Array.from(this.nodes.values()),s=new Be(e);for(const t of e)this.calculateForceFromOctree(t,s.root)}calculateForceFromOctree(e,s){if(s.isLeaf){s.node&&s.node.id!==e.id&&this.applyRepulsionBetween(e,s.node);return}if(s.mass===0)return;const t=s.centerOfMass.x-e.position.x,i=s.centerOfMass.y-e.position.y,o=s.centerOfMass.z-e.position.z,a=t*t+i*i+o*o;if(a>this.REPULSION_CUTOFF_SQ)return;const r=Math.sqrt(a),c=this.getEffectiveRepulsion();if(r>0&&s.size/r<this.barnesHutTheta){const h=Math.max(a,.01),p=c*this.alpha*s.mass/h;e.velocity.x-=t/r*p/e.mass,e.velocity.y-=i/r*p/e.mass,e.velocity.z-=o/r*p/e.mass}else for(const h of s.children)h&&this.calculateForceFromOctree(e,h)}applyRepulsionBetween(e,s){const t=s.position.x-e.position.x,i=s.position.y-e.position.y,o=s.position.z-e.position.z;let a=t*t+i*i+o*o;if(a>this.REPULSION_CUTOFF_SQ)return;a<.01&&(a=.01);const r=Math.sqrt(a),h=this.getEffectiveRepulsion()*this.alpha/a;e.velocity.x-=t/r*h/e.mass,e.velocity.y-=i/r*h/e.mass,e.velocity.z-=o/r*h/e.mass}calculateAttraction(){const e=this.nodes.size,s=e>500?1+Math.log10(e/500):1;for(const t of this.edges){const i=this.nodes.get(t.source),o=this.nodes.get(t.target);if(!i||!o)continue;const a=o.position.x-i.position.x,r=o.position.y-i.position.y,c=o.position.z-i.position.z,h=Math.sqrt(a*a+r*r+c*c);if(h<.01)continue;const b=(h-15)*this.attractionStrength*s*this.alpha,x=a/h*b,f=r/h*b,m=c/h*b;i.velocity.x+=x/i.mass,i.velocity.y+=f/i.mass,i.velocity.z+=m/i.mass,o.velocity.x-=x/o.mass,o.velocity.y-=f/o.mass,o.velocity.z-=m/o.mass}}applyCenteringForce(){const e=this.GRAVITY_STRENGTH*this.alpha;for(const s of this.nodes.values())s.velocity.x-=s.position.x*e,s.velocity.y-=s.position.y*e,s.velocity.z-=s.position.z*e}applyForces(){for(const e of this.nodes.values()){if(e.id===this.pinnedNodeId){e.position.x=0,e.position.y=0,e.position.z=0,e.velocity.x=0,e.velocity.y=0,e.velocity.z=0;continue}e.velocity.x*=this.damping,e.velocity.y*=this.damping,e.velocity.z*=this.damping;const s=Math.sqrt(e.velocity.x*e.velocity.x+e.velocity.y*e.velocity.y+e.velocity.z*e.velocity.z);if(s>this.MAX_VELOCITY){const t=this.MAX_VELOCITY/s;e.velocity.x*=t,e.velocity.y*=t,e.velocity.z*=t}e.position.x+=e.velocity.x,e.position.y+=e.velocity.y,e.position.z+=e.velocity.z}}setEdges(e){this.edges=e}restart(){this.alpha=1}getAlpha(){return this.alpha}setPhysicsParams(e){e.repulsionStrength!==void 0&&(this.repulsionStrength=e.repulsionStrength),e.attractionStrength!==void 0&&(this.attractionStrength=e.attractionStrength),e.damping!==void 0&&(this.damping=e.damping)}}class Be{constructor(e){l(this,"root");const s=this.calculateBounds(e);this.root=this.buildTree(e,s)}calculateBounds(e){if(e.length===0)return{min:{x:-100,y:-100,z:-100},max:{x:100,y:100,z:100}};const s={x:1/0,y:1/0,z:1/0},t={x:-1/0,y:-1/0,z:-1/0};for(const o of e)s.x=Math.min(s.x,o.position.x),s.y=Math.min(s.y,o.position.y),s.z=Math.min(s.z,o.position.z),t.x=Math.max(t.x,o.position.x),t.y=Math.max(t.y,o.position.y),t.z=Math.max(t.z,o.position.z);const i=10;return s.x-=i,s.y-=i,s.z-=i,t.x+=i,t.y+=i,t.z+=i,{min:s,max:t}}buildTree(e,s,t=0){const i=Math.max(s.max.x-s.min.x,s.max.y-s.min.y,s.max.z-s.min.z);if(e.length===0)return{bounds:s,size:i,centerOfMass:{x:0,y:0,z:0},mass:0,isLeaf:!0,node:null,children:[]};if(e.length===1||t>20){let f=0;const m={x:0,y:0,z:0};for(const v of e)f+=v.mass,m.x+=v.position.x*v.mass,m.y+=v.position.y*v.mass,m.z+=v.position.z*v.mass;return f>0&&(m.x/=f,m.y/=f,m.z/=f),{bounds:s,size:i,centerOfMass:m,mass:f,isLeaf:!0,node:e[0],children:[]}}const o=(s.min.x+s.max.x)/2,a=(s.min.y+s.max.y)/2,r=(s.min.z+s.max.z)/2,c=[[],[],[],[],[],[],[],[]];for(const f of e){const m=(f.position.x>=o?1:0)+(f.position.y>=a?2:0)+(f.position.z>=r?4:0);c[m].push(f)}const h=[{min:{x:s.min.x,y:s.min.y,z:s.min.z},max:{x:o,y:a,z:r}},{min:{x:o,y:s.min.y,z:s.min.z},max:{x:s.max.x,y:a,z:r}},{min:{x:s.min.x,y:a,z:s.min.z},max:{x:o,y:s.max.y,z:r}},{min:{x:o,y:a,z:s.min.z},max:{x:s.max.x,y:s.max.y,z:r}},{min:{x:s.min.x,y:s.min.y,z:r},max:{x:o,y:a,z:s.max.z}},{min:{x:o,y:s.min.y,z:r},max:{x:s.max.x,y:a,z:s.max.z}},{min:{x:s.min.x,y:a,z:r},max:{x:o,y:s.max.y,z:s.max.z}},{min:{x:o,y:a,z:r},max:{x:s.max.x,y:s.max.y,z:s.max.z}}],p=[];let b=0;const x={x:0,y:0,z:0};for(let f=0;f<8;f++)if(c[f].length>0){const m=this.buildTree(c[f],h[f],t+1);p.push(m),b+=m.mass,x.x+=m.centerOfMass.x*m.mass,x.y+=m.centerOfMass.y*m.mass,x.z+=m.centerOfMass.z*m.mass}else p.push(null);return b>0&&(x.x/=b,x.y/=b,x.z/=b),{bounds:s,size:i,centerOfMass:x,mass:b,isLeaf:!1,node:null,children:p}}}class Ve{constructor(e,s,t,i=60){l(this,"sceneManager");l(this,"animationId",null);l(this,"isRunning",!1);l(this,"frameInterval");l(this,"lastFrameTime",0);l(this,"onSimulate");l(this,"onRender");l(this,"frameCount",0);l(this,"fpsStartTime",0);l(this,"currentFPS",60);l(this,"animate",()=>{if(!this.isRunning)return;this.animationId=requestAnimationFrame(this.animate);const e=performance.now(),s=e-this.lastFrameTime;if(s<this.frameInterval)return;this.lastFrameTime=e-s%this.frameInterval,this.frameCount++;const t=e-this.fpsStartTime;t>=1e3&&(this.currentFPS=this.frameCount/(t/1e3),this.frameCount=0,this.fpsStartTime=e),this.onSimulate(),this.onRender(),this.sceneManager.render()});this.sceneManager=e,this.onSimulate=s,this.onRender=t,this.frameInterval=1e3/i}start(){this.isRunning||(this.isRunning=!0,this.lastFrameTime=performance.now(),this.fpsStartTime=performance.now(),this.frameCount=0,this.animate())}stop(){this.isRunning=!1,this.animationId!==null&&(cancelAnimationFrame(this.animationId),this.animationId=null)}getFPS(){return Math.round(this.currentFPS)}setTargetFPS(e){this.frameInterval=1e3/e}isAnimating(){return this.isRunning}dispose(){this.stop()}}class Ue{constructor(){l(this,"envMap",null);l(this,"materialCache",new Map);l(this,"COLORS",[16777215,16750950,16764057,16772829,16746564]);this.createEnvironmentMap()}createEnvironmentMap(){const s=[],t=[{colors:["#1a1a2e","#16213e","#0f3460"]},{colors:["#2d1f1f","#1a1a1a","#0f0f0f"]},{colors:["#1f2d2d","#1a1a2e","#101020"]},{colors:["#0a0a0a","#050505","#000000"]},{colors:["#1a1a2e","#0f1a2a","#0a0a15"]},{colors:["#2d1a1a","#1a0a0a","#0f0505"]}];for(const i of t){const o=document.createElement("canvas");o.width=256,o.height=256;const a=o.getContext("2d"),r=a.createRadialGradient(256/2,256/2,0,256/2,256/2,256*.8);r.addColorStop(0,i.colors[0]),r.addColorStop(.5,i.colors[1]),r.addColorStop(1,i.colors[2]),a.fillStyle=r,a.fillRect(0,0,256,256);const c=a.getImageData(0,0,256,256);for(let h=0;h<c.data.length;h+=4){const p=(Math.random()-.5)*5;c.data[h]=Math.min(255,Math.max(0,c.data[h]+p)),c.data[h+1]=Math.min(255,Math.max(0,c.data[h+1]+p)),c.data[h+2]=Math.min(255,Math.max(0,c.data[h+2]+p))}a.putImageData(c,0,0),s.push(o)}this.envMap=new y.CubeTexture(s.map(i=>{const o=new Image;return o.src=i.toDataURL(),o})),this.envMap.needsUpdate=!0}getRandomColor(){return this.COLORS[Math.floor(Math.random()*this.COLORS.length)]}createGlassMaterial(e){const t="glass-single";if(this.materialCache.has(t))return this.materialCache.get(t).clone();const i=new y.Color(16750950),o=new y.ShaderMaterial({uniforms:{uColor:{value:i},uEnvMap:{value:this.envMap},uGlowColor:{value:new y.Color(16777215)},uGlowIntensity:{value:.8},uReflectivity:{value:.4},uFresnelPower:{value:2.5}},vertexShader:`
9
9
  varying vec3 vNormal;
10
10
  varying vec3 vViewPosition;
11
11
  varying vec3 vWorldPosition;
@@ -63,7 +63,7 @@
63
63
 
64
64
  gl_FragColor = vec4(finalColor, opacity);
65
65
  }
66
- `,transparent:!0,side:m.FrontSide,depthWrite:!0,blending:m.NormalBlending});return this.materialCache.set(t,o),o.clone()}createEdgeMaterial(e=6710886,s=.4){return new m.LineBasicMaterial({color:e,transparent:!0,opacity:s,linewidth:1})}createHighlightedEdgeMaterial(){return new m.LineBasicMaterial({color:16750950,transparent:!1,opacity:1,linewidth:2})}createLabelMaterial(e,s=24){const t=document.createElement("canvas"),i=t.getContext("2d");i.font=`600 ${s}px Inter, -apple-system, sans-serif`;const a=i.measureText(e).width;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);const r=new m.CanvasTexture(t);return r.needsUpdate=!0,new m.SpriteMaterial({map:r,transparent:!0,depthTest:!1,depthWrite:!1})}getEnvMap(){return this.envMap}dispose(){this.materialCache.forEach(e=>e.dispose()),this.materialCache.clear(),this.envMap&&this.envMap.dispose()}}class Ke{constructor(e,s=2,t=[32,16,8],i=16750950){l(this,"materialFactory");l(this,"geometryCache",new Map);l(this,"nodeRadius");l(this,"lodSegments");l(this,"defaultNodeColor");this.materialFactory=e,this.nodeRadius=s,this.lodSegments=t,this.defaultNodeColor=i,this.initGeometryCache()}initGeometryCache(){this.lodSegments.forEach((e,s)=>{const t=`lod-${s}`;this.geometryCache.set(t,new m.SphereGeometry(this.nodeRadius,e,e))})}getGeometry(e){const s=`lod-${e}`;return this.geometryCache.has(s)?this.geometryCache.get(s):this.geometryCache.get("lod-0")}createNode(e,s=0){const t=new m.Group;t.name=`node-${e.id}`,t.userData={nodeId:e.id,nodeData:e};const i=this.getGeometry(s),o=this.materialFactory.createGlassMaterial(e.color??this.defaultNodeColor),a=new m.Mesh(i,o);a.castShadow=!0,a.receiveShadow=!0,t.add(a);const r=this.materialFactory.createLabelMaterial(e.label),c=new m.Sprite(r);return c.position.y=this.nodeRadius+1.5,c.scale.set(4,1,1),t.add(c),e.position&&t.position.set(e.position.x,e.position.y,e.position.z),{group:t,sphere:a,label:c,lodLevel:s}}updateNodeLOD(e,s){if(e.lodLevel===s)return;const t=this.getGeometry(s);e.sphere.geometry=t,e.lodLevel=s}updateNodeColor(e,s){e.sphere.material instanceof m.Material&&e.sphere.material.dispose(),e.sphere.material=this.materialFactory.createGlassMaterial(s)}updateNodeLabel(e,s){e.label.material instanceof m.SpriteMaterial&&(e.label.material.map&&e.label.material.map.dispose(),e.label.material.dispose()),e.label.material=this.materialFactory.createLabelMaterial(s)}disposeNode(e){e.sphere.material instanceof m.Material&&e.sphere.material.dispose(),e.label.material instanceof m.SpriteMaterial&&(e.label.material.map&&e.label.material.map.dispose(),e.label.material.dispose())}dispose(){this.geometryCache.forEach(e=>e.dispose()),this.geometryCache.clear()}}class Ue{constructor(e,s=10066329,t=.5){l(this,"materialFactory");l(this,"edgeColor");l(this,"edgeOpacity");l(this,"defaultMaterial",null);l(this,"highlightMaterial",null);this.materialFactory=e,this.edgeColor=s,this.edgeOpacity=t}getDefaultMaterial(){return this.defaultMaterial||(this.defaultMaterial=this.materialFactory.createEdgeMaterial(this.edgeColor,this.edgeOpacity)),this.defaultMaterial}getHighlightMaterial(){return this.highlightMaterial||(this.highlightMaterial=this.materialFactory.createHighlightedEdgeMaterial()),this.highlightMaterial}createEdge(e,s,t,i,o){const a=new m.BufferGeometry,r=new Float32Array([i.x,i.y,i.z,o.x,o.y,o.z]);a.setAttribute("position",new m.BufferAttribute(r,3));const c=this.getDefaultMaterial().clone(),d=new m.Line(a,c);return d.name=`edge-${e.source}-${e.target}`,d.userData={source:e.source,target:e.target,edge:e,sourceNode:s,targetNode:t},d.frustumCulled=!0,{line:d,source:e.source,target:e.target}}highlightEdge(e){e.line.material instanceof m.Material&&e.line.material.dispose(),e.line.material=this.getHighlightMaterial().clone()}unhighlightEdge(e){e.line.material instanceof m.Material&&e.line.material.dispose(),e.line.material=this.getDefaultMaterial().clone()}updateEdgePositions(e,s,t){const i=e.line.geometry.attributes.position,o=i.array;o[0]=s.x,o[1]=s.y,o[2]=s.z,o[3]=t.x,o[4]=t.y,o[5]=t.z,i.needsUpdate=!0,e.line.geometry.computeBoundingSphere()}disposeEdge(e){e.line.geometry.dispose(),e.line.material instanceof m.Material&&e.line.material.dispose()}dispose(){this.defaultMaterial&&this.defaultMaterial.dispose(),this.highlightMaterial&&this.highlightMaterial.dispose()}}class Xe{constructor(e,s=[50,100,200],t=!0){l(this,"camera");l(this,"lodDistances");l(this,"enabled");this.camera=e,this.lodDistances=s,this.enabled=t}getLODLevel(e){if(!this.enabled)return H.HIGH;const s=e.x-this.camera.position.x,t=e.y-this.camera.position.y,i=e.z-this.camera.position.z,o=Math.sqrt(s*s+t*t+i*i);return o<this.lodDistances[0]?H.HIGH:o<this.lodDistances[1]?H.MEDIUM:H.LOW}shouldRenderNode(e,s=500){const t=e.x-this.camera.position.x,i=e.y-this.camera.position.y,o=e.z-this.camera.position.z;return Math.sqrt(t*t+i*i+o*o)<s}setLODDistances(e){this.lodDistances=e}setEnabled(e){this.enabled=e}}class _e{constructor(e,s=!0){l(this,"camera");l(this,"frustum");l(this,"projScreenMatrix");l(this,"enabled");this.camera=e,this.frustum=new m.Frustum,this.projScreenMatrix=new m.Matrix4,this.enabled=s}update(){this.projScreenMatrix.multiplyMatrices(this.camera.projectionMatrix,this.camera.matrixWorldInverse),this.frustum.setFromProjectionMatrix(this.projScreenMatrix)}isPointVisible(e){if(!this.enabled)return!0;const s=new m.Vector3(e.x,e.y,e.z);return this.frustum.containsPoint(s)}isSphereVisible(e,s){if(!this.enabled)return!0;const t=new m.Sphere(new m.Vector3(e.x,e.y,e.z),s);return this.frustum.intersectsSphere(t)}isLineVisible(e,s){if(!this.enabled)return!0;const t=new m.Vector3(e.x,e.y,e.z),i=new m.Vector3(s.x,s.y,s.z);if(this.frustum.containsPoint(t)||this.frustum.containsPoint(i))return!0;const o=new m.Vector3((e.x+s.x)/2,(e.y+s.y)/2,(e.z+s.z)/2),a=o.distanceTo(t),r=new m.Sphere(o,a);return this.frustum.intersectsSphere(r)}setEnabled(e){this.enabled=e}}class qe{constructor(e,s){l(this,"sceneManager");l(this,"raycaster");l(this,"mouse");l(this,"container");l(this,"onNodeClick",null);l(this,"onNodeHover",null);l(this,"onEdgeHover",null);l(this,"onEdgeClick",null);l(this,"hoveredNodeId",null);l(this,"hoveredEdgeKey",null);l(this,"nodeObjects",[]);l(this,"edgeObjects",[]);this.sceneManager=e,this.container=s,this.raycaster=new m.Raycaster,this.raycaster.params.Line={threshold:1.5},this.mouse=new m.Vector2,this.handleClick=this.handleClick.bind(this),this.handleMouseMove=this.handleMouseMove.bind(this),s.addEventListener("click",this.handleClick),s.addEventListener("mousemove",this.handleMouseMove)}setNodeObjects(e){this.nodeObjects=e}setEdgeObjects(e){this.edgeObjects=e}setClickCallback(e){this.onNodeClick=e}setHoverCallback(e){this.onNodeHover=e}setEdgeHoverCallback(e){this.onEdgeHover=e}setEdgeClickCallback(e){this.onEdgeClick=e}handleClick(e){const s=this.getIntersectedNode(e);if(s&&this.onNodeClick){this.onNodeClick(s);return}const t=this.getIntersectedEdge(e);t&&this.onEdgeClick&&this.onEdgeClick(t)}handleMouseMove(e){const s=this.getIntersectedNode(e),t=(s==null?void 0:s.id)??null;if(t!==this.hoveredNodeId&&(this.hoveredNodeId=t,this.onNodeHover&&this.onNodeHover(s)),s){this.hoveredEdgeKey!==null&&this.onEdgeHover&&(this.hoveredEdgeKey=null,this.onEdgeHover(null)),this.container.style.cursor="pointer";return}const i=this.getIntersectedEdge(e),o=i?`${i.edge.source}-${i.edge.target}`:null;o!==this.hoveredEdgeKey&&(this.hoveredEdgeKey=o,this.onEdgeHover&&this.onEdgeHover(i)),this.container.style.cursor=i?"pointer":"default"}getIntersectedNode(e){var i;const s=this.container.getBoundingClientRect();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);const t=this.raycaster.intersectObjects(this.nodeObjects,!0);if(t.length>0){let o=t[0].object;for(;o;){if((i=o.userData)!=null&&i.nodeData)return o.userData.nodeData;o=o.parent}}return null}getIntersectedEdge(e){const s=this.container.getBoundingClientRect();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);const t=this.raycaster.intersectObjects(this.edgeObjects,!1);if(t.length>0){const i=t[0].object,o=i.userData;if(o!=null&&o.edge&&(o!=null&&o.sourceNode)&&(o!=null&&o.targetNode))return{edge:o.edge,sourceNode:o.sourceNode,targetNode:o.targetNode,edgeLine:i}}return null}getIntersectedNodeId(e,s){var o;const t=this.container.getBoundingClientRect();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);const i=this.raycaster.intersectObjects(this.nodeObjects,!0);if(i.length>0){let a=i[0].object;for(;a;){if((o=a.userData)!=null&&o.nodeId)return a.userData.nodeId;a=a.parent}}return null}dispose(){this.container.removeEventListener("click",this.handleClick),this.container.removeEventListener("mousemove",this.handleMouseMove)}}class We{constructor(e){l(this,"container");l(this,"panel",null);l(this,"currentNodeId",null);l(this,"visible",!1);l(this,"panelTemplate",null);l(this,"panelStyles",{});l(this,"onExpand",null);this.container=e,this.createPanel()}createPanel(){this.panel=document.createElement("div"),this.panel.className="force-graph-panel",this.panel.style.cssText=`
66
+ `,transparent:!0,side:y.FrontSide,depthWrite:!0,blending:y.NormalBlending});return this.materialCache.set(t,o),o.clone()}createEdgeMaterial(e=6710886,s=.4){return new y.LineBasicMaterial({color:e,transparent:!0,opacity:s,linewidth:1})}createHighlightedEdgeMaterial(){return new y.LineBasicMaterial({color:16750950,transparent:!1,opacity:1,linewidth:2})}createLabelMaterial(e,s=24){const t=document.createElement("canvas"),i=t.getContext("2d");i.font=`600 ${s}px Inter, -apple-system, sans-serif`;const a=i.measureText(e).width;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);const r=new y.CanvasTexture(t);return r.needsUpdate=!0,new y.SpriteMaterial({map:r,transparent:!0,depthTest:!1,depthWrite:!1})}getEnvMap(){return this.envMap}dispose(){this.materialCache.forEach(e=>e.dispose()),this.materialCache.clear(),this.envMap&&this.envMap.dispose()}}class Ke{constructor(e,s=2,t=[32,16,8],i=16750950){l(this,"materialFactory");l(this,"geometryCache",new Map);l(this,"nodeRadius");l(this,"lodSegments");l(this,"defaultNodeColor");this.materialFactory=e,this.nodeRadius=s,this.lodSegments=t,this.defaultNodeColor=i,this.initGeometryCache()}initGeometryCache(){this.lodSegments.forEach((e,s)=>{const t=`lod-${s}`;this.geometryCache.set(t,new y.SphereGeometry(this.nodeRadius,e,e))})}getGeometry(e){const s=`lod-${e}`;return this.geometryCache.has(s)?this.geometryCache.get(s):this.geometryCache.get("lod-0")}createNode(e,s=0){const t=new y.Group;t.name=`node-${e.id}`,t.userData={nodeId:e.id,nodeData:e};const i=this.getGeometry(s),o=this.materialFactory.createGlassMaterial(e.color??this.defaultNodeColor),a=new y.Mesh(i,o);a.castShadow=!0,a.receiveShadow=!0,t.add(a);const r=this.materialFactory.createLabelMaterial(e.label),c=new y.Sprite(r);return c.position.y=this.nodeRadius+1.5,c.scale.set(4,1,1),t.add(c),e.position&&t.position.set(e.position.x,e.position.y,e.position.z),{group:t,sphere:a,label:c,lodLevel:s}}updateNodeLOD(e,s){if(e.lodLevel===s)return;const t=this.getGeometry(s);e.sphere.geometry=t,e.lodLevel=s}updateNodeColor(e,s){e.sphere.material instanceof y.Material&&e.sphere.material.dispose(),e.sphere.material=this.materialFactory.createGlassMaterial(s)}updateNodeLabel(e,s){e.label.material instanceof y.SpriteMaterial&&(e.label.material.map&&e.label.material.map.dispose(),e.label.material.dispose()),e.label.material=this.materialFactory.createLabelMaterial(s)}disposeNode(e){e.sphere.material instanceof y.Material&&e.sphere.material.dispose(),e.label.material instanceof y.SpriteMaterial&&(e.label.material.map&&e.label.material.map.dispose(),e.label.material.dispose())}dispose(){this.geometryCache.forEach(e=>e.dispose()),this.geometryCache.clear()}}class _e{constructor(e,s=10066329,t=.5){l(this,"materialFactory");l(this,"edgeColor");l(this,"edgeOpacity");l(this,"defaultMaterial",null);l(this,"highlightMaterial",null);this.materialFactory=e,this.edgeColor=s,this.edgeOpacity=t}getDefaultMaterial(){return this.defaultMaterial||(this.defaultMaterial=this.materialFactory.createEdgeMaterial(this.edgeColor,this.edgeOpacity)),this.defaultMaterial}getHighlightMaterial(){return this.highlightMaterial||(this.highlightMaterial=this.materialFactory.createHighlightedEdgeMaterial()),this.highlightMaterial}createEdge(e,s,t,i,o){const a=new y.BufferGeometry,r=new Float32Array([i.x,i.y,i.z,o.x,o.y,o.z]);a.setAttribute("position",new y.BufferAttribute(r,3));const c=this.getDefaultMaterial().clone(),h=new y.Line(a,c);return h.name=`edge-${e.source}-${e.target}`,h.userData={source:e.source,target:e.target,edge:e,sourceNode:s,targetNode:t},h.frustumCulled=!0,{line:h,source:e.source,target:e.target}}highlightEdge(e){e.line.material instanceof y.Material&&e.line.material.dispose(),e.line.material=this.getHighlightMaterial().clone()}unhighlightEdge(e){e.line.material instanceof y.Material&&e.line.material.dispose(),e.line.material=this.getDefaultMaterial().clone()}updateEdgePositions(e,s,t){const i=e.line.geometry.attributes.position,o=i.array;o[0]=s.x,o[1]=s.y,o[2]=s.z,o[3]=t.x,o[4]=t.y,o[5]=t.z,i.needsUpdate=!0,e.line.geometry.computeBoundingSphere()}disposeEdge(e){e.line.geometry.dispose(),e.line.material instanceof y.Material&&e.line.material.dispose()}dispose(){this.defaultMaterial&&this.defaultMaterial.dispose(),this.highlightMaterial&&this.highlightMaterial.dispose()}}class Xe{constructor(e,s=[50,100,200],t=!0){l(this,"camera");l(this,"lodDistances");l(this,"enabled");this.camera=e,this.lodDistances=s,this.enabled=t}getLODLevel(e){if(!this.enabled)return H.HIGH;const s=e.x-this.camera.position.x,t=e.y-this.camera.position.y,i=e.z-this.camera.position.z,o=Math.sqrt(s*s+t*t+i*i);return o<this.lodDistances[0]?H.HIGH:o<this.lodDistances[1]?H.MEDIUM:H.LOW}shouldRenderNode(e,s=500){const t=e.x-this.camera.position.x,i=e.y-this.camera.position.y,o=e.z-this.camera.position.z;return Math.sqrt(t*t+i*i+o*o)<s}setLODDistances(e){this.lodDistances=e}setEnabled(e){this.enabled=e}}class qe{constructor(e,s=!0){l(this,"camera");l(this,"frustum");l(this,"projScreenMatrix");l(this,"enabled");this.camera=e,this.frustum=new y.Frustum,this.projScreenMatrix=new y.Matrix4,this.enabled=s}update(){this.projScreenMatrix.multiplyMatrices(this.camera.projectionMatrix,this.camera.matrixWorldInverse),this.frustum.setFromProjectionMatrix(this.projScreenMatrix)}isPointVisible(e){if(!this.enabled)return!0;const s=new y.Vector3(e.x,e.y,e.z);return this.frustum.containsPoint(s)}isSphereVisible(e,s){if(!this.enabled)return!0;const t=new y.Sphere(new y.Vector3(e.x,e.y,e.z),s);return this.frustum.intersectsSphere(t)}isLineVisible(e,s){if(!this.enabled)return!0;const t=new y.Vector3(e.x,e.y,e.z),i=new y.Vector3(s.x,s.y,s.z);if(this.frustum.containsPoint(t)||this.frustum.containsPoint(i))return!0;const o=new y.Vector3((e.x+s.x)/2,(e.y+s.y)/2,(e.z+s.z)/2),a=o.distanceTo(t),r=new y.Sphere(o,a);return this.frustum.intersectsSphere(r)}setEnabled(e){this.enabled=e}}class We{constructor(e,s){l(this,"sceneManager");l(this,"raycaster");l(this,"mouse");l(this,"container");l(this,"onNodeClick",null);l(this,"onNodeHover",null);l(this,"onEdgeHover",null);l(this,"onEdgeClick",null);l(this,"hoveredNodeId",null);l(this,"hoveredEdgeKey",null);l(this,"nodeObjects",[]);l(this,"edgeObjects",[]);this.sceneManager=e,this.container=s,this.raycaster=new y.Raycaster,this.raycaster.params.Line={threshold:1.5},this.mouse=new y.Vector2,this.handleClick=this.handleClick.bind(this),this.handleMouseMove=this.handleMouseMove.bind(this),s.addEventListener("click",this.handleClick),s.addEventListener("mousemove",this.handleMouseMove)}setNodeObjects(e){this.nodeObjects=e}setEdgeObjects(e){this.edgeObjects=e}setClickCallback(e){this.onNodeClick=e}setHoverCallback(e){this.onNodeHover=e}setEdgeHoverCallback(e){this.onEdgeHover=e}setEdgeClickCallback(e){this.onEdgeClick=e}handleClick(e){const s=this.getIntersectedNode(e);if(s&&this.onNodeClick){this.onNodeClick(s);return}const t=this.getIntersectedEdge(e);t&&this.onEdgeClick&&this.onEdgeClick(t)}handleMouseMove(e){const s=this.getIntersectedNode(e),t=(s==null?void 0:s.id)??null;if(t!==this.hoveredNodeId&&(this.hoveredNodeId=t,this.onNodeHover&&this.onNodeHover(s)),s){this.hoveredEdgeKey!==null&&this.onEdgeHover&&(this.hoveredEdgeKey=null,this.onEdgeHover(null)),this.container.style.cursor="pointer";return}const i=this.getIntersectedEdge(e),o=i?`${i.edge.source}-${i.edge.target}`:null;o!==this.hoveredEdgeKey&&(this.hoveredEdgeKey=o,this.onEdgeHover&&this.onEdgeHover(i)),this.container.style.cursor=i?"pointer":"default"}getIntersectedNode(e){var i;const s=this.container.getBoundingClientRect();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);const t=this.raycaster.intersectObjects(this.nodeObjects,!0);if(t.length>0){let o=t[0].object;for(;o;){if((i=o.userData)!=null&&i.nodeData)return o.userData.nodeData;o=o.parent}}return null}getIntersectedEdge(e){const s=this.container.getBoundingClientRect();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);const t=this.raycaster.intersectObjects(this.edgeObjects,!1);if(t.length>0){const i=t[0].object,o=i.userData;if(o!=null&&o.edge&&(o!=null&&o.sourceNode)&&(o!=null&&o.targetNode))return{edge:o.edge,sourceNode:o.sourceNode,targetNode:o.targetNode,edgeLine:i}}return null}getIntersectedNodeId(e,s){var o;const t=this.container.getBoundingClientRect();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);const i=this.raycaster.intersectObjects(this.nodeObjects,!0);if(i.length>0){let a=i[0].object;for(;a;){if((o=a.userData)!=null&&o.nodeId)return a.userData.nodeId;a=a.parent}}return null}dispose(){this.container.removeEventListener("click",this.handleClick),this.container.removeEventListener("mousemove",this.handleMouseMove)}}class Ze{constructor(e){l(this,"container");l(this,"panel",null);l(this,"currentNodeId",null);l(this,"visible",!1);l(this,"panelTemplate",null);l(this,"panelStyles",{});l(this,"onExpand",null);this.container=e,this.createPanel()}createPanel(){this.panel=document.createElement("div"),this.panel.className="force-graph-panel",this.panel.style.cssText=`
67
67
  position: absolute;
68
68
  right: 20px;
69
69
  top: 50%;
@@ -249,7 +249,7 @@
249
249
  <button class="btn-expand" data-action="expand">Expand</button>
250
250
  <button class="btn-close" data-action="close">Close</button>
251
251
  </div>
252
- `}escapeHtml(e){const s=document.createElement("div");return s.textContent=e,s.innerHTML}hide(){this.panel&&(this.panel.style.opacity="0",this.panel.style.pointerEvents="none",this.panel.style.transform="translateY(-50%) translateX(20px)",this.visible=!1,this.currentNodeId=null)}isVisible(){return this.visible}getCurrentNodeId(){return this.currentNodeId}dispose(){this.panel&&this.panel.parentNode&&this.panel.parentNode.removeChild(this.panel),this.panel=null}}class Ze{constructor(e){l(this,"container");l(this,"panel",null);l(this,"currentEdgeKey",null);l(this,"visible",!1);l(this,"panelTemplate",null);l(this,"onClose",null);l(this,"onNodeClick",null);this.container=e,this.createPanel()}createPanel(){this.panel=document.createElement("div"),this.panel.className="force-graph-edge-panel",this.panel.style.cssText=`
252
+ `}escapeHtml(e){const s=document.createElement("div");return s.textContent=e,s.innerHTML}hide(){this.panel&&(this.panel.style.opacity="0",this.panel.style.pointerEvents="none",this.panel.style.transform="translateY(-50%) translateX(20px)",this.visible=!1,this.currentNodeId=null)}isVisible(){return this.visible}getCurrentNodeId(){return this.currentNodeId}dispose(){this.panel&&this.panel.parentNode&&this.panel.parentNode.removeChild(this.panel),this.panel=null}}class Qe{constructor(e){l(this,"container");l(this,"panel",null);l(this,"currentEdgeKey",null);l(this,"visible",!1);l(this,"panelTemplate",null);l(this,"onClose",null);l(this,"onNodeClick",null);this.container=e,this.createPanel()}createPanel(){this.panel=document.createElement("div"),this.panel.className="force-graph-edge-panel",this.panel.style.cssText=`
253
253
  position: absolute;
254
254
  right: 20px;
255
255
  top: 50%;
@@ -399,7 +399,7 @@
399
399
  <p class="hint-text">Click on a node to focus on it</p>
400
400
 
401
401
  <button class="btn-close" data-action="close">Close</button>
402
- `}escapeHtml(e){const s=document.createElement("div");return s.textContent=e,s.innerHTML}hide(){this.panel&&(this.panel.style.opacity="0",this.panel.style.pointerEvents="none",this.panel.style.transform="translateY(-50%) translateX(20px)",this.visible=!1,this.currentEdgeKey=null)}isVisible(){return this.visible}getCurrentEdgeKey(){return this.currentEdgeKey}dispose(){this.panel&&this.panel.parentNode&&this.panel.parentNode.removeChild(this.panel),this.panel=null}}class Qe{constructor(){l(this,"tooltip",null);l(this,"visible",!1);this.createTooltip(),this.setupMouseTracking()}createTooltip(){this.tooltip=document.createElement("div"),this.tooltip.className="force-graph-edge-tooltip",this.tooltip.style.cssText=`
402
+ `}escapeHtml(e){const s=document.createElement("div");return s.textContent=e,s.innerHTML}hide(){this.panel&&(this.panel.style.opacity="0",this.panel.style.pointerEvents="none",this.panel.style.transform="translateY(-50%) translateX(20px)",this.visible=!1,this.currentEdgeKey=null)}isVisible(){return this.visible}getCurrentEdgeKey(){return this.currentEdgeKey}dispose(){this.panel&&this.panel.parentNode&&this.panel.parentNode.removeChild(this.panel),this.panel=null}}class Je{constructor(){l(this,"tooltip",null);l(this,"visible",!1);this.createTooltip(),this.setupMouseTracking()}createTooltip(){this.tooltip=document.createElement("div"),this.tooltip.className="force-graph-edge-tooltip",this.tooltip.style.cssText=`
403
403
  position: fixed;
404
404
  padding: 10px 14px;
405
405
  background: rgba(30, 30, 30, 0.95);
@@ -432,7 +432,7 @@
432
432
  <span style="font-weight: 600; color: #ff9966;">${this.escapeHtml(t.label)}</span>
433
433
  </div>
434
434
  </div>
435
- `,this.positionTooltip(i,o),this.tooltip.style.opacity="1",this.tooltip.style.transform="translateY(0)",this.visible=!0}updatePosition(e,s){this.visible&&this.positionTooltip(e,s)}hide(){this.tooltip&&(this.tooltip.style.opacity="0",this.tooltip.style.transform="translateY(5px)",this.visible=!1)}isVisible(){return this.visible}escapeHtml(e){const s=document.createElement("div");return s.textContent=e,s.innerHTML}dispose(){this.tooltip&&this.tooltip.parentNode&&this.tooltip.parentNode.removeChild(this.tooltip),this.tooltip=null}}class Je{constructor(e,s){l(this,"container");l(this,"searchContainer",null);l(this,"searchInput",null);l(this,"searchResults",null);l(this,"searchTimeout",null);l(this,"placeholder");l(this,"onSearch");l(this,"onResultClick");this.container=e,this.placeholder=s.placeholder||"Search nodes or relationships...",this.onSearch=s.onSearch,this.onResultClick=s.onResultClick,this.init()}init(){this.createSearchUI(),this.addEventListeners()}createSearchUI(){this.searchContainer=document.createElement("div"),this.searchContainer.className="f3d-search-container",Object.assign(this.searchContainer.style,{position:"absolute",top:"20px",left:"175px",zIndex:"100",width:"320px"});const e=document.createElement("div");e.className="f3d-search-input-wrapper",Object.assign(e.style,{position:"relative",display:"flex",alignItems:"center"}),e.innerHTML=`
435
+ `,this.positionTooltip(i,o),this.tooltip.style.opacity="1",this.tooltip.style.transform="translateY(0)",this.visible=!0}updatePosition(e,s){this.visible&&this.positionTooltip(e,s)}hide(){this.tooltip&&(this.tooltip.style.opacity="0",this.tooltip.style.transform="translateY(5px)",this.visible=!1)}isVisible(){return this.visible}escapeHtml(e){const s=document.createElement("div");return s.textContent=e,s.innerHTML}dispose(){this.tooltip&&this.tooltip.parentNode&&this.tooltip.parentNode.removeChild(this.tooltip),this.tooltip=null}}class et{constructor(e,s){l(this,"container");l(this,"searchContainer",null);l(this,"searchInput",null);l(this,"searchResults",null);l(this,"searchTimeout",null);l(this,"placeholder");l(this,"onSearch");l(this,"onResultClick");this.container=e,this.placeholder=s.placeholder||"Search nodes or relationships...",this.onSearch=s.onSearch,this.onResultClick=s.onResultClick,this.init()}init(){this.createSearchUI(),this.addEventListeners()}createSearchUI(){this.searchContainer=document.createElement("div"),this.searchContainer.className="f3d-search-container",Object.assign(this.searchContainer.style,{position:"absolute",top:"20px",left:"175px",zIndex:"100",width:"320px"});const e=document.createElement("div");e.className="f3d-search-input-wrapper",Object.assign(e.style,{position:"relative",display:"flex",alignItems:"center"}),e.innerHTML=`
436
436
  <svg class="f3d-search-icon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor"
437
437
  stroke-width="2" style="position: absolute; left: 14px; z-index: 10; color: rgba(255, 255, 255, 0.5); pointer-events: none;">
438
438
  <circle cx="11" cy="11" r="8"></circle>
@@ -497,7 +497,7 @@
497
497
  <div class="f3d-result-label">${this.escapeHtml(a.label)} → ${this.escapeHtml(r.label)}</div>
498
498
  <div class="f3d-result-relationship">${this.escapeHtml(o.relationship||"connected")}</div>
499
499
  </div>
500
- `}),t.length>5&&(i+=`<div class="f3d-no-results">+ ${t.length-5} more relationships</div>`)),this.searchResults.innerHTML=i,this.searchResults.style.display="block",this.searchResults.querySelectorAll(".f3d-search-result-item").forEach(o=>{o.addEventListener("click",()=>{const a=o.dataset.nodeId;a&&(this.onResultClick(a),this.searchResults&&(this.searchResults.style.display="none"),this.searchInput&&this.searchInput.blur())})})}escapeHtml(e){const s=document.createElement("div");return s.textContent=e,s.innerHTML}dispose(){this.searchContainer&&this.searchContainer.parentNode&&this.searchContainer.parentNode.removeChild(this.searchContainer)}}class et{constructor(e,s){l(this,"container");l(this,"toggleContainer",null);l(this,"currentMode","3d");l(this,"onViewChange");this.container=e,this.currentMode=s.initialMode||"3d",this.onViewChange=s.onViewChange,this.init()}init(){this.createToggleUI()}createToggleUI(){this.toggleContainer=document.createElement("div"),this.toggleContainer.className="f3d-view-toggle",Object.assign(this.toggleContainer.style,{position:"absolute",top:"20px",left:"20px",zIndex:"100",display:"flex",gap:"0",background:"rgba(255, 255, 255, 0.08)",backdropFilter:"blur(20px)",WebkitBackdropFilter:"blur(20px)",border:"1px solid rgba(255, 255, 255, 0.12)",borderRadius:"12px",padding:"5px",boxShadow:"0 4px 20px rgba(0, 0, 0, 0.3)"});const e=this.createButton("2D","2d"),s=this.createButton("3D","3d");this.toggleContainer.appendChild(e),this.toggleContainer.appendChild(s),this.container.appendChild(this.toggleContainer),this.updateButtonStates();const t=document.createElement("style");t.textContent=`
500
+ `}),t.length>5&&(i+=`<div class="f3d-no-results">+ ${t.length-5} more relationships</div>`)),this.searchResults.innerHTML=i,this.searchResults.style.display="block",this.searchResults.querySelectorAll(".f3d-search-result-item").forEach(o=>{o.addEventListener("click",()=>{const a=o.dataset.nodeId;a&&(this.onResultClick(a),this.searchResults&&(this.searchResults.style.display="none"),this.searchInput&&this.searchInput.blur())})})}escapeHtml(e){const s=document.createElement("div");return s.textContent=e,s.innerHTML}dispose(){this.searchContainer&&this.searchContainer.parentNode&&this.searchContainer.parentNode.removeChild(this.searchContainer)}}class tt{constructor(e,s){l(this,"container");l(this,"toggleContainer",null);l(this,"currentMode","3d");l(this,"onViewChange");this.container=e,this.currentMode=s.initialMode||"3d",this.onViewChange=s.onViewChange,this.init()}init(){this.createToggleUI()}createToggleUI(){this.toggleContainer=document.createElement("div"),this.toggleContainer.className="f3d-view-toggle",Object.assign(this.toggleContainer.style,{position:"absolute",top:"20px",left:"20px",zIndex:"100",display:"flex",gap:"0",background:"rgba(255, 255, 255, 0.08)",backdropFilter:"blur(20px)",WebkitBackdropFilter:"blur(20px)",border:"1px solid rgba(255, 255, 255, 0.12)",borderRadius:"12px",padding:"5px",boxShadow:"0 4px 20px rgba(0, 0, 0, 0.3)"});const e=this.createButton("2D","2d"),s=this.createButton("3D","3d");this.toggleContainer.appendChild(e),this.toggleContainer.appendChild(s),this.container.appendChild(this.toggleContainer),this.updateButtonStates();const t=document.createElement("style");t.textContent=`
501
501
  .f3d-view-btn {
502
502
  padding: 8px 16px;
503
503
  background: transparent;
@@ -532,7 +532,7 @@
532
532
  <path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path>
533
533
  <polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline>
534
534
  <line x1="12" y1="22.08" x2="12" y2="12"></line>
535
- </svg>`}updateButtonStates(){if(!this.toggleContainer)return;this.toggleContainer.querySelectorAll(".f3d-view-btn").forEach(s=>{s.dataset.mode===this.currentMode?s.classList.add("active"):s.classList.remove("active")})}setMode(e){this.currentMode!==e&&(this.currentMode=e,this.updateButtonStates())}getMode(){return this.currentMode}dispose(){this.toggleContainer&&this.toggleContainer.parentNode&&this.toggleContainer.parentNode.removeChild(this.toggleContainer)}}const tt={backgroundColor:"#0a0a0a",gridColor:"rgba(255, 255, 255, 0.03)",nodeRadius:24,edgeColor:"rgba(255, 255, 255, 0.15)",edgeOpacity:.4,repulsionStrength:5e3,attractionStrength:.001,damping:.85};class st{constructor(e,s={}){l(this,"container");l(this,"canvas");l(this,"ctx");l(this,"options");l(this,"nodes",new Map);l(this,"edges",[]);l(this,"nodeIdToIndex",new Map);l(this,"transform",{x:0,y:0,scale:1});l(this,"isDragging",!1);l(this,"isPanning",!1);l(this,"draggedNode",null);l(this,"hoveredNode",null);l(this,"hoveredEdge",null);l(this,"lastMousePos",{x:0,y:0});l(this,"dragStartPos",{x:0,y:0});l(this,"selectedNode",null);l(this,"animationId",null);l(this,"isSimulating",!0);l(this,"resizeHandler");this.container=e,this.options={...tt,...s},this.canvas=document.createElement("canvas"),this.canvas.style.position="absolute",this.canvas.style.top="0",this.canvas.style.left="0",this.canvas.style.width="100%",this.canvas.style.height="100%",this.canvas.style.cursor="grab",e.appendChild(this.canvas);const t=this.canvas.getContext("2d");if(!t)throw new Error("Failed to get 2D context");this.ctx=t,this.resizeHandler=this.handleResize.bind(this),window.addEventListener("resize",this.resizeHandler),this.handleResize(),this.transform.x=this.canvas.width/2,this.transform.y=this.canvas.height/2,this.setupInteractions(),this.startAnimation()}handleResize(){const e=this.container.getBoundingClientRect(),s=window.devicePixelRatio||1;this.canvas.width=e.width*s,this.canvas.height=e.height*s,this.ctx.scale(s,s)}setupInteractions(){this.canvas.addEventListener("wheel",e=>{e.preventDefault();const s=this.canvas.getBoundingClientRect(),t=e.clientX-s.left,i=e.clientY-s.top,o=e.deltaY>0?.9:1.1,a=Math.max(.1,Math.min(5,this.transform.scale*o)),r=a/this.transform.scale;this.transform.x=t-(t-this.transform.x)*r,this.transform.y=i-(i-this.transform.y)*r,this.transform.scale=a}),this.canvas.addEventListener("mousedown",e=>{const s=this.canvas.getBoundingClientRect(),t=e.clientX-s.left,i=e.clientY-s.top,o=this.screenToWorld(t,i),a=this.findNodeAt(o.x,o.y);this.dragStartPos={x:e.clientX,y:e.clientY},a?(this.isDragging=!0,this.draggedNode=a,this.canvas.style.cursor="grabbing",this.isSimulating=!0):(this.isPanning=!0,this.canvas.style.cursor="grabbing"),this.lastMousePos={x:e.clientX,y:e.clientY}}),this.canvas.addEventListener("mousemove",e=>{const s=this.canvas.getBoundingClientRect(),t=e.clientX-s.left,i=e.clientY-s.top,o=this.screenToWorld(t,i);if(this.isDragging&&this.draggedNode)this.draggedNode.x=o.x,this.draggedNode.y=o.y,this.draggedNode.vx=0,this.draggedNode.vy=0;else if(this.isPanning){const a=e.clientX-this.lastMousePos.x,r=e.clientY-this.lastMousePos.y;this.transform.x+=a,this.transform.y+=r,this.lastMousePos={x:e.clientX,y:e.clientY}}else{const a=this.findNodeAt(o.x,o.y);if(a!==this.hoveredNode&&(this.hoveredNode=a,a?(this.hoveredEdge&&(this.hoveredEdge=null,this.options.onEdgeHover&&this.options.onEdgeHover(null)),this.canvas.style.cursor="pointer",this.options.onNodeHover&&this.options.onNodeHover(a.data)):this.options.onNodeHover&&this.options.onNodeHover(null)),!a){const r=this.findEdgeAt(o.x,o.y);r!==this.hoveredEdge&&(this.hoveredEdge=r,this.canvas.style.cursor=r?"pointer":"grab",this.options.onEdgeHover&&this.options.onEdgeHover(r?r.data:null,e))}}}),this.canvas.addEventListener("mouseup",e=>{const s=Math.abs(e.clientX-this.dragStartPos.x),t=Math.abs(e.clientY-this.dragStartPos.y),i=s<5&&t<5;if(this.isDragging&&this.draggedNode)i&&this.options.onNodeClick&&(this.selectedNode=this.draggedNode,this.options.onNodeClick(this.draggedNode.data));else if(i){const o=this.canvas.getBoundingClientRect(),a=this.screenToWorld(e.clientX-o.left,e.clientY-o.top),r=this.findEdgeAt(a.x,a.y);r&&this.options.onEdgeClick&&this.options.onEdgeClick(r.data)}this.isDragging=!1,this.isPanning=!1,this.draggedNode=null,this.canvas.style.cursor=this.hoveredNode?"pointer":"grab"}),this.canvas.addEventListener("mouseleave",()=>{this.isDragging=!1,this.isPanning=!1,this.draggedNode=null,this.hoveredNode=null,this.canvas.style.cursor="grab"})}screenToWorld(e,s){return{x:(e-this.transform.x)/this.transform.scale,y:(s-this.transform.y)/this.transform.scale}}findNodeAt(e,s){for(const t of this.nodes.values()){const i=t.x-e,o=t.y-s;if(Math.sqrt(i*i+o*o)<t.radius)return t}return null}findEdgeAt(e,s){for(const i of this.edges){const o=this.nodes.get(i.source),a=this.nodes.get(i.target);if(!o||!a)continue;const r=a.x-o.x,c=a.y-o.y,d=r*r+c*c;if(d===0)continue;const p=Math.max(0,Math.min(1,((e-o.x)*r+(s-o.y)*c)/d)),b=o.x+p*r,y=o.y+p*c,f=e-b,x=s-y;if(Math.sqrt(f*f+x*x)<12)return i}return null}startAnimation(){const e=()=>{this.isSimulating&&this.simulate(),this.render(),this.animationId=requestAnimationFrame(e)};e()}simulate(){const e=Array.from(this.nodes.values()),s=e.length;if(s===0)return;const t=60,i=5;let o=0;for(let r=0;r<s;r++)for(let c=r+1;c<s;c++){const d=e[r],p=e[c];let b=p.x-d.x,y=p.y-d.y,f=Math.sqrt(b*b+y*y);if(f<t*3){f<1&&(f=1);const x=this.options.repulsionStrength/(f*f),v=b/f*x,w=y/f*x;d.vx-=v,d.vy-=w,p.vx+=v,p.vy+=w}}const a=80;for(const r of this.edges){const c=this.nodes.get(r.source),d=this.nodes.get(r.target);if(!c||!d)continue;let p=d.x-c.x,b=d.y-c.y,y=Math.sqrt(p*p+b*b);y<1&&(y=1);const x=(y-a)*this.options.attractionStrength,v=p/y*x,w=b/y*x;c.vx+=v,c.vy+=w,d.vx-=v,d.vy-=w}for(const r of e){if(this.draggedNode===r)continue;r.vx*=this.options.damping,r.vy*=this.options.damping;const c=Math.sqrt(r.vx*r.vx+r.vy*r.vy);c>i&&(r.vx=r.vx/c*i,r.vy=r.vy/c*i),r.x+=r.vx,r.y+=r.vy,o+=r.vx*r.vx+r.vy*r.vy}o<.01&&!this.draggedNode&&(this.isSimulating=!1)}render(){const e=this.ctx,s=this.canvas.width/(window.devicePixelRatio||1),t=this.canvas.height/(window.devicePixelRatio||1);e.fillStyle=this.options.backgroundColor,e.fillRect(0,0,s,t),this.renderGrid(s,t),e.save(),e.translate(this.transform.x,this.transform.y),e.scale(this.transform.scale,this.transform.scale),this.renderEdges(),this.renderNodes(),e.restore()}renderGrid(e,s){const t=this.ctx,i=40*this.transform.scale,o=1.5,a=this.transform.x%i,r=this.transform.y%i;t.fillStyle=this.options.gridColor;for(let c=a;c<e;c+=i)for(let d=r;d<s;d+=i)t.beginPath(),t.arc(c,d,o,0,Math.PI*2),t.fill()}renderEdges(){const e=this.ctx;for(const s of this.edges){const t=this.nodes.get(s.source),i=this.nodes.get(s.target);if(!t||!i)continue;const o=s===this.hoveredEdge,a=e.createLinearGradient(t.x,t.y,i.x,i.y);o?(a.addColorStop(0,"rgba(255, 153, 102, 0.8)"),a.addColorStop(.5,"rgba(255, 255, 255, 0.5)"),a.addColorStop(1,"rgba(102, 153, 255, 0.8)"),e.lineWidth=3):(a.addColorStop(0,"rgba(255, 153, 102, 0.3)"),a.addColorStop(.5,"rgba(255, 255, 255, 0.15)"),a.addColorStop(1,"rgba(102, 153, 255, 0.3)"),e.lineWidth=1.5),e.beginPath(),e.moveTo(t.x,t.y),e.lineTo(i.x,i.y),e.strokeStyle=a,e.stroke()}}renderNodes(){const e=this.ctx;for(const s of this.nodes.values()){const t=s===this.hoveredNode,i=s===this.selectedNode,o=this.hoveredEdge&&(s.data.id===this.hoveredEdge.source||s.data.id===this.hoveredEdge.target),a=s.radius*(t?1.1:1);if(t||i||o){const x=e.createRadialGradient(s.x,s.y,a*.5,s.x,s.y,a*2),v=t||i?.4:.25;x.addColorStop(0,`rgba(255, 153, 102, ${v})`),x.addColorStop(1,"rgba(255, 153, 102, 0)"),e.fillStyle=x,e.beginPath(),e.arc(s.x,s.y,a*2,0,Math.PI*2),e.fill()}const r=e.createRadialGradient(s.x-a*.3,s.y-a*.3,0,s.x,s.y,a),c=s.color>>16&255,d=s.color>>8&255,p=s.color&255;r.addColorStop(0,`rgba(${Math.min(255,c+60)}, ${Math.min(255,d+60)}, ${Math.min(255,p+60)}, 0.95)`),r.addColorStop(.7,`rgba(${c}, ${d}, ${p}, 0.9)`),r.addColorStop(1,`rgba(${Math.max(0,c-40)}, ${Math.max(0,d-40)}, ${Math.max(0,p-40)}, 0.85)`),e.beginPath(),e.arc(s.x,s.y,a,0,Math.PI*2),e.fillStyle=r,e.fill(),e.strokeStyle="rgba(255, 255, 255, 0.2)",e.lineWidth=1,e.stroke(),e.beginPath(),e.arc(s.x-a*.25,s.y-a*.25,a*.3,0,Math.PI*2),e.fillStyle="rgba(255, 255, 255, 0.15)",e.fill(),e.fillStyle="white",e.font="600 11px Inter, -apple-system, BlinkMacSystemFont, sans-serif",e.textAlign="center",e.textBaseline="middle";const b=a*1.6;let y=s.label,f=e.measureText(y).width;if(f>b){for(;f>b&&y.length>3;)y=y.slice(0,-1),f=e.measureText(y+"...").width;y+="..."}e.shadowColor="rgba(0, 0, 0, 0.5)",e.shadowBlur=3,e.fillText(y,s.x,s.y),e.shadowBlur=0}}setData(e){this.nodes.clear(),this.edges=[],this.nodeIdToIndex.clear(),e.nodes.forEach((s,t)=>{const i=s.position||{x:(Math.random()-.5)*300,y:(Math.random()-.5)*300},o={id:s.id,label:s.label,x:i.x,y:i.y,vx:0,vy:0,color:s.color||16750950,radius:this.options.nodeRadius,data:s};this.nodes.set(s.id,o),this.nodeIdToIndex.set(s.id,t)}),this.edges=e.edges.map(s=>({source:s.source,target:s.target,relationship:s.relationship,data:s}))}addNode(e){const s=e.position||{x:(Math.random()-.5)*300,y:(Math.random()-.5)*300},t={id:e.id,label:e.label,x:s.x,y:s.y,vx:0,vy:0,color:e.color||16750950,radius:this.options.nodeRadius,data:e};this.nodes.set(e.id,t)}addEdge(e){this.edges.push({source:e.source,target:e.target,relationship:e.relationship,data:e})}removeNode(e){this.nodes.delete(e),this.edges=this.edges.filter(s=>s.source!==e&&s.target!==e)}getNode(e){return this.nodes.get(e)}getAllNodes(){return Array.from(this.nodes.values()).map(e=>e.data)}getNodeCount(){return this.nodes.size}getEdgeCount(){return this.edges.length}focusOnNode(e){const s=this.nodes.get(e);if(!s)return;const t=this.canvas.width/2/(window.devicePixelRatio||1)-s.x*this.transform.scale,i=this.canvas.height/2/(window.devicePixelRatio||1)-s.y*this.transform.scale,o=this.transform.x,a=this.transform.y,r=500,c=performance.now(),d=()=>{const p=performance.now()-c,b=Math.min(p/r,1),y=1-Math.pow(1-b,3);this.transform.x=o+(t-o)*y,this.transform.y=a+(i-a)*y,b<1?requestAnimationFrame(d):this.selectedNode=s};d()}syncFrom3D(e){e.forEach((s,t)=>{const i=this.nodes.get(t);i&&(i.x=s.position.x*3,i.y=s.position.y*3,i.vx=0,i.vy=0)}),this.isSimulating=!1}getPositions(){const e=new Map;return this.nodes.forEach((s,t)=>{e.set(t,{x:s.x,y:s.y})}),e}show(){this.canvas.style.display="block"}hide(){this.canvas.style.display="none"}setPhysicsParams(e){e.repulsionStrength!==void 0&&(this.options.repulsionStrength=e.repulsionStrength),e.attractionStrength!==void 0&&(this.options.attractionStrength=e.attractionStrength),e.damping!==void 0&&(this.options.damping=e.damping),this.isSimulating=!0}dispose(){this.animationId&&cancelAnimationFrame(this.animationId),window.removeEventListener("resize",this.resizeHandler),this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas)}}class it{constructor(e,s={}){l(this,"options");l(this,"container");l(this,"sceneManager");l(this,"nodeManager");l(this,"edgeManager");l(this,"graphEngine");l(this,"rendererManager");l(this,"materialFactory");l(this,"nodeFactory");l(this,"edgeFactory");l(this,"lodManager");l(this,"frustumCuller");l(this,"raycasterManager");l(this,"panelManager");l(this,"edgePanelManager");l(this,"edgeTooltipManager");l(this,"searchManager",null);l(this,"viewToggleManager",null);l(this,"forceGraph2D",null);l(this,"eventCallbacks",new Map);l(this,"initialized",!1);l(this,"devControls",null);l(this,"viewMode","3d");l(this,"graphData",null);this.options={...P,...s},this.container=De(e),this.materialFactory=new Ve,this.nodeFactory=new Ke(this.materialFactory,this.options.nodeRadius??P.nodeRadius,this.options.lodSegments??P.lodSegments,this.options.defaultNodeColor??P.defaultNodeColor),this.edgeFactory=new Ue(this.materialFactory,this.options.edgeColor??P.edgeColor,this.options.edgeOpacity??P.edgeOpacity),this.sceneManager=new He(this.container,this.options),this.lodManager=new Xe(this.sceneManager.camera,this.options.lodDistances??P.lodDistances,this.options.enableLOD??P.enableLOD),this.frustumCuller=new _e(this.sceneManager.camera,this.options.enableEdgeCulling??P.enableEdgeCulling),this.nodeManager=new $e(this.sceneManager,this.nodeFactory),this.edgeManager=new Ge(this.sceneManager,this.nodeManager,this.edgeFactory),this.graphEngine=new ge(this.nodeManager.getAllNodes(),this.edgeManager.getAllEdges(),{repulsionStrength:this.options.repulsionStrength,attractionStrength:this.options.attractionStrength,damping:this.options.damping,useBarnesHut:this.options.useBarnesHut,barnesHutTheta:this.options.barnesHutTheta}),this.rendererManager=new Be(this.sceneManager,()=>this.onSimulate(),()=>this.onRender(),this.options.targetFPS??P.targetFPS),this.raycasterManager=new qe(this.sceneManager,this.container),this.panelManager=new We(this.container),this.edgePanelManager=new Ze(this.container),this.edgeTooltipManager=new Qe,this.edgePanelManager.setNodeClickCallback(t=>{this.edgePanelManager.hide(),this.focusOnNode(t),setTimeout(()=>{this.showNodePanel(t)},400)}),this.options.showSearch!==!1&&(this.searchManager=new Je(this.container,{placeholder:this.options.searchPlaceholder,onSearch:t=>({nodeResults:this.searchNodes(t),edgeResults:this.searchEdges(t)}),onResultClick:t=>{this.focusOnNode(t),setTimeout(()=>{this.showNodePanel(t)},400)}})),this.options.showViewToggle!==!1&&(this.viewMode=this.options.initialViewMode||"3d",this.viewToggleManager=new et(this.container,{initialMode:this.viewMode,onViewChange:t=>{this.switchView(t)}})),this.setupCallbacks(),this.rendererManager.start(),this.initialized=!0,this.emit("ready")}setupCallbacks(){this.raycasterManager.setClickCallback(e=>{this.onNodeClick(e)}),this.options.onNodeHover&&this.raycasterManager.setHoverCallback(this.options.onNodeHover),this.panelManager.setExpandCallback((e,s)=>{this.expandNode(e,s)}),this.options.panelTemplate&&this.panelManager.setPanelTemplate(this.options.panelTemplate),this.options.panelStyles&&this.panelManager.setPanelStyles(this.options.panelStyles),this.raycasterManager.setEdgeHoverCallback(e=>{this.onEdgeHover(e)}),this.raycasterManager.setEdgeClickCallback(e=>{this.onEdgeClick(e)})}onEdgeHover(e){if(e){this.edgeManager.highlightEdge(e.edge.source,e.edge.target);const s=this.container.getBoundingClientRect(),t=s.left+s.width/2,i=s.top+s.height/2;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)}else this.edgeManager.unhighlightCurrentEdge(),this.edgeTooltipManager.hide(),this.options.onEdgeHover&&this.options.onEdgeHover(null,null,null),this.emit("edgeHover",null,null,null)}onNodeClick(e){this.edgePanelManager.hide();const t=this.edgeManager.getNeighborIds(e.id).map(i=>this.nodeManager.getNode(i)).filter(i=>i!==void 0);this.options.showPanel!==!1&&this.panelManager.show(e,t),this.options.onNodeClick&&this.options.onNodeClick(e),this.emit("nodeClick",e)}onEdgeClick(e){this.panelManager.hide(),this.edgeTooltipManager.hide(),this.edgeManager.highlightEdge(e.edge.source,e.edge.target),this.edgePanelManager.show(e.edge,e.sourceNode,e.targetNode),this.focusOnEdge(e.edge.source,e.edge.target),this.emit("edgeClick",e.edge,e.sourceNode,e.targetNode)}onSimulate(){this.graphEngine.simulate();for(const[e,s]of this.nodeManager.getAllNodes())if(this.nodeManager.updateNodePosition(e,s.position),this.options.enableLOD){const t=this.lodManager.getLODLevel(s.position);this.nodeManager.updateNodeLOD(e,t)}this.edgeManager.updateEdgePositions()}onRender(){this.frustumCuller.update(),this.raycasterManager.setNodeObjects(this.nodeManager.getAllNodeObjects()),this.raycasterManager.setEdgeObjects(this.edgeManager.getAllEdgeLines())}setData(e){if(this.graphData=e,this.edgeManager.clear(),this.nodeManager.clear(),e.nodes&&Array.isArray(e.nodes))for(const s of e.nodes)this.addNode(s);if(e.edges&&Array.isArray(e.edges))for(const s of e.edges)this.addEdge(s);this.graphEngine=new ge(this.nodeManager.getAllNodes(),this.edgeManager.getAllEdges(),{repulsionStrength:this.options.repulsionStrength,attractionStrength:this.options.attractionStrength,damping:this.options.damping,useBarnesHut:this.options.useBarnesHut,barnesHutTheta:this.options.barnesHutTheta}),this.graphEngine.restart(),this.forceGraph2D&&this.forceGraph2D.setData(e)}addNode(e){if(!J(e))return!1;const s=this.nodeManager.addNode(e);return s&&(this.graphEngine.restart(),this.forceGraph2D&&this.forceGraph2D.addNode(e),this.options.onNodeAdd&&this.options.onNodeAdd(e),this.emit("nodeAdd",e)),s}removeNode(e){if(!Fe(e))return!1;this.edgeManager.removeEdgesForNode(e);const s=this.nodeManager.removeNode(e);return s&&(this.graphEngine.restart(),this.options.onNodeRemove&&this.options.onNodeRemove(e),this.emit("nodeRemove",e),this.panelManager.getCurrentNodeId()===e&&this.panelManager.hide()),s}updateNode(e,s){return this.nodeManager.updateNode(e,s)}addEdge(e){if(!ee(e))return!1;const s=this.edgeManager.addEdge(e);return s&&(this.graphEngine.setEdges(this.edgeManager.getAllEdges()),this.graphEngine.restart(),this.forceGraph2D&&this.forceGraph2D.addEdge(e),this.options.onEdgeAdd&&this.options.onEdgeAdd(e),this.emit("edgeAdd",e)),s}removeEdge(e,s){const t=this.edgeManager.removeEdge(e,s);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}async expandNode(e,s=1,t){const i=t??this.options.onExpand;if(!i)return console.warn("[ForceGraph3D] No expand callback provided"),!1;try{const o=await i(e,s);if(o.nodes&&Array.isArray(o.nodes))for(const a of o.nodes)this.addNode(a);if(o.edges&&Array.isArray(o.edges))for(const a of o.edges)this.addEdge(a);return this.panelManager.hide(),this.emit("expand",e,o),!0}catch(o){return console.error("[ForceGraph3D] Error expanding node:",o),!1}}getNode(e){return this.nodeManager.getNode(e)}getNeighbors(e){return this.edgeManager.getNeighborIds(e).map(t=>this.nodeManager.getNode(t)).filter(t=>t!==void 0)}getNodeCount(){return this.nodeManager.getNodeCount()}getEdgeCount(){return this.edgeManager.getEdgeCount()}setExpandCallback(e){this.options.onExpand=e}focusOnNode(e,s=30){if(this.viewMode==="2d"&&this.forceGraph2D){this.forceGraph2D.focusOnNode(e);return}const t=this.nodeManager.getNode(e);if(!t){console.warn(`[ForceGraph3D] Node "${e}" not found`);return}const i=t.position,o=this.sceneManager.camera,a=this.sceneManager.controls,r=o.position.clone().sub(a.target).normalize(),c={x:i.x+r.x*s,y:i.y+r.y*s,z:i.z+r.z*s},d={x:o.position.x,y:o.position.y,z:o.position.z},p={x:a.target.x,y:a.target.y,z:a.target.z},b=800,y=performance.now(),f=()=>{const x=performance.now()-y,v=Math.min(x/b,1),w=1-Math.pow(1-v,3);o.position.x=d.x+(c.x-d.x)*w,o.position.y=d.y+(c.y-d.y)*w,o.position.z=d.z+(c.z-d.z)*w,a.target.x=p.x+(i.x-p.x)*w,a.target.y=p.y+(i.y-p.y)*w,a.target.z=p.z+(i.z-p.z)*w,a.update(),v<1&&requestAnimationFrame(f)};f()}focusOnEdge(e,s,t=1.5){const i=this.nodeManager.getNode(e),o=this.nodeManager.getNode(s);if(!i||!o){console.warn(`[ForceGraph3D] Could not find nodes for edge "${e}" -> "${s}"`);return}const a=this.sceneManager.camera,r=this.sceneManager.controls,c={x:(i.position.x+o.position.x)/2,y:(i.position.y+o.position.y)/2,z:(i.position.z+o.position.z)/2},d=o.position.x-i.position.x,p=o.position.y-i.position.y,b=o.position.z-i.position.z,y=Math.sqrt(d*d+p*p+b*b),f=Math.max(y*t,40),x=a.position.clone().sub(r.target).normalize(),v={x:c.x+x.x*f,y:c.y+x.y*f,z:c.z+x.z*f},w={x:a.position.x,y:a.position.y,z:a.position.z},z={x:r.target.x,y:r.target.y,z:r.target.z},F=800,O=performance.now(),Y=()=>{const T=performance.now()-O,j=Math.min(T/F,1),E=1-Math.pow(1-j,3);a.position.x=w.x+(v.x-w.x)*E,a.position.y=w.y+(v.y-w.y)*E,a.position.z=w.z+(v.z-w.z)*E,r.target.x=z.x+(c.x-z.x)*E,r.target.y=z.y+(c.y-z.y)*E,r.target.z=z.z+(c.z-z.z)*E,r.update(),j<1&&requestAnimationFrame(Y)};Y()}showNodePanel(e){const s=this.nodeManager.getNode(e);if(!s){console.warn(`[ForceGraph3D] Node "${e}" not found`);return}const t=this.getNeighbors(e);this.panelManager.show(s,t)}searchNodes(e){if(!e||e.trim()==="")return[];const s=e.toLowerCase().trim(),t=this.nodeManager.getAllNodes(),i=[];return t.forEach(o=>{var d,p,b;const a=(d=o.label)==null?void 0:d.toLowerCase().includes(s),r=(p=o.id)==null?void 0:p.toLowerCase().includes(s),c=(b=o.type)==null?void 0:b.toLowerCase().includes(s);(a||r||c)&&i.push(o)}),i}searchEdges(e){var o;if(!e||e.trim()==="")return[];const s=e.toLowerCase().trim(),t=this.edgeManager.getAllEdges(),i=[];for(const a of t)if((o=a.relationship)==null?void 0:o.toLowerCase().includes(s)){const c=this.nodeManager.getNode(a.source),d=this.nodeManager.getNode(a.target);c&&d&&i.push({edge:a,sourceNode:c,targetNode:d})}return i}getAllNodes(){const e=this.nodeManager.getAllNodes();return Array.from(e.values())}getAllEdges(){return this.edgeManager.getAllEdges()}isInitialized(){return this.initialized}getViewMode(){return this.viewMode}switchView(e){this.viewMode!==e&&(this.viewMode=e,this.panelManager.hide(),this.edgePanelManager.hide(),this.edgeTooltipManager.hide(),e==="2d"?(this.sceneManager.renderer.domElement.style.display="none",this.rendererManager.stop(),this.forceGraph2D?(this.forceGraph2D.show(),this.forceGraph2D.syncFrom3D(this.nodeManager.getAllNodes())):(this.forceGraph2D=new st(this.container,{backgroundColor:"#0a0a0a",nodeRadius:24,onNodeClick:s=>{this.onNodeClick(s)},onNodeHover:s=>{this.options.onNodeHover&&this.options.onNodeHover(s)},onEdgeHover:(s,t)=>{if(s&&t){const i=this.nodeManager.getNode(s.source),o=this.nodeManager.getNode(s.target);i&&o&&this.edgeTooltipManager.show(s,i,o,t.clientX,t.clientY)}else this.edgeTooltipManager.hide()},onEdgeClick:s=>{const t=this.nodeManager.getNode(s.source),i=this.nodeManager.getNode(s.target);t&&i&&this.edgePanelManager.show(s,t,i)}}),this.graphData&&(this.forceGraph2D.setData(this.graphData),this.forceGraph2D.syncFrom3D(this.nodeManager.getAllNodes())))):(this.forceGraph2D&&this.forceGraph2D.hide(),this.sceneManager.renderer.domElement.style.display="block",this.rendererManager.start()),this.emit("viewChange",e))}on(e,s){this.eventCallbacks.has(e)||this.eventCallbacks.set(e,[]),this.eventCallbacks.get(e).push(s)}emit(e,...s){const t=this.eventCallbacks.get(e);t&&t.forEach(i=>i(...s))}setPhysicsParams(e){this.graphEngine.setPhysicsParams(e),this.graphEngine.restart(),this.forceGraph2D&&this.forceGraph2D.setPhysicsParams(e)}createDevControls(){this.devControls=document.createElement("div"),this.devControls.className="force-graph-dev-controls",this.devControls.innerHTML=`
535
+ </svg>`}updateButtonStates(){if(!this.toggleContainer)return;this.toggleContainer.querySelectorAll(".f3d-view-btn").forEach(s=>{s.dataset.mode===this.currentMode?s.classList.add("active"):s.classList.remove("active")})}setMode(e){this.currentMode!==e&&(this.currentMode=e,this.updateButtonStates())}getMode(){return this.currentMode}dispose(){this.toggleContainer&&this.toggleContainer.parentNode&&this.toggleContainer.parentNode.removeChild(this.toggleContainer)}}const st={backgroundColor:"#0a0a0a",gridColor:"rgba(255, 255, 255, 0.03)",nodeRadius:24,edgeColor:"rgba(255, 255, 255, 0.15)",edgeOpacity:.4,repulsionStrength:5e3,attractionStrength:.001,damping:.85};class it{constructor(e,s={}){l(this,"container");l(this,"canvas");l(this,"ctx");l(this,"options");l(this,"nodes",new Map);l(this,"edges",[]);l(this,"nodeIdToIndex",new Map);l(this,"transform",{x:0,y:0,scale:1});l(this,"isDragging",!1);l(this,"isPanning",!1);l(this,"draggedNode",null);l(this,"hoveredNode",null);l(this,"hoveredEdge",null);l(this,"lastMousePos",{x:0,y:0});l(this,"dragStartPos",{x:0,y:0});l(this,"selectedNode",null);l(this,"animationId",null);l(this,"isSimulating",!0);l(this,"resizeHandler");this.container=e,this.options={...st,...s},this.canvas=document.createElement("canvas"),this.canvas.style.position="absolute",this.canvas.style.top="0",this.canvas.style.left="0",this.canvas.style.width="100%",this.canvas.style.height="100%",this.canvas.style.cursor="grab",e.appendChild(this.canvas);const t=this.canvas.getContext("2d");if(!t)throw new Error("Failed to get 2D context");this.ctx=t,this.resizeHandler=this.handleResize.bind(this),window.addEventListener("resize",this.resizeHandler),this.handleResize(),this.transform.x=this.canvas.width/2,this.transform.y=this.canvas.height/2,this.setupInteractions(),this.startAnimation()}handleResize(){const e=this.container.getBoundingClientRect(),s=window.devicePixelRatio||1;this.canvas.width=e.width*s,this.canvas.height=e.height*s,this.ctx.scale(s,s)}setupInteractions(){this.canvas.addEventListener("wheel",e=>{e.preventDefault();const s=this.canvas.getBoundingClientRect(),t=e.clientX-s.left,i=e.clientY-s.top,o=e.deltaY>0?.9:1.1,a=Math.max(.1,Math.min(5,this.transform.scale*o)),r=a/this.transform.scale;this.transform.x=t-(t-this.transform.x)*r,this.transform.y=i-(i-this.transform.y)*r,this.transform.scale=a}),this.canvas.addEventListener("mousedown",e=>{const s=this.canvas.getBoundingClientRect(),t=e.clientX-s.left,i=e.clientY-s.top,o=this.screenToWorld(t,i),a=this.findNodeAt(o.x,o.y);this.dragStartPos={x:e.clientX,y:e.clientY},a?(this.isDragging=!0,this.draggedNode=a,this.canvas.style.cursor="grabbing",this.isSimulating=!0):(this.isPanning=!0,this.canvas.style.cursor="grabbing"),this.lastMousePos={x:e.clientX,y:e.clientY}}),this.canvas.addEventListener("mousemove",e=>{const s=this.canvas.getBoundingClientRect(),t=e.clientX-s.left,i=e.clientY-s.top,o=this.screenToWorld(t,i);if(this.isDragging&&this.draggedNode)this.draggedNode.x=o.x,this.draggedNode.y=o.y,this.draggedNode.vx=0,this.draggedNode.vy=0;else if(this.isPanning){const a=e.clientX-this.lastMousePos.x,r=e.clientY-this.lastMousePos.y;this.transform.x+=a,this.transform.y+=r,this.lastMousePos={x:e.clientX,y:e.clientY}}else{const a=this.findNodeAt(o.x,o.y);if(a!==this.hoveredNode&&(this.hoveredNode=a,a?(this.hoveredEdge&&(this.hoveredEdge=null,this.options.onEdgeHover&&this.options.onEdgeHover(null)),this.canvas.style.cursor="pointer",this.options.onNodeHover&&this.options.onNodeHover(a.data)):this.options.onNodeHover&&this.options.onNodeHover(null)),!a){const r=this.findEdgeAt(o.x,o.y);r!==this.hoveredEdge&&(this.hoveredEdge=r,this.canvas.style.cursor=r?"pointer":"grab",this.options.onEdgeHover&&this.options.onEdgeHover(r?r.data:null,e))}}}),this.canvas.addEventListener("mouseup",e=>{const s=Math.abs(e.clientX-this.dragStartPos.x),t=Math.abs(e.clientY-this.dragStartPos.y),i=s<5&&t<5;if(this.isDragging&&this.draggedNode)i&&this.options.onNodeClick&&(this.selectedNode=this.draggedNode,this.options.onNodeClick(this.draggedNode.data));else if(i){const o=this.canvas.getBoundingClientRect(),a=this.screenToWorld(e.clientX-o.left,e.clientY-o.top),r=this.findEdgeAt(a.x,a.y);r&&this.options.onEdgeClick&&this.options.onEdgeClick(r.data)}this.isDragging=!1,this.isPanning=!1,this.draggedNode=null,this.canvas.style.cursor=this.hoveredNode?"pointer":"grab"}),this.canvas.addEventListener("mouseleave",()=>{this.isDragging=!1,this.isPanning=!1,this.draggedNode=null,this.hoveredNode=null,this.canvas.style.cursor="grab"})}screenToWorld(e,s){return{x:(e-this.transform.x)/this.transform.scale,y:(s-this.transform.y)/this.transform.scale}}findNodeAt(e,s){for(const t of this.nodes.values()){const i=t.x-e,o=t.y-s;if(Math.sqrt(i*i+o*o)<t.radius)return t}return null}findEdgeAt(e,s){for(const i of this.edges){const o=this.nodes.get(i.source),a=this.nodes.get(i.target);if(!o||!a)continue;const r=a.x-o.x,c=a.y-o.y,h=r*r+c*c;if(h===0)continue;const p=Math.max(0,Math.min(1,((e-o.x)*r+(s-o.y)*c)/h)),b=o.x+p*r,x=o.y+p*c,f=e-b,m=s-x;if(Math.sqrt(f*f+m*m)<12)return i}return null}startAnimation(){const e=()=>{this.isSimulating&&this.simulate(),this.render(),this.animationId=requestAnimationFrame(e)};e()}simulate(){const e=Array.from(this.nodes.values()),s=e.length;if(s===0)return;const t=60,i=5;let o=0;for(let r=0;r<s;r++)for(let c=r+1;c<s;c++){const h=e[r],p=e[c];let b=p.x-h.x,x=p.y-h.y,f=Math.sqrt(b*b+x*x);if(f<t*3){f<1&&(f=1);const m=this.options.repulsionStrength/(f*f),v=b/f*m,w=x/f*m;h.vx-=v,h.vy-=w,p.vx+=v,p.vy+=w}}const a=80;for(const r of this.edges){const c=this.nodes.get(r.source),h=this.nodes.get(r.target);if(!c||!h)continue;let p=h.x-c.x,b=h.y-c.y,x=Math.sqrt(p*p+b*b);x<1&&(x=1);const m=(x-a)*this.options.attractionStrength,v=p/x*m,w=b/x*m;c.vx+=v,c.vy+=w,h.vx-=v,h.vy-=w}for(const r of e){if(this.draggedNode===r)continue;r.vx*=this.options.damping,r.vy*=this.options.damping;const c=Math.sqrt(r.vx*r.vx+r.vy*r.vy);c>i&&(r.vx=r.vx/c*i,r.vy=r.vy/c*i),r.x+=r.vx,r.y+=r.vy,o+=r.vx*r.vx+r.vy*r.vy}o<.01&&!this.draggedNode&&(this.isSimulating=!1)}render(){const e=this.ctx,s=this.canvas.width/(window.devicePixelRatio||1),t=this.canvas.height/(window.devicePixelRatio||1);e.fillStyle=this.options.backgroundColor,e.fillRect(0,0,s,t),this.renderGrid(s,t),e.save(),e.translate(this.transform.x,this.transform.y),e.scale(this.transform.scale,this.transform.scale),this.renderEdges(),this.renderNodes(),e.restore()}renderGrid(e,s){const t=this.ctx,i=40*this.transform.scale,o=1.5,a=this.transform.x%i,r=this.transform.y%i;t.fillStyle=this.options.gridColor;for(let c=a;c<e;c+=i)for(let h=r;h<s;h+=i)t.beginPath(),t.arc(c,h,o,0,Math.PI*2),t.fill()}renderEdges(){const e=this.ctx;for(const s of this.edges){const t=this.nodes.get(s.source),i=this.nodes.get(s.target);if(!t||!i)continue;const o=s===this.hoveredEdge,a=e.createLinearGradient(t.x,t.y,i.x,i.y);o?(a.addColorStop(0,"rgba(255, 153, 102, 0.8)"),a.addColorStop(.5,"rgba(255, 255, 255, 0.5)"),a.addColorStop(1,"rgba(102, 153, 255, 0.8)"),e.lineWidth=3):(a.addColorStop(0,"rgba(255, 153, 102, 0.3)"),a.addColorStop(.5,"rgba(255, 255, 255, 0.15)"),a.addColorStop(1,"rgba(102, 153, 255, 0.3)"),e.lineWidth=1.5),e.beginPath(),e.moveTo(t.x,t.y),e.lineTo(i.x,i.y),e.strokeStyle=a,e.stroke()}}renderNodes(){const e=this.ctx;for(const s of this.nodes.values()){const t=s===this.hoveredNode,i=s===this.selectedNode,o=this.hoveredEdge&&(s.data.id===this.hoveredEdge.source||s.data.id===this.hoveredEdge.target),a=s.radius*(t?1.1:1);if(t||i||o){const m=e.createRadialGradient(s.x,s.y,a*.5,s.x,s.y,a*2),v=t||i?.4:.25;m.addColorStop(0,`rgba(255, 153, 102, ${v})`),m.addColorStop(1,"rgba(255, 153, 102, 0)"),e.fillStyle=m,e.beginPath(),e.arc(s.x,s.y,a*2,0,Math.PI*2),e.fill()}const r=e.createRadialGradient(s.x-a*.3,s.y-a*.3,0,s.x,s.y,a),c=s.color>>16&255,h=s.color>>8&255,p=s.color&255;r.addColorStop(0,`rgba(${Math.min(255,c+60)}, ${Math.min(255,h+60)}, ${Math.min(255,p+60)}, 0.95)`),r.addColorStop(.7,`rgba(${c}, ${h}, ${p}, 0.9)`),r.addColorStop(1,`rgba(${Math.max(0,c-40)}, ${Math.max(0,h-40)}, ${Math.max(0,p-40)}, 0.85)`),e.beginPath(),e.arc(s.x,s.y,a,0,Math.PI*2),e.fillStyle=r,e.fill(),e.strokeStyle="rgba(255, 255, 255, 0.2)",e.lineWidth=1,e.stroke(),e.beginPath(),e.arc(s.x-a*.25,s.y-a*.25,a*.3,0,Math.PI*2),e.fillStyle="rgba(255, 255, 255, 0.15)",e.fill(),e.fillStyle="white",e.font="600 11px Inter, -apple-system, BlinkMacSystemFont, sans-serif",e.textAlign="center",e.textBaseline="middle";const b=a*1.6;let x=s.label,f=e.measureText(x).width;if(f>b){for(;f>b&&x.length>3;)x=x.slice(0,-1),f=e.measureText(x+"...").width;x+="..."}e.shadowColor="rgba(0, 0, 0, 0.5)",e.shadowBlur=3,e.fillText(x,s.x,s.y),e.shadowBlur=0}}setData(e){this.nodes.clear(),this.edges=[],this.nodeIdToIndex.clear(),e.nodes.forEach((s,t)=>{const i=s.position||{x:(Math.random()-.5)*300,y:(Math.random()-.5)*300},o={id:s.id,label:s.label,x:i.x,y:i.y,vx:0,vy:0,color:s.color||16750950,radius:this.options.nodeRadius,data:s};this.nodes.set(s.id,o),this.nodeIdToIndex.set(s.id,t)}),this.edges=e.edges.map(s=>({source:s.source,target:s.target,relationship:s.relationship,data:s}))}addNode(e){const s=e.position||{x:(Math.random()-.5)*300,y:(Math.random()-.5)*300},t={id:e.id,label:e.label,x:s.x,y:s.y,vx:0,vy:0,color:e.color||16750950,radius:this.options.nodeRadius,data:e};this.nodes.set(e.id,t)}addEdge(e){this.edges.push({source:e.source,target:e.target,relationship:e.relationship,data:e})}removeNode(e){this.nodes.delete(e),this.edges=this.edges.filter(s=>s.source!==e&&s.target!==e)}getNode(e){return this.nodes.get(e)}getAllNodes(){return Array.from(this.nodes.values()).map(e=>e.data)}getNodeCount(){return this.nodes.size}getEdgeCount(){return this.edges.length}focusOnNode(e){const s=this.nodes.get(e);if(!s)return;const t=this.canvas.width/2/(window.devicePixelRatio||1)-s.x*this.transform.scale,i=this.canvas.height/2/(window.devicePixelRatio||1)-s.y*this.transform.scale,o=this.transform.x,a=this.transform.y,r=500,c=performance.now(),h=()=>{const p=performance.now()-c,b=Math.min(p/r,1),x=1-Math.pow(1-b,3);this.transform.x=o+(t-o)*x,this.transform.y=a+(i-a)*x,b<1?requestAnimationFrame(h):this.selectedNode=s};h()}syncFrom3D(e){e.forEach((s,t)=>{const i=this.nodes.get(t);i&&(i.x=s.position.x*3,i.y=s.position.y*3,i.vx=0,i.vy=0)}),this.isSimulating=!1}getPositions(){const e=new Map;return this.nodes.forEach((s,t)=>{e.set(t,{x:s.x,y:s.y})}),e}show(){this.canvas.style.display="block"}hide(){this.canvas.style.display="none"}setPhysicsParams(e){e.repulsionStrength!==void 0&&(this.options.repulsionStrength=e.repulsionStrength),e.attractionStrength!==void 0&&(this.options.attractionStrength=e.attractionStrength),e.damping!==void 0&&(this.options.damping=e.damping),this.isSimulating=!0}dispose(){this.animationId&&cancelAnimationFrame(this.animationId),window.removeEventListener("resize",this.resizeHandler),this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas)}}class ot{constructor(e,s={}){l(this,"options");l(this,"container");l(this,"sceneManager");l(this,"nodeManager");l(this,"edgeManager");l(this,"graphEngine");l(this,"rendererManager");l(this,"materialFactory");l(this,"nodeFactory");l(this,"edgeFactory");l(this,"lodManager");l(this,"frustumCuller");l(this,"raycasterManager");l(this,"panelManager");l(this,"edgePanelManager");l(this,"edgeTooltipManager");l(this,"searchManager",null);l(this,"viewToggleManager",null);l(this,"forceGraph2D",null);l(this,"eventCallbacks",new Map);l(this,"initialized",!1);l(this,"devControls",null);l(this,"viewMode","3d");l(this,"graphData",null);this.options={...k,...s},this.container=Ae(e),this.materialFactory=new Ue,this.nodeFactory=new Ke(this.materialFactory,this.options.nodeRadius??k.nodeRadius,this.options.lodSegments??k.lodSegments,this.options.defaultNodeColor??k.defaultNodeColor),this.edgeFactory=new _e(this.materialFactory,this.options.edgeColor??k.edgeColor,this.options.edgeOpacity??k.edgeOpacity),this.sceneManager=new $e(this.container,this.options),this.lodManager=new Xe(this.sceneManager.camera,this.options.lodDistances??k.lodDistances,this.options.enableLOD??k.enableLOD),this.frustumCuller=new qe(this.sceneManager.camera,this.options.enableEdgeCulling??k.enableEdgeCulling),this.nodeManager=new q(this.sceneManager,this.nodeFactory),this.edgeManager=new Ye(this.sceneManager,this.nodeManager,this.edgeFactory),this.graphEngine=new fe(this.nodeManager.getAllNodes(),this.edgeManager.getAllEdges(),{repulsionStrength:this.options.repulsionStrength,attractionStrength:this.options.attractionStrength,damping:this.options.damping,useBarnesHut:this.options.useBarnesHut,barnesHutTheta:this.options.barnesHutTheta}),this.rendererManager=new Ve(this.sceneManager,()=>this.onSimulate(),()=>this.onRender(),this.options.targetFPS??k.targetFPS),this.raycasterManager=new We(this.sceneManager,this.container),this.panelManager=new Ze(this.container),this.edgePanelManager=new Qe(this.container),this.edgeTooltipManager=new Je,this.edgePanelManager.setNodeClickCallback(t=>{this.edgePanelManager.hide(),this.focusOnNode(t),setTimeout(()=>{this.showNodePanel(t)},400)}),this.options.showSearch!==!1&&(this.searchManager=new et(this.container,{placeholder:this.options.searchPlaceholder,onSearch:t=>({nodeResults:this.searchNodes(t),edgeResults:this.searchEdges(t)}),onResultClick:t=>{this.focusOnNode(t),setTimeout(()=>{this.showNodePanel(t)},400)}})),this.options.showViewToggle!==!1&&(this.viewMode=this.options.initialViewMode||"3d",this.viewToggleManager=new tt(this.container,{initialMode:this.viewMode,onViewChange:t=>{this.switchView(t)}})),this.setupCallbacks(),this.rendererManager.start(),this.initialized=!0,this.emit("ready")}setupCallbacks(){this.raycasterManager.setClickCallback(e=>{this.onNodeClick(e)}),this.options.onNodeHover&&this.raycasterManager.setHoverCallback(this.options.onNodeHover),this.panelManager.setExpandCallback((e,s)=>{this.expandNode(e,s)}),this.options.panelTemplate&&this.panelManager.setPanelTemplate(this.options.panelTemplate),this.options.panelStyles&&this.panelManager.setPanelStyles(this.options.panelStyles),this.raycasterManager.setEdgeHoverCallback(e=>{this.onEdgeHover(e)}),this.raycasterManager.setEdgeClickCallback(e=>{this.onEdgeClick(e)})}onEdgeHover(e){if(e){this.edgeManager.highlightEdge(e.edge.source,e.edge.target);const s=this.container.getBoundingClientRect(),t=s.left+s.width/2,i=s.top+s.height/2;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)}else this.edgeManager.unhighlightCurrentEdge(),this.edgeTooltipManager.hide(),this.options.onEdgeHover&&this.options.onEdgeHover(null,null,null),this.emit("edgeHover",null,null,null)}onNodeClick(e){this.edgePanelManager.hide();const t=this.edgeManager.getNeighborIds(e.id).map(i=>this.nodeManager.getNode(i)).filter(i=>i!==void 0);this.options.showPanel!==!1&&this.panelManager.show(e,t),this.options.onNodeClick&&this.options.onNodeClick(e),this.emit("nodeClick",e)}onEdgeClick(e){this.panelManager.hide(),this.edgeTooltipManager.hide(),this.edgeManager.highlightEdge(e.edge.source,e.edge.target),this.edgePanelManager.show(e.edge,e.sourceNode,e.targetNode),this.focusOnEdge(e.edge.source,e.edge.target),this.emit("edgeClick",e.edge,e.sourceNode,e.targetNode)}onSimulate(){this.graphEngine.simulate();for(const[e,s]of this.nodeManager.getAllNodes())if(this.nodeManager.updateNodePosition(e,s.position),this.options.enableLOD){const t=this.lodManager.getLODLevel(s.position);this.nodeManager.updateNodeLOD(e,t)}this.edgeManager.updateEdgePositions()}onRender(){this.frustumCuller.update(),this.raycasterManager.setNodeObjects(this.nodeManager.getAllNodeObjects()),this.raycasterManager.setEdgeObjects(this.edgeManager.getAllEdgeLines())}setData(e){var a;const s=(a=e.data)!=null&&a.nodes?e.data:e,i=(s.edges||s.links||[]).map(r=>({...r,relationship:r.relationship||r.label||"related_to"})),o={nodes:s.nodes||[],edges:i};if(this.graphData=o,this.edgeManager.clear(),this.nodeManager.clear(),o.nodes&&Array.isArray(o.nodes)){q.setExpectedNodeCount(o.nodes.length);for(const r of o.nodes)this.addNode(r)}if(o.edges&&Array.isArray(o.edges))for(const r of o.edges)this.addEdge(r);this.graphEngine=new fe(this.nodeManager.getAllNodes(),this.edgeManager.getAllEdges(),{repulsionStrength:this.options.repulsionStrength,attractionStrength:this.options.attractionStrength,damping:this.options.damping,useBarnesHut:this.options.useBarnesHut,barnesHutTheta:this.options.barnesHutTheta}),this.graphEngine.restart(),this.forceGraph2D&&this.forceGraph2D.setData(o)}addNode(e){if(!te(e))return!1;const s=this.nodeManager.addNode(e);return s&&(this.graphEngine.restart(),this.forceGraph2D&&this.forceGraph2D.addNode(e),this.options.onNodeAdd&&this.options.onNodeAdd(e),this.emit("nodeAdd",e)),s}removeNode(e){if(!Re(e))return!1;this.edgeManager.removeEdgesForNode(e);const s=this.nodeManager.removeNode(e);return s&&(this.graphEngine.restart(),this.options.onNodeRemove&&this.options.onNodeRemove(e),this.emit("nodeRemove",e),this.panelManager.getCurrentNodeId()===e&&this.panelManager.hide()),s}updateNode(e,s){return this.nodeManager.updateNode(e,s)}addEdge(e){if(!se(e))return!1;const s=this.edgeManager.addEdge(e);return s&&(this.graphEngine.setEdges(this.edgeManager.getAllEdges()),this.graphEngine.restart(),this.forceGraph2D&&this.forceGraph2D.addEdge(e),this.options.onEdgeAdd&&this.options.onEdgeAdd(e),this.emit("edgeAdd",e)),s}removeEdge(e,s){const t=this.edgeManager.removeEdge(e,s);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}async expandNode(e,s=1,t){const i=t??this.options.onExpand;if(!i)return console.warn("[ForceGraph3D] No expand callback provided"),!1;try{const o=await i(e,s);if(o.nodes&&Array.isArray(o.nodes))for(const a of o.nodes)this.addNode(a);if(o.edges&&Array.isArray(o.edges))for(const a of o.edges)this.addEdge(a);return this.panelManager.hide(),this.emit("expand",e,o),!0}catch(o){return console.error("[ForceGraph3D] Error expanding node:",o),!1}}getNode(e){return this.nodeManager.getNode(e)}getNeighbors(e){return this.edgeManager.getNeighborIds(e).map(t=>this.nodeManager.getNode(t)).filter(t=>t!==void 0)}getNodeCount(){return this.nodeManager.getNodeCount()}getEdgeCount(){return this.edgeManager.getEdgeCount()}setExpandCallback(e){this.options.onExpand=e}focusOnNode(e,s=30){if(this.viewMode==="2d"&&this.forceGraph2D){this.forceGraph2D.focusOnNode(e);return}const t=this.nodeManager.getNode(e);if(!t){console.warn(`[ForceGraph3D] Node "${e}" not found`);return}const i=t.position,o=this.sceneManager.camera,a=this.sceneManager.controls,r=o.position.clone().sub(a.target).normalize(),c={x:i.x+r.x*s,y:i.y+r.y*s,z:i.z+r.z*s},h={x:o.position.x,y:o.position.y,z:o.position.z},p={x:a.target.x,y:a.target.y,z:a.target.z},b=800,x=performance.now(),f=()=>{const m=performance.now()-x,v=Math.min(m/b,1),w=1-Math.pow(1-v,3);o.position.x=h.x+(c.x-h.x)*w,o.position.y=h.y+(c.y-h.y)*w,o.position.z=h.z+(c.z-h.z)*w,a.target.x=p.x+(i.x-p.x)*w,a.target.y=p.y+(i.y-p.y)*w,a.target.z=p.z+(i.z-p.z)*w,a.update(),v<1&&requestAnimationFrame(f)};f()}focusOnEdge(e,s,t=1.5){const i=this.nodeManager.getNode(e),o=this.nodeManager.getNode(s);if(!i||!o){console.warn(`[ForceGraph3D] Could not find nodes for edge "${e}" -> "${s}"`);return}const a=this.sceneManager.camera,r=this.sceneManager.controls,c={x:(i.position.x+o.position.x)/2,y:(i.position.y+o.position.y)/2,z:(i.position.z+o.position.z)/2},h=o.position.x-i.position.x,p=o.position.y-i.position.y,b=o.position.z-i.position.z,x=Math.sqrt(h*h+p*p+b*b),f=Math.max(x*t,40),m=a.position.clone().sub(r.target).normalize(),v={x:c.x+m.x*f,y:c.y+m.y*f,z:c.z+m.z*f},w={x:a.position.x,y:a.position.y,z:a.position.z},z={x:r.target.x,y:r.target.y,z:r.target.z},D=800,T=performance.now(),B=()=>{const O=performance.now()-T,R=Math.min(O/D,1),E=1-Math.pow(1-R,3);a.position.x=w.x+(v.x-w.x)*E,a.position.y=w.y+(v.y-w.y)*E,a.position.z=w.z+(v.z-w.z)*E,r.target.x=z.x+(c.x-z.x)*E,r.target.y=z.y+(c.y-z.y)*E,r.target.z=z.z+(c.z-z.z)*E,r.update(),R<1&&requestAnimationFrame(B)};B()}showNodePanel(e){const s=this.nodeManager.getNode(e);if(!s){console.warn(`[ForceGraph3D] Node "${e}" not found`);return}const t=this.getNeighbors(e);this.panelManager.show(s,t)}searchNodes(e){if(!e||e.trim()==="")return[];const s=e.toLowerCase().trim(),t=this.nodeManager.getAllNodes(),i=[];return t.forEach(o=>{var h,p,b;const a=(h=o.label)==null?void 0:h.toLowerCase().includes(s),r=(p=o.id)==null?void 0:p.toLowerCase().includes(s),c=(b=o.type)==null?void 0:b.toLowerCase().includes(s);(a||r||c)&&i.push(o)}),i}searchEdges(e){var o;if(!e||e.trim()==="")return[];const s=e.toLowerCase().trim(),t=this.edgeManager.getAllEdges(),i=[];for(const a of t)if((o=a.relationship)==null?void 0:o.toLowerCase().includes(s)){const c=this.nodeManager.getNode(a.source),h=this.nodeManager.getNode(a.target);c&&h&&i.push({edge:a,sourceNode:c,targetNode:h})}return i}getAllNodes(){const e=this.nodeManager.getAllNodes();return Array.from(e.values())}getAllEdges(){return this.edgeManager.getAllEdges()}isInitialized(){return this.initialized}getViewMode(){return this.viewMode}switchView(e){this.viewMode!==e&&(this.viewMode=e,this.panelManager.hide(),this.edgePanelManager.hide(),this.edgeTooltipManager.hide(),e==="2d"?(this.sceneManager.renderer.domElement.style.display="none",this.rendererManager.stop(),this.forceGraph2D?(this.forceGraph2D.show(),this.forceGraph2D.syncFrom3D(this.nodeManager.getAllNodes())):(this.forceGraph2D=new it(this.container,{backgroundColor:"#0a0a0a",nodeRadius:24,onNodeClick:s=>{this.onNodeClick(s)},onNodeHover:s=>{this.options.onNodeHover&&this.options.onNodeHover(s)},onEdgeHover:(s,t)=>{if(s&&t){const i=this.nodeManager.getNode(s.source),o=this.nodeManager.getNode(s.target);i&&o&&this.edgeTooltipManager.show(s,i,o,t.clientX,t.clientY)}else this.edgeTooltipManager.hide()},onEdgeClick:s=>{const t=this.nodeManager.getNode(s.source),i=this.nodeManager.getNode(s.target);t&&i&&this.edgePanelManager.show(s,t,i)}}),this.graphData&&(this.forceGraph2D.setData(this.graphData),this.forceGraph2D.syncFrom3D(this.nodeManager.getAllNodes())))):(this.forceGraph2D&&this.forceGraph2D.hide(),this.sceneManager.renderer.domElement.style.display="block",this.rendererManager.start()),this.emit("viewChange",e))}on(e,s){this.eventCallbacks.has(e)||this.eventCallbacks.set(e,[]),this.eventCallbacks.get(e).push(s)}emit(e,...s){const t=this.eventCallbacks.get(e);t&&t.forEach(i=>i(...s))}setPhysicsParams(e){this.graphEngine.setPhysicsParams(e),this.graphEngine.restart(),this.forceGraph2D&&this.forceGraph2D.setPhysicsParams(e)}createDevControls(){this.devControls=document.createElement("div"),this.devControls.className="force-graph-dev-controls",this.devControls.innerHTML=`
536
536
  <style>
537
537
  .force-graph-dev-controls {
538
538
  position: absolute;
@@ -594,5 +594,5 @@
594
594
  <div>Edges: <span class="value" id="dev-edge-count">0</span></div>
595
595
  <div>FPS: <span class="value" id="dev-fps">60</span></div>
596
596
  </div>
597
- `,this.container.appendChild(this.devControls);const e=this.devControls.querySelector("#dev-repulsion"),s=this.devControls.querySelector("#dev-attraction"),t=this.devControls.querySelector("#dev-damping");e==null||e.addEventListener("input",()=>{const i=parseFloat(e.value);this.setPhysicsParams({repulsionStrength:i}),this.devControls.querySelector("#dev-repulsion-val").textContent=i.toString()}),s==null||s.addEventListener("input",()=>{const i=parseFloat(s.value)/1e3;this.setPhysicsParams({attractionStrength:i}),this.devControls.querySelector("#dev-attraction-val").textContent=i.toFixed(3)}),t==null||t.addEventListener("input",()=>{const i=parseFloat(t.value)/100;this.setPhysicsParams({damping:i}),this.devControls.querySelector("#dev-damping-val").textContent=i.toFixed(2)}),setInterval(()=>{const i=this.devControls.querySelector("#dev-node-count"),o=this.devControls.querySelector("#dev-edge-count"),a=this.devControls.querySelector("#dev-fps");i&&(i.textContent=this.getNodeCount().toString()),o&&(o.textContent=this.getEdgeCount().toString()),a&&(a.textContent=this.rendererManager.getFPS().toString())},500)}destroy(){this.rendererManager.dispose(),this.panelManager.dispose(),this.raycasterManager.dispose(),this.edgeTooltipManager.dispose(),this.searchManager&&this.searchManager.dispose(),this.viewToggleManager&&this.viewToggleManager.dispose(),this.forceGraph2D&&this.forceGraph2D.dispose(),this.edgeManager.dispose(),this.nodeManager.dispose(),this.nodeFactory.dispose(),this.materialFactory.dispose(),this.sceneManager.dispose(),this.devControls&&this.devControls.parentNode&&this.devControls.parentNode.removeChild(this.devControls),this.eventCallbacks.clear(),this.initialized=!1}}const ue=["Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega","Core","Hub","Node","Link","Point","Vertex"],_=["connects to","links with","relates to","depends on","references","extends","includes","partners with","collaborates with","supports"],fe=[16777215,16750950,16764057,16772829,16746564];function ot(h=30){const e=[],s=[];for(let i=0;i<h;i++){const o=i<ue.length?ue[i]:`Node ${i+1}`;e.push({id:`node-${i}`,label:o,color:fe[i%fe.length],position:{x:(Math.random()-.5)*60,y:(Math.random()-.5)*60,z:(Math.random()-.5)*60}})}for(let i=1;i<h;i++){const o=Math.floor(Math.random()*i);s.push({source:`node-${i}`,target:`node-${o}`,relationship:_[Math.floor(Math.random()*_.length)]})}const t=Math.floor(h*.5);for(let i=0;i<t;i++){const o=Math.floor(Math.random()*h);let a=Math.floor(Math.random()*h);o===a&&(a=(a+1)%h);const r=`node-${o}`,c=`node-${a}`;s.some(p=>p.source===r&&p.target===c||p.source===c&&p.target===r)||s.push({source:r,target:c,relationship:_[Math.floor(Math.random()*_.length)]})}return{nodes:e,edges:s}}function nt(h=1e3){const e=[],s=[],t=Math.ceil(h/50),i=[];for(let o=0;o<t;o++)i.push({x:(Math.random()-.5)*200,y:(Math.random()-.5)*200,z:(Math.random()-.5)*200});for(let o=0;o<h;o++){const a=i[o%t];e.push({id:`node-${o}`,label:`N${o}`,position:{x:a.x+(Math.random()-.5)*40,y:a.y+(Math.random()-.5)*40,z:a.z+(Math.random()-.5)*40}})}for(let o=1;o<h;o++){const a=Math.floor(o/50)*50,r=a===0?Math.floor(Math.random()*o):a+Math.floor(Math.random()*Math.min(o-a,50));s.push({source:`node-${o}`,target:`node-${Math.min(r,o-1)}`,relationship:"links to"})}for(let o=1;o<t;o++){const a=o*50,r=(o-1)*50+Math.floor(Math.random()*50);s.push({source:`node-${a}`,target:`node-${r}`,relationship:"bridges to"})}return{nodes:e,edges:s}}N.DEFAULT_OPTIONS=P,N.ForceGraph3D=it,N.LODLevel=H,N.createEdgeKey=D,N.generateLargeSampleData=nt,N.generateSampleData=ot,N.validateEdgeData=ee,N.validateNodeData=J,Object.defineProperty(N,Symbol.toStringTag,{value:"Module"})});
597
+ `,this.container.appendChild(this.devControls);const e=this.devControls.querySelector("#dev-repulsion"),s=this.devControls.querySelector("#dev-attraction"),t=this.devControls.querySelector("#dev-damping");e==null||e.addEventListener("input",()=>{const i=parseFloat(e.value);this.setPhysicsParams({repulsionStrength:i}),this.devControls.querySelector("#dev-repulsion-val").textContent=i.toString()}),s==null||s.addEventListener("input",()=>{const i=parseFloat(s.value)/1e3;this.setPhysicsParams({attractionStrength:i}),this.devControls.querySelector("#dev-attraction-val").textContent=i.toFixed(3)}),t==null||t.addEventListener("input",()=>{const i=parseFloat(t.value)/100;this.setPhysicsParams({damping:i}),this.devControls.querySelector("#dev-damping-val").textContent=i.toFixed(2)}),setInterval(()=>{const i=this.devControls.querySelector("#dev-node-count"),o=this.devControls.querySelector("#dev-edge-count"),a=this.devControls.querySelector("#dev-fps");i&&(i.textContent=this.getNodeCount().toString()),o&&(o.textContent=this.getEdgeCount().toString()),a&&(a.textContent=this.rendererManager.getFPS().toString())},500)}destroy(){this.rendererManager.dispose(),this.panelManager.dispose(),this.raycasterManager.dispose(),this.edgeTooltipManager.dispose(),this.searchManager&&this.searchManager.dispose(),this.viewToggleManager&&this.viewToggleManager.dispose(),this.forceGraph2D&&this.forceGraph2D.dispose(),this.edgeManager.dispose(),this.nodeManager.dispose(),this.nodeFactory.dispose(),this.materialFactory.dispose(),this.sceneManager.dispose(),this.devControls&&this.devControls.parentNode&&this.devControls.parentNode.removeChild(this.devControls),this.eventCallbacks.clear(),this.initialized=!1}}const me=["Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega","Core","Hub","Node","Link","Point","Vertex"],W=["connects to","links with","relates to","depends on","references","extends","includes","partners with","collaborates with","supports"],ye=[16777215,16750950,16764057,16772829,16746564];function nt(d=30){const e=[],s=[];for(let i=0;i<d;i++){const o=i<me.length?me[i]:`Node ${i+1}`;e.push({id:`node-${i}`,label:o,color:ye[i%ye.length],position:{x:(Math.random()-.5)*60,y:(Math.random()-.5)*60,z:(Math.random()-.5)*60}})}for(let i=1;i<d;i++){const o=Math.floor(Math.random()*i);s.push({source:`node-${i}`,target:`node-${o}`,relationship:W[Math.floor(Math.random()*W.length)]})}const t=Math.floor(d*.5);for(let i=0;i<t;i++){const o=Math.floor(Math.random()*d);let a=Math.floor(Math.random()*d);o===a&&(a=(a+1)%d);const r=`node-${o}`,c=`node-${a}`;s.some(p=>p.source===r&&p.target===c||p.source===c&&p.target===r)||s.push({source:r,target:c,relationship:W[Math.floor(Math.random()*W.length)]})}return{nodes:e,edges:s}}function at(d=1e3){const e=[],s=[],t=Math.ceil(d/50),i=[];for(let o=0;o<t;o++)i.push({x:(Math.random()-.5)*200,y:(Math.random()-.5)*200,z:(Math.random()-.5)*200});for(let o=0;o<d;o++){const a=i[o%t];e.push({id:`node-${o}`,label:`N${o}`,position:{x:a.x+(Math.random()-.5)*40,y:a.y+(Math.random()-.5)*40,z:a.z+(Math.random()-.5)*40}})}for(let o=1;o<d;o++){const a=Math.floor(o/50)*50,r=a===0?Math.floor(Math.random()*o):a+Math.floor(Math.random()*Math.min(o-a,50));s.push({source:`node-${o}`,target:`node-${Math.min(r,o-1)}`,relationship:"links to"})}for(let o=1;o<t;o++){const a=o*50,r=(o-1)*50+Math.floor(Math.random()*50);s.push({source:`node-${a}`,target:`node-${r}`,relationship:"bridges to"})}return{nodes:e,edges:s}}N.DEFAULT_OPTIONS=k,N.ForceGraph3D=ot,N.LODLevel=H,N.createEdgeKey=F,N.generateLargeSampleData=at,N.generateSampleData=nt,N.validateEdgeData=se,N.validateNodeData=te,Object.defineProperty(N,Symbol.toStringTag,{value:"Module"})});
598
598
  //# sourceMappingURL=force-3d-graph.umd.cjs.map