@logicflow/extension 2.2.0-alpha.0 → 2.2.0-alpha.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/.turbo/turbo-build.log +7 -7
- package/CHANGELOG.md +12 -2
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/es/insert-node-in-polyline/index.js +11 -35
- package/es/tools/label/LabelOverlay.js +3 -3
- package/es/tools/label/mediumEditor.d.ts +1 -1
- package/es/tools/label/mediumEditor.js +89 -52
- package/es/tools/snapshot/index.js +26 -13
- package/lib/insert-node-in-polyline/index.js +10 -34
- package/lib/tools/label/LabelOverlay.js +2 -2
- package/lib/tools/label/mediumEditor.d.ts +1 -1
- package/lib/tools/label/mediumEditor.js +91 -53
- package/lib/tools/snapshot/index.js +26 -13
- package/package.json +5 -5
- package/src/insert-node-in-polyline/index.ts +17 -11
- package/src/tools/label/LabelOverlay.tsx +7 -3
- package/src/tools/label/mediumEditor.ts +78 -51
- package/src/tools/snapshot/index.ts +12 -0
- package/stats.html +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@logicflow/extension",
|
|
3
|
-
"version": "2.2.0-alpha.
|
|
3
|
+
"version": "2.2.0-alpha.1",
|
|
4
4
|
"description": "LogicFlow Extensions",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "es/index.js",
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"author": "Logicflow-Team",
|
|
21
21
|
"license": "Apache-2.0",
|
|
22
22
|
"peerDependencies": {
|
|
23
|
-
"@logicflow/
|
|
24
|
-
"@logicflow/
|
|
23
|
+
"@logicflow/vue-node-registry": "1.2.0-alpha.1",
|
|
24
|
+
"@logicflow/core": "2.2.0-alpha.1"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@antv/hierarchy": "^0.6.11",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"preact": "^10.17.1",
|
|
33
33
|
"rangy": "^1.3.1",
|
|
34
34
|
"vanilla-picker": "^2.12.3",
|
|
35
|
-
"@logicflow/core": "2.2.0-alpha.
|
|
36
|
-
"@logicflow/vue-node-registry": "1.2.0-alpha.
|
|
35
|
+
"@logicflow/core": "2.2.0-alpha.1",
|
|
36
|
+
"@logicflow/vue-node-registry": "1.2.0-alpha.1"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"less": "^4.1.1",
|
|
@@ -3,6 +3,7 @@ import LogicFlow, {
|
|
|
3
3
|
PolylineEdgeModel,
|
|
4
4
|
EventType,
|
|
5
5
|
formatAnchorConnectValidateData,
|
|
6
|
+
getClosestAnchor,
|
|
6
7
|
} from '@logicflow/core'
|
|
7
8
|
import { cloneDeep } from 'lodash-es'
|
|
8
9
|
import { isNodeInSegment } from './edge'
|
|
@@ -132,7 +133,6 @@ export class InsertNodeInPolyline {
|
|
|
132
133
|
} = edges[i]
|
|
133
134
|
// fix https://github.com/didi/LogicFlow/issues/996
|
|
134
135
|
const startPoint = cloneDeep(pointsList[0])
|
|
135
|
-
const endPoint = cloneDeep(crossPoints.startCrossPoint)
|
|
136
136
|
this._lf.deleteEdge(id)
|
|
137
137
|
const checkResult = this.checkRuleBeforeInsetNode(
|
|
138
138
|
sourceNodeId,
|
|
@@ -141,27 +141,33 @@ export class InsertNodeInPolyline {
|
|
|
141
141
|
targetAnchorId!,
|
|
142
142
|
nodeData,
|
|
143
143
|
)
|
|
144
|
+
// 基于插入节点的进入交点计算出最近的“进入锚点”,用于重连原边的前半段
|
|
145
|
+
const entryAnchorInfo = getClosestAnchor(
|
|
146
|
+
crossPoints.startCrossPoint,
|
|
147
|
+
nodeModel,
|
|
148
|
+
)
|
|
149
|
+
const entryAnchor = entryAnchorInfo.anchor
|
|
150
|
+
// 构造第一条边:原 source → 插入节点(终点为进入锚点)
|
|
144
151
|
this._lf.addEdge({
|
|
145
152
|
type,
|
|
146
153
|
sourceNodeId,
|
|
147
154
|
targetNodeId: nodeData.id,
|
|
148
155
|
startPoint,
|
|
149
|
-
endPoint,
|
|
150
|
-
pointsList: [
|
|
151
|
-
...pointsList.slice(0, crossIndex),
|
|
152
|
-
crossPoints.startCrossPoint,
|
|
153
|
-
],
|
|
156
|
+
endPoint: entryAnchor,
|
|
154
157
|
})
|
|
158
|
+
// 基于插入节点的离开交点计算出最近的“离开锚点”,用于重连原边的后半段
|
|
159
|
+
const exitAnchorInfo = getClosestAnchor(
|
|
160
|
+
crossPoints.endCrossPoint,
|
|
161
|
+
nodeModel,
|
|
162
|
+
)
|
|
163
|
+
const exitAnchor = exitAnchorInfo.anchor
|
|
164
|
+
// 构造第二条边:插入节点 → 原 target(起点为离开锚点)
|
|
155
165
|
this._lf.addEdge({
|
|
156
166
|
type,
|
|
157
167
|
sourceNodeId: nodeData.id,
|
|
158
168
|
targetNodeId,
|
|
159
|
-
startPoint: cloneDeep(
|
|
169
|
+
startPoint: cloneDeep(exitAnchor),
|
|
160
170
|
endPoint: cloneDeep(pointsList[pointsList.length - 1]),
|
|
161
|
-
pointsList: [
|
|
162
|
-
crossPoints.endCrossPoint,
|
|
163
|
-
...pointsList.slice(crossIndex),
|
|
164
|
-
],
|
|
165
171
|
})
|
|
166
172
|
if (!checkResult.isPass) {
|
|
167
173
|
this._lf.graphModel.eventCenter.emit(
|
|
@@ -4,7 +4,11 @@ import { forEach, merge } from 'lodash-es'
|
|
|
4
4
|
import LabelPlugin from '.'
|
|
5
5
|
import Label from './Label'
|
|
6
6
|
import LabelModel from './LabelModel'
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
MediumEditor,
|
|
9
|
+
defaultOptions,
|
|
10
|
+
createColorPickerButtonClass,
|
|
11
|
+
} from './mediumEditor'
|
|
8
12
|
|
|
9
13
|
import LabelConfig = LogicFlow.LabelConfig
|
|
10
14
|
|
|
@@ -47,7 +51,7 @@ export class LabelOverlay extends Component<IToolProps, ILabelOverlayState> {
|
|
|
47
51
|
merge(defaultOptions, {
|
|
48
52
|
autoLink: true,
|
|
49
53
|
extensions: {
|
|
50
|
-
colorPicker: new
|
|
54
|
+
colorPicker: new (createColorPickerButtonClass(MediumEditor))(),
|
|
51
55
|
},
|
|
52
56
|
}),
|
|
53
57
|
)
|
|
@@ -82,7 +86,7 @@ export class LabelOverlay extends Component<IToolProps, ILabelOverlayState> {
|
|
|
82
86
|
merge(defaultOptions, {
|
|
83
87
|
autoLink: true,
|
|
84
88
|
extensions: {
|
|
85
|
-
colorPicker: new
|
|
89
|
+
colorPicker: new (createColorPickerButtonClass(MediumEditor))(),
|
|
86
90
|
},
|
|
87
91
|
}),
|
|
88
92
|
)
|
|
@@ -39,56 +39,83 @@ export const defaultOptions = {
|
|
|
39
39
|
disableEditing: true,
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
export
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
42
|
+
export function createColorPickerButtonClass(MediumEditor?: any) {
|
|
43
|
+
const ButtonBase =
|
|
44
|
+
MediumEditor?.extensions?.button || MediumEditor?.extensions?.button
|
|
45
|
+
const ExtensionBase =
|
|
46
|
+
MediumEditor?.Extension || (MediumEditor as any)?.Extension
|
|
47
|
+
|
|
48
|
+
// 当 Button 扩展基类不可用时,回退到 Extension 基类,避免在模块加载阶段抛错
|
|
49
|
+
const Base = ButtonBase || ExtensionBase
|
|
50
|
+
if (!Base) {
|
|
51
|
+
console.warn(
|
|
52
|
+
'MediumEditor button/extension base not available; using noop extension',
|
|
53
|
+
)
|
|
54
|
+
return class {}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return Base.extend({
|
|
58
|
+
name: 'colorpicker',
|
|
59
|
+
tagNames: ['mark'],
|
|
60
|
+
contentDefault: '<b>Color</b>',
|
|
61
|
+
aria: 'Color Picker',
|
|
62
|
+
action: 'colorPicker',
|
|
63
|
+
init: function () {
|
|
64
|
+
try {
|
|
65
|
+
rangy.init()
|
|
66
|
+
} catch {
|
|
67
|
+
console.error('rangy.init failed')
|
|
68
|
+
}
|
|
69
|
+
// 初始化按钮(ButtonBase 才有 prototype.init)
|
|
70
|
+
try {
|
|
71
|
+
;(ButtonBase as any)?.prototype?.init?.call(this)
|
|
72
|
+
} catch {
|
|
73
|
+
console.error('ButtonBase.init failed')
|
|
74
|
+
}
|
|
75
|
+
this.colorPicker = new Picker({
|
|
76
|
+
parent: (this as any).button || undefined,
|
|
77
|
+
color: '#000',
|
|
78
|
+
onDone: (res) => {
|
|
79
|
+
try {
|
|
80
|
+
if (this.coloredText && this.coloredText.isAppliedToSelection?.()) {
|
|
81
|
+
this.coloredText.undoToSelection()
|
|
82
|
+
}
|
|
83
|
+
this.coloredText = rangy.createClassApplier('colored', {
|
|
84
|
+
elementTagName: 'span',
|
|
85
|
+
elementProperties: { style: { color: res.hex } },
|
|
86
|
+
normalize: true,
|
|
87
|
+
})
|
|
88
|
+
this.coloredText.toggleSelection()
|
|
89
|
+
this.base?.checkContentChanged?.()
|
|
90
|
+
this.setInactive?.()
|
|
91
|
+
} catch {
|
|
92
|
+
console.error('Picker.onDone failed')
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
})
|
|
96
|
+
},
|
|
97
|
+
getButton: function () {
|
|
98
|
+
return (this as any).button
|
|
99
|
+
},
|
|
100
|
+
handleClick: function () {
|
|
101
|
+
this.setActive?.()
|
|
102
|
+
this.colorPicker?.show?.()
|
|
103
|
+
},
|
|
104
|
+
isAlreadyApplied: function (node) {
|
|
105
|
+
return node?.nodeName?.toLowerCase?.() === 'mark'
|
|
106
|
+
},
|
|
107
|
+
isActive: function () {
|
|
108
|
+
return (this as any).button?.classList?.contains(
|
|
109
|
+
'medium-editor-button-active',
|
|
110
|
+
)
|
|
111
|
+
},
|
|
112
|
+
setInactive: function () {
|
|
113
|
+
;(this as any).button?.classList?.remove('medium-editor-button-active')
|
|
114
|
+
},
|
|
115
|
+
setActive: function () {
|
|
116
|
+
;(this as any).button?.classList?.add('medium-editor-button-active')
|
|
117
|
+
},
|
|
118
|
+
})
|
|
119
|
+
}
|
|
93
120
|
|
|
94
121
|
export { MediumEditor }
|
|
@@ -646,6 +646,18 @@ export class Snapshot {
|
|
|
646
646
|
const { fileType = baseFileType } = toImageOptions ?? {}
|
|
647
647
|
const svg = this.getSvgRootElement(this.lf)
|
|
648
648
|
await updateImageSource(svg as SVGElement)
|
|
649
|
+
if (fileType === 'svg') {
|
|
650
|
+
const copy = await this.cloneSvg(svg)
|
|
651
|
+
const svgString = new XMLSerializer().serializeToString(copy)
|
|
652
|
+
const blob = new Blob([svgString], {
|
|
653
|
+
type: 'image/svg+xml;charset=utf-8',
|
|
654
|
+
})
|
|
655
|
+
return {
|
|
656
|
+
data: blob,
|
|
657
|
+
width: 0,
|
|
658
|
+
height: 0,
|
|
659
|
+
}
|
|
660
|
+
}
|
|
649
661
|
return new Promise((resolve) => {
|
|
650
662
|
this.getCanvasData(svg, {
|
|
651
663
|
backgroundColor,
|