@flowgram.ai/free-auto-layout-plugin 0.1.0-alpha.3 → 0.1.0-alpha.30

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
@@ -2081,21 +2081,47 @@ import { definePluginCreator } from "@flowgram.ai/core";
2081
2081
 
2082
2082
  // src/services.ts
2083
2083
  import { inject, injectable } from "inversify";
2084
+ import { Rectangle } from "@flowgram.ai/utils";
2084
2085
  import {
2085
2086
  WorkflowDocument,
2086
2087
  WorkflowNodeLinesData
2087
2088
  } from "@flowgram.ai/free-layout-core";
2089
+ import { Playground } from "@flowgram.ai/core";
2090
+
2091
+ // src/layout/constant.ts
2092
+ var DefaultLayoutConfig = {
2093
+ rankdir: "LR",
2094
+ align: void 0,
2095
+ nodesep: 100,
2096
+ edgesep: 10,
2097
+ ranksep: 100,
2098
+ marginx: 0,
2099
+ marginy: 0,
2100
+ acyclicer: void 0,
2101
+ ranker: "network-simplex"
2102
+ };
2103
+ var DefaultLayoutOptions = {
2104
+ filterNode: void 0,
2105
+ getFollowNode: void 0,
2106
+ disableFitView: false,
2107
+ enableAnimation: false,
2108
+ animationDuration: 300
2109
+ };
2088
2110
 
2089
2111
  // src/layout/store.ts
2090
- import { FlowNodeTransformData } from "@flowgram.ai/document";
2112
+ import { FlowNodeBaseType } from "@flowgram.ai/document";
2091
2113
  var LayoutStore = class {
2092
- constructor() {
2114
+ constructor(config) {
2115
+ this.config = config;
2093
2116
  this.init = false;
2094
2117
  }
2095
2118
  get initialized() {
2096
2119
  return this.init;
2097
2120
  }
2098
2121
  getNode(id) {
2122
+ if (!id) {
2123
+ return void 0;
2124
+ }
2099
2125
  return this.store.nodes.get(id);
2100
2126
  }
2101
2127
  getNodeByIndex(index) {
@@ -2111,56 +2137,76 @@ var LayoutStore = class {
2111
2137
  get edges() {
2112
2138
  return Array.from(this.store.edges.values());
2113
2139
  }
2114
- create(params) {
2140
+ create(params, options) {
2141
+ this.container = params.container;
2115
2142
  this.store = this.createStore(params);
2116
2143
  this.indexMap = this.createIndexMap();
2144
+ this.setOptions(options);
2117
2145
  this.init = true;
2118
2146
  }
2119
2147
  /** 创建布局数据 */
2120
2148
  createStore(params) {
2121
- const { nodes, edges } = params;
2149
+ const { layoutNodes, layoutEdges } = params;
2150
+ const virtualEdges = this.createVirtualEdges(params);
2122
2151
  const store = {
2123
2152
  nodes: /* @__PURE__ */ new Map(),
2124
2153
  edges: /* @__PURE__ */ new Map()
2125
2154
  };
2126
- nodes.forEach((node, index) => {
2127
- const { bounds } = node.getData(FlowNodeTransformData);
2128
- const layoutNode = {
2129
- id: node.id,
2130
- entity: node,
2131
- index: "",
2132
- // 初始化时,index 未计算
2133
- rank: -1,
2134
- // 初始化时,节点还未布局,层级为-1
2135
- order: -1,
2136
- // 初始化时,节点还未布局,顺序为-1
2137
- position: { x: bounds.center.x, y: bounds.center.y },
2138
- offset: { x: 0, y: 0 },
2139
- size: { width: bounds.width, height: bounds.height },
2140
- hasChildren: node.collapsedChildren?.length > 0
2141
- };
2142
- store.nodes.set(layoutNode.id, layoutNode);
2143
- });
2144
- edges.forEach((edge) => {
2145
- const { from, to } = edge.info;
2146
- if (!from || !to || edge.vertical) {
2147
- return;
2148
- }
2149
- const layoutEdge = {
2150
- id: edge.id,
2151
- entity: edge,
2152
- from,
2153
- to,
2154
- fromIndex: "",
2155
- // 初始化时,index 未计算
2156
- toIndex: "",
2157
- // 初始化时,index 未计算
2158
- name: edge.id
2159
- };
2160
- store.edges.set(layoutEdge.id, layoutEdge);
2161
- });
2155
+ layoutNodes.forEach((node) => store.nodes.set(node.id, node));
2156
+ layoutEdges.concat(virtualEdges).forEach((edge) => store.edges.set(edge.id, edge));
2162
2157
  return store;
2163
2158
  }
2159
+ /** 创建虚拟线条数据 */
2160
+ createVirtualEdges(params) {
2161
+ const { layoutNodes, layoutEdges } = params;
2162
+ const nodes = layoutNodes.map((layoutNode) => layoutNode.entity);
2163
+ const edges = layoutEdges.map((layoutEdge) => layoutEdge.entity);
2164
+ const groupNodes = nodes.filter((n) => n.flowNodeType === FlowNodeBaseType.GROUP);
2165
+ const virtualEdges = groupNodes.map((group) => {
2166
+ const { id: groupId, blocks = [] } = group;
2167
+ const blockIdSet = new Set(blocks.map((b) => b.id));
2168
+ const groupFromEdges = edges.filter((edge) => blockIdSet.has(edge.to?.id ?? "")).map((edge) => {
2169
+ const { from, to } = edge.info;
2170
+ if (!from || !to || edge.vertical) {
2171
+ return;
2172
+ }
2173
+ const id = `virtual_${groupId}_from_${from}_to_${to}`;
2174
+ const layoutEdge = {
2175
+ id,
2176
+ entity: edge,
2177
+ from,
2178
+ to: groupId,
2179
+ fromIndex: "",
2180
+ // 初始化时,index 未计算
2181
+ toIndex: "",
2182
+ // 初始化时,index 未计算
2183
+ name: id
2184
+ };
2185
+ return layoutEdge;
2186
+ }).filter(Boolean);
2187
+ const groupToEdges = edges.filter((edge) => blockIdSet.has(edge.from?.id ?? "")).map((edge) => {
2188
+ const { from, to } = edge.info;
2189
+ if (!from || !to || edge.vertical) {
2190
+ return;
2191
+ }
2192
+ const id = `virtual_${groupId}_from_${from}_to_${to}`;
2193
+ const layoutEdge = {
2194
+ id,
2195
+ entity: edge,
2196
+ from: groupId,
2197
+ to,
2198
+ fromIndex: "",
2199
+ // 初始化时,index 未计算
2200
+ toIndex: "",
2201
+ // 初始化时,index 未计算
2202
+ name: id
2203
+ };
2204
+ return layoutEdge;
2205
+ }).filter(Boolean);
2206
+ return [...groupFromEdges, ...groupToEdges];
2207
+ }).flat();
2208
+ return virtualEdges;
2209
+ }
2164
2210
  /** 创建节点索引映射 */
2165
2211
  createIndexMap() {
2166
2212
  const nodeIndexes = this.sortNodes();
@@ -2196,27 +2242,42 @@ var LayoutStore = class {
2196
2242
  this.nodes.forEach((node) => {
2197
2243
  nodeIdList.push(node.id);
2198
2244
  });
2199
- const sameFromEdges = /* @__PURE__ */ new Map();
2200
2245
  this.edges.forEach((edge) => {
2201
2246
  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
2247
  });
2207
- sameFromEdges.forEach((edges, from) => {
2208
- const sortedEdges = edges.sort((a, b) => {
2209
- const aPort = a.entity.fromPort;
2210
- const bPort = b.entity.fromPort;
2248
+ const visited = /* @__PURE__ */ new Set();
2249
+ const visit = (node) => {
2250
+ if (!node || visited.has(node.id)) {
2251
+ return;
2252
+ }
2253
+ visited.add(node.id);
2254
+ nodeIdList.push(node.id);
2255
+ node.blocks.forEach((child) => {
2256
+ visit(child);
2257
+ });
2258
+ const { outputLines } = node.lines;
2259
+ const sortedLines = outputLines.sort((a, b) => {
2260
+ const aNode = this.getNode(a.to?.id);
2261
+ const bNode = this.getNode(b.to?.id);
2262
+ const aPort = a.fromPort;
2263
+ const bPort = b.fromPort;
2264
+ if (aPort === bPort && aNode && bNode) {
2265
+ return aNode.position.y - bNode.position.y;
2266
+ }
2211
2267
  if (aPort && bPort) {
2212
2268
  return aPort.point.y - bPort.point.y;
2213
2269
  }
2214
2270
  return 0;
2215
2271
  });
2216
- sortedEdges.forEach((edge) => {
2217
- nodeIdList.push(edge.to);
2272
+ sortedLines.forEach((line) => {
2273
+ const { to } = line;
2274
+ if (!to) {
2275
+ return;
2276
+ }
2277
+ visit(to);
2218
2278
  });
2219
- });
2279
+ };
2280
+ visit(this.container.entity);
2220
2281
  const uniqueNodeIds = nodeIdList.reduceRight((acc, nodeId) => {
2221
2282
  if (!acc.includes(nodeId)) {
2222
2283
  acc.unshift(nodeId);
@@ -2225,21 +2286,52 @@ var LayoutStore = class {
2225
2286
  }, []);
2226
2287
  return uniqueNodeIds;
2227
2288
  }
2289
+ /** 记录运行选项 */
2290
+ setOptions(options) {
2291
+ this.options = options;
2292
+ this.setFollowNode(options.getFollowNode);
2293
+ }
2294
+ /** 设置跟随节点配置 */
2295
+ setFollowNode(getFollowNode) {
2296
+ if (!getFollowNode) return;
2297
+ const context = { store: this };
2298
+ this.nodes.forEach((node) => {
2299
+ const followTo = getFollowNode(node, context)?.followTo;
2300
+ if (!followTo) return;
2301
+ const followToNode = this.getNode(followTo);
2302
+ if (!followToNode) return;
2303
+ if (!followToNode.followedBy) {
2304
+ followToNode.followedBy = [];
2305
+ }
2306
+ followToNode.followedBy.push(node.id);
2307
+ node.followTo = followTo;
2308
+ });
2309
+ }
2228
2310
  };
2229
2311
 
2230
2312
  // src/layout/position.ts
2231
- import { FlowNodeTransformData as FlowNodeTransformData2 } from "@flowgram.ai/document";
2232
- import { startTween, TransformData } from "@flowgram.ai/core";
2313
+ import { startTween } from "@flowgram.ai/core";
2233
2314
  var LayoutPosition = class {
2234
2315
  constructor(store) {
2235
2316
  this.store = store;
2236
2317
  }
2237
2318
  async position() {
2319
+ if (this.store.options.enableAnimation) {
2320
+ return this.positionWithAnimation();
2321
+ }
2322
+ return this.positionDirectly();
2323
+ }
2324
+ positionDirectly() {
2325
+ this.store.nodes.forEach((layoutNode) => {
2326
+ this.updateNodePosition({ layoutNode, step: 100 });
2327
+ });
2328
+ }
2329
+ async positionWithAnimation() {
2238
2330
  return new Promise((resolve) => {
2239
2331
  startTween({
2240
2332
  from: { d: 0 },
2241
2333
  to: { d: 100 },
2242
- duration: 300,
2334
+ duration: this.store.options.animationDuration ?? 0,
2243
2335
  onUpdate: (v) => {
2244
2336
  this.store.nodes.forEach((layoutNode) => {
2245
2337
  this.updateNodePosition({ layoutNode, step: v.d });
@@ -2253,41 +2345,28 @@ var LayoutPosition = class {
2253
2345
  }
2254
2346
  updateNodePosition(params) {
2255
2347
  const { layoutNode, step } = params;
2256
- const transform = layoutNode.entity.getData(TransformData);
2257
- const position2 = {
2348
+ const { transform } = layoutNode.entity.transform;
2349
+ const layoutPosition = {
2258
2350
  x: layoutNode.position.x + layoutNode.offset.x,
2259
- y: layoutNode.position.y + layoutNode.offset.y
2351
+ // layoutNode.position.y 是中心点,但画布节点原点在上边沿的中间,所以 y 坐标需要转化后一下
2352
+ y: layoutNode.position.y + layoutNode.offset.y - (layoutNode.size.height - layoutNode.padding.top - layoutNode.padding.bottom) / 2
2353
+ };
2354
+ const deltaX = (layoutPosition.x - transform.position.x) * step / 100;
2355
+ const deltaY = (layoutPosition.y - transform.position.y) * step / 100;
2356
+ const position2 = {
2357
+ x: transform.position.x + deltaX,
2358
+ y: transform.position.y + deltaY
2260
2359
  };
2261
- const deltaX = (position2.x - transform.position.x) * step / 100;
2262
- 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
2360
  transform.update({
2270
- position: {
2271
- x: transform.position.x + deltaX,
2272
- y: transform.position.y + deltaY
2273
- }
2361
+ position: position2
2274
2362
  });
2363
+ const document = layoutNode.entity.document;
2364
+ document.layout.updateAffectedTransform(layoutNode.entity);
2275
2365
  }
2276
2366
  };
2277
2367
 
2278
2368
  // src/layout/dagre.ts
2279
- import { FlowNodeTransformData as FlowNodeTransformData3 } from "@flowgram.ai/document";
2280
2369
  import { Graph as DagreGraph } from "@dagrejs/graphlib";
2281
-
2282
- // src/layout/constant.ts
2283
- var DagreLayoutOptions = {
2284
- rankdir: "LR",
2285
- nodesep: 100,
2286
- ranksep: 100,
2287
- ranker: "network-simplex"
2288
- };
2289
-
2290
- // src/layout/dagre.ts
2291
2370
  var DagreLayout = class {
2292
2371
  constructor(store) {
2293
2372
  this.store = store;
@@ -2336,17 +2415,11 @@ var DagreLayout = class {
2336
2415
  createGraph() {
2337
2416
  const graph = new DagreGraph({ multigraph: true });
2338
2417
  graph.setDefaultEdgeLabel(() => ({}));
2339
- graph.setGraph(DagreLayoutOptions);
2418
+ graph.setGraph(this.store.config);
2340
2419
  return graph;
2341
2420
  }
2342
2421
  graphSetData() {
2343
- const nodes = Array.from(this.store.nodes.values());
2344
- const edges = Array.from(this.store.edges.values()).sort((next, prev) => {
2345
- if (next.fromIndex === prev.fromIndex) {
2346
- return next.toIndex < prev.toIndex ? -1 : 1;
2347
- }
2348
- return next.fromIndex < prev.fromIndex ? -1 : 1;
2349
- });
2422
+ const { nodes, edges } = this.store;
2350
2423
  nodes.forEach((layoutNode) => {
2351
2424
  this.graph.setNode(layoutNode.index, {
2352
2425
  originID: layoutNode.id,
@@ -2354,7 +2427,12 @@ var DagreLayout = class {
2354
2427
  height: layoutNode.size.height
2355
2428
  });
2356
2429
  });
2357
- edges.forEach((layoutEdge) => {
2430
+ edges.sort((next, prev) => {
2431
+ if (next.fromIndex === prev.fromIndex) {
2432
+ return next.toIndex < prev.toIndex ? -1 : 1;
2433
+ }
2434
+ return next.fromIndex < prev.fromIndex ? -1 : 1;
2435
+ }).forEach((layoutEdge) => {
2358
2436
  this.graph.setEdge({
2359
2437
  v: layoutEdge.fromIndex,
2360
2438
  w: layoutEdge.toIndex,
@@ -2385,12 +2463,11 @@ var DagreLayout = class {
2385
2463
  return Number.isNaN(number) ? 0 : number;
2386
2464
  }
2387
2465
  getOffsetX(layoutNode) {
2388
- if (!layoutNode.hasChildren) {
2466
+ if (layoutNode.layoutNodes.length === 0) {
2389
2467
  return 0;
2390
2468
  }
2391
- const nodeTransform = layoutNode.entity.getData(FlowNodeTransformData3);
2392
- const { bounds, padding } = nodeTransform;
2393
- const leftOffset = -bounds.width / 2 + padding.left;
2469
+ const { padding } = layoutNode;
2470
+ const leftOffset = -layoutNode.size.width / 2 + padding.left;
2394
2471
  return leftOffset;
2395
2472
  }
2396
2473
  setOrderAndRank(g) {
@@ -2458,14 +2535,13 @@ var DagreLayout = class {
2458
2535
 
2459
2536
  // src/layout/layout.ts
2460
2537
  var Layout = class {
2461
- constructor() {
2462
- this._store = new LayoutStore();
2538
+ constructor(config) {
2539
+ this._store = new LayoutStore(config);
2463
2540
  this._layout = new DagreLayout(this._store);
2464
2541
  this._position = new LayoutPosition(this._store);
2465
2542
  }
2466
- init(params, options = {}) {
2467
- this._store.create(params);
2468
- this.setFollowNode(options.getFollowNode);
2543
+ init(params, options) {
2544
+ this._store.create(params, options);
2469
2545
  }
2470
2546
  layout() {
2471
2547
  if (!this._store.initialized) {
@@ -2479,44 +2555,144 @@ var Layout = class {
2479
2555
  }
2480
2556
  return await this._position.position();
2481
2557
  }
2482
- setFollowNode(getFollowNode) {
2483
- if (!getFollowNode) return;
2484
- const context = { store: this._store };
2485
- this._store.nodes.forEach((node) => {
2486
- const followTo = getFollowNode(node, context)?.followTo;
2487
- if (!followTo) return;
2488
- const followToNode = this._store.getNode(followTo);
2489
- if (!followToNode) return;
2490
- if (!followToNode.followedBy) {
2491
- followToNode.followedBy = [];
2492
- }
2493
- followToNode.followedBy.push(node.id);
2494
- node.followTo = followTo;
2495
- });
2496
- }
2497
2558
  };
2498
2559
 
2499
2560
  // src/services.ts
2500
2561
  var AutoLayoutService = class {
2562
+ constructor() {
2563
+ this.layoutConfig = DefaultLayoutConfig;
2564
+ }
2565
+ init(options) {
2566
+ this.layoutConfig = {
2567
+ ...this.layoutConfig,
2568
+ ...options.layoutConfig
2569
+ };
2570
+ }
2501
2571
  async layout(options = {}) {
2502
- await this.layoutNode(this.document.root, options);
2572
+ const layoutOptions = {
2573
+ ...DefaultLayoutOptions,
2574
+ ...options
2575
+ };
2576
+ const containerNode = layoutOptions.containerNode ?? this.document.root;
2577
+ const container = this.createLayoutNode(containerNode, options);
2578
+ const layouts = await this.layoutNode(container, layoutOptions);
2579
+ const rect = this.getLayoutNodeRect(container);
2580
+ const positionPromise = layouts.map((layout2) => layout2.position());
2581
+ const fitViewPromise = this.fitView(layoutOptions, rect);
2582
+ await Promise.all([...positionPromise, fitViewPromise]);
2583
+ }
2584
+ async fitView(options, rect) {
2585
+ if (options.disableFitView === true) {
2586
+ return;
2587
+ }
2588
+ return this.playground.config.fitView(rect, options.enableAnimation, 30);
2503
2589
  }
2504
- async layoutNode(node, options) {
2505
- const nodes = node.collapsedChildren;
2506
- if (!nodes || !Array.isArray(nodes) || !nodes.length) {
2590
+ async layoutNode(container, options) {
2591
+ const { layoutNodes, layoutEdges } = container;
2592
+ if (layoutNodes.length === 0) {
2593
+ return [];
2594
+ }
2595
+ const childrenLayouts = (await Promise.all(layoutNodes.map((n) => this.layoutNode(n, options)))).flat();
2596
+ const layoutConfig = {
2597
+ ...this.layoutConfig,
2598
+ ...options.layoutConfig
2599
+ };
2600
+ const layout2 = new Layout(layoutConfig);
2601
+ layout2.init({ container, layoutNodes, layoutEdges }, options);
2602
+ layout2.layout();
2603
+ const rect = this.getLayoutNodeRect(container);
2604
+ container.size = {
2605
+ width: rect.width,
2606
+ height: rect.height
2607
+ };
2608
+ return [...childrenLayouts, layout2];
2609
+ }
2610
+ createLayoutNodes(nodes, options) {
2611
+ return nodes.map((node) => this.createLayoutNode(node, options));
2612
+ }
2613
+ /** 创建节点布局数据 */
2614
+ createLayoutNode(node, options) {
2615
+ const blocks = node.blocks.filter(
2616
+ (blockNode) => options.filterNode ? options.filterNode?.({ node: blockNode, parent: node.parent }) : true
2617
+ );
2618
+ const edges = this.getNodesAllLines(blocks).filter(
2619
+ (edge) => options.filterLine ? options.filterLine?.({ line: edge }) : true
2620
+ );
2621
+ const layoutNodes = this.createLayoutNodes(blocks, options);
2622
+ const layoutEdges = this.createLayoutEdges(edges);
2623
+ const { bounds, padding } = node.transform;
2624
+ const { width: width2, height, center } = bounds;
2625
+ const { x, y } = center;
2626
+ const layoutNode = {
2627
+ id: node.id,
2628
+ entity: node,
2629
+ index: "",
2630
+ // 初始化时,index 未计算
2631
+ rank: -1,
2632
+ // 初始化时,节点还未布局,层级为-1
2633
+ order: -1,
2634
+ // 初始化时,节点还未布局,顺序为-1
2635
+ position: { x, y },
2636
+ offset: { x: 0, y: 0 },
2637
+ padding,
2638
+ size: { width: width2, height },
2639
+ layoutNodes,
2640
+ layoutEdges
2641
+ };
2642
+ return layoutNode;
2643
+ }
2644
+ createLayoutEdges(edges) {
2645
+ const layoutEdges = edges.map((edge) => this.createLayoutEdge(edge)).filter(Boolean);
2646
+ return layoutEdges;
2647
+ }
2648
+ /** 创建线条布局数据 */
2649
+ createLayoutEdge(edge) {
2650
+ const { from, to } = edge.info;
2651
+ if (!from || !to) {
2507
2652
  return;
2508
2653
  }
2509
- const edges = node.collapsedChildren.map((child) => {
2510
- const childLinesData = child.getData(WorkflowNodeLinesData);
2511
- return childLinesData.outputLines.filter(Boolean);
2654
+ const layoutEdge = {
2655
+ id: edge.id,
2656
+ entity: edge,
2657
+ from,
2658
+ to,
2659
+ fromIndex: "",
2660
+ // 初始化时,index 未计算
2661
+ toIndex: "",
2662
+ // 初始化时,index 未计算
2663
+ name: edge.id
2664
+ };
2665
+ return layoutEdge;
2666
+ }
2667
+ getNodesAllLines(nodes) {
2668
+ const lines = nodes.map((node) => {
2669
+ const linesData = node.getData(WorkflowNodeLinesData);
2670
+ const outputLines = linesData.outputLines.filter(Boolean);
2671
+ const inputLines = linesData.inputLines.filter(Boolean);
2672
+ return [...outputLines, ...inputLines];
2512
2673
  }).flat();
2513
- await Promise.all(nodes.map(async (child) => this.layoutNode(child, options)));
2514
- const layout2 = new Layout();
2515
- layout2.init({ nodes, edges }, options);
2516
- layout2.layout();
2517
- await layout2.position();
2674
+ return lines;
2675
+ }
2676
+ getLayoutNodeRect(layoutNode) {
2677
+ const rects = layoutNode.layoutNodes.map((node) => this.layoutNodeRect(node));
2678
+ const rect = Rectangle.enlarge(rects);
2679
+ const { padding } = layoutNode;
2680
+ const width2 = rect.width + padding.left + padding.right;
2681
+ const height = rect.height + padding.top + padding.bottom;
2682
+ const x = rect.x - padding.left;
2683
+ const y = rect.y - padding.top;
2684
+ return new Rectangle(x, y, width2, height);
2685
+ }
2686
+ layoutNodeRect(layoutNode) {
2687
+ const { width: width2, height } = layoutNode.size;
2688
+ const x = layoutNode.position.x - width2 / 2;
2689
+ const y = layoutNode.position.y - height / 2;
2690
+ return new Rectangle(x, y, width2, height);
2518
2691
  }
2519
2692
  };
2693
+ __decorateClass([
2694
+ inject(Playground)
2695
+ ], AutoLayoutService.prototype, "playground", 2);
2520
2696
  __decorateClass([
2521
2697
  inject(WorkflowDocument)
2522
2698
  ], AutoLayoutService.prototype, "document", 2);
@@ -2528,7 +2704,11 @@ AutoLayoutService = __decorateClass([
2528
2704
  var createFreeAutoLayoutPlugin = definePluginCreator({
2529
2705
  onBind: ({ bind }) => {
2530
2706
  bind(AutoLayoutService).toSelf().inSingletonScope();
2531
- }
2707
+ },
2708
+ onInit: (ctx, opts) => {
2709
+ ctx.get(AutoLayoutService).init(opts);
2710
+ },
2711
+ singleton: true
2532
2712
  });
2533
2713
 
2534
2714
  // src/index.ts
@@ -2536,6 +2716,7 @@ import { Graph as Graph8 } from "@dagrejs/graphlib";
2536
2716
  export {
2537
2717
  AutoLayoutService,
2538
2718
  Graph8 as DagreGraph,
2719
+ DefaultLayoutConfig,
2539
2720
  Layout,
2540
2721
  createFreeAutoLayoutPlugin,
2541
2722
  dagreLib