@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.
- package/CHANGELOG.md +48 -0
- package/README.md +100 -4
- package/css/graph.css +165 -4
- package/dist/flexgraph.esm.js +2 -2
- package/dist/flexgraph.umd.cjs +2 -2
- package/dist/flexgraph.umd.js +2 -2
- package/dist/flexgraph.worker.js +2 -2
- package/package.json +1 -1
- package/types/index.d.ts +116 -11
package/dist/flexgraph.worker.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! FlexGraph v1.
|
|
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.
|
|
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
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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
|
-
|
|
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
|
|
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 }>;
|