chalkbridge 1.0.4 → 1.1.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/dist/{chunk-U2ZMSGNS.js → chunk-XDK5UUTO.js} +243 -9
- package/dist/cli.js +538 -86
- package/dist/index.js +1 -1
- package/guides/icons.md +22 -3
- package/guides/layout.md +42 -3
- package/package.json +1 -1
- package/ui-dist/assets/{abnfDiagram-VCTEODGH-C_cqCKun.js → abnfDiagram-VCTEODGH-BCawxiKB.js} +1 -1
- package/ui-dist/assets/{ar-SA-G6X2FPQ2-CEKRHtmX.js → ar-SA-G6X2FPQ2-UCm9FftA.js} +1 -1
- package/ui-dist/assets/architecture-7GRP2DOG-CiyYoVgW.js +1 -0
- package/ui-dist/assets/{architectureDiagram-5GKGNRK7-BuWVonvB.js → architectureDiagram-5GKGNRK7-DIw1pNEk.js} +1 -1
- package/ui-dist/assets/{az-AZ-76LH7QW2-mn2Y6BCY.js → az-AZ-76LH7QW2-B5LEIxkk.js} +1 -1
- package/ui-dist/assets/{bg-BG-XCXSNQG7-CraLx0fE.js → bg-BG-XCXSNQG7-2bpThpZL.js} +1 -1
- package/ui-dist/assets/{blockDiagram-NRAW4CY4-83XozRPe.js → blockDiagram-NRAW4CY4-BGr2WGp_.js} +1 -1
- package/ui-dist/assets/{bn-BD-2XOGV67Q-CsTrJsPu.js → bn-BD-2XOGV67Q-Drz-y_cX.js} +1 -1
- package/ui-dist/assets/{c4Diagram-UCG6FXSJ-DTdS8B8G.js → c4Diagram-UCG6FXSJ-vbm87bpC.js} +1 -1
- package/ui-dist/assets/{ca-ES-6MX7JW3Y-DD8cv_ze.js → ca-ES-6MX7JW3Y-D89p_FZ-.js} +1 -1
- package/ui-dist/assets/channel-DtgwkzBZ.js +1 -0
- package/ui-dist/assets/{chunk-75Z2AOVW-DQDqkKP0.js → chunk-75Z2AOVW-B7kf5jVz.js} +1 -1
- package/ui-dist/assets/{chunk-DU6HZSFF-_YwywVCK.js → chunk-DU6HZSFF-BlGPS6B6.js} +1 -1
- package/ui-dist/assets/{chunk-EIO257PC-CLwbKeso.js → chunk-EIO257PC-nzXnwORk.js} +1 -1
- package/ui-dist/assets/{chunk-F27PBJKO-BwhryBf6.js → chunk-F27PBJKO-B7qepoj_.js} +1 -1
- package/ui-dist/assets/{chunk-G27WJ6UU-BixSJdhz.js → chunk-G27WJ6UU-CSjcvmOf.js} +1 -1
- package/ui-dist/assets/{chunk-GMAD6QVW-Bp7aUQup.js → chunk-GMAD6QVW-CtaZAO5u.js} +1 -1
- package/ui-dist/assets/{chunk-JQ64N6SF-Dt5bAScf.js → chunk-JQ64N6SF-CuhtdTse.js} +1 -1
- package/ui-dist/assets/{chunk-LCL6LL3I-B5MsvPPp.js → chunk-LCL6LL3I-DMfA3a_s.js} +1 -1
- package/ui-dist/assets/{chunk-OBVCFTLP-DBqcHzNF.js → chunk-OBVCFTLP-BoBuso2l.js} +1 -1
- package/ui-dist/assets/{chunk-P2QGCYS3-TMRACTMO.js → chunk-P2QGCYS3-BZHK87sP.js} +1 -1
- package/ui-dist/assets/{chunk-POPQ4Y6H-BsmX_MmQ.js → chunk-POPQ4Y6H-Dk_v51-0.js} +1 -1
- package/ui-dist/assets/{chunk-PWAF6VOD-g4MniF8u.js → chunk-PWAF6VOD-DQTvHbxy.js} +1 -1
- package/ui-dist/assets/{chunk-R7TYR2AO-S7THFl9x.js → chunk-R7TYR2AO-CQ_StUs1.js} +1 -1
- package/ui-dist/assets/{chunk-RHFEMEQ7-CZYull6D.js → chunk-RHFEMEQ7-BTgGEQit.js} +1 -1
- package/ui-dist/assets/{chunk-SVP7TREG-DCss0vmb.js → chunk-SVP7TREG-lkVXeHxJ.js} +1 -1
- package/ui-dist/assets/{chunk-TEH6E4GO-B-6h5v_5.js → chunk-TEH6E4GO-DIEC-0PO.js} +1 -1
- package/ui-dist/assets/classDiagram-DTDB5LWJ-B83TJF6p.js +1 -0
- package/ui-dist/assets/classDiagram-v2-JRS7N3AN-B83TJF6p.js +1 -0
- package/ui-dist/assets/{cs-CZ-2BRQDIVT-C9fIM1z5.js → cs-CZ-2BRQDIVT-CmSaQCAW.js} +1 -1
- package/ui-dist/assets/{cynefin-OW5HDTMX-CtdCt-Da.js → cynefin-OW5HDTMX-B6f8qooM.js} +1 -1
- package/ui-dist/assets/{cynefinDiagram-5FMLGOSQ-CF9L7X85.js → cynefinDiagram-5FMLGOSQ-DFu8uB2c.js} +1 -1
- package/ui-dist/assets/{da-DK-5WZEPLOC-DXGP9-TU.js → da-DK-5WZEPLOC-DZ68cfJh.js} +1 -1
- package/ui-dist/assets/{dagre-3AP2YEHR-Bt0GOj3f.js → dagre-3AP2YEHR-CuUE3cEY.js} +1 -1
- package/ui-dist/assets/{de-DE-XR44H4JA-ChR8kF4h.js → de-DE-XR44H4JA-ClBUqbwZ.js} +1 -1
- package/ui-dist/assets/{diagram-S7CK7UJ4-D2NIL20U.js → diagram-S7CK7UJ4-DjLndaJK.js} +1 -1
- package/ui-dist/assets/{diagram-UQ7AKVKN-Dty3qvRq.js → diagram-UQ7AKVKN-wLhxEBwN.js} +1 -1
- package/ui-dist/assets/{diagram-VSXAHHWV-znpNlomZ.js → diagram-VSXAHHWV-CVek4gvW.js} +1 -1
- package/ui-dist/assets/{diagram-VX7I27RA-DMKYB58y.js → diagram-VX7I27RA-CXyuaDuW.js} +1 -1
- package/ui-dist/assets/{diagram-Z3DM3KII-BLsAgfm1.js → diagram-Z3DM3KII-BGk8dw5c.js} +1 -1
- package/ui-dist/assets/{dist-Biz3NhE4.js → dist-DyDCC61R.js} +4 -4
- package/ui-dist/assets/{ebnfDiagram-PWID7BFC-sN1WpIzH.js → ebnfDiagram-PWID7BFC-Bq5wdWGX.js} +1 -1
- package/ui-dist/assets/{el-GR-BZB4AONW-BMi-5oTn.js → el-GR-BZB4AONW-oCuJWxYE.js} +1 -1
- package/ui-dist/assets/{en-B4ZKOASM-DTTcVPyw.js → en-B4ZKOASM-DevQWFhD.js} +1 -1
- package/ui-dist/assets/{erDiagram-SSCWMZ5O-qLib13wp.js → erDiagram-SSCWMZ5O-CXZW4I_b.js} +1 -1
- package/ui-dist/assets/{es-ES-U4NZUMDT-DSk-whe2.js → es-ES-U4NZUMDT-DgzMLG1J.js} +1 -1
- package/ui-dist/assets/{eu-ES-A7QVB2H4-Dlhf1HMz.js → eu-ES-A7QVB2H4-1tA3vosZ.js} +1 -1
- package/ui-dist/assets/eventmodeling-NTZA5JFV-Bh0QsTUi.js +1 -0
- package/ui-dist/assets/{fa-IR-HGAKTJCU-C4NL1SUQ.js → fa-IR-HGAKTJCU-BVbN6Ifb.js} +1 -1
- package/ui-dist/assets/{fi-FI-Z5N7JZ37-BPDGFbjy.js → fi-FI-Z5N7JZ37-DsGMdP7T.js} +1 -1
- package/ui-dist/assets/flowDiagram-A5DVABFB-Chb6hSSG.js +1 -0
- package/ui-dist/assets/{fr-FR-RHASNOE6-BKM44_qc.js → fr-FR-RHASNOE6-BEZa94DA.js} +1 -1
- package/ui-dist/assets/{ganttDiagram-EL5Y4UJY-Cm_9m3AA.js → ganttDiagram-EL5Y4UJY-BZxyNgRP.js} +1 -1
- package/ui-dist/assets/{gitGraph-4MIJSDKK-B53Ccobw.js → gitGraph-4MIJSDKK-Cz7F-_6d.js} +1 -1
- package/ui-dist/assets/{gitGraphDiagram-WWUBYQGX-CshbIfrd.js → gitGraphDiagram-WWUBYQGX-77gOaAOD.js} +1 -1
- package/ui-dist/assets/{gl-ES-HMX3MZ6V-CYq-Wgeo.js → gl-ES-HMX3MZ6V-DfSDz_sy.js} +1 -1
- package/ui-dist/assets/{he-IL-6SHJWFNN-CejOCh7c.js → he-IL-6SHJWFNN-DT8nqxK2.js} +1 -1
- package/ui-dist/assets/{hi-IN-IWLTKZ5I-DdZM6com.js → hi-IN-IWLTKZ5I-BtL1eizk.js} +1 -1
- package/ui-dist/assets/{hu-HU-A5ZG7DT2-DcLFRMuO.js → hu-HU-A5ZG7DT2-5FwjCLbT.js} +1 -1
- package/ui-dist/assets/{id-ID-SAP4L64H-1x9JAf0A.js → id-ID-SAP4L64H-DXfUbYET.js} +1 -1
- package/ui-dist/assets/image-GAAHSSAO-AgKiDvHK.js +1 -0
- package/ui-dist/assets/{index-CzWe1zeF.js → index-Boxo043A.js} +8 -8
- package/ui-dist/assets/{info-A6RAGUB7-Cge9ecX_.js → info-A6RAGUB7-DIe8iET8.js} +1 -1
- package/ui-dist/assets/{infoDiagram-RXCK75RN-VS1BTI_H.js → infoDiagram-RXCK75RN-Dik-rzpk.js} +1 -1
- package/ui-dist/assets/{ishikawaDiagram-5VMMS53U-Cbf1xbxj.js → ishikawaDiagram-5VMMS53U-Ccb-hHW6.js} +1 -1
- package/ui-dist/assets/{it-IT-JPQ66NNP-DgmQi0B_.js → it-IT-JPQ66NNP-6_sPHBVO.js} +1 -1
- package/ui-dist/assets/{ja-JP-DBVTYXUO-BpmMfXE3.js → ja-JP-DBVTYXUO-DgY_5_c8.js} +1 -1
- package/ui-dist/assets/{journeyDiagram-EYS64GPL-C8RWIfHV.js → journeyDiagram-EYS64GPL-CgzxmpyV.js} +1 -1
- package/ui-dist/assets/{kaa-6HZHGXH3-CczLR43o.js → kaa-6HZHGXH3-glmGx672.js} +1 -1
- package/ui-dist/assets/{kab-KAB-ZGHBKWFO-Cx74DVre.js → kab-KAB-ZGHBKWFO--G7baVL0.js} +1 -1
- package/ui-dist/assets/{kanban-definition-3QL26DDD-R8ng9q7k.js → kanban-definition-3QL26DDD-D6TnbrdQ.js} +1 -1
- package/ui-dist/assets/{kk-KZ-P5N5QNE5-BPvg9KTT.js → kk-KZ-P5N5QNE5-D3Vn0qgF.js} +1 -1
- package/ui-dist/assets/{km-KH-HSX4SM5Z-Blgo7Zit.js → km-KH-HSX4SM5Z-CAHt3o8M.js} +1 -1
- package/ui-dist/assets/{ko-KR-MTYHY66A-DZdo-KOi.js → ko-KR-MTYHY66A-N3tCiPap.js} +1 -1
- package/ui-dist/assets/{ku-TR-6OUDTVRD-CTpgWpW_.js → ku-TR-6OUDTVRD-CSZFwS--.js} +1 -1
- package/ui-dist/assets/{line-Baf15v0x.js → line-BhVZwKwh.js} +1 -1
- package/ui-dist/assets/{lt-LT-XHIRWOB4-DKNkbcsj.js → lt-LT-XHIRWOB4-DuSlkfc-.js} +1 -1
- package/ui-dist/assets/{lv-LV-5QDEKY6T-DwnZRxkH.js → lv-LV-5QDEKY6T-COuWGNLd.js} +1 -1
- package/ui-dist/assets/{mermaid-parser.core-0V2gZHuN.js → mermaid-parser.core-DlqbfUOM.js} +3 -3
- package/ui-dist/assets/{mindmap-definition-FBJOCRG2-7hOTFX4B.js → mindmap-definition-FBJOCRG2-D9wLjZXa.js} +1 -1
- package/ui-dist/assets/{mr-IN-CRQNXWMA-C-BFvdUk.js → mr-IN-CRQNXWMA-Bv4WHAzM.js} +1 -1
- package/ui-dist/assets/{my-MM-5M5IBNSE-BFs64Lrm.js → my-MM-5M5IBNSE-BNltBCCh.js} +1 -1
- package/ui-dist/assets/{nb-NO-T6EIAALU-CHGzOQzI.js → nb-NO-T6EIAALU-DgsGabVE.js} +1 -1
- package/ui-dist/assets/{nl-NL-IS3SIHDZ-CmrNJ43t.js → nl-NL-IS3SIHDZ-MPMxu0cH.js} +1 -1
- package/ui-dist/assets/{nn-NO-6E72VCQL-Cmx8XlD1.js → nn-NO-6E72VCQL-CY-NT6bD.js} +1 -1
- package/ui-dist/assets/{oc-FR-POXYY2M6-D6ZK0W24.js → oc-FR-POXYY2M6-BCWtA2dJ.js} +1 -1
- package/ui-dist/assets/{pa-IN-N4M65BXN-CoFjVv1P.js → pa-IN-N4M65BXN-CU1D5Lce.js} +1 -1
- package/ui-dist/assets/{packet-AYTQ26CC-auec35xT.js → packet-AYTQ26CC-DCMIIosG.js} +1 -1
- package/ui-dist/assets/{pegDiagram-XKGWAZYB-NMMkeAIs.js → pegDiagram-XKGWAZYB-CpU2aj-A.js} +1 -1
- package/ui-dist/assets/percentages-BXMCSKIN-CMz17NMy.js +1 -0
- package/ui-dist/assets/{pie-WAS4IAKB-Brhoju7F.js → pie-WAS4IAKB-BEVkH0em.js} +1 -1
- package/ui-dist/assets/{pieDiagram-E7YTZNPT-CbaXV2ep.js → pieDiagram-E7YTZNPT-D-jyX8nJ.js} +1 -1
- package/ui-dist/assets/{pl-PL-T2D74RX3-CtZh2-fJ.js → pl-PL-T2D74RX3-CwNWACCb.js} +1 -1
- package/ui-dist/assets/{pt-BR-5N22H2LF-Dwnm2Lle.js → pt-BR-5N22H2LF-DCs1W5P0.js} +1 -1
- package/ui-dist/assets/{pt-PT-UZXXM6DQ-Cb08TgqC.js → pt-PT-UZXXM6DQ-Bm9Hlh9S.js} +1 -1
- package/ui-dist/assets/{quadrantDiagram-AXDQQJYC-CXEPKL_-.js → quadrantDiagram-AXDQQJYC-BqzJD4zL.js} +1 -1
- package/ui-dist/assets/{radar-RG4KPBEZ-CTDsgRBl.js → radar-RG4KPBEZ-B6T3SZ4z.js} +1 -1
- package/ui-dist/assets/{railroad-74A4TZTK-Bad-j95k.js → railroad-74A4TZTK-BPKCaP4g.js} +1 -1
- package/ui-dist/assets/railroad-abnf-HS5TGJTU-RL2kk25t.js +1 -0
- package/ui-dist/assets/railroad-ebnf-LZEXJU2U-NY4mALmg.js +1 -0
- package/ui-dist/assets/railroad-peg-WCYAUIDC-BNAC9MGy.js +1 -0
- package/ui-dist/assets/{railroadDiagram-O6MQD6OU-CJiZ6mmg.js → railroadDiagram-O6MQD6OU-CzTuUKE-.js} +1 -1
- package/ui-dist/assets/{requirementDiagram-EFPCY7ZU-T8QMEZu6.js → requirementDiagram-EFPCY7ZU-Bly8_reu.js} +1 -1
- package/ui-dist/assets/{ro-RO-JPDTUUEW-D6H165NT.js → ro-RO-JPDTUUEW-DbKkWzmT.js} +1 -1
- package/ui-dist/assets/{ru-RU-B4JR7IUQ-CBp0xVXG.js → ru-RU-B4JR7IUQ-C7y8hptt.js} +1 -1
- package/ui-dist/assets/{sankeyDiagram-P5KCCOFB-Z9s0vmSt.js → sankeyDiagram-P5KCCOFB-BNe1jsYh.js} +1 -1
- package/ui-dist/assets/{sequenceDiagram-WJ2MYXX4-BulR70nw.js → sequenceDiagram-WJ2MYXX4-jpU3VDzA.js} +1 -1
- package/ui-dist/assets/{si-LK-N5RQ5JYF-10AxMH9e.js → si-LK-N5RQ5JYF-DsyN9eZC.js} +1 -1
- package/ui-dist/assets/{sk-SK-C5VTKIMK-BXvCxb46.js → sk-SK-C5VTKIMK-C3GmutL2.js} +1 -1
- package/ui-dist/assets/{sl-SI-NN7IZMDC-BI5_PFXZ.js → sl-SI-NN7IZMDC-C6dxM6aa.js} +1 -1
- package/ui-dist/assets/{stateDiagram-HBIQ2CUA-Dam0DwKS.js → stateDiagram-HBIQ2CUA-B2ZRnydN.js} +1 -1
- package/ui-dist/assets/stateDiagram-v2-4QOOHH4V-BUscqu-N.js +1 -0
- package/ui-dist/assets/subset-shared.chunk-CRXudW0i.js +1 -0
- package/ui-dist/assets/{subset-worker.chunk-BaDYCnkg.js → subset-worker.chunk-WItGSQq_.js} +1 -1
- package/ui-dist/assets/{sv-SE-XGPEYMSR-dVM3morJ.js → sv-SE-XGPEYMSR-BPU1z_vz.js} +1 -1
- package/ui-dist/assets/{swimlanes-XN3QIQJK-txWA6rWV.js → swimlanes-XN3QIQJK-BuYIN15M.js} +1 -1
- package/ui-dist/assets/swimlanesDiagram-VK2B7HYN-Cn_HC7uw.js +8 -0
- package/ui-dist/assets/{ta-IN-2NMHFXQM-CWJY03pN.js → ta-IN-2NMHFXQM-AJVbdGTO.js} +1 -1
- package/ui-dist/assets/{th-TH-HPSO5L25-CR6GhLgj.js → th-TH-HPSO5L25-B1vvYNmv.js} +1 -1
- package/ui-dist/assets/{timeline-definition-24CTP7MA-D8m_1UrT.js → timeline-definition-24CTP7MA-Bld3Oj9i.js} +1 -1
- package/ui-dist/assets/{tr-TR-DEFEU3FU-BI8tDJSm.js → tr-TR-DEFEU3FU-C_emJDca.js} +1 -1
- package/ui-dist/assets/{treeView-Q6P3EWNA-CWJmpg6A.js → treeView-Q6P3EWNA-CQEi50Re.js} +1 -1
- package/ui-dist/assets/{treemap-WGGIJYW6-CvClsvN5.js → treemap-WGGIJYW6-D3gRwGbr.js} +1 -1
- package/ui-dist/assets/{uk-UA-QMV73CPH-D3Uc38wP.js → uk-UA-QMV73CPH-B69Ddo0p.js} +1 -1
- package/ui-dist/assets/{vennDiagram-4TSXK5OY-C5iS8F8o.js → vennDiagram-4TSXK5OY-BWtR81LD.js} +1 -1
- package/ui-dist/assets/{vi-VN-M7AON7JQ-B6BZpyS4.js → vi-VN-M7AON7JQ-ByM0OkIF.js} +1 -1
- package/ui-dist/assets/{wardley-WFR3VGLG-CdqB7_9-.js → wardley-WFR3VGLG-DpBUmo8s.js} +1 -1
- package/ui-dist/assets/{wardleyDiagram-VM6X3IG4-DAHyWwbW.js → wardleyDiagram-VM6X3IG4-n39Dh9vZ.js} +1 -1
- package/ui-dist/assets/{xychartDiagram-S5SC5T6Z-ilyFTLQ_.js → xychartDiagram-S5SC5T6Z-D8-lcdGr.js} +1 -1
- package/ui-dist/assets/{zh-CN-LNUGB5OW-B0PN355q.js → zh-CN-LNUGB5OW-g_S93sCp.js} +1 -1
- package/ui-dist/assets/{zh-HK-E62DVLB3-DUEHDaPB.js → zh-HK-E62DVLB3-B3J_lyrF.js} +1 -1
- package/ui-dist/assets/{zh-TW-RAJ6MFWO-Ci4YMClQ.js → zh-TW-RAJ6MFWO-mYLP5aqQ.js} +1 -1
- package/ui-dist/index.html +1 -1
- package/ui-dist/assets/architecture-7GRP2DOG-fqG4giDT.js +0 -1
- package/ui-dist/assets/channel-BOrwYBHk.js +0 -1
- package/ui-dist/assets/classDiagram-DTDB5LWJ-Dm2kcSSm.js +0 -1
- package/ui-dist/assets/classDiagram-v2-JRS7N3AN-Dm2kcSSm.js +0 -1
- package/ui-dist/assets/eventmodeling-NTZA5JFV-BN91GLT5.js +0 -1
- package/ui-dist/assets/flowDiagram-A5DVABFB-DBrXJ-Jf.js +0 -1
- package/ui-dist/assets/image-GAAHSSAO-BgehxCDd.js +0 -1
- package/ui-dist/assets/percentages-BXMCSKIN-BBuUnwM-.js +0 -1
- package/ui-dist/assets/railroad-abnf-HS5TGJTU-CbvNSNpm.js +0 -1
- package/ui-dist/assets/railroad-ebnf-LZEXJU2U-DdltjnE0.js +0 -1
- package/ui-dist/assets/railroad-peg-WCYAUIDC-CgbxToYh.js +0 -1
- package/ui-dist/assets/stateDiagram-v2-4QOOHH4V-CSjCWsxW.js +0 -1
- package/ui-dist/assets/subset-shared.chunk-Du7WrYQy.js +0 -1
- package/ui-dist/assets/swimlanesDiagram-VK2B7HYN-CU4h0g7a.js +0 -8
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { SceneElement, PackName, PackKind, IconId, SceneId, Scene, SnapshotId, SERVER_MANAGED_FIELDS, BINDING_FIELDS, GUIDE_TOPICS, DetailLevel, createNodeSkeletonExpander, ok, fail, bridgeSpawnFailed, bridgeVersionMismatch, bridgeUnreachable, GuideTopic, storeUnavailable, describeThrown, unreadableSceneFile, pathOutsideRepo, packInstallFailed, sceneFileMissing, notAPack, PackRecipe, portUnavailable, DescribeSceneOutput, DescribeSceneInput, GetSelectionOutput, GetSelectionInput, GetElementsOutput, GetElementsInput, ListScenesOutput, ListScenesInput, SceneSettingsOutput, SceneSettingsInput, SearchIconsOutput, SearchIconsInput, ScreenshotOutput, ScreenshotInput, ReadMeOutput, ReadMeInput, PlaceIconOutput, PlaceIconInput, SnapshotOutput, SnapshotInput, RestoreSnapshotOutput, RestoreSnapshotInput, ExportSceneOutput, ExportSceneInput, ImportSceneOutput, ImportSceneInput, ExportImageOutput, ExportImageInput, InstallPackOutput, InstallPackInput, notARepo, ScreenshotResponse, RemovePackOutput, ListPacksOutput, RawElementsOutput, FocusOutput, EmbedOutput, AnnotateOutput, FrameOutput, UngroupOutput, GroupOutput, ArrangeOutput, DeleteElementsOutput, UpdateElementsOutput, ConnectOutput, CreateElementsOutput, HealthResponse, iconIdOf, unknownScene, unknownSnapshot, exportFailed, unknownIcon, HOUSE, FileId, ElementId, diskConflict, refusedFieldMessage, idCollision, expansionFailed, emptySelection, unknownElement, frameIdOf, GroupId, staleVersion, noBoundLabel, deepEqual, exportTimedOut, noBrowser, DebugElementRequest, CreateElementsInput, ConnectToolInput, UpdateElementsInput, DeleteElementsInput, ArrangeToolInput, GroupInput, UngroupInput, FrameInput, AnnotateInput, EmbedInput, FocusInput, RawElementsInput, ListPacksInput, RemovePackInput, DataUrl, Index, ROUNDNESS, STALE_SELECTION_MS, noScenes, ClientMessage, assertNever, PROTOCOL_VERSION, ApiError, EXCALIDRAW_FILE_VERSION, EXCALIDRAW_FILE_TYPE, point, FLAG_GLYPH, KIND_ABBREVIATION, catalogUnavailable, FrameId, IconItem, ExcalidrawFile } from './chunk-
|
|
2
|
+
import { SceneElement, PackName, PackKind, IconId, SceneId, Scene, SnapshotId, SERVER_MANAGED_FIELDS, BINDING_FIELDS, GUIDE_TOPICS, DetailLevel, createNodeSkeletonExpander, ok, fail, bridgeSpawnFailed, bridgeVersionMismatch, bridgeUnreachable, GuideTopic, storeUnavailable, describeThrown, unreadableSceneFile, pathOutsideRepo, packInstallFailed, sceneFileMissing, notAPack, PackRecipe, portUnavailable, DescribeSceneOutput, DescribeSceneInput, GetSelectionOutput, GetSelectionInput, GetElementsOutput, GetElementsInput, ListScenesOutput, ListScenesInput, SceneSettingsOutput, SceneSettingsInput, SearchIconsOutput, SearchIconsInput, ScreenshotOutput, ScreenshotInput, ReadMeOutput, ReadMeInput, PlaceIconOutput, PlaceIconInput, SnapshotOutput, SnapshotInput, RestoreSnapshotOutput, RestoreSnapshotInput, ExportSceneOutput, ExportSceneInput, ImportSceneOutput, ImportSceneInput, ExportImageOutput, ExportImageInput, InstallPackOutput, InstallPackInput, notARepo, ScreenshotResponse, RemovePackOutput, ListPacksOutput, RawElementsOutput, FocusOutput, EmbedOutput, AnnotateOutput, FrameOutput, UngroupOutput, GroupOutput, ArrangeOutput, DeleteElementsOutput, UpdateElementsOutput, ConnectOutput, CreateElementsOutput, HealthResponse, iconIdOf, unknownScene, unknownSnapshot, exportFailed, unknownIcon, HOUSE, FileId, ElementId, diskConflict, refusedFieldMessage, idCollision, expansionFailed, emptySelection, unknownElement, frameIdOf, GroupId, staleVersion, noBoundLabel, deepEqual, exportTimedOut, noBrowser, DebugElementRequest, CreateElementsInput, ConnectToolInput, UpdateElementsInput, DeleteElementsInput, ArrangeToolInput, GroupInput, UngroupInput, FrameInput, AnnotateInput, EmbedInput, FocusInput, RawElementsInput, ListPacksInput, RemovePackInput, iconNeedsAPlace, DataUrl, Index, ROUNDNESS, STALE_SELECTION_MS, noScenes, ClientMessage, assertNever, PROTOCOL_VERSION, ApiError, EXCALIDRAW_FILE_VERSION, EXCALIDRAW_FILE_TYPE, point, FLAG_GLYPH, measureLine, wrapLines, KIND_ABBREVIATION, catalogUnavailable, FrameId, IconItem, ExcalidrawFile } from './chunk-XDK5UUTO.js';
|
|
3
3
|
import './chunk-7D4SUZUM.js';
|
|
4
4
|
import { appendFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
5
5
|
import { homedir } from 'node:os';
|
|
@@ -2025,6 +2025,109 @@ function createExportBroker(options, deps) {
|
|
|
2025
2025
|
};
|
|
2026
2026
|
}
|
|
2027
2027
|
|
|
2028
|
+
// src/domain/scene/overlaps.ts
|
|
2029
|
+
var MIN_OVERLAP_PX = 2;
|
|
2030
|
+
var MAX_REPORTED_OVERLAPS = 12;
|
|
2031
|
+
function routeMidpoint(arrow) {
|
|
2032
|
+
const points = arrow.points;
|
|
2033
|
+
const lengths = points.slice(1).map((p, i) => {
|
|
2034
|
+
const prev = points[i];
|
|
2035
|
+
const [px2, py] = p;
|
|
2036
|
+
if (prev === void 0 || px2 === void 0 || py === void 0) return 0;
|
|
2037
|
+
const [qx, qy] = prev;
|
|
2038
|
+
if (qx === void 0 || qy === void 0) return 0;
|
|
2039
|
+
return Math.hypot(px2 - qx, py - qy);
|
|
2040
|
+
});
|
|
2041
|
+
let want = lengths.reduce((sum, l) => sum + l, 0) / 2;
|
|
2042
|
+
for (let i = 0; i < lengths.length; i++) {
|
|
2043
|
+
const from = points[i];
|
|
2044
|
+
const to = points[i + 1];
|
|
2045
|
+
const length = lengths[i];
|
|
2046
|
+
if (from === void 0 || to === void 0 || length === void 0) continue;
|
|
2047
|
+
const [fx, fy] = from;
|
|
2048
|
+
const [tx, ty] = to;
|
|
2049
|
+
if (fx === void 0 || fy === void 0 || tx === void 0 || ty === void 0) continue;
|
|
2050
|
+
if (want > length && i < lengths.length - 1) {
|
|
2051
|
+
want -= length;
|
|
2052
|
+
continue;
|
|
2053
|
+
}
|
|
2054
|
+
const k = length === 0 ? 0 : want / length;
|
|
2055
|
+
return { x: arrow.x + fx + (tx - fx) * k, y: arrow.y + fy + (ty - fy) * k };
|
|
2056
|
+
}
|
|
2057
|
+
return { x: arrow.x, y: arrow.y };
|
|
2058
|
+
}
|
|
2059
|
+
function renderedRect(element, byId) {
|
|
2060
|
+
if (element.type !== "text" || element.containerId === null) return element;
|
|
2061
|
+
const container = byId.get(element.containerId);
|
|
2062
|
+
if (container === void 0 || container.type !== "arrow") return element;
|
|
2063
|
+
const mid = routeMidpoint(container);
|
|
2064
|
+
return {
|
|
2065
|
+
x: mid.x - element.width / 2,
|
|
2066
|
+
y: mid.y - element.height / 2,
|
|
2067
|
+
width: element.width,
|
|
2068
|
+
height: element.height
|
|
2069
|
+
};
|
|
2070
|
+
}
|
|
2071
|
+
var intersection = (a, b) => ({
|
|
2072
|
+
width: Math.min(a.x + a.width, b.x + b.width) - Math.max(a.x, b.x),
|
|
2073
|
+
height: Math.min(a.y + a.height, b.y + b.height) - Math.max(a.y, b.y)
|
|
2074
|
+
});
|
|
2075
|
+
function rectsOverlap(a, b) {
|
|
2076
|
+
const { width, height } = intersection(a, b);
|
|
2077
|
+
return width >= MIN_OVERLAP_PX && height >= MIN_OVERLAP_PX;
|
|
2078
|
+
}
|
|
2079
|
+
function frameOf(element, byId) {
|
|
2080
|
+
if (element.frameId !== null) return element.frameId;
|
|
2081
|
+
if (element.type !== "text" || element.containerId === null) return null;
|
|
2082
|
+
return byId.get(element.containerId)?.frameId ?? null;
|
|
2083
|
+
}
|
|
2084
|
+
function nested(a, b, byId) {
|
|
2085
|
+
if (a.type === "frame" && frameOf(b, byId) === frameIdOf(a.id)) return true;
|
|
2086
|
+
if (b.type === "frame" && frameOf(a, byId) === frameIdOf(b.id)) return true;
|
|
2087
|
+
if (a.type === "text" && a.containerId === b.id && b.type !== "arrow") return true;
|
|
2088
|
+
if (b.type === "text" && b.containerId === a.id && a.type !== "arrow") return true;
|
|
2089
|
+
return false;
|
|
2090
|
+
}
|
|
2091
|
+
var participates = (element) => !element.isDeleted && element.type !== "arrow" && element.type !== "line" && // Frames are regions, not shapes. One is 600 px across, so nearly everything near it
|
|
2092
|
+
// intersects its area — and unlike a box it does not obscure what it covers, because a
|
|
2093
|
+
// frame only clips its *own* children. Reporting non-children put a warning on every
|
|
2094
|
+
// framed diagram, which is the noise this file exists to avoid. The case that genuinely
|
|
2095
|
+
// hides content — a child outside the frame holding it — is prevented rather than
|
|
2096
|
+
// reported: `frames.refitFrames` grows the frame on every path that can move a child.
|
|
2097
|
+
element.type !== "frame" && element.width > 0 && element.height > 0;
|
|
2098
|
+
function wouldCollide(candidate, elements, ignore = /* @__PURE__ */ new Set()) {
|
|
2099
|
+
const byId = new Map(elements.map((element) => [element.id, element]));
|
|
2100
|
+
return elements.filter(participates).filter((element) => !ignore.has(element.id)).some((element) => rectsOverlap(candidate, renderedRect(element, byId)));
|
|
2101
|
+
}
|
|
2102
|
+
function findOverlaps(elements) {
|
|
2103
|
+
const byId = new Map(elements.map((element) => [element.id, element]));
|
|
2104
|
+
const live = elements.filter(participates);
|
|
2105
|
+
const found = [];
|
|
2106
|
+
for (let i = 0; i < live.length; i++) {
|
|
2107
|
+
const a = live[i];
|
|
2108
|
+
if (a === void 0) continue;
|
|
2109
|
+
for (let j = i + 1; j < live.length; j++) {
|
|
2110
|
+
const b = live[j];
|
|
2111
|
+
if (b === void 0) continue;
|
|
2112
|
+
if (nested(a, b, byId)) continue;
|
|
2113
|
+
const { width, height } = intersection(renderedRect(a, byId), renderedRect(b, byId));
|
|
2114
|
+
if (width < MIN_OVERLAP_PX || height < MIN_OVERLAP_PX) continue;
|
|
2115
|
+
found.push({ a: a.id, b: b.id, width: Math.round(width), height: Math.round(height) });
|
|
2116
|
+
}
|
|
2117
|
+
}
|
|
2118
|
+
return found.sort(
|
|
2119
|
+
(p, q) => q.width * q.height - p.width * p.height || (p.a < q.a ? -1 : p.a > q.a ? 1 : 0) || (p.b < q.b ? -1 : p.b > q.b ? 1 : 0)
|
|
2120
|
+
);
|
|
2121
|
+
}
|
|
2122
|
+
function overlapWarning(elements) {
|
|
2123
|
+
const found = findOverlaps(elements);
|
|
2124
|
+
const worst = found[0];
|
|
2125
|
+
if (worst === void 0) return null;
|
|
2126
|
+
const size = `${Math.round(worst.width)}x${Math.round(worst.height)}`;
|
|
2127
|
+
const count2 = found.length === 1 ? "1 overlap" : `${found.length} overlaps`;
|
|
2128
|
+
return `${count2} on the canvas \u2014 worst ${worst.a} \xD7 ${worst.b} (${size}). chalk_describe_scene lists them; chalk_arrange moves them apart`;
|
|
2129
|
+
}
|
|
2130
|
+
|
|
2028
2131
|
// src/domain/scene/observe.ts
|
|
2029
2132
|
var SHORT_ID_LENGTH = 4;
|
|
2030
2133
|
var shortId2 = (id) => id.slice(0, SHORT_ID_LENGTH);
|
|
@@ -2131,6 +2234,7 @@ function observeScene(input) {
|
|
|
2131
2234
|
const selected = new Set(input.selectedIds ?? []);
|
|
2132
2235
|
const context = { labels, frames, selected, detail: input.detail };
|
|
2133
2236
|
const rows = rowElements(scene.elements).filter((element) => element.type !== "frame");
|
|
2237
|
+
const overlaps = findOverlaps(scene.elements);
|
|
2134
2238
|
return {
|
|
2135
2239
|
sceneId: scene.id,
|
|
2136
2240
|
name: scene.name,
|
|
@@ -2139,6 +2243,8 @@ function observeScene(input) {
|
|
|
2139
2243
|
updatedAgoMs: Math.max(0, input.now - scene.updatedAt),
|
|
2140
2244
|
frames: [...frames.values()],
|
|
2141
2245
|
elements: rows.map((element) => describeElement(element, context)),
|
|
2246
|
+
overlaps: overlaps.slice(0, MAX_REPORTED_OVERLAPS),
|
|
2247
|
+
overlapCount: overlaps.length,
|
|
2142
2248
|
detail: input.detail
|
|
2143
2249
|
};
|
|
2144
2250
|
}
|
|
@@ -3171,6 +3277,10 @@ function restoreSnapshot(deps) {
|
|
|
3171
3277
|
sceneId: scene.id,
|
|
3172
3278
|
sceneVersion: updated.sceneVersion,
|
|
3173
3279
|
broadcastTo,
|
|
3280
|
+
// A restore puts back exactly what was saved, so any collision in it is the one the
|
|
3281
|
+
// snapshot was taken with. Worth saying: the reader is often restoring *because* a
|
|
3282
|
+
// layout went wrong, and silence here would read as "the old one was clean".
|
|
3283
|
+
overlapWarning: overlapWarning(snapshot.elements),
|
|
3174
3284
|
snapshotId: snapshot.summary.id,
|
|
3175
3285
|
label: snapshot.summary.label,
|
|
3176
3286
|
restored: snapshot.elements.filter((element) => !element.isDeleted).length
|
|
@@ -3195,6 +3305,19 @@ function serviceSize() {
|
|
|
3195
3305
|
const [width, height] = HOUSE.sizes.service;
|
|
3196
3306
|
return { width, height };
|
|
3197
3307
|
}
|
|
3308
|
+
var LINE_HEIGHT = 1.25;
|
|
3309
|
+
var quantise = (value) => Math.ceil(value / HOUSE.grid) * HOUSE.grid;
|
|
3310
|
+
function labelledSize(label, fontSize = HOUSE.fontSize) {
|
|
3311
|
+
const floor = serviceSize();
|
|
3312
|
+
if (label === void 0 || label === "") return floor;
|
|
3313
|
+
const padX = HOUSE.sizes.labelPadX * 2;
|
|
3314
|
+
const padY = HOUSE.sizes.labelPadY * 2;
|
|
3315
|
+
const oneLine = measureLine(label, fontSize) + padX;
|
|
3316
|
+
const width = Math.max(floor.width, quantise(Math.min(oneLine, HOUSE.sizes.maxBox)));
|
|
3317
|
+
const lines = wrapLines(label, fontSize, width - padX);
|
|
3318
|
+
const height = Math.max(floor.height, quantise(lines.length * fontSize * LINE_HEIGHT + padY));
|
|
3319
|
+
return { width, height };
|
|
3320
|
+
}
|
|
3198
3321
|
|
|
3199
3322
|
// src/app/usecases/write/annotate-elements.ts
|
|
3200
3323
|
var NOTE_GAP = 24;
|
|
@@ -3273,6 +3396,120 @@ function focusElements(deps) {
|
|
|
3273
3396
|
return ok({ sceneId: scene.value.id, focused, broadcastTo });
|
|
3274
3397
|
};
|
|
3275
3398
|
}
|
|
3399
|
+
|
|
3400
|
+
// src/domain/scene/anchors.ts
|
|
3401
|
+
var ANCHOR_GAP = 12;
|
|
3402
|
+
var anchorsOf = (element) => element.customData?.chalk?.anchorIds ?? [];
|
|
3403
|
+
var isAnchored = (element) => anchorsOf(element).length > 0;
|
|
3404
|
+
function anchoredPosition(anchor, size, placement) {
|
|
3405
|
+
const midX = anchor.x + anchor.width / 2 - size.width / 2;
|
|
3406
|
+
const midY = anchor.y + anchor.height / 2 - size.height / 2;
|
|
3407
|
+
switch (placement) {
|
|
3408
|
+
case "above":
|
|
3409
|
+
return { x: midX, y: anchor.y - size.height - ANCHOR_GAP };
|
|
3410
|
+
case "below":
|
|
3411
|
+
return { x: midX, y: anchor.y + anchor.height + ANCHOR_GAP };
|
|
3412
|
+
case "left":
|
|
3413
|
+
return { x: anchor.x - size.width - ANCHOR_GAP, y: midY };
|
|
3414
|
+
case "right":
|
|
3415
|
+
return { x: anchor.x + anchor.width + ANCHOR_GAP, y: midY };
|
|
3416
|
+
case "badge":
|
|
3417
|
+
return { x: anchor.x + anchor.width - size.width / 2, y: anchor.y - size.height / 2 };
|
|
3418
|
+
case "inside":
|
|
3419
|
+
return { x: midX, y: midY };
|
|
3420
|
+
}
|
|
3421
|
+
}
|
|
3422
|
+
var captionBelow = (position, size) => ({
|
|
3423
|
+
x: position.x,
|
|
3424
|
+
y: position.y + size.height + 8
|
|
3425
|
+
});
|
|
3426
|
+
function withAnchoredElements(scene, deltas) {
|
|
3427
|
+
const attached = scene.filter((element) => !element.isDeleted && isAnchored(element));
|
|
3428
|
+
if (attached.length === 0) return deltas;
|
|
3429
|
+
const widened = new Map(deltas);
|
|
3430
|
+
const present2 = new Set(scene.filter((element) => !element.isDeleted).map((e) => e.id));
|
|
3431
|
+
for (const element of attached) {
|
|
3432
|
+
if (widened.has(element.id)) continue;
|
|
3433
|
+
const live = anchorsOf(element).filter((id) => present2.has(id));
|
|
3434
|
+
if (live.length === 0) continue;
|
|
3435
|
+
const moves = live.map((id) => deltas.get(id));
|
|
3436
|
+
const [first] = moves;
|
|
3437
|
+
if (first === void 0) continue;
|
|
3438
|
+
if (!moves.every((move) => move !== void 0 && move[0] === first[0] && move[1] === first[1])) {
|
|
3439
|
+
continue;
|
|
3440
|
+
}
|
|
3441
|
+
widened.set(element.id, first);
|
|
3442
|
+
}
|
|
3443
|
+
return widened;
|
|
3444
|
+
}
|
|
3445
|
+
|
|
3446
|
+
// src/domain/scene/frames.ts
|
|
3447
|
+
function boundsAround(children) {
|
|
3448
|
+
const pad2 = HOUSE.sizes.framePad;
|
|
3449
|
+
const left = Math.min(...children.map((c) => c.x));
|
|
3450
|
+
const top = Math.min(...children.map((c) => c.y));
|
|
3451
|
+
const right = Math.max(...children.map((c) => c.x + c.width));
|
|
3452
|
+
const bottom = Math.max(...children.map((c) => c.y + c.height));
|
|
3453
|
+
return {
|
|
3454
|
+
x: left - pad2,
|
|
3455
|
+
y: top - pad2,
|
|
3456
|
+
width: right - left + pad2 * 2,
|
|
3457
|
+
// Room at the top for the frame's own name, which renders above its border.
|
|
3458
|
+
height: bottom - top + pad2 * 2
|
|
3459
|
+
};
|
|
3460
|
+
}
|
|
3461
|
+
function childrenOf(scene, frame) {
|
|
3462
|
+
const id = frameIdOf(frame.id);
|
|
3463
|
+
return scene.filter(
|
|
3464
|
+
(element) => !element.isDeleted && element.id !== frame.id && element.frameId === id
|
|
3465
|
+
);
|
|
3466
|
+
}
|
|
3467
|
+
function releaseCrossingArrows(scene, frame) {
|
|
3468
|
+
const id = frameIdOf(frame.id);
|
|
3469
|
+
const inside = new Set(childrenOf(scene, frame).map((element) => element.id));
|
|
3470
|
+
const byId = new Map(scene.map((element) => [element.id, element]));
|
|
3471
|
+
return childrenOf(scene, frame).filter((element) => element.type === "arrow" || element.type === "line").filter((arrow) => {
|
|
3472
|
+
if (arrow.type !== "arrow") return true;
|
|
3473
|
+
const from = arrow.startBinding?.elementId;
|
|
3474
|
+
const to = arrow.endBinding?.elementId;
|
|
3475
|
+
if (from === void 0 || to === void 0) return true;
|
|
3476
|
+
return !(inside.has(from) && inside.has(to));
|
|
3477
|
+
}).filter((arrow) => byId.get(arrow.id)?.frameId === id).map((arrow) => ({ ...arrow, frameId: null }));
|
|
3478
|
+
}
|
|
3479
|
+
function withFrameChildren(scene, deltas) {
|
|
3480
|
+
const frames = scene.filter(
|
|
3481
|
+
(element) => element.type === "frame" && !element.isDeleted && deltas.has(element.id)
|
|
3482
|
+
);
|
|
3483
|
+
if (frames.length === 0) return deltas;
|
|
3484
|
+
const widened = new Map(deltas);
|
|
3485
|
+
for (const frame of frames) {
|
|
3486
|
+
const delta = deltas.get(frame.id);
|
|
3487
|
+
if (delta === void 0) continue;
|
|
3488
|
+
for (const child of childrenOf(scene, frame)) {
|
|
3489
|
+
if (widened.has(child.id)) continue;
|
|
3490
|
+
widened.set(child.id, delta);
|
|
3491
|
+
}
|
|
3492
|
+
}
|
|
3493
|
+
return widened;
|
|
3494
|
+
}
|
|
3495
|
+
function refitFrames(scene, moved) {
|
|
3496
|
+
if (moved.size === 0) return [];
|
|
3497
|
+
const current = scene.map((element) => moved.get(element.id) ?? element);
|
|
3498
|
+
const refitted = [];
|
|
3499
|
+
for (const element of current) {
|
|
3500
|
+
if (element.type !== "frame" || element.isDeleted) continue;
|
|
3501
|
+
const crossing = new Set(releaseCrossingArrows(current, element).map((a) => a.id));
|
|
3502
|
+
const children = childrenOf(current, element).filter((c) => !crossing.has(c.id));
|
|
3503
|
+
if (children.length === 0) continue;
|
|
3504
|
+
if (!children.some((child) => moved.has(child.id))) continue;
|
|
3505
|
+
const box = boundsAround(children);
|
|
3506
|
+
if (element.x === box.x && element.y === box.y && element.width === box.width && element.height === box.height) {
|
|
3507
|
+
continue;
|
|
3508
|
+
}
|
|
3509
|
+
refitted.push({ ...element, ...box });
|
|
3510
|
+
}
|
|
3511
|
+
return refitted;
|
|
3512
|
+
}
|
|
3276
3513
|
function highestIndex(elements) {
|
|
3277
3514
|
let highest = null;
|
|
3278
3515
|
for (const element of elements) {
|
|
@@ -3337,7 +3574,7 @@ function edgePoint(from, to, gap) {
|
|
|
3337
3574
|
const t = scale + push;
|
|
3338
3575
|
return [cx + dx * t, cy + dy * t];
|
|
3339
3576
|
}
|
|
3340
|
-
function redrawOne(current, labels, arrow) {
|
|
3577
|
+
function redrawOne(current, labels, arrow, lane) {
|
|
3341
3578
|
if (arrow.type !== "arrow") return [];
|
|
3342
3579
|
const fromId = startOf(arrow);
|
|
3343
3580
|
const toId = endOf(arrow);
|
|
@@ -3347,40 +3584,126 @@ function redrawOne(current, labels, arrow) {
|
|
|
3347
3584
|
if (from === void 0 || to === void 0) return [];
|
|
3348
3585
|
const startGap = arrow.startBinding?.gap ?? 4;
|
|
3349
3586
|
const endGap = arrow.endBinding?.gap ?? 4;
|
|
3350
|
-
const
|
|
3351
|
-
const [ex, ey] =
|
|
3352
|
-
|
|
3587
|
+
const elbowed = arrow.elbowed === true;
|
|
3588
|
+
const [sx, sy, ex, ey] = elbowed ? facePoints(boxOf(from), boxOf(to), startGap, endGap, lane) : [
|
|
3589
|
+
...edgePoint(boxOf(from), boxOf(to), startGap),
|
|
3590
|
+
...edgePoint(boxOf(to), boxOf(from), endGap)
|
|
3591
|
+
];
|
|
3592
|
+
const points = elbowed ? elbowRoute(ex - sx, ey - sy) : [point(0, 0), point(ex - sx, ey - sy)];
|
|
3593
|
+
const spans = points.reduce(
|
|
3594
|
+
(box, [px2, py]) => ({
|
|
3595
|
+
w: Math.max(box.w, Math.abs(px2)),
|
|
3596
|
+
h: Math.max(box.h, Math.abs(py))
|
|
3597
|
+
}),
|
|
3598
|
+
{ w: 0, h: 0 }
|
|
3599
|
+
);
|
|
3353
3600
|
const redrawn = {
|
|
3354
3601
|
...arrow,
|
|
3355
3602
|
x: sx,
|
|
3356
3603
|
y: sy,
|
|
3357
|
-
width:
|
|
3358
|
-
height:
|
|
3604
|
+
width: spans.w,
|
|
3605
|
+
height: spans.h,
|
|
3359
3606
|
points,
|
|
3360
3607
|
lastCommittedPoint: null
|
|
3361
3608
|
};
|
|
3362
3609
|
const label = labels.get(arrow.id);
|
|
3363
3610
|
if (label === void 0) return [redrawn];
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3611
|
+
const mid = routeMidpoint({ x: sx, y: sy, points });
|
|
3612
|
+
const at = { x: mid.x - label.width / 2, y: mid.y - label.height / 2 };
|
|
3613
|
+
return [redrawn, { ...label, ...at }];
|
|
3614
|
+
}
|
|
3615
|
+
function faceBetween(from, to) {
|
|
3616
|
+
const [fx, fy] = centre(from);
|
|
3617
|
+
const [tx, ty] = centre(to);
|
|
3618
|
+
const dx = tx - fx;
|
|
3619
|
+
const dy = ty - fy;
|
|
3620
|
+
if (Math.abs(dx) >= Math.abs(dy)) return dx >= 0 ? "right" : "left";
|
|
3621
|
+
return dy >= 0 ? "bottom" : "top";
|
|
3622
|
+
}
|
|
3623
|
+
var LANE_SPREAD = 44;
|
|
3624
|
+
function laneOffsets(arrows, current) {
|
|
3625
|
+
const groups = /* @__PURE__ */ new Map();
|
|
3626
|
+
const add = (nodeId, face, node, slot) => {
|
|
3627
|
+
const key = `${nodeId}|${face}`;
|
|
3628
|
+
const bucket = groups.get(key);
|
|
3629
|
+
if (bucket === void 0) groups.set(key, { face, node, slots: [slot] });
|
|
3630
|
+
else bucket.slots.push(slot);
|
|
3631
|
+
};
|
|
3632
|
+
const across = (face, box) => face === "right" || face === "left" ? centre(box)[1] : centre(box)[0];
|
|
3633
|
+
for (const arrow of arrows) {
|
|
3634
|
+
if (arrow.type !== "arrow" || arrow.elbowed !== true) continue;
|
|
3635
|
+
const fromId = startOf(arrow);
|
|
3636
|
+
const toId = endOf(arrow);
|
|
3637
|
+
if (fromId === null || toId === null) continue;
|
|
3638
|
+
const from = current.get(fromId);
|
|
3639
|
+
const to = current.get(toId);
|
|
3640
|
+
if (from === void 0 || to === void 0) continue;
|
|
3641
|
+
const outFace = faceBetween(boxOf(from), boxOf(to));
|
|
3642
|
+
const inFace = faceBetween(boxOf(to), boxOf(from));
|
|
3643
|
+
add(fromId, outFace, boxOf(from), {
|
|
3644
|
+
arrow: arrow.id,
|
|
3645
|
+
end: "start",
|
|
3646
|
+
along: across(outFace, boxOf(to))
|
|
3647
|
+
});
|
|
3648
|
+
add(toId, inFace, boxOf(to), {
|
|
3649
|
+
arrow: arrow.id,
|
|
3650
|
+
end: "end",
|
|
3651
|
+
along: across(inFace, boxOf(from))
|
|
3652
|
+
});
|
|
3653
|
+
}
|
|
3654
|
+
const offsets = /* @__PURE__ */ new Map();
|
|
3655
|
+
for (const { face, node, slots } of groups.values()) {
|
|
3656
|
+
if (slots.length < 2) continue;
|
|
3657
|
+
slots.sort((a, b) => a.along - b.along || (a.arrow < b.arrow ? -1 : 1));
|
|
3658
|
+
const span = face === "right" || face === "left" ? node.height : node.width;
|
|
3659
|
+
const spread = Math.min(LANE_SPREAD, span / (slots.length + 1));
|
|
3660
|
+
slots.forEach((slot, i) => {
|
|
3661
|
+
const shift = (i - (slots.length - 1) / 2) * spread;
|
|
3662
|
+
const so_far = offsets.get(slot.arrow) ?? { start: 0, end: 0 };
|
|
3663
|
+
offsets.set(slot.arrow, { ...so_far, [slot.end]: shift });
|
|
3664
|
+
});
|
|
3665
|
+
}
|
|
3666
|
+
return offsets;
|
|
3667
|
+
}
|
|
3668
|
+
function facePoints(from, to, startGap, endGap, lane) {
|
|
3669
|
+
const [fx, fy] = centre(from);
|
|
3670
|
+
const [tx, ty] = centre(to);
|
|
3671
|
+
const dx = tx - fx;
|
|
3672
|
+
const dy = ty - fy;
|
|
3673
|
+
if (Math.abs(dx) >= Math.abs(dy)) {
|
|
3674
|
+
const sx = dx >= 0 ? from.x + from.width + startGap : from.x - startGap;
|
|
3675
|
+
const ex = dx >= 0 ? to.x - endGap : to.x + to.width + endGap;
|
|
3676
|
+
return [sx, fy + lane.start, ex, ty + lane.end];
|
|
3677
|
+
}
|
|
3678
|
+
const sy = dy >= 0 ? from.y + from.height + startGap : from.y - startGap;
|
|
3679
|
+
const ey = dy >= 0 ? to.y - endGap : to.y + to.height + endGap;
|
|
3680
|
+
return [fx + lane.start, sy, tx + lane.end, ey];
|
|
3681
|
+
}
|
|
3682
|
+
function elbowRoute(dx, dy) {
|
|
3683
|
+
const ALIGNED = 1;
|
|
3684
|
+
if (Math.abs(dy) <= ALIGNED || Math.abs(dx) <= ALIGNED) {
|
|
3685
|
+
return [point(0, 0), point(dx, dy)];
|
|
3686
|
+
}
|
|
3687
|
+
if (Math.abs(dx) >= Math.abs(dy)) {
|
|
3688
|
+
const mid2 = dx / 2;
|
|
3689
|
+
return [point(0, 0), point(mid2, 0), point(mid2, dy), point(dx, dy)];
|
|
3690
|
+
}
|
|
3691
|
+
const mid = dy / 2;
|
|
3692
|
+
return [point(0, 0), point(0, mid), point(dx, mid), point(dx, dy)];
|
|
3372
3693
|
}
|
|
3373
3694
|
function redrawArrowsTouching(scene, moved) {
|
|
3374
3695
|
const current = new Map(scene.map((element) => [element.id, moved.get(element.id) ?? element]));
|
|
3375
3696
|
const labels = labelsByContainer([...current.values()]);
|
|
3376
3697
|
const redrawn = [];
|
|
3698
|
+
const lanes = laneOffsets([...current.values()], current);
|
|
3699
|
+
const NO_LANE = { start: 0, end: 0 };
|
|
3377
3700
|
for (const element of current.values()) {
|
|
3378
3701
|
if (element.type !== "arrow") continue;
|
|
3379
3702
|
const fromId = startOf(element);
|
|
3380
3703
|
const toId = endOf(element);
|
|
3381
3704
|
if (fromId === null || toId === null) continue;
|
|
3382
3705
|
if (!moved.has(fromId) && !moved.has(toId)) continue;
|
|
3383
|
-
redrawn.push(...redrawOne(current, labels, element));
|
|
3706
|
+
redrawn.push(...redrawOne(current, labels, element, lanes.get(element.id) ?? NO_LANE));
|
|
3384
3707
|
}
|
|
3385
3708
|
return redrawn;
|
|
3386
3709
|
}
|
|
@@ -3388,13 +3711,16 @@ function redrawArrows(scene, ids) {
|
|
|
3388
3711
|
const current = new Map(scene.map((element) => [element.id, element]));
|
|
3389
3712
|
const labels = labelsByContainer(scene);
|
|
3390
3713
|
const wanted = new Set(ids);
|
|
3391
|
-
|
|
3714
|
+
const lanes = laneOffsets([...current.values()], current);
|
|
3715
|
+
const NO_LANE = { start: 0, end: 0 };
|
|
3716
|
+
return [...current.values()].filter((element) => wanted.has(element.id)).flatMap((element) => redrawOne(current, labels, element, lanes.get(element.id) ?? NO_LANE));
|
|
3392
3717
|
}
|
|
3393
3718
|
function translate(scene, deltas) {
|
|
3719
|
+
const widened = withAnchoredElements(scene, withFrameChildren(scene, deltas));
|
|
3394
3720
|
const labels = labelsByContainer(scene);
|
|
3395
3721
|
const moved = /* @__PURE__ */ new Map();
|
|
3396
3722
|
for (const element of scene) {
|
|
3397
|
-
const delta =
|
|
3723
|
+
const delta = widened.get(element.id);
|
|
3398
3724
|
if (delta === void 0) continue;
|
|
3399
3725
|
const [dx, dy] = delta;
|
|
3400
3726
|
if (dx === 0 && dy === 0) continue;
|
|
@@ -3404,7 +3730,10 @@ function translate(scene, deltas) {
|
|
|
3404
3730
|
moved.set(label.id, { ...label, x: label.x + dx, y: label.y + dy });
|
|
3405
3731
|
}
|
|
3406
3732
|
}
|
|
3407
|
-
|
|
3733
|
+
const changed = new Map(moved);
|
|
3734
|
+
for (const element of redrawArrowsTouching(scene, moved)) changed.set(element.id, element);
|
|
3735
|
+
for (const element of refitFrames(scene, moved)) changed.set(element.id, element);
|
|
3736
|
+
return [...changed.values()];
|
|
3408
3737
|
}
|
|
3409
3738
|
var alignments = {
|
|
3410
3739
|
"align-left": (box, bounds) => [bounds.x - box.x, 0],
|
|
@@ -3545,18 +3874,11 @@ function layoutLayered(scene, targets, spacing) {
|
|
|
3545
3874
|
if (!inSet.has(from) || !inSet.has(to) || from === to) continue;
|
|
3546
3875
|
edges.push({ from, to });
|
|
3547
3876
|
}
|
|
3548
|
-
const nodes = targets.filter((element) => !isLinear(element));
|
|
3877
|
+
const nodes = targets.filter((element) => !isLinear(element) && !isAnchored(element));
|
|
3549
3878
|
if (nodes.length === 0) return [];
|
|
3550
3879
|
const incoming = /* @__PURE__ */ new Map();
|
|
3551
|
-
const
|
|
3552
|
-
for (const
|
|
3553
|
-
incoming.set(node.id, []);
|
|
3554
|
-
outgoing.set(node.id, []);
|
|
3555
|
-
}
|
|
3556
|
-
for (const edge of edges) {
|
|
3557
|
-
incoming.get(edge.to)?.push(edge.from);
|
|
3558
|
-
outgoing.get(edge.from)?.push(edge.to);
|
|
3559
|
-
}
|
|
3880
|
+
for (const node of nodes) incoming.set(node.id, []);
|
|
3881
|
+
for (const edge of edges) incoming.get(edge.to)?.push(edge.from);
|
|
3560
3882
|
const rank = new Map(nodes.map((node) => [node.id, 0]));
|
|
3561
3883
|
for (let pass = 0; pass < nodes.length; pass++) {
|
|
3562
3884
|
let settled = true;
|
|
@@ -3570,57 +3892,101 @@ function layoutLayered(scene, targets, spacing) {
|
|
|
3570
3892
|
}
|
|
3571
3893
|
if (settled) break;
|
|
3572
3894
|
}
|
|
3573
|
-
const
|
|
3895
|
+
const LANE_WIDTH = 0;
|
|
3896
|
+
const LANE_HEIGHT = 48;
|
|
3897
|
+
const slots = /* @__PURE__ */ new Map();
|
|
3898
|
+
const push = (r, slot) => {
|
|
3899
|
+
const bucket = slots.get(r);
|
|
3900
|
+
if (bucket === void 0) slots.set(r, [slot]);
|
|
3901
|
+
else bucket.push(slot);
|
|
3902
|
+
};
|
|
3574
3903
|
for (const node of nodes) {
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3904
|
+
push(rank.get(node.id) ?? 0, {
|
|
3905
|
+
key: node.id,
|
|
3906
|
+
box: boxOf(node),
|
|
3907
|
+
parents: incoming.get(node.id) ?? [],
|
|
3908
|
+
node
|
|
3909
|
+
});
|
|
3910
|
+
}
|
|
3911
|
+
for (const edge of edges) {
|
|
3912
|
+
const from = rank.get(edge.from);
|
|
3913
|
+
const to = rank.get(edge.to);
|
|
3914
|
+
if (from === void 0 || to === void 0) continue;
|
|
3915
|
+
let previous = edge.from;
|
|
3916
|
+
for (let r = Math.min(from, to) + 1; r < Math.max(from, to); r++) {
|
|
3917
|
+
const key = `lane:${edge.from}>${edge.to}@${r}`;
|
|
3918
|
+
push(r, {
|
|
3919
|
+
key,
|
|
3920
|
+
box: { x: 0, y: 0, width: LANE_WIDTH, height: LANE_HEIGHT },
|
|
3921
|
+
parents: [previous]
|
|
3922
|
+
});
|
|
3923
|
+
previous = key;
|
|
3924
|
+
}
|
|
3579
3925
|
}
|
|
3580
3926
|
const position = /* @__PURE__ */ new Map();
|
|
3581
|
-
const rankNumbers = [...
|
|
3927
|
+
const rankNumbers = [...slots.keys()].sort((a, b) => a - b);
|
|
3582
3928
|
for (const r of rankNumbers) {
|
|
3583
|
-
const bucket =
|
|
3584
|
-
const scored = bucket.map((
|
|
3585
|
-
const parents =
|
|
3929
|
+
const bucket = slots.get(r) ?? [];
|
|
3930
|
+
const scored = bucket.map((slot) => {
|
|
3931
|
+
const parents = slot.parents.map((id) => position.get(id)).filter((p) => p !== void 0);
|
|
3586
3932
|
const barycentre = parents.length === 0 ? Number.POSITIVE_INFINITY : parents.reduce((sum, p) => sum + p, 0) / parents.length;
|
|
3587
|
-
return {
|
|
3933
|
+
return { slot, barycentre };
|
|
3588
3934
|
});
|
|
3589
3935
|
scored.sort(
|
|
3590
|
-
(a, b) => a.barycentre - b.barycentre || (a.
|
|
3936
|
+
(a, b) => a.barycentre - b.barycentre || (a.slot.key < b.slot.key ? -1 : a.slot.key > b.slot.key ? 1 : 0)
|
|
3591
3937
|
);
|
|
3592
|
-
scored.forEach(({
|
|
3593
|
-
position.set(
|
|
3938
|
+
scored.forEach(({ slot }, i) => {
|
|
3939
|
+
position.set(slot.key, i);
|
|
3594
3940
|
});
|
|
3595
|
-
|
|
3941
|
+
slots.set(
|
|
3596
3942
|
r,
|
|
3597
|
-
scored.map((entry) => entry.
|
|
3943
|
+
scored.map((entry) => entry.slot)
|
|
3598
3944
|
);
|
|
3599
3945
|
}
|
|
3600
|
-
const gapH = spacing ?? HOUSE.spacing.h;
|
|
3601
3946
|
const gapV = HOUSE.spacing.v;
|
|
3947
|
+
const labelWidths = labelsByContainer(scene);
|
|
3948
|
+
const captionRoom = (column) => {
|
|
3949
|
+
const floor = spacing ?? HOUSE.spacing.h;
|
|
3950
|
+
let widest = 0;
|
|
3951
|
+
for (const edge of edges) {
|
|
3952
|
+
const from = rank.get(edge.from);
|
|
3953
|
+
const to = rank.get(edge.to);
|
|
3954
|
+
if (from === void 0 || to === void 0) continue;
|
|
3955
|
+
const low = Math.min(from, to);
|
|
3956
|
+
const high = Math.max(from, to);
|
|
3957
|
+
if (column < low || column >= high) continue;
|
|
3958
|
+
const arrow = scene.find(
|
|
3959
|
+
(element) => element.type === "arrow" && startOf(element) === edge.from && endOf(element) === edge.to
|
|
3960
|
+
);
|
|
3961
|
+
const caption = arrow === void 0 ? void 0 : labelWidths.get(arrow.id);
|
|
3962
|
+
if (caption !== void 0) widest = Math.max(widest, caption.width);
|
|
3963
|
+
}
|
|
3964
|
+
return Math.max(floor, widest + HOUSE.sizes.labelPadX * 2);
|
|
3965
|
+
};
|
|
3602
3966
|
const anchor = boundsOfAll(nodes.map(boxOf));
|
|
3603
3967
|
const columnWidths = rankNumbers.map(
|
|
3604
|
-
(r) => Math.max(...(
|
|
3968
|
+
(r) => Math.max(...(slots.get(r) ?? []).map((slot) => slot.box.width))
|
|
3605
3969
|
);
|
|
3606
3970
|
const tallest = Math.max(
|
|
3607
3971
|
...rankNumbers.map(
|
|
3608
|
-
(r) => (
|
|
3972
|
+
(r) => (slots.get(r) ?? []).reduce((sum, slot) => sum + slot.box.height + gapV, -gapV)
|
|
3609
3973
|
)
|
|
3610
3974
|
);
|
|
3611
3975
|
const deltas = /* @__PURE__ */ new Map();
|
|
3612
3976
|
let cursorX = anchor.x;
|
|
3613
3977
|
rankNumbers.forEach((r, column) => {
|
|
3614
|
-
const bucket =
|
|
3615
|
-
const columnHeight = bucket.reduce((sum,
|
|
3978
|
+
const bucket = slots.get(r) ?? [];
|
|
3979
|
+
const columnHeight = bucket.reduce((sum, slot) => sum + slot.box.height + gapV, -gapV);
|
|
3616
3980
|
let cursorY = anchor.y + (tallest - columnHeight) / 2;
|
|
3617
3981
|
const width = columnWidths[column] ?? 0;
|
|
3618
|
-
for (const
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3982
|
+
for (const slot of bucket) {
|
|
3983
|
+
if (slot.node !== void 0) {
|
|
3984
|
+
const x = cursorX + (width - slot.box.width) / 2;
|
|
3985
|
+
deltas.set(slot.node.id, [x - slot.box.x, cursorY - slot.box.y]);
|
|
3986
|
+
}
|
|
3987
|
+
cursorY += slot.box.height + gapV;
|
|
3622
3988
|
}
|
|
3623
|
-
cursorX += width +
|
|
3989
|
+
cursorX += width + captionRoom(r);
|
|
3624
3990
|
});
|
|
3625
3991
|
return translate(scene, deltas);
|
|
3626
3992
|
}
|
|
@@ -3644,6 +4010,7 @@ function arrangeElements(deps) {
|
|
|
3644
4010
|
sceneId: applied.value.sceneId,
|
|
3645
4011
|
sceneVersion: applied.value.sceneVersion,
|
|
3646
4012
|
broadcastTo: applied.value.broadcastTo,
|
|
4013
|
+
overlapWarning: applied.value.overlapWarning,
|
|
3647
4014
|
moved: [...applied.value.applied]
|
|
3648
4015
|
});
|
|
3649
4016
|
};
|
|
@@ -3809,7 +4176,7 @@ function explicit(input) {
|
|
|
3809
4176
|
}
|
|
3810
4177
|
return kept;
|
|
3811
4178
|
}
|
|
3812
|
-
var defaultSize = () =>
|
|
4179
|
+
var defaultSize = (element) => labelledSize(element.label, element.fontSize ?? HOUSE.fontSize);
|
|
3813
4180
|
function normalizeElements(input) {
|
|
3814
4181
|
return input.elements.map((element, i) => {
|
|
3815
4182
|
const fallback = input.ids[i];
|
|
@@ -3858,7 +4225,7 @@ function normalizeElements(input) {
|
|
|
3858
4225
|
id,
|
|
3859
4226
|
x: element.x,
|
|
3860
4227
|
y: element.y,
|
|
3861
|
-
...defaultSize(),
|
|
4228
|
+
...defaultSize(element),
|
|
3862
4229
|
...role,
|
|
3863
4230
|
...set,
|
|
3864
4231
|
...element.label === void 0 ? {} : { label: houseLabel(element.label) }
|
|
@@ -3901,20 +4268,6 @@ function createElements(deps) {
|
|
|
3901
4268
|
}
|
|
3902
4269
|
|
|
3903
4270
|
// src/app/usecases/write/frame-elements.ts
|
|
3904
|
-
function boundsAround(children) {
|
|
3905
|
-
const pad2 = HOUSE.sizes.framePad;
|
|
3906
|
-
const left = Math.min(...children.map((c) => c.x));
|
|
3907
|
-
const top = Math.min(...children.map((c) => c.y));
|
|
3908
|
-
const right = Math.max(...children.map((c) => c.x + c.width));
|
|
3909
|
-
const bottom = Math.max(...children.map((c) => c.y + c.height));
|
|
3910
|
-
return {
|
|
3911
|
-
x: left - pad2,
|
|
3912
|
-
y: top - pad2,
|
|
3913
|
-
width: right - left + pad2 * 2,
|
|
3914
|
-
// Room at the top for the frame's own name, which renders above its border.
|
|
3915
|
-
height: bottom - top + pad2 * 2
|
|
3916
|
-
};
|
|
3917
|
-
}
|
|
3918
4271
|
function frameElements(deps) {
|
|
3919
4272
|
return async (input) => {
|
|
3920
4273
|
const scene = deps.write.resolve(input.sceneId);
|
|
@@ -3943,6 +4296,18 @@ function frameElements(deps) {
|
|
|
3943
4296
|
if (!created.ok) return created;
|
|
3944
4297
|
const committed = deps.write.append(scene.value, created.value);
|
|
3945
4298
|
if (!committed.ok) return committed;
|
|
4299
|
+
const after = deps.write.resolve(input.sceneId);
|
|
4300
|
+
if (after.ok) {
|
|
4301
|
+
const built = after.value.elements.find((element) => element.id === elementId);
|
|
4302
|
+
if (built !== void 0) {
|
|
4303
|
+
const released = releaseCrossingArrows(after.value.elements, built);
|
|
4304
|
+
if (released.length > 0) {
|
|
4305
|
+
const freed = deps.write.apply(after.value, released);
|
|
4306
|
+
if (!freed.ok) return freed;
|
|
4307
|
+
return ok({ ...freed.value, frameId, children: named2.map((e) => e.id) });
|
|
4308
|
+
}
|
|
4309
|
+
}
|
|
4310
|
+
}
|
|
3946
4311
|
return ok({ ...committed.value, frameId, children: named2.map((e) => e.id) });
|
|
3947
4312
|
}
|
|
3948
4313
|
if (input.frameId === void 0) {
|
|
@@ -3960,12 +4325,14 @@ function frameElements(deps) {
|
|
|
3960
4325
|
if (members.length > 0) {
|
|
3961
4326
|
changed.push({ ...frame, ...boundsAround(members) });
|
|
3962
4327
|
}
|
|
4328
|
+
changed.push(...releaseCrossingArrows([...scene.value.elements, ...changed], frame));
|
|
3963
4329
|
const applied = deps.write.apply(scene.value, changed);
|
|
3964
4330
|
if (!applied.ok) return applied;
|
|
3965
4331
|
return ok({
|
|
3966
4332
|
sceneId: applied.value.sceneId,
|
|
3967
4333
|
sceneVersion: applied.value.sceneVersion,
|
|
3968
4334
|
broadcastTo: applied.value.broadcastTo,
|
|
4335
|
+
overlapWarning: applied.value.overlapWarning,
|
|
3969
4336
|
frameId: input.frameId,
|
|
3970
4337
|
children: members.map((element) => element.id)
|
|
3971
4338
|
});
|
|
@@ -3991,6 +4358,7 @@ function groupElements(deps) {
|
|
|
3991
4358
|
sceneId: applied.value.sceneId,
|
|
3992
4359
|
sceneVersion: applied.value.sceneVersion,
|
|
3993
4360
|
broadcastTo: applied.value.broadcastTo,
|
|
4361
|
+
overlapWarning: applied.value.overlapWarning,
|
|
3994
4362
|
groupId,
|
|
3995
4363
|
grouped: applied.value.applied
|
|
3996
4364
|
});
|
|
@@ -4011,6 +4379,7 @@ function ungroupElements(deps) {
|
|
|
4011
4379
|
sceneId: applied.value.sceneId,
|
|
4012
4380
|
sceneVersion: applied.value.sceneVersion,
|
|
4013
4381
|
broadcastTo: applied.value.broadcastTo,
|
|
4382
|
+
overlapWarning: applied.value.overlapWarning,
|
|
4014
4383
|
ungrouped: applied.value.applied
|
|
4015
4384
|
});
|
|
4016
4385
|
};
|
|
@@ -4026,6 +4395,29 @@ var iconBox = (art, size) => {
|
|
|
4026
4395
|
};
|
|
4027
4396
|
};
|
|
4028
4397
|
var svgDataUrl = (svg) => DataUrl.parse(`data:image/svg+xml;base64,${Buffer.from(svg, "utf8").toString("base64")}`);
|
|
4398
|
+
function placementOf(elements, input, box) {
|
|
4399
|
+
if (input.attachTo !== void 0) {
|
|
4400
|
+
const anchor = elements.find((element) => element.id === input.attachTo && !element.isDeleted);
|
|
4401
|
+
if (anchor === void 0) return fail(unknownElement(input.attachTo));
|
|
4402
|
+
const sides = input.placement !== void 0 ? [input.placement] : ["above", "below", "right", "left"];
|
|
4403
|
+
const ignore = /* @__PURE__ */ new Set([anchor.id]);
|
|
4404
|
+
for (const side of sides) {
|
|
4405
|
+
const at = anchoredPosition(anchor, box, side);
|
|
4406
|
+
const candidate = { ...at, width: box.width, height: box.height };
|
|
4407
|
+
if (sides.length === 1 || !wouldCollide(candidate, elements, ignore)) {
|
|
4408
|
+
return ok({ ...at, anchorIds: [anchor.id] });
|
|
4409
|
+
}
|
|
4410
|
+
}
|
|
4411
|
+
return ok({
|
|
4412
|
+
...anchoredPosition(anchor, box, "above"),
|
|
4413
|
+
anchorIds: [anchor.id]
|
|
4414
|
+
});
|
|
4415
|
+
}
|
|
4416
|
+
if (input.x === void 0 || input.y === void 0) {
|
|
4417
|
+
return fail(iconNeedsAPlace(input.iconId));
|
|
4418
|
+
}
|
|
4419
|
+
return ok({ x: input.x, y: input.y, anchorIds: null });
|
|
4420
|
+
}
|
|
4029
4421
|
function placeIcon(deps) {
|
|
4030
4422
|
return async (input) => {
|
|
4031
4423
|
const opened = await deps.icons();
|
|
@@ -4044,12 +4436,21 @@ function placeIcon(deps) {
|
|
|
4044
4436
|
if (!resolved.ok) return resolved;
|
|
4045
4437
|
const scene = resolved.value;
|
|
4046
4438
|
const size = input.size ?? HOUSE.sizes.icon;
|
|
4047
|
-
const
|
|
4439
|
+
const box = icon.art.kind === "elements" ? { width: size, height: size } : iconBox(icon.art, size);
|
|
4440
|
+
const spot = placementOf(scene.elements, input, box);
|
|
4441
|
+
if (!spot.ok) return spot;
|
|
4442
|
+
const { x, y, anchorIds } = spot.value;
|
|
4443
|
+
const chalk = {
|
|
4444
|
+
author: "claude",
|
|
4445
|
+
kind: "icon",
|
|
4446
|
+
iconId: icon.id,
|
|
4447
|
+
...anchorIds === null ? {} : { anchorIds }
|
|
4448
|
+
};
|
|
4048
4449
|
if (icon.art.kind === "elements") {
|
|
4049
4450
|
const ids = deps.idGen.elementIds(icon.art.elements.length);
|
|
4050
4451
|
const placed = deps.placer.place({
|
|
4051
4452
|
elements: icon.art.elements,
|
|
4052
|
-
at: { x
|
|
4453
|
+
at: { x, y },
|
|
4053
4454
|
ids
|
|
4054
4455
|
});
|
|
4055
4456
|
const stamped = placed.map(
|
|
@@ -4066,7 +4467,6 @@ function placeIcon(deps) {
|
|
|
4066
4467
|
iconId: icon.id
|
|
4067
4468
|
});
|
|
4068
4469
|
}
|
|
4069
|
-
const box = iconBox(icon.art, size);
|
|
4070
4470
|
const fileId = FileId.parse(deps.idGen.token());
|
|
4071
4471
|
const file = {
|
|
4072
4472
|
id: fileId,
|
|
@@ -4079,8 +4479,8 @@ function placeIcon(deps) {
|
|
|
4079
4479
|
{
|
|
4080
4480
|
type: "image",
|
|
4081
4481
|
id: elementId,
|
|
4082
|
-
x
|
|
4083
|
-
y
|
|
4482
|
+
x,
|
|
4483
|
+
y,
|
|
4084
4484
|
width: box.width,
|
|
4085
4485
|
height: box.height,
|
|
4086
4486
|
fileId,
|
|
@@ -4092,14 +4492,22 @@ function placeIcon(deps) {
|
|
|
4092
4492
|
skeletons.push({
|
|
4093
4493
|
type: "text",
|
|
4094
4494
|
id: labelId,
|
|
4095
|
-
|
|
4096
|
-
y: input.y + box.height + 8,
|
|
4495
|
+
...captionBelow({ x, y }, box),
|
|
4097
4496
|
text: input.label,
|
|
4098
4497
|
width: box.width,
|
|
4099
4498
|
fontSize: HOUSE.fontSize,
|
|
4100
4499
|
fontFamily: HOUSE.fontFamily,
|
|
4101
4500
|
textAlign: "center",
|
|
4102
|
-
|
|
4501
|
+
// The caption carries the anchor too, or the glyph travels with its box and the
|
|
4502
|
+
// word it is captioned with stays behind.
|
|
4503
|
+
customData: {
|
|
4504
|
+
chalk: {
|
|
4505
|
+
author: "claude",
|
|
4506
|
+
kind: "note",
|
|
4507
|
+
iconId: icon.id,
|
|
4508
|
+
...anchorIds === null ? {} : { anchorIds }
|
|
4509
|
+
}
|
|
4510
|
+
}
|
|
4103
4511
|
});
|
|
4104
4512
|
}
|
|
4105
4513
|
const expanded = await deps.write.create(scene, skeletons);
|
|
@@ -4185,7 +4593,10 @@ function writeContext(deps) {
|
|
|
4185
4593
|
return ok({
|
|
4186
4594
|
sceneId: scene.id,
|
|
4187
4595
|
sceneVersion: updated.sceneVersion,
|
|
4188
|
-
broadcastTo: broadcast(scene, updated.sceneVersion, pushed, patch?.files)
|
|
4596
|
+
broadcastTo: broadcast(scene, updated.sceneVersion, pushed, patch?.files),
|
|
4597
|
+
// The scene as it now stands, not the batch: a new box buries whatever was
|
|
4598
|
+
// already underneath it, and the batch alone cannot see that.
|
|
4599
|
+
overlapWarning: overlapWarning([...kept, ...expansion.created])
|
|
4189
4600
|
});
|
|
4190
4601
|
},
|
|
4191
4602
|
apply(scene, changed, options) {
|
|
@@ -4195,7 +4606,10 @@ function writeContext(deps) {
|
|
|
4195
4606
|
sceneVersion: scene.sceneVersion,
|
|
4196
4607
|
broadcastTo: 0,
|
|
4197
4608
|
applied: [],
|
|
4198
|
-
rejected: []
|
|
4609
|
+
rejected: [],
|
|
4610
|
+
// Nothing was written, so nothing was made worse. Staying quiet here keeps the
|
|
4611
|
+
// warning meaning "your write did this".
|
|
4612
|
+
overlapWarning: null
|
|
4199
4613
|
});
|
|
4200
4614
|
}
|
|
4201
4615
|
deps.markPresence("writing");
|
|
@@ -4224,7 +4638,8 @@ function writeContext(deps) {
|
|
|
4224
4638
|
sceneVersion: scene.sceneVersion,
|
|
4225
4639
|
broadcastTo: 0,
|
|
4226
4640
|
applied: [...merged.applied],
|
|
4227
|
-
rejected
|
|
4641
|
+
rejected,
|
|
4642
|
+
overlapWarning: null
|
|
4228
4643
|
});
|
|
4229
4644
|
}
|
|
4230
4645
|
const updated = deps.commit(scene.id, merged.elements);
|
|
@@ -4236,7 +4651,8 @@ function writeContext(deps) {
|
|
|
4236
4651
|
sceneVersion: updated.sceneVersion,
|
|
4237
4652
|
broadcastTo: broadcast(scene, updated.sceneVersion, pushed),
|
|
4238
4653
|
applied: [...merged.applied],
|
|
4239
|
-
rejected
|
|
4654
|
+
rejected,
|
|
4655
|
+
overlapWarning: overlapWarning(merged.elements)
|
|
4240
4656
|
});
|
|
4241
4657
|
}
|
|
4242
4658
|
};
|
|
@@ -4378,6 +4794,19 @@ function updateElements(deps) {
|
|
|
4378
4794
|
}
|
|
4379
4795
|
}
|
|
4380
4796
|
if (moved.size > 0) {
|
|
4797
|
+
const deltas = /* @__PURE__ */ new Map();
|
|
4798
|
+
for (const [id, next] of moved) {
|
|
4799
|
+
const before = byId.get(id);
|
|
4800
|
+
if (before !== void 0) deltas.set(id, [next.x - before.x, next.y - before.y]);
|
|
4801
|
+
}
|
|
4802
|
+
for (const [id, [dx, dy]] of withAnchoredElements(scene.value.elements, deltas)) {
|
|
4803
|
+
if (deltas.has(id) || dx === 0 && dy === 0) continue;
|
|
4804
|
+
const element = byId.get(id);
|
|
4805
|
+
if (element === void 0) continue;
|
|
4806
|
+
const followed = { ...element, x: element.x + dx, y: element.y + dy };
|
|
4807
|
+
moved.set(id, followed);
|
|
4808
|
+
knockOn.push(followed);
|
|
4809
|
+
}
|
|
4381
4810
|
for (const [id, next] of moved) {
|
|
4382
4811
|
const before = byId.get(id);
|
|
4383
4812
|
const caption = captionOf(scene.value.elements, id);
|
|
@@ -4389,6 +4818,10 @@ function updateElements(deps) {
|
|
|
4389
4818
|
});
|
|
4390
4819
|
}
|
|
4391
4820
|
knockOn.push(...redrawArrowsTouching(scene.value.elements, moved));
|
|
4821
|
+
const patched = new Set(changed.map((element) => element.id));
|
|
4822
|
+
knockOn.push(
|
|
4823
|
+
...refitFrames(scene.value.elements, moved).filter((frame) => !patched.has(frame.id))
|
|
4824
|
+
);
|
|
4392
4825
|
}
|
|
4393
4826
|
for (const element of knockOn) {
|
|
4394
4827
|
const before = byId.get(element.id);
|
|
@@ -4402,6 +4835,7 @@ function updateElements(deps) {
|
|
|
4402
4835
|
sceneId: applied.value.sceneId,
|
|
4403
4836
|
sceneVersion: applied.value.sceneVersion,
|
|
4404
4837
|
broadcastTo: applied.value.broadcastTo,
|
|
4838
|
+
overlapWarning: applied.value.overlapWarning,
|
|
4405
4839
|
// What the caller asked for, not everything that moved. A caption that followed its
|
|
4406
4840
|
// box and an arrow that was redrawn are consequences; listing them would turn this
|
|
4407
4841
|
// into "every element that changed" and leave the caller working out which of them
|
|
@@ -4455,6 +4889,7 @@ function deleteElements(deps) {
|
|
|
4455
4889
|
sceneId: applied.value.sceneId,
|
|
4456
4890
|
sceneVersion: applied.value.sceneVersion,
|
|
4457
4891
|
broadcastTo: applied.value.broadcastTo,
|
|
4892
|
+
overlapWarning: applied.value.overlapWarning,
|
|
4458
4893
|
deleted: onlyRequested(
|
|
4459
4894
|
applied.value.applied,
|
|
4460
4895
|
input.deletions.map((deletion) => deletion.id)
|
|
@@ -4509,7 +4944,7 @@ function readEnv(source) {
|
|
|
4509
4944
|
}
|
|
4510
4945
|
|
|
4511
4946
|
// src/composition/container.ts
|
|
4512
|
-
var PACKAGE_VERSION = "1.0
|
|
4947
|
+
var PACKAGE_VERSION = "1.1.0";
|
|
4513
4948
|
function readRuntime() {
|
|
4514
4949
|
return {
|
|
4515
4950
|
env: process.env,
|
|
@@ -5117,8 +5552,22 @@ function renderScene(description) {
|
|
|
5117
5552
|
}
|
|
5118
5553
|
lines.push("elements:");
|
|
5119
5554
|
for (const element of description.elements) lines.push(row(element, true));
|
|
5555
|
+
lines.push(...overlapLines(description));
|
|
5120
5556
|
return lines.join("\n");
|
|
5121
5557
|
}
|
|
5558
|
+
function overlapLines(description) {
|
|
5559
|
+
if (description.overlapCount === 0) return [];
|
|
5560
|
+
const shown = description.overlaps.length;
|
|
5561
|
+
const header = shown === description.overlapCount ? `overlaps: ${description.overlapCount}` : `overlaps: ${description.overlapCount} (worst ${shown} shown)`;
|
|
5562
|
+
return [
|
|
5563
|
+
header,
|
|
5564
|
+
...description.overlaps.map(
|
|
5565
|
+
(overlap) => `! ${shortId2(overlap.a)} \xD7 ${shortId2(overlap.b)} ${px(overlap.width)}x${px(
|
|
5566
|
+
overlap.height
|
|
5567
|
+
)}`
|
|
5568
|
+
)
|
|
5569
|
+
];
|
|
5570
|
+
}
|
|
5122
5571
|
var arrowGlyph = (label) => label === null ? "->" : `-"${label}"->`;
|
|
5123
5572
|
var insideLine = (edge) => ` ${shortId2(edge.from)} ${arrowGlyph(edge.label)} ${shortId2(edge.to)}`;
|
|
5124
5573
|
var named = (id, label) => label === null ? shortId2(id) : `${shortId2(id)} "${label}"`;
|
|
@@ -5235,7 +5684,7 @@ var searchIconsTool = {
|
|
|
5235
5684
|
};
|
|
5236
5685
|
var placeIconTool = {
|
|
5237
5686
|
name: "chalk_place_icon",
|
|
5238
|
-
description: "Put an icon from the catalog on the canvas, at an id from chalk_search_icons. Give it a `label` \u2014 an unlabelled icon says a thing was here and not which thing. The icon id is recorded on the element, so chalk_describe_scene reports it as [icon:aws/lambda] rather than [image] and you can reason about it later without looking at pixels.
|
|
5687
|
+
description: "Put an icon from the catalog on the canvas, at an id from chalk_search_icons. **Prefer `attachTo`** \u2014 the element the icon belongs to \u2014 over x/y: an attached icon travels with that element through every layout, while one at bare coordinates is near its box by coincidence and gets stranded the first time chalk_arrange runs. `placement` picks the side (above by default, or below/left/right/badge/inside). Give it a `label` unless it is attached to something already named \u2014 an unlabelled loose icon says a thing was here and not which thing. The icon id is recorded on the element, so chalk_describe_scene reports it as [icon:aws/lambda] rather than [image] and you can reason about it later without looking at pixels.",
|
|
5239
5688
|
annotations: {
|
|
5240
5689
|
title: "Place an icon",
|
|
5241
5690
|
readOnlyHint: false,
|
|
@@ -5353,7 +5802,7 @@ var sceneSettingsTool = {
|
|
|
5353
5802
|
// src/interfaces/mcp/tools/session.ts
|
|
5354
5803
|
var screenshotTool = {
|
|
5355
5804
|
name: "chalk_screenshot",
|
|
5356
|
-
description: "Look at the canvas as an image. Use it
|
|
5805
|
+
description: "Look at the canvas as an image. Use it for questions only a picture answers \u2014 does the diagram read, does it look deliberate, is the visual weight right. Do NOT use it to find collisions: chalk_describe_scene reports every overlap with ids and sizes, and every write tool warns when it buried something. Rendering happens in the user's browser, so the canvas has to be open; if no tab is connected the error says so. Prefer chalk_describe_scene for anything answerable from structure \u2014 it is far smaller and it gives you ids you can act on.",
|
|
5357
5806
|
annotations: {
|
|
5358
5807
|
title: "Screenshot the canvas",
|
|
5359
5808
|
readOnlyHint: true,
|
|
@@ -5509,7 +5958,7 @@ var createElementsTool = proxyTool({
|
|
|
5509
5958
|
var connectTool = proxyTool({
|
|
5510
5959
|
name: "chalk_connect",
|
|
5511
5960
|
title: "Connect two elements",
|
|
5512
|
-
description: "Draw an arrow between two elements. This is the ONLY way to make one: it binds both ends, so the arrow follows its boxes when the user drags them \u2014 an arrow made from coordinates comes loose the first time anybody tidies the diagram. Label it with what actually moves ('embeddings', 'POST /ingest', 'nightly'); an unlabelled arrow only says 'related', which the reader already assumed.",
|
|
5961
|
+
description: "Draw an arrow between two elements. This is the ONLY way to make one: it binds both ends, so the arrow follows its boxes when the user drags them \u2014 an arrow made from coordinates comes loose the first time anybody tidies the diagram. Label it with what actually moves ('embeddings', 'POST /ingest', 'nightly'); an unlabelled arrow only says 'related', which the reader already assumed. How the line runs, what each end looks like, and whether it is dashed all carry meaning here and are all settable \u2014 read chalk_read_me('arrows') before drawing a diagram's worth of them, or every edge comes out an identical straight solid line.",
|
|
5513
5962
|
input: ConnectToolInput,
|
|
5514
5963
|
output: ConnectOutput,
|
|
5515
5964
|
call: (bridge) => bridge.connect
|
|
@@ -5853,6 +6302,9 @@ var STATUS = {
|
|
|
5853
6302
|
// Phase 5.
|
|
5854
6303
|
CATALOG_UNAVAILABLE: 500,
|
|
5855
6304
|
UNKNOWN_ICON: 404,
|
|
6305
|
+
// 400: the icon exists and the request is malformed — it says nothing about where to
|
|
6306
|
+
// put the thing.
|
|
6307
|
+
ICON_NEEDS_A_PLACE: 400,
|
|
5856
6308
|
UNKNOWN_PACK: 404,
|
|
5857
6309
|
// 502, not 500: the failure is somebody else registry or somebody else archive, and
|
|
5858
6310
|
// the distinction is what tells a user to check their network rather than file a bug.
|