@bytechain.cn/colamd 1.5.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 (157) hide show
  1. package/.github/workflows/release.yml +66 -0
  2. package/.trae/documents/fix-mermaid-colors-and-sankey.md +50 -0
  3. package/CLAUDE.md +87 -0
  4. package/LICENSE +21 -0
  5. package/README.md +540 -0
  6. package/README_CN.md +543 -0
  7. package/demo.md +486 -0
  8. package/dist/main/index.js +735 -0
  9. package/dist/preload/index.js +71 -0
  10. package/dist/renderer/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  11. package/dist/renderer/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  12. package/dist/renderer/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  13. package/dist/renderer/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  14. package/dist/renderer/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  15. package/dist/renderer/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  16. package/dist/renderer/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  17. package/dist/renderer/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  18. package/dist/renderer/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  19. package/dist/renderer/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  20. package/dist/renderer/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  21. package/dist/renderer/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  22. package/dist/renderer/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  23. package/dist/renderer/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  24. package/dist/renderer/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  25. package/dist/renderer/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  26. package/dist/renderer/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  27. package/dist/renderer/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  28. package/dist/renderer/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  29. package/dist/renderer/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  30. package/dist/renderer/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  31. package/dist/renderer/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  32. package/dist/renderer/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  33. package/dist/renderer/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  34. package/dist/renderer/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  35. package/dist/renderer/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  36. package/dist/renderer/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  37. package/dist/renderer/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  38. package/dist/renderer/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  39. package/dist/renderer/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  40. package/dist/renderer/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  41. package/dist/renderer/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  42. package/dist/renderer/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  43. package/dist/renderer/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  44. package/dist/renderer/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  45. package/dist/renderer/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  46. package/dist/renderer/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  47. package/dist/renderer/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  48. package/dist/renderer/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  49. package/dist/renderer/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  50. package/dist/renderer/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  51. package/dist/renderer/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  52. package/dist/renderer/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  53. package/dist/renderer/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  54. package/dist/renderer/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  55. package/dist/renderer/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  56. package/dist/renderer/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  57. package/dist/renderer/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  58. package/dist/renderer/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  59. package/dist/renderer/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  60. package/dist/renderer/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  61. package/dist/renderer/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  62. package/dist/renderer/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  63. package/dist/renderer/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  64. package/dist/renderer/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  65. package/dist/renderer/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  66. package/dist/renderer/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  67. package/dist/renderer/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  68. package/dist/renderer/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  69. package/dist/renderer/assets/arc-tTbbM8LO.js +131 -0
  70. package/dist/renderer/assets/architectureDiagram-3BPJPVTR-CEgYow6c.js +8720 -0
  71. package/dist/renderer/assets/blockDiagram-GPEHLZMM-LHyVtPwW.js +3825 -0
  72. package/dist/renderer/assets/c4Diagram-AAUBKEIU-C1P1eJrf.js +2482 -0
  73. package/dist/renderer/assets/channel-upve91Tq.js +7 -0
  74. package/dist/renderer/assets/chunk-2J33WTMH-lag2vhq9.js +24 -0
  75. package/dist/renderer/assets/chunk-4BX2VUAB-BXJ8Ggh-.js +16 -0
  76. package/dist/renderer/assets/chunk-55IACEB6-CiBpxRa1.js +13 -0
  77. package/dist/renderer/assets/chunk-727SXJPM-ODeKQFXC.js +2016 -0
  78. package/dist/renderer/assets/chunk-AQP2D5EJ-BK7xJolB.js +1953 -0
  79. package/dist/renderer/assets/chunk-FMBD7UC4-BxpCZPtz.js +19 -0
  80. package/dist/renderer/assets/chunk-ND2GUHAM-CqqaU9Ue.js +116 -0
  81. package/dist/renderer/assets/chunk-QZHKN3VN-Biq_K124.js +19 -0
  82. package/dist/renderer/assets/classDiagram-4FO5ZUOK-Cq95X99o.js +23 -0
  83. package/dist/renderer/assets/classDiagram-v2-Q7XG4LA2-Cq95X99o.js +23 -0
  84. package/dist/renderer/assets/cose-bilkent-S5V4N54A-XasiD0bu.js +4942 -0
  85. package/dist/renderer/assets/cytoscape.esm-CpHeHM5e.js +30269 -0
  86. package/dist/renderer/assets/dagre-BM42HDAG-Nq84Gfx4.js +705 -0
  87. package/dist/renderer/assets/defaultLocale-B2RvLBDe.js +206 -0
  88. package/dist/renderer/assets/diagram-2AECGRRQ-DwuB1GWt.js +301 -0
  89. package/dist/renderer/assets/diagram-5GNKFQAL-C2tgeI1h.js +169 -0
  90. package/dist/renderer/assets/diagram-KO2AKTUF-D5KzjNBc.js +632 -0
  91. package/dist/renderer/assets/diagram-LMA3HP47-C12xHS1c.js +212 -0
  92. package/dist/renderer/assets/diagram-OG6HWLK6-CnxI9oEa.js +851 -0
  93. package/dist/renderer/assets/erDiagram-TEJ5UH35-D_uPaKwn.js +1227 -0
  94. package/dist/renderer/assets/flowDiagram-I6XJVG4X-B6q_1-tE.js +2332 -0
  95. package/dist/renderer/assets/ganttDiagram-6RSMTGT7-CFo7ifF9.js +3720 -0
  96. package/dist/renderer/assets/gitGraphDiagram-PVQCEYII-WSexHTnq.js +1373 -0
  97. package/dist/renderer/assets/graph-DyX_9f6d.js +1988 -0
  98. package/dist/renderer/assets/index-DW7LS8C1.js +72292 -0
  99. package/dist/renderer/assets/index-dyHEFYvY.css +2184 -0
  100. package/dist/renderer/assets/infoDiagram-5YYISTIA-DaeJdLRq.js +31 -0
  101. package/dist/renderer/assets/init-ZxktEp_H.js +16 -0
  102. package/dist/renderer/assets/ishikawaDiagram-YF4QCWOH-DDCZc35f.js +967 -0
  103. package/dist/renderer/assets/journeyDiagram-JHISSGLW-BEdmpAgl.js +1255 -0
  104. package/dist/renderer/assets/kanban-definition-UN3LZRKU-BEFtQcFb.js +1052 -0
  105. package/dist/renderer/assets/layout-CAJgQHdw.js +2610 -0
  106. package/dist/renderer/assets/linear-B2ggJ8Am.js +340 -0
  107. package/dist/renderer/assets/mindmap-definition-RKZ34NQL-DSxVgHB5.js +1180 -0
  108. package/dist/renderer/assets/ordinal-DSZU4PqD.js +76 -0
  109. package/dist/renderer/assets/pieDiagram-4H26LBE5-CwYoJBuL.js +246 -0
  110. package/dist/renderer/assets/quadrantDiagram-W4KKPZXB-CST9Fvg9.js +1344 -0
  111. package/dist/renderer/assets/requirementDiagram-4Y6WPE33-DtrH52jS.js +1204 -0
  112. package/dist/renderer/assets/sankeyDiagram-5OEKKPKP-ca1tPzJ_.js +1274 -0
  113. package/dist/renderer/assets/sequenceDiagram-3UESZ5HK-Dfp1EJZ7.js +4514 -0
  114. package/dist/renderer/assets/stateDiagram-AJRCARHV-Bha2QoNB.js +450 -0
  115. package/dist/renderer/assets/stateDiagram-v2-BHNVJYJU-DWgFUYu1.js +21 -0
  116. package/dist/renderer/assets/timeline-definition-PNZ67QCA-C3h_-OTj.js +1596 -0
  117. package/dist/renderer/assets/vennDiagram-CIIHVFJN-DFzjSrZi.js +2486 -0
  118. package/dist/renderer/assets/wardley-L42UT6IY-Cx-VbqoS.js +30699 -0
  119. package/dist/renderer/assets/wardleyDiagram-YWT4CUSO-S2D9XqX6.js +975 -0
  120. package/dist/renderer/assets/xychartDiagram-2RQKCTM6-Cfxigbts.js +1932 -0
  121. package/dist/renderer/index.html +19 -0
  122. package/docs/agent-diff-view.md +48 -0
  123. package/electron-builder.yml +57 -0
  124. package/electron.vite.config.ts +30 -0
  125. package/package.json +40 -0
  126. package/resources/entitlements.mac.plist +12 -0
  127. package/resources/icon.icns +0 -0
  128. package/resources/icon.png +0 -0
  129. package/resources/icon.svg +23 -0
  130. package/resources/templates/slides/icon.png +0 -0
  131. package/resources/templates/slides/slides-template.md +74 -0
  132. package/resources/templates/slides/template.html +535 -0
  133. package/scripts/afterPack.js +13 -0
  134. package/src/main/index.ts +881 -0
  135. package/src/preload/index.ts +110 -0
  136. package/src/renderer/editor/editor.ts +204 -0
  137. package/src/renderer/editor/html-view.ts +15 -0
  138. package/src/renderer/editor/plugins/index.ts +76 -0
  139. package/src/renderer/editor/plugins/math-plugin.ts +297 -0
  140. package/src/renderer/editor/plugins/mermaid-plugin-custom.css +431 -0
  141. package/src/renderer/editor/plugins/mermaid-plugin-dark.css +428 -0
  142. package/src/renderer/editor/plugins/mermaid-plugin-elegant.css +443 -0
  143. package/src/renderer/editor/plugins/mermaid-plugin-newsprint.css +208 -0
  144. package/src/renderer/editor/plugins/mermaid-plugin.css +111 -0
  145. package/src/renderer/editor/plugins/mermaid-plugin.ts +679 -0
  146. package/src/renderer/env.d.ts +7 -0
  147. package/src/renderer/index.html +18 -0
  148. package/src/renderer/main.ts +303 -0
  149. package/src/renderer/themes/base.css +509 -0
  150. package/src/renderer/themes/theme-manager.ts +40 -0
  151. package/themes/README.md +280 -0
  152. package/themes/elegant.css +664 -0
  153. package/themes/guizang.css +732 -0
  154. package/tsconfig.json +14 -0
  155. package/tsconfig.main.json +11 -0
  156. package/tsconfig.preload.json +11 -0
  157. package/tsconfig.renderer.json +12 -0
@@ -0,0 +1,975 @@
1
+ import { s as setAccDescription, g as getAccDescription, q as getDiagramTitle, p as setDiagramTitle, a as getAccTitle, b as setAccTitle, _ as __name, K as getThemeVariables3, D as getConfig, F as cleanAndMerge, l as log, I as selectSvgElement, e as configureSvgSize, z as clear, c as getConfig2 } from "./index-DW7LS8C1.js";
2
+ import { p as populateCommonDb } from "./chunk-4BX2VUAB-BXJ8Ggh-.js";
3
+ import { p as parse } from "./wardley-L42UT6IY-Cx-VbqoS.js";
4
+ var toPercent = /* @__PURE__ */ __name((value, context) => {
5
+ const normalized = value <= 1 ? value * 100 : value;
6
+ if (normalized < 0 || normalized > 100) {
7
+ throw new Error(
8
+ `${context} must be between 0-1 (decimal) or 0-100 (percentage). Received: ${value}`
9
+ );
10
+ }
11
+ return normalized;
12
+ }, "toPercent");
13
+ var toCoordinates = /* @__PURE__ */ __name((visibility, evolution, context) => {
14
+ return {
15
+ x: toPercent(evolution, `${context} evolution`),
16
+ y: toPercent(visibility, `${context} visibility`)
17
+ };
18
+ }, "toCoordinates");
19
+ var getFlowFromPort = /* @__PURE__ */ __name((port) => {
20
+ if (!port) {
21
+ return void 0;
22
+ }
23
+ if (port === "+<>") {
24
+ return "bidirectional";
25
+ }
26
+ if (port === "+<") {
27
+ return "backward";
28
+ }
29
+ if (port === "+>") {
30
+ return "forward";
31
+ }
32
+ return void 0;
33
+ }, "getFlowFromPort");
34
+ var extractFlowFromArrow = /* @__PURE__ */ __name((arrow) => {
35
+ if (!arrow?.startsWith("+")) {
36
+ return {};
37
+ }
38
+ const labelMatch = /^\+'([^']*)'/.exec(arrow);
39
+ const flowLabel = labelMatch?.[1];
40
+ if (arrow.includes("<>")) {
41
+ return { flow: "bidirectional", label: flowLabel };
42
+ }
43
+ if (arrow.includes("<")) {
44
+ return { flow: "backward", label: flowLabel };
45
+ }
46
+ if (arrow.includes(">")) {
47
+ return { flow: "forward", label: flowLabel };
48
+ }
49
+ return { label: flowLabel };
50
+ }, "extractFlowFromArrow");
51
+ var populateDb = /* @__PURE__ */ __name((ast, db) => {
52
+ populateCommonDb(ast, db);
53
+ if (ast.size) {
54
+ db.setSize(ast.size.width, ast.size.height);
55
+ }
56
+ if (ast.evolution) {
57
+ const stages = ast.evolution.stages.map((stage) => {
58
+ if (stage.secondName) {
59
+ return `${stage.name.trim()} / ${stage.secondName.trim()}`;
60
+ }
61
+ return stage.name.trim();
62
+ });
63
+ const stageBoundaries = ast.evolution.stages.filter((stage) => stage.boundary !== void 0).map((stage) => stage.boundary);
64
+ db.updateAxes({ stages, stageBoundaries });
65
+ }
66
+ ast.anchors.forEach((anchor) => {
67
+ const coords = toCoordinates(anchor.visibility, anchor.evolution, `Anchor "${anchor.name}"`);
68
+ db.addNode(anchor.name, anchor.name, coords.x, coords.y, "anchor");
69
+ });
70
+ ast.components.forEach((component) => {
71
+ const coords = toCoordinates(
72
+ component.visibility,
73
+ component.evolution,
74
+ `Component "${component.name}"`
75
+ );
76
+ const labelOffsetX = component.label ? (component.label.negX ? -1 : 1) * component.label.offsetX : void 0;
77
+ const labelOffsetY = component.label ? (component.label.negY ? -1 : 1) * component.label.offsetY : void 0;
78
+ const sourceStrategy = component.decorator?.strategy;
79
+ db.addNode(
80
+ component.name,
81
+ component.name,
82
+ coords.x,
83
+ coords.y,
84
+ "component",
85
+ labelOffsetX,
86
+ labelOffsetY,
87
+ component.inertia,
88
+ sourceStrategy
89
+ );
90
+ });
91
+ ast.notes.forEach((note) => {
92
+ const coords = toCoordinates(note.visibility, note.evolution, `Note "${note.text}"`);
93
+ db.addNote(note.text, coords.x, coords.y);
94
+ });
95
+ ast.pipelines.forEach((pipeline) => {
96
+ const parentNode = db.getNode(pipeline.parent);
97
+ if (!parentNode || typeof parentNode.y !== "number") {
98
+ throw new Error(
99
+ `Pipeline "${pipeline.parent}" must reference an existing component with coordinates.`
100
+ );
101
+ }
102
+ const parentY = parentNode.y;
103
+ db.startPipeline(pipeline.parent);
104
+ pipeline.components.forEach((component) => {
105
+ const componentId = `${pipeline.parent}_${component.name}`;
106
+ const labelOffsetX = component.label ? (component.label.negX ? -1 : 1) * component.label.offsetX : void 0;
107
+ const labelOffsetY = component.label ? (component.label.negY ? -1 : 1) * component.label.offsetY : void 0;
108
+ const x = toPercent(component.evolution, `Pipeline component "${component.name}" evolution`);
109
+ db.addNode(
110
+ componentId,
111
+ component.name,
112
+ x,
113
+ parentY,
114
+ "pipeline-component",
115
+ labelOffsetX,
116
+ labelOffsetY
117
+ );
118
+ db.addPipelineComponent(pipeline.parent, componentId);
119
+ });
120
+ });
121
+ ast.links.forEach((link) => {
122
+ const isDashed = !!link.arrow && (link.arrow.includes("-.->") || link.arrow.includes(".-."));
123
+ let flow = getFlowFromPort(link.fromPort) ?? getFlowFromPort(link.toPort);
124
+ const { flow: arrowFlow, label: flowLabel } = extractFlowFromArrow(link.arrow);
125
+ if (!flow && arrowFlow) {
126
+ flow = arrowFlow;
127
+ }
128
+ const annotation = link.linkLabel;
129
+ const label = flowLabel ?? annotation;
130
+ db.addLink(db.resolveNodeId(link.from), db.resolveNodeId(link.to), isDashed, label, flow);
131
+ });
132
+ ast.evolves.forEach((evolve) => {
133
+ const node = db.getNode(evolve.component);
134
+ if (node?.y !== void 0) {
135
+ const target = toPercent(evolve.target, `Evolve target for "${evolve.component}"`);
136
+ db.addTrend(evolve.component, target, node.y);
137
+ }
138
+ });
139
+ if (ast.annotations.length > 0) {
140
+ const annotationsBox = ast.annotations[0];
141
+ const coords = toCoordinates(annotationsBox.x, annotationsBox.y, "Annotations box");
142
+ db.setAnnotationsBox(coords.x, coords.y);
143
+ }
144
+ ast.annotation.forEach((annotation) => {
145
+ const coords = toCoordinates(annotation.x, annotation.y, `Annotation ${annotation.number}`);
146
+ db.addAnnotation(annotation.number, [{ x: coords.x, y: coords.y }], annotation.text);
147
+ });
148
+ ast.accelerators.forEach((accelerator) => {
149
+ const coords = toCoordinates(accelerator.x, accelerator.y, `Accelerator "${accelerator.name}"`);
150
+ db.addAccelerator(accelerator.name, coords.x, coords.y);
151
+ });
152
+ ast.deaccelerators.forEach((deaccelerator) => {
153
+ const coords = toCoordinates(
154
+ deaccelerator.x,
155
+ deaccelerator.y,
156
+ `Deaccelerator "${deaccelerator.name}"`
157
+ );
158
+ db.addDeaccelerator(deaccelerator.name, coords.x, coords.y);
159
+ });
160
+ }, "populateDb");
161
+ var parser = {
162
+ parser: {
163
+ // @ts-expect-error - WardleyDB is not assignable to DiagramDB
164
+ yy: void 0
165
+ },
166
+ parse: /* @__PURE__ */ __name(async (input) => {
167
+ const ast = await parse("wardley", input);
168
+ log.debug(ast);
169
+ const db = parser.parser?.yy;
170
+ if (!db || typeof db.addNode !== "function") {
171
+ throw new Error(
172
+ "parser.parser?.yy was not a WardleyDB. This is due to a bug within Mermaid, please report this issue at https://github.com/mermaid-js/mermaid/issues."
173
+ );
174
+ }
175
+ populateDb(ast, db);
176
+ }, "parse")
177
+ };
178
+ var WardleyBuilder = class {
179
+ constructor() {
180
+ this.nodes = /* @__PURE__ */ new Map();
181
+ this.links = [];
182
+ this.trends = /* @__PURE__ */ new Map();
183
+ this.pipelines = /* @__PURE__ */ new Map();
184
+ this.annotations = [];
185
+ this.notes = [];
186
+ this.accelerators = [];
187
+ this.deaccelerators = [];
188
+ this.axes = {};
189
+ }
190
+ static {
191
+ __name(this, "WardleyBuilder");
192
+ }
193
+ addNode(node) {
194
+ const existing = this.nodes.get(node.id) ?? { id: node.id, label: node.label };
195
+ const merged = {
196
+ ...existing,
197
+ ...node,
198
+ className: node.className ?? existing.className,
199
+ labelOffsetX: node.labelOffsetX ?? existing.labelOffsetX,
200
+ labelOffsetY: node.labelOffsetY ?? existing.labelOffsetY
201
+ };
202
+ this.nodes.set(node.id, merged);
203
+ }
204
+ addLink(link) {
205
+ this.links.push(link);
206
+ }
207
+ addTrend(trend) {
208
+ this.trends.set(trend.nodeId, trend);
209
+ }
210
+ startPipeline(nodeId) {
211
+ this.pipelines.set(nodeId, { nodeId, componentIds: [] });
212
+ const node = this.nodes.get(nodeId);
213
+ if (node) {
214
+ node.isPipelineParent = true;
215
+ }
216
+ }
217
+ addPipelineComponent(pipelineNodeId, componentId) {
218
+ const pipeline = this.pipelines.get(pipelineNodeId);
219
+ if (pipeline) {
220
+ pipeline.componentIds.push(componentId);
221
+ }
222
+ const node = this.nodes.get(componentId);
223
+ if (node) {
224
+ node.inPipeline = true;
225
+ }
226
+ }
227
+ addAnnotation(annotation) {
228
+ this.annotations.push(annotation);
229
+ }
230
+ addNote(note) {
231
+ this.notes.push(note);
232
+ }
233
+ addAccelerator(accelerator) {
234
+ this.accelerators.push(accelerator);
235
+ }
236
+ addDeaccelerator(deaccelerator) {
237
+ this.deaccelerators.push(deaccelerator);
238
+ }
239
+ setAnnotationsBox(x, y) {
240
+ this.annotationsBox = { x, y };
241
+ }
242
+ setAxes(partial) {
243
+ this.axes = {
244
+ ...this.axes,
245
+ ...partial
246
+ };
247
+ }
248
+ setSize(width, height) {
249
+ this.size = { width, height };
250
+ }
251
+ getNode(id) {
252
+ return this.nodes.get(id);
253
+ }
254
+ /**
255
+ * Resolve a name to a node ID. Tries exact ID match first,
256
+ * then falls back to finding a node whose label matches the name
257
+ * (handles pipeline components which have synthetic IDs like "Parent_Child").
258
+ */
259
+ resolveNodeId(name) {
260
+ if (this.nodes.has(name)) {
261
+ return name;
262
+ }
263
+ for (const [id, node] of this.nodes) {
264
+ if (node.label === name) {
265
+ return id;
266
+ }
267
+ }
268
+ return name;
269
+ }
270
+ build() {
271
+ const nodes = [];
272
+ for (const node of this.nodes.values()) {
273
+ if (typeof node.x !== "number" || typeof node.y !== "number") {
274
+ throw new Error(`Node "${node.label}" is missing coordinates`);
275
+ }
276
+ nodes.push(node);
277
+ }
278
+ return {
279
+ nodes,
280
+ links: [...this.links],
281
+ trends: [...this.trends.values()],
282
+ pipelines: [...this.pipelines.values()],
283
+ annotations: [...this.annotations],
284
+ notes: [...this.notes],
285
+ accelerators: [...this.accelerators],
286
+ deaccelerators: [...this.deaccelerators],
287
+ annotationsBox: this.annotationsBox,
288
+ axes: { ...this.axes },
289
+ size: this.size
290
+ };
291
+ }
292
+ clear() {
293
+ this.nodes.clear();
294
+ this.links = [];
295
+ this.trends.clear();
296
+ this.pipelines.clear();
297
+ this.annotations = [];
298
+ this.notes = [];
299
+ this.accelerators = [];
300
+ this.deaccelerators = [];
301
+ this.annotationsBox = void 0;
302
+ this.axes = {};
303
+ this.size = void 0;
304
+ }
305
+ };
306
+ var builder = new WardleyBuilder();
307
+ function getConfig3() {
308
+ return getConfig2()["wardley-beta"];
309
+ }
310
+ __name(getConfig3, "getConfig");
311
+ function addNode(id, label, x, y, className, labelOffsetX, labelOffsetY, inertia, sourceStrategy) {
312
+ builder.addNode({
313
+ id,
314
+ label,
315
+ x,
316
+ y,
317
+ className,
318
+ labelOffsetX,
319
+ labelOffsetY,
320
+ inertia,
321
+ sourceStrategy
322
+ });
323
+ }
324
+ __name(addNode, "addNode");
325
+ function addLink(sourceId, targetId, dashed = false, label, flow) {
326
+ builder.addLink({
327
+ source: sourceId,
328
+ target: targetId,
329
+ dashed,
330
+ label,
331
+ flow
332
+ });
333
+ }
334
+ __name(addLink, "addLink");
335
+ function addTrend(nodeId, targetX, targetY) {
336
+ builder.addTrend({ nodeId, targetX, targetY });
337
+ }
338
+ __name(addTrend, "addTrend");
339
+ function addAnnotation(number, coordinates, text) {
340
+ builder.addAnnotation({
341
+ number,
342
+ coordinates,
343
+ text
344
+ });
345
+ }
346
+ __name(addAnnotation, "addAnnotation");
347
+ function addNote(text, x, y) {
348
+ builder.addNote({
349
+ text,
350
+ x,
351
+ y
352
+ });
353
+ }
354
+ __name(addNote, "addNote");
355
+ function addAccelerator(name, x, y) {
356
+ builder.addAccelerator({
357
+ name,
358
+ x,
359
+ y
360
+ });
361
+ }
362
+ __name(addAccelerator, "addAccelerator");
363
+ function addDeaccelerator(name, x, y) {
364
+ builder.addDeaccelerator({
365
+ name,
366
+ x,
367
+ y
368
+ });
369
+ }
370
+ __name(addDeaccelerator, "addDeaccelerator");
371
+ function setAnnotationsBox(x, y) {
372
+ builder.setAnnotationsBox(x, y);
373
+ }
374
+ __name(setAnnotationsBox, "setAnnotationsBox");
375
+ function setSize(width, height) {
376
+ builder.setSize(width, height);
377
+ }
378
+ __name(setSize, "setSize");
379
+ function startPipeline(nodeId) {
380
+ builder.startPipeline(nodeId);
381
+ }
382
+ __name(startPipeline, "startPipeline");
383
+ function addPipelineComponent(pipelineNodeId, componentId) {
384
+ builder.addPipelineComponent(pipelineNodeId, componentId);
385
+ }
386
+ __name(addPipelineComponent, "addPipelineComponent");
387
+ function updateAxes(partial) {
388
+ builder.setAxes(partial);
389
+ }
390
+ __name(updateAxes, "updateAxes");
391
+ function getNode(id) {
392
+ return builder.getNode(id);
393
+ }
394
+ __name(getNode, "getNode");
395
+ function resolveNodeId(name) {
396
+ return builder.resolveNodeId(name);
397
+ }
398
+ __name(resolveNodeId, "resolveNodeId");
399
+ function getWardleyData() {
400
+ return builder.build();
401
+ }
402
+ __name(getWardleyData, "getWardleyData");
403
+ function clear2() {
404
+ builder.clear();
405
+ clear();
406
+ }
407
+ __name(clear2, "clear");
408
+ var wardleyDb_default = {
409
+ getConfig: getConfig3,
410
+ addNode,
411
+ addLink,
412
+ addTrend,
413
+ addAnnotation,
414
+ addNote,
415
+ addAccelerator,
416
+ addDeaccelerator,
417
+ setAnnotationsBox,
418
+ setSize,
419
+ startPipeline,
420
+ addPipelineComponent,
421
+ updateAxes,
422
+ getNode,
423
+ resolveNodeId,
424
+ getWardleyData,
425
+ clear: clear2,
426
+ setAccTitle,
427
+ getAccTitle,
428
+ setDiagramTitle,
429
+ getDiagramTitle,
430
+ getAccDescription,
431
+ setAccDescription
432
+ };
433
+ var DEFAULT_STAGES = ["Genesis", "Custom Built", "Product", "Commodity"];
434
+ var getTheme = /* @__PURE__ */ __name(() => {
435
+ const { themeVariables } = getConfig2();
436
+ return {
437
+ backgroundColor: themeVariables.wardley?.backgroundColor ?? themeVariables.background ?? "#fff",
438
+ axisColor: themeVariables.wardley?.axisColor ?? "#000",
439
+ axisTextColor: themeVariables.wardley?.axisTextColor ?? themeVariables.primaryTextColor ?? "#222",
440
+ gridColor: themeVariables.wardley?.gridColor ?? "rgba(100, 100, 100, 0.2)",
441
+ componentFill: themeVariables.wardley?.componentFill ?? "#fff",
442
+ componentStroke: themeVariables.wardley?.componentStroke ?? "#000",
443
+ componentLabelColor: themeVariables.wardley?.componentLabelColor ?? themeVariables.primaryTextColor ?? "#222",
444
+ linkStroke: themeVariables.wardley?.linkStroke ?? "#000",
445
+ evolutionStroke: themeVariables.wardley?.evolutionStroke ?? "#dc3545",
446
+ annotationStroke: themeVariables.wardley?.annotationStroke ?? "#000",
447
+ annotationTextColor: themeVariables.wardley?.annotationTextColor ?? themeVariables.primaryTextColor ?? "#222",
448
+ annotationFill: themeVariables.wardley?.annotationFill ?? themeVariables.background ?? "#fff"
449
+ };
450
+ }, "getTheme");
451
+ var getConfigValues = /* @__PURE__ */ __name(() => {
452
+ const wardleyConfig = getConfig2()["wardley-beta"];
453
+ return {
454
+ width: wardleyConfig?.width ?? 900,
455
+ height: wardleyConfig?.height ?? 600,
456
+ padding: wardleyConfig?.padding ?? 48,
457
+ nodeRadius: wardleyConfig?.nodeRadius ?? 6,
458
+ nodeLabelOffset: wardleyConfig?.nodeLabelOffset ?? 8,
459
+ axisFontSize: wardleyConfig?.axisFontSize ?? 12,
460
+ labelFontSize: wardleyConfig?.labelFontSize ?? 10,
461
+ showGrid: wardleyConfig?.showGrid ?? false,
462
+ useMaxWidth: wardleyConfig?.useMaxWidth ?? true
463
+ };
464
+ }, "getConfigValues");
465
+ var draw = /* @__PURE__ */ __name((text, id, _version, diagObj) => {
466
+ log.debug("Rendering Wardley map\n" + text);
467
+ const configValues = getConfigValues();
468
+ const theme = getTheme();
469
+ const squareSize = configValues.nodeRadius * 1.6;
470
+ const db = diagObj.db;
471
+ const data = db.getWardleyData();
472
+ const title = db.getDiagramTitle();
473
+ const width = data.size?.width ?? configValues.width;
474
+ const height = data.size?.height ?? configValues.height;
475
+ const svg = selectSvgElement(id);
476
+ svg.selectAll("*").remove();
477
+ configureSvgSize(svg, height, width, configValues.useMaxWidth);
478
+ svg.attr("viewBox", `0 0 ${width} ${height}`);
479
+ const root = svg.append("g").attr("class", "wardley-map");
480
+ const defs = svg.append("defs");
481
+ defs.append("marker").attr("id", `arrow-${id}`).attr("viewBox", "0 0 10 10").attr("refX", 9).attr("refY", 5).attr("markerWidth", 6).attr("markerHeight", 6).attr("orient", "auto-start-reverse").append("path").attr("d", "M 0 0 L 10 5 L 0 10 z").attr("fill", theme.evolutionStroke).attr("stroke", "none");
482
+ defs.append("marker").attr("id", `link-arrow-end-${id}`).attr("viewBox", "0 0 10 10").attr("refX", 9).attr("refY", 5).attr("markerWidth", 5).attr("markerHeight", 5).attr("orient", "auto").append("path").attr("d", "M 0 0 L 10 5 L 0 10 z").attr("fill", theme.linkStroke).attr("stroke", "none");
483
+ defs.append("marker").attr("id", `link-arrow-start-${id}`).attr("viewBox", "0 0 10 10").attr("refX", 1).attr("refY", 5).attr("markerWidth", 5).attr("markerHeight", 5).attr("orient", "auto").append("path").attr("d", "M 10 0 L 0 5 L 10 10 z").attr("fill", theme.linkStroke).attr("stroke", "none");
484
+ root.append("rect").attr("class", "wardley-background").attr("width", width).attr("height", height).attr("fill", theme.backgroundColor);
485
+ const chartWidth = width - configValues.padding * 2;
486
+ const chartHeight = height - configValues.padding * 2;
487
+ if (title) {
488
+ root.append("text").attr("class", "wardley-title").attr("x", width / 2).attr("y", configValues.padding / 2).attr("fill", theme.axisTextColor).attr("font-size", configValues.axisFontSize * 1.05).attr("font-weight", "bold").attr("text-anchor", "middle").attr("dominant-baseline", "middle").text(title);
489
+ }
490
+ const projectX = /* @__PURE__ */ __name((value) => configValues.padding + value / 100 * chartWidth, "projectX");
491
+ const projectY = /* @__PURE__ */ __name((value) => height - configValues.padding - value / 100 * chartHeight, "projectY");
492
+ const axisGroup = root.append("g").attr("class", "wardley-axes");
493
+ axisGroup.append("line").attr("x1", configValues.padding).attr("x2", width - configValues.padding).attr("y1", height - configValues.padding).attr("y2", height - configValues.padding).attr("stroke", theme.axisColor).attr("stroke-width", 1);
494
+ axisGroup.append("line").attr("x1", configValues.padding).attr("x2", configValues.padding).attr("y1", configValues.padding).attr("y2", height - configValues.padding).attr("stroke", theme.axisColor).attr("stroke-width", 1);
495
+ const xLabel = data.axes.xLabel ?? "Evolution";
496
+ const yLabel = data.axes.yLabel ?? "Visibility";
497
+ axisGroup.append("text").attr("class", "wardley-axis-label wardley-axis-label-x").attr("x", configValues.padding + chartWidth / 2).attr("y", height - configValues.padding / 4).attr("fill", theme.axisTextColor).attr("font-size", configValues.axisFontSize).attr("font-weight", "bold").attr("text-anchor", "middle").text(xLabel);
498
+ axisGroup.append("text").attr("class", "wardley-axis-label wardley-axis-label-y").attr("x", configValues.padding / 3).attr("y", configValues.padding + chartHeight / 2).attr("fill", theme.axisTextColor).attr("font-size", configValues.axisFontSize).attr("font-weight", "bold").attr("text-anchor", "middle").attr(
499
+ "transform",
500
+ `rotate(-90 ${configValues.padding / 3} ${configValues.padding + chartHeight / 2})`
501
+ ).text(yLabel);
502
+ const stages = data.axes.stages && data.axes.stages.length > 0 ? data.axes.stages : DEFAULT_STAGES;
503
+ if (stages.length > 0) {
504
+ const stageGroup = root.append("g").attr("class", "wardley-stages");
505
+ const boundaries = data.axes.stageBoundaries;
506
+ const stagePositions = [];
507
+ if (boundaries && boundaries.length === stages.length) {
508
+ let prevBoundary = 0;
509
+ boundaries.forEach((boundary) => {
510
+ stagePositions.push({ start: prevBoundary, end: boundary });
511
+ prevBoundary = boundary;
512
+ });
513
+ } else {
514
+ const stageWidth = 1 / stages.length;
515
+ stages.forEach((_, index) => {
516
+ stagePositions.push({
517
+ start: index * stageWidth,
518
+ end: (index + 1) * stageWidth
519
+ });
520
+ });
521
+ }
522
+ stages.forEach((stage, index) => {
523
+ const pos = stagePositions[index];
524
+ const startX = configValues.padding + pos.start * chartWidth;
525
+ const endX = configValues.padding + pos.end * chartWidth;
526
+ const centerX = (startX + endX) / 2;
527
+ if (index > 0) {
528
+ stageGroup.append("line").attr("x1", startX).attr("x2", startX).attr("y1", configValues.padding).attr("y2", height - configValues.padding).attr("stroke", "#000").attr("stroke-width", 1).attr("stroke-dasharray", "5 5").attr("opacity", 0.8);
529
+ }
530
+ stageGroup.append("text").attr("class", "wardley-stage-label").attr("x", centerX).attr("y", height - configValues.padding / 1.5).attr("fill", theme.axisTextColor).attr("font-size", configValues.axisFontSize - 2).attr("text-anchor", "middle").text(stage);
531
+ });
532
+ }
533
+ if (configValues.showGrid) {
534
+ const gridGroup = root.append("g").attr("class", "wardley-grid");
535
+ for (let i = 1; i < 4; i++) {
536
+ const ratio = i / 4;
537
+ const x = configValues.padding + chartWidth * ratio;
538
+ gridGroup.append("line").attr("x1", x).attr("x2", x).attr("y1", configValues.padding).attr("y2", height - configValues.padding).attr("stroke", theme.gridColor).attr("stroke-dasharray", "2 6");
539
+ gridGroup.append("line").attr("x1", configValues.padding).attr("x2", width - configValues.padding).attr("y1", height - configValues.padding - chartHeight * ratio).attr("y2", height - configValues.padding - chartHeight * ratio).attr("stroke", theme.gridColor).attr("stroke-dasharray", "2 6");
540
+ }
541
+ }
542
+ const positions = /* @__PURE__ */ new Map();
543
+ data.nodes.forEach((node) => {
544
+ positions.set(node.id, {
545
+ x: projectX(node.x),
546
+ y: projectY(node.y),
547
+ node
548
+ });
549
+ });
550
+ if (data.pipelines.length > 0) {
551
+ const pipelineGroup = root.append("g").attr("class", "wardley-pipelines");
552
+ const pipelineLinksGroup = root.append("g").attr("class", "wardley-pipeline-links");
553
+ data.pipelines.forEach((pipeline) => {
554
+ if (pipeline.componentIds.length === 0) {
555
+ return;
556
+ }
557
+ const sortedComponents = pipeline.componentIds.map((id2) => ({ id: id2, pos: positions.get(id2), node: data.nodes.find((n) => n.id === id2) })).filter((c) => c.pos && c.node).sort((a, b) => a.node.x - b.node.x);
558
+ for (let i = 0; i < sortedComponents.length - 1; i++) {
559
+ const current = sortedComponents[i];
560
+ const next = sortedComponents[i + 1];
561
+ pipelineLinksGroup.append("line").attr("class", "wardley-pipeline-evolution-link").attr("x1", current.pos.x).attr("y1", current.pos.y).attr("x2", next.pos.x).attr("y2", next.pos.y).attr("stroke", theme.linkStroke).attr("stroke-width", 1).attr("stroke-dasharray", "4 4");
562
+ }
563
+ let minX = Infinity;
564
+ let maxX = -Infinity;
565
+ let y = 0;
566
+ pipeline.componentIds.forEach((componentId) => {
567
+ const pos = positions.get(componentId);
568
+ if (pos) {
569
+ minX = Math.min(minX, pos.x);
570
+ maxX = Math.max(maxX, pos.x);
571
+ y = pos.y;
572
+ }
573
+ });
574
+ if (minX !== Infinity && maxX !== -Infinity) {
575
+ const padding = 15;
576
+ const height2 = configValues.nodeRadius * 4;
577
+ const boxTop = y - height2 / 2;
578
+ const parentPos = positions.get(pipeline.nodeId);
579
+ if (parentPos) {
580
+ const centerX = (minX + maxX) / 2;
581
+ parentPos.x = centerX;
582
+ parentPos.y = boxTop - squareSize / 6;
583
+ }
584
+ pipelineGroup.append("rect").attr("class", "wardley-pipeline-box").attr("x", minX - padding).attr("y", boxTop).attr("width", maxX - minX + padding * 2).attr("height", height2).attr("fill", "none").attr("stroke", theme.axisColor).attr("stroke-width", 1.5).attr("rx", 4).attr("ry", 4);
585
+ }
586
+ });
587
+ }
588
+ const linksGroup = root.append("g").attr("class", "wardley-links");
589
+ const pipelineMap = /* @__PURE__ */ new Map();
590
+ data.pipelines.forEach((pipeline) => {
591
+ pipelineMap.set(pipeline.nodeId, new Set(pipeline.componentIds));
592
+ });
593
+ const validLinks = data.links.filter((link) => {
594
+ if (!positions.has(link.source) || !positions.has(link.target)) {
595
+ return false;
596
+ }
597
+ const pipelineComponents = pipelineMap.get(link.target);
598
+ if (pipelineComponents?.has(link.source)) {
599
+ return false;
600
+ }
601
+ return true;
602
+ });
603
+ linksGroup.selectAll("line").data(validLinks).enter().append("line").attr("class", (link) => `wardley-link${link.dashed ? " wardley-link--dashed" : ""}`).attr("x1", (link) => {
604
+ const sourcePos = positions.get(link.source);
605
+ const targetPos = positions.get(link.target);
606
+ const sourceNode = data.nodes.find((n) => n.id === link.source);
607
+ const radius = sourceNode.isPipelineParent ? squareSize / Math.sqrt(2) : configValues.nodeRadius;
608
+ const dx = targetPos.x - sourcePos.x;
609
+ const dy = targetPos.y - sourcePos.y;
610
+ const distance = Math.sqrt(dx * dx + dy * dy);
611
+ return sourcePos.x + dx / distance * radius;
612
+ }).attr("y1", (link) => {
613
+ const sourcePos = positions.get(link.source);
614
+ const targetPos = positions.get(link.target);
615
+ const sourceNode = data.nodes.find((n) => n.id === link.source);
616
+ const radius = sourceNode.isPipelineParent ? squareSize / Math.sqrt(2) : configValues.nodeRadius;
617
+ const dx = targetPos.x - sourcePos.x;
618
+ const dy = targetPos.y - sourcePos.y;
619
+ const distance = Math.sqrt(dx * dx + dy * dy);
620
+ return sourcePos.y + dy / distance * radius;
621
+ }).attr("x2", (link) => {
622
+ const sourcePos = positions.get(link.source);
623
+ const targetPos = positions.get(link.target);
624
+ const targetNode = data.nodes.find((n) => n.id === link.target);
625
+ const radius = targetNode.isPipelineParent ? squareSize / Math.sqrt(2) : configValues.nodeRadius;
626
+ const dx = sourcePos.x - targetPos.x;
627
+ const dy = sourcePos.y - targetPos.y;
628
+ const distance = Math.sqrt(dx * dx + dy * dy);
629
+ return targetPos.x + dx / distance * radius;
630
+ }).attr("y2", (link) => {
631
+ const sourcePos = positions.get(link.source);
632
+ const targetPos = positions.get(link.target);
633
+ const targetNode = data.nodes.find((n) => n.id === link.target);
634
+ const radius = targetNode.isPipelineParent ? squareSize / Math.sqrt(2) : configValues.nodeRadius;
635
+ const dx = sourcePos.x - targetPos.x;
636
+ const dy = sourcePos.y - targetPos.y;
637
+ const distance = Math.sqrt(dx * dx + dy * dy);
638
+ return targetPos.y + dy / distance * radius;
639
+ }).attr("stroke", theme.linkStroke).attr("stroke-width", 1).attr("stroke-dasharray", (link) => link.dashed ? "6 6" : null).attr("marker-end", (link) => {
640
+ if (link.flow === "forward" || link.flow === "bidirectional") {
641
+ return `url(#link-arrow-end-${id})`;
642
+ }
643
+ return null;
644
+ }).attr("marker-start", (link) => {
645
+ if (link.flow === "backward" || link.flow === "bidirectional") {
646
+ return `url(#link-arrow-start-${id})`;
647
+ }
648
+ return null;
649
+ });
650
+ linksGroup.selectAll("text").data(validLinks.filter((link) => link.label)).enter().append("text").attr("class", "wardley-link-label").attr("x", (link) => {
651
+ const sourcePos = positions.get(link.source);
652
+ const targetPos = positions.get(link.target);
653
+ const midX = (sourcePos.x + targetPos.x) / 2;
654
+ const dy = targetPos.y - sourcePos.y;
655
+ const dx = targetPos.x - sourcePos.x;
656
+ const distance = Math.sqrt(dx * dx + dy * dy);
657
+ const offset = 8;
658
+ const perpX = dy / distance;
659
+ return midX + perpX * offset;
660
+ }).attr("y", (link) => {
661
+ const sourcePos = positions.get(link.source);
662
+ const targetPos = positions.get(link.target);
663
+ const midY = (sourcePos.y + targetPos.y) / 2;
664
+ const dx = targetPos.x - sourcePos.x;
665
+ const dy = targetPos.y - sourcePos.y;
666
+ const distance = Math.sqrt(dx * dx + dy * dy);
667
+ const offset = 8;
668
+ const perpY = -dx / distance;
669
+ return midY + perpY * offset;
670
+ }).attr("fill", theme.axisTextColor).attr("font-size", configValues.labelFontSize).attr("text-anchor", "middle").attr("dominant-baseline", "middle").attr("transform", (link) => {
671
+ const sourcePos = positions.get(link.source);
672
+ const targetPos = positions.get(link.target);
673
+ const midX = (sourcePos.x + targetPos.x) / 2;
674
+ const midY = (sourcePos.y + targetPos.y) / 2;
675
+ const dx = targetPos.x - sourcePos.x;
676
+ const dy = targetPos.y - sourcePos.y;
677
+ const distance = Math.sqrt(dx * dx + dy * dy);
678
+ const offset = 8;
679
+ const perpX = dy / distance;
680
+ const perpY = -dx / distance;
681
+ const labelX = midX + perpX * offset;
682
+ const labelY = midY + perpY * offset;
683
+ let angle = Math.atan2(dy, dx) * 180 / Math.PI;
684
+ if (angle > 90 || angle < -90) {
685
+ angle += 180;
686
+ }
687
+ return `rotate(${angle} ${labelX} ${labelY})`;
688
+ }).text((link) => link.label);
689
+ const trendGroup = root.append("g").attr("class", "wardley-trends");
690
+ const trendsWithPositions = data.trends.map((trend) => {
691
+ const origin = positions.get(trend.nodeId);
692
+ if (!origin) {
693
+ return null;
694
+ }
695
+ const targetX = projectX(trend.targetX);
696
+ const targetY = projectY(trend.targetY);
697
+ const dx = targetX - origin.x;
698
+ const dy = targetY - origin.y;
699
+ const distance = Math.sqrt(dx * dx + dy * dy);
700
+ const shortenBy = configValues.nodeRadius + 2;
701
+ const adjustedX2 = distance > shortenBy ? targetX - dx / distance * shortenBy : targetX;
702
+ const adjustedY2 = distance > shortenBy ? targetY - dy / distance * shortenBy : targetY;
703
+ return {
704
+ origin,
705
+ targetX,
706
+ targetY,
707
+ adjustedX2,
708
+ adjustedY2
709
+ };
710
+ }).filter((trend) => trend !== null);
711
+ trendGroup.selectAll("line").data(trendsWithPositions).enter().append("line").attr("class", "wardley-trend").attr("x1", (trend) => trend.origin.x).attr("y1", (trend) => trend.origin.y).attr("x2", (trend) => trend.adjustedX2).attr("y2", (trend) => trend.adjustedY2).attr("stroke", theme.evolutionStroke).attr("stroke-width", 1).attr("stroke-dasharray", "4 4").attr("marker-end", `url(#arrow-${id})`);
712
+ const nodesGroup = root.append("g").attr("class", "wardley-nodes");
713
+ const nodeEnter = nodesGroup.selectAll("g").data(data.nodes).enter().append("g").attr(
714
+ "class",
715
+ (node) => ["wardley-node", node.className ? `wardley-node--${node.className}` : ""].filter(Boolean).join(" ")
716
+ );
717
+ nodeEnter.filter((node) => node.sourceStrategy === "outsource").append("circle").attr("class", "wardley-outsource-overlay").attr("cx", (node) => positions.get(node.id).x).attr("cy", (node) => positions.get(node.id).y).attr("r", configValues.nodeRadius * 2).attr("fill", "#666").attr("stroke", theme.componentStroke).attr("stroke-width", 1);
718
+ nodeEnter.filter((node) => node.sourceStrategy === "buy").append("circle").attr("class", "wardley-buy-overlay").attr("cx", (node) => positions.get(node.id).x).attr("cy", (node) => positions.get(node.id).y).attr("r", configValues.nodeRadius * 2).attr("fill", "#ccc").attr("stroke", theme.componentStroke).attr("stroke-width", 1);
719
+ nodeEnter.filter((node) => node.sourceStrategy === "build").append("circle").attr("class", "wardley-build-overlay").attr("cx", (node) => positions.get(node.id).x).attr("cy", (node) => positions.get(node.id).y).attr("r", configValues.nodeRadius * 2).attr("fill", "#eee").attr("stroke", "#000").attr("stroke-width", 1);
720
+ const marketNodes = nodeEnter.filter((node) => node.sourceStrategy === "market");
721
+ marketNodes.append("circle").attr("class", "wardley-market-overlay").attr("cx", (node) => positions.get(node.id).x).attr("cy", (node) => positions.get(node.id).y).attr("r", configValues.nodeRadius * 2).attr("fill", "white").attr("stroke", theme.componentStroke).attr("stroke-width", 1);
722
+ nodeEnter.filter(
723
+ (node) => !node.isPipelineParent && node.sourceStrategy !== "market" && node.className !== "anchor"
724
+ ).append("circle").attr("cx", (node) => positions.get(node.id).x).attr("cy", (node) => positions.get(node.id).y).attr("r", configValues.nodeRadius).attr("fill", theme.componentFill).attr("stroke", theme.componentStroke).attr("stroke-width", 1);
725
+ const smallCircleRadius = configValues.nodeRadius * 0.7;
726
+ const triangleRadius = configValues.nodeRadius * 1.2;
727
+ marketNodes.append("line").attr("class", "wardley-market-line").attr("x1", (node) => positions.get(node.id).x).attr("y1", (node) => positions.get(node.id).y - triangleRadius).attr("x2", (node) => positions.get(node.id).x - triangleRadius * Math.cos(Math.PI / 6)).attr("y2", (node) => positions.get(node.id).y + triangleRadius * Math.sin(Math.PI / 6)).attr("stroke", theme.componentStroke).attr("stroke-width", 1);
728
+ marketNodes.append("line").attr("class", "wardley-market-line").attr("x1", (node) => positions.get(node.id).x - triangleRadius * Math.cos(Math.PI / 6)).attr("y1", (node) => positions.get(node.id).y + triangleRadius * Math.sin(Math.PI / 6)).attr("x2", (node) => positions.get(node.id).x + triangleRadius * Math.cos(Math.PI / 6)).attr("y2", (node) => positions.get(node.id).y + triangleRadius * Math.sin(Math.PI / 6)).attr("stroke", theme.componentStroke).attr("stroke-width", 1);
729
+ marketNodes.append("line").attr("class", "wardley-market-line").attr("x1", (node) => positions.get(node.id).x + triangleRadius * Math.cos(Math.PI / 6)).attr("y1", (node) => positions.get(node.id).y + triangleRadius * Math.sin(Math.PI / 6)).attr("x2", (node) => positions.get(node.id).x).attr("y2", (node) => positions.get(node.id).y - triangleRadius).attr("stroke", theme.componentStroke).attr("stroke-width", 1);
730
+ marketNodes.append("circle").attr("class", "wardley-market-dot").attr("cx", (node) => positions.get(node.id).x).attr("cy", (node) => positions.get(node.id).y - triangleRadius).attr("r", smallCircleRadius).attr("fill", "white").attr("stroke", theme.componentStroke).attr("stroke-width", 2);
731
+ marketNodes.append("circle").attr("class", "wardley-market-dot").attr("cx", (node) => positions.get(node.id).x - triangleRadius * Math.cos(Math.PI / 6)).attr("cy", (node) => positions.get(node.id).y + triangleRadius * Math.sin(Math.PI / 6)).attr("r", smallCircleRadius).attr("fill", "white").attr("stroke", theme.componentStroke).attr("stroke-width", 2);
732
+ marketNodes.append("circle").attr("class", "wardley-market-dot").attr("cx", (node) => positions.get(node.id).x + triangleRadius * Math.cos(Math.PI / 6)).attr("cy", (node) => positions.get(node.id).y + triangleRadius * Math.sin(Math.PI / 6)).attr("r", smallCircleRadius).attr("fill", "white").attr("stroke", theme.componentStroke).attr("stroke-width", 2);
733
+ nodeEnter.filter((node) => node.isPipelineParent === true).append("rect").attr("x", (node) => positions.get(node.id).x - squareSize / 2).attr("y", (node) => positions.get(node.id).y - squareSize / 2).attr("width", squareSize).attr("height", squareSize).attr("fill", theme.componentFill).attr("stroke", theme.componentStroke).attr("stroke-width", 1);
734
+ nodeEnter.filter((node) => node.inertia === true).append("line").attr("class", "wardley-inertia").attr("x1", (node) => {
735
+ const pos = positions.get(node.id);
736
+ let offset = node.isPipelineParent ? squareSize / 2 + 15 : configValues.nodeRadius + 15;
737
+ if (node.sourceStrategy) {
738
+ offset += configValues.nodeRadius + 10;
739
+ }
740
+ return pos.x + offset;
741
+ }).attr("y1", (node) => {
742
+ const pos = positions.get(node.id);
743
+ const lineHeight = node.isPipelineParent ? squareSize : configValues.nodeRadius * 2;
744
+ return pos.y - lineHeight / 2;
745
+ }).attr("x2", (node) => {
746
+ const pos = positions.get(node.id);
747
+ let offset = node.isPipelineParent ? squareSize / 2 + 15 : configValues.nodeRadius + 15;
748
+ if (node.sourceStrategy) {
749
+ offset += configValues.nodeRadius + 10;
750
+ }
751
+ return pos.x + offset;
752
+ }).attr("y2", (node) => {
753
+ const pos = positions.get(node.id);
754
+ const lineHeight = node.isPipelineParent ? squareSize : configValues.nodeRadius * 2;
755
+ return pos.y + lineHeight / 2;
756
+ }).attr("stroke", theme.componentStroke).attr("stroke-width", 6);
757
+ nodeEnter.append("text").attr("x", (node) => {
758
+ const pos = positions.get(node.id);
759
+ if (node.className === "anchor") {
760
+ return node.labelOffsetX !== void 0 ? pos.x + node.labelOffsetX : pos.x;
761
+ }
762
+ let defaultOffset = configValues.nodeLabelOffset;
763
+ if (node.sourceStrategy && node.labelOffsetX === void 0) {
764
+ defaultOffset += 10;
765
+ }
766
+ const customOffset = node.labelOffsetX ?? defaultOffset;
767
+ return pos.x + customOffset;
768
+ }).attr("y", (node) => {
769
+ const pos = positions.get(node.id);
770
+ if (node.className === "anchor") {
771
+ return node.labelOffsetY !== void 0 ? pos.y + node.labelOffsetY : pos.y - 3;
772
+ }
773
+ let defaultOffset = -configValues.nodeLabelOffset;
774
+ if (node.sourceStrategy && node.labelOffsetY === void 0) {
775
+ defaultOffset -= 10;
776
+ }
777
+ const customOffset = node.labelOffsetY ?? defaultOffset;
778
+ return pos.y + customOffset;
779
+ }).attr("class", "wardley-node-label").attr("fill", (node) => {
780
+ if (node.className === "evolved") {
781
+ return theme.evolutionStroke;
782
+ }
783
+ if (node.className === "anchor") {
784
+ return "#000";
785
+ }
786
+ return theme.componentLabelColor;
787
+ }).attr("font-size", configValues.labelFontSize).attr("font-weight", (node) => node.className === "anchor" ? "bold" : "normal").attr("text-anchor", (node) => node.className === "anchor" ? "middle" : "start").attr("dominant-baseline", (node) => node.className === "anchor" ? "middle" : "auto").text((node) => node.label);
788
+ if (data.annotations.length > 0) {
789
+ const annotationsGroup = root.append("g").attr("class", "wardley-annotations");
790
+ data.annotations.forEach((annotation) => {
791
+ const projectedCoords = annotation.coordinates.map((coord) => ({
792
+ x: projectX(coord.x),
793
+ y: projectY(coord.y)
794
+ }));
795
+ if (projectedCoords.length > 1) {
796
+ for (let i = 0; i < projectedCoords.length - 1; i++) {
797
+ annotationsGroup.append("line").attr("class", "wardley-annotation-line").attr("x1", projectedCoords[i].x).attr("y1", projectedCoords[i].y).attr("x2", projectedCoords[i + 1].x).attr("y2", projectedCoords[i + 1].y).attr("stroke", theme.axisColor).attr("stroke-width", 1.5).attr("stroke-dasharray", "4 4");
798
+ }
799
+ }
800
+ projectedCoords.forEach((coord) => {
801
+ const annotationNode = annotationsGroup.append("g").attr("class", "wardley-annotation");
802
+ annotationNode.append("circle").attr("cx", coord.x).attr("cy", coord.y).attr("r", 10).attr("fill", "white").attr("stroke", theme.axisColor).attr("stroke-width", 1.5);
803
+ annotationNode.append("text").attr("x", coord.x).attr("y", coord.y).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", 10).attr("fill", theme.axisTextColor).attr("font-weight", "bold").text(annotation.number);
804
+ });
805
+ });
806
+ if (data.annotationsBox) {
807
+ let boxX = projectX(data.annotationsBox.x);
808
+ let boxY = projectY(data.annotationsBox.y);
809
+ const padding = 10;
810
+ const lineHeight = 16;
811
+ const fontSize = 11;
812
+ const textBoxGroup = annotationsGroup.append("g").attr("class", "wardley-annotations-box");
813
+ const sortedAnnotations = [...data.annotations].filter((a) => a.text).sort((a, b) => a.number - b.number);
814
+ const textElements = [];
815
+ sortedAnnotations.forEach((annotation, idx) => {
816
+ const text2 = textBoxGroup.append("text").attr("x", boxX + padding).attr("y", boxY + padding + (idx + 1) * lineHeight).attr("font-size", fontSize).attr("fill", theme.axisTextColor).attr("text-anchor", "start").attr("dominant-baseline", "middle").text(`${annotation.number}. ${annotation.text}`);
817
+ textElements.push(text2);
818
+ });
819
+ if (textElements.length > 0) {
820
+ let maxWidth = 0;
821
+ let maxHeight = 0;
822
+ textElements.forEach((text2) => {
823
+ const textNode = text2.node();
824
+ const textWidth = textNode.getComputedTextLength();
825
+ maxWidth = Math.max(maxWidth, textWidth);
826
+ const bbox = textNode.getBBox();
827
+ maxHeight = Math.max(maxHeight, bbox.height);
828
+ });
829
+ const boxWidth = maxWidth + padding * 2 + 105;
830
+ const boxHeight = sortedAnnotations.length * lineHeight + padding * 2 + maxHeight / 2;
831
+ const minX = configValues.padding;
832
+ const maxX = width - configValues.padding - boxWidth;
833
+ const minY = configValues.padding;
834
+ const maxY = height - configValues.padding - boxHeight;
835
+ boxX = Math.max(minX, Math.min(boxX, maxX));
836
+ boxY = Math.max(minY, Math.min(boxY, maxY));
837
+ textElements.forEach((text2, idx) => {
838
+ text2.attr("x", boxX + padding).attr("y", boxY + padding + (idx + 1) * lineHeight);
839
+ });
840
+ textBoxGroup.insert("rect", "text").attr("x", boxX).attr("y", boxY).attr("width", boxWidth).attr("height", boxHeight).attr("fill", "white").attr("stroke", theme.axisColor).attr("stroke-width", 1.5).attr("rx", 4).attr("ry", 4);
841
+ }
842
+ }
843
+ }
844
+ if (data.notes.length > 0) {
845
+ const notesGroup = root.append("g").attr("class", "wardley-notes");
846
+ data.notes.forEach((note) => {
847
+ const noteX = projectX(note.x);
848
+ const noteY = projectY(note.y);
849
+ notesGroup.append("text").attr("x", noteX).attr("y", noteY).attr("text-anchor", "start").attr("font-size", 11).attr("fill", theme.axisTextColor).attr("font-weight", "bold").text(note.text);
850
+ });
851
+ }
852
+ if (data.accelerators.length > 0) {
853
+ const acceleratorsGroup = root.append("g").attr("class", "wardley-accelerators");
854
+ data.accelerators.forEach((accelerator) => {
855
+ const accX = projectX(accelerator.x);
856
+ const accY = projectY(accelerator.y);
857
+ const arrowWidth = 60;
858
+ const arrowHeight = 30;
859
+ const arrowHeadWidth = 20;
860
+ const arrowPath = `
861
+ M ${accX} ${accY - arrowHeight / 2}
862
+ L ${accX + arrowWidth - arrowHeadWidth} ${accY - arrowHeight / 2}
863
+ L ${accX + arrowWidth - arrowHeadWidth} ${accY - arrowHeight / 2 - 8}
864
+ L ${accX + arrowWidth} ${accY}
865
+ L ${accX + arrowWidth - arrowHeadWidth} ${accY + arrowHeight / 2 + 8}
866
+ L ${accX + arrowWidth - arrowHeadWidth} ${accY + arrowHeight / 2}
867
+ L ${accX} ${accY + arrowHeight / 2}
868
+ Z
869
+ `;
870
+ acceleratorsGroup.append("path").attr("d", arrowPath).attr("fill", "white").attr("stroke", theme.componentStroke).attr("stroke-width", 1);
871
+ acceleratorsGroup.append("text").attr("x", accX + arrowWidth / 2).attr("y", accY + arrowHeight / 2 + 15).attr("text-anchor", "middle").attr("font-size", 10).attr("fill", theme.axisTextColor).attr("font-weight", "bold").text(accelerator.name);
872
+ });
873
+ }
874
+ if (data.deaccelerators.length > 0) {
875
+ const deacceleratorsGroup = root.append("g").attr("class", "wardley-deaccelerators");
876
+ data.deaccelerators.forEach((deaccelerator) => {
877
+ const decX = projectX(deaccelerator.x);
878
+ const decY = projectY(deaccelerator.y);
879
+ const arrowWidth = 60;
880
+ const arrowHeight = 30;
881
+ const arrowHeadWidth = 20;
882
+ const arrowPath = `
883
+ M ${decX + arrowWidth} ${decY - arrowHeight / 2}
884
+ L ${decX + arrowHeadWidth} ${decY - arrowHeight / 2}
885
+ L ${decX + arrowHeadWidth} ${decY - arrowHeight / 2 - 8}
886
+ L ${decX} ${decY}
887
+ L ${decX + arrowHeadWidth} ${decY + arrowHeight / 2 + 8}
888
+ L ${decX + arrowHeadWidth} ${decY + arrowHeight / 2}
889
+ L ${decX + arrowWidth} ${decY + arrowHeight / 2}
890
+ Z
891
+ `;
892
+ deacceleratorsGroup.append("path").attr("d", arrowPath).attr("fill", "white").attr("stroke", theme.componentStroke).attr("stroke-width", 1);
893
+ deacceleratorsGroup.append("text").attr("x", decX + arrowWidth / 2).attr("y", decY + arrowHeight / 2 + 15).attr("text-anchor", "middle").attr("font-size", 10).attr("fill", theme.axisTextColor).attr("font-weight", "bold").text(deaccelerator.name);
894
+ });
895
+ }
896
+ }, "draw");
897
+ var wardleyRenderer_default = {
898
+ draw
899
+ };
900
+ var styles = /* @__PURE__ */ __name(({
901
+ wardley
902
+ } = {}) => {
903
+ const defaultThemeVariables = getThemeVariables3();
904
+ const currentConfig = getConfig();
905
+ const themeVariables = cleanAndMerge(defaultThemeVariables, currentConfig.themeVariables);
906
+ const w = cleanAndMerge(themeVariables.wardley, wardley);
907
+ return `
908
+ .wardley-background {
909
+ fill: ${w.backgroundColor};
910
+ }
911
+ .wardley-axes line, .wardley-axes path {
912
+ stroke: ${w.axisColor};
913
+ }
914
+ .wardley-axis-label {
915
+ fill: ${w.axisTextColor};
916
+ }
917
+ .wardley-stage-label {
918
+ fill: ${w.axisTextColor};
919
+ }
920
+ .wardley-grid line {
921
+ stroke: ${w.gridColor};
922
+ }
923
+ .wardley-node circle {
924
+ fill: ${w.componentFill};
925
+ stroke: ${w.componentStroke};
926
+ }
927
+ .wardley-node-label {
928
+ fill: ${w.componentLabelColor};
929
+ }
930
+ .wardley-link {
931
+ stroke: ${w.linkStroke};
932
+ }
933
+ .wardley-link--dashed {
934
+ stroke-dasharray: 4 4;
935
+ }
936
+ .wardley-link-label {
937
+ fill: ${w.axisTextColor};
938
+ }
939
+ .wardley-trend line {
940
+ stroke: ${w.evolutionStroke};
941
+ }
942
+ .wardley-annotation-line {
943
+ stroke: ${w.annotationStroke};
944
+ }
945
+ .wardley-annotation circle {
946
+ fill: ${w.annotationFill};
947
+ stroke: ${w.annotationStroke};
948
+ }
949
+ .wardley-annotation text {
950
+ fill: ${w.annotationTextColor};
951
+ }
952
+ .wardley-annotations-box rect {
953
+ fill: ${w.annotationFill};
954
+ stroke: ${w.annotationStroke};
955
+ }
956
+ .wardley-annotations-box text {
957
+ fill: ${w.annotationTextColor};
958
+ }
959
+ .wardley-pipeline-box {
960
+ stroke: ${w.componentStroke};
961
+ }
962
+ .wardley-notes text {
963
+ fill: ${w.axisTextColor};
964
+ }
965
+ `;
966
+ }, "styles");
967
+ var diagram = {
968
+ parser,
969
+ db: wardleyDb_default,
970
+ renderer: wardleyRenderer_default,
971
+ styles
972
+ };
973
+ export {
974
+ diagram
975
+ };