@diagrammo/dgmo 0.46.0 → 0.48.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 (534) hide show
  1. package/dist/advanced.d.ts +3 -855
  2. package/dist/advanced.js +541 -70107
  3. package/dist/analyzer-UYKBXAKR.js +15 -0
  4. package/dist/auto.js +1 -1
  5. package/dist/auto.mjs +1 -1
  6. package/dist/block.js +83 -69417
  7. package/dist/calculator-LDYQCDDY.js +11 -0
  8. package/dist/charts-d3-QOZHKTCT.js +25 -0
  9. package/dist/chunk-2DXMZRWJ.js +800 -0
  10. package/dist/chunk-2LACINWN.js +786 -0
  11. package/dist/chunk-33LCUH4H.js +893 -0
  12. package/dist/chunk-3CIOJ5YJ.js +35 -0
  13. package/dist/chunk-3HDBAXF5.js +86 -0
  14. package/dist/chunk-3JLKYGBQ.js +290 -0
  15. package/dist/chunk-3MQQNXPD.js +415 -0
  16. package/dist/chunk-3R5POCTZ.js +967 -0
  17. package/dist/chunk-3SMGIJDD.js +112 -0
  18. package/dist/chunk-44CM72SQ.js +409 -0
  19. package/dist/chunk-4GRI7MEB.js +1604 -0
  20. package/dist/chunk-4OHACBGX.js +606 -0
  21. package/dist/chunk-5DH3KYFH.js +21 -0
  22. package/dist/chunk-5MLYVTYM.js +76 -0
  23. package/dist/chunk-5QXL4NYS.js +553 -0
  24. package/dist/chunk-5WRI5ZAA.js +31 -0
  25. package/dist/chunk-6EK55ART.js +117 -0
  26. package/dist/chunk-6FZYCKXB.js +2065 -0
  27. package/dist/chunk-6HO5ZTXK.js +277 -0
  28. package/dist/chunk-6KFWC4CO.js +7 -0
  29. package/dist/chunk-6MTWIQVO.js +121 -0
  30. package/dist/chunk-6NYWYNBI.js +329 -0
  31. package/dist/chunk-6SM5NJQH.js +620 -0
  32. package/dist/chunk-725LDASD.js +422 -0
  33. package/dist/chunk-76OWZ3BA.js +130 -0
  34. package/{src/block/parser.ts → dist/chunk-7JEGTRLD.js} +100 -189
  35. package/dist/chunk-A44USUV7.js +923 -0
  36. package/dist/chunk-A4GOY3PE.js +25 -0
  37. package/dist/chunk-A4VFQH5G.js +251 -0
  38. package/dist/chunk-AELOBFW5.js +375 -0
  39. package/dist/chunk-AN2MOO5T.js +522 -0
  40. package/dist/chunk-BMR4CIEO.js +41 -0
  41. package/dist/chunk-BS7SV7C3.js +51 -0
  42. package/dist/chunk-BUPDIHML.js +613 -0
  43. package/dist/chunk-BUVJFRPY.js +887 -0
  44. package/dist/chunk-C3Z4DX3V.js +112 -0
  45. package/dist/chunk-CI2G3OEB.js +1818 -0
  46. package/dist/chunk-CKNVO24D.js +54 -0
  47. package/dist/chunk-CUVHQHZ7.js +391 -0
  48. package/dist/chunk-CXK4DZH3.js +114 -0
  49. package/dist/{editor.cjs → chunk-DKEPS5LH.js} +14 -225
  50. package/dist/chunk-DU7W62N5.js +487 -0
  51. package/dist/chunk-DZAQBW35.js +751 -0
  52. package/dist/chunk-EB6FPQUP.js +316 -0
  53. package/dist/chunk-EMS2SK26.js +376 -0
  54. package/dist/chunk-ERLBPDGU.js +510 -0
  55. package/dist/chunk-EVCVDTXE.js +732 -0
  56. package/dist/chunk-FCIIHT24.js +384 -0
  57. package/dist/chunk-FFUN5D66.js +97 -0
  58. package/dist/chunk-FITOLXSX.js +714 -0
  59. package/dist/chunk-FMDSF3OV.js +68 -0
  60. package/dist/chunk-FNB3PNGF.js +410 -0
  61. package/dist/chunk-G2H74XJZ.js +2104 -0
  62. package/dist/chunk-GMR5MFHJ.js +339 -0
  63. package/dist/chunk-H6PI3KJT.js +305 -0
  64. package/dist/chunk-I46X5VUA.js +59 -0
  65. package/dist/chunk-I5IGB56C.js +255 -0
  66. package/dist/chunk-IH6ZMVQ5.js +3950 -0
  67. package/dist/chunk-IJZFN3HM.js +463 -0
  68. package/dist/chunk-IPWPWM6R.js +3079 -0
  69. package/dist/chunk-IYULMRBE.js +23 -0
  70. package/dist/chunk-IZMRON6C.js +167 -0
  71. package/dist/chunk-J5FIXQRT.js +813 -0
  72. package/dist/chunk-JED6ZDEE.js +73 -0
  73. package/dist/chunk-JEUJOX5X.js +136 -0
  74. package/dist/chunk-JM4LEPY3.js +436 -0
  75. package/dist/chunk-L3UHP6TD.js +101 -0
  76. package/dist/chunk-L66GEFB6.js +524 -0
  77. package/dist/chunk-LIOHW36Z.js +469 -0
  78. package/dist/chunk-LP7EC4MI.js +16 -0
  79. package/dist/chunk-MITI6NOL.js +548 -0
  80. package/dist/chunk-MO5YHHMQ.js +168 -0
  81. package/dist/chunk-MZSBFAPJ.js +885 -0
  82. package/dist/chunk-NNAAJVBU.js +9 -0
  83. package/dist/chunk-NOTA6TEI.js +47 -0
  84. package/dist/chunk-NURGB5Z4.js +335 -0
  85. package/dist/chunk-NX4EQS3U.js +1062 -0
  86. package/dist/chunk-NXMESY4J.js +1 -0
  87. package/dist/chunk-OJR3MQYV.js +1458 -0
  88. package/dist/chunk-OURHMODR.js +454 -0
  89. package/dist/chunk-P235SVAH.js +1057 -0
  90. package/dist/chunk-P4RH4OSP.js +1038 -0
  91. package/dist/chunk-P6T66CCZ.js +226 -0
  92. package/dist/chunk-PBAHEPLQ.js +223 -0
  93. package/dist/chunk-PBHE5UG6.js +1530 -0
  94. package/dist/chunk-PDKUANDZ.js +35 -0
  95. package/dist/chunk-PWIHZ6NJ.js +296 -0
  96. package/{src/c4/layout.ts → dist/chunk-QEBUY5NY.js} +384 -1140
  97. package/dist/chunk-QLCCJEJI.js +253 -0
  98. package/dist/chunk-QOOUC2J5.js +52 -0
  99. package/dist/chunk-QYTPPDAO.js +402 -0
  100. package/dist/chunk-R3XI2VC7.js +801 -0
  101. package/dist/chunk-RCERWOJR.js +154 -0
  102. package/dist/chunk-RJE5JTVK.js +362 -0
  103. package/dist/chunk-RTLBSQ3G.js +1155 -0
  104. package/dist/chunk-RUNNI6VE.js +448 -0
  105. package/dist/chunk-RVMRZAPB.js +354 -0
  106. package/dist/chunk-RYEGFMUO.js +955 -0
  107. package/dist/chunk-RZCF2VVM.js +528 -0
  108. package/dist/chunk-SML67VPV.js +1025 -0
  109. package/dist/chunk-SQ7IY53Q.js +44 -0
  110. package/dist/chunk-SQAG3UXH.js +161 -0
  111. package/dist/chunk-SRTU6HMQ.js +1851 -0
  112. package/dist/chunk-T2OE3YQB.js +550 -0
  113. package/dist/chunk-T3UBLACL.js +299 -0
  114. package/dist/chunk-TLVIHFRO.js +296 -0
  115. package/dist/chunk-TYS6CSS5.js +52 -0
  116. package/dist/chunk-U6EQI3U6.js +130 -0
  117. package/dist/chunk-UJ4FJLBF.js +86 -0
  118. package/dist/chunk-ULOEATBZ.js +347 -0
  119. package/dist/chunk-UNCCZ3NU.js +127 -0
  120. package/dist/chunk-USZW2HHU.js +197 -0
  121. package/dist/chunk-UWN33VNX.js +1610 -0
  122. package/dist/chunk-UZ7EZW3B.js +40 -0
  123. package/dist/chunk-VOKGH627.js +37 -0
  124. package/dist/chunk-WBRZJOEC.js +204 -0
  125. package/dist/chunk-WCSOJFU3.js +380 -0
  126. package/dist/chunk-WCT3NYCV.js +160 -0
  127. package/dist/chunk-WVAJFAIA.js +529 -0
  128. package/dist/chunk-X5LCYCL5.js +394 -0
  129. package/dist/chunk-XAKEUMEJ.js +1256 -0
  130. package/dist/chunk-Y2ZE3MSG.js +590 -0
  131. package/dist/chunk-Y3J7VR52.js +646 -0
  132. package/dist/chunk-Y5QGVTVC.js +33 -0
  133. package/dist/chunk-YAA6IID3.js +548 -0
  134. package/dist/chunk-YGJTDXVR.js +692 -0
  135. package/{src/utils/time-ticks.ts → dist/chunk-YRYKTYMQ.js} +45 -112
  136. package/dist/chunk-YYVTBZZC.js +61 -0
  137. package/dist/chunk-Z5CGSFJB.js +647 -0
  138. package/{src/gantt/calculator.ts → dist/chunk-Z72XRXD4.js} +236 -428
  139. package/dist/chunk-ZGR7ULFJ.js +978 -0
  140. package/dist/chunk-ZJEL4H2R.js +851 -0
  141. package/dist/chunk-ZO27FGJS.js +554 -0
  142. package/dist/collapse-CLPJD2RL.js +11 -0
  143. package/dist/collapse-SLINJQW6.js +9 -0
  144. package/dist/collapse-ZWUFFCK2.js +9 -0
  145. package/dist/compute-G55RG53N.js +8 -0
  146. package/dist/dgmo-router-DZCIDUO5.js +73 -0
  147. package/dist/dimensions-J3FHIMJ6.js +22 -0
  148. package/dist/element.js +1 -1
  149. package/dist/element.mjs +1 -1
  150. package/dist/flowchart-parser-ZNSKIBVR.js +21 -0
  151. package/dist/flowchart-renderer-ZAEOL4DX.js +35 -0
  152. package/dist/index.d.ts +3 -469
  153. package/dist/index.js +137 -69685
  154. package/dist/layout-46N4JJYK.js +17 -0
  155. package/dist/layout-5RA6QWR6.js +26 -0
  156. package/dist/layout-5T6RH5M6.js +14 -0
  157. package/dist/layout-7QXCNOVS.js +13 -0
  158. package/dist/layout-EE6GE46Y.js +17 -0
  159. package/dist/layout-G23F7LDH.js +9 -0
  160. package/dist/layout-HRBZPFCN.js +23 -0
  161. package/dist/layout-HWDSRX5E.js +20 -0
  162. package/dist/layout-HYZPWAK5.js +18 -0
  163. package/dist/layout-N76NR4ZO.js +19 -0
  164. package/dist/layout-OB3RI63S.js +14 -0
  165. package/dist/layout-S2QBYSK2.js +15 -0
  166. package/dist/layout-UM5F4DJB.js +15 -0
  167. package/dist/layout-search-OYV77HHS.js +1655 -0
  168. package/dist/load-data-EHDDZ5ZS.js +8 -0
  169. package/dist/palettes-PRJ2RI6D.js +56 -0
  170. package/dist/parser-2MFP2H2E.js +11 -0
  171. package/dist/parser-3STE62GB.js +21 -0
  172. package/dist/parser-4FL2CMDG.js +18 -0
  173. package/dist/parser-4OGOBJJ4.js +13 -0
  174. package/dist/parser-6BTRLKRZ.js +15 -0
  175. package/dist/parser-AQETEVRW.js +21 -0
  176. package/dist/parser-CFZD5IBL.js +12 -0
  177. package/dist/parser-FUSKFGZN.js +16 -0
  178. package/dist/parser-I6KXEYFK.js +13 -0
  179. package/dist/parser-IXSZZQHY.js +18 -0
  180. package/dist/parser-JAL2HD4I.js +13 -0
  181. package/dist/parser-KNSQSKQO.js +20 -0
  182. package/dist/parser-N5O4IHUN.js +13 -0
  183. package/dist/parser-NGU3ETO6.js +16 -0
  184. package/dist/parser-NRAI6O25.js +19 -0
  185. package/dist/parser-O5J4VBII.js +11 -0
  186. package/dist/parser-OV7NOBW6.js +21 -0
  187. package/dist/parser-PQ3POX45.js +23 -0
  188. package/dist/parser-TFZFBVWN.js +11 -0
  189. package/dist/parser-TRTHDFPP.js +18 -0
  190. package/dist/parser-VQP2UJ6W.js +11 -0
  191. package/dist/parser-XDVELHRK.js +13 -0
  192. package/dist/parser-XKRP7QKP.js +11 -0
  193. package/dist/parser-Y6WTBU76.js +14 -0
  194. package/dist/parser-ZSDPZYQP.js +12 -0
  195. package/dist/renderer-2XQQQ6QR.js +28 -0
  196. package/dist/renderer-5NDVNDAZ.js +26 -0
  197. package/dist/renderer-6EEZHMH4.js +26 -0
  198. package/dist/renderer-6W5462RB.js +43 -0
  199. package/dist/renderer-7MVLWWQD.js +22 -0
  200. package/dist/renderer-AWWAF6XD.js +33 -0
  201. package/dist/renderer-BYCNMBF7.js +34 -0
  202. package/dist/renderer-CLJHQPBJ.js +29 -0
  203. package/dist/renderer-GHPZMFU2.js +15 -0
  204. package/dist/renderer-JGBKUCZD.js +16 -0
  205. package/dist/renderer-KQB7UGDS.js +19 -0
  206. package/dist/renderer-PGX2TKVS.js +24 -0
  207. package/dist/renderer-QIWVHWZO.js +15 -0
  208. package/dist/renderer-RPOA5YPZ.js +35 -0
  209. package/dist/renderer-SMIBCRVB.js +24 -0
  210. package/dist/renderer-T7YKC5VP.js +28 -0
  211. package/dist/renderer-TOCOVLHS.js +37 -0
  212. package/dist/renderer-UWA5XS74.js +39 -0
  213. package/dist/renderer-VACVQYML.js +25 -0
  214. package/dist/renderer-W4M6QLIJ.js +37 -0
  215. package/dist/renderer-WZRREQ2P.js +23 -0
  216. package/dist/renderer-YY2OSF6E.js +27 -0
  217. package/dist/renderer-Z7I3W2PP.js +24 -0
  218. package/dist/renderer-ZGNTUWC4.js +22 -0
  219. package/dist/renderer-ZTR3DER3.js +19 -0
  220. package/dist/renderer-radial-C32GPJQ7.js +21 -0
  221. package/dist/resolver-NOAA7ID7.js +13 -0
  222. package/dist/state-collapse-HCGD6IVJ.js +8 -0
  223. package/dist/state-parser-Z2V23ATR.js +18 -0
  224. package/dist/state-renderer-RFYHSP4K.js +34 -0
  225. package/dist/themes-1-CuKpeH.d.ts +908 -0
  226. package/package.json +19 -70
  227. package/dist/advanced.cjs +0 -71648
  228. package/dist/advanced.d.cts +0 -6571
  229. package/dist/auto.cjs +0 -70648
  230. package/dist/auto.d.cts +0 -54
  231. package/dist/block.cjs +0 -70208
  232. package/dist/block.d.cts +0 -115
  233. package/dist/editor.d.cts +0 -26
  234. package/dist/element.cjs +0 -70530
  235. package/dist/element.d.cts +0 -62
  236. package/dist/highlight.cjs +0 -852
  237. package/dist/highlight.d.cts +0 -49
  238. package/dist/index.cjs +0 -70491
  239. package/dist/index.d.cts +0 -626
  240. package/dist/pert.cjs +0 -325
  241. package/dist/pert.d.cts +0 -559
  242. package/src/advanced.ts +0 -873
  243. package/src/arc/parser.ts +0 -15
  244. package/src/arc/renderer.ts +0 -633
  245. package/src/auto/index.ts +0 -621
  246. package/src/auto/shared.ts +0 -370
  247. package/src/auto/styles.ts +0 -73
  248. package/src/block/layout.ts +0 -198
  249. package/src/block/renderer.ts +0 -484
  250. package/src/block/types.ts +0 -67
  251. package/src/boxes-and-lines/collapse.ts +0 -96
  252. package/src/boxes-and-lines/focus.ts +0 -257
  253. package/src/boxes-and-lines/label-placement.ts +0 -339
  254. package/src/boxes-and-lines/layout-grouped.ts +0 -912
  255. package/src/boxes-and-lines/layout-layered.ts +0 -722
  256. package/src/boxes-and-lines/layout-search.ts +0 -1678
  257. package/src/boxes-and-lines/layout.ts +0 -398
  258. package/src/boxes-and-lines/parser.ts +0 -1181
  259. package/src/boxes-and-lines/renderer.ts +0 -1465
  260. package/src/boxes-and-lines/types.ts +0 -66
  261. package/src/c4/parser.ts +0 -1158
  262. package/src/c4/renderer.ts +0 -2008
  263. package/src/c4/types.ts +0 -89
  264. package/src/chart-type-registry.ts +0 -529
  265. package/src/chart-types.ts +0 -225
  266. package/src/chart.ts +0 -685
  267. package/src/charts-d3/bar.ts +0 -338
  268. package/src/charts-d3/chord.ts +0 -140
  269. package/src/charts-d3/function.ts +0 -147
  270. package/src/charts-d3/funnel.ts +0 -104
  271. package/src/charts-d3/heatmap.ts +0 -145
  272. package/src/charts-d3/index.ts +0 -337
  273. package/src/charts-d3/interactions.ts +0 -477
  274. package/src/charts-d3/line.ts +0 -344
  275. package/src/charts-d3/mount.ts +0 -151
  276. package/src/charts-d3/pie.ts +0 -117
  277. package/src/charts-d3/polar.ts +0 -89
  278. package/src/charts-d3/radar.ts +0 -0
  279. package/src/charts-d3/sankey.ts +0 -0
  280. package/src/charts-d3/scatter.ts +0 -185
  281. package/src/charts-d3/shared.ts +0 -208
  282. package/src/class/layout.ts +0 -326
  283. package/src/class/parser.ts +0 -635
  284. package/src/class/renderer.ts +0 -793
  285. package/src/class/types.ts +0 -58
  286. package/src/cli-banner.ts +0 -106
  287. package/src/cli.ts +0 -1080
  288. package/src/colors-diagnostics.ts +0 -35
  289. package/src/colors.ts +0 -379
  290. package/src/completion-types.ts +0 -27
  291. package/src/completion.ts +0 -2668
  292. package/src/cycle/layout.ts +0 -1026
  293. package/src/cycle/parser.ts +0 -387
  294. package/src/cycle/renderer.ts +0 -653
  295. package/src/cycle/types.ts +0 -101
  296. package/src/d3.ts +0 -1434
  297. package/src/data-chart-parser.ts +0 -1007
  298. package/src/dgmo-router.ts +0 -296
  299. package/src/diagnostics-registry.ts +0 -108
  300. package/src/diagnostics.ts +0 -0
  301. package/src/dimensions.ts +0 -20
  302. package/src/directives-registry.ts +0 -396
  303. package/src/editor/dgmo.grammar +0 -76
  304. package/src/editor/dgmo.grammar.d.ts +0 -2
  305. package/src/editor/dgmo.grammar.js +0 -18
  306. package/src/editor/dgmo.grammar.terms.d.ts +0 -5
  307. package/src/editor/dgmo.grammar.terms.js +0 -35
  308. package/src/editor/highlight-api.ts +0 -596
  309. package/src/editor/highlight.ts +0 -36
  310. package/src/editor/index.ts +0 -27
  311. package/src/editor/keywords.ts +0 -128
  312. package/src/editor/tokens.ts +0 -30
  313. package/src/element/index.ts +0 -432
  314. package/src/embed/css.ts +0 -312
  315. package/src/embed/escape.ts +0 -15
  316. package/src/embed/index.ts +0 -280
  317. package/src/er/classify.ts +0 -228
  318. package/src/er/layout.ts +0 -530
  319. package/src/er/parser.ts +0 -750
  320. package/src/er/renderer.ts +0 -725
  321. package/src/er/types.ts +0 -52
  322. package/src/error-card.ts +0 -269
  323. package/src/event-line/diagnostics.ts +0 -117
  324. package/src/event-line/parser.ts +0 -643
  325. package/src/event-line/renderer.ts +0 -1742
  326. package/src/event-line/types.ts +0 -74
  327. package/src/fonts.ts +0 -3
  328. package/src/gantt/parser.ts +0 -1641
  329. package/src/gantt/renderer.ts +0 -3787
  330. package/src/gantt/resolver.ts +0 -172
  331. package/src/gantt/types.ts +0 -206
  332. package/src/graph/diagnostics.ts +0 -64
  333. package/src/graph/edge-spline.ts +0 -29
  334. package/src/graph/flowchart-parser.ts +0 -759
  335. package/src/graph/flowchart-renderer.ts +0 -817
  336. package/src/graph/layout.ts +0 -472
  337. package/src/graph/notes.ts +0 -21
  338. package/src/graph/state-collapse.ts +0 -78
  339. package/src/graph/state-parser.ts +0 -574
  340. package/src/graph/state-renderer.ts +0 -653
  341. package/src/graph/types.ts +0 -65
  342. package/src/index.ts +0 -261
  343. package/src/infra/compute.ts +0 -1385
  344. package/src/infra/layout.ts +0 -888
  345. package/src/infra/parser.ts +0 -1234
  346. package/src/infra/renderer.ts +0 -2534
  347. package/src/infra/roles.ts +0 -75
  348. package/src/infra/types.ts +0 -216
  349. package/src/infra/validation.ts +0 -201
  350. package/src/journey-map/layout.ts +0 -490
  351. package/src/journey-map/parser.ts +0 -557
  352. package/src/journey-map/renderer.ts +0 -1580
  353. package/src/journey-map/types.ts +0 -47
  354. package/src/kanban/mutations.ts +0 -175
  355. package/src/kanban/parser.ts +0 -509
  356. package/src/kanban/renderer.ts +0 -1449
  357. package/src/kanban/types.ts +0 -39
  358. package/src/label-layout.ts +0 -368
  359. package/src/map/colorize.ts +0 -54
  360. package/src/map/completion.ts +0 -316
  361. package/src/map/context-labels.ts +0 -609
  362. package/src/map/data/PROVENANCE.json +0 -1
  363. package/src/map/data/README.md +0 -40
  364. package/src/map/data/airport-collisions.json +0 -1
  365. package/src/map/data/airports.json +0 -1
  366. package/src/map/data/gazetteer.json +0 -1
  367. package/src/map/data/lakes.json +0 -1
  368. package/src/map/data/mountain-ranges.json +0 -1
  369. package/src/map/data/na-lakes.json +0 -1
  370. package/src/map/data/na-land.json +0 -1
  371. package/src/map/data/region-names.json +0 -1
  372. package/src/map/data/rivers.json +0 -1
  373. package/src/map/data/types.ts +0 -121
  374. package/src/map/data/us-states.json +0 -1
  375. package/src/map/data/water-bodies.json +0 -1
  376. package/src/map/data/world-coarse.json +0 -1
  377. package/src/map/data/world-detail.json +0 -1
  378. package/src/map/diagnostics.ts +0 -134
  379. package/src/map/dimensions.ts +0 -150
  380. package/src/map/geo-query.ts +0 -295
  381. package/src/map/geo.ts +0 -438
  382. package/src/map/invert.ts +0 -111
  383. package/src/map/layout.ts +0 -5069
  384. package/src/map/legend-band.ts +0 -127
  385. package/src/map/load-data.ts +0 -186
  386. package/src/map/parser.ts +0 -783
  387. package/src/map/renderer.ts +0 -1445
  388. package/src/map/resolved-types.ts +0 -160
  389. package/src/map/resolver.ts +0 -1146
  390. package/src/map/types.ts +0 -194
  391. package/src/mindmap/collapse.ts +0 -67
  392. package/src/mindmap/layout.ts +0 -649
  393. package/src/mindmap/parser.ts +0 -430
  394. package/src/mindmap/renderer.ts +0 -637
  395. package/src/mindmap/text-wrap.ts +0 -218
  396. package/src/mindmap/types.ts +0 -56
  397. package/src/org/collapse.ts +0 -151
  398. package/src/org/layout.ts +0 -1262
  399. package/src/org/parser.ts +0 -519
  400. package/src/org/renderer.ts +0 -866
  401. package/src/org/resolver.ts +0 -636
  402. package/src/palettes/atlas.ts +0 -77
  403. package/src/palettes/blueprint.ts +0 -73
  404. package/src/palettes/catppuccin.ts +0 -84
  405. package/src/palettes/color-utils.ts +0 -443
  406. package/src/palettes/index.ts +0 -67
  407. package/src/palettes/nord.ts +0 -67
  408. package/src/palettes/registry.ts +0 -114
  409. package/src/palettes/slate.ts +0 -73
  410. package/src/palettes/tidewater.ts +0 -73
  411. package/src/palettes/tokyo-night.ts +0 -86
  412. package/src/palettes/types.ts +0 -88
  413. package/src/pert/analyzer.ts +0 -1183
  414. package/src/pert/diagnostics.ts +0 -110
  415. package/src/pert/index.ts +0 -43
  416. package/src/pert/internal.ts +0 -252
  417. package/src/pert/layout.ts +0 -971
  418. package/src/pert/monte-carlo.ts +0 -446
  419. package/src/pert/parser.ts +0 -1606
  420. package/src/pert/renderer.ts +0 -4009
  421. package/src/pert/share-normalize.ts +0 -62
  422. package/src/pert/types.ts +0 -604
  423. package/src/pyramid/parser.ts +0 -185
  424. package/src/pyramid/renderer.ts +0 -768
  425. package/src/pyramid/types.ts +0 -28
  426. package/src/quadrant/parser.ts +0 -18
  427. package/src/quadrant/renderer.ts +0 -638
  428. package/src/raci/diagnostics.ts +0 -213
  429. package/src/raci/index.ts +0 -23
  430. package/src/raci/mutations.ts +0 -321
  431. package/src/raci/parser.ts +0 -699
  432. package/src/raci/renderer.ts +0 -1627
  433. package/src/raci/types.ts +0 -82
  434. package/src/raci/variants.ts +0 -320
  435. package/src/render.ts +0 -268
  436. package/src/ring/parser.ts +0 -212
  437. package/src/ring/renderer.ts +0 -490
  438. package/src/ring/types.ts +0 -27
  439. package/src/sequence/collapse.ts +0 -174
  440. package/src/sequence/parser.ts +0 -1596
  441. package/src/sequence/participant-inference.ts +0 -152
  442. package/src/sequence/renderer.ts +0 -3168
  443. package/src/sequence/tag-resolution.ts +0 -164
  444. package/src/sharing.ts +0 -211
  445. package/src/sitemap/collapse.ts +0 -100
  446. package/src/sitemap/layout.ts +0 -925
  447. package/src/sitemap/parser.ts +0 -755
  448. package/src/sitemap/renderer.ts +0 -828
  449. package/src/sitemap/types.ts +0 -42
  450. package/src/slope/parser.ts +0 -18
  451. package/src/slope/renderer.ts +0 -378
  452. package/src/swimlane/diagnostics.ts +0 -94
  453. package/src/swimlane/layout.ts +0 -597
  454. package/src/swimlane/parser.ts +0 -613
  455. package/src/swimlane/renderer.ts +0 -681
  456. package/src/swimlane/types.ts +0 -151
  457. package/src/tech-radar/interactive.ts +0 -1129
  458. package/src/tech-radar/layout.ts +0 -197
  459. package/src/tech-radar/parser.ts +0 -436
  460. package/src/tech-radar/renderer.ts +0 -1239
  461. package/src/tech-radar/shared.ts +0 -151
  462. package/src/tech-radar/types.ts +0 -86
  463. package/src/themes.ts +0 -22
  464. package/src/timeline/parser.ts +0 -472
  465. package/src/timeline/renderer.ts +0 -3024
  466. package/src/timeline/types.ts +0 -33
  467. package/src/timeline/viz-parser.ts +0 -21
  468. package/src/treemap/diagnostics.ts +0 -62
  469. package/src/treemap/layout-radial.ts +0 -233
  470. package/src/treemap/layout.ts +0 -189
  471. package/src/treemap/parser.ts +0 -463
  472. package/src/treemap/renderer-radial.ts +0 -438
  473. package/src/treemap/renderer.ts +0 -572
  474. package/src/treemap/treemap-shared.ts +0 -309
  475. package/src/treemap/types.ts +0 -60
  476. package/src/utils/arrow-markers.ts +0 -51
  477. package/src/utils/arrows-diagnostics.ts +0 -62
  478. package/src/utils/arrows.ts +0 -227
  479. package/src/utils/brand.ts +0 -61
  480. package/src/utils/card.ts +0 -183
  481. package/src/utils/collapse-engine/tree-edges.ts +0 -115
  482. package/src/utils/collapse-engine/tree.ts +0 -117
  483. package/src/utils/d3-helpers.ts +0 -219
  484. package/src/utils/d3-types.ts +0 -9
  485. package/src/utils/description-helpers.ts +0 -38
  486. package/src/utils/duration.ts +0 -312
  487. package/src/utils/export-container.ts +0 -41
  488. package/src/utils/expr-eval.ts +0 -27
  489. package/src/utils/fit-canvas.ts +0 -64
  490. package/src/utils/hover-styles.ts +0 -673
  491. package/src/utils/inline-markdown.ts +0 -96
  492. package/src/utils/legend-constants.ts +0 -48
  493. package/src/utils/legend-d3.ts +0 -618
  494. package/src/utils/legend-integration.ts +0 -107
  495. package/src/utils/legend-layout.ts +0 -776
  496. package/src/utils/legend-svg.ts +0 -214
  497. package/src/utils/legend-types.ts +0 -272
  498. package/src/utils/name-normalize.ts +0 -163
  499. package/src/utils/note-box/constants.ts +0 -25
  500. package/src/utils/note-box/index.ts +0 -11
  501. package/src/utils/note-box/metrics.ts +0 -90
  502. package/src/utils/note-box/svg.ts +0 -331
  503. package/src/utils/notes/bounds.ts +0 -30
  504. package/src/utils/notes/build.ts +0 -131
  505. package/src/utils/notes/index.ts +0 -18
  506. package/src/utils/notes/model.ts +0 -19
  507. package/src/utils/notes/parse.ts +0 -131
  508. package/src/utils/notes/place.ts +0 -177
  509. package/src/utils/notes/resolve.ts +0 -88
  510. package/src/utils/number-format.ts +0 -36
  511. package/src/utils/parsing.ts +0 -953
  512. package/src/utils/reserved-key-registry.ts +0 -239
  513. package/src/utils/safe-href.ts +0 -38
  514. package/src/utils/scaling.ts +0 -97
  515. package/src/utils/svg-embed.ts +0 -251
  516. package/src/utils/tag-groups.ts +0 -607
  517. package/src/utils/text-measure.ts +0 -122
  518. package/src/utils/title-constants.ts +0 -24
  519. package/src/utils/visual-conventions.ts +0 -61
  520. package/src/utils/wrapped-desc.ts +0 -87
  521. package/src/venn/parser.ts +0 -18
  522. package/src/venn/renderer.ts +0 -1047
  523. package/src/version-control/diagnostics.ts +0 -67
  524. package/src/version-control/parser.ts +0 -544
  525. package/src/version-control/renderer.ts +0 -724
  526. package/src/version-control/types.ts +0 -100
  527. package/src/visualizations/parse.ts +0 -1560
  528. package/src/visualizations/types.ts +0 -262
  529. package/src/wireframe/layout.ts +0 -479
  530. package/src/wireframe/parser.ts +0 -1114
  531. package/src/wireframe/renderer.ts +0 -1318
  532. package/src/wireframe/types.ts +0 -110
  533. package/src/wordcloud/parser.ts +0 -18
  534. package/src/wordcloud/renderer.ts +0 -357
@@ -1,768 +0,0 @@
1
- // ============================================================
2
- // Pyramid Diagram — D3 SVG Renderer
3
- // ============================================================
4
-
5
- import * as d3Selection from 'd3-selection';
6
- import { FONT_FAMILY } from '../fonts';
7
- import {
8
- TITLE_FONT_SIZE,
9
- TITLE_FONT_WEIGHT,
10
- TITLE_Y,
11
- } from '../utils/title-constants';
12
- import {
13
- contrastText,
14
- getSeriesColors,
15
- shapeFill,
16
- } from '../palettes/color-utils';
17
- import { resolveColor } from '../colors';
18
- import { renderInlineText } from '../utils/inline-markdown';
19
- import { CHAR_WIDTH_RATIO, measureText } from '../utils/text-measure';
20
- import {
21
- wrapDescriptionLines,
22
- type WrappedDescLine,
23
- } from '../utils/wrapped-desc';
24
- import type { PaletteColors } from '../palettes';
25
- import type { D3ExportDimensions } from '../utils/d3-types';
26
- import type { ParsedPyramid, PyramidLayer } from './types';
27
- import { ScaleContext } from '../utils/scaling';
28
-
29
- // ── Constants ────────────────────────────────────────────────
30
- const TITLE_AREA_HEIGHT = 50;
31
- /** Side margin as fraction of viewport. */
32
- const H_MARGIN_FRAC = 0.03;
33
- /** Vertical breathing room above/below the pyramid body. */
34
- const V_MARGIN = 16;
35
- /** Max base-width fraction when no descriptions. */
36
- const BASE_WIDTH_FRAC_NO_DESC = 0.78;
37
- /** Pyramid width share when descriptions are on one side. */
38
- const PYRAMID_SHARE_WITH_DESC = 0.58;
39
- /** Pyramid width share when descriptions alternate sides. */
40
- const PYRAMID_SHARE_ALTERNATE = 0.42;
41
- /** Height-to-base-width ratio for the pyramid. Taller = more dramatic. */
42
- const PITCH_RATIO = 0.85;
43
- /** Gap between pyramid edge and description accent bar. */
44
- const DESC_GAP = 28;
45
- /** Width of the colored accent bar on the left of each description. */
46
- const DESC_ACCENT_WIDTH = 3;
47
- /** Gap between accent bar and description text. */
48
- const DESC_ACCENT_GAP = 12;
49
- /** Pixel offset between bullet glyph column and body-text column. */
50
- const BULLET_BODY_INDENT = 10;
51
-
52
- const LABEL_FONT_MIN = 12;
53
- const LABEL_FONT_MAX = 22;
54
- const DESC_FONT_MIN = 11;
55
- const DESC_FONT_MAX = 15;
56
-
57
- type Side = 'left' | 'right';
58
-
59
- interface WrappedDescription {
60
- /** All wrapped lines, full content. */
61
- allLines: WrappedDescLine[];
62
- /** Whether the wrapped content exceeds the layer's band cap. */
63
- overflows: boolean;
64
- /** Visible line count for the short (truncated) variant. */
65
- shortLineCount: number;
66
- }
67
-
68
- /**
69
- * Render a pyramid diagram into the given container.
70
- */
71
- export function renderPyramid(
72
- container: HTMLDivElement,
73
- parsed: ParsedPyramid,
74
- palette: PaletteColors,
75
- isDark: boolean,
76
- onClickItem?: (lineNumber: number) => void,
77
- exportDims?: D3ExportDimensions
78
- ): void {
79
- if (parsed.layers.length === 0) return;
80
-
81
- // Clear previous render
82
- d3Selection.select(container).selectAll(':not([data-d3-tooltip])').remove();
83
- const width = exportDims?.width ?? container.clientWidth;
84
- const height = exportDims?.height ?? container.clientHeight;
85
- if (width <= 0 || height <= 0) return;
86
-
87
- const idealWidth = width;
88
- const sctx = exportDims
89
- ? ScaleContext.identity()
90
- : ScaleContext.from(width, idealWidth);
91
-
92
- const sTitleFontSize = sctx.text(TITLE_FONT_SIZE);
93
- const sTitleY = sctx.structural(TITLE_Y);
94
- const sTitleAreaHeight = sctx.structural(TITLE_AREA_HEIGHT);
95
- const sVMargin = sctx.aesthetic(V_MARGIN);
96
-
97
- const hasAnyDescription = parsed.layers.some((l) => l.description.length > 0);
98
-
99
- const showTitle = !!parsed.title && parsed.options['no-title'] !== 'on';
100
- const titleH = showTitle ? sTitleAreaHeight : 0;
101
- const bodyTop = titleH + sVMargin;
102
- const bodyBottom = height - sVMargin;
103
- const bodyHeight = Math.max(60, bodyBottom - bodyTop);
104
- const sideMargin = width * H_MARGIN_FRAC;
105
- const usableWidth = width - sideMargin * 2;
106
-
107
- const N = parsed.layers.length;
108
-
109
- // Probe layout: single-column first. If any description would overflow its
110
- // band at single-column width, flip to alternating to buy wider columns.
111
- const singleProbe = computeLayout({
112
- width,
113
- usableWidth,
114
- sideMargin,
115
- bodyTop,
116
- bodyHeight,
117
- layers: parsed.layers,
118
- hasDescription: hasAnyDescription,
119
- alternate: false,
120
- });
121
-
122
- const anyOverflow = singleProbe.wraps.some((w) => w.overflows);
123
- const useAlternate = anyOverflow && hasAnyDescription && N >= 2;
124
-
125
- const layout = useAlternate
126
- ? computeLayout({
127
- width,
128
- usableWidth,
129
- sideMargin,
130
- bodyTop,
131
- bodyHeight,
132
- layers: parsed.layers,
133
- hasDescription: true,
134
- alternate: true,
135
- })
136
- : singleProbe;
137
-
138
- // ── SVG root ────────────────────────────────────────────────
139
- const svg = d3Selection
140
- .select(container)
141
- .append('svg')
142
- .attr('width', width)
143
- .attr('height', height)
144
- .attr('viewBox', `0 0 ${width} ${height}`)
145
- .attr('preserveAspectRatio', 'xMidYMin meet')
146
- .attr('xmlns', 'http://www.w3.org/2000/svg')
147
- .style('font-family', FONT_FAMILY);
148
-
149
- if (sctx.isBelowFloor) {
150
- svg.attr('width', '100%');
151
- }
152
-
153
- svg
154
- .append('style')
155
- .text(
156
- '.pyramid-desc-full{display:none}.dgmo-pyramid-layer-highlight.pyramid-desc-short{display:none}.dgmo-pyramid-layer-highlight.pyramid-desc-full{display:inline}.dgmo-pyramid-hidden{display:none}'
157
- );
158
-
159
- svg
160
- .append('rect')
161
- .attr('width', width)
162
- .attr('height', height)
163
- .attr('fill', palette.bg);
164
-
165
- if (showTitle) {
166
- const titleText = svg
167
- .append('text')
168
- .attr('class', 'chart-title')
169
- .attr('x', width / 2)
170
- .attr('y', sTitleY)
171
- .attr('text-anchor', 'middle')
172
- .attr('fill', palette.text)
173
- .attr('font-family', FONT_FAMILY)
174
- .attr('font-size', sTitleFontSize)
175
- .attr('font-weight', TITLE_FONT_WEIGHT)
176
- .attr('data-line-number', parsed.titleLineNumber)
177
- .text(parsed.title)
178
- .style('cursor', onClickItem ? 'pointer' : 'default');
179
- if (onClickItem) {
180
- titleText.on('click', () => onClickItem(parsed.titleLineNumber));
181
- }
182
- }
183
-
184
- // ── Layer colors ────────────────────────────────────────────
185
- const seriesColors = getSeriesColors(palette);
186
- const resolveSolid = (layer: PyramidLayer, i: number): string => {
187
- if (layer.color) {
188
- const named = resolveColor(layer.color, palette);
189
- if (named) return named;
190
- }
191
- // seriesColors is always non-empty (8 series colors).
192
- return seriesColors[i % seriesColors.length]!;
193
- };
194
-
195
- // ── Render layers ───────────────────────────────────────────
196
- const diagramG = svg.append('g').attr('class', 'pyramid-body');
197
-
198
- for (let i = 0; i < N; i++) {
199
- // In-bounds by loop guard (N = parsed.layers.length).
200
- const layer = parsed.layers[i]!;
201
- const topEdgeY = layout.pyramidTop + i * layout.layerH;
202
- const botEdgeY = topEdgeY + layout.layerH;
203
- const topHalf = halfWidthAt(i, N, layout.baseWidth, parsed.inverted);
204
- const botHalf = halfWidthAt(i + 1, N, layout.baseWidth, parsed.inverted);
205
-
206
- const polyPoints = [
207
- [layout.pyramidCx - topHalf, topEdgeY],
208
- [layout.pyramidCx + topHalf, topEdgeY],
209
- [layout.pyramidCx + botHalf, botEdgeY],
210
- [layout.pyramidCx - botHalf, botEdgeY],
211
- ]
212
- .map((p) => `${p[0]},${p[1]}`)
213
- .join(' ');
214
-
215
- const solidColor = resolveSolid(layer, i);
216
- const fillColor = shapeFill(palette, solidColor, isDark, {
217
- solid: parsed.options['solid-fill'] === 'on',
218
- });
219
-
220
- const layerG = diagramG
221
- .append('g')
222
- .attr('class', 'pyramid-layer')
223
- .attr('data-line-number', layer.lineNumber);
224
-
225
- if (onClickItem) {
226
- const ln = layer.lineNumber;
227
- layerG.style('cursor', 'pointer').on('click', () => onClickItem(ln));
228
- }
229
-
230
- layerG
231
- .append('polygon')
232
- .attr('points', polyPoints)
233
- .attr('fill', fillColor)
234
- .attr('stroke', solidColor)
235
- .attr('stroke-width', 2);
236
-
237
- const midY = (topEdgeY + botEdgeY) / 2;
238
- // Always contrast text color against the fill — that's where the label
239
- // sits in the common case.
240
- const textColor = contrastText(
241
- fillColor,
242
- palette.textOnFillLight,
243
- palette.textOnFillDark
244
- );
245
- // At narrow apexes the label can horizontally overflow the triangle and
246
- // spill onto the chart bg, where a single text color can't be readable
247
- // against both backgrounds. Add a paint-order halo in the opposite
248
- // contrast (dark halo around light text or vice versa) so the spilled
249
- // portion stays readable. Only when needed — wide segments don't need
250
- // the visual noise of a stroke.
251
- const labelFitsInside =
252
- Math.min(topHalf, botHalf) * 2 >
253
- measureText(layer.label, layout.labelFont);
254
- const haloColor =
255
- textColor === palette.textOnFillLight
256
- ? palette.textOnFillDark
257
- : palette.textOnFillLight;
258
-
259
- const labelText = layerG
260
- .append('text')
261
- .attr('x', layout.pyramidCx)
262
- .attr('y', midY)
263
- .attr('dy', '0.35em')
264
- .attr('text-anchor', 'middle')
265
- .attr('fill', textColor)
266
- .attr('font-family', FONT_FAMILY)
267
- .attr('font-size', layout.labelFont)
268
- .attr('font-weight', 600);
269
- if (!labelFitsInside) {
270
- labelText
271
- .attr('paint-order', 'stroke fill')
272
- .attr('stroke', haloColor)
273
- .attr('stroke-width', 3)
274
- .attr('stroke-linejoin', 'round')
275
- .attr('stroke-opacity', 0.6);
276
- }
277
- renderInlineText(labelText, layer.label, palette);
278
-
279
- // Description: render both short (truncated) and full variants.
280
- // CSS toggles visibility during highlight.
281
- if (layer.description.length > 0) {
282
- const side: Side = useAlternate
283
- ? i % 2 === 0
284
- ? 'right'
285
- : 'left'
286
- : 'right';
287
- const wrap = layout.wraps[i]!;
288
- renderLayerDescriptions(
289
- diagramG,
290
- layer,
291
- side,
292
- wrap,
293
- layout,
294
- midY,
295
- solidColor,
296
- palette,
297
- titleH + V_MARGIN,
298
- height - V_MARGIN,
299
- onClickItem
300
- );
301
- }
302
- }
303
- }
304
-
305
- /**
306
- * Render for CLI/export (no click handlers).
307
- */
308
- export function renderPyramidForExport(
309
- container: HTMLDivElement,
310
- parsed: ParsedPyramid,
311
- palette: PaletteColors,
312
- isDark: boolean,
313
- exportDims?: D3ExportDimensions
314
- ): void {
315
- renderPyramid(container, parsed, palette, isDark, undefined, exportDims);
316
- }
317
-
318
- // ============================================================
319
- // Layout
320
- // ============================================================
321
-
322
- interface LayoutInput {
323
- width: number;
324
- usableWidth: number;
325
- sideMargin: number;
326
- bodyTop: number;
327
- bodyHeight: number;
328
- layers: readonly PyramidLayer[];
329
- hasDescription: boolean;
330
- alternate: boolean;
331
- }
332
-
333
- interface PyramidLayout {
334
- alternate: boolean;
335
- baseWidth: number;
336
- pyramidCx: number;
337
- pyramidTop: number;
338
- pyramidH: number;
339
- layerH: number;
340
- labelFont: number;
341
- descFont: number;
342
- descLineHeight: number;
343
- /** Column widths: text-wrap budget, per side. */
344
- rightTextX: number;
345
- rightTextWidth: number;
346
- leftTextX: number;
347
- leftTextWidth: number;
348
- rightAccentX: number;
349
- leftAccentX: number;
350
- wraps: WrappedDescription[];
351
- }
352
-
353
- function computeLayout(input: LayoutInput): PyramidLayout {
354
- const {
355
- width,
356
- usableWidth,
357
- sideMargin,
358
- bodyTop,
359
- bodyHeight,
360
- layers,
361
- hasDescription,
362
- alternate,
363
- } = input;
364
- const N = layers.length;
365
-
366
- const pyramidShareFrac = hasDescription
367
- ? alternate
368
- ? PYRAMID_SHARE_ALTERNATE
369
- : PYRAMID_SHARE_WITH_DESC
370
- : BASE_WIDTH_FRAC_NO_DESC;
371
- const pyramidBandWidth = usableWidth * pyramidShareFrac;
372
-
373
- const maxBaseByHeight = bodyHeight / PITCH_RATIO;
374
- const baseWidth = Math.min(pyramidBandWidth, maxBaseByHeight);
375
- const pyramidH = baseWidth * PITCH_RATIO;
376
-
377
- let pyramidCx: number;
378
- if (!hasDescription) {
379
- pyramidCx = width / 2;
380
- } else if (alternate) {
381
- pyramidCx = width / 2;
382
- } else {
383
- pyramidCx = sideMargin + pyramidBandWidth / 2;
384
- }
385
-
386
- const pyramidTop = bodyTop + (bodyHeight - pyramidH) / 2;
387
- const layerH = pyramidH / N;
388
-
389
- // Font sizes scale with layer height.
390
- const labelFont = clamp(
391
- Math.round(layerH * 0.38),
392
- LABEL_FONT_MIN,
393
- LABEL_FONT_MAX
394
- );
395
- const descFont = clamp(
396
- Math.round(layerH * 0.22),
397
- DESC_FONT_MIN,
398
- DESC_FONT_MAX
399
- );
400
- const descLineHeight = Math.round(descFont * 1.35);
401
-
402
- // Description columns.
403
- // Right column: from right edge of pyramid (+ DESC_GAP) to (width - sideMargin).
404
- // Left column (alternate only): from sideMargin to left edge of pyramid (- DESC_GAP).
405
- const pyramidRightEdge = pyramidCx + baseWidth / 2;
406
- const pyramidLeftEdge = pyramidCx - baseWidth / 2;
407
-
408
- const rightAccentX = pyramidRightEdge + DESC_GAP;
409
- const rightTextX = rightAccentX + DESC_ACCENT_WIDTH + DESC_ACCENT_GAP;
410
- const rightTextWidth = Math.max(80, width - sideMargin - rightTextX);
411
-
412
- const leftAccentX = pyramidLeftEdge - DESC_GAP - DESC_ACCENT_WIDTH;
413
- const leftTextWidth = Math.max(
414
- 80,
415
- leftAccentX - DESC_ACCENT_GAP - sideMargin
416
- );
417
- const leftTextX = sideMargin;
418
-
419
- // Per-layer wrapping (measurement pass).
420
- const wraps: WrappedDescription[] = layers.map((layer, i) => {
421
- if (layer.description.length === 0) {
422
- return { allLines: [], overflows: false, shortLineCount: 0 };
423
- }
424
- const side: Side = alternate ? (i % 2 === 0 ? 'right' : 'left') : 'right';
425
- const colWidth = side === 'right' ? rightTextWidth : leftTextWidth;
426
- const wrapped = wrapDescription(layer.description, colWidth, descFont);
427
- // Visible cap: lines that fit the layer band with a little breathing room.
428
- const bandCap = Math.max(1, Math.floor(layerH / descLineHeight) - 0);
429
- const overflows = wrapped.length > bandCap;
430
- const shortLineCount = overflows ? bandCap : wrapped.length;
431
- return { allLines: wrapped, overflows, shortLineCount };
432
- });
433
-
434
- return {
435
- alternate,
436
- baseWidth,
437
- pyramidCx,
438
- pyramidTop,
439
- pyramidH,
440
- layerH,
441
- labelFont,
442
- descFont,
443
- descLineHeight,
444
- rightTextX,
445
- rightTextWidth,
446
- leftTextX,
447
- leftTextWidth,
448
- rightAccentX,
449
- leftAccentX,
450
- wraps,
451
- };
452
- }
453
-
454
- function halfWidthAt(
455
- edgeIdx: number,
456
- n: number,
457
- baseWidth: number,
458
- inverted: boolean
459
- ): number {
460
- const topNarrow = !inverted;
461
- const frac = topNarrow ? edgeIdx / n : (n - edgeIdx) / n;
462
- return (frac * baseWidth) / 2;
463
- }
464
-
465
- // ============================================================
466
- // Descriptions
467
- // ============================================================
468
-
469
- function renderLayerDescriptions(
470
- parentG: d3Selection.Selection<SVGGElement, unknown, null, undefined>,
471
- layer: PyramidLayer,
472
- side: Side,
473
- wrap: WrappedDescription,
474
- layout: PyramidLayout,
475
- midY: number,
476
- accentColor: string,
477
- palette: PaletteColors,
478
- topBound: number,
479
- bottomBound: number,
480
- onClickItem?: (lineNumber: number) => void
481
- ): void {
482
- const { descFont, descLineHeight } = layout;
483
- const accentX = side === 'right' ? layout.rightAccentX : layout.leftAccentX;
484
- const textX = side === 'right' ? layout.rightTextX : layout.leftTextX;
485
- const textAnchor: 'start' | 'end' = side === 'right' ? 'start' : 'end';
486
- // For right-anchored (left-column) text, x is the right edge of the column.
487
- const textLineX =
488
- side === 'right' ? textX : layout.leftAccentX - DESC_ACCENT_GAP;
489
- // For right-side bullets, anchor the glyph at the column's left edge and
490
- // let body text flow rightward. For left-side bullets, the column sits to
491
- // the LEFT of the bar and plain text right-aligns to the bar — to keep
492
- // the visual block tight against the bar (rather than floating at the
493
- // canvas margin), measure the widest bullet line per variant and
494
- // right-anchor the bullet block as a whole. Hanging indent is preserved
495
- // because all bullet rows still share the same body-column x.
496
- const bulletColRightEdge = layout.leftAccentX - DESC_ACCENT_GAP;
497
- const computeBulletColLeftX = (lines: WrappedDescLine[]): number => {
498
- if (side === 'right') return layout.rightTextX;
499
- let maxBodyW = 0;
500
- for (const l of lines) {
501
- if (l.kind === 'bullet-first' || l.kind === 'bullet-cont') {
502
- maxBodyW = Math.max(maxBodyW, measureText(l.text, descFont));
503
- }
504
- }
505
- return bulletColRightEdge - maxBodyW - BULLET_BODY_INDENT;
506
- };
507
-
508
- // Full-reveal budget: how many wrapped lines can fit between title and
509
- // bottom margin. Truncate beyond that.
510
- const availableH = bottomBound - topBound;
511
- const fullMaxLines = Math.max(1, Math.floor(availableH / descLineHeight));
512
- const fullLines = truncateWithEllipsis(wrap.allLines, fullMaxLines);
513
-
514
- // If the whole (full-budget) content fits the layer band, render once.
515
- if (!wrap.overflows) {
516
- renderDescriptionVariant({
517
- parentG,
518
- layer,
519
- lines: wrap.allLines,
520
- className: 'pyramid-desc',
521
- accentX,
522
- accentColor,
523
- textX: textLineX,
524
- textAnchor,
525
- side,
526
- bulletColLeftX: computeBulletColLeftX(wrap.allLines),
527
- midY,
528
- descFont,
529
- descLineHeight,
530
- palette,
531
- topBound,
532
- bottomBound,
533
- ...(onClickItem !== undefined && { onClickItem }),
534
- variant: 'short',
535
- });
536
- return;
537
- }
538
-
539
- // Overflow case: render short (visible by default) + full (revealed on highlight).
540
- const shortLines = buildShortLines(wrap);
541
- renderDescriptionVariant({
542
- parentG,
543
- layer,
544
- lines: shortLines,
545
- className: 'pyramid-desc pyramid-desc-short',
546
- accentX,
547
- accentColor,
548
- textX: textLineX,
549
- textAnchor,
550
- side,
551
- bulletColLeftX: computeBulletColLeftX(shortLines),
552
- midY,
553
- descFont,
554
- descLineHeight,
555
- palette,
556
- topBound,
557
- bottomBound,
558
- ...(onClickItem !== undefined && { onClickItem }),
559
- variant: 'short',
560
- });
561
-
562
- renderDescriptionVariant({
563
- parentG,
564
- layer,
565
- lines: fullLines,
566
- className: 'pyramid-desc pyramid-desc-full',
567
- accentX,
568
- accentColor,
569
- textX: textLineX,
570
- textAnchor,
571
- side,
572
- bulletColLeftX: computeBulletColLeftX(fullLines),
573
- midY,
574
- descFont,
575
- descLineHeight,
576
- palette,
577
- topBound,
578
- bottomBound,
579
- ...(onClickItem !== undefined && { onClickItem }),
580
- variant: 'full',
581
- });
582
- }
583
-
584
- function truncateWithEllipsis(
585
- lines: WrappedDescLine[],
586
- maxLines: number
587
- ): WrappedDescLine[] {
588
- if (lines.length <= maxLines) return lines.slice();
589
- const visible = lines.slice(0, maxLines);
590
- if (visible.length === 0) return visible;
591
- // Length checked above.
592
- const last = visible[visible.length - 1]!;
593
- visible[visible.length - 1] = {
594
- ...last,
595
- text: last.text.endsWith('…') ? last.text : `${last.text} …`,
596
- };
597
- return visible;
598
- }
599
-
600
- function buildShortLines(wrap: WrappedDescription): WrappedDescLine[] {
601
- if (!wrap.overflows) return wrap.allLines.slice();
602
- const visible = wrap.allLines.slice(0, wrap.shortLineCount);
603
- if (visible.length === 0) return [];
604
- // Length checked above.
605
- const last = visible[visible.length - 1]!;
606
- visible[visible.length - 1] = {
607
- ...last,
608
- text: last.text.endsWith('…') ? last.text : `${last.text} …`,
609
- };
610
- return visible;
611
- }
612
-
613
- interface RenderVariantArgs {
614
- parentG: d3Selection.Selection<SVGGElement, unknown, null, undefined>;
615
- layer: PyramidLayer;
616
- lines: WrappedDescLine[];
617
- className: string;
618
- accentX: number;
619
- accentColor: string;
620
- textX: number;
621
- textAnchor: 'start' | 'end';
622
- /**
623
- * Side of the pyramid the description sits on. Bullet lines are always
624
- * laid out left-to-right with the glyph at the column's left edge so
625
- * continuation lines align under the body — regardless of which side
626
- * the column is on.
627
- */
628
- side: Side;
629
- bulletColLeftX: number;
630
- midY: number;
631
- descFont: number;
632
- descLineHeight: number;
633
- palette: PaletteColors;
634
- topBound: number;
635
- bottomBound: number;
636
- onClickItem?: (lineNumber: number) => void;
637
- variant: 'short' | 'full';
638
- }
639
-
640
- function renderDescriptionVariant(args: RenderVariantArgs): void {
641
- const {
642
- parentG,
643
- layer,
644
- lines,
645
- className,
646
- accentX,
647
- accentColor,
648
- textX,
649
- textAnchor,
650
- bulletColLeftX,
651
- midY,
652
- descFont,
653
- descLineHeight,
654
- palette,
655
- topBound,
656
- bottomBound,
657
- onClickItem,
658
- variant,
659
- } = args;
660
- if (lines.length === 0) return;
661
-
662
- // Center the block on midY, but clamp so it stays between topBound/bottomBound.
663
- const totalH = lines.length * descLineHeight;
664
- let startY = midY - totalH / 2 + descLineHeight / 2;
665
- const accentPad = Math.max(4, Math.round(descFont * 0.3));
666
- const blockTop = startY - descLineHeight / 2 - accentPad;
667
- const blockBottom =
668
- startY +
669
- (lines.length - 1) * descLineHeight +
670
- descLineHeight / 2 +
671
- accentPad;
672
-
673
- let shift = 0;
674
- if (blockTop < topBound) shift = topBound - blockTop;
675
- else if (blockBottom > bottomBound) shift = bottomBound - blockBottom;
676
- startY += shift;
677
-
678
- const accentTop = startY - descLineHeight / 2 - accentPad;
679
- const accentH = totalH + accentPad * 2;
680
-
681
- const descG = parentG
682
- .append('g')
683
- .attr('class', className)
684
- .attr('data-line-number', layer.lineNumber)
685
- .attr('data-variant', variant);
686
-
687
- if (onClickItem) {
688
- const ln = layer.lineNumber;
689
- descG.style('cursor', 'pointer').on('click', () => onClickItem(ln));
690
- }
691
-
692
- descG
693
- .append('rect')
694
- .attr('x', accentX)
695
- .attr('y', accentTop)
696
- .attr('width', DESC_ACCENT_WIDTH)
697
- .attr('height', accentH)
698
- .attr('rx', DESC_ACCENT_WIDTH / 2)
699
- .attr('fill', accentColor);
700
-
701
- for (let j = 0; j < lines.length; j++) {
702
- // In-bounds by loop guard.
703
- const line = lines[j]!;
704
- const y = startY + j * descLineHeight;
705
- const isBullet =
706
- line.kind === 'bullet-first' || line.kind === 'bullet-cont';
707
- if (line.kind === 'bullet-first') {
708
- descG
709
- .append('text')
710
- .attr('x', bulletColLeftX)
711
- .attr('y', y)
712
- .attr('dy', '0.35em')
713
- .attr('text-anchor', 'start')
714
- .attr('fill', palette.text)
715
- .attr('font-family', FONT_FAMILY)
716
- .attr('font-size', descFont)
717
- .attr('font-weight', j === 0 ? 500 : 400)
718
- .text('•');
719
- }
720
- const t = descG
721
- .append('text')
722
- .attr('x', isBullet ? bulletColLeftX + BULLET_BODY_INDENT : textX)
723
- .attr('y', y)
724
- .attr('dy', '0.35em')
725
- .attr('text-anchor', isBullet ? 'start' : textAnchor)
726
- .attr('fill', palette.text)
727
- .attr('font-family', FONT_FAMILY)
728
- .attr('font-size', descFont)
729
- .attr('font-weight', j === 0 ? 500 : 400);
730
- renderInlineText(t, line.text, palette);
731
- }
732
- }
733
-
734
- // ============================================================
735
- // Text wrapping
736
- // ============================================================
737
-
738
- /**
739
- * Wrap a layer's description. Bullet lines (leading "- " or "• ") are split
740
- * by the shared helper into bullet-first / bullet-cont rows so the renderer
741
- * can place the glyph at the column edge and align continuation lines under
742
- * the body. Empty source lines render as a blank "plain" row to preserve
743
- * paragraph spacing.
744
- */
745
- function wrapDescription(
746
- lines: readonly string[],
747
- maxWidth: number,
748
- fontSize: number
749
- ): WrappedDescLine[] {
750
- const avgCharW = fontSize * CHAR_WIDTH_RATIO;
751
- const maxChars = Math.max(8, Math.floor(maxWidth / avgCharW));
752
- const normalized = lines.map((l) =>
753
- l.startsWith('- ') ? '• ' + l.slice(2) : l
754
- );
755
- const out: WrappedDescLine[] = [];
756
- for (const line of normalized) {
757
- if (line === '') {
758
- out.push({ text: '', kind: 'plain' });
759
- continue;
760
- }
761
- out.push(...wrapDescriptionLines([line], maxChars));
762
- }
763
- return out;
764
- }
765
-
766
- function clamp(x: number, lo: number, hi: number): number {
767
- return Math.max(lo, Math.min(hi, x));
768
- }