@kazant/flexgraph 1.0.2 → 1.2.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 +42 -0
- package/README.md +90 -4
- package/css/graph.css +121 -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 +117 -5
package/dist/flexgraph.worker.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! FlexGraph v1.0
|
|
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.2.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.0
|
|
3
|
+
"version": "1.2.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,12 @@ 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;
|
|
43
49
|
[key: string]: unknown;
|
|
44
50
|
}
|
|
45
51
|
|
|
@@ -93,6 +99,8 @@ export interface GraphOptions {
|
|
|
93
99
|
maxIterations: number;
|
|
94
100
|
bendPenalty: number;
|
|
95
101
|
crossingPenalty: number;
|
|
102
|
+
/** When this many edges leave one side of a node, they share one trunk (tree style). 0 turns it off. Default 5. */
|
|
103
|
+
bundleFanOut: number;
|
|
96
104
|
defaultNodeWidth: number;
|
|
97
105
|
defaultNodeHeight: number;
|
|
98
106
|
pinOnDrag: boolean;
|
|
@@ -107,15 +115,53 @@ export interface GraphOptions {
|
|
|
107
115
|
hoverHighlight: 'chain' | 'neighbors';
|
|
108
116
|
/** Keep the hover highlight on the selected (clicked) node or edge until the selection is cleared. Default true. */
|
|
109
117
|
highlightSelection: boolean;
|
|
118
|
+
/**
|
|
119
|
+
* Multi-select (default true): Ctrl/Cmd/Shift + click adds or removes items, Shift + drag on the background draws a
|
|
120
|
+
* selection box, Ctrl/Cmd+A selects all, and dragging a selected node moves the whole selection.
|
|
121
|
+
*/
|
|
122
|
+
multiSelect: boolean;
|
|
123
|
+
/**
|
|
124
|
+
* Undo / redo (default true) for moves, pins, relayout, updateGraph, expand / collapse, importState and direction /
|
|
125
|
+
* routing changes. Ctrl/Cmd+Z, Ctrl/Cmd+Shift+Z or Ctrl/Cmd+Y, and buttons in the controls.
|
|
126
|
+
*/
|
|
127
|
+
history: boolean;
|
|
128
|
+
/** Undo steps kept. Default 100. */
|
|
129
|
+
historyLimit: number;
|
|
130
|
+
/** Text of the details toggle on expandable nodes. Defaults 'Details' / 'Hide'. */
|
|
131
|
+
expandText: string;
|
|
132
|
+
collapseText: string;
|
|
133
|
+
/**
|
|
134
|
+
* Explore mode for huge hierarchies: only nodes without a parent are shown at first; clicking a node opens its
|
|
135
|
+
* children. Only the open part of the graph is laid out and rendered.
|
|
136
|
+
*/
|
|
137
|
+
explore: boolean;
|
|
138
|
+
/** Explore mode: nodes off the open path are 'dim' (default), 'blur' or 'hide'. */
|
|
139
|
+
exploreUnfocused: 'dim' | 'blur' | 'hide';
|
|
140
|
+
/** Explore mode: children shown per node before a "+N more" node (click it to show more). Default 25. */
|
|
141
|
+
exploreLimit: number;
|
|
142
|
+
/** Explore mode: show the path as a breadcrumb in the top-left corner. Default true. */
|
|
143
|
+
exploreBreadcrumb: boolean;
|
|
144
|
+
/** Explore mode: first breadcrumb item (back to the start nodes). Default 'Start'. */
|
|
145
|
+
exploreStartText: string;
|
|
146
|
+
/** Explore mode: label of the "+N more" node. */
|
|
147
|
+
exploreMoreText?: (count: number) => string;
|
|
110
148
|
edgeTypes: Record<string, { markerStart?: MarkerName | null; markerEnd?: MarkerName | null }>;
|
|
111
149
|
/** URL of dist/flexgraph.worker.js to run layout + routing in a Web Worker. */
|
|
112
150
|
worker?: string | URL;
|
|
113
151
|
/** Custom node content. Return an HTML string, an element, or nothing (to fill `el` yourself). */
|
|
114
152
|
renderNode?: (node: NodeSpec, el: HTMLElement) => string | Node | void | null;
|
|
153
|
+
/** Content of an expanded node. When set, every node gets a "Details" toggle (opt out per node with expandable: false). */
|
|
154
|
+
renderDetails?: (node: NodeSpec, el: HTMLElement) => string | Node | void | null;
|
|
155
|
+
onNodeExpand?: (node: NodeSpec, expanded: boolean) => void;
|
|
115
156
|
/** `connections.previous` / `connections.next`: the nodes directly before and after the clicked node. */
|
|
116
157
|
onNodeClick?: (node: NodeSpec, event: PointerEvent, connections: Connections) => void;
|
|
117
158
|
onEdgeClick?: (edge: EdgeSpec, event: PointerEvent) => void;
|
|
118
159
|
onBackgroundClick?: (event: PointerEvent) => void;
|
|
160
|
+
/** Right-click on a node. The browser menu is suppressed when this is set; open your own menu at event.clientX / clientY. */
|
|
161
|
+
onNodeContextMenu?: (node: NodeSpec, event: MouseEvent, connections: Connections) => void;
|
|
162
|
+
onEdgeContextMenu?: (edge: EdgeSpec, event: MouseEvent) => void;
|
|
163
|
+
onGroupContextMenu?: (group: GroupSpec, event: MouseEvent) => void;
|
|
164
|
+
onBackgroundContextMenu?: (event: MouseEvent) => void;
|
|
119
165
|
}
|
|
120
166
|
|
|
121
167
|
export interface ViewState {
|
|
@@ -138,13 +184,30 @@ export interface GraphEvents {
|
|
|
138
184
|
nodeclick: { node: NodeSpec; event: PointerEvent; previous: NodeSpec[]; next: NodeSpec[] };
|
|
139
185
|
edgeclick: { edge: EdgeSpec; event: PointerEvent };
|
|
140
186
|
groupclick: { group: GroupSpec; event: PointerEvent };
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
187
|
+
/** `ids`: every node being moved (the whole selection when a selected node is dragged). */
|
|
188
|
+
dragstart: { id: string; ids: string[] };
|
|
189
|
+
drag: { id: string; x: number; y: number; ids: string[] };
|
|
190
|
+
dragend: { id: string; x: number; y: number; ids: string[] };
|
|
191
|
+
/**
|
|
192
|
+
* Undo history changed. `data` is the graph data now shown: after an undo it can be an earlier object than the
|
|
193
|
+
* one you last passed to updateGraph, so keep your own copy in sync from here.
|
|
194
|
+
*/
|
|
195
|
+
history: { action: 'record' | 'undo' | 'redo' | 'clear'; label?: string; canUndo: boolean; canRedo: boolean; data: GraphData };
|
|
196
|
+
/** The set of selected items changed (`select` only reports the primary item). */
|
|
197
|
+
selectionchange: { items: Selection[]; nodes: NodeSpec[]; edges: EdgeSpec[] };
|
|
144
198
|
pin: { id: string; pinned: boolean };
|
|
145
199
|
change: ViewState;
|
|
146
200
|
viewport: { x: number; y: number; k: number };
|
|
147
201
|
animationend: void;
|
|
202
|
+
expand: { id: string; expanded: boolean; node: NodeSpec };
|
|
203
|
+
/** Explore mode: the open path changed. */
|
|
204
|
+
explore: { path: string[] };
|
|
205
|
+
/** Right-click anywhere in the graph. Registering a listener suppresses the browser menu inside the graph. */
|
|
206
|
+
contextmenu:
|
|
207
|
+
| { kind: 'node'; id: string; node: NodeSpec; previous: NodeSpec[]; next: NodeSpec[]; event: MouseEvent; selection: Selection[] }
|
|
208
|
+
| { kind: 'edge'; id: string; edge: EdgeSpec; event: MouseEvent; selection: Selection[] }
|
|
209
|
+
| { kind: 'group'; id: string; group: GroupSpec; event: MouseEvent; selection: Selection[] }
|
|
210
|
+
| { kind: 'background'; event: MouseEvent; selection: Selection[] };
|
|
148
211
|
}
|
|
149
212
|
|
|
150
213
|
export interface Connections {
|
|
@@ -156,6 +219,15 @@ export interface Connections {
|
|
|
156
219
|
outgoing: EdgeSpec[];
|
|
157
220
|
}
|
|
158
221
|
|
|
222
|
+
export interface FitOptions {
|
|
223
|
+
/** Space around the fitted area in px. Default 40. */
|
|
224
|
+
padding?: number;
|
|
225
|
+
/** Highest zoom to use. Default: the graph's maxZoom option (4). */
|
|
226
|
+
maxZoom?: number;
|
|
227
|
+
/** Animate the zoom. Default: the graph's animate option. */
|
|
228
|
+
animate?: boolean;
|
|
229
|
+
}
|
|
230
|
+
|
|
159
231
|
export interface GraphView {
|
|
160
232
|
readonly ready: Promise<GraphView>;
|
|
161
233
|
readonly options: GraphOptions;
|
|
@@ -167,11 +239,51 @@ export interface GraphView {
|
|
|
167
239
|
pin(id: string, pinned?: boolean): void;
|
|
168
240
|
unpin(id: string): void;
|
|
169
241
|
unpinAll(): void;
|
|
170
|
-
|
|
242
|
+
/**
|
|
243
|
+
* Select one item, several, or nothing. Node ids can be passed as strings.
|
|
244
|
+
* `add` adds to the current selection, `toggle` flips each item in or out of it.
|
|
245
|
+
*/
|
|
246
|
+
select(sel: string | Selection | (string | Selection)[] | null, opts?: { add?: boolean; toggle?: boolean }): void;
|
|
247
|
+
/** The primary selected item (the one selected last), or null. */
|
|
171
248
|
getSelection(): Selection | null;
|
|
249
|
+
/** Every selected item, in the order they were selected. */
|
|
250
|
+
getSelectedItems(): Selection[];
|
|
251
|
+
getSelectedNodes(): NodeSpec[];
|
|
252
|
+
getSelectedEdges(): EdgeSpec[];
|
|
253
|
+
selectAll(): void;
|
|
254
|
+
clearSelection(): void;
|
|
255
|
+
/** Undo the last change. Resolves false if there was nothing to undo. */
|
|
256
|
+
undo(): Promise<boolean>;
|
|
257
|
+
redo(): Promise<boolean>;
|
|
258
|
+
canUndo(): boolean;
|
|
259
|
+
canRedo(): boolean;
|
|
260
|
+
/** Labels of the undo / redo steps, oldest first ("move", "pin", "update", "relayout", "expand", …). */
|
|
261
|
+
getHistory(): { undo: string[]; redo: string[] };
|
|
262
|
+
clearHistory(): void;
|
|
263
|
+
/** Run several changes as one undo step. Returns what fn returns. */
|
|
264
|
+
batch<T>(label: string, fn: () => T): T;
|
|
172
265
|
/** Previous / next nodes of a node (direct, or the whole chain with { chain: true }). null if the id is unknown. */
|
|
173
266
|
getConnections(id: string, opts?: { chain?: boolean }): Connections | null;
|
|
174
267
|
fit(opts?: { padding?: number; maxZoom?: number }): void;
|
|
268
|
+
/**
|
|
269
|
+
* Zoom and pan so the whole flow through a node or edge (everything upstream and downstream) fills the view,
|
|
270
|
+
* as large as possible. Defaults to the selected node or edge (with several selected: fits the selection).
|
|
271
|
+
* Returns false if there is nothing to fit.
|
|
272
|
+
*/
|
|
273
|
+
fitFlow(target?: string | Selection | EdgeSpec, opts?: FitOptions & { mode?: 'chain' | 'neighbors' }): boolean;
|
|
274
|
+
/** Zoom and pan so the given nodes and the edges between them fill the view, as large as possible. */
|
|
275
|
+
fitNodes(ids: Iterable<string>, opts?: FitOptions): boolean;
|
|
276
|
+
/** Open (or close) a node's details. The layout makes room; the node keeps its place on screen. */
|
|
277
|
+
expand(id: string, expanded?: boolean): Promise<boolean>;
|
|
278
|
+
collapse(id: string): Promise<boolean>;
|
|
279
|
+
toggleExpand(id: string): Promise<boolean>;
|
|
280
|
+
isExpanded(id: string): boolean;
|
|
281
|
+
/** Explore mode: the open nodes, from a start node down. */
|
|
282
|
+
getExplorePath(): string[];
|
|
283
|
+
/** Explore mode: open a path (each id a child of the one before). [] shows only the start nodes. */
|
|
284
|
+
setExplorePath(path: string[], opts?: { animate?: boolean }): Promise<GraphView>;
|
|
285
|
+
/** Explore mode: close the last open node (also Escape). */
|
|
286
|
+
exploreBack(): Promise<GraphView>;
|
|
175
287
|
zoomBy(factor: number): void;
|
|
176
288
|
zoomTo(k: number): void;
|
|
177
289
|
zoomAt(k: number, clientX: number, clientY: number): void;
|
|
@@ -185,7 +297,7 @@ export interface GraphView {
|
|
|
185
297
|
|
|
186
298
|
export function createGraph(container: HTMLElement | string, data: GraphData, options?: Partial<GraphOptions>): GraphView;
|
|
187
299
|
|
|
188
|
-
export interface RoutedPath { points: Point[]; kind: EdgeRouting; sourceSide: Side; targetSide: Side; hops: { seg: number; x: number; y: number }[]; }
|
|
300
|
+
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; }
|
|
189
301
|
export interface LayoutResult {
|
|
190
302
|
nodes: Map<string, Rect & { rank: number; order: number }>;
|
|
191
303
|
edges: Map<string, { waypoints: Point[]; reversed: boolean; selfLoop: boolean; flat: boolean }>;
|