@kazant/flexgraph 1.1.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- /*! FlexGraph v1.1.0 | MIT License | (c) 2026 Alexander Pettersen (kazant) | https://github.com/kazant/flexgraph */
2
- var bn=["top","right","bottom","left"],kn=["TB","LR","BT","RL"],vn=["orthogonal","straight","curved"],Gt=Object.freeze({direction:"TB",nodeSpacing:40,rankSpacing:80,edgeSpacing:10,edgeRouting:"orthogonal",cornerRadius:6,lineHops:!0,hopRadius:4,animate:!0,animationDuration:300,nodeMargin:14,groupPadding:20,groupLabelHeight:22,componentSpacing:80,maxIterations:24,bendPenalty:24,crossingPenalty:120,defaultNodeWidth:160,defaultNodeHeight:60,pinOnDrag:!0,draggable:!0,zoomable:!0,pannable:!0,minZoom:.1,maxZoom:4,controls:!0,showPorts:!0,hoverHighlight:"chain",highlightSelection:!0,edgeTypes:{default:{markerEnd:"arrow"},"has-many":{markerStart:"one",markerEnd:"many"},"has-one":{markerStart:"one",markerEnd:"onlyOne"},"belongs-to":{markerStart:"many",markerEnd:"one"},"many-to-many":{markerStart:"many",markerEnd:"many"},association:{markerEnd:"open"},composition:{markerStart:"diamond"},dependency:{markerEnd:"open"}}}),ut=class extends Error{constructor(s,c=[]){super(s),this.name="GraphValidationError",this.details=c}},Z=t=>typeof t=="number"&&Number.isFinite(t);function In(...t){let s={...Gt,edgeTypes:{...Gt.edgeTypes}};for(let c of t)if(c)for(let[r,o]of Object.entries(c))o!==void 0&&(r==="edgeTypes"?Object.assign(s.edgeTypes,o):s[r]=o);return kn.includes(s.direction)||(s.direction="TB"),vn.includes(s.edgeRouting)||(s.edgeRouting="orthogonal"),s}function Ut(t,s,c){if(!t||typeof t!="object")throw new ut("Graph must be an object");let r=In(t.options,s),o=[],n=[],i=[],h=new Map;for(let f of t.groups||[]){if(!f||f.id==null){o.push("Group without id");continue}let e=String(f.id);if(h.has(e)){o.push(`Duplicate group id "${e}"`);continue}let l={id:e,label:f.label??e,className:f.className||"",data:f};i.push(l),h.set(e,l)}let a=[],u=new Map;(t.nodes||[]).forEach((f,e)=>{if(!f||f.id==null){o.push(`Node at index ${e} has no id`);return}let l=String(f.id);if(u.has(l)){o.push(`Duplicate node id "${l}"`);return}let m=c&&c.get(l),x=Z(f.width)?f.width:m?m.width:r.defaultNodeWidth,M=Z(f.height)?f.height:m?m.height:r.defaultNodeHeight,w=f.group!=null?String(f.group):null;if(w&&!h.has(w)){let R={id:w,label:w,className:"",data:{id:w}};i.push(R),h.set(w,R)}let y=[],b=new Set;for(let R of f.ports||[]){if(!R||R.id==null){n.push(`Node "${l}": port without id ignored`);continue}let A=String(R.id);if(b.has(A)){n.push(`Node "${l}": duplicate port "${A}" ignored`);continue}let $=bn.includes(R.side)?R.side:null;$||n.push(`Node "${l}": port "${A}" has invalid side "${R.side}", using auto side`),b.add(A),y.push({id:A,side:$,offset:Z(R.offset)?Math.min(1,Math.max(0,R.offset)):null,label:R.label,data:R})}let k=f.constraints||{},P={pinned:!!k.pinned,x:Z(k.x)?k.x:Z(f.x)&&k.pinned?f.x:null,y:Z(k.y)?k.y:Z(f.y)&&k.pinned?f.y:null,rank:Number.isInteger(k.rank)&&k.rank>=0?k.rank:null};P.pinned&&(P.x==null||P.y==null)&&(n.push(`Node "${l}" is pinned but has no x/y; pin ignored until it has a position`),P.pinned=!1);let L={id:l,index:e,label:f.label??l,width:x,height:M,group:w,ports:y,portById:new Map(y.map(R=>[R.id,R])),constraints:P,className:f.className||"",type:f.type||null,data:f};a.push(L),u.set(l,L)});let p=[],g=new Map;(t.edges||[]).forEach((f,e)=>{if(!f)return;let l=f.id!=null?String(f.id):`e${e}`;if(g.has(l)){o.push(`Duplicate edge id "${l}"`);return}let m=String(f.source),x=String(f.target);if(!u.has(m)){o.push(`Edge "${l}": unknown source node "${m}"`);return}if(!u.has(x)){o.push(`Edge "${l}": unknown target node "${x}"`);return}let M=f.sourcePort!=null?String(f.sourcePort):null,w=f.targetPort!=null?String(f.targetPort):null;M&&!u.get(m).portById.has(M)&&(n.push(`Edge "${l}": node "${m}" has no port "${M}"`),M=null),w&&!u.get(x).portById.has(w)&&(n.push(`Edge "${l}": node "${x}" has no port "${w}"`),w=null);let y=r.edgeTypes[f.type]||r.edgeTypes.default||{},b={id:l,index:e,source:m,target:x,sourcePort:M,targetPort:w,type:f.type||"default",label:f.label??null,minLen:Number.isInteger(f.minLen)&&f.minLen>=0?f.minLen:1,weight:Z(f.weight)?f.weight:1,markerStart:f.markerStart!==void 0?f.markerStart:y.markerStart||null,markerEnd:f.markerEnd!==void 0?f.markerEnd:y.markerEnd||null,className:f.className||"",data:f};p.push(b),g.set(l,b)});let d=[];for(let f of t.constraints||[])if(!(!f||!f.type))if(f.type==="leftOf"||f.type==="before"){let e=String(f.a),l=String(f.b);if(!u.has(e)||!u.has(l)){n.push("leftOf constraint references unknown node");continue}d.push({type:"leftOf",a:e,b:l})}else if(f.type==="sameRank"){let e=(f.nodes||[]).map(String).filter(l=>u.has(l));e.length>=2?d.push({type:"sameRank",nodes:e}):n.push("sameRank constraint needs at least two known nodes")}else if(f.type==="rank"){let e=String(f.node);u.has(e)&&Number.isInteger(f.rank)&&(u.get(e).constraints.rank=f.rank)}else n.push(`Unknown constraint type "${f.type}"`);if(o.length)throw new ut(o[0],o);return{options:r,nodes:a,nodeById:u,edges:p,edgeById:g,groups:i,groupById:h,constraints:d,warnings:n}}function Sn(t,s){let c=new Map(t.map(h=>[h,[]])),r=new Map(t.map(h=>[h,0]));for(let h of s)c.get(h.v).push(h),r.set(h.w,r.get(h.w)+1);let o=new Map,n=new Set,i=[...t.filter(h=>r.get(h)===0),...t];for(let h of i){if(o.has(h))continue;let a=[[h,0]];for(o.set(h,1);a.length;){let u=a[a.length-1],[p,g]=u,d=c.get(p);if(g>=d.length){o.set(p,2),a.pop();continue}u[1]++;let f=d[g],e=o.get(f.w);e===1?n.add(f.id):e||(o.set(f.w,1),a.push([f.w,0]))}}return n}var bt=class{constructor(s){this.p=new Map(s.map(c=>[c,c]))}find(s){let c=s;for(;this.p.get(c)!==c;)c=this.p.get(c);for(;this.p.get(s)!==c;){let r=this.p.get(s);this.p.set(s,c),s=r}return c}union(s,c){let r=this.find(s),o=this.find(c);r!==o&&this.p.set(o,r)}};function Yt(t,s,c={}){let r=[],o=new bt(t);for(let y of c.sameRank||[])for(let b=1;b<y.length;b++)o.union(y[0],y[b]);let n=[...new Set(t.map(y=>o.find(y)))],i=new Set,h=new Set,a=[];for(let y of s){if(y.source===y.target){i.add(y.id);continue}let b=o.find(y.source),k=o.find(y.target);if(b===k){h.add(y.id);continue}a.push({id:y.id,v:b,w:k,minLen:y.minLen??1})}let u=Sn(n,a),p=a.map(y=>u.has(y.id)?{...y,v:y.w,w:y.v}:y),g=new Map;if(c.fixedRank)for(let[y,b]of c.fixedRank){if(!o.p.has(y))continue;let k=o.find(y);g.has(k)&&g.get(k)!==b&&r.push(`Conflicting fixed ranks in sameRank set of "${y}"`),g.set(k,Math.max(g.get(k)??0,b))}let d=new Map(n.map(y=>[y,[]])),f=new Map(n.map(y=>[y,[]]));for(let y of p)d.get(y.v).push(y),f.get(y.w).push(y);let e=new Map(n.map(y=>[y,f.get(y).length])),l=n.filter(y=>e.get(y)===0),m=[];for(;l.length;){let y=l.shift();m.push(y);for(let b of d.get(y))e.set(b.w,e.get(b.w)-1),e.get(b.w)===0&&l.push(b.w)}let x=new Map;for(let y of m){let b=g.get(y)??0;for(let k of f.get(y))b=Math.max(b,x.get(k.v)+k.minLen);g.has(y)&&b!==g.get(y)&&r.push(`Fixed rank ${g.get(y)} for "${y}" cannot be satisfied; using ${b}`),x.set(y,b)}for(let y=m.length-1;y>=0;y--){let b=m[y];if(g.has(b))continue;let k=d.get(b);if(!k.length||f.get(b).length>=k.length)continue;let L=1/0;for(let R of k)L=Math.min(L,x.get(R.w)-R.minLen);L>x.get(b)&&x.set(b,L)}let M=1/0;for(let y of x.values())M=Math.min(M,y);if(!g.size&&M>0)for(let[y,b]of x)x.set(y,b-M);let w=new Map;for(let y of t)w.set(y,x.get(o.find(y))??0);return{rank:w,reversed:u,flat:h,selfLoops:i,warnings:r}}function Vt(t,s,c=0){let r=[],o=new Map;for(let u of t)o.set(u.id,r.length),r.push({id:u.id,real:!0,rank:u.rank,width:u.width,height:u.height??0,group:u.group??null,pinX:u.pinX??null,inputIndex:r.length,up:[],down:[]});let n=new Map,i=[],h=(u,p,g,d,f,e)=>{let l={a:u,b:p,aOff:g,bOff:d,w:f,edgeId:e};i.push(l),r[u].down.push({n:p,off:d,own:g,w:f}),r[p].up.push({n:u,off:g,own:d,w:f})};for(let u of s){let p=o.get(u.v),g=o.get(u.w),d=r[p].rank,f=r[g].rank;if(f<=d)continue;let e=r[p].group&&r[p].group===r[g].group?r[p].group:null,l=[],m=p,x=u.vOff||0;for(let M=d+1;M<f;M++){let w=r.length;r.push({id:`__d_${u.id}_${M}`,real:!1,rank:M,width:c,height:0,group:e,pinX:null,edgeId:u.id,inputIndex:w,up:[],down:[]}),h(m,w,x,0,u.weight??1,u.id),l.push(w),m=w,x=0}h(m,g,x,u.wOff||0,u.weight??1,u.id),n.set(u.id,l)}let a=0;for(let u of r)a=Math.max(a,u.rank);return{v:r,index:o,segs:i,chains:n,maxRank:a}}function vt(t){let s=Array.from({length:t.maxRank+1},()=>[]),c=new Uint8Array(t.v.length),r=t.v.map((o,n)=>n).filter(o=>t.v[o].real).sort((o,n)=>t.v[o].rank-t.v[n].rank||t.v[o].inputIndex-t.v[n].inputIndex);for(let o of r){if(c[o])continue;let n=[o];for(;n.length;){let i=n.pop();if(c[i])continue;c[i]=1,s[t.v[i].rank].push(i);let h=t.v[i].down.map(a=>a.n);for(let a=h.length-1;a>=0;a--)c[h[a]]||n.push(h[a])}}for(let o=0;o<t.v.length;o++)c[o]||s[t.v[o].rank].push(o);return s}function Pn(t){let s=t.length;if(s<2)return 0;let c=t.slice(),r=new Array(s),o=0;for(let n=1;n<s;n*=2){for(let i=0;i<s;i+=2*n){let h=Math.min(i+n,s),a=Math.min(i+2*n,s),u=i,p=h,g=i;for(;u<h&&p<a;)c[u]<=c[p]?r[g++]=c[u++]:(o+=h-u,r[g++]=c[p++]);for(;u<h;)r[g++]=c[u++];for(;p<a;)r[g++]=c[p++]}[c,r]=[r,c]}return o}function Rn(t,s,c,r){let o=[];for(let n of s)for(let i of t.v[n].down)o.push([r[n]+i.own*.999,r[i.n]+i.off*.999]);return o.sort((n,i)=>n[0]-i[0]||n[1]-i[1]),Pn(o.map(n=>n[1]))}function kt(t,s){let c=ht(t,s),r=0;for(let o=0;o<s.length-1;o++)r+=Rn(t,s[o],s[o+1],c);return r}function ht(t,s){let c=new Float64Array(t.v.length);for(let r of s)r.forEach((o,n)=>{c[o]=n});return c}function Wt(t,s={}){let c=s.maxIterations??24,r=(s.leftOf||[]).map(([u,p])=>[t.index.get(u),t.index.get(p)]).filter(([u,p])=>u!=null&&p!=null&&t.v[u].rank===t.v[p].rank),o=new Set(r.map(([u,p])=>u+":"+p)),n=[];s.initial&&n.push(s.initial.map(u=>u.slice()));let i=vt(t);n.push(i),!s.initial&&c>4&&(n.push(i.map(u=>u.slice().reverse())),n.push(i.map(u=>u.slice().sort((p,g)=>t.v[p].inputIndex-t.v[g].inputIndex))));let h=null,a=1/0;for(let u of n){let p=Nn(t,u,r,o,c);if(p.crossings<a&&(h=p.layers,a=p.crossings),a===0)break}return{layers:h,crossings:a}}function Nn(t,s,c,r,o){let n=s.map(u=>Kt(t,u,c)),i=n.map(u=>u.slice()),h=kt(t,n),a=0;for(let u=0;u<o&&h>0;u++){let p=u%2===0;On(t,n,p,c,u%4>=2),Ln(t,n,r);let g=kt(t,n);if(g<h)h=g,i=n.map(d=>d.slice()),a=0;else if(++a>=6)break}if(h>0&&o>4){n=i.map(u=>u.slice());for(let u=0;u<2;u++){En(t,n,r);let p=kt(t,n);if(p<h)h=p,i=n.map(g=>g.slice());else break}}return{layers:i,crossings:h}}function En(t,s,c){let r=ht(t,s);for(let o of s)if(!(o.length<3||o.length>120))for(let n of o.slice()){let i=t.v[n];if(i.pinX!=null||i.group)continue;let h=o.indexOf(n),a=0,u=h,p=0;for(let g=h-1;g>=0;g--){let d=o[g];if(c.has(d+":"+n)||t.v[d].group)break;p+=et(t,n,d,r)-et(t,d,n,r),p<a&&(a=p,u=g)}p=0;for(let g=h+1;g<o.length;g++){let d=o[g];if(c.has(n+":"+d)||t.v[d].group)break;p+=et(t,d,n,r)-et(t,n,d,r),p<a&&(a=p,u=g)}u!==h&&(o.splice(h,1),o.splice(u,0,n),o.forEach((g,d)=>{r[g]=d}))}}function On(t,s,c,r,o){let n=ht(t,s),i=s.length,h=c?_t(1,i):_t(i-2,-1,-1);for(let a of h){let u=s[a],p=new Map;u.forEach((e,l)=>{let m=c?t.v[e].up:t.v[e].down;if(!m.length){p.set(e,l);return}if(o){let w=m.map(b=>n[b.n]+b.off-b.own).sort((b,k)=>b-k),y=w.length>>1;p.set(e,w.length%2?w[y]:(w[y-1]+w[y])/2);return}let x=0,M=0;for(let w of m)x+=(n[w.n]+w.off-w.own)*w.w,M+=w.w;p.set(e,x/M)});let g=new Map;for(let e of u){let l=t.v[e].group;if(!l)continue;let m=g.get(l)||[0,0];m[0]+=p.get(e),m[1]++,g.set(l,m)}let d=e=>{let l=t.v[e].group;return l?g.get(l)[0]/g.get(l)[1]:p.get(e)},f=new Map(u.map((e,l)=>[e,l]));u.sort((e,l)=>d(e)-d(l)||(t.v[e].group||"").localeCompare(t.v[l].group||"")||p.get(e)-p.get(l)||f.get(e)-f.get(l)),s[a]=Kt(t,u,r),s[a].forEach((e,l)=>{n[e]=l})}}function Kt(t,s,c){let r=s.slice(),o=[],n=[];if(r.forEach((i,h)=>{t.v[i].pinX!=null&&(o.push(h),n.push(i))}),n.length>1&&(n.sort((i,h)=>t.v[i].pinX-t.v[h].pinX),o.forEach((i,h)=>{r[i]=n[h]})),c.length)for(let i=0;i<c.length+1;i++){let h=!1;for(let[a,u]of c){let p=r.indexOf(a),g=r.indexOf(u);p<0||g<0||p<g||(r.splice(p,1),r.splice(r.indexOf(u),0,a),h=!0)}if(!h)break}return r}function et(t,s,c,r){let o=0;for(let n of["up","down"]){let i=t.v[s][n],h=t.v[c][n];for(let a of i)for(let u of h)r[a.n]+a.off>r[u.n]+u.off&&(o+=a.w*u.w)}return o}function Ln(t,s,c){let r=ht(t,s),o=!0,n=0;for(;o&&n++<8;){o=!1;for(let i of s)for(let h=0;h<i.length-1;h++){let a=i[h],u=i[h+1],p=t.v[a],g=t.v[u];if((p.group||null)!==(g.group||null)||p.pinX!=null&&g.pinX!=null||c.has(a+":"+u))continue;let d=et(t,a,u,r);et(t,u,a,r)<d&&(i[h]=u,i[h+1]=a,r[u]=h,r[a]=h+1,o=!0)}}}function _t(t,s,c=1){let r=[];if(c>0)for(let o=t;o<s;o+=c)r.push(o);else for(let o=t;o>s;o+=c)r.push(o);return r}function An(t,s,c){let r=t.length,o=new Float64Array(r);for(let p=1;p<r;p++)o[p]=o[p-1]+c[p];let n=[],i=[],h=[],a=[];for(let p=0;p<r;p++)for(n.push(t[p]-o[p]),i.push(s[p]),h.push(p),a.push(p);n.length>1&&n[n.length-2]>n[n.length-1];){let g=n.length-1,d=g-1,f=i[d]+i[g];n[d]=(n[d]*i[d]+n[g]*i[g])/f,i[d]=f,a[d]=a[g],n.pop(),i.pop(),h.pop(),a.pop()}let u=new Float64Array(r);for(let p=0;p<n.length;p++)for(let g=h[p];g<=a[p];g++)u[g]=n[p]+o[g];return u}function Zt(t,s,c){let r=t.v.length,o=new Float64Array(r),n=new Float64Array(r),i=c.groupPadding??20,h=c.groupLabelHeight??0,a=(w,y)=>{let b=t.v[w],k=t.v[y],P;return!b.real&&!k.real?P=c.edgeSpacing:!b.real||!k.real?P=(c.nodeSpacing+c.edgeSpacing)/2:P=c.nodeSpacing,b.group!==k.group&&(b.group&&(P+=i),k.group&&(P+=i+(c.labelOnOrderAxis?h:0))),(b.width+k.width)/2+P},u=s.map(w=>w.map((y,b)=>b===0?0:a(w[b-1],y)));s.forEach((w,y)=>{let b=0;w.forEach((P,L)=>{b+=u[y][L],o[P]=b});let k=b/2;w.forEach(P=>{o[P]-=k})});let p=w=>t.v[w].real?1:4,g=(w,y,b)=>{let k=s[w];if(!k.length)return;let P=new Array(k.length),L=new Array(k.length);k.forEach((A,$)=>{let z=t.v[A];if(z.pinX!=null){P[$]=z.pinX,L[$]=1e6;return}let v=0,N=0,X=G=>{for(let V of G){let Q=V.w*(t.v[V.n].real?1:2)*p(A);v+=(o[V.n]+V.off*t.v[V.n].width-V.own*z.width)*Q,N+=Q}};y&&X(z.up),b&&X(z.down),N===0?(P[$]=o[A],L[$]=.05):(P[$]=v/N,L[$]=N)});let R=An(P,L,u[w]);k.forEach((A,$)=>{o[A]=R[$]})},d=s.length,f=c.iterations??8;for(let w=0;w<f;w++){for(let y=1;y<d;y++)g(y,!0,!1);for(let y=d-2;y>=0;y--)g(y,!1,!0)}for(let w=0;w<2;w++){for(let y=0;y<d;y++)g(y,!0,!0);for(let y=d-1;y>=0;y--)g(y,!0,!0)}let e=s.map(w=>w.reduce((y,b)=>Math.max(y,t.v[b].height||0),0)),l=new Map;for(let w of t.v){if(!w.real||!w.group)continue;let y=l.get(w.group)||[1/0,-1/0];y[0]=Math.min(y[0],w.rank),y[1]=Math.max(y[1],w.rank),l.set(w.group,y)}let m=new Float64Array(d);for(let[w,y]of l.values()){let b=c.labelOnOrderAxis||c.labelAtRankEnd?0:h,k=c.labelAtRankEnd&&!c.labelOnOrderAxis?h:0;w>0&&(m[w]=Math.max(m[w],i+b)),y<d-1&&(m[y+1]=Math.max(m[y+1],i+k))}let x=[],M=0;for(let w=0;w<d;w++)w>0?M+=e[w-1]/2+c.rankSpacing+m[w]+e[w]/2:M=e[0]/2,x.push(M);for(let w=0;w<r;w++)n[w]=x[t.v[w].rank];return{x:o,y:n,rankY:x,rankHeight:e}}var ct={top:{x:0,y:-1},bottom:{x:0,y:1},left:{x:-1,y:0},right:{x:1,y:0}};function Jt(t){switch(t){case"LR":return{x:1,y:0,exit:"right",entry:"left"};case"RL":return{x:-1,y:0,exit:"left",entry:"right"};case"BT":return{x:0,y:-1,exit:"top",entry:"bottom"};default:return{x:0,y:1,exit:"bottom",entry:"top"}}}function lt(t){let s=new Map,c={top:[],right:[],bottom:[],left:[]};for(let r of t.ports)r.side&&c[r.side].push(r);for(let r of Object.keys(c)){let o=c[r];o.forEach((n,i)=>{let h=n.offset!=null?n.offset:(i+1)/(o.length+1);s.set(n.id,{side:r,t:h,...Bn(r,h)})})}return s}function Bn(t,s){switch(t){case"top":return{px:s,py:0};case"bottom":return{px:s,py:1};case"left":return{px:0,py:s};default:return{px:1,py:s}}}var J=t=>({x:t.x+t.width/2,y:t.y+t.height/2});function Qt(t,s){return{x:t.x-s,y:t.y-s,width:t.width+2*s,height:t.height+2*s}}function qt(t,s,c,r=.5){return s>t.x+r&&s<t.x+t.width-r&&c>t.y+r&&c<t.y+t.height-r}function It(t,s){let c=J(t),r=s.x-c.x,o=s.y-c.y;if(r===0&&o===0)return{...c,side:"bottom"};let n=r!==0?t.width/2/Math.abs(r):1/0,i=o!==0?t.height/2/Math.abs(o):1/0,h=Math.min(n,i),a=n<i?r>0?"right":"left":o>0?"bottom":"top";return{x:c.x+r*h,y:c.y+o*h,side:a}}function St(t){let s=[];for(let c of t){let r=s[s.length-1];r&&Math.abs(r.x-c.x)<.01&&Math.abs(r.y-c.y)<.01||s.push({x:c.x,y:c.y})}for(let c=s.length-2;c>=1;c--){let r=s[c-1],o=s[c],n=s[c+1],i=(o.x-r.x)*(n.y-o.y)-(o.y-r.y)*(n.x-o.x),h=(o.x-r.x)*(n.x-o.x)+(o.y-r.y)*(n.y-o.y);Math.abs(i)<.01&&h>=0&&s.splice(c,1)}return s}var tn=(t,s,c)=>{switch(t){case"BT":return{x:s,y:-c};case"LR":return{x:c,y:s};case"RL":return{x:-c,y:s};default:return{x:s,y:c}}},Pt=(t,s,c)=>{switch(t){case"BT":return{x:s,y:-c};case"LR":return{x:c,y:s};case"RL":return{x:c,y:-s};default:return{x:s,y:c}}};function on(t,s={}){return t.nodes.some(c=>c.group)?$n(t,s):Rt(t,s)}function nn(t,s,c){let r=new Set(s.map(n=>n.id)),o=s.map(n=>({...n,group:null,constraints:c?n.constraints:{...n.constraints,pinned:!1}}));return{options:t.options,nodes:o,nodeById:new Map(o.map(n=>[n.id,n])),edges:t.edges.filter(n=>r.has(n.source)&&r.has(n.target)),groups:[],groupById:new Map,constraints:t.constraints.filter(n=>n.type==="sameRank"?n.nodes.every(i=>r.has(i)):r.has(n.a)&&r.has(n.b)),warnings:[]}}function $n(t,s){let c=en(t,s.hints||null,s.hints||null),r=new Map,o=i=>({x:i.x+i.width/2,y:i.y+i.height/2});for(let i of t.nodes){let h=c.nodes.get(i.id);if(!i.group){r.set(i.id,o(h));continue}let a=0,u=0,p=0;for(let g of t.edges){let d=g.source===i.id?g.target:g.target===i.id?g.source:null;if(d==null||t.nodeById.get(d).group===i.group)continue;let f=o(c.nodes.get(d));a+=f.x,u+=f.y,p++}r.set(i.id,p?{x:a/p,y:u/p}:o(h))}let n=en(t,r,s.hints||r);return n.crossingsRouted<=c.crossingsRouted?n:c}function en(t,s,c){let r=t.options,o=r.groupPadding,n=r.groupLabelHeight,i=new Map;for(let e of t.nodes)e.group&&(i.has(e.group)||i.set(e.group,[]),i.get(e.group).push(e));let h=new Map,a=[];for(let[e,l]of i){let m=Rt(nn(t,l,!1),{hints:s}),x=m.bounds,M="\0group:"+e;h.set(e,{sub:m,b:x,blockId:M}),a.push({id:M,index:-1,label:e,width:x.width+2*o,height:x.height+2*o+n,group:null,ports:[],portById:new Map,constraints:{pinned:!1,x:null,y:null,rank:null}})}let u=e=>{let l=t.nodeById.get(e);return l.group?h.get(l.group).blockId:e},p=nn(t,t.nodes.filter(e=>!e.group),!0);p.nodes.push(...a);for(let e of a)p.nodeById.set(e.id,e);p.edges=[];for(let e of t.edges){let l=u(e.source),m=u(e.target);l===m&&(e.source!==e.target||l!==e.source)||p.edges.push({...e,source:l,target:m,sourcePort:l===e.source?e.sourcePort:null,targetPort:m===e.target?e.targetPort:null})}let g=null;if(c){g=new Map(c);for(let[e,l]of i){let m=0,x=0,M=0;for(let w of l){let y=c.get(w.id);y&&(m+=y.x,x+=y.y,M++)}M&&g.set(h.get(e).blockId,{x:m/M,y:x/M})}}let d=Rt(p,{hints:g}),f={nodes:new Map,edges:new Map,groups:new Map,crossings:d.crossings,warnings:d.warnings};for(let e of t.nodes)e.group||f.nodes.set(e.id,d.nodes.get(e.id));for(let[,{sub:e,b:l,blockId:m}]of h){let x=d.nodes.get(m),M=x.x+o-l.x,w=x.y+o+n-l.y;for(let[y,b]of e.nodes)f.nodes.set(y,{...b,x:b.x+M,y:b.y+w});for(let[y,b]of e.edges)f.edges.set(y,{...b,waypoints:b.waypoints.map(k=>({x:k.x+M,y:k.y+w}))});f.crossings+=e.crossings}for(let e of t.edges){if(f.edges.has(e.id))continue;let l=d.edges.get(e.id),m=u(e.source)!==e.source||u(e.target)!==e.target;f.edges.set(e.id,l?{...l,waypoints:m?[]:l.waypoints}:{waypoints:[],reversed:!1,selfLoop:e.source===e.target,flat:!1})}for(let e of t.nodes)if(e.group&&e.constraints.pinned){let l=f.nodes.get(e.id);l.x=e.constraints.x,l.y=e.constraints.y}if(rn(t,f),!t.nodes.some(e=>e.constraints.pinned)){let e=Nt(f);sn(f,-e.x,-e.y);for(let l of f.groups.values())l.x-=e.x,l.y-=e.y}return f.bounds=Nt(f),f.crossingsRouted=Xn(t,f),f}function Xn(t,s){let c=[];for(let n of t.edges){if(n.source===n.target)continue;let i=s.nodes.get(n.source),h=s.nodes.get(n.target);c.push([n.source,n.target,i.x+i.width/2,i.y+i.height/2,h.x+h.width/2,h.y+h.height/2])}let r=0,o=(n,i,h,a,u,p)=>(h-n)*(p-i)-(a-i)*(u-n);for(let n=0;n<c.length;n++)for(let i=n+1;i<c.length;i++){let h=c[n],a=c[i];if(h[0]===a[0]||h[0]===a[1]||h[1]===a[0]||h[1]===a[1])continue;let u=o(a[2],a[3],a[4],a[5],h[2],h[3]),p=o(a[2],a[3],a[4],a[5],h[4],h[5]),g=o(h[2],h[3],h[4],h[5],a[2],a[3]),d=o(h[2],h[3],h[4],h[5],a[4],a[5]);u*p<0&&g*d<0&&r++}return r}function Rt(t,s={}){let c=t.options,r=c.direction,o=r==="LR"||r==="RL",n=[],i=new Map;for(let d of t.nodes){let f=lt(d),e=new Map;for(let[x,M]of f)e.set(x,(o?M.py:M.px)-.5);let l=null,m=null;if(d.constraints.pinned){let x=Pt(r,d.constraints.x+d.width/2,d.constraints.y+d.height/2);l=x.x,m=x.y}i.set(d.id,{iw:o?d.height:d.width,ih:o?d.width:d.height,frac:e,pinX:l,pinY:m})}let h=Hn(t),a={nodes:new Map,edges:new Map,groups:new Map,crossings:0,warnings:n},u=[];for(let d of h){let f=d.nodes,e=new Set(f),l=t.edges.filter(v=>e.has(v.source)),m=new Map;for(let v of f){let N=t.nodeById.get(v).constraints.rank;N!=null&&m.set(v,N)}let x=t.constraints.filter(v=>v.type==="sameRank").map(v=>v.nodes.filter(N=>e.has(N))).filter(v=>v.length>1),M=Yt(f,l,{fixedRank:m,sameRank:x});n.push(...M.warnings);let w=f.map(v=>{let N=t.nodeById.get(v),X=i.get(v);return{id:v,rank:M.rank.get(v),width:X.iw,height:X.ih,group:N.group,pinX:X.pinX}}),y=[];for(let v of l){if(M.selfLoops.has(v.id)||M.flat.has(v.id))continue;let N=M.reversed.has(v.id),X=v.sourcePort?i.get(v.source).frac.get(v.sourcePort)??0:0,G=v.targetPort?i.get(v.target).frac.get(v.targetPort)??0:0;y.push(N?{id:v.id,v:v.target,w:v.source,vOff:G,wOff:X,weight:v.weight}:{id:v.id,v:v.source,w:v.target,vOff:X,wOff:G,weight:v.weight})}let b=Vt(w,y,0),k;s.hints&&s.hints.size&&(k=Tn(b,s.hints,r));let P=t.constraints.filter(v=>v.type==="leftOf"&&e.has(v.a)&&e.has(v.b)).map(v=>[v.a,v.b]),L=Wt(b,{maxIterations:c.maxIterations,leftOf:P,initial:k});a.crossings+=L.crossings;let R=Zt(b,L.layers,{nodeSpacing:c.nodeSpacing,edgeSpacing:c.edgeSpacing,rankSpacing:c.rankSpacing,groupPadding:c.groupPadding,groupLabelHeight:c.groupLabelHeight,labelOnOrderAxis:o,labelAtRankEnd:r==="BT"||r==="RL"?!o:!1}),A=f.filter(v=>i.get(v).pinY!=null);if(A.length){let v=0;for(let N of A)v+=i.get(N).pinY-R.y[b.index.get(N)];v/=A.length;for(let N=0;N<R.y.length;N++)R.y[N]+=v;for(let N of A){let X=b.index.get(N);R.x[X]=i.get(N).pinX,R.y[X]=i.get(N).pinY}}let $=1/0,z=-1/0;for(let v=0;v<b.v.length;v++){let N=b.v[v].width/2;$=Math.min($,R.x[v]-N),z=Math.max(z,R.x[v]+N)}u.push({comp:d,g:b,co:R,rk:M,layers:L.layers,minX:$,maxX:z,pinned:A.length>0})}if(s.hints&&s.hints.size){let d=e=>{let l=0,m=0;for(let x of e.comp.nodes){let M=s.hints.get(x);M&&(l+=Pt(r,M.x,M.y).x,m++)}return m?l/m:1/0},f=new Map(u.map(e=>[e,d(e)]));u.sort((e,l)=>f.get(e)-f.get(l))}let p=-1/0;for(let d of u)d.pinned&&(p=Math.max(p,d.maxX+c.componentSpacing));p===-1/0&&(p=0);for(let d of u){if(d.pinned)continue;let f=p-d.minX;for(let e=0;e<d.co.x.length;e++)d.co.x[e]+=f;p+=d.maxX-d.minX+c.componentSpacing}for(let d of u){let{g:f,co:e,rk:l}=d;d.layers.forEach((m,x)=>m.forEach((M,w)=>{let y=f.v[M];if(!y.real)return;let b=t.nodeById.get(y.id),k=tn(r,e.x[M],e.y[M]);a.nodes.set(y.id,{x:k.x-b.width/2,y:k.y-b.height/2,width:b.width,height:b.height,rank:x,order:w})}));for(let m of t.edges){if(!d.comp.set.has(m.source))continue;let M=(f.chains.get(m.id)||[]).map(y=>tn(r,e.x[y],e.y[y])),w=l.reversed.has(m.id);w&&(M=M.reverse()),a.edges.set(m.id,{waypoints:M,reversed:w,selfLoop:l.selfLoops.has(m.id),flat:l.flat.has(m.id)})}}if(!u.some(d=>d.pinned)){let d=1/0,f=1/0;for(let l of a.nodes.values())d=Math.min(d,l.x),f=Math.min(f,l.y);let e=t.groups.length?c.groupPadding+c.groupLabelHeight:0;Number.isFinite(d)&&sn(a,-d+e,-f+e)}return rn(t,a),a.bounds=Nt(a),a}function sn(t,s,c){for(let r of t.nodes.values())r.x+=s,r.y+=c;for(let r of t.edges.values())for(let o of r.waypoints)o.x+=s,o.y+=c}function rn(t,s){let c=t.options;s.groups=new Map;for(let r of t.groups){let o=1/0,n=1/0,i=-1/0,h=-1/0;for(let u of t.nodes){if(u.group!==r.id)continue;let p=s.nodes.get(u.id);p&&(o=Math.min(o,p.x),n=Math.min(n,p.y),i=Math.max(i,p.x+p.width),h=Math.max(h,p.y+p.height))}if(!Number.isFinite(o))continue;let a=c.groupPadding;s.groups.set(r.id,{x:o-a,y:n-a-c.groupLabelHeight,width:i-o+2*a,height:h-n+2*a+c.groupLabelHeight})}return s.groups}function Nt(t){let s=1/0,c=1/0,r=-1/0,o=-1/0,n=i=>{s=Math.min(s,i.x),c=Math.min(c,i.y),r=Math.max(r,i.x+i.width),o=Math.max(o,i.y+i.height)};for(let i of t.nodes.values())n(i);for(let i of t.groups.values())n(i);return Number.isFinite(s)?{x:s,y:c,width:r-s,height:o-c}:{x:0,y:0,width:0,height:0}}function Tn(t,s,c){let r=vt(t),o=new Float64Array(t.v.length).fill(NaN);t.v.forEach((n,i)=>{if(n.real&&s.has(n.id)){let h=s.get(n.id);o[i]=Pt(c,h.x,h.y).x}});for(let[,n]of t.chains){if(!n.length)continue;let i=t.v[n[0]].up[0]?.n,h=t.v[n[n.length-1]].down[0]?.n;i==null||h==null||Number.isNaN(o[i])||Number.isNaN(o[h])||n.forEach((a,u)=>{o[a]=o[i]+(o[h]-o[i])*(u+1)/(n.length+1)})}return r.map(n=>{let i=new Map(n.map((h,a)=>[h,a]));return n.slice().sort((h,a)=>{let u=o[h],p=o[a];return Number.isNaN(u)&&Number.isNaN(p)?i.get(h)-i.get(a):Number.isNaN(u)?1:Number.isNaN(p)?-1:u-p})})}function Hn(t){let s=new Map(t.nodes.map(i=>[i.id,i.id])),c=i=>{for(;s.get(i)!==i;)s.set(i,s.get(s.get(i))),i=s.get(i);return i},r=(i,h)=>{let a=c(i),u=c(h);a!==u&&s.set(u,a)};for(let i of t.edges)r(i.source,i.target);let o=new Map;for(let i of t.nodes)i.group&&(o.has(i.group)?r(o.get(i.group),i.id):o.set(i.group,i.id));for(let i of t.constraints)if(i.type==="leftOf"&&r(i.a,i.b),i.type==="sameRank")for(let h of i.nodes)r(i.nodes[0],h);let n=new Map;for(let i of t.nodes){let h=c(i.id);n.has(h)||n.set(h,[]),n.get(h).push(i.id)}return[...n.values()].map(i=>({nodes:i,set:new Set(i)}))}function zn(t,s,c){let r=Jt(c),o=J(t),n=J(s),i=n.x-o.x,h=n.y-o.y,a=Math.abs(i)-(t.width+s.width)/2,u=Math.abs(h)-(t.height+s.height)/2,p=r.x!==0?i*r.x:h*r.y,g=r.x!==0?a:u;return p>0&&g>4?[r.exit,r.entry]:a>=u?i>=0?["right","left"]:["left","right"]:h>=0?["bottom","top"]:["top","bottom"]}function an(t,s){let c=t.options.direction,r=new Map,o=new Map;for(let a of t.nodes){let u=s.get(a.id);if(!u)continue;let p=lt(a),g=new Map;for(let[d,f]of p)g.set(d,{x:u.x+f.px*u.width,y:u.y+f.py*u.height,side:f.side,t:f.t});o.set(a.id,g)}let n=new Map,i=new Map;for(let a of t.edges){let u=s.get(a.source),p=s.get(a.target);if(!u||!p)continue;if(a.source===a.target){let l=o.get(a.source),m=a.sourcePort&&l.get(a.sourcePort),x=a.targetPort&&l.get(a.targetPort),M=Math.min(20,u.width/4,u.height/4);r.set(a.id,{source:m&&m.side?{x:m.x,y:m.y,side:m.side}:{x:u.x+u.width-M,y:u.y,side:"top"},target:x&&x.side?{x:x.x,y:x.y,side:x.side}:{x:u.x+u.width,y:u.y+M,side:"right"}});continue}let[g,d]=zn(u,p,c),f=a.sourcePort&&o.get(a.source).get(a.sourcePort),e=a.targetPort&&o.get(a.target).get(a.targetPort);f&&f.side&&(g=f.side),e&&e.side&&(d=e.side),i.set(a.id,[g,d]),f||cn(n,a.source+"|"+g,{edgeId:a.id,end:"source",other:a.target}),e||cn(n,a.target+"|"+d,{edgeId:a.id,end:"target",other:a.source}),r.set(a.id,{source:f?{x:f.x,y:f.y,side:f.side}:null,target:e?{x:e.x,y:e.y,side:e.side}:null})}for(let a=0;a<2;a++)for(let[u,p]of n){let[g,d]=u.split("|"),f=s.get(g),e=d==="top"||d==="bottom",l=x=>{let M=r.get(x.edgeId),w=x.end==="source"?M.target:M.source;if(a>0&&w)return e?w.x:w.y;let y=J(s.get(x.other));return e?y.x:y.y};p.sort((x,M)=>l(x)-l(M)||(x.edgeId<M.edgeId?-1:1));let m=[...o.get(g)?.values()||[]].filter(x=>x.side===d).map(x=>x.t);p.forEach((x,M)=>{let w=(M+1)/(p.length+1);for(let b of m)Math.abs(b-w)<.06&&(w=Math.min(.95,w+.1));let y=e?{x:f.x+w*f.width,y:d==="top"?f.y:f.y+f.height,side:d}:{x:d==="left"?f.x:f.x+f.width,y:f.y+w*f.height,side:d};r.get(x.edgeId)[x.end]=y})}let h=a=>{a&&(a.x=Math.round(a.x*100)/100,a.y=Math.round(a.y*100)/100)};for(let a of r.values())h(a.source),h(a.target);return{ends:r,ports:o,sides:i}}function cn(t,s,c){t.has(s)||t.set(s,[]),t.get(s).push(c)}function ln(t,s,c){let r=c.spacing,o={h:new Map,v:new Map},n=new Map;for(let[g,d]of t)n.set(g,d.points.map(f=>({x:f.x,y:f.y})));for(let[g,d]of t){if(d.kind!=="orthogonal")continue;let f=d.points;for(let e=0;e<f.length-1;e++){if(c.fixedEnds!==!1&&(e===0||e===f.length-2))continue;let l=f[e],m=f[e+1],x=Math.abs(l.x-m.x)<.01,M=Math.abs(l.y-m.y)<.01;if(!x&&!M)continue;let w=x?l.x:l.y,y=x?Math.min(l.y,m.y):Math.min(l.x,m.x),b=x?Math.max(l.y,m.y):Math.max(l.x,m.x);if(b-y<.5)continue;let k=x?l.y<=m.y:l.x<=m.x,P=f[e-1],L=f[e+2],R=(X,G)=>X?Math.sign(x?X.x-G.x:X.y-G.y):0,A=R(P,l),$=R(L,m),z={id:g,i:e,c:w,lo:y,hi:b,vertical:x,loIsA:k,pts:n.get(g),dirLo:k?A:$,dirHi:k?$:A},v=Math.round(w*100),N=x?o.v:o.h;N.has(v)||N.set(v,[]),N.get(v).push(z)}}let i=[...o.v.values()].flat(),h=[...o.h.values()].flat(),a=[];for(let g of[!0,!1])for(let d of(g?o.v:o.h).values()){if(d.length<2)continue;d.sort((m,x)=>m.lo-x.lo);let f=[d[0]],e=d[0].hi,l=()=>{f.length>1&&u(f,g)};for(let m=1;m<d.length;m++){let x=d[m];x.lo<e-.5?(f.push(x),e=Math.max(e,x.hi)):(l(),f=[x],e=x.hi)}l()}function u(g,d){if(new Set(g.map(k=>k.id)).size<2)return;let f=[];for(let k of g){let P=f.length;for(;P>0&&Fn(k,f[P-1])<0;)P--;f.splice(P,0,k)}let e=g[0].c,l=Math.min(...g.map(k=>k.lo)),m=Math.max(...g.map(k=>k.hi)),x=1/0,M=1/0;for(let k of s.values()){let P=d?k.y:k.x;if((d?k.y+k.height:k.x+k.width)<=l||P>=m)continue;let R=d?k.x:k.y,A=d?k.x+k.width:k.y+k.height;A<=e+.01?x=Math.min(x,e-A):R>=e-.01&&(M=Math.min(M,R-e))}for(let k of d?i:h){if(k.c===e||k.hi<=l||k.lo>=m)continue;let P=Math.abs(k.c-e)/2;k.c<e?x=Math.min(x,P+4):M=Math.min(M,P+4)}let w=f.length,y=Math.max(0,Math.min(x,M)-4),b=Math.min(r,w>1?2*y/(w-1):r);f.forEach((k,P)=>{let L=(P-(w-1)/2)*b;Math.abs(L)>.01&&a.push([k.id,k.i,d,L])})}let p=new Map;for(let[g,d,f,e]of a)p.has(g)||p.set(g,new Map),p.get(g).set(d,f?{x:e,y:0}:{x:0,y:e});for(let[g,d]of p){let f=t.get(g),e=f.points,l=[],m={x:0,y:0};for(let x=0;x<e.length;x++){let M=x>0&&d.get(x-1)||m,w=x<e.length-1&&d.get(x)||m,y=x>0&&x<e.length-1&&Cn(e[x-1],e[x],e[x+1]);y&&(M.x!==w.x||M.y!==w.y)?(l.push({x:e[x].x+M.x,y:e[x].y+M.y}),l.push({x:e[x].x+w.x,y:e[x].y+w.y})):l.push({x:e[x].x+M.x+(y?0:w.x),y:e[x].y+M.y+(y?0:w.y)})}f.points=jn(l)}}function Cn(t,s,c){return Math.abs(t.x-s.x)<.01&&Math.abs(s.x-c.x)<.01||Math.abs(t.y-s.y)<.01&&Math.abs(s.y-c.y)<.01}function jn(t){let s=[];for(let c of t){let r=s[s.length-1];r&&Math.abs(r.x-c.x)<.01&&Math.abs(r.y-c.y)<.01||s.push(c)}return s}function Fn(t,s){return hn(t,s,!0)||hn(t,s,!1)||Gn(t,s)}function fn(t,s){let{pts:c,i:r,loIsA:o}=t,n=[];if(s?!o:o)for(let h=r+1;h<c.length;h++)n.push(c[h]);else for(let h=r;h>=0;h--)n.push(c[h]);return n}var Dn=(t,s)=>t.x*s.y-t.y*s.x,un=(t,s)=>{let c=s.x-t.x,r=s.y-t.y,o=Math.hypot(c,r)||1;return{x:c/o,y:r/o}};function hn(t,s,c){let r=t.vertical,o=fn(t,c),n=fn(s,c),i=c?Math.max(t.lo,s.lo):Math.min(t.hi,s.hi),h=r?{x:t.c,y:i}:{x:i,y:t.c},a=r?{x:0,y:c?-1:1}:{x:c?-1:1,y:0},u=a,p=0,g=0,d=(e,l)=>{if(e===l)return 0;let m={x:a.y,y:-a.x},x=r?m.x:m.y;return(e<l?x<0:x>0)?-1:1},f=(e,l)=>l+1<e.length?Math.sign(Math.round(Dn(u,un(e[l],e[l+1]))*1e3)):null;for(let e=0;e<64;e++){let l=p<o.length?(o[p].x-h.x)*u.x+(o[p].y-h.y)*u.y:1/0,m=g<n.length?(n[g].x-h.x)*u.x+(n[g].y-h.y)*u.y:1/0;if(l===1/0&&m===1/0)return 0;if(Math.abs(l-m)<.5){let M=f(o,p),w=f(n,g);if(M===null||w===null)return M===null&&w===null?0:d(M??0,w??0);if(M!==w)return d(M,w);h=o[p],u=un(o[p],o[p+1]),p++,g++;continue}if(l<m){let M=f(o,p);return M?d(M,0):0}let x=f(n,g);return x?d(0,x):0}return 0}var Gn=(t,s)=>t.id<s.id?-1:t.id>s.id?1:t.i-s.i;function dn(t,s,c=4){let r=[],o=new Map(s.map((a,u)=>[a,u]));for(let a of s){let u=t.get(a).points;for(let p=0;p<u.length-1;p++){let g=u[p],d=u[p+1];Math.abs(g.x-d.x)<.01&&Math.abs(g.y-d.y)>.01&&r.push([o.get(a),g.x,Math.min(g.y,d.y),Math.max(g.y,d.y)])}}let n=64,i=new Map;for(let a of r){let u=Math.floor(a[1]/n);i.has(u)||i.set(u,[]),i.get(u).push(a)}let h=new Map;for(let a of s){let u=o.get(a),p=t.get(a).points,g=[];for(let d=0;d<p.length-1;d++){let f=p[d],e=p[d+1];if(Math.abs(f.y-e.y)>.01)continue;let l=Math.min(f.x,e.x)+c*2,m=Math.max(f.x,e.x)-c*2;if(!(m<=l))for(let x=Math.floor(l/n);x<=Math.floor(m/n);x++)for(let M of i.get(x)||[])M[0]>=u||M[1]<=l||M[1]>=m||f.y<=M[2]+c||f.y>=M[3]-c||g.push({seg:d,x:M[1],y:f.y})}g.length&&h.set(a,g)}return h}var Et=1,Un=[1,-1,0,0],Yn=[0,0,1,-1],Ot=[1,0,3,2],pn=t=>t.x>0?0:t.x<0?1:t.y>0?2:3;function gn(t,s,c={}){let r=t.options,o=s.nodes,n=r.edgeRouting,{ends:i,ports:h}=an(t,o),a=new Map,u=new Map,p=c.only||null,g=c.prev||null;if(n==="orthogonal")_n(t,o,i,r,p,g,a,u),ln(a,o,{spacing:r.edgeSpacing,fixedEnds:!0});else for(let e of t.edges){let l=o.get(e.source),m=o.get(e.target);if(!l||!m)continue;if(e.source===e.target){a.set(e.id,yn(l,r,i.get(e.id)));continue}let x=s.edges.get(e.id),M=x&&x.waypoints||[],w=i.get(e.id),y,b;n==="curved"||e.sourcePort?y=w.source:y=It(l,M[0]||J(m)),n==="curved"||e.targetPort?b=w.target:b=It(m,M[M.length-1]||J(l)),a.set(e.id,{points:[y,...M.map(k=>({...k})),b],kind:n,sourceSide:y.side,targetSide:b.side})}let d=t.edges.map(e=>e.id).filter(e=>a.has(e)),f=r.lineHops&&n==="orthogonal"?dn(a,d,r.hopRadius):new Map;for(let[e,l]of a)l.hops=f.get(e)||[];return{paths:a,raw:u,ports:h,mode:n}}function yn(t,s,c){let r=Math.max(s.nodeMargin*1.5,16),o=c.source,n=c.target,i=ct[o.side],h=ct[n.side],a={x:o.x+i.x*r,y:o.y+i.y*r},u={x:n.x+h.x*r,y:n.y+h.y*r},p;if(o.side===n.side)p=o.side==="left"||o.side==="right"?[a,{x:a.x,y:u.y}]:[a,{x:u.x,y:a.y}];else if((o.side==="top"||o.side==="bottom")!=(n.side==="top"||n.side==="bottom"))p=o.side==="top"||o.side==="bottom"?[a,{x:u.x,y:a.y}]:[a,{x:a.x,y:u.y}];else{let g=o.side==="top"||o.side==="bottom",d=g?t.x+t.width+r:t.y+t.height+r;p=g?[a,{x:d,y:a.y},{x:d,y:u.y}]:[a,{x:a.x,y:d},{x:u.x,y:d}]}return{points:St([o,...p,u,n]),kind:"orthogonal",sourceSide:o.side,targetSide:n.side,selfLoop:!0}}function _n(t,s,c,r,o,n,i,h){let a=r.nodeMargin,u=[];for(let[e,l]of s)u.push({id:e,...Qt(l,a)});let p=new Map;for(let e of t.edges){let l=c.get(e.id);if(!l||!l.source||!l.target)continue;let m=ct[l.source.side],x=ct[l.target.side];p.set(e.id,{s:{x:l.source.x+m.x*a,y:l.source.y+m.y*a},t:{x:l.target.x+x.x*a,y:l.target.y+x.y*a},sDir:pn(m),tNeed:Ot[pn(x)]})}let g=Wn(u,p,a);for(let e of t.edges)if(o&&!o.has(e.id)&&n&&n.raw.has(e.id)){let l=n.raw.get(e.id);h.set(e.id,l),g.markPath(l);let m=n.paths.get(e.id);m&&i.set(e.id,{...m,points:l.map(x=>({...x}))})}let d=t.edges.filter(e=>!i.has(e.id)&&s.has(e.source)&&s.has(e.target)),f=e=>{let l=p.get(e.id);return l?Math.abs(l.s.x-l.t.x)+Math.abs(l.s.y-l.t.y):0};d.sort((e,l)=>f(e)-f(l));for(let e of d){if(e.source===e.target){let w=yn(s.get(e.source),r,c.get(e.id));i.set(e.id,w),h.set(e.id,w.points);continue}let l=c.get(e.id),m=p.get(e.id),x=g.astar(m.s,m.sDir,m.t,m.tNeed,r);x||(x=Vn(m.s,m.t,l.source.side,l.target.side));let M=[l.source,...St(x),l.target];g.markPath(M),h.set(e.id,M),i.set(e.id,{points:M.map(w=>({...w})),kind:"orthogonal",sourceSide:l.source.side,targetSide:l.target.side})}}function Vn(t,s,c,r){let o=c==="top"||c==="bottom",n=r==="top"||r==="bottom";if(o&&n){let i=(t.y+s.y)/2;return[t,{x:t.x,y:i},{x:s.x,y:i},s]}if(!o&&!n){let i=(t.x+s.x)/2;return[t,{x:i,y:t.y},{x:i,y:s.y},s]}return o?[t,{x:t.x,y:s.y},s]:[t,{x:s.x,y:t.y},s]}function Wn(t,s,c){let r=new Set,o=new Set,n=I=>Math.round(I*100)/100,i=1/0,h=1/0,a=-1/0,u=-1/0;for(let I of t)r.add(n(I.x)),r.add(n(I.x+I.width)),o.add(n(I.y)),o.add(n(I.y+I.height)),i=Math.min(i,I.x),h=Math.min(h,I.y),a=Math.max(a,I.x+I.width),u=Math.max(u,I.y+I.height);for(let I of s.values())for(let S of[I.s,I.t])r.add(n(S.x)),o.add(n(S.y)),i=Math.min(i,S.x),h=Math.min(h,S.y),a=Math.max(a,S.x),u=Math.max(u,S.y);r.add(n(i-2*c)),r.add(n(a+2*c)),o.add(n(h-2*c)),o.add(n(u+2*c));let p=I=>{let S=[...I].sort((O,U)=>O-U),E=[];for(let O=0;O<S.length;O++)E.push(S[O]),O+1<S.length&&S[O+1]-S[O]>4&&E.push(n((S[O]+S[O+1])/2));return E},g=p(r),d=p(o),f=g.length,e=d.length,l=f*e,m=new Map(g.map((I,S)=>[I,S])),x=new Map(d.map((I,S)=>[I,S])),M=120,w=new Map,y=(I,S)=>I*73856093^S*19349663;for(let I of t)for(let S=Math.floor(I.x/M);S<=Math.floor((I.x+I.width)/M);S++)for(let E=Math.floor(I.y/M);E<=Math.floor((I.y+I.height)/M);E++){let O=y(S,E);w.has(O)||w.set(O,[]),w.get(O).push(I)}let b=(I,S)=>{let E=w.get(y(Math.floor(I/M),Math.floor(S/M)));if(!E)return!1;for(let O of E)if(qt(O,I,S,.01))return!0;return!1},k=l<=4e6?new Uint8Array(l):null,P=k?null:new Map,L=I=>{if(k){let E=k[I];return E||(E=b(g[I%f],d[I/f|0])?2:1,k[I]=E),E===2}let S=P.get(I);return S===void 0&&(S=b(g[I%f],d[I/f|0]),P.set(I,S)),S},R=new Uint8Array(l),A=new Uint8Array(l),$=(I,S)=>{let E=S?R:A,O=E[I];if(!O){let U=I%f,Y=I/f|0,T=S?(g[U]+g[U+1])/2:g[U],j=S?d[Y]:(d[Y]+d[Y+1])/2;O=b(T,j)?2:1,E[I]=O}return O===2},z=new Uint16Array(l),v=new Uint16Array(l),N=new Uint16Array(l),X=new Uint16Array(l),G=I=>{let S=m.get(n(I.x)),E=x.get(n(I.y));return S==null||E==null?-1:E*f+S};function V(I){for(let S=0;S<I.length-1;S++){let E=I[S],O=I[S+1],U=Math.abs(E.y-O.y)<.01,Y=Math.abs(E.x-O.x)<.01;if(U){let T=x.get(n(E.y)),j=m.get(n(E.x)),D=m.get(n(O.x));if(T==null||j==null||D==null)continue;let q=Math.min(j,D),tt=Math.max(j,D);for(let C=q;C<=tt;C++)z[T*f+C]++,C<tt&&N[T*f+C]++}else if(Y){let T=m.get(n(E.x)),j=x.get(n(E.y)),D=x.get(n(O.y));if(T==null||j==null||D==null)continue;let q=Math.min(j,D),tt=Math.max(j,D);for(let C=q;C<=tt;C++)v[C*f+T]++,C<tt&&X[C*f+T]++}}}let Q=l*4,W=Q<=16e6,At=W?new Float64Array(Q):null,Bt=W?new Int32Array(Q):null,$t=W?new Uint32Array(Q):null,dt=0;function xn(I,S,E,O,U){let Y=G(I),T=G(E);if(Y<0||T<0)return null;let j=g[T%f],D=d[T/f|0],q=U.bendPenalty,tt=U.crossingPenalty;dt++;let C=W?null:new Map,Xt=W?null:new Map,Tt=W?B=>$t[B]===dt?At[B]:void 0:B=>C.get(B),Ht=W?(B,F,K)=>{$t[B]=dt,At[B]=F,Bt[B]=K}:(B,F,K)=>{C.set(B,F),Xt.set(B,K)},mn=W?B=>Bt[B]:B=>Xt.get(B),ot=new Lt,zt=Y*4+S;Ht(zt,0,-1),ot.push(zt,Et*(Math.abs(g[Y%f]-j)+Math.abs(d[Y/f|0]-D)));let pt=1/0,gt=-1,wn=0,Mn=4e5;for(;ot.size;){let B=ot.peekKey(),F=ot.pop();if(B>=pt)break;let K=Tt(F),nt=F>>2,at=F&3,xt=nt%f,mt=nt/f|0;if(!(B>K+Et*(Math.abs(g[xt]-j)+Math.abs(d[mt]-D))+1e-6)){if(++wn>Mn)break;if(nt===T){let H=at===O?0:at===Ot[O]?2*q:q;K+H<pt&&(pt=K+H,gt=F);continue}for(let H=0;H<4;H++){if(H===Ot[at])continue;let st=xt+Un[H],it=mt+Yn[H];if(st<0||it<0||st>=f||it>=e)continue;let _=it*f+st;if(_!==T&&L(_))continue;let rt=H<2;if($(rt?H===0?nt:_:H===2?nt:_,rt))continue;let Ct=Math.abs(rt?g[st]-g[xt]:d[it]-d[mt]),ft=Ct;H!==at&&(ft+=q);let jt=H===0||H===2?nt:_,Ft=rt?N[jt]:X[jt];Ft&&(ft+=Ct*.25*Ft),_!==T&&(rt?v[_]:z[_])&&(ft+=tt);let wt=_*4+H,Mt=K+ft,Dt=Tt(wt);(Dt===void 0||Mt<Dt-1e-9)&&(Ht(wt,Mt,F),ot.push(wt,Mt+Et*(Math.abs(g[st]-j)+Math.abs(d[it]-D))))}}}if(gt<0)return null;let yt=[];for(let B=gt;B!==-1&&B!==void 0;B=mn(B)){let F=B>>2;yt.push({x:g[F%f],y:d[F/f|0]})}return yt.reverse(),yt}return{astar:xn,markPath:V,xs:g,ys:d,N:l}}var Lt=class{constructor(){this.k=[],this.v=[]}get size(){return this.k.length}push(s,c){let r=this.k,o=this.v,n=r.length;for(r.push(c),o.push(s);n>0;){let i=n-1>>1;if(r[i]<=c)break;r[n]=r[i],o[n]=o[i],n=i}r[n]=c,o[n]=s}peekKey(){return this.k[0]}pop(){let s=this.k,c=this.v,r=c[0],o=s.pop(),n=c.pop();if(s.length){let i=0,h=s.length;for(;;){let a=2*i+1;if(a>=h||(a+1<h&&s[a+1]<s[a]&&a++,s[a]>=o))break;s[i]=s[a],c[i]=c[a],i=a}s[i]=o,c[i]=n}return r}};self.onmessage=t=>{let{seq:s,data:c,options:r,hints:o}=t.data;try{let n=Ut(c,r),i=on(n,{hints:o||null}),h=gn(n,i);self.postMessage({seq:s,nodes:i.nodes,edges:i.edges,crossings:i.crossings,routing:{paths:h.paths,raw:h.raw,ports:h.ports,mode:h.mode}})}catch(n){self.postMessage({seq:s,error:String(n&&n.message||n)})}};
1
+ /*! FlexGraph v1.3.0 | MIT License | (c) 2026 Alexander Pettersen (kazant) | https://github.com/kazant/flexgraph */
2
+ var kn=["top","right","bottom","left"],vn=["TB","LR","BT","RL"],Sn=["orthogonal","straight","curved"],Ut=Object.freeze({direction:"TB",nodeSpacing:40,rankSpacing:80,edgeSpacing:10,edgeRouting:"orthogonal",cornerRadius:6,lineHops:!0,hopRadius:4,animate:!0,animationDuration:300,nodeMargin:14,groupPadding:20,groupLabelHeight:22,componentSpacing:80,maxIterations:24,bendPenalty:24,crossingPenalty:120,bundleFanOut:5,defaultNodeWidth:160,defaultNodeHeight:60,pinOnDrag:!0,draggable:!0,zoomable:!0,pannable:!0,minZoom:.1,maxZoom:4,controls:!0,showPorts:!0,hoverHighlight:"chain",highlightSelection:!0,multiSelect:!0,history:!0,historyLimit:100,expandText:"Details",collapseText:"Hide",explore:!1,exploreUnfocused:"dim",exploreLimit:25,exploreBreadcrumb:!0,exploreStartText:"Start",exploreMoreText:void 0,edgeTypes:{default:{markerEnd:"arrow"},"has-many":{markerStart:"one",markerEnd:"many"},"has-one":{markerStart:"one",markerEnd:"onlyOne"},"belongs-to":{markerStart:"many",markerEnd:"one"},"many-to-many":{markerStart:"many",markerEnd:"many"},association:{markerEnd:"open"},composition:{markerStart:"diamond"},dependency:{markerEnd:"open"}}}),ut=class extends Error{constructor(s,c=[]){super(s),this.name="GraphValidationError",this.details=c}},Z=t=>typeof t=="number"&&Number.isFinite(t);function In(...t){let s={...Ut,edgeTypes:{...Ut.edgeTypes}};for(let c of t)if(c)for(let[i,o]of Object.entries(c))o!==void 0&&(i==="edgeTypes"?Object.assign(s.edgeTypes,o):s[i]=o);return vn.includes(s.direction)||(s.direction="TB"),Sn.includes(s.edgeRouting)||(s.edgeRouting="orthogonal"),s}function Gt(t,s,c){if(!t||typeof t!="object")throw new ut("Graph must be an object");let i=In(t.options,s),o=[],n=[],r=[],h=new Map;for(let f of t.groups||[]){if(!f||f.id==null){o.push("Group without id");continue}let e=String(f.id);if(h.has(e)){o.push(`Duplicate group id "${e}"`);continue}let l={id:e,label:f.label??e,className:f.className||"",data:f};r.push(l),h.set(e,l)}let a=[],u=new Map;(t.nodes||[]).forEach((f,e)=>{if(!f||f.id==null){o.push(`Node at index ${e} has no id`);return}let l=String(f.id);if(u.has(l)){o.push(`Duplicate node id "${l}"`);return}let w=c&&c.get(l),x=Z(f.width)?f.width:w?w.width:i.defaultNodeWidth,M=Z(f.height)?f.height:w?w.height:i.defaultNodeHeight,m=f.group!=null?String(f.group):null;if(m&&!h.has(m)){let I={id:m,label:m,className:"",data:{id:m}};r.push(I),h.set(m,I)}let y=[],b=new Set;for(let I of f.ports||[]){if(!I||I.id==null){n.push(`Node "${l}": port without id ignored`);continue}let R=String(I.id);if(b.has(R)){n.push(`Node "${l}": duplicate port "${R}" ignored`);continue}let B=kn.includes(I.side)?I.side:null;B||n.push(`Node "${l}": port "${R}" has invalid side "${I.side}", using auto side`),b.add(R),y.push({id:R,side:B,offset:Z(I.offset)?Math.min(1,Math.max(0,I.offset)):null,label:I.label,data:I})}let k=f.constraints||{},O={pinned:!!k.pinned,x:Z(k.x)?k.x:Z(f.x)&&k.pinned?f.x:null,y:Z(k.y)?k.y:Z(f.y)&&k.pinned?f.y:null,rank:Number.isInteger(k.rank)&&k.rank>=0?k.rank:null};O.pinned&&(O.x==null||O.y==null)&&(n.push(`Node "${l}" is pinned but has no x/y; pin ignored until it has a position`),O.pinned=!1);let N={id:l,index:e,label:f.label??l,width:x,height:M,group:m,ports:y,portById:new Map(y.map(I=>[I.id,I])),constraints:O,className:f.className||"",type:f.type||null,data:f};a.push(N),u.set(l,N)});let g=[],p=new Map;(t.edges||[]).forEach((f,e)=>{if(!f)return;let l=f.id!=null?String(f.id):`e${e}`;if(p.has(l)){o.push(`Duplicate edge id "${l}"`);return}let w=String(f.source),x=String(f.target);if(!u.has(w)){o.push(`Edge "${l}": unknown source node "${w}"`);return}if(!u.has(x)){o.push(`Edge "${l}": unknown target node "${x}"`);return}let M=f.sourcePort!=null?String(f.sourcePort):null,m=f.targetPort!=null?String(f.targetPort):null;M&&!u.get(w).portById.has(M)&&(n.push(`Edge "${l}": node "${w}" has no port "${M}"`),M=null),m&&!u.get(x).portById.has(m)&&(n.push(`Edge "${l}": node "${x}" has no port "${m}"`),m=null);let y=i.edgeTypes[f.type]||i.edgeTypes.default||{},b={id:l,index:e,source:w,target:x,sourcePort:M,targetPort:m,type:f.type||"default",label:f.label??null,minLen:Number.isInteger(f.minLen)&&f.minLen>=0?f.minLen:1,weight:Z(f.weight)?f.weight:1,markerStart:f.markerStart!==void 0?f.markerStart:y.markerStart||null,markerEnd:f.markerEnd!==void 0?f.markerEnd:y.markerEnd||null,className:f.className||"",data:f};g.push(b),p.set(l,b)});let d=[];for(let f of t.constraints||[])if(!(!f||!f.type))if(f.type==="leftOf"||f.type==="before"){let e=String(f.a),l=String(f.b);if(!u.has(e)||!u.has(l)){n.push("leftOf constraint references unknown node");continue}d.push({type:"leftOf",a:e,b:l})}else if(f.type==="sameRank"){let e=(f.nodes||[]).map(String).filter(l=>u.has(l));e.length>=2?d.push({type:"sameRank",nodes:e}):n.push("sameRank constraint needs at least two known nodes")}else if(f.type==="rank"){let e=String(f.node);u.has(e)&&Number.isInteger(f.rank)&&(u.get(e).constraints.rank=f.rank)}else n.push(`Unknown constraint type "${f.type}"`);if(o.length)throw new ut(o[0],o);return{options:i,nodes:a,nodeById:u,edges:g,edgeById:p,groups:r,groupById:h,constraints:d,warnings:n}}function Pn(t,s){let c=new Map(t.map(h=>[h,[]])),i=new Map(t.map(h=>[h,0]));for(let h of s)c.get(h.v).push(h),i.set(h.w,i.get(h.w)+1);let o=new Map,n=new Set,r=[...t.filter(h=>i.get(h)===0),...t];for(let h of r){if(o.has(h))continue;let a=[[h,0]];for(o.set(h,1);a.length;){let u=a[a.length-1],[g,p]=u,d=c.get(g);if(p>=d.length){o.set(g,2),a.pop();continue}u[1]++;let f=d[p],e=o.get(f.w);e===1?n.add(f.id):e||(o.set(f.w,1),a.push([f.w,0]))}}return n}var kt=class{constructor(s){this.p=new Map(s.map(c=>[c,c]))}find(s){let c=s;for(;this.p.get(c)!==c;)c=this.p.get(c);for(;this.p.get(s)!==c;){let i=this.p.get(s);this.p.set(s,c),s=i}return c}union(s,c){let i=this.find(s),o=this.find(c);i!==o&&this.p.set(o,i)}};function Yt(t,s,c={}){let i=[],o=new kt(t);for(let y of c.sameRank||[])for(let b=1;b<y.length;b++)o.union(y[0],y[b]);let n=[...new Set(t.map(y=>o.find(y)))],r=new Set,h=new Set,a=[];for(let y of s){if(y.source===y.target){r.add(y.id);continue}let b=o.find(y.source),k=o.find(y.target);if(b===k){h.add(y.id);continue}a.push({id:y.id,v:b,w:k,minLen:y.minLen??1})}let u=Pn(n,a),g=a.map(y=>u.has(y.id)?{...y,v:y.w,w:y.v}:y),p=new Map;if(c.fixedRank)for(let[y,b]of c.fixedRank){if(!o.p.has(y))continue;let k=o.find(y);p.has(k)&&p.get(k)!==b&&i.push(`Conflicting fixed ranks in sameRank set of "${y}"`),p.set(k,Math.max(p.get(k)??0,b))}let d=new Map(n.map(y=>[y,[]])),f=new Map(n.map(y=>[y,[]]));for(let y of g)d.get(y.v).push(y),f.get(y.w).push(y);let e=new Map(n.map(y=>[y,f.get(y).length])),l=n.filter(y=>e.get(y)===0),w=[];for(;l.length;){let y=l.shift();w.push(y);for(let b of d.get(y))e.set(b.w,e.get(b.w)-1),e.get(b.w)===0&&l.push(b.w)}let x=new Map;for(let y of w){let b=p.get(y)??0;for(let k of f.get(y))b=Math.max(b,x.get(k.v)+k.minLen);p.has(y)&&b!==p.get(y)&&i.push(`Fixed rank ${p.get(y)} for "${y}" cannot be satisfied; using ${b}`),x.set(y,b)}for(let y=w.length-1;y>=0;y--){let b=w[y];if(p.has(b))continue;let k=d.get(b);if(!k.length||f.get(b).length>=k.length)continue;let N=1/0;for(let I of k)N=Math.min(N,x.get(I.w)-I.minLen);N>x.get(b)&&x.set(b,N)}let M=1/0;for(let y of x.values())M=Math.min(M,y);if(!p.size&&M>0)for(let[y,b]of x)x.set(y,b-M);let m=new Map;for(let y of t)m.set(y,x.get(o.find(y))??0);return{rank:m,reversed:u,flat:h,selfLoops:r,warnings:i}}function Vt(t,s,c=0){let i=[],o=new Map;for(let u of t)o.set(u.id,i.length),i.push({id:u.id,real:!0,rank:u.rank,width:u.width,height:u.height??0,group:u.group??null,pinX:u.pinX??null,inputIndex:i.length,up:[],down:[]});let n=new Map,r=[],h=(u,g,p,d,f,e)=>{let l={a:u,b:g,aOff:p,bOff:d,w:f,edgeId:e};r.push(l),i[u].down.push({n:g,off:d,own:p,w:f}),i[g].up.push({n:u,off:p,own:d,w:f})};for(let u of s){let g=o.get(u.v),p=o.get(u.w),d=i[g].rank,f=i[p].rank;if(f<=d)continue;let e=i[g].group&&i[g].group===i[p].group?i[g].group:null,l=[],w=g,x=u.vOff||0;for(let M=d+1;M<f;M++){let m=i.length;i.push({id:`__d_${u.id}_${M}`,real:!1,rank:M,width:c,height:0,group:e,pinX:null,edgeId:u.id,inputIndex:m,up:[],down:[]}),h(w,m,x,0,u.weight??1,u.id),l.push(m),w=m,x=0}h(w,p,x,u.wOff||0,u.weight??1,u.id),n.set(u.id,l)}let a=0;for(let u of i)a=Math.max(a,u.rank);return{v:i,index:o,segs:r,chains:n,maxRank:a}}function St(t){let s=Array.from({length:t.maxRank+1},()=>[]),c=new Uint8Array(t.v.length),i=t.v.map((o,n)=>n).filter(o=>t.v[o].real).sort((o,n)=>t.v[o].rank-t.v[n].rank||t.v[o].inputIndex-t.v[n].inputIndex);for(let o of i){if(c[o])continue;let n=[o];for(;n.length;){let r=n.pop();if(c[r])continue;c[r]=1,s[t.v[r].rank].push(r);let h=t.v[r].down.map(a=>a.n);for(let a=h.length-1;a>=0;a--)c[h[a]]||n.push(h[a])}}for(let o=0;o<t.v.length;o++)c[o]||s[t.v[o].rank].push(o);return s}function On(t){let s=t.length;if(s<2)return 0;let c=t.slice(),i=new Array(s),o=0;for(let n=1;n<s;n*=2){for(let r=0;r<s;r+=2*n){let h=Math.min(r+n,s),a=Math.min(r+2*n,s),u=r,g=h,p=r;for(;u<h&&g<a;)c[u]<=c[g]?i[p++]=c[u++]:(o+=h-u,i[p++]=c[g++]);for(;u<h;)i[p++]=c[u++];for(;g<a;)i[p++]=c[g++]}[c,i]=[i,c]}return o}function Rn(t,s,c,i){let o=[];for(let n of s)for(let r of t.v[n].down)o.push([i[n]+r.own*.999,i[r.n]+r.off*.999]);return o.sort((n,r)=>n[0]-r[0]||n[1]-r[1]),On(o.map(n=>n[1]))}function vt(t,s){let c=lt(t,s),i=0;for(let o=0;o<s.length-1;o++)i+=Rn(t,s[o],s[o+1],c);return i}function lt(t,s){let c=new Float64Array(t.v.length);for(let i of s)i.forEach((o,n)=>{c[o]=n});return c}function Wt(t,s={}){let c=s.maxIterations??24,i=(s.leftOf||[]).map(([u,g])=>[t.index.get(u),t.index.get(g)]).filter(([u,g])=>u!=null&&g!=null&&t.v[u].rank===t.v[g].rank),o=new Set(i.map(([u,g])=>u+":"+g)),n=[];s.initial&&n.push(s.initial.map(u=>u.slice()));let r=St(t);n.push(r),!s.initial&&c>4&&(n.push(r.map(u=>u.slice().reverse())),n.push(r.map(u=>u.slice().sort((g,p)=>t.v[g].inputIndex-t.v[p].inputIndex))));let h=null,a=1/0;for(let u of n){let g=En(t,u,i,o,c);if(g.crossings<a&&(h=g.layers,a=g.crossings),a===0)break}return{layers:h,crossings:a}}function En(t,s,c,i,o){let n=s.map(u=>Kt(t,u,c)),r=n.map(u=>u.slice()),h=vt(t,n),a=0;for(let u=0;u<o&&h>0;u++){let g=u%2===0;Ln(t,n,g,c,u%4>=2),An(t,n,i);let p=vt(t,n);if(p<h)h=p,r=n.map(d=>d.slice()),a=0;else if(++a>=6)break}if(h>0&&o>4){n=r.map(u=>u.slice());for(let u=0;u<2;u++){Nn(t,n,i);let g=vt(t,n);if(g<h)h=g,r=n.map(p=>p.slice());else break}}return{layers:r,crossings:h}}function Nn(t,s,c){let i=lt(t,s);for(let o of s)if(!(o.length<3||o.length>120))for(let n of o.slice()){let r=t.v[n];if(r.pinX!=null||r.group)continue;let h=o.indexOf(n),a=0,u=h,g=0;for(let p=h-1;p>=0;p--){let d=o[p];if(c.has(d+":"+n)||t.v[d].group)break;g+=et(t,n,d,i)-et(t,d,n,i),g<a&&(a=g,u=p)}g=0;for(let p=h+1;p<o.length;p++){let d=o[p];if(c.has(n+":"+d)||t.v[d].group)break;g+=et(t,d,n,i)-et(t,n,d,i),g<a&&(a=g,u=p)}u!==h&&(o.splice(h,1),o.splice(u,0,n),o.forEach((p,d)=>{i[p]=d}))}}function Ln(t,s,c,i,o){let n=lt(t,s),r=s.length,h=c?_t(1,r):_t(r-2,-1,-1);for(let a of h){let u=s[a],g=new Map;u.forEach((e,l)=>{let w=c?t.v[e].up:t.v[e].down;if(!w.length){g.set(e,l);return}if(o){let m=w.map(b=>n[b.n]+b.off-b.own).sort((b,k)=>b-k),y=m.length>>1;g.set(e,m.length%2?m[y]:(m[y-1]+m[y])/2);return}let x=0,M=0;for(let m of w)x+=(n[m.n]+m.off-m.own)*m.w,M+=m.w;g.set(e,x/M)});let p=new Map;for(let e of u){let l=t.v[e].group;if(!l)continue;let w=p.get(l)||[0,0];w[0]+=g.get(e),w[1]++,p.set(l,w)}let d=e=>{let l=t.v[e].group;return l?p.get(l)[0]/p.get(l)[1]:g.get(e)},f=new Map(u.map((e,l)=>[e,l]));u.sort((e,l)=>d(e)-d(l)||(t.v[e].group||"").localeCompare(t.v[l].group||"")||g.get(e)-g.get(l)||f.get(e)-f.get(l)),s[a]=Kt(t,u,i),s[a].forEach((e,l)=>{n[e]=l})}}function Kt(t,s,c){let i=s.slice(),o=[],n=[];if(i.forEach((r,h)=>{t.v[r].pinX!=null&&(o.push(h),n.push(r))}),n.length>1&&(n.sort((r,h)=>t.v[r].pinX-t.v[h].pinX),o.forEach((r,h)=>{i[r]=n[h]})),c.length)for(let r=0;r<c.length+1;r++){let h=!1;for(let[a,u]of c){let g=i.indexOf(a),p=i.indexOf(u);g<0||p<0||g<p||(i.splice(g,1),i.splice(i.indexOf(u),0,a),h=!0)}if(!h)break}return i}function et(t,s,c,i){let o=0;for(let n of["up","down"]){let r=t.v[s][n],h=t.v[c][n];for(let a of r)for(let u of h)i[a.n]+a.off>i[u.n]+u.off&&(o+=a.w*u.w)}return o}function An(t,s,c){let i=lt(t,s),o=!0,n=0;for(;o&&n++<8;){o=!1;for(let r of s)for(let h=0;h<r.length-1;h++){let a=r[h],u=r[h+1],g=t.v[a],p=t.v[u];if((g.group||null)!==(p.group||null)||g.pinX!=null&&p.pinX!=null||c.has(a+":"+u))continue;let d=et(t,a,u,i);et(t,u,a,i)<d&&(r[h]=u,r[h+1]=a,i[u]=h,i[a]=h+1,o=!0)}}}function _t(t,s,c=1){let i=[];if(c>0)for(let o=t;o<s;o+=c)i.push(o);else for(let o=t;o>s;o+=c)i.push(o);return i}function Bn(t,s,c){let i=t.length,o=new Float64Array(i);for(let g=1;g<i;g++)o[g]=o[g-1]+c[g];let n=[],r=[],h=[],a=[];for(let g=0;g<i;g++)for(n.push(t[g]-o[g]),r.push(s[g]),h.push(g),a.push(g);n.length>1&&n[n.length-2]>n[n.length-1];){let p=n.length-1,d=p-1,f=r[d]+r[p];n[d]=(n[d]*r[d]+n[p]*r[p])/f,r[d]=f,a[d]=a[p],n.pop(),r.pop(),h.pop(),a.pop()}let u=new Float64Array(i);for(let g=0;g<n.length;g++)for(let p=h[g];p<=a[g];p++)u[p]=n[g]+o[p];return u}function Zt(t,s,c){let i=t.v.length,o=new Float64Array(i),n=new Float64Array(i),r=c.groupPadding??20,h=c.groupLabelHeight??0,a=(m,y)=>{let b=t.v[m],k=t.v[y],O;return!b.real&&!k.real?O=c.edgeSpacing:!b.real||!k.real?O=(c.nodeSpacing+c.edgeSpacing)/2:O=c.nodeSpacing,b.group!==k.group&&(b.group&&(O+=r),k.group&&(O+=r+(c.labelOnOrderAxis?h:0))),(b.width+k.width)/2+O},u=s.map(m=>m.map((y,b)=>b===0?0:a(m[b-1],y)));s.forEach((m,y)=>{let b=0;m.forEach((O,N)=>{b+=u[y][N],o[O]=b});let k=b/2;m.forEach(O=>{o[O]-=k})});let g=m=>t.v[m].real?1:4,p=(m,y,b)=>{let k=s[m];if(!k.length)return;let O=new Array(k.length),N=new Array(k.length);k.forEach((R,B)=>{let T=t.v[R];if(T.pinX!=null){O[B]=T.pinX,N[B]=1e6;return}let v=0,E=0,X=U=>{for(let V of U){let Q=V.w*(t.v[V.n].real?1:2)*g(R);v+=(o[V.n]+V.off*t.v[V.n].width-V.own*T.width)*Q,E+=Q}};y&&X(T.up),b&&X(T.down),E===0?(O[B]=o[R],N[B]=.05):(O[B]=v/E,N[B]=E)});let I=Bn(O,N,u[m]);k.forEach((R,B)=>{o[R]=I[B]})},d=s.length,f=c.iterations??8;for(let m=0;m<f;m++){for(let y=1;y<d;y++)p(y,!0,!1);for(let y=d-2;y>=0;y--)p(y,!1,!0)}for(let m=0;m<2;m++){for(let y=0;y<d;y++)p(y,!0,!0);for(let y=d-1;y>=0;y--)p(y,!0,!0)}let e=s.map(m=>m.reduce((y,b)=>Math.max(y,t.v[b].height||0),0)),l=new Map;for(let m of t.v){if(!m.real||!m.group)continue;let y=l.get(m.group)||[1/0,-1/0];y[0]=Math.min(y[0],m.rank),y[1]=Math.max(y[1],m.rank),l.set(m.group,y)}let w=new Float64Array(d);for(let[m,y]of l.values()){let b=c.labelOnOrderAxis||c.labelAtRankEnd?0:h,k=c.labelAtRankEnd&&!c.labelOnOrderAxis?h:0;m>0&&(w[m]=Math.max(w[m],r+b)),y<d-1&&(w[y+1]=Math.max(w[y+1],r+k))}let x=[],M=0;for(let m=0;m<d;m++)m>0?M+=e[m-1]/2+c.rankSpacing+w[m]+e[m]/2:M=e[0]/2,x.push(M);for(let m=0;m<i;m++)n[m]=x[t.v[m].rank];return{x:o,y:n,rankY:x,rankHeight:e}}var ot={top:{x:0,y:-1},bottom:{x:0,y:1},left:{x:-1,y:0},right:{x:1,y:0}};function Jt(t){switch(t){case"LR":return{x:1,y:0,exit:"right",entry:"left"};case"RL":return{x:-1,y:0,exit:"left",entry:"right"};case"BT":return{x:0,y:-1,exit:"top",entry:"bottom"};default:return{x:0,y:1,exit:"bottom",entry:"top"}}}function ht(t){let s=new Map,c={top:[],right:[],bottom:[],left:[]};for(let i of t.ports)i.side&&c[i.side].push(i);for(let i of Object.keys(c)){let o=c[i];o.forEach((n,r)=>{let h=n.offset!=null?n.offset:(r+1)/(o.length+1);s.set(n.id,{side:i,t:h,...$n(i,h)})})}return s}function $n(t,s){switch(t){case"top":return{px:s,py:0};case"bottom":return{px:s,py:1};case"left":return{px:0,py:s};default:return{px:1,py:s}}}var J=t=>({x:t.x+t.width/2,y:t.y+t.height/2});function Qt(t,s){return{x:t.x-s,y:t.y-s,width:t.width+2*s,height:t.height+2*s}}function qt(t,s,c,i=.5){return s>t.x+i&&s<t.x+t.width-i&&c>t.y+i&&c<t.y+t.height-i}function tn(t,s,c,i=.5){let o=c.x+i,n=c.x+c.width-i,r=c.y+i,h=c.y+c.height-i;if(n<=o||h<=r)return!1;let a=0,u=1,g=s.x-t.x,p=s.y-t.y,d=(f,e)=>{if(f===0)return e>0;let l=e/f;if(f<0){if(l>u)return!1;l>a&&(a=l)}else{if(l<a)return!1;l<u&&(u=l)}return!0};return!d(-g,t.x-o)||!d(g,n-t.x)||!d(-p,t.y-r)||!d(p,h-t.y)?!1:u-a>1e-9}function It(t,s){let c=J(t),i=s.x-c.x,o=s.y-c.y;if(i===0&&o===0)return{...c,side:"bottom"};let n=i!==0?t.width/2/Math.abs(i):1/0,r=o!==0?t.height/2/Math.abs(o):1/0,h=Math.min(n,r),a=n<r?i>0?"right":"left":o>0?"bottom":"top";return{x:c.x+i*h,y:c.y+o*h,side:a}}function dt(t){let s=[];for(let c of t){let i=s[s.length-1];i&&Math.abs(i.x-c.x)<.01&&Math.abs(i.y-c.y)<.01||s.push({x:c.x,y:c.y})}for(let c=s.length-2;c>=1;c--){let i=s[c-1],o=s[c],n=s[c+1],r=(o.x-i.x)*(n.y-o.y)-(o.y-i.y)*(n.x-o.x),h=(o.x-i.x)*(n.x-o.x)+(o.y-i.y)*(n.y-o.y);Math.abs(r)<.01&&h>=0&&s.splice(c,1)}return s}var nn=(t,s,c)=>{switch(t){case"BT":return{x:s,y:-c};case"LR":return{x:c,y:s};case"RL":return{x:-c,y:s};default:return{x:s,y:c}}},Pt=(t,s,c)=>{switch(t){case"BT":return{x:s,y:-c};case"LR":return{x:c,y:s};case"RL":return{x:c,y:-s};default:return{x:s,y:c}}};function sn(t,s={}){return t.nodes.some(c=>c.group)?Tn(t,s):Ot(t,s)}function en(t,s,c){let i=new Set(s.map(n=>n.id)),o=s.map(n=>({...n,group:null,constraints:c?n.constraints:{...n.constraints,pinned:!1}}));return{options:t.options,nodes:o,nodeById:new Map(o.map(n=>[n.id,n])),edges:t.edges.filter(n=>i.has(n.source)&&i.has(n.target)),groups:[],groupById:new Map,constraints:t.constraints.filter(n=>n.type==="sameRank"?n.nodes.every(r=>i.has(r)):i.has(n.a)&&i.has(n.b)),warnings:[]}}function Tn(t,s){let c=on(t,s.hints||null,s.hints||null),i=new Map,o=r=>({x:r.x+r.width/2,y:r.y+r.height/2});for(let r of t.nodes){let h=c.nodes.get(r.id);if(!r.group){i.set(r.id,o(h));continue}let a=0,u=0,g=0;for(let p of t.edges){let d=p.source===r.id?p.target:p.target===r.id?p.source:null;if(d==null||t.nodeById.get(d).group===r.group)continue;let f=o(c.nodes.get(d));a+=f.x,u+=f.y,g++}i.set(r.id,g?{x:a/g,y:u/g}:o(h))}let n=on(t,i,s.hints||i);return n.crossingsRouted<=c.crossingsRouted?n:c}function on(t,s,c){let i=t.options,o=i.groupPadding,n=i.groupLabelHeight,r=new Map;for(let e of t.nodes)e.group&&(r.has(e.group)||r.set(e.group,[]),r.get(e.group).push(e));let h=new Map,a=[];for(let[e,l]of r){let w=Ot(en(t,l,!1),{hints:s}),x=w.bounds,M="\0group:"+e;h.set(e,{sub:w,b:x,blockId:M}),a.push({id:M,index:-1,label:e,width:x.width+2*o,height:x.height+2*o+n,group:null,ports:[],portById:new Map,constraints:{pinned:!1,x:null,y:null,rank:null}})}let u=e=>{let l=t.nodeById.get(e);return l.group?h.get(l.group).blockId:e},g=en(t,t.nodes.filter(e=>!e.group),!0);g.nodes.push(...a);for(let e of a)g.nodeById.set(e.id,e);g.edges=[];for(let e of t.edges){let l=u(e.source),w=u(e.target);l===w&&(e.source!==e.target||l!==e.source)||g.edges.push({...e,source:l,target:w,sourcePort:l===e.source?e.sourcePort:null,targetPort:w===e.target?e.targetPort:null})}let p=null;if(c){p=new Map(c);for(let[e,l]of r){let w=0,x=0,M=0;for(let m of l){let y=c.get(m.id);y&&(w+=y.x,x+=y.y,M++)}M&&p.set(h.get(e).blockId,{x:w/M,y:x/M})}}let d=Ot(g,{hints:p}),f={nodes:new Map,edges:new Map,groups:new Map,crossings:d.crossings,warnings:d.warnings};for(let e of t.nodes)e.group||f.nodes.set(e.id,d.nodes.get(e.id));for(let[,{sub:e,b:l,blockId:w}]of h){let x=d.nodes.get(w),M=x.x+o-l.x,m=x.y+o+n-l.y;for(let[y,b]of e.nodes)f.nodes.set(y,{...b,x:b.x+M,y:b.y+m});for(let[y,b]of e.edges)f.edges.set(y,{...b,waypoints:b.waypoints.map(k=>({x:k.x+M,y:k.y+m}))});f.crossings+=e.crossings}for(let e of t.edges){if(f.edges.has(e.id))continue;let l=d.edges.get(e.id),w=u(e.source)!==e.source||u(e.target)!==e.target;f.edges.set(e.id,l?{...l,waypoints:w?[]:l.waypoints}:{waypoints:[],reversed:!1,selfLoop:e.source===e.target,flat:!1})}for(let e of t.nodes)if(e.group&&e.constraints.pinned){let l=f.nodes.get(e.id);l.x=e.constraints.x,l.y=e.constraints.y}if(cn(t,f),!t.nodes.some(e=>e.constraints.pinned)){let e=Rt(f);rn(f,-e.x,-e.y);for(let l of f.groups.values())l.x-=e.x,l.y-=e.y}return f.bounds=Rt(f),f.crossingsRouted=Xn(t,f),f}function Xn(t,s){let c=[];for(let n of t.edges){if(n.source===n.target)continue;let r=s.nodes.get(n.source),h=s.nodes.get(n.target);c.push([n.source,n.target,r.x+r.width/2,r.y+r.height/2,h.x+h.width/2,h.y+h.height/2])}let i=0,o=(n,r,h,a,u,g)=>(h-n)*(g-r)-(a-r)*(u-n);for(let n=0;n<c.length;n++)for(let r=n+1;r<c.length;r++){let h=c[n],a=c[r];if(h[0]===a[0]||h[0]===a[1]||h[1]===a[0]||h[1]===a[1])continue;let u=o(a[2],a[3],a[4],a[5],h[2],h[3]),g=o(a[2],a[3],a[4],a[5],h[4],h[5]),p=o(h[2],h[3],h[4],h[5],a[2],a[3]),d=o(h[2],h[3],h[4],h[5],a[4],a[5]);u*g<0&&p*d<0&&i++}return i}function Ot(t,s={}){let c=t.options,i=c.direction,o=i==="LR"||i==="RL",n=[],r=new Map;for(let d of t.nodes){let f=ht(d),e=new Map;for(let[x,M]of f)e.set(x,(o?M.py:M.px)-.5);let l=null,w=null;if(d.constraints.pinned){let x=Pt(i,d.constraints.x+d.width/2,d.constraints.y+d.height/2);l=x.x,w=x.y}r.set(d.id,{iw:o?d.height:d.width,ih:o?d.width:d.height,frac:e,pinX:l,pinY:w})}let h=Fn(t),a={nodes:new Map,edges:new Map,groups:new Map,crossings:0,warnings:n},u=[];for(let d of h){let f=d.nodes,e=new Set(f),l=t.edges.filter(v=>e.has(v.source)),w=new Map;for(let v of f){let E=t.nodeById.get(v).constraints.rank;E!=null&&w.set(v,E)}let x=t.constraints.filter(v=>v.type==="sameRank").map(v=>v.nodes.filter(E=>e.has(E))).filter(v=>v.length>1),M=Yt(f,l,{fixedRank:w,sameRank:x});n.push(...M.warnings);let m=f.map(v=>{let E=t.nodeById.get(v),X=r.get(v);return{id:v,rank:M.rank.get(v),width:X.iw,height:X.ih,group:E.group,pinX:X.pinX}}),y=[];for(let v of l){if(M.selfLoops.has(v.id)||M.flat.has(v.id))continue;let E=M.reversed.has(v.id),X=v.sourcePort?r.get(v.source).frac.get(v.sourcePort)??0:0,U=v.targetPort?r.get(v.target).frac.get(v.targetPort)??0:0;y.push(E?{id:v.id,v:v.target,w:v.source,vOff:U,wOff:X,weight:v.weight}:{id:v.id,v:v.source,w:v.target,vOff:X,wOff:U,weight:v.weight})}let b=Vt(m,y,0),k;s.hints&&s.hints.size&&(k=Hn(b,s.hints,i));let O=t.constraints.filter(v=>v.type==="leftOf"&&e.has(v.a)&&e.has(v.b)).map(v=>[v.a,v.b]),N=Wt(b,{maxIterations:c.maxIterations,leftOf:O,initial:k});a.crossings+=N.crossings;let I=Zt(b,N.layers,{nodeSpacing:c.nodeSpacing,edgeSpacing:c.edgeSpacing,rankSpacing:c.rankSpacing,groupPadding:c.groupPadding,groupLabelHeight:c.groupLabelHeight,labelOnOrderAxis:o,labelAtRankEnd:i==="BT"||i==="RL"?!o:!1}),R=f.filter(v=>r.get(v).pinY!=null);if(R.length){let v=0;for(let E of R)v+=r.get(E).pinY-I.y[b.index.get(E)];v/=R.length;for(let E=0;E<I.y.length;E++)I.y[E]+=v;for(let E of R){let X=b.index.get(E);I.x[X]=r.get(E).pinX,I.y[X]=r.get(E).pinY}}let B=1/0,T=-1/0;for(let v=0;v<b.v.length;v++){let E=b.v[v].width/2;B=Math.min(B,I.x[v]-E),T=Math.max(T,I.x[v]+E)}u.push({comp:d,g:b,co:I,rk:M,layers:N.layers,minX:B,maxX:T,pinned:R.length>0})}if(s.hints&&s.hints.size){let d=e=>{let l=0,w=0;for(let x of e.comp.nodes){let M=s.hints.get(x);M&&(l+=Pt(i,M.x,M.y).x,w++)}return w?l/w:1/0},f=new Map(u.map(e=>[e,d(e)]));u.sort((e,l)=>f.get(e)-f.get(l))}let g=-1/0;for(let d of u)d.pinned&&(g=Math.max(g,d.maxX+c.componentSpacing));g===-1/0&&(g=0);for(let d of u){if(d.pinned)continue;let f=g-d.minX;for(let e=0;e<d.co.x.length;e++)d.co.x[e]+=f;g+=d.maxX-d.minX+c.componentSpacing}for(let d of u){let{g:f,co:e,rk:l}=d;d.layers.forEach((w,x)=>w.forEach((M,m)=>{let y=f.v[M];if(!y.real)return;let b=t.nodeById.get(y.id),k=nn(i,e.x[M],e.y[M]);a.nodes.set(y.id,{x:k.x-b.width/2,y:k.y-b.height/2,width:b.width,height:b.height,rank:x,order:m})}));for(let w of t.edges){if(!d.comp.set.has(w.source))continue;let M=(f.chains.get(w.id)||[]).map(y=>nn(i,e.x[y],e.y[y])),m=l.reversed.has(w.id);m&&(M=M.reverse()),a.edges.set(w.id,{waypoints:M,reversed:m,selfLoop:l.selfLoops.has(w.id),flat:l.flat.has(w.id)})}}if(!u.some(d=>d.pinned)){let d=1/0,f=1/0;for(let l of a.nodes.values())d=Math.min(d,l.x),f=Math.min(f,l.y);let e=t.groups.length?c.groupPadding+c.groupLabelHeight:0;Number.isFinite(d)&&rn(a,-d+e,-f+e)}return cn(t,a),a.bounds=Rt(a),a}function rn(t,s,c){for(let i of t.nodes.values())i.x+=s,i.y+=c;for(let i of t.edges.values())for(let o of i.waypoints)o.x+=s,o.y+=c}function cn(t,s){let c=t.options;s.groups=new Map;for(let i of t.groups){let o=1/0,n=1/0,r=-1/0,h=-1/0;for(let u of t.nodes){if(u.group!==i.id)continue;let g=s.nodes.get(u.id);g&&(o=Math.min(o,g.x),n=Math.min(n,g.y),r=Math.max(r,g.x+g.width),h=Math.max(h,g.y+g.height))}if(!Number.isFinite(o))continue;let a=c.groupPadding;s.groups.set(i.id,{x:o-a,y:n-a-c.groupLabelHeight,width:r-o+2*a,height:h-n+2*a+c.groupLabelHeight})}return s.groups}function Rt(t){let s=1/0,c=1/0,i=-1/0,o=-1/0,n=r=>{s=Math.min(s,r.x),c=Math.min(c,r.y),i=Math.max(i,r.x+r.width),o=Math.max(o,r.y+r.height)};for(let r of t.nodes.values())n(r);for(let r of t.groups.values())n(r);return Number.isFinite(s)?{x:s,y:c,width:i-s,height:o-c}:{x:0,y:0,width:0,height:0}}function Hn(t,s,c){let i=St(t),o=new Float64Array(t.v.length).fill(NaN);t.v.forEach((n,r)=>{if(n.real&&s.has(n.id)){let h=s.get(n.id);o[r]=Pt(c,h.x,h.y).x}});for(let[,n]of t.chains){if(!n.length)continue;let r=t.v[n[0]].up[0]?.n,h=t.v[n[n.length-1]].down[0]?.n;r==null||h==null||Number.isNaN(o[r])||Number.isNaN(o[h])||n.forEach((a,u)=>{o[a]=o[r]+(o[h]-o[r])*(u+1)/(n.length+1)})}return i.map(n=>{let r=new Map(n.map((h,a)=>[h,a]));return n.slice().sort((h,a)=>{let u=o[h],g=o[a];return Number.isNaN(u)&&Number.isNaN(g)?r.get(h)-r.get(a):Number.isNaN(u)?1:Number.isNaN(g)?-1:u-g})})}function Fn(t){let s=new Map(t.nodes.map(r=>[r.id,r.id])),c=r=>{for(;s.get(r)!==r;)s.set(r,s.get(s.get(r))),r=s.get(r);return r},i=(r,h)=>{let a=c(r),u=c(h);a!==u&&s.set(u,a)};for(let r of t.edges)i(r.source,r.target);let o=new Map;for(let r of t.nodes)r.group&&(o.has(r.group)?i(o.get(r.group),r.id):o.set(r.group,r.id));for(let r of t.constraints)if(r.type==="leftOf"&&i(r.a,r.b),r.type==="sameRank")for(let h of r.nodes)i(r.nodes[0],h);let n=new Map;for(let r of t.nodes){let h=c(r.id);n.has(h)||n.set(h,[]),n.get(h).push(r.id)}return[...n.values()].map(r=>({nodes:r,set:new Set(r)}))}function zn(t,s,c){let i=Jt(c),o=J(t),n=J(s),r=n.x-o.x,h=n.y-o.y,a=Math.abs(r)-(t.width+s.width)/2,u=Math.abs(h)-(t.height+s.height)/2,g=i.x!==0?r*i.x:h*i.y,p=i.x!==0?a:u;return g>0&&p>4?[i.exit,i.entry]:a>=u?r>=0?["right","left"]:["left","right"]:h>=0?["bottom","top"]:["top","bottom"]}function fn(t,s){let c=t.options.direction,i=new Map,o=new Map;for(let a of t.nodes){let u=s.get(a.id);if(!u)continue;let g=ht(a),p=new Map;for(let[d,f]of g)p.set(d,{x:u.x+f.px*u.width,y:u.y+f.py*u.height,side:f.side,t:f.t});o.set(a.id,p)}let n=new Map,r=new Map;for(let a of t.edges){let u=s.get(a.source),g=s.get(a.target);if(!u||!g)continue;if(a.source===a.target){let l=o.get(a.source),w=a.sourcePort&&l.get(a.sourcePort),x=a.targetPort&&l.get(a.targetPort),M=Math.min(20,u.width/4,u.height/4);i.set(a.id,{source:w&&w.side?{x:w.x,y:w.y,side:w.side}:{x:u.x+u.width-M,y:u.y,side:"top"},target:x&&x.side?{x:x.x,y:x.y,side:x.side}:{x:u.x+u.width,y:u.y+M,side:"right"}});continue}let[p,d]=zn(u,g,c),f=a.sourcePort&&o.get(a.source).get(a.sourcePort),e=a.targetPort&&o.get(a.target).get(a.targetPort);f&&f.side&&(p=f.side),e&&e.side&&(d=e.side),r.set(a.id,[p,d]),f||an(n,a.source+"|"+p,{edgeId:a.id,end:"source",other:a.target}),e||an(n,a.target+"|"+d,{edgeId:a.id,end:"target",other:a.source}),i.set(a.id,{source:f?{x:f.x,y:f.y,side:f.side}:null,target:e?{x:e.x,y:e.y,side:e.side}:null})}for(let a=0;a<2;a++)for(let[u,g]of n){let[p,d]=u.split("|"),f=s.get(p),e=d==="top"||d==="bottom",l=x=>{let M=i.get(x.edgeId),m=x.end==="source"?M.target:M.source;if(a>0&&m)return e?m.x:m.y;let y=J(s.get(x.other));return e?y.x:y.y};g.sort((x,M)=>l(x)-l(M)||(x.edgeId<M.edgeId?-1:1));let w=[...o.get(p)?.values()||[]].filter(x=>x.side===d).map(x=>x.t);g.forEach((x,M)=>{let m=(M+1)/(g.length+1);for(let b of w)Math.abs(b-m)<.06&&(m=Math.min(.95,m+.1));let y=e?{x:f.x+m*f.width,y:d==="top"?f.y:f.y+f.height,side:d}:{x:d==="left"?f.x:f.x+f.width,y:f.y+m*f.height,side:d};i.get(x.edgeId)[x.end]=y})}let h=a=>{a&&(a.x=Math.round(a.x*100)/100,a.y=Math.round(a.y*100)/100)};for(let a of i.values())h(a.source),h(a.target);return{ends:i,ports:o,sides:r}}function an(t,s,c){t.has(s)||t.set(s,[]),t.get(s).push(c)}function dn(t,s,c){let i=c.spacing,o={h:new Map,v:new Map},n=new Map;for(let[p,d]of t)n.set(p,d.points.map(f=>({x:f.x,y:f.y})));for(let[p,d]of t){if(d.kind!=="orthogonal"||d.bundle)continue;let f=d.points;for(let e=0;e<f.length-1;e++){if(c.fixedEnds!==!1&&(e===0||e===f.length-2))continue;let l=f[e],w=f[e+1],x=Math.abs(l.x-w.x)<.01,M=Math.abs(l.y-w.y)<.01;if(!x&&!M)continue;let m=x?l.x:l.y,y=x?Math.min(l.y,w.y):Math.min(l.x,w.x),b=x?Math.max(l.y,w.y):Math.max(l.x,w.x);if(b-y<.5)continue;let k=x?l.y<=w.y:l.x<=w.x,O=f[e-1],N=f[e+2],I=(X,U)=>X?Math.sign(x?X.x-U.x:X.y-U.y):0,R=I(O,l),B=I(N,w),T={id:p,i:e,c:m,lo:y,hi:b,vertical:x,loIsA:k,pts:n.get(p),dirLo:k?R:B,dirHi:k?B:R},v=Math.round(m*100),E=x?o.v:o.h;E.has(v)||E.set(v,[]),E.get(v).push(T)}}let r=[...o.v.values()].flat(),h=[...o.h.values()].flat(),a=[];for(let p of[!0,!1])for(let d of(p?o.v:o.h).values()){if(d.length<2)continue;d.sort((w,x)=>w.lo-x.lo);let f=[d[0]],e=d[0].hi,l=()=>{f.length>1&&u(f,p)};for(let w=1;w<d.length;w++){let x=d[w];x.lo<e-.5?(f.push(x),e=Math.max(e,x.hi)):(l(),f=[x],e=x.hi)}l()}function u(p,d){if(new Set(p.map(k=>k.id)).size<2)return;let f=[];for(let k of p){let O=f.length;for(;O>0&&Dn(k,f[O-1])<0;)O--;f.splice(O,0,k)}let e=p[0].c,l=Math.min(...p.map(k=>k.lo)),w=Math.max(...p.map(k=>k.hi)),x=1/0,M=1/0;for(let k of s.values()){let O=d?k.y:k.x;if((d?k.y+k.height:k.x+k.width)<=l||O>=w)continue;let I=d?k.x:k.y,R=d?k.x+k.width:k.y+k.height;R<=e+.01?x=Math.min(x,e-R):I>=e-.01&&(M=Math.min(M,I-e))}for(let k of d?r:h){if(k.c===e||k.hi<=l||k.lo>=w)continue;let O=Math.abs(k.c-e)/2;k.c<e?x=Math.min(x,O+4):M=Math.min(M,O+4)}let m=f.length,y=Math.max(0,Math.min(x,M)-4),b=Math.min(i,m>1?2*y/(m-1):i);f.forEach((k,O)=>{let N=(O-(m-1)/2)*b;Math.abs(N)>.01&&a.push([k.id,k.i,d,N])})}let g=new Map;for(let[p,d,f,e]of a)g.has(p)||g.set(p,new Map),g.get(p).set(d,f?{x:e,y:0}:{x:0,y:e});for(let[p,d]of g){let f=t.get(p),e=f.points,l=[],w={x:0,y:0};for(let x=0;x<e.length;x++){let M=x>0&&d.get(x-1)||w,m=x<e.length-1&&d.get(x)||w,y=x>0&&x<e.length-1&&Cn(e[x-1],e[x],e[x+1]);y&&(M.x!==m.x||M.y!==m.y)?(l.push({x:e[x].x+M.x,y:e[x].y+M.y}),l.push({x:e[x].x+m.x,y:e[x].y+m.y})):l.push({x:e[x].x+M.x+(y?0:m.x),y:e[x].y+M.y+(y?0:m.y)})}f.points=jn(l)}}function Cn(t,s,c){return Math.abs(t.x-s.x)<.01&&Math.abs(s.x-c.x)<.01||Math.abs(t.y-s.y)<.01&&Math.abs(s.y-c.y)<.01}function jn(t){let s=[];for(let c of t){let i=s[s.length-1];i&&Math.abs(i.x-c.x)<.01&&Math.abs(i.y-c.y)<.01||s.push(c)}return s}function Dn(t,s){return hn(t,s,!0)||hn(t,s,!1)||Gn(t,s)}function un(t,s){let{pts:c,i,loIsA:o}=t,n=[];if(s?!o:o)for(let h=i+1;h<c.length;h++)n.push(c[h]);else for(let h=i;h>=0;h--)n.push(c[h]);return n}var Un=(t,s)=>t.x*s.y-t.y*s.x,ln=(t,s)=>{let c=s.x-t.x,i=s.y-t.y,o=Math.hypot(c,i)||1;return{x:c/o,y:i/o}};function hn(t,s,c){let i=t.vertical,o=un(t,c),n=un(s,c),r=c?Math.max(t.lo,s.lo):Math.min(t.hi,s.hi),h=i?{x:t.c,y:r}:{x:r,y:t.c},a=i?{x:0,y:c?-1:1}:{x:c?-1:1,y:0},u=a,g=0,p=0,d=(e,l)=>{if(e===l)return 0;let w={x:a.y,y:-a.x},x=i?w.x:w.y;return(e<l?x<0:x>0)?-1:1},f=(e,l)=>l+1<e.length?Math.sign(Math.round(Un(u,ln(e[l],e[l+1]))*1e3)):null;for(let e=0;e<64;e++){let l=g<o.length?(o[g].x-h.x)*u.x+(o[g].y-h.y)*u.y:1/0,w=p<n.length?(n[p].x-h.x)*u.x+(n[p].y-h.y)*u.y:1/0;if(l===1/0&&w===1/0)return 0;if(Math.abs(l-w)<.5){let M=f(o,g),m=f(n,p);if(M===null||m===null)return M===null&&m===null?0:d(M??0,m??0);if(M!==m)return d(M,m);h=o[g],u=ln(o[g],o[g+1]),g++,p++;continue}if(l<w){let M=f(o,g);return M?d(M,0):0}let x=f(n,p);return x?d(0,x):0}return 0}var Gn=(t,s)=>t.id<s.id?-1:t.id>s.id?1:t.i-s.i;function gn(t,s,c=4){let i=[],o=new Map(s.map((a,u)=>[a,u]));for(let a of s){let u=t.get(a).points;for(let g=0;g<u.length-1;g++){let p=u[g],d=u[g+1];Math.abs(p.x-d.x)<.01&&Math.abs(p.y-d.y)>.01&&i.push([o.get(a),p.x,Math.min(p.y,d.y),Math.max(p.y,d.y)])}}let n=64,r=new Map;for(let a of i){let u=Math.floor(a[1]/n);r.has(u)||r.set(u,[]),r.get(u).push(a)}let h=new Map;for(let a of s){let u=o.get(a),g=t.get(a).points,p=[];for(let d=0;d<g.length-1;d++){let f=g[d],e=g[d+1];if(Math.abs(f.y-e.y)>.01)continue;let l=Math.min(f.x,e.x)+c*2,w=Math.max(f.x,e.x)-c*2;if(!(w<=l))for(let x=Math.floor(l/n);x<=Math.floor(w/n);x++)for(let M of r.get(x)||[])M[0]>=u||M[1]<=l||M[1]>=w||f.y<=M[2]+c||f.y>=M[3]-c||p.push({seg:d,x:M[1],y:f.y})}p.length&&h.set(a,p)}return h}var Et=1,Yn=[1,-1,0,0],_n=[0,0,1,-1],Nt=[1,0,3,2],pn=t=>t.x>0?0:t.x<0?1:t.y>0?2:3;function yn(t,s,c={}){let i=t.options,o=s.nodes,n=i.edgeRouting,{ends:r,ports:h}=fn(t,o),a=new Map,u=new Map,g=c.only||null,p=c.prev||null;if(n==="orthogonal")Vn(t,o,r,i,g,p,a,u),dn(a,o,{spacing:i.edgeSpacing,fixedEnds:!0});else for(let e of t.edges){let l=o.get(e.source),w=o.get(e.target);if(!l||!w)continue;if(e.source===e.target){a.set(e.id,xn(l,i,r.get(e.id)));continue}let x=s.edges.get(e.id),M=x&&x.waypoints||[],m=r.get(e.id),y,b;n==="curved"||e.sourcePort?y=m.source:y=It(l,M[0]||J(w)),n==="curved"||e.targetPort?b=m.target:b=It(w,M[M.length-1]||J(l)),a.set(e.id,{points:[y,...M.map(k=>({...k})),b],kind:n,sourceSide:y.side,targetSide:b.side})}let d=t.edges.map(e=>e.id).filter(e=>a.has(e)),f=i.lineHops&&n==="orthogonal"?gn(a,d,i.hopRadius):new Map;for(let[e,l]of a)l.hops=f.get(e)||[];return{paths:a,raw:u,ports:h,mode:n}}function xn(t,s,c){let i=Math.max(s.nodeMargin*1.5,16),o=c.source,n=c.target,r=ot[o.side],h=ot[n.side],a={x:o.x+r.x*i,y:o.y+r.y*i},u={x:n.x+h.x*i,y:n.y+h.y*i},g;if(o.side===n.side)g=o.side==="left"||o.side==="right"?[a,{x:a.x,y:u.y}]:[a,{x:u.x,y:a.y}];else if((o.side==="top"||o.side==="bottom")!=(n.side==="top"||n.side==="bottom"))g=o.side==="top"||o.side==="bottom"?[a,{x:u.x,y:a.y}]:[a,{x:a.x,y:u.y}];else{let p=o.side==="top"||o.side==="bottom",d=p?t.x+t.width+i:t.y+t.height+i;g=p?[a,{x:d,y:a.y},{x:d,y:u.y}]:[a,{x:a.x,y:d},{x:u.x,y:d}]}return{points:dt([o,...g,u,n]),kind:"orthogonal",sourceSide:o.side,targetSide:n.side,selfLoop:!0}}function Vn(t,s,c,i,o,n,r,h){let a=i.nodeMargin,u=[];for(let[e,l]of s)u.push({id:e,...Qt(l,a)});let g=new Map;for(let e of t.edges){let l=c.get(e.id);if(!l||!l.source||!l.target)continue;let w=ot[l.source.side],x=ot[l.target.side];g.set(e.id,{s:{x:l.source.x+w.x*a,y:l.source.y+w.y*a},t:{x:l.target.x+x.x*a,y:l.target.y+x.y*a},sDir:pn(w),tNeed:Nt[pn(x)]})}let p=Jn(u,g,a);for(let e of t.edges)if(o&&!o.has(e.id)&&n&&n.raw.has(e.id)){let l=n.raw.get(e.id);h.set(e.id,l),p.markPath(l);let w=n.paths.get(e.id);w&&r.set(e.id,{...w,points:l.map(x=>({...x}))})}let d=t.edges.filter(e=>!r.has(e.id)&&s.has(e.source)&&s.has(e.target)),f=e=>{let l=g.get(e.id);return l?Math.abs(l.s.x-l.t.x)+Math.abs(l.s.y-l.t.y):0};d.sort((e,l)=>f(e)-f(l)),Kn(t,s,c,i,u,d,p,r,h);for(let e of d){if(r.has(e.id))continue;if(e.source===e.target){let m=xn(s.get(e.source),i,c.get(e.id));r.set(e.id,m),h.set(e.id,m.points);continue}let l=c.get(e.id),w=g.get(e.id),x=p.astar(w.s,w.sDir,w.t,w.tNeed,i);x||(x=Zn(w.s,w.t,l.source.side,l.target.side));let M=[l.source,...dt(x),l.target];p.markPath(M),h.set(e.id,M),r.set(e.id,{points:M.map(m=>({...m})),kind:"orthogonal",sourceSide:l.source.side,targetSide:l.target.side})}}var Wn={top:"bottom",bottom:"top",left:"right",right:"left"};function Kn(t,s,c,i,o,n,r,h,a){let u=i.bundleFanOut;if(!u)return;let g=new Map;for(let p of n){if(p.source===p.target||p.sourcePort||p.markerStart)continue;let d=c.get(p.id);if(!d||!d.source||!d.target||d.target.side!==Wn[d.source.side])continue;let f=p.source+"|"+d.source.side;g.has(f)||g.set(f,[]),g.get(f).push(p)}for(let[p,d]of g){if(d.length<u)continue;let f=d[0].source,e=c.get(d[0].id).source.side,l=s.get(f),w=ot[e],x=w.y!==0,M=x?w.y:w.x,m=e==="bottom"?l.y+l.height:e==="top"?l.y:e==="right"?l.x+l.width:l.x,y=1/0;for(let I of d){let R=c.get(I.id).target;y=Math.min(y,((x?R.y:R.x)-m)*M)}if(y<2*i.nodeMargin+4)continue;let b=m+M*y/2,k=x?{x:l.x+l.width/2,y:m}:{x:m,y:l.y+l.height/2},O=[],N=!0;for(let I of d){let R=c.get(I.id).target,B=dt(x?[k,{x:k.x,y:b},{x:R.x,y:b},R]:[k,{x:b,y:k.y},{x:b,y:R.y},R]);for(let T=0;N&&T<B.length-1;T++)for(let v of o)if(v.id!==f&&v.id!==I.target&&tn(B[T],B[T+1],v,1)){N=!1;break}if(!N)break;O.push([I,B,R.side])}if(N)for(let[I,R,B]of O)r.markPath(R),a.set(I.id,R),h.set(I.id,{points:R.map(T=>({...T})),kind:"orthogonal",sourceSide:e,targetSide:B,bundle:p})}}function Zn(t,s,c,i){let o=c==="top"||c==="bottom",n=i==="top"||i==="bottom";if(o&&n){let r=(t.y+s.y)/2;return[t,{x:t.x,y:r},{x:s.x,y:r},s]}if(!o&&!n){let r=(t.x+s.x)/2;return[t,{x:r,y:t.y},{x:r,y:s.y},s]}return o?[t,{x:t.x,y:s.y},s]:[t,{x:s.x,y:t.y},s]}function Jn(t,s,c){let i=new Set,o=new Set,n=S=>Math.round(S*100)/100,r=1/0,h=1/0,a=-1/0,u=-1/0;for(let S of t)i.add(n(S.x)),i.add(n(S.x+S.width)),o.add(n(S.y)),o.add(n(S.y+S.height)),r=Math.min(r,S.x),h=Math.min(h,S.y),a=Math.max(a,S.x+S.width),u=Math.max(u,S.y+S.height);for(let S of s.values())for(let P of[S.s,S.t])i.add(n(P.x)),o.add(n(P.y)),r=Math.min(r,P.x),h=Math.min(h,P.y),a=Math.max(a,P.x),u=Math.max(u,P.y);i.add(n(r-2*c)),i.add(n(a+2*c)),o.add(n(h-2*c)),o.add(n(u+2*c));let g=S=>{let P=[...S].sort((A,G)=>A-G),L=[];for(let A=0;A<P.length;A++)L.push(P[A]),A+1<P.length&&P[A+1]-P[A]>4&&L.push(n((P[A]+P[A+1])/2));return L},p=g(i),d=g(o),f=p.length,e=d.length,l=f*e,w=new Map(p.map((S,P)=>[S,P])),x=new Map(d.map((S,P)=>[S,P])),M=120,m=new Map,y=(S,P)=>S*73856093^P*19349663;for(let S of t)for(let P=Math.floor(S.x/M);P<=Math.floor((S.x+S.width)/M);P++)for(let L=Math.floor(S.y/M);L<=Math.floor((S.y+S.height)/M);L++){let A=y(P,L);m.has(A)||m.set(A,[]),m.get(A).push(S)}let b=(S,P)=>{let L=m.get(y(Math.floor(S/M),Math.floor(P/M)));if(!L)return!1;for(let A of L)if(qt(A,S,P,.01))return!0;return!1},k=l<=4e6?new Uint8Array(l):null,O=k?null:new Map,N=S=>{if(k){let L=k[S];return L||(L=b(p[S%f],d[S/f|0])?2:1,k[S]=L),L===2}let P=O.get(S);return P===void 0&&(P=b(p[S%f],d[S/f|0]),O.set(S,P)),P},I=new Uint8Array(l),R=new Uint8Array(l),B=(S,P)=>{let L=P?I:R,A=L[S];if(!A){let G=S%f,Y=S/f|0,H=P?(p[G]+p[G+1])/2:p[G],C=P?d[Y]:(d[Y]+d[Y+1])/2;A=b(H,C)?2:1,L[S]=A}return A===2},T=new Uint16Array(l),v=new Uint16Array(l),E=new Uint16Array(l),X=new Uint16Array(l),U=S=>{let P=w.get(n(S.x)),L=x.get(n(S.y));return P==null||L==null?-1:L*f+P};function V(S){for(let P=0;P<S.length-1;P++){let L=S[P],A=S[P+1],G=Math.abs(L.y-A.y)<.01,Y=Math.abs(L.x-A.x)<.01;if(G){let H=x.get(n(L.y)),C=w.get(n(L.x)),D=w.get(n(A.x));if(H==null||C==null||D==null)continue;let q=Math.min(C,D),tt=Math.max(C,D);for(let z=q;z<=tt;z++)T[H*f+z]++,z<tt&&E[H*f+z]++}else if(Y){let H=w.get(n(L.x)),C=x.get(n(L.y)),D=x.get(n(A.y));if(H==null||C==null||D==null)continue;let q=Math.min(C,D),tt=Math.max(C,D);for(let z=q;z<=tt;z++)v[z*f+H]++,z<tt&&X[z*f+H]++}}}let Q=l*4,W=Q<=16e6,At=W?new Float64Array(Q):null,Bt=W?new Int32Array(Q):null,$t=W?new Uint32Array(Q):null,gt=0;function mn(S,P,L,A,G){let Y=U(S),H=U(L);if(Y<0||H<0)return null;let C=p[H%f],D=d[H/f|0],q=G.bendPenalty,tt=G.crossingPenalty;gt++;let z=W?null:new Map,Tt=W?null:new Map,Xt=W?$=>$t[$]===gt?At[$]:void 0:$=>z.get($),Ht=W?($,j,K)=>{$t[$]=gt,At[$]=j,Bt[$]=K}:($,j,K)=>{z.set($,j),Tt.set($,K)},wn=W?$=>Bt[$]:$=>Tt.get($),st=new Lt,Ft=Y*4+P;Ht(Ft,0,-1),st.push(Ft,Et*(Math.abs(p[Y%f]-C)+Math.abs(d[Y/f|0]-D)));let pt=1/0,yt=-1,Mn=0,bn=4e5;for(;st.size;){let $=st.peekKey(),j=st.pop();if($>=pt)break;let K=Xt(j),nt=j>>2,at=j&3,mt=nt%f,wt=nt/f|0;if(!($>K+Et*(Math.abs(p[mt]-C)+Math.abs(d[wt]-D))+1e-6)){if(++Mn>bn)break;if(nt===H){let F=at===A?0:at===Nt[A]?2*q:q;K+F<pt&&(pt=K+F,yt=j);continue}for(let F=0;F<4;F++){if(F===Nt[at])continue;let it=mt+Yn[F],rt=wt+_n[F];if(it<0||rt<0||it>=f||rt>=e)continue;let _=rt*f+it;if(_!==H&&N(_))continue;let ct=F<2;if(B(ct?F===0?nt:_:F===2?nt:_,ct))continue;let zt=Math.abs(ct?p[it]-p[mt]:d[rt]-d[wt]),ft=zt;F!==at&&(ft+=q);let Ct=F===0||F===2?nt:_,jt=ct?E[Ct]:X[Ct];jt&&(ft+=zt*.25*jt),_!==H&&(ct?v[_]:T[_])&&(ft+=tt);let Mt=_*4+F,bt=K+ft,Dt=Xt(Mt);(Dt===void 0||bt<Dt-1e-9)&&(Ht(Mt,bt,j),st.push(Mt,bt+Et*(Math.abs(p[it]-C)+Math.abs(d[rt]-D))))}}}if(yt<0)return null;let xt=[];for(let $=yt;$!==-1&&$!==void 0;$=wn($)){let j=$>>2;xt.push({x:p[j%f],y:d[j/f|0]})}return xt.reverse(),xt}return{astar:mn,markPath:V,xs:p,ys:d,N:l}}var Lt=class{constructor(){this.k=[],this.v=[]}get size(){return this.k.length}push(s,c){let i=this.k,o=this.v,n=i.length;for(i.push(c),o.push(s);n>0;){let r=n-1>>1;if(i[r]<=c)break;i[n]=i[r],o[n]=o[r],n=r}i[n]=c,o[n]=s}peekKey(){return this.k[0]}pop(){let s=this.k,c=this.v,i=c[0],o=s.pop(),n=c.pop();if(s.length){let r=0,h=s.length;for(;;){let a=2*r+1;if(a>=h||(a+1<h&&s[a+1]<s[a]&&a++,s[a]>=o))break;s[r]=s[a],c[r]=c[a],r=a}s[r]=o,c[r]=n}return i}};self.onmessage=t=>{let{seq:s,data:c,options:i,hints:o}=t.data;try{let n=Gt(c,i),r=sn(n,{hints:o||null}),h=yn(n,r);self.postMessage({seq:s,nodes:r.nodes,edges:r.edges,crossings:r.crossings,routing:{paths:h.paths,raw:h.raw,ports:h.ports,mode:h.mode}})}catch(n){self.postMessage({seq:s,error:String(n&&n.message||n)})}};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kazant/flexgraph",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "Flexible relationship graph for the browser: layered layout with strong crossing minimization, ports, orthogonal edge routing with obstacle avoidance, groups and constraints. Plain HTML, CSS & JS.",
5
5
  "license": "MIT",
6
6
  "author": "Alexander Pettersen (https://github.com/kazant)",
package/types/index.d.ts CHANGED
@@ -40,6 +40,16 @@ export interface NodeSpec {
40
40
  type?: string;
41
41
  /** Trusted HTML content for the default node template. */
42
42
  html?: string;
43
+ /** Trusted HTML shown when the node is expanded. A node with details gets a "Details" toggle. */
44
+ details?: string;
45
+ /** Force the details toggle on or off (default: on when `details` or options.renderDetails is set). */
46
+ expandable?: boolean;
47
+ /** Start with the details open. */
48
+ expanded?: boolean;
49
+ /** Show a +/− toggle that stacks the nodes before ("upstream") or after ("downstream", also `true`) this node under it. */
50
+ stackable?: boolean | 'upstream' | 'downstream';
51
+ /** Start with the stack folded (direction from `stackable`). */
52
+ stacked?: boolean;
43
53
  [key: string]: unknown;
44
54
  }
45
55
 
@@ -93,6 +103,8 @@ export interface GraphOptions {
93
103
  maxIterations: number;
94
104
  bendPenalty: number;
95
105
  crossingPenalty: number;
106
+ /** When this many edges leave one side of a node, they share one trunk (tree style). 0 turns it off. Default 5. */
107
+ bundleFanOut: number;
96
108
  defaultNodeWidth: number;
97
109
  defaultNodeHeight: number;
98
110
  pinOnDrag: boolean;
@@ -107,11 +119,44 @@ export interface GraphOptions {
107
119
  hoverHighlight: 'chain' | 'neighbors';
108
120
  /** Keep the hover highlight on the selected (clicked) node or edge until the selection is cleared. Default true. */
109
121
  highlightSelection: boolean;
122
+ /**
123
+ * Multi-select (default true): Ctrl/Cmd/Shift + click adds or removes items, Shift + drag on the background draws a
124
+ * selection box, Ctrl/Cmd+A selects all, and dragging a selected node moves the whole selection.
125
+ */
126
+ multiSelect: boolean;
127
+ /**
128
+ * Undo / redo (default true) for moves, pins, relayout, updateGraph, expand / collapse, importState and direction /
129
+ * routing changes. Ctrl/Cmd+Z, Ctrl/Cmd+Shift+Z or Ctrl/Cmd+Y, and buttons in the controls.
130
+ */
131
+ history: boolean;
132
+ /** Undo steps kept. Default 100. */
133
+ historyLimit: number;
134
+ /** Text of the details toggle on expandable nodes. Defaults 'Details' / 'Hide'. */
135
+ expandText: string;
136
+ collapseText: string;
137
+ /**
138
+ * Explore mode for huge hierarchies: only nodes without a parent are shown at first; clicking a node opens its
139
+ * children. Only the open part of the graph is laid out and rendered.
140
+ */
141
+ explore: boolean;
142
+ /** Explore mode: nodes off the open path are 'dim' (default), 'blur' or 'hide'. */
143
+ exploreUnfocused: 'dim' | 'blur' | 'hide';
144
+ /** Explore mode: children shown per node before a "+N more" node (click it to show more). Default 25. */
145
+ exploreLimit: number;
146
+ /** Explore mode: show the path as a breadcrumb in the top-left corner. Default true. */
147
+ exploreBreadcrumb: boolean;
148
+ /** Explore mode: first breadcrumb item (back to the start nodes). Default 'Start'. */
149
+ exploreStartText: string;
150
+ /** Explore mode: label of the "+N more" node. */
151
+ exploreMoreText?: (count: number) => string;
110
152
  edgeTypes: Record<string, { markerStart?: MarkerName | null; markerEnd?: MarkerName | null }>;
111
153
  /** URL of dist/flexgraph.worker.js to run layout + routing in a Web Worker. */
112
154
  worker?: string | URL;
113
155
  /** Custom node content. Return an HTML string, an element, or nothing (to fill `el` yourself). */
114
156
  renderNode?: (node: NodeSpec, el: HTMLElement) => string | Node | void | null;
157
+ /** Content of an expanded node. When set, every node gets a "Details" toggle (opt out per node with expandable: false). */
158
+ renderDetails?: (node: NodeSpec, el: HTMLElement) => string | Node | void | null;
159
+ onNodeExpand?: (node: NodeSpec, expanded: boolean) => void;
115
160
  /** `connections.previous` / `connections.next`: the nodes directly before and after the clicked node. */
116
161
  onNodeClick?: (node: NodeSpec, event: PointerEvent, connections: Connections) => void;
117
162
  onEdgeClick?: (edge: EdgeSpec, event: PointerEvent) => void;
@@ -131,6 +176,7 @@ export interface ViewState {
131
176
  nodes: Record<string, { x: number; y: number; pinned: boolean }>;
132
177
  /** Exact edge lines as [x, y] points. Reused on import while the nodes still match, so lines come back as the user left them. */
133
178
  edges?: Record<string, [number, number][]>;
179
+ stacked?: [string, 'upstream' | 'downstream'][];
134
180
  transform: { x: number; y: number; k: number };
135
181
  }
136
182
 
@@ -143,19 +189,32 @@ export interface GraphEvents {
143
189
  nodeclick: { node: NodeSpec; event: PointerEvent; previous: NodeSpec[]; next: NodeSpec[] };
144
190
  edgeclick: { edge: EdgeSpec; event: PointerEvent };
145
191
  groupclick: { group: GroupSpec; event: PointerEvent };
146
- dragstart: { id: string };
147
- drag: { id: string; x: number; y: number };
148
- dragend: { id: string; x: number; y: number };
192
+ /** `ids`: every node being moved (the whole selection when a selected node is dragged). */
193
+ dragstart: { id: string; ids: string[] };
194
+ drag: { id: string; x: number; y: number; ids: string[] };
195
+ dragend: { id: string; x: number; y: number; ids: string[] };
196
+ /**
197
+ * Undo history changed. `data` is the graph data now shown: after an undo it can be an earlier object than the
198
+ * one you last passed to updateGraph, so keep your own copy in sync from here.
199
+ */
200
+ history: { action: 'record' | 'undo' | 'redo' | 'clear'; label?: string; canUndo: boolean; canRedo: boolean; data: GraphData };
201
+ /** The set of selected items changed (`select` only reports the primary item). */
202
+ selectionchange: { items: Selection[]; nodes: NodeSpec[]; edges: EdgeSpec[] };
149
203
  pin: { id: string; pinned: boolean };
150
204
  change: ViewState;
151
205
  viewport: { x: number; y: number; k: number };
152
206
  animationend: void;
207
+ expand: { id: string; expanded: boolean; node: NodeSpec };
208
+ stack: { id: string; direction: 'upstream' | 'downstream'; stacked: string[] };
209
+ unstack: { id: string };
210
+ /** Explore mode: the open path changed. */
211
+ explore: { path: string[] };
153
212
  /** Right-click anywhere in the graph. Registering a listener suppresses the browser menu inside the graph. */
154
213
  contextmenu:
155
- | { kind: 'node'; id: string; node: NodeSpec; previous: NodeSpec[]; next: NodeSpec[]; event: MouseEvent }
156
- | { kind: 'edge'; id: string; edge: EdgeSpec; event: MouseEvent }
157
- | { kind: 'group'; id: string; group: GroupSpec; event: MouseEvent }
158
- | { kind: 'background'; event: MouseEvent };
214
+ | { kind: 'node'; id: string; node: NodeSpec; previous: NodeSpec[]; next: NodeSpec[]; event: MouseEvent; selection: Selection[] }
215
+ | { kind: 'edge'; id: string; edge: EdgeSpec; event: MouseEvent; selection: Selection[] }
216
+ | { kind: 'group'; id: string; group: GroupSpec; event: MouseEvent; selection: Selection[] }
217
+ | { kind: 'background'; event: MouseEvent; selection: Selection[] };
159
218
  }
160
219
 
161
220
  export interface Connections {
@@ -180,25 +239,71 @@ export interface GraphView {
180
239
  readonly ready: Promise<GraphView>;
181
240
  readonly options: GraphOptions;
182
241
  relayout(opts?: { animate?: boolean; fresh?: boolean }): Promise<GraphView>;
183
- updateGraph(data: GraphData, opts?: { mode?: 'stable' | 'relayout'; animate?: boolean }): Promise<GraphView>;
242
+ updateGraph(data: GraphData, opts?: { mode?: 'stable' | 'relayout'; animate?: boolean; from?: string | Map<string, string>; to?: string | Map<string, string> }): Promise<GraphView>;
184
243
  setOptions(options: Partial<GraphOptions>, opts?: { relayout?: boolean }): Promise<GraphView>;
185
244
  exportState(): ViewState;
186
245
  importState(state: ViewState, opts?: { animate?: boolean; transform?: boolean }): Promise<GraphView>;
187
246
  pin(id: string, pinned?: boolean): void;
188
247
  unpin(id: string): void;
189
248
  unpinAll(): void;
190
- select(sel: string | Selection | null): void;
249
+ /**
250
+ * Select one item, several, or nothing. Node ids can be passed as strings.
251
+ * `add` adds to the current selection, `toggle` flips each item in or out of it.
252
+ */
253
+ select(sel: string | Selection | (string | Selection)[] | null, opts?: { add?: boolean; toggle?: boolean }): void;
254
+ /** The primary selected item (the one selected last), or null. */
191
255
  getSelection(): Selection | null;
256
+ /** Every selected item, in the order they were selected. */
257
+ getSelectedItems(): Selection[];
258
+ getSelectedNodes(): NodeSpec[];
259
+ getSelectedEdges(): EdgeSpec[];
260
+ selectAll(): void;
261
+ clearSelection(): void;
262
+ /** Undo the last change. Resolves false if there was nothing to undo. */
263
+ undo(): Promise<boolean>;
264
+ redo(): Promise<boolean>;
265
+ canUndo(): boolean;
266
+ canRedo(): boolean;
267
+ /** Labels of the undo / redo steps, oldest first ("move", "pin", "update", "relayout", "expand", …). */
268
+ getHistory(): { undo: string[]; redo: string[] };
269
+ clearHistory(): void;
270
+ /** Run several changes as one undo step. Returns what fn returns. */
271
+ batch<T>(label: string, fn: () => T): T;
192
272
  /** Previous / next nodes of a node (direct, or the whole chain with { chain: true }). null if the id is unknown. */
193
273
  getConnections(id: string, opts?: { chain?: boolean }): Connections | null;
194
274
  fit(opts?: { padding?: number; maxZoom?: number }): void;
195
275
  /**
196
276
  * Zoom and pan so the whole flow through a node or edge (everything upstream and downstream) fills the view,
197
- * as large as possible. Defaults to the selected node or edge. Returns false if there is nothing to fit.
277
+ * as large as possible. Defaults to the selected node or edge (with several selected: fits the selection).
278
+ * Returns false if there is nothing to fit.
198
279
  */
199
280
  fitFlow(target?: string | Selection | EdgeSpec, opts?: FitOptions & { mode?: 'chain' | 'neighbors' }): boolean;
200
281
  /** Zoom and pan so the given nodes and the edges between them fill the view, as large as possible. */
201
282
  fitNodes(ids: Iterable<string>, opts?: FitOptions): boolean;
283
+ /** Open (or close) a node's details. The layout makes room; the node keeps its place on screen. */
284
+ expand(id: string, expanded?: boolean): Promise<boolean>;
285
+ collapse(id: string): Promise<boolean>;
286
+ toggleExpand(id: string): Promise<boolean>;
287
+ isExpanded(id: string): boolean;
288
+ /** Fold nodes under `id` with an animation: they slide in underneath it; the node shows a card stack and "+N". */
289
+ stack(id: string, opts?: { direction?: 'upstream' | 'downstream'; animate?: boolean }): Promise<boolean>;
290
+ /** Unfold a stack: the nodes come back out from underneath `id`. */
291
+ unstack(id: string, opts?: { animate?: boolean }): Promise<boolean>;
292
+ toggleStack(id: string, opts?: { direction?: 'upstream' | 'downstream'; animate?: boolean }): Promise<boolean>;
293
+ unstackAll(opts?: { animate?: boolean }): Promise<GraphView>;
294
+ isStacked(id: string): boolean;
295
+ /** Ids folded under `id`, or every folded-away node when `id` is omitted. */
296
+ getStacked(id?: string): string[];
297
+ /** Add nodes/edges; the new nodes come out from underneath `from` (default: their first existing predecessor). */
298
+ addNodes(add: { nodes?: NodeSpec[]; edges?: EdgeSpec[]; groups?: GroupSpec[] }, opts?: { from?: string; animate?: boolean; mode?: 'stable' | 'relayout' }): Promise<GraphView>;
299
+ /** Remove nodes and their edges; they slide into `to` (default: their first remaining neighbour) and disappear. */
300
+ removeNodes(ids: string | string[], opts?: { to?: string; animate?: boolean; mode?: 'stable' | 'relayout' }): Promise<GraphView>;
301
+ /** Explore mode: the open nodes, from a start node down. */
302
+ getExplorePath(): string[];
303
+ /** Explore mode: open a path (each id a child of the one before). [] shows only the start nodes. */
304
+ setExplorePath(path: string[], opts?: { animate?: boolean }): Promise<GraphView>;
305
+ /** Explore mode: close the last open node (also Escape). */
306
+ exploreBack(): Promise<GraphView>;
202
307
  zoomBy(factor: number): void;
203
308
  zoomTo(k: number): void;
204
309
  zoomAt(k: number, clientX: number, clientY: number): void;
@@ -212,7 +317,7 @@ export interface GraphView {
212
317
 
213
318
  export function createGraph(container: HTMLElement | string, data: GraphData, options?: Partial<GraphOptions>): GraphView;
214
319
 
215
- export interface RoutedPath { points: Point[]; kind: EdgeRouting; sourceSide: Side; targetSide: Side; hops: { seg: number; x: number; y: number }[]; }
320
+ export interface RoutedPath { points: Point[]; kind: EdgeRouting; sourceSide: Side; targetSide: Side; hops: { seg: number; x: number; y: number }[]; /** Set on edges that share a fan-out trunk. */ bundle?: string; }
216
321
  export interface LayoutResult {
217
322
  nodes: Map<string, Rect & { rank: number; order: number }>;
218
323
  edges: Map<string, { waypoints: Point[]; reversed: boolean; selfLoop: boolean; flat: boolean }>;