@logicflow/core 2.0.6 → 2.0.8

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 (105) hide show
  1. package/.turbo/turbo-build$colon$dev.log +2 -2
  2. package/.turbo/turbo-build.log +3 -19
  3. package/CHANGELOG.md +31 -0
  4. package/__tests__/algorithm/egde.test.ts +36 -23
  5. package/dist/index.css +3 -0
  6. package/es/algorithm/edge.js +3 -5
  7. package/es/constant/index.d.ts +4 -0
  8. package/es/constant/index.js +4 -0
  9. package/es/event/eventArgs.d.ts +40 -30
  10. package/es/index.css +3 -0
  11. package/es/model/GraphModel.d.ts +13 -3
  12. package/es/model/GraphModel.js +54 -3
  13. package/es/model/edge/BaseEdgeModel.d.ts +1 -0
  14. package/es/model/edge/LineEdgeModel.d.ts +2 -0
  15. package/es/model/edge/LineEdgeModel.js +8 -0
  16. package/es/model/edge/PolylineEdgeModel.d.ts +1 -0
  17. package/es/model/edge/PolylineEdgeModel.js +4 -3
  18. package/es/model/node/BaseNodeModel.d.ts +2 -2
  19. package/es/model/node/BaseNodeModel.js +1 -1
  20. package/es/model/node/HtmlNodeModel.d.ts +2 -2
  21. package/es/model/node/TextNodeModel.d.ts +2 -2
  22. package/es/style/index.css +3 -0
  23. package/es/style/index.less +5 -0
  24. package/es/style/raw.d.ts +1 -1
  25. package/es/style/raw.js +1 -1
  26. package/es/util/drag.d.ts +1 -0
  27. package/es/util/drag.js +11 -0
  28. package/es/view/Anchor.js +6 -8
  29. package/es/view/Control.js +1 -1
  30. package/es/view/Graph.js +3 -15
  31. package/es/view/behavior/dnd.js +1 -0
  32. package/es/view/edge/BaseEdge.d.ts +5 -1
  33. package/es/view/edge/BaseEdge.js +20 -5
  34. package/es/view/node/BaseNode.d.ts +2 -0
  35. package/es/view/node/BaseNode.js +13 -1
  36. package/es/view/overlay/BackgroundOverlay.d.ts +4 -14
  37. package/es/view/overlay/BackgroundOverlay.js +12 -1
  38. package/es/view/overlay/Grid.d.ts +4 -3
  39. package/es/view/overlay/Grid.js +8 -31
  40. package/es/view/overlay/getTransformHoc.d.ts +1 -1
  41. package/es/view/text/BaseText.js +1 -1
  42. package/lib/algorithm/edge.js +3 -5
  43. package/lib/constant/index.d.ts +4 -0
  44. package/lib/constant/index.js +4 -0
  45. package/lib/event/eventArgs.d.ts +40 -30
  46. package/lib/index.css +3 -0
  47. package/lib/model/GraphModel.d.ts +13 -3
  48. package/lib/model/GraphModel.js +53 -2
  49. package/lib/model/edge/BaseEdgeModel.d.ts +1 -0
  50. package/lib/model/edge/LineEdgeModel.d.ts +2 -0
  51. package/lib/model/edge/LineEdgeModel.js +8 -0
  52. package/lib/model/edge/PolylineEdgeModel.d.ts +1 -0
  53. package/lib/model/edge/PolylineEdgeModel.js +4 -3
  54. package/lib/model/node/BaseNodeModel.d.ts +2 -2
  55. package/lib/model/node/BaseNodeModel.js +1 -1
  56. package/lib/model/node/HtmlNodeModel.d.ts +2 -2
  57. package/lib/model/node/TextNodeModel.d.ts +2 -2
  58. package/lib/style/index.css +3 -0
  59. package/lib/style/index.less +5 -0
  60. package/lib/style/raw.d.ts +1 -1
  61. package/lib/style/raw.js +1 -1
  62. package/lib/util/drag.d.ts +1 -0
  63. package/lib/util/drag.js +11 -0
  64. package/lib/view/Anchor.js +6 -8
  65. package/lib/view/Control.js +1 -1
  66. package/lib/view/Graph.js +3 -15
  67. package/lib/view/behavior/dnd.js +1 -0
  68. package/lib/view/edge/BaseEdge.d.ts +5 -1
  69. package/lib/view/edge/BaseEdge.js +20 -5
  70. package/lib/view/node/BaseNode.d.ts +2 -0
  71. package/lib/view/node/BaseNode.js +13 -1
  72. package/lib/view/overlay/BackgroundOverlay.d.ts +4 -14
  73. package/lib/view/overlay/BackgroundOverlay.js +12 -1
  74. package/lib/view/overlay/Grid.d.ts +4 -3
  75. package/lib/view/overlay/Grid.js +8 -31
  76. package/lib/view/overlay/getTransformHoc.d.ts +1 -1
  77. package/lib/view/text/BaseText.js +1 -1
  78. package/package.json +1 -1
  79. package/src/LogicFlow.tsx +6 -0
  80. package/src/algorithm/edge.ts +3 -5
  81. package/src/algorithm/outline.ts +1 -1
  82. package/src/constant/index.ts +4 -0
  83. package/src/event/eventArgs.ts +50 -30
  84. package/src/model/GraphModel.ts +122 -3
  85. package/src/model/edge/BaseEdgeModel.ts +1 -0
  86. package/src/model/edge/LineEdgeModel.ts +8 -0
  87. package/src/model/edge/PolylineEdgeModel.ts +5 -3
  88. package/src/model/node/BaseNodeModel.ts +1 -1
  89. package/src/model/node/HtmlNodeModel.ts +1 -1
  90. package/src/style/index.less +5 -0
  91. package/src/style/raw.ts +3 -0
  92. package/src/util/drag.ts +12 -0
  93. package/src/view/Anchor.tsx +7 -8
  94. package/src/view/Control.tsx +1 -1
  95. package/src/view/Graph.tsx +5 -7
  96. package/src/view/behavior/dnd.ts +1 -0
  97. package/src/view/edge/BaseEdge.tsx +24 -3
  98. package/src/view/node/BaseNode.tsx +17 -1
  99. package/src/view/overlay/BackgroundOverlay.tsx +11 -16
  100. package/src/view/overlay/Grid.tsx +13 -9
  101. package/src/view/overlay/OutlineOverlay.tsx +1 -1
  102. package/src/view/text/BaseText.tsx +1 -1
  103. package/stats.html +1 -1
  104. package/dist/index.min.js +0 -2
  105. package/dist/index.min.js.map +0 -1
@@ -262,6 +262,18 @@ var BaseNode = /** @class */ (function (_super) {
262
262
  _this.stepDrag && _this.stepDrag.handleMouseDown(ev);
263
263
  }
264
264
  };
265
+ _this.handleFocus = function () {
266
+ var _a = _this.props, model = _a.model, graphModel = _a.graphModel;
267
+ graphModel.eventCenter.emit(constant_1.EventType.NODE_FOCUS, {
268
+ data: model.getData(),
269
+ });
270
+ };
271
+ _this.handleBlur = function () {
272
+ var _a = _this.props, model = _a.model, graphModel = _a.graphModel;
273
+ graphModel.eventCenter.emit(constant_1.EventType.NODE_BLUR, {
274
+ data: model.getData(),
275
+ });
276
+ };
265
277
  // 因为自定义节点的时候,可能会基于hover状态自定义不同的样式。
266
278
  _this.setHoverOn = function (ev) {
267
279
  var _a = _this.props, model = _a.model, graphModel = _a.graphModel;
@@ -421,7 +433,7 @@ var BaseNode = /** @class */ (function (_super) {
421
433
  if (adjustNodePosition && draggable) {
422
434
  this.stepDrag.setStep(gridSize * SCALE_X);
423
435
  }
424
- nodeShape = ((0, jsx_runtime_1.jsx)("g", __assign({ className: "".concat(this.getStateClassName(), " ").concat(className), onMouseDown: this.handleMouseDown, onMouseUp: this.handleMouseUp, onClick: this.handleClick, onMouseEnter: this.setHoverOn, onMouseOver: this.setHoverOn, onMouseLeave: this.setHoverOff, onMouseOut: this.onMouseOut, onContextMenu: this.handleContextMenu }, restAttributes, { children: nodeShapeInner })));
436
+ nodeShape = ((0, jsx_runtime_1.jsx)("g", __assign({ className: "".concat(this.getStateClassName(), " ").concat(className), onMouseDown: this.handleMouseDown, onMouseUp: this.handleMouseUp, onClick: this.handleClick, onMouseEnter: this.setHoverOn, onMouseOver: this.setHoverOn, onMouseLeave: this.setHoverOff, onMouseOut: this.onMouseOut, onContextMenu: this.handleContextMenu, onFocus: this.handleFocus, onBlur: this.handleBlur }, restAttributes, { children: nodeShapeInner })));
425
437
  }
426
438
  return nodeShape;
427
439
  };
@@ -1,26 +1,16 @@
1
1
  import { Component } from 'preact/compat';
2
+ import { Options as LFOptions } from '../../options';
2
3
  /**
3
4
  * 背景配置, 支持css属性配置
4
5
  * https://developer.mozilla.org/zh-CN/docs/Web/CSS/background
5
6
  * @example
6
7
  * {
7
- * backgroundImage: "url('./img/grid.svg')",
8
- backgroundRepeat: 'repeat',
8
+ * backgroundImage: "url('./img/grid.svg')",
9
+ backgroundRepeat: 'repeat',
9
10
  * }
10
11
  */
11
- export type BackgroundConfig = {
12
- /**
13
- * 背景图片地址
14
- */
15
- backgroundImage?: string;
16
- /**
17
- * 是否重复
18
- */
19
- backgroundRepeat?: string;
20
- [key: string]: any;
21
- };
22
12
  type IProps = {
23
- background: BackgroundConfig;
13
+ background: boolean | LFOptions.BackgroundConfig;
24
14
  };
25
15
  export declare class BackgroundOverlay extends Component<IProps> {
26
16
  render(): import("preact/compat").JSX.Element;
@@ -14,10 +14,18 @@ var __extends = (this && this.__extends) || (function () {
14
14
  d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
15
  };
16
16
  })();
17
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
18
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
19
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
20
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
21
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
22
+ };
17
23
  Object.defineProperty(exports, "__esModule", { value: true });
18
24
  exports.BackgroundOverlay = void 0;
19
25
  var jsx_runtime_1 = require("preact/jsx-runtime");
20
26
  var compat_1 = require("preact/compat");
27
+ var lodash_es_1 = require("lodash-es");
28
+ var __1 = require("../..");
21
29
  var BackgroundOverlay = /** @class */ (function (_super) {
22
30
  __extends(BackgroundOverlay, _super);
23
31
  function BackgroundOverlay() {
@@ -25,8 +33,11 @@ var BackgroundOverlay = /** @class */ (function (_super) {
25
33
  }
26
34
  BackgroundOverlay.prototype.render = function () {
27
35
  var background = this.props.background;
28
- return ((0, jsx_runtime_1.jsx)("div", { className: "lf-background", children: (0, jsx_runtime_1.jsx)("div", { style: background, className: "lf-background-area" }) }));
36
+ return ((0, jsx_runtime_1.jsx)("div", { className: "lf-background", children: (0, jsx_runtime_1.jsx)("div", { style: (0, lodash_es_1.isObject)(background) ? background : {}, className: "lf-background-area" }) }));
29
37
  };
38
+ BackgroundOverlay = __decorate([
39
+ __1.observer
40
+ ], BackgroundOverlay);
30
41
  return BackgroundOverlay;
31
42
  }(compat_1.Component));
32
43
  exports.BackgroundOverlay = BackgroundOverlay;
@@ -1,11 +1,12 @@
1
1
  import { Component } from 'preact/compat';
2
2
  import { GraphModel } from '../../model';
3
- import GridOptions = Grid.GridOptions;
4
- type IProps = GridOptions & {
3
+ type IProps = {
5
4
  graphModel: GraphModel;
6
5
  };
7
6
  export declare class Grid extends Component<IProps> {
7
+ gridOptions: Grid.GridOptions;
8
8
  readonly id: string;
9
+ constructor(props: IProps);
9
10
  renderDot(): import("preact/compat").JSX.Element;
10
11
  renderMesh(): import("preact/compat").JSX.Element;
11
12
  render(): import("preact/compat").JSX.Element;
@@ -30,7 +31,7 @@ export declare namespace Grid {
30
31
  /**
31
32
  * 网格的颜色
32
33
  */
33
- color: string;
34
+ color?: string;
34
35
  /**
35
36
  * 网格的宽度
36
37
  * - 对于 `dot` 点状网格,表示点的大小
@@ -20,31 +20,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
20
20
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
21
21
  return c > 3 && r && Object.defineProperty(target, key, r), r;
22
22
  };
23
- var __read = (this && this.__read) || function (o, n) {
24
- var m = typeof Symbol === "function" && o[Symbol.iterator];
25
- if (!m) return o;
26
- var i = m.call(o), r, ar = [], e;
27
- try {
28
- while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
29
- }
30
- catch (error) { e = { error: error }; }
31
- finally {
32
- try {
33
- if (r && !r.done && (m = i["return"])) m.call(i);
34
- }
35
- finally { if (e) throw e.error; }
36
- }
37
- return ar;
38
- };
39
- var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
40
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
41
- if (ar || !(i in from)) {
42
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
43
- ar[i] = from[i];
44
- }
45
- }
46
- return to.concat(ar || Array.prototype.slice.call(from));
47
- };
48
23
  Object.defineProperty(exports, "__esModule", { value: true });
49
24
  exports.Grid = void 0;
50
25
  var jsx_runtime_1 = require("preact/jsx-runtime");
@@ -55,14 +30,15 @@ var util_1 = require("../../util");
55
30
  var constant_1 = require("../../constant");
56
31
  var Grid = /** @class */ (function (_super) {
57
32
  __extends(Grid, _super);
58
- function Grid() {
59
- var _this = _super.apply(this, __spreadArray([], __read(arguments), false)) || this;
33
+ function Grid(props) {
34
+ var _this = _super.call(this, props) || this;
60
35
  _this.id = (0, util_1.createUuid)();
36
+ _this.gridOptions = _this.props.graphModel.grid;
61
37
  return _this;
62
38
  }
63
39
  // 网格类型为点状
64
40
  Grid.prototype.renderDot = function () {
65
- var _a = this.props, config = _a.config, _b = _a.size, size = _b === void 0 ? 1 : _b, visible = _a.visible;
41
+ var _a = this.gridOptions, config = _a.config, _b = _a.size, size = _b === void 0 ? 1 : _b, visible = _a.visible;
66
42
  var _c = config !== null && config !== void 0 ? config : {}, color = _c.color, _d = _c.thickness, thickness = _d === void 0 ? 2 : _d;
67
43
  // 对于点状网格,点的半径不能大于网格大小的四分之一
68
44
  var radius = Math.min(Math.max(2, thickness), size / 4);
@@ -72,16 +48,17 @@ var Grid = /** @class */ (function (_super) {
72
48
  // 网格类型为交叉线
73
49
  // todo: 采用背景缩放的方式,实现更好的体验
74
50
  Grid.prototype.renderMesh = function () {
75
- var _a = this.props, config = _a.config, _b = _a.size, size = _b === void 0 ? 1 : _b, visible = _a.visible;
51
+ var _a = this.gridOptions, config = _a.config, _b = _a.size, size = _b === void 0 ? 1 : _b, visible = _a.visible;
76
52
  var _c = config !== null && config !== void 0 ? config : {}, color = _c.color, _d = _c.thickness, thickness = _d === void 0 ? 1 : _d;
77
53
  // 对于交叉线网格,线的宽度不能大于网格大小的一半
78
54
  var strokeWidth = Math.min(Math.max(1, thickness), size / 2);
79
55
  var d = "M 0 0 H ".concat(size, " V ").concat(size, " H 0 Z");
80
56
  var opacity = visible ? 1 : 0;
81
- return ((0, jsx_runtime_1.jsx)("path", { d: d, stroke: color, strokeWidth: strokeWidth, opacity: opacity, fill: "transparent" }));
57
+ return ((0, jsx_runtime_1.jsx)("path", { d: d, stroke: color, strokeWidth: strokeWidth / 2, opacity: opacity, fill: "transparent" }));
82
58
  };
83
59
  Grid.prototype.render = function () {
84
- var _a = this.props, type = _a.type, _b = _a.size, size = _b === void 0 ? 1 : _b, transformModel = _a.graphModel.transformModel;
60
+ var transformModel = this.props.graphModel.transformModel;
61
+ var _a = this.gridOptions, type = _a.type, _b = _a.size, size = _b === void 0 ? 1 : _b;
85
62
  var SCALE_X = transformModel.SCALE_X, SKEW_Y = transformModel.SKEW_Y, SKEW_X = transformModel.SKEW_X, SCALE_Y = transformModel.SCALE_Y, TRANSLATE_X = transformModel.TRANSLATE_X, TRANSLATE_Y = transformModel.TRANSLATE_Y;
86
63
  var matrixString = [
87
64
  SCALE_X,
@@ -25,7 +25,7 @@ export declare function getTransform<P>(WrappedComponent: ComponentType<P>): {
25
25
  props: import("preact").RenderableProps<IProps & P, any>;
26
26
  context: any;
27
27
  base?: Element | Text | undefined;
28
- setState<K extends never>(state: Partial<{}> | ((prevState: Readonly<{}>, props: Readonly<IProps & P>) => Partial<{}> | Pick<{}, K> | null) | Pick<{}, K> | null, callback?: (() => void) | undefined): void;
28
+ setState<K extends never>(state: ((prevState: Readonly<{}>, props: Readonly<IProps & P>) => Pick<{}, K> | Partial<{}> | null) | Pick<{}, K> | Partial<{}> | null, callback?: (() => void) | undefined): void;
29
29
  forceUpdate(callback?: (() => void) | undefined): void;
30
30
  };
31
31
  displayName?: string | undefined;
@@ -67,7 +67,7 @@ var BaseText = /** @class */ (function (_super) {
67
67
  _this.onDragging = function (_a) {
68
68
  var deltaX = _a.deltaX, deltaY = _a.deltaY;
69
69
  var _b = _this.props, model = _b.model, transformModel = _b.graphModel.transformModel;
70
- if (deltaX && deltaY) {
70
+ if (deltaX || deltaY) {
71
71
  var _c = __read(transformModel.fixDeltaXY(deltaX, deltaY), 2), curDeltaX = _c[0], curDeltaY = _c[1];
72
72
  model.moveText(curDeltaX, curDeltaY);
73
73
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logicflow/core",
3
- "version": "2.0.6",
3
+ "version": "2.0.8",
4
4
  "description": "LogicFlow, help you quickly create flowcharts",
5
5
  "main": "lib/index.js",
6
6
  "module": "es/index.js",
package/src/LogicFlow.tsx CHANGED
@@ -1369,6 +1369,11 @@ export class LogicFlow {
1369
1369
  this.components.push(extensionIns.render.bind(extensionIns))
1370
1370
  this.extension[pluginName] = extensionIns
1371
1371
  }
1372
+
1373
+ /** 销毁当前实例 */
1374
+ destroy() {
1375
+ this.graphModel.destroy()
1376
+ }
1372
1377
  }
1373
1378
 
1374
1379
  // Option
@@ -1451,6 +1456,7 @@ export namespace LogicFlow {
1451
1456
  // label数据类型声明
1452
1457
  export type LabelConfig = {
1453
1458
  id?: string // label唯一标识
1459
+ type?: string
1454
1460
  x: number
1455
1461
  y: number
1456
1462
  content?: string // 富文本内容
@@ -60,10 +60,8 @@ export const isInSegment = (point: Point, start: Point, end: Point) => {
60
60
  const k = (endY - startY) / (endX - startX)
61
61
  const b = startY - k * startX
62
62
  return (
63
- x >= startX &&
64
- x <= endX &&
65
- y >= startY &&
66
- y <= endY &&
67
- Math.abs(y - k * x + b) < Number.EPSILON
63
+ ((x >= startX && x <= endX) || (x <= startX && x >= endX)) &&
64
+ ((y >= startY && y <= endY) || (y <= startY && y >= endY)) &&
65
+ Math.abs(y - k * x - b) < Number.EPSILON
68
66
  )
69
67
  }
@@ -66,7 +66,7 @@ export const getEdgeOutline = (
66
66
  edge: BaseEdgeModel,
67
67
  ): OutlineInfo | undefined => {
68
68
  if (edge.modelType === ModelType.LINE_EDGE) {
69
- return getLineOutline(edge)
69
+ return getLineOutline(edge as LineEdgeModel)
70
70
  }
71
71
  if (edge.modelType === ModelType.POLYLINE_EDGE) {
72
72
  return getPolylineOutline(edge as PolylineEdgeModel)
@@ -57,6 +57,8 @@ export enum EventType {
57
57
  NODE_CONTEXTMENU = 'node:contextmenu',
58
58
  NODE_ROTATE = 'node:rotate',
59
59
  NODE_RESIZE = 'node:resize',
60
+ NODE_FOCUS = 'node:focus',
61
+ NODE_BLUR = 'node:blur',
60
62
 
61
63
  // 节点 properties 变化事件
62
64
  NODE_PROPERTIES_CHANGE = 'node:properties-change',
@@ -67,6 +69,8 @@ export enum EventType {
67
69
  EDGE_DELETE = 'edge:delete',
68
70
  EDGE_CLICK = 'edge:click',
69
71
  EDGE_DBCLICK = 'edge:dbclick',
72
+ EDGE_FOCUS = 'edge:focus',
73
+ EDGE_BLUR = 'edge:blur',
70
74
 
71
75
  EDGE_MOUSEENTER = 'edge:mouseenter',
72
76
  EDGE_MOUSELEAVE = 'edge:mouseleave',
@@ -132,7 +132,7 @@ interface NodeEventArgs {
132
132
  /**
133
133
  * 删除节点
134
134
  */
135
- 'node:delete': NodeEventArgsPick<'data'>
135
+ 'node:delete': NodeEventArgsPick<'data' | 'model'>
136
136
  /**
137
137
  * 添加外部拖入节点
138
138
  */
@@ -140,7 +140,7 @@ interface NodeEventArgs {
140
140
  /**
141
141
  * 拖拽外部拖入节点
142
142
  */
143
- 'node:dnd-drag': NodeEventArgsPick<'data'>
143
+ 'node:dnd-drag': NodeEventArgsPick<'data' | 'e'>
144
144
  /**
145
145
  * 开始拖拽节点
146
146
  */
@@ -167,6 +167,35 @@ interface NodeEventArgs {
167
167
  'node:resize': NodeEventArgsPick<
168
168
  'preData' | 'data' | 'model' | 'deltaX' | 'deltaY' | 'index'
169
169
  >
170
+ /**
171
+ * 元素的 properties 发生改变
172
+ */
173
+ 'node:properties-change': {
174
+ /**
175
+ * 元素的 id
176
+ */
177
+ id: string
178
+ /**
179
+ * 改变的 properties 的 key
180
+ */
181
+ keys: string[]
182
+ /**
183
+ * 改变前的 properties
184
+ */
185
+ preProperties: Record<string, any>
186
+ /**
187
+ * 改变后的 properties
188
+ */
189
+ properties: Record<string, any>
190
+ }
191
+ /**
192
+ * 节点获焦
193
+ */
194
+ 'node:focus': NodeEventArgsPick<'data'>
195
+ /**
196
+ * 节点失焦
197
+ */
198
+ 'node:blur': NodeEventArgsPick<'data'>
170
199
  }
171
200
 
172
201
  type EdgeEventArgsPick<T extends 'data' | 'e' | 'position'> = Pick<
@@ -238,6 +267,14 @@ interface EdgeEventArgs {
238
267
  oldEdge: EdgeData
239
268
  }
240
269
  }
270
+ /**
271
+ * 边获焦
272
+ */
273
+ 'edge:focus': EdgeEventArgsPick<'data'>
274
+ /**
275
+ * 边失焦
276
+ */
277
+ 'edge:blur': EdgeEventArgsPick<'data'>
241
278
  }
242
279
 
243
280
  /**
@@ -356,33 +393,6 @@ interface CommonEventArgs {
356
393
  */
357
394
  position: ClientPosition
358
395
  }
359
- /**
360
- * 元素的 properties 发生改变
361
- */
362
- 'properties:change': {
363
- data: {
364
- /**
365
- * 元素的 id
366
- */
367
- id: string
368
- /**
369
- * 元素的类型
370
- */
371
- type: string
372
- /**
373
- * 改变的 properties 的 key
374
- */
375
- keys: string[]
376
- /**
377
- * 改变前的 properties
378
- */
379
- preProperties: Record<string, any>
380
- /**
381
- * 改变后的 properties
382
- */
383
- properties: Record<string, any>
384
- }
385
- }
386
396
  /**
387
397
  * 进行画布平移或缩放等变化操作时触发
388
398
  */
@@ -420,6 +430,16 @@ interface CommonEventArgs {
420
430
  */
421
431
  data: GraphData
422
432
  }
433
+ /**
434
+ * 画布容器大小发生变化触发,为了性能考虑对事件做了防抖处理,间隔为16ms
435
+ */
436
+ 'graph:resize': {
437
+ /**
438
+ * 更新后的画布数据
439
+ */
440
+ target: HTMLElement
441
+ contentRect: DOMRectReadOnly
442
+ }
423
443
  }
424
444
 
425
445
  type AnchorEventArgsPick<T extends 'data' | 'e' | 'nodeModel' | 'edgeModel'> =
@@ -440,7 +460,7 @@ type AnchorEventArgsPick<T extends 'data' | 'e' | 'nodeModel' | 'edgeModel'> =
440
460
  /**
441
461
  * 通过拖动锚点连线添加的边的数据
442
462
  */
443
- edgeModel: BaseEdgeModel
463
+ edgeModel?: BaseEdgeModel
444
464
  },
445
465
  T
446
466
  >
@@ -1,4 +1,4 @@
1
- import { find, forEach, map } 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,
@@ -36,10 +36,12 @@ import {
36
36
  updateTheme,
37
37
  } from '../util'
38
38
  import EventEmitter from '../event/eventEmitter'
39
+ import { Grid } from '../view/overlay'
39
40
  import Position = LogicFlow.Position
40
41
  import PointTuple = LogicFlow.PointTuple
41
42
  import GraphData = LogicFlow.GraphData
42
43
  import NodeConfig = LogicFlow.NodeConfig
44
+ import AnchorConfig = Model.AnchorConfig
43
45
  import BaseNodeModelCtor = LogicFlow.BaseNodeModelCtor
44
46
  import BaseEdgeModelCtor = LogicFlow.BaseEdgeModelCtor
45
47
 
@@ -55,6 +57,8 @@ export class GraphModel {
55
57
 
56
58
  // 流程图主题配置
57
59
  theme: LogicFlow.Theme
60
+ // 网格配置
61
+ @observable grid: Grid.GridOptions
58
62
  // 事件中心
59
63
  readonly eventCenter: EventEmitter
60
64
  // 维护所有节点和边类型对应的 model
@@ -124,6 +128,8 @@ export class GraphModel {
124
128
  // 用户自定义属性
125
129
  [propName: string]: any
126
130
 
131
+ private waitCleanEffects: (() => void)[] = []
132
+
127
133
  constructor(options: LFOptions.Common) {
128
134
  const {
129
135
  container,
@@ -142,6 +148,7 @@ export class GraphModel {
142
148
  this.gridSize = grid.size || 1 // 默认 gridSize 设置为 1
143
149
  }
144
150
  this.theme = setupTheme(options.style)
151
+ this.grid = Grid.getGridOptions(grid ?? false)
145
152
  this.edgeType = options.edgeType || 'polyline'
146
153
  this.animation = setupAnimation(animation)
147
154
  this.overlapMode = options.overlapMode || OverlapMode.DEFAULT
@@ -149,6 +156,27 @@ export class GraphModel {
149
156
  this.width = options.width || this.rootEl.getBoundingClientRect().width
150
157
  this.height = options.height || this.rootEl.getBoundingClientRect().height
151
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
+
152
180
  this.eventCenter = new EventEmitter()
153
181
  this.editConfigModel = new EditConfigModel(options)
154
182
  this.transformModel = new TransformModel(this.eventCenter, options)
@@ -435,6 +463,58 @@ export class GraphModel {
435
463
  throw new Error(`找不到${edge.type}对应的边。`)
436
464
  }
437
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
+ }
438
518
  this.edgeModelMap.set(edgeModel.id, edgeModel)
439
519
  this.elementsModelMap.set(edgeModel.id, edgeModel)
440
520
 
@@ -745,11 +825,15 @@ export class GraphModel {
745
825
  */
746
826
  @action
747
827
  deleteNode(nodeId: string) {
748
- const nodeData = this.nodesMap[nodeId].model.getData()
828
+ const nodeModel = this.nodesMap[nodeId].model
829
+ const nodeData = nodeModel.getData()
749
830
  this.deleteEdgeBySource(nodeId)
750
831
  this.deleteEdgeByTarget(nodeId)
751
832
  this.nodes.splice(this.nodesMap[nodeId].index, 1)
752
- this.eventCenter.emit(EventType.NODE_DELETE, { data: nodeData })
833
+ this.eventCenter.emit(EventType.NODE_DELETE, {
834
+ data: nodeData,
835
+ model: nodeModel,
836
+ })
753
837
  }
754
838
 
755
839
  /**
@@ -1407,6 +1491,29 @@ export class GraphModel {
1407
1491
  this.theme = updateTheme({ ...this.theme, ...style })
1408
1492
  }
1409
1493
 
1494
+ /**
1495
+ * 更新网格配置
1496
+ */
1497
+ updateGridOptions(options: Partial<Grid.GridOptions>) {
1498
+ merge(this.grid, options)
1499
+ }
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
+
1410
1517
  /**
1411
1518
  * 重新设置画布的宽高
1412
1519
  */
@@ -1562,6 +1669,18 @@ export class GraphModel {
1562
1669
  @action setPartial(partial: boolean): void {
1563
1670
  this.partial = partial
1564
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
+ }
1565
1684
  }
1566
1685
 
1567
1686
  export namespace GraphModel {
@@ -87,6 +87,7 @@ export class BaseEdgeModel<P extends PropertiesType = PropertiesType>
87
87
  // 边特有属性,动画及调整点
88
88
  @observable isAnimation = false
89
89
  @observable isShowAdjustPoint = false // 是否显示边两端的调整点
90
+ isDragging?: boolean
90
91
  // 引用属性
91
92
  graphModel: GraphModel
92
93
  @observable zIndex: number = 0
@@ -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
  }
@@ -835,7 +835,7 @@ export class BaseNodeModel<P extends PropertiesType = PropertiesType>
835
835
  this.properties = nextProperties
836
836
  this.setAttributes()
837
837
 
838
- // 触发更新节点 properties:change 的事件
838
+ // 触发更新节点 node:properties-change 的事件
839
839
  this.graphModel.eventCenter.emit(EventType.NODE_PROPERTIES_CHANGE, {
840
840
  id: this.id,
841
841
  keys: updateKeys,
@@ -6,7 +6,7 @@ import AnchorConfig = Model.AnchorConfig
6
6
  import LogicFlow from '../../LogicFlow'
7
7
  import GraphModel from '../GraphModel'
8
8
 
9
- export type IHtmlNodeProperties = {
9
+ export interface IHtmlNodeProperties {
10
10
  width?: number
11
11
  height?: number
12
12
  style?: LogicFlow.CommonTheme