@webskill/sdk 0.21.0 → 0.23.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 (135) hide show
  1. package/dist/abnfDiagram-O67JEVCF-DtYFjfqO.js +109 -0
  2. package/dist/agent.d.ts +3 -3
  3. package/dist/agent.js +1174 -169
  4. package/dist/{approval-DwN2o2QG.js → approval-7CuZS3Z4.js} +104 -18
  5. package/dist/arc-8U_6NQWm.js +130 -0
  6. package/dist/architecture-7GRP2DOG-RTw1wpAq.js +4 -0
  7. package/dist/architectureDiagram-NJMV4G6O-XmmXrJAK.js +7473 -0
  8. package/dist/array-DQfpQNY8.js +8 -0
  9. package/dist/blockDiagram-BEXU5L5S-D4yjnCD1.js +2582 -0
  10. package/dist/browser.d.ts +455 -49
  11. package/dist/browser.js +2134 -138
  12. package/dist/c4Diagram-YGBWAQC7-BLmA_JSd.js +3668 -0
  13. package/dist/channel-CZxxLrG7.js +9 -0
  14. package/dist/chunk-2Q5K7J3B-Ck03gkFR.js +21 -0
  15. package/dist/chunk-3FUC2YCW-tr6jmbQf.js +530 -0
  16. package/dist/chunk-5DYCD2WN-Bt97YGTd.js +58 -0
  17. package/dist/chunk-5VM5RSS4-BBxa48HL.js +21 -0
  18. package/dist/chunk-6AEJRKK7-JXK89I-O.js +14 -0
  19. package/dist/chunk-742MDFTN-CPmgCGwC.js +466 -0
  20. package/dist/chunk-7INBJB4K-C9jq9o66.js +6552 -0
  21. package/dist/chunk-7M6MHVWA-BrKCWcR1.js +4894 -0
  22. package/dist/chunk-7PRAP22T-BHED6GVs.js +95 -0
  23. package/dist/chunk-DUW6YSOI-DoZj78PO.js +19 -0
  24. package/dist/chunk-FOHPRMQF-Dkbp819z.js +27189 -0
  25. package/dist/chunk-GNY47TPC-Bpvq1T49.js +87 -0
  26. package/dist/chunk-GTNCS2PH-CLmh4I2c.js +686 -0
  27. package/dist/chunk-GWA4HPMP-B6vN3fkL.js +95 -0
  28. package/dist/chunk-J5ZVWO5B-Bi_Pcobw.js +26 -0
  29. package/dist/chunk-JWPE2WC7-D1rC79GS.js +12 -0
  30. package/dist/chunk-LNGE3PJU-D5OIoe3Z.js +2582 -0
  31. package/dist/chunk-MBY4JIJT-C34L7a4f.js +2276 -0
  32. package/dist/chunk-NETBCI7D-Cg84k8N8.js +321 -0
  33. package/dist/chunk-O7XYJQB3-B6K0KOSL.js +8846 -0
  34. package/dist/chunk-UA2S7LBM-DxHM29_K.js +612 -0
  35. package/dist/chunk-WEXAMYUT-Ba6jFWhB.js +33 -0
  36. package/dist/chunk-XXDRQBXY-DPbSy4kg.js +12 -0
  37. package/dist/chunk-Y2CYZVJY-U3QOMqrW.js +15 -0
  38. package/dist/chunk-Z7XXMR3K-oLg1h8F3.js +1038 -0
  39. package/dist/chunk-ZIGJFQKS-DqEFBuHR.js +2215 -0
  40. package/dist/classDiagram-v2-NBCMYWYE-BqnOWIUt.js +3845 -0
  41. package/dist/cose-bilkent-JH36ORCC-C0dTAHVK.js +4270 -0
  42. package/dist/cynefin-OW5HDTMX-B2QvgEQj.js +4 -0
  43. package/dist/cynefinDiagram-VND7K2PF-yAWc6Z3W.js +479 -0
  44. package/dist/cytoscape.esm-C64mRh9B.js +28325 -0
  45. package/dist/dagre-6A5THRUB-D0w2W27v.js +4816 -0
  46. package/dist/defaultLocale-B_EoOkSF.js +249 -0
  47. package/dist/diagram-22UHCM2B-DvgzhUzP.js +6115 -0
  48. package/dist/diagram-3UASUU5V-DWgUB-ef.js +795 -0
  49. package/dist/diagram-ATOU4E4O-P1olqwIs.js +553 -0
  50. package/dist/diagram-CDSNMT55-BUlZuLUe.js +402 -0
  51. package/dist/diagram-MLGK6HIB-6w5qmkGt.js +186 -0
  52. package/dist/diagram-MPIPVDR6-DEFiSo8o.js +289 -0
  53. package/dist/dist-UajCDt3n.js +92 -0
  54. package/dist/ebnfDiagram-ZINNZB2B-CI8liCfR.js +123 -0
  55. package/dist/elk-276RUBZZ-3SvW6OAK.js +90034 -0
  56. package/dist/erDiagram-OPXOYQCR-CPTbKhwP.js +2301 -0
  57. package/dist/eventmodeling-NTZA5JFV-BlyuqGp0.js +4 -0
  58. package/dist/flowDiagram-KWPJA3E3-CcUJ6HbV.js +18 -0
  59. package/dist/ganttDiagram-FUAMR5RP-31UjY0KK.js +3939 -0
  60. package/dist/{toolSource-C9oNuKmr.js → geometry-CRhuySKV.js} +169 -12
  61. package/dist/gitGraph-4MIJSDKK-ChdVlrk7.js +4 -0
  62. package/dist/gitGraphDiagram-X574FWY7-DKuxJymB.js +1153 -0
  63. package/dist/governance.d.ts +22 -4
  64. package/dist/governance.js +100 -10
  65. package/dist/graphlib-tk9gQYuN.js +4194 -0
  66. package/dist/{index-DHopiH_m.d.ts → index-7No55dRb.d.ts} +161 -11
  67. package/dist/{index-B8Tgmpwh.d.ts → index-ShvCB5I9.d.ts} +2 -2
  68. package/dist/{index-CYLt5u4L.d.ts → index-V76_OFj2.d.ts} +789 -21
  69. package/dist/index.d.ts +4 -4
  70. package/dist/index.js +11 -9
  71. package/dist/info-A6RAGUB7-CxRAt9S9.js +4 -0
  72. package/dist/infoDiagram-VRGFBTTK-pRspGfjZ.js +25 -0
  73. package/dist/init-CMOIWdg-.js +16 -0
  74. package/dist/ishikawaDiagram-OU5B5YK6-DKerAPAg.js +975 -0
  75. package/dist/journeyDiagram-ZHPQQLJL-C4MK-YO5.js +1227 -0
  76. package/dist/kanban-definition-PNTS6WVX-BqsZpMXx.js +1244 -0
  77. package/dist/katex-BcRRvyh_.js +26465 -0
  78. package/dist/{kind-DaKqLX2F.js → kind-Dc8x0HWz.js} +54 -7
  79. package/dist/line-LgV8iVMV.js +48 -0
  80. package/dist/linear-BWKR0Tqd.js +393 -0
  81. package/dist/linkedDocument-CZZOl9cO.js +456 -0
  82. package/dist/mcp.d.ts +2 -2
  83. package/dist/{memoryArtifactStore-D6dLeY55.js → memoryArtifactStore-Bs7glPqm.js} +14 -0
  84. package/dist/mermaid-parser.core-pYR5siSx.js +754 -0
  85. package/dist/mermaid.core-DMtwGCHy.js +1756 -0
  86. package/dist/mindmap-definition-NLK3R4M7-CXbD-myG.js +1312 -0
  87. package/dist/node.d.ts +3 -3
  88. package/dist/node.js +12 -5
  89. package/dist/{openUiLibrary-b0i7F_oZ.js → openUiLibrary-B7j3rLrm.js} +1 -1
  90. package/dist/{openUiSpecLang-CLXJEeRU.js → openUiSpecLang-BSYYnjay.js} +1 -1
  91. package/dist/ordinal-CxA6GHQS.js +84 -0
  92. package/dist/packet-AYTQ26CC-BOm08cxl.js +4 -0
  93. package/dist/path-C27Z2Bjv.js +106 -0
  94. package/dist/{pathSecurity-B1owvJAF.js → pathSecurity-CirkQwWP.js} +12 -1
  95. package/dist/pegDiagram-GJSIUBJH-BLGJOewQ.js +115 -0
  96. package/dist/pie-WAS4IAKB-Dvg7glpk.js +4 -0
  97. package/dist/pieDiagram-5QR66LMP-laoaV_PB.js +298 -0
  98. package/dist/quadrantDiagram-O4NWA36T-Db_wFBkT.js +2236 -0
  99. package/dist/radar-RG4KPBEZ-BZDaTu06.js +4 -0
  100. package/dist/railroad-74A4TZTK-C-UhjkOy.js +4 -0
  101. package/dist/railroad-abnf-HS5TGJTU-dUKVA4OS.js +4 -0
  102. package/dist/railroad-ebnf-LZEXJU2U-DzQumk18.js +4 -0
  103. package/dist/railroad-peg-WCYAUIDC-B3vvTWed.js +4 -0
  104. package/dist/railroadDiagram-XR7U4H2S-BY0sTM4X.js +89 -0
  105. package/dist/requirementDiagram-PLB6GJNP-3rkQfEhs.js +2474 -0
  106. package/dist/rough.cjs-AmDd_NQk.js +1395 -0
  107. package/dist/sankeyDiagram-IPEJSGJF-CGAJhyG2.js +3578 -0
  108. package/dist/sequenceDiagram-PO4LG4MO-9FJjFX06.js +5522 -0
  109. package/dist/sizeCapture-INFHLROL-D8PWxdOn.js +56 -0
  110. package/dist/{skill-CAJMsLod.js → skill-WSUDp6A1.js} +1 -1
  111. package/dist/{skillVersionStore-B24Jjjry-BkOk9wI_.d.ts → skillVersionStore-S4_HJ_Fl-Cvy9LqVu.d.ts} +35 -4
  112. package/dist/src-NkhI3UMl.js +2653 -0
  113. package/dist/stateDiagram-v2-GCMORJYK-B0O3wc1-.js +2715 -0
  114. package/dist/swimlanes-2SLR337P-D4EOnrpu.js +6637 -0
  115. package/dist/swimlanesDiagram-TC7HE7FX-BUx29EJ9.js +30 -0
  116. package/dist/testing.d.ts +2 -1
  117. package/dist/testing.js +1 -1
  118. package/dist/timeline-definition-EJHVYXUP-CrgiiB4C.js +1513 -0
  119. package/dist/treeView-Q6P3EWNA-C1by-Gzc.js +4 -0
  120. package/dist/treemap-WGGIJYW6-mC2NZ6ad.js +4 -0
  121. package/dist/{types-BvTV_05--BW8zDuEk.d.ts → types-CpDRZ0rA-BiZBXGm4.d.ts} +66 -8
  122. package/dist/ui-react.d.ts +3 -3
  123. package/dist/ui-react.js +3746 -96
  124. package/dist/ui-vue.d.ts +1 -1
  125. package/dist/ui.d.ts +3 -3
  126. package/dist/ui.js +2 -2
  127. package/dist/usecaseDiagram-POWQR4AR-BUt_TQOY.js +14397 -0
  128. package/dist/vennDiagram-UO4OBE2U-CwXr0wjA.js +2808 -0
  129. package/dist/wardley-WFR3VGLG-CVSYjq_S.js +4 -0
  130. package/dist/wardleyDiagram-VNRHLVJA-Cpfd47dQ.js +874 -0
  131. package/dist/{webSkillApi-Cib6G-94.js → webSkillApi-D5VMUnrv.js} +2 -2
  132. package/dist/{webskillLitCatalog-W06npwej.js → webskillLitCatalog-D5BCiMCU.js} +1 -1
  133. package/dist/xychartDiagram-PMCCYNJV-e1TeVoc6.js +2704 -0
  134. package/package.json +1 -1
  135. package/dist/linkedDocument-C0gj1sMq.js +0 -245
@@ -0,0 +1,2808 @@
1
+ import { o as __toESM } from "./rolldown-runtime-BHkdefai.js";
2
+ import { n as __name } from "./chunk-Y2CYZVJY-U3QOMqrW.js";
3
+ import { p as select_default } from "./src-NkhI3UMl.js";
4
+ import { H as setAccDescription, U as setAccTitle, a as clear, b as getConfig, c as configureSvgSize, f as defaultConfig_default, it as isDark, nt as lighten, q as setDiagramTitle, rt as adjustChannel, tt as darken, v as getAccDescription, w as getDiagramTitle, y as getAccTitle } from "./chunk-O7XYJQB3-B6K0KOSL.js";
5
+ import { i as cleanAndMerge } from "./chunk-ZIGJFQKS-DqEFBuHR.js";
6
+ import { t as selectSvgElement } from "./chunk-6AEJRKK7-JXK89I-O.js";
7
+ import { t as require_rough_cjs } from "./rough.cjs-AmDd_NQk.js";
8
+
9
+ //#region ../../node_modules/.pnpm/khroma@2.1.0/node_modules/khroma/dist/methods/transparentize.js
10
+ const transparentize = (color, amount) => {
11
+ return adjustChannel(color, "a", -amount);
12
+ };
13
+
14
+ //#endregion
15
+ //#region ../../node_modules/.pnpm/@upsetjs+venn.js@2.0.0/node_modules/@upsetjs/venn.js/build/venn.esm.js
16
+ const SMALL$1 = 1e-10;
17
+ /**
18
+ * Returns the intersection area of a bunch of circles (where each circle
19
+ * is an object having an x,y and radius property)
20
+ * @param {ReadonlyArray<{x: number, y: number, radius: number}>} circles
21
+ * @param {undefined | { area?: number, arcArea?: number, polygonArea?: number, arcs?: ReadonlyArray<{ circle: {x: number, y: number, radius: number}, width: number, p1: {x: number, y: number}, p2: {x: number, y: number} }>, innerPoints: ReadonlyArray<{
22
+ x: number;
23
+ y: number;
24
+ parentIndex: [number, number];
25
+ }>, intersectionPoints: ReadonlyArray<{
26
+ x: number;
27
+ y: number;
28
+ parentIndex: [number, number];
29
+ }> }} stats
30
+ * @returns {number}
31
+ */
32
+ function intersectionArea(circles, stats) {
33
+ const intersectionPoints = getIntersectionPoints(circles);
34
+ const innerPoints = intersectionPoints.filter((p) => containedInCircles(p, circles));
35
+ let arcArea = 0;
36
+ let polygonArea = 0;
37
+ /** @type {{ circle: {x: number, y: number, radius: number}, width: number, p1: {x: number, y: number}, p2: {x: number, y: number} }[]} */
38
+ const arcs = [];
39
+ if (innerPoints.length > 1) {
40
+ const center = getCenter(innerPoints);
41
+ for (let i = 0; i < innerPoints.length; ++i) {
42
+ const p = innerPoints[i];
43
+ p.angle = Math.atan2(p.x - center.x, p.y - center.y);
44
+ }
45
+ innerPoints.sort((a, b) => b.angle - a.angle);
46
+ let p2 = innerPoints[innerPoints.length - 1];
47
+ for (let i = 0; i < innerPoints.length; ++i) {
48
+ const p1 = innerPoints[i];
49
+ polygonArea += (p2.x + p1.x) * (p1.y - p2.y);
50
+ const midPoint = {
51
+ x: (p1.x + p2.x) / 2,
52
+ y: (p1.y + p2.y) / 2
53
+ };
54
+ /** @types null | { circle: {x: number, y: number, radius: number}, width: number, p1: {x: number, y: number}, p2: {x: number, y: number} } */
55
+ let arc = null;
56
+ for (let j = 0; j < p1.parentIndex.length; ++j) if (p2.parentIndex.includes(p1.parentIndex[j])) {
57
+ const circle = circles[p1.parentIndex[j]];
58
+ const a1 = Math.atan2(p1.x - circle.x, p1.y - circle.y);
59
+ const a2 = Math.atan2(p2.x - circle.x, p2.y - circle.y);
60
+ let angleDiff = a2 - a1;
61
+ if (angleDiff < 0) angleDiff += 2 * Math.PI;
62
+ const a = a2 - angleDiff / 2;
63
+ let width = distance(midPoint, {
64
+ x: circle.x + circle.radius * Math.sin(a),
65
+ y: circle.y + circle.radius * Math.cos(a)
66
+ });
67
+ if (width > circle.radius * 2) width = circle.radius * 2;
68
+ if (arc == null || arc.width > width) arc = {
69
+ circle,
70
+ width,
71
+ p1,
72
+ p2,
73
+ large: width > circle.radius,
74
+ sweep: true
75
+ };
76
+ }
77
+ if (arc != null) {
78
+ arcs.push(arc);
79
+ arcArea += circleArea(arc.circle.radius, arc.width);
80
+ p2 = p1;
81
+ }
82
+ }
83
+ } else {
84
+ let smallest = circles[0];
85
+ for (let i = 1; i < circles.length; ++i) if (circles[i].radius < smallest.radius) smallest = circles[i];
86
+ let disjoint = false;
87
+ for (let i = 0; i < circles.length; ++i) if (distance(circles[i], smallest) > Math.abs(smallest.radius - circles[i].radius)) {
88
+ disjoint = true;
89
+ break;
90
+ }
91
+ if (disjoint) arcArea = polygonArea = 0;
92
+ else {
93
+ arcArea = smallest.radius * smallest.radius * Math.PI;
94
+ arcs.push({
95
+ circle: smallest,
96
+ p1: {
97
+ x: smallest.x,
98
+ y: smallest.y + smallest.radius
99
+ },
100
+ p2: {
101
+ x: smallest.x - SMALL$1,
102
+ y: smallest.y + smallest.radius
103
+ },
104
+ width: smallest.radius * 2,
105
+ large: true,
106
+ sweep: true
107
+ });
108
+ }
109
+ }
110
+ polygonArea /= 2;
111
+ if (stats) {
112
+ stats.area = arcArea + polygonArea;
113
+ stats.arcArea = arcArea;
114
+ stats.polygonArea = polygonArea;
115
+ stats.arcs = arcs;
116
+ stats.innerPoints = innerPoints;
117
+ stats.intersectionPoints = intersectionPoints;
118
+ }
119
+ return arcArea + polygonArea;
120
+ }
121
+ /**
122
+ * returns whether a point is contained by all of a list of circles
123
+ * @param {{x: number, y: number}} point
124
+ * @param {ReadonlyArray<{x: number, y: number, radius: number}>} circles
125
+ * @returns {boolean}
126
+ */
127
+ function containedInCircles(point, circles) {
128
+ return circles.every((circle) => distance(point, circle) < circle.radius + SMALL$1);
129
+ }
130
+ /**
131
+ * Gets all intersection points between a bunch of circles
132
+ * @param {ReadonlyArray<{x: number, y: number, radius: number}>} circles
133
+ * @returns {ReadonlyArray<{x: number, y: number, parentIndex: [number, number]}>}
134
+ */
135
+ function getIntersectionPoints(circles) {
136
+ /** @type {{x: number, y: number, parentIndex: [number, number]}[]} */
137
+ const ret = [];
138
+ for (let i = 0; i < circles.length; ++i) for (let j = i + 1; j < circles.length; ++j) {
139
+ const intersect = circleCircleIntersection(circles[i], circles[j]);
140
+ for (const p of intersect) {
141
+ p.parentIndex = [i, j];
142
+ ret.push(p);
143
+ }
144
+ }
145
+ return ret;
146
+ }
147
+ /**
148
+ * Circular segment area calculation. See http://mathworld.wolfram.com/CircularSegment.html
149
+ * @param {number} r
150
+ * @param {number} width
151
+ * @returns {number}
152
+ **/
153
+ function circleArea(r, width) {
154
+ return r * r * Math.acos(1 - width / r) - (r - width) * Math.sqrt(width * (2 * r - width));
155
+ }
156
+ /**
157
+ * euclidean distance between two points
158
+ * @param {{x: number, y: number}} p1
159
+ * @param {{x: number, y: number}} p2
160
+ * @returns {number}
161
+ **/
162
+ function distance(p1, p2) {
163
+ return Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
164
+ }
165
+ /**
166
+ * Returns the overlap area of two circles of radius r1 and r2 - that
167
+ * have their centers separated by distance d. Simpler faster
168
+ * circle intersection for only two circles
169
+ * @param {number} r1
170
+ * @param {number} r2
171
+ * @param {number} d
172
+ * @returns {number}
173
+ */
174
+ function circleOverlap(r1, r2, d) {
175
+ if (d >= r1 + r2) return 0;
176
+ if (d <= Math.abs(r1 - r2)) return Math.PI * Math.min(r1, r2) * Math.min(r1, r2);
177
+ const w1 = r1 - (d * d - r2 * r2 + r1 * r1) / (2 * d);
178
+ const w2 = r2 - (d * d - r1 * r1 + r2 * r2) / (2 * d);
179
+ return circleArea(r1, w1) + circleArea(r2, w2);
180
+ }
181
+ /**
182
+ * Given two circles (containing a x/y/radius attributes),
183
+ * returns the intersecting points if possible
184
+ * note: doesn't handle cases where there are infinitely many
185
+ * intersection points (circles are equivalent):, or only one intersection point
186
+ * @param {{x: number, y: number, radius: number}} p1
187
+ * @param {{x: number, y: number, radius: number}} p2
188
+ * @returns {ReadonlyArray<{x: number, y: number}>}
189
+ **/
190
+ function circleCircleIntersection(p1, p2) {
191
+ const d = distance(p1, p2);
192
+ const r1 = p1.radius;
193
+ const r2 = p2.radius;
194
+ if (d >= r1 + r2 || d <= Math.abs(r1 - r2)) return [];
195
+ const a = (r1 * r1 - r2 * r2 + d * d) / (2 * d);
196
+ const h = Math.sqrt(r1 * r1 - a * a);
197
+ const x0 = p1.x + a * (p2.x - p1.x) / d;
198
+ const y0 = p1.y + a * (p2.y - p1.y) / d;
199
+ const rx = -(p2.y - p1.y) * (h / d);
200
+ const ry = -(p2.x - p1.x) * (h / d);
201
+ return [{
202
+ x: x0 + rx,
203
+ y: y0 - ry
204
+ }, {
205
+ x: x0 - rx,
206
+ y: y0 + ry
207
+ }];
208
+ }
209
+ /**
210
+ * Returns the center of a bunch of points
211
+ * @param {ReadonlyArray<{x: number, y: number}>} points
212
+ * @returns {{x: number, y: number}}
213
+ */
214
+ function getCenter(points) {
215
+ const center = {
216
+ x: 0,
217
+ y: 0
218
+ };
219
+ for (const point of points) {
220
+ center.x += point.x;
221
+ center.y += point.y;
222
+ }
223
+ center.x /= points.length;
224
+ center.y /= points.length;
225
+ return center;
226
+ }
227
+ /** finds the zeros of a function, given two starting points (which must
228
+ * have opposite signs */
229
+ function bisect(f, a, b, parameters) {
230
+ parameters = parameters || {};
231
+ const maxIterations = parameters.maxIterations || 100;
232
+ const tolerance = parameters.tolerance || 1e-10;
233
+ const fA = f(a);
234
+ const fB = f(b);
235
+ let delta = b - a;
236
+ if (fA * fB > 0) throw "Initial bisect points must have opposite signs";
237
+ if (fA === 0) return a;
238
+ if (fB === 0) return b;
239
+ for (let i = 0; i < maxIterations; ++i) {
240
+ delta /= 2;
241
+ const mid = a + delta;
242
+ const fMid = f(mid);
243
+ if (fMid * fA >= 0) a = mid;
244
+ if (Math.abs(delta) < tolerance || fMid === 0) return mid;
245
+ }
246
+ return a + delta;
247
+ }
248
+ function zeros(x) {
249
+ const r = new Array(x);
250
+ for (let i = 0; i < x; ++i) r[i] = 0;
251
+ return r;
252
+ }
253
+ function zerosM(x, y) {
254
+ return zeros(x).map(() => zeros(y));
255
+ }
256
+ function dot(a, b) {
257
+ let ret = 0;
258
+ for (let i = 0; i < a.length; ++i) ret += a[i] * b[i];
259
+ return ret;
260
+ }
261
+ function norm2(a) {
262
+ return Math.sqrt(dot(a, a));
263
+ }
264
+ function scale(ret, value, c) {
265
+ for (let i = 0; i < value.length; ++i) ret[i] = value[i] * c;
266
+ }
267
+ function weightedSum(ret, w1, v1, w2, v2) {
268
+ for (let j = 0; j < ret.length; ++j) ret[j] = w1 * v1[j] + w2 * v2[j];
269
+ }
270
+ /** minimizes a function using the downhill simplex method */
271
+ function nelderMead(f, x0, parameters) {
272
+ parameters = parameters || {};
273
+ const maxIterations = parameters.maxIterations || x0.length * 200;
274
+ const nonZeroDelta = parameters.nonZeroDelta || 1.05;
275
+ const zeroDelta = parameters.zeroDelta || .001;
276
+ const minErrorDelta = parameters.minErrorDelta || 1e-6;
277
+ const minTolerance = parameters.minErrorDelta || 1e-5;
278
+ const rho = parameters.rho !== void 0 ? parameters.rho : 1;
279
+ const chi = parameters.chi !== void 0 ? parameters.chi : 2;
280
+ const psi = parameters.psi !== void 0 ? parameters.psi : -.5;
281
+ const sigma = parameters.sigma !== void 0 ? parameters.sigma : .5;
282
+ let maxDiff;
283
+ const N = x0.length;
284
+ const simplex = new Array(N + 1);
285
+ simplex[0] = x0;
286
+ simplex[0].fx = f(x0);
287
+ simplex[0].id = 0;
288
+ for (let i = 0; i < N; ++i) {
289
+ const point = x0.slice();
290
+ point[i] = point[i] ? point[i] * nonZeroDelta : zeroDelta;
291
+ simplex[i + 1] = point;
292
+ simplex[i + 1].fx = f(point);
293
+ simplex[i + 1].id = i + 1;
294
+ }
295
+ function updateSimplex(value) {
296
+ for (let i = 0; i < value.length; i++) simplex[N][i] = value[i];
297
+ simplex[N].fx = value.fx;
298
+ }
299
+ const sortOrder = (a, b) => a.fx - b.fx;
300
+ const centroid = x0.slice();
301
+ const reflected = x0.slice();
302
+ const contracted = x0.slice();
303
+ const expanded = x0.slice();
304
+ for (let iteration = 0; iteration < maxIterations; ++iteration) {
305
+ simplex.sort(sortOrder);
306
+ if (parameters.history) {
307
+ const sortedSimplex = simplex.map((x) => {
308
+ const state = x.slice();
309
+ state.fx = x.fx;
310
+ state.id = x.id;
311
+ return state;
312
+ });
313
+ sortedSimplex.sort((a, b) => a.id - b.id);
314
+ parameters.history.push({
315
+ x: simplex[0].slice(),
316
+ fx: simplex[0].fx,
317
+ simplex: sortedSimplex
318
+ });
319
+ }
320
+ maxDiff = 0;
321
+ for (let i = 0; i < N; ++i) maxDiff = Math.max(maxDiff, Math.abs(simplex[0][i] - simplex[1][i]));
322
+ if (Math.abs(simplex[0].fx - simplex[N].fx) < minErrorDelta && maxDiff < minTolerance) break;
323
+ for (let i = 0; i < N; ++i) {
324
+ centroid[i] = 0;
325
+ for (let j = 0; j < N; ++j) centroid[i] += simplex[j][i];
326
+ centroid[i] /= N;
327
+ }
328
+ const worst = simplex[N];
329
+ weightedSum(reflected, 1 + rho, centroid, -rho, worst);
330
+ reflected.fx = f(reflected);
331
+ if (reflected.fx < simplex[0].fx) {
332
+ weightedSum(expanded, 1 + chi, centroid, -chi, worst);
333
+ expanded.fx = f(expanded);
334
+ if (expanded.fx < reflected.fx) updateSimplex(expanded);
335
+ else updateSimplex(reflected);
336
+ } else if (reflected.fx >= simplex[N - 1].fx) {
337
+ let shouldReduce = false;
338
+ if (reflected.fx > worst.fx) {
339
+ weightedSum(contracted, 1 + psi, centroid, -psi, worst);
340
+ contracted.fx = f(contracted);
341
+ if (contracted.fx < worst.fx) updateSimplex(contracted);
342
+ else shouldReduce = true;
343
+ } else {
344
+ weightedSum(contracted, 1 - psi * rho, centroid, psi * rho, worst);
345
+ contracted.fx = f(contracted);
346
+ if (contracted.fx < reflected.fx) updateSimplex(contracted);
347
+ else shouldReduce = true;
348
+ }
349
+ if (shouldReduce) {
350
+ if (sigma >= 1) break;
351
+ for (let i = 1; i < simplex.length; ++i) {
352
+ weightedSum(simplex[i], 1 - sigma, simplex[0], sigma, simplex[i]);
353
+ simplex[i].fx = f(simplex[i]);
354
+ }
355
+ }
356
+ } else updateSimplex(reflected);
357
+ }
358
+ simplex.sort(sortOrder);
359
+ return {
360
+ fx: simplex[0].fx,
361
+ x: simplex[0]
362
+ };
363
+ }
364
+ function wolfeLineSearch(f, pk, current, next, a, c1, c2) {
365
+ const phi0 = current.fx;
366
+ const phiPrime0 = dot(current.fxprime, pk);
367
+ let phi = phi0;
368
+ let phi_old = phi0;
369
+ let phiPrime = phiPrime0;
370
+ let a0 = 0;
371
+ a = a || 1;
372
+ c1 = c1 || 1e-6;
373
+ c2 = c2 || .1;
374
+ function zoom(a_lo, a_high, phi_lo) {
375
+ for (let iteration = 0; iteration < 16; ++iteration) {
376
+ a = (a_lo + a_high) / 2;
377
+ weightedSum(next.x, 1, current.x, a, pk);
378
+ phi = next.fx = f(next.x, next.fxprime);
379
+ phiPrime = dot(next.fxprime, pk);
380
+ if (phi > phi0 + c1 * a * phiPrime0 || phi >= phi_lo) a_high = a;
381
+ else {
382
+ if (Math.abs(phiPrime) <= -c2 * phiPrime0) return a;
383
+ if (phiPrime * (a_high - a_lo) >= 0) a_high = a_lo;
384
+ a_lo = a;
385
+ phi_lo = phi;
386
+ }
387
+ }
388
+ return 0;
389
+ }
390
+ for (let iteration = 0; iteration < 10; ++iteration) {
391
+ weightedSum(next.x, 1, current.x, a, pk);
392
+ phi = next.fx = f(next.x, next.fxprime);
393
+ phiPrime = dot(next.fxprime, pk);
394
+ if (phi > phi0 + c1 * a * phiPrime0 || iteration && phi >= phi_old) return zoom(a0, a, phi_old);
395
+ if (Math.abs(phiPrime) <= -c2 * phiPrime0) return a;
396
+ if (phiPrime >= 0) return zoom(a, a0, phi);
397
+ phi_old = phi;
398
+ a0 = a;
399
+ a *= 2;
400
+ }
401
+ return a;
402
+ }
403
+ function conjugateGradient(f, initial, params) {
404
+ let current = {
405
+ x: initial.slice(),
406
+ fx: 0,
407
+ fxprime: initial.slice()
408
+ };
409
+ let next = {
410
+ x: initial.slice(),
411
+ fx: 0,
412
+ fxprime: initial.slice()
413
+ };
414
+ const yk = initial.slice();
415
+ let pk;
416
+ let temp;
417
+ let a = 1;
418
+ let maxIterations;
419
+ params = params || {};
420
+ maxIterations = params.maxIterations || initial.length * 20;
421
+ current.fx = f(current.x, current.fxprime);
422
+ pk = current.fxprime.slice();
423
+ scale(pk, current.fxprime, -1);
424
+ for (let i = 0; i < maxIterations; ++i) {
425
+ a = wolfeLineSearch(f, pk, current, next, a);
426
+ if (params.history) params.history.push({
427
+ x: current.x.slice(),
428
+ fx: current.fx,
429
+ fxprime: current.fxprime.slice(),
430
+ alpha: a
431
+ });
432
+ if (!a) scale(pk, current.fxprime, -1);
433
+ else {
434
+ weightedSum(yk, 1, next.fxprime, -1, current.fxprime);
435
+ const delta_k = dot(current.fxprime, current.fxprime);
436
+ const beta_k = Math.max(0, dot(yk, next.fxprime) / delta_k);
437
+ weightedSum(pk, beta_k, pk, -1, next.fxprime);
438
+ temp = current;
439
+ current = next;
440
+ next = temp;
441
+ }
442
+ if (norm2(current.fxprime) <= 1e-5) break;
443
+ }
444
+ if (params.history) params.history.push({
445
+ x: current.x.slice(),
446
+ fx: current.fx,
447
+ fxprime: current.fxprime.slice(),
448
+ alpha: a
449
+ });
450
+ return current;
451
+ }
452
+ /**
453
+ * given a list of set objects, and their corresponding overlaps
454
+ * updates the (x, y, radius) attribute on each set such that their positions
455
+ * roughly correspond to the desired overlaps
456
+ * @param {readonly {sets: readonly string[]; size: number; weight?: number}[]} sets
457
+ * @returns {{[setid: string]: {x: number, y: number, radius: number}}}
458
+ */
459
+ function venn(sets, parameters = {}) {
460
+ parameters.maxIterations = parameters.maxIterations || 500;
461
+ const initialLayout = parameters.initialLayout || bestInitialLayout;
462
+ const loss = parameters.lossFunction || lossFunction;
463
+ const areas = addMissingAreas(sets, parameters);
464
+ const circles = initialLayout(areas, parameters);
465
+ const setids = Object.keys(circles);
466
+ /** @type {number[]} */
467
+ const initial = [];
468
+ for (const setid of setids) {
469
+ initial.push(circles[setid].x);
470
+ initial.push(circles[setid].y);
471
+ }
472
+ const positions = nelderMead((values) => {
473
+ const current = {};
474
+ for (let i = 0; i < setids.length; ++i) {
475
+ const setid = setids[i];
476
+ current[setid] = {
477
+ x: values[2 * i],
478
+ y: values[2 * i + 1],
479
+ radius: circles[setid].radius
480
+ };
481
+ }
482
+ return loss(current, areas);
483
+ }, initial, parameters).x;
484
+ for (let i = 0; i < setids.length; ++i) {
485
+ const setid = setids[i];
486
+ circles[setid].x = positions[2 * i];
487
+ circles[setid].y = positions[2 * i + 1];
488
+ }
489
+ return circles;
490
+ }
491
+ const SMALL = 1e-10;
492
+ /**
493
+ * Returns the distance necessary for two circles of radius r1 + r2 to
494
+ * have the overlap area 'overlap'
495
+ * @param {number} r1
496
+ * @param {number} r2
497
+ * @param {number} overlap
498
+ * @returns {number}
499
+ */
500
+ function distanceFromIntersectArea(r1, r2, overlap) {
501
+ if (Math.min(r1, r2) * Math.min(r1, r2) * Math.PI <= overlap + SMALL) return Math.abs(r1 - r2);
502
+ return bisect((distance) => circleOverlap(r1, r2, distance) - overlap, 0, r1 + r2);
503
+ }
504
+ /**
505
+ * Missing pair-wise intersection area data can cause problems:
506
+ * treating as an unknown means that sets will be laid out overlapping,
507
+ * which isn't what people expect. To reflect that we want disjoint sets
508
+ * here, set the overlap to 0 for all missing pairwise set intersections
509
+ * @param {ReadonlyArray<{sets: ReadonlyArray<string>, size: number}>} areas
510
+ * @returns {ReadonlyArray<{sets: ReadonlyArray<string>, size: number}>}
511
+ */
512
+ function addMissingAreas(areas, parameters = {}) {
513
+ const distinct = parameters.distinct;
514
+ const r = areas.map((s) => Object.assign({}, s));
515
+ function toKey(arr) {
516
+ return arr.join(";");
517
+ }
518
+ if (distinct) {
519
+ /** @types Map<string, number> */
520
+ const count = /* @__PURE__ */ new Map();
521
+ for (const area of r) for (let i = 0; i < area.sets.length; i++) {
522
+ const si = String(area.sets[i]);
523
+ count.set(si, area.size + (count.get(si) || 0));
524
+ for (let j = i + 1; j < area.sets.length; j++) {
525
+ const sj = String(area.sets[j]);
526
+ const k1 = `${si};${sj}`;
527
+ const k2 = `${sj};${si}`;
528
+ count.set(k1, area.size + (count.get(k1) || 0));
529
+ count.set(k2, area.size + (count.get(k2) || 0));
530
+ }
531
+ }
532
+ for (const area of r) if (area.sets.length < 3) area.size = count.get(toKey(area.sets));
533
+ }
534
+ const ids = [];
535
+ /** @type {Set<string>} */
536
+ const pairs = /* @__PURE__ */ new Set();
537
+ for (const area of r) if (area.sets.length === 1) ids.push(area.sets[0]);
538
+ else if (area.sets.length === 2) {
539
+ const a = area.sets[0];
540
+ const b = area.sets[1];
541
+ pairs.add(toKey(area.sets));
542
+ pairs.add(toKey([b, a]));
543
+ }
544
+ ids.sort((a, b) => a === b ? 0 : a < b ? -1 : 1);
545
+ for (let i = 0; i < ids.length; ++i) {
546
+ const a = ids[i];
547
+ for (let j = i + 1; j < ids.length; ++j) {
548
+ const b = ids[j];
549
+ if (!pairs.has(toKey([a, b]))) r.push({
550
+ sets: [a, b],
551
+ size: 0
552
+ });
553
+ }
554
+ }
555
+ return r;
556
+ }
557
+ /**
558
+ * Returns two matrices, one of the euclidean distances between the sets
559
+ * and the other indicating if there are subset or disjoint set relationships
560
+ * @param {ReadonlyArray<{sets: ReadonlyArray<number>}>} areas
561
+ * @param {ReadonlyArray<{size: number}>} sets
562
+ * @param {ReadonlyArray<number>} setids
563
+ */
564
+ function getDistanceMatrices(areas, sets, setids) {
565
+ /**
566
+ * @type {number[][]}
567
+ */
568
+ const distances = zerosM(sets.length, sets.length);
569
+ /**
570
+ * @type {number[][]}
571
+ */
572
+ const constraints = zerosM(sets.length, sets.length);
573
+ areas.filter((x) => x.sets.length === 2).forEach((current) => {
574
+ const left = setids[current.sets[0]];
575
+ const right = setids[current.sets[1]];
576
+ const distance = distanceFromIntersectArea(Math.sqrt(sets[left].size / Math.PI), Math.sqrt(sets[right].size / Math.PI), current.size);
577
+ distances[left][right] = distances[right][left] = distance;
578
+ let c = 0;
579
+ if (current.size + 1e-10 >= Math.min(sets[left].size, sets[right].size)) c = 1;
580
+ else if (current.size <= 1e-10) c = -1;
581
+ constraints[left][right] = constraints[right][left] = c;
582
+ });
583
+ return {
584
+ distances,
585
+ constraints
586
+ };
587
+ }
588
+ function constrainedMDSGradient(x, fxprime, distances, constraints) {
589
+ for (let i = 0; i < fxprime.length; ++i) fxprime[i] = 0;
590
+ let loss = 0;
591
+ for (let i = 0; i < distances.length; ++i) {
592
+ const xi = x[2 * i];
593
+ const yi = x[2 * i + 1];
594
+ for (let j = i + 1; j < distances.length; ++j) {
595
+ const xj = x[2 * j];
596
+ const yj = x[2 * j + 1];
597
+ const dij = distances[i][j];
598
+ const constraint = constraints[i][j];
599
+ const squaredDistance = (xj - xi) * (xj - xi) + (yj - yi) * (yj - yi);
600
+ const distance = Math.sqrt(squaredDistance);
601
+ const delta = squaredDistance - dij * dij;
602
+ if (constraint > 0 && distance <= dij || constraint < 0 && distance >= dij) continue;
603
+ loss += 2 * delta * delta;
604
+ fxprime[2 * i] += 4 * delta * (xi - xj);
605
+ fxprime[2 * i + 1] += 4 * delta * (yi - yj);
606
+ fxprime[2 * j] += 4 * delta * (xj - xi);
607
+ fxprime[2 * j + 1] += 4 * delta * (yj - yi);
608
+ }
609
+ }
610
+ return loss;
611
+ }
612
+ /**
613
+ * takes the best working variant of either constrained MDS or greedy
614
+ * @param {ReadonlyArray<{sets: ReadonlyArray<string>, size: number}>} areas
615
+ */
616
+ function bestInitialLayout(areas, params = {}) {
617
+ let initial = greedyLayout(areas, params);
618
+ const loss = params.lossFunction || lossFunction;
619
+ if (areas.length >= 8) {
620
+ const constrained = constrainedMDSLayout(areas, params);
621
+ const constrainedLoss = loss(constrained, areas);
622
+ const greedyLoss = loss(initial, areas);
623
+ if (constrainedLoss + 1e-8 < greedyLoss) initial = constrained;
624
+ }
625
+ return initial;
626
+ }
627
+ /**
628
+ * use the constrained MDS variant to generate an initial layout
629
+ * @param {ReadonlyArray<{sets: ReadonlyArray<string>, size: number}>} areas
630
+ * @returns {{[key: string]: {x: number, y: number, radius: number}}}
631
+ */
632
+ function constrainedMDSLayout(areas, params = {}) {
633
+ const restarts = params.restarts || 10;
634
+ const sets = [];
635
+ const setids = {};
636
+ for (const area of areas) if (area.sets.length === 1) {
637
+ setids[area.sets[0]] = sets.length;
638
+ sets.push(area);
639
+ }
640
+ let { distances, constraints } = getDistanceMatrices(areas, sets, setids);
641
+ const norm = norm2(distances.map(norm2)) / distances.length;
642
+ distances = distances.map((row) => row.map((value) => value / norm));
643
+ const obj = (x, fxprime) => constrainedMDSGradient(x, fxprime, distances, constraints);
644
+ let best = null;
645
+ for (let i = 0; i < restarts; ++i) {
646
+ const current = conjugateGradient(obj, zeros(distances.length * 2).map(Math.random), params);
647
+ if (!best || current.fx < best.fx) best = current;
648
+ }
649
+ const positions = best.x;
650
+ /** @type {{[key: string]: {x: number, y: number, radius: number}}} */
651
+ const circles = {};
652
+ for (let i = 0; i < sets.length; ++i) {
653
+ const set = sets[i];
654
+ circles[set.sets[0]] = {
655
+ x: positions[2 * i] * norm,
656
+ y: positions[2 * i + 1] * norm,
657
+ radius: Math.sqrt(set.size / Math.PI)
658
+ };
659
+ }
660
+ if (params.history) for (const h of params.history) scale(h.x, norm);
661
+ return circles;
662
+ }
663
+ /**
664
+ * Lays out a Venn diagram greedily, going from most overlapped sets to
665
+ * least overlapped, attempting to position each new set such that the
666
+ * overlapping areas to already positioned sets are basically right
667
+ * @param {ReadonlyArray<{size: number, sets: ReadonlyArray<string>}>} areas
668
+ * @return {{[key: string]: {x: number, y: number, radius: number}}}
669
+ */
670
+ function greedyLayout(areas, params) {
671
+ const loss = params && params.lossFunction ? params.lossFunction : lossFunction;
672
+ /** @type {{[key: string]: {x: number, y: number, radius: number}}} */
673
+ const circles = {};
674
+ /** @type {{[key: string]: {set: string, size: number, weight: number}[]}} */
675
+ const setOverlaps = {};
676
+ for (const area of areas) if (area.sets.length === 1) {
677
+ const set = area.sets[0];
678
+ circles[set] = {
679
+ x: 1e10,
680
+ y: 1e10,
681
+ rowid: circles.length,
682
+ size: area.size,
683
+ radius: Math.sqrt(area.size / Math.PI)
684
+ };
685
+ setOverlaps[set] = [];
686
+ }
687
+ areas = areas.filter((a) => a.sets.length === 2);
688
+ for (const current of areas) {
689
+ let weight = current.weight != null ? current.weight : 1;
690
+ const left = current.sets[0];
691
+ const right = current.sets[1];
692
+ if (current.size + SMALL >= Math.min(circles[left].size, circles[right].size)) weight = 0;
693
+ setOverlaps[left].push({
694
+ set: right,
695
+ size: current.size,
696
+ weight
697
+ });
698
+ setOverlaps[right].push({
699
+ set: left,
700
+ size: current.size,
701
+ weight
702
+ });
703
+ }
704
+ const mostOverlapped = [];
705
+ Object.keys(setOverlaps).forEach((set) => {
706
+ let size = 0;
707
+ for (let i = 0; i < setOverlaps[set].length; ++i) size += setOverlaps[set][i].size * setOverlaps[set][i].weight;
708
+ mostOverlapped.push({
709
+ set,
710
+ size
711
+ });
712
+ });
713
+ function sortOrder(a, b) {
714
+ return b.size - a.size;
715
+ }
716
+ mostOverlapped.sort(sortOrder);
717
+ const positioned = {};
718
+ function isPositioned(element) {
719
+ return element.set in positioned;
720
+ }
721
+ /**
722
+ * adds a point to the output
723
+ * @param {{x: number, y: number}} point
724
+ * @param {number} index
725
+ */
726
+ function positionSet(point, index) {
727
+ circles[index].x = point.x;
728
+ circles[index].y = point.y;
729
+ positioned[index] = true;
730
+ }
731
+ positionSet({
732
+ x: 0,
733
+ y: 0
734
+ }, mostOverlapped[0].set);
735
+ for (let i = 1; i < mostOverlapped.length; ++i) {
736
+ const setIndex = mostOverlapped[i].set;
737
+ const overlap = setOverlaps[setIndex].filter(isPositioned);
738
+ const set = circles[setIndex];
739
+ overlap.sort(sortOrder);
740
+ if (overlap.length === 0) throw "ERROR: missing pairwise overlap information";
741
+ /** @type {{x: number, y: number}[]} */
742
+ const points = [];
743
+ for (var j = 0; j < overlap.length; ++j) {
744
+ const p1 = circles[overlap[j].set];
745
+ const d1 = distanceFromIntersectArea(set.radius, p1.radius, overlap[j].size);
746
+ points.push({
747
+ x: p1.x + d1,
748
+ y: p1.y
749
+ });
750
+ points.push({
751
+ x: p1.x - d1,
752
+ y: p1.y
753
+ });
754
+ points.push({
755
+ y: p1.y + d1,
756
+ x: p1.x
757
+ });
758
+ points.push({
759
+ y: p1.y - d1,
760
+ x: p1.x
761
+ });
762
+ for (let k = j + 1; k < overlap.length; ++k) {
763
+ const p2 = circles[overlap[k].set];
764
+ const d2 = distanceFromIntersectArea(set.radius, p2.radius, overlap[k].size);
765
+ const extraPoints = circleCircleIntersection({
766
+ x: p1.x,
767
+ y: p1.y,
768
+ radius: d1
769
+ }, {
770
+ x: p2.x,
771
+ y: p2.y,
772
+ radius: d2
773
+ });
774
+ points.push(...extraPoints);
775
+ }
776
+ }
777
+ let bestLoss = 1e50;
778
+ let bestPoint = points[0];
779
+ for (const point of points) {
780
+ circles[setIndex].x = point.x;
781
+ circles[setIndex].y = point.y;
782
+ const localLoss = loss(circles, areas);
783
+ if (localLoss < bestLoss) {
784
+ bestLoss = localLoss;
785
+ bestPoint = point;
786
+ }
787
+ }
788
+ positionSet(bestPoint, setIndex);
789
+ }
790
+ return circles;
791
+ }
792
+ /**
793
+ * Given a bunch of sets, and the desired overlaps between these sets - computes
794
+ * the distance from the actual overlaps to the desired overlaps. Note that
795
+ * this method ignores overlaps of more than 2 circles
796
+ * @param {{[key: string]: <{x: number, y: number, radius: number}>}} circles
797
+ * @param {ReadonlyArray<{size: number, sets: ReadonlyArray<string>, weight?: number}>} overlaps
798
+ * @returns {number}
799
+ */
800
+ function lossFunction(circles, overlaps) {
801
+ let output = 0;
802
+ for (const area of overlaps) {
803
+ if (area.sets.length === 1) continue;
804
+ /** @type {number} */
805
+ let overlap;
806
+ if (area.sets.length === 2) {
807
+ const left = circles[area.sets[0]];
808
+ const right = circles[area.sets[1]];
809
+ overlap = circleOverlap(left.radius, right.radius, distance(left, right));
810
+ } else overlap = intersectionArea(area.sets.map((d) => circles[d]));
811
+ const weight = area.weight != null ? area.weight : 1;
812
+ output += weight * (overlap - area.size) * (overlap - area.size);
813
+ }
814
+ return output;
815
+ }
816
+ function logRatioLossFunction(circles, overlaps) {
817
+ let output = 0;
818
+ for (const area of overlaps) {
819
+ if (area.sets.length === 1) continue;
820
+ /** @type {number} */
821
+ let overlap;
822
+ if (area.sets.length === 2) {
823
+ const left = circles[area.sets[0]];
824
+ const right = circles[area.sets[1]];
825
+ overlap = circleOverlap(left.radius, right.radius, distance(left, right));
826
+ } else overlap = intersectionArea(area.sets.map((d) => circles[d]));
827
+ const weight = area.weight != null ? area.weight : 1;
828
+ const differenceFromIdeal = Math.log((overlap + 1) / (area.size + 1));
829
+ output += weight * differenceFromIdeal * differenceFromIdeal;
830
+ }
831
+ return output;
832
+ }
833
+ /**
834
+ * orientates a bunch of circles to point in orientation
835
+ * @param {{x :number, y: number, radius: number}[]} circles
836
+ * @param {number | undefined} orientation
837
+ * @param {((a: {x :number, y: number, radius: number}, b: {x :number, y: number, radius: number}) => number) | undefined} orientationOrder
838
+ */
839
+ function orientateCircles(circles, orientation, orientationOrder) {
840
+ if (orientationOrder == null) circles.sort((a, b) => b.radius - a.radius);
841
+ else circles.sort(orientationOrder);
842
+ if (circles.length > 0) {
843
+ const largestX = circles[0].x;
844
+ const largestY = circles[0].y;
845
+ for (const circle of circles) {
846
+ circle.x -= largestX;
847
+ circle.y -= largestY;
848
+ }
849
+ }
850
+ if (circles.length === 2) {
851
+ if (distance(circles[0], circles[1]) < Math.abs(circles[1].radius - circles[0].radius)) {
852
+ circles[1].x = circles[0].x + circles[0].radius - circles[1].radius - 1e-10;
853
+ circles[1].y = circles[0].y;
854
+ }
855
+ }
856
+ if (circles.length > 1) {
857
+ const rotation = Math.atan2(circles[1].x, circles[1].y) - orientation;
858
+ const c = Math.cos(rotation);
859
+ const s = Math.sin(rotation);
860
+ for (const circle of circles) {
861
+ const x = circle.x;
862
+ const y = circle.y;
863
+ circle.x = c * x - s * y;
864
+ circle.y = s * x + c * y;
865
+ }
866
+ }
867
+ if (circles.length > 2) {
868
+ let angle = Math.atan2(circles[2].x, circles[2].y) - orientation;
869
+ while (angle < 0) angle += 2 * Math.PI;
870
+ while (angle > 2 * Math.PI) angle -= 2 * Math.PI;
871
+ if (angle > Math.PI) {
872
+ const slope = circles[1].y / (1e-10 + circles[1].x);
873
+ for (const circle of circles) {
874
+ var d = (circle.x + slope * circle.y) / (1 + slope * slope);
875
+ circle.x = 2 * d - circle.x;
876
+ circle.y = 2 * d * slope - circle.y;
877
+ }
878
+ }
879
+ }
880
+ }
881
+ /**
882
+ *
883
+ * @param {ReadonlyArray<{x: number, y: number, radius: number}>} circles
884
+ * @returns {{x: number, y: number, radius: number}[][]}
885
+ */
886
+ function disjointCluster(circles) {
887
+ circles.forEach((circle) => {
888
+ circle.parent = circle;
889
+ });
890
+ function find(circle) {
891
+ if (circle.parent !== circle) circle.parent = find(circle.parent);
892
+ return circle.parent;
893
+ }
894
+ function union(x, y) {
895
+ const xRoot = find(x);
896
+ xRoot.parent = find(y);
897
+ }
898
+ for (let i = 0; i < circles.length; ++i) for (let j = i + 1; j < circles.length; ++j) {
899
+ const maxDistance = circles[i].radius + circles[j].radius;
900
+ if (distance(circles[i], circles[j]) + 1e-10 < maxDistance) union(circles[j], circles[i]);
901
+ }
902
+ /** @type {Map<string, {x: number, y: number, radius: number}[]>} */
903
+ const disjointClusters = /* @__PURE__ */ new Map();
904
+ for (let i = 0; i < circles.length; ++i) {
905
+ const setid = find(circles[i]).parent.setid;
906
+ if (!disjointClusters.has(setid)) disjointClusters.set(setid, []);
907
+ disjointClusters.get(setid).push(circles[i]);
908
+ }
909
+ circles.forEach((circle) => {
910
+ delete circle.parent;
911
+ });
912
+ return Array.from(disjointClusters.values());
913
+ }
914
+ /**
915
+ * @param {ReadonlyArray<{x :number, y: number, radius: number}>} circles
916
+ * @returns {{xRange: [number, number], yRange: [number, number]}}
917
+ */
918
+ function getBoundingBox(circles) {
919
+ const minMax = (d) => {
920
+ return {
921
+ max: circles.reduce((acc, c) => Math.max(acc, c[d] + c.radius), Number.NEGATIVE_INFINITY),
922
+ min: circles.reduce((acc, c) => Math.min(acc, c[d] - c.radius), Number.POSITIVE_INFINITY)
923
+ };
924
+ };
925
+ return {
926
+ xRange: minMax("x"),
927
+ yRange: minMax("y")
928
+ };
929
+ }
930
+ /**
931
+ *
932
+ * @param {{[setid: string]: {x: number, y: number, radius: number}}} solution
933
+ * @param {undefined | number} orientation
934
+ * @param {((a: {x :number, y: number, radius: number}, b: {x :number, y: number, radius: number}) => number) | undefined} orientationOrder
935
+ * @returns {{[setid: string]: {x: number, y: number, radius: number}}}
936
+ */
937
+ function normalizeSolution(solution, orientation, orientationOrder) {
938
+ if (orientation == null) orientation = Math.PI / 2;
939
+ let circles = fromObjectNotation(solution).map((d) => Object.assign({}, d));
940
+ const clusters = disjointCluster(circles);
941
+ for (const cluster of clusters) {
942
+ orientateCircles(cluster, orientation, orientationOrder);
943
+ const bounds = getBoundingBox(cluster);
944
+ cluster.size = (bounds.xRange.max - bounds.xRange.min) * (bounds.yRange.max - bounds.yRange.min);
945
+ cluster.bounds = bounds;
946
+ }
947
+ clusters.sort((a, b) => b.size - a.size);
948
+ circles = clusters[0];
949
+ let returnBounds = circles.bounds;
950
+ const spacing = (returnBounds.xRange.max - returnBounds.xRange.min) / 50;
951
+ /**
952
+ * @param {ReadonlyArray<{x: number, y: number, radius: number, setid: string}>} cluster
953
+ * @param {boolean} right
954
+ * @param {boolean} bottom
955
+ */
956
+ function addCluster(cluster, right, bottom) {
957
+ if (!cluster) return;
958
+ const bounds = cluster.bounds;
959
+ /** @type {number} */
960
+ let xOffset;
961
+ /** @type {number} */
962
+ let yOffset;
963
+ if (right) xOffset = returnBounds.xRange.max - bounds.xRange.min + spacing;
964
+ else {
965
+ xOffset = returnBounds.xRange.max - bounds.xRange.max;
966
+ const centreing = (bounds.xRange.max - bounds.xRange.min) / 2 - (returnBounds.xRange.max - returnBounds.xRange.min) / 2;
967
+ if (centreing < 0) xOffset += centreing;
968
+ }
969
+ if (bottom) yOffset = returnBounds.yRange.max - bounds.yRange.min + spacing;
970
+ else {
971
+ yOffset = returnBounds.yRange.max - bounds.yRange.max;
972
+ const centreing = (bounds.yRange.max - bounds.yRange.min) / 2 - (returnBounds.yRange.max - returnBounds.yRange.min) / 2;
973
+ if (centreing < 0) yOffset += centreing;
974
+ }
975
+ for (const c of cluster) {
976
+ c.x += xOffset;
977
+ c.y += yOffset;
978
+ circles.push(c);
979
+ }
980
+ }
981
+ let index = 1;
982
+ while (index < clusters.length) {
983
+ addCluster(clusters[index], true, false);
984
+ addCluster(clusters[index + 1], false, true);
985
+ addCluster(clusters[index + 2], true, true);
986
+ index += 3;
987
+ returnBounds = getBoundingBox(circles);
988
+ }
989
+ return toObjectNotation(circles);
990
+ }
991
+ /**
992
+ * Scales a solution from venn.venn or venn.greedyLayout such that it fits in
993
+ * a rectangle of width/height - with padding around the borders. also
994
+ * centers the diagram in the available space at the same time.
995
+ * If the scale parameter is not null, this automatic scaling is ignored in favor of this custom one
996
+ * @param {{[setid: string]: {x: number, y: number, radius: number}}} solution
997
+ * @param {number} width
998
+ * @param {number} height
999
+ * @param {number} padding
1000
+ * @param {boolean} scaleToFit
1001
+ * @returns {{[setid: string]: {x: number, y: number, radius: number}}}
1002
+ */
1003
+ function scaleSolution(solution, width, height, padding, scaleToFit) {
1004
+ const circles = fromObjectNotation(solution);
1005
+ width -= 2 * padding;
1006
+ height -= 2 * padding;
1007
+ const { xRange, yRange } = getBoundingBox(circles);
1008
+ if (xRange.max === xRange.min || yRange.max === yRange.min) {
1009
+ console.log("not scaling solution: zero size detected");
1010
+ return solution;
1011
+ }
1012
+ /** @type {number} */
1013
+ let xScaling;
1014
+ /** @type {number} */
1015
+ let yScaling;
1016
+ if (scaleToFit) {
1017
+ const toScaleDiameter = Math.sqrt(scaleToFit / Math.PI) * 2;
1018
+ xScaling = width / toScaleDiameter;
1019
+ yScaling = height / toScaleDiameter;
1020
+ } else {
1021
+ xScaling = width / (xRange.max - xRange.min);
1022
+ yScaling = height / (yRange.max - yRange.min);
1023
+ }
1024
+ const scaling = Math.min(yScaling, xScaling);
1025
+ const xOffset = (width - (xRange.max - xRange.min) * scaling) / 2;
1026
+ const yOffset = (height - (yRange.max - yRange.min) * scaling) / 2;
1027
+ return toObjectNotation(circles.map((circle) => ({
1028
+ radius: scaling * circle.radius,
1029
+ x: padding + xOffset + (circle.x - xRange.min) * scaling,
1030
+ y: padding + yOffset + (circle.y - yRange.min) * scaling,
1031
+ setid: circle.setid
1032
+ })));
1033
+ }
1034
+ /**
1035
+ * @param {readonly {x: number, y: number, radius: number, setid: string}[]} circles
1036
+ * @returns {{[setid: string]: {x: number, y: number, radius: number, setid: string}}}
1037
+ */
1038
+ function toObjectNotation(circles) {
1039
+ /** @type {{[setid: string]: {x: number, y: number, radius: number, setid: string}}} */
1040
+ const r = {};
1041
+ for (const circle of circles) r[circle.setid] = circle;
1042
+ return r;
1043
+ }
1044
+ /**
1045
+ * @param {{[setid: string]: {x: number, y: number, radius: number}}} solution
1046
+ * @returns {{x: number, y: number, radius: number, setid: string}[]}}
1047
+ */
1048
+ function fromObjectNotation(solution) {
1049
+ return Object.keys(solution).map((id) => Object.assign(solution[id], { setid: id }));
1050
+ }
1051
+ /**
1052
+ * VennDiagram includes an optional `options` parameter containing the following option(s):
1053
+ *
1054
+ * `colourScheme: Array<String>`
1055
+ * A list of color values to be applied when coloring diagram circles.
1056
+ *
1057
+ * `symmetricalTextCentre: Boolean`
1058
+ * Whether to symmetrically center each circle's text horizontally and vertically.
1059
+ * Defaults to `false`.
1060
+ *
1061
+ * `textFill: String`
1062
+ * The color to be applied to the text within each circle.
1063
+ *
1064
+ * @param {object} options
1065
+ */
1066
+ function VennDiagram(options = {}) {
1067
+ let useViewBox = false, width = 600, height = 350, padding = 15, duration = 1e3, orientation = Math.PI / 2, normalize = true, scaleToFit = null, wrap = true, styled = true, fontSize = null, orientationOrder = null, distinct = false, round = null, symmetricalTextCentre = options && options.symmetricalTextCentre ? options.symmetricalTextCentre : false, colourMap = {}, colourScheme = options && options.colourScheme ? options.colourScheme : options && options.colorScheme ? options.colorScheme : [
1068
+ "#1f77b4",
1069
+ "#ff7f0e",
1070
+ "#2ca02c",
1071
+ "#d62728",
1072
+ "#9467bd",
1073
+ "#8c564b",
1074
+ "#e377c2",
1075
+ "#7f7f7f",
1076
+ "#bcbd22",
1077
+ "#17becf"
1078
+ ], colourIndex = 0, colours = function(key) {
1079
+ if (key in colourMap) return colourMap[key];
1080
+ var ret = colourMap[key] = colourScheme[colourIndex];
1081
+ colourIndex += 1;
1082
+ if (colourIndex >= colourScheme.length) colourIndex = 0;
1083
+ return ret;
1084
+ }, layoutFunction = venn, loss = lossFunction;
1085
+ function chart(selection) {
1086
+ let data = selection.datum();
1087
+ const toRemove = /* @__PURE__ */ new Set();
1088
+ data.forEach((datum) => {
1089
+ if (datum.size == 0 && datum.sets.length == 1) toRemove.add(datum.sets[0]);
1090
+ });
1091
+ data = data.filter((datum) => !datum.sets.some((set) => toRemove.has(set)));
1092
+ let circles = {};
1093
+ let textCentres = {};
1094
+ if (data.length > 0) {
1095
+ let solution = layoutFunction(data, {
1096
+ lossFunction: loss,
1097
+ distinct
1098
+ });
1099
+ if (normalize) solution = normalizeSolution(solution, orientation, orientationOrder);
1100
+ circles = scaleSolution(solution, width, height, padding, scaleToFit);
1101
+ textCentres = computeTextCentres(circles, data, symmetricalTextCentre);
1102
+ }
1103
+ const labels = {};
1104
+ data.forEach((datum) => {
1105
+ if (datum.label) labels[datum.sets] = datum.label;
1106
+ });
1107
+ function label(d) {
1108
+ if (d.sets in labels) return labels[d.sets];
1109
+ if (d.sets.length == 1) return "" + d.sets[0];
1110
+ }
1111
+ selection.selectAll("svg").data([circles]).enter().append("svg");
1112
+ const svg = selection.select("svg");
1113
+ if (useViewBox) svg.attr("viewBox", `0 0 ${width} ${height}`);
1114
+ else svg.attr("width", width).attr("height", height);
1115
+ const previous = {};
1116
+ let hasPrevious = false;
1117
+ svg.selectAll(".venn-area path").each(function(d) {
1118
+ const path = this.getAttribute("d");
1119
+ if (d.sets.length == 1 && path && !distinct) {
1120
+ hasPrevious = true;
1121
+ previous[d.sets[0]] = circleFromPath(path);
1122
+ }
1123
+ });
1124
+ function pathTween(d) {
1125
+ return (t) => {
1126
+ return intersectionAreaPath(d.sets.map((set) => {
1127
+ let start = previous[set];
1128
+ let end = circles[set];
1129
+ if (!start) start = {
1130
+ x: width / 2,
1131
+ y: height / 2,
1132
+ radius: 1
1133
+ };
1134
+ if (!end) end = {
1135
+ x: width / 2,
1136
+ y: height / 2,
1137
+ radius: 1
1138
+ };
1139
+ return {
1140
+ x: start.x * (1 - t) + end.x * t,
1141
+ y: start.y * (1 - t) + end.y * t,
1142
+ radius: start.radius * (1 - t) + end.radius * t
1143
+ };
1144
+ }), round);
1145
+ };
1146
+ }
1147
+ const nodes = svg.selectAll(".venn-area").data(data, (d) => d.sets);
1148
+ const enter = nodes.enter().append("g").attr("class", (d) => `venn-area venn-${d.sets.length == 1 ? "circle" : "intersection"}${d.colour || d.color ? " venn-coloured" : ""}`).attr("data-venn-sets", (d) => d.sets.join("_"));
1149
+ const enterPath = enter.append("path");
1150
+ const enterText = enter.append("text").attr("class", "label").text((d) => label(d)).attr("text-anchor", "middle").attr("dy", ".35em").attr("x", width / 2).attr("y", height / 2);
1151
+ if (styled) {
1152
+ enterPath.style("fill-opacity", "0").filter((d) => d.sets.length == 1).style("fill", (d) => d.colour ? d.colour : d.color ? d.color : colours(d.sets)).style("fill-opacity", ".25");
1153
+ enterText.style("fill", (d) => {
1154
+ if (d.colour || d.color) return "#FFF";
1155
+ if (options.textFill) return options.textFill;
1156
+ return d.sets.length == 1 ? colours(d.sets) : "#444";
1157
+ });
1158
+ }
1159
+ function asTransition(s) {
1160
+ if (typeof s.transition === "function") return s.transition("venn").duration(duration);
1161
+ return s;
1162
+ }
1163
+ let update = selection;
1164
+ if (hasPrevious && typeof update.transition === "function") {
1165
+ update = asTransition(selection);
1166
+ update.selectAll("path").attrTween("d", pathTween);
1167
+ } else update.selectAll("path").attr("d", (d) => intersectionAreaPath(d.sets.map((set) => circles[set])), round);
1168
+ const updateText = update.selectAll("text").filter((d) => d.sets in textCentres).text((d) => label(d)).attr("x", (d) => Math.floor(textCentres[d.sets].x)).attr("y", (d) => Math.floor(textCentres[d.sets].y));
1169
+ if (wrap) if (hasPrevious) if ("on" in updateText) updateText.on("end", wrapText(circles, label));
1170
+ else updateText.each("end", wrapText(circles, label));
1171
+ else updateText.each(wrapText(circles, label));
1172
+ const exit = asTransition(nodes.exit()).remove();
1173
+ if (typeof nodes.transition === "function") exit.selectAll("path").attrTween("d", pathTween);
1174
+ const exitText = exit.selectAll("text").attr("x", width / 2).attr("y", height / 2);
1175
+ if (fontSize !== null) {
1176
+ enterText.style("font-size", "0px");
1177
+ updateText.style("font-size", fontSize);
1178
+ exitText.style("font-size", "0px");
1179
+ }
1180
+ return {
1181
+ circles,
1182
+ textCentres,
1183
+ nodes,
1184
+ enter,
1185
+ update,
1186
+ exit
1187
+ };
1188
+ }
1189
+ chart.wrap = function(_) {
1190
+ if (!arguments.length) return wrap;
1191
+ wrap = _;
1192
+ return chart;
1193
+ };
1194
+ chart.useViewBox = function() {
1195
+ useViewBox = true;
1196
+ return chart;
1197
+ };
1198
+ chart.width = function(_) {
1199
+ if (!arguments.length) return width;
1200
+ width = _;
1201
+ return chart;
1202
+ };
1203
+ chart.height = function(_) {
1204
+ if (!arguments.length) return height;
1205
+ height = _;
1206
+ return chart;
1207
+ };
1208
+ chart.padding = function(_) {
1209
+ if (!arguments.length) return padding;
1210
+ padding = _;
1211
+ return chart;
1212
+ };
1213
+ chart.distinct = function(_) {
1214
+ if (!arguments.length) return distinct;
1215
+ distinct = _;
1216
+ return chart;
1217
+ };
1218
+ chart.colours = function(_) {
1219
+ if (!arguments.length) return colours;
1220
+ colours = _;
1221
+ return chart;
1222
+ };
1223
+ chart.colors = function(_) {
1224
+ if (!arguments.length) return colours;
1225
+ colours = _;
1226
+ return chart;
1227
+ };
1228
+ chart.fontSize = function(_) {
1229
+ if (!arguments.length) return fontSize;
1230
+ fontSize = _;
1231
+ return chart;
1232
+ };
1233
+ chart.round = function(_) {
1234
+ if (!arguments.length) return round;
1235
+ round = _;
1236
+ return chart;
1237
+ };
1238
+ chart.duration = function(_) {
1239
+ if (!arguments.length) return duration;
1240
+ duration = _;
1241
+ return chart;
1242
+ };
1243
+ chart.layoutFunction = function(_) {
1244
+ if (!arguments.length) return layoutFunction;
1245
+ layoutFunction = _;
1246
+ return chart;
1247
+ };
1248
+ chart.normalize = function(_) {
1249
+ if (!arguments.length) return normalize;
1250
+ normalize = _;
1251
+ return chart;
1252
+ };
1253
+ chart.scaleToFit = function(_) {
1254
+ if (!arguments.length) return scaleToFit;
1255
+ scaleToFit = _;
1256
+ return chart;
1257
+ };
1258
+ chart.styled = function(_) {
1259
+ if (!arguments.length) return styled;
1260
+ styled = _;
1261
+ return chart;
1262
+ };
1263
+ chart.orientation = function(_) {
1264
+ if (!arguments.length) return orientation;
1265
+ orientation = _;
1266
+ return chart;
1267
+ };
1268
+ chart.orientationOrder = function(_) {
1269
+ if (!arguments.length) return orientationOrder;
1270
+ orientationOrder = _;
1271
+ return chart;
1272
+ };
1273
+ chart.lossFunction = function(_) {
1274
+ if (!arguments.length) return loss;
1275
+ loss = _ === "default" ? lossFunction : _ === "logRatio" ? logRatioLossFunction : _;
1276
+ return chart;
1277
+ };
1278
+ return chart;
1279
+ }
1280
+ function wrapText(circles, labeller) {
1281
+ return function(data) {
1282
+ const text = this;
1283
+ const width = circles[data.sets[0]].radius || 50;
1284
+ const label = labeller(data) || "";
1285
+ const words = label.split(/\s+/).reverse();
1286
+ const minChars = (label.length + words.length) / 3;
1287
+ let word = words.pop();
1288
+ let line = [word];
1289
+ let lineNumber = 0;
1290
+ const lineHeight = 1.1;
1291
+ text.textContent = null;
1292
+ const tspans = [];
1293
+ function append(word) {
1294
+ const tspan = text.ownerDocument.createElementNS(text.namespaceURI, "tspan");
1295
+ tspan.textContent = word;
1296
+ tspans.push(tspan);
1297
+ text.append(tspan);
1298
+ return tspan;
1299
+ }
1300
+ let tspan = append(word);
1301
+ while (true) {
1302
+ word = words.pop();
1303
+ if (!word) break;
1304
+ line.push(word);
1305
+ const joined = line.join(" ");
1306
+ tspan.textContent = joined;
1307
+ if (joined.length > minChars && tspan.getComputedTextLength() > width) {
1308
+ line.pop();
1309
+ tspan.textContent = line.join(" ");
1310
+ line = [word];
1311
+ tspan = append(word);
1312
+ lineNumber++;
1313
+ }
1314
+ }
1315
+ const initial = .35 - lineNumber * lineHeight / 2;
1316
+ const x = text.getAttribute("x");
1317
+ const y = text.getAttribute("y");
1318
+ tspans.forEach((t, i) => {
1319
+ t.setAttribute("x", x);
1320
+ t.setAttribute("y", y);
1321
+ t.setAttribute("dy", `${initial + i * lineHeight}em`);
1322
+ });
1323
+ };
1324
+ }
1325
+ /**
1326
+ *
1327
+ * @param {{x: number, y: number}} current
1328
+ * @param {ReadonlyArray<{x: number, y: number}>} interior
1329
+ * @param {ReadonlyArray<{x: number, y: number}>} exterior
1330
+ * @returns {number}
1331
+ */
1332
+ function circleMargin(current, interior, exterior) {
1333
+ let margin = interior[0].radius - distance(interior[0], current);
1334
+ for (let i = 1; i < interior.length; ++i) {
1335
+ const m = interior[i].radius - distance(interior[i], current);
1336
+ if (m <= margin) margin = m;
1337
+ }
1338
+ for (let i = 0; i < exterior.length; ++i) {
1339
+ const m = distance(exterior[i], current) - exterior[i].radius;
1340
+ if (m <= margin) margin = m;
1341
+ }
1342
+ return margin;
1343
+ }
1344
+ /**
1345
+ * compute the center of some circles by maximizing the margin of
1346
+ * the center point relative to the circles (interior) after subtracting
1347
+ * nearby circles (exterior)
1348
+ * @param {readonly {x: number, y: number, radius: number}[]} interior
1349
+ * @param {readonly {x: number, y: number, radius: number}[]} exterior
1350
+ * @param {boolean} symmetricalTextCentre
1351
+ * @returns {{x:number, y: number}}
1352
+ */
1353
+ function computeTextCentre(interior, exterior, symmetricalTextCentre) {
1354
+ /** @type {{x: number, y: number}[]} */
1355
+ const points = [];
1356
+ for (const c of interior) {
1357
+ points.push({
1358
+ x: c.x,
1359
+ y: c.y
1360
+ });
1361
+ points.push({
1362
+ x: c.x + c.radius / 2,
1363
+ y: c.y
1364
+ });
1365
+ points.push({
1366
+ x: c.x - c.radius / 2,
1367
+ y: c.y
1368
+ });
1369
+ points.push({
1370
+ x: c.x,
1371
+ y: c.y + c.radius / 2
1372
+ });
1373
+ points.push({
1374
+ x: c.x,
1375
+ y: c.y - c.radius / 2
1376
+ });
1377
+ }
1378
+ let initial = points[0];
1379
+ let margin = circleMargin(points[0], interior, exterior);
1380
+ for (let i = 1; i < points.length; ++i) {
1381
+ const m = circleMargin(points[i], interior, exterior);
1382
+ if (m >= margin) {
1383
+ initial = points[i];
1384
+ margin = m;
1385
+ }
1386
+ }
1387
+ const solution = nelderMead((p) => -1 * circleMargin({
1388
+ x: p[0],
1389
+ y: p[1]
1390
+ }, interior, exterior), [initial.x, initial.y], {
1391
+ maxIterations: 500,
1392
+ minErrorDelta: 1e-10
1393
+ }).x;
1394
+ const ret = {
1395
+ x: symmetricalTextCentre ? 0 : solution[0],
1396
+ y: solution[1]
1397
+ };
1398
+ let valid = true;
1399
+ for (const i of interior) if (distance(ret, i) > i.radius) {
1400
+ valid = false;
1401
+ break;
1402
+ }
1403
+ for (const e of exterior) if (distance(ret, e) < e.radius) {
1404
+ valid = false;
1405
+ break;
1406
+ }
1407
+ if (valid) return ret;
1408
+ if (interior.length == 1) return {
1409
+ x: interior[0].x,
1410
+ y: interior[0].y
1411
+ };
1412
+ const areaStats = {};
1413
+ intersectionArea(interior, areaStats);
1414
+ if (areaStats.arcs.length === 0) return {
1415
+ x: 0,
1416
+ y: -1e3,
1417
+ disjoint: true
1418
+ };
1419
+ if (areaStats.arcs.length == 1) return {
1420
+ x: areaStats.arcs[0].circle.x,
1421
+ y: areaStats.arcs[0].circle.y
1422
+ };
1423
+ if (exterior.length) return computeTextCentre(interior, []);
1424
+ return getCenter(areaStats.arcs.map((a) => a.p1));
1425
+ }
1426
+ function getOverlappingCircles(circles) {
1427
+ const ret = {};
1428
+ const circleids = Object.keys(circles);
1429
+ for (const circleid of circleids) ret[circleid] = [];
1430
+ for (let i = 0; i < circleids.length; i++) {
1431
+ const ci = circleids[i];
1432
+ const a = circles[ci];
1433
+ for (let j = i + 1; j < circleids.length; ++j) {
1434
+ const cj = circleids[j];
1435
+ const b = circles[cj];
1436
+ const d = distance(a, b);
1437
+ if (d + b.radius <= a.radius + 1e-10) ret[cj].push(ci);
1438
+ else if (d + a.radius <= b.radius + 1e-10) ret[ci].push(cj);
1439
+ }
1440
+ }
1441
+ return ret;
1442
+ }
1443
+ function computeTextCentres(circles, areas, symmetricalTextCentre) {
1444
+ const ret = {};
1445
+ const overlapped = getOverlappingCircles(circles);
1446
+ for (let i = 0; i < areas.length; ++i) {
1447
+ const area = areas[i].sets;
1448
+ const areaids = {};
1449
+ const exclude = {};
1450
+ for (let j = 0; j < area.length; ++j) {
1451
+ areaids[area[j]] = true;
1452
+ const overlaps = overlapped[area[j]];
1453
+ for (let k = 0; k < overlaps.length; ++k) exclude[overlaps[k]] = true;
1454
+ }
1455
+ const interior = [];
1456
+ const exterior = [];
1457
+ for (let setid in circles) if (setid in areaids) interior.push(circles[setid]);
1458
+ else if (!(setid in exclude)) exterior.push(circles[setid]);
1459
+ const centre = computeTextCentre(interior, exterior, symmetricalTextCentre);
1460
+ ret[area] = centre;
1461
+ if (centre.disjoint && areas[i].size > 0) console.log("WARNING: area " + area + " not represented on screen");
1462
+ }
1463
+ return ret;
1464
+ }
1465
+ /**
1466
+ * @param {number} x
1467
+ * @param {number} y
1468
+ * @param {number} r
1469
+ * @returns {string}
1470
+ */
1471
+ function circlePath(x, y, r) {
1472
+ const ret = [];
1473
+ ret.push("\nM", x, y);
1474
+ ret.push("\nm", -r, 0);
1475
+ ret.push("\na", r, r, 0, 1, 0, r * 2, 0);
1476
+ ret.push("\na", r, r, 0, 1, 0, -r * 2, 0);
1477
+ return ret.join(" ");
1478
+ }
1479
+ /**
1480
+ * inverse of the circlePath function, returns a circle object from an svg path
1481
+ * @param {string} path
1482
+ * @returns {{x: number, y: number, radius: number}}
1483
+ */
1484
+ function circleFromPath(path) {
1485
+ const tokens = path.split(" ");
1486
+ return {
1487
+ x: Number.parseFloat(tokens[1]),
1488
+ y: Number.parseFloat(tokens[2]),
1489
+ radius: -Number.parseFloat(tokens[4])
1490
+ };
1491
+ }
1492
+ function intersectionAreaArcs(circles) {
1493
+ if (circles.length === 0) return [];
1494
+ const stats = {};
1495
+ intersectionArea(circles, stats);
1496
+ return stats.arcs;
1497
+ }
1498
+ function arcsToPath(arcs, round) {
1499
+ if (arcs.length === 0) return "M 0 0";
1500
+ const rFactor = Math.pow(10, round || 0);
1501
+ const r = round != null ? (v) => Math.round(v * rFactor) / rFactor : (v) => v;
1502
+ if (arcs.length == 1) {
1503
+ const circle = arcs[0].circle;
1504
+ return circlePath(r(circle.x), r(circle.y), r(circle.radius));
1505
+ }
1506
+ const ret = [
1507
+ "\nM",
1508
+ r(arcs[0].p2.x),
1509
+ r(arcs[0].p2.y)
1510
+ ];
1511
+ for (const arc of arcs) {
1512
+ const radius = r(arc.circle.radius);
1513
+ ret.push("\nA", radius, radius, 0, arc.large ? 1 : 0, arc.sweep ? 1 : 0, r(arc.p1.x), r(arc.p1.y));
1514
+ }
1515
+ return ret.join(" ");
1516
+ }
1517
+ /**
1518
+ * returns a svg path of the intersection area of a bunch of circles
1519
+ * @param {ReadonlyArray<{x: number, y: number, radius: number}>} circles
1520
+ * @returns {string}
1521
+ */
1522
+ function intersectionAreaPath(circles, round) {
1523
+ return arcsToPath(intersectionAreaArcs(circles), round);
1524
+ }
1525
+ function layout(data, options = {}) {
1526
+ const { lossFunction: loss, layoutFunction: layout = venn, normalize = true, orientation = Math.PI / 2, orientationOrder, width = 600, height = 350, padding = 15, scaleToFit = false, symmetricalTextCentre = false, distinct, round = 2 } = options;
1527
+ let solution = layout(data, {
1528
+ lossFunction: loss === "default" || !loss ? lossFunction : loss === "logRatio" ? logRatioLossFunction : loss,
1529
+ distinct
1530
+ });
1531
+ if (normalize) solution = normalizeSolution(solution, orientation, orientationOrder);
1532
+ const circles = scaleSolution(solution, width, height, padding, scaleToFit);
1533
+ const textCentres = computeTextCentres(circles, data, symmetricalTextCentre);
1534
+ const circleLookup = new Map(Object.keys(circles).map((set) => [set, {
1535
+ set,
1536
+ x: circles[set].x,
1537
+ y: circles[set].y,
1538
+ radius: circles[set].radius
1539
+ }]));
1540
+ const helpers = data.map((area) => {
1541
+ const circles = area.sets.map((s) => circleLookup.get(s));
1542
+ const arcs = intersectionAreaArcs(circles);
1543
+ return {
1544
+ circles,
1545
+ arcs,
1546
+ path: arcsToPath(arcs, round),
1547
+ area,
1548
+ has: new Set(area.sets)
1549
+ };
1550
+ });
1551
+ function genDistinctPath(sets) {
1552
+ let r = "";
1553
+ for (const e of helpers) if (e.has.size > sets.length && sets.every((s) => e.has.has(s))) r += " " + e.path;
1554
+ return r;
1555
+ }
1556
+ return helpers.map(({ circles, arcs, path, area }) => {
1557
+ return {
1558
+ data: area,
1559
+ text: textCentres[area.sets],
1560
+ circles,
1561
+ arcs,
1562
+ path,
1563
+ distinctPath: path + genDistinctPath(area.sets)
1564
+ };
1565
+ });
1566
+ }
1567
+
1568
+ //#endregion
1569
+ //#region ../../node_modules/.pnpm/mermaid@12.0.0/node_modules/mermaid/dist/chunks/mermaid.core/vennDiagram-UO4OBE2U.mjs
1570
+ var import_rough_cjs = /* @__PURE__ */ __toESM(require_rough_cjs(), 1);
1571
+ var parser = (function() {
1572
+ var o = /* @__PURE__ */ __name(function(k, v, o2, l) {
1573
+ for (o2 = o2 || {}, l = k.length; l--; o2[k[l]] = v);
1574
+ return o2;
1575
+ }, "o"), $V0 = [5, 8], $V1 = [
1576
+ 7,
1577
+ 8,
1578
+ 11,
1579
+ 12,
1580
+ 17,
1581
+ 19,
1582
+ 22,
1583
+ 24
1584
+ ], $V2 = [1, 17], $V3 = [1, 18], $V4 = [
1585
+ 7,
1586
+ 8,
1587
+ 11,
1588
+ 12,
1589
+ 14,
1590
+ 15,
1591
+ 16,
1592
+ 17,
1593
+ 19,
1594
+ 20,
1595
+ 21,
1596
+ 22,
1597
+ 24,
1598
+ 27
1599
+ ], $V5 = [1, 31], $V6 = [1, 39], $V7 = [
1600
+ 7,
1601
+ 8,
1602
+ 11,
1603
+ 12,
1604
+ 17,
1605
+ 19,
1606
+ 22,
1607
+ 24,
1608
+ 27
1609
+ ], $V8 = [1, 57], $V9 = [1, 56], $Va = [1, 58], $Vb = [1, 59], $Vc = [1, 60], $Vd = [
1610
+ 7,
1611
+ 8,
1612
+ 11,
1613
+ 12,
1614
+ 16,
1615
+ 17,
1616
+ 19,
1617
+ 20,
1618
+ 22,
1619
+ 24,
1620
+ 27,
1621
+ 31,
1622
+ 32,
1623
+ 33
1624
+ ];
1625
+ var parser2 = {
1626
+ trace: /* @__PURE__ */ __name(function trace() {}, "trace"),
1627
+ yy: {},
1628
+ symbols_: {
1629
+ "error": 2,
1630
+ "start": 3,
1631
+ "optNewlines": 4,
1632
+ "VENN": 5,
1633
+ "document": 6,
1634
+ "EOF": 7,
1635
+ "NEWLINE": 8,
1636
+ "line": 9,
1637
+ "statement": 10,
1638
+ "TITLE": 11,
1639
+ "SET": 12,
1640
+ "identifier": 13,
1641
+ "BRACKET_LABEL": 14,
1642
+ "COLON": 15,
1643
+ "NUMERIC": 16,
1644
+ "UNION": 17,
1645
+ "identifierList": 18,
1646
+ "TEXT": 19,
1647
+ "IDENTIFIER": 20,
1648
+ "STRING": 21,
1649
+ "INDENT_TEXT": 22,
1650
+ "indentedTextTail": 23,
1651
+ "STYLE": 24,
1652
+ "stylesOpt": 25,
1653
+ "styleField": 26,
1654
+ "COMMA": 27,
1655
+ "styleValue": 28,
1656
+ "valueTokens": 29,
1657
+ "valueToken": 30,
1658
+ "HEXCOLOR": 31,
1659
+ "RGBCOLOR": 32,
1660
+ "RGBACOLOR": 33,
1661
+ "$accept": 0,
1662
+ "$end": 1
1663
+ },
1664
+ terminals_: {
1665
+ 2: "error",
1666
+ 5: "VENN",
1667
+ 7: "EOF",
1668
+ 8: "NEWLINE",
1669
+ 11: "TITLE",
1670
+ 12: "SET",
1671
+ 14: "BRACKET_LABEL",
1672
+ 15: "COLON",
1673
+ 16: "NUMERIC",
1674
+ 17: "UNION",
1675
+ 19: "TEXT",
1676
+ 20: "IDENTIFIER",
1677
+ 21: "STRING",
1678
+ 22: "INDENT_TEXT",
1679
+ 24: "STYLE",
1680
+ 27: "COMMA",
1681
+ 31: "HEXCOLOR",
1682
+ 32: "RGBCOLOR",
1683
+ 33: "RGBACOLOR"
1684
+ },
1685
+ productions_: [
1686
+ 0,
1687
+ [3, 4],
1688
+ [4, 0],
1689
+ [4, 2],
1690
+ [6, 0],
1691
+ [6, 2],
1692
+ [9, 1],
1693
+ [9, 1],
1694
+ [10, 1],
1695
+ [10, 2],
1696
+ [10, 3],
1697
+ [10, 4],
1698
+ [10, 5],
1699
+ [10, 2],
1700
+ [10, 3],
1701
+ [10, 4],
1702
+ [10, 5],
1703
+ [10, 3],
1704
+ [10, 3],
1705
+ [10, 3],
1706
+ [10, 4],
1707
+ [10, 4],
1708
+ [10, 2],
1709
+ [10, 3],
1710
+ [23, 1],
1711
+ [23, 1],
1712
+ [23, 1],
1713
+ [23, 2],
1714
+ [23, 2],
1715
+ [25, 1],
1716
+ [25, 3],
1717
+ [26, 3],
1718
+ [28, 1],
1719
+ [28, 1],
1720
+ [29, 1],
1721
+ [29, 2],
1722
+ [30, 1],
1723
+ [30, 1],
1724
+ [30, 1],
1725
+ [30, 1],
1726
+ [30, 1],
1727
+ [18, 1],
1728
+ [18, 3],
1729
+ [13, 1],
1730
+ [13, 1]
1731
+ ],
1732
+ performAction: /* @__PURE__ */ __name(function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$) {
1733
+ var $0 = $$.length - 1;
1734
+ switch (yystate) {
1735
+ case 1: return $$[$0 - 1];
1736
+ case 2:
1737
+ case 3:
1738
+ case 4:
1739
+ this.$ = [];
1740
+ break;
1741
+ case 5:
1742
+ $$[$0 - 1].push($$[$0]);
1743
+ this.$ = $$[$0 - 1];
1744
+ break;
1745
+ case 6:
1746
+ this.$ = [];
1747
+ break;
1748
+ case 7:
1749
+ case 22:
1750
+ case 32:
1751
+ case 36:
1752
+ case 37:
1753
+ case 38:
1754
+ case 39:
1755
+ case 40:
1756
+ this.$ = $$[$0];
1757
+ break;
1758
+ case 8:
1759
+ yy.setDiagramTitle($$[$0].substr(6));
1760
+ this.$ = $$[$0].substr(6);
1761
+ break;
1762
+ case 9:
1763
+ yy.addSubsetData([$$[$0]], void 0, void 0);
1764
+ if (yy.setIndentMode) yy.setIndentMode(true);
1765
+ break;
1766
+ case 10:
1767
+ yy.addSubsetData([$$[$0 - 1]], $$[$0], void 0);
1768
+ if (yy.setIndentMode) yy.setIndentMode(true);
1769
+ break;
1770
+ case 11:
1771
+ yy.addSubsetData([$$[$0 - 2]], void 0, parseFloat($$[$0]));
1772
+ if (yy.setIndentMode) yy.setIndentMode(true);
1773
+ break;
1774
+ case 12:
1775
+ yy.addSubsetData([$$[$0 - 3]], $$[$0 - 2], parseFloat($$[$0]));
1776
+ if (yy.setIndentMode) yy.setIndentMode(true);
1777
+ break;
1778
+ case 13:
1779
+ if ($$[$0].length < 2) throw new Error("union requires multiple identifiers");
1780
+ if (yy.validateUnionIdentifiers) yy.validateUnionIdentifiers($$[$0]);
1781
+ yy.addSubsetData($$[$0], void 0, void 0);
1782
+ if (yy.setIndentMode) yy.setIndentMode(true);
1783
+ break;
1784
+ case 14:
1785
+ if ($$[$0 - 1].length < 2) throw new Error("union requires multiple identifiers");
1786
+ if (yy.validateUnionIdentifiers) yy.validateUnionIdentifiers($$[$0 - 1]);
1787
+ yy.addSubsetData($$[$0 - 1], $$[$0], void 0);
1788
+ if (yy.setIndentMode) yy.setIndentMode(true);
1789
+ break;
1790
+ case 15:
1791
+ if ($$[$0 - 2].length < 2) throw new Error("union requires multiple identifiers");
1792
+ if (yy.validateUnionIdentifiers) yy.validateUnionIdentifiers($$[$0 - 2]);
1793
+ yy.addSubsetData($$[$0 - 2], void 0, parseFloat($$[$0]));
1794
+ if (yy.setIndentMode) yy.setIndentMode(true);
1795
+ break;
1796
+ case 16:
1797
+ if ($$[$0 - 3].length < 2) throw new Error("union requires multiple identifiers");
1798
+ if (yy.validateUnionIdentifiers) yy.validateUnionIdentifiers($$[$0 - 3]);
1799
+ yy.addSubsetData($$[$0 - 3], $$[$0 - 2], parseFloat($$[$0]));
1800
+ if (yy.setIndentMode) yy.setIndentMode(true);
1801
+ break;
1802
+ case 17:
1803
+ case 18:
1804
+ case 19:
1805
+ yy.addTextData($$[$0 - 1], $$[$0], void 0);
1806
+ break;
1807
+ case 20:
1808
+ case 21:
1809
+ yy.addTextData($$[$0 - 2], $$[$0 - 1], $$[$0]);
1810
+ break;
1811
+ case 23:
1812
+ yy.addStyleData($$[$0 - 1], $$[$0]);
1813
+ break;
1814
+ case 24:
1815
+ case 25:
1816
+ case 26:
1817
+ var cs = yy.getCurrentSets();
1818
+ if (!cs) throw new Error("text requires set");
1819
+ yy.addTextData(cs, $$[$0], void 0);
1820
+ break;
1821
+ case 27:
1822
+ case 28:
1823
+ var cs = yy.getCurrentSets();
1824
+ if (!cs) throw new Error("text requires set");
1825
+ yy.addTextData(cs, $$[$0 - 1], $$[$0]);
1826
+ break;
1827
+ case 29:
1828
+ case 41:
1829
+ this.$ = [$$[$0]];
1830
+ break;
1831
+ case 30:
1832
+ case 42:
1833
+ this.$ = [...$$[$0 - 2], $$[$0]];
1834
+ break;
1835
+ case 31:
1836
+ this.$ = [$$[$0 - 2], $$[$0]];
1837
+ break;
1838
+ case 33:
1839
+ this.$ = $$[$0].join(" ");
1840
+ break;
1841
+ case 34:
1842
+ this.$ = [$$[$0]];
1843
+ break;
1844
+ case 35:
1845
+ $$[$0 - 1].push($$[$0]);
1846
+ this.$ = $$[$0 - 1];
1847
+ break;
1848
+ case 43:
1849
+ case 44:
1850
+ this.$ = $$[$0];
1851
+ break;
1852
+ }
1853
+ }, "anonymous"),
1854
+ table: [
1855
+ o($V0, [2, 2], {
1856
+ 3: 1,
1857
+ 4: 2
1858
+ }),
1859
+ { 1: [3] },
1860
+ {
1861
+ 5: [1, 3],
1862
+ 8: [1, 4]
1863
+ },
1864
+ o($V1, [2, 4], { 6: 5 }),
1865
+ o($V0, [2, 3]),
1866
+ {
1867
+ 7: [1, 6],
1868
+ 8: [1, 8],
1869
+ 9: 7,
1870
+ 10: 9,
1871
+ 11: [1, 10],
1872
+ 12: [1, 11],
1873
+ 17: [1, 12],
1874
+ 19: [1, 13],
1875
+ 22: [1, 14],
1876
+ 24: [1, 15]
1877
+ },
1878
+ { 1: [2, 1] },
1879
+ o($V1, [2, 5]),
1880
+ o($V1, [2, 6]),
1881
+ o($V1, [2, 7]),
1882
+ o($V1, [2, 8]),
1883
+ {
1884
+ 13: 16,
1885
+ 20: $V2,
1886
+ 21: $V3
1887
+ },
1888
+ {
1889
+ 13: 20,
1890
+ 18: 19,
1891
+ 20: $V2,
1892
+ 21: $V3
1893
+ },
1894
+ {
1895
+ 13: 20,
1896
+ 18: 21,
1897
+ 20: $V2,
1898
+ 21: $V3
1899
+ },
1900
+ {
1901
+ 16: [1, 25],
1902
+ 20: [1, 23],
1903
+ 21: [1, 24],
1904
+ 23: 22
1905
+ },
1906
+ {
1907
+ 13: 20,
1908
+ 18: 26,
1909
+ 20: $V2,
1910
+ 21: $V3
1911
+ },
1912
+ o($V1, [2, 9], {
1913
+ 14: [1, 27],
1914
+ 15: [1, 28]
1915
+ }),
1916
+ o($V4, [2, 43]),
1917
+ o($V4, [2, 44]),
1918
+ o($V1, [2, 13], {
1919
+ 14: [1, 29],
1920
+ 15: [1, 30],
1921
+ 27: $V5
1922
+ }),
1923
+ o($V4, [2, 41]),
1924
+ {
1925
+ 16: [1, 34],
1926
+ 20: [1, 32],
1927
+ 21: [1, 33],
1928
+ 27: $V5
1929
+ },
1930
+ o($V1, [2, 22]),
1931
+ o($V1, [2, 24], { 14: [1, 35] }),
1932
+ o($V1, [2, 25], { 14: [1, 36] }),
1933
+ o($V1, [2, 26]),
1934
+ {
1935
+ 20: $V6,
1936
+ 25: 37,
1937
+ 26: 38,
1938
+ 27: $V5
1939
+ },
1940
+ o($V1, [2, 10], { 15: [1, 40] }),
1941
+ { 16: [1, 41] },
1942
+ o($V1, [2, 14], { 15: [1, 42] }),
1943
+ { 16: [1, 43] },
1944
+ {
1945
+ 13: 44,
1946
+ 20: $V2,
1947
+ 21: $V3
1948
+ },
1949
+ o($V1, [2, 17], { 14: [1, 45] }),
1950
+ o($V1, [2, 18], { 14: [1, 46] }),
1951
+ o($V1, [2, 19]),
1952
+ o($V1, [2, 27]),
1953
+ o($V1, [2, 28]),
1954
+ o($V1, [2, 23], { 27: [1, 47] }),
1955
+ o($V7, [2, 29]),
1956
+ { 15: [1, 48] },
1957
+ { 16: [1, 49] },
1958
+ o($V1, [2, 11]),
1959
+ { 16: [1, 50] },
1960
+ o($V1, [2, 15]),
1961
+ o($V4, [2, 42]),
1962
+ o($V1, [2, 20]),
1963
+ o($V1, [2, 21]),
1964
+ {
1965
+ 20: $V6,
1966
+ 26: 51
1967
+ },
1968
+ {
1969
+ 16: $V8,
1970
+ 20: $V9,
1971
+ 21: [1, 53],
1972
+ 28: 52,
1973
+ 29: 54,
1974
+ 30: 55,
1975
+ 31: $Va,
1976
+ 32: $Vb,
1977
+ 33: $Vc
1978
+ },
1979
+ o($V1, [2, 12]),
1980
+ o($V1, [2, 16]),
1981
+ o($V7, [2, 30]),
1982
+ o($V7, [2, 31]),
1983
+ o($V7, [2, 32]),
1984
+ o($V7, [2, 33], {
1985
+ 30: 61,
1986
+ 16: $V8,
1987
+ 20: $V9,
1988
+ 31: $Va,
1989
+ 32: $Vb,
1990
+ 33: $Vc
1991
+ }),
1992
+ o($Vd, [2, 34]),
1993
+ o($Vd, [2, 36]),
1994
+ o($Vd, [2, 37]),
1995
+ o($Vd, [2, 38]),
1996
+ o($Vd, [2, 39]),
1997
+ o($Vd, [2, 40]),
1998
+ o($Vd, [2, 35])
1999
+ ],
2000
+ defaultActions: { 6: [2, 1] },
2001
+ parseError: /* @__PURE__ */ __name(function parseError(str, hash) {
2002
+ if (hash.recoverable) this.trace(str);
2003
+ else {
2004
+ var error = new Error(str);
2005
+ error.hash = hash;
2006
+ throw error;
2007
+ }
2008
+ }, "parseError"),
2009
+ parse: /* @__PURE__ */ __name(function parse(input) {
2010
+ var self = this, stack = [0], tstack = [], vstack = [null], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
2011
+ var args = lstack.slice.call(arguments, 1);
2012
+ var lexer2 = Object.create(this.lexer);
2013
+ var sharedState = { yy: {} };
2014
+ for (var k in this.yy) if (Object.prototype.hasOwnProperty.call(this.yy, k)) sharedState.yy[k] = this.yy[k];
2015
+ lexer2.setInput(input, sharedState.yy);
2016
+ sharedState.yy.lexer = lexer2;
2017
+ sharedState.yy.parser = this;
2018
+ if (typeof lexer2.yylloc == "undefined") lexer2.yylloc = {};
2019
+ var yyloc = lexer2.yylloc;
2020
+ lstack.push(yyloc);
2021
+ var ranges = lexer2.options && lexer2.options.ranges;
2022
+ if (typeof sharedState.yy.parseError === "function") this.parseError = sharedState.yy.parseError;
2023
+ else this.parseError = Object.getPrototypeOf(this).parseError;
2024
+ function popStack(n) {
2025
+ stack.length = stack.length - 2 * n;
2026
+ vstack.length = vstack.length - n;
2027
+ lstack.length = lstack.length - n;
2028
+ }
2029
+ __name(popStack, "popStack");
2030
+ function lex() {
2031
+ var token = tstack.pop() || lexer2.lex() || EOF;
2032
+ if (typeof token !== "number") {
2033
+ if (token instanceof Array) {
2034
+ tstack = token;
2035
+ token = tstack.pop();
2036
+ }
2037
+ token = self.symbols_[token] || token;
2038
+ }
2039
+ return token;
2040
+ }
2041
+ __name(lex, "lex");
2042
+ var symbol, preErrorSymbol, state, action, r, yyval = {}, p, len, newState, expected;
2043
+ while (true) {
2044
+ state = stack[stack.length - 1];
2045
+ if (this.defaultActions[state]) action = this.defaultActions[state];
2046
+ else {
2047
+ if (symbol === null || typeof symbol == "undefined") symbol = lex();
2048
+ action = table[state] && table[state][symbol];
2049
+ }
2050
+ if (typeof action === "undefined" || !action.length || !action[0]) {
2051
+ var errStr = "";
2052
+ expected = [];
2053
+ for (p in table[state]) if (this.terminals_[p] && p > TERROR) expected.push("'" + this.terminals_[p] + "'");
2054
+ if (lexer2.showPosition) errStr = "Parse error on line " + (yylineno + 1) + ":\n" + lexer2.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'";
2055
+ else errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == EOF ? "end of input" : "'" + (this.terminals_[symbol] || symbol) + "'");
2056
+ this.parseError(errStr, {
2057
+ text: lexer2.match,
2058
+ token: this.terminals_[symbol] || symbol,
2059
+ line: lexer2.yylineno,
2060
+ loc: yyloc,
2061
+ expected
2062
+ });
2063
+ }
2064
+ if (action[0] instanceof Array && action.length > 1) throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol);
2065
+ switch (action[0]) {
2066
+ case 1:
2067
+ stack.push(symbol);
2068
+ vstack.push(lexer2.yytext);
2069
+ lstack.push(lexer2.yylloc);
2070
+ stack.push(action[1]);
2071
+ symbol = null;
2072
+ if (!preErrorSymbol) {
2073
+ yyleng = lexer2.yyleng;
2074
+ yytext = lexer2.yytext;
2075
+ yylineno = lexer2.yylineno;
2076
+ yyloc = lexer2.yylloc;
2077
+ if (recovering > 0) recovering--;
2078
+ } else {
2079
+ symbol = preErrorSymbol;
2080
+ preErrorSymbol = null;
2081
+ }
2082
+ break;
2083
+ case 2:
2084
+ len = this.productions_[action[1]][1];
2085
+ yyval.$ = vstack[vstack.length - len];
2086
+ yyval._$ = {
2087
+ first_line: lstack[lstack.length - (len || 1)].first_line,
2088
+ last_line: lstack[lstack.length - 1].last_line,
2089
+ first_column: lstack[lstack.length - (len || 1)].first_column,
2090
+ last_column: lstack[lstack.length - 1].last_column
2091
+ };
2092
+ if (ranges) yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
2093
+ r = this.performAction.apply(yyval, [
2094
+ yytext,
2095
+ yyleng,
2096
+ yylineno,
2097
+ sharedState.yy,
2098
+ action[1],
2099
+ vstack,
2100
+ lstack
2101
+ ].concat(args));
2102
+ if (typeof r !== "undefined") return r;
2103
+ if (len) {
2104
+ stack = stack.slice(0, -1 * len * 2);
2105
+ vstack = vstack.slice(0, -1 * len);
2106
+ lstack = lstack.slice(0, -1 * len);
2107
+ }
2108
+ stack.push(this.productions_[action[1]][0]);
2109
+ vstack.push(yyval.$);
2110
+ lstack.push(yyval._$);
2111
+ newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
2112
+ stack.push(newState);
2113
+ break;
2114
+ case 3: return true;
2115
+ }
2116
+ }
2117
+ return true;
2118
+ }, "parse")
2119
+ };
2120
+ parser2.lexer = /* @__PURE__ */ (function() {
2121
+ return {
2122
+ EOF: 1,
2123
+ parseError: /* @__PURE__ */ __name(function parseError(str, hash) {
2124
+ if (this.yy.parser) this.yy.parser.parseError(str, hash);
2125
+ else throw new Error(str);
2126
+ }, "parseError"),
2127
+ setInput: /* @__PURE__ */ __name(function(input, yy) {
2128
+ this.yy = yy || this.yy || {};
2129
+ this._input = input;
2130
+ this._more = this._backtrack = this.done = false;
2131
+ this.yylineno = this.yyleng = 0;
2132
+ this.yytext = this.matched = this.match = "";
2133
+ this.conditionStack = ["INITIAL"];
2134
+ this.yylloc = {
2135
+ first_line: 1,
2136
+ first_column: 0,
2137
+ last_line: 1,
2138
+ last_column: 0
2139
+ };
2140
+ if (this.options.ranges) this.yylloc.range = [0, 0];
2141
+ this.offset = 0;
2142
+ return this;
2143
+ }, "setInput"),
2144
+ input: /* @__PURE__ */ __name(function() {
2145
+ var ch = this._input[0];
2146
+ this.yytext += ch;
2147
+ this.yyleng++;
2148
+ this.offset++;
2149
+ this.match += ch;
2150
+ this.matched += ch;
2151
+ if (ch.match(/(?:\r\n?|\n).*/g)) {
2152
+ this.yylineno++;
2153
+ this.yylloc.last_line++;
2154
+ } else this.yylloc.last_column++;
2155
+ if (this.options.ranges) this.yylloc.range[1]++;
2156
+ this._input = this._input.slice(1);
2157
+ return ch;
2158
+ }, "input"),
2159
+ unput: /* @__PURE__ */ __name(function(ch) {
2160
+ var len = ch.length;
2161
+ var lines = ch.split(/(?:\r\n?|\n)/g);
2162
+ this._input = ch + this._input;
2163
+ this.yytext = this.yytext.substr(0, this.yytext.length - len);
2164
+ this.offset -= len;
2165
+ var oldLines = this.match.split(/(?:\r\n?|\n)/g);
2166
+ this.match = this.match.substr(0, this.match.length - 1);
2167
+ this.matched = this.matched.substr(0, this.matched.length - 1);
2168
+ if (lines.length - 1) this.yylineno -= lines.length - 1;
2169
+ var r = this.yylloc.range;
2170
+ this.yylloc = {
2171
+ first_line: this.yylloc.first_line,
2172
+ last_line: this.yylineno + 1,
2173
+ first_column: this.yylloc.first_column,
2174
+ last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len
2175
+ };
2176
+ if (this.options.ranges) this.yylloc.range = [r[0], r[0] + this.yyleng - len];
2177
+ this.yyleng = this.yytext.length;
2178
+ return this;
2179
+ }, "unput"),
2180
+ more: /* @__PURE__ */ __name(function() {
2181
+ this._more = true;
2182
+ return this;
2183
+ }, "more"),
2184
+ reject: /* @__PURE__ */ __name(function() {
2185
+ if (this.options.backtrack_lexer) this._backtrack = true;
2186
+ else return this.parseError("Lexical error on line " + (this.yylineno + 1) + ". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n" + this.showPosition(), {
2187
+ text: "",
2188
+ token: null,
2189
+ line: this.yylineno
2190
+ });
2191
+ return this;
2192
+ }, "reject"),
2193
+ less: /* @__PURE__ */ __name(function(n) {
2194
+ this.unput(this.match.slice(n));
2195
+ }, "less"),
2196
+ pastInput: /* @__PURE__ */ __name(function() {
2197
+ var past = this.matched.substr(0, this.matched.length - this.match.length);
2198
+ return (past.length > 20 ? "..." : "") + past.substr(-20).replace(/\n/g, "");
2199
+ }, "pastInput"),
2200
+ upcomingInput: /* @__PURE__ */ __name(function() {
2201
+ var next = this.match;
2202
+ if (next.length < 20) next += this._input.substr(0, 20 - next.length);
2203
+ return (next.substr(0, 20) + (next.length > 20 ? "..." : "")).replace(/\n/g, "");
2204
+ }, "upcomingInput"),
2205
+ showPosition: /* @__PURE__ */ __name(function() {
2206
+ var pre = this.pastInput();
2207
+ var c = new Array(pre.length + 1).join("-");
2208
+ return pre + this.upcomingInput() + "\n" + c + "^";
2209
+ }, "showPosition"),
2210
+ test_match: /* @__PURE__ */ __name(function(match, indexed_rule) {
2211
+ var token, lines, backup;
2212
+ if (this.options.backtrack_lexer) {
2213
+ backup = {
2214
+ yylineno: this.yylineno,
2215
+ yylloc: {
2216
+ first_line: this.yylloc.first_line,
2217
+ last_line: this.last_line,
2218
+ first_column: this.yylloc.first_column,
2219
+ last_column: this.yylloc.last_column
2220
+ },
2221
+ yytext: this.yytext,
2222
+ match: this.match,
2223
+ matches: this.matches,
2224
+ matched: this.matched,
2225
+ yyleng: this.yyleng,
2226
+ offset: this.offset,
2227
+ _more: this._more,
2228
+ _input: this._input,
2229
+ yy: this.yy,
2230
+ conditionStack: this.conditionStack.slice(0),
2231
+ done: this.done
2232
+ };
2233
+ if (this.options.ranges) backup.yylloc.range = this.yylloc.range.slice(0);
2234
+ }
2235
+ lines = match[0].match(/(?:\r\n?|\n).*/g);
2236
+ if (lines) this.yylineno += lines.length;
2237
+ this.yylloc = {
2238
+ first_line: this.yylloc.last_line,
2239
+ last_line: this.yylineno + 1,
2240
+ first_column: this.yylloc.last_column,
2241
+ last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length
2242
+ };
2243
+ this.yytext += match[0];
2244
+ this.match += match[0];
2245
+ this.matches = match;
2246
+ this.yyleng = this.yytext.length;
2247
+ if (this.options.ranges) this.yylloc.range = [this.offset, this.offset += this.yyleng];
2248
+ this._more = false;
2249
+ this._backtrack = false;
2250
+ this._input = this._input.slice(match[0].length);
2251
+ this.matched += match[0];
2252
+ token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
2253
+ if (this.done && this._input) this.done = false;
2254
+ if (token) return token;
2255
+ else if (this._backtrack) {
2256
+ for (var k in backup) this[k] = backup[k];
2257
+ return false;
2258
+ }
2259
+ return false;
2260
+ }, "test_match"),
2261
+ next: /* @__PURE__ */ __name(function() {
2262
+ if (this.done) return this.EOF;
2263
+ if (!this._input) this.done = true;
2264
+ var token, match, tempMatch, index;
2265
+ if (!this._more) {
2266
+ this.yytext = "";
2267
+ this.match = "";
2268
+ }
2269
+ var rules = this._currentRules();
2270
+ for (var i = 0; i < rules.length; i++) {
2271
+ tempMatch = this._input.match(this.rules[rules[i]]);
2272
+ if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
2273
+ match = tempMatch;
2274
+ index = i;
2275
+ if (this.options.backtrack_lexer) {
2276
+ token = this.test_match(tempMatch, rules[i]);
2277
+ if (token !== false) return token;
2278
+ else if (this._backtrack) {
2279
+ match = false;
2280
+ continue;
2281
+ } else return false;
2282
+ } else if (!this.options.flex) break;
2283
+ }
2284
+ }
2285
+ if (match) {
2286
+ token = this.test_match(match, rules[index]);
2287
+ if (token !== false) return token;
2288
+ return false;
2289
+ }
2290
+ if (this._input === "") return this.EOF;
2291
+ else return this.parseError("Lexical error on line " + (this.yylineno + 1) + ". Unrecognized text.\n" + this.showPosition(), {
2292
+ text: "",
2293
+ token: null,
2294
+ line: this.yylineno
2295
+ });
2296
+ }, "next"),
2297
+ lex: /* @__PURE__ */ __name(function lex() {
2298
+ var r = this.next();
2299
+ if (r) return r;
2300
+ else return this.lex();
2301
+ }, "lex"),
2302
+ begin: /* @__PURE__ */ __name(function begin(condition) {
2303
+ this.conditionStack.push(condition);
2304
+ }, "begin"),
2305
+ popState: /* @__PURE__ */ __name(function popState() {
2306
+ if (this.conditionStack.length - 1 > 0) return this.conditionStack.pop();
2307
+ else return this.conditionStack[0];
2308
+ }, "popState"),
2309
+ _currentRules: /* @__PURE__ */ __name(function _currentRules() {
2310
+ if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
2311
+ else return this.conditions["INITIAL"].rules;
2312
+ }, "_currentRules"),
2313
+ topState: /* @__PURE__ */ __name(function topState(n) {
2314
+ n = this.conditionStack.length - 1 - Math.abs(n || 0);
2315
+ if (n >= 0) return this.conditionStack[n];
2316
+ else return "INITIAL";
2317
+ }, "topState"),
2318
+ pushState: /* @__PURE__ */ __name(function pushState(condition) {
2319
+ this.begin(condition);
2320
+ }, "pushState"),
2321
+ stateStackSize: /* @__PURE__ */ __name(function stateStackSize() {
2322
+ return this.conditionStack.length;
2323
+ }, "stateStackSize"),
2324
+ options: { "case-insensitive": true },
2325
+ performAction: /* @__PURE__ */ __name(function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) {
2326
+ switch ($avoiding_name_collisions) {
2327
+ case 0: break;
2328
+ case 1: break;
2329
+ case 2: break;
2330
+ case 3:
2331
+ if (yy.getIndentMode && yy.getIndentMode()) {
2332
+ yy.consumeIndentText = true;
2333
+ this.begin("INITIAL");
2334
+ return 22;
2335
+ }
2336
+ break;
2337
+ case 4: break;
2338
+ case 5:
2339
+ if (yy.setIndentMode) yy.setIndentMode(false);
2340
+ this.begin("INITIAL");
2341
+ this.unput(yy_.yytext);
2342
+ break;
2343
+ case 6:
2344
+ this.begin("bol");
2345
+ return 8;
2346
+ case 7: break;
2347
+ case 8: break;
2348
+ case 9: return 7;
2349
+ case 10: return 11;
2350
+ case 11: return 5;
2351
+ case 12: return 12;
2352
+ case 13: return 17;
2353
+ case 14:
2354
+ if (yy.consumeIndentText) yy.consumeIndentText = false;
2355
+ else return 19;
2356
+ break;
2357
+ case 15: return 24;
2358
+ case 16:
2359
+ yy_.yytext = yy_.yytext.slice(2, -2);
2360
+ return 14;
2361
+ case 17:
2362
+ yy_.yytext = yy_.yytext.slice(1, -1).trim();
2363
+ return 14;
2364
+ case 18: return 16;
2365
+ case 19: return 31;
2366
+ case 20: return 33;
2367
+ case 21: return 32;
2368
+ case 22: return 20;
2369
+ case 23: return 21;
2370
+ case 24: return 27;
2371
+ case 25: return 15;
2372
+ }
2373
+ }, "anonymous"),
2374
+ rules: [
2375
+ /^(?:%%(?!\{)[^\n]*)/i,
2376
+ /^(?:[^\}]%%[^\n]*)/i,
2377
+ /^(?:[ \t]+(?=[\n\r]))/i,
2378
+ /^(?:[ \t]+(?=text\b))/i,
2379
+ /^(?:[ \t]+)/i,
2380
+ /^(?:[^ \t\n\r])/i,
2381
+ /^(?:[\n\r]+)/i,
2382
+ /^(?:%%[^\n]*)/i,
2383
+ /^(?:[ \t]+)/i,
2384
+ /^(?:$)/i,
2385
+ /^(?:title\s[^#\n;]+)/i,
2386
+ /^(?:venn-beta\b)/i,
2387
+ /^(?:set\b)/i,
2388
+ /^(?:union\b)/i,
2389
+ /^(?:text\b)/i,
2390
+ /^(?:style\b)/i,
2391
+ /^(?:\["[^\"]*"\])/i,
2392
+ /^(?:\[[^\]\"]+\])/i,
2393
+ /^(?:[+-]?(\d+(\.\d+)?|\.\d+))/i,
2394
+ /^(?:#[0-9a-fA-F]{3,8})/i,
2395
+ /^(?:rgba\(\s*[0-9.]+\s*[,]\s*[0-9.]+\s*[,]\s*[0-9.]+\s*[,]\s*[0-9.]+\s*\))/i,
2396
+ /^(?:rgb\(\s*[0-9.]+\s*[,]\s*[0-9.]+\s*[,]\s*[0-9.]+\s*\))/i,
2397
+ /^(?:[A-Za-z_][A-Za-z0-9\-_]*)/i,
2398
+ /^(?:"[^\"]*")/i,
2399
+ /^(?:,)/i,
2400
+ /^(?::)/i
2401
+ ],
2402
+ conditions: {
2403
+ "bol": {
2404
+ "rules": [
2405
+ 0,
2406
+ 1,
2407
+ 2,
2408
+ 3,
2409
+ 4,
2410
+ 5,
2411
+ 6,
2412
+ 7,
2413
+ 8,
2414
+ 9,
2415
+ 10,
2416
+ 11,
2417
+ 12,
2418
+ 13,
2419
+ 14,
2420
+ 15,
2421
+ 16,
2422
+ 17,
2423
+ 18,
2424
+ 19,
2425
+ 20,
2426
+ 21,
2427
+ 22,
2428
+ 23,
2429
+ 24,
2430
+ 25
2431
+ ],
2432
+ "inclusive": true
2433
+ },
2434
+ "INITIAL": {
2435
+ "rules": [
2436
+ 0,
2437
+ 1,
2438
+ 6,
2439
+ 7,
2440
+ 8,
2441
+ 9,
2442
+ 10,
2443
+ 11,
2444
+ 12,
2445
+ 13,
2446
+ 14,
2447
+ 15,
2448
+ 16,
2449
+ 17,
2450
+ 18,
2451
+ 19,
2452
+ 20,
2453
+ 21,
2454
+ 22,
2455
+ 23,
2456
+ 24,
2457
+ 25
2458
+ ],
2459
+ "inclusive": true
2460
+ }
2461
+ }
2462
+ };
2463
+ })();
2464
+ function Parser() {
2465
+ this.yy = {};
2466
+ }
2467
+ __name(Parser, "Parser");
2468
+ Parser.prototype = parser2;
2469
+ parser2.Parser = Parser;
2470
+ return new Parser();
2471
+ })();
2472
+ parser.parser = parser;
2473
+ var venn_default = parser;
2474
+ var subsets = [];
2475
+ var textNodes = [];
2476
+ var styleEntries = [];
2477
+ var knownSets = /* @__PURE__ */ new Set();
2478
+ var currentSets;
2479
+ var indentMode = false;
2480
+ var addSubsetData = /* @__PURE__ */ __name((identifierList, label, size) => {
2481
+ const sets = normalizeIdentifierList(identifierList).sort();
2482
+ const resolvedSize = size ?? 10 / Math.pow(identifierList.length, 2);
2483
+ currentSets = sets;
2484
+ if (sets.length === 1) knownSets.add(sets[0]);
2485
+ subsets.push({
2486
+ sets,
2487
+ size: resolvedSize,
2488
+ label: label ? normalizeText(label) : void 0
2489
+ });
2490
+ }, "addSubsetData");
2491
+ var getSubsetData = /* @__PURE__ */ __name(() => {
2492
+ return subsets;
2493
+ }, "getSubsetData");
2494
+ var normalizeText = /* @__PURE__ */ __name((text) => {
2495
+ const trimmed = text.trim();
2496
+ if (trimmed.length >= 2 && trimmed.startsWith("\"") && trimmed.endsWith("\"")) return trimmed.slice(1, -1);
2497
+ return trimmed;
2498
+ }, "normalizeText");
2499
+ var normalizeStyleValue = /* @__PURE__ */ __name((value) => {
2500
+ return value ? normalizeText(value) : value;
2501
+ }, "normalizeStyleValue");
2502
+ var addTextData = /* @__PURE__ */ __name((identifierList, id, label) => {
2503
+ const normalizedId = normalizeText(id);
2504
+ textNodes.push({
2505
+ sets: normalizeIdentifierList(identifierList).sort(),
2506
+ id: normalizedId,
2507
+ label: label ? normalizeText(label) : void 0
2508
+ });
2509
+ }, "addTextData");
2510
+ var addStyleData = /* @__PURE__ */ __name((identifierList, data) => {
2511
+ const targets = normalizeIdentifierList(identifierList).sort();
2512
+ const styles = {};
2513
+ for (const [key, value] of data) styles[key] = normalizeStyleValue(value) ?? value;
2514
+ styleEntries.push({
2515
+ targets,
2516
+ styles
2517
+ });
2518
+ }, "addStyleData");
2519
+ var getStyleData = /* @__PURE__ */ __name(() => {
2520
+ return styleEntries;
2521
+ }, "getStyleData");
2522
+ var normalizeIdentifierList = /* @__PURE__ */ __name((identifierList) => {
2523
+ return identifierList.map((identifier) => normalizeText(identifier));
2524
+ }, "normalizeIdentifierList");
2525
+ var validateUnionIdentifiers = /* @__PURE__ */ __name((identifierList) => {
2526
+ const unknown = normalizeIdentifierList(identifierList).filter((identifier) => !knownSets.has(identifier));
2527
+ if (unknown.length > 0) throw new Error(`unknown set identifier: ${unknown.join(", ")}`);
2528
+ }, "validateUnionIdentifiers");
2529
+ var getTextData = /* @__PURE__ */ __name(() => {
2530
+ return textNodes;
2531
+ }, "getTextData");
2532
+ var getCurrentSets = /* @__PURE__ */ __name(() => currentSets, "getCurrentSets");
2533
+ var getIndentMode = /* @__PURE__ */ __name(() => indentMode, "getIndentMode");
2534
+ var setIndentMode = /* @__PURE__ */ __name((enabled) => {
2535
+ indentMode = enabled;
2536
+ }, "setIndentMode");
2537
+ var DEFAULT_VENN_CONFIG = defaultConfig_default.venn;
2538
+ function getConfig2() {
2539
+ return cleanAndMerge(DEFAULT_VENN_CONFIG, getConfig().venn);
2540
+ }
2541
+ __name(getConfig2, "getConfig");
2542
+ var db = {
2543
+ getConfig: getConfig2,
2544
+ clear: /* @__PURE__ */ __name(() => {
2545
+ clear();
2546
+ subsets.length = 0;
2547
+ textNodes.length = 0;
2548
+ styleEntries.length = 0;
2549
+ knownSets.clear();
2550
+ currentSets = void 0;
2551
+ indentMode = false;
2552
+ }, "customClear"),
2553
+ setAccTitle,
2554
+ getAccTitle,
2555
+ setDiagramTitle,
2556
+ getDiagramTitle,
2557
+ getAccDescription,
2558
+ setAccDescription,
2559
+ addSubsetData,
2560
+ getSubsetData,
2561
+ addTextData,
2562
+ addStyleData,
2563
+ validateUnionIdentifiers,
2564
+ getTextData,
2565
+ getStyleData,
2566
+ getCurrentSets,
2567
+ getIndentMode,
2568
+ setIndentMode
2569
+ };
2570
+ var styles_default = /* @__PURE__ */ __name((options) => `
2571
+ .venn-title {
2572
+ font-size: 32px;
2573
+ fill: ${options.vennTitleTextColor};
2574
+ font-family: ${options.fontFamily};
2575
+ }
2576
+
2577
+ .venn-circle text {
2578
+ font-size: 48px;
2579
+ font-family: ${options.fontFamily};
2580
+ }
2581
+
2582
+ .venn-intersection text {
2583
+ font-size: 48px;
2584
+ fill: ${options.vennSetTextColor};
2585
+ font-family: ${options.fontFamily};
2586
+ }
2587
+
2588
+ .venn-text-node {
2589
+ font-family: ${options.fontFamily};
2590
+ color: ${options.vennSetTextColor};
2591
+ }
2592
+ `, "getStyles");
2593
+ function buildStyleByKey(styleData) {
2594
+ const map = /* @__PURE__ */ new Map();
2595
+ for (const entry of styleData) {
2596
+ const key = entry.targets.join("|");
2597
+ const existing = map.get(key);
2598
+ if (existing) Object.assign(existing, entry.styles);
2599
+ else map.set(key, { ...entry.styles });
2600
+ }
2601
+ return map;
2602
+ }
2603
+ __name(buildStyleByKey, "buildStyleByKey");
2604
+ var draw = /* @__PURE__ */ __name((_text, id, _version, diagObj) => {
2605
+ const db2 = diagObj.db;
2606
+ const config = db2.getConfig?.();
2607
+ const { themeVariables, look, handDrawnSeed } = getConfig();
2608
+ const isHandDrawn = look === "handDrawn";
2609
+ const themeColors = [
2610
+ themeVariables.venn1,
2611
+ themeVariables.venn2,
2612
+ themeVariables.venn3,
2613
+ themeVariables.venn4,
2614
+ themeVariables.venn5,
2615
+ themeVariables.venn6,
2616
+ themeVariables.venn7,
2617
+ themeVariables.venn8
2618
+ ].filter(Boolean);
2619
+ const title = db2.getDiagramTitle?.();
2620
+ const sets = db2.getSubsetData();
2621
+ const textNodes2 = db2.getTextData();
2622
+ const styleByKey = buildStyleByKey(db2.getStyleData());
2623
+ const renderSets = ensurePairwiseSubsets(sets);
2624
+ const svgWidth = config?.width ?? 800;
2625
+ const svgHeight = config?.height ?? 450;
2626
+ const scale = svgWidth / 1600;
2627
+ const titleHeight = title ? 48 * scale : 0;
2628
+ const defaultTextColor = themeVariables.primaryTextColor ?? themeVariables.textColor;
2629
+ const svg = selectSvgElement(id);
2630
+ svg.attr("viewBox", `0 0 ${svgWidth} ${svgHeight}`);
2631
+ if (title) svg.append("text").text(title).attr("class", "venn-title").attr("font-size", `${32 * scale}px`).attr("text-anchor", "middle").attr("dominant-baseline", "middle").attr("x", "50%").attr("y", 32 * scale).style("fill", themeVariables.vennTitleTextColor || themeVariables.titleColor);
2632
+ const dummyD3root = select_default(document.createElement("div"));
2633
+ const vennDiagram = VennDiagram().width(svgWidth).height(svgHeight - titleHeight);
2634
+ dummyD3root.datum(renderSets).call(vennDiagram);
2635
+ const roughSvg = isHandDrawn ? import_rough_cjs.default.svg(dummyD3root.select("svg").node()) : void 0;
2636
+ const layoutAreas = layout(renderSets, {
2637
+ width: svgWidth,
2638
+ height: svgHeight - titleHeight,
2639
+ padding: config?.padding ?? 15
2640
+ });
2641
+ const layoutByKey = /* @__PURE__ */ new Map();
2642
+ for (const area of layoutAreas) {
2643
+ const key = stableSetsKey([...area.data.sets].sort());
2644
+ layoutByKey.set(key, area);
2645
+ }
2646
+ if (textNodes2.length > 0) renderTextNodes(config, layoutByKey, dummyD3root, textNodes2, scale, styleByKey);
2647
+ const themeDark = isDark(themeVariables.background || "#f4f4f4");
2648
+ dummyD3root.selectAll(".venn-circle").each(function(d, i) {
2649
+ const group = select_default(this);
2650
+ const setsKey = stableSetsKey([...d.sets].sort());
2651
+ const customStyle = styleByKey.get(setsKey);
2652
+ const paletteColor = themeColors.length > 0 ? themeColors[i % themeColors.length] : void 0;
2653
+ const baseColor = customStyle?.fill || paletteColor || themeVariables.primaryColor;
2654
+ group.classed(`venn-set-${i % 8}`, true);
2655
+ const fillOpacity = customStyle?.["fill-opacity"] ?? .1;
2656
+ const strokeColor = customStyle?.stroke || baseColor;
2657
+ const strokeWidthVal = customStyle?.["stroke-width"] || `${5 * scale}`;
2658
+ if (isHandDrawn && roughSvg) {
2659
+ const layoutArea = layoutByKey.get(setsKey);
2660
+ if (layoutArea && layoutArea.circles.length > 0) {
2661
+ const c = layoutArea.circles[0];
2662
+ const roughNode = roughSvg.circle(c.x, c.y, c.radius * 2, {
2663
+ roughness: .7,
2664
+ seed: handDrawnSeed,
2665
+ fill: transparentize(baseColor, .7),
2666
+ fillStyle: "hachure",
2667
+ fillWeight: 2,
2668
+ hachureGap: 8,
2669
+ hachureAngle: -41 + i * 60,
2670
+ stroke: strokeColor,
2671
+ strokeWidth: parseFloat(String(strokeWidthVal))
2672
+ });
2673
+ group.select("path").remove();
2674
+ group.node()?.insertBefore(roughNode, group.select("text").node());
2675
+ }
2676
+ } else group.select("path").style("fill", baseColor).style("fill-opacity", fillOpacity).style("stroke", strokeColor).style("stroke-width", strokeWidthVal).style("stroke-opacity", .95);
2677
+ const textColor = customStyle?.color || (themeDark ? lighten(baseColor, 30) : darken(baseColor, 30));
2678
+ group.select("text").style("font-size", `${48 * scale}px`).style("fill", textColor);
2679
+ });
2680
+ if (isHandDrawn && roughSvg) dummyD3root.selectAll(".venn-intersection").each(function(d) {
2681
+ const group = select_default(this);
2682
+ const setsKey = stableSetsKey([...d.sets].sort());
2683
+ const customStyle = styleByKey.get(setsKey);
2684
+ const customFill = customStyle?.fill;
2685
+ if (customFill) {
2686
+ const pathEl = group.select("path");
2687
+ const pathD = pathEl.attr("d");
2688
+ if (pathD) {
2689
+ const roughNode = roughSvg.path(pathD, {
2690
+ roughness: .7,
2691
+ seed: handDrawnSeed,
2692
+ fill: transparentize(customFill, .3),
2693
+ fillStyle: "cross-hatch",
2694
+ fillWeight: 2,
2695
+ hachureGap: 6,
2696
+ hachureAngle: 60,
2697
+ stroke: "none"
2698
+ });
2699
+ const existingPath = pathEl.node();
2700
+ existingPath?.parentNode?.insertBefore(roughNode, existingPath);
2701
+ pathEl.remove();
2702
+ }
2703
+ } else group.select("path").style("fill-opacity", 0);
2704
+ group.select("text").style("font-size", `${48 * scale}px`).style("fill", customStyle?.color ?? themeVariables.vennSetTextColor ?? defaultTextColor);
2705
+ });
2706
+ else {
2707
+ dummyD3root.selectAll(".venn-intersection text").style("font-size", `${48 * scale}px`).style("fill", (e) => {
2708
+ const setsKey = stableSetsKey([...e.sets].sort());
2709
+ return styleByKey.get(setsKey)?.color ?? themeVariables.vennSetTextColor ?? defaultTextColor;
2710
+ });
2711
+ dummyD3root.selectAll(".venn-intersection path").style("fill-opacity", (e) => {
2712
+ const setsKey = stableSetsKey([...e.sets].sort());
2713
+ return styleByKey.get(setsKey)?.fill ? 1 : 0;
2714
+ }).style("fill", (e) => {
2715
+ const setsKey = stableSetsKey([...e.sets].sort());
2716
+ return styleByKey.get(setsKey)?.fill ?? "transparent";
2717
+ });
2718
+ }
2719
+ const vennGroup = svg.append("g").attr("transform", `translate(0, ${titleHeight})`);
2720
+ const dummySvg = dummyD3root.select("svg").node();
2721
+ if (dummySvg && "childNodes" in dummySvg) for (const child of [...dummySvg.childNodes]) vennGroup.node()?.appendChild(child);
2722
+ configureSvgSize(svg, svgHeight, svgWidth, config?.useMaxWidth ?? true);
2723
+ }, "draw");
2724
+ function stableSetsKey(setIds) {
2725
+ return setIds.join("|");
2726
+ }
2727
+ __name(stableSetsKey, "stableSetsKey");
2728
+ function renderTextNodes(config, layoutByKey, dummyD3root, textNodes2, scale, styleByKey) {
2729
+ const useDebugLayout = config?.useDebugLayout ?? false;
2730
+ const textGroup = dummyD3root.select("svg").append("g").attr("class", "venn-text-nodes");
2731
+ const nodesByArea = /* @__PURE__ */ new Map();
2732
+ for (const node of textNodes2) {
2733
+ const key = stableSetsKey(node.sets);
2734
+ const existing = nodesByArea.get(key);
2735
+ if (existing) existing.push(node);
2736
+ else nodesByArea.set(key, [node]);
2737
+ }
2738
+ for (const [key, nodes] of nodesByArea.entries()) {
2739
+ const area = layoutByKey.get(key);
2740
+ if (!area?.text) continue;
2741
+ const centerX = area.text.x;
2742
+ const centerY = area.text.y;
2743
+ const minCircleRadius = Math.min(...area.circles.map((c) => c.radius));
2744
+ const innerRadiusRaw = Math.min(...area.circles.map((c) => c.radius - Math.hypot(centerX - c.x, centerY - c.y)));
2745
+ let innerRadius = Number.isFinite(innerRadiusRaw) ? Math.max(0, innerRadiusRaw) : 0;
2746
+ if (innerRadius === 0 && Number.isFinite(minCircleRadius)) innerRadius = minCircleRadius * .6;
2747
+ const areaGroup = textGroup.append("g").attr("class", "venn-text-area").attr("font-size", `${40 * scale}px`);
2748
+ if (useDebugLayout) areaGroup.append("circle").attr("class", "venn-text-debug-circle").attr("cx", centerX).attr("cy", centerY).attr("r", innerRadius).attr("fill", "none").attr("stroke", "purple").attr("stroke-width", 1.5 * scale).attr("stroke-dasharray", `${6 * scale} ${4 * scale}`);
2749
+ const innerWidth = Math.max(80 * scale, innerRadius * 2 * .95);
2750
+ const innerHeight = Math.max(60 * scale, innerRadius * 2 * .95);
2751
+ const labelOffset = (area.data.label && area.data.label.length > 0 ? Math.min(32 * scale, innerRadius * .25) : 0) + (nodes.length <= 2 ? 30 * scale : 0);
2752
+ const startX = centerX - innerWidth / 2;
2753
+ const startY = centerY - innerHeight / 2 + labelOffset;
2754
+ const cols = Math.max(1, Math.ceil(Math.sqrt(nodes.length)));
2755
+ const rows = Math.max(1, Math.ceil(nodes.length / cols));
2756
+ const cellWidth = innerWidth / cols;
2757
+ const cellHeight = innerHeight / rows;
2758
+ for (const [i, node] of nodes.entries()) {
2759
+ const col = i % cols;
2760
+ const row = Math.floor(i / cols);
2761
+ const x = startX + cellWidth * (col + .5);
2762
+ const y = startY + cellHeight * (row + .5);
2763
+ if (useDebugLayout) areaGroup.append("rect").attr("class", "venn-text-debug-cell").attr("x", startX + cellWidth * col).attr("y", startY + cellHeight * row).attr("width", cellWidth).attr("height", cellHeight).attr("fill", "none").attr("stroke", "teal").attr("stroke-width", 1 * scale).attr("stroke-dasharray", `${4 * scale} ${3 * scale}`);
2764
+ const boxWidth = cellWidth * .9;
2765
+ const boxHeight = cellHeight * .9;
2766
+ const container = areaGroup.append("foreignObject").attr("class", "venn-text-node-fo").attr("width", boxWidth).attr("height", boxHeight).attr("x", x - boxWidth / 2).attr("y", y - boxHeight / 2).attr("overflow", "visible");
2767
+ const textColor = styleByKey.get(node.id)?.color;
2768
+ const text = container.append("xhtml:span").attr("class", "venn-text-node").style("display", "flex").style("width", "100%").style("height", "100%").style("white-space", "normal").style("align-items", "center").style("justify-content", "center").style("text-align", "center").style("overflow-wrap", "normal").style("word-break", "normal").text(node.label ?? node.id);
2769
+ if (textColor) text.style("color", textColor);
2770
+ }
2771
+ }
2772
+ }
2773
+ __name(renderTextNodes, "renderTextNodes");
2774
+ function ensurePairwiseSubsets(subsets2) {
2775
+ const existingKeys = new Set(subsets2.map((s) => [...s.sets].sort().join("|")));
2776
+ const individualSetSizes = new Map(subsets2.filter((s) => s.sets.length === 1 && s.size !== void 0).map((s) => [s.sets[0], s.size]));
2777
+ const synthetic = [];
2778
+ for (const subset of subsets2) {
2779
+ if (subset.sets.length < 3) continue;
2780
+ const members = [...subset.sets].sort();
2781
+ for (let i = 0; i < members.length - 1; i++) for (let j = i + 1; j < members.length; j++) {
2782
+ const pair = [members[i], members[j]];
2783
+ const key = pair.join("|");
2784
+ if (!existingKeys.has(key)) {
2785
+ existingKeys.add(key);
2786
+ const sizeA = individualSetSizes.get(pair[0]);
2787
+ const sizeB = individualSetSizes.get(pair[1]);
2788
+ const pairSize = sizeA !== void 0 && sizeB !== void 0 ? Math.min(sizeA, sizeB) / 4 : 2.5;
2789
+ synthetic.push({
2790
+ sets: pair,
2791
+ size: pairSize,
2792
+ label: ""
2793
+ });
2794
+ }
2795
+ }
2796
+ }
2797
+ return synthetic.length > 0 ? [...subsets2, ...synthetic] : subsets2;
2798
+ }
2799
+ __name(ensurePairwiseSubsets, "ensurePairwiseSubsets");
2800
+ var diagram = {
2801
+ parser: venn_default,
2802
+ db,
2803
+ renderer: { draw },
2804
+ styles: styles_default
2805
+ };
2806
+
2807
+ //#endregion
2808
+ export { diagram };