@diagrammo/dgmo 0.88.0 → 0.90.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/README.md +5 -3
  2. package/dist/advanced.d.ts +472 -22
  3. package/dist/advanced.js +401 -240
  4. package/dist/{analyzer-R5UBTRO2.js → analyzer-7ZGAZIE6.js} +2 -2
  5. package/dist/block.d.ts +1 -1
  6. package/dist/block.js +95 -72
  7. package/dist/{calculator-35YVW4QO.js → calculator-PX3JHKAS.js} +2 -2
  8. package/dist/{chart-meta-PbgpGwYo.d.ts → chart-meta-B_WTMP0y.d.ts} +1 -1
  9. package/dist/chart-meta.d.ts +2 -2
  10. package/dist/chart-meta.js +22 -21
  11. package/dist/{chart-types-Db_EGf1o.d.ts → chart-types-V2NcgN5O.d.ts} +5 -1
  12. package/dist/{charts-d3-3BZRSZV6.js → charts-d3-QW4ERNUE.js} +13 -12
  13. package/dist/{chunk-O6MMQQLF.js → chunk-2EDJPHXQ.js} +17 -17
  14. package/dist/{chunk-7WGCQE2E.js → chunk-2ZVLI6GQ.js} +1 -1
  15. package/dist/{chunk-JLETTWUJ.js → chunk-3BQCSQQJ.js} +57 -28
  16. package/dist/{chunk-MVCPO6LI.js → chunk-3HBR3YAN.js} +37 -27
  17. package/dist/chunk-3UR4F7FE.js +14 -0
  18. package/dist/{chunk-IDJGV6VM.js → chunk-4HG4PYHM.js} +209 -1
  19. package/dist/{chunk-YMG7JDEY.js → chunk-4IYJOXGS.js} +78 -31
  20. package/dist/{chunk-BOO24UMJ.js → chunk-4YO7VJTP.js} +1 -1
  21. package/dist/{chunk-AAMCXQPP.js → chunk-54YUDXGP.js} +6 -6
  22. package/dist/{chunk-UG2XG57E.js → chunk-5M52RPAS.js} +2 -2
  23. package/dist/{chunk-UNAP6O26.js → chunk-5M6PMV5Z.js} +14 -14
  24. package/dist/{chunk-BMUWF77V.js → chunk-5MDQMB6A.js} +4 -4
  25. package/dist/{chunk-WPL5PFXE.js → chunk-5TZPIKNV.js} +5 -5
  26. package/dist/{chunk-VPASQOR3.js → chunk-62VWZ3SE.js} +6 -5
  27. package/dist/{chunk-N4XHXBDQ.js → chunk-64KSPLU2.js} +6 -5
  28. package/dist/{chunk-VEPIAUSK.js → chunk-6BQSDF77.js} +1 -5
  29. package/dist/{chunk-LNO3ASX5.js → chunk-A5EE66RQ.js} +2 -2
  30. package/dist/{chunk-5KGM44TG.js → chunk-A5PUOHIS.js} +4 -4
  31. package/dist/{chunk-UNNJCSSQ.js → chunk-AAC3XQWV.js} +3 -3
  32. package/dist/{chunk-VJ2KROJ5.js → chunk-AHWA36O7.js} +1 -1
  33. package/dist/{chunk-FKZ2Y3Q5.js → chunk-C4W62JZO.js} +2 -2
  34. package/dist/{chunk-6I5UN4FD.js → chunk-CDT33RHG.js} +4 -4
  35. package/dist/{chunk-3DOQOXXI.js → chunk-CNUN5GO6.js} +1 -1
  36. package/dist/{chunk-NF5YKFRH.js → chunk-COPSI54O.js} +3 -3
  37. package/dist/{chunk-GUTZCRBT.js → chunk-CUY56BK4.js} +2 -2
  38. package/dist/{chunk-HSRQDWV7.js → chunk-CYF2X3CG.js} +2 -11
  39. package/dist/{chunk-NGC3IZRY.js → chunk-DNMICILX.js} +2 -2
  40. package/dist/{chunk-CFBY77QJ.js → chunk-DXPT2HPH.js} +145 -156
  41. package/dist/{chunk-J7Q4VPBJ.js → chunk-EB7AEM2H.js} +28 -22
  42. package/dist/{chunk-MGBV4JEI.js → chunk-EDXGEQW3.js} +1 -1
  43. package/dist/{chunk-H2GEIFUF.js → chunk-EEYQFJVK.js} +154 -48
  44. package/dist/{chunk-FPXMCGS5.js → chunk-EK7JYFCL.js} +2 -2
  45. package/dist/{chunk-3C2FWS2J.js → chunk-EWERNTOX.js} +1 -1
  46. package/dist/{chunk-WZ23JJ7U.js → chunk-FDRHBQUG.js} +26 -24
  47. package/dist/{chunk-FJNXXGTR.js → chunk-FS2LZBHG.js} +2 -2
  48. package/dist/{chunk-ERNCPKD4.js → chunk-G2KHLANR.js} +1 -1
  49. package/dist/{chunk-XVSJYAK7.js → chunk-G5BGW4BX.js} +2 -2
  50. package/dist/{chunk-33FQ6HNV.js → chunk-GQVXYRPC.js} +9 -9
  51. package/dist/{chunk-MHAYUS65.js → chunk-GXP344YZ.js} +3 -3
  52. package/dist/{chunk-NJIGYGZS.js → chunk-GYBKG4Z6.js} +15 -10
  53. package/dist/{chunk-MSXRNVHB.js → chunk-HIVJBESO.js} +311 -72
  54. package/dist/{chunk-UY6TEJJH.js → chunk-HJRP6PXL.js} +1 -1
  55. package/dist/{chunk-DOXBS7F5.js → chunk-HLE5QGZJ.js} +4 -4
  56. package/dist/{chunk-L5AFONQU.js → chunk-HX2KJEPD.js} +1 -1
  57. package/dist/{chunk-LL6D3MES.js → chunk-I6FWHICD.js} +19 -19
  58. package/dist/{chunk-RH2PROYG.js → chunk-I6GGMCTV.js} +4 -2
  59. package/dist/{chunk-3RYBTEF5.js → chunk-I74AQRVD.js} +6 -12
  60. package/dist/{chunk-PLE2432T.js → chunk-ICYPGWOV.js} +3 -3
  61. package/dist/chunk-IHK3Y2HG.js +781 -0
  62. package/dist/{chunk-JD4RHBNX.js → chunk-IMHNZITR.js} +9 -9
  63. package/dist/{chunk-GUYVKGFN.js → chunk-IRVQT4GR.js} +3 -3
  64. package/dist/{chunk-XUDGZJTJ.js → chunk-J3ODKAWN.js} +8 -8
  65. package/dist/{chunk-UMRZPRAN.js → chunk-JRQ4LBQI.js} +20 -20
  66. package/dist/{chunk-MY6GUH26.js → chunk-JX4RCC6B.js} +2 -2
  67. package/dist/{chunk-DSG6GBUQ.js → chunk-K4GUO7FV.js} +8 -8
  68. package/dist/{chunk-HAH5X345.js → chunk-KATED53P.js} +1 -1
  69. package/dist/{chunk-J64NZ6NF.js → chunk-KSZHIAI2.js} +1 -1
  70. package/dist/{chunk-7HWY4QAJ.js → chunk-L24LESXF.js} +1 -0
  71. package/dist/{chunk-UIUXIDBX.js → chunk-LBRHDWEA.js} +5 -5
  72. package/dist/{chunk-GSYZZFI5.js → chunk-LC5LY5V2.js} +2 -2
  73. package/dist/{chunk-P5V63L35.js → chunk-LNQDICFJ.js} +22 -22
  74. package/dist/{chunk-PIXJL77H.js → chunk-M6J25PAZ.js} +1 -1
  75. package/dist/{chunk-RGI64U3A.js → chunk-MIVSVEK4.js} +14 -14
  76. package/dist/{chunk-6K7RODXG.js → chunk-MKFQ5E7J.js} +1 -1
  77. package/dist/{chunk-44GP7PD5.js → chunk-MPJQMMBZ.js} +12 -0
  78. package/dist/{chunk-WQ6G6FFM.js → chunk-NFWRIC2V.js} +1 -1
  79. package/dist/{chunk-LHL6HDUL.js → chunk-NJYA4QSN.js} +84 -12
  80. package/dist/{chunk-RU725VCJ.js → chunk-NMKLX57Y.js} +10 -35
  81. package/dist/{chunk-PPH6ILHL.js → chunk-NP2SE6MQ.js} +4 -4
  82. package/dist/{chunk-FM3WAVB6.js → chunk-NS7L7YKH.js} +1 -1
  83. package/dist/{chunk-HEYGGSNQ.js → chunk-NTJ5HVV6.js} +5 -5
  84. package/dist/{chunk-BAZT6CIF.js → chunk-NUYWNKHH.js} +9 -9
  85. package/dist/{chunk-DV2VEJCC.js → chunk-NWSPPGIE.js} +6 -6
  86. package/dist/{chunk-AYOVY75O.js → chunk-NY56FM55.js} +3 -3
  87. package/dist/{chunk-LD2JSKU3.js → chunk-OOCVGX4W.js} +15 -0
  88. package/dist/{chunk-A4XPI4YN.js → chunk-OSIUWQ3N.js} +29 -2
  89. package/dist/{chunk-LJFXC3IP.js → chunk-OWJVSJLA.js} +17 -17
  90. package/dist/{chunk-GDJW64XE.js → chunk-OYKNMFUY.js} +1 -1
  91. package/dist/{chunk-YK4N6TBN.js → chunk-PIHAUVA4.js} +10 -10
  92. package/dist/{chunk-C7QRRTAW.js → chunk-PNCKZFPE.js} +2 -2
  93. package/dist/{chunk-D4M25W6R.js → chunk-POBNN5DP.js} +6 -6
  94. package/dist/{chunk-N7XRBWXA.js → chunk-PQ5NW3QZ.js} +15 -15
  95. package/dist/{chunk-HTPZDZKQ.js → chunk-PXEUQ7EG.js} +22 -22
  96. package/dist/{chunk-XWYR5T52.js → chunk-QOZ4RVQY.js} +19 -19
  97. package/dist/{chunk-BV6PKJUS.js → chunk-QRIW46LR.js} +8 -8
  98. package/dist/{chunk-LSQGJN5H.js → chunk-R2PTZ6QM.js} +21 -21
  99. package/dist/{chunk-VW52W5F6.js → chunk-RCBHL2B5.js} +229 -159
  100. package/dist/{chunk-66YFDTT6.js → chunk-RJYFHEP4.js} +3 -3
  101. package/dist/{chunk-P3SKSKJI.js → chunk-RNXX2GOQ.js} +2 -2
  102. package/dist/{chunk-BT2WH2XT.js → chunk-RRBV4HIM.js} +3 -3
  103. package/dist/{chunk-WXPBP4IT.js → chunk-RY5RRKYN.js} +14 -14
  104. package/dist/{chunk-NZCSVD4M.js → chunk-S4LLHDGK.js} +8 -8
  105. package/dist/chunk-S7C32S2T.js +825 -0
  106. package/dist/{chunk-QFIXL3OK.js → chunk-SEKNYIMO.js} +1 -1
  107. package/dist/{chunk-JRUEIRJB.js → chunk-SLO22FPS.js} +2 -2
  108. package/dist/{chunk-47E5UTXE.js → chunk-SMEVBJJJ.js} +2 -2
  109. package/dist/{chunk-QFHWYWQL.js → chunk-SVQDLYX7.js} +1 -1
  110. package/dist/{chunk-WP2RLGDI.js → chunk-TCX5PMEY.js} +1 -1
  111. package/dist/{chunk-5LD7SHXO.js → chunk-TQ644YGV.js} +18 -18
  112. package/dist/{chunk-PUVTFUNH.js → chunk-U762HK4D.js} +28 -28
  113. package/dist/{chunk-DAX42XVH.js → chunk-VCHYS3RD.js} +14 -9
  114. package/dist/{chunk-XIFK423U.js → chunk-W7QN5BC5.js} +4 -4
  115. package/dist/{chunk-7UDAIP6W.js → chunk-WHRIN7N3.js} +1 -1
  116. package/dist/{chunk-ZUCXFXLD.js → chunk-X3WYJ5T7.js} +2 -2
  117. package/dist/{chunk-RE6TVIAV.js → chunk-X6IZP2BD.js} +4 -4
  118. package/dist/{chunk-LCJURK7L.js → chunk-Y6GQQ4Y2.js} +1 -1
  119. package/dist/{chunk-HTWH2XQL.js → chunk-YE7D2S75.js} +2 -2
  120. package/dist/{chunk-B7CU2HW5.js → chunk-YKGUSW6D.js} +17 -17
  121. package/dist/{chunk-AQIBKTPG.js → chunk-YWRZG6GN.js} +10 -10
  122. package/dist/{chunk-JQ57AWDL.js → chunk-ZJ4PYTCK.js} +1 -1
  123. package/dist/completion-registry.d.ts +7 -1
  124. package/dist/completion-registry.js +64 -20
  125. package/dist/countdown.js +1 -1
  126. package/dist/{d3-B6524aaP.d.ts → d3-2S3PrXik.d.ts} +11 -0
  127. package/dist/dgmo-router-BJBXSZMV.js +94 -0
  128. package/dist/{dimensions-6QAWEGIR.js → dimensions-AMA2S7RO.js} +7 -7
  129. package/dist/editor.js +12 -0
  130. package/dist/{flowchart-parser-GG7XBLQH.js → flowchart-parser-ADZIFVCH.js} +3 -3
  131. package/dist/{flowchart-renderer-THC6Y7EH.js → flowchart-renderer-CAG6ZNJ6.js} +10 -9
  132. package/dist/highlight.js +12 -0
  133. package/dist/index.d.ts +26 -5
  134. package/dist/index.js +94 -67
  135. package/dist/{layout-P6DTD4RT.js → layout-4RRC7XU7.js} +2 -2
  136. package/dist/{layout-LUQKAGGT.js → layout-6OSF2UGP.js} +5 -5
  137. package/dist/{layout-AM57TGN5.js → layout-C6MKMOBI.js} +3 -3
  138. package/dist/{layout-EHTYSMV4.js → layout-H4K54IW3.js} +2 -2
  139. package/dist/{layout-XUW444O5.js → layout-QS2SESBU.js} +3 -3
  140. package/dist/{layout-5NPBHV5F.js → layout-T2PGKQUQ.js} +4 -4
  141. package/dist/{layout-CUFA7XJD.js → layout-UFB2O4AO.js} +5 -5
  142. package/dist/{layout-MSSHF45T.js → layout-UPQGIT3N.js} +2 -2
  143. package/dist/{layout-QX5T6ZNE.js → layout-VQ2USZJ3.js} +5 -5
  144. package/dist/{layout-SOPAVXIH.js → layout-VRJ5YFUE.js} +3 -3
  145. package/dist/{layout-BOVTLAOT.js → layout-ZP7XYVXF.js} +2 -2
  146. package/dist/{layout-search-VKSBUCDM.js → layout-search-YKUL4VBV.js} +105 -6
  147. package/dist/{legend-constants-ZVO4FLAK.js → legend-constants-HE7FVDJP.js} +4 -2
  148. package/dist/{palettes-BIV54XLS.js → palettes-WQHELGVQ.js} +7 -4
  149. package/dist/{parser-KYPP2DX6.js → parser-223VOHSB.js} +4 -4
  150. package/dist/{parser-JOOAVBJI.js → parser-2PNV7UI3.js} +3 -3
  151. package/dist/{parser-GZ3LVF72.js → parser-3MGA2MTM.js} +2 -2
  152. package/dist/{parser-NOANDFJ4.js → parser-4AR25MAS.js} +2 -2
  153. package/dist/{parser-ACW6C6OY.js → parser-4B2PIXHI.js} +3 -3
  154. package/dist/{parser-KZMJNKDW.js → parser-57YQEEMC.js} +2 -2
  155. package/dist/{parser-J4DVNL4W.js → parser-5ZD2NKGU.js} +4 -4
  156. package/dist/{parser-LANGKWRG.js → parser-6LMB7BQQ.js} +2 -2
  157. package/dist/parser-AL6YL7KM.js +12 -0
  158. package/dist/{parser-5655XSOR.js → parser-B2FWP7ZO.js} +3 -3
  159. package/dist/{parser-GEKPWSSK.js → parser-BJDQX4KV.js} +3 -3
  160. package/dist/{parser-C327BBE3.js → parser-CA5WC5HF.js} +3 -3
  161. package/dist/{parser-KZMALSB2.js → parser-E5HFYL7B.js} +4 -4
  162. package/dist/{parser-WUK6CP5X.js → parser-ESZ5J5IJ.js} +6 -5
  163. package/dist/{parser-256EIWB2.js → parser-FDXUQ5TI.js} +2 -2
  164. package/dist/{parser-AN3MGHRL.js → parser-FV6RGALQ.js} +3 -3
  165. package/dist/{parser-DGF3ZEO6.js → parser-HPR7G7F6.js} +3 -3
  166. package/dist/{parser-OKB64MMN.js → parser-I4HZVIHX.js} +3 -3
  167. package/dist/{parser-JXS4426S.js → parser-J3BM2AP2.js} +4 -4
  168. package/dist/{parser-NPXPJHWN.js → parser-JFNDS5E5.js} +3 -3
  169. package/dist/{parser-PVIWHVGY.js → parser-KFIK3EOO.js} +3 -3
  170. package/dist/{parser-GPW4ZHPQ.js → parser-LGUT7KKH.js} +4 -3
  171. package/dist/{parser-KFYRTGTC.js → parser-MYRGCK7Q.js} +4 -4
  172. package/dist/{parser-ZLKYDFI5.js → parser-NAUUUCI3.js} +3 -3
  173. package/dist/{parser-DHSFIUPU.js → parser-NJ5VEZA3.js} +3 -3
  174. package/dist/{parser-OVQTTTUJ.js → parser-OFTMA36M.js} +2 -2
  175. package/dist/{parser-AKBVJHMK.js → parser-OV2WDSEV.js} +3 -3
  176. package/dist/{parser-LGS65QPN.js → parser-Q3UAOLEZ.js} +2 -2
  177. package/dist/{parser-XYY5NHP4.js → parser-R6OETHWM.js} +2 -2
  178. package/dist/{parser-7OEE7QT6.js → parser-RARXAHC7.js} +2 -2
  179. package/dist/{parser-NGHQQGD2.js → parser-T2RVIRDG.js} +3 -3
  180. package/dist/{parser-WEVTMBJ5.js → parser-W2DWCCLO.js} +3 -3
  181. package/dist/{parser-HCGXNHHL.js → parser-WFY4ZJUW.js} +3 -3
  182. package/dist/{parser-SA3RAJFS.js → parser-WSONWDFN.js} +2 -2
  183. package/dist/{renderer-2OOPQ4CH.js → renderer-3N64GVNM.js} +3 -3
  184. package/dist/{renderer-4BIMRO4X.js → renderer-3QM2DK7I.js} +7 -7
  185. package/dist/{renderer-4NZZ5J2F.js → renderer-3W5T3IU6.js} +8 -8
  186. package/dist/{renderer-RWJ45DWH.js → renderer-4Z7FRQ2A.js} +3 -3
  187. package/dist/{renderer-LODEVN3V.js → renderer-52CHSV6S.js} +13 -13
  188. package/dist/{renderer-X5A5VIRD.js → renderer-6OOJNEQE.js} +10 -10
  189. package/dist/{renderer-YDAVCRTP.js → renderer-A3PMPUO6.js} +15 -11
  190. package/dist/{renderer-NHPKNNBD.js → renderer-AM4VZSBQ.js} +11 -11
  191. package/dist/{renderer-SDUSBCJI.js → renderer-B3CPMS5R.js} +10 -10
  192. package/dist/{renderer-TPOZOAXR.js → renderer-B4KE3NM4.js} +17 -16
  193. package/dist/renderer-COSJM7UG.js +80 -0
  194. package/dist/{renderer-R34GJL7U.js → renderer-FXCVH2M5.js} +16 -15
  195. package/dist/{renderer-QM23SWAM.js → renderer-GWH5ACJ5.js} +4 -4
  196. package/dist/{renderer-222OTVQV.js → renderer-IG72UJHW.js} +5 -5
  197. package/dist/{renderer-A6ACVK4X.js → renderer-IO3D5E4E.js} +7 -7
  198. package/dist/{renderer-RMGN3Q7D.js → renderer-IPDCAACY.js} +5 -5
  199. package/dist/{renderer-XUPLAO4B.js → renderer-KK5BU5K2.js} +8 -8
  200. package/dist/{renderer-DCFQDBGJ.js → renderer-LD2H7WGP.js} +3 -3
  201. package/dist/{renderer-KVAQE7PQ.js → renderer-MK47ESCB.js} +8 -8
  202. package/dist/{renderer-4BHOELCE.js → renderer-MRMFYYZT.js} +3 -3
  203. package/dist/{renderer-6BUUTWVS.js → renderer-O5RQHGK2.js} +9 -9
  204. package/dist/{renderer-2KVQGGTT.js → renderer-OA5D3ZKB.js} +10 -10
  205. package/dist/{renderer-RENDISO5.js → renderer-ON4PTUHJ.js} +14 -14
  206. package/dist/{renderer-JKV2DBYP.js → renderer-OPDSKCQS.js} +7 -7
  207. package/dist/{renderer-XRALFCIN.js → renderer-PLRMST57.js} +10 -10
  208. package/dist/{renderer-WH2HWE5Z.js → renderer-PSMRAL72.js} +11 -11
  209. package/dist/{renderer-RNCYODNF.js → renderer-PXGCR7N4.js} +11 -10
  210. package/dist/{renderer-PQYO2HCE.js → renderer-R7OYCJEA.js} +4 -4
  211. package/dist/{renderer-36JH4OMC.js → renderer-SBXCPA3S.js} +12 -12
  212. package/dist/{renderer-A4LMOBZL.js → renderer-TMQNTUQS.js} +15 -15
  213. package/dist/renderer-TTKTBB4C.js +46 -0
  214. package/dist/{renderer-RAATRF6W.js → renderer-UVFGW2O6.js} +12 -10
  215. package/dist/{renderer-3FF4QVGW.js → renderer-W22GX72R.js} +10 -10
  216. package/dist/{renderer-BICLPGAH.js → renderer-WQ654YT5.js} +2 -2
  217. package/dist/{renderer-radial-XZ5TKUT4.js → renderer-radial-42LVSG74.js} +8 -8
  218. package/dist/{state-parser-FE3RF6XY.js → state-parser-ROKY5KSI.js} +4 -4
  219. package/dist/{state-renderer-5IQ4OJUI.js → state-renderer-MMG23G4W.js} +14 -14
  220. package/dist/{themes-CzuBdx1T.d.ts → themes-Cm2YBcT8.d.ts} +38 -2
  221. package/docs/ai-integration.md +8 -5
  222. package/docs/language-reference.md +163 -13
  223. package/gallery/fixtures/sketch.dgmo +2 -2
  224. package/gallery/fixtures/whiteboard.dgmo +18 -0
  225. package/package.json +2 -1
  226. package/dist/dgmo-router-F2DSURTR.js +0 -92
  227. package/dist/renderer-YIZ7G4HU.js +0 -78
  228. package/dist/{chunk-3TYUXC7D.js → chunk-2SKMEL7V.js} +0 -0
  229. package/dist/{chunk-CLQIXD2C.js → chunk-7Z2VFRP5.js} +3 -3
  230. package/dist/{chunk-2A4DQAXG.js → chunk-IIOLFAGJ.js} +3 -3
@@ -0,0 +1,825 @@
1
+ import {
2
+ drawCylinderCard,
3
+ drawQueueCard
4
+ } from "./chunk-FDRHBQUG.js";
5
+ import {
6
+ CYLINDER_RY,
7
+ QUEUE_CAP
8
+ } from "./chunk-VCHYS3RD.js";
9
+ import {
10
+ renderChartTitle
11
+ } from "./chunk-X6IZP2BD.js";
12
+ import {
13
+ TITLE_FONT_SIZE
14
+ } from "./chunk-VLC6WNRD.js";
15
+ import {
16
+ FONT_FAMILY
17
+ } from "./chunk-ICLB27PZ.js";
18
+ import {
19
+ measureText,
20
+ wrapTextToWidth
21
+ } from "./chunk-KAO7JL4I.js";
22
+ import {
23
+ contrastText,
24
+ mix,
25
+ shapeFill,
26
+ themeBaseBg
27
+ } from "./chunk-L24LESXF.js";
28
+
29
+ // src/whiteboard/renderer.ts
30
+ import * as d3 from "d3-selection";
31
+ import { getStroke } from "perfect-freehand";
32
+
33
+ // src/whiteboard/geometry.ts
34
+ var RECT_RADIUS = 6;
35
+ var NOTE_FOLD = 18;
36
+ function whiteboardNoteFold(width, height) {
37
+ return Math.max(0, Math.min(NOTE_FOLD, width / 3, height / 3));
38
+ }
39
+ function isAttachable(el) {
40
+ return el.kind === "shape" || el.kind === "note";
41
+ }
42
+ var EPS = 1e-6;
43
+ function rect(x0, y0, x1, y1) {
44
+ return x1 >= x0 && y1 >= y0 ? [{ kind: "rect", x0, y0, x1, y1 }] : [];
45
+ }
46
+ function ellipse(cx, cy, rx, ry) {
47
+ return rx > 0 && ry > 0 ? [{ kind: "ellipse", cx, cy, rx, ry }] : [];
48
+ }
49
+ function roundedRect(x, y, w, h, radius) {
50
+ const r = Math.max(0, Math.min(radius, w / 2, h / 2));
51
+ if (r === 0) return rect(x, y, x + w, y + h);
52
+ return [
53
+ ...rect(x + r, y, x + w - r, y + h),
54
+ ...rect(x, y + r, x + w, y + h - r),
55
+ ...ellipse(x + r, y + r, r, r),
56
+ ...ellipse(x + w - r, y + r, r, r),
57
+ ...ellipse(x + r, y + h - r, r, r),
58
+ ...ellipse(x + w - r, y + h - r, r, r)
59
+ ];
60
+ }
61
+ function piecesOf(s) {
62
+ const { x, y, width: w, height: h } = s;
63
+ if (s.kind === "note") {
64
+ const f = whiteboardNoteFold(w, h);
65
+ if (f === 0) return rect(x, y, x + w, y + h);
66
+ const pts = [
67
+ { x, y },
68
+ { x: x + w - f, y },
69
+ { x: x + w, y: y + f },
70
+ { x: x + w, y: y + h },
71
+ { x, y: y + h }
72
+ ];
73
+ return [{ kind: "poly", pts }];
74
+ }
75
+ const cx = x + w / 2;
76
+ const cy = y + h / 2;
77
+ switch (s.shape) {
78
+ case "rectangle":
79
+ return roundedRect(x, y, w, h, RECT_RADIUS);
80
+ case "ellipse":
81
+ return ellipse(cx, cy, w / 2, h / 2);
82
+ case "database": {
83
+ const ry = CYLINDER_RY;
84
+ return [
85
+ ...rect(x, y + ry, x + w, y + h - ry),
86
+ ...ellipse(cx, y + ry, w / 2, ry),
87
+ ...ellipse(cx, y + h - ry, w / 2, ry)
88
+ ];
89
+ }
90
+ case "queue": {
91
+ const cap = QUEUE_CAP;
92
+ return [
93
+ ...rect(x + cap, y, x + w - cap, y + h),
94
+ ...ellipse(x + cap, cy, cap, h / 2),
95
+ ...ellipse(x + w - cap, cy, cap, h / 2)
96
+ ];
97
+ }
98
+ }
99
+ }
100
+ function halfPlanes(pts) {
101
+ return pts.map((a, i) => {
102
+ const b = pts[(i + 1) % pts.length];
103
+ const nx = b.y - a.y;
104
+ const ny = -(b.x - a.x);
105
+ const len = Math.hypot(nx, ny) || 1;
106
+ return [nx / len, ny / len, (nx * a.x + ny * a.y) / len];
107
+ });
108
+ }
109
+ function pieceContains(p, px, py) {
110
+ if (p.kind === "poly") {
111
+ return halfPlanes(p.pts).every(
112
+ ([nx2, ny2, c]) => nx2 * px + ny2 * py <= c + EPS
113
+ );
114
+ }
115
+ if (p.kind === "rect") {
116
+ return px >= p.x0 - EPS && px <= p.x1 + EPS && py >= p.y0 - EPS && py <= p.y1 + EPS;
117
+ }
118
+ const nx = (px - p.cx) / p.rx;
119
+ const ny = (py - p.cy) / p.ry;
120
+ return nx * nx + ny * ny <= 1 + EPS;
121
+ }
122
+ function whiteboardShapeContains(shape, point) {
123
+ return piecesOf(shape).some((p) => pieceContains(p, point.x, point.y));
124
+ }
125
+ function whiteboardShapeAt(point, elements) {
126
+ for (let i = elements.length - 1; i >= 0; i--) {
127
+ const el = elements[i];
128
+ if (isAttachable(el) && whiteboardShapeContains(el, point)) return i;
129
+ }
130
+ return -1;
131
+ }
132
+ function whiteboardConnectorAttachments(connector, elements) {
133
+ const a = { x: connector.x1, y: connector.y1 };
134
+ const b = { x: connector.x2, y: connector.y2 };
135
+ const attach = (end, other) => {
136
+ const i = whiteboardShapeAt(end, elements);
137
+ if (i < 0) return -1;
138
+ return whiteboardShapeContains(elements[i], other) ? -1 : i;
139
+ };
140
+ return { from: attach(a, b), to: attach(b, a) };
141
+ }
142
+ function interval(p, ax, ay, dx, dy) {
143
+ if (p.kind === "poly") {
144
+ let lo = -Infinity;
145
+ let hi = Infinity;
146
+ for (const [nx, ny, c] of halfPlanes(p.pts)) {
147
+ const num = c - (nx * ax + ny * ay);
148
+ const den = nx * dx + ny * dy;
149
+ if (Math.abs(den) < EPS) {
150
+ if (num < -EPS) return null;
151
+ continue;
152
+ }
153
+ const t = num / den;
154
+ if (den > 0) hi = Math.min(hi, t);
155
+ else lo = Math.max(lo, t);
156
+ }
157
+ return lo <= hi ? [lo, hi] : null;
158
+ }
159
+ if (p.kind === "rect") {
160
+ let lo = -Infinity;
161
+ let hi = Infinity;
162
+ for (const [o, d, min, max] of [
163
+ [ax, dx, p.x0, p.x1],
164
+ [ay, dy, p.y0, p.y1]
165
+ ]) {
166
+ if (Math.abs(d) < EPS) {
167
+ if (o < min - EPS || o > max + EPS) return null;
168
+ continue;
169
+ }
170
+ const t0 = (min - o) / d;
171
+ const t1 = (max - o) / d;
172
+ lo = Math.max(lo, Math.min(t0, t1));
173
+ hi = Math.min(hi, Math.max(t0, t1));
174
+ }
175
+ return lo <= hi ? [lo, hi] : null;
176
+ }
177
+ const ox = (ax - p.cx) / p.rx;
178
+ const oy = (ay - p.cy) / p.ry;
179
+ const ux = dx / p.rx;
180
+ const uy = dy / p.ry;
181
+ const qa = ux * ux + uy * uy;
182
+ const qb = 2 * (ox * ux + oy * uy);
183
+ const qc = ox * ox + oy * oy - 1;
184
+ const disc = qb * qb - 4 * qa * qc;
185
+ if (qa === 0 || disc < 0) return null;
186
+ const s = Math.sqrt(disc);
187
+ return [(-qb - s) / (2 * qa), (-qb + s) / (2 * qa)];
188
+ }
189
+ function entryParam(shape, a, b) {
190
+ const dx = b.x - a.x;
191
+ const dy = b.y - a.y;
192
+ let best = 1;
193
+ for (const p of piecesOf(shape)) {
194
+ const iv = interval(p, a.x, a.y, dx, dy);
195
+ if (!iv || iv[1] < 0 || iv[0] > 1) continue;
196
+ best = Math.min(best, Math.max(0, iv[0]));
197
+ }
198
+ return best;
199
+ }
200
+ function clipWhiteboardConnector(connector, elements) {
201
+ const { x1, y1, x2, y2 } = connector;
202
+ const stored = { x1, y1, x2, y2 };
203
+ if (Math.hypot(x2 - x1, y2 - y1) < EPS) return stored;
204
+ const { from, to } = whiteboardConnectorAttachments(connector, elements);
205
+ if (connector.bend !== 0) return clipCurve(connector, elements, from, to);
206
+ if (from < 0 && to < 0) return stored;
207
+ const { a, b } = aimedEnds(connector, elements, from, to);
208
+ if (Math.hypot(b.x - a.x, b.y - a.y) < EPS) return stored;
209
+ const uEnd = to < 0 ? 1 : entryParam(elements[to], a, b);
210
+ const uStart = from < 0 ? 1 : entryParam(elements[from], b, a);
211
+ if (uEnd + uStart - 1 < EPS) return stored;
212
+ return {
213
+ x1: b.x + (a.x - b.x) * uStart,
214
+ y1: b.y + (a.y - b.y) * uStart,
215
+ x2: a.x + (b.x - a.x) * uEnd,
216
+ y2: a.y + (b.y - a.y) * uEnd
217
+ };
218
+ }
219
+ function aimedEnds(connector, elements, from, to) {
220
+ const centre = (i, x, y) => {
221
+ if (i < 0) return { x, y };
222
+ const s = elements[i];
223
+ return { x: s.x + s.width / 2, y: s.y + s.height / 2 };
224
+ };
225
+ return {
226
+ a: centre(from, connector.x1, connector.y1),
227
+ b: centre(to, connector.x2, connector.y2)
228
+ };
229
+ }
230
+ function bendFrame(connector, elements) {
231
+ const { from, to } = whiteboardConnectorAttachments(connector, elements);
232
+ const { a, b } = aimedEnds(connector, elements, from, to);
233
+ const dx = b.x - a.x;
234
+ const dy = b.y - a.y;
235
+ const len = Math.hypot(dx, dy);
236
+ if (len < EPS) return null;
237
+ return {
238
+ a,
239
+ b,
240
+ mid: { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 },
241
+ nx: -dy / len,
242
+ ny: dx / len
243
+ };
244
+ }
245
+ function whiteboardBendHandle(connector, elements) {
246
+ const f = bendFrame(connector, elements);
247
+ if (!f) return { x: connector.x1, y: connector.y1 };
248
+ return {
249
+ x: f.mid.x + f.nx * connector.bend,
250
+ y: f.mid.y + f.ny * connector.bend
251
+ };
252
+ }
253
+ function whiteboardBendFor(connector, elements, p) {
254
+ const f = bendFrame(connector, elements);
255
+ if (!f) return 0;
256
+ return Math.round((p.x - f.mid.x) * f.nx + (p.y - f.mid.y) * f.ny);
257
+ }
258
+ var CURVE_STEPS = 64;
259
+ function quad(a, c, b, t) {
260
+ const u = 1 - t;
261
+ return {
262
+ x: u * u * a.x + 2 * u * t * c.x + t * t * b.x,
263
+ y: u * u * a.y + 2 * u * t * c.y + t * t * b.y
264
+ };
265
+ }
266
+ function clipCurve(connector, elements, from, to) {
267
+ const { x1, y1, x2, y2 } = connector;
268
+ const f = bendFrame(connector, elements);
269
+ if (!f) return { x1, y1, x2, y2 };
270
+ const { a, b } = f;
271
+ const h = {
272
+ x: f.mid.x + f.nx * connector.bend,
273
+ y: f.mid.y + f.ny * connector.bend
274
+ };
275
+ const c = { x: 2 * h.x - f.mid.x, y: 2 * h.y - f.mid.y };
276
+ const inside = (i, t) => {
277
+ const p = quad(a, c, b, t);
278
+ return whiteboardShapeContains(elements[i], p);
279
+ };
280
+ const leave = (i, start, end) => {
281
+ let inT = start;
282
+ for (let k = 1; k <= CURVE_STEPS; k++) {
283
+ const t = start + (end - start) * k / CURVE_STEPS;
284
+ if (!inside(i, t)) {
285
+ let lo = inT;
286
+ let hi = t;
287
+ for (let n = 0; n < 24; n++) {
288
+ const m = (lo + hi) / 2;
289
+ if (inside(i, m)) lo = m;
290
+ else hi = m;
291
+ }
292
+ return (lo + hi) / 2;
293
+ }
294
+ inT = t;
295
+ }
296
+ return end;
297
+ };
298
+ const t0 = from < 0 ? 0 : leave(from, 0, 1);
299
+ const t1 = to < 0 ? 1 : leave(to, 1, 0);
300
+ const [s0, s1] = t1 - t0 > EPS ? [t0, t1] : [0, 1];
301
+ const p0 = quad(a, c, b, s0);
302
+ const p1 = quad(a, c, b, s1);
303
+ const w0 = (1 - s0) * (1 - s1);
304
+ const w1 = (1 - s0) * s1 + s0 * (1 - s1);
305
+ const w2 = s0 * s1;
306
+ return {
307
+ x1: p0.x,
308
+ y1: p0.y,
309
+ x2: p1.x,
310
+ y2: p1.y,
311
+ cx: w0 * a.x + w1 * c.x + w2 * b.x,
312
+ cy: w0 * a.y + w1 * c.y + w2 * b.y
313
+ };
314
+ }
315
+ function whiteboardSegmentMidpoint(s) {
316
+ if (s.cx === void 0 || s.cy === void 0) {
317
+ return { x: (s.x1 + s.x2) / 2, y: (s.y1 + s.y2) / 2 };
318
+ }
319
+ return {
320
+ x: (s.x1 + 2 * s.cx + s.x2) / 4,
321
+ y: (s.y1 + 2 * s.cy + s.y2) / 4
322
+ };
323
+ }
324
+
325
+ // src/whiteboard/label.ts
326
+ var WHITEBOARD_LABEL_FONT = 14;
327
+ var WHITEBOARD_NOTE_FONT = 12;
328
+ var WHITEBOARD_LABEL_LINE = 1.25;
329
+ var LABEL_PAD = 8;
330
+ var WHITEBOARD_NOTE_PAD = 12;
331
+ var NOTE_TIGHT_TOP = 6;
332
+ var NOTE_TIGHT_BOTTOM = 3;
333
+ var ELLIPSE_INSET = 0.15;
334
+ var MIN_WRAP = 20;
335
+ var WHITEBOARD_LABEL_MIN_FONT = 9;
336
+ function whiteboardLabelWidth(box) {
337
+ if ("kind" in box && box.kind === "note") {
338
+ return Math.max(box.width - 2 * WHITEBOARD_NOTE_PAD, MIN_WRAP);
339
+ }
340
+ if ("shape" in box && box.shape === "queue") {
341
+ return Math.max(box.width - 2 * LABEL_PAD - 3 * QUEUE_CAP, MIN_WRAP);
342
+ }
343
+ const inset = "shape" in box && box.shape === "ellipse" ? box.width * ELLIPSE_INSET : 0;
344
+ return Math.max(box.width - 2 * (LABEL_PAD + inset), MIN_WRAP);
345
+ }
346
+ function whiteboardLabelShift(box) {
347
+ return "shape" in box && box.shape === "queue" ? -QUEUE_CAP / 2 : 0;
348
+ }
349
+ function whiteboardLabelHeight(box) {
350
+ if ("kind" in box && box.kind === "note") {
351
+ return Math.max(box.height - 2 * WHITEBOARD_NOTE_PAD, 0);
352
+ }
353
+ const shape = "shape" in box ? box.shape : "rectangle";
354
+ const inset = shape === "ellipse" ? box.height * ELLIPSE_INSET : shape === "database" ? 2 * CYLINDER_RY : 0;
355
+ return Math.max(box.height - 2 * (LABEL_PAD + inset), 0);
356
+ }
357
+ function wrapWhiteboardLabel(label, box) {
358
+ if (!label) return [];
359
+ const width = whiteboardLabelWidth(box);
360
+ const font = "kind" in box && box.kind === "note" ? WHITEBOARD_NOTE_FONT : WHITEBOARD_LABEL_FONT;
361
+ return label.split("\n").flatMap((line) => line ? wrapTextToWidth(line, font, width) : [""]);
362
+ }
363
+ function fitWhiteboardLabel(label, box) {
364
+ const isNote = "kind" in box && box.kind === "note";
365
+ const full = isNote ? WHITEBOARD_NOTE_FONT : WHITEBOARD_LABEL_FONT;
366
+ const pad = isNote ? WHITEBOARD_NOTE_PAD : LABEL_PAD;
367
+ if (!label) return { lines: [], font: full, top: pad };
368
+ const width = whiteboardLabelWidth(box);
369
+ const height = whiteboardLabelHeight(box);
370
+ const wrap = (font2, hardBreak) => label.split("\n").flatMap(
371
+ (line) => line ? wrapTextToWidth(line, font2, width, { hardBreak }) : [""]
372
+ );
373
+ const tall = (n, font2) => n * font2 * WHITEBOARD_LABEL_LINE > height;
374
+ for (let font2 = full; font2 >= WHITEBOARD_LABEL_MIN_FONT; font2--) {
375
+ const lines2 = wrap(font2, false);
376
+ if (!tall(lines2.length, font2) && lines2.every((l) => measureText(l, font2) <= width))
377
+ return { lines: lines2, font: font2, top: pad };
378
+ }
379
+ const font = WHITEBOARD_LABEL_MIN_FONT;
380
+ const lines = wrap(font, true);
381
+ const lh = font * WHITEBOARD_LABEL_LINE;
382
+ const room = isNote ? Math.max(
383
+ 1,
384
+ Math.floor(
385
+ (box.height - NOTE_TIGHT_TOP - NOTE_TIGHT_BOTTOM - font) / lh
386
+ ) + 1
387
+ ) : Math.max(1, Math.floor(height / lh));
388
+ const top = isNote ? NOTE_TIGHT_TOP : pad;
389
+ if (lines.length <= room) return { lines, font, top };
390
+ const kept = lines.slice(0, room);
391
+ let last = kept[room - 1];
392
+ while (last && measureText(`${last}\u2026`, font) > width)
393
+ last = [...last].slice(0, -1).join("");
394
+ kept[room - 1] = `${last.trimEnd()}\u2026`;
395
+ return { lines: kept, font, top };
396
+ }
397
+
398
+ // src/whiteboard/renderer.ts
399
+ function visibleWhiteboardIndices(parsed, options = {}) {
400
+ const all = parsed.elements;
401
+ const show = options.showNotes ?? !parsed.options.noNotes;
402
+ const out = [];
403
+ all.forEach((el, i) => {
404
+ if (show) return void out.push(i);
405
+ if (el.kind === "note") return;
406
+ if (el.kind === "arrow" || el.kind === "line") {
407
+ const { from, to } = whiteboardConnectorAttachments(el, all);
408
+ if (all[from]?.kind === "note" || all[to]?.kind === "note") return;
409
+ }
410
+ out.push(i);
411
+ });
412
+ return out;
413
+ }
414
+ function visibleWhiteboardElements(parsed, options = {}) {
415
+ const show = options.showNotes ?? !parsed.options.noNotes;
416
+ if (show) return parsed.elements;
417
+ return visibleWhiteboardIndices(parsed, options).map(
418
+ (i) => parsed.elements[i]
419
+ );
420
+ }
421
+ var WHITEBOARD_MARGIN = 24;
422
+ var TITLE_BAND = 40;
423
+ var SHAPE_STROKE = 2;
424
+ var ARROW_STROKE = 2;
425
+ var ARROW_HEAD_LEN = 12;
426
+ var ARROW_HEAD_HALF = 6;
427
+ var LABEL_HALO = 3;
428
+ var DASH_ON = 3;
429
+ var DASH_OFF = 4;
430
+ var WHITEBOARD_TEXT_FONT = 16;
431
+ var NOTE_TINT = 40;
432
+ var NOTE_EDGE = 65;
433
+ var SOLID_EDGE = 55;
434
+ var NOTE_INK = 40;
435
+ var NOTE_FOLD_OPACITY = 0.55;
436
+ var BASELINE = 0.8;
437
+ var IMAGE_NOT_UPLOADED = "image not uploaded";
438
+ var PLACEHOLDER_MIN_FONT = 8;
439
+ var SAFE_IMAGE_HREF_RE = /^(https?:|blob:|data:image\/)/i;
440
+ function labelLines(label) {
441
+ return label.split("\n");
442
+ }
443
+ function widest(lines, font) {
444
+ return Math.max(0, ...lines.map((l) => measureText(l, font)));
445
+ }
446
+ function grow(b, x0, y0, x1, y1) {
447
+ b.minX = Math.min(b.minX, x0, x1);
448
+ b.minY = Math.min(b.minY, y0, y1);
449
+ b.maxX = Math.max(b.maxX, x0, x1);
450
+ b.maxY = Math.max(b.maxY, y0, y1);
451
+ }
452
+ function noteTextHeight(el) {
453
+ const { lines, font, top } = fitWhiteboardLabel(el.text, el);
454
+ return 2 * top + lines.length * font * WHITEBOARD_LABEL_LINE;
455
+ }
456
+ function whiteboardBounds(parsed, options = {}) {
457
+ const b = {
458
+ minX: Infinity,
459
+ minY: Infinity,
460
+ maxX: -Infinity,
461
+ maxY: -Infinity
462
+ };
463
+ const elements = visibleWhiteboardElements(parsed, options);
464
+ for (const el of elements) {
465
+ switch (el.kind) {
466
+ case "shape":
467
+ case "image":
468
+ grow(b, el.x, el.y, el.x + el.width, el.y + el.height);
469
+ break;
470
+ case "note":
471
+ grow(
472
+ b,
473
+ el.x,
474
+ el.y,
475
+ el.x + el.width,
476
+ el.y + Math.max(el.height, noteTextHeight(el))
477
+ );
478
+ break;
479
+ case "arrow":
480
+ case "line": {
481
+ const s = clipWhiteboardConnector(el, elements);
482
+ const pad = ARROW_HEAD_HALF + ARROW_STROKE;
483
+ grow(b, s.x1 - pad, s.y1 - pad, s.x2 + pad, s.y2 + pad);
484
+ grow(b, s.x1 + pad, s.y1 + pad, s.x2 - pad, s.y2 - pad);
485
+ if (s.cx !== void 0) {
486
+ for (let k = 1; k < CURVE_BOUND_STEPS; k++) {
487
+ const p = segmentPoint(s, k / CURVE_BOUND_STEPS);
488
+ grow(b, p.x - pad, p.y - pad, p.x + pad, p.y + pad);
489
+ }
490
+ }
491
+ if (el.label) {
492
+ const lines = labelLines(el.label);
493
+ const { x: mx, y: my } = whiteboardSegmentMidpoint(s);
494
+ const hw = widest(lines, WHITEBOARD_LABEL_FONT) / 2 + 4;
495
+ const hh = WHITEBOARD_LABEL_FONT + (lines.length - 1) * WHITEBOARD_LABEL_FONT * WHITEBOARD_LABEL_LINE / 2;
496
+ grow(b, mx - hw, my - hh, mx + hw, my + hh);
497
+ }
498
+ break;
499
+ }
500
+ case "text": {
501
+ const lines = labelLines(el.text);
502
+ grow(
503
+ b,
504
+ el.x,
505
+ el.y,
506
+ el.x + widest(lines, WHITEBOARD_TEXT_FONT),
507
+ el.y + lines.length * WHITEBOARD_TEXT_FONT * WHITEBOARD_LABEL_LINE
508
+ );
509
+ break;
510
+ }
511
+ case "ink": {
512
+ const r = el.width;
513
+ for (const p of el.points) grow(b, p.x - r, p.y - r, p.x + r, p.y + r);
514
+ break;
515
+ }
516
+ }
517
+ }
518
+ if (!Number.isFinite(b.minX)) return { minX: 0, minY: 0, maxX: 0, maxY: 0 };
519
+ return b;
520
+ }
521
+ var CURVE_BOUND_STEPS = 16;
522
+ function segmentPoint(s, t) {
523
+ const u = 1 - t;
524
+ if (s.cx === void 0 || s.cy === void 0) {
525
+ return { x: u * s.x1 + t * s.x2, y: u * s.y1 + t * s.y2 };
526
+ }
527
+ return {
528
+ x: u * u * s.x1 + 2 * u * t * s.cx + t * t * s.x2,
529
+ y: u * u * s.y1 + 2 * u * t * s.cy + t * t * s.y2
530
+ };
531
+ }
532
+ function curveTrim(s, end, len) {
533
+ const tip = segmentPoint(s, end);
534
+ let near = end;
535
+ let far = 1 - end;
536
+ for (let n = 0; n < 24; n++) {
537
+ const m = (near + far) / 2;
538
+ const p = segmentPoint(s, m);
539
+ if (Math.hypot(p.x - tip.x, p.y - tip.y) < len) near = m;
540
+ else far = m;
541
+ }
542
+ return (near + far) / 2;
543
+ }
544
+ function whiteboardConnectorPaint(s, heads) {
545
+ const polygon = (tip, ux, uy, head) => {
546
+ const bx = tip.x - ux * head;
547
+ const by = tip.y - uy * head;
548
+ const px = -uy * ARROW_HEAD_HALF;
549
+ const py = ux * ARROW_HEAD_HALF;
550
+ return `${round2(tip.x)},${round2(tip.y)} ${round2(bx + px)},${round2(by + py)} ${round2(bx - px)},${round2(by - py)}`;
551
+ };
552
+ const dx = s.x2 - s.x1;
553
+ const dy = s.y2 - s.y1;
554
+ const len = Math.hypot(dx, dy);
555
+ if (s.cx === void 0 || s.cy === void 0) {
556
+ if (len === 0) return { heads: [] };
557
+ const ux = dx / len;
558
+ const uy = dy / len;
559
+ const headE = heads.end ? Math.min(ARROW_HEAD_LEN, len) : 0;
560
+ const headS = heads.start ? Math.min(ARROW_HEAD_LEN, len / 2) : 0;
561
+ const head = heads.start ? Math.min(headE, len / 2) : headE;
562
+ const out2 = [];
563
+ if (heads.end) out2.push(polygon({ x: s.x2, y: s.y2 }, ux, uy, head));
564
+ if (heads.start) out2.push(polygon({ x: s.x1, y: s.y1 }, -ux, -uy, headS));
565
+ return {
566
+ line: {
567
+ x1: round2(s.x1 + ux * headS),
568
+ y1: round2(s.y1 + uy * headS),
569
+ x2: round2(s.x2 - ux * head),
570
+ y2: round2(s.y2 - uy * head)
571
+ },
572
+ heads: out2
573
+ };
574
+ }
575
+ const tEnd = heads.end ? curveTrim(s, 1, ARROW_HEAD_LEN) : 1;
576
+ const tStart = heads.start ? curveTrim(s, 0, ARROW_HEAD_LEN) : 0;
577
+ const [t0, t1] = tEnd - tStart > 0 ? [tStart, tEnd] : [0, 1];
578
+ const p0 = segmentPoint(s, t0);
579
+ const p1 = segmentPoint(s, t1);
580
+ const w0 = (1 - t0) * (1 - t1);
581
+ const w1 = (1 - t0) * t1 + t0 * (1 - t1);
582
+ const w2 = t0 * t1;
583
+ const qx = w0 * s.x1 + w1 * s.cx + w2 * s.x2;
584
+ const qy = w0 * s.y1 + w1 * s.cy + w2 * s.y2;
585
+ const out = [];
586
+ const along = (tip, base) => {
587
+ const hx = tip.x - base.x;
588
+ const hy = tip.y - base.y;
589
+ const hl = Math.hypot(hx, hy);
590
+ if (hl > 0) out.push(polygon(tip, hx / hl, hy / hl, hl));
591
+ };
592
+ if (heads.end) along({ x: s.x2, y: s.y2 }, p1);
593
+ if (heads.start) along({ x: s.x1, y: s.y1 }, p0);
594
+ return {
595
+ path: `M${round2(p0.x)} ${round2(p0.y)}Q${round2(qx)} ${round2(qy)} ${round2(p1.x)} ${round2(p1.y)}`,
596
+ heads: out
597
+ };
598
+ }
599
+ function inkOutlinePath(points, width) {
600
+ const hasPressure = points.every((p) => p.pressure !== void 0);
601
+ const outline = getStroke(
602
+ points.map((p) => hasPressure ? [p.x, p.y, p.pressure] : [p.x, p.y]),
603
+ {
604
+ size: width,
605
+ thinning: 0.5,
606
+ smoothing: 0.5,
607
+ streamline: 0.5,
608
+ simulatePressure: !hasPressure,
609
+ last: true
610
+ }
611
+ );
612
+ if (outline.length === 0) return "";
613
+ const r = (n) => String(Math.round(n * 100) / 100);
614
+ const first = outline[0];
615
+ let d = `M${r(first[0])} ${r(first[1])}Q`;
616
+ for (let i = 0; i < outline.length; i++) {
617
+ const a = outline[i];
618
+ const b = outline[(i + 1) % outline.length];
619
+ d += `${r(a[0])} ${r(a[1])} ${r((a[0] + b[0]) / 2)} ${r((a[1] + b[1]) / 2)} `;
620
+ }
621
+ return d.trimEnd() + "Z";
622
+ }
623
+ function renderWhiteboard(container, parsed, palette, isDark, options = {}) {
624
+ const base = themeBaseBg(palette, isDark);
625
+ const colorOf = (c) => c === "ink" ? palette.text : palette.colors[c] ?? palette.text;
626
+ const fillOf = (c) => c === "ink" ? base : shapeFill(palette, colorOf(c), isDark);
627
+ const showTitle = !!parsed.title && !parsed.options.noTitle;
628
+ const titleOffset = showTitle ? TITLE_BAND : 0;
629
+ const elements = visibleWhiteboardElements(parsed, options);
630
+ const b = whiteboardBounds(parsed, options);
631
+ const contentW = b.maxX - b.minX;
632
+ const contentH = b.maxY - b.minY;
633
+ const titleW = showTitle ? measureText(parsed.title, TITLE_FONT_SIZE, { bold: true }) : 0;
634
+ const width = Math.ceil(Math.max(contentW, titleW) + 2 * WHITEBOARD_MARGIN);
635
+ const height = Math.ceil(contentH + 2 * WHITEBOARD_MARGIN + titleOffset);
636
+ const tx = WHITEBOARD_MARGIN - b.minX + (width - 2 * WHITEBOARD_MARGIN - contentW) / 2;
637
+ const ty = WHITEBOARD_MARGIN + titleOffset - b.minY;
638
+ d3.select(container).selectAll("*").remove();
639
+ const svg = d3.select(container).append("svg").attr("width", width).attr("height", height).attr("viewBox", `0 0 ${width} ${height}`).style("font-family", FONT_FAMILY);
640
+ if (showTitle) {
641
+ renderChartTitle(
642
+ svg,
643
+ parsed.title,
644
+ parsed.titleLineNumber,
645
+ width,
646
+ palette.text
647
+ );
648
+ }
649
+ const canvas = svg.append("g").attr("class", "whiteboard-canvas").attr("transform", `translate(${round2(tx)},${round2(ty)})`);
650
+ const halo = palette.bg;
651
+ const centredLabel = (g, { lines, font }, cx, cy, color, ground) => {
652
+ if (lines.length === 0) return;
653
+ const lh = font * WHITEBOARD_LABEL_LINE;
654
+ const top = cy - lines.length * lh / 2 + lh * BASELINE;
655
+ const t = g.append("text").attr("class", "whiteboard-label").attr("text-anchor", "middle").attr("font-size", font).attr("fill", color).attr("stroke", ground).attr("stroke-width", LABEL_HALO).attr("stroke-linejoin", "round").attr("paint-order", "stroke");
656
+ appendLines(t, lines, cx, top, lh);
657
+ };
658
+ const drawImage = (g, el) => {
659
+ const resolved = options.resolveImage ? options.resolveImage(el.ref) : /^https:\/\//i.test(el.ref) ? el.ref : void 0;
660
+ if (resolved !== void 0 && SAFE_IMAGE_HREF_RE.test(resolved)) {
661
+ g.append("image").attr("x", el.x).attr("y", el.y).attr("width", el.width).attr("height", el.height).attr("preserveAspectRatio", "xMidYMid meet").attr("href", resolved);
662
+ return;
663
+ }
664
+ g.append("rect").attr("class", "whiteboard-image-placeholder").attr("x", el.x).attr("y", el.y).attr("width", el.width).attr("height", el.height).attr("rx", 4).attr("fill", mix(palette.textMuted, base, 10)).attr("stroke", mix(palette.textMuted, base, 50)).attr("stroke-width", 1).attr("stroke-dasharray", "6 4");
665
+ const fit = Math.min(
666
+ WHITEBOARD_LABEL_FONT,
667
+ (el.width - 8) / (IMAGE_NOT_UPLOADED.length * 0.55)
668
+ );
669
+ if (fit < PLACEHOLDER_MIN_FONT) return;
670
+ g.append("text").attr("x", el.x + el.width / 2).attr("y", el.y + el.height / 2 + fit * 0.35).attr("text-anchor", "middle").attr("font-size", round2(fit)).attr("fill", palette.textMuted).text(IMAGE_NOT_UPLOADED);
671
+ };
672
+ const drawElement = (el) => {
673
+ const g = canvas.append("g").attr("class", `whiteboard-${el.kind === "shape" ? el.shape : el.kind}`).attr("data-line-number", el.lineNumber);
674
+ switch (el.kind) {
675
+ case "shape": {
676
+ const hue = colorOf(el.color);
677
+ const fill = el.fill === "solid" ? hue : el.fill === "outline" ? "none" : fillOf(el.color);
678
+ const labelColor = el.fill === "solid" ? contrastText(hue, base, palette.text) : palette.text;
679
+ const stroke = el.fill === "solid" ? mix(hue, labelColor, SOLID_EDGE) : hue;
680
+ const cx = el.x + el.width / 2;
681
+ const cy = el.y + el.height / 2;
682
+ if (el.shape === "rectangle") {
683
+ g.append("rect").attr("x", el.x).attr("y", el.y).attr("width", el.width).attr("height", el.height).attr("rx", Math.min(RECT_RADIUS, el.width / 2, el.height / 2)).attr("fill", fill).attr("stroke", stroke).attr("stroke-width", SHAPE_STROKE);
684
+ } else if (el.shape === "ellipse") {
685
+ g.append("ellipse").attr("cx", cx).attr("cy", cy).attr("rx", el.width / 2).attr("ry", el.height / 2).attr("fill", fill).attr("stroke", stroke).attr("stroke-width", SHAPE_STROKE);
686
+ } else {
687
+ const inner = g.append("g").attr("transform", `translate(${round2(cx)},${round2(cy)})`);
688
+ if (el.shape === "database") {
689
+ drawCylinderCard(inner, el.width, el.height, fill, stroke, false);
690
+ } else {
691
+ drawQueueCard(inner, el.width, el.height, fill, stroke);
692
+ }
693
+ }
694
+ centredLabel(
695
+ g,
696
+ fitWhiteboardLabel(el.label, el),
697
+ cx + whiteboardLabelShift(el),
698
+ cy,
699
+ labelColor,
700
+ fill === "none" ? halo : fill
701
+ );
702
+ break;
703
+ }
704
+ case "note": {
705
+ const hue = colorOf(el.color);
706
+ const edge = mix(hue, base, NOTE_EDGE);
707
+ const { x, y, width: w, height: h } = el;
708
+ const f = whiteboardNoteFold(w, h);
709
+ g.append("path").attr("d", `M${x} ${y}h${w - f}l${f} ${f}v${h - f}h${-w}z`).attr("fill", mix(hue, base, NOTE_TINT)).attr("stroke", edge).attr("stroke-width", 1).attr("stroke-linejoin", "round");
710
+ if (f > 2) {
711
+ g.append("path").attr("class", "whiteboard-note-fold").attr("d", `M${x + w - f} ${y}v${f - 2}q0 2 2 2h${f - 2}z`).attr("fill", edge).attr("opacity", NOTE_FOLD_OPACITY);
712
+ }
713
+ const { lines, font, top } = fitWhiteboardLabel(el.text, el);
714
+ if (lines.length > 0) {
715
+ const lh = font * WHITEBOARD_LABEL_LINE;
716
+ const t = g.append("text").attr("class", "whiteboard-label").attr("font-size", font).attr("fill", mix(hue, palette.text, NOTE_INK));
717
+ appendLines(
718
+ t,
719
+ lines,
720
+ el.x + WHITEBOARD_NOTE_PAD,
721
+ el.y + top + lh * BASELINE,
722
+ lh
723
+ );
724
+ }
725
+ break;
726
+ }
727
+ case "arrow":
728
+ case "line": {
729
+ const color = colorOf(el.color);
730
+ const s = clipWhiteboardConnector(el, elements);
731
+ const paint = whiteboardConnectorPaint(s, {
732
+ start: el.kind === "arrow" && el.heads === "both",
733
+ end: el.kind === "arrow"
734
+ });
735
+ let stroke = null;
736
+ if (paint.line) {
737
+ stroke = g.append("line").attr("x1", paint.line.x1).attr("y1", paint.line.y1).attr("x2", paint.line.x2).attr("y2", paint.line.y2);
738
+ } else if (paint.path) {
739
+ stroke = g.append("path").attr("d", paint.path).attr("fill", "none");
740
+ }
741
+ if (stroke) {
742
+ stroke.attr("stroke", color).attr("stroke-width", ARROW_STROKE).attr("stroke-linecap", "round");
743
+ if (el.style === "dashed") {
744
+ stroke.attr(
745
+ "stroke-dasharray",
746
+ `${DASH_ON * ARROW_STROKE} ${DASH_OFF * ARROW_STROKE}`
747
+ );
748
+ }
749
+ }
750
+ for (const points of paint.heads) {
751
+ g.append("polygon").attr("points", points).attr("fill", color);
752
+ }
753
+ if (el.label) {
754
+ const lines = labelLines(el.label);
755
+ const mid = whiteboardSegmentMidpoint(s);
756
+ const mx = round2(mid.x);
757
+ const lh = WHITEBOARD_LABEL_FONT * WHITEBOARD_LABEL_LINE;
758
+ const firstY = mid.y + WHITEBOARD_LABEL_FONT * 0.35 - (lines.length - 1) * lh / 2;
759
+ const t = g.append("text").attr("class", "whiteboard-label").attr("x", mx).attr("y", round2(firstY)).attr("text-anchor", "middle").attr("font-size", WHITEBOARD_LABEL_FONT).attr("fill", palette.text).attr("stroke", halo).attr("stroke-width", 4).attr("stroke-linejoin", "round").attr("paint-order", "stroke");
760
+ if (lines.length === 1) t.text(el.label);
761
+ else appendLines(t, lines, mx, firstY, lh);
762
+ }
763
+ break;
764
+ }
765
+ case "text": {
766
+ const lines = labelLines(el.text);
767
+ const firstY = el.y + WHITEBOARD_TEXT_FONT * BASELINE;
768
+ const t = g.append("text").attr("x", el.x).attr("y", round2(firstY)).attr("font-size", WHITEBOARD_TEXT_FONT).attr("fill", colorOf(el.color));
769
+ if (lines.length === 1) t.text(el.text);
770
+ else
771
+ appendLines(
772
+ t,
773
+ lines,
774
+ el.x,
775
+ firstY,
776
+ WHITEBOARD_TEXT_FONT * WHITEBOARD_LABEL_LINE
777
+ );
778
+ break;
779
+ }
780
+ case "image":
781
+ drawImage(g, el);
782
+ break;
783
+ case "ink": {
784
+ const d = inkOutlinePath(el.points, el.width);
785
+ if (d) g.append("path").attr("d", d).attr("fill", colorOf(el.color));
786
+ break;
787
+ }
788
+ }
789
+ };
790
+ for (const el of elements) drawElement(el);
791
+ }
792
+ function appendLines(t, lines, x, firstY, lh) {
793
+ lines.forEach((ln, i) => {
794
+ if (!ln) return;
795
+ t.append("tspan").attr("x", round2(x)).attr("y", round2(firstY + i * lh)).text(ln);
796
+ });
797
+ }
798
+ function round2(n) {
799
+ return Math.round(n * 100) / 100;
800
+ }
801
+
802
+ export {
803
+ whiteboardNoteFold,
804
+ whiteboardShapeContains,
805
+ whiteboardShapeAt,
806
+ whiteboardConnectorAttachments,
807
+ clipWhiteboardConnector,
808
+ whiteboardBendHandle,
809
+ whiteboardBendFor,
810
+ whiteboardSegmentMidpoint,
811
+ WHITEBOARD_NOTE_FONT,
812
+ WHITEBOARD_LABEL_MIN_FONT,
813
+ whiteboardLabelWidth,
814
+ whiteboardLabelShift,
815
+ whiteboardLabelHeight,
816
+ wrapWhiteboardLabel,
817
+ fitWhiteboardLabel,
818
+ visibleWhiteboardIndices,
819
+ visibleWhiteboardElements,
820
+ IMAGE_NOT_UPLOADED,
821
+ whiteboardBounds,
822
+ whiteboardConnectorPaint,
823
+ inkOutlinePath,
824
+ renderWhiteboard
825
+ };