@diagrammo/dgmo 0.46.0 → 0.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/advanced.d.cts +3 -855
- package/dist/advanced.d.ts +3 -855
- package/dist/advanced.js +541 -70107
- package/dist/analyzer-UYKBXAKR.js +15 -0
- package/dist/auto.cjs +1 -1
- package/dist/auto.js +1 -1
- package/dist/auto.mjs +1 -1
- package/dist/block.js +83 -69417
- package/dist/calculator-LDYQCDDY.js +11 -0
- package/dist/charts-d3-QOZHKTCT.js +25 -0
- package/dist/chunk-2DXMZRWJ.js +800 -0
- package/dist/chunk-2LACINWN.js +786 -0
- package/dist/chunk-33LCUH4H.js +893 -0
- package/dist/chunk-3CIOJ5YJ.js +35 -0
- package/dist/chunk-3HDBAXF5.js +86 -0
- package/dist/chunk-3JLKYGBQ.js +290 -0
- package/dist/chunk-3MQQNXPD.js +415 -0
- package/dist/chunk-3R5POCTZ.js +967 -0
- package/dist/chunk-3SMGIJDD.js +112 -0
- package/dist/chunk-44CM72SQ.js +409 -0
- package/dist/chunk-4GRI7MEB.js +1604 -0
- package/dist/chunk-4OHACBGX.js +606 -0
- package/dist/chunk-5DH3KYFH.js +21 -0
- package/dist/chunk-5MLYVTYM.js +76 -0
- package/dist/chunk-5QXL4NYS.js +553 -0
- package/dist/chunk-5WRI5ZAA.js +31 -0
- package/dist/chunk-6EK55ART.js +117 -0
- package/dist/chunk-6FZYCKXB.js +2065 -0
- package/dist/chunk-6HO5ZTXK.js +277 -0
- package/dist/chunk-6KFWC4CO.js +7 -0
- package/dist/chunk-6MTWIQVO.js +121 -0
- package/dist/chunk-6NYWYNBI.js +329 -0
- package/dist/chunk-6SM5NJQH.js +620 -0
- package/dist/chunk-725LDASD.js +422 -0
- package/dist/chunk-76OWZ3BA.js +130 -0
- package/dist/chunk-7JEGTRLD.js +338 -0
- package/dist/chunk-A44USUV7.js +923 -0
- package/dist/chunk-A4GOY3PE.js +25 -0
- package/dist/chunk-A4VFQH5G.js +251 -0
- package/dist/chunk-AELOBFW5.js +375 -0
- package/dist/chunk-AN2MOO5T.js +522 -0
- package/dist/chunk-BMR4CIEO.js +41 -0
- package/dist/chunk-BS7SV7C3.js +51 -0
- package/dist/chunk-BUPDIHML.js +613 -0
- package/dist/chunk-BUVJFRPY.js +887 -0
- package/dist/chunk-C3Z4DX3V.js +112 -0
- package/dist/chunk-CI2G3OEB.js +1818 -0
- package/dist/chunk-CKNVO24D.js +54 -0
- package/dist/chunk-CUVHQHZ7.js +391 -0
- package/dist/chunk-CXK4DZH3.js +114 -0
- package/dist/chunk-DKEPS5LH.js +315 -0
- package/dist/chunk-DU7W62N5.js +487 -0
- package/dist/chunk-DZAQBW35.js +751 -0
- package/dist/chunk-EB6FPQUP.js +316 -0
- package/dist/chunk-EMS2SK26.js +376 -0
- package/dist/chunk-ERLBPDGU.js +510 -0
- package/dist/chunk-EVCVDTXE.js +732 -0
- package/dist/chunk-FCIIHT24.js +384 -0
- package/dist/chunk-FFUN5D66.js +97 -0
- package/dist/chunk-FITOLXSX.js +714 -0
- package/dist/chunk-FMDSF3OV.js +68 -0
- package/dist/chunk-FNB3PNGF.js +410 -0
- package/dist/chunk-G2H74XJZ.js +2104 -0
- package/dist/chunk-GMR5MFHJ.js +339 -0
- package/dist/chunk-H6PI3KJT.js +305 -0
- package/dist/chunk-I46X5VUA.js +59 -0
- package/dist/chunk-I5IGB56C.js +255 -0
- package/dist/chunk-IH6ZMVQ5.js +3950 -0
- package/dist/chunk-IJZFN3HM.js +463 -0
- package/dist/chunk-IPWPWM6R.js +3079 -0
- package/dist/chunk-IYULMRBE.js +23 -0
- package/dist/chunk-IZMRON6C.js +167 -0
- package/dist/chunk-J5FIXQRT.js +813 -0
- package/dist/chunk-JED6ZDEE.js +73 -0
- package/dist/chunk-JEUJOX5X.js +136 -0
- package/dist/chunk-JM4LEPY3.js +436 -0
- package/dist/chunk-L3UHP6TD.js +101 -0
- package/dist/chunk-L66GEFB6.js +524 -0
- package/dist/chunk-LIOHW36Z.js +469 -0
- package/dist/chunk-LP7EC4MI.js +16 -0
- package/dist/chunk-MITI6NOL.js +548 -0
- package/dist/chunk-MO5YHHMQ.js +168 -0
- package/dist/chunk-MZSBFAPJ.js +885 -0
- package/dist/chunk-NNAAJVBU.js +9 -0
- package/dist/chunk-NOTA6TEI.js +47 -0
- package/dist/chunk-NURGB5Z4.js +335 -0
- package/dist/chunk-NX4EQS3U.js +1062 -0
- package/dist/chunk-NXMESY4J.js +1 -0
- package/dist/chunk-OJR3MQYV.js +1458 -0
- package/dist/chunk-OURHMODR.js +454 -0
- package/dist/chunk-P235SVAH.js +1057 -0
- package/dist/chunk-P4RH4OSP.js +1038 -0
- package/dist/chunk-P6T66CCZ.js +226 -0
- package/dist/chunk-PBAHEPLQ.js +223 -0
- package/dist/chunk-PBHE5UG6.js +1530 -0
- package/dist/chunk-PDKUANDZ.js +35 -0
- package/dist/chunk-PWIHZ6NJ.js +296 -0
- package/dist/chunk-QEBUY5NY.js +1685 -0
- package/dist/chunk-QLCCJEJI.js +253 -0
- package/dist/chunk-QOOUC2J5.js +52 -0
- package/dist/chunk-QYTPPDAO.js +402 -0
- package/dist/chunk-R3XI2VC7.js +801 -0
- package/dist/chunk-RCERWOJR.js +154 -0
- package/dist/chunk-RJE5JTVK.js +362 -0
- package/dist/chunk-RTLBSQ3G.js +1155 -0
- package/dist/chunk-RUNNI6VE.js +448 -0
- package/dist/chunk-RVMRZAPB.js +354 -0
- package/dist/chunk-RYEGFMUO.js +955 -0
- package/dist/chunk-RZCF2VVM.js +528 -0
- package/dist/chunk-SML67VPV.js +1025 -0
- package/dist/chunk-SQ7IY53Q.js +44 -0
- package/dist/chunk-SQAG3UXH.js +161 -0
- package/dist/chunk-SRTU6HMQ.js +1851 -0
- package/dist/chunk-T2OE3YQB.js +550 -0
- package/dist/chunk-T3UBLACL.js +299 -0
- package/dist/chunk-TLVIHFRO.js +296 -0
- package/dist/chunk-TYS6CSS5.js +52 -0
- package/dist/chunk-U6EQI3U6.js +130 -0
- package/dist/chunk-UJ4FJLBF.js +86 -0
- package/dist/chunk-ULOEATBZ.js +347 -0
- package/dist/chunk-UNCCZ3NU.js +127 -0
- package/dist/chunk-USZW2HHU.js +197 -0
- package/dist/chunk-UWN33VNX.js +1610 -0
- package/dist/chunk-UZ7EZW3B.js +40 -0
- package/dist/chunk-VOKGH627.js +37 -0
- package/dist/chunk-WBRZJOEC.js +204 -0
- package/dist/chunk-WCSOJFU3.js +380 -0
- package/dist/chunk-WCT3NYCV.js +160 -0
- package/dist/chunk-WVAJFAIA.js +529 -0
- package/dist/chunk-X5LCYCL5.js +394 -0
- package/dist/chunk-XAKEUMEJ.js +1256 -0
- package/dist/chunk-Y2ZE3MSG.js +590 -0
- package/dist/chunk-Y3J7VR52.js +646 -0
- package/dist/chunk-Y5QGVTVC.js +33 -0
- package/dist/chunk-YAA6IID3.js +548 -0
- package/dist/chunk-YGJTDXVR.js +692 -0
- package/dist/chunk-YRYKTYMQ.js +186 -0
- package/dist/chunk-YYVTBZZC.js +61 -0
- package/dist/chunk-Z5CGSFJB.js +647 -0
- package/dist/chunk-Z72XRXD4.js +787 -0
- package/dist/chunk-ZGR7ULFJ.js +978 -0
- package/dist/chunk-ZJEL4H2R.js +851 -0
- package/dist/chunk-ZO27FGJS.js +554 -0
- package/dist/collapse-CLPJD2RL.js +11 -0
- package/dist/collapse-SLINJQW6.js +9 -0
- package/dist/collapse-ZWUFFCK2.js +9 -0
- package/dist/compute-G55RG53N.js +8 -0
- package/dist/dgmo-router-DZCIDUO5.js +73 -0
- package/dist/dimensions-J3FHIMJ6.js +22 -0
- package/dist/element.cjs +1 -1
- package/dist/element.js +1 -1
- package/dist/element.mjs +1 -1
- package/dist/flowchart-parser-ZNSKIBVR.js +21 -0
- package/dist/flowchart-renderer-ZAEOL4DX.js +35 -0
- package/dist/index.cjs +3 -3
- package/dist/index.d.cts +3 -469
- package/dist/index.d.ts +3 -469
- package/dist/index.js +137 -69685
- package/dist/layout-46N4JJYK.js +17 -0
- package/dist/layout-5RA6QWR6.js +26 -0
- package/dist/layout-5T6RH5M6.js +14 -0
- package/dist/layout-7QXCNOVS.js +13 -0
- package/dist/layout-EE6GE46Y.js +17 -0
- package/dist/layout-G23F7LDH.js +9 -0
- package/dist/layout-HRBZPFCN.js +23 -0
- package/dist/layout-HWDSRX5E.js +20 -0
- package/dist/layout-HYZPWAK5.js +18 -0
- package/dist/layout-N76NR4ZO.js +19 -0
- package/dist/layout-OB3RI63S.js +14 -0
- package/dist/layout-S2QBYSK2.js +15 -0
- package/dist/layout-UM5F4DJB.js +15 -0
- package/dist/layout-search-OYV77HHS.js +1655 -0
- package/dist/load-data-EHDDZ5ZS.js +8 -0
- package/dist/palettes-PRJ2RI6D.js +56 -0
- package/dist/parser-2MFP2H2E.js +11 -0
- package/dist/parser-3STE62GB.js +21 -0
- package/dist/parser-4FL2CMDG.js +18 -0
- package/dist/parser-4OGOBJJ4.js +13 -0
- package/dist/parser-6BTRLKRZ.js +15 -0
- package/dist/parser-AQETEVRW.js +21 -0
- package/dist/parser-CFZD5IBL.js +12 -0
- package/dist/parser-FUSKFGZN.js +16 -0
- package/dist/parser-I6KXEYFK.js +13 -0
- package/dist/parser-IXSZZQHY.js +18 -0
- package/dist/parser-JAL2HD4I.js +13 -0
- package/dist/parser-KNSQSKQO.js +20 -0
- package/dist/parser-N5O4IHUN.js +13 -0
- package/dist/parser-NGU3ETO6.js +16 -0
- package/dist/parser-NRAI6O25.js +19 -0
- package/dist/parser-O5J4VBII.js +11 -0
- package/dist/parser-OV7NOBW6.js +21 -0
- package/dist/parser-PQ3POX45.js +23 -0
- package/dist/parser-TFZFBVWN.js +11 -0
- package/dist/parser-TRTHDFPP.js +18 -0
- package/dist/parser-VQP2UJ6W.js +11 -0
- package/dist/parser-XDVELHRK.js +13 -0
- package/dist/parser-XKRP7QKP.js +11 -0
- package/dist/parser-Y6WTBU76.js +14 -0
- package/dist/parser-ZSDPZYQP.js +12 -0
- package/dist/renderer-2XQQQ6QR.js +28 -0
- package/dist/renderer-5NDVNDAZ.js +26 -0
- package/dist/renderer-6EEZHMH4.js +26 -0
- package/dist/renderer-6W5462RB.js +43 -0
- package/dist/renderer-7MVLWWQD.js +22 -0
- package/dist/renderer-AWWAF6XD.js +33 -0
- package/dist/renderer-BYCNMBF7.js +34 -0
- package/dist/renderer-CLJHQPBJ.js +29 -0
- package/dist/renderer-GHPZMFU2.js +15 -0
- package/dist/renderer-JGBKUCZD.js +16 -0
- package/dist/renderer-KQB7UGDS.js +19 -0
- package/dist/renderer-PGX2TKVS.js +24 -0
- package/dist/renderer-QIWVHWZO.js +15 -0
- package/dist/renderer-RPOA5YPZ.js +35 -0
- package/dist/renderer-SMIBCRVB.js +24 -0
- package/dist/renderer-T7YKC5VP.js +28 -0
- package/dist/renderer-TOCOVLHS.js +37 -0
- package/dist/renderer-UWA5XS74.js +39 -0
- package/dist/renderer-VACVQYML.js +25 -0
- package/dist/renderer-W4M6QLIJ.js +37 -0
- package/dist/renderer-WZRREQ2P.js +23 -0
- package/dist/renderer-YY2OSF6E.js +27 -0
- package/dist/renderer-Z7I3W2PP.js +24 -0
- package/dist/renderer-ZGNTUWC4.js +22 -0
- package/dist/renderer-ZTR3DER3.js +19 -0
- package/dist/renderer-radial-C32GPJQ7.js +21 -0
- package/dist/resolver-NOAA7ID7.js +13 -0
- package/dist/state-collapse-HCGD6IVJ.js +8 -0
- package/dist/state-parser-Z2V23ATR.js +18 -0
- package/dist/state-renderer-RFYHSP4K.js +34 -0
- package/dist/themes-1-CuKpeH.d.cts +908 -0
- package/dist/themes-1-CuKpeH.d.ts +908 -0
- package/package.json +1 -1
|
@@ -0,0 +1,606 @@
|
|
|
1
|
+
import {
|
|
2
|
+
measureText
|
|
3
|
+
} from "./chunk-WCT3NYCV.js";
|
|
4
|
+
import {
|
|
5
|
+
formatDuration,
|
|
6
|
+
formatScheduleValue,
|
|
7
|
+
formatSlackValue,
|
|
8
|
+
formatSprintCell
|
|
9
|
+
} from "./chunk-L3UHP6TD.js";
|
|
10
|
+
|
|
11
|
+
// src/pert/layout.ts
|
|
12
|
+
import dagre from "@dagrejs/dagre";
|
|
13
|
+
var DEFAULT_NODE_HEIGHT = 90;
|
|
14
|
+
var MILESTONE_NODE_HEIGHT = DEFAULT_NODE_HEIGHT;
|
|
15
|
+
var COLLAPSED_GROUP_HEIGHT = 90;
|
|
16
|
+
var DIAGRAM_PADDING = 20;
|
|
17
|
+
var GROUP_PADDING = 18;
|
|
18
|
+
var GROUP_TOP_PADDING = 28;
|
|
19
|
+
var SWIMLANE_SLOT_SEP = 40;
|
|
20
|
+
var SWIMLANE_GAP = 24;
|
|
21
|
+
var NODE_CELL_FONT_SIZE = 11;
|
|
22
|
+
var NODE_NAME_FONT_SIZE = 13;
|
|
23
|
+
var MILESTONE_NAME_FONT_SIZE = 12;
|
|
24
|
+
var CELL_PAD_X = 8;
|
|
25
|
+
var NAME_PAD_X = 6;
|
|
26
|
+
var NAME_PIN_WIDTH = 13 + 4;
|
|
27
|
+
var MIN_CELL_WIDTH = 30;
|
|
28
|
+
var MIN_NODE_WIDTH = 120;
|
|
29
|
+
var MAX_NODE_WIDTH = 280;
|
|
30
|
+
var MIN_MILESTONE_WIDTH = 80;
|
|
31
|
+
var MAX_MILESTONE_WIDTH = 160;
|
|
32
|
+
function computeNodeSizing(resolved) {
|
|
33
|
+
const unit = resolved.options.timeUnit;
|
|
34
|
+
const sprintMode = resolved.options.sprintMode;
|
|
35
|
+
const sprintNumber = resolved.options.sprintNumber ?? 1;
|
|
36
|
+
const projectStart = resolved.projectStart;
|
|
37
|
+
const fmtSchedule = (v, isTbd) => sprintMode ? formatSprintCell(v, sprintNumber, isTbd ? "?" : null) : formatScheduleValue(v, projectStart, unit, isTbd ? "?" : null);
|
|
38
|
+
const fmtSlack = (v, isTbd) => formatSlackValue(v, projectStart, unit, isTbd ? "?" : null);
|
|
39
|
+
const fmtDur = (v, isTbd) => formatDuration(v, unit, isTbd ? "?" : null);
|
|
40
|
+
let maxOuterW = 0;
|
|
41
|
+
let maxMidW = 0;
|
|
42
|
+
let maxNameW = 0;
|
|
43
|
+
let maxMilestoneTopW = 0;
|
|
44
|
+
let maxMilestoneSlackW = 0;
|
|
45
|
+
let maxMilestoneNameW = 0;
|
|
46
|
+
for (const r of resolved.activities) {
|
|
47
|
+
const isTbd = r.es === null;
|
|
48
|
+
if (r.activity.isMilestone) {
|
|
49
|
+
const dateStr = fmtSchedule(r.es, isTbd);
|
|
50
|
+
const slackStr2 = fmtSlack(r.slack, isTbd);
|
|
51
|
+
const slackHidden = !isTbd && /^0[a-z]?$/.test(slackStr2);
|
|
52
|
+
maxMilestoneTopW = Math.max(
|
|
53
|
+
maxMilestoneTopW,
|
|
54
|
+
measureText(dateStr, NODE_CELL_FONT_SIZE)
|
|
55
|
+
);
|
|
56
|
+
if (!slackHidden) {
|
|
57
|
+
maxMilestoneSlackW = Math.max(
|
|
58
|
+
maxMilestoneSlackW,
|
|
59
|
+
measureText(slackStr2, NODE_CELL_FONT_SIZE)
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
maxMilestoneNameW = Math.max(
|
|
63
|
+
maxMilestoneNameW,
|
|
64
|
+
measureText(`\u25C6 ${r.activity.name}`, MILESTONE_NAME_FONT_SIZE)
|
|
65
|
+
);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const esStr = fmtSchedule(r.es, isTbd);
|
|
69
|
+
const efStr = fmtSchedule(r.ef, isTbd);
|
|
70
|
+
const lsStr = fmtSchedule(r.ls, isTbd);
|
|
71
|
+
const lfStr = fmtSchedule(r.lf, isTbd);
|
|
72
|
+
const durStr = fmtDur(r.mu, isTbd);
|
|
73
|
+
const slackStr = fmtSlack(r.slack, isTbd);
|
|
74
|
+
maxOuterW = Math.max(
|
|
75
|
+
maxOuterW,
|
|
76
|
+
measureText(esStr, NODE_CELL_FONT_SIZE),
|
|
77
|
+
measureText(efStr, NODE_CELL_FONT_SIZE),
|
|
78
|
+
measureText(lsStr, NODE_CELL_FONT_SIZE),
|
|
79
|
+
measureText(lfStr, NODE_CELL_FONT_SIZE)
|
|
80
|
+
);
|
|
81
|
+
maxMidW = Math.max(
|
|
82
|
+
maxMidW,
|
|
83
|
+
measureText(durStr, NODE_CELL_FONT_SIZE),
|
|
84
|
+
measureText(slackStr, NODE_CELL_FONT_SIZE)
|
|
85
|
+
);
|
|
86
|
+
maxNameW = Math.max(
|
|
87
|
+
maxNameW,
|
|
88
|
+
measureText(r.activity.name, NODE_NAME_FONT_SIZE)
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
for (const rg of resolved.groups) {
|
|
92
|
+
maxNameW = Math.max(
|
|
93
|
+
maxNameW,
|
|
94
|
+
measureText(rg.group.name, NODE_NAME_FONT_SIZE)
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
const outerCell = Math.ceil(maxOuterW) + 2 * CELL_PAD_X;
|
|
98
|
+
const midCell = Math.ceil(maxMidW) + 2 * CELL_PAD_X;
|
|
99
|
+
const outerNeeded = Math.max(MIN_CELL_WIDTH, outerCell);
|
|
100
|
+
const midNeeded = Math.max(MIN_CELL_WIDTH, midCell);
|
|
101
|
+
const cellsTotalW = 2 * outerNeeded + midNeeded;
|
|
102
|
+
const nameTextW = Math.ceil(maxNameW);
|
|
103
|
+
const nameTotalW = nameTextW + NAME_PIN_WIDTH + 2 * NAME_PAD_X;
|
|
104
|
+
const activityWidth = Math.max(
|
|
105
|
+
MIN_NODE_WIDTH,
|
|
106
|
+
Math.min(MAX_NODE_WIDTH, Math.max(cellsTotalW, nameTotalW))
|
|
107
|
+
);
|
|
108
|
+
let midColW = midNeeded;
|
|
109
|
+
let outerColW = (activityWidth - midColW) / 2;
|
|
110
|
+
if (midColW > outerColW) {
|
|
111
|
+
outerColW = activityWidth / 3;
|
|
112
|
+
midColW = activityWidth - 2 * outerColW;
|
|
113
|
+
}
|
|
114
|
+
const mTop = Math.ceil(maxMilestoneTopW) + 2 * CELL_PAD_X;
|
|
115
|
+
const mSlack = maxMilestoneSlackW > 0 ? Math.ceil(maxMilestoneSlackW) + 2 * CELL_PAD_X : 0;
|
|
116
|
+
const mName = Math.ceil(maxMilestoneNameW) + NAME_PIN_WIDTH + 2 * NAME_PAD_X;
|
|
117
|
+
const milestoneWidth = Math.max(
|
|
118
|
+
MIN_MILESTONE_WIDTH,
|
|
119
|
+
Math.min(MAX_MILESTONE_WIDTH, Math.max(mTop, mSlack, mName))
|
|
120
|
+
);
|
|
121
|
+
return { activityWidth, milestoneWidth, outerColW, midColW };
|
|
122
|
+
}
|
|
123
|
+
function nodeDimensions(resolved, id, sizing, overrides) {
|
|
124
|
+
if (overrides?.[id]) {
|
|
125
|
+
return { width: overrides[id].width, height: overrides[id].height };
|
|
126
|
+
}
|
|
127
|
+
const r = resolved.activities.find((a) => a.activity.id === id);
|
|
128
|
+
if (r?.activity.isMilestone) {
|
|
129
|
+
return { width: sizing.milestoneWidth, height: MILESTONE_NODE_HEIGHT };
|
|
130
|
+
}
|
|
131
|
+
return { width: sizing.activityWidth, height: DEFAULT_NODE_HEIGHT };
|
|
132
|
+
}
|
|
133
|
+
function layoutPert(resolved) {
|
|
134
|
+
return relayoutPert(resolved, {});
|
|
135
|
+
}
|
|
136
|
+
function relayoutPert(resolved, overrides, collapsedGroupIds = /* @__PURE__ */ new Set()) {
|
|
137
|
+
if (resolved.activities.length === 0) {
|
|
138
|
+
return { nodes: [], edges: [], groups: [], width: 0, height: 0 };
|
|
139
|
+
}
|
|
140
|
+
const memberToGroup = /* @__PURE__ */ new Map();
|
|
141
|
+
for (const rg of resolved.groups) {
|
|
142
|
+
if (collapsedGroupIds.has(rg.group.id)) {
|
|
143
|
+
for (const aid of rg.group.activityIds) {
|
|
144
|
+
memberToGroup.set(aid, rg.group.id);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const dagreId = (id) => memberToGroup.get(id) ?? id;
|
|
149
|
+
const g = new dagre.graphlib.Graph();
|
|
150
|
+
g.setGraph({
|
|
151
|
+
rankdir: resolved.options.direction,
|
|
152
|
+
nodesep: 50,
|
|
153
|
+
ranksep: 60,
|
|
154
|
+
edgesep: 18,
|
|
155
|
+
marginx: DIAGRAM_PADDING,
|
|
156
|
+
marginy: DIAGRAM_PADDING
|
|
157
|
+
});
|
|
158
|
+
g.setDefaultEdgeLabel(() => ({}));
|
|
159
|
+
const sizing = computeNodeSizing(resolved);
|
|
160
|
+
for (const r of resolved.activities) {
|
|
161
|
+
if (memberToGroup.has(r.activity.id)) continue;
|
|
162
|
+
const { width, height } = nodeDimensions(
|
|
163
|
+
resolved,
|
|
164
|
+
r.activity.id,
|
|
165
|
+
sizing,
|
|
166
|
+
overrides
|
|
167
|
+
);
|
|
168
|
+
g.setNode(r.activity.id, { width, height });
|
|
169
|
+
}
|
|
170
|
+
for (const rg of resolved.groups) {
|
|
171
|
+
if (collapsedGroupIds.has(rg.group.id)) {
|
|
172
|
+
g.setNode(rg.group.id, {
|
|
173
|
+
width: sizing.activityWidth,
|
|
174
|
+
height: COLLAPSED_GROUP_HEIGHT
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
const seenEdges = /* @__PURE__ */ new Set();
|
|
179
|
+
for (const e of resolved.edges) {
|
|
180
|
+
const src = dagreId(e.source);
|
|
181
|
+
const tgt = dagreId(e.target);
|
|
182
|
+
if (src === tgt) continue;
|
|
183
|
+
const k = `${src}|${tgt}`;
|
|
184
|
+
if (seenEdges.has(k)) continue;
|
|
185
|
+
seenEdges.add(k);
|
|
186
|
+
g.setEdge(src, tgt, {});
|
|
187
|
+
}
|
|
188
|
+
dagre.layout(g);
|
|
189
|
+
const swimApplied = applySwimLanes(
|
|
190
|
+
g,
|
|
191
|
+
resolved,
|
|
192
|
+
memberToGroup,
|
|
193
|
+
collapsedGroupIds
|
|
194
|
+
);
|
|
195
|
+
if (!swimApplied) {
|
|
196
|
+
centerByCriticality(g, resolved, memberToGroup, collapsedGroupIds);
|
|
197
|
+
reduceCrossings(g, resolved.options.direction);
|
|
198
|
+
}
|
|
199
|
+
const nodes = resolved.activities.filter((r) => !memberToGroup.has(r.activity.id)).map((r) => {
|
|
200
|
+
const pos = g.node(r.activity.id);
|
|
201
|
+
return {
|
|
202
|
+
id: r.activity.id,
|
|
203
|
+
x: pos.x,
|
|
204
|
+
y: pos.y,
|
|
205
|
+
width: pos.width,
|
|
206
|
+
height: pos.height
|
|
207
|
+
};
|
|
208
|
+
});
|
|
209
|
+
const edges = Array.from(seenEdges).map((k) => {
|
|
210
|
+
const [source, target] = k.split("|");
|
|
211
|
+
const data = g.edge(source, target);
|
|
212
|
+
return { source, target, points: data?.points ?? [] };
|
|
213
|
+
});
|
|
214
|
+
const nodeMap = /* @__PURE__ */ new Map();
|
|
215
|
+
for (const n of nodes) nodeMap.set(n.id, n);
|
|
216
|
+
for (const rg of resolved.groups) {
|
|
217
|
+
if (collapsedGroupIds.has(rg.group.id)) {
|
|
218
|
+
const vn = g.node(rg.group.id);
|
|
219
|
+
nodeMap.set(rg.group.id, {
|
|
220
|
+
x: vn.x,
|
|
221
|
+
y: vn.y,
|
|
222
|
+
width: vn.width,
|
|
223
|
+
height: vn.height
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
const groups = resolved.groups.map((rg) => {
|
|
228
|
+
const classification = rg.group.classification ?? "cluster";
|
|
229
|
+
if (collapsedGroupIds.has(rg.group.id)) {
|
|
230
|
+
const vn = nodeMap.get(rg.group.id);
|
|
231
|
+
if (!vn) {
|
|
232
|
+
return {
|
|
233
|
+
id: rg.group.id,
|
|
234
|
+
x: 0,
|
|
235
|
+
y: 0,
|
|
236
|
+
width: 0,
|
|
237
|
+
height: 0,
|
|
238
|
+
classification,
|
|
239
|
+
collapsed: true
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
return {
|
|
243
|
+
id: rg.group.id,
|
|
244
|
+
x: vn.x - vn.width / 2,
|
|
245
|
+
y: vn.y - vn.height / 2,
|
|
246
|
+
width: vn.width,
|
|
247
|
+
height: vn.height,
|
|
248
|
+
classification,
|
|
249
|
+
collapsed: true
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
const members = rg.group.activityIds.map((id) => nodeMap.get(id)).filter(
|
|
253
|
+
(n) => n !== void 0
|
|
254
|
+
);
|
|
255
|
+
if (members.length === 0) {
|
|
256
|
+
return {
|
|
257
|
+
id: rg.group.id,
|
|
258
|
+
x: 0,
|
|
259
|
+
y: 0,
|
|
260
|
+
width: 0,
|
|
261
|
+
height: 0,
|
|
262
|
+
classification
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
let minX = Infinity;
|
|
266
|
+
let minY = Infinity;
|
|
267
|
+
let maxX = -Infinity;
|
|
268
|
+
let maxY = -Infinity;
|
|
269
|
+
for (const m of members) {
|
|
270
|
+
const left = m.x - m.width / 2;
|
|
271
|
+
const right = m.x + m.width / 2;
|
|
272
|
+
const top = m.y - m.height / 2;
|
|
273
|
+
const bottom = m.y + m.height / 2;
|
|
274
|
+
if (left < minX) minX = left;
|
|
275
|
+
if (right > maxX) maxX = right;
|
|
276
|
+
if (top < minY) minY = top;
|
|
277
|
+
if (bottom > maxY) maxY = bottom;
|
|
278
|
+
}
|
|
279
|
+
return {
|
|
280
|
+
id: rg.group.id,
|
|
281
|
+
x: minX - GROUP_PADDING,
|
|
282
|
+
y: minY - GROUP_TOP_PADDING,
|
|
283
|
+
width: maxX - minX + GROUP_PADDING * 2,
|
|
284
|
+
height: maxY - minY + GROUP_TOP_PADDING + GROUP_PADDING,
|
|
285
|
+
classification
|
|
286
|
+
};
|
|
287
|
+
});
|
|
288
|
+
let totalW = 0;
|
|
289
|
+
let totalH = 0;
|
|
290
|
+
for (const n of nodes) {
|
|
291
|
+
const right = n.x + n.width / 2;
|
|
292
|
+
const bottom = n.y + n.height / 2;
|
|
293
|
+
if (right > totalW) totalW = right;
|
|
294
|
+
if (bottom > totalH) totalH = bottom;
|
|
295
|
+
}
|
|
296
|
+
for (const grp of groups) {
|
|
297
|
+
if (grp.x + grp.width > totalW) totalW = grp.x + grp.width;
|
|
298
|
+
if (grp.y + grp.height > totalH) totalH = grp.y + grp.height;
|
|
299
|
+
}
|
|
300
|
+
return {
|
|
301
|
+
nodes,
|
|
302
|
+
edges,
|
|
303
|
+
groups,
|
|
304
|
+
width: totalW + DIAGRAM_PADDING,
|
|
305
|
+
height: totalH + DIAGRAM_PADDING
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
function applySwimLanes(g, resolved, _memberToGroup, collapsedGroupIds) {
|
|
309
|
+
const expanded = resolved.groups.filter(
|
|
310
|
+
(rg) => !collapsedGroupIds.has(rg.group.id)
|
|
311
|
+
);
|
|
312
|
+
if (expanded.length === 0) return false;
|
|
313
|
+
const isLR = resolved.options.direction !== "TB";
|
|
314
|
+
const rankAxis = isLR ? "x" : "y";
|
|
315
|
+
const slotAxis = isLR ? "y" : "x";
|
|
316
|
+
let spineIdx = 1;
|
|
317
|
+
let spineMembers = 0;
|
|
318
|
+
expanded.forEach((rg, i) => {
|
|
319
|
+
if (rg.group.activityIds.length > spineMembers) {
|
|
320
|
+
spineMembers = rg.group.activityIds.length;
|
|
321
|
+
spineIdx = i + 1;
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
const laneOf = /* @__PURE__ */ new Map();
|
|
325
|
+
expanded.forEach((rg, i) => {
|
|
326
|
+
for (const aid of rg.group.activityIds) laneOf.set(aid, i + 1);
|
|
327
|
+
});
|
|
328
|
+
for (const id of g.nodes()) {
|
|
329
|
+
if (!laneOf.has(id)) laneOf.set(id, spineIdx);
|
|
330
|
+
}
|
|
331
|
+
const spineMemberSet = new Set(
|
|
332
|
+
expanded[spineIdx - 1]?.group.activityIds ?? []
|
|
333
|
+
);
|
|
334
|
+
const numLanes = expanded.length + 1;
|
|
335
|
+
const rankBuckets = /* @__PURE__ */ new Map();
|
|
336
|
+
for (const id of g.nodes()) {
|
|
337
|
+
const node = g.node(id);
|
|
338
|
+
if (!node) continue;
|
|
339
|
+
const rankKey = Math.round(node[rankAxis]);
|
|
340
|
+
const laneIdx = laneOf.get(id) ?? spineIdx;
|
|
341
|
+
let byLane = rankBuckets.get(rankKey);
|
|
342
|
+
if (!byLane) {
|
|
343
|
+
byLane = /* @__PURE__ */ new Map();
|
|
344
|
+
rankBuckets.set(rankKey, byLane);
|
|
345
|
+
}
|
|
346
|
+
if (!byLane.has(laneIdx)) byLane.set(laneIdx, []);
|
|
347
|
+
byLane.get(laneIdx).push(id);
|
|
348
|
+
}
|
|
349
|
+
const laneSlots = new Array(numLanes).fill(0);
|
|
350
|
+
for (const byLane of rankBuckets.values()) {
|
|
351
|
+
for (const [li, members] of byLane) {
|
|
352
|
+
if (members.length > laneSlots[li]) laneSlots[li] = members.length;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
const slotSize = isLR ? DEFAULT_NODE_HEIGHT : g.node(g.nodes()[0])?.width ?? DEFAULT_NODE_HEIGHT;
|
|
356
|
+
const laneSize = new Array(numLanes).fill(0);
|
|
357
|
+
for (let i = 1; i < numLanes; i++) {
|
|
358
|
+
const slots = laneSlots[i];
|
|
359
|
+
if (slots === 0) {
|
|
360
|
+
laneSize[i] = 0;
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
const slotsExtent = slots * slotSize + Math.max(0, slots - 1) * SWIMLANE_SLOT_SEP;
|
|
364
|
+
laneSize[i] = GROUP_TOP_PADDING + slotsExtent + GROUP_PADDING;
|
|
365
|
+
}
|
|
366
|
+
const laneOrder = [
|
|
367
|
+
spineIdx,
|
|
368
|
+
...Array.from({ length: expanded.length }, (_, i) => i + 1).filter(
|
|
369
|
+
(i) => i !== spineIdx
|
|
370
|
+
)
|
|
371
|
+
];
|
|
372
|
+
const laneStart = new Array(numLanes).fill(0);
|
|
373
|
+
let cursor = DIAGRAM_PADDING;
|
|
374
|
+
for (const li of laneOrder) {
|
|
375
|
+
laneStart[li] = cursor;
|
|
376
|
+
if (laneSize[li] > 0) cursor += laneSize[li] + SWIMLANE_GAP;
|
|
377
|
+
}
|
|
378
|
+
const critOf = (id) => {
|
|
379
|
+
const r = resolved.activities.find((a) => a.activity.id === id);
|
|
380
|
+
if (r) {
|
|
381
|
+
return r.criticality !== null ? r.criticality : r.isCriticalPath ? 1 : 0;
|
|
382
|
+
}
|
|
383
|
+
const rg = resolved.groups.find((x) => x.group.id === id);
|
|
384
|
+
if (!rg) return 0;
|
|
385
|
+
let m = 0;
|
|
386
|
+
for (const aid of rg.group.activityIds) {
|
|
387
|
+
const ar = resolved.activities.find((a) => a.activity.id === aid);
|
|
388
|
+
if (!ar) continue;
|
|
389
|
+
const c = ar.criticality !== null ? ar.criticality : ar.isCriticalPath ? 1 : 0;
|
|
390
|
+
if (c > m) m = c;
|
|
391
|
+
}
|
|
392
|
+
return m;
|
|
393
|
+
};
|
|
394
|
+
const oldSlot = /* @__PURE__ */ new Map();
|
|
395
|
+
for (const id of g.nodes()) {
|
|
396
|
+
oldSlot.set(id, g.node(id)[slotAxis]);
|
|
397
|
+
}
|
|
398
|
+
for (const byLane of rankBuckets.values()) {
|
|
399
|
+
for (const [li, members] of byLane) {
|
|
400
|
+
const slotStripStart = laneStart[li] + GROUP_TOP_PADDING;
|
|
401
|
+
const sorted = [...members].sort((a, b) => {
|
|
402
|
+
const aSpine = spineMemberSet.has(a) ? 0 : 1;
|
|
403
|
+
const bSpine = spineMemberSet.has(b) ? 0 : 1;
|
|
404
|
+
if (aSpine !== bSpine) return aSpine - bSpine;
|
|
405
|
+
const ca = critOf(a);
|
|
406
|
+
const cb = critOf(b);
|
|
407
|
+
if (cb !== ca) return cb - ca;
|
|
408
|
+
return (oldSlot.get(a) ?? 0) - (oldSlot.get(b) ?? 0);
|
|
409
|
+
});
|
|
410
|
+
sorted.forEach((id, idx) => {
|
|
411
|
+
const node = g.node(id);
|
|
412
|
+
node[slotAxis] = slotStripStart + slotSize / 2 + idx * (slotSize + SWIMLANE_SLOT_SEP);
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
const dir = resolved.options.direction;
|
|
417
|
+
for (const e of g.edges()) {
|
|
418
|
+
const src = g.node(e.v);
|
|
419
|
+
const tgt = g.node(e.w);
|
|
420
|
+
if (!src || !tgt) continue;
|
|
421
|
+
const data = g.edge(e);
|
|
422
|
+
if (!data) continue;
|
|
423
|
+
data.points = smoothEdge(src, tgt, dir);
|
|
424
|
+
}
|
|
425
|
+
return true;
|
|
426
|
+
}
|
|
427
|
+
function centerByCriticality(g, resolved, memberToGroup, collapsedGroupIds) {
|
|
428
|
+
const critById = /* @__PURE__ */ new Map();
|
|
429
|
+
for (const r of resolved.activities) {
|
|
430
|
+
if (memberToGroup.has(r.activity.id)) continue;
|
|
431
|
+
const c = r.criticality !== null ? r.criticality : r.isCriticalPath ? 1 : 0;
|
|
432
|
+
critById.set(r.activity.id, c);
|
|
433
|
+
}
|
|
434
|
+
for (const rg of resolved.groups) {
|
|
435
|
+
if (!collapsedGroupIds.has(rg.group.id)) continue;
|
|
436
|
+
let maxC = 0;
|
|
437
|
+
for (const aid of rg.group.activityIds) {
|
|
438
|
+
const r = resolved.activities.find((x) => x.activity.id === aid);
|
|
439
|
+
if (!r) continue;
|
|
440
|
+
const c = r.criticality !== null ? r.criticality : r.isCriticalPath ? 1 : 0;
|
|
441
|
+
if (c > maxC) maxC = c;
|
|
442
|
+
}
|
|
443
|
+
critById.set(rg.group.id, maxC);
|
|
444
|
+
}
|
|
445
|
+
const rankAxis = resolved.options.direction === "TB" ? "y" : "x";
|
|
446
|
+
const slotAxis = resolved.options.direction === "TB" ? "x" : "y";
|
|
447
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
448
|
+
for (const id of g.nodes()) {
|
|
449
|
+
const node = g.node(id);
|
|
450
|
+
if (!node) continue;
|
|
451
|
+
const key = Math.round(node[rankAxis]);
|
|
452
|
+
if (!buckets.has(key)) buckets.set(key, []);
|
|
453
|
+
buckets.get(key).push(id);
|
|
454
|
+
}
|
|
455
|
+
const shifts = /* @__PURE__ */ new Map();
|
|
456
|
+
for (const ids of buckets.values()) {
|
|
457
|
+
if (ids.length < 2) continue;
|
|
458
|
+
const slots = ids.map((id) => g.node(id)[slotAxis]).sort((a, b) => a - b);
|
|
459
|
+
const currentSlot = /* @__PURE__ */ new Map();
|
|
460
|
+
for (const id of ids) currentSlot.set(id, g.node(id)[slotAxis]);
|
|
461
|
+
const sortedDesc = [...ids].sort((a, b) => {
|
|
462
|
+
const ca = critById.get(a) ?? 0;
|
|
463
|
+
const cb = critById.get(b) ?? 0;
|
|
464
|
+
if (cb !== ca) return cb - ca;
|
|
465
|
+
return (currentSlot.get(a) ?? 0) - (currentSlot.get(b) ?? 0);
|
|
466
|
+
});
|
|
467
|
+
const top = [];
|
|
468
|
+
const bottom = [];
|
|
469
|
+
let middle = null;
|
|
470
|
+
sortedDesc.forEach((id, i) => {
|
|
471
|
+
if (i === 0) middle = id;
|
|
472
|
+
else if (i % 2 === 1) top.unshift(id);
|
|
473
|
+
else bottom.push(id);
|
|
474
|
+
});
|
|
475
|
+
const newOrder = middle ? [...top, middle, ...bottom] : [...top, ...bottom];
|
|
476
|
+
newOrder.forEach((id, i) => {
|
|
477
|
+
const node = g.node(id);
|
|
478
|
+
const oldVal = node[slotAxis];
|
|
479
|
+
const newVal = slots[i];
|
|
480
|
+
shifts.set(id, newVal - oldVal);
|
|
481
|
+
node[slotAxis] = newVal;
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
if (shifts.size > 0) {
|
|
485
|
+
const dir = resolved.options.direction;
|
|
486
|
+
for (const e of g.edges()) {
|
|
487
|
+
if (!shifts.has(e.v) && !shifts.has(e.w)) continue;
|
|
488
|
+
const src = g.node(e.v);
|
|
489
|
+
const tgt = g.node(e.w);
|
|
490
|
+
if (!src || !tgt) continue;
|
|
491
|
+
const data = g.edge(e);
|
|
492
|
+
if (!data) continue;
|
|
493
|
+
data.points = smoothEdge(src, tgt, dir);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
function smoothEdge(src, tgt, direction) {
|
|
498
|
+
if (direction === "TB") {
|
|
499
|
+
const sy = src.y + src.height / 2;
|
|
500
|
+
const ty = tgt.y - tgt.height / 2;
|
|
501
|
+
const span2 = ty - sy;
|
|
502
|
+
const pad2 = Math.max(20, Math.abs(span2) * 0.3);
|
|
503
|
+
return [
|
|
504
|
+
{ x: src.x, y: sy },
|
|
505
|
+
{ x: src.x, y: sy + Math.sign(span2 || 1) * pad2 },
|
|
506
|
+
{ x: tgt.x, y: ty - Math.sign(span2 || 1) * pad2 },
|
|
507
|
+
{ x: tgt.x, y: ty }
|
|
508
|
+
];
|
|
509
|
+
}
|
|
510
|
+
const sx = src.x + src.width / 2;
|
|
511
|
+
const tx = tgt.x - tgt.width / 2;
|
|
512
|
+
const span = tx - sx;
|
|
513
|
+
const pad = Math.max(20, Math.abs(span) * 0.3);
|
|
514
|
+
return [
|
|
515
|
+
{ x: sx, y: src.y },
|
|
516
|
+
{ x: sx + Math.sign(span || 1) * pad, y: src.y },
|
|
517
|
+
{ x: tx - Math.sign(span || 1) * pad, y: tgt.y },
|
|
518
|
+
{ x: tx, y: tgt.y }
|
|
519
|
+
];
|
|
520
|
+
}
|
|
521
|
+
function reduceCrossings(g, direction) {
|
|
522
|
+
const isLR = direction !== "TB";
|
|
523
|
+
const rankAxis = isLR ? "x" : "y";
|
|
524
|
+
const slotAxis = isLR ? "y" : "x";
|
|
525
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
526
|
+
for (const id of g.nodes()) {
|
|
527
|
+
const node = g.node(id);
|
|
528
|
+
if (!node) continue;
|
|
529
|
+
const key = Math.round(node[rankAxis]);
|
|
530
|
+
if (!buckets.has(key)) buckets.set(key, []);
|
|
531
|
+
buckets.get(key).push(id);
|
|
532
|
+
}
|
|
533
|
+
const edges = g.edges().map((e) => ({ v: e.v, w: e.w }));
|
|
534
|
+
const countCrossings = () => {
|
|
535
|
+
let total = 0;
|
|
536
|
+
for (let i = 0; i < edges.length; i++) {
|
|
537
|
+
const a = edges[i];
|
|
538
|
+
const a1 = g.node(a.v);
|
|
539
|
+
const a2 = g.node(a.w);
|
|
540
|
+
if (!a1 || !a2) continue;
|
|
541
|
+
for (let j = i + 1; j < edges.length; j++) {
|
|
542
|
+
const b = edges[j];
|
|
543
|
+
if (a.v === b.v || a.v === b.w || a.w === b.v || a.w === b.w) continue;
|
|
544
|
+
const b1 = g.node(b.v);
|
|
545
|
+
const b2 = g.node(b.w);
|
|
546
|
+
if (!b1 || !b2) continue;
|
|
547
|
+
if (segmentsCross(a1, a2, b1, b2)) total++;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
return total;
|
|
551
|
+
};
|
|
552
|
+
const MAX_ITER = 8;
|
|
553
|
+
let baseline = countCrossings();
|
|
554
|
+
if (baseline === 0) return;
|
|
555
|
+
for (let iter = 0; iter < MAX_ITER; iter++) {
|
|
556
|
+
let improved = false;
|
|
557
|
+
for (const ids of buckets.values()) {
|
|
558
|
+
if (ids.length < 2) continue;
|
|
559
|
+
const sorted = ids.slice().sort(
|
|
560
|
+
(a, b) => g.node(a)[slotAxis] - g.node(b)[slotAxis]
|
|
561
|
+
);
|
|
562
|
+
for (let i = 0; i < sorted.length - 1; i++) {
|
|
563
|
+
const a = sorted[i];
|
|
564
|
+
const b = sorted[i + 1];
|
|
565
|
+
const an = g.node(a);
|
|
566
|
+
const bn = g.node(b);
|
|
567
|
+
const av = an[slotAxis];
|
|
568
|
+
const bv = bn[slotAxis];
|
|
569
|
+
an[slotAxis] = bv;
|
|
570
|
+
bn[slotAxis] = av;
|
|
571
|
+
const after = countCrossings();
|
|
572
|
+
if (after < baseline) {
|
|
573
|
+
baseline = after;
|
|
574
|
+
improved = true;
|
|
575
|
+
} else {
|
|
576
|
+
an[slotAxis] = av;
|
|
577
|
+
bn[slotAxis] = bv;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
if (!improved || baseline === 0) break;
|
|
582
|
+
}
|
|
583
|
+
for (const e of g.edges()) {
|
|
584
|
+
const src = g.node(e.v);
|
|
585
|
+
const tgt = g.node(e.w);
|
|
586
|
+
if (!src || !tgt) continue;
|
|
587
|
+
const data = g.edge(e);
|
|
588
|
+
if (!data) continue;
|
|
589
|
+
data.points = smoothEdge(src, tgt, direction);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
function segmentsCross(a1, a2, b1, b2) {
|
|
593
|
+
const ccw = (p, q, r) => (q.x - p.x) * (r.y - p.y) - (q.y - p.y) * (r.x - p.x);
|
|
594
|
+
const d1 = ccw(b1, b2, a1);
|
|
595
|
+
const d2 = ccw(b1, b2, a2);
|
|
596
|
+
const d3 = ccw(a1, a2, b1);
|
|
597
|
+
const d4 = ccw(a1, a2, b2);
|
|
598
|
+
return (d1 > 0 && d2 < 0 || d1 < 0 && d2 > 0) && (d3 > 0 && d4 < 0 || d3 < 0 && d4 > 0);
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
export {
|
|
602
|
+
computeNodeSizing,
|
|
603
|
+
layoutPert,
|
|
604
|
+
relayoutPert
|
|
605
|
+
};
|
|
606
|
+
//# sourceMappingURL=chunk-4OHACBGX.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// src/utils/note-box/constants.ts
|
|
2
|
+
var NOTE_MAX_W = 200;
|
|
3
|
+
var NOTE_FOLD = 10;
|
|
4
|
+
var NOTE_PAD_H = 8;
|
|
5
|
+
var NOTE_PAD_V = 6;
|
|
6
|
+
var NOTE_FONT_SIZE = 10;
|
|
7
|
+
var NOTE_LINE_H = 14;
|
|
8
|
+
var NOTE_GAP = 22;
|
|
9
|
+
var NOTE_BULLET_INDENT = 10;
|
|
10
|
+
|
|
11
|
+
export {
|
|
12
|
+
NOTE_MAX_W,
|
|
13
|
+
NOTE_FOLD,
|
|
14
|
+
NOTE_PAD_H,
|
|
15
|
+
NOTE_PAD_V,
|
|
16
|
+
NOTE_FONT_SIZE,
|
|
17
|
+
NOTE_LINE_H,
|
|
18
|
+
NOTE_GAP,
|
|
19
|
+
NOTE_BULLET_INDENT
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=chunk-5DH3KYFH.js.map
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import {
|
|
2
|
+
extractColor,
|
|
3
|
+
measureIndent
|
|
4
|
+
} from "./chunk-Y3J7VR52.js";
|
|
5
|
+
import {
|
|
6
|
+
makeDgmoError
|
|
7
|
+
} from "./chunk-CXK4DZH3.js";
|
|
8
|
+
|
|
9
|
+
// src/utils/notes/parse.ts
|
|
10
|
+
function parseNoteHeader(rest) {
|
|
11
|
+
const t = rest.trim();
|
|
12
|
+
const quoted = t.match(/^"([^"]+)"\s*(.*)$/);
|
|
13
|
+
if (quoted) {
|
|
14
|
+
return { ref: quoted[1].trim(), inlineBody: quoted[2].trim() };
|
|
15
|
+
}
|
|
16
|
+
const m = t.match(/^(\S+)\s*(.*)$/);
|
|
17
|
+
if (m) {
|
|
18
|
+
return { ref: m[1], inlineBody: m[2].trim() };
|
|
19
|
+
}
|
|
20
|
+
return { ref: t, inlineBody: "" };
|
|
21
|
+
}
|
|
22
|
+
function collectNoteBody(lines, noteIndex, noteIndent, inlineBody) {
|
|
23
|
+
const parts = [];
|
|
24
|
+
if (inlineBody) parts.push(inlineBody);
|
|
25
|
+
let lastIndex = noteIndex;
|
|
26
|
+
let endLineNumber = noteIndex + 1;
|
|
27
|
+
for (let j = noteIndex + 1; j < lines.length; j++) {
|
|
28
|
+
const raw = lines[j];
|
|
29
|
+
const trimmed = raw.trim();
|
|
30
|
+
if (!trimmed) break;
|
|
31
|
+
if (measureIndent(raw) <= noteIndent) break;
|
|
32
|
+
parts.push(trimmed);
|
|
33
|
+
lastIndex = j;
|
|
34
|
+
endLineNumber = j + 1;
|
|
35
|
+
}
|
|
36
|
+
return { body: parts.join("\n"), endLineNumber, lastIndex };
|
|
37
|
+
}
|
|
38
|
+
function tryCollectNote(lines, index, indent, palette, diagnostics) {
|
|
39
|
+
const trimmed = lines[index].trim();
|
|
40
|
+
const m = trimmed.match(/^note\s+(.+)$/i);
|
|
41
|
+
if (!m || /^note\s+->/i.test(trimmed)) return null;
|
|
42
|
+
const lineNumber = index + 1;
|
|
43
|
+
const { label: headerNoColor, color } = extractColor(
|
|
44
|
+
m[1],
|
|
45
|
+
palette,
|
|
46
|
+
diagnostics,
|
|
47
|
+
lineNumber
|
|
48
|
+
);
|
|
49
|
+
const { ref, inlineBody } = parseNoteHeader(headerNoColor);
|
|
50
|
+
const collected = collectNoteBody(lines, index, indent, inlineBody);
|
|
51
|
+
if (!collected.body.trim()) {
|
|
52
|
+
diagnostics.push(
|
|
53
|
+
makeDgmoError(
|
|
54
|
+
lineNumber,
|
|
55
|
+
`Note on "${ref}" has no text \u2014 ignored.`,
|
|
56
|
+
"warning"
|
|
57
|
+
)
|
|
58
|
+
);
|
|
59
|
+
return { lastIndex: collected.lastIndex };
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
note: {
|
|
63
|
+
ref,
|
|
64
|
+
body: collected.body,
|
|
65
|
+
...color && { color },
|
|
66
|
+
lineNumber,
|
|
67
|
+
endLineNumber: collected.endLineNumber
|
|
68
|
+
},
|
|
69
|
+
lastIndex: collected.lastIndex
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export {
|
|
74
|
+
tryCollectNote
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=chunk-5MLYVTYM.js.map
|