@logicflow/core 2.0.7 → 2.0.9
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$colon$dev.log +10 -10
- package/.turbo/turbo-build.log +33 -33
- package/CHANGELOG.md +18 -2
- package/__tests__/algorithm/egde.test.ts +4 -4
- package/dist/index.css +3 -0
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/es/LogicFlow.d.ts +3 -0
- package/es/LogicFlow.js +4 -0
- package/es/algorithm/edge.js +3 -5
- package/es/constant/index.d.ts +4 -0
- package/es/constant/index.js +4 -0
- package/es/event/eventArgs.d.ts +27 -1
- package/es/index.css +3 -0
- package/es/model/GraphModel.d.ts +3 -0
- package/es/model/GraphModel.js +84 -7
- package/es/model/edge/LineEdgeModel.d.ts +2 -0
- package/es/model/edge/LineEdgeModel.js +8 -0
- package/es/model/edge/PolylineEdgeModel.d.ts +1 -0
- package/es/model/edge/PolylineEdgeModel.js +4 -3
- package/es/model/node/HtmlNodeModel.d.ts +2 -2
- package/es/style/index.css +3 -0
- package/es/style/index.less +5 -0
- package/es/style/raw.d.ts +1 -1
- package/es/style/raw.js +1 -1
- package/es/view/edge/BaseEdge.d.ts +2 -0
- package/es/view/edge/BaseEdge.js +13 -1
- package/es/view/node/BaseNode.d.ts +2 -0
- package/es/view/node/BaseNode.js +14 -2
- package/es/view/overlay/BackgroundOverlay.js +2 -1
- package/lib/LogicFlow.d.ts +3 -0
- package/lib/LogicFlow.js +4 -0
- package/lib/algorithm/edge.js +3 -5
- package/lib/constant/index.d.ts +4 -0
- package/lib/constant/index.js +4 -0
- package/lib/event/eventArgs.d.ts +27 -1
- package/lib/index.css +3 -0
- package/lib/model/GraphModel.d.ts +3 -0
- package/lib/model/GraphModel.js +83 -6
- package/lib/model/edge/LineEdgeModel.d.ts +2 -0
- package/lib/model/edge/LineEdgeModel.js +8 -0
- package/lib/model/edge/PolylineEdgeModel.d.ts +1 -0
- package/lib/model/edge/PolylineEdgeModel.js +4 -3
- package/lib/model/node/HtmlNodeModel.d.ts +2 -2
- package/lib/style/index.css +3 -0
- package/lib/style/index.less +5 -0
- package/lib/style/raw.d.ts +1 -1
- package/lib/style/raw.js +1 -1
- package/lib/view/edge/BaseEdge.d.ts +2 -0
- package/lib/view/edge/BaseEdge.js +13 -1
- package/lib/view/node/BaseNode.d.ts +2 -0
- package/lib/view/node/BaseNode.js +14 -2
- package/lib/view/overlay/BackgroundOverlay.js +2 -1
- package/package.json +1 -1
- package/src/LogicFlow.tsx +6 -0
- package/src/algorithm/edge.ts +1 -1
- package/src/algorithm/outline.ts +1 -1
- package/src/constant/index.ts +4 -0
- package/src/event/eventArgs.ts +27 -1
- package/src/model/GraphModel.ts +111 -3
- package/src/model/edge/LineEdgeModel.ts +8 -0
- package/src/model/edge/PolylineEdgeModel.ts +5 -3
- package/src/style/index.less +5 -0
- package/src/style/raw.ts +3 -0
- package/src/view/Graph.tsx +3 -4
- package/src/view/edge/BaseEdge.tsx +16 -0
- package/src/view/node/BaseNode.tsx +17 -1
- package/src/view/overlay/BackgroundOverlay.tsx +11 -16
- package/src/view/overlay/OutlineOverlay.tsx +1 -1
- package/stats.html +1 -1
package/src/model/GraphModel.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { find, forEach, map, merge } from 'lodash-es'
|
|
1
|
+
import { find, forEach, map, merge, isBoolean, debounce, isEqual } from 'lodash-es'
|
|
2
2
|
import { action, computed, observable } from 'mobx'
|
|
3
3
|
import {
|
|
4
4
|
BaseEdgeModel,
|
|
@@ -41,6 +41,7 @@ import Position = LogicFlow.Position
|
|
|
41
41
|
import PointTuple = LogicFlow.PointTuple
|
|
42
42
|
import GraphData = LogicFlow.GraphData
|
|
43
43
|
import NodeConfig = LogicFlow.NodeConfig
|
|
44
|
+
import AnchorConfig = Model.AnchorConfig
|
|
44
45
|
import BaseNodeModelCtor = LogicFlow.BaseNodeModelCtor
|
|
45
46
|
import BaseEdgeModelCtor = LogicFlow.BaseEdgeModelCtor
|
|
46
47
|
|
|
@@ -127,6 +128,8 @@ export class GraphModel {
|
|
|
127
128
|
// 用户自定义属性
|
|
128
129
|
[propName: string]: any
|
|
129
130
|
|
|
131
|
+
private waitCleanEffects: (() => void)[] = []
|
|
132
|
+
|
|
130
133
|
constructor(options: LFOptions.Common) {
|
|
131
134
|
const {
|
|
132
135
|
container,
|
|
@@ -153,6 +156,27 @@ export class GraphModel {
|
|
|
153
156
|
this.width = options.width || this.rootEl.getBoundingClientRect().width
|
|
154
157
|
this.height = options.height || this.rootEl.getBoundingClientRect().height
|
|
155
158
|
|
|
159
|
+
const resizeObserver = new ResizeObserver(
|
|
160
|
+
debounce(
|
|
161
|
+
((entries) => {
|
|
162
|
+
for (const entry of entries) {
|
|
163
|
+
if (entry.target === this.rootEl) {
|
|
164
|
+
this.resize()
|
|
165
|
+
this.eventCenter.emit('graph:resize', {
|
|
166
|
+
target: this.rootEl,
|
|
167
|
+
contentRect: entry.contentRect,
|
|
168
|
+
})
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}) as ResizeObserverCallback,
|
|
172
|
+
16,
|
|
173
|
+
),
|
|
174
|
+
)
|
|
175
|
+
resizeObserver.observe(this.rootEl)
|
|
176
|
+
this.waitCleanEffects.push(() => {
|
|
177
|
+
resizeObserver.disconnect()
|
|
178
|
+
})
|
|
179
|
+
|
|
156
180
|
this.eventCenter = new EventEmitter()
|
|
157
181
|
this.editConfigModel = new EditConfigModel(options)
|
|
158
182
|
this.transformModel = new TransformModel(this.eventCenter, options)
|
|
@@ -439,6 +463,58 @@ export class GraphModel {
|
|
|
439
463
|
throw new Error(`找不到${edge.type}对应的边。`)
|
|
440
464
|
}
|
|
441
465
|
const edgeModel = new Model(edge, this)
|
|
466
|
+
// 根据edgeModel中存储的数据找到当前画布上的起终锚点坐标
|
|
467
|
+
// 判断当前起终锚点数据和Model中存储的起终点数据是否一致,不一致更新起终点信息
|
|
468
|
+
const {
|
|
469
|
+
sourceNodeId,
|
|
470
|
+
targetNodeId,
|
|
471
|
+
sourceAnchorId = '',
|
|
472
|
+
targetAnchorId = '',
|
|
473
|
+
startPoint,
|
|
474
|
+
endPoint,
|
|
475
|
+
text,
|
|
476
|
+
textPosition,
|
|
477
|
+
} = edgeModel
|
|
478
|
+
const updateAnchorPoint = (
|
|
479
|
+
node: BaseNodeModel | undefined,
|
|
480
|
+
anchorId: string,
|
|
481
|
+
point: Position,
|
|
482
|
+
updatePoint: (anchor: AnchorConfig) => void,
|
|
483
|
+
) => {
|
|
484
|
+
const anchor = node?.anchors.find((anchor) => anchor.id === anchorId)
|
|
485
|
+
if (anchor && !isEqual(anchor, point)) {
|
|
486
|
+
updatePoint(anchor)
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
const sourceNode = this.getNodeModelById(sourceNodeId)
|
|
491
|
+
const targetNode = this.getNodeModelById(targetNodeId)
|
|
492
|
+
|
|
493
|
+
updateAnchorPoint(
|
|
494
|
+
sourceNode,
|
|
495
|
+
sourceAnchorId,
|
|
496
|
+
startPoint,
|
|
497
|
+
edgeModel.updateStartPoint.bind(edgeModel),
|
|
498
|
+
)
|
|
499
|
+
updateAnchorPoint(
|
|
500
|
+
targetNode,
|
|
501
|
+
targetAnchorId,
|
|
502
|
+
endPoint,
|
|
503
|
+
edgeModel.updateEndPoint.bind(edgeModel),
|
|
504
|
+
)
|
|
505
|
+
|
|
506
|
+
// 而文本需要先算一下文本与默认文本位置之间的相对位置差
|
|
507
|
+
// 再计算新路径的文本默认位置,加上相对位置差,得到调整后边的文本的位置
|
|
508
|
+
if (text) {
|
|
509
|
+
const { x, y } = text
|
|
510
|
+
const { x: defaultX, y: defaultY } = textPosition
|
|
511
|
+
if (x && y && defaultX && defaultY) {
|
|
512
|
+
const deltaX = x - defaultX
|
|
513
|
+
const deltaY = y - defaultY
|
|
514
|
+
edgeModel.resetTextPosition()
|
|
515
|
+
edgeModel.moveText(deltaX, deltaY)
|
|
516
|
+
}
|
|
517
|
+
}
|
|
442
518
|
this.edgeModelMap.set(edgeModel.id, edgeModel)
|
|
443
519
|
this.elementsModelMap.set(edgeModel.id, edgeModel)
|
|
444
520
|
|
|
@@ -749,11 +825,15 @@ export class GraphModel {
|
|
|
749
825
|
*/
|
|
750
826
|
@action
|
|
751
827
|
deleteNode(nodeId: string) {
|
|
752
|
-
const
|
|
828
|
+
const nodeModel = this.nodesMap[nodeId].model
|
|
829
|
+
const nodeData = nodeModel.getData()
|
|
753
830
|
this.deleteEdgeBySource(nodeId)
|
|
754
831
|
this.deleteEdgeByTarget(nodeId)
|
|
755
832
|
this.nodes.splice(this.nodesMap[nodeId].index, 1)
|
|
756
|
-
this.eventCenter.emit(EventType.NODE_DELETE, {
|
|
833
|
+
this.eventCenter.emit(EventType.NODE_DELETE, {
|
|
834
|
+
data: nodeData,
|
|
835
|
+
model: nodeModel,
|
|
836
|
+
})
|
|
757
837
|
}
|
|
758
838
|
|
|
759
839
|
/**
|
|
@@ -1418,6 +1498,22 @@ export class GraphModel {
|
|
|
1418
1498
|
merge(this.grid, options)
|
|
1419
1499
|
}
|
|
1420
1500
|
|
|
1501
|
+
/**
|
|
1502
|
+
* 更新网格配置
|
|
1503
|
+
*/
|
|
1504
|
+
updateBackgroundOptions(
|
|
1505
|
+
options: boolean | Partial<LFOptions.BackgroundConfig>,
|
|
1506
|
+
) {
|
|
1507
|
+
if (isBoolean(options) || isBoolean(this.background)) {
|
|
1508
|
+
this.background = options
|
|
1509
|
+
} else {
|
|
1510
|
+
this.background = {
|
|
1511
|
+
...this.background,
|
|
1512
|
+
...options,
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1421
1517
|
/**
|
|
1422
1518
|
* 重新设置画布的宽高
|
|
1423
1519
|
*/
|
|
@@ -1573,6 +1669,18 @@ export class GraphModel {
|
|
|
1573
1669
|
@action setPartial(partial: boolean): void {
|
|
1574
1670
|
this.partial = partial
|
|
1575
1671
|
}
|
|
1672
|
+
|
|
1673
|
+
/** 销毁当前实例 */
|
|
1674
|
+
destroy() {
|
|
1675
|
+
try {
|
|
1676
|
+
this.waitCleanEffects.forEach((fn) => {
|
|
1677
|
+
fn()
|
|
1678
|
+
})
|
|
1679
|
+
} catch (err) {
|
|
1680
|
+
console.warn('error on destroy GraphModel', err)
|
|
1681
|
+
}
|
|
1682
|
+
this.waitCleanEffects.length = 0
|
|
1683
|
+
}
|
|
1576
1684
|
}
|
|
1577
1685
|
|
|
1578
1686
|
export namespace GraphModel {
|
|
@@ -17,6 +17,14 @@ export class LineEdgeModel extends BaseEdgeModel {
|
|
|
17
17
|
...cloneDeep(customStyle),
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
|
+
initEdgeData(data: LogicFlow.EdgeConfig): void {
|
|
21
|
+
super.initEdgeData(data)
|
|
22
|
+
this.points = this.getPath([this.startPoint, this.endPoint])
|
|
23
|
+
}
|
|
24
|
+
getPath(points: Point[]): string {
|
|
25
|
+
const [start, end] = points
|
|
26
|
+
return `${start.x},${start.y} ${end.x},${end.y}`
|
|
27
|
+
}
|
|
20
28
|
getTextPosition(): Point {
|
|
21
29
|
return {
|
|
22
30
|
x: (this.startPoint.x + this.endPoint.x) / 2,
|
|
@@ -326,12 +326,14 @@ export class PolylineEdgeModel extends BaseEdgeModel {
|
|
|
326
326
|
})
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
+
getPath(points: Point[]): string {
|
|
330
|
+
return points.map((point) => `${point.x},${point.y}`).join(' ')
|
|
331
|
+
}
|
|
332
|
+
|
|
329
333
|
@action
|
|
330
334
|
initPoints() {
|
|
331
335
|
if (this.pointsList.length > 0) {
|
|
332
|
-
this.points = this.pointsList
|
|
333
|
-
.map((point) => `${point.x},${point.y}`)
|
|
334
|
-
.join(' ')
|
|
336
|
+
this.points = this.getPath(this.pointsList)
|
|
335
337
|
} else {
|
|
336
338
|
this.updatePoints()
|
|
337
339
|
}
|
package/src/style/index.less
CHANGED
package/src/style/raw.ts
CHANGED
package/src/view/Graph.tsx
CHANGED
|
@@ -87,7 +87,7 @@ class Graph extends Component<IGraphProps> {
|
|
|
87
87
|
if (options.height) {
|
|
88
88
|
style.height = `${graphModel.height}px`
|
|
89
89
|
}
|
|
90
|
-
const { fakeNode, editConfigModel } = graphModel
|
|
90
|
+
const { fakeNode, editConfigModel, background } = graphModel
|
|
91
91
|
const { adjustEdge } = editConfigModel
|
|
92
92
|
return (
|
|
93
93
|
<div className="lf-graph" flow-id={graphModel.flowId} style={style}>
|
|
@@ -112,9 +112,8 @@ class Graph extends Component<IGraphProps> {
|
|
|
112
112
|
</ModificationOverlay>
|
|
113
113
|
{/* 工具层:插件 */}
|
|
114
114
|
<ToolOverlay graphModel={graphModel} tool={tool} />
|
|
115
|
-
{
|
|
116
|
-
|
|
117
|
-
)}
|
|
115
|
+
{/* 画布背景 */}
|
|
116
|
+
{background && <BackgroundOverlay background={background} />}
|
|
118
117
|
{/* 画布网格 */}
|
|
119
118
|
<Grid graphModel={graphModel} />
|
|
120
119
|
</div>
|
|
@@ -459,6 +459,20 @@ export abstract class BaseEdge<P extends IProps> extends Component<
|
|
|
459
459
|
this.toFront()
|
|
460
460
|
}
|
|
461
461
|
|
|
462
|
+
handleFocus = () => {
|
|
463
|
+
const { model, graphModel } = this.props
|
|
464
|
+
graphModel.eventCenter.emit(EventType.EDGE_FOCUS, {
|
|
465
|
+
data: model.getData(),
|
|
466
|
+
})
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
handleBlur = () => {
|
|
470
|
+
const { model, graphModel } = this.props
|
|
471
|
+
graphModel.eventCenter.emit(EventType.EDGE_BLUR, {
|
|
472
|
+
data: model.getData(),
|
|
473
|
+
})
|
|
474
|
+
}
|
|
475
|
+
|
|
462
476
|
/**
|
|
463
477
|
* @overridable 支持重写, 此方法为获取边的形状,如果需要自定义边的形状,请重写此方法。
|
|
464
478
|
* @example https://docs.logic-flow.cn/docs/#/zh/guide/basic/edge?id=%e5%9f%ba%e4%ba%8e-react-%e7%bb%84%e4%bb%b6%e8%87%aa%e5%ae%9a%e4%b9%89%e8%be%b9
|
|
@@ -499,6 +513,8 @@ export abstract class BaseEdge<P extends IProps> extends Component<
|
|
|
499
513
|
onMouseOver={this.setHoverOn}
|
|
500
514
|
onMouseEnter={this.setHoverOn}
|
|
501
515
|
onMouseLeave={this.setHoverOff}
|
|
516
|
+
onFocus={this.handleFocus}
|
|
517
|
+
onBlur={this.handleBlur}
|
|
502
518
|
>
|
|
503
519
|
{this.getShape()}
|
|
504
520
|
{this.getAppend()}
|
|
@@ -377,7 +377,7 @@ export abstract class BaseNode<P extends IProps = IProps> extends Component<
|
|
|
377
377
|
// 不是双击的,默认都是单击
|
|
378
378
|
if (isDoubleClick) {
|
|
379
379
|
if (editConfigModel.nodeTextEdit) {
|
|
380
|
-
if (model.text.editable) {
|
|
380
|
+
if (model.text.editable && editConfigModel.textMode === TextMode.TEXT) {
|
|
381
381
|
model.setSelected(false)
|
|
382
382
|
graphModel.setElementStateById(model.id, ElementState.TEXT_EDIT)
|
|
383
383
|
}
|
|
@@ -424,6 +424,20 @@ export abstract class BaseNode<P extends IProps = IProps> extends Component<
|
|
|
424
424
|
}
|
|
425
425
|
}
|
|
426
426
|
|
|
427
|
+
handleFocus = () => {
|
|
428
|
+
const { model, graphModel } = this.props
|
|
429
|
+
graphModel.eventCenter.emit(EventType.NODE_FOCUS, {
|
|
430
|
+
data: model.getData(),
|
|
431
|
+
})
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
handleBlur = () => {
|
|
435
|
+
const { model, graphModel } = this.props
|
|
436
|
+
graphModel.eventCenter.emit(EventType.NODE_BLUR, {
|
|
437
|
+
data: model.getData(),
|
|
438
|
+
})
|
|
439
|
+
}
|
|
440
|
+
|
|
427
441
|
// 因为自定义节点的时候,可能会基于hover状态自定义不同的样式。
|
|
428
442
|
setHoverOn = (ev: MouseEvent) => {
|
|
429
443
|
const { model, graphModel } = this.props
|
|
@@ -508,6 +522,8 @@ export abstract class BaseNode<P extends IProps = IProps> extends Component<
|
|
|
508
522
|
onMouseLeave={this.setHoverOff}
|
|
509
523
|
onMouseOut={this.onMouseOut}
|
|
510
524
|
onContextMenu={this.handleContextMenu}
|
|
525
|
+
onFocus={this.handleFocus}
|
|
526
|
+
onBlur={this.handleBlur}
|
|
511
527
|
{...restAttributes}
|
|
512
528
|
>
|
|
513
529
|
{nodeShapeInner}
|
|
@@ -1,36 +1,31 @@
|
|
|
1
1
|
import { Component } from 'preact/compat'
|
|
2
|
+
import { isObject } from 'lodash-es'
|
|
3
|
+
import { Options as LFOptions } from '../../options'
|
|
4
|
+
import { observer } from '../..'
|
|
2
5
|
|
|
3
6
|
/**
|
|
4
7
|
* 背景配置, 支持css属性配置
|
|
5
8
|
* https://developer.mozilla.org/zh-CN/docs/Web/CSS/background
|
|
6
9
|
* @example
|
|
7
10
|
* {
|
|
8
|
-
*
|
|
9
|
-
|
|
11
|
+
* backgroundImage: "url('./img/grid.svg')",
|
|
12
|
+
backgroundRepeat: 'repeat',
|
|
10
13
|
* }
|
|
11
14
|
*/
|
|
12
|
-
export type BackgroundConfig = {
|
|
13
|
-
/**
|
|
14
|
-
* 背景图片地址
|
|
15
|
-
*/
|
|
16
|
-
backgroundImage?: string
|
|
17
|
-
/**
|
|
18
|
-
* 是否重复
|
|
19
|
-
*/
|
|
20
|
-
backgroundRepeat?: string
|
|
21
|
-
[key: string]: any
|
|
22
|
-
}
|
|
23
|
-
|
|
24
15
|
type IProps = {
|
|
25
|
-
background: BackgroundConfig
|
|
16
|
+
background: boolean | LFOptions.BackgroundConfig
|
|
26
17
|
}
|
|
27
18
|
|
|
19
|
+
@observer
|
|
28
20
|
export class BackgroundOverlay extends Component<IProps> {
|
|
29
21
|
render() {
|
|
30
22
|
const { background } = this.props
|
|
31
23
|
return (
|
|
32
24
|
<div className="lf-background">
|
|
33
|
-
<div
|
|
25
|
+
<div
|
|
26
|
+
style={isObject(background) ? background : {}}
|
|
27
|
+
className="lf-background-area"
|
|
28
|
+
/>
|
|
34
29
|
</div>
|
|
35
30
|
)
|
|
36
31
|
}
|
|
@@ -82,7 +82,7 @@ export class OutlineOverlay extends Component<IProps> {
|
|
|
82
82
|
(hoverOutline && edge.isHovered)
|
|
83
83
|
) {
|
|
84
84
|
if (edge.modelType === ModelType.LINE_EDGE) {
|
|
85
|
-
edgeOutline.push(this.getLineOutline(edge))
|
|
85
|
+
edgeOutline.push(this.getLineOutline(edge as LineEdgeModel))
|
|
86
86
|
} else if (edge.modelType === ModelType.POLYLINE_EDGE) {
|
|
87
87
|
edgeOutline.push(this.getPolylineOutline(edge as PolylineEdgeModel))
|
|
88
88
|
} else if (edge.modelType === ModelType.BEZIER_EDGE) {
|