compasso 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +115 -5
- package/dist/{chunk-ZBDABVIO.js → chunk-2NDET6O5.js} +3 -3
- package/dist/{chunk-ZBDABVIO.js.map → chunk-2NDET6O5.js.map} +1 -1
- package/dist/{chunk-Q6DVTCXD.js → chunk-3RGYLVTN.js} +18 -6
- package/dist/chunk-3RGYLVTN.js.map +1 -0
- package/dist/chunk-BM7UJBK5.js +680 -0
- package/dist/chunk-BM7UJBK5.js.map +1 -0
- package/dist/chunk-DVLWT565.js +372 -0
- package/dist/chunk-DVLWT565.js.map +1 -0
- package/dist/{chunk-F47C6ZEB.js → chunk-JBDA7E2O.js} +3 -3
- package/dist/{chunk-F47C6ZEB.js.map → chunk-JBDA7E2O.js.map} +1 -1
- package/dist/chunk-MIJTBYX2.js +982 -0
- package/dist/chunk-MIJTBYX2.js.map +1 -0
- package/dist/{chunk-JP4N42AY.js → chunk-PJHLWSGD.js} +3 -3
- package/dist/{chunk-JP4N42AY.js.map → chunk-PJHLWSGD.js.map} +1 -1
- package/dist/{chunk-LRHHUJFZ.js → chunk-RDH4XHA2.js} +3 -3
- package/dist/{chunk-LRHHUJFZ.js.map → chunk-RDH4XHA2.js.map} +1 -1
- package/dist/{chunk-UJVU7B44.js → chunk-WEHUSHVI.js} +31 -51
- package/dist/chunk-WEHUSHVI.js.map +1 -0
- package/dist/{chunk-RWPGGWO5.js → chunk-Z66YUOUM.js} +34 -10
- package/dist/chunk-Z66YUOUM.js.map +1 -0
- package/dist/core/index.cjs +247 -0
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +94 -2
- package/dist/core/index.d.ts +94 -2
- package/dist/core/index.js +1 -1
- package/dist/ecomap/index.cjs +34 -11
- package/dist/ecomap/index.cjs.map +1 -1
- package/dist/ecomap/index.d.cts +12 -0
- package/dist/ecomap/index.d.ts +12 -0
- package/dist/ecomap/index.js +2 -2
- package/dist/fault-tree/index.d.cts +2 -2
- package/dist/fault-tree/index.d.ts +2 -2
- package/dist/fault-tree/index.js +2 -2
- package/dist/fishbone/index.js +2 -2
- package/dist/genogram/index.cjs +57 -7
- package/dist/genogram/index.cjs.map +1 -1
- package/dist/genogram/index.d.cts +22 -6
- package/dist/genogram/index.d.ts +22 -6
- package/dist/genogram/index.js +2 -2
- package/dist/geometry-P-XGqGe7.d.cts +8 -0
- package/dist/geometry-P-XGqGe7.d.ts +8 -0
- package/dist/grid-BMgUSly1.d.cts +79 -0
- package/dist/grid-BMgUSly1.d.ts +79 -0
- package/dist/index.cjs +2360 -395
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -7
- package/dist/index.d.ts +14 -7
- package/dist/index.js +10 -8
- package/dist/{kinship-DqEklrDN.d.ts → kinship-BF90HyyS.d.ts} +1 -1
- package/dist/{kinship-Dy_ijjJV.d.cts → kinship-BOUss5cT.d.cts} +1 -1
- package/dist/{labels-RtFw9tX1.d.cts → labels-B0aOMbHy.d.cts} +12 -0
- package/dist/{labels-RtFw9tX1.d.ts → labels-B0aOMbHy.d.ts} +12 -0
- package/dist/labels-Br8yjc3C.d.cts +29 -0
- package/dist/labels-Br8yjc3C.d.ts +29 -0
- package/dist/{labels-DNqRkWuI.d.ts → labels-CuLbFyrz.d.ts} +1 -1
- package/dist/labels-D1v1RWZd.d.cts +97 -0
- package/dist/labels-D1v1RWZd.d.ts +97 -0
- package/dist/{labels-CBQ_3Ec9.d.cts → labels-DhQe7I8m.d.cts} +1 -1
- package/dist/layered-DmZluAqe.d.cts +72 -0
- package/dist/layered-DmZluAqe.d.ts +72 -0
- package/dist/locales/pt-br.cjs +53 -0
- package/dist/locales/pt-br.cjs.map +1 -1
- package/dist/locales/pt-br.d.cts +11 -5
- package/dist/locales/pt-br.d.ts +11 -5
- package/dist/locales/pt-br.js +50 -1
- package/dist/locales/pt-br.js.map +1 -1
- package/dist/org-chart/index.cjs +138 -94
- package/dist/org-chart/index.cjs.map +1 -1
- package/dist/org-chart/index.d.cts +24 -33
- package/dist/org-chart/index.d.ts +24 -33
- package/dist/org-chart/index.js +2 -2
- package/dist/pedigree/index.d.cts +6 -6
- package/dist/pedigree/index.d.ts +6 -6
- package/dist/pedigree/index.js +2 -2
- package/dist/phylo/index.d.cts +2 -2
- package/dist/phylo/index.d.ts +2 -2
- package/dist/phylo/index.js +2 -2
- package/dist/prisma/index.cjs +882 -0
- package/dist/prisma/index.cjs.map +1 -0
- package/dist/prisma/index.d.cts +174 -0
- package/dist/prisma/index.d.ts +174 -0
- package/dist/prisma/index.js +4 -0
- package/dist/prisma/index.js.map +1 -0
- package/dist/{text-DuO_PwYw.d.cts → text-DDVzpwPZ.d.cts} +1 -8
- package/dist/{text-DuO_PwYw.d.ts → text-DDVzpwPZ.d.ts} +1 -8
- package/dist/{types-BnMG7TCd.d.cts → types-jE2fdM1t.d.cts} +8 -0
- package/dist/{types-BnMG7TCd.d.ts → types-jE2fdM1t.d.ts} +8 -0
- package/dist/uml/index.cjs +1214 -0
- package/dist/uml/index.cjs.map +1 -0
- package/dist/uml/index.d.cts +189 -0
- package/dist/uml/index.d.ts +189 -0
- package/dist/uml/index.js +4 -0
- package/dist/uml/index.js.map +1 -0
- package/package.json +28 -2
- package/dist/chunk-O3BT2O42.js +0 -145
- package/dist/chunk-O3BT2O42.js.map +0 -1
- package/dist/chunk-Q6DVTCXD.js.map +0 -1
- package/dist/chunk-RWPGGWO5.js.map +0 -1
- package/dist/chunk-UJVU7B44.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/prisma/types.ts","../src/prisma/validate.ts","../src/prisma/labels.ts","../src/prisma/layout.ts","../src/prisma/svg.ts","../src/prisma/render.ts"],"names":["round"],"mappings":";;;AAMO,IAAM,aAAA,GAAgB,CAAC,gBAAA,EAAkB,WAAA,EAAa,UAAU;AAIhE,IAAM,gBAAA,GAAmB,CAAC,MAAA,EAAQ,WAAW;AAI7C,IAAM,cAAA,GAAiB,CAAC,MAAA,EAAQ,KAAA,EAAO,UAAU;;;ACSjD,IAAM,qBAAA,GAAN,cAAoC,KAAA,CAAM;AAAA,EACtC,MAAA;AAAA,EAET,YAAY,MAAA,EAAgC;AAC1C,IAAA,KAAA,CAAM,CAAA,wBAAA,EAA2B,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAC1E,IAAA,IAAA,CAAK,IAAA,GAAO,uBAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AACF;AAMA,SAAS,WAAW,MAAA,EAAwD;AAC1E,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAyB;AAC5C,EAAA,KAAA,MAAW,KAAA,IAAS,MAAA,EAAQ,MAAA,CAAO,GAAA,CAAI,CAAA,EAAG,KAAA,CAAM,IAAI,CAAA,CAAA,EAAI,KAAA,CAAM,OAAO,CAAA,CAAA,EAAI,KAAK,CAAA;AAC9E,EAAA,OAAO,CAAC,GAAG,MAAA,CAAO,MAAA,EAAQ,CAAA,CAAE,IAAA;AAAA,IAAK,CAAC,GAAG,CAAA,KACnC,CAAA,CAAE,SAAS,CAAA,CAAE,IAAA,GACT,CAAA,CAAE,IAAA,GAAO,CAAA,CAAE,IAAA,GAAO,KAAK,CAAA,GACvB,CAAA,CAAE,UAAU,CAAA,CAAE,OAAA,GAAU,KAAK,CAAA,CAAE,OAAA,GAAU,CAAA,CAAE,OAAA,GAAU,CAAA,GAAI;AAAA,GAC/D;AACF;AAMO,SAAS,aAAa,KAAA,EAA4C;AACvE,EAAA,IAAI,KAAA,CAAM,MAAM,MAAA,KAAW,CAAA,IAAK,MAAM,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG,OAAO,EAAC;AAEnE,EAAA,MAAM,SAAwB,EAAC;AAC/B,EAAA,MAAM,IAAA,GAAO,CAAC,IAAA,EAAuB,OAAA,KAA0B;AAC7D,IAAA,MAAA,CAAO,IAAA,CAAK,EAAE,IAAA,EAAM,OAAA,EAAS,CAAA;AAAA,EAC/B,CAAA;AAIA,EAAA,MAAM,OAAA,uBAAc,GAAA,EAA0C;AAC9D,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAY;AAClC,EAAA,KAAA,MAAW,CAAA,IAAK,MAAM,KAAA,EAAO;AAC3B,IAAA,IAAI,OAAA,CAAQ,IAAI,CAAA,CAAE,EAAE,GAAG,SAAA,CAAU,GAAA,CAAI,EAAE,EAAE,CAAA;AAAA,SACpC,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAE,EAAA,EAAI,CAAC,CAAA;AAAA,EAC1B;AACA,EAAA,KAAA,MAAW,EAAA,IAAM,CAAC,GAAG,SAAS,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,CAAC,CAAA,EAAG;AACrD,IAAA,IAAA,CAAK,cAAA,EAAgB,CAAA,iBAAA,EAAoB,EAAE,CAAA,CAAE,CAAA;AAAA,EAC/C;AAEA,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAA2C;AACjE,EAAA,MAAM,WAAA,uBAAkB,GAAA,EAAY;AACpC,EAAA,KAAA,MAAW,CAAA,IAAK,MAAM,MAAA,EAAQ;AAC5B,IAAA,IAAI,SAAA,CAAU,IAAI,CAAA,CAAE,EAAE,GAAG,WAAA,CAAY,GAAA,CAAI,EAAE,EAAE,CAAA;AAAA,SACxC,SAAA,CAAU,GAAA,CAAI,CAAA,CAAE,EAAA,EAAI,CAAC,CAAA;AAAA,EAC5B;AACA,EAAA,KAAA,MAAW,EAAA,IAAM,CAAC,GAAG,WAAW,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,CAAC,CAAA,EAAG;AACvD,IAAA,IAAA,CAAK,cAAA,EAAgB,CAAA,mBAAA,EAAsB,EAAE,CAAA,CAAE,CAAA;AAAA,EACjD;AAEA,EAAA,IAAI,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG,OAAO,WAAW,MAAM,CAAA;AAK/C,EAAA,KAAA,MAAW,KAAA,IAAS,CAAC,GAAG,SAAA,CAAU,QAAQ,CAAA,CAAE,IAAA,CAAK,CAAC,GAAG,CAAA,KAAM,CAAA,CAAE,EAAA,GAAK,CAAA,CAAE,EAAE,CAAA,EAAG;AACvE,IAAA,IAAI,CAAC,OAAA,CAAQ,GAAA,CAAI,KAAA,CAAM,MAAM,CAAA,EAAG;AAC9B,MAAA,IAAA,CAAK,0BAA0B,CAAA,MAAA,EAAS,KAAA,CAAM,EAAE,CAAA,QAAA,EAAW,KAAA,CAAM,MAAM,CAAA,sBAAA,CAAwB,CAAA;AAAA,IACjG;AACA,IAAA,IAAI,CAAC,OAAA,CAAQ,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA,EAAG;AAC5B,MAAA,IAAA,CAAK,0BAA0B,CAAA,MAAA,EAAS,KAAA,CAAM,EAAE,CAAA,MAAA,EAAS,KAAA,CAAM,IAAI,CAAA,sBAAA,CAAwB,CAAA;AAAA,IAC7F;AAEA,IAAA,IAAI,KAAA,CAAM,MAAA,KAAW,KAAA,CAAM,IAAA,EAAM;AAC/B,MAAA,IAAA,CAAK,cAAc,CAAA,MAAA,EAAS,KAAA,CAAM,EAAE,CAAA,sBAAA,EAAyB,KAAA,CAAM,MAAM,CAAA,CAAA,CAAG,CAAA;AAAA,IAC9E;AAAA,EACF;AAGA,EAAA,KAAA,MAAW,GAAA,IAAO,CAAC,GAAG,OAAA,CAAQ,QAAQ,CAAA,CAAE,IAAA,CAAK,CAAC,GAAG,CAAA,KAAM,CAAA,CAAE,EAAA,GAAK,CAAA,CAAE,EAAE,CAAA,EAAG;AACnE,IAAA,KAAA,MAAW,KAAA,IAAS,IAAI,MAAA,EAAQ;AAC9B,MAAA,IAAI,KAAA,CAAM,MAAM,IAAA,IAAQ,CAAC,OAAO,QAAA,CAAS,KAAA,CAAM,CAAC,CAAA,EAAG;AACjD,QAAA,IAAA,CAAK,kBAAA,EAAoB,CAAA,IAAA,EAAO,GAAA,CAAI,EAAE,CAAA,QAAA,EAAW,KAAA,CAAM,KAAK,CAAA,oBAAA,EAAuB,MAAA,CAAO,KAAA,CAAM,CAAC,CAAC,CAAA,CAAE,CAAA;AAAA,MACtG;AAAA,IACF;AAAA,EACF;AAGA,EAAA,IAAI,KAAA,CAAM,YAAY,iBAAA,EAAmB;AACvC,IAAA,KAAA,MAAW,GAAA,IAAO,CAAC,GAAG,OAAA,CAAQ,QAAQ,CAAA,CAAE,IAAA,CAAK,CAAC,GAAG,CAAA,KAAM,CAAA,CAAE,EAAA,GAAK,CAAA,CAAE,EAAE,CAAA,EAAG;AACnE,MAAA,IAAI,GAAA,CAAI,WAAW,UAAA,EAAY;AAC7B,QAAA,IAAA;AAAA,UACE,wBAAA;AAAA,UACA,CAAA,IAAA,EAAO,GAAA,CAAI,EAAE,CAAA,uCAAA,EAA0C,MAAM,OAAO,CAAA,CAAA;AAAA,SACtE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAA,MAAM,cAAA,uBAAmD,GAAA,CAAI;AAAA,IAC3D,cAAA;AAAA,IACA;AAAA,GACD,CAAA;AACD,EAAA,IAAI,CAAC,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAAM,eAAe,GAAA,CAAI,CAAA,CAAE,IAAI,CAAC,CAAA,EAAG;AAInD,IAAA,MAAM,UAAA,uBAAiB,GAAA,EAAyB;AAChD,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,aAAA,CAAc,MAAA,EAAQ,CAAA,EAAA,EAAK,UAAA,CAAW,GAAA,CAAI,aAAA,CAAc,CAAC,CAAA,EAAI,CAAC,CAAA;AAElF,IAAA,KAAA,MAAW,KAAA,IAAS,CAAC,GAAG,SAAA,CAAU,QAAQ,CAAA,CAAE,IAAA,CAAK,CAAC,GAAG,CAAA,KAAM,CAAA,CAAE,EAAA,GAAK,CAAA,CAAE,EAAE,CAAA,EAAG;AACvE,MAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,GAAA,CAAI,KAAA,CAAM,MAAM,CAAA;AACxC,MAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA;AACpC,MAAA,MAAM,YAAA,GAAe,UAAA,CAAW,GAAA,CAAI,OAAA,CAAQ,KAAK,CAAA;AACjD,MAAA,MAAM,UAAA,GAAa,UAAA,CAAW,GAAA,CAAI,KAAA,CAAM,KAAK,CAAA;AAG7C,MAAA,IACE,OAAA,CAAQ,SAAS,MAAA,IACjB,KAAA,CAAM,SAAS,WAAA,IACf,OAAA,CAAQ,KAAA,KAAU,KAAA,CAAM,KAAA,EACxB;AACA,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,aAAa,YAAA,EAAc;AAC7B,QAAA,IAAA;AAAA,UACE,sBAAA;AAAA,UACA,CAAA,MAAA,EAAS,MAAM,EAAE,CAAA,4BAAA,EAA+B,QAAQ,KAAK,CAAA,MAAA,EAAS,MAAM,KAAK,CAAA,CAAA;AAAA,SACnF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,WAAW,MAAM,CAAA;AAC1B;AAGO,SAAS,eAAe,KAAA,EAA0B;AACvD,EAAA,MAAM,MAAA,GAAS,aAAa,KAAK,CAAA;AACjC,EAAA,IAAI,OAAO,MAAA,GAAS,CAAA,EAAG,MAAM,IAAI,sBAAsB,MAAM,CAAA;AAC/D;;;ACpIO,IAAM,sBAAA,GAA4C;AAAA,EACvD,MAAA,EAAQ;AAAA,IACN,cAAA,EAAgB,gBAAA;AAAA,IAChB,SAAA,EAAW,WAAA;AAAA,IACX,QAAA,EAAU;AAAA,GACZ;AAAA,EACA,SAAA,EAAW,YAAA;AAAA,EACX,UAAA,EAAY;AAAA,IACV,IAAA,EAAM,MAAA;AAAA,IACN,SAAA,EAAW,WAAA;AAAA,IACX,KAAA,EAAO;AAAA;AAEX;AAEO,IAAM,oBAAA,GAAwC;AAAA,EACnD,MAAA,EAAQ;AAAA,IACN,IAAA,EAAM,WAAA;AAAA,IACN,SAAA,EAAW;AAAA,GACb;AAAA,EACA,SAAA,EAAW;AACb;;;ACUO,IAAM,cAAA,GAAiB;AAEvB,IAAM,mBAAA,GAAsB;AAE5B,IAAM,cAAA,GAAiB;AAEvB,IAAM,eAAA,GAAkB;AACxB,IAAM,gBAAA,GAAmB;AACzB,IAAM,gBAAA,GAAmB;AACzB,IAAM,aAAA,GAAgB;AACtB,IAAM,gBAAA,GAAmB;AAEzB,IAAM,eAAA,GAAkB;AACxB,IAAM,mBAAA,GAAsB;AAC5B,IAAM,iBAAA,GAAoB;AAEjC,IAAM,mBAAA,GAAsB,EAAA;AAE5B,IAAM,kBAAA,GAAqB,EAAA;AAGpB,IAAM,sBAAA,GAAyB;AAC/B,IAAM,sBAAA,GAAyB;AAC/B,IAAM,uBAAA,GAA0B;AAiDvC,SAAS,MAAM,CAAA,EAAmB;AAChC,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,GAAI,GAAG,CAAA,GAAI,GAAA;AAC/B;AAEA,SAAS,YAAY,CAAA,EAA4B;AAC/C,EAAA,IAAI,CAAA,KAAM,IAAA,IAAQ,CAAA,KAAM,EAAA,SAAW,EAAC;AACpC,EAAA,OAAO,kBAAkB,CAAC,CAAA;AAC5B;AAEA,SAAS,SAAA,CAAU,KAAA,EAAe,CAAA,EAAkB,SAAA,EAA2B;AAC7E,EAAA,MAAM,IAAA,GAAO,CAAA,KAAM,IAAA,GAAO,SAAA,GAAY,OAAO,CAAC,CAAA;AAC9C,EAAA,OAAO,CAAA,EAAG,KAAK,CAAA,MAAA,EAAS,IAAI,CAAA,CAAA;AAC9B;AAEA,SAAS,eAAA,CAAgB,QAA+C,SAAA,EAA6B;AACnG,EAAA,OAAO,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,SAAA,CAAU,EAAE,KAAA,EAAO,CAAA,CAAE,CAAA,EAAG,SAAS,CAAC,CAAA;AAC7D;AAEA,SAAS,QAAA,CACP,KACA,SAAA,EACQ;AACR,EAAA,IAAI,GAAA,CAAI,KAAA,KAAU,MAAA,EAAW,OAAO,GAAA,CAAI,KAAA;AACxC,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,IAAI,GAAA,CAAI,YAAY,IAAA,IAAQ,GAAA,CAAI,YAAY,EAAA,EAAI,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,OAAO,CAAA;AACtE,EAAA,KAAA,MAAW,CAAA,IAAK,GAAA,CAAI,MAAA,EAAQ,KAAA,CAAM,IAAA,CAAK,SAAA,CAAU,CAAA,CAAE,KAAA,EAAO,CAAA,CAAE,CAAA,EAAG,SAAS,CAAC,CAAA;AACzE,EAAA,OAAO,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA,IAAK,OAAA;AAC7B;AASO,SAAS,mBAAA,CAAoB,KAAA,EAAoB,IAAA,GAAyB,EAAC,EAAiB;AACjG,EAAA,IAAI,IAAA,CAAK,QAAA,KAAa,KAAA,EAAO,cAAA,CAAe,KAAK,CAAA;AAEjD,EAAA,MAAM,MAAA,GAA4B,KAAK,MAAA,IAAU,sBAAA;AACjD,EAAA,MAAM,YAAY,MAAA,CAAO,SAAA;AAGzB,EAAA,MAAM,SAAA,GAAY;AAAA,IAChB,IAAA,EAAM,gBAAA;AAAA,IACN,IAAA,EAAM,gBAAA;AAAA,IACN,KAAA,EAAO,aAAA;AAAA,IACP,IAAA,EAAM,gBAAA;AAAA,IACN,MAAA,EAAQ;AAAA,GACV;AAEA,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAMpB;AAEH,EAAA,KAAA,MAAW,CAAA,IAAK,MAAM,KAAA,EAAO;AAC3B,IAAA,MAAM,YAAA,GAAe,WAAA,CAAY,CAAA,CAAE,OAAO,CAAA;AAC1C,IAAA,MAAM,MAAA,GAAS,eAAA,CAAgB,CAAA,CAAE,MAAA,EAAQ,SAAS,CAAA;AAClD,IAAA,MAAM,OAAA,GAAU,qBAAA;AAAA,MACd;AAAA,QACE,EAAE,KAAA,EAAO,YAAA,EAAc,IAAA,EAAM,mBAAA,EAAoB;AAAA,QACjD,EAAE,KAAA,EAAO,MAAA,EAAQ,IAAA,EAAM,iBAAA;AAAkB,OAC3C;AAAA,MACA;AAAA,KACF;AACA,IAAA,UAAA,CAAW,GAAA,CAAI,EAAE,EAAA,EAAI;AAAA,MACnB,MAAM,OAAA,CAAQ,IAAA;AAAA,MAAM,MAAM,OAAA,CAAQ,IAAA;AAAA,MAClC,MAAM,OAAA,CAAQ,IAAA;AAAA,MAAM,WAAW,OAAA,CAAQ,SAAA;AAAA,MACvC,YAAA;AAAA,MAAc,UAAA,EAAY;AAAA,KAC3B,CAAA;AAAA,EACH;AAMA,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAA4C;AACnE,EAAA,KAAA,MAAW,CAAA,IAAK,MAAM,KAAA,EAAO;AAC3B,IAAA,MAAM,GAAA,GAAgB,GAAG,CAAA,CAAE,KAAK,IAAI,CAAA,CAAE,MAAiB,CAAA,CAAA,EAAI,CAAA,CAAE,IAAI,CAAA,CAAA;AACjE,IAAA,MAAM,GAAA,GAAM,UAAA,CAAW,GAAA,CAAI,GAAG,KAAK,EAAC;AACpC,IAAA,GAAA,CAAI,KAAK,CAAC,CAAA;AACV,IAAA,UAAA,CAAW,GAAA,CAAI,KAAK,GAAG,CAAA;AAAA,EACzB;AACA,EAAA,KAAA,MAAW,GAAA,IAAO,UAAA,CAAW,MAAA,EAAO,EAAG;AACrC,IAAA,GAAA,CAAI,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,EAAE,IAAA,KAAS,CAAA,CAAE,IAAA,GAAO,CAAA,CAAE,OAAO,CAAA,CAAE,IAAA,GAAO,CAAA,CAAE,EAAA,GAAK,EAAE,EAAE,CAAA;AAAA,EACtE;AACA,EAAA,MAAM,OAAA,GAAU,CAAC,KAAA,EAAoB,GAAA,EAAc,SACjD,UAAA,CAAW,GAAA,CAAI,CAAA,EAAG,KAAK,IAAI,GAAG,CAAA,CAAA,EAAI,IAAI,CAAA,CAAE,KAAK,EAAC;AAEhD,EAAA,MAAM,WACJ,KAAA,CAAM,OAAA,KAAY,iBAAA,GAAoB,CAAC,OAAO,UAAU,CAAA,GACxD,KAAA,CAAM,OAAA,KAAY,uBAAuB,CAAC,MAAA,EAAQ,KAAK,CAAA,GACvD,CAAC,MAAM,CAAA;AAST,EAAA,MAAM,cAAc,cAAA,GAAiB,mBAAA;AAErC,EAAA,SAAS,OAAA,CAAQ,KAAc,IAAA,EAAoC;AACjE,IAAA,IAAI,CAAA,GAAI,CAAA;AACR,IAAA,KAAA,MAAW,SAAS,aAAA,EAAe;AACjC,MAAA,KAAA,MAAW,CAAA,IAAK,OAAA,CAAQ,KAAA,EAAO,GAAA,EAAK,IAAI,CAAA,EAAG;AACzC,QAAA,MAAM,EAAA,GAAK,UAAA,CAAW,GAAA,CAAI,CAAA,CAAE,EAAE,CAAA,CAAG,IAAA;AACjC,QAAA,IAAI,EAAA,GAAK,GAAG,CAAA,GAAI,EAAA;AAAA,MAClB;AAAA,IACF;AACA,IAAA,OAAO,CAAA;AAAA,EACT;AACA,EAAA,MAAM,UAAA,GAAa,CAAC,GAAA,KAClB,aAAA,CAAc,IAAA,CAAK,CAAC,KAAA,KAAU,OAAA,CAAQ,KAAA,EAAO,GAAA,EAAK,MAAM,CAAA,CAAE,SAAS,CAAC,CAAA;AACtE,EAAA,MAAM,UAAA,GAAa,CAAC,GAAA,KAClB,aAAA,CAAc,IAAA,CAAK,CAAC,KAAA,KAAU,OAAA,CAAQ,KAAA,EAAO,GAAA,EAAK,WAAW,CAAA,CAAE,SAAS,CAAC,CAAA;AAG3E,EAAA,MAAM,YAAA,GAA2B,CAAC,MAAA,EAAQ,KAAA,EAAO,UAAU,CAAA,CAAY,MAAA;AAAA,IACrE,CAAC,QAAQ,CAAC,QAAA,CAAS,SAAS,GAAG,CAAA,IAAK,WAAW,GAAG;AAAA,GACpD;AACA,EAAA,MAAM,UAAA,GAAwB,CAAC,GAAG,QAAA,EAAU,GAAG,YAAY,CAAA;AAU3D,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAsB;AAC1C,EAAA,KAAA,MAAW,OAAO,UAAA,EAAY;AAC5B,IAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,GAAG,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,gBAAA,EAAkB,OAAA,CAAQ,GAAA,EAAK,MAAM,CAAC,CAAA,GAAI,CAAA;AACnF,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,EAAK,WAAW,CAAA;AACtC,IAAA,MAAM,MAAA,GACJ,KAAA,GAAQ,CAAA,IAAK,KAAA,GAAQ,CAAA,GAAI,QAAQ,eAAA,GAAkB,KAAA,GACnD,KAAA,GAAQ,CAAA,GAAI,KAAA,GACZ,KAAA;AACF,IAAA,OAAA,CAAQ,GAAA,CAAI,GAAA,EAAK,EAAE,KAAA,EAAO,KAAA,EAAO,QAAQ,MAAA,EAAQ,CAAA,EAAG,MAAA,EAAQ,CAAA,EAAG,CAAA;AAAA,EACjE;AAIA,EAAA,SAAS,UAAA,CAAW,KAAc,SAAA,EAAyB;AACzD,IAAA,MAAM,CAAA,GAAI,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AACzB,IAAA,IAAI,CAAA,CAAE,QAAQ,CAAA,EAAG,CAAA,CAAE,SAAS,KAAA,CAAM,SAAA,GAAY,CAAA,CAAE,KAAA,GAAQ,CAAC,CAAA;AACzD,IAAA,IAAI,CAAA,CAAE,QAAQ,CAAA,EAAG;AACf,MAAA,MAAM,WAAW,CAAA,CAAE,KAAA,GAAQ,IAAI,SAAA,GAAY,CAAA,CAAE,QAAQ,eAAA,GAAkB,SAAA;AACvE,MAAA,CAAA,CAAE,MAAA,GAAS,KAAA,CAAM,QAAA,GAAW,CAAA,CAAE,QAAQ,CAAC,CAAA;AAAA,IACzC;AAAA,EACF;AAEA,EAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAC3B,IAAA,UAAA,CAAW,UAAA,CAAW,CAAC,CAAA,EAAI,WAAW,CAAA;AAAA,EACxC,CAAA,MAAO;AAEL,IAAA,MAAM,MAAA,GAAS,WAAA;AAAA,MACb;AAAA,QAAE,QAAA,EAAU,CAAA;AAAA,QAAG,QAAA,EAAU,CAAA;AAAA,QACvB,QAAA,EAAU,UAAA,CAAW,GAAA,CAAI,CAAC,GAAA,KAAQ;AAChC,UAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,CAAI,GAAG,EAAG,MAAA,GAAS,CAAA;AACxC,UAAA,OAAO,EAAE,KAAA,EAAO,IAAA,EAAM,KAAA,EAAO,IAAA,EAAK;AAAA,QACpC,CAAC;AAAA,OACH;AAAA,MACA,EAAE,YAAY,cAAA;AAAe,KAC/B;AACA,IAAA,MAAM,MAAA,GAAS,MAAA,CAAO,KAAA,GAAQ,MAAA,CAAO,KAAA;AACrC,IAAA,MAAM,OAAA,GAAU,KAAA,CAAM,WAAA,GAAc,MAAA,GAAS,CAAC,CAAA;AAC9C,IAAA,UAAA,CAAW,OAAA,CAAQ,CAAC,GAAA,EAAK,CAAA,KAAM;AAC7B,MAAA,MAAM,CAAA,GAAI,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA,CAAG,MAAA;AAC5B,MAAA,UAAA,CAAW,GAAA,EAAK,MAAM,OAAA,GAAU,MAAA,CAAO,QAAQ,CAAC,CAAA,GAAK,CAAA,GAAI,CAAC,CAAC,CAAA;AAAA,IAC7D,CAAC,CAAA;AAAA,EACH;AAGA,EAAA,IAAI,UAAA,GAAa,WAAA;AACjB,EAAA,KAAA,MAAW,OAAO,UAAA,EAAY;AAC5B,IAAA,MAAM,CAAA,GAAI,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AACzB,IAAA,MAAM,IAAI,CAAA,CAAE,KAAA,GAAQ,CAAA,GAAI,KAAA,CAAM,EAAE,MAAA,GAAS,CAAA,CAAE,KAAA,GAAQ,CAAC,IAAI,KAAA,CAAM,CAAA,CAAE,MAAA,GAAS,CAAA,CAAE,QAAQ,CAAC,CAAA;AACpF,IAAA,IAAI,CAAA,GAAI,YAAY,UAAA,GAAa,CAAA;AAAA,EACnC;AAaA,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAuB;AAC7C,EAAA,MAAM,UAAU,CAAC,KAAA,EAAoB,QAAiB,CAAA,EAAG,KAAK,IAAI,GAAG,CAAA,CAAA;AAErE,EAAA,SAAS,aAAA,CAAc,OAAoB,GAAA,EAAyB;AAClE,IAAA,MAAM,MAAA,uBAAa,GAAA,EAAoB;AACvC,IAAA,KAAA,MAAW,IAAA,IAAQ,CAAC,MAAA,EAAQ,WAAW,CAAA,EAAY;AACjD,MAAA,KAAA,MAAW,CAAA,IAAK,OAAA,CAAQ,KAAA,EAAO,GAAA,EAAK,IAAI,CAAA,EAAG;AACzC,QAAA,MAAM,CAAA,GAAI,UAAA,CAAW,GAAA,CAAI,CAAA,CAAE,EAAE,CAAA,CAAG,IAAA;AAChC,QAAA,MAAM,IAAA,GAAO,MAAA,CAAO,GAAA,CAAI,CAAA,CAAE,IAAI,CAAA,IAAK,CAAA;AACnC,QAAA,IAAI,IAAI,IAAA,EAAM,MAAA,CAAO,GAAA,CAAI,CAAA,CAAE,MAAM,CAAC,CAAA;AAAA,MACpC;AAAA,IACF;AACA,IAAA,MAAM,KAAA,GAAQ,CAAC,GAAG,MAAA,CAAO,IAAA,EAAM,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,CAAC,CAAA;AACrD,IAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,MAAU,EAAE,IAAA,EAAM,IAAA,EAAM,MAAA,CAAO,GAAA,CAAI,IAAI,CAAA,EAAI,GAAA,EAAK,GAAE,CAAE,CAAA;AAAA,EACxE;AACA,EAAA,KAAA,MAAW,SAAS,aAAA,EAAe;AACjC,IAAA,KAAA,MAAW,OAAO,UAAA,EAAY;AAC5B,MAAA,SAAA,CAAU,GAAA,CAAI,QAAQ,KAAA,EAAO,GAAG,GAAG,aAAA,CAAc,KAAA,EAAO,GAAG,CAAC,CAAA;AAAA,IAC9D;AAAA,EACF;AAGA,EAAA,SAAS,UAAU,IAAA,EAAyB;AAC1C,IAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,CAAA;AAC9B,IAAA,IAAI,CAAA,GAAI,CAAA;AACR,IAAA,KAAA,MAAW,CAAA,IAAK,IAAA,EAAM,CAAA,IAAK,CAAA,CAAE,IAAA,GAAO,gBAAA;AACpC,IAAA,OAAO,CAAA,GAAI,gBAAA;AAAA,EACb;AACA,EAAA,SAAS,SAAS,KAAA,EAA4B;AAC5C,IAAA,IAAI,IAAA,GAAO,CAAA;AACX,IAAA,IAAI,GAAA,GAAM,KAAA;AACV,IAAA,KAAA,MAAW,OAAO,UAAA,EAAY;AAC5B,MAAA,MAAM,OAAO,SAAA,CAAU,GAAA,CAAI,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAC,CAAA;AAC9C,MAAA,IAAI,IAAA,CAAK,MAAA,GAAS,CAAA,EAAG,GAAA,GAAM,IAAA;AAC3B,MAAA,MAAM,CAAA,GAAI,UAAU,IAAI,CAAA;AACxB,MAAA,IAAI,CAAA,GAAI,MAAM,IAAA,GAAO,CAAA;AAAA,IACvB;AACA,IAAA,IAAI,CAAC,GAAA,EAAK,OAAO,aAAA,GAAgB,IAAI,gBAAA,GAAmB,CAAA;AACxD,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,SAAA,GAAY,aAAA,CAAc,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,IAC9C,IAAA,EAAM,SAAS,KAAK,CAAA;AAAA,IACpB,KAAA,EAAO;AAAA,GACT,CAAE,CAAA;AAEF,EAAA,MAAM,OAAA,GAAU,UAAU,SAAA,EAAW,EAAE,SAAS,cAAA,EAAgB,QAAA,EAAU,iBAAiB,CAAA;AAK3F,EAAA,MAAM,cAAiC,EAAC;AACxC,EAAA,MAAM,QAAA,uBAAe,GAAA,EAA6B;AAElD,EAAA,SAAS,QAAA,CACP,CAAA,EACA,KAAA,EACA,IAAA,EACA,IACA,GAAA,EACM;AACN,IAAA,MAAM,CAAA,GAAI,UAAA,CAAW,GAAA,CAAI,CAAA,CAAE,EAAE,CAAA;AAC7B,IAAA,MAAM,CAAA,GAAI,MAAM,GAAG,CAAA;AACnB,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,CAAA,EAAG,SAAS,CAAA;AACnC,IAAA,MAAM,IAAA,GAAwB;AAAA,MAC5B,IAAI,CAAA,CAAE,EAAA;AAAA,MAAI,KAAA;AAAA,MAAO,IAAA;AAAA,MAAM,EAAA,EAAI,MAAM,EAAE,CAAA;AAAA,MAAG,GAAA,EAAK,CAAA;AAAA,MAC3C,MAAM,CAAA,CAAE,IAAA;AAAA,MAAM,MAAM,CAAA,CAAE,IAAA;AAAA,MACtB,IAAA,EAAM,CAAA,CAAE,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,MAAO,EAAE,GAAG,CAAA,EAAG,KAAK,KAAA,CAAM,CAAA,GAAI,CAAA,CAAE,GAAG,GAAE,CAAE,CAAA;AAAA,MACzD,SAAA,EAAW,EAAE,SAAA,CAAU,GAAA,CAAI,CAAC,CAAA,KAAM,KAAA,CAAM,CAAA,GAAI,CAAC,CAAC,CAAA;AAAA,MAC9C,SAAS,CAAA,CAAE,OAAA;AAAA,MAAS,YAAY,CAAA,CAAE,UAAA;AAAA,MAAY;AAAA,KAChD;AACA,IAAA,WAAA,CAAY,KAAK,IAAI,CAAA;AACrB,IAAA,QAAA,CAAS,GAAA,CAAI,CAAA,CAAE,EAAA,EAAI,IAAI,CAAA;AAAA,EACzB;AAEA,EAAA,KAAA,IAAS,QAAA,GAAW,CAAA,EAAG,QAAA,GAAW,aAAA,CAAc,QAAQ,QAAA,EAAA,EAAY;AAClE,IAAA,MAAM,KAAA,GAAQ,cAAc,QAAQ,CAAA;AACpC,IAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,MAAA,CAAO,QAAQ,CAAA;AACvC,IAAA,KAAA,MAAW,OAAO,UAAA,EAAY;AAC5B,MAAA,MAAM,CAAA,GAAI,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AACzB,MAAA,MAAM,OAAO,SAAA,CAAU,GAAA,CAAI,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAC,CAAA;AAC9C,MAAA,MAAM,SAAA,uBAAgB,GAAA,EAAoB;AAC1C,MAAA,IAAI,CAAA,GAAI,OAAA;AACR,MAAA,KAAA,MAAW,KAAK,IAAA,EAAM;AACpB,QAAA,CAAA,CAAE,GAAA,GAAM,MAAM,CAAC,CAAA;AACf,QAAA,SAAA,CAAU,GAAA,CAAI,CAAA,CAAE,IAAA,EAAM,CAAA,CAAE,GAAG,CAAA;AAC3B,QAAA,CAAA,GAAI,KAAA,CAAM,CAAA,GAAI,CAAA,CAAE,IAAA,GAAO,gBAAgB,CAAA;AAAA,MACzC;AACA,MAAA,IAAI,CAAA,CAAE,QAAQ,CAAA,EAAG;AACf,QAAA,KAAA,MAAW,CAAA,IAAK,OAAA,CAAQ,KAAA,EAAO,GAAA,EAAK,MAAM,CAAA,EAAG;AAC3C,UAAA,QAAA,CAAS,CAAA,EAAG,OAAO,MAAA,EAAQ,CAAA,CAAE,QAAQ,SAAA,CAAU,GAAA,CAAI,CAAA,CAAE,IAAI,CAAE,CAAA;AAAA,QAC7D;AAAA,MACF;AACA,MAAA,IAAI,CAAA,CAAE,QAAQ,CAAA,EAAG;AACf,QAAA,KAAA,MAAW,CAAA,IAAK,OAAA,CAAQ,KAAA,EAAO,GAAA,EAAK,WAAW,CAAA,EAAG;AAChD,UAAA,QAAA,CAAS,CAAA,EAAG,OAAO,WAAA,EAAa,CAAA,CAAE,QAAQ,SAAA,CAAU,GAAA,CAAI,CAAA,CAAE,IAAI,CAAE,CAAA;AAAA,QAClE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAoCA,EAAA,MAAM,WAAkC,EAAC;AACzC,EAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAI,KAAA,CAAM,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,EAAA,EAAI,CAAC,CAAC,CAAC,CAAA;AAGzD,EAAA,MAAM,gBAAgB,IAAI,GAAA;AAAA,IACxB,aAAA,CAAc,IAAI,CAAC,CAAA,EAAG,MAAM,CAAC,CAAA,EAAG,CAAC,CAAC;AAAA,GACpC;AAGA,EAAA,SAAS,UAAU,EAAA,EAA6B;AAC9C,IAAA,OAAO,KAAA,CAAM,EAAA,CAAG,GAAA,GAAM,EAAA,CAAG,IAAI,CAAA;AAAA,EAC/B;AAGA,EAAA,SAAS,WAAW,KAAA,EAA4B;AAC9C,IAAA,MAAM,GAAA,GAAM,aAAA,CAAc,OAAA,CAAQ,KAAK,CAAA;AACvC,IAAA,OAAO,KAAA,CAAM,QAAQ,MAAA,CAAO,GAAG,IAAK,SAAA,CAAU,GAAG,EAAG,IAAI,CAAA;AAAA,EAC1D;AAKA,EAAA,MAAM,WAAA,uBAAkB,GAAA,EAAsB;AAC9C,EAAA,KAAA,MAAW,KAAA,IAAS,MAAM,MAAA,EAAQ;AAChC,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA;AACpC,IAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,GAAA,CAAI,KAAA,CAAM,MAAM,CAAA;AACxC,IAAA,IAAI,KAAA,KAAU,MAAA,IAAa,OAAA,KAAY,MAAA,EAAW;AAClD,IAAA,IAAI,OAAA,CAAQ,IAAA,KAAS,MAAA,IAAU,KAAA,CAAM,SAAS,MAAA,EAAQ;AACpD,MAAA,MAAM,MAAM,WAAA,CAAY,GAAA,CAAI,KAAA,CAAM,IAAI,KAAK,EAAC;AAC5C,MAAA,GAAA,CAAI,IAAA,CAAK,MAAM,EAAE,CAAA;AACjB,MAAA,WAAA,CAAY,GAAA,CAAI,KAAA,CAAM,IAAA,EAAM,GAAG,CAAA;AAAA,IACjC;AAAA,EACF;AAGA,EAAA,MAAM,oBAAA,uBAA2B,GAAA,EAAoB;AAGrD,EAAA,MAAM,sBAAA,uBAA6B,GAAA,EAAoB;AAEvD,EAAA,KAAA,MAAW,KAAA,IAAS,MAAM,MAAA,EAAQ;AAChC,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,GAAA,CAAI,KAAA,CAAM,MAAM,CAAA;AAC1C,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA;AACtC,IAAA,IAAI,QAAA,KAAa,MAAA,IAAa,MAAA,KAAW,MAAA,EAAW;AAEpD,IAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,GAAA,CAAI,KAAA,CAAM,MAAM,CAAA;AACxC,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA;AAEpC,IAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,IAAA,KAAS,MAAA,IAAU,MAAM,IAAA,KAAS,WAAA;AAC9D,IAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,IAAA,KAAS,MAAA,IAAU,MAAM,IAAA,KAAS,MAAA;AAE/D,IAAA,IAAI,WAAA,EAAa;AAEf,MAAA,MAAM,GAAA,GAAM,sBAAA,CAAuB,GAAA,CAAI,KAAA,CAAM,MAAM,CAAA,IAAK,CAAA;AACxD,MAAA,sBAAA,CAAuB,GAAA,CAAI,KAAA,CAAM,MAAA,EAAQ,GAAA,GAAM,CAAC,CAAA;AAEhD,MAAA,MAAM,WAAW,KAAA,CAAM,QAAA,CAAS,EAAA,GAAK,QAAA,CAAS,OAAO,CAAC,CAAA;AACtD,MAAA,MAAM,WAAW,KAAA,CAAM,MAAA,CAAO,GAAA,GAAM,MAAA,CAAO,OAAO,CAAC,CAAA;AACnD,MAAA,MAAM,QAAQ,KAAA,CAAM,MAAA,CAAO,EAAA,GAAK,MAAA,CAAO,OAAO,CAAC,CAAA;AAI/C,MAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,MAAA,KAAW,KAAA,CAAM,MAAA;AAE5C,MAAA,IAAI,MAAA;AAEJ,MAAA,IAAI,UAAA,EAAY;AAEd,QAAA,MAAA,GAAS;AAAA,UACP,EAAE,GAAG,KAAA,CAAM,QAAQ,GAAG,CAAA,EAAG,KAAA,CAAM,QAAQ,CAAA,EAAE;AAAA,UACzC,EAAE,GAAG,KAAA,CAAM,KAAK,GAAM,CAAA,EAAG,KAAA,CAAM,QAAQ,CAAA;AAAE,SAC3C;AAAA,MACF,CAAA,MAAO;AAKL,QAAA,MAAM,UAAA,GAAa,KAAA,CAAM,cAAA,GAAiB,CAAC,CAAA;AAC3C,QAAA,MAAM,WAAA,GAAc,KAAA,CAAM,eAAA,GAAkB,CAAC,CAAA;AAE7C,QAAA,MAAM,MAAA,GAAS,KAAA,CAAM,QAAA,GAAA,CAAY,GAAA,GAAM,KAAK,UAAU,CAAA;AACtD,QAAA,MAAM,UAAA,GAAa,KAAA,CAAM,KAAA,GAAA,CAAS,GAAA,GAAM,KAAK,WAAW,CAAA;AACxD,QAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,OAAA,CAAQ,KAAK,CAAA;AACtC,QAAA,MAAM,SAAA,GAAY,KAAA,CAAM,KAAA,GAAQ,mBAAA,GAAsB,MAAM,kBAAkB,CAAA;AAE9E,QAAA,MAAA,GAAS;AAAA,UACP,EAAE,GAAG,KAAA,CAAM,QAAQ,GAAK,CAAA,EAAG,KAAA,CAAM,QAAQ,CAAA,EAAE;AAAA;AAAA,UAC3C,EAAE,GAAG,KAAA,CAAM,MAAM,GAAO,CAAA,EAAG,KAAA,CAAM,QAAQ,CAAA,EAAE;AAAA;AAAA,UAC3C,EAAE,GAAG,KAAA,CAAM,MAAM,GAAO,CAAA,EAAG,KAAA,CAAM,SAAS,CAAA,EAAE;AAAA;AAAA,UAC5C,EAAE,GAAG,KAAA,CAAM,UAAU,GAAG,CAAA,EAAG,KAAA,CAAM,SAAS,CAAA,EAAE;AAAA;AAAA,UAC5C,EAAE,GAAG,KAAA,CAAM,UAAU,GAAG,CAAA,EAAG,KAAA,CAAM,QAAQ,CAAA,EAAE;AAAA;AAAA,UAC3C,EAAE,GAAG,KAAA,CAAM,KAAK,GAAQ,CAAA,EAAG,KAAA,CAAM,QAAQ,CAAA;AAAE;AAAA,SAC7C;AAAA,MACF;AAEA,MAAA,QAAA,CAAS,IAAA,CAAK;AAAA,QACZ,MAAA,EAAQ,yBAAyB,KAAA,CAAM,EAAA;AAAA,QACvC,IAAA,EAAM,WAAA;AAAA,QACN,MAAA;AAAA,QACA,KAAA,EAAO,CAAA,EAAG,MAAA,CAAO,UAAA,CAAW,SAAS,KAAK,QAAA,CAAS,KAAK,CAAA,QAAA,EAAM,MAAA,CAAO,KAAK,CAAA,CAAA;AAAA,QAC1E,OAAA,EAAS;AAAA,OACV,CAAA;AAAA,IACH,WAAW,YAAA,EAAc;AAEvB,MAAA,MAAM,YAAA,GAAe,aAAA,CAAc,GAAA,CAAI,OAAA,CAAQ,KAAK,CAAA;AACpD,MAAA,MAAM,UAAA,GAAa,aAAA,CAAc,GAAA,CAAI,KAAA,CAAM,KAAK,CAAA;AAChD,MAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,KAAA,KAAU,KAAA,CAAM,KAAA;AAC5C,MAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,MAAA,KAAW,KAAA,CAAM,MAAA;AAC3C,MAAA,MAAM,YAAY,UAAA,IAAc,YAAA;AAGhC,MAAA,MAAM,WAAW,WAAA,CAAY,GAAA,CAAI,KAAA,CAAM,IAAI,KAAK,EAAC;AACjD,MAAA,IAAI,UAAA,GAAa,oBAAA,CAAqB,GAAA,CAAI,KAAA,CAAM,EAAE,CAAA,IAAK,CAAA;AACvD,MAAA,IAAI,CAAC,oBAAA,CAAqB,GAAA,CAAI,KAAA,CAAM,EAAE,CAAA,EAAG;AACvC,QAAA,UAAA,GAAa,QAAA,CAAS,OAAA,CAAQ,KAAA,CAAM,EAAE,CAAA;AACtC,QAAA,oBAAA,CAAqB,GAAA,CAAI,KAAA,CAAM,EAAA,EAAI,UAAU,CAAA;AAAA,MAC/C;AACA,MAAA,MAAM,YAAY,QAAA,CAAS,MAAA;AAG3B,MAAA,MAAM,eAAA,GAAkB,KAAA,CAAM,MAAA,CAAO,IAAA,GAAO,CAAC,CAAA;AAC7C,MAAA,MAAM,aAAa,SAAA,GAAY,CAAA,GAAI,MAAM,eAAA,IAAmB,SAAA,GAAY,EAAE,CAAA,GAAI,CAAA;AAC9E,MAAA,MAAM,YAAY,KAAA,CAAM,MAAA,CAAO,KAAK,eAAA,GAAkB,CAAA,GAAI,aAAa,UAAU,CAAA;AACjF,MAAA,MAAM,QAAQ,MAAA,CAAO,GAAA;AAErB,MAAA,IAAI,eAAe,SAAA,EAAW;AAK5B,QAAA,MAAM,UAAA,GAAa,UAAU,QAAQ,CAAA;AACrC,QAAA,MAAM,MAAA,GAAS,KAAA,CAAM,QAAA,CAAS,EAAE,CAAA;AAChC,QAAA,MAAM,IAAA,GAAO,KAAA,CAAM,MAAA,CAAO,EAAE,CAAA;AAC5B,QAAA,MAAM,KAAA,GAAQ,MAAA,KAAW,IAAA,GAAO,MAAA,GAAS,IAAA;AACzC,QAAA,QAAA,CAAS,IAAA,CAAK;AAAA,UACZ,MAAA,EAAQ,yBAAyB,KAAA,CAAM,EAAA;AAAA,UACvC,IAAA,EAAM,MAAA;AAAA,UACN,MAAA,EAAQ;AAAA,YACN,EAAE,CAAA,EAAG,MAAA,EAAQ,CAAA,EAAG,KAAA,CAAM,UAAU,CAAA,EAAE;AAAA,YAClC,EAAE,CAAA,EAAG,KAAA,EAAQ,CAAA,EAAG,KAAA,CAAM,KAAK,CAAA;AAAE,WAC/B;AAAA,UACA,KAAA,EAAO,CAAA,EAAG,MAAA,CAAO,UAAA,CAAW,IAAI,KAAK,QAAA,CAAS,KAAK,CAAA,QAAA,EAAM,MAAA,CAAO,KAAK,CAAA,CAAA;AAAA,UACrE,OAAA,EAAS;AAAA,SACV,CAAA;AAAA,MACH,CAAA,MAAA,IAAW,aAAa,SAAA,EAAW;AAIjC,QAAA,MAAM,UAAA,GAAa,UAAU,QAAQ,CAAA;AACrC,QAAA,IAAI,SAAA,IAAa,KAAK,KAAA,CAAM,QAAA,CAAS,EAAE,CAAA,KAAM,KAAA,CAAM,MAAA,CAAO,EAAE,CAAA,EAAG;AAE7D,UAAA,QAAA,CAAS,IAAA,CAAK;AAAA,YACZ,MAAA,EAAQ,yBAAyB,KAAA,CAAM,EAAA;AAAA,YACvC,IAAA,EAAM,MAAA;AAAA,YACN,MAAA,EAAQ;AAAA,cACN,EAAE,GAAG,KAAA,CAAM,QAAA,CAAS,EAAE,CAAA,EAAG,CAAA,EAAG,KAAA,CAAM,UAAU,CAAA,EAAE;AAAA,cAC9C,EAAE,GAAG,KAAA,CAAM,MAAA,CAAO,EAAE,CAAA,EAAK,CAAA,EAAG,KAAA,CAAM,KAAK,CAAA;AAAE,aAC3C;AAAA,YACA,KAAA,EAAO,CAAA,EAAG,MAAA,CAAO,UAAA,CAAW,IAAI,KAAK,QAAA,CAAS,KAAK,CAAA,QAAA,EAAM,MAAA,CAAO,KAAK,CAAA,CAAA;AAAA,YACrE,OAAA,EAAS;AAAA,WACV,CAAA;AAAA,QACH,CAAA,MAAO;AAEL,UAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,GAAA,CAAI,OAAA,CAAQ,KAAK,CAAA;AAC7C,UAAA,MAAM,MAAA,GAAS,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,KAAK,CAAA,GAAK,SAAA,CAAU,KAAK,CAAA,CAAG,IAAA,GAAO,eAAA,GAAkB,CAAC,CAAA;AAC1F,UAAA,QAAA,CAAS,IAAA,CAAK;AAAA,YACZ,MAAA,EAAQ,yBAAyB,KAAA,CAAM,EAAA;AAAA,YACvC,IAAA,EAAM,MAAA;AAAA,YACN,MAAA,EAAQ;AAAA,cACN,EAAE,GAAG,KAAA,CAAM,QAAA,CAAS,EAAE,CAAA,EAAG,CAAA,EAAG,KAAA,CAAM,UAAU,CAAA,EAAE;AAAA,cAC9C,EAAE,GAAG,KAAA,CAAM,QAAA,CAAS,EAAE,CAAA,EAAG,CAAA,EAAG,KAAA,CAAM,MAAM,CAAA,EAAE;AAAA,cAC1C,EAAE,GAAG,KAAA,CAAM,SAAS,GAAK,CAAA,EAAG,KAAA,CAAM,MAAM,CAAA,EAAE;AAAA,cAC1C,EAAE,GAAG,KAAA,CAAM,SAAS,GAAK,CAAA,EAAG,KAAA,CAAM,KAAK,CAAA;AAAE,aAC3C;AAAA,YACA,KAAA,EAAO,CAAA,EAAG,MAAA,CAAO,UAAA,CAAW,IAAI,KAAK,QAAA,CAAS,KAAK,CAAA,QAAA,EAAM,MAAA,CAAO,KAAK,CAAA,CAAA;AAAA,YACrE,OAAA,EAAS;AAAA,WACV,CAAA;AAAA,QACH;AAAA,MACF,CAAA,MAAO;AAIL,QAAA,MAAM,UAAA,GAAa,UAAU,QAAQ,CAAA;AACrC,QAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,GAAA,CAAI,OAAA,CAAQ,KAAK,CAAA;AAC7C,QAAA,MAAM,MAAA,GAAS,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,KAAK,CAAA,GAAK,SAAA,CAAU,KAAK,CAAA,CAAG,IAAA,GAAO,eAAA,GAAkB,CAAC,CAAA;AAE1F,QAAA,MAAM,MAAA,GAAS,KAAA,CAAM,QAAA,CAAS,EAAE,CAAA;AAChC,QAAA,IAAI,KAAA,CAAM,MAAM,CAAA,KAAM,KAAA,CAAM,SAAS,CAAA,EAAG;AAEtC,UAAA,QAAA,CAAS,IAAA,CAAK;AAAA,YACZ,MAAA,EAAQ,0BAA0B,KAAA,CAAM,EAAA;AAAA,YACxC,IAAA,EAAM,OAAA;AAAA,YACN,MAAA,EAAQ;AAAA,cACN,EAAE,CAAA,EAAG,MAAA,EAAkB,CAAA,EAAG,KAAA,CAAM,UAAU,CAAA,EAAE;AAAA,cAC5C,EAAE,GAAG,KAAA,CAAM,SAAS,GAAG,CAAA,EAAG,KAAA,CAAM,KAAK,CAAA;AAAE,aACzC;AAAA,YACA,KAAA,EAAO,CAAA,EAAG,MAAA,CAAO,UAAA,CAAW,KAAK,KAAK,QAAA,CAAS,KAAK,CAAA,QAAA,EAAM,MAAA,CAAO,KAAK,CAAA,CAAA;AAAA,YACtE,OAAA,EAAS;AAAA,WACV,CAAA;AAAA,QACH,CAAA,MAAO;AACL,UAAA,QAAA,CAAS,IAAA,CAAK;AAAA,YACZ,MAAA,EAAQ,0BAA0B,KAAA,CAAM,EAAA;AAAA,YACxC,IAAA,EAAM,OAAA;AAAA,YACN,MAAA,EAAQ;AAAA,cACN,EAAE,CAAA,EAAG,MAAA,EAAkB,CAAA,EAAG,KAAA,CAAM,UAAU,CAAA,EAAE;AAAA,cAC5C,EAAE,CAAA,EAAG,MAAA,EAAkB,CAAA,EAAG,KAAA,CAAM,MAAM,CAAA,EAAE;AAAA,cACxC,EAAE,GAAG,KAAA,CAAM,SAAS,GAAG,CAAA,EAAG,KAAA,CAAM,MAAM,CAAA,EAAE;AAAA,cACxC,EAAE,GAAG,KAAA,CAAM,SAAS,GAAG,CAAA,EAAG,KAAA,CAAM,KAAK,CAAA;AAAE,aACzC;AAAA,YACA,KAAA,EAAO,CAAA,EAAG,MAAA,CAAO,UAAA,CAAW,KAAK,KAAK,QAAA,CAAS,KAAK,CAAA,QAAA,EAAM,MAAA,CAAO,KAAK,CAAA,CAAA;AAAA,YACtE,OAAA,EAAS;AAAA,WACV,CAAA;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EAEF;AAGA,EAAA,MAAM,UAAU,OAAA,CAAQ,MAAA;AACxB,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,UAAA,GAAa,cAAc,CAAA;AAGjD,EAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,GAAA,CAAI,CAAC,OAAO,CAAA,KAAM;AAC5C,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA;AAC/B,IAAA,MAAM,IAAA,GAAO,SAAA,CAAU,CAAC,CAAA,CAAG,IAAA;AAC3B,IAAA,OAAO;AAAA,MACL,KAAA;AAAA,MACA,MAAA;AAAA,MACA,IAAA;AAAA,MACA,MAAA,EAAQ,cAAA;AAAA,MACR,OAAA,EAAS,KAAA,CAAM,MAAA,GAAS,IAAA,GAAO,CAAC;AAAA,KAClC;AAAA,EACF,CAAC,CAAA;AAED,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,OAAA;AAAA,IACP,MAAA,EAAQ,OAAA;AAAA,IACR,KAAA,EAAO,WAAA;AAAA,IACP,QAAA;AAAA,IACA,KAAA;AAAA,IACA,SAAS,KAAA,CAAM;AAAA,GACjB;AACF;;;ACxqBA,IAAM,UAAA,GAAa,SAAA;AACnB,IAAM,YAAA,GAAe,CAAA;AACrB,IAAM,QAAA,GAAW,MAAA;AACjB,IAAM,MAAA,GAAS,CAAA;AACf,IAAM,YAAA,GAAe,SAAA;AACrB,IAAM,UAAA,GAAa,SAAA;AACnB,IAAM,YAAA,GAAe,SAAA;AACrB,IAAM,cAAA,GAAiB,GAAA;AACvB,IAAM,UAAA,GAAa,SAAA;AACnB,IAAM,eAAA,GAAkB,SAAA;AACxB,IAAM,eAAA,GAAkB,EAAA;AAExB,SAASA,OAAM,CAAA,EAAmB;AAChC,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,GAAI,GAAG,CAAA,GAAI,GAAA;AAC/B;AAIA,SAAS,QAAQ,CAAA,EAA4B;AAC3C,EAAA,MAAM,IAAIA,MAAAA,CAAM,CAAA,CAAE,EAAA,GAAK,CAAA,CAAE,OAAO,CAAC,CAAA;AACjC,EAAA,MAAM,IAAI,CAAA,CAAE,GAAA;AACZ,EAAA,MAAM,QAAkB,EAAC;AAGzB,EAAA,KAAA,CAAM,IAAA;AAAA,IACJ,YAAY,CAAC,CAAA,KAAA,EAAQ,CAAC,CAAA,SAAA,EAAY,EAAE,IAAI,CAAA,UAAA,EAAa,CAAA,CAAE,IAAI,SACpD,MAAM,CAAA,QAAA,EAAW,QAAQ,CAAA,UAAA,EAAa,UAAU,mBAAmB,YAAY,CAAA,GAAA;AAAA,GACxF;AAGA,EAAA,KAAA,MAAW,EAAA,IAAM,EAAE,SAAA,EAAW;AAC5B,IAAA,KAAA,CAAM,IAAA;AAAA,MACJ,CAAA,UAAA,EAAa,CAAC,CAAA,MAAA,EAAS,EAAE,CAAA,MAAA,EAASA,MAAAA,CAAM,CAAA,GAAI,CAAA,CAAE,IAAI,CAAC,CAAA,MAAA,EAAS,EAAE,aACnD,UAAU,CAAA,oBAAA;AAAA,KACvB;AAAA,EACF;AAGA,EAAA,KAAA,IAAS,KAAK,CAAA,EAAG,EAAA,GAAK,CAAA,CAAE,IAAA,CAAK,QAAQ,EAAA,EAAA,EAAM;AACzC,IAAA,MAAM,GAAA,GAAM,CAAA,CAAE,IAAA,CAAK,EAAE,CAAA;AACrB,IAAA,MAAM,YAAY,EAAA,KAAO,CAAA;AACzB,IAAA,MAAM,OAAO,GAAA,CAAI,IAAA;AACjB,IAAA,MAAM,IAAA,GAAO,YAAY,YAAA,GAAe,UAAA;AACxC,IAAA,MAAM,KAAA,GAAQ,YACVA,MAAAA,CAAM,CAAA,CAAE,EAAE,CAAA,GACVA,MAAAA,CAAM,IAAI,CAAC,CAAA;AAEf,IAAA,KAAA,IAAS,KAAK,CAAA,EAAG,EAAA,GAAK,GAAA,CAAI,KAAA,CAAM,QAAQ,EAAA,EAAA,EAAM;AAC5C,MAAA,MAAM,IAAA,GAAO,GAAA,CAAI,KAAA,CAAM,EAAE,CAAA;AACzB,MAAA,MAAM,QAAQA,MAAAA,CAAM,GAAA,CAAI,GAAA,GAAM,EAAA,GAAK,KAAK,IAAI,CAAA;AAC5C,MAAA,MAAM,UAAA,GAAa,YAAY,CAAA,qBAAA,CAAA,GAA0B,EAAA;AACzD,MAAA,MAAM,UAAA,GAAa,YAAY,CAAA,mBAAA,CAAA,GAAwB,EAAA;AACvD,MAAA,KAAA,CAAM,IAAA;AAAA,QACJ,YAAY,KAAK,CAAA,KAAA,EAAQ,KAAK,CAAA,eAAA,EAAkB,WAAW,CAAA,aAAA,EAC7C,IAAI,CAAA,QAAA,EAAW,IAAI,IAAI,UAAU,CAAA,EAAG,UAAU,CAAA,CAAA,EAAI,SAAA,CAAU,IAAI,CAAC,CAAA,OAAA;AAAA,OACjF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,KAAA,CAAM,KAAK,EAAE,CAAA;AACtB;AAIA,SAAS,UAAU,EAAA,EAAiC;AAClD,EAAA,MAAM,SAAS,EAAA,CAAG,MAAA;AAClB,EAAA,IAAI,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG,OAAO,EAAA;AAG9B,EAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,EAAA,CAAG,OAAA,EAAS,OAAO,CAAA;AAC5C,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,MAAA,CAAO,MAAA,GAAS,CAAC,CAAA;AAGrC,EAAA,IAAI,WAAW,IAAA,CAAK,CAAA;AACpB,EAAA,IAAI,WAAW,IAAA,CAAK,CAAA;AACpB,EAAA,IAAI,GAAG,OAAA,KAAY,MAAA,aAAmBA,MAAAA,CAAM,IAAA,CAAK,IAAI,KAAK,CAAA;AAAA,OAAA,IACjD,GAAG,OAAA,KAAY,OAAA,aAAoBA,MAAAA,CAAM,IAAA,CAAK,IAAI,KAAK,CAAA;AAAA,OAAA,IACvD,GAAG,OAAA,KAAY,MAAA,aAAmBA,MAAAA,CAAM,IAAA,CAAK,IAAI,KAAK,CAAA;AAAA,OAC1D,QAAA,GAAWA,MAAAA,CAAM,IAAA,CAAK,CAAA,GAAI,KAAK,CAAA;AAGpC,EAAA,MAAM,UAAA,GAAa;AAAA,IACjB,GAAG,MAAA,CAAO,KAAA,CAAM,GAAG,MAAA,CAAO,MAAA,GAAS,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,MAAO,EAAE,CAAA,EAAG,CAAA,CAAE,GAAG,CAAA,EAAG,CAAA,CAAE,GAAE,CAAE,CAAA;AAAA,IACrE,EAAE,CAAA,EAAG,QAAA,EAAU,CAAA,EAAG,QAAA;AAAS,GAC7B;AAEA,EAAA,MAAM,OAAA,GAAU,SAAS,UAAU,CAAA;AACnC,EAAA,MAAM,QAAA,GAAW,iBAAA,CAAkB,EAAE,CAAA,EAAG,IAAA,CAAK,CAAA,EAAG,CAAA,EAAG,IAAA,CAAK,CAAA,EAAE,EAAG,EAAA,CAAG,OAAO,CAAA;AAEvE,EAAA,OACE,CAAA,OAAA,EAAU,SAAA,CAAU,EAAA,CAAG,KAAK,CAAC,CAAA,iBAAA,EACjB,OAAO,CAAA,UAAA,EAAa,YAAY,CAAA,gBAAA,EAAmB,cAAc,CAAA,gCAAA,EACzD,QAAQ,WAAW,UAAU,CAAA,iBAAA,CAAA;AAErD;AAIA,SAAS,aAAA,CACP,KAAA,EACA,MAAA,EACA,OAAA,EACA,eAAA,EACQ;AACR,EAAA,MAAM,IAAA,GAAO,eAAA,CAAgB,MAAA,CAAO,KAAK,CAAA;AACzC,EAAA,MAAM,QAAA,GAAWA,MAAAA,CAAM,MAAA,GAAS,mBAAA,GAAsB,CAAC,CAAA;AACvD,EAAA,OACE,CAAA,SAAA,EAAY,QAAQ,CAAA,KAAA,EAAQA,MAAAA,CAAM,OAAO,CAAC,CAAA,eAAA,EAAkB,WAAW,CAAA,aAAA,EACzD,eAAe,WAAW,eAAe,CAAA,6CAAA,EAC9B,QAAQ,CAAA,CAAA,EAAIA,MAAAA,CAAM,OAAO,CAAC,CAAA,GAAA,EAAM,SAAA,CAAU,IAAI,CAAC,CAAA,OAAA,CAAA;AAE5E;AAIA,SAAS,kBAAA,CACP,QACA,SAAA,EACe;AACf,EAAA,MAAM,OAAA,GAAU,OAAO,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,MAAM,CAAA;AAC1D,EAAA,MAAM,OAAA,GAAU,OAAO,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,WAAW,CAAA;AAC/D,EAAA,MAAM,UAAyB,EAAC;AAEhC,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,KAAA,EAAO,UAAU,MAAA,CAAO,IAAA;AAAA,MACxB,MAAA,EAAQ,CAAC,CAAA,EAAG,EAAA,KACV,YAAY,CAAC,CAAA,KAAA,EAAQA,MAAAA,CAAM,EAAA,GAAK,CAAC,CAAC,CAAA,sCAAA,EACzB,QAAQ,aAAa,UAAU,CAAA,oBAAA;AAAA,KAE3C,CAAA;AAAA,EACH;AACA,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,KAAA,EAAO,UAAU,MAAA,CAAO,SAAA;AAAA,MACxB,MAAA,EAAQ,CAAC,CAAA,EAAG,EAAA,KACV,YAAY,CAAC,CAAA,KAAA,EAAQA,MAAAA,CAAM,EAAA,GAAK,CAAC,CAAC,CAAA,sCAAA,EACzB,QAAQ,aAAa,UAAU,CAAA,2CAAA;AAAA,KAE3C,CAAA;AAAA,EACH;AACA,EAAA,OAAO,OAAA;AACT;AAcO,SAAS,eAAA,CAAgB,MAAA,EAAsB,IAAA,GAAsB,EAAC,EAAW;AACtF,EAAA,MAAM,SAAA,GAA6B,KAAK,SAAA,IAAa,oBAAA;AACrD,EAAA,MAAM,eAAA,GAAqC,KAAK,WAAA,IAAe,sBAAA;AAC/D,EAAA,MAAM,QAAA,GAAW,KAAK,MAAA,KAAW,KAAA;AAGjC,EAAA,MAAM,QAAkB,EAAC;AAGzB,EAAA,KAAA,MAAW,IAAA,IAAQ,OAAO,KAAA,EAAO;AAC/B,IAAA,KAAA,CAAM,IAAA,CAAK,cAAc,IAAA,CAAK,KAAA,EAAO,KAAK,MAAA,EAAQ,IAAA,CAAK,OAAA,EAAS,eAAe,CAAC,CAAA;AAAA,EAClF;AAGA,EAAA,KAAA,MAAW,CAAA,IAAK,OAAO,KAAA,EAAO;AAC5B,IAAA,MAAM,MAAA,GAAS,QAAQ,CAAC,CAAA;AACxB,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,kBAAA,EAAqB,CAAA,CAAE,EAAE,CAAA,SAAA,EAAY,SAAA,CAAU,CAAA,CAAE,KAAK,CAAC,CAAA,QAAA,EAAW,MAAM,CAAA,IAAA,CAAM,CAAA;AAAA,EAC3F;AAGA,EAAA,KAAA,MAAW,EAAA,IAAM,OAAO,QAAA,EAAU;AAChC,IAAA,MAAM,QAAA,GAAW,UAAU,EAAE,CAAA;AAC7B,IAAA,KAAA,CAAM,KAAK,CAAA,iBAAA,EAAoB,EAAA,CAAG,MAAM,CAAA,EAAA,EAAK,QAAQ,CAAA,IAAA,CAAM,CAAA;AAAA,EAC7D;AAEA,EAAA,IAAI,IAAI,MAAA,CAAO,KAAA;AACf,EAAA,IAAI,IAAI,MAAA,CAAO,MAAA;AAGf,EAAA,IAAI,SAAA,GAAY,EAAA;AAChB,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,MAAM,OAAA,GAAU,kBAAA,CAAmB,MAAA,EAAQ,SAAS,CAAA;AACpD,IAAA,MAAM,EAAA,GAAK,WAAA,CAAY,OAAA,EAAS,CAAC,CAAA;AACjC,IAAA,SAAA,GAAY,EAAA,CAAG,GAAA;AACf,IAAA,IAAI,OAAA,CAAQ,SAAS,CAAA,EAAG;AACtB,MAAA,CAAA,GAAI,KAAK,GAAA,CAAI,CAAA,EAAG,EAAA,CAAG,KAAA,GAAQ,KAAK,CAAC,CAAA;AACjC,MAAA,CAAA,GAAI,EAAA,CAAG,MAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,CAAA,GAAIA,OAAM,CAAC,CAAA;AACX,EAAA,CAAA,GAAIA,OAAM,CAAC,CAAA;AAEX,EAAA,OACE,kDAAkD,CAAC,CAAA,UAAA,EAAa,CAAC,CAAA,eAAA,EAAkB,CAAC,IAAI,CAAC,CAAA,yBAAA,EAC/D,SAAA,CAAU,SAAA,CAAU,SAAS,CAAC,CAAA,EAAA,CAAA,GACxD,MAAM,IAAA,CAAK,EAAE,IACb,SAAA,GACA,CAAA,MAAA,CAAA;AAEJ;;;AChOO,SAAS,SAAA,CACd,KAAA,EACA,IAAA,GAAyB,EAAC,EACa;AACvC,EAAA,MAAM,MAAA,GAAS,mBAAA,CAAoB,KAAA,EAAO,IAAI,CAAA;AAC9C,EAAA,MAAM,GAAA,GAAM,eAAA,CAAgB,MAAA,EAAQ,IAAI,CAAA;AACxC,EAAA,OAAO,EAAE,KAAK,MAAA,EAAO;AACvB","file":"chunk-BM7UJBK5.js","sourcesContent":["// PRISMA 2020 flow diagram — input model.\n// Declared facts only: the caller declares boxes, arrows, and variant.\n// NO arithmetic anywhere — honesty rule: the author's figures are drawn faithfully,\n// never summed, reconciled, or validated for mathematical consistency.\n\n/** The three standard PRISMA phases, in display order. */\nexport const PRISMA_PHASES = [\"identification\", \"screening\", \"included\"] as const;\nexport type PrismaPhase = (typeof PRISMA_PHASES)[number];\n\n/** Main-column step vs right side-box (exclusion reasons). */\nexport const PRISMA_BOX_KINDS = [\"flow\", \"exclusion\"] as const;\nexport type PrismaBoxKind = (typeof PRISMA_BOX_KINDS)[number];\n\n/** Single-column default + two-column prior variant. */\nexport const PRISMA_COLUMNS = [\"main\", \"new\", \"previous\"] as const;\nexport type PrismaColumn = (typeof PRISMA_COLUMNS)[number];\n\n/**\n * A single count line in a box. `n: null` draws the localized \"n = —\" token.\n * NEVER inferred or summed — each figure is verbatim as the author declared it.\n */\nexport interface PrismaCount {\n label: string;\n n: number | null;\n}\n\n/**\n * A single PRISMA box — a flow step or an exclusion reason side-box.\n *\n * @property id Unique identifier (within the boxes namespace).\n * @property phase Which band the box belongs to.\n * @property kind \"flow\" = main-column step; \"exclusion\" = right side-box.\n * @property column Which column within the band. Validation defaults absent → \"main\".\n * @property rank Declared vertical order within (phase, column), 0-based top→down.\n * This is the AUTHOR's claim, never derived.\n * @property heading Verbatim header text (e.g. \"Records identified from:\"), or null.\n * @property counts Verbatim count lines (zero allowed).\n * @property title Optional <title> override; defaults to heading + counts.\n */\nexport interface PrismaBox {\n id: number;\n phase: PrismaPhase;\n kind: PrismaBoxKind;\n column: PrismaColumn;\n rank: number;\n heading: string | null;\n counts: PrismaCount[];\n title?: string;\n}\n\n/**\n * A declared flow arrow. Direction is determined by geometry (flow→exclusion = horizontal;\n * flow→flow = vertical). NO direction flag — the layout decides from box positions.\n */\nexport interface PrismaArrow {\n id: number;\n fromId: number;\n toId: number;\n}\n\n/**\n * The full input for one PRISMA diagram.\n *\n * @property variant \"flow\" = standard single-column;\n * \"flow-with-prior\" = two-column (new + previous sources, with merge arrow);\n * \"flow-other-methods\" = parallel new + other-sources stacks in the main column.\n * @property boxes Declared PRISMA boxes.\n * @property arrows Declared flow arrows.\n */\nexport interface PrismaInput {\n variant: \"flow\" | \"flow-with-prior\" | \"flow-other-methods\";\n boxes: PrismaBox[];\n arrows: PrismaArrow[];\n}\n","// PRISMA 2020 validation — REJECT-WITH-CODES.\n// Three-phase pipeline: duplicate-id short-circuit → reference/semantic → graph.\n// Empty input (no boxes AND no arrows) → valid, never throws.\n// NO arithmetic anywhere — the honesty rule is non-negotiable.\n\nimport type { PrismaInput, PrismaPhase } from \"./types\";\nimport { PRISMA_PHASES } from \"./types\";\n\n/** Stable machine-readable issue codes (kebab-case; public contract). */\nexport type PrismaIssueCode =\n | \"duplicate-id\"\n | \"unknown-arrow-endpoint\"\n | \"self-arrow\"\n | \"non-finite-count\"\n | \"invalid-variant-column\"\n | \"arrow-skips-backward\";\n\nexport interface PrismaIssue {\n code: PrismaIssueCode;\n message: string;\n}\n\n/** Thrown by computePrismaLayout / prismaSvg on structurally invalid input. */\nexport class PrismaValidationError extends Error {\n readonly issues: readonly PrismaIssue[];\n\n constructor(issues: readonly PrismaIssue[]) {\n super(`invalid PRISMA diagram: ${issues.map((i) => i.message).join(\"; \")}`);\n this.name = \"PrismaValidationError\";\n this.issues = issues;\n }\n}\n\n/**\n * Deduplicates and sorts issues deterministically (by code, then byte-message).\n * Shared by every phase that returns.\n */\nfunction sortIssues(issues: readonly PrismaIssue[]): readonly PrismaIssue[] {\n const unique = new Map<string, PrismaIssue>();\n for (const issue of issues) unique.set(`${issue.code} ${issue.message}`, issue);\n return [...unique.values()].sort((a, b) =>\n a.code !== b.code\n ? a.code < b.code ? -1 : 1\n : a.message < b.message ? -1 : a.message > b.message ? 1 : 0,\n );\n}\n\n/**\n * Computes ALL validation issues for the input, deduplicated and deterministically sorted.\n * Empty input (no boxes AND no arrows) → valid (returns []).\n */\nexport function prismaIssues(input: PrismaInput): readonly PrismaIssue[] {\n if (input.boxes.length === 0 && input.arrows.length === 0) return [];\n\n const issues: PrismaIssue[] = [];\n const push = (code: PrismaIssueCode, message: string): void => {\n issues.push({ code, message });\n };\n\n // ── Phase 0: duplicate ids (per namespace — phase-0 short-circuit). ──────────────\n // Both namespaces checked together; any duplicate makes downstream rules order-dependent.\n const boxById = new Map<number, (typeof input.boxes)[number]>();\n const dupBoxIds = new Set<number>();\n for (const b of input.boxes) {\n if (boxById.has(b.id)) dupBoxIds.add(b.id);\n else boxById.set(b.id, b);\n }\n for (const id of [...dupBoxIds].sort((a, b) => a - b)) {\n push(\"duplicate-id\", `duplicate box id ${id}`);\n }\n\n const arrowById = new Map<number, (typeof input.arrows)[number]>();\n const dupArrowIds = new Set<number>();\n for (const a of input.arrows) {\n if (arrowById.has(a.id)) dupArrowIds.add(a.id);\n else arrowById.set(a.id, a);\n }\n for (const id of [...dupArrowIds].sort((a, b) => a - b)) {\n push(\"duplicate-id\", `duplicate arrow id ${id}`);\n }\n\n if (issues.length > 0) return sortIssues(issues);\n\n // ── Phase 1: reference + semantic rules. ────────────────────────────────────────\n\n // R1: unknown arrow endpoints.\n for (const arrow of [...arrowById.values()].sort((a, b) => a.id - b.id)) {\n if (!boxById.has(arrow.fromId)) {\n push(\"unknown-arrow-endpoint\", `arrow ${arrow.id} fromId ${arrow.fromId} is not a declared box`);\n }\n if (!boxById.has(arrow.toId)) {\n push(\"unknown-arrow-endpoint\", `arrow ${arrow.id} toId ${arrow.toId} is not a declared box`);\n }\n // R2: self-arrow.\n if (arrow.fromId === arrow.toId) {\n push(\"self-arrow\", `arrow ${arrow.id} has fromId === toId (${arrow.fromId})`);\n }\n }\n\n // R3: non-finite counts. null is legal; NaN/±Infinity is not.\n for (const box of [...boxById.values()].sort((a, b) => a.id - b.id)) {\n for (const count of box.counts) {\n if (count.n !== null && !Number.isFinite(count.n)) {\n push(\"non-finite-count\", `box ${box.id} count \"${count.label}\" has non-finite n: ${String(count.n)}`);\n }\n }\n }\n\n // R4: invalid-variant-column — \"previous\" column only valid in \"flow-with-prior\".\n if (input.variant !== \"flow-with-prior\") {\n for (const box of [...boxById.values()].sort((a, b) => a.id - b.id)) {\n if (box.column === \"previous\") {\n push(\n \"invalid-variant-column\",\n `box ${box.id} has column \"previous\" but variant is \"${input.variant}\"`,\n );\n }\n }\n }\n\n // ── Phase 2: graph rules. GRAPH_BLOCKING-gated. ─────────────────────────────────\n const GRAPH_BLOCKING: ReadonlySet<PrismaIssueCode> = new Set([\n \"duplicate-id\",\n \"unknown-arrow-endpoint\",\n ]);\n if (!issues.some((i) => GRAPH_BLOCKING.has(i.code))) {\n // R5: arrow-skips-backward — toId's box is in an EARLIER phase band than fromId's.\n // EXCEPTION: a flow→exclusion arrow within the SAME band is never \"backward\"\n // (side-boxes are horizontal, same-band).\n const phaseIndex = new Map<PrismaPhase, number>();\n for (let i = 0; i < PRISMA_PHASES.length; i++) phaseIndex.set(PRISMA_PHASES[i]!, i);\n\n for (const arrow of [...arrowById.values()].sort((a, b) => a.id - b.id)) {\n const fromBox = boxById.get(arrow.fromId)!;\n const toBox = boxById.get(arrow.toId)!;\n const fromPhaseIdx = phaseIndex.get(fromBox.phase)!;\n const toPhaseIdx = phaseIndex.get(toBox.phase)!;\n\n // Same-band flow→exclusion exception.\n if (\n fromBox.kind === \"flow\" &&\n toBox.kind === \"exclusion\" &&\n fromBox.phase === toBox.phase\n ) {\n continue;\n }\n\n if (toPhaseIdx < fromPhaseIdx) {\n push(\n \"arrow-skips-backward\",\n `arrow ${arrow.id} goes backward: from phase \"${fromBox.phase}\" to \"${toBox.phase}\"`,\n );\n }\n }\n }\n\n return sortIssues(issues);\n}\n\n/** Throws PrismaValidationError (carrying ALL issues) when the input is invalid. */\nexport function validatePrisma(input: PrismaInput): void {\n const issues = prismaIssues(input);\n if (issues.length > 0) throw new PrismaValidationError(issues);\n}\n","// PRISMA 2020 display vocabularies.\n// Split into title labels (woven into <title>s by layout) and SVG labels (legend/aria).\n// English defaults inline; pt-BR in src/locales/pt-br.ts.\n\n/** Labels woven into element <title>s — phase names, count token, arrow kind words. */\nexport interface PrismaTitleLabels {\n /** Display names for each phase band (left gutter label). */\n phases: {\n identification: string;\n screening: string;\n included: string;\n };\n /** Localized token for n=null counts (\"n = —\" in EN/PT-BR). */\n nullCount: string;\n /** Arrow kind words used in <title>s. */\n arrowKinds: {\n flow: string;\n exclusion: string;\n merge: string;\n };\n}\n\n/** Labels drawn by the SVG emitter (legend entries, accessibility aria-label). */\nexport interface PrismaSvgLabels {\n legend: {\n flow: string;\n exclusion: string;\n };\n ariaLabel: string;\n}\n\nexport const PRISMA_TITLE_LABELS_EN: PrismaTitleLabels = {\n phases: {\n identification: \"Identification\",\n screening: \"Screening\",\n included: \"Included\",\n },\n nullCount: \"n = —\",\n arrowKinds: {\n flow: \"Flow\",\n exclusion: \"Exclusion\",\n merge: \"Merge\",\n },\n};\n\nexport const PRISMA_SVG_LABELS_EN: PrismaSvgLabels = {\n legend: {\n flow: \"Main flow\",\n exclusion: \"Excluded\",\n },\n ariaLabel: \"PRISMA 2020 flow diagram\",\n};\n","// PRISMA 2020 pure layout — the single source of truth for positioning and routing.\n// The emitter (./svg.ts) draws EXACTLY what this computes; no geometry is re-derived\n// downstream. Pure + deterministic (no DOM, no clock, no randomness).\n//\n// LAYOUT SUMMARY:\n// - Bands stack top→down via core/bandStack in fixed PRISMA_PHASES order.\n// - Each flow column owns a COLUMN BLOCK = [flow sub-column | EXCL_GAP | exclusion\n// sub-column]. Blocks are GLOBAL (widths are the max box width in that column across\n// ALL phases) and disjoint by construction (single block at contentLeft, or two blocks\n// packed as disjoint siblings via core/packSubtree with PRISMA_COL_GAP between them).\n// - Within a band, a column's flow boxes stack by (rank, id) at the flow sub-column x;\n// that SAME column's exclusion boxes stack by (rank, id) at the exclusion sub-column x —\n// PER COLUMN, so an exclusion always sits to the right of ITS OWN column's flow box.\n// - Band height = max over columns of max(column flow-stack total, column excl-stack total),\n// where a stack total = Σ(boxH) + PRISMA_BOX_PAD_Y between consecutive boxes. Reserving\n// the STACKED total (not the tallest single box) is what lets multiple flow steps share a\n// band (the canonical screening column: screened → sought → assessed) without spilling.\n// - Arrows are all orthogonal (H/V only):\n// * flow→flow same-column (within a band, adjacent ranks; or across bands): vertical drop\n// on the box-center x (box-free because the column is a single vertical stack).\n// * flow→flow cross-column or with multiple arrivals (merge/fan-in): orthogonal elbow via\n// a unique approach_x spread across the target box width — no collinear vertical stubs.\n// * flow→exclusion: a direct horizontal from the source's right edge to its own column's\n// exclusion box left edge, at the exclusion box's center y. The strip between a flow\n// sub-column and ITS OWN exclusion sub-column is box-free (only this column lives in the\n// block), so no detour is ever needed — the per-column block is what kills it.\n//\n// OVERLAP INVARIANTS:\n// 1. Boxes: disjoint by construction — disjoint bands (bandStack recurrence) × disjoint\n// column blocks (packSubtree / single block) × within a block, flow and exclusion\n// sub-columns separated by PRISMA_EXCL_GAP.\n// 2. flow→exclusion arrows: each at the unique center y of its (stacked) exclusion box,\n// inside its own column's box-free flow→excl strip → no collinear, no box crossing.\n// 3. flow→flow drops: one per source on its column's center x (single stack ⇒ box-free),\n// adjacent-rank drops are short and consecutive (no intervening box).\n// 4. Merge/fan-in arrows: each uses a unique approach_x (spread across target box width) so\n// no two arrows share a collinear vertical stub into the same target box.\n//\n// NO ARITHMETIC VALIDATION — the honesty rule. Figures are drawn faithfully as declared.\n\nimport {\n bandStack,\n measureCompartmentBox,\n packSubtree,\n wrapLabelBalanced,\n type Point,\n} from \"../core\";\nimport { PRISMA_TITLE_LABELS_EN, type PrismaTitleLabels } from \"./labels\";\nimport { validatePrisma } from \"./validate\";\nimport { PRISMA_PHASES, type PrismaInput, type PrismaPhase } from \"./types\";\n\nexport {\n PrismaValidationError,\n prismaIssues,\n validatePrisma,\n type PrismaIssue,\n type PrismaIssueCode,\n} from \"./validate\";\nexport type { Point };\n\n// ── Geometry constants ────────────────────────────────────────────────────────\nexport const PRISMA_PADDING = 32;\n/** Left gutter reserved for rotated band labels (never overlaps boxes). */\nexport const PRISMA_BAND_LABEL_W = 40;\n/** Horizontal gap between two flow columns. */\nexport const PRISMA_COL_GAP = 56;\n/** Vertical corridor between bands. */\nexport const PRISMA_CORRIDOR = 30;\nexport const PRISMA_BOX_PAD_X = 12;\nexport const PRISMA_BOX_PAD_Y = 10;\nexport const PRISMA_LINE_H = 14;\nexport const PRISMA_MIN_BOX_W = 200;\n/** Gap between the right edge of ALL flow columns and the left edge of exclusion boxes. */\nexport const PRISMA_EXCL_GAP = 48;\nexport const PRISMA_HEADING_FONT = 12;\nexport const PRISMA_COUNT_FONT = 10;\n/** Vertical margin added below band bottom for corridor routing. */\nconst PRISMA_ROUTE_MARGIN = 10;\n/** Pitch between unique corridor y-levels for multiple arrows from same source. */\nconst PRISMA_ROUTE_PITCH = 10;\n\n// ── Namespaced edge-id blocks ─────────────────────────────────────────────────\nexport const PRISMA_FLOW_ARROW_BASE = 1_000_000; // + arrow.id\nexport const PRISMA_EXCL_ARROW_BASE = 2_000_000; // + arrow.id\nexport const PRISMA_MERGE_ARROW_BASE = 3_000_000; // + arrow.id\n\n// ── Layout types ──────────────────────────────────────────────────────────────\n\n/** A positioned PRISMA box with all metrics needed by the emitter and harness. */\nexport interface PrismaLayoutBox {\n id: number;\n phase: PrismaPhase;\n kind: \"flow\" | \"exclusion\";\n /** Center x. */\n cx: number;\n /** Top y. */\n top: number;\n boxW: number;\n boxH: number;\n rows: { lines: string[]; top: number; font: number }[];\n dividerYs: number[];\n heading: string | null;\n countLines: string[];\n title: string;\n}\n\n/** A routed element (arrow segment polyline). */\nexport interface PrismaLayoutElement {\n edgeId: number;\n kind: \"flow\" | \"exclusion\" | \"merge\";\n points: Point[];\n title: string;\n headDir: \"down\" | \"right\" | \"left\" | \"up\";\n}\n\n/** The positioned PRISMA layout. */\nexport interface PrismaLayout {\n width: number;\n height: number;\n boxes: PrismaLayoutBox[];\n elements: PrismaLayoutElement[];\n bands: {\n phase: PrismaPhase;\n rowTop: number;\n rowH: number;\n labelX: number;\n centerY: number;\n }[];\n variant: PrismaInput[\"variant\"];\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction round(n: number): number {\n return Math.round(n * 100) / 100;\n}\n\nfunction wrapHeading(h: string | null): string[] {\n if (h === null || h === \"\") return [];\n return wrapLabelBalanced(h);\n}\n\nfunction countLine(label: string, n: number | null, nullToken: string): string {\n const nStr = n === null ? nullToken : String(n);\n return `${label}: n = ${nStr}`;\n}\n\nfunction buildCountLines(counts: { label: string; n: number | null }[], nullToken: string): string[] {\n return counts.map((c) => countLine(c.label, c.n, nullToken));\n}\n\nfunction boxTitle(\n box: { heading: string | null; counts: { label: string; n: number | null }[]; title?: string },\n nullToken: string,\n): string {\n if (box.title !== undefined) return box.title;\n const parts: string[] = [];\n if (box.heading !== null && box.heading !== \"\") parts.push(box.heading);\n for (const c of box.counts) parts.push(countLine(c.label, c.n, nullToken));\n return parts.join(\"; \") || \"(box)\";\n}\n\n// ── Main layout function ──────────────────────────────────────────────────────\n\nexport interface PrismaLayoutOpts {\n labels?: PrismaTitleLabels;\n validate?: boolean;\n}\n\nexport function computePrismaLayout(input: PrismaInput, opts: PrismaLayoutOpts = {}): PrismaLayout {\n if (opts.validate !== false) validatePrisma(input);\n\n const labels: PrismaTitleLabels = opts.labels ?? PRISMA_TITLE_LABELS_EN;\n const nullToken = labels.nullCount;\n\n // ── 1. Measure each box ────────────────────────────────────────────────────\n const COMP_OPTS = {\n padX: PRISMA_BOX_PAD_X,\n padY: PRISMA_BOX_PAD_Y,\n lineH: PRISMA_LINE_H,\n minW: PRISMA_MIN_BOX_W,\n sepPad: 0,\n };\n\n const boxMetrics = new Map<number, {\n boxW: number; boxH: number;\n rows: { lines: string[]; top: number; font: number }[];\n dividerYs: number[];\n headingLines: string[];\n countLines: string[];\n }>();\n\n for (const b of input.boxes) {\n const headingLines = wrapHeading(b.heading);\n const cLines = buildCountLines(b.counts, nullToken);\n const metrics = measureCompartmentBox(\n [\n { lines: headingLines, font: PRISMA_HEADING_FONT },\n { lines: cLines, font: PRISMA_COUNT_FONT },\n ],\n COMP_OPTS,\n );\n boxMetrics.set(b.id, {\n boxW: metrics.boxW, boxH: metrics.boxH,\n rows: metrics.rows, dividerYs: metrics.dividerYs,\n headingLines, countLines: cLines,\n });\n }\n\n // ── 2. Group boxes by (phase, column, kind) ────────────────────────────────\n type FlowCol = \"main\" | \"new\" | \"previous\";\n type GroupKey = `${PrismaPhase}:${FlowCol}:${\"flow\" | \"exclusion\"}`;\n\n const boxesByKey = new Map<GroupKey, typeof input.boxes[number][]>();\n for (const b of input.boxes) {\n const key: GroupKey = `${b.phase}:${b.column as FlowCol}:${b.kind}`;\n const arr = boxesByKey.get(key) ?? [];\n arr.push(b);\n boxesByKey.set(key, arr);\n }\n for (const arr of boxesByKey.values()) {\n arr.sort((a, b) => a.rank !== b.rank ? a.rank - b.rank : a.id - b.id);\n }\n const groupOf = (phase: PrismaPhase, col: FlowCol, kind: \"flow\" | \"exclusion\") =>\n boxesByKey.get(`${phase}:${col}:${kind}`) ?? [];\n\n const flowCols: FlowCol[] =\n input.variant === \"flow-with-prior\" ? [\"new\", \"previous\"] :\n input.variant === \"flow-other-methods\" ? [\"main\", \"new\"] :\n [\"main\"];\n\n // ── 3. GLOBAL per-column blocks: [flow sub-column | EXCL_GAP | exclusion sub-column] ──\n // Each column owns a block whose widths are the max box width in that column across ALL\n // phases (so every band's column shares one x). A column with no exclusion box reserves no\n // exclusion sub-column. Blocks pack left→right as disjoint siblings (PRISMA_COL_GAP between\n // block AABBs). A column that carries ONLY exclusion boxes (e.g. a shared \"main\" duplicates\n // box in the prior variant) becomes a trailing exclusion-only block to the right of the flow\n // blocks (flowW = 0) — its arrows are the one cross-column case (routed via a detour below).\n const contentLeft = PRISMA_PADDING + PRISMA_BAND_LABEL_W;\n\n function maxColW(col: FlowCol, kind: \"flow\" | \"exclusion\"): number {\n let w = 0;\n for (const phase of PRISMA_PHASES) {\n for (const b of groupOf(phase, col, kind)) {\n const bw = boxMetrics.get(b.id)!.boxW;\n if (bw > w) w = bw;\n }\n }\n return w;\n }\n const colHasFlow = (col: FlowCol): boolean =>\n PRISMA_PHASES.some((phase) => groupOf(phase, col, \"flow\").length > 0);\n const colHasExcl = (col: FlowCol): boolean =>\n PRISMA_PHASES.some((phase) => groupOf(phase, col, \"exclusion\").length > 0);\n\n // Exclusion-only columns (have exclusion boxes but are not a flow column) → trailing blocks.\n const exclOnlyCols: FlowCol[] = ([\"main\", \"new\", \"previous\"] as const).filter(\n (col) => !flowCols.includes(col) && colHasExcl(col),\n );\n const placedCols: FlowCol[] = [...flowCols, ...exclOnlyCols];\n\n // Per-column geometry: flow x-center, optional exclusion x-center, total block width.\n interface ColGeom {\n flowW: number; // 0 ⇒ exclusion-only column (no flow sub-column)\n exclW: number; // 0 ⇒ no exclusion sub-column in this column\n blockW: number;\n flowCx: number; // absolute, set in the placement pass; meaningful only when flowW > 0\n exclCx: number; // absolute; meaningful only when exclW > 0\n }\n const colGeom = new Map<FlowCol, ColGeom>();\n for (const col of placedCols) {\n const flowW = colHasFlow(col) ? Math.max(PRISMA_MIN_BOX_W, maxColW(col, \"flow\")) : 0;\n const exclW = maxColW(col, \"exclusion\");\n const blockW =\n flowW > 0 && exclW > 0 ? flowW + PRISMA_EXCL_GAP + exclW :\n flowW > 0 ? flowW :\n exclW;\n colGeom.set(col, { flowW, exclW, blockW, flowCx: 0, exclCx: 0 });\n }\n\n // Place each column block; within a block the flow sub-column is left-aligned and the\n // exclusion sub-column (if any) sits at flowRight + EXCL_GAP (or at blockLeft when flowW=0).\n function placeBlock(col: FlowCol, blockLeft: number): void {\n const g = colGeom.get(col)!;\n if (g.flowW > 0) g.flowCx = round(blockLeft + g.flowW / 2);\n if (g.exclW > 0) {\n const exclLeft = g.flowW > 0 ? blockLeft + g.flowW + PRISMA_EXCL_GAP : blockLeft;\n g.exclCx = round(exclLeft + g.exclW / 2);\n }\n }\n\n if (placedCols.length === 1) {\n placeBlock(placedCols[0]!, contentLeft);\n } else {\n // Pack all column BLOCKS as disjoint siblings (PRISMA_COL_GAP between block AABBs).\n const packed = packSubtree(\n { ownHalfL: 0, ownHalfR: 0,\n children: placedCols.map((col) => {\n const half = colGeom.get(col)!.blockW / 2;\n return { halfL: half, halfR: half };\n }),\n },\n { siblingGap: PRISMA_COL_GAP },\n );\n const totalW = packed.halfL + packed.halfR;\n const blockCx = round(contentLeft + totalW / 2);\n placedCols.forEach((col, i) => {\n const w = colGeom.get(col)!.blockW;\n placeBlock(col, round(blockCx + packed.offsets[i]! - w / 2));\n });\n }\n\n // Right-most drawn x (for the canvas width).\n let totalRight = contentLeft;\n for (const col of placedCols) {\n const g = colGeom.get(col)!;\n const r = g.exclW > 0 ? round(g.exclCx + g.exclW / 2) : round(g.flowCx + g.flowW / 2);\n if (r > totalRight) totalRight = r;\n }\n\n // ── 4. Per-(phase, column) RANK ROWS ───────────────────────────────────────\n // Within a column a flow box and its same-rank exclusion box MUST share a vertical level\n // (the exclusion sits directly to the right of its flow box). So rows are indexed by the\n // DECLARED rank: a row's height is the tallest box (flow OR exclusion) at that rank, and\n // ranks stack top→down by rowH + PRISMA_BOX_PAD_Y. The flow box draws at flowCx, the\n // exclusion box at exclCx, BOTH at the rank's row-top — keeping a same-rank flow→excl\n // horizontal box-free and aligning all stacked steps. Reserving the stacked total (not the\n // tallest single box) lets a multi-step screening column (screened → sought → assessed)\n // share one band; the old max-single-box reserve spilled ranks ≥ 1 into the next band.\n interface RankRow { rank: number; rowH: number; top: number; }\n // rowsByCol[phase][col] = ordered rank rows (top set after the band's rowTop is known).\n const rowsByCol = new Map<string, RankRow[]>();\n const rowsKey = (phase: PrismaPhase, col: FlowCol) => `${phase}:${col}`;\n\n function buildRankRows(phase: PrismaPhase, col: FlowCol): RankRow[] {\n const byRank = new Map<number, number>(); // rank → tallest box height at that rank\n for (const kind of [\"flow\", \"exclusion\"] as const) {\n for (const b of groupOf(phase, col, kind)) {\n const h = boxMetrics.get(b.id)!.boxH;\n const prev = byRank.get(b.rank) ?? 0;\n if (h > prev) byRank.set(b.rank, h);\n }\n }\n const ranks = [...byRank.keys()].sort((a, b) => a - b);\n return ranks.map((rank) => ({ rank, rowH: byRank.get(rank)!, top: 0 }));\n }\n for (const phase of PRISMA_PHASES) {\n for (const col of placedCols) {\n rowsByCol.set(rowsKey(phase, col), buildRankRows(phase, col));\n }\n }\n\n // A column's total stacked height = Σ(rowH) + (rows−1)·PRISMA_BOX_PAD_Y.\n function colStackH(rows: RankRow[]): number {\n if (rows.length === 0) return 0;\n let h = 0;\n for (const r of rows) h += r.rowH + PRISMA_BOX_PAD_Y;\n return h - PRISMA_BOX_PAD_Y; // last row has no trailing pad\n }\n function bandRowH(phase: PrismaPhase): number {\n let maxH = 0;\n let any = false;\n for (const col of placedCols) {\n const rows = rowsByCol.get(rowsKey(phase, col))!;\n if (rows.length > 0) any = true;\n const h = colStackH(rows);\n if (h > maxH) maxH = h;\n }\n if (!any) return PRISMA_LINE_H * 2 + PRISMA_BOX_PAD_Y * 4; // empty band: gutter only\n return maxH;\n }\n\n const bandRowHs = PRISMA_PHASES.map((phase) => ({\n rowH: bandRowH(phase),\n zoneH: 0,\n }));\n\n const stacked = bandStack(bandRowHs, { padding: PRISMA_PADDING, corridor: PRISMA_CORRIDOR });\n\n // ── 5. Position all boxes ─────────────────────────────────────────────────\n // Each rank row's top is the band rowTop plus the cumulative height of the rows above it.\n // Every box at rank k draws at its row's top — flow at flowCx, exclusion at exclCx.\n const layoutBoxes: PrismaLayoutBox[] = [];\n const lboxById = new Map<number, PrismaLayoutBox>();\n\n function placeBox(\n b: typeof input.boxes[number],\n phase: PrismaPhase,\n kind: \"flow\" | \"exclusion\",\n cx: number,\n top: number,\n ): void {\n const m = boxMetrics.get(b.id)!;\n const t = round(top);\n const title = boxTitle(b, nullToken);\n const lbox: PrismaLayoutBox = {\n id: b.id, phase, kind, cx: round(cx), top: t,\n boxW: m.boxW, boxH: m.boxH,\n rows: m.rows.map((r) => ({ ...r, top: round(t + r.top) })),\n dividerYs: m.dividerYs.map((d) => round(t + d)),\n heading: b.heading, countLines: m.countLines, title,\n };\n layoutBoxes.push(lbox);\n lboxById.set(b.id, lbox);\n }\n\n for (let phaseIdx = 0; phaseIdx < PRISMA_PHASES.length; phaseIdx++) {\n const phase = PRISMA_PHASES[phaseIdx]!;\n const bandTop = stacked.rowTop[phaseIdx]!;\n for (const col of placedCols) {\n const g = colGeom.get(col)!;\n const rows = rowsByCol.get(rowsKey(phase, col))!;\n const topByRank = new Map<number, number>();\n let y = bandTop;\n for (const r of rows) {\n r.top = round(y);\n topByRank.set(r.rank, r.top);\n y = round(y + r.rowH + PRISMA_BOX_PAD_Y);\n }\n if (g.flowW > 0) {\n for (const b of groupOf(phase, col, \"flow\")) {\n placeBox(b, phase, \"flow\", g.flowCx, topByRank.get(b.rank)!);\n }\n }\n if (g.exclW > 0) {\n for (const b of groupOf(phase, col, \"exclusion\")) {\n placeBox(b, phase, \"exclusion\", g.exclCx, topByRank.get(b.rank)!);\n }\n }\n }\n }\n\n // ── 6. Route arrows ───────────────────────────────────────────────────────\n //\n // ROUTING INVARIANTS (proof that collisions == []):\n //\n // A. FLOW → EXCLUSION, SAME COLUMN (the common case):\n // A direct horizontal at the exclusion box's center y, from the source flow box's right\n // edge to the exclusion box's left edge. The strip between a column's flow sub-column and\n // ITS OWN exclusion sub-column is box-free by construction (only this column lives in the\n // block, and the two sub-columns are separated by PRISMA_EXCL_GAP), so the segment crosses\n // no box. Each exclusion box in the column has a unique center y (vertical stack) → distinct\n // horizontals → no collinear double-draw.\n //\n // B. FLOW → EXCLUSION, CROSS COLUMN (a shared exclusion column, e.g. a \"main\" duplicates box\n // in the prior variant — the one case a column's flow box points at another column's box):\n // The direct horizontal would cross an intervening column's box, so detour through the\n // box-free inter-column gap and the corridor below the band, using a per-source-arrow unique\n // x on every vertical leg and a unique y on every horizontal leg:\n // (srcRight, exclMidY) → (fenceX, exclMidY) → (fenceX, corridorY)\n // → (exclFenceX, corridorY) → (exclFenceX, exclMidY) → (exclLeft, exclMidY)\n // fenceX (in the inter-column gap) and exclFenceX (just left of the target excl box) are\n // unique per arrow → no collinear vertical; corridorY and exclMidY are unique per arrow\n // → no collinear horizontal. The corridor sits below the band (bandRowH reserves the full\n // stacked height, so it is below every box) → the corridor legs are box-free.\n //\n // C. FLOW → FLOW, SAME COLUMN:\n // A vertical drop on the column's center x, from the source box bottom to the target box top.\n // The column is a single vertical stack, so the strip on its center x between two boxes is\n // box-free; adjacent ranks make the drop short and consecutive (no intervening box).\n //\n // D. FLOW → FLOW, CROSS COLUMN or FAN-IN (merge):\n // An orthogonal elbow via the corridor below the source band, entering the target box top at\n // a unique approach_x spread across the target box width → no two incoming arrows share a\n // collinear vertical stub into the same target box.\n\n const elements: PrismaLayoutElement[] = [];\n const boxById = new Map(input.boxes.map((b) => [b.id, b]));\n\n // Build phase index for backward-arrow check.\n const phaseIndexMap = new Map<PrismaPhase, number>(\n PRISMA_PHASES.map((p, i) => [p, i]),\n );\n\n // Helper: bottom y of a layout box.\n function boxBottom(lb: PrismaLayoutBox): number {\n return round(lb.top + lb.boxH);\n }\n\n // Helper: band bottom y (rowTop + rowH).\n function bandBottom(phase: PrismaPhase): number {\n const idx = PRISMA_PHASES.indexOf(phase);\n return round(stacked.rowTop[idx]! + bandRowHs[idx]!.rowH);\n }\n\n // ── Count arrows per target box (for merge approach-x spread) ────────────────\n // For flow→flow arrows, count how many arrows arrive at each target box.\n // This determines the spread of approach_x to avoid collinear vertical stubs.\n const arrowsToBox = new Map<number, number[]>(); // toId → [arrowId, ...]\n for (const arrow of input.arrows) {\n const toBox = boxById.get(arrow.toId);\n const fromBox = boxById.get(arrow.fromId);\n if (toBox === undefined || fromBox === undefined) continue;\n if (fromBox.kind === \"flow\" && toBox.kind === \"flow\") {\n const arr = arrowsToBox.get(arrow.toId) ?? [];\n arr.push(arrow.id);\n arrowsToBox.set(arrow.toId, arr);\n }\n }\n\n // Track per-target arrival index (for unique approach_x assignment).\n const arrowToBoxArrivalIdx = new Map<number, number>(); // arrowId → arrival index at target\n\n // ── Excl arrow index tracking per source box ──────────────────────────────\n const exclArrowIndexBySource = new Map<number, number>(); // sourceId → next index\n\n for (const arrow of input.arrows) {\n const fromLBox = lboxById.get(arrow.fromId);\n const toLBox = lboxById.get(arrow.toId);\n if (fromLBox === undefined || toLBox === undefined) continue;\n\n const fromBox = boxById.get(arrow.fromId)!;\n const toBox = boxById.get(arrow.toId)!;\n\n const isExclusion = fromBox.kind === \"flow\" && toBox.kind === \"exclusion\";\n const isFlowToFlow = fromBox.kind === \"flow\" && toBox.kind === \"flow\";\n\n if (isExclusion) {\n // ── Flow → Exclusion ────────────────────────────────────────────────\n const idx = exclArrowIndexBySource.get(arrow.fromId) ?? 0;\n exclArrowIndexBySource.set(arrow.fromId, idx + 1);\n\n const srcRight = round(fromLBox.cx + fromLBox.boxW / 2);\n const exclMidY = round(toLBox.top + toLBox.boxH / 2);\n const eLeft = round(toLBox.cx - toLBox.boxW / 2);\n\n // Same column ⇒ the flow→excl strip is box-free ⇒ a direct horizontal suffices.\n // Cross column (shared exclusion) ⇒ detour around the intervening boxes.\n const sameColumn = fromBox.column === toBox.column;\n\n let points: Point[];\n\n if (sameColumn) {\n // Direct: unique y per excl box guarantees no collinear with other direct arrows.\n points = [\n { x: round(srcRight), y: round(exclMidY) },\n { x: round(eLeft), y: round(exclMidY) },\n ];\n } else {\n // Detour via the inter-column gap and the corridor below the band.\n // fenceX_i: unique x just right of the source box (in its block's right margin / gap).\n // exclFenceX_i: unique x just left of the target excl box (inside the gap before it).\n // corridorY_i: unique y below the band (the band reserves the full stacked height).\n const colGapStep = round(PRISMA_COL_GAP / 8); // ~7px per slot\n const exclGapStep = round(PRISMA_EXCL_GAP / 8); // ~6px per slot\n\n const fenceX = round(srcRight + (idx + 1) * colGapStep);\n const exclFenceX = round(eLeft - (idx + 1) * exclGapStep);\n const bBotY = bandBottom(fromBox.phase);\n const corridorY = round(bBotY + PRISMA_ROUTE_MARGIN + idx * PRISMA_ROUTE_PITCH);\n\n points = [\n { x: round(srcRight), y: round(exclMidY) }, // exit source right at excl center y\n { x: round(fenceX), y: round(exclMidY) }, // horizontal into inter-col gap (unique y)\n { x: round(fenceX), y: round(corridorY) }, // vertical at unique x in inter-col gap\n { x: round(exclFenceX), y: round(corridorY) }, // horizontal in corridor (unique y)\n { x: round(exclFenceX), y: round(exclMidY) }, // vertical at unique x left of excl box\n { x: round(eLeft), y: round(exclMidY) }, // horizontal into excl box (unique y)\n ];\n }\n\n elements.push({\n edgeId: PRISMA_EXCL_ARROW_BASE + arrow.id,\n kind: \"exclusion\",\n points,\n title: `${labels.arrowKinds.exclusion}: ${fromLBox.title} → ${toLBox.title}`,\n headDir: \"right\",\n });\n } else if (isFlowToFlow) {\n // ── Flow → Flow ─────────────────────────────────────────────────────\n const fromPhaseIdx = phaseIndexMap.get(fromBox.phase)!;\n const toPhaseIdx = phaseIndexMap.get(toBox.phase)!;\n const isSamePhase = fromBox.phase === toBox.phase;\n const isSameCol = fromBox.column === toBox.column;\n const isForward = toPhaseIdx >= fromPhaseIdx;\n\n // Arrival index for unique approach_x at target.\n const arrivals = arrowsToBox.get(arrow.toId) ?? [];\n let arrivalIdx = arrowToBoxArrivalIdx.get(arrow.id) ?? 0;\n if (!arrowToBoxArrivalIdx.has(arrow.id)) {\n arrivalIdx = arrivals.indexOf(arrow.id);\n arrowToBoxArrivalIdx.set(arrow.id, arrivalIdx);\n }\n const nArrivals = arrivals.length;\n // Spread approach_x across the target box width.\n // With n arrows, divide target box into n+1 slots and use slots 1..n.\n const APPROACH_SPREAD = round(toLBox.boxW / 4); // use middle half of box\n const spreadStep = nArrivals > 1 ? round(APPROACH_SPREAD / (nArrivals - 1)) : 0;\n const approachX = round(toLBox.cx - APPROACH_SPREAD / 2 + arrivalIdx * spreadStep);\n const toTop = toLBox.top;\n\n if (isSamePhase && isSameCol) {\n // Same-column same-phase (adjacent ranks in one stack): a short straight vertical drop\n // on the shared box-center x. Source and target share cx (one column ⇒ one x), and the\n // PAD-sized gap between them is box-free, so no elbow / approach-x spread is needed; a\n // diagonal would only appear if we offset to approachX, which is wrong here.\n const fromBottom = boxBottom(fromLBox);\n const fromCx = round(fromLBox.cx);\n const toCx = round(toLBox.cx);\n const dropX = fromCx === toCx ? fromCx : toCx; // identical in practice; defensive\n elements.push({\n edgeId: PRISMA_FLOW_ARROW_BASE + arrow.id,\n kind: \"flow\",\n points: [\n { x: fromCx, y: round(fromBottom) },\n { x: dropX, y: round(toTop) },\n ],\n title: `${labels.arrowKinds.flow}: ${fromLBox.title} → ${toLBox.title}`,\n headDir: \"down\",\n });\n } else if (isSameCol && isForward) {\n // Same-column cross-phase downward: vertical drop from fromCx to toCx.\n // If same cx, this is a clean vertical line; if cx differs (shouldn't in global scheme),\n // use the approach_x for unique routing.\n const fromBottom = boxBottom(fromLBox);\n if (nArrivals <= 1 && round(fromLBox.cx) === round(toLBox.cx)) {\n // Single arrow, same cx: clean straight vertical.\n elements.push({\n edgeId: PRISMA_FLOW_ARROW_BASE + arrow.id,\n kind: \"flow\",\n points: [\n { x: round(fromLBox.cx), y: round(fromBottom) },\n { x: round(toLBox.cx), y: round(toTop) },\n ],\n title: `${labels.arrowKinds.flow}: ${fromLBox.title} → ${toLBox.title}`,\n headDir: \"down\",\n });\n } else {\n // Multiple arrows or different cx: use elbow routing.\n const phIdx = phaseIndexMap.get(fromBox.phase)!;\n const elbowY = round(stacked.rowTop[phIdx]! + bandRowHs[phIdx]!.rowH + PRISMA_CORRIDOR / 2);\n elements.push({\n edgeId: PRISMA_FLOW_ARROW_BASE + arrow.id,\n kind: \"flow\",\n points: [\n { x: round(fromLBox.cx), y: round(fromBottom) },\n { x: round(fromLBox.cx), y: round(elbowY) },\n { x: round(approachX), y: round(elbowY) },\n { x: round(approachX), y: round(toTop) },\n ],\n title: `${labels.arrowKinds.flow}: ${fromLBox.title} → ${toLBox.title}`,\n headDir: \"down\",\n });\n }\n } else {\n // Cross-column or cross-phase merge arrow.\n // Route: (fromCx, fromBottom) → (fromCx, elbowY) → (approachX, elbowY) → (approachX, toTop)\n // elbowY = mid-corridor below the FROM band.\n const fromBottom = boxBottom(fromLBox);\n const phIdx = phaseIndexMap.get(fromBox.phase)!;\n const elbowY = round(stacked.rowTop[phIdx]! + bandRowHs[phIdx]!.rowH + PRISMA_CORRIDOR / 2);\n\n const fromCx = round(fromLBox.cx);\n if (round(fromCx) === round(approachX)) {\n // Same x: straight vertical.\n elements.push({\n edgeId: PRISMA_MERGE_ARROW_BASE + arrow.id,\n kind: \"merge\",\n points: [\n { x: fromCx, y: round(fromBottom) },\n { x: round(approachX), y: round(toTop) },\n ],\n title: `${labels.arrowKinds.merge}: ${fromLBox.title} → ${toLBox.title}`,\n headDir: \"down\",\n });\n } else {\n elements.push({\n edgeId: PRISMA_MERGE_ARROW_BASE + arrow.id,\n kind: \"merge\",\n points: [\n { x: fromCx, y: round(fromBottom) },\n { x: fromCx, y: round(elbowY) },\n { x: round(approachX), y: round(elbowY) },\n { x: round(approachX), y: round(toTop) },\n ],\n title: `${labels.arrowKinds.merge}: ${fromLBox.title} → ${toLBox.title}`,\n headDir: \"down\",\n });\n }\n }\n }\n // Backward arrows (validation catches them but layout tolerates silently).\n }\n\n // ── 7. Canvas dimensions ───────────────────────────────────────────────────\n const canvasH = stacked.height;\n const canvasW = round(totalRight + PRISMA_PADDING);\n\n // ── 8. Band metadata ───────────────────────────────────────────────────────\n const bands = PRISMA_PHASES.map((phase, i) => {\n const rowTop = stacked.rowTop[i]!;\n const rowH = bandRowHs[i]!.rowH;\n return {\n phase,\n rowTop,\n rowH,\n labelX: PRISMA_PADDING,\n centerY: round(rowTop + rowH / 2),\n };\n });\n\n return {\n width: canvasW,\n height: canvasH,\n boxes: layoutBoxes,\n elements,\n bands,\n variant: input.variant,\n };\n}\n","// PRISMA 2020 SVG emitter — draws EXACTLY what layout.ts computed.\n// Literal presentation attributes only; no CSS, no <defs>, no <marker>.\n// All text interpolations are xmlEscape'd.\n// Arrowheads are explicit <polygon>s from core/glyph.\n\nimport {\n FONT_FAMILY,\n arrowFilledPoints,\n glyphInset,\n legendBlock,\n pathData,\n xmlEscape,\n type LegendEntry,\n} from \"../core\";\nimport {\n PRISMA_BAND_LABEL_W,\n type PrismaLayout,\n type PrismaLayoutBox,\n type PrismaLayoutElement,\n} from \"./layout\";\nimport {\n PRISMA_SVG_LABELS_EN,\n PRISMA_TITLE_LABELS_EN,\n type PrismaSvgLabels,\n type PrismaTitleLabels,\n} from \"./labels\";\nimport type { PrismaPhase } from \"./types\";\n\n// ── Presentation constants ────────────────────────────────────────────────────\nconst BOX_STROKE = \"#52525b\";\nconst BOX_STROKE_W = 2;\nconst BOX_FILL = \"#fff\";\nconst BOX_RX = 2;\nconst HEADING_FILL = \"#3f3f46\";\nconst COUNT_FILL = \"#52525b\";\nconst ARROW_STROKE = \"#71717a\";\nconst ARROW_STROKE_W = 1.5;\nconst ARROW_FILL = \"#71717a\";\nconst BAND_LABEL_FILL = \"#52525b\";\nconst BAND_LABEL_FONT = 11;\n\nfunction round(n: number): number {\n return Math.round(n * 100) / 100;\n}\n\n// ── Box emitter ───────────────────────────────────────────────────────────────\n\nfunction emitBox(b: PrismaLayoutBox): string {\n const x = round(b.cx - b.boxW / 2);\n const y = b.top;\n const parts: string[] = [];\n\n // Outer rect\n parts.push(\n `<rect x=\"${x}\" y=\"${y}\" width=\"${b.boxW}\" height=\"${b.boxH}\" ` +\n `rx=\"${BOX_RX}\" fill=\"${BOX_FILL}\" stroke=\"${BOX_STROKE}\" stroke-width=\"${BOX_STROKE_W}\"/>`,\n );\n\n // Dividers (between heading and counts compartment)\n for (const dy of b.dividerYs) {\n parts.push(\n `<line x1=\"${x}\" y1=\"${dy}\" x2=\"${round(x + b.boxW)}\" y2=\"${dy}\" ` +\n `stroke=\"${BOX_STROKE}\" stroke-width=\"1\"/>`,\n );\n }\n\n // Text rows: first compartment = heading (bold by size), second = counts (regular, left-aligned)\n for (let ri = 0; ri < b.rows.length; ri++) {\n const row = b.rows[ri]!;\n const isHeading = ri === 0;\n const font = row.font;\n const fill = isHeading ? HEADING_FILL : COUNT_FILL;\n const textX = isHeading\n ? round(b.cx) // heading: centered\n : round(x + 8); // counts: left-aligned with small indent\n\n for (let li = 0; li < row.lines.length; li++) {\n const line = row.lines[li]!;\n const textY = round(row.top + li * 14 + font); // 14 = PRISMA_LINE_H\n const anchorAttr = isHeading ? ` text-anchor=\"middle\"` : \"\";\n const weightAttr = isHeading ? ` font-weight=\"bold\"` : \"\";\n parts.push(\n `<text x=\"${textX}\" y=\"${textY}\" font-family=\"${FONT_FAMILY}\" ` +\n `font-size=\"${font}\" fill=\"${fill}\"${anchorAttr}${weightAttr}>${xmlEscape(line)}</text>`,\n );\n }\n }\n\n return parts.join(\"\");\n}\n\n// ── Arrow emitter ─────────────────────────────────────────────────────────────\n\nfunction emitArrow(el: PrismaLayoutElement): string {\n const points = el.points;\n if (points.length < 2) return \"\";\n\n // The line stops short by glyphInset before the terminal point\n const inset = glyphInset(el.headDir, \"arrow\");\n const last = points[points.length - 1]!;\n\n // Shorten the last segment by inset\n let lineEndX = last.x;\n let lineEndY = last.y;\n if (el.headDir === \"down\") lineEndY = round(last.y - inset);\n else if (el.headDir === \"right\") lineEndX = round(last.x - inset);\n else if (el.headDir === \"left\") lineEndX = round(last.x + inset);\n else lineEndY = round(last.y + inset); // \"up\"\n\n // Build shortened polyline\n const linePoints = [\n ...points.slice(0, points.length - 1).map((p) => ({ x: p.x, y: p.y })),\n { x: lineEndX, y: lineEndY },\n ];\n\n const pathStr = pathData(linePoints);\n const arrowPts = arrowFilledPoints({ x: last.x, y: last.y }, el.headDir);\n\n return (\n `<title>${xmlEscape(el.title)}</title>` +\n `<path d=\"${pathStr}\" stroke=\"${ARROW_STROKE}\" stroke-width=\"${ARROW_STROKE_W}\" fill=\"none\"/>` +\n `<polygon points=\"${arrowPts}\" fill=\"${ARROW_FILL}\" stroke=\"none\"/>`\n );\n}\n\n// ── Band label emitter (rotated, left gutter — decoration) ────────────────────\n\nfunction emitBandLabel(\n phase: PrismaPhase,\n labelX: number,\n centerY: number,\n bandTitleLabels: PrismaTitleLabels,\n): string {\n const text = bandTitleLabels.phases[phase];\n const gutterCx = round(labelX + PRISMA_BAND_LABEL_W / 2);\n return (\n `<text x=\"${gutterCx}\" y=\"${round(centerY)}\" font-family=\"${FONT_FAMILY}\" ` +\n `font-size=\"${BAND_LABEL_FONT}\" fill=\"${BAND_LABEL_FILL}\" text-anchor=\"middle\" ` +\n `transform=\"rotate(-90,${gutterCx},${round(centerY)})\">${xmlEscape(text)}</text>`\n );\n}\n\n// ── Legend ────────────────────────────────────────────────────────────────────\n\nfunction buildLegendEntries(\n layout: PrismaLayout,\n svgLabels: PrismaSvgLabels,\n): LegendEntry[] {\n const hasFlow = layout.boxes.some((b) => b.kind === \"flow\");\n const hasExcl = layout.boxes.some((b) => b.kind === \"exclusion\");\n const entries: LegendEntry[] = [];\n\n if (hasFlow) {\n entries.push({\n label: svgLabels.legend.flow,\n swatch: (x, cy) => (\n `<rect x=\"${x}\" y=\"${round(cy - 6)}\" width=\"22\" height=\"12\" rx=\"2\" ` +\n `fill=\"${BOX_FILL}\" stroke=\"${BOX_STROKE}\" stroke-width=\"2\"/>`\n ),\n });\n }\n if (hasExcl) {\n entries.push({\n label: svgLabels.legend.exclusion,\n swatch: (x, cy) => (\n `<rect x=\"${x}\" y=\"${round(cy - 6)}\" width=\"22\" height=\"12\" rx=\"2\" ` +\n `fill=\"${BOX_FILL}\" stroke=\"${BOX_STROKE}\" stroke-width=\"2\" stroke-dasharray=\"4,2\"/>`\n ),\n });\n }\n return entries;\n}\n\n// ── Main emitter ──────────────────────────────────────────────────────────────\n\nexport interface PrismaSvgOpts {\n svgLabels?: PrismaSvgLabels;\n titleLabels?: PrismaTitleLabels;\n legend?: boolean;\n}\n\n/**\n * Emits the SVG string for a pre-computed PRISMA layout.\n * All coordinates come from the layout; no geometry is re-derived here.\n */\nexport function prismaLayoutSvg(layout: PrismaLayout, opts: PrismaSvgOpts = {}): string {\n const svgLabels: PrismaSvgLabels = opts.svgLabels ?? PRISMA_SVG_LABELS_EN;\n const bandTitleLabels: PrismaTitleLabels = opts.titleLabels ?? PRISMA_TITLE_LABELS_EN;\n const doLegend = opts.legend !== false;\n\n // ── Collect SVG parts ─────────────────────────────────────────────────────\n const parts: string[] = [];\n\n // Band labels (rotated, decoration)\n for (const band of layout.bands) {\n parts.push(emitBandLabel(band.phase, band.labelX, band.centerY, bandTitleLabels));\n }\n\n // Boxes\n for (const b of layout.boxes) {\n const boxSvg = emitBox(b);\n parts.push(`<g data-node-id=\"b${b.id}\"><title>${xmlEscape(b.title)}</title>${boxSvg}</g>`);\n }\n\n // Arrows\n for (const el of layout.elements) {\n const arrowSvg = emitArrow(el);\n parts.push(`<g data-edge-id=\"${el.edgeId}\">${arrowSvg}</g>`);\n }\n\n let w = layout.width;\n let h = layout.height;\n\n // Legend\n let legendSvg = \"\";\n if (doLegend) {\n const entries = buildLegendEntries(layout, svgLabels);\n const lb = legendBlock(entries, h);\n legendSvg = lb.svg;\n if (entries.length > 0) {\n w = Math.max(w, lb.width + 32 * 2);\n h = lb.height;\n }\n }\n\n w = round(w);\n h = round(h);\n\n return (\n `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${w}\" height=\"${h}\" viewBox=\"0 0 ${w} ${h}\" ` +\n `role=\"img\" aria-label=\"${xmlEscape(svgLabels.ariaLabel)}\">` +\n parts.join(\"\") +\n legendSvg +\n `</svg>`\n );\n}\n","// PRISMA 2020 one-call render wrapper.\n// prismaSvg(input, opts) → { svg, layout }\n// Validates, computes layout, emits SVG — the three-step pipeline in one call.\n\nimport { computePrismaLayout, type PrismaLayout, type PrismaLayoutOpts } from \"./layout\";\nimport { prismaLayoutSvg, type PrismaSvgOpts } from \"./svg\";\nimport type { PrismaInput } from \"./types\";\n\nexport type PrismaRenderOpts = PrismaLayoutOpts & PrismaSvgOpts;\n\n/** Compute layout + emit SVG in one call. Returns both for callers that need the layout. */\nexport function prismaSvg(\n input: PrismaInput,\n opts: PrismaRenderOpts = {},\n): { svg: string; layout: PrismaLayout } {\n const layout = computePrismaLayout(input, opts);\n const svg = prismaLayoutSvg(layout, opts);\n return { svg, layout };\n}\n"]}
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
// src/core/xml.ts
|
|
2
|
+
function xmlEscape(text) {
|
|
3
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// src/core/roman.ts
|
|
7
|
+
var ROMAN_TABLE = [
|
|
8
|
+
[1e3, "M"],
|
|
9
|
+
[900, "CM"],
|
|
10
|
+
[500, "D"],
|
|
11
|
+
[400, "CD"],
|
|
12
|
+
[100, "C"],
|
|
13
|
+
[90, "XC"],
|
|
14
|
+
[50, "L"],
|
|
15
|
+
[40, "XL"],
|
|
16
|
+
[10, "X"],
|
|
17
|
+
[9, "IX"],
|
|
18
|
+
[5, "V"],
|
|
19
|
+
[4, "IV"],
|
|
20
|
+
[1, "I"]
|
|
21
|
+
];
|
|
22
|
+
function romanNumeral(n) {
|
|
23
|
+
if (!Number.isInteger(n) || n < 1 || n > 3999) return String(n);
|
|
24
|
+
let remaining = n;
|
|
25
|
+
let out = "";
|
|
26
|
+
for (const [value, symbol] of ROMAN_TABLE) {
|
|
27
|
+
while (remaining >= value) {
|
|
28
|
+
out += symbol;
|
|
29
|
+
remaining -= value;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// src/core/geometry.ts
|
|
36
|
+
function pathData(points) {
|
|
37
|
+
return points.map((p, i) => `${i === 0 ? "M" : "L"} ${p.x} ${p.y}`).join(" ");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// src/core/text.ts
|
|
41
|
+
var CHAR_W = 0.6;
|
|
42
|
+
function estimateTextWidth(text, fontPx) {
|
|
43
|
+
return text.length * fontPx * CHAR_W;
|
|
44
|
+
}
|
|
45
|
+
function wrapLabel(label, perLine, maxLines = 2) {
|
|
46
|
+
if (label.length <= perLine) return [label];
|
|
47
|
+
const cap = (s) => s.length > perLine ? s.slice(0, Math.max(1, perLine - 1)) + "\u2026" : s;
|
|
48
|
+
const lines = [""];
|
|
49
|
+
for (const word of label.split(/\s+/)) {
|
|
50
|
+
const last = lines.length - 1;
|
|
51
|
+
const current = lines[last];
|
|
52
|
+
if (current === "" || (current + " " + word).length <= perLine) {
|
|
53
|
+
lines[last] = current === "" ? word : `${current} ${word}`;
|
|
54
|
+
} else if (lines.length < maxLines) {
|
|
55
|
+
lines.push(word);
|
|
56
|
+
} else {
|
|
57
|
+
lines[last] = `${current} ${word}`;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (lines.length > 1 && lines[lines.length - 1] === "") lines.pop();
|
|
61
|
+
return lines.map(cap);
|
|
62
|
+
}
|
|
63
|
+
function wrapLabelBalanced(label, maxLines) {
|
|
64
|
+
const perLine = Math.min(26, Math.max(14, Math.ceil(label.length / 2) + 2));
|
|
65
|
+
return wrapLabel(label, perLine, maxLines);
|
|
66
|
+
}
|
|
67
|
+
function clampLabel(label, maxChars) {
|
|
68
|
+
if (maxChars === void 0 || label.length <= maxChars) return label;
|
|
69
|
+
return label.slice(0, Math.max(1, maxChars - 1)) + "\u2026";
|
|
70
|
+
}
|
|
71
|
+
var FONT_FAMILY = "Helvetica, Arial, sans-serif";
|
|
72
|
+
|
|
73
|
+
// src/core/legend.ts
|
|
74
|
+
var LEGEND_ROW_H = 18;
|
|
75
|
+
var LEGEND_PAD = 16;
|
|
76
|
+
var LEGEND_SWATCH_W = 22;
|
|
77
|
+
var LEGEND_GAP = 14;
|
|
78
|
+
var LEGEND_FONT = 11;
|
|
79
|
+
var LEGEND_TEXT_FILL = "#52525b";
|
|
80
|
+
function legendBlock(entries, startY) {
|
|
81
|
+
if (entries.length === 0) return { svg: "", width: 0, height: startY };
|
|
82
|
+
const rows = entries.map((entry, i) => {
|
|
83
|
+
const rowCenterY = startY + i * LEGEND_ROW_H + LEGEND_ROW_H / 2;
|
|
84
|
+
const textX = LEGEND_PAD + LEGEND_SWATCH_W + LEGEND_GAP;
|
|
85
|
+
return entry.swatch(LEGEND_PAD, rowCenterY) + `<text x="${textX}" y="${rowCenterY + LEGEND_FONT * 0.32}" font-family="${FONT_FAMILY}" font-size="${LEGEND_FONT}" fill="${LEGEND_TEXT_FILL}">${xmlEscape(entry.label)}</text>`;
|
|
86
|
+
});
|
|
87
|
+
const widestLabel = entries.reduce((m, e) => Math.max(m, estimateTextWidth(e.label, LEGEND_FONT)), 0);
|
|
88
|
+
return {
|
|
89
|
+
svg: `<g data-compasso-legend="true">${rows.join("")}</g>`,
|
|
90
|
+
width: LEGEND_PAD + LEGEND_SWATCH_W + LEGEND_GAP + widestLabel + LEGEND_PAD,
|
|
91
|
+
height: startY + entries.length * LEGEND_ROW_H + LEGEND_PAD / 2
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// src/core/stroke.ts
|
|
96
|
+
var EDGE_STROKE = {
|
|
97
|
+
plain: { width: 1.5, dash: null, opacity: 0.6 },
|
|
98
|
+
close: { width: 3, dash: null, opacity: 0.85 },
|
|
99
|
+
distant: { width: 1.5, dash: [4, 4], opacity: 0.55 },
|
|
100
|
+
conflict: { width: 2, dash: [2, 2], opacity: 0.75 },
|
|
101
|
+
cutoff: { width: 1.5, dash: [6, 5], opacity: 0.4 }
|
|
102
|
+
};
|
|
103
|
+
var QUALITY_LEXICON_EN = {
|
|
104
|
+
buckets: [
|
|
105
|
+
{
|
|
106
|
+
style: "close",
|
|
107
|
+
needles: ["close", "warm", "support", "lov", "affection", "caring", "tight", "harmon", "healthy"]
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
style: "distant",
|
|
111
|
+
needles: ["distant", "detach", "absent", "cold", "drift"]
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
style: "conflict",
|
|
115
|
+
needles: ["conflict", "fight", "tens", "difficult", "hostil", "violen", "abus", "aggress", "complicat", "toxic", "argu"]
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
style: "cutoff",
|
|
119
|
+
needles: ["estrang", "cut off", "cutoff", "no contact", "broken off", "sever"]
|
|
120
|
+
}
|
|
121
|
+
],
|
|
122
|
+
negations: ["not", "never", "no longer", "hardly"]
|
|
123
|
+
};
|
|
124
|
+
function normalizeText(text) {
|
|
125
|
+
return text.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase();
|
|
126
|
+
}
|
|
127
|
+
var escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
128
|
+
function qualityLineStyle(quality, lexicon = QUALITY_LEXICON_EN) {
|
|
129
|
+
if (quality === null) return "plain";
|
|
130
|
+
const haystack = normalizeText(quality);
|
|
131
|
+
if (haystack.trim() === "") return "plain";
|
|
132
|
+
if (lexicon.negations.length > 0) {
|
|
133
|
+
const negation = new RegExp(`\\b(${lexicon.negations.map(escapeRegExp).join("|")})\\b`);
|
|
134
|
+
if (negation.test(haystack)) return "plain";
|
|
135
|
+
}
|
|
136
|
+
const matched = [];
|
|
137
|
+
for (const { style, needles } of lexicon.buckets) {
|
|
138
|
+
if (needles.some((n) => haystack.includes(n))) matched.push(style);
|
|
139
|
+
}
|
|
140
|
+
return matched.length === 1 ? matched[0] : "plain";
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// src/core/annotation.ts
|
|
144
|
+
var round = (n) => Math.round(n * 100) / 100;
|
|
145
|
+
var ANNOTATION_INK = "#52525b";
|
|
146
|
+
var DOT_R = 3;
|
|
147
|
+
var TICK_HALF = 3;
|
|
148
|
+
function annotationDot(cx, cy) {
|
|
149
|
+
return `<circle cx="${round(cx)}" cy="${round(cy)}" r="${DOT_R}" fill="${ANNOTATION_INK}" fill-opacity="0.6"/>`;
|
|
150
|
+
}
|
|
151
|
+
function annotationTick(points) {
|
|
152
|
+
if (points.length < 2) return "";
|
|
153
|
+
const i = Math.floor((points.length - 1) / 2);
|
|
154
|
+
const a = points[i];
|
|
155
|
+
const b = points[i + 1] ?? points[i];
|
|
156
|
+
const mx = (a.x + b.x) / 2;
|
|
157
|
+
const my = (a.y + b.y) / 2;
|
|
158
|
+
const horizontal = Math.abs(a.y - b.y) <= Math.abs(a.x - b.x);
|
|
159
|
+
const x1 = horizontal ? mx : mx - TICK_HALF;
|
|
160
|
+
const x2 = horizontal ? mx : mx + TICK_HALF;
|
|
161
|
+
const y1 = horizontal ? my - TICK_HALF : my;
|
|
162
|
+
const y2 = horizontal ? my + TICK_HALF : my;
|
|
163
|
+
return `<line x1="${round(x1)}" y1="${round(y1)}" x2="${round(x2)}" y2="${round(y2)}" stroke="${ANNOTATION_INK}" stroke-width="1.5"/>`;
|
|
164
|
+
}
|
|
165
|
+
function annotationSwatch(x, yCenter) {
|
|
166
|
+
return annotationDot(x + LEGEND_SWATCH_W / 2, yCenter);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// src/core/layered.ts
|
|
170
|
+
function packSubtree(node, gaps) {
|
|
171
|
+
const { ownHalfL, ownHalfR, children } = node;
|
|
172
|
+
if (children.length === 0) {
|
|
173
|
+
return { halfL: ownHalfL, halfR: ownHalfR, offsets: [] };
|
|
174
|
+
}
|
|
175
|
+
const xs = [0];
|
|
176
|
+
for (let i = 1; i < children.length; i++) {
|
|
177
|
+
xs.push(xs[i - 1] + children[i - 1].halfR + gaps.siblingGap + children[i].halfL);
|
|
178
|
+
}
|
|
179
|
+
const first = children[0];
|
|
180
|
+
const last = children[children.length - 1];
|
|
181
|
+
const axis = (xs[0] + xs[xs.length - 1]) / 2;
|
|
182
|
+
const offsets = xs.map((x) => x - axis);
|
|
183
|
+
const halfL = Math.max(ownHalfL, axis - (xs[0] - first.halfL));
|
|
184
|
+
const halfR = Math.max(ownHalfR, xs[xs.length - 1] + last.halfR - axis);
|
|
185
|
+
return { halfL, halfR, offsets };
|
|
186
|
+
}
|
|
187
|
+
function allocateLanes(items) {
|
|
188
|
+
const lanes = [];
|
|
189
|
+
for (const it of items) {
|
|
190
|
+
let chosen = -1;
|
|
191
|
+
for (let l = 0; l < lanes.length; l++) {
|
|
192
|
+
if (lanes[l].every((o) => it.hi <= o.lo || it.lo >= o.hi)) {
|
|
193
|
+
chosen = l;
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (chosen === -1) {
|
|
198
|
+
chosen = lanes.length;
|
|
199
|
+
lanes.push([]);
|
|
200
|
+
}
|
|
201
|
+
lanes[chosen].push({ lo: it.lo, hi: it.hi });
|
|
202
|
+
it.set(chosen);
|
|
203
|
+
}
|
|
204
|
+
return lanes.length;
|
|
205
|
+
}
|
|
206
|
+
function bandStack(rows, opts) {
|
|
207
|
+
const { padding, corridor } = opts;
|
|
208
|
+
if (rows.length === 0) {
|
|
209
|
+
return { rowTop: [], busY: () => 0, height: padding * 2 };
|
|
210
|
+
}
|
|
211
|
+
const rowTop = [padding];
|
|
212
|
+
for (let d = 0; d < rows.length - 1; d++) {
|
|
213
|
+
rowTop.push(rowTop[d] + rows[d].rowH + rows[d].zoneH + corridor);
|
|
214
|
+
}
|
|
215
|
+
const last = rows.length - 1;
|
|
216
|
+
const busY = (d) => rowTop[d + 1] - corridor / 2;
|
|
217
|
+
const height = rowTop[last] + rows[last].rowH + rows[last].zoneH + padding;
|
|
218
|
+
return { rowTop, busY, height };
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// src/core/glyph.ts
|
|
222
|
+
function dirVec(dir) {
|
|
223
|
+
switch (dir) {
|
|
224
|
+
case "right":
|
|
225
|
+
return [1, 0];
|
|
226
|
+
case "left":
|
|
227
|
+
return [-1, 0];
|
|
228
|
+
case "down":
|
|
229
|
+
return [0, 1];
|
|
230
|
+
case "up":
|
|
231
|
+
return [0, -1];
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function r(n) {
|
|
235
|
+
return Math.round(n * 100) / 100;
|
|
236
|
+
}
|
|
237
|
+
function pt(x, y) {
|
|
238
|
+
return `${r(x)},${r(y)}`;
|
|
239
|
+
}
|
|
240
|
+
var GLYPH_ARROW_LEN = 10;
|
|
241
|
+
var GLYPH_ARROW_HALF = 5;
|
|
242
|
+
var GLYPH_TRI_LEN = 14;
|
|
243
|
+
var GLYPH_TRI_HALF = 8;
|
|
244
|
+
var GLYPH_DIAMOND_LEN = 16;
|
|
245
|
+
var GLYPH_DIAMOND_HALF = 6;
|
|
246
|
+
function arrowOpenPoints(tip, dir, len = GLYPH_ARROW_LEN, half = GLYPH_ARROW_HALF) {
|
|
247
|
+
return _arrowPoints(tip, dir, len, half);
|
|
248
|
+
}
|
|
249
|
+
function arrowFilledPoints(tip, dir, len = GLYPH_ARROW_LEN, half = GLYPH_ARROW_HALF) {
|
|
250
|
+
return _arrowPoints(tip, dir, len, half);
|
|
251
|
+
}
|
|
252
|
+
function _arrowPoints(tip, dir, len, half) {
|
|
253
|
+
const [ux, uy] = dirVec(dir);
|
|
254
|
+
const tx = tip.x;
|
|
255
|
+
const ty = tip.y;
|
|
256
|
+
const bx = tx - ux * len;
|
|
257
|
+
const by = ty - uy * len;
|
|
258
|
+
const px = -uy;
|
|
259
|
+
const py = ux;
|
|
260
|
+
return [
|
|
261
|
+
pt(tx, ty),
|
|
262
|
+
pt(bx + px * half, by + py * half),
|
|
263
|
+
pt(bx - px * half, by - py * half)
|
|
264
|
+
].join(" ");
|
|
265
|
+
}
|
|
266
|
+
function trianglePoints(tip, dir, len = GLYPH_TRI_LEN, half = GLYPH_TRI_HALF) {
|
|
267
|
+
return _arrowPoints(tip, dir, len, half);
|
|
268
|
+
}
|
|
269
|
+
function diamondPoints(tip, dir, len = GLYPH_DIAMOND_LEN, half = GLYPH_DIAMOND_HALF) {
|
|
270
|
+
const [ux, uy] = dirVec(dir);
|
|
271
|
+
const tx = tip.x;
|
|
272
|
+
const ty = tip.y;
|
|
273
|
+
const mx = tx + ux * (len / 2);
|
|
274
|
+
const my = ty + uy * (len / 2);
|
|
275
|
+
const basex = tx + ux * len;
|
|
276
|
+
const basey = ty + uy * len;
|
|
277
|
+
const px = -uy;
|
|
278
|
+
const py = ux;
|
|
279
|
+
return [
|
|
280
|
+
pt(tx, ty),
|
|
281
|
+
pt(mx - px * half, my - py * half),
|
|
282
|
+
pt(basex, basey),
|
|
283
|
+
pt(mx + px * half, my + py * half)
|
|
284
|
+
].join(" ");
|
|
285
|
+
}
|
|
286
|
+
function glyphInset(_dir, kind) {
|
|
287
|
+
switch (kind) {
|
|
288
|
+
case "arrow":
|
|
289
|
+
return GLYPH_ARROW_LEN;
|
|
290
|
+
case "triangle":
|
|
291
|
+
return GLYPH_TRI_LEN;
|
|
292
|
+
case "diamond":
|
|
293
|
+
return GLYPH_DIAMOND_LEN;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// src/core/compartment.ts
|
|
298
|
+
function round2(n) {
|
|
299
|
+
return Math.round(n * 100) / 100;
|
|
300
|
+
}
|
|
301
|
+
function measureCompartmentBox(compartments, opts) {
|
|
302
|
+
const { padX, padY, lineH, minW } = opts;
|
|
303
|
+
let maxLineW = 0;
|
|
304
|
+
for (const c of compartments) {
|
|
305
|
+
for (const line of c.lines) {
|
|
306
|
+
const w = estimateTextWidth(line, c.font);
|
|
307
|
+
if (w > maxLineW) maxLineW = w;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
const boxW = round2(Math.max(minW, maxLineW + 2 * padX));
|
|
311
|
+
const rows = [];
|
|
312
|
+
const dividerYs = [];
|
|
313
|
+
let y = 0;
|
|
314
|
+
for (let i = 0; i < compartments.length; i++) {
|
|
315
|
+
const c = compartments[i];
|
|
316
|
+
const lineCount = c.lines.length > 0 ? c.lines.length : 1;
|
|
317
|
+
const compartmentH = padY + lineCount * lineH + padY;
|
|
318
|
+
rows.push({
|
|
319
|
+
lines: c.lines,
|
|
320
|
+
top: round2(y + padY),
|
|
321
|
+
font: c.font
|
|
322
|
+
});
|
|
323
|
+
y += compartmentH;
|
|
324
|
+
if (i < compartments.length - 1) {
|
|
325
|
+
dividerYs.push(round2(y));
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
const boxH = round2(y);
|
|
329
|
+
return { boxW, boxH, rows, dividerYs };
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// src/core/grid.ts
|
|
333
|
+
function round3(n) {
|
|
334
|
+
return Math.round(n * 100) / 100;
|
|
335
|
+
}
|
|
336
|
+
function packGrid(cells, gaps) {
|
|
337
|
+
if (cells.length === 0) {
|
|
338
|
+
return { cellX: [], cellY: [], colW: [], rowH: [] };
|
|
339
|
+
}
|
|
340
|
+
const { colGap, rowGap } = gaps;
|
|
341
|
+
let maxCol = 0;
|
|
342
|
+
let maxRow = 0;
|
|
343
|
+
for (const c of cells) {
|
|
344
|
+
if (c.col > maxCol) maxCol = c.col;
|
|
345
|
+
if (c.row > maxRow) maxRow = c.row;
|
|
346
|
+
}
|
|
347
|
+
const colW = Array.from({ length: maxCol + 1 }, () => 0);
|
|
348
|
+
const rowH = Array.from({ length: maxRow + 1 }, () => 0);
|
|
349
|
+
for (const c of cells) {
|
|
350
|
+
if (c.w > colW[c.col]) colW[c.col] = c.w;
|
|
351
|
+
if (c.h > rowH[c.row]) rowH[c.row] = c.h;
|
|
352
|
+
}
|
|
353
|
+
const colX = Array.from({ length: maxCol + 1 }, () => 0);
|
|
354
|
+
for (let c = 1; c <= maxCol; c++) {
|
|
355
|
+
colX[c] = round3(colX[c - 1] + colW[c - 1] + colGap);
|
|
356
|
+
}
|
|
357
|
+
const rowY = Array.from({ length: maxRow + 1 }, () => 0);
|
|
358
|
+
for (let r2 = 1; r2 <= maxRow; r2++) {
|
|
359
|
+
rowY[r2] = round3(rowY[r2 - 1] + rowH[r2 - 1] + rowGap);
|
|
360
|
+
}
|
|
361
|
+
const cellX = cells.map(
|
|
362
|
+
(c) => round3(colX[c.col] + colW[c.col] / 2)
|
|
363
|
+
);
|
|
364
|
+
const cellY = cells.map(
|
|
365
|
+
(c) => round3(rowY[c.row] + rowH[c.row] / 2)
|
|
366
|
+
);
|
|
367
|
+
return { cellX, cellY, colW, rowH };
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
export { ANNOTATION_INK, CHAR_W, EDGE_STROKE, FONT_FAMILY, GLYPH_ARROW_HALF, GLYPH_ARROW_LEN, GLYPH_DIAMOND_HALF, GLYPH_DIAMOND_LEN, GLYPH_TRI_HALF, GLYPH_TRI_LEN, LEGEND_FONT, LEGEND_GAP, LEGEND_PAD, LEGEND_ROW_H, LEGEND_SWATCH_W, QUALITY_LEXICON_EN, allocateLanes, annotationDot, annotationSwatch, annotationTick, arrowFilledPoints, arrowOpenPoints, bandStack, clampLabel, diamondPoints, estimateTextWidth, glyphInset, legendBlock, measureCompartmentBox, normalizeText, packGrid, packSubtree, pathData, qualityLineStyle, romanNumeral, trianglePoints, wrapLabel, wrapLabelBalanced, xmlEscape };
|
|
371
|
+
//# sourceMappingURL=chunk-DVLWT565.js.map
|
|
372
|
+
//# sourceMappingURL=chunk-DVLWT565.js.map
|