@diagrammo/dgmo 0.76.0 → 0.78.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 (229) hide show
  1. package/README.md +17 -13
  2. package/dist/advanced.d.ts +150 -13
  3. package/dist/advanced.js +180 -131
  4. package/dist/block.css +1 -1
  5. package/dist/block.d.ts +2 -2
  6. package/dist/block.js +45 -41
  7. package/dist/{chart-meta-lP8Rl19E.d.ts → chart-meta-BKN2ORkc.d.ts} +2 -2
  8. package/dist/chart-meta.d.ts +3 -3
  9. package/dist/chart-meta.js +30 -29
  10. package/dist/charts-d3-KEQ7XVSM.js +31 -0
  11. package/dist/{chunk-7IATMZSA.js → chunk-26EVL454.js} +1 -25
  12. package/dist/{chunk-3H4PDNP4.js → chunk-2NLBIZEW.js} +2 -2
  13. package/dist/{chunk-GFXFRKUG.js → chunk-32VR65TL.js} +63 -36
  14. package/dist/{chunk-IHUOYDLN.js → chunk-36UQ77JV.js} +24 -24
  15. package/dist/chunk-3DPOIW3W.js +10 -0
  16. package/dist/{chunk-3SP6G4LN.js → chunk-3GLTQZKE.js} +2 -2
  17. package/dist/{chunk-DY7KDZUF.js → chunk-3OWIYK52.js} +2 -2
  18. package/dist/{chunk-UBW53CNS.js → chunk-3XFOE3DQ.js} +12 -7
  19. package/dist/{chunk-W7UBPARG.js → chunk-3ZLQM6XN.js} +2 -2
  20. package/dist/{chunk-5GM6BZO7.js → chunk-4AWLEWSD.js} +5 -2
  21. package/dist/{chunk-AYM472K3.js → chunk-4IGUEGD6.js} +80 -61
  22. package/dist/{chunk-QOVM5VRC.js → chunk-57GSSHBR.js} +2 -2
  23. package/dist/{chunk-5VMUVJO4.js → chunk-5G55TS3H.js} +2 -2
  24. package/dist/{chunk-QT5UMFPE.js → chunk-67I3HFSF.js} +9 -9
  25. package/dist/{chunk-WQXD3IIN.js → chunk-6B3M6LW6.js} +10 -8
  26. package/dist/{chunk-3EGIU5WY.js → chunk-6PHOZBW5.js} +4 -6
  27. package/dist/{chunk-5PFNUDXR.js → chunk-6VTLVU7D.js} +2 -2
  28. package/dist/{chunk-M5JT2AU7.js → chunk-6Z2NUJSX.js} +2 -2
  29. package/dist/{chunk-BWJLLNUX.js → chunk-7BNRHSSF.js} +2 -2
  30. package/dist/{chunk-JLODGGN2.js → chunk-7NNJXYXU.js} +2 -2
  31. package/dist/{chunk-FTTB64OJ.js → chunk-7SMVTA7I.js} +26 -26
  32. package/dist/{chunk-Z7KVOVE4.js → chunk-7WTFX6OA.js} +6 -3
  33. package/dist/{chunk-ZM27UI5O.js → chunk-A7Y32YD6.js} +2 -2
  34. package/dist/{chunk-FPRMP6YA.js → chunk-AHN2CVCH.js} +10 -7
  35. package/dist/{chunk-N6MZSBOL.js → chunk-AN7T6VP7.js} +2 -2
  36. package/dist/{chunk-F4X5NVKY.js → chunk-B6PVPAS5.js} +2 -2
  37. package/dist/{chunk-QI4Q5ZZH.js → chunk-BB2ORSTF.js} +19 -18
  38. package/dist/{chunk-HGFKDSKZ.js → chunk-BJB4YDJP.js} +21 -21
  39. package/dist/{chunk-BZQCAZZZ.js → chunk-BPM52K3Z.js} +41 -34
  40. package/dist/{chunk-HFCKU73Y.js → chunk-BSREARWG.js} +29 -28
  41. package/dist/{chunk-F4V67JXG.js → chunk-CTERZC4K.js} +2 -2
  42. package/dist/{chunk-FMZEU7MF.js → chunk-CYLSQO4L.js} +6 -6
  43. package/dist/{chunk-JLJ7SP4X.js → chunk-DCPD5SHV.js} +3 -3
  44. package/dist/{chunk-U7AO6FRL.js → chunk-ENDB5YSV.js} +363 -129
  45. package/dist/{chunk-RTTZIX34.js → chunk-EOB7XVYR.js} +2 -2
  46. package/dist/chunk-EPDBWATV.js +38 -0
  47. package/dist/{chunk-TPN7RJOM.js → chunk-FJADQOFQ.js} +3 -3
  48. package/dist/{chunk-MG3DE3VO.js → chunk-FLMXJMMY.js} +3 -3
  49. package/dist/{chunk-WGC42WJU.js → chunk-FWNJDD4U.js} +6 -2
  50. package/dist/{chunk-S5P5Z5Y5.js → chunk-GINNZHVN.js} +2 -2
  51. package/dist/{chunk-7EZ5AKBK.js → chunk-GJH7ZEPH.js} +45 -38
  52. package/dist/{chunk-E3BJVEMZ.js → chunk-GQEXY7XL.js} +68 -65
  53. package/dist/{chunk-COCMMQXW.js → chunk-HHHYVTVS.js} +16 -16
  54. package/dist/chunk-ICLB27PZ.js +11 -0
  55. package/dist/{chunk-QMFIZQTB.js → chunk-IDGQB6XD.js} +6 -4
  56. package/dist/{chunk-R3XI2VC7.js → chunk-IDJGV6VM.js} +2 -1
  57. package/dist/{chunk-4CRLM3IT.js → chunk-IE47TYZT.js} +177 -118
  58. package/dist/{chunk-FJ57274M.js → chunk-IIEI7VK5.js} +15 -1
  59. package/dist/{chunk-YDA46XHI.js → chunk-IMO46ROR.js} +38 -32
  60. package/dist/{chunk-4SXHMFFP.js → chunk-IZTU6WVR.js} +24 -13
  61. package/dist/{chunk-U74EGVOA.js → chunk-JOD2CK2M.js} +16 -14
  62. package/dist/{chunk-U5B3TUEW.js → chunk-JUNTVLOU.js} +16 -15
  63. package/dist/{chunk-RWFMOVHG.js → chunk-KAZQX2EY.js} +2 -2
  64. package/dist/{chunk-NHQ7HUAS.js → chunk-KGX5LIUG.js} +10 -8
  65. package/dist/{chunk-Q74GP3GK.js → chunk-KO6DGOOB.js} +3 -3
  66. package/dist/{chunk-UTTRJ6KN.js → chunk-L26M3X7K.js} +16 -13
  67. package/dist/{chunk-RU2HHHYA.js → chunk-LD2JSKU3.js} +12 -2
  68. package/dist/{chunk-32MOGTKT.js → chunk-LEBPWFVF.js} +50 -46
  69. package/dist/{chunk-MU3CJPJF.js → chunk-LGI735AJ.js} +2 -2
  70. package/dist/{chunk-OWVDD5EC.js → chunk-LMWXBFLA.js} +2 -2
  71. package/dist/{chunk-CLQJAGWL.js → chunk-M3LZCDB6.js} +40 -42
  72. package/dist/{chunk-YT5ICQ4R.js → chunk-MFK7LF66.js} +2 -2
  73. package/dist/{chunk-JL7BDLC6.js → chunk-MJYFPFZT.js} +110 -20
  74. package/dist/{chunk-2QRIMMIH.js → chunk-N56W4R66.js} +2 -2
  75. package/dist/{chunk-LXXVHLTH.js → chunk-NN5IDH2I.js} +2 -2
  76. package/dist/{chunk-46KVXDUJ.js → chunk-NS3KIRSW.js} +2 -2
  77. package/dist/{chunk-LM3HY3VG.js → chunk-P2DM7Q5U.js} +2 -2
  78. package/dist/{chunk-DJL5PO27.js → chunk-P4SQV3XD.js} +2 -2
  79. package/dist/{chunk-HOIAQ3P2.js → chunk-P54AX5XN.js} +9 -9
  80. package/dist/{chunk-JQ575OAK.js → chunk-P64NBPSK.js} +14 -14
  81. package/dist/{chunk-7G4XMHDB.js → chunk-PIWUZFG7.js} +33 -25
  82. package/dist/{chunk-SWEKCK34.js → chunk-QAPFXLAC.js} +2 -2
  83. package/dist/chunk-QFIXL3OK.js +68 -0
  84. package/dist/{chunk-KRTLS3G6.js → chunk-QVMV4KCA.js} +2 -2
  85. package/dist/{chunk-76LHNLGX.js → chunk-R4YGH7DJ.js} +5 -3
  86. package/dist/{chunk-PAW4RMH3.js → chunk-RC3FM3FE.js} +12 -13
  87. package/dist/{chunk-UJBP57UJ.js → chunk-RC6GGF6X.js} +2 -2
  88. package/dist/{chunk-S6OXNZBM.js → chunk-RHZZVIGA.js} +3 -3
  89. package/dist/{chunk-MS5574I7.js → chunk-RIXWLFB4.js} +2 -2
  90. package/dist/{chunk-BCB24FG7.js → chunk-RUNI4OXP.js} +18 -14
  91. package/dist/{chunk-ICVIJLBA.js → chunk-SFSJ6XWV.js} +2 -2
  92. package/dist/{chunk-EGXJWRO6.js → chunk-SNBEAO4Q.js} +8 -8
  93. package/dist/{chunk-XHROEQ23.js → chunk-SXD6VY7D.js} +16 -14
  94. package/dist/{chunk-GEURKGZS.js → chunk-TLM3I4XF.js} +16 -16
  95. package/dist/{chunk-IFC3JXCT.js → chunk-TO6TWNMF.js} +19 -15
  96. package/dist/{chunk-OUJG73YJ.js → chunk-U2JIFCJN.js} +18 -18
  97. package/dist/{chunk-CAPR5DET.js → chunk-U4ND3J6C.js} +18 -14
  98. package/dist/{chunk-YVDBBWEP.js → chunk-UCF6TKWV.js} +51 -48
  99. package/dist/{chunk-UWYZIGCB.js → chunk-UDYJVX6Y.js} +9 -9
  100. package/dist/{chunk-OBYZU23V.js → chunk-UQY2VLUK.js} +25 -23
  101. package/dist/{chunk-CQKD6GOC.js → chunk-VAA7QSZ7.js} +53 -32
  102. package/dist/{chunk-Q6BAFS7I.js → chunk-VQGQF7O7.js} +12 -10
  103. package/dist/{chunk-DEW62ON3.js → chunk-VSPNH7LC.js} +2 -2
  104. package/dist/{chunk-4YER7UCV.js → chunk-VUJQ6RU6.js} +2 -2
  105. package/dist/{chunk-C576CU77.js → chunk-VZD3ZV4Y.js} +26 -22
  106. package/dist/{chunk-NCT22MOD.js → chunk-WMIKC5XO.js} +2 -2
  107. package/dist/{chunk-C2WH3BMS.js → chunk-X326N4GN.js} +10 -7
  108. package/dist/chunk-XBJJP2HN.js +37 -0
  109. package/dist/{chunk-7NSNE52V.js → chunk-XCR3PDFF.js} +2 -2
  110. package/dist/{chunk-TF76LCZS.js → chunk-XDPJMLOH.js} +30 -27
  111. package/dist/{chunk-3LJNQ6LR.js → chunk-YKDZ3ZRI.js} +27 -25
  112. package/dist/{chunk-GLREDNBA.js → chunk-YVLTNNME.js} +12 -2
  113. package/dist/{chunk-76IBFEYW.js → chunk-ZGOBAMQ2.js} +15 -13
  114. package/dist/{chunk-AFR6GWXD.js → chunk-ZMCFUGKO.js} +49 -42
  115. package/dist/clock.js +11 -5
  116. package/dist/completion-registry.js +2 -2
  117. package/dist/countdown.js +26 -20
  118. package/dist/{d3--y67plmW.d.ts → d3-CQT5bwpb.d.ts} +1 -1
  119. package/dist/{dgmo-router-CY5j16Pl.d.ts → dgmo-router-C9CsswPZ.d.ts} +1 -1
  120. package/dist/{dgmo-router-A3LIHT6H.js → dgmo-router-XZNCLYTV.js} +30 -29
  121. package/dist/{dimensions-7NYBSZRJ.js → dimensions-SIZMZ4DC.js} +8 -8
  122. package/dist/{flowchart-renderer-QYGQ64BM.js → flowchart-renderer-FDJ4QQXE.js} +15 -14
  123. package/dist/index.d.ts +7 -7
  124. package/dist/index.js +58 -43
  125. package/dist/{layout-LAS67TK3.js → layout-5DZ2LI2R.js} +2 -2
  126. package/dist/{layout-ZAGUFT2G.js → layout-6I6LSBUR.js} +6 -5
  127. package/dist/{layout-2OJ25STS.js → layout-C2SCZV5M.js} +6 -5
  128. package/dist/{layout-6SKHNQYO.js → layout-CHWKNE3O.js} +3 -3
  129. package/dist/{layout-EM4DLMAX.js → layout-K4KML2DL.js} +3 -3
  130. package/dist/{layout-KQUSB45X.js → layout-S53FSD6R.js} +7 -6
  131. package/dist/{layout-ROORJQ4X.js → layout-TCFXB5XH.js} +7 -6
  132. package/dist/{layout-5ILNODTP.js → layout-XK6ZD7BU.js} +6 -5
  133. package/dist/{layout-B5GQVXXY.js → layout-YVY72CIG.js} +7 -6
  134. package/dist/{layout-VUZ3MLOI.js → layout-YY6VH5XH.js} +6 -5
  135. package/dist/{layout-RV2T2YTT.js → layout-ZDN252GR.js} +4 -3
  136. package/dist/{layout-search-UOKEMER5.js → layout-search-TSV4FURP.js} +7 -6
  137. package/dist/{legend-constants-PLN2YHGM.js → legend-constants-SB4PLHV5.js} +3 -3
  138. package/dist/{palettes-54YSI3IX.js → palettes-YIPSRYXP.js} +5 -3
  139. package/dist/{parser-GCVSRQPY.js → parser-2BX2EJUB.js} +3 -3
  140. package/dist/{parser-WVE6SKB7.js → parser-3UNIPVNY.js} +3 -3
  141. package/dist/{parser-5XFGK5C5.js → parser-4IHIVDJD.js} +5 -5
  142. package/dist/{parser-ZT3PU2HT.js → parser-62VNEQRT.js} +3 -3
  143. package/dist/{parser-PR3OR3LO.js → parser-6JNJHQAG.js} +3 -3
  144. package/dist/{parser-ZXQZZK6W.js → parser-6ZFQLLVE.js} +3 -2
  145. package/dist/{parser-WMJEPZDC.js → parser-BOPXE6RP.js} +3 -3
  146. package/dist/{parser-WWRRG2DV.js → parser-DFBQ2RID.js} +3 -3
  147. package/dist/{parser-2GMHFSTS.js → parser-EPKXJ2RL.js} +3 -3
  148. package/dist/{parser-ML3LVNDV.js → parser-G7E2BURB.js} +3 -3
  149. package/dist/{parser-QOIZGW7I.js → parser-GFGU5ZLQ.js} +3 -3
  150. package/dist/{parser-L7T7FY3H.js → parser-GKZWI5SZ.js} +3 -3
  151. package/dist/{parser-QYAIFXLP.js → parser-HSPODF4H.js} +3 -3
  152. package/dist/{parser-EQ4I3TSH.js → parser-IK3FXZ7D.js} +3 -3
  153. package/dist/{parser-LV7PQBUG.js → parser-LJWPKRDM.js} +3 -3
  154. package/dist/{parser-RDBXEVI4.js → parser-OYWUBQV4.js} +3 -3
  155. package/dist/{parser-6FUESG4N.js → parser-PD4TP6NM.js} +3 -3
  156. package/dist/{parser-E3OHNNTH.js → parser-R2JHC7LQ.js} +3 -3
  157. package/dist/{parser-CJNP7RKR.js → parser-RMZ6YI7H.js} +3 -3
  158. package/dist/{parser-TA5TYZNL.js → parser-RUJNN5PK.js} +3 -3
  159. package/dist/{parser-UTR5WE4O.js → parser-YWE7GHW6.js} +3 -3
  160. package/dist/{parser-3AOMUX5D.js → parser-Z5UK6ADF.js} +3 -3
  161. package/dist/{parser-YWQCC33R.js → parser-ZO5YT5SV.js} +3 -3
  162. package/dist/renderer-5TPUPMZ7.js +26 -0
  163. package/dist/{renderer-4EWGZLJ6.js → renderer-AIVALEQR.js} +7 -7
  164. package/dist/renderer-AMELXBNW.js +23 -0
  165. package/dist/renderer-BF7FYXG3.js +25 -0
  166. package/dist/renderer-CRRW7LTW.js +17 -0
  167. package/dist/renderer-CXU2MGSC.js +27 -0
  168. package/dist/renderer-DI66RLAG.js +30 -0
  169. package/dist/renderer-E2JTYQY5.js +39 -0
  170. package/dist/{renderer-ZAJ5353N.js → renderer-FA4BTAOL.js} +7 -7
  171. package/dist/{renderer-GF6S5ZX6.js → renderer-FFGFTIT4.js} +15 -14
  172. package/dist/renderer-IVAM7Z3Y.js +27 -0
  173. package/dist/renderer-J6HK2KOW.js +23 -0
  174. package/dist/renderer-J7J3OVLQ.js +39 -0
  175. package/dist/{renderer-QAMOXOZ2.js → renderer-JC7MK7SD.js} +6 -5
  176. package/dist/{renderer-CGOPX4HW.js → renderer-JHQC5RGJ.js} +14 -14
  177. package/dist/renderer-JRITSZY3.js +28 -0
  178. package/dist/{renderer-E6NHTVN6.js → renderer-KD5X4RIS.js} +14 -13
  179. package/dist/{renderer-OTHBTGBN.js → renderer-KWNNWCGD.js} +6 -5
  180. package/dist/{renderer-EP4GRCDX.js → renderer-LGMIAG6N.js} +7 -6
  181. package/dist/{renderer-IH45QV6Z.js → renderer-LQN3FXAP.js} +33 -32
  182. package/dist/renderer-LRL4SU43.js +29 -0
  183. package/dist/{renderer-D7N7PPB7.js → renderer-MBL64AJI.js} +6 -6
  184. package/dist/renderer-NA3DTAWF.js +39 -0
  185. package/dist/renderer-OR5QHR7X.js +31 -0
  186. package/dist/renderer-SBVWHQVW.js +30 -0
  187. package/dist/{renderer-KMOGGMM7.js → renderer-TLOSBJKW.js} +13 -13
  188. package/dist/{renderer-LE3ZKHNS.js → renderer-UDWJRRIC.js} +11 -11
  189. package/dist/renderer-VHK6UAW2.js +20 -0
  190. package/dist/{renderer-FUJNSC5X.js → renderer-W5UG2HWT.js} +5 -5
  191. package/dist/renderer-WOOKJOBQ.js +25 -0
  192. package/dist/renderer-WYNLGZRF.js +25 -0
  193. package/dist/{renderer-BUEFD2IF.js → renderer-Y74Y54C3.js} +8 -8
  194. package/dist/renderer-ZUAXGHFC.js +28 -0
  195. package/dist/renderer-radial-YVUDGR7C.js +21 -0
  196. package/dist/{state-parser-TPA67IXM.js → state-parser-CT5HQQ7E.js} +3 -3
  197. package/dist/state-renderer-7O3QGNJ5.js +41 -0
  198. package/dist/{tag-groups-DrHT2tEc.d.ts → tag-groups-BoJg3lFV.d.ts} +23 -1
  199. package/dist/{themes-GWhsabnx.d.ts → themes-CXYnNA4e.d.ts} +2 -2
  200. package/docs/architecture-report.md +3 -3
  201. package/docs/language-reference.md +122 -30
  202. package/docs/migration-sequence-color-to-tags.md +16 -8
  203. package/gallery/fixtures/sketch.dgmo +1 -1
  204. package/package.json +7 -6
  205. package/dist/charts-d3-SQEVMIAM.js +0 -29
  206. package/dist/chunk-LP7EC4MI.js +0 -16
  207. package/dist/chunk-UTCPNJND.js +0 -7
  208. package/dist/chunk-VV6HZQ5K.js +0 -40
  209. package/dist/renderer-3FB56573.js +0 -22
  210. package/dist/renderer-4PNVGHVA.js +0 -16
  211. package/dist/renderer-5W3HWIUL.js +0 -24
  212. package/dist/renderer-CO5O5VR5.js +0 -20
  213. package/dist/renderer-DKW273R7.js +0 -26
  214. package/dist/renderer-F24V3RD3.js +0 -26
  215. package/dist/renderer-F6WSR7UM.js +0 -39
  216. package/dist/renderer-FGGDZZFQ.js +0 -31
  217. package/dist/renderer-GJDVPXI3.js +0 -30
  218. package/dist/renderer-JMJ7Q5OC.js +0 -28
  219. package/dist/renderer-LBNVKVO3.js +0 -39
  220. package/dist/renderer-MUW4G2N6.js +0 -38
  221. package/dist/renderer-PIEPRK6M.js +0 -23
  222. package/dist/renderer-PKRKLOYR.js +0 -25
  223. package/dist/renderer-PR3KLNST.js +0 -28
  224. package/dist/renderer-RUHC6D3B.js +0 -25
  225. package/dist/renderer-UUP6OX6F.js +0 -27
  226. package/dist/renderer-UYZSP7MF.js +0 -25
  227. package/dist/renderer-XBL6CLN2.js +0 -30
  228. package/dist/renderer-radial-MZP3SVTZ.js +0 -21
  229. package/dist/state-renderer-UIE3AQM6.js +0 -40
@@ -1,39 +1,63 @@
1
+ import {
2
+ appendArrowheadMarkers,
3
+ appendReverseArrowheadMarkers
4
+ } from "./chunk-XBJJP2HN.js";
1
5
  import {
2
6
  renderCollapseBar,
3
7
  renderNodeCard
4
- } from "./chunk-5GM6BZO7.js";
8
+ } from "./chunk-4AWLEWSD.js";
9
+ import {
10
+ ScaleContext
11
+ } from "./chunk-24YPR5EH.js";
5
12
  import {
13
+ ARROWHEAD_HEIGHT,
14
+ ARROWHEAD_WIDTH,
6
15
  CARD_RADIUS,
7
- CONTAINER_RADIUS
8
- } from "./chunk-FJ57274M.js";
16
+ COLLAPSE_BAR_HEIGHT,
17
+ CONTAINER_LABEL_FONT_SIZE,
18
+ CONTAINER_RADIUS,
19
+ EDGE_DASH,
20
+ EDGE_LABEL_KNOCKOUT_OPACITY,
21
+ EDGE_STROKE_WIDTH,
22
+ HEADER_HEIGHT,
23
+ LABEL_FONT_SIZE,
24
+ META_FONT_SIZE,
25
+ NODE_STROKE_WIDTH
26
+ } from "./chunk-IIEI7VK5.js";
9
27
  import {
10
28
  layoutInlineHeader
11
- } from "./chunk-MG3DE3VO.js";
29
+ } from "./chunk-FLMXJMMY.js";
30
+ import {
31
+ TITLE_FONT_SIZE,
32
+ TITLE_FONT_WEIGHT,
33
+ TITLE_Y
34
+ } from "./chunk-VSPNH7LC.js";
12
35
  import {
13
36
  renderIntegratedLegend
14
- } from "./chunk-QT5UMFPE.js";
37
+ } from "./chunk-67I3HFSF.js";
15
38
  import {
16
39
  getLegendExtent,
17
40
  getMaxLegendReservedHeight
18
- } from "./chunk-4SXHMFFP.js";
41
+ } from "./chunk-IZTU6WVR.js";
19
42
  import {
20
43
  FONT_FAMILY
21
- } from "./chunk-UTCPNJND.js";
44
+ } from "./chunk-ICLB27PZ.js";
22
45
  import {
23
46
  measureText,
24
47
  wrapTextToWidth
25
48
  } from "./chunk-MTGGOCND.js";
26
49
  import {
50
+ UNTAGGED_TAG_COLOR,
27
51
  resolveActiveTagGroup,
28
52
  resolveTagColor,
29
53
  tagAttrKey
30
- } from "./chunk-76LHNLGX.js";
54
+ } from "./chunk-R4YGH7DJ.js";
31
55
  import {
32
56
  contrastText,
33
57
  mix,
34
58
  shapeFill,
35
59
  themeBaseBg
36
- } from "./chunk-GLREDNBA.js";
60
+ } from "./chunk-YVLTNNME.js";
37
61
 
38
62
  // src/sketch/renderer.ts
39
63
  import * as d3 from "d3-selection";
@@ -232,29 +256,180 @@ function drawMarkdownBlock(container, text, opts) {
232
256
  };
233
257
  }
234
258
 
259
+ // src/sketch/colors.ts
260
+ var CONTAINER_FILL_OPACITY = 1;
261
+ var CONTAINER_STROKE_OPACITY = 0.35;
262
+ var CONTAINER_STROKE_WIDTH = 1;
263
+ function sketchContainerFill(palette, _isDark) {
264
+ return mix(palette.surface, palette.bg, 40);
265
+ }
266
+ function sketchNeutralFill(palette, isDark, fillMode) {
267
+ return fillMode === "outline" ? themeBaseBg(palette, isDark) : mix(palette.textMuted, palette.bg, 12);
268
+ }
269
+ function sketchColors(opts) {
270
+ const { palette, isDark, fillMode } = opts;
271
+ const neutralFill = sketchNeutralFill(palette, isDark, fillMode);
272
+ const tagGroups = [...opts.tagGroups];
273
+ const activeName = resolveActiveTagGroup(
274
+ tagGroups,
275
+ void 0,
276
+ opts.activeTagGroup ?? void 0
277
+ );
278
+ const activeKey = activeName === null ? null : tagAttrKey(activeName);
279
+ return (metadata, isContainer = false) => {
280
+ if (isContainer) {
281
+ return {
282
+ fill: sketchContainerFill(palette, isDark),
283
+ stroke: palette.textMuted,
284
+ text: palette.text
285
+ };
286
+ }
287
+ const tagged = activeKey !== null && metadata[activeKey] !== void 0;
288
+ const tagColor = tagged ? resolveTagColor(metadata, tagGroups, activeName, isContainer) : void 0;
289
+ if (!tagColor) {
290
+ return {
291
+ fill: neutralFill,
292
+ // 🔴 The same expression `boxes-and-lines` gives an untagged node
293
+ // (`renderer.ts`): a softened text colour, not `palette.textMuted`.
294
+ // Muted is a good deal darker, and at the shared stroke width it made
295
+ // an untagged sketch card the most heavily outlined object in the
296
+ // product (2026-08-27).
297
+ stroke: mix(palette.text, palette.bg, isDark ? 60 : 40),
298
+ text: palette.text
299
+ };
300
+ }
301
+ const fill = shapeFill(palette, tagColor, isDark, { mode: fillMode });
302
+ return {
303
+ fill,
304
+ stroke: tagColor,
305
+ // 🔴 CONTRAST-DERIVED, like every other chart type. This took the tag
306
+ // colour itself in the default and `outline` modes, which made sketch the
307
+ // only chart in the product whose labels are tinted — and on the 25% blend
308
+ // a card is filled with, that is pale-green text on a pale-green card.
309
+ // `boxes-and-lines` and `org` both derive it from the fill and land on one
310
+ // of two neutral tokens; sketch now does the same, in every mode rather
311
+ // than only `solid`.
312
+ text: contrastText(fill, palette.textOnFillLight, palette.textOnFillDark)
313
+ };
314
+ };
315
+ }
316
+
317
+ // src/sketch/visuals.ts
318
+ var SKETCH_VISUALS = {
319
+ /** Air round the whole diagram. */
320
+ diagramPadding: 20,
321
+ // 🔴 SHARED, not a second answer. Sketch printed its title at 18/y-32 while
322
+ // every other chart type used 20/y-30 from `utils/title-constants` — so two
323
+ // diagrams of the same content, side by side, did not even agree on how big
324
+ // their own name was (2026-08-27, #518).
325
+ titleY: TITLE_Y,
326
+ titleFontSize: TITLE_FONT_SIZE,
327
+ // 🔴 `bold` AS A NUMBER, and never `Number('bold')` — which is `NaN`, which is
328
+ // what this shipped. Every other consumer of `TITLE_FONT_WEIGHT` writes it
329
+ // straight into an SVG attribute, where the string is valid; this one is read
330
+ // as a VALUE by the desktop canvas, which puts it on an SVG attribute AND on
331
+ // an input's inline style, so it has to be a weight rather than a word.
332
+ //
333
+ // The result was `font-weight="NaN"` on every sketch title — silently
334
+ // rendered at the default weight, so a sketch's name was the one title in the
335
+ // product that was not bold, and nothing failed. Found 2026-08-29 by an app
336
+ // test asserting the drawn weight, which had been red on it.
337
+ //
338
+ // The comparison rather than a bare `700` so that changing the shared
339
+ // constant is a type error here instead of another silent coercion.
340
+ //
341
+ // ⚠️ Widened back to `number`. Without the assertion the literal `700` leaks
342
+ // into the published type surface — `check:api` caught it on the push — and a
343
+ // consumer would then be typed against this exact weight rather than against
344
+ // "a weight", which is the opposite of what a shared constant is for.
345
+ titleFontWeight: TITLE_FONT_WEIGHT === "bold" ? 700 : 400,
346
+ // 🔴 SHARED, not overridden. These read 2 and 2 against the conventions'
347
+ // 1.5, under a comment claiming "a bolder, less-washed look" — and the
348
+ // boldness was the complaint: a sketch beside a boxes-and-lines or an org
349
+ // chart of the same content did not look like the same product (2026-08-27).
350
+ // Sketch is not in the deviation list `visual-conventions.ts` keeps, either,
351
+ // so the override was drift rather than a decision anyone had recorded.
352
+ nodeStrokeWidth: NODE_STROKE_WIDTH,
353
+ edgeStrokeWidth: EDGE_STROKE_WIDTH,
354
+ // 🔴 A FILLED polygon, not an open V — and sized in STROKE-WIDTHS, like every
355
+ // other chart type. These read 18×12 in USER SPACE, which is 2.4× the ink
356
+ // boxes-and-lines puts on the same 1.5px connector, and it was the loudest
357
+ // single difference between the two pictures (#518). `markerUnits` defaults
358
+ // to `strokeWidth`, so 5×4 here renders 7.5×6 — the same triangle
359
+ // boxes-and-lines draws.
360
+ arrowheadW: ARROWHEAD_WIDTH,
361
+ arrowheadH: ARROWHEAD_HEIGHT,
362
+ dash: EDGE_DASH,
363
+ /** A card's name. Shared, and it fits DOWN to `nodeLabelFontSizeMin` before
364
+ * it wraps — it used to be allowed up to 30 on a card with no rows, which is
365
+ * more than twice what any other chart type prints. */
366
+ nodeLabelFontSize: LABEL_FONT_SIZE,
367
+ nodeLabelFontSizeMin: 11,
368
+ /** A card's description rows. */
369
+ cardMetaFontSize: META_FONT_SIZE,
370
+ /** A card's header band. */
371
+ cardHeaderHeight: HEADER_HEIGHT,
372
+ // 🔴 A container's own name: shared size, and `600` is what boxes-and-lines
373
+ // gives the same object (org gives it bold). It was 19 at weight 800 behind
374
+ // 0.55 opacity — bigger than a node's name, and the only container label in
375
+ // the product that was faded.
376
+ // 🔴 SHARED, and it stays shared even though boxes-and-lines prints 14 here.
377
+ // Going to 14 to match it was tried and reverted (#518): `sketch` keeps the
378
+ // rule that a container's name is never LOUDER than the names inside it, and
379
+ // one point is imperceptible next to the differences that actually made the
380
+ // two pictures look like different products (footprint, arrowheads, title).
381
+ // boxes-and-lines' 14 — and infra's — are the undocumented deviations here;
382
+ // the fix is those two coming to 13, not a third chart type leaving.
383
+ bandLabelFontSize: CONTAINER_LABEL_FONT_SIZE,
384
+ // 🔴 A WEIGHT, never the word — the same defect `titleFontWeight` carries
385
+ // the note for, one property along. `'bold'` is valid on the SVG attribute
386
+ // this renderer writes it to, and invalid everywhere a consumer needs a
387
+ // number: the app's live canvas puts a container band's weight on an
388
+ // `<input>`'s inline style and into a `fontWeight: number` slot, so it had
389
+ // to translate the word back to 700 itself and typecheck went red on main
390
+ // when it did not (#537, 2026-08-29). 700 is what `'bold'` already drew —
391
+ // this changes the type, not the picture. `as number` for the same reason
392
+ // `titleFontWeight` carries it: the literal would otherwise leak into the
393
+ // published type surface and `check:api` fails on it.
394
+ bandLabelFontWeight: 700,
395
+ bandLabelOpacity: 1,
396
+ /** 11 — what boxes-and-lines prints. It was 12, the only edge label in the
397
+ * product at that size. */
398
+ edgeLabelFontSize: 11,
399
+ /** The `palette.bg` halo painted under an edge label so the connector cannot
400
+ * cross its glyphs. Stroke, with `paint-order: stroke`. */
401
+ edgeLabelHaloWidth: 3,
402
+ cardRadius: CARD_RADIUS,
403
+ containerRadius: CONTAINER_RADIUS
404
+ };
405
+
235
406
  // src/sketch/renderer.ts
236
- var DIAGRAM_PADDING = 20;
237
- var TITLE_Y = 32;
238
- var TITLE_FONT_SIZE = 18;
239
- var NODE_STROKE_WIDTH = 2;
240
- var EDGE_STROKE_WIDTH = 2;
407
+ var DIAGRAM_PADDING = SKETCH_VISUALS.diagramPadding;
408
+ var TITLE_Y2 = SKETCH_VISUALS.titleY;
409
+ var TITLE_FONT_SIZE2 = SKETCH_VISUALS.titleFontSize;
410
+ var NODE_STROKE_WIDTH2 = SKETCH_VISUALS.nodeStrokeWidth;
411
+ var EDGE_STROKE_WIDTH2 = SKETCH_VISUALS.edgeStrokeWidth;
241
412
  var EDGE_HIT_WIDTH = 18;
242
- var ARROWHEAD_W = 18;
243
- var ARROWHEAD_H = 12;
244
- var DASH = "6 3";
245
- var BAND_LABEL_FONT_SIZE = 19;
246
- var BAND_LABEL_OPACITY = 0.55;
413
+ var EDGE_LABEL_H_PAD = 6;
414
+ var EDGE_LABEL_V_PAD = 3;
415
+ var CONTAINER_LABEL_BASELINE = 18;
416
+ var ARROWHEAD_W = SKETCH_VISUALS.arrowheadW;
417
+ var ARROWHEAD_H = SKETCH_VISUALS.arrowheadH;
418
+ var DASH = SKETCH_VISUALS.dash;
419
+ var BAND_LABEL_FONT_SIZE = SKETCH_VISUALS.bandLabelFontSize;
420
+ var BAND_LABEL_OPACITY = SKETCH_VISUALS.bandLabelOpacity;
421
+ var BAND_LABEL_WEIGHT = SKETCH_VISUALS.bandLabelFontWeight;
247
422
  var NOTE_FONT_SIZE = 11;
248
- var COLLAPSE_BAR_HEIGHT = 4;
249
- var EDGE_LABEL_FONT_SIZE = 12;
423
+ var COLLAPSE_BAR_HEIGHT2 = COLLAPSE_BAR_HEIGHT;
424
+ var EDGE_LABEL_FONT_SIZE = SKETCH_VISUALS.edgeLabelFontSize;
250
425
  var CURVE_HANDLE_MIN = 24;
251
426
  var CURVE_HANDLE_MAX = 90;
252
- function drawNoteBody(g, w, h, colors) {
427
+ function drawNoteBody(g, w, h, colors, strokeWidth) {
253
428
  const f = 14;
254
429
  g.append("path").attr(
255
430
  "d",
256
431
  `M0 2 a2 2 0 0 1 2 -2 h${w - f - 2} l${f} ${f} v${h - f - 2} a2 2 0 0 1 -2 2 h-${w - 4} a2 2 0 0 1 -2 -2 Z`
257
- ).attr("fill", colors.fill).attr("stroke", colors.stroke).attr("stroke-width", NODE_STROKE_WIDTH);
432
+ ).attr("fill", colors.fill).attr("stroke", colors.stroke).attr("stroke-width", strokeWidth);
258
433
  g.append("path").attr("d", `M${w - f} 0 v${f} h${f}`).attr("fill", "none").attr("stroke", colors.stroke).attr("stroke-width", 1.2);
259
434
  }
260
435
  function drawTypeBadge(g, kind, color, bx, by) {
@@ -279,12 +454,12 @@ function drawTypeBadge(g, kind, color, bx, by) {
279
454
  return;
280
455
  }
281
456
  }
282
- var CARD_HEADER_H = 34;
283
- var CARD_LABEL_MAX = 15;
284
- var CARD_LABEL_MIN = 11;
285
- var CARD_META_FONT = 12;
286
- var CARD_TITLE_MAX = 30;
287
- function fitWrapped(label, maxWidth, maxFont = CARD_LABEL_MAX, minFont = CARD_LABEL_MIN, maxLines = 2) {
457
+ var CARD_HEADER_H = SKETCH_VISUALS.cardHeaderHeight;
458
+ var CARD_LABEL_MAX = SKETCH_VISUALS.nodeLabelFontSize;
459
+ var CARD_LABEL_MIN = SKETCH_VISUALS.nodeLabelFontSizeMin;
460
+ var CARD_META_FONT = SKETCH_VISUALS.cardMetaFontSize;
461
+ var CARD_TITLE_MAX = SKETCH_VISUALS.nodeLabelFontSize;
462
+ function fitWrapped(label, maxWidth, maxFont, minFont, maxLines = 2) {
288
463
  const BOLD = { hardBreak: true, bold: true };
289
464
  for (let fs = maxFont; fs >= minFont; fs--) {
290
465
  const lines2 = wrapTextToWidth(label, fs, maxWidth, BOLD);
@@ -307,7 +482,34 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
307
482
  splitCardIds
308
483
  } = options;
309
484
  const hideDesc = hideDescriptions || parsed.options.noDescriptions;
310
- const neutralFill = parsed.options.fillMode === "outline" ? themeBaseBg(palette, isDark) : mix(palette.textMuted, palette.bg, 12);
485
+ const sctx = ScaleContext.identity();
486
+ const sTitleFontSize = sctx.text(TITLE_FONT_SIZE2);
487
+ const sEdgeLabelFontSize = sctx.text(EDGE_LABEL_FONT_SIZE);
488
+ const sBandLabelFontSize = sctx.text(BAND_LABEL_FONT_SIZE);
489
+ const sNoteFontSize = sctx.text(NOTE_FONT_SIZE);
490
+ const sCardLabelMax = sctx.text(CARD_LABEL_MAX);
491
+ const sCardLabelMin = sctx.text(CARD_LABEL_MIN);
492
+ const sCardMetaFont = sctx.text(CARD_META_FONT);
493
+ const sCardTitleMax = sctx.text(CARD_TITLE_MAX);
494
+ const sNodeStrokeWidth = sctx.structural(NODE_STROKE_WIDTH2);
495
+ const sEdgeStrokeWidth = sctx.structural(EDGE_STROKE_WIDTH2);
496
+ const sCardRadius = sctx.structural(CARD_RADIUS);
497
+ const sContainerRadius = sctx.structural(CONTAINER_RADIUS);
498
+ const sCardHeaderH = sctx.structural(CARD_HEADER_H);
499
+ const sCollapseBarHeight = sctx.structural(COLLAPSE_BAR_HEIGHT2);
500
+ const scaled = {
501
+ nodeStrokeWidth: sNodeStrokeWidth,
502
+ cardRadius: sCardRadius,
503
+ containerRadius: sContainerRadius,
504
+ cardHeaderH: sCardHeaderH,
505
+ collapseBarHeight: sCollapseBarHeight,
506
+ cardLabelMax: sCardLabelMax,
507
+ cardLabelMin: sCardLabelMin,
508
+ cardMetaFont: sCardMetaFont,
509
+ cardTitleMax: sCardTitleMax,
510
+ bandLabelFontSize: sBandLabelFontSize,
511
+ noteFontSize: sNoteFontSize
512
+ };
311
513
  const tagGroups = [...parsed.tagGroups];
312
514
  const activeName = resolveActiveTagGroup(
313
515
  tagGroups,
@@ -315,27 +517,13 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
315
517
  activeTagGroup
316
518
  );
317
519
  const activeKey = activeName === null ? null : tagAttrKey(activeName);
318
- const colorsFor = (metadata, isContainer = false) => {
319
- const tagged = activeKey !== null && metadata[activeKey] !== void 0;
320
- const tagColor = tagged ? resolveTagColor(metadata, tagGroups, activeName, isContainer) : void 0;
321
- if (!tagColor) {
322
- return {
323
- fill: neutralFill,
324
- stroke: palette.textMuted,
325
- text: palette.text
326
- };
327
- }
328
- const fill = shapeFill(palette, tagColor, isDark, {
329
- mode: parsed.options.fillMode
330
- });
331
- return {
332
- fill,
333
- stroke: tagColor,
334
- // Label text takes the shape's own (tag) color — but for solid fills the
335
- // tag color would vanish into the fill, so keep a contrast color there.
336
- text: parsed.options.fillMode === "solid" ? contrastText(fill, palette.textOnFillLight, palette.textOnFillDark) : tagColor
337
- };
338
- };
520
+ const colorsFor = sketchColors({
521
+ palette,
522
+ isDark,
523
+ tagGroups,
524
+ activeTagGroup,
525
+ fillMode: parsed.options.fillMode
526
+ });
339
527
  const showTitle = !!parsed.title;
340
528
  const titleOffset = showTitle ? 40 : 0;
341
529
  const legendGroups = parsed.options.noLegend ? [] : tagGroups;
@@ -356,8 +544,8 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
356
544
  }
357
545
  const label = layout.edges[i]?.label;
358
546
  if (label) {
359
- const hw = measureText(label, EDGE_LABEL_FONT_SIZE) / 2 + 6;
360
- const hh = EDGE_LABEL_FONT_SIZE / 2 + 4;
547
+ const hw = measureText(label, sEdgeLabelFontSize) / 2 + 6;
548
+ const hh = sEdgeLabelFontSize / 2 + 4;
361
549
  minX = Math.min(minX, g.mid.x - hw);
362
550
  maxX = Math.max(maxX, g.mid.x + hw);
363
551
  minY = Math.min(minY, g.mid.y - hh);
@@ -401,8 +589,8 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
401
589
  containerWidth: width,
402
590
  titleBandHeight: titleOffset,
403
591
  legendReserve: legendHeight,
404
- titleBaselineY: TITLE_Y,
405
- titleFontSize: TITLE_FONT_SIZE
592
+ titleBaselineY: TITLE_Y2,
593
+ titleFontSize: sTitleFontSize
406
594
  });
407
595
  const contentTop = titleOffset + (header.inline ? 0 : legendHeight) + DIAGRAM_PADDING + extraTop;
408
596
  const height = Math.max(
@@ -415,22 +603,26 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
415
603
  const edgeColorFor = (metadata) => {
416
604
  if (activeKey !== null && metadata[activeKey] !== void 0) {
417
605
  const c = resolveTagColor(metadata, tagGroups, activeName);
418
- if (c && c !== "#999999") return c;
606
+ if (c && c !== UNTAGGED_TAG_COLOR) return c;
419
607
  }
420
608
  return palette.textMuted;
421
609
  };
422
610
  const flowColor = (edge) => edgeColorFor(edge.metadata);
423
611
  const edgeColors = new Set(layout.edges.map((e) => flowColor(e)));
424
- for (const color of edgeColors) {
425
- const hex = color.replace("#", "");
426
- defs.append("marker").attr("id", `sk-arrow-${hex}`).attr("viewBox", `0 0 ${ARROWHEAD_W} ${ARROWHEAD_H}`).attr("refX", ARROWHEAD_W).attr("refY", ARROWHEAD_H / 2).attr("markerWidth", ARROWHEAD_W).attr("markerHeight", ARROWHEAD_H).attr("markerUnits", "userSpaceOnUse").attr("orient", "auto").append("polygon").attr("points", `0,0 ${ARROWHEAD_W},${ARROWHEAD_H / 2} 0,${ARROWHEAD_H}`).attr("fill", color);
427
- defs.append("marker").attr("id", `sk-arrow-rev-${hex}`).attr("viewBox", `0 0 ${ARROWHEAD_W} ${ARROWHEAD_H}`).attr("refX", 0).attr("refY", ARROWHEAD_H / 2).attr("markerWidth", ARROWHEAD_W).attr("markerHeight", ARROWHEAD_H).attr("markerUnits", "userSpaceOnUse").attr("orient", "auto").append("polygon").attr(
428
- "points",
429
- `${ARROWHEAD_W},0 0,${ARROWHEAD_H / 2} ${ARROWHEAD_W},${ARROWHEAD_H}`
430
- ).attr("fill", color);
612
+ if (edgeColors.size > 0) {
613
+ const markerOpts = {
614
+ idPrefix: "sk",
615
+ width: ARROWHEAD_W,
616
+ height: ARROWHEAD_H,
617
+ // Every marker is per-colour here; the base id is never referenced.
618
+ baseFill: [...edgeColors][0],
619
+ colors: edgeColors
620
+ };
621
+ appendArrowheadMarkers(defs, markerOpts);
622
+ appendReverseArrowheadMarkers(defs, markerOpts);
431
623
  }
432
624
  if (showTitle) {
433
- svg.append("text").attr("class", "chart-title").attr("x", header.titleX).attr("y", TITLE_Y).attr("text-anchor", header.titleAnchor).attr("font-size", TITLE_FONT_SIZE).attr("font-weight", 700).attr("fill", palette.text).text(parsed.title);
625
+ svg.append("text").attr("class", "chart-title").attr("x", header.titleX).attr("y", TITLE_Y2).attr("text-anchor", header.titleAnchor).attr("font-size", sTitleFontSize).attr("font-weight", "bold").attr("fill", palette.text).text(parsed.title);
434
626
  }
435
627
  if (legendGroups.length > 0) {
436
628
  const legendG = svg.append("g").attr(
@@ -456,7 +648,7 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
456
648
  const root = svg.append("g").attr("class", "sk-root").attr("transform", `translate(${contentX},${contentTop})`);
457
649
  const boxLayer = root.append("g").attr("class", "sk-boxes");
458
650
  for (const box of layout.boxes) {
459
- drawBoxFrame(boxLayer, box, colorsFor(box.metadata, true), palette);
651
+ drawBoxFrame(boxLayer, box, colorsFor(box.metadata, true), palette, scaled);
460
652
  }
461
653
  const edgeLayer = root.append("g").attr("class", "sk-edges");
462
654
  const labelLayerData = [];
@@ -468,7 +660,7 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
468
660
  const hex = color.replace("#", "");
469
661
  const { d, mid } = geo;
470
662
  const g = edgeLayer.append("g").attr("class", "sk-edge-group").attr("data-from", edge.sourceId).attr("data-to", edge.targetId).attr("data-line-number", edge.lineNumber);
471
- const path = g.append("path").attr("d", geo.dRender ?? d).attr("fill", "none").attr("stroke", color).attr("stroke-width", EDGE_STROKE_WIDTH);
663
+ const path = g.append("path").attr("d", geo.dRender ?? d).attr("fill", "none").attr("stroke", color).attr("stroke-width", sEdgeStrokeWidth);
472
664
  if (edge.dashed) path.attr("stroke-dasharray", DASH);
473
665
  if (edge.heads === "one" || edge.heads === "both") {
474
666
  path.attr("marker-end", `url(#sk-arrow-${hex})`);
@@ -491,12 +683,18 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
491
683
  }
492
684
  }
493
685
  {
494
- const labelW = (t) => t.length * EDGE_LABEL_FONT_SIZE * 0.56;
495
- const halfH = EDGE_LABEL_FONT_SIZE / 2 + 3;
686
+ const labelW = (t) => t.length * sEdgeLabelFontSize * 0.56;
687
+ const halfH = sEdgeLabelFontSize / 2 + 3;
496
688
  const GAP = 4;
497
689
  const shapeRects = [
498
690
  ...layout.nodes.map((n) => ({ x: n.x, y: n.y, w: n.w, h: n.h })),
499
- ...layout.boxes.map((b) => ({ x: b.x, y: b.y, w: b.w, h: b.h }))
691
+ ...layout.boxes.map((b) => ({
692
+ // The band the name is drawn in, not the frame below it.
693
+ x: b.x,
694
+ y: b.y,
695
+ w: b.w,
696
+ h: b.bandH
697
+ }))
500
698
  ];
501
699
  const cubicPt = (cp, t) => {
502
700
  const u = 1 - t;
@@ -518,42 +716,67 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
518
716
  return pts;
519
717
  });
520
718
  const covers = (cx, cy, hw, ox, oy, ohw, ohh) => Math.abs(cx - ox) < hw + ohw + GAP && Math.abs(cy - oy) < halfH + ohh + GAP;
719
+ const normalAt = (cp, t) => {
720
+ const e = 0.01;
721
+ const a = cubicPt(cp, Math.max(0, t - e));
722
+ const b = cubicPt(cp, Math.min(1, t + e));
723
+ const dx = b.x - a.x;
724
+ const dy = b.y - a.y;
725
+ const len = Math.hypot(dx, dy);
726
+ return len === 0 ? { x: 0, y: -1 } : { x: -dy / len, y: dx / len };
727
+ };
521
728
  const placed = [];
522
729
  const TS = [0.5, 0.4, 0.6, 0.32, 0.68, 0.25, 0.75, 0.18, 0.82];
730
+ const PERP_STEP = 8;
731
+ const PERP_MAX = 40;
732
+ const PERP_OFFSETS = [0];
733
+ for (let d = PERP_STEP; d <= PERP_MAX; d += PERP_STEP)
734
+ PERP_OFFSETS.push(d, -d);
523
735
  for (const l of labelLayerData) {
524
736
  const hw = labelW(l.text) / 2 + 3;
525
- let bestT = 0.5;
737
+ let best = cubicPt(l.cp, 0.5);
526
738
  let bestScore = Infinity;
527
- for (const t of TS) {
528
- const p2 = cubicPt(l.cp, t);
529
- let labelHits = 0;
530
- for (const q of placed)
531
- if (covers(p2.x, p2.y, hw, q.x, q.y, q.hw, halfH)) labelHits++;
532
- let shapeHits = 0;
533
- for (const r of shapeRects)
534
- if (covers(p2.x, p2.y, hw, r.x + r.w / 2, r.y + r.h / 2, r.w / 2, r.h / 2))
535
- shapeHits++;
536
- let lineHits = 0;
537
- for (let k = 0; k < allPolys.length; k++) {
538
- if (k === l.ei) continue;
539
- const poly = allPolys[k];
540
- if (poly?.some((pt) => covers(p2.x, p2.y, hw, pt.x, pt.y, 0, 0)))
541
- lineHits++;
542
- }
543
- if (labelHits === 0 && shapeHits === 0 && lineHits === 0) {
544
- bestT = t;
545
- break;
546
- }
547
- const score = labelHits * 10 + shapeHits * 6 + lineHits * 4 + Math.abs(t - 0.5);
548
- if (score < bestScore) {
549
- bestScore = score;
550
- bestT = t;
739
+ search: for (const perp of PERP_OFFSETS) {
740
+ const n = perp === 0 ? { x: 0, y: 0 } : normalAt(l.cp, 0.5);
741
+ for (const t of TS) {
742
+ const base = cubicPt(l.cp, t);
743
+ const p = { x: base.x + n.x * perp, y: base.y + n.y * perp };
744
+ let labelHits = 0;
745
+ for (const q of placed)
746
+ if (covers(p.x, p.y, hw, q.x, q.y, q.hw, halfH)) labelHits++;
747
+ let shapeHits = 0;
748
+ for (const r of shapeRects)
749
+ if (covers(
750
+ p.x,
751
+ p.y,
752
+ hw,
753
+ r.x + r.w / 2,
754
+ r.y + r.h / 2,
755
+ r.w / 2,
756
+ r.h / 2
757
+ ))
758
+ shapeHits++;
759
+ let lineHits = 0;
760
+ for (let k = 0; k < allPolys.length; k++) {
761
+ if (k === l.ei) continue;
762
+ const poly = allPolys[k];
763
+ if (poly?.some((pt) => covers(p.x, p.y, hw, pt.x, pt.y, 0, 0)))
764
+ lineHits++;
765
+ }
766
+ if (labelHits === 0 && shapeHits === 0 && lineHits === 0) {
767
+ best = p;
768
+ break search;
769
+ }
770
+ const score = labelHits * 10 + shapeHits * 6 + lineHits * 4 + Math.abs(t - 0.5) + Math.abs(perp) / PERP_MAX;
771
+ if (score < bestScore) {
772
+ bestScore = score;
773
+ best = p;
774
+ }
551
775
  }
552
776
  }
553
- const p = cubicPt(l.cp, bestT);
554
- l.x = p.x;
555
- l.y = p.y;
556
- placed.push({ x: p.x, y: p.y, hw });
777
+ l.x = best.x;
778
+ l.y = best.y;
779
+ placed.push({ x: best.x, y: best.y, hw });
557
780
  }
558
781
  }
559
782
  const nodeLayer = root.append("g").attr("class", "sk-nodes");
@@ -569,13 +792,17 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
569
792
  colorsFor(node.metadata),
570
793
  palette,
571
794
  isDark,
572
- !hideDesc && (splitCardIds?.includes(node.id) ?? false)
795
+ !hideDesc && (splitCardIds?.includes(node.id) ?? false),
796
+ scaled
573
797
  );
574
798
  }
575
799
  const labelLayer = root.append("g").attr("class", "sk-edge-labels");
576
800
  for (const l of labelLayerData) {
577
801
  const g = labelLayer.append("g").attr("class", "sk-edge-label").attr("data-from", l.from).attr("data-to", l.to);
578
- g.append("text").attr("x", l.x).attr("y", l.y).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", EDGE_LABEL_FONT_SIZE).attr("fill", l.color).attr("stroke", palette.bg).attr("stroke-width", 3).attr("stroke-linejoin", "round").attr("paint-order", "stroke").text(l.text);
802
+ const plateW = measureText(l.text, sEdgeLabelFontSize) + EDGE_LABEL_H_PAD * 2;
803
+ const plateH = sEdgeLabelFontSize * 1.3 + EDGE_LABEL_V_PAD * 2;
804
+ g.append("rect").attr("x", l.x - plateW / 2).attr("y", l.y - plateH / 2).attr("width", plateW).attr("height", plateH).attr("rx", 3).attr("fill", palette.bg).attr("opacity", EDGE_LABEL_KNOCKOUT_OPACITY);
805
+ g.append("text").attr("x", l.x).attr("y", l.y).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", sEdgeLabelFontSize).attr("fill", l.color).text(l.text);
579
806
  }
580
807
  if (options.onClickItem) {
581
808
  const handler = options.onClickItem;
@@ -585,18 +812,18 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
585
812
  });
586
813
  }
587
814
  }
588
- function drawBoxFrame(layer, box, colors, palette) {
815
+ function drawBoxFrame(layer, box, colors, palette, s) {
589
816
  const g = layer.append("g").attr("class", "sk-box").attr("data-node-id", box.id).attr("data-group-toggle", box.label).attr("data-line-number", box.lineNumber);
590
- g.append("rect").attr("x", box.x).attr("y", box.y).attr("width", box.w).attr("height", box.h).attr("rx", CONTAINER_RADIUS).attr("fill", colors.fill).attr("fill-opacity", 0.4).attr("stroke", colors.stroke).attr("stroke-opacity", 0.7).attr("stroke-width", NODE_STROKE_WIDTH);
591
- const fit = fitWrapped(box.label, box.w - 16, BAND_LABEL_FONT_SIZE, 12, 2);
817
+ g.append("rect").attr("x", box.x).attr("y", box.y).attr("width", box.w).attr("height", box.h).attr("rx", s.containerRadius).attr("fill", colors.fill).attr("fill-opacity", CONTAINER_FILL_OPACITY).attr("stroke", colors.stroke).attr("stroke-opacity", CONTAINER_STROKE_OPACITY).attr("stroke-width", CONTAINER_STROKE_WIDTH);
818
+ const fit = fitWrapped(box.label, box.w - 16, s.bandLabelFontSize, 12, 2);
592
819
  const lineH = fit.fontSize * 1.2;
593
- const bandMid = box.y + box.bandH / 2;
820
+ const bandMid = box.y + CONTAINER_LABEL_BASELINE;
594
821
  const startY = bandMid - (fit.lines.length - 1) * lineH / 2;
595
822
  for (let li = 0; li < fit.lines.length; li++) {
596
- g.append("text").attr("x", box.x + box.w / 2).attr("y", startY + li * lineH).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", fit.fontSize).attr("font-weight", 800).attr("fill", palette.text).attr("opacity", BAND_LABEL_OPACITY).text(fit.lines[li]);
823
+ g.append("text").attr("x", box.x + box.w / 2).attr("y", startY + li * lineH).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", fit.fontSize).attr("font-weight", BAND_LABEL_WEIGHT).attr("fill", palette.text).attr("opacity", BAND_LABEL_OPACITY).text(fit.lines[li]);
597
824
  }
598
825
  }
599
- function drawNode(layer, node, colors, palette, isDark, splitCard) {
826
+ function drawNode(layer, node, colors, palette, isDark, splitCard, s) {
600
827
  void isDark;
601
828
  const g = layer.append("g").attr("class", node.isCollapsedBox ? "sk-node sk-box-collapsed" : "sk-node").attr("transform", `translate(${node.x},${node.y})`).attr("data-node-id", node.id).attr("data-line-number", node.lineNumber);
602
829
  for (const [k, v] of Object.entries(node.metadata)) {
@@ -606,11 +833,11 @@ function drawNode(layer, node, colors, palette, isDark, splitCard) {
606
833
  g.attr("data-group-toggle", node.label);
607
834
  }
608
835
  if (node.shape === "note") {
609
- drawNoteBody(g, node.w, node.h, colors);
610
- const lines = wrapTextToWidth(node.label, NOTE_FONT_SIZE, node.w - 34);
611
- const lineHeight = NOTE_FONT_SIZE + 4;
836
+ drawNoteBody(g, node.w, node.h, colors, s.nodeStrokeWidth);
837
+ const lines = wrapTextToWidth(node.label, s.noteFontSize, node.w - 34);
838
+ const lineHeight = s.noteFontSize + 4;
612
839
  lines.slice(0, 5).forEach((line, i) => {
613
- g.append("text").attr("x", 10).attr("y", 20 + i * lineHeight).attr("font-size", NOTE_FONT_SIZE).attr("fill", colors.text).text(line);
840
+ g.append("text").attr("x", 10).attr("y", 20 + i * lineHeight).attr("font-size", s.noteFontSize).attr("fill", colors.text).text(line);
614
841
  });
615
842
  } else {
616
843
  const badge = node.shape !== "rectangle";
@@ -621,32 +848,32 @@ function drawNode(layer, node, colors, palette, isDark, splitCard) {
621
848
  const fitH = fitWrapped(
622
849
  node.label,
623
850
  node.w - 24 - labelInset,
624
- CARD_LABEL_MAX,
625
- CARD_LABEL_MIN,
851
+ s.cardLabelMax,
852
+ s.cardLabelMin,
626
853
  1
627
854
  );
628
855
  renderNodeCard(g, {
629
856
  width: node.w,
630
857
  height: node.h,
631
- rx: CARD_RADIUS,
858
+ rx: s.cardRadius,
632
859
  fill: colors.fill,
633
860
  stroke: colors.stroke,
634
- strokeWidth: NODE_STROKE_WIDTH,
861
+ strokeWidth: s.nodeStrokeWidth,
635
862
  label: fitH.lines[0] ?? node.label,
636
863
  labelColor: colors.text,
637
864
  labelFontSize: fitH.fontSize,
638
- headerHeight: CARD_HEADER_H
865
+ headerHeight: s.cardHeaderH
639
866
  });
640
- g.append("line").attr("x1", 0).attr("y1", CARD_HEADER_H).attr("x2", node.w).attr("y2", CARD_HEADER_H).attr("stroke", ruleColor).attr("stroke-opacity", 0.3).attr("stroke-width", 1);
867
+ g.append("line").attr("x1", 0).attr("y1", s.cardHeaderH).attr("x2", node.w).attr("y2", s.cardHeaderH).attr("stroke", ruleColor).attr("stroke-opacity", 0.3).attr("stroke-width", 1);
641
868
  if (node.description) {
642
869
  const inset = 12;
643
870
  const bodyGap = 8;
644
- const lh = CARD_META_FONT + 4;
645
- const avail = node.h - CARD_HEADER_H - bodyGap - 8;
646
- const body = g.append("g").attr("class", "sk-desc").attr("transform", `translate(${inset} ${CARD_HEADER_H + bodyGap})`);
871
+ const lh = s.cardMetaFont + 4;
872
+ const avail = node.h - s.cardHeaderH - bodyGap - 8;
873
+ const body = g.append("g").attr("class", "sk-desc").attr("transform", `translate(${inset} ${s.cardHeaderH + bodyGap})`);
647
874
  const block = drawMarkdownBlock(body, node.description, {
648
875
  width: node.w - inset * 2,
649
- fontSize: CARD_META_FONT,
876
+ fontSize: s.cardMetaFont,
650
877
  lineHeight: lh,
651
878
  color: colors.text,
652
879
  // match the header label (contrast-aware in solid)
@@ -659,24 +886,24 @@ function drawNode(layer, node, colors, palette, isDark, splitCard) {
659
886
  }
660
887
  }
661
888
  if (badge) {
662
- drawTypeBadge(g, node.shape, colors.text, 10, (CARD_HEADER_H - 16) / 2);
889
+ drawTypeBadge(g, node.shape, colors.text, 10, (s.cardHeaderH - 16) / 2);
663
890
  }
664
891
  return;
665
892
  }
666
893
  const fit = fitWrapped(
667
894
  node.label,
668
895
  node.w - 24 - labelInset,
669
- CARD_TITLE_MAX,
670
- CARD_LABEL_MIN,
896
+ s.cardTitleMax,
897
+ s.cardLabelMin,
671
898
  3
672
899
  );
673
900
  renderNodeCard(g, {
674
901
  width: node.w,
675
902
  height: node.h,
676
- rx: CARD_RADIUS,
903
+ rx: s.cardRadius,
677
904
  fill: colors.fill,
678
905
  stroke: colors.stroke,
679
- strokeWidth: NODE_STROKE_WIDTH,
906
+ strokeWidth: s.nodeStrokeWidth,
680
907
  label: fit.lines.join(" "),
681
908
  labelLines: fit.lines,
682
909
  labelColor: colors.text,
@@ -684,16 +911,16 @@ function drawNode(layer, node, colors, palette, isDark, splitCard) {
684
911
  headerHeight: node.h
685
912
  });
686
913
  if (badge) {
687
- drawTypeBadge(g, node.shape, colors.text, 10, (CARD_HEADER_H - 16) / 2);
914
+ drawTypeBadge(g, node.shape, colors.text, 10, (s.cardHeaderH - 16) / 2);
688
915
  }
689
916
  }
690
917
  if (node.isCollapsedBox) {
691
918
  renderCollapseBar(g, {
692
919
  width: node.w,
693
920
  height: node.h,
694
- barHeight: COLLAPSE_BAR_HEIGHT,
921
+ barHeight: s.collapseBarHeight,
695
922
  inset: 0,
696
- rx: CARD_RADIUS,
923
+ rx: s.cardRadius,
697
924
  fill: colors.stroke === palette.textMuted ? palette.textMuted : colors.stroke,
698
925
  clipId: `sk-clip-${node.id.replace(/[^a-zA-Z0-9_-]/g, "")}-${node.lineNumber}`,
699
926
  className: "sk-collapse-bar"
@@ -1123,8 +1350,15 @@ function renderSketchForExport(container, parsed, layout, palette, isDark, optio
1123
1350
  }
1124
1351
 
1125
1352
  export {
1353
+ CONTAINER_FILL_OPACITY,
1354
+ CONTAINER_STROKE_OPACITY,
1355
+ CONTAINER_STROKE_WIDTH,
1356
+ sketchContainerFill,
1357
+ sketchNeutralFill,
1358
+ sketchColors,
1359
+ SKETCH_VISUALS,
1126
1360
  renderSketch,
1127
1361
  sketchEdgeGeometry,
1128
1362
  renderSketchForExport
1129
1363
  };
1130
- //# sourceMappingURL=chunk-U7AO6FRL.js.map
1364
+ //# sourceMappingURL=chunk-ENDB5YSV.js.map