@flowgram.ai/free-auto-layout-plugin 0.1.0-alpha.6 → 0.1.0-alpha.8
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/esm/index.js +135 -44
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +133 -44
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
package/dist/esm/index.js
CHANGED
|
@@ -2083,11 +2083,14 @@ import { definePluginCreator } from "@flowgram.ai/core";
|
|
|
2083
2083
|
import { inject, injectable } from "inversify";
|
|
2084
2084
|
import {
|
|
2085
2085
|
WorkflowDocument,
|
|
2086
|
-
WorkflowNodeLinesData
|
|
2086
|
+
WorkflowNodeLinesData as WorkflowNodeLinesData2
|
|
2087
2087
|
} from "@flowgram.ai/free-layout-core";
|
|
2088
2088
|
|
|
2089
2089
|
// src/layout/store.ts
|
|
2090
|
-
import {
|
|
2090
|
+
import {
|
|
2091
|
+
WorkflowNodeLinesData
|
|
2092
|
+
} from "@flowgram.ai/free-layout-core";
|
|
2093
|
+
import { FlowNodeBaseType, FlowNodeTransformData } from "@flowgram.ai/document";
|
|
2091
2094
|
var LayoutStore = class {
|
|
2092
2095
|
constructor() {
|
|
2093
2096
|
this.init = false;
|
|
@@ -2118,12 +2121,23 @@ var LayoutStore = class {
|
|
|
2118
2121
|
}
|
|
2119
2122
|
/** 创建布局数据 */
|
|
2120
2123
|
createStore(params) {
|
|
2121
|
-
const { nodes, edges } = params;
|
|
2124
|
+
const { nodes, edges, container } = params;
|
|
2125
|
+
this.container = container;
|
|
2126
|
+
const layoutNodes = this.createLayoutNodes(nodes);
|
|
2127
|
+
const layoutEdges = this.createEdgesStore(edges);
|
|
2128
|
+
const virtualEdges = this.createVirtualEdges(params);
|
|
2122
2129
|
const store = {
|
|
2123
2130
|
nodes: /* @__PURE__ */ new Map(),
|
|
2124
2131
|
edges: /* @__PURE__ */ new Map()
|
|
2125
2132
|
};
|
|
2126
|
-
|
|
2133
|
+
layoutNodes.forEach((node) => store.nodes.set(node.id, node));
|
|
2134
|
+
layoutEdges.concat(virtualEdges).forEach((edge) => store.edges.set(edge.id, edge));
|
|
2135
|
+
return store;
|
|
2136
|
+
}
|
|
2137
|
+
/** 创建节点布局数据 */
|
|
2138
|
+
createLayoutNodes(nodes) {
|
|
2139
|
+
const layoutNodes = nodes.map((node, index) => {
|
|
2140
|
+
var _a;
|
|
2127
2141
|
const { bounds } = node.getData(FlowNodeTransformData);
|
|
2128
2142
|
const layoutNode = {
|
|
2129
2143
|
id: node.id,
|
|
@@ -2137,11 +2151,15 @@ var LayoutStore = class {
|
|
|
2137
2151
|
position: { x: bounds.center.x, y: bounds.center.y },
|
|
2138
2152
|
offset: { x: 0, y: 0 },
|
|
2139
2153
|
size: { width: bounds.width, height: bounds.height },
|
|
2140
|
-
hasChildren: node.collapsedChildren
|
|
2154
|
+
hasChildren: ((_a = node.collapsedChildren) == null ? void 0 : _a.length) > 0
|
|
2141
2155
|
};
|
|
2142
|
-
|
|
2156
|
+
return layoutNode;
|
|
2143
2157
|
});
|
|
2144
|
-
|
|
2158
|
+
return layoutNodes;
|
|
2159
|
+
}
|
|
2160
|
+
/** 创建线条布局数据 */
|
|
2161
|
+
createEdgesStore(edges) {
|
|
2162
|
+
const layoutEdges = edges.map((edge) => {
|
|
2145
2163
|
const { from, to } = edge.info;
|
|
2146
2164
|
if (!from || !to || edge.vertical) {
|
|
2147
2165
|
return;
|
|
@@ -2157,9 +2175,64 @@ var LayoutStore = class {
|
|
|
2157
2175
|
// 初始化时,index 未计算
|
|
2158
2176
|
name: edge.id
|
|
2159
2177
|
};
|
|
2160
|
-
|
|
2161
|
-
});
|
|
2162
|
-
return
|
|
2178
|
+
return layoutEdge;
|
|
2179
|
+
}).filter(Boolean);
|
|
2180
|
+
return layoutEdges;
|
|
2181
|
+
}
|
|
2182
|
+
/** 创建虚拟线条数据 */
|
|
2183
|
+
createVirtualEdges(params) {
|
|
2184
|
+
const { nodes, edges } = params;
|
|
2185
|
+
const groupNodes = nodes.filter((n) => n.flowNodeType === FlowNodeBaseType.GROUP);
|
|
2186
|
+
const virtualEdges = groupNodes.map((group) => {
|
|
2187
|
+
const { id: groupId, blocks = [] } = group;
|
|
2188
|
+
const blockIdSet = new Set(blocks.map((b) => b.id));
|
|
2189
|
+
const groupFromEdges = edges.filter((edge) => {
|
|
2190
|
+
var _a, _b;
|
|
2191
|
+
return blockIdSet.has((_b = (_a = edge.to) == null ? void 0 : _a.id) != null ? _b : "");
|
|
2192
|
+
}).map((edge) => {
|
|
2193
|
+
const { from, to } = edge.info;
|
|
2194
|
+
if (!from || !to || edge.vertical) {
|
|
2195
|
+
return;
|
|
2196
|
+
}
|
|
2197
|
+
const id = `virtual_${groupId}_${to}`;
|
|
2198
|
+
const layoutEdge = {
|
|
2199
|
+
id,
|
|
2200
|
+
entity: edge,
|
|
2201
|
+
from,
|
|
2202
|
+
to: groupId,
|
|
2203
|
+
fromIndex: "",
|
|
2204
|
+
// 初始化时,index 未计算
|
|
2205
|
+
toIndex: "",
|
|
2206
|
+
// 初始化时,index 未计算
|
|
2207
|
+
name: id
|
|
2208
|
+
};
|
|
2209
|
+
return layoutEdge;
|
|
2210
|
+
}).filter(Boolean);
|
|
2211
|
+
const groupToEdges = edges.filter((edge) => {
|
|
2212
|
+
var _a;
|
|
2213
|
+
return blockIdSet.has((_a = edge.from.id) != null ? _a : "");
|
|
2214
|
+
}).map((edge) => {
|
|
2215
|
+
const { from, to } = edge.info;
|
|
2216
|
+
if (!from || !to || edge.vertical) {
|
|
2217
|
+
return;
|
|
2218
|
+
}
|
|
2219
|
+
const id = `virtual_${groupId}_${from}`;
|
|
2220
|
+
const layoutEdge = {
|
|
2221
|
+
id,
|
|
2222
|
+
entity: edge,
|
|
2223
|
+
from: groupId,
|
|
2224
|
+
to,
|
|
2225
|
+
fromIndex: "",
|
|
2226
|
+
// 初始化时,index 未计算
|
|
2227
|
+
toIndex: "",
|
|
2228
|
+
// 初始化时,index 未计算
|
|
2229
|
+
name: id
|
|
2230
|
+
};
|
|
2231
|
+
return layoutEdge;
|
|
2232
|
+
}).filter(Boolean);
|
|
2233
|
+
return [...groupFromEdges, ...groupToEdges];
|
|
2234
|
+
}).flat();
|
|
2235
|
+
return virtualEdges;
|
|
2163
2236
|
}
|
|
2164
2237
|
/** 创建节点索引映射 */
|
|
2165
2238
|
createIndexMap() {
|
|
@@ -2196,27 +2269,37 @@ var LayoutStore = class {
|
|
|
2196
2269
|
this.nodes.forEach((node) => {
|
|
2197
2270
|
nodeIdList.push(node.id);
|
|
2198
2271
|
});
|
|
2199
|
-
const sameFromEdges = /* @__PURE__ */ new Map();
|
|
2200
2272
|
this.edges.forEach((edge) => {
|
|
2201
2273
|
nodeIdList.push(edge.to);
|
|
2202
|
-
if (edge.entity.info.fromPort) {
|
|
2203
|
-
const edgesForFrom = sameFromEdges.get(edge.from) || [];
|
|
2204
|
-
sameFromEdges.set(edge.from, [...edgesForFrom, edge]);
|
|
2205
|
-
}
|
|
2206
2274
|
});
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2275
|
+
const visited = /* @__PURE__ */ new Set();
|
|
2276
|
+
const visit = (node) => {
|
|
2277
|
+
if (visited.has(node.id)) {
|
|
2278
|
+
return;
|
|
2279
|
+
}
|
|
2280
|
+
visited.add(node.id);
|
|
2281
|
+
nodeIdList.push(node.id);
|
|
2282
|
+
node.blocks.forEach((child) => {
|
|
2283
|
+
visit(child);
|
|
2284
|
+
});
|
|
2285
|
+
const { outputLines } = node.getData(WorkflowNodeLinesData);
|
|
2286
|
+
const sortedLines = outputLines.sort((a, b) => {
|
|
2287
|
+
const aPort = a.fromPort;
|
|
2288
|
+
const bPort = b.fromPort;
|
|
2211
2289
|
if (aPort && bPort) {
|
|
2212
2290
|
return aPort.point.y - bPort.point.y;
|
|
2213
2291
|
}
|
|
2214
2292
|
return 0;
|
|
2215
2293
|
});
|
|
2216
|
-
|
|
2217
|
-
|
|
2294
|
+
sortedLines.forEach((line) => {
|
|
2295
|
+
const { to } = line;
|
|
2296
|
+
if (!to) {
|
|
2297
|
+
return;
|
|
2298
|
+
}
|
|
2299
|
+
visit(to);
|
|
2218
2300
|
});
|
|
2219
|
-
}
|
|
2301
|
+
};
|
|
2302
|
+
visit(this.container);
|
|
2220
2303
|
const uniqueNodeIds = nodeIdList.reduceRight((acc, nodeId) => {
|
|
2221
2304
|
if (!acc.includes(nodeId)) {
|
|
2222
2305
|
acc.unshift(nodeId);
|
|
@@ -2228,7 +2311,6 @@ var LayoutStore = class {
|
|
|
2228
2311
|
};
|
|
2229
2312
|
|
|
2230
2313
|
// src/layout/position.ts
|
|
2231
|
-
import { FlowNodeTransformData as FlowNodeTransformData2 } from "@flowgram.ai/document";
|
|
2232
2314
|
import { startTween, TransformData } from "@flowgram.ai/core";
|
|
2233
2315
|
var LayoutPosition = class {
|
|
2234
2316
|
constructor(store) {
|
|
@@ -2260,23 +2342,19 @@ var LayoutPosition = class {
|
|
|
2260
2342
|
};
|
|
2261
2343
|
const deltaX = (position2.x - transform.position.x) * step / 100;
|
|
2262
2344
|
const deltaY = (position2.y - transform.bounds.height / 2 - transform.position.y) * step / 100;
|
|
2263
|
-
if (layoutNode.hasChildren) {
|
|
2264
|
-
layoutNode.entity.collapsedChildren.forEach((childNode) => {
|
|
2265
|
-
const childNodeTransformData = childNode.getData(FlowNodeTransformData2);
|
|
2266
|
-
childNodeTransformData.fireChange();
|
|
2267
|
-
});
|
|
2268
|
-
}
|
|
2269
2345
|
transform.update({
|
|
2270
2346
|
position: {
|
|
2271
2347
|
x: transform.position.x + deltaX,
|
|
2272
2348
|
y: transform.position.y + deltaY
|
|
2273
2349
|
}
|
|
2274
2350
|
});
|
|
2351
|
+
const document = layoutNode.entity.document;
|
|
2352
|
+
document.layout.updateAffectedTransform(layoutNode.entity);
|
|
2275
2353
|
}
|
|
2276
2354
|
};
|
|
2277
2355
|
|
|
2278
2356
|
// src/layout/dagre.ts
|
|
2279
|
-
import { FlowNodeTransformData as
|
|
2357
|
+
import { FlowNodeTransformData as FlowNodeTransformData2 } from "@flowgram.ai/document";
|
|
2280
2358
|
import { Graph as DagreGraph } from "@dagrejs/graphlib";
|
|
2281
2359
|
|
|
2282
2360
|
// src/layout/constant.ts
|
|
@@ -2364,6 +2442,7 @@ var DagreLayout = class {
|
|
|
2364
2442
|
}
|
|
2365
2443
|
layoutSetPosition() {
|
|
2366
2444
|
this.store.nodes.forEach((layoutNode) => {
|
|
2445
|
+
var _a;
|
|
2367
2446
|
const offsetX = this.getOffsetX(layoutNode);
|
|
2368
2447
|
const graphNode = this.graph.node(layoutNode.index);
|
|
2369
2448
|
if (!graphNode) {
|
|
@@ -2374,7 +2453,7 @@ var DagreLayout = class {
|
|
|
2374
2453
|
};
|
|
2375
2454
|
return;
|
|
2376
2455
|
}
|
|
2377
|
-
layoutNode.rank = graphNode.rank
|
|
2456
|
+
layoutNode.rank = (_a = graphNode.rank) != null ? _a : -1;
|
|
2378
2457
|
layoutNode.position = {
|
|
2379
2458
|
x: this.normalizeNumber(graphNode.x) + offsetX,
|
|
2380
2459
|
y: this.normalizeNumber(graphNode.y)
|
|
@@ -2388,7 +2467,7 @@ var DagreLayout = class {
|
|
|
2388
2467
|
if (!layoutNode.hasChildren) {
|
|
2389
2468
|
return 0;
|
|
2390
2469
|
}
|
|
2391
|
-
const nodeTransform = layoutNode.entity.getData(
|
|
2470
|
+
const nodeTransform = layoutNode.entity.getData(FlowNodeTransformData2);
|
|
2392
2471
|
const { bounds, padding } = nodeTransform;
|
|
2393
2472
|
const leftOffset = -bounds.width / 2 + padding.left;
|
|
2394
2473
|
return leftOffset;
|
|
@@ -2404,10 +2483,13 @@ var DagreLayout = class {
|
|
|
2404
2483
|
g.nodes().forEach((i) => {
|
|
2405
2484
|
const graphNode = g.node(i);
|
|
2406
2485
|
const layoutNode = this.store.getNodeByIndex(i);
|
|
2407
|
-
if (!graphNode || !layoutNode
|
|
2486
|
+
if (!graphNode || !(layoutNode == null ? void 0 : layoutNode.followedBy)) return;
|
|
2408
2487
|
const { followedBy } = layoutNode;
|
|
2409
2488
|
const { rank: targetRank, order: targetOrder } = graphNode;
|
|
2410
|
-
const followIndexes = followedBy.map((id) =>
|
|
2489
|
+
const followIndexes = followedBy.map((id) => {
|
|
2490
|
+
var _a;
|
|
2491
|
+
return (_a = this.store.getNode(id)) == null ? void 0 : _a.index;
|
|
2492
|
+
}).filter(Boolean);
|
|
2411
2493
|
const followSet = new Set(followIndexes);
|
|
2412
2494
|
const rankIndexes = rankGroup.get(targetRank);
|
|
2413
2495
|
if (!rankIndexes) return;
|
|
@@ -2421,12 +2503,13 @@ var DagreLayout = class {
|
|
|
2421
2503
|
graphNode2.order = graphNode2.order + followedBy.length;
|
|
2422
2504
|
});
|
|
2423
2505
|
followIndexes.forEach((followIndex, index) => {
|
|
2506
|
+
var _a, _b;
|
|
2424
2507
|
const graphNode2 = g.node(followIndex);
|
|
2425
2508
|
graphNode2.order = targetOrder + index + 1;
|
|
2426
2509
|
const originRank = graphNode2.rank;
|
|
2427
2510
|
graphNode2.rank = targetRank;
|
|
2428
|
-
rankGroup.get(originRank)
|
|
2429
|
-
rankGroup.get(targetRank)
|
|
2511
|
+
(_a = rankGroup.get(originRank)) == null ? void 0 : _a.delete(followIndex);
|
|
2512
|
+
(_b = rankGroup.get(targetRank)) == null ? void 0 : _b.add(followIndex);
|
|
2430
2513
|
});
|
|
2431
2514
|
});
|
|
2432
2515
|
}
|
|
@@ -2445,12 +2528,13 @@ var DagreLayout = class {
|
|
|
2445
2528
|
rankGroup(g) {
|
|
2446
2529
|
const rankGroup = /* @__PURE__ */ new Map();
|
|
2447
2530
|
g.nodes().forEach((i) => {
|
|
2531
|
+
var _a;
|
|
2448
2532
|
const graphNode = g.node(i);
|
|
2449
2533
|
const rank2 = graphNode.rank;
|
|
2450
2534
|
if (!rankGroup.has(rank2)) {
|
|
2451
2535
|
rankGroup.set(rank2, /* @__PURE__ */ new Set());
|
|
2452
2536
|
}
|
|
2453
|
-
rankGroup.get(rank2)
|
|
2537
|
+
(_a = rankGroup.get(rank2)) == null ? void 0 : _a.add(i);
|
|
2454
2538
|
});
|
|
2455
2539
|
return rankGroup;
|
|
2456
2540
|
}
|
|
@@ -2483,7 +2567,8 @@ var Layout = class {
|
|
|
2483
2567
|
if (!getFollowNode) return;
|
|
2484
2568
|
const context = { store: this._store };
|
|
2485
2569
|
this._store.nodes.forEach((node) => {
|
|
2486
|
-
|
|
2570
|
+
var _a;
|
|
2571
|
+
const followTo = (_a = getFollowNode(node, context)) == null ? void 0 : _a.followTo;
|
|
2487
2572
|
if (!followTo) return;
|
|
2488
2573
|
const followToNode = this._store.getNode(followTo);
|
|
2489
2574
|
if (!followToNode) return;
|
|
@@ -2502,20 +2587,26 @@ var AutoLayoutService = class {
|
|
|
2502
2587
|
await this.layoutNode(this.document.root, options);
|
|
2503
2588
|
}
|
|
2504
2589
|
async layoutNode(node, options) {
|
|
2505
|
-
const nodes = node.
|
|
2590
|
+
const nodes = node.blocks;
|
|
2506
2591
|
if (!nodes || !Array.isArray(nodes) || !nodes.length) {
|
|
2507
2592
|
return;
|
|
2508
2593
|
}
|
|
2509
|
-
const edges =
|
|
2510
|
-
const childLinesData = child.getData(WorkflowNodeLinesData);
|
|
2511
|
-
return childLinesData.outputLines.filter(Boolean);
|
|
2512
|
-
}).flat();
|
|
2594
|
+
const edges = this.getNodesAllLines(nodes);
|
|
2513
2595
|
await Promise.all(nodes.map(async (child) => this.layoutNode(child, options)));
|
|
2514
2596
|
const layout2 = new Layout();
|
|
2515
|
-
layout2.init({ nodes, edges }, options);
|
|
2597
|
+
layout2.init({ nodes, edges, container: node }, options);
|
|
2516
2598
|
layout2.layout();
|
|
2517
2599
|
await layout2.position();
|
|
2518
2600
|
}
|
|
2601
|
+
getNodesAllLines(nodes) {
|
|
2602
|
+
const lines = nodes.map((node) => {
|
|
2603
|
+
const linesData = node.getData(WorkflowNodeLinesData2);
|
|
2604
|
+
const outputLines = linesData.outputLines.filter(Boolean);
|
|
2605
|
+
const inputLines = linesData.inputLines.filter(Boolean);
|
|
2606
|
+
return [...outputLines, ...inputLines];
|
|
2607
|
+
}).flat();
|
|
2608
|
+
return lines;
|
|
2609
|
+
}
|
|
2519
2610
|
};
|
|
2520
2611
|
__decorateClass([
|
|
2521
2612
|
inject(WorkflowDocument)
|