@kazant/flexgraph 1.1.0 → 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 +31 -0
- package/README.md +71 -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 +95 -10
package/dist/flexgraph.worker.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! FlexGraph v1.
|
|
2
|
-
var bn=["top","right","bottom","left"],kn=["TB","LR","BT","RL"],vn=["orthogonal","straight","curved"],Gt=Object.freeze({direction:"TB",nodeSpacing:40,rankSpacing:80,edgeSpacing:10,edgeRouting:"orthogonal",cornerRadius:6,lineHops:!0,hopRadius:4,animate:!0,animationDuration:300,nodeMargin:14,groupPadding:20,groupLabelHeight:22,componentSpacing:80,maxIterations:24,bendPenalty:24,crossingPenalty:120,defaultNodeWidth:160,defaultNodeHeight:60,pinOnDrag:!0,draggable:!0,zoomable:!0,pannable:!0,minZoom:.1,maxZoom:4,controls:!0,showPorts:!0,hoverHighlight:"chain",highlightSelection:!0,edgeTypes:{default:{markerEnd:"arrow"},"has-many":{markerStart:"one",markerEnd:"many"},"has-one":{markerStart:"one",markerEnd:"onlyOne"},"belongs-to":{markerStart:"many",markerEnd:"one"},"many-to-many":{markerStart:"many",markerEnd:"many"},association:{markerEnd:"open"},composition:{markerStart:"diamond"},dependency:{markerEnd:"open"}}}),ut=class extends Error{constructor(s,c=[]){super(s),this.name="GraphValidationError",this.details=c}},Z=t=>typeof t=="number"&&Number.isFinite(t);function In(...t){let s={...Gt,edgeTypes:{...Gt.edgeTypes}};for(let c of t)if(c)for(let[r,o]of Object.entries(c))o!==void 0&&(r==="edgeTypes"?Object.assign(s.edgeTypes,o):s[r]=o);return kn.includes(s.direction)||(s.direction="TB"),vn.includes(s.edgeRouting)||(s.edgeRouting="orthogonal"),s}function Ut(t,s,c){if(!t||typeof t!="object")throw new ut("Graph must be an object");let r=In(t.options,s),o=[],n=[],i=[],h=new Map;for(let f of t.groups||[]){if(!f||f.id==null){o.push("Group without id");continue}let e=String(f.id);if(h.has(e)){o.push(`Duplicate group id "${e}"`);continue}let l={id:e,label:f.label??e,className:f.className||"",data:f};i.push(l),h.set(e,l)}let a=[],u=new Map;(t.nodes||[]).forEach((f,e)=>{if(!f||f.id==null){o.push(`Node at index ${e} has no id`);return}let l=String(f.id);if(u.has(l)){o.push(`Duplicate node id "${l}"`);return}let m=c&&c.get(l),x=Z(f.width)?f.width:m?m.width:r.defaultNodeWidth,M=Z(f.height)?f.height:m?m.height:r.defaultNodeHeight,w=f.group!=null?String(f.group):null;if(w&&!h.has(w)){let R={id:w,label:w,className:"",data:{id:w}};i.push(R),h.set(w,R)}let y=[],b=new Set;for(let R of f.ports||[]){if(!R||R.id==null){n.push(`Node "${l}": port without id ignored`);continue}let A=String(R.id);if(b.has(A)){n.push(`Node "${l}": duplicate port "${A}" ignored`);continue}let $=bn.includes(R.side)?R.side:null;$||n.push(`Node "${l}": port "${A}" has invalid side "${R.side}", using auto side`),b.add(A),y.push({id:A,side:$,offset:Z(R.offset)?Math.min(1,Math.max(0,R.offset)):null,label:R.label,data:R})}let k=f.constraints||{},P={pinned:!!k.pinned,x:Z(k.x)?k.x:Z(f.x)&&k.pinned?f.x:null,y:Z(k.y)?k.y:Z(f.y)&&k.pinned?f.y:null,rank:Number.isInteger(k.rank)&&k.rank>=0?k.rank:null};P.pinned&&(P.x==null||P.y==null)&&(n.push(`Node "${l}" is pinned but has no x/y; pin ignored until it has a position`),P.pinned=!1);let L={id:l,index:e,label:f.label??l,width:x,height:M,group:w,ports:y,portById:new Map(y.map(R=>[R.id,R])),constraints:P,className:f.className||"",type:f.type||null,data:f};a.push(L),u.set(l,L)});let p=[],g=new Map;(t.edges||[]).forEach((f,e)=>{if(!f)return;let l=f.id!=null?String(f.id):`e${e}`;if(g.has(l)){o.push(`Duplicate edge id "${l}"`);return}let m=String(f.source),x=String(f.target);if(!u.has(m)){o.push(`Edge "${l}": unknown source node "${m}"`);return}if(!u.has(x)){o.push(`Edge "${l}": unknown target node "${x}"`);return}let M=f.sourcePort!=null?String(f.sourcePort):null,w=f.targetPort!=null?String(f.targetPort):null;M&&!u.get(m).portById.has(M)&&(n.push(`Edge "${l}": node "${m}" has no port "${M}"`),M=null),w&&!u.get(x).portById.has(w)&&(n.push(`Edge "${l}": node "${x}" has no port "${w}"`),w=null);let y=r.edgeTypes[f.type]||r.edgeTypes.default||{},b={id:l,index:e,source:m,target:x,sourcePort:M,targetPort:w,type:f.type||"default",label:f.label??null,minLen:Number.isInteger(f.minLen)&&f.minLen>=0?f.minLen:1,weight:Z(f.weight)?f.weight:1,markerStart:f.markerStart!==void 0?f.markerStart:y.markerStart||null,markerEnd:f.markerEnd!==void 0?f.markerEnd:y.markerEnd||null,className:f.className||"",data:f};p.push(b),g.set(l,b)});let d=[];for(let f of t.constraints||[])if(!(!f||!f.type))if(f.type==="leftOf"||f.type==="before"){let e=String(f.a),l=String(f.b);if(!u.has(e)||!u.has(l)){n.push("leftOf constraint references unknown node");continue}d.push({type:"leftOf",a:e,b:l})}else if(f.type==="sameRank"){let e=(f.nodes||[]).map(String).filter(l=>u.has(l));e.length>=2?d.push({type:"sameRank",nodes:e}):n.push("sameRank constraint needs at least two known nodes")}else if(f.type==="rank"){let e=String(f.node);u.has(e)&&Number.isInteger(f.rank)&&(u.get(e).constraints.rank=f.rank)}else n.push(`Unknown constraint type "${f.type}"`);if(o.length)throw new ut(o[0],o);return{options:r,nodes:a,nodeById:u,edges:p,edgeById:g,groups:i,groupById:h,constraints:d,warnings:n}}function Sn(t,s){let c=new Map(t.map(h=>[h,[]])),r=new Map(t.map(h=>[h,0]));for(let h of s)c.get(h.v).push(h),r.set(h.w,r.get(h.w)+1);let o=new Map,n=new Set,i=[...t.filter(h=>r.get(h)===0),...t];for(let h of i){if(o.has(h))continue;let a=[[h,0]];for(o.set(h,1);a.length;){let u=a[a.length-1],[p,g]=u,d=c.get(p);if(g>=d.length){o.set(p,2),a.pop();continue}u[1]++;let f=d[g],e=o.get(f.w);e===1?n.add(f.id):e||(o.set(f.w,1),a.push([f.w,0]))}}return n}var bt=class{constructor(s){this.p=new Map(s.map(c=>[c,c]))}find(s){let c=s;for(;this.p.get(c)!==c;)c=this.p.get(c);for(;this.p.get(s)!==c;){let r=this.p.get(s);this.p.set(s,c),s=r}return c}union(s,c){let r=this.find(s),o=this.find(c);r!==o&&this.p.set(o,r)}};function Yt(t,s,c={}){let r=[],o=new bt(t);for(let y of c.sameRank||[])for(let b=1;b<y.length;b++)o.union(y[0],y[b]);let n=[...new Set(t.map(y=>o.find(y)))],i=new Set,h=new Set,a=[];for(let y of s){if(y.source===y.target){i.add(y.id);continue}let b=o.find(y.source),k=o.find(y.target);if(b===k){h.add(y.id);continue}a.push({id:y.id,v:b,w:k,minLen:y.minLen??1})}let u=Sn(n,a),p=a.map(y=>u.has(y.id)?{...y,v:y.w,w:y.v}:y),g=new Map;if(c.fixedRank)for(let[y,b]of c.fixedRank){if(!o.p.has(y))continue;let k=o.find(y);g.has(k)&&g.get(k)!==b&&r.push(`Conflicting fixed ranks in sameRank set of "${y}"`),g.set(k,Math.max(g.get(k)??0,b))}let d=new Map(n.map(y=>[y,[]])),f=new Map(n.map(y=>[y,[]]));for(let y of p)d.get(y.v).push(y),f.get(y.w).push(y);let e=new Map(n.map(y=>[y,f.get(y).length])),l=n.filter(y=>e.get(y)===0),m=[];for(;l.length;){let y=l.shift();m.push(y);for(let b of d.get(y))e.set(b.w,e.get(b.w)-1),e.get(b.w)===0&&l.push(b.w)}let x=new Map;for(let y of m){let b=g.get(y)??0;for(let k of f.get(y))b=Math.max(b,x.get(k.v)+k.minLen);g.has(y)&&b!==g.get(y)&&r.push(`Fixed rank ${g.get(y)} for "${y}" cannot be satisfied; using ${b}`),x.set(y,b)}for(let y=m.length-1;y>=0;y--){let b=m[y];if(g.has(b))continue;let k=d.get(b);if(!k.length||f.get(b).length>=k.length)continue;let L=1/0;for(let R of k)L=Math.min(L,x.get(R.w)-R.minLen);L>x.get(b)&&x.set(b,L)}let M=1/0;for(let y of x.values())M=Math.min(M,y);if(!g.size&&M>0)for(let[y,b]of x)x.set(y,b-M);let w=new Map;for(let y of t)w.set(y,x.get(o.find(y))??0);return{rank:w,reversed:u,flat:h,selfLoops:i,warnings:r}}function Vt(t,s,c=0){let r=[],o=new Map;for(let u of t)o.set(u.id,r.length),r.push({id:u.id,real:!0,rank:u.rank,width:u.width,height:u.height??0,group:u.group??null,pinX:u.pinX??null,inputIndex:r.length,up:[],down:[]});let n=new Map,i=[],h=(u,p,g,d,f,e)=>{let l={a:u,b:p,aOff:g,bOff:d,w:f,edgeId:e};i.push(l),r[u].down.push({n:p,off:d,own:g,w:f}),r[p].up.push({n:u,off:g,own:d,w:f})};for(let u of s){let p=o.get(u.v),g=o.get(u.w),d=r[p].rank,f=r[g].rank;if(f<=d)continue;let e=r[p].group&&r[p].group===r[g].group?r[p].group:null,l=[],m=p,x=u.vOff||0;for(let M=d+1;M<f;M++){let w=r.length;r.push({id:`__d_${u.id}_${M}`,real:!1,rank:M,width:c,height:0,group:e,pinX:null,edgeId:u.id,inputIndex:w,up:[],down:[]}),h(m,w,x,0,u.weight??1,u.id),l.push(w),m=w,x=0}h(m,g,x,u.wOff||0,u.weight??1,u.id),n.set(u.id,l)}let a=0;for(let u of r)a=Math.max(a,u.rank);return{v:r,index:o,segs:i,chains:n,maxRank:a}}function vt(t){let s=Array.from({length:t.maxRank+1},()=>[]),c=new Uint8Array(t.v.length),r=t.v.map((o,n)=>n).filter(o=>t.v[o].real).sort((o,n)=>t.v[o].rank-t.v[n].rank||t.v[o].inputIndex-t.v[n].inputIndex);for(let o of r){if(c[o])continue;let n=[o];for(;n.length;){let i=n.pop();if(c[i])continue;c[i]=1,s[t.v[i].rank].push(i);let h=t.v[i].down.map(a=>a.n);for(let a=h.length-1;a>=0;a--)c[h[a]]||n.push(h[a])}}for(let o=0;o<t.v.length;o++)c[o]||s[t.v[o].rank].push(o);return s}function Pn(t){let s=t.length;if(s<2)return 0;let c=t.slice(),r=new Array(s),o=0;for(let n=1;n<s;n*=2){for(let i=0;i<s;i+=2*n){let h=Math.min(i+n,s),a=Math.min(i+2*n,s),u=i,p=h,g=i;for(;u<h&&p<a;)c[u]<=c[p]?r[g++]=c[u++]:(o+=h-u,r[g++]=c[p++]);for(;u<h;)r[g++]=c[u++];for(;p<a;)r[g++]=c[p++]}[c,r]=[r,c]}return o}function Rn(t,s,c,r){let o=[];for(let n of s)for(let i of t.v[n].down)o.push([r[n]+i.own*.999,r[i.n]+i.off*.999]);return o.sort((n,i)=>n[0]-i[0]||n[1]-i[1]),Pn(o.map(n=>n[1]))}function kt(t,s){let c=ht(t,s),r=0;for(let o=0;o<s.length-1;o++)r+=Rn(t,s[o],s[o+1],c);return r}function ht(t,s){let c=new Float64Array(t.v.length);for(let r of s)r.forEach((o,n)=>{c[o]=n});return c}function Wt(t,s={}){let c=s.maxIterations??24,r=(s.leftOf||[]).map(([u,p])=>[t.index.get(u),t.index.get(p)]).filter(([u,p])=>u!=null&&p!=null&&t.v[u].rank===t.v[p].rank),o=new Set(r.map(([u,p])=>u+":"+p)),n=[];s.initial&&n.push(s.initial.map(u=>u.slice()));let i=vt(t);n.push(i),!s.initial&&c>4&&(n.push(i.map(u=>u.slice().reverse())),n.push(i.map(u=>u.slice().sort((p,g)=>t.v[p].inputIndex-t.v[g].inputIndex))));let h=null,a=1/0;for(let u of n){let p=Nn(t,u,r,o,c);if(p.crossings<a&&(h=p.layers,a=p.crossings),a===0)break}return{layers:h,crossings:a}}function Nn(t,s,c,r,o){let n=s.map(u=>Kt(t,u,c)),i=n.map(u=>u.slice()),h=kt(t,n),a=0;for(let u=0;u<o&&h>0;u++){let p=u%2===0;On(t,n,p,c,u%4>=2),Ln(t,n,r);let g=kt(t,n);if(g<h)h=g,i=n.map(d=>d.slice()),a=0;else if(++a>=6)break}if(h>0&&o>4){n=i.map(u=>u.slice());for(let u=0;u<2;u++){En(t,n,r);let p=kt(t,n);if(p<h)h=p,i=n.map(g=>g.slice());else break}}return{layers:i,crossings:h}}function En(t,s,c){let r=ht(t,s);for(let o of s)if(!(o.length<3||o.length>120))for(let n of o.slice()){let i=t.v[n];if(i.pinX!=null||i.group)continue;let h=o.indexOf(n),a=0,u=h,p=0;for(let g=h-1;g>=0;g--){let d=o[g];if(c.has(d+":"+n)||t.v[d].group)break;p+=et(t,n,d,r)-et(t,d,n,r),p<a&&(a=p,u=g)}p=0;for(let g=h+1;g<o.length;g++){let d=o[g];if(c.has(n+":"+d)||t.v[d].group)break;p+=et(t,d,n,r)-et(t,n,d,r),p<a&&(a=p,u=g)}u!==h&&(o.splice(h,1),o.splice(u,0,n),o.forEach((g,d)=>{r[g]=d}))}}function On(t,s,c,r,o){let n=ht(t,s),i=s.length,h=c?_t(1,i):_t(i-2,-1,-1);for(let a of h){let u=s[a],p=new Map;u.forEach((e,l)=>{let m=c?t.v[e].up:t.v[e].down;if(!m.length){p.set(e,l);return}if(o){let w=m.map(b=>n[b.n]+b.off-b.own).sort((b,k)=>b-k),y=w.length>>1;p.set(e,w.length%2?w[y]:(w[y-1]+w[y])/2);return}let x=0,M=0;for(let w of m)x+=(n[w.n]+w.off-w.own)*w.w,M+=w.w;p.set(e,x/M)});let g=new Map;for(let e of u){let l=t.v[e].group;if(!l)continue;let m=g.get(l)||[0,0];m[0]+=p.get(e),m[1]++,g.set(l,m)}let d=e=>{let l=t.v[e].group;return l?g.get(l)[0]/g.get(l)[1]:p.get(e)},f=new Map(u.map((e,l)=>[e,l]));u.sort((e,l)=>d(e)-d(l)||(t.v[e].group||"").localeCompare(t.v[l].group||"")||p.get(e)-p.get(l)||f.get(e)-f.get(l)),s[a]=Kt(t,u,r),s[a].forEach((e,l)=>{n[e]=l})}}function Kt(t,s,c){let r=s.slice(),o=[],n=[];if(r.forEach((i,h)=>{t.v[i].pinX!=null&&(o.push(h),n.push(i))}),n.length>1&&(n.sort((i,h)=>t.v[i].pinX-t.v[h].pinX),o.forEach((i,h)=>{r[i]=n[h]})),c.length)for(let i=0;i<c.length+1;i++){let h=!1;for(let[a,u]of c){let p=r.indexOf(a),g=r.indexOf(u);p<0||g<0||p<g||(r.splice(p,1),r.splice(r.indexOf(u),0,a),h=!0)}if(!h)break}return r}function et(t,s,c,r){let o=0;for(let n of["up","down"]){let i=t.v[s][n],h=t.v[c][n];for(let a of i)for(let u of h)r[a.n]+a.off>r[u.n]+u.off&&(o+=a.w*u.w)}return o}function Ln(t,s,c){let r=ht(t,s),o=!0,n=0;for(;o&&n++<8;){o=!1;for(let i of s)for(let h=0;h<i.length-1;h++){let a=i[h],u=i[h+1],p=t.v[a],g=t.v[u];if((p.group||null)!==(g.group||null)||p.pinX!=null&&g.pinX!=null||c.has(a+":"+u))continue;let d=et(t,a,u,r);et(t,u,a,r)<d&&(i[h]=u,i[h+1]=a,r[u]=h,r[a]=h+1,o=!0)}}}function _t(t,s,c=1){let r=[];if(c>0)for(let o=t;o<s;o+=c)r.push(o);else for(let o=t;o>s;o+=c)r.push(o);return r}function An(t,s,c){let r=t.length,o=new Float64Array(r);for(let p=1;p<r;p++)o[p]=o[p-1]+c[p];let n=[],i=[],h=[],a=[];for(let p=0;p<r;p++)for(n.push(t[p]-o[p]),i.push(s[p]),h.push(p),a.push(p);n.length>1&&n[n.length-2]>n[n.length-1];){let g=n.length-1,d=g-1,f=i[d]+i[g];n[d]=(n[d]*i[d]+n[g]*i[g])/f,i[d]=f,a[d]=a[g],n.pop(),i.pop(),h.pop(),a.pop()}let u=new Float64Array(r);for(let p=0;p<n.length;p++)for(let g=h[p];g<=a[p];g++)u[g]=n[p]+o[g];return u}function Zt(t,s,c){let r=t.v.length,o=new Float64Array(r),n=new Float64Array(r),i=c.groupPadding??20,h=c.groupLabelHeight??0,a=(w,y)=>{let b=t.v[w],k=t.v[y],P;return!b.real&&!k.real?P=c.edgeSpacing:!b.real||!k.real?P=(c.nodeSpacing+c.edgeSpacing)/2:P=c.nodeSpacing,b.group!==k.group&&(b.group&&(P+=i),k.group&&(P+=i+(c.labelOnOrderAxis?h:0))),(b.width+k.width)/2+P},u=s.map(w=>w.map((y,b)=>b===0?0:a(w[b-1],y)));s.forEach((w,y)=>{let b=0;w.forEach((P,L)=>{b+=u[y][L],o[P]=b});let k=b/2;w.forEach(P=>{o[P]-=k})});let p=w=>t.v[w].real?1:4,g=(w,y,b)=>{let k=s[w];if(!k.length)return;let P=new Array(k.length),L=new Array(k.length);k.forEach((A,$)=>{let z=t.v[A];if(z.pinX!=null){P[$]=z.pinX,L[$]=1e6;return}let v=0,N=0,X=G=>{for(let V of G){let Q=V.w*(t.v[V.n].real?1:2)*p(A);v+=(o[V.n]+V.off*t.v[V.n].width-V.own*z.width)*Q,N+=Q}};y&&X(z.up),b&&X(z.down),N===0?(P[$]=o[A],L[$]=.05):(P[$]=v/N,L[$]=N)});let R=An(P,L,u[w]);k.forEach((A,$)=>{o[A]=R[$]})},d=s.length,f=c.iterations??8;for(let w=0;w<f;w++){for(let y=1;y<d;y++)g(y,!0,!1);for(let y=d-2;y>=0;y--)g(y,!1,!0)}for(let w=0;w<2;w++){for(let y=0;y<d;y++)g(y,!0,!0);for(let y=d-1;y>=0;y--)g(y,!0,!0)}let e=s.map(w=>w.reduce((y,b)=>Math.max(y,t.v[b].height||0),0)),l=new Map;for(let w of t.v){if(!w.real||!w.group)continue;let y=l.get(w.group)||[1/0,-1/0];y[0]=Math.min(y[0],w.rank),y[1]=Math.max(y[1],w.rank),l.set(w.group,y)}let m=new Float64Array(d);for(let[w,y]of l.values()){let b=c.labelOnOrderAxis||c.labelAtRankEnd?0:h,k=c.labelAtRankEnd&&!c.labelOnOrderAxis?h:0;w>0&&(m[w]=Math.max(m[w],i+b)),y<d-1&&(m[y+1]=Math.max(m[y+1],i+k))}let x=[],M=0;for(let w=0;w<d;w++)w>0?M+=e[w-1]/2+c.rankSpacing+m[w]+e[w]/2:M=e[0]/2,x.push(M);for(let w=0;w<r;w++)n[w]=x[t.v[w].rank];return{x:o,y:n,rankY:x,rankHeight:e}}var ct={top:{x:0,y:-1},bottom:{x:0,y:1},left:{x:-1,y:0},right:{x:1,y:0}};function Jt(t){switch(t){case"LR":return{x:1,y:0,exit:"right",entry:"left"};case"RL":return{x:-1,y:0,exit:"left",entry:"right"};case"BT":return{x:0,y:-1,exit:"top",entry:"bottom"};default:return{x:0,y:1,exit:"bottom",entry:"top"}}}function lt(t){let s=new Map,c={top:[],right:[],bottom:[],left:[]};for(let r of t.ports)r.side&&c[r.side].push(r);for(let r of Object.keys(c)){let o=c[r];o.forEach((n,i)=>{let h=n.offset!=null?n.offset:(i+1)/(o.length+1);s.set(n.id,{side:r,t:h,...Bn(r,h)})})}return s}function Bn(t,s){switch(t){case"top":return{px:s,py:0};case"bottom":return{px:s,py:1};case"left":return{px:0,py:s};default:return{px:1,py:s}}}var J=t=>({x:t.x+t.width/2,y:t.y+t.height/2});function Qt(t,s){return{x:t.x-s,y:t.y-s,width:t.width+2*s,height:t.height+2*s}}function qt(t,s,c,r=.5){return s>t.x+r&&s<t.x+t.width-r&&c>t.y+r&&c<t.y+t.height-r}function It(t,s){let c=J(t),r=s.x-c.x,o=s.y-c.y;if(r===0&&o===0)return{...c,side:"bottom"};let n=r!==0?t.width/2/Math.abs(r):1/0,i=o!==0?t.height/2/Math.abs(o):1/0,h=Math.min(n,i),a=n<i?r>0?"right":"left":o>0?"bottom":"top";return{x:c.x+r*h,y:c.y+o*h,side:a}}function St(t){let s=[];for(let c of t){let r=s[s.length-1];r&&Math.abs(r.x-c.x)<.01&&Math.abs(r.y-c.y)<.01||s.push({x:c.x,y:c.y})}for(let c=s.length-2;c>=1;c--){let r=s[c-1],o=s[c],n=s[c+1],i=(o.x-r.x)*(n.y-o.y)-(o.y-r.y)*(n.x-o.x),h=(o.x-r.x)*(n.x-o.x)+(o.y-r.y)*(n.y-o.y);Math.abs(i)<.01&&h>=0&&s.splice(c,1)}return s}var tn=(t,s,c)=>{switch(t){case"BT":return{x:s,y:-c};case"LR":return{x:c,y:s};case"RL":return{x:-c,y:s};default:return{x:s,y:c}}},Pt=(t,s,c)=>{switch(t){case"BT":return{x:s,y:-c};case"LR":return{x:c,y:s};case"RL":return{x:c,y:-s};default:return{x:s,y:c}}};function on(t,s={}){return t.nodes.some(c=>c.group)?$n(t,s):Rt(t,s)}function nn(t,s,c){let r=new Set(s.map(n=>n.id)),o=s.map(n=>({...n,group:null,constraints:c?n.constraints:{...n.constraints,pinned:!1}}));return{options:t.options,nodes:o,nodeById:new Map(o.map(n=>[n.id,n])),edges:t.edges.filter(n=>r.has(n.source)&&r.has(n.target)),groups:[],groupById:new Map,constraints:t.constraints.filter(n=>n.type==="sameRank"?n.nodes.every(i=>r.has(i)):r.has(n.a)&&r.has(n.b)),warnings:[]}}function $n(t,s){let c=en(t,s.hints||null,s.hints||null),r=new Map,o=i=>({x:i.x+i.width/2,y:i.y+i.height/2});for(let i of t.nodes){let h=c.nodes.get(i.id);if(!i.group){r.set(i.id,o(h));continue}let a=0,u=0,p=0;for(let g of t.edges){let d=g.source===i.id?g.target:g.target===i.id?g.source:null;if(d==null||t.nodeById.get(d).group===i.group)continue;let f=o(c.nodes.get(d));a+=f.x,u+=f.y,p++}r.set(i.id,p?{x:a/p,y:u/p}:o(h))}let n=en(t,r,s.hints||r);return n.crossingsRouted<=c.crossingsRouted?n:c}function en(t,s,c){let r=t.options,o=r.groupPadding,n=r.groupLabelHeight,i=new Map;for(let e of t.nodes)e.group&&(i.has(e.group)||i.set(e.group,[]),i.get(e.group).push(e));let h=new Map,a=[];for(let[e,l]of i){let m=Rt(nn(t,l,!1),{hints:s}),x=m.bounds,M="\0group:"+e;h.set(e,{sub:m,b:x,blockId:M}),a.push({id:M,index:-1,label:e,width:x.width+2*o,height:x.height+2*o+n,group:null,ports:[],portById:new Map,constraints:{pinned:!1,x:null,y:null,rank:null}})}let u=e=>{let l=t.nodeById.get(e);return l.group?h.get(l.group).blockId:e},p=nn(t,t.nodes.filter(e=>!e.group),!0);p.nodes.push(...a);for(let e of a)p.nodeById.set(e.id,e);p.edges=[];for(let e of t.edges){let l=u(e.source),m=u(e.target);l===m&&(e.source!==e.target||l!==e.source)||p.edges.push({...e,source:l,target:m,sourcePort:l===e.source?e.sourcePort:null,targetPort:m===e.target?e.targetPort:null})}let g=null;if(c){g=new Map(c);for(let[e,l]of i){let m=0,x=0,M=0;for(let w of l){let y=c.get(w.id);y&&(m+=y.x,x+=y.y,M++)}M&&g.set(h.get(e).blockId,{x:m/M,y:x/M})}}let d=Rt(p,{hints:g}),f={nodes:new Map,edges:new Map,groups:new Map,crossings:d.crossings,warnings:d.warnings};for(let e of t.nodes)e.group||f.nodes.set(e.id,d.nodes.get(e.id));for(let[,{sub:e,b:l,blockId:m}]of h){let x=d.nodes.get(m),M=x.x+o-l.x,w=x.y+o+n-l.y;for(let[y,b]of e.nodes)f.nodes.set(y,{...b,x:b.x+M,y:b.y+w});for(let[y,b]of e.edges)f.edges.set(y,{...b,waypoints:b.waypoints.map(k=>({x:k.x+M,y:k.y+w}))});f.crossings+=e.crossings}for(let e of t.edges){if(f.edges.has(e.id))continue;let l=d.edges.get(e.id),m=u(e.source)!==e.source||u(e.target)!==e.target;f.edges.set(e.id,l?{...l,waypoints:m?[]:l.waypoints}:{waypoints:[],reversed:!1,selfLoop:e.source===e.target,flat:!1})}for(let e of t.nodes)if(e.group&&e.constraints.pinned){let l=f.nodes.get(e.id);l.x=e.constraints.x,l.y=e.constraints.y}if(rn(t,f),!t.nodes.some(e=>e.constraints.pinned)){let e=Nt(f);sn(f,-e.x,-e.y);for(let l of f.groups.values())l.x-=e.x,l.y-=e.y}return f.bounds=Nt(f),f.crossingsRouted=Xn(t,f),f}function Xn(t,s){let c=[];for(let n of t.edges){if(n.source===n.target)continue;let i=s.nodes.get(n.source),h=s.nodes.get(n.target);c.push([n.source,n.target,i.x+i.width/2,i.y+i.height/2,h.x+h.width/2,h.y+h.height/2])}let r=0,o=(n,i,h,a,u,p)=>(h-n)*(p-i)-(a-i)*(u-n);for(let n=0;n<c.length;n++)for(let i=n+1;i<c.length;i++){let h=c[n],a=c[i];if(h[0]===a[0]||h[0]===a[1]||h[1]===a[0]||h[1]===a[1])continue;let u=o(a[2],a[3],a[4],a[5],h[2],h[3]),p=o(a[2],a[3],a[4],a[5],h[4],h[5]),g=o(h[2],h[3],h[4],h[5],a[2],a[3]),d=o(h[2],h[3],h[4],h[5],a[4],a[5]);u*p<0&&g*d<0&&r++}return r}function Rt(t,s={}){let c=t.options,r=c.direction,o=r==="LR"||r==="RL",n=[],i=new Map;for(let d of t.nodes){let f=lt(d),e=new Map;for(let[x,M]of f)e.set(x,(o?M.py:M.px)-.5);let l=null,m=null;if(d.constraints.pinned){let x=Pt(r,d.constraints.x+d.width/2,d.constraints.y+d.height/2);l=x.x,m=x.y}i.set(d.id,{iw:o?d.height:d.width,ih:o?d.width:d.height,frac:e,pinX:l,pinY:m})}let h=Hn(t),a={nodes:new Map,edges:new Map,groups:new Map,crossings:0,warnings:n},u=[];for(let d of h){let f=d.nodes,e=new Set(f),l=t.edges.filter(v=>e.has(v.source)),m=new Map;for(let v of f){let N=t.nodeById.get(v).constraints.rank;N!=null&&m.set(v,N)}let x=t.constraints.filter(v=>v.type==="sameRank").map(v=>v.nodes.filter(N=>e.has(N))).filter(v=>v.length>1),M=Yt(f,l,{fixedRank:m,sameRank:x});n.push(...M.warnings);let w=f.map(v=>{let N=t.nodeById.get(v),X=i.get(v);return{id:v,rank:M.rank.get(v),width:X.iw,height:X.ih,group:N.group,pinX:X.pinX}}),y=[];for(let v of l){if(M.selfLoops.has(v.id)||M.flat.has(v.id))continue;let N=M.reversed.has(v.id),X=v.sourcePort?i.get(v.source).frac.get(v.sourcePort)??0:0,G=v.targetPort?i.get(v.target).frac.get(v.targetPort)??0:0;y.push(N?{id:v.id,v:v.target,w:v.source,vOff:G,wOff:X,weight:v.weight}:{id:v.id,v:v.source,w:v.target,vOff:X,wOff:G,weight:v.weight})}let b=Vt(w,y,0),k;s.hints&&s.hints.size&&(k=Tn(b,s.hints,r));let P=t.constraints.filter(v=>v.type==="leftOf"&&e.has(v.a)&&e.has(v.b)).map(v=>[v.a,v.b]),L=Wt(b,{maxIterations:c.maxIterations,leftOf:P,initial:k});a.crossings+=L.crossings;let R=Zt(b,L.layers,{nodeSpacing:c.nodeSpacing,edgeSpacing:c.edgeSpacing,rankSpacing:c.rankSpacing,groupPadding:c.groupPadding,groupLabelHeight:c.groupLabelHeight,labelOnOrderAxis:o,labelAtRankEnd:r==="BT"||r==="RL"?!o:!1}),A=f.filter(v=>i.get(v).pinY!=null);if(A.length){let v=0;for(let N of A)v+=i.get(N).pinY-R.y[b.index.get(N)];v/=A.length;for(let N=0;N<R.y.length;N++)R.y[N]+=v;for(let N of A){let X=b.index.get(N);R.x[X]=i.get(N).pinX,R.y[X]=i.get(N).pinY}}let $=1/0,z=-1/0;for(let v=0;v<b.v.length;v++){let N=b.v[v].width/2;$=Math.min($,R.x[v]-N),z=Math.max(z,R.x[v]+N)}u.push({comp:d,g:b,co:R,rk:M,layers:L.layers,minX:$,maxX:z,pinned:A.length>0})}if(s.hints&&s.hints.size){let d=e=>{let l=0,m=0;for(let x of e.comp.nodes){let M=s.hints.get(x);M&&(l+=Pt(r,M.x,M.y).x,m++)}return m?l/m:1/0},f=new Map(u.map(e=>[e,d(e)]));u.sort((e,l)=>f.get(e)-f.get(l))}let p=-1/0;for(let d of u)d.pinned&&(p=Math.max(p,d.maxX+c.componentSpacing));p===-1/0&&(p=0);for(let d of u){if(d.pinned)continue;let f=p-d.minX;for(let e=0;e<d.co.x.length;e++)d.co.x[e]+=f;p+=d.maxX-d.minX+c.componentSpacing}for(let d of u){let{g:f,co:e,rk:l}=d;d.layers.forEach((m,x)=>m.forEach((M,w)=>{let y=f.v[M];if(!y.real)return;let b=t.nodeById.get(y.id),k=tn(r,e.x[M],e.y[M]);a.nodes.set(y.id,{x:k.x-b.width/2,y:k.y-b.height/2,width:b.width,height:b.height,rank:x,order:w})}));for(let m of t.edges){if(!d.comp.set.has(m.source))continue;let M=(f.chains.get(m.id)||[]).map(y=>tn(r,e.x[y],e.y[y])),w=l.reversed.has(m.id);w&&(M=M.reverse()),a.edges.set(m.id,{waypoints:M,reversed:w,selfLoop:l.selfLoops.has(m.id),flat:l.flat.has(m.id)})}}if(!u.some(d=>d.pinned)){let d=1/0,f=1/0;for(let l of a.nodes.values())d=Math.min(d,l.x),f=Math.min(f,l.y);let e=t.groups.length?c.groupPadding+c.groupLabelHeight:0;Number.isFinite(d)&&sn(a,-d+e,-f+e)}return rn(t,a),a.bounds=Nt(a),a}function sn(t,s,c){for(let r of t.nodes.values())r.x+=s,r.y+=c;for(let r of t.edges.values())for(let o of r.waypoints)o.x+=s,o.y+=c}function rn(t,s){let c=t.options;s.groups=new Map;for(let r of t.groups){let o=1/0,n=1/0,i=-1/0,h=-1/0;for(let u of t.nodes){if(u.group!==r.id)continue;let p=s.nodes.get(u.id);p&&(o=Math.min(o,p.x),n=Math.min(n,p.y),i=Math.max(i,p.x+p.width),h=Math.max(h,p.y+p.height))}if(!Number.isFinite(o))continue;let a=c.groupPadding;s.groups.set(r.id,{x:o-a,y:n-a-c.groupLabelHeight,width:i-o+2*a,height:h-n+2*a+c.groupLabelHeight})}return s.groups}function Nt(t){let s=1/0,c=1/0,r=-1/0,o=-1/0,n=i=>{s=Math.min(s,i.x),c=Math.min(c,i.y),r=Math.max(r,i.x+i.width),o=Math.max(o,i.y+i.height)};for(let i of t.nodes.values())n(i);for(let i of t.groups.values())n(i);return Number.isFinite(s)?{x:s,y:c,width:r-s,height:o-c}:{x:0,y:0,width:0,height:0}}function Tn(t,s,c){let r=vt(t),o=new Float64Array(t.v.length).fill(NaN);t.v.forEach((n,i)=>{if(n.real&&s.has(n.id)){let h=s.get(n.id);o[i]=Pt(c,h.x,h.y).x}});for(let[,n]of t.chains){if(!n.length)continue;let i=t.v[n[0]].up[0]?.n,h=t.v[n[n.length-1]].down[0]?.n;i==null||h==null||Number.isNaN(o[i])||Number.isNaN(o[h])||n.forEach((a,u)=>{o[a]=o[i]+(o[h]-o[i])*(u+1)/(n.length+1)})}return r.map(n=>{let i=new Map(n.map((h,a)=>[h,a]));return n.slice().sort((h,a)=>{let u=o[h],p=o[a];return Number.isNaN(u)&&Number.isNaN(p)?i.get(h)-i.get(a):Number.isNaN(u)?1:Number.isNaN(p)?-1:u-p})})}function Hn(t){let s=new Map(t.nodes.map(i=>[i.id,i.id])),c=i=>{for(;s.get(i)!==i;)s.set(i,s.get(s.get(i))),i=s.get(i);return i},r=(i,h)=>{let a=c(i),u=c(h);a!==u&&s.set(u,a)};for(let i of t.edges)r(i.source,i.target);let o=new Map;for(let i of t.nodes)i.group&&(o.has(i.group)?r(o.get(i.group),i.id):o.set(i.group,i.id));for(let i of t.constraints)if(i.type==="leftOf"&&r(i.a,i.b),i.type==="sameRank")for(let h of i.nodes)r(i.nodes[0],h);let n=new Map;for(let i of t.nodes){let h=c(i.id);n.has(h)||n.set(h,[]),n.get(h).push(i.id)}return[...n.values()].map(i=>({nodes:i,set:new Set(i)}))}function zn(t,s,c){let r=Jt(c),o=J(t),n=J(s),i=n.x-o.x,h=n.y-o.y,a=Math.abs(i)-(t.width+s.width)/2,u=Math.abs(h)-(t.height+s.height)/2,p=r.x!==0?i*r.x:h*r.y,g=r.x!==0?a:u;return p>0&&g>4?[r.exit,r.entry]:a>=u?i>=0?["right","left"]:["left","right"]:h>=0?["bottom","top"]:["top","bottom"]}function an(t,s){let c=t.options.direction,r=new Map,o=new Map;for(let a of t.nodes){let u=s.get(a.id);if(!u)continue;let p=lt(a),g=new Map;for(let[d,f]of p)g.set(d,{x:u.x+f.px*u.width,y:u.y+f.py*u.height,side:f.side,t:f.t});o.set(a.id,g)}let n=new Map,i=new Map;for(let a of t.edges){let u=s.get(a.source),p=s.get(a.target);if(!u||!p)continue;if(a.source===a.target){let l=o.get(a.source),m=a.sourcePort&&l.get(a.sourcePort),x=a.targetPort&&l.get(a.targetPort),M=Math.min(20,u.width/4,u.height/4);r.set(a.id,{source:m&&m.side?{x:m.x,y:m.y,side:m.side}:{x:u.x+u.width-M,y:u.y,side:"top"},target:x&&x.side?{x:x.x,y:x.y,side:x.side}:{x:u.x+u.width,y:u.y+M,side:"right"}});continue}let[g,d]=zn(u,p,c),f=a.sourcePort&&o.get(a.source).get(a.sourcePort),e=a.targetPort&&o.get(a.target).get(a.targetPort);f&&f.side&&(g=f.side),e&&e.side&&(d=e.side),i.set(a.id,[g,d]),f||cn(n,a.source+"|"+g,{edgeId:a.id,end:"source",other:a.target}),e||cn(n,a.target+"|"+d,{edgeId:a.id,end:"target",other:a.source}),r.set(a.id,{source:f?{x:f.x,y:f.y,side:f.side}:null,target:e?{x:e.x,y:e.y,side:e.side}:null})}for(let a=0;a<2;a++)for(let[u,p]of n){let[g,d]=u.split("|"),f=s.get(g),e=d==="top"||d==="bottom",l=x=>{let M=r.get(x.edgeId),w=x.end==="source"?M.target:M.source;if(a>0&&w)return e?w.x:w.y;let y=J(s.get(x.other));return e?y.x:y.y};p.sort((x,M)=>l(x)-l(M)||(x.edgeId<M.edgeId?-1:1));let m=[...o.get(g)?.values()||[]].filter(x=>x.side===d).map(x=>x.t);p.forEach((x,M)=>{let w=(M+1)/(p.length+1);for(let b of m)Math.abs(b-w)<.06&&(w=Math.min(.95,w+.1));let y=e?{x:f.x+w*f.width,y:d==="top"?f.y:f.y+f.height,side:d}:{x:d==="left"?f.x:f.x+f.width,y:f.y+w*f.height,side:d};r.get(x.edgeId)[x.end]=y})}let h=a=>{a&&(a.x=Math.round(a.x*100)/100,a.y=Math.round(a.y*100)/100)};for(let a of r.values())h(a.source),h(a.target);return{ends:r,ports:o,sides:i}}function cn(t,s,c){t.has(s)||t.set(s,[]),t.get(s).push(c)}function ln(t,s,c){let r=c.spacing,o={h:new Map,v:new Map},n=new Map;for(let[g,d]of t)n.set(g,d.points.map(f=>({x:f.x,y:f.y})));for(let[g,d]of t){if(d.kind!=="orthogonal")continue;let f=d.points;for(let e=0;e<f.length-1;e++){if(c.fixedEnds!==!1&&(e===0||e===f.length-2))continue;let l=f[e],m=f[e+1],x=Math.abs(l.x-m.x)<.01,M=Math.abs(l.y-m.y)<.01;if(!x&&!M)continue;let w=x?l.x:l.y,y=x?Math.min(l.y,m.y):Math.min(l.x,m.x),b=x?Math.max(l.y,m.y):Math.max(l.x,m.x);if(b-y<.5)continue;let k=x?l.y<=m.y:l.x<=m.x,P=f[e-1],L=f[e+2],R=(X,G)=>X?Math.sign(x?X.x-G.x:X.y-G.y):0,A=R(P,l),$=R(L,m),z={id:g,i:e,c:w,lo:y,hi:b,vertical:x,loIsA:k,pts:n.get(g),dirLo:k?A:$,dirHi:k?$:A},v=Math.round(w*100),N=x?o.v:o.h;N.has(v)||N.set(v,[]),N.get(v).push(z)}}let i=[...o.v.values()].flat(),h=[...o.h.values()].flat(),a=[];for(let g of[!0,!1])for(let d of(g?o.v:o.h).values()){if(d.length<2)continue;d.sort((m,x)=>m.lo-x.lo);let f=[d[0]],e=d[0].hi,l=()=>{f.length>1&&u(f,g)};for(let m=1;m<d.length;m++){let x=d[m];x.lo<e-.5?(f.push(x),e=Math.max(e,x.hi)):(l(),f=[x],e=x.hi)}l()}function u(g,d){if(new Set(g.map(k=>k.id)).size<2)return;let f=[];for(let k of g){let P=f.length;for(;P>0&&Fn(k,f[P-1])<0;)P--;f.splice(P,0,k)}let e=g[0].c,l=Math.min(...g.map(k=>k.lo)),m=Math.max(...g.map(k=>k.hi)),x=1/0,M=1/0;for(let k of s.values()){let P=d?k.y:k.x;if((d?k.y+k.height:k.x+k.width)<=l||P>=m)continue;let R=d?k.x:k.y,A=d?k.x+k.width:k.y+k.height;A<=e+.01?x=Math.min(x,e-A):R>=e-.01&&(M=Math.min(M,R-e))}for(let k of d?i:h){if(k.c===e||k.hi<=l||k.lo>=m)continue;let P=Math.abs(k.c-e)/2;k.c<e?x=Math.min(x,P+4):M=Math.min(M,P+4)}let w=f.length,y=Math.max(0,Math.min(x,M)-4),b=Math.min(r,w>1?2*y/(w-1):r);f.forEach((k,P)=>{let L=(P-(w-1)/2)*b;Math.abs(L)>.01&&a.push([k.id,k.i,d,L])})}let p=new Map;for(let[g,d,f,e]of a)p.has(g)||p.set(g,new Map),p.get(g).set(d,f?{x:e,y:0}:{x:0,y:e});for(let[g,d]of p){let f=t.get(g),e=f.points,l=[],m={x:0,y:0};for(let x=0;x<e.length;x++){let M=x>0&&d.get(x-1)||m,w=x<e.length-1&&d.get(x)||m,y=x>0&&x<e.length-1&&Cn(e[x-1],e[x],e[x+1]);y&&(M.x!==w.x||M.y!==w.y)?(l.push({x:e[x].x+M.x,y:e[x].y+M.y}),l.push({x:e[x].x+w.x,y:e[x].y+w.y})):l.push({x:e[x].x+M.x+(y?0:w.x),y:e[x].y+M.y+(y?0:w.y)})}f.points=jn(l)}}function Cn(t,s,c){return Math.abs(t.x-s.x)<.01&&Math.abs(s.x-c.x)<.01||Math.abs(t.y-s.y)<.01&&Math.abs(s.y-c.y)<.01}function jn(t){let s=[];for(let c of t){let r=s[s.length-1];r&&Math.abs(r.x-c.x)<.01&&Math.abs(r.y-c.y)<.01||s.push(c)}return s}function Fn(t,s){return hn(t,s,!0)||hn(t,s,!1)||Gn(t,s)}function fn(t,s){let{pts:c,i:r,loIsA:o}=t,n=[];if(s?!o:o)for(let h=r+1;h<c.length;h++)n.push(c[h]);else for(let h=r;h>=0;h--)n.push(c[h]);return n}var Dn=(t,s)=>t.x*s.y-t.y*s.x,un=(t,s)=>{let c=s.x-t.x,r=s.y-t.y,o=Math.hypot(c,r)||1;return{x:c/o,y:r/o}};function hn(t,s,c){let r=t.vertical,o=fn(t,c),n=fn(s,c),i=c?Math.max(t.lo,s.lo):Math.min(t.hi,s.hi),h=r?{x:t.c,y:i}:{x:i,y:t.c},a=r?{x:0,y:c?-1:1}:{x:c?-1:1,y:0},u=a,p=0,g=0,d=(e,l)=>{if(e===l)return 0;let m={x:a.y,y:-a.x},x=r?m.x:m.y;return(e<l?x<0:x>0)?-1:1},f=(e,l)=>l+1<e.length?Math.sign(Math.round(Dn(u,un(e[l],e[l+1]))*1e3)):null;for(let e=0;e<64;e++){let l=p<o.length?(o[p].x-h.x)*u.x+(o[p].y-h.y)*u.y:1/0,m=g<n.length?(n[g].x-h.x)*u.x+(n[g].y-h.y)*u.y:1/0;if(l===1/0&&m===1/0)return 0;if(Math.abs(l-m)<.5){let M=f(o,p),w=f(n,g);if(M===null||w===null)return M===null&&w===null?0:d(M??0,w??0);if(M!==w)return d(M,w);h=o[p],u=un(o[p],o[p+1]),p++,g++;continue}if(l<m){let M=f(o,p);return M?d(M,0):0}let x=f(n,g);return x?d(0,x):0}return 0}var Gn=(t,s)=>t.id<s.id?-1:t.id>s.id?1:t.i-s.i;function dn(t,s,c=4){let r=[],o=new Map(s.map((a,u)=>[a,u]));for(let a of s){let u=t.get(a).points;for(let p=0;p<u.length-1;p++){let g=u[p],d=u[p+1];Math.abs(g.x-d.x)<.01&&Math.abs(g.y-d.y)>.01&&r.push([o.get(a),g.x,Math.min(g.y,d.y),Math.max(g.y,d.y)])}}let n=64,i=new Map;for(let a of r){let u=Math.floor(a[1]/n);i.has(u)||i.set(u,[]),i.get(u).push(a)}let h=new Map;for(let a of s){let u=o.get(a),p=t.get(a).points,g=[];for(let d=0;d<p.length-1;d++){let f=p[d],e=p[d+1];if(Math.abs(f.y-e.y)>.01)continue;let l=Math.min(f.x,e.x)+c*2,m=Math.max(f.x,e.x)-c*2;if(!(m<=l))for(let x=Math.floor(l/n);x<=Math.floor(m/n);x++)for(let M of i.get(x)||[])M[0]>=u||M[1]<=l||M[1]>=m||f.y<=M[2]+c||f.y>=M[3]-c||g.push({seg:d,x:M[1],y:f.y})}g.length&&h.set(a,g)}return h}var Et=1,Un=[1,-1,0,0],Yn=[0,0,1,-1],Ot=[1,0,3,2],pn=t=>t.x>0?0:t.x<0?1:t.y>0?2:3;function gn(t,s,c={}){let r=t.options,o=s.nodes,n=r.edgeRouting,{ends:i,ports:h}=an(t,o),a=new Map,u=new Map,p=c.only||null,g=c.prev||null;if(n==="orthogonal")_n(t,o,i,r,p,g,a,u),ln(a,o,{spacing:r.edgeSpacing,fixedEnds:!0});else for(let e of t.edges){let l=o.get(e.source),m=o.get(e.target);if(!l||!m)continue;if(e.source===e.target){a.set(e.id,yn(l,r,i.get(e.id)));continue}let x=s.edges.get(e.id),M=x&&x.waypoints||[],w=i.get(e.id),y,b;n==="curved"||e.sourcePort?y=w.source:y=It(l,M[0]||J(m)),n==="curved"||e.targetPort?b=w.target:b=It(m,M[M.length-1]||J(l)),a.set(e.id,{points:[y,...M.map(k=>({...k})),b],kind:n,sourceSide:y.side,targetSide:b.side})}let d=t.edges.map(e=>e.id).filter(e=>a.has(e)),f=r.lineHops&&n==="orthogonal"?dn(a,d,r.hopRadius):new Map;for(let[e,l]of a)l.hops=f.get(e)||[];return{paths:a,raw:u,ports:h,mode:n}}function yn(t,s,c){let r=Math.max(s.nodeMargin*1.5,16),o=c.source,n=c.target,i=ct[o.side],h=ct[n.side],a={x:o.x+i.x*r,y:o.y+i.y*r},u={x:n.x+h.x*r,y:n.y+h.y*r},p;if(o.side===n.side)p=o.side==="left"||o.side==="right"?[a,{x:a.x,y:u.y}]:[a,{x:u.x,y:a.y}];else if((o.side==="top"||o.side==="bottom")!=(n.side==="top"||n.side==="bottom"))p=o.side==="top"||o.side==="bottom"?[a,{x:u.x,y:a.y}]:[a,{x:a.x,y:u.y}];else{let g=o.side==="top"||o.side==="bottom",d=g?t.x+t.width+r:t.y+t.height+r;p=g?[a,{x:d,y:a.y},{x:d,y:u.y}]:[a,{x:a.x,y:d},{x:u.x,y:d}]}return{points:St([o,...p,u,n]),kind:"orthogonal",sourceSide:o.side,targetSide:n.side,selfLoop:!0}}function _n(t,s,c,r,o,n,i,h){let a=r.nodeMargin,u=[];for(let[e,l]of s)u.push({id:e,...Qt(l,a)});let p=new Map;for(let e of t.edges){let l=c.get(e.id);if(!l||!l.source||!l.target)continue;let m=ct[l.source.side],x=ct[l.target.side];p.set(e.id,{s:{x:l.source.x+m.x*a,y:l.source.y+m.y*a},t:{x:l.target.x+x.x*a,y:l.target.y+x.y*a},sDir:pn(m),tNeed:Ot[pn(x)]})}let g=Wn(u,p,a);for(let e of t.edges)if(o&&!o.has(e.id)&&n&&n.raw.has(e.id)){let l=n.raw.get(e.id);h.set(e.id,l),g.markPath(l);let m=n.paths.get(e.id);m&&i.set(e.id,{...m,points:l.map(x=>({...x}))})}let d=t.edges.filter(e=>!i.has(e.id)&&s.has(e.source)&&s.has(e.target)),f=e=>{let l=p.get(e.id);return l?Math.abs(l.s.x-l.t.x)+Math.abs(l.s.y-l.t.y):0};d.sort((e,l)=>f(e)-f(l));for(let e of d){if(e.source===e.target){let w=yn(s.get(e.source),r,c.get(e.id));i.set(e.id,w),h.set(e.id,w.points);continue}let l=c.get(e.id),m=p.get(e.id),x=g.astar(m.s,m.sDir,m.t,m.tNeed,r);x||(x=Vn(m.s,m.t,l.source.side,l.target.side));let M=[l.source,...St(x),l.target];g.markPath(M),h.set(e.id,M),i.set(e.id,{points:M.map(w=>({...w})),kind:"orthogonal",sourceSide:l.source.side,targetSide:l.target.side})}}function Vn(t,s,c,r){let o=c==="top"||c==="bottom",n=r==="top"||r==="bottom";if(o&&n){let i=(t.y+s.y)/2;return[t,{x:t.x,y:i},{x:s.x,y:i},s]}if(!o&&!n){let i=(t.x+s.x)/2;return[t,{x:i,y:t.y},{x:i,y:s.y},s]}return o?[t,{x:t.x,y:s.y},s]:[t,{x:s.x,y:t.y},s]}function Wn(t,s,c){let r=new Set,o=new Set,n=I=>Math.round(I*100)/100,i=1/0,h=1/0,a=-1/0,u=-1/0;for(let I of t)r.add(n(I.x)),r.add(n(I.x+I.width)),o.add(n(I.y)),o.add(n(I.y+I.height)),i=Math.min(i,I.x),h=Math.min(h,I.y),a=Math.max(a,I.x+I.width),u=Math.max(u,I.y+I.height);for(let I of s.values())for(let S of[I.s,I.t])r.add(n(S.x)),o.add(n(S.y)),i=Math.min(i,S.x),h=Math.min(h,S.y),a=Math.max(a,S.x),u=Math.max(u,S.y);r.add(n(i-2*c)),r.add(n(a+2*c)),o.add(n(h-2*c)),o.add(n(u+2*c));let p=I=>{let S=[...I].sort((O,U)=>O-U),E=[];for(let O=0;O<S.length;O++)E.push(S[O]),O+1<S.length&&S[O+1]-S[O]>4&&E.push(n((S[O]+S[O+1])/2));return E},g=p(r),d=p(o),f=g.length,e=d.length,l=f*e,m=new Map(g.map((I,S)=>[I,S])),x=new Map(d.map((I,S)=>[I,S])),M=120,w=new Map,y=(I,S)=>I*73856093^S*19349663;for(let I of t)for(let S=Math.floor(I.x/M);S<=Math.floor((I.x+I.width)/M);S++)for(let E=Math.floor(I.y/M);E<=Math.floor((I.y+I.height)/M);E++){let O=y(S,E);w.has(O)||w.set(O,[]),w.get(O).push(I)}let b=(I,S)=>{let E=w.get(y(Math.floor(I/M),Math.floor(S/M)));if(!E)return!1;for(let O of E)if(qt(O,I,S,.01))return!0;return!1},k=l<=4e6?new Uint8Array(l):null,P=k?null:new Map,L=I=>{if(k){let E=k[I];return E||(E=b(g[I%f],d[I/f|0])?2:1,k[I]=E),E===2}let S=P.get(I);return S===void 0&&(S=b(g[I%f],d[I/f|0]),P.set(I,S)),S},R=new Uint8Array(l),A=new Uint8Array(l),$=(I,S)=>{let E=S?R:A,O=E[I];if(!O){let U=I%f,Y=I/f|0,T=S?(g[U]+g[U+1])/2:g[U],j=S?d[Y]:(d[Y]+d[Y+1])/2;O=b(T,j)?2:1,E[I]=O}return O===2},z=new Uint16Array(l),v=new Uint16Array(l),N=new Uint16Array(l),X=new Uint16Array(l),G=I=>{let S=m.get(n(I.x)),E=x.get(n(I.y));return S==null||E==null?-1:E*f+S};function V(I){for(let S=0;S<I.length-1;S++){let E=I[S],O=I[S+1],U=Math.abs(E.y-O.y)<.01,Y=Math.abs(E.x-O.x)<.01;if(U){let T=x.get(n(E.y)),j=m.get(n(E.x)),D=m.get(n(O.x));if(T==null||j==null||D==null)continue;let q=Math.min(j,D),tt=Math.max(j,D);for(let C=q;C<=tt;C++)z[T*f+C]++,C<tt&&N[T*f+C]++}else if(Y){let T=m.get(n(E.x)),j=x.get(n(E.y)),D=x.get(n(O.y));if(T==null||j==null||D==null)continue;let q=Math.min(j,D),tt=Math.max(j,D);for(let C=q;C<=tt;C++)v[C*f+T]++,C<tt&&X[C*f+T]++}}}let Q=l*4,W=Q<=16e6,At=W?new Float64Array(Q):null,Bt=W?new Int32Array(Q):null,$t=W?new Uint32Array(Q):null,dt=0;function xn(I,S,E,O,U){let Y=G(I),T=G(E);if(Y<0||T<0)return null;let j=g[T%f],D=d[T/f|0],q=U.bendPenalty,tt=U.crossingPenalty;dt++;let C=W?null:new Map,Xt=W?null:new Map,Tt=W?B=>$t[B]===dt?At[B]:void 0:B=>C.get(B),Ht=W?(B,F,K)=>{$t[B]=dt,At[B]=F,Bt[B]=K}:(B,F,K)=>{C.set(B,F),Xt.set(B,K)},mn=W?B=>Bt[B]:B=>Xt.get(B),ot=new Lt,zt=Y*4+S;Ht(zt,0,-1),ot.push(zt,Et*(Math.abs(g[Y%f]-j)+Math.abs(d[Y/f|0]-D)));let pt=1/0,gt=-1,wn=0,Mn=4e5;for(;ot.size;){let B=ot.peekKey(),F=ot.pop();if(B>=pt)break;let K=Tt(F),nt=F>>2,at=F&3,xt=nt%f,mt=nt/f|0;if(!(B>K+Et*(Math.abs(g[xt]-j)+Math.abs(d[mt]-D))+1e-6)){if(++wn>Mn)break;if(nt===T){let H=at===O?0:at===Ot[O]?2*q:q;K+H<pt&&(pt=K+H,gt=F);continue}for(let H=0;H<4;H++){if(H===Ot[at])continue;let st=xt+Un[H],it=mt+Yn[H];if(st<0||it<0||st>=f||it>=e)continue;let _=it*f+st;if(_!==T&&L(_))continue;let rt=H<2;if($(rt?H===0?nt:_:H===2?nt:_,rt))continue;let Ct=Math.abs(rt?g[st]-g[xt]:d[it]-d[mt]),ft=Ct;H!==at&&(ft+=q);let jt=H===0||H===2?nt:_,Ft=rt?N[jt]:X[jt];Ft&&(ft+=Ct*.25*Ft),_!==T&&(rt?v[_]:z[_])&&(ft+=tt);let wt=_*4+H,Mt=K+ft,Dt=Tt(wt);(Dt===void 0||Mt<Dt-1e-9)&&(Ht(wt,Mt,F),ot.push(wt,Mt+Et*(Math.abs(g[st]-j)+Math.abs(d[it]-D))))}}}if(gt<0)return null;let yt=[];for(let B=gt;B!==-1&&B!==void 0;B=mn(B)){let F=B>>2;yt.push({x:g[F%f],y:d[F/f|0]})}return yt.reverse(),yt}return{astar:xn,markPath:V,xs:g,ys:d,N:l}}var Lt=class{constructor(){this.k=[],this.v=[]}get size(){return this.k.length}push(s,c){let r=this.k,o=this.v,n=r.length;for(r.push(c),o.push(s);n>0;){let i=n-1>>1;if(r[i]<=c)break;r[n]=r[i],o[n]=o[i],n=i}r[n]=c,o[n]=s}peekKey(){return this.k[0]}pop(){let s=this.k,c=this.v,r=c[0],o=s.pop(),n=c.pop();if(s.length){let i=0,h=s.length;for(;;){let a=2*i+1;if(a>=h||(a+1<h&&s[a+1]<s[a]&&a++,s[a]>=o))break;s[i]=s[a],c[i]=c[a],i=a}s[i]=o,c[i]=n}return r}};self.onmessage=t=>{let{seq:s,data:c,options:r,hints:o}=t.data;try{let n=Ut(c,r),i=on(n,{hints:o||null}),h=gn(n,i);self.postMessage({seq:s,nodes:i.nodes,edges:i.edges,crossings:i.crossings,routing:{paths:h.paths,raw:h.raw,ports:h.ports,mode:h.mode}})}catch(n){self.postMessage({seq:s,error:String(n&&n.message||n)})}};
|
|
1
|
+
/*! FlexGraph v1.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.
|
|
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,11 +115,44 @@ 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;
|
|
@@ -143,19 +184,30 @@ export interface GraphEvents {
|
|
|
143
184
|
nodeclick: { node: NodeSpec; event: PointerEvent; previous: NodeSpec[]; next: NodeSpec[] };
|
|
144
185
|
edgeclick: { edge: EdgeSpec; event: PointerEvent };
|
|
145
186
|
groupclick: { group: GroupSpec; event: PointerEvent };
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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[] };
|
|
149
198
|
pin: { id: string; pinned: boolean };
|
|
150
199
|
change: ViewState;
|
|
151
200
|
viewport: { x: number; y: number; k: number };
|
|
152
201
|
animationend: void;
|
|
202
|
+
expand: { id: string; expanded: boolean; node: NodeSpec };
|
|
203
|
+
/** Explore mode: the open path changed. */
|
|
204
|
+
explore: { path: string[] };
|
|
153
205
|
/** Right-click anywhere in the graph. Registering a listener suppresses the browser menu inside the graph. */
|
|
154
206
|
contextmenu:
|
|
155
|
-
| { kind: 'node'; id: string; node: NodeSpec; previous: NodeSpec[]; next: NodeSpec[]; event: MouseEvent }
|
|
156
|
-
| { kind: 'edge'; id: string; edge: EdgeSpec; event: MouseEvent }
|
|
157
|
-
| { kind: 'group'; id: string; group: GroupSpec; event: MouseEvent }
|
|
158
|
-
| { kind: 'background'; event: MouseEvent };
|
|
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[] };
|
|
159
211
|
}
|
|
160
212
|
|
|
161
213
|
export interface Connections {
|
|
@@ -187,18 +239,51 @@ export interface GraphView {
|
|
|
187
239
|
pin(id: string, pinned?: boolean): void;
|
|
188
240
|
unpin(id: string): void;
|
|
189
241
|
unpinAll(): void;
|
|
190
|
-
|
|
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. */
|
|
191
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;
|
|
192
265
|
/** Previous / next nodes of a node (direct, or the whole chain with { chain: true }). null if the id is unknown. */
|
|
193
266
|
getConnections(id: string, opts?: { chain?: boolean }): Connections | null;
|
|
194
267
|
fit(opts?: { padding?: number; maxZoom?: number }): void;
|
|
195
268
|
/**
|
|
196
269
|
* Zoom and pan so the whole flow through a node or edge (everything upstream and downstream) fills the view,
|
|
197
|
-
* as large as possible. Defaults to the selected node or edge
|
|
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.
|
|
198
272
|
*/
|
|
199
273
|
fitFlow(target?: string | Selection | EdgeSpec, opts?: FitOptions & { mode?: 'chain' | 'neighbors' }): boolean;
|
|
200
274
|
/** Zoom and pan so the given nodes and the edges between them fill the view, as large as possible. */
|
|
201
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>;
|
|
202
287
|
zoomBy(factor: number): void;
|
|
203
288
|
zoomTo(k: number): void;
|
|
204
289
|
zoomAt(k: number, clientX: number, clientY: number): void;
|
|
@@ -212,7 +297,7 @@ export interface GraphView {
|
|
|
212
297
|
|
|
213
298
|
export function createGraph(container: HTMLElement | string, data: GraphData, options?: Partial<GraphOptions>): GraphView;
|
|
214
299
|
|
|
215
|
-
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; }
|
|
216
301
|
export interface LayoutResult {
|
|
217
302
|
nodes: Map<string, Rect & { rank: number; order: number }>;
|
|
218
303
|
edges: Map<string, { waypoints: Point[]; reversed: boolean; selfLoop: boolean; flat: boolean }>;
|