@logicflow/extension 2.0.0-beta.1 → 2.0.0-beta.10
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/.turbo/turbo-build.log +361 -6
- package/dist/index.css +63 -0
- package/dist/index.min.js +32 -2
- package/es/NodeResize/control/Control.d.ts +3 -3
- package/es/NodeResize/control/Control.js +13 -3
- package/es/NodeResize/control/Control.js.map +1 -1
- package/es/NodeResize/index.d.ts +4 -0
- package/es/NodeResize/index.js.map +1 -1
- package/es/NodeResize/node/DiamondResize.d.ts +1 -0
- package/es/NodeResize/node/DiamondResize.js +2 -1
- package/es/NodeResize/node/DiamondResize.js.map +1 -1
- package/es/NodeResize/node/EllipseResize.d.ts +1 -0
- package/es/NodeResize/node/EllipseResize.js +2 -1
- package/es/NodeResize/node/EllipseResize.js.map +1 -1
- package/es/NodeResize/node/HtmlResize.js +1 -1
- package/es/NodeResize/node/HtmlResize.js.map +1 -1
- package/es/NodeResize/node/RectResize.js +1 -1
- package/es/NodeResize/node/RectResize.js.map +1 -1
- package/es/bpmn/constant.d.ts +1 -1
- package/es/bpmn/constant.js +3 -0
- package/es/bpmn/constant.js.map +1 -1
- package/es/bpmn/index.d.ts +3 -6
- package/es/bpmn/index.js +5 -7
- package/es/bpmn/index.js.map +1 -1
- package/es/bpmn-elements/presets/Pool/Pool.d.ts +21 -1
- package/es/components/control/index.d.ts +4 -4
- package/es/components/control/index.js.map +1 -1
- package/es/components/highlight/index.d.ts +6 -4
- package/es/components/highlight/index.js +32 -5
- package/es/components/highlight/index.js.map +1 -1
- package/es/components/menu/index.d.ts +1 -1
- package/es/components/menu/index.js +9 -10
- package/es/components/menu/index.js.map +1 -1
- package/es/components/mini-map/index.d.ts +1 -1
- package/es/components/mini-map/index.js +2 -2
- package/es/components/mini-map/index.js.map +1 -1
- package/es/components/selection-select/index.d.ts +1 -1
- package/es/components/selection-select/index.js.map +1 -1
- package/es/dynamic-group/index.d.ts +106 -0
- package/es/dynamic-group/index.js +536 -0
- package/es/dynamic-group/index.js.map +1 -0
- package/es/dynamic-group/model.d.ts +135 -0
- package/es/dynamic-group/model.js +413 -0
- package/es/dynamic-group/model.js.map +1 -0
- package/es/dynamic-group/node.d.ts +16 -0
- package/es/dynamic-group/node.js +143 -0
- package/es/dynamic-group/node.js.map +1 -0
- package/es/dynamic-group/utils.d.ts +17 -0
- package/es/dynamic-group/utils.js +27 -0
- package/es/dynamic-group/utils.js.map +1 -0
- package/es/index.css +63 -0
- package/es/index.d.ts +16 -8
- package/es/index.js +24 -8
- package/es/index.js.map +1 -1
- package/es/insert-node-in-polyline/index.js +3 -3
- package/es/insert-node-in-polyline/index.js.map +1 -1
- package/es/materials/group/GroupNode.d.ts +6 -10
- package/es/materials/group/GroupNode.js +8 -6
- package/es/materials/group/GroupNode.js.map +1 -1
- package/es/materials/group/index.d.ts +5 -5
- package/es/materials/group/index.js +25 -26
- package/es/materials/group/index.js.map +1 -1
- package/es/materials/node-selection/index.d.ts +6 -1
- package/es/materials/node-selection/index.js +64 -56
- package/es/materials/node-selection/index.js.map +1 -1
- package/es/mindmap/index.d.ts +2 -2
- package/es/style/index.css +63 -0
- package/es/style/index.less +73 -0
- package/es/style/raw.d.ts +1 -1
- package/es/style/raw.js +1 -1
- package/es/style/raw.js.map +1 -1
- package/es/tools/flow-path/index.js +0 -1
- package/es/tools/flow-path/index.js.map +1 -1
- package/es/tools/label/Label.d.ts +30 -0
- package/es/tools/label/Label.js +241 -0
- package/es/tools/label/Label.js.map +1 -0
- package/es/tools/label/LabelModel.d.ts +26 -0
- package/es/tools/label/LabelModel.js +86 -0
- package/es/tools/label/LabelModel.js.map +1 -0
- package/es/tools/label/LabelOverlay.d.ts +28 -0
- package/es/tools/label/LabelOverlay.js +161 -0
- package/es/tools/label/LabelOverlay.js.map +1 -0
- package/es/tools/label/algorithm.d.ts +16 -0
- package/es/tools/label/algorithm.js +27 -0
- package/es/tools/label/algorithm.js.map +1 -0
- package/es/tools/label/index.d.ts +59 -0
- package/es/tools/label/index.js +292 -0
- package/es/tools/label/index.js.map +1 -0
- package/es/tools/label/mediumEditor.d.ts +17 -0
- package/es/tools/label/mediumEditor.js +92 -0
- package/es/tools/label/mediumEditor.js.map +1 -0
- package/es/tools/label/utils.d.ts +64 -0
- package/es/tools/label/utils.js +336 -0
- package/es/tools/label/utils.js.map +1 -0
- package/es/tools/snapshot/index.d.ts +107 -11
- package/es/tools/snapshot/index.js +366 -149
- package/es/tools/snapshot/index.js.map +1 -1
- package/es/tools/snapshot/utils.d.ts +35 -0
- package/es/tools/snapshot/utils.js +238 -0
- package/es/tools/snapshot/utils.js.map +1 -0
- package/lib/NodeResize/control/Control.d.ts +3 -3
- package/lib/NodeResize/control/Control.js +13 -3
- package/lib/NodeResize/control/Control.js.map +1 -1
- package/lib/NodeResize/index.d.ts +4 -0
- package/lib/NodeResize/index.js.map +1 -1
- package/lib/NodeResize/node/DiamondResize.d.ts +1 -0
- package/lib/NodeResize/node/DiamondResize.js +2 -1
- package/lib/NodeResize/node/DiamondResize.js.map +1 -1
- package/lib/NodeResize/node/EllipseResize.d.ts +1 -0
- package/lib/NodeResize/node/EllipseResize.js +2 -1
- package/lib/NodeResize/node/EllipseResize.js.map +1 -1
- package/lib/NodeResize/node/HtmlResize.js +1 -1
- package/lib/NodeResize/node/HtmlResize.js.map +1 -1
- package/lib/NodeResize/node/RectResize.js +1 -1
- package/lib/NodeResize/node/RectResize.js.map +1 -1
- package/lib/bpmn/constant.d.ts +1 -1
- package/lib/bpmn/constant.js +3 -0
- package/lib/bpmn/constant.js.map +1 -1
- package/lib/bpmn/index.d.ts +3 -6
- package/lib/bpmn/index.js +5 -7
- package/lib/bpmn/index.js.map +1 -1
- package/lib/bpmn-elements/presets/Pool/Pool.d.ts +21 -1
- package/lib/components/control/index.d.ts +4 -4
- package/lib/components/control/index.js.map +1 -1
- package/lib/components/highlight/index.d.ts +6 -4
- package/lib/components/highlight/index.js +32 -5
- package/lib/components/highlight/index.js.map +1 -1
- package/lib/components/menu/index.d.ts +1 -1
- package/lib/components/menu/index.js +9 -10
- package/lib/components/menu/index.js.map +1 -1
- package/lib/components/mini-map/index.d.ts +1 -1
- package/lib/components/mini-map/index.js +2 -2
- package/lib/components/mini-map/index.js.map +1 -1
- package/lib/components/selection-select/index.d.ts +1 -1
- package/lib/components/selection-select/index.js.map +1 -1
- package/lib/dynamic-group/index.d.ts +106 -0
- package/lib/dynamic-group/index.js +553 -0
- package/lib/dynamic-group/index.js.map +1 -0
- package/lib/dynamic-group/model.d.ts +135 -0
- package/lib/dynamic-group/model.js +416 -0
- package/lib/dynamic-group/model.js.map +1 -0
- package/lib/dynamic-group/node.d.ts +16 -0
- package/lib/dynamic-group/node.js +146 -0
- package/lib/dynamic-group/node.js.map +1 -0
- package/lib/dynamic-group/utils.d.ts +17 -0
- package/lib/dynamic-group/utils.js +32 -0
- package/lib/dynamic-group/utils.js.map +1 -0
- package/lib/index.css +63 -0
- package/lib/index.d.ts +16 -8
- package/lib/index.js +24 -8
- package/lib/index.js.map +1 -1
- package/lib/insert-node-in-polyline/index.js +2 -2
- package/lib/insert-node-in-polyline/index.js.map +1 -1
- package/lib/materials/group/GroupNode.d.ts +6 -10
- package/lib/materials/group/GroupNode.js +8 -6
- package/lib/materials/group/GroupNode.js.map +1 -1
- package/lib/materials/group/index.d.ts +5 -5
- package/lib/materials/group/index.js +24 -25
- package/lib/materials/group/index.js.map +1 -1
- package/lib/materials/node-selection/index.d.ts +6 -1
- package/lib/materials/node-selection/index.js +63 -55
- package/lib/materials/node-selection/index.js.map +1 -1
- package/lib/mindmap/index.d.ts +2 -2
- package/lib/style/index.css +63 -0
- package/lib/style/index.less +73 -0
- package/lib/style/raw.d.ts +1 -1
- package/lib/style/raw.js +1 -1
- package/lib/style/raw.js.map +1 -1
- package/lib/tools/flow-path/index.js +0 -1
- package/lib/tools/flow-path/index.js.map +1 -1
- package/lib/tools/label/Label.d.ts +30 -0
- package/lib/tools/label/Label.js +247 -0
- package/lib/tools/label/Label.js.map +1 -0
- package/lib/tools/label/LabelModel.d.ts +26 -0
- package/lib/tools/label/LabelModel.js +89 -0
- package/lib/tools/label/LabelModel.js.map +1 -0
- package/lib/tools/label/LabelOverlay.d.ts +28 -0
- package/lib/tools/label/LabelOverlay.js +167 -0
- package/lib/tools/label/LabelOverlay.js.map +1 -0
- package/lib/tools/label/algorithm.d.ts +16 -0
- package/lib/tools/label/algorithm.js +32 -0
- package/lib/tools/label/algorithm.js.map +1 -0
- package/lib/tools/label/index.d.ts +59 -0
- package/lib/tools/label/index.js +298 -0
- package/lib/tools/label/index.js.map +1 -0
- package/lib/tools/label/mediumEditor.d.ts +17 -0
- package/lib/tools/label/mediumEditor.js +98 -0
- package/lib/tools/label/mediumEditor.js.map +1 -0
- package/lib/tools/label/utils.d.ts +64 -0
- package/lib/tools/label/utils.js +349 -0
- package/lib/tools/label/utils.js.map +1 -0
- package/lib/tools/snapshot/index.d.ts +107 -11
- package/lib/tools/snapshot/index.js +366 -149
- package/lib/tools/snapshot/index.js.map +1 -1
- package/lib/tools/snapshot/utils.d.ts +35 -0
- package/lib/tools/snapshot/utils.js +247 -0
- package/lib/tools/snapshot/utils.js.map +1 -0
- package/package.json +9 -3
- package/rollup.config.js +1 -1
- package/src/NodeResize/control/Control.tsx +13 -3
- package/src/NodeResize/index.ts +4 -0
- package/src/NodeResize/node/DiamondResize.tsx +2 -1
- package/src/NodeResize/node/EllipseResize.tsx +2 -1
- package/src/NodeResize/node/HtmlResize.tsx +1 -1
- package/src/NodeResize/node/RectResize.tsx +1 -1
- package/src/bpmn/constant.ts +4 -1
- package/src/bpmn/index.ts +7 -4
- package/src/bpmn-elements-adapter/README.md +1 -3
- package/src/components/control/index.ts +4 -4
- package/src/components/highlight/index.ts +33 -6
- package/src/components/menu/index.ts +16 -13
- package/src/components/mini-map/index.ts +3 -3
- package/src/components/selection-select/index.ts +6 -2
- package/src/dynamic-group/index.ts +609 -0
- package/src/dynamic-group/model.ts +503 -0
- package/src/dynamic-group/node.ts +140 -0
- package/src/dynamic-group/utils.ts +33 -0
- package/src/index.ts +30 -8
- package/src/insert-node-in-polyline/index.ts +3 -3
- package/src/materials/group/GroupNode.ts +12 -12
- package/src/materials/group/index.ts +40 -40
- package/src/materials/node-selection/index.ts +78 -70
- package/src/style/index.less +73 -0
- package/src/style/raw.ts +64 -1
- package/src/tools/flow-path/index.ts +0 -1
- package/src/tools/label/Label.tsx +297 -0
- package/src/tools/label/LabelModel.ts +82 -0
- package/src/tools/label/LabelOverlay.tsx +159 -0
- package/src/tools/label/algorithm.ts +42 -0
- package/src/tools/label/index.ts +401 -0
- package/src/tools/label/mediumEditor.ts +94 -0
- package/src/tools/label/utils.ts +395 -0
- package/src/tools/snapshot/README.md +141 -5
- package/src/tools/snapshot/index.ts +288 -101
- package/src/tools/snapshot/utils.ts +163 -0
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
import LogicFlow, {
|
|
2
|
+
observable,
|
|
3
|
+
BaseEdgeModel,
|
|
4
|
+
ElementType,
|
|
5
|
+
GraphModel,
|
|
6
|
+
IRectNodeProperties,
|
|
7
|
+
RectNodeModel,
|
|
8
|
+
} from '@logicflow/core'
|
|
9
|
+
import { forEach } from 'lodash-es'
|
|
10
|
+
|
|
11
|
+
import NodeData = LogicFlow.NodeData
|
|
12
|
+
import NodeConfig = LogicFlow.NodeConfig
|
|
13
|
+
import EdgeConfig = LogicFlow.EdgeConfig
|
|
14
|
+
|
|
15
|
+
export type IGroupNodeProperties = {
|
|
16
|
+
/**
|
|
17
|
+
* 当前分组中的节点 id
|
|
18
|
+
*/
|
|
19
|
+
children?: string[]
|
|
20
|
+
/**
|
|
21
|
+
* 分组节点是否可以折叠
|
|
22
|
+
*/
|
|
23
|
+
collapsible?: boolean
|
|
24
|
+
/**
|
|
25
|
+
* 分组节点折叠状态
|
|
26
|
+
*/
|
|
27
|
+
isCollapsed?: boolean
|
|
28
|
+
/**
|
|
29
|
+
* 子节点是否限制移动范围
|
|
30
|
+
* 默认为 false,允许拖拽移除分组
|
|
31
|
+
*/
|
|
32
|
+
isRestrict?: boolean
|
|
33
|
+
/**
|
|
34
|
+
* isRestrict 模式启用时,
|
|
35
|
+
* 如果同时设置 autoResize 为 true,
|
|
36
|
+
* 那么子节点在父节点中移动时,父节点会自动调整大小
|
|
37
|
+
*/
|
|
38
|
+
autoResize?: boolean
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 分组节点的收起状态宽高
|
|
42
|
+
*/
|
|
43
|
+
collapsedWidth?: number
|
|
44
|
+
collapsedHeight?: number
|
|
45
|
+
// 默认宽高作为 group 的展开宽高
|
|
46
|
+
// /**
|
|
47
|
+
// * 分组节点的展开状态宽高
|
|
48
|
+
// */
|
|
49
|
+
// expandWidth?: number
|
|
50
|
+
// expandHeight?: number
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 当前分组元素的 zIndex
|
|
54
|
+
*/
|
|
55
|
+
zIndex?: number
|
|
56
|
+
/**
|
|
57
|
+
* 分组节点是否自动置顶
|
|
58
|
+
*/
|
|
59
|
+
autoToFront?: boolean
|
|
60
|
+
|
|
61
|
+
// 节点是否允许添加到分组中,是否可以通过 properties 的方式传入
|
|
62
|
+
// TODO: 函数类型的 properties 该如何传入
|
|
63
|
+
isAllowAppendIn?: (_nodeData) => boolean
|
|
64
|
+
} & IRectNodeProperties
|
|
65
|
+
|
|
66
|
+
// 分组节点默认展开时的大小
|
|
67
|
+
const DEFAULT_GROUP_EXPAND_WIDTH = 400
|
|
68
|
+
const DEFAULT_GROUP_EXPAND_HEIGHT = 230
|
|
69
|
+
// 分组节点默认收起时的大小
|
|
70
|
+
const DEFAULT_GROUP_COLLAPSE_WIDTH = 80
|
|
71
|
+
const DEFAULT_GROUP_COLLAPSE_HEIGHT = 60
|
|
72
|
+
|
|
73
|
+
const DEFAULT_BOTTOM_Z_INDEX = -10000
|
|
74
|
+
|
|
75
|
+
export class DynamicGroupNodeModel extends RectNodeModel<IGroupNodeProperties> {
|
|
76
|
+
readonly isGroup = true
|
|
77
|
+
|
|
78
|
+
// 保存组内的节点
|
|
79
|
+
children!: Set<string>
|
|
80
|
+
// 是否限制组内节点的移动范围。默认不限制 TODO: 完善该功能
|
|
81
|
+
isRestrict: boolean = false
|
|
82
|
+
// 分组节点是否可以折叠
|
|
83
|
+
collapsible: boolean = true
|
|
84
|
+
|
|
85
|
+
// 分组节点 初始化尺寸(默认展开),后续支持从 properties 中传入 width 和 height 设置
|
|
86
|
+
expandWidth!: number
|
|
87
|
+
expandHeight!: number
|
|
88
|
+
// 折叠后
|
|
89
|
+
collapsedWidth!: number
|
|
90
|
+
collapsedHeight!: number
|
|
91
|
+
|
|
92
|
+
// 当前组是否收起状态
|
|
93
|
+
@observable isCollapsed: boolean = false
|
|
94
|
+
// 当前分组是否在可添加状态 - 实时状态
|
|
95
|
+
@observable groupAddable: boolean = false
|
|
96
|
+
// 缩放或旋转容器时,是否缩放或旋转组内节点
|
|
97
|
+
@observable transformWidthContainer: boolean = true
|
|
98
|
+
childrenLastCollapseStateDict: Record<string, boolean> = {}
|
|
99
|
+
|
|
100
|
+
constructor(data: NodeConfig<IGroupNodeProperties>, graphModel: GraphModel) {
|
|
101
|
+
super(data, graphModel)
|
|
102
|
+
this.initNodeData(data)
|
|
103
|
+
|
|
104
|
+
this.setAttributes()
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
initNodeData(data: LogicFlow.NodeConfig<IGroupNodeProperties>) {
|
|
108
|
+
super.initNodeData(data)
|
|
109
|
+
|
|
110
|
+
const {
|
|
111
|
+
children,
|
|
112
|
+
width,
|
|
113
|
+
height,
|
|
114
|
+
collapsedWidth,
|
|
115
|
+
collapsedHeight,
|
|
116
|
+
|
|
117
|
+
collapsible,
|
|
118
|
+
isCollapsed,
|
|
119
|
+
zIndex,
|
|
120
|
+
isRestrict,
|
|
121
|
+
autoToFront,
|
|
122
|
+
} = data.properties ?? {}
|
|
123
|
+
|
|
124
|
+
this.children = children ? new Set(children) : new Set()
|
|
125
|
+
this.zIndex = zIndex ?? DEFAULT_BOTTOM_Z_INDEX
|
|
126
|
+
this.isCollapsed = isCollapsed ?? false
|
|
127
|
+
|
|
128
|
+
const expandWidth = width ?? DEFAULT_GROUP_EXPAND_WIDTH
|
|
129
|
+
const expandHeight = height ?? DEFAULT_GROUP_EXPAND_HEIGHT
|
|
130
|
+
|
|
131
|
+
// 初始化分组节点的宽高数据
|
|
132
|
+
this.width = expandWidth
|
|
133
|
+
this.height = expandHeight
|
|
134
|
+
this.expandWidth = expandWidth
|
|
135
|
+
this.expandHeight = expandHeight
|
|
136
|
+
this.collapsedWidth = collapsedWidth ?? DEFAULT_GROUP_COLLAPSE_WIDTH
|
|
137
|
+
this.collapsedHeight = collapsedHeight ?? DEFAULT_GROUP_COLLAPSE_HEIGHT
|
|
138
|
+
|
|
139
|
+
this.isRestrict = isRestrict ?? false
|
|
140
|
+
this.collapsible = collapsible ?? true
|
|
141
|
+
this.autoToFront = autoToFront ?? false
|
|
142
|
+
|
|
143
|
+
// 禁用掉 Group 节点的文本编辑能力
|
|
144
|
+
this.text.editable = false
|
|
145
|
+
this.text.draggable = false
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
setAttributes() {
|
|
149
|
+
super.setAttributes()
|
|
150
|
+
|
|
151
|
+
// 初始化时,如果 this.isCollapsed 为 true,则主动触发一次折叠操作
|
|
152
|
+
if (this.isCollapsed) {
|
|
153
|
+
this.toggleCollapse(true)
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
getData(): NodeData {
|
|
158
|
+
const data = super.getData()
|
|
159
|
+
const children: string[] = []
|
|
160
|
+
|
|
161
|
+
forEach(Array.from(this.children), (childId) => {
|
|
162
|
+
const model = this.graphModel.getNodeModelById(childId)
|
|
163
|
+
if (model && !model.virtual) {
|
|
164
|
+
children.push(childId)
|
|
165
|
+
}
|
|
166
|
+
})
|
|
167
|
+
data.children = children
|
|
168
|
+
|
|
169
|
+
if (data.properties) {
|
|
170
|
+
data.properties.children = children
|
|
171
|
+
data.properties.isCollapsed = this.isCollapsed
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return data
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* 重写 getHistoryData 方法
|
|
179
|
+
*/
|
|
180
|
+
getHistoryData(): NodeData {
|
|
181
|
+
const data = super.getHistoryData()
|
|
182
|
+
data.children = Array.from(this.children)
|
|
183
|
+
data.isGroup = true
|
|
184
|
+
|
|
185
|
+
const {
|
|
186
|
+
x,
|
|
187
|
+
y,
|
|
188
|
+
collapsedWidth,
|
|
189
|
+
collapsedHeight,
|
|
190
|
+
expandWidth,
|
|
191
|
+
expandHeight,
|
|
192
|
+
isCollapsed,
|
|
193
|
+
} = this
|
|
194
|
+
if (isCollapsed) {
|
|
195
|
+
data.x = x + expandWidth / 2 - collapsedWidth / 2
|
|
196
|
+
data.y = y + expandHeight / 2 - collapsedHeight / 2
|
|
197
|
+
}
|
|
198
|
+
return data
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* 触发分组节点的「折叠 or 展开」动作
|
|
203
|
+
* 1. 折叠分组的宽高
|
|
204
|
+
* 2. 处理分组子节点
|
|
205
|
+
* 3. 处理连线
|
|
206
|
+
* @param collapse {boolean} true -> 折叠;false -> 展开
|
|
207
|
+
*/
|
|
208
|
+
toggleCollapse(collapse?: boolean) {
|
|
209
|
+
const nextCollapseState = !!collapse
|
|
210
|
+
this.isCollapsed = nextCollapseState
|
|
211
|
+
// step 1
|
|
212
|
+
if (nextCollapseState) {
|
|
213
|
+
this.collapse()
|
|
214
|
+
} else {
|
|
215
|
+
this.expand()
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// step 2
|
|
219
|
+
let allRelatedEdges = [...this.incoming.edges, ...this.outgoing.edges]
|
|
220
|
+
console.log('this -->>', this)
|
|
221
|
+
console.log('this.children -->>', this.children)
|
|
222
|
+
const childrenArr = Array.from(this.children)
|
|
223
|
+
forEach(childrenArr, (elementId) => {
|
|
224
|
+
const model = this.graphModel.getElement(elementId)
|
|
225
|
+
|
|
226
|
+
if (model) {
|
|
227
|
+
// TODO: ??? 普通节点有这个属性吗?确认这个代码的意义
|
|
228
|
+
const collapseStatus = model.isCollapsed
|
|
229
|
+
// FIX: https://github.com/didi/LogicFlow/issues/1007
|
|
230
|
+
// 下面代码片段,针对 Group 节点执行
|
|
231
|
+
if (model.isGroup) {
|
|
232
|
+
const groupModel = model as DynamicGroupNodeModel
|
|
233
|
+
|
|
234
|
+
if (!groupModel.isCollapsed) {
|
|
235
|
+
// 正常情况下,parent 折叠后,children 也应该折叠
|
|
236
|
+
// 因此当前 parent 准备展开时,children 的目前状态肯定是折叠状态,也就是 model.isCollapsed 为 true,这个代码块不会触发
|
|
237
|
+
// 只有当 parent 准备折叠时,children 目前状态才有可能是展开
|
|
238
|
+
// 即 model.isCollapsed 为 false,这个代码块触发, 此时 isCollapse 为 true,触发 children 也进行折叠
|
|
239
|
+
groupModel.toggleCollapse(collapse)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (!collapse) {
|
|
243
|
+
// 当 parent 准备展开时,children 的值应该恢复到折叠前的状态
|
|
244
|
+
const lastCollapseStatus =
|
|
245
|
+
this.childrenLastCollapseStateDict[elementId]
|
|
246
|
+
if (
|
|
247
|
+
lastCollapseStatus !== undefined &&
|
|
248
|
+
lastCollapseStatus !== model.isCollapsed
|
|
249
|
+
) {
|
|
250
|
+
// https://github.com/didi/LogicFlow/issues/1145
|
|
251
|
+
// 当parent准备展开时,children的值肯定是折叠,也就是nodeModel.isCollapsed=true
|
|
252
|
+
// 当parent准备展开时,如果children之前的状态是展开,则恢复展开状态
|
|
253
|
+
groupModel.toggleCollapse(lastCollapseStatus)
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
this.childrenLastCollapseStateDict[elementId] = !!collapseStatus
|
|
259
|
+
model.visible = !collapse
|
|
260
|
+
|
|
261
|
+
// 判断,如果是节点时,才去读取节点的 incoming 和 outgoing
|
|
262
|
+
if (model.BaseType === ElementType.NODE) {
|
|
263
|
+
const incomingEdges = model.incoming.edges
|
|
264
|
+
const outgoingEdges = model.outgoing.edges
|
|
265
|
+
|
|
266
|
+
allRelatedEdges = [
|
|
267
|
+
...allRelatedEdges,
|
|
268
|
+
...incomingEdges,
|
|
269
|
+
...outgoingEdges,
|
|
270
|
+
]
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
})
|
|
274
|
+
// step 3
|
|
275
|
+
this.collapseEdge(nextCollapseState, allRelatedEdges)
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// 折叠操作
|
|
279
|
+
private collapse() {
|
|
280
|
+
const { x, y, text, width, height, collapsedWidth, collapsedHeight } = this
|
|
281
|
+
this.x = x - width / 2 + collapsedWidth / 2
|
|
282
|
+
this.y = y - height / 2 + collapsedHeight / 2
|
|
283
|
+
|
|
284
|
+
this.text.x = text.x - width / 2 + collapsedWidth / 2
|
|
285
|
+
this.text.y = text.y - height / 2 + collapsedHeight / 2
|
|
286
|
+
|
|
287
|
+
// 记录折叠前的节点大小,并将其记录到 expandWidth 中
|
|
288
|
+
this.expandWidth = width
|
|
289
|
+
this.expandHeight = height
|
|
290
|
+
|
|
291
|
+
this.width = collapsedWidth
|
|
292
|
+
this.height = collapsedHeight
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// 展开操作
|
|
296
|
+
private expand() {
|
|
297
|
+
const {
|
|
298
|
+
x,
|
|
299
|
+
y,
|
|
300
|
+
text,
|
|
301
|
+
expandWidth,
|
|
302
|
+
expandHeight,
|
|
303
|
+
collapsedWidth,
|
|
304
|
+
collapsedHeight,
|
|
305
|
+
} = this
|
|
306
|
+
this.width = expandWidth
|
|
307
|
+
this.height = expandHeight
|
|
308
|
+
|
|
309
|
+
// 重新计算节点及文本的坐标
|
|
310
|
+
this.x = x + this.width / 2 - collapsedWidth / 2
|
|
311
|
+
this.y = y + this.height / 2 - collapsedHeight / 2
|
|
312
|
+
|
|
313
|
+
this.text.x = text.x + this.width / 2 - collapsedWidth / 2
|
|
314
|
+
this.text.y = text.y + this.height / 2 - collapsedHeight / 2
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
createVirtualEdge(edgeConfig: EdgeConfig) {
|
|
318
|
+
edgeConfig.pointsList = undefined
|
|
319
|
+
|
|
320
|
+
const virtualEdge = this.graphModel.addEdge(edgeConfig)
|
|
321
|
+
virtualEdge.virtual = true
|
|
322
|
+
|
|
323
|
+
// TODO: 强制不保存 group 连线数据???-> 为什么注释掉?是不是不能强制设置为 null,会导致无法回填
|
|
324
|
+
// virtualEdge.getData = () => null
|
|
325
|
+
virtualEdge.text.editable = false
|
|
326
|
+
virtualEdge.isCollapsedEdge = true // 这一行干啥的,TODO: 项目中没搜到应用的地方,是否应该移除
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* 折叠分组的时候,需要处理分组自身的连线和分组内部子节点上的连线
|
|
331
|
+
* 边的分类:
|
|
332
|
+
* - 虚拟边:分组被收起时,标识分组本身与外部节点关系的边
|
|
333
|
+
* - 真实边:分组本身或者分组内部节点与外部节点(非收起分组)关系的边
|
|
334
|
+
* 如果一个分组,本身与外部节点有 M 条连线,且内部 N 个子节点与外部节点有连线,那么这个分组收起时会生成 M+N 条连线
|
|
335
|
+
* 折叠分组时:
|
|
336
|
+
* - 原有的虚拟边删除
|
|
337
|
+
* - 创建一个虚拟边
|
|
338
|
+
* - 真实边则隐藏
|
|
339
|
+
* 展开分组时:
|
|
340
|
+
* - 当前的虚拟边删除
|
|
341
|
+
* - 如果外部节点是收起的分组,则创建虚拟边
|
|
342
|
+
* - 如果外部节点是普通节点,则显示真实边
|
|
343
|
+
*
|
|
344
|
+
* @param collapse
|
|
345
|
+
* @param edges
|
|
346
|
+
*/
|
|
347
|
+
collapseEdge(collapse: boolean, edges: BaseEdgeModel[]) {
|
|
348
|
+
const { graphModel } = this
|
|
349
|
+
forEach(edges, (edge, idx) => {
|
|
350
|
+
const edgeData = edge.getData()
|
|
351
|
+
const { targetNodeId, sourceNodeId } = edgeData
|
|
352
|
+
|
|
353
|
+
const edgeConfig: EdgeConfig = {
|
|
354
|
+
...edgeData,
|
|
355
|
+
id: `${edgeData.id}__${idx}`,
|
|
356
|
+
text: edgeData.text?.value,
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if (edge.virtual) {
|
|
360
|
+
graphModel.deleteEdgeById(edge.id)
|
|
361
|
+
}
|
|
362
|
+
// 考虑目标节点也属于分组的情况
|
|
363
|
+
let targetNodeGroup = graphModel.group.getGroupByNodeId(targetNodeId)
|
|
364
|
+
if (!targetNodeGroup) {
|
|
365
|
+
targetNodeGroup = graphModel.getNodeModelById(targetNodeId)
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// 考虑源节点也属于分组的情况
|
|
369
|
+
let sourceNodeGroup = graphModel.group.getGroupByNodeId(sourceNodeId)
|
|
370
|
+
if (!sourceNodeGroup) {
|
|
371
|
+
sourceNodeGroup = graphModel.getNodeModelById(sourceNodeId)
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// 折叠时,处理未被隐藏的边的逻辑 -> collapse
|
|
375
|
+
if (collapse && edge.visible) {
|
|
376
|
+
// 需要确认此分组节点是新连线的起点还是终点
|
|
377
|
+
// 创建一个虚拟边,虚拟边相对于真实边,起点或者终点从一起分组节点的中心点开始 TODO:??? 确认什么意思
|
|
378
|
+
// 如果需要被隐藏的边的起点在需要折叠的分组中,那么设置虚拟边的开始节点为此分组
|
|
379
|
+
if (this.children.has(sourceNodeId) || this.id === sourceNodeId) {
|
|
380
|
+
edgeConfig.startPoint = undefined
|
|
381
|
+
edgeConfig.sourceNodeId = this.id
|
|
382
|
+
} else {
|
|
383
|
+
edgeConfig.endPoint = undefined
|
|
384
|
+
edgeConfig.targetNodeId = this.id
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// 如果边的起点和终点都在分组内部,则不创建新的虚拟边
|
|
388
|
+
if (targetNodeGroup.id !== this.id || sourceNodeGroup.id !== this.id) {
|
|
389
|
+
this.createVirtualEdge(edgeConfig)
|
|
390
|
+
}
|
|
391
|
+
edge.visible = false
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// 展开时,处理被隐藏的边的逻辑 -> expand
|
|
395
|
+
if (!collapse && !edge.visible) {
|
|
396
|
+
// 展开分组时:判断真实边的起点和中带你是否有任一节点在已折叠分组中,如果不是,则显示真实边
|
|
397
|
+
// 如果是,则修改这个边的对应目标节点 id 来创建虚拟边
|
|
398
|
+
if (
|
|
399
|
+
targetNodeGroup &&
|
|
400
|
+
targetNodeGroup.isGroup &&
|
|
401
|
+
targetNodeGroup.isCollapsed
|
|
402
|
+
) {
|
|
403
|
+
edgeConfig.targetNodeId = targetNodeGroup.id
|
|
404
|
+
edgeConfig.endPoint = undefined
|
|
405
|
+
this.createVirtualEdge(edgeConfig)
|
|
406
|
+
} else if (
|
|
407
|
+
sourceNodeGroup &&
|
|
408
|
+
sourceNodeGroup.isGroup &&
|
|
409
|
+
sourceNodeGroup.isCollapsed
|
|
410
|
+
) {
|
|
411
|
+
edgeConfig.sourceNodeId = sourceNodeGroup.id
|
|
412
|
+
edgeConfig.startPoint = undefined
|
|
413
|
+
this.createVirtualEdge(edgeConfig)
|
|
414
|
+
} else {
|
|
415
|
+
edge.visible = true
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
})
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* 是否允许此节点添加到该分组
|
|
423
|
+
* TODO: 如何重写该方法呢?
|
|
424
|
+
* @param _nodeData
|
|
425
|
+
*/
|
|
426
|
+
isAllowAppendIn(_nodeData: NodeData) {
|
|
427
|
+
console.info('_nodeData', _nodeData)
|
|
428
|
+
// TODO: 此处使用 this.properties.groupAddable 还是 this.groupAddable
|
|
429
|
+
// this.groupAddable 是否存在更新不及时的问题
|
|
430
|
+
return true
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* 更新分组节点是否允许添加节点的属性
|
|
435
|
+
* @param isAllow
|
|
436
|
+
*/
|
|
437
|
+
setAllowAppendChild(isAllow: boolean) {
|
|
438
|
+
// this.setProperty('groupAddable', isAllow)
|
|
439
|
+
this.groupAddable = isAllow
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* 添加节点至分组中
|
|
444
|
+
* @param id
|
|
445
|
+
*/
|
|
446
|
+
addChild(id: string) {
|
|
447
|
+
this.children.add(id)
|
|
448
|
+
const groupData = this.getData()
|
|
449
|
+
this.graphModel.eventCenter.emit('group:add-node', { data: groupData })
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* 从分组中移除某节点
|
|
454
|
+
* @param id
|
|
455
|
+
*/
|
|
456
|
+
removeChild(id: string) {
|
|
457
|
+
this.children.delete(id)
|
|
458
|
+
const groupData = this.getData()
|
|
459
|
+
this.graphModel.eventCenter.emit('group:remove-node', { data: groupData })
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* 当 groupA 被添加到 groupB 中时,将 groupB 及 groupB 所属的 group zIndex 减 1
|
|
464
|
+
*/
|
|
465
|
+
toBack() {
|
|
466
|
+
this.zIndex--
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* 重写 Group 节点的 Resize Outline
|
|
471
|
+
*/
|
|
472
|
+
getResizeOutlineStyle(): LogicFlow.CommonTheme {
|
|
473
|
+
const style = super.getResizeOutlineStyle()
|
|
474
|
+
style.stroke = 'none'
|
|
475
|
+
return style
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// TODO: 是否是设置 group 节点没有锚点,而不是设置成透明???
|
|
479
|
+
getAnchorStyle() {
|
|
480
|
+
const style = super.getAnchorStyle()
|
|
481
|
+
style.stroke = 'transparent'
|
|
482
|
+
style.fill = 'transparent'
|
|
483
|
+
if (style.hover) {
|
|
484
|
+
style.hover.fill = 'transparent'
|
|
485
|
+
style.hover.stroke = 'transparent'
|
|
486
|
+
}
|
|
487
|
+
return style
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* 设置分组节点 drop 区域的样式
|
|
492
|
+
*/
|
|
493
|
+
getAddableOutlineStyle() {
|
|
494
|
+
return {
|
|
495
|
+
stroke: '#feb663',
|
|
496
|
+
strokeWidth: 2,
|
|
497
|
+
strokeDasharray: '4 4',
|
|
498
|
+
fill: 'transparent',
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
export default DynamicGroupNodeModel
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { GraphModel, h, RectNode } from '@logicflow/core'
|
|
2
|
+
import { forEach } from 'lodash-es'
|
|
3
|
+
import { DynamicGroupNodeModel } from './model'
|
|
4
|
+
import { handleResize } from '@logicflow/core/es/util/resize'
|
|
5
|
+
|
|
6
|
+
export interface IDynamicGroupNodeProps {
|
|
7
|
+
model: DynamicGroupNodeModel
|
|
8
|
+
graphModel: GraphModel
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class DynamicGroupNode<
|
|
12
|
+
P extends IDynamicGroupNodeProps = IDynamicGroupNodeProps,
|
|
13
|
+
> extends RectNode<P> {
|
|
14
|
+
componentDidMount() {
|
|
15
|
+
super.componentDidMount()
|
|
16
|
+
|
|
17
|
+
const { model: curGroup, graphModel } = this.props
|
|
18
|
+
const { eventCenter } = graphModel
|
|
19
|
+
|
|
20
|
+
// 在 group 旋转时,对组内的所有子节点也进行对应的旋转计算
|
|
21
|
+
eventCenter.on('node:rotate', ({ model }) => {
|
|
22
|
+
if (model.id === curGroup.id) {
|
|
23
|
+
forEach(Array.from(curGroup.children), (childId) => {
|
|
24
|
+
const child = graphModel.getNodeModelById(childId)
|
|
25
|
+
if (child) {
|
|
26
|
+
child.rotate = model.rotate
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
// 在 group 缩放时,对组内的所有子节点也进行对应的缩放计算
|
|
33
|
+
eventCenter.on('node:resize', ({ deltaX, deltaY, index, model }) => {
|
|
34
|
+
if (model.id === curGroup.id) {
|
|
35
|
+
forEach(Array.from(curGroup.children), (childId) => {
|
|
36
|
+
const child = graphModel.getNodeModelById(childId)
|
|
37
|
+
if (child) {
|
|
38
|
+
// child.rotate = model.rotate
|
|
39
|
+
handleResize({
|
|
40
|
+
deltaX,
|
|
41
|
+
deltaY,
|
|
42
|
+
index,
|
|
43
|
+
nodeModel: child,
|
|
44
|
+
graphModel,
|
|
45
|
+
cancelCallback: () => {},
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
getResizeControl(): h.JSX.Element | null {
|
|
54
|
+
const { resizable, isCollapsed } = this.props.model
|
|
55
|
+
const showResizeControl = resizable && !isCollapsed
|
|
56
|
+
return showResizeControl ? super.getResizeControl() : null
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
getAppendAreaShape(): h.JSX.Element | null {
|
|
60
|
+
// DONE: 此区域用于初始化 group container, 即元素拖拽进入感应区域
|
|
61
|
+
const { model } = this.props
|
|
62
|
+
const { width, height, x, y, radius, groupAddable } = model
|
|
63
|
+
if (!groupAddable) return null
|
|
64
|
+
|
|
65
|
+
const { strokeWidth = 0 } = model.getNodeStyle()
|
|
66
|
+
const style = model.getAddableOutlineStyle()
|
|
67
|
+
|
|
68
|
+
const newWidth = width + strokeWidth + 8
|
|
69
|
+
const newHeight = height + strokeWidth + 8
|
|
70
|
+
return h('rect', {
|
|
71
|
+
...style,
|
|
72
|
+
width: newWidth,
|
|
73
|
+
height: newHeight,
|
|
74
|
+
x: x - newWidth / 2,
|
|
75
|
+
y: y - newHeight / 2,
|
|
76
|
+
rx: radius,
|
|
77
|
+
ry: radius,
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
getCollapseIcon(sx: number, sy: number): string {
|
|
82
|
+
return `M ${sx + 3},${sy + 6} ${sx + 11},${sy + 6} M${sx + 7},${sy + 2} ${
|
|
83
|
+
sx + 7
|
|
84
|
+
},${sy + 10}`
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
getExpandIcon(sx: number, sy: number): string {
|
|
88
|
+
return `M ${sx + 3},${sy + 6} ${sx + 11},${sy + 6} `
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 获取操作图标(收起或展开)
|
|
92
|
+
getOperateIcon(): h.JSX.Element | null {
|
|
93
|
+
const { model } = this.props
|
|
94
|
+
const { x, y, width, height } = model
|
|
95
|
+
const sx = x - width / 2 + 10
|
|
96
|
+
const sy = y - height / 2 + 10
|
|
97
|
+
|
|
98
|
+
if (!model.collapsible) return null
|
|
99
|
+
const iconPath = model?.isCollapsed
|
|
100
|
+
? this.getCollapseIcon(sx, sy)
|
|
101
|
+
: this.getExpandIcon(sx, sy)
|
|
102
|
+
|
|
103
|
+
const operateIcon = h('path', {
|
|
104
|
+
fill: 'none',
|
|
105
|
+
stroke: '#818281',
|
|
106
|
+
strokeWidth: 2,
|
|
107
|
+
'pointer-events': 'none',
|
|
108
|
+
d: iconPath,
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
return h('g', {}, [
|
|
112
|
+
h('rect', {
|
|
113
|
+
height: 12,
|
|
114
|
+
width: 14,
|
|
115
|
+
rx: 2,
|
|
116
|
+
ry: 2,
|
|
117
|
+
strokeWidth: 1,
|
|
118
|
+
fill: '#f4f5f6',
|
|
119
|
+
stroke: '#cecece',
|
|
120
|
+
cursor: 'pointer',
|
|
121
|
+
x: sx,
|
|
122
|
+
y: sy,
|
|
123
|
+
onClick: () => {
|
|
124
|
+
model.toggleCollapse(!model.isCollapsed)
|
|
125
|
+
},
|
|
126
|
+
}),
|
|
127
|
+
operateIcon,
|
|
128
|
+
])
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
getShape(): h.JSX.Element | null {
|
|
132
|
+
return h('g', {}, [
|
|
133
|
+
this.getAppendAreaShape(),
|
|
134
|
+
super.getShape(),
|
|
135
|
+
this.getOperateIcon(),
|
|
136
|
+
])
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export default DynamicGroupNode
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { BaseNodeModel, Model } from '@logicflow/core'
|
|
2
|
+
import BoxBoundsPoint = Model.BoxBoundsPoint
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param bounds
|
|
7
|
+
* @param group
|
|
8
|
+
*/
|
|
9
|
+
export function isBoundsInGroup(bounds: BoxBoundsPoint, group: BaseNodeModel) {
|
|
10
|
+
const { minX, minY, maxX, maxY } = bounds
|
|
11
|
+
const { x, y, width, height } = group
|
|
12
|
+
return (
|
|
13
|
+
minX >= x - width / 2 &&
|
|
14
|
+
maxX <= x + width / 2 &&
|
|
15
|
+
minY >= y - height / 2 &&
|
|
16
|
+
maxY <= y + height / 2
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 判断 bounds 是否可以移动到下一个范围
|
|
22
|
+
* @param bounds
|
|
23
|
+
* @param group
|
|
24
|
+
*/
|
|
25
|
+
export function isAllowMoveTo(bounds: BoxBoundsPoint, group: BaseNodeModel) {
|
|
26
|
+
const { minX, minY, maxX, maxY } = bounds
|
|
27
|
+
const { x, y, width, height } = group
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
x: minX >= x - width / 2 && maxX <= x + width / 2,
|
|
31
|
+
y: minY >= y - height / 2 && maxY <= y + height / 2,
|
|
32
|
+
}
|
|
33
|
+
}
|