{"version":3,"sources":["jsdelivr-header.js","/npm/netviz@0.1.1/node_modules/force-in-a-box/dist/forceInABox.esm.js","/npm/netviz@0.1.1/node_modules/d3-force-boundary/dist/d3-force-boundary.esm.js","/npm/netviz@0.1.1/src/forces/forceTransport.js","/npm/netviz@0.1.1/src/forces/forceExtent.js","/npm/netviz@0.1.1/src/forces/edgeBundling.js","/npm/netviz@0.1.1/src/utils/sample.js","/npm/netviz@0.1.1/src/utils/drag.js","/npm/netviz@0.1.1/src/utils/computeAutoFit.js","/npm/netviz@0.1.1/src/utils/applyTransform.js","/npm/netviz@0.1.1/node_modules/smart-labels/dist/smartLabels.es.js","/npm/netviz@0.1.1/src/renderers/renderCanvas.js","/npm/netviz@0.1.1/src/renderers/renderSVG.js","/npm/netviz@0.1.1/src/defaults.js","/npm/netviz@0.1.1/src/forceGraph.js","/npm/netviz@0.1.1/src/utils/filterNetwork.js","/npm/netviz@0.1.1/src/utils/nodesFromLinks.js","/npm/netviz@0.1.1/src/utils/mapProperties.js","/npm/netviz@0.1.1/src/utils/resolveIndexLinks.js","/npm/netviz@0.1.1/src/utils/computeNodeGroups.js","/npm/netviz@0.1.1/src/utils/prepareNetwork.js","/npm/netviz@0.1.1/src/index.js"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA,2WCHA,SAAS,cAEP,SAAS,EAAS,GAChB,MAAO,IAAM,CACf,CAMA,IAGE,EAaA,EAhBE,EAJJ,SAAe,GACb,OAAO,EAAE,KACX,EAGE,EAAQ,GACR,EAAQ,GAER,EAAO,CAAC,IAAK,KACb,EAAgB,EAAS,GACzB,EAAc,GAAS,GACvB,EAAoB,EAAS,KAC7B,EAAoB,EAAS,IAC7B,EAAO,GAEP,EAA2B,GAC3B,EAA2B,KAE3B,EAAgB,GAChB,EAAS,CAAC,EAAG,GAEb,EAAU,SAAU,GAClB,OAAO,EAAE,OACX,EACA,EAAW,UACX,GAAiB,EACjB,EAAW,GAGb,SAAS,EAAM,GACb,IAAK,EACH,OAAO,EAEQ,UAAb,IAEF,EAAc,OACd,KAGF,IAAK,IAA6B,EAAzB,EAAI,EAAG,EAAI,EAAM,OAAc,EAAI,EAAQ,EAAU,EAAI,IAAK,EACrE,EAAO,EAAM,GACb,EAAK,KAAO,EAAK,EAAQ,IAAO,EAAI,EAAK,GAAK,EAC9C,EAAK,KAAO,EAAK,EAAQ,IAAO,EAAI,EAAK,GAAK,CAElD,CAEA,SAAS,IACF,IAQY,YAAb,EAwJN,WACE,IAAI,EAAU,cAAG,UAAU,KAAK,EAAM,QAEtC,EAAO,cACJ,UAtCL,WACE,IACE,EACA,EACA,EAHE,EAAW,GAOf,IAAK,KAFL,EAAiB,EAA0B,EAAM,SAEvC,EAAe,QACvB,EAAK,EAAe,IAAI,GACxB,EAAS,KAAK,CAAE,GAAI,EAAG,KAAM,EAAG,QAElC,MAAO,CAAE,GAAI,eAAgB,SAAU,EACzC,CAyBe,IACV,KAAI,SAAU,GACb,OAAO,EAAE,IACX,IACC,MAAK,SAAU,EAAG,GACjB,OAAO,EAAE,OAAS,EAAE,QAAU,EAAE,MAAQ,EAAE,KAC5C,IAEF,EAAgB,EAAQ,GAAM,SAC9B,GACF,CArKI,GA+LJ,WACE,IAAI,EAEJ,IAAK,IAAU,EAAM,OACnB,OAGF,GAAI,GAAS,EAAM,OAAS,QACA,IAAtB,EAAQ,EAAM,IAChB,MAAM,MACJ,8IAlCR,WAEE,IAAI,EAAY,EAChB,GAAqB,IAAjB,EAAM,OAAc,OAExB,EAAM,SAAQ,SAAU,GACtB,IAAI,EAAQ,EACZ,GAAK,EAAL,CAKA,GAJA,EAAS,EAAK,OACd,EAAS,EAAK,OACa,iBAAhB,EAAK,SAAqB,EAAS,EAAM,EAAK,SAC9B,iBAAhB,EAAK,SAAqB,EAAS,EAAM,EAAK,cAC1C,IAAX,QAAmC,IAAX,EAE1B,MAAM,MACJ,8EAGJ,EAAK,OAAS,EACd,EAAK,OAAS,EACd,EAAK,MAAQ,GAbD,CAcd,GACF,EAiBE,GAEA,EApIF,WACE,IAKE,EACA,EACA,EACA,EACA,EATE,EAAS,GACX,EAAS,GAET,EAAS,IAAI,IAWf,IAAK,KAHL,EAAiB,EAA0B,GAC3C,EA7CF,SAAmC,GACjC,IAAI,EAAgB,IAAI,IACtB,EAAe,GA0BjB,OAxBA,EAAM,SAAQ,SAAU,GACtB,IACE,EADE,EAtCR,SAAoB,GAClB,IAAI,EAAW,EAAQ,EAAE,QACvB,EAAW,EAAQ,EAAE,QAEvB,OAAO,GAAY,EACf,EAAW,IAAM,EACjB,EAAW,IAAM,CACvB,CA+Bc,CAAW,GAGnB,EADE,EAAc,IAAI,GACZ,EAAc,IAAI,GAElB,EAEV,GAAS,EACT,EAAc,IAAI,EAAK,EACzB,IAEA,EAAc,SAAQ,SAAU,EAAO,GACrC,IAAI,EAAQ,EACZ,EAAS,EAAI,MAAM,KAAK,GACxB,EAAS,EAAI,MAAM,KAAK,QACT,IAAX,QAAmC,IAAX,GAC1B,EAAa,KAAK,CAChB,OAAQ,EACR,OAAQ,EACR,MAAO,GAGb,IACO,CACT,CAgBkB,CAA0B,GAEhC,EAAe,QACvB,EAAK,EAAe,IAAI,GACxB,EAAO,KAAK,CACV,GAAI,EACJ,KAAM,EAAG,MACT,EAAG,KAAK,KAAK,EAAG,iBAAmB,KAAK,MAE1C,EAAO,IAAI,EAAG,GAgBhB,OAZA,EAAc,SAAQ,SAAU,GAC9B,IAAI,EAAS,EAAO,IAAI,EAAE,QACxB,EAAS,EAAO,IAAI,EAAE,aACT,IAAX,QAAmC,IAAX,GAC1B,EAAO,KAAK,CACV,OAAQ,EACR,OAAQ,EACR,MAAO,EAAE,OAGf,IAEO,CAAE,MAAO,EAAQ,MAAO,EACjC,CA6FQ,GACN,EAAgB,cACb,gBAAgB,EAAI,OACpB,MAAM,IAAK,cAAG,OAAO,EAAK,GAAK,GAAG,SAAS,KAC3C,MAAM,IAAK,cAAG,OAAO,EAAK,GAAK,GAAG,SAAS,KAC3C,MACC,UACA,cACG,cAAa,SAAU,GACtB,OAAO,EAAE,CACX,IACC,WAAW,IAEf,MAAM,SAAU,cAAG,gBAAgB,SAAS,IAC5C,MACC,QACA,cACG,UAAU,EAAI,MAAM,OAAS,EAAI,MAAQ,IACzC,SAAS,GACT,SAAS,IAQhB,EAAgB,EAAc,QAE9B,GACF,CA5OI,GAEJ,CAgBA,SAAS,EAA0B,GACjC,IAAI,EAAiB,IAAI,IACvB,EAAW,GAkBb,OAhBA,EAAM,SAAQ,SAAU,GACjB,EAAe,IAAI,EAAQ,KAC9B,EAAe,IAAI,EAAQ,GAAI,CAAE,MAAO,EAAG,iBAAkB,GAEjE,IAEA,EAAM,SAAQ,SAAU,GAEtB,EAAW,EAAe,IAAI,EAAQ,IACtC,EAAS,MAAQ,EAAS,MAAQ,EAClC,EAAS,iBACP,EAAS,iBACT,KAAK,IAAM,EAAc,GAAK,EAAc,IAAM,IACpD,EAAe,IAAI,EAAQ,GAAI,EACjC,IAEO,CACT,CA2FA,SAAS,IAgBP,OAdA,EAAK,KAAO,CAAE,EAAG,EAAG,EAAG,GACvB,EAAc,SAAQ,SAAU,GACb,YAAb,EACF,EAAK,EAAE,KAAK,IAAM,CAChB,EAAG,EAAE,IAAM,EAAE,GAAK,EAAE,IAAM,EAAI,EAAO,GACrC,EAAG,EAAE,IAAM,EAAE,GAAK,EAAE,IAAM,EAAI,EAAO,IAGvC,EAAK,EAAE,IAAM,CACX,EAAG,EAAE,EAAI,EAAO,GAChB,EAAG,EAAE,EAAI,EAAO,GAGtB,IACO,CACT,CAmHA,SAAS,EAAU,GAEjB,EAAU,UAAU,aAAa,SACjC,IAAI,EAAmB,EACpB,UAAU,aACV,KAAK,EAAc,MAAM,SAAS,SACrC,EACG,QACA,OAAO,QACP,KAAK,QAAS,QACd,MAAM,GACN,KAAK,MAAM,SAAU,GACpB,OAAO,EAAE,OAAO,CAClB,IACC,KAAK,MAAM,SAAU,GACpB,OAAO,EAAE,OAAO,CAClB,IACC,KAAK,MAAM,SAAU,GACpB,OAAO,EAAE,OAAO,CAClB,IACC,KAAK,MAAM,SAAU,GACpB,OAAO,EAAE,OAAO,CAClB,IACC,MAAM,eAAgB,OACtB,MAAM,iBAAkB,OAE3B,IAAI,EAAmB,EACpB,UAAU,eACV,KAAK,EAAc,SACtB,EACG,QACA,OAAO,cACP,KAAK,QAAS,QACd,MAAM,GACN,KAAK,MAAM,SAAU,GACpB,OAAO,EAAE,CACX,IACC,KAAK,MAAM,SAAU,GACpB,OAAO,EAAE,CACX,IACC,KAAK,KAAK,SAAU,GACnB,OAAO,EAAE,CACX,IAEF,EACG,GAAG,QAAQ,KAEV,EAAU,EAAU,IAErB,UAEH,EAAiB,OAAO,SACxB,EAAiB,OAAO,QAC1B,CA8JA,OArdA,EAAM,WAAa,SAAU,GAC3B,EAAQ,EACR,GACF,EAsTA,EAAM,aAAe,SAAU,GAO7B,MALiB,YAAb,EAjFN,SAAqB,GAEnB,EAAU,UAAU,eAAe,SACnC,EAAU,UAAU,aAAa,SACjC,EACG,UAAU,aACV,KAAK,GACL,QACA,OAAO,YACP,KAAK,QAAS,QACd,KAAK,KAAK,SAAU,GACnB,OAAO,EAAE,EACX,IACC,KAAK,KAAK,SAAU,GACnB,OAAO,EAAE,EACX,IACC,KAAK,SAAS,SAAU,GACvB,OAAO,EAAE,GAAK,EAAE,EAClB,IACC,KAAK,UAAU,SAAU,GACxB,OAAO,EAAE,GAAK,EAAE,EAClB,GACJ,CA4DI,CAAY,GAEZ,EAAU,GAEL,CACT,EAGA,EAAM,YAAc,EAAM,aAE1B,EAAM,eAAiB,SAAU,GAQ/B,OANA,EAAU,UAAU,SAAS,SAEzB,GACF,EAAc,GAAG,OAAQ,MAAM,UAG1B,CACT,EAEA,EAAM,SAAW,SAAU,GACzB,OAAK,UAAU,QACf,EAAW,EACX,IACO,GAHuB,CAIhC,EAEA,EAAM,QAAU,SAAU,GACxB,OAAK,UAAU,OACE,iBAAN,GACT,EAAU,SAAU,GAClB,OAAO,EAAE,EACX,EACO,IAET,EAAU,EACH,GARuB,CAShC,EAEA,EAAM,eAAiB,SAAU,GAC/B,OAAK,UAAU,QACf,EAAiB,EAEV,GAHuB,CAIhC,EAEA,EAAM,SAAW,SAAU,GACzB,OAAK,UAAU,QACf,EAAW,EACJ,GAFuB,CAGhC,EAEA,EAAM,gBAAkB,SAAU,GAChC,OAAI,EACE,EAAQ,EAAE,UAAY,EAAQ,EAAE,QACM,mBAA7B,EACF,EAAyB,GAEzB,EAG+B,mBAA7B,EACF,EAAyB,GAEzB,EAK6B,mBAA7B,EACF,EAAyB,GAEzB,CAGb,EAEA,EAAM,GAAK,SAAU,GACnB,OAAO,UAAU,QAAW,EAAK,EAAI,GAAS,CAChD,EAEA,EAAM,KAAO,SAAU,GACrB,OAAO,UAAU,QAAW,EAAO,EAAI,GAAS,CAClD,EAEA,EAAM,yBAA2B,SAAU,GACzC,OAAO,UAAU,QACX,EAA2B,EAAI,GACjC,CACN,EAEA,EAAM,yBAA2B,SAAU,GACzC,OAAO,UAAU,QACX,EAA2B,EAAI,GACjC,CACN,EAEA,EAAM,MAAQ,SAAU,GACtB,OAAO,UAAU,QAAW,EAAQ,EAAI,GAAS,CACnD,EAEA,EAAM,MAAQ,SAAU,GACtB,OAAK,UAAU,QACC,EAAN,OAAN,EAAoB,GACX,EACb,IACO,GAJuB,CAKhC,EAEA,EAAM,cAAgB,SAAU,GAC9B,OAAO,UAAU,QACX,EAA6B,mBAAN,EAAmB,EAAI,GAAU,GAC1D,IACA,GACA,CACN,EAGA,EAAM,SAAW,EAAM,cAEvB,EAAM,YAAc,SAAU,GAC5B,OAAO,UAAU,QACX,EAA2B,mBAAN,EAAmB,EAAI,GAAU,GACxD,IACA,GACA,CACN,EAEA,EAAM,kBAAoB,SAAU,GAClC,OAAO,UAAU,QACX,EAAiC,mBAAN,EAAmB,EAAI,GAAU,GAC9D,IACA,GACA,CACN,EAEA,EAAM,kBAAoB,SAAU,GAClC,OAAO,UAAU,QACX,EAAiC,mBAAN,EAAmB,EAAI,GAAU,GAC9D,IACA,GACA,CACN,EAEA,EAAM,OAAS,SAAU,GACvB,OAAO,UAAU,QACX,EAAsB,mBAAN,EAAmB,EAAI,GAAU,GAAK,GACxD,CACN,EAEA,EAAM,SAAW,EAEV,CACT,CC5hBA,SAAS,SAAS,GAChB,OAAO,WACL,OAAO,CACT,CACF,CAEA,SAAS,cAAc,EAAI,EAAI,EAAI,GACjC,IAGI,EACA,EACA,EACA,EAAK,EACL,EAAK,EACL,EACA,EAAO,EATP,EAAW,SAAS,IACpB,GAAe,EACf,EAAS,SAAU,KAAK,KAAK,EAAK,GAAI,GAAI,EAAK,GAAI,IAcvD,SAAS,EAAM,EAAO,EAAG,EAAW,EAAQ,GAC1C,OAAQ,EAAQ,GAAM,KAAK,IAAI,EAAG,KAAK,IAAK,EAAQ,GAAK,GAAS,EAAY,CAChF,CAEA,SAAS,EAAM,GACb,IAAK,IAA6B,EAAzB,EAAI,EAAG,EAAI,EAAM,OAAc,EAAI,IAAK,GAC/C,EAAO,EAAM,IAEH,EAAK,EAAI,GAAK,EAAQ,IAAO,EAAK,EAAK,EAAI,GAAK,EAAQ,IAC/D,EAAK,EAAK,EAAI,GAAK,EAAQ,IAAO,EAAK,EAAK,EAAI,GAAK,EAAQ,IAC9D,EAAK,IAAM,EAAM,EAAM,GAAI,EAAK,EAAG,EAAW,GAAI,EAAQ,GAAI,GAC9D,EAAK,IAAM,EAAM,EAAM,GAAI,EAAK,EAAG,EAAW,GAAI,EAAQ,GAAI,IACrD,EAAK,EAAK,EAAI,GAAK,EAAQ,KAAO,EAAK,EAAK,EAAI,GAAK,EAAQ,IAEpE,IACE,EAAK,GAAK,EAAI,KAAI,EAAK,IAAM,EAAI,GAAK,EAAK,GAC3C,EAAK,GAAK,EAAI,KAAI,EAAK,IAAM,EAAI,GAAK,EAAK,GAC3C,EAAK,GAAK,EAAI,KAAI,EAAK,IAAM,EAAI,GAAK,EAAK,GAC3C,EAAK,GAAK,EAAI,KAAI,EAAK,IAAM,EAAI,GAAK,EAAK,GAGrD,CAEA,SAAS,IACP,GAAK,EAAL,CACA,IAAI,EAAG,EAAI,EAAM,OAWjB,IAVA,EAAa,IAAI,MAAM,GACvB,EAAa,IAAI,MAAM,GACvB,EAAM,IAAI,MAAM,GAChB,EAAM,IAAI,MAAM,GAChB,EAAM,IAAI,MAAM,GAChB,EAAM,IAAI,MAAM,GAChB,EAAQ,IAAI,MAAM,GAClB,EAAQ,IAAI,MAAM,GAClB,EAAU,IAAI,MAAM,GAEf,EAAI,EAAG,EAAI,IAAK,EACnB,EAAW,GAAM,MAAM,EAAI,IAAM,EAAG,EAAM,GAAI,EAAG,KAC/C,MAAM,EAAI,IAAM,EAAG,EAAM,GAAI,EAAG,IAAW,GAAK,EAAS,EAAM,GAAI,EAAG,GACxE,EAAW,GAAM,MAAM,EAAI,IAAM,EAAG,EAAM,GAAI,EAAG,KAC/C,MAAM,EAAI,IAAM,EAAG,EAAM,GAAI,EAAG,IAAW,GAAK,EAAS,EAAM,GAAI,EAAG,GACxE,EAAM,GAAK,EAAI,IAAM,EAAI,GAAK,EAAI,IAAI,EACtC,EAAM,GAAK,EAAI,IAAM,EAAI,GAAK,EAAI,IAAI,EACtC,EAAQ,IAAM,EAAO,EAAM,GAAI,EAAG,EAnBxB,CAqBd,CAmCA,MArFkB,mBAAP,IAAmB,EAAK,SAAe,MAAN,GAAa,KAAQ,IAC/C,mBAAP,IAAmB,EAAK,SAAe,MAAN,EAAa,KAAO,IAC9C,mBAAP,IAAmB,EAAK,SAAe,MAAN,GAAa,KAAQ,IAC/C,mBAAP,IAAmB,EAAK,SAAe,MAAN,EAAa,KAAO,IAiDhE,EAAM,WAAa,SAAS,GAC1B,EAAQ,EACR,GACF,EAEA,EAAM,GAAK,SAAS,GAClB,OAAO,UAAU,QAAU,EAAkB,mBAAN,EAAmB,EAAI,UAAU,GAAI,IAAc,GAAS,CACrG,EAEA,EAAM,GAAK,SAAS,GAClB,OAAO,UAAU,QAAU,EAAkB,mBAAN,EAAmB,EAAI,UAAU,GAAI,IAAc,GAAS,CACrG,EAEA,EAAM,GAAK,SAAS,GAClB,OAAO,UAAU,QAAU,EAAkB,mBAAN,EAAmB,EAAI,UAAU,GAAI,IAAc,GAAS,CACrG,EAEA,EAAM,GAAK,SAAS,GAClB,OAAO,UAAU,QAAU,EAAkB,mBAAN,EAAmB,EAAI,UAAU,GAAI,IAAc,GAAS,CACrG,EAEA,EAAM,SAAW,SAAS,GACxB,OAAO,UAAU,QAAU,EAAwB,mBAAN,EAAmB,EAAI,UAAU,GAAI,IAAc,GAAS,CAC3G,EAEA,EAAM,OAAS,SAAS,GACtB,OAAO,UAAU,QAAU,EAAsB,mBAAN,EAAmB,EAAI,UAAU,GAAI,IAAc,GAAS,CACzG,EAEA,EAAM,aAAe,SAAS,GAC5B,OAAO,UAAU,QAAU,EAAe,EAAG,GAAS,CACxD,EAEO,CACT,CC3FO,SAAS,eAAe,EAAQ,EAAQ,GAC7C,IAAI,OAEW,IAAX,IACF,EAAS,CACP,CAAC,EAAG,GACJ,CAAC,IAAK,YAEK,IAAX,IAAsB,EAAS,QAClB,IAAb,IAAwB,EAAW,GAEvC,MAAM,EAAI,cACP,cACA,MAAM,CAAC,EAAO,GAAG,GAAK,EAAQ,EAAO,GAAG,GAAK,IAC1C,EAAI,cACP,cACA,MAAM,CAAC,EAAO,GAAG,GAAK,EAAQ,EAAO,GAAG,GAAK,IAEhD,IAAI,EAAU,GAEd,SAAS,EAAM,GACT,EAAQ,SAAW,EAAM,SAC3B,EAAU,YAAY,KAAK,cAAG,MAAM,EAAM,SAC1C,EAAE,OAAO,EAAC,EAAI,EAAM,SACpB,EAAE,OAAO,EAAC,EAAI,EAAM,UAItB,EAAQ,MAAK,CAAC,EAAG,IAAM,EAAM,GAAG,EAAI,EAAM,GAAG,IAC7C,IAAK,IAAI,EAAI,EAAG,EAAI,EAAM,SAAU,EAAG,CACrC,MAAM,EAAO,EAAM,EAAQ,IACrB,EAAS,EAAE,GACjB,EAAK,KAAO,EAAS,EAAK,GAAK,CACjC,CAGA,EAAQ,MAAK,CAAC,EAAG,IAAM,EAAM,GAAG,EAAI,EAAM,GAAG,IAC7C,IAAK,IAAI,EAAI,EAAG,EAAI,EAAM,SAAU,EAAG,CACrC,MAAM,EAAO,EAAM,EAAQ,IACrB,EAAS,EAAE,GACjB,EAAK,KAAO,EAAS,EAAK,GAAK,EAAW,CAC5C,CACF,CAkBA,OAhBA,EAAM,WAAa,SAAU,GAC3B,EAAQ,CACV,EAEA,EAAM,OAAS,SAAU,GACvB,OAAO,UAAU,QAAW,EAAS,EAAI,GAAS,CACpD,EAEA,EAAM,OAAS,SAAU,GACvB,OAAO,UAAU,QAAW,GAAU,EAAI,GAAS,CACrD,EAEA,EAAM,SAAW,SAAU,GACzB,OAAO,UAAU,QAAW,GAAY,EAAI,GAAS,CACvD,EAEO,CACT,CClEO,SAAS,YAAY,GAC1B,IAAI,EAQJ,SAAS,EAAM,EAAG,EAAK,GACrB,OAAO,KAAK,IAAI,EAAK,KAAK,IAAI,EAAK,GACrC,CAEA,SAAS,IACP,IAAK,IAAI,EAAI,EAAG,EAAI,EAAM,SAAU,EAAG,CACrC,MAAM,EAAO,EAAM,GACb,EAAI,EAAK,QAAU,EACzB,EAAK,EAAI,EAAM,EAAK,EAAG,EAAO,GAAG,GAAK,EAAG,EAAO,GAAG,GAAK,GACxD,EAAK,EAAI,EAAM,EAAK,EAAG,EAAO,GAAG,GAAK,EAAG,EAAO,GAAG,GAAK,EAC1D,CACF,CAUA,YA3Be,IAAX,IACF,EAAS,CACP,CAAC,EAAG,GACJ,CAAC,IAAK,OAgBV,EAAM,WAAa,SAAU,GAC3B,EAAQ,CACV,EAEA,EAAM,OAAS,SAAU,GACvB,OAAO,UAAU,QAAW,EAAS,EAAI,GAAS,CACpD,EAEO,CACT,CClBO,SAAS,oBACd,IAAI,EAAa,GACf,EAAa,GACb,EAA8B,GAC9B,EAA8B,GAC9B,EAAI,GACJ,EAAY,GAEZ,EAAS,EACT,EAAI,EACJ,EAAY,GACZ,EAAS,SACT,EAA0B,GAC1B,EAAM,KACN,EAAI,KAON,SAAS,EAAe,GACtB,MAAO,CACL,EAAG,EAAW,EAAE,QAAQ,EAAI,EAAW,EAAE,QAAQ,EACjD,EAAG,EAAW,EAAE,QAAQ,EAAI,EAAW,EAAE,QAAQ,EAErD,CAEA,SAAS,EAAY,GAEnB,OACE,KAAK,IAAI,EAAW,EAAE,QAAQ,EAAI,EAAW,EAAE,QAAQ,GAAK,GAC5D,KAAK,IAAI,EAAW,EAAE,QAAQ,EAAI,EAAW,EAAE,QAAQ,GAAK,EAErD,EAGF,KAAK,KACV,KAAK,IAAI,EAAW,EAAE,QAAQ,EAAI,EAAW,EAAE,QAAQ,EAAG,GACxD,KAAK,IAAI,EAAW,EAAE,QAAQ,EAAI,EAAW,EAAE,QAAQ,EAAG,GAEhE,CAmBA,SAAS,EAA4B,GACnC,IAAI,EAAS,EAEb,IAAK,IAAI,EAAI,EAAG,EAAI,EAA4B,GAAO,OAAQ,IAAK,CAKlE,GAJqB,EACnB,EAA4B,GAAO,GACnC,EAA4B,GAAO,EAAI,GAG3C,CAEA,OAAO,CACT,CAEA,SAAS,EAAmB,EAAG,GAC7B,OAAO,KAAK,KAAK,KAAK,IAAI,EAAE,EAAI,EAAE,EAAG,GAAK,KAAK,IAAI,EAAE,EAAI,EAAE,EAAG,GAChE,CAEA,SAAS,EAAsB,EAAG,GAChC,IAAI,EAAI,KAAK,MACV,EAAE,OAAO,EAAI,EAAE,OAAO,IAAM,EAAE,OAAO,EAAI,EAAE,OAAO,IAChD,EAAE,OAAO,EAAI,EAAE,OAAO,IAAM,EAAE,OAAO,EAAI,EAAE,OAAO,IAEnD,IACA,EAAE,OAAO,EAAI,EAAE,IAAM,EAAE,OAAO,EAAI,EAAE,OAAO,IAC1C,EAAE,OAAO,EAAI,EAAE,IAAM,EAAE,OAAO,EAAI,EAAE,OAAO,KAC7C,EAAI,GAEP,MAAO,CACL,EAAG,EAAE,OAAO,EAAI,GAAK,EAAE,OAAO,EAAI,EAAE,OAAO,GAC3C,EAAG,EAAE,OAAO,EAAI,GAAK,EAAE,OAAO,EAAI,EAAE,OAAO,GAE/C,CAsCA,SAAS,EAAmB,EAAO,EAAG,GACpC,IAAI,EAAO,EAA4B,GAAO,EAAI,GAC9C,EAAO,EAA4B,GAAO,EAAI,GAC9C,EAAO,EAA4B,GAAO,GAC1C,EAAI,EAAK,EAAI,EAAK,EAAI,EAAK,EAAI,EAAK,EACpC,EAAI,EAAK,EAAI,EAAK,EAAI,EAAK,EAAI,EAAK,EAKxC,OAHA,GAAK,EACL,GAAK,EAEE,CACL,EAAG,EACH,EAAG,EAEP,CAEA,SAAS,EAA0B,EAAO,GACxC,IAAI,EAAgB,CAClB,EAAG,EACH,EAAG,GAED,EAAwB,EAA4B,GAExD,IAAK,IAAI,EAAK,EAAG,EAAK,EAAsB,OAAQ,IAAM,CACxD,IAAI,EAAQ,CACV,EACE,EAA4B,EAAsB,IAAK,GAAG,EAC1D,EAA4B,GAAO,GAAG,EACxC,EACE,EAA4B,EAAsB,IAAK,GAAG,EAC1D,EAA4B,GAAO,GAAG,GAG1C,GAAI,KAAK,IAAI,EAAM,GAAK,GAAO,KAAK,IAAI,EAAM,GAAK,EAAK,CACtD,IAAI,EACF,EACA,KAAK,KA3He,EA4HC,CACjB,OAAQ,EAA4B,EAAsB,IAAK,GAC/D,OAAQ,EAA4B,GAAO,IA7H9C,KAAK,KACV,KAAK,IAAI,EAAE,OAAO,EAAI,EAAE,OAAO,EAAG,GAChC,KAAK,IAAI,EAAE,OAAO,EAAI,EAAE,OAAO,EAAG,KA6H9B,GAGJ,EAAc,GAAK,EAAM,EAAI,EAC7B,EAAc,GAAK,EAAM,EAAI,CAC/B,CACF,CAtIF,IAA4B,EAwI1B,OAAO,CACT,CAEA,SAAS,EAA6C,EAAO,EAAG,GAC9D,IAAI,EAAK,GAAK,EAAY,EAAW,KAAW,EAAI,IAEhD,EAA0C,CAC5C,CACE,EAAG,EACH,EAAG,IAIP,IAAK,IAAI,EAAI,EAAG,EAAI,EAAI,EAAG,IAAK,CAE9B,IAAI,EAAkB,CACpB,EAAG,EACH,EAAG,GAGD,EAAe,EAAmB,EAAO,EAAG,GAC5C,EAAsB,EAA0B,EAAO,GAE3D,EAAgB,EAAI,GAAK,EAAa,EAAI,EAAoB,GAC9D,EAAgB,EAAI,GAAK,EAAa,EAAI,EAAoB,GAE9D,EAAwC,KAAK,EAC/C,CAOA,OALA,EAAwC,KAAK,CAC3C,EAAG,EACH,EAAG,IAGE,CACT,CAGA,SAAS,EAAsB,GAC7B,IAAK,IAAI,EAAQ,EAAG,EAAQ,EAAW,OAAQ,IAC7C,GAAU,IAAN,EACF,EAA4B,GAAO,KACjC,EAAW,EAAW,GAAO,SAE/B,EAA4B,GAAO,MA7KlB,EA8KD,EAAW,GA1KxB,CACL,GAJc,EAAW,EAAE,QAAQ,EAAI,EAAW,EAAE,QAAQ,GAAK,EAKjE,GAJc,EAAW,EAAE,QAAQ,EAAI,EAAW,EAAE,QAAQ,GAAK,KA8K/D,EAA4B,GAAO,KACjC,EAAW,EAAW,GAAO,aAE1B,CACL,IACI,EADsB,EAA4B,IACV,EAAI,GAC5C,EAAyB,EACzB,EAAyB,GAC7B,EAAuB,KAAK,EAAW,EAAW,GAAO,SAEzD,IAAK,IAAI,EAAI,EAAG,EAAI,EAA4B,GAAO,OAAQ,IAAK,CAClE,IAAI,EAAqB,EACvB,EAA4B,GAAO,GACnC,EAA4B,GAAO,EAAI,IAGzC,KAAO,EAAqB,GAAwB,CAClD,IAAI,EAAmB,EAAyB,EAC5C,EACF,EAA4B,GAAO,EAAI,GAAG,EACxC,EACF,EAA4B,GAAO,EAAI,GAAG,EAE5C,GACE,GACC,EAA4B,GAAO,GAAG,EACrC,EAA4B,GAAO,EAAI,GAAG,GAC9C,GACE,GACC,EAA4B,GAAO,GAAG,EACrC,EAA4B,GAAO,EAAI,GAAG,GAC9C,EAAuB,KAAK,CAC1B,EAAG,EACH,EAAG,IAGL,GAAsB,EACtB,EAAyB,CAC3B,CACA,GAA0B,CAC5B,CACA,EAAuB,KAAK,EAAW,EAAW,GAAO,SACzD,EAA4B,GAAS,CACvC,CA3NJ,IAAuB,CA6NvB,CAiCA,SAAS,EAAgB,EAAG,GAC1B,IAAI,EAAK,EAAsB,EAAW,EAAE,QAAS,CACnD,OAAQ,EAAW,EAAE,QACrB,OAAQ,EAAW,EAAE,UAEnB,EAAK,EAAsB,EAAW,EAAE,QAAS,CACnD,OAAQ,EAAW,EAAE,QACrB,OAAQ,EAAW,EAAE,UAEnB,EAAO,CACT,GAAI,EAAG,EAAI,EAAG,GAAK,EACnB,GAAI,EAAG,EAAI,EAAG,GAAK,GAEjB,EAAO,CACT,GAAI,EAAW,EAAE,QAAQ,EAAI,EAAW,EAAE,QAAQ,GAAK,EACvD,GAAI,EAAW,EAAE,QAAQ,EAAI,EAAW,EAAE,QAAQ,GAAK,GAGzD,OAAO,KAAK,IACV,EACA,EAAK,EAAI,EAAmB,EAAM,GAAS,EAAmB,EAAI,GAEtE,CAMA,SAAS,EAAoB,EAAG,GAC9B,OA3DF,SAA6B,EAAG,GAC9B,OAAO,KAAK,KAlQc,EAmQL,EAAe,GAnQP,EAmQW,EAAe,IAlQhD,EAAE,EAAI,EAAE,EAAI,EAAE,EAAI,EAAE,IAmQtB,EAAY,GAAK,EAAY,MApQpC,IAA4B,EAAG,CAsQ/B,CAuDI,CAAoB,EAAG,GArD3B,SAA6B,EAAG,GAC9B,IAAI,GAAQ,EAAY,GAAK,EAAY,IAAM,EAC/C,OACE,GACC,EAAO,KAAK,IAAI,EAAY,GAAI,EAAY,IAC3C,KAAK,IAAI,EAAY,GAAI,EAAY,IAAM,EAEjD,CA+CI,CAAoB,EAAG,GA7C3B,SAAgC,EAAG,GACjC,IAAI,GAAQ,EAAY,GAAK,EAAY,IAAM,EAU/C,OAAO,GAAQ,EAAO,EATX,CACT,GAAI,EAAW,EAAE,QAAQ,EAAI,EAAW,EAAE,QAAQ,GAAK,EACvD,GAAI,EAAW,EAAE,QAAQ,EAAI,EAAW,EAAE,QAAQ,GAAK,GAE9C,CACT,GAAI,EAAW,EAAE,QAAQ,EAAI,EAAW,EAAE,QAAQ,GAAK,EACvD,GAAI,EAAW,EAAE,QAAQ,EAAI,EAAW,EAAE,QAAQ,GAAK,IAI3D,CAkCI,CAAuB,EAAG,GAR9B,SAAkC,EAAG,GACnC,OAAO,KAAK,IAAI,EAAgB,EAAG,GAAI,EAAgB,EAAG,GAC5D,CAOI,CAAyB,EAAG,EAEhC,CAEA,SAAS,EAAe,EAAG,GACzB,OAAO,EAAoB,EAAG,IAAM,CACtC,CAeA,IAAI,EAAc,WAChB,IAAI,EAAI,EACJ,EAAI,EACJ,EAlWQ,GAwFd,WACE,IAAK,IAAI,EAAI,EAAG,EAAI,EAAW,OAAQ,IAEnC,EAA4B,GAAK,EAOvC,CAkQE,GAhQF,WACE,IAAK,IAAI,EAAI,EAAG,EAAI,EAAW,OAAQ,IACrC,EAA4B,GAAK,EAErC,CA6PE,GACA,EAAsB,GApBxB,WACE,IAAK,IAAI,EAAI,EAAG,EAAI,EAAW,OAAS,EAAG,IACzC,IAAK,IAAI,EAAK,EAAI,EAAG,EAAK,EAAW,OAAQ,IAEvC,EAAe,EAAW,GAAI,EAAW,MAC3C,EAA4B,GAAG,KAAK,GACpC,EAA4B,GAAI,KAAK,GAI7C,CAWE,GAEA,IAAK,IAAI,EAAQ,EAAG,EAAQ,EAAG,IAAS,CACtC,IAAK,IAAI,EAAY,EAAG,EAAY,EAAG,IAAa,CAClD,IAAI,EAAS,GACb,IAAK,IAAI,EAAO,EAAG,EAAO,EAAW,OAAQ,IAC3C,EAAO,GAAQ,EACb,EACA,EACA,GAGJ,IAAK,IAAI,EAAI,EAAG,EAAI,EAAW,OAAQ,IACrC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAI,EAAG,IACzB,EAA4B,GAAG,GAAG,GAAK,EAAO,GAAG,GAAG,EACpD,EAA4B,GAAG,GAAG,GAAK,EAAO,GAAG,GAAG,CAG1D,CAEA,GAAQ,EACR,GAAQ,EACR,GAAI,EAEJ,EAAsB,EACxB,CACA,OAAO,CACT,EAuGA,OApGA,EAAY,MAAQ,SAAU,GAC5B,OAAyB,IAArB,UAAU,OACL,GAEP,EAAa,EAGR,EACT,EAEA,EAAY,MAAQ,SAAU,GAC5B,OAAyB,IAArB,UAAU,OACL,GAEP,EAzSJ,SAA2B,GACzB,IAAI,EAAqB,GAEzB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAS,OAAQ,IAEjC,EAAW,EAAS,GAAG,QAAQ,GAAK,EAAW,EAAS,GAAG,QAAQ,GACnE,EAAW,EAAS,GAAG,QAAQ,GAAK,EAAW,EAAS,GAAG,QAAQ,GAGnE,EAAmB,KAAK,EAAS,IAIrC,OAAO,CACT,CA2RiB,CAAkB,GAG1B,EACT,EAEA,EAAY,mBAAqB,SAAU,GACzC,OAAyB,IAArB,UAAU,OACL,GAEP,EAAI,EAGC,EACT,EAEA,EAAY,UAAY,SAAU,GAChC,OAAyB,IAArB,UAAU,OACL,GAEP,EAAY,EAGP,EACT,EAEA,EAAY,OAAS,SAAU,GAC7B,OAAyB,IAArB,UAAU,OACL,GAEP,EAAI,EAGC,EACT,EAEA,EAAY,WAAa,SAAU,GACjC,OAAyB,IAArB,UAAU,OACL,GAEP,EAAY,EAGP,EACT,EAEA,EAAY,gBAAkB,SAAU,GACtC,OAAyB,IAArB,UAAU,OACL,GAEP,EAAS,EAGJ,EACT,EAEA,EAAY,wBAA0B,SAAU,GAC9C,OAAwB,GAApB,UAAU,OACL,GAEP,EAAI,EAGC,EACT,EAEA,EAAY,iBAAmB,SAAU,GACvC,OAAyB,IAArB,UAAU,OACL,GAEP,EAAS,EAGJ,EACT,EAEA,EAAY,wBAA0B,SAAU,GAC9C,OAAyB,IAArB,UAAU,OACL,GAEP,EAA0B,EAGrB,EACT,EAEO,CACT,CASO,SAAS,cACd,MACE,EAAK,MACL,IAEF,GACE,EAAM,GAAM,EAAE,GAAE,SAChB,EAAW,OAAM,mBACjB,EAAqB,GAAG,UACxB,EAAY,GAAG,iBACf,EAAmB,EAAC,OACpB,EAAS,EAAC,WACV,EAAa,GAAE,gBACf,EAAkB,SAAS,wBAC3B,EAA0B,IACxB,IAGJ,MAAM,EAAS,IAAI,IAAI,EAAM,KAAI,CAAC,EAAG,IAAM,CAAC,EAAG,GAAI,MAC7C,EAAU,EAAM,KAAK,IAAC,CAC1B,OAAQ,EAAO,IAAwB,iBAAb,EAAE,OAAsB,EAAG,EAAE,QAAU,EAAE,QACnE,OAAQ,EAAO,IAAwB,iBAAb,EAAE,OAAsB,EAAG,EAAE,QAAU,EAAE,YAG/D,EAAe,oBAClB,MAAM,GACN,MAAM,GACN,mBAAmB,GACnB,UAAU,GACV,iBAAiB,GACjB,OAAO,GACP,WAAW,GACX,gBAAgB,GAChB,wBAAwB,GAS3B,OAPA,EAAa,OAAS,KACpB,MAAM,EAAQ,IACd,EAAM,KAAI,CAAC,EAAG,IAAO,EAAE,GAAY,EAAM,IAAI,EAG/C,EAAa,SAEN,CACT,CChjBO,SAAS,OAAO,EAAO,GAC5B,OAAI,GAAK,EAAM,OAAe,EAEvB,EAAM,QAAO,CAAC,EAAG,IAAM,EAAI,KAAK,MAAM,EAAM,OAAS,IAAO,GACrE,CCFO,SAAS,KAAK,EAAY,EAAM,GAqCrC,OAAO,cACJ,OACA,SAtCH,SAAqB,GACnB,MAAM,EAAY,cAAG,cAAc,GACnC,IAAK,EAAG,GAAK,EAAU,OAAO,CAAC,EAAM,EAAG,EAAM,IAC9C,EAAI,EAAK,EAAE,OAAO,GAClB,EAAI,EAAK,EAAE,OAAO,GAClB,IAAI,EAAU,EAAW,KAAK,EAAG,GAIjC,OAFQ,KAAK,MAAM,EAAI,EAAQ,EAAG,EAAI,EAAQ,GAEnC,EAAK,mBACZ,CACE,OAAQ,EACR,EAAG,EAAU,OAAO,EAAK,EAAE,EAAQ,IACnC,EAAG,EAAU,OAAO,EAAK,EAAE,EAAQ,KAErC,IACN,IAuBG,GAAG,SArBN,SAAqB,GACd,EAAM,QAAQ,EAAW,YAAY,IAAK,UAC/C,EAAM,QAAQ,OAAO,GAAK,EAAM,QAAQ,OAAO,EAC/C,EAAM,QAAQ,OAAO,GAAK,EAAM,QAAQ,OAAO,CACjD,IAkBG,GAAG,QAhBN,SAAiB,GACf,MAAM,EAAY,cAAG,cAAc,GACnC,EAAM,QAAQ,OAAO,GAAK,EAAK,EAAE,OAAO,EAAU,QAAQ,EAAM,IAChE,EAAM,QAAQ,OAAO,GAAK,EAAK,EAAE,OAAO,EAAU,QAAQ,EAAM,GAClE,IAaG,GAAG,OAXN,SAAmB,GACZ,EAAM,QAAQ,EAAW,YAAY,GAC1C,EAAM,QAAQ,OAAO,GAAK,KAC1B,EAAM,QAAQ,OAAO,GAAK,IAC5B,GAQF,CC7CO,SAAS,eAAe,GAC7B,GAAI,EAAK,QAAS,CAChB,MAAM,EAAU,cAAG,OAAO,EAAK,OAAQ,GAAM,EAAE,IACzC,EAAU,cAAG,OAAO,EAAK,OAAQ,GAAM,EAAE,IAK/C,GAHA,EAAK,EAAE,OAAO,cAAG,OAAO,EAAK,OAAQ,GAAM,EAAE,KAC7C,EAAK,EAAE,OAAO,cAAG,OAAO,EAAK,OAAQ,GAAM,EAAE,KAEzC,EAAK,gBAAiB,CACxB,MAAM,EAAQ,EAAK,MAAQ,EAAK,OAGhC,IAFkB,EAAQ,GAAK,EAAQ,KAAO,EAAQ,GAAK,EAAQ,IAEpD,EAAO,CAEpB,MAAM,EACH,EAAK,MAAQ,EAAK,QAAW,EAAQ,GAAK,EAAQ,KAClD,EAAQ,GAAK,EAAQ,IAExB,EAAK,EAAE,OAAO,CAAC,EAAQ,GAAK,EAAI,EAAG,EAAQ,GAAK,EAAI,IACpD,EAAK,EAAE,OAAO,EAChB,KAAO,CAEL,MAAM,EACH,EAAK,OAAS,EAAK,OAAU,EAAQ,GAAK,EAAQ,KAClD,EAAQ,GAAK,EAAQ,IAExB,EAAK,EAAE,OAAO,CAAC,EAAQ,GAAK,EAAI,EAAG,EAAQ,GAAK,EAAI,IACpD,EAAK,EAAE,OAAO,EAChB,CACF,CACF,CACF,CC/BO,SAAS,eAAe,EAAG,EAAW,GAC3C,MAAO,EAAG,GAAK,EAAU,MAAM,CAAC,EAAK,EAAE,EAAE,GAAI,EAAK,EAAE,EAAE,KACtD,MAAO,IAAK,EAAG,IAAG,IACpB,CCKA,SAAS,YACP,GACA,EACE,EAAK,GAAM,EAAE,GAAE,EACf,EAAK,GAAM,EAAE,GAAE,EACf,EAAI,IAAM,EAAC,MACX,EAAQ,CAAC,EAAG,IAAM,EAAC,KACnB,EAAO,OAAM,OACb,EAAS,QAAO,MAChB,EAAQ,KAAI,OACZ,EAAS,KAAI,OACb,EAAS,KAAI,SACb,EAAW,MAAK,KAChB,EAAO,IAAM,kBAAiB,MAC9B,GAAQ,EAAI,QACZ,EAAW,GAAM,EAAC,UAClB,EAAY,IAAM,yBAAwB,kBAC1C,GAAoB,EAAI,UACxB,EAAY,IAAI,WAChB,EAAc,IAAM,EAAK,UACzB,EAAY,CAAC,EAAG,IAAS,EAAW,KAAO,cAAG,YAAY,GAAQ,EAAS,eAE3E,EAAiB,YAAW,YAC5B,EAAc,EAAC,YAEf,GAAc,EAAK,cACnB,EAAgB,OAAM,YAEtB,GAAc,EAAK,cACnB,EAAgB,SAAQ,YACxB,EAAc,OAAM,aAEpB,GAAe,EAAI,cACnB,EAAgB,eAAc,WAG9B,GAAa,EAAK,WAClB,EAAa,OAAM,mBACnB,EAAqB,YAAW,aAChC,EAAe,OAAM,MACrB,GAAQ,EAAK,SACb,EAAW,KAAI,QACf,EAAU,GACR,IAEJ,IAAK,GAAyB,IAAjB,GAAM,OAEjB,OADA,QAAQ,IAAI,kCACL,EAGT,EAAO,EAAK,QACV,CAAC,EAAG,SACc,IAAhB,EAAE,EAAG,IACW,OAAhB,EAAE,EAAG,SACW,IAAhB,EAAE,EAAG,IACW,OAAhB,EAAE,EAAG,KAGW,iBAAT,IAAmB,EAAO,IAAM,GAClB,iBAAd,IAAwB,EAAY,IAAM,GAErD,IAAI,EAAU,cAAG,OAAO,EAAM,GAC5B,EAAU,cAAG,OAAO,EAAM,GAiB5B,GAhBA,EAAQ,GAAS,EAAQ,GAAK,EAAQ,GACtC,EAAS,GAAU,EAAQ,GAAK,EAAQ,GAEpC,GAAO,QAAQ,IAAI,yBAA0B,GAa7C,IAXJ,SAAsC,EAAQ,GAI5C,OAHI,GAAU,EAAO,OACnB,EAAS,EAAO,QAEmB,WAAjC,EAAS,oBACJ,aAAkB,kBAElB,aAAkB,UAE7B,CAEe,CAA6B,EAAQ,GAOlD,MANI,GACF,QAAQ,IACN,kDACA,EACA,GAEE,IAAI,MACR,gDACA,EACA,GAKiC,WAAjC,EAAS,qBAET,EADE,EACO,cAAG,OAAO,EAAO,KAAO,EAAO,OAAS,GAExC,cAAG,OAAO,UAAU,KAAK,QAAS,GAAO,KAAK,SAAU,GAEnE,GAAe,GAOf,GAJE,EADE,EACO,cAAG,OAAO,EAAO,KAAO,EAAO,OAAS,GAExC,cAAG,OAAO,OAAO,KAAK,UAAW,CAAC,EAAG,EAAG,EAAO,MAEvC,cAAG,OAAO,OAAO,KAAK,UAAW,CAAC,EAAG,EAAG,EAAO,IAGpE,MAAM,EAAW,cAAG,SAAS,KAAK,EAAM,EAAG,GACrC,EAAU,EAAS,QAAQ,CAC/B,EAAQ,GAAK,EACb,EAAQ,GAAK,EACb,EAAQ,GAAK,EACb,EAAQ,GAAK,IAGf,IAAI,EAAQ,EAAK,KAAI,CAAC,EAAG,IAAM,CAAC,EAAG,EAAQ,YAAY,MAQvD,SAAS,EAAe,EAAG,EAAM,GAC/B,IAAK,EAAM,CACT,MAAM,EAAI,EAAS,KAAK,EAAE,EAAG,GAAQ,EAAE,EAAG,IAC1C,IAAU,IAAN,EAEF,OADA,QAAQ,IAAI,qBAAsB,EAAG,EAAG,EAAE,EAAG,GAAQ,EAAE,EAAG,IACnD,KAET,EAAO,EAAM,GAAG,EAClB,CACA,OAAO,CACT,CAkMA,SAAS,EAAiC,GACpC,GACF,QAAQ,IACN,mCACA,cACA,EACA,oBACA,EACA,cACA,EACA,aACA,IAEA,GAAe,IACjB,EAAM,SAAQ,EAAG,IAAG,OAAM,QAAQ,KAChC,IAAK,EAAM,OACX,MAAO,EAAI,GAAM,cAAG,gBAAgB,GACpC,EAAQ,YACR,EAAQ,OAAO,EAAI,GACnB,EAAQ,OAAO,EAAE,EAAG,GAAQ,EAAE,EAAG,IACjC,EAAQ,YAAc,EACtB,EAAQ,QAAQ,IAIhB,IACF,EAAQ,YACR,EAAQ,OAAO,GACf,EAAQ,YAAc,EACtB,EAAQ,UAGN,IACF,EAAQ,YAER,EAAQ,OACR,EAAQ,YAAc,GACtB,EAAQ,UAAY,QACpB,EAAK,SAAQ,CAAC,EAAG,KACf,EAAQ,YACR,EAAQ,IAAI,EAAE,EAAG,GAAI,EAAE,EAAG,GAAI,EAAE,EAAG,GAAI,EAAG,EAAI,KAAK,GAAG,IAExD,EAAQ,UACR,EAAQ,UAAY,EACpB,EAAQ,OACR,EAAQ,YAAc,EACtB,EAAQ,SAEZ,CAEA,SAAS,EAAmB,EAAS,GACnC,EAAM,SAAQ,EAAG,IAAG,OAAM,QAAQ,KAChC,IAAK,GAAQ,IAAU,EAAU,OACjC,MAAO,EAAI,GAAM,cAAG,gBAAgB,GAC9B,GACH,KAAK,MACH,KAAK,MAAM,EAAK,EAAE,EAAG,GAAQ,EAAK,EAAE,EAAG,IAAU,KAAK,GAAM,GAE7D,GACF,EAEF,EAAQ,OACR,MAAM,EAAK,EAAE,EAAG,GAAS,EACnB,EAAe,IAAV,EAAc,EAAe,IAAV,GAAe,EAAK,EAC5C,EAAe,IAAV,EAAc,EAAe,IAAV,GAAe,EAAK,EAClD,EAAQ,UACN,EAAoB,EAAK,EAAE,EAAG,GAAS,EACvC,EAAoB,EAAK,EAAE,EAAG,GAAS,GAEzC,EAAQ,UACI,IAAV,EACI,OACU,IAAV,EACE,SACU,IAAV,EACE,QACA,SACV,EAAQ,aACI,IAAV,EACI,SACU,IAAV,EACE,MACU,IAAV,EACE,SACA,SACV,EAAQ,KAAO,IAAU,EAAW,EAAU,EAAG,GAAS,EAAK,EAAG,GAClE,EAAQ,UAAY,EACpB,EAAQ,YAAc,EACtB,EAAQ,UAAY,EAEpB,EAAQ,WAAW,EAAM,EAAG,GAAQ,EAAG,GACvC,EAAQ,SAAS,EAAM,EAAG,GAAQ,EAAG,GACrC,EAAQ,SAAS,GAErB,CA+BA,OA/UA,EAAQ,EACL,KAAI,EAAE,EAAG,GAAO,IAAU,CAAC,EAAG,EAAe,EAAG,EAAM,MACtD,KAAI,EAAE,EAAG,MAAK,CAAQ,IAAG,OAAM,KAAM,EAAU,EAAG,OAuUhB,WAAjC,EAAS,oBAvBb,WACE,MAAM,EAAU,EAAO,OAAO,WAAW,MAEzC,EAAiC,GACjC,EAAmB,EAAS,GAExB,IACE,GAAO,QAAQ,IAAI,sBAAuB,GAE9C,EAAO,GAAG,aAAc,IACtB,MAAO,EAAI,GAAM,cAAG,QAAQ,GACtB,EAAI,EAAS,KAAK,EAAI,GACxB,IAAM,IACV,EAAW,EAEX,EAAQ,UAAU,EAAG,EAAG,EAAO,GAC/B,EAAiC,GAC7B,GAA8B,mBAAZ,GAAwB,EAAQ,GACtD,EAAmB,EAAS,GAAS,IAG3C,CAGE,GAxTF,WACE,IAAI,EAAU,KACV,GACF,EACG,UAAU,qBACV,KAAK,CAAC,IACN,KAAK,SACL,KAAK,QAAS,eAAe,KAAK,2DACa,aAIpD,MAAM,EAAY,EACf,UAAU,oBACV,KAAK,CAAC,IACN,KAAK,QACL,KAAK,QAAS,eACd,KAAK,QAAS,GACd,KAAK,SAAU,GACf,KAAK,OAAQ,GACb,KAAK,SAAU,QAEZ,EAAS,CACb,IAAM,GACJ,EACG,KAAK,cAAe,UACpB,KAAK,KAAK,CAAC,EAAG,MAAQ,EAAE,EAAG,GAAK,KACrC,MAAQ,GACN,EACG,KAAK,cAAe,SACpB,KAAK,KAAM,UACX,KAAK,KAAK,CAAC,EAAG,IAAM,EAAE,EAAG,GAAK,IACnC,OAAS,GACP,EACG,KAAK,cAAe,UACpB,KAAK,KAAM,UACX,KAAK,KAAK,CAAC,EAAG,IAAM,EAAE,EAAG,GAAK,IACnC,KAAO,GACL,EACG,KAAK,cAAe,OACpB,KAAK,KAAM,UACX,KAAK,KAAK,CAAC,EAAG,MAAQ,EAAE,EAAG,GAAK,MAmCvC,IAAI,GAhCA,GAAe,KACjB,EAAU,EACP,UAAU,aACV,KAAK,CAAC,IACN,KAAK,KACL,KAAK,iBAAkB,QACvB,KAAK,KAAM,WACX,KAAK,SAAU,GACf,KAAK,OAAQ,GACb,UAAU,eACV,MAAM,GAAM,IACZ,KAAK,QACL,KAAK,QAAS,UACd,KAAK,WAAW,EAAG,UAAY,EAAO,KAAO,SAC7C,KAAK,KAAK,EAAG,IAAG,QAAQ,IACvB,EACI,IAAI,cAAG,gBAAgB,MAAS,EAAE,EAAG,MAAU,EAAE,EAAG,KACpD,QAIN,GACF,EACG,UAAU,gBACV,KAAK,CAAC,IACN,KAAK,QACL,KAAK,KAAM,WACX,KAAK,SAAU,GACf,KAAK,iBAAkB,QACvB,KAAK,IAAK,EAAQ,UAInB,IACF,EAAS,EACN,UAAU,iBACV,KAAK,CAAC,IACN,KAAK,QACL,KAAK,KAAM,UACX,KAAK,iBAAkB,QACvB,KAAK,SAAU,GACf,KAAK,OAAQ,GACb,KAAK,IAAK,EAAS,aAAa,KAAM,KAG3C,MAAM,EAAS,EACZ,UAAU,YACV,KAAK,CAAC,IACN,KAAK,KACL,KAAK,QAAS,UACd,KAAK,OAAQ,GAEb,KAAK,SAAU,GACf,KAAK,eAAgB,GACrB,KAAK,cAAe,UACpB,KAAK,iBAAkB,QACvB,UAAU,QACV,MAAM,GAAM,IACZ,KAAK,QACL,MAAM,QAAQ,EAAE,KAAI,IAAM,EAAK,EAAG,KAClC,MAAK,UAAU,EAAE,EAAC,KAAE,GAAQ,GAC3B,IAAK,EAAM,OACX,MAAO,EAAI,GAAM,cAAG,gBAAgB,GAC9B,GACH,KAAK,MACH,KAAK,MAAM,EAAK,EAAE,EAAG,GAAQ,EAAK,EAAE,EAAG,IAAU,KAAK,GAAM,GAE7D,GACF,EAEF,cAAG,OAAO,MAAM,KACJ,IAAV,EACI,EAAO,MACG,IAAV,EACE,EAAO,IACG,IAAV,EACE,EAAO,OACP,EAAO,KAEnB,IACC,KAAK,aAAa,EAAG,IAAG,QAAQ,KAC/B,GAAI,EAAmB,CACrB,MAAO,EAAI,GAAM,cAAG,gBAAgB,GAEpC,MAAO,aAAa,MAAO,IAC7B,CACE,MAAO,aAAa,EAAE,EAAG,OAAW,EAAE,EAAG,KAC3C,IAED,KAAK,WAAW,EAAG,UAAY,EAAO,KAAO,SAC7C,MAAK,EAAG,KAAK,EAAG,IAAQ,EAAM,EAAG,EAAG,KAEvC,IAAI,EAAW,KAuCf,GAtCI,GACF,EAAU,GAAG,aAAc,IAEzB,MAAM,EAAI,EAAS,QAAQ,cAAG,QAAQ,IAClC,IAAM,IACV,EAAW,EAGX,EACG,KAAK,WAAW,EAAG,QAAQ,IAC1B,IAAM,GAAY,EAAO,KAAO,SAEjC,MAAM,QAAQ,EAAE,KAAI,IACnB,IAAM,EAAW,EAAU,EAAG,GAAK,EAAK,EAAG,KAE5C,QAAQ,YAAY,CAAC,EAAG,IAAM,IAAM,IACpC,QAAO,CAAC,EAAG,IAAM,IAAM,IACvB,QAEH,GACE,EAAQ,KAAK,WAAW,EAAG,QAAQ,IACjC,GAAQ,IAAM,EAAW,KAAO,SAGhC,GACF,EACG,KAAK,QAAQ,CAAC,EAAG,IACC,IAElB,QAAQ,YAAY,CAAC,EAAG,IAAM,IAAM,IAGrC,GAA8B,mBAAZ,GAAwB,EAAQ,GAAE,IAMxD,EAAc,CAChB,MAAM,EAAW,IAAI,kBAAiB,WAChC,SAAS,SAAS,EAAO,UAC3B,EAAO,KAAK,UAAW,mBACvB,EAAS,aAEb,IAEA,EAAS,QAAQ,SAAU,CACzB,YAAY,EACZ,WAAW,EACX,eAAe,EACf,SAAS,GAEb,CACF,CA4HE,GAGK,OAAO,OAAO,EAAO,OAAQ,CAAE,WAAU,UAAS,SAC3D,CAiBA,SAAS,UAAU,EAAK,EAAU,QAChC,MAAM,EAAQ,cACX,KAAK,EAAI,UAAU,IAAW,IAAU,EAAK,aAAa,mBAC1D,UACA,KAAK,IACJ,MAAM,EAAE,EAAC,EAAE,EAAC,MAAE,EAAK,OAAE,GAAW,EAAK,wBACrC,MAAO,CAAE,OAAM,IAAG,IAAG,QAAO,SAAQ,IAGlC,EAAU,GAChB,IAAK,MAAM,KAAK,EAAO,CACrB,MAAM,EAAW,EAAQ,MAAM,GAAM,cAAc,EAAG,KACtD,cAAG,OAAO,EAAE,MAAM,QAAQ,WAAY,GACjC,GAAU,EAAQ,KAAK,EAC9B,CACA,OAAO,CACT,CAGA,SAAS,cAAc,EAAG,GACxB,QACE,EAAE,EAAI,EAAE,MAAQ,EAAE,GAClB,EAAE,EAAI,EAAE,MAAQ,EAAE,GAClB,EAAE,EAAI,EAAE,OAAS,EAAE,GACnB,EAAE,EAAI,EAAE,OAAS,EAAE,EAEvB,CCxfO,SAAS,aAAa,GAC3B,IAAI,EAEJ,IACE,GAA4B,WAAxB,EAAK,OAAO,QACd,MAAM,IAAI,MAAM,qBAElB,EAAU,EAAK,OAAO,WAAW,KACnC,CAAE,MAAO,GAEP,MAAM,EAAS,SAAS,cAAc,UACtC,EAAO,MAAQ,EAAK,MACpB,EAAO,OAAS,EAAK,OACrB,EAAU,EAAO,WAAW,KAC9B,CAEA,MAAM,EAAO,cACV,OACA,MAAM,EAAK,WACX,GAAG,GAAM,EAAE,IACX,GAAG,GAAM,EAAE,IACX,QAAQ,GAEL,EAAO,cACV,OACA,OAAO,CACN,CAAC,EAAG,GACJ,CAAC,EAAK,MAAO,EAAK,UAEnB,YAAY,EAAK,iBACjB,GAAG,QAAQ,EAAG,eAAgB,EAAO,KAExC,SAAS,EAAkB,EAAY,cAAG,cAAc,EAAQ,SAC9D,GACgC,OAA9B,EAAK,sBACL,EAAK,WAAW,QAAU,EAAK,qBAC/B,CACA,EAAQ,OAEH,EAAK,KACR,EAAQ,YAAc,EAAK,mBAG7B,IAAK,MAAO,EAAG,KAAS,EAAK,MAAM,UACjC,EAAQ,YACR,EAAS,EAAM,GAGX,EAAK,KAAI,EAAQ,YAAc,EAAK,GAAG,IAC3C,EAAQ,YAAc,EAAK,EAAI,EAAK,EAAE,GAAK,EAAK,WAChD,EAAQ,UAAY,EAAK,EAAI,EAAK,EAAE,GAAK,EAAK,gBAC9C,EAAQ,SAEV,EAAQ,SACV,CAEA,EAAQ,OACR,EAAQ,YAAc,EAAK,kBAC3B,IAAK,MAAO,EAAG,KAAS,EAAK,MAAM,UACjC,EAAQ,YACR,EAAS,EAAM,EAAG,GAClB,EAAQ,UAAY,EAAK,EAAI,EAAK,MAAM,EAAK,EAAE,IAAM,EAAK,SAC1D,EAAQ,YAAc,EAAK,GAAK,EAAK,GAAG,GAAK,EAAK,WAClD,EAAQ,OACR,EAAQ,SAEV,EAAQ,SACV,CAEA,SAAS,EAAO,EAAY,cAAG,cAAc,EAAQ,SAKnD,GAJA,EAAQ,OAER,eAAe,GAEX,EAAK,iBAAmB,EAAK,SAAU,CACzC,IAAK,IAAI,KAAK,EAAK,aACV,EAAE,OAGP,EAAK,aAAa,qBACwB,IAA1C,EAAK,aAAa,qBACpB,EAAK,WAAW,QAAU,EAAK,aAAa,sBAE5C,EAAK,SAAS,QAElB,CAKA,GAHA,EAAQ,UAAU,EAAG,EAAG,EAAK,MAAO,EAAK,QACzC,EAAkB,GAEd,EAAK,UAAW,CAMlB,GAJA,EAAQ,OACR,EAAQ,UAAY,EAAK,cACzB,EAAQ,UAAY,EAAK,mBACzB,EAAQ,WAAa,EAAK,oBACtB,EAAK,EAAG,CAIV,GAHA,EAAQ,KAAO,EAAK,cACpB,EAAQ,YAEJ,EAAK,eACP,YAAY,EAAK,MAAO,IACnB,EAAK,YACR,OAAQ,EAAQ,OAChB,MAAO,CAAC,EAAG,IAAM,EAAK,EAAE,GACxB,EAAI,GAAM,EAAU,OAAO,EAAK,EAAE,EAAE,IACpC,EAAI,GAAM,EAAU,OAAO,EAAK,EAAE,EAAE,IACpC,MAAO,EAAK,MACZ,OAAQ,EAAK,OACb,SAAU,EAAK,SACf,QAAS,IAAM,EAAkB,UAGnC,IAAK,MAAO,EAAG,KAAS,EAAK,MAAM,UACjC,EAAU,EAAM,EAAG,GAGvB,EAAQ,QACV,CACA,EAAQ,SACV,CAEA,EAAQ,SACV,CAEA,SAAS,EAAS,EAAG,GACnB,EACE,EAAK,iBAAmB,EAAE,KACtB,EAAE,KAAK,KAAK,GAAM,eAAe,EAAG,EAAW,KAC/C,CACE,eAAe,EAAE,OAAQ,EAAW,GACpC,eAAe,EAAE,OAAQ,EAAW,IAG9C,CAEA,SAAS,EAAS,EAAG,EAAG,GACtB,EAAI,eAAe,EAAG,EAAW,GACjC,EAAQ,OAAO,EAAE,EAAI,EAAK,EAAE,GAAI,EAAE,GAClC,EAAQ,IAAI,EAAE,EAAG,EAAE,EAAG,EAAK,EAAE,GAAI,EAAG,EAAI,KAAK,GAC/C,CAEA,SAAS,EAAU,EAAG,EAAG,GACvB,EAAI,eAAe,EAAG,EAAW,GACjC,EAAQ,SAAS,EAAK,EAAE,GAAI,EAAE,EAAG,EAAE,EAAI,EAAK,EAAE,GAAK,EACrD,CAEA,MAAO,CACL,OAAQ,cACL,OAAO,EAAQ,QACf,KACC,EACG,KAAK,EAAK,WAAY,EAAQ,OAAQ,GACtC,GAAG,uCAAuC,IAClC,EAAO,cAAG,cAAc,EAAQ,YAG5C,KACC,EAAK,QAAU,EAAO,QAEvB,OACH,SAEJ,CCnKO,SAAS,UAAU,GACxB,IAAI,EAEJ,IACE,GAA4B,QAAxB,EAAK,OAAO,QACd,MAAM,IAAI,MAAM,kBAElB,EAAM,cAAG,OAAO,EAAK,MACvB,CAAE,MACA,EAAM,cAAG,OAAO,MAClB,CAEA,MAAM,EAAO,cACV,OACA,MAAM,EAAK,WACX,GAAG,GAAM,EAAE,IACX,GAAG,GAAM,EAAE,IAEd,EACG,KAAK,QAAS,EAAK,OACnB,KAAK,SAAU,EAAK,QACpB,KAAK,UAAW,CAAC,EAAG,EAAG,EAAK,MAAO,EAAK,SACxC,KAAK,QAAS,qDAEjB,MAMM,EANQ,EACX,UAAU,YACV,KAAK,CAAC,IACN,KAAK,KACL,KAAK,KAAM,UAGX,KACC,SAC2B,mBAApB,EAAK,WAA4B,EAAK,WAAa,MAE3D,KAAK,OAAQ,QACb,KAAK,kBAAkB,CAAC,EAAG,IAC1B,EAAK,GAAK,EAAK,GAAG,GAAK,EAAK,oBAE7B,KACC,eACgC,mBAAzB,EAAK,gBAAiC,EAAK,gBAAkB,MAErE,KAAK,iBAAkB,EAAK,mBAC5B,UAAU,QACV,KAAK,EAAK,OACV,KAAK,QAEF,EAAQ,EACX,UAAU,YACV,KAAK,CAAC,IACN,KAAK,KACL,KAAK,KAAM,UAER,EAAO,EACV,KAAK,OAAQ,EAAK,UAClB,KAAK,iBAAkB,EAAK,mBAC5B,KAAK,eAAgB,EAAK,iBAC1B,UAAU,eACV,KAAK,EAAK,OACV,KAAK,UACL,KAAK,QAAS,QACd,KAAK,UAAU,CAAC,EAAG,IAAO,EAAK,GAAK,EAAK,GAAG,GAAK,EAAK,aACtD,KAAK,KAAK,CAAC,EAAG,IAAM,EAAK,EAAE,KAE9B,IAAI,EAAQ,KAEP,EAAK,iBACR,EAAQ,EACL,UAAU,cACV,KAAK,EAAK,OACV,KAAK,QACL,KAAK,OAAQ,EAAK,eAClB,KAAK,SAAU,EAAK,iBAAmB,QACvC,MAAM,cAAe,EAAK,gBAC1B,MAAM,cAAe,EAAK,qBAC1B,MAAM,OAAQ,EAAK,eACnB,KAAK,QAAS,SACd,MAAK,CAAC,EAAG,IAAM,EAAK,EAAE,MAG3B,EAAK,KAAK,EAAK,KAAK,EAAK,WAAY,EAAI,OAAQ,IAEjD,MAAM,EAAO,cACV,OACA,OAAO,CACN,CAAC,EAAG,GACJ,CAAC,EAAK,MAAO,EAAK,UAEnB,YAAY,EAAK,iBACjB,GAAG,QAAQ,EAAG,eAAgB,EAAO,KAWxC,SAAS,EAAO,EAAY,cAAG,cAAc,EAAI,SAG/C,GAFA,eAAe,GAEX,EAAK,iBAAmB,EAAK,SAAU,CACzC,IAAK,IAAI,KAAK,EAAK,aACV,EAAE,OAGP,EAAK,aAAa,qBACwB,IAA1C,EAAK,aAAa,qBACpB,EAAK,WAAW,QAAU,EAAK,aAAa,sBAE5C,EAAK,SAAS,QAElB,CAEA,EACG,KACC,UAC8B,OAA9B,EAAK,sBACH,EAAK,WAAW,SAAW,EAAK,qBAC9B,QACA,QAEL,KAAK,KAAM,GACH,EACL,EAAK,iBAAmB,EAAE,KACtB,EAAE,KAAK,KAAK,GAAM,eAAe,EAAG,EAAW,KAC/C,CACE,eAAe,EAAE,OAAQ,EAAW,GACpC,eAAe,EAAE,OAAQ,EAAW,OAKhD,EACG,KAAK,MAAO,GAAM,eAAe,EAAG,EAAW,GAAM,IACrD,KAAK,MAAO,GAAM,eAAe,EAAG,EAAW,GAAM,IAEpD,EAAK,gBAAkB,EAAK,EAC9B,YAAY,EAAK,MAAO,IACnB,EAAK,YACR,OAAQ,EACR,MAAO,CAAC,EAAG,IAAM,EAAK,EAAE,GACxB,EAAI,GAAM,EAAU,OAAO,EAAK,EAAE,EAAE,IACpC,EAAI,GAAM,EAAU,OAAO,EAAK,EAAE,EAAE,IACpC,MAAO,EAAK,MACZ,OAAQ,EAAK,SAEN,GACT,EACG,KACC,KACC,GAAM,eAAe,EAAG,EAAW,GAAM,EAAI,EAAK,cAEpD,KACC,KACC,GAAM,eAAe,EAAG,EAAW,GAAM,EAAI,EAAK,aAG3D,CAEA,OAvEA,EAAI,KACF,EAAK,QAAU,EAAO,QAGpB,EAAK,GAAG,EAAK,KAAK,gBAAgB,EAAG,MAAO,KAAQ,EAAK,EAAE,KAC3D,EAAK,GAAG,EAAK,KAAK,UAAU,EAAG,MAAO,KAAQ,EAAK,EAAE,KACrD,EAAK,GAAG,EAAK,KAAK,QAAQ,EAAG,MAAO,KAAQ,EAAK,MAAM,EAAK,EAAE,MAC9D,EAAK,GAAG,EAAK,OAAO,SAAS,MAAK,EAAG,MAAO,KAAQ,EAAK,EAAE,KAgExD,CAAE,OAAQ,EAAI,OAAQ,SAC/B,CCvKO,SAAS,eAAe,EAAW,IACxC,MAAM,MAAE,EAAQ,IAAG,OAAE,EAAS,IAAG,aAAE,EAAe,MAAS,EAE3D,MAAO,CACL,OAAS,GAAM,GAAG,GAClB,eAAW,EACX,gBAAY,EACZ,SAAU,eACV,WAAY,IAAM,OAClB,gBAAiB,IACjB,kBAAmB,EACnB,WAAY,EACZ,eAAW,EACX,cAAe,OACf,gBAAiB,KACjB,mBAAoB,SACpB,oBAAqB,SACrB,cAAe,iBACf,aAAa,EACb,YAAa,EACb,kBAAc,EACd,gBAAY,EACZ,gBAAY,EACZ,WAAY,OACZ,kBAAmB,GACnB,gBAAiB,IACjB,kBAAmB,QACnB,kBAAc,EACd,aAAc,GACd,UAAW,cAAG,WACd,OAAQ,cAAG,gBACX,MAAO,KACP,QACA,SACA,eACA,SAAU,SACV,qBAAsB,KACtB,WAAO,EACP,OAAQ,KACR,YAAa,gBACb,aAAc,GACd,eAAgB,GAChB,uBAAwB,EACxB,oBAAgB,EAChB,oBAAgB,EAChB,kBAAmB,IACnB,SAAS,EACT,eAAgB,EAChB,kBAAmB,EACnB,OAAQ,KACR,UAAU,EACV,iBAAiB,EACjB,aAAc,CACZ,mBAAoB,GACpB,UAAW,GACX,iBAAkB,EAClB,OAAQ,EACR,WAAY,GACZ,gBAAiB,SACjB,wBAAyB,GACzB,UAAW,IACX,oBAAqB,IAEvB,gBAAgB,EAChB,YAAa,CACX,SAAU,QACV,SAAU,GACV,yBAA0B,KAC1B,yBAA0B,GAC1B,kBAAmB,IACnB,kBAAmB,GACnB,aAAa,EACb,cAAe,IAEjB,SAAS,EACT,gBAAiB,CAAC,GAAK,IACvB,mBAAoB,GACpB,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,YAAa,CACX,OAAQ,QACR,UAAW,IACX,KAAO,GAAO,iBACd,OAAO,EACP,QAAU,GAAM,EAChB,UAAY,GAAO,wBACnB,mBAAmB,EACnB,eAAgB,YAChB,YAAa,EACb,aAAa,EACb,cAAe,OACf,aAAa,EACb,cAAe,SACf,YAAa,OACb,cAAc,EACd,cAAe,gBAEjB,YAAa,EACb,OAAO,EAEX,CC1FO,SAAS,cACd,MAAE,EAAK,MAAE,EAAQ,IACjB,EAAQ,IAGR,IAAK,EACH,MAAM,IAAI,MACR,iHAKJ,IAAK,MAAM,QAAQ,GACjB,MAAM,IAAI,MACR,qDAAqD,oEAWzD,GANqB,IAAjB,EAAM,QACR,QAAQ,KACN,mEAIC,MAAM,QAAQ,GACjB,MAAM,IAAI,MACR,qDAAqD,oEAMzD,MAAM,EAAiB,EAAM,QAAM,CAAM,GAAM,GAAG,IAC5C,EAAe,EAAM,QAAQ,IACjC,MAAM,EAAK,EAAe,GAC1B,OAAO,OAA+B,IAGxC,GAAI,EAAa,OAAS,EACxB,MAAM,IAAI,MACR,WAAW,EAAa,4KAO5B,IAAI,EAAO,IACN,eAAe,MACf,EACH,aAAc,IACT,eAAe,GAAO,gBACtB,EAAM,cAEX,YAAa,IACR,eAAe,GAAO,eACtB,EAAM,aAEX,YAAa,IACR,eAAe,GAAO,eACtB,EAAM,cAIb,GAAI,EAAK,YAAyC,mBAApB,EAAK,WAA2B,CAC5D,MAAM,EAAmB,EAAK,WAC9B,EAAK,WAAa,IAAM,CAC1B,CACA,GAAI,EAAK,YAAyC,mBAApB,EAAK,WAA2B,CAC5D,MAAM,EAAa,EAAK,WACxB,EAAK,WAAa,IAAM,CAC1B,CAGA,EAAK,WACH,EAAK,YACT,GAAQ,YAEoB,iBAAX,EACF,EAAK,OAAO,EAAM,IAGL,iBAAX,EACF,EAGF,EAAK,OAAO,IAAW,GAElC,EAAK,WACH,EAAK,YACT,GAAQ,YAEoB,iBAAX,EACF,EAAK,OAAO,EAAM,IAGL,iBAAX,EACF,EAGF,EAAK,OAAO,IAAW,GAIlC,MAAM,EAAI,cAAG,IAAI,EAAO,EAAK,QAAQ,IAAI,GACnC,EAAK,cAAG,IAAI,EAAO,EAAK,YAAY,IAAI,GACxC,EAAK,cAAG,IAAI,EAAO,EAAK,YAAY,IAAI,GACxC,EAAsB,MAAlB,EAAK,UAAoB,KAAO,cAAG,IAAI,EAAO,EAAK,WACvD,EAAuB,MAAnB,EAAK,WAAqB,KAAO,cAAG,IAAI,EAAO,EAAK,YACxD,EACc,MAAlB,EAAK,UAAoB,KAAO,cAAG,IAAI,EAAO,EAAK,WAAW,IAAI,GAC9D,EACe,MAAnB,EAAK,WAAqB,KAAO,cAAG,IAAI,EAAO,EAAK,YAAY,IAAI,GAChE,EAC4B,mBAAzB,EAAK,gBACR,KACA,cAAG,IAAI,EAAO,EAAK,iBACnB,EACuB,mBAApB,EAAK,WACR,KACA,cAAG,IAAI,EAAO,EAAK,YACnB,EAC8B,mBAA3B,EAAK,kBACR,KACA,cAAG,IAAI,EAAO,EAAK,mBAMzB,GAJA,EAAK,EAAI,cAAG,cAAc,OAAO,CAAC,EAAG,EAAK,QAAQ,MAAM,CAAC,EAAG,EAAK,QACjE,EAAK,EAAI,cAAG,cAAc,OAAO,CAAC,EAAG,EAAK,SAAS,MAAM,CAAC,EAAG,EAAK,SAG9D,EAAK,OAAO,MAAO,CAGrB,MAAM,EAAW,IAAI,IAAI,EAAK,OAAO,MAAM,KAAK,GAAM,CAAC,EAAE,GAAI,MAC7D,EAAQ,EAAM,KAAI,CAAC,EAAG,IACpB,OAAO,OACL,EAAS,IAAI,EAAK,OAAO,KAAO,IAAK,EAAG,GAAI,EAAE,GAAI,QAAS,GAAK,EAAE,MAGxE,MAEE,EAAQ,cAAG,IAAI,GAAO,CAAC,EAAG,KAAC,IACtB,EACH,GAAI,EAAE,GACN,QAAS,GAAK,EAAE,OAGpB,EAAQ,cAAG,IAAI,GAAO,CAAC,EAAG,KAAC,CAAQ,OAAQ,EAAG,GAAI,OAAQ,EAAG,OAG7D,IAAK,IAAI,KAAK,EAAO,CACnB,MAAM,EAAe,EACrB,EAAE,OACQ,IAAR,EAAE,EACE,EAAE,GACD,KAAK,SAAW,KAAQ,EAAK,MAAQ,GAAgB,EAAK,MAAQ,EACzE,EAAE,OACQ,IAAR,EAAE,EACE,EAAE,GACD,KAAK,SAAW,KAAQ,EAAK,OAAS,GACvC,EAAK,OAAS,CACtB,CAGI,QAAyB,IAApB,EAAK,aAA0B,EAAK,WAAa,cAAG,KAAK,IAGlE,MAAM,EAAQ,EAAK,MACf,EAAK,MACa,MAAlB,EAAK,UACH,KACA,cAAG,aAAa,EAAK,WAAY,EAAK,QAE5C,IAAI,EACF,EAAK,OAAO,YAAY,MAAM,EAAK,yBAAyB,WAC5D,cAAG,kBAIL,GAFA,EAAW,MAAM,GAEb,EAAK,OACP,IAAK,IAAI,KAAK,EAAK,OACjB,EAAW,MAAM,EAAG,EAAK,OAAO,GAAG,CAAE,QAAO,eAEzC,CAEL,MAAM,EAAY,cAAG,gBACf,EAAY,cAAG,UAAU,GAAO,IAAG,EAAG,MAAO,KAAQ,EAAE,UACnC,IAAtB,EAAK,cAA4B,EAAU,SAAS,EAAK,mBACnC,IAAtB,EAAK,cAA4B,EAAU,SAAS,EAAK,mBAEjC,IAAxB,EAAK,iBACP,EAAK,eAAkB,EAAK,OAAS,EAAK,MAAS,EAAK,wBAE9B,IAAxB,EAAK,iBACP,EAAK,eAAkB,EAAK,MAAQ,EAAK,OAAU,EAAK,mBAG1D,MAAM,EAAe,EAAK,QACtB,cACG,cAAa,CAAC,EAAG,IAAM,EAAE,GAAK,EAAK,iBACnC,WAAW,EAAK,mBACnB,KAEE,EAAS,cAAG,OAAO,EAAK,MAAQ,GAAG,SAAS,EAAK,gBACjD,EAAS,cAAG,OAAO,EAAK,OAAS,GAAG,SAAS,EAAK,gBAExD,IAAI,EACA,EAAK,iBACP,EAAgB,cACb,KAAK,CAAC,EAAK,MAAO,EAAK,OAAS,MAChC,SAAS,EAAK,YAAY,UAC1B,QAAQ,WACR,SAAS,EAAK,YAAY,UAC1B,MAAM,GACN,yBAAyB,EAAK,YAAY,0BAC1C,yBAAyB,EAAK,YAAY,0BAC1C,kBAAkB,EAAK,YAAY,mBACnC,kBAAkB,EAAK,YAAY,mBACnC,YAAY,EAAK,YAAY,aAC7B,cAAc,EAAK,YAAY,gBAGpC,EACG,MACC,OACA,EACG,SAAS,EAAK,cACd,SACC,EAAK,eACD,EAAc,gBACd,EAAK,cAAgB,KAG9B,MAAM,SAAU,GAChB,MAAM,IAAK,EAAK,eAAiB,KAAO,EAAK,SAAW,EAAS,MACjE,MAAM,IAAK,EAAK,eAAiB,KAAO,EAAK,SAAW,EAAS,MACjE,MACC,SACA,EAAK,gBAEA,EAAK,SADN,KAEE,cAAG,YAAY,EAAK,MAAQ,EAAG,EAAK,OAAS,IAGpD,MAAM,UAAW,GACjB,MAAM,cAAe,EAAK,eAAiB,EAAgB,KAChE,CAGA,EAAK,SACH,EAAK,iBACL,aACE,CAAE,QAAO,MAAO,OAAO,EAAO,EAAK,aAAa,YAChD,IACK,EAAK,eAId,EAAW,YAAY,EAAK,aAAa,UAErC,EAAK,QACP,EAAW,MACT,WACqB,kBAArB,EAAK,YACD,iBAAiB,EAAK,OAAO,KAAK,IAC/B,OAAO,EAAK,cACZ,cAAa,GACb,SAAS,EAAK,gBACI,gBAArB,EAAK,YACH,YAAY,EAAK,QACjB,eAAe,EAAK,OAAQ,EAAyB,GAAtB,EAAK,iBAI9C,EAAO,IACF,EACH,QACA,QACA,IACA,KACA,KACA,IACA,IACA,IACA,IACA,KACA,IACA,KACA,UACA,aACA,SAGF,MAAM,OAAE,EAAM,OAAE,GACI,WAAlB,EAAK,SAAwB,aAAa,GAAQ,UAAU,GAU9D,SAAS,EAAO,GACd,OAAiB,OAAV,GAAmC,iBAAV,EAC5B,EAAM,UACN,CACN,CAIA,OAhBA,EAAW,GAAG,OAAQ,GAElB,EAAK,cACP,EAAK,aAAa,MAAK,KACrB,EAAW,MAAM,IAUrB,IAEO,OAAO,OAAO,EAAQ,CAC3B,OAAQ,CAAE,SACV,aACA,QACA,SAEJ,CC3UO,SAAS,cACd,GACA,OACE,EAAU,GAAM,EAAE,GAAE,QACpB,EAAU,KAAI,QACd,EAAU,KAAI,cACd,GAAgB,EAAK,SACrB,EAAQ,YACR,EAAc,EAAC,aACf,GAAe,EAAI,aACnB,GAAe,GACb,IAEJ,EAAW,GAEP,IAAI,IAAI,EAAQ,MAAM,KAAI,CAAC,EAAG,EAAG,IAAQ,CAAC,EAAO,EAAG,EAAG,GAAM,MACjE,IAAI,EAAM,CACR,MAAO,IAAI,EAAQ,OACnB,MAAO,IAAI,EAAQ,QAGrB,SAAS,EAAqB,GAC5B,MAAM,EAAM,IAAI,IAAI,IAAI,EAAI,MAAM,KAAK,GAAM,CAAC,EAAE,OAAQ,EAAE,UAAS,SAGnE,OAFA,EAAI,MAAQ,EAAI,KAAK,GAAO,EAAS,IAAI,KAAK,QAAQ,GAAM,IAErD,CACT,CAEA,SAAS,GACP,MAAE,EAAK,MAAE,IACT,aAAE,GAAe,EAAI,aAAE,GAAe,GAAS,IAE/C,MAAM,EAAM,IAAI,IAAI,EAAM,IAAI,IAU9B,MAAO,CAAE,QAAO,MARhB,EAAQ,EACL,QACC,EAAG,SAAQ,cACP,GAAgB,EAAI,IAAI,OACxB,GAAgB,EAAI,IAAI,MAE7B,KAAK,IAAC,IAAW,MAGtB,CAGI,IACF,EAAI,MAAQ,EAAI,MAAM,OAAO,GAAS,KAAK,IAAC,IAAW,OAGzD,EAAM,EAAqB,EAAK,CAAE,eAAc,iBAG5C,IACF,EAAI,MAAQ,EAAI,MAAM,OAAO,GAAS,KAAK,IAAC,IACvC,MAGA,IACH,EAAM,EAAqB,KAI/B,IACE,IAAI,EAAkB,EACtB,EAAkB,EAClB,GAAmB,EAEnB,EAAM,EACJ,CAAE,MAAO,EAAI,MAAO,MAAO,EAAQ,OACnC,CAAE,eAAc,cAAc,IAGhC,EAAM,EAAqB,GAG7B,OAAO,CACT,CC7DO,SAAS,eACd,GACA,WACE,EAAc,GAAM,EAAE,OAAM,WAC5B,EAAc,GAAM,EAAE,OAAM,OAC5B,EAAU,GAAM,EAAC,UACjB,EAAa,IAAE,CAAQ,QACrB,IAEJ,IAAK,MAAM,QAAQ,GACjB,MAAM,IAAI,MAAM,0CAIlB,MAAM,EAAU,IAAI,IACpB,IAAK,MAAM,KAAQ,EAAO,CACxB,MAAM,EAAW,EAAO,EAAW,IAC7B,EAAW,EAAO,EAAW,IAC/B,SAA6C,EAAQ,IAAI,GACzD,SAA6C,EAAQ,IAAI,EAC/D,CAKA,MAAO,CAAE,MAFK,MAAM,KAAK,GAAS,IAAI,GAEtB,MAAO,IAAI,GAC7B,CCrBO,SAAS,cACd,GACE,MAAO,EAAc,GAAI,MAAO,EAAc,IAAO,IAEvD,IAAK,IAAY,EAAQ,MACvB,MAAM,IAAI,MAAM,kDAGlB,SAAS,EAAa,EAAM,GAC1B,MAAM,EAAS,IAAK,GACpB,IAAK,MAAO,EAAI,KAAS,OAAO,QAAQ,GAClB,mBAAT,EACT,EAAO,GAAM,EAAK,GACO,iBAAT,GAAqB,KAAQ,IAC7C,EAAO,GAAM,EAAK,GAEd,IAAO,UAAa,EAAO,IAGnC,OAAO,CACT,CAEA,MAAO,CACL,MAAO,EAAQ,MAAM,KAAK,GAAM,EAAa,EAAG,KAChD,OAAQ,EAAQ,OAAS,IAAI,KAAK,GAAM,EAAa,EAAG,KAE5D,CChCO,SAAS,kBACd,GACA,OACE,EAAU,GAAM,EAAE,GAAE,WACpB,EAAc,GAAM,EAAE,OAAM,WAC5B,EAAc,GAAM,EAAE,QACpB,IAEJ,IAAK,IAAY,EAAQ,MACvB,MAAM,IAAI,MAAM,sDAGlB,MAAM,EAAQ,EAAQ,MAEhB,GAAS,EAAQ,OAAS,IAAI,KAAK,IACvC,MAAM,EAAS,EAAW,GACpB,EAAS,EAAW,GAE1B,MAAO,IACF,EACH,OAA0B,iBAAX,EAAsB,EAAO,EAAM,IAAW,EAC7D,OAA0B,iBAAX,EAAsB,EAAO,EAAM,IAAW,EAC9D,IAGH,MAAO,CAAE,MAAO,IAAI,GAAQ,QAC9B,CCjBO,SAAS,kBACd,GACA,OACE,EAAS,YAAW,cACpB,EAAgB,QAAO,OACvB,EAAU,GAAM,EAAE,GAAE,WACpB,EAAc,GAA2B,iBAAb,EAAE,OAAsB,EAAE,OAAO,GAAK,EAAE,OAAO,WAC3E,EAAc,GAA2B,iBAAb,EAAE,OAAsB,EAAE,OAAO,GAAK,EAAE,QAClE,IAEJ,IAAK,IAAY,EAAQ,MACvB,MAAM,IAAI,MAAM,sDAGlB,MAAM,MAAE,EAAK,MAAE,EAAQ,IAAO,EAGxB,EAAU,EAAM,IAAI,GACpB,EAAY,IAAI,IAAI,EAAQ,KAAI,CAAC,EAAI,IAAM,CAAC,EAAI,MAGhD,EAAU,IAAI,IAAI,EAAQ,KAAK,GAAO,CAAC,EAAI,MACjD,IAAK,MAAM,KAAQ,EAAO,CACxB,MAAM,EAAM,EAAW,GACjB,EAAM,EAAW,GACnB,EAAQ,IAAI,IAAM,EAAQ,IAAI,EAAK,EAAQ,IAAI,GAAO,GACtD,EAAQ,IAAI,IAAM,EAAQ,IAAI,EAAK,EAAQ,IAAI,GAAO,EAC5D,CAEA,IAAI,EAEJ,GAAsB,mBAAX,EAET,EAAU,CAAC,EAAM,IAAM,EAAO,EAAM,EAAG,EAAO,EAAO,QAChD,GAAe,cAAX,EAAwB,CAEjC,MAAM,EAAS,EAAQ,KAAI,CAAC,EAAG,IAAM,IAC/B,EAAQ,GAAO,EAAO,KAAO,EAAI,EAAK,EAAO,GAAK,EAAK,EAAO,IAC9D,EAAQ,CAAC,EAAG,KAChB,EAAO,EAAK,IAAM,EAAK,EAAE,EAG3B,IAAK,MAAM,KAAQ,EAAO,CACxB,MAAM,EAAK,EAAU,IAAI,EAAW,IAC9B,EAAK,EAAU,IAAI,EAAW,SACzB,IAAP,QAA2B,IAAP,GAAkB,EAAM,EAAI,EACtD,CAGA,MAAM,EAAe,IAAI,IACzB,IAAI,EAAY,EAChB,EAAU,CAAC,EAAM,KACf,MAAM,EAAO,EAAK,GAIlB,OAHK,EAAa,IAAI,IACpB,EAAa,IAAI,EAAM,KAElB,EAAa,IAAI,EAAK,CAEjC,KAAO,IAAe,WAAX,EAST,MAAM,IAAI,MACR,sCAAsC,iDAVV,CAE9B,MAAM,EAAY,KAAK,OAAO,EAAQ,SAAU,GAChD,EAAW,IACT,MAAM,EAAS,EAAQ,IAAI,EAAO,KAAU,EAE5C,OAAO,KAAK,IAAI,EAAG,KAAK,MAAO,EAAS,EAAa,GAAG,CAE5D,CAIA,CAOA,MAAO,CAAE,MALY,EAAM,KAAI,CAAC,EAAM,KAAC,IAClC,EACH,CAAC,GAAgB,EAAQ,EAAM,OAGH,MAAO,IAAI,GAC3C,CCpEO,SAAS,eACd,GACA,YACE,EAAW,YACX,EAAW,YACX,EAAW,cACX,EAAgB,QAAO,OACvB,EAAU,GAAM,EAAE,GAAE,UACpB,EAAS,WACT,EAAc,GAAM,EAAE,OAAM,WAC5B,EAAc,GAAM,EAAE,QACpB,IAEJ,IAAI,EA4CJ,OAvCE,EAFE,MAAM,QAAQ,GAEN,eAAe,EAAM,CAC7B,aACA,aACA,UAAW,GAAS,CAAM,IAAE,CAAQ,UAE5B,EAAK,OAA+B,IAAtB,EAAK,MAAM,OASzB,CACR,MAAO,IAAI,EAAK,OAChB,MAAO,IAAK,EAAK,OAAS,KATlB,eAAe,EAAK,OAAS,GAAI,CACzC,aACA,aACA,UAAW,GAAS,CAAM,IAAE,CAAQ,WAWpC,GAAe,KACjB,EAAU,cAAc,EAAS,CAC/B,MAAO,EACP,MAAO,KAKP,IACF,EAAU,kBAAkB,EAAS,CACnC,OAAQ,EACR,gBACA,SACA,aACA,gBAIG,CACT,CCjEO,SAAS,WAAW,EAAM,EAAU,IAEzC,MAAM,EAAU,aAAe,EAAM,GA8CrC,OAzCA,EAAQ,MAAQ,KAOhB,EAAQ,OAAS,SAAU,EAAS,EAAa,IAE/C,MAOM,EAAU,aAAe,EAPT,IACjB,KACA,EACH,MAAO,IAYT,OALA,EAAQ,WAAa,EAAQ,WAC7B,EAAQ,MAAQ,EAAQ,MACxB,EAAQ,MAAQ,EAAQ,MACxB,EAAQ,OAAS,EAAQ,OAElB,CACT,EAKA,EAAQ,QAAU,WACZ,EAAQ,YACV,EAAQ,WAAW,MAIvB,EAKO,CACT,CAMY,MAAC,SAAW,W","file":"/npm/netviz@0.1.1/dist/netviz.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/netviz@0.1.1/dist/netviz.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","// https://github.com/john-guerra/forceInABox#readme v1.0.2 Copyright 2024 undefined\nimport * as d3 from 'd3';\n\nfunction forceInABox() {\n  // d3 style\n  function constant(_) {\n    return () => _;\n  }\n\n  function index(d) {\n    return d.index;\n  }\n\n  let id = index,\n    nodes = [],\n    links = [], //needed for the force version\n    tree,\n    size = [100, 100],\n    forceNodeSize = constant(1), // The expected node size used for computing the cluster node\n    forceCharge = constant(-1),\n    forceLinkDistance = constant(100),\n    forceLinkStrength = constant(0.1),\n    foci = {},\n    // oldStart = force.start,\n    linkStrengthIntraCluster = 0.1,\n    linkStrengthInterCluster = 0.001,\n    // oldGravity = force.gravity(),\n    templateNodes = [],\n    offset = [0, 0],\n    templateForce,\n    groupBy = function (d) {\n      return d.cluster;\n    },\n    template = \"treemap\",\n    enableGrouping = true,\n    strength = 0.1;\n  // showingTemplate = false;\n\n  function force(alpha) {\n    if (!enableGrouping) {\n      return force;\n    }\n    if (template === \"force\") {\n      //Do the tick of the template force and get the new focis\n      templateForce.tick();\n      getFocisFromTemplate();\n    }\n\n    for (let i = 0, n = nodes.length, node, k = alpha * strength; i < n; ++i) {\n      node = nodes[i];\n      node.vx += (foci[groupBy(node)].x - node.x) * k;\n      node.vy += (foci[groupBy(node)].y - node.y) * k;\n    }\n  }\n\n  function initialize() {\n    if (!nodes) return;\n\n    // let i,\n    //     n = nodes.length,\n    //     m = links.length,\n    //     nodeById = map(nodes, id),\n    //     link;\n\n    if (template === \"treemap\") {\n      initializeWithTreemap();\n    } else {\n      initializeWithForce();\n    }\n  }\n\n  force.initialize = function (_) {\n    nodes = _;\n    initialize();\n  };\n\n  function getLinkKey(l) {\n    let sourceID = groupBy(l.source),\n      targetID = groupBy(l.target);\n\n    return sourceID <= targetID\n      ? sourceID + \"~\" + targetID\n      : targetID + \"~\" + sourceID;\n  }\n\n  function computeClustersNodeCounts(nodes) {\n    let clustersCounts = new Map(),\n      tmpCount = {};\n\n    nodes.forEach(function (d) {\n      if (!clustersCounts.has(groupBy(d))) {\n        clustersCounts.set(groupBy(d), { count: 0, sumforceNodeSize: 0 });\n      }\n    });\n\n    nodes.forEach(function (d) {\n      // if (!d.show) { return; }\n      tmpCount = clustersCounts.get(groupBy(d));\n      tmpCount.count = tmpCount.count + 1;\n      tmpCount.sumforceNodeSize =\n        tmpCount.sumforceNodeSize +\n        Math.PI * (forceNodeSize(d) * forceNodeSize(d)) * 1.3;\n      clustersCounts.set(groupBy(d), tmpCount);\n    });\n\n    return clustersCounts;\n  }\n\n  //Returns\n  function computeClustersLinkCounts(links) {\n    let dClusterLinks = new Map(),\n      clusterLinks = [];\n\n    links.forEach(function (l) {\n      let key = getLinkKey(l),\n        count;\n      if (dClusterLinks.has(key)) {\n        count = dClusterLinks.get(key);\n      } else {\n        count = 0;\n      }\n      count += 1;\n      dClusterLinks.set(key, count);\n    });\n\n    dClusterLinks.forEach(function (value, key) {\n      let source, target;\n      source = key.split(\"~\")[0];\n      target = key.split(\"~\")[1];\n      if (source !== undefined && target !== undefined) {\n        clusterLinks.push({\n          source: source,\n          target: target,\n          count: value,\n        });\n      }\n    });\n    return clusterLinks;\n  }\n\n  //Returns the metagraph of the clusters\n  function getGroupsGraph() {\n    let gnodes = [],\n      glinks = [],\n      // edges = [],\n      dNodes = new Map(),\n      // totalSize = 0,\n      c,\n      i,\n      cc,\n      clustersCounts,\n      clustersLinks;\n\n    clustersCounts = computeClustersNodeCounts(nodes);\n    clustersLinks = computeClustersLinkCounts(links);\n\n    for (c of clustersCounts.keys()) {\n      cc = clustersCounts.get(c);\n      gnodes.push({\n        id: c,\n        size: cc.count,\n        r: Math.sqrt(cc.sumforceNodeSize / Math.PI),\n      }); // Uses approx meta-node size\n      dNodes.set(c, i);\n      // totalSize += size;\n    }\n\n    clustersLinks.forEach(function (l) {\n      let source = dNodes.get(l.source),\n        target = dNodes.get(l.target);\n      if (source !== undefined && target !== undefined) {\n        glinks.push({\n          source: source,\n          target: target,\n          count: l.count,\n        });\n      }\n    });\n\n    return { nodes: gnodes, links: glinks };\n  }\n\n  function getGroupsTree() {\n    let children = [],\n      c,\n      cc,\n      clustersCounts;\n\n    clustersCounts = computeClustersNodeCounts(force.nodes());\n\n    for (c of clustersCounts.keys()) {\n      cc = clustersCounts.get(c);\n      children.push({ id: c, size: cc.count });\n    }\n    return { id: \"clustersTree\", children: children };\n  }\n\n  function getFocisFromTemplate() {\n    //compute foci\n    foci.none = { x: 0, y: 0 };\n    templateNodes.forEach(function (d) {\n      if (template === \"treemap\") {\n        foci[d.data.id] = {\n          x: d.x0 + (d.x1 - d.x0) / 2 - offset[0],\n          y: d.y0 + (d.y1 - d.y0) / 2 - offset[1],\n        };\n      } else {\n        foci[d.id] = {\n          x: d.x - offset[0],\n          y: d.y - offset[1],\n        };\n      }\n    });\n    return foci;\n  }\n\n  function initializeWithTreemap() {\n    let treemap = d3.treemap().size(force.size());\n\n    tree = d3\n      .hierarchy(getGroupsTree())\n      .sum(function (d) {\n        return d.size;\n      })\n      .sort(function (a, b) {\n        return b.height - a.height || b.value - a.value;\n      });\n\n    templateNodes = treemap(tree).leaves();\n    getFocisFromTemplate();\n  }\n\n  function checkLinksAsObjects() {\n    // Check if links come in the format of indexes instead of objects\n    let linkCount = 0;\n    if (nodes.length === 0) return;\n\n    links.forEach(function (link) {\n      let source, target;\n      if (!nodes) return;\n      source = link.source;\n      target = link.target;\n      if (typeof link.source !== \"object\") source = nodes[link.source];\n      if (typeof link.target !== \"object\") target = nodes[link.target];\n      if (source === undefined || target === undefined) {\n        // console.error(link);\n        throw Error(\n          \"Error setting links, couldnt find nodes for a link (see it on the console)\"\n        );\n      }\n      link.source = source;\n      link.target = target;\n      link.index = linkCount++;\n    });\n  }\n\n  function initializeWithForce() {\n    let net;\n\n    if (!nodes || !nodes.length) {\n      return;\n    }\n\n    if (nodes && nodes.length > 0) {\n      if (groupBy(nodes[0]) === undefined) {\n        throw Error(\n          \"Couldnt find the grouping attribute for the nodes. Make sure to set it up with forceInABox.groupBy('clusterAttr') before calling .links()\"\n        );\n      }\n    }\n\n    checkLinksAsObjects();\n\n    net = getGroupsGraph();\n    templateForce = d3\n      .forceSimulation(net.nodes)\n      .force(\"x\", d3.forceX(size[0] / 2).strength(0.1))\n      .force(\"y\", d3.forceY(size[1] / 2).strength(0.1))\n      .force(\n        \"collide\",\n        d3\n          .forceCollide(function (d) {\n            return d.r;\n          })\n          .iterations(4)\n      )\n      .force(\"charge\", d3.forceManyBody().strength(forceCharge))\n      .force(\n        \"links\",\n        d3\n          .forceLink(net.nodes.length ? net.links : [])\n          .distance(forceLinkDistance)\n          .strength(forceLinkStrength)\n      );\n\n    // console.log(\"Initialize with force \", templateForce.nodes().length, \" \", templateForce.force(\"links\").links().length);\n\n    // let i = 0;\n    // while (i++ < 500) templateForce.tick();\n\n    templateNodes = templateForce.nodes();\n\n    getFocisFromTemplate();\n  }\n\n  function drawTreemap(container) {\n    // Delete the circle Template if it exists\n    container.selectAll(\"circle.cell\").remove();\n    container.selectAll(\"line.cell\").remove();\n    container\n      .selectAll(\"rect.cell\")\n      .data(templateNodes)\n      .enter()\n      .append(\"svg:rect\")\n      .attr(\"class\", \"cell\")\n      .attr(\"x\", function (d) {\n        return d.x0;\n      })\n      .attr(\"y\", function (d) {\n        return d.y0;\n      })\n      .attr(\"width\", function (d) {\n        return d.x1 - d.x0;\n      })\n      .attr(\"height\", function (d) {\n        return d.y1 - d.y0;\n      });\n  }\n\n  function drawGraph(container) {\n    // Delete the treemap if any\n    container.selectAll(\"rect.cell\").remove();\n    let templateLinksSel = container\n      .selectAll(\"line.cell\")\n      .data(templateForce.force(\"links\").links());\n    templateLinksSel\n      .enter()\n      .append(\"line\")\n      .attr(\"class\", \"cell\")\n      .merge(templateLinksSel)\n      .attr(\"x2\", function (d) {\n        return d.source.x;\n      })\n      .attr(\"y2\", function (d) {\n        return d.source.y;\n      })\n      .attr(\"x1\", function (d) {\n        return d.target.x;\n      })\n      .attr(\"y1\", function (d) {\n        return d.target.y;\n      })\n      .style(\"stroke-width\", \"1px\")\n      .style(\"stroke-opacity\", \"0.5\");\n\n    let templateNodesSel = container\n      .selectAll(\"circle.cell\")\n      .data(templateForce.nodes());\n    templateNodesSel\n      .enter()\n      .append(\"svg:circle\")\n      .attr(\"class\", \"cell\")\n      .merge(templateNodesSel)\n      .attr(\"cx\", function (d) {\n        return d.x;\n      })\n      .attr(\"cy\", function (d) {\n        return d.y;\n      })\n      .attr(\"r\", function (d) {\n        return d.r;\n      });\n\n    templateForce\n      .on(\"tick\", () => {\n        // console.log(\"tick\");\n        drawGraph(container);\n      })\n      .restart();\n\n    templateNodesSel.exit().remove();\n    templateLinksSel.exit().remove();\n  }\n\n  force.drawTemplate = function (container) {\n    // showingTemplate = true;\n    if (template === \"treemap\") {\n      drawTreemap(container);\n    } else {\n      drawGraph(container);\n    }\n    return force;\n  };\n\n  //Backwards compatibility\n  force.drawTreemap = force.drawTemplate;\n\n  force.deleteTemplate = function (container) {\n    // showingTemplate = false;\n    container.selectAll(\".cell\").remove();\n\n    if (templateForce) {\n      templateForce.on(\"tick\", null).restart();\n    }\n\n    return force;\n  };\n\n  force.template = function (x) {\n    if (!arguments.length) return template;\n    template = x;\n    initialize();\n    return force;\n  };\n\n  force.groupBy = function (x) {\n    if (!arguments.length) return groupBy;\n    if (typeof x === \"string\") {\n      groupBy = function (d) {\n        return d[x];\n      };\n      return force;\n    }\n    groupBy = x;\n    return force;\n  };\n\n  force.enableGrouping = function (x) {\n    if (!arguments.length) return enableGrouping;\n    enableGrouping = x;\n    // update();\n    return force;\n  };\n\n  force.strength = function (x) {\n    if (!arguments.length) return strength;\n    strength = x;\n    return force;\n  };\n\n  force.getLinkStrength = function (e) {\n    if (enableGrouping) {\n      if (groupBy(e.source) === groupBy(e.target)) {\n        if (typeof linkStrengthIntraCluster === \"function\") {\n          return linkStrengthIntraCluster(e);\n        } else {\n          return linkStrengthIntraCluster;\n        }\n      } else {\n        if (typeof linkStrengthInterCluster === \"function\") {\n          return linkStrengthInterCluster(e);\n        } else {\n          return linkStrengthInterCluster;\n        }\n      }\n    } else {\n      // Not grouping return the intracluster\n      if (typeof linkStrengthIntraCluster === \"function\") {\n        return linkStrengthIntraCluster(e);\n      } else {\n        return linkStrengthIntraCluster;\n      }\n    }\n  };\n\n  force.id = function (_) {\n    return arguments.length ? ((id = _), force) : id;\n  };\n\n  force.size = function (_) {\n    return arguments.length ? ((size = _), force) : size;\n  };\n\n  force.linkStrengthInterCluster = function (_) {\n    return arguments.length\n      ? ((linkStrengthInterCluster = _), force)\n      : linkStrengthInterCluster;\n  };\n\n  force.linkStrengthIntraCluster = function (_) {\n    return arguments.length\n      ? ((linkStrengthIntraCluster = _), force)\n      : linkStrengthIntraCluster;\n  };\n\n  force.nodes = function (_) {\n    return arguments.length ? ((nodes = _), force) : nodes;\n  };\n\n  force.links = function (_) {\n    if (!arguments.length) return links;\n    if (_ === null) links = [];\n    else links = _;\n    initialize();\n    return force;\n  };\n\n  force.forceNodeSize = function (_) {\n    return arguments.length\n      ? ((forceNodeSize = typeof _ === \"function\" ? _ : constant(+_)),\n        initialize(),\n        force)\n      : forceNodeSize;\n  };\n\n  // Legacy support\n  force.nodeSize = force.forceNodeSize;\n\n  force.forceCharge = function (_) {\n    return arguments.length\n      ? ((forceCharge = typeof _ === \"function\" ? _ : constant(+_)),\n        initialize(),\n        force)\n      : forceCharge;\n  };\n\n  force.forceLinkDistance = function (_) {\n    return arguments.length\n      ? ((forceLinkDistance = typeof _ === \"function\" ? _ : constant(+_)),\n        initialize(),\n        force)\n      : forceLinkDistance;\n  };\n\n  force.forceLinkStrength = function (_) {\n    return arguments.length\n      ? ((forceLinkStrength = typeof _ === \"function\" ? _ : constant(+_)),\n        initialize(),\n        force)\n      : forceLinkStrength;\n  };\n\n  force.offset = function (_) {\n    return arguments.length\n      ? ((offset = typeof _ === \"function\" ? _ : constant(+_)), force)\n      : offset;\n  };\n\n  force.getFocis = getFocisFromTemplate;\n\n  return force;\n}\n\n// module.exports = forceInABox;\n\nexport { forceInABox as default };\n","// https://observablehq.com/@john-guerra/d3-force-boundary v0.0.2 Copyright 2022 John Alexis Guerra Gómez\nfunction constant(x) {\n  return function() {\n    return x;\n  };\n}\n\nfunction forceBoundary(x0, y0, x1, y1) {\n  var strength = constant(0.1),\n      hardBoundary = true,\n      border = constant( Math.min((x1 - x0)/2, (y1 - y0)/2) ),\n      nodes,\n      strengthsX,\n      strengthsY,\n      x0z, x1z,\n      y0z, y1z,\n      borderz,\n      halfX, halfY;\n\n  if (typeof x0 !== \"function\") x0 = constant(x0 == null ? -100 : +x0);\n  if (typeof x1 !== \"function\") x1 = constant(x1 == null ? 100 : +x1);\n  if (typeof y0 !== \"function\") y0 = constant(y0 == null ? -100 : +y0);\n  if (typeof y1 !== \"function\") y1 = constant(y1 == null ? 100 : +y1);\n\n  function getVx(halfX, x, strengthX, border, alpha) {\n    return (halfX - x) *  Math.min(2, Math.abs( halfX - x) / halfX) * strengthX * alpha;\n  }\n\n  function force(alpha) {\n    for (var i = 0, n = nodes.length, node; i < n; ++i) {\n      node = nodes[i];\n      // debugger;\n      if ((node.x < (x0z[i] + borderz[i]) || node.x > (x1z[i] - borderz[i])) ||\n        (node.y < (y0z[i] + borderz[i]) || node.y > (y1z[i] - borderz[i]))) {\n        node.vx += getVx(halfX[i], node.x, strengthsX[i], borderz[i], alpha);\n        node.vy += getVx(halfY[i], node.y, strengthsY[i], borderz[i], alpha);\n      } else if (node.y < (y0z[i] + borderz[i]) || node.y > (y1z[i] - borderz[i])) ;\n\n      if (hardBoundary) {\n        if (node.x >= x1z[i]) node.vx += x1z[i] - node.x;\n        if (node.x <= x0z[i]) node.vx += x0z[i] - node.x;\n        if (node.y >= y1z[i]) node.vy += y1z[i] - node.y;\n        if (node.y <= y0z[i]) node.vy += y0z[i] - node.y;\n      }\n    }\n  }\n\n  function initialize() {\n    if (!nodes) return;\n    var i, n = nodes.length;\n    strengthsX = new Array(n);\n    strengthsY = new Array(n);\n    x0z = new Array(n);\n    y0z = new Array(n);\n    x1z = new Array(n);\n    y1z = new Array(n);\n    halfY = new Array(n);\n    halfX = new Array(n);\n    borderz = new Array(n);\n\n    for (i = 0; i < n; ++i) {\n      strengthsX[i] = (isNaN(x0z[i] = +x0(nodes[i], i, nodes)) ||\n        isNaN(x1z[i] = +x1(nodes[i], i, nodes))) ? 0 : +strength(nodes[i], i, nodes);\n      strengthsY[i] = (isNaN(y0z[i] = +y0(nodes[i], i, nodes)) ||\n        isNaN(y1z[i] = +y1(nodes[i], i, nodes))) ? 0 : +strength(nodes[i], i, nodes);\n      halfX[i] = x0z[i] + (x1z[i] - x0z[i])/2,\n      halfY[i] = y0z[i] + (y1z[i] - y0z[i])/2;\n      borderz[i] = +border(nodes[i], i, nodes);\n    }\n  }\n\n  force.initialize = function(_) {\n    nodes = _;\n    initialize();\n  };\n\n  force.x0 = function(_) {\n    return arguments.length ? (x0 = typeof _ === \"function\" ? _ : constant(+_), initialize(), force) : x0;\n  };\n\n  force.x1 = function(_) {\n    return arguments.length ? (x1 = typeof _ === \"function\" ? _ : constant(+_), initialize(), force) : x1;\n  };\n\n  force.y0 = function(_) {\n    return arguments.length ? (y0 = typeof _ === \"function\" ? _ : constant(+_), initialize(), force) : y0;\n  };\n\n  force.y1 = function(_) {\n    return arguments.length ? (y1 = typeof _ === \"function\" ? _ : constant(+_), initialize(), force) : y1;\n  };\n\n  force.strength = function(_) {\n    return arguments.length ? (strength = typeof _ === \"function\" ? _ : constant(+_), initialize(), force) : strength;\n  };\n\n  force.border = function(_) {\n    return arguments.length ? (border = typeof _ === \"function\" ? _ : constant(+_), initialize(), force) : border;\n  };\n\n  force.hardBoundary = function(_) {\n    return arguments.length ? (hardBoundary = _, force) : hardBoundary;\n  };\n\n  return force;\n}\n\nexport default forceBoundary;\n","import * as d3 from \"d3\";\n\n/**\n * forceTransport - A D3 force that transports nodes to stay within bounds\n * by sorting them and distributing them evenly within the extent.\n *\n * Original source: https://observablehq.com/d/21d2053b3bc85bce\n * Implementation discussion: https://github.com/d3/d3-force/issues/89\n *\n * @param {Array} extent - [[x0, y0], [x1, y1]] bounding box\n * @param {number} margin - Margin from the extent edges (default: 0)\n * @param {number} strength - Force strength multiplier (default: 1)\n * @returns {Function} D3 force function\n */\nexport function forceTransport(extent, margin, strength) {\n  let nodes;\n\n  if (extent === undefined)\n    extent = [\n      [0, 0],\n      [960, 500],\n    ];\n  if (margin === undefined) margin = 0;\n  if (strength === undefined) strength = 1;\n\n  const X = d3\n    .scaleLinear()\n    .range([extent[0][0] + margin, extent[1][0] - margin]);\n  const Y = d3\n    .scaleLinear()\n    .range([extent[0][1] + margin, extent[1][1] - margin]);\n\n  let indices = [];\n\n  function force(alpha) {\n    if (indices.length !== nodes.length) {\n      indices = Uint32Array.from(d3.range(nodes.length));\n      X.domain([-1, nodes.length]);\n      Y.domain([-1, nodes.length]);\n    }\n\n    // Sort nodes by x position and distribute them evenly\n    indices.sort((i, j) => nodes[i].x - nodes[j].x);\n    for (let i = 0; i < nodes.length; ++i) {\n      const node = nodes[indices[i]];\n      const target = X(i);\n      node.vx += (target - node.x) * strength;\n    }\n\n    // Sort nodes by y position and distribute them evenly\n    indices.sort((i, j) => nodes[i].y - nodes[j].y);\n    for (let i = 0; i < nodes.length; ++i) {\n      const node = nodes[indices[i]];\n      const target = Y(i);\n      node.vy += (target - node.y) * strength * alpha;\n    }\n  }\n\n  force.initialize = function (_) {\n    nodes = _;\n  };\n\n  force.extent = function (_) {\n    return arguments.length ? ((extent = _), force) : extent;\n  };\n\n  force.margin = function (_) {\n    return arguments.length ? ((margin = +_), force) : margin;\n  };\n\n  force.strength = function (_) {\n    return arguments.length ? ((strength = +_), force) : strength;\n  };\n\n  return force;\n}\n","/**\n * forceExtent - A D3 force that clamps nodes to stay within bounds\n *\n * Original source: https://observablehq.com/d/21d2053b3bc85bce\n * Implementation discussion: https://github.com/d3/d3-force/issues/89\n *\n * @param {Array} extent - [[x0, y0], [x1, y1]] bounding box\n * @returns {Function} D3 force function\n */\nexport function forceExtent(extent) {\n  let nodes;\n\n  if (extent === undefined)\n    extent = [\n      [0, 0],\n      [960, 500],\n    ];\n\n  function clamp(x, min, max) {\n    return Math.max(min, Math.min(max, x));\n  }\n\n  function force() {\n    for (let i = 0; i < nodes.length; ++i) {\n      const node = nodes[i];\n      const r = node.radius || 0;\n      node.x = clamp(node.x, extent[0][0] - r, extent[1][0] + r);\n      node.y = clamp(node.y, extent[0][1] - r, extent[1][1] + r);\n    }\n  }\n\n  force.initialize = function (_) {\n    nodes = _;\n  };\n\n  force.extent = function (_) {\n    return arguments.length ? ((extent = _), force) : extent;\n  };\n\n  return force;\n}\n","/**\n * Force Edge Bundling\n *\n * Bundles edges together using a force simulation.\n *\n * Original source: https://observablehq.com/@john-guerra/force-edge-bundling\n * Adapted from: https://github.com/upphiminn/d3.ForceBundle\n *\n * LICENSE: GNU General Public License v2\n * Copyright (C) John Alexis Guerra Gómez\n *\n * This is an adaptation of the Force Directed Edge Bundling d3 plugin to work\n * with ES6 and modern D3, with bug fixes from:\n * https://github.com/upphiminn/d3.ForceBundle/pull/11\n *\n * Note: Make sure no two nodes have the same x,y coordinates\n */\n\n/**\n * ForceEdgeBundling - Core edge bundling algorithm\n * @returns {Function} Edge bundling force function\n */\nexport function ForceEdgeBundling() {\n  let data_nodes = {}, // {'nodeid':{'x':,'y':},..}\n    data_edges = [], // [{'source':'nodeid1', 'target':'nodeid2'},..]\n    compatibility_list_for_edge = [],\n    subdivision_points_for_edge = [],\n    K = 0.1, // global bundling constant controlling edge stiffness\n    S_initial = 0.1, // init. distance to move points\n    P_initial = 1, // init. subdivision number\n    P_rate = 2, // subdivision rate increase\n    C = 6, // number of cycles to perform\n    I_initial = 90, // init. number of iterations for cycle\n    I_rate = 0.6666667, // rate at which iteration number decreases i.e. 2/3\n    compatibility_threshold = 0.6,\n    eps = 1e-6,\n    P = null;\n\n  /*** Geometry Helper Methods ***/\n  function vector_dot_product(p, q) {\n    return p.x * q.x + p.y * q.y;\n  }\n\n  function edge_as_vector(P) {\n    return {\n      x: data_nodes[P.target].x - data_nodes[P.source].x,\n      y: data_nodes[P.target].y - data_nodes[P.source].y,\n    };\n  }\n\n  function edge_length(e) {\n    // handling nodes that are on the same location, so that K/edge_length != Inf\n    if (\n      Math.abs(data_nodes[e.source].x - data_nodes[e.target].x) < eps &&\n      Math.abs(data_nodes[e.source].y - data_nodes[e.target].y) < eps\n    ) {\n      return eps;\n    }\n\n    return Math.sqrt(\n      Math.pow(data_nodes[e.source].x - data_nodes[e.target].x, 2) +\n        Math.pow(data_nodes[e.source].y - data_nodes[e.target].y, 2)\n    );\n  }\n\n  function custom_edge_length(e) {\n    return Math.sqrt(\n      Math.pow(e.source.x - e.target.x, 2) +\n        Math.pow(e.source.y - e.target.y, 2)\n    );\n  }\n\n  function edge_midpoint(e) {\n    let middle_x = (data_nodes[e.source].x + data_nodes[e.target].x) / 2.0;\n    let middle_y = (data_nodes[e.source].y + data_nodes[e.target].y) / 2.0;\n\n    return {\n      x: middle_x,\n      y: middle_y,\n    };\n  }\n\n  function compute_divided_edge_length(e_idx) {\n    let length = 0;\n\n    for (let i = 1; i < subdivision_points_for_edge[e_idx].length; i++) {\n      let segment_length = euclidean_distance(\n        subdivision_points_for_edge[e_idx][i],\n        subdivision_points_for_edge[e_idx][i - 1]\n      );\n      length += segment_length;\n    }\n\n    return length;\n  }\n\n  function euclidean_distance(p, q) {\n    return Math.sqrt(Math.pow(p.x - q.x, 2) + Math.pow(p.y - q.y, 2));\n  }\n\n  function project_point_on_line(p, Q) {\n    let L = Math.sqrt(\n      (Q.target.x - Q.source.x) * (Q.target.x - Q.source.x) +\n        (Q.target.y - Q.source.y) * (Q.target.y - Q.source.y)\n    );\n    let r =\n      ((Q.source.y - p.y) * (Q.source.y - Q.target.y) -\n        (Q.source.x - p.x) * (Q.target.x - Q.source.x)) /\n      (L * L);\n\n    return {\n      x: Q.source.x + r * (Q.target.x - Q.source.x),\n      y: Q.source.y + r * (Q.target.y - Q.source.y),\n    };\n  }\n\n  /*** Initialization Methods ***/\n  function initialize_edge_subdivisions() {\n    for (let i = 0; i < data_edges.length; i++) {\n      if (P_initial === 1) {\n        subdivision_points_for_edge[i] = []; //0 subdivisions\n      } else {\n        subdivision_points_for_edge[i] = [];\n        subdivision_points_for_edge[i].push(data_nodes[data_edges[i].source]);\n        subdivision_points_for_edge[i].push(data_nodes[data_edges[i].target]);\n      }\n    }\n  }\n\n  function initialize_compatibility_lists() {\n    for (let i = 0; i < data_edges.length; i++) {\n      compatibility_list_for_edge[i] = []; //0 compatible edges.\n    }\n  }\n\n  function filter_self_loops(edgelist) {\n    let filtered_edge_list = [];\n\n    for (let e = 0; e < edgelist.length; e++) {\n      if (\n        data_nodes[edgelist[e].source].x != data_nodes[edgelist[e].target].x ||\n        data_nodes[edgelist[e].source].y != data_nodes[edgelist[e].target].y\n      ) {\n        //or smaller than eps\n        filtered_edge_list.push(edgelist[e]);\n      }\n    }\n\n    return filtered_edge_list;\n  }\n\n  /*** Force Calculation Methods ***/\n  function apply_spring_force(e_idx, i, kP) {\n    let prev = subdivision_points_for_edge[e_idx][i - 1];\n    let next = subdivision_points_for_edge[e_idx][i + 1];\n    let crnt = subdivision_points_for_edge[e_idx][i];\n    let x = prev.x - crnt.x + next.x - crnt.x;\n    let y = prev.y - crnt.y + next.y - crnt.y;\n\n    x *= kP;\n    y *= kP;\n\n    return {\n      x: x,\n      y: y,\n    };\n  }\n\n  function apply_electrostatic_force(e_idx, i) {\n    let sum_of_forces = {\n      x: 0,\n      y: 0,\n    };\n    let compatible_edges_list = compatibility_list_for_edge[e_idx];\n\n    for (let oe = 0; oe < compatible_edges_list.length; oe++) {\n      let force = {\n        x:\n          subdivision_points_for_edge[compatible_edges_list[oe]][i].x -\n          subdivision_points_for_edge[e_idx][i].x,\n        y:\n          subdivision_points_for_edge[compatible_edges_list[oe]][i].y -\n          subdivision_points_for_edge[e_idx][i].y,\n      };\n\n      if (Math.abs(force.x) > eps || Math.abs(force.y) > eps) {\n        let diff =\n          1 /\n          Math.pow(\n            custom_edge_length({\n              source: subdivision_points_for_edge[compatible_edges_list[oe]][i],\n              target: subdivision_points_for_edge[e_idx][i],\n            }),\n            1\n          );\n\n        sum_of_forces.x += force.x * diff;\n        sum_of_forces.y += force.y * diff;\n      }\n    }\n\n    return sum_of_forces;\n  }\n\n  function apply_resulting_forces_on_subdivision_points(e_idx, P, S) {\n    let kP = K / (edge_length(data_edges[e_idx]) * (P + 1)); // kP=K/|P|(number of segments), where |P| is the initial length of edge P.\n    // (length * (num of sub division pts - 1))\n    let resulting_forces_for_subdivision_points = [\n      {\n        x: 0,\n        y: 0,\n      },\n    ];\n\n    for (let i = 1; i < P + 1; i++) {\n      // exclude initial end points of the edge 0 and P+1\n      let resulting_force = {\n        x: 0,\n        y: 0,\n      };\n\n      let spring_force = apply_spring_force(e_idx, i, kP);\n      let electrostatic_force = apply_electrostatic_force(e_idx, i, S);\n\n      resulting_force.x = S * (spring_force.x + electrostatic_force.x);\n      resulting_force.y = S * (spring_force.y + electrostatic_force.y);\n\n      resulting_forces_for_subdivision_points.push(resulting_force);\n    }\n\n    resulting_forces_for_subdivision_points.push({\n      x: 0,\n      y: 0,\n    });\n\n    return resulting_forces_for_subdivision_points;\n  }\n\n  /*** Edge Division Calculation Methods ***/\n  function update_edge_divisions(P) {\n    for (let e_idx = 0; e_idx < data_edges.length; e_idx++) {\n      if (P === 1) {\n        subdivision_points_for_edge[e_idx].push(\n          data_nodes[data_edges[e_idx].source]\n        ); // source\n        subdivision_points_for_edge[e_idx].push(\n          edge_midpoint(data_edges[e_idx])\n        ); // mid point\n        subdivision_points_for_edge[e_idx].push(\n          data_nodes[data_edges[e_idx].target]\n        ); // target\n      } else {\n        let divided_edge_length = compute_divided_edge_length(e_idx);\n        let segment_length = divided_edge_length / (P + 1);\n        let current_segment_length = segment_length;\n        let new_subdivision_points = [];\n        new_subdivision_points.push(data_nodes[data_edges[e_idx].source]); //source\n\n        for (let i = 1; i < subdivision_points_for_edge[e_idx].length; i++) {\n          let old_segment_length = euclidean_distance(\n            subdivision_points_for_edge[e_idx][i],\n            subdivision_points_for_edge[e_idx][i - 1]\n          );\n\n          while (old_segment_length > current_segment_length) {\n            let percent_position = current_segment_length / old_segment_length;\n            let new_subdivision_point_x =\n              subdivision_points_for_edge[e_idx][i - 1].x;\n            let new_subdivision_point_y =\n              subdivision_points_for_edge[e_idx][i - 1].y;\n\n            new_subdivision_point_x +=\n              percent_position *\n              (subdivision_points_for_edge[e_idx][i].x -\n                subdivision_points_for_edge[e_idx][i - 1].x);\n            new_subdivision_point_y +=\n              percent_position *\n              (subdivision_points_for_edge[e_idx][i].y -\n                subdivision_points_for_edge[e_idx][i - 1].y);\n            new_subdivision_points.push({\n              x: new_subdivision_point_x,\n              y: new_subdivision_point_y,\n            });\n\n            old_segment_length -= current_segment_length;\n            current_segment_length = segment_length;\n          }\n          current_segment_length -= old_segment_length;\n        }\n        new_subdivision_points.push(data_nodes[data_edges[e_idx].target]); //target\n        subdivision_points_for_edge[e_idx] = new_subdivision_points;\n      }\n    }\n  }\n\n  /*** Edge compatibility measures ***/\n  function angle_compatibility(P, Q) {\n    return Math.abs(\n      vector_dot_product(edge_as_vector(P), edge_as_vector(Q)) /\n        (edge_length(P) * edge_length(Q))\n    );\n  }\n\n  function scale_compatibility(P, Q) {\n    let lavg = (edge_length(P) + edge_length(Q)) / 2.0;\n    return (\n      2.0 /\n      (lavg / Math.min(edge_length(P), edge_length(Q)) +\n        Math.max(edge_length(P), edge_length(Q)) / lavg)\n    );\n  }\n\n  function position_compatibility(P, Q) {\n    let lavg = (edge_length(P) + edge_length(Q)) / 2.0;\n    let midP = {\n      x: (data_nodes[P.source].x + data_nodes[P.target].x) / 2.0,\n      y: (data_nodes[P.source].y + data_nodes[P.target].y) / 2.0,\n    };\n    let midQ = {\n      x: (data_nodes[Q.source].x + data_nodes[Q.target].x) / 2.0,\n      y: (data_nodes[Q.source].y + data_nodes[Q.target].y) / 2.0,\n    };\n\n    return lavg / (lavg + euclidean_distance(midP, midQ));\n  }\n\n  function edge_visibility(P, Q) {\n    let I0 = project_point_on_line(data_nodes[Q.source], {\n      source: data_nodes[P.source],\n      target: data_nodes[P.target],\n    });\n    let I1 = project_point_on_line(data_nodes[Q.target], {\n      source: data_nodes[P.source],\n      target: data_nodes[P.target],\n    }); //send actual edge points positions\n    let midI = {\n      x: (I0.x + I1.x) / 2.0,\n      y: (I0.y + I1.y) / 2.0,\n    };\n    let midP = {\n      x: (data_nodes[P.source].x + data_nodes[P.target].x) / 2.0,\n      y: (data_nodes[P.source].y + data_nodes[P.target].y) / 2.0,\n    };\n\n    return Math.max(\n      0,\n      1 - (2 * euclidean_distance(midP, midI)) / euclidean_distance(I0, I1)\n    );\n  }\n\n  function visibility_compatibility(P, Q) {\n    return Math.min(edge_visibility(P, Q), edge_visibility(Q, P));\n  }\n\n  function compatibility_score(P, Q) {\n    return (\n      angle_compatibility(P, Q) *\n      scale_compatibility(P, Q) *\n      position_compatibility(P, Q) *\n      visibility_compatibility(P, Q)\n    );\n  }\n\n  function are_compatible(P, Q) {\n    return compatibility_score(P, Q) >= compatibility_threshold;\n  }\n\n  function compute_compatibility_lists() {\n    for (let e = 0; e < data_edges.length - 1; e++) {\n      for (let oe = e + 1; oe < data_edges.length; oe++) {\n        // don't want any duplicates\n        if (are_compatible(data_edges[e], data_edges[oe])) {\n          compatibility_list_for_edge[e].push(oe);\n          compatibility_list_for_edge[oe].push(e);\n        }\n      }\n    }\n  }\n\n  /*** Main Bundling Loop Methods ***/\n  let forcebundle = function () {\n    let S = S_initial;\n    let I = I_initial;\n    let P = P_initial;\n\n    initialize_edge_subdivisions();\n    initialize_compatibility_lists();\n    update_edge_divisions(P);\n    compute_compatibility_lists();\n\n    for (let cycle = 0; cycle < C; cycle++) {\n      for (let iteration = 0; iteration < I; iteration++) {\n        let forces = [];\n        for (let edge = 0; edge < data_edges.length; edge++) {\n          forces[edge] = apply_resulting_forces_on_subdivision_points(\n            edge,\n            P,\n            S\n          );\n        }\n        for (let e = 0; e < data_edges.length; e++) {\n          for (let i = 0; i < P + 1; i++) {\n            subdivision_points_for_edge[e][i].x += forces[e][i].x;\n            subdivision_points_for_edge[e][i].y += forces[e][i].y;\n          }\n        }\n      }\n      // prepare for next cycle\n      S = S / 2;\n      P = P * P_rate;\n      I = I_rate * I;\n\n      update_edge_divisions(P);\n    }\n    return subdivision_points_for_edge;\n  };\n\n  /*** Getters/Setters Methods ***/\n  forcebundle.nodes = function (nl) {\n    if (arguments.length === 0) {\n      return data_nodes;\n    } else {\n      data_nodes = nl;\n    }\n\n    return forcebundle;\n  };\n\n  forcebundle.edges = function (ll) {\n    if (arguments.length === 0) {\n      return data_edges;\n    } else {\n      data_edges = filter_self_loops(ll); //remove edges to from to the same point\n    }\n\n    return forcebundle;\n  };\n\n  forcebundle.bundling_stiffness = function (k) {\n    if (arguments.length === 0) {\n      return K;\n    } else {\n      K = k;\n    }\n\n    return forcebundle;\n  };\n\n  forcebundle.step_size = function (step) {\n    if (arguments.length === 0) {\n      return S_initial;\n    } else {\n      S_initial = step;\n    }\n\n    return forcebundle;\n  };\n\n  forcebundle.cycles = function (c) {\n    if (arguments.length === 0) {\n      return C;\n    } else {\n      C = c;\n    }\n\n    return forcebundle;\n  };\n\n  forcebundle.iterations = function (i) {\n    if (arguments.length === 0) {\n      return I_initial;\n    } else {\n      I_initial = i;\n    }\n\n    return forcebundle;\n  };\n\n  forcebundle.iterations_rate = function (i) {\n    if (arguments.length === 0) {\n      return I_rate;\n    } else {\n      I_rate = i;\n    }\n\n    return forcebundle;\n  };\n\n  forcebundle.subdivision_points_seed = function (p) {\n    if (arguments.length == 0) {\n      return P;\n    } else {\n      P = p;\n    }\n\n    return forcebundle;\n  };\n\n  forcebundle.subdivision_rate = function (r) {\n    if (arguments.length === 0) {\n      return P_rate;\n    } else {\n      P_rate = r;\n    }\n\n    return forcebundle;\n  };\n\n  forcebundle.compatibility_threshold = function (t) {\n    if (arguments.length === 0) {\n      return compatibility_threshold;\n    } else {\n      compatibility_threshold = t;\n    }\n\n    return forcebundle;\n  };\n\n  return forcebundle;\n}\n\n/**\n * edgeBundling - Convenience wrapper for ForceEdgeBundling\n *\n * @param {Object} data - {nodes, links} where nodes have x,y coords\n * @param {Object} options - Configuration options\n * @returns {Object} Edge bundling instance with update() method\n */\nexport function edgeBundling(\n  {\n    nodes, // Array of nodes including x and y coords e.g. [{id: \"a\", x: 10, y:10}, ...]\n    links, // Array of links in D3 forceSimulation format e.g. [{source: \"a\", target: \"b\"}, ...]\n  },\n  {\n    id = (d) => d.id,\n    pathAttr = \"path\", // name of the attribute to save the paths\n    bundling_stiffness = 0.1, // global bundling constant controlling edge stiffness\n    step_size = 0.1, // init. distance to move points\n    subdivision_rate = 2, // subdivision rate increase\n    cycles = 6, // number of cycles to perform\n    iterations = 90, // init. number of iterations for cycle\n    iterations_rate = 0.6666667, // rate at which iteration number decreases i.e. 2/3\n    compatibility_threshold = 0.6, //  \"which pairs of edges should be considered compatible (default is set to 0.6, 60% compatiblity)\"\n  } = {}\n) {\n  // The library wants the links as the index positions in the nodes array\n  const dNodes = new Map(nodes.map((d, i) => [id(d), i]));\n  const linksIs = links.map((l) => ({\n    source: dNodes.get(typeof l.source === \"object\" ? id(l.source) : l.source),\n    target: dNodes.get(typeof l.target === \"object\" ? id(l.target) : l.target),\n  }));\n\n  const edgeBundling = ForceEdgeBundling()\n    .nodes(nodes)\n    .edges(linksIs)\n    .bundling_stiffness(bundling_stiffness)\n    .step_size(step_size)\n    .subdivision_rate(subdivision_rate)\n    .cycles(cycles)\n    .iterations(iterations)\n    .iterations_rate(iterations_rate)\n    .compatibility_threshold(compatibility_threshold);\n\n  edgeBundling.update = () => {\n    const paths = edgeBundling();\n    links.map((l, i) => (l[pathAttr] = paths[i]));\n  };\n\n  edgeBundling.update();\n\n  return edgeBundling;\n}\n","/**\n * sample - Samples an array to limit the number of elements\n * Used for edge bundling to limit the number of links processed\n *\n * Original source: https://observablehq.com/@john-guerra/force-directed-graph\n * From 89207a2280891f15@1859.js lines 885-890\n *\n * @param {Array} array - Array to sample\n * @param {number} n - Maximum number of elements to return\n * @returns {Array} Sampled array\n */\nexport function sample(array, n) {\n  if (n >= array.length) return array;\n\n  return array.filter((d, i) => i % Math.floor(array.length / n) === 0);\n}\n","import * as d3 from \"d3\";\n\n/**\n * drag - Custom drag behavior that works with zoom transforms\n *\n * Original source: https://observablehq.com/@john-guerra/force-directed-graph\n * From 89207a2280891f15@1859.js lines 830-875\n *\n * @param {Object} simulation - D3 force simulation\n * @param {HTMLElement} node - DOM node (SVG or Canvas element)\n * @param {Object} opts - Options object with x, y scales and minDistanceForDrag\n * @returns {Function} D3 drag behavior\n */\nexport function drag(simulation, node, opts) {\n  function dragsubject(event) {\n    const transform = d3.zoomTransform(node);\n    let [x, y] = transform.invert([event.x, event.y]);\n    x = opts.x.invert(x);\n    y = opts.y.invert(y);\n    let subject = simulation.find(x, y);\n\n    let d = Math.hypot(x - subject.x, y - subject.y);\n\n    return d < opts.minDistanceForDrag\n      ? {\n          circle: subject,\n          x: transform.applyX(opts.x(subject.x)),\n          y: transform.applyY(opts.y(subject.y)),\n        }\n      : null;\n  }\n\n  function dragstarted(event) {\n    if (!event.active) simulation.alphaTarget(0.3).restart();\n    event.subject.circle.fx = event.subject.circle.x;\n    event.subject.circle.fy = event.subject.circle.y;\n  }\n\n  function dragged(event) {\n    const transform = d3.zoomTransform(node);\n    event.subject.circle.fx = opts.x.invert(transform.invertX(event.x));\n    event.subject.circle.fy = opts.y.invert(transform.invertY(event.y));\n  }\n\n  function dragended(event) {\n    if (!event.active) simulation.alphaTarget(0);\n    event.subject.circle.fx = null;\n    event.subject.circle.fy = null;\n  }\n\n  return d3\n    .drag()\n    .subject(dragsubject)\n    .on(\"start\", dragstarted)\n    .on(\"drag\", dragged)\n    .on(\"end\", dragended);\n}\n","import * as d3 from \"d3\";\n\n/**\n * computeAutoFit - Adjusts x/y scales to fit nodes in viewport\n * with optional aspect ratio preservation\n *\n * Original source: https://observablehq.com/@john-guerra/force-directed-graph\n * From 89207a2280891f15@1859.js lines 979-1022\n *\n * @param {Object} opts - Options object with nodes, x, y scales, width, height, autoFit, keepAspectRatio\n */\nexport function computeAutoFit(opts) {\n  if (opts.autoFit) {\n    const yExtent = d3.extent(opts.nodes, (d) => d.y);\n    const xExtent = d3.extent(opts.nodes, (d) => d.x);\n\n    opts.x.domain(d3.extent(opts.nodes, (d) => d.x));\n    opts.y.domain(d3.extent(opts.nodes, (d) => d.y));\n\n    if (opts.keepAspectRatio) {\n      const ratio = opts.width / opts.height;\n      const newRatio = (xExtent[1] - xExtent[0]) / (yExtent[1] - yExtent[0]);\n\n      if (newRatio < ratio) {\n        // Adjust x axis to fit\n        const d =\n          (opts.width / opts.height) * (yExtent[1] - yExtent[0]) -\n          (xExtent[1] - xExtent[0]);\n\n        opts.x.domain([xExtent[0] - d / 2, xExtent[1] + d / 2]);\n        opts.y.domain(yExtent);\n      } else {\n        // Adjust y axis to fit\n        const d =\n          (opts.height / opts.width) * (xExtent[1] - xExtent[0]) -\n          (yExtent[1] - yExtent[0]);\n\n        opts.y.domain([yExtent[0] - d / 2, yExtent[1] + d / 2]);\n        opts.x.domain(xExtent);\n      }\n    }\n  }\n}\n","/**\n * applyTransform - Applies zoom transform to node/link coordinates\n *\n * Original source: https://observablehq.com/@john-guerra/force-directed-graph\n * From 89207a2280891f15@1859.js lines 823-828\n *\n * @param {Object} d - Node or point with x, y coordinates\n * @param {Object} transform - D3 zoom transform\n * @param {Object} opts - Options object with x, y scales\n * @returns {Object} Transformed point with x, y\n */\nexport function applyTransform(d, transform, opts) {\n  const [x, y] = transform.apply([opts.x(d.x), opts.y(d.y)]);\n  return { ...d, x, y };\n}\n","// smart-labels v0.0.11 Copyright (c) 2024 John Alexis Guerra Gómez\nimport * as d3 from 'd3';\n\n// Based on https://observablehq.com/@d3/voronoi-labels by Mike Bostock\n\n// ISC License\n\n// Copyright 2018–2023 Observable, Inc.\n// Permission to use, copy, modify, and/or distribute this software for any\n// purpose with or without fee is hereby granted, provided that the above\n// copyright notice and this permission notice appear in all copies.\n\n// THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\nfunction smartLabels(\n  data,\n  {\n    x = (d) => d[0], // x coordinate accessor, expected to be in pixels\n    y = (d) => d[1], // y coordinate accessor, expected to be in pixels\n    r = () => 3, // radius accessor, expected to be in pixels\n    label = (d, i) => i, // Accessor for the label\n    fill = \"#333\", // label fill color\n    stroke = \"white\", // label stroke color\n    width = null,\n    height = null,\n    target = null, // Where do you want it to draw\n    renderer = \"svg\", // canvas or svg\n    font = () => \"10pt sans-serif\",\n    hover = true, // Show label of the hovered point\n    onHover = (i) => i, // callback when hovered, will pass the index of the selected element\n    hoverFont = () => \"bolder 12pt sans-serif\",\n    labelsInCentroids = true,\n    threshold = 2000, // Areas over this size would get labels\n    alwaysShow = (d) => false, // If returns true for the node, it will always show the label\n    showLabel = (d, cell) => alwaysShow(d) || -d3.polygonArea(cell) > threshold, // If true, show the label\n\n    backgroundFill = \"#fefefe01\", // What to paint the bg rect of the labels. Needed for the onHover\n    strokeWidth = 5,\n\n    showVoronoi = false,\n    voronoiStroke = \"#ccc\",\n\n    showAnchors = false,\n    anchorsStroke = \"orange\",\n    anchorsFill = \"none\",\n\n    useOcclusion = true,\n    occludedStyle = \"opacity: 0.2\", // css style rules to be used on occluded labels\n\n    // For debugging\n    showPoints = false,\n    pointsFill = \"#ccc\",\n    pointsSelectedFill = \"firebrick\",\n    pointsStroke = \"#ccc\",\n    debug = false,\n    selected = null,\n    padding = 3, // label padding in pixels\n  } = {}\n) {\n  if (!data || data?.length === 0) {\n    console.log(\"smartLabels: No data to render\");\n    return target;\n  }\n\n  data = data.filter(\n    (d, index) =>\n      x(d, index) !== undefined &&\n      x(d, index) !== null &&\n      y(d, index) !== undefined &&\n      y(d, index) !== null\n  );\n\n  if (typeof font === \"string\") font = () => font;\n  if (typeof hoverFont === \"string\") hoverFont = () => hoverFont;\n\n  let xExtent = d3.extent(data, x),\n    yExtent = d3.extent(data, y);\n  width = width || xExtent[1] - xExtent[0];\n  height = height || yExtent[1] - yExtent[0];\n\n  if (debug) console.log(\"✅ smartLabels renderer\", renderer);\n\n  function checkIfTargetMatchesRenderer(target, renderer) {\n    if (target && target.node) {\n      target = target.node();\n    }\n    if (renderer.toLocaleLowerCase() === \"canvas\") {\n      return target instanceof HTMLCanvasElement;\n    } else {\n      return target instanceof SVGElement;\n    }\n  }\n\n  if (target && !checkIfTargetMatchesRenderer(target, renderer)) {\n    if (debug)\n      console.log(\n        \"❌ smartLabels Target doesn't match the renderer\",\n        target,\n        renderer\n      );\n    throw new Error(\n      \"Smartlabels Target doesn't match the renderer\",\n      target,\n      renderer\n    );\n  }\n\n  // Try to reuse the target\n  if (renderer.toLocaleLowerCase() === \"canvas\") {\n    if (target) {\n      target = d3.select(target.node ? target.node() : target);\n    } else {\n      target = d3.create(\"canvas\").attr(\"width\", width).attr(\"height\", height);\n    }\n    useOcclusion = false;\n  } else {\n    if (target) {\n      target = d3.select(target.node ? target.node() : target);\n    } else {\n      target = d3.create(\"svg\").attr(\"viewBox\", [0, 0, width, height]);\n    }\n    target = target || d3.create(\"svg\").attr(\"viewBox\", [0, 0, width, height]);\n  }\n\n  const delaunay = d3.Delaunay.from(data, x, y);\n  const voronoi = delaunay.voronoi([\n    xExtent[0] - 1,\n    yExtent[0] - 1,\n    xExtent[1] + 1,\n    yExtent[1] + 1,\n  ]);\n\n  let cells = data.map((d, i) => [d, voronoi.cellPolygon(i)]);\n  // Replace null cells with the nearest one\n  cells = cells\n    .map(([d, cell], index) => [d, getNearestCell(d, cell, index)])\n    .map(([d, cell]) => ({ d, cell, show: showLabel(d, cell) }));\n\n  // cells can be null when we have duplicated coords\n  // https://github.com/d3/d3-delaunay/issues/106\n  function getNearestCell(d, cell, index) {\n    if (!cell) {\n      const i = delaunay.find(x(d, index), y(d, index));\n      if (i === -1) {\n        console.log(\"couldn't find cell\", i, d, x(d, index), y(d, index));\n        return null;\n      }\n      cell = cells[i][1];\n    }\n    return cell;\n  }\n\n  function renderSVG() {\n    let anchors = null;\n    if (useOcclusion) {\n      target\n        .selectAll(\"style.smartLabels\")\n        .data([0])\n        .join(\"style\")\n        .attr(\"class\", \"smartLabels\").html(`\n        svg g.labels > text.occluded:not(.selected) { ${occludedStyle} }\n    `);\n    }\n\n    const mouseRect = target\n      .selectAll(\"rect.smartLabels\")\n      .data([0])\n      .join(\"rect\")\n      .attr(\"class\", \"smartLabels\")\n      .attr(\"width\", width)\n      .attr(\"height\", height)\n      .attr(\"fill\", backgroundFill)\n      .attr(\"stroke\", \"none\");\n\n    const orient = {\n      top: (text) =>\n        text\n          .attr(\"text-anchor\", \"middle\")\n          .attr(\"y\", (d, i) => -(r(d, i) + padding)),\n      right: (text) =>\n        text\n          .attr(\"text-anchor\", \"start\")\n          .attr(\"dy\", \"0.35em\")\n          .attr(\"x\", (d, i) => r(d, i) + padding),\n      bottom: (text) =>\n        text\n          .attr(\"text-anchor\", \"middle\")\n          .attr(\"dy\", \"0.71em\")\n          .attr(\"y\", (d, i) => r(d, i) + padding),\n      left: (text) =>\n        text\n          .attr(\"text-anchor\", \"end\")\n          .attr(\"dy\", \"0.35em\")\n          .attr(\"x\", (d, i) => -(r(d, i) + padding)),\n    };\n\n    if (showAnchors || labelsInCentroids) {\n      anchors = target\n        .selectAll(\"g#anchors\")\n        .data([cells])\n        .join(\"g\")\n        .attr(\"pointer-events\", \"none\")\n        .attr(\"id\", \"anchors\")\n        .attr(\"stroke\", anchorsStroke)\n        .attr(\"fill\", anchorsFill)\n        .selectAll(\"path.anchor\")\n        .data((d) => d)\n        .join(\"path\")\n        .attr(\"class\", \"anchor\")\n        .attr(\"display\", ({ show }) => (show ? null : \"none\"))\n        .attr(\"d\", ({ d, cell }, index) =>\n          cell\n            ? `M${d3.polygonCentroid(cell)}L${x(d, index)},${y(d, index)}`\n            : null\n        );\n    }\n\n    if (showVoronoi) {\n      target\n        .selectAll(\"path#voronoi\")\n        .data([1])\n        .join(\"path\")\n        .attr(\"id\", \"voronoi\")\n        .attr(\"stroke\", voronoiStroke)\n        .attr(\"pointer-events\", \"none\")\n        .attr(\"d\", voronoi.render());\n    }\n\n    let points;\n    if (showPoints) {\n      points = target\n        .selectAll(\"circle#points\")\n        .data([1])\n        .join(\"path\")\n        .attr(\"id\", \"points\")\n        .attr(\"pointer-events\", \"none\")\n        .attr(\"stroke\", pointsStroke)\n        .attr(\"fill\", pointsFill)\n        .attr(\"d\", delaunay.renderPoints(null, 2));\n    }\n\n    const labels = target\n      .selectAll(\"g.labels\")\n      .data([cells])\n      .join(\"g\")\n      .attr(\"class\", \"labels\")\n      .attr(\"fill\", fill)\n\n      .attr(\"stroke\", stroke)\n      .attr(\"stroke-width\", strokeWidth)\n      .attr(\"paint-order\", \"stroke\")\n      .attr(\"pointer-events\", \"none\")\n      .selectAll(\"text\")\n      .data((d) => d)\n      .join(\"text\")\n      .style(\"font\", ({d}, i) => font(d, i))\n      .each(function ({ d, cell }, index) {\n        if (!cell) return;\n        const [cx, cy] = d3.polygonCentroid(cell);\n        const angle =\n          (Math.round(\n            (Math.atan2(cy - y(d, index), cx - x(d, index)) / Math.PI) * 2\n          ) +\n            4) %\n          4;\n\n        d3.select(this).call(\n          angle === 0\n            ? orient.right\n            : angle === 3\n              ? orient.top\n              : angle === 1\n                ? orient.bottom\n                : orient.left\n        );\n      })\n      .attr(\"transform\", ({ d, cell }, index) => {\n        if (labelsInCentroids) {\n          const [cx, cy] = d3.polygonCentroid(cell);\n\n          return `translate(${cx}, ${cy})`;\n        } else {\n          return `translate(${x(d, index)}, ${y(d, index)})`;\n        }\n      })\n      .attr(\"display\", ({ show }) => (show ? null : \"none\"))\n      .text(({ d }, i, all) => label(d, i, all));\n\n    let selected = null;\n    if (hover) {\n      mouseRect.on(\"mousemove\", (event) => {\n        // Find the selected point\n        const i = delaunay.find(...d3.pointer(event));\n        if (i === selected) return;\n        selected = i;\n\n        // Update labels\n        labels\n          .attr(\"display\", ({ show }, i) =>\n            i === selected || show ? null : \"none\"\n          )\n          .style(\"font\", ({d}, i) =>\n            i === selected ? hoverFont(d, i) : font(d, i)\n          )\n          .classed(\"selected\", (_, i) => i === selected)\n          .filter((_, i) => i === selected)\n          .raise();\n\n        anchors &&\n          anchors.attr(\"display\", ({ show }, i) =>\n            show || i === selected ? null : \"none\"\n          );\n\n        if (showPoints) {\n          points\n            .attr(\"fill\", (_, i) =>\n              i === selected ? pointsSelectedFill : pointsSelectedFill\n            )\n            .classed(\"selected\", (_, i) => i === selected);\n        }\n\n        if (onHover && typeof onHover === \"function\") onHover(i);\n      });\n    }\n\n    // Setup a MutationObserver to wait for the element to be rendered\n    // https://stackoverflow.com/questions/15875128/is-there-element-rendered-event\n    if (useOcclusion) {\n      const observer = new MutationObserver(function () {\n        if (document.contains(target.node())) {\n          target.call(occlusion, \"g.labels > text\");\n          observer.disconnect();\n        }\n      });\n\n      observer.observe(document, {\n        attributes: false,\n        childList: true,\n        characterData: false,\n        subtree: true,\n      });\n    }\n  } // renderSVG\n\n  function renderCanvasAnchorsVoronoiPoints(context) {\n    if (debug)\n      console.log(\n        \"renderCanvasAnchorsVoronoiPoints\",\n        \"showAnchors\",\n        showAnchors,\n        \"labelsInCentroids\",\n        labelsInCentroids,\n        \"showVoronoi\",\n        showVoronoi,\n        \"showPoints\",\n        showPoints\n      );\n    if (showAnchors || labelsInCentroids) {\n      cells.forEach(({ d, cell, show }, index) => {\n        if (!show) return;\n        const [cx, cy] = d3.polygonCentroid(cell);\n        context.beginPath();\n        context.moveTo(cx, cy);\n        context.lineTo(x(d, index), y(d, index));\n        context.strokeStyle = anchorsStroke;\n        context.stroke();\n      });\n    }\n\n    if (showVoronoi) {\n      context.beginPath();\n      voronoi.render(context);\n      context.strokeStyle = voronoiStroke;\n      context.stroke();\n    }\n\n    if (showPoints) {\n      context.beginPath();\n      // delaunay.renderPoints(context, 2);\n      context.save();\n      context.globalAlpha = 0.7;\n      context.fillStyle = \"black\";\n      data.forEach((d, i) => {\n        context.beginPath();\n        context.arc(x(d, i), y(d, i), r(d, i), 0, 2 * Math.PI);\n      });\n      context.restore();\n      context.fillStyle = pointsFill;\n      context.fill();\n      context.strokeStyle = pointsStroke;\n      context.stroke();\n    }\n  } // renderCanvasAnchorsVoronoiPoints\n\n  function renderCanvasLabels(context, selected) {\n    cells.forEach(({ d, cell, show }, index) => {\n      if (!show && index !== selected) return;\n      const [cx, cy] = d3.polygonCentroid(cell);\n      const angle =\n        (Math.round(\n          (Math.atan2(cy - y(d, index), cx - x(d, index)) / Math.PI) * 2\n        ) +\n          4) %\n        4;\n\n      context.save();\n      const dr = r(d, index) + padding;\n      const dx = angle === 0 ? dr : angle === 2 ? -dr : dr;\n      const dy = angle === 1 ? dr : angle === 3 ? -dr : dr;\n      context.translate(\n        labelsInCentroids ? cx : x(d, index) + dx,\n        labelsInCentroids ? cy : y(d, index) + dy\n      );\n      context.textAlign =\n        angle === 0\n          ? \"left\"\n          : angle === 1\n            ? \"center\"\n            : angle === 2\n              ? \"right\"\n              : \"center\";\n      context.textBaseline =\n        angle === 0\n          ? \"middle\"\n          : angle === 1\n            ? \"top\"\n            : angle === 2\n              ? \"middle\"\n              : \"bottom\";\n      context.font = index === selected ? hoverFont(d, index) : font(d, index);\n      context.fillStyle = fill;\n      context.strokeStyle = stroke;\n      context.lineWidth = strokeWidth;\n      // if (debug) console.log(index, dx, dy, angle);\n      context.strokeText(label(d, index), 0, 0);\n      context.fillText(label(d, index), 0, 0);\n      context.restore();\n    });\n  } // renderCanvasLabels\n\n  function renderCanvas() {\n    const context = target.node().getContext(\"2d\");\n\n    renderCanvasAnchorsVoronoiPoints(context);\n    renderCanvasLabels(context, selected);\n\n    if (hover) {\n      if (debug) console.log(\"setting onmousemove\", target);\n\n      target.on(\"mousemove\", (event) => {\n        const [mx, my] = d3.pointer(event);\n        const i = delaunay.find(mx, my);\n        if (i === selected) return;\n        selected = i;\n\n        context.clearRect(0, 0, width, height);\n        renderCanvasAnchorsVoronoiPoints(context);\n        if (onHover && typeof onHover === \"function\") onHover(i);\n        renderCanvasLabels(context, selected);\n      });\n    }\n  } // renderCanvas\n\n  if (renderer.toLocaleLowerCase() === \"canvas\") {\n    renderCanvas();\n  } else {\n    renderSVG();\n  }\n\n  return Object.assign(target.node(), { delaunay, voronoi, cells });\n}\n\n// https://observablehq.com/@d3/occlusion\n// ISC License\n\n// Copyright 2020-2023 Philippe Rivière\n// Permission to use, copy, modify, and/or distribute this software for any\n// purpose with or without fee is hereby granted, provided that the above\n// copyright notice and this permission notice appear in all copies.\n\n// THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\nfunction occlusion(svg, against = \"text\") {\n  const nodes = d3\n    .sort(svg.selectAll(against), (node) => +node.getAttribute(\"data-priority\"))\n    .reverse()\n    .map((node) => {\n      const { x, y, width, height } = node.getBoundingClientRect();\n      return { node, x, y, width, height };\n    });\n\n  const visible = [];\n  for (const d of nodes) {\n    const occluded = visible.some((e) => intersectRect(d, e));\n    d3.select(d.node).classed(\"occluded\", occluded);\n    if (!occluded) visible.push(d);\n  }\n  return visible;\n}\n\n// This intersection function works for rect and text, but not so much for circles.\nfunction intersectRect(a, b) {\n  return !(\n    a.x + a.width < b.x ||\n    b.x + b.width < a.x ||\n    a.y + a.height < b.y ||\n    b.y + b.height < a.y\n  );\n}\n\nexport { smartLabels as default };\n","import * as d3 from \"d3\";\nimport { computeAutoFit } from \"../utils/computeAutoFit.js\";\nimport { applyTransform } from \"../utils/applyTransform.js\";\nimport smartLabels from \"smart-labels\";\n\n/**\n * renderCanvas - Canvas renderer for force-directed graph\n *\n * Original source: https://observablehq.com/@john-guerra/force-directed-graph\n * From 89207a2280891f15@1859.js lines 490-651\n *\n * @param {Object} opts - Options object with all configuration\n * @returns {Object} {target: canvas element, ticked: render function}\n */\nexport function renderCanvas(opts) {\n  let context;\n\n  try {\n    if (opts._this?.tagName !== \"CANVAS\") {\n      throw new Error(\"recreating canvas\");\n    }\n    context = opts._this?.getContext(\"2d\");\n  } catch (_e) {\n    // Create new canvas\n    const canvas = document.createElement(\"canvas\");\n    canvas.width = opts.width;\n    canvas.height = opts.height;\n    context = canvas.getContext(\"2d\");\n  }\n\n  const line = d3\n    .line()\n    .curve(opts.linkCurve)\n    .x((d) => d.x)\n    .y((d) => d.y)\n    .context(context);\n\n  const zoom = d3\n    .zoom()\n    .extent([\n      [0, 0],\n      [opts.width, opts.height],\n    ])\n    .scaleExtent(opts.zoomScaleExtent)\n    .on(\"zoom\", ({ transform }) => ticked(transform));\n\n  function drawNodesAndLinks(transform = d3.zoomTransform(context.canvas)) {\n    if (\n      opts.drawLinksWhenAlphaIs === null ||\n      opts.simulation.alpha() < opts.drawLinksWhenAlphaIs\n    ) {\n      context.save();\n      // constant opacity\n      if (!opts.LO) {\n        context.globalAlpha = opts.linkStrokeOpacity;\n      }\n\n      for (const [i, link] of opts.links.entries()) {\n        context.beginPath();\n        drawLink(link, transform);\n\n        // Dynamic opacity\n        if (opts.LO) context.globalAlpha = opts.LO[i];\n        context.strokeStyle = opts.L ? opts.L[i] : opts.linkStroke;\n        context.lineWidth = opts.W ? opts.W[i] : opts.linkStrokeWidth;\n        context.stroke();\n      }\n      context.restore();\n    }\n\n    context.save();\n    context.globalAlpha = opts.nodeStrokeOpacity;\n    for (const [i, node] of opts.nodes.entries()) {\n      context.beginPath();\n      drawNode(node, i, transform);\n      context.fillStyle = opts.G ? opts.color(opts.G[i]) : opts.nodeFill;\n      context.strokeStyle = opts.NS ? opts.NS[i] : opts.nodeStroke;\n      context.fill();\n      context.stroke();\n    }\n    context.restore();\n  }\n\n  function ticked(transform = d3.zoomTransform(context.canvas)) {\n    context.save();\n\n    computeAutoFit(opts);\n\n    if (opts.useEdgeBundling && opts.bundling) {\n      for (let l of opts.links) {\n        delete l.path;\n      }\n      if (\n        (!opts.edgeBundling.min_alpha_to_bundle &&\n          opts.edgeBundling.min_alpha_to_bundle !== 0) ||\n        opts.simulation.alpha() < opts.edgeBundling.min_alpha_to_bundle\n      ) {\n        opts.bundling.update();\n      }\n    }\n\n    context.clearRect(0, 0, opts.width, opts.height);\n    drawNodesAndLinks(transform);\n\n    if (opts.nodeLabel) {\n      // Draw Labels\n      context.save();\n      context.fillStyle = opts.nodeLabelFill;\n      context.textAlign = opts.nodeLabelTextAlign;\n      context.textAnchor = opts.nodeLabelTextAnchor;\n      if (opts.T) {\n        context.font = opts.nodeLabelFont;\n        context.beginPath();\n\n        if (opts.useSmartLabels) {\n          smartLabels(opts.nodes, {\n            ...opts.smartLabels,\n            target: context.canvas,\n            label: (_, i) => opts.T[i],\n            x: (d) => transform.applyX(opts.x(d.x)),\n            y: (d) => transform.applyY(opts.y(d.y)),\n            width: opts.width,\n            height: opts.height,\n            renderer: opts.renderer,\n            onHover: () => drawNodesAndLinks(transform),\n          });\n        } else {\n          for (const [i, node] of opts.nodes.entries()) {\n            drawLabel(node, i, transform);\n          }\n        }\n        context.stroke();\n      }\n      context.restore();\n    }\n\n    context.restore();\n  }\n\n  function drawLink(l, transform) {\n    line(\n      opts.useEdgeBundling && l.path\n        ? l.path.map((d) => applyTransform(d, transform, opts))\n        : [\n            applyTransform(l.source, transform, opts),\n            applyTransform(l.target, transform, opts),\n          ]\n    );\n  }\n\n  function drawNode(d, i, transform) {\n    d = applyTransform(d, transform, opts);\n    context.moveTo(d.x + opts.R[i], d.y);\n    context.arc(d.x, d.y, opts.R[i], 0, 2 * Math.PI);\n  }\n\n  function drawLabel(d, i, transform) {\n    d = applyTransform(d, transform, opts);\n    context.fillText(opts.T[i], d.x, d.y - opts.R[i] - 2);\n  }\n\n  return {\n    target: d3\n      .select(context.canvas)\n      .call(\n        opts\n          .drag(opts.simulation, context.canvas, opts)\n          .on(\"start.render drag.render end.render\", () => {\n            return ticked(d3.zoomTransform(context.canvas));\n          })\n      )\n      .call(\n        opts.useZoom ? zoom : () => {} // do not use zoom\n      )\n      .node(),\n    ticked,\n  };\n}\n","import * as d3 from \"d3\";\nimport { computeAutoFit } from \"../utils/computeAutoFit.js\";\nimport { applyTransform } from \"../utils/applyTransform.js\";\nimport smartLabels from \"smart-labels\";\n\n/**\n * renderSVG - SVG renderer for force-directed graph\n *\n * Original source: https://observablehq.com/@john-guerra/force-directed-graph\n * From 89207a2280891f15@1859.js lines 653-821\n *\n * @param {Object} opts - Options object with all configuration\n * @returns {Object} {target: SVG element, ticked: render function}\n */\nexport function renderSVG(opts) {\n  let svg;\n\n  try {\n    if (opts._this?.tagName !== \"svg\") {\n      throw new Error(\"recreating svg\");\n    }\n    svg = d3.select(opts._this);\n  } catch {\n    svg = d3.create(\"svg\");\n  }\n\n  const line = d3\n    .line()\n    .curve(opts.linkCurve)\n    .x((d) => d.x)\n    .y((d) => d.y);\n\n  svg\n    .attr(\"width\", opts.width)\n    .attr(\"height\", opts.height)\n    .attr(\"viewBox\", [0, 0, opts.width, opts.height])\n    .attr(\"style\", \"max-width: 100%; height: auto; height: intrinsic;\");\n\n  const linkG = svg\n    .selectAll(\"g#gLinks\")\n    .data([0])\n    .join(\"g\")\n    .attr(\"id\", \"gLinks\");\n\n  const link = linkG\n    .attr(\n      \"stroke\",\n      typeof opts.linkStroke !== \"function\" ? opts.linkStroke : null\n    )\n    .attr(\"fill\", \"none\")\n    .attr(\"stroke-opacity\", (_, i) =>\n      opts.LO ? opts.LO[i] : opts.linkStrokeOpacity\n    )\n    .attr(\n      \"stroke-width\",\n      typeof opts.linkStrokeWidth !== \"function\" ? opts.linkStrokeWidth : null\n    )\n    .attr(\"stroke-linecap\", opts.linkStrokeLinecap)\n    .selectAll(\"path\")\n    .data(opts.links)\n    .join(\"path\");\n\n  const nodeG = svg\n    .selectAll(\"g#gNodes\")\n    .data([0])\n    .join(\"g\")\n    .attr(\"id\", \"gNodes\");\n\n  const node = nodeG\n    .attr(\"fill\", opts.nodeFill)\n    .attr(\"stroke-opacity\", opts.nodeStrokeOpacity)\n    .attr(\"stroke-width\", opts.nodeStrokeWidth)\n    .selectAll(\"circle.node\")\n    .data(opts.nodes)\n    .join(\"circle\")\n    .attr(\"class\", \"node\")\n    .attr(\"stroke\", (_, i) => (opts.NS ? opts.NS[i] : opts.nodeStroke))\n    .attr(\"r\", (_, i) => opts.R[i]);\n\n  let label = null;\n\n  if (!opts.useSmartLabels) {\n    label = nodeG\n      .selectAll(\"text.label\")\n      .data(opts.nodes)\n      .join(\"text\")\n      .attr(\"fill\", opts.nodeLabelFill)\n      .attr(\"stroke\", opts.nodeLabelStroke || \"none\")\n      .style(\"text-anchor\", opts.nodeLabelAlign)\n      .style(\"text-anchor\", opts.nodeLabelTextAnchor)\n      .style(\"font\", opts.nodeLabelFont)\n      .attr(\"class\", \"label\")\n      .text((_, i) => opts.T[i]);\n  }\n\n  node.call(opts.drag(opts.simulation, svg.node(), opts));\n\n  const zoom = d3\n    .zoom()\n    .extent([\n      [0, 0],\n      [opts.width, opts.height],\n    ])\n    .scaleExtent(opts.zoomScaleExtent)\n    .on(\"zoom\", ({ transform }) => ticked(transform));\n\n  svg.call(\n    opts.useZoom ? zoom : () => {} // do not use zoom\n  );\n\n  if (opts.W) link.attr(\"stroke-width\", ({ index: i }) => opts.W[i]);\n  if (opts.L) link.attr(\"stroke\", ({ index: i }) => opts.L[i]);\n  if (opts.G) node.attr(\"fill\", ({ index: i }) => opts.color(opts.G[i]));\n  if (opts.T) node.append(\"title\").text(({ index: i }) => opts.T[i]);\n\n  function ticked(transform = d3.zoomTransform(svg.node())) {\n    computeAutoFit(opts);\n\n    if (opts.useEdgeBundling && opts.bundling) {\n      for (let l of opts.links) {\n        delete l.path;\n      }\n      if (\n        (!opts.edgeBundling.min_alpha_to_bundle &&\n          opts.edgeBundling.min_alpha_to_bundle !== 0) ||\n        opts.simulation.alpha() < opts.edgeBundling.min_alpha_to_bundle\n      ) {\n        opts.bundling.update();\n      }\n    }\n\n    link\n      .attr(\n        \"display\",\n        opts.drawLinksWhenAlphaIs === null ||\n          opts.simulation.alpha() <= opts.drawLinksWhenAlphaIs\n          ? \"block\"\n          : \"none\"\n      )\n      .attr(\"d\", (l) => {\n        return line(\n          opts.useEdgeBundling && l.path\n            ? l.path.map((d) => applyTransform(d, transform, opts))\n            : [\n                applyTransform(l.source, transform, opts),\n                applyTransform(l.target, transform, opts),\n              ]\n        );\n      });\n\n    node\n      .attr(\"cx\", (d) => applyTransform(d, transform, opts).x)\n      .attr(\"cy\", (d) => applyTransform(d, transform, opts).y);\n\n    if (opts.useSmartLabels && opts.T) {\n      smartLabels(opts.nodes, {\n        ...opts.smartLabels,\n        target: nodeG,\n        label: (_, i) => opts.T[i],\n        x: (d) => transform.applyX(opts.x(d.x)),\n        y: (d) => transform.applyY(opts.y(d.y)),\n        width: opts.width,\n        height: opts.height,\n      });\n    } else if (label) {\n      label\n        .attr(\n          \"x\",\n          (d) => applyTransform(d, transform, opts).x + opts.nodeLabelDx\n        )\n        .attr(\n          \"y\",\n          (d) => applyTransform(d, transform, opts).y + opts.nodeLabelDy\n        );\n    }\n  }\n\n  return { target: svg.node(), ticked };\n}\n","import * as d3 from \"d3\";\n\n/**\n * Default options for forceGraph\n *\n * Original source: https://observablehq.com/@john-guerra/force-directed-graph\n * From 89207a2280891f15@1859.js lines 125-223\n *\n * @param {Object} userOpts - User-provided options to merge\n * @returns {Object} Complete options object with defaults\n */\nexport function getDefaultOpts(userOpts = {}) {\n  const { width = 800, height = 600, invalidation = null } = userOpts;\n\n  return {\n    nodeId: (d) => d?.id, // given d in nodes, returns a unique identifier (string)\n    nodeGroup: undefined, // given d in nodes, returns an (ordinal) value for color\n    nodeGroups: undefined, // an array of ordinal values representing the node groups\n    nodeFill: \"currentColor\", // node stroke fill (if not using a group color encoding)\n    nodeStroke: () => \"#fff\", // node stroke color\n    nodeStrokeWidth: 1.5, // node stroke width, in pixels\n    nodeStrokeOpacity: 1, // node stroke opacity\n    nodeRadius: 3, // node radius, in pixels or a function\n    nodeLabel: undefined, // given d in nodes, a title string\n    nodeLabelFill: \"#333\", // node legend color\n    nodeLabelStroke: null, // node legend stroke color\n    nodeLabelTextAlign: \"center\", // node legend align used in canvas\n    nodeLabelTextAnchor: \"middle\", // used in svg\n    nodeLabelFont: \"8pt sans-serif\",\n    nodeLabelDy: -8, // label dy distance to node center\n    nodeLabelDx: 0, // label dx distance to node center\n    nodeStrength: undefined, // nodeCharge strength\n    linkSource: undefined, // given d in links, returns a node identifier string\n    linkTarget: undefined, // given d in links, returns a node identifier string\n    linkStroke: \"#999\", // link stroke color\n    linkStrokeOpacity: 0.6, // link stroke opacity\n    linkStrokeWidth: 1.5, // given d in links, returns a stroke width in pixels\n    linkStrokeLinecap: \"round\", // link stroke linecap\n    linkStrength: undefined,\n    linkDistance: 10,\n    linkCurve: d3.curveBasis,\n    colors: d3.schemeTableau10, // an array of color strings, for the node groups\n    color: null, // you can provide your own custom d3.scaleOrdinal color scale\n    width, // outer width, in pixels\n    height, // outer height, in pixels\n    invalidation, // when this promise resolves, stop the simulation\n    renderer: \"canvas\", // either \"svg\" or \"canvas\"\n    drawLinksWhenAlphaIs: null, // if set to a number [0,1] will only draw links if alpha is below this number\n    _this: undefined,\n    extent: null, // set to [[0, 0], [width, height]] for a border to avoid nodes leaving the canvas\n    extentForce: \"forceBoundary\", // one of [\"forceBoundary\", \"forceTransport\", \"forceExtent\"]\n    extentBorder: 20, // Size of the border\n    extentStrength: 0.1, // Strength of the border\n    simulationRestartAlpha: 1, // What alpha to set when redrawing\n    forceXStrength: undefined, // if not provided will try to fit in the width height\n    forceYStrength: undefined, // if not provided will try to fit in the width height\n    centeringStrength: 0.01,\n    collide: true,\n    collidePadding: 1,\n    collideIterations: 4,\n    forces: null, // You can pass your own forces using an object {\"forceName\": d3.forceManyBody()}\n    disjoint: true, // Set to false if your network is heavily connected\n    useEdgeBundling: false, // true to use edge bundling\n    edgeBundling: {\n      bundling_stiffness: 0.1, // global bundling constant controlling edge stiffness\n      step_size: 0.1, // init. distance to move points\n      subdivision_rate: 2, // subdivision rate increase\n      cycles: 2, // number of cycles to perform\n      iterations: 90, // init. number of iterations for cycle\n      iterations_rate: 0.6666667, // rate at which iteration number decreases i.e. 2/3\n      compatibility_threshold: 0.2, // which pairs of edges should be considered compatible\n      max_links: 1000, // If your network is large, edgebundling will only apply to these many links\n      min_alpha_to_bundle: 0.6,\n    },\n    useForceInABox: false, // will group by nodeGroup\n    forceInABox: {\n      template: \"force\", // Either treemap or force\n      strength: 0.3, // Strength to foci\n      linkStrengthInterCluster: 0.001, // linkStrength between nodes of different clusters\n      linkStrengthIntraCluster: 0.1, // linkStrength between nodes of the same cluster\n      forceLinkDistance: 100, // linkDistance between meta-nodes on the template (Force template only)\n      forceLinkStrength: 0.1, // linkStrength between meta-nodes of the template (Force template only)\n      forceCharge: -1, // Charge between the meta-nodes (Force template only)\n      forceNodeSize: 10, // Used to compute the template force nodes size (Force template only)\n    },\n    useZoom: true,\n    zoomScaleExtent: [0.1, 20],\n    minDistanceForDrag: 10,\n    autoFit: true, // keep nodes in view using scales\n    keepAspectRatio: false,\n    useSmartLabels: true,\n    smartLabels: {\n      stroke: \"white\", // label stroke color\n      threshold: 2000, // Areas over this size would get labels\n      font: (_d) => \"8pt sans-serif\",\n      hover: true, // Show label of the hovered point\n      onHover: (i) => i, // callback when hovered, will pass the index of the selected element\n      hoverFont: (_d) => \"bolder 8pt sans-serif\",\n      labelsInCentroids: false,\n      backgroundFill: \"#fefefe01\", // What to paint the bg rect of the labels\n      strokeWidth: 5,\n      showVoronoi: false,\n      voronoiStroke: \"#ccc\",\n      showAnchors: false,\n      anchorsStroke: \"orange\",\n      anchorsFill: \"none\",\n      useOcclusion: true,\n      occludedStyle: \"opacity: 0.2\", // css style rules to be used on occluded labels\n    },\n    alphaTarget: 0,\n    debug: false,\n  };\n}\n","import * as d3 from \"d3\";\nimport forceInABox from \"force-in-a-box\";\nimport forceBoundary from \"d3-force-boundary\";\nimport { forceTransport } from \"./forces/forceTransport.js\";\nimport { forceExtent } from \"./forces/forceExtent.js\";\nimport { edgeBundling } from \"./forces/edgeBundling.js\";\nimport { sample } from \"./utils/sample.js\";\nimport { drag } from \"./utils/drag.js\";\nimport { renderCanvas } from \"./renderers/renderCanvas.js\";\nimport { renderSVG } from \"./renderers/renderSVG.js\";\nimport { getDefaultOpts } from \"./defaults.js\";\n\n/**\n * ForceGraph - Core force-directed graph function\n *\n * Original source: https://observablehq.com/@john-guerra/force-directed-graph\n * From 89207a2280891f15@1859.js lines 230-488\n *\n * @param {Object} data - {nodes, links} graph data\n * @param {Object} _opts - User options\n * @returns {HTMLElement} DOM element (SVG or Canvas) with additional properties\n */\nexport function ForceGraph(\n  { nodes, links = [] }, // an iterable of node and link objects\n  _opts = {}\n) {\n  // Validation: Check for required data\n  if (!nodes) {\n    throw new Error(\n      \"netviz: Missing required 'nodes' array in data. \" +\n        \"Expected: ForceGraph({ nodes: [...], links: [...] }, options)\"\n    );\n  }\n\n  if (!Array.isArray(nodes)) {\n    throw new Error(\n      `netviz: 'nodes' must be an array, received ${typeof nodes}. ` +\n        \"Expected: ForceGraph({ nodes: [...], links: [...] }, options)\"\n    );\n  }\n\n  if (nodes.length === 0) {\n    console.warn(\n      \"netviz: Empty 'nodes' array provided. The graph will be empty.\"\n    );\n  }\n\n  if (!Array.isArray(links)) {\n    throw new Error(\n      `netviz: 'links' must be an array, received ${typeof links}. ` +\n        \"Expected: ForceGraph({ nodes: [...], links: [...] }, options)\"\n    );\n  }\n\n  // Validate that nodes have IDs\n  const nodeIdAccessor = _opts.nodeId || ((d) => d?.id);\n  const invalidNodes = nodes.filter((node) => {\n    const id = nodeIdAccessor(node);\n    return id === undefined || id === null;\n  });\n\n  if (invalidNodes.length > 0) {\n    throw new Error(\n      `netviz: ${invalidNodes.length} node(s) are missing an 'id' property. ` +\n        \"All nodes must have an 'id' field. \" +\n        \"Example: { id: 'nodeA', ...otherProps }. \" +\n        \"Or provide a custom nodeId function in options.\"\n    );\n  }\n\n  let opts = {\n    ...getDefaultOpts(_opts),\n    ..._opts,\n    edgeBundling: {\n      ...getDefaultOpts(_opts).edgeBundling,\n      ..._opts.edgeBundling,\n    },\n    forceInABox: {\n      ...getDefaultOpts(_opts).forceInABox,\n      ..._opts.forceInABox,\n    },\n    smartLabels: {\n      ...getDefaultOpts(_opts).smartLabels,\n      ..._opts.smartLabels,\n    },\n  };\n\n  if (opts.nodeRadius && typeof opts.nodeRadius !== \"function\") {\n    const numberNodeRadius = opts.nodeRadius;\n    opts.nodeRadius = () => numberNodeRadius;\n  }\n  if (opts.nodeStroke && typeof opts.nodeStroke !== \"function\") {\n    const nodeStroke = opts.nodeStroke;\n    opts.nodeStroke = () => nodeStroke;\n  }\n\n  // Handle both object references and numeric indices in links\n  opts.linkSource =\n    opts.linkSource ||\n    (({ source }) => {\n      // If source is a number, it's an index into the nodes array\n      if (typeof source === \"number\") {\n        return opts.nodeId(nodes[source]);\n      }\n      // If source is a string, it's already the ID\n      if (typeof source === \"string\") {\n        return source;\n      }\n      // If source is an object, get its ID\n      return opts.nodeId(source) || source;\n    });\n  opts.linkTarget =\n    opts.linkTarget ||\n    (({ target }) => {\n      // If target is a number, it's an index into the nodes array\n      if (typeof target === \"number\") {\n        return opts.nodeId(nodes[target]);\n      }\n      // If target is a string, it's already the ID\n      if (typeof target === \"string\") {\n        return target;\n      }\n      // If target is an object, get its ID\n      return opts.nodeId(target) || target;\n    });\n\n  // Compute values\n  const N = d3.map(nodes, opts.nodeId).map(intern);\n  const LS = d3.map(links, opts.linkSource).map(intern);\n  const LT = d3.map(links, opts.linkTarget).map(intern);\n  const T = opts.nodeLabel == null ? null : d3.map(nodes, opts.nodeLabel);\n  const R = opts.nodeRadius == null ? null : d3.map(nodes, opts.nodeRadius);\n  const G =\n    opts.nodeGroup == null ? null : d3.map(nodes, opts.nodeGroup).map(intern);\n  const NS =\n    opts.nodeStroke == null ? null : d3.map(nodes, opts.nodeStroke).map(intern);\n  const W =\n    typeof opts.linkStrokeWidth !== \"function\"\n      ? null\n      : d3.map(links, opts.linkStrokeWidth);\n  const L =\n    typeof opts.linkStroke !== \"function\"\n      ? null\n      : d3.map(links, opts.linkStroke);\n  const LO =\n    typeof opts.linkStrokeOpacity !== \"function\"\n      ? null\n      : d3.map(links, opts.linkStrokeOpacity);\n\n  opts.x = d3.scaleLinear().domain([0, opts.width]).range([0, opts.width]);\n  opts.y = d3.scaleLinear().domain([0, opts.height]).range([0, opts.height]);\n\n  // Copy nodes\n  if (opts._this?.nodes) {\n    // Make a shallow copy to protect against mutation, while\n    // recycling old nodes to preserve position and velocity\n    const oldNodes = new Map(opts._this?.nodes.map((d) => [d.id, d]));\n    nodes = nodes.map((n, i) =>\n      Object.assign(\n        oldNodes.get(opts.nodeId(n)) || { ...n, id: N[i], groupBy: G && G[i] }\n      )\n    );\n  } else {\n    // Replace the input nodes and links with mutable objects for the simulation\n    nodes = d3.map(nodes, (n, i) => ({\n      ...n,\n      id: N[i],\n      groupBy: G && G[i], // we need the groupBy for forceInABox\n    }));\n  }\n  links = d3.map(links, (_, i) => ({ source: LS[i], target: LT[i] }));\n\n  // Initialize towards the middle\n  for (let n of nodes) {\n    const randomFactor = 3; // how far from the center should nodes be initialized\n    n.x =\n      n.x !== undefined\n        ? n.x\n        : (Math.random() - 0.5) * (opts.width / randomFactor) + opts.width / 2;\n    n.y =\n      n.y !== undefined\n        ? n.y\n        : (Math.random() - 0.5) * (opts.height / randomFactor) +\n          opts.height / 2;\n  }\n\n  // Compute default domains\n  if (G && opts.nodeGroups === undefined) opts.nodeGroups = d3.sort(G);\n\n  // Construct the scales\n  const color = opts.color\n    ? opts.color\n    : opts.nodeGroup == null\n      ? null\n      : d3.scaleOrdinal(opts.nodeGroups, opts.colors);\n\n  let simulation =\n    opts._this?.simulation?.alpha(opts.simulationRestartAlpha)?.restart() ||\n    d3.forceSimulation();\n\n  simulation.nodes(nodes);\n\n  if (opts.forces) {\n    for (let k in opts.forces) {\n      simulation.force(k, opts.forces[k]({ nodes, links }));\n    }\n  } else {\n    // Construct the forces\n    const forceNode = d3.forceManyBody();\n    const forceLink = d3.forceLink(links).id(({ index: i }) => N[i]);\n    if (opts.nodeStrength !== undefined) forceNode.strength(opts.nodeStrength);\n    if (opts.linkStrength !== undefined) forceLink.strength(opts.linkStrength);\n\n    if (opts.forceXStrength === undefined) {\n      opts.forceXStrength = (opts.height / opts.width) * opts.centeringStrength;\n    }\n    if (opts.forceYStrength === undefined) {\n      opts.forceYStrength = (opts.width / opts.height) * opts.centeringStrength;\n    }\n\n    const forceCollide = opts.collide\n      ? d3\n          .forceCollide((_, i) => R[i] + opts.collidePadding)\n          .iterations(opts.collideIterations)\n      : null;\n\n    const forceX = d3.forceX(opts.width / 2).strength(opts.forceXStrength);\n    const forceY = d3.forceY(opts.height / 2).strength(opts.forceYStrength);\n\n    let groupingForce;\n    if (opts.useForceInABox) {\n      groupingForce = forceInABox()\n        .size([opts.width, opts.height - 100])\n        .template(opts.forceInABox.template)\n        .groupBy(\"groupBy\")\n        .strength(opts.forceInABox.strength)\n        .links(links)\n        .linkStrengthInterCluster(opts.forceInABox.linkStrengthInterCluster)\n        .linkStrengthIntraCluster(opts.forceInABox.linkStrengthIntraCluster)\n        .forceLinkDistance(opts.forceInABox.forceLinkDistance)\n        .forceLinkStrength(opts.forceInABox.forceLinkStrength)\n        .forceCharge(opts.forceInABox.forceCharge)\n        .forceNodeSize(opts.forceInABox.forceNodeSize);\n    }\n\n    simulation\n      .force(\n        \"link\",\n        forceLink\n          .distance(opts.linkDistance)\n          .strength(\n            opts.useForceInABox\n              ? groupingForce.getLinkStrength\n              : opts.linkStrength || 0.1\n          )\n      )\n      .force(\"charge\", forceNode)\n      .force(\"x\", opts.useForceInABox ? null : opts.disjoint ? forceX : null)\n      .force(\"y\", opts.useForceInABox ? null : opts.disjoint ? forceY : null)\n      .force(\n        \"center\",\n        opts.useForceInABox\n          ? null\n          : !opts.disjoint\n            ? d3.forceCenter(opts.width / 2, opts.height / 2)\n            : null\n      )\n      .force(\"collide\", forceCollide)\n      .force(\"forceInABox\", opts.useForceInABox ? groupingForce : null);\n  }\n\n  // Edge bundling\n  opts.bundling =\n    opts.useEdgeBundling &&\n    edgeBundling(\n      { nodes, links: sample(links, opts.edgeBundling.max_links) },\n      {\n        ...opts.edgeBundling,\n      }\n    );\n\n  simulation.alphaTarget(opts.alphaTarget).restart();\n\n  if (opts.extent) {\n    simulation.force(\n      \"boundary\",\n      opts.extentForce === \"forceBoundary\"\n        ? forceBoundary(...opts.extent.flat(2))\n            .border(opts.extentBorder)\n            .hardBoundary(true)\n            .strength(opts.extentStrength)\n        : opts.extentForce === \"forceExtent\"\n          ? forceExtent(opts.extent)\n          : forceTransport(opts.extent, 5, opts.extentStrength * 10)\n    );\n  }\n\n  opts = {\n    ...opts,\n    nodes,\n    links,\n    N,\n    LS,\n    LT,\n    T,\n    G,\n    W,\n    L,\n    LO,\n    R,\n    NS,\n    drag,\n    simulation,\n    color,\n  };\n\n  const { target, ticked } =\n    opts.renderer === \"canvas\" ? renderCanvas(opts) : renderSVG(opts);\n\n  simulation.on(\"tick\", ticked);\n\n  if (opts.invalidation) {\n    opts.invalidation.then(() => {\n      simulation.stop();\n    });\n  }\n\n  function intern(value) {\n    return value !== null && typeof value === \"object\"\n      ? value.valueOf()\n      : value;\n  }\n\n  ticked();\n\n  return Object.assign(target, {\n    scales: { color },\n    simulation,\n    nodes,\n    links,\n  });\n}\n","/**\n * filterNetwork - Utility to filter network by nodes/links with ego-network support\n *\n * Original source: https://observablehq.com/@john-guerra/force-directed-graph\n * From 89207a2280891f15@1859.js lines 893-977\n *\n * @param {Object} network - {nodes, links} network data\n * @param {Object} options - Filtering options\n * @returns {Object} Filtered {nodes, links}\n */\nexport function filterNetwork(\n  network,\n  {\n    nodeId = (d) => d.id,\n    byNodes = null,\n    byLinks = null,\n    edgelessNodes = false, // Should we allow nodes without edges?\n    nodesMap,\n    egoDistance = 1,\n    filterSource = true,\n    filterTarget = true,\n  } = {}\n) {\n  nodesMap = nodesMap\n    ? nodesMap\n    : new Map(network.nodes.map((d, i, all) => [nodeId(d, i, all), d]));\n  let res = {\n    nodes: [...network.nodes],\n    links: [...network.links],\n  };\n\n  function filterNodesFromLinks(res) {\n    const ids = [...new Set(res.links.map((l) => [l.source, l.target]).flat())];\n    res.nodes = ids.map((id) => nodesMap.get(id)).filter((d) => d); // undefined when the node is not visible anymore\n\n    return res;\n  }\n\n  function filterLinksFromNodes(\n    { nodes, links },\n    { filterSource = true, filterTarget = true } = {}\n  ) {\n    const ids = new Set(nodes.map(nodeId));\n\n    links = links\n      .filter(\n        ({ source, target }) =>\n          (!filterSource || ids.has(source)) &&\n          (!filterTarget || ids.has(target))\n      )\n      .map((l) => ({ ...l }));\n\n    return { nodes, links };\n  }\n\n  // Filter nodes\n  if (byNodes) {\n    res.nodes = res.nodes.filter(byNodes).map((n) => ({ ...n }));\n  }\n\n  res = filterLinksFromNodes(res, { filterSource, filterTarget });\n\n  // Then links\n  if (byLinks) {\n    res.links = res.links.filter(byLinks).map((l) => ({\n      ...l,\n    }));\n    // Remove edgeless nodes\n    if (!edgelessNodes) {\n      res = filterNodesFromLinks(res, { filterSource, filterTarget });\n    }\n  }\n\n  for (\n    let currentDistance = 1;\n    currentDistance < egoDistance;\n    currentDistance += 1\n  ) {\n    res = filterLinksFromNodes(\n      { nodes: res.nodes, links: network.links },\n      { filterSource, filterTarget: false }\n    );\n\n    res = filterNodesFromLinks(res, { filterSource, filterTarget });\n  }\n\n  return res;\n}\n","/**\n * nodesFromLinks - Creates nodes array from links-only data\n *\n * Useful when data only contains links (like flare-dependencies.json from vega-datasets)\n * and nodes need to be inferred from source/target references.\n *\n * @param {Array<Object>} links - Array of link objects with source/target\n * @param {Object} options - Configuration options\n * @param {function} [options.linkSource] - Extract source from link (default: d => d.source)\n * @param {function} [options.linkTarget] - Extract target from link (default: d => d.target)\n * @param {function} [options.nodeId] - Create node ID from extracted value (default: identity)\n * @param {function} [options.nodeProps] - Additional node properties (receives id, returns object)\n * @returns {Object} { nodes: [...], links: [...] } - Ready for ForceGraph\n *\n * @example\n * // Edge-list only data (like flare-dependencies.json)\n * const edgeData = [{ source: 35, target: 4 }, { source: 190, target: 4 }];\n * const graph = nodesFromLinks(edgeData);\n * // => { nodes: [{ id: 4 }, { id: 35 }, { id: 190 }], links: [...] }\n *\n * @example\n * // With custom node properties\n * const graph = nodesFromLinks(edgeData, {\n *   nodeProps: (id) => ({ id, label: `Node ${id}` })\n * });\n */\nexport function nodesFromLinks(\n  links,\n  {\n    linkSource = (d) => d.source,\n    linkTarget = (d) => d.target,\n    nodeId = (v) => v,\n    nodeProps = (id) => ({ id }),\n  } = {}\n) {\n  if (!Array.isArray(links)) {\n    throw new Error(\"nodesFromLinks: links must be an array\");\n  }\n\n  // Extract unique node identifiers from links\n  const nodeSet = new Set();\n  for (const link of links) {\n    const sourceId = nodeId(linkSource(link));\n    const targetId = nodeId(linkTarget(link));\n    if (sourceId !== undefined && sourceId !== null) nodeSet.add(sourceId);\n    if (targetId !== undefined && targetId !== null) nodeSet.add(targetId);\n  }\n\n  // Create nodes array with optional properties\n  const nodes = Array.from(nodeSet).map(nodeProps);\n\n  return { nodes, links: [...links] };\n}\n","/**\n * mapProperties - Maps property names in nodes and/or links\n *\n * Useful when data uses different property names than netviz expects\n * (e.g., 'name' instead of 'id', 'weight' instead of 'value').\n *\n * @param {Object} network - { nodes, links } network data\n * @param {Object} options - Mapping configuration\n * @param {Object} [options.nodes] - Node property mappings { to: from } or { to: accessor }\n * @param {Object} [options.links] - Link property mappings { to: from } or { to: accessor }\n * @returns {Object} { nodes, links } with mapped properties\n *\n * @example\n * // Simple property rename (value is the source property name)\n * const mapped = mapProperties(data, {\n *   nodes: { id: 'name', group: 'country' }\n * });\n *\n * @example\n * // With accessor functions\n * const mapped = mapProperties(data, {\n *   nodes: {\n *     id: d => d.name,\n *     label: d => d.fullName || d.name,\n *     group: d => d.category\n *   },\n *   links: {\n *     value: d => d.weight || 1\n *   }\n * });\n */\nexport function mapProperties(\n  network,\n  { nodes: nodeMapping = {}, links: linkMapping = {} } = {}\n) {\n  if (!network || !network.nodes) {\n    throw new Error(\"mapProperties: network must have a nodes array\");\n  }\n\n  function applyMapping(item, mapping) {\n    const result = { ...item };\n    for (const [to, from] of Object.entries(mapping)) {\n      if (typeof from === \"function\") {\n        result[to] = from(item);\n      } else if (typeof from === \"string\" && from in item) {\n        result[to] = item[from];\n        // Remove old property if renamed (but not if mapping to same name)\n        if (to !== from) delete result[from];\n      }\n    }\n    return result;\n  }\n\n  return {\n    nodes: network.nodes.map((n) => applyMapping(n, nodeMapping)),\n    links: (network.links || []).map((l) => applyMapping(l, linkMapping)),\n  };\n}\n","/**\n * resolveIndexLinks - Resolves numeric array indices in links to node IDs\n *\n * Useful when links reference nodes by their array position (index)\n * rather than by ID. Converts to ID-based references for consistency.\n *\n * Note: ForceGraph already handles numeric indices internally, so this\n * utility is mainly for users who want to pre-process data or chain\n * with other transformations.\n *\n * @param {Object} network - { nodes, links } network data\n * @param {Object} options - Configuration options\n * @param {function} [options.nodeId] - Extract ID from node (default: d => d.id)\n * @param {function} [options.linkSource] - Extract source from link (default: d => d.source)\n * @param {function} [options.linkTarget] - Extract target from link (default: d => d.target)\n * @returns {Object} { nodes, links } with resolved references\n *\n * @example\n * const data = {\n *   nodes: [{ id: 'A' }, { id: 'B' }, { id: 'C' }],\n *   links: [{ source: 0, target: 1 }, { source: 1, target: 2 }]\n * };\n * const resolved = resolveIndexLinks(data);\n * // => { nodes: [...], links: [{ source: 'A', target: 'B' }, { source: 'B', target: 'C' }] }\n */\nexport function resolveIndexLinks(\n  network,\n  {\n    nodeId = (d) => d.id,\n    linkSource = (d) => d.source,\n    linkTarget = (d) => d.target,\n  } = {}\n) {\n  if (!network || !network.nodes) {\n    throw new Error(\"resolveIndexLinks: network must have a nodes array\");\n  }\n\n  const nodes = network.nodes;\n\n  const links = (network.links || []).map((link) => {\n    const source = linkSource(link);\n    const target = linkTarget(link);\n\n    return {\n      ...link,\n      source: typeof source === \"number\" ? nodeId(nodes[source]) : source,\n      target: typeof target === \"number\" ? nodeId(nodes[target]) : target,\n    };\n  });\n\n  return { nodes: [...nodes], links };\n}\n","/**\n * computeNodeGroups - Computes node groups/clusters from network topology\n *\n * Useful when nodes lack group/cluster information. Can compute groups using:\n * - 'connected': Connected component membership\n * - 'degree': Degree-based binning (low/medium/high connectivity)\n * - custom function\n *\n * @param {Object} network - { nodes, links } network data\n * @param {Object} options - Configuration options\n * @param {string|function} [options.method='connected'] - Grouping method\n * @param {string} [options.groupProperty='group'] - Property name to add\n * @param {function} [options.nodeId] - Extract ID from node (default: d => d.id)\n * @param {function} [options.linkSource] - Extract source from link (default: d => d.source)\n * @param {function} [options.linkTarget] - Extract target from link (default: d => d.target)\n * @returns {Object} { nodes, links } with group property added to nodes\n *\n * @example\n * // Group by connected components\n * const grouped = computeNodeGroups(data);\n * // => nodes now have { id: 'A', group: 0 }, { id: 'B', group: 0 }, { id: 'C', group: 1 }\n *\n * @example\n * // Group by node degree\n * const grouped = computeNodeGroups(data, { method: 'degree' });\n *\n * @example\n * // Custom grouping function\n * const grouped = computeNodeGroups(data, {\n *   method: (node, index, nodes, links, degrees) => {\n *     return degrees.get(node.id) > 5 ? 'hub' : 'leaf';\n *   }\n * });\n */\nexport function computeNodeGroups(\n  network,\n  {\n    method = \"connected\",\n    groupProperty = \"group\",\n    nodeId = (d) => d.id,\n    linkSource = (d) => (typeof d.source === \"object\" ? d.source.id : d.source),\n    linkTarget = (d) => (typeof d.target === \"object\" ? d.target.id : d.target),\n  } = {}\n) {\n  if (!network || !network.nodes) {\n    throw new Error(\"computeNodeGroups: network must have a nodes array\");\n  }\n\n  const { nodes, links = [] } = network;\n\n  // Build node ID list and index map\n  const nodeIds = nodes.map(nodeId);\n  const idToIndex = new Map(nodeIds.map((id, i) => [id, i]));\n\n  // Compute degrees (useful for multiple methods)\n  const degrees = new Map(nodeIds.map((id) => [id, 0]));\n  for (const link of links) {\n    const src = linkSource(link);\n    const tgt = linkTarget(link);\n    if (degrees.has(src)) degrees.set(src, degrees.get(src) + 1);\n    if (degrees.has(tgt)) degrees.set(tgt, degrees.get(tgt) + 1);\n  }\n\n  let groupFn;\n\n  if (typeof method === \"function\") {\n    // Custom function receives node, index, all nodes, all links, and degrees map\n    groupFn = (node, i) => method(node, i, nodes, links, degrees);\n  } else if (method === \"connected\") {\n    // Union-Find for connected components\n    const parent = nodeIds.map((_, i) => i);\n    const find = (i) => (parent[i] === i ? i : (parent[i] = find(parent[i])));\n    const union = (a, b) => {\n      parent[find(a)] = find(b);\n    };\n\n    for (const link of links) {\n      const si = idToIndex.get(linkSource(link));\n      const ti = idToIndex.get(linkTarget(link));\n      if (si !== undefined && ti !== undefined) union(si, ti);\n    }\n\n    // Normalize component IDs to 0, 1, 2...\n    const componentMap = new Map();\n    let nextGroup = 0;\n    groupFn = (node, i) => {\n      const root = find(i);\n      if (!componentMap.has(root)) {\n        componentMap.set(root, nextGroup++);\n      }\n      return componentMap.get(root);\n    };\n  } else if (method === \"degree\") {\n    // Bin nodes by degree into low/medium/high\n    const maxDegree = Math.max(...degrees.values(), 1);\n    groupFn = (node) => {\n      const degree = degrees.get(nodeId(node)) || 0;\n      // Create 4 bins: 0, 1, 2, 3\n      return Math.min(3, Math.floor((degree / maxDegree) * 4));\n    };\n  } else {\n    throw new Error(\n      `computeNodeGroups: unknown method \"${method}\". Use \"connected\", \"degree\", or a function.`\n    );\n  }\n\n  const groupedNodes = nodes.map((node, i) => ({\n    ...node,\n    [groupProperty]: groupFn(node, i),\n  }));\n\n  return { nodes: groupedNodes, links: [...links] };\n}\n","/**\n * prepareNetwork - Convenience function that auto-detects and applies transformations\n *\n * Intelligently prepares network data for ForceGraph by:\n * 1. Creating nodes from links if nodes array is missing\n * 2. Applying property mappings\n * 3. Computing groups if requested\n *\n * @param {Object|Array} data - Network data or links-only array\n * @param {Object} options - Transformation options\n * @param {Object} [options.nodeMapping] - Property mappings for nodes { to: from }\n * @param {Object} [options.linkMapping] - Property mappings for links { to: from }\n * @param {string|function} [options.groupMethod] - Method for computing groups ('connected', 'degree', or function)\n * @param {string} [options.groupProperty='group'] - Property name for computed groups\n * @param {function} [options.nodeId] - Node ID accessor (default: d => d.id)\n * @param {function} [options.nodeProps] - Create node properties from ID (for edge-only data)\n * @param {function} [options.linkSource] - Extract source from link (default: d => d.source)\n * @param {function} [options.linkTarget] - Extract target from link (default: d => d.target)\n * @returns {Object} { nodes, links } ready for ForceGraph\n *\n * @example\n * // Auto-detect and prepare edge-only data\n * const data = [{ source: 0, target: 1 }, { source: 1, target: 2 }];\n * const graph = prepareNetwork(data);\n *\n * @example\n * // Prepare with property mappings\n * const graph = prepareNetwork(rawData, {\n *   nodeMapping: { id: 'name', group: 'country' },\n *   groupMethod: 'connected'\n * });\n *\n * @example\n * // Full transformation pipeline\n * const graph = prepareNetwork(edgeData, {\n *   nodeProps: (id) => ({ id, label: `Node ${id}` }),\n *   groupMethod: 'degree',\n *   groupProperty: 'cluster'\n * });\n */\nimport { nodesFromLinks } from \"./nodesFromLinks.js\";\nimport { mapProperties } from \"./mapProperties.js\";\nimport { computeNodeGroups } from \"./computeNodeGroups.js\";\n\nexport function prepareNetwork(\n  data,\n  {\n    nodeMapping,\n    linkMapping,\n    groupMethod,\n    groupProperty = \"group\",\n    nodeId = (d) => d.id,\n    nodeProps,\n    linkSource = (d) => d.source,\n    linkTarget = (d) => d.target,\n  } = {}\n) {\n  let network;\n\n  // Step 1: Handle edge-only data (array input or missing nodes)\n  if (Array.isArray(data)) {\n    // Data is just an array of links\n    network = nodesFromLinks(data, {\n      linkSource,\n      linkTarget,\n      nodeProps: nodeProps || ((id) => ({ id })),\n    });\n  } else if (!data.nodes || data.nodes.length === 0) {\n    // Data has links property but no nodes\n    network = nodesFromLinks(data.links || [], {\n      linkSource,\n      linkTarget,\n      nodeProps: nodeProps || ((id) => ({ id })),\n    });\n  } else {\n    // Data already has nodes and links\n    network = {\n      nodes: [...data.nodes],\n      links: [...(data.links || [])],\n    };\n  }\n\n  // Step 2: Apply property mappings if provided\n  if (nodeMapping || linkMapping) {\n    network = mapProperties(network, {\n      nodes: nodeMapping,\n      links: linkMapping,\n    });\n  }\n\n  // Step 3: Compute groups if requested\n  if (groupMethod) {\n    network = computeNodeGroups(network, {\n      method: groupMethod,\n      groupProperty,\n      nodeId,\n      linkSource,\n      linkTarget,\n    });\n  }\n\n  return network;\n}\n","/**\n * netviz - Network Visualization Library\n *\n * A collection of network visualization widgets supporting multiple rendering modes\n * and layout algorithms. Currently includes force-directed graphs with SVG and Canvas\n * rendering, edge bundling, grouping layouts, and reactive widgets integration.\n *\n * Based on: https://observablehq.com/@john-guerra/force-directed-graph\n * Follows reactive widgets pattern from: https://reactivewidgets.org\n */\n\nimport { ForceGraph as ForceGraphCore } from \"./forceGraph.js\";\n\n/**\n * ForceGraph - Force-directed graph visualization widget\n *\n * @param {Object} data - {nodes, links} graph data\n * @param {Object} options - Configuration options\n * @returns {HTMLElement} DOM element with .value property, .update(), .destroy() methods\n *\n * @example\n * const graph = ForceGraph(data, {\n *   width: 800,\n *   height: 600,\n *   renderer: \"svg\" // or \"canvas\"\n * });\n * document.body.appendChild(graph);\n *\n * // Update later\n * graph.update(newData);\n *\n * // Cleanup\n * graph.destroy();\n *\n * // Observable compatibility\n * ForceGraph(data, { invalidation, _this });\n */\nexport function ForceGraph(data, options = {}) {\n  // Create the graph using the core ForceGraph function\n  const element = ForceGraphCore(data, options);\n\n  // Add reactive widgets properties and methods\n\n  // .value property for selected nodes/edges (TODO: implement selection)\n  element.value = null;\n\n  /**\n   * update - Update the graph with new data or options\n   * @param {Object} newData - New {nodes, links} data\n   * @param {Object} newOptions - New options to merge\n   */\n  element.update = function (newData, newOptions = {}) {\n    // Preserve the current element and simulation by passing _this\n    const mergedOptions = {\n      ...options,\n      ...newOptions,\n      _this: element,\n    };\n\n    // Re-create the graph with preserved state\n    const updated = ForceGraphCore(newData, mergedOptions);\n\n    // Update the element's properties\n    element.simulation = updated.simulation;\n    element.nodes = updated.nodes;\n    element.links = updated.links;\n    element.scales = updated.scales;\n\n    return element;\n  };\n\n  /**\n   * destroy - Cleanup and stop the simulation\n   */\n  element.destroy = function () {\n    if (element.simulation) {\n      element.simulation.stop();\n    }\n    // Remove event listeners if any\n    // (TODO: add event listeners and clean them up here)\n  };\n\n  // Emit input events when user interacts\n  // (TODO: implement selection and event emission)\n\n  return element;\n}\n\n/**\n * NodeLink - Alias for ForceGraph (node-link diagrams)\n * Provides a semantic name for force-directed node-link visualizations\n */\nexport const NodeLink = ForceGraph;\n\n// Re-export utility functions for advanced usage\nexport { ForceGraph as ForceGraphCore } from \"./forceGraph.js\";\nexport { forceTransport } from \"./forces/forceTransport.js\";\nexport { forceExtent } from \"./forces/forceExtent.js\";\nexport { edgeBundling, ForceEdgeBundling } from \"./forces/edgeBundling.js\";\nexport { filterNetwork } from \"./utils/filterNetwork.js\";\n\n// Data transformation utilities\nexport { nodesFromLinks } from \"./utils/nodesFromLinks.js\";\nexport { mapProperties } from \"./utils/mapProperties.js\";\nexport { resolveIndexLinks } from \"./utils/resolveIndexLinks.js\";\nexport { computeNodeGroups } from \"./utils/computeNodeGroups.js\";\nexport { prepareNetwork } from \"./utils/prepareNetwork.js\";\n"]}