@diagrammo/dgmo 0.48.2 → 0.50.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 (244) hide show
  1. package/.cursorrules +12 -3
  2. package/.github/copilot-instructions.md +12 -3
  3. package/.windsurfrules +12 -3
  4. package/SKILL.md +12 -3
  5. package/dist/advanced.d.ts +851 -1
  6. package/dist/advanced.js +601 -177
  7. package/dist/auto.css +63 -0
  8. package/dist/auto.js +220 -110
  9. package/dist/auto.mjs +45920 -33167
  10. package/dist/block.css +63 -0
  11. package/dist/block.d.ts +13 -5
  12. package/dist/block.js +239 -62
  13. package/dist/{charts-d3-QOZHKTCT.js → charts-d3-DKUD7MQE.js} +9 -8
  14. package/dist/{chunk-3MQQNXPD.js → chunk-2C56LEML.js} +3 -3
  15. package/dist/{chunk-L66GEFB6.js → chunk-2JJ2KNPI.js} +4 -4
  16. package/dist/{chunk-6SM5NJQH.js → chunk-2QYTMIRR.js} +4 -4
  17. package/dist/{chunk-RJE5JTVK.js → chunk-3G6TMNVF.js} +7 -7
  18. package/dist/{chunk-MO5YHHMQ.js → chunk-3LKM6FMW.js} +2 -2
  19. package/dist/{chunk-76OWZ3BA.js → chunk-3P2DKJCG.js} +2 -2
  20. package/dist/chunk-3TDRHT4J.js +1043 -0
  21. package/dist/chunk-3XPUDB7B.js +420 -0
  22. package/dist/{chunk-2LACINWN.js → chunk-3ZPC476N.js} +7 -7
  23. package/dist/{chunk-G2H74XJZ.js → chunk-4BMJQFNK.js} +8 -8
  24. package/dist/{chunk-THXCFRTU.js → chunk-4S723I74.js} +9 -9
  25. package/dist/{chunk-6NYWYNBI.js → chunk-4XK3FLFB.js} +3 -3
  26. package/dist/chunk-5JSWBPZZ.js +607 -0
  27. package/dist/{chunk-WCT3NYCV.js → chunk-5LWQH6QV.js} +1 -1
  28. package/dist/{chunk-7DTWEFUE.js → chunk-5Z736BSU.js} +8 -8
  29. package/dist/{chunk-ERLBPDGU.js → chunk-6BFZKBGD.js} +2 -2
  30. package/dist/{chunk-6HO5ZTXK.js → chunk-6IAA2QQ2.js} +2 -2
  31. package/dist/{chunk-H6PI3KJT.js → chunk-6IUAK7RZ.js} +2 -2
  32. package/dist/{chunk-RTLBSQ3G.js → chunk-6M5PJFQG.js} +3 -3
  33. package/dist/{chunk-Z5CGSFJB.js → chunk-6X4AKWLF.js} +4 -4
  34. package/dist/{chunk-OJR3MQYV.js → chunk-6ZT4U37Q.js} +291 -52
  35. package/dist/{chunk-5QXL4NYS.js → chunk-7G2ER4CY.js} +10 -5
  36. package/dist/chunk-7PQYTZMA.js +681 -0
  37. package/dist/{chunk-OURHMODR.js → chunk-7RB5Q6MB.js} +11 -11
  38. package/dist/{chunk-YAA6IID3.js → chunk-7UEMZREK.js} +2 -2
  39. package/dist/{chunk-AN2MOO5T.js → chunk-A3WQVFBS.js} +3 -3
  40. package/dist/{chunk-VOKGH627.js → chunk-AHGF2YYA.js} +13 -3
  41. package/dist/{chunk-CI2G3OEB.js → chunk-ASS5YYIZ.js} +12 -12
  42. package/dist/{chunk-TYS6CSS5.js → chunk-BCYVE3N5.js} +2 -2
  43. package/dist/chunk-BDXC7MDK.js +2395 -0
  44. package/dist/chunk-BTUTZMPT.js +482 -0
  45. package/dist/{chunk-YGJTDXVR.js → chunk-C4GQDB5L.js} +2 -2
  46. package/dist/{chunk-Y2ZE3MSG.js → chunk-C63UWAKM.js} +2 -2
  47. package/dist/{chunk-725LDASD.js → chunk-CLD2OKV7.js} +2 -2
  48. package/dist/{chunk-WBRZJOEC.js → chunk-CMCR5WBW.js} +3 -3
  49. package/dist/{chunk-IZMRON6C.js → chunk-CVV36CWI.js} +2 -2
  50. package/dist/chunk-DMJJ3CEQ.js +254 -0
  51. package/dist/{chunk-MZSBFAPJ.js → chunk-EJTKV7CY.js} +9 -9
  52. package/dist/{chunk-FITOLXSX.js → chunk-EOFPYPAU.js} +26 -2
  53. package/dist/{chunk-X5LCYCL5.js → chunk-ER5SCQWQ.js} +5 -5
  54. package/dist/{chunk-4OHACBGX.js → chunk-F2L5GCQ4.js} +2 -2
  55. package/dist/{chunk-FCIIHT24.js → chunk-F5UDBSJY.js} +7 -7
  56. package/dist/{chunk-3JLKYGBQ.js → chunk-F7BFXWNQ.js} +2 -2
  57. package/dist/{chunk-FANX6UJR.js → chunk-FAL7NOK3.js} +11 -11
  58. package/dist/{chunk-BUPDIHML.js → chunk-FB2WHOEQ.js} +4 -4
  59. package/dist/chunk-FL4IOQ37.js +379 -0
  60. package/dist/{chunk-LIOHW36Z.js → chunk-GBE54KY6.js} +6 -5
  61. package/dist/{chunk-RUNNI6VE.js → chunk-GL5UZ6NY.js} +3 -3
  62. package/dist/{chunk-4GRI7MEB.js → chunk-GPWHQ5FJ.js} +6 -6
  63. package/dist/chunk-GROQGHCT.js +960 -0
  64. package/dist/{chunk-SGZYXELT.js → chunk-H73FP42Q.js} +9 -6
  65. package/dist/{chunk-PBAHEPLQ.js → chunk-HGN652MU.js} +7 -6
  66. package/dist/{chunk-3SMGIJDD.js → chunk-HHXOONLX.js} +13 -1
  67. package/dist/{chunk-QOOUC2J5.js → chunk-HQCHYB5F.js} +2 -2
  68. package/dist/{chunk-AELOBFW5.js → chunk-I4IFRCUB.js} +3 -3
  69. package/dist/{chunk-GMR5MFHJ.js → chunk-I7F2A35O.js} +2 -2
  70. package/dist/{chunk-T2OE3YQB.js → chunk-IA3FJYWR.js} +3 -3
  71. package/dist/chunk-IAEC4KLA.js +492 -0
  72. package/dist/chunk-IVKC4GID.js +32 -0
  73. package/dist/{chunk-HSH73DP6.js → chunk-JFYIP7XU.js} +139 -39
  74. package/dist/{chunk-CKNVO24D.js → chunk-JZNMXEIV.js} +2 -2
  75. package/dist/chunk-KJXIHOVL.js +940 -0
  76. package/dist/chunk-L2ZTFHAY.js +331 -0
  77. package/dist/{chunk-B7JUCQUA.js → chunk-M5RXSRO2.js} +4 -4
  78. package/dist/{chunk-ULOEATBZ.js → chunk-NFFIKVNO.js} +106 -29
  79. package/dist/{chunk-PZMETGLY.js → chunk-NISQC5KW.js} +358 -122
  80. package/dist/chunk-O4VUFXIH.js +574 -0
  81. package/dist/{chunk-RVMRZAPB.js → chunk-O76UD6VJ.js} +3 -3
  82. package/dist/{chunk-JM4LEPY3.js → chunk-O7NUCTFU.js} +2 -2
  83. package/dist/{chunk-JED6ZDEE.js → chunk-O7WP4ZD4.js} +2 -2
  84. package/dist/{chunk-EVCVDTXE.js → chunk-OHQEMBLI.js} +3 -3
  85. package/dist/{chunk-ZBWMSD5N.js → chunk-ONA5KPV3.js} +4 -4
  86. package/dist/{chunk-Y3J7VR52.js → chunk-OTAL43EH.js} +34 -2
  87. package/dist/{chunk-WCSOJFU3.js → chunk-OTP5KVLO.js} +3 -3
  88. package/dist/{chunk-RYEGFMUO.js → chunk-PGEGPSCZ.js} +2 -2
  89. package/dist/{chunk-ZO27FGJS.js → chunk-PH5X4GIP.js} +2 -2
  90. package/dist/{chunk-ZJEL4H2R.js → chunk-PJUGRJHJ.js} +9 -9
  91. package/dist/{chunk-ZGR7ULFJ.js → chunk-PLZI6KPM.js} +26 -14
  92. package/dist/{chunk-3R5POCTZ.js → chunk-PMN3Q7RJ.js} +6 -6
  93. package/dist/{chunk-YGJZWZTY.js → chunk-PZFVK3IH.js} +2 -2
  94. package/dist/chunk-Q4V4XQWV.js +158 -0
  95. package/dist/chunk-QDFNCATJ.js +325 -0
  96. package/dist/{chunk-QEBUY5NY.js → chunk-QFQ35BTO.js} +4 -4
  97. package/dist/chunk-QQJUTGQH.js +135 -0
  98. package/dist/{chunk-PWIHZ6NJ.js → chunk-QUJGFNFN.js} +4 -4
  99. package/dist/{chunk-J5FIXQRT.js → chunk-R56LASIN.js} +4 -4
  100. package/dist/{chunk-SRTU6HMQ.js → chunk-RV26LTUU.js} +8 -8
  101. package/dist/chunk-RV6A2B5S.js +354 -0
  102. package/dist/{chunk-EB6FPQUP.js → chunk-S5GRONXL.js} +3 -3
  103. package/dist/{chunk-5MLYVTYM.js → chunk-SCHXJTZL.js} +2 -2
  104. package/dist/{chunk-T3UBLACL.js → chunk-SCQ5VPUF.js} +19 -5
  105. package/dist/{chunk-PBHE5UG6.js → chunk-SGFZZAUO.js} +46 -12
  106. package/dist/{chunk-BUVJFRPY.js → chunk-SU2VBK4L.js} +4 -4
  107. package/dist/{chunk-SML67VPV.js → chunk-T4BRO3Z6.js} +3 -3
  108. package/dist/{chunk-NURGB5Z4.js → chunk-TSA237IM.js} +2 -2
  109. package/dist/chunk-TWCLK2GA.js +273 -0
  110. package/dist/{chunk-IJZFN3HM.js → chunk-TWQUYVP3.js} +4 -4
  111. package/dist/{chunk-DKEPS5LH.js → chunk-U2HGPLZS.js} +36 -2
  112. package/dist/{chunk-B65G5DNL.js → chunk-URSQLCTR.js} +3 -3
  113. package/dist/{chunk-ILKORZ3H.js → chunk-UUS2GIJZ.js} +7 -7
  114. package/dist/{chunk-XAKEUMEJ.js → chunk-UXOSVCLJ.js} +4 -4
  115. package/dist/{chunk-QLCCJEJI.js → chunk-WCUHAQKB.js} +2 -2
  116. package/dist/{chunk-WVAJFAIA.js → chunk-WWN566I7.js} +257 -101
  117. package/dist/{chunk-IPWPWM6R.js → chunk-X2NMFTG3.js} +111 -10
  118. package/dist/{chunk-UWN33VNX.js → chunk-XCLHOZAM.js} +10 -10
  119. package/dist/{chunk-P235SVAH.js → chunk-XDXNDSKO.js} +2 -2
  120. package/dist/chunk-XHVV4NVW.js +51 -0
  121. package/dist/{chunk-33LCUH4H.js → chunk-XMVQ5F4M.js} +4 -4
  122. package/dist/{chunk-MITI6NOL.js → chunk-YA7D2N2O.js} +11 -11
  123. package/dist/{chunk-7JEGTRLD.js → chunk-YB3FW24O.js} +3 -3
  124. package/dist/chunk-YNRDWYZP.js +295 -0
  125. package/dist/{chunk-44CM72SQ.js → chunk-YZLMKW4T.js} +3 -3
  126. package/dist/chunk-Z6XJQ6KO.js +452 -0
  127. package/dist/cli.cjs +179 -133
  128. package/dist/clock.d.ts +10 -0
  129. package/dist/clock.js +235 -0
  130. package/dist/countdown.d.ts +12 -0
  131. package/dist/countdown.js +450 -0
  132. package/dist/dgmo-router-QOMFCOOV.js +84 -0
  133. package/dist/dimensions-P5FSX2QN.js +22 -0
  134. package/dist/editor.js +43 -2
  135. package/dist/element.js +220 -110
  136. package/dist/element.mjs +45920 -33167
  137. package/dist/{flowchart-parser-ZNSKIBVR.js → flowchart-parser-OE4WHLTF.js} +4 -4
  138. package/dist/{flowchart-renderer-SNDSII4D.js → flowchart-renderer-GPCSMTOR.js} +8 -8
  139. package/dist/highlight.d.ts +17 -1
  140. package/dist/highlight.js +163 -6
  141. package/dist/index.d.ts +5 -1
  142. package/dist/index.js +199 -233
  143. package/dist/{layout-HRBZPFCN.js → layout-34CLNICW.js} +5 -5
  144. package/dist/layout-46366KBT.js +10 -0
  145. package/dist/{layout-HWDSRX5E.js → layout-5BG6DFCU.js} +6 -6
  146. package/dist/layout-6RDJHS6E.js +9 -0
  147. package/dist/{layout-7QXCNOVS.js → layout-7H4H46CS.js} +3 -3
  148. package/dist/{layout-46N4JJYK.js → layout-7SKMFYHL.js} +5 -5
  149. package/dist/{layout-EE6GE46Y.js → layout-DC4TVXER.js} +5 -5
  150. package/dist/layout-FGQWRYYW.js +14 -0
  151. package/dist/{layout-S2QBYSK2.js → layout-NXG63LWH.js} +3 -3
  152. package/dist/{layout-N76NR4ZO.js → layout-PUQCB6AN.js} +7 -7
  153. package/dist/{layout-HYZPWAK5.js → layout-QNUQLEHU.js} +3 -3
  154. package/dist/{layout-UM5F4DJB.js → layout-T3OZU5QW.js} +5 -5
  155. package/dist/layout-TJIWF7EM.js +14 -0
  156. package/dist/layout-VYELEAW7.js +14 -0
  157. package/dist/{layout-5RA6QWR6.js → layout-WZHNDT2O.js} +6 -6
  158. package/dist/{layout-search-OYV77HHS.js → layout-search-QS44PI5R.js} +6 -6
  159. package/dist/{parser-6BTRLKRZ.js → parser-45DENHFZ.js} +4 -4
  160. package/dist/{parser-TFZFBVWN.js → parser-4AI5ZN5F.js} +3 -3
  161. package/dist/{parser-XDVELHRK.js → parser-4P36TUVD.js} +4 -4
  162. package/dist/{parser-ZSDPZYQP.js → parser-5AURY4A6.js} +4 -4
  163. package/dist/{parser-N5O4IHUN.js → parser-A2BEFMGK.js} +4 -4
  164. package/dist/parser-B5FVS7O6.js +11 -0
  165. package/dist/{parser-NGU3ETO6.js → parser-C2HF2C2E.js} +4 -4
  166. package/dist/parser-CSFUN3CT.js +14 -0
  167. package/dist/{parser-TRTHDFPP.js → parser-D3QT6GWN.js} +5 -5
  168. package/dist/parser-D5637H5H.js +15 -0
  169. package/dist/{parser-VQP2UJ6W.js → parser-DFFEDKHH.js} +3 -3
  170. package/dist/parser-DOKMZXVZ.js +13 -0
  171. package/dist/parser-FMPCVFRK.js +15 -0
  172. package/dist/{parser-Y6WTBU76.js → parser-HYRTF3DO.js} +3 -3
  173. package/dist/{parser-I6KXEYFK.js → parser-I2UIJKVQ.js} +4 -4
  174. package/dist/{parser-O5J4VBII.js → parser-IBWNAPY4.js} +3 -3
  175. package/dist/{parser-PQ3POX45.js → parser-KUQWRPIT.js} +4 -4
  176. package/dist/{parser-2MFP2H2E.js → parser-LWKKBNSA.js} +3 -3
  177. package/dist/{parser-OV7NOBW6.js → parser-O4QFCUW7.js} +5 -5
  178. package/dist/{parser-IXSZZQHY.js → parser-PGMQDD4G.js} +4 -4
  179. package/dist/{parser-3STE62GB.js → parser-Q4QKCIWQ.js} +4 -4
  180. package/dist/parser-QTOB4KFL.js +14 -0
  181. package/dist/{parser-2EWECDSA.js → parser-QYYM4QVW.js} +4 -4
  182. package/dist/{parser-4OGOBJJ4.js → parser-RZMQP7MM.js} +4 -4
  183. package/dist/parser-RZPVAQVX.js +11 -0
  184. package/dist/parser-SOUJOEYI.js +13 -0
  185. package/dist/{parser-4FL2CMDG.js → parser-UQE5OWZI.js} +5 -5
  186. package/dist/{parser-NRAI6O25.js → parser-WAV5JRPT.js} +4 -4
  187. package/dist/{parser-KNSQSKQO.js → parser-YLKYBRIT.js} +5 -5
  188. package/dist/{parser-XKRP7QKP.js → parser-YS7TOS2K.js} +3 -3
  189. package/dist/{parser-AQETEVRW.js → parser-ZSOWUBML.js} +5 -5
  190. package/dist/{parser-CFZD5IBL.js → parser-ZTBATMLX.js} +4 -4
  191. package/dist/{renderer-VACVQYML.js → renderer-35HSIDMZ.js} +8 -8
  192. package/dist/{renderer-5MYBMBYO.js → renderer-4ITCHBT7.js} +5 -5
  193. package/dist/{renderer-CLJHQPBJ.js → renderer-67NPCBIS.js} +11 -11
  194. package/dist/{renderer-5NDVNDAZ.js → renderer-6GHYK7DX.js} +9 -9
  195. package/dist/{renderer-Z7I3W2PP.js → renderer-6RNGHC5Z.js} +8 -8
  196. package/dist/renderer-72LGR2YF.js +14 -0
  197. package/dist/{renderer-KQB7UGDS.js → renderer-7RH2SI3B.js} +3 -3
  198. package/dist/renderer-7SWMIFMM.js +21 -0
  199. package/dist/renderer-BBCEFILK.js +24 -0
  200. package/dist/{renderer-JGBKUCZD.js → renderer-BSW7SRIZ.js} +4 -4
  201. package/dist/{renderer-BYCNMBF7.js → renderer-BY533UWU.js} +11 -11
  202. package/dist/{renderer-6W5462RB.js → renderer-BZSBPTZJ.js} +9 -9
  203. package/dist/{renderer-7MVLWWQD.js → renderer-CXUC4KAD.js} +9 -9
  204. package/dist/{renderer-QIWVHWZO.js → renderer-DAXMXIKD.js} +3 -3
  205. package/dist/renderer-FZUKFUNZ.js +23 -0
  206. package/dist/renderer-G2NLGNKF.js +17 -0
  207. package/dist/renderer-GO3FE3RA.js +24 -0
  208. package/dist/{renderer-ZGNTUWC4.js → renderer-HPGR6USK.js} +8 -8
  209. package/dist/{renderer-UV6MI64M.js → renderer-HVCU2C3Z.js} +3 -3
  210. package/dist/renderer-ICJN2SA2.js +24 -0
  211. package/dist/{renderer-AWWAF6XD.js → renderer-INEXO7B6.js} +10 -10
  212. package/dist/{renderer-YY2OSF6E.js → renderer-KDYCFRBX.js} +8 -8
  213. package/dist/renderer-KY4KQBTF.js +19 -0
  214. package/dist/{renderer-B2OMQIQG.js → renderer-LBN65V45.js} +13 -13
  215. package/dist/{renderer-N43WR5GV.js → renderer-MGBWOCXG.js} +10 -10
  216. package/dist/{renderer-PGX2TKVS.js → renderer-O4JKUGKO.js} +8 -8
  217. package/dist/{renderer-4JHRUBE6.js → renderer-OOGFODWP.js} +10 -10
  218. package/dist/{renderer-6EEZHMH4.js → renderer-Q6ZKPLS6.js} +9 -9
  219. package/dist/{renderer-RPOA5YPZ.js → renderer-SZQ326M5.js} +12 -12
  220. package/dist/{renderer-ZRNG54CW.js → renderer-TKG6LS4U.js} +11 -11
  221. package/dist/{renderer-W4M6QLIJ.js → renderer-TQMZGDAX.js} +13 -13
  222. package/dist/renderer-radial-JELMHQ24.js +21 -0
  223. package/dist/{resolver-NOAA7ID7.js → resolver-FHBCO3PL.js} +3 -3
  224. package/dist/{state-parser-Z2V23ATR.js → state-parser-3REXRK3R.js} +4 -4
  225. package/dist/{state-renderer-B4DQBM6M.js → state-renderer-XYLNRWXR.js} +8 -8
  226. package/docs/ai-integration.md +12 -3
  227. package/docs/language-reference.md +429 -24
  228. package/gallery/fixtures/body.dgmo +17 -0
  229. package/gallery/fixtures/bracket.dgmo +30 -0
  230. package/gallery/fixtures/clock.dgmo +8 -0
  231. package/gallery/fixtures/countdown.dgmo +3 -0
  232. package/gallery/fixtures/family.dgmo +23 -0
  233. package/gallery/fixtures/goal.dgmo +4 -0
  234. package/gallery/fixtures/sketch.dgmo +22 -0
  235. package/package.json +12 -4
  236. package/dist/chunk-ODZVHU3R.js +0 -153
  237. package/dist/dgmo-router-X35VLZLM.js +0 -73
  238. package/dist/dimensions-J3FHIMJ6.js +0 -22
  239. package/dist/layout-5T6RH5M6.js +0 -14
  240. package/dist/layout-G23F7LDH.js +0 -9
  241. package/dist/layout-OB3RI63S.js +0 -14
  242. package/dist/parser-JAL2HD4I.js +0 -13
  243. package/dist/renderer-SMIBCRVB.js +0 -24
  244. package/dist/renderer-radial-C32GPJQ7.js +0 -21
@@ -0,0 +1,331 @@
1
+ import {
2
+ encodeDiagramUrl
3
+ } from "./chunk-NISQC5KW.js";
4
+ import {
5
+ FONT_FAMILY
6
+ } from "./chunk-6KFWC4CO.js";
7
+ import {
8
+ measureText,
9
+ truncateText
10
+ } from "./chunk-5LWQH6QV.js";
11
+
12
+ // src/error-card.ts
13
+ var MONO_FAMILY = "ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace";
14
+ var W = 660;
15
+ var PAD = 24;
16
+ var CONTENT_W = W - PAD * 2;
17
+ var MAX_ERRORS = 4;
18
+ var MONO_CH = 0.6;
19
+ var CODE_FS = 12.5;
20
+ function renderErrorCard(errors, source, palette, theme) {
21
+ const c = palette[theme === "dark" ? "dark" : "light"];
22
+ const isTransparent = theme === "transparent";
23
+ const card = c.surface;
24
+ const codeBg = c.bg;
25
+ const border = c.border;
26
+ const danger = c.destructive ?? c.colors.red;
27
+ const text = c.text;
28
+ const muted = c.textMuted;
29
+ const srcLines = source.split("\n");
30
+ const shown = errors.slice(0, MAX_ERRORS);
31
+ const overflow = errors.length - shown.length;
32
+ const parts = [];
33
+ let y = PAD + 8;
34
+ parts.push(frownMark(PAD + 14, y + 12, danger));
35
+ parts.push(
36
+ `<text x="${PAD + 38}" y="${y + 11}" fill="${text}" font-family="${FONT_FAMILY}" font-size="16" font-weight="700">Couldn't render this diagram</text>`,
37
+ `<text x="${W - PAD}" y="${y + 10}" text-anchor="end" fill="${muted}" font-family="${FONT_FAMILY}" font-size="12" font-weight="600" letter-spacing="0.5">dgmo</text>`
38
+ );
39
+ y += 24;
40
+ const errLabel = errors.length === 1 ? "1 error" : `${errors.length} errors`;
41
+ parts.push(
42
+ `<text x="${PAD + 38}" y="${y + 4}" fill="${muted}" font-family="${FONT_FAMILY}" font-size="12.5">${errLabel} \u2014 fix the lines below and re-render</text>`
43
+ );
44
+ y += 22;
45
+ parts.push(
46
+ `<line x1="${PAD}" y1="${y}" x2="${W - PAD}" y2="${y}" stroke="${border}" stroke-width="1"/>`
47
+ );
48
+ y += 24;
49
+ for (const e of shown) {
50
+ const hasLine = e.line > 0;
51
+ let msgX = PAD;
52
+ if (hasLine) {
53
+ const label = e.column ? `Line ${e.line}:${e.column}` : `Line ${e.line}`;
54
+ const badgeW = 14 + label.length * 7;
55
+ parts.push(
56
+ `<rect x="${PAD}" y="${y - 13}" width="${badgeW}" height="19" rx="4" fill="${danger}"/>`,
57
+ `<text x="${PAD + badgeW / 2}" y="${y + 1}" text-anchor="middle" fill="${c.bg}" font-family="${FONT_FAMILY}" font-size="11.5" font-weight="700">${escapeXml(label)}</text>`
58
+ );
59
+ msgX = PAD + badgeW + 12;
60
+ }
61
+ const lines = wrapMessage(e.message, CONTENT_W - (msgX - PAD), CONTENT_W);
62
+ lines.forEach((line, i) => {
63
+ parts.push(
64
+ `<text x="${i === 0 ? msgX : PAD}" y="${y + 1}" fill="${text}" font-family="${FONT_FAMILY}" font-size="13">${escapeXml(line)}</text>`
65
+ );
66
+ if (i < lines.length - 1) y += 18;
67
+ });
68
+ y += 24;
69
+ if (hasLine) {
70
+ const CTX = 2;
71
+ const first = Math.max(1, e.line - CTX);
72
+ const last = Math.min(srcLines.length, e.line + CTX);
73
+ const rowH = 18;
74
+ const hasCaret = e.column !== void 0 && e.column > 0;
75
+ const gutterW = `${last}`.length * CODE_FS * MONO_CH + 16;
76
+ const codeX = PAD + gutterW;
77
+ const codeMaxW = CONTENT_W - gutterW - 12;
78
+ const topY = y - 14;
79
+ const rowCount = last - first + 1;
80
+ const blockH = rowCount * rowH + (hasCaret ? 14 : 0) + 10;
81
+ const rowParts = [];
82
+ let ry = y + 3;
83
+ for (let n = first; n <= last; n++) {
84
+ const raw = (srcLines[n - 1] ?? "").replace(/\t/g, " ");
85
+ const codeText = truncateText(raw, CODE_FS, codeMaxW);
86
+ const isBad = n === e.line;
87
+ if (isBad) {
88
+ rowParts.push(
89
+ `<rect x="${PAD + 1}" y="${ry - 13}" width="${CONTENT_W - 2}" height="${rowH}" fill="${danger}" fill-opacity="0.16"/>`
90
+ );
91
+ }
92
+ rowParts.push(
93
+ `<text x="${PAD + 8}" y="${ry + 1}" fill="${isBad ? danger : muted}" font-family="${MONO_FAMILY}" font-size="${CODE_FS}" font-weight="${isBad ? 700 : 400}">${escapeXml(`${n}`)}</text>`,
94
+ `<text x="${codeX}" y="${ry + 1}" fill="${text}" font-family="${MONO_FAMILY}" font-size="${CODE_FS}" xml:space="preserve">${escapeXml(codeText)}</text>`
95
+ );
96
+ if (isBad && hasCaret) {
97
+ const caretX = codeX + (e.column - 1) * CODE_FS * MONO_CH;
98
+ rowParts.push(
99
+ `<text x="${caretX}" y="${ry + 15}" fill="${danger}" font-family="${MONO_FAMILY}" font-size="${CODE_FS}" font-weight="700">^</text>`
100
+ );
101
+ ry += 14;
102
+ }
103
+ ry += rowH;
104
+ }
105
+ parts.push(
106
+ `<rect x="${PAD}" y="${topY}" width="${CONTENT_W}" height="${blockH}" rx="5" fill="${codeBg}" stroke="${border}" stroke-width="1"/>`,
107
+ `<line x1="${codeX - 8}" y1="${topY}" x2="${codeX - 8}" y2="${topY + blockH}" stroke="${border}" stroke-width="1"/>`,
108
+ rowParts.join("")
109
+ );
110
+ y = topY + blockH + 10;
111
+ }
112
+ y += 14;
113
+ }
114
+ if (overflow > 0) {
115
+ parts.push(
116
+ `<text x="${PAD}" y="${y}" fill="${muted}" font-family="${FONT_FAMILY}" font-size="12.5" font-style="italic">+ ${overflow} more error${overflow === 1 ? "" : "s"}</text>`
117
+ );
118
+ y += 22;
119
+ }
120
+ y += 2;
121
+ parts.push(
122
+ `<line x1="${PAD}" y1="${y}" x2="${W - PAD}" y2="${y}" stroke="${border}" stroke-width="1"/>`
123
+ );
124
+ y += 24;
125
+ const encoded = encodeDiagramUrl(source);
126
+ const editUrl = "url" in encoded && encoded.url ? encoded.url : "https://online.diagrammo.app";
127
+ const iconSize = 18;
128
+ const linkColor = c.colors.blue ?? c.text;
129
+ parts.push(
130
+ `<a href="${escapeXml(editUrl)}" target="_blank" rel="noopener noreferrer">` + diagrammoIcon(PAD, y - 14, iconSize) + `<text x="${PAD + iconSize + 8}" y="${y}" fill="${linkColor}" font-family="${FONT_FAMILY}" font-size="12.5" font-weight="600" text-decoration="underline">Edit &amp; fix this diagram at online.diagrammo.app \u2197</text></a>`
131
+ );
132
+ y += 8;
133
+ const height = Math.round(y + PAD - 14);
134
+ const pageBg = isTransparent ? "" : `<rect width="100%" height="100%" fill="${c.bg}"/>`;
135
+ return [
136
+ `<svg xmlns="http://www.w3.org/2000/svg" width="${W}" height="${height}" viewBox="0 0 ${W} ${height}" font-family="${FONT_FAMILY}">`,
137
+ pageBg,
138
+ `<rect x="0.5" y="0.5" width="${W - 1}" height="${height - 1}" rx="10" fill="${card}" stroke="${border}" stroke-width="1"/>`,
139
+ parts.join(""),
140
+ `</svg>`
141
+ ].join("");
142
+ }
143
+ function wrapMessage(message, firstWidth, fullWidth) {
144
+ const words = message.split(/\s+/).filter(Boolean);
145
+ if (words.length === 0) return [""];
146
+ const lines = [];
147
+ let cur = "";
148
+ for (const word of words) {
149
+ const limit = lines.length === 0 ? firstWidth : fullWidth;
150
+ const test = cur ? `${cur} ${word}` : word;
151
+ if (measureText(test, 13) <= limit || !cur) {
152
+ cur = test;
153
+ } else {
154
+ lines.push(cur);
155
+ cur = word;
156
+ }
157
+ }
158
+ if (cur) lines.push(cur);
159
+ return lines;
160
+ }
161
+ function frownMark(cx, cy, color) {
162
+ const r = 12;
163
+ return [
164
+ `<circle cx="${cx}" cy="${cy}" r="${r}" fill="none" stroke="${color}" stroke-width="2"/>`,
165
+ `<circle cx="${cx - 4.5}" cy="${cy - 3}" r="1.6" fill="${color}"/>`,
166
+ `<circle cx="${cx + 4.5}" cy="${cy - 3}" r="1.6" fill="${color}"/>`,
167
+ `<path d="M ${cx - 5} ${cy + 6} Q ${cx} ${cy + 1} ${cx + 5} ${cy + 6}" fill="none" stroke="${color}" stroke-width="2" stroke-linecap="round"/>`
168
+ ].join("");
169
+ }
170
+ function diagrammoIcon(x, y, size) {
171
+ const s = size / 100;
172
+ return `<g transform="translate(${x} ${y}) scale(${s})"><rect width="100" height="100" rx="18" fill="#1f2933"/><path d="M41 71 L41 63.51 A28 28 0 1 1 59 63.51 L59 71" fill="none" stroke="#c9a227" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/><rect x="36" y="43" width="7" height="9" rx="1.9" fill="#c0504d"/><rect x="45" y="37" width="7" height="15" rx="1.9" fill="#5b9357"/><rect x="54" y="30" width="7" height="22" rx="1.9" fill="#3b6ea5"/><rect x="36" y="75" width="28" height="4.6" rx="2.3" fill="#7d5ba6"/><rect x="36" y="82" width="28" height="4.6" rx="2.3" fill="#7d5ba6"/><rect x="36" y="89" width="28" height="4.6" rx="2.3" fill="#7d5ba6"/></g>`;
173
+ }
174
+ function escapeXml(s) {
175
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
176
+ }
177
+
178
+ // src/utils/svg-embed.ts
179
+ function normalizeSvgForEmbed(input) {
180
+ let svg = input;
181
+ const rootMatch = svg.match(/<svg[^>]*>/);
182
+ const rootTag = rootMatch?.[0] ?? "";
183
+ if (rootTag && !rootTag.includes("viewBox")) {
184
+ const wh = rootTag.match(/width="(\d+)"[^>]*height="(\d+)"/);
185
+ if (wh) {
186
+ svg = svg.replace(/<svg/, `<svg viewBox="0 0 ${wh[1]} ${wh[2]}"`);
187
+ }
188
+ }
189
+ const tight = computeBBox(svg);
190
+ if (tight && tight.width > 0 && tight.height > 0) {
191
+ const pad = 16;
192
+ const x = tight.x - pad;
193
+ const y = tight.y - pad;
194
+ const w = tight.width + pad * 2;
195
+ const h = tight.height + pad * 2;
196
+ const canvas = readViewBox(svg);
197
+ const TOL = 2;
198
+ const MIN_COVERAGE = 0.5;
199
+ const trustworthy = !canvas || x >= canvas.x - TOL && y >= canvas.y - TOL && x + w <= canvas.x + canvas.width + TOL && y + h <= canvas.y + canvas.height + TOL && w >= canvas.width * MIN_COVERAGE && h >= canvas.height * MIN_COVERAGE;
200
+ if (trustworthy) {
201
+ const vb = `${x} ${y} ${w} ${h}`;
202
+ svg = svg.replace(/(<svg[^>]*?)viewBox="[^"]*"/, `$1viewBox="${vb}"`);
203
+ }
204
+ }
205
+ svg = svg.replace(/(<svg[^>]*?) width="[^"]*"/g, "$1");
206
+ svg = svg.replace(/(<svg[^>]*?) height="[^"]*"/g, "$1");
207
+ svg = svg.replace(/<svg\s{2,}/g, "<svg ");
208
+ return svg;
209
+ }
210
+ function getEmbedSvgViewBox(svg) {
211
+ const tight = computeBBox(svg);
212
+ if (!tight || tight.width <= 0 || tight.height <= 0) return null;
213
+ const pad = 16;
214
+ return {
215
+ x: tight.x - pad,
216
+ y: tight.y - pad,
217
+ width: tight.width + pad * 2,
218
+ height: tight.height + pad * 2
219
+ };
220
+ }
221
+ function readViewBox(svg) {
222
+ const m = svg.match(/<svg[^>]*?\bviewBox="([^"]+)"/);
223
+ if (!m) return null;
224
+ const n = m[1].trim().split(/[\s,]+/).map(Number);
225
+ if (n.length !== 4 || n.some((v) => !Number.isFinite(v)) || n[2] <= 0 || n[3] <= 0)
226
+ return null;
227
+ return { x: n[0], y: n[1], width: n[2], height: n[3] };
228
+ }
229
+ function computeBBox(svg) {
230
+ const xs = [];
231
+ const ys = [];
232
+ function push(x, y) {
233
+ if (Number.isFinite(x) && Number.isFinite(y)) {
234
+ xs.push(x);
235
+ ys.push(y);
236
+ }
237
+ }
238
+ function attr(tag, name) {
239
+ const m = tag.match(new RegExp(`\\b${name}="([^"]*)"`));
240
+ if (!m) return null;
241
+ const n = parseFloat(m[1]);
242
+ return Number.isFinite(n) ? n : null;
243
+ }
244
+ for (const m of svg.matchAll(/<rect\b[^>]*?\/?>/g)) {
245
+ const tag = m[0];
246
+ const x = attr(tag, "x");
247
+ const y = attr(tag, "y");
248
+ const w = attr(tag, "width");
249
+ const h = attr(tag, "height");
250
+ if (x !== null && y !== null && w !== null && h !== null) {
251
+ push(x, y);
252
+ push(x + w, y + h);
253
+ }
254
+ }
255
+ for (const m of svg.matchAll(/<line\b[^>]*?\/?>/g)) {
256
+ const tag = m[0];
257
+ const x1 = attr(tag, "x1");
258
+ const y1 = attr(tag, "y1");
259
+ const x2 = attr(tag, "x2");
260
+ const y2 = attr(tag, "y2");
261
+ if (x1 !== null && y1 !== null && x2 !== null && y2 !== null) {
262
+ push(x1, y1);
263
+ push(x2, y2);
264
+ }
265
+ }
266
+ for (const m of svg.matchAll(/<circle\b[^>]*?\/?>/g)) {
267
+ const tag = m[0];
268
+ const cx = attr(tag, "cx");
269
+ const cy = attr(tag, "cy");
270
+ const r = attr(tag, "r");
271
+ if (cx !== null && cy !== null && r !== null) {
272
+ push(cx - r, cy - r);
273
+ push(cx + r, cy + r);
274
+ }
275
+ }
276
+ for (const m of svg.matchAll(/<ellipse\b[^>]*?\/?>/g)) {
277
+ const tag = m[0];
278
+ const cx = attr(tag, "cx");
279
+ const cy = attr(tag, "cy");
280
+ const rx = attr(tag, "rx");
281
+ const ry = attr(tag, "ry");
282
+ if (cx !== null && cy !== null && rx !== null && ry !== null) {
283
+ push(cx - rx, cy - ry);
284
+ push(cx + rx, cy + ry);
285
+ }
286
+ }
287
+ for (const m of svg.matchAll(/<text\b([^>]*?)>([\s\S]*?)<\/text>/g)) {
288
+ const tag = `<text${m[1]}>`;
289
+ const text = m[2].replace(/<[^>]+>/g, "");
290
+ const x = attr(tag, "x");
291
+ const y = attr(tag, "y");
292
+ if (x !== null && y !== null) {
293
+ const w = text.length * 7;
294
+ const anchor = tag.match(/\btext-anchor="([^"]*)"/)?.[1] ?? "start";
295
+ const left = anchor === "middle" ? x - w / 2 : anchor === "end" ? x - w : x;
296
+ const right = anchor === "middle" ? x + w / 2 : anchor === "end" ? x : x + w;
297
+ push(left, y - 14);
298
+ push(right, y + 4);
299
+ }
300
+ }
301
+ for (const m of svg.matchAll(/<path\b[^>]*?\bd="([^"]+)"/g)) {
302
+ const d = m[1];
303
+ const nums = d.match(/-?\d+(?:\.\d+)?/g);
304
+ if (!nums) continue;
305
+ for (let i = 0; i + 1 < nums.length; i += 2) {
306
+ push(parseFloat(nums[i]), parseFloat(nums[i + 1]));
307
+ }
308
+ }
309
+ for (const m of svg.matchAll(
310
+ /<(?:polygon|polyline)\b[^>]*?\bpoints="([^"]+)"/g
311
+ )) {
312
+ const nums = m[1].match(/-?\d+(?:\.\d+)?/g);
313
+ if (!nums) continue;
314
+ for (let i = 0; i + 1 < nums.length; i += 2) {
315
+ push(parseFloat(nums[i]), parseFloat(nums[i + 1]));
316
+ }
317
+ }
318
+ if (xs.length === 0 || ys.length === 0) return null;
319
+ const minX = Math.min(...xs);
320
+ const maxX = Math.max(...xs);
321
+ const minY = Math.min(...ys);
322
+ const maxY = Math.max(...ys);
323
+ return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
324
+ }
325
+
326
+ export {
327
+ renderErrorCard,
328
+ normalizeSvgForEmbed,
329
+ getEmbedSvgViewBox
330
+ };
331
+ //# sourceMappingURL=chunk-L2ZTFHAY.js.map
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-PDKUANDZ.js";
5
5
  import {
6
6
  layoutGraph
7
- } from "./chunk-T3UBLACL.js";
7
+ } from "./chunk-SCQ5VPUF.js";
8
8
  import {
9
9
  appendArrowheadMarkers
10
10
  } from "./chunk-LP7EC4MI.js";
@@ -32,14 +32,14 @@ import {
32
32
  } from "./chunk-6KFWC4CO.js";
33
33
  import {
34
34
  measureText
35
- } from "./chunk-WCT3NYCV.js";
35
+ } from "./chunk-5LWQH6QV.js";
36
36
  import {
37
37
  contrastText,
38
38
  shapeFill
39
39
  } from "./chunk-P6T66CCZ.js";
40
40
  import {
41
41
  parseFlowchart
42
- } from "./chunk-LIOHW36Z.js";
42
+ } from "./chunk-GBE54KY6.js";
43
43
 
44
44
  // src/graph/flowchart-renderer.ts
45
45
  import * as d3Selection from "d3-selection";
@@ -527,4 +527,4 @@ export {
527
527
  renderFlowchart,
528
528
  renderFlowchartForExport
529
529
  };
530
- //# sourceMappingURL=chunk-B7JUCQUA.js.map
530
+ //# sourceMappingURL=chunk-M5RXSRO2.js.map
@@ -5,29 +5,33 @@ import {
5
5
  formatPct,
6
6
  resolveCellColor,
7
7
  resolveColorMode
8
- } from "./chunk-IZMRON6C.js";
8
+ } from "./chunk-CVV36CWI.js";
9
9
  import {
10
10
  renderIntegratedLegend
11
- } from "./chunk-PWIHZ6NJ.js";
11
+ } from "./chunk-QUJGFNFN.js";
12
12
  import {
13
13
  getMaxLegendReservedHeight
14
- } from "./chunk-YAA6IID3.js";
14
+ } from "./chunk-7UEMZREK.js";
15
15
  import {
16
16
  FONT_FAMILY
17
17
  } from "./chunk-6KFWC4CO.js";
18
18
  import {
19
19
  LEGEND_GROUP_GAP
20
- } from "./chunk-QOOUC2J5.js";
20
+ } from "./chunk-HQCHYB5F.js";
21
21
  import {
22
22
  measureText
23
- } from "./chunk-WCT3NYCV.js";
23
+ } from "./chunk-5LWQH6QV.js";
24
24
  import {
25
+ contrastRatio,
25
26
  contrastText,
26
- getSeriesColors
27
+ getSeriesColors,
28
+ hexToHSL,
29
+ hslToHex,
30
+ relativeLuminance
27
31
  } from "./chunk-P6T66CCZ.js";
28
32
  import {
29
33
  tagAttrKey
30
- } from "./chunk-QLCCJEJI.js";
34
+ } from "./chunk-WCUHAQKB.js";
31
35
 
32
36
  // src/treemap/renderer-radial.ts
33
37
  import * as d3Selection from "d3-selection";
@@ -149,6 +153,7 @@ var LEGEND_POSITION = {
149
153
  };
150
154
  var MIN_LABEL_SWEEP = 6 * Math.PI / 180;
151
155
  var MIN_LABEL_FS = 8;
156
+ var LABEL_BASE_FS = 16;
152
157
  function renderTreemapRadialForExport(container, parsed, palette, isDark, exportDims, options) {
153
158
  renderTreemapRadial(container, parsed, palette, isDark, exportDims, {
154
159
  exportMode: true,
@@ -271,58 +276,130 @@ function drawCenterDisc(plot, parsed, discRadius, total, isEmpty, palette) {
271
276
  return;
272
277
  }
273
278
  const title = parsed.title ?? "";
274
- const totalStr = compactNumber(total);
279
+ const totalStr = groupedNumber(total);
275
280
  const titleFs = clampFs(15, discRadius);
276
- const totalFs = clampFs(22, discRadius);
281
+ const totalFs = fitFs(totalStr, clampFs(22, discRadius), maxW);
277
282
  if (title) {
278
283
  const t = disc.append("text").attr("class", "dgmo-treemap-disc-title").attr("text-anchor", "middle").attr("y", -4).attr("fill", ink).attr("font-size", titleFs).attr("font-weight", 600).text(clip(title, maxW, titleFs));
279
284
  if (parsed.titleLineNumber !== null) {
280
285
  t.attr("data-line-number", parsed.titleLineNumber);
281
286
  }
282
287
  }
283
- disc.append("text").attr("class", "dgmo-treemap-disc-total").attr("text-anchor", "middle").attr("y", title ? titleFs : 8).attr("fill", ink).attr("font-size", totalFs).attr("font-weight", 700).text(clip(totalStr, maxW, totalFs));
288
+ disc.append("text").attr("class", "dgmo-treemap-disc-total").attr("text-anchor", "middle").attr("y", title ? titleFs : 8).attr("fill", ink).attr("font-size", totalFs).attr("font-weight", 700).text(totalStr);
289
+ }
290
+ function groupedNumber(v) {
291
+ const rounded = Math.round(v * 100) / 100;
292
+ const neg = rounded < 0 ? "-" : "";
293
+ const [int, frac] = String(Math.abs(rounded)).split(".");
294
+ const grouped = int.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
295
+ return frac ? `${neg}${grouped}.${frac}` : `${neg}${grouped}`;
284
296
  }
285
297
  function drawArcLabel(g, defs, pathId, cell, opts, palette, fill) {
286
298
  const sweep = cell.endAngle - cell.startAngle;
287
299
  if (sweep < MIN_LABEL_SWEEP) return;
288
300
  const ringThickness = cell.outerR - cell.innerR;
289
301
  if (ringThickness < 10) return;
290
- const ink = contrastText(
291
- fill,
292
- palette.textOnFillLight,
293
- palette.textOnFillDark
294
- );
302
+ const ink = tonalInk(fill, palette.textOnFillLight, palette.textOnFillDark);
295
303
  const rMid = (cell.innerR + cell.outerR) / 2;
296
- const maxFs = clampFs(13, ringThickness);
304
+ const maxFs = clampFs(LABEL_BASE_FS, ringThickness);
305
+ const name = cell.label;
297
306
  const valParts = [
298
307
  opts.noValues ? "" : compactNumber(cell.value),
299
308
  opts.noPercent ? "" : formatPct(cell.pctOfRoot)
300
309
  ].filter(Boolean);
301
310
  const valStr = valParts.join(" \xB7 ");
302
- const full = valStr ? `${cell.label} ${valStr}` : cell.label;
303
- const availLen = sweep * rMid * 0.94;
304
- let fs = maxFs;
305
- const wAtMax = measureText(full, maxFs);
306
- if (wAtMax > availLen) {
307
- fs = Math.max(MIN_LABEL_FS, Math.floor(maxFs * availLen / wAtMax));
311
+ const valFsBase = Math.max(MIN_LABEL_FS, Math.round(maxFs * 0.82));
312
+ const lineGap = Math.round((maxFs + valFsBase) * 0.6);
313
+ const blockExtent = lineGap + 0.35 * maxFs + 0.35 * valFsBase + 4;
314
+ if (valStr && ringThickness >= blockExtent) {
315
+ const nameOuter = !isBottomHalf(cell);
316
+ const rName = rMid + (nameOuter ? 1 : -1) * (lineGap / 2);
317
+ const rVal = rMid + (nameOuter ? -1 : 1) * (lineGap / 2);
318
+ const nameAvail = sweep * rName * 0.94;
319
+ const nameFs = fitFs(name, maxFs, nameAvail);
320
+ const nameText = clip(name, nameAvail, nameFs);
321
+ if (nameText) {
322
+ drawCurvedLine(
323
+ g,
324
+ defs,
325
+ `${pathId}-n`,
326
+ cell,
327
+ rName,
328
+ nameFs,
329
+ 600,
330
+ nameText,
331
+ ink
332
+ );
333
+ const valAvail = sweep * rVal * 0.94;
334
+ const valFs = fitFs(valStr, valFsBase, valAvail);
335
+ const valText = clip(valStr, valAvail, valFs);
336
+ if (valText) {
337
+ drawCurvedLine(
338
+ g,
339
+ defs,
340
+ `${pathId}-v`,
341
+ cell,
342
+ rVal,
343
+ valFs,
344
+ 500,
345
+ valText,
346
+ ink
347
+ );
348
+ }
349
+ return;
350
+ }
308
351
  }
352
+ const full = valStr ? `${name} ${valStr}` : name;
353
+ const availLen = sweep * rMid * 0.94;
354
+ const fs = fitFs(full, maxFs, availLen);
309
355
  const text = clip(full, availLen, fs);
310
356
  if (!text) return;
311
- drawCurvedLabel(g, defs, pathId, cell, rMid, fs, text, ink);
357
+ drawCurvedLine(g, defs, pathId, cell, rMid, fs, 600, text, ink);
312
358
  }
313
- function drawCurvedLabel(g, defs, pathId, cell, rMid, fs, text, ink) {
359
+ function isBottomHalf(cell) {
314
360
  const mid = (cell.startAngle + cell.endAngle) / 2;
315
- const bottom = mid > Math.PI / 2 && mid < 3 * Math.PI / 2;
316
- const rPath = bottom ? rMid + fs * 0.32 : rMid - fs * 0.32;
361
+ return mid > Math.PI / 2 && mid < 3 * Math.PI / 2;
362
+ }
363
+ function fitFs(text, maxFs, availLen) {
364
+ const w = measureText(text, maxFs);
365
+ if (w <= availLen) return maxFs;
366
+ return Math.max(MIN_LABEL_FS, Math.floor(maxFs * availLen / w));
367
+ }
368
+ function drawCurvedLine(g, defs, pathId, cell, centerR, fs, weight, text, ink) {
369
+ const bottom = isBottomHalf(cell);
370
+ const rPath = bottom ? centerR + fs * 0.32 : centerR - fs * 0.32;
317
371
  const [a0, a1] = bottom ? [cell.endAngle, cell.startAngle] : [cell.startAngle, cell.endAngle];
318
372
  const p0x = Math.sin(a0) * rPath;
319
373
  const p0y = -Math.cos(a0) * rPath;
320
374
  const p1x = Math.sin(a1) * rPath;
321
375
  const p1y = -Math.cos(a1) * rPath;
322
376
  const sweepFlag = bottom ? 0 : 1;
323
- const d = `M ${p0x.toFixed(2)} ${p0y.toFixed(2)} A ${rPath.toFixed(2)} ${rPath.toFixed(2)} 0 0 ${sweepFlag} ${p1x.toFixed(2)} ${p1y.toFixed(2)}`;
377
+ const largeArc = cell.endAngle - cell.startAngle > Math.PI ? 1 : 0;
378
+ const d = `M ${p0x.toFixed(2)} ${p0y.toFixed(2)} A ${rPath.toFixed(2)} ${rPath.toFixed(2)} 0 ${largeArc} ${sweepFlag} ${p1x.toFixed(2)} ${p1y.toFixed(2)}`;
324
379
  defs.append("path").attr("id", pathId).attr("d", d);
325
- g.append("text").attr("class", "dgmo-treemap-label").attr("font-size", fs).attr("font-weight", 600).attr("fill", ink).append("textPath").attr("href", `#${pathId}`).attr("startOffset", "50%").attr("text-anchor", "middle").text(text);
380
+ g.append("text").attr("class", "dgmo-treemap-label").attr("font-size", fs).attr("font-weight", weight).attr("fill", ink).append("textPath").attr("href", `#${pathId}`).attr("startOffset", "50%").attr("text-anchor", "middle").text(text);
381
+ }
382
+ var INK_MIN_CONTRAST = 3;
383
+ function tonedCandidate(h, s, fill, dark) {
384
+ const sat = dark ? Math.min(85, Math.max(s, 55)) : Math.min(72, Math.max(42, s));
385
+ let l = dark ? 34 : 80;
386
+ let ink = hslToHex(h, sat, l);
387
+ for (let i = 0; i < 30 && contrastRatio(ink, fill) < INK_MIN_CONTRAST; i++) {
388
+ l += dark ? -3 : 3;
389
+ if (l <= 3 || l >= 97) break;
390
+ ink = hslToHex(h, sat, l);
391
+ }
392
+ return { ink, ok: contrastRatio(ink, fill) >= INK_MIN_CONTRAST };
393
+ }
394
+ function tonalInk(fill, onLight, onDark) {
395
+ const { h, s } = hexToHSL(fill);
396
+ const dark = tonedCandidate(h, s, fill, true);
397
+ const light = tonedCandidate(h, s, fill, false);
398
+ const preferLight = relativeLuminance(fill) <= 0.45;
399
+ if (dark.ok && light.ok) return preferLight ? light.ink : dark.ink;
400
+ if (dark.ok) return dark.ink;
401
+ if (light.ok) return light.ink;
402
+ return contrastText(fill, onLight, onDark);
326
403
  }
327
404
  function clampFs(base, thickness) {
328
405
  return Math.max(8, Math.min(base, Math.round(thickness * 0.9)));
@@ -344,4 +421,4 @@ export {
344
421
  renderTreemapRadialForExport,
345
422
  renderTreemapRadial
346
423
  };
347
- //# sourceMappingURL=chunk-ULOEATBZ.js.map
424
+ //# sourceMappingURL=chunk-NFFIKVNO.js.map