@flowgram.ai/free-auto-layout-plugin 0.1.0-alpha.15 → 0.1.0-alpha.16
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 +138 -93
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +77 -42
- package/dist/index.d.ts +77 -42
- package/dist/index.js +142 -95
- package/dist/index.js.map +1 -1
- package/package.json +11 -13
package/dist/index.js
CHANGED
|
@@ -26,8 +26,8 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
// src/index.ts
|
|
29
|
-
var
|
|
30
|
-
__export(
|
|
29
|
+
var index_exports = {};
|
|
30
|
+
__export(index_exports, {
|
|
31
31
|
AutoLayoutService: () => AutoLayoutService,
|
|
32
32
|
DagreGraph: () => import_graphlib10.Graph,
|
|
33
33
|
DefaultLayoutConfig: () => DefaultLayoutConfig,
|
|
@@ -35,7 +35,7 @@ __export(src_exports, {
|
|
|
35
35
|
createFreeAutoLayoutPlugin: () => createFreeAutoLayoutPlugin,
|
|
36
36
|
dagreLib: () => dagreLib
|
|
37
37
|
});
|
|
38
|
-
module.exports = __toCommonJS(
|
|
38
|
+
module.exports = __toCommonJS(index_exports);
|
|
39
39
|
|
|
40
40
|
// src/dagre-lib/greedy-fas.js
|
|
41
41
|
var import_graphlib = require("@dagrejs/graphlib");
|
|
@@ -2105,11 +2105,13 @@ var dagreLib = {
|
|
|
2105
2105
|
};
|
|
2106
2106
|
|
|
2107
2107
|
// src/create-auto-layout-plugin.tsx
|
|
2108
|
-
var
|
|
2108
|
+
var import_core3 = require("@flowgram.ai/core");
|
|
2109
2109
|
|
|
2110
2110
|
// src/services.ts
|
|
2111
2111
|
var import_inversify = require("inversify");
|
|
2112
|
-
var
|
|
2112
|
+
var import_utils = require("@flowgram.ai/utils");
|
|
2113
|
+
var import_free_layout_core = require("@flowgram.ai/free-layout-core");
|
|
2114
|
+
var import_core2 = require("@flowgram.ai/core");
|
|
2113
2115
|
|
|
2114
2116
|
// src/layout/constant.ts
|
|
2115
2117
|
var DefaultLayoutConfig = {
|
|
@@ -2125,11 +2127,12 @@ var DefaultLayoutConfig = {
|
|
|
2125
2127
|
};
|
|
2126
2128
|
var DefaultLayoutOptions = {
|
|
2127
2129
|
getFollowNode: void 0,
|
|
2128
|
-
|
|
2130
|
+
disableFitView: false,
|
|
2131
|
+
enableAnimation: false,
|
|
2132
|
+
animationDuration: 300
|
|
2129
2133
|
};
|
|
2130
2134
|
|
|
2131
2135
|
// src/layout/store.ts
|
|
2132
|
-
var import_free_layout_core = require("@flowgram.ai/free-layout-core");
|
|
2133
2136
|
var import_document = require("@flowgram.ai/document");
|
|
2134
2137
|
var LayoutStore = class {
|
|
2135
2138
|
constructor(config) {
|
|
@@ -2159,6 +2162,7 @@ var LayoutStore = class {
|
|
|
2159
2162
|
return Array.from(this.store.edges.values());
|
|
2160
2163
|
}
|
|
2161
2164
|
create(params, options) {
|
|
2165
|
+
this.container = params.container;
|
|
2162
2166
|
this.store = this.createStore(params);
|
|
2163
2167
|
this.indexMap = this.createIndexMap();
|
|
2164
2168
|
this.setOptions(options);
|
|
@@ -2166,10 +2170,7 @@ var LayoutStore = class {
|
|
|
2166
2170
|
}
|
|
2167
2171
|
/** 创建布局数据 */
|
|
2168
2172
|
createStore(params) {
|
|
2169
|
-
const {
|
|
2170
|
-
this.container = container;
|
|
2171
|
-
const layoutNodes = this.createLayoutNodes(nodes);
|
|
2172
|
-
const layoutEdges = this.createEdgesStore(edges);
|
|
2173
|
+
const { layoutNodes, layoutEdges } = params;
|
|
2173
2174
|
const virtualEdges = this.createVirtualEdges(params);
|
|
2174
2175
|
const store = {
|
|
2175
2176
|
nodes: /* @__PURE__ */ new Map(),
|
|
@@ -2179,53 +2180,11 @@ var LayoutStore = class {
|
|
|
2179
2180
|
layoutEdges.concat(virtualEdges).forEach((edge) => store.edges.set(edge.id, edge));
|
|
2180
2181
|
return store;
|
|
2181
2182
|
}
|
|
2182
|
-
/** 创建节点布局数据 */
|
|
2183
|
-
createLayoutNodes(nodes) {
|
|
2184
|
-
const layoutNodes = nodes.map((node, index) => {
|
|
2185
|
-
const { bounds } = node.getData(import_document.FlowNodeTransformData);
|
|
2186
|
-
const layoutNode = {
|
|
2187
|
-
id: node.id,
|
|
2188
|
-
entity: node,
|
|
2189
|
-
index: "",
|
|
2190
|
-
// 初始化时,index 未计算
|
|
2191
|
-
rank: -1,
|
|
2192
|
-
// 初始化时,节点还未布局,层级为-1
|
|
2193
|
-
order: -1,
|
|
2194
|
-
// 初始化时,节点还未布局,顺序为-1
|
|
2195
|
-
position: { x: bounds.center.x, y: bounds.center.y },
|
|
2196
|
-
offset: { x: 0, y: 0 },
|
|
2197
|
-
size: { width: bounds.width, height: bounds.height },
|
|
2198
|
-
hasChildren: node.collapsedChildren?.length > 0
|
|
2199
|
-
};
|
|
2200
|
-
return layoutNode;
|
|
2201
|
-
});
|
|
2202
|
-
return layoutNodes;
|
|
2203
|
-
}
|
|
2204
|
-
/** 创建线条布局数据 */
|
|
2205
|
-
createEdgesStore(edges) {
|
|
2206
|
-
const layoutEdges = edges.map((edge) => {
|
|
2207
|
-
const { from, to } = edge.info;
|
|
2208
|
-
if (!from || !to || edge.vertical) {
|
|
2209
|
-
return;
|
|
2210
|
-
}
|
|
2211
|
-
const layoutEdge = {
|
|
2212
|
-
id: edge.id,
|
|
2213
|
-
entity: edge,
|
|
2214
|
-
from,
|
|
2215
|
-
to,
|
|
2216
|
-
fromIndex: "",
|
|
2217
|
-
// 初始化时,index 未计算
|
|
2218
|
-
toIndex: "",
|
|
2219
|
-
// 初始化时,index 未计算
|
|
2220
|
-
name: edge.id
|
|
2221
|
-
};
|
|
2222
|
-
return layoutEdge;
|
|
2223
|
-
}).filter(Boolean);
|
|
2224
|
-
return layoutEdges;
|
|
2225
|
-
}
|
|
2226
2183
|
/** 创建虚拟线条数据 */
|
|
2227
2184
|
createVirtualEdges(params) {
|
|
2228
|
-
const {
|
|
2185
|
+
const { layoutNodes, layoutEdges } = params;
|
|
2186
|
+
const nodes = layoutNodes.map((layoutNode) => layoutNode.entity);
|
|
2187
|
+
const edges = layoutEdges.map((layoutEdge) => layoutEdge.entity);
|
|
2229
2188
|
const groupNodes = nodes.filter((n) => n.flowNodeType === import_document.FlowNodeBaseType.GROUP);
|
|
2230
2189
|
const virtualEdges = groupNodes.map((group) => {
|
|
2231
2190
|
const { id: groupId, blocks = [] } = group;
|
|
@@ -2312,7 +2271,7 @@ var LayoutStore = class {
|
|
|
2312
2271
|
});
|
|
2313
2272
|
const visited = /* @__PURE__ */ new Set();
|
|
2314
2273
|
const visit = (node) => {
|
|
2315
|
-
if (visited.has(node.id)) {
|
|
2274
|
+
if (!node || visited.has(node.id)) {
|
|
2316
2275
|
return;
|
|
2317
2276
|
}
|
|
2318
2277
|
visited.add(node.id);
|
|
@@ -2320,7 +2279,7 @@ var LayoutStore = class {
|
|
|
2320
2279
|
node.blocks.forEach((child) => {
|
|
2321
2280
|
visit(child);
|
|
2322
2281
|
});
|
|
2323
|
-
const { outputLines } = node.
|
|
2282
|
+
const { outputLines } = node.lines;
|
|
2324
2283
|
const sortedLines = outputLines.sort((a, b) => {
|
|
2325
2284
|
const aNode = this.getNode(a.to?.id);
|
|
2326
2285
|
const bNode = this.getNode(b.to?.id);
|
|
@@ -2342,7 +2301,7 @@ var LayoutStore = class {
|
|
|
2342
2301
|
visit(to);
|
|
2343
2302
|
});
|
|
2344
2303
|
};
|
|
2345
|
-
visit(this.container);
|
|
2304
|
+
visit(this.container.entity);
|
|
2346
2305
|
const uniqueNodeIds = nodeIdList.reduceRight((acc, nodeId) => {
|
|
2347
2306
|
if (!acc.includes(nodeId)) {
|
|
2348
2307
|
acc.unshift(nodeId);
|
|
@@ -2396,7 +2355,7 @@ var LayoutPosition = class {
|
|
|
2396
2355
|
(0, import_core.startTween)({
|
|
2397
2356
|
from: { d: 0 },
|
|
2398
2357
|
to: { d: 100 },
|
|
2399
|
-
duration:
|
|
2358
|
+
duration: this.store.options.animationDuration ?? 0,
|
|
2400
2359
|
onUpdate: (v) => {
|
|
2401
2360
|
this.store.nodes.forEach((layoutNode) => {
|
|
2402
2361
|
this.updateNodePosition({ layoutNode, step: v.d });
|
|
@@ -2410,18 +2369,20 @@ var LayoutPosition = class {
|
|
|
2410
2369
|
}
|
|
2411
2370
|
updateNodePosition(params) {
|
|
2412
2371
|
const { layoutNode, step } = params;
|
|
2413
|
-
const transform = layoutNode.entity.
|
|
2414
|
-
const
|
|
2372
|
+
const { transform } = layoutNode.entity.transform;
|
|
2373
|
+
const layoutPosition = {
|
|
2415
2374
|
x: layoutNode.position.x + layoutNode.offset.x,
|
|
2416
|
-
|
|
2375
|
+
// layoutNode.position.y 是中心点,但画布节点原点在上边沿的中间,所以 y 坐标需要转化后一下
|
|
2376
|
+
y: layoutNode.position.y - layoutNode.size.height / 2 + layoutNode.offset.y
|
|
2377
|
+
};
|
|
2378
|
+
const deltaX = (layoutPosition.x - transform.position.x) * step / 100;
|
|
2379
|
+
const deltaY = (layoutPosition.y - transform.position.y) * step / 100;
|
|
2380
|
+
const position2 = {
|
|
2381
|
+
x: transform.position.x + deltaX,
|
|
2382
|
+
y: transform.position.y + deltaY
|
|
2417
2383
|
};
|
|
2418
|
-
const deltaX = (position2.x - transform.position.x) * step / 100;
|
|
2419
|
-
const deltaY = (position2.y - transform.bounds.height / 2 - transform.position.y) * step / 100;
|
|
2420
2384
|
transform.update({
|
|
2421
|
-
position:
|
|
2422
|
-
x: transform.position.x + deltaX,
|
|
2423
|
-
y: transform.position.y + deltaY
|
|
2424
|
-
}
|
|
2385
|
+
position: position2
|
|
2425
2386
|
});
|
|
2426
2387
|
const document = layoutNode.entity.document;
|
|
2427
2388
|
document.layout.updateAffectedTransform(layoutNode.entity);
|
|
@@ -2429,7 +2390,6 @@ var LayoutPosition = class {
|
|
|
2429
2390
|
};
|
|
2430
2391
|
|
|
2431
2392
|
// src/layout/dagre.ts
|
|
2432
|
-
var import_document2 = require("@flowgram.ai/document");
|
|
2433
2393
|
var import_graphlib9 = require("@dagrejs/graphlib");
|
|
2434
2394
|
var DagreLayout = class {
|
|
2435
2395
|
constructor(store) {
|
|
@@ -2483,13 +2443,7 @@ var DagreLayout = class {
|
|
|
2483
2443
|
return graph;
|
|
2484
2444
|
}
|
|
2485
2445
|
graphSetData() {
|
|
2486
|
-
const nodes =
|
|
2487
|
-
const edges = Array.from(this.store.edges.values()).sort((next, prev) => {
|
|
2488
|
-
if (next.fromIndex === prev.fromIndex) {
|
|
2489
|
-
return next.toIndex < prev.toIndex ? -1 : 1;
|
|
2490
|
-
}
|
|
2491
|
-
return next.fromIndex < prev.fromIndex ? -1 : 1;
|
|
2492
|
-
});
|
|
2446
|
+
const { nodes, edges } = this.store;
|
|
2493
2447
|
nodes.forEach((layoutNode) => {
|
|
2494
2448
|
this.graph.setNode(layoutNode.index, {
|
|
2495
2449
|
originID: layoutNode.id,
|
|
@@ -2497,7 +2451,12 @@ var DagreLayout = class {
|
|
|
2497
2451
|
height: layoutNode.size.height
|
|
2498
2452
|
});
|
|
2499
2453
|
});
|
|
2500
|
-
edges.
|
|
2454
|
+
edges.sort((next, prev) => {
|
|
2455
|
+
if (next.fromIndex === prev.fromIndex) {
|
|
2456
|
+
return next.toIndex < prev.toIndex ? -1 : 1;
|
|
2457
|
+
}
|
|
2458
|
+
return next.fromIndex < prev.fromIndex ? -1 : 1;
|
|
2459
|
+
}).forEach((layoutEdge) => {
|
|
2501
2460
|
this.graph.setEdge({
|
|
2502
2461
|
v: layoutEdge.fromIndex,
|
|
2503
2462
|
w: layoutEdge.toIndex,
|
|
@@ -2528,12 +2487,11 @@ var DagreLayout = class {
|
|
|
2528
2487
|
return Number.isNaN(number) ? 0 : number;
|
|
2529
2488
|
}
|
|
2530
2489
|
getOffsetX(layoutNode) {
|
|
2531
|
-
if (
|
|
2490
|
+
if (layoutNode.layoutNodes.length === 0) {
|
|
2532
2491
|
return 0;
|
|
2533
2492
|
}
|
|
2534
|
-
const
|
|
2535
|
-
const
|
|
2536
|
-
const leftOffset = -bounds.width / 2 + padding.left;
|
|
2493
|
+
const { padding } = layoutNode;
|
|
2494
|
+
const leftOffset = -layoutNode.size.width / 2 + padding.left;
|
|
2537
2495
|
return leftOffset;
|
|
2538
2496
|
}
|
|
2539
2497
|
setOrderAndRank(g) {
|
|
@@ -2635,42 +2593,131 @@ var AutoLayoutService = class {
|
|
|
2635
2593
|
};
|
|
2636
2594
|
}
|
|
2637
2595
|
async layout(options = {}) {
|
|
2638
|
-
|
|
2596
|
+
const layoutOptions = {
|
|
2639
2597
|
...DefaultLayoutOptions,
|
|
2640
2598
|
...options
|
|
2641
|
-
}
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
const
|
|
2645
|
-
|
|
2599
|
+
};
|
|
2600
|
+
const containerNode = layoutOptions.containerNode ?? this.document.root;
|
|
2601
|
+
const container = this.createLayoutNode(containerNode, options);
|
|
2602
|
+
const layouts = await this.layoutNode(container, layoutOptions);
|
|
2603
|
+
const rect = this.getLayoutNodeRect(container);
|
|
2604
|
+
const positionPromise = layouts.map((layout2) => layout2.position());
|
|
2605
|
+
const fitViewPromise = this.fitView(layoutOptions, rect);
|
|
2606
|
+
await Promise.all([...positionPromise, fitViewPromise]);
|
|
2607
|
+
}
|
|
2608
|
+
async fitView(options, rect) {
|
|
2609
|
+
if (options.disableFitView === true) {
|
|
2646
2610
|
return;
|
|
2647
2611
|
}
|
|
2648
|
-
|
|
2649
|
-
|
|
2612
|
+
return this.playground.config.fitView(rect, options.enableAnimation, 30);
|
|
2613
|
+
}
|
|
2614
|
+
async layoutNode(container, options) {
|
|
2615
|
+
const { layoutNodes, layoutEdges } = container;
|
|
2616
|
+
if (layoutNodes.length === 0) {
|
|
2617
|
+
return [];
|
|
2618
|
+
}
|
|
2619
|
+
const childrenLayouts = (await Promise.all(layoutNodes.map((n) => this.layoutNode(n, options)))).flat();
|
|
2650
2620
|
const layout2 = new Layout(this.layoutConfig);
|
|
2651
|
-
layout2.init({
|
|
2621
|
+
layout2.init({ container, layoutNodes, layoutEdges }, options);
|
|
2652
2622
|
layout2.layout();
|
|
2653
|
-
|
|
2623
|
+
const rect = this.getLayoutNodeRect(container);
|
|
2624
|
+
container.size = {
|
|
2625
|
+
width: rect.width,
|
|
2626
|
+
height: rect.height
|
|
2627
|
+
};
|
|
2628
|
+
return [...childrenLayouts, layout2];
|
|
2629
|
+
}
|
|
2630
|
+
createLayoutNodes(nodes, options) {
|
|
2631
|
+
return nodes.map((node) => this.createLayoutNode(node, options));
|
|
2632
|
+
}
|
|
2633
|
+
/** 创建节点布局数据 */
|
|
2634
|
+
createLayoutNode(node, options) {
|
|
2635
|
+
const { blocks } = node;
|
|
2636
|
+
const edges = this.getNodesAllLines(blocks);
|
|
2637
|
+
const layoutNodes = this.createLayoutNodes(blocks, options);
|
|
2638
|
+
const layoutEdges = this.createLayoutEdges(edges);
|
|
2639
|
+
const { bounds, padding } = node.transform;
|
|
2640
|
+
const { width: width2, height, center } = bounds;
|
|
2641
|
+
const { x, y } = center;
|
|
2642
|
+
const layoutNode = {
|
|
2643
|
+
id: node.id,
|
|
2644
|
+
entity: node,
|
|
2645
|
+
index: "",
|
|
2646
|
+
// 初始化时,index 未计算
|
|
2647
|
+
rank: -1,
|
|
2648
|
+
// 初始化时,节点还未布局,层级为-1
|
|
2649
|
+
order: -1,
|
|
2650
|
+
// 初始化时,节点还未布局,顺序为-1
|
|
2651
|
+
position: { x, y },
|
|
2652
|
+
offset: { x: 0, y: 0 },
|
|
2653
|
+
padding,
|
|
2654
|
+
size: { width: width2, height },
|
|
2655
|
+
layoutNodes,
|
|
2656
|
+
layoutEdges
|
|
2657
|
+
};
|
|
2658
|
+
return layoutNode;
|
|
2659
|
+
}
|
|
2660
|
+
createLayoutEdges(edges) {
|
|
2661
|
+
const layoutEdges = edges.map((edge) => this.createLayoutEdge(edge)).filter(Boolean);
|
|
2662
|
+
return layoutEdges;
|
|
2663
|
+
}
|
|
2664
|
+
/** 创建线条布局数据 */
|
|
2665
|
+
createLayoutEdge(edge) {
|
|
2666
|
+
const { from, to } = edge.info;
|
|
2667
|
+
if (!from || !to || edge.vertical) {
|
|
2668
|
+
return;
|
|
2669
|
+
}
|
|
2670
|
+
const layoutEdge = {
|
|
2671
|
+
id: edge.id,
|
|
2672
|
+
entity: edge,
|
|
2673
|
+
from,
|
|
2674
|
+
to,
|
|
2675
|
+
fromIndex: "",
|
|
2676
|
+
// 初始化时,index 未计算
|
|
2677
|
+
toIndex: "",
|
|
2678
|
+
// 初始化时,index 未计算
|
|
2679
|
+
name: edge.id
|
|
2680
|
+
};
|
|
2681
|
+
return layoutEdge;
|
|
2654
2682
|
}
|
|
2655
2683
|
getNodesAllLines(nodes) {
|
|
2656
2684
|
const lines = nodes.map((node) => {
|
|
2657
|
-
const linesData = node.getData(
|
|
2685
|
+
const linesData = node.getData(import_free_layout_core.WorkflowNodeLinesData);
|
|
2658
2686
|
const outputLines = linesData.outputLines.filter(Boolean);
|
|
2659
2687
|
const inputLines = linesData.inputLines.filter(Boolean);
|
|
2660
2688
|
return [...outputLines, ...inputLines];
|
|
2661
2689
|
}).flat();
|
|
2662
2690
|
return lines;
|
|
2663
2691
|
}
|
|
2692
|
+
getLayoutNodeRect(layoutNode) {
|
|
2693
|
+
const rects = layoutNode.layoutNodes.map((node) => this.layoutNodeRect(node));
|
|
2694
|
+
const rect = import_utils.Rectangle.enlarge(rects);
|
|
2695
|
+
const { padding } = layoutNode;
|
|
2696
|
+
const width2 = rect.width + padding.left + padding.right;
|
|
2697
|
+
const height = rect.height + padding.top + padding.bottom;
|
|
2698
|
+
const x = rect.x - padding.left;
|
|
2699
|
+
const y = rect.y - padding.top;
|
|
2700
|
+
return new import_utils.Rectangle(x, y, width2, height);
|
|
2701
|
+
}
|
|
2702
|
+
layoutNodeRect(layoutNode) {
|
|
2703
|
+
const { width: width2, height } = layoutNode.size;
|
|
2704
|
+
const x = layoutNode.position.x - width2 / 2;
|
|
2705
|
+
const y = layoutNode.position.y - height / 2;
|
|
2706
|
+
return new import_utils.Rectangle(x, y, width2, height);
|
|
2707
|
+
}
|
|
2664
2708
|
};
|
|
2665
2709
|
__decorateClass([
|
|
2666
|
-
(0, import_inversify.inject)(
|
|
2710
|
+
(0, import_inversify.inject)(import_core2.Playground)
|
|
2711
|
+
], AutoLayoutService.prototype, "playground", 2);
|
|
2712
|
+
__decorateClass([
|
|
2713
|
+
(0, import_inversify.inject)(import_free_layout_core.WorkflowDocument)
|
|
2667
2714
|
], AutoLayoutService.prototype, "document", 2);
|
|
2668
2715
|
AutoLayoutService = __decorateClass([
|
|
2669
2716
|
(0, import_inversify.injectable)()
|
|
2670
2717
|
], AutoLayoutService);
|
|
2671
2718
|
|
|
2672
2719
|
// src/create-auto-layout-plugin.tsx
|
|
2673
|
-
var createFreeAutoLayoutPlugin = (0,
|
|
2720
|
+
var createFreeAutoLayoutPlugin = (0, import_core3.definePluginCreator)({
|
|
2674
2721
|
onBind: ({ bind }) => {
|
|
2675
2722
|
bind(AutoLayoutService).toSelf().inSingletonScope();
|
|
2676
2723
|
},
|