@logicflow/layout 2.1.0-alpha.2 → 2.1.0-alpha.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.
Files changed (47) hide show
  1. package/.turbo/turbo-build.log +7 -6
  2. package/CHANGELOG.md +15 -0
  3. package/README.md +9 -2
  4. package/dist/index.min.js +1 -1
  5. package/dist/index.min.js.map +1 -1
  6. package/es/{dagre.d.ts → dagre/index.d.ts} +18 -20
  7. package/es/dagre/index.js +126 -0
  8. package/es/dagre/index.js.map +1 -0
  9. package/es/elkLayout/config.d.ts +26 -0
  10. package/es/elkLayout/config.js +27 -0
  11. package/es/elkLayout/config.js.map +1 -0
  12. package/es/elkLayout/index.d.ts +107 -0
  13. package/es/elkLayout/index.js +187 -0
  14. package/es/elkLayout/index.js.map +1 -0
  15. package/es/index.d.ts +1 -0
  16. package/es/index.js +1 -0
  17. package/es/index.js.map +1 -1
  18. package/es/utils/processEdge.d.ts +3 -0
  19. package/es/utils/processEdge.js +479 -0
  20. package/es/utils/processEdge.js.map +1 -0
  21. package/lib/{dagre.d.ts → dagre/index.d.ts} +18 -20
  22. package/lib/dagre/index.js +152 -0
  23. package/lib/dagre/index.js.map +1 -0
  24. package/lib/elkLayout/config.d.ts +26 -0
  25. package/lib/elkLayout/config.js +30 -0
  26. package/lib/elkLayout/config.js.map +1 -0
  27. package/lib/elkLayout/index.d.ts +107 -0
  28. package/lib/elkLayout/index.js +193 -0
  29. package/lib/elkLayout/index.js.map +1 -0
  30. package/lib/index.d.ts +1 -0
  31. package/lib/index.js +1 -0
  32. package/lib/index.js.map +1 -1
  33. package/lib/utils/processEdge.d.ts +3 -0
  34. package/lib/utils/processEdge.js +483 -0
  35. package/lib/utils/processEdge.js.map +1 -0
  36. package/package.json +3 -2
  37. package/src/dagre/index.ts +177 -0
  38. package/src/elkLayout/config.ts +26 -0
  39. package/src/elkLayout/index.ts +255 -0
  40. package/src/index.ts +2 -0
  41. package/src/utils/processEdge.ts +585 -0
  42. package/stats.html +1 -1
  43. package/es/dagre.js +0 -376
  44. package/es/dagre.js.map +0 -1
  45. package/lib/dagre.js +0 -402
  46. package/lib/dagre.js.map +0 -1
  47. package/src/dagre.ts +0 -438
@@ -4,10 +4,14 @@
4
4
  * 本插件基于dagre.js实现LogicFlow的自动化布局功能,支持多种布局方向
5
5
  * 可自动计算节点位置和连线路径,实现整洁的图形展示
6
6
  */
7
- import LogicFlow, { BaseEdgeModel } from '@logicflow/core';
7
+ import LogicFlow, { BaseNodeModel, BaseEdgeModel } from '@logicflow/core';
8
8
  import { GraphLabel } from 'dagre';
9
- import NodeConfig = LogicFlow.NodeConfig;
10
- import Point = LogicFlow.Point;
9
+ type BaseNodeData = {
10
+ x: number;
11
+ y: number;
12
+ width: number;
13
+ height: number;
14
+ };
11
15
  /**
12
16
  * Dagre布局配置选项接口
13
17
  * @interface DagreOption
@@ -52,22 +56,16 @@ export declare class Dagre {
52
56
  */
53
57
  layout(option?: DagreOption): void;
54
58
  /**
55
- * 计算字符串显示宽度(用于文本定位)
56
- * @param word - 要计算的文本
57
- * @returns 估算的文本像素宽度
59
+ * 使用 Dagre 布局
60
+ * @param nodes - 节点数据
61
+ * @param edges - 边数据
58
62
  */
59
- getBytesLength(word: string): number;
60
- /**
61
- * 优化折线路径点,移除冗余点
62
- * @param points - 原始路径点数组
63
- * @returns 优化后的路径点数组
64
- */
65
- pointFilter(points: Point[]): Point[];
66
- /**
67
- * 计算边的折线路径点
68
- * @param model - 边模型
69
- * @param nodes - 节点数据数组
70
- * @returns 计算后的路径点数组,如果无法计算则返回undefined
71
- */
72
- calcPointsList(model: BaseEdgeModel, nodes: NodeConfig[]): Point[] | undefined;
63
+ applyDagreLayout(nodes: BaseNodeModel[], edges: BaseEdgeModel[]): void;
64
+ convertLayoutDataToLf(nodes: BaseNodeModel[], edges: BaseEdgeModel[], layoutData: {
65
+ node: (id: string) => BaseNodeData;
66
+ }): {
67
+ nodes: LogicFlow.NodeConfig<LogicFlow.PropertiesType>[];
68
+ edges: LogicFlow.EdgeConfig<LogicFlow.PropertiesType>[];
69
+ };
73
70
  }
71
+ export {};
@@ -0,0 +1,126 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ import dagre, { graphlib } from 'dagre';
13
+ import { processEdges } from '../utils/processEdge';
14
+ /**
15
+ * Dagre布局类 - LogicFlow自动布局插件
16
+ * 基于dagre.js提供图的自动布局能力
17
+ */
18
+ var Dagre = /** @class */ (function () {
19
+ function Dagre() {
20
+ }
21
+ /**
22
+ * 插件初始化方法,由LogicFlow自动调用
23
+ * @param lf - LogicFlow实例
24
+ */
25
+ Dagre.prototype.render = function (lf) {
26
+ this.lf = lf;
27
+ };
28
+ /**
29
+ * 执行布局算法,重新排列图中的节点和边
30
+ * @param option - 布局配置选项
31
+ */
32
+ Dagre.prototype.layout = function (option) {
33
+ if (option === void 0) { option = {}; }
34
+ var _a = this.lf.graphModel, nodes = _a.nodes, edges = _a.edges, gridSize = _a.gridSize;
35
+ // 根据网格大小调整节点间距
36
+ var nodesep = 100;
37
+ var ranksep = 150;
38
+ if (gridSize > 20) {
39
+ nodesep = gridSize * 2;
40
+ ranksep = gridSize * 2;
41
+ }
42
+ // 合并默认配置和用户配置
43
+ this.option = __assign({
44
+ // 默认从左到右布局
45
+ rankdir: 'LR',
46
+ // 默认右下角对齐
47
+ align: 'UL',
48
+ // 紧凑树形排名算法
49
+ ranker: 'tight-tree',
50
+ // 层级间距
51
+ ranksep: ranksep,
52
+ // 同层节点间距
53
+ nodesep: nodesep,
54
+ // 图的水平边距
55
+ marginx: 120,
56
+ // 图的垂直边距
57
+ marginy: 120 }, option);
58
+ this.applyDagreLayout(nodes, edges);
59
+ };
60
+ /**
61
+ * 使用 Dagre 布局
62
+ * @param nodes - 节点数据
63
+ * @param edges - 边数据
64
+ */
65
+ Dagre.prototype.applyDagreLayout = function (nodes, edges) {
66
+ // 创建dagre图实例
67
+ var g = new graphlib.Graph();
68
+ // dagre布局配置
69
+ g.setGraph(this.option);
70
+ //构造dagre布局数据
71
+ g.setDefaultEdgeLabel(function () { return ({}); });
72
+ nodes.forEach(function (node) {
73
+ g.setNode(node.id, {
74
+ width: node.width || 150,
75
+ height: node.height || 50,
76
+ id: node.id,
77
+ });
78
+ });
79
+ edges.forEach(function (edge) {
80
+ g.setEdge(edge.sourceNodeId, edge.targetNodeId, {
81
+ id: edge.id,
82
+ });
83
+ });
84
+ // 开始dagre布局
85
+ try {
86
+ dagre.layout(g);
87
+ var newGraphData = this.convertLayoutDataToLf(nodes, edges, g);
88
+ this.lf.renderRawData(newGraphData);
89
+ }
90
+ catch (error) {
91
+ console.error('Dagre layout error:', error);
92
+ }
93
+ };
94
+ Dagre.prototype.convertLayoutDataToLf = function (nodes, edges, layoutData) {
95
+ // 存储新的节点和边数据
96
+ var newNodes = [];
97
+ // 更新节点位置
98
+ nodes.forEach(function (nodeModel) {
99
+ var _a;
100
+ var lfNode = nodeModel.getData();
101
+ var newNode = layoutData.node(nodeModel.id);
102
+ if (!lfNode || !newNode) {
103
+ throw new Error("\u5E03\u5C40\u9519\u8BEF\uFF1A\u627E\u4E0D\u5230ID\u4E3A ".concat(nodeModel.id, " \u7684\u8282\u70B9"));
104
+ }
105
+ // 更新节点坐标
106
+ lfNode.x = newNode.x;
107
+ lfNode.y = newNode.y;
108
+ // 更新节点文本位置
109
+ if ((_a = lfNode === null || lfNode === void 0 ? void 0 : lfNode.text) === null || _a === void 0 ? void 0 : _a.x) {
110
+ lfNode.text.x = newNode.x;
111
+ lfNode.text.y = newNode.y;
112
+ }
113
+ newNodes.push(lfNode);
114
+ });
115
+ var newEdges = processEdges(this.lf, this.option.rankdir, this.option.isDefaultAnchor, edges, newNodes);
116
+ return {
117
+ nodes: newNodes,
118
+ edges: newEdges,
119
+ };
120
+ };
121
+ /** 插件名称,用于在LogicFlow中注册 */
122
+ Dagre.pluginName = 'dagre';
123
+ return Dagre;
124
+ }());
125
+ export { Dagre };
126
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/dagre/index.ts"],"names":[],"mappings":";;;;;;;;;;;AAOA,OAAO,KAAK,EAAE,EAAc,QAAQ,EAAE,MAAM,OAAO,CAAA;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAoCnD;;;GAGG;AACH;IAAA;IAgIA,CAAC;IAtHC;;;OAGG;IACH,sBAAM,GAAN,UAAO,EAAa;QAClB,IAAI,CAAC,EAAE,GAAG,EAAE,CAAA;IACd,CAAC;IAED;;;OAGG;IACH,sBAAM,GAAN,UAAO,MAAwB;QAAxB,uBAAA,EAAA,WAAwB;QACvB,IAAA,KAA6B,IAAI,CAAC,EAAE,CAAC,UAAU,EAA7C,KAAK,WAAA,EAAE,KAAK,WAAA,EAAE,QAAQ,cAAuB,CAAA;QAErD,eAAe;QACf,IAAI,OAAO,GAAG,GAAG,CAAA;QACjB,IAAI,OAAO,GAAG,GAAG,CAAA;QACjB,IAAI,QAAQ,GAAG,EAAE,EAAE,CAAC;YAClB,OAAO,GAAG,QAAQ,GAAG,CAAC,CAAA;YACtB,OAAO,GAAG,QAAQ,GAAG,CAAC,CAAA;QACxB,CAAC;QAED,cAAc;QACd,IAAI,CAAC,MAAM;YACT,WAAW;YACX,OAAO,EAAE,IAAI;YACb,UAAU;YACV,KAAK,EAAE,IAAI;YACX,WAAW;YACX,MAAM,EAAE,YAAY;YACpB,OAAO;YACP,OAAO,SAAA;YACP,SAAS;YACT,OAAO,SAAA;YACP,SAAS;YACT,OAAO,EAAE,GAAG;YACZ,SAAS;YACT,OAAO,EAAE,GAAG,IAET,MAAM,CACV,CAAA;QACD,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;IACrC,CAAC;IAED;;;;OAIG;IACH,gCAAgB,GAAhB,UAAiB,KAAsB,EAAE,KAAsB;QAC7D,aAAa;QACb,IAAM,CAAC,GAAG,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAA;QAC9B,YAAY;QACZ,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACvB,aAAa;QACb,CAAC,CAAC,mBAAmB,CAAC,cAAM,OAAA,CAAC,EAAE,CAAC,EAAJ,CAAI,CAAC,CAAA;QACjC,KAAK,CAAC,OAAO,CAAC,UAAC,IAAmB;YAChC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE;gBACjB,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,GAAG;gBACxB,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,EAAE;gBACzB,EAAE,EAAE,IAAI,CAAC,EAAE;aACZ,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;QACF,KAAK,CAAC,OAAO,CAAC,UAAC,IAAmB;YAChC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE;gBAC9C,EAAE,EAAE,IAAI,CAAC,EAAE;aACZ,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;QACF,YAAY;QACZ,IAAI,CAAC;YACH,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;YACf,IAAM,YAAY,GAAG,IAAI,CAAC,qBAAqB,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;YAChE,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,YAAY,CAAC,CAAA;QACrC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAA;QAC7C,CAAC;IACH,CAAC;IACD,qCAAqB,GAArB,UACE,KAAsB,EACtB,KAAsB,EACtB,UAAkD;QAElD,aAAa;QACb,IAAM,QAAQ,GAAiB,EAAE,CAAA;QAEjC,SAAS;QACT,KAAK,CAAC,OAAO,CAAC,UAAC,SAAS;;YACtB,IAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,CAAA;YAClC,IAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;YAC7C,IAAI,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CAAC,mEAAe,SAAS,CAAC,EAAE,wBAAM,CAAC,CAAA;YACpD,CAAC;YACD,SAAS;YACT,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAA;YACpB,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAA;YAEpB,WAAW;YACX,IAAI,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,0CAAE,CAAC,EAAE,CAAC;gBACpB,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAA;gBACzB,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAA;YAC3B,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACvB,CAAC,CAAC,CAAA;QAEF,IAAM,QAAQ,GAAiB,YAAY,CACzC,IAAI,CAAC,EAAE,EACP,IAAI,CAAC,MAAM,CAAC,OAAO,EACnB,IAAI,CAAC,MAAM,CAAC,eAAe,EAC3B,KAAK,EACL,QAAQ,CACT,CAAA;QAED,OAAO;YACL,KAAK,EAAE,QAAQ;YACf,KAAK,EAAE,QAAQ;SAChB,CAAA;IACH,CAAC;IA9HD,2BAA2B;IACpB,gBAAU,GAAG,OAAO,CAAA;IA8H7B,YAAC;CAAA,AAhID,IAgIC;SAhIY,KAAK"}
@@ -0,0 +1,26 @@
1
+ export declare const elkOptionMap: {
2
+ rankdir: {
3
+ LR: string;
4
+ TB: string;
5
+ BT: string;
6
+ RL: string;
7
+ default: string;
8
+ };
9
+ align: {
10
+ UL: string;
11
+ UR: string;
12
+ DL: string;
13
+ DR: string;
14
+ default: string;
15
+ };
16
+ ranker: {
17
+ 'network-simplex': string;
18
+ 'tight-tree': string;
19
+ 'longest-path': string;
20
+ default: string;
21
+ };
22
+ acyclicer: {
23
+ greedy: string;
24
+ default: string;
25
+ };
26
+ };
@@ -0,0 +1,27 @@
1
+ export var elkOptionMap = {
2
+ rankdir: {
3
+ LR: 'RIGHT',
4
+ TB: 'DOWN',
5
+ BT: 'UP',
6
+ RL: 'LEFT',
7
+ default: 'RIGHT',
8
+ },
9
+ align: {
10
+ UL: 'RIGHTDOWN',
11
+ UR: 'RIGHTUP',
12
+ DL: 'LEFTDOWN',
13
+ DR: 'LEFTUP',
14
+ default: 'BALANCED',
15
+ },
16
+ ranker: {
17
+ 'network-simplex': 'NETWORK_SIMPLEX',
18
+ 'tight-tree': 'NETWORK_SIMPLEX',
19
+ 'longest-path': 'LONGEST_PATH',
20
+ default: 'NETWORK_SIMPLEX',
21
+ },
22
+ acyclicer: {
23
+ greedy: 'GREEDY',
24
+ default: 'DEPTH_FIRST',
25
+ },
26
+ };
27
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/elkLayout/config.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,IAAM,YAAY,GAAG;IAC1B,OAAO,EAAE;QACP,EAAE,EAAE,OAAO;QACX,EAAE,EAAE,MAAM;QACV,EAAE,EAAE,IAAI;QACR,EAAE,EAAE,MAAM;QACV,OAAO,EAAE,OAAO;KACjB;IACD,KAAK,EAAE;QACL,EAAE,EAAE,WAAW;QACf,EAAE,EAAE,SAAS;QACb,EAAE,EAAE,UAAU;QACd,EAAE,EAAE,QAAQ;QACZ,OAAO,EAAE,UAAU;KACpB;IACD,MAAM,EAAE;QACN,iBAAiB,EAAE,iBAAiB;QACpC,YAAY,EAAE,iBAAiB;QAC/B,cAAc,EAAE,cAAc;QAC9B,OAAO,EAAE,iBAAiB;KAC3B;IACD,SAAS,EAAE;QACT,MAAM,EAAE,QAAQ;QAChB,OAAO,EAAE,aAAa;KACvB;CACF,CAAA"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * @fileoverview ElkLayout布局插件 - 提供自动化图形布局功能
3
+ *
4
+ * 本插件基于elkjs实现LogicFlow的自动化布局功能,支持多种布局方向
5
+ * 可自动计算节点位置和连线路径,实现整洁的图形展示
6
+ */
7
+ import LogicFlow, { BaseNodeModel, BaseEdgeModel } from '@logicflow/core';
8
+ import { LayoutOptions, ElkNode } from 'elkjs/lib/elk-api';
9
+ /**
10
+ * ElkLayout布局配置选项接口
11
+ * @interface ElkLayoutOption
12
+ */
13
+ export interface ElkLayoutOption {
14
+ /**
15
+ * 布局方向
16
+ * 'LR' | 'TB' | 'BT' | 'RL'
17
+ */
18
+ rankdir?: 'LR' | 'TB' | 'BT' | 'RL';
19
+ /**
20
+ * 对齐方式
21
+ * 'UL' | 'UR' | 'DL' | 'DR'
22
+ */
23
+ align?: 'UL' | 'UR' | 'DL' | 'DR';
24
+ /**
25
+ * 同层节点间距
26
+ */
27
+ nodesep?: number;
28
+ /**
29
+ * 层级间距
30
+ */
31
+ ranksep?: number;
32
+ /**
33
+ * 图的水平边距
34
+ */
35
+ marginx?: number;
36
+ /**
37
+ * 图的垂直边距
38
+ */
39
+ marginy?: number;
40
+ /**
41
+ * 排版算法
42
+ * 'network-simplex' | 'tight-tree' | 'longest-path'
43
+ */
44
+ ranker?: 'network-simplex' | 'tight-tree' | 'longest-path';
45
+ /**
46
+ * 边间距
47
+ */
48
+ edgesep?: number;
49
+ /**
50
+ * 有向无环图处理算法
51
+ * 'greedy'
52
+ */
53
+ acyclicer?: 'greedy';
54
+ /**
55
+ * 是否是默认锚点
56
+ * true: 会根据布局方向自动计算边的路径点
57
+ */
58
+ isDefaultAnchor?: boolean;
59
+ /**
60
+ * ELK 原生布局属性,用于覆盖默认配置
61
+ */
62
+ elkOption?: LayoutOptions;
63
+ }
64
+ /**
65
+ * ElkLayout插件接口定义
66
+ */
67
+ export interface ElkLayoutPlugin {
68
+ /**
69
+ * 执行布局计算
70
+ * @param option - 布局配置选项
71
+ */
72
+ layout(option: ElkLayoutOption): void;
73
+ }
74
+ /**
75
+ * ElkLayout布局类 - LogicFlow自动布局插件
76
+ * 基于elkjs提供图的自动布局能力
77
+ */
78
+ export declare class ElkLayout {
79
+ /** 插件名称,用于在LogicFlow中注册 */
80
+ static pluginName: string;
81
+ /** LogicFlow实例引用 */
82
+ lf: LogicFlow;
83
+ /** 当前布局配置 */
84
+ option: ElkLayoutOption;
85
+ /**
86
+ * 插件初始化方法,由LogicFlow自动调用
87
+ * @param lf - LogicFlow实例
88
+ */
89
+ render(lf: LogicFlow): void;
90
+ /**
91
+ * 执行布局算法,重新排列图中的节点和边
92
+ * @param option - 布局配置选项
93
+ */
94
+ layout(option?: ElkLayoutOption): void;
95
+ /**
96
+ * 使用 ELK 布局
97
+ * @param nodes - 节点数据
98
+ * @param edges - 边数据
99
+ * @param elkOption - ELK 配置选项
100
+ */
101
+ applyElkLayout(nodes: BaseNodeModel[], edges: BaseEdgeModel[]): Promise<void>;
102
+ convertOptionsToElk(): LayoutOptions;
103
+ convertLayoutDataToLf(nodes: BaseNodeModel[], edges: BaseEdgeModel[], layoutData: ElkNode): {
104
+ nodes: LogicFlow.NodeConfig<LogicFlow.PropertiesType>[];
105
+ edges: LogicFlow.EdgeConfig<LogicFlow.PropertiesType>[];
106
+ };
107
+ }
@@ -0,0 +1,187 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
13
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
14
+ return new (P || (P = Promise))(function (resolve, reject) {
15
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
16
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
17
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
18
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
19
+ });
20
+ };
21
+ var __generator = (this && this.__generator) || function (thisArg, body) {
22
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
23
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
24
+ function verb(n) { return function (v) { return step([n, v]); }; }
25
+ function step(op) {
26
+ if (f) throw new TypeError("Generator is already executing.");
27
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
28
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
29
+ if (y = 0, t) op = [op[0] & 2, t.value];
30
+ switch (op[0]) {
31
+ case 0: case 1: t = op; break;
32
+ case 4: _.label++; return { value: op[1], done: false };
33
+ case 5: _.label++; y = op[1]; op = [0]; continue;
34
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
35
+ default:
36
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
37
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
38
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
39
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
40
+ if (t[2]) _.ops.pop();
41
+ _.trys.pop(); continue;
42
+ }
43
+ op = body.call(thisArg, _);
44
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
45
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
46
+ }
47
+ };
48
+ import elkConstructor from 'elkjs/lib/elk.bundled';
49
+ import { processEdges } from '../utils/processEdge';
50
+ import { elkOptionMap } from './config';
51
+ /**
52
+ * ElkLayout布局类 - LogicFlow自动布局插件
53
+ * 基于elkjs提供图的自动布局能力
54
+ */
55
+ var ElkLayout = /** @class */ (function () {
56
+ function ElkLayout() {
57
+ }
58
+ /**
59
+ * 插件初始化方法,由LogicFlow自动调用
60
+ * @param lf - LogicFlow实例
61
+ */
62
+ ElkLayout.prototype.render = function (lf) {
63
+ this.lf = lf;
64
+ };
65
+ /**
66
+ * 执行布局算法,重新排列图中的节点和边
67
+ * @param option - 布局配置选项
68
+ */
69
+ ElkLayout.prototype.layout = function (option) {
70
+ if (option === void 0) { option = {}; }
71
+ var _a = this.lf.graphModel, nodes = _a.nodes, edges = _a.edges, gridSize = _a.gridSize;
72
+ // 根据网格大小调整节点间距
73
+ var nodesep = 100;
74
+ var ranksep = 150;
75
+ if (gridSize > 20) {
76
+ nodesep = gridSize * 2;
77
+ ranksep = gridSize * 2;
78
+ }
79
+ // 合并默认配置和用户配置
80
+ this.option = __assign({
81
+ // 默认从左到右布局
82
+ rankdir: 'LR',
83
+ // 默认右下角对齐
84
+ align: 'UL',
85
+ // 紧凑树形排名算法
86
+ ranker: 'tight-tree',
87
+ // 层级间距
88
+ ranksep: ranksep,
89
+ // 同层节点间距
90
+ nodesep: nodesep,
91
+ // 图的水平边距
92
+ marginx: 120,
93
+ // 图的垂直边距
94
+ marginy: 120 }, option);
95
+ this.applyElkLayout(nodes, edges);
96
+ };
97
+ /**
98
+ * 使用 ELK 布局
99
+ * @param nodes - 节点数据
100
+ * @param edges - 边数据
101
+ * @param elkOption - ELK 配置选项
102
+ */
103
+ ElkLayout.prototype.applyElkLayout = function (nodes, edges) {
104
+ return __awaiter(this, void 0, void 0, function () {
105
+ var elk, layoutOptions, elkGraph, elkLayoutGraph, newGraphData, error_1;
106
+ return __generator(this, function (_a) {
107
+ switch (_a.label) {
108
+ case 0:
109
+ elk = new elkConstructor();
110
+ layoutOptions = this.convertOptionsToElk();
111
+ elkGraph = {
112
+ id: 'root',
113
+ children: nodes.map(function (node) { return ({
114
+ id: node.id,
115
+ width: node.width || 150,
116
+ height: node.height || 50,
117
+ }); }),
118
+ edges: edges.map(function (edge) { return ({
119
+ id: edge.id,
120
+ sources: [edge.sourceNodeId],
121
+ targets: [edge.targetNodeId],
122
+ }); }),
123
+ };
124
+ _a.label = 1;
125
+ case 1:
126
+ _a.trys.push([1, 3, , 4]);
127
+ return [4 /*yield*/, elk.layout(elkGraph, { layoutOptions: layoutOptions })];
128
+ case 2:
129
+ elkLayoutGraph = _a.sent();
130
+ newGraphData = this.convertLayoutDataToLf(nodes, edges, elkLayoutGraph);
131
+ this.lf.renderRawData(newGraphData);
132
+ return [3 /*break*/, 4];
133
+ case 3:
134
+ error_1 = _a.sent();
135
+ console.error('ELK layout error:', error_1);
136
+ return [3 /*break*/, 4];
137
+ case 4: return [2 /*return*/];
138
+ }
139
+ });
140
+ });
141
+ };
142
+ ElkLayout.prototype.convertOptionsToElk = function () {
143
+ // elk布局配置
144
+ var rankdir = (this.option.rankdir ||
145
+ 'default');
146
+ var align = (this.option.align ||
147
+ 'default');
148
+ var ranker = (this.option.ranker ||
149
+ 'default');
150
+ var acyclicer = (this.option.acyclicer ||
151
+ 'default');
152
+ var layoutOptions = __assign({ 'elk.algorithm': 'layered', 'elk.direction': elkOptionMap.rankdir[rankdir] || elkOptionMap.rankdir.default, 'elk.layered.nodePlacement.bk.fixedAlignment': elkOptionMap.align[align] || elkOptionMap.align.default, 'elk.layered.layering.strategy': elkOptionMap.ranker[ranker] || elkOptionMap.ranker.default, 'elk.layered.cycleBreaking.strategy': elkOptionMap.acyclicer[acyclicer] || elkOptionMap.acyclicer.default, 'elk.padding': "[top=".concat(this.option.marginx || 20, ", left=").concat(this.option.marginy || 20, ", bottom=").concat(this.option.marginx || 20, ", right=").concat(this.option.marginy || 20, "]"), 'elk.spacing.nodeNode': "".concat(this.option.nodesep || 50), 'elk.spacing.edgeEdge': "".concat(this.option.edgesep || 10), 'elk.layered.spacing.nodeNodeBetweenLayers': "".concat(this.option.ranksep || 100), 'elk.layered.considerModelOrder.strategy': 'NODES_AND_EDGES', 'elk.layered.nodePlacement.strategy': 'BRANDES_KOEPF' }, this.option.elkOption);
153
+ return layoutOptions;
154
+ };
155
+ ElkLayout.prototype.convertLayoutDataToLf = function (nodes, edges, layoutData) {
156
+ // 存储新的节点和边数据
157
+ var newNodes = [];
158
+ // 更新节点位置
159
+ nodes.forEach(function (nodeModel) {
160
+ var _a;
161
+ var lfNode = nodeModel.getData();
162
+ var newNode = ((layoutData === null || layoutData === void 0 ? void 0 : layoutData.children) || []).find(function (n) { return n.id === nodeModel.id; });
163
+ if (!lfNode || !newNode || !newNode.x || !newNode.y) {
164
+ throw new Error("\u5E03\u5C40\u9519\u8BEF\uFF1A\u627E\u4E0D\u5230ID\u4E3A ".concat(nodeModel.id, " \u7684\u8282\u70B9"));
165
+ }
166
+ // 更新节点坐标
167
+ lfNode.x = newNode.x + nodeModel.width / 2;
168
+ lfNode.y = newNode.y + nodeModel.height / 2;
169
+ // 更新节点文本位置
170
+ if ((_a = lfNode === null || lfNode === void 0 ? void 0 : lfNode.text) === null || _a === void 0 ? void 0 : _a.x) {
171
+ lfNode.text.x = newNode.x + nodeModel.width / 2;
172
+ lfNode.text.y = newNode.y + nodeModel.height / 2;
173
+ }
174
+ newNodes.push(lfNode);
175
+ });
176
+ var newEdges = processEdges(this.lf, this.option.rankdir, this.option.isDefaultAnchor, edges, newNodes);
177
+ return {
178
+ nodes: newNodes,
179
+ edges: newEdges,
180
+ };
181
+ };
182
+ /** 插件名称,用于在LogicFlow中注册 */
183
+ ElkLayout.pluginName = 'elkLayout';
184
+ return ElkLayout;
185
+ }());
186
+ export { ElkLayout };
187
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/elkLayout/index.ts"],"names":[],"mappings":"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"}
package/es/index.d.ts CHANGED
@@ -1 +1,2 @@
1
1
  export * from './dagre';
2
+ export * from './elkLayout';
package/es/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from './dagre';
2
+ export * from './elkLayout';
2
3
  //# sourceMappingURL=index.js.map
package/es/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AAEvB,cAAc,aAAa,CAAA"}
@@ -0,0 +1,3 @@
1
+ import LogicFlow, { BaseEdgeModel } from '@logicflow/core';
2
+ import NodeConfig = LogicFlow.NodeConfig;
3
+ export declare function processEdges(lf: LogicFlow, rankdir: string | undefined, isDefaultAnchor: boolean | undefined, edges: BaseEdgeModel[], newNodes: NodeConfig[]): LogicFlow.EdgeConfig<LogicFlow.PropertiesType>[];