vortx-gl 1.0.2 → 1.0.4

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 +1 @@
1
- import{mat3 as e,vec3 as t,vec2 as i}from"gl-matrix";import{defineComponent as a,computed as s,openBlock as n,createElementBlock as o,Fragment as l,renderList as r,withModifiers as c,normalizeStyle as d,createElementVNode as h,renderSlot as u,createBlock as v,createVNode as m,toDisplayString as g,createCommentVNode as p,ref as f,normalizeClass as M,onMounted as b,onUnmounted as w,withDirectives as y,withKeys as x,vModelText as k,watch as C,unref as E,vShow as I}from"vue";class _{gl;constructor(e){this.gl=e}pickNode(e){const t=this.gl,{mouseX:i,mouseY:a,canvas:s,program:n,pickingFramebuffer:o,vao:l,viewMatrix:r,pointSize:c,nodeCount:d}=e;t.bindFramebuffer(t.FRAMEBUFFER,o),t.viewport(0,0,s.width,s.height),t.clearColor(0,0,0,0),t.clear(t.COLOR_BUFFER_BIT),t.useProgram(n),t.uniformMatrix3fv(t.getUniformLocation(n,"u_matrix"),!1,r),t.uniform1f(t.getUniformLocation(n,"u_pointSize"),c),t.uniform1i(t.getUniformLocation(n,"u_pickingMode"),1),t.bindVertexArray(l),t.drawArrays(t.POINTS,0,d);const h=new Uint8Array(4),u=window.devicePixelRatio;if(t.readPixels(Math.floor(i*u),Math.floor(s.height-a*u),1,1,t.RGBA,t.UNSIGNED_BYTE,h),t.bindFramebuffer(t.FRAMEBUFFER,null),0===h[3])return null;return(h[0]<<16|h[1]<<8|h[2])-1}pickEdge(a){const{mouseX:s,mouseY:n,edgeIndices:o,positions:l,nodeCount:r,viewMatrix:c,canvasW:d,canvasH:h}=a;if(!o||!l)return null;const u=window.devicePixelRatio,v=s*u,m=n*u,g=5*u,p=e.invert(e.create(),c);if(!p)return null;const f=t.fromValues(v/d*2-1,-(m/h*2-1),1);t.transformMat3(f,f,p);const M=f[0],b=f[1],w=2*g/Math.abs(c[0]+c[4]);for(let e=0;e<o.length/2;e++){const t=o[2*e],a=o[2*e+1];if(t>=r||a>=r)continue;const s=l[2*t],n=l[2*t+1],u=l[2*a],p=l[2*a+1];if(M<(s<u?s:u)-w||M>(s>u?s:u)+w||b<(n<p?n:p)-w||b>(n>p?n:p)+w)continue;const f=this.project(s,n,c,d,h),y=this.project(u,p,c,d,h);if(this.distToSegment(i.fromValues(v,m),f,y)<g)return`${t}-${a}`}return null}pickCombo(e){const{mouseX:t,mouseY:i,combos:a,positions:s,nodeCount:n,viewMatrix:o,canvasW:l,canvasH:r}=e;if(!s)return null;const c=window.devicePixelRatio,d=t*c,h=i*c;for(const u of a.values()){let e=1/0,t=1/0,i=-1/0,a=-1/0,v=!1;for(const c of u.nodeIds){if(c>=n)continue;const d=this.project(s[2*c],s[2*c+1],o,l,r);e=Math.min(e,d[0]),t=Math.min(t,d[1]),i=Math.max(i,d[0]),a=Math.max(a,d[1]),v=!0}if(v){const s=30*c;if(d>=e-s&&d<=i+s&&h>=t-s&&h<=a+s)return u.id}}return null}distToSegment(e,t,a){const s=i.dist(t,a)**2;if(0===s)return i.dist(e,t);let n=((e[0]-t[0])*(a[0]-t[0])+(e[1]-t[1])*(a[1]-t[1]))/s;n=Math.max(0,Math.min(1,n));const o=i.fromValues(t[0]+n*(a[0]-t[0]),t[1]+n*(a[1]-t[1]));return i.dist(e,o)}project(e,a,s,n,o){const l=t.fromValues(e,a,1);return t.transformMat3(l,l,s),i.fromValues((.5*l[0]+.5)*n,(.5*-l[1]+.5)*o)}}class A{canvas;ctx;constructor(e,t){this.canvas=e,this.ctx=t}_posScratch=t.create();_spScratch=i.create();_s1Scratch=i.create();_s2Scratch=i.create();project(e,i,a,s){return t.set(this._posScratch,e,i,1),t.transformMat3(this._posScratch,this._posScratch,a),s[0]=(.5*this._posScratch[0]+.5)*this.canvas.width,s[1]=(.5*-this._posScratch[1]+.5)*this.canvas.height,s}render(i){const{ctx:a,canvas:s}=this,{positions:n,nodeCount:o,edgeCount:l,edgeIndices:r,metadata:c,combos:d,theme:h,zoom:u,viewMatrix:v,selectedNodeIds:m,selectedEdgeId:g,selectedComboId:p,hoveredNodeId:f,isBoxSelecting:M,selectionStart:b,selectionEnd:w,isFlowAnimating:y}=i;if(!n)return;const x=e.invert(e.create(),v);if(!x)return;const k=t.fromValues(-1.1,1.1,1),C=t.fromValues(1.1,-1.1,1);t.transformMat3(k,k,x),t.transformMat3(C,C,x);const E=Math.min(k[0],C[0]),I=Math.max(k[0],C[0]),_=Math.min(k[1],C[1]),A=Math.max(k[1],C[1]);a.clearRect(0,0,s.width,s.height);const S=window.devicePixelRatio,R=40*u*S;M&&this.drawMarquee(b,w,S),this.drawCombos(d,n,o,v,p,h,S),this.drawNodeHighlights(m,o,n,v,R,S),this.drawEdgeHighlight(g,r,n,v,S);const F=u<.1;y&&!(u<.3)&&l<5e4&&this.drawFlow(r,l,n,v,h,S,E,I,_,A),null!==f&&r&&this.drawHoverHighlight(f,r,l,n,v,h,S),F||this.drawNodeLabels(o,c,n,v,h,S,R,u,E,I,_,A)}drawMarquee(e,t,i){const a=Math.min(e[0],t[0]),s=Math.min(e[1],t[1]),n=Math.abs(e[0]-t[0]),o=Math.abs(e[1]-t[1]);this.ctx.strokeStyle="rgba(0, 255, 204, 0.8)",this.ctx.fillStyle="rgba(0, 255, 204, 0.1)",this.ctx.lineWidth=1*i,this.ctx.strokeRect(a,s,n,o),this.ctx.fillRect(a,s,n,o)}drawCombos(e,t,i,a,s,n,o){const l=this.ctx,r=this._spScratch;for(const c of e.values()){let e=1/0,d=1/0,h=-1/0,u=-1/0,v=!1;for(const s of c.nodeIds){if(s>=i)continue;const n=this.project(t[2*s],t[2*s+1],a,r);e=Math.min(e,n[0]),d=Math.min(d,n[1]),h=Math.max(h,n[0]),u=Math.max(u,n[1]),v=!0}if(v){const t=30*o,i=e-t,a=d-t,r=h-e+2*t,v=u-d+2*t;if(i+r<0||i>this.canvas.width||a+v<0||a>this.canvas.height)continue;const m=s===c.id;l.save(),l.beginPath();const g=16*o;l.moveTo(i+g,a),l.arcTo(i+r,a,i+r,a+v,g),l.arcTo(i+r,a+v,i,a+v,g),l.arcTo(i,a+v,i,a,g),l.arcTo(i,a,i+r,a,g),l.closePath(),l.fillStyle=m?"rgba(0, 255, 204, 0.15)":"dark"===n?"rgba(0, 255, 204, 0.05)":"rgba(0, 170, 136, 0.05)",l.strokeStyle=m?"rgba(0, 255, 204, 0.8)":"dark"===n?"rgba(0, 255, 204, 0.2)":"rgba(0, 170, 136, 0.2)",l.lineWidth=(m?3:2)*o,l.setLineDash(m?[]:[5*o,5*o]),l.fill(),l.stroke(),l.setLineDash([]),l.fillStyle=m||"dark"===n?"#00ffcc":"#00aa88",l.font=`bold ${14*o}px Inter, sans-serif`,l.fillText(c.label.toUpperCase(),i+10*o,a-10*o),l.restore()}}}drawNodeHighlights(e,t,i,a,s,n){const o=this.ctx,l=this._spScratch;o.strokeStyle="#00ffcc",o.lineWidth=2*n;for(const r of e)r>=t||(this.project(i[2*r],i[2*r+1],a,l),l[0]<-50||l[0]>this.canvas.width+50||l[1]<-50||l[1]>this.canvas.height+50||(o.beginPath(),o.arc(l[0],l[1],.7*s,0,2*Math.PI),o.stroke()))}drawEdgeHighlight(e,t,i,a,s){if(!e||!t)return;const n=this.ctx,o=e.split("-"),l=Number(o[0]),r=Number(o[1]);if(isNaN(l)||isNaN(r))return;const c=this._s1Scratch,d=this._s2Scratch;this.project(i[2*l],i[2*l+1],a,c),this.project(i[2*r],i[2*r+1],a,d);const h=Math.min(c[0],d[0]),u=Math.max(c[0],d[0]),v=Math.min(c[1],d[1]),m=Math.max(c[1],d[1]);u<-20||h>this.canvas.width+20||m<-20||v>this.canvas.height+20||(n.strokeStyle="#ff00ff",n.lineWidth=3*s,n.beginPath(),n.moveTo(c[0],c[1]),n.lineTo(d[0],d[1]),n.stroke())}drawFlow(e,t,i,a,s,n,o,l,r,c){if(!e)return;const d=this.ctx,h=.002*performance.now(),u=this._s1Scratch,v=this._s2Scratch,m=Math.max(1,Math.floor(t/15e3));for(let g=0;g<t/2;g+=m){const t=e[2*g],m=e[2*g+1],p=i[2*t],f=i[2*t+1],M=i[2*m],b=i[2*m+1];if((p>M?p:M)<o||(p<M?p:M)>l||(f>b?f:b)<r||(f<b?f:b)>c)continue;this.project(p,f,a,u),this.project(M,b,a,v);const w=Math.min(u[0],v[0]),y=Math.max(u[0],v[0]),x=Math.min(u[1],v[1]),k=Math.max(u[1],v[1]);if(y<-20||w>this.canvas.width+20||k<-20||x>this.canvas.height+20)continue;const C=(h+.1*g%1)%1,E=u[0]+(v[0]-u[0])*C,I=u[1]+(v[1]-u[1])*C;d.beginPath(),d.arc(E,I,2*n,0,2*Math.PI),d.fillStyle="dark"===s?"#00ffcc":"#00aa88",d.shadowBlur=4*n,d.shadowColor=d.fillStyle,d.fill(),d.shadowBlur=0}}drawHoverHighlight(e,t,i,a,s,n,o){const l=this.ctx;l.lineWidth=2*o,l.strokeStyle="dark"===n?"rgba(0, 255, 204, 0.6)":"rgba(0, 170, 136, 0.5)";const r=this._s1Scratch,c=this._s2Scratch;for(let d=0;d<i/2;d++){const i=t[2*d],n=t[2*d+1];i!==e&&n!==e||(this.project(a[2*i],a[2*i+1],s,r),this.project(a[2*n],a[2*n+1],s,c),l.beginPath(),l.moveTo(r[0],r[1]),l.lineTo(c[0],c[1]),l.stroke())}}drawNodeLabels(e,t,i,a,s,n,o,l,r,c,d,h){const u=this.ctx;u.textAlign="center",u.textBaseline="top";const v=this._spScratch;let m=0;for(let g=0;g<e&&!(m>200);g++){const e=i[2*g],p=i[2*g+1];if(e<r||e>c||p<d||p>h)continue;const f=t.get(g);if(!f)continue;this.project(e,p,a,v);const M=v[0],b=v[1];if(M<-50||M>this.canvas.width+50||b<-50||b>this.canvas.height+50)continue;m++;const w=.5*o,y=l>.6;if(o>12*n&&(u.beginPath(),u.arc(M,b,w,0,2*Math.PI),u.strokeStyle="dark"===s?"rgba(255, 255, 255, 0.8)":"rgba(0, 0, 0, 0.8)",u.lineWidth=1*n,u.stroke()),y)if(f.processedImageElement){const e=o*.7;u.drawImage(f.processedImageElement,M-e/2,b-e/2,e,e)}else if(f.imageElement&&f.imageElement.complete&&0!==f.imageElement.naturalWidth){const e=o*.7;u.save(),u.beginPath(),u.arc(M,b,.9*w,0,2*Math.PI),u.clip(),u.filter="grayscale(100%) brightness(1000%)",u.drawImage(f.imageElement,M-e/2,b-e/2,e,e),u.restore()}else f.icon&&(u.font=.6*o+"px serif",u.fillStyle="dark"===s?"white":"black",u.fillText(f.icon,M,b-.2*o));if(!(l<.5)&&f.label){const e=w+8*n;u.font=12*n+"px Inter, sans-serif",u.fillStyle="dark"===s?"white":"black",u.fillText(f.label,M,b+e)}}}}class S{lastMouse=i.create();isPanning=!1;engine;canvas;lastTouchDistance=0;lastTouchMidpoint=i.create();isTouching=!1;touchStartTime=0;touchStartPos=i.create();longPressTimer=null;isLongPress=!1;constructor(e,t){this.engine=e,this.canvas=t,this.setupListeners()}setupListeners(){this.canvas.addEventListener("mousedown",e=>this.handleMouseDown(e)),window.addEventListener("mousemove",e=>this.handleMouseMove(e)),window.addEventListener("mouseup",()=>this.handleMouseUp()),this.canvas.addEventListener("wheel",e=>this.handleWheel(e),{passive:!1}),this.canvas.addEventListener("touchstart",e=>this.handleTouchStart(e),{passive:!1}),this.canvas.addEventListener("touchmove",e=>this.handleTouchMove(e),{passive:!1}),this.canvas.addEventListener("touchend",e=>this.handleTouchEnd(e)),this.canvas.addEventListener("touchcancel",e=>this.handleTouchEnd(e))}handleMouseDown(e){const t=this.canvas.getBoundingClientRect(),a=e.clientX-t.left,s=e.clientY-t.top,n=this.engine.getState();if(e.shiftKey)return this.engine.updateInteractionState({isBoxSelecting:!0,selectionStart:i.fromValues(a,s),selectionEnd:i.fromValues(a,s)}),void this.engine.render();const o=this.engine.pick(a,s);if(null!==o){const t=n.selectedNodeIds.has(o);e.ctrlKey||e.metaKey||t||n.selectedNodeIds.clear(),n.selectedNodeIds.add(o),this.engine.updateInteractionState({isMultiDragging:!0,draggedNodeId:null}),this.engine.syncDragOffsets(a,s),this.canvas.dispatchEvent(new CustomEvent("node-selected",{detail:o})),this.canvas.dispatchEvent(new CustomEvent("nodes-selected",{detail:Array.from(n.selectedNodeIds)}))}else{n.selectedNodeIds.clear();const e=this.engine.getEdgeAt(a,s),t=this.engine.pickCombo(a,s);this.engine.updateInteractionState({selectedEdgeId:e,selectedComboId:t}),this.canvas.dispatchEvent(new CustomEvent("edge-selected",{detail:e})),this.canvas.dispatchEvent(new CustomEvent("combo-selected",{detail:t})),this.canvas.dispatchEvent(new CustomEvent("nodes-selected",{detail:[]})),this.canvas.dispatchEvent(new CustomEvent("node-selected",{detail:null})),e||t||(this.isPanning=!0)}i.set(this.lastMouse,e.clientX,e.clientY),this.engine.render()}handleMouseMove(e){const t=this.canvas.getBoundingClientRect(),a=e.clientX-t.left,s=e.clientY-t.top,n=this.engine.getState();if(n.isBoxSelecting)return this.engine.updateInteractionState({selectionEnd:i.fromValues(a,s)}),void this.engine.render();if(n.isMultiDragging||null!==n.draggedNodeId)this.engine.handleDragging(a,s);else if(this.isPanning){const t=(e.clientX-this.lastMouse[0])/(this.canvas.width/2),a=-(e.clientY-this.lastMouse[1])/(this.canvas.height/2);this.engine.pan(t,a),i.set(this.lastMouse,e.clientX,e.clientY)}else{const e=n.hoveredNodeId,t=this.engine.pick(a,s);t!==e&&(this.engine.updateInteractionState({hoveredNodeId:t}),this.engine.render(),this.canvas.dispatchEvent(new CustomEvent("node-hovered",{detail:t})))}}handleMouseUp(){this.engine.getState().isBoxSelecting&&this.engine.performBoxSelection(),this.isPanning=!1,this.engine.updateInteractionState({isBoxSelecting:!1,isMultiDragging:!1,draggedNodeId:null}),this.engine.render()}handleWheel(e){e.preventDefault();const t=this.canvas.getBoundingClientRect(),i=e.clientX-t.left,a=e.clientY-t.top,s=.001*-e.deltaY;this.engine.zoomAt(i,a,s)}handleTouchStart(e){if(e.preventDefault(),this.isTouching=!0,this.touchStartTime=Date.now(),this.isLongPress=!1,1===e.touches.length){const t=e.touches[0],a=this.canvas.getBoundingClientRect(),s=t.clientX-a.left,n=t.clientY-a.top;i.set(this.touchStartPos,s,n),i.set(this.lastMouse,t.clientX,t.clientY),this.longPressTimer=window.setTimeout(()=>{this.isLongPress=!0,this.triggerContextMenu(t.clientX,t.clientY)},500);const o=this.engine.pick(s,n),l=this.engine.getState();null!==o&&(l.selectedNodeIds.has(o)||(l.selectedNodeIds.clear(),l.selectedNodeIds.add(o)),this.engine.updateInteractionState({isMultiDragging:!0,draggedNodeId:null}),this.engine.syncDragOffsets(s,n),this.canvas.dispatchEvent(new CustomEvent("node-selected",{detail:o})))}else if(2===e.touches.length){this.clearLongPress();const t=e.touches[0],a=e.touches[1];this.lastTouchDistance=i.distance(i.fromValues(t.clientX,t.clientY),i.fromValues(a.clientX,a.clientY)),i.set(this.lastTouchMidpoint,(t.clientX+a.clientX)/2,(t.clientY+a.clientY)/2)}}handleTouchMove(e){if(e.preventDefault(),this.isTouching){if(1===e.touches.length){const t=e.touches[0],a=this.canvas.getBoundingClientRect(),s=t.clientX-a.left,n=t.clientY-a.top;if(i.distance(this.touchStartPos,i.fromValues(s,n))>10&&this.clearLongPress(),this.isLongPress)return;if(this.engine.getState().isMultiDragging)this.engine.handleDragging(s,n);else{const e=(t.clientX-this.lastMouse[0])/(this.canvas.width/2),i=-(t.clientY-this.lastMouse[1])/(this.canvas.height/2);this.engine.pan(e,i)}i.set(this.lastMouse,t.clientX,t.clientY)}else if(2===e.touches.length){this.clearLongPress();const t=e.touches[0],a=e.touches[1],s=i.distance(i.fromValues(t.clientX,t.clientY),i.fromValues(a.clientX,a.clientY)),n=i.fromValues((t.clientX+a.clientX)/2,(t.clientY+a.clientY)/2),o=s/this.lastTouchDistance,l=this.canvas.getBoundingClientRect(),r=n[0]-l.left,c=n[1]-l.top;this.engine.zoomAt(r,c,o-1);const d=(n[0]-this.lastTouchMidpoint[0])/(this.canvas.width/2),h=-(n[1]-this.lastTouchMidpoint[1])/(this.canvas.height/2);this.engine.pan(d,h),this.lastTouchDistance=s,i.copy(this.lastTouchMidpoint,n)}this.engine.render()}}handleTouchEnd(e){if(this.isTouching=!1,this.clearLongPress(),0===e.touches.length&&!this.isLongPress){const t=Date.now()-this.touchStartTime,a=e.changedTouches[0],s=this.canvas.getBoundingClientRect(),n=a.clientX-s.left,o=a.clientY-s.top,l=i.distance(this.touchStartPos,i.fromValues(n,o));if(t<250&&l<10){const e=this.engine.pick(n,o);this.engine.selectNode(e)}}this.engine.updateInteractionState({isMultiDragging:!1}),this.engine.render()}clearLongPress(){null!==this.longPressTimer&&(window.clearTimeout(this.longPressTimer),this.longPressTimer=null)}triggerContextMenu(e,t){const i=new MouseEvent("contextmenu",{clientX:e,clientY:t,bubbles:!0,cancelable:!0});this.canvas.dispatchEvent(i)}}class R{gl;pickingEngine;overlayManager;program=null;edgeProgram=null;viewMatrix=e.create();vao=null;edgeVao=null;positionBuffer=null;colorBuffer=null;idBuffer=null;edgeIndexBuffer=null;pickingFramebuffer=null;pickingTexture=null;uMatrixLoc=null;uPointSizeLoc=null;uPickingModeLoc=null;uEdgeMatrixLoc=null;uEdgeColorLoc=null;nodeCount=0;edgeCount=0;positions=null;metadata=/* @__PURE__ */new Map;edgeIndices=null;edgeMetadata=/* @__PURE__ */new Map;combos=/* @__PURE__ */new Map;theme="dark";static MAX_ZOOM=100;static MIN_ZOOM=1e-4;state={zoom:1,offset:i.fromValues(0,0),selectedNodeIds:/* @__PURE__ */new Set,selectedEdgeId:null,selectedComboId:null,hoveredNodeId:null,isBoxSelecting:!1,selectionStart:i.create(),selectionEnd:i.create(),isMultiDragging:!1,draggedNodeId:null};dragOffsets=/* @__PURE__ */new Map;isFlowAnimating=!1;canvas;overlayCanvas;constructor(e,t){this.canvas=e,this.overlayCanvas=t;const i=e.getContext("webgl2",{antialias:!0,stencil:!0});if(!i)throw new Error("WebGL2 not supported");this.gl=i;const a=t.getContext("2d");if(!a)throw new Error("Canvas 2D not supported");this.pickingEngine=new _(i),this.overlayManager=new A(t,a),this.initShaders(),this.initBuffers(),this.initPicking(),this.updateMatrix(),new S(this,e),this.handleResize(),window.addEventListener("resize",()=>this.handleResize())}setData(e,t,i,a,s,n){this.positions=e,this.nodeCount=i.length,this.metadata=a;const o=this.gl;o.bindBuffer(o.ARRAY_BUFFER,this.positionBuffer),o.bufferData(o.ARRAY_BUFFER,e,o.DYNAMIC_DRAW),o.bindBuffer(o.ARRAY_BUFFER,this.colorBuffer),o.bufferData(o.ARRAY_BUFFER,t,o.STATIC_DRAW),o.bindBuffer(o.ARRAY_BUFFER,this.idBuffer),o.bufferData(o.ARRAY_BUFFER,i,o.STATIC_DRAW),s&&(this.edgeIndices=s,this.edgeCount=s.length,o.bindBuffer(o.ELEMENT_ARRAY_BUFFER,this.edgeIndexBuffer),o.bufferData(o.ELEMENT_ARRAY_BUFFER,s,o.STATIC_DRAW)),n&&(this.edgeMetadata=n),this.render()}updatePositions(e){this.positions=e;const t=this.gl;t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,e),this.render()}setNodePosition(e,t,i){if(!this.positions||e>=this.nodeCount)return;this.positions[2*e]=t,this.positions[2*e+1]=i;const a=this.gl;a.bindBuffer(a.ARRAY_BUFFER,this.positionBuffer),a.bufferSubData(a.ARRAY_BUFFER,2*e*4,this.positions.subarray(2*e,2*e+2)),this.render()}getNodePosition(e){return!this.positions||e>=this.nodeCount?null:i.fromValues(this.positions[2*e],this.positions[2*e+1])}setFlowAnimation(e){if(this.isFlowAnimating=e,e){const e=()=>{this.isFlowAnimating&&(this.render(),requestAnimationFrame(e))};requestAnimationFrame(e)}else this.render()}setTheme(e){this.theme=e,this.render()}createCombo(e,t,i){this.combos.set(e,{id:e,label:t,nodeIds:new Set(i)}),this.render()}removeCombo(e){this.combos.delete(e),this.render()}updateCombo(e,t,i){const a=this.combos.get(e);a&&(a.label=t,a.nodeIds=new Set(i),this.render())}getCombo(e){return this.combos.get(e)}getSelectedNodeIds(){return Array.from(this.state.selectedNodeIds)}getNodeMetadata(e){return this.metadata.get(e)}getEdgeMetadata(e){return this.edgeMetadata.get(e)}addNodeToCombo(e,t){const i=this.combos.get(e);i&&(i.nodeIds.add(t),this.render())}removeNodeFromCombo(e,t){const i=this.combos.get(e);i&&(i.nodeIds.delete(t),this.render())}render(){const e=this.gl;if(!this.program)return;this.updateMatrix();const t="dark"===this.theme?.05:.95;e.clearColor(t,t,t,1),e.clear(e.COLOR_BUFFER_BIT),this.edgeCount>0&&this.edgeProgram&&(e.useProgram(this.edgeProgram),e.uniformMatrix3fv(this.uEdgeMatrixLoc,!1,this.viewMatrix),e.uniform4fv(this.uEdgeColorLoc,"dark"===this.theme?[1,1,1,.15]:[0,0,0,.1]),e.bindVertexArray(this.edgeVao),e.drawElements(e.LINES,this.edgeCount,e.UNSIGNED_INT,0)),e.useProgram(this.program),e.uniformMatrix3fv(this.uMatrixLoc,!1,this.viewMatrix),e.uniform1f(this.uPointSizeLoc,40*this.state.zoom*window.devicePixelRatio),e.uniform1i(this.uPickingModeLoc,0),e.bindVertexArray(this.vao),e.drawArrays(e.POINTS,0,this.nodeCount),this.renderOverlay()}renderOverlay(){this.overlayManager.render({...this.state,positions:this.positions,nodeCount:this.nodeCount,edgeCount:this.edgeCount,edgeIndices:this.edgeIndices,metadata:this.metadata,edgeMetadata:this.edgeMetadata,combos:this.combos,theme:this.theme,viewMatrix:this.viewMatrix,isFlowAnimating:this.isFlowAnimating})}getState(){return this.state}updateInteractionState(e){Object.assign(this.state,e)}pick(e,t){return this.program&&this.pickingFramebuffer&&this.vao?this.pickingEngine.pickNode({mouseX:e,mouseY:t,canvas:this.canvas,program:this.program,pickingFramebuffer:this.pickingFramebuffer,vao:this.vao,nodeCount:this.nodeCount,viewMatrix:this.viewMatrix,pointSize:40*this.state.zoom*window.devicePixelRatio}):null}getEdgeAt(e,t){return this.pickingEngine.pickEdge({mouseX:e,mouseY:t,edgeIndices:this.edgeIndices,positions:this.positions,nodeCount:this.nodeCount,viewMatrix:this.viewMatrix,canvasW:this.canvas.width,canvasH:this.canvas.height})}pickCombo(e,t){return this.pickingEngine.pickCombo({mouseX:e,mouseY:t,combos:this.combos,positions:this.positions,nodeCount:this.nodeCount,viewMatrix:this.viewMatrix,canvasW:this.canvas.width,canvasH:this.canvas.height})}fitToView(){if(!this.positions||0===this.nodeCount)return this.state.zoom=1,this.state.offset=i.fromValues(0,0),void this.render();let e=1/0,t=1/0,a=-1/0,s=-1/0;for(let i=0;i<this.nodeCount;i++){const n=this.positions[2*i],o=this.positions[2*i+1];n<e&&(e=n),n>a&&(a=n),o<t&&(t=o),o>s&&(s=o)}const n=a-e,o=s-t,l=(e+a)/2,r=(t+s)/2,c=2*(this.canvas.width/this.canvas.height)*.9/Math.max(n,.01),d=1.8/Math.max(o,.01);this.state.zoom=Math.min(c,d,100),this.state.offset=i.fromValues(-l,-r),this.render()}zoomIn(){this.state.zoom=Math.min(R.MAX_ZOOM,1.2*this.state.zoom),this.render()}zoomOut(){this.state.zoom=Math.max(R.MIN_ZOOM,this.state.zoom/1.2),this.render()}setCameraCenter(e,t){this.state.offset=i.fromValues(-e,-t),this.render()}setCameraZoom(e){this.state.zoom=Math.max(R.MIN_ZOOM,Math.min(R.MAX_ZOOM,e)),this.render()}selectNode(e){this.state.selectedNodeIds.clear(),null!==e&&this.state.selectedNodeIds.add(e),this.canvas.dispatchEvent(new CustomEvent("node-selected",{detail:e})),this.render()}zoomAt(e,t,a){const s=window.devicePixelRatio,n=this.unproject(e*s,t*s);this.state.zoom=Math.max(R.MIN_ZOOM,Math.min(R.MAX_ZOOM,this.state.zoom*(1+a))),this.updateMatrix();const o=this.unproject(e*s,t*s);i.add(this.state.offset,this.state.offset,i.sub(i.create(),o,n)),this.render()}pan(e,t){i.add(this.state.offset,this.state.offset,i.fromValues(e/this.state.zoom,t/this.state.zoom)),this.render()}syncDragOffsets(e,t){const a=window.devicePixelRatio,s=this.unproject(e*a,t*a);this.dragOffsets.clear();for(const n of this.state.selectedNodeIds){const e=this.getNodePosition(n);e&&this.dragOffsets.set(n,i.sub(i.create(),e,s))}}handleDragging(e,t){if(!this.positions)return;const a=window.devicePixelRatio,s=this.unproject(e*a,t*a),n=this.gl;n.bindBuffer(n.ARRAY_BUFFER,this.positionBuffer);for(const o of this.state.selectedNodeIds){const e=this.dragOffsets.get(o);if(e){const t=i.add(i.create(),s,e);this.positions[2*o]=t[0],this.positions[2*o+1]=t[1],n.bufferSubData(n.ARRAY_BUFFER,2*o*4,this.positions.subarray(2*o,2*o+2)),this.canvas.dispatchEvent(new CustomEvent("node-moved",{detail:{id:o,x:t[0],y:t[1]}}))}}this.render()}performBoxSelection(){if(!this.positions)return;const e=window.devicePixelRatio,t=this.unproject(this.state.selectionStart[0]*e,this.state.selectionStart[1]*e),i=this.unproject(this.state.selectionEnd[0]*e,this.state.selectionEnd[1]*e),a=Math.min(t[0],i[0]),s=Math.max(t[0],i[0]),n=Math.min(t[1],i[1]),o=Math.max(t[1],i[1]);this.state.selectedNodeIds.clear();for(let l=0;l<this.nodeCount;l++){const e=this.positions[2*l],t=this.positions[2*l+1];e>=a&&e<=s&&t>=n&&t<=o&&this.state.selectedNodeIds.add(l)}this.canvas.dispatchEvent(new CustomEvent("nodes-selected",{detail:Array.from(this.state.selectedNodeIds)}))}unproject(a,s){const n=a/this.canvas.width*2-1,o=-(s/this.canvas.height*2-1),l=e.invert(e.create(),this.viewMatrix);if(!l)return i.create();const r=t.fromValues(n,o,1);return t.transformMat3(r,r,l),i.fromValues(r[0],r[1])}initShaders(){const e=this.gl;this.program=this.createProgram("#version 300 es\nlayout(location = 0) in vec2 a_position;\nlayout(location = 1) in vec4 a_color;\nlayout(location = 2) in float a_id;\n\nuniform mat3 u_matrix;\nuniform float u_pointSize;\nuniform bool u_pickingMode;\n\nout vec4 v_color;\nflat out uint v_id;\n\nvoid main() {\n vec3 position = u_matrix * vec3(a_position, 1.0);\n gl_Position = vec4(position.xy, 0, 1);\n gl_PointSize = u_pointSize;\n v_color = a_color;\n v_id = uint(a_id);\n}\n","#version 300 es\nprecision highp float;\n\nin vec4 v_color;\nflat in uint v_id;\n\nuniform bool u_pickingMode;\nout vec4 outColor;\n\nvoid main() {\n float dist = distance(gl_PointCoord, vec2(0.5));\n if (dist > 0.5) discard;\n\n if (u_pickingMode) {\n uint id = v_id + 1u;\n float r = float((id >> 16) & 0xFFu) / 255.0;\n float g = float((id >> 8) & 0xFFu) / 255.0;\n float b = float(id & 0xFFu) / 255.0;\n outColor = vec4(r, g, b, 1.0);\n } else {\n outColor = v_color;\n }\n}\n"),this.uMatrixLoc=e.getUniformLocation(this.program,"u_matrix"),this.uPointSizeLoc=e.getUniformLocation(this.program,"u_pointSize"),this.uPickingModeLoc=e.getUniformLocation(this.program,"u_pickingMode"),this.edgeProgram=this.createProgram("#version 300 es\nlayout(location = 0) in vec2 a_position;\n\nuniform mat3 u_matrix;\n\nvoid main() {\n vec3 position = u_matrix * vec3(a_position, 1.0);\n gl_Position = vec4(position.xy, 0, 1);\n}\n","#version 300 es\nprecision highp float;\nuniform vec4 u_color;\nout vec4 outColor;\n\nvoid main() {\n outColor = u_color;\n}\n"),this.uEdgeMatrixLoc=e.getUniformLocation(this.edgeProgram,"u_matrix"),this.uEdgeColorLoc=e.getUniformLocation(this.edgeProgram,"u_color")}initBuffers(){const e=this.gl;this.vao=e.createVertexArray(),e.bindVertexArray(this.vao),this.positionBuffer=e.createBuffer(),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(0),e.vertexAttribPointer(0,2,e.FLOAT,!1,0,0),this.colorBuffer=e.createBuffer(),e.bindBuffer(e.ARRAY_BUFFER,this.colorBuffer),e.enableVertexAttribArray(1),e.vertexAttribPointer(1,4,e.FLOAT,!1,0,0),this.idBuffer=e.createBuffer(),e.bindBuffer(e.ARRAY_BUFFER,this.idBuffer),e.enableVertexAttribArray(2),e.vertexAttribPointer(2,1,e.FLOAT,!1,0,0),this.edgeVao=e.createVertexArray(),e.bindVertexArray(this.edgeVao),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(0),e.vertexAttribPointer(0,2,e.FLOAT,!1,0,0),this.edgeIndexBuffer=e.createBuffer(),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.edgeIndexBuffer),e.bindVertexArray(null)}initPicking(){const e=this.gl;this.pickingFramebuffer=e.createFramebuffer(),this.pickingTexture=e.createTexture(),e.bindTexture(e.TEXTURE_2D,this.pickingTexture),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,this.canvas.width,this.canvas.height,0,e.RGBA,e.UNSIGNED_BYTE,null),e.bindFramebuffer(e.FRAMEBUFFER,this.pickingFramebuffer),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,this.pickingTexture,0),e.bindFramebuffer(e.FRAMEBUFFER,null)}handleResize(){const e=window.devicePixelRatio;this.canvas.width=this.canvas.clientWidth*e,this.canvas.height=this.canvas.clientHeight*e,this.overlayCanvas.width=this.overlayCanvas.clientWidth*e,this.overlayCanvas.height=this.overlayCanvas.clientHeight*e,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.initPicking(),this.render()}updateMatrix(){const t=this.canvas.width/this.canvas.height;e.identity(this.viewMatrix),e.scale(this.viewMatrix,this.viewMatrix,[this.state.zoom/t,this.state.zoom]),e.translate(this.viewMatrix,this.viewMatrix,this.state.offset)}createProgram(e,t){const i=this.gl,a=i.createShader(i.VERTEX_SHADER);i.shaderSource(a,e),i.compileShader(a);const s=i.createShader(i.FRAGMENT_SHADER);i.shaderSource(s,t),i.compileShader(s);const n=i.createProgram();return i.attachShader(n,a),i.attachShader(n,s),i.linkProgram(n),n}}const F=["width","height","stroke-width"],T=["d"],L=["cx","cy","r"],P=["x1","y1","x2","y2"],B=["x","y","width","height","rx","ry"],N=(e,t)=>{const i=e.__vccOpts||e;for(const[a,s]of t)i[a]=s;return i},z=/* @__PURE__ */N(/* @__PURE__ */a({__name:"LucideIcon",props:{name:{},size:{default:24},strokeWidth:{default:2}},setup(e){const t=e,i={sun:{paths:["M12 1v2","M12 21v2","M4.22 4.22l1.42 1.42","M18.36 18.36l1.42 1.42","M1 12h2","M21 12h2","M4.22 19.78l1.42-1.42","M18.36 5.64l1.42-1.42"],circles:[{cx:12,cy:12,r:4}]},moon:{paths:["M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"]},maximize:{paths:["M8 3H5a2 2 0 0 0-2 2v3","M21 8V5a2 2 0 0 0-2-2h-3","M3 16v3a2 2 0 0 0 2 2h3","M16 21h3a2 2 0 0 0 2-2v-3"]},plus:{paths:["M12 5v14","M5 12h14"]},minus:{paths:["M5 12h14"]},rocket:{paths:["M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z","m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z","M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0","M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5"]},shrink:{paths:["M14 10l7-7","M3 21l7-7","M21 10h-7V3","M3 14h7v7"]},expand:{paths:["M15 3h6v6","M9 21H3v-6","M21 3l-7 7","M3 21l7-7"]},"layout-grid":{rects:[{x:3,y:3,width:7,height:7,rx:1},{x:14,y:3,width:7,height:7,rx:1},{x:14,y:14,width:7,height:7,rx:1},{x:3,y:14,width:7,height:7,rx:1}]},circle:{circles:[{cx:12,cy:12,r:10}]},dices:{rects:[{x:2,y:11,width:11,height:11,rx:2}],paths:["M7 15h.01","M7 19h.01","M11 19h.01","M22 5V2a1 1 0 0 0-1-1h-6a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2","M22 5h-4a1 1 0 0 0-1 1v4","M22 5c0-1.1-.9-2-2-2","M14 7h.01"]},spiral:{paths:["M12 12a1 1 0 1 0 1 1","M12 7a5 5 0 1 0 5 5","M12 2a10 10 0 1 0 10 10","M12 12a1 1 0 0 0-1-1"]},target:{circles:[{cx:12,cy:12,r:10},{cx:12,cy:12,r:6},{cx:12,cy:12,r:2}]},atom:{circles:[{cx:12,cy:12,r:1}],paths:["M12 2v2","M12 20v2","m4.93 4.93 1.41 1.41","m17.66 17.66 1.41 1.41","M2 12h2","M20 12h2","m6.34 17.66-1.41-1.41","m19.07 4.93-1.41 1.41"]},"git-branch":{circles:[{cx:6,cy:3,r:3},{cx:6,cy:21,r:3},{cx:18,cy:9,r:3}],paths:["M6 6v12","M18 12a6 6 0 0 1-6 6H6"]},sparkles:{paths:["m12 3-1.912 5.813a2 2 0 0 1-1.275 1.275L3 12l5.813 1.912a2 2 0 0 1 1.275 1.275L12 21l1.912-5.813a2 2 0 0 1 1.275-1.275L21 12l-5.813-1.912a2 2 0 0 1-1.275-1.275L12 3Z","M5 3L4 5.5 1.5 6.5 4 7.5 5 10l1-2.5 2.5-1L6 5.5 5 3Z","M19 19l-1 2.5-2.5 1L18 23.5l1 2.5 1-2.5 2.5-1-2.5-1-1-2.5Z"]},search:{circles:[{cx:11,cy:11,r:8}],lines:[{x1:21,y1:21,x2:16.65,y2:16.65}]},info:{circles:[{cx:12,cy:12,r:10}],paths:["M12 16v-4","M12 8h.01"]},"trash-2":{paths:["M3 6h18","M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6","M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2","M10 11v6","M14 11v6"]},palette:{circles:[{cx:13.5,cy:6.5,r:.5},{cx:17.5,cy:10.5,r:.5},{cx:8.5,cy:7.5,r:.5},{cx:6.5,cy:12.5,r:.5}],paths:["M12 2C6.47 2 2 6.47 2 12s4.47 10 9.99 10a3 3 0 0 0 3-3c0-.8-.34-1.56-.92-2.1l-.1-.08c-.53-.45-.88-1.1-.88-1.82 0-1.38 1.12-2.5 2.5-2.5H19a3 3 0 0 0 2-5c0-4.42-4.03-8-9-8Z"]},pin:{paths:["M15 4.5l-4 4L7 10l-1.5 1.5 7 7L14 17l1.5-4 4-4L15 4.5z","m9 21 3-3","M14 4.5L19.5 10"]},box:{paths:["M21 8a2 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","m3.3 7 8.7 5 8.7-5","M12 22V12"]},eye:{paths:["M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"],circles:[{cx:12,cy:12,r:3}]},"eye-off":{paths:["M9.88 9.88a3 3 0 1 0 4.24 4.24","M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68","M6.61 6.61A13.52 13.52 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61","m2 2 20 20"]},"refresh-cw":{paths:["M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8","M21 3v5h-5","M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16","M3 21v-5h5"]},scale:{paths:["m16 16 3-8 3 8c-.87.62-1.92 1-3 1s-2.13-.38-3-1Z","m2 16 3-8 3 8c-.87.62-1.92 1-3 1s-2.13-.38-3-1Z","M7 21h10","M12 3v18","M3 7h18"]},zap:{paths:["M13 2 3 14h9l-1 8 10-12h-9l1-8z"]},x:{paths:["M18 6L6 18","M6 6l12 12"]}},a=s(()=>i[t.name]||i.search),c=s(()=>a.value.paths||[]),d=s(()=>a.value.circles||[]),h=s(()=>a.value.lines||[]),u=s(()=>a.value.rects||[]);return(t,i)=>(n(),o("svg",{xmlns:"http://www.w3.org/2000/svg",width:e.size,height:e.size,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":e.strokeWidth,"stroke-linecap":"round","stroke-linejoin":"round",class:"lucide-icon"},[(n(!0),o(l,null,r(c.value,(e,t)=>(n(),o("path",{key:t,d:e},null,8,T))),128)),(n(!0),o(l,null,r(d.value,(e,t)=>(n(),o("circle",{key:t,cx:e.cx,cy:e.cy,r:e.r},null,8,L))),128)),(n(!0),o(l,null,r(h.value,(e,t)=>(n(),o("line",{key:t,x1:e.x1,y1:e.y1,x2:e.x2,y2:e.y2},null,8,P))),128)),(n(!0),o(l,null,r(u.value,(e,t)=>(n(),o("rect",{key:t,x:e.x,y:e.y,width:e.width,height:e.height,rx:e.rx,ry:e.ry},null,8,B))),128))],8,F))}}),[["__scopeId","data-v-6aa14fad"]]),D={class:"radial-center glass shadow-glow"},Y=["onClick"],V={class:"radial-icon"},U={class:"radial-label"},O=/* @__PURE__ */N(/* @__PURE__ */a({__name:"RadialMenu",props:{show:{type:Boolean},x:{},y:{},type:{},items:{}},emits:["action"],setup(e){const t=(e,t)=>{const i=e/t*Math.PI*2-Math.PI/2,a=window.innerWidth<768?100:85;return{transform:`translate(-50%, -50%) translate(${Math.cos(i)*a}px, ${Math.sin(i)*a}px)`,transitionDelay:.05*e+"s"}};return(i,a)=>e.show?(n(),o("div",{key:0,class:"radial-menu",style:d({left:e.x+"px",top:e.y+"px"}),onMousedown:a[0]||(a[0]=c(()=>{},["stop"])),onTouchstart:a[1]||(a[1]=c(()=>{},["stop"]))},[h("div",D,[u(i.$slots,"center",{},()=>["node"===e.type?(n(),v(z,{key:0,name:"target",size:"24"})):"edge"===e.type?(n(),v(z,{key:1,name:"git-branch",size:"24"})):(n(),v(z,{key:2,name:"search",size:"24"}))],!0)]),(n(!0),o(l,null,r(e.items,(a,s)=>(n(),o("div",{key:s,class:"radial-item",style:d(t(s,e.items.length))},[h("button",{class:"radial-item-inner glass-interactive",onClick:e=>i.$emit("action",a.action)},[h("span",V,[m(z,{name:a.icon,size:"20"},null,8,["name"])]),h("span",U,g(a.label),1)],8,Y)],4))),128))],36)):p("",!0)}}),[["__scopeId","data-v-9d75fdc7"]]),X={class:"top-right-controls glass"},W=["title"],j=/* @__PURE__ */N(/* @__PURE__ */a({__name:"ViewControls",props:{theme:{}},emits:["toggleTheme","fit","zoomIn","zoomOut","stress"],setup(e){const t=f(!1),i=()=>{document.fullscreenElement?(document.exitFullscreen(),t.value=!1):(document.documentElement.requestFullscreen(),t.value=!0)};return(a,s)=>(n(),o("div",X,[h("button",{class:"control-btn glass-interactive",onClick:s[0]||(s[0]=e=>a.$emit("toggleTheme")),title:"dark"===e.theme?"Switch to Light":"Switch to Dark"},[m(z,{name:"dark"===e.theme?"moon":"sun",size:"20"},null,8,["name"])],8,W),s[5]||(s[5]=h("div",{class:"divider"},null,-1)),h("button",{class:"control-btn glass-interactive",onClick:s[1]||(s[1]=e=>a.$emit("fit")),title:"Fit View"},[m(z,{name:"maximize",size:"20"})]),h("button",{class:"control-btn glass-interactive",onClick:s[2]||(s[2]=e=>a.$emit("zoomIn")),title:"Zoom In"},[m(z,{name:"plus",size:"20"})]),h("button",{class:"control-btn glass-interactive",onClick:s[3]||(s[3]=e=>a.$emit("zoomOut")),title:"Zoom Out"},[m(z,{name:"minus",size:"20"})]),s[6]||(s[6]=h("div",{class:"divider"},null,-1)),h("button",{class:"control-btn glass-interactive stress-btn",onClick:s[4]||(s[4]=e=>a.$emit("stress")),title:"Stress Test (100k Nodes)"},[m(z,{name:"rocket",size:"20"})]),s[7]||(s[7]=h("div",{class:"divider"},null,-1)),h("button",{class:"control-btn glass-interactive",onClick:i,title:"Toggle Fullscreen"},[m(z,{name:t.value?"shrink":"expand",size:"20"},null,8,["name"])])]))}}),[["__scopeId","data-v-f90ff709"]]),Z={class:"layout-controls glass"},H={class:"scroll-container"},$=["onClick"],G={class:"btn-icon"},q={class:"btn-name"},K=/* @__PURE__ */N(/* @__PURE__ */a({__name:"LayoutControls",props:{layouts:{},currentLayout:{},flowEnabled:{type:Boolean}},emits:["runLayout","toggleFlow"],setup:e=>(t,i)=>(n(),o("div",Z,[h("div",H,[(n(!0),o(l,null,r(e.layouts,i=>(n(),o("button",{key:i.id,class:M(["layout-btn glass-interactive",{active:e.currentLayout===i.id}]),onClick:e=>t.$emit("runLayout",i.id)},[h("span",G,[m(z,{name:i.icon,size:"16"},null,8,["name"])]),h("span",q,g(i.name),1)],10,$))),128))])]))}),[["__scopeId","data-v-2650a643"]]),J={key:0,class:"property-panel glass node-panel"},Q={class:"panel-header"},ee={class:"panel-content"},te={key:0,class:"val-container"},ie=["src"],ae={key:1},se={key:1,class:"json-prop"},ne={key:1,class:"property-panel glass edge-panel"},oe={class:"panel-header"},le={class:"panel-content"},re={class:"prop-group"},ce={class:"id-badge"},de={key:0,class:"val-container"},he=["src"],ue={key:1},ve={key:1,class:"json-prop"},me={key:2,class:"property-panel glass combo-panel"},ge={class:"panel-header"},pe={class:"panel-content"},fe={class:"prop-group shadow-sm"},Me=["value"],be={class:"prop-group"},we={class:"member-list"},ye=["onClick"],xe={key:0,class:"more-hint"},ke=/* @__PURE__ */N(/* @__PURE__ */a({__name:"PropertyPanel",props:{nodeId:{},nodeMetadata:{},nodeX:{},nodeY:{},edgeId:{},edgeMetadata:{},combo:{}},emits:["update:nodeX","update:nodeY","update:nodeId","update:edgeId","update:combo","update:comboLabel","removeFromCombo"],setup(e,{emit:t}){const i=e=>"string"==typeof e&&e.startsWith("data:image/");return(t,a)=>null!==e.nodeId?(n(),o("div",J,[h("div",Q,[a[4]||(a[4]=h("h3",null,"Node Properties",-1)),h("button",{class:"close-btn",onClick:a[0]||(a[0]=e=>t.$emit("update:nodeId",null))},[m(z,{name:"x",size:"18"})])]),h("div",ee,[e.nodeMetadata&&e.nodeMetadata.data?(n(!0),o(l,{key:0},r(e.nodeMetadata.data,(t,a)=>(n(),o("div",{key:a,class:"prop-group"},[h("label",null,g(a),1),"object"!=typeof t?(n(),o("div",te,[i(t)?(n(),o("img",{key:0,src:t,class:"prop-image",style:d("backgroundImage"===a?{backgroundColor:e.nodeMetadata.data.color||"var(--primary)"}:{})},null,12,ie)):(n(),o("span",ae,g(t),1))])):(n(),o("pre",se,g(JSON.stringify(t,null,2)),1))]))),128)):p("",!0)])])):null!==e.edgeId?(n(),o("div",ne,[h("div",oe,[a[5]||(a[5]=h("h3",null,"Edge Properties",-1)),h("button",{class:"close-btn",onClick:a[1]||(a[1]=e=>t.$emit("update:edgeId",null))},[m(z,{name:"x",size:"18"})])]),h("div",le,[h("div",re,[a[6]||(a[6]=h("label",null,"ID",-1)),h("span",ce,g(e.edgeId),1)]),e.edgeMetadata&&e.edgeMetadata.data?(n(!0),o(l,{key:0},r(e.edgeMetadata.data,(t,a)=>(n(),o("div",{key:a,class:"prop-group"},[h("label",null,g(a),1),"object"!=typeof t?(n(),o("div",de,[i(t)?(n(),o("img",{key:0,src:t,class:"prop-image",style:d("backgroundImage"===a?{backgroundColor:e.edgeMetadata.data.color||"var(--secondary)"}:{})},null,12,he)):(n(),o("span",ue,g(t),1))])):(n(),o("pre",ve,g(JSON.stringify(t,null,2)),1))]))),128)):p("",!0)])])):e.combo?(n(),o("div",me,[h("div",ge,[a[7]||(a[7]=h("h3",null,"Group Properties",-1)),h("button",{class:"close-btn",onClick:a[2]||(a[2]=e=>t.$emit("update:combo",null))},[m(z,{name:"x",size:"18"})])]),h("div",pe,[h("div",fe,[a[8]||(a[8]=h("label",null,"Label",-1)),h("input",{type:"text",value:e.combo.label,class:"full-width",onInput:a[3]||(a[3]=e=>t.$emit("update:comboLabel",e.target.value))},null,40,Me)]),h("div",be,[h("label",null,"Members ("+g(e.combo.nodeIds.size)+")",1),h("div",we,[(n(!0),o(l,null,r(Array.from(e.combo.nodeIds).slice(0,50),e=>(n(),o("div",{key:e,class:"member-item"},[h("span",null,"Node "+g(e),1),h("button",{class:"remove-btn",onClick:i=>t.$emit("removeFromCombo",e)},[m(z,{name:"trash-2",size:"12"})],8,ye)]))),128)),e.combo.nodeIds.size>50?(n(),o("div",xe," + "+g(e.combo.nodeIds.size-50)+" more ",1)):p("",!0)])])])])):p("",!0)}}),[["__scopeId","data-v-205cc0b7"]]),Ce={class:"search-icon"},Ee={key:0,class:"results-panel"},Ie=["onMousedown","onTouchstart"],_e={class:"node-icon"},Ae={class:"node-info"},Se={class:"node-label"},Re={class:"node-id"},Fe={key:1,class:"no-results"},Te=/* @__PURE__ */N(/* @__PURE__ */a({__name:"SearchBar",props:{nodes:{}},emits:["select"],setup(e,{emit:t}){const i=e,a=t,d=f(""),u=f(!1),v=f(null),C=f(window.innerWidth<768),E=()=>{C.value=window.innerWidth<768};b(()=>{window.addEventListener("resize",E)}),w(()=>{window.removeEventListener("resize",E)});const I=s(()=>{if(!d.value)return[];const e=d.value.toLowerCase();return i.nodes.filter(t=>t.label?.toLowerCase().includes(e)||t.id.toString().includes(e)).slice(0,10)}),_=e=>{a("select",e),d.value="",u.value=!1},A=()=>{C.value&&!u.value&&(u.value=!0,setTimeout(()=>v.value?.focus(),100))},S=()=>{d.value="",u.value=!1,v.value?.blur()},R=()=>{C.value||setTimeout(()=>{u.value=!1},200)};return(e,t)=>(n(),o("div",{class:M(["search-wrapper",{"mobile-expanded":u.value&&C.value,"is-mobile":C.value}])},[h("div",{class:M(["search-container glass",{expanded:u.value,"has-query":d.value.length>0}])},[h("div",{class:"search-input-wrapper",onClick:A},[h("span",Ce,[m(z,{name:"search",size:C.value?20:14},null,8,["size"])]),y(h("input",{ref_key:"inputRef",ref:v,"onUpdate:modelValue":t[0]||(t[0]=e=>d.value=e),placeholder:"Search nodes...",onFocus:t[1]||(t[1]=e=>u.value=!0),onBlur:R,onKeydown:t[2]||(t[2]=x(e=>u.value=!1,["esc"]))},null,544),[[k,d.value]]),d.value||C.value&&u.value?(n(),o("div",{key:0,class:"clear-btn",onClick:c(S,["stop"])},[m(z,{name:d.value?"x":"chevron-down",size:C.value?20:12},null,8,["name","size"])])):p("",!0)]),u.value&&I.value.length>0?(n(),o("div",Ee,[(n(!0),o(l,null,r(I.value,e=>(n(),o("div",{key:e.id,class:"result-item",onMousedown:t=>_(e.id),onTouchstart:t=>_(e.id)},[h("span",_e,[m(z,{name:"circle",size:"8"})]),h("div",Ae,[h("div",Se,g(e.label),1),h("div",Re,"ID: "+g(e.id),1)])],40,Ie))),128))])):u.value&&d.value?(n(),o("div",Fe," No nodes found ")):p("",!0)],2),C.value&&u.value?(n(),o("div",{key:0,class:"mobile-backdrop",onClick:S})):p("",!0)],2))}}),[["__scopeId","data-v-283de02c"]]),Le={key:0,class:"mobile-menu glass shadow-lg"},Pe={class:"drawer-header"},Be={key:0,class:"drawer-content"},Ne={key:1,class:"drawer-content"},ze={class:"help-header"},De={class:"help-content"},Ye={class:"key-badge"},Ve={class:"action-desc"},Ue=/* @__PURE__ */N(/* @__PURE__ */a({__name:"GraphCanvas",props:{data:{}},setup(e){const t=e,i=f(null),a=f(null),s=f(1e4),d=f(null),u=f(null),x=f(null),k=f(null),_=f(0),A=f("dark"),S=f(null),F=f(0),T=f(0),L=f(null),P=f(null),B=f("random"),N=f(!1),D=f(0),Y=f([]),V=f(!1),U=f(window.innerWidth<768),X=f(null),W=f(!1),Z=f(null),H=e=>{X.value===e?X.value=null:X.value=e},$=e=>{ge(e),X.value=null},G=()=>{W.value=!0,setTimeout(()=>{Z.value?.handleWrapperClick?.()},50)},q=()=>{U.value=window.innerWidth<768},J=[{key:"Shift + Drag",action:"Box Selection"},{key:"Ctrl + Click",action:"Multi Selection"},{key:"Right Click",action:"Radial Menu"},{key:"Scroll",action:"Zoom In/Out"},{key:"Drag",action:"Pan View"}],Q=[{id:"random",name:"Random",icon:"dices"},{id:"grid",name:"Grid",icon:"layout-grid"},{id:"circle",name:"Circle",icon:"circle"},{id:"spiral",name:"Spiral",icon:"spiral"},{id:"concentric",name:"Concentric",icon:"target"},{id:"radial",name:"Radial",icon:"atom"},{id:"hierarchy",name:"Hierarchy",icon:"git-branch"},{id:"force",name:"Force",icon:"sparkles"}];let ee,te,ie,ae=null;const se=()=>{A.value="dark"===A.value?"light":"dark",ee&&ee.setTheme(A.value),document.documentElement.classList.toggle("light","light"===A.value)},ne=()=>{null!==u.value&&ee&&ee.setNodePosition(u.value,F.value,T.value)};C(u,()=>(()=>{if(null!==u.value&&ee){const e=ee.getNodePosition(u.value);e&&(F.value=Number(e[0].toFixed(3)),T.value=Number(e[1].toFixed(3))),L.value=ee.getNodeMetadata(u.value)}else L.value=null})()),C(F,()=>ne()),C(T,()=>ne()),C(k,e=>{S.value=e&&ee?ee.getCombo(e):null}),C(S,e=>{null===e&&(k.value=null)});const oe=e=>{if(k.value&&ee){const t=ee.getCombo(k.value);t&&(ee.updateCombo(t.id,e,Array.from(t.nodeIds)),S.value={...t,label:e})}},le=e=>{if(k.value&&ee){ee.removeNodeFromCombo(k.value,e);const t=ee.getCombo(k.value);t&&(S.value={...t,nodeIds:new Set(t.nodeIds)})}},re=()=>{N.value=!N.value,ee&&ee.setFlowAnimation(N.value)},ce=e=>{if(ee){ee.selectNode(e);const t=ee.getNodePosition(e);t&&(ee.setCameraCenter(t[0],t[1]),ee.setCameraZoom(2))}W.value=!1},de=f({show:!1,x:0,y:0,type:"none",target:null}),he=f([]),ue=e=>{const t=i.value?.getBoundingClientRect();if(!t||!ee)return;const a=e.clientX-t.left,s=e.clientY-t.top,n=ee.pick(a,s);if(null!==n)de.value={show:!0,x:e.clientX,y:e.clientY,type:"node",target:n},he.value=[{label:"Delete",icon:"trash-2",action:"delete"},{label:"Color",icon:"palette",action:"color"},{label:"Pin",icon:"pin",action:"pin"},{label:"Info",icon:"info",action:"info"}],_.value>1&&he.value.push({label:"Group",icon:"box",action:"create-combo"});else{const t=ee.getEdgeAt(a,s);if(t)de.value={show:!0,x:e.clientX,y:e.clientY,type:"edge",target:t},he.value=[{label:"Hide",icon:"eye-off",action:"hide"},{label:"Weight",icon:"scale",action:"weight"},{label:"Reverse",icon:"refresh-cw",action:"reverse"}];else{const t=ee.pickCombo(a,s);t?(de.value={show:!0,x:e.clientX,y:e.clientY,type:"none",target:t},he.value=[{label:"Dissolve",icon:"zap",action:"dissolve-combo"},{label:"Add Selected",icon:"plus",action:"add-to-group"}]):de.value.show=!1}}},ve=e=>{if(ee)if("create-combo"===e){const e=ee.getSelectedNodeIds(),t=`combo-${Date.now()}`;ee.createCombo(t,`Group ${t.split("-")[1]}`,e),D.value++}else if("dissolve-combo"===e)de.value.target&&(ee.removeCombo(de.value.target),D.value--);else if("add-to-group"===e){const e=ee.getSelectedNodeIds();if(de.value.target)for(const t of e)ee.addNodeToCombo(de.value.target,t)}de.value.show=!1},me=e=>{if(!ee)return;s.value=e;const t=new Float32Array(2*e),i=new Float32Array(4*e),a=new Float32Array(e);te=new Float32Array(e);const n=/* @__PURE__ */new Map;for(let s=0;s<e;s++)t[2*s]=50*(Math.random()-.5),t[2*s+1]=50*(Math.random()-.5),i[4*s]=Math.random(),i[4*s+1]=Math.random(),i[4*s+2]=Math.random(),i[4*s+3]=1,a[s]=s,te[s]=.05,n.set(s,{label:`S-${s}`,width:50,height:50});const o=[];for(let s=0;s<5e4;s++)o.push(Math.floor(Math.random()*e)),o.push(Math.floor(Math.random()*e));ie=new Uint32Array(o),ee.setData(t,i,a,n,ie,/* @__PURE__ */new Map),ae&&ae.postMessage({type:"init",data:{nodeCount:e,positions:t,nodeRadii:te,edgeIndices:ie}}),ee.fitToView()},ge=e=>{B.value=e,ae&&ae.postMessage({type:"layout",data:{layoutType:e,nodeRadii:te,edgeIndices:ie}})};return b(()=>{if(window.addEventListener("resize",q),i.value&&a.value){ee=new R(i.value,a.value);const e=t.data.nodes||[],n=t.data.edges||[],o=e.length;s.value=o;const l=new Float32Array(2*o),r=new Float32Array(4*o),c=new Float32Array(o);te=new Float32Array(o);const h=/* @__PURE__ */new Map,v=/* @__PURE__ */new Map,m=e=>{const t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return t?[parseInt(t[1],16)/255,parseInt(t[2],16)/255,parseInt(t[3],16)/255]:[Math.random(),Math.random(),Math.random()]};e.forEach((e,t)=>{const i=e.data,a=e.position||{x:0,y:0};v.set(i.id,t),l[2*t]=((a.x??2500)-2500)/500,l[2*t+1]=((a.y??2500)-2500)/500;const s=i.color||"#000000",n=m(s);r[4*t]=n[0],r[4*t+1]=n[1],r[4*t+2]=n[2],r[4*t+3]=1,c[t]=t;const o=i.width||50,d=i.height||50;te[t]=Math.max(o,d)/1e3;const u={label:i.label||i.code||`Node ${i.id}`,image:i.backgroundImage,width:o,height:d,data:i};if(i.backgroundImage){const e=new Image;e.src=i.backgroundImage,e.onload=()=>{const t=document.createElement("canvas"),i=128;t.width=i,t.height=i;const a=t.getContext("2d");a&&(a.beginPath(),a.arc(64,64,64,0,2*Math.PI),a.clip(),a.filter="grayscale(100%) brightness(1000%)",a.drawImage(e,0,0,i,i),u.processedImageElement=t)},u.imageElement=e}h.set(t,u)}),Y.value=Array.from(h.entries()).map(([e,t])=>({id:e,label:t.label}));const g=[],p=/* @__PURE__ */new Map;n.forEach(e=>{const t=e.data.source,i=e.data.target,a=v.get(t),s=v.get(i);if(void 0!==a&&void 0!==s){g.push(a),g.push(s);const t=`${a}-${s}`;p.set(t,{label:e.data.label,data:e.data})}}),ie=new Uint32Array(g),ee.setData(l,r,c,h,ie,p),ae=new Worker(new URL("/assets/layout.worker-CBxeMMC3.js",import.meta.url),{type:"module"}),ae.postMessage({type:"init",data:{nodeCount:o,positions:l,nodeRadii:te,edgeIndices:ie}}),ae.onmessage=e=>{"layout-complete"===e.data.type&&(e=>{if(!ee)return;const t=s.value,i=new Float32Array(2*t);for(let s=0;s<t;s++){const e=ee.getNodePosition(s);e&&(i[2*s]=e[0],i[2*s+1]=e[1])}const a=performance.now(),n=new Float32Array(2*t),o=s=>{const l=s-a,r=Math.min(l/1e3,1),c=r<.5?4*r**3:1-Math.pow(-2*r+2,3)/2;if(i&&e)for(let a=0;a<2*t;a++)n[a]=i[a]+(e[a]-i[a])*c;ee.updatePositions(n),r<1?requestAnimationFrame(o):ee.fitToView()};requestAnimationFrame(o)})(e.data.positions)},window.addEventListener("mousedown",()=>{de.value.show=!1}),i.value.addEventListener("node-picked",e=>{d.value=e.detail}),i.value.addEventListener("node-selected",e=>{u.value=e.detail,null!==e.detail&&(x.value=null,k.value=null)}),i.value.addEventListener("edge-selected",e=>{x.value=e.detail,null!==e.detail?(u.value=null,k.value=null,P.value=ee.getEdgeMetadata(e.detail)):P.value=null}),i.value.addEventListener("combo-selected",e=>{k.value=e.detail,null!==e.detail&&(u.value=null,x.value=null)}),i.value.addEventListener("nodes-selected",e=>{_.value=e.detail.length}),i.value.addEventListener("node-moved",e=>{e.detail.id===u.value&&(F.value=Number(e.detail.x.toFixed(3)),T.value=Number(e.detail.y.toFixed(3)))})}}),w(()=>{window.removeEventListener("resize",q),ae&&ae.terminate()}),(e,t)=>(n(),o("div",{class:M(["container vortx-gl-root",A.value])},[h("canvas",{ref_key:"canvasRef",ref:i,class:"main-canvas",onContextmenu:c(ue,["prevent"])},null,544),h("canvas",{ref_key:"overlayCanvasRef",ref:a,class:"overlay-canvas"},null,512),U.value?(n(),o("div",Le,[h("button",{class:M(["menu-btn",{active:"layouts"===X.value}]),onClick:t[0]||(t[0]=e=>H("layouts"))},[m(z,{name:"layout",size:"20"}),t[22]||(t[22]=h("span",null,"Layout",-1))],2),h("button",{class:M(["menu-btn",{active:"view"===X.value}]),onClick:t[1]||(t[1]=e=>H("view"))},[m(z,{name:"eye",size:"20"}),t[23]||(t[23]=h("span",null,"View",-1))],2),t[25]||(t[25]=h("div",{class:"menu-divider"},null,-1)),h("button",{class:"menu-btn search-trigger",onClick:G},[m(z,{name:"search",size:"20"}),t[24]||(t[24]=h("span",null,"Search",-1))])])):p("",!0),U.value&&X.value?(n(),o("div",{key:1,class:"drawer-overlay",onClick:t[8]||(t[8]=e=>X.value=null)},[h("div",{class:"mobile-drawer glass shadow-2xl",onClick:t[7]||(t[7]=c(()=>{},["stop"]))},[t[26]||(t[26]=h("div",{class:"drawer-handle"},null,-1)),h("div",Pe,[h("h3",null,g("layouts"===X.value?"Graph Layouts":"View Controls"),1),h("button",{class:"drawer-close",onClick:t[2]||(t[2]=e=>X.value=null)},[m(z,{name:"x",size:"20"})])]),"layouts"===X.value?(n(),o("div",Be,[m(K,{layouts:Q,currentLayout:B.value,flowEnabled:N.value,onRunLayout:$,onToggleFlow:re},null,8,["currentLayout","flowEnabled"])])):p("",!0),"view"===X.value?(n(),o("div",Ne,[m(j,{theme:A.value,onToggleTheme:se,onFit:t[3]||(t[3]=e=>E(ee)?.fitToView()),onZoomIn:t[4]||(t[4]=e=>E(ee)?.zoomIn()),onZoomOut:t[5]||(t[5]=e=>E(ee)?.zoomOut()),onStress:t[6]||(t[6]=e=>me(1e5))},null,8,["theme"])])):p("",!0)])])):p("",!0),y(m(Te,{ref_key:"searchBarRef",ref:Z,nodes:Y.value,onSelect:ce},null,8,["nodes"]),[[I,!U.value||W.value]]),U.value?p("",!0):(n(),v(j,{key:2,theme:A.value,onToggleTheme:se,onFit:t[9]||(t[9]=e=>E(ee)?.fitToView()),onZoomIn:t[10]||(t[10]=e=>E(ee)?.zoomIn()),onZoomOut:t[11]||(t[11]=e=>E(ee)?.zoomOut()),onStress:t[12]||(t[12]=e=>me(1e5))},null,8,["theme"])),U.value?p("",!0):(n(),v(K,{key:3,layouts:Q,currentLayout:B.value,flowEnabled:N.value,onRunLayout:ge,onToggleFlow:re},null,8,["currentLayout","flowEnabled"])),m(O,{show:de.value.show,x:de.value.x,y:de.value.y,type:de.value.type,items:he.value,onAction:ve},null,8,["show","x","y","type","items"]),m(ke,{nodeId:u.value,"onUpdate:nodeId":t[13]||(t[13]=e=>u.value=e),nodeMetadata:L.value,nodeX:F.value,"onUpdate:nodeX":t[14]||(t[14]=e=>F.value=e),nodeY:T.value,"onUpdate:nodeY":t[15]||(t[15]=e=>T.value=e),edgeId:x.value,"onUpdate:edgeId":t[16]||(t[16]=e=>x.value=e),edgeMetadata:P.value,combo:S.value,"onUpdate:combo":t[17]||(t[17]=e=>S.value=e),"onUpdate:comboLabel":oe,onRemoveFromCombo:le},null,8,["nodeId","nodeMetadata","nodeX","nodeY","edgeId","edgeMetadata","combo"]),U.value?p("",!0):(n(),o("div",{key:4,class:"help-trigger glass-interactive",onClick:t[18]||(t[18]=e=>V.value=!0),title:"Keyboard Shortcuts"},[m(z,{name:"info",size:"18"})])),V.value?(n(),o("div",{key:5,class:"help-modal-overlay",onClick:t[21]||(t[21]=e=>V.value=!1)},[h("div",{class:"help-modal glass",onClick:t[20]||(t[20]=c(()=>{},["stop"]))},[h("div",ze,[t[27]||(t[27]=h("h3",null,"Keyboard Shortcuts",-1)),h("button",{class:"close-btn",onClick:t[19]||(t[19]=e=>V.value=!1)},[m(z,{name:"x",size:"20"})])]),h("div",De,[(n(),o(l,null,r(J,e=>h("div",{key:e.key,class:"shortcut-row"},[h("span",Ye,g(e.key),1),h("span",Ve,g(e.action),1)])),64))])])])):p("",!0)],2))}}),[["__scopeId","data-v-d6f5f92c"]]),Oe=(e,t)=>({nodes:e,edges:t});export{Ue as GraphCanvas,R as GraphEngine,Oe as createGraphData};
1
+ import{mat3 as e,vec3 as t,vec2 as s}from"gl-matrix";import{ref as i,onMounted as o,onUnmounted as a,watch as n,computed as r,defineComponent as l,openBlock as d,createElementBlock as c,Fragment as h,renderList as u,withModifiers as g,normalizeStyle as m,createElementVNode as v,renderSlot as f,createBlock as p,createVNode as b,toDisplayString as M,createCommentVNode as w,normalizeClass as y,withDirectives as I,withKeys as x,vModelText as E,shallowRef as A,unref as C,vShow as R,isRef as k}from"vue";class N{gl;constructor(e){this.gl=e}pickNode(e){const t=this.gl,{mouseX:s,mouseY:i,canvas:o,program:a,pickingFramebuffer:n,vao:r,viewMatrix:l,pointSize:d,nodeCount:c}=e;t.bindFramebuffer(t.FRAMEBUFFER,n),t.viewport(0,0,o.width,o.height),t.clearColor(0,0,0,0),t.clear(t.COLOR_BUFFER_BIT),t.useProgram(a),t.uniformMatrix3fv(t.getUniformLocation(a,"u_matrix"),!1,l),t.uniform1f(t.getUniformLocation(a,"u_pointSize"),d),t.uniform1i(t.getUniformLocation(a,"u_pickingMode"),1),t.bindVertexArray(r),t.drawArrays(t.POINTS,0,c);const h=new Uint8Array(4),u=window.devicePixelRatio;if(t.readPixels(Math.floor(s*u),Math.floor(o.height-i*u),1,1,t.RGBA,t.UNSIGNED_BYTE,h),t.bindFramebuffer(t.FRAMEBUFFER,null),0===h[3])return null;return(h[0]<<16|h[1]<<8|h[2])-1}pickEdge(i){const{mouseX:o,mouseY:a,edgeIndices:n,positions:r,nodeCount:l,viewMatrix:d,canvasW:c,canvasH:h}=i;if(!n||!r)return null;const u=window.devicePixelRatio,g=o*u,m=a*u,v=5*u,f=e.invert(e.create(),d);if(!f)return null;const p=t.fromValues(g/c*2-1,-(m/h*2-1),1);t.transformMat3(p,p,f);const b=p[0],M=p[1],w=2*v/Math.abs(d[0]+d[4]);for(let e=0;e<n.length/2;e++){const t=n[2*e],i=n[2*e+1];if(t>=l||i>=l)continue;const o=r[2*t],a=r[2*t+1],u=r[2*i],f=r[2*i+1];if(b<(o<u?o:u)-w||b>(o>u?o:u)+w||M<(a<f?a:f)-w||M>(a>f?a:f)+w)continue;const p=this.project(o,a,d,c,h),y=this.project(u,f,d,c,h);if(this.distToSegment(s.fromValues(g,m),p,y)<v)return`${t}-${i}`}return null}pickCombo(e){const{mouseX:t,mouseY:s,combos:i,positions:o,nodeCount:a,viewMatrix:n,zoom:r,canvasW:l,canvasH:d}=e;if(!o)return null;const c=window.devicePixelRatio,h=t*c,u=s*c;for(const g of i.values()){let e=1/0,t=1/0,s=-1/0,i=-1/0,m=!1;for(const r of g.nodeIds){if(r>=a)continue;const c=this.project(o[2*r],o[2*r+1],n,l,d);e=Math.min(e,c[0]),t=Math.min(t,c[1]),s=Math.max(s,c[0]),i=Math.max(i,c[1]),m=!0}if(m){const o=30*r*c;if(h>=e-o&&h<=s+o&&u>=t-o&&u<=i+o)return g.id}}return null}distToSegment(e,t,i){const o=s.dist(t,i)**2;if(0===o)return s.dist(e,t);let a=((e[0]-t[0])*(i[0]-t[0])+(e[1]-t[1])*(i[1]-t[1]))/o;a=Math.max(0,Math.min(1,a));const n=s.fromValues(t[0]+a*(i[0]-t[0]),t[1]+a*(i[1]-t[1]));return s.dist(e,n)}project(e,i,o,a,n){const r=t.fromValues(e,i,1);return t.transformMat3(r,r,o),s.fromValues((.5*r[0]+.5)*a,(.5*-r[1]+.5)*n)}}class F{canvas;ctx;hudRects=/* @__PURE__ */new Map;projectedCache=new Float32Array(0);constructor(e,t){this.canvas=e,this.ctx=t}_posScratch=t.create();_spScratch=s.create();_s1Scratch=s.create();_s2Scratch=s.create();project(e,s,i,o){return t.set(this._posScratch,e,s,1),t.transformMat3(this._posScratch,this._posScratch,i),o[0]=(.5*this._posScratch[0]+.5)*this.canvas.width,o[1]=(.5*-this._posScratch[1]+.5)*this.canvas.height,o}getThemeColor(e,t){return{dark:{primary:"#00ffcc",secondary:"rgba(0, 255, 204, 0.6)",danger:"#ff6b6b",edge:"rgba(255,255,255,0.15)"},light:{primary:"#00aa88",secondary:"rgba(0, 170, 136, 0.5)",danger:"#d00000",edge:"rgba(0,0,0,0.1)"}}[e][t]}render(s){const{ctx:i,canvas:o}=this,{positions:a,nodeCount:n,hiddenNodes:r,edgeCount:l,edgeIndices:d,metadata:c,edgeMetadata:h,combos:u,theme:g,zoom:m,viewMatrix:v,selectedNodeIds:f,selectedEdgeId:p,selectedComboId:b,hoveredNodeId:M,lockedNodes:w,isBoxSelecting:y,selectionStart:I,selectionEnd:x,phantomEdge:E,edgeIndexToUserIdMap:A}=s;if(!a)return;const C=e.invert(e.create(),v);if(!C)return;const R=t.fromValues(-1.1,1.1,1),k=t.fromValues(1.1,-1.1,1);t.transformMat3(R,R,C),t.transformMat3(k,k,C);const N=Math.min(R[0],k[0]),F=Math.max(R[0],k[0]),_=Math.min(R[1],k[1]),B=Math.max(R[1],k[1]);this.projectedCache.length<2*n&&(this.projectedCache=new Float32Array(2*n));const S=this._s1Scratch,D=.2*(F-N),L=.2*(B-_),T=N-D,P=F+D,U=_-L,z=B+L;for(let e=0;e<n;e++){const t=a[2*e],s=a[2*e+1];r.has(e)||t<T||t>P||s<U||s>z?this.projectedCache[2*e]=NaN:(this.project(t,s,v,S),this.projectedCache[2*e]=S[0],this.projectedCache[2*e+1]=S[1])}i.clearRect(0,0,o.width,o.height);const Y=window.devicePixelRatio,V=40*m*Y;y&&this.drawMarquee(I,x,Y),this.drawCombos(u,a,n,v,m,b,g,Y),this.drawNodeHighlights(f,n,a,v,V,Y),this.drawEdgeHighlight(p,d,a,v,Y),d&&A&&this.drawCustomEdges(d,l,h,A,g,Y),s.flow.enabled&&d&&this.drawFlow(d,l,m,Y,g,s.flow,h,s.selectedNodes),E&&this.drawPhantomEdge(E,a,v,Y),null!==M&&d&&this.drawHoverHighlight(M,d,l,g,Y),m>.1&&d&&A&&this.drawEdgeLabels(d,l,h,A,g,Y,m),m>.1&&this.drawNodeLabels(n,c,a,g,Y,V,m,{vMinX:N,vMaxX:F,vMinY:_,vMaxY:B},w)}drawMarquee(e,t,s){const i=Math.min(e[0],t[0])*s,o=Math.min(e[1],t[1])*s,a=Math.abs(e[0]-t[0])*s,n=Math.abs(e[1]-t[1])*s;this.ctx.strokeStyle="rgba(0, 255, 204, 0.8)",this.ctx.fillStyle="rgba(0, 255, 204, 0.1)",this.ctx.lineWidth=1*s,this.ctx.strokeRect(i,o,a,n),this.ctx.fillRect(i,o,a,n)}drawCombos(e,t,s,i,o,a,n,r){const l=this.ctx,d=this._spScratch;for(const c of e.values()){let e=1/0,h=1/0,u=-1/0,g=-1/0,m=!1;const v=Array.from(c.nodeIds);for(const o of v){if(o>=s)continue;const a=this.project(t[2*o],t[2*o+1],i,d);e=Math.min(e,a[0]),h=Math.min(h,a[1]),u=Math.max(u,a[0]),g=Math.max(g,a[1]),m=!0}if(m){const s=30*r,m=e-s,f=h-s,p=g-h+2*s;if(m+(u-e+2*s)<0||m>this.canvas.width||f+p<0||f>this.canvas.height)continue;const b=a===c.id;if(l.save(),c.collapsed){if(0===v.length)continue;const e=v[0];if(void 0===e)continue;const s=this.project(t[2*e],t[2*e+1],i,d),a=25*o*r;l.beginPath(),l.arc(s[0],s[1],a,0,2*Math.PI),l.fillStyle=b?"rgba(0, 255, 204, 0.4)":"rgba(0, 255, 204, 0.2)",l.strokeStyle="#00ffcc",l.lineWidth=3*r,l.fill(),l.stroke(),l.fillStyle="dark"===n?"#fff":"#000",l.font=`bold ${14*o*r}px Inter, sans-serif`,l.textAlign="center",l.fillText(c.label,s[0],s[1]+a+20*o*r);const h=s[0]-a,u=s[1]-a-35*r;this.drawGroupHUD(l,c,h,u,r)}else{const t=40*o*r,s=e-t,i=h-t,a=u-e+2*t,d=g-h+2*t;l.beginPath();const m=16*o*r;l.moveTo(s+m,i),l.arcTo(s+a,i,s+a,i+d,m),l.arcTo(s+a,i+d,s,i+d,m),l.arcTo(s,i+d,s,i,m),l.arcTo(s,i,s+a,i,m),l.closePath(),l.fillStyle=b?"rgba(0, 255, 204, 0.15)":"dark"===n?"rgba(0, 255, 204, 0.05)":"rgba(0, 170, 136, 0.05)",l.strokeStyle=b?"rgba(0, 255, 204, 0.8)":"dark"===n?"rgba(0, 255, 204, 0.2)":"rgba(0, 170, 136, 0.2)",l.lineWidth=(b?3:2)*o*r,l.setLineDash(b?[]:[5*r,5*r]),l.fill(),l.stroke(),l.setLineDash([]);const v=s,f=i-30*r;this.drawGroupHUD(l,c,v,f,r)}l.restore()}}}drawGroupHUD(e,t,s,i,o){const a=12*o,n=(t.label||"Group").toUpperCase();e.font=`bold ${11*o}px Inter, sans-serif`;const r=2*a+e.measureText(n).width+24*o,l=32*o;e.fillStyle="rgba(18, 18, 22, 0.9)",e.strokeStyle="rgba(255, 255, 255, 0.1)",e.lineWidth=1*o,e.beginPath(),e.roundRect(s-6*o,i-6*o,r,l,[12*o]),e.fill(),e.stroke(),e.beginPath(),e.arc(s+a,i+10*o,a,0,2*Math.PI),e.fillStyle=t.collapsed?"rgba(0, 255, 204, 1)":"rgba(255,255,255,0.1)",e.fill(),t.collapsed||(e.strokeStyle="rgba(0, 255, 204, 0.5)",e.stroke()),e.fillStyle=t.collapsed?"#000":"#00ffcc",e.font=`800 ${14*o}px Inter, sans-serif`,e.textAlign="center",e.textBaseline="middle",e.fillText(t.collapsed?"+":"−",s+a,i+10*o),e.textAlign="left",e.fillStyle="#ffffff",e.font=`bold ${11*o}px Inter, sans-serif`,e.fillText(n,s+2*a+8*o,i+10*o),this.hudRects.set(t.id,{x:s-6*o,y:i-6*o,w:r,h:l})}pickHUDAction(e,t){const s=window.devicePixelRatio,i=e*s,o=t*s;for(const[a,n]of this.hudRects)if(i>=n.x&&i<=n.x+n.w&&o>=n.y&&o<=n.y+n.h)return{comboId:a,action:"expand"};return null}drawNodeHighlights(e,t,s,i,o,a){const n=this.ctx,r=this._spScratch;n.strokeStyle="#00ffcc",n.lineWidth=2*a;for(const l of e)l>=t||(this.project(s[2*l],s[2*l+1],i,r),r[0]<-50||r[0]>this.canvas.width+50||r[1]<-50||r[1]>this.canvas.height+50||(n.beginPath(),n.arc(r[0],r[1],.7*o,0,2*Math.PI),n.stroke()))}drawEdgeHighlight(e,t,s,i,o){if(!e||!t)return;const a=this.ctx,n=e.split("-"),r=Number(n[0]),l=Number(n[1]);if(isNaN(r)||isNaN(l))return;const d=this._s1Scratch,c=this._s2Scratch;this.project(s[2*r],s[2*r+1],i,d),this.project(s[2*l],s[2*l+1],i,c);const h=Math.min(d[0],c[0]),u=Math.max(d[0],c[0]),g=Math.min(d[1],c[1]),m=Math.max(d[1],c[1]);if(u<-20||h>this.canvas.width+20||m<-20||g>this.canvas.height+20)return;const v=this.projectedCache[2*r],f=this.projectedCache[2*r+1],p=this.projectedCache[2*l],b=this.projectedCache[2*l+1];isNaN(v)||isNaN(p)||(a.strokeStyle="#ff00ff",a.lineWidth=3*o,a.beginPath(),a.moveTo(v,f),a.lineTo(p,b),a.stroke())}drawPhantomEdge(e,t,s,i){const o=this.ctx,a=this._s1Scratch,n=this._s2Scratch,r=e.sourceNodeId;this.project(t[2*r],t[2*r+1],s,a),this.project(e.targetPos[0],e.targetPos[1],s,n),o.save(),o.strokeStyle="rgba(0, 255, 204, 0.6)",o.lineWidth=2*i,o.setLineDash([5*i,5*i]),o.beginPath(),o.moveTo(a[0],a[1]),o.lineTo(n[0],n[1]),o.stroke(),o.restore()}drawFlow(e,t,s,i,o,a,n,r){const{velocity:l,size:d,color:c,filterProp:h,filterValue:u}=a,g=this.ctx,m=performance.now()*l,v=Math.max(1,Math.floor(t/4e4)),f=d*Math.min(3,Math.pow(1/s,.25))*i;g.save();const p=a.opacity??1,b=a.pulse?.6+.4*Math.sin(.005*performance.now()):1;g.globalAlpha=p*b,g.globalCompositeOperation="dark"===o?"lighter":"source-over",g.beginPath(),g.fillStyle=c||("dark"===o?"#00ffcc":"#00aa88");for(let M=0;M<t/2;M+=v){const t=e[2*M],s=e[2*M+1];if(a.selectedOnly&&!r.has(t)&&!r.has(s))continue;if(h){const e=`${t}-${s}`,i=n.get(e);if(!i||!i.data||i.data[h]!==u)continue}const i=this.projectedCache[2*t],o=this.projectedCache[2*t+1],l=this.projectedCache[2*s],d=this.projectedCache[2*s+1];if(isNaN(i)||isNaN(l))continue;const c=(m+.1*M%1)%1,v=i+(l-i)*c,p=o+(d-o)*c;g.moveTo(v+f,p),g.arc(v,p,f,0,2*Math.PI)}g.fill(),g.restore()}drawHoverHighlight(e,t,s,i,o){const a=this.ctx;a.lineWidth=2*o,a.strokeStyle=this.getThemeColor(i,"secondary");for(let n=0;n<s/2;n++){const s=t[2*n],i=t[2*n+1];if(s===e||i===e){const e=this.projectedCache[2*s],t=this.projectedCache[2*s+1],o=this.projectedCache[2*i],n=this.projectedCache[2*i+1];if(isNaN(e)||isNaN(o))continue;a.beginPath(),a.moveTo(e,t),a.lineTo(o,n),a.stroke()}}}drawCustomEdges(e,t,s,i,o,a){const n=this.ctx;n.save();for(let r=0;r<t/2;r++){const t=e[2*r],l=e[2*r+1],d=i.get(`${t}-${l}`);if(!d)continue;const c=s.get(d);if(c&&c.data&&(c.data.customColor||c.data.customSize)){const e=this.projectedCache[2*t],s=this.projectedCache[2*t+1],i=this.projectedCache[2*l],r=this.projectedCache[2*l+1];if(isNaN(e)||isNaN(i))continue;n.beginPath(),n.strokeStyle=c.data.customColor||("dark"===o?"rgba(255,255,255,0.4)":"rgba(0,0,0,0.2)"),n.lineWidth=(c.data.customSize||1.5)*a,n.lineCap="round",n.moveTo(e,s),n.lineTo(i,r),n.stroke()}}n.restore()}drawEdgeLabels(e,t,s,i,o,a,n){if(n<.3)return;const r=this.ctx;r.font=`bold ${10*a}px Inter, sans-serif`,r.textAlign="center",r.textBaseline="middle";for(let l=0;l<t/2;l++){const t=e[2*l],n=e[2*l+1],d=i.get(`${t}-${n}`);if(!d)continue;const c=s.get(d);if(c&&c.label){const e=this.projectedCache[2*t],s=this.projectedCache[2*t+1],i=this.projectedCache[2*n],l=this.projectedCache[2*n+1];if(isNaN(e)||isNaN(i))continue;const d=(e+i)/2,h=(s+l)/2;if(d<0||d>this.canvas.width||h<0||h>this.canvas.height)continue;const u=r.measureText(c.label).width;r.fillStyle="dark"===o?"rgba(0,0,0,0.8)":"rgba(255,255,255,0.8)",r.fillRect(d-u/2-4*a,h-8*a,u+8*a,16*a),r.fillStyle="dark"===o?"#fff":"#000",r.fillText(c.label,d,h)}}}drawNodeLabels(e,t,s,i,o,a,n,r,l){const d=this.ctx;d.textAlign="center",d.textBaseline="top";let c=0;const h=60*o,u=/* @__PURE__ */new Set,g=Math.min(1,Math.max(0,15*(n-.02)));if(g<=0)return;d.globalAlpha=g;const m=Array.from({length:e},(e,t)=>t);e<1e4&&m.sort((e,t)=>(l.has(t)?1:0)-(l.has(e)?1:0));for(const v of m){const e=s[2*v],m=s[2*v+1];if(e<r.vMinX||e>r.vMaxX||m<r.vMinY||m>r.vMaxY)continue;const f=t.get(v);if(!f)continue;const p=this.projectedCache[2*v],b=this.projectedCache[2*v+1];if(isNaN(p))continue;if(p<-50||p>this.canvas.width+50||b<-50||b>this.canvas.height+50)continue;const M=.5*a,w=n>.04,y=a>6*o;if(y&&(d.beginPath(),d.arc(p,b,M,0,2*Math.PI),d.strokeStyle="dark"===i?"rgba(255, 255, 255, 0.8)":"rgba(0, 0, 0, 0.8)",d.lineWidth=1*o,d.stroke()),w&&(this.drawNodeIcon(d,f,p,b,a,M,i,o),c++),l.has(v)&&y&&this.drawLockIcon(d,p,b,M,i,o),c>800)break;const I=l.has(v)?.05:.12;if(n<I)continue;const x=`${Math.floor(p/h)},${Math.floor(b/h)}`;if(u.has(x))continue;u.add(x);const E=Math.min(g,Math.max(0,12*(n-I)));if(d.globalAlpha=E,f.label){const e=M+8*o,t=Math.max(8*o,Math.min(13*o,10*n*o*4));d.font=`${t}px Inter, sans-serif`,d.shadowBlur=4*o,d.shadowColor="dark"===i?"rgba(0,0,0,1)":"rgba(255,255,255,1)",d.fillStyle="dark"===i?"rgba(255,255,255,1)":"rgba(0,0,0,1)",d.fillText(f.label,p,b+e),d.shadowBlur=0}}d.globalAlpha=1}drawNodeIcon(e,t,s,i,o,a,n,r){if(t.processedImageElement){const a=.7*o;e.drawImage(t.processedImageElement,s-a/2,i-a/2,a,a)}else if(t.imageElement?.complete){const n=.7*o;e.save(),e.beginPath(),e.arc(s,i,.9*a,0,2*Math.PI),e.clip(),e.filter="grayscale(100%) brightness(1000%)",e.drawImage(t.imageElement,s-n/2,i-n/2,n,n),e.restore()}else if(t.icon){const a=Math.max(12*r,.6*o);e.font=`${a}px serif`,e.fillStyle="dark"===n?"white":"black",e.fillText(t.icon,s,i-.2*o)}}drawLockIcon(e,t,s,i,o,a){const n=Math.max(8*a,Math.min(12*a,.4*i));e.font=`${n}px serif`,e.fillStyle="dark"===o?"#ff6b6b":"#d00000",e.shadowBlur=2*a,e.shadowColor="rgba(0,0,0,0.5)",e.fillText("🔒",t+.7*i,s-.7*i)}}class _{lastMouse=s.create();isPanning=!1;engine;canvas;lastTouchDistance=0;lastTouchMidpoint=s.create();isTouching=!1;touchStartTime=0;touchStartPos=s.create();longPressTimer=null;isLongPress=!1;isDraggingCombo=!1;constructor(e,t){this.engine=e,this.canvas=t,this.setupListeners()}setupListeners(){this.canvas.addEventListener("mousedown",e=>this.handleMouseDown(e)),window.addEventListener("mousemove",e=>this.handleMouseMove(e)),window.addEventListener("mouseup",()=>this.handleMouseUp()),this.canvas.addEventListener("wheel",e=>this.handleWheel(e),{passive:!1}),this.canvas.addEventListener("touchstart",e=>this.handleTouchStart(e),{passive:!1}),this.canvas.addEventListener("touchmove",e=>this.handleTouchMove(e),{passive:!1}),this.canvas.addEventListener("touchend",e=>this.handleTouchEnd(e)),this.canvas.addEventListener("touchcancel",e=>this.handleTouchEnd(e))}handleMouseDown(e){const t=this.canvas.getBoundingClientRect(),i=e.clientX-t.left,o=e.clientY-t.top,a=this.engine.getState(),n=this.engine.pickHUD(i,o);if(n)return void("expand"===n.action&&n.comboId&&this.engine.toggleComboCollapse(n.comboId));if(e.shiftKey)return this.engine.updateInteractionState({isBoxSelecting:!0,selectionStart:s.fromValues(i,o),selectionEnd:s.fromValues(i,o)}),void this.engine.render();const r=this.engine.pick(i,o);if(null!==r){const t=a.selectedNodeIds.has(r);e.ctrlKey||e.metaKey||t||a.selectedNodeIds.clear(),a.selectedNodeIds.add(r),this.engine.updateInteractionState({isMultiDragging:!0,draggedNodeId:null}),this.engine.syncDragOffsets(i,o),this.engine.emitEvent("node:mousedown",{id:this.engine.getNodeId(r)??r,index:r}),this.engine.emitEvent("node:click",{id:this.engine.getNodeId(r)??r,index:r}),this.engine.emitEvent("nodes:select",{ids:Array.from(a.selectedNodeIds).map(e=>this.engine.getNodeId(e)??e),indices:Array.from(a.selectedNodeIds)}),this.canvas.dispatchEvent(new CustomEvent("nodes-selected",{detail:Array.from(a.selectedNodeIds)})),this.canvas.dispatchEvent(new CustomEvent("node-selected",{detail:r}))}else{a.selectedNodeIds.clear();const e=this.engine.getEdgeAt(i,o),t=this.engine.pickCombo(i,o);this.engine.updateInteractionState({selectedEdgeId:e,selectedComboId:t}),e&&(this.engine.emitEvent("edge:mousedown",{id:e}),this.engine.emitEvent("edge:click",{id:e}),this.engine.emitEvent("edge:select",{id:e}),this.canvas.dispatchEvent(new CustomEvent("edge-selected",{detail:e}))),t&&(this.isDraggingCombo=!0,this.engine.emitEvent("combo:mousedown",{id:t}),this.engine.emitEvent("combo:click",{id:t}),this.engine.emitEvent("combo:select",{id:t}),this.canvas.dispatchEvent(new CustomEvent("combo-selected",{detail:t}))),e||t||(this.isPanning=!0,this.engine.emitEvent("graph:click",{x:i,y:o}),this.engine.emitEvent("graph:mousedown",{x:i,y:o}),this.canvas.dispatchEvent(new CustomEvent("graph:click",{detail:{x:i,y:o}})))}s.set(this.lastMouse,i,o),this.engine.render()}handleMouseMove(e){const t=this.canvas.getBoundingClientRect(),i=e.clientX-t.left,o=e.clientY-t.top,a=this.engine.getState();if(a.isBoxSelecting)return this.engine.updateInteractionState({selectionEnd:s.fromValues(i,o)}),void this.engine.render();if(a.isMultiDragging||null!==a.draggedNodeId)this.engine.handleDragging(i,o);else{if(this.isDraggingCombo&&a.selectedComboId){const e=window.devicePixelRatio,t=this.engine.unproject(i*e,o*e),n=this.engine.unproject(this.lastMouse[0]*e,this.lastMouse[1]*e),r=t[0]-n[0],l=t[1]-n[1];return this.engine.moveGroup(a.selectedComboId,r,l),void s.set(this.lastMouse,i,o)}if(this.isPanning){const e=window.devicePixelRatio,t=(i-this.lastMouse[0])*e/(this.canvas.width/2),a=-(o-this.lastMouse[1])*e/(this.canvas.height/2);this.engine.pan(t,a),s.set(this.lastMouse,i,o)}else{const e=a.hoveredNodeId,t=this.engine.pick(i,o);if(t!==e&&(this.engine.updateInteractionState({hoveredNodeId:t}),this.engine.render(),null!==t?this.engine.emitEvent("node:hover",{id:this.engine.getNodeId(t)??t,index:t}):this.engine.emitEvent("node:hoverout",{prevIndex:e})),null===t){const e=this.engine.getEdgeAt(i,o),t=this.engine.pickCombo(i,o);e&&this.engine.emitEvent("edge:hover",{id:e}),t&&this.engine.emitEvent("combo:hover",{id:t})}}}}handleMouseUp(){const e=this.engine.getState();this.isPanning&&this.engine.emitEvent("graph:mouseup"),this.isPanning=!1,this.isDraggingCombo=!1,e.isBoxSelecting&&(this.engine.performBoxSelection(),this.engine.emitEvent("boxselect",{indices:Array.from(e.selectedNodeIds),ids:Array.from(e.selectedNodeIds).map(e=>this.engine.getNodeId(e)??e)}),this.engine.emitEvent("boxend")),this.engine.updateInteractionState({isBoxSelecting:!1,isMultiDragging:!1,draggedNodeId:null}),this.engine.render()}handleWheel(e){e.preventDefault();const t=this.canvas.getBoundingClientRect(),s=e.clientX-t.left,i=e.clientY-t.top,o=.001*-e.deltaY;this.engine.zoomAt(s,i,o)}handleTouchStart(e){if(e.preventDefault(),this.isTouching=!0,this.touchStartTime=Date.now(),this.isLongPress=!1,1===e.touches.length){const t=e.touches[0],i=this.canvas.getBoundingClientRect(),o=t.clientX-i.left,a=t.clientY-i.top;s.set(this.touchStartPos,o,a),s.set(this.lastMouse,o,a),this.longPressTimer=window.setTimeout(()=>{this.isLongPress=!0,this.triggerContextMenu(t.clientX,t.clientY)},500);const n=this.engine.pick(o,a),r=this.engine.getState();null!==n&&(r.selectedNodeIds.has(n)||(r.selectedNodeIds.clear(),r.selectedNodeIds.add(n)),this.engine.updateInteractionState({isMultiDragging:!0,draggedNodeId:null}),this.engine.syncDragOffsets(o,a),this.canvas.dispatchEvent(new CustomEvent("node-selected",{detail:n})))}else if(2===e.touches.length){this.clearLongPress();const t=e.touches[0],i=e.touches[1];this.lastTouchDistance=s.distance(s.fromValues(t.clientX,t.clientY),s.fromValues(i.clientX,i.clientY)),s.set(this.lastTouchMidpoint,(t.clientX+i.clientX)/2,(t.clientY+i.clientY)/2)}}handleTouchMove(e){if(e.preventDefault(),this.isTouching){if(1===e.touches.length){const t=e.touches[0],i=this.canvas.getBoundingClientRect(),o=t.clientX-i.left,a=t.clientY-i.top;if(s.distance(this.touchStartPos,s.fromValues(o,a))>10&&this.clearLongPress(),this.isLongPress)return;if(this.engine.getState().isMultiDragging)this.engine.handleDragging(o,a);else{const e=window.devicePixelRatio,t=(o-this.lastMouse[0])*e/(this.canvas.width/2),s=-(a-this.lastMouse[1])*e/(this.canvas.height/2);this.engine.pan(t,s)}s.set(this.lastMouse,o,a)}else if(2===e.touches.length){this.clearLongPress();const t=e.touches[0],i=e.touches[1],o=s.distance(s.fromValues(t.clientX,t.clientY),s.fromValues(i.clientX,i.clientY)),a=s.fromValues((t.clientX+i.clientX)/2,(t.clientY+i.clientY)/2),n=o/this.lastTouchDistance,r=this.canvas.getBoundingClientRect(),l=a[0]-r.left,d=a[1]-r.top;this.engine.zoomAt(l,d,n-1);const c=window.devicePixelRatio,h=(a[0]-this.lastTouchMidpoint[0])*c/(this.canvas.width/2),u=-(a[1]-this.lastTouchMidpoint[1])*c/(this.canvas.height/2);this.engine.pan(h,u),this.lastTouchDistance=o,s.copy(this.lastTouchMidpoint,a)}this.engine.render()}}handleTouchEnd(e){if(this.isTouching=!1,this.clearLongPress(),0===e.touches.length&&!this.isLongPress){const t=Date.now()-this.touchStartTime,i=e.changedTouches[0],o=this.canvas.getBoundingClientRect(),a=i.clientX-o.left,n=i.clientY-o.top,r=s.distance(this.touchStartPos,s.fromValues(a,n));if(t<250&&r<10){const e=this.engine.pick(a,n);this.engine.selectNode(e)}}this.engine.updateInteractionState({isMultiDragging:!1}),this.engine.render()}clearLongPress(){null!==this.longPressTimer&&(window.clearTimeout(this.longPressTimer),this.longPressTimer=null)}triggerContextMenu(e,t){const s=new MouseEvent("contextmenu",{clientX:e,clientY:t,bubbles:!0,cancelable:!0});this.canvas.dispatchEvent(s)}}class B{listeners=/* @__PURE__ */new Map;on(e,t){return this.listeners.has(e)||this.listeners.set(e,/* @__PURE__ */new Set),this.listeners.get(e).add(t),()=>this.off(e,t)}off(e,t){this.listeners.get(e)?.delete(t)}emit(e,t){this.listeners.get(e)?.forEach(e=>{try{e(t)}catch(s){}})}removeAllListeners(e){e?this.listeners.delete(e):this.listeners.clear()}}class S{gl;pickingEngine;overlayManager;emitter=new B;program=null;edgeProgram=null;viewMatrix=e.create();vao=null;edgeVao=null;positionBuffer=null;colorBuffer=null;idBuffer=null;edgeIndexBuffer=null;pickingFramebuffer=null;pickingTexture=null;uMatrixLoc=null;uPointSizeLoc=null;uPickingModeLoc=null;uEdgeMatrixLoc=null;uEdgeColorLoc=null;nodeCount=0;edgeCount=0;positions=null;metadata=/* @__PURE__ */new Map;edgeIndices=null;edgeMetadata=/* @__PURE__ */new Map;combos=/* @__PURE__ */new Map;theme="dark";static MAX_ZOOM=100;static MIN_ZOOM=1e-4;colorData=new Float32Array(0);idData=new Float32Array(0);capacity=0;autoNodeId=0;autoEdgeId=0;nodeIdMap=/* @__PURE__ */new Map;reverseIdMap=/* @__PURE__ */new Map;edgeList=[];edgeIdMap=/* @__PURE__ */new Map;edgeIndexToUserIdMap=/* @__PURE__ */new Map;stylesheet={};lockedNodes=/* @__PURE__ */new Set;hiddenNodes=/* @__PURE__ */new Set;hiddenEdges=/* @__PURE__ */new Set;state={zoom:1,offset:s.fromValues(0,0),selectedNodeIds:/* @__PURE__ */new Set,selectedEdgeId:null,selectedComboId:null,hoveredNodeId:null,isBoxSelecting:!1,selectionStart:s.create(),selectionEnd:s.create(),isMultiDragging:!1,draggedNodeId:null,flow:{enabled:!1,velocity:.002,size:1.5,opacity:1,pulse:!1},phantomEdge:null};dragOffsets=/* @__PURE__ */new Map;canvas;overlayCanvas;setPhantomEdge(e,t,i){this.state.phantomEdge={sourceNodeId:e,targetPos:s.fromValues(t,i)},this.render()}clearPhantomEdge(){this.state.phantomEdge=null,this.render()}constructor(e,t){this.canvas=e,this.overlayCanvas=t;const s=e.getContext("webgl2",{antialias:!0,stencil:!0});if(!s)throw new Error("WebGL2 not supported");this.gl=s,s.enable(s.BLEND),s.blendFunc(s.SRC_ALPHA,s.ONE_MINUS_SRC_ALPHA);const i=t.getContext("2d");if(!i)throw new Error("Canvas 2D not supported");this.pickingEngine=new N(s),this.overlayManager=new F(t,i),this.initShaders(),this.initBuffers(),this.initPicking(),this.updateMatrix(),new _(this,e),this.handleResize(),window.addEventListener("resize",()=>this.handleResize())}on(e,t){return this.emitter.on(e,t)}off(e,t){this.emitter.off(e,t)}emitEvent(e,t){this.emitter.emit(e,t)}setStylesheet(e){this.stylesheet=e,this.render()}resolveStyle(e){if(!e||0===e.length)return{};const t={};for(const s of e){const e=this.stylesheet[s];e&&Object.assign(t,e)}return t}addNode(e){const t=e.id??"vortx-node-"+this.autoNodeId++;if(this.nodeIdMap.has(t))throw new Error(`[VortxGL] Node '${t}' already exists. Use a unique ID.`);const s=this.nodeCount;this.ensureNodeCapacity(s+1);const i=this.resolveStyle(e.classes),o=e.position?.x??0,a=e.position?.y??0;this.positions[2*s]=o,this.positions[2*s+1]=a;const n=e.color||i.color,[r,l,d,c]=this.parseColor(n);this.colorData[4*s]=r,this.colorData[4*s+1]=l,this.colorData[4*s+2]=d,this.colorData[4*s+3]=c,this.idData[s]=s,this.nodeIdMap.set(t,s),this.reverseIdMap.set(s,t);const h={label:e.label||i.label,icon:e.icon||i.icon,image:e.image||i.image,data:e.data,classes:e.classes,width:e.size||i.size||50,height:e.size||i.size||50};this.metadata.set(s,h),e.image&&this.loadNodeImage(s,e.image),this.nodeCount++;const u=this.gl;return u.bindBuffer(u.ARRAY_BUFFER,this.positionBuffer),u.bufferSubData(u.ARRAY_BUFFER,8*s,this.positions.subarray(2*s,2*s+2)),u.bindBuffer(u.ARRAY_BUFFER,this.colorBuffer),u.bufferSubData(u.ARRAY_BUFFER,16*s,this.colorData.subarray(4*s,4*s+4)),u.bindBuffer(u.ARRAY_BUFFER,this.idBuffer),u.bufferSubData(u.ARRAY_BUFFER,4*s,this.idData.subarray(s,s+1)),this.emitter.emit("node:add",{id:t,index:s,position:{x:o,y:a}}),this.render(),t}updateNode(e){if(void 0===e.id)throw new Error("[VortxGL] Must provide node ID for update.");const t=this.nodeIdMap.get(e.id);if(void 0===t)throw new Error(`[VortxGL] Node '${e.id}' not found for update.`);const s=this.resolveStyle(e.classes||this.metadata.get(t)?.classes);e.position&&(this.positions[2*t]=e.position.x,this.positions[2*t+1]=e.position.y);const i=e.color||(e.classes?s.color:void 0);if(i){const[e,s,o,a]=this.parseColor(i);this.colorData[4*t]=e,this.colorData[4*t+1]=s,this.colorData[4*t+2]=o,this.colorData[4*t+3]=a}const o=this.metadata.get(t);if(o){e.classes&&(o.classes=e.classes),(void 0!==e.label||s.label)&&(o.label=e.label||s.label),(void 0!==e.icon||s.icon)&&(o.icon=e.icon||s.icon),(void 0!==e.image||s.image)&&(o.image=e.image||s.image,o.image&&this.loadNodeImage(t,o.image)),void 0!==e.data&&(o.data=e.data);const i=e.size||(e.classes?s.size:void 0);void 0!==i&&(o.width=i,o.height=i)}const a=this.gl;e.position&&(a.bindBuffer(a.ARRAY_BUFFER,this.positionBuffer),a.bufferSubData(a.ARRAY_BUFFER,8*t,this.positions.subarray(2*t,2*t+2))),e.color&&(a.bindBuffer(a.ARRAY_BUFFER,this.colorBuffer),a.bufferSubData(a.ARRAY_BUFFER,16*t,this.colorData.subarray(4*t,4*t+4))),this.emitter.emit("node:update",{id:e.id,index:t}),this.render()}removeNode(e){const t=this.nodeIdMap.get(e);if(void 0===t)return;const s=this.edgeList.filter(e=>e.u===t||e.v===t).map(e=>e.id);for(const o of s)this._removeEdgeInternal(o);const i=this.nodeCount-1;if(t!==i){this.positions[2*t]=this.positions[2*i],this.positions[2*t+1]=this.positions[2*i+1],this.colorData[4*t]=this.colorData[4*i],this.colorData[4*t+1]=this.colorData[4*i+1],this.colorData[4*t+2]=this.colorData[4*i+2],this.colorData[4*t+3]=this.colorData[4*i+3],this.idData[t]=t;const e=this.metadata.get(i);e&&this.metadata.set(t,e),this.metadata.delete(i);const s=this.reverseIdMap.get(i);this.nodeIdMap.set(s,t),this.reverseIdMap.set(t,s);for(const a of this.edgeList)a.u===i&&(a.u=t),a.v===i&&(a.v=t);this.rebuildEdgeIndexToUserIdMap(),this.lockedNodes.has(i)&&(this.lockedNodes.delete(i),this.lockedNodes.add(t)),this.hiddenNodes.has(i)&&(this.hiddenNodes.delete(i),this.hiddenNodes.add(t)),this.state.selectedNodeIds.has(i)&&(this.state.selectedNodeIds.delete(i),this.state.selectedNodeIds.add(t)),this.state.hoveredNodeId===i&&(this.state.hoveredNodeId=t);const o=this.gl;o.bindBuffer(o.ARRAY_BUFFER,this.positionBuffer),o.bufferSubData(o.ARRAY_BUFFER,8*t,this.positions.subarray(2*t,2*t+2)),o.bindBuffer(o.ARRAY_BUFFER,this.colorBuffer),o.bufferSubData(o.ARRAY_BUFFER,16*t,this.colorData.subarray(4*t,4*t+4)),o.bindBuffer(o.ARRAY_BUFFER,this.idBuffer),o.bufferSubData(o.ARRAY_BUFFER,4*t,this.idData.subarray(t,t+1))}else this.metadata.delete(i);this.nodeIdMap.delete(e),this.reverseIdMap.delete(i),this.lockedNodes.delete(i),this.hiddenNodes.delete(i),this.state.selectedNodeIds.delete(i),this.nodeCount--,this.rebuildEdgeBuffer(),this.emitter.emit("node:remove",{id:e}),this.render()}addEdge(e){const t=this.nodeIdMap.get(e.source),s=this.nodeIdMap.get(e.target);if(void 0===t)throw new Error(`[VortxGL] Source node '${e.source}' not found.`);if(void 0===s)throw new Error(`[VortxGL] Target node '${e.target}' not found.`);const i=e.id??"vortx-edge-"+this.autoEdgeId++;if(this.edgeIdMap.has(i))throw new Error(`[VortxGL] Edge '${i}' already exists.`);const o=this.resolveStyle(e.classes),a={label:e.label||o.label,data:e.data,classes:e.classes};return this.edgeList.push({id:i,u:t,v:s,metadata:a}),this.edgeIdMap.set(i,this.edgeList.length-1),this.edgeMetadata.set(i,a),this.edgeIndexToUserIdMap.set(`${t}-${s}`,i),this.edgeIndexToUserIdMap.set(`${s}-${t}`,i),this.rebuildEdgeBuffer(),this.emitter.emit("edge:add",{id:i,source:e.source,target:e.target}),this.render(),i}updateEdge(e){if(!e.id)throw new Error("[VortxGL] Must provide edge ID for update.");const t=this.edgeIdMap.get(e.id);if(void 0===t)throw new Error(`[VortxGL] Edge '${e.id}' not found.`);const s=this.edgeList[t];void 0!==e.label&&(s.metadata.label=e.label),void 0!==e.data&&(s.metadata.data=e.data),this.emitter.emit("edge:update",{id:e.id}),this.render()}removeEdge(e){this._removeEdgeInternal(e),this.rebuildEdgeBuffer(),this.emitter.emit("edge:remove",{id:e}),this.render()}clear(){this.nodeCount=0,this.edgeCount=0,this.edgeList=[],this.edgeIdMap.clear(),this.edgeIndexToUserIdMap.clear(),this.nodeIdMap.clear(),this.reverseIdMap.clear(),this.metadata.clear(),this.edgeMetadata.clear(),this.edgeIndices=null,this.combos.clear(),this.lockedNodes.clear(),this.hiddenNodes.clear(),this.hiddenEdges.clear(),this.state.selectedNodeIds.clear(),this.state.selectedEdgeId=null,this.state.hoveredNodeId=null,this.emitter.emit("graph:clear",{}),this.render()}getAllNodes(){const e=[];for(const[t,s]of this.nodeIdMap){const i=this.metadata.get(s);e.push({id:t,_index:s,position:{x:this.positions?this.positions[2*s]:0,y:this.positions?this.positions[2*s+1]:0},label:i?.label,icon:i?.icon,image:i?.image,data:i?.data,size:i?.width})}return e}getAllEdges(){return this.edgeList.map(e=>({id:e.id,source:this.reverseIdMap.get(e.u)??e.u,target:this.reverseIdMap.get(e.v)??e.v,label:e.metadata.label,data:e.metadata.data}))}getNodesByClass(e){return this.getAllNodes().filter(t=>{const s=this.metadata.get(t._index);return s?.classes?.includes(e)})}getEdgesByClass(e){return this.getAllEdges().filter(t=>{const s=this.edgeMetadata.get(t.id);return s?.classes?.includes(e)})}getNode(e){const t=this.resolveNodeIndex(e);if(null===t)return null;const s=this.metadata.get(t);return{id:e,_index:t,position:{x:this.positions[2*t],y:this.positions[2*t+1]},label:s?.label,icon:s?.icon,data:s?.data,classes:s?.classes}}getInternalIndex(e){return this.nodeIdMap.get(e)??null}getNodeId(e){return this.reverseIdMap.get(e)??null}getNodeMetadata(e){const t=this.resolveNodeIndex(e);return null===t?null:this.metadata.get(t)??null}getEdgeMetadata(e){return this.edgeMetadata.get(e)??null}lockNode(e){const t=this.resolveNodeIndex(e);null!==t&&(this.lockedNodes.add(t),this.render())}unlockNode(e){const t=this.resolveNodeIndex(e);null!==t&&(this.lockedNodes.delete(t),this.render())}isNodeLocked(e){return this.lockedNodes.has(e)}hideNode(e){const t=this.resolveNodeIndex(e);if(null===t)return;this.hiddenNodes.add(t),this.colorData[4*t+3]=0;const s=this.gl;s.bindBuffer(s.ARRAY_BUFFER,this.colorBuffer),s.bufferSubData(s.ARRAY_BUFFER,16*t+12,this.colorData.subarray(4*t+3,4*t+4)),this.render()}showNode(e){const t=this.resolveNodeIndex(e);if(null===t)return;this.hiddenNodes.delete(t),this.colorData[4*t+3]=1;const s=this.gl;s.bindBuffer(s.ARRAY_BUFFER,this.colorBuffer),s.bufferSubData(s.ARRAY_BUFFER,16*t+12,this.colorData.subarray(4*t+3,4*t+4)),this.render()}isNodeHidden(e){return this.hiddenNodes.has(e)}setNodeColor(e,t,s,i,o=1){const a=this.resolveNodeIndex(e);if(null===a)return;this.colorData[4*a]=t,this.colorData[4*a+1]=s,this.colorData[4*a+2]=i,this.hiddenNodes.has(a)||(this.colorData[4*a+3]=o);const n=this.gl;n.bindBuffer(n.ARRAY_BUFFER,this.colorBuffer),n.bufferSubData(n.ARRAY_BUFFER,16*a,this.colorData.subarray(4*a,4*a+4)),this.render()}setNodeLabel(e,t){const s=this.resolveNodeIndex(e);if(null===s)return;let i=this.metadata.get(s);i?i.label=t:(i={label:t,width:50,height:50},this.metadata.set(s,i)),this.render()}setNodeData(e,t){const s=this.resolveNodeIndex(e);if(null===s)return;let i=this.metadata.get(s);i?i.data={...i.data||{},...t}:(i={data:t,width:50,height:50},this.metadata.set(s,i))}hideEdge(e){this.hiddenEdges.add(e),this.rebuildEdgeBuffer(),this.render()}showEdge(e){this.hiddenEdges.delete(e),this.rebuildEdgeBuffer(),this.render()}reverseEdge(e){const t=this.edgeMetadata.get(e),s=e.split("-");if(s.length<2)return;const i=this.resolveNodeIndex(s[0]),o=this.resolveNodeIndex(s[1]);if(null!==i&&null!==o&&this.edgeIndices){for(let e=0;e<this.edgeIndices.length;e+=2)if(this.edgeIndices[e]===i&&this.edgeIndices[e+1]===o){this.edgeIndices[e]=o,this.edgeIndices[e+1]=i;break}t&&(this.edgeMetadata.delete(e),this.edgeMetadata.set(`${s[1]}-${s[0]}`,t)),this.render()}}setEdgeLabel(e,t){const s=this.edgeMetadata.get(e);s&&(s.label=t,this.render())}setEdgeData(e,t){const s=this.edgeMetadata.get(e);s&&(s.data={...s.data,...t})}deselectAll(){this.state.selectedNodeIds.clear(),this.state.selectedEdgeId=null,this.state.selectedComboId=null,this.canvas.dispatchEvent(new CustomEvent("node-selected",{detail:null})),this.canvas.dispatchEvent(new CustomEvent("nodes-selected",{detail:[]})),this.emitter.emit("nodes:select",{ids:[],indices:[]}),this.render()}setData(e,t,s,i,o,a,n){if(this.positions=e,this.nodeCount=s.length,this.metadata=i,this.capacity=s.length,this.colorData=new Float32Array(t),this.idData=new Float32Array(s),this.nodeIdMap.clear(),this.reverseIdMap.clear(),n){this.nodeIdMap=new Map(n);for(const[e,t]of n)this.reverseIdMap.set(t,e)}else for(let l=0;l<this.nodeCount;l++)this.nodeIdMap.set(l,l),this.reverseIdMap.set(l,l);const r=this.gl;if(r.bindBuffer(r.ARRAY_BUFFER,this.positionBuffer),r.bufferData(r.ARRAY_BUFFER,e,r.DYNAMIC_DRAW),r.bindBuffer(r.ARRAY_BUFFER,this.colorBuffer),r.bufferData(r.ARRAY_BUFFER,t,r.DYNAMIC_DRAW),r.bindBuffer(r.ARRAY_BUFFER,this.idBuffer),r.bufferData(r.ARRAY_BUFFER,s,r.DYNAMIC_DRAW),o){this.edgeIndices=o,this.edgeCount=o.length,this.edgeList=[],this.edgeIdMap.clear(),this.edgeIndexToUserIdMap.clear();for(let e=0;e<o.length/2;e++){const t=o[2*e],s=o[2*e+1],i=`${t}-${s}`,n=a?.get(i)??{};this.edgeList.push({id:i,u:t,v:s,metadata:n}),this.edgeIdMap.set(i,e),this.edgeIndexToUserIdMap.set(`${t}-${s}`,i),this.edgeIndexToUserIdMap.set(`${s}-${t}`,i)}r.bindVertexArray(this.edgeVao),r.bindBuffer(r.ELEMENT_ARRAY_BUFFER,this.edgeIndexBuffer),r.bufferData(r.ELEMENT_ARRAY_BUFFER,o,r.DYNAMIC_DRAW),r.bindVertexArray(null)}a&&(this.edgeMetadata=a),this.render()}updatePositions(e){this.positions=e;for(const s of this.combos.values())if(s.collapsed){const t=s.representativeId??Array.from(s.nodeIds)[0];if(void 0===t||!this.positions)continue;const i=this.positions[2*t],o=this.positions[2*t+1];let a=0,n=0,r=0;for(const l of s.nodeIds)l<this.nodeCount&&(a+=e[2*l],n+=e[2*l+1],r++);if(r>0){a/=r,n/=r,s.originalPositions||(s.originalPositions=/* @__PURE__ */new Map);for(const t of s.nodeIds)if(t<this.nodeCount){const r=e[2*t]-a,l=e[2*t+1]-n;s.originalPositions.set(t,{x:i+r,y:o+l}),e[2*t]=i,e[2*t+1]=o}}}const t=this.gl;t.bindBuffer(t.ARRAY_BUFFER,this.positionBuffer),t.bufferSubData(t.ARRAY_BUFFER,0,e),this.render()}setNodePosition(e,t,s){if(!this.positions||e>=this.nodeCount)return;this.positions[2*e]=t,this.positions[2*e+1]=s;const i=this.gl;i.bindBuffer(i.ARRAY_BUFFER,this.positionBuffer),i.bufferSubData(i.ARRAY_BUFFER,2*e*4,this.positions.subarray(2*e,2*e+2)),this.render()}getNodePosition(e){return!this.positions||e>=this.nodeCount?null:s.fromValues(this.positions[2*e],this.positions[2*e+1])}setFlowAnimation(e){if(this.state.flow.enabled=e,e){const e=()=>{this.state.flow.enabled&&(this.render(),requestAnimationFrame(e))};requestAnimationFrame(e)}else this.render()}setTheme(e){this.theme=e,this.render()}setFlowVelocity(e){this.state.flow.velocity=e,this.render()}setFlowSize(e){this.state.flow.size=e,this.render()}setFlowColor(e){this.state.flow.color=e,this.render()}setFlowFilter(e,t=null){this.state.flow.filterProp=e,this.state.flow.filterValue=t,this.render()}createGroup(e,t,s){const i=/* @__PURE__ */new Set;for(const o of s){const e=this.resolveNodeIndex(o);null!==e&&i.add(e)}this.combos.set(e,{id:e,label:t,nodeIds:i}),this.emitter.emit("combo:add",{id:e,label:t,nodeIds:s}),this.render()}removeGroup(e){this.combos.delete(e)&&(this.emitter.emit("combo:remove",{id:e}),this.render())}addToGroup(e,t){const s=this.combos.get(e),i=this.resolveNodeIndex(t);s&&null!==i&&(s.nodeIds.add(i),this.emitter.emit("combo:update",{id:e,nodeId:t,action:"add"}),this.render())}removeFromGroup(e,t){const s=this.combos.get(e),i=this.resolveNodeIndex(t);s&&null!==i&&(s.nodeIds.delete(i),this.emitter.emit("combo:update",{id:e,nodeId:t,action:"remove"}),this.render())}toggleComboCollapse(e){const t=this.combos.get(e);if(!t||0===t.nodeIds.size)return;if(t.collapsed=!t.collapsed,t.collapsed){let e=0,s=0;t.nodeIds.forEach(t=>{e+=this.positions[2*t],s+=this.positions[2*t+1]}),e/=t.nodeIds.size,s/=t.nodeIds.size,t.originalPositions=/* @__PURE__ */new Map;const i=Array.from(t.nodeIds);t.representativeId=i[0];for(const o of i)t.originalPositions.set(o,{x:this.positions[2*o],y:this.positions[2*o+1]}),this.positions[2*o]=e,this.positions[2*o+1]=s,o!==t.representativeId?(this.hiddenNodes.add(o),this.colorData[4*o+3]=0):(this.hiddenNodes.delete(o),this.colorData[4*o+3]=1);for(const o of this.edgeList)t.nodeIds.has(o.u)&&t.nodeIds.has(o.v)&&this.hiddenEdges.add(o.id)}else{if(t.originalPositions)for(const[e,s]of t.originalPositions)this.positions[2*e]=s.x,this.positions[2*e+1]=s.y,this.hiddenNodes.delete(e),this.colorData[4*e+3]=1;for(const e of this.edgeList)t.nodeIds.has(e.u)&&t.nodeIds.has(e.v)&&this.hiddenEdges.delete(e.id);t.originalPositions=void 0,t.representativeId=void 0}const s=this.gl;s.bindBuffer(s.ARRAY_BUFFER,this.positionBuffer),s.bufferData(s.ARRAY_BUFFER,this.positions,s.DYNAMIC_DRAW),s.bindBuffer(s.ARRAY_BUFFER,this.colorBuffer),s.bufferData(s.ARRAY_BUFFER,this.colorData,s.DYNAMIC_DRAW),this.rebuildEdgeBuffer(),this.emitter.emit("combo:update",{id:e,action:"collapse",state:t.collapsed}),this.render()}moveGroup(e,t,s,i=!1){const o=this.combos.get(e);if(o){for(const e of o.nodeIds)if(this.positions&&!(e>=this.nodeCount)&&(this.positions[2*e]+=t,this.positions[2*e+1]+=s,o.collapsed&&o.originalPositions)){const i=o.originalPositions.get(e);i&&(i.x+=t,i.y+=s)}if(!i){const e=this.gl;e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.bufferData(e.ARRAY_BUFFER,this.positions,e.DYNAMIC_DRAW),this.render()}}}getAllGroups(){return Array.from(this.combos.values()).map(e=>({id:e.id,label:e.label,nodeIds:Array.from(e.nodeIds).map(e=>this.reverseIdMap.get(e)??e)}))}createCombo(e,t,s){this.createGroup(e,t,s)}removeCombo(e){this.removeGroup(e)}updateCombo(e,t,s){this.createGroup(e,t,s)}getCombo(e){return this.combos.get(e)}addNodeToCombo(e,t){this.addToGroup(e,t)}removeNodeFromCombo(e,t){this.removeFromGroup(e,t)}render(){const e=this.gl;if(!this.program)return;this.updateMatrix();const t="dark"===this.theme?.05:.95;e.clearColor(t,t,t,1),e.clear(e.COLOR_BUFFER_BIT),this.edgeCount>0&&this.edgeProgram&&(e.useProgram(this.edgeProgram),e.uniformMatrix3fv(this.uEdgeMatrixLoc,!1,this.viewMatrix),e.uniform4fv(this.uEdgeColorLoc,"dark"===this.theme?[1,1,1,.15]:[0,0,0,.1]),e.bindVertexArray(this.edgeVao),e.drawElements(e.LINES,this.edgeCount,e.UNSIGNED_INT,0)),e.useProgram(this.program),e.uniformMatrix3fv(this.uMatrixLoc,!1,this.viewMatrix),e.uniform1f(this.uPointSizeLoc,40*this.state.zoom*window.devicePixelRatio),e.uniform1i(this.uPickingModeLoc,0),e.bindVertexArray(this.vao),e.drawArrays(e.POINTS,0,this.nodeCount),this.renderOverlay()}renderOverlay(){this.overlayManager.render({...this.state,selectedNodes:this.state.selectedNodeIds,lockedNodes:this.lockedNodes,hiddenNodes:this.hiddenNodes,positions:this.positions,nodeCount:this.nodeCount,edgeCount:this.edgeCount,edgeIndices:this.edgeIndices,metadata:this.metadata,edgeMetadata:this.edgeMetadata,combos:this.combos,theme:this.theme,viewMatrix:this.viewMatrix,edgeIndexToUserIdMap:this.edgeIndexToUserIdMap})}getState(){return this.state}updateInteractionState(e){Object.assign(this.state,e)}setFlowConfig(e){this.state.flow={...this.state.flow,...e},this.render()}pick(e,t){if(!this.program||!this.pickingFramebuffer||!this.vao)return null;const s=this.pickingEngine.pickNode({mouseX:e,mouseY:t,canvas:this.canvas,program:this.program,pickingFramebuffer:this.pickingFramebuffer,vao:this.vao,nodeCount:this.nodeCount,viewMatrix:this.viewMatrix,pointSize:40*this.state.zoom*window.devicePixelRatio});return null!==s&&this.hiddenNodes.has(s)?null:s}getEdgeAt(e,t){const s=this.pickingEngine.pickEdge({mouseX:e,mouseY:t,edgeIndices:this.edgeIndices,positions:this.positions,nodeCount:this.nodeCount,viewMatrix:this.viewMatrix,canvasW:this.canvas.width,canvasH:this.canvas.height});if(!s)return null;const i=this.edgeIndexToUserIdMap.get(s);return i&&this.hiddenEdges.has(i)?null:i??s}pickCombo(e,t){return this.pickingEngine.pickCombo({mouseX:e,mouseY:t,combos:this.combos,positions:this.positions,nodeCount:this.nodeCount,viewMatrix:this.viewMatrix,zoom:this.state.zoom,canvasW:this.canvas.width,canvasH:this.canvas.height})}pickHUD(e,t){return this.overlayManager.pickHUDAction(e,t)}fitToView(){if(!this.positions||0===this.nodeCount)return this.state.zoom=1,this.state.offset=s.fromValues(0,0),void this.render();let e=1/0,t=1/0,i=-1/0,o=-1/0;for(let s=0;s<this.nodeCount;s++){if(this.hiddenNodes.has(s))continue;const a=this.positions[2*s],n=this.positions[2*s+1];a<e&&(e=a),a>i&&(i=a),n<t&&(t=n),n>o&&(o=n)}const a=i-e,n=o-t,r=(e+i)/2,l=(t+o)/2,d=2*(this.canvas.width/this.canvas.height)*.9/Math.max(a,.01),c=1.8/Math.max(n,.01);this.state.zoom=Math.min(d,c,100),this.state.offset=s.fromValues(-r,-l),this.render()}zoomIn(){this.state.zoom=Math.min(S.MAX_ZOOM,1.2*this.state.zoom),this.render()}zoomOut(){this.state.zoom=Math.max(S.MIN_ZOOM,this.state.zoom/1.2),this.render()}setCameraCenter(e,t){this.state.offset=s.fromValues(-e,-t),this.render()}setCameraZoom(e){this.state.zoom=Math.max(S.MIN_ZOOM,Math.min(S.MAX_ZOOM,e)),this.render()}getSelectedNodeIds(){return Array.from(this.state.selectedNodeIds)}getSelectedUserIds(){return Array.from(this.state.selectedNodeIds).map(e=>this.reverseIdMap.get(e)??e)}selectNode(e){this.state.selectedNodeIds.clear(),null!==e&&this.state.selectedNodeIds.add(e),this.canvas.dispatchEvent(new CustomEvent("node-selected",{detail:e})),this.emitter.emit("node:select",{id:null!==e?this.reverseIdMap.get(e)??e:null,index:e}),this.render()}zoomAt(e,t,i){const o=window.devicePixelRatio,a=this.unproject(e*o,t*o);this.state.zoom=Math.max(S.MIN_ZOOM,Math.min(S.MAX_ZOOM,this.state.zoom*(1+i))),this.updateMatrix();const n=this.unproject(e*o,t*o);s.add(this.state.offset,this.state.offset,s.sub(s.create(),n,a)),this.emitter.emit("graph:zoom",{zoom:this.state.zoom}),this.render()}runLayout(e,t){if(!this.positions)return;const s=t?.selectedOnly?Array.from(this.state.selectedNodeIds):Array.from({length:this.nodeCount},(e,t)=>t);if(0===s.length)return;const i=this.nodeCount,o=new Float32Array(this.positions),a=new Float32Array(this.positions);if("grid"===e){const e=Math.ceil(Math.sqrt(s.length)),t=150;s.forEach((s,i)=>{const o=Math.floor(i/e),n=i%e;a[2*s]=n*t-e*t/2,a[2*s+1]=o*t-e*t/2})}else if("circle"===e){const e=Math.max(200,15*s.length),t=2*Math.PI/s.length;s.forEach((s,i)=>{a[2*s]=Math.cos(i*t)*e,a[2*s+1]=Math.sin(i*t)*e})}else if("random"===e){const e=Math.max(500,100*Math.sqrt(s.length));s.forEach(t=>{a[2*t]=(Math.random()-.5)*e,a[2*t+1]=(Math.random()-.5)*e})}const n=performance.now(),r=e=>{const t=e-n,s=Math.min(t/600,1),l=s<.5?2*s*s:1-Math.pow(-2*s+2,2)/2;for(let n=0;n<2*i;n++)this.positions[n]=o[n]+(a[n]-o[n])*l;this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.positionBuffer),this.gl.bufferData(this.gl.ARRAY_BUFFER,this.positions,this.gl.DYNAMIC_DRAW),this.render(),s<1&&requestAnimationFrame(r)};requestAnimationFrame(r)}radialMenuConfigs={node:[{label:"Connect",icon:"link",action:"start-connect"},{label:"Lock",icon:"lock",action:"pin"},{label:"Color",icon:"palette",action:"color"},{label:"Delete",icon:"trash-2",action:"delete"},{label:"Group",icon:"box",action:"create-combo"}],edge:[{label:"Reverse",icon:"repeat",action:"reverse"},{label:"Hide",icon:"eye-off",action:"hide"},{label:"Delete",icon:"trash-2",action:"delete-edge"}],combo:[{label:"Toggle",icon:"maximize",action:"toggle-collapse"},{label:"Rename",icon:"edit-3",action:"rename-group"},{label:"Ungroup",icon:"zap",action:"dissolve-combo"}]};setRadialMenu(e,t){this.radialMenuConfigs[e]=t}getRadialMenu(e){return this.radialMenuConfigs[e]||[]}pan(e,t){s.add(this.state.offset,this.state.offset,s.fromValues(e/this.state.zoom,t/this.state.zoom)),this.emitter.emit("graph:pan",{dx:e,dy:t,offset:{x:this.state.offset[0],y:this.state.offset[1]}}),this.emitter.emit("viewport",{zoom:this.state.zoom,offset:this.state.offset}),this.render()}syncDragOffsets(e,t){const i=window.devicePixelRatio,o=this.unproject(e*i,t*i);this.dragOffsets.clear();for(const a of this.state.selectedNodeIds){const e=this.getNodePosition(a);e&&this.dragOffsets.set(a,s.sub(s.create(),e,o))}}handleDragging(e,t){if(!this.positions)return;const i=window.devicePixelRatio,o=this.unproject(e*i,t*i),a=this.gl;a.bindBuffer(a.ARRAY_BUFFER,this.positionBuffer);const n=/* @__PURE__ */new Set;for(const r of this.state.selectedNodeIds){if(this.lockedNodes.has(r))continue;const e=this.dragOffsets.get(r);if(e&&this.positions){const t=s.add(s.create(),o,e);let i=null;for(const e of this.combos.values())if(e.collapsed&&e.representativeId===r){i=e.id;break}if(i&&!n.has(i)){const e=t[0]-this.positions[2*r],s=t[1]-this.positions[2*r+1];this.moveGroup(i,e,s,!0),n.add(i)}else i||(this.positions[2*r]=t[0],this.positions[2*r+1]=t[1]);this.canvas.dispatchEvent(new CustomEvent("node-moved",{detail:{id:r,x:t[0],y:t[1]}})),this.emitter.emit("node:drag",{id:this.reverseIdMap.get(r)??r,index:r,x:t[0],y:t[1]})}}this.positions&&(a.bindBuffer(a.ARRAY_BUFFER,this.positionBuffer),a.bufferData(a.ARRAY_BUFFER,this.positions,a.DYNAMIC_DRAW)),this.render()}performBoxSelection(){if(!this.positions)return;const e=window.devicePixelRatio,t=this.unproject(this.state.selectionStart[0]*e,this.state.selectionStart[1]*e),s=this.unproject(this.state.selectionEnd[0]*e,this.state.selectionEnd[1]*e),i=Math.min(t[0],s[0]),o=Math.max(t[0],s[0]),a=Math.min(t[1],s[1]),n=Math.max(t[1],s[1]);this.state.selectedNodeIds.clear();for(let r=0;r<this.nodeCount;r++){if(this.hiddenNodes.has(r))continue;const e=this.positions[2*r],t=this.positions[2*r+1];e>=i&&e<=o&&t>=a&&t<=n&&this.state.selectedNodeIds.add(r)}this.canvas.dispatchEvent(new CustomEvent("nodes-selected",{detail:Array.from(this.state.selectedNodeIds)})),this.emitter.emit("nodes:select",{ids:Array.from(this.state.selectedNodeIds).map(e=>this.reverseIdMap.get(e)??e),indices:Array.from(this.state.selectedNodeIds)})}unproject(i,o){const a=i/this.canvas.width*2-1,n=-(o/this.canvas.height*2-1),r=e.invert(e.create(),this.viewMatrix);if(!r)return s.create();const l=t.fromValues(a,n,1);return t.transformMat3(l,l,r),s.fromValues(l[0],l[1])}initShaders(){const e=this.gl;this.program=this.createProgram("#version 300 es\nlayout(location = 0) in vec2 a_position;\nlayout(location = 1) in vec4 a_color;\nlayout(location = 2) in float a_id;\n\nuniform mat3 u_matrix;\nuniform float u_pointSize;\nuniform bool u_pickingMode;\n\nout vec4 v_color;\nflat out uint v_id;\n\nvoid main() {\n vec3 position = u_matrix * vec3(a_position, 1.0);\n gl_Position = vec4(position.xy, 0, 1);\n gl_PointSize = u_pointSize;\n v_color = a_color;\n v_id = uint(a_id);\n}\n","#version 300 es\nprecision highp float;\n\nin vec4 v_color;\nflat in uint v_id;\n\nuniform bool u_pickingMode;\nout vec4 outColor;\n\nvoid main() {\n float dist = distance(gl_PointCoord, vec2(0.5));\n if (dist > 0.5) discard;\n if (v_color.a <= 0.0) discard;\n\n if (u_pickingMode) {\n uint id = v_id + 1u;\n float r = float((id >> 16) & 0xFFu) / 255.0;\n float g = float((id >> 8) & 0xFFu) / 255.0;\n float b = float(id & 0xFFu) / 255.0;\n outColor = vec4(r, g, b, 1.0);\n } else {\n outColor = v_color;\n }\n}\n"),this.uMatrixLoc=e.getUniformLocation(this.program,"u_matrix"),this.uPointSizeLoc=e.getUniformLocation(this.program,"u_pointSize"),this.uPickingModeLoc=e.getUniformLocation(this.program,"u_pickingMode"),this.edgeProgram=this.createProgram("#version 300 es\nlayout(location = 0) in vec2 a_position;\n\nuniform mat3 u_matrix;\n\nvoid main() {\n vec3 position = u_matrix * vec3(a_position, 1.0);\n gl_Position = vec4(position.xy, 0, 1);\n}\n","#version 300 es\nprecision highp float;\nuniform vec4 u_color;\nout vec4 outColor;\n\nvoid main() {\n outColor = u_color;\n}\n"),this.uEdgeMatrixLoc=e.getUniformLocation(this.edgeProgram,"u_matrix"),this.uEdgeColorLoc=e.getUniformLocation(this.edgeProgram,"u_color")}initBuffers(){const e=this.gl;this.vao=e.createVertexArray(),e.bindVertexArray(this.vao),this.positionBuffer=e.createBuffer(),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(0),e.vertexAttribPointer(0,2,e.FLOAT,!1,0,0),this.colorBuffer=e.createBuffer(),e.bindBuffer(e.ARRAY_BUFFER,this.colorBuffer),e.enableVertexAttribArray(1),e.vertexAttribPointer(1,4,e.FLOAT,!1,0,0),this.idBuffer=e.createBuffer(),e.bindBuffer(e.ARRAY_BUFFER,this.idBuffer),e.enableVertexAttribArray(2),e.vertexAttribPointer(2,1,e.FLOAT,!1,0,0),this.edgeVao=e.createVertexArray(),e.bindVertexArray(this.edgeVao),e.bindBuffer(e.ARRAY_BUFFER,this.positionBuffer),e.enableVertexAttribArray(0),e.vertexAttribPointer(0,2,e.FLOAT,!1,0,0),this.edgeIndexBuffer=e.createBuffer(),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.edgeIndexBuffer),e.bindVertexArray(null)}initPicking(){const e=this.gl;this.pickingFramebuffer=e.createFramebuffer(),this.pickingTexture=e.createTexture(),e.bindTexture(e.TEXTURE_2D,this.pickingTexture),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,this.canvas.width,this.canvas.height,0,e.RGBA,e.UNSIGNED_BYTE,null),e.bindFramebuffer(e.FRAMEBUFFER,this.pickingFramebuffer),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,this.pickingTexture,0),e.bindFramebuffer(e.FRAMEBUFFER,null)}handleResize(){const e=window.devicePixelRatio;this.canvas.width=this.canvas.clientWidth*e,this.canvas.height=this.canvas.clientHeight*e,this.overlayCanvas.width=this.overlayCanvas.clientWidth*e,this.overlayCanvas.height=this.overlayCanvas.clientHeight*e,this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.initPicking(),this.render()}updateMatrix(){const t=this.canvas.width/this.canvas.height;e.identity(this.viewMatrix),e.scale(this.viewMatrix,this.viewMatrix,[this.state.zoom/t,this.state.zoom]),e.translate(this.viewMatrix,this.viewMatrix,this.state.offset)}createProgram(e,t){const s=this.gl,i=s.createShader(s.VERTEX_SHADER);s.shaderSource(i,e),s.compileShader(i);const o=s.createShader(s.FRAGMENT_SHADER);s.shaderSource(o,t),s.compileShader(o);const a=s.createProgram();return s.attachShader(a,i),s.attachShader(a,o),s.linkProgram(a),a}resolveNodeIndex(e){let t=this.nodeIdMap.get(e);if(void 0!==t)return t;if(t=this.nodeIdMap.get(e.toString()),void 0!==t)return t;const s="number"==typeof e?e:Number(e);return!isNaN(s)&&s>=0&&s<this.nodeCount?s:null}parseColor(e){if(!e)return[Math.random(),Math.random(),Math.random(),1];if(Array.isArray(e))return[e[0]??0,e[1]??0,e[2]??0,e[3]??1];if("string"==typeof e){const t=e.replace("#","");if(t.length>=6)return[parseInt(t.slice(0,2),16)/255,parseInt(t.slice(2,4),16)/255,parseInt(t.slice(4,6),16)/255,1]}return[Math.random(),Math.random(),Math.random(),1]}ensureNodeCapacity(e){if(e<=this.capacity)return;const t=Math.max(2*this.capacity,e,64),s=new Float32Array(2*t),i=new Float32Array(4*t),o=new Float32Array(t);this.positions&&s.set(this.positions.subarray(0,2*this.nodeCount)),this.colorData.length>0&&i.set(this.colorData.subarray(0,4*this.nodeCount)),this.idData.length>0&&o.set(this.idData.subarray(0,this.nodeCount)),this.positions=s,this.colorData=i,this.idData=o,this.capacity=t;const a=this.gl;a.bindBuffer(a.ARRAY_BUFFER,this.positionBuffer),a.bufferData(a.ARRAY_BUFFER,this.positions,a.DYNAMIC_DRAW),a.bindBuffer(a.ARRAY_BUFFER,this.colorBuffer),a.bufferData(a.ARRAY_BUFFER,this.colorData,a.DYNAMIC_DRAW),a.bindBuffer(a.ARRAY_BUFFER,this.idBuffer),a.bufferData(a.ARRAY_BUFFER,this.idData,a.DYNAMIC_DRAW)}rebuildEdgeBuffer(){const e=this.gl,t=this.edgeList.filter(e=>!this.hiddenEdges.has(e.id));if(0===t.length)return this.edgeIndices=null,void(this.edgeCount=0);this.edgeIndices=new Uint32Array(2*t.length);for(let s=0;s<t.length;s++)this.edgeIndices[2*s]=t[s].u,this.edgeIndices[2*s+1]=t[s].v;this.edgeCount=this.edgeIndices.length,e.bindVertexArray(this.edgeVao),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.edgeIndexBuffer),e.bufferData(e.ELEMENT_ARRAY_BUFFER,this.edgeIndices,e.DYNAMIC_DRAW),e.bindVertexArray(null)}rebuildEdgeIndexToUserIdMap(){this.edgeIndexToUserIdMap.clear();for(const e of this.edgeList)this.edgeIndexToUserIdMap.set(`${e.u}-${e.v}`,e.id),this.edgeIndexToUserIdMap.set(`${e.v}-${e.u}`,e.id)}_removeEdgeInternal(e){const t=this.edgeIdMap.get(e);if(void 0===t)return;const s=this.edgeList.length-1;if(t!==s){const e=this.edgeList[s];this.edgeList[t]=e,this.edgeIdMap.set(e.id,t)}this.edgeList.pop(),this.edgeIdMap.delete(e),this.edgeMetadata.delete(e),this.hiddenEdges.delete(e),this.rebuildEdgeIndexToUserIdMap()}loadNodeImage(e,t){const s=this.metadata.get(e);if(!s)return;const i=new Image;i.src=t,i.onload=()=>{const e=document.createElement("canvas"),t=128;e.width=t,e.height=t;const o=e.getContext("2d");o&&(o.beginPath(),o.arc(64,64,64,0,2*Math.PI),o.clip(),o.filter="grayscale(100%) brightness(1000%)",o.drawImage(i,0,0,t,t),s.processedImageElement=e),s.imageElement=i,this.render()},s.imageElement=i}}function D(){const e=i([]);return{graphNodes:e,processGraphData:t=>{const s=t.nodes||[],i=t.edges||[],o=s.length,a=new Float32Array(2*o),n=new Float32Array(4*o),r=new Float32Array(o),l=new Float32Array(o),d=/* @__PURE__ */new Map,c=/* @__PURE__ */new Map;s.forEach((e,t)=>{const s=e.data,i=e.position||{x:0,y:0};c.set(s.id,t),a[2*t]=((i.x??2500)-2500)/500,a[2*t+1]=((i.y??2500)-2500)/500;const o=(e=>{const t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return t?[parseInt(t[1],16)/255,parseInt(t[2],16)/255,parseInt(t[3],16)/255]:[Math.random(),Math.random(),Math.random()]})(s.color||"#000000");n[4*t]=o[0],n[4*t+1]=o[1],n[4*t+2]=o[2],n[4*t+3]=1,r[t]=t;const h=s.width||50,u=s.height||50;l[t]=Math.max(h,u)/1e3;const g={label:s.label||s.code||`Node ${s.id}`,image:s.backgroundImage,width:h,height:u,data:s};if(s.backgroundImage){const e=new Image;e.src=s.backgroundImage,e.onload=()=>{const t=document.createElement("canvas"),s=128;t.width=s,t.height=s;const i=t.getContext("2d");i&&(i.beginPath(),i.arc(64,64,64,0,2*Math.PI),i.clip(),i.filter="grayscale(100%) brightness(1000%)",i.drawImage(e,0,0,s,s),g.processedImageElement=t)},g.imageElement=e}d.set(t,g)}),e.value=Array.from(d.entries()).map(([e,t])=>({id:e,_index:e,label:t.label,position:{x:a[2*e],y:a[2*e+1]}}));const h=[],u=/* @__PURE__ */new Map;return i.forEach(e=>{const t=e.data.source,s=e.data.target,i=c.get(t),o=c.get(s);if(void 0!==i&&void 0!==o){h.push(i),h.push(o);const t=`${i}-${o}`;u.set(t,{label:e.data.label,data:e.data})}}),{positions:a,colors:n,ids:r,nodeRadii:l,metadata:d,edgeIndices:new Uint32Array(h),edgeMetadata:u,idMap:c,count:o}}}}const L=["width","height","stroke-width"],T=["d"],P=["cx","cy","r"],U=["x1","y1","x2","y2"],z=["x","y","width","height","rx","ry"],Y=(e,t)=>{const s=e.__vccOpts||e;for(const[i,o]of t)s[i]=o;return s},V=/* @__PURE__ */Y(/* @__PURE__ */l({__name:"LucideIcon",props:{name:{},size:{default:24},strokeWidth:{default:2}},setup(e){const t=e,s={sun:{paths:["M12 1v2","M12 21v2","M4.22 4.22l1.42 1.42","M18.36 18.36l1.42 1.42","M1 12h2","M21 12h2","M4.22 19.78l1.42-1.42","M18.36 5.64l1.42-1.42"],circles:[{cx:12,cy:12,r:4}]},moon:{paths:["M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"]},maximize:{paths:["M8 3H5a2 2 0 0 0-2 2v3","M21 8V5a2 2 0 0 0-2-2h-3","M3 16v3a2 2 0 0 0 2 2h3","M16 21h3a2 2 0 0 0 2-2v-3"]},plus:{paths:["M12 5v14","M5 12h14"]},minus:{paths:["M5 12h14"]},rocket:{paths:["M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z","m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z","M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0","M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5"]},shrink:{paths:["M14 10l7-7","M3 21l7-7","M21 10h-7V3","M3 14h7v7"]},expand:{paths:["M15 3h6v6","M9 21H3v-6","M21 3l-7 7","M3 21l7-7"]},"layout-grid":{rects:[{x:3,y:3,width:7,height:7,rx:1},{x:14,y:3,width:7,height:7,rx:1},{x:14,y:14,width:7,height:7,rx:1},{x:3,y:14,width:7,height:7,rx:1}]},circle:{circles:[{cx:12,cy:12,r:10}]},dices:{rects:[{x:2,y:11,width:11,height:11,rx:2}],paths:["M7 15h.01","M7 19h.01","M11 19h.01","M22 5V2a1 1 0 0 0-1-1h-6a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2","M22 5h-4a1 1 0 0 0-1 1v4","M22 5c0-1.1-.9-2-2-2","M14 7h.01"]},spiral:{paths:["M12 12a1 1 0 1 0 1 1","M12 7a5 5 0 1 0 5 5","M12 2a10 10 0 1 0 10 10","M12 12a1 1 0 0 0-1-1"]},target:{circles:[{cx:12,cy:12,r:10},{cx:12,cy:12,r:6},{cx:12,cy:12,r:2}]},atom:{circles:[{cx:12,cy:12,r:1}],paths:["M12 2v2","M12 20v2","m4.93 4.93 1.41 1.41","m17.66 17.66 1.41 1.41","M2 12h2","M20 12h2","m6.34 17.66-1.41-1.41","m19.07 4.93-1.41 1.41"]},"git-branch":{circles:[{cx:6,cy:3,r:3},{cx:6,cy:21,r:3},{cx:18,cy:9,r:3}],paths:["M6 6v12","M18 12a6 6 0 0 1-6 6H6"]},sparkles:{paths:["m12 3-1.912 5.813a2 2 0 0 1-1.275 1.275L3 12l5.813 1.912a2 2 0 0 1 1.275 1.275L12 21l1.912-5.813a2 2 0 0 1 1.275-1.275L21 12l-5.813-1.912a2 2 0 0 1-1.275-1.275L12 3Z","M5 3L4 5.5 1.5 6.5 4 7.5 5 10l1-2.5 2.5-1L6 5.5 5 3Z","M19 19l-1 2.5-2.5 1L18 23.5l1 2.5 1-2.5 2.5-1-2.5-1-1-2.5Z"]},search:{circles:[{cx:11,cy:11,r:8}],lines:[{x1:21,y1:21,x2:16.65,y2:16.65}]},info:{circles:[{cx:12,cy:12,r:10}],paths:["M12 16v-4","M12 8h.01"]},"trash-2":{paths:["M3 6h18","M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6","M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2","M10 11v6","M14 11v6"]},palette:{circles:[{cx:13.5,cy:6.5,r:.5},{cx:17.5,cy:10.5,r:.5},{cx:8.5,cy:7.5,r:.5},{cx:6.5,cy:12.5,r:.5}],paths:["M12 2C6.47 2 2 6.47 2 12s4.47 10 9.99 10a3 3 0 0 0 3-3c0-.8-.34-1.56-.92-2.1l-.1-.08c-.53-.45-.88-1.1-.88-1.82 0-1.38 1.12-2.5 2.5-2.5H19a3 3 0 0 0 2-5c0-4.42-4.03-8-9-8Z"]},pin:{paths:["M15 4.5l-4 4L7 10l-1.5 1.5 7 7L14 17l1.5-4 4-4L15 4.5z","m9 21 3-3","M14 4.5L19.5 10"]},box:{paths:["M21 8a2 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","m3.3 7 8.7 5 8.7-5","M12 22V12"]},eye:{paths:["M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"],circles:[{cx:12,cy:12,r:3}]},"eye-off":{paths:["M9.88 9.88a3 3 0 1 0 4.24 4.24","M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68","M6.61 6.61A13.52 13.52 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61","m2 2 20 20"]},"refresh-cw":{paths:["M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8","M21 3v5h-5","M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16","M3 21v-5h5"]},scale:{paths:["m16 16 3-8 3 8c-.87.62-1.92 1-3 1s-2.13-.38-3-1Z","m2 16 3-8 3 8c-.87.62-1.92 1-3 1s-2.13-.38-3-1Z","M7 21h10","M12 3v18","M3 7h18"]},zap:{paths:["M13 2 3 14h9l-1 8 10-12h-9l1-8z"]},x:{paths:["M18 6L6 18","M6 6l12 12"]}},i=r(()=>s[t.name]||s.search),o=r(()=>i.value.paths||[]),a=r(()=>i.value.circles||[]),n=r(()=>i.value.lines||[]),l=r(()=>i.value.rects||[]);return(t,s)=>(d(),c("svg",{xmlns:"http://www.w3.org/2000/svg",width:e.size,height:e.size,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":e.strokeWidth,"stroke-linecap":"round","stroke-linejoin":"round",class:"lucide-icon"},[(d(!0),c(h,null,u(o.value,(e,t)=>(d(),c("path",{key:t,d:e},null,8,T))),128)),(d(!0),c(h,null,u(a.value,(e,t)=>(d(),c("circle",{key:t,cx:e.cx,cy:e.cy,r:e.r},null,8,P))),128)),(d(!0),c(h,null,u(n.value,(e,t)=>(d(),c("line",{key:t,x1:e.x1,y1:e.y1,x2:e.x2,y2:e.y2},null,8,U))),128)),(d(!0),c(h,null,u(l.value,(e,t)=>(d(),c("rect",{key:t,x:e.x,y:e.y,width:e.width,height:e.height,rx:e.rx,ry:e.ry},null,8,z))),128))],8,L))}}),[["__scopeId","data-v-6aa14fad"]]),$={class:"radial-center glass shadow-glow"},j=["onClick"],O={class:"radial-icon"},W={class:"radial-label"},G=/* @__PURE__ */Y(/* @__PURE__ */l({__name:"RadialMenu",props:{show:{type:Boolean},x:{},y:{},type:{},items:{}},emits:["action"],setup(e){const t=(e,t)=>{const s=e/t*Math.PI*2-Math.PI/2,i=window.innerWidth<768?96:76;return{transform:`translate(-50%, -50%) translate(${Math.cos(s)*i}px, ${Math.sin(s)*i}px)`,transitionDelay:.04*e+"s"}};return(s,i)=>e.show?(d(),c("div",{key:0,class:"radial-menu",style:m({left:e.x+"px",top:e.y+"px"}),onMousedown:i[0]||(i[0]=g(()=>{},["stop"])),onTouchstart:i[1]||(i[1]=g(()=>{},["stop"]))},[v("div",$,[f(s.$slots,"center",{},()=>["node"===e.type?(d(),p(V,{key:0,name:"target",size:"24"})):"edge"===e.type?(d(),p(V,{key:1,name:"git-branch",size:"24"})):(d(),p(V,{key:2,name:"search",size:"24"}))],!0)]),(d(!0),c(h,null,u(e.items,(i,o)=>(d(),c("div",{key:o,class:"radial-item",style:m(t(o,e.items.length))},[v("button",{class:"radial-item-inner glass-interactive",onClick:e=>s.$emit("action",i.action)},[v("span",O,[b(V,{name:i.icon,size:"20"},null,8,["name"])]),v("span",W,M(i.label),1)],8,j)],4))),128))],36)):w("",!0)}}),[["__scopeId","data-v-31b4eac1"]]),X={class:"top-right-controls glass"},H=["title"],Z=["title"],q=/* @__PURE__ */Y(/* @__PURE__ */l({__name:"ViewControls",props:{theme:{},flowEnabled:{type:Boolean}},emits:["toggleTheme","fit","zoomIn","zoomOut","stress","toggleFlow"],setup(e){const t=i(!1),s=()=>{document.fullscreenElement?(document.exitFullscreen(),t.value=!1):(document.documentElement.requestFullscreen(),t.value=!0)};return(i,o)=>(d(),c("div",X,[v("button",{class:"control-btn glass-interactive",onClick:o[0]||(o[0]=e=>i.$emit("toggleTheme")),title:"dark"===e.theme?"Switch to Light":"Switch to Dark"},[b(V,{name:"dark"===e.theme?"moon":"sun",size:"20"},null,8,["name"])],8,H),o[6]||(o[6]=v("div",{class:"divider"},null,-1)),v("button",{class:"control-btn glass-interactive",onClick:o[1]||(o[1]=e=>i.$emit("fit")),title:"Fit View"},[b(V,{name:"maximize",size:"20"})]),v("button",{class:"control-btn glass-interactive",onClick:o[2]||(o[2]=e=>i.$emit("zoomIn")),title:"Zoom In"},[b(V,{name:"plus",size:"20"})]),v("button",{class:"control-btn glass-interactive",onClick:o[3]||(o[3]=e=>i.$emit("zoomOut")),title:"Zoom Out"},[b(V,{name:"minus",size:"20"})]),o[7]||(o[7]=v("div",{class:"divider"},null,-1)),v("button",{class:"control-btn glass-interactive stress-btn",onClick:o[4]||(o[4]=e=>i.$emit("stress")),title:"Stress Test (100k Nodes)"},[b(V,{name:"rocket",size:"20"})]),o[8]||(o[8]=v("div",{class:"divider"},null,-1)),v("button",{class:y(["control-btn glass-interactive",{"flow-active":e.flowEnabled}]),onClick:o[5]||(o[5]=e=>i.$emit("toggleFlow")),title:e.flowEnabled?"Disable Energy Flow":"Enable Energy Flow"},[b(V,{name:"waves",size:"20"})],10,Z),o[9]||(o[9]=v("div",{class:"divider"},null,-1)),v("button",{class:"control-btn glass-interactive",onClick:s,title:"Toggle Fullscreen"},[b(V,{name:t.value?"shrink":"expand",size:"20"},null,8,["name"])])]))}}),[["__scopeId","data-v-08b2ffb9"]]),K={class:"layout-controls glass"},J={class:"scroll-container no-scrollbar"},Q=["onClick","title"],ee={class:"btn-icon"},te={key:0,class:"btn-name"},se=/* @__PURE__ */Y(/* @__PURE__ */l({__name:"LayoutControls",props:{layouts:{},currentLayout:{},flowEnabled:{type:Boolean}},emits:["runLayout","toggleFlow"],setup:e=>(t,s)=>(d(),c("div",K,[v("div",J,[(d(!0),c(h,null,u(e.layouts,s=>(d(),c("button",{key:s.id,class:y(["layout-btn glass-interactive",{active:e.currentLayout===s.id}]),onClick:e=>t.$emit("runLayout",s.id),title:s.name},[v("span",ee,[b(V,{name:s.icon,size:"18"},null,8,["name"])]),e.currentLayout===s.id?(d(),c("span",te,M(s.name),1)):w("",!0)],10,Q))),128))])]))}),[["__scopeId","data-v-503d31c7"]]),ie={key:0,class:"property-panel glass node-panel"},oe={class:"panel-header"},ae={class:"panel-content"},ne={key:0,class:"val-container"},re=["src"],le={key:1},de={key:1,class:"json-prop"},ce={key:1,class:"property-panel glass edge-panel"},he={class:"panel-header"},ue={class:"panel-content"},ge={class:"prop-group"},me={class:"id-badge"},ve={key:0,class:"val-container"},fe=["src"],pe={key:1},be={key:1,class:"json-prop"},Me={key:2,class:"property-panel glass combo-panel"},we={class:"panel-header"},ye={class:"panel-content"},Ie={class:"prop-group shadow-sm"},xe=["value"],Ee={class:"prop-group"},Ae={class:"member-list"},Ce=["onClick"],Re={key:0,class:"more-hint"},ke=/* @__PURE__ */Y(/* @__PURE__ */l({__name:"PropertyPanel",props:{nodeId:{},nodeMetadata:{},nodeX:{},nodeY:{},edgeId:{},edgeMetadata:{},combo:{}},emits:["update:nodeX","update:nodeY","update:nodeId","update:edgeId","update:combo","update:comboLabel","removeFromCombo"],setup(e,{emit:t}){const s=e=>"string"==typeof e&&e.startsWith("data:image/");return(t,i)=>null!==e.nodeId?(d(),c("div",ie,[v("div",oe,[i[4]||(i[4]=v("h3",null,"Node Properties",-1)),v("button",{class:"close-btn",onClick:i[0]||(i[0]=e=>t.$emit("update:nodeId",null))},[b(V,{name:"x",size:"18"})])]),v("div",ae,[e.nodeMetadata&&e.nodeMetadata.data?(d(!0),c(h,{key:0},u(e.nodeMetadata.data,(t,i)=>(d(),c("div",{key:i,class:"prop-group"},[v("label",null,M(i),1),"object"!=typeof t?(d(),c("div",ne,[s(t)?(d(),c("img",{key:0,src:t,class:"prop-image",style:m("backgroundImage"===i?{backgroundColor:e.nodeMetadata.data.color||"var(--primary)"}:{})},null,12,re)):(d(),c("span",le,M(t),1))])):(d(),c("pre",de,M(JSON.stringify(t,null,2)),1))]))),128)):w("",!0)])])):null!==e.edgeId?(d(),c("div",ce,[v("div",he,[i[5]||(i[5]=v("h3",null,"Edge Properties",-1)),v("button",{class:"close-btn",onClick:i[1]||(i[1]=e=>t.$emit("update:edgeId",null))},[b(V,{name:"x",size:"18"})])]),v("div",ue,[v("div",ge,[i[6]||(i[6]=v("label",null,"ID",-1)),v("span",me,M(e.edgeId),1)]),e.edgeMetadata&&e.edgeMetadata.data?(d(!0),c(h,{key:0},u(e.edgeMetadata.data,(t,i)=>(d(),c("div",{key:i,class:"prop-group"},[v("label",null,M(i),1),"object"!=typeof t?(d(),c("div",ve,[s(t)?(d(),c("img",{key:0,src:t,class:"prop-image",style:m("backgroundImage"===i?{backgroundColor:e.edgeMetadata.data.color||"var(--secondary)"}:{})},null,12,fe)):(d(),c("span",pe,M(t),1))])):(d(),c("pre",be,M(JSON.stringify(t,null,2)),1))]))),128)):w("",!0)])])):e.combo?(d(),c("div",Me,[v("div",we,[i[7]||(i[7]=v("h3",null,"Group Properties",-1)),v("button",{class:"close-btn",onClick:i[2]||(i[2]=e=>t.$emit("update:combo",null))},[b(V,{name:"x",size:"18"})])]),v("div",ye,[v("div",Ie,[i[8]||(i[8]=v("label",null,"Label",-1)),v("input",{type:"text",value:e.combo.label,class:"full-width",onInput:i[3]||(i[3]=e=>t.$emit("update:comboLabel",e.target.value))},null,40,xe)]),v("div",Ee,[v("label",null,"Members ("+M(e.combo.nodeIds.size)+")",1),v("div",Ae,[(d(!0),c(h,null,u(Array.from(e.combo.nodeIds).slice(0,50),e=>(d(),c("div",{key:e,class:"member-item"},[v("span",null,"Node "+M(e),1),v("button",{class:"remove-btn",onClick:s=>t.$emit("removeFromCombo",e)},[b(V,{name:"trash-2",size:"12"})],8,Ce)]))),128)),e.combo.nodeIds.size>50?(d(),c("div",Re," + "+M(e.combo.nodeIds.size-50)+" more ",1)):w("",!0)])])])])):w("",!0)}}),[["__scopeId","data-v-acd191f9"]]),Ne={class:"search-icon"},Fe={key:0,class:"results-panel"},_e=["onMousedown","onTouchstart"],Be={class:"node-icon"},Se={class:"node-info"},De={class:"node-label"},Le={class:"node-id"},Te={key:1,class:"no-results"},Pe=/* @__PURE__ */Y(/* @__PURE__ */l({__name:"SearchBar",props:{nodes:{}},emits:["select"],setup(e,{emit:t}){const s=e,n=t,l=i(""),m=i(!1),f=i(null),p=i(window.innerWidth<768),A=()=>{p.value=window.innerWidth<768};o(()=>{window.addEventListener("resize",A)}),a(()=>{window.removeEventListener("resize",A)});const C=r(()=>{if(!l.value)return[];const e=l.value.toLowerCase();return s.nodes.filter(t=>t.label?.toLowerCase().includes(e)||t.id.toString().includes(e)).slice(0,10)}),R=e=>{n("select",e),l.value="",m.value=!1},k=()=>{p.value&&!m.value&&(m.value=!0,setTimeout(()=>f.value?.focus(),100))},N=()=>{l.value="",m.value=!1,f.value?.blur()},F=()=>{p.value||setTimeout(()=>{m.value=!1},200)};return(e,t)=>(d(),c("div",{class:y(["search-wrapper",{"mobile-expanded":m.value&&p.value,"is-mobile":p.value}])},[v("div",{class:y(["search-container glass",{expanded:m.value,"has-query":l.value.length>0}])},[v("div",{class:"search-input-wrapper",onClick:k},[v("span",Ne,[b(V,{name:"search",size:p.value?20:14},null,8,["size"])]),I(v("input",{ref_key:"inputRef",ref:f,"onUpdate:modelValue":t[0]||(t[0]=e=>l.value=e),placeholder:"Search nodes...",onFocus:t[1]||(t[1]=e=>m.value=!0),onBlur:F,onKeydown:t[2]||(t[2]=x(e=>m.value=!1,["esc"]))},null,544),[[E,l.value]]),l.value||p.value&&m.value?(d(),c("div",{key:0,class:"clear-btn",onClick:g(N,["stop"])},[b(V,{name:l.value?"x":"chevron-down",size:p.value?20:12},null,8,["name","size"])])):w("",!0)]),m.value&&C.value.length>0?(d(),c("div",Fe,[(d(!0),c(h,null,u(C.value,e=>(d(),c("div",{key:e.id,class:"result-item",onMousedown:t=>R(e.id),onTouchstart:t=>R(e.id)},[v("span",Be,[b(V,{name:"circle",size:"8"})]),v("div",Se,[v("div",De,M(e.label),1),v("div",Le,"ID: "+M(e.id),1)])],40,_e))),128))])):m.value&&l.value?(d(),c("div",Te," No nodes found ")):w("",!0)],2),p.value&&m.value?(d(),c("div",{key:0,class:"mobile-backdrop",onClick:N})):w("",!0)],2))}}),[["__scopeId","data-v-283de02c"]]),Ue={key:0,class:"mobile-menu glass shadow-lg"},ze={class:"drawer-header"},Ye={key:0,class:"drawer-content"},Ve={key:1,class:"drawer-content"},$e={key:2,class:"top-right-controls"},je={class:"help-header"},Oe={class:"help-content no-scrollbar"},We={class:"key-badge"},Ge={class:"action-desc"},Xe={key:6,class:"connecting-toast glass shadow-glow"},He={class:"toast-content"},Ze={class:"edge-config-group"},qe={class:"color-presets"},Ke=["onClick"],Je={class:"size-config"},Qe=/* @__PURE__ */Y(/* @__PURE__ */l({__name:"GraphCanvas",props:{data:{}},setup(e){const t=e,s=i(null),l=i(null),f=A(null),{theme:x,isMobile:N,activeMobileDrawer:F,showMobileSearch:_,showHelp:B,apiPanelOpen:L,toggleTheme:T,toggleMobileDrawer:P,handleMobileSearch:U}=function(e){const t=i("dark"),s=i(window.innerWidth<768),n=i(null),r=i(!1),l=i(!1),d=i(!1),c=i(null),h=()=>{s.value=window.innerWidth<768};return o(()=>{window.addEventListener("resize",h)}),a(()=>{window.removeEventListener("resize",h)}),{theme:t,isMobile:s,activeMobileDrawer:n,showMobileSearch:r,showHelp:l,apiPanelOpen:d,searchBarRef:c,toggleTheme:()=>{t.value="dark"===t.value?"light":"dark",e.value&&e.value.setTheme(t.value),document.documentElement.classList.toggle("light","light"===t.value)},toggleMobileDrawer:e=>{n.value===e?n.value=null:n.value=e},handleMobileSearch:()=>{r.value=!0,setTimeout(()=>{c.value?.handleWrapperClick?.()},50)},updateMobileStatus:h}}(f),{graphNodes:z,processGraphData:Y}=D(),{selectedId:$,selectedEdgeId:j,selectedComboId:O,selectedCount:W,nodeX:X,nodeY:H,selectedNodeMetadata:Z,selectedEdgeMetadata:K,currentCombo:J,updateComboLabel:Q,removeFromCombo:ee,syncEdgeMetadata:te}=function(e){const t=i(null),s=i(null),o=i(null),a=i(0),r=i(0),l=i(0),d=i(null),c=i(null),h=i(null),u=()=>{if(null!==t.value&&e.value){const s=e.value.getNodePosition(t.value);s&&(r.value=Number(s[0].toFixed(3)),l.value=Number(s[1].toFixed(3))),d.value=e.value.getNodeMetadata(t.value)}else d.value=null},g=()=>{null!==s.value&&e.value?c.value=e.value.getEdgeMetadata(s.value):c.value=null},m=()=>{null!==t.value&&e.value&&e.value.setNodePosition(t.value,r.value,l.value)};return n(t,u),n(s,g),n(r,m),n(l,m),n(o,t=>{t&&e.value?h.value=e.value.getCombo(t)||null:h.value=null}),{selectedId:t,selectedEdgeId:s,selectedComboId:o,selectedCount:a,nodeX:r,nodeY:l,selectedNodeMetadata:d,selectedEdgeMetadata:c,currentCombo:h,updateComboLabel:t=>{if(o.value&&e.value){const s=e.value.getCombo(o.value);s&&(e.value.updateCombo(s.id,t,Array.from(s.nodeIds)),h.value={...s,label:t})}},removeFromCombo:t=>{if(o.value&&e.value){e.value.removeNodeFromCombo(o.value,t);const s=e.value.getCombo(o.value);s&&(h.value={...s,nodeIds:new Set(s.nodeIds)})}},syncNodeMetadata:u,syncEdgeMetadata:g}}(f),{currentLayout:ie,runLayout:oe,runStressTest:ae,initWorker:ne}=function(e){const t=i("random"),s=i(0);let o,n,r=null;const l=(e,t,i,a)=>{s.value=e,o=i,n=a,r&&r.terminate(),r=new Worker(new URL("/assets/layout.worker-CBxeMMC3.js",import.meta.url),{type:"module"}),r.postMessage({type:"init",data:{nodeCount:e,positions:t,nodeRadii:o,edgeIndices:n}}),r.onmessage=e=>{"layout-complete"===e.data.type&&d(e.data.positions)}},d=t=>{if(!e.value)return;const i=s.value,o=new Float32Array(2*i);for(let s=0;s<i;s++){const t=e.value.getNodePosition(s);t&&(o[2*s]=t[0],o[2*s+1]=t[1])}const a=performance.now(),n=new Float32Array(2*i),r=s=>{const l=s-a,d=Math.min(l/1e3,1),c=d<.5?4*d**3:1-Math.pow(-2*d+2,3)/2;if(o&&t)for(let e=0;e<2*i;e++)n[e]=o[e]+(t[e]-o[e])*c;e.value?.updatePositions(n),d<1?requestAnimationFrame(r):e.value?.fitToView()};requestAnimationFrame(r)};return a(()=>{r&&r.terminate()}),{currentLayout:t,nodeCount:s,runLayout:e=>{t.value=e,r&&r.postMessage({type:"layout",data:{layoutType:e,nodeRadii:o,edgeIndices:n}})},runStressTest:t=>{if(!e.value)return;s.value=t;const i=new Float32Array(2*t),o=new Float32Array(4*t),a=new Float32Array(t),n=new Float32Array(t),r=/* @__PURE__ */new Map;for(let e=0;e<t;e++)i[2*e]=50*(Math.random()-.5),i[2*e+1]=50*(Math.random()-.5),o[4*e]=Math.random(),o[4*e+1]=Math.random(),o[4*e+2]=Math.random(),o[4*e+3]=1,a[e]=e,n[e]=.05,r.set(e,{label:`S-${e}`,width:50,height:50});const d=[];for(let e=0;e<5e4;e++)d.push(Math.floor(Math.random()*t)),d.push(Math.floor(Math.random()*t));const c=new Uint32Array(d);e.value.setData(i,o,a,r,c,/* @__PURE__ */new Map),l(t,i,n,c),e.value.fitToView()},initWorker:l,animateToPositions:d}}(f),{contextMenu:re,menuItems:le,handleContextMenu:de,handleMenuAction:ce,connectingSourceId:he}=function(e,t,s,o,a){const n=i({show:!1,x:0,y:0,type:"none",target:null}),l=i(null),d=r(()=>{const t=n.value.type;return e.value&&"none"!==t?e.value.getRadialMenu(t).map(s=>{if("node"===t&&"pin"===s.action){const t=null!==n.value.target&&e.value?.isNodeLocked(n.value.target);return{...s,label:t?"Unlock":"Lock",icon:t?"lock-open":"lock"}}if("combo"===t&&"toggle-collapse"===s.action){const t=e.value?.getCombo(n.value.target)?.collapsed;return{...s,label:t?"Expand":"Collapse",icon:t?"maximize":"minimize"}}return s}):[]});return{contextMenu:n,menuItems:d,handleContextMenu:i=>{const o=t.value?.getBoundingClientRect();if(!o||!e.value)return;const r=i.clientX-o.left,l=i.clientY-o.top,d=140;let c=i.clientX,h=i.clientY;const u=(a.value?380:0)+d,g=(null!==s.value?window.innerWidth-340:window.innerWidth)-d;c=Math.min(Math.max(c,u),g);const m=window.innerHeight-d;h=Math.min(Math.max(h,140),m);const v=e.value.pick(r,l);if(null!==v)return void(n.value={show:!0,x:c,y:h,type:"node",target:v});const f=e.value.getEdgeAt(r,l);if(f)return void(n.value={show:!0,x:c,y:h,type:"edge",target:f});const p=e.value.pickCombo(r,l);p?n.value={show:!0,x:c,y:h,type:"combo",target:p}:n.value.show=!1},handleMenuAction:(t,i)=>{if(!e.value)return;const a={"start-connect":()=>{l.value=n.value.target},delete:()=>{(o.value>1?e.value.getSelectedUserIds():[e.value.getNodeId(n.value.target)??n.value.target]).forEach(t=>e.value.removeNode(t)),s.value=null},pin:()=>{const t=e.value.getNodeId(n.value.target)??n.value.target;e.value.isNodeLocked(n.value.target)?e.value.unlockNode(t):e.value.lockNode(t)},color:()=>{const t=o.value>1?e.value.getSelectedUserIds():[e.value.getNodeId(n.value.target)??n.value.target],s=["#ff6b6b","#4ecdc4","#45b7d1","#f7dc6f","#bb8fce","#6bcb77"],i=s[Math.floor(Math.random()*s.length)],a=parseInt(i.slice(1,3),16)/255,r=parseInt(i.slice(3,5),16)/255,l=parseInt(i.slice(5,7),16)/255;t.forEach(t=>e.value.setNodeColor(t,a,r,l))},hide:()=>{"edge"===n.value.type&&n.value.target&&e.value.hideEdge(n.value.target)},reverse:()=>{"edge"===n.value.type&&n.value.target&&e.value.reverseEdge(n.value.target)},weight:()=>{alert("Weight adjustment coming soon!")},"delete-edge":()=>{n.value.target&&e.value.removeEdge(n.value.target)},"create-combo":()=>{const t=e.value.getSelectedUserIds();if(t.length<2){const s=e.value.getNodeId(n.value.target)??n.value.target;null!=s&&t.push(s)}if(0===t.length)return;const s=`group-${Date.now()}`;e.value.createGroup(s,`Group ${s.split("-")[1]}`,t),i.value++},"dissolve-combo":()=>{n.value.target&&(e.value.removeGroup(n.value.target),i.value--)},"toggle-collapse":()=>{n.value.target&&e.value.toggleComboCollapse(n.value.target)},"rename-group":()=>{const t=n.value.target,s=e.value.getCombo(t);if(s){const i=prompt("Enter new group name:",s.label);i&&e.value.updateCombo(t,i,Array.from(s.nodeIds).map(t=>e.value.getNodeId(t)??t))}},"add-to-group":()=>{const t=e.value.getSelectedUserIds();t.length>0&&n.value.target&&t.forEach(t=>e.value.addToGroup(n.value.target,t))}};a[t]&&a[t](),n.value.show=!1},connectingSourceId:l}}(f,s,$,W,L),ue=i(!1),ge=i(0),me=i({label:"relation",color:"#00ffcc",size:1.5}),ve=["#00ffcc","#ff00ff","#ffcc00","#ff4444","#ffffff","#44aaff"],fe=[{id:"random",name:"Random",icon:"dices"},{id:"grid",name:"Grid",icon:"layout-grid"},{id:"circle",name:"Circle",icon:"circle"},{id:"spiral",name:"Spiral",icon:"spiral"},{id:"concentric",name:"Concentric",icon:"target"},{id:"radial",name:"Radial",icon:"atom"},{id:"hierarchy",name:"Hierarchy",icon:"git-branch"},{id:"force",name:"Force",icon:"sparkles"}],pe=[{key:"Shift + Drag",action:"Box Selection"},{key:"Ctrl + Click",action:"Multi Selection"},{key:"Right Click",action:"Radial Menu"},{key:"Scroll",action:"Zoom In/Out"},{key:"Drag",action:"Pan View"}],be=()=>{ue.value=!ue.value,f.value&&f.value.setFlowAnimation(ue.value)},Me=e=>{oe(e),F.value=null},we=e=>{ce(e,ge)},ye=e=>{if(f.value){f.value.selectNode(e);const t=f.value.getNodePosition(e);t&&(f.value.setCameraCenter(t[0],t[1]),f.value.setCameraZoom(2))}_.value=!1};return o(()=>{if(s.value&&l.value){f.value=new S(s.value,l.value);const e=Y(t.data);f.value.setData(e.positions,e.colors,e.ids,e.metadata,e.edgeIndices,e.edgeMetadata,e.idMap),ne(e.count,e.positions,e.nodeRadii,e.edgeIndices);const i=()=>{re.value.show=!1},o=e=>{if(null!==he.value&&f.value&&s.value){const t=s.value.getBoundingClientRect(),i=e.clientX-t.left,o=e.clientY-t.top,a=window.devicePixelRatio,n=f.value.unproject(i*a,o*a);f.value.setPhantomEdge(he.value,n[0],n[1])}};window.addEventListener("mousedown",i),window.addEventListener("mousemove",o),n(he,e=>{null===e&&f.value&&f.value.clearPhantomEdge()}),a(()=>{window.removeEventListener("mousedown",i),window.removeEventListener("mousemove",o)}),s.value.addEventListener("graph:click",()=>{null!==he.value&&(he.value=null)}),s.value.addEventListener("node-selected",e=>{const t=e.detail;if(null!==he.value&&null!==t&&t!==he.value){const e=f.value.getNodeId(he.value),s=f.value.getNodeId(t);return e&&s&&f.value.addEdge({source:e,target:s,label:me.value.label,data:{customColor:me.value.color,customSize:me.value.size}}),he.value=null,void(me.value={label:"relation",color:"#00ffcc",size:1.5})}$.value=t,null!==$.value&&(j.value=null,O.value=null)}),s.value.addEventListener("edge-selected",e=>{const t=e.detail;j.value=t,null!==t&&($.value=null,O.value=null,te())}),s.value.addEventListener("combo-selected",e=>{O.value=e.detail,null!==O.value&&($.value=null,j.value=null)}),s.value.addEventListener("nodes-selected",e=>{W.value=e.detail.length}),s.value.addEventListener("node-moved",e=>{const t=e.detail;t.id===$.value&&(X.value=Number(t.x.toFixed(3)),H.value=Number(t.y.toFixed(3)))})}}),(e,t)=>(d(),c("div",{class:y(["container vortx-gl-root",C(x)])},[v("canvas",{ref_key:"canvasRef",ref:s,class:"main-canvas",onContextmenu:t[0]||(t[0]=g((...e)=>C(de)&&C(de)(...e),["prevent"]))},null,544),v("canvas",{ref_key:"overlayCanvasRef",ref:l,class:"overlay-canvas"},null,512),C(N)?(d(),c("div",Ue,[v("button",{class:y(["menu-btn",{active:"layouts"===C(F)}]),onClick:t[1]||(t[1]=e=>C(P)("layouts"))},[b(V,{name:"layout",size:"20"}),t[30]||(t[30]=v("span",null,"Layout",-1))],2),v("button",{class:y(["menu-btn",{active:"view"===C(F)}]),onClick:t[2]||(t[2]=e=>C(P)("view"))},[b(V,{name:"eye",size:"20"}),t[31]||(t[31]=v("span",null,"View",-1))],2),t[33]||(t[33]=v("div",{class:"menu-divider"},null,-1)),v("button",{class:"menu-btn search-trigger",onClick:t[3]||(t[3]=(...e)=>C(U)&&C(U)(...e))},[b(V,{name:"search",size:"20"}),t[32]||(t[32]=v("span",null,"Search",-1))])])):w("",!0),C(N)&&C(F)?(d(),c("div",{key:1,class:"drawer-overlay",onClick:t[10]||(t[10]=e=>F.value=null)},[v("div",{class:"mobile-drawer glass shadow-2xl",onClick:t[9]||(t[9]=g(()=>{},["stop"]))},[t[34]||(t[34]=v("div",{class:"drawer-handle"},null,-1)),v("div",ze,[v("h3",null,M("layouts"===C(F)?"Graph Layouts":"View Controls"),1),v("button",{class:"drawer-close",onClick:t[4]||(t[4]=e=>F.value=null)},[b(V,{name:"x",size:"20"})])]),"layouts"===C(F)?(d(),c("div",Ye,[b(se,{layouts:fe,currentLayout:C(ie),flowEnabled:ue.value,onRunLayout:Me,onToggleFlow:be},null,8,["currentLayout","flowEnabled"])])):w("",!0),"view"===C(F)?(d(),c("div",Ve,[b(q,{theme:C(x),flowEnabled:ue.value,onToggleTheme:C(T),onFit:t[5]||(t[5]=e=>f.value?.fitToView()),onZoomIn:t[6]||(t[6]=e=>f.value?.zoomIn()),onZoomOut:t[7]||(t[7]=e=>f.value?.zoomOut()),onStress:t[8]||(t[8]=e=>C(ae)(1e5))},null,8,["theme","flowEnabled","onToggleTheme"])])):w("",!0)])])):w("",!0),I(b(Pe,{ref:"searchBarRef",nodes:C(z),onSelect:ye},null,8,["nodes"]),[[R,!C(N)||C(_)]]),C(N)?w("",!0):(d(),c("div",$e,[b(q,{theme:C(x),flowEnabled:ue.value,onToggleTheme:C(T),onToggleFlow:be,onFit:t[11]||(t[11]=e=>f.value?.fitToView()),onZoomIn:t[12]||(t[12]=e=>f.value?.zoomIn()),onZoomOut:t[13]||(t[13]=e=>f.value?.zoomOut()),onStress:t[14]||(t[14]=e=>C(ae)(1e5))},null,8,["theme","flowEnabled","onToggleTheme"]),v("div",{class:"help-trigger glass-interactive",onClick:t[15]||(t[15]=e=>B.value=!0),title:"Keyboard Shortcuts"},[b(V,{name:"info",size:"18"})])])),b(G,{show:C(re).show,x:C(re).x,y:C(re).y,type:C(re).type,items:C(le),onAction:we},null,8,["show","x","y","type","items"]),b(ke,{nodeId:C($),"onUpdate:nodeId":t[16]||(t[16]=e=>k($)?$.value=e:null),nodeMetadata:C(Z),nodeX:C(X),"onUpdate:nodeX":t[17]||(t[17]=e=>k(X)?X.value=e:null),nodeY:C(H),"onUpdate:nodeY":t[18]||(t[18]=e=>k(H)?H.value=e:null),edgeId:C(j),"onUpdate:edgeId":t[19]||(t[19]=e=>k(j)?j.value=e:null),edgeMetadata:C(K),combo:C(J),"onUpdate:combo":t[20]||(t[20]=e=>k(J)?J.value=e:null),"onUpdate:comboLabel":C(Q),onRemoveFromCombo:C(ee)},null,8,["nodeId","nodeMetadata","nodeX","nodeY","edgeId","edgeMetadata","combo","onUpdate:comboLabel","onRemoveFromCombo"]),C(N)?(d(),c("div",{key:3,class:"help-trigger mobile help-trigger-pos glass-interactive",onClick:t[21]||(t[21]=e=>B.value=!0)},[b(V,{name:"info",size:"18"})])):w("",!0),C(B)?(d(),c("div",{key:4,class:"help-modal-overlay",onClick:t[24]||(t[24]=e=>B.value=!1)},[v("div",{class:"help-modal glass",onClick:t[23]||(t[23]=g(()=>{},["stop"]))},[v("div",je,[t[35]||(t[35]=v("h3",null,"Keyboard Shortcuts",-1)),v("button",{class:"close-btn",onClick:t[22]||(t[22]=e=>B.value=!1)},[b(V,{name:"x",size:"20"})])]),v("div",Oe,[(d(),c(h,null,u(pe,e=>v("div",{key:e.key,class:"shortcut-row"},[v("span",We,M(e.key),1),v("span",Ge,M(e.action),1)])),64))])])])):w("",!0),C(N)?w("",!0):(d(),p(se,{key:5,layouts:fe,currentLayout:C(ie),flowEnabled:ue.value,onRunLayout:C(oe),onToggleFlow:be},null,8,["currentLayout","flowEnabled","onRunLayout"])),null!==C(he)?(d(),c("div",Xe,[v("div",He,[b(V,{name:"link-2",size:"20",class:"pulse-icon"}),v("div",Ze,[I(v("input",{"onUpdate:modelValue":t[25]||(t[25]=e=>me.value.label=e),class:"vortx-input-sm",placeholder:"Label",onMousedown:t[26]||(t[26]=g(()=>{},["stop"]))},null,544),[[E,me.value.label]]),v("div",qe,[(d(),c(h,null,u(ve,e=>v("button",{key:e,class:"color-dot",style:m({backgroundColor:e,border:me.value.color===e?"2px solid white":"none"}),onClick:t=>me.value.color=e},null,12,Ke)),64))]),v("div",Je,[b(V,{name:"move-horizontal",size:"14",class:"dim"}),I(v("input",{"onUpdate:modelValue":t[27]||(t[27]=e=>me.value.size=e),type:"number",class:"vortx-input-sm narrow",placeholder:"Size",onMousedown:t[28]||(t[28]=g(()=>{},["stop"]))},null,544),[[E,me.value.size,void 0,{number:!0}]])])]),t[36]||(t[36]=v("div",{class:"divider-v"},null,-1)),t[37]||(t[37]=v("span",{class:"instruction-text"},"Click target node",-1))]),v("button",{class:"toast-cancel",onClick:t[29]||(t[29]=e=>he.value=null)},[b(V,{name:"x",size:"14"})])])):w("",!0)],2))}}),[["__scopeId","data-v-0b4073a8"]]),et=(e,t)=>({nodes:e,edges:t});export{Qe as GraphCanvas,S as GraphEngine,et as createGraphData};