@logicflow/core 2.2.0-alpha.7 → 2.2.1

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 (137) hide show
  1. package/package.json +6 -1
  2. package/.turbo/turbo-build$colon$dev.log +0 -10
  3. package/.turbo/turbo-build.log +0 -33
  4. package/CHANGELOG.md +0 -1901
  5. package/__tests__/algorithm/egde.test.ts +0 -131
  6. package/__tests__/algorithm/index.test.ts +0 -74
  7. package/__tests__/algorithm/outline.test.ts +0 -43
  8. package/__tests__/bugs/1545-spec.test.ts +0 -42
  9. package/__tests__/event/event.test.ts +0 -22
  10. package/__tests__/history/history.test.ts +0 -28
  11. package/__tests__/logicflow.test.ts +0 -575
  12. package/__tests__/model/graphmodel.test.ts +0 -87
  13. package/__tests__/util/compatible.test.ts +0 -48
  14. package/__tests__/util/edge.test.ts +0 -224
  15. package/__tests__/util/geometry.test.ts +0 -14
  16. package/__tests__/util/graph.test.ts +0 -16
  17. package/__tests__/util/matrix.test.ts +0 -41
  18. package/__tests__/util/node.test.ts +0 -68
  19. package/__tests__/util/sampling.test.ts +0 -12
  20. package/__tests__/util/vector.test.ts +0 -50
  21. package/__tests__/util/zIndex.test.ts +0 -10
  22. package/src/LogicFlow.tsx +0 -2017
  23. package/src/algorithm/edge.ts +0 -67
  24. package/src/algorithm/index.ts +0 -70
  25. package/src/algorithm/outline.ts +0 -77
  26. package/src/algorithm/rotate.ts +0 -55
  27. package/src/common/drag.ts +0 -219
  28. package/src/common/history.ts +0 -108
  29. package/src/common/index.ts +0 -6
  30. package/src/common/keyboard.ts +0 -108
  31. package/src/common/matrix.ts +0 -122
  32. package/src/common/vector.ts +0 -93
  33. package/src/constant/index.ts +0 -179
  34. package/src/constant/theme.ts +0 -708
  35. package/src/event/event.md +0 -66
  36. package/src/event/eventArgs.ts +0 -643
  37. package/src/event/eventEmitter.ts +0 -156
  38. package/src/history/index.ts +0 -119
  39. package/src/index.less +0 -1
  40. package/src/index.ts +0 -26
  41. package/src/keyboard/index.ts +0 -112
  42. package/src/keyboard/shortcut.ts +0 -200
  43. package/src/model/BaseModel.ts +0 -250
  44. package/src/model/EditConfigModel.ts +0 -334
  45. package/src/model/GraphModel.ts +0 -1824
  46. package/src/model/NestedTransformModel.ts +0 -121
  47. package/src/model/SnaplineModel.ts +0 -256
  48. package/src/model/TransformModel.ts +0 -258
  49. package/src/model/edge/BaseEdgeModel.ts +0 -785
  50. package/src/model/edge/BezierEdgeModel.ts +0 -197
  51. package/src/model/edge/LineEdgeModel.ts +0 -36
  52. package/src/model/edge/PolylineEdgeModel.ts +0 -817
  53. package/src/model/edge/index.ts +0 -4
  54. package/src/model/index.ts +0 -9
  55. package/src/model/node/BaseNodeModel.ts +0 -959
  56. package/src/model/node/CircleNodeModel.ts +0 -91
  57. package/src/model/node/DiamondNodeModel.ts +0 -132
  58. package/src/model/node/EllipseNodeModel.ts +0 -98
  59. package/src/model/node/HtmlNodeModel.ts +0 -64
  60. package/src/model/node/PolygonNodeModel.ts +0 -152
  61. package/src/model/node/RectNodeModel.ts +0 -69
  62. package/src/model/node/TextNodeModel.ts +0 -54
  63. package/src/model/node/index.ts +0 -8
  64. package/src/options.ts +0 -150
  65. package/src/style/index.less +0 -262
  66. package/src/style/raw.ts +0 -221
  67. package/src/tool/MultipleSelectTool.tsx +0 -140
  68. package/src/tool/TextEditTool.tsx +0 -193
  69. package/src/tool/index.ts +0 -101
  70. package/src/typings.d.ts +0 -5
  71. package/src/util/animation.ts +0 -29
  72. package/src/util/browser.ts +0 -4
  73. package/src/util/compatible.ts +0 -15
  74. package/src/util/drag.ts +0 -219
  75. package/src/util/edge.ts +0 -1094
  76. package/src/util/geometry.ts +0 -154
  77. package/src/util/graph.ts +0 -46
  78. package/src/util/index.ts +0 -17
  79. package/src/util/matrix.ts +0 -129
  80. package/src/util/mobx.ts +0 -23
  81. package/src/util/node.ts +0 -543
  82. package/src/util/raf.ts +0 -28
  83. package/src/util/resize.ts +0 -606
  84. package/src/util/sampling.ts +0 -85
  85. package/src/util/theme.ts +0 -84
  86. package/src/util/uuid.ts +0 -26
  87. package/src/util/vector.ts +0 -93
  88. package/src/util/zIndex.ts +0 -6
  89. package/src/view/Anchor.tsx +0 -462
  90. package/src/view/Control.tsx +0 -510
  91. package/src/view/Graph.tsx +0 -141
  92. package/src/view/Rotate.tsx +0 -113
  93. package/src/view/behavior/dnd.ts +0 -162
  94. package/src/view/behavior/index.ts +0 -2
  95. package/src/view/behavior/snapline.ts +0 -16
  96. package/src/view/edge/AdjustPoint.tsx +0 -425
  97. package/src/view/edge/Arrow.tsx +0 -54
  98. package/src/view/edge/BaseEdge.tsx +0 -660
  99. package/src/view/edge/BezierEdge.tsx +0 -101
  100. package/src/view/edge/LineEdge.tsx +0 -81
  101. package/src/view/edge/PolylineEdge.tsx +0 -311
  102. package/src/view/edge/index.ts +0 -6
  103. package/src/view/index.ts +0 -8
  104. package/src/view/node/BaseNode.tsx +0 -585
  105. package/src/view/node/CircleNode.tsx +0 -21
  106. package/src/view/node/DiamondNode.tsx +0 -24
  107. package/src/view/node/EllipseNode.tsx +0 -22
  108. package/src/view/node/HtmlNode.tsx +0 -112
  109. package/src/view/node/PolygonNode.tsx +0 -28
  110. package/src/view/node/RectNode.tsx +0 -30
  111. package/src/view/node/TextNode.tsx +0 -39
  112. package/src/view/node/index.ts +0 -8
  113. package/src/view/overlay/BackgroundOverlay.tsx +0 -34
  114. package/src/view/overlay/BezierAdjustOverlay.tsx +0 -150
  115. package/src/view/overlay/CanvasOverlay.tsx +0 -290
  116. package/src/view/overlay/Grid.tsx +0 -319
  117. package/src/view/overlay/ModificationOverlay.tsx +0 -31
  118. package/src/view/overlay/OutlineOverlay.tsx +0 -158
  119. package/src/view/overlay/SnaplineOverlay.tsx +0 -44
  120. package/src/view/overlay/ToolOverlay.tsx +0 -65
  121. package/src/view/overlay/getTransformHoc.tsx +0 -50
  122. package/src/view/overlay/gridConfig.ts +0 -103
  123. package/src/view/overlay/index.ts +0 -8
  124. package/src/view/shape/Circle.tsx +0 -41
  125. package/src/view/shape/Ellipse.tsx +0 -42
  126. package/src/view/shape/Line.tsx +0 -39
  127. package/src/view/shape/Path.tsx +0 -22
  128. package/src/view/shape/Polygon.tsx +0 -54
  129. package/src/view/shape/Polyline.tsx +0 -31
  130. package/src/view/shape/Rect.tsx +0 -44
  131. package/src/view/shape/Text.tsx +0 -168
  132. package/src/view/shape/index.ts +0 -8
  133. package/src/view/text/BaseText.tsx +0 -134
  134. package/src/view/text/LineText.tsx +0 -168
  135. package/src/view/text/index.ts +0 -2
  136. package/stats.html +0 -4842
  137. package/tsconfig.json +0 -18
package/src/util/theme.ts DELETED
@@ -1,84 +0,0 @@
1
- import { cloneDeep, merge, assign } from 'lodash-es'
2
- import LogicFlow from '../LogicFlow'
3
- import {
4
- themeModeMap,
5
- backgroundModeMap,
6
- defaultBackground,
7
- gridModeMap,
8
- defaultGrid,
9
- } from '../constant/theme'
10
-
11
- /* 主题(全局样式)相关工具方法 */
12
- export const setupTheme = (
13
- customTheme?: Partial<LogicFlow.Theme>,
14
- themeMode?: LogicFlow.ThemeMode | string,
15
- ): LogicFlow.Theme => {
16
- let theme =
17
- cloneDeep(themeModeMap[themeMode || 'default']) ||
18
- cloneDeep(themeModeMap.default)
19
- if (customTheme) {
20
- /**
21
- * 为了不让默认样式被覆盖,使用 merge 方法
22
- * @docs https://lodash.com/docs/4.17.15#merge
23
- * 例如:锚点主题 hover,用户传入如下 ->
24
- * lf.setTheme({
25
- * anchor: {
26
- * fill: 'red'
27
- * }
28
- * })
29
- *
30
- * 预期得到的结果如下:
31
- * {
32
- * // ...
33
- * anchor: {
34
- * stroke: '#000',
35
- * fill: 'red',
36
- * r: 4,
37
- * hover: {
38
- * r: 10,
39
- * fill: '#949494',
40
- * fillOpacity: 0.5,
41
- * stroke: '#949494',
42
- * },
43
- * },
44
- * // ...
45
- * }
46
- */
47
- theme = merge(theme, customTheme)
48
- }
49
- return theme
50
- }
51
-
52
- export const addThemeMode = (
53
- themeMode: string,
54
- style: Partial<LogicFlow.Theme>,
55
- ): void => {
56
- if (themeModeMap[themeMode]) {
57
- console.warn(`theme mode ${themeMode} already exists`)
58
- return
59
- }
60
- themeModeMap[themeMode] = style
61
- backgroundModeMap[themeMode] = style.background || defaultBackground
62
- gridModeMap[themeMode] = style.grid || defaultGrid
63
- }
64
-
65
- export const removeThemeMode = (themeMode: string): void => {
66
- delete themeModeMap[themeMode]
67
- delete backgroundModeMap[themeMode]
68
- delete gridModeMap[themeMode]
69
- }
70
-
71
- export const clearThemeMode = (): void => {
72
- const resetTheme = {
73
- colorful: {},
74
- dark: {},
75
- retro: {},
76
- default: {},
77
- }
78
- assign(themeModeMap, resetTheme)
79
- assign(backgroundModeMap, resetTheme)
80
- assign(gridModeMap, resetTheme)
81
- }
82
-
83
- /* 更新 theme 方法 */
84
- export const updateTheme = setupTheme
package/src/util/uuid.ts DELETED
@@ -1,26 +0,0 @@
1
- import { v4 as uuidV4 } from 'uuid'
2
- import LogicFlow from '../LogicFlow'
3
-
4
- import GraphData = LogicFlow.GraphData
5
-
6
- export const createUuid = (): string => uuidV4()
7
-
8
- /**
9
- * 重新刷新流程图的所有id
10
- */
11
- export const refreshGraphId = (
12
- graphData: GraphData,
13
- prefix = '',
14
- ): GraphData => {
15
- const nodeIdMap = graphData.nodes.reduce((nMap, node) => {
16
- nMap[node.id] = prefix + uuidV4()
17
- node.id = nMap[node.id]
18
- return nMap
19
- }, {})
20
- graphData.edges.forEach((edge) => {
21
- edge.id = prefix + uuidV4()
22
- edge.sourceNodeId = nodeIdMap[edge.sourceNodeId]
23
- edge.targetNodeId = nodeIdMap[edge.targetNodeId]
24
- })
25
- return graphData
26
- }
@@ -1,93 +0,0 @@
1
- function isVector(a1: any, a2: any): boolean {
2
- return !!(a1 instanceof Vector && a2 instanceof Vector)
3
- }
4
-
5
- class Base extends Array<number> {
6
- x: number
7
- y: number
8
- z: number
9
-
10
- constructor(x: number, y: number, z: number) {
11
- super(3)
12
- this[0] = x
13
- this[1] = y
14
- this[2] = z
15
- this.x = x
16
- this.y = y
17
- this.z = z
18
- Object.setPrototypeOf(this, Base.prototype)
19
- }
20
-
21
- add(v1: Vector | Point): Vector | Point {
22
- if (isVector(this, v1)) {
23
- return new Vector(this.x + v1.x, this.y + v1.y)
24
- }
25
- const z = this.z + v1.z
26
- return new Point((this.x + v1.x) / z, (this.y + v1.y) / z)
27
- }
28
-
29
- subtract(v1: Vector | Point): Vector | Point {
30
- if (isVector(this, v1)) {
31
- return new Vector(this.x - v1.x, this.y - v1.y)
32
- }
33
- const z = this.z - v1.z
34
- return z === 0
35
- ? new Vector(this.x - v1.x, this.y - v1.y)
36
- : new Point((this.x - v1.x) / z, (this.y - v1.y) / z)
37
- }
38
- }
39
-
40
- class Vector extends Base {
41
- constructor(x: number, y: number, z?: number) {
42
- super(x, y, z ?? 0)
43
- Object.setPrototypeOf(this, Vector.prototype)
44
- }
45
-
46
- toString(): string {
47
- return 'Vector'
48
- }
49
-
50
- dot(v1: Vector) {
51
- return v1.reduce((prev, cur, index) => prev + cur * this[index])
52
- }
53
-
54
- cross(v1: Vector) {
55
- return new Vector(
56
- this.y * v1.z - this.z * v1.y,
57
- this.z * v1.x - this.x * v1.z,
58
- this.x * v1.y - this.y * v1.x,
59
- )
60
- }
61
-
62
- getLength() {
63
- return Math.hypot(this.x, this.y)
64
- }
65
-
66
- normalize() {
67
- const len = this.getLength()
68
- return new Vector(this.x / len, this.y / len)
69
- }
70
-
71
- crossZ(v1: Vector) {
72
- return this.x * v1.y - this.y * v1.x
73
- }
74
-
75
- angle(v1: Vector) {
76
- const negative = this.crossZ(v1)
77
- const r = Math.acos(this.normalize().dot(v1.normalize()))
78
- return negative >= 0 ? r : -r
79
- }
80
- }
81
-
82
- class Point extends Base {
83
- constructor(x: number, y: number) {
84
- super(x, y, 1)
85
- Object.setPrototypeOf(this, Point.prototype)
86
- }
87
-
88
- toString(): string {
89
- return 'Point'
90
- }
91
- }
92
-
93
- export { Vector, Point }
@@ -1,6 +0,0 @@
1
- let maxIndex = 1000
2
- let minIndex = 999
3
-
4
- export const getZIndex = () => ++maxIndex
5
-
6
- export const getMinIndex = () => --minIndex
@@ -1,462 +0,0 @@
1
- import { Component } from 'preact/compat'
2
- import { Circle, Line } from './shape'
3
- import { BaseNode } from './node'
4
- import LogicFlow from '../LogicFlow'
5
- import { ElementState, EventType } from '../constant'
6
- import { GraphModel, BaseNodeModel, Model } from '../model'
7
- import {
8
- StepDrag,
9
- formatAnchorConnectValidateData,
10
- targetNodeInfo,
11
- distance,
12
- cancelRaf,
13
- createRaf,
14
- IDragParams,
15
- } from '../util'
16
-
17
- import AnchorConfig = Model.AnchorConfig
18
- import NodeData = LogicFlow.NodeData
19
-
20
- interface IProps {
21
- // x: number;
22
- // y: number;
23
- // id?: string;
24
- anchorData: AnchorConfig
25
- node: BaseNode<any>
26
- style?: Record<string, any>
27
- hoverStyle?: Record<string, any>
28
- edgeStyle?: Record<string, any>
29
- anchorIndex: number
30
- graphModel: GraphModel
31
- nodeModel: BaseNodeModel
32
- setHoverOff: (e: PointerEvent) => void
33
- }
34
-
35
- interface IState {
36
- startX: number
37
- startY: number
38
- endX: number
39
- endY: number
40
- dragging: boolean
41
- }
42
-
43
- class Anchor extends Component<IProps, IState> {
44
- preTargetNode?: BaseNodeModel
45
- sourceRuleResults: Map<string, Model.ConnectRuleResult> // 不同的target,source的校验规则产生的结果不同
46
- targetRuleResults: Map<string, Model.ConnectRuleResult> // 不同的target,target的校验规则不同
47
- dragHandler: StepDrag
48
- t: any
49
-
50
- constructor() {
51
- super()
52
- this.sourceRuleResults = new Map()
53
- this.targetRuleResults = new Map()
54
-
55
- this.state = {
56
- startX: 0,
57
- startY: 0,
58
- endX: 0,
59
- endY: 0,
60
- dragging: false,
61
- }
62
- this.dragHandler = new StepDrag({
63
- onDragStart: this.onDragStart,
64
- onDragging: this.onDragging,
65
- onDragEnd: this.onDragEnd,
66
- })
67
- }
68
-
69
- getAnchorShape() {
70
- const { anchorData, style, node } = this.props
71
- const anchorShape = node.getAnchorShape(anchorData)
72
- if (anchorShape) return anchorShape
73
- const { x, y } = anchorData
74
- const hoverStyle = {
75
- ...style,
76
- ...style?.hover,
77
- }
78
- return (
79
- <g>
80
- <Circle
81
- className="lf-node-anchor-hover"
82
- {...hoverStyle}
83
- {...{
84
- x,
85
- y,
86
- }}
87
- />
88
- <Circle
89
- className="lf-node-anchor"
90
- {...style}
91
- {...{
92
- x,
93
- y,
94
- }}
95
- />
96
- </g>
97
- )
98
- }
99
-
100
- // TODO: 确定 event 是否会有 null 和 undefined 的情况,事件类型做相应的适配
101
- onDragStart = ({ event }: Partial<IDragParams>) => {
102
- const { anchorData, nodeModel, graphModel } = this.props
103
- graphModel.selectNodeById(nodeModel.id)
104
- if (nodeModel.autoToFront) {
105
- graphModel.toFront(nodeModel.id)
106
- }
107
- graphModel.eventCenter.emit(EventType.ANCHOR_DRAGSTART, {
108
- data: anchorData,
109
- e: event!,
110
- nodeModel,
111
- })
112
- this.setState({
113
- startX: anchorData.x,
114
- startY: anchorData.y,
115
- endX: anchorData.x,
116
- endY: anchorData.y,
117
- })
118
- }
119
- onDragging = ({ event }: IDragParams) => {
120
- const { graphModel, nodeModel, anchorData } = this.props
121
- const {
122
- transformModel,
123
- eventCenter,
124
- width,
125
- height,
126
- editConfigModel: { autoExpand, stopMoveGraph },
127
- } = graphModel
128
- // TODO:确认该方法是否有影响!理论上 onDragging 时 event 必有值
129
- if (!event) return
130
- const { clientX, clientY } = event
131
- const {
132
- domOverlayPosition: { x, y },
133
- canvasOverlayPosition: { x: x1, y: y1 },
134
- } = graphModel.getPointByClient({
135
- x: clientX,
136
- y: clientY,
137
- })
138
- if (this.t) {
139
- cancelRaf(this.t)
140
- }
141
- let nearBoundary: number[] = [] // TODO: 定义元组类型 Tuple
142
- const size = 10
143
- if (x < 10) {
144
- nearBoundary = [size, 0]
145
- } else if (x + 10 > width) {
146
- nearBoundary = [-size, 0]
147
- } else if (y < 10) {
148
- nearBoundary = [0, size]
149
- } else if (y + 10 > height) {
150
- nearBoundary = [0, -size]
151
- }
152
- this.setState({
153
- endX: x1,
154
- endY: y1,
155
- dragging: true,
156
- })
157
- this.moveAnchorEnd(x1, y1, event)
158
- if (nearBoundary.length > 0 && !stopMoveGraph && autoExpand) {
159
- this.t = createRaf(() => {
160
- const [translateX, translateY] = nearBoundary
161
- transformModel.translate(translateX, translateY)
162
- const { endX, endY } = this.state
163
- this.setState({
164
- endX: endX - translateX,
165
- endY: endY - translateY,
166
- })
167
- this.moveAnchorEnd(endX - translateX, endY - translateY, event)
168
- })
169
- }
170
- eventCenter.emit(EventType.ANCHOR_DRAG, {
171
- data: anchorData,
172
- e: event,
173
- nodeModel,
174
- })
175
- }
176
- onDragEnd = ({ event }: Partial<IDragParams>) => {
177
- if (this.t) {
178
- cancelRaf(this.t)
179
- }
180
- const edgeModel = this.checkEnd(event)
181
- this.setState({
182
- startX: 0,
183
- startY: 0,
184
- endX: 0,
185
- endY: 0,
186
- dragging: false,
187
- })
188
- // 清除掉缓存结果 fix:#320 因为创建边之后,会影响校验结果变化,所以需要重新校验
189
- this.sourceRuleResults.clear()
190
- this.targetRuleResults.clear()
191
- const { graphModel, nodeModel, anchorData } = this.props
192
- // 拖拽结束清理:取消悬浮态
193
- if (this.preTargetNode) {
194
- this.preTargetNode.setHovered(false)
195
- this.preTargetNode = undefined
196
- }
197
-
198
- graphModel.eventCenter.emit(EventType.ANCHOR_DRAGEND, {
199
- data: anchorData,
200
- e: event!,
201
- nodeModel,
202
- edgeModel: edgeModel ?? undefined,
203
- })
204
- }
205
-
206
- get customTrajectory() {
207
- const {
208
- graphModel: { customTrajectory },
209
- } = this.props
210
- return customTrajectory
211
- }
212
-
213
- get relateEdges() {
214
- const {
215
- graphModel: { getAnchorIncomingEdge, getAnchorOutgoingEdge },
216
- anchorData: { id },
217
- } = this.props
218
- return {
219
- incomingEdgeList: getAnchorIncomingEdge(id),
220
- outgoingEdgeList: getAnchorOutgoingEdge(id),
221
- }
222
- }
223
-
224
- checkEnd = (event: PointerEvent | null | undefined) => {
225
- const {
226
- graphModel,
227
- nodeModel,
228
- anchorData: { x, y, id },
229
- } = this.props
230
- // nodeModel.setSelected(false);
231
- /* 创建边 */
232
- const { endX, endY, dragging } = this.state
233
- const info = targetNodeInfo(
234
- {
235
- x: endX,
236
- y: endY,
237
- },
238
- graphModel,
239
- )
240
- // 为了保证鼠标离开的时候,将上一个节点状态重置为正常状态。
241
- if (
242
- this.preTargetNode &&
243
- this.preTargetNode.state !== ElementState.DEFAULT
244
- ) {
245
- this.preTargetNode.setElementState(ElementState.DEFAULT)
246
- }
247
- // 没有dragging就结束边
248
- if (!dragging) return
249
- if (info && info.node) {
250
- const targetNode = info.node
251
- const anchorId = info.anchor.id
252
- const targetInfoId = `${nodeModel.id}_${targetNode.id}_${anchorId}_${id}`
253
- const { isAllPass: isSourcePass, msg: sourceMsg } =
254
- this.sourceRuleResults.get(targetInfoId) || {}
255
- const { isAllPass: isTargetPass, msg: targetMsg } =
256
- this.targetRuleResults.get(targetInfoId) || {}
257
- if (isSourcePass && isTargetPass) {
258
- targetNode.setElementState(ElementState.DEFAULT)
259
- const targetNodeModel = graphModel.getNodeModelById(info.node.id)
260
- const edgeData = graphModel.edgeGenerator?.(
261
- nodeModel.getData(),
262
- targetNodeModel?.getData() as NodeData,
263
- )
264
- const edgeModel = graphModel.addEdge({
265
- ...edgeData,
266
- sourceNodeId: nodeModel.id,
267
- sourceAnchorId: id,
268
- startPoint: {
269
- x,
270
- y,
271
- },
272
- targetNodeId: info.node.id,
273
- targetAnchorId: info.anchor.id,
274
- endPoint: {
275
- x: info.anchor.x,
276
- y: info.anchor.y,
277
- },
278
- })
279
- const { anchorData } = this.props
280
- graphModel.eventCenter.emit(EventType.ANCHOR_DROP, {
281
- data: anchorData,
282
- e: event!,
283
- nodeModel,
284
- edgeModel,
285
- })
286
- return edgeModel
287
- }
288
- const nodeData = targetNode.getData()
289
- graphModel.eventCenter.emit(EventType.CONNECTION_NOT_ALLOWED, {
290
- data: nodeData,
291
- msg: targetMsg || sourceMsg || '不允许添加连线',
292
- })
293
- return null
294
- }
295
- }
296
-
297
- moveAnchorEnd(endX: number, endY: number, event?: PointerEvent) {
298
- const { graphModel, nodeModel, anchorData } = this.props
299
- const info = targetNodeInfo(
300
- {
301
- x: endX,
302
- y: endY,
303
- },
304
- graphModel,
305
- )
306
- if (info) {
307
- const targetNode = info.node
308
- const anchorId = info.anchor.id
309
- if (this.preTargetNode && this.preTargetNode !== info.node) {
310
- this.preTargetNode.setElementState(ElementState.DEFAULT)
311
- }
312
- // #500 不允许锚点自己连自己, 在锚点一开始连接的时候, 不触发自己连接自己的校验。
313
- if (anchorData.id === anchorId) {
314
- return
315
- }
316
- this.preTargetNode = targetNode
317
-
318
- this.validateAndSetState(
319
- targetNode,
320
- anchorId,
321
- info.anchor,
322
- nodeModel,
323
- anchorData,
324
- )
325
-
326
- // 人工触发进入目标节点事件,同步设置 hovered 以驱动锚点显隐和样式
327
- if (!targetNode.isHovered) {
328
- const nodeData = targetNode.getData()
329
- if (event) {
330
- graphModel.eventCenter.emit(EventType.NODE_MOUSEENTER, {
331
- data: nodeData,
332
- e: event,
333
- })
334
- }
335
- targetNode.setHovered(true)
336
- }
337
- } else if (
338
- this.preTargetNode &&
339
- this.preTargetNode.state !== ElementState.DEFAULT
340
- ) {
341
- // 为了保证鼠标离开的时候,将上一个节点状态重置为正常状态。
342
- this.preTargetNode.setElementState(ElementState.DEFAULT)
343
- // 未命中任何节点:人工派发离开事件并取消悬浮,避免状态残留
344
- const prevData = this.preTargetNode.getData()
345
- if (event) {
346
- graphModel.eventCenter.emit(EventType.NODE_MOUSELEAVE, {
347
- data: prevData,
348
- e: event,
349
- })
350
- }
351
- this.preTargetNode.setHovered(false)
352
- this.preTargetNode = undefined
353
- }
354
- }
355
-
356
- // 校验 source/target 连接规则并设置目标节点状态
357
- validateAndSetState(
358
- targetNode: BaseNodeModel,
359
- anchorId: string | undefined,
360
- targetAnchor: AnchorConfig,
361
- nodeModel: BaseNodeModel,
362
- anchorData: AnchorConfig,
363
- ) {
364
- const targetInfoId = `${nodeModel.id}_${targetNode.id}_${anchorId}_${anchorData.id}`
365
- if (!this.targetRuleResults.has(targetInfoId)) {
366
- // 首次计算并缓存源/目标两侧的规则校验结果
367
- const sourceRuleResult = nodeModel.isAllowConnectedAsSource(
368
- targetNode,
369
- anchorData,
370
- targetAnchor,
371
- )
372
- const targetRuleResult = targetNode.isAllowConnectedAsTarget(
373
- nodeModel,
374
- anchorData,
375
- targetAnchor,
376
- )
377
- this.sourceRuleResults.set(
378
- targetInfoId,
379
- formatAnchorConnectValidateData(sourceRuleResult),
380
- )
381
- this.targetRuleResults.set(
382
- targetInfoId,
383
- formatAnchorConnectValidateData(targetRuleResult),
384
- )
385
- }
386
- // 读取缓存的校验结果
387
- const { isAllPass: isSourcePass } =
388
- this.sourceRuleResults.get(targetInfoId) ?? {}
389
- const { isAllPass: isTargetPass } =
390
- this.targetRuleResults.get(targetInfoId) ?? {}
391
- // 两侧都通过则允许连接,否则标记为不允许连接
392
- if (isSourcePass && isTargetPass) {
393
- targetNode.setElementState(ElementState.ALLOW_CONNECT)
394
- } else {
395
- targetNode.setElementState(ElementState.NOT_ALLOW_CONNECT)
396
- }
397
- }
398
-
399
- isShowLine() {
400
- const { startX, startY, endX, endY } = this.state
401
- const v = distance(startX, startY, endX, endY)
402
- return v > 10
403
- }
404
-
405
- render() {
406
- const { startX, startY, endX, endY } = this.state
407
- const { anchorData, edgeStyle, nodeModel, graphModel } = this.props
408
- const { edgeAddable } = anchorData
409
- return (
410
- // className="lf-anchor" 作为下载时,需要将锚点删除的依据,不要修改类名
411
- <g className="lf-anchor">
412
- <g
413
- onClick={(ev) => {
414
- ev.stopPropagation()
415
- graphModel.eventCenter.emit(EventType.ANCHOR_CLICK, {
416
- data: anchorData,
417
- e: ev!,
418
- nodeModel,
419
- })
420
- }}
421
- onPointerDown={(ev) => {
422
- graphModel.eventCenter.emit(EventType.ANCHOR_MOUSEDOWN, {
423
- data: anchorData,
424
- e: ev!,
425
- nodeModel,
426
- })
427
- if (edgeAddable !== false) {
428
- this.dragHandler.handleMouseDown(ev)
429
- }
430
- }}
431
- >
432
- {this.getAnchorShape()}
433
- </g>
434
- {this.isShowLine() &&
435
- (this.customTrajectory ? (
436
- this.customTrajectory({
437
- sourcePoint: {
438
- x: startX,
439
- y: startY,
440
- },
441
- targetPoint: {
442
- x: endX,
443
- y: endY,
444
- },
445
- ...edgeStyle,
446
- })
447
- ) : (
448
- <Line
449
- x1={startX}
450
- y1={startY}
451
- x2={endX}
452
- y2={endY}
453
- {...edgeStyle}
454
- pointer-events="none"
455
- />
456
- ))}
457
- </g>
458
- )
459
- }
460
- }
461
-
462
- export default Anchor