@logicflow/core 2.0.13 → 2.0.15

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 (58) hide show
  1. package/.turbo/turbo-build$colon$dev.log +2 -2
  2. package/.turbo/turbo-build.log +6 -6
  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 +24 -4
  21. package/es/LogicFlow.js +28 -6
  22. package/es/model/GraphModel.d.ts +34 -1
  23. package/es/model/GraphModel.js +36 -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/edge/BaseEdge.d.ts +4 -0
  29. package/es/view/edge/BaseEdge.js +45 -3
  30. package/es/view/overlay/Grid.js +3 -2
  31. package/es/view/shape/Polygon.d.ts +8 -0
  32. package/es/view/shape/Polygon.js +50 -3
  33. package/lib/LogicFlow.d.ts +24 -4
  34. package/lib/LogicFlow.js +27 -5
  35. package/lib/model/GraphModel.d.ts +34 -1
  36. package/lib/model/GraphModel.js +34 -3
  37. package/lib/model/node/RectNodeModel.js +3 -0
  38. package/lib/options.d.ts +1 -0
  39. package/lib/util/theme.d.ts +67 -2
  40. package/lib/util/theme.js +192 -2
  41. package/lib/view/edge/BaseEdge.d.ts +4 -0
  42. package/lib/view/edge/BaseEdge.js +45 -3
  43. package/lib/view/overlay/Grid.js +3 -2
  44. package/lib/view/shape/Polygon.d.ts +8 -0
  45. package/lib/view/shape/Polygon.js +52 -4
  46. package/package.json +1 -1
  47. package/src/LogicFlow.tsx +48 -6
  48. package/src/model/GraphModel.ts +48 -3
  49. package/src/model/edge/index.ts +4 -4
  50. package/src/model/index.ts +7 -7
  51. package/src/model/node/RectNodeModel.ts +2 -1
  52. package/src/model/node/index.ts +8 -8
  53. package/src/options.ts +1 -0
  54. package/src/util/theme.ts +198 -3
  55. package/src/view/edge/BaseEdge.tsx +96 -12
  56. package/src/view/overlay/Grid.tsx +2 -1
  57. package/src/view/shape/Polygon.tsx +56 -4
  58. 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 = 'none',
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
@@ -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