@crazyhappyone/auto-graph 0.0.3 → 0.0.4
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/cli/index.cjs +730 -15
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +730 -15
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +730 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +730 -15
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1200,6 +1200,7 @@ function normalizeDiagramDsl(dslValue, options = {}) {
|
|
|
1200
1200
|
const measurer = options.textMeasurer ?? createDefaultTextMeasurer();
|
|
1201
1201
|
const routeKind = dsl.routing?.kind ?? "orthogonal";
|
|
1202
1202
|
const portShifting = normalizePortShifting(dsl.routing?.portShifting);
|
|
1203
|
+
const primaryReadingDirection = dsl.layout?.primaryReadingDirection;
|
|
1203
1204
|
const diagram = {
|
|
1204
1205
|
id: options.id ?? dsl.id ?? "diagram",
|
|
1205
1206
|
...dsl.title === void 0 ? {} : { title: dsl.title },
|
|
@@ -1213,6 +1214,7 @@ function normalizeDiagramDsl(dslValue, options = {}) {
|
|
|
1213
1214
|
...dsl.frame === void 0 ? {} : { frame: normalizeFrame(dsl.frame) },
|
|
1214
1215
|
metadata: {
|
|
1215
1216
|
routeKind,
|
|
1217
|
+
...primaryReadingDirection === void 0 ? {} : { primaryReadingDirection },
|
|
1216
1218
|
...portShifting === void 0 ? {} : { portShifting }
|
|
1217
1219
|
}
|
|
1218
1220
|
};
|
|
@@ -1383,14 +1385,17 @@ function formatCompartmentEntry(value) {
|
|
|
1383
1385
|
return `${entry[0]}: ${entry[1]}`;
|
|
1384
1386
|
}
|
|
1385
1387
|
function normalizeSwimlanes(dsl) {
|
|
1386
|
-
return Object.keys(dsl.swimlanes ?? {}).
|
|
1388
|
+
return Object.keys(dsl.swimlanes ?? {}).map((id) => {
|
|
1387
1389
|
const swimlane = dsl.swimlanes?.[id];
|
|
1388
1390
|
const label = toLabel(swimlane?.label);
|
|
1389
1391
|
return {
|
|
1390
1392
|
id,
|
|
1391
1393
|
...label === void 0 ? {} : { label },
|
|
1392
1394
|
orientation: swimlane?.orientation ?? "vertical",
|
|
1393
|
-
|
|
1395
|
+
layout: swimlane?.layout ?? "overlay",
|
|
1396
|
+
...swimlane?.headerHeight === void 0 ? {} : { headerHeight: swimlane.headerHeight },
|
|
1397
|
+
...swimlane?.padding === void 0 ? {} : { padding: swimlane.padding },
|
|
1398
|
+
lanes: Object.keys(swimlane?.lanes ?? {}).map((laneId) => {
|
|
1394
1399
|
const lane = swimlane?.lanes[laneId];
|
|
1395
1400
|
const laneLabel = toLabel(lane?.label);
|
|
1396
1401
|
return {
|
|
@@ -1657,6 +1662,10 @@ var routeKindSchema = zod.z.enum(["orthogonal", "straight"]);
|
|
|
1657
1662
|
var outputFormatSchema = zod.z.enum(["svg", "excalidraw"]);
|
|
1658
1663
|
var edgeStrokeStyleSchema = zod.z.enum(["solid", "dashed"]);
|
|
1659
1664
|
var edgeArrowheadSchema = zod.z.enum(["triangle", "hollowTriangle"]);
|
|
1665
|
+
var primaryReadingDirectionSchema = zod.z.enum([
|
|
1666
|
+
"top_to_bottom",
|
|
1667
|
+
"top-to-bottom"
|
|
1668
|
+
]);
|
|
1660
1669
|
var nodeShapeSchema = zod.z.enum([
|
|
1661
1670
|
"rectangle",
|
|
1662
1671
|
"rounded-rectangle",
|
|
@@ -1667,6 +1676,7 @@ var nodeShapeSchema = zod.z.enum([
|
|
|
1667
1676
|
"cylinder"
|
|
1668
1677
|
]);
|
|
1669
1678
|
var finiteNumberSchema = zod.z.number().finite();
|
|
1679
|
+
var nonNegativeNumberSchema = finiteNumberSchema.min(0);
|
|
1670
1680
|
var pointSchema = zod.z.object({
|
|
1671
1681
|
x: finiteNumberSchema,
|
|
1672
1682
|
y: finiteNumberSchema
|
|
@@ -1753,6 +1763,9 @@ var groupSchema = zod.z.object({
|
|
|
1753
1763
|
var swimlaneSchema = zod.z.object({
|
|
1754
1764
|
label: labelSchema.optional(),
|
|
1755
1765
|
orientation: zod.z.enum(["vertical", "horizontal"]).optional(),
|
|
1766
|
+
layout: zod.z.enum(["overlay", "contract"]).optional(),
|
|
1767
|
+
headerHeight: nonNegativeNumberSchema.optional(),
|
|
1768
|
+
padding: nonNegativeNumberSchema.optional(),
|
|
1756
1769
|
lanes: zod.z.record(
|
|
1757
1770
|
zod.z.string(),
|
|
1758
1771
|
zod.z.object({
|
|
@@ -1818,7 +1831,8 @@ var diagramDslSchema = zod.z.object({
|
|
|
1818
1831
|
title: zod.z.string().optional(),
|
|
1819
1832
|
direction: directionSchema.optional(),
|
|
1820
1833
|
layout: zod.z.object({
|
|
1821
|
-
direction: directionSchema.optional()
|
|
1834
|
+
direction: directionSchema.optional(),
|
|
1835
|
+
primaryReadingDirection: primaryReadingDirectionSchema.optional()
|
|
1822
1836
|
}).optional(),
|
|
1823
1837
|
routing: zod.z.object({
|
|
1824
1838
|
kind: routeKindSchema.optional(),
|
|
@@ -2348,15 +2362,30 @@ function renderSwimlane(swimlane) {
|
|
|
2348
2362
|
lines.push(
|
|
2349
2363
|
` <rect class="swimlane-lane" data-lane="${escapeAttribute(`${swimlane.id}.${lane.id}`)}" x="${formatNumber(lane.box.x)}" y="${formatNumber(lane.box.y)}" width="${formatNumber(lane.box.width)}" height="${formatNumber(lane.box.height)}" fill="none" stroke="${STROKE}"/>`
|
|
2350
2364
|
);
|
|
2351
|
-
if (lane.
|
|
2365
|
+
if (lane.headerBox !== void 0) {
|
|
2366
|
+
lines.push(
|
|
2367
|
+
` <rect class="swimlane-header" data-lane-header="${escapeAttribute(`${swimlane.id}.${lane.id}`)}" x="${formatNumber(lane.headerBox.x)}" y="${formatNumber(lane.headerBox.y)}" width="${formatNumber(lane.headerBox.width)}" height="${formatNumber(lane.headerBox.height)}" fill="#f3f4f6" stroke="${STROKE}"/>`
|
|
2368
|
+
);
|
|
2369
|
+
}
|
|
2370
|
+
if (lane.contentBox !== void 0) {
|
|
2352
2371
|
lines.push(
|
|
2353
|
-
` <
|
|
2372
|
+
` <rect class="swimlane-content" data-lane-content="${escapeAttribute(`${swimlane.id}.${lane.id}`)}" x="${formatNumber(lane.contentBox.x)}" y="${formatNumber(lane.contentBox.y)}" width="${formatNumber(lane.contentBox.width)}" height="${formatNumber(lane.contentBox.height)}" fill="none" stroke="none"/>`
|
|
2354
2373
|
);
|
|
2355
2374
|
}
|
|
2375
|
+
if (lane.label?.text !== void 0) {
|
|
2376
|
+
const labelBox = lane.headerBox ?? lane.box;
|
|
2377
|
+
lines.push(renderSwimlaneLabel(swimlane, lane.label.text, labelBox));
|
|
2378
|
+
}
|
|
2356
2379
|
}
|
|
2357
2380
|
lines.push(" </g>");
|
|
2358
2381
|
return lines;
|
|
2359
2382
|
}
|
|
2383
|
+
function renderSwimlaneLabel(swimlane, text, labelBox) {
|
|
2384
|
+
const x = labelBox.x + labelBox.width / 2;
|
|
2385
|
+
const y = labelBox.y + labelBox.height / 2;
|
|
2386
|
+
const transform = swimlane.orientation === "horizontal" ? ` transform="rotate(-90 ${formatNumber(x)} ${formatNumber(y)})"` : "";
|
|
2387
|
+
return ` <text class="swimlane-label" x="${formatNumber(x)}" y="${formatNumber(y)}" text-anchor="middle" dominant-baseline="middle"${transform} font-family="${FONT_FAMILY}" font-size="12" fill="#111827">${escapeXml(text)}</text>`;
|
|
2388
|
+
}
|
|
2360
2389
|
function renderPorts(node) {
|
|
2361
2390
|
return (node.ports ?? []).flatMap((port) => [
|
|
2362
2391
|
` <rect class="port" data-kind="${escapeAttribute(port.kind)}" data-port="${escapeAttribute(`${node.id}.${port.id}`)}" x="${formatNumber(port.box.x)}" y="${formatNumber(port.box.y)}" width="${formatNumber(port.box.width)}" height="${formatNumber(port.box.height)}" fill="${escapeAttribute(port.style?.fill ?? "#d9ead3")}" stroke="${escapeAttribute(port.style?.stroke ?? STROKE)}"/>`,
|
|
@@ -2934,6 +2963,19 @@ function solveDiagram(diagram, options = {}) {
|
|
|
2934
2963
|
constraints
|
|
2935
2964
|
});
|
|
2936
2965
|
diagnostics.push(...constrained.diagnostics);
|
|
2966
|
+
const swimlaneContracts = applySwimlaneLayoutContracts(
|
|
2967
|
+
diagram.swimlanes ?? [],
|
|
2968
|
+
constraints,
|
|
2969
|
+
edges,
|
|
2970
|
+
isTopToBottomReadingDirection(diagram.metadata?.primaryReadingDirection),
|
|
2971
|
+
constrained.boxes,
|
|
2972
|
+
constrained.locks,
|
|
2973
|
+
options?.overlapSpacing ?? 40
|
|
2974
|
+
);
|
|
2975
|
+
if (swimlaneContracts.layouts.size > 0) {
|
|
2976
|
+
removeResolvedOverlapDiagnostics(diagnostics, constrained.boxes);
|
|
2977
|
+
}
|
|
2978
|
+
diagnostics.push(...swimlaneContracts.diagnostics);
|
|
2937
2979
|
const coordinatedNodes = coordinateNodes(
|
|
2938
2980
|
nodes,
|
|
2939
2981
|
constrained.boxes,
|
|
@@ -2958,7 +3000,8 @@ function solveDiagram(diagram, options = {}) {
|
|
|
2958
3000
|
);
|
|
2959
3001
|
const coordinatedSwimlanes = coordinateSwimlanes(
|
|
2960
3002
|
diagram.swimlanes ?? [],
|
|
2961
|
-
constrained.boxes
|
|
3003
|
+
constrained.boxes,
|
|
3004
|
+
swimlaneContracts.layouts
|
|
2962
3005
|
);
|
|
2963
3006
|
const groupBoxes = new Map(
|
|
2964
3007
|
coordinatedGroups.map((group) => [group.id, group.box])
|
|
@@ -3000,6 +3043,591 @@ function solveDiagram(diagram, options = {}) {
|
|
|
3000
3043
|
...diagram.metadata === void 0 ? {} : { metadata: diagram.metadata }
|
|
3001
3044
|
};
|
|
3002
3045
|
}
|
|
3046
|
+
function applySwimlaneLayoutContracts(swimlanes, constraints, edges, topToBottomFlow, nodeBoxes, locks, overlapSpacing) {
|
|
3047
|
+
const layouts = /* @__PURE__ */ new Map();
|
|
3048
|
+
const diagnostics = [];
|
|
3049
|
+
const movedChildIds = /* @__PURE__ */ new Set();
|
|
3050
|
+
for (const swimlane of swimlanes) {
|
|
3051
|
+
if ((swimlane.layout ?? "overlay") !== "contract") {
|
|
3052
|
+
continue;
|
|
3053
|
+
}
|
|
3054
|
+
if (swimlane.lanes.length === 0) {
|
|
3055
|
+
continue;
|
|
3056
|
+
}
|
|
3057
|
+
const layout2 = applySingleSwimlaneContract(
|
|
3058
|
+
swimlane,
|
|
3059
|
+
edges,
|
|
3060
|
+
topToBottomFlow,
|
|
3061
|
+
nodeBoxes,
|
|
3062
|
+
locks,
|
|
3063
|
+
diagnostics,
|
|
3064
|
+
movedChildIds
|
|
3065
|
+
);
|
|
3066
|
+
if (layout2 !== void 0) {
|
|
3067
|
+
layouts.set(swimlane.id, layout2);
|
|
3068
|
+
}
|
|
3069
|
+
}
|
|
3070
|
+
if (layouts.size > 0) {
|
|
3071
|
+
diagnostics.push(
|
|
3072
|
+
...reportSwimlaneOverlaps(nodeBoxes, locks, overlapSpacing),
|
|
3073
|
+
...reportSwimlaneConstraintInvalidations(
|
|
3074
|
+
constraints,
|
|
3075
|
+
nodeBoxes,
|
|
3076
|
+
movedChildIds
|
|
3077
|
+
)
|
|
3078
|
+
);
|
|
3079
|
+
}
|
|
3080
|
+
return { layouts, diagnostics, movedChildIds };
|
|
3081
|
+
}
|
|
3082
|
+
function applySingleSwimlaneContract(swimlane, edges, topToBottomFlow, nodeBoxes, locks, diagnostics, movedChildIds) {
|
|
3083
|
+
const headerHeight = swimlane.headerHeight ?? 28;
|
|
3084
|
+
const padding = swimlane.padding ?? 16;
|
|
3085
|
+
const laneBounds = swimlane.lanes.map((lane) => {
|
|
3086
|
+
const childBoxes = lane.children.map((child) => nodeBoxes.get(child)).filter((box) => box !== void 0);
|
|
3087
|
+
return childBoxes.length === 0 ? void 0 : unionBoxes(childBoxes);
|
|
3088
|
+
});
|
|
3089
|
+
const populatedBounds = laneBounds.filter(
|
|
3090
|
+
(box) => box !== void 0
|
|
3091
|
+
);
|
|
3092
|
+
if (populatedBounds.length === 0) {
|
|
3093
|
+
return void 0;
|
|
3094
|
+
}
|
|
3095
|
+
if (swimlane.orientation === "vertical") {
|
|
3096
|
+
return applyVerticalSwimlaneContract(
|
|
3097
|
+
swimlane,
|
|
3098
|
+
edges,
|
|
3099
|
+
topToBottomFlow,
|
|
3100
|
+
nodeBoxes,
|
|
3101
|
+
laneBounds,
|
|
3102
|
+
headerHeight,
|
|
3103
|
+
padding,
|
|
3104
|
+
locks,
|
|
3105
|
+
diagnostics,
|
|
3106
|
+
movedChildIds
|
|
3107
|
+
);
|
|
3108
|
+
}
|
|
3109
|
+
return applyHorizontalSwimlaneContract(
|
|
3110
|
+
swimlane,
|
|
3111
|
+
nodeBoxes,
|
|
3112
|
+
laneBounds,
|
|
3113
|
+
headerHeight,
|
|
3114
|
+
padding,
|
|
3115
|
+
locks,
|
|
3116
|
+
diagnostics,
|
|
3117
|
+
movedChildIds
|
|
3118
|
+
);
|
|
3119
|
+
}
|
|
3120
|
+
function applyVerticalSwimlaneContract(swimlane, edges, topToBottomFlow, nodeBoxes, laneBounds, headerHeight, padding, locks, diagnostics, movedChildIds) {
|
|
3121
|
+
const populatedBounds = laneBounds.filter(
|
|
3122
|
+
(box) => box !== void 0
|
|
3123
|
+
);
|
|
3124
|
+
const top = Math.min(...populatedBounds.map((box) => box.y));
|
|
3125
|
+
const left = Math.min(...populatedBounds.map((box) => box.x));
|
|
3126
|
+
const maxChildHeight = Math.max(...populatedBounds.map((box) => box.height));
|
|
3127
|
+
const flowRanks = topToBottomFlow ? rankVerticalSwimlaneChildren(swimlane, edges) : /* @__PURE__ */ new Map();
|
|
3128
|
+
const maxRank = flowRanks.size === 0 ? 0 : Math.max(...Array.from(flowRanks.values()));
|
|
3129
|
+
const rankStackGap = Math.max(8, padding / 2);
|
|
3130
|
+
const maxRankStackHeight = maxVerticalRankStackHeight(
|
|
3131
|
+
swimlane,
|
|
3132
|
+
nodeBoxes,
|
|
3133
|
+
flowRanks,
|
|
3134
|
+
rankStackGap
|
|
3135
|
+
);
|
|
3136
|
+
const rankSpacing = Math.max(96, maxRankStackHeight + padding);
|
|
3137
|
+
const contentHeight = maxRank === 0 ? maxChildHeight : maxRankStackHeight + maxRank * rankSpacing;
|
|
3138
|
+
const slotWidth = Math.max(...populatedBounds.map((box) => box.width)) + padding * 2;
|
|
3139
|
+
const laneContentTop = top + headerHeight + padding;
|
|
3140
|
+
for (let index = 0; index < swimlane.lanes.length; index += 1) {
|
|
3141
|
+
const lane = swimlane.lanes[index];
|
|
3142
|
+
const bounds = laneBounds[index];
|
|
3143
|
+
if (lane === void 0 || bounds === void 0) {
|
|
3144
|
+
continue;
|
|
3145
|
+
}
|
|
3146
|
+
const target = {
|
|
3147
|
+
x: left + slotWidth * index + padding,
|
|
3148
|
+
y: laneContentTop
|
|
3149
|
+
};
|
|
3150
|
+
if (maxRank === 0) {
|
|
3151
|
+
moveLaneChildren(
|
|
3152
|
+
lane.children,
|
|
3153
|
+
nodeBoxes,
|
|
3154
|
+
locks,
|
|
3155
|
+
diagnostics,
|
|
3156
|
+
movedChildIds,
|
|
3157
|
+
{
|
|
3158
|
+
x: target.x - bounds.x,
|
|
3159
|
+
y: target.y - bounds.y
|
|
3160
|
+
}
|
|
3161
|
+
);
|
|
3162
|
+
continue;
|
|
3163
|
+
}
|
|
3164
|
+
moveRankedVerticalLaneChildren(
|
|
3165
|
+
lane.children,
|
|
3166
|
+
nodeBoxes,
|
|
3167
|
+
locks,
|
|
3168
|
+
diagnostics,
|
|
3169
|
+
movedChildIds,
|
|
3170
|
+
flowRanks,
|
|
3171
|
+
rankSpacing,
|
|
3172
|
+
rankStackGap,
|
|
3173
|
+
{
|
|
3174
|
+
x: target.x - bounds.x,
|
|
3175
|
+
y: laneContentTop
|
|
3176
|
+
}
|
|
3177
|
+
);
|
|
3178
|
+
}
|
|
3179
|
+
return {
|
|
3180
|
+
box: {
|
|
3181
|
+
x: left,
|
|
3182
|
+
y: top,
|
|
3183
|
+
width: slotWidth * swimlane.lanes.length,
|
|
3184
|
+
height: contentHeight + padding * 2 + headerHeight
|
|
3185
|
+
},
|
|
3186
|
+
slotWidth,
|
|
3187
|
+
slotHeight: contentHeight + padding * 2 + headerHeight
|
|
3188
|
+
};
|
|
3189
|
+
}
|
|
3190
|
+
function isTopToBottomReadingDirection(value) {
|
|
3191
|
+
return value === "top_to_bottom" || value === "top-to-bottom";
|
|
3192
|
+
}
|
|
3193
|
+
function rankVerticalSwimlaneChildren(swimlane, edges) {
|
|
3194
|
+
const childOrder = /* @__PURE__ */ new Map();
|
|
3195
|
+
for (const lane of swimlane.lanes) {
|
|
3196
|
+
for (const childId of lane.children) {
|
|
3197
|
+
if (!childOrder.has(childId)) {
|
|
3198
|
+
childOrder.set(childId, childOrder.size);
|
|
3199
|
+
}
|
|
3200
|
+
}
|
|
3201
|
+
}
|
|
3202
|
+
if (childOrder.size === 0) {
|
|
3203
|
+
return /* @__PURE__ */ new Map();
|
|
3204
|
+
}
|
|
3205
|
+
const childIds = new Set(childOrder.keys());
|
|
3206
|
+
const relevantEdges = edges.filter(
|
|
3207
|
+
(edge) => childIds.has(edge.source.nodeId) && childIds.has(edge.target.nodeId) && edge.source.nodeId !== edge.target.nodeId
|
|
3208
|
+
);
|
|
3209
|
+
if (relevantEdges.length === 0) {
|
|
3210
|
+
return /* @__PURE__ */ new Map();
|
|
3211
|
+
}
|
|
3212
|
+
const ranks = new Map([...childIds].map((id) => [id, 0]));
|
|
3213
|
+
const outgoing = /* @__PURE__ */ new Map();
|
|
3214
|
+
const inDegree = new Map([...childIds].map((id) => [id, 0]));
|
|
3215
|
+
for (const edge of relevantEdges) {
|
|
3216
|
+
const targets = outgoing.get(edge.source.nodeId) ?? [];
|
|
3217
|
+
targets.push(edge.target.nodeId);
|
|
3218
|
+
outgoing.set(edge.source.nodeId, targets);
|
|
3219
|
+
inDegree.set(
|
|
3220
|
+
edge.target.nodeId,
|
|
3221
|
+
(inDegree.get(edge.target.nodeId) ?? 0) + 1
|
|
3222
|
+
);
|
|
3223
|
+
}
|
|
3224
|
+
const queue = [...childIds].filter((id) => (inDegree.get(id) ?? 0) === 0).sort((a, b) => (childOrder.get(a) ?? 0) - (childOrder.get(b) ?? 0));
|
|
3225
|
+
let visited = 0;
|
|
3226
|
+
for (let cursor = 0; cursor < queue.length; cursor += 1) {
|
|
3227
|
+
const sourceId = queue[cursor];
|
|
3228
|
+
if (sourceId === void 0) {
|
|
3229
|
+
continue;
|
|
3230
|
+
}
|
|
3231
|
+
visited += 1;
|
|
3232
|
+
for (const targetId of outgoing.get(sourceId) ?? []) {
|
|
3233
|
+
ranks.set(
|
|
3234
|
+
targetId,
|
|
3235
|
+
Math.max(ranks.get(targetId) ?? 0, (ranks.get(sourceId) ?? 0) + 1)
|
|
3236
|
+
);
|
|
3237
|
+
const nextInDegree = (inDegree.get(targetId) ?? 0) - 1;
|
|
3238
|
+
inDegree.set(targetId, nextInDegree);
|
|
3239
|
+
if (nextInDegree === 0) {
|
|
3240
|
+
queue.push(targetId);
|
|
3241
|
+
}
|
|
3242
|
+
}
|
|
3243
|
+
}
|
|
3244
|
+
return visited === childIds.size ? ranks : rankCyclicSwimlaneChildren(childIds, relevantEdges);
|
|
3245
|
+
}
|
|
3246
|
+
function rankCyclicSwimlaneChildren(childIds, edges) {
|
|
3247
|
+
const maxRank = Math.max(0, childIds.size - 1);
|
|
3248
|
+
const ranks = new Map([...childIds].map((id) => [id, 0]));
|
|
3249
|
+
for (let iteration = 0; iteration < childIds.size; iteration += 1) {
|
|
3250
|
+
let changed = false;
|
|
3251
|
+
for (const edge of edges) {
|
|
3252
|
+
const nextRank = Math.min(
|
|
3253
|
+
maxRank,
|
|
3254
|
+
(ranks.get(edge.source.nodeId) ?? 0) + 1
|
|
3255
|
+
);
|
|
3256
|
+
if (nextRank > (ranks.get(edge.target.nodeId) ?? 0)) {
|
|
3257
|
+
ranks.set(edge.target.nodeId, nextRank);
|
|
3258
|
+
changed = true;
|
|
3259
|
+
}
|
|
3260
|
+
}
|
|
3261
|
+
if (!changed) {
|
|
3262
|
+
break;
|
|
3263
|
+
}
|
|
3264
|
+
}
|
|
3265
|
+
return ranks;
|
|
3266
|
+
}
|
|
3267
|
+
function maxVerticalRankStackHeight(swimlane, nodeBoxes, flowRanks, gap) {
|
|
3268
|
+
let maxHeight = 0;
|
|
3269
|
+
for (const lane of swimlane.lanes) {
|
|
3270
|
+
for (const stack of rankStacks(
|
|
3271
|
+
lane.children,
|
|
3272
|
+
nodeBoxes,
|
|
3273
|
+
flowRanks
|
|
3274
|
+
).values()) {
|
|
3275
|
+
const height = stack.reduce(
|
|
3276
|
+
(total, item, index) => total + item.box.height + (index === 0 ? 0 : gap),
|
|
3277
|
+
0
|
|
3278
|
+
);
|
|
3279
|
+
maxHeight = Math.max(maxHeight, height);
|
|
3280
|
+
}
|
|
3281
|
+
}
|
|
3282
|
+
return maxHeight;
|
|
3283
|
+
}
|
|
3284
|
+
function moveRankedVerticalLaneChildren(childIds, nodeBoxes, locks, diagnostics, movedChildIds, flowRanks, rankSpacing, rankStackGap, target) {
|
|
3285
|
+
for (const [rank, stack] of rankStacks(childIds, nodeBoxes, flowRanks)) {
|
|
3286
|
+
let yOffset = 0;
|
|
3287
|
+
for (const item of stack) {
|
|
3288
|
+
const { childId, box } = item;
|
|
3289
|
+
if (locks.has(childId)) {
|
|
3290
|
+
diagnostics.push({
|
|
3291
|
+
severity: "warning",
|
|
3292
|
+
code: "constraints.locked-target-not-moved",
|
|
3293
|
+
message: `Locked child ${childId} was not moved into contract swimlane slot.`,
|
|
3294
|
+
path: ["swimlanes"],
|
|
3295
|
+
detail: { nodeId: childId }
|
|
3296
|
+
});
|
|
3297
|
+
continue;
|
|
3298
|
+
}
|
|
3299
|
+
const next = {
|
|
3300
|
+
...box,
|
|
3301
|
+
x: box.x + target.x,
|
|
3302
|
+
y: target.y + rank * rankSpacing + yOffset
|
|
3303
|
+
};
|
|
3304
|
+
if (next.x !== box.x || next.y !== box.y) {
|
|
3305
|
+
movedChildIds.add(childId);
|
|
3306
|
+
}
|
|
3307
|
+
nodeBoxes.set(childId, next);
|
|
3308
|
+
yOffset += box.height + rankStackGap;
|
|
3309
|
+
}
|
|
3310
|
+
}
|
|
3311
|
+
}
|
|
3312
|
+
function rankStacks(childIds, nodeBoxes, flowRanks) {
|
|
3313
|
+
const stacks = /* @__PURE__ */ new Map();
|
|
3314
|
+
for (const childId of childIds) {
|
|
3315
|
+
const box = nodeBoxes.get(childId);
|
|
3316
|
+
if (box === void 0) {
|
|
3317
|
+
continue;
|
|
3318
|
+
}
|
|
3319
|
+
const rank = flowRanks.get(childId) ?? 0;
|
|
3320
|
+
const stack = stacks.get(rank) ?? [];
|
|
3321
|
+
stack.push({ childId, box });
|
|
3322
|
+
stacks.set(rank, stack);
|
|
3323
|
+
}
|
|
3324
|
+
for (const stack of stacks.values()) {
|
|
3325
|
+
stack.sort((a, b) => {
|
|
3326
|
+
const deltaY = a.box.y - b.box.y;
|
|
3327
|
+
return deltaY === 0 ? a.childId.localeCompare(b.childId) : deltaY;
|
|
3328
|
+
});
|
|
3329
|
+
}
|
|
3330
|
+
return stacks;
|
|
3331
|
+
}
|
|
3332
|
+
function applyHorizontalSwimlaneContract(swimlane, nodeBoxes, laneBounds, headerHeight, padding, locks, diagnostics, movedChildIds) {
|
|
3333
|
+
const populatedBounds = laneBounds.filter(
|
|
3334
|
+
(box) => box !== void 0
|
|
3335
|
+
);
|
|
3336
|
+
const top = Math.min(...populatedBounds.map((box) => box.y));
|
|
3337
|
+
const left = Math.min(...populatedBounds.map((box) => box.x));
|
|
3338
|
+
const slotWidth = Math.max(...populatedBounds.map((box) => box.width)) + headerHeight + padding * 2;
|
|
3339
|
+
const slotHeight = Math.max(...populatedBounds.map((box) => box.height)) + padding * 2;
|
|
3340
|
+
for (let index = 0; index < swimlane.lanes.length; index += 1) {
|
|
3341
|
+
const lane = swimlane.lanes[index];
|
|
3342
|
+
const bounds = laneBounds[index];
|
|
3343
|
+
if (lane === void 0 || bounds === void 0) {
|
|
3344
|
+
continue;
|
|
3345
|
+
}
|
|
3346
|
+
const target = {
|
|
3347
|
+
x: left + headerHeight + padding,
|
|
3348
|
+
y: top + slotHeight * index + padding
|
|
3349
|
+
};
|
|
3350
|
+
moveLaneChildren(
|
|
3351
|
+
lane.children,
|
|
3352
|
+
nodeBoxes,
|
|
3353
|
+
locks,
|
|
3354
|
+
diagnostics,
|
|
3355
|
+
movedChildIds,
|
|
3356
|
+
{
|
|
3357
|
+
x: target.x - bounds.x,
|
|
3358
|
+
y: target.y - bounds.y
|
|
3359
|
+
}
|
|
3360
|
+
);
|
|
3361
|
+
}
|
|
3362
|
+
return {
|
|
3363
|
+
box: {
|
|
3364
|
+
x: left,
|
|
3365
|
+
y: top,
|
|
3366
|
+
width: slotWidth,
|
|
3367
|
+
height: slotHeight * swimlane.lanes.length
|
|
3368
|
+
},
|
|
3369
|
+
slotWidth,
|
|
3370
|
+
slotHeight
|
|
3371
|
+
};
|
|
3372
|
+
}
|
|
3373
|
+
function moveLaneChildren(childIds, nodeBoxes, locks, diagnostics, movedChildIds, offset) {
|
|
3374
|
+
for (const childId of childIds) {
|
|
3375
|
+
const box = nodeBoxes.get(childId);
|
|
3376
|
+
if (box === void 0) {
|
|
3377
|
+
continue;
|
|
3378
|
+
}
|
|
3379
|
+
if (locks.has(childId)) {
|
|
3380
|
+
diagnostics.push({
|
|
3381
|
+
severity: "warning",
|
|
3382
|
+
code: "constraints.locked-target-not-moved",
|
|
3383
|
+
message: `Locked child ${childId} was not moved into contract swimlane slot.`,
|
|
3384
|
+
path: ["swimlanes"],
|
|
3385
|
+
detail: { nodeId: childId }
|
|
3386
|
+
});
|
|
3387
|
+
continue;
|
|
3388
|
+
}
|
|
3389
|
+
if (offset.x !== 0 || offset.y !== 0) {
|
|
3390
|
+
movedChildIds.add(childId);
|
|
3391
|
+
}
|
|
3392
|
+
nodeBoxes.set(childId, {
|
|
3393
|
+
...box,
|
|
3394
|
+
x: box.x + offset.x,
|
|
3395
|
+
y: box.y + offset.y
|
|
3396
|
+
});
|
|
3397
|
+
}
|
|
3398
|
+
}
|
|
3399
|
+
function removeResolvedOverlapDiagnostics(diagnostics, nodeBoxes) {
|
|
3400
|
+
for (let index = diagnostics.length - 1; index >= 0; index -= 1) {
|
|
3401
|
+
const diagnostic = diagnostics[index];
|
|
3402
|
+
if (diagnostic?.code !== "constraints.overlap.unresolved") {
|
|
3403
|
+
continue;
|
|
3404
|
+
}
|
|
3405
|
+
const firstId = detailString(diagnostic, "firstId");
|
|
3406
|
+
const secondId = detailString(diagnostic, "secondId");
|
|
3407
|
+
const first = firstId === void 0 ? void 0 : nodeBoxes.get(firstId);
|
|
3408
|
+
const second = secondId === void 0 ? void 0 : nodeBoxes.get(secondId);
|
|
3409
|
+
if (first !== void 0 && second !== void 0 && !intersectsAabb(first, second)) {
|
|
3410
|
+
diagnostics.splice(index, 1);
|
|
3411
|
+
}
|
|
3412
|
+
}
|
|
3413
|
+
}
|
|
3414
|
+
function reportSwimlaneConstraintInvalidations(constraints, nodeBoxes, movedChildIds) {
|
|
3415
|
+
const diagnostics = [];
|
|
3416
|
+
for (const constraint of constraints) {
|
|
3417
|
+
const invalidatedNodeIds = movedConstraintNodeIds(
|
|
3418
|
+
constraint,
|
|
3419
|
+
nodeBoxes,
|
|
3420
|
+
movedChildIds
|
|
3421
|
+
);
|
|
3422
|
+
if (invalidatedNodeIds.length === 0) {
|
|
3423
|
+
continue;
|
|
3424
|
+
}
|
|
3425
|
+
diagnostics.push({
|
|
3426
|
+
severity: "warning",
|
|
3427
|
+
code: "constraints.swimlane-contract.invalidated",
|
|
3428
|
+
message: `Contract swimlane placement moved node(s) after ${constraint.kind} constraint solving; final geometry no longer satisfies that constraint.`,
|
|
3429
|
+
path: ["swimlanes"],
|
|
3430
|
+
detail: {
|
|
3431
|
+
constraintKind: constraint.kind,
|
|
3432
|
+
...constraint.id === void 0 ? {} : { constraintId: constraint.id },
|
|
3433
|
+
nodeIds: invalidatedNodeIds
|
|
3434
|
+
}
|
|
3435
|
+
});
|
|
3436
|
+
}
|
|
3437
|
+
return diagnostics;
|
|
3438
|
+
}
|
|
3439
|
+
function movedConstraintNodeIds(constraint, nodeBoxes, movedChildIds) {
|
|
3440
|
+
switch (constraint.kind) {
|
|
3441
|
+
case "exact-position":
|
|
3442
|
+
return [];
|
|
3443
|
+
case "containment":
|
|
3444
|
+
return movedContainmentViolations(constraint, nodeBoxes, movedChildIds);
|
|
3445
|
+
case "relative-position":
|
|
3446
|
+
return movedRelativeViolations(constraint, nodeBoxes, movedChildIds);
|
|
3447
|
+
case "align":
|
|
3448
|
+
return movedAlignViolations(constraint, nodeBoxes, movedChildIds);
|
|
3449
|
+
case "distribute":
|
|
3450
|
+
return movedDistributeViolations(constraint, nodeBoxes, movedChildIds);
|
|
3451
|
+
}
|
|
3452
|
+
}
|
|
3453
|
+
function movedContainmentViolations(constraint, nodeBoxes, movedChildIds) {
|
|
3454
|
+
const container = nodeBoxes.get(constraint.containerId);
|
|
3455
|
+
if (container === void 0) {
|
|
3456
|
+
return [];
|
|
3457
|
+
}
|
|
3458
|
+
const content = paddedContentBox(container, constraint.padding);
|
|
3459
|
+
return constraint.childIds.filter((childId) => {
|
|
3460
|
+
if (!movedChildIds.has(childId)) {
|
|
3461
|
+
return false;
|
|
3462
|
+
}
|
|
3463
|
+
const child = nodeBoxes.get(childId);
|
|
3464
|
+
return child !== void 0 && !boxInside(child, content);
|
|
3465
|
+
});
|
|
3466
|
+
}
|
|
3467
|
+
function movedRelativeViolations(constraint, nodeBoxes, movedChildIds) {
|
|
3468
|
+
if (!movedChildIds.has(constraint.sourceId) && !movedChildIds.has(constraint.referenceId)) {
|
|
3469
|
+
return [];
|
|
3470
|
+
}
|
|
3471
|
+
const source = nodeBoxes.get(constraint.sourceId);
|
|
3472
|
+
const reference = nodeBoxes.get(constraint.referenceId);
|
|
3473
|
+
if (source === void 0 || reference === void 0) {
|
|
3474
|
+
return [];
|
|
3475
|
+
}
|
|
3476
|
+
return sameBoxPosition(
|
|
3477
|
+
source,
|
|
3478
|
+
expectedRelativeBox(source, reference, constraint)
|
|
3479
|
+
) ? [] : [constraint.sourceId];
|
|
3480
|
+
}
|
|
3481
|
+
function movedAlignViolations(constraint, nodeBoxes, movedChildIds) {
|
|
3482
|
+
if (!constraint.targetIds.some((id) => movedChildIds.has(id))) {
|
|
3483
|
+
return [];
|
|
3484
|
+
}
|
|
3485
|
+
const targets = constraint.targetIds.map((id) => ({ id, box: nodeBoxes.get(id) })).filter(
|
|
3486
|
+
(target) => target.box !== void 0
|
|
3487
|
+
);
|
|
3488
|
+
const anchor = targets[0];
|
|
3489
|
+
if (anchor === void 0) {
|
|
3490
|
+
return [];
|
|
3491
|
+
}
|
|
3492
|
+
const expected = alignmentValue2(anchor.box, constraint.axis);
|
|
3493
|
+
return targets.filter(
|
|
3494
|
+
(target) => movedChildIds.has(target.id) && !sameNumber(alignmentValue2(target.box, constraint.axis), expected)
|
|
3495
|
+
).map((target) => target.id);
|
|
3496
|
+
}
|
|
3497
|
+
function movedDistributeViolations(constraint, nodeBoxes, movedChildIds) {
|
|
3498
|
+
if (!constraint.targetIds.some((id) => movedChildIds.has(id))) {
|
|
3499
|
+
return [];
|
|
3500
|
+
}
|
|
3501
|
+
const targets = constraint.targetIds.map((id) => ({ id, box: nodeBoxes.get(id) })).filter(
|
|
3502
|
+
(target) => target.box !== void 0
|
|
3503
|
+
).sort((a, b) => {
|
|
3504
|
+
const delta = constraint.axis === "horizontal" ? a.box.x - b.box.x : a.box.y - b.box.y;
|
|
3505
|
+
return delta === 0 ? a.id.localeCompare(b.id) : delta;
|
|
3506
|
+
});
|
|
3507
|
+
if (targets.length < 3) {
|
|
3508
|
+
return [];
|
|
3509
|
+
}
|
|
3510
|
+
const first = targets[0];
|
|
3511
|
+
const last = targets.at(-1);
|
|
3512
|
+
if (first === void 0 || last === void 0) {
|
|
3513
|
+
return [];
|
|
3514
|
+
}
|
|
3515
|
+
const expectedSpacing = constraint.spacing ?? (distributionStart2(last.box, constraint.axis) - distributionStart2(first.box, constraint.axis)) / (targets.length - 1);
|
|
3516
|
+
return targets.slice(1).filter((target, index) => {
|
|
3517
|
+
const previous = targets[index];
|
|
3518
|
+
if (previous === void 0 || !movedChildIds.has(target.id)) {
|
|
3519
|
+
return false;
|
|
3520
|
+
}
|
|
3521
|
+
return !sameNumber(
|
|
3522
|
+
distributionStart2(target.box, constraint.axis) - distributionStart2(previous.box, constraint.axis),
|
|
3523
|
+
expectedSpacing
|
|
3524
|
+
);
|
|
3525
|
+
}).map((target) => target.id);
|
|
3526
|
+
}
|
|
3527
|
+
function expectedRelativeBox(source, reference, constraint) {
|
|
3528
|
+
const offset = constraint.offset ?? { x: 0, y: 0 };
|
|
3529
|
+
switch (constraint.relation) {
|
|
3530
|
+
case "above":
|
|
3531
|
+
return {
|
|
3532
|
+
...source,
|
|
3533
|
+
x: reference.x + offset.x,
|
|
3534
|
+
y: reference.y - source.height + offset.y
|
|
3535
|
+
};
|
|
3536
|
+
case "right-of":
|
|
3537
|
+
return {
|
|
3538
|
+
...source,
|
|
3539
|
+
x: reference.x + reference.width + offset.x,
|
|
3540
|
+
y: reference.y + offset.y
|
|
3541
|
+
};
|
|
3542
|
+
case "below":
|
|
3543
|
+
return {
|
|
3544
|
+
...source,
|
|
3545
|
+
x: reference.x + offset.x,
|
|
3546
|
+
y: reference.y + reference.height + offset.y
|
|
3547
|
+
};
|
|
3548
|
+
case "left-of":
|
|
3549
|
+
return {
|
|
3550
|
+
...source,
|
|
3551
|
+
x: reference.x - source.width + offset.x,
|
|
3552
|
+
y: reference.y + offset.y
|
|
3553
|
+
};
|
|
3554
|
+
}
|
|
3555
|
+
}
|
|
3556
|
+
function paddedContentBox(container, padding) {
|
|
3557
|
+
const margin = padding ?? { top: 0, right: 0, bottom: 0, left: 0 };
|
|
3558
|
+
return {
|
|
3559
|
+
x: container.x + margin.left,
|
|
3560
|
+
y: container.y + margin.top,
|
|
3561
|
+
width: container.width - margin.left - margin.right,
|
|
3562
|
+
height: container.height - margin.top - margin.bottom
|
|
3563
|
+
};
|
|
3564
|
+
}
|
|
3565
|
+
function boxInside(child, container) {
|
|
3566
|
+
return child.x >= container.x && child.y >= container.y && child.x + child.width <= container.x + container.width && child.y + child.height <= container.y + container.height;
|
|
3567
|
+
}
|
|
3568
|
+
function sameBoxPosition(first, second) {
|
|
3569
|
+
return sameNumber(first.x, second.x) && sameNumber(first.y, second.y);
|
|
3570
|
+
}
|
|
3571
|
+
function sameNumber(first, second) {
|
|
3572
|
+
return Math.abs(first - second) < 1e-3;
|
|
3573
|
+
}
|
|
3574
|
+
function alignmentValue2(box, axis) {
|
|
3575
|
+
switch (axis) {
|
|
3576
|
+
case "x":
|
|
3577
|
+
case "left":
|
|
3578
|
+
return box.x;
|
|
3579
|
+
case "y":
|
|
3580
|
+
case "top":
|
|
3581
|
+
return box.y;
|
|
3582
|
+
case "center-x":
|
|
3583
|
+
return box.x + box.width / 2;
|
|
3584
|
+
case "center-y":
|
|
3585
|
+
return box.y + box.height / 2;
|
|
3586
|
+
case "right":
|
|
3587
|
+
return box.x + box.width;
|
|
3588
|
+
case "bottom":
|
|
3589
|
+
return box.y + box.height;
|
|
3590
|
+
}
|
|
3591
|
+
}
|
|
3592
|
+
function distributionStart2(box, axis) {
|
|
3593
|
+
return axis === "horizontal" ? box.x : box.y;
|
|
3594
|
+
}
|
|
3595
|
+
function detailString(diagnostic, key) {
|
|
3596
|
+
const value = diagnostic.detail?.[key];
|
|
3597
|
+
return typeof value === "string" ? value : void 0;
|
|
3598
|
+
}
|
|
3599
|
+
function reportSwimlaneOverlaps(nodeBoxes, locks, overlapSpacing) {
|
|
3600
|
+
const diagnostics = [];
|
|
3601
|
+
const ids = [...nodeBoxes.keys()].sort();
|
|
3602
|
+
for (const firstId of ids) {
|
|
3603
|
+
for (const secondId of ids) {
|
|
3604
|
+
if (firstId >= secondId) {
|
|
3605
|
+
continue;
|
|
3606
|
+
}
|
|
3607
|
+
const first = nodeBoxes.get(firstId);
|
|
3608
|
+
const second = nodeBoxes.get(secondId);
|
|
3609
|
+
if (first === void 0 || second === void 0) {
|
|
3610
|
+
continue;
|
|
3611
|
+
}
|
|
3612
|
+
if (!intersectsAabb(first, second)) {
|
|
3613
|
+
continue;
|
|
3614
|
+
}
|
|
3615
|
+
diagnostics.push({
|
|
3616
|
+
severity: "warning",
|
|
3617
|
+
code: "constraints.overlap.unresolved",
|
|
3618
|
+
message: `Boxes ${firstId} and ${secondId} still overlap after contract swimlane placement with configured spacing ${overlapSpacing}.`,
|
|
3619
|
+
path: ["swimlanes"],
|
|
3620
|
+
detail: {
|
|
3621
|
+
firstId,
|
|
3622
|
+
secondId,
|
|
3623
|
+
firstLocked: locks.has(firstId),
|
|
3624
|
+
secondLocked: locks.has(secondId)
|
|
3625
|
+
}
|
|
3626
|
+
});
|
|
3627
|
+
}
|
|
3628
|
+
}
|
|
3629
|
+
return diagnostics;
|
|
3630
|
+
}
|
|
3003
3631
|
function coordinateNodes(nodes, boxes, options, diagnostics) {
|
|
3004
3632
|
const coordinated = [];
|
|
3005
3633
|
for (const node of nodes) {
|
|
@@ -3114,16 +3742,70 @@ function portLabelBox(port) {
|
|
|
3114
3742
|
height
|
|
3115
3743
|
};
|
|
3116
3744
|
}
|
|
3117
|
-
function coordinateSwimlanes(swimlanes, nodeBoxes) {
|
|
3118
|
-
const titleSize = 28;
|
|
3119
|
-
const padding = 16;
|
|
3745
|
+
function coordinateSwimlanes(swimlanes, nodeBoxes, layouts) {
|
|
3120
3746
|
return swimlanes.map((swimlane) => {
|
|
3121
|
-
const
|
|
3747
|
+
const layout2 = swimlane.layout ?? "overlay";
|
|
3748
|
+
const headerHeight = swimlane.headerHeight ?? 28;
|
|
3749
|
+
const padding = swimlane.padding ?? 16;
|
|
3750
|
+
const contractLayout = layouts.get(swimlane.id);
|
|
3751
|
+
if (layout2 === "contract" && contractLayout !== void 0) {
|
|
3752
|
+
const lanes2 = swimlane.lanes.map((lane, index) => {
|
|
3753
|
+
const box = swimlane.orientation === "vertical" ? {
|
|
3754
|
+
x: contractLayout.box.x + contractLayout.slotWidth * index,
|
|
3755
|
+
y: contractLayout.box.y,
|
|
3756
|
+
width: contractLayout.slotWidth,
|
|
3757
|
+
height: contractLayout.box.height
|
|
3758
|
+
} : {
|
|
3759
|
+
x: contractLayout.box.x,
|
|
3760
|
+
y: contractLayout.box.y + contractLayout.slotHeight * index,
|
|
3761
|
+
width: contractLayout.box.width,
|
|
3762
|
+
height: contractLayout.slotHeight
|
|
3763
|
+
};
|
|
3764
|
+
const headerBox = swimlane.orientation === "vertical" ? {
|
|
3765
|
+
x: box.x,
|
|
3766
|
+
y: box.y,
|
|
3767
|
+
width: box.width,
|
|
3768
|
+
height: headerHeight
|
|
3769
|
+
} : {
|
|
3770
|
+
x: box.x,
|
|
3771
|
+
y: box.y,
|
|
3772
|
+
width: headerHeight,
|
|
3773
|
+
height: box.height
|
|
3774
|
+
};
|
|
3775
|
+
const contentBox2 = swimlane.orientation === "vertical" ? {
|
|
3776
|
+
x: box.x,
|
|
3777
|
+
y: box.y + headerHeight,
|
|
3778
|
+
width: box.width,
|
|
3779
|
+
height: Math.max(0, box.height - headerHeight)
|
|
3780
|
+
} : {
|
|
3781
|
+
x: box.x + headerHeight,
|
|
3782
|
+
y: box.y,
|
|
3783
|
+
width: Math.max(0, box.width - headerHeight),
|
|
3784
|
+
height: box.height
|
|
3785
|
+
};
|
|
3786
|
+
return {
|
|
3787
|
+
...lane,
|
|
3788
|
+
box,
|
|
3789
|
+
headerBox,
|
|
3790
|
+
contentBox: contentBox2
|
|
3791
|
+
};
|
|
3792
|
+
});
|
|
3793
|
+
return {
|
|
3794
|
+
...swimlane,
|
|
3795
|
+
lanes: lanes2,
|
|
3796
|
+
box: contractLayout.box,
|
|
3797
|
+
...headerHeight === void 0 ? {} : { headerHeight },
|
|
3798
|
+
...padding === void 0 ? {} : { padding }
|
|
3799
|
+
};
|
|
3800
|
+
}
|
|
3801
|
+
const laneContentBoxes = swimlane.lanes.map((lane) => {
|
|
3122
3802
|
const childBoxes = lane.children.map((child) => nodeBoxes.get(child)).filter((box) => box !== void 0);
|
|
3123
|
-
return childBoxes.length === 0 ?
|
|
3803
|
+
return childBoxes.length === 0 ? void 0 : unionBoxes(childBoxes);
|
|
3124
3804
|
});
|
|
3125
|
-
const laneUnion =
|
|
3126
|
-
|
|
3805
|
+
const laneUnion = laneContentBoxes.filter((box) => box !== void 0).length === 0 ? { x: 0, y: 0, width: 120, height: 80 } : unionBoxes(
|
|
3806
|
+
laneContentBoxes.filter((box) => box !== void 0)
|
|
3807
|
+
);
|
|
3808
|
+
const outer = expand(laneUnion, padding, headerHeight);
|
|
3127
3809
|
const laneCount = Math.max(1, swimlane.lanes.length);
|
|
3128
3810
|
const lanes = swimlane.lanes.map((lane, index) => {
|
|
3129
3811
|
const box = swimlane.orientation === "vertical" ? {
|
|
@@ -3137,9 +3819,42 @@ function coordinateSwimlanes(swimlanes, nodeBoxes) {
|
|
|
3137
3819
|
width: outer.width,
|
|
3138
3820
|
height: outer.height / laneCount
|
|
3139
3821
|
};
|
|
3140
|
-
|
|
3822
|
+
const headerBox = layout2 === "contract" ? swimlane.orientation === "vertical" ? {
|
|
3823
|
+
x: box.x,
|
|
3824
|
+
y: box.y,
|
|
3825
|
+
width: box.width,
|
|
3826
|
+
height: headerHeight
|
|
3827
|
+
} : {
|
|
3828
|
+
x: box.x,
|
|
3829
|
+
y: box.y,
|
|
3830
|
+
width: headerHeight,
|
|
3831
|
+
height: box.height
|
|
3832
|
+
} : void 0;
|
|
3833
|
+
const contentBox2 = layout2 === "contract" ? swimlane.orientation === "vertical" ? {
|
|
3834
|
+
x: box.x,
|
|
3835
|
+
y: box.y + headerHeight,
|
|
3836
|
+
width: box.width,
|
|
3837
|
+
height: Math.max(0, box.height - headerHeight)
|
|
3838
|
+
} : {
|
|
3839
|
+
x: box.x + headerHeight,
|
|
3840
|
+
y: box.y,
|
|
3841
|
+
width: Math.max(0, box.width - headerHeight),
|
|
3842
|
+
height: box.height
|
|
3843
|
+
} : void 0;
|
|
3844
|
+
return {
|
|
3845
|
+
...lane,
|
|
3846
|
+
box,
|
|
3847
|
+
...headerBox === void 0 ? {} : { headerBox },
|
|
3848
|
+
...contentBox2 === void 0 ? {} : { contentBox: contentBox2 }
|
|
3849
|
+
};
|
|
3141
3850
|
});
|
|
3142
|
-
return {
|
|
3851
|
+
return {
|
|
3852
|
+
...swimlane,
|
|
3853
|
+
lanes,
|
|
3854
|
+
box: outer,
|
|
3855
|
+
...headerHeight === void 0 ? {} : { headerHeight },
|
|
3856
|
+
...padding === void 0 ? {} : { padding }
|
|
3857
|
+
};
|
|
3143
3858
|
});
|
|
3144
3859
|
}
|
|
3145
3860
|
function coordinateFrame(frame, contentBounds) {
|