@logicflow/core 2.0.12 → 2.0.14

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 (68) hide show
  1. package/.turbo/turbo-build$colon$dev.log +2 -2
  2. package/.turbo/turbo-build.log +7 -7
  3. package/CHANGELOG.md +12 -0
  4. package/__tests__/algorithm/index.test.ts +22 -17
  5. package/__tests__/algorithm/outline.test.ts +9 -9
  6. package/__tests__/event/event.test.ts +18 -18
  7. package/__tests__/history/history.test.ts +23 -23
  8. package/__tests__/logicflow.test.ts +236 -228
  9. package/__tests__/model/graphmodel.test.ts +51 -31
  10. package/__tests__/util/compatible.test.ts +5 -5
  11. package/__tests__/util/geometry.test.ts +10 -10
  12. package/__tests__/util/graph.test.ts +12 -12
  13. package/__tests__/util/matrix.test.ts +26 -26
  14. package/__tests__/util/node.test.ts +22 -22
  15. package/__tests__/util/sampling.test.ts +6 -10
  16. package/__tests__/util/vector.test.ts +36 -36
  17. package/__tests__/util/zIndex.test.ts +6 -6
  18. package/dist/index.min.js +1 -1
  19. package/dist/index.min.js.map +1 -1
  20. package/es/LogicFlow.d.ts +29 -4
  21. package/es/LogicFlow.js +35 -6
  22. package/es/model/GraphModel.d.ts +35 -1
  23. package/es/model/GraphModel.js +45 -5
  24. package/es/model/node/RectNodeModel.js +3 -0
  25. package/es/options.d.ts +1 -0
  26. package/es/util/theme.d.ts +67 -2
  27. package/es/util/theme.js +189 -2
  28. package/es/view/Graph.d.ts +0 -3
  29. package/es/view/Graph.js +3 -7
  30. package/es/view/edge/BaseEdge.d.ts +4 -0
  31. package/es/view/edge/BaseEdge.js +45 -3
  32. package/es/view/overlay/Grid.js +3 -2
  33. package/es/view/overlay/ToolOverlay.d.ts +1 -3
  34. package/es/view/overlay/ToolOverlay.js +2 -39
  35. package/es/view/shape/Polygon.d.ts +8 -0
  36. package/es/view/shape/Polygon.js +50 -3
  37. package/lib/LogicFlow.d.ts +29 -4
  38. package/lib/LogicFlow.js +34 -5
  39. package/lib/model/GraphModel.d.ts +35 -1
  40. package/lib/model/GraphModel.js +43 -3
  41. package/lib/model/node/RectNodeModel.js +3 -0
  42. package/lib/options.d.ts +1 -0
  43. package/lib/util/theme.d.ts +67 -2
  44. package/lib/util/theme.js +192 -2
  45. package/lib/view/Graph.d.ts +0 -3
  46. package/lib/view/Graph.js +2 -6
  47. package/lib/view/edge/BaseEdge.d.ts +4 -0
  48. package/lib/view/edge/BaseEdge.js +45 -3
  49. package/lib/view/overlay/Grid.js +3 -2
  50. package/lib/view/overlay/ToolOverlay.d.ts +1 -3
  51. package/lib/view/overlay/ToolOverlay.js +2 -39
  52. package/lib/view/shape/Polygon.d.ts +8 -0
  53. package/lib/view/shape/Polygon.js +52 -4
  54. package/package.json +1 -1
  55. package/src/LogicFlow.tsx +57 -7
  56. package/src/model/GraphModel.ts +56 -3
  57. package/src/model/edge/index.ts +4 -4
  58. package/src/model/index.ts +7 -7
  59. package/src/model/node/RectNodeModel.ts +2 -1
  60. package/src/model/node/index.ts +8 -8
  61. package/src/options.ts +1 -0
  62. package/src/util/theme.ts +198 -3
  63. package/src/view/Graph.tsx +3 -15
  64. package/src/view/edge/BaseEdge.tsx +96 -12
  65. package/src/view/overlay/Grid.tsx +2 -1
  66. package/src/view/overlay/ToolOverlay.tsx +2 -17
  67. package/src/view/shape/Polygon.tsx +56 -4
  68. package/stats.html +1 -1
@@ -162,6 +162,64 @@ export abstract class BaseEdge<P extends IProps> extends Component<
162
162
  )
163
163
  }
164
164
 
165
+ /**
166
+ * Private helper method to generate arrow path based on type and parameters
167
+ */
168
+ private getArrowPath(
169
+ arrowType: string,
170
+ props: {
171
+ stroke?: string
172
+ fill?: string
173
+ strokeWidth?: number
174
+ offset: number
175
+ verticalLength: number
176
+ strokeLinecap?: string
177
+ strokeLinejoin?: string
178
+ transform?: string
179
+ },
180
+ ): h.JSX.Element {
181
+ const {
182
+ stroke,
183
+ fill = stroke,
184
+ strokeWidth,
185
+ offset = 10,
186
+ verticalLength,
187
+ strokeLinecap,
188
+ strokeLinejoin,
189
+ transform,
190
+ } = props
191
+ let arrowPath = ''
192
+
193
+ switch (arrowType) {
194
+ case 'solid':
195
+ arrowPath = `M${-offset / 4},0 L${(3 * offset) / 4},${verticalLength} L${(3 * offset) / 4},-${verticalLength} Z`
196
+ break
197
+ case 'hollow':
198
+ arrowPath = `M${-offset / 4},0 L${(3 * offset) / 4},${verticalLength} L${-offset / 4},0 L${(3 * offset) / 4},-${verticalLength} L${-offset / 4},0 Z`
199
+ break
200
+ case 'diamond':
201
+ arrowPath = `M${-offset / 2},0 L0,${verticalLength} L${offset / 2},0 L0,-${verticalLength} L${-offset / 2},0 Z`
202
+ break
203
+ case 'circle':
204
+ arrowPath = `M${-offset / 2},0 A${offset / 4},${offset / 4} 0 1,0 ${offset / 2},0 A${offset / 4},${offset / 4} 0 1,0 ${-offset / 2},0 Z`
205
+ break
206
+ default:
207
+ arrowPath = ''
208
+ break
209
+ }
210
+ return (
211
+ <path
212
+ d={arrowPath}
213
+ stroke={stroke}
214
+ fill={fill}
215
+ strokeWidth={strokeWidth}
216
+ strokeLinecap={strokeLinecap as any}
217
+ strokeLinejoin={strokeLinejoin as any}
218
+ transform={transform}
219
+ />
220
+ )
221
+ }
222
+
165
223
  /**
166
224
  * @overridable 可重写,自定义边起点箭头形状。
167
225
  * @example
@@ -176,7 +234,25 @@ export abstract class BaseEdge<P extends IProps> extends Component<
176
234
  * }
177
235
  */
178
236
  getStartArrow(): h.JSX.Element | null {
179
- return <path />
237
+ const { model } = this.props
238
+ const {
239
+ stroke,
240
+ strokeWidth,
241
+ offset,
242
+ verticalLength,
243
+ startArrowType = 'solid',
244
+ strokeLinecap,
245
+ strokeLinejoin,
246
+ } = model.getArrowStyle()
247
+
248
+ return this.getArrowPath(startArrowType, {
249
+ stroke,
250
+ strokeWidth,
251
+ offset,
252
+ verticalLength,
253
+ strokeLinecap,
254
+ strokeLinejoin,
255
+ })
180
256
  }
181
257
 
182
258
  /**
@@ -194,17 +270,25 @@ export abstract class BaseEdge<P extends IProps> extends Component<
194
270
  */
195
271
  getEndArrow(): h.JSX.Element | null {
196
272
  const { model } = this.props
197
- const { stroke, strokeWidth, offset, verticalLength } =
198
- model.getArrowStyle()
199
- return (
200
- <path
201
- stroke={stroke}
202
- fill={stroke}
203
- strokeWidth={strokeWidth}
204
- transform="rotate(180)"
205
- d={`M 0 0 L ${offset} -${verticalLength} L ${offset} ${verticalLength} Z`}
206
- />
207
- )
273
+ const {
274
+ stroke,
275
+ strokeWidth,
276
+ offset,
277
+ verticalLength,
278
+ endArrowType = 'solid',
279
+ strokeLinecap,
280
+ strokeLinejoin,
281
+ } = model.getArrowStyle()
282
+
283
+ return this.getArrowPath(endArrowType, {
284
+ stroke,
285
+ strokeWidth,
286
+ offset,
287
+ verticalLength,
288
+ strokeLinecap,
289
+ strokeLinejoin,
290
+ transform: 'rotate(180)',
291
+ })
208
292
  }
209
293
 
210
294
  /**
@@ -62,8 +62,9 @@ export class Grid extends Component<IProps> {
62
62
 
63
63
  render() {
64
64
  const {
65
- graphModel: { transformModel },
65
+ graphModel: { transformModel, grid },
66
66
  } = this.props
67
+ this.gridOptions = grid
67
68
  const { type, size = 1 } = this.gridOptions
68
69
  const { SCALE_X, SKEW_Y, SKEW_X, SCALE_Y, TRANSLATE_X, TRANSLATE_Y } =
69
70
  transformModel
@@ -1,5 +1,5 @@
1
1
  import { createElement as h, Component } from 'preact/compat'
2
- import { CanvasOverlay, OutlineOverlay } from '.'
2
+ import { OutlineOverlay } from '.'
3
3
  import { observer } from '../..'
4
4
  import LogicFlow from '../../LogicFlow'
5
5
  import { GraphModel } from '../../model'
@@ -8,7 +8,6 @@ import { Tool } from '../../tool'
8
8
  type IProps = {
9
9
  graphModel: GraphModel
10
10
  tool: Tool
11
- getCanvasOverlay: () => CanvasOverlay | null
12
11
  }
13
12
 
14
13
  @observer
@@ -53,24 +52,10 @@ export class ToolOverlay extends Component<IProps> {
53
52
  lf.components = [] // 保证extension组件的render只执行一次
54
53
  }
55
54
 
56
- zoomHandler = (e: WheelEvent) => {
57
- // TODO 是否应该使用 dispatchEvent 来触发事件
58
- this.props.getCanvasOverlay()?.zoomHandler(e)
59
- }
60
-
61
55
  render() {
62
56
  const { graphModel } = this.props
63
57
  return (
64
- <div
65
- className="lf-tool-overlay"
66
- id={`ToolOverlay_${graphModel.flowId}`}
67
- /*
68
- * 默认情况下该容器设置了 pointer-events: none,不会触发这些事件
69
- * 只会在容器取消 pointer-events: none 后触发,用于缩放、滚动画布等操作
70
- * 目前只在 selection-select 插件中使用。为了能在元素内部进行框选,在开启选区后会关闭事件透传。需要手动触发事件
71
- */
72
- onWheel={this.zoomHandler}
73
- >
58
+ <div className="lf-tool-overlay" id={`ToolOverlay_${graphModel.flowId}`}>
74
59
  {this.getTools()}
75
60
  </div>
76
61
  )
@@ -7,10 +7,57 @@ export type IPolygonProps = {
7
7
  x?: number
8
8
  y?: number
9
9
  className?: string
10
+ radius?: number
11
+ }
12
+ /**
13
+ * 生成带圆角的多边形路径
14
+ * @param points 多边形顶点坐标数组
15
+ * @param radius 圆角半径
16
+ * @returns SVG 路径字符串
17
+ */
18
+ export function createRoundedPolygonPath(points, radius): string {
19
+ const pointList = points.map((point) => ({ x: point[0], y: point[1] }))
20
+ const len = pointList.length
21
+ if (len < 3) return ''
22
+
23
+ const r = Math.abs(radius)
24
+ let path = ''
25
+
26
+ for (let i = 0; i < len; i++) {
27
+ const prev = pointList[(i - 1 + len) % len]
28
+ const curr = pointList[i]
29
+ const next = pointList[(i + 1) % len]
30
+
31
+ // 向量
32
+ const v1 = { x: curr.x - prev.x, y: curr.y - prev.y }
33
+ const v2 = { x: next.x - curr.x, y: next.y - curr.y }
34
+
35
+ // 单位向量
36
+ const len1 = Math.hypot(v1.x, v1.y)
37
+ const len2 = Math.hypot(v2.x, v2.y)
38
+ const u1 = { x: v1.x / len1, y: v1.y / len1 }
39
+ const u2 = { x: v2.x / len2, y: v2.y / len2 }
40
+
41
+ // 起点 = curr - u1 * r,终点 = curr + u2 * r
42
+ const start = { x: curr.x - u1.x * r, y: curr.y - u1.y * r }
43
+ const end = { x: curr.x + u2.x * r, y: curr.y + u2.y * r }
44
+
45
+ if (i === 0) {
46
+ path += `M ${start.x} ${start.y} `
47
+ } else {
48
+ path += `L ${start.x} ${start.y} `
49
+ }
50
+
51
+ // Q 控制点是当前拐角点
52
+ path += `Q ${curr.x} ${curr.y} ${end.x} ${end.y} `
53
+ }
54
+
55
+ path += 'Z'
56
+ return path
10
57
  }
11
58
 
12
59
  export function Polygon(props: IPolygonProps): h.JSX.Element {
13
- const { points = [], className } = props
60
+ const { points = [], className, radius } = props
14
61
  const attrs: Record<string, any> = {
15
62
  fill: 'transparent',
16
63
  fillOpacity: 1,
@@ -31,9 +78,14 @@ export function Polygon(props: IPolygonProps): h.JSX.Element {
31
78
  } else {
32
79
  attrs.className = 'lf-basic-shape'
33
80
  }
34
- attrs.points = points.map((point) => point.join(',')).join(' ')
35
-
36
- return <polygon {...attrs} />
81
+ if (radius) {
82
+ const path = createRoundedPolygonPath(points, radius)
83
+ attrs.d = path
84
+ return <path {...attrs} />
85
+ } else {
86
+ attrs.points = points.map((point) => point.join(',')).join(' ')
87
+ return <polygon {...attrs} />
88
+ }
37
89
  }
38
90
 
39
91
  export default Polygon