@flowgram-vue/document 0.2.0

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 (42) hide show
  1. package/LICENSE +22 -0
  2. package/dist/index.cjs +3233 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.ts +1728 -0
  5. package/dist/index.js +3199 -0
  6. package/dist/index.js.map +1 -0
  7. package/package.json +61 -0
  8. package/src/datas/flow-node-render-data.ts +227 -0
  9. package/src/datas/flow-node-transform-data.ts +337 -0
  10. package/src/datas/flow-node-transition-data.ts +182 -0
  11. package/src/datas/index.ts +8 -0
  12. package/src/entities/flow-document-transformer-entity.ts +125 -0
  13. package/src/entities/flow-node-entity.ts +415 -0
  14. package/src/entities/flow-renderer-state-entity.ts +127 -0
  15. package/src/entities/index.ts +8 -0
  16. package/src/flow-document-config.ts +42 -0
  17. package/src/flow-document-container-module.ts +33 -0
  18. package/src/flow-document-contribution.ts +22 -0
  19. package/src/flow-document-options.ts +79 -0
  20. package/src/flow-document.ts +766 -0
  21. package/src/flow-render-tree.ts +236 -0
  22. package/src/flow-virtual-tree.ts +244 -0
  23. package/src/index.ts +16 -0
  24. package/src/layout/horizontal-fixed-layout.ts +198 -0
  25. package/src/layout/index.ts +7 -0
  26. package/src/layout/vertical-fixed-layout.ts +198 -0
  27. package/src/services/flow-drag-service.ts +211 -0
  28. package/src/services/flow-group-service/flow-group-controller.ts +120 -0
  29. package/src/services/flow-group-service/flow-group-service.ts +107 -0
  30. package/src/services/flow-group-service/flow-group-utils.ts +104 -0
  31. package/src/services/flow-group-service/index.ts +7 -0
  32. package/src/services/flow-operation-base-service.ts +333 -0
  33. package/src/services/index.ts +8 -0
  34. package/src/typings/flow-group.ts +8 -0
  35. package/src/typings/flow-layout.ts +72 -0
  36. package/src/typings/flow-node-register.ts +356 -0
  37. package/src/typings/flow-operation.ts +312 -0
  38. package/src/typings/flow-transition.ts +104 -0
  39. package/src/typings/flow.ts +70 -0
  40. package/src/typings/index.ts +11 -0
  41. package/src/utils/get-default-spacing.ts +21 -0
  42. package/src/utils/index.ts +6 -0
@@ -0,0 +1,356 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { type IPoint } from '@flowgram-vue/utils';
7
+ import { PaddingSchema } from '@flowgram-vue/utils';
8
+ import { PositionSchema } from '@flowgram-vue/utils';
9
+ import { type EntityDataRegistry, type OriginSchema, type SizeSchema } from '@flowgram-vue/core';
10
+
11
+ import { FlowDocument } from '../flow-document';
12
+ import { type FlowNodeEntity } from '../entities';
13
+ import { type FlowNodeTransformData, type FlowNodeTransitionData } from '../datas';
14
+ import { type FlowTransitionLabel, type FlowTransitionLine } from './flow-transition';
15
+ import { FlowLayout, FlowLayoutDefault } from './flow-layout';
16
+ import {
17
+ FLOW_DEFAULT_HIDDEN_TYPES,
18
+ FlowNodeBaseType,
19
+ type FlowNodeJSON,
20
+ FlowNodeType,
21
+ } from './flow';
22
+
23
+ /**
24
+ * 节点渲染相关配置信息,可扩展
25
+ */
26
+ export interface FlowNodeMeta {
27
+ isStart?: boolean; // 是否为开始节点
28
+ addable?: boolean; // 是否可添加节点
29
+ expandable?: boolean; // 是否可展开
30
+ draggable?: boolean | ((node: FlowNodeEntity) => boolean); // 是否可拖拽
31
+ selectable?: boolean | ((node: FlowNodeEntity, mousePos?: PositionSchema) => boolean); // 是否可被框选
32
+ deleteDisable?: boolean; // 是否禁用删除
33
+ copyDisable?: boolean; // 禁用复制
34
+ addDisable?: boolean; // 禁止添加
35
+ hidden?: boolean; // 是否隐藏
36
+ // maxSize?: SizeSchema // 默认展开后的大小
37
+ size?: SizeSchema; // 默认大小
38
+ autoResizeDisable?: boolean; // 禁用监听节点变化自动调整大小
39
+ /**
40
+ * @deprecated 使用 NodeRegister.getOrigin 代替
41
+ */
42
+ origin?: OriginSchema; // 原点配置,默认 垂直 { x: 0.5, y: 0 } 水平 { x: 0, y: 0.5 }
43
+ defaultExpanded?: boolean; // 默认是否展开
44
+ defaultCollapsed?: boolean; // 复合节点默认是否收起
45
+ spacing?: number | ((transform: FlowNodeTransformData) => number); // 兄弟节点间,等价于 marginBottom
46
+ padding?: PaddingSchema | ((transform: FlowNodeTransformData) => PaddingSchema); // 节点设置了 padding,则不需要 inlineSpacingPre 和 inlineSpacingAfter
47
+ inlineSpacingPre?: number | ((transform: FlowNodeTransformData) => number); // 父子节点间,等价于 paddingTop 或者 paddingLeft
48
+ inlineSpacingAfter?: number | ((transform: FlowNodeTransformData) => number); // 父子节点间,等价于 paddingBottom 或者 paddingRight
49
+ renderKey?: string; // 节点的渲染组件,可以绑定 react 组件
50
+ isInlineBlocks?: boolean | ((node: FlowNodeEntity) => boolean); // 采用水平布局
51
+ minInlineBlockSpacing?: number | ((node: FlowNodeTransformData) => number); // 最小的 inlineBlock 的间距
52
+ isNodeEnd?: boolean; // 是否标识节点结束
53
+ [key: string]: any;
54
+ }
55
+
56
+ /**
57
+ * spacing default key 值
58
+ */
59
+ export const DefaultSpacingKey = {
60
+ /**
61
+ * 普通节点间距。垂直 / 水平
62
+ */
63
+ NODE_SPACING: 'SPACING',
64
+ /**
65
+ * 分支节点间距
66
+ */
67
+ BRANCH_SPACING: 'BRANCH_SPACING',
68
+ /**
69
+ * 圆弧线条拐角 radius
70
+ */
71
+ ROUNDED_LINE_RADIUS: 'ROUNDED_LINE_RADIUS',
72
+ /**
73
+ * 圆弧线条 x radius
74
+ */
75
+ ROUNDED_LINE_X_RADIUS: 'ROUNDED_LINE_X_RADIUS',
76
+ /**
77
+ * 圆弧线条 y radius
78
+ */
79
+ ROUNDED_LINE_Y_RADIUS: 'ROUNDED_LINE_Y_RADIUS',
80
+ /**
81
+ * dynamicSplit block list 下部留白间距,因为有两个拐弯,所以翻一倍
82
+ */
83
+ INLINE_BLOCKS_PADDING_BOTTOM: 'INLINE_BLOCKS_PADDING_BOTTOM',
84
+ /**
85
+ * 复合节点距离上个节点的距离
86
+ * 条件分支菱形下边和分支的距离
87
+ */
88
+ COLLAPSED_SPACING: 'COLLAPSED_SPACING',
89
+ /**
90
+ * width of hover area
91
+ */
92
+ HOVER_AREA_WIDTH: 'HOVER_AREA_WIDTH',
93
+ };
94
+
95
+ /**
96
+ * 默认一些间隔参数
97
+ */
98
+ export const DEFAULT_SPACING = {
99
+ NULL: 0,
100
+ [DefaultSpacingKey.NODE_SPACING]: 32, // 普通节点间距。垂直 / 水平
101
+ [DefaultSpacingKey.BRANCH_SPACING]: 20, // 分支节点间距
102
+ /**
103
+ * @deprecated use 'BRANCH_SPACING' instead
104
+ */
105
+ MARGIN_RIGHT: 20, // 分支节点右边间距
106
+ INLINE_BLOCK_PADDING_BOTTOM: 16, // block 底部留白
107
+ INLINE_BLOCKS_PADDING_TOP: 30, // block list 上部留白间距
108
+ // JS 浮点数有误差,1046.6 -1006.6 = 39.9999999,会导致 间距/20 < 2 导致布局计算问题,因此需要额外增加 0.1 像素
109
+ [DefaultSpacingKey.INLINE_BLOCKS_PADDING_BOTTOM]: 40.1, // block lit 下部留白间距,因为有两个拐弯,所以翻一倍
110
+ MIN_INLINE_BLOCK_SPACING: 200, // 分支间最小边距 (垂直布局)
111
+ MIN_INLINE_BLOCK_SPACING_HORIZONTAL: 80, // 分支间最小边距 (水平布局)
112
+ [DefaultSpacingKey.COLLAPSED_SPACING]: 12, // 复合节点距离上个节点的距离
113
+ [DefaultSpacingKey.ROUNDED_LINE_RADIUS]: 16, // 圆弧线条拐角 radius
114
+ [DefaultSpacingKey.ROUNDED_LINE_X_RADIUS]: 16, // 圆弧线条 x radius
115
+ [DefaultSpacingKey.ROUNDED_LINE_Y_RADIUS]: 20, // 圆弧线条 y radius
116
+ [DefaultSpacingKey.HOVER_AREA_WIDTH]: 20, // width of hover area
117
+ };
118
+
119
+ /**
120
+ * 拖拽种类枚举
121
+ * 1. 节点拖拽
122
+ * 2. 分支拖拽
123
+ */
124
+ export enum DRAGGING_TYPE {
125
+ NODE = 'node',
126
+ BRANCH = 'branch',
127
+ }
128
+
129
+ /**
130
+ * 拖拽分支 Adder、Line 类型
131
+ */
132
+ export enum LABEL_SIDE_TYPE {
133
+ // 前缀分支
134
+ PRE_BRANCH = 'pre_branch',
135
+ NORMAL_BRANCH = 'normal_branch',
136
+ }
137
+
138
+ /**
139
+ * 默认节点大小
140
+ */
141
+ export const DEFAULT_SIZE = {
142
+ width: 280,
143
+ height: 60,
144
+ };
145
+
146
+ /**
147
+ * 默认 meta 配置
148
+ */
149
+ export const DEFAULT_FLOW_NODE_META: (
150
+ nodeType: FlowNodeType,
151
+ document: FlowDocument
152
+ ) => FlowNodeMeta = (nodeType: FlowNodeType, document: FlowDocument) => {
153
+ const hidden = FLOW_DEFAULT_HIDDEN_TYPES.includes(nodeType);
154
+ return {
155
+ isStart: nodeType === 'start',
156
+ hidden,
157
+ defaultExpanded: document.options.allNodesDefaultExpanded,
158
+ size: DEFAULT_SIZE,
159
+ origin: document.layout.getDefaultNodeOrigin(),
160
+ isInlineBlocks: nodeType === FlowNodeBaseType.INLINE_BLOCKS,
161
+ // miniSize: { width: 200, height: 40 },
162
+ spacing: DEFAULT_SPACING.SPACING,
163
+ inlineSpacingPre: 0,
164
+ inlineSpacingAfter: 0,
165
+ expandable: true,
166
+ draggable: true,
167
+ selectable: true,
168
+ renderKey: '',
169
+ minInlineBlockSpacing: () => {
170
+ const isVertical = FlowLayoutDefault.isVertical(document.layout);
171
+ return isVertical
172
+ ? DEFAULT_SPACING.MIN_INLINE_BLOCK_SPACING
173
+ : DEFAULT_SPACING.MIN_INLINE_BLOCK_SPACING_HORIZONTAL;
174
+ },
175
+ } as FlowNodeMeta;
176
+ };
177
+
178
+ /**
179
+ * 节点注册
180
+ */
181
+ export interface FlowNodeRegistry<M extends FlowNodeMeta = FlowNodeMeta> {
182
+ /**
183
+ * 从另外一个注册扩展
184
+ */
185
+ extend?: string;
186
+ /**
187
+ * 节点类型
188
+ */
189
+ type: FlowNodeType;
190
+ /**
191
+ * 节点注册的数据,可以理解为 ECS 里的 Component, 这里可以配置自定义数据
192
+ */
193
+ dataRegistries?: EntityDataRegistry[];
194
+ /**
195
+ * 节点画布相关初始化配置信息,会覆盖 DEFAULT_FLOW_NODE_META
196
+ */
197
+ meta?: Partial<M>;
198
+ /**
199
+ * 自定义创建节点,可以自定义节点的树形结构
200
+ * 返回新加入的节点,这样才能统计缓存
201
+ *
202
+ * @action 使用该方法,在创建时候将会忽略 json blocks 数据,而是交给适用节点自己处理 json 逻辑
203
+ */
204
+ onCreate?: (node: FlowNodeEntity, json: FlowNodeJSON) => FlowNodeEntity[] | void;
205
+ /**
206
+ * 添加子 block,一般用于分支的动态添加
207
+ */
208
+ onBlockChildCreate?: (
209
+ node: FlowNodeEntity,
210
+ json: FlowNodeJSON,
211
+ addedNodes?: FlowNodeEntity[] // 新创建的节点都要存在这里
212
+ ) => FlowNodeEntity;
213
+ /**
214
+ * 创建线条
215
+ */
216
+ getLines?: (transition: FlowNodeTransitionData, layout: FlowLayout) => FlowTransitionLine[];
217
+ /**
218
+ * 创建 label
219
+ */
220
+ getLabels?: (transition: FlowNodeTransitionData, layout: FlowLayout) => FlowTransitionLabel[];
221
+
222
+ /**
223
+ * 调整子节点的线条,优先级高于子节点本身的 getLines
224
+ */
225
+ getChildLines?: (transition: FlowNodeTransitionData, layout: FlowLayout) => FlowTransitionLine[];
226
+
227
+ /**
228
+ * 调整子节点的 Labels,优先级高于子节点本身的 getLabels
229
+ */
230
+ getChildLabels?: (
231
+ transition: FlowNodeTransitionData,
232
+ layout: FlowLayout
233
+ ) => FlowTransitionLabel[];
234
+
235
+ /**
236
+ * 自定义输入节点
237
+ */
238
+ getInputPoint?: (transform: FlowNodeTransformData, layout: FlowLayout) => IPoint;
239
+ /**
240
+ * 自定义输出节点
241
+ */
242
+ getOutputPoint?: (transform: FlowNodeTransformData, layoutKey: FlowLayout) => IPoint;
243
+ /**
244
+ * 获取当前节点 Position 偏移量,偏移量计算只能使用已经计算完的数据,如上一个节点或者子节点,不然会造成 o(n^2) 复杂度
245
+ *
246
+ * 1. 切记不要用当前节点的 localBounds(相对位置 bbox),因为 delta 计算发生在 localBounds 计算之前
247
+ * 2. 切记不要用 bounds(绝对位置 bbox, 会触发所有父节点绝对位置计算), bounds 只能在最终 render 时候使用
248
+ * 3. 可以用 pre 节点 和 子节点的 localBounds 或者 size 数据,因为子节点是先算的
249
+ * 4. 可以用当前节点的 size (所有子节点的最大 bbox), 这是已经确定下来的
250
+ */
251
+ getDelta?: (transform: FlowNodeTransformData, layout: FlowLayout) => IPoint | undefined;
252
+
253
+ /**
254
+ * 动态获取原点,会覆盖 meta.origin
255
+ */
256
+ getOrigin?(transform: FlowNodeTransformData, layout: FlowLayout): IPoint;
257
+ /**
258
+ * 原点 X 偏移
259
+ * @param transform
260
+ */
261
+ getOriginDeltaX?: (transform: FlowNodeTransformData, layout: FlowLayout) => number;
262
+ /**
263
+ * 原点 Y 偏移
264
+ * @param transform
265
+ */
266
+ getOriginDeltaY?: (transform: FlowNodeTransformData, layout: FlowLayout) => number;
267
+ /**
268
+ * 通过 parent 计算当前节点的偏移,规则同 getDelta
269
+ */
270
+ getChildDelta?: (childBlock: FlowNodeTransformData, layout: FlowLayout) => IPoint | undefined;
271
+ /**
272
+ * 在当前节点布局完成后调用,可以对布局做更精细的调整
273
+ */
274
+ onAfterUpdateLocalTransform?: (transform: FlowNodeTransformData, layout: FlowLayout) => void;
275
+
276
+ /**
277
+ * 子节点的 registry 覆盖,这里通过 originParent 来查找
278
+ */
279
+ extendChildRegistries?: FlowNodeRegistry[];
280
+
281
+ /**
282
+ * @deprecated
283
+ * 自定义子节点添加逻辑
284
+ * @param node 节点
285
+ * @param json 添加的节点 JSON
286
+ * @param options 其它配置
287
+ * @returns
288
+ */
289
+ addChild?: (
290
+ node: FlowNodeEntity,
291
+ json: FlowNodeJSON,
292
+ options?: {
293
+ hidden?: boolean;
294
+ index?: number;
295
+ }
296
+ ) => FlowNodeEntity;
297
+
298
+ /**
299
+ * 内部用于继承逻辑判断,不要使用
300
+ */
301
+ __extends__?: FlowNodeType[];
302
+ /**
303
+ * 扩展注册器
304
+ */
305
+ [key: string]: any;
306
+ }
307
+
308
+ export namespace FlowNodeRegistry {
309
+ export function mergeChildRegistries(
310
+ r1: FlowNodeRegistry[] = [],
311
+ r2: FlowNodeRegistry[] = []
312
+ ): FlowNodeRegistry[] {
313
+ if (r1.length === 0 || r2.length === 0) {
314
+ return [...r1, ...r2];
315
+ }
316
+ const r1Filter = r1.map((r1Current) => {
317
+ const r2Current = r2.find((n) => n.type === r1Current.type);
318
+ if (r2Current) {
319
+ return merge(r1Current, r2Current, r1Current.type);
320
+ }
321
+ return r1Current;
322
+ });
323
+ const r2Filter = r2.filter((n) => !r1.some((r) => r.type === n.type));
324
+ return [...r1Filter, ...r2Filter];
325
+ }
326
+ export function merge(
327
+ registry1: FlowNodeRegistry,
328
+ registry2: FlowNodeRegistry,
329
+ finalType: FlowNodeType
330
+ ): FlowNodeRegistry {
331
+ const extendKeys = registry1.__extends__ ? registry1.__extends__.slice() : [];
332
+ if (registry1.type !== registry2.type) {
333
+ extendKeys.unshift(registry1.type);
334
+ }
335
+ return {
336
+ ...registry1,
337
+ ...registry2,
338
+ extendChildRegistries: mergeChildRegistries(
339
+ registry1.extendChildRegistries,
340
+ registry2.extendChildRegistries
341
+ ),
342
+ meta: { ...registry1.meta, ...registry2.meta },
343
+ extend: undefined,
344
+ type: finalType,
345
+ __extends__: extendKeys,
346
+ };
347
+ }
348
+
349
+ export function extend(
350
+ registry: FlowNodeRegistry,
351
+ extendRegistries: FlowNodeRegistry[]
352
+ ): FlowNodeRegistry {
353
+ if (!extendRegistries.length) return registry;
354
+ return extendRegistries.reduce((res, ext) => merge(res, ext, registry.type), registry);
355
+ }
356
+ }
@@ -0,0 +1,312 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+
6
+ import { Event } from '@flowgram-vue/utils';
7
+ import { Disposable } from '@flowgram-vue/utils';
8
+
9
+ import { type FlowNodeEntity } from '../entities/flow-node-entity';
10
+ import { AddNodeData, FlowNodeJSON } from './flow';
11
+
12
+ export enum OperationType {
13
+ addFromNode = 'addFromNode',
14
+ deleteFromNode = 'deleteFromNode',
15
+ addBlock = 'addBlock',
16
+ deleteBlock = 'deleteBlock',
17
+ createGroup = 'createGroup',
18
+ ungroup = 'ungroup',
19
+ moveNodes = 'moveNodes',
20
+ moveBlock = 'moveBlock',
21
+ moveChildNodes = 'moveChildNodes',
22
+ addNodes = 'addNodes',
23
+ deleteNodes = 'deleteNodes',
24
+ addChildNode = 'addChildNode',
25
+ deleteChildNode = 'deleteChildNode',
26
+ addNode = 'addNode',
27
+ deleteNode = 'deleteNode',
28
+ }
29
+
30
+ export interface AddOrDeleteFromNodeOperationValue {
31
+ fromId: string;
32
+ data: FlowNodeJSON;
33
+ }
34
+
35
+ export interface AddOrDeleteNodeOperationValue {
36
+ fromId: string;
37
+ data: FlowNodeJSON;
38
+ }
39
+
40
+ export interface AddFromNodeOperation {
41
+ type: OperationType.addFromNode;
42
+ value: AddOrDeleteFromNodeOperationValue;
43
+ }
44
+
45
+ export interface DeleteFromNodeOperation {
46
+ type: OperationType.deleteFromNode;
47
+ value: AddOrDeleteFromNodeOperationValue;
48
+ }
49
+
50
+ export interface AddOrDeleteBlockValue {
51
+ targetId: string;
52
+ index?: number;
53
+ blockData: FlowNodeJSON;
54
+ parentId?: string;
55
+ }
56
+
57
+ export interface createOrUngroupValue {
58
+ targetId: string;
59
+ groupId: string;
60
+ nodeIds: string[];
61
+ }
62
+
63
+ export interface AddBlockOperation {
64
+ type: OperationType.addBlock;
65
+ value: AddOrDeleteBlockValue;
66
+ }
67
+
68
+ export interface DeleteBlockOperation {
69
+ type: OperationType.deleteBlock;
70
+ value: AddOrDeleteBlockValue;
71
+ }
72
+
73
+ export interface CreateGroupOperation {
74
+ type: OperationType.createGroup;
75
+ value: createOrUngroupValue;
76
+ }
77
+
78
+ export interface UngroupOperation {
79
+ type: OperationType.ungroup;
80
+ value: createOrUngroupValue;
81
+ }
82
+
83
+ export interface MoveNodesOperationValue {
84
+ fromId: string;
85
+ toId: string;
86
+ nodeIds: string[];
87
+ }
88
+
89
+ export interface MoveNodesOperation {
90
+ type: OperationType.moveNodes;
91
+ value: MoveNodesOperationValue;
92
+ }
93
+
94
+ export interface AddOrDeleteNodesOperationValue {
95
+ fromId: string;
96
+ nodes: FlowNodeJSON[];
97
+ }
98
+
99
+ export interface AddNodesOperation {
100
+ type: OperationType.addNodes;
101
+ value: AddOrDeleteNodesOperationValue;
102
+ }
103
+
104
+ export interface DeleteNodesOperation {
105
+ type: OperationType.deleteNodes;
106
+ value: AddOrDeleteNodesOperationValue;
107
+ }
108
+
109
+ export interface MoveChildNodesOperationValue {
110
+ nodeIds: string[];
111
+ fromParentId: string;
112
+ fromIndex: number;
113
+ toParentId: string;
114
+ toIndex: number;
115
+ }
116
+
117
+ export type MoveBlockOperationValue = {
118
+ nodeId: string;
119
+ fromParentId: string;
120
+ fromIndex: number;
121
+ toParentId: string;
122
+ toIndex: number;
123
+ };
124
+
125
+ export interface MoveBlockOperation {
126
+ type: OperationType.moveBlock;
127
+ value: MoveBlockOperationValue;
128
+ }
129
+
130
+ export interface MoveChildNodesOperation {
131
+ type: OperationType.moveChildNodes;
132
+ value: MoveChildNodesOperationValue;
133
+ }
134
+
135
+ export interface AddChildNodeOperation {
136
+ type: OperationType.addChildNode;
137
+ value: AddOrDeleteChildNodeValue;
138
+ }
139
+
140
+ export interface DeleteChildNodeOperation {
141
+ type: OperationType.deleteChildNode;
142
+ value: AddOrDeleteChildNodeValue;
143
+ }
144
+
145
+ export interface AddOrDeleteChildNodeValue {
146
+ data: FlowNodeJSON;
147
+ parentId?: string;
148
+ index?: number;
149
+ originParentId?: string;
150
+ hidden?: boolean;
151
+ }
152
+
153
+ export interface AddNodeOperation {
154
+ type: OperationType.addNode;
155
+ value: AddOrDeleteNodeValue;
156
+ }
157
+
158
+ export interface DeleteNodeOperation {
159
+ type: OperationType.deleteNode;
160
+ value: AddOrDeleteNodeValue;
161
+ }
162
+
163
+ export interface AddOrDeleteNodeValue {
164
+ data: FlowNodeJSON;
165
+ parentId?: string;
166
+ index?: number;
167
+ hidden?: boolean;
168
+ }
169
+
170
+ export type FlowOperation =
171
+ | AddFromNodeOperation
172
+ | DeleteFromNodeOperation
173
+ | AddBlockOperation
174
+ | DeleteBlockOperation
175
+ | CreateGroupOperation
176
+ | UngroupOperation
177
+ | MoveNodesOperation
178
+ | AddNodesOperation
179
+ | DeleteNodesOperation
180
+ | MoveBlockOperation
181
+ | AddChildNodeOperation
182
+ | DeleteChildNodeOperation
183
+ | MoveChildNodesOperation
184
+ | AddNodeOperation
185
+ | DeleteNodeOperation;
186
+
187
+ export type FlowNodeEntityOrId = string | FlowNodeEntity;
188
+
189
+ // 添加节点时的配置
190
+ export type AddNodeConfig = {
191
+ // 父节点
192
+ parent?: FlowNodeEntityOrId;
193
+ // 是否隐藏
194
+ hidden?: boolean;
195
+ // 插入位置
196
+ index?: number;
197
+ };
198
+
199
+ /**
200
+ * 添加block时的配置
201
+ */
202
+ export interface AddBlockConfig {
203
+ // 父节点,默认去找 $inlineBlocks$
204
+ parent?: FlowNodeEntity;
205
+ // 插入位置,默认最后
206
+ index?: number;
207
+ }
208
+
209
+ /**
210
+ * 移动节点时的配置
211
+ */
212
+ export interface MoveNodeConfig {
213
+ // 目标父节点,如果不传,默认使用移动节点的父节点
214
+ parent?: FlowNodeEntityOrId;
215
+ // 目标位置, 默认移动到最后
216
+ index?: number;
217
+ }
218
+
219
+ /**
220
+ * 节点添加事件
221
+ */
222
+ export interface OnNodeAddEvent {
223
+ node: FlowNodeEntity;
224
+ data: AddNodeData;
225
+ }
226
+
227
+ /**
228
+ * 节点移动事件
229
+ */
230
+ export interface OnNodeMoveEvent {
231
+ node: FlowNodeEntity;
232
+ fromParent: FlowNodeEntity;
233
+ fromIndex: number;
234
+ toParent: FlowNodeEntity;
235
+ toIndex: number;
236
+ }
237
+
238
+ export interface FlowOperationBaseService extends Disposable {
239
+ /**
240
+ * 执行操作
241
+ * @param operation 可序列化的操作
242
+ * @returns 操作返回
243
+ */
244
+ apply(operation: FlowOperation): any;
245
+
246
+ /**
247
+ * 添加节点,如果节点已经存在则不会重复创建
248
+ * @param nodeJSON 节点数据
249
+ * @param config 配置
250
+ * @returns 成功添加的节点
251
+ */
252
+ addNode(nodeJSON: FlowNodeJSON, config?: AddNodeConfig): FlowNodeEntity;
253
+
254
+ /**
255
+ * 基于某一个起始节点往后面添加
256
+ * @param fromNode 起始节点
257
+ * @param nodeJSON 添加的节点JSON
258
+ */
259
+ addFromNode(fromNode: FlowNodeEntityOrId, nodeJSON: FlowNodeJSON): FlowNodeEntity;
260
+
261
+ /**
262
+ * 删除节点
263
+ * @param node 节点
264
+ * @returns
265
+ */
266
+ deleteNode(node: FlowNodeEntityOrId): void;
267
+
268
+ /**
269
+ * 批量删除节点
270
+ * @param nodes
271
+ */
272
+ deleteNodes(nodes: FlowNodeEntityOrId[]): void;
273
+
274
+ /**
275
+ * 添加块(分支)
276
+ * @param target 目标
277
+ * @param blockJSON 块数据
278
+ * @param config 配置
279
+ * @returns
280
+ */
281
+ addBlock(
282
+ target: FlowNodeEntityOrId,
283
+ blockJSON: FlowNodeJSON,
284
+ config?: AddBlockConfig
285
+ ): FlowNodeEntity;
286
+
287
+ /**
288
+ * 移动节点
289
+ * @param node 被移动的节点
290
+ * @param config 移动节点配置
291
+ */
292
+ moveNode(node: FlowNodeEntityOrId, config?: MoveNodeConfig): void;
293
+
294
+ /**
295
+ * 拖拽节点
296
+ * @param param0
297
+ * @returns
298
+ */
299
+ dragNodes({ dropNode, nodes }: { dropNode: FlowNodeEntity; nodes: FlowNodeEntity[] }): void;
300
+
301
+ /**
302
+ * 添加节点的回调
303
+ */
304
+ onNodeAdd: Event<OnNodeAddEvent>;
305
+
306
+ /**
307
+ * 节点移动的回调
308
+ */
309
+ onNodeMove: Event<OnNodeMoveEvent>;
310
+ }
311
+
312
+ export const FlowOperationBaseService = Symbol('FlowOperationBaseService');