@logicflow/core 2.2.0 → 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.
- package/dist/index.css +3 -2
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/es/LogicFlow.d.ts +9 -0
- package/es/LogicFlow.js +0 -1
- package/es/constant/index.d.ts +1 -1
- package/es/constant/index.js +1 -1
- package/es/constant/theme.d.ts +136 -0
- package/es/constant/theme.js +680 -0
- package/es/index.css +3 -2
- package/es/model/GraphModel.d.ts +10 -2
- package/es/model/GraphModel.js +48 -14
- package/es/model/TransformModel.js +9 -9
- package/es/model/edge/BaseEdgeModel.js +7 -2
- package/es/model/edge/PolylineEdgeModel.d.ts +7 -0
- package/es/model/edge/PolylineEdgeModel.js +136 -7
- package/es/model/node/BaseNodeModel.d.ts +12 -1
- package/es/model/node/BaseNodeModel.js +9 -2
- package/es/model/node/HtmlNodeModel.d.ts +12 -0
- package/es/model/node/HtmlNodeModel.js +19 -0
- package/es/model/node/PolygonNodeModel.js +3 -3
- package/es/options.d.ts +4 -2
- package/es/style/index.css +3 -2
- package/es/style/index.less +3 -2
- package/es/style/raw.d.ts +1 -1
- package/es/style/raw.js +1 -1
- package/es/tool/MultipleSelectTool.js +10 -5
- package/es/util/drag.js +0 -1
- package/es/util/edge.d.ts +40 -1
- package/es/util/edge.js +43 -9
- package/es/util/geometry.d.ts +8 -0
- package/es/util/geometry.js +79 -0
- package/es/util/theme.d.ts +2 -65
- package/es/util/theme.js +4 -281
- package/es/view/Anchor.d.ts +1 -0
- package/es/view/Anchor.js +24 -21
- package/es/view/Control.d.ts +5 -0
- package/es/view/Control.js +44 -57
- package/es/view/edge/BaseEdge.js +9 -0
- package/es/view/edge/PolylineEdge.js +13 -2
- package/es/view/node/BaseNode.d.ts +1 -0
- package/es/view/node/BaseNode.js +23 -11
- package/es/view/node/HtmlNode.js +2 -4
- package/es/view/overlay/CanvasOverlay.js +5 -2
- package/es/view/overlay/Grid.d.ts +12 -1
- package/es/view/overlay/Grid.js +85 -23
- package/es/view/overlay/OutlineOverlay.d.ts +1 -0
- package/es/view/overlay/OutlineOverlay.js +18 -17
- package/es/view/overlay/gridConfig.d.ts +46 -0
- package/es/view/overlay/gridConfig.js +99 -0
- package/es/view/shape/Polygon.d.ts +0 -7
- package/es/view/shape/Polygon.js +12 -43
- package/lib/LogicFlow.d.ts +9 -0
- package/lib/LogicFlow.js +0 -1
- package/lib/constant/index.d.ts +1 -1
- package/lib/constant/index.js +16 -2
- package/lib/constant/theme.d.ts +136 -0
- package/lib/constant/theme.js +683 -0
- package/lib/index.css +3 -2
- package/lib/model/GraphModel.d.ts +10 -2
- package/lib/model/GraphModel.js +49 -15
- package/lib/model/TransformModel.js +9 -9
- package/lib/model/edge/BaseEdgeModel.js +7 -2
- package/lib/model/edge/PolylineEdgeModel.d.ts +7 -0
- package/lib/model/edge/PolylineEdgeModel.js +136 -7
- package/lib/model/node/BaseNodeModel.d.ts +12 -1
- package/lib/model/node/BaseNodeModel.js +9 -2
- package/lib/model/node/HtmlNodeModel.d.ts +12 -0
- package/lib/model/node/HtmlNodeModel.js +19 -0
- package/lib/model/node/PolygonNodeModel.js +3 -3
- package/lib/options.d.ts +4 -2
- package/lib/style/index.css +3 -2
- package/lib/style/index.less +3 -2
- package/lib/style/raw.d.ts +1 -1
- package/lib/style/raw.js +1 -1
- package/lib/tool/MultipleSelectTool.js +10 -5
- package/lib/util/drag.js +0 -1
- package/lib/util/edge.d.ts +40 -1
- package/lib/util/edge.js +43 -9
- package/lib/util/geometry.d.ts +8 -0
- package/lib/util/geometry.js +81 -1
- package/lib/util/theme.d.ts +2 -65
- package/lib/util/theme.js +15 -292
- package/lib/view/Anchor.d.ts +1 -0
- package/lib/view/Anchor.js +24 -21
- package/lib/view/Control.d.ts +5 -0
- package/lib/view/Control.js +44 -57
- package/lib/view/edge/BaseEdge.js +9 -0
- package/lib/view/edge/PolylineEdge.js +13 -2
- package/lib/view/node/BaseNode.d.ts +1 -0
- package/lib/view/node/BaseNode.js +22 -10
- package/lib/view/node/HtmlNode.js +1 -3
- package/lib/view/overlay/CanvasOverlay.js +5 -2
- package/lib/view/overlay/Grid.d.ts +12 -1
- package/lib/view/overlay/Grid.js +83 -21
- package/lib/view/overlay/OutlineOverlay.d.ts +1 -0
- package/lib/view/overlay/OutlineOverlay.js +18 -17
- package/lib/view/overlay/gridConfig.d.ts +46 -0
- package/lib/view/overlay/gridConfig.js +104 -0
- package/lib/view/shape/Polygon.d.ts +0 -7
- package/lib/view/shape/Polygon.js +13 -45
- package/package.json +6 -1
- package/.turbo/turbo-build$colon$dev.log +0 -10
- package/.turbo/turbo-build.log +0 -33
- package/CHANGELOG.md +0 -1849
- package/__tests__/algorithm/egde.test.ts +0 -131
- package/__tests__/algorithm/index.test.ts +0 -74
- package/__tests__/algorithm/outline.test.ts +0 -43
- package/__tests__/bugs/1545-spec.test.ts +0 -42
- package/__tests__/event/event.test.ts +0 -22
- package/__tests__/history/history.test.ts +0 -28
- package/__tests__/logicflow.test.ts +0 -575
- package/__tests__/model/graphmodel.test.ts +0 -87
- package/__tests__/util/compatible.test.ts +0 -48
- package/__tests__/util/edge.test.ts +0 -224
- package/__tests__/util/geometry.test.ts +0 -14
- package/__tests__/util/graph.test.ts +0 -16
- package/__tests__/util/matrix.test.ts +0 -41
- package/__tests__/util/node.test.ts +0 -68
- package/__tests__/util/sampling.test.ts +0 -12
- package/__tests__/util/vector.test.ts +0 -50
- package/__tests__/util/zIndex.test.ts +0 -10
- package/src/LogicFlow.tsx +0 -2008
- package/src/algorithm/edge.ts +0 -67
- package/src/algorithm/index.ts +0 -70
- package/src/algorithm/outline.ts +0 -77
- package/src/algorithm/rotate.ts +0 -55
- package/src/common/drag.ts +0 -219
- package/src/common/history.ts +0 -108
- package/src/common/index.ts +0 -6
- package/src/common/keyboard.ts +0 -108
- package/src/common/matrix.ts +0 -122
- package/src/common/vector.ts +0 -93
- package/src/constant/index.ts +0 -179
- package/src/event/event.md +0 -66
- package/src/event/eventArgs.ts +0 -643
- package/src/event/eventEmitter.ts +0 -156
- package/src/history/index.ts +0 -119
- package/src/index.less +0 -1
- package/src/index.ts +0 -26
- package/src/keyboard/index.ts +0 -112
- package/src/keyboard/shortcut.ts +0 -200
- package/src/model/BaseModel.ts +0 -250
- package/src/model/EditConfigModel.ts +0 -334
- package/src/model/GraphModel.ts +0 -1788
- package/src/model/NestedTransformModel.ts +0 -121
- package/src/model/SnaplineModel.ts +0 -256
- package/src/model/TransformModel.ts +0 -258
- package/src/model/edge/BaseEdgeModel.ts +0 -777
- package/src/model/edge/BezierEdgeModel.ts +0 -197
- package/src/model/edge/LineEdgeModel.ts +0 -36
- package/src/model/edge/PolylineEdgeModel.ts +0 -672
- package/src/model/edge/index.ts +0 -4
- package/src/model/index.ts +0 -9
- package/src/model/node/BaseNodeModel.ts +0 -949
- package/src/model/node/CircleNodeModel.ts +0 -91
- package/src/model/node/DiamondNodeModel.ts +0 -132
- package/src/model/node/EllipseNodeModel.ts +0 -98
- package/src/model/node/HtmlNodeModel.ts +0 -50
- package/src/model/node/PolygonNodeModel.ts +0 -150
- package/src/model/node/RectNodeModel.ts +0 -69
- package/src/model/node/TextNodeModel.ts +0 -54
- package/src/model/node/index.ts +0 -8
- package/src/options.ts +0 -145
- package/src/style/index.less +0 -261
- package/src/style/raw.ts +0 -220
- package/src/tool/MultipleSelectTool.tsx +0 -132
- package/src/tool/TextEditTool.tsx +0 -193
- package/src/tool/index.ts +0 -101
- package/src/typings.d.ts +0 -5
- package/src/util/animation.ts +0 -29
- package/src/util/browser.ts +0 -4
- package/src/util/compatible.ts +0 -15
- package/src/util/drag.ts +0 -220
- package/src/util/edge.ts +0 -1060
- package/src/util/geometry.ts +0 -55
- package/src/util/graph.ts +0 -46
- package/src/util/index.ts +0 -17
- package/src/util/matrix.ts +0 -129
- package/src/util/mobx.ts +0 -23
- package/src/util/node.ts +0 -543
- package/src/util/raf.ts +0 -28
- package/src/util/resize.ts +0 -606
- package/src/util/sampling.ts +0 -85
- package/src/util/theme.ts +0 -375
- package/src/util/uuid.ts +0 -26
- package/src/util/vector.ts +0 -93
- package/src/util/zIndex.ts +0 -6
- package/src/view/Anchor.tsx +0 -445
- package/src/view/Control.tsx +0 -512
- package/src/view/Graph.tsx +0 -141
- package/src/view/Rotate.tsx +0 -113
- package/src/view/behavior/dnd.ts +0 -162
- package/src/view/behavior/index.ts +0 -2
- package/src/view/behavior/snapline.ts +0 -16
- package/src/view/edge/AdjustPoint.tsx +0 -425
- package/src/view/edge/Arrow.tsx +0 -54
- package/src/view/edge/BaseEdge.tsx +0 -650
- package/src/view/edge/BezierEdge.tsx +0 -101
- package/src/view/edge/LineEdge.tsx +0 -81
- package/src/view/edge/PolylineEdge.tsx +0 -299
- package/src/view/edge/index.ts +0 -6
- package/src/view/index.ts +0 -8
- package/src/view/node/BaseNode.tsx +0 -571
- package/src/view/node/CircleNode.tsx +0 -21
- package/src/view/node/DiamondNode.tsx +0 -24
- package/src/view/node/EllipseNode.tsx +0 -22
- package/src/view/node/HtmlNode.tsx +0 -95
- package/src/view/node/PolygonNode.tsx +0 -28
- package/src/view/node/RectNode.tsx +0 -30
- package/src/view/node/TextNode.tsx +0 -39
- package/src/view/node/index.ts +0 -8
- package/src/view/overlay/BackgroundOverlay.tsx +0 -34
- package/src/view/overlay/BezierAdjustOverlay.tsx +0 -150
- package/src/view/overlay/CanvasOverlay.tsx +0 -288
- package/src/view/overlay/Grid.tsx +0 -162
- package/src/view/overlay/ModificationOverlay.tsx +0 -31
- package/src/view/overlay/OutlineOverlay.tsx +0 -170
- package/src/view/overlay/SnaplineOverlay.tsx +0 -44
- package/src/view/overlay/ToolOverlay.tsx +0 -65
- package/src/view/overlay/getTransformHoc.tsx +0 -50
- package/src/view/overlay/index.ts +0 -8
- package/src/view/shape/Circle.tsx +0 -41
- package/src/view/shape/Ellipse.tsx +0 -42
- package/src/view/shape/Line.tsx +0 -39
- package/src/view/shape/Path.tsx +0 -22
- package/src/view/shape/Polygon.tsx +0 -91
- package/src/view/shape/Polyline.tsx +0 -31
- package/src/view/shape/Rect.tsx +0 -44
- package/src/view/shape/Text.tsx +0 -169
- package/src/view/shape/index.ts +0 -8
- package/src/view/text/BaseText.tsx +0 -134
- package/src/view/text/LineText.tsx +0 -168
- package/src/view/text/index.ts +0 -2
- package/stats.html +0 -4842
- package/tsconfig.json +0 -18
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import { EventArgs } from './eventArgs'
|
|
2
|
-
|
|
3
|
-
export type EventType<T extends string = string> = {
|
|
4
|
-
readonly callback: EventCallback<T>
|
|
5
|
-
readonly once: boolean
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export type EventsType<T extends string = string> = {
|
|
9
|
-
[k in T]?: EventType<k>[]
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export type CallbackArgs<T extends string = string> = T extends keyof EventArgs
|
|
13
|
-
? EventArgs[T]
|
|
14
|
-
: // 如果不是内部定义的事件类型,那么允许用户抛出任何类型的参数
|
|
15
|
-
// 这部分的类型定义由用户自己来保证
|
|
16
|
-
any
|
|
17
|
-
|
|
18
|
-
export type EventCallback<T extends string = string> = (
|
|
19
|
-
args: CallbackArgs<T>,
|
|
20
|
-
) => void
|
|
21
|
-
|
|
22
|
-
const WILDCARD = '*'
|
|
23
|
-
|
|
24
|
-
/* event-emitter */
|
|
25
|
-
export default class EventEmitter {
|
|
26
|
-
private _events: EventsType = {}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* 监听一个事件
|
|
30
|
-
* @param evt 事件名称
|
|
31
|
-
* @param callback 回调函数
|
|
32
|
-
* @param once 是否只监听一次
|
|
33
|
-
*/
|
|
34
|
-
on<T extends keyof EventArgs>(
|
|
35
|
-
evt: T,
|
|
36
|
-
callback: EventCallback<T>,
|
|
37
|
-
once?: boolean,
|
|
38
|
-
): void
|
|
39
|
-
on<T extends string>(evt: T, callback: EventCallback<T>, once?: boolean): void
|
|
40
|
-
on(evt: string, callback: EventCallback, once?: boolean) {
|
|
41
|
-
evt?.split(',').forEach((evKey) => {
|
|
42
|
-
evKey = evKey.trim()
|
|
43
|
-
if (!this._events[evKey]) {
|
|
44
|
-
this._events[evKey] = []
|
|
45
|
-
}
|
|
46
|
-
this._events[evKey]!.push({
|
|
47
|
-
callback,
|
|
48
|
-
once: !!once,
|
|
49
|
-
})
|
|
50
|
-
})
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* 监听一个事件一次
|
|
55
|
-
* @param evt 事件名称
|
|
56
|
-
* @param callback 回调函数
|
|
57
|
-
*/
|
|
58
|
-
once<T extends keyof EventArgs>(
|
|
59
|
-
evt: T,
|
|
60
|
-
callback: (args: EventArgs[T]) => void,
|
|
61
|
-
): void
|
|
62
|
-
once<T extends string>(evt: T, callback: EventCallback<T>): void
|
|
63
|
-
once(evt: string, callback: EventCallback) {
|
|
64
|
-
evt?.split(',').forEach((evKey) => {
|
|
65
|
-
evKey = evKey.trim()
|
|
66
|
-
this.on(evKey, callback, true)
|
|
67
|
-
})
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* 触发一个事件
|
|
72
|
-
* @param evts
|
|
73
|
-
* @param eventArgs
|
|
74
|
-
*/
|
|
75
|
-
emit<T extends keyof EventArgs>(evts: T, eventArgs: CallbackArgs<T>): void
|
|
76
|
-
emit<T extends string>(evts: T, eventArgs: CallbackArgs<T>): void
|
|
77
|
-
emit(evts: string, eventArgs?: EventCallback) {
|
|
78
|
-
evts?.split(',').forEach((evt) => {
|
|
79
|
-
const events = this._events[evt] || []
|
|
80
|
-
const wildcardEvents = this._events[WILDCARD] || []
|
|
81
|
-
// 实际的处理 emit 方法
|
|
82
|
-
const doEmit = (es: EventType[]) => {
|
|
83
|
-
let { length } = es
|
|
84
|
-
for (let i = 0; i < length; i++) {
|
|
85
|
-
if (!es[i]) {
|
|
86
|
-
continue
|
|
87
|
-
}
|
|
88
|
-
const { callback, once } = es[i]
|
|
89
|
-
if (once) {
|
|
90
|
-
es.splice(i, 1)
|
|
91
|
-
if (es.length === 0) {
|
|
92
|
-
delete this._events[evt]
|
|
93
|
-
}
|
|
94
|
-
length--
|
|
95
|
-
i--
|
|
96
|
-
}
|
|
97
|
-
callback.apply(this, [eventArgs])
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
doEmit(events)
|
|
101
|
-
doEmit(wildcardEvents)
|
|
102
|
-
})
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* 取消事件监听
|
|
107
|
-
* @param evts 事件名称
|
|
108
|
-
* @param callback 回调函数
|
|
109
|
-
*
|
|
110
|
-
* - evts 为空时,清除所有事件的监听器
|
|
111
|
-
* - evts 非空,callback 为空时,清除指定事件的所有监听器
|
|
112
|
-
* - evts 非空,callback 非空,进行对象比较,清除指定事件的指定监听器
|
|
113
|
-
*/
|
|
114
|
-
off<T extends keyof EventArgs>(
|
|
115
|
-
evts: T,
|
|
116
|
-
callback?: (args: EventArgs[T]) => void,
|
|
117
|
-
): void
|
|
118
|
-
off<T extends string>(evts: T, callback?: EventCallback<T>): void
|
|
119
|
-
off(evts: string, callback?: EventCallback) {
|
|
120
|
-
if (!evts) {
|
|
121
|
-
// evt 为空全部清除
|
|
122
|
-
this._events = {}
|
|
123
|
-
}
|
|
124
|
-
evts.split(',').forEach((evt) => {
|
|
125
|
-
if (!callback) {
|
|
126
|
-
// evt 存在,callback 为空,清除事件所有方法
|
|
127
|
-
delete this._events[evt]
|
|
128
|
-
} else {
|
|
129
|
-
// evt 存在,callback 存在,清除匹配的
|
|
130
|
-
const events = this._events[evt] || []
|
|
131
|
-
let { length } = events
|
|
132
|
-
for (let i = 0; i < length; i++) {
|
|
133
|
-
if (events[i].callback === callback) {
|
|
134
|
-
events.splice(i, 1)
|
|
135
|
-
length--
|
|
136
|
-
i--
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
if (events.length === 0) {
|
|
140
|
-
delete this._events[evt]
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
})
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/* 当前所有的事件 */
|
|
147
|
-
getEvents() {
|
|
148
|
-
return this._events
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
destroy() {
|
|
152
|
-
this._events = {}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
export { EventEmitter, EventArgs }
|
package/src/history/index.ts
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import { debounce, isEqual, last, cloneDeep } from 'lodash-es'
|
|
2
|
-
import { deepObserve, IDisposer } from 'mobx-utils'
|
|
3
|
-
import LogicFlow from '..'
|
|
4
|
-
import { GraphModel } from '../model'
|
|
5
|
-
import { EventType } from '../constant'
|
|
6
|
-
import EventEmitter from '../event/eventEmitter'
|
|
7
|
-
|
|
8
|
-
import GraphData = LogicFlow.GraphData
|
|
9
|
-
|
|
10
|
-
export class History {
|
|
11
|
-
undos: GraphData[] = []
|
|
12
|
-
redos: GraphData[] = []
|
|
13
|
-
callbacks = []
|
|
14
|
-
stopWatch: IDisposer | null = null
|
|
15
|
-
curData: GraphData | null = null
|
|
16
|
-
maxSize = 50
|
|
17
|
-
// 发生数据变化后,最多再等500ms,把距离上次的数据变更存储起来。
|
|
18
|
-
// 所以waitTime值越小,History对数据变化越敏感,存的undos就越细。
|
|
19
|
-
waitTime = 100
|
|
20
|
-
eventCenter: EventEmitter
|
|
21
|
-
|
|
22
|
-
constructor(eventCenter: EventEmitter) {
|
|
23
|
-
this.eventCenter = eventCenter
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
add(data: GraphData) {
|
|
27
|
-
if (isEqual(last(this.undos), data)) return
|
|
28
|
-
this.undos.push(data)
|
|
29
|
-
// 因为undo的时候,会触发add.
|
|
30
|
-
// 所以需要区分这个add是undo触发的,还是用户正常操作触发的。
|
|
31
|
-
// 如果是用户正常操作触发的,需要清空redos
|
|
32
|
-
if (!isEqual(this.curData, data)) {
|
|
33
|
-
this.redos = []
|
|
34
|
-
}
|
|
35
|
-
this.eventCenter.emit(EventType.HISTORY_CHANGE, {
|
|
36
|
-
data: {
|
|
37
|
-
undos: this.undos,
|
|
38
|
-
redos: this.redos,
|
|
39
|
-
undoAble: this.undoAble(),
|
|
40
|
-
redoAble: this.redoAble(),
|
|
41
|
-
},
|
|
42
|
-
})
|
|
43
|
-
if (this.undos.length > this.maxSize) {
|
|
44
|
-
this.undos.shift()
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
undoAble() {
|
|
49
|
-
// undos栈顶就是当前图渲染出来的数据。
|
|
50
|
-
return this.undos.length > 1
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// 1) undo方法触发
|
|
54
|
-
// 2) graphModel重新渲染nodes和edges
|
|
55
|
-
// 3) graphModel发生变化,触发watch
|
|
56
|
-
// 4) watch触发add
|
|
57
|
-
undo() {
|
|
58
|
-
if (!this.undoAble()) return
|
|
59
|
-
const preData = this.undos.pop()!
|
|
60
|
-
this.redos.push(preData)
|
|
61
|
-
const curData = this.undos.pop()!
|
|
62
|
-
this.curData = cloneDeep(curData)
|
|
63
|
-
return curData
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
redoAble() {
|
|
67
|
-
return this.redos.length > 0
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
redo() {
|
|
71
|
-
if (!this.redoAble()) return
|
|
72
|
-
const curData = this.redos.pop()!
|
|
73
|
-
this.curData = cloneDeep(curData)
|
|
74
|
-
return curData
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
watch(model: GraphModel) {
|
|
78
|
-
this.stopWatch && this.stopWatch()
|
|
79
|
-
|
|
80
|
-
// 把当前watch的model转换一下数据存起来,无需清空redos。
|
|
81
|
-
this.undos.push(model.modelToGraphData())
|
|
82
|
-
|
|
83
|
-
this.stopWatch = deepObserve(
|
|
84
|
-
// TODO:避免用户触发「The same observable object cannot appear twice in the same tree」 错误
|
|
85
|
-
// 例如:在自定义节点的 setAttributes 方法中,将 nodeModel 属性赋值给另一个 observable 属性
|
|
86
|
-
// eg:
|
|
87
|
-
// setAttributes() {
|
|
88
|
-
// this.width = 120
|
|
89
|
-
// this.height = 50
|
|
90
|
-
//
|
|
91
|
-
// if (this.text) {
|
|
92
|
-
// this.properties.text = this.text;
|
|
93
|
-
// this.text.value = '';
|
|
94
|
-
// }
|
|
95
|
-
// }
|
|
96
|
-
// 解决方案:使用 cloneDeep 方法,将 observable 对象克隆一份。需要测试下面操作是否会造成其它问题
|
|
97
|
-
// https://stackoverflow.com/questions/55328504/a-node-cannot-exists-twice-in-the-state-tree-mobx-state-tree
|
|
98
|
-
// cloneDeep(model),
|
|
99
|
-
model,
|
|
100
|
-
debounce(() => {
|
|
101
|
-
// 数据变更后,把最新的当前model数据存起来,并清空 redos。
|
|
102
|
-
// 因为这个回调函数的触发,一般是用户交互而引起的,所以按正常逻辑需要清空 redos。
|
|
103
|
-
const data = model.modelToHistoryData()
|
|
104
|
-
if (data) {
|
|
105
|
-
this.add({ ...data })
|
|
106
|
-
}
|
|
107
|
-
}, this.waitTime),
|
|
108
|
-
)
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
destroy() {
|
|
112
|
-
this.undos = []
|
|
113
|
-
this.redos = []
|
|
114
|
-
this.curData = null
|
|
115
|
-
this.stopWatch && this.stopWatch()
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export default History
|
package/src/index.less
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
@import url('./style/index');
|
package/src/index.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { observer as mobxObserver } from 'mobx-preact'
|
|
2
|
-
import { createElement as h, createRef, Component } from 'preact/compat'
|
|
3
|
-
import LogicFlow from './LogicFlow'
|
|
4
|
-
|
|
5
|
-
import * as LogicFlowUtil from './util'
|
|
6
|
-
|
|
7
|
-
export function observer<P>(props: P) {
|
|
8
|
-
return mobxObserver(props as any)
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export { LogicFlow, h, createRef, Component, LogicFlowUtil }
|
|
12
|
-
|
|
13
|
-
export * from './util'
|
|
14
|
-
export * from './tool'
|
|
15
|
-
export * from './view'
|
|
16
|
-
export * from './model'
|
|
17
|
-
export * from './options'
|
|
18
|
-
export * from './keyboard'
|
|
19
|
-
export * from './constant'
|
|
20
|
-
export * from './algorithm'
|
|
21
|
-
export * from './event/eventEmitter'
|
|
22
|
-
export { ElementState, ModelType, ElementType, EventType } from './constant'
|
|
23
|
-
|
|
24
|
-
export { formatAnchorConnectValidateData } from './util/node'
|
|
25
|
-
|
|
26
|
-
export default LogicFlow
|
package/src/keyboard/index.ts
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { isArray } from 'lodash-es'
|
|
2
|
-
import Mousetrap, { MousetrapInstance } from 'mousetrap'
|
|
3
|
-
import LogicFlow from '../LogicFlow'
|
|
4
|
-
|
|
5
|
-
export * from './shortcut'
|
|
6
|
-
|
|
7
|
-
export type Action = 'keypress' | 'keydown' | 'keyup'
|
|
8
|
-
export type Handler = (e: KeyboardEvent) => void
|
|
9
|
-
|
|
10
|
-
export interface KeyboardDef {
|
|
11
|
-
enabled: boolean
|
|
12
|
-
shortcuts?: Array<{
|
|
13
|
-
keys: string | string[]
|
|
14
|
-
callback: Handler
|
|
15
|
-
action?: Action
|
|
16
|
-
}>
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface KeyboardOptions {
|
|
20
|
-
lf: LogicFlow
|
|
21
|
-
keyboard?: KeyboardDef
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export class Keyboard {
|
|
25
|
-
public readonly mousetrap: MousetrapInstance
|
|
26
|
-
public options: KeyboardOptions
|
|
27
|
-
private readonly target: HTMLElement
|
|
28
|
-
|
|
29
|
-
constructor(options: KeyboardOptions) {
|
|
30
|
-
if (!options.keyboard) {
|
|
31
|
-
options.keyboard = { enabled: false }
|
|
32
|
-
}
|
|
33
|
-
this.options = options
|
|
34
|
-
const { lf } = options
|
|
35
|
-
this.target = lf.container
|
|
36
|
-
this.mousetrap = new Mousetrap(this.target)
|
|
37
|
-
// 默认开启快捷键,且不是静默模式时enable
|
|
38
|
-
if (options.keyboard.enabled && !lf.options.isSilentMode) {
|
|
39
|
-
this.enable(true)
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
initShortcuts() {
|
|
44
|
-
const { shortcuts } = this.options.keyboard ?? {}
|
|
45
|
-
if (shortcuts) {
|
|
46
|
-
if (isArray(shortcuts)) {
|
|
47
|
-
shortcuts.forEach(({ keys, callback, action }) =>
|
|
48
|
-
this.on(keys, callback, action),
|
|
49
|
-
)
|
|
50
|
-
} else {
|
|
51
|
-
const { keys, callback, action } = shortcuts
|
|
52
|
-
this.on(keys, callback, action)
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
on(keys: string | string[], callback: Handler, action?: Action) {
|
|
58
|
-
this.mousetrap.bind(this.getKeys(keys), callback, action)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
get disabled() {
|
|
62
|
-
return this.options?.keyboard?.enabled !== true
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
off(keys: string | string[], action?: Action) {
|
|
66
|
-
this.mousetrap.unbind(this.getKeys(keys), action)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
enable(force: boolean) {
|
|
70
|
-
if (this.disabled || force) {
|
|
71
|
-
if (this.options.keyboard) {
|
|
72
|
-
this.options.keyboard.enabled = true
|
|
73
|
-
}
|
|
74
|
-
if (this.target instanceof HTMLElement) {
|
|
75
|
-
this.target.setAttribute('tabindex', '-1')
|
|
76
|
-
// 去掉节点被选中时container出现的边框
|
|
77
|
-
this.target.style.outline = 'none'
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
disable() {
|
|
83
|
-
if (!this.disabled) {
|
|
84
|
-
if (this.options.keyboard) {
|
|
85
|
-
this.options.keyboard.enabled = false
|
|
86
|
-
}
|
|
87
|
-
if (this.target instanceof HTMLElement) {
|
|
88
|
-
this.target.removeAttribute('tabindex')
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
destroy() {
|
|
94
|
-
this.mousetrap.reset()
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
private getKeys(keys: string | string[]) {
|
|
98
|
-
return (Array.isArray(keys) ? keys : [keys]).map((key) =>
|
|
99
|
-
this.formatKey(key),
|
|
100
|
-
)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
protected formatKey(key: string) {
|
|
104
|
-
return key
|
|
105
|
-
.toLowerCase()
|
|
106
|
-
.replace(/\s/g, '')
|
|
107
|
-
.replace('delete', 'del')
|
|
108
|
-
.replace('cmd', 'command')
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export default Keyboard
|
package/src/keyboard/shortcut.ts
DELETED
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import { isEmpty } from 'lodash-es'
|
|
2
|
-
import LogicFlow from '../LogicFlow'
|
|
3
|
-
import { map } from 'lodash-es'
|
|
4
|
-
import GraphModel from '../model/GraphModel'
|
|
5
|
-
|
|
6
|
-
import NodeData = LogicFlow.NodeData
|
|
7
|
-
import EdgeData = LogicFlow.EdgeData
|
|
8
|
-
import NodeConfig = LogicFlow.NodeConfig
|
|
9
|
-
import EdgeConfig = LogicFlow.EdgeConfig
|
|
10
|
-
|
|
11
|
-
let selected: LogicFlow.GraphData | null = null
|
|
12
|
-
|
|
13
|
-
export function translateNodeData(nodeData: NodeData, distance: number) {
|
|
14
|
-
nodeData.x += distance
|
|
15
|
-
nodeData.y += distance
|
|
16
|
-
|
|
17
|
-
if (!isEmpty(nodeData.text)) {
|
|
18
|
-
nodeData.text.x += distance
|
|
19
|
-
nodeData.text.y += distance
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (!isEmpty(nodeData.properties?._label)) {
|
|
23
|
-
nodeData.properties?._label.forEach((label) => {
|
|
24
|
-
label.x += distance
|
|
25
|
-
label.y += distance
|
|
26
|
-
})
|
|
27
|
-
}
|
|
28
|
-
return nodeData
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function translateEdgeData(edgeData: EdgeData, distance: number) {
|
|
32
|
-
if (edgeData.startPoint) {
|
|
33
|
-
edgeData.startPoint.x += distance
|
|
34
|
-
edgeData.startPoint.y += distance
|
|
35
|
-
}
|
|
36
|
-
if (edgeData.endPoint) {
|
|
37
|
-
edgeData.endPoint.x += distance
|
|
38
|
-
edgeData.endPoint.y += distance
|
|
39
|
-
}
|
|
40
|
-
if (edgeData.pointsList && edgeData.pointsList.length > 0) {
|
|
41
|
-
edgeData.pointsList.forEach((point) => {
|
|
42
|
-
point.x += distance
|
|
43
|
-
point.y += distance
|
|
44
|
-
})
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (!isEmpty(edgeData.text)) {
|
|
48
|
-
edgeData.text.x += distance
|
|
49
|
-
edgeData.text.y += distance
|
|
50
|
-
}
|
|
51
|
-
return edgeData
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function transformNodeData(
|
|
55
|
-
nodeData: NodeData,
|
|
56
|
-
distance: number,
|
|
57
|
-
): NodeConfig {
|
|
58
|
-
const { x, y, text } = nodeData
|
|
59
|
-
// 重新计算 text 的位置,保证粘贴后 text 位置和复制的原节点相对位置一致
|
|
60
|
-
const nextText = text
|
|
61
|
-
? {
|
|
62
|
-
x: text.x + distance,
|
|
63
|
-
y: text.y + distance,
|
|
64
|
-
value: text.value,
|
|
65
|
-
}
|
|
66
|
-
: undefined
|
|
67
|
-
|
|
68
|
-
return {
|
|
69
|
-
...nodeData,
|
|
70
|
-
id: '',
|
|
71
|
-
x: x + distance,
|
|
72
|
-
y: y + distance,
|
|
73
|
-
text: nextText,
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export function transformEdgeData(
|
|
78
|
-
edgeData: EdgeData,
|
|
79
|
-
distance: number,
|
|
80
|
-
): EdgeConfig {
|
|
81
|
-
const { startPoint, endPoint, pointsList, text, ...edgeConfig } = edgeData
|
|
82
|
-
// 清除原始边的 id
|
|
83
|
-
edgeConfig.id = ''
|
|
84
|
-
|
|
85
|
-
// 重新计算边的位置,包括 startPoint、endPoint、pointsList 以及 text
|
|
86
|
-
// TODO: 看这个是否可以提出一个通用方法,用于重新计算边的位置
|
|
87
|
-
const nextStartPoint = {
|
|
88
|
-
x: startPoint.x + distance,
|
|
89
|
-
y: startPoint.y + distance,
|
|
90
|
-
}
|
|
91
|
-
const nextEndPoint = {
|
|
92
|
-
x: endPoint.x + distance,
|
|
93
|
-
y: endPoint.y + distance,
|
|
94
|
-
}
|
|
95
|
-
const newPointsList: LogicFlow.Point[] = map(pointsList, (point) => {
|
|
96
|
-
return {
|
|
97
|
-
x: point.x + distance,
|
|
98
|
-
y: point.y + distance,
|
|
99
|
-
}
|
|
100
|
-
})
|
|
101
|
-
const nextText = text
|
|
102
|
-
? {
|
|
103
|
-
...text,
|
|
104
|
-
x: text.x + distance,
|
|
105
|
-
y: text.y + distance,
|
|
106
|
-
}
|
|
107
|
-
: undefined
|
|
108
|
-
|
|
109
|
-
return {
|
|
110
|
-
...edgeConfig,
|
|
111
|
-
startPoint: nextStartPoint,
|
|
112
|
-
endPoint: nextEndPoint,
|
|
113
|
-
pointsList: newPointsList,
|
|
114
|
-
text: nextText,
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const TRANSLATION_DISTANCE = 40
|
|
119
|
-
let CHILDREN_TRANSLATION_DISTANCE = 40
|
|
120
|
-
|
|
121
|
-
export function initDefaultShortcut(lf: LogicFlow, graph: GraphModel) {
|
|
122
|
-
const { keyboard } = lf
|
|
123
|
-
const {
|
|
124
|
-
options: { keyboard: keyboardOptions },
|
|
125
|
-
} = keyboard
|
|
126
|
-
|
|
127
|
-
// 复制
|
|
128
|
-
keyboard.on(['cmd + c', 'ctrl + c'], () => {
|
|
129
|
-
CHILDREN_TRANSLATION_DISTANCE = TRANSLATION_DISTANCE
|
|
130
|
-
if (!keyboardOptions?.enabled) return true
|
|
131
|
-
if (graph.textEditElement) return true
|
|
132
|
-
const { guards } = lf.options
|
|
133
|
-
const elements = graph.getSelectElements(false)
|
|
134
|
-
const enabledClone =
|
|
135
|
-
guards && guards.beforeClone ? guards.beforeClone(elements) : true
|
|
136
|
-
if (
|
|
137
|
-
!enabledClone ||
|
|
138
|
-
(elements.nodes.length === 0 && elements.edges.length === 0)
|
|
139
|
-
) {
|
|
140
|
-
selected = null
|
|
141
|
-
return true
|
|
142
|
-
}
|
|
143
|
-
selected = elements
|
|
144
|
-
selected.nodes.forEach((node) =>
|
|
145
|
-
translateNodeData(node, TRANSLATION_DISTANCE),
|
|
146
|
-
)
|
|
147
|
-
selected.edges.forEach((edge) =>
|
|
148
|
-
translateEdgeData(edge, TRANSLATION_DISTANCE),
|
|
149
|
-
)
|
|
150
|
-
return false
|
|
151
|
-
})
|
|
152
|
-
// 粘贴
|
|
153
|
-
keyboard.on(['cmd + v', 'ctrl + v'], () => {
|
|
154
|
-
if (!keyboardOptions?.enabled) return true
|
|
155
|
-
if (graph.textEditElement) return true
|
|
156
|
-
if (selected && (selected.nodes || selected.edges)) {
|
|
157
|
-
lf.clearSelectElements()
|
|
158
|
-
const addElements = lf.addElements(
|
|
159
|
-
selected,
|
|
160
|
-
CHILDREN_TRANSLATION_DISTANCE,
|
|
161
|
-
)
|
|
162
|
-
if (!addElements) return true
|
|
163
|
-
addElements.nodes.forEach((node) => lf.selectElementById(node.id, true))
|
|
164
|
-
addElements.edges.forEach((edge) => lf.selectElementById(edge.id, true))
|
|
165
|
-
selected.nodes.forEach((node) =>
|
|
166
|
-
translateNodeData(node, TRANSLATION_DISTANCE),
|
|
167
|
-
)
|
|
168
|
-
selected.edges.forEach((edge) =>
|
|
169
|
-
translateEdgeData(edge, TRANSLATION_DISTANCE),
|
|
170
|
-
)
|
|
171
|
-
CHILDREN_TRANSLATION_DISTANCE =
|
|
172
|
-
CHILDREN_TRANSLATION_DISTANCE + TRANSLATION_DISTANCE
|
|
173
|
-
}
|
|
174
|
-
return false
|
|
175
|
-
})
|
|
176
|
-
// undo
|
|
177
|
-
keyboard.on(['cmd + z', 'ctrl + z'], () => {
|
|
178
|
-
if (!keyboardOptions?.enabled) return true
|
|
179
|
-
if (graph.textEditElement) return true
|
|
180
|
-
lf.undo()
|
|
181
|
-
return false
|
|
182
|
-
})
|
|
183
|
-
// redo
|
|
184
|
-
keyboard.on(['cmd + y', 'ctrl + y'], () => {
|
|
185
|
-
if (!keyboardOptions?.enabled) return true
|
|
186
|
-
if (graph.textEditElement) return true
|
|
187
|
-
lf.redo()
|
|
188
|
-
return false
|
|
189
|
-
})
|
|
190
|
-
// delete
|
|
191
|
-
keyboard.on(['backspace'], () => {
|
|
192
|
-
if (!keyboardOptions?.enabled) return true
|
|
193
|
-
if (graph.textEditElement) return true
|
|
194
|
-
const elements = graph.getSelectElements(true)
|
|
195
|
-
lf.clearSelectElements()
|
|
196
|
-
elements.edges.forEach((edge) => edge.id && lf.deleteEdge(edge.id))
|
|
197
|
-
elements.nodes.forEach((node) => node.id && lf.deleteNode(node.id))
|
|
198
|
-
return false
|
|
199
|
-
})
|
|
200
|
-
}
|