@aiready/components 0.14.3 → 0.14.5
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/charts/ForceDirectedGraph.js.map +1 -1
- package/dist/components/button.d.ts +1 -1
- package/dist/hooks/useForceSimulation.js +46 -23
- package/dist/hooks/useForceSimulation.js.map +1 -1
- package/dist/index.js +46 -23
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/charts/force-directed/useGraphInteractions.ts +2 -2
- package/src/charts/force-directed/useImperativeHandle.ts +1 -1
- package/src/components/__tests__/badge.test.tsx +38 -0
- package/src/components/__tests__/button.test.tsx +54 -0
- package/src/components/__tests__/card.test.tsx +56 -17
- package/src/components/__tests__/checkbox.test.tsx +28 -58
- package/src/components/__tests__/container.test.tsx +44 -51
- package/src/components/__tests__/grid.test.tsx +27 -134
- package/src/components/__tests__/input.test.tsx +35 -20
- package/src/components/__tests__/label.test.tsx +29 -35
- package/src/components/__tests__/modal.test.tsx +43 -72
- package/src/components/__tests__/select.test.tsx +51 -84
- package/src/components/__tests__/separator.test.tsx +23 -56
- package/src/components/__tests__/switch.test.tsx +28 -68
- package/src/components/__tests__/textarea.test.tsx +29 -77
- package/src/hooks/useForceSimulation.ts +85 -36
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/charts/force-directed/useGraphInteractions.ts","../../src/charts/constants.ts","../../src/charts/layout-utils.ts","../../src/charts/force-directed/useGraphLayout.ts","../../src/charts/force-directed/useImperativeHandle.ts","../../src/utils/cn.ts","../../src/charts/NodeItem.tsx","../../src/charts/LinkItem.tsx","../../src/charts/PackageBoundaries.tsx","../../src/charts/force-directed/GraphCanvas.tsx","../../src/charts/force-directed/ForceDirectedGraph.tsx"],"names":["d3","zoom","useEffect","useCallback","d32","jsxs","jsx"],"mappings":";;;;;;;AAKO,SAAS,QAAQ,IAAA,EAAuB;AAC7C,EAAA,IAAA,CAAK,KAAK,IAAA,CAAK,CAAA;AACf,EAAA,IAAA,CAAK,KAAK,IAAA,CAAK,CAAA;AACjB;AAGO,SAAS,UAAU,IAAA,EAAuB;AAC/C,EAAA,IAAA,CAAK,EAAA,GAAK,IAAA;AACV,EAAA,IAAA,CAAK,EAAA,GAAK,IAAA;AACZ;AAGO,SAAS,cAAc,KAAA,EAA0B;AACtD,EAAA,KAAA,CAAM,QAAQ,SAAS,CAAA;AACzB;AAKO,SAAS,YAAA,CACd,MAAA,EACA,IAAA,EACA,UAAA,EACA,cACA,YAAA,EACA;AACA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,UAAA,IAAc,CAAC,OAAO,OAAA,IAAW,CAAC,KAAK,OAAA,EAAS;AAErD,IAAA,MAAM,GAAA,GAASA,GAAA,CAAA,MAAA,CAAO,MAAA,CAAO,OAAO,CAAA;AACpC,IAAA,MAAM,CAAA,GAAOA,GAAA,CAAA,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA;AAEhC,IAAA,MAAMC,KAAAA,GACHD,GAAA,CAAA,IAAA,EAAK,CACL,WAAA,CAAY,CAAC,GAAA,EAAK,EAAE,CAAC,CAAA,CACrB,EAAA,CAAG,MAAA,EAAQ,CAAC,KAAA,KAAe;AAC1B,MAAA,CAAA,CAAE,IAAA,CAAK,WAAA,EAAa,KAAA,CAAM,SAAS,CAAA;AACnC,MAAA,YAAA,CAAa,UAAU,KAAA,CAAM,SAAA;AAC7B,MAAA,YAAA,CAAa,MAAM,SAAS,CAAA;AAAA,IAC9B,CAAC,CAAA;AAEH,IAAA,GAAA,CAAI,KAAKC,KAAI,CAAA;AAEb,IAAA,OAAO,MAAM;AACX,MAAA,GAAA,CAAI,EAAA,CAAG,SAAS,IAAI,CAAA;AAAA,IACtB,CAAA;AAAA,EACF,GAAG,CAAC,UAAA,EAAY,QAAQ,IAAA,EAAM,YAAA,EAAc,YAAY,CAAC,CAAA;AAC3D;AAKO,SAAS,cACd,UAAA,EACA,MAAA,EACA,YAAA,EACA,aAAA,EACA,aACA,SAAA,EACA;AACA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,UAAA,EAAY;AAEjB,IAAA,MAAM,gBAAA,GAAmB,CAAC,KAAA,KAAsB;AAC9C,MAAA,IAAI,CAAC,aAAA,CAAc,OAAA,IAAW,CAAC,YAAY,OAAA,EAAS;AACpD,MAAA,MAAM,MAAM,MAAA,CAAO,OAAA;AACnB,MAAA,IAAI,CAAC,GAAA,EAAK;AACV,MAAA,MAAM,IAAA,GAAO,IAAI,qBAAA,EAAsB;AACvC,MAAA,MAAM,IAAS,YAAA,CAAa,OAAA;AAC5B,MAAA,MAAM,KAAK,KAAA,CAAM,OAAA,GAAU,KAAK,IAAA,GAAO,CAAA,CAAE,KAAK,CAAA,CAAE,CAAA;AAChD,MAAA,MAAM,KAAK,KAAA,CAAM,OAAA,GAAU,KAAK,GAAA,GAAM,CAAA,CAAE,KAAK,CAAA,CAAE,CAAA;AAC/C,MAAA,WAAA,CAAY,QAAQ,EAAA,GAAK,CAAA;AACzB,MAAA,WAAA,CAAY,QAAQ,EAAA,GAAK,CAAA;AAAA,IAC3B,CAAA;AAEA,IAAA,MAAM,iBAAiB,MAAM;AAC3B,MAAA,IAAI,CAAC,cAAc,OAAA,EAAS;AAC5B,MAAA,SAAA,EAAU;AACV,MAAA,WAAA,CAAY,OAAA,GAAU,IAAA;AACtB,MAAA,aAAA,CAAc,OAAA,GAAU,KAAA;AAAA,IAC1B,CAAA;AAEA,IAAA,MAAM,iBAAA,GAAoB,CAAC,KAAA,KAAsB;AAC/C,MAAA,IAAI,KAAA,CAAM,aAAA,KAAkB,IAAA,EAAM,cAAA,EAAe;AAAA,IACnD,CAAA;AAEA,IAAA,MAAA,CAAO,gBAAA,CAAiB,aAAa,gBAAgB,CAAA;AACrD,IAAA,MAAA,CAAO,gBAAA,CAAiB,WAAW,cAAc,CAAA;AACjD,IAAA,MAAA,CAAO,gBAAA,CAAiB,YAAY,iBAAiB,CAAA;AACrD,IAAA,MAAA,CAAO,gBAAA,CAAiB,QAAQ,cAAc,CAAA;AAE9C,IAAA,OAAO,MAAM;AACX,MAAA,MAAA,CAAO,mBAAA,CAAoB,aAAa,gBAAgB,CAAA;AACxD,MAAA,MAAA,CAAO,mBAAA,CAAoB,WAAW,cAAc,CAAA;AACpD,MAAA,MAAA,CAAO,mBAAA,CAAoB,YAAY,iBAAiB,CAAA;AACxD,MAAA,MAAA,CAAO,mBAAA,CAAoB,QAAQ,cAAc,CAAA;AAAA,IACnD,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,UAAA,EAAY,MAAA,EAAQ,cAAc,aAAA,EAAe,WAAA,EAAa,SAAS,CAAC,CAAA;AAC9E;AAKO,SAAS,oBACd,UAAA,EACA,MAAA,EACA,YAAA,EACA,cAAA,EACA,SACA,IAAA,EACA;AACA,EAAA,MAAM,eAAA,GAAkB,WAAA;AAAA,IACtB,CAAC,OAAyB,IAAA,KAAoB;AAC5C,MAAA,IAAI,CAAC,UAAA,EAAY;AACjB,MAAA,KAAA,CAAM,cAAA,EAAe;AACrB,MAAA,KAAA,CAAM,eAAA,EAAgB;AACtB,MAAA,OAAA,CAAQ,IAAI,CAAA;AACZ,MAAA,cAAA,CAAe,CAAC,IAAA,qBAAS,IAAI,GAAA,CAAI,CAAC,GAAG,IAAA,EAAM,IAAA,CAAK,EAAE,CAAC,CAAC,CAAA;AACpD,MAAA,IAAA,EAAK;AAAA,IACP,CAAA;AAAA,IACA,CAAC,UAAA,EAAY,IAAA,EAAM,cAAc;AAAA,GACnC;AAEA,EAAA,MAAM,qBAAA,GAAwB,WAAA;AAAA,IAC5B,CAAC,OAAyB,IAAA,KAAoB;AAC5C,MAAA,KAAA,CAAM,eAAA,EAAgB;AACtB,MAAA,IAAI,CAAC,UAAA,EAAY;AACjB,MAAA,IAAI,IAAA,CAAK,EAAA,KAAO,IAAA,IAAQ,IAAA,CAAK,OAAO,MAAA,EAAW;AAC7C,QAAA,OAAA,CAAQ,IAAI,CAAA;AACZ,QAAA,cAAA,CAAe,CAAC,IAAA,qBAAS,IAAI,GAAA,CAAI,CAAC,GAAG,IAAA,EAAM,IAAA,CAAK,EAAE,CAAC,CAAC,CAAA;AAAA,MACtD,CAAA,MAAO;AACL,QAAA,SAAA,CAAU,IAAI,CAAA;AACd,QAAA,cAAA,CAAe,CAAC,IAAA,KAAS;AACvB,UAAA,MAAM,IAAA,GAAO,IAAI,GAAA,CAAI,IAAI,CAAA;AACzB,UAAA,IAAA,CAAK,MAAA,CAAO,KAAK,EAAE,CAAA;AACnB,UAAA,OAAO,IAAA;AAAA,QACT,CAAC,CAAA;AAAA,MACH;AACA,MAAA,OAAA,EAAQ;AAAA,IACV,CAAA;AAAA,IACA,CAAC,UAAA,EAAY,OAAA,EAAS,cAAc;AAAA,GACtC;AAEA,EAAA,OAAO,EAAE,iBAAiB,qBAAA,EAAsB;AAClD;;;AClJO,IAAM,kBAAA,GAAqB,SAAA;AAC3B,IAAM,iBAAA,GAAoB,EAAA;AAC1B,IAAM,kBAAA,GAAqB,SAAA;AAC3B,IAAM,kBAAA,GAAqB,CAAA;AAK3B,IAAM,4BAAA,GAA+B,IAAA;AACrC,IAAM,gBAAA,GAAmB,EAAA;AAOzB,IAAM,sBAAA,GAAyB,GAAA;AAK/B,IAAM,qBAAA,GAAwB,wBAAA;AAC9B,IAAM,uBAAA,GAA0B,SAAA;AAChC,IAAM,6BAAA,GAAgC,CAAA;AACtC,IAAM,qBAAA,GAAwB,KAAA;AAC9B,IAAM,uBAAA,GAA0B,EAAA;AAChC,IAAM,mBAAA,GAAsB,SAAA;;;AClB5B,SAAS,mBAAA,CACd,KAAA,EACA,KAAA,EACA,MAAA,EACM;AACN,EAAA,MAAM,UAAU,KAAA,GAAQ,CAAA;AACxB,EAAA,MAAM,UAAU,MAAA,GAAS,CAAA;AACzB,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,KAAA,EAAO,MAAM,CAAA,GAAI,4BAAA;AAEzC,EAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,IAAA,EAAM,CAAA,KAAM;AACzB,IAAA,MAAM,KAAA,GAAS,CAAA,GAAI,IAAA,CAAK,EAAA,GAAK,IAAK,KAAA,CAAM,MAAA;AACxC,IAAA,IAAA,CAAK,EAAA,GAAK,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA,GAAI,MAAA;AACtC,IAAA,IAAA,CAAK,EAAA,GAAK,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA,GAAI,MAAA;AACtC,IAAA,IAAA,CAAK,IAAI,IAAA,CAAK,EAAA;AACd,IAAA,IAAA,CAAK,IAAI,IAAA,CAAK,EAAA;AAAA,EAChB,CAAC,CAAA;AACH;AAUO,SAAS,uBAAA,CACd,KAAA,EACA,KAAA,EACA,MAAA,EACM;AACN,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAyB;AAC5C,EAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA,KAAW;AACxB,IAAA,MAAM,GAAA,GAAM,CAAA,CAAE,YAAA,IAAgB,CAAA,CAAE,KAAA,IAAS,MAAA;AACzC,IAAA,IAAI,CAAC,OAAO,GAAA,CAAI,GAAG,GAAG,MAAA,CAAO,GAAA,CAAI,GAAA,EAAK,EAAE,CAAA;AACxC,IAAA,MAAA,CAAO,GAAA,CAAI,GAAG,CAAA,CAAG,IAAA,CAAK,CAAC,CAAA;AAAA,EACzB,CAAC,CAAA;AAED,EAAA,MAAM,UAAA,GAAa,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,SAAS,CAAA;AAC9C,EAAA,MAAM,OAAO,IAAA,CAAK,IAAA,CAAK,KAAK,IAAA,CAAK,UAAA,CAAW,MAAM,CAAC,CAAA;AACnD,EAAA,MAAM,aAAA,GAAiB,QAAQ,GAAA,GAAO,IAAA;AACtC,EAAA,MAAM,gBAAiB,MAAA,GAAS,GAAA,GAAO,KAAK,IAAA,CAAK,UAAA,CAAW,SAAS,IAAI,CAAA;AAEzE,EAAA,UAAA,CAAW,QAAQ,CAAC,CAAC,QAAA,EAAU,UAAU,GAAG,EAAA,KAAO;AACjD,IAAA,MAAM,MAAM,EAAA,GAAK,IAAA;AACjB,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,EAAA,GAAK,IAAI,CAAA;AAChC,IAAA,MAAM,MAAA,GAAA,CAAU,MAAM,GAAA,IAAO,aAAA;AAC7B,IAAA,MAAM,MAAA,GAAA,CAAU,MAAM,GAAA,IAAO,aAAA;AAE7B,IAAA,IAAI,QAAA,CAAS,UAAA,CAAW,MAAM,CAAA,IAAK,aAAa,QAAA,EAAU;AACxD,MAAA,UAAA,CAAW,OAAA,CAAQ,CAAC,CAAA,EAAG,EAAA,KAAO;AAC5B,QAAA,MAAM,KAAA,GAAS,CAAA,GAAI,IAAA,CAAK,EAAA,GAAK,KAAM,UAAA,CAAW,MAAA;AAC9C,QAAA,MAAM,IAAI,IAAA,CAAK,GAAA,CAAI,IAAI,EAAA,GAAK,UAAA,CAAW,SAAS,CAAC,CAAA;AACjD,QAAA,CAAA,CAAE,EAAA,GAAK,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA,GAAI,CAAA;AAClC,QAAA,CAAA,CAAE,EAAA,GAAK,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA,GAAI,CAAA;AAClC,QAAA,CAAA,CAAE,IAAI,CAAA,CAAE,EAAA;AACR,QAAA,CAAA,CAAE,IAAI,CAAA,CAAE,EAAA;AAAA,MACV,CAAC,CAAA;AAAA,IACH;AAAA,EACF,CAAC,CAAA;AACH;AAUO,SAAS,uBAAA,CACd,KAAA,EACA,KAAA,EACA,MAAA,EACM;AACN,EAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,IAAA,KAAS;AACtB,IAAA,IAAI,IAAA,CAAK,EAAA,KAAO,MAAA,IAAa,IAAA,CAAK,OAAO,IAAA,EAAM;AAC7C,MAAA,IAAA,CAAK,CAAA,GAAI,IAAA,CAAK,MAAA,EAAO,GAAI,KAAA;AACzB,MAAA,IAAA,CAAK,CAAA,GAAI,IAAA,CAAK,MAAA,EAAO,GAAI,MAAA;AAAA,IAC3B;AAAA,EACF,CAAC,CAAA;AACH;;;ACjFO,SAAS,cAAA,CACd,YAAA,EACA,KAAA,EACA,MAAA,EACA,QACA,OAAA,EACA;AAEA,EAAA,MAAM,KAAA,GAAQ,QAAQ,MAAM;AAC1B,IAAA,IAAI,CAAC,YAAA,IAAgB,CAAC,YAAA,CAAa,QAAQ,OAAO,YAAA;AAClD,IAAA,MAAM,IAAA,GAAO,aAAa,GAAA,CAAI,CAAC,OAAO,EAAE,GAAG,GAAE,CAAE,CAAA;AAC/C,IAAA,IAAI,MAAA,KAAW,UAAA,EAAY,mBAAA,CAAoB,IAAA,EAAM,OAAO,MAAM,CAAA;AAAA,SAAA,IACzD,MAAA,KAAW,cAAA;AAClB,MAAA,uBAAA,CAAwB,IAAA,EAAM,OAAO,MAAM,CAAA;AAAA,SACxC,uBAAA,CAAwB,IAAA,EAAM,KAAA,EAAO,MAAM,CAAA;AAChD,IAAA,OAAO,IAAA;AAAA,EACT,GAAG,CAAC,YAAA,EAAc,KAAA,EAAO,MAAA,EAAQ,MAAM,CAAC,CAAA;AAGxC,EAAAC,UAAU,MAAM;AACd,IAAA,IAAI,CAAC,KAAA,IAAS,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG;AAClC,IAAA,IAAI,MAAA,KAAW,UAAA,EAAY,mBAAA,CAAoB,KAAA,EAAO,OAAO,MAAM,CAAA;AAAA,SAAA,IAC1D,MAAA,KAAW,cAAA;AAClB,MAAA,uBAAA,CAAwB,KAAA,EAAO,OAAO,MAAM,CAAA;AAE9C,IAAA,OAAA,EAAQ;AAAA,EACV,GAAG,CAAC,MAAA,EAAQ,OAAO,KAAA,EAAO,MAAA,EAAQ,OAAO,CAAC,CAAA;AAE1C,EAAA,OAAO,EAAE,KAAA,EAAM;AACjB;AAKO,SAAS,qBAAA,GAAwB;AACtC,EAAA,MAAM,OAAA,GAAUC,YAAY,MAAM;AAAA,EAAC,CAAA,EAAG,EAAE,CAAA;AACxC,EAAA,MAAM,IAAA,GAAOA,YAAY,MAAM;AAAA,EAAC,CAAA,EAAG,EAAE,CAAA;AACrC,EAAA,MAAM,gBAAA,GAAmBA,WAAAA,CAAY,CAAC,OAAA,KAAsB;AACrD,EACP,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,gBAAA,EAAiB;AAC3C;ACxBO,SAAS,0BAAA,CAA2B;AAAA,EACzC,KAAA;AAAA,EACA,WAAA;AAAA,EACA,cAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,kBAAA;AAAA,EACA,MAAA;AAAA,EACA,IAAA;AAAA,EACA,YAAA;AAAA,EACA;AACF,CAAA,EAAuD;AACrD,EAAA,MAAM,MAAA,GAASA,YAAY,MAAM;AAC/B,IAAA,MAAM,SAAA,uBAAgB,GAAA,EAAY;AAClC,IAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,IAAA,KAAS;AACtB,MAAA,OAAA,CAAQ,IAAI,CAAA;AACZ,MAAA,SAAA,CAAU,GAAA,CAAI,KAAK,EAAE,CAAA;AAAA,IACvB,CAAC,CAAA;AACD,IAAA,cAAA,CAAe,SAAS,CAAA;AACxB,IAAA,OAAA,EAAQ;AAAA,EACV,CAAA,EAAG,CAAC,KAAA,EAAO,cAAA,EAAgB,OAAO,CAAC,CAAA;AAEnC,EAAA,MAAM,QAAA,GAAWA,YAAY,MAAM;AACjC,IAAA,aAAA,CAAc,KAAK,CAAA;AACnB,IAAA,cAAA,iBAAe,IAAI,KAAK,CAAA;AACxB,IAAA,OAAA,EAAQ;AAAA,EACV,CAAA,EAAG,CAAC,KAAA,EAAO,cAAA,EAAgB,OAAO,CAAC,CAAA;AAEnC,EAAA,MAAM,WAAA,GAAcA,YAAY,MAAM;AACpC,IAAA,aAAA,CAAc,KAAK,CAAA;AACnB,IAAA,cAAA,iBAAe,IAAI,KAAK,CAAA;AACxB,IAAA,OAAA,EAAQ;AAAA,EACV,CAAA,EAAG,CAAC,KAAA,EAAO,cAAA,EAAgB,OAAO,CAAC,CAAA;AAEnC,EAAA,MAAM,OAAA,GAAUA,YAAY,MAAM;AAChC,IAAA,IAAI,CAAC,MAAA,CAAO,OAAA,IAAW,CAAC,MAAM,MAAA,EAAQ;AACtC,IAAA,IAAI,OAAO,QAAA,EACT,IAAA,GAAO,CAAA,QAAA,EACP,IAAA,GAAO,UACP,IAAA,GAAO,CAAA,QAAA;AACT,IAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,IAAA,KAAS;AACtB,MAAA,IAAI,IAAA,CAAK,CAAA,KAAM,MAAA,IAAa,IAAA,CAAK,MAAM,MAAA,EAAW;AAChD,QAAA,MAAM,IAAA,GAAO,KAAK,IAAA,IAAQ,iBAAA;AAC1B,QAAA,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,IAAA,CAAK,IAAI,IAAI,CAAA;AACnC,QAAA,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,IAAA,CAAK,IAAI,IAAI,CAAA;AACnC,QAAA,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,IAAA,CAAK,IAAI,IAAI,CAAA;AACnC,QAAA,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,IAAA,CAAK,IAAI,IAAI,CAAA;AAAA,MACrC;AAAA,IACF,CAAC,CAAA;AACD,IAAA,IAAI,CAAC,QAAA,CAAS,IAAI,CAAA,EAAG;AACrB,IAAA,MAAM,QAAQ,IAAA,CAAK,GAAA;AAAA,MAAA,CAChB,KAAA,GAAQ,gBAAA,GAAmB,CAAA,KAAM,IAAA,GAAO,IAAA,CAAA;AAAA,MAAA,CACxC,MAAA,GAAS,gBAAA,GAAmB,CAAA,KAAM,IAAA,GAAO,IAAA,CAAA;AAAA,MAC1C;AAAA,KACF;AACA,IAAA,MAAM,CAAA,GAAI,KAAA,GAAQ,CAAA,GAAA,CAAM,IAAA,GAAO,QAAQ,CAAA,GAAK,KAAA;AAC5C,IAAA,MAAM,CAAA,GAAI,MAAA,GAAS,CAAA,GAAA,CAAM,IAAA,GAAO,QAAQ,CAAA,GAAK,KAAA;AAC7C,IAAA,IAAI,IAAA,CAAK,OAAA,IAAW,MAAA,CAAO,OAAA,EAAS;AAClC,MAAA,MAAM,GAAA,GAASC,GAAA,CAAA,MAAA,CAAO,MAAA,CAAO,OAAO,CAAA;AACpC,MAAA,MAAM,eAAkBA,GAAA,CAAA,YAAA,CAAa,SAAA,CAAU,GAAG,CAAC,CAAA,CAAE,MAAM,KAAK,CAAA;AAChE,MAAA,GAAA,CACG,UAAA,GACA,QAAA,CAAS,sBAAsB,EAC/B,IAAA,CAAiBA,GAAA,CAAA,IAAA,EAAK,CAAE,SAAA,EAAkB,YAAY,CAAA;AACzD,MAAA,YAAA,CAAa,YAAY,CAAA;AAAA,IAC3B;AAAA,EACF,CAAA,EAAG,CAAC,KAAA,EAAO,KAAA,EAAO,QAAQ,MAAA,EAAQ,IAAA,EAAM,YAAY,CAAC,CAAA;AAErD,EAAA,MAAM,cAAA,GAAiBD,WAAAA;AAAA,IACrB,MAAM,KAAA,CAAM,IAAA,CAAK,WAAW,CAAA;AAAA,IAC5B,CAAC,WAAW;AAAA,GACd;AAEA,EAAA,MAAM,WAAA,GAAcA,WAAAA;AAAA,IAClB,CAAC,OAAA,KAAqB;AACpB,MAAA,sBAAA,CAAuB,OAAA,GAAU,OAAA;AAAA,IACnC,CAAA;AAAA,IACA,CAAC,sBAAsB;AAAA,GACzB;AAEA,EAAA,MAAM,eAAA,GAAkBA,WAAAA;AAAA,IACtB,CAAC,SAAA,KAA0B;AACzB,MAAA,kBAAA,CAAmB,SAAS,CAAA;AAAA,IAC9B,CAAA;AAAA,IACA,CAAC,kBAAkB;AAAA,GACrB;AAEA,EAAA,MAAM,YAAYA,WAAAA,CAAY,MAAM,MAAA,EAAQ,CAAC,MAAM,CAAC,CAAA;AAEpD,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAA;AAAA,IACA,OAAA;AAAA,IACA,cAAA;AAAA,IACA,WAAA;AAAA,IACA,SAAA,EAAW,eAAA;AAAA,IACX;AAAA,GACF;AACF;AC1HO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;ACQO,IAAM,WAAoC,CAAC;AAAA,EAChD,IAAA;AAAA,EACA,UAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AAAA,EACA,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,SAAA,GAAY,IAAA;AAAA,EACZ,OAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA;AAAA,EACA,YAAA;AAAA,EACA;AACF,CAAA,KAAM;AACJ,EAAA,MAAM,QAAA,GAAW,KAAK,IAAA,IAAQ,eAAA;AAC9B,EAAA,MAAM,SAAA,GAAY,KAAK,KAAA,IAAS,gBAAA;AAEhC,EAAA,MAAM,CAAA,GAAI,KAAK,CAAA,IAAK,CAAA;AACpB,EAAA,MAAM,CAAA,GAAI,KAAK,CAAA,IAAK,CAAA;AAEpB,EAAA,uBACEE,IAAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MAEC,SAAA,EAAU,qBAAA;AAAA,MACV,WAAS,IAAA,CAAK,EAAA;AAAA,MACd,SAAA,EAAW,CAAA,UAAA,EAAa,CAAC,CAAA,CAAA,EAAI,CAAC,CAAA,CAAA,CAAA;AAAA,MAC9B,OAAA,EAAS,MAAM,OAAA,GAAU,IAAI,CAAA;AAAA,MAC7B,aAAA,EAAe,CAAC,CAAA,KAAM,aAAA,GAAgB,GAAG,IAAI,CAAA;AAAA,MAC7C,YAAA,EAAc,MAAM,YAAA,GAAe,IAAI,CAAA;AAAA,MACvC,YAAA,EAAc,MAAM,YAAA,IAAe;AAAA,MACnC,WAAA,EAAa,CAAC,CAAA,KAAM,WAAA,GAAc,GAAG,IAAI,CAAA;AAAA,MAEzC,QAAA,EAAA;AAAA,wBAAAC,GAAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,CAAA,EAAG,QAAA;AAAA,YACH,IAAA,EAAM,SAAA;AAAA,YACN,MAAA,EAAQ,UAAA,GAAa,MAAA,GAAS,SAAA,GAAY,MAAA,GAAS,MAAA;AAAA,YACnD,aAAa,MAAA,GAAS,CAAA,GAAI,UAAA,GAAa,GAAA,GAAM,YAAY,CAAA,GAAI,GAAA;AAAA,YAC7D,OAAA,EAAS,SAAA,IAAa,UAAA,GAAa,CAAA,GAAI;AAAA;AAAA,SACzC;AAAA,QACC,0BACCA,GAAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,GAAG,QAAA,GAAW,CAAA;AAAA,YACd,IAAA,EAAK,MAAA;AAAA,YACL,MAAA,EAAO,SAAA;AAAA,YACP,WAAA,EAAa,CAAA;AAAA,YACb,OAAA,EAAS,GAAA;AAAA,YACT,SAAA,EAAU;AAAA;AAAA,SACZ;AAAA,QAED,SAAA,IAAa,IAAA,CAAK,KAAA,oBACjBA,GAAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,GAAG,QAAA,GAAW,EAAA;AAAA,YACd,IAAA,EAAK,MAAA;AAAA,YACL,QAAA,EAAS,IAAA;AAAA,YACT,UAAA,EAAW,QAAA;AAAA,YACX,gBAAA,EAAiB,QAAA;AAAA,YACjB,aAAA,EAAc,MAAA;AAAA,YACd,SAAA,EAAU,aAAA;AAAA,YAET,QAAA,EAAA,IAAA,CAAK;AAAA;AAAA;AACR;AAAA,KAAA;AAAA,IAtCG,IAAA,CAAK;AAAA,GAwCZ;AAEJ,CAAA;AAEA,IAAO,gBAAA,GAAQ,QAAA;ACzER,IAAM,WAAoC,CAAC;AAAA,EAChD,IAAA;AAAA,EACA,OAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA,GAAY,IAAA;AAAA,EACZ,QAAQ;AACV,CAAA,KAAM;AACJ,EAAA,MAAM,GAAA,GACH,KAAK,MAAA,EAAgB,EAAA,KACrB,OAAO,IAAA,CAAK,MAAA,KAAW,QAAA,GAAW,IAAA,CAAK,MAAA,GAAS,MAAA,CAAA;AACnD,EAAA,MAAM,GAAA,GACH,KAAK,MAAA,EAAgB,EAAA,KACrB,OAAO,IAAA,CAAK,MAAA,KAAW,QAAA,GAAW,IAAA,CAAK,MAAA,GAAS,MAAA,CAAA;AAGnD,EAAA,MAAM,eAAA,GAAkB,CACtB,QAAA,KACoC;AACpC,IAAA,IAAI,OAAO,QAAA,KAAa,QAAA,IAAY,QAAA,KAAa,IAAA,EAAM;AAErD,MAAA,MAAM,IAAA,GAAO,QAAA;AACb,MAAA,OAAO,EAAE,GAAG,IAAA,CAAK,CAAA,IAAK,GAAG,CAAA,EAAG,IAAA,CAAK,KAAK,CAAA,EAAE;AAAA,IAC1C,CAAA,MAAA,IAAW,OAAO,QAAA,KAAa,QAAA,EAAU;AAEvC,MAAA,MAAM,QAAQ,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,QAAQ,CAAA;AACjD,MAAA,IAAI,KAAA,EAAO,OAAO,EAAE,CAAA,EAAG,KAAA,CAAM,KAAK,CAAA,EAAG,CAAA,EAAG,KAAA,CAAM,CAAA,IAAK,CAAA,EAAE;AAAA,IACvD;AACA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AAEA,EAAA,MAAM,SAAA,GAAY,eAAA,CAAgB,IAAA,CAAK,MAAM,CAAA;AAC7C,EAAA,MAAM,SAAA,GAAY,eAAA,CAAgB,IAAA,CAAK,MAAM,CAAA;AAG7C,EAAA,IAAI,CAAC,SAAA,IAAa,CAAC,SAAA,EAAW;AAC5B,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,MAAM,IAAA,GAAA,CAAQ,SAAA,CAAU,CAAA,GAAI,SAAA,CAAU,CAAA,IAAK,CAAA;AAC3C,EAAA,MAAM,IAAA,GAAA,CAAQ,SAAA,CAAU,CAAA,GAAI,SAAA,CAAU,CAAA,IAAK,CAAA;AAE3C,EAAA,uBACED,KAAC,GAAA,EAAA,EACC,QAAA,EAAA;AAAA,oBAAAC,GAAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,IAAI,SAAA,CAAU,CAAA;AAAA,QACd,IAAI,SAAA,CAAU,CAAA;AAAA,QACd,IAAI,SAAA,CAAU,CAAA;AAAA,QACd,IAAI,SAAA,CAAU,CAAA;AAAA,QACd,aAAA,EAAa,GAAA;AAAA,QACb,aAAA,EAAa,GAAA;AAAA,QACb,QAAQ,IAAA,CAAK,KAAA;AAAA,QACb,WAAA,EAAa,IAAA,CAAK,KAAA,IAAS,YAAA,IAAgB,CAAA;AAAA,QAC3C,OAAA,EAAS,GAAA;AAAA,QACT,SAAA,EAAU,qDAAA;AAAA,QACV,OAAA,EAAS,MAAM,OAAA,GAAU,IAAI;AAAA;AAAA,KAC/B;AAAA,IACC,SAAA,IAAa,IAAA,CAAK,KAAA,oBACjBA,GAAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,CAAA,EAAG,IAAA;AAAA,QACH,CAAA,EAAG,IAAA;AAAA,QACH,IAAA,EAAK,MAAA;AAAA,QACL,QAAA,EAAS,IAAA;AAAA,QACT,UAAA,EAAW,QAAA;AAAA,QACX,gBAAA,EAAiB,QAAA;AAAA,QACjB,aAAA,EAAc,MAAA;AAAA,QAEb,QAAA,EAAA,IAAA,CAAK;AAAA;AAAA;AACR,GAAA,EAEJ,CAAA;AAEJ,CAAA;AAEA,IAAO,gBAAA,GAAQ,QAAA;AClER,IAAM,oBAAsD,CAAC;AAAA,EAClE;AACF,CAAA,KAAM;AACJ,EAAA,IAAI,CAAC,iBAAiB,MAAA,CAAO,IAAA,CAAK,aAAa,CAAA,CAAE,MAAA,KAAW,GAAG,OAAO,IAAA;AAEtE,EAAA,uBACEA,GAAAA,CAAC,GAAA,EAAA,EAAE,WAAU,oBAAA,EAAqB,aAAA,EAAc,QAC7C,QAAA,EAAA,MAAA,CAAO,OAAA,CAAQ,aAAa,CAAA,CAAE,GAAA,CAAI,CAAC,CAAC,GAAA,EAAK,CAAC,CAAA,qBACzCD,KAAC,GAAA,EAAA,EACC,QAAA,EAAA;AAAA,oBAAAC,GAAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,IAAI,CAAA,CAAE,CAAA;AAAA,QACN,IAAI,CAAA,CAAE,CAAA;AAAA,QACN,GAAG,CAAA,CAAE,CAAA;AAAA,QACL,IAAA,EAAM,qBAAA;AAAA,QACN,MAAA,EAAQ,uBAAA;AAAA,QACR,WAAA,EAAa,6BAAA;AAAA,QACb,eAAA,EAAiB,qBAAA;AAAA,QACjB,OAAA,EAAS;AAAA;AAAA,KACX;AAAA,oBACAA,GAAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,GAAG,CAAA,CAAE,CAAA;AAAA,QACL,CAAA,EAAG,KAAK,GAAA,CAAI,EAAA,EAAI,EAAE,CAAA,GAAI,CAAA,CAAE,IAAI,EAAE,CAAA;AAAA,QAC9B,IAAA,EAAM,mBAAA;AAAA,QACN,QAAA,EAAU,uBAAA;AAAA,QACV,UAAA,EAAW,QAAA;AAAA,QACX,aAAA,EAAc,MAAA;AAAA,QAEb,QAAA,EAAA,GAAA,CAAI,OAAA,CAAQ,OAAA,EAAS,EAAE;AAAA;AAAA;AAC1B,GAAA,EAAA,EApBM,GAqBR,CACD,CAAA,EACH,CAAA;AAEJ,CAAA;AAEA,iBAAA,CAAkB,WAAA,GAAc,mBAAA;ACXzB,IAAM,cAA0C,CAAC;AAAA,EACtD,MAAA;AAAA,EACA,IAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,WAAA;AAAA,EACA,cAAA;AAAA,EACA,aAAA;AAAA,EACA,gBAAA,GAAmB,kBAAA;AAAA,EACnB,eAAA,GAAkB,iBAAA;AAAA,EAClB,gBAAA,GAAmB,kBAAA;AAAA,EACnB,gBAAA,GAAmB,kBAAA;AAAA,EACnB,cAAA,GAAiB,IAAA;AAAA,EACjB,cAAA,GAAiB,KAAA;AAAA,EACjB,WAAA;AAAA,EACA,WAAA;AAAA,EACA,WAAA;AAAA,EACA,aAAA;AAAA,EACA,qBAAA;AAAA,EACA,eAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAA,KAAM;AACJ,EAAA,uBACED,IAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,MAAA;AAAA,MACL,KAAA;AAAA,MACA,MAAA;AAAA,MACA,SAAA,EAAW,EAAA,CAAG,2BAAA,EAA6B,SAAS,CAAA;AAAA,MACpD,eAAe,MAAM;AACnB,QAAA,aAAA,CAAc,KAAK,CAAA;AACnB,QAAA,cAAA,iBAAe,IAAI,KAAK,CAAA;AACxB,QAAA,OAAA,EAAQ;AAAA,MACV,CAAA;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAAC,GAAAA,CAAC,UACC,QAAA,kBAAAA,GAAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,EAAA,EAAG,OAAA;AAAA,YACH,OAAA,EAAQ,WAAA;AAAA,YACR,IAAA,EAAK,IAAA;AAAA,YACL,IAAA,EAAK,GAAA;AAAA,YACL,WAAA,EAAY,GAAA;AAAA,YACZ,YAAA,EAAa,GAAA;AAAA,YACb,MAAA,EAAO,MAAA;AAAA,YAEP,0BAAAA,GAAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,uBAAA,EAAwB,MAAM,gBAAA,EAAkB;AAAA;AAAA,SAC1D,EACF,CAAA;AAAA,wBAEAD,IAAAA,CAAC,GAAA,EAAA,EAAE,GAAA,EAAK,IAAA,EACL,QAAA,EAAA;AAAA,UAAA,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,EAAM,CAAA,qBAChBC,GAAAA;AAAA,YAAC,gBAAA;AAAA,YAAA;AAAA,cAEC,IAAA;AAAA,cACA,OAAA,EAAS,WAAA;AAAA,cACT,YAAA,EAAc,gBAAA;AAAA,cACd,SAAA,EAAW,cAAA;AAAA,cACX;AAAA,aAAA;AAAA,YALK,QAAQ,CAAC,CAAA;AAAA,WAOjB,CAAA;AAAA,UAEA,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,qBACVA,GAAAA;AAAA,YAAC,gBAAA;AAAA,YAAA;AAAA,cAEC,IAAA;AAAA,cACA,UAAA,EAAY,mBAAmB,IAAA,CAAK,EAAA;AAAA,cACpC,SAAA,EAAW,kBAAkB,IAAA,CAAK,EAAA;AAAA,cAClC,MAAA,EAAQ,WAAA,CAAY,GAAA,CAAI,IAAA,CAAK,EAAE,CAAA;AAAA,cAC/B,eAAA;AAAA,cACA,gBAAA;AAAA,cACA,SAAA,EAAW,cAAA;AAAA,cACX,OAAA,EAAS,WAAA;AAAA,cACT,aAAA,EAAe,qBAAA;AAAA,cACf,YAAA,EAAc,CAAC,CAAA,KAAM,WAAA,GAAc,CAAC,CAAA;AAAA,cACpC,YAAA,EAAc,MAAM,WAAA,GAAc,IAAI,CAAA;AAAA,cACtC,WAAA,EAAa;AAAA,aAAA;AAAA,YAZR,IAAA,CAAK;AAAA,WAcb,CAAA;AAAA,0BACDA,GAAAA,CAAC,iBAAA,EAAA,EAAkB,aAAA,EAAe,aAAA,IAAiB,EAAC,EAAG;AAAA,SAAA,EACzD;AAAA;AAAA;AAAA,GACF;AAEJ,CAAA;ACxGO,IAAM,kBAAA,GAAqB,UAAA;AAAA,EAIhC,CACE;AAAA,IACE,KAAA,EAAO,YAAA;AAAA,IACP,KAAA,EAAO,YAAA;AAAA,IACP,KAAA;AAAA,IACA,MAAA;AAAA,IACA,UAAA,GAAa,IAAA;AAAA,IACb,UAAA,GAAa,IAAA;AAAA,IACb,WAAA;AAAA,IACA,WAAA;AAAA,IACA,WAAA;AAAA,IACA,cAAA;AAAA,IACA,aAAA;AAAA,IACA,gBAAA;AAAA,IACA,eAAA;AAAA,IACA,gBAAA;AAAA,IACA,gBAAA;AAAA,IACA,cAAA;AAAA,IACA,cAAA;AAAA,IACA,SAAA;AAAA,IACA,YAAA,GAAe,KAAA;AAAA,IACf,oBAAA;AAAA,IACA,aAAA;AAAA,IACA,MAAA,EAAQ,cAAA;AAAA,IACR;AAAA,KAEF,GAAA,KACG;AACH,IAAA,MAAM,MAAA,GAAS,OAAsB,IAAI,CAAA;AACzC,IAAA,MAAM,IAAA,GAAO,OAAoB,IAAI,CAAA;AACrC,IAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,QAAA,CAAS,EAAE,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA;AAC/D,IAAA,MAAM,YAAA,GAAe,OAAO,SAAS,CAAA;AACrC,IAAA,MAAM,WAAA,GAAc,OAAyB,IAAI,CAAA;AACjD,IAAA,MAAM,aAAA,GAAgB,OAAO,KAAK,CAAA;AAClC,IAAA,MAAM,CAAC,WAAA,EAAa,cAAc,IAAI,QAAA,iBAAsB,IAAI,KAAK,CAAA;AACrE,IAAA,MAAM,sBAAA,GAAyB,OAAO,UAAU,CAAA;AAChD,IAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,QAAA,CAAqB,kBAAkB,OAAO,CAAA;AAE1E,IAAAJ,UAAU,MAAM;AACd,MAAA,IAAI,kBAAkB,cAAA,KAAmB,MAAA;AACvC,QAAA,SAAA,CAAU,cAAc,CAAA;AAAA,IAC5B,CAAA,EAAG,CAAC,cAAA,EAAgB,MAAM,CAAC,CAAA;AAE3B,IAAA,MAAM,kBAAA,GAAqBC,WAAAA;AAAA,MACzB,CAAC,SAAA,KAA0B;AACzB,QAAA,SAAA,CAAU,SAAS,CAAA;AACnB,QAAA,cAAA,GAAiB,SAAS,CAAA;AAAA,MAC5B,CAAA;AAAA,MACA,CAAC,cAAc;AAAA,KACjB;AAEA,IAAAD,UAAU,MAAM;AACd,MAAA,sBAAA,CAAuB,OAAA,GAAU,UAAA;AAAA,IACnC,CAAA,EAAG,CAAC,UAAU,CAAC,CAAA;AAEf,IAAA,MAAM,EAAE,OAAA,EAAS,IAAA,EAAM,gBAAA,KAAqB,qBAAA,EAAsB;AAClE,IAAA,MAAM,EAAE,OAAM,GAAI,cAAA;AAAA,MAChB,YAAA;AAAA,MACA,KAAA;AAAA,MACA,MAAA;AAAA,MACA,MAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAAA,UAAU,MAAM;AACd,MAAA,gBAAA,CAAiB,EAAE,YAAA,IAAgB,WAAA,CAAY,IAAA,GAAO,CAAA,CAAE,CAAA;AAAA,IAC1D,CAAA,EAAG,CAAC,YAAA,EAAc,WAAA,EAAa,gBAAgB,CAAC,CAAA;AAEhD,IAAA,mBAAA;AAAA,MACE,GAAA;AAAA,MACA,MACE,0BAAA,CAA2B;AAAA,QACzB,KAAA;AAAA,QACA,WAAA;AAAA,QACA,cAAA;AAAA,QACA,OAAA;AAAA,QACA,KAAA;AAAA,QACA,MAAA;AAAA,QACA,MAAA;AAAA,QACA,kBAAA;AAAA,QAEA,MAAA;AAAA,QACA,IAAA;AAAA,QACA,YAAA;AAAA,QACA;AAAA,OACD,CAAA;AAAA,MACH;AAAA,QACE,KAAA;AAAA,QACA,WAAA;AAAA,QACA,OAAA;AAAA,QACA,KAAA;AAAA,QACA,MAAA;AAAA,QACA,MAAA;AAAA,QACA,kBAAA;AAAA,QACA;AAAA;AACF,KACF;AAEA,IAAAA,UAAU,MAAM;AACd,MAAA,oBAAA,GAAuB,YAAY,CAAA;AAAA,IACrC,CAAA,EAAG,CAAC,YAAA,EAAc,oBAAoB,CAAC,CAAA;AAEvC,IAAA,YAAA,CAAa,MAAA,EAAQ,IAAA,EAAM,UAAA,EAAY,YAAA,EAAc,YAAY,CAAA;AACjE,IAAA,aAAA;AAAA,MACE,UAAA;AAAA,MACA,MAAA;AAAA,MACA,YAAA;AAAA,MACA,aAAA;AAAA,MACA,WAAA;AAAA,MACA,MAAM;AACJ,QAAA,gBAAA,CAAiB,IAAI,CAAA;AACrB,QAAA,OAAA,EAAQ;AAAA,MACV;AAAA,KACF;AAEA,IAAAA,UAAU,MAAM;AACd,MAAA,IAAI,CAAC,KAAK,OAAA,EAAS;AACnB,MAAA,MAAM,CAAA,GAAO,GAAA,CAAA,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA;AAChC,MAAA,CAAA,CAAE,SAAA,CAAU,QAAQ,CAAA,CAAE,IAAA,CAAK,WAAqB;AAC9C,QAAA,MAAM,CAAA,GAAO,GAAA,CAAA,MAAA,CAAO,IAAI,CAAA,CAAE,KAAA,EAAM;AAChC,QAAA,IAAI,CAAA;AACF,UAAG,GAAA,CAAA,MAAA,CAAO,IAAI,CAAA,CAAE,IAAA;AAAA,YACd,WAAA;AAAA,YACA,aAAa,CAAA,CAAE,CAAA,IAAK,CAAC,CAAA,CAAA,EAAI,CAAA,CAAE,KAAK,CAAC,CAAA,CAAA;AAAA,WACnC;AAAA,MACJ,CAAC,CAAA;AACD,MAAA,CAAA,CAAE,SAAA,CAAU,MAAM,CAAA,CAAE,IAAA,CAAK,WAAqB;AAC5C,QAAA,MAAM,CAAA,GAAO,GAAA,CAAA,MAAA,CAAO,IAAI,CAAA,CAAE,KAAA,EAAM;AAChC,QAAA,IAAI,CAAC,CAAA,EAAG;AACR,QAAA,MAAM,CAAA,GACJ,OAAO,CAAA,CAAE,MAAA,KAAW,WAChB,CAAA,CAAE,MAAA,GACF,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,EAAE,MAAM,CAAA;AACzC,QAAA,MAAM,CAAA,GACJ,OAAO,CAAA,CAAE,MAAA,KAAW,WAChB,CAAA,CAAE,MAAA,GACF,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,EAAE,MAAM,CAAA;AACzC,QAAA,IAAI,CAAA,IAAK,CAAA;AACP,UAAG,GAAA,CAAA,MAAA,CAAO,IAAI,CAAA,CACX,IAAA,CAAK,MAAM,CAAA,CAAE,CAAC,EACd,IAAA,CAAK,IAAA,EAAM,EAAE,CAAC,CAAA,CACd,KAAK,IAAA,EAAM,CAAA,CAAE,CAAC,CAAA,CACd,IAAA,CAAK,IAAA,EAAM,CAAA,CAAE,CAAC,CAAA;AAAA,MACrB,CAAC,CAAA;AAAA,IACH,CAAA,EAAG,CAAC,KAAA,EAAO,YAAY,CAAC,CAAA;AAExB,IAAA,MAAM,EAAE,eAAA,EAAiB,qBAAA,EAAsB,GAAI,mBAAA;AAAA,MACjD,UAAA;AAAA,MACA,KAAA;AAAA,MACA,WAAA;AAAA,MACA,cAAA;AAAA,MACA,OAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAAA,UAAU,MAAM;AACd,MAAA,IAAI,CAAC,IAAA,CAAK,OAAA,IAAW,CAAC,UAAA,EAAY;AAClC,MAAA,MAAM,CAAA,GAAO,GAAA,CAAA,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA;AAChC,MAAA,MAAM,eACH,GAAA,CAAA,IAAA,EAAK,CACL,EAAA,CAAG,OAAA,EAAS,CAAC,KAAA,KAAe;AAC3B,QAAA,MAAM,MAAA,GAAU,KAAA,CAAM,WAAA,EAAa,MAAA,IAAU,KAAA,CAAM,MAAA;AACnD,QAAA,MAAM,KAAK,MAAA,CAAO,OAAA,GAAU,QAAQ,CAAA,EAAG,aAAa,SAAS,CAAA;AAC7D,QAAA,IAAI,CAAC,EAAA,IAAM,CAAC,sBAAA,CAAuB,OAAA,EAAS;AAC5C,QAAA,MAAM,OAAO,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,EAAE,CAAA;AAC1C,QAAA,IAAI,CAAC,IAAA,EAAM;AACX,QAAA,IAAI,CAAC,KAAA,CAAM,MAAA,EAAQ,OAAA,EAAQ;AAC3B,QAAA,aAAA,CAAc,OAAA,GAAU,IAAA;AACxB,QAAA,WAAA,CAAY,OAAA,GAAU,IAAA;AAAA,MACxB,CAAC,CAAA,CACA,EAAA,CAAG,MAAA,EAAQ,CAAC,KAAA,KAAe;AAC1B,QAAA,IAAI,CAAC,aAAA,CAAc,OAAA,IAAW,CAAC,WAAA,CAAY,OAAA,IAAW,CAAC,MAAA,CAAO,OAAA;AAC5D,UAAA;AACF,QAAA,MAAM,IAAA,GAAO,MAAA,CAAO,OAAA,CAAQ,qBAAA,EAAsB;AAClD,QAAA,WAAA,CAAY,OAAA,CAAQ,MACjB,KAAA,CAAM,WAAA,CAAY,UAAU,IAAA,CAAK,IAAA,GAAO,SAAA,CAAU,CAAA,IAAK,SAAA,CAAU,CAAA;AACpE,QAAA,WAAA,CAAY,OAAA,CAAQ,MACjB,KAAA,CAAM,WAAA,CAAY,UAAU,IAAA,CAAK,GAAA,GAAM,SAAA,CAAU,CAAA,IAAK,SAAA,CAAU,CAAA;AAAA,MACrE,CAAC,CAAA,CACA,EAAA,CAAG,KAAA,EAAO,MAAM;AACf,QAAA,gBAAA,CAAiB,IAAI,CAAA;AACrB,QAAA,OAAA,EAAQ;AAAA,MACV,CAAC,CAAA;AAEH,MAAA,CAAA,CAAE,SAAA,CAAU,QAAQ,CAAA,CAAE,IAAA,CAAK,YAAY,CAAA;AACvC,MAAA,OAAO,MAAM;AACX,QAAA,CAAA,CAAE,SAAA,CAAU,QAAQ,CAAA,CAAE,EAAA,CAAG,SAAS,IAAI,CAAA;AAAA,MACxC,CAAA;AAAA,IACF,CAAA,EAAG,CAAC,IAAA,EAAM,UAAA,EAAY,OAAO,SAAA,EAAW,OAAA,EAAS,gBAAgB,CAAC,CAAA;AAElE,IAAA,uBACEI,GAAAA;AAAA,MAAC,WAAA;AAAA,MAAA;AAAA,QACC,MAAA;AAAA,QACA,IAAA;AAAA,QACA,KAAA;AAAA,QACA,MAAA;AAAA,QACA,SAAA;AAAA,QACA,KAAA;AAAA,QACA,KAAA,EAAO,YAAA;AAAA,QACP,WAAA;AAAA,QACA,cAAA;AAAA,QACA,aAAA;AAAA,QACA,gBAAA;AAAA,QACA,eAAA;AAAA,QACA,gBAAA;AAAA,QACA,gBAAA;AAAA,QACA,cAAA;AAAA,QACA,cAAA;AAAA,QACA,WAAA;AAAA,QACA,WAAA;AAAA,QACA,WAAA;AAAA,QACA,aAAA;AAAA,QACA,qBAAA;AAAA,QACA,eAAA;AAAA,QACA,OAAA;AAAA,QACA;AAAA;AAAA,KACF;AAAA,EAEJ;AACF;AAEA,kBAAA,CAAmB,WAAA,GAAc,oBAAA","file":"ForceDirectedGraph.js","sourcesContent":["import { useCallback, useEffect } from 'react';\nimport * as d3 from 'd3';\nimport { GraphNode } from './types';\n\n/** Pins a node to its current position (sets fx/fy to current x/y) */\nexport function pinNode(node: GraphNode): void {\n node.fx = node.x;\n node.fy = node.y;\n}\n\n/** Unpins a node (sets fx/fy to null) */\nexport function unpinNode(node: GraphNode): void {\n node.fx = null;\n node.fy = null;\n}\n\n/** Unpins all nodes - helper for bulk unpin operations */\nexport function unpinAllNodes(nodes: GraphNode[]): void {\n nodes.forEach(unpinNode);\n}\n\n/**\n * Hook for managing D3 zoom behavior on an SVG element.\n */\nexport function useGraphZoom(\n svgRef: React.RefObject<SVGSVGElement | null>,\n gRef: React.RefObject<SVGGElement | null>,\n enableZoom: boolean,\n setTransform: (transform: { k: number; x: number; y: number }) => void,\n transformRef: React.MutableRefObject<{ k: number; x: number; y: number }>\n) {\n useEffect(() => {\n if (!enableZoom || !svgRef.current || !gRef.current) return;\n\n const svg = d3.select(svgRef.current);\n const g = d3.select(gRef.current);\n\n const zoom = (d3 as any)\n .zoom()\n .scaleExtent([0.1, 10])\n .on('zoom', (event: any) => {\n g.attr('transform', event.transform);\n transformRef.current = event.transform;\n setTransform(event.transform);\n });\n\n svg.call(zoom);\n\n return () => {\n svg.on('.zoom', null);\n };\n }, [enableZoom, svgRef, gRef, setTransform, transformRef]);\n}\n\n/**\n * Hook for managing window-level drag events for smooth node dragging.\n */\nexport function useWindowDrag(\n enableDrag: boolean,\n svgRef: React.RefObject<SVGSVGElement | null>,\n transformRef: React.MutableRefObject<{ k: number; x: number; y: number }>,\n dragActiveRef: React.MutableRefObject<boolean>,\n dragNodeRef: React.MutableRefObject<GraphNode | null>,\n onDragEnd: () => void\n) {\n useEffect(() => {\n if (!enableDrag) return;\n\n const handleWindowMove = (event: MouseEvent) => {\n if (!dragActiveRef.current || !dragNodeRef.current) return;\n const svg = svgRef.current;\n if (!svg) return;\n const rect = svg.getBoundingClientRect();\n const t: any = transformRef.current;\n const x = (event.clientX - rect.left - t.x) / t.k;\n const y = (event.clientY - rect.top - t.y) / t.k;\n dragNodeRef.current.fx = x;\n dragNodeRef.current.fy = y;\n };\n\n const handleWindowUp = () => {\n if (!dragActiveRef.current) return;\n onDragEnd();\n dragNodeRef.current = null;\n dragActiveRef.current = false;\n };\n\n const handleWindowLeave = (event: MouseEvent) => {\n if (event.relatedTarget === null) handleWindowUp();\n };\n\n window.addEventListener('mousemove', handleWindowMove);\n window.addEventListener('mouseup', handleWindowUp);\n window.addEventListener('mouseout', handleWindowLeave);\n window.addEventListener('blur', handleWindowUp);\n\n return () => {\n window.removeEventListener('mousemove', handleWindowMove);\n window.removeEventListener('mouseup', handleWindowUp);\n window.removeEventListener('mouseout', handleWindowLeave);\n window.removeEventListener('blur', handleWindowUp);\n };\n }, [enableDrag, svgRef, transformRef, dragActiveRef, dragNodeRef, onDragEnd]);\n}\n\n/**\n * Hook for managing node interactions (drag, double-click pinning).\n */\nexport function useNodeInteractions(\n enableDrag: boolean,\n _nodes: GraphNode[],\n _pinnedNodes: Set<string>,\n setPinnedNodes: React.Dispatch<React.SetStateAction<Set<string>>>,\n restart: () => void,\n stop: () => void\n) {\n const handleDragStart = useCallback(\n (event: React.MouseEvent, node: GraphNode) => {\n if (!enableDrag) return;\n event.preventDefault();\n event.stopPropagation();\n pinNode(node);\n setPinnedNodes((prev) => new Set([...prev, node.id]));\n stop();\n },\n [enableDrag, stop, setPinnedNodes]\n );\n\n const handleNodeDoubleClick = useCallback(\n (event: React.MouseEvent, node: GraphNode) => {\n event.stopPropagation();\n if (!enableDrag) return;\n if (node.fx === null || node.fx === undefined) {\n pinNode(node);\n setPinnedNodes((prev) => new Set([...prev, node.id]));\n } else {\n unpinNode(node);\n setPinnedNodes((prev) => {\n const next = new Set(prev);\n next.delete(node.id);\n return next;\n });\n }\n restart();\n },\n [enableDrag, restart, setPinnedNodes]\n );\n\n return { handleDragStart, handleNodeDoubleClick };\n}\n","/**\n * Default visual constants for the ForceDirectedGraph component.\n */\nexport const DEFAULT_NODE_COLOR = '#64748b';\nexport const DEFAULT_NODE_SIZE = 10;\nexport const DEFAULT_LINK_COLOR = '#94a3b8';\nexport const DEFAULT_LINK_WIDTH = 1;\n\n/**\n * Layout and interaction thresholds.\n */\nexport const CIRCULAR_LAYOUT_RADIUS_RATIO = 0.35;\nexport const FIT_VIEW_PADDING = 40;\nexport const ZOOM_MIN_SCALE = 0.1;\nexport const ZOOM_MAX_SCALE = 10;\n\n/**\n * Transition and animation durations.\n */\nexport const TRANSITION_DURATION_MS = 300;\n\n/**\n * Package boundary styling.\n */\nexport const PACKAGE_BOUNDARY_FILL = 'rgba(148,163,184,0.06)';\nexport const PACKAGE_BOUNDARY_STROKE = '#475569';\nexport const PACKAGE_BOUNDARY_STROKE_WIDTH = 2;\nexport const PACKAGE_BOUNDARY_DASH = '6 6';\nexport const PACKAGE_LABEL_FONT_SIZE = 11;\nexport const PACKAGE_LABEL_COLOR = '#475569';\n","import { GraphNode } from './force-directed/types';\nimport { CIRCULAR_LAYOUT_RADIUS_RATIO } from './constants';\n\n/**\n * Calculates node positions for a circular layout.\n *\n * @param nodes - Array of dependency nodes.\n * @param width - Canvas width.\n * @param height - Canvas height.\n * @lastUpdated 2026-03-18\n */\nexport function applyCircularLayout(\n nodes: GraphNode[],\n width: number,\n height: number\n): void {\n const centerX = width / 2;\n const centerY = height / 2;\n const radius = Math.min(width, height) * CIRCULAR_LAYOUT_RADIUS_RATIO;\n\n nodes.forEach((node, i) => {\n const angle = (2 * Math.PI * i) / nodes.length;\n node.fx = centerX + Math.cos(angle) * radius;\n node.fy = centerY + Math.sin(angle) * radius;\n node.x = node.fx;\n node.y = node.fy;\n });\n}\n\n/**\n * Calculates node positions for a hierarchical layout by grouping packages.\n *\n * @param nodes - Array of dependency nodes.\n * @param width - Canvas width.\n * @param height - Canvas height.\n * @lastUpdated 2026-03-18\n */\nexport function applyHierarchicalLayout(\n nodes: GraphNode[],\n width: number,\n height: number\n): void {\n const groups = new Map<string, GraphNode[]>();\n nodes.forEach((n: any) => {\n const key = n.packageGroup || n.group || 'root';\n if (!groups.has(key)) groups.set(key, []);\n groups.get(key)!.push(n);\n });\n\n const groupArray = Array.from(groups.entries());\n const cols = Math.ceil(Math.sqrt(groupArray.length));\n const groupSpacingX = (width * 0.8) / cols;\n const groupSpacingY = (height * 0.8) / Math.ceil(groupArray.length / cols);\n\n groupArray.forEach(([groupKey, groupNodes], gi) => {\n const col = gi % cols;\n const row = Math.floor(gi / cols);\n const groupX = (col + 0.5) * groupSpacingX;\n const groupY = (row + 0.5) * groupSpacingY;\n\n if (groupKey.startsWith('pkg:') || groupKey === groupKey) {\n groupNodes.forEach((n, ni) => {\n const angle = (2 * Math.PI * ni) / groupNodes.length;\n const r = Math.min(80, 20 + groupNodes.length * 8);\n n.fx = groupX + Math.cos(angle) * r;\n n.fy = groupY + Math.sin(angle) * r;\n n.x = n.fx;\n n.y = n.fy;\n });\n }\n });\n}\n\n/**\n * Calculates initial random positions for nodes in a force-directed layout.\n *\n * @param nodes - Array of dependency nodes.\n * @param width - Canvas width.\n * @param height - Canvas height.\n * @lastUpdated 2026-03-18\n */\nexport function applyInitialForceLayout(\n nodes: GraphNode[],\n width: number,\n height: number\n): void {\n nodes.forEach((node) => {\n if (node.fx === undefined || node.fx === null) {\n node.x = Math.random() * width;\n node.y = Math.random() * height;\n }\n });\n}\n","import { useCallback, useEffect, useMemo } from 'react';\nimport { GraphNode, LayoutType } from './types';\nimport {\n applyCircularLayout,\n applyHierarchicalLayout,\n applyInitialForceLayout,\n} from '../layout-utils';\n\n/**\n * Hook for managing graph layout algorithms.\n */\nexport function useGraphLayout(\n initialNodes: GraphNode[],\n width: number,\n height: number,\n layout: LayoutType,\n restart: () => void\n) {\n // Initial positioning - delegate to layout utils\n const nodes = useMemo(() => {\n if (!initialNodes || !initialNodes.length) return initialNodes;\n const copy = initialNodes.map((n) => ({ ...n }));\n if (layout === 'circular') applyCircularLayout(copy, width, height);\n else if (layout === 'hierarchical')\n applyHierarchicalLayout(copy, width, height);\n else applyInitialForceLayout(copy, width, height);\n return copy;\n }, [initialNodes, width, height, layout]);\n\n // Apply layout-specific positioning when layout changes\n useEffect(() => {\n if (!nodes || nodes.length === 0) return;\n if (layout === 'circular') applyCircularLayout(nodes, width, height);\n else if (layout === 'hierarchical')\n applyHierarchicalLayout(nodes, width, height);\n\n restart();\n }, [layout, nodes, width, height, restart]);\n\n return { nodes };\n}\n\n/**\n * Hook for managing simulation controls (stubs for API compatibility).\n */\nexport function useSimulationControls() {\n const restart = useCallback(() => {}, []);\n const stop = useCallback(() => {}, []);\n const setForcesEnabled = useCallback((enabled?: boolean) => {\n void enabled;\n }, []);\n\n return { restart, stop, setForcesEnabled };\n}\n","import { useCallback } from 'react';\nimport * as d3 from 'd3';\nimport { GraphNode, LayoutType, ForceDirectedGraphHandle } from './types';\nimport { pinNode, unpinAllNodes } from './useGraphInteractions';\nimport {\n DEFAULT_NODE_SIZE,\n FIT_VIEW_PADDING,\n TRANSITION_DURATION_MS,\n} from '../constants';\n\ninterface UseImperativeHandleProps {\n nodes: GraphNode[];\n pinnedNodes: Set<string>;\n setPinnedNodes: React.Dispatch<React.SetStateAction<Set<string>>>;\n restart: () => void;\n width: number;\n height: number;\n layout: LayoutType;\n handleLayoutChange: (layout: LayoutType) => void;\n setForcesEnabled: (enabled: boolean) => void;\n svgRef: React.RefObject<SVGSVGElement | null>;\n gRef: React.RefObject<SVGGElement | null>;\n setTransform: (transform: { k: number; x: number; y: number }) => void;\n internalDragEnabledRef: React.MutableRefObject<boolean>;\n}\n\n/**\n * Creates the imperative handle methods for the ForceDirectedGraph component.\n */\nexport function useImperativeHandleMethods({\n nodes,\n pinnedNodes,\n setPinnedNodes,\n restart,\n width,\n height,\n layout,\n handleLayoutChange,\n svgRef,\n gRef,\n setTransform,\n internalDragEnabledRef,\n}: UseImperativeHandleProps): ForceDirectedGraphHandle {\n const pinAll = useCallback(() => {\n const newPinned = new Set<string>();\n nodes.forEach((node) => {\n pinNode(node);\n newPinned.add(node.id);\n });\n setPinnedNodes(newPinned);\n restart();\n }, [nodes, setPinnedNodes, restart]);\n\n const unpinAll = useCallback(() => {\n unpinAllNodes(nodes);\n setPinnedNodes(new Set());\n restart();\n }, [nodes, setPinnedNodes, restart]);\n\n const resetLayout = useCallback(() => {\n unpinAllNodes(nodes);\n setPinnedNodes(new Set());\n restart();\n }, [nodes, setPinnedNodes, restart]);\n\n const fitView = useCallback(() => {\n if (!svgRef.current || !nodes.length) return;\n let minX = Infinity,\n maxX = -Infinity,\n minY = Infinity,\n maxY = -Infinity;\n nodes.forEach((node) => {\n if (node.x !== undefined && node.y !== undefined) {\n const size = node.size || DEFAULT_NODE_SIZE;\n minX = Math.min(minX, node.x - size);\n maxX = Math.max(maxX, node.x + size);\n minY = Math.min(minY, node.y - size);\n maxY = Math.max(maxY, node.y + size);\n }\n });\n if (!isFinite(minX)) return;\n const scale = Math.min(\n (width - FIT_VIEW_PADDING * 2) / (maxX - minX),\n (height - FIT_VIEW_PADDING * 2) / (maxY - minY),\n 10\n );\n const x = width / 2 - ((minX + maxX) / 2) * scale;\n const y = height / 2 - ((minY + maxY) / 2) * scale;\n if (gRef.current && svgRef.current) {\n const svg = d3.select(svgRef.current);\n const newTransform = d3.zoomIdentity.translate(x, y).scale(scale);\n svg\n .transition()\n .duration(TRANSITION_DURATION_MS)\n .call((d3 as any).zoom().transform as any, newTransform);\n setTransform(newTransform);\n }\n }, [nodes, width, height, svgRef, gRef, setTransform]);\n\n const getPinnedNodes = useCallback(\n () => Array.from(pinnedNodes),\n [pinnedNodes]\n );\n\n const setDragMode = useCallback(\n (enabled: boolean) => {\n internalDragEnabledRef.current = enabled;\n },\n [internalDragEnabledRef]\n );\n\n const setLayoutMethod = useCallback(\n (newLayout: LayoutType) => {\n handleLayoutChange(newLayout);\n },\n [handleLayoutChange]\n );\n\n const getLayout = useCallback(() => layout, [layout]);\n\n return {\n pinAll,\n unpinAll,\n resetLayout,\n fitView,\n getPinnedNodes,\n setDragMode,\n setLayout: setLayoutMethod,\n getLayout,\n };\n}\n","import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\n/**\n * Merges class names using clsx and tailwind-merge\n * @param inputs - Class values to merge\n * @returns Merged class names\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import React from 'react';\nimport type { GraphNode } from './force-directed/types';\n\nexport interface NodeItemProps {\n node: GraphNode;\n isSelected: boolean;\n isHovered: boolean;\n pinned: boolean;\n defaultNodeSize: number;\n defaultNodeColor: string;\n showLabel?: boolean;\n onClick?: (n: GraphNode) => void;\n onDoubleClick?: (e: React.MouseEvent, n: GraphNode) => void;\n onMouseEnter?: (n: GraphNode) => void;\n onMouseLeave?: () => void;\n onMouseDown?: (e: React.MouseEvent, n: GraphNode) => void;\n}\n\nexport const NodeItem: React.FC<NodeItemProps> = ({\n node,\n isSelected,\n isHovered,\n pinned,\n defaultNodeSize,\n defaultNodeColor,\n showLabel = true,\n onClick,\n onDoubleClick,\n onMouseEnter,\n onMouseLeave,\n onMouseDown,\n}) => {\n const nodeSize = node.size || defaultNodeSize;\n const nodeColor = node.color || defaultNodeColor;\n\n const x = node.x ?? 0;\n const y = node.y ?? 0;\n\n return (\n <g\n key={node.id}\n className=\"cursor-pointer node\"\n data-id={node.id}\n transform={`translate(${x},${y})`}\n onClick={() => onClick?.(node)}\n onDoubleClick={(e) => onDoubleClick?.(e, node)}\n onMouseEnter={() => onMouseEnter?.(node)}\n onMouseLeave={() => onMouseLeave?.()}\n onMouseDown={(e) => onMouseDown?.(e, node)}\n >\n <circle\n r={nodeSize}\n fill={nodeColor}\n stroke={isSelected ? '#000' : isHovered ? '#666' : 'none'}\n strokeWidth={pinned ? 3 : isSelected ? 2.5 : isHovered ? 2 : 1.5}\n opacity={isHovered || isSelected ? 1 : 0.9}\n />\n {pinned && (\n <circle\n r={nodeSize + 4}\n fill=\"none\"\n stroke=\"#ff6b6b\"\n strokeWidth={1}\n opacity={0.5}\n className=\"pointer-events-none\"\n />\n )}\n {showLabel && node.label && (\n <text\n y={nodeSize + 15}\n fill=\"#333\"\n fontSize=\"12\"\n textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n pointerEvents=\"none\"\n className=\"select-none\"\n >\n {node.label}\n </text>\n )}\n </g>\n );\n};\n\nexport default NodeItem;\n","import React from 'react';\nimport type { GraphLink, GraphNode } from './force-directed/types';\n\nexport interface LinkItemProps {\n link: GraphLink;\n onClick?: (l: GraphLink) => void;\n defaultWidth?: number;\n showLabel?: boolean;\n nodes?: GraphNode[]; // Optional nodes array to resolve string IDs to node objects\n}\n\nexport const LinkItem: React.FC<LinkItemProps> = ({\n link,\n onClick,\n defaultWidth,\n showLabel = true,\n nodes = [],\n}) => {\n const src =\n (link.source as any)?.id ??\n (typeof link.source === 'string' ? link.source : undefined);\n const tgt =\n (link.target as any)?.id ??\n (typeof link.target === 'string' ? link.target : undefined);\n\n // Helper to get node position from source/target (which could be node object or string ID)\n const getNodePosition = (\n nodeOrId: string | GraphNode\n ): { x: number; y: number } | null => {\n if (typeof nodeOrId === 'object' && nodeOrId !== null) {\n // It's a node object\n const node = nodeOrId as GraphNode;\n return { x: node.x ?? 0, y: node.y ?? 0 };\n } else if (typeof nodeOrId === 'string') {\n // It's a string ID, try to find in nodes array\n const found = nodes.find((n) => n.id === nodeOrId);\n if (found) return { x: found.x ?? 0, y: found.y ?? 0 };\n }\n return null;\n };\n\n const sourcePos = getNodePosition(link.source);\n const targetPos = getNodePosition(link.target);\n\n // If we can't get positions, render nothing (or a placeholder)\n if (!sourcePos || !targetPos) {\n return null;\n }\n\n // Calculate midpoint for label positioning\n const midX = (sourcePos.x + targetPos.x) / 2;\n const midY = (sourcePos.y + targetPos.y) / 2;\n\n return (\n <g>\n <line\n x1={sourcePos.x}\n y1={sourcePos.y}\n x2={targetPos.x}\n y2={targetPos.y}\n data-source={src}\n data-target={tgt}\n stroke={link.color}\n strokeWidth={link.width ?? defaultWidth ?? 1}\n opacity={0.6}\n className=\"cursor-pointer transition-opacity hover:opacity-100\"\n onClick={() => onClick?.(link)}\n />\n {showLabel && link.label && (\n <text\n x={midX}\n y={midY}\n fill=\"#666\"\n fontSize=\"10\"\n textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n pointerEvents=\"none\"\n >\n {link.label}\n </text>\n )}\n </g>\n );\n};\n\nexport default LinkItem;\n","import React from 'react';\nimport {\n PACKAGE_BOUNDARY_FILL,\n PACKAGE_BOUNDARY_STROKE,\n PACKAGE_BOUNDARY_STROKE_WIDTH,\n PACKAGE_BOUNDARY_DASH,\n PACKAGE_LABEL_COLOR,\n PACKAGE_LABEL_FONT_SIZE,\n} from './constants';\n\ninterface PackageBoundariesProps {\n packageBounds: Record<string, { x: number; y: number; r: number }>;\n}\n\n/**\n * Renders the circular boundaries and labels for package groups in the force-directed graph.\n *\n * @lastUpdated 2026-03-18\n */\nexport const PackageBoundaries: React.FC<PackageBoundariesProps> = ({\n packageBounds,\n}) => {\n if (!packageBounds || Object.keys(packageBounds).length === 0) return null;\n\n return (\n <g className=\"package-boundaries\" pointerEvents=\"none\">\n {Object.entries(packageBounds).map(([pid, b]) => (\n <g key={pid}>\n <circle\n cx={b.x}\n cy={b.y}\n r={b.r}\n fill={PACKAGE_BOUNDARY_FILL}\n stroke={PACKAGE_BOUNDARY_STROKE}\n strokeWidth={PACKAGE_BOUNDARY_STROKE_WIDTH}\n strokeDasharray={PACKAGE_BOUNDARY_DASH}\n opacity={0.9}\n />\n <text\n x={b.x}\n y={Math.max(12, b.y - b.r + 14)}\n fill={PACKAGE_LABEL_COLOR}\n fontSize={PACKAGE_LABEL_FONT_SIZE}\n textAnchor=\"middle\"\n pointerEvents=\"none\"\n >\n {pid.replace(/^pkg:/, '')}\n </text>\n </g>\n ))}\n </g>\n );\n};\n\nPackageBoundaries.displayName = 'PackageBoundaries';\n","import React from 'react';\nimport { cn } from '../../utils/cn';\nimport NodeItem from '../NodeItem';\nimport LinkItem from '../LinkItem';\nimport { PackageBoundaries } from '../PackageBoundaries';\nimport {\n DEFAULT_NODE_COLOR,\n DEFAULT_NODE_SIZE,\n DEFAULT_LINK_COLOR,\n DEFAULT_LINK_WIDTH,\n} from '../constants';\nimport { GraphNode, GraphLink, ForceDirectedGraphProps } from './types';\nimport { unpinAllNodes } from './useGraphInteractions';\n\ninterface GraphCanvasProps extends Pick<\n ForceDirectedGraphProps,\n | 'width'\n | 'height'\n | 'className'\n | 'selectedNodeId'\n | 'hoveredNodeId'\n | 'defaultNodeColor'\n | 'defaultNodeSize'\n | 'defaultLinkColor'\n | 'defaultLinkWidth'\n | 'showNodeLabels'\n | 'showLinkLabels'\n | 'onNodeClick'\n | 'onNodeHover'\n | 'onLinkClick'\n | 'packageBounds'\n> {\n svgRef: React.RefObject<SVGSVGElement | null>;\n gRef: React.RefObject<SVGGElement | null>;\n nodes: GraphNode[];\n links: GraphLink[];\n pinnedNodes: Set<string>;\n handleNodeDoubleClick: (e: React.MouseEvent, node: GraphNode) => void;\n handleDragStart: (e: React.MouseEvent, node: GraphNode) => void;\n restart: () => void;\n setPinnedNodes: React.Dispatch<React.SetStateAction<Set<string>>>;\n}\n\nexport const GraphCanvas: React.FC<GraphCanvasProps> = ({\n svgRef,\n gRef,\n width,\n height,\n className,\n nodes,\n links,\n pinnedNodes,\n selectedNodeId,\n hoveredNodeId,\n defaultNodeColor = DEFAULT_NODE_COLOR,\n defaultNodeSize = DEFAULT_NODE_SIZE,\n defaultLinkColor = DEFAULT_LINK_COLOR,\n defaultLinkWidth = DEFAULT_LINK_WIDTH,\n showNodeLabels = true,\n showLinkLabels = false,\n onNodeClick,\n onNodeHover,\n onLinkClick,\n packageBounds,\n handleNodeDoubleClick,\n handleDragStart,\n restart,\n setPinnedNodes,\n}) => {\n return (\n <svg\n ref={svgRef}\n width={width}\n height={height}\n className={cn('bg-white dark:bg-gray-900', className)}\n onDoubleClick={() => {\n unpinAllNodes(nodes);\n setPinnedNodes(new Set());\n restart();\n }}\n >\n <defs>\n <marker\n id=\"arrow\"\n viewBox=\"0 0 10 10\"\n refX=\"20\"\n refY=\"5\"\n markerWidth=\"6\"\n markerHeight=\"6\"\n orient=\"auto\"\n >\n <path d=\"M 0 0 L 10 5 L 0 10 z\" fill={defaultLinkColor} />\n </marker>\n </defs>\n\n <g ref={gRef}>\n {links.map((link, i) => (\n <LinkItem\n key={`link-${i}`}\n link={link as GraphLink}\n onClick={onLinkClick}\n defaultWidth={defaultLinkWidth}\n showLabel={showLinkLabels}\n nodes={nodes}\n />\n ))}\n\n {nodes.map((node) => (\n <NodeItem\n key={node.id}\n node={node}\n isSelected={selectedNodeId === node.id}\n isHovered={hoveredNodeId === node.id}\n pinned={pinnedNodes.has(node.id)}\n defaultNodeSize={defaultNodeSize}\n defaultNodeColor={defaultNodeColor}\n showLabel={showNodeLabels}\n onClick={onNodeClick}\n onDoubleClick={handleNodeDoubleClick}\n onMouseEnter={(n) => onNodeHover?.(n)}\n onMouseLeave={() => onNodeHover?.(null)}\n onMouseDown={handleDragStart}\n />\n ))}\n <PackageBoundaries packageBounds={packageBounds || {}} />\n </g>\n </svg>\n );\n};\n","import {\n useCallback,\n useEffect,\n useRef,\n useState,\n forwardRef,\n useImperativeHandle,\n} from 'react';\nimport * as d3 from 'd3';\nimport {\n GraphNode,\n LayoutType,\n ForceDirectedGraphHandle,\n ForceDirectedGraphProps,\n} from './types';\nimport {\n useGraphZoom,\n useWindowDrag,\n useNodeInteractions,\n} from './useGraphInteractions';\nimport { useGraphLayout, useSimulationControls } from './useGraphLayout';\nimport { useImperativeHandleMethods } from './useImperativeHandle';\nimport { GraphCanvas } from './GraphCanvas';\n\nexport const ForceDirectedGraph = forwardRef<\n ForceDirectedGraphHandle,\n ForceDirectedGraphProps\n>(\n (\n {\n nodes: initialNodes,\n links: initialLinks,\n width,\n height,\n enableZoom = true,\n enableDrag = true,\n onNodeClick,\n onNodeHover,\n onLinkClick,\n selectedNodeId,\n hoveredNodeId,\n defaultNodeColor,\n defaultNodeSize,\n defaultLinkColor,\n defaultLinkWidth,\n showNodeLabels,\n showLinkLabels,\n className,\n manualLayout = false,\n onManualLayoutChange,\n packageBounds,\n layout: externalLayout,\n onLayoutChange,\n },\n ref\n ) => {\n const svgRef = useRef<SVGSVGElement>(null);\n const gRef = useRef<SVGGElement>(null);\n const [transform, setTransform] = useState({ k: 1, x: 0, y: 0 });\n const transformRef = useRef(transform);\n const dragNodeRef = useRef<GraphNode | null>(null);\n const dragActiveRef = useRef(false);\n const [pinnedNodes, setPinnedNodes] = useState<Set<string>>(new Set());\n const internalDragEnabledRef = useRef(enableDrag);\n const [layout, setLayout] = useState<LayoutType>(externalLayout || 'force');\n\n useEffect(() => {\n if (externalLayout && externalLayout !== layout)\n setLayout(externalLayout);\n }, [externalLayout, layout]);\n\n const handleLayoutChange = useCallback(\n (newLayout: LayoutType) => {\n setLayout(newLayout);\n onLayoutChange?.(newLayout);\n },\n [onLayoutChange]\n );\n\n useEffect(() => {\n internalDragEnabledRef.current = enableDrag;\n }, [enableDrag]);\n\n const { restart, stop, setForcesEnabled } = useSimulationControls();\n const { nodes } = useGraphLayout(\n initialNodes,\n width,\n height,\n layout,\n restart\n );\n\n useEffect(() => {\n setForcesEnabled(!(manualLayout || pinnedNodes.size > 0));\n }, [manualLayout, pinnedNodes, setForcesEnabled]);\n\n useImperativeHandle(\n ref,\n () =>\n useImperativeHandleMethods({\n nodes,\n pinnedNodes,\n setPinnedNodes,\n restart,\n width,\n height,\n layout,\n handleLayoutChange,\n setForcesEnabled,\n svgRef,\n gRef,\n setTransform,\n internalDragEnabledRef,\n }),\n [\n nodes,\n pinnedNodes,\n restart,\n width,\n height,\n layout,\n handleLayoutChange,\n setForcesEnabled,\n ]\n );\n\n useEffect(() => {\n onManualLayoutChange?.(manualLayout);\n }, [manualLayout, onManualLayoutChange]);\n\n useGraphZoom(svgRef, gRef, enableZoom, setTransform, transformRef);\n useWindowDrag(\n enableDrag,\n svgRef,\n transformRef,\n dragActiveRef,\n dragNodeRef,\n () => {\n setForcesEnabled(true);\n restart();\n }\n );\n\n useEffect(() => {\n if (!gRef.current) return;\n const g = d3.select(gRef.current);\n g.selectAll('g.node').each(function (this: any) {\n const d = d3.select(this).datum() as any;\n if (d)\n d3.select(this).attr(\n 'transform',\n `translate(${d.x || 0},${d.y || 0})`\n );\n });\n g.selectAll('line').each(function (this: any) {\n const l = d3.select(this).datum() as any;\n if (!l) return;\n const s =\n typeof l.source === 'object'\n ? l.source\n : nodes.find((n) => n.id === l.source);\n const t =\n typeof l.target === 'object'\n ? l.target\n : nodes.find((n) => n.id === l.target);\n if (s && t)\n d3.select(this)\n .attr('x1', s.x)\n .attr('y1', s.y)\n .attr('x2', t.x)\n .attr('y2', t.y);\n });\n }, [nodes, initialLinks]);\n\n const { handleDragStart, handleNodeDoubleClick } = useNodeInteractions(\n enableDrag,\n nodes,\n pinnedNodes,\n setPinnedNodes,\n restart,\n stop\n );\n\n useEffect(() => {\n if (!gRef.current || !enableDrag) return;\n const g = d3.select(gRef.current);\n const dragBehavior = (d3 as any)\n .drag()\n .on('start', (event: any) => {\n const target = (event.sourceEvent?.target || event.target) as Element;\n const id = target.closest?.('g.node')?.getAttribute('data-id');\n if (!id || !internalDragEnabledRef.current) return;\n const node = nodes.find((n) => n.id === id);\n if (!node) return;\n if (!event.active) restart();\n dragActiveRef.current = true;\n dragNodeRef.current = node;\n })\n .on('drag', (event: any) => {\n if (!dragActiveRef.current || !dragNodeRef.current || !svgRef.current)\n return;\n const rect = svgRef.current.getBoundingClientRect();\n dragNodeRef.current.fx =\n (event.sourceEvent.clientX - rect.left - transform.x) / transform.k;\n dragNodeRef.current.fy =\n (event.sourceEvent.clientY - rect.top - transform.y) / transform.k;\n })\n .on('end', () => {\n setForcesEnabled(true);\n restart();\n });\n\n g.selectAll('g.node').call(dragBehavior);\n return () => {\n g.selectAll('g.node').on('.drag', null);\n };\n }, [gRef, enableDrag, nodes, transform, restart, setForcesEnabled]);\n\n return (\n <GraphCanvas\n svgRef={svgRef}\n gRef={gRef}\n width={width}\n height={height}\n className={className}\n nodes={nodes}\n links={initialLinks}\n pinnedNodes={pinnedNodes}\n selectedNodeId={selectedNodeId}\n hoveredNodeId={hoveredNodeId}\n defaultNodeColor={defaultNodeColor}\n defaultNodeSize={defaultNodeSize}\n defaultLinkColor={defaultLinkColor}\n defaultLinkWidth={defaultLinkWidth}\n showNodeLabels={showNodeLabels}\n showLinkLabels={showLinkLabels}\n onNodeClick={onNodeClick}\n onNodeHover={onNodeHover}\n onLinkClick={onLinkClick}\n packageBounds={packageBounds}\n handleNodeDoubleClick={handleNodeDoubleClick}\n handleDragStart={handleDragStart}\n restart={restart}\n setPinnedNodes={setPinnedNodes}\n />\n );\n }\n);\n\nForceDirectedGraph.displayName = 'ForceDirectedGraph';\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/charts/force-directed/useGraphInteractions.ts","../../src/charts/constants.ts","../../src/charts/layout-utils.ts","../../src/charts/force-directed/useGraphLayout.ts","../../src/charts/force-directed/useImperativeHandle.ts","../../src/utils/cn.ts","../../src/charts/NodeItem.tsx","../../src/charts/LinkItem.tsx","../../src/charts/PackageBoundaries.tsx","../../src/charts/force-directed/GraphCanvas.tsx","../../src/charts/force-directed/ForceDirectedGraph.tsx"],"names":["d3","zoom","useEffect","useCallback","d32","jsxs","jsx"],"mappings":"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","file":"ForceDirectedGraph.js","sourcesContent":["import { useCallback, useEffect } from 'react';\nimport * as d3 from 'd3';\nimport { GraphNode } from './types';\n\n/** Pins a node to its current position (sets fx/fy to current x/y) */\nexport function pinNode(node: GraphNode): void {\n node.fx = node.x;\n node.fy = node.y;\n}\n\n/** Unpins a node (sets fx/fy to null) */\nexport function unpinNode(node: GraphNode): void {\n node.fx = null;\n node.fy = null;\n}\n\n/** Unpins all nodes - helper for bulk unpin operations */\nexport function unpinAllNodes(nodes: GraphNode[]): void {\n nodes.forEach(unpinNode);\n}\n\n/**\n * Hook for managing D3 zoom behavior on an SVG element.\n */\nexport function useGraphZoom(\n svgRef: React.RefObject<SVGSVGElement | null>,\n gRef: React.RefObject<SVGGElement | null>,\n enableZoom: boolean,\n setTransform: (transform: { k: number; x: number; y: number }) => void,\n transformRef: React.MutableRefObject<{ k: number; x: number; y: number }>\n) {\n useEffect(() => {\n if (!enableZoom || !svgRef.current || !gRef.current) return;\n\n const svg = d3.select(svgRef.current);\n const g = d3.select(gRef.current);\n\n const zoom = (d3 as typeof d3)\n .zoom()\n .scaleExtent([0.1, 10])\n .on('zoom', (event: any) => {\n g.attr('transform', event.transform);\n transformRef.current = event.transform;\n setTransform(event.transform);\n });\n\n svg.call(zoom as unknown as any);\n\n return () => {\n svg.on('.zoom', null);\n };\n }, [enableZoom, svgRef, gRef, setTransform, transformRef]);\n}\n\n/**\n * Hook for managing window-level drag events for smooth node dragging.\n */\nexport function useWindowDrag(\n enableDrag: boolean,\n svgRef: React.RefObject<SVGSVGElement | null>,\n transformRef: React.MutableRefObject<{ k: number; x: number; y: number }>,\n dragActiveRef: React.MutableRefObject<boolean>,\n dragNodeRef: React.MutableRefObject<GraphNode | null>,\n onDragEnd: () => void\n) {\n useEffect(() => {\n if (!enableDrag) return;\n\n const handleWindowMove = (event: MouseEvent) => {\n if (!dragActiveRef.current || !dragNodeRef.current) return;\n const svg = svgRef.current;\n if (!svg) return;\n const rect = svg.getBoundingClientRect();\n const t: any = transformRef.current;\n const x = (event.clientX - rect.left - t.x) / t.k;\n const y = (event.clientY - rect.top - t.y) / t.k;\n dragNodeRef.current.fx = x;\n dragNodeRef.current.fy = y;\n };\n\n const handleWindowUp = () => {\n if (!dragActiveRef.current) return;\n onDragEnd();\n dragNodeRef.current = null;\n dragActiveRef.current = false;\n };\n\n const handleWindowLeave = (event: MouseEvent) => {\n if (event.relatedTarget === null) handleWindowUp();\n };\n\n window.addEventListener('mousemove', handleWindowMove);\n window.addEventListener('mouseup', handleWindowUp);\n window.addEventListener('mouseout', handleWindowLeave);\n window.addEventListener('blur', handleWindowUp);\n\n return () => {\n window.removeEventListener('mousemove', handleWindowMove);\n window.removeEventListener('mouseup', handleWindowUp);\n window.removeEventListener('mouseout', handleWindowLeave);\n window.removeEventListener('blur', handleWindowUp);\n };\n }, [enableDrag, svgRef, transformRef, dragActiveRef, dragNodeRef, onDragEnd]);\n}\n\n/**\n * Hook for managing node interactions (drag, double-click pinning).\n */\nexport function useNodeInteractions(\n enableDrag: boolean,\n _nodes: GraphNode[],\n _pinnedNodes: Set<string>,\n setPinnedNodes: React.Dispatch<React.SetStateAction<Set<string>>>,\n restart: () => void,\n stop: () => void\n) {\n const handleDragStart = useCallback(\n (event: React.MouseEvent, node: GraphNode) => {\n if (!enableDrag) return;\n event.preventDefault();\n event.stopPropagation();\n pinNode(node);\n setPinnedNodes((prev) => new Set([...prev, node.id]));\n stop();\n },\n [enableDrag, stop, setPinnedNodes]\n );\n\n const handleNodeDoubleClick = useCallback(\n (event: React.MouseEvent, node: GraphNode) => {\n event.stopPropagation();\n if (!enableDrag) return;\n if (node.fx === null || node.fx === undefined) {\n pinNode(node);\n setPinnedNodes((prev) => new Set([...prev, node.id]));\n } else {\n unpinNode(node);\n setPinnedNodes((prev) => {\n const next = new Set(prev);\n next.delete(node.id);\n return next;\n });\n }\n restart();\n },\n [enableDrag, restart, setPinnedNodes]\n );\n\n return { handleDragStart, handleNodeDoubleClick };\n}\n","/**\n * Default visual constants for the ForceDirectedGraph component.\n */\nexport const DEFAULT_NODE_COLOR = '#64748b';\nexport const DEFAULT_NODE_SIZE = 10;\nexport const DEFAULT_LINK_COLOR = '#94a3b8';\nexport const DEFAULT_LINK_WIDTH = 1;\n\n/**\n * Layout and interaction thresholds.\n */\nexport const CIRCULAR_LAYOUT_RADIUS_RATIO = 0.35;\nexport const FIT_VIEW_PADDING = 40;\nexport const ZOOM_MIN_SCALE = 0.1;\nexport const ZOOM_MAX_SCALE = 10;\n\n/**\n * Transition and animation durations.\n */\nexport const TRANSITION_DURATION_MS = 300;\n\n/**\n * Package boundary styling.\n */\nexport const PACKAGE_BOUNDARY_FILL = 'rgba(148,163,184,0.06)';\nexport const PACKAGE_BOUNDARY_STROKE = '#475569';\nexport const PACKAGE_BOUNDARY_STROKE_WIDTH = 2;\nexport const PACKAGE_BOUNDARY_DASH = '6 6';\nexport const PACKAGE_LABEL_FONT_SIZE = 11;\nexport const PACKAGE_LABEL_COLOR = '#475569';\n","import { GraphNode } from './force-directed/types';\nimport { CIRCULAR_LAYOUT_RADIUS_RATIO } from './constants';\n\n/**\n * Calculates node positions for a circular layout.\n *\n * @param nodes - Array of dependency nodes.\n * @param width - Canvas width.\n * @param height - Canvas height.\n * @lastUpdated 2026-03-18\n */\nexport function applyCircularLayout(\n nodes: GraphNode[],\n width: number,\n height: number\n): void {\n const centerX = width / 2;\n const centerY = height / 2;\n const radius = Math.min(width, height) * CIRCULAR_LAYOUT_RADIUS_RATIO;\n\n nodes.forEach((node, i) => {\n const angle = (2 * Math.PI * i) / nodes.length;\n node.fx = centerX + Math.cos(angle) * radius;\n node.fy = centerY + Math.sin(angle) * radius;\n node.x = node.fx;\n node.y = node.fy;\n });\n}\n\n/**\n * Calculates node positions for a hierarchical layout by grouping packages.\n *\n * @param nodes - Array of dependency nodes.\n * @param width - Canvas width.\n * @param height - Canvas height.\n * @lastUpdated 2026-03-18\n */\nexport function applyHierarchicalLayout(\n nodes: GraphNode[],\n width: number,\n height: number\n): void {\n const groups = new Map<string, GraphNode[]>();\n nodes.forEach((n: any) => {\n const key = n.packageGroup || n.group || 'root';\n if (!groups.has(key)) groups.set(key, []);\n groups.get(key)!.push(n);\n });\n\n const groupArray = Array.from(groups.entries());\n const cols = Math.ceil(Math.sqrt(groupArray.length));\n const groupSpacingX = (width * 0.8) / cols;\n const groupSpacingY = (height * 0.8) / Math.ceil(groupArray.length / cols);\n\n groupArray.forEach(([groupKey, groupNodes], gi) => {\n const col = gi % cols;\n const row = Math.floor(gi / cols);\n const groupX = (col + 0.5) * groupSpacingX;\n const groupY = (row + 0.5) * groupSpacingY;\n\n if (groupKey.startsWith('pkg:') || groupKey === groupKey) {\n groupNodes.forEach((n, ni) => {\n const angle = (2 * Math.PI * ni) / groupNodes.length;\n const r = Math.min(80, 20 + groupNodes.length * 8);\n n.fx = groupX + Math.cos(angle) * r;\n n.fy = groupY + Math.sin(angle) * r;\n n.x = n.fx;\n n.y = n.fy;\n });\n }\n });\n}\n\n/**\n * Calculates initial random positions for nodes in a force-directed layout.\n *\n * @param nodes - Array of dependency nodes.\n * @param width - Canvas width.\n * @param height - Canvas height.\n * @lastUpdated 2026-03-18\n */\nexport function applyInitialForceLayout(\n nodes: GraphNode[],\n width: number,\n height: number\n): void {\n nodes.forEach((node) => {\n if (node.fx === undefined || node.fx === null) {\n node.x = Math.random() * width;\n node.y = Math.random() * height;\n }\n });\n}\n","import { useCallback, useEffect, useMemo } from 'react';\nimport { GraphNode, LayoutType } from './types';\nimport {\n applyCircularLayout,\n applyHierarchicalLayout,\n applyInitialForceLayout,\n} from '../layout-utils';\n\n/**\n * Hook for managing graph layout algorithms.\n */\nexport function useGraphLayout(\n initialNodes: GraphNode[],\n width: number,\n height: number,\n layout: LayoutType,\n restart: () => void\n) {\n // Initial positioning - delegate to layout utils\n const nodes = useMemo(() => {\n if (!initialNodes || !initialNodes.length) return initialNodes;\n const copy = initialNodes.map((n) => ({ ...n }));\n if (layout === 'circular') applyCircularLayout(copy, width, height);\n else if (layout === 'hierarchical')\n applyHierarchicalLayout(copy, width, height);\n else applyInitialForceLayout(copy, width, height);\n return copy;\n }, [initialNodes, width, height, layout]);\n\n // Apply layout-specific positioning when layout changes\n useEffect(() => {\n if (!nodes || nodes.length === 0) return;\n if (layout === 'circular') applyCircularLayout(nodes, width, height);\n else if (layout === 'hierarchical')\n applyHierarchicalLayout(nodes, width, height);\n\n restart();\n }, [layout, nodes, width, height, restart]);\n\n return { nodes };\n}\n\n/**\n * Hook for managing simulation controls (stubs for API compatibility).\n */\nexport function useSimulationControls() {\n const restart = useCallback(() => {}, []);\n const stop = useCallback(() => {}, []);\n const setForcesEnabled = useCallback((enabled?: boolean) => {\n void enabled;\n }, []);\n\n return { restart, stop, setForcesEnabled };\n}\n","import { useCallback } from 'react';\nimport * as d3 from 'd3';\nimport { GraphNode, LayoutType, ForceDirectedGraphHandle } from './types';\nimport { pinNode, unpinAllNodes } from './useGraphInteractions';\nimport {\n DEFAULT_NODE_SIZE,\n FIT_VIEW_PADDING,\n TRANSITION_DURATION_MS,\n} from '../constants';\n\ninterface UseImperativeHandleProps {\n nodes: GraphNode[];\n pinnedNodes: Set<string>;\n setPinnedNodes: React.Dispatch<React.SetStateAction<Set<string>>>;\n restart: () => void;\n width: number;\n height: number;\n layout: LayoutType;\n handleLayoutChange: (layout: LayoutType) => void;\n setForcesEnabled: (enabled: boolean) => void;\n svgRef: React.RefObject<SVGSVGElement | null>;\n gRef: React.RefObject<SVGGElement | null>;\n setTransform: (transform: { k: number; x: number; y: number }) => void;\n internalDragEnabledRef: React.MutableRefObject<boolean>;\n}\n\n/**\n * Creates the imperative handle methods for the ForceDirectedGraph component.\n */\nexport function useImperativeHandleMethods({\n nodes,\n pinnedNodes,\n setPinnedNodes,\n restart,\n width,\n height,\n layout,\n handleLayoutChange,\n svgRef,\n gRef,\n setTransform,\n internalDragEnabledRef,\n}: UseImperativeHandleProps): ForceDirectedGraphHandle {\n const pinAll = useCallback(() => {\n const newPinned = new Set<string>();\n nodes.forEach((node) => {\n pinNode(node);\n newPinned.add(node.id);\n });\n setPinnedNodes(newPinned);\n restart();\n }, [nodes, setPinnedNodes, restart]);\n\n const unpinAll = useCallback(() => {\n unpinAllNodes(nodes);\n setPinnedNodes(new Set());\n restart();\n }, [nodes, setPinnedNodes, restart]);\n\n const resetLayout = useCallback(() => {\n unpinAllNodes(nodes);\n setPinnedNodes(new Set());\n restart();\n }, [nodes, setPinnedNodes, restart]);\n\n const fitView = useCallback(() => {\n if (!svgRef.current || !nodes.length) return;\n let minX = Infinity,\n maxX = -Infinity,\n minY = Infinity,\n maxY = -Infinity;\n nodes.forEach((node) => {\n if (node.x !== undefined && node.y !== undefined) {\n const size = node.size || DEFAULT_NODE_SIZE;\n minX = Math.min(minX, node.x - size);\n maxX = Math.max(maxX, node.x + size);\n minY = Math.min(minY, node.y - size);\n maxY = Math.max(maxY, node.y + size);\n }\n });\n if (!isFinite(minX)) return;\n const scale = Math.min(\n (width - FIT_VIEW_PADDING * 2) / (maxX - minX),\n (height - FIT_VIEW_PADDING * 2) / (maxY - minY),\n 10\n );\n const x = width / 2 - ((minX + maxX) / 2) * scale;\n const y = height / 2 - ((minY + maxY) / 2) * scale;\n if (gRef.current && svgRef.current) {\n const svg = d3.select(svgRef.current);\n const newTransform = d3.zoomIdentity.translate(x, y).scale(scale);\n svg\n .transition()\n .duration(TRANSITION_DURATION_MS)\n .call(d3.zoom().transform as any, newTransform);\n setTransform(newTransform);\n }\n }, [nodes, width, height, svgRef, gRef, setTransform]);\n\n const getPinnedNodes = useCallback(\n () => Array.from(pinnedNodes),\n [pinnedNodes]\n );\n\n const setDragMode = useCallback(\n (enabled: boolean) => {\n internalDragEnabledRef.current = enabled;\n },\n [internalDragEnabledRef]\n );\n\n const setLayoutMethod = useCallback(\n (newLayout: LayoutType) => {\n handleLayoutChange(newLayout);\n },\n [handleLayoutChange]\n );\n\n const getLayout = useCallback(() => layout, [layout]);\n\n return {\n pinAll,\n unpinAll,\n resetLayout,\n fitView,\n getPinnedNodes,\n setDragMode,\n setLayout: setLayoutMethod,\n getLayout,\n };\n}\n","import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\n/**\n * Merges class names using clsx and tailwind-merge\n * @param inputs - Class values to merge\n * @returns Merged class names\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import React from 'react';\nimport type { GraphNode } from './force-directed/types';\n\nexport interface NodeItemProps {\n node: GraphNode;\n isSelected: boolean;\n isHovered: boolean;\n pinned: boolean;\n defaultNodeSize: number;\n defaultNodeColor: string;\n showLabel?: boolean;\n onClick?: (n: GraphNode) => void;\n onDoubleClick?: (e: React.MouseEvent, n: GraphNode) => void;\n onMouseEnter?: (n: GraphNode) => void;\n onMouseLeave?: () => void;\n onMouseDown?: (e: React.MouseEvent, n: GraphNode) => void;\n}\n\nexport const NodeItem: React.FC<NodeItemProps> = ({\n node,\n isSelected,\n isHovered,\n pinned,\n defaultNodeSize,\n defaultNodeColor,\n showLabel = true,\n onClick,\n onDoubleClick,\n onMouseEnter,\n onMouseLeave,\n onMouseDown,\n}) => {\n const nodeSize = node.size || defaultNodeSize;\n const nodeColor = node.color || defaultNodeColor;\n\n const x = node.x ?? 0;\n const y = node.y ?? 0;\n\n return (\n <g\n key={node.id}\n className=\"cursor-pointer node\"\n data-id={node.id}\n transform={`translate(${x},${y})`}\n onClick={() => onClick?.(node)}\n onDoubleClick={(e) => onDoubleClick?.(e, node)}\n onMouseEnter={() => onMouseEnter?.(node)}\n onMouseLeave={() => onMouseLeave?.()}\n onMouseDown={(e) => onMouseDown?.(e, node)}\n >\n <circle\n r={nodeSize}\n fill={nodeColor}\n stroke={isSelected ? '#000' : isHovered ? '#666' : 'none'}\n strokeWidth={pinned ? 3 : isSelected ? 2.5 : isHovered ? 2 : 1.5}\n opacity={isHovered || isSelected ? 1 : 0.9}\n />\n {pinned && (\n <circle\n r={nodeSize + 4}\n fill=\"none\"\n stroke=\"#ff6b6b\"\n strokeWidth={1}\n opacity={0.5}\n className=\"pointer-events-none\"\n />\n )}\n {showLabel && node.label && (\n <text\n y={nodeSize + 15}\n fill=\"#333\"\n fontSize=\"12\"\n textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n pointerEvents=\"none\"\n className=\"select-none\"\n >\n {node.label}\n </text>\n )}\n </g>\n );\n};\n\nexport default NodeItem;\n","import React from 'react';\nimport type { GraphLink, GraphNode } from './force-directed/types';\n\nexport interface LinkItemProps {\n link: GraphLink;\n onClick?: (l: GraphLink) => void;\n defaultWidth?: number;\n showLabel?: boolean;\n nodes?: GraphNode[]; // Optional nodes array to resolve string IDs to node objects\n}\n\nexport const LinkItem: React.FC<LinkItemProps> = ({\n link,\n onClick,\n defaultWidth,\n showLabel = true,\n nodes = [],\n}) => {\n const src =\n (link.source as any)?.id ??\n (typeof link.source === 'string' ? link.source : undefined);\n const tgt =\n (link.target as any)?.id ??\n (typeof link.target === 'string' ? link.target : undefined);\n\n // Helper to get node position from source/target (which could be node object or string ID)\n const getNodePosition = (\n nodeOrId: string | GraphNode\n ): { x: number; y: number } | null => {\n if (typeof nodeOrId === 'object' && nodeOrId !== null) {\n // It's a node object\n const node = nodeOrId as GraphNode;\n return { x: node.x ?? 0, y: node.y ?? 0 };\n } else if (typeof nodeOrId === 'string') {\n // It's a string ID, try to find in nodes array\n const found = nodes.find((n) => n.id === nodeOrId);\n if (found) return { x: found.x ?? 0, y: found.y ?? 0 };\n }\n return null;\n };\n\n const sourcePos = getNodePosition(link.source);\n const targetPos = getNodePosition(link.target);\n\n // If we can't get positions, render nothing (or a placeholder)\n if (!sourcePos || !targetPos) {\n return null;\n }\n\n // Calculate midpoint for label positioning\n const midX = (sourcePos.x + targetPos.x) / 2;\n const midY = (sourcePos.y + targetPos.y) / 2;\n\n return (\n <g>\n <line\n x1={sourcePos.x}\n y1={sourcePos.y}\n x2={targetPos.x}\n y2={targetPos.y}\n data-source={src}\n data-target={tgt}\n stroke={link.color}\n strokeWidth={link.width ?? defaultWidth ?? 1}\n opacity={0.6}\n className=\"cursor-pointer transition-opacity hover:opacity-100\"\n onClick={() => onClick?.(link)}\n />\n {showLabel && link.label && (\n <text\n x={midX}\n y={midY}\n fill=\"#666\"\n fontSize=\"10\"\n textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n pointerEvents=\"none\"\n >\n {link.label}\n </text>\n )}\n </g>\n );\n};\n\nexport default LinkItem;\n","import React from 'react';\nimport {\n PACKAGE_BOUNDARY_FILL,\n PACKAGE_BOUNDARY_STROKE,\n PACKAGE_BOUNDARY_STROKE_WIDTH,\n PACKAGE_BOUNDARY_DASH,\n PACKAGE_LABEL_COLOR,\n PACKAGE_LABEL_FONT_SIZE,\n} from './constants';\n\ninterface PackageBoundariesProps {\n packageBounds: Record<string, { x: number; y: number; r: number }>;\n}\n\n/**\n * Renders the circular boundaries and labels for package groups in the force-directed graph.\n *\n * @lastUpdated 2026-03-18\n */\nexport const PackageBoundaries: React.FC<PackageBoundariesProps> = ({\n packageBounds,\n}) => {\n if (!packageBounds || Object.keys(packageBounds).length === 0) return null;\n\n return (\n <g className=\"package-boundaries\" pointerEvents=\"none\">\n {Object.entries(packageBounds).map(([pid, b]) => (\n <g key={pid}>\n <circle\n cx={b.x}\n cy={b.y}\n r={b.r}\n fill={PACKAGE_BOUNDARY_FILL}\n stroke={PACKAGE_BOUNDARY_STROKE}\n strokeWidth={PACKAGE_BOUNDARY_STROKE_WIDTH}\n strokeDasharray={PACKAGE_BOUNDARY_DASH}\n opacity={0.9}\n />\n <text\n x={b.x}\n y={Math.max(12, b.y - b.r + 14)}\n fill={PACKAGE_LABEL_COLOR}\n fontSize={PACKAGE_LABEL_FONT_SIZE}\n textAnchor=\"middle\"\n pointerEvents=\"none\"\n >\n {pid.replace(/^pkg:/, '')}\n </text>\n </g>\n ))}\n </g>\n );\n};\n\nPackageBoundaries.displayName = 'PackageBoundaries';\n","import React from 'react';\nimport { cn } from '../../utils/cn';\nimport NodeItem from '../NodeItem';\nimport LinkItem from '../LinkItem';\nimport { PackageBoundaries } from '../PackageBoundaries';\nimport {\n DEFAULT_NODE_COLOR,\n DEFAULT_NODE_SIZE,\n DEFAULT_LINK_COLOR,\n DEFAULT_LINK_WIDTH,\n} from '../constants';\nimport { GraphNode, GraphLink, ForceDirectedGraphProps } from './types';\nimport { unpinAllNodes } from './useGraphInteractions';\n\ninterface GraphCanvasProps extends Pick<\n ForceDirectedGraphProps,\n | 'width'\n | 'height'\n | 'className'\n | 'selectedNodeId'\n | 'hoveredNodeId'\n | 'defaultNodeColor'\n | 'defaultNodeSize'\n | 'defaultLinkColor'\n | 'defaultLinkWidth'\n | 'showNodeLabels'\n | 'showLinkLabels'\n | 'onNodeClick'\n | 'onNodeHover'\n | 'onLinkClick'\n | 'packageBounds'\n> {\n svgRef: React.RefObject<SVGSVGElement | null>;\n gRef: React.RefObject<SVGGElement | null>;\n nodes: GraphNode[];\n links: GraphLink[];\n pinnedNodes: Set<string>;\n handleNodeDoubleClick: (e: React.MouseEvent, node: GraphNode) => void;\n handleDragStart: (e: React.MouseEvent, node: GraphNode) => void;\n restart: () => void;\n setPinnedNodes: React.Dispatch<React.SetStateAction<Set<string>>>;\n}\n\nexport const GraphCanvas: React.FC<GraphCanvasProps> = ({\n svgRef,\n gRef,\n width,\n height,\n className,\n nodes,\n links,\n pinnedNodes,\n selectedNodeId,\n hoveredNodeId,\n defaultNodeColor = DEFAULT_NODE_COLOR,\n defaultNodeSize = DEFAULT_NODE_SIZE,\n defaultLinkColor = DEFAULT_LINK_COLOR,\n defaultLinkWidth = DEFAULT_LINK_WIDTH,\n showNodeLabels = true,\n showLinkLabels = false,\n onNodeClick,\n onNodeHover,\n onLinkClick,\n packageBounds,\n handleNodeDoubleClick,\n handleDragStart,\n restart,\n setPinnedNodes,\n}) => {\n return (\n <svg\n ref={svgRef}\n width={width}\n height={height}\n className={cn('bg-white dark:bg-gray-900', className)}\n onDoubleClick={() => {\n unpinAllNodes(nodes);\n setPinnedNodes(new Set());\n restart();\n }}\n >\n <defs>\n <marker\n id=\"arrow\"\n viewBox=\"0 0 10 10\"\n refX=\"20\"\n refY=\"5\"\n markerWidth=\"6\"\n markerHeight=\"6\"\n orient=\"auto\"\n >\n <path d=\"M 0 0 L 10 5 L 0 10 z\" fill={defaultLinkColor} />\n </marker>\n </defs>\n\n <g ref={gRef}>\n {links.map((link, i) => (\n <LinkItem\n key={`link-${i}`}\n link={link as GraphLink}\n onClick={onLinkClick}\n defaultWidth={defaultLinkWidth}\n showLabel={showLinkLabels}\n nodes={nodes}\n />\n ))}\n\n {nodes.map((node) => (\n <NodeItem\n key={node.id}\n node={node}\n isSelected={selectedNodeId === node.id}\n isHovered={hoveredNodeId === node.id}\n pinned={pinnedNodes.has(node.id)}\n defaultNodeSize={defaultNodeSize}\n defaultNodeColor={defaultNodeColor}\n showLabel={showNodeLabels}\n onClick={onNodeClick}\n onDoubleClick={handleNodeDoubleClick}\n onMouseEnter={(n) => onNodeHover?.(n)}\n onMouseLeave={() => onNodeHover?.(null)}\n onMouseDown={handleDragStart}\n />\n ))}\n <PackageBoundaries packageBounds={packageBounds || {}} />\n </g>\n </svg>\n );\n};\n","import {\n useCallback,\n useEffect,\n useRef,\n useState,\n forwardRef,\n useImperativeHandle,\n} from 'react';\nimport * as d3 from 'd3';\nimport {\n GraphNode,\n LayoutType,\n ForceDirectedGraphHandle,\n ForceDirectedGraphProps,\n} from './types';\nimport {\n useGraphZoom,\n useWindowDrag,\n useNodeInteractions,\n} from './useGraphInteractions';\nimport { useGraphLayout, useSimulationControls } from './useGraphLayout';\nimport { useImperativeHandleMethods } from './useImperativeHandle';\nimport { GraphCanvas } from './GraphCanvas';\n\nexport const ForceDirectedGraph = forwardRef<\n ForceDirectedGraphHandle,\n ForceDirectedGraphProps\n>(\n (\n {\n nodes: initialNodes,\n links: initialLinks,\n width,\n height,\n enableZoom = true,\n enableDrag = true,\n onNodeClick,\n onNodeHover,\n onLinkClick,\n selectedNodeId,\n hoveredNodeId,\n defaultNodeColor,\n defaultNodeSize,\n defaultLinkColor,\n defaultLinkWidth,\n showNodeLabels,\n showLinkLabels,\n className,\n manualLayout = false,\n onManualLayoutChange,\n packageBounds,\n layout: externalLayout,\n onLayoutChange,\n },\n ref\n ) => {\n const svgRef = useRef<SVGSVGElement>(null);\n const gRef = useRef<SVGGElement>(null);\n const [transform, setTransform] = useState({ k: 1, x: 0, y: 0 });\n const transformRef = useRef(transform);\n const dragNodeRef = useRef<GraphNode | null>(null);\n const dragActiveRef = useRef(false);\n const [pinnedNodes, setPinnedNodes] = useState<Set<string>>(new Set());\n const internalDragEnabledRef = useRef(enableDrag);\n const [layout, setLayout] = useState<LayoutType>(externalLayout || 'force');\n\n useEffect(() => {\n if (externalLayout && externalLayout !== layout)\n setLayout(externalLayout);\n }, [externalLayout, layout]);\n\n const handleLayoutChange = useCallback(\n (newLayout: LayoutType) => {\n setLayout(newLayout);\n onLayoutChange?.(newLayout);\n },\n [onLayoutChange]\n );\n\n useEffect(() => {\n internalDragEnabledRef.current = enableDrag;\n }, [enableDrag]);\n\n const { restart, stop, setForcesEnabled } = useSimulationControls();\n const { nodes } = useGraphLayout(\n initialNodes,\n width,\n height,\n layout,\n restart\n );\n\n useEffect(() => {\n setForcesEnabled(!(manualLayout || pinnedNodes.size > 0));\n }, [manualLayout, pinnedNodes, setForcesEnabled]);\n\n useImperativeHandle(\n ref,\n () =>\n useImperativeHandleMethods({\n nodes,\n pinnedNodes,\n setPinnedNodes,\n restart,\n width,\n height,\n layout,\n handleLayoutChange,\n setForcesEnabled,\n svgRef,\n gRef,\n setTransform,\n internalDragEnabledRef,\n }),\n [\n nodes,\n pinnedNodes,\n restart,\n width,\n height,\n layout,\n handleLayoutChange,\n setForcesEnabled,\n ]\n );\n\n useEffect(() => {\n onManualLayoutChange?.(manualLayout);\n }, [manualLayout, onManualLayoutChange]);\n\n useGraphZoom(svgRef, gRef, enableZoom, setTransform, transformRef);\n useWindowDrag(\n enableDrag,\n svgRef,\n transformRef,\n dragActiveRef,\n dragNodeRef,\n () => {\n setForcesEnabled(true);\n restart();\n }\n );\n\n useEffect(() => {\n if (!gRef.current) return;\n const g = d3.select(gRef.current);\n g.selectAll('g.node').each(function (this: any) {\n const d = d3.select(this).datum() as any;\n if (d)\n d3.select(this).attr(\n 'transform',\n `translate(${d.x || 0},${d.y || 0})`\n );\n });\n g.selectAll('line').each(function (this: any) {\n const l = d3.select(this).datum() as any;\n if (!l) return;\n const s =\n typeof l.source === 'object'\n ? l.source\n : nodes.find((n) => n.id === l.source);\n const t =\n typeof l.target === 'object'\n ? l.target\n : nodes.find((n) => n.id === l.target);\n if (s && t)\n d3.select(this)\n .attr('x1', s.x)\n .attr('y1', s.y)\n .attr('x2', t.x)\n .attr('y2', t.y);\n });\n }, [nodes, initialLinks]);\n\n const { handleDragStart, handleNodeDoubleClick } = useNodeInteractions(\n enableDrag,\n nodes,\n pinnedNodes,\n setPinnedNodes,\n restart,\n stop\n );\n\n useEffect(() => {\n if (!gRef.current || !enableDrag) return;\n const g = d3.select(gRef.current);\n const dragBehavior = (d3 as any)\n .drag()\n .on('start', (event: any) => {\n const target = (event.sourceEvent?.target || event.target) as Element;\n const id = target.closest?.('g.node')?.getAttribute('data-id');\n if (!id || !internalDragEnabledRef.current) return;\n const node = nodes.find((n) => n.id === id);\n if (!node) return;\n if (!event.active) restart();\n dragActiveRef.current = true;\n dragNodeRef.current = node;\n })\n .on('drag', (event: any) => {\n if (!dragActiveRef.current || !dragNodeRef.current || !svgRef.current)\n return;\n const rect = svgRef.current.getBoundingClientRect();\n dragNodeRef.current.fx =\n (event.sourceEvent.clientX - rect.left - transform.x) / transform.k;\n dragNodeRef.current.fy =\n (event.sourceEvent.clientY - rect.top - transform.y) / transform.k;\n })\n .on('end', () => {\n setForcesEnabled(true);\n restart();\n });\n\n g.selectAll('g.node').call(dragBehavior);\n return () => {\n g.selectAll('g.node').on('.drag', null);\n };\n }, [gRef, enableDrag, nodes, transform, restart, setForcesEnabled]);\n\n return (\n <GraphCanvas\n svgRef={svgRef}\n gRef={gRef}\n width={width}\n height={height}\n className={className}\n nodes={nodes}\n links={initialLinks}\n pinnedNodes={pinnedNodes}\n selectedNodeId={selectedNodeId}\n hoveredNodeId={hoveredNodeId}\n defaultNodeColor={defaultNodeColor}\n defaultNodeSize={defaultNodeSize}\n defaultLinkColor={defaultLinkColor}\n defaultLinkWidth={defaultLinkWidth}\n showNodeLabels={showNodeLabels}\n showLinkLabels={showLinkLabels}\n onNodeClick={onNodeClick}\n onNodeHover={onNodeHover}\n onLinkClick={onLinkClick}\n packageBounds={packageBounds}\n handleNodeDoubleClick={handleNodeDoubleClick}\n handleDragStart={handleDragStart}\n restart={restart}\n setPinnedNodes={setPinnedNodes}\n />\n );\n }\n);\n\nForceDirectedGraph.displayName = 'ForceDirectedGraph';\n"]}
|
|
@@ -3,7 +3,7 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const buttonVariants: (props?: ({
|
|
6
|
-
variant?: "
|
|
6
|
+
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | "glow" | "glass" | "accent" | null | undefined;
|
|
7
7
|
size?: "default" | "sm" | "lg" | "icon" | "xs" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
@@ -117,10 +117,15 @@ function useForceSimulation(initialNodes, initialLinks, options) {
|
|
|
117
117
|
try {
|
|
118
118
|
seedCircularPositions(nodesCopy, width, height);
|
|
119
119
|
} catch (error) {
|
|
120
|
-
console.warn(
|
|
120
|
+
console.warn(
|
|
121
|
+
"AIReady: Position seeding failed, using random fallback:",
|
|
122
|
+
error
|
|
123
|
+
);
|
|
121
124
|
seedRandomPositions(nodesCopy, width, height);
|
|
122
125
|
}
|
|
123
|
-
const simulation = d3.forceSimulation(
|
|
126
|
+
const simulation = d3.forceSimulation(
|
|
127
|
+
nodesCopy
|
|
128
|
+
);
|
|
124
129
|
applySimulationForces(simulation, linksCopy);
|
|
125
130
|
configureSimulationParameters(simulation);
|
|
126
131
|
simulationRef.current = simulation;
|
|
@@ -150,10 +155,19 @@ function useForceSimulation(initialNodes, initialLinks, options) {
|
|
|
150
155
|
const applySimulationForces = (simulation, linksCopy) => {
|
|
151
156
|
try {
|
|
152
157
|
const linkForce = d3.forceLink(linksCopy).id((d) => d.id).distance((d) => d.distance ?? linkDistance).strength(linkStrength);
|
|
153
|
-
simulation.force(FORCE_NAMES.LINK, linkForce).force(FORCE_NAMES.CHARGE, d3.forceManyBody().strength(chargeStrength)).force(
|
|
158
|
+
simulation.force(FORCE_NAMES.LINK, linkForce).force(FORCE_NAMES.CHARGE, d3.forceManyBody().strength(chargeStrength)).force(
|
|
159
|
+
FORCE_NAMES.CENTER,
|
|
160
|
+
d3.forceCenter(width / 2, height / 2).strength(centerStrength)
|
|
161
|
+
).force(
|
|
154
162
|
FORCE_NAMES.COLLISION,
|
|
155
163
|
d3.forceCollide().radius((d) => (d.size ?? 10) + collisionRadius).strength(collisionStrength)
|
|
156
|
-
).force(
|
|
164
|
+
).force(
|
|
165
|
+
FORCE_NAMES.X,
|
|
166
|
+
d3.forceX(width / 2).strength(Math.max(0.02, centerStrength * 0.5))
|
|
167
|
+
).force(
|
|
168
|
+
FORCE_NAMES.Y,
|
|
169
|
+
d3.forceY(height / 2).strength(Math.max(0.02, centerStrength * 0.5))
|
|
170
|
+
);
|
|
157
171
|
} catch (error) {
|
|
158
172
|
console.warn("AIReady: Failed to configure simulation forces:", error);
|
|
159
173
|
}
|
|
@@ -167,7 +181,9 @@ function useForceSimulation(initialNodes, initialLinks, options) {
|
|
|
167
181
|
}
|
|
168
182
|
if (maxSimulationTimeMs > 0) {
|
|
169
183
|
stopTimeoutRef.current = setTimeout(() => {
|
|
170
|
-
safelyStopSimulation(simulation, nodesCopy, {
|
|
184
|
+
safelyStopSimulation(simulation, nodesCopy, {
|
|
185
|
+
stabilize: stabilizeOnStop
|
|
186
|
+
});
|
|
171
187
|
updateStateAfterStop(nodesCopy, linksCopy, 0);
|
|
172
188
|
}, maxSimulationTimeMs);
|
|
173
189
|
}
|
|
@@ -189,7 +205,9 @@ function useForceSimulation(initialNodes, initialLinks, options) {
|
|
|
189
205
|
}
|
|
190
206
|
const currentAlpha = simulation.alpha();
|
|
191
207
|
if (currentAlpha <= alphaMin) {
|
|
192
|
-
safelyStopSimulation(simulation, nodesCopy, {
|
|
208
|
+
safelyStopSimulation(simulation, nodesCopy, {
|
|
209
|
+
stabilize: stabilizeOnStop
|
|
210
|
+
});
|
|
193
211
|
updateStateAfterStop(nodesCopy, linksCopy, currentAlpha);
|
|
194
212
|
return;
|
|
195
213
|
}
|
|
@@ -241,24 +259,29 @@ function useForceSimulation(initialNodes, initialLinks, options) {
|
|
|
241
259
|
setIsRunning(false);
|
|
242
260
|
}
|
|
243
261
|
}, []);
|
|
244
|
-
const setForcesEnabled = useCallback(
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
262
|
+
const setForcesEnabled = useCallback(
|
|
263
|
+
(enabled) => {
|
|
264
|
+
const sim = simulationRef.current;
|
|
265
|
+
if (!sim || forcesEnabledRef.current === enabled) return;
|
|
266
|
+
forcesEnabledRef.current = enabled;
|
|
267
|
+
try {
|
|
268
|
+
const charge = sim.force(
|
|
269
|
+
FORCE_NAMES.CHARGE
|
|
270
|
+
);
|
|
271
|
+
if (charge) {
|
|
272
|
+
charge.strength(enabled ? originalForcesRef.current.charge : 0);
|
|
273
|
+
}
|
|
274
|
+
const link = sim.force(FORCE_NAMES.LINK);
|
|
275
|
+
if (link) {
|
|
276
|
+
link.strength(enabled ? originalForcesRef.current.link : 0);
|
|
277
|
+
}
|
|
278
|
+
sim.alpha(warmAlpha).restart();
|
|
279
|
+
} catch (error) {
|
|
280
|
+
console.warn("AIReady: Failed to toggle simulation forces:", error);
|
|
256
281
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
}, [warmAlpha]);
|
|
282
|
+
},
|
|
283
|
+
[warmAlpha]
|
|
284
|
+
);
|
|
262
285
|
return {
|
|
263
286
|
nodes,
|
|
264
287
|
links,
|
|
@@ -1 +1 @@
|
|
|
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 { SIMULATION_DEFAULTS, FORCE_NAMES, EVENT_NAMES } 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<SimulationNode, SimulationLink> | 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 = typeof l.source === 'string' ? l.source : (l.source as SimulationNode)?.id;\n const targetId = typeof l.target === 'string' ? l.target : (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('AIReady: Position seeding failed, using random fallback:', error);\n seedRandomPositions(nodesCopy, width, height);\n }\n\n const simulation = d3.forceSimulation<SimulationNode, SimulationLink>(nodesCopy);\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(FORCE_NAMES.CENTER, d3.forceCenter(width / 2, height / 2).strength(centerStrength))\n .force(\n FORCE_NAMES.COLLISION,\n d3.forceCollide<SimulationNode>().radius((d) => (d.size ?? 10) + collisionRadius).strength(collisionStrength)\n )\n .force(FORCE_NAMES.X, d3.forceX(width / 2).strength(Math.max(0.02, centerStrength * 0.5)))\n .force(FORCE_NAMES.Y, d3.forceY(height / 2).strength(Math.max(0.02, centerStrength * 0.5)));\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 = (simulation: d3.Simulation<SimulationNode, SimulationLink>) => {\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, { stabilize: stabilizeOnStop });\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, { stabilize: stabilizeOnStop });\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 (rafState.rafId === null && now - rafState.lastUpdate >= tickThrottleMs) {\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((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(FORCE_NAMES.CHARGE) 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<SimulationNode, SimulationLink> | 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 }, [warmAlpha]);\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(simulation: d3.Simulation<SimulationNode, any> | null | undefined) {\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"]}
|
|
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 { type?: string }).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 { distance?: number }).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"]}
|