@diagrammo/dgmo 0.45.0 → 0.47.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 (250) hide show
  1. package/dist/advanced.cjs +31 -25
  2. package/dist/advanced.d.cts +3 -855
  3. package/dist/advanced.d.ts +3 -855
  4. package/dist/advanced.js +541 -70101
  5. package/dist/analyzer-UYKBXAKR.js +15 -0
  6. package/dist/auto.cjs +500 -341
  7. package/dist/auto.css +342 -159
  8. package/dist/auto.d.cts +10 -8
  9. package/dist/auto.d.ts +10 -8
  10. package/dist/auto.js +373 -265
  11. package/dist/auto.mjs +500 -341
  12. package/dist/block.cjs +31 -25
  13. package/dist/block.js +83 -69411
  14. package/dist/calculator-LDYQCDDY.js +11 -0
  15. package/dist/charts-d3-QOZHKTCT.js +25 -0
  16. package/dist/chunk-2DXMZRWJ.js +800 -0
  17. package/dist/chunk-2LACINWN.js +786 -0
  18. package/dist/chunk-33LCUH4H.js +893 -0
  19. package/dist/chunk-3CIOJ5YJ.js +35 -0
  20. package/dist/chunk-3HDBAXF5.js +86 -0
  21. package/dist/chunk-3JLKYGBQ.js +290 -0
  22. package/dist/chunk-3MQQNXPD.js +415 -0
  23. package/dist/chunk-3R5POCTZ.js +967 -0
  24. package/dist/chunk-3SMGIJDD.js +112 -0
  25. package/dist/chunk-44CM72SQ.js +409 -0
  26. package/dist/chunk-4GRI7MEB.js +1604 -0
  27. package/dist/chunk-4OHACBGX.js +606 -0
  28. package/dist/chunk-5DH3KYFH.js +21 -0
  29. package/dist/chunk-5MLYVTYM.js +76 -0
  30. package/dist/chunk-5QXL4NYS.js +553 -0
  31. package/dist/chunk-5WRI5ZAA.js +31 -0
  32. package/dist/chunk-6EK55ART.js +117 -0
  33. package/dist/chunk-6FZYCKXB.js +2065 -0
  34. package/dist/chunk-6HO5ZTXK.js +277 -0
  35. package/dist/chunk-6KFWC4CO.js +7 -0
  36. package/dist/chunk-6MTWIQVO.js +121 -0
  37. package/dist/chunk-6NYWYNBI.js +329 -0
  38. package/dist/chunk-6SM5NJQH.js +620 -0
  39. package/dist/chunk-725LDASD.js +422 -0
  40. package/dist/chunk-76OWZ3BA.js +130 -0
  41. package/dist/chunk-7JEGTRLD.js +338 -0
  42. package/dist/chunk-A44USUV7.js +923 -0
  43. package/dist/chunk-A4GOY3PE.js +25 -0
  44. package/dist/chunk-A4VFQH5G.js +251 -0
  45. package/dist/chunk-AELOBFW5.js +375 -0
  46. package/dist/chunk-AN2MOO5T.js +522 -0
  47. package/dist/chunk-BMR4CIEO.js +41 -0
  48. package/dist/chunk-BS7SV7C3.js +51 -0
  49. package/dist/chunk-BUPDIHML.js +613 -0
  50. package/dist/chunk-BUVJFRPY.js +887 -0
  51. package/dist/chunk-C3Z4DX3V.js +112 -0
  52. package/dist/chunk-CI2G3OEB.js +1818 -0
  53. package/dist/chunk-CKNVO24D.js +54 -0
  54. package/dist/chunk-CUVHQHZ7.js +391 -0
  55. package/dist/chunk-CXK4DZH3.js +114 -0
  56. package/dist/chunk-DKEPS5LH.js +315 -0
  57. package/dist/chunk-DU7W62N5.js +487 -0
  58. package/dist/chunk-DZAQBW35.js +751 -0
  59. package/dist/chunk-EB6FPQUP.js +316 -0
  60. package/dist/chunk-EMS2SK26.js +376 -0
  61. package/dist/chunk-ERLBPDGU.js +510 -0
  62. package/dist/chunk-EVCVDTXE.js +732 -0
  63. package/dist/chunk-FCIIHT24.js +384 -0
  64. package/dist/chunk-FFUN5D66.js +97 -0
  65. package/dist/chunk-FITOLXSX.js +714 -0
  66. package/dist/chunk-FMDSF3OV.js +68 -0
  67. package/dist/chunk-FNB3PNGF.js +410 -0
  68. package/dist/chunk-G2H74XJZ.js +2104 -0
  69. package/dist/chunk-GMR5MFHJ.js +339 -0
  70. package/dist/chunk-H6PI3KJT.js +305 -0
  71. package/dist/chunk-I46X5VUA.js +59 -0
  72. package/dist/chunk-I5IGB56C.js +255 -0
  73. package/dist/chunk-IH6ZMVQ5.js +3950 -0
  74. package/dist/chunk-IJZFN3HM.js +463 -0
  75. package/dist/chunk-IPWPWM6R.js +3079 -0
  76. package/dist/chunk-IYULMRBE.js +23 -0
  77. package/dist/chunk-IZMRON6C.js +167 -0
  78. package/dist/chunk-J5FIXQRT.js +813 -0
  79. package/dist/chunk-JED6ZDEE.js +73 -0
  80. package/dist/chunk-JEUJOX5X.js +136 -0
  81. package/dist/chunk-JM4LEPY3.js +436 -0
  82. package/dist/chunk-L3UHP6TD.js +101 -0
  83. package/dist/chunk-L66GEFB6.js +524 -0
  84. package/dist/chunk-LIOHW36Z.js +469 -0
  85. package/dist/chunk-LP7EC4MI.js +16 -0
  86. package/dist/chunk-MITI6NOL.js +548 -0
  87. package/dist/chunk-MO5YHHMQ.js +168 -0
  88. package/dist/chunk-MZSBFAPJ.js +885 -0
  89. package/dist/chunk-NNAAJVBU.js +9 -0
  90. package/dist/chunk-NOTA6TEI.js +47 -0
  91. package/dist/chunk-NURGB5Z4.js +335 -0
  92. package/dist/chunk-NX4EQS3U.js +1062 -0
  93. package/dist/chunk-NXMESY4J.js +1 -0
  94. package/dist/chunk-OJR3MQYV.js +1458 -0
  95. package/dist/chunk-OURHMODR.js +454 -0
  96. package/dist/chunk-P235SVAH.js +1057 -0
  97. package/dist/chunk-P4RH4OSP.js +1038 -0
  98. package/dist/chunk-P6T66CCZ.js +226 -0
  99. package/dist/chunk-PBAHEPLQ.js +223 -0
  100. package/dist/chunk-PBHE5UG6.js +1530 -0
  101. package/dist/chunk-PDKUANDZ.js +35 -0
  102. package/dist/chunk-PWIHZ6NJ.js +296 -0
  103. package/dist/chunk-QEBUY5NY.js +1685 -0
  104. package/dist/chunk-QLCCJEJI.js +253 -0
  105. package/dist/chunk-QOOUC2J5.js +52 -0
  106. package/dist/chunk-QYTPPDAO.js +402 -0
  107. package/dist/chunk-R3XI2VC7.js +801 -0
  108. package/dist/chunk-RCERWOJR.js +154 -0
  109. package/dist/chunk-RJE5JTVK.js +362 -0
  110. package/dist/chunk-RTLBSQ3G.js +1155 -0
  111. package/dist/chunk-RUNNI6VE.js +448 -0
  112. package/dist/chunk-RVMRZAPB.js +354 -0
  113. package/dist/chunk-RYEGFMUO.js +955 -0
  114. package/dist/chunk-RZCF2VVM.js +528 -0
  115. package/dist/chunk-SML67VPV.js +1025 -0
  116. package/dist/chunk-SQ7IY53Q.js +44 -0
  117. package/dist/chunk-SQAG3UXH.js +161 -0
  118. package/dist/chunk-SRTU6HMQ.js +1851 -0
  119. package/dist/chunk-T2OE3YQB.js +550 -0
  120. package/dist/chunk-T3UBLACL.js +299 -0
  121. package/dist/chunk-TLVIHFRO.js +296 -0
  122. package/dist/chunk-TYS6CSS5.js +52 -0
  123. package/dist/chunk-U6EQI3U6.js +130 -0
  124. package/dist/chunk-UJ4FJLBF.js +86 -0
  125. package/dist/chunk-ULOEATBZ.js +347 -0
  126. package/dist/chunk-UNCCZ3NU.js +127 -0
  127. package/dist/chunk-USZW2HHU.js +197 -0
  128. package/dist/chunk-UWN33VNX.js +1610 -0
  129. package/dist/chunk-UZ7EZW3B.js +40 -0
  130. package/dist/chunk-VOKGH627.js +37 -0
  131. package/dist/chunk-WBRZJOEC.js +204 -0
  132. package/dist/chunk-WCSOJFU3.js +380 -0
  133. package/dist/chunk-WCT3NYCV.js +160 -0
  134. package/dist/chunk-WVAJFAIA.js +529 -0
  135. package/dist/chunk-X5LCYCL5.js +394 -0
  136. package/dist/chunk-XAKEUMEJ.js +1256 -0
  137. package/dist/chunk-Y2ZE3MSG.js +590 -0
  138. package/dist/chunk-Y3J7VR52.js +646 -0
  139. package/dist/chunk-Y5QGVTVC.js +33 -0
  140. package/dist/chunk-YAA6IID3.js +548 -0
  141. package/dist/chunk-YGJTDXVR.js +692 -0
  142. package/dist/chunk-YRYKTYMQ.js +186 -0
  143. package/dist/chunk-YYVTBZZC.js +61 -0
  144. package/dist/chunk-Z5CGSFJB.js +647 -0
  145. package/dist/chunk-Z72XRXD4.js +787 -0
  146. package/dist/chunk-ZGR7ULFJ.js +978 -0
  147. package/dist/chunk-ZJEL4H2R.js +851 -0
  148. package/dist/chunk-ZO27FGJS.js +554 -0
  149. package/dist/cli.cjs +112 -112
  150. package/dist/collapse-CLPJD2RL.js +11 -0
  151. package/dist/collapse-SLINJQW6.js +9 -0
  152. package/dist/collapse-ZWUFFCK2.js +9 -0
  153. package/dist/compute-G55RG53N.js +8 -0
  154. package/dist/dgmo-router-DZCIDUO5.js +73 -0
  155. package/dist/dimensions-J3FHIMJ6.js +22 -0
  156. package/dist/element.cjs +492 -325
  157. package/dist/element.js +367 -259
  158. package/dist/element.mjs +492 -325
  159. package/dist/flowchart-parser-ZNSKIBVR.js +21 -0
  160. package/dist/flowchart-renderer-ZAEOL4DX.js +35 -0
  161. package/dist/index.cjs +34 -28
  162. package/dist/index.d.cts +3 -469
  163. package/dist/index.d.ts +3 -469
  164. package/dist/index.js +137 -69679
  165. package/dist/layout-46N4JJYK.js +17 -0
  166. package/dist/layout-5RA6QWR6.js +26 -0
  167. package/dist/layout-5T6RH5M6.js +14 -0
  168. package/dist/layout-7QXCNOVS.js +13 -0
  169. package/dist/layout-EE6GE46Y.js +17 -0
  170. package/dist/layout-G23F7LDH.js +9 -0
  171. package/dist/layout-HRBZPFCN.js +23 -0
  172. package/dist/layout-HWDSRX5E.js +20 -0
  173. package/dist/layout-HYZPWAK5.js +18 -0
  174. package/dist/layout-N76NR4ZO.js +19 -0
  175. package/dist/layout-OB3RI63S.js +14 -0
  176. package/dist/layout-S2QBYSK2.js +15 -0
  177. package/dist/layout-UM5F4DJB.js +15 -0
  178. package/dist/layout-search-OYV77HHS.js +1655 -0
  179. package/dist/load-data-EHDDZ5ZS.js +8 -0
  180. package/dist/palettes-PRJ2RI6D.js +56 -0
  181. package/dist/parser-2MFP2H2E.js +11 -0
  182. package/dist/parser-3STE62GB.js +21 -0
  183. package/dist/parser-4FL2CMDG.js +18 -0
  184. package/dist/parser-4OGOBJJ4.js +13 -0
  185. package/dist/parser-6BTRLKRZ.js +15 -0
  186. package/dist/parser-AQETEVRW.js +21 -0
  187. package/dist/parser-CFZD5IBL.js +12 -0
  188. package/dist/parser-FUSKFGZN.js +16 -0
  189. package/dist/parser-I6KXEYFK.js +13 -0
  190. package/dist/parser-IXSZZQHY.js +18 -0
  191. package/dist/parser-JAL2HD4I.js +13 -0
  192. package/dist/parser-KNSQSKQO.js +20 -0
  193. package/dist/parser-N5O4IHUN.js +13 -0
  194. package/dist/parser-NGU3ETO6.js +16 -0
  195. package/dist/parser-NRAI6O25.js +19 -0
  196. package/dist/parser-O5J4VBII.js +11 -0
  197. package/dist/parser-OV7NOBW6.js +21 -0
  198. package/dist/parser-PQ3POX45.js +23 -0
  199. package/dist/parser-TFZFBVWN.js +11 -0
  200. package/dist/parser-TRTHDFPP.js +18 -0
  201. package/dist/parser-VQP2UJ6W.js +11 -0
  202. package/dist/parser-XDVELHRK.js +13 -0
  203. package/dist/parser-XKRP7QKP.js +11 -0
  204. package/dist/parser-Y6WTBU76.js +14 -0
  205. package/dist/parser-ZSDPZYQP.js +12 -0
  206. package/dist/renderer-2XQQQ6QR.js +28 -0
  207. package/dist/renderer-5NDVNDAZ.js +26 -0
  208. package/dist/renderer-6EEZHMH4.js +26 -0
  209. package/dist/renderer-6W5462RB.js +43 -0
  210. package/dist/renderer-7MVLWWQD.js +22 -0
  211. package/dist/renderer-AWWAF6XD.js +33 -0
  212. package/dist/renderer-BYCNMBF7.js +34 -0
  213. package/dist/renderer-CLJHQPBJ.js +29 -0
  214. package/dist/renderer-GHPZMFU2.js +15 -0
  215. package/dist/renderer-JGBKUCZD.js +16 -0
  216. package/dist/renderer-KQB7UGDS.js +19 -0
  217. package/dist/renderer-PGX2TKVS.js +24 -0
  218. package/dist/renderer-QIWVHWZO.js +15 -0
  219. package/dist/renderer-RPOA5YPZ.js +35 -0
  220. package/dist/renderer-SMIBCRVB.js +24 -0
  221. package/dist/renderer-T7YKC5VP.js +28 -0
  222. package/dist/renderer-TOCOVLHS.js +37 -0
  223. package/dist/renderer-UWA5XS74.js +39 -0
  224. package/dist/renderer-VACVQYML.js +25 -0
  225. package/dist/renderer-W4M6QLIJ.js +37 -0
  226. package/dist/renderer-WZRREQ2P.js +23 -0
  227. package/dist/renderer-YY2OSF6E.js +27 -0
  228. package/dist/renderer-Z7I3W2PP.js +24 -0
  229. package/dist/renderer-ZGNTUWC4.js +22 -0
  230. package/dist/renderer-ZTR3DER3.js +19 -0
  231. package/dist/renderer-radial-C32GPJQ7.js +21 -0
  232. package/dist/resolver-NOAA7ID7.js +13 -0
  233. package/dist/state-collapse-HCGD6IVJ.js +8 -0
  234. package/dist/state-parser-Z2V23ATR.js +18 -0
  235. package/dist/state-renderer-RFYHSP4K.js +34 -0
  236. package/dist/themes-1-CuKpeH.d.cts +908 -0
  237. package/dist/themes-1-CuKpeH.d.ts +908 -0
  238. package/package.json +1 -1
  239. package/src/auto/index.ts +55 -57
  240. package/src/auto/shared.ts +142 -142
  241. package/src/auto/styles.ts +44 -199
  242. package/src/c4/renderer.ts +2 -2
  243. package/src/element/index.ts +29 -21
  244. package/src/infra/renderer.ts +1 -1
  245. package/src/render.ts +34 -14
  246. package/src/sitemap/renderer.ts +1 -1
  247. package/src/timeline/renderer.ts +1 -1
  248. package/src/utils/hover-styles.ts +6 -1
  249. package/src/utils/legend-d3.ts +1 -4
  250. package/src/utils/legend-svg.ts +1 -1
@@ -0,0 +1,73 @@
1
+ import {
2
+ placeNotes
3
+ } from "./chunk-6EK55ART.js";
4
+ import {
5
+ noteBoxSize
6
+ } from "./chunk-TYS6CSS5.js";
7
+
8
+ // src/utils/notes/build.ts
9
+ function buildPlacedNotes(anchors, noteByNode, direction, collapsedNotes) {
10
+ const placed = /* @__PURE__ */ new Map();
11
+ if (noteByNode.size === 0) return placed;
12
+ const geoms = /* @__PURE__ */ new Map();
13
+ const requests = [];
14
+ for (const a of anchors) {
15
+ const note = noteByNode.get(a.id);
16
+ if (!note) continue;
17
+ const size = noteBoxSize(note.body);
18
+ geoms.set(a.id, {
19
+ noteW: size.width,
20
+ noteH: size.height,
21
+ ...note.color && { color: note.color },
22
+ lines: size.lines,
23
+ lineNumber: note.lineNumber,
24
+ endLineNumber: note.endLineNumber
25
+ });
26
+ requests.push({
27
+ key: a.id,
28
+ node: { x: a.x, y: a.y, width: a.width, height: a.height },
29
+ noteW: size.width,
30
+ noteH: size.height,
31
+ collapsed: collapsedNotes?.has(note.lineNumber) ?? false
32
+ });
33
+ }
34
+ const placements = placeNotes(
35
+ anchors.map((a) => ({ x: a.x, y: a.y, width: a.width, height: a.height })),
36
+ requests,
37
+ direction
38
+ );
39
+ for (const [id, g] of geoms) {
40
+ const p = placements.get(id);
41
+ placed.set(
42
+ id,
43
+ p.collapsed ? {
44
+ x: 0,
45
+ y: 0,
46
+ width: 0,
47
+ height: 0,
48
+ side: "right",
49
+ ...g.color && { color: g.color },
50
+ lines: [],
51
+ lineNumber: g.lineNumber,
52
+ endLineNumber: g.endLineNumber,
53
+ collapsed: true
54
+ } : {
55
+ x: p.x,
56
+ y: p.y,
57
+ width: g.noteW,
58
+ height: g.noteH,
59
+ side: p.side,
60
+ ...g.color && { color: g.color },
61
+ lines: g.lines,
62
+ lineNumber: g.lineNumber,
63
+ endLineNumber: g.endLineNumber
64
+ }
65
+ );
66
+ }
67
+ return placed;
68
+ }
69
+
70
+ export {
71
+ buildPlacedNotes
72
+ };
73
+ //# sourceMappingURL=chunk-JED6ZDEE.js.map
@@ -0,0 +1,136 @@
1
+ import {
2
+ NOTE_BULLET_INDENT,
3
+ NOTE_FOLD,
4
+ NOTE_FONT_SIZE,
5
+ NOTE_LINE_H,
6
+ NOTE_PAD_H,
7
+ NOTE_PAD_V
8
+ } from "./chunk-5DH3KYFH.js";
9
+ import {
10
+ renderInlineText
11
+ } from "./chunk-3HDBAXF5.js";
12
+ import {
13
+ mix
14
+ } from "./chunk-P6T66CCZ.js";
15
+
16
+ // src/utils/note-box/svg.ts
17
+ var NOTE_STROKE_WIDTH = 0.6;
18
+ var NOTE_STROKE_OPACITY = 0.6;
19
+ function renderNoteConnector(parent, x1, y1, x2, y2, palette) {
20
+ parent.append("line").attr("x1", x1).attr("y1", y1).attr("x2", x2).attr("y2", y2).attr("stroke", palette.textMuted).attr("stroke-width", NOTE_STROKE_WIDTH).attr("stroke-opacity", NOTE_STROKE_OPACITY).attr("class", "note-connector").style("pointer-events", "none");
21
+ }
22
+ function noteConnectorPoints(node, note) {
23
+ const clampX = Math.max(note.x, Math.min(0, note.x + note.width));
24
+ switch (note.side) {
25
+ case "right":
26
+ return [node.width / 2, 0, note.x, note.y + note.height / 2];
27
+ case "left":
28
+ return [
29
+ -node.width / 2,
30
+ 0,
31
+ note.x + note.width,
32
+ note.y + note.height / 2
33
+ ];
34
+ case "below":
35
+ return [clampX, node.height / 2, clampX, note.y];
36
+ case "above":
37
+ default:
38
+ return [clampX, -node.height / 2, clampX, note.y + note.height];
39
+ }
40
+ }
41
+ function noteAccent(palette, color) {
42
+ return color ?? palette.colors.yellow;
43
+ }
44
+ function noteBoxFill(palette, isDark, color) {
45
+ const accent = noteAccent(palette, color);
46
+ return isDark ? mix(accent, palette.bg, 24) : mix(accent, palette.bg, 16);
47
+ }
48
+ function renderNoteBox(parent, rect, lines, palette, opts) {
49
+ const fontSize = opts.fontSize ?? NOTE_FONT_SIZE;
50
+ const interactive = opts.interactive ?? false;
51
+ const { x, y, width, height } = rect;
52
+ const fill = noteBoxFill(palette, opts.isDark, opts.color);
53
+ const accent = noteAccent(palette, opts.color);
54
+ const noteG = parent.append("g").attr("class", "note").attr("data-note-toggle", "");
55
+ if (opts.lineNumber !== void 0) {
56
+ noteG.attr("data-line-number", String(opts.lineNumber));
57
+ }
58
+ if (opts.endLineNumber !== void 0) {
59
+ noteG.attr("data-line-end", String(opts.endLineNumber));
60
+ }
61
+ if (interactive) {
62
+ noteG.style("cursor", "pointer").attr("role", "button").attr("tabindex", "0").attr("aria-expanded", "true").attr("aria-label", "Collapse note");
63
+ }
64
+ const boxPath = noteG.append("path").attr(
65
+ "d",
66
+ [
67
+ `M ${x} ${y}`,
68
+ `L ${x + width - NOTE_FOLD} ${y}`,
69
+ `L ${x + width} ${y + NOTE_FOLD}`,
70
+ `L ${x + width} ${y + height}`,
71
+ `L ${x} ${y + height}`,
72
+ "Z"
73
+ ].join(" ")
74
+ ).attr("fill", fill).attr("stroke", accent).attr("stroke-width", NOTE_STROKE_WIDTH).attr("stroke-opacity", NOTE_STROKE_OPACITY).attr("class", "note-box");
75
+ if (!interactive) boxPath.style("pointer-events", "none");
76
+ noteG.append("path").attr(
77
+ "d",
78
+ [
79
+ `M ${x + width - NOTE_FOLD} ${y}`,
80
+ `L ${x + width - NOTE_FOLD} ${y + NOTE_FOLD}`,
81
+ `L ${x + width} ${y + NOTE_FOLD}`
82
+ ].join(" ")
83
+ ).attr("fill", "none").attr("stroke", accent).attr("stroke-width", NOTE_STROKE_WIDTH).attr("stroke-opacity", NOTE_STROKE_OPACITY).attr("class", "note-fold").style("pointer-events", "none");
84
+ lines.forEach((line, li) => {
85
+ const textY = y + NOTE_PAD_V + (li + 1) * NOTE_LINE_H - 3;
86
+ const indent = line.kind === "plain" ? 0 : NOTE_BULLET_INDENT;
87
+ if (line.kind === "bullet-first") {
88
+ noteG.append("text").attr("x", x + NOTE_PAD_H).attr("y", textY).attr("fill", palette.text).attr("font-size", fontSize).text("\u2022");
89
+ }
90
+ const textEl = noteG.append("text").attr("x", x + NOTE_PAD_H + indent).attr("y", textY).attr("fill", palette.text).attr("font-size", fontSize).attr("class", "note-text");
91
+ renderInlineText(textEl, line.text, palette, fontSize);
92
+ });
93
+ return noteG;
94
+ }
95
+ var NOTE_BADGE_RADIUS = 7;
96
+ var NOTE_BADGE_OPACITY = 0.6;
97
+ function renderNoteBadge(parent, center, palette, opts) {
98
+ const fill = noteBoxFill(palette, opts.isDark, opts.color);
99
+ const accent = noteAccent(palette, opts.color);
100
+ const g = parent.append("g").attr("class", "note note-badge").attr("data-note-toggle", "").attr("transform", `translate(${center.x}, ${center.y})`).attr("opacity", NOTE_BADGE_OPACITY).style("cursor", "pointer").attr("role", "button").attr("tabindex", "0").attr("aria-expanded", "false").attr("aria-label", "Expand note");
101
+ if (opts.lineNumber !== void 0) {
102
+ g.attr("data-line-number", String(opts.lineNumber));
103
+ }
104
+ if (opts.endLineNumber !== void 0) {
105
+ g.attr("data-line-end", String(opts.endLineNumber));
106
+ }
107
+ g.append("path").attr(
108
+ "d",
109
+ [
110
+ "M -6.5 -4",
111
+ "Q -6.5 -6 -4.5 -6",
112
+ "L 4.5 -6",
113
+ "Q 6.5 -6 6.5 -4",
114
+ "L 6.5 1",
115
+ "Q 6.5 3 4.5 3",
116
+ "L -1 3",
117
+ "L -4 6",
118
+ "L -2.5 3",
119
+ "L -4.5 3",
120
+ "Q -6.5 3 -6.5 1",
121
+ "Z"
122
+ ].join(" ")
123
+ ).attr("fill", fill).attr("stroke", accent).attr("stroke-width", 0.55).attr("class", "note-badge-bubble");
124
+ g.append("line").attr("x1", -3.5).attr("y1", -3).attr("x2", 3.5).attr("y2", -3).attr("stroke", palette.textMuted).attr("stroke-width", 0.75).style("pointer-events", "none");
125
+ g.append("line").attr("x1", -3.5).attr("y1", -0.5).attr("x2", 1.5).attr("y2", -0.5).attr("stroke", palette.textMuted).attr("stroke-width", 0.75).style("pointer-events", "none");
126
+ return g;
127
+ }
128
+
129
+ export {
130
+ renderNoteConnector,
131
+ noteConnectorPoints,
132
+ renderNoteBox,
133
+ NOTE_BADGE_RADIUS,
134
+ renderNoteBadge
135
+ };
136
+ //# sourceMappingURL=chunk-JEUJOX5X.js.map
@@ -0,0 +1,436 @@
1
+ import {
2
+ renderInlineText
3
+ } from "./chunk-3HDBAXF5.js";
4
+ import {
5
+ wrapDescriptionLines
6
+ } from "./chunk-BMR4CIEO.js";
7
+ import {
8
+ ScaleContext
9
+ } from "./chunk-YYVTBZZC.js";
10
+ import {
11
+ TITLE_FONT_SIZE,
12
+ TITLE_FONT_WEIGHT,
13
+ TITLE_Y
14
+ } from "./chunk-A4GOY3PE.js";
15
+ import {
16
+ FONT_FAMILY
17
+ } from "./chunk-6KFWC4CO.js";
18
+ import {
19
+ CHAR_WIDTH_RATIO,
20
+ measureText
21
+ } from "./chunk-WCT3NYCV.js";
22
+ import {
23
+ contrastText,
24
+ getSeriesColors,
25
+ shapeFill
26
+ } from "./chunk-P6T66CCZ.js";
27
+ import {
28
+ resolveColor
29
+ } from "./chunk-TLVIHFRO.js";
30
+
31
+ // src/pyramid/renderer.ts
32
+ import * as d3Selection from "d3-selection";
33
+ var TITLE_AREA_HEIGHT = 50;
34
+ var H_MARGIN_FRAC = 0.03;
35
+ var V_MARGIN = 16;
36
+ var BASE_WIDTH_FRAC_NO_DESC = 0.78;
37
+ var PYRAMID_SHARE_WITH_DESC = 0.58;
38
+ var PYRAMID_SHARE_ALTERNATE = 0.42;
39
+ var PITCH_RATIO = 0.85;
40
+ var DESC_GAP = 28;
41
+ var DESC_ACCENT_WIDTH = 3;
42
+ var DESC_ACCENT_GAP = 12;
43
+ var BULLET_BODY_INDENT = 10;
44
+ var LABEL_FONT_MIN = 12;
45
+ var LABEL_FONT_MAX = 22;
46
+ var DESC_FONT_MIN = 11;
47
+ var DESC_FONT_MAX = 15;
48
+ function renderPyramid(container, parsed, palette, isDark, onClickItem, exportDims) {
49
+ if (parsed.layers.length === 0) return;
50
+ d3Selection.select(container).selectAll(":not([data-d3-tooltip])").remove();
51
+ const width = exportDims?.width ?? container.clientWidth;
52
+ const height = exportDims?.height ?? container.clientHeight;
53
+ if (width <= 0 || height <= 0) return;
54
+ const idealWidth = width;
55
+ const sctx = exportDims ? ScaleContext.identity() : ScaleContext.from(width, idealWidth);
56
+ const sTitleFontSize = sctx.text(TITLE_FONT_SIZE);
57
+ const sTitleY = sctx.structural(TITLE_Y);
58
+ const sTitleAreaHeight = sctx.structural(TITLE_AREA_HEIGHT);
59
+ const sVMargin = sctx.aesthetic(V_MARGIN);
60
+ const hasAnyDescription = parsed.layers.some((l) => l.description.length > 0);
61
+ const showTitle = !!parsed.title && parsed.options["no-title"] !== "on";
62
+ const titleH = showTitle ? sTitleAreaHeight : 0;
63
+ const bodyTop = titleH + sVMargin;
64
+ const bodyBottom = height - sVMargin;
65
+ const bodyHeight = Math.max(60, bodyBottom - bodyTop);
66
+ const sideMargin = width * H_MARGIN_FRAC;
67
+ const usableWidth = width - sideMargin * 2;
68
+ const N = parsed.layers.length;
69
+ const singleProbe = computeLayout({
70
+ width,
71
+ usableWidth,
72
+ sideMargin,
73
+ bodyTop,
74
+ bodyHeight,
75
+ layers: parsed.layers,
76
+ hasDescription: hasAnyDescription,
77
+ alternate: false
78
+ });
79
+ const anyOverflow = singleProbe.wraps.some((w) => w.overflows);
80
+ const useAlternate = anyOverflow && hasAnyDescription && N >= 2;
81
+ const layout = useAlternate ? computeLayout({
82
+ width,
83
+ usableWidth,
84
+ sideMargin,
85
+ bodyTop,
86
+ bodyHeight,
87
+ layers: parsed.layers,
88
+ hasDescription: true,
89
+ alternate: true
90
+ }) : singleProbe;
91
+ const svg = d3Selection.select(container).append("svg").attr("width", width).attr("height", height).attr("viewBox", `0 0 ${width} ${height}`).attr("preserveAspectRatio", "xMidYMin meet").attr("xmlns", "http://www.w3.org/2000/svg").style("font-family", FONT_FAMILY);
92
+ if (sctx.isBelowFloor) {
93
+ svg.attr("width", "100%");
94
+ }
95
+ svg.append("style").text(
96
+ ".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}"
97
+ );
98
+ svg.append("rect").attr("width", width).attr("height", height).attr("fill", palette.bg);
99
+ if (showTitle) {
100
+ const titleText = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", sTitleY).attr("text-anchor", "middle").attr("fill", palette.text).attr("font-family", FONT_FAMILY).attr("font-size", sTitleFontSize).attr("font-weight", TITLE_FONT_WEIGHT).attr("data-line-number", parsed.titleLineNumber).text(parsed.title).style("cursor", onClickItem ? "pointer" : "default");
101
+ if (onClickItem) {
102
+ titleText.on("click", () => onClickItem(parsed.titleLineNumber));
103
+ }
104
+ }
105
+ const seriesColors = getSeriesColors(palette);
106
+ const resolveSolid = (layer, i) => {
107
+ if (layer.color) {
108
+ const named = resolveColor(layer.color, palette);
109
+ if (named) return named;
110
+ }
111
+ return seriesColors[i % seriesColors.length];
112
+ };
113
+ const diagramG = svg.append("g").attr("class", "pyramid-body");
114
+ for (let i = 0; i < N; i++) {
115
+ const layer = parsed.layers[i];
116
+ const topEdgeY = layout.pyramidTop + i * layout.layerH;
117
+ const botEdgeY = topEdgeY + layout.layerH;
118
+ const topHalf = halfWidthAt(i, N, layout.baseWidth, parsed.inverted);
119
+ const botHalf = halfWidthAt(i + 1, N, layout.baseWidth, parsed.inverted);
120
+ const polyPoints = [
121
+ [layout.pyramidCx - topHalf, topEdgeY],
122
+ [layout.pyramidCx + topHalf, topEdgeY],
123
+ [layout.pyramidCx + botHalf, botEdgeY],
124
+ [layout.pyramidCx - botHalf, botEdgeY]
125
+ ].map((p) => `${p[0]},${p[1]}`).join(" ");
126
+ const solidColor = resolveSolid(layer, i);
127
+ const fillColor = shapeFill(palette, solidColor, isDark, {
128
+ solid: parsed.options["solid-fill"] === "on"
129
+ });
130
+ const layerG = diagramG.append("g").attr("class", "pyramid-layer").attr("data-line-number", layer.lineNumber);
131
+ if (onClickItem) {
132
+ const ln = layer.lineNumber;
133
+ layerG.style("cursor", "pointer").on("click", () => onClickItem(ln));
134
+ }
135
+ layerG.append("polygon").attr("points", polyPoints).attr("fill", fillColor).attr("stroke", solidColor).attr("stroke-width", 2);
136
+ const midY = (topEdgeY + botEdgeY) / 2;
137
+ const textColor = contrastText(
138
+ fillColor,
139
+ palette.textOnFillLight,
140
+ palette.textOnFillDark
141
+ );
142
+ const labelFitsInside = Math.min(topHalf, botHalf) * 2 > measureText(layer.label, layout.labelFont);
143
+ const haloColor = textColor === palette.textOnFillLight ? palette.textOnFillDark : palette.textOnFillLight;
144
+ const labelText = layerG.append("text").attr("x", layout.pyramidCx).attr("y", midY).attr("dy", "0.35em").attr("text-anchor", "middle").attr("fill", textColor).attr("font-family", FONT_FAMILY).attr("font-size", layout.labelFont).attr("font-weight", 600);
145
+ if (!labelFitsInside) {
146
+ labelText.attr("paint-order", "stroke fill").attr("stroke", haloColor).attr("stroke-width", 3).attr("stroke-linejoin", "round").attr("stroke-opacity", 0.6);
147
+ }
148
+ renderInlineText(labelText, layer.label, palette);
149
+ if (layer.description.length > 0) {
150
+ const side = useAlternate ? i % 2 === 0 ? "right" : "left" : "right";
151
+ const wrap = layout.wraps[i];
152
+ renderLayerDescriptions(
153
+ diagramG,
154
+ layer,
155
+ side,
156
+ wrap,
157
+ layout,
158
+ midY,
159
+ solidColor,
160
+ palette,
161
+ titleH + V_MARGIN,
162
+ height - V_MARGIN,
163
+ onClickItem
164
+ );
165
+ }
166
+ }
167
+ }
168
+ function renderPyramidForExport(container, parsed, palette, isDark, exportDims) {
169
+ renderPyramid(container, parsed, palette, isDark, void 0, exportDims);
170
+ }
171
+ function computeLayout(input) {
172
+ const {
173
+ width,
174
+ usableWidth,
175
+ sideMargin,
176
+ bodyTop,
177
+ bodyHeight,
178
+ layers,
179
+ hasDescription,
180
+ alternate
181
+ } = input;
182
+ const N = layers.length;
183
+ const pyramidShareFrac = hasDescription ? alternate ? PYRAMID_SHARE_ALTERNATE : PYRAMID_SHARE_WITH_DESC : BASE_WIDTH_FRAC_NO_DESC;
184
+ const pyramidBandWidth = usableWidth * pyramidShareFrac;
185
+ const maxBaseByHeight = bodyHeight / PITCH_RATIO;
186
+ const baseWidth = Math.min(pyramidBandWidth, maxBaseByHeight);
187
+ const pyramidH = baseWidth * PITCH_RATIO;
188
+ let pyramidCx;
189
+ if (!hasDescription) {
190
+ pyramidCx = width / 2;
191
+ } else if (alternate) {
192
+ pyramidCx = width / 2;
193
+ } else {
194
+ pyramidCx = sideMargin + pyramidBandWidth / 2;
195
+ }
196
+ const pyramidTop = bodyTop + (bodyHeight - pyramidH) / 2;
197
+ const layerH = pyramidH / N;
198
+ const labelFont = clamp(
199
+ Math.round(layerH * 0.38),
200
+ LABEL_FONT_MIN,
201
+ LABEL_FONT_MAX
202
+ );
203
+ const descFont = clamp(
204
+ Math.round(layerH * 0.22),
205
+ DESC_FONT_MIN,
206
+ DESC_FONT_MAX
207
+ );
208
+ const descLineHeight = Math.round(descFont * 1.35);
209
+ const pyramidRightEdge = pyramidCx + baseWidth / 2;
210
+ const pyramidLeftEdge = pyramidCx - baseWidth / 2;
211
+ const rightAccentX = pyramidRightEdge + DESC_GAP;
212
+ const rightTextX = rightAccentX + DESC_ACCENT_WIDTH + DESC_ACCENT_GAP;
213
+ const rightTextWidth = Math.max(80, width - sideMargin - rightTextX);
214
+ const leftAccentX = pyramidLeftEdge - DESC_GAP - DESC_ACCENT_WIDTH;
215
+ const leftTextWidth = Math.max(
216
+ 80,
217
+ leftAccentX - DESC_ACCENT_GAP - sideMargin
218
+ );
219
+ const leftTextX = sideMargin;
220
+ const wraps = layers.map((layer, i) => {
221
+ if (layer.description.length === 0) {
222
+ return { allLines: [], overflows: false, shortLineCount: 0 };
223
+ }
224
+ const side = alternate ? i % 2 === 0 ? "right" : "left" : "right";
225
+ const colWidth = side === "right" ? rightTextWidth : leftTextWidth;
226
+ const wrapped = wrapDescription(layer.description, colWidth, descFont);
227
+ const bandCap = Math.max(1, Math.floor(layerH / descLineHeight) - 0);
228
+ const overflows = wrapped.length > bandCap;
229
+ const shortLineCount = overflows ? bandCap : wrapped.length;
230
+ return { allLines: wrapped, overflows, shortLineCount };
231
+ });
232
+ return {
233
+ alternate,
234
+ baseWidth,
235
+ pyramidCx,
236
+ pyramidTop,
237
+ pyramidH,
238
+ layerH,
239
+ labelFont,
240
+ descFont,
241
+ descLineHeight,
242
+ rightTextX,
243
+ rightTextWidth,
244
+ leftTextX,
245
+ leftTextWidth,
246
+ rightAccentX,
247
+ leftAccentX,
248
+ wraps
249
+ };
250
+ }
251
+ function halfWidthAt(edgeIdx, n, baseWidth, inverted) {
252
+ const topNarrow = !inverted;
253
+ const frac = topNarrow ? edgeIdx / n : (n - edgeIdx) / n;
254
+ return frac * baseWidth / 2;
255
+ }
256
+ function renderLayerDescriptions(parentG, layer, side, wrap, layout, midY, accentColor, palette, topBound, bottomBound, onClickItem) {
257
+ const { descFont, descLineHeight } = layout;
258
+ const accentX = side === "right" ? layout.rightAccentX : layout.leftAccentX;
259
+ const textX = side === "right" ? layout.rightTextX : layout.leftTextX;
260
+ const textAnchor = side === "right" ? "start" : "end";
261
+ const textLineX = side === "right" ? textX : layout.leftAccentX - DESC_ACCENT_GAP;
262
+ const bulletColRightEdge = layout.leftAccentX - DESC_ACCENT_GAP;
263
+ const computeBulletColLeftX = (lines) => {
264
+ if (side === "right") return layout.rightTextX;
265
+ let maxBodyW = 0;
266
+ for (const l of lines) {
267
+ if (l.kind === "bullet-first" || l.kind === "bullet-cont") {
268
+ maxBodyW = Math.max(maxBodyW, measureText(l.text, descFont));
269
+ }
270
+ }
271
+ return bulletColRightEdge - maxBodyW - BULLET_BODY_INDENT;
272
+ };
273
+ const availableH = bottomBound - topBound;
274
+ const fullMaxLines = Math.max(1, Math.floor(availableH / descLineHeight));
275
+ const fullLines = truncateWithEllipsis(wrap.allLines, fullMaxLines);
276
+ if (!wrap.overflows) {
277
+ renderDescriptionVariant({
278
+ parentG,
279
+ layer,
280
+ lines: wrap.allLines,
281
+ className: "pyramid-desc",
282
+ accentX,
283
+ accentColor,
284
+ textX: textLineX,
285
+ textAnchor,
286
+ side,
287
+ bulletColLeftX: computeBulletColLeftX(wrap.allLines),
288
+ midY,
289
+ descFont,
290
+ descLineHeight,
291
+ palette,
292
+ topBound,
293
+ bottomBound,
294
+ ...onClickItem !== void 0 && { onClickItem },
295
+ variant: "short"
296
+ });
297
+ return;
298
+ }
299
+ const shortLines = buildShortLines(wrap);
300
+ renderDescriptionVariant({
301
+ parentG,
302
+ layer,
303
+ lines: shortLines,
304
+ className: "pyramid-desc pyramid-desc-short",
305
+ accentX,
306
+ accentColor,
307
+ textX: textLineX,
308
+ textAnchor,
309
+ side,
310
+ bulletColLeftX: computeBulletColLeftX(shortLines),
311
+ midY,
312
+ descFont,
313
+ descLineHeight,
314
+ palette,
315
+ topBound,
316
+ bottomBound,
317
+ ...onClickItem !== void 0 && { onClickItem },
318
+ variant: "short"
319
+ });
320
+ renderDescriptionVariant({
321
+ parentG,
322
+ layer,
323
+ lines: fullLines,
324
+ className: "pyramid-desc pyramid-desc-full",
325
+ accentX,
326
+ accentColor,
327
+ textX: textLineX,
328
+ textAnchor,
329
+ side,
330
+ bulletColLeftX: computeBulletColLeftX(fullLines),
331
+ midY,
332
+ descFont,
333
+ descLineHeight,
334
+ palette,
335
+ topBound,
336
+ bottomBound,
337
+ ...onClickItem !== void 0 && { onClickItem },
338
+ variant: "full"
339
+ });
340
+ }
341
+ function truncateWithEllipsis(lines, maxLines) {
342
+ if (lines.length <= maxLines) return lines.slice();
343
+ const visible = lines.slice(0, maxLines);
344
+ if (visible.length === 0) return visible;
345
+ const last = visible[visible.length - 1];
346
+ visible[visible.length - 1] = {
347
+ ...last,
348
+ text: last.text.endsWith("\u2026") ? last.text : `${last.text} \u2026`
349
+ };
350
+ return visible;
351
+ }
352
+ function buildShortLines(wrap) {
353
+ if (!wrap.overflows) return wrap.allLines.slice();
354
+ const visible = wrap.allLines.slice(0, wrap.shortLineCount);
355
+ if (visible.length === 0) return [];
356
+ const last = visible[visible.length - 1];
357
+ visible[visible.length - 1] = {
358
+ ...last,
359
+ text: last.text.endsWith("\u2026") ? last.text : `${last.text} \u2026`
360
+ };
361
+ return visible;
362
+ }
363
+ function renderDescriptionVariant(args) {
364
+ const {
365
+ parentG,
366
+ layer,
367
+ lines,
368
+ className,
369
+ accentX,
370
+ accentColor,
371
+ textX,
372
+ textAnchor,
373
+ bulletColLeftX,
374
+ midY,
375
+ descFont,
376
+ descLineHeight,
377
+ palette,
378
+ topBound,
379
+ bottomBound,
380
+ onClickItem,
381
+ variant
382
+ } = args;
383
+ if (lines.length === 0) return;
384
+ const totalH = lines.length * descLineHeight;
385
+ let startY = midY - totalH / 2 + descLineHeight / 2;
386
+ const accentPad = Math.max(4, Math.round(descFont * 0.3));
387
+ const blockTop = startY - descLineHeight / 2 - accentPad;
388
+ const blockBottom = startY + (lines.length - 1) * descLineHeight + descLineHeight / 2 + accentPad;
389
+ let shift = 0;
390
+ if (blockTop < topBound) shift = topBound - blockTop;
391
+ else if (blockBottom > bottomBound) shift = bottomBound - blockBottom;
392
+ startY += shift;
393
+ const accentTop = startY - descLineHeight / 2 - accentPad;
394
+ const accentH = totalH + accentPad * 2;
395
+ const descG = parentG.append("g").attr("class", className).attr("data-line-number", layer.lineNumber).attr("data-variant", variant);
396
+ if (onClickItem) {
397
+ const ln = layer.lineNumber;
398
+ descG.style("cursor", "pointer").on("click", () => onClickItem(ln));
399
+ }
400
+ descG.append("rect").attr("x", accentX).attr("y", accentTop).attr("width", DESC_ACCENT_WIDTH).attr("height", accentH).attr("rx", DESC_ACCENT_WIDTH / 2).attr("fill", accentColor);
401
+ for (let j = 0; j < lines.length; j++) {
402
+ const line = lines[j];
403
+ const y = startY + j * descLineHeight;
404
+ const isBullet = line.kind === "bullet-first" || line.kind === "bullet-cont";
405
+ if (line.kind === "bullet-first") {
406
+ descG.append("text").attr("x", bulletColLeftX).attr("y", y).attr("dy", "0.35em").attr("text-anchor", "start").attr("fill", palette.text).attr("font-family", FONT_FAMILY).attr("font-size", descFont).attr("font-weight", j === 0 ? 500 : 400).text("\u2022");
407
+ }
408
+ const t = descG.append("text").attr("x", isBullet ? bulletColLeftX + BULLET_BODY_INDENT : textX).attr("y", y).attr("dy", "0.35em").attr("text-anchor", isBullet ? "start" : textAnchor).attr("fill", palette.text).attr("font-family", FONT_FAMILY).attr("font-size", descFont).attr("font-weight", j === 0 ? 500 : 400);
409
+ renderInlineText(t, line.text, palette);
410
+ }
411
+ }
412
+ function wrapDescription(lines, maxWidth, fontSize) {
413
+ const avgCharW = fontSize * CHAR_WIDTH_RATIO;
414
+ const maxChars = Math.max(8, Math.floor(maxWidth / avgCharW));
415
+ const normalized = lines.map(
416
+ (l) => l.startsWith("- ") ? "\u2022 " + l.slice(2) : l
417
+ );
418
+ const out = [];
419
+ for (const line of normalized) {
420
+ if (line === "") {
421
+ out.push({ text: "", kind: "plain" });
422
+ continue;
423
+ }
424
+ out.push(...wrapDescriptionLines([line], maxChars));
425
+ }
426
+ return out;
427
+ }
428
+ function clamp(x, lo, hi) {
429
+ return Math.max(lo, Math.min(hi, x));
430
+ }
431
+
432
+ export {
433
+ renderPyramid,
434
+ renderPyramidForExport
435
+ };
436
+ //# sourceMappingURL=chunk-JM4LEPY3.js.map