UNPKG

ngraph.svg

Version:

SVG-based graph visualization library with adaptive rendering

1 lines 82 kB
(function(S,Y){typeof exports=="object"&&typeof module<"u"?Y(exports,require("ngraph.graph")):typeof define=="function"&&define.amd?define(["exports","ngraph.graph"],Y):(S=typeof globalThis<"u"?globalThis:S||self,Y(S.ngraphSvg={},S.createGraph))})(this,(function(S,Y){"use strict";var Qt=Object.defineProperty;var Jt=(S,Y,E)=>Y in S?Qt(S,Y,{enumerable:!0,configurable:!0,writable:!0,value:E}):S[Y]=E;var Ct=(S,Y,E)=>Jt(S,typeof Y!="symbol"?Y+"":Y,E);class E{constructor(){this.viewBox={left:-100,top:-100,right:100,bottom:100},this.transform={scale:1,x:0,y:0},this.width=0,this.height=0,this.pixelRatio=typeof window<"u"?window.devicePixelRatio:1,this._visibleBounds={left:0,top:0,right:0,bottom:0},this._visibleBoundsDirty=!0,this._reusableScenePoint={x:0,y:0},this._reusableScreenPoint={x:0,y:0}}setSize(t,e){this.width=t,this.height=e,this._visibleBoundsDirty=!0}setViewBox(t,e,s,i){this.viewBox.left=t,this.viewBox.top=e,this.viewBox.right=s,this.viewBox.bottom=i}setTransform(t,e,s){this.transform.scale=t,this.transform.x=e,this.transform.y=s,this._visibleBoundsDirty=!0}getNodeScreenSize(t){return t*this.transform.scale}screenToScene(t,e){const s=this._reusableScenePoint;return s.x=(t-this.transform.x)/this.transform.scale,s.y=(e-this.transform.y)/this.transform.scale,s}sceneToScreen(t,e){const s=this._reusableScreenPoint;return s.x=t*this.transform.scale+this.transform.x,s.y=e*this.transform.scale+this.transform.y,s}getVisibleBounds(){return this._updateVisibleBounds(),this._visibleBounds}_updateVisibleBounds(){if(this._visibleBoundsDirty){this._visibleBoundsDirty=!1;const t=this.transform.scale,e=this.transform.x,s=this.transform.y;this._visibleBounds.left=(0-e)/t,this._visibleBounds.top=(0-s)/t,this._visibleBounds.right=(this.width-e)/t,this._visibleBounds.bottom=(this.height-s)/t}}isVisible(t,e,s=0){this._updateVisibleBounds();const i=this._visibleBounds;return t+s>=i.left&&t-s<=i.right&&e+s>=i.top&&e-s<=i.bottom}getTransformString(){return`translate(${this.transform.x}, ${this.transform.y}) scale(${this.transform.scale})`}}function at(a,t){const{onPanStart:e,onPanMove:s,onPanEnd:i,onZoom:n}=t;let o=!1,h=0,l=0;const c=[];function r(d,m,_,y){d.addEventListener(m,_,y),c.push({target:d,event:m,handler:_,options:y})}function u(d){d.button===0&&(o=!0,h=d.clientX,l=d.clientY,e&&e({x:h,y:l,event:d}),d.preventDefault())}function p(d){if(!o)return;const m=d.clientX-h,_=d.clientY-l;h=d.clientX,l=d.clientY,s&&s({dx:m,dy:_,x:h,y:l,event:d})}function x(d){o&&(o=!1,i&&i({x:d.clientX,y:d.clientY,event:d}))}function g(d){d.preventDefault();let m=d.deltaY;d.deltaMode===1?m*=40:d.deltaMode===2&&(m*=800);const _=1-m*.003,y=a.getBoundingClientRect(),v=d.clientX-y.left,b=d.clientY-y.top;n&&n({factor:_,x:v,y:b,event:d})}function f(d){const m=a.getBoundingClientRect(),_=d.clientX-m.left,y=d.clientY-m.top;n&&n({factor:2,x:_,y,event:d})}return r(a,"mousedown",u),r(window,"mousemove",p),r(window,"mouseup",x),r(a,"wheel",g,{passive:!1}),r(a,"dblclick",f),{dispose(){for(const{target:d,event:m,handler:_,options:y}of c)d.removeEventListener(m,_,y);c.length=0}}}class St{constructor(t){this.id=t.identifier,this.x=t.clientX,this.y=t.clientY,this.lastX=this.x,this.lastY=this.y}move(t){this.lastX=this.x,this.lastY=this.y,this.x=t.clientX,this.y=t.clientY}}function ht(a,t){const{onPanStart:e,onPanMove:s,onPanEnd:i,onZoom:n}=t;let o=new Map,h=!1,l=0,c=0,r=null;a.addEventListener("touchstart",u,{passive:!1});function u(d){h||(g(),h=!0);for(let m=0;m<d.touches.length;m++){const _=d.touches[m];o.has(_.identifier)||o.set(_.identifier,new St(_))}if(d.touches.length===1){const m=d.touches[0];e&&e({x:m.clientX,y:m.clientY,event:d})}d.preventDefault(),d.stopPropagation()}function p(d){const m=Date.now();let _=0,y=0,v=0,b=0,C=null,w=null;for(let X=0;X<d.touches.length;X++){const D=d.touches[X],L=o.get(D.identifier);L&&(L.move(D),v+=L.x,b+=L.y,_+=L.x-L.lastX,y+=L.y-L.lastY,C?w||(w=L):C=L)}const P=d.touches.length;if(P===0)return;if(_/=P,y/=P,v/=P,b/=P,C&&w){c=m;const X=Math.hypot(w.x-C.x,w.y-C.y),D=Math.hypot(w.lastX-C.lastX,w.lastY-C.lastY);if(D>0){const L=X/D,st=a.getBoundingClientRect(),nt=v-st.left,U=b-st.top;n&&n({factor:L,x:nt,y:U,event:d})}d.preventDefault(),d.stopPropagation()}const I=m-c;d.touches.length===1&&I>100&&(_!==0||y!==0)&&s&&s({dx:_,dy:y,x:v,y:b,event:d})}function x(d){const m=Date.now(),_=m-l;l=m;for(let y=0;y<d.changedTouches.length;y++){const v=d.changedTouches[y];o.delete(v.identifier)}if(d.touches.length===0){if(o.clear(),h=!1,f(),d.changedTouches.length===1&&m-c>350){const y=d.changedTouches[0];if(_<350&&r&&Math.hypot(y.clientX-r.clientX,y.clientY-r.clientY)<30){const b=a.getBoundingClientRect(),C=y.clientX-b.left,w=y.clientY-b.top;n&&n({factor:2,x:C,y:w,event:d})}r={clientX:y.clientX,clientY:y.clientY}}i&&i({x:0,y:0,event:d})}}function g(){document.addEventListener("touchmove",p,{passive:!1}),document.addEventListener("touchend",x,{passive:!1}),document.addEventListener("touchcancel",x,{passive:!1})}function f(){document.removeEventListener("touchmove",p,{passive:!1}),document.removeEventListener("touchend",x,{passive:!1}),document.removeEventListener("touchcancel",x,{passive:!1})}return{dispose(){a.removeEventListener("touchstart",u,{passive:!1}),f(),o.clear()}}}function rt(a={}){const{friction:t=.92,minVelocity:e=.5,onUpdate:s=()=>{}}=a;let i=0,n=0,o=0,h=null,l=!1;const c=[],r=5;function u(g,f){const d=performance.now();for(c.push({dx:g,dy:f,time:d});c.length>r;)c.shift()}function p(){if(c.length<2)return{vx:0,vy:0};let g=0,f=0,d=0;for(let m=1;m<c.length;m++){const _=c[m].time-c[m-1].time;_>0&&(g+=c[m].dx,f+=c[m].dy,d+=_)}return d===0?{vx:0,vy:0}:{vx:g/d*16,vy:f/d*16}}function x(){h=null;const g=performance.now(),f=Math.min(g-o,32);o=g;const d=f/16,m=Math.pow(t,d);if(i*=m,n*=m,Math.sqrt(i*i+n*n)<e){i=0,n=0;return}s(i*d,n*d),h=requestAnimationFrame(x)}return{startTracking(){l=!0,c.length=0,this.stop()},track(g,f){l&&u(g,f)},release(){l=!1;const{vx:g,vy:f}=p();i=g,n=f,c.length=0,Math.sqrt(i*i+n*n)>=e&&(o=performance.now(),h=requestAnimationFrame(x))},stop(){h!==null&&(cancelAnimationFrame(h),h=null),i=0,n=0},isAnimating(){return h!==null},dispose(){this.stop(),c.length=0}}}function lt(a,t,e={}){const{onTransform:s=()=>{}}=e;let i=e.minZoom||.1,n=e.maxZoom||20,o=null,h=null,l=null,c=null,r=null;function u(f,d){const{x:m,y:_,scale:y}=t.transform;t.setTransform(y,m+f,_+d),s()}function p(f,d,m){const{x:_,y,scale:v}=t.transform;let b=v*f;if(b=Math.max(i,Math.min(n,b)),b===v)return;const C=b/v,w=d-(d-_)*C,P=m-(m-y)*C;t.setTransform(b,w,P),s()}l=rt({onUpdate(f,d){u(f,d)}});const x={onPanStart(){l.startTracking()},onPanMove({dx:f,dy:d}){u(f,d),l.track(f,d)},onPanEnd(){l.release()},onZoom({factor:f,x:d,y:m}){p(f,d,m)}};o=at(a,x),h=ht(a,x);function g(){c!==null&&(cancelAnimationFrame(c),c=null),r&&(r(),r=null)}return{setZoomLimits(f,d){i=f,n=d},getZoom(){return t.transform.scale},setZoom(f,d=!1){if(d){const y=(t.width/2-t.transform.x)/t.transform.scale,v=(t.height/2-t.transform.y)/t.transform.scale;return this.flyTo(y,v,f)}const{width:m,height:_}=t;p(f/t.transform.scale,m/2,_/2)},pan(f,d){u(f,d)},flyTo(f,d,m,_=300){return new Promise(y=>{l.stop(),g(),r=y;const v=t.transform.x,b=t.transform.y,C=t.transform.scale,w=Math.max(i,Math.min(n,m)),{width:P,height:I}=t,z=P/2-f*w,X=I/2-d*w,D=performance.now();function L(){const nt=performance.now()-D,U=Math.min(nt/_,1),ot=1-Math.pow(1-U,3),Ut=v+(z-v)*ot,Kt=b+(X-b)*ot,jt=C+(w-C)*ot;t.setTransform(jt,Ut,Kt),s(),U<1?c=requestAnimationFrame(L):(c=null,r=null,y())}c=requestAnimationFrame(L)})},stop(){l.stop(),g()},dispose(){g(),o&&(o.dispose(),o=null),h&&(h.dispose(),h=null),l&&(l.dispose(),l=null)}}}const ct="http://www.w3.org/2000/svg";function wt(a,t={}){const{viewBox:e={left:-100,top:-100,right:100,bottom:100},panZoom:s={}}=t,i=document.createElementNS(ct,"svg");i.style.position="relative",i.style.width="100%",i.style.height="100%",i.style.display="block",i.style.overflow="hidden",a.appendChild(i);const n=document.createElementNS(ct,"g");n.setAttribute("class","scene-transform"),i.appendChild(n);const o=new E;o.setViewBox(e.left,e.top,e.right,e.bottom);const h=[],l={render:[],transform:[],resize:[]};let c=null,r=!0;function u(){const _=a.getBoundingClientRect();o.setSize(_.width,_.height);const y=e.right-e.left,v=e.bottom-e.top,b=_.width/y,C=_.height/v,w=Math.min(b,C),P=_.width/2,I=_.height/2,z=(e.left+e.right)/2,X=(e.top+e.bottom)/2;o.setTransform(w,P-z*w,I-X*w),p("resize",{width:_.width,height:_.height}),g()}function p(_,y){const v=l[_];if(v)for(let b=0;b<v.length;b++)v[b](y)}function x(){if(c=null,!!r){r=!1,n.setAttribute("transform",o.getTransformString());for(let _=0;_<h.length;_++)h[_].render(o);p("render",o)}}function g(){r=!0,c===null&&(c=requestAnimationFrame(x))}let f=null;s.enabled!==!1&&(f=lt(i,o,{minZoom:s.minZoom||.1,maxZoom:s.maxZoom||20,onTransform:()=>{p("transform",o.transform),g()}}));const d=new ResizeObserver(()=>{u()});d.observe(a),u();const m={svg:i,root:n,drawContext:o,addCollection(_){h.push(_);const y=_.getRoot();return y&&n.appendChild(y),g(),_},removeCollection(_){const y=h.indexOf(_);if(y!==-1){h.splice(y,1);const v=_.getRoot();v&&v.parentNode&&v.parentNode.removeChild(v),g()}},requestRender:g,on(_,y){return l[_]&&l[_].push(y),m},off(_,y){if(l[_]){const v=l[_].indexOf(y);v!==-1&&l[_].splice(v,1)}return m},getPanZoom(){return f},flyTo(_,y,v,b=300){return f?f.flyTo(_,y,v,b):Promise.resolve()},fitToView(_,y=20){const{width:v,height:b}=o,C=_.right-_.left,w=_.bottom-_.top,P=(v-y*2)/C,I=(b-y*2)/w,z=Math.min(P,I),X=(_.left+_.right)/2,D=(_.top+_.bottom)/2;return this.flyTo(X,D,z)},dispose(){c!==null&&(cancelAnimationFrame(c),c=null),d.disconnect(),f&&(f.dispose(),f=null);for(let _=0;_<h.length;_++)h[_].dispose&&h[_].dispose();h.length=0;for(const _ in l)l[_].length=0;i.parentNode&&i.parentNode.removeChild(i)}};return m}function Pt(a,t,e,s,i){dt(a,t,e||0,s||a.length-1,i||Lt)}function dt(a,t,e,s,i){for(;s>e;){if(s-e>600){var n=s-e+1,o=t-e+1,h=Math.log(n),l=.5*Math.exp(2*h/3),c=.5*Math.sqrt(h*l*(n-l)/n)*(o-n/2<0?-1:1),r=Math.max(e,Math.floor(t-o*l/n+c)),u=Math.min(s,Math.floor(t+(n-o)*l/n+c));dt(a,t,r,u,i)}var p=a[t],x=e,g=s;for(O(a,e,t),i(a[s],p)>0&&O(a,e,s);x<g;){for(O(a,x,g),x++,g--;i(a[x],p)<0;)x++;for(;i(a[g],p)>0;)g--}i(a[e],p)===0?O(a,e,g):(g++,O(a,g,s)),g<=t&&(e=g+1),t<=g&&(s=g-1)}}function O(a,t,e){var s=a[t];a[t]=a[e],a[e]=s}function Lt(a,t){return a<t?-1:a>t?1:0}class N{constructor(t=9){this._maxEntries=Math.max(4,t),this._minEntries=Math.max(2,Math.ceil(this._maxEntries*.4)),this.clear()}all(){return this._all(this.data,[])}search(t){let e=this.data;const s=[];if(!Z(t,e))return s;const i=this.toBBox,n=[];for(;e;){for(let o=0;o<e.children.length;o++){const h=e.children[o],l=e.leaf?i(h):h;Z(t,l)&&(e.leaf?s.push(h):j(t,l)?this._all(h,s):n.push(h))}e=n.pop()}return s}collides(t){let e=this.data;if(!Z(t,e))return!1;const s=[];for(;e;){for(let i=0;i<e.children.length;i++){const n=e.children[i],o=e.leaf?this.toBBox(n):n;if(Z(t,o)){if(e.leaf||j(t,o))return!0;s.push(n)}}e=s.pop()}return!1}load(t){if(!(t&&t.length))return this;if(t.length<this._minEntries){for(let s=0;s<t.length;s++)this.insert(t[s]);return this}let e=this._build(t.slice(),0,t.length-1,0);if(!this.data.children.length)this.data=e;else if(this.data.height===e.height)this._splitRoot(this.data,e);else{if(this.data.height<e.height){const s=this.data;this.data=e,e=s}this._insert(e,this.data.height-e.height-1,!0)}return this}insert(t){return t&&this._insert(t,this.data.height-1),this}clear(){return this.data=k([]),this}remove(t,e){if(!t)return this;let s=this.data;const i=this.toBBox(t),n=[],o=[];let h,l,c;for(;s||n.length;){if(s||(s=n.pop(),l=n[n.length-1],h=o.pop(),c=!0),s.leaf){const r=Yt(t,s.children,e);if(r!==-1)return s.children.splice(r,1),n.push(s),this._condense(n),this}!c&&!s.leaf&&j(s,i)?(n.push(s),o.push(h),h=0,l=s,s=s.children[0]):l?(h++,s=l.children[h],c=!1):s=null}return this}toBBox(t){return t}compareMinX(t,e){return t.minX-e.minX}compareMinY(t,e){return t.minY-e.minY}toJSON(){return this.data}fromJSON(t){return this.data=t,this}_all(t,e){const s=[];for(;t;)t.leaf?e.push(...t.children):s.push(...t.children),t=s.pop();return e}_build(t,e,s,i){const n=s-e+1;let o=this._maxEntries,h;if(n<=o)return h=k(t.slice(e,s+1)),A(h,this.toBBox),h;i||(i=Math.ceil(Math.log(n)/Math.log(o)),o=Math.ceil(n/Math.pow(o,i-1))),h=k([]),h.leaf=!1,h.height=i;const l=Math.ceil(n/o),c=l*Math.ceil(Math.sqrt(o));ft(t,e,s,c,this.compareMinX);for(let r=e;r<=s;r+=c){const u=Math.min(r+c-1,s);ft(t,r,u,l,this.compareMinY);for(let p=r;p<=u;p+=l){const x=Math.min(p+l-1,u);h.children.push(this._build(t,p,x,i-1))}}return A(h,this.toBBox),h}_chooseSubtree(t,e,s,i){for(;i.push(e),!(e.leaf||i.length-1===s);){let n=1/0,o=1/0,h;for(let l=0;l<e.children.length;l++){const c=e.children[l],r=K(c),u=Dt(t,c)-r;u<o?(o=u,n=r<n?r:n,h=c):u===o&&r<n&&(n=r,h=c)}e=h||e.children[0]}return e}_insert(t,e,s){const i=s?t:this.toBBox(t),n=[],o=this._chooseSubtree(i,this.data,e,n);for(o.children.push(t),F(o,i);e>=0&&n[e].children.length>this._maxEntries;)this._split(n,e),e--;this._adjustParentBBoxes(i,n,e)}_split(t,e){const s=t[e],i=s.children.length,n=this._minEntries;this._chooseSplitAxis(s,n,i);const o=this._chooseSplitIndex(s,n,i),h=k(s.children.splice(o,s.children.length-o));h.height=s.height,h.leaf=s.leaf,A(s,this.toBBox),A(h,this.toBBox),e?t[e-1].children.push(h):this._splitRoot(s,h)}_splitRoot(t,e){this.data=k([t,e]),this.data.height=t.height+1,this.data.leaf=!1,A(this.data,this.toBBox)}_chooseSplitIndex(t,e,s){let i,n=1/0,o=1/0;for(let h=e;h<=s-e;h++){const l=R(t,0,h,this.toBBox),c=R(t,h,s,this.toBBox),r=Tt(l,c),u=K(l)+K(c);r<n?(n=r,i=h,o=u<o?u:o):r===n&&u<o&&(o=u,i=h)}return i||s-e}_chooseSplitAxis(t,e,s){const i=t.leaf?this.compareMinX:Xt,n=t.leaf?this.compareMinY:It,o=this._allDistMargin(t,e,s,i),h=this._allDistMargin(t,e,s,n);o<h&&t.children.sort(i)}_allDistMargin(t,e,s,i){t.children.sort(i);const n=this.toBBox,o=R(t,0,e,n),h=R(t,s-e,s,n);let l=W(o)+W(h);for(let c=e;c<s-e;c++){const r=t.children[c];F(o,t.leaf?n(r):r),l+=W(o)}for(let c=s-e-1;c>=e;c--){const r=t.children[c];F(h,t.leaf?n(r):r),l+=W(h)}return l}_adjustParentBBoxes(t,e,s){for(let i=s;i>=0;i--)F(e[i],t)}_condense(t){for(let e=t.length-1,s;e>=0;e--)t[e].children.length===0?e>0?(s=t[e-1].children,s.splice(s.indexOf(t[e]),1)):this.clear():A(t[e],this.toBBox)}}function Yt(a,t,e){if(!e)return t.indexOf(a);for(let s=0;s<t.length;s++)if(e(a,t[s]))return s;return-1}function A(a,t){R(a,0,a.children.length,t,a)}function R(a,t,e,s,i){i||(i=k(null)),i.minX=1/0,i.minY=1/0,i.maxX=-1/0,i.maxY=-1/0;for(let n=t;n<e;n++){const o=a.children[n];F(i,a.leaf?s(o):o)}return i}function F(a,t){return a.minX=Math.min(a.minX,t.minX),a.minY=Math.min(a.minY,t.minY),a.maxX=Math.max(a.maxX,t.maxX),a.maxY=Math.max(a.maxY,t.maxY),a}function Xt(a,t){return a.minX-t.minX}function It(a,t){return a.minY-t.minY}function K(a){return(a.maxX-a.minX)*(a.maxY-a.minY)}function W(a){return a.maxX-a.minX+(a.maxY-a.minY)}function Dt(a,t){return(Math.max(t.maxX,a.maxX)-Math.min(t.minX,a.minX))*(Math.max(t.maxY,a.maxY)-Math.min(t.minY,a.minY))}function Tt(a,t){const e=Math.max(a.minX,t.minX),s=Math.max(a.minY,t.minY),i=Math.min(a.maxX,t.maxX),n=Math.min(a.maxY,t.maxY);return Math.max(0,i-e)*Math.max(0,n-s)}function j(a,t){return a.minX<=t.minX&&a.minY<=t.minY&&t.maxX<=a.maxX&&t.maxY<=a.maxY}function Z(a,t){return t.minX<=a.maxX&&t.minY<=a.maxY&&t.maxX>=a.minX&&t.maxY>=a.minY}function k(a){return{children:a,height:1,leaf:!0,minX:1/0,minY:1/0,maxX:-1/0,maxY:-1/0}}function ft(a,t,e,s,i){const n=[t,e];for(;n.length;){if(e=n.pop(),t=n.pop(),e-t<=s)continue;const o=t+Math.ceil((e-t)/s/2)*s;Pt(a,o,t,e,i),n.push(t,o,o,e)}}class Et{constructor(t){this._svg=t,this._elements=new Map,this._restoreTimer=0,this._onSvgWheel=this._handleSvgWheel.bind(this),this._svg.addEventListener("wheel",this._onSvgWheel),this._container=this._createContainer(),this._injectStyle()}_createContainer(){const t=document.createElement("div");t.style.position="absolute",t.style.top="0",t.style.left="0",t.style.width="0",t.style.height="0",t.style.transformOrigin="0 0",t.style.pointerEvents="none";const e=this._svg.parentNode;return e&&(getComputedStyle(e).position==="static"&&(e.style.position="relative"),e.insertBefore(t,this._svg.nextSibling)),t}_injectStyle(){if(document.getElementById("dom-overlay-style"))return;const t=document.createElement("style");t.id="dom-overlay-style",t.textContent=".dom-overlay--suppressed > * { pointer-events: none !important; }",document.head.appendChild(t)}_handleSvgWheel(){this._container.classList.add("dom-overlay--suppressed"),clearTimeout(this._restoreTimer),this._restoreTimer=setTimeout(()=>{this._container.classList.remove("dom-overlay--suppressed")},150)}syncTransform(t){const e=t.transform;this._container.style.transform=`translate(${e.x}px,${e.y}px) scale(${e.scale})`}ensureElement(t,e,s,i){let n=this._elements.get(t);if(!n){const o=i(e,s);o.style.position="absolute",o.style.left="0",o.style.top="0",o.style.transformOrigin="0 0",o.style.pointerEvents="none",n={el:o,attached:!1,stateVersion:-1},this._elements.set(t,n)}return n}updateState(t,e,s,i,n){const o=this._elements.get(t);!o||o.stateVersion===n||(o.stateVersion=n,i(e,s,o.el))}setPosition(t,e,s,i,n,o){const h=this._elements.get(t);if(h){const l=e-(n||0)*i,c=s-(o||0)*i;h.el.style.transform=`translate(${l}px,${c}px) scale(${i})`}}attach(t){const e=this._elements.get(t);e&&!e.attached&&(this._container.appendChild(e.el),e.attached=!0)}detach(t){const e=this._elements.get(t);e&&e.attached&&(this._container.removeChild(e.el),e.attached=!1)}remove(t){const e=this._elements.get(t);e&&(e.attached&&e.el.parentNode&&e.el.parentNode.removeChild(e.el),this._elements.delete(t))}dispose(){clearTimeout(this._restoreTimer),this._svg.removeEventListener("wheel",this._onSvgWheel),this._container&&this._container.parentNode&&this._container.parentNode.removeChild(this._container),this._elements.clear(),this._container=null}}const _t="http://www.w3.org/2000/svg";function M(a,t,e){return typeof a=="function"?a(t,e):a}function Q(a){return a?String(a).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;"):""}function Bt(a){let t;if(a.type&&!a.layers){const{minZoom:i,maxZoom:n,importance:o,hitArea:h,...l}=a;t={minZoom:i||0,maxZoom:n,importance:o,hitArea:h,layers:[l]}}else t={minZoom:a.minZoom||0,maxZoom:a.maxZoom,importance:a.importance,hitArea:a.hitArea,layers:a.layers||[]};const e=t.layers.find(i=>i.type==="dom");e&&(t._domLayer=e);const s=t.layers.find(i=>i.type==="svg"&&i.update);return s&&(t._svgUpdate=s.update),t}function Nt(a,t,e){if(a.visible!==void 0&&!M(a.visible,t,e))return"";const s=a.type;if(s==="circle"){const i=M(a.radius,t,e)||4,n=M(a.fill,t,e)||"none",o=M(a.stroke,t,e)||"none",h=M(a.strokeWidth,t,e)||0,l=M(a.opacity,t,e),c=M(a.filter,t,e);let r=`r="${i}" fill="${n}"`;return o!=="none"&&(r+=` stroke="${o}"`),h&&(r+=` stroke-width="${h}"`),l!=null&&(r+=` opacity="${l}"`),c&&(r+=` filter="${c}"`),`<circle ${r}/>`}if(s==="rect"){const i=M(a.width,t,e)||10,n=M(a.height,t,e)||10,o=M(a.rx,t,e),h=M(a.ry,t,e),l=M(a.fill,t,e)||"none",c=M(a.stroke,t,e)||"none",r=M(a.strokeWidth,t,e)||0,u=M(a.opacity,t,e),p=M(a.filter,t,e);let x=`x="${-i/2}" y="${-n/2}" width="${i}" height="${n}" fill="${l}"`;return o!=null&&(x+=` rx="${o}"`),h!=null&&(x+=` ry="${h}"`),c!=="none"&&(x+=` stroke="${c}"`),r&&(x+=` stroke-width="${r}"`),u!=null&&(x+=` opacity="${u}"`),p&&(x+=` filter="${p}"`),`<rect ${x}/>`}if(s==="text"){const i=M(a.text,t,e);if(i==null||i==="")return"";const n=M(a.fontSize,t,e)||10,o=M(a.fill,t,e)||"#000",h=M(a.fontFamily,t,e),l=M(a.fontWeight,t,e),c=M(a.anchor,t,e)||"center",r=M(a.offset,t,e)||[0,0],u=M(a.opacity,t,e),p=M(a.maxWidth,t,e);let x="middle",g=r[0],f=r[1];c==="center"&&(f+=n*.35);let d=`x="${g}" y="${f}" text-anchor="${x}" font-size="${n}" fill="${o}"`;h&&(d+=` font-family="${h}"`),l&&(d+=` font-weight="${l}"`),u!=null&&(d+=` opacity="${u}"`);const m=String(i);if(p&&m.length*n*.6>p){const _=ut(m,n,p),y=n*1.3;let v="";for(let b=0;b<_.length;b++)b===0?v+=`<tspan x="${g}">${Q(_[b])}</tspan>`:v+=`<tspan x="${g}" dy="${y}">${Q(_[b])}</tspan>`;return`<text ${d}>${v}</text>`}return`<text ${d}>${Q(m)}</text>`}return s==="svg"&&typeof a.create=="function"&&a.create(t,e)||""}function ut(a,t,e){const s=t*.6,i=Math.max(1,Math.floor(e/s)),n=a.split(/\s+/),o=[];let h="";for(let l=0;l<n.length;l++){const c=n[l],r=h?h+" "+c:c;r.length>i&&h?(o.push(h),h=c):h=r}return h&&o.push(h),o}function q(a,t,e){const s=a.layers;if(!s||s.length===0)return"";let i="";for(let n=0;n<s.length;n++)i+=Nt(s[n],t,e);return i}function J(a,t,e){const s=a.layers;let i=0,n=0;for(let o=0;o<s.length;o++){const h=s[o];if(h.visible!==void 0&&!M(h.visible,t,e))continue;const l=h.type;if(l==="circle"){const r=(M(h.radius,t,e)||4)*2;r>i&&(i=r),r>n&&(n=r)}else if(l==="rect"){const c=M(h.width,t,e)||10,r=M(h.height,t,e)||10;c>i&&(i=c),r>n&&(n=r)}else if(l==="svg"){const c=M(h.width,t,e),r=M(h.height,t,e);c&&c>i&&(i=c),r&&r>n&&(n=r)}else if(l==="dom"){const c=M(h.width,t,e)||0,r=M(h.height,t,e)||0;c>i&&(i=c),r>n&&(n=r)}else if(l==="text"){const c=M(h.text,t,e);if(!c)continue;const r=M(h.fontSize,t,e)||10,u=M(h.offset,t,e)||[0,0],p=M(h.maxWidth,t,e),x=String(c);let g,f;if(p&&x.length*r*.6>p){const d=ut(x,r,p);g=p+Math.abs(u[0])*2,f=d.length*r*1.3+Math.abs(u[1])}else g=x.length*r*.6+Math.abs(u[0])*2,f=r+Math.abs(u[1]);g>i&&(i=g),n+=f}}if(a.hitArea){const o=a.hitArea;o.type==="rect"&&(i=M(o.width,t,e)||i,n=M(o.height,t,e)||n)}return{width:i,height:n}}function At(a,t,e){const s=a.layers;for(let i=0;i<s.length;i++){const n=s[i];if(n.type==="circle")return{type:"circle",radius:M(n.radius,t,e)||4};if(n.type==="rect")return{type:"rect",width:M(n.width,t,e)||10,height:M(n.height,t,e)||10}}return null}class kt{constructor(t={}){Ct(this,"_transitionRafId",null);this._dataFn=t.data||null,this._maxScale=t.maxScale??1,this._levels=(t.levels||[]).map(Bt),this._collisionTrees=new Map,this._spatialIndex=new N,this._spatialValid=!1,this._positionsDirty=!0,this._attachedNodes=new Set,this._swapAttachedSet=new Set,this._maxNodeSize=0,this._root=document.createElementNS(_t,"g"),this._root.setAttribute("class","node-collection"),this._nodes=[],this._nodeMap=new Map,this._freeIndices=[],this._batchDepth=0,this._batchDirty=!1,this._elementPool=[],this._lastDrawContext=null,this._lastScale=1,this._lastCollisionZoom=0,this._lastCandidateLevel=void 0,this._state=new Map,this._resolvedLevels=new Map,this._prevResolvedLevels=new Map,this._transitions=new Map,this._transitionDuration=150,this._reusableCtx={zoom:1},this._reusableCtxKeys=[],this._collisionInterval=t.collisionInterval??200,this._lastCollisionTime=0,this._collisionNodes=[],this._collisionCandidates=[],this._collisionStable=[],this._hasDomLayers=this._levels.some(e=>e._domLayer),this._domOverlay=null,this._graph=t.graph||null,this._graphChangeListener=null,this._graph&&this._dataFn&&this._bindGraph()}getRoot(){return this._root}add(t){const{id:e=this._generateId(),x:s=0,y:i=0,data:n={}}=t,o=this._computeNodeSize(n);let h;this._freeIndices.length>0?h=this._freeIndices.pop():h=this._nodes.length;const l={id:e,index:h,x:s,y:i,size:o,data:n,visible:!0,_element:null,_currentLevel:-1,_inDOM:!1,_collection:this,_stateVersion:0,_renderedLevel:-1,_renderedStateVersion:-1};return this._nodes[h]=l,this._nodeMap.set(e,l),o>this._maxNodeSize&&(this._maxNodeSize=o),this._createNodeElement(l),this._spatialValid=!1,this._batchDepth===0?this._addNodeToScene(l,this._lastDrawContext):this._batchDirty=!0,l}remove(t){const e=typeof t=="object"?t:this._nodeMap.get(t);e&&(e._element&&(e._inDOM&&(this._root.removeChild(e._element),e._inDOM=!1),this._elementPool.push(e._element),e._element=null),this._domOverlay&&this._domOverlay.remove(e.id),this._freeIndices.push(e.index),this._nodes[e.index]=null,this._nodeMap.delete(e.id),this._attachedNodes.delete(e),this._state.delete(e.id),this._resolvedLevels.delete(e.id),this._prevResolvedLevels.delete(e.id),this._transitions.delete(e.id),this._spatialValid=!1,this._batchDepth>0&&(this._batchDirty=!0))}get(t){return this._nodeMap.get(t)}setPosition(t,e,s){t.x=e,t.y=s,this._positionsDirty=!0,this._batchDepth===0&&t._element&&t._inDOM&&this._applyTransform(t)}_applyTransform(t){if(!t._element)return;const e=Math.min(1,this._maxScale/this._lastScale);e!==1?t._element.setAttribute("transform",`translate(${t.x}, ${t.y}) scale(${e})`):t._element.setAttribute("transform",`translate(${t.x}, ${t.y})`)}setState(t,e,s){const i=typeof t=="object"?t.id:t;let n=this._state.get(i);s?(n||(n=new Map,this._state.set(i,n)),n.set(e,!0)):n&&(n.delete(e),n.size===0&&this._state.delete(i));const o=this._nodeMap.get(i);o&&(o._stateVersion++,o._element&&(s?o._element.classList.add(e):o._element.classList.remove(e)))}getState(t,e){const s=typeof t=="object"?t.id:t,i=this._state.get(s);return i&&i.get(e)||!1}invalidateContent(){for(const t of this._nodeMap.values())t._stateVersion++}clearState(t){for(const[e,s]of this._state)if(s.has(t)){s.delete(t),s.size===0&&this._state.delete(e);const i=this._nodeMap.get(e);i&&(i._stateVersion++,i._element&&i._element.classList.remove(t))}}_reapplyState(t){if(!t._element)return;t._element.setAttribute("class","node");const e=this._state.get(t.id);if(e)for(const s of e.keys())t._element.classList.add(s)}_buildCtx(t){const e=this._reusableCtx,s=this._reusableCtxKeys;for(let n=0;n<s.length;n++)e[s[n]]=void 0;s.length=0,e.zoom=this._lastScale;const i=this._state.get(t);if(i)for(const[n,o]of i)e[n]=o,s.push(n);return e}getNodeShape(t){const e=this._nodeMap.get(t);if(!e)return null;const s=this._resolvedLevels.get(t)??0;if(s<0||s>=this._levels.length)return null;const i=this._levels[s],n=this._buildCtx(t),o=At(i,e.data,n);if(!o)return null;const h=Math.min(1,this._maxScale/this._lastScale);return o.type==="circle"?{type:"circle",radius:o.radius*h,x:e.x,y:e.y}:o.type==="rect"?{type:"rect",width:o.width*h,height:o.height*h,x:e.x,y:e.y}:null}getContentScale(){return Math.min(1,this._maxScale/this._lastScale)}syncPositions(t){this.beginBatch();for(const[e,s]of t){const i=this._nodeMap.get(e);i&&(i.x=s.x,i.y=s.y,i.visible||(i.visible=!0))}for(let e=0;e<this._nodes.length;e++){const s=this._nodes[e];s&&s.visible&&!t.has(s.id)&&(s.visible=!1)}this._positionsDirty=!0,this.endBatch()}getNodeAt(t,e,s){if(s||(s=this._lastDrawContext),!s)return null;const i=s.screenToScene(t,e),n=Math.max(this._maxNodeSize,80/this._lastScale);this._spatialValid||(this._rebuildSpatialIndex(),this._spatialValid=!0);const o=this._spatialIndex.search({minX:i.x-n,minY:i.y-n,maxX:i.x+n,maxY:i.y+n});let h=null,l=1/0;const c=Math.min(1,this._maxScale/this._lastScale),r=10/this._lastScale;for(let u=0;u<o.length;u++){const p=o[u].node,x=i.x-p.x,g=i.y-p.y,f=x*x+g*g;let d=!1;if(this._levels.length>0){const m=this._resolvedLevels.get(p.id)??0;if(m>=0&&m<this._levels.length){const _=this._levels[m],y=this._buildCtx(p.id),v=J(_,p.data,y),b=Math.max(v.width*c/2,r),C=Math.max(v.height*c/2,r);d=Math.abs(x)<=b&&Math.abs(g)<=C}}if(!d){const m=this.getNodeShape(p.id);if(m&&m.type==="circle"){const _=Math.max(m.radius,r);d=f<=_*_}else if(m&&m.type==="rect"){const _=Math.max(m.width/2,r),y=Math.max(m.height/2,r);d=Math.abs(x)<=_&&Math.abs(g)<=y}else{const _=Math.max(r,p.size*.5);d=f<=_*_}}d&&f<l&&(l=f,h=p)}return h?h.id:null}beginBatch(){this._batchDepth++}endBatch(){this._batchDepth>0&&this._batchDepth--,this._batchDepth===0&&this._batchDirty&&(this._batchDirty=!1,this.render(this._lastDrawContext))}forEach(t){for(let e=0;e<this._nodes.length;e++){const s=this._nodes[e];s&&t(s,s.id)}}get count(){return this._nodeMap.size}render(t){if(this._lastDrawContext=t,!t)return;const e=t.transform.scale,s=e!==this._lastScale;this._lastScale=e;const i=performance.now(),n=this._getCandidateLevelIndex(e),o=this._lastCandidateLevel!==void 0&&n!==this._lastCandidateLevel;this._lastCandidateLevel=n;const h=this._lastCollisionZoom>0?e/this._lastCollisionZoom:1/0,l=h>1.2,c=h<.83;if(o||c||this._positionsDirty&&i-this._lastCollisionTime>=this._collisionInterval?(this._computeResolvedLevels(t,!1),this._lastCollisionTime=i,this._lastCollisionZoom=e):l&&(this._computeResolvedLevels(t,!0),this._lastCollisionTime=i,this._lastCollisionZoom=e),this._hasDomLayers&&!this._domOverlay){const r=this._root.ownerSVGElement;r&&(this._domOverlay=new Et(r))}this._domOverlay&&this._domOverlay.syncTransform(t),this._positionsDirty?(this._positionsDirty=!1,this._spatialValid=!1,this._renderAllNodes(t,s)):(this._spatialValid||(this._rebuildSpatialIndex(),this._spatialValid=!0),this._renderWithSpatialQuery(t,s))}_computeResolvedLevels(t,e=!1){const s=this._lastScale,i=this._levels;if(i.length===0)return;const n=this._prevResolvedLevels;this._prevResolvedLevels=this._resolvedLevels,this._resolvedLevels=n,this._resolvedLevels.clear();const o=this._getCandidateLevelIndex(s),h=this._collisionNodes;h.length=0;for(let f=0;f<this._nodes.length;f++){const d=this._nodes[f];if(!d||!d.visible)continue;const m=Math.max(d.size,50/s);t.isVisible(d.x,d.y,m)&&h.push(d)}const l=Math.min(1,this._maxScale/s),c=this._collisionCandidates,r=this._collisionStable,u=t.width/2,p=t.height/2,x=Math.hypot(u,p)||1,g={minX:0,minY:0,maxX:0,maxY:0};for(let f=o;f>=0;f--){const d=i[f];if(s<d.minZoom||d.maxZoom!==void 0&&s>=d.maxZoom)continue;if(!d.importance){for(let _=0;_<h.length;_++){const y=h[_];this._resolvedLevels.has(y.id)||this._resolvedLevels.set(y.id,f)}break}let m=this._collisionTrees.get(f);if(m?m.clear():(m=new N,this._collisionTrees.set(f,m)),e){r.length=0;for(let _=0;_<h.length;_++){const y=h[_];if(this._resolvedLevels.has(y.id)||this._prevResolvedLevels.get(y.id)!==f)continue;const v=this._buildCtx(y.id),b=t.sceneToScreen(y.x,y.y);v.centerProximity=1-Math.min(1,Math.hypot(b.x-u,b.y-p)/x);const C=M(d.importance,y.data,v);r.push(y,C||0)}this._sortPairs(r);for(let _=0;_<r.length;_+=2){const y=r[_];this._fillBbox(g,y,d,l,s,t),m.collides(g)||(m.insert({minX:g.minX,minY:g.minY,maxX:g.maxX,maxY:g.maxY}),this._resolvedLevels.set(y.id,f))}}c.length=0;for(let _=0;_<h.length;_++){const y=h[_];if(this._resolvedLevels.has(y.id))continue;const v=this._buildCtx(y.id),b=t.sceneToScreen(y.x,y.y);v.centerProximity=1-Math.min(1,Math.hypot(b.x-u,b.y-p)/x);const C=M(d.importance,y.data,v);c.push(y,C||0)}this._sortPairs(c);for(let _=0;_<c.length;_+=2){const y=c[_];this._fillBbox(g,y,d,l,s,t),m.collides(g)||(m.insert({minX:g.minX,minY:g.minY,maxX:g.maxX,maxY:g.maxY}),this._resolvedLevels.set(y.id,f))}}for(let f=0;f<h.length;f++){const d=h[f];this._resolvedLevels.has(d.id)||this._resolvedLevels.set(d.id,0)}}_getCandidateLevelIndex(t){const e=this._levels;let s=0;for(let i=0;i<e.length;i++)t>=e[i].minZoom&&(e[i].maxZoom===void 0||t<e[i].maxZoom)&&(s=i);return s}_renderAllNodes(t,e){this._attachedNodes.clear();for(let s=0;s<this._nodes.length;s++){const i=this._nodes[s];if(!i||!i._element)continue;const n=Math.max(i.size,50/this._lastScale);i.visible&&t.isVisible(i.x,i.y,n)?(i._inDOM||(this._root.appendChild(i._element),i._inDOM=!0,this._reapplyState(i)),this._applyTransform(i),this._updateNodeContent(i,t,e),this._attachedNodes.add(i)):(i._inDOM&&(this._root.removeChild(i._element),i._inDOM=!1),this._domOverlay&&this._domOverlay.detach(i.id))}}_renderWithSpatialQuery(t,e){const s=t.getVisibleBounds(),i=Math.max(this._maxNodeSize,100/this._lastScale),n=this._spatialIndex.search({minX:s.left-i,minY:s.top-i,maxX:s.right+i,maxY:s.bottom+i}),o=this._swapAttachedSet;o.clear();for(let h=0;h<n.length;h++){const l=n[h].node;if(!l._element)continue;const c=Math.max(l.size,50/this._lastScale);t.isVisible(l.x,l.y,c)&&(l._inDOM||(this._root.appendChild(l._element),l._inDOM=!0,this._reapplyState(l),this._applyTransform(l)),this._updateNodeContent(l,t,e),o.add(l))}for(const h of this._attachedNodes)o.has(h)||(h._inDOM&&(this._root.removeChild(h._element),h._inDOM=!1),this._domOverlay&&this._domOverlay.detach(h.id));this._swapAttachedSet=this._attachedNodes,this._attachedNodes=o}_rebuildSpatialIndex(){const t=[];for(const e of this._nodes)!e||!e.visible||t.push({minX:e.x,minY:e.y,maxX:e.x,maxY:e.y,node:e});this._spatialIndex.clear(),t.length>0&&this._spatialIndex.load(t)}_addNodeToScene(t,e){if(!t._element||!e)return;const s=Math.max(t.size,50/this._lastScale);e.isVisible(t.x,t.y,s)&&(t._inDOM||(this._root.appendChild(t._element),t._inDOM=!0,this._reapplyState(t),this._attachedNodes.add(t)),this._updateNodeContent(t,e))}_updateNodeContent(t,e,s=!1){if(!t._element||!e||(s&&this._applyTransform(t),this._levels.length===0))return;const i=this._resolvedLevels.get(t.id)??0;t._currentLevel!==i&&(t._currentLevel>=0&&this._transitions.set(t.id,{fromLevel:t._currentLevel,toLevel:i,startTime:performance.now()}),t._currentLevel=i),this._domOverlay&&this._syncDomLayer(t),!(!this._transitions.has(t.id)&&t._currentLevel===t._renderedLevel&&t._stateVersion===t._renderedStateVersion)&&(this._renderNode(t),t._renderedLevel=t._currentLevel,t._renderedStateVersion=t._stateVersion)}_syncDomLayer(t){const e=this._levels[t._currentLevel],s=e==null?void 0:e._domLayer;if(s){const i=t.data,n=this._buildCtx(t.id),o=this._domOverlay;o.ensureElement(t.id,i,n,s.create);const h=Math.min(1,this._maxScale/this._lastScale),l=M(s.width,i,n)/2||0,c=M(s.height,i,n)/2||0;o.setPosition(t.id,t.x,t.y,h,l,c),o.attach(t.id),s.update&&o.updateState(t.id,i,n,s.update,t._stateVersion)}else this._domOverlay.detach(t.id)}_renderNode(t){const e=this._levels,s=t._currentLevel;if(s<0||s>=e.length)return;const i=e[s],n=this._buildCtx(t.id),o=this._transitions.get(t.id);if(o){const h=performance.now()-o.startTime,l=Math.min(1,h/this._transitionDuration);if(l>=1){this._transitions.delete(t.id);const c=q(i,t.data,n);t._element.innerHTML=`<g>${c}</g>`}else{const c=e[o.fromLevel],r=e[o.toLevel],u=c?q(c,t.data,n):"",p=r?q(r,t.data,n):"";t._element.innerHTML=`<g opacity="${1-l}">${u}</g><g opacity="${l}">${p}</g>`,this._lastDrawContext&&this._scheduleTransitionFrame();return}}else if(t._renderedLevel===s&&i._svgUpdate)i._svgUpdate(t.data,n,t._element);else{const h=q(i,t.data,n);t._element.innerHTML=`<g>${h}</g>`}}_scheduleTransitionFrame(){this._transitionRafId||(this._transitionRafId=requestAnimationFrame(()=>{if(this._transitionRafId=null,this._transitions.size>0)for(const[t]of this._transitions){const e=this._nodeMap.get(t);e&&e._inDOM&&this._renderNode(e)}}))}_fillBbox(t,e,s,i,n,o){const h=this._buildCtx(e.id),l=J(s,e.data,h),c=o.sceneToScreen(e.x,e.y),r=l.width*i*n/2,u=l.height*i*n/2;t.minX=c.x-r,t.minY=c.y-u,t.maxX=c.x+r,t.maxY=c.y+u}_sortPairs(t){const e=t.length>>1;if(!(e<=1))for(let s=1;s<e;s++){const i=t[s*2],n=t[s*2+1];let o=s-1;for(;o>=0&&t[o*2+1]<n;)t[(o+1)*2]=t[o*2],t[(o+1)*2+1]=t[o*2+1],o--;t[(o+1)*2]=i,t[(o+1)*2+1]=n}}clear(){for(let t=0;t<this._nodes.length;t++){const e=this._nodes[t];e&&this.remove(e)}this._nodes.length=0,this._freeIndices.length=0,this._nodeMap.clear(),this._attachedNodes.clear(),this._swapAttachedSet.clear(),this._spatialIndex.clear(),this._spatialValid=!1,this._maxNodeSize=0,this._state.clear(),this._resolvedLevels.clear(),this._prevResolvedLevels.clear(),this._transitions.clear(),this._collisionTrees.clear(),this._lastCollisionZoom=0,this._lastCandidateLevel=void 0}dispose(){this._graph&&this._graphChangeListener&&(this._graph.off("changed",this._graphChangeListener),this._graphChangeListener=null),this._transitionRafId&&(cancelAnimationFrame(this._transitionRafId),this._transitionRafId=null),this.clear(),this._elementPool.length=0,this._root.parentNode&&this._root.parentNode.removeChild(this._root),this._domOverlay&&(this._domOverlay.dispose(),this._domOverlay=null)}_generateId(){return`node_${Date.now()}_${Math.random().toString(36).slice(2,9)}`}_computeNodeSize(t){const e=this._levels;if(e.length===0)return 10;let s=0;const i={zoom:1};for(let n=0;n<e.length;n++){const o=J(e[n],t,i),h=Math.max(o.width,o.height);h>s&&(s=h)}return s||10}_createNodeElement(t){let e=this._elementPool.pop();e||(e=document.createElementNS(_t,"g")),e.setAttribute("class","node"),e.innerHTML="",t._element=e}_bindGraph(){const t=this._graph;this.beginBatch(),t.forEachNode(e=>{const s=this._dataFn(e);this.add({id:e.id,data:s})}),this.endBatch(),this._graphChangeListener=e=>{this.beginBatch();for(let s=0;s<e.length;s++){const i=e[s];if(i.node)if(i.changeType==="add"){if(!this._nodeMap.has(i.node.id)){const n=this._dataFn(i.node);this.add({id:i.node.id,data:n})}}else i.changeType==="remove"&&this.remove(i.node.id)}this.endBatch()},t.on("changed",this._graphChangeListener)}}function mt(a,t,e){return{x:a*e,y:t*e}}function pt(a,t,e,s){const i=Math.abs(a)||1e-10,n=Math.abs(t)||1e-10,o=e/i,h=s/n,l=Math.min(o,h);return{x:a*l,y:t*l}}function B(a,t,e){return e.type==="circle"?mt(a,t,e.radius):e.type==="rect"?pt(a,t,e.width/2,e.height/2):{x:0,y:0}}const V="http://www.w3.org/2000/svg";function tt(a,t,e){return typeof a=="function"?a(t,e):a}class zt{constructor(t={}){this._colorProp=t.color||"#999",this._widthProp=t.width||1,this._opacityProp=t.opacity||.6,this._directed=t.directed||!1,this._dataFn=t.data||null,this._spatialIndex=new N,this._spatialValid=!1,this._positionsDirty=!0,this._attachedEdges=new Set,this._swapAttachedSet=new Set,this._root=document.createElementNS(V,"g"),this._root.setAttribute("class","edge-collection"),this._edges=[],this._edgeMap=new Map,this._freeIndices=[],this._batchDepth=0,this._batchDirty=!1,this._elementPool=[],this._lastDrawContext=null,this._lastScale=-1,this._state=new Map,this._stateVersion=0,this._arrowLength=t.arrowLength||10,this._arrowWidth=t.arrowWidth||5,this._markerElement=null,this._markerId=null,this._defs=null,this._graph=t.graph||null,this._nodeCollection=t.nodeCollection||null,this._graphChangeListener=null,this._cachedDirections=new Map,this._reusableCtx={zoom:1},this._reusableCtxKeys=[],this._graph&&this._bindGraph()}getRoot(){return this._root}add(t){const{id:e=this._generateId(),fromX:s=0,fromY:i=0,toX:n=0,toY:o=0,data:h={}}=t;let l;this._freeIndices.length>0?l=this._freeIndices.pop():l=this._edges.length;const c={id:e,index:l,fromX:s,fromY:i,toX:n,toY:o,data:h,visible:!0,_element:null,_inDOM:!1,_collection:this};return this._edges[l]=c,this._edgeMap.set(e,c),this._createEdgeElement(c),this._spatialValid=!1,this._batchDepth===0?this._addEdgeToScene(c,this._lastDrawContext):this._batchDirty=!0,c}remove(t){const e=typeof t=="object"?t:this._edgeMap.get(t);e&&(e._element&&(e._inDOM&&(this._root.removeChild(e._element),e._inDOM=!1),this._elementPool.push(e._element),e._element=null),this._freeIndices.push(e.index),this._edges[e.index]=null,this._edgeMap.delete(e.id),this._attachedEdges.delete(e),this._state.delete(e.id),this._cachedDirections.delete(e.id),this._spatialValid=!1,this._batchDepth>0&&(this._batchDirty=!0))}get(t){return this._edgeMap.get(t)}setEndpoints(t,e,s,i,n){t.fromX=e,t.fromY=s,t.toX=i,t.toY=n,this._positionsDirty=!0,this._batchDepth===0&&t._element&&t._inDOM&&this._updateEdgeGeometry(t)}setState(t,e,s){const i=typeof t=="object"?t.id:t;let n=this._state.get(i);s?(n||(n=new Map,this._state.set(i,n)),n.set(e,!0)):n&&(n.delete(e),n.size===0&&this._state.delete(i)),this._stateVersion++;const o=this._edgeMap.get(i);o&&o._element&&(s?o._element.classList.add(e):o._element.classList.remove(e))}getState(t,e){const s=typeof t=="object"?t.id:t,i=this._state.get(s);return i&&i.get(e)||!1}clearState(t){let e=!1;for(const[s,i]of this._state)if(i.has(t)){i.delete(t),i.size===0&&this._state.delete(s),e=!0;const n=this._edgeMap.get(s);n&&n._element&&n._element.classList.remove(t)}e&&this._stateVersion++}_reapplyState(t){if(!t._element)return;t._element.setAttribute("class","edge");const e=this._state.get(t.id);if(e)for(const s of e.keys())t._element.classList.add(s)}_buildCtx(t){const e=this._reusableCtx,s=this._reusableCtxKeys;for(let n=0;n<s.length;n++)e[s[n]]=void 0;s.length=0,e.zoom=this._lastScale;const i=this._state.get(t);if(i)for(const[n,o]of i)e[n]=o,s.push(n);return e}syncPositions(t){if(!this._graph)return;const e=this._nodeCollection,s=this._directed&&e;this.beginBatch();for(const i of this._edges){if(!i)continue;const n=i.data.fromId,o=i.data.toId;if(!n||!o)continue;const h=t.get(n),l=t.get(o);if(!(!h||!l))if(s){const c=h.x-l.x,r=h.y-l.y,u=Math.sqrt(c*c+r*r);if(u>.001){const p=c/u,x=r/u;this._cachedDirections.set(i.id,{dirX:p,dirY:x});const g=e.getNodeShape(o);if(g){const f=B(p,x,g);i.fromX=h.x,i.fromY=h.y,i.toX=g.x+f.x,i.toY=g.y+f.y}else i.fromX=h.x,i.fromY=h.y,i.toX=l.x,i.toY=l.y}else i.fromX=h.x,i.fromY=h.y,i.toX=l.x,i.toY=l.y}else i.fromX=h.x,i.fromY=h.y,i.toX=l.x,i.toY=l.y}this._positionsDirty=!0,this.endBatch()}beginBatch(){this._batchDepth++}endBatch(){this._batchDepth>0&&this._batchDepth--,this._batchDepth===0&&this._batchDirty&&(this._batchDirty=!1,this.render(this._lastDrawContext))}forEach(t){for(let e=0;e<this._edges.length;e++){const s=this._edges[e];s&&t(s,s.id)}}get count(){return this._edgeMap.size}render(t){if(this._lastDrawContext=t,!t)return;const e=t.transform.scale,s=this._directed&&e!==this._lastScale;this._lastScale=e,s&&this._nodeCollection&&this._recomputeArrowOffsets(),this._positionsDirty?(this._positionsDirty=!1,this._spatialValid=!1,this._renderAllEdges(t)):(this._spatialValid||(this._rebuildSpatialIndex(),this._spatialValid=!0),this._renderWithSpatialQuery(t))}_renderAllEdges(t){this._attachedEdges.clear();const e=t.getVisibleBounds();for(let s=0;s<this._edges.length;s++){const i=this._edges[s];if(!i||!i._element)continue;this._isEdgeVisibleInBounds(i,e)?(i._inDOM||(this._root.appendChild(i._element),i._inDOM=!0,this._reapplyState(i)),this._updateEdgeGeometry(i),this._updateEdgeStyle(i),this._attachedEdges.add(i)):i._inDOM&&(this._root.removeChild(i._element),i._inDOM=!1)}}_renderWithSpatialQuery(t){const e=t.getVisibleBounds(),s=this._spatialIndex.search({minX:e.left,minY:e.top,maxX:e.right,maxY:e.bottom}),i=this._swapAttachedSet;i.clear();for(let n=0;n<s.length;n++){const o=s[n].edge;o._element&&(o._inDOM||(this._root.appendChild(o._element),o._inDOM=!0,this._reapplyState(o),this._updateEdgeGeometry(o)),this._updateEdgeStyle(o),i.add(o))}for(const n of this._attachedEdges)!i.has(n)&&n._inDOM&&(this._root.removeChild(n._element),n._inDOM=!1);this._swapAttachedSet=this._attachedEdges,this._attachedEdges=i}_rebuildSpatialIndex(){const t=[];for(const e of this._edges)e&&t.push({minX:Math.min(e.fromX,e.toX),minY:Math.min(e.fromY,e.toY),maxX:Math.max(e.fromX,e.toX),maxY:Math.max(e.fromY,e.toY),edge:e});this._spatialIndex.clear(),t.length>0&&this._spatialIndex.load(t)}_addEdgeToScene(t,e){if(!t._element||!e)return;const s=e.getVisibleBounds();this._isEdgeVisibleInBounds(t,s)&&(t._inDOM||(this._root.appendChild(t._element),t._inDOM=!0,this._reapplyState(t),this._attachedEdges.add(t)),this._updateEdgeGeometry(t),this._updateEdgeStyle(t))}_recomputeArrowOffsets(){const t=this._nodeCollection;if(t){for(const e of this._edges){if(!e)continue;const s=this._cachedDirections.get(e.id);if(!s)continue;const i=e.data.toId;if(!i)continue;const n=t.getNodeShape(i);if(!n)continue;const o=B(s.dirX,s.dirY,n);e.toX=n.x+o.x,e.toY=n.y+o.y}this._positionsDirty=!0,this._spatialValid=!1}}clear(){for(let t=0;t<this._edges.length;t++){const e=this._edges[t];e&&this.remove(e)}this._edges.length=0,this._freeIndices.length=0,this._edgeMap.clear(),this._attachedEdges.clear(),this._swapAttachedSet.clear(),this._spatialIndex.clear(),this._spatialValid=!1,this._state.clear(),this._cachedDirections.clear()}dispose(){this._graph&&this._graphChangeListener&&(this._graph.off("changed",this._graphChangeListener),this._graphChangeListener=null),this.clear(),this._elementPool.length=0,this._markerId=null,this._defs&&this._defs.parentNode&&(this._defs.parentNode.removeChild(this._defs),this._defs=null),this._root.parentNode&&this._root.parentNode.removeChild(this._root)}_generateId(){return`edge_${Date.now()}_${Math.random().toString(36).slice(2,9)}`}_createEdgeElement(t){let e=this._elementPool.pop();e||(e=document.createElementNS(V,"path")),e.setAttribute("class","edge"),e.setAttribute("vector-effect","non-scaling-stroke"),t._element=e,this._updateEdgeStyle(t),this._directed&&this._applyArrowMarker(t)}_updateEdgeGeometry(t){t._element.setAttribute("d",`M${t.fromX} ${t.fromY}L${t.toX} ${t.toY}`)}_updateEdgeStyle(t){if(t._renderedStateVersion===this._stateVersion&&t._renderedZoom===this._lastScale)return;const e=this._buildCtx(t.id),s=tt(this._colorProp,t.data,e),i=tt(this._widthProp,t.data,e),n=tt(this._opacityProp,t.data,e);t._element.setAttribute("stroke",s),t._element.setAttribute("stroke-width",i),t._element.setAttribute("opacity",n),t._renderedStateVersion=this._stateVersion,t._renderedZoom=this._lastScale}_ensureDefs(){if(this._defs)return this._defs;let t=this._root.parentNode;for(;t&&t.nodeName!=="svg";)t=t.parentNode;return t||(t=this._root),this._defs=t.querySelector("defs"),this._defs||(this._defs=document.createElementNS(V,"defs"),t.insertBefore(this._defs,t.firstChild)),this._defs}_applyArrowMarker(t){this._markerId||this._createSharedMarker(),t._element.setAttribute("marker-end",`url(#${this._markerId})`)}_createSharedMarker(){const t="ngraph-arrow";this._markerId=t;const e=this._ensureDefs(),s=document.createElementNS(V,"marker");s.setAttribute("id",t),s.setAttribute("viewBox","0 0 10 10"),s.setAttribute("refX","10"),s.setAttribute("refY","5"),s.setAttribute("markerUnits","userSpaceOnUse"),s.setAttribute("markerWidth",this._arrowLength),s.setAttribute("markerHeight",this._arrowWidth),s.setAttribute("preserveAspectRatio","none"),s.setAttribute("orient","auto");const i=document.createElementNS(V,"path");i.setAttribute("d","M 0 0 L 10 5 L 0 10 z"),i.setAttribute("fill","context-stroke"),s.appendChild(i),e.appendChild(s),this._markerElement=s}_isEdgeVisibleInBounds(t,e){const s=Math.min(t.fromX,t.toX),i=Math.max(t.fromX,t.toX),n=Math.min(t.fromY,t.toY),o=Math.max(t.fromY,t.toY);return!(i<e.left||s>e.right||o<e.top||n>e.bottom)}_bindGraph(){const t=this._graph;this.beginBatch(),t.forEachLink(e=>{const s=this._dataFn?{fromId:e.fromId,toId:e.toId,...this._dataFn(e)}:{fromId:e.fromId,toId:e.toId};this.add({id:e.id,data:s})}),this.endBatch(),this._graphChangeListener=e=>{this.beginBatch();for(let s=0;s<e.length;s++){const i=e[s];if(i.link)if(i.changeType==="add"){if(!this._edgeMap.has(i.link.id)){const n=this._dataFn?{fromId:i.link.fromId,toId:i.link.toId,...this._dataFn(i.link)}:{fromId:i.link.fromId,toId:i.link.toId};this.add({id:i.link.id,data:n})}}else i.changeType==="remove"&&this.remove(i.link.id)}this.endBatch()},t.on("changed",this._graphChangeListener)}}function et(a,t,e){return typeof a=="function"?a(t,e):a}class Ot{constructor(t={}){this._colorProp=t.color||"#999",this._widthProp=t.width||1,this._opacityProp=t.opacity||.6,this._allLiteralStyles=typeof this._colorProp!="function"&&typeof this._widthProp!="function"&&typeof this._opacityProp!="function",this._directed=t.directed||!1,this._dataFn=t.data||null,this._spatialIndex=new N,this._spatialValid=!1,this._positionsDirty=!0,this._edges=[],this._edgeMap=new Map,this._freeIndices=[],this._batchDepth=0,this._batchDirty=!1,this._lastDrawContext=null,this._lastScale=-1,this._state=new Map,this._stateVersion=0,this._arrowLength=t.arrowLength||10,this._arrowWidth=t.arrowWidth||5,this._graph=t.graph||null,this._nodeCollection=t.nodeCollection||null,this._graphChangeListener=null,this._cachedDirections=new Map,this._reusableCtx={zoom:1},this._reusableCtxKeys=[],this._batches=new Map,this._batchPool=[],this._container=t.container||null,this._canvas=document.createElement("canvas"),this._canvas.style.position="absolute",this._canvas.style.top="0",this._canvas.style.left="0",this._canvas.style.pointerEvents="none",this._ctx2d=this._canvas.getContext("2d"),this._container&&(getComputedStyle(this._container).position==="static"&&(this._container.style.position="relative"),this._container.insertBefore(this._canvas,this._container.firstChild)),this._root=null,this._canvasWidth=0,this._canvasHeight=0,this._resizeObserver=null,this._container&&typeof ResizeObserver<"u"&&(this._resizeObserver=new ResizeObserver(()=>{this._resizeCanvas(),this._lastDrawContext&&this.render(this._lastDrawContext)}),this._resizeObserver.observe(this._container)),this._graph&&this._bindGraph()}getRoot(){return this._root}add(t){const{id:e=this._generateId(),fromX:s=0,fromY:i=0,toX:n=0,toY:o=0,data:h={}}=t;let l;this._freeIndices.length>0?l=this._freeIndices.pop():l=this._edges.length;const c={id:e,index:l,fromX:s,fromY:i,toX:n,toY:o,data:h,_collection:this};return this._edges[l]=c,this._edgeMap.set(e,c),this._spatialValid=!1,this._batchDepth>0&&(this._batchDirty=!0),c}remove(t){const e=typeof t=="object"?t:this._edgeMap.get(t);e&&(this._freeIndices.push(e.index),this._edges[e.index]=null,this._edgeMap.delete(e.id),this._state.delete(e.id),this._cachedDirections.delete(e.id),this._spatialValid=!1,this._batchDepth>0&&(this._batchDirty=!0))}get(t){return this._edgeMap.get(t)}setEndpoints(t,e,s,i,n){t.fromX=e,t.fromY=s,t.toX=i,t.toY=n,this._positionsDirty=!0}setState(t,e,s){const i=typeof t=="object"?t.id:t;let n=this._state.get(i);s?(n||(n=new Map,this._state.set(i,n)),n.set(e,!0)):n&&(n.delete(e),n.size===0&&this._state.delete(i)),this._stateVersion++}getState(t,e){const s=typeof t=="object"?t.id:t,i=this._state.get(s);return i&&i.get(e)||!1}clearState(t){let e=!1;for(const[s,i]of this._state)i.has(t)&&(i.delete(t),i.size===0&&this._state.delete(s),e=!0);e&&this._stateVersion++}_buildCtx(t){const e=this._reusableCtx,s=this._reusableCtxKeys;for(let n=0;n<s.length;n++)e[s[n]]=void 0;s.length=0,e.zoom=this._lastScale;const i=this._state.get(t);if(i)for(const[n,o]of i)e[n]=o,s.push(n);return e}syncPositions(t){if(!this._graph)return;const e=this._nodeCollection,s=this._directed&&e;this.beginBatch();for(const i of this._edges){if(!i)continue;const n=i.data.fromId,o=i.data.toId;if(!n||!o)continue;const h=t.get(n),l=t.get(o);if(!(!h||!l))if(s){const c=h.x-l.x,r=h.y-l.y,u=Math.sqrt(c*c+r*r);if(u>.001){const p=c/