@memberjunction/ng-entity-relationship-diagram 5.43.0 → 5.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/dist/lib/components/entity-details/entity-details.component.js +157 -154
  2. package/dist/lib/components/entity-details/entity-details.component.js.map +1 -1
  3. package/dist/lib/components/erd-diagram.component.d.ts +4 -0
  4. package/dist/lib/components/erd-diagram.component.d.ts.map +1 -1
  5. package/dist/lib/components/erd-diagram.component.js +19 -25
  6. package/dist/lib/components/erd-diagram.component.js.map +1 -1
  7. package/dist/lib/entity-relationship-diagram.module.d.ts +1 -1
  8. package/dist/lib/entity-relationship-diagram.module.d.ts.map +1 -1
  9. package/dist/lib/entity-relationship-diagram.module.js +9 -3
  10. package/dist/lib/entity-relationship-diagram.module.js.map +1 -1
  11. package/package.json +6 -5
  12. package/dist/__tests__/compute-erd-layout.test.d.ts +0 -2
  13. package/dist/__tests__/compute-erd-layout.test.d.ts.map +0 -1
  14. package/dist/__tests__/compute-erd-layout.test.js +0 -207
  15. package/dist/__tests__/compute-erd-layout.test.js.map +0 -1
  16. package/dist/__tests__/entity-to-erd-adapter.test.d.ts +0 -2
  17. package/dist/__tests__/entity-to-erd-adapter.test.d.ts.map +0 -1
  18. package/dist/__tests__/entity-to-erd-adapter.test.js +0 -252
  19. package/dist/__tests__/entity-to-erd-adapter.test.js.map +0 -1
  20. package/dist/__tests__/erd-types.test.d.ts +0 -2
  21. package/dist/__tests__/erd-types.test.d.ts.map +0 -1
  22. package/dist/__tests__/erd-types.test.js +0 -104
  23. package/dist/__tests__/erd-types.test.js.map +0 -1
  24. package/dist/__tests__/index.test.d.ts +0 -2
  25. package/dist/__tests__/index.test.d.ts.map +0 -1
  26. package/dist/__tests__/index.test.js +0 -7
  27. package/dist/__tests__/index.test.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"entity-details.component.js","sourceRoot":"","sources":["../../../../src/lib/components/entity-details/entity-details.component.ts","../../../../src/lib/components/entity-details/entity-details.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAA4B,SAAS,EAAc,MAAM,eAAe,CAAC;AAExH,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;;;;;;;ICsB7D,AADF,+BAAsB,YACb;IAAA,4BAAY;IAAA,iBAAQ;IAC3B,4BAAM;IAAA,YAAiC;IACzC,AADyC,iBAAO,EAC1C;;;IADE,eAAiC;IAAjC,8FAAiC;;;;IAkBrC,AADF,+BAA2B,iBAKC;IADxB,2LAAS,sBAAe,KAAK,CAAC,KAAC;IAE/B,qBACF;IAAA,iBAAS;IACT,kCAI0C;IADxC,2LAAS,sBAAe,MAAM,CAAC,KAAC;IAEhC,sBACF;IAAA,iBAAS;IACT,kCAIuC;IADrC,2LAAS,sBAAe,cAAc,CAAC,KAAC;IAExC,qBACF;IAAA,iBAAS;IACT,kCAImC;IADjC,2LAAS,sBAAe,SAAS,CAAC,KAAC;IAEnC,yBACF;IACF,AADE,iBAAS,EACL;;;IA1BF,cAAsC;IAAtC,sDAAsC;IAOtC,eAAuC;IAAvC,uDAAuC;IAOvC,eAA+C;IAA/C,+DAA+C;IAO/C,eAA0C;IAA1C,0DAA0C;;;IAuBpC,2BAAoE;;;IAEpE,2BAAqE;;;;IAMrE,kCAIiC;IAF/B,+PAAS,qCAA2B,KAAC;IAGrC,2BAAsC;IACxC,iBAAS;;;;IAHP,qEAAkD;;;;IAMpD,kCAImC;IAFjC,+PAAS,0CAAgC,KAAC;IAG1C,2BAA6C;IAC/C,iBAAS;;;;IAHP,0EAAuD;;;IAOvD,gCAAsC;IAAA,kBAAE;IAAA,iBAAO;;;IAG/C,gCAAsC;IAAA,kBAAE;IAAA,iBAAO;;;IAQnD,+BAA4B;IAC1B,2BAA6C;IAC7C,gCACF;IAAA,iBAAM;;;IAKN,AADF,+BAA+B,cACC;IAAA,YAAuB;IACvD,AADuD,iBAAM,EACvD;;;IAD0B,eAAuB;IAAvB,0CAAuB;;;IAQjD,gCAAwB;IAAA,YAAW;IAAA,iBAAO;;;IAAlB,cAAW;IAAX,8BAAW;;;IAHvC,AADF,+BAA0B,cACG;IAAA,gCAAgB;IAAA,iBAAM;IACjD,+BAAyB;IACvB,iJAEC;IAEL,AADE,iBAAM,EACF;;;;IAJF,eAEC;IAFD,cAAA,uCAA6B,CAE5B;;;IAQC,AADF,+BAA2C,cACR;IAAA,YAAuB;IAC1D,AAD0D,iBAAM,EAC1D;;;IAD6B,eAAuB;IAAvB,0CAAuB;;;IAe9C,gCAAyB;IAAA,YAAuB;IAAA,iBAAO;;;IAA9B,cAAuB;IAAvB,mDAAuB;;;IAIlD,+BAA+B;IAAA,YAA4B;IAAA,iBAAM;;;IAAlC,cAA4B;IAA5B,+CAA4B;;;IAN3D,AADF,AADF,+BAAwB,cACE,eACG;IAAA,YAAsB;IAAA,iBAAO;IACtD,kJAA+D;IAGjE,iBAAM;IACN,iJAA6E;IAG/E,iBAAM;;;IARuB,eAAsB;IAAtB,yCAAsB;IAC/C,cAEC;IAFD,2FAEC;IAEH,cAEC;IAFD,yGAEC;;;IAfP,AADF,+BAAwC,cACX;IACzB,2BAAsC;IACtC,YACF;IAAA,iBAAM;IACN,+BAAyB;IACvB,4IAYC;IAEL,AADE,iBAAM,EACF;;;;IAjBF,eACF;IADE,oFACF;IAEE,eAYC;IAZD,cAAA,2CAAiC,CAYhC;;;IAiBD,AADF,+BAAwB,eACK;IAAA,2BAAW;IAAA,iBAAO;IAC7C,gCAA2B;IAAA,YAAkB;IAC/C,AAD+C,iBAAO,EAChD;;;IADuB,eAAkB;IAAlB,qCAAkB;;;IAK7C,AADF,+BAAwB,eACK;IAAA,0BAAU;IAAA,iBAAO;IAC5C,gCAA2B;IAAA,YAAqB;IAClD,AADkD,iBAAO,EACnD;;;IADuB,eAAqB;IAArB,wCAAqB;;;IAKhD,AADF,+BAAwB,eACK;IAAA,sBAAM;IAAA,iBAAO;IACxC,gCAA2B;IAAA,YAAiB;IAC9C,AAD8C,iBAAO,EAC/C;;;IADuB,eAAiB;IAAjB,oCAAiB;;;IAW5C,AADF,+BAAwB,eACK;IAAA,8BAAc;IAAA,iBAAO;IAChD,gCAAyC;IAAA,YAAwB;IACnE,AADmE,iBAAO,EACpE;;;IADqC,eAAwB;IAAxB,2CAAwB;;;;IAKjE,AADF,+BAAwB,eACK;IAAA,+BAAe;IAAA,iBAAO;IACjD,gCAE+D;IADzD,oRAAS,6CAAmC,KAAC;IAEjD,YACA;IAAA,2BAA6C;IAEjD,AADE,iBAAO,EACH;;;IAJE,eAAwD;IAAxD,uBAAA,wEAAwD,CAAA;IAC5D,cACA;IADA,uDACA;;;IAMF,AADF,+BAAwB,eACK;IAAA,+BAAe;IAAA,iBAAO;IACjD,gCAA0C;IAAA,mBAAG;IAC/C,AAD+C,iBAAO,EAChD;;;IArFZ,+BAAyC;IACvC,6HAAyB;IAKzB,6HAAqE;IAyBjE,AADF,AADF,+BAA0B,cACA,eACK;IAAA,0BAAU;IAAA,iBAAO;IAC5C,gCAA2B;IAAA,YAAgB;IAC7C,AAD6C,iBAAO,EAC9C;IAEJ,AADF,+BAAwB,gBACK;IAAA,0BAAS;IAAA,iBAAO;IAC3C,iCAAuF;IACrF,aACF;IACF,AADE,iBAAO,EACH;IACN,+HAAwC;IAMxC,+HAA8C;IAM9C,+HAAsC;IAOpC,AADF,gCAAwB,gBACK;IAAA,+BAAc;IAAA,iBAAO;IAChD,iCAAoF;IAClF,aACF;IACF,AADE,iBAAO,EACH;IACN,+HAA0B;IAM1B,+HAA6B;IAW7B,+HAA2B;IAO/B,AADE,iBAAM,EACF;;;IAvFJ,cAIC;IAJD,+CAIC;IACD,cAsBC;IAtBD,8FAsBC;IAI8B,eAAgB;IAAhB,mCAAgB;IAIhB,eAA2D;IAA3D,mEAA2D;IACpF,cACF;IADE,mEACF;IAEF,cAKC;IALD,kEAKC;IACD,cAKC;IALD,wEAKC;IACD,cAKC;IALD,gEAKC;IAG4B,eAAwD;IAAxD,gEAAwD;IACjF,cACF;IADE,kEACF;IAEF,cAKC;IALD,iDAKC;IACD,cAUC;IAVD,oDAUC;IACD,cAKC;IALD,kDAKC;;;;IA9JT,+BAQ+D;IAD1D,0NAAS,6BAAmB,KAAC;IAG9B,AADF,+BAA0B,cACA;IAGpB,AAFF,+GAA0B,yFAEU;IAGpC,YACF;IAAA,iBAAM;IACN,+BAA2B;IACzB,iHAAqC;IASrC,iHAAyB;IASzB,+BAA0B;IACxB,iHAA0B;IAG1B,iHAAoD;IAK1D,AADE,AADE,iBAAM,EACF,EACF;IAEJ,AADF,gCAA2B,eACD;IAAA,aAAgB;IAAA,iBAAM;IAC9C,gHAA6B;IAM/B,iBAAM;IACN,gHAAiE;IAKjE,gHAAwE;IAUxE,kHAAwC;IA2F1C,iBAAM;;;;IAjKD,sNAKE;IAEF,0EAAyD;IAGxD,eAIC;IAJD,+EAIC;IACD,eACF;IADE,8CACF;IAEE,eAQC;IARD,kEAQC;IACD,cAQC;IARD,+CAQC;IAEC,eAEC;IAFD,iDAEC;IACD,cAEC;IAFD,8EAEC;IAKmB,eAAgB;IAAhB,mCAAgB;IACxC,cAKC;IALD,oDAKC;IAEH,cAIC;IAJD,kGAIC;IACD,cASC;IATD,gHASC;IACD,cA0FC;IA1FD,sEA0FC;;;IAnKP,kCAA8C;IAC5C,2GAoKC;IACH,iBAAM;;;IArKJ,eAoKC;IApKD,cAAA,4FAAsC,EAAE,CAAC,CAoKxC;;;;IAoBC,+BAA6E;IAA5C,oOAAS,uCAA4B,IAAI,CAAC,KAAC;IAC1E,2BAA0C;IAC1C,gCAA0B;IAAA,YAAoD;IAAA,iBAAO;IACrF,2BAA4F;IAC9F,iBAAM;;;IAFsB,eAAoD;IAApD,4EAAoD;;;IAJpF,kCAA+D;IAC7D,yGAMC;IACH,iBAAM;;;IAPJ,eAMC;IAND,cAAA,+FAAyC,EAAE,CAAC,CAM3C;;AD7PT;;;;;;GAMG;AAOH,MAAM,OAAO,sBAAuB,SAAQ,oBAAoB;IACT,mBAAmB,CAAc;IAC1B,0BAA0B,CAAc;IAEpG,2DAA2D;IAClD,cAAc,GAAsB,IAAI,CAAC;IAElD,yDAAyD;IAChD,eAAe,GAAsB,EAAE,CAAC;IAEjD,6CAA6C;IACpC,qBAAqB,GAAG,IAAI,CAAC;IAEtC,oDAAoD;IAC3C,4BAA4B,GAAG,IAAI,CAAC;IAE7C,yDAAyD;IAC/C,UAAU,GAAG,IAAI,YAAY,EAAc,CAAC;IAEtD,gDAAgD;IACtC,UAAU,GAAG,IAAI,YAAY,EAAQ,CAAC;IAEhD,6CAA6C;IACnC,mBAAmB,GAAG,IAAI,YAAY,EAAQ,CAAC;IAEzD,oDAAoD;IAC1C,0BAA0B,GAAG,IAAI,YAAY,EAAQ,CAAC;IAEhE,gFAAgF;IACtE,cAAc,GAAG,IAAI,YAAY,EAAc,CAAC;IAE1D,uDAAuD;IAC7C,UAAU,GAAG,IAAI,YAAY,EAAgC,CAAC;IAEjE,WAAW,GAAgD,KAAK,CAAC;IACjE,yBAAyB,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9C,mBAAmB,GAAG,IAAI,GAAG,EAAU,CAAC;IACxC,oBAAoB,GAAG,IAAI,GAAG,EAAU,CAAC;IACxC,wBAAwB,GAAkB,IAAI,CAAC;IAEvD,WAAW,CAAC,OAAsB;QAChC,IAAI,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,WAAW,EAAE,CAAC;YACxE,MAAM,eAAe,GAAG,IAAI,CAAC,cAAc,EAAE,EAAE,IAAI,IAAI,CAAC;YAExD,mCAAmC;YACnC,IAAI,eAAe,KAAK,IAAI,CAAC,wBAAwB,EAAE,CAAC;gBACtD,6CAA6C;gBAC7C,IAAI,CAAC,oBAAoB,EAAE,CAAC;gBAE5B,IAAI,CAAC,wBAAwB,GAAG,eAAe,CAAC;YAClD,CAAC;QACH,CAAC;IACH,CAAC;IAEO,oBAAoB;QAC1B,8CAA8C;QAC9C,UAAU,CAAC,GAAG,EAAE;YACd,IAAI,IAAI,CAAC,mBAAmB,EAAE,aAAa,EAAE,CAAC;gBAC5C,IAAI,CAAC,mBAAmB,CAAC,aAAa,CAAC,SAAS,GAAG,CAAC,CAAC;YACvD,CAAC;YACD,IAAI,IAAI,CAAC,0BAA0B,EAAE,aAAa,EAAE,CAAC;gBACnD,IAAI,CAAC,0BAA0B,CAAC,aAAa,CAAC,SAAS,GAAG,CAAC,CAAC;YAC9D,CAAC;QACH,CAAC,EAAE,CAAC,CAAC,CAAC;IACR,CAAC;IAEM,YAAY;QACjB,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;gBACnB,UAAU,EAAE,cAAc;gBAC1B,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC,EAAE;aACjC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAEM,YAAY;QACjB,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC;IAEM,mBAAmB;QACxB,IAAI,CAAC,mBAAmB,CAAC,IAAI,EAAE,CAAC;IAClC,CAAC;IAEM,0BAA0B;QAC/B,IAAI,CAAC,0BAA0B,CAAC,IAAI,EAAE,CAAC;IACzC,CAAC;IAEM,cAAc,CAAC,MAAmD;QACvE,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC;IAC5B,CAAC;IAEM,eAAe,CAAC,QAAgB;QACrC,IAAI,CAAC,QAAQ;YAAE,OAAO,EAAE,CAAC;QAEzB,IAAI,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;QAEhF,QAAQ,IAAI,CAAC,WAAW,EAAE,CAAC;YACzB,KAAK,MAAM;gBACT,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;YACnF,KAAK,cAAc;gBACjB,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;YAClE,KAAK,SAAS;gBACZ,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;YACnE;gBACE,OAAO,MAAM,CAAC;QAClB,CAAC;IACH,CAAC;IAEM,kBAAkB,CAAC,QAAgB;QACxC,IAAI,CAAC,QAAQ;YAAE,OAAO,EAAE,CAAC;QAEzB,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAU,CAAC;QAE3C,0DAA0D;QAC1D,IAAI,CAAC,eAAe;aACjB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,eAAe,CAAC;aAClE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,eAAgB,CAAC,CAAC,CAAC;QAE1D,0CAA0C;QAC1C,IAAI,CAAC,eAAe;aACjB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;aACpD,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAElD,wEAAwE;QACxE,gBAAgB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAElC,uCAAuC;QACvC,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC;QAC9B,MAAM,WAAW,GAAG,EAAE,CAAC,QAAQ,CAAC;QAChC,MAAM,OAAO,GAAiB,EAAE,CAAC;QACjC,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE;YAC5B,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;YAC3D,IAAI,MAAM,EAAE,CAAC;gBACX,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACvB,CAAC;QACH,CAAC,CAAC,CAAC;QACH,OAAO,OAAO,CAAC;IACjB,CAAC;IAEM,YAAY,CAAC,KAAsB;QACxC,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACpC,CAAC;IAEM,sBAAsB,CAAC,OAAe;QAC3C,IAAI,IAAI,CAAC,yBAAyB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YAChD,IAAI,CAAC,yBAAyB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACjD,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,yBAAyB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAEM,iBAAiB,CAAC,OAAe;QACtC,IAAI,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YAC1C,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC3C,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAEM,kBAAkB,CAAC,OAAe;QACvC,IAAI,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3C,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC5C,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IAEM,0BAA0B,CAAC,OAAe;QAC/C,OAAO,IAAI,CAAC,yBAAyB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACrD,CAAC;IAEM,qBAAqB,CAAC,OAAe;QAC1C,OAAO,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC/C,CAAC;IAEM,sBAAsB,CAAC,OAAe;QAC3C,OAAO,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC;IAEM,sBAAsB,CAAC,KAAsB;QAClD,OAAO,KAAK,CAAC,iBAAiB,IAAI,KAAK,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC;IACvE,CAAC;IAEM,sBAAsB,CAAC,KAAsB;QAClD,IAAI,CAAC,KAAK,CAAC,iBAAiB;YAAE,OAAO,EAAE,CAAC;QACxC,OAAO,KAAK,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChE,CAAC;IAEM,0BAA0B,CAAC,KAAsB;QACtD,IAAI,CAAC,KAAK,CAAC,iBAAiB;YAAE,OAAO,EAAE,CAAC;QACxC,OAAO,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAC3C,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;gBACzD,OAAO,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC;YACjC,CAAC;YACD,OAAO,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;IACL,CAAC;IAEM,oBAAoB,CAAC,KAAY,EAAE,KAAsB;QAC9D,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,IAAI,KAAK,CAAC,eAAe,EAAE,CAAC;YAC1B,mDAAmD;YACnD,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC;YAC9B,MAAM,aAAa,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;YACrF,IAAI,aAAa,EAAE,CAAC;gBAClB,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;IACH,CAAC;IAEM,YAAY,CAAC,MAAkB,EAAE,UAAmB,KAAK;QAC9D,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;qQApNU,sBAAsB,yBAAtB,sBAAsB;6DAAtB,sBAAsB;;;;;;;YCxB/B,AADF,AADF,8BAA2B,aACC,SACpB;YAAA,YAAwD;YAAA,iBAAK;YAE/D,AADF,8BAA2B,gBACoD;YAApD,mGAAS,kBAAc,IAAC;YAC/C,0BAAmD;YACnD,sBACF;YAAA,iBAAS;YACT,iCAAmD;YAAzB,mGAAS,kBAAc,IAAC;YAChD,0BAAuC;YAG7C,AADE,AADE,iBAAS,EACL,EACF;YAIF,AADF,AADF,+BAAyB,eACD,aACb;YAAA,wBAAO;YAAA,iBAAQ;YACtB,6BAAM;YAAA,aAAgC;YACxC,AADwC,iBAAO,EACzC;YAEJ,AADF,gCAAsB,aACb;YAAA,uBAAM;YAAA,iBAAQ;YACrB,6BAAM;YAAA,aAA+B;YACvC,AADuC,iBAAO,EACxC;YACN,2FAAmC;YAMrC,iBAAM;YAIF,AADF,AADF,gCAAgI,eACpF,eACyB;YAAhC,iGAAS,yBAAqB,IAAC;YAC9D,mCAGgC;YAC9B,4BAA+C;YACjD,iBAAS;YACT,2BAAI;YAAA,aAA6E;YACnF,AADmF,iBAAK,EAClF;YACN,2FAA6B;YAgC/B,iBAAM;YACN,2FAA6B;YAyK/B,iBAAM;YAIF,AADF,AADF,gCAAqJ,eACzG,eACgC;YAAvC,iGAAS,gCAA4B,IAAC;YACrE,mCAGuC;YACrC,4BAA+C;YACjD,iBAAS;YACT,2BAAI;YAAA,aAA0F;YAElG,AADE,AADgG,iBAAK,EAC/F,EACF;YACN,2FAAoC;YAYxC,AADE,iBAAM,EACF;;YA5QE,eAAwD;YAAxD,0JAAwD;YAepD,gBAAgC;YAAhC,uFAAgC;YAIhC,eAA+B;YAA/B,sFAA+B;YAEvC,cAKC;YALD,gGAKC;YAGyB,cAAgD;YAAC,AAAjD,6DAAgD,iDAAmD;YAKvH,eAAwC;YAAxC,qDAAwC;YAItC,eAA6E;YAA7E,kHAA6E;YAEnF,cA+BC;YA/BD,qDA+BC;YAEH,cAwKC;YAxKD,qDAwKC;YAGgC,cAAuD;YAAC,AAAxD,oEAAuD,wDAA0D;YAK5I,eAA+C;YAA/C,4DAA+C;YAI7C,eAA0F;YAA1F,+HAA0F;YAGlG,cAUC;YAVD,4DAUC;;;iFDlPQ,sBAAsB;cANlC,SAAS;6BACI,KAAK,YACP,mBAAmB;;kBAK5B,SAAS;mBAAC,qBAAqB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE;;kBAClD,SAAS;mBAAC,4BAA4B,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE;;kBAGzD,KAAK;;kBAGL,KAAK;;kBAGL,KAAK;;kBAGL,KAAK;;kBAGL,MAAM;;kBAGN,MAAM;;kBAGN,MAAM;;kBAGN,MAAM;;kBAGN,MAAM;;kBAGN,MAAM;;kFAhCI,sBAAsB","sourcesContent":["import { Component, Input, Output, EventEmitter, OnChanges, SimpleChanges, ViewChild, ElementRef } from '@angular/core';\nimport { EntityInfo, EntityFieldInfo, EntityFieldValueInfo } from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\n\n/**\n * Event emitted when requesting to open an entity record.\n */\nexport interface EntityDetailsOpenRecordEvent {\n EntityName: string;\n RecordID: string;\n}\n\n/**\n * Entity details panel component that displays detailed information about a selected entity.\n * Shows entity metadata, fields with filtering capabilities, and related entities.\n *\n * This component is designed to be used alongside the ERD diagram to provide\n * a detailed view of the currently selected entity.\n */\n@Component({\n standalone: false,\n selector: 'mj-entity-details',\n templateUrl: './entity-details.component.html',\n styleUrls: ['./entity-details.component.css']\n})\nexport class EntityDetailsComponent extends BaseAngularComponent implements OnChanges {\n @ViewChild('fieldsListContainer', { static: false }) fieldsListContainer!: ElementRef;\n @ViewChild('relationshipsListContainer', { static: false }) relationshipsListContainer!: ElementRef;\n\n /** The currently selected entity to display details for */\n @Input() selectedEntity: EntityInfo | null = null;\n\n /** All entity fields for looking up field information */\n @Input() allEntityFields: EntityFieldInfo[] = [];\n\n /** Whether the fields section is expanded */\n @Input() fieldsSectionExpanded = true;\n\n /** Whether the relationships section is expanded */\n @Input() relationshipsSectionExpanded = true;\n\n /** Emitted when user clicks to open the entity record */\n @Output() openEntity = new EventEmitter<EntityInfo>();\n\n /** Emitted when user clicks the close button */\n @Output() closePanel = new EventEmitter<void>();\n\n /** Emitted when fields section is toggled */\n @Output() fieldsSectionToggle = new EventEmitter<void>();\n\n /** Emitted when relationships section is toggled */\n @Output() relationshipsSectionToggle = new EventEmitter<void>();\n\n /** Emitted when a related entity is selected (clicked in relationships list) */\n @Output() entitySelected = new EventEmitter<EntityInfo>();\n\n /** Emitted when requesting to open an entity record */\n @Output() openRecord = new EventEmitter<EntityDetailsOpenRecordEvent>();\n\n public fieldFilter: 'all' | 'keys' | 'foreign_keys' | 'regular' = 'all';\n public expandedFieldDescriptions = new Set<string>();\n public expandedFieldValues = new Set<string>();\n public expandedFieldDetails = new Set<string>();\n private previousSelectedEntityId: string | null = null;\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['selectedEntity'] && !changes['selectedEntity'].firstChange) {\n const currentEntityId = this.selectedEntity?.ID || null;\n\n // Check if entity actually changed\n if (currentEntityId !== this.previousSelectedEntityId) {\n // Reset scroll positions when entity changes\n this.resetScrollPositions();\n\n this.previousSelectedEntityId = currentEntityId;\n }\n }\n }\n\n private resetScrollPositions(): void {\n // Use setTimeout to ensure the DOM is updated\n setTimeout(() => {\n if (this.fieldsListContainer?.nativeElement) {\n this.fieldsListContainer.nativeElement.scrollTop = 0;\n }\n if (this.relationshipsListContainer?.nativeElement) {\n this.relationshipsListContainer.nativeElement.scrollTop = 0;\n }\n }, 0);\n }\n\n public onOpenEntity(): void {\n if (this.selectedEntity) {\n this.openRecord.emit({\n EntityName: 'MJ: Entities',\n RecordID: this.selectedEntity.ID\n });\n }\n }\n\n public onClosePanel(): void {\n this.closePanel.emit();\n }\n\n public toggleFieldsSection(): void {\n this.fieldsSectionToggle.emit();\n }\n\n public toggleRelationshipsSection(): void {\n this.relationshipsSectionToggle.emit();\n }\n\n public setFieldFilter(filter: 'all' | 'keys' | 'foreign_keys' | 'regular'): void {\n this.fieldFilter = filter;\n }\n\n public getEntityFields(entityId: string): EntityFieldInfo[] {\n if (!entityId) return [];\n\n let fields = this.allEntityFields.filter(f => UUIDsEqual(f.EntityID, entityId));\n\n switch (this.fieldFilter) {\n case 'keys':\n return fields.filter(f => f.IsPrimaryKey || f.Name.toLowerCase().includes('id'));\n case 'foreign_keys':\n return fields.filter(f => f.RelatedEntityID && !f.IsPrimaryKey);\n case 'regular':\n return fields.filter(f => !f.IsPrimaryKey && !f.RelatedEntityID);\n default:\n return fields;\n }\n }\n\n public getRelatedEntities(entityId: string): EntityInfo[] {\n if (!entityId) return [];\n\n const relatedEntityIds = new Set<string>();\n\n // Get entities that this entity references (foreign keys)\n this.allEntityFields\n .filter(f => UUIDsEqual(f.EntityID, entityId) && f.RelatedEntityID)\n .forEach(f => relatedEntityIds.add(f.RelatedEntityID!));\n\n // Get entities that reference this entity\n this.allEntityFields\n .filter(f => UUIDsEqual(f.RelatedEntityID, entityId))\n .forEach(f => relatedEntityIds.add(f.EntityID));\n\n // Remove the current entity from the set (don't return self-references)\n relatedEntityIds.delete(entityId);\n\n // Convert to actual EntityInfo objects\n const md = this.ProviderToUse;\n const allEntities = md.Entities;\n const retVals: EntityInfo[] = [];\n relatedEntityIds.forEach(id => {\n const entity = allEntities.find(e => UUIDsEqual(e.ID, id));\n if (entity) {\n retVals.push(entity);\n }\n });\n return retVals;\n }\n\n public onFieldClick(field: EntityFieldInfo): void {\n this.toggleFieldDetails(field.ID);\n }\n\n public toggleFieldDescription(fieldId: string): void {\n if (this.expandedFieldDescriptions.has(fieldId)) {\n this.expandedFieldDescriptions.delete(fieldId);\n } else {\n this.expandedFieldDescriptions.add(fieldId);\n }\n }\n\n public toggleFieldValues(fieldId: string): void {\n if (this.expandedFieldValues.has(fieldId)) {\n this.expandedFieldValues.delete(fieldId);\n } else {\n this.expandedFieldValues.add(fieldId);\n }\n }\n\n public toggleFieldDetails(fieldId: string): void {\n if (this.expandedFieldDetails.has(fieldId)) {\n this.expandedFieldDetails.delete(fieldId);\n } else {\n this.expandedFieldDetails.add(fieldId);\n }\n }\n\n public isFieldDescriptionExpanded(fieldId: string): boolean {\n return this.expandedFieldDescriptions.has(fieldId);\n }\n\n public isFieldValuesExpanded(fieldId: string): boolean {\n return this.expandedFieldValues.has(fieldId);\n }\n\n public isFieldDetailsExpanded(fieldId: string): boolean {\n return this.expandedFieldDetails.has(fieldId);\n }\n\n public hasFieldPossibleValues(field: EntityFieldInfo): boolean {\n return field.EntityFieldValues && field.EntityFieldValues.length > 0;\n }\n\n public getFieldPossibleValues(field: EntityFieldInfo): string[] {\n if (!field.EntityFieldValues) return [];\n return field.EntityFieldValues.map(v => v.Value).slice(0, 10);\n }\n\n public getSortedEntityFieldValues(field: EntityFieldInfo): EntityFieldValueInfo[] {\n if (!field.EntityFieldValues) return [];\n return field.EntityFieldValues.sort((a, b) => {\n if (a.Sequence !== undefined && b.Sequence !== undefined) {\n return a.Sequence - b.Sequence;\n }\n return a.Value.localeCompare(b.Value);\n });\n }\n\n public onRelatedEntityClick(event: Event, field: EntityFieldInfo): void {\n event.stopPropagation();\n if (field.RelatedEntityID) {\n // Find the related entity and select it in the ERD\n const md = this.ProviderToUse;\n const relatedEntity = md.Entities.find(e => UUIDsEqual(e.ID, field.RelatedEntityID));\n if (relatedEntity) {\n this.entitySelected.emit(relatedEntity);\n }\n }\n }\n\n public selectEntity(entity: EntityInfo, _zoomTo: boolean = false): void {\n this.entitySelected.emit(entity);\n }\n}\n","<div class=\"details-panel\">\n <div class=\"panel-header\">\n <h3>{{ selectedEntity?.Name || selectedEntity?.SchemaName }}</h3>\n <div class=\"panel-actions\">\n <button class=\"open-btn\" (click)=\"onOpenEntity()\" title=\"Open Entity Record\">\n <span class=\"fa-solid fa-external-link-alt\"></span>\n Open\n </button>\n <button class=\"close-btn\" (click)=\"onClosePanel()\">\n <span class=\"fa-solid fa-times\"></span>\n </button>\n </div>\n </div>\n\n <div class=\"entity-info\">\n <div class=\"info-row\">\n <label>Schema:</label>\n <span>{{ selectedEntity?.SchemaName }}</span>\n </div>\n <div class=\"info-row\">\n <label>Table:</label>\n <span>{{ selectedEntity?.BaseTable }}</span>\n </div>\n @if (selectedEntity?.Description) {\n <div class=\"info-row\">\n <label>Description:</label>\n <span>{{ selectedEntity?.Description }}</span>\n </div>\n }\n </div>\n\n <div class=\"fields-section\" [class.section-expanded]=\"fieldsSectionExpanded\" [class.section-collapsed]=\"!fieldsSectionExpanded\">\n <div class=\"section-header extra-padding\">\n <div class=\"section-title-group\" (click)=\"toggleFieldsSection()\">\n <button\n class=\"expand-btn\"\n [class.expanded]=\"fieldsSectionExpanded\"\n title=\"Toggle fields section\">\n <span class=\"fa-solid fa-chevron-right\"></span>\n </button>\n <h4>Fields ({{ selectedEntity ? getEntityFields(selectedEntity.ID).length : 0 }})</h4>\n </div>\n @if (fieldsSectionExpanded) {\n <div class=\"field-filters\">\n <button\n class=\"filter-btn\"\n [class.active]=\"fieldFilter === 'all'\"\n (click)=\"setFieldFilter('all')\"\n title=\"Show all fields\">\n All\n </button>\n <button\n class=\"filter-btn\"\n [class.active]=\"fieldFilter === 'keys'\"\n (click)=\"setFieldFilter('keys')\"\n title=\"Show primary keys and ID fields\">\n Keys\n </button>\n <button\n class=\"filter-btn\"\n [class.active]=\"fieldFilter === 'foreign_keys'\"\n (click)=\"setFieldFilter('foreign_keys')\"\n title=\"Show foreign key fields only\">\n FKs\n </button>\n <button\n class=\"filter-btn\"\n [class.active]=\"fieldFilter === 'regular'\"\n (click)=\"setFieldFilter('regular')\"\n title=\"Show regular data fields\">\n Regular\n </button>\n </div>\n }\n </div>\n @if (fieldsSectionExpanded) {\n <div class=\"fields-list\" #fieldsListContainer>\n @for (field of getEntityFields(selectedEntity?.ID || ''); track field.ID) {\n <div class=\"field-item\"\n [class]=\"{\n 'primary-key-field': field.IsPrimaryKey,\n 'foreign-key-field': field.RelatedEntityID && !field.IsPrimaryKey,\n 'regular-field': !field.IsPrimaryKey && !field.RelatedEntityID,\n 'field-expanded': isFieldDetailsExpanded(field.ID)\n }\"\n (click)=\"onFieldClick(field)\"\n [title]=\"'Click to see more details about ' + field.Name\">\n <div class=\"field-header\">\n <div class=\"field-name\">\n @if (field.IsPrimaryKey) {\n <span class=\"field-icon fa-solid fa-key\" title=\"Primary Key\"></span>\n } @else if (field.RelatedEntityID) {\n <span class=\"field-icon fa-solid fa-link\" title=\"Foreign Key\"></span>\n }\n {{ field.Name }}\n </div>\n <div class=\"field-actions\">\n @if (hasFieldPossibleValues(field)) {\n <button\n class=\"field-values-btn\"\n (click)=\"toggleFieldValues(field.ID)\"\n [class.expanded]=\"isFieldValuesExpanded(field.ID)\"\n title=\"Toggle possible values\">\n <span class=\"fa-solid fa-list\"></span>\n </button>\n }\n @if (field.Description) {\n <button\n class=\"field-info-btn\"\n (click)=\"toggleFieldDescription(field.ID)\"\n [class.expanded]=\"isFieldDescriptionExpanded(field.ID)\"\n title=\"Toggle field description\">\n <span class=\"fa-solid fa-info-circle\"></span>\n </button>\n }\n <div class=\"field-badges\">\n @if (field.IsPrimaryKey) {\n <span class=\"field-badge primary-key\">PK</span>\n }\n @if (field.RelatedEntityID && !field.IsPrimaryKey) {\n <span class=\"field-badge foreign-key\">FK</span>\n }\n </div>\n </div>\n </div>\n <div class=\"field-details\">\n <div class=\"field-type\">{{ field.Type }}</div>\n @if (field.RelatedEntityID) {\n <div class=\"field-relation\">\n <span class=\"fa-solid fa-arrow-right\"></span>\n Related Entity\n </div>\n }\n </div>\n @if (field.Description && isFieldDescriptionExpanded(field.ID)) {\n <div class=\"field-description\">\n <div class=\"description-text\">{{ field.Description }}</div>\n </div>\n }\n @if (hasFieldPossibleValues(field) && isFieldValuesExpanded(field.ID)) {\n <div class=\"field-values\">\n <div class=\"values-header\">Possible Values:</div>\n <div class=\"values-list\">\n @for (value of getFieldPossibleValues(field); track value; let i = $index) {\n <span class=\"value-tag\">{{ value }}</span>\n }\n </div>\n </div>\n }\n @if (isFieldDetailsExpanded(field.ID)) {\n <div class=\"field-comprehensive-details\">\n @if (field.Description) {\n <div class=\"comprehensive-description-top\">\n <div class=\"description-content\">{{ field.Description }}</div>\n </div>\n }\n @if (field.EntityFieldValues && field.EntityFieldValues.length > 0) {\n <div class=\"field-values-comprehensive\">\n <div class=\"values-header\">\n <span class=\"fa-solid fa-list\"></span>\n Possible Values ({{ field.EntityFieldValues.length }})\n </div>\n <div class=\"values-grid\">\n @for (fieldValue of getSortedEntityFieldValues(field); track fieldValue.ID) {\n <div class=\"value-item\">\n <div class=\"value-main\">\n <span class=\"value-text\">{{ fieldValue.Value }}</span>\n @if (fieldValue.Code && fieldValue.Code !== fieldValue.Value) {\n <span class=\"value-code\">[{{ fieldValue.Code }}]</span>\n }\n </div>\n @if (fieldValue.Description && fieldValue.Description !== fieldValue.Value) {\n <div class=\"value-description\">{{ fieldValue.Description }}</div>\n }\n </div>\n }\n </div>\n </div>\n }\n <div class=\"details-grid\">\n <div class=\"detail-row\">\n <span class=\"detail-label\">Data Type:</span>\n <span class=\"detail-value\">{{ field.Type }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Nullable:</span>\n <span class=\"detail-value\" [class]=\"field.AllowsNull ? 'nullable-yes' : 'nullable-no'\">\n {{ field.AllowsNull ? 'Yes' : 'No' }}\n </span>\n </div>\n @if (field.Length && field.Length > 0) {\n <div class=\"detail-row\">\n <span class=\"detail-label\">Max Length:</span>\n <span class=\"detail-value\">{{ field.Length }}</span>\n </div>\n }\n @if (field.Precision && field.Precision > 0) {\n <div class=\"detail-row\">\n <span class=\"detail-label\">Precision:</span>\n <span class=\"detail-value\">{{ field.Precision }}</span>\n </div>\n }\n @if (field.Scale && field.Scale > 0) {\n <div class=\"detail-row\">\n <span class=\"detail-label\">Scale:</span>\n <span class=\"detail-value\">{{ field.Scale }}</span>\n </div>\n }\n <div class=\"detail-row\">\n <span class=\"detail-label\">Virtual Field:</span>\n <span class=\"detail-value\" [class]=\"field.IsVirtual ? 'virtual-yes' : 'virtual-no'\">\n {{ field.IsVirtual ? 'Yes' : 'No' }}\n </span>\n </div>\n @if (field.DefaultValue) {\n <div class=\"detail-row\">\n <span class=\"detail-label\">Default Value:</span>\n <span class=\"detail-value default-value\">{{ field.DefaultValue }}</span>\n </div>\n }\n @if (field.RelatedEntityID) {\n <div class=\"detail-row\">\n <span class=\"detail-label\">Related Entity:</span>\n <span class=\"detail-value related-entity\"\n (click)=\"onRelatedEntityClick($event, field)\"\n title=\"Click to select {{ field.RelatedEntity }} in ERD\">\n {{ field.RelatedEntity }}\n <span class=\"fa-solid fa-arrow-right\"></span>\n </span>\n </div>\n }\n @if (field.AutoIncrement) {\n <div class=\"detail-row\">\n <span class=\"detail-label\">Auto Increment:</span>\n <span class=\"detail-value auto-increment\">Yes</span>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n\n <div class=\"relationships-section\" [class.section-expanded]=\"relationshipsSectionExpanded\" [class.section-collapsed]=\"!relationshipsSectionExpanded\">\n <div class=\"section-header extra-padding\">\n <div class=\"section-title-group\" (click)=\"toggleRelationshipsSection()\">\n <button\n class=\"expand-btn\"\n [class.expanded]=\"relationshipsSectionExpanded\"\n title=\"Toggle relationships section\">\n <span class=\"fa-solid fa-chevron-right\"></span>\n </button>\n <h4>Related Entities ({{ selectedEntity ? getRelatedEntities(selectedEntity.ID).length : 0 }})</h4>\n </div>\n </div>\n @if (relationshipsSectionExpanded) {\n <div class=\"related-entities-list\" #relationshipsListContainer>\n @for (relatedEntity of getRelatedEntities(selectedEntity?.ID || ''); track relatedEntity.ID) {\n <div class=\"related-entity-item\" (click)=\"selectEntity(relatedEntity, true)\">\n <span class=\"fa-solid fa-database\"></span>\n <span class=\"entity-name\">{{ relatedEntity.Name || relatedEntity.SchemaName }}</span>\n <span class=\"zoom-indicator fa-solid fa-search-plus\" title=\"Click to zoom to entity\"></span>\n </div>\n }\n </div>\n }\n </div>\n</div>\n"]}
1
+ {"version":3,"file":"entity-details.component.js","sourceRoot":"","sources":["../../../../src/lib/components/entity-details/entity-details.component.ts","../../../../src/lib/components/entity-details/entity-details.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnChanges, SimpleChanges, ViewChild, ElementRef } from '@angular/core';\nimport { EntityInfo, EntityFieldInfo, EntityFieldValueInfo } from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\n\n/**\n * Event emitted when requesting to open an entity record.\n */\nexport interface EntityDetailsOpenRecordEvent {\n EntityName: string;\n RecordID: string;\n}\n\n/**\n * Entity details panel component that displays detailed information about a selected entity.\n * Shows entity metadata, fields with filtering capabilities, and related entities.\n *\n * This component is designed to be used alongside the ERD diagram to provide\n * a detailed view of the currently selected entity.\n */\n@Component({\n standalone: false,\n selector: 'mj-entity-details',\n templateUrl: './entity-details.component.html',\n styleUrls: ['./entity-details.component.css']\n})\nexport class EntityDetailsComponent extends BaseAngularComponent implements OnChanges {\n @ViewChild('fieldsListContainer', { static: false }) fieldsListContainer!: ElementRef;\n @ViewChild('relationshipsListContainer', { static: false }) relationshipsListContainer!: ElementRef;\n\n /** The currently selected entity to display details for */\n @Input() selectedEntity: EntityInfo | null = null;\n\n /** All entity fields for looking up field information */\n @Input() allEntityFields: EntityFieldInfo[] = [];\n\n /** Whether the fields section is expanded */\n @Input() fieldsSectionExpanded = true;\n\n /** Whether the relationships section is expanded */\n @Input() relationshipsSectionExpanded = true;\n\n /** Emitted when user clicks to open the entity record */\n @Output() openEntity = new EventEmitter<EntityInfo>();\n\n /** Emitted when user clicks the close button */\n @Output() closePanel = new EventEmitter<void>();\n\n /** Emitted when fields section is toggled */\n @Output() fieldsSectionToggle = new EventEmitter<void>();\n\n /** Emitted when relationships section is toggled */\n @Output() relationshipsSectionToggle = new EventEmitter<void>();\n\n /** Emitted when a related entity is selected (clicked in relationships list) */\n @Output() entitySelected = new EventEmitter<EntityInfo>();\n\n /** Emitted when requesting to open an entity record */\n @Output() openRecord = new EventEmitter<EntityDetailsOpenRecordEvent>();\n\n public fieldFilter: 'all' | 'keys' | 'foreign_keys' | 'regular' = 'all';\n public expandedFieldDescriptions = new Set<string>();\n public expandedFieldValues = new Set<string>();\n public expandedFieldDetails = new Set<string>();\n private previousSelectedEntityId: string | null = null;\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['selectedEntity'] && !changes['selectedEntity'].firstChange) {\n const currentEntityId = this.selectedEntity?.ID || null;\n\n // Check if entity actually changed\n if (currentEntityId !== this.previousSelectedEntityId) {\n // Reset scroll positions when entity changes\n this.resetScrollPositions();\n\n this.previousSelectedEntityId = currentEntityId;\n }\n }\n }\n\n private resetScrollPositions(): void {\n // Use setTimeout to ensure the DOM is updated\n setTimeout(() => {\n if (this.fieldsListContainer?.nativeElement) {\n this.fieldsListContainer.nativeElement.scrollTop = 0;\n }\n if (this.relationshipsListContainer?.nativeElement) {\n this.relationshipsListContainer.nativeElement.scrollTop = 0;\n }\n }, 0);\n }\n\n public onOpenEntity(): void {\n if (this.selectedEntity) {\n this.openRecord.emit({\n EntityName: 'MJ: Entities',\n RecordID: this.selectedEntity.ID\n });\n }\n }\n\n public onClosePanel(): void {\n this.closePanel.emit();\n }\n\n public toggleFieldsSection(): void {\n this.fieldsSectionToggle.emit();\n }\n\n public toggleRelationshipsSection(): void {\n this.relationshipsSectionToggle.emit();\n }\n\n public setFieldFilter(filter: 'all' | 'keys' | 'foreign_keys' | 'regular'): void {\n this.fieldFilter = filter;\n }\n\n public getEntityFields(entityId: string): EntityFieldInfo[] {\n if (!entityId) return [];\n\n let fields = this.allEntityFields.filter(f => UUIDsEqual(f.EntityID, entityId));\n\n switch (this.fieldFilter) {\n case 'keys':\n return fields.filter(f => f.IsPrimaryKey || f.Name.toLowerCase().includes('id'));\n case 'foreign_keys':\n return fields.filter(f => f.RelatedEntityID && !f.IsPrimaryKey);\n case 'regular':\n return fields.filter(f => !f.IsPrimaryKey && !f.RelatedEntityID);\n default:\n return fields;\n }\n }\n\n public getRelatedEntities(entityId: string): EntityInfo[] {\n if (!entityId) return [];\n\n const relatedEntityIds = new Set<string>();\n\n // Get entities that this entity references (foreign keys)\n this.allEntityFields\n .filter(f => UUIDsEqual(f.EntityID, entityId) && f.RelatedEntityID)\n .forEach(f => relatedEntityIds.add(f.RelatedEntityID!));\n\n // Get entities that reference this entity\n this.allEntityFields\n .filter(f => UUIDsEqual(f.RelatedEntityID, entityId))\n .forEach(f => relatedEntityIds.add(f.EntityID));\n\n // Remove the current entity from the set (don't return self-references)\n relatedEntityIds.delete(entityId);\n\n // Convert to actual EntityInfo objects\n const md = this.ProviderToUse;\n const allEntities = md.Entities;\n const retVals: EntityInfo[] = [];\n relatedEntityIds.forEach(id => {\n const entity = allEntities.find(e => UUIDsEqual(e.ID, id));\n if (entity) {\n retVals.push(entity);\n }\n });\n return retVals;\n }\n\n public onFieldClick(field: EntityFieldInfo): void {\n this.toggleFieldDetails(field.ID);\n }\n\n public toggleFieldDescription(fieldId: string): void {\n if (this.expandedFieldDescriptions.has(fieldId)) {\n this.expandedFieldDescriptions.delete(fieldId);\n } else {\n this.expandedFieldDescriptions.add(fieldId);\n }\n }\n\n public toggleFieldValues(fieldId: string): void {\n if (this.expandedFieldValues.has(fieldId)) {\n this.expandedFieldValues.delete(fieldId);\n } else {\n this.expandedFieldValues.add(fieldId);\n }\n }\n\n public toggleFieldDetails(fieldId: string): void {\n if (this.expandedFieldDetails.has(fieldId)) {\n this.expandedFieldDetails.delete(fieldId);\n } else {\n this.expandedFieldDetails.add(fieldId);\n }\n }\n\n public isFieldDescriptionExpanded(fieldId: string): boolean {\n return this.expandedFieldDescriptions.has(fieldId);\n }\n\n public isFieldValuesExpanded(fieldId: string): boolean {\n return this.expandedFieldValues.has(fieldId);\n }\n\n public isFieldDetailsExpanded(fieldId: string): boolean {\n return this.expandedFieldDetails.has(fieldId);\n }\n\n public hasFieldPossibleValues(field: EntityFieldInfo): boolean {\n return field.EntityFieldValues && field.EntityFieldValues.length > 0;\n }\n\n public getFieldPossibleValues(field: EntityFieldInfo): string[] {\n if (!field.EntityFieldValues) return [];\n return field.EntityFieldValues.map(v => v.Value).slice(0, 10);\n }\n\n public getSortedEntityFieldValues(field: EntityFieldInfo): EntityFieldValueInfo[] {\n if (!field.EntityFieldValues) return [];\n return field.EntityFieldValues.sort((a, b) => {\n if (a.Sequence !== undefined && b.Sequence !== undefined) {\n return a.Sequence - b.Sequence;\n }\n return a.Value.localeCompare(b.Value);\n });\n }\n\n public onRelatedEntityClick(event: Event, field: EntityFieldInfo): void {\n event.stopPropagation();\n if (field.RelatedEntityID) {\n // Find the related entity and select it in the ERD\n const md = this.ProviderToUse;\n const relatedEntity = md.Entities.find(e => UUIDsEqual(e.ID, field.RelatedEntityID));\n if (relatedEntity) {\n this.entitySelected.emit(relatedEntity);\n }\n }\n }\n\n public selectEntity(entity: EntityInfo, _zoomTo: boolean = false): void {\n this.entitySelected.emit(entity);\n }\n}\n","<div class=\"details-panel\">\n <div class=\"panel-header\">\n <h3>{{ selectedEntity?.Name || selectedEntity?.SchemaName }}</h3>\n <div class=\"panel-actions\">\n <button class=\"open-btn\" (click)=\"onOpenEntity()\" title=\"Open Entity Record\">\n <span class=\"fa-solid fa-external-link-alt\"></span>\n Open\n </button>\n <button class=\"close-btn\" (click)=\"onClosePanel()\">\n <span class=\"fa-solid fa-times\"></span>\n </button>\n </div>\n </div>\n\n <div class=\"entity-info\">\n <div class=\"info-row\">\n <label>Schema:</label>\n <span>{{ selectedEntity?.SchemaName }}</span>\n </div>\n <div class=\"info-row\">\n <label>Table:</label>\n <span>{{ selectedEntity?.BaseTable }}</span>\n </div>\n @if (selectedEntity?.Description) {\n <div class=\"info-row\">\n <label>Description:</label>\n <span>{{ selectedEntity?.Description }}</span>\n </div>\n }\n </div>\n\n <mj-accordion-panel class=\"erd-details-accordion\" Size=\"sm\" [Fill]=\"true\" [FlushBody]=\"true\"\n [Expanded]=\"fieldsSectionExpanded\" (ExpandedChange)=\"toggleFieldsSection()\">\n <ng-template mjAccordionTitle>\n <span class=\"erd-section-title\">Fields ({{ selectedEntity ? getEntityFields(selectedEntity.ID).length : 0 }})</span>\n </ng-template>\n <ng-template mjAccordionActions>\n @if (fieldsSectionExpanded) {\n <div class=\"field-filters\">\n <button\n class=\"filter-btn\"\n [class.active]=\"fieldFilter === 'all'\"\n (click)=\"setFieldFilter('all')\"\n title=\"Show all fields\">\n All\n </button>\n <button\n class=\"filter-btn\"\n [class.active]=\"fieldFilter === 'keys'\"\n (click)=\"setFieldFilter('keys')\"\n title=\"Show primary keys and ID fields\">\n Keys\n </button>\n <button\n class=\"filter-btn\"\n [class.active]=\"fieldFilter === 'foreign_keys'\"\n (click)=\"setFieldFilter('foreign_keys')\"\n title=\"Show foreign key fields only\">\n FKs\n </button>\n <button\n class=\"filter-btn\"\n [class.active]=\"fieldFilter === 'regular'\"\n (click)=\"setFieldFilter('regular')\"\n title=\"Show regular data fields\">\n Regular\n </button>\n </div>\n }\n </ng-template>\n @if (fieldsSectionExpanded) {\n <div class=\"fields-list\" #fieldsListContainer>\n @for (field of getEntityFields(selectedEntity?.ID || ''); track field.ID) {\n <div class=\"field-item\"\n [class]=\"{\n 'primary-key-field': field.IsPrimaryKey,\n 'foreign-key-field': field.RelatedEntityID && !field.IsPrimaryKey,\n 'regular-field': !field.IsPrimaryKey && !field.RelatedEntityID,\n 'field-expanded': isFieldDetailsExpanded(field.ID)\n }\"\n (click)=\"onFieldClick(field)\"\n [title]=\"'Click to see more details about ' + field.Name\">\n <div class=\"field-header\">\n <div class=\"field-name\">\n @if (field.IsPrimaryKey) {\n <span class=\"field-icon fa-solid fa-key\" title=\"Primary Key\"></span>\n } @else if (field.RelatedEntityID) {\n <span class=\"field-icon fa-solid fa-link\" title=\"Foreign Key\"></span>\n }\n {{ field.Name }}\n </div>\n <div class=\"field-actions\">\n @if (hasFieldPossibleValues(field)) {\n <button\n class=\"field-values-btn\"\n (click)=\"toggleFieldValues(field.ID)\"\n [class.expanded]=\"isFieldValuesExpanded(field.ID)\"\n title=\"Toggle possible values\">\n <span class=\"fa-solid fa-list\"></span>\n </button>\n }\n @if (field.Description) {\n <button\n class=\"field-info-btn\"\n (click)=\"toggleFieldDescription(field.ID)\"\n [class.expanded]=\"isFieldDescriptionExpanded(field.ID)\"\n title=\"Toggle field description\">\n <span class=\"fa-solid fa-info-circle\"></span>\n </button>\n }\n <div class=\"field-badges\">\n @if (field.IsPrimaryKey) {\n <span class=\"field-badge primary-key\">PK</span>\n }\n @if (field.RelatedEntityID && !field.IsPrimaryKey) {\n <span class=\"field-badge foreign-key\">FK</span>\n }\n </div>\n </div>\n </div>\n <div class=\"field-details\">\n <div class=\"field-type\">{{ field.Type }}</div>\n @if (field.RelatedEntityID) {\n <div class=\"field-relation\">\n <span class=\"fa-solid fa-arrow-right\"></span>\n Related Entity\n </div>\n }\n </div>\n @if (field.Description && isFieldDescriptionExpanded(field.ID)) {\n <div class=\"field-description\">\n <div class=\"description-text\">{{ field.Description }}</div>\n </div>\n }\n @if (hasFieldPossibleValues(field) && isFieldValuesExpanded(field.ID)) {\n <div class=\"field-values\">\n <div class=\"values-header\">Possible Values:</div>\n <div class=\"values-list\">\n @for (value of getFieldPossibleValues(field); track value; let i = $index) {\n <span class=\"value-tag\">{{ value }}</span>\n }\n </div>\n </div>\n }\n @if (isFieldDetailsExpanded(field.ID)) {\n <div class=\"field-comprehensive-details\">\n @if (field.Description) {\n <div class=\"comprehensive-description-top\">\n <div class=\"description-content\">{{ field.Description }}</div>\n </div>\n }\n @if (field.EntityFieldValues && field.EntityFieldValues.length > 0) {\n <div class=\"field-values-comprehensive\">\n <div class=\"values-header\">\n <span class=\"fa-solid fa-list\"></span>\n Possible Values ({{ field.EntityFieldValues.length }})\n </div>\n <div class=\"values-grid\">\n @for (fieldValue of getSortedEntityFieldValues(field); track fieldValue.ID) {\n <div class=\"value-item\">\n <div class=\"value-main\">\n <span class=\"value-text\">{{ fieldValue.Value }}</span>\n @if (fieldValue.Code && fieldValue.Code !== fieldValue.Value) {\n <span class=\"value-code\">[{{ fieldValue.Code }}]</span>\n }\n </div>\n @if (fieldValue.Description && fieldValue.Description !== fieldValue.Value) {\n <div class=\"value-description\">{{ fieldValue.Description }}</div>\n }\n </div>\n }\n </div>\n </div>\n }\n <div class=\"details-grid\">\n <div class=\"detail-row\">\n <span class=\"detail-label\">Data Type:</span>\n <span class=\"detail-value\">{{ field.Type }}</span>\n </div>\n <div class=\"detail-row\">\n <span class=\"detail-label\">Nullable:</span>\n <span class=\"detail-value\" [class]=\"field.AllowsNull ? 'nullable-yes' : 'nullable-no'\">\n {{ field.AllowsNull ? 'Yes' : 'No' }}\n </span>\n </div>\n @if (field.Length && field.Length > 0) {\n <div class=\"detail-row\">\n <span class=\"detail-label\">Max Length:</span>\n <span class=\"detail-value\">{{ field.Length }}</span>\n </div>\n }\n @if (field.Precision && field.Precision > 0) {\n <div class=\"detail-row\">\n <span class=\"detail-label\">Precision:</span>\n <span class=\"detail-value\">{{ field.Precision }}</span>\n </div>\n }\n @if (field.Scale && field.Scale > 0) {\n <div class=\"detail-row\">\n <span class=\"detail-label\">Scale:</span>\n <span class=\"detail-value\">{{ field.Scale }}</span>\n </div>\n }\n <div class=\"detail-row\">\n <span class=\"detail-label\">Virtual Field:</span>\n <span class=\"detail-value\" [class]=\"field.IsVirtual ? 'virtual-yes' : 'virtual-no'\">\n {{ field.IsVirtual ? 'Yes' : 'No' }}\n </span>\n </div>\n @if (field.DefaultValue) {\n <div class=\"detail-row\">\n <span class=\"detail-label\">Default Value:</span>\n <span class=\"detail-value default-value\">{{ field.DefaultValue }}</span>\n </div>\n }\n @if (field.RelatedEntityID) {\n <div class=\"detail-row\">\n <span class=\"detail-label\">Related Entity:</span>\n <span class=\"detail-value related-entity\"\n (click)=\"onRelatedEntityClick($event, field)\"\n title=\"Click to select {{ field.RelatedEntity }} in ERD\">\n {{ field.RelatedEntity }}\n <span class=\"fa-solid fa-arrow-right\"></span>\n </span>\n </div>\n }\n @if (field.AutoIncrement) {\n <div class=\"detail-row\">\n <span class=\"detail-label\">Auto Increment:</span>\n <span class=\"detail-value auto-increment\">Yes</span>\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n </mj-accordion-panel>\n\n <mj-accordion-panel class=\"erd-details-accordion\" Size=\"sm\" [Fill]=\"true\" [FlushBody]=\"true\"\n [Expanded]=\"relationshipsSectionExpanded\" (ExpandedChange)=\"toggleRelationshipsSection()\">\n <ng-template mjAccordionTitle>\n <span class=\"erd-section-title\">Related Entities ({{ selectedEntity ? getRelatedEntities(selectedEntity.ID).length : 0 }})</span>\n </ng-template>\n @if (relationshipsSectionExpanded) {\n <div class=\"related-entities-list\" #relationshipsListContainer>\n @for (relatedEntity of getRelatedEntities(selectedEntity?.ID || ''); track relatedEntity.ID) {\n <div class=\"related-entity-item\" (click)=\"selectEntity(relatedEntity, true)\">\n <span class=\"fa-solid fa-database\"></span>\n <span class=\"entity-name\">{{ relatedEntity.Name || relatedEntity.SchemaName }}</span>\n <span class=\"zoom-indicator fa-solid fa-search-plus\" title=\"Click to zoom to entity\"></span>\n </div>\n }\n </div>\n }\n </mj-accordion-panel>\n</div>\n"]}
@@ -83,6 +83,10 @@ export declare class ERDDiagramComponent implements AfterViewInit, OnDestroy, On
83
83
  schemaChips: SchemaChip[];
84
84
  /** Derived — number of entities currently visible. */
85
85
  visibleCount: number;
86
+ /** Icon for the empty state — honours `config.emptyStateIcon` when provided. */
87
+ get emptyStateIcon(): string;
88
+ /** Title for the empty state — distinguishes "nothing here" from "filtered to nothing". */
89
+ get emptyStateTitle(): string;
86
90
  /** Derived — total entities in the input, before any filtering. */
87
91
  totalCount: number;
88
92
  /** Derived — the Set of IDs in the focus/hover neighbourhood (null when no highlight active). */
@@ -1 +1 @@
1
- {"version":3,"file":"erd-diagram.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/erd-diagram.component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"erd-diagram.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/erd-diagram.component.ts"],"names":[],"mappings":"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"}
@@ -18,6 +18,7 @@ import { Component, Input, Output, EventEmitter, ElementRef, ViewChild, HostBind
18
18
  import { computeErdLayout, pointsToPath, getNeighbors, } from '../layout/compute-erd-layout';
19
19
  import { computeDagreLayout } from '../layout/compute-dagre-layout';
20
20
  import * as i0 from "@angular/core";
21
+ import * as i1 from "@memberjunction/ng-ui-components";
21
22
  const _c0 = ["canvasRef"];
22
23
  function ERDDiagramComponent_Conditional_0_Conditional_16_Template(rf, ctx) { if (rf & 1) {
23
24
  const _r4 = i0.ɵɵgetCurrentView();
@@ -314,32 +315,15 @@ function ERDDiagramComponent_For_21_Template(rf, ctx) { if (rf & 1) {
314
315
  i0.ɵɵadvance();
315
316
  i0.ɵɵattribute("width", node_r13.width)("height", node_r13.height);
316
317
  } }
317
- function ERDDiagramComponent_Conditional_22_Conditional_5_Template(rf, ctx) { if (rf & 1) {
318
- i0.ɵɵelementStart(0, "div", 79);
319
- i0.ɵɵtext(1, "Try adjusting schema filters or clearing search");
320
- i0.ɵɵelementEnd();
321
- } }
322
318
  function ERDDiagramComponent_Conditional_22_Template(rf, ctx) { if (rf & 1) {
323
- i0.ɵɵelementStart(0, "div", 17)(1, "div", 76);
324
- i0.ɵɵelement(2, "i", 77);
325
- i0.ɵɵelementEnd();
326
- i0.ɵɵelementStart(3, "div", 78);
327
- i0.ɵɵtext(4);
328
- i0.ɵɵelementEnd();
329
- i0.ɵɵconditionalCreate(5, ERDDiagramComponent_Conditional_22_Conditional_5_Template, 2, 0, "div", 79);
330
- i0.ɵɵelementEnd();
319
+ i0.ɵɵelement(0, "mj-empty-state", 17);
331
320
  } if (rf & 2) {
332
321
  const ctx_r2 = i0.ɵɵnextContext();
333
- i0.ɵɵadvance(2);
334
- i0.ɵɵclassMap(ctx_r2.config.emptyStateIcon || "fa-solid fa-diagram-project");
335
- i0.ɵɵadvance(2);
336
- i0.ɵɵtextInterpolate1(" ", ctx_r2.totalCount === 0 ? ctx_r2.config.emptyStateMessage || "No entities to display" : "No entities match", " ");
337
- i0.ɵɵadvance();
338
- i0.ɵɵconditional(ctx_r2.totalCount > 0 ? 5 : -1);
322
+ i0.ɵɵproperty("Variant", ctx_r2.totalCount === 0 ? "empty" : "no-results")("Icon", ctx_r2.emptyStateIcon)("Title", ctx_r2.emptyStateTitle)("Message", ctx_r2.totalCount > 0 ? "Try adjusting schema filters or clearing search" : "");
339
323
  } }
340
324
  function ERDDiagramComponent_Conditional_23_Template(rf, ctx) { if (rf & 1) {
341
- i0.ɵɵelementStart(0, "div", 18)(1, "div", 80);
342
- i0.ɵɵelement(2, "i", 81);
325
+ i0.ɵɵelementStart(0, "div", 18)(1, "div", 76);
326
+ i0.ɵɵelement(2, "i", 77);
343
327
  i0.ɵɵelementStart(3, "span");
344
328
  i0.ɵɵtext(4, "Loading\u2026");
345
329
  i0.ɵɵelementEnd()()();
@@ -402,6 +386,16 @@ export class ERDDiagramComponent {
402
386
  schemaChips = [];
403
387
  /** Derived — number of entities currently visible. */
404
388
  visibleCount = 0;
389
+ /** Icon for the empty state — honours `config.emptyStateIcon` when provided. */
390
+ get emptyStateIcon() {
391
+ return this.config.emptyStateIcon || 'fa-solid fa-diagram-project';
392
+ }
393
+ /** Title for the empty state — distinguishes "nothing here" from "filtered to nothing". */
394
+ get emptyStateTitle() {
395
+ return this.totalCount === 0
396
+ ? (this.config.emptyStateMessage || 'No entities to display')
397
+ : 'No entities match';
398
+ }
405
399
  /** Derived — total entities in the input, before any filtering. */
406
400
  totalCount = 0;
407
401
  /** Derived — the Set of IDs in the focus/hover neighbourhood (null when no highlight active). */
@@ -981,7 +975,7 @@ export class ERDDiagramComponent {
981
975
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.canvasRef = _t.first);
982
976
  } }, hostVars: 2, hostBindings: function ERDDiagramComponent_HostBindings(rf, ctx) { if (rf & 2) {
983
977
  i0.ɵɵclassProp("erd-root", ctx.rootClass);
984
- } }, inputs: { nodes: "nodes", selectedNodeId: "selectedNodeId", highlightedNodeIds: "highlightedNodeIds", focusNodeId: "focusNodeId", focusDepth: "focusDepth", isRefreshing: "isRefreshing", readOnly: "readOnly", config: "config", showHeader: "showHeader", headerTitle: "headerTitle" }, outputs: { nodeClick: "nodeClick", nodeDoubleClick: "nodeDoubleClick", nodeSelected: "nodeSelected", nodeDeselected: "nodeDeselected", linkClick: "linkClick", nodeHover: "nodeHover", nodeHoverEnd: "nodeHoverEnd", linkHover: "linkHover", linkHoverEnd: "linkHoverEnd", nodeContextMenu: "nodeContextMenu", linkContextMenu: "linkContextMenu", diagramContextMenu: "diagramContextMenu", nodeDragStart: "nodeDragStart", nodeDragEnd: "nodeDragEnd", zoomChange: "zoomChange", refreshRequested: "refreshRequested", layoutComplete: "layoutComplete", stateChange: "stateChange" }, standalone: false, features: [i0.ɵɵNgOnChangesFeature], decls: 24, vars: 7, consts: [["canvasRef", ""], [1, "erd-chrome"], [1, "erd-canvas-wrap"], [1, "erd-canvas", 3, "mousedown", "wheel"], ["id", "erd-arrow", "viewBox", "0 0 10 10", "refX", "9", "refY", "5", "markerWidth", "7", "markerHeight", "7", "orient", "auto"], ["d", "M 0 0 L 10 5 L 0 10 z", 1, "erd-marker"], ["id", "erd-arrow-active", "viewBox", "0 0 10 10", "refX", "9", "refY", "5", "markerWidth", "7", "markerHeight", "7", "orient", "auto"], ["d", "M 0 0 L 10 5 L 0 10 z", 1, "erd-marker", "erd-marker-active"], ["id", "erd-many", "viewBox", "-10 -6 14 12", "refX", "-8", "refY", "0", "markerWidth", "14", "markerHeight", "14", "orient", "auto"], ["d", "M 0 -5 L -8 0 L 0 5 M -8 0 L 4 0", 1, "erd-marker-stroke"], ["id", "erd-many-active", "viewBox", "-10 -6 14 12", "refX", "-8", "refY", "0", "markerWidth", "14", "markerHeight", "14", "orient", "auto"], ["d", "M 0 -5 L -8 0 L 0 5 M -8 0 L 4 0", 1, "erd-marker-stroke", "erd-marker-active"], [1, "erd-edges"], ["fill", "none", 1, "erd-edge", 3, "erd-edge-active", "erd-edge-dimmed"], [1, "erd-edge-labels"], [1, "erd-nodes"], [1, "erd-node", 3, "erd-node-focus", "erd-node-neighbour", "erd-node-dimmed"], [1, "erd-empty"], [1, "erd-loading-overlay"], [1, "erd-title-group"], [1, "erd-title"], [1, "erd-subtitle"], [1, "erd-count-pill"], [1, "erd-count-label"], [1, "erd-dot"], [1, "erd-search"], ["aria-hidden", "true", 1, "fa-solid", "fa-magnifying-glass"], ["type", "text", "placeholder", "Search entities, schemas, fields\u2026", "spellcheck", "false", "aria-label", "Search entities", 3, "input", "value"], ["type", "button", "aria-label", "Clear search", 1, "erd-search-clear"], [1, "erd-chrome-right"], ["role", "group", "aria-label", "Filter by schema", 1, "erd-schema-chips"], ["role", "group", "aria-label", "Layout mode", 1, "erd-toolbar"], ["type", "button", "title", "Schema grid \u2014 grouped by schema, predictable", "aria-label", "Schema-grid layout", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-table-cells"], ["type", "button", "title", "Hierarchical \u2014 classic ERD, relationship-driven", "aria-label", "Hierarchical layout", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-sitemap"], ["role", "group", "aria-label", "Zoom controls", 1, "erd-toolbar"], ["type", "button", "title", "Zoom in", "aria-label", "Zoom in", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-magnifying-glass-plus"], ["type", "button", "title", "Zoom out", "aria-label", "Zoom out", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-magnifying-glass-minus"], ["type", "button", "title", "Fit to view", "aria-label", "Fit to view", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-expand"], [1, "erd-zoom-val"], ["type", "button", "aria-label", "Clear search", 1, "erd-search-clear", 3, "click"], ["type", "button", 1, "erd-chip", 3, "active"], ["type", "button", 1, "erd-chip", 3, "click"], [1, "erd-chip-label"], [1, "erd-chip-count"], [1, "erd-band"], ["rx", "16", 1, "erd-band-rect"], ["text-anchor", "middle", 1, "erd-band-title"], ["fill", "none", 1, "erd-edge"], [1, "erd-edge-label", 3, "erd-edge-label-active", "erd-edge-label-dimmed"], [1, "erd-edge-label"], ["height", "16", "rx", "3", 1, "erd-edge-label-bg"], ["text-anchor", "middle", 1, "erd-edge-label-text"], [1, "erd-node", 3, "click", "mouseenter", "mouseleave"], ["x", "0", "y", "2", "rx", "8", 1, "erd-node-shadow"], ["x", "0", "y", "0", "rx", "8", 1, "erd-node-body"], ["x", "0", "y", "0", "height", "36", "rx", "6", 1, "erd-node-header"], ["x", "14", "y", "8", "height", "22"], ["xmlns", "http://www.w3.org/1999/xhtml", 1, "erd-node-header-content"], [1, "erd-node-name", 3, "title"], [1, "erd-node-rows"], ["x1", "0", "y1", "36", "y2", "36", 1, "erd-node-separator"], ["x", "0", "height", "22"], ["x", "4", "height", "14"], ["x", "0", "y", "0", "rx", "8", 1, "erd-node-frame"], ["xmlns", "http://www.w3.org/1999/xhtml", 1, "erd-field-row"], [1, "erd-field-chip", "erd-field-chip-pk"], [1, "erd-field-chip", "erd-field-chip-fk"], [1, "erd-field-name", 3, "title"], [1, "erd-field-type", 3, "title"], ["x", "4", "height", "14", 3, "click"], ["xmlns", "http://www.w3.org/1999/xhtml", 1, "erd-field-more"], [1, "erd-empty-icon"], ["aria-hidden", "true"], [1, "erd-empty-title"], [1, "erd-empty-hint"], [1, "erd-loading-content"], ["aria-hidden", "true", 1, "fa-solid", "fa-circle-notch", "fa-spin"]], template: function ERDDiagramComponent_Template(rf, ctx) { if (rf & 1) {
978
+ } }, inputs: { nodes: "nodes", selectedNodeId: "selectedNodeId", highlightedNodeIds: "highlightedNodeIds", focusNodeId: "focusNodeId", focusDepth: "focusDepth", isRefreshing: "isRefreshing", readOnly: "readOnly", config: "config", showHeader: "showHeader", headerTitle: "headerTitle" }, outputs: { nodeClick: "nodeClick", nodeDoubleClick: "nodeDoubleClick", nodeSelected: "nodeSelected", nodeDeselected: "nodeDeselected", linkClick: "linkClick", nodeHover: "nodeHover", nodeHoverEnd: "nodeHoverEnd", linkHover: "linkHover", linkHoverEnd: "linkHoverEnd", nodeContextMenu: "nodeContextMenu", linkContextMenu: "linkContextMenu", diagramContextMenu: "diagramContextMenu", nodeDragStart: "nodeDragStart", nodeDragEnd: "nodeDragEnd", zoomChange: "zoomChange", refreshRequested: "refreshRequested", layoutComplete: "layoutComplete", stateChange: "stateChange" }, standalone: false, features: [i0.ɵɵNgOnChangesFeature], decls: 24, vars: 7, consts: [["canvasRef", ""], [1, "erd-chrome"], [1, "erd-canvas-wrap"], [1, "erd-canvas", 3, "mousedown", "wheel"], ["id", "erd-arrow", "viewBox", "0 0 10 10", "refX", "9", "refY", "5", "markerWidth", "7", "markerHeight", "7", "orient", "auto"], ["d", "M 0 0 L 10 5 L 0 10 z", 1, "erd-marker"], ["id", "erd-arrow-active", "viewBox", "0 0 10 10", "refX", "9", "refY", "5", "markerWidth", "7", "markerHeight", "7", "orient", "auto"], ["d", "M 0 0 L 10 5 L 0 10 z", 1, "erd-marker", "erd-marker-active"], ["id", "erd-many", "viewBox", "-10 -6 14 12", "refX", "-8", "refY", "0", "markerWidth", "14", "markerHeight", "14", "orient", "auto"], ["d", "M 0 -5 L -8 0 L 0 5 M -8 0 L 4 0", 1, "erd-marker-stroke"], ["id", "erd-many-active", "viewBox", "-10 -6 14 12", "refX", "-8", "refY", "0", "markerWidth", "14", "markerHeight", "14", "orient", "auto"], ["d", "M 0 -5 L -8 0 L 0 5 M -8 0 L 4 0", 1, "erd-marker-stroke", "erd-marker-active"], [1, "erd-edges"], ["fill", "none", 1, "erd-edge", 3, "erd-edge-active", "erd-edge-dimmed"], [1, "erd-edge-labels"], [1, "erd-nodes"], [1, "erd-node", 3, "erd-node-focus", "erd-node-neighbour", "erd-node-dimmed"], [1, "erd-empty", 3, "Variant", "Icon", "Title", "Message"], [1, "erd-loading-overlay"], [1, "erd-title-group"], [1, "erd-title"], [1, "erd-subtitle"], [1, "erd-count-pill"], [1, "erd-count-label"], [1, "erd-dot"], [1, "erd-search"], ["aria-hidden", "true", 1, "fa-solid", "fa-magnifying-glass"], ["type", "text", "placeholder", "Search entities, schemas, fields\u2026", "spellcheck", "false", "aria-label", "Search entities", 3, "input", "value"], ["type", "button", "aria-label", "Clear search", 1, "erd-search-clear"], [1, "erd-chrome-right"], ["role", "group", "aria-label", "Filter by schema", 1, "erd-schema-chips"], ["role", "group", "aria-label", "Layout mode", 1, "erd-toolbar"], ["type", "button", "title", "Schema grid \u2014 grouped by schema, predictable", "aria-label", "Schema-grid layout", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-table-cells"], ["type", "button", "title", "Hierarchical \u2014 classic ERD, relationship-driven", "aria-label", "Hierarchical layout", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-sitemap"], ["role", "group", "aria-label", "Zoom controls", 1, "erd-toolbar"], ["type", "button", "title", "Zoom in", "aria-label", "Zoom in", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-magnifying-glass-plus"], ["type", "button", "title", "Zoom out", "aria-label", "Zoom out", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-magnifying-glass-minus"], ["type", "button", "title", "Fit to view", "aria-label", "Fit to view", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-expand"], [1, "erd-zoom-val"], ["type", "button", "aria-label", "Clear search", 1, "erd-search-clear", 3, "click"], ["type", "button", 1, "erd-chip", 3, "active"], ["type", "button", 1, "erd-chip", 3, "click"], [1, "erd-chip-label"], [1, "erd-chip-count"], [1, "erd-band"], ["rx", "16", 1, "erd-band-rect"], ["text-anchor", "middle", 1, "erd-band-title"], ["fill", "none", 1, "erd-edge"], [1, "erd-edge-label", 3, "erd-edge-label-active", "erd-edge-label-dimmed"], [1, "erd-edge-label"], ["height", "16", "rx", "3", 1, "erd-edge-label-bg"], ["text-anchor", "middle", 1, "erd-edge-label-text"], [1, "erd-node", 3, "click", "mouseenter", "mouseleave"], ["x", "0", "y", "2", "rx", "8", 1, "erd-node-shadow"], ["x", "0", "y", "0", "rx", "8", 1, "erd-node-body"], ["x", "0", "y", "0", "height", "36", "rx", "6", 1, "erd-node-header"], ["x", "14", "y", "8", "height", "22"], ["xmlns", "http://www.w3.org/1999/xhtml", 1, "erd-node-header-content"], [1, "erd-node-name", 3, "title"], [1, "erd-node-rows"], ["x1", "0", "y1", "36", "y2", "36", 1, "erd-node-separator"], ["x", "0", "height", "22"], ["x", "4", "height", "14"], ["x", "0", "y", "0", "rx", "8", 1, "erd-node-frame"], ["xmlns", "http://www.w3.org/1999/xhtml", 1, "erd-field-row"], [1, "erd-field-chip", "erd-field-chip-pk"], [1, "erd-field-chip", "erd-field-chip-fk"], [1, "erd-field-name", 3, "title"], [1, "erd-field-type", 3, "title"], ["x", "4", "height", "14", 3, "click"], ["xmlns", "http://www.w3.org/1999/xhtml", 1, "erd-field-more"], [1, "erd-loading-content"], ["aria-hidden", "true", 1, "fa-solid", "fa-circle-notch", "fa-spin"]], template: function ERDDiagramComponent_Template(rf, ctx) { if (rf & 1) {
985
979
  const _r1 = i0.ɵɵgetCurrentView();
986
980
  i0.ɵɵconditionalCreate(0, ERDDiagramComponent_Conditional_0_Template, 33, 12, "header", 1);
987
981
  i0.ɵɵelementStart(1, "div", 2);
@@ -1009,7 +1003,7 @@ export class ERDDiagramComponent {
1009
1003
  i0.ɵɵelementStart(19, "g", 15);
1010
1004
  i0.ɵɵrepeaterCreate(20, ERDDiagramComponent_For_21_Template, 14, 20, ":svg:g", 16, ctx.trackByNode, true);
1011
1005
  i0.ɵɵelementEnd()()();
1012
- i0.ɵɵconditionalCreate(22, ERDDiagramComponent_Conditional_22_Template, 6, 4, "div", 17);
1006
+ i0.ɵɵconditionalCreate(22, ERDDiagramComponent_Conditional_22_Template, 1, 4, "mj-empty-state", 17);
1013
1007
  i0.ɵɵconditionalCreate(23, ERDDiagramComponent_Conditional_23_Template, 5, 0, "div", 18);
1014
1008
  i0.ɵɵelementEnd();
1015
1009
  } if (rf & 2) {
@@ -1030,11 +1024,11 @@ export class ERDDiagramComponent {
1030
1024
  i0.ɵɵconditional(ctx.visibleCount === 0 ? 22 : -1);
1031
1025
  i0.ɵɵadvance();
1032
1026
  i0.ɵɵconditional(ctx.isRefreshing ? 23 : -1);
1033
- } }, styles: ["\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n[_nghost-%COMP%] {\n display: flex !important;\n flex-direction: column !important;\n height: 100%;\n width: 100%;\n overflow: hidden;\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n --erd-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, \"Liberation Mono\", monospace;\n}\n\n\n\n\n.erd-chrome[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 24px;\n padding: 14px 24px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n flex-shrink: 0;\n min-height: 64px;\n}\n\n.erd-title-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n flex-shrink: 0;\n}\n\n.erd-title[_ngcontent-%COMP%] {\n font-size: 15px;\n font-weight: 600;\n letter-spacing: -0.01em;\n color: var(--mj-text-primary);\n}\n\n.erd-subtitle[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.erd-count-pill[_ngcontent-%COMP%] {\n font-family: var(--erd-mono);\n font-size: 11px;\n font-weight: 600;\n padding: 2px 8px;\n border-radius: 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n color: var(--mj-brand-primary);\n line-height: 1.3;\n}\n\n.erd-count-label[_ngcontent-%COMP%] { color: var(--mj-text-secondary); }\n.erd-dot[_ngcontent-%COMP%] { color: var(--mj-text-muted); }\n\n.erd-search[_ngcontent-%COMP%] {\n flex: 1;\n max-width: 440px;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface-card);\n transition: border-color .12s, background .12s, box-shadow .12s;\n}\n\n.erd-search[_ngcontent-%COMP%]:focus-within {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.erd-search[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n flex-shrink: 0;\n font-size: 13px;\n}\n\n.erd-search[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n flex: 1;\n border: 0;\n outline: 0;\n background: transparent;\n font: inherit;\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n.erd-search[_ngcontent-%COMP%] input[_ngcontent-%COMP%]::placeholder { color: var(--mj-text-muted); }\n\n.erd-search-clear[_ngcontent-%COMP%] {\n border: 0;\n background: transparent;\n color: var(--mj-text-muted);\n font-size: 18px;\n line-height: 1;\n cursor: pointer;\n padding: 0 4px;\n}\n\n.erd-search-clear[_ngcontent-%COMP%]:hover { color: var(--mj-text-primary); }\n\n.erd-chrome-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n margin-left: auto;\n}\n\n\n\n.erd-schema-chips[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n padding: 3px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n}\n\n.erd-chip[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 5px 10px;\n border: 0;\n background: transparent;\n border-radius: 7px;\n font-family: var(--erd-mono);\n font-size: 11px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: background .1s, color .1s;\n}\n\n.erd-chip[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.erd-chip.active[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);\n}\n\n.erd-chip-count[_ngcontent-%COMP%] {\n font-size: 10px;\n padding: 1px 5px;\n border-radius: 6px;\n background: color-mix(in srgb, var(--mj-bg-surface-card) 80%, transparent);\n color: var(--mj-text-muted);\n}\n\n\n\n.erd-toolbar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 3px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n}\n\n.erd-toolbar[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n border: 0;\n background: transparent;\n border-radius: 5px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n transition: background .1s, color .1s;\n}\n\n.erd-toolbar[_ngcontent-%COMP%] button[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.erd-toolbar[_ngcontent-%COMP%] button.active[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.erd-zoom-val[_ngcontent-%COMP%] {\n padding: 0 8px;\n font-family: var(--erd-mono);\n font-size: 10px;\n color: var(--mj-text-secondary);\n min-width: 42px;\n text-align: right;\n}\n\n\n\n\n.erd-canvas-wrap[_ngcontent-%COMP%] {\n flex: 1;\n position: relative;\n overflow: hidden;\n background: var(--mj-bg-surface-sunken);\n min-height: 300px;\n}\n\n.erd-canvas[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n user-select: none;\n cursor: grab;\n display: block;\n}\n\n.erd-canvas[data-panning=\"true\"][_ngcontent-%COMP%] { cursor: grabbing; }\n\n.erd-canvas[_ngcontent-%COMP%] text[_ngcontent-%COMP%] { pointer-events: none; }\n\n\n\n.erd-band-rect[_ngcontent-%COMP%] {\n fill: color-mix(in srgb, var(--mj-text-primary) 4%, transparent);\n stroke: var(--mj-border-default);\n stroke-width: 1;\n}\n\n.erd-band-title[_ngcontent-%COMP%] {\n font-family: var(--erd-mono);\n font-size: 13px;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n fill: var(--mj-text-muted);\n}\n\n\n\n.erd-edge[_ngcontent-%COMP%] {\n stroke: var(--mj-border-strong);\n stroke-width: 1.2;\n transition: stroke-width .15s, opacity .15s;\n}\n\n.erd-edge-active[_ngcontent-%COMP%] {\n stroke: var(--mj-brand-primary);\n stroke-width: 1.8;\n}\n\n.erd-edge-dimmed[_ngcontent-%COMP%] { opacity: 0.18; }\n\n\n\n\n.erd-edge-label[_ngcontent-%COMP%] {\n pointer-events: none;\n transition: opacity .15s;\n}\n\n.erd-edge-label-bg[_ngcontent-%COMP%] {\n fill: var(--mj-bg-surface);\n stroke: var(--mj-border-default);\n stroke-width: 0.75;\n}\n\n.erd-edge-label-text[_ngcontent-%COMP%] {\n font-family: var(--erd-mono);\n font-size: 11px;\n fill: var(--mj-text-secondary);\n}\n\n.erd-edge-label-active[_ngcontent-%COMP%] .erd-edge-label-bg[_ngcontent-%COMP%] {\n stroke: var(--mj-brand-primary);\n}\n\n.erd-edge-label-active[_ngcontent-%COMP%] .erd-edge-label-text[_ngcontent-%COMP%] {\n fill: var(--mj-brand-primary);\n}\n\n.erd-edge-label-dimmed[_ngcontent-%COMP%] { opacity: 0.18; }\n\n\n\n.erd-marker[_ngcontent-%COMP%] { fill: var(--mj-border-strong); }\n.erd-marker-active[_ngcontent-%COMP%], \n.erd-marker-active.erd-marker[_ngcontent-%COMP%], \n.erd-marker-active.erd-marker-stroke[_ngcontent-%COMP%] { fill: var(--mj-brand-primary); stroke: var(--mj-brand-primary); }\n.erd-marker-stroke[_ngcontent-%COMP%] { stroke: var(--mj-border-strong); stroke-width: 1.4; fill: none; stroke-linecap: round; }\n\n\n\n.erd-node[_ngcontent-%COMP%] {\n cursor: pointer;\n transition: opacity .15s;\n}\n\n.erd-node-dimmed[_ngcontent-%COMP%] { opacity: 0.22; }\n\n.erd-node-shadow[_ngcontent-%COMP%] {\n fill: color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n}\n\n.erd-node-body[_ngcontent-%COMP%] {\n fill: var(--mj-bg-surface);\n}\n\n\n\n\n\n.erd-node-frame[_ngcontent-%COMP%] {\n fill: none;\n stroke: var(--mj-border-default);\n stroke-width: 1;\n pointer-events: none;\n}\n\n.erd-node-focus[_ngcontent-%COMP%] .erd-node-frame[_ngcontent-%COMP%] {\n stroke: var(--mj-brand-primary);\n stroke-width: 2;\n}\n\n.erd-node-neighbour[_ngcontent-%COMP%] .erd-node-frame[_ngcontent-%COMP%] {\n stroke-width: 1.5;\n}\n\n.erd-node-header[_ngcontent-%COMP%] {\n fill: var(--mj-bg-surface-card);\n}\n\n.erd-node-separator[_ngcontent-%COMP%] {\n stroke: var(--mj-border-default);\n stroke-width: 1;\n}\n\n\n\n.erd-node-header-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-family: var(--erd-mono);\n line-height: 22px;\n height: 22px;\n color: var(--mj-text-primary);\n}\n\n.erd-node-name[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n flex: 1;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.erd-node-rows[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-muted);\n flex-shrink: 0;\n}\n\n\n\n.erd-field-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n height: 22px;\n padding: 0 12px 0 8px;\n font-family: var(--erd-mono);\n line-height: 22px;\n box-sizing: border-box;\n}\n\n.erd-field-chip[_ngcontent-%COMP%] {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 14px;\n border-radius: 3px;\n font-size: 8px;\n font-weight: 700;\n letter-spacing: 0.05em;\n line-height: 1;\n}\n\n.erd-field-chip-pk[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 20%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text, var(--mj-status-warning));\n}\n\n.erd-field-chip-fk[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 18%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.erd-field-name[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n font-size: 11px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.erd-field-type[_ngcontent-%COMP%] {\n flex-shrink: 0;\n font-size: 10px;\n color: var(--mj-text-muted);\n \n\n max-width: 45%;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n\n\n.erd-field-more[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 14px;\n border-radius: 3px;\n background: var(--mj-bg-surface-card);\n opacity: 0.7;\n font-family: inherit;\n font-size: 9px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: opacity .1s;\n}\n\n.erd-field-more[_ngcontent-%COMP%]:hover { opacity: 1; }\n\n\n\n\n.erd-empty[_ngcontent-%COMP%] {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n pointer-events: none;\n}\n\n.erd-empty-icon[_ngcontent-%COMP%] {\n font-size: 40px;\n color: var(--mj-text-muted);\n opacity: 0.45;\n}\n\n.erd-empty-title[_ngcontent-%COMP%] {\n font-size: 15px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.erd-empty-hint[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.erd-loading-overlay[_ngcontent-%COMP%] {\n position: absolute;\n inset: 0;\n background: color-mix(in srgb, var(--mj-bg-page) 90%, transparent);\n backdrop-filter: blur(2px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 100;\n}\n\n.erd-loading-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n color: var(--mj-text-secondary);\n font-size: 13px;\n}\n\n.erd-loading-content[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 20px;\n}"], changeDetection: 0 });
1027
+ } }, dependencies: [i1.MJEmptyStateComponent], styles: ["\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n[_nghost-%COMP%] {\n display: flex !important;\n flex-direction: column !important;\n height: 100%;\n width: 100%;\n overflow: hidden;\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n --erd-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, \"Liberation Mono\", monospace;\n}\n\n\n\n\n.erd-chrome[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 24px;\n padding: 14px 24px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n flex-shrink: 0;\n min-height: 64px;\n}\n\n.erd-title-group[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n flex-shrink: 0;\n}\n\n.erd-title[_ngcontent-%COMP%] {\n font-size: 15px;\n font-weight: 600;\n letter-spacing: -0.01em;\n color: var(--mj-text-primary);\n}\n\n.erd-subtitle[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.erd-count-pill[_ngcontent-%COMP%] {\n font-family: var(--erd-mono);\n font-size: 11px;\n font-weight: 600;\n padding: 2px 8px;\n border-radius: 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n color: var(--mj-brand-primary);\n line-height: 1.3;\n}\n\n.erd-count-label[_ngcontent-%COMP%] { color: var(--mj-text-secondary); }\n.erd-dot[_ngcontent-%COMP%] { color: var(--mj-text-muted); }\n\n.erd-search[_ngcontent-%COMP%] {\n flex: 1;\n max-width: 440px;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface-card);\n transition: border-color .12s, background .12s, box-shadow .12s;\n}\n\n.erd-search[_ngcontent-%COMP%]:focus-within {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.erd-search[_ngcontent-%COMP%] > i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n flex-shrink: 0;\n font-size: 13px;\n}\n\n.erd-search[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n flex: 1;\n border: 0;\n outline: 0;\n background: transparent;\n font: inherit;\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n.erd-search[_ngcontent-%COMP%] input[_ngcontent-%COMP%]::placeholder { color: var(--mj-text-muted); }\n\n.erd-search-clear[_ngcontent-%COMP%] {\n border: 0;\n background: transparent;\n color: var(--mj-text-muted);\n font-size: 18px;\n line-height: 1;\n cursor: pointer;\n padding: 0 4px;\n}\n\n.erd-search-clear[_ngcontent-%COMP%]:hover { color: var(--mj-text-primary); }\n\n.erd-chrome-right[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 16px;\n margin-left: auto;\n}\n\n\n\n.erd-schema-chips[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n padding: 3px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n}\n\n.erd-chip[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 5px 10px;\n border: 0;\n background: transparent;\n border-radius: 7px;\n font-family: var(--erd-mono);\n font-size: 11px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: background .1s, color .1s;\n}\n\n.erd-chip[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.erd-chip.active[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);\n}\n\n.erd-chip-count[_ngcontent-%COMP%] {\n font-size: 10px;\n padding: 1px 5px;\n border-radius: 6px;\n background: color-mix(in srgb, var(--mj-bg-surface-card) 80%, transparent);\n color: var(--mj-text-muted);\n}\n\n\n\n.erd-toolbar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 3px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n}\n\n.erd-toolbar[_ngcontent-%COMP%] button[_ngcontent-%COMP%] {\n width: 28px;\n height: 28px;\n border: 0;\n background: transparent;\n border-radius: 5px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n transition: background .1s, color .1s;\n}\n\n.erd-toolbar[_ngcontent-%COMP%] button[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.erd-toolbar[_ngcontent-%COMP%] button.active[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.erd-zoom-val[_ngcontent-%COMP%] {\n padding: 0 8px;\n font-family: var(--erd-mono);\n font-size: 10px;\n color: var(--mj-text-secondary);\n min-width: 42px;\n text-align: right;\n}\n\n\n\n\n.erd-canvas-wrap[_ngcontent-%COMP%] {\n flex: 1;\n position: relative;\n overflow: hidden;\n background: var(--mj-bg-surface-sunken);\n min-height: 300px;\n}\n\n.erd-canvas[_ngcontent-%COMP%] {\n width: 100%;\n height: 100%;\n user-select: none;\n cursor: grab;\n display: block;\n}\n\n.erd-canvas[data-panning=\"true\"][_ngcontent-%COMP%] { cursor: grabbing; }\n\n.erd-canvas[_ngcontent-%COMP%] text[_ngcontent-%COMP%] { pointer-events: none; }\n\n\n\n.erd-band-rect[_ngcontent-%COMP%] {\n fill: color-mix(in srgb, var(--mj-text-primary) 4%, transparent);\n stroke: var(--mj-border-default);\n stroke-width: 1;\n}\n\n.erd-band-title[_ngcontent-%COMP%] {\n font-family: var(--erd-mono);\n font-size: 13px;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n fill: var(--mj-text-muted);\n}\n\n\n\n.erd-edge[_ngcontent-%COMP%] {\n stroke: var(--mj-border-strong);\n stroke-width: 1.2;\n transition: stroke-width .15s, opacity .15s;\n}\n\n.erd-edge-active[_ngcontent-%COMP%] {\n stroke: var(--mj-brand-primary);\n stroke-width: 1.8;\n}\n\n.erd-edge-dimmed[_ngcontent-%COMP%] { opacity: 0.18; }\n\n\n\n\n.erd-edge-label[_ngcontent-%COMP%] {\n pointer-events: none;\n transition: opacity .15s;\n}\n\n.erd-edge-label-bg[_ngcontent-%COMP%] {\n fill: var(--mj-bg-surface);\n stroke: var(--mj-border-default);\n stroke-width: 0.75;\n}\n\n.erd-edge-label-text[_ngcontent-%COMP%] {\n font-family: var(--erd-mono);\n font-size: 11px;\n fill: var(--mj-text-secondary);\n}\n\n.erd-edge-label-active[_ngcontent-%COMP%] .erd-edge-label-bg[_ngcontent-%COMP%] {\n stroke: var(--mj-brand-primary);\n}\n\n.erd-edge-label-active[_ngcontent-%COMP%] .erd-edge-label-text[_ngcontent-%COMP%] {\n fill: var(--mj-brand-primary);\n}\n\n.erd-edge-label-dimmed[_ngcontent-%COMP%] { opacity: 0.18; }\n\n\n\n.erd-marker[_ngcontent-%COMP%] { fill: var(--mj-border-strong); }\n.erd-marker-active[_ngcontent-%COMP%], \n.erd-marker-active.erd-marker[_ngcontent-%COMP%], \n.erd-marker-active.erd-marker-stroke[_ngcontent-%COMP%] { fill: var(--mj-brand-primary); stroke: var(--mj-brand-primary); }\n.erd-marker-stroke[_ngcontent-%COMP%] { stroke: var(--mj-border-strong); stroke-width: 1.4; fill: none; stroke-linecap: round; }\n\n\n\n.erd-node[_ngcontent-%COMP%] {\n cursor: pointer;\n transition: opacity .15s;\n}\n\n.erd-node-dimmed[_ngcontent-%COMP%] { opacity: 0.22; }\n\n.erd-node-shadow[_ngcontent-%COMP%] {\n fill: color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n}\n\n.erd-node-body[_ngcontent-%COMP%] {\n fill: var(--mj-bg-surface);\n}\n\n\n\n\n\n.erd-node-frame[_ngcontent-%COMP%] {\n fill: none;\n stroke: var(--mj-border-default);\n stroke-width: 1;\n pointer-events: none;\n}\n\n.erd-node-focus[_ngcontent-%COMP%] .erd-node-frame[_ngcontent-%COMP%] {\n stroke: var(--mj-brand-primary);\n stroke-width: 2;\n}\n\n.erd-node-neighbour[_ngcontent-%COMP%] .erd-node-frame[_ngcontent-%COMP%] {\n stroke-width: 1.5;\n}\n\n.erd-node-header[_ngcontent-%COMP%] {\n fill: var(--mj-bg-surface-card);\n}\n\n.erd-node-separator[_ngcontent-%COMP%] {\n stroke: var(--mj-border-default);\n stroke-width: 1;\n}\n\n\n\n.erd-node-header-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n font-family: var(--erd-mono);\n line-height: 22px;\n height: 22px;\n color: var(--mj-text-primary);\n}\n\n.erd-node-name[_ngcontent-%COMP%] {\n font-size: 13px;\n font-weight: 600;\n flex: 1;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.erd-node-rows[_ngcontent-%COMP%] {\n font-size: 10px;\n color: var(--mj-text-muted);\n flex-shrink: 0;\n}\n\n\n\n.erd-field-row[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n height: 22px;\n padding: 0 12px 0 8px;\n font-family: var(--erd-mono);\n line-height: 22px;\n box-sizing: border-box;\n}\n\n.erd-field-chip[_ngcontent-%COMP%] {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 14px;\n border-radius: 3px;\n font-size: 8px;\n font-weight: 700;\n letter-spacing: 0.05em;\n line-height: 1;\n}\n\n.erd-field-chip-pk[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 20%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text, var(--mj-status-warning));\n}\n\n.erd-field-chip-fk[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 18%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.erd-field-name[_ngcontent-%COMP%] {\n flex: 1;\n min-width: 0;\n font-size: 11px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.erd-field-type[_ngcontent-%COMP%] {\n flex-shrink: 0;\n font-size: 10px;\n color: var(--mj-text-muted);\n \n\n max-width: 45%;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n\n\n.erd-field-more[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 14px;\n border-radius: 3px;\n background: var(--mj-bg-surface-card);\n opacity: 0.7;\n font-family: inherit;\n font-size: 9px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: opacity .1s;\n}\n\n.erd-field-more[_ngcontent-%COMP%]:hover { opacity: 1; }\n\n\n\n\n\n\n.erd-empty[_ngcontent-%COMP%] {\n position: absolute;\n inset: 0;\n pointer-events: none;\n}\n\n.erd-loading-overlay[_ngcontent-%COMP%] {\n position: absolute;\n inset: 0;\n background: color-mix(in srgb, var(--mj-bg-page) 90%, transparent);\n backdrop-filter: blur(2px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 100;\n}\n\n.erd-loading-content[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 10px;\n color: var(--mj-text-secondary);\n font-size: 13px;\n}\n\n.erd-loading-content[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n font-size: 20px;\n}"], changeDetection: 0 });
1034
1028
  }
1035
1029
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ERDDiagramComponent, [{
1036
1030
  type: Component,
1037
- args: [{ standalone: false, selector: 'mj-erd-diagram', changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- \u2500\u2500 CHROME \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n@if (showHeader) {\n <header class=\"erd-chrome\">\n <div class=\"erd-title-group\">\n <div class=\"erd-title\">{{ headerTitle }}</div>\n <div class=\"erd-subtitle\">\n <span class=\"erd-count-pill\">{{ visibleCount }}</span>\n <span class=\"erd-count-label\">of {{ totalCount }} entities</span>\n <span class=\"erd-dot\">\u00B7</span>\n <span>{{ layout.edges.length }} relationships</span>\n </div>\n </div>\n\n <label class=\"erd-search\">\n <i class=\"fa-solid fa-magnifying-glass\" aria-hidden=\"true\"></i>\n <input\n type=\"text\"\n [value]=\"searchQuery\"\n (input)=\"onSearchChange($any($event.target).value)\"\n placeholder=\"Search entities, schemas, fields\u2026\"\n spellcheck=\"false\"\n aria-label=\"Search entities\" />\n @if (searchQuery) {\n <button type=\"button\" class=\"erd-search-clear\" (click)=\"onClearSearch()\" aria-label=\"Clear search\">\u00D7</button>\n }\n </label>\n\n <div class=\"erd-chrome-right\">\n @if (schemaChips.length > 1) {\n <div class=\"erd-schema-chips\" role=\"group\" aria-label=\"Filter by schema\">\n @for (chip of schemaChips; track trackByChip($index, chip)) {\n <button\n type=\"button\"\n class=\"erd-chip\"\n [class.active]=\"chip.active\"\n (click)=\"onSchemaChipToggle(chip.name)\"\n [attr.aria-pressed]=\"chip.active\">\n <span class=\"erd-chip-label\">{{ chip.name }}</span>\n <span class=\"erd-chip-count\">{{ chip.count }}</span>\n </button>\n }\n </div>\n }\n\n <div class=\"erd-toolbar\" role=\"group\" aria-label=\"Layout mode\">\n <button\n type=\"button\"\n [class.active]=\"activeLayout === 'schema-grid'\"\n (click)=\"setLayoutAlgorithm('schema-grid')\"\n title=\"Schema grid \u2014 grouped by schema, predictable\"\n aria-label=\"Schema-grid layout\">\n <i class=\"fa-solid fa-table-cells\" aria-hidden=\"true\"></i>\n </button>\n <button\n type=\"button\"\n [class.active]=\"activeLayout === 'dagre'\"\n (click)=\"setLayoutAlgorithm('dagre')\"\n title=\"Hierarchical \u2014 classic ERD, relationship-driven\"\n aria-label=\"Hierarchical layout\">\n <i class=\"fa-solid fa-sitemap\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n <div class=\"erd-toolbar\" role=\"group\" aria-label=\"Zoom controls\">\n <button type=\"button\" (click)=\"zoomBy(1.2)\" title=\"Zoom in\" aria-label=\"Zoom in\">\n <i class=\"fa-solid fa-magnifying-glass-plus\" aria-hidden=\"true\"></i>\n </button>\n <button type=\"button\" (click)=\"zoomBy(0.83)\" title=\"Zoom out\" aria-label=\"Zoom out\">\n <i class=\"fa-solid fa-magnifying-glass-minus\" aria-hidden=\"true\"></i>\n </button>\n <button type=\"button\" (click)=\"fitToView()\" title=\"Fit to view\" aria-label=\"Fit to view\">\n <i class=\"fa-solid fa-expand\" aria-hidden=\"true\"></i>\n </button>\n <span class=\"erd-zoom-val\">{{ zoomPercent }}</span>\n </div>\n </div>\n </header>\n}\n\n<!-- \u2500\u2500 CANVAS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n<!-- Pan handling is window-level once mousedown fires (see component) so\n dragging continues even if the cursor leaves the canvas-wrap. -->\n<div class=\"erd-canvas-wrap\">\n\n <svg\n #canvasRef\n class=\"erd-canvas\"\n [attr.data-panning]=\"panning ? 'true' : null\"\n (mousedown)=\"onBackgroundMouseDown($event)\"\n (wheel)=\"onWheel($event)\">\n\n <defs>\n <marker id=\"erd-arrow\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto\">\n <path d=\"M 0 0 L 10 5 L 0 10 z\" class=\"erd-marker\" />\n </marker>\n <marker id=\"erd-arrow-active\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto\">\n <path d=\"M 0 0 L 10 5 L 0 10 z\" class=\"erd-marker erd-marker-active\" />\n </marker>\n <marker id=\"erd-many\" viewBox=\"-10 -6 14 12\" refX=\"-8\" refY=\"0\" markerWidth=\"14\" markerHeight=\"14\" orient=\"auto\">\n <path d=\"M 0 -5 L -8 0 L 0 5 M -8 0 L 4 0\" class=\"erd-marker-stroke\" />\n </marker>\n <marker id=\"erd-many-active\" viewBox=\"-10 -6 14 12\" refX=\"-8\" refY=\"0\" markerWidth=\"14\" markerHeight=\"14\" orient=\"auto\">\n <path d=\"M 0 -5 L -8 0 L 0 5 M -8 0 L 4 0\" class=\"erd-marker-stroke erd-marker-active\" />\n </marker>\n </defs>\n\n <g [attr.transform]=\"'translate(' + transform.x + ' ' + transform.y + ') scale(' + transform.k + ')'\">\n\n <!-- Schema bands -->\n @if ((config.showSchemaBands ?? true)) {\n @for (band of layout.bands; track trackByBand($index, band)) {\n <g class=\"erd-band\">\n <rect\n [attr.x]=\"band.x\" [attr.y]=\"band.y\"\n [attr.width]=\"band.width\" [attr.height]=\"band.height\"\n rx=\"16\"\n class=\"erd-band-rect\" />\n <text\n [attr.x]=\"band.x + band.width / 2\"\n [attr.y]=\"band.y + 32\"\n text-anchor=\"middle\"\n class=\"erd-band-title\">\n {{ band.schemaName }}\n </text>\n </g>\n }\n }\n\n <!-- Edges -->\n <g class=\"erd-edges\">\n @for (edge of layout.edges; track trackByEdge($index, edge)) {\n <path\n [attr.d]=\"edgePath(edge)\"\n fill=\"none\"\n class=\"erd-edge\"\n [class.erd-edge-active]=\"isEdgeActive(edge)\"\n [class.erd-edge-dimmed]=\"isEdgeDimmed(edge)\"\n [attr.marker-start]=\"(config.crowsFoot ?? true) ? (isEdgeActive(edge) ? 'url(#erd-many-active)' : 'url(#erd-many)') : null\"\n [attr.marker-end]=\"isEdgeActive(edge) ? 'url(#erd-arrow-active)' : 'url(#erd-arrow)'\" />\n }\n </g>\n\n <!-- Edge labels \u2014 FK field names rendered along edges. Only shown\n when zoom is high enough for the text to be legible, and only\n when config.showRelationshipLabels resolves true. -->\n @if (showEdgeLabels) {\n <g class=\"erd-edge-labels\">\n @for (edge of layout.edges; track trackByEdge($index, edge)) {\n @let pos = edgeLabelPosition(edge);\n @if (pos) {\n <g\n class=\"erd-edge-label\"\n [class.erd-edge-label-active]=\"isEdgeActive(edge)\"\n [class.erd-edge-label-dimmed]=\"isEdgeDimmed(edge)\">\n <rect\n [attr.x]=\"pos.x - pos.w / 2 - 4\"\n [attr.y]=\"pos.y - 8\"\n [attr.width]=\"pos.w + 8\"\n height=\"16\"\n rx=\"3\"\n class=\"erd-edge-label-bg\" />\n <text\n [attr.x]=\"pos.x\"\n [attr.y]=\"pos.y + 4\"\n text-anchor=\"middle\"\n class=\"erd-edge-label-text\">{{ edge.sourceField.name }}</text>\n </g>\n }\n }\n </g>\n }\n\n <!-- Nodes -->\n <g class=\"erd-nodes\">\n @for (node of layout.nodes; track trackByNode($index, node)) {\n <g\n class=\"erd-node\"\n [attr.transform]=\"'translate(' + node.x + ' ' + node.y + ')'\"\n [class.erd-node-focus]=\"isFocus(node.id)\"\n [class.erd-node-neighbour]=\"isNeighbour(node.id)\"\n [class.erd-node-dimmed]=\"isDimmed(node.id)\"\n (click)=\"onNodeClick(node, $event)\"\n (mouseenter)=\"onNodeMouseEnter(node, $event)\"\n (mouseleave)=\"onNodeMouseLeave(node)\">\n\n <!-- Card shadow -->\n <rect class=\"erd-node-shadow\"\n [attr.width]=\"node.width\" [attr.height]=\"node.height\"\n x=\"0\" y=\"2\" rx=\"8\" />\n\n <!-- Card body -->\n <rect class=\"erd-node-body\"\n [attr.width]=\"node.width\" [attr.height]=\"node.height\"\n x=\"0\" y=\"0\" rx=\"8\" />\n\n <!-- Header -->\n <rect class=\"erd-node-header\"\n x=\"0\" y=\"0\"\n [attr.width]=\"node.width\" height=\"36\"\n rx=\"6\" />\n <foreignObject x=\"14\" y=\"8\" [attr.width]=\"node.width - 28\" height=\"22\">\n <div xmlns=\"http://www.w3.org/1999/xhtml\" class=\"erd-node-header-content\">\n <span class=\"erd-node-name\" [title]=\"node.name\">{{ node.name }}</span>\n @if (node.customData && $any(node.customData).rows != null) {\n <span class=\"erd-node-rows\">{{ formatCount($any(node.customData).rows) }}</span>\n }\n </div>\n </foreignObject>\n\n <!-- Separator -->\n <line class=\"erd-node-separator\"\n x1=\"0\" [attr.x2]=\"node.width\" y1=\"36\" y2=\"36\" />\n\n <!-- Fields -->\n @for (field of node.visibleFields; track trackByField($index, field); let i = $index) {\n <foreignObject x=\"0\" [attr.y]=\"36 + i * 22\" [attr.width]=\"node.width\" height=\"22\">\n <div xmlns=\"http://www.w3.org/1999/xhtml\"\n class=\"erd-field-row\"\n [class.erd-field-pk]=\"field.isPrimaryKey\"\n [class.erd-field-fk]=\"!field.isPrimaryKey && field.relatedNodeId\">\n @if (field.isPrimaryKey) {\n <span class=\"erd-field-chip erd-field-chip-pk\">PK</span>\n } @else if (field.relatedNodeId) {\n <span class=\"erd-field-chip erd-field-chip-fk\">FK</span>\n }\n <span class=\"erd-field-name\" [title]=\"field.name\">{{ field.name }}</span>\n @if (field.type) {\n <span class=\"erd-field-type\" [title]=\"field.type\">{{ field.type }}</span>\n }\n </div>\n </foreignObject>\n }\n\n <!-- +N more toggle -->\n @if (node.hasMore) {\n <foreignObject\n x=\"4\"\n [attr.y]=\"36 + node.visibleFields.length * 22 + 6\"\n [attr.width]=\"node.width - 8\"\n height=\"14\"\n (click)=\"onToggleExpand(node.id, $event)\">\n <div xmlns=\"http://www.w3.org/1999/xhtml\" class=\"erd-field-more\">\n + {{ node.fields.length - node.visibleFields.length }} more fields\n </div>\n </foreignObject>\n }\n\n <!-- Outline frame \u2014 drawn last so the focus/neighbour stroke\n sits above the header instead of being clipped by it. -->\n <rect class=\"erd-node-frame\"\n [attr.width]=\"node.width\" [attr.height]=\"node.height\"\n x=\"0\" y=\"0\" rx=\"8\" />\n </g>\n }\n </g>\n </g>\n </svg>\n\n <!-- Focus details are rendered by the consumer's side panel\n (mj-entity-details inside mj-erd-composite); the in-canvas\n floating focus card was removed as it duplicated that content. -->\n\n <!-- \u2500\u2500 Empty state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (visibleCount === 0) {\n <div class=\"erd-empty\">\n <div class=\"erd-empty-icon\">\n <i [class]=\"config.emptyStateIcon || 'fa-solid fa-diagram-project'\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"erd-empty-title\">\n {{ totalCount === 0 ? (config.emptyStateMessage || 'No entities to display') : 'No entities match' }}\n </div>\n @if (totalCount > 0) {\n <div class=\"erd-empty-hint\">Try adjusting schema filters or clearing search</div>\n }\n </div>\n }\n\n <!-- \u2500\u2500 Loading overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (isRefreshing) {\n <div class=\"erd-loading-overlay\">\n <div class=\"erd-loading-content\">\n <i class=\"fa-solid fa-circle-notch fa-spin\" aria-hidden=\"true\"></i>\n <span>Loading\u2026</span>\n </div>\n </div>\n }\n</div>\n", styles: ["/**\n * ERD Diagram Component \u2014 MJ Design Tokens.\n *\n * Uses MJ semantic tokens for all colors so the diagram adapts automatically\n * to light/dark mode via the app's global theme. Per-schema accent colors\n * are OKLCH computed from a hash of the schema name (categorical chart\n * colors, one of the few intentional exceptions to the token rule).\n *\n * Typography: MJ's default UI font inherits; entity/field names use a\n * platform monospace stack so they read as technical identifiers.\n */\n\n/* !important on display + direction keeps consumer classes (e.g. a host\n `.something { display: block }`) from collapsing the flex layout \u2014 without\n this the chrome + canvas-wrap stop being flex items and .erd-canvas-wrap's\n `flex: 1` has no effect, causing the SVG to shrink to its min-height. */\n:host {\n display: flex !important;\n flex-direction: column !important;\n height: 100%;\n width: 100%;\n overflow: hidden;\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n --erd-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, \"Liberation Mono\", monospace;\n}\n\n/* \u2550\u2550\u2550 CHROME \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.erd-chrome {\n display: flex;\n align-items: center;\n gap: 24px;\n padding: 14px 24px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n flex-shrink: 0;\n min-height: 64px;\n}\n\n.erd-title-group {\n display: flex;\n flex-direction: column;\n gap: 2px;\n flex-shrink: 0;\n}\n\n.erd-title {\n font-size: 15px;\n font-weight: 600;\n letter-spacing: -0.01em;\n color: var(--mj-text-primary);\n}\n\n.erd-subtitle {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.erd-count-pill {\n font-family: var(--erd-mono);\n font-size: 11px;\n font-weight: 600;\n padding: 2px 8px;\n border-radius: 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n color: var(--mj-brand-primary);\n line-height: 1.3;\n}\n\n.erd-count-label { color: var(--mj-text-secondary); }\n.erd-dot { color: var(--mj-text-muted); }\n\n.erd-search {\n flex: 1;\n max-width: 440px;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface-card);\n transition: border-color .12s, background .12s, box-shadow .12s;\n}\n\n.erd-search:focus-within {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.erd-search > i {\n color: var(--mj-text-muted);\n flex-shrink: 0;\n font-size: 13px;\n}\n\n.erd-search input {\n flex: 1;\n border: 0;\n outline: 0;\n background: transparent;\n font: inherit;\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n.erd-search input::placeholder { color: var(--mj-text-muted); }\n\n.erd-search-clear {\n border: 0;\n background: transparent;\n color: var(--mj-text-muted);\n font-size: 18px;\n line-height: 1;\n cursor: pointer;\n padding: 0 4px;\n}\n\n.erd-search-clear:hover { color: var(--mj-text-primary); }\n\n.erd-chrome-right {\n display: flex;\n align-items: center;\n gap: 16px;\n margin-left: auto;\n}\n\n/* Schema chips */\n.erd-schema-chips {\n display: flex;\n gap: 4px;\n padding: 3px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n}\n\n.erd-chip {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 5px 10px;\n border: 0;\n background: transparent;\n border-radius: 7px;\n font-family: var(--erd-mono);\n font-size: 11px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: background .1s, color .1s;\n}\n\n.erd-chip:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.erd-chip.active {\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);\n}\n\n.erd-chip-count {\n font-size: 10px;\n padding: 1px 5px;\n border-radius: 6px;\n background: color-mix(in srgb, var(--mj-bg-surface-card) 80%, transparent);\n color: var(--mj-text-muted);\n}\n\n/* Toolbar */\n.erd-toolbar {\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 3px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n}\n\n.erd-toolbar button {\n width: 28px;\n height: 28px;\n border: 0;\n background: transparent;\n border-radius: 5px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n transition: background .1s, color .1s;\n}\n\n.erd-toolbar button:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.erd-toolbar button.active {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.erd-zoom-val {\n padding: 0 8px;\n font-family: var(--erd-mono);\n font-size: 10px;\n color: var(--mj-text-secondary);\n min-width: 42px;\n text-align: right;\n}\n\n/* \u2550\u2550\u2550 CANVAS \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.erd-canvas-wrap {\n flex: 1;\n position: relative;\n overflow: hidden;\n background: var(--mj-bg-surface-sunken);\n min-height: 300px;\n}\n\n.erd-canvas {\n width: 100%;\n height: 100%;\n user-select: none;\n cursor: grab;\n display: block;\n}\n\n.erd-canvas[data-panning=\"true\"] { cursor: grabbing; }\n\n.erd-canvas text { pointer-events: none; }\n\n/* Schema band \u2014 subtle neutral grouping (no per-schema color) */\n.erd-band-rect {\n fill: color-mix(in srgb, var(--mj-text-primary) 4%, transparent);\n stroke: var(--mj-border-default);\n stroke-width: 1;\n}\n\n.erd-band-title {\n font-family: var(--erd-mono);\n font-size: 13px;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n fill: var(--mj-text-muted);\n}\n\n/* Edges */\n.erd-edge {\n stroke: var(--mj-border-strong);\n stroke-width: 1.2;\n transition: stroke-width .15s, opacity .15s;\n}\n\n.erd-edge-active {\n stroke: var(--mj-brand-primary);\n stroke-width: 1.8;\n}\n\n.erd-edge-dimmed { opacity: 0.18; }\n\n/* Edge labels \u2014 FK field name on a small chip along the edge.\n Background uses surface so the text is legible over crossings. */\n.erd-edge-label {\n pointer-events: none;\n transition: opacity .15s;\n}\n\n.erd-edge-label-bg {\n fill: var(--mj-bg-surface);\n stroke: var(--mj-border-default);\n stroke-width: 0.75;\n}\n\n.erd-edge-label-text {\n font-family: var(--erd-mono);\n font-size: 11px;\n fill: var(--mj-text-secondary);\n}\n\n.erd-edge-label-active .erd-edge-label-bg {\n stroke: var(--mj-brand-primary);\n}\n\n.erd-edge-label-active .erd-edge-label-text {\n fill: var(--mj-brand-primary);\n}\n\n.erd-edge-label-dimmed { opacity: 0.18; }\n\n/* Edge markers (crow's-foot and arrow) */\n.erd-marker { fill: var(--mj-border-strong); }\n.erd-marker-active,\n.erd-marker-active.erd-marker,\n.erd-marker-active.erd-marker-stroke { fill: var(--mj-brand-primary); stroke: var(--mj-brand-primary); }\n.erd-marker-stroke { stroke: var(--mj-border-strong); stroke-width: 1.4; fill: none; stroke-linecap: round; }\n\n/* Node card */\n.erd-node {\n cursor: pointer;\n transition: opacity .15s;\n}\n\n.erd-node-dimmed { opacity: 0.22; }\n\n.erd-node-shadow {\n fill: color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n}\n\n.erd-node-body {\n fill: var(--mj-bg-surface);\n}\n\n/* Outline rendered as a separate rect on top of the header so the focus\n stroke is visible all the way around the card (otherwise the header\n fill clips the top edge of the body's stroke). */\n.erd-node-frame {\n fill: none;\n stroke: var(--mj-border-default);\n stroke-width: 1;\n pointer-events: none;\n}\n\n.erd-node-focus .erd-node-frame {\n stroke: var(--mj-brand-primary);\n stroke-width: 2;\n}\n\n.erd-node-neighbour .erd-node-frame {\n stroke-width: 1.5;\n}\n\n.erd-node-header {\n fill: var(--mj-bg-surface-card);\n}\n\n.erd-node-separator {\n stroke: var(--mj-border-default);\n stroke-width: 1;\n}\n\n/* Header content (foreignObject) \u2014 entity name + row count on one line */\n.erd-node-header-content {\n display: flex;\n align-items: center;\n gap: 8px;\n font-family: var(--erd-mono);\n line-height: 22px;\n height: 22px;\n color: var(--mj-text-primary);\n}\n\n.erd-node-name {\n font-size: 13px;\n font-weight: 600;\n flex: 1;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.erd-node-rows {\n font-size: 10px;\n color: var(--mj-text-muted);\n flex-shrink: 0;\n}\n\n/* Field row (foreignObject) \u2014 chip + name + type, all on one line */\n.erd-field-row {\n display: flex;\n align-items: center;\n gap: 8px;\n height: 22px;\n padding: 0 12px 0 8px;\n font-family: var(--erd-mono);\n line-height: 22px;\n box-sizing: border-box;\n}\n\n.erd-field-chip {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 14px;\n border-radius: 3px;\n font-size: 8px;\n font-weight: 700;\n letter-spacing: 0.05em;\n line-height: 1;\n}\n\n.erd-field-chip-pk {\n background: color-mix(in srgb, var(--mj-status-warning) 20%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text, var(--mj-status-warning));\n}\n\n.erd-field-chip-fk {\n background: color-mix(in srgb, var(--mj-brand-primary) 18%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.erd-field-name {\n flex: 1;\n min-width: 0;\n font-size: 11px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.erd-field-type {\n flex-shrink: 0;\n font-size: 10px;\n color: var(--mj-text-muted);\n /* Cap very long type strings so the field name still has room */\n max-width: 45%;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* +N more toggle (foreignObject) */\n.erd-field-more {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 14px;\n border-radius: 3px;\n background: var(--mj-bg-surface-card);\n opacity: 0.7;\n font-family: inherit;\n font-size: 9px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: opacity .1s;\n}\n\n.erd-field-more:hover { opacity: 1; }\n\n/* \u2550\u2550\u2550 EMPTY + LOADING \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.erd-empty {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n pointer-events: none;\n}\n\n.erd-empty-icon {\n font-size: 40px;\n color: var(--mj-text-muted);\n opacity: 0.45;\n}\n\n.erd-empty-title {\n font-size: 15px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.erd-empty-hint {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.erd-loading-overlay {\n position: absolute;\n inset: 0;\n background: color-mix(in srgb, var(--mj-bg-page) 90%, transparent);\n backdrop-filter: blur(2px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 100;\n}\n\n.erd-loading-content {\n display: flex;\n align-items: center;\n gap: 10px;\n color: var(--mj-text-secondary);\n font-size: 13px;\n}\n\n.erd-loading-content i {\n color: var(--mj-brand-primary);\n font-size: 20px;\n}\n"] }]
1031
+ args: [{ standalone: false, selector: 'mj-erd-diagram', changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- \u2500\u2500 CHROME \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n@if (showHeader) {\n <header class=\"erd-chrome\">\n <div class=\"erd-title-group\">\n <div class=\"erd-title\">{{ headerTitle }}</div>\n <div class=\"erd-subtitle\">\n <span class=\"erd-count-pill\">{{ visibleCount }}</span>\n <span class=\"erd-count-label\">of {{ totalCount }} entities</span>\n <span class=\"erd-dot\">\u00B7</span>\n <span>{{ layout.edges.length }} relationships</span>\n </div>\n </div>\n\n <label class=\"erd-search\">\n <i class=\"fa-solid fa-magnifying-glass\" aria-hidden=\"true\"></i>\n <input\n type=\"text\"\n [value]=\"searchQuery\"\n (input)=\"onSearchChange($any($event.target).value)\"\n placeholder=\"Search entities, schemas, fields\u2026\"\n spellcheck=\"false\"\n aria-label=\"Search entities\" />\n @if (searchQuery) {\n <button type=\"button\" class=\"erd-search-clear\" (click)=\"onClearSearch()\" aria-label=\"Clear search\">\u00D7</button>\n }\n </label>\n\n <div class=\"erd-chrome-right\">\n @if (schemaChips.length > 1) {\n <div class=\"erd-schema-chips\" role=\"group\" aria-label=\"Filter by schema\">\n @for (chip of schemaChips; track trackByChip($index, chip)) {\n <button\n type=\"button\"\n class=\"erd-chip\"\n [class.active]=\"chip.active\"\n (click)=\"onSchemaChipToggle(chip.name)\"\n [attr.aria-pressed]=\"chip.active\">\n <span class=\"erd-chip-label\">{{ chip.name }}</span>\n <span class=\"erd-chip-count\">{{ chip.count }}</span>\n </button>\n }\n </div>\n }\n\n <div class=\"erd-toolbar\" role=\"group\" aria-label=\"Layout mode\">\n <button\n type=\"button\"\n [class.active]=\"activeLayout === 'schema-grid'\"\n (click)=\"setLayoutAlgorithm('schema-grid')\"\n title=\"Schema grid \u2014 grouped by schema, predictable\"\n aria-label=\"Schema-grid layout\">\n <i class=\"fa-solid fa-table-cells\" aria-hidden=\"true\"></i>\n </button>\n <button\n type=\"button\"\n [class.active]=\"activeLayout === 'dagre'\"\n (click)=\"setLayoutAlgorithm('dagre')\"\n title=\"Hierarchical \u2014 classic ERD, relationship-driven\"\n aria-label=\"Hierarchical layout\">\n <i class=\"fa-solid fa-sitemap\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n <div class=\"erd-toolbar\" role=\"group\" aria-label=\"Zoom controls\">\n <button type=\"button\" (click)=\"zoomBy(1.2)\" title=\"Zoom in\" aria-label=\"Zoom in\">\n <i class=\"fa-solid fa-magnifying-glass-plus\" aria-hidden=\"true\"></i>\n </button>\n <button type=\"button\" (click)=\"zoomBy(0.83)\" title=\"Zoom out\" aria-label=\"Zoom out\">\n <i class=\"fa-solid fa-magnifying-glass-minus\" aria-hidden=\"true\"></i>\n </button>\n <button type=\"button\" (click)=\"fitToView()\" title=\"Fit to view\" aria-label=\"Fit to view\">\n <i class=\"fa-solid fa-expand\" aria-hidden=\"true\"></i>\n </button>\n <span class=\"erd-zoom-val\">{{ zoomPercent }}</span>\n </div>\n </div>\n </header>\n}\n\n<!-- \u2500\u2500 CANVAS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n<!-- Pan handling is window-level once mousedown fires (see component) so\n dragging continues even if the cursor leaves the canvas-wrap. -->\n<div class=\"erd-canvas-wrap\">\n\n <svg\n #canvasRef\n class=\"erd-canvas\"\n [attr.data-panning]=\"panning ? 'true' : null\"\n (mousedown)=\"onBackgroundMouseDown($event)\"\n (wheel)=\"onWheel($event)\">\n\n <defs>\n <marker id=\"erd-arrow\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto\">\n <path d=\"M 0 0 L 10 5 L 0 10 z\" class=\"erd-marker\" />\n </marker>\n <marker id=\"erd-arrow-active\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto\">\n <path d=\"M 0 0 L 10 5 L 0 10 z\" class=\"erd-marker erd-marker-active\" />\n </marker>\n <marker id=\"erd-many\" viewBox=\"-10 -6 14 12\" refX=\"-8\" refY=\"0\" markerWidth=\"14\" markerHeight=\"14\" orient=\"auto\">\n <path d=\"M 0 -5 L -8 0 L 0 5 M -8 0 L 4 0\" class=\"erd-marker-stroke\" />\n </marker>\n <marker id=\"erd-many-active\" viewBox=\"-10 -6 14 12\" refX=\"-8\" refY=\"0\" markerWidth=\"14\" markerHeight=\"14\" orient=\"auto\">\n <path d=\"M 0 -5 L -8 0 L 0 5 M -8 0 L 4 0\" class=\"erd-marker-stroke erd-marker-active\" />\n </marker>\n </defs>\n\n <g [attr.transform]=\"'translate(' + transform.x + ' ' + transform.y + ') scale(' + transform.k + ')'\">\n\n <!-- Schema bands -->\n @if ((config.showSchemaBands ?? true)) {\n @for (band of layout.bands; track trackByBand($index, band)) {\n <g class=\"erd-band\">\n <rect\n [attr.x]=\"band.x\" [attr.y]=\"band.y\"\n [attr.width]=\"band.width\" [attr.height]=\"band.height\"\n rx=\"16\"\n class=\"erd-band-rect\" />\n <text\n [attr.x]=\"band.x + band.width / 2\"\n [attr.y]=\"band.y + 32\"\n text-anchor=\"middle\"\n class=\"erd-band-title\">\n {{ band.schemaName }}\n </text>\n </g>\n }\n }\n\n <!-- Edges -->\n <g class=\"erd-edges\">\n @for (edge of layout.edges; track trackByEdge($index, edge)) {\n <path\n [attr.d]=\"edgePath(edge)\"\n fill=\"none\"\n class=\"erd-edge\"\n [class.erd-edge-active]=\"isEdgeActive(edge)\"\n [class.erd-edge-dimmed]=\"isEdgeDimmed(edge)\"\n [attr.marker-start]=\"(config.crowsFoot ?? true) ? (isEdgeActive(edge) ? 'url(#erd-many-active)' : 'url(#erd-many)') : null\"\n [attr.marker-end]=\"isEdgeActive(edge) ? 'url(#erd-arrow-active)' : 'url(#erd-arrow)'\" />\n }\n </g>\n\n <!-- Edge labels \u2014 FK field names rendered along edges. Only shown\n when zoom is high enough for the text to be legible, and only\n when config.showRelationshipLabels resolves true. -->\n @if (showEdgeLabels) {\n <g class=\"erd-edge-labels\">\n @for (edge of layout.edges; track trackByEdge($index, edge)) {\n @let pos = edgeLabelPosition(edge);\n @if (pos) {\n <g\n class=\"erd-edge-label\"\n [class.erd-edge-label-active]=\"isEdgeActive(edge)\"\n [class.erd-edge-label-dimmed]=\"isEdgeDimmed(edge)\">\n <rect\n [attr.x]=\"pos.x - pos.w / 2 - 4\"\n [attr.y]=\"pos.y - 8\"\n [attr.width]=\"pos.w + 8\"\n height=\"16\"\n rx=\"3\"\n class=\"erd-edge-label-bg\" />\n <text\n [attr.x]=\"pos.x\"\n [attr.y]=\"pos.y + 4\"\n text-anchor=\"middle\"\n class=\"erd-edge-label-text\">{{ edge.sourceField.name }}</text>\n </g>\n }\n }\n </g>\n }\n\n <!-- Nodes -->\n <g class=\"erd-nodes\">\n @for (node of layout.nodes; track trackByNode($index, node)) {\n <g\n class=\"erd-node\"\n [attr.transform]=\"'translate(' + node.x + ' ' + node.y + ')'\"\n [class.erd-node-focus]=\"isFocus(node.id)\"\n [class.erd-node-neighbour]=\"isNeighbour(node.id)\"\n [class.erd-node-dimmed]=\"isDimmed(node.id)\"\n (click)=\"onNodeClick(node, $event)\"\n (mouseenter)=\"onNodeMouseEnter(node, $event)\"\n (mouseleave)=\"onNodeMouseLeave(node)\">\n\n <!-- Card shadow -->\n <rect class=\"erd-node-shadow\"\n [attr.width]=\"node.width\" [attr.height]=\"node.height\"\n x=\"0\" y=\"2\" rx=\"8\" />\n\n <!-- Card body -->\n <rect class=\"erd-node-body\"\n [attr.width]=\"node.width\" [attr.height]=\"node.height\"\n x=\"0\" y=\"0\" rx=\"8\" />\n\n <!-- Header -->\n <rect class=\"erd-node-header\"\n x=\"0\" y=\"0\"\n [attr.width]=\"node.width\" height=\"36\"\n rx=\"6\" />\n <foreignObject x=\"14\" y=\"8\" [attr.width]=\"node.width - 28\" height=\"22\">\n <div xmlns=\"http://www.w3.org/1999/xhtml\" class=\"erd-node-header-content\">\n <span class=\"erd-node-name\" [title]=\"node.name\">{{ node.name }}</span>\n @if (node.customData && $any(node.customData).rows != null) {\n <span class=\"erd-node-rows\">{{ formatCount($any(node.customData).rows) }}</span>\n }\n </div>\n </foreignObject>\n\n <!-- Separator -->\n <line class=\"erd-node-separator\"\n x1=\"0\" [attr.x2]=\"node.width\" y1=\"36\" y2=\"36\" />\n\n <!-- Fields -->\n @for (field of node.visibleFields; track trackByField($index, field); let i = $index) {\n <foreignObject x=\"0\" [attr.y]=\"36 + i * 22\" [attr.width]=\"node.width\" height=\"22\">\n <div xmlns=\"http://www.w3.org/1999/xhtml\"\n class=\"erd-field-row\"\n [class.erd-field-pk]=\"field.isPrimaryKey\"\n [class.erd-field-fk]=\"!field.isPrimaryKey && field.relatedNodeId\">\n @if (field.isPrimaryKey) {\n <span class=\"erd-field-chip erd-field-chip-pk\">PK</span>\n } @else if (field.relatedNodeId) {\n <span class=\"erd-field-chip erd-field-chip-fk\">FK</span>\n }\n <span class=\"erd-field-name\" [title]=\"field.name\">{{ field.name }}</span>\n @if (field.type) {\n <span class=\"erd-field-type\" [title]=\"field.type\">{{ field.type }}</span>\n }\n </div>\n </foreignObject>\n }\n\n <!-- +N more toggle -->\n @if (node.hasMore) {\n <foreignObject\n x=\"4\"\n [attr.y]=\"36 + node.visibleFields.length * 22 + 6\"\n [attr.width]=\"node.width - 8\"\n height=\"14\"\n (click)=\"onToggleExpand(node.id, $event)\">\n <div xmlns=\"http://www.w3.org/1999/xhtml\" class=\"erd-field-more\">\n + {{ node.fields.length - node.visibleFields.length }} more fields\n </div>\n </foreignObject>\n }\n\n <!-- Outline frame \u2014 drawn last so the focus/neighbour stroke\n sits above the header instead of being clipped by it. -->\n <rect class=\"erd-node-frame\"\n [attr.width]=\"node.width\" [attr.height]=\"node.height\"\n x=\"0\" y=\"0\" rx=\"8\" />\n </g>\n }\n </g>\n </g>\n </svg>\n\n <!-- Focus details are rendered by the consumer's side panel\n (mj-entity-details inside mj-erd-composite); the in-canvas\n floating focus card was removed as it duplicated that content. -->\n\n <!-- \u2500\u2500 Empty state \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (visibleCount === 0) {\n <mj-empty-state\n class=\"erd-empty\"\n [Variant]=\"totalCount === 0 ? 'empty' : 'no-results'\"\n [Icon]=\"emptyStateIcon\"\n [Title]=\"emptyStateTitle\"\n [Message]=\"totalCount > 0 ? 'Try adjusting schema filters or clearing search' : ''\" />\n }\n\n <!-- \u2500\u2500 Loading overlay \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n @if (isRefreshing) {\n <div class=\"erd-loading-overlay\">\n <div class=\"erd-loading-content\">\n <i class=\"fa-solid fa-circle-notch fa-spin\" aria-hidden=\"true\"></i>\n <span>Loading\u2026</span>\n </div>\n </div>\n }\n</div>\n", styles: ["/**\n * ERD Diagram Component \u2014 MJ Design Tokens.\n *\n * Uses MJ semantic tokens for all colors so the diagram adapts automatically\n * to light/dark mode via the app's global theme. Per-schema accent colors\n * are OKLCH computed from a hash of the schema name (categorical chart\n * colors, one of the few intentional exceptions to the token rule).\n *\n * Typography: MJ's default UI font inherits; entity/field names use a\n * platform monospace stack so they read as technical identifiers.\n */\n\n/* !important on display + direction keeps consumer classes (e.g. a host\n `.something { display: block }`) from collapsing the flex layout \u2014 without\n this the chrome + canvas-wrap stop being flex items and .erd-canvas-wrap's\n `flex: 1` has no effect, causing the SVG to shrink to its min-height. */\n:host {\n display: flex !important;\n flex-direction: column !important;\n height: 100%;\n width: 100%;\n overflow: hidden;\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n --erd-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, \"Liberation Mono\", monospace;\n}\n\n/* \u2550\u2550\u2550 CHROME \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.erd-chrome {\n display: flex;\n align-items: center;\n gap: 24px;\n padding: 14px 24px;\n border-bottom: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n flex-shrink: 0;\n min-height: 64px;\n}\n\n.erd-title-group {\n display: flex;\n flex-direction: column;\n gap: 2px;\n flex-shrink: 0;\n}\n\n.erd-title {\n font-size: 15px;\n font-weight: 600;\n letter-spacing: -0.01em;\n color: var(--mj-text-primary);\n}\n\n.erd-subtitle {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.erd-count-pill {\n font-family: var(--erd-mono);\n font-size: 11px;\n font-weight: 600;\n padding: 2px 8px;\n border-radius: 10px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n color: var(--mj-brand-primary);\n line-height: 1.3;\n}\n\n.erd-count-label { color: var(--mj-text-secondary); }\n.erd-dot { color: var(--mj-text-muted); }\n\n.erd-search {\n flex: 1;\n max-width: 440px;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface-card);\n transition: border-color .12s, background .12s, box-shadow .12s;\n}\n\n.erd-search:focus-within {\n border-color: var(--mj-brand-primary);\n background: var(--mj-bg-surface);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.erd-search > i {\n color: var(--mj-text-muted);\n flex-shrink: 0;\n font-size: 13px;\n}\n\n.erd-search input {\n flex: 1;\n border: 0;\n outline: 0;\n background: transparent;\n font: inherit;\n font-size: 13px;\n color: var(--mj-text-primary);\n}\n\n.erd-search input::placeholder { color: var(--mj-text-muted); }\n\n.erd-search-clear {\n border: 0;\n background: transparent;\n color: var(--mj-text-muted);\n font-size: 18px;\n line-height: 1;\n cursor: pointer;\n padding: 0 4px;\n}\n\n.erd-search-clear:hover { color: var(--mj-text-primary); }\n\n.erd-chrome-right {\n display: flex;\n align-items: center;\n gap: 16px;\n margin-left: auto;\n}\n\n/* Schema chips */\n.erd-schema-chips {\n display: flex;\n gap: 4px;\n padding: 3px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n}\n\n.erd-chip {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 5px 10px;\n border: 0;\n background: transparent;\n border-radius: 7px;\n font-family: var(--erd-mono);\n font-size: 11px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: background .1s, color .1s;\n}\n\n.erd-chip:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.erd-chip.active {\n background: var(--mj-bg-surface);\n color: var(--mj-text-primary);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);\n}\n\n.erd-chip-count {\n font-size: 10px;\n padding: 1px 5px;\n border-radius: 6px;\n background: color-mix(in srgb, var(--mj-bg-surface-card) 80%, transparent);\n color: var(--mj-text-muted);\n}\n\n/* Toolbar */\n.erd-toolbar {\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 3px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n}\n\n.erd-toolbar button {\n width: 28px;\n height: 28px;\n border: 0;\n background: transparent;\n border-radius: 5px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n transition: background .1s, color .1s;\n}\n\n.erd-toolbar button:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.erd-toolbar button.active {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.erd-zoom-val {\n padding: 0 8px;\n font-family: var(--erd-mono);\n font-size: 10px;\n color: var(--mj-text-secondary);\n min-width: 42px;\n text-align: right;\n}\n\n/* \u2550\u2550\u2550 CANVAS \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n.erd-canvas-wrap {\n flex: 1;\n position: relative;\n overflow: hidden;\n background: var(--mj-bg-surface-sunken);\n min-height: 300px;\n}\n\n.erd-canvas {\n width: 100%;\n height: 100%;\n user-select: none;\n cursor: grab;\n display: block;\n}\n\n.erd-canvas[data-panning=\"true\"] { cursor: grabbing; }\n\n.erd-canvas text { pointer-events: none; }\n\n/* Schema band \u2014 subtle neutral grouping (no per-schema color) */\n.erd-band-rect {\n fill: color-mix(in srgb, var(--mj-text-primary) 4%, transparent);\n stroke: var(--mj-border-default);\n stroke-width: 1;\n}\n\n.erd-band-title {\n font-family: var(--erd-mono);\n font-size: 13px;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n fill: var(--mj-text-muted);\n}\n\n/* Edges */\n.erd-edge {\n stroke: var(--mj-border-strong);\n stroke-width: 1.2;\n transition: stroke-width .15s, opacity .15s;\n}\n\n.erd-edge-active {\n stroke: var(--mj-brand-primary);\n stroke-width: 1.8;\n}\n\n.erd-edge-dimmed { opacity: 0.18; }\n\n/* Edge labels \u2014 FK field name on a small chip along the edge.\n Background uses surface so the text is legible over crossings. */\n.erd-edge-label {\n pointer-events: none;\n transition: opacity .15s;\n}\n\n.erd-edge-label-bg {\n fill: var(--mj-bg-surface);\n stroke: var(--mj-border-default);\n stroke-width: 0.75;\n}\n\n.erd-edge-label-text {\n font-family: var(--erd-mono);\n font-size: 11px;\n fill: var(--mj-text-secondary);\n}\n\n.erd-edge-label-active .erd-edge-label-bg {\n stroke: var(--mj-brand-primary);\n}\n\n.erd-edge-label-active .erd-edge-label-text {\n fill: var(--mj-brand-primary);\n}\n\n.erd-edge-label-dimmed { opacity: 0.18; }\n\n/* Edge markers (crow's-foot and arrow) */\n.erd-marker { fill: var(--mj-border-strong); }\n.erd-marker-active,\n.erd-marker-active.erd-marker,\n.erd-marker-active.erd-marker-stroke { fill: var(--mj-brand-primary); stroke: var(--mj-brand-primary); }\n.erd-marker-stroke { stroke: var(--mj-border-strong); stroke-width: 1.4; fill: none; stroke-linecap: round; }\n\n/* Node card */\n.erd-node {\n cursor: pointer;\n transition: opacity .15s;\n}\n\n.erd-node-dimmed { opacity: 0.22; }\n\n.erd-node-shadow {\n fill: color-mix(in srgb, var(--mj-text-primary) 8%, transparent);\n}\n\n.erd-node-body {\n fill: var(--mj-bg-surface);\n}\n\n/* Outline rendered as a separate rect on top of the header so the focus\n stroke is visible all the way around the card (otherwise the header\n fill clips the top edge of the body's stroke). */\n.erd-node-frame {\n fill: none;\n stroke: var(--mj-border-default);\n stroke-width: 1;\n pointer-events: none;\n}\n\n.erd-node-focus .erd-node-frame {\n stroke: var(--mj-brand-primary);\n stroke-width: 2;\n}\n\n.erd-node-neighbour .erd-node-frame {\n stroke-width: 1.5;\n}\n\n.erd-node-header {\n fill: var(--mj-bg-surface-card);\n}\n\n.erd-node-separator {\n stroke: var(--mj-border-default);\n stroke-width: 1;\n}\n\n/* Header content (foreignObject) \u2014 entity name + row count on one line */\n.erd-node-header-content {\n display: flex;\n align-items: center;\n gap: 8px;\n font-family: var(--erd-mono);\n line-height: 22px;\n height: 22px;\n color: var(--mj-text-primary);\n}\n\n.erd-node-name {\n font-size: 13px;\n font-weight: 600;\n flex: 1;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.erd-node-rows {\n font-size: 10px;\n color: var(--mj-text-muted);\n flex-shrink: 0;\n}\n\n/* Field row (foreignObject) \u2014 chip + name + type, all on one line */\n.erd-field-row {\n display: flex;\n align-items: center;\n gap: 8px;\n height: 22px;\n padding: 0 12px 0 8px;\n font-family: var(--erd-mono);\n line-height: 22px;\n box-sizing: border-box;\n}\n\n.erd-field-chip {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 14px;\n border-radius: 3px;\n font-size: 8px;\n font-weight: 700;\n letter-spacing: 0.05em;\n line-height: 1;\n}\n\n.erd-field-chip-pk {\n background: color-mix(in srgb, var(--mj-status-warning) 20%, var(--mj-bg-surface));\n color: var(--mj-status-warning-text, var(--mj-status-warning));\n}\n\n.erd-field-chip-fk {\n background: color-mix(in srgb, var(--mj-brand-primary) 18%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n}\n\n.erd-field-name {\n flex: 1;\n min-width: 0;\n font-size: 11px;\n color: var(--mj-text-primary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.erd-field-type {\n flex-shrink: 0;\n font-size: 10px;\n color: var(--mj-text-muted);\n /* Cap very long type strings so the field name still has room */\n max-width: 45%;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* +N more toggle (foreignObject) */\n.erd-field-more {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 14px;\n border-radius: 3px;\n background: var(--mj-bg-surface-card);\n opacity: 0.7;\n font-family: inherit;\n font-size: 9px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: opacity .1s;\n}\n\n.erd-field-more:hover { opacity: 1; }\n\n/* \u2550\u2550\u2550 EMPTY + LOADING \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n/* Overlay the canvas; mj-empty-state owns the centered icon/title/message. */\n.erd-empty {\n position: absolute;\n inset: 0;\n pointer-events: none;\n}\n\n.erd-loading-overlay {\n position: absolute;\n inset: 0;\n background: color-mix(in srgb, var(--mj-bg-page) 90%, transparent);\n backdrop-filter: blur(2px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 100;\n}\n\n.erd-loading-content {\n display: flex;\n align-items: center;\n gap: 10px;\n color: var(--mj-text-secondary);\n font-size: 13px;\n}\n\n.erd-loading-content i {\n color: var(--mj-brand-primary);\n font-size: 20px;\n}\n"] }]
1038
1032
  }], null, { nodes: [{
1039
1033
  type: Input
1040
1034
  }], selectedNodeId: [{