@aiready/components 0.14.2 → 0.14.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hooks/useForceSimulation.d.ts +1 -1
- package/dist/hooks/useForceSimulation.js +231 -253
- package/dist/hooks/useForceSimulation.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +228 -252
- package/dist/index.js.map +1 -1
- package/dist/{useForceSimulation-BNhxX4gH.d.ts → useForceSimulation-CjLhYevG.d.ts} +4 -3
- package/package.json +2 -2
- package/src/hooks/simulation-constants.ts +39 -0
- package/src/hooks/simulation-helpers.ts +42 -4
- package/src/hooks/useForceSimulation.ts +306 -421
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hooks/simulation-helpers.ts","../../src/hooks/useForceSimulation.ts"],"names":[],"mappings":";;;;AAMO,SAAS,eAAe,KAAA,EAA+B;AAC5D,EAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA,KAAM;AACnB,IAAC,EAAU,EAAA,GAAK,CAAA;AAChB,IAAC,EAAU,EAAA,GAAK,CAAA;AAChB,IAAA,IAAI,OAAO,CAAA,CAAE,CAAA,KAAM,QAAA,EAAU,CAAA,CAAE,CAAA,GAAI,MAAA,CAAO,CAAA,CAAE,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAC,CAAA;AACxD,IAAA,IAAI,OAAO,CAAA,CAAE,CAAA,KAAM,QAAA,EAAU,CAAA,CAAE,CAAA,GAAI,MAAA,CAAO,CAAA,CAAE,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAC,CAAA;AAAA,EAC1D,CAAC,CAAA;AACH;AAMO,SAAS,mBAAA,CACd,KAAA,EACA,KAAA,EACA,MAAA,EACM;AACN,EAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA,KAAM;AACnB,IAAA,CAAA,CAAE,CAAA,GAAI,IAAA,CAAK,MAAA,EAAO,GAAI,KAAA;AACtB,IAAA,CAAA,CAAE,CAAA,GAAI,IAAA,CAAK,MAAA,EAAO,GAAI,MAAA;AACtB,IAAC,CAAA,CAAU,EAAA,GAAA,CAAM,IAAA,CAAK,MAAA,KAAW,GAAA,IAAO,EAAA;AACxC,IAAC,CAAA,CAAU,EAAA,GAAA,CAAM,IAAA,CAAK,MAAA,KAAW,GAAA,IAAO,EAAA;AAAA,EAC1C,CAAC,CAAA;AACH;AC0CO,SAAS,kBAAA,CACd,YAAA,EACA,YAAA,EACA,OAAA,EAC6E;AAM7E,EAAA,MAAM;AAAA,IACJ,cAAA,GAAiB,IAAA;AAAA,IACjB,YAAA,GAAe,GAAA;AAAA,IACf,YAAA,GAAe,CAAA;AAAA,IACf,iBAAA,GAAoB,CAAA;AAAA,IACpB,eAAA,GAAkB,EAAA;AAAA,IAClB,cAAA,GAAiB,GAAA;AAAA,IACjB,KAAA;AAAA,IACA,MAAA;AAAA,IACA,UAAA,GAAa,MAAA;AAAA,IACb,aAAA,GAAgB,GAAA;AAAA,IAChB,WAAA,GAAc,CAAA;AAAA,IACd,SAAA,GAAY,GAAA;AAAA,IACZ,QAAA,GAAW,IAAA;AAAA,IACX,MAAA;AAAA;AAAA;AAAA,IAGA,eAAA,GAAkB,IAAA;AAAA,IAClB,cAAA,GAAiB,EAAA;AAAA,IACjB,mBAAA,GAAsB;AAAA,GACxB,GAAI,OAAA;AAEJ,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAA2B,YAAY,CAAA;AACjE,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAA2B,YAAY,CAAA;AACjE,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAS,KAAK,CAAA;AAChD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAS,CAAC,CAAA;AAEpC,EAAA,MAAM,aAAA,GAAgB,OAGZ,IAAI,CAAA;AACd,EAAA,MAAM,cAAA,GAAiB,OAA6C,IAAI,CAAA;AAKxE,EAAA,MAAM,QAAA,GAAW,aAAa,GAAA,CAAI,CAAC,MAAM,CAAA,CAAE,EAAE,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA;AACvD,EAAA,MAAM,YAAY,YAAA,IAAgB,EAAC,EAChC,GAAA,CAAI,CAAC,CAAA,KAAM;AACV,IAAA,MAAM,QAAA,GACJ,OAAO,CAAA,CAAE,MAAA,KAAW,WAChB,CAAA,CAAE,MAAA,GACD,EAAE,MAAA,EAA2B,EAAA;AACpC,IAAA,MAAM,QAAA,GACJ,OAAO,CAAA,CAAE,MAAA,KAAW,WAChB,CAAA,CAAE,MAAA,GACD,EAAE,MAAA,EAA2B,EAAA;AACpC,IAAA,MAAM,QAAA,GAAY,EAAyC,IAAA,IAAQ,EAAA;AACnE,IAAA,OAAO,CAAA,EAAG,QAAQ,CAAA,EAAA,EAAK,QAAQ,IAAI,QAAQ,CAAA,CAAA;AAAA,EAC7C,CAAC,CAAA,CACA,IAAA,CAAK,GAAG,CAAA;AAEX,EAAA,SAAA,CAAU,MAAM;AAEd,IAAA,MAAM,SAAA,GAAY,aAAa,GAAA,CAAI,CAAC,UAAU,EAAE,GAAG,MAAK,CAAE,CAAA;AAC1D,IAAA,MAAM,SAAA,GAAY,aAAa,GAAA,CAAI,CAAC,UAAU,EAAE,GAAG,MAAK,CAAE,CAAA;AAI1D,IAAA,IAAI;AAGF,MAAA,SAAA,CAAU,OAAA,CAAQ,CAAC,CAAA,EAAG,CAAA,KAAM;AAE1B,QAAA,MAAM,KAAA,GAAS,CAAA,GAAI,CAAA,GAAI,IAAA,CAAK,KAAM,SAAA,CAAU,MAAA;AAE5C,QAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,KAAA,EAAO,MAAM,CAAA,GAAI,IAAA;AACzC,QAAA,CAAA,CAAE,IAAI,KAAA,GAAQ,CAAA,GAAI,MAAA,GAAS,IAAA,CAAK,IAAI,KAAK,CAAA;AACzC,QAAA,CAAA,CAAE,IAAI,MAAA,GAAS,CAAA,GAAI,MAAA,GAAS,IAAA,CAAK,IAAI,KAAK,CAAA;AAE1C,QAAA,CAAA,CAAE,EAAA,GAAA,CAAM,IAAA,CAAK,MAAA,EAAO,GAAI,GAAA,IAAO,CAAA;AAC/B,QAAA,CAAA,CAAE,EAAA,GAAA,CAAM,IAAA,CAAK,MAAA,EAAO,GAAI,GAAA,IAAO,CAAA;AAAA,MACjC,CAAC,CAAA;AAAA,IACH,SAAS,CAAA,EAAG;AACV,MAAA,OAAA,CAAQ,IAAA,CAAK,0DAA0D,CAAC,CAAA;AAExE,MAAA,mBAAA,CAAoB,SAAA,EAAW,OAAO,MAAM,CAAA;AAAA,IAC9C;AAGA,IAAA,MAAM,UAAA,GAAgB,EAAA,CAAA,eAAA;AAAA,MACpB;AAAA,KACF;AAGA,IAAA,IAAI;AACF,MAAA,MAAM,SAAA,GAAe,EAAA,CAAA,SAAA;AAAA,QACnB;AAAA,OACF;AACA,MAAA,SAAA,CACG,EAAA,CAAG,CAAC,CAAA,KAAsB,CAAA,CAAE,EAAE,CAAA,CAC9B,QAAA,CAAS,CAAC,CAAA,KAA8C;AACvD,QAAA,MAAM,IAAA,GAAO,CAAA;AACb,QAAA,OAAO,IAAA,IAAQ,IAAA,CAAK,QAAA,IAAY,IAAA,GAAO,KAAK,QAAA,GAAW,YAAA;AAAA,MACzD,CAAC,CAAA,CACA,QAAA,CAAS,YAAY,CAAA;AACxB,MAAA,UAAA,CAAW,KAAA;AAAA,QACT,MAAA;AAAA,QACA;AAAA,OAIF;AAAA,IACF,SAAS,CAAA,EAAG;AACV,MAAA,OAAA,CAAQ,IAAA,CAAK,mDAAmD,CAAC,CAAA;AAEjE,MAAA,IAAI;AACF,QAAA,UAAA,CAAW,KAAA;AAAA,UACT,MAAA;AAAA,UACG,EAAA,CAAA,SAAA;AAAA,YACD;AAAA;AACF,SACF;AAAA,MACF,SAAS,aAAA,EAAe;AACtB,QAAA,OAAA,CAAQ,IAAA,CAAK,oCAAoC,aAAa,CAAA;AAAA,MAChE;AAAA,IACF;AACA,IAAA,IAAI;AACF,MAAA,UAAA,CAAW,KAAA;AAAA,QACT,QAAA;AAAA,QACG,EAAA,CAAA,aAAA,EAAc,CAAE,QAAA,CAAS,cAAc;AAAA,OAI5C;AACA,MAAA,UAAA,CAAW,KAAA;AAAA,QACT,QAAA;AAAA,QAEG,eAAY,KAAA,GAAQ,CAAA,EAAG,SAAS,CAAC,CAAA,CACjC,SAAS,cAAc;AAAA,OAI5B;AACA,MAAA,MAAM,OAAA,GACH,EAAA,CAAA,YAAA,EAAa,CACb,MAAA,CAAO,CAAC,CAAA,KAA8B;AACrC,QAAA,MAAM,IAAA,GAAO,CAAA;AACb,QAAA,MAAM,QAAA,GAAW,IAAA,IAAQ,IAAA,CAAK,IAAA,GAAQ,KAAK,IAAA,GAAkB,EAAA;AAC7D,QAAA,OAAO,QAAA,GAAW,eAAA;AAAA,MACpB,CAAC,CAAA,CACA,QAAA,CAAS,iBAAiB,CAAA;AAI7B,MAAA,UAAA,CAAW,KAAA,CAAM,aAAa,OAAO,CAAA;AACrC,MAAA,UAAA,CAAW,KAAA;AAAA,QACT,GAAA;AAAA,QAEG,EAAA,CAAA,MAAA,CAAO,KAAA,GAAQ,CAAC,CAAA,CAChB,QAAA,CAAS,KAAK,GAAA,CAAI,IAAA,EAAM,cAAA,GAAiB,GAAG,CAAC;AAAA,OAIlD;AACA,MAAA,UAAA,CAAW,KAAA;AAAA,QACT,GAAA;AAAA,QAEG,EAAA,CAAA,MAAA,CAAO,MAAA,GAAS,CAAC,CAAA,CACjB,QAAA,CAAS,KAAK,GAAA,CAAI,IAAA,EAAM,cAAA,GAAiB,GAAG,CAAC;AAAA,OAIlD;AACA,MAAA,UAAA,CAAW,WAAW,UAAU,CAAA;AAChC,MAAA,UAAA,CAAW,cAAc,aAAa,CAAA;AACtC,MAAA,UAAA,CAAW,SAAS,QAAQ,CAAA;AAC5B,MAAA,IAAI;AACF,QAAA,UAAA,CAAW,YAAY,WAAW,CAAA;AAAA,MACpC,SAAS,CAAA,EAAG;AACV,QAAA,OAAA,CAAQ,IAAA,CAAK,+BAA+B,CAAC,CAAA;AAAA,MAC/C;AACA,MAAA,IAAI;AACF,QAAA,UAAA,CAAW,MAAM,SAAS,CAAA;AAAA,MAC5B,SAAS,CAAA,EAAG;AACV,QAAA,OAAA,CAAQ,IAAA,CAAK,gCAAgC,CAAC,CAAA;AAAA,MAChD;AAAA,IACF,SAAS,CAAA,EAAG;AACV,MAAA,OAAA,CAAQ,IAAA,CAAK,0CAA0C,CAAC,CAAA;AAAA,IAE1D;AAEA,IAAA,aAAA,CAAc,OAAA,GAAU,UAAA;AAGxB,IAAA,IAAI,cAAA,CAAe,WAAW,IAAA,EAAM;AAClC,MAAA,IAAI;AACF,QAAA,UAAA,CAAW,YAAA,CAAa,eAAe,OAAO,CAAA;AAAA,MAChD,SAAS,CAAA,EAAG;AACV,QAAA,OAAA,CAAQ,IAAA,CAAK,uCAAuC,CAAC,CAAA;AAAA,MACvD;AACA,MAAA,cAAA,CAAe,OAAA,GAAU,IAAA;AAAA,IAC3B;AACA,IAAA,IAAI,mBAAA,IAAuB,sBAAsB,CAAA,EAAG;AAClD,MAAA,cAAA,CAAe,OAAA,GAAU,UAAA,CAAW,UAAA,CAAW,MAAM;AACnD,QAAA,IAAI;AACF,UAAA,IAAI,eAAA,EAAiB;AACnB,YAAA,cAAA,CAAe,SAAS,CAAA;AAAA,UAC1B;AACA,UAAA,UAAA,CAAW,MAAM,CAAC,CAAA;AAClB,UAAA,UAAA,CAAW,IAAA,EAAK;AAAA,QAClB,SAAS,CAAA,EAAG;AACV,UAAA,OAAA,CAAQ,IAAA,CAAK,8BAA8B,CAAC,CAAA;AAAA,QAC9C;AACA,QAAA,YAAA,CAAa,KAAK,CAAA;AAClB,QAAA,QAAA,CAAS,CAAC,GAAG,SAAS,CAAC,CAAA;AACvB,QAAA,QAAA,CAAS,CAAC,GAAG,SAAS,CAAC,CAAA;AAAA,MACzB,GAAG,mBAAmB,CAAA;AAAA,IACxB;AAIA,IAAA,IAAI,KAAA,GAAuB,IAAA;AAC3B,IAAA,IAAI,UAAA,GAAa,CAAA;AACjB,IAAA,MAAM,cAAc,MAAM;AACxB,MAAA,IAAI;AACF,QAAA,IAAI,OAAO,MAAA,KAAW,UAAA;AACpB,UAAA,MAAA,CAAO,SAAA,EAAW,WAAW,UAAU,CAAA;AAAA,MAC3C,SAAS,CAAA,EAAG;AACV,QAAA,OAAA,CAAQ,IAAA,CAAK,wBAAwB,CAAC,CAAA;AAAA,MACxC;AAIA,MAAA,IAAI;AACF,QAAA,IAAI,UAAA,CAAW,KAAA,EAAM,IAAK,QAAA,EAAU;AAClC,UAAA,IAAI;AACF,YAAA,IAAI,eAAA,EAAiB;AACnB,cAAA,cAAA,CAAe,SAAS,CAAA;AAAA,YAC1B;AACA,YAAA,UAAA,CAAW,IAAA,EAAK;AAAA,UAClB,SAAS,CAAA,EAAG;AACV,YAAA,OAAA,CAAQ,IAAA,CAAK,8BAA8B,CAAC,CAAA;AAAA,UAC9C;AACA,UAAA,QAAA,CAAS,UAAA,CAAW,OAAO,CAAA;AAC3B,UAAA,YAAA,CAAa,KAAK,CAAA;AAClB,UAAA,QAAA,CAAS,CAAC,GAAG,SAAS,CAAC,CAAA;AACvB,UAAA,QAAA,CAAS,CAAC,GAAG,SAAS,CAAC,CAAA;AACvB,UAAA;AAAA,QACF;AAAA,MACF,SAAS,CAAA,EAAG;AACV,QAAA,OAAA,CAAQ,IAAA,CAAK,oCAAoC,CAAC,CAAA;AAAA,MACpD;AAEA,MAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,MAAA,MAAM,YAAA,GAAe,MAAM,UAAA,IAAc,cAAA;AACzC,MAAA,IAAI,KAAA,IAAS,QAAQ,YAAA,EAAc;AACjC,QAAA,KAAA,GAAA,CACE,UAAA,CAAW,0BACV,CAAC,EAAA,KAA6B,WAAW,EAAA,EAAI,EAAE,IAChD,MAAM;AACN,UAAA,KAAA,GAAQ,IAAA;AACR,UAAA,UAAA,GAAa,KAAK,GAAA,EAAI;AACtB,UAAA,QAAA,CAAS,CAAC,GAAG,SAAS,CAAC,CAAA;AACvB,UAAA,QAAA,CAAS,CAAC,GAAG,SAAS,CAAC,CAAA;AACvB,UAAA,QAAA,CAAS,UAAA,CAAW,OAAO,CAAA;AAC3B,UAAA,YAAA,CAAa,UAAA,CAAW,KAAA,EAAM,GAAI,UAAA,CAAW,UAAU,CAAA;AAAA,QACzD,CAAC,CAAA;AAAA,MACH;AAAA,IACF,CAAA;AAEA,IAAA,UAAA,CAAW,EAAA,CAAG,QAAQ,WAAW,CAAA;AAEjC,IAAA,UAAA,CAAW,EAAA,CAAG,OAAO,MAAM;AACzB,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB,CAAC,CAAA;AAGD,IAAA,OAAO,MAAM;AACX,MAAA,IAAI;AACF,QAAA,UAAA,CAAW,EAAA,CAAG,QAAQ,IAAI,CAAA;AAAA,MAC5B,SAAS,CAAA,EAAG;AACV,QAAA,OAAA,CAAQ,IAAA,CAAK,4CAA4C,CAAC,CAAA;AAAA,MAC5D;AACA,MAAA,IAAI,cAAA,CAAe,WAAW,IAAA,EAAM;AAClC,QAAA,IAAI;AACF,UAAA,UAAA,CAAW,YAAA,CAAa,eAAe,OAAO,CAAA;AAAA,QAChD,SAAS,CAAA,EAAG;AACV,UAAA,OAAA,CAAQ,IAAA,CAAK,uCAAuC,CAAC,CAAA;AAAA,QACvD;AACA,QAAA,cAAA,CAAe,OAAA,GAAU,IAAA;AAAA,MAC3B;AACA,MAAA,IAAI,SAAS,IAAA,EAAM;AACjB,QAAA,IAAI;AACF,UAAA,CACE,WAAW,oBAAA,KACV,CAAC,OAAe,YAAA,CAAa,EAAE,IAChC,KAAK,CAAA;AAAA,QACT,SAAS,CAAA,EAAG;AACV,UAAA,OAAA,CAAQ,IAAA,CAAK,qCAAqC,CAAC,CAAA;AAAA,QACrD;AACA,QAAA,KAAA,GAAQ,IAAA;AAAA,MACV;AACA,MAAA,UAAA,CAAW,IAAA,EAAK;AAAA,IAClB,CAAA;AAAA,EACF,CAAA,EAAG;AAAA,IACD,QAAA;AAAA,IACA,QAAA;AAAA,IACA,cAAA;AAAA,IACA,YAAA;AAAA,IACA,YAAA;AAAA,IACA,iBAAA;AAAA,IACA,eAAA;AAAA,IACA,cAAA;AAAA,IACA,KAAA;AAAA,IACA,MAAA;AAAA,IACA,UAAA;AAAA,IACA,aAAA;AAAA,IACA,WAAA;AAAA,IACA,QAAA;AAAA,IACA,eAAA;AAAA,IACA,cAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,UAAU,MAAM;AACpB,IAAA,IAAI,cAAc,OAAA,EAAS;AAGzB,MAAA,IAAI;AACF,QAAA,aAAA,CAAc,OAAA,CAAQ,WAAA,CAAY,SAAS,CAAA,CAAE,OAAA,EAAQ;AAAA,MACvD,CAAA,CAAA,MAAQ;AACN,QAAA,aAAA,CAAc,QAAQ,OAAA,EAAQ;AAAA,MAChC;AACA,MAAA,YAAA,CAAa,IAAI,CAAA;AAEjB,MAAA,IAAI,cAAA,CAAe,WAAW,IAAA,EAAM;AAClC,QAAA,IAAI;AACF,UAAA,UAAA,CAAW,YAAA,CAAa,eAAe,OAAO,CAAA;AAAA,QAChD,SAAS,CAAA,EAAG;AACV,UAAA,OAAA,CAAQ,IAAA,CAAK,uCAAuC,CAAC,CAAA;AAAA,QACvD;AACA,QAAA,cAAA,CAAe,OAAA,GAAU,IAAA;AAAA,MAC3B;AACA,MAAA,IAAI,mBAAA,IAAuB,sBAAsB,CAAA,EAAG;AAClD,QAAA,cAAA,CAAe,OAAA,GAAU,UAAA,CAAW,UAAA,CAAW,MAAM;AACnD,UAAA,IAAI;AACF,YAAA,aAAA,CAAc,OAAA,EAAS,MAAM,CAAC,CAAA;AAC9B,YAAA,aAAA,CAAc,SAAS,IAAA,EAAK;AAAA,UAC9B,SAAS,CAAA,EAAG;AACV,YAAA,OAAA,CAAQ,IAAA,CAAK,8BAA8B,CAAC,CAAA;AAAA,UAC9C;AACA,UAAA,YAAA,CAAa,KAAK,CAAA;AAAA,QACpB,GAAG,mBAAmB,CAAA;AAAA,MACxB;AAAA,IACF;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,OAAO,MAAM;AACjB,IAAA,IAAI,cAAc,OAAA,EAAS;AACzB,MAAA,aAAA,CAAc,QAAQ,IAAA,EAAK;AAC3B,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,oBAAoB,MAAA,CAAO;AAAA,IAC/B,MAAA,EAAQ,cAAA;AAAA,IACR,IAAA,EAAM,YAAA;AAAA,IACN,SAAA,EAAW;AAAA,GACZ,CAAA;AACD,EAAA,MAAM,gBAAA,GAAmB,OAAO,IAAI,CAAA;AAEpC,EAAA,MAAM,gBAAA,GAAmB,CAAC,OAAA,KAAqB;AAC7C,IAAA,MAAM,MAAM,aAAA,CAAc,OAAA;AAC1B,IAAA,IAAI,CAAC,GAAA,EAAK;AAEV,IAAA,IAAI,gBAAA,CAAiB,YAAY,OAAA,EAAS;AAC1C,IAAA,gBAAA,CAAiB,OAAA,GAAU,OAAA;AAE3B,IAAA,IAAI;AAEF,MAAA,MAAM,SAAS,GAAA,CAAI,KAAA;AAAA,QACjB;AAAA,OACF;AACA,MAAA,IAAI,MAAA,IAAU,OAAO,MAAA,CAAO,QAAA,KAAa,UAAA,EAAY;AACnD,QAAA,MAAA,CAAO,QAAA,CAAS,OAAA,GAAU,iBAAA,CAAkB,OAAA,CAAQ,SAAS,CAAC,CAAA;AAAA,MAChE;AAEA,MAAA,MAAM,IAAA,GAAO,GAAA,CAAI,KAAA,CAAM,MAAM,CAAA;AAI7B,MAAA,IAAI,IAAA,IAAQ,OAAO,IAAA,CAAK,QAAA,KAAa,UAAA,EAAY;AAC/C,QAAA,IAAA,CAAK,QAAA,CAAS,OAAA,GAAU,iBAAA,CAAkB,OAAA,CAAQ,OAAO,CAAC,CAAA;AAAA,MAC5D;AAAA,IACF,SAAS,CAAA,EAAG;AACV,MAAA,OAAA,CAAQ,IAAA,CAAK,uCAAuC,CAAC,CAAA;AAAA,IACvD;AAAA,EACF,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA;AAAA,IACA,IAAA;AAAA,IACA,SAAA;AAAA,IACA,KAAA;AAAA,IACA;AAAA,GACF;AACF;AA+BO,SAAS,QACd,UAAA,EACA;AACA,EAAA,MAAM,WAAA,GAAc,CAAC,KAAA,EAAY,IAAA,KAAyB;AACxD,IAAA,IAAI,CAAC,UAAA,EAAY;AACjB,IAAA,IAAI,CAAC,KAAA,CAAM,MAAA,aAAmB,WAAA,CAAY,GAAG,EAAE,OAAA,EAAQ;AACvD,IAAA,IAAA,CAAK,KAAK,IAAA,CAAK,CAAA;AACf,IAAA,IAAA,CAAK,KAAK,IAAA,CAAK,CAAA;AAAA,EACjB,CAAA;AAEA,EAAA,MAAM,OAAA,GAAU,CAAC,KAAA,EAAY,IAAA,KAAyB;AACpD,IAAA,IAAA,CAAK,KAAK,KAAA,CAAM,CAAA;AAChB,IAAA,IAAA,CAAK,KAAK,KAAA,CAAM,CAAA;AAAA,EAClB,CAAA;AAEA,EAAA,MAAM,SAAA,GAAY,CAAC,KAAA,EAAY,IAAA,KAAyB;AACtD,IAAA,IAAI,CAAC,UAAA,EAAY;AACjB,IAAA,IAAI,CAAC,KAAA,CAAM,MAAA,EAAQ,UAAA,CAAW,YAAY,CAAC,CAAA;AAC3C,IAAA,IAAA,CAAK,EAAA,GAAK,IAAA;AACV,IAAA,IAAA,CAAK,EAAA,GAAK,IAAA;AAAA,EACZ,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,WAAA,EAAa,WAAA;AAAA,IACb,MAAA,EAAQ,OAAA;AAAA,IACR,SAAA,EAAW;AAAA,GACb;AACF","file":"useForceSimulation.js","sourcesContent":["import { SimulationNode } from './simulation-types';\n\n/**\n * Stabilizes nodes by zeroing velocities and rounding positions.\n * Extracted to reduce duplicate patterns in useForceSimulation.\n */\nexport function stabilizeNodes(nodes: SimulationNode[]): void {\n nodes.forEach((n) => {\n (n as any).vx = 0;\n (n as any).vy = 0;\n if (typeof n.x === 'number') n.x = Number(n.x.toFixed(3));\n if (typeof n.y === 'number') n.y = Number(n.y.toFixed(3));\n });\n}\n\n/**\n * Seeds nodes with random positions within bounds.\n * Used as fallback when initial positioning fails.\n */\nexport function seedRandomPositions(\n nodes: SimulationNode[],\n width: number,\n height: number\n): void {\n nodes.forEach((n) => {\n n.x = Math.random() * width;\n n.y = Math.random() * height;\n (n as any).vx = (Math.random() - 0.5) * 10;\n (n as any).vy = (Math.random() - 0.5) * 10;\n });\n}\n","// Import helpers from separate module\nimport { stabilizeNodes, seedRandomPositions } from './simulation-helpers';\nimport type {\n SimulationNode,\n SimulationLink,\n ForceSimulationOptions,\n UseForceSimulationReturn,\n} from './simulation-types';\n\nimport { useEffect, useRef, useState } from 'react';\nimport * as d3 from 'd3';\n\n/**\n * Hook for managing d3-force simulations\n * Automatically handles simulation lifecycle, tick updates, and cleanup\n *\n * @param initialNodes - Initial nodes for the simulation\n * @param initialLinks - Initial links for the simulation\n * @param options - Configuration options for the force simulation\n * @returns Simulation state and control functions\n *\n * @example\n * ```tsx\n * function NetworkGraph() {\n * const nodes = [\n * { id: 'node1', name: 'Node 1' },\n * { id: 'node2', name: 'Node 2' },\n * { id: 'node3', name: 'Node 3' },\n * ];\n *\n * const links = [\n * { source: 'node1', target: 'node2' },\n * { source: 'node2', target: 'node3' },\n * ];\n *\n * const { nodes: simulatedNodes, links: simulatedLinks, restart } = useForceSimulation(\n * nodes,\n * links,\n * {\n * width: 800,\n * height: 600,\n * chargeStrength: -500,\n * linkDistance: 150,\n * }\n * );\n *\n * return (\n * <svg width={800} height={600}>\n * {simulatedLinks.map((link, i) => (\n * <line\n * key={i}\n * x1={(link.source as SimulationNode).x}\n * y1={(link.source as SimulationNode).y}\n * x2={(link.target as SimulationNode).x}\n * y2={(link.target as SimulationNode).y}\n * stroke=\"#999\"\n * />\n * ))}\n * {simulatedNodes.map((node) => (\n * <circle\n * key={node.id}\n * cx={node.x}\n * cy={node.y}\n * r={10}\n * fill=\"#69b3a2\"\n * />\n * ))}\n * </svg>\n * );\n * }\n * ```\n */\nexport function useForceSimulation(\n initialNodes: SimulationNode[],\n initialLinks: SimulationLink[],\n options: ForceSimulationOptions\n): UseForceSimulationReturn & { setForcesEnabled: (enabled: boolean) => void } {\n /**\n * Enable or disable the simulation forces (charge and link forces).\n * When disabled, nodes can still be dragged but won't be affected by forces.\n * @param enabled - When true, simulation forces are active; when false, forces are disabled\n */\n const {\n chargeStrength = -300,\n linkDistance = 100,\n linkStrength = 1,\n collisionStrength = 1,\n collisionRadius = 10,\n centerStrength = 0.1,\n width,\n height,\n alphaDecay = 0.0228,\n velocityDecay = 0.4,\n alphaTarget = 0,\n warmAlpha = 0.3,\n alphaMin = 0.01,\n onTick,\n // Optional throttle in milliseconds for tick updates (reduce React re-renders)\n // Lower values = smoother but more CPU; default ~30ms (~33fps)\n stabilizeOnStop = true,\n tickThrottleMs = 33,\n maxSimulationTimeMs = 3000,\n } = options;\n\n const [nodes, setNodes] = useState<SimulationNode[]>(initialNodes);\n const [links, setLinks] = useState<SimulationLink[]>(initialLinks);\n const [isRunning, setIsRunning] = useState(false);\n const [alpha, setAlpha] = useState(1);\n\n const simulationRef = useRef<d3.Simulation<\n SimulationNode,\n SimulationLink\n > | null>(null);\n const stopTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // Create lightweight keys for nodes/links so we only recreate the simulation\n // when the actual identity/content of inputs change (not when parent passes\n // new array references on each render).\n const nodesKey = initialNodes.map((n) => n.id).join('|');\n const linksKey = (initialLinks || [])\n .map((l) => {\n const sourceId =\n typeof l.source === 'string'\n ? l.source\n : (l.source as SimulationNode)?.id;\n const targetId =\n typeof l.target === 'string'\n ? l.target\n : (l.target as SimulationNode)?.id;\n const linkType = (l as SimulationLink & { type?: string }).type || '';\n return `${sourceId}->${targetId}:${linkType}`;\n })\n .join('|');\n\n useEffect(() => {\n // Create a copy of nodes and links to avoid mutating the original data\n const nodesCopy = initialNodes.map((node) => ({ ...node }));\n const linksCopy = initialLinks.map((link) => ({ ...link }));\n\n // ALWAYS seed initial positions to ensure nodes don't stack at origin\n // This is critical for force-directed graphs to work properly\n try {\n // Always seed positions for all nodes when simulation is created\n // This ensures nodes start spread out even if they have coordinates\n nodesCopy.forEach((n, i) => {\n // Use deterministic but more widely spread positions based on index\n const angle = (i * 2 * Math.PI) / nodesCopy.length;\n // Larger seed radius to encourage an initial spread\n const radius = Math.min(width, height) * 0.45;\n n.x = width / 2 + radius * Math.cos(angle);\n n.y = height / 2 + radius * Math.sin(angle);\n // Add very small random velocity to avoid large initial motion\n n.vx = (Math.random() - 0.5) * 2;\n n.vy = (Math.random() - 0.5) * 2;\n });\n } catch (e) {\n console.warn('Failed to seed node positions, falling back to random:', e);\n // If error, fall back to random positions\n seedRandomPositions(nodesCopy, width, height);\n }\n\n // Create the simulation\n const simulation = d3.forceSimulation(\n nodesCopy as SimulationNode[]\n ) as d3.Simulation<SimulationNode, SimulationLink>;\n\n // Configure link force separately to avoid using generic type args on d3 helpers\n try {\n const linkForce = d3.forceLink(\n linksCopy as d3.SimulationLinkDatum<SimulationNode>[]\n ) as d3.ForceLink<SimulationNode, d3.SimulationLinkDatum<SimulationNode>>;\n linkForce\n .id((d: SimulationNode) => d.id)\n .distance((d: d3.SimulationLinkDatum<SimulationNode>) => {\n const link = d as SimulationLink & { distance?: number };\n return link && link.distance != null ? link.distance : linkDistance;\n })\n .strength(linkStrength);\n simulation.force(\n 'link',\n linkForce as d3.Force<\n SimulationNode,\n d3.SimulationLinkDatum<SimulationNode>\n >\n );\n } catch (e) {\n console.warn('Failed to configure link force, using fallback:', e);\n // fallback: attach a plain link force\n try {\n simulation.force(\n 'link',\n d3.forceLink(\n linksCopy as d3.SimulationLinkDatum<SimulationNode>[]\n ) as d3.Force<SimulationNode, d3.SimulationLinkDatum<SimulationNode>>\n );\n } catch (fallbackError) {\n console.warn('Fallback link force also failed:', fallbackError);\n }\n }\n try {\n simulation.force(\n 'charge',\n d3.forceManyBody().strength(chargeStrength) as d3.Force<\n SimulationNode,\n d3.SimulationLinkDatum<SimulationNode>\n >\n );\n simulation.force(\n 'center',\n d3\n .forceCenter(width / 2, height / 2)\n .strength(centerStrength) as d3.Force<\n SimulationNode,\n d3.SimulationLinkDatum<SimulationNode>\n >\n );\n const collide = d3\n .forceCollide()\n .radius((d: d3.SimulationNodeDatum) => {\n const node = d as SimulationNode;\n const nodeSize = node && node.size ? (node.size as number) : 10;\n return nodeSize + collisionRadius;\n })\n .strength(collisionStrength) as d3.Force<\n SimulationNode,\n d3.SimulationLinkDatum<SimulationNode>\n >;\n simulation.force('collision', collide);\n simulation.force(\n 'x',\n d3\n .forceX(width / 2)\n .strength(Math.max(0.02, centerStrength * 0.5)) as d3.Force<\n SimulationNode,\n d3.SimulationLinkDatum<SimulationNode>\n >\n );\n simulation.force(\n 'y',\n d3\n .forceY(height / 2)\n .strength(Math.max(0.02, centerStrength * 0.5)) as d3.Force<\n SimulationNode,\n d3.SimulationLinkDatum<SimulationNode>\n >\n );\n simulation.alphaDecay(alphaDecay);\n simulation.velocityDecay(velocityDecay);\n simulation.alphaMin(alphaMin);\n try {\n simulation.alphaTarget(alphaTarget);\n } catch (e) {\n console.warn('Failed to set alpha target:', e);\n }\n try {\n simulation.alpha(warmAlpha);\n } catch (e) {\n console.warn('Failed to set initial alpha:', e);\n }\n } catch (e) {\n console.warn('Failed to configure simulation forces:', e);\n // ignore force configuration errors\n }\n\n simulationRef.current = simulation;\n\n // Force-stop timeout to ensure simulation doesn't run forever.\n if (stopTimeoutRef.current != null) {\n try {\n globalThis.clearTimeout(stopTimeoutRef.current);\n } catch (e) {\n console.warn('Failed to clear simulation timeout:', e);\n }\n stopTimeoutRef.current = null;\n }\n if (maxSimulationTimeMs && maxSimulationTimeMs > 0) {\n stopTimeoutRef.current = globalThis.setTimeout(() => {\n try {\n if (stabilizeOnStop) {\n stabilizeNodes(nodesCopy);\n }\n simulation.alpha(0);\n simulation.stop();\n } catch (e) {\n console.warn('Failed to stop simulation:', e);\n }\n setIsRunning(false);\n setNodes([...nodesCopy]);\n setLinks([...linksCopy]);\n }, maxSimulationTimeMs);\n }\n\n // Update state on each tick. Batch updates via requestAnimationFrame to avoid\n // excessive React re-renders which can cause visual flicker.\n let rafId: number | null = null;\n let lastUpdate = 0;\n const tickHandler = () => {\n try {\n if (typeof onTick === 'function')\n onTick(nodesCopy, linksCopy, simulation);\n } catch (e) {\n console.warn('Tick callback error:', e);\n }\n\n // If simulation alpha has cooled below the configured minimum, stop it to\n // ensure nodes don't drift indefinitely (acts as a hard-stop safeguard).\n try {\n if (simulation.alpha() <= alphaMin) {\n try {\n if (stabilizeOnStop) {\n stabilizeNodes(nodesCopy);\n }\n simulation.stop();\n } catch (e) {\n console.warn('Failed to stop simulation:', e);\n }\n setAlpha(simulation.alpha());\n setIsRunning(false);\n setNodes([...nodesCopy]);\n setLinks([...linksCopy]);\n return;\n }\n } catch (e) {\n console.warn('Error checking simulation alpha:', e);\n }\n\n const now = Date.now();\n const shouldUpdate = now - lastUpdate >= tickThrottleMs;\n if (rafId == null && shouldUpdate) {\n rafId = (\n globalThis.requestAnimationFrame ||\n ((cb: FrameRequestCallback) => setTimeout(cb, 16))\n )(() => {\n rafId = null;\n lastUpdate = Date.now();\n setNodes([...nodesCopy]);\n setLinks([...linksCopy]);\n setAlpha(simulation.alpha());\n setIsRunning(simulation.alpha() > simulation.alphaMin());\n });\n }\n };\n\n simulation.on('tick', tickHandler);\n\n simulation.on('end', () => {\n setIsRunning(false);\n });\n\n // Cleanup on unmount\n return () => {\n try {\n simulation.on('tick', null);\n } catch (e) {\n console.warn('Failed to clear simulation tick handler:', e);\n }\n if (stopTimeoutRef.current != null) {\n try {\n globalThis.clearTimeout(stopTimeoutRef.current);\n } catch (e) {\n console.warn('Failed to clear timeout on cleanup:', e);\n }\n stopTimeoutRef.current = null;\n }\n if (rafId != null) {\n try {\n (\n globalThis.cancelAnimationFrame ||\n ((id: number) => clearTimeout(id))\n )(rafId);\n } catch (e) {\n console.warn('Failed to cancel animation frame:', e);\n }\n rafId = null;\n }\n simulation.stop();\n };\n }, [\n nodesKey,\n linksKey,\n chargeStrength,\n linkDistance,\n linkStrength,\n collisionStrength,\n collisionRadius,\n centerStrength,\n width,\n height,\n alphaDecay,\n velocityDecay,\n alphaTarget,\n alphaMin,\n stabilizeOnStop,\n tickThrottleMs,\n maxSimulationTimeMs,\n ]);\n\n const restart = () => {\n if (simulationRef.current) {\n // Reheat the simulation to a modest alpha target rather than forcing\n // full heat; this matches the Observable pattern and helps stability.\n try {\n simulationRef.current.alphaTarget(warmAlpha).restart();\n } catch {\n simulationRef.current.restart();\n }\n setIsRunning(true);\n // Reset safety timeout when simulation is manually restarted\n if (stopTimeoutRef.current != null) {\n try {\n globalThis.clearTimeout(stopTimeoutRef.current);\n } catch (e) {\n console.warn('Failed to clear simulation timeout:', e);\n }\n stopTimeoutRef.current = null;\n }\n if (maxSimulationTimeMs && maxSimulationTimeMs > 0) {\n stopTimeoutRef.current = globalThis.setTimeout(() => {\n try {\n simulationRef.current?.alpha(0);\n simulationRef.current?.stop();\n } catch (e) {\n console.warn('Failed to stop simulation:', e);\n }\n setIsRunning(false);\n }, maxSimulationTimeMs);\n }\n }\n };\n\n const stop = () => {\n if (simulationRef.current) {\n simulationRef.current.stop();\n setIsRunning(false);\n }\n };\n\n const originalForcesRef = useRef({\n charge: chargeStrength,\n link: linkStrength,\n collision: collisionStrength,\n });\n const forcesEnabledRef = useRef(true);\n\n const setForcesEnabled = (enabled: boolean) => {\n const sim = simulationRef.current;\n if (!sim) return;\n // avoid repeated updates\n if (forcesEnabledRef.current === enabled) return;\n forcesEnabledRef.current = enabled;\n\n try {\n // Only toggle charge and link forces to avoid collapse; keep collision/centering\n const charge = sim.force(\n 'charge'\n ) as d3.ForceManyBody<SimulationNode> | null;\n if (charge && typeof charge.strength === 'function') {\n charge.strength(enabled ? originalForcesRef.current.charge : 0);\n }\n\n const link = sim.force('link') as d3.ForceLink<\n SimulationNode,\n d3.SimulationLinkDatum<SimulationNode>\n > | null;\n if (link && typeof link.strength === 'function') {\n link.strength(enabled ? originalForcesRef.current.link : 0);\n }\n } catch (e) {\n console.warn('Failed to toggle simulation forces:', e);\n }\n };\n\n return {\n nodes,\n links,\n restart,\n stop,\n isRunning,\n alpha,\n setForcesEnabled,\n };\n}\n\n/**\n * Hook for creating a draggable force simulation\n * Provides drag handlers that can be attached to node elements\n *\n * @param simulation - The d3 force simulation instance\n * @returns Drag behavior that can be applied to nodes\n *\n * @example\n * ```tsx\n * function DraggableNetworkGraph() {\n * const simulation = useRef<d3.Simulation<SimulationNode, SimulationLink>>();\n * const drag = useDrag(simulation.current);\n *\n * return (\n * <svg>\n * {nodes.map((node) => (\n * <circle\n * key={node.id}\n * {...drag}\n * cx={node.x}\n * cy={node.y}\n * r={10}\n * />\n * ))}\n * </svg>\n * );\n * }\n * ```\n */\nexport function useDrag(\n simulation: d3.Simulation<SimulationNode, any> | null | undefined\n) {\n const dragStarted = (event: any, node: SimulationNode) => {\n if (!simulation) return;\n if (!event.active) simulation.alphaTarget(0.3).restart();\n node.fx = node.x;\n node.fy = node.y;\n };\n\n const dragged = (event: any, node: SimulationNode) => {\n node.fx = event.x;\n node.fy = event.y;\n };\n\n const dragEnded = (event: any, node: SimulationNode) => {\n if (!simulation) return;\n if (!event.active) simulation.alphaTarget(0);\n node.fx = null;\n node.fy = null;\n };\n\n return {\n onDragStart: dragStarted,\n onDrag: dragged,\n onDragEnd: dragEnded,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/simulation-helpers.ts","../../src/hooks/simulation-constants.ts","../../src/hooks/useForceSimulation.ts"],"names":[],"mappings":"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","file":"useForceSimulation.js","sourcesContent":["import { SimulationNode } from './simulation-types';\n\n/**\n * Stabilizes nodes by zeroing velocities and rounding positions.\n * Extracted to reduce duplicate patterns in useForceSimulation.\n */\nexport function stabilizeNodes(nodes: SimulationNode[]): void {\n nodes.forEach((n) => {\n n.vx = 0;\n n.vy = 0;\n if (typeof n.x === 'number') n.x = Number(n.x.toFixed(3));\n if (typeof n.y === 'number') n.y = Number(n.y.toFixed(3));\n });\n}\n\n/**\n * Seeds nodes with initial positions in a spread circle.\n * This ensures nodes don't stack at origin and have some initial velocity.\n */\nexport function seedCircularPositions(\n nodes: SimulationNode[],\n width: number,\n height: number\n): void {\n const radius = Math.min(width, height) * 0.45;\n nodes.forEach((n, i) => {\n const angle = (i * 2 * Math.PI) / nodes.length;\n n.x = width / 2 + radius * Math.cos(angle);\n n.y = height / 2 + radius * Math.sin(angle);\n // Add very small random velocity to avoid large initial motion\n n.vx = (Math.random() - 0.5) * 2;\n n.vy = (Math.random() - 0.5) * 2;\n });\n}\n\n/**\n * Seeds nodes with random positions within bounds.\n * Used as fallback when initial positioning fails.\n */\nexport function seedRandomPositions(\n nodes: SimulationNode[],\n width: number,\n height: number\n): void {\n nodes.forEach((n) => {\n n.x = Math.random() * width;\n n.y = Math.random() * height;\n n.vx = (Math.random() - 0.5) * 10;\n n.vy = (Math.random() - 0.5) * 10;\n });\n}\n\n/**\n * Safely stops a d3 simulation and performs cleanup tasks.\n */\nexport function safelyStopSimulation(\n simulation: d3.Simulation<SimulationNode, any>,\n nodes: SimulationNode[],\n options: { stabilize?: boolean } = {}\n): void {\n try {\n if (options.stabilize) {\n stabilizeNodes(nodes);\n }\n simulation.stop();\n } catch (error) {\n console.warn('AIReady: Failed to stop simulation safely:', error);\n }\n}\n","/**\n * Constants for force simulation defaults and configuration\n */\nexport const SIMULATION_DEFAULTS = {\n CHARGE_STRENGTH: -300,\n LINK_DISTANCE: 100,\n LINK_STRENGTH: 1,\n COLLISION_STRENGTH: 1,\n COLLISION_RADIUS: 10,\n CENTER_STRENGTH: 0.1,\n ALPHA_DECAY: 0.0228,\n VELOCITY_DECAY: 0.4,\n ALPHA_TARGET: 0,\n WARM_ALPHA: 0.3,\n ALPHA_MIN: 0.01,\n TICK_THROTTLE_MS: 33, // ~30 fps\n MAX_SIMULATION_TIME_MS: 3000,\n STABILIZE_ON_STOP: true,\n} as const;\n\n/**\n * Force names used in d3-force\n */\nexport const FORCE_NAMES = {\n LINK: 'link',\n CHARGE: 'charge',\n CENTER: 'center',\n COLLISION: 'collision',\n X: 'x',\n Y: 'y',\n} as const;\n\n/**\n * Event names used in d3-force\n */\nexport const EVENT_NAMES = {\n TICK: 'tick',\n END: 'end',\n} as const;\n","/**\n * Hook for managing d3-force simulations\n * Automatically handles simulation lifecycle, tick updates, and cleanup\n */\n\nimport { useEffect, useRef, useState, useCallback } from 'react';\nimport * as d3 from 'd3';\nimport {\n seedRandomPositions,\n seedCircularPositions,\n safelyStopSimulation,\n} from './simulation-helpers';\nimport {\n SIMULATION_DEFAULTS,\n FORCE_NAMES,\n EVENT_NAMES,\n} from './simulation-constants';\nimport type {\n SimulationNode,\n SimulationLink,\n ForceSimulationOptions,\n UseForceSimulationReturn,\n} from './simulation-types';\n\n/**\n * Enhanced return type for the force simulation hook\n */\nexport interface UseForceSimulationReturnExt extends UseForceSimulationReturn {\n /**\n * Enable or disable simulation forces (charge and link forces)\n */\n setForcesEnabled: (enabled: boolean) => void;\n}\n\n/**\n * useForceSimulation: robust d3-force management with React\n * @lastUpdated 2026-03-27\n */\nexport function useForceSimulation(\n initialNodes: SimulationNode[],\n initialLinks: SimulationLink[],\n options: ForceSimulationOptions\n): UseForceSimulationReturnExt {\n const {\n chargeStrength = SIMULATION_DEFAULTS.CHARGE_STRENGTH,\n linkDistance = SIMULATION_DEFAULTS.LINK_DISTANCE,\n linkStrength = SIMULATION_DEFAULTS.LINK_STRENGTH,\n collisionStrength = SIMULATION_DEFAULTS.COLLISION_STRENGTH,\n collisionRadius = SIMULATION_DEFAULTS.COLLISION_RADIUS,\n centerStrength = SIMULATION_DEFAULTS.CENTER_STRENGTH,\n width,\n height,\n alphaDecay = SIMULATION_DEFAULTS.ALPHA_DECAY,\n velocityDecay = SIMULATION_DEFAULTS.VELOCITY_DECAY,\n alphaTarget = SIMULATION_DEFAULTS.ALPHA_TARGET,\n warmAlpha = SIMULATION_DEFAULTS.WARM_ALPHA,\n alphaMin = SIMULATION_DEFAULTS.ALPHA_MIN,\n onTick,\n stabilizeOnStop = SIMULATION_DEFAULTS.STABILIZE_ON_STOP,\n tickThrottleMs = SIMULATION_DEFAULTS.TICK_THROTTLE_MS,\n maxSimulationTimeMs = SIMULATION_DEFAULTS.MAX_SIMULATION_TIME_MS,\n } = options;\n\n const [nodes, setNodes] = useState<SimulationNode[]>(initialNodes);\n const [links, setLinks] = useState<SimulationLink[]>(initialLinks);\n const [isRunning, setIsRunning] = useState(false);\n const [alpha, setAlpha] = useState(1);\n\n const simulationRef = useRef<d3.Simulation<\n SimulationNode,\n SimulationLink\n > | null>(null);\n const stopTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const forcesEnabledRef = useRef(true);\n const originalForcesRef = useRef({\n charge: chargeStrength,\n link: linkStrength,\n });\n\n // Unique keys to detect when to rebuild the simulation\n const nodesKey = initialNodes.map((n) => n.id).join('|');\n const linksKey = initialLinks\n .map((l) => {\n const sourceId =\n typeof l.source === 'string'\n ? l.source\n : (l.source as SimulationNode)?.id;\n const targetId =\n typeof l.target === 'string'\n ? l.target\n : (l.target as SimulationNode)?.id;\n const linkType = (l as any).type || '';\n return `${sourceId}->${targetId}:${linkType}`;\n })\n .join('|');\n\n /**\n * Internal effect to manage simulation lifecycle\n */\n useEffect(() => {\n const nodesCopy = initialNodes.map((node) => ({ ...node }));\n const linksCopy = initialLinks.map((link) => ({ ...link }));\n\n try {\n seedCircularPositions(nodesCopy, width, height);\n } catch (error) {\n console.warn(\n 'AIReady: Position seeding failed, using random fallback:',\n error\n );\n seedRandomPositions(nodesCopy, width, height);\n }\n\n const simulation = d3.forceSimulation<SimulationNode, SimulationLink>(\n nodesCopy\n );\n applySimulationForces(simulation, linksCopy);\n configureSimulationParameters(simulation);\n\n simulationRef.current = simulation;\n\n const rafState = { rafId: null as number | null, lastUpdate: 0 };\n setupTickHandler(simulation, nodesCopy, linksCopy, rafState);\n\n setupStopTimer(simulation, nodesCopy, linksCopy);\n\n return () => cleanupSimulation(simulation, rafState);\n }, [\n nodesKey,\n linksKey,\n chargeStrength,\n linkDistance,\n linkStrength,\n collisionStrength,\n collisionRadius,\n centerStrength,\n width,\n height,\n alphaDecay,\n velocityDecay,\n alphaTarget,\n alphaMin,\n stabilizeOnStop,\n tickThrottleMs,\n maxSimulationTimeMs,\n ]);\n\n /**\n * Applies d3 forces to the simulation instance\n */\n const applySimulationForces = (\n simulation: d3.Simulation<SimulationNode, SimulationLink>,\n linksCopy: SimulationLink[]\n ) => {\n try {\n const linkForce = d3\n .forceLink<SimulationNode, SimulationLink>(linksCopy)\n .id((d) => d.id)\n .distance((d) => (d as any).distance ?? linkDistance)\n .strength(linkStrength);\n\n simulation\n .force(FORCE_NAMES.LINK, linkForce)\n .force(FORCE_NAMES.CHARGE, d3.forceManyBody().strength(chargeStrength))\n .force(\n FORCE_NAMES.CENTER,\n d3.forceCenter(width / 2, height / 2).strength(centerStrength)\n )\n .force(\n FORCE_NAMES.COLLISION,\n d3\n .forceCollide<SimulationNode>()\n .radius((d) => (d.size ?? 10) + collisionRadius)\n .strength(collisionStrength)\n )\n .force(\n FORCE_NAMES.X,\n d3.forceX(width / 2).strength(Math.max(0.02, centerStrength * 0.5))\n )\n .force(\n FORCE_NAMES.Y,\n d3.forceY(height / 2).strength(Math.max(0.02, centerStrength * 0.5))\n );\n } catch (error) {\n console.warn('AIReady: Failed to configure simulation forces:', error);\n }\n };\n\n /**\n * Configures simulation decay and heat parameters\n */\n const configureSimulationParameters = (\n simulation: d3.Simulation<SimulationNode, SimulationLink>\n ) => {\n simulation\n .alphaDecay(alphaDecay)\n .velocityDecay(velocityDecay)\n .alphaMin(alphaMin)\n .alphaTarget(alphaTarget)\n .alpha(warmAlpha);\n };\n\n /**\n * Sets up a timer to force-stop the simulation after maxSimulationTimeMs\n */\n const setupStopTimer = (\n simulation: d3.Simulation<SimulationNode, SimulationLink>,\n nodesCopy: SimulationNode[],\n linksCopy: SimulationLink[]\n ) => {\n if (stopTimeoutRef.current) {\n clearTimeout(stopTimeoutRef.current);\n }\n\n if (maxSimulationTimeMs > 0) {\n stopTimeoutRef.current = setTimeout(() => {\n safelyStopSimulation(simulation, nodesCopy, {\n stabilize: stabilizeOnStop,\n });\n updateStateAfterStop(nodesCopy, linksCopy, 0);\n }, maxSimulationTimeMs);\n }\n };\n\n /**\n * Updates state variables after simulation stops\n */\n const updateStateAfterStop = (\n nodesCopy: SimulationNode[],\n linksCopy: SimulationLink[],\n currentAlpha: number\n ) => {\n setIsRunning(false);\n setAlpha(currentAlpha);\n setNodes([...nodesCopy]);\n setLinks([...linksCopy]);\n };\n\n /**\n * Manages simulation ticks and React state sync\n */\n const setupTickHandler = (\n simulation: d3.Simulation<SimulationNode, SimulationLink>,\n nodesCopy: SimulationNode[],\n linksCopy: SimulationLink[],\n rafState: { rafId: number | null; lastUpdate: number }\n ) => {\n const handleTick = () => {\n if (onTick) {\n try {\n onTick(nodesCopy, linksCopy, simulation);\n } catch (error) {\n console.warn('AIReady: Simulation onTick callback failed:', error);\n }\n }\n\n const currentAlpha = simulation.alpha();\n if (currentAlpha <= alphaMin) {\n safelyStopSimulation(simulation, nodesCopy, {\n stabilize: stabilizeOnStop,\n });\n updateStateAfterStop(nodesCopy, linksCopy, currentAlpha);\n return;\n }\n\n syncStateOnTick(nodesCopy, linksCopy, currentAlpha, rafState);\n };\n\n simulation.on(EVENT_NAMES.TICK, handleTick);\n simulation.on(EVENT_NAMES.END, () => setIsRunning(false));\n };\n\n /**\n * Syncs simulation results to React state using requestAnimationFrame\n */\n const syncStateOnTick = (\n nodesCopy: SimulationNode[],\n linksCopy: SimulationLink[],\n currentAlpha: number,\n rafState: { rafId: number | null; lastUpdate: number }\n ) => {\n const now = Date.now();\n if (\n rafState.rafId === null &&\n now - rafState.lastUpdate >= tickThrottleMs\n ) {\n rafState.rafId = requestAnimationFrame(() => {\n rafState.rafId = null;\n rafState.lastUpdate = Date.now();\n setNodes([...nodesCopy]);\n setLinks([...linksCopy]);\n setAlpha(currentAlpha);\n setIsRunning(currentAlpha > alphaMin);\n });\n }\n };\n\n /**\n * Cleanup routine for simulation unmount or rebuild\n */\n const cleanupSimulation = (\n simulation: d3.Simulation<SimulationNode, SimulationLink>,\n rafState: { rafId: number | null }\n ) => {\n simulation.on(EVENT_NAMES.TICK, null);\n if (stopTimeoutRef.current) clearTimeout(stopTimeoutRef.current);\n if (rafState.rafId !== null) cancelAnimationFrame(rafState.rafId);\n simulation.stop();\n };\n\n /**\n * Restart the simulation manually\n */\n const restartSimulation = useCallback(() => {\n const sim = simulationRef.current;\n if (!sim) return;\n\n try {\n sim.alphaTarget(warmAlpha).restart();\n setIsRunning(true);\n if (stopTimeoutRef.current) clearTimeout(stopTimeoutRef.current);\n if (maxSimulationTimeMs > 0) {\n stopTimeoutRef.current = setTimeout(() => {\n sim.alpha(0);\n sim.stop();\n setIsRunning(false);\n }, maxSimulationTimeMs);\n }\n } catch (error) {\n console.warn('AIReady: Failed to restart simulation:', error);\n }\n }, [warmAlpha, maxSimulationTimeMs]);\n\n /**\n * Stop the simulation manually\n */\n const stopSimulation = useCallback(() => {\n if (simulationRef.current) {\n simulationRef.current.stop();\n setIsRunning(false);\n }\n }, []);\n\n /**\n * Enable or disable simulation forces\n */\n const setForcesEnabled = useCallback(\n (enabled: boolean) => {\n const sim = simulationRef.current;\n if (!sim || forcesEnabledRef.current === enabled) return;\n\n forcesEnabledRef.current = enabled;\n\n try {\n const charge = sim.force(\n FORCE_NAMES.CHARGE\n ) as d3.ForceManyBody<SimulationNode> | null;\n if (charge) {\n charge.strength(enabled ? originalForcesRef.current.charge : 0);\n }\n\n const link = sim.force(FORCE_NAMES.LINK) as d3.ForceLink<\n SimulationNode,\n SimulationLink\n > | null;\n if (link) {\n link.strength(enabled ? originalForcesRef.current.link : 0);\n }\n\n sim.alpha(warmAlpha).restart();\n } catch (error) {\n console.warn('AIReady: Failed to toggle simulation forces:', error);\n }\n },\n [warmAlpha]\n );\n\n return {\n nodes,\n links,\n restart: restartSimulation,\n stop: stopSimulation,\n isRunning,\n alpha,\n setForcesEnabled,\n };\n}\n\n/**\n * Hook for creating a draggable force simulation\n */\nexport function useDrag(\n simulation: d3.Simulation<SimulationNode, any> | null | undefined\n) {\n const handleDragStart = useCallback(\n (event: any, node: SimulationNode) => {\n if (!simulation) return;\n if (!event.active) simulation.alphaTarget(0.3).restart();\n node.fx = node.x;\n node.fy = node.y;\n },\n [simulation]\n );\n\n const handleDragged = useCallback((event: any, node: SimulationNode) => {\n node.fx = event.x;\n node.fy = event.y;\n }, []);\n\n const handleDragEnd = useCallback(\n (event: any, node: SimulationNode) => {\n if (!simulation) return;\n if (!event.active) simulation.alphaTarget(0);\n node.fx = null;\n node.fy = null;\n },\n [simulation]\n );\n\n return {\n onDragStart: handleDragStart,\n onDrag: handleDragged,\n onDragEnd: handleDragEnd,\n };\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export { chartColors, domainColors, getDomainColor, getSeverityColor, hexToRgba,
|
|
|
20
20
|
export { formatCompactNumber, formatDate, formatDateTime, formatDecimal, formatDuration, formatFileSize, formatMetric, formatNumber, formatPercentage, formatRange, formatRelativeTime } from './utils/formatters.js';
|
|
21
21
|
export { useDebounce } from './hooks/useDebounce.js';
|
|
22
22
|
export { useD3, useD3WithResize } from './hooks/useD3.js';
|
|
23
|
-
export { F as ForceSimulationOptions, S as SimulationLink, a as SimulationNode, U as UseForceSimulationReturn, u as useDrag, b as useForceSimulation } from './useForceSimulation-
|
|
23
|
+
export { F as ForceSimulationOptions, S as SimulationLink, a as SimulationNode, U as UseForceSimulationReturn, u as useDrag, b as useForceSimulation } from './useForceSimulation-CjLhYevG.js';
|
|
24
24
|
export { ForceDirectedGraph, ForceDirectedGraphHandle, ForceDirectedGraphProps, GraphLink, GraphNode, LayoutType } from './charts/ForceDirectedGraph.js';
|
|
25
25
|
import 'class-variance-authority/types';
|
|
26
26
|
import 'class-variance-authority';
|