@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 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 { FlowNodeTransformData } from "@flowgram.ai/document";
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
- nodes.forEach((node, index) => {
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?.length > 0
2154
+ hasChildren: ((_a = node.collapsedChildren) == null ? void 0 : _a.length) > 0
2141
2155
  };
2142
- store.nodes.set(layoutNode.id, layoutNode);
2156
+ return layoutNode;
2143
2157
  });
2144
- edges.forEach((edge) => {
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
- store.edges.set(layoutEdge.id, layoutEdge);
2161
- });
2162
- return store;
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
- sameFromEdges.forEach((edges, from) => {
2208
- const sortedEdges = edges.sort((a, b) => {
2209
- const aPort = a.entity.fromPort;
2210
- const bPort = b.entity.fromPort;
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
- sortedEdges.forEach((edge) => {
2217
- nodeIdList.push(edge.to);
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 FlowNodeTransformData3 } from "@flowgram.ai/document";
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 ?? -1;
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(FlowNodeTransformData3);
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?.followedBy) return;
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) => this.store.getNode(id)?.index).filter(Boolean);
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)?.delete(followIndex);
2429
- rankGroup.get(targetRank)?.add(followIndex);
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)?.add(i);
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
- const followTo = getFollowNode(node, context)?.followTo;
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.collapsedChildren;
2590
+ const nodes = node.blocks;
2506
2591
  if (!nodes || !Array.isArray(nodes) || !nodes.length) {
2507
2592
  return;
2508
2593
  }
2509
- const edges = node.collapsedChildren.map((child) => {
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)