@foblex/flow 12.6.9 → 12.7.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.
Files changed (20) hide show
  1. package/README.md +23 -18
  2. package/bundles/foblex-flow.umd.js +96 -58
  3. package/bundles/foblex-flow.umd.js.map +1 -1
  4. package/esm2015/f-canvas/f-canvas.component.js +12 -5
  5. package/esm2015/f-connection/common/f-connection-text/f-connection-text-path.directive.js +2 -2
  6. package/esm2015/f-draggable/connections/reassign-connection/f-reassign-connection.event.js +3 -2
  7. package/esm2015/f-draggable/connections/reassign-connection/reassign-connection-finalize/reassign-connection-finalize.execution.js +3 -3
  8. package/esm2015/f-draggable/node/connection-base-drag-handler.js +14 -3
  9. package/esm2015/f-draggable/node/create-move-nodes-drag-model-from-selection/create-move-nodes-drag-model-from-selection.execution.js +8 -4
  10. package/esm2015/f-draggable/node/create-move-nodes-drag-model-from-selection/create-move-nodes-drag-model-from-selection.request.js +4 -1
  11. package/esm2015/f-draggable/node/node-move-preparation/node-move-preparation.execution.js +17 -7
  12. package/esm2015/f-draggable/single-select/single-select.execution.js +4 -1
  13. package/esm2015/f-zoom/f-zoom-base.js +39 -39
  14. package/f-canvas/f-canvas.component.d.ts +1 -0
  15. package/f-draggable/connections/reassign-connection/f-reassign-connection.event.d.ts +3 -1
  16. package/f-draggable/node/connection-base-drag-handler.d.ts +1 -0
  17. package/f-draggable/node/create-move-nodes-drag-model-from-selection/create-move-nodes-drag-model-from-selection.request.d.ts +3 -0
  18. package/fesm2015/foblex-flow.js +96 -57
  19. package/fesm2015/foblex-flow.js.map +1 -1
  20. package/package.json +2 -2
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <p align="center">
2
- <a href="https://flow.foblex.com">
3
- <img style="margin: auto" src="https://github.com/user-attachments/assets/0557914d-a43d-43c1-8346-760d3627da14" alt="Foblex Flow Logo"/>
2
+ <a href="https://flow.foblex.com/">
3
+ <img style="margin: auto" src="https://github.com/user-attachments/assets/ee1d39f6-0a89-4cb9-8dee-1652aba82e69" alt="Foblex Flow Logo"/>
4
4
  </a>
5
5
  </p>
6
6
 
@@ -15,40 +15,45 @@
15
15
 
16
16
  ## Welcome to Foblex Flow
17
17
 
18
- Foblex Flow is an [Angular](https://angular.dev/) library designed to simplify the creation and manipulation of
19
- dynamic flows. It provides components for flows, nodes, and connections, automating node
20
- manipulation and inter-node connections.
18
+ Foblex Flow is an [Angular](https://angular.dev/) library built to simplify the creation and management of dynamic, interactive flows.
19
+ Whether you're developing complex systems or lightweight visualizations, Foblex Flow provides a robust set of tools to help automate node manipulation and inter-node connections with ease. It's fully compatible with Angular 12+, Server-Side Rendering (SSR), and the Composition API.
21
20
 
22
21
  ### Examples
23
22
 
24
- - [Call Center](https://github.com/Foblex/f-flow-example) - A simple example of a call center flow.
23
+ Explore practical use cases to see Foblex Flow in action:
25
24
 
26
- - [Scheme Editor](https://github.com/Foblex/f-scheme-editor) - A more complex example of a scheme editor.
25
+ - [Call Center](https://github.com/Foblex/f-flow-example) - A streamlined flow example simulating a call flow.
26
+
27
+ - [Scheme Editor](https://github.com/Foblex/f-scheme-editor) - A more advanced example of a fully interactive scheme editor.
28
+
29
+ - [Visual Programming](https://flow.foblex.com/examples/f-visual-programming-flow/) - An example of a visual programming flow.
30
+
31
+ - [DB Management](https://flow.foblex.com/examples/f-db-management-flow/) - An example of a database management flow.
27
32
 
28
33
  ### Features
29
34
 
30
- 1. Node and Connection creation and manipulation.
31
- 2. Connection and Node events.
32
- 3. Reassigning Nodes and Connections.
33
- 4. Customizable Node and Connection templates.
34
- 5. Drag-and-drop support.
35
- 6. Zoom and pan support.
35
+ 1. **Node and Connection Creation:** Dynamically generate and manipulate nodes and their connections.
36
+ 2. **Event-Driven Architecture:** Built-in events for nodes and connections to allow seamless interaction handling.
37
+ 3. **Reassign Connections:** Easily reassign connections between nodes, allowing for flexible flow adjustments.
38
+ 4. **Custom Templates:** Fully customizable node and connection templates for tailored visual representation.
39
+ 5. **Drag-and-Drop:** Simplified drag-and-drop functionality for intuitive flow manipulation.
40
+ 6. **Zoom and Pan Support:** Explore large flows with smooth zooming and panning controls.
36
41
 
37
42
  ### Getting Started and Documentation
38
43
 
39
- Visit our [Documentation](https://flow.foblex.com/docs/get-started) to learn how to install and use the library in your Angular project.
44
+ For a comprehensive guide on how to install, configure, and use Foblex Flow in your Angular project, visit our [Documentation](https://flow.foblex.com/docs/get-started).
40
45
 
41
46
  ### Installation
42
47
 
43
- To add Foblex Flow to your project, run the following command:
48
+ To add Foblex Flow to your project, use the following npm command:
44
49
 
45
50
  ```bash
46
51
  npm install @foblex/flow
47
52
  ```
48
53
 
49
- ### Usage
54
+ ### Usage Example
50
55
 
51
- Example:
56
+ Here’s a simple example of how you can use Foblex Flow to create draggable nodes and connections:
52
57
 
53
58
  ```html
54
59
 
@@ -61,7 +66,7 @@ Example:
61
66
  </f-flow>
62
67
  ```
63
68
 
64
- ### Support and Community
69
+ ### Community and Support
65
70
 
66
71
  For questions, feedback, and support, visit the [Foblex Portal](https://flow.foblex.com) to connect with the community and the development team.
67
72
  You can also report [issues](https://github.com/Foblex/flow/issues) and request [features](https://github.com/Foblex/flow/discussions) on the [GitHub repository](https://github.com/Foblex/flow).
@@ -3127,11 +3127,12 @@
3127
3127
  }());
3128
3128
 
3129
3129
  var FReassignConnectionEvent = /** @class */ (function () {
3130
- function FReassignConnectionEvent(fConnectionId, fOutputId, oldFInputId, newFInputId) {
3130
+ function FReassignConnectionEvent(fConnectionId, fOutputId, oldFInputId, newFInputId, fDropPosition) {
3131
3131
  this.fConnectionId = fConnectionId;
3132
3132
  this.fOutputId = fOutputId;
3133
3133
  this.oldFInputId = oldFInputId;
3134
3134
  this.newFInputId = newFInputId;
3135
+ this.fDropPosition = fDropPosition;
3135
3136
  }
3136
3137
  return FReassignConnectionEvent;
3137
3138
  }());
@@ -3162,10 +3163,10 @@
3162
3163
  };
3163
3164
  ReassignConnectionFinalizeExecution.prototype.emitEvent = function (event) {
3164
3165
  var input = this.getInputUnderPointer(event);
3165
- if (!input || !this.isReassignToDifferentInput(input)) {
3166
+ if (!!input && !this.isReassignToDifferentInput(input)) {
3166
3167
  return;
3167
3168
  }
3168
- this.fDraggable.fReassignConnection.emit(new FReassignConnectionEvent(this.dragHandler.fConnection.fId, this.dragHandler.fConnection.fOutputId, this.dragHandler.fConnection.fInputId, input.id));
3169
+ this.fDraggable.fReassignConnection.emit(new FReassignConnectionEvent(this.dragHandler.fConnection.fId, this.dragHandler.fConnection.fOutputId, this.dragHandler.fConnection.fInputId, input === null || input === void 0 ? void 0 : input.id, event.getPosition()));
3169
3170
  };
3170
3171
  ReassignConnectionFinalizeExecution.prototype.getInputUnderPointer = function (event) {
3171
3172
  return this.fMediator.send(new GetInputUnderPointerRequest(event, this.dragHandler));
@@ -3604,7 +3605,7 @@
3604
3605
  FConnectionTextPathDirective.prototype.getSymbolWidth = function (name) {
3605
3606
  var text = name || 'connection';
3606
3607
  var _a = this.getFontStyles(this.hostElement), fontFamily = _a.fontFamily, fontSize = _a.fontSize;
3607
- this.fontSize = fontSize;
3608
+ this.fontSize = fontSize || '12px';
3608
3609
  var canvas = this.fBrowser.document.createElement('canvas');
3609
3610
  var context;
3610
3611
  try {
@@ -5048,11 +5049,22 @@
5048
5049
  };
5049
5050
  ConnectionBaseDragHandler.prototype.getOutput = function () {
5050
5051
  var _this = this;
5051
- return this.fComponentsStore.fOutputs.find(function (x) { return x.id === _this.connection.fOutputId; });
5052
+ var result = this.fComponentsStore.fOutputs.find(function (x) { return x.id === _this.connection.fOutputId; });
5053
+ if (!result) {
5054
+ throw new Error(this.connectorNotFoundPrefix("fOutput with id " + this.connection.fOutputId + " not found"));
5055
+ }
5056
+ return result;
5052
5057
  };
5053
5058
  ConnectionBaseDragHandler.prototype.getInput = function () {
5054
5059
  var _this = this;
5055
- return this.fComponentsStore.fInputs.find(function (x) { return x.id === _this.connection.fInputId; });
5060
+ var result = this.fComponentsStore.fInputs.find(function (x) { return x.id === _this.connection.fInputId; });
5061
+ if (!result) {
5062
+ throw new Error(this.connectorNotFoundPrefix("fInput with id " + this.connection.fInputId + " not found"));
5063
+ }
5064
+ return result;
5065
+ };
5066
+ ConnectionBaseDragHandler.prototype.connectorNotFoundPrefix = function (message) {
5067
+ return "ConnectionDragHandler Error: Connection From (fOutput)" + this.connection.fOutputId + " To (fInput)" + this.connection.fInputId + ". " + message + ". Please ensure that all f-connections are associated with existing connectors";
5056
5068
  };
5057
5069
  ConnectionBaseDragHandler.prototype.getDifference = function (difference, restrictions) {
5058
5070
  return {
@@ -5312,7 +5324,8 @@
5312
5324
  };
5313
5325
 
5314
5326
  var CreateMoveNodesDragModelFromSelectionRequest = /** @class */ (function () {
5315
- function CreateMoveNodesDragModelFromSelectionRequest() {
5327
+ function CreateMoveNodesDragModelFromSelectionRequest(nodeWithDisabledSelection) {
5328
+ this.nodeWithDisabledSelection = nodeWithDisabledSelection;
5316
5329
  }
5317
5330
  return CreateMoveNodesDragModelFromSelectionRequest;
5318
5331
  }());
@@ -5371,14 +5384,18 @@
5371
5384
  this.fMediator = fMediator;
5372
5385
  }
5373
5386
  CreateMoveNodesDragModelFromSelectionExecution.prototype.handle = function (request) {
5374
- var itemsToDrag = this.getNodesWithRestrictions(this.getSelectedNodes());
5387
+ var itemsToDrag = this.getNodesWithRestrictions(this.getSelectedNodes(request.nodeWithDisabledSelection));
5375
5388
  return this.getDragHandlersWithConnections(this.getDragHandlersFromNodes(itemsToDrag), this.getAllOutputIds(itemsToDrag), this.getAllInputIds(itemsToDrag));
5376
5389
  };
5377
- CreateMoveNodesDragModelFromSelectionExecution.prototype.getSelectedNodes = function () {
5390
+ CreateMoveNodesDragModelFromSelectionExecution.prototype.getSelectedNodes = function (nodeWithDisabledSelection) {
5378
5391
  var _this = this;
5379
- return this.fDraggableDataContext.selectedItems
5392
+ var result = this.fDraggableDataContext.selectedItems
5380
5393
  .map(function (x) { return _this.fComponentsStore.findNode(x.hostElement); })
5381
5394
  .filter(function (x) { return !!x; });
5395
+ if (nodeWithDisabledSelection) {
5396
+ result.push(nodeWithDisabledSelection);
5397
+ }
5398
+ return result;
5382
5399
  };
5383
5400
  CreateMoveNodesDragModelFromSelectionExecution.prototype.getNodesWithRestrictions = function (selectedNodes) {
5384
5401
  var _this = this;
@@ -5474,22 +5491,32 @@
5474
5491
  configurable: true
5475
5492
  });
5476
5493
  NodeMovePreparationExecution.prototype.handle = function (request) {
5477
- this.selectAndUpdateNodeLayer(request.event.targetElement);
5478
- var itemsToDrag = this.createDragModelFromSelection();
5494
+ var node = this.getNode(request.event.targetElement);
5495
+ if (!node) {
5496
+ throw new Error('Node not found');
5497
+ }
5498
+ var itemsToDrag = [];
5499
+ if (!node.fSelectionDisabled) {
5500
+ this.selectAndUpdateNodeLayer(node);
5501
+ itemsToDrag = this.createDragModelFromSelection();
5502
+ }
5503
+ else {
5504
+ itemsToDrag = this.createDragModelFromSelection(node);
5505
+ }
5479
5506
  this.initializeLineAlignment(this.filterNodesFromDraggableItems(itemsToDrag));
5480
5507
  this.fDraggableDataContext.onPointerDownScale = this.transform.scale;
5481
5508
  this.fDraggableDataContext.onPointerDownPosition = _2d.Point.fromPoint(request.event.getPosition())
5482
5509
  .elementTransform(this.flowHost).div(this.transform.scale);
5483
5510
  this.fDraggableDataContext.draggableItems = itemsToDrag;
5484
5511
  };
5485
- NodeMovePreparationExecution.prototype.selectAndUpdateNodeLayer = function (targetElement) {
5486
- this.fMediator.send(new SelectAndUpdateNodeLayerRequest(this.getNode(targetElement)));
5512
+ NodeMovePreparationExecution.prototype.selectAndUpdateNodeLayer = function (node) {
5513
+ this.fMediator.send(new SelectAndUpdateNodeLayerRequest(node));
5487
5514
  };
5488
5515
  NodeMovePreparationExecution.prototype.getNode = function (targetElement) {
5489
5516
  return this.fComponentsStore.findNode(targetElement);
5490
5517
  };
5491
- NodeMovePreparationExecution.prototype.createDragModelFromSelection = function () {
5492
- return this.fMediator.send(new CreateMoveNodesDragModelFromSelectionRequest());
5518
+ NodeMovePreparationExecution.prototype.createDragModelFromSelection = function (nodeWithDisabledSelection) {
5519
+ return this.fMediator.send(new CreateMoveNodesDragModelFromSelectionRequest(nodeWithDisabledSelection));
5493
5520
  };
5494
5521
  NodeMovePreparationExecution.prototype.initializeLineAlignment = function (nodesToDrag) {
5495
5522
  var _a;
@@ -6133,6 +6160,9 @@
6133
6160
  this.clearSelection();
6134
6161
  this.selectItem(item);
6135
6162
  }
6163
+ else if (item.fSelectionDisabled) {
6164
+ this.clearSelection();
6165
+ }
6136
6166
  }
6137
6167
  else {
6138
6168
  this.clearSelection();
@@ -8679,11 +8709,18 @@
8679
8709
  FCanvasComponent.prototype.redrawWithAnimation = function () {
8680
8710
  var _this = this;
8681
8711
  var _a;
8712
+ var duration = F_CANVAS_ANIMATION_DURATION;
8713
+ if (this.isMobile()) {
8714
+ duration = 80;
8715
+ }
8682
8716
  (_a = this.fComponentsStore.fBackground) === null || _a === void 0 ? void 0 : _a.setTransform(this.transform);
8683
- this.hostElement.setAttribute("style", "transition: transform " + F_CANVAS_ANIMATION_DURATION + "ms ease-in-out; transform: " + _2d.TransformModelExtensions.toString(this.transform));
8684
- setTimeout(function () {
8685
- _this.redraw();
8686
- }, F_CANVAS_ANIMATION_DURATION);
8717
+ this.hostElement.setAttribute("style", "transition: transform " + duration + "ms ease-in-out; transform: " + _2d.TransformModelExtensions.toString(this.transform));
8718
+ setTimeout(function () { return _this.redraw(); }, F_CANVAS_ANIMATION_DURATION);
8719
+ };
8720
+ FCanvasComponent.prototype.isMobile = function () {
8721
+ // @ts-ignore
8722
+ var userAgent = navigator.userAgent || navigator.vendor || window['opera'];
8723
+ return /android|iPad|iPhone|iPod/i.test(userAgent);
8687
8724
  };
8688
8725
  FCanvasComponent.prototype.centerGroupOrNode = function (id, animated) {
8689
8726
  if (animated === void 0) { animated = true; }
@@ -9448,9 +9485,44 @@
9448
9485
  var F_ZOOM = new i0.InjectionToken('F_ZOOM');
9449
9486
  var FZoomBase = /** @class */ (function () {
9450
9487
  function FZoomBase(fComponentsStore) {
9488
+ var _this = this;
9451
9489
  this.fComponentsStore = fComponentsStore;
9452
9490
  this.isEnabled = false;
9453
9491
  this.listeners = dragToolkit.EventExtensions.emptyListener();
9492
+ this.onWheel = function (event) {
9493
+ var _a;
9494
+ event.preventDefault();
9495
+ var targetElement = event.target;
9496
+ if (((_a = _this.fComponentsStore.fDraggable) === null || _a === void 0 ? void 0 : _a.isDragStarted) || (targetElement === null || targetElement === void 0 ? void 0 : targetElement.closest('[fLockedContext]'))) {
9497
+ return;
9498
+ }
9499
+ var result = _this.getScale();
9500
+ var direction = event.deltaY > 0 ? -1 : 1;
9501
+ var step = _this.step;
9502
+ result = result + step * direction;
9503
+ result = Math.max(_this.minimum, Math.min(result, _this.maximum));
9504
+ var pointerPositionInFlow = new _2d.Point(event.clientX, event.clientY).elementTransform(_this.flowHost);
9505
+ _this.fCanvas.setZoom(result, pointerPositionInFlow);
9506
+ _this.fCanvas.redraw();
9507
+ _this.fCanvas.emitCanvasChangeEvent();
9508
+ };
9509
+ this.onDoubleClick = function (event) {
9510
+ var _a;
9511
+ event.preventDefault();
9512
+ var targetElement = event.target;
9513
+ if (((_a = _this.fComponentsStore.fDraggable) === null || _a === void 0 ? void 0 : _a.isDragStarted) || isNode(targetElement) || (targetElement === null || targetElement === void 0 ? void 0 : targetElement.closest('[fLockedContext]'))) {
9514
+ return;
9515
+ }
9516
+ var result = _this.getScale();
9517
+ var direction = 1;
9518
+ var step = _this.dblClickStep;
9519
+ result = result + step * direction;
9520
+ result = Math.max(_this.minimum, Math.min(result, _this.maximum));
9521
+ var pointerPositionInFlow = new _2d.Point(event.clientX, event.clientY).elementTransform(_this.flowHost);
9522
+ _this.fCanvas.setZoom(result, pointerPositionInFlow);
9523
+ _this.fCanvas.redrawWithAnimation();
9524
+ _this.fCanvas.emitCanvasChangeEvent();
9525
+ };
9454
9526
  }
9455
9527
  Object.defineProperty(FZoomBase.prototype, "flowHost", {
9456
9528
  get: function () {
@@ -9480,50 +9552,16 @@
9480
9552
  if (!this.flowHost) {
9481
9553
  return;
9482
9554
  }
9483
- this.flowHost.addEventListener('wheel', this.onWheel.bind(this));
9484
- this.flowHost.addEventListener('dblclick', this.onDoubleClick.bind(this));
9555
+ this.flowHost.addEventListener('wheel', this.onWheel);
9556
+ this.flowHost.addEventListener('dblclick', this.onDoubleClick);
9485
9557
  this.listeners = function () {
9486
- _this.flowHost.removeEventListener('wheel', _this.onWheel.bind(_this));
9487
- _this.flowHost.removeEventListener('dblclick', _this.onDoubleClick.bind(_this));
9558
+ _this.flowHost.removeEventListener('wheel', _this.onWheel);
9559
+ _this.flowHost.removeEventListener('dblclick', _this.onDoubleClick);
9488
9560
  };
9489
9561
  };
9490
9562
  FZoomBase.prototype.getScale = function () {
9491
9563
  return this.fCanvas.transform.scale || 1;
9492
9564
  };
9493
- FZoomBase.prototype.onWheel = function (event) {
9494
- var _a;
9495
- event.preventDefault();
9496
- var targetElement = event.target;
9497
- if (((_a = this.fComponentsStore.fDraggable) === null || _a === void 0 ? void 0 : _a.isDragStarted) || (targetElement === null || targetElement === void 0 ? void 0 : targetElement.closest('[fLockedContext]'))) {
9498
- return;
9499
- }
9500
- var result = this.getScale();
9501
- var direction = event.deltaY > 0 ? -1 : 1;
9502
- var step = this.step;
9503
- result = result + step * direction;
9504
- result = Math.max(this.minimum, Math.min(result, this.maximum));
9505
- var pointerPositionInFlow = new _2d.Point(event.clientX, event.clientY).elementTransform(this.flowHost);
9506
- this.fCanvas.setZoom(result, pointerPositionInFlow);
9507
- this.fCanvas.redraw();
9508
- this.fCanvas.emitCanvasChangeEvent();
9509
- };
9510
- FZoomBase.prototype.onDoubleClick = function (event) {
9511
- var _a;
9512
- event.preventDefault();
9513
- var targetElement = event.target;
9514
- if (((_a = this.fComponentsStore.fDraggable) === null || _a === void 0 ? void 0 : _a.isDragStarted) || isNode(targetElement) || (targetElement === null || targetElement === void 0 ? void 0 : targetElement.closest('[fLockedContext]'))) {
9515
- return;
9516
- }
9517
- var result = this.getScale();
9518
- var direction = 1;
9519
- var step = this.dblClickStep;
9520
- result = result + step * direction;
9521
- result = Math.max(this.minimum, Math.min(result, this.maximum));
9522
- var pointerPositionInFlow = new _2d.Point(event.clientX, event.clientY).elementTransform(this.flowHost);
9523
- this.fCanvas.setZoom(result, pointerPositionInFlow);
9524
- this.fCanvas.redrawWithAnimation();
9525
- this.fCanvas.emitCanvasChangeEvent();
9526
- };
9527
9565
  FZoomBase.prototype.onZoomToCenter = function (deltaY, position) {
9528
9566
  var preventDefault = function () {
9529
9567
  };