@flowgram.ai/free-stack-plugin 0.1.0-alpha.2 → 0.1.0-alpha.20

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
@@ -13,31 +13,34 @@ var __decorateClass = (decorators, target, key, kind) => {
13
13
  import { definePluginCreator } from "@flowgram.ai/core";
14
14
 
15
15
  // src/manager.ts
16
- import { debounce } from "lodash";
16
+ import { debounce } from "lodash-es";
17
17
  import { inject, injectable } from "inversify";
18
- import { FlowNodeRenderData as FlowNodeRenderData2 } from "@flowgram.ai/document";
19
- import { EntityManager, PipelineRegistry, PipelineRenderer } from "@flowgram.ai/core";
18
+ import { domUtils } from "@flowgram.ai/utils";
20
19
  import {
21
20
  WorkflowHoverService,
22
21
  WorkflowNodeEntity as WorkflowNodeEntity2,
23
22
  WorkflowSelectService
24
23
  } from "@flowgram.ai/free-layout-core";
25
- import { WorkflowLineEntity } from "@flowgram.ai/free-layout-core";
24
+ import { WorkflowLineEntity as WorkflowLineEntity2 } from "@flowgram.ai/free-layout-core";
26
25
  import { WorkflowDocument } from "@flowgram.ai/free-layout-core";
27
- import { domUtils } from "@flowgram.ai/utils";
26
+ import { FlowNodeRenderData } from "@flowgram.ai/document";
27
+ import { EntityManager, PipelineRegistry, PipelineRenderer } from "@flowgram.ai/core";
28
28
 
29
29
  // src/stacking-computing.ts
30
+ import {
31
+ WorkflowNodeLinesData
32
+ } from "@flowgram.ai/free-layout-core";
30
33
  import { FlowNodeBaseType } from "@flowgram.ai/document";
31
- import { WorkflowNodeLinesData } from "@flowgram.ai/free-layout-core";
32
34
  var StackingComputing = class {
33
35
  compute(params) {
34
36
  this.clearCache();
35
37
  const { root, nodes, context } = params;
36
38
  this.context = context;
37
39
  this.nodeIndexes = this.computeNodeIndexesMap(nodes);
40
+ this.selectedNodeParentSet = this.computeSelectedNodeParentSet(nodes);
38
41
  this.topLevel = this.computeTopLevel(nodes);
39
42
  this.maxLevel = this.topLevel * 2;
40
- this.layerHandler(root.collapsedChildren);
43
+ this.layerHandler(root.blocks);
41
44
  return {
42
45
  nodeLevel: this.nodeLevel,
43
46
  lineLevel: this.lineLevel,
@@ -60,10 +63,25 @@ var StackingComputing = class {
60
63
  });
61
64
  return nodeIndexMap;
62
65
  }
66
+ computeSelectedNodeParentSet(nodes) {
67
+ const selectedNodeParents = this.context.selectedNodes.flatMap(
68
+ (node) => this.getNodeParents(node)
69
+ );
70
+ return new Set(selectedNodeParents.map((node) => node.id));
71
+ }
72
+ getNodeParents(node) {
73
+ const nodes = [];
74
+ let currentNode = node;
75
+ while (currentNode && currentNode.flowNodeType !== FlowNodeBaseType.ROOT) {
76
+ nodes.unshift(currentNode);
77
+ currentNode = currentNode.parent;
78
+ }
79
+ return nodes;
80
+ }
63
81
  computeTopLevel(nodes) {
64
82
  const nodesWithoutRoot = nodes.filter((node) => node.id !== FlowNodeBaseType.ROOT);
65
83
  const nodeHasChildren = nodesWithoutRoot.reduce((count, node) => {
66
- if (node.collapsedChildren.length > 0) {
84
+ if (node.blocks.length > 0) {
67
85
  return count + 1;
68
86
  } else {
69
87
  return count;
@@ -71,44 +89,69 @@ var StackingComputing = class {
71
89
  }, 0);
72
90
  return nodesWithoutRoot.length + nodeHasChildren + 1;
73
91
  }
74
- layerHandler(nodes, pinTop = false) {
75
- const sortedNodes = nodes.sort((a, b) => {
76
- const aIndex = this.nodeIndexes.get(a.id);
77
- const bIndex = this.nodeIndexes.get(b.id);
78
- if (aIndex === void 0 || bIndex === void 0) {
79
- return 0;
80
- }
81
- return aIndex - bIndex;
82
- });
83
- const lines = nodes.map((node) => {
84
- const linesData = node.getData(WorkflowNodeLinesData);
85
- const outputLines = linesData.outputLines.filter(Boolean);
86
- const inputLines = linesData.inputLines.filter(Boolean);
87
- return [...outputLines, ...inputLines];
88
- }).flat();
92
+ layerHandler(layerNodes, pinTop = false) {
93
+ const nodes = this.sortNodes(layerNodes);
94
+ const lines = this.getNodesAllLines(nodes);
89
95
  lines.forEach((line) => {
90
96
  if (line.isDrawing || // 正在绘制
91
97
  this.context.hoveredEntityID === line.id || // hover
92
- this.context.selectedIDs.includes(line.id)) {
98
+ this.context.selectedIDs.has(line.id)) {
93
99
  this.lineLevel.set(line.id, this.maxLevel);
94
100
  } else {
95
101
  this.lineLevel.set(line.id, this.getLevel(pinTop));
96
102
  }
97
103
  });
98
104
  this.levelIncrease();
99
- sortedNodes.forEach((node) => {
100
- const selected = this.context.selectedIDs.includes(node.id);
105
+ nodes.forEach((node) => {
106
+ const selected = this.context.selectedIDs.has(node.id);
101
107
  if (selected) {
102
108
  this.nodeLevel.set(node.id, this.topLevel);
103
109
  } else {
104
110
  this.nodeLevel.set(node.id, this.getLevel(pinTop));
105
111
  }
106
112
  this.levelIncrease();
107
- if (node.collapsedChildren.length > 0) {
108
- this.layerHandler(node.collapsedChildren, pinTop || selected);
113
+ if (node.blocks.length > 0) {
114
+ this.layerHandler(node.blocks, pinTop || selected);
115
+ }
116
+ });
117
+ }
118
+ sortNodes(nodes) {
119
+ const baseSortNodes = nodes.sort((a, b) => {
120
+ const aIndex = this.nodeIndexes.get(a.id);
121
+ const bIndex = this.nodeIndexes.get(b.id);
122
+ if (aIndex === void 0 || bIndex === void 0) {
123
+ return 0;
124
+ }
125
+ return aIndex - bIndex;
126
+ });
127
+ const contextSortNodes = this.context.sortNodes(baseSortNodes);
128
+ return contextSortNodes.sort((a, b) => {
129
+ const aIsSelectedParent = this.selectedNodeParentSet.has(a.id);
130
+ const bIsSelectedParent = this.selectedNodeParentSet.has(b.id);
131
+ if (aIsSelectedParent && !bIsSelectedParent) {
132
+ return 1;
133
+ } else if (!aIsSelectedParent && bIsSelectedParent) {
134
+ return -1;
135
+ } else {
136
+ return 0;
109
137
  }
110
138
  });
111
139
  }
140
+ getNodesAllLines(nodes) {
141
+ const lines = nodes.map((node) => {
142
+ const linesData = node.getData(WorkflowNodeLinesData);
143
+ const outputLines = linesData.outputLines.filter(Boolean);
144
+ const inputLines = linesData.inputLines.filter(Boolean);
145
+ return [...outputLines, ...inputLines];
146
+ }).flat();
147
+ const filteredLines = lines.filter(
148
+ (line) => this.lineLevel.get(line.id) === void 0 || this.isHigherFirstLine(line)
149
+ );
150
+ return filteredLines;
151
+ }
152
+ isHigherFirstLine(line) {
153
+ return line.to?.parent === line.from || line.from?.parent === line.to;
154
+ }
112
155
  getLevel(pinTop) {
113
156
  if (pinTop) {
114
157
  return this.topLevel + this.currentLevel;
@@ -120,138 +163,8 @@ var StackingComputing = class {
120
163
  }
121
164
  };
122
165
 
123
- // src/layers-computing.ts
124
- import { FlowNodeRenderData } from "@flowgram.ai/document";
125
-
126
166
  // src/constant.ts
127
- var StackingItem = /* @__PURE__ */ ((StackingItem2) => {
128
- StackingItem2["Line"] = "line";
129
- StackingItem2["Node"] = "node";
130
- return StackingItem2;
131
- })(StackingItem || {});
132
- var StackingType = /* @__PURE__ */ ((StackingType2) => {
133
- StackingType2["Line"] = "line" /* Line */;
134
- StackingType2["Node"] = "node" /* Node */;
135
- return StackingType2;
136
- })(StackingType || {});
137
- var StackingBaseIndex = {
138
- ["line" /* Line */]: 0,
139
- ["node" /* Node */]: 1
140
- };
141
- var startIndex = 8;
142
- var allowLevel = 2;
143
- var levelIndexStep = Object.keys(StackingType).length;
144
- var maxLevel = allowLevel * 2;
145
- var maxIndex = startIndex + maxLevel * levelIndexStep;
146
- var StackingConfig = {
147
- /** index 起始值 */
148
- startIndex,
149
- /** 允许存在的层级 */
150
- allowLevel,
151
- /** 每层 index 跨度 */
152
- levelIndexStep,
153
- /** 叠加计算后出现的最深层级 */
154
- maxLevel,
155
- /** 最大 index */
156
- maxIndex
157
- };
158
- var StackingComputeMode = /* @__PURE__ */ ((StackingComputeMode2) => {
159
- StackingComputeMode2["Stacking"] = "stacking";
160
- StackingComputeMode2["Layers"] = "layers";
161
- return StackingComputeMode2;
162
- })(StackingComputeMode || {});
163
-
164
- // src/layers-computing.ts
165
- var NodeComputing;
166
- ((NodeComputing2) => {
167
- NodeComputing2.compute = (node, context) => {
168
- const zIndex = nodeZIndex(node, context);
169
- const element = nodeElement(node);
170
- element.style.position = "absolute";
171
- element.style.zIndex = (0, NodeComputing2.zIndexStringify)(zIndex);
172
- };
173
- NodeComputing2.stackingIndex = (stackingType, level) => {
174
- if (level < 1) {
175
- return void 0;
176
- }
177
- const baseZIndex = StackingBaseIndex[stackingType];
178
- const zIndex = StackingConfig.startIndex + StackingConfig.levelIndexStep * (level - 1) + baseZIndex;
179
- return zIndex;
180
- };
181
- NodeComputing2.nodeStackingLevel = (node, context, disableTopLevel = false) => {
182
- const unReversedLinage = [];
183
- let currentNode = node;
184
- while (currentNode) {
185
- unReversedLinage.push(currentNode);
186
- currentNode = currentNode.parent;
187
- }
188
- const linage = unReversedLinage.reverse();
189
- const nodeLevel = linage.length - 1;
190
- const topLevelIndex = linage.findIndex((node2) => {
191
- if (context.selectedIDs.includes(node2.id)) {
192
- return true;
193
- }
194
- return false;
195
- });
196
- const topLevel = StackingConfig.allowLevel + (linage.length - topLevelIndex);
197
- if (!disableTopLevel && topLevelIndex !== -1) {
198
- return topLevel;
199
- }
200
- return nodeLevel;
201
- };
202
- NodeComputing2.zIndexStringify = (zIndex) => {
203
- if (zIndex === void 0) {
204
- return "auto";
205
- }
206
- return zIndex.toString();
207
- };
208
- const nodeZIndex = (node, context) => {
209
- const level = (0, NodeComputing2.nodeStackingLevel)(node, context);
210
- const zIndex = (0, NodeComputing2.stackingIndex)("node" /* Node */, level);
211
- return zIndex;
212
- };
213
- const nodeElement = (node) => {
214
- const nodeRenderData = node.getData(FlowNodeRenderData);
215
- return nodeRenderData.node;
216
- };
217
- })(NodeComputing || (NodeComputing = {}));
218
- var LineComputing;
219
- ((LineComputing2) => {
220
- LineComputing2.compute = (line, context) => {
221
- const zIndex = lineZIndex(line, context);
222
- const element = line.node;
223
- element.style.position = "absolute";
224
- element.style.zIndex = NodeComputing.zIndexStringify(zIndex);
225
- };
226
- const lineStackingLevel = (line, context) => {
227
- if (line.isDrawing || // 正在绘制
228
- context.hoveredEntityID === line.id || // hover
229
- context.selectedIDs.includes(line.id)) {
230
- return StackingConfig.maxLevel + 1;
231
- }
232
- const fromLevel = NodeComputing.nodeStackingLevel(line.from, context, true);
233
- if (!line.to) {
234
- return fromLevel;
235
- }
236
- const toLevel = NodeComputing.nodeStackingLevel(line.to, context, true);
237
- const level = Math.min(fromLevel, toLevel);
238
- return level;
239
- };
240
- const lineZIndex = (line, context) => {
241
- const level = lineStackingLevel(line, context);
242
- const zIndex = NodeComputing.stackingIndex("line" /* Line */, level);
243
- return zIndex;
244
- };
245
- })(LineComputing || (LineComputing = {}));
246
- var layersComputing = (params) => {
247
- const { nodes, lines, context } = params;
248
- nodes.forEach((node) => {
249
- NodeComputing.compute(node, context);
250
- });
251
- lines.forEach((line) => {
252
- LineComputing.compute(line, context);
253
- });
254
- };
167
+ var BASE_Z_INDEX = 8;
255
168
 
256
169
  // src/manager.ts
257
170
  var StackingContextManager = class {
@@ -259,16 +172,18 @@ var StackingContextManager = class {
259
172
  this.node = domUtils.createDivWithClass(
260
173
  "gedit-playground-layer gedit-flow-render-layer"
261
174
  );
175
+ this.options = {
176
+ sortNodes: (nodes) => nodes
177
+ };
262
178
  this.disposers = [];
263
- this.mode = "stacking" /* Stacking */;
264
179
  /**
265
180
  * 触发计算
266
181
  * 10ms内仅计算一次
267
182
  */
268
183
  this.compute = debounce(this._compute, 10);
269
184
  }
270
- init(mode) {
271
- if (mode) this.mode = mode;
185
+ init(options = {}) {
186
+ this.options = { ...this.options, ...options };
272
187
  this.pipelineRenderer.node.appendChild(this.node);
273
188
  this.mountListener();
274
189
  }
@@ -279,17 +194,6 @@ var StackingContextManager = class {
279
194
  this.disposers.forEach((disposer) => disposer.dispose());
280
195
  }
281
196
  _compute() {
282
- if (this.mode === "stacking" /* Stacking */) {
283
- return this.stackingCompute();
284
- } else {
285
- return layersComputing({
286
- nodes: this.nodes,
287
- lines: this.lines,
288
- context: this.context
289
- });
290
- }
291
- }
292
- stackingCompute() {
293
197
  const context = this.context;
294
198
  const stackingComputing = new StackingComputing();
295
199
  const { nodeLevel, lineLevel } = stackingComputing.compute({
@@ -299,38 +203,44 @@ var StackingContextManager = class {
299
203
  });
300
204
  this.nodes.forEach((node) => {
301
205
  const level = nodeLevel.get(node.id);
302
- const nodeRenderData = node.getData(FlowNodeRenderData2);
206
+ const nodeRenderData = node.getData(FlowNodeRenderData);
303
207
  const element = nodeRenderData.node;
304
208
  element.style.position = "absolute";
305
- if (!level) {
209
+ if (level === void 0) {
210
+ nodeRenderData.stackIndex = 0;
306
211
  element.style.zIndex = "auto";
307
212
  return;
308
213
  }
309
- element.style.zIndex = String(StackingConfig.startIndex + level);
214
+ nodeRenderData.stackIndex = level;
215
+ const zIndex = BASE_Z_INDEX + level;
216
+ element.style.zIndex = String(zIndex);
310
217
  });
311
218
  this.lines.forEach((line) => {
312
219
  const level = lineLevel.get(line.id);
313
220
  const element = line.node;
314
221
  element.style.position = "absolute";
315
- if (!level) {
222
+ if (level === void 0) {
223
+ line.stackIndex = 0;
316
224
  element.style.zIndex = "auto";
317
225
  return;
318
226
  }
319
- element.style.zIndex = String(StackingConfig.startIndex + level);
227
+ line.stackIndex = level;
228
+ const zIndex = BASE_Z_INDEX + level;
229
+ element.style.zIndex = String(zIndex);
320
230
  });
321
231
  }
322
232
  get nodes() {
323
233
  return this.entityManager.getEntities(WorkflowNodeEntity2);
324
234
  }
325
235
  get lines() {
326
- return this.entityManager.getEntities(WorkflowLineEntity);
236
+ return this.entityManager.getEntities(WorkflowLineEntity2);
327
237
  }
328
238
  get context() {
329
239
  return {
330
- hoveredEntity: this.hoverService.hoveredNode,
331
- hoveredEntityID: this.hoverService.hoveredNode?.id,
332
- selectedEntities: this.selectService.selection,
333
- selectedIDs: this.selectService.selection.map((entity) => entity.id)
240
+ hoveredEntityID: this.hoverService.someHovered?.id,
241
+ selectedNodes: this.selectService.selectedNodes,
242
+ selectedIDs: new Set(this.selectService.selection.map((entity) => entity.id)),
243
+ sortNodes: this.options.sortNodes
334
244
  };
335
245
  }
336
246
  mountListener() {
@@ -385,12 +295,13 @@ StackingContextManager = __decorateClass([
385
295
 
386
296
  // src/create-free-stack-plugin.ts
387
297
  var createFreeStackPlugin = definePluginCreator({
298
+ singleton: true,
388
299
  onBind({ bind }) {
389
300
  bind(StackingContextManager).toSelf().inSingletonScope();
390
301
  },
391
- onInit(ctx, opts) {
302
+ onInit(ctx, options) {
392
303
  const stackingContextManager = ctx.get(StackingContextManager);
393
- stackingContextManager.init(opts?.mode);
304
+ stackingContextManager.init(options);
394
305
  },
395
306
  onReady(ctx) {
396
307
  const stackingContextManager = ctx.get(StackingContextManager);
@@ -402,14 +313,9 @@ var createFreeStackPlugin = definePluginCreator({
402
313
  }
403
314
  });
404
315
  export {
405
- StackingBaseIndex,
406
- StackingComputeMode,
316
+ BASE_Z_INDEX,
407
317
  StackingComputing,
408
- StackingConfig,
409
318
  StackingContextManager,
410
- StackingItem,
411
- StackingType,
412
- createFreeStackPlugin,
413
- layersComputing
319
+ createFreeStackPlugin
414
320
  };
415
321
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/create-free-stack-plugin.ts","../../src/manager.ts","../../src/stacking-computing.ts","../../src/layers-computing.ts","../../src/constant.ts"],"sourcesContent":["import { definePluginCreator } from '@flowgram.ai/core';\n\nimport { StackingContextManager } from './manager';\nimport { StackingComputeMode } from './constant';\n\nexport const createFreeStackPlugin = definePluginCreator<{\n mode?: StackingComputeMode;\n}>({\n onBind({ bind }) {\n bind(StackingContextManager).toSelf().inSingletonScope();\n },\n onInit(ctx, opts) {\n const stackingContextManager = ctx.get<StackingContextManager>(StackingContextManager);\n stackingContextManager.init(opts?.mode);\n },\n onReady(ctx) {\n const stackingContextManager = ctx.get<StackingContextManager>(StackingContextManager);\n stackingContextManager.ready();\n },\n onDispose(ctx) {\n const stackingContextManager = ctx.get<StackingContextManager>(StackingContextManager);\n stackingContextManager.dispose();\n },\n});\n","import { debounce } from 'lodash';\nimport { inject, injectable } from 'inversify';\nimport { FlowNodeRenderData } from '@flowgram.ai/document';\nimport { EntityManager, PipelineRegistry, PipelineRenderer } from '@flowgram.ai/core';\nimport {\n WorkflowHoverService,\n WorkflowNodeEntity,\n WorkflowSelectService,\n} from '@flowgram.ai/free-layout-core';\nimport { WorkflowLineEntity } from '@flowgram.ai/free-layout-core';\nimport { WorkflowDocument } from '@flowgram.ai/free-layout-core';\nimport { domUtils } from '@flowgram.ai/utils';\nimport { Disposable } from '@flowgram.ai/utils';\n\nimport type { StackingContext } from './type';\nimport { StackingComputing } from './stacking-computing';\nimport { layersComputing } from './layers-computing';\nimport { StackingComputeMode, StackingConfig } from './constant';\n\n@injectable()\nexport class StackingContextManager {\n @inject(WorkflowDocument) private readonly document: WorkflowDocument;\n\n @inject(EntityManager) private readonly entityManager: EntityManager;\n\n @inject(PipelineRenderer)\n private readonly pipelineRenderer: PipelineRenderer;\n\n @inject(PipelineRegistry)\n private readonly pipelineRegistry: PipelineRegistry;\n\n @inject(WorkflowHoverService)\n private readonly hoverService: WorkflowHoverService;\n\n @inject(WorkflowSelectService)\n private readonly selectService: WorkflowSelectService;\n\n public readonly node = domUtils.createDivWithClass(\n 'gedit-playground-layer gedit-flow-render-layer',\n );\n\n private disposers: Disposable[] = [];\n\n private mode: StackingComputeMode = StackingComputeMode.Stacking;\n\n constructor() {}\n\n public init(mode?: StackingComputeMode): void {\n if (mode) this.mode = mode;\n this.pipelineRenderer.node.appendChild(this.node);\n this.mountListener();\n }\n\n public ready(): void {\n this.compute();\n }\n\n public dispose(): void {\n this.disposers.forEach(disposer => disposer.dispose());\n }\n\n /**\n * 触发计算\n * 10ms内仅计算一次\n */\n private compute = debounce(this._compute, 10);\n\n private _compute(): void {\n if (this.mode === StackingComputeMode.Stacking) {\n return this.stackingCompute();\n } else {\n return layersComputing({\n nodes: this.nodes,\n lines: this.lines,\n context: this.context,\n });\n }\n }\n\n private stackingCompute(): void {\n const context = this.context;\n const stackingComputing = new StackingComputing();\n const { nodeLevel, lineLevel } = stackingComputing.compute({\n root: this.document.root,\n nodes: this.nodes,\n context,\n });\n this.nodes.forEach(node => {\n const level = nodeLevel.get(node.id);\n const nodeRenderData = node.getData<FlowNodeRenderData>(FlowNodeRenderData);\n const element = nodeRenderData.node;\n element.style.position = 'absolute';\n if (!level) {\n element.style.zIndex = 'auto';\n return;\n }\n element.style.zIndex = String(StackingConfig.startIndex + level);\n });\n this.lines.forEach(line => {\n const level = lineLevel.get(line.id);\n const element = line.node;\n element.style.position = 'absolute';\n if (!level) {\n element.style.zIndex = 'auto';\n return;\n }\n element.style.zIndex = String(StackingConfig.startIndex + level);\n });\n }\n\n private get nodes(): WorkflowNodeEntity[] {\n return this.entityManager.getEntities<WorkflowNodeEntity>(WorkflowNodeEntity);\n }\n\n private get lines(): WorkflowLineEntity[] {\n return this.entityManager.getEntities<WorkflowLineEntity>(WorkflowLineEntity);\n }\n\n private get context(): StackingContext {\n return {\n hoveredEntity: this.hoverService.hoveredNode,\n hoveredEntityID: this.hoverService.hoveredNode?.id,\n selectedEntities: this.selectService.selection,\n selectedIDs: this.selectService.selection.map(entity => entity.id),\n };\n }\n\n private mountListener(): void {\n const entityChangeDisposer = this.onEntityChange();\n const zoomDisposer = this.onZoom();\n const hoverDisposer = this.onHover();\n const selectDisposer = this.onSelect();\n this.disposers = [entityChangeDisposer, zoomDisposer, hoverDisposer, selectDisposer];\n }\n\n private onZoom(): Disposable {\n return this.pipelineRegistry.onZoom((scale: number) => {\n this.node.style.transform = `scale(${scale})`;\n });\n }\n\n private onHover(): Disposable {\n return this.hoverService.onHoveredChange(() => {\n this.compute();\n });\n }\n\n private onEntityChange(): Disposable {\n return this.entityManager.onEntityChange(() => {\n this.compute();\n });\n }\n\n private onSelect(): Disposable {\n return this.selectService.onSelectionChanged(() => {\n this.compute();\n });\n }\n}\n","import { FlowNodeBaseType } from '@flowgram.ai/document';\nimport { WorkflowNodeEntity, WorkflowNodeLinesData } from '@flowgram.ai/free-layout-core';\n\nimport type { StackingContext } from './type';\n\nexport class StackingComputing {\n private currentLevel: number;\n\n private topLevel: number;\n\n private maxLevel: number;\n\n private nodeIndexes: Map<string, number>;\n\n private nodeLevel: Map<string, number>;\n\n private lineLevel: Map<string, number>;\n\n private context: StackingContext;\n\n public compute(params: {\n root: WorkflowNodeEntity;\n nodes: WorkflowNodeEntity[];\n context: StackingContext;\n }): {\n /** 节点层级 */\n nodeLevel: Map<string, number>;\n /** 线条层级 */\n lineLevel: Map<string, number>;\n /** 正常渲染的最高层级 */\n topLevel: number;\n /** 选中计算叠加后可能计算出的最高层级 */\n maxLevel: number;\n } {\n this.clearCache();\n const { root, nodes, context } = params;\n this.context = context;\n this.nodeIndexes = this.computeNodeIndexesMap(nodes);\n this.topLevel = this.computeTopLevel(nodes);\n this.maxLevel = this.topLevel * 2;\n this.layerHandler(root.collapsedChildren);\n return {\n nodeLevel: this.nodeLevel,\n lineLevel: this.lineLevel,\n topLevel: this.topLevel,\n maxLevel: this.maxLevel,\n };\n }\n\n private clearCache(): void {\n this.currentLevel = 0;\n this.topLevel = 0;\n this.maxLevel = 0;\n this.nodeIndexes = new Map();\n this.nodeLevel = new Map();\n this.lineLevel = new Map();\n }\n\n private computeNodeIndexesMap(nodes: WorkflowNodeEntity[]): Map<string, number> {\n const nodeIndexMap = new Map<string, number>();\n nodes.forEach((node, index) => {\n nodeIndexMap.set(node.id, index);\n });\n return nodeIndexMap;\n }\n\n private computeTopLevel(nodes: WorkflowNodeEntity[]): number {\n const nodesWithoutRoot = nodes.filter(node => node.id !== FlowNodeBaseType.ROOT);\n const nodeHasChildren = nodesWithoutRoot.reduce((count, node) => {\n if (node.collapsedChildren.length > 0) {\n return count + 1;\n } else {\n return count;\n }\n }, 0);\n // 最高层数 = 节点个数 + 容器节点个数(线条单独占一层) + 抬高一层\n return nodesWithoutRoot.length + nodeHasChildren + 1;\n }\n\n private layerHandler(nodes: WorkflowNodeEntity[], pinTop: boolean = false): void {\n const sortedNodes = nodes.sort((a, b) => {\n const aIndex = this.nodeIndexes.get(a.id);\n const bIndex = this.nodeIndexes.get(b.id);\n if (aIndex === undefined || bIndex === undefined) {\n return 0;\n }\n return aIndex - bIndex;\n });\n\n const lines = nodes\n .map(node => {\n const linesData = node.getData<WorkflowNodeLinesData>(WorkflowNodeLinesData);\n const outputLines = linesData.outputLines.filter(Boolean);\n const inputLines = linesData.inputLines.filter(Boolean);\n // 前后线条会有重复,下面 Map 会通过线条 ID 过滤掉\n return [...outputLines, ...inputLines];\n })\n .flat();\n\n // 线条统一设为当前层级最低\n lines.forEach(line => {\n if (\n line.isDrawing || // 正在绘制\n this.context.hoveredEntityID === line.id || // hover\n this.context.selectedIDs.includes(line.id) // 选中\n ) {\n // 线条置顶条件:正在绘制 / hover / 选中\n this.lineLevel.set(line.id, this.maxLevel);\n } else {\n this.lineLevel.set(line.id, this.getLevel(pinTop));\n }\n });\n this.levelIncrease();\n sortedNodes.forEach(node => {\n const selected = this.context.selectedIDs.includes(node.id);\n if (selected) {\n // 节点置顶条件:选中\n this.nodeLevel.set(node.id, this.topLevel);\n } else {\n this.nodeLevel.set(node.id, this.getLevel(pinTop));\n }\n // 节点层级逐层增高\n this.levelIncrease();\n if (node.collapsedChildren.length > 0) {\n // 子节点层级需低于后续兄弟节点,因此需要先进行计算\n this.layerHandler(node.collapsedChildren, pinTop || selected);\n }\n });\n }\n\n private getLevel(pinTop: boolean): number {\n if (pinTop) {\n return this.topLevel + this.currentLevel;\n }\n return this.currentLevel;\n }\n\n private levelIncrease(): void {\n this.currentLevel += 1;\n }\n}\n","import { FlowNodeRenderData } from '@flowgram.ai/document';\nimport type { WorkflowNodeEntity } from '@flowgram.ai/free-layout-core';\nimport type { WorkflowLineEntity } from '@flowgram.ai/free-layout-core';\n\nimport type { StackingContext } from './type';\nimport { StackingBaseIndex, StackingConfig, StackingType } from './constant';\n\nnamespace NodeComputing {\n export const compute = (node: WorkflowNodeEntity, context: StackingContext): void => {\n const zIndex = nodeZIndex(node, context);\n const element = nodeElement(node);\n element.style.position = 'absolute';\n element.style.zIndex = zIndexStringify(zIndex);\n };\n\n export const stackingIndex = (stackingType: StackingType, level: number): number | undefined => {\n if (level < 1) {\n // root节点\n return undefined;\n }\n const baseZIndex = StackingBaseIndex[stackingType];\n const zIndex =\n StackingConfig.startIndex + StackingConfig.levelIndexStep * (level - 1) + baseZIndex;\n return zIndex;\n };\n\n export const nodeStackingLevel = (\n node: WorkflowNodeEntity,\n context: StackingContext,\n disableTopLevel = false,\n ): number => {\n // TODO 后续支持多层级时这个计算逻辑应该去掉,level信息应该直接由 FlowNodeEntity 缓存给出\n // 多层时这里的计算会有 O(logN) 时间复杂度,并且在多层级联同计算时会有BUG,本次需求不处理这种情况\n const unReversedLinage: WorkflowNodeEntity[] = [];\n let currentNode: WorkflowNodeEntity | undefined = node;\n while (currentNode) {\n unReversedLinage.push(currentNode);\n currentNode = currentNode.parent;\n }\n const linage = unReversedLinage.reverse();\n const nodeLevel = linage.length - 1;\n\n const topLevelIndex = linage.findIndex((node: WorkflowNodeEntity) => {\n if (context.selectedIDs.includes(node.id)) {\n // 存在被选中的父级或自身被选中,直接置顶\n return true;\n }\n return false;\n });\n const topLevel = StackingConfig.allowLevel + (linage.length - topLevelIndex);\n\n if (!disableTopLevel && topLevelIndex !== -1) {\n // 置顶\n return topLevel;\n }\n\n return nodeLevel;\n };\n\n export const zIndexStringify = (zIndex?: number): string => {\n if (zIndex === undefined) {\n return 'auto';\n }\n return zIndex.toString();\n };\n\n const nodeZIndex = (node: WorkflowNodeEntity, context: StackingContext): number | undefined => {\n const level = nodeStackingLevel(node, context);\n const zIndex = stackingIndex(StackingType.Node, level);\n return zIndex;\n };\n\n const nodeElement = (node: WorkflowNodeEntity): HTMLDivElement => {\n const nodeRenderData = node.getData<FlowNodeRenderData>(FlowNodeRenderData);\n return nodeRenderData.node;\n };\n}\n\nnamespace LineComputing {\n export const compute = (line: WorkflowLineEntity, context: StackingContext): void => {\n const zIndex = lineZIndex(line, context);\n const element = line.node;\n element.style.position = 'absolute';\n element.style.zIndex = NodeComputing.zIndexStringify(zIndex);\n };\n\n const lineStackingLevel = (line: WorkflowLineEntity, context: StackingContext): number => {\n if (\n line.isDrawing || // 正在绘制\n context.hoveredEntityID === line.id || // hover\n context.selectedIDs.includes(line.id) // 选中\n ) {\n // 线条置顶条件:正在绘制 / hover / 选中\n return StackingConfig.maxLevel + 1;\n }\n const fromLevel = NodeComputing.nodeStackingLevel(line.from, context, true);\n if (!line.to) {\n // 还处于连线中\n return fromLevel;\n }\n const toLevel = NodeComputing.nodeStackingLevel(line.to, context, true);\n const level = Math.min(fromLevel, toLevel);\n return level;\n };\n\n const lineZIndex = (line: WorkflowLineEntity, context: StackingContext): number | undefined => {\n const level = lineStackingLevel(line, context);\n const zIndex = NodeComputing.stackingIndex(StackingType.Line, level);\n return zIndex;\n };\n}\n\nexport const layersComputing = (params: {\n nodes: WorkflowNodeEntity[];\n lines: WorkflowLineEntity[];\n context: StackingContext;\n}) => {\n const { nodes, lines, context } = params;\n nodes.forEach(node => {\n NodeComputing.compute(node, context);\n });\n lines.forEach(line => {\n LineComputing.compute(line, context);\n });\n};\n","export enum StackingItem {\n Line = 'line',\n Node = 'node',\n}\n\nexport enum StackingType {\n Line = StackingItem.Line,\n Node = StackingItem.Node,\n}\n\nexport const StackingBaseIndex: Record<StackingType, number> = {\n [StackingType.Line]: 0,\n [StackingType.Node]: 1,\n};\n\n// 常量\nconst startIndex = 8;\nconst allowLevel = 2;\n\n// 计算值\nconst levelIndexStep = Object.keys(StackingType).length;\nconst maxLevel = allowLevel * 2;\nconst maxIndex = startIndex + maxLevel * levelIndexStep;\n\nexport const StackingConfig = {\n /** index 起始值 */\n startIndex,\n /** 允许存在的层级 */\n allowLevel,\n /** 每层 index 跨度 */\n levelIndexStep,\n /** 叠加计算后出现的最深层级 */\n maxLevel,\n /** 最大 index */\n maxIndex,\n};\n\nexport enum StackingComputeMode {\n /** 层叠计算模式 */\n Stacking = 'stacking',\n /** 层级计算模式 */\n Layers = 'layers',\n}\n"],"mappings":"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","names":["FlowNodeRenderData","WorkflowNodeEntity","StackingItem","StackingType","StackingComputeMode","NodeComputing","node","LineComputing","FlowNodeRenderData","WorkflowNodeEntity"]}
1
+ {"version":3,"sources":["../../src/create-free-stack-plugin.ts","../../src/manager.ts","../../src/stacking-computing.ts","../../src/constant.ts"],"sourcesContent":["/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { definePluginCreator } from '@flowgram.ai/core';\n\nimport { FreeStackPluginOptions } from './type';\nimport { StackingContextManager } from './manager';\n\nexport const createFreeStackPlugin = definePluginCreator<FreeStackPluginOptions>({\n singleton: true,\n onBind({ bind }) {\n bind(StackingContextManager).toSelf().inSingletonScope();\n },\n onInit(ctx, options) {\n const stackingContextManager = ctx.get<StackingContextManager>(StackingContextManager);\n stackingContextManager.init(options);\n },\n onReady(ctx) {\n const stackingContextManager = ctx.get<StackingContextManager>(StackingContextManager);\n stackingContextManager.ready();\n },\n onDispose(ctx) {\n const stackingContextManager = ctx.get<StackingContextManager>(StackingContextManager);\n stackingContextManager.dispose();\n },\n});\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport { debounce } from 'lodash-es';\nimport { inject, injectable } from 'inversify';\nimport { domUtils } from '@flowgram.ai/utils';\nimport { Disposable } from '@flowgram.ai/utils';\nimport {\n WorkflowHoverService,\n WorkflowNodeEntity,\n WorkflowSelectService,\n} from '@flowgram.ai/free-layout-core';\nimport { WorkflowLineEntity } from '@flowgram.ai/free-layout-core';\nimport { WorkflowDocument } from '@flowgram.ai/free-layout-core';\nimport { FlowNodeRenderData } from '@flowgram.ai/document';\nimport { EntityManager, PipelineRegistry, PipelineRenderer } from '@flowgram.ai/core';\n\nimport type { StackContextManagerOptions, StackingContext } from './type';\nimport { StackingComputing } from './stacking-computing';\nimport { BASE_Z_INDEX } from './constant';\n\n@injectable()\nexport class StackingContextManager {\n @inject(WorkflowDocument) private readonly document: WorkflowDocument;\n\n @inject(EntityManager) private readonly entityManager: EntityManager;\n\n @inject(PipelineRenderer)\n private readonly pipelineRenderer: PipelineRenderer;\n\n @inject(PipelineRegistry)\n private readonly pipelineRegistry: PipelineRegistry;\n\n @inject(WorkflowHoverService)\n private readonly hoverService: WorkflowHoverService;\n\n @inject(WorkflowSelectService)\n private readonly selectService: WorkflowSelectService;\n\n public readonly node = domUtils.createDivWithClass(\n 'gedit-playground-layer gedit-flow-render-layer'\n );\n\n private options: StackContextManagerOptions = {\n sortNodes: (nodes: WorkflowNodeEntity[]) => nodes,\n };\n\n private disposers: Disposable[] = [];\n\n constructor() {}\n\n public init(options: Partial<StackContextManagerOptions> = {}): void {\n this.options = { ...this.options, ...options };\n this.pipelineRenderer.node.appendChild(this.node);\n this.mountListener();\n }\n\n public ready(): void {\n this.compute();\n }\n\n public dispose(): void {\n this.disposers.forEach((disposer) => disposer.dispose());\n }\n\n /**\n * 触发计算\n * 10ms内仅计算一次\n */\n private compute = debounce(this._compute, 10);\n\n private _compute(): void {\n const context = this.context;\n const stackingComputing = new StackingComputing();\n const { nodeLevel, lineLevel } = stackingComputing.compute({\n root: this.document.root,\n nodes: this.nodes,\n context,\n });\n this.nodes.forEach((node) => {\n const level = nodeLevel.get(node.id);\n const nodeRenderData = node.getData<FlowNodeRenderData>(FlowNodeRenderData);\n const element = nodeRenderData.node;\n element.style.position = 'absolute';\n if (level === undefined) {\n nodeRenderData.stackIndex = 0;\n element.style.zIndex = 'auto';\n return;\n }\n nodeRenderData.stackIndex = level;\n const zIndex = BASE_Z_INDEX + level;\n element.style.zIndex = String(zIndex);\n });\n this.lines.forEach((line) => {\n const level = lineLevel.get(line.id);\n const element = line.node;\n element.style.position = 'absolute';\n if (level === undefined) {\n line.stackIndex = 0;\n element.style.zIndex = 'auto';\n return;\n }\n line.stackIndex = level;\n const zIndex = BASE_Z_INDEX + level;\n element.style.zIndex = String(zIndex);\n });\n }\n\n private get nodes(): WorkflowNodeEntity[] {\n return this.entityManager.getEntities<WorkflowNodeEntity>(WorkflowNodeEntity);\n }\n\n private get lines(): WorkflowLineEntity[] {\n return this.entityManager.getEntities<WorkflowLineEntity>(WorkflowLineEntity);\n }\n\n private get context(): StackingContext {\n return {\n hoveredEntityID: this.hoverService.someHovered?.id,\n selectedNodes: this.selectService.selectedNodes,\n selectedIDs: new Set(this.selectService.selection.map((entity) => entity.id)),\n sortNodes: this.options.sortNodes,\n };\n }\n\n private mountListener(): void {\n const entityChangeDisposer = this.onEntityChange();\n const zoomDisposer = this.onZoom();\n const hoverDisposer = this.onHover();\n const selectDisposer = this.onSelect();\n this.disposers = [entityChangeDisposer, zoomDisposer, hoverDisposer, selectDisposer];\n }\n\n private onZoom(): Disposable {\n return this.pipelineRegistry.onZoom((scale: number) => {\n this.node.style.transform = `scale(${scale})`;\n });\n }\n\n private onHover(): Disposable {\n return this.hoverService.onHoveredChange(() => {\n this.compute();\n });\n }\n\n private onEntityChange(): Disposable {\n return this.entityManager.onEntityChange(() => {\n this.compute();\n });\n }\n\n private onSelect(): Disposable {\n return this.selectService.onSelectionChanged(() => {\n this.compute();\n });\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\nimport {\n WorkflowLineEntity,\n WorkflowNodeEntity,\n WorkflowNodeLinesData,\n} from '@flowgram.ai/free-layout-core';\nimport { FlowNodeBaseType } from '@flowgram.ai/document';\n\nimport type { StackingContext } from './type';\n\nexport class StackingComputing {\n private currentLevel: number;\n\n private topLevel: number;\n\n private maxLevel: number;\n\n private nodeIndexes: Map<string, number>;\n\n private nodeLevel: Map<string, number>;\n\n private lineLevel: Map<string, number>;\n\n private selectedNodeParentSet: Set<string>;\n\n private context: StackingContext;\n\n public compute(params: {\n root: WorkflowNodeEntity;\n nodes: WorkflowNodeEntity[];\n context: StackingContext;\n }): {\n /** 节点层级 */\n nodeLevel: Map<string, number>;\n /** 线条层级 */\n lineLevel: Map<string, number>;\n /** 正常渲染的最高层级 */\n topLevel: number;\n /** 选中计算叠加后可能计算出的最高层级 */\n maxLevel: number;\n } {\n this.clearCache();\n const { root, nodes, context } = params;\n this.context = context;\n this.nodeIndexes = this.computeNodeIndexesMap(nodes);\n this.selectedNodeParentSet = this.computeSelectedNodeParentSet(nodes);\n this.topLevel = this.computeTopLevel(nodes);\n this.maxLevel = this.topLevel * 2;\n this.layerHandler(root.blocks);\n return {\n nodeLevel: this.nodeLevel,\n lineLevel: this.lineLevel,\n topLevel: this.topLevel,\n maxLevel: this.maxLevel,\n };\n }\n\n private clearCache(): void {\n this.currentLevel = 0;\n this.topLevel = 0;\n this.maxLevel = 0;\n this.nodeIndexes = new Map();\n this.nodeLevel = new Map();\n this.lineLevel = new Map();\n }\n\n private computeNodeIndexesMap(nodes: WorkflowNodeEntity[]): Map<string, number> {\n const nodeIndexMap = new Map<string, number>();\n // 默认按照创建节点顺序排序\n nodes.forEach((node, index) => {\n nodeIndexMap.set(node.id, index);\n });\n return nodeIndexMap;\n }\n\n private computeSelectedNodeParentSet(nodes: WorkflowNodeEntity[]): Set<string> {\n const selectedNodeParents = this.context.selectedNodes.flatMap((node) =>\n this.getNodeParents(node)\n );\n return new Set(selectedNodeParents.map((node) => node.id));\n }\n\n private getNodeParents(node: WorkflowNodeEntity): WorkflowNodeEntity[] {\n const nodes: WorkflowNodeEntity[] = [];\n let currentNode: WorkflowNodeEntity | undefined = node;\n while (currentNode && currentNode.flowNodeType !== FlowNodeBaseType.ROOT) {\n nodes.unshift(currentNode);\n currentNode = currentNode.parent;\n }\n return nodes;\n }\n\n private computeTopLevel(nodes: WorkflowNodeEntity[]): number {\n const nodesWithoutRoot = nodes.filter((node) => node.id !== FlowNodeBaseType.ROOT);\n const nodeHasChildren = nodesWithoutRoot.reduce((count, node) => {\n if (node.blocks.length > 0) {\n return count + 1;\n } else {\n return count;\n }\n }, 0);\n // 最高层数 = 节点个数 + 容器节点个数(线条单独占一层) + 抬高一层\n return nodesWithoutRoot.length + nodeHasChildren + 1;\n }\n\n private layerHandler(layerNodes: WorkflowNodeEntity[], pinTop: boolean = false): void {\n const nodes = this.sortNodes(layerNodes);\n const lines = this.getNodesAllLines(nodes);\n\n // 线条统一设为当前层级最低\n lines.forEach((line) => {\n if (\n line.isDrawing || // 正在绘制\n this.context.hoveredEntityID === line.id || // hover\n this.context.selectedIDs.has(line.id) // 选中\n ) {\n // 线条置顶条件:正在绘制 / hover / 选中\n this.lineLevel.set(line.id, this.maxLevel);\n } else {\n this.lineLevel.set(line.id, this.getLevel(pinTop));\n }\n });\n this.levelIncrease();\n nodes.forEach((node) => {\n const selected = this.context.selectedIDs.has(node.id);\n if (selected) {\n // 节点置顶条件:选中\n this.nodeLevel.set(node.id, this.topLevel);\n } else {\n this.nodeLevel.set(node.id, this.getLevel(pinTop));\n }\n // 节点层级逐层增高\n this.levelIncrease();\n if (node.blocks.length > 0) {\n // 子节点层级需低于后续兄弟节点,因此需要先进行计算\n this.layerHandler(node.blocks, pinTop || selected);\n }\n });\n }\n\n private sortNodes(nodes: WorkflowNodeEntity[]): WorkflowNodeEntity[] {\n const baseSortNodes = nodes.sort((a, b) => {\n const aIndex = this.nodeIndexes.get(a.id);\n const bIndex = this.nodeIndexes.get(b.id);\n if (aIndex === undefined || bIndex === undefined) {\n return 0;\n }\n return aIndex - bIndex;\n });\n const contextSortNodes = this.context.sortNodes(baseSortNodes);\n return contextSortNodes.sort((a, b) => {\n const aIsSelectedParent = this.selectedNodeParentSet.has(a.id);\n const bIsSelectedParent = this.selectedNodeParentSet.has(b.id);\n if (aIsSelectedParent && !bIsSelectedParent) {\n return 1;\n } else if (!aIsSelectedParent && bIsSelectedParent) {\n return -1;\n } else {\n return 0;\n }\n });\n }\n\n private getNodesAllLines(nodes: WorkflowNodeEntity[]): WorkflowLineEntity[] {\n const lines = nodes\n .map((node) => {\n const linesData = node.getData<WorkflowNodeLinesData>(WorkflowNodeLinesData);\n const outputLines = linesData.outputLines.filter(Boolean);\n const inputLines = linesData.inputLines.filter(Boolean);\n return [...outputLines, ...inputLines];\n })\n .flat();\n\n // 过滤出未计算层级的线条,以及高度优先(需要覆盖计算)的线条\n const filteredLines = lines.filter(\n (line) => this.lineLevel.get(line.id) === undefined || this.isHigherFirstLine(line)\n );\n\n return filteredLines;\n }\n\n private isHigherFirstLine(line: WorkflowLineEntity): boolean {\n // 父子相连的线条,需要作为高度优先的线条,避免线条不可见\n return line.to?.parent === line.from || line.from?.parent === line.to;\n }\n\n private getLevel(pinTop: boolean): number {\n if (pinTop) {\n return this.topLevel + this.currentLevel;\n }\n return this.currentLevel;\n }\n\n private levelIncrease(): void {\n this.currentLevel += 1;\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n */\n\n// 起始 z-index\nexport const BASE_Z_INDEX = 8;\n"],"mappings":"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","names":["WorkflowNodeEntity","WorkflowLineEntity","WorkflowNodeEntity","WorkflowLineEntity"]}
package/dist/index.d.mts CHANGED
@@ -1,38 +1,32 @@
1
1
  import * as _flowgram_ai_core from '@flowgram.ai/core';
2
- import { Entity } from '@flowgram.ai/core';
3
- import { WorkfloEntityHoverable, WorkflowNodeEntity, WorkflowLineEntity } from '@flowgram.ai/free-layout-core';
2
+ import { WorkflowNodeEntity } from '@flowgram.ai/free-layout-core';
4
3
 
5
- declare enum StackingItem {
6
- Line = "line",
7
- Node = "node"
8
- }
9
- declare enum StackingType {
10
- Line = "line",
11
- Node = "node"
4
+ /**
5
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
6
+ * SPDX-License-Identifier: MIT
7
+ */
8
+
9
+ interface StackingContext {
10
+ hoveredEntityID?: string;
11
+ selectedNodes: WorkflowNodeEntity[];
12
+ selectedIDs: Set<string>;
13
+ sortNodes: (nodes: WorkflowNodeEntity[]) => WorkflowNodeEntity[];
12
14
  }
13
- declare const StackingBaseIndex: Record<StackingType, number>;
14
- declare const StackingConfig: {
15
- /** index 起始值 */
16
- startIndex: number;
17
- /** 允许存在的层级 */
18
- allowLevel: number;
19
- /** 每层 index 跨度 */
20
- levelIndexStep: number;
21
- /** 叠加计算后出现的最深层级 */
22
- maxLevel: number;
23
- /** 最大 index */
24
- maxIndex: number;
25
- };
26
- declare enum StackingComputeMode {
27
- /** 层叠计算模式 */
28
- Stacking = "stacking",
29
- /** 层级计算模式 */
30
- Layers = "layers"
15
+ interface StackContextManagerOptions {
16
+ sortNodes: (nodes: WorkflowNodeEntity[]) => WorkflowNodeEntity[];
31
17
  }
18
+ type FreeStackPluginOptions = Partial<StackContextManagerOptions>;
32
19
 
33
- declare const createFreeStackPlugin: _flowgram_ai_core.PluginCreator<{
34
- mode?: StackingComputeMode | undefined;
35
- }>;
20
+ /**
21
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
22
+ * SPDX-License-Identifier: MIT
23
+ */
24
+ declare const createFreeStackPlugin: _flowgram_ai_core.PluginCreator<Partial<StackContextManagerOptions>>;
25
+
26
+ /**
27
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
28
+ * SPDX-License-Identifier: MIT
29
+ */
36
30
 
37
31
  declare class StackingContextManager {
38
32
  private readonly document;
@@ -42,10 +36,10 @@ declare class StackingContextManager {
42
36
  private readonly hoverService;
43
37
  private readonly selectService;
44
38
  readonly node: HTMLDivElement;
39
+ private options;
45
40
  private disposers;
46
- private mode;
47
41
  constructor();
48
- init(mode?: StackingComputeMode): void;
42
+ init(options?: Partial<StackContextManagerOptions>): void;
49
43
  ready(): void;
50
44
  dispose(): void;
51
45
  /**
@@ -54,7 +48,6 @@ declare class StackingContextManager {
54
48
  */
55
49
  private compute;
56
50
  private _compute;
57
- private stackingCompute;
58
51
  private get nodes();
59
52
  private get lines();
60
53
  private get context();
@@ -65,18 +58,16 @@ declare class StackingContextManager {
65
58
  private onSelect;
66
59
  }
67
60
 
68
- type StackingContext = {
69
- hoveredEntity?: WorkfloEntityHoverable;
70
- hoveredEntityID?: string;
71
- selectedEntities: Entity[];
72
- selectedIDs: string[];
73
- };
61
+ /**
62
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
63
+ * SPDX-License-Identifier: MIT
64
+ */
65
+ declare const BASE_Z_INDEX = 8;
74
66
 
75
- declare const layersComputing: (params: {
76
- nodes: WorkflowNodeEntity[];
77
- lines: WorkflowLineEntity[];
78
- context: StackingContext;
79
- }) => void;
67
+ /**
68
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
69
+ * SPDX-License-Identifier: MIT
70
+ */
80
71
 
81
72
  declare class StackingComputing {
82
73
  private currentLevel;
@@ -85,6 +76,7 @@ declare class StackingComputing {
85
76
  private nodeIndexes;
86
77
  private nodeLevel;
87
78
  private lineLevel;
79
+ private selectedNodeParentSet;
88
80
  private context;
89
81
  compute(params: {
90
82
  root: WorkflowNodeEntity;
@@ -102,10 +94,15 @@ declare class StackingComputing {
102
94
  };
103
95
  private clearCache;
104
96
  private computeNodeIndexesMap;
97
+ private computeSelectedNodeParentSet;
98
+ private getNodeParents;
105
99
  private computeTopLevel;
106
100
  private layerHandler;
101
+ private sortNodes;
102
+ private getNodesAllLines;
103
+ private isHigherFirstLine;
107
104
  private getLevel;
108
105
  private levelIncrease;
109
106
  }
110
107
 
111
- export { StackingBaseIndex, StackingComputeMode, StackingComputing, StackingConfig, type StackingContext, StackingContextManager, StackingItem, StackingType, createFreeStackPlugin, layersComputing };
108
+ export { BASE_Z_INDEX, type FreeStackPluginOptions, type StackContextManagerOptions, StackingComputing, type StackingContext, StackingContextManager, createFreeStackPlugin };