@foblex/flow 1.2.5 → 1.2.7

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.
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, Component, ChangeDetectionStrategy, Input, Directive, Injectable, ContentChild, Inject, ViewChild, ContentChildren, Optional, SkipSelf, EventEmitter, Output, HostBinding, NgModule } from '@angular/core';
3
- import { TransformModelExtensions, DomElementExtensions, RectExtensions, sanitizeElementId, PointExtensions, Point, GuidExtensions, VectorExtensions, SizeExtensions, BooleanExtensions, EventExtensions, MouseEventExtensions, IDragAndDropBase } from '@foblex/core';
4
- import { Subject, Observable, Subscription, startWith, debounceTime } from 'rxjs';
2
+ import { InjectionToken, Component, ChangeDetectionStrategy, Input, Directive, Injectable, ContentChild, Inject, ViewChild, ContentChildren, EventEmitter, Output, Optional, SkipSelf, HostBinding, NgModule } from '@angular/core';
3
+ import { TransformModelExtensions, DomElementExtensions, RectExtensions, sanitizeElementId, PointExtensions, Point, GuidExtensions, VectorExtensions, SizeExtensions, MouseEventExtensions, IDragAndDropBase, BooleanExtensions, EventExtensions } from '@foblex/core';
4
+ import { Subject, Subscription, Observable, startWith, debounceTime } from 'rxjs';
5
5
  import { DOCUMENT, CommonModule } from '@angular/common';
6
6
 
7
7
  const F_BACKGROUND_PATTERN = new InjectionToken('F_BACKGROUND_PATTERN');
@@ -1375,2461 +1375,2492 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImpor
1375
1375
  type: Injectable
1376
1376
  }], ctorParameters: () => [{ type: FComponentsStore }] });
1377
1377
 
1378
- const COMMON_PROVIDERS = [
1379
- GetAllNodesRectHandler,
1380
- GetConnectionVectorHandler,
1381
- GetConnectionHandler,
1382
- GetElementRectInFlowHandler,
1383
- GetOutputRectInFlowHandler,
1384
- GetInputRectInFlowHandler,
1385
- GetIncomingConnectionsHandler,
1386
- GetOutgoingConnectionsHandler,
1387
- UpdateNodeLayerHandler,
1388
- ];
1378
+ var EDraggableType;
1379
+ (function (EDraggableType) {
1380
+ EDraggableType["NODE"] = "node";
1381
+ EDraggableType["REASSIGN_CONNECTION"] = "reassign-connection";
1382
+ EDraggableType["CREATE_CONNECTION"] = "create-connection";
1383
+ EDraggableType["CONNECTION"] = "connection";
1384
+ EDraggableType["CANVAS"] = "canvas";
1385
+ EDraggableType["PALETTE_ITEM"] = "palette-item";
1386
+ EDraggableType["SELECTION"] = "selection";
1387
+ })(EDraggableType || (EDraggableType = {}));
1389
1388
 
1390
- class FConnectorBase {
1391
- constructor() {
1392
- this.stateChanges = new Subject();
1393
- this.side = EConnectorSide.BOTTOM;
1389
+ class CanvasDragHandler {
1390
+ constructor(fComponentsStore) {
1391
+ this.fComponentsStore = fComponentsStore;
1392
+ this.type = EDraggableType.CANVAS;
1393
+ this.onPointerDownPosition = PointExtensions.initialize();
1394
1394
  }
1395
- isContains(element) {
1396
- return this.hostElement.contains(element);
1395
+ initialize() {
1396
+ this.onPointerDownPosition = this.fComponentsStore.fCanvas.transform.position;
1397
1397
  }
1398
- setConnected(isConnected) {
1399
- this.isConnected = isConnected;
1398
+ move(difference) {
1399
+ this.fComponentsStore.fCanvas.setPosition(Point.fromPoint(this.onPointerDownPosition).add(difference));
1400
+ this.fComponentsStore.fCanvas.redraw();
1401
+ }
1402
+ complete() {
1403
+ this.fComponentsStore.fCanvas.completeDrag();
1400
1404
  }
1401
1405
  }
1402
1406
 
1403
- const F_NODE_INPUT = new InjectionToken('F_NODE_INPUT');
1404
- class FNodeInputBase extends FConnectorBase {
1407
+ class FDraggableDataContext {
1405
1408
  constructor() {
1406
- super(...arguments);
1407
- this.isConnected = false;
1409
+ this.selectedItems = [];
1410
+ this.onPointerDownScale = 1;
1411
+ this.onPointerDownPosition = new Point(0, 0);
1412
+ this.draggableItems = [];
1408
1413
  }
1409
- get canBeConnected() {
1410
- return !this.disabled && (this.multiple ? true : !this.isConnected);
1414
+ reset() {
1415
+ this.draggableItems = [];
1416
+ this.onPointerDownScale = 1;
1417
+ this.onPointerDownPosition = new Point(0, 0);
1411
1418
  }
1412
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeInputBase, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
1413
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FNodeInputBase, usesInheritance: true, ngImport: i0 }); }
1419
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FDraggableDataContext, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1420
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FDraggableDataContext }); }
1414
1421
  }
1415
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeInputBase, decorators: [{
1416
- type: Directive
1422
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FDraggableDataContext, decorators: [{
1423
+ type: Injectable
1417
1424
  }] });
1418
1425
 
1419
- function isNodeInput(element) {
1420
- return !!element.closest('[fNodeInput]');
1426
+ class CanvasOnPointerUp {
1427
+ constructor(fDraggableDataContext) {
1428
+ this.fDraggableDataContext = fDraggableDataContext;
1429
+ }
1430
+ handle(event) {
1431
+ const isDragCanvas = this.fDraggableDataContext.draggableItems.some((x) => x.type === EDraggableType.CANVAS);
1432
+ if (isDragCanvas) {
1433
+ this.fDraggableDataContext.draggableItems.forEach((x) => {
1434
+ x.complete?.();
1435
+ });
1436
+ }
1437
+ }
1438
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CanvasOnPointerUp, deps: [{ token: FDraggableDataContext }], target: i0.ɵɵFactoryTarget.Injectable }); }
1439
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CanvasOnPointerUp }); }
1421
1440
  }
1441
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CanvasOnPointerUp, decorators: [{
1442
+ type: Injectable
1443
+ }], ctorParameters: () => [{ type: FDraggableDataContext }] });
1422
1444
 
1423
- const F_NODE = new InjectionToken('F_NODE');
1424
- class FNodeBase {
1425
- constructor() {
1426
- this.stateChanges = new Subject();
1427
- this._position = PointExtensions.initialize();
1428
- }
1429
- isContains(element) {
1430
- return this.hostElement.contains(element);
1445
+ class CanvasPrepareDragSequence {
1446
+ get flowHost() {
1447
+ return this.fComponentsStore.fFlow.hostElement;
1431
1448
  }
1432
- redraw() {
1433
- this.hostElement.setAttribute('style', 'transform: translate(' + this.position.x + 'px,' + this.position.y + 'px)');
1449
+ constructor(fComponentsStore, fDraggableDataContext) {
1450
+ this.fComponentsStore = fComponentsStore;
1451
+ this.fDraggableDataContext = fDraggableDataContext;
1434
1452
  }
1435
- deselect() {
1436
- this.hostElement.classList.remove(F_SELECTED_CLASS);
1453
+ handle(event) {
1454
+ const pointerPositionInFlow = Point.fromPoint(event.getPosition()).elementTransform(this.flowHost);
1455
+ const isBackgroundElement = this.fComponentsStore.fBackground?.isBackgroundElement(event.targetElement);
1456
+ const isFlowHost = this.flowHost.contains(event.targetElement);
1457
+ let node = this.fComponentsStore.findNode(event.targetElement);
1458
+ if (node && node.disabled) {
1459
+ node = undefined;
1460
+ }
1461
+ if ((isBackgroundElement || (isFlowHost && !node)) && !this.fDraggableDataContext.draggableItems.length) {
1462
+ this.fDraggableDataContext.onPointerDownScale = 1;
1463
+ this.fDraggableDataContext.onPointerDownPosition = pointerPositionInFlow.div(1);
1464
+ this.fDraggableDataContext.draggableItems = [
1465
+ new CanvasDragHandler(this.fComponentsStore)
1466
+ ];
1467
+ }
1437
1468
  }
1438
- select() {
1439
- this.hostElement.classList.add(F_SELECTED_CLASS);
1469
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CanvasPrepareDragSequence, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }], target: i0.ɵɵFactoryTarget.Injectable }); }
1470
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CanvasPrepareDragSequence }); }
1471
+ }
1472
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CanvasPrepareDragSequence, decorators: [{
1473
+ type: Injectable
1474
+ }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }] });
1475
+
1476
+ const CANVAS_PROVIDERS = [
1477
+ CanvasOnPointerUp,
1478
+ CanvasPrepareDragSequence
1479
+ ];
1480
+
1481
+ const F_EXTERNAL_ITEM = new InjectionToken('F_EXTERNAL_ITEM');
1482
+ class FExternalItemBase {
1483
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FExternalItemBase, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1484
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FExternalItemBase, ngImport: i0 }); }
1485
+ }
1486
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FExternalItemBase, decorators: [{
1487
+ type: Directive
1488
+ }] });
1489
+
1490
+ function isExternalItem(element) {
1491
+ return !!element.closest('[fExternalItem]');
1492
+ }
1493
+ function getExternalItem(element) {
1494
+ return element.closest('[fExternalItem]');
1495
+ }
1496
+
1497
+ class FExternalItemService {
1498
+ constructor() {
1499
+ this.items = [];
1440
1500
  }
1441
- isSelected() {
1442
- return this.hostElement.classList.contains(F_SELECTED_CLASS);
1501
+ registerItem(item) {
1502
+ this.items.push(item);
1443
1503
  }
1444
- updatePosition(position) {
1445
- this._position = position;
1504
+ getItem(element) {
1505
+ return this.items.find(item => item.hostElement === element);
1446
1506
  }
1447
- completeDrag() {
1448
- this.positionChange.emit(this.position);
1507
+ removeItem(item) {
1508
+ const index = this.items.indexOf(item);
1509
+ if (index !== -1) {
1510
+ this.items.splice(index, 1);
1511
+ }
1449
1512
  }
1513
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FExternalItemService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1514
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FExternalItemService, providedIn: 'root' }); }
1450
1515
  }
1516
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FExternalItemService, decorators: [{
1517
+ type: Injectable,
1518
+ args: [{
1519
+ providedIn: 'root'
1520
+ }]
1521
+ }] });
1451
1522
 
1452
1523
  let uniqueId$5 = 0;
1453
- class FNodeInputDirective extends FNodeInputBase {
1454
- get disabled() {
1455
- return this.isDisabled;
1456
- }
1457
- set disabled(isDisabled) {
1458
- const value = BooleanExtensions.castToBoolean(isDisabled);
1459
- if (value !== this.isDisabled) {
1460
- this.isDisabled = value;
1461
- this.stateChanges.next();
1462
- }
1463
- }
1524
+ class FExternalItemDirective extends FExternalItemBase {
1464
1525
  get hostElement() {
1465
1526
  return this.elementReference.nativeElement;
1466
1527
  }
1467
- constructor(elementReference, fNode, fComponentsStore) {
1528
+ constructor(elementReference, fExternalItemService) {
1468
1529
  super();
1469
1530
  this.elementReference = elementReference;
1470
- this.fNode = fNode;
1471
- this.fComponentsStore = fComponentsStore;
1472
- this.id = `f-node-input-${uniqueId$5++}`;
1473
- this.multiple = true;
1474
- this.isDisabled = false;
1475
- this.isConnected = false;
1531
+ this.fExternalItemService = fExternalItemService;
1532
+ this.id = `f-external-item-${uniqueId$5++}`;
1476
1533
  }
1477
1534
  ngOnInit() {
1478
- if (!this.fNode) {
1479
- throw new Error('fNodeInput must be inside f-node');
1480
- }
1481
- this.fComponentsStore.addInput(this);
1482
- this.fNode.addConnector(this);
1483
- }
1484
- setConnected(isConnected) {
1485
- this.isConnected = isConnected;
1486
- this.hostElement.classList.toggle('f-node-input-connected', isConnected);
1535
+ this.fExternalItemService.registerItem(this);
1487
1536
  }
1488
1537
  ngOnDestroy() {
1489
- this.fNode.removeConnector(this);
1490
- this.fComponentsStore.removeInput(this);
1538
+ this.fExternalItemService.removeItem(this);
1491
1539
  }
1492
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeInputDirective, deps: [{ token: i0.ElementRef }, { token: F_NODE }, { token: FComponentsStore }], target: i0.ɵɵFactoryTarget.Directive }); }
1493
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FNodeInputDirective, selector: "[fNodeInput]", inputs: { id: ["fNodeInputId", "id"], multiple: ["fNodeInputMultiple", "multiple"], disabled: ["fNodeInputDisabled", "disabled"] }, host: { properties: { "attr.id": "id", "class.f-node-input-multiple": "multiple", "class.f-node-input-disabled": "disabled", "class.f-node-input-not-connectable": "!canBeConnected" }, classAttribute: "f-component f-node-input" }, providers: [{ provide: F_NODE_INPUT, useExisting: FNodeInputDirective }], exportAs: ["fNodeInput"], usesInheritance: true, ngImport: i0 }); }
1540
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FExternalItemDirective, deps: [{ token: i0.ElementRef }, { token: FExternalItemService }], target: i0.ɵɵFactoryTarget.Directive }); }
1541
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FExternalItemDirective, selector: "[fExternalItem]", inputs: { id: "id", data: "data" }, host: { properties: { "attr.id": "id" }, classAttribute: "f-component f-external-item" }, providers: [
1542
+ { provide: F_EXTERNAL_ITEM, useExisting: FExternalItemDirective }
1543
+ ], usesInheritance: true, ngImport: i0 }); }
1494
1544
  }
1495
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeInputDirective, decorators: [{
1545
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FExternalItemDirective, decorators: [{
1496
1546
  type: Directive,
1497
1547
  args: [{
1498
- selector: "[fNodeInput]",
1499
- exportAs: 'fNodeInput',
1548
+ selector: "[fExternalItem]",
1500
1549
  host: {
1501
1550
  '[attr.id]': 'id',
1502
- class: "f-component f-node-input",
1503
- '[class.f-node-input-multiple]': 'multiple',
1504
- '[class.f-node-input-disabled]': 'disabled',
1505
- '[class.f-node-input-not-connectable]': '!canBeConnected',
1551
+ class: "f-component f-external-item",
1506
1552
  },
1507
- providers: [{ provide: F_NODE_INPUT, useExisting: FNodeInputDirective }],
1553
+ providers: [
1554
+ { provide: F_EXTERNAL_ITEM, useExisting: FExternalItemDirective }
1555
+ ],
1508
1556
  }]
1509
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: FNodeBase, decorators: [{
1510
- type: Inject,
1511
- args: [F_NODE]
1512
- }] }, { type: FComponentsStore }], propDecorators: { id: [{
1513
- type: Input,
1514
- args: ['fNodeInputId']
1515
- }], multiple: [{
1516
- type: Input,
1517
- args: ['fNodeInputMultiple']
1518
- }], disabled: [{
1519
- type: Input,
1520
- args: ['fNodeInputDisabled']
1557
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: FExternalItemService }], propDecorators: { id: [{
1558
+ type: Input
1559
+ }], data: [{
1560
+ type: Input
1521
1561
  }] } });
1522
1562
 
1523
- const F_NODE_OUTLET = new InjectionToken('F_NODE_OUTLET');
1524
- class FNodeOutletBase extends FConnectorBase {
1525
- constructor() {
1526
- super(...arguments);
1527
- this.isConnected = false;
1528
- this.outputs = [];
1563
+ class LineElement {
1564
+ constructor(hostElement) {
1565
+ this.hostElement = hostElement;
1566
+ this.element = DomElementExtensions.createHtmlElement('div');
1567
+ this.hostElement.appendChild(this.element);
1568
+ this.element.classList.add('f-line');
1529
1569
  }
1530
- get canBeConnected() {
1531
- return !this.disabled;
1570
+ hide() {
1571
+ this.element.style.display = 'none';
1532
1572
  }
1533
- setOutputs(outputs) {
1534
- this.outputs = outputs;
1573
+ show() {
1574
+ this.element.style.display = 'block';
1575
+ }
1576
+ draw(object) {
1577
+ this.element.style.position = 'absolute';
1578
+ Object.keys(object).forEach((key) => {
1579
+ // @ts-ignore
1580
+ this.element.style[key] = object[key] + 'px';
1581
+ });
1535
1582
  }
1536
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeOutletBase, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
1537
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FNodeOutletBase, usesInheritance: true, ngImport: i0 }); }
1538
- }
1539
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeOutletBase, decorators: [{
1540
- type: Directive
1541
- }] });
1542
-
1543
- function isNodeOutlet(element) {
1544
- return !!element.closest('[fNodeOutlet]');
1545
1583
  }
1546
1584
 
1547
- let uniqueId$4 = 0;
1548
- class FNodeOutletDirective extends FNodeOutletBase {
1549
- get disabled() {
1550
- return this.isDisabled;
1551
- }
1552
- set disabled(isDisabled) {
1553
- const value = BooleanExtensions.castToBoolean(isDisabled);
1554
- if (value !== this.isDisabled) {
1555
- this.isDisabled = value;
1556
- this.stateChanges.next();
1557
- }
1585
+ class LineService {
1586
+ constructor(hostElement) {
1587
+ this.hostElement = hostElement;
1588
+ this.fHorizontalLine = new LineElement(this.hostElement);
1589
+ this.fVerticalLine = new LineElement(this.hostElement);
1558
1590
  }
1559
- get hostElement() {
1560
- return this.elementReference.nativeElement;
1591
+ drawVerticalLine(x, size, transform) {
1592
+ this.fVerticalLine.show();
1593
+ this.fVerticalLine.draw({
1594
+ left: x * transform.scale + transform.position.x + transform.scaledPosition.x,
1595
+ top: 0,
1596
+ width: 1,
1597
+ height: size.height
1598
+ });
1561
1599
  }
1562
- constructor(elementReference, fNode, fComponentsStore) {
1563
- super();
1564
- this.elementReference = elementReference;
1565
- this.fNode = fNode;
1566
- this.fComponentsStore = fComponentsStore;
1567
- this.id = `f-node-outlet-${uniqueId$4++}`;
1568
- this.isDisabled = false;
1569
- this.isConnectionFromOutlet = false;
1600
+ drawHorizontalLine(y, size, transform) {
1601
+ this.fHorizontalLine.show();
1602
+ this.fHorizontalLine.draw({
1603
+ left: 0,
1604
+ top: y * transform.scale + transform.position.y + transform.scaledPosition.y,
1605
+ width: size.width,
1606
+ height: 1
1607
+ });
1570
1608
  }
1571
- ngOnInit() {
1572
- if (!this.fNode) {
1573
- throw new Error('fNodeOutlet must be inside f-node');
1574
- }
1575
- this.fComponentsStore.addOutlet(this);
1609
+ hideVerticalLine() {
1610
+ this.fVerticalLine.hide();
1576
1611
  }
1577
- ngOnDestroy() {
1578
- this.fComponentsStore.removeOutlet(this);
1612
+ hideHorizontalLine() {
1613
+ this.fHorizontalLine.hide();
1579
1614
  }
1580
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeOutletDirective, deps: [{ token: i0.ElementRef }, { token: F_NODE }, { token: FComponentsStore }], target: i0.ɵɵFactoryTarget.Directive }); }
1581
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FNodeOutletDirective, selector: "[fNodeOutlet]", inputs: { id: ["fNodeOutletId", "id"], disabled: ["fNodeOutletDisabled", "disabled"], isConnectionFromOutlet: "isConnectionFromOutlet" }, host: { properties: { "attr.id": "id", "class.f-node-outlet-disabled": "disabled" }, classAttribute: "f-component f-node-outlet" }, providers: [{ provide: F_NODE_OUTLET, useExisting: FNodeOutletDirective }], exportAs: ["fNodeOutlet"], usesInheritance: true, ngImport: i0 }); }
1582
1615
  }
1583
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeOutletDirective, decorators: [{
1584
- type: Directive,
1585
- args: [{
1586
- selector: "[fNodeOutlet]",
1587
- exportAs: 'fNodeOutlet',
1588
- host: {
1589
- '[attr.id]': 'id',
1590
- class: "f-component f-node-outlet",
1591
- '[class.f-node-outlet-disabled]': 'disabled'
1592
- },
1593
- providers: [{ provide: F_NODE_OUTLET, useExisting: FNodeOutletDirective }],
1594
- }]
1595
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: FNodeBase, decorators: [{
1596
- type: Inject,
1597
- args: [F_NODE]
1598
- }] }, { type: FComponentsStore }], propDecorators: { id: [{
1599
- type: Input,
1600
- args: ['fNodeOutletId']
1601
- }], disabled: [{
1602
- type: Input,
1603
- args: ['fNodeOutletDisabled']
1604
- }], isConnectionFromOutlet: [{
1605
- type: Input
1606
- }] } });
1607
1616
 
1608
- const F_NODE_OUTPUT = new InjectionToken('F_NODE_OUTPUT');
1609
- class FNodeOutputBase extends FConnectorBase {
1610
- constructor() {
1611
- super(...arguments);
1612
- this.isConnected = false;
1617
+ const ALIGN_THRESHOLD = 10;
1618
+ /**
1619
+ * A class to find the nearest coordinate.
1620
+ */
1621
+ class NearestCoordinateFinder {
1622
+ /**
1623
+ * Constructor to initialize the NearestCoordinateFinder.
1624
+ * @param elements - The array of IRect elements.
1625
+ * @param target - The target IRect element.
1626
+ */
1627
+ constructor(elements, target) {
1628
+ this.elements = elements;
1629
+ this.target = target;
1613
1630
  }
1614
- get canBeConnected() {
1615
- return !this.disabled && !this.isConnected;
1631
+ /**
1632
+ * Finds the nearest coordinate on a specified axis.
1633
+ * @returns The nearest coordinate and its distance.
1634
+ */
1635
+ findNearestCoordinateByX() {
1636
+ let nearest;
1637
+ let minDistance;
1638
+ for (const element of this.elements) {
1639
+ const distanceLeftLeft = this.target.x - element.x;
1640
+ const distanceLeftRight = this.target.x - (element.x + element.width);
1641
+ const distanceCenterCenter = this.target.gravityCenter.x - element.gravityCenter.x;
1642
+ const distanceRightLeft = (this.target.x + this.target.width) - element.x;
1643
+ const distanceRightRight = (this.target.x + this.target.width) - (element.x + element.width);
1644
+ if (Math.abs(distanceLeftLeft) <= ALIGN_THRESHOLD ||
1645
+ Math.abs(distanceLeftRight) <= ALIGN_THRESHOLD ||
1646
+ Math.abs(distanceCenterCenter) <= ALIGN_THRESHOLD ||
1647
+ Math.abs(distanceRightLeft) <= ALIGN_THRESHOLD ||
1648
+ Math.abs(distanceRightRight) <= ALIGN_THRESHOLD) {
1649
+ if (minDistance === undefined || Math.abs(distanceCenterCenter) < Math.abs(minDistance)) {
1650
+ minDistance = distanceCenterCenter;
1651
+ nearest = element.gravityCenter.x;
1652
+ }
1653
+ if (Math.abs(distanceLeftLeft) < Math.abs(minDistance)) {
1654
+ minDistance = distanceLeftLeft;
1655
+ nearest = element.x;
1656
+ }
1657
+ if (Math.abs(distanceRightRight) < Math.abs(minDistance)) {
1658
+ minDistance = distanceRightRight;
1659
+ nearest = element.x + element.width;
1660
+ }
1661
+ if (Math.abs(distanceLeftRight) < Math.abs(minDistance)) {
1662
+ minDistance = distanceLeftRight;
1663
+ nearest = element.x + element.width;
1664
+ }
1665
+ if (Math.abs(distanceRightLeft) < Math.abs(minDistance)) {
1666
+ minDistance = distanceRightLeft;
1667
+ nearest = element.x;
1668
+ }
1669
+ }
1670
+ }
1671
+ return { value: nearest, distance: minDistance };
1672
+ }
1673
+ /**
1674
+ * Finds the nearest coordinate on a specified axis.
1675
+ * @returns The nearest coordinate and its distance.
1676
+ */
1677
+ findNearestCoordinateByY() {
1678
+ let nearest;
1679
+ let minDistance;
1680
+ for (const element of this.elements) {
1681
+ const distanceTopTop = this.target.y - element.y;
1682
+ const distanceTopBottom = this.target.y - (element.y + element.height);
1683
+ const distanceCenterCenter = this.target.gravityCenter.y - element.gravityCenter.y;
1684
+ const distanceBottomTop = (this.target.y + this.target.height) - element.y;
1685
+ const distanceBottomBottom = (this.target.y + this.target.height) - (element.y + element.height);
1686
+ if (Math.abs(distanceTopTop) <= ALIGN_THRESHOLD ||
1687
+ Math.abs(distanceTopBottom) <= ALIGN_THRESHOLD ||
1688
+ Math.abs(distanceCenterCenter) <= ALIGN_THRESHOLD ||
1689
+ Math.abs(distanceBottomTop) <= ALIGN_THRESHOLD ||
1690
+ Math.abs(distanceBottomBottom) <= ALIGN_THRESHOLD) {
1691
+ if (minDistance === undefined || Math.abs(distanceCenterCenter) < Math.abs(minDistance)) {
1692
+ minDistance = distanceCenterCenter;
1693
+ nearest = element.gravityCenter.y;
1694
+ }
1695
+ if (Math.abs(distanceTopTop) < Math.abs(minDistance)) {
1696
+ minDistance = distanceTopTop;
1697
+ nearest = element.y;
1698
+ }
1699
+ if (Math.abs(distanceBottomBottom) < Math.abs(minDistance)) {
1700
+ minDistance = distanceBottomBottom;
1701
+ nearest = element.y + element.height;
1702
+ }
1703
+ if (Math.abs(distanceTopBottom) < Math.abs(minDistance)) {
1704
+ minDistance = distanceTopBottom;
1705
+ nearest = element.y + element.height;
1706
+ }
1707
+ if (Math.abs(distanceBottomTop) < Math.abs(minDistance)) {
1708
+ minDistance = distanceBottomTop;
1709
+ nearest = element.y;
1710
+ }
1711
+ }
1712
+ }
1713
+ return { value: nearest, distance: minDistance };
1616
1714
  }
1617
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeOutputBase, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
1618
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FNodeOutputBase, usesInheritance: true, ngImport: i0 }); }
1619
1715
  }
1620
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeOutputBase, decorators: [{
1621
- type: Directive
1622
- }] });
1623
1716
 
1624
- function isNodeOutput(element) {
1625
- return !!element.closest('[fNodeOutput]');
1717
+ const F_LINE_ALIGNMENT = new InjectionToken('F_LINE_ALIGNMENT');
1718
+ class FLineAlignmentBase {
1719
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FLineAlignmentBase, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1720
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FLineAlignmentBase, ngImport: i0 }); }
1626
1721
  }
1722
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FLineAlignmentBase, decorators: [{
1723
+ type: Directive
1724
+ }] });
1627
1725
 
1628
- let uniqueId$3 = 0;
1629
- class FNodeOutputDirective extends FNodeOutputBase {
1630
- get disabled() {
1631
- return this.isDisabled;
1632
- }
1633
- set disabled(isDisabled) {
1634
- const value = BooleanExtensions.castToBoolean(isDisabled);
1635
- if (value !== this.isDisabled) {
1636
- this.isDisabled = value;
1637
- this.stateChanges.next();
1638
- }
1639
- }
1726
+ class FLineAlignmentComponent extends FLineAlignmentBase {
1640
1727
  get hostElement() {
1641
1728
  return this.elementReference.nativeElement;
1642
1729
  }
1643
- constructor(elementReference, fNode, fComponentsStore) {
1730
+ get transform() {
1731
+ return this.fComponentsStore.fCanvas.transform;
1732
+ }
1733
+ get flowHost() {
1734
+ return this.fComponentsStore.fFlow.hostElement;
1735
+ }
1736
+ constructor(elementReference, fComponentsStore, fDraggableDataContext, getElementRectInFlowHandler) {
1644
1737
  super();
1645
1738
  this.elementReference = elementReference;
1646
- this.fNode = fNode;
1647
1739
  this.fComponentsStore = fComponentsStore;
1648
- this.id = `f-node-output-${uniqueId$3++}`;
1649
- this.isDisabled = false;
1650
- this.isConnected = false;
1740
+ this.fDraggableDataContext = fDraggableDataContext;
1741
+ this.getElementRectInFlowHandler = getElementRectInFlowHandler;
1742
+ this.size = SizeExtensions.initialize();
1743
+ this.draggedNodeRect = RectExtensions.initialize();
1744
+ this.rects = [];
1745
+ this.lineService = new LineService(this.hostElement);
1651
1746
  }
1652
1747
  ngOnInit() {
1653
- if (!this.fNode) {
1654
- throw new Error('fNodeOutput must be inside f-node');
1655
- }
1656
- this.fComponentsStore.addOutput(this);
1657
- this.fNode.addConnector(this);
1748
+ this.fDraggableDataContext.fLineAlignment = this;
1658
1749
  }
1659
- setConnected(isConnected) {
1660
- this.isConnected = isConnected;
1661
- this.hostElement.classList.toggle('f-node-output-connected', isConnected);
1662
- }
1663
- ngOnDestroy() {
1664
- this.fNode.removeConnector(this);
1665
- this.fComponentsStore.removeOutput(this);
1750
+ initialize(allNodes, currentNodes) {
1751
+ this.size = this.flowHost.getBoundingClientRect();
1752
+ this.rects = [];
1753
+ const draggedNodeRects = currentNodes.map((x) => {
1754
+ return this.getElementRectInFlowHandler.handle(x.hostElement);
1755
+ });
1756
+ this.draggedNodeRect = RectExtensions.union(draggedNodeRects);
1757
+ const allNodesExcludeCurrents = allNodes.filter((x) => {
1758
+ return !currentNodes.includes(x);
1759
+ });
1760
+ this.rects = allNodesExcludeCurrents.map((x) => {
1761
+ return this.getElementRectInFlowHandler.handle(x.hostElement);
1762
+ });
1666
1763
  }
1667
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeOutputDirective, deps: [{ token: i0.ElementRef }, { token: F_NODE }, { token: FComponentsStore }], target: i0.ɵɵFactoryTarget.Directive }); }
1668
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FNodeOutputDirective, selector: "[fNodeOutput]", inputs: { id: ["fNodeOutputId", "id"], disabled: ["fNodeOutputDisabled", "disabled"] }, host: { properties: { "attr.id": "id", "class.f-node-output-disabled": "disabled" }, classAttribute: "f-component f-node-output" }, providers: [{ provide: F_NODE_OUTPUT, useExisting: FNodeOutputDirective }], exportAs: ["fNodeOutput"], usesInheritance: true, ngImport: i0 }); }
1669
- }
1670
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeOutputDirective, decorators: [{
1671
- type: Directive,
1672
- args: [{
1673
- selector: "[fNodeOutput]",
1674
- exportAs: 'fNodeOutput',
1675
- host: {
1676
- '[attr.id]': 'id',
1677
- class: "f-component f-node-output",
1678
- '[class.f-node-output-disabled]': 'disabled',
1679
- },
1680
- providers: [{ provide: F_NODE_OUTPUT, useExisting: FNodeOutputDirective }],
1681
- }]
1682
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: FNodeBase, decorators: [{
1683
- type: Inject,
1684
- args: [F_NODE]
1685
- }] }, { type: FComponentsStore }], propDecorators: { id: [{
1686
- type: Input,
1687
- args: ['fNodeOutputId']
1688
- }], disabled: [{
1689
- type: Input,
1690
- args: ['fNodeOutputDisabled']
1691
- }] } });
1692
-
1693
- const F_DRAG_HANDLE = new InjectionToken('F_DRAG_HANDLE');
1694
- class FDragHandleDirective {
1695
- get disabled() {
1696
- return this.isDisabled;
1764
+ handle(difference) {
1765
+ this.drawIntersectingLines(difference);
1697
1766
  }
1698
- set disabled(isDisabled) {
1699
- const value = BooleanExtensions.castToBoolean(isDisabled);
1700
- if (value !== this.isDisabled) {
1701
- this.isDisabled = value;
1702
- this.stateChanges.next();
1767
+ drawIntersectingLines(difference) {
1768
+ const intersect = this.findNearestCoordinate(difference);
1769
+ if (intersect.xResult.value !== undefined) {
1770
+ this.lineService.drawVerticalLine(intersect.xResult.value, this.size, this.transform);
1771
+ }
1772
+ else {
1773
+ this.lineService.hideVerticalLine();
1774
+ }
1775
+ if (intersect.yResult.value !== undefined) {
1776
+ this.lineService.drawHorizontalLine(intersect.yResult.value, this.size, this.transform);
1777
+ }
1778
+ else {
1779
+ this.lineService.hideHorizontalLine();
1703
1780
  }
1704
1781
  }
1705
- get hostElement() {
1706
- return this.elementReference.nativeElement;
1707
- }
1708
- constructor(elementReference, _parentNode) {
1709
- this.elementReference = elementReference;
1710
- this.stateChanges = new Subject();
1711
- this.isDisabled = false;
1712
- this._parentNode = _parentNode;
1713
- }
1714
- ngOnDestroy() {
1715
- this.stateChanges.complete();
1782
+ findNearestCoordinate(difference) {
1783
+ const rect = RectExtensions.addPoint(this.draggedNodeRect, difference);
1784
+ const finder = new NearestCoordinateFinder(this.rects, rect);
1785
+ const xResult = finder.findNearestCoordinateByX();
1786
+ const yResult = finder.findNearestCoordinateByY();
1787
+ const result = { xResult, yResult };
1788
+ return result;
1716
1789
  }
1717
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FDragHandleDirective, deps: [{ token: i0.ElementRef }, { token: F_NODE, optional: true, skipSelf: true }], target: i0.ɵɵFactoryTarget.Directive }); }
1718
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FDragHandleDirective, isStandalone: true, selector: "[fDragHandle]", inputs: { disabled: ["fDragHandleDisabled", "disabled"] }, host: { properties: { "class.f-drag-handle-disabled": "disabled" }, classAttribute: "f-drag-handle f-component" }, providers: [{ provide: F_DRAG_HANDLE, useExisting: FDragHandleDirective }], ngImport: i0 }); }
1719
- }
1720
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FDragHandleDirective, decorators: [{
1721
- type: Directive,
1722
- args: [{
1723
- selector: "[fDragHandle]",
1724
- standalone: true,
1725
- host: {
1726
- class: "f-drag-handle f-component",
1727
- '[class.f-drag-handle-disabled]': 'disabled'
1728
- },
1729
- providers: [{ provide: F_DRAG_HANDLE, useExisting: FDragHandleDirective }],
1730
- }]
1731
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: undefined, decorators: [{
1732
- type: Inject,
1733
- args: [F_NODE]
1734
- }, {
1735
- type: Optional
1736
- }, {
1737
- type: SkipSelf
1738
- }] }], propDecorators: { disabled: [{
1739
- type: Input,
1740
- args: ['fDragHandleDisabled']
1741
- }] } });
1742
-
1743
- function isNodeDragHandle(element) {
1744
- const dragHandle = getClosestDragHandle(element);
1745
- return !!dragHandle && !isElementOrParentExcluded(element);
1746
- }
1747
- function isElementOrParentExcluded(element) {
1748
- const isContains = isElementContainsClass(element);
1749
- const parentElement = element.parentElement;
1750
- const dragHandle = getClosestDragHandle(parentElement);
1751
- if (!isContains && !!dragHandle) {
1752
- return isElementOrParentExcluded(parentElement);
1790
+ complete() {
1791
+ this.lineService.hideVerticalLine();
1792
+ this.lineService.hideHorizontalLine();
1753
1793
  }
1754
- return isContains;
1755
- }
1756
- function getClosestDragHandle(element) {
1757
- return element.closest('.f-drag-handle');
1758
- }
1759
- function isElementContainsClass(element) {
1760
- return element.classList.contains('f-drag-handle-disabled');
1794
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FLineAlignmentComponent, deps: [{ token: i0.ElementRef }, { token: FComponentsStore }, { token: FDraggableDataContext }, { token: GetElementRectInFlowHandler }], target: i0.ɵɵFactoryTarget.Component }); }
1795
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.9", type: FLineAlignmentComponent, selector: "f-line-alignment", host: { classAttribute: "f-line-alignment f-component" }, providers: [
1796
+ { provide: F_LINE_ALIGNMENT, useExisting: FLineAlignmentComponent }
1797
+ ], exportAs: ["fComponent"], usesInheritance: true, ngImport: i0, template: "", isInline: true, styles: [":host{display:block;position:absolute;left:0;top:0;width:100%;height:100%;overflow:hidden;pointer-events:none;-webkit-user-select:none;user-select:none}\n"] }); }
1761
1798
  }
1799
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FLineAlignmentComponent, decorators: [{
1800
+ type: Component,
1801
+ args: [{ selector: "f-line-alignment", template: "", exportAs: "fComponent", host: {
1802
+ 'class': 'f-line-alignment f-component'
1803
+ }, providers: [
1804
+ { provide: F_LINE_ALIGNMENT, useExisting: FLineAlignmentComponent }
1805
+ ], styles: [":host{display:block;position:absolute;left:0;top:0;width:100%;height:100%;overflow:hidden;pointer-events:none;-webkit-user-select:none;user-select:none}\n"] }]
1806
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: FComponentsStore }, { type: FDraggableDataContext }, { type: GetElementRectInFlowHandler }] });
1762
1807
 
1763
- class FResizeObserver extends Observable {
1764
- constructor(element) {
1765
- super(subscriber => {
1766
- const observer = new ResizeObserver(entries => {
1767
- subscriber.next(entries);
1768
- });
1769
- observer.observe(element);
1770
- return function unsubscribe() {
1771
- observer.unobserve(element);
1772
- observer.disconnect();
1773
- };
1774
- });
1775
- }
1808
+ const F_SELECTION_AREA = new InjectionToken('F_SELECTION_AREA');
1809
+ class FSelectionAreaBase {
1810
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FSelectionAreaBase, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1811
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FSelectionAreaBase, ngImport: i0 }); }
1776
1812
  }
1813
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FSelectionAreaBase, decorators: [{
1814
+ type: Directive
1815
+ }] });
1777
1816
 
1778
- let uniqueId$2 = 0;
1779
- class FNodeComponent extends FNodeBase {
1780
- set position(value) {
1781
- this._position = PointExtensions.castToPoint(value);
1782
- this.refresh();
1783
- }
1784
- get position() {
1785
- return this._position;
1786
- }
1817
+ class FSelectionAreaComponent extends FSelectionAreaBase {
1787
1818
  get hostElement() {
1788
1819
  return this.elementReference.nativeElement;
1789
1820
  }
1790
- constructor(elementReference, fComponentsStore) {
1821
+ constructor(elementReference, fDraggableDataContext) {
1791
1822
  super();
1792
1823
  this.elementReference = elementReference;
1793
- this.fComponentsStore = fComponentsStore;
1794
- this.subscriptions$ = new Subscription();
1795
- this.id = `f-node-${uniqueId$2++}`;
1796
- this.positionChange = new EventEmitter();
1797
- this.disabled = false;
1798
- this.connectors = [];
1824
+ this.fDraggableDataContext = fDraggableDataContext;
1799
1825
  }
1800
1826
  ngOnInit() {
1801
- super.redraw();
1802
- this.fComponentsStore.addNode(this);
1803
- }
1804
- ngAfterViewInit() {
1805
- this.subscriptions$.add(this.subscribeOnResizeChanges());
1806
- }
1807
- subscribeOnResizeChanges() {
1808
- return new FResizeObserver(this.hostElement).pipe(startWith(null)).subscribe(() => {
1809
- this.connectors.forEach((connector) => {
1810
- connector.side = new GetConnectorSideInNodeHandler().handle(connector.hostElement, this.hostElement);
1811
- });
1812
- this.fComponentsStore.changes.next();
1813
- });
1814
- }
1815
- addConnector(connector) {
1816
- this.connectors.push(connector);
1827
+ this.fDraggableDataContext.fSelectionArea = this;
1828
+ this.hostElement.style.display = 'none';
1817
1829
  }
1818
- removeConnector(connector) {
1819
- const index = this.connectors.indexOf(connector);
1820
- if (index !== -1) {
1821
- this.connectors.splice(index, 1);
1822
- }
1830
+ hide() {
1831
+ this.hostElement.style.display = 'none';
1823
1832
  }
1824
- refresh() {
1825
- this.stateChanges.next();
1833
+ show() {
1834
+ this.hostElement.style.display = 'block';
1826
1835
  }
1827
- ngOnDestroy() {
1828
- this.fComponentsStore.removeNode(this);
1829
- this.stateChanges.complete();
1830
- this.subscriptions$.unsubscribe();
1836
+ draw(object) {
1837
+ const style = this.hostElement.style;
1838
+ style.left = object.left + 'px';
1839
+ style.top = object.top + 'px';
1840
+ style.width = object.width + 'px';
1841
+ style.height = object.height + 'px';
1831
1842
  }
1832
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeComponent, deps: [{ token: i0.ElementRef }, { token: FComponentsStore }], target: i0.ɵɵFactoryTarget.Component }); }
1833
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.9", type: FNodeComponent, selector: "f-node", inputs: { id: "id", position: ["fNodePosition", "position"], disabled: "disabled" }, outputs: { positionChange: "fNodePositionChange" }, host: { properties: { "attr.id": "id", "class.f-node-disabled": "disabled" }, classAttribute: "f-node f-component" }, providers: [
1834
- { provide: F_NODE, useExisting: FNodeComponent }
1835
- ], exportAs: ["fComponent"], usesInheritance: true, ngImport: i0, template: "<ng-content></ng-content>\n", styles: [":host{position:absolute!important;left:0;top:0;pointer-events:all;transform-origin:0 0;-webkit-user-select:none;user-select:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1843
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FSelectionAreaComponent, deps: [{ token: i0.ElementRef }, { token: FDraggableDataContext }], target: i0.ɵɵFactoryTarget.Component }); }
1844
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.9", type: FSelectionAreaComponent, selector: "f-selection-area", host: { classAttribute: "f-selection-area f-component" }, providers: [
1845
+ { provide: F_SELECTION_AREA, useExisting: FSelectionAreaComponent }
1846
+ ], usesInheritance: true, ngImport: i0, template: ``, isInline: true, styles: [":host{position:absolute}\n"] }); }
1836
1847
  }
1837
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeComponent, decorators: [{
1848
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FSelectionAreaComponent, decorators: [{
1838
1849
  type: Component,
1839
- args: [{ selector: "f-node", exportAs: "fComponent", changeDetection: ChangeDetectionStrategy.OnPush, host: {
1840
- '[attr.id]': 'id',
1841
- class: "f-node f-component",
1842
- '[class.f-node-disabled]': 'disabled',
1850
+ args: [{ selector: "f-selection-area", template: ``, host: {
1851
+ 'class': 'f-selection-area f-component'
1843
1852
  }, providers: [
1844
- { provide: F_NODE, useExisting: FNodeComponent }
1845
- ], template: "<ng-content></ng-content>\n", styles: [":host{position:absolute!important;left:0;top:0;pointer-events:all;transform-origin:0 0;-webkit-user-select:none;user-select:none}\n"] }]
1846
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: FComponentsStore }], propDecorators: { id: [{
1847
- type: Input
1848
- }], position: [{
1849
- type: Input,
1850
- args: ['fNodePosition']
1851
- }], positionChange: [{
1852
- type: Output,
1853
- args: ['fNodePositionChange']
1854
- }], disabled: [{
1855
- type: Input
1856
- }] } });
1857
-
1858
- function isNode(element) {
1859
- return !!element.closest('f-node');
1860
- }
1853
+ { provide: F_SELECTION_AREA, useExisting: FSelectionAreaComponent }
1854
+ ], styles: [":host{position:absolute}\n"] }]
1855
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: FDraggableDataContext }] });
1861
1856
 
1862
- const F_ZOOM = new InjectionToken('F_ZOOM');
1863
- class FZoomBase {
1864
- get flowHost() {
1865
- return this.fComponentsStore.flowHost;
1857
+ class FindFirstCanBeConnectedOutputByOutletHandler {
1858
+ get fNodes() {
1859
+ return this.fComponentsStore.fNodes;
1866
1860
  }
1867
- get fCanvas() {
1868
- return this.fComponentsStore.fCanvas;
1861
+ get fOutputs() {
1862
+ return this.fComponentsStore.fOutputs;
1869
1863
  }
1870
1864
  constructor(fComponentsStore) {
1871
1865
  this.fComponentsStore = fComponentsStore;
1872
- this.isEnabled = false;
1873
- this.listeners = EventExtensions.emptyListener();
1874
1866
  }
1875
- toggleZoom() {
1876
- if (this.isEnabled) {
1877
- this.subscribe();
1867
+ handle(outlet) {
1868
+ let result;
1869
+ const node = this.fNodes.find((x) => x.isContains(outlet.hostElement));
1870
+ if (!node) {
1871
+ throw new Error('Node not found');
1878
1872
  }
1879
- else {
1880
- this.unsubscribe();
1873
+ const outputsOfNode = this.fOutputs.filter((x) => {
1874
+ return node.isContains(x.hostElement) && x.canBeConnected;
1875
+ });
1876
+ if (outputsOfNode.length > 0) {
1877
+ result = outputsOfNode[0];
1881
1878
  }
1879
+ return result;
1882
1880
  }
1883
- subscribe() {
1884
- this.listeners();
1885
- if (!this.flowHost) {
1886
- return;
1887
- }
1888
- this.flowHost.addEventListener('wheel', this.onWheel.bind(this));
1889
- this.flowHost.addEventListener('dblclick', this.onDoubleClick.bind(this));
1890
- this.listeners = () => {
1891
- this.flowHost.removeEventListener('wheel', this.onWheel.bind(this));
1892
- this.flowHost.removeEventListener('dblclick', this.onDoubleClick.bind(this));
1893
- };
1881
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FindFirstCanBeConnectedOutputByOutletHandler, deps: [{ token: FComponentsStore }], target: i0.ɵɵFactoryTarget.Injectable }); }
1882
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FindFirstCanBeConnectedOutputByOutletHandler }); }
1883
+ }
1884
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FindFirstCanBeConnectedOutputByOutletHandler, decorators: [{
1885
+ type: Injectable
1886
+ }], ctorParameters: () => [{ type: FComponentsStore }] });
1887
+
1888
+ class CreateConnectionDragHandler {
1889
+ constructor(getOutputRectInFlowHandler, getConnectionVectorHandler, connection, mouseDownPoint) {
1890
+ this.getOutputRectInFlowHandler = getOutputRectInFlowHandler;
1891
+ this.getConnectionVectorHandler = getConnectionVectorHandler;
1892
+ this.connection = connection;
1893
+ this.mouseDownPoint = mouseDownPoint;
1894
+ this.type = EDraggableType.CREATE_CONNECTION;
1895
+ this.onPointerDownFromConnectorRect = RectExtensions.initialize();
1896
+ this.onPointerDownToConnectorRect = RectExtensions.initialize();
1897
+ this.outputSide = EConnectorSide.BOTTOM;
1894
1898
  }
1895
- getScale() {
1896
- return this.fCanvas.transform.scale || 1;
1899
+ initialize() {
1900
+ const outputRect = this.getOutputRectInFlowHandler.handle(this.connection.outputId);
1901
+ this.outputSide = outputRect.side;
1902
+ this.onPointerDownFromConnectorRect = outputRect.rect;
1903
+ this.onPointerDownToConnectorRect = RectExtensions.initialize(this.mouseDownPoint.x, this.mouseDownPoint.y, 0, 0);
1904
+ this.connection.show();
1905
+ this.move(new Point(0, 0));
1897
1906
  }
1898
- onWheel(event) {
1899
- event.preventDefault();
1900
- if (this.fComponentsStore.fDraggable?.isDragStarted) {
1901
- return;
1902
- }
1903
- let result = this.getScale();
1904
- const direction = event.deltaY > 0 ? -1 : 1;
1905
- const step = this.step;
1906
- result = result + step * direction;
1907
- result = Math.max(this.minimum, Math.min(result, this.maximum));
1908
- const pointerPositionInFlow = new Point(event.clientX, event.clientY).elementTransform(this.flowHost);
1909
- this.fCanvas.setZoom(result, pointerPositionInFlow);
1910
- this.fCanvas.redraw();
1911
- this.fCanvas.completeDrag();
1907
+ move(difference) {
1908
+ const toPoint = RectExtensions.addPoint(this.onPointerDownToConnectorRect, difference);
1909
+ const vector = this.getConnectionVectorHandler.handle(new GetConnectionVectorRequest(this.onPointerDownFromConnectorRect, toPoint, this.connection.behavior, this.outputSide, EConnectorSide.TOP));
1910
+ this.connection.setVector(vector.point1, this.outputSide, vector.point2, EConnectorSide.TOP);
1911
+ this.connection.redraw();
1912
1912
  }
1913
- onDoubleClick(event) {
1914
- event.preventDefault();
1915
- if (this.fComponentsStore.fDraggable?.isDragStarted || isNode(event.target)) {
1916
- return;
1917
- }
1918
- let result = this.getScale();
1919
- const direction = 1;
1920
- const step = this.dblClickStep;
1921
- result = result + step * direction;
1922
- result = Math.max(this.minimum, Math.min(result, this.maximum));
1923
- const pointerPositionInFlow = new Point(event.clientX, event.clientY).elementTransform(this.flowHost);
1924
- this.fCanvas.setZoom(result, pointerPositionInFlow);
1925
- this.fCanvas.redrawWithAnimation();
1926
- this.fCanvas.completeDrag();
1913
+ complete() {
1914
+ this.connection.redraw();
1915
+ this.connection.hide();
1927
1916
  }
1928
- onZoomToCenter(deltaY, position) {
1929
- const preventDefault = () => {
1930
- };
1931
- const rect = RectExtensions.fromElement(this.flowHost);
1932
- this.onWheel({
1933
- deltaY, preventDefault, clientX: position?.x || rect.gravityCenter.x, clientY: position?.y || rect.gravityCenter.y
1934
- });
1917
+ }
1918
+
1919
+ class CreateConnectionEvent {
1920
+ constructor(outputId, inputId) {
1921
+ this.outputId = outputId;
1922
+ this.inputId = inputId;
1935
1923
  }
1936
- zoomIn(position) {
1937
- this.onZoomToCenter(-1, position);
1924
+ }
1925
+
1926
+ class FirstNotConnectedInputOfNodeUnderPointerHandler {
1927
+ get fNodes() {
1928
+ return this.fComponentsStore.fNodes;
1938
1929
  }
1939
- zoomOut(position) {
1940
- this.onZoomToCenter(1, position);
1930
+ get fInputs() {
1931
+ return this.fComponentsStore.fInputs;
1941
1932
  }
1942
- reset() {
1943
- this.fCanvas.resetZoom();
1944
- this.fCanvas.redraw();
1945
- this.fCanvas.completeDrag();
1933
+ constructor(fComponentsStore) {
1934
+ this.fComponentsStore = fComponentsStore;
1946
1935
  }
1947
- unsubscribe() {
1948
- this.listeners();
1949
- this.listeners = EventExtensions.emptyListener();
1936
+ handle(event) {
1937
+ const position = event.getPosition();
1938
+ const elementsFromPoint = document.elementsFromPoint(position.x, position.y);
1939
+ const nodes = elementsFromPoint.map((element) => {
1940
+ return this.fNodes.find((x) => x.isContains(element));
1941
+ }).filter((x) => !!x);
1942
+ const inputs = nodes.map((x) => {
1943
+ return this.fInputs.filter((i) => x.isContains(i.hostElement)).find((i) => {
1944
+ return !i.isConnected && i.canBeConnected;
1945
+ });
1946
+ });
1947
+ const result = inputs.find((x) => !!x);
1948
+ return result;
1950
1949
  }
1950
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FirstNotConnectedInputOfNodeUnderPointerHandler, deps: [{ token: FComponentsStore }], target: i0.ɵɵFactoryTarget.Injectable }); }
1951
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FirstNotConnectedInputOfNodeUnderPointerHandler }); }
1951
1952
  }
1953
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FirstNotConnectedInputOfNodeUnderPointerHandler, decorators: [{
1954
+ type: Injectable
1955
+ }], ctorParameters: () => [{ type: FComponentsStore }] });
1952
1956
 
1953
- class FZoomDirective extends FZoomBase {
1954
- get fFlowZoom() {
1955
- return this.isEnabled;
1956
- }
1957
- set fFlowZoom(isEnabled) {
1958
- const value = BooleanExtensions.castToBoolean(isEnabled);
1959
- if (value !== this.isEnabled) {
1960
- this.isEnabled = value;
1961
- this.toggleZoom();
1962
- }
1957
+ class InputsUnderPointerHandler {
1958
+ get fInputs() {
1959
+ return this.fComponentsStore.fInputs;
1963
1960
  }
1964
1961
  constructor(fComponentsStore) {
1965
- super(fComponentsStore);
1966
- this.minimum = 0.1;
1967
- this.maximum = 4;
1968
- this.step = 0.1;
1969
- this.dblClickStep = 0.5;
1970
- }
1971
- ngAfterViewInit() {
1972
- super.toggleZoom();
1962
+ this.fComponentsStore = fComponentsStore;
1973
1963
  }
1974
- ngOnDestroy() {
1975
- super.unsubscribe();
1964
+ handle(event) {
1965
+ const position = event.getPosition();
1966
+ const elementsFromPoint = document.elementsFromPoint(position.x, position.y);
1967
+ return elementsFromPoint.filter((x) => isNodeInput(x)).map((element) => {
1968
+ return this.fInputs.find((x) => x.isContains(element));
1969
+ }).filter((x) => !!x);
1976
1970
  }
1977
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FZoomDirective, deps: [{ token: FComponentsStore }], target: i0.ɵɵFactoryTarget.Directive }); }
1978
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FZoomDirective, selector: "f-canvas[fZoom]", inputs: { fFlowZoom: ["fZoom", "fFlowZoom"], minimum: ["fZoomMinimum", "minimum"], maximum: ["fZoomMaximum", "maximum"], step: ["fZoomStep", "step"], dblClickStep: ["fZoomDblClickStep", "dblClickStep"] }, host: { classAttribute: "f-zoom f-component" }, providers: [{ provide: F_ZOOM, useExisting: FZoomDirective }], exportAs: ["fComponent"], usesInheritance: true, ngImport: i0 }); }
1971
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: InputsUnderPointerHandler, deps: [{ token: FComponentsStore }], target: i0.ɵɵFactoryTarget.Injectable }); }
1972
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: InputsUnderPointerHandler }); }
1979
1973
  }
1980
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FZoomDirective, decorators: [{
1981
- type: Directive,
1982
- args: [{
1983
- selector: "f-canvas[fZoom]",
1984
- exportAs: 'fComponent',
1985
- host: {
1986
- 'class': 'f-zoom f-component'
1987
- },
1988
- providers: [{ provide: F_ZOOM, useExisting: FZoomDirective }],
1989
- }]
1990
- }], ctorParameters: () => [{ type: FComponentsStore }], propDecorators: { fFlowZoom: [{
1991
- type: Input,
1992
- args: ['fZoom']
1993
- }], minimum: [{
1994
- type: Input,
1995
- args: ['fZoomMinimum']
1996
- }], maximum: [{
1997
- type: Input,
1998
- args: ['fZoomMaximum']
1999
- }], step: [{
2000
- type: Input,
2001
- args: ['fZoomStep']
2002
- }], dblClickStep: [{
2003
- type: Input,
2004
- args: ['fZoomDblClickStep']
2005
- }] } });
1974
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: InputsUnderPointerHandler, decorators: [{
1975
+ type: Injectable
1976
+ }], ctorParameters: () => [{ type: FComponentsStore }] });
2006
1977
 
2007
- function mixinChangeZoom(base) {
2008
- return class extends base {
2009
- setZoom(scaleValue, toPosition) {
2010
- if (scaleValue !== this.transform.scale) {
2011
- const summaryPosition = PointExtensions.sum(this.transform.scaledPosition, this.transform.position);
2012
- const newX = toPosition.x - (toPosition.x - summaryPosition.x) * scaleValue / this.transform.scale;
2013
- const newY = toPosition.y - (toPosition.y - summaryPosition.y) * scaleValue / this.transform.scale;
2014
- this.transform.scale = scaleValue;
2015
- this.transform.scaledPosition = PointExtensions.sub(PointExtensions.initialize(newX, newY), this.transform.position);
2016
- }
2017
- }
2018
- setScalePosition(value) {
2019
- this.transform.scaledPosition = value;
2020
- }
2021
- resetZoom() {
2022
- this.transform.scale = 1;
2023
- this.transform.scaledPosition = PointExtensions.initialize();
2024
- }
2025
- constructor(...args) {
2026
- super(...args);
2027
- }
2028
- };
1978
+ class FindInputsUnderPointerRequest {
1979
+ constructor(event, dragHandler) {
1980
+ this.event = event;
1981
+ this.dragHandler = dragHandler;
1982
+ }
2029
1983
  }
2030
1984
 
2031
- function mixinFitToParent(base) {
2032
- return class extends base {
2033
- fitToParent(rect, parentRect, points) {
2034
- this.transform.scaledPosition = PointExtensions.initialize();
2035
- this.transform.position = this.getZeroPositionWithoutScale(points);
2036
- const itemsContainerWidth = rect.width / this.transform.scale;
2037
- const itemsContainerHeight = rect.height / this.transform.scale;
2038
- if ((itemsContainerWidth > parentRect.width || itemsContainerHeight > parentRect.height) ||
2039
- itemsContainerWidth < parentRect.width && itemsContainerHeight < parentRect.height) {
2040
- this.transform.scale = Math.min(parentRect.width / itemsContainerWidth, parentRect.height / itemsContainerHeight);
2041
- }
2042
- const newX = (parentRect.width - itemsContainerWidth * this.transform.scale) / 2 - this.transform.position.x * this.transform.scale;
2043
- const newY = (parentRect.height - itemsContainerHeight * this.transform.scale) / 2 - this.transform.position.y * this.transform.scale;
2044
- this.transform.position = PointExtensions.initialize(newX, newY);
2045
- }
2046
- getZeroPositionWithoutScale(points) {
2047
- const xPoint = points.length ? Math.min(...points.map((point) => point.x)) : 0;
2048
- const yPoint = points.length ? Math.min(...points.map((point) => point.y)) : 0;
2049
- return PointExtensions.initialize(xPoint, yPoint);
2050
- }
2051
- constructor(...args) {
2052
- super(...args);
2053
- }
2054
- };
2055
- }
2056
-
2057
- function mixinOneToOneCentering(base) {
2058
- return class extends base {
2059
- oneToOneCentering(rect, parentRect, points) {
2060
- this.transform.scaledPosition = PointExtensions.initialize();
2061
- this.transform.position = this.getZeroPositionWithoutScale(points);
2062
- const itemsContainerWidth = rect.width / this.transform.scale;
2063
- const itemsContainerHeight = rect.height / this.transform.scale;
2064
- this.transform.scale = 1;
2065
- const newX = (parentRect.width - itemsContainerWidth * this.transform.scale) / 2 - this.transform.position.x * this.transform.scale;
2066
- const newY = (parentRect.height - itemsContainerHeight * this.transform.scale) / 2 - this.transform.position.y * this.transform.scale;
2067
- this.transform.position = PointExtensions.initialize(newX, newY);
2068
- }
2069
- getZeroPositionWithoutScale(points) {
2070
- const xPoint = points.length ? Math.min(...points.map((point) => point.x)) : 0;
2071
- const yPoint = points.length ? Math.min(...points.map((point) => point.y)) : 0;
2072
- return PointExtensions.initialize(xPoint, yPoint);
1985
+ class FindInputsUnderPointerHandler {
1986
+ get fNodes() {
1987
+ return this.fComponentsStore.fNodes;
1988
+ }
1989
+ constructor(fComponentsStore, inputsUnderPointerHandler, firstNotConnectedInputOfNodeUnderPointerHandler) {
1990
+ this.fComponentsStore = fComponentsStore;
1991
+ this.inputsUnderPointerHandler = inputsUnderPointerHandler;
1992
+ this.firstNotConnectedInputOfNodeUnderPointerHandler = firstNotConnectedInputOfNodeUnderPointerHandler;
1993
+ }
1994
+ handle(payload) {
1995
+ const inputsUnderPointer = this.getInputsUnderPointer(payload);
1996
+ const output = this.fComponentsStore.fOutputs.find((x) => x.id === payload.dragHandler.connection.outputId);
1997
+ if (!output) {
1998
+ throw OutputNotFound(payload.dragHandler.connection.outputId);
2073
1999
  }
2074
- constructor(...args) {
2075
- super(...args);
2000
+ return inputsUnderPointer.filter((x) => {
2001
+ const targetNode = this.fNodes.find((y) => y.isContains(x.hostElement));
2002
+ const sourceNode = this.fNodes.find((y) => y.isContains(output.hostElement));
2003
+ return sourceNode?.hostElement !== targetNode?.hostElement;
2004
+ });
2005
+ }
2006
+ getInputsUnderPointer(payload) {
2007
+ let inputs = this.inputsUnderPointerHandler.handle(payload.event);
2008
+ const input = this.firstNotConnectedInputOfNodeUnderPointerHandler.handle(payload.event);
2009
+ if (input) {
2010
+ inputs.push(input);
2076
2011
  }
2077
- };
2012
+ inputs = inputs.filter((x) => x.canBeConnected);
2013
+ return inputs;
2014
+ }
2015
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FindInputsUnderPointerHandler, deps: [{ token: FComponentsStore }, { token: InputsUnderPointerHandler }, { token: FirstNotConnectedInputOfNodeUnderPointerHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
2016
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FindInputsUnderPointerHandler }); }
2078
2017
  }
2018
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FindInputsUnderPointerHandler, decorators: [{
2019
+ type: Injectable
2020
+ }], ctorParameters: () => [{ type: FComponentsStore }, { type: InputsUnderPointerHandler }, { type: FirstNotConnectedInputOfNodeUnderPointerHandler }] });
2079
2021
 
2080
- function mixinChangePosition(base) {
2081
- return class extends base {
2082
- getPosition() {
2083
- return this.transform.position;
2084
- }
2085
- setPosition(position) {
2086
- this.transform.position = PointExtensions.copy(position);
2087
- }
2088
- constructor(...args) {
2089
- super(...args);
2022
+ class CreateConnectionOnPointerUp {
2023
+ constructor(fComponentsStore, fDraggableDataContext, findInputsUnderPointerHandler, findFirstCanBeConnectedOutputByOutletHandler) {
2024
+ this.fComponentsStore = fComponentsStore;
2025
+ this.fDraggableDataContext = fDraggableDataContext;
2026
+ this.findInputsUnderPointerHandler = findInputsUnderPointerHandler;
2027
+ this.findFirstCanBeConnectedOutputByOutletHandler = findFirstCanBeConnectedOutputByOutletHandler;
2028
+ }
2029
+ handle(event) {
2030
+ const isCreateConnection = this.fDraggableDataContext.draggableItems.some((x) => x.type === EDraggableType.CREATE_CONNECTION);
2031
+ if (isCreateConnection) {
2032
+ const handler = this.fDraggableDataContext.draggableItems[0];
2033
+ const inputsUnderPointer = this.findInputsUnderPointerHandler.handle(new FindInputsUnderPointerRequest(event, handler));
2034
+ if (inputsUnderPointer.length > 0) {
2035
+ let output = this.fComponentsStore.fOutputs.find((x) => x.id === handler.connection.outputId);
2036
+ if (!output) {
2037
+ output = this.fComponentsStore.fOutlets.find((x) => x.id === handler.connection.outputId);
2038
+ }
2039
+ if (!output) {
2040
+ throw OutputNotFound(handler.connection.outputId);
2041
+ }
2042
+ const isOutlet = isNodeOutlet(output.hostElement);
2043
+ if (isOutlet) {
2044
+ output = this.findFirstCanBeConnectedOutputByOutletHandler.handle(output);
2045
+ if (!output) {
2046
+ throw requiredOutput();
2047
+ }
2048
+ }
2049
+ this.fComponentsStore.fDraggable?.fCreateConnection.emit(new CreateConnectionEvent(output.id, inputsUnderPointer[0]?.id));
2050
+ }
2051
+ handler.complete();
2090
2052
  }
2091
- };
2053
+ }
2054
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CreateConnectionOnPointerUp, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: FindInputsUnderPointerHandler }, { token: FindFirstCanBeConnectedOutputByOutletHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
2055
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CreateConnectionOnPointerUp }); }
2092
2056
  }
2057
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CreateConnectionOnPointerUp, decorators: [{
2058
+ type: Injectable
2059
+ }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: FindInputsUnderPointerHandler }, { type: FindFirstCanBeConnectedOutputByOutletHandler }] });
2093
2060
 
2094
- const F_CANVAS = new InjectionToken('F_CANVAS');
2095
- const MIXIN_BASE = mixinChangePosition(mixinFitToParent(mixinOneToOneCentering(mixinChangeZoom(class {
2096
- constructor(transform) {
2097
- this.transform = transform;
2061
+ class CreateConnectionPrepareDragSequence {
2062
+ get transform() {
2063
+ return this.fComponentsStore.fCanvas.transform;
2098
2064
  }
2099
- }))));
2100
- class FCanvasBase extends MIXIN_BASE {
2101
- constructor() {
2102
- super(TransformModelExtensions.default());
2065
+ get flowHost() {
2066
+ return this.fComponentsStore.fFlow.hostElement;
2103
2067
  }
2104
- completeDrag() {
2105
- const position = PointExtensions.sum(this.transform.position, this.transform.scaledPosition);
2106
- this.fCanvasChange.emit(new FCanvasChangeEvent(position, this.transform.scale));
2068
+ constructor(fComponentsStore, fDraggableDataContext, getElementRectInFlowHandler, getConnectionVectorHandler, findFirstCanBeConnectedOutputByOutletHandler, getOutputRectInFlowHandler) {
2069
+ this.fComponentsStore = fComponentsStore;
2070
+ this.fDraggableDataContext = fDraggableDataContext;
2071
+ this.getElementRectInFlowHandler = getElementRectInFlowHandler;
2072
+ this.getConnectionVectorHandler = getConnectionVectorHandler;
2073
+ this.findFirstCanBeConnectedOutputByOutletHandler = findFirstCanBeConnectedOutputByOutletHandler;
2074
+ this.getOutputRectInFlowHandler = getOutputRectInFlowHandler;
2107
2075
  }
2108
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FCanvasBase, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2109
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FCanvasBase, usesInheritance: true, ngImport: i0 }); }
2110
- }
2111
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FCanvasBase, decorators: [{
2112
- type: Directive
2113
- }], ctorParameters: () => [] });
2114
-
2115
- class FCanvasComponent extends FCanvasBase {
2116
- set position(value) {
2117
- if (!value) {
2076
+ handle(event) {
2077
+ const node = this.fComponentsStore.findNode(event.targetElement);
2078
+ const pointerPositionInFlow = Point.fromPoint(event.getPosition()).elementTransform(this.flowHost);
2079
+ if (!node || this.fDraggableDataContext.draggableItems.length || !this.fComponentsStore.fTempConnection) {
2118
2080
  return;
2119
2081
  }
2120
- const position = PointExtensions.sum(this.transform.position, this.transform.scaledPosition);
2121
- if (!PointExtensions.isEqual(position, value)) {
2122
- this.transform.position = value;
2123
- this.transform.scaledPosition = PointExtensions.initialize();
2124
- this.redraw();
2082
+ if (isNodeOutlet(event.targetElement)) {
2083
+ const outlet = this.fComponentsStore.fOutlets.find((x) => {
2084
+ return x.hostElement.contains(event.targetElement);
2085
+ });
2086
+ if (!outlet) {
2087
+ throw new Error('Outlet not found');
2088
+ }
2089
+ const nodeOutputs = this.fComponentsStore.fOutputs.filter((x) => node.isContains(x.hostElement));
2090
+ outlet.setOutputs(nodeOutputs);
2091
+ if (outlet.canBeConnected) {
2092
+ const outletCenter = this.getElementRectInFlowHandler.handle(outlet.hostElement).gravityCenter;
2093
+ if (outlet.isConnectionFromOutlet) {
2094
+ this.createConnectionHandler(pointerPositionInFlow, outlet, outletCenter);
2095
+ }
2096
+ else {
2097
+ const output = this.findFirstCanBeConnectedOutputByOutletHandler.handle(outlet);
2098
+ if (!output) {
2099
+ throw new Error('Output not found');
2100
+ }
2101
+ this.createConnectionHandler(pointerPositionInFlow, output, outletCenter);
2102
+ }
2103
+ }
2125
2104
  }
2126
- }
2127
- set scale(value) {
2128
- if (!value) {
2129
- return;
2105
+ else if (this.isNodeOutput(event.targetElement, node)) {
2106
+ const output = this.fComponentsStore.fOutputs.find((x) => {
2107
+ return x.hostElement.contains(event.targetElement);
2108
+ });
2109
+ if (!output) {
2110
+ throw new Error('Output not found');
2111
+ }
2112
+ if (output.canBeConnected) {
2113
+ const outputCenter = this.getElementRectInFlowHandler.handle(output.hostElement).gravityCenter;
2114
+ this.createConnectionHandler(pointerPositionInFlow, output, outputCenter);
2115
+ }
2130
2116
  }
2131
- this.transform.scale = value;
2132
- this.redraw();
2133
- }
2134
- get fNodes() {
2135
- return this.fComponentsStore.fNodes;
2136
2117
  }
2137
- get hostElement() {
2138
- return this.elementReference.nativeElement;
2118
+ createConnectionHandler(pointerPositionInCanvas, output, outputCenter) {
2119
+ this.fComponentsStore.fTempConnection.outputId = output.id;
2120
+ this.fComponentsStore.fTempConnection.initialize();
2121
+ this.fDraggableDataContext.onPointerDownScale = this.transform.scale;
2122
+ this.fDraggableDataContext.onPointerDownPosition = pointerPositionInCanvas.div(this.transform.scale);
2123
+ this.fDraggableDataContext.draggableItems = [
2124
+ new CreateConnectionDragHandler(this.getOutputRectInFlowHandler, this.getConnectionVectorHandler, this.fComponentsStore.fTempConnection, outputCenter)
2125
+ ];
2139
2126
  }
2140
- constructor(getAllNodesRectHandler, elementReference, fComponentsStore) {
2141
- super();
2142
- this.getAllNodesRectHandler = getAllNodesRectHandler;
2143
- this.elementReference = elementReference;
2144
- this.fComponentsStore = fComponentsStore;
2145
- this.fCanvasChange = new EventEmitter();
2127
+ isNodeOutput(targetElement, node) {
2128
+ const outlets = this.fComponentsStore.fOutlets.filter((x) => node.isContains(x.hostElement));
2129
+ return isNodeOutput(targetElement) && !outlets.length;
2146
2130
  }
2147
- ngOnInit() {
2148
- this.fComponentsStore.fCanvas = this;
2131
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CreateConnectionPrepareDragSequence, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: GetElementRectInFlowHandler }, { token: GetConnectionVectorHandler }, { token: FindFirstCanBeConnectedOutputByOutletHandler }, { token: GetOutputRectInFlowHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
2132
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CreateConnectionPrepareDragSequence }); }
2133
+ }
2134
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CreateConnectionPrepareDragSequence, decorators: [{
2135
+ type: Injectable
2136
+ }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: GetElementRectInFlowHandler }, { type: GetConnectionVectorHandler }, { type: FindFirstCanBeConnectedOutputByOutletHandler }, { type: GetOutputRectInFlowHandler }] });
2137
+
2138
+ class ReassignConnectionDragHandler {
2139
+ constructor(getInputRectInFlowHandler, getOutputRectInFlowHandler, getConnectionVectorHandler, connection) {
2140
+ this.getInputRectInFlowHandler = getInputRectInFlowHandler;
2141
+ this.getOutputRectInFlowHandler = getOutputRectInFlowHandler;
2142
+ this.getConnectionVectorHandler = getConnectionVectorHandler;
2143
+ this.connection = connection;
2144
+ this.type = EDraggableType.REASSIGN_CONNECTION;
2145
+ this.onPointerDownFromConnectorRect = RectExtensions.initialize();
2146
+ this.onPointerDownToConnectorRect = RectExtensions.initialize();
2147
+ this.outputSide = EConnectorSide.BOTTOM;
2148
+ this.inputSide = EConnectorSide.TOP;
2149
2149
  }
2150
- redraw() {
2151
- this.fComponentsStore.fBackground?.setTransform(this.transform);
2152
- this.hostElement.setAttribute("style", `transform: ${TransformModelExtensions.toString(this.transform)}`);
2150
+ initialize() {
2151
+ const fromConnector = this.getOutputRectInFlowHandler.handle(this.connection.outputId);
2152
+ this.inputSide = this.getInputRectInFlowHandler.handle(this.connection.inputId).side;
2153
+ this.outputSide = fromConnector.side;
2154
+ this.onPointerDownFromConnectorRect = fromConnector.rect;
2155
+ this.onPointerDownToConnectorRect = RectExtensions.initialize(this.connection.vector.point2.x, this.connection.vector.point2.y, 0, 0);
2153
2156
  }
2154
- redrawWithAnimation() {
2155
- this.fComponentsStore.fBackground?.setTransform(this.transform);
2156
- this.hostElement.setAttribute("style", `transition: transform 0.15s ease-in-out; transform: ${TransformModelExtensions.toString(this.transform)}`);
2157
- setTimeout(() => {
2158
- this.redraw();
2159
- }, 150);
2160
- }
2161
- fitToScreen(toCenter = PointExtensions.initialize(), animated = true) {
2162
- const fNodesRect = this.getAllNodesRectHandler.handle();
2163
- const rect = RectExtensions.addPointToSize(fNodesRect, Point.fromPoint(toCenter).mult(2));
2164
- this.fitToParent(rect, RectExtensions.fromElement(this.fComponentsStore.fFlow.hostElement), this.fNodes.map((x) => {
2165
- return Point.fromPoint(x.position).sub(toCenter);
2166
- }));
2167
- animated ? this.redrawWithAnimation() : this.redraw();
2168
- this.completeDrag();
2169
- }
2170
- oneToOne() {
2171
- const fNodesRect = this.getAllNodesRectHandler.handle();
2172
- this.oneToOneCentering(fNodesRect, RectExtensions.fromElement(this.fComponentsStore.fFlow.hostElement), this.fNodes.map((x) => {
2173
- return Point.fromPoint(x.position).sub(new Point(0, 0));
2174
- }));
2175
- this.redrawWithAnimation();
2176
- this.completeDrag();
2177
- }
2178
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FCanvasComponent, deps: [{ token: GetAllNodesRectHandler }, { token: i0.ElementRef }, { token: FComponentsStore }], target: i0.ɵɵFactoryTarget.Component }); }
2179
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.9", type: FCanvasComponent, selector: "f-canvas", inputs: { position: "position", scale: "scale" }, outputs: { fCanvasChange: "fCanvasChange" }, host: { classAttribute: "f-component f-canvas" }, providers: [{ provide: F_CANVAS, useExisting: FCanvasComponent }], viewQueries: [{ propertyName: "fNodesContainer", first: true, predicate: ["fNodesContainer"], descendants: true, static: true }], exportAs: ["fComponent"], usesInheritance: true, ngImport: i0, template: "<ng-container>\n <div>\n <ng-content select=\"f-connection\"></ng-content>\n <ng-content select=\"f-connection-for-create\"></ng-content>\n </div>\n <div #fNodesContainer>\n <ng-content select=\"f-node\"></ng-content>\n </div>\n</ng-container>\n", styles: [":host{position:absolute;overflow:visible;width:100%;height:100%;left:0;top:0;transform-origin:0 0;pointer-events:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2180
- }
2181
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FCanvasComponent, decorators: [{
2182
- type: Component,
2183
- args: [{ selector: 'f-canvas', exportAs: 'fComponent', host: {
2184
- 'class': 'f-component f-canvas',
2185
- }, providers: [{ provide: F_CANVAS, useExisting: FCanvasComponent }], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container>\n <div>\n <ng-content select=\"f-connection\"></ng-content>\n <ng-content select=\"f-connection-for-create\"></ng-content>\n </div>\n <div #fNodesContainer>\n <ng-content select=\"f-node\"></ng-content>\n </div>\n</ng-container>\n", styles: [":host{position:absolute;overflow:visible;width:100%;height:100%;left:0;top:0;transform-origin:0 0;pointer-events:none}\n"] }]
2186
- }], ctorParameters: () => [{ type: GetAllNodesRectHandler }, { type: i0.ElementRef }, { type: FComponentsStore }], propDecorators: { fCanvasChange: [{
2187
- type: Output
2188
- }], position: [{
2189
- type: Input
2190
- }], scale: [{
2191
- type: Input
2192
- }], fNodesContainer: [{
2193
- type: ViewChild,
2194
- args: ['fNodesContainer', { static: true }]
2195
- }] } });
2196
-
2197
- const F_FLOW = new InjectionToken('F_FLOW');
2198
-
2199
- var EDraggableType;
2200
- (function (EDraggableType) {
2201
- EDraggableType["NODE"] = "node";
2202
- EDraggableType["REASSIGN_CONNECTION"] = "reassign-connection";
2203
- EDraggableType["CREATE_CONNECTION"] = "create-connection";
2204
- EDraggableType["CONNECTION"] = "connection";
2205
- EDraggableType["CANVAS"] = "canvas";
2206
- EDraggableType["PALETTE_ITEM"] = "palette-item";
2207
- EDraggableType["SELECTION"] = "selection";
2208
- })(EDraggableType || (EDraggableType = {}));
2209
-
2210
- class CanvasDragHandler {
2211
- constructor(fComponentsStore) {
2212
- this.fComponentsStore = fComponentsStore;
2213
- this.type = EDraggableType.CANVAS;
2214
- this.onPointerDownPosition = PointExtensions.initialize();
2215
- }
2216
- initialize() {
2217
- this.onPointerDownPosition = this.fComponentsStore.fCanvas.transform.position;
2218
- }
2219
- move(difference) {
2220
- this.fComponentsStore.fCanvas.setPosition(Point.fromPoint(this.onPointerDownPosition).add(difference));
2221
- this.fComponentsStore.fCanvas.redraw();
2157
+ move(difference) {
2158
+ const toRect = RectExtensions.addPoint(this.onPointerDownToConnectorRect, difference);
2159
+ const vector = this.getConnectionVectorHandler.handle(new GetConnectionVectorRequest(this.onPointerDownFromConnectorRect, toRect, this.connection.behavior, this.outputSide, this.inputSide));
2160
+ this.connection.setVector(vector.point1, this.outputSide, vector.point2, this.inputSide);
2161
+ this.connection.redraw();
2222
2162
  }
2223
2163
  complete() {
2224
- this.fComponentsStore.fCanvas.completeDrag();
2164
+ const fromConnector = this.getOutputRectInFlowHandler.handle(this.connection.outputId);
2165
+ const toConnector = this.getInputRectInFlowHandler.handle(this.connection.inputId);
2166
+ const vector = this.getConnectionVectorHandler.handle(new GetConnectionVectorRequest(fromConnector.rect, toConnector.rect, this.connection.behavior, fromConnector.side, toConnector.side));
2167
+ this.connection.setVector(vector.point1, fromConnector.side, vector.point2, toConnector.side);
2168
+ this.connection.redraw();
2225
2169
  }
2226
2170
  }
2227
2171
 
2228
- class FDraggableDataContext {
2229
- constructor() {
2230
- this.selectedItems = [];
2231
- this.onPointerDownScale = 1;
2232
- this.onPointerDownPosition = new Point(0, 0);
2233
- this.draggableItems = [];
2234
- }
2235
- reset() {
2236
- this.draggableItems = [];
2237
- this.onPointerDownScale = 1;
2238
- this.onPointerDownPosition = new Point(0, 0);
2172
+ class ReassignConnectionEvent {
2173
+ constructor(connectionId, outputId, oldInputId, newInputId) {
2174
+ this.connectionId = connectionId;
2175
+ this.outputId = outputId;
2176
+ this.oldInputId = oldInputId;
2177
+ this.newInputId = newInputId;
2239
2178
  }
2240
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FDraggableDataContext, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2241
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FDraggableDataContext }); }
2242
2179
  }
2243
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FDraggableDataContext, decorators: [{
2244
- type: Injectable
2245
- }] });
2246
2180
 
2247
- class CanvasOnPointerUp {
2248
- constructor(fDraggableDataContext) {
2181
+ class ReassignConnectionOnPointerUp {
2182
+ get fDraggable() {
2183
+ return this.fComponentsStore.fDraggable;
2184
+ }
2185
+ constructor(fComponentsStore, fDraggableDataContext, findInputsUnderPointerHandler) {
2186
+ this.fComponentsStore = fComponentsStore;
2249
2187
  this.fDraggableDataContext = fDraggableDataContext;
2188
+ this.findInputsUnderPointerHandler = findInputsUnderPointerHandler;
2250
2189
  }
2251
2190
  handle(event) {
2252
- const isDragCanvas = this.fDraggableDataContext.draggableItems.some((x) => x.type === EDraggableType.CANVAS);
2253
- if (isDragCanvas) {
2254
- this.fDraggableDataContext.draggableItems.forEach((x) => {
2255
- x.complete?.();
2256
- });
2191
+ const isReassignConnection = this.fDraggableDataContext.draggableItems.some((x) => x.type === EDraggableType.REASSIGN_CONNECTION);
2192
+ if (isReassignConnection) {
2193
+ const handler = this.fDraggableDataContext.draggableItems[0];
2194
+ const inputsUnderPointer = this.findInputsUnderPointerHandler.handle(new FindInputsUnderPointerRequest(event, handler));
2195
+ if (inputsUnderPointer.length > 0) {
2196
+ if (handler.connection.inputId !== inputsUnderPointer[0]?.id) {
2197
+ this.fDraggable.fReassignConnection.emit(new ReassignConnectionEvent(handler.connection.id, handler.connection.outputId, handler.connection.inputId, inputsUnderPointer[0]?.id));
2198
+ }
2199
+ }
2200
+ handler.complete();
2257
2201
  }
2258
2202
  }
2259
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CanvasOnPointerUp, deps: [{ token: FDraggableDataContext }], target: i0.ɵɵFactoryTarget.Injectable }); }
2260
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CanvasOnPointerUp }); }
2203
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ReassignConnectionOnPointerUp, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: FindInputsUnderPointerHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
2204
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ReassignConnectionOnPointerUp }); }
2261
2205
  }
2262
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CanvasOnPointerUp, decorators: [{
2206
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ReassignConnectionOnPointerUp, decorators: [{
2263
2207
  type: Injectable
2264
- }], ctorParameters: () => [{ type: FDraggableDataContext }] });
2208
+ }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: FindInputsUnderPointerHandler }] });
2265
2209
 
2266
- class CanvasPrepareDragSequence {
2210
+ class ReassignConnectionPrepareDragSequence {
2211
+ get transform() {
2212
+ return this.fComponentsStore.fCanvas.transform;
2213
+ }
2267
2214
  get flowHost() {
2268
2215
  return this.fComponentsStore.fFlow.hostElement;
2269
2216
  }
2270
- constructor(fComponentsStore, fDraggableDataContext) {
2217
+ constructor(fComponentsStore, fDraggableDataContext, getConnectionHandler, getInputRectInFlowHandler, getOutputRectInFlowHandler, getConnectionVectorHandler) {
2271
2218
  this.fComponentsStore = fComponentsStore;
2272
2219
  this.fDraggableDataContext = fDraggableDataContext;
2220
+ this.getConnectionHandler = getConnectionHandler;
2221
+ this.getInputRectInFlowHandler = getInputRectInFlowHandler;
2222
+ this.getOutputRectInFlowHandler = getOutputRectInFlowHandler;
2223
+ this.getConnectionVectorHandler = getConnectionVectorHandler;
2273
2224
  }
2274
2225
  handle(event) {
2275
2226
  const pointerPositionInFlow = Point.fromPoint(event.getPosition()).elementTransform(this.flowHost);
2276
- const isBackgroundElement = this.fComponentsStore.fBackground?.isBackgroundElement(event.targetElement);
2277
- const isFlowHost = this.flowHost.contains(event.targetElement);
2278
- let node = this.fComponentsStore.findNode(event.targetElement);
2279
- if (node && node.disabled) {
2280
- node = undefined;
2227
+ const position = event.getPosition();
2228
+ const allElements = document.elementsFromPoint(position.x, position.y);
2229
+ const dragHandlesOfConnections = allElements.filter((x) => {
2230
+ return !!this.getConnectionHandler.handle(x) && x.classList.contains(F_CONNECTION_DRAG_HANDLE_CLASS);
2231
+ });
2232
+ let connectionToReassign;
2233
+ if (dragHandlesOfConnections.length) {
2234
+ const connections = dragHandlesOfConnections.map((x) => this.getConnectionHandler.handle(x)).filter((x) => !x?.disabled);
2235
+ if (connections.length) {
2236
+ connectionToReassign = this.getConnectionHandler.handle(dragHandlesOfConnections[0]);
2237
+ }
2281
2238
  }
2282
- if ((isBackgroundElement || (isFlowHost && !node)) && !this.fDraggableDataContext.draggableItems.length) {
2283
- this.fDraggableDataContext.onPointerDownScale = 1;
2284
- this.fDraggableDataContext.onPointerDownPosition = pointerPositionInFlow.div(1);
2239
+ if (connectionToReassign && !this.fDraggableDataContext.draggableItems.length) {
2240
+ this.fDraggableDataContext.onPointerDownScale = this.transform.scale;
2241
+ this.fDraggableDataContext.onPointerDownPosition = pointerPositionInFlow.div(this.transform.scale);
2285
2242
  this.fDraggableDataContext.draggableItems = [
2286
- new CanvasDragHandler(this.fComponentsStore)
2243
+ new ReassignConnectionDragHandler(this.getInputRectInFlowHandler, this.getOutputRectInFlowHandler, this.getConnectionVectorHandler, connectionToReassign)
2287
2244
  ];
2288
2245
  }
2289
2246
  }
2290
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CanvasPrepareDragSequence, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }], target: i0.ɵɵFactoryTarget.Injectable }); }
2291
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CanvasPrepareDragSequence }); }
2247
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ReassignConnectionPrepareDragSequence, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: GetConnectionHandler }, { token: GetInputRectInFlowHandler }, { token: GetOutputRectInFlowHandler }, { token: GetConnectionVectorHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
2248
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ReassignConnectionPrepareDragSequence }); }
2292
2249
  }
2293
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CanvasPrepareDragSequence, decorators: [{
2250
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ReassignConnectionPrepareDragSequence, decorators: [{
2294
2251
  type: Injectable
2295
- }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }] });
2252
+ }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: GetConnectionHandler }, { type: GetInputRectInFlowHandler }, { type: GetOutputRectInFlowHandler }, { type: GetConnectionVectorHandler }] });
2296
2253
 
2297
- const CANVAS_PROVIDERS = [
2298
- CanvasOnPointerUp,
2299
- CanvasPrepareDragSequence
2254
+ const CONNECTIONS_PROVIDERS = [
2255
+ FindFirstCanBeConnectedOutputByOutletHandler,
2256
+ CreateConnectionOnPointerUp,
2257
+ CreateConnectionPrepareDragSequence,
2258
+ FirstNotConnectedInputOfNodeUnderPointerHandler,
2259
+ InputsUnderPointerHandler,
2260
+ FindInputsUnderPointerHandler,
2261
+ ReassignConnectionOnPointerUp,
2262
+ ReassignConnectionPrepareDragSequence
2300
2263
  ];
2301
2264
 
2302
- const F_EXTERNAL_ITEM = new InjectionToken('F_EXTERNAL_ITEM');
2303
- class FExternalItemBase {
2304
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FExternalItemBase, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2305
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FExternalItemBase, ngImport: i0 }); }
2306
- }
2307
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FExternalItemBase, decorators: [{
2308
- type: Directive
2309
- }] });
2310
-
2311
- function isExternalItem(element) {
2312
- return !!element.closest('[fExternalItem]');
2313
- }
2314
- function getExternalItem(element) {
2315
- return element.closest('[fExternalItem]');
2265
+ class CreateNodeEvent {
2266
+ constructor(rect, data) {
2267
+ this.rect = rect;
2268
+ this.data = data;
2269
+ }
2316
2270
  }
2317
2271
 
2318
- class FExternalItemService {
2319
- constructor() {
2320
- this.items = [];
2272
+ class ExternalItemDragHandler {
2273
+ constructor(externalItem) {
2274
+ this.externalItem = externalItem;
2275
+ this.type = EDraggableType.PALETTE_ITEM;
2276
+ this.onPointerDownRect = RectExtensions.initialize();
2277
+ this.difference = PointExtensions.initialize();
2321
2278
  }
2322
- registerItem(item) {
2323
- this.items.push(item);
2279
+ getStyle(position) {
2280
+ return `position: absolute; left: 0; top: 0; transform: translate(${position.x}px, ${position.y}px)`;
2324
2281
  }
2325
- getItem(element) {
2326
- return this.items.find(item => item.hostElement === element);
2282
+ initialize() {
2283
+ this.onPointerDownRect = this.getExternalItemRect();
2284
+ this.placeholder = DomElementExtensions.deepCloneNode(this.externalItem.hostElement);
2285
+ document.body.appendChild(this.placeholder);
2327
2286
  }
2328
- removeItem(item) {
2329
- const index = this.items.indexOf(item);
2330
- if (index !== -1) {
2331
- this.items.splice(index, 1);
2332
- }
2287
+ getExternalItemRect() {
2288
+ const rect = this.externalItem.hostElement.getBoundingClientRect();
2289
+ const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
2290
+ const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
2291
+ const offsetTop = rect.top + scrollTop;
2292
+ const offsetLeft = rect.left + scrollLeft;
2293
+ return RectExtensions.initialize(offsetLeft, offsetTop, rect.width, rect.height);
2294
+ }
2295
+ move(difference) {
2296
+ this.difference = difference;
2297
+ const position = Point.fromPoint(this.onPointerDownRect).add(this.difference);
2298
+ this.placeholder.setAttribute('style', this.getStyle(position));
2299
+ }
2300
+ getPlaceholderRect() {
2301
+ return RectExtensions.fromElement(this.placeholder);
2302
+ }
2303
+ complete() {
2304
+ document.body.removeChild(this.placeholder);
2333
2305
  }
2334
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FExternalItemService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2335
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FExternalItemService, providedIn: 'root' }); }
2336
2306
  }
2337
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FExternalItemService, decorators: [{
2338
- type: Injectable,
2339
- args: [{
2340
- providedIn: 'root'
2341
- }]
2342
- }] });
2343
2307
 
2344
- let uniqueId$1 = 0;
2345
- class FExternalItemDirective extends FExternalItemBase {
2346
- get hostElement() {
2347
- return this.elementReference.nativeElement;
2308
+ class ExternalItemPrepareDragSequence {
2309
+ get transform() {
2310
+ return this.fComponentsStore.fCanvas.transform;
2348
2311
  }
2349
- constructor(elementReference, fExternalItemService) {
2350
- super();
2351
- this.elementReference = elementReference;
2352
- this.fExternalItemService = fExternalItemService;
2353
- this.id = `f-external-item-${uniqueId$1++}`;
2312
+ get flowHost() {
2313
+ return this.fComponentsStore.fFlow.hostElement;
2354
2314
  }
2355
- ngOnInit() {
2356
- this.fExternalItemService.registerItem(this);
2315
+ constructor(fComponentsStore, fDraggableDataContext, fExternalItemService) {
2316
+ this.fComponentsStore = fComponentsStore;
2317
+ this.fDraggableDataContext = fDraggableDataContext;
2318
+ this.fExternalItemService = fExternalItemService;
2357
2319
  }
2358
- ngOnDestroy() {
2359
- this.fExternalItemService.removeItem(this);
2320
+ handle(event) {
2321
+ if (isExternalItem(event.targetElement)) {
2322
+ const item = this.fExternalItemService.getItem(getExternalItem(event.targetElement));
2323
+ if (!item) {
2324
+ throw new Error('External item not found');
2325
+ }
2326
+ const pointerPositionInFlow = Point.fromPoint(event.getPosition()).elementTransform(this.flowHost);
2327
+ this.fDraggableDataContext.onPointerDownScale = 1;
2328
+ this.fDraggableDataContext.onPointerDownPosition = pointerPositionInFlow.div(1);
2329
+ this.fDraggableDataContext.draggableItems = [
2330
+ new ExternalItemDragHandler(item)
2331
+ ];
2332
+ }
2360
2333
  }
2361
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FExternalItemDirective, deps: [{ token: i0.ElementRef }, { token: FExternalItemService }], target: i0.ɵɵFactoryTarget.Directive }); }
2362
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FExternalItemDirective, selector: "[fExternalItem]", inputs: { id: "id", data: "data" }, host: { properties: { "attr.id": "id" }, classAttribute: "f-component f-external-item" }, providers: [
2363
- { provide: F_EXTERNAL_ITEM, useExisting: FExternalItemDirective }
2364
- ], usesInheritance: true, ngImport: i0 }); }
2334
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ExternalItemPrepareDragSequence, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: FExternalItemService }], target: i0.ɵɵFactoryTarget.Injectable }); }
2335
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ExternalItemPrepareDragSequence }); }
2365
2336
  }
2366
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FExternalItemDirective, decorators: [{
2367
- type: Directive,
2368
- args: [{
2369
- selector: "[fExternalItem]",
2370
- host: {
2371
- '[attr.id]': 'id',
2372
- class: "f-component f-external-item",
2373
- },
2374
- providers: [
2375
- { provide: F_EXTERNAL_ITEM, useExisting: FExternalItemDirective }
2376
- ],
2377
- }]
2378
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: FExternalItemService }], propDecorators: { id: [{
2379
- type: Input
2380
- }], data: [{
2381
- type: Input
2382
- }] } });
2337
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ExternalItemPrepareDragSequence, decorators: [{
2338
+ type: Injectable
2339
+ }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: FExternalItemService }] });
2383
2340
 
2384
- class LineElement {
2385
- constructor(hostElement) {
2386
- this.hostElement = hostElement;
2387
- this.element = DomElementExtensions.createHtmlElement('div');
2388
- this.hostElement.appendChild(this.element);
2389
- this.element.classList.add('f-line');
2341
+ class ExternalItemOnPointerUp {
2342
+ get flowHost() {
2343
+ return this.fComponentsStore.fFlow.hostElement;
2390
2344
  }
2391
- hide() {
2392
- this.element.style.display = 'none';
2345
+ get fCreateNode() {
2346
+ return this.fComponentsStore.fDraggable.fCreateNode;
2393
2347
  }
2394
- show() {
2395
- this.element.style.display = 'block';
2348
+ constructor(fComponentsStore, fDraggableDataContext, getElementRectInFlowHandler) {
2349
+ this.fComponentsStore = fComponentsStore;
2350
+ this.fDraggableDataContext = fDraggableDataContext;
2351
+ this.getElementRectInFlowHandler = getElementRectInFlowHandler;
2396
2352
  }
2397
- draw(object) {
2398
- this.element.style.position = 'absolute';
2399
- Object.keys(object).forEach((key) => {
2400
- // @ts-ignore
2401
- this.element.style[key] = object[key] + 'px';
2402
- });
2353
+ handle(event) {
2354
+ const pointerPositionInFlow = Point.fromPoint(event.getPosition()).elementTransform(this.flowHost);
2355
+ let difference = pointerPositionInFlow.div(this.fDraggableDataContext.onPointerDownScale).sub(this.fDraggableDataContext.onPointerDownPosition);
2356
+ const isDragPaletteItem = this.fDraggableDataContext.draggableItems.some((x) => x.type === EDraggableType.PALETTE_ITEM);
2357
+ if (isDragPaletteItem) {
2358
+ const dragHandler = this.fDraggableDataContext.draggableItems[0];
2359
+ dragHandler.move(difference);
2360
+ const isPointerInCanvasRect = document.elementsFromPoint(event.getPosition().x, event.getPosition().y).some((x) => x === this.flowHost);
2361
+ if (isPointerInCanvasRect) {
2362
+ const rectInCanvas = this.getElementRectInFlowHandler.handle(dragHandler.placeholder);
2363
+ this.fCreateNode.emit(new CreateNodeEvent(rectInCanvas, dragHandler.externalItem.data));
2364
+ }
2365
+ dragHandler.complete();
2366
+ }
2403
2367
  }
2368
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ExternalItemOnPointerUp, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: GetElementRectInFlowHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
2369
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ExternalItemOnPointerUp }); }
2404
2370
  }
2371
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ExternalItemOnPointerUp, decorators: [{
2372
+ type: Injectable
2373
+ }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: GetElementRectInFlowHandler }] });
2405
2374
 
2406
- class LineService {
2407
- constructor(hostElement) {
2408
- this.hostElement = hostElement;
2409
- this.fHorizontalLine = new LineElement(this.hostElement);
2410
- this.fVerticalLine = new LineElement(this.hostElement);
2411
- }
2412
- drawVerticalLine(x, size, transform) {
2413
- this.fVerticalLine.show();
2414
- this.fVerticalLine.draw({
2415
- left: x * transform.scale + transform.position.x + transform.scaledPosition.x,
2416
- top: 0,
2417
- width: 1,
2418
- height: size.height
2419
- });
2420
- }
2421
- drawHorizontalLine(y, size, transform) {
2422
- this.fHorizontalLine.show();
2423
- this.fHorizontalLine.draw({
2424
- left: 0,
2425
- top: y * transform.scale + transform.position.y + transform.scaledPosition.y,
2426
- width: size.width,
2427
- height: 1
2428
- });
2375
+ const EXTERNAL_ITEM_PROVIDERS = [
2376
+ ExternalItemOnPointerUp,
2377
+ ExternalItemPrepareDragSequence
2378
+ ];
2379
+
2380
+ class ConnectionDragHandler {
2381
+ constructor(getInputRectInFlowHandler, getOutputRectInFlowHandler, getConnectionVectorHandler, connection) {
2382
+ this.getInputRectInFlowHandler = getInputRectInFlowHandler;
2383
+ this.getOutputRectInFlowHandler = getOutputRectInFlowHandler;
2384
+ this.getConnectionVectorHandler = getConnectionVectorHandler;
2385
+ this.connection = connection;
2386
+ this.type = EDraggableType.CONNECTION;
2387
+ this.onPointerDownVector = VectorExtensions.initialize();
2388
+ this.fromConnectorSide = EConnectorSide.BOTTOM;
2389
+ this.toConnectorSide = EConnectorSide.TOP;
2429
2390
  }
2430
- hideVerticalLine() {
2431
- this.fVerticalLine.hide();
2391
+ initialize() {
2392
+ const fromConnector = this.getOutputRectInFlowHandler.handle(this.connection.outputId);
2393
+ this.fromConnectorSide = fromConnector.side;
2394
+ const toConnector = this.getInputRectInFlowHandler.handle(this.connection.inputId);
2395
+ this.toConnectorSide = toConnector.side;
2396
+ this.onPointerDownVector = this.getConnectionVectorHandler.handle(new GetConnectionVectorRequest(fromConnector.rect, toConnector.rect, this.connection.behavior, fromConnector.side, toConnector.side));
2432
2397
  }
2433
- hideHorizontalLine() {
2434
- this.fHorizontalLine.hide();
2398
+ move(difference) {
2399
+ const fromPoint = Point.fromPoint(this.onPointerDownVector.point1).add(difference);
2400
+ const toPoint = Point.fromPoint(this.onPointerDownVector.point2).add(difference);
2401
+ this.connection.setVector(fromPoint, this.fromConnectorSide, toPoint, this.toConnectorSide);
2402
+ this.connection.redraw();
2435
2403
  }
2436
2404
  }
2437
2405
 
2438
- const ALIGN_THRESHOLD = 10;
2439
- /**
2440
- * A class to find the nearest coordinate.
2441
- */
2442
- class NearestCoordinateFinder {
2443
- /**
2444
- * Constructor to initialize the NearestCoordinateFinder.
2445
- * @param elements - The array of IRect elements.
2446
- * @param target - The target IRect element.
2447
- */
2448
- constructor(elements, target) {
2449
- this.elements = elements;
2450
- this.target = target;
2406
+ class ConnectionSourceDragHandler {
2407
+ constructor(getInputRectInFlowHandler, getOutputRectInFlowHandler, getConnectionVectorHandler, connection) {
2408
+ this.getInputRectInFlowHandler = getInputRectInFlowHandler;
2409
+ this.getOutputRectInFlowHandler = getOutputRectInFlowHandler;
2410
+ this.getConnectionVectorHandler = getConnectionVectorHandler;
2411
+ this.connection = connection;
2412
+ this.type = EDraggableType.CONNECTION;
2413
+ this.fromConnectorRect = RectExtensions.initialize();
2414
+ this.fromConnectorSide = EConnectorSide.BOTTOM;
2415
+ this.toConnectorRect = RectExtensions.initialize();
2416
+ this.toConnectorSide = EConnectorSide.TOP;
2451
2417
  }
2452
- /**
2453
- * Finds the nearest coordinate on a specified axis.
2454
- * @returns The nearest coordinate and its distance.
2455
- */
2456
- findNearestCoordinateByX() {
2457
- let nearest;
2458
- let minDistance;
2459
- for (const element of this.elements) {
2460
- const distanceLeftLeft = this.target.x - element.x;
2461
- const distanceLeftRight = this.target.x - (element.x + element.width);
2462
- const distanceCenterCenter = this.target.gravityCenter.x - element.gravityCenter.x;
2463
- const distanceRightLeft = (this.target.x + this.target.width) - element.x;
2464
- const distanceRightRight = (this.target.x + this.target.width) - (element.x + element.width);
2465
- if (Math.abs(distanceLeftLeft) <= ALIGN_THRESHOLD ||
2466
- Math.abs(distanceLeftRight) <= ALIGN_THRESHOLD ||
2467
- Math.abs(distanceCenterCenter) <= ALIGN_THRESHOLD ||
2468
- Math.abs(distanceRightLeft) <= ALIGN_THRESHOLD ||
2469
- Math.abs(distanceRightRight) <= ALIGN_THRESHOLD) {
2470
- if (minDistance === undefined || Math.abs(distanceCenterCenter) < Math.abs(minDistance)) {
2471
- minDistance = distanceCenterCenter;
2472
- nearest = element.gravityCenter.x;
2473
- }
2474
- if (Math.abs(distanceLeftLeft) < Math.abs(minDistance)) {
2475
- minDistance = distanceLeftLeft;
2476
- nearest = element.x;
2477
- }
2478
- if (Math.abs(distanceRightRight) < Math.abs(minDistance)) {
2479
- minDistance = distanceRightRight;
2480
- nearest = element.x + element.width;
2481
- }
2482
- if (Math.abs(distanceLeftRight) < Math.abs(minDistance)) {
2483
- minDistance = distanceLeftRight;
2484
- nearest = element.x + element.width;
2485
- }
2486
- if (Math.abs(distanceRightLeft) < Math.abs(minDistance)) {
2487
- minDistance = distanceRightLeft;
2488
- nearest = element.x;
2489
- }
2490
- }
2491
- }
2492
- return { value: nearest, distance: minDistance };
2418
+ initialize() {
2419
+ const fromConnector = this.getOutputRectInFlowHandler.handle(this.connection.outputId);
2420
+ this.fromConnectorRect = fromConnector.rect;
2421
+ this.fromConnectorSide = fromConnector.side;
2422
+ const toConnector = this.getInputRectInFlowHandler.handle(this.connection.inputId);
2423
+ this.toConnectorRect = toConnector.rect;
2424
+ this.toConnectorSide = toConnector.side;
2493
2425
  }
2494
- /**
2495
- * Finds the nearest coordinate on a specified axis.
2496
- * @returns The nearest coordinate and its distance.
2497
- */
2498
- findNearestCoordinateByY() {
2499
- let nearest;
2500
- let minDistance;
2501
- for (const element of this.elements) {
2502
- const distanceTopTop = this.target.y - element.y;
2503
- const distanceTopBottom = this.target.y - (element.y + element.height);
2504
- const distanceCenterCenter = this.target.gravityCenter.y - element.gravityCenter.y;
2505
- const distanceBottomTop = (this.target.y + this.target.height) - element.y;
2506
- const distanceBottomBottom = (this.target.y + this.target.height) - (element.y + element.height);
2507
- if (Math.abs(distanceTopTop) <= ALIGN_THRESHOLD ||
2508
- Math.abs(distanceTopBottom) <= ALIGN_THRESHOLD ||
2509
- Math.abs(distanceCenterCenter) <= ALIGN_THRESHOLD ||
2510
- Math.abs(distanceBottomTop) <= ALIGN_THRESHOLD ||
2511
- Math.abs(distanceBottomBottom) <= ALIGN_THRESHOLD) {
2512
- if (minDistance === undefined || Math.abs(distanceCenterCenter) < Math.abs(minDistance)) {
2513
- minDistance = distanceCenterCenter;
2514
- nearest = element.gravityCenter.y;
2515
- }
2516
- if (Math.abs(distanceTopTop) < Math.abs(minDistance)) {
2517
- minDistance = distanceTopTop;
2518
- nearest = element.y;
2519
- }
2520
- if (Math.abs(distanceBottomBottom) < Math.abs(minDistance)) {
2521
- minDistance = distanceBottomBottom;
2522
- nearest = element.y + element.height;
2523
- }
2524
- if (Math.abs(distanceTopBottom) < Math.abs(minDistance)) {
2525
- minDistance = distanceTopBottom;
2526
- nearest = element.y + element.height;
2527
- }
2528
- if (Math.abs(distanceBottomTop) < Math.abs(minDistance)) {
2529
- minDistance = distanceBottomTop;
2530
- nearest = element.y;
2531
- }
2532
- }
2533
- }
2534
- return { value: nearest, distance: minDistance };
2426
+ move(difference) {
2427
+ const fromConnectorRect = RectExtensions.addPoint(this.fromConnectorRect, difference);
2428
+ const vector = this.getConnectionVectorHandler.handle(new GetConnectionVectorRequest(fromConnectorRect, this.toConnectorRect, this.connection.behavior, this.fromConnectorSide, this.toConnectorSide));
2429
+ this.connection.setVector(vector.point1, this.fromConnectorSide, vector.point2, this.toConnectorSide);
2430
+ this.connection.redraw();
2535
2431
  }
2536
2432
  }
2537
2433
 
2538
- const F_LINE_ALIGNMENT = new InjectionToken('F_LINE_ALIGNMENT');
2539
- class FLineAlignmentBase {
2540
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FLineAlignmentBase, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2541
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FLineAlignmentBase, ngImport: i0 }); }
2542
- }
2543
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FLineAlignmentBase, decorators: [{
2544
- type: Directive
2545
- }] });
2546
-
2547
- class FLineAlignmentComponent extends FLineAlignmentBase {
2548
- get hostElement() {
2549
- return this.elementReference.nativeElement;
2550
- }
2551
- get transform() {
2552
- return this.fComponentsStore.fCanvas.transform;
2553
- }
2554
- get flowHost() {
2555
- return this.fComponentsStore.fFlow.hostElement;
2556
- }
2557
- constructor(elementReference, fComponentsStore, fDraggableDataContext, getElementRectInFlowHandler) {
2558
- super();
2559
- this.elementReference = elementReference;
2560
- this.fComponentsStore = fComponentsStore;
2561
- this.fDraggableDataContext = fDraggableDataContext;
2562
- this.getElementRectInFlowHandler = getElementRectInFlowHandler;
2563
- this.size = SizeExtensions.initialize();
2564
- this.draggedNodeRect = RectExtensions.initialize();
2565
- this.rects = [];
2566
- this.lineService = new LineService(this.hostElement);
2567
- }
2568
- ngOnInit() {
2569
- this.fDraggableDataContext.fLineAlignment = this;
2570
- }
2571
- initialize(allNodes, currentNodes) {
2572
- this.size = this.flowHost.getBoundingClientRect();
2573
- this.rects = [];
2574
- const draggedNodeRects = currentNodes.map((x) => {
2575
- return this.getElementRectInFlowHandler.handle(x.hostElement);
2576
- });
2577
- this.draggedNodeRect = RectExtensions.union(draggedNodeRects);
2578
- const allNodesExcludeCurrents = allNodes.filter((x) => {
2579
- return !currentNodes.includes(x);
2580
- });
2581
- this.rects = allNodesExcludeCurrents.map((x) => {
2582
- return this.getElementRectInFlowHandler.handle(x.hostElement);
2583
- });
2584
- }
2585
- handle(difference) {
2586
- this.drawIntersectingLines(difference);
2587
- }
2588
- drawIntersectingLines(difference) {
2589
- const intersect = this.findNearestCoordinate(difference);
2590
- if (intersect.xResult.value !== undefined) {
2591
- this.lineService.drawVerticalLine(intersect.xResult.value, this.size, this.transform);
2592
- }
2593
- else {
2594
- this.lineService.hideVerticalLine();
2595
- }
2596
- if (intersect.yResult.value !== undefined) {
2597
- this.lineService.drawHorizontalLine(intersect.yResult.value, this.size, this.transform);
2598
- }
2599
- else {
2600
- this.lineService.hideHorizontalLine();
2601
- }
2434
+ class ConnectionTargetDragHandler {
2435
+ constructor(getInputRectInFlowHandler, getOutputRectInFlowHandler, getConnectionVectorHandler, connection) {
2436
+ this.getInputRectInFlowHandler = getInputRectInFlowHandler;
2437
+ this.getOutputRectInFlowHandler = getOutputRectInFlowHandler;
2438
+ this.getConnectionVectorHandler = getConnectionVectorHandler;
2439
+ this.connection = connection;
2440
+ this.type = EDraggableType.CONNECTION;
2441
+ this.fromConnectorRect = RectExtensions.initialize();
2442
+ this.fromConnectorSide = EConnectorSide.BOTTOM;
2443
+ this.toConnectorRect = RectExtensions.initialize();
2444
+ this.toConnectorSide = EConnectorSide.TOP;
2602
2445
  }
2603
- findNearestCoordinate(difference) {
2604
- const rect = RectExtensions.addPoint(this.draggedNodeRect, difference);
2605
- const finder = new NearestCoordinateFinder(this.rects, rect);
2606
- const xResult = finder.findNearestCoordinateByX();
2607
- const yResult = finder.findNearestCoordinateByY();
2608
- const result = { xResult, yResult };
2609
- return result;
2446
+ initialize() {
2447
+ const fromConnector = this.getOutputRectInFlowHandler.handle(this.connection.outputId);
2448
+ this.fromConnectorRect = fromConnector.rect;
2449
+ this.fromConnectorSide = fromConnector.side;
2450
+ const toConnector = this.getInputRectInFlowHandler.handle(this.connection.inputId);
2451
+ this.toConnectorRect = toConnector.rect;
2452
+ this.toConnectorSide = toConnector.side;
2610
2453
  }
2611
- complete() {
2612
- this.lineService.hideVerticalLine();
2613
- this.lineService.hideHorizontalLine();
2454
+ move(difference) {
2455
+ const toConnectorRect = RectExtensions.addPoint(this.toConnectorRect, difference);
2456
+ const vector = this.getConnectionVectorHandler.handle(new GetConnectionVectorRequest(this.fromConnectorRect, toConnectorRect, this.connection.behavior, this.fromConnectorSide, this.toConnectorSide));
2457
+ this.connection.setVector(vector.point1, this.fromConnectorSide, vector.point2, this.toConnectorSide);
2458
+ this.connection.redraw();
2614
2459
  }
2615
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FLineAlignmentComponent, deps: [{ token: i0.ElementRef }, { token: FComponentsStore }, { token: FDraggableDataContext }, { token: GetElementRectInFlowHandler }], target: i0.ɵɵFactoryTarget.Component }); }
2616
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.9", type: FLineAlignmentComponent, selector: "f-line-alignment", host: { classAttribute: "f-line-alignment f-component" }, providers: [
2617
- { provide: F_LINE_ALIGNMENT, useExisting: FLineAlignmentComponent }
2618
- ], exportAs: ["fComponent"], usesInheritance: true, ngImport: i0, template: "", isInline: true, styles: [":host{display:block;position:absolute;left:0;top:0;width:100%;height:100%;overflow:hidden;pointer-events:none;-webkit-user-select:none;user-select:none}\n"] }); }
2619
2460
  }
2620
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FLineAlignmentComponent, decorators: [{
2621
- type: Component,
2622
- args: [{ selector: "f-line-alignment", template: "", exportAs: "fComponent", host: {
2623
- 'class': 'f-line-alignment f-component'
2624
- }, providers: [
2625
- { provide: F_LINE_ALIGNMENT, useExisting: FLineAlignmentComponent }
2626
- ], styles: [":host{display:block;position:absolute;left:0;top:0;width:100%;height:100%;overflow:hidden;pointer-events:none;-webkit-user-select:none;user-select:none}\n"] }]
2627
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: FComponentsStore }, { type: FDraggableDataContext }, { type: GetElementRectInFlowHandler }] });
2628
-
2629
- const F_SELECTION_AREA = new InjectionToken('F_SELECTION_AREA');
2630
- class FSelectionAreaBase {
2631
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FSelectionAreaBase, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2632
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FSelectionAreaBase, ngImport: i0 }); }
2633
- }
2634
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FSelectionAreaBase, decorators: [{
2635
- type: Directive
2636
- }] });
2637
2461
 
2638
- class FSelectionAreaComponent extends FSelectionAreaBase {
2639
- get hostElement() {
2640
- return this.elementReference.nativeElement;
2641
- }
2642
- constructor(elementReference, fDraggableDataContext) {
2643
- super();
2644
- this.elementReference = elementReference;
2462
+ class NodeDragHandler {
2463
+ constructor(fDraggableDataContext, fNode) {
2645
2464
  this.fDraggableDataContext = fDraggableDataContext;
2465
+ this.fNode = fNode;
2466
+ this.type = EDraggableType.NODE;
2467
+ this.onPointerDownPosition = PointExtensions.initialize();
2468
+ this.onPointerDownPosition = this.fNode.position;
2646
2469
  }
2647
- ngOnInit() {
2648
- this.fDraggableDataContext.fSelectionArea = this;
2649
- this.hostElement.style.display = 'none';
2650
- }
2651
- hide() {
2652
- this.hostElement.style.display = 'none';
2653
- }
2654
- show() {
2655
- this.hostElement.style.display = 'block';
2470
+ move(difference) {
2471
+ const position = Point.fromPoint(this.onPointerDownPosition).add(difference);
2472
+ this.fNode.updatePosition(position);
2473
+ this.fNode.redraw();
2474
+ this.fDraggableDataContext.fLineAlignment?.handle(difference);
2656
2475
  }
2657
- draw(object) {
2658
- const style = this.hostElement.style;
2659
- style.left = object.left + 'px';
2660
- style.top = object.top + 'px';
2661
- style.width = object.width + 'px';
2662
- style.height = object.height + 'px';
2476
+ complete() {
2477
+ this.fNode.completeDrag();
2663
2478
  }
2664
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FSelectionAreaComponent, deps: [{ token: i0.ElementRef }, { token: FDraggableDataContext }], target: i0.ɵɵFactoryTarget.Component }); }
2665
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.9", type: FSelectionAreaComponent, selector: "f-selection-area", host: { classAttribute: "f-selection-area f-component" }, providers: [
2666
- { provide: F_SELECTION_AREA, useExisting: FSelectionAreaComponent }
2667
- ], usesInheritance: true, ngImport: i0, template: ``, isInline: true, styles: [":host{position:absolute}\n"] }); }
2668
2479
  }
2669
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FSelectionAreaComponent, decorators: [{
2670
- type: Component,
2671
- args: [{ selector: "f-selection-area", template: ``, host: {
2672
- 'class': 'f-selection-area f-component'
2673
- }, providers: [
2674
- { provide: F_SELECTION_AREA, useExisting: FSelectionAreaComponent }
2675
- ], styles: [":host{position:absolute}\n"] }]
2676
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: FDraggableDataContext }] });
2677
2480
 
2678
- class FindFirstCanBeConnectedOutputByOutletHandler {
2679
- get fNodes() {
2680
- return this.fComponentsStore.fNodes;
2481
+ class IsConnectionUnderNodeHandler {
2482
+ get transform() {
2483
+ return this.fComponentsStore.fCanvas.transform;
2681
2484
  }
2682
- get fOutputs() {
2683
- return this.fComponentsStore.fOutputs;
2485
+ get flowHost() {
2486
+ return this.fComponentsStore.fFlow.hostElement;
2684
2487
  }
2685
- constructor(fComponentsStore) {
2488
+ constructor(fComponentsStore, fDraggableDataContext, getElementRectInFlowHandler, getOutgoingConnectionsHandler, getIncomingConnectionsHandler) {
2686
2489
  this.fComponentsStore = fComponentsStore;
2490
+ this.fDraggableDataContext = fDraggableDataContext;
2491
+ this.getElementRectInFlowHandler = getElementRectInFlowHandler;
2492
+ this.getOutgoingConnectionsHandler = getOutgoingConnectionsHandler;
2493
+ this.getIncomingConnectionsHandler = getIncomingConnectionsHandler;
2687
2494
  }
2688
- handle(outlet) {
2689
- let result;
2690
- const node = this.fNodes.find((x) => x.isContains(outlet.hostElement));
2691
- if (!node) {
2692
- throw new Error('Node not found');
2495
+ handle() {
2496
+ const isValid = this.isValidRequest();
2497
+ if (!isValid) {
2498
+ return;
2693
2499
  }
2694
- const outputsOfNode = this.fOutputs.filter((x) => {
2695
- return node.isContains(x.hostElement) && x.canBeConnected;
2500
+ const fNode = this.fDraggableDataContext.draggableItems[0].fNode;
2501
+ const outputsOfNode = this.getOutputsForNode(fNode);
2502
+ const inputsOfNode = this.getInputsForNode(fNode);
2503
+ const isCantBeConnectedByOutput = outputsOfNode.some((x) => !x.canBeConnected);
2504
+ const isCantBeConnectedByInput = this.fComponentsStore.fConnections.some((x) => {
2505
+ return inputsOfNode.find((input) => input.id === x.inputId);
2696
2506
  });
2697
- if (outputsOfNode.length > 0) {
2698
- result = outputsOfNode[0];
2507
+ if (!isCantBeConnectedByInput && outputsOfNode.length && !isCantBeConnectedByOutput && inputsOfNode.length) {
2508
+ const output = outputsOfNode[0];
2509
+ const input = inputsOfNode[0];
2510
+ const outgoingConnections = this.getOutgoingConnectionsHandler.handle([output]);
2511
+ const incomingConnections = this.getIncomingConnectionsHandler.handle([input]);
2512
+ if (outgoingConnections.length === 0 && incomingConnections.length === 0) {
2513
+ const connections = this.findConnectionsUnderNode(fNode);
2514
+ if (connections.length) {
2515
+ }
2516
+ }
2699
2517
  }
2700
- return result;
2701
- }
2702
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FindFirstCanBeConnectedOutputByOutletHandler, deps: [{ token: FComponentsStore }], target: i0.ɵɵFactoryTarget.Injectable }); }
2703
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FindFirstCanBeConnectedOutputByOutletHandler }); }
2704
- }
2705
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FindFirstCanBeConnectedOutputByOutletHandler, decorators: [{
2706
- type: Injectable
2707
- }], ctorParameters: () => [{ type: FComponentsStore }] });
2708
-
2709
- class CreateConnectionDragHandler {
2710
- constructor(getOutputRectInFlowHandler, getConnectionVectorHandler, connection, mouseDownPoint) {
2711
- this.getOutputRectInFlowHandler = getOutputRectInFlowHandler;
2712
- this.getConnectionVectorHandler = getConnectionVectorHandler;
2713
- this.connection = connection;
2714
- this.mouseDownPoint = mouseDownPoint;
2715
- this.type = EDraggableType.CREATE_CONNECTION;
2716
- this.onPointerDownFromConnectorRect = RectExtensions.initialize();
2717
- this.onPointerDownToConnectorRect = RectExtensions.initialize();
2718
- this.outputSide = EConnectorSide.BOTTOM;
2719
2518
  }
2720
- initialize() {
2721
- const outputRect = this.getOutputRectInFlowHandler.handle(this.connection.outputId);
2722
- this.outputSide = outputRect.side;
2723
- this.onPointerDownFromConnectorRect = outputRect.rect;
2724
- this.onPointerDownToConnectorRect = RectExtensions.initialize(this.mouseDownPoint.x, this.mouseDownPoint.y, 0, 0);
2725
- this.connection.show();
2726
- this.move(new Point(0, 0));
2519
+ isValidRequest() {
2520
+ const result = this.fDraggableDataContext.draggableItems.length === 1 &&
2521
+ this.fDraggableDataContext.draggableItems[0].type === EDraggableType.NODE;
2522
+ return result;
2727
2523
  }
2728
- move(difference) {
2729
- const toPoint = RectExtensions.addPoint(this.onPointerDownToConnectorRect, difference);
2730
- const vector = this.getConnectionVectorHandler.handle(new GetConnectionVectorRequest(this.onPointerDownFromConnectorRect, toPoint, this.connection.behavior, this.outputSide, EConnectorSide.TOP));
2731
- this.connection.setVector(vector.point1, this.outputSide, vector.point2, EConnectorSide.TOP);
2732
- this.connection.redraw();
2524
+ getOutputsForNode(node) {
2525
+ return this.fComponentsStore.fOutputs.filter((x) => node.isContains(x.hostElement));
2733
2526
  }
2734
- complete() {
2735
- this.connection.redraw();
2736
- this.connection.hide();
2527
+ getInputsForNode(node) {
2528
+ return this.fComponentsStore.fInputs.filter((x) => node.isContains(x.hostElement));
2737
2529
  }
2738
- }
2739
-
2740
- class CreateConnectionEvent {
2741
- constructor(outputId, inputId) {
2742
- this.outputId = outputId;
2743
- this.inputId = inputId;
2530
+ findConnectionsUnderNode(node) {
2531
+ const nodeRect = this.getElementRectInFlowHandler.handle(node.hostElement);
2532
+ return this.fComponentsStore.fConnections.filter((x) => {
2533
+ const intersection = RectExtensions.intersectionWithVector(nodeRect, x.vector.point1, x.vector.point2);
2534
+ return (intersection || []).length > 0;
2535
+ });
2744
2536
  }
2537
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: IsConnectionUnderNodeHandler, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: GetElementRectInFlowHandler }, { token: GetOutgoingConnectionsHandler }, { token: GetIncomingConnectionsHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
2538
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: IsConnectionUnderNodeHandler }); }
2745
2539
  }
2540
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: IsConnectionUnderNodeHandler, decorators: [{
2541
+ type: Injectable
2542
+ }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: GetElementRectInFlowHandler }, { type: GetOutgoingConnectionsHandler }, { type: GetIncomingConnectionsHandler }] });
2746
2543
 
2747
- class FirstNotConnectedInputOfNodeUnderPointerHandler {
2748
- get fNodes() {
2749
- return this.fComponentsStore.fNodes;
2544
+ class NodeOnPointerUp {
2545
+ get transform() {
2546
+ return this.fComponentsStore.fCanvas.transform;
2750
2547
  }
2751
- get fInputs() {
2752
- return this.fComponentsStore.fInputs;
2548
+ get flowHost() {
2549
+ return this.fComponentsStore.fFlow.hostElement;
2753
2550
  }
2754
- constructor(fComponentsStore) {
2551
+ constructor(fComponentsStore, fDraggableDataContext, isConnectionUnderNodeHandler) {
2755
2552
  this.fComponentsStore = fComponentsStore;
2553
+ this.fDraggableDataContext = fDraggableDataContext;
2554
+ this.isConnectionUnderNodeHandler = isConnectionUnderNodeHandler;
2756
2555
  }
2757
2556
  handle(event) {
2758
- const position = event.getPosition();
2759
- const elementsFromPoint = document.elementsFromPoint(position.x, position.y);
2760
- const nodes = elementsFromPoint.map((element) => {
2761
- return this.fNodes.find((x) => x.isContains(element));
2762
- }).filter((x) => !!x);
2763
- const inputs = nodes.map((x) => {
2764
- return this.fInputs.filter((i) => x.isContains(i.hostElement)).find((i) => {
2765
- return !i.isConnected && i.canBeConnected;
2557
+ const pointerPositionInFlow = Point.fromPoint(event.getPosition()).elementTransform(this.flowHost);
2558
+ let difference = pointerPositionInFlow.div(this.fDraggableDataContext.onPointerDownScale).sub(this.fDraggableDataContext.onPointerDownPosition);
2559
+ const isDragNodes = this.fDraggableDataContext.draggableItems.some((x) => x.type === EDraggableType.NODE);
2560
+ if (isDragNodes) {
2561
+ const nearestIntersection = this.fDraggableDataContext.fLineAlignment?.findNearestCoordinate(difference);
2562
+ if (nearestIntersection) {
2563
+ difference.x = nearestIntersection.xResult.value ? (difference.x - nearestIntersection.xResult.distance) : difference.x;
2564
+ difference.y = nearestIntersection.yResult.value ? (difference.y - nearestIntersection.yResult.distance) : difference.y;
2565
+ }
2566
+ this.fDraggableDataContext.draggableItems.forEach((x) => {
2567
+ x.move(difference);
2568
+ x.complete?.();
2766
2569
  });
2767
- });
2768
- const result = inputs.find((x) => !!x);
2769
- return result;
2570
+ this.isConnectionUnderNodeHandler.handle();
2571
+ this.fDraggableDataContext.fLineAlignment?.complete();
2572
+ }
2770
2573
  }
2771
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FirstNotConnectedInputOfNodeUnderPointerHandler, deps: [{ token: FComponentsStore }], target: i0.ɵɵFactoryTarget.Injectable }); }
2772
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FirstNotConnectedInputOfNodeUnderPointerHandler }); }
2574
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: NodeOnPointerUp, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: IsConnectionUnderNodeHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
2575
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: NodeOnPointerUp }); }
2773
2576
  }
2774
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FirstNotConnectedInputOfNodeUnderPointerHandler, decorators: [{
2577
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: NodeOnPointerUp, decorators: [{
2775
2578
  type: Injectable
2776
- }], ctorParameters: () => [{ type: FComponentsStore }] });
2579
+ }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: IsConnectionUnderNodeHandler }] });
2777
2580
 
2778
- class InputsUnderPointerHandler {
2779
- get fInputs() {
2780
- return this.fComponentsStore.fInputs;
2581
+ class NodePrepareDragSequence {
2582
+ get transform() {
2583
+ return this.fComponentsStore.fCanvas.transform;
2781
2584
  }
2782
- constructor(fComponentsStore) {
2585
+ get flowHost() {
2586
+ return this.fComponentsStore.fFlow.hostElement;
2587
+ }
2588
+ constructor(fComponentsStore, fDraggableDataContext, updateNodeLayerHandler, getInputRectInFlowHandler, getOutputRectInFlowHandler, getOutgoingConnectionsHandler, getIncomingConnectionsHandler, getConnectionVectorHandler) {
2783
2589
  this.fComponentsStore = fComponentsStore;
2590
+ this.fDraggableDataContext = fDraggableDataContext;
2591
+ this.updateNodeLayerHandler = updateNodeLayerHandler;
2592
+ this.getInputRectInFlowHandler = getInputRectInFlowHandler;
2593
+ this.getOutputRectInFlowHandler = getOutputRectInFlowHandler;
2594
+ this.getOutgoingConnectionsHandler = getOutgoingConnectionsHandler;
2595
+ this.getIncomingConnectionsHandler = getIncomingConnectionsHandler;
2596
+ this.getConnectionVectorHandler = getConnectionVectorHandler;
2784
2597
  }
2785
2598
  handle(event) {
2786
- const position = event.getPosition();
2787
- const elementsFromPoint = document.elementsFromPoint(position.x, position.y);
2788
- return elementsFromPoint.filter((x) => isNodeInput(x)).map((element) => {
2789
- return this.fInputs.find((x) => x.isContains(element));
2599
+ const node = this.fComponentsStore.findNode(event.targetElement);
2600
+ const pointerPositionInFlow = Point.fromPoint(event.getPosition()).elementTransform(this.flowHost);
2601
+ if (node && !node.disabled && !this.fDraggableDataContext.draggableItems.length) {
2602
+ if (isNodeDragHandle(event.targetElement)) {
2603
+ if (!this.fDraggableDataContext.selectedItems.includes(node)) {
2604
+ this.fDraggableDataContext.selectedItems.push(node);
2605
+ node.select();
2606
+ }
2607
+ this.updateNodeLayerHandler.handle(node);
2608
+ const itemsToDrag = this.calculateDraggableConnectionsAndNodes();
2609
+ const draggedNodes = itemsToDrag.filter((x) => {
2610
+ return x.type === EDraggableType.NODE;
2611
+ }).map((x) => x.fNode);
2612
+ this.fDraggableDataContext.fLineAlignment?.initialize(this.fComponentsStore.fNodes, draggedNodes);
2613
+ this.fDraggableDataContext.onPointerDownScale = this.transform.scale;
2614
+ this.fDraggableDataContext.onPointerDownPosition = pointerPositionInFlow.div(this.transform.scale);
2615
+ this.fDraggableDataContext.draggableItems = itemsToDrag;
2616
+ }
2617
+ }
2618
+ }
2619
+ calculateDraggableConnectionsAndNodes() {
2620
+ let itemsToDrag = [];
2621
+ const selectedNodes = this.fDraggableDataContext.selectedItems.map((x) => {
2622
+ return this.fComponentsStore.findNode(x.hostElement);
2790
2623
  }).filter((x) => !!x);
2624
+ const nodeDragHandlers = selectedNodes.map((x) => new NodeDragHandler(this.fDraggableDataContext, x));
2625
+ itemsToDrag = nodeDragHandlers;
2626
+ const allOutputIds = selectedNodes.reduce((result, x) => {
2627
+ return result.concat(this.getOutputsForNode(x));
2628
+ }, []).map((x) => x.id);
2629
+ const allInputIds = selectedNodes.reduce((result, x) => {
2630
+ return result.concat(this.getInputsForNode(x));
2631
+ }, []).map((x) => x.id);
2632
+ nodeDragHandlers.forEach((nodeHandler) => {
2633
+ const outputConnections = this.getOutgoingConnectionsHandler.handle(this.getOutputsForNode(nodeHandler.fNode));
2634
+ outputConnections.forEach((c) => {
2635
+ if (allInputIds.includes(c.inputId)) {
2636
+ itemsToDrag.push(new ConnectionDragHandler(this.getInputRectInFlowHandler, this.getOutputRectInFlowHandler, this.getConnectionVectorHandler, c));
2637
+ }
2638
+ else {
2639
+ itemsToDrag.push(new ConnectionSourceDragHandler(this.getInputRectInFlowHandler, this.getOutputRectInFlowHandler, this.getConnectionVectorHandler, c));
2640
+ }
2641
+ });
2642
+ const inputConnections = this.getIncomingConnectionsHandler.handle(this.getInputsForNode(nodeHandler.fNode));
2643
+ inputConnections.forEach((c) => {
2644
+ if (allOutputIds.includes(c.outputId)) {
2645
+ const index = itemsToDrag.findIndex((x) => x.type === EDraggableType.CONNECTION && x.connection.id === c.id);
2646
+ if (index !== -1) {
2647
+ itemsToDrag.push(new ConnectionDragHandler(this.getInputRectInFlowHandler, this.getOutputRectInFlowHandler, this.getConnectionVectorHandler, c));
2648
+ }
2649
+ }
2650
+ else {
2651
+ itemsToDrag.push(new ConnectionTargetDragHandler(this.getInputRectInFlowHandler, this.getOutputRectInFlowHandler, this.getConnectionVectorHandler, c));
2652
+ }
2653
+ });
2654
+ });
2655
+ return itemsToDrag;
2791
2656
  }
2792
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: InputsUnderPointerHandler, deps: [{ token: FComponentsStore }], target: i0.ɵɵFactoryTarget.Injectable }); }
2793
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: InputsUnderPointerHandler }); }
2657
+ getInputsForNode(node) {
2658
+ return this.fComponentsStore.fInputs.filter((x) => node.isContains(x.hostElement));
2659
+ }
2660
+ getOutputsForNode(node) {
2661
+ return this.fComponentsStore.fOutputs.filter((x) => node.isContains(x.hostElement));
2662
+ }
2663
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: NodePrepareDragSequence, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: UpdateNodeLayerHandler }, { token: GetInputRectInFlowHandler }, { token: GetOutputRectInFlowHandler }, { token: GetOutgoingConnectionsHandler }, { token: GetIncomingConnectionsHandler }, { token: GetConnectionVectorHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
2664
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: NodePrepareDragSequence }); }
2794
2665
  }
2795
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: InputsUnderPointerHandler, decorators: [{
2666
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: NodePrepareDragSequence, decorators: [{
2796
2667
  type: Injectable
2797
- }], ctorParameters: () => [{ type: FComponentsStore }] });
2668
+ }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: UpdateNodeLayerHandler }, { type: GetInputRectInFlowHandler }, { type: GetOutputRectInFlowHandler }, { type: GetOutgoingConnectionsHandler }, { type: GetIncomingConnectionsHandler }, { type: GetConnectionVectorHandler }] });
2798
2669
 
2799
- class FindInputsUnderPointerRequest {
2800
- constructor(event, dragHandler) {
2801
- this.event = event;
2802
- this.dragHandler = dragHandler;
2803
- }
2804
- }
2670
+ const NODE_PROVIDERS = [
2671
+ NodeOnPointerUp,
2672
+ NodePrepareDragSequence,
2673
+ IsConnectionUnderNodeHandler
2674
+ ];
2805
2675
 
2806
- class FindInputsUnderPointerHandler {
2807
- get fNodes() {
2808
- return this.fComponentsStore.fNodes;
2809
- }
2810
- constructor(fComponentsStore, inputsUnderPointerHandler, firstNotConnectedInputOfNodeUnderPointerHandler) {
2676
+ class SingleSelectOnPointerDown {
2677
+ constructor(fComponentsStore, fDraggableDataContext, getConnectionHandler) {
2811
2678
  this.fComponentsStore = fComponentsStore;
2812
- this.inputsUnderPointerHandler = inputsUnderPointerHandler;
2813
- this.firstNotConnectedInputOfNodeUnderPointerHandler = firstNotConnectedInputOfNodeUnderPointerHandler;
2679
+ this.fDraggableDataContext = fDraggableDataContext;
2680
+ this.getConnectionHandler = getConnectionHandler;
2814
2681
  }
2815
- handle(payload) {
2816
- const inputsUnderPointer = this.getInputsUnderPointer(payload);
2817
- const output = this.fComponentsStore.fOutputs.find((x) => x.id === payload.dragHandler.connection.outputId);
2818
- if (!output) {
2819
- throw OutputNotFound(payload.dragHandler.connection.outputId);
2682
+ handle(event) {
2683
+ const node = this.fComponentsStore.findNode(event.targetElement);
2684
+ const connection = this.getConnectionHandler.handle(event.targetElement);
2685
+ this.deselectAll(node, event);
2686
+ this.resetSelectionIfNotMultiselect(event);
2687
+ if (node) {
2688
+ if (!this.fDraggableDataContext.selectedItems.includes(node)) {
2689
+ this.fDraggableDataContext.selectedItems.push(node);
2690
+ }
2691
+ else {
2692
+ this.fDraggableDataContext.selectedItems.splice(this.fDraggableDataContext.selectedItems.indexOf(node), 1);
2693
+ }
2820
2694
  }
2821
- return inputsUnderPointer.filter((x) => {
2822
- const targetNode = this.fNodes.find((y) => y.isContains(x.hostElement));
2823
- const sourceNode = this.fNodes.find((y) => y.isContains(output.hostElement));
2824
- return sourceNode?.hostElement !== targetNode?.hostElement;
2695
+ else if (connection) {
2696
+ if (!this.fDraggableDataContext.selectedItems.includes(connection)) {
2697
+ this.fDraggableDataContext.selectedItems.push(connection);
2698
+ }
2699
+ else {
2700
+ this.fDraggableDataContext.selectedItems.splice(this.fDraggableDataContext.selectedItems.indexOf(connection), 1);
2701
+ }
2702
+ }
2703
+ this.selectIfNotSelected();
2704
+ }
2705
+ deselectAll(node, event) {
2706
+ this.fDraggableDataContext.selectedItems.forEach((x) => {
2707
+ if (x !== node || (!isNodeOutlet(event.targetElement) && !isNodeOutput(event.targetElement))) {
2708
+ x.deselect();
2709
+ }
2825
2710
  });
2826
2711
  }
2827
- getInputsUnderPointer(payload) {
2828
- let inputs = this.inputsUnderPointerHandler.handle(payload.event);
2829
- const input = this.firstNotConnectedInputOfNodeUnderPointerHandler.handle(payload.event);
2830
- if (input) {
2831
- inputs.push(input);
2712
+ resetSelectionIfNotMultiselect(event) {
2713
+ const isMultiselect = MouseEventExtensions.isCommandButton(event.originalEvent) ||
2714
+ MouseEventExtensions.isShiftPressed(event.originalEvent);
2715
+ if (!isMultiselect) {
2716
+ this.fDraggableDataContext.selectedItems = [];
2832
2717
  }
2833
- inputs = inputs.filter((x) => x.canBeConnected);
2834
- return inputs;
2835
2718
  }
2836
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FindInputsUnderPointerHandler, deps: [{ token: FComponentsStore }, { token: InputsUnderPointerHandler }, { token: FirstNotConnectedInputOfNodeUnderPointerHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
2837
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FindInputsUnderPointerHandler }); }
2719
+ selectIfNotSelected() {
2720
+ this.fDraggableDataContext.selectedItems.forEach((x) => {
2721
+ if (!x.isSelected()) {
2722
+ x.select();
2723
+ }
2724
+ });
2725
+ }
2726
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SingleSelectOnPointerDown, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: GetConnectionHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
2727
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SingleSelectOnPointerDown }); }
2838
2728
  }
2839
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FindInputsUnderPointerHandler, decorators: [{
2729
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SingleSelectOnPointerDown, decorators: [{
2840
2730
  type: Injectable
2841
- }], ctorParameters: () => [{ type: FComponentsStore }, { type: InputsUnderPointerHandler }, { type: FirstNotConnectedInputOfNodeUnderPointerHandler }] });
2731
+ }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: GetConnectionHandler }] });
2842
2732
 
2843
- class CreateConnectionOnPointerUp {
2844
- constructor(fComponentsStore, fDraggableDataContext, findInputsUnderPointerHandler, findFirstCanBeConnectedOutputByOutletHandler) {
2845
- this.fComponentsStore = fComponentsStore;
2846
- this.fDraggableDataContext = fDraggableDataContext;
2847
- this.findInputsUnderPointerHandler = findInputsUnderPointerHandler;
2848
- this.findFirstCanBeConnectedOutputByOutletHandler = findFirstCanBeConnectedOutputByOutletHandler;
2849
- }
2850
- handle(event) {
2851
- const isCreateConnection = this.fDraggableDataContext.draggableItems.some((x) => x.type === EDraggableType.CREATE_CONNECTION);
2852
- if (isCreateConnection) {
2853
- const handler = this.fDraggableDataContext.draggableItems[0];
2854
- const inputsUnderPointer = this.findInputsUnderPointerHandler.handle(new FindInputsUnderPointerRequest(event, handler));
2855
- if (inputsUnderPointer.length > 0) {
2856
- let output = this.fComponentsStore.fOutputs.find((x) => x.id === handler.connection.outputId);
2857
- if (!output) {
2858
- output = this.fComponentsStore.fOutlets.find((x) => x.id === handler.connection.outputId);
2859
- }
2860
- if (!output) {
2861
- throw OutputNotFound(handler.connection.outputId);
2862
- }
2863
- const isOutlet = isNodeOutlet(output.hostElement);
2864
- if (isOutlet) {
2865
- output = this.findFirstCanBeConnectedOutputByOutletHandler.handle(output);
2866
- if (!output) {
2867
- throw requiredOutput();
2868
- }
2869
- }
2870
- this.fComponentsStore.fDraggable?.fCreateConnection.emit(new CreateConnectionEvent(output.id, inputsUnderPointer[0]?.id));
2871
- }
2872
- handler.complete();
2873
- }
2733
+ const SINGLE_SELECT_PROVIDERS = [
2734
+ SingleSelectOnPointerDown
2735
+ ];
2736
+
2737
+ class SelectionChangeEvent {
2738
+ constructor(nodes, connections) {
2739
+ this.nodes = nodes;
2740
+ this.connections = connections;
2874
2741
  }
2875
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CreateConnectionOnPointerUp, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: FindInputsUnderPointerHandler }, { token: FindFirstCanBeConnectedOutputByOutletHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
2876
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CreateConnectionOnPointerUp }); }
2877
2742
  }
2878
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CreateConnectionOnPointerUp, decorators: [{
2879
- type: Injectable
2880
- }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: FindInputsUnderPointerHandler }, { type: FindFirstCanBeConnectedOutputByOutletHandler }] });
2881
2743
 
2882
- class CreateConnectionPrepareDragSequence {
2744
+ class GetCanBeSelectedItemsHandler {
2745
+ get fNodes() {
2746
+ return this.fComponentsStore.fNodes;
2747
+ }
2748
+ get fConnections() {
2749
+ return this.fComponentsStore.fConnections;
2750
+ }
2883
2751
  get transform() {
2884
2752
  return this.fComponentsStore.fCanvas.transform;
2885
2753
  }
2886
- get flowHost() {
2887
- return this.fComponentsStore.fFlow.hostElement;
2888
- }
2889
- constructor(fComponentsStore, fDraggableDataContext, getElementRectInFlowHandler, getConnectionVectorHandler, findFirstCanBeConnectedOutputByOutletHandler, getOutputRectInFlowHandler) {
2754
+ constructor(fComponentsStore, fDraggableDataContext, getElementRectInFlowHandler) {
2890
2755
  this.fComponentsStore = fComponentsStore;
2891
2756
  this.fDraggableDataContext = fDraggableDataContext;
2892
2757
  this.getElementRectInFlowHandler = getElementRectInFlowHandler;
2893
- this.getConnectionVectorHandler = getConnectionVectorHandler;
2894
- this.findFirstCanBeConnectedOutputByOutletHandler = findFirstCanBeConnectedOutputByOutletHandler;
2895
- this.getOutputRectInFlowHandler = getOutputRectInFlowHandler;
2896
2758
  }
2897
- handle(event) {
2898
- const node = this.fComponentsStore.findNode(event.targetElement);
2899
- const pointerPositionInFlow = Point.fromPoint(event.getPosition()).elementTransform(this.flowHost);
2900
- if (!node || this.fDraggableDataContext.draggableItems.length || !this.fComponentsStore.fTempConnection) {
2901
- return;
2902
- }
2903
- if (isNodeOutlet(event.targetElement)) {
2904
- const outlet = this.fComponentsStore.fOutlets.find((x) => {
2905
- return x.hostElement.contains(event.targetElement);
2906
- });
2907
- if (!outlet) {
2908
- throw new Error('Outlet not found');
2909
- }
2910
- const nodeOutputs = this.fComponentsStore.fOutputs.filter((x) => node.isContains(x.hostElement));
2911
- outlet.setOutputs(nodeOutputs);
2912
- if (outlet.canBeConnected) {
2913
- const outletCenter = this.getElementRectInFlowHandler.handle(outlet.hostElement).gravityCenter;
2914
- if (outlet.isConnectionFromOutlet) {
2915
- this.createConnectionHandler(pointerPositionInFlow, outlet, outletCenter);
2916
- }
2917
- else {
2918
- const output = this.findFirstCanBeConnectedOutputByOutletHandler.handle(outlet);
2919
- if (!output) {
2920
- throw new Error('Output not found');
2921
- }
2922
- this.createConnectionHandler(pointerPositionInFlow, output, outletCenter);
2923
- }
2924
- }
2925
- }
2926
- else if (this.isNodeOutput(event.targetElement, node)) {
2927
- const output = this.fComponentsStore.fOutputs.find((x) => {
2928
- return x.hostElement.contains(event.targetElement);
2929
- });
2930
- if (!output) {
2931
- throw new Error('Output not found');
2932
- }
2933
- if (output.canBeConnected) {
2934
- const outputCenter = this.getElementRectInFlowHandler.handle(output.hostElement).gravityCenter;
2935
- this.createConnectionHandler(pointerPositionInFlow, output, outputCenter);
2936
- }
2937
- }
2759
+ handle() {
2760
+ const nodeRects = this.getNodesWithRects();
2761
+ const lineRects = this.getConnectionsWithRects();
2762
+ const result = [...nodeRects, ...lineRects].filter((x) => {
2763
+ return !this.fDraggableDataContext.selectedItems.includes(x.element);
2764
+ });
2765
+ return result;
2938
2766
  }
2939
- createConnectionHandler(pointerPositionInCanvas, output, outputCenter) {
2940
- this.fComponentsStore.fTempConnection.outputId = output.id;
2941
- this.fComponentsStore.fTempConnection.initialize();
2942
- this.fDraggableDataContext.onPointerDownScale = this.transform.scale;
2943
- this.fDraggableDataContext.onPointerDownPosition = pointerPositionInCanvas.div(this.transform.scale);
2944
- this.fDraggableDataContext.draggableItems = [
2945
- new CreateConnectionDragHandler(this.getOutputRectInFlowHandler, this.getConnectionVectorHandler, this.fComponentsStore.fTempConnection, outputCenter)
2946
- ];
2767
+ getNodesWithRects() {
2768
+ return this.fNodes.map((x) => {
2769
+ const rect = this.getElementRectInFlowHandler.handle(x.hostElement);
2770
+ return {
2771
+ element: x,
2772
+ rect: RectExtensions.mult(rect, this.transform.scale)
2773
+ };
2774
+ });
2947
2775
  }
2948
- isNodeOutput(targetElement, node) {
2949
- const outlets = this.fComponentsStore.fOutlets.filter((x) => node.isContains(x.hostElement));
2950
- return isNodeOutput(targetElement) && !outlets.length;
2776
+ getConnectionsWithRects() {
2777
+ return this.fConnections.map((x) => {
2778
+ const rect = this.getElementRectInFlowHandler.handle(x.boundingElement);
2779
+ return {
2780
+ element: x,
2781
+ rect: RectExtensions.mult(rect, this.transform.scale)
2782
+ };
2783
+ });
2951
2784
  }
2952
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CreateConnectionPrepareDragSequence, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: GetElementRectInFlowHandler }, { token: GetConnectionVectorHandler }, { token: FindFirstCanBeConnectedOutputByOutletHandler }, { token: GetOutputRectInFlowHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
2953
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CreateConnectionPrepareDragSequence }); }
2785
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: GetCanBeSelectedItemsHandler, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: GetElementRectInFlowHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
2786
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: GetCanBeSelectedItemsHandler }); }
2954
2787
  }
2955
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: CreateConnectionPrepareDragSequence, decorators: [{
2788
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: GetCanBeSelectedItemsHandler, decorators: [{
2956
2789
  type: Injectable
2957
- }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: GetElementRectInFlowHandler }, { type: GetConnectionVectorHandler }, { type: FindFirstCanBeConnectedOutputByOutletHandler }, { type: GetOutputRectInFlowHandler }] });
2790
+ }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: GetElementRectInFlowHandler }] });
2958
2791
 
2959
- class ReassignConnectionDragHandler {
2960
- constructor(getInputRectInFlowHandler, getOutputRectInFlowHandler, getConnectionVectorHandler, connection) {
2961
- this.getInputRectInFlowHandler = getInputRectInFlowHandler;
2962
- this.getOutputRectInFlowHandler = getOutputRectInFlowHandler;
2963
- this.getConnectionVectorHandler = getConnectionVectorHandler;
2964
- this.connection = connection;
2965
- this.type = EDraggableType.REASSIGN_CONNECTION;
2966
- this.onPointerDownFromConnectorRect = RectExtensions.initialize();
2967
- this.onPointerDownToConnectorRect = RectExtensions.initialize();
2968
- this.outputSide = EConnectorSide.BOTTOM;
2969
- this.inputSide = EConnectorSide.TOP;
2792
+ class SelectionAreaDragHandle {
2793
+ get canvasPosition() {
2794
+ return Point.fromPoint(this.fComponentsStore.fCanvas.transform.position).add(this.fComponentsStore.fCanvas.transform.scaledPosition);
2795
+ }
2796
+ constructor(fComponentsStore, fDraggableDataContext, injector) {
2797
+ this.fComponentsStore = fComponentsStore;
2798
+ this.fDraggableDataContext = fDraggableDataContext;
2799
+ this.injector = injector;
2800
+ this.type = EDraggableType.SELECTION;
2801
+ this.canBeSelected = [];
2802
+ this.selectedByMove = [];
2970
2803
  }
2971
2804
  initialize() {
2972
- const fromConnector = this.getOutputRectInFlowHandler.handle(this.connection.outputId);
2973
- this.inputSide = this.getInputRectInFlowHandler.handle(this.connection.inputId).side;
2974
- this.outputSide = fromConnector.side;
2975
- this.onPointerDownFromConnectorRect = fromConnector.rect;
2976
- this.onPointerDownToConnectorRect = RectExtensions.initialize(this.connection.vector.point2.x, this.connection.vector.point2.y, 0, 0);
2805
+ this.canBeSelected = this.injector.get(GetCanBeSelectedItemsHandler).handle();
2806
+ this.fDraggableDataContext.fSelectionArea?.show();
2807
+ this.fDraggableDataContext.fSelectionArea?.draw({
2808
+ left: this.fDraggableDataContext.onPointerDownPosition.x,
2809
+ top: this.fDraggableDataContext.onPointerDownPosition.y,
2810
+ width: 0,
2811
+ height: 0
2812
+ });
2977
2813
  }
2978
2814
  move(difference) {
2979
- const toRect = RectExtensions.addPoint(this.onPointerDownToConnectorRect, difference);
2980
- const vector = this.getConnectionVectorHandler.handle(new GetConnectionVectorRequest(this.onPointerDownFromConnectorRect, toRect, this.connection.behavior, this.outputSide, this.inputSide));
2981
- this.connection.setVector(vector.point1, this.outputSide, vector.point2, this.inputSide);
2982
- this.connection.redraw();
2815
+ const currentPoint = Point.fromPoint(difference).add(this.fDraggableDataContext.onPointerDownPosition);
2816
+ const x = Math.min(this.fDraggableDataContext.onPointerDownPosition.x, currentPoint.x);
2817
+ const y = Math.min(this.fDraggableDataContext.onPointerDownPosition.y, currentPoint.y);
2818
+ const width = Math.abs(difference.x);
2819
+ const height = Math.abs(difference.y);
2820
+ this.fDraggableDataContext.fSelectionArea?.draw({ left: x, top: y, width, height });
2821
+ this.selectedByMove = [];
2822
+ this.canBeSelected.forEach((item) => {
2823
+ item.element.deselect();
2824
+ const itemRect = RectExtensions.addPoint(item.rect, this.canvasPosition);
2825
+ const isIntersect = RectExtensions.intersectionWithRect(itemRect, RectExtensions.initialize(x, y, width, height));
2826
+ if (isIntersect) {
2827
+ item.element.select();
2828
+ this.selectedByMove.push(item.element);
2829
+ }
2830
+ });
2983
2831
  }
2984
2832
  complete() {
2985
- const fromConnector = this.getOutputRectInFlowHandler.handle(this.connection.outputId);
2986
- const toConnector = this.getInputRectInFlowHandler.handle(this.connection.inputId);
2987
- const vector = this.getConnectionVectorHandler.handle(new GetConnectionVectorRequest(fromConnector.rect, toConnector.rect, this.connection.behavior, fromConnector.side, toConnector.side));
2988
- this.connection.setVector(vector.point1, fromConnector.side, vector.point2, toConnector.side);
2989
- this.connection.redraw();
2833
+ this.fDraggableDataContext.fSelectionArea?.hide();
2834
+ this.fDraggableDataContext.selectedItems.push(...this.selectedByMove);
2990
2835
  }
2991
2836
  }
2992
2837
 
2993
- class ReassignConnectionEvent {
2994
- constructor(connectionId, outputId, oldInputId, newInputId) {
2995
- this.connectionId = connectionId;
2996
- this.outputId = outputId;
2997
- this.oldInputId = oldInputId;
2998
- this.newInputId = newInputId;
2838
+ class SelectionAreaPrepareDragSequence {
2839
+ get fFlow() {
2840
+ return this.fComponentsStore.fFlow;
2841
+ }
2842
+ constructor(fComponentsStore, fDraggableDataContext, injector) {
2843
+ this.fComponentsStore = fComponentsStore;
2844
+ this.fDraggableDataContext = fDraggableDataContext;
2845
+ this.injector = injector;
2846
+ }
2847
+ handle(event) {
2848
+ const pointerPositionInFlow = Point.fromPoint(event.getPosition()).elementTransform(this.fFlow.hostElement);
2849
+ if (MouseEventExtensions.isShiftPressed(event.originalEvent) && this.fDraggableDataContext.fSelectionArea) {
2850
+ this.fDraggableDataContext.draggableItems = [
2851
+ new SelectionAreaDragHandle(this.fComponentsStore, this.fDraggableDataContext, this.injector)
2852
+ ];
2853
+ this.fDraggableDataContext.onPointerDownScale = 1;
2854
+ this.fDraggableDataContext.onPointerDownPosition = pointerPositionInFlow.div(1);
2855
+ }
2999
2856
  }
2857
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SelectionAreaPrepareDragSequence, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable }); }
2858
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SelectionAreaPrepareDragSequence }); }
3000
2859
  }
2860
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SelectionAreaPrepareDragSequence, decorators: [{
2861
+ type: Injectable
2862
+ }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: i0.Injector }] });
3001
2863
 
3002
- class ReassignConnectionOnPointerUp {
3003
- get fDraggable() {
3004
- return this.fComponentsStore.fDraggable;
3005
- }
3006
- constructor(fComponentsStore, fDraggableDataContext, findInputsUnderPointerHandler) {
3007
- this.fComponentsStore = fComponentsStore;
2864
+ class SelectionAreaOnPointerUp {
2865
+ constructor(fDraggableDataContext) {
3008
2866
  this.fDraggableDataContext = fDraggableDataContext;
3009
- this.findInputsUnderPointerHandler = findInputsUnderPointerHandler;
3010
2867
  }
3011
2868
  handle(event) {
3012
- const isReassignConnection = this.fDraggableDataContext.draggableItems.some((x) => x.type === EDraggableType.REASSIGN_CONNECTION);
3013
- if (isReassignConnection) {
3014
- const handler = this.fDraggableDataContext.draggableItems[0];
3015
- const inputsUnderPointer = this.findInputsUnderPointerHandler.handle(new FindInputsUnderPointerRequest(event, handler));
3016
- if (inputsUnderPointer.length > 0) {
3017
- if (handler.connection.inputId !== inputsUnderPointer[0]?.id) {
3018
- this.fDraggable.fReassignConnection.emit(new ReassignConnectionEvent(handler.connection.id, handler.connection.outputId, handler.connection.inputId, inputsUnderPointer[0]?.id));
3019
- }
3020
- }
3021
- handler.complete();
2869
+ const isSelection = this.fDraggableDataContext.draggableItems.some((x) => x.type === EDraggableType.SELECTION);
2870
+ if (isSelection) {
2871
+ this.fDraggableDataContext.draggableItems.forEach((x) => {
2872
+ x.complete?.();
2873
+ });
3022
2874
  }
3023
2875
  }
3024
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ReassignConnectionOnPointerUp, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: FindInputsUnderPointerHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
3025
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ReassignConnectionOnPointerUp }); }
2876
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SelectionAreaOnPointerUp, deps: [{ token: FDraggableDataContext }], target: i0.ɵɵFactoryTarget.Injectable }); }
2877
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SelectionAreaOnPointerUp }); }
3026
2878
  }
3027
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ReassignConnectionOnPointerUp, decorators: [{
2879
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SelectionAreaOnPointerUp, decorators: [{
3028
2880
  type: Injectable
3029
- }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: FindInputsUnderPointerHandler }] });
2881
+ }], ctorParameters: () => [{ type: FDraggableDataContext }] });
3030
2882
 
3031
- class ReassignConnectionPrepareDragSequence {
3032
- get transform() {
3033
- return this.fComponentsStore.fCanvas.transform;
2883
+ const SELECTION_AREA_PROVIDERS = [
2884
+ GetCanBeSelectedItemsHandler,
2885
+ SelectionAreaPrepareDragSequence,
2886
+ SelectionAreaOnPointerUp,
2887
+ ];
2888
+
2889
+ const F_DRAGGABLE = new InjectionToken('F_DRAGGABLE');
2890
+ class FDraggableBase extends IDragAndDropBase {
2891
+ constructor(ngZone) {
2892
+ super(ngZone);
3034
2893
  }
3035
- get flowHost() {
3036
- return this.fComponentsStore.fFlow.hostElement;
2894
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FDraggableBase, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive }); }
2895
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FDraggableBase, usesInheritance: true, ngImport: i0 }); }
2896
+ }
2897
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FDraggableBase, decorators: [{
2898
+ type: Directive
2899
+ }], ctorParameters: () => [{ type: i0.NgZone }] });
2900
+
2901
+ class FDraggableDirective extends FDraggableBase {
2902
+ get hostElement() {
2903
+ return this.elementReference.nativeElement;
3037
2904
  }
3038
- constructor(fComponentsStore, fDraggableDataContext, getConnectionHandler, getInputRectInFlowHandler, getOutputRectInFlowHandler, getConnectionVectorHandler) {
3039
- this.fComponentsStore = fComponentsStore;
2905
+ constructor(elementReference, fDraggableDataContext, ngZone, injector, fComponentsStore, document) {
2906
+ super(ngZone);
2907
+ this.elementReference = elementReference;
3040
2908
  this.fDraggableDataContext = fDraggableDataContext;
3041
- this.getConnectionHandler = getConnectionHandler;
3042
- this.getInputRectInFlowHandler = getInputRectInFlowHandler;
3043
- this.getOutputRectInFlowHandler = getOutputRectInFlowHandler;
3044
- this.getConnectionVectorHandler = getConnectionVectorHandler;
2909
+ this.injector = injector;
2910
+ this.fComponentsStore = fComponentsStore;
2911
+ this.subscriptions$ = new Subscription();
2912
+ this.disabled = false;
2913
+ this.fSelectionChange = new EventEmitter();
2914
+ // @Output()
2915
+ // public override fConnectionIntersectNode: EventEmitter<ConnectionIntersectNodeEvent> = new EventEmitter<ConnectionIntersectNodeEvent>();
2916
+ this.fCreateNode = new EventEmitter();
2917
+ this.fReassignConnection = new EventEmitter();
2918
+ this.fCreateConnection = new EventEmitter();
2919
+ this.document = document;
3045
2920
  }
3046
- handle(event) {
3047
- const pointerPositionInFlow = Point.fromPoint(event.getPosition()).elementTransform(this.flowHost);
3048
- const position = event.getPosition();
3049
- const allElements = document.elementsFromPoint(position.x, position.y);
3050
- const dragHandlesOfConnections = allElements.filter((x) => {
3051
- return !!this.getConnectionHandler.handle(x) && x.classList.contains(F_CONNECTION_DRAG_HANDLE_CLASS);
2921
+ ngOnInit() {
2922
+ this.fComponentsStore.fDraggable = this;
2923
+ }
2924
+ ngAfterViewInit() {
2925
+ super.subscribe(this.document);
2926
+ }
2927
+ onPointerDown(event) {
2928
+ this.fDraggableDataContext.reset();
2929
+ let result = event.isMouseLeftButton();
2930
+ this.injector.get(SingleSelectOnPointerDown).handle(event);
2931
+ this.injector.get(ReassignConnectionPrepareDragSequence).handle(event);
2932
+ this.injector.get(CreateConnectionPrepareDragSequence).handle(event);
2933
+ return result;
2934
+ }
2935
+ prepareDragSequence(event) {
2936
+ this.injector.get(SelectionAreaPrepareDragSequence).handle(event);
2937
+ this.injector.get(NodePrepareDragSequence).handle(event);
2938
+ this.injector.get(CanvasPrepareDragSequence).handle(event);
2939
+ this.injector.get(ExternalItemPrepareDragSequence).handle(event);
2940
+ this.fDraggableDataContext.draggableItems.forEach((item) => {
2941
+ item.initialize?.();
3052
2942
  });
3053
- let connectionToReassign;
3054
- if (dragHandlesOfConnections.length) {
3055
- const connections = dragHandlesOfConnections.map((x) => this.getConnectionHandler.handle(x)).filter((x) => !x?.disabled);
3056
- if (connections.length) {
3057
- connectionToReassign = this.getConnectionHandler.handle(dragHandlesOfConnections[0]);
3058
- }
3059
- }
3060
- if (connectionToReassign && !this.fDraggableDataContext.draggableItems.length) {
3061
- this.fDraggableDataContext.onPointerDownScale = this.transform.scale;
3062
- this.fDraggableDataContext.onPointerDownPosition = pointerPositionInFlow.div(this.transform.scale);
3063
- this.fDraggableDataContext.draggableItems = [
3064
- new ReassignConnectionDragHandler(this.getInputRectInFlowHandler, this.getOutputRectInFlowHandler, this.getConnectionVectorHandler, connectionToReassign)
3065
- ];
2943
+ this.emitSelectionChangeEvent();
2944
+ if (this.fDraggableDataContext.draggableItems.length > 0) {
2945
+ this.hostElement.classList.add('f-dragging');
3066
2946
  }
3067
2947
  }
3068
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ReassignConnectionPrepareDragSequence, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: GetConnectionHandler }, { token: GetInputRectInFlowHandler }, { token: GetOutputRectInFlowHandler }, { token: GetConnectionVectorHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
3069
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ReassignConnectionPrepareDragSequence }); }
2948
+ onPointerMove(event) {
2949
+ const pointerPositionInCanvas = Point.fromPoint(event.getPosition()).elementTransform(this.hostElement);
2950
+ const difference = pointerPositionInCanvas.div(this.fDraggableDataContext.onPointerDownScale).sub(this.fDraggableDataContext.onPointerDownPosition);
2951
+ this.fDraggableDataContext.draggableItems.forEach((item) => {
2952
+ item.move(difference);
2953
+ });
2954
+ }
2955
+ onPointerUp(event) {
2956
+ this.injector.get(ReassignConnectionOnPointerUp).handle(event);
2957
+ this.injector.get(CreateConnectionOnPointerUp).handle(event);
2958
+ this.injector.get(SelectionAreaOnPointerUp).handle(event);
2959
+ this.injector.get(NodeOnPointerUp).handle(event);
2960
+ this.injector.get(CanvasOnPointerUp).handle(event);
2961
+ this.injector.get(ExternalItemOnPointerUp).handle(event);
2962
+ this.hostElement.classList.remove('f-dragging');
2963
+ this.fDraggableDataContext.reset();
2964
+ }
2965
+ emitSelectionChangeEvent() {
2966
+ let selectedNodes = [];
2967
+ let selectedConnections = [];
2968
+ this.fDraggableDataContext.selectedItems.forEach((x) => {
2969
+ if (x.hostElement.classList.contains('f-node')) {
2970
+ selectedNodes.push(x.hostElement.id);
2971
+ }
2972
+ else {
2973
+ selectedConnections.push(x.hostElement.id);
2974
+ }
2975
+ });
2976
+ this.fSelectionChange.emit(new SelectionChangeEvent(selectedNodes, selectedConnections));
2977
+ }
2978
+ ngOnDestroy() {
2979
+ super.unsubscribe();
2980
+ this.subscriptions$.unsubscribe();
2981
+ }
2982
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FDraggableDirective, deps: [{ token: i0.ElementRef }, { token: FDraggableDataContext }, { token: i0.NgZone }, { token: i0.Injector }, { token: FComponentsStore }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Directive }); }
2983
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FDraggableDirective, selector: "f-flow[fDraggable]", inputs: { disabled: ["fDraggableDisabled", "disabled"] }, outputs: { fSelectionChange: "fSelectionChange", fCreateNode: "fCreateNode", fReassignConnection: "fReassignConnection", fCreateConnection: "fCreateConnection" }, providers: [
2984
+ { provide: F_DRAGGABLE, useExisting: FDraggableDirective }
2985
+ ], exportAs: ["fDraggable"], usesInheritance: true, ngImport: i0 }); }
3070
2986
  }
3071
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ReassignConnectionPrepareDragSequence, decorators: [{
2987
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FDraggableDirective, decorators: [{
2988
+ type: Directive,
2989
+ args: [{
2990
+ selector: "f-flow[fDraggable]",
2991
+ exportAs: 'fDraggable',
2992
+ providers: [
2993
+ { provide: F_DRAGGABLE, useExisting: FDraggableDirective }
2994
+ ]
2995
+ }]
2996
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: FDraggableDataContext }, { type: i0.NgZone }, { type: i0.Injector }, { type: FComponentsStore }, { type: undefined, decorators: [{
2997
+ type: Inject,
2998
+ args: [DOCUMENT]
2999
+ }] }], propDecorators: { disabled: [{
3000
+ type: Input,
3001
+ args: ['fDraggableDisabled']
3002
+ }], fSelectionChange: [{
3003
+ type: Output
3004
+ }], fCreateNode: [{
3005
+ type: Output
3006
+ }], fReassignConnection: [{
3007
+ type: Output
3008
+ }], fCreateConnection: [{
3009
+ type: Output
3010
+ }] } });
3011
+
3012
+ class SelectAllHandler {
3013
+ constructor(fDataContext, fDraggableDataContext) {
3014
+ this.fDataContext = fDataContext;
3015
+ this.fDraggableDataContext = fDraggableDataContext;
3016
+ }
3017
+ handle() {
3018
+ this.fDraggableDataContext.selectedItems.forEach((x) => {
3019
+ x.deselect();
3020
+ });
3021
+ this.fDraggableDataContext.selectedItems = [];
3022
+ this.fDataContext.fNodes.forEach((x) => {
3023
+ x.select();
3024
+ this.fDraggableDataContext.selectedItems.push(x);
3025
+ });
3026
+ this.fDataContext.fConnections.forEach((x) => {
3027
+ x.select();
3028
+ this.fDraggableDataContext.selectedItems.push(x);
3029
+ });
3030
+ }
3031
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SelectAllHandler, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }], target: i0.ɵɵFactoryTarget.Injectable }); }
3032
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SelectAllHandler }); }
3033
+ }
3034
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SelectAllHandler, decorators: [{
3072
3035
  type: Injectable
3073
- }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: GetConnectionHandler }, { type: GetInputRectInFlowHandler }, { type: GetOutputRectInFlowHandler }, { type: GetConnectionVectorHandler }] });
3036
+ }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }] });
3074
3037
 
3075
- const CONNECTIONS_PROVIDERS = [
3076
- FindFirstCanBeConnectedOutputByOutletHandler,
3077
- CreateConnectionOnPointerUp,
3078
- CreateConnectionPrepareDragSequence,
3079
- FirstNotConnectedInputOfNodeUnderPointerHandler,
3080
- InputsUnderPointerHandler,
3081
- FindInputsUnderPointerHandler,
3082
- ReassignConnectionOnPointerUp,
3083
- ReassignConnectionPrepareDragSequence
3038
+ const COMMON_PROVIDERS = [
3039
+ GetAllNodesRectHandler,
3040
+ GetConnectionVectorHandler,
3041
+ GetConnectionHandler,
3042
+ GetElementRectInFlowHandler,
3043
+ GetOutputRectInFlowHandler,
3044
+ GetInputRectInFlowHandler,
3045
+ GetIncomingConnectionsHandler,
3046
+ GetOutgoingConnectionsHandler,
3047
+ SelectAllHandler,
3048
+ UpdateNodeLayerHandler,
3084
3049
  ];
3085
3050
 
3086
- class CreateNodeEvent {
3087
- constructor(rect, data) {
3088
- this.rect = rect;
3089
- this.data = data;
3051
+ class FConnectorBase {
3052
+ constructor() {
3053
+ this.stateChanges = new Subject();
3054
+ this.side = EConnectorSide.BOTTOM;
3055
+ }
3056
+ isContains(element) {
3057
+ return this.hostElement.contains(element);
3058
+ }
3059
+ setConnected(isConnected) {
3060
+ this.isConnected = isConnected;
3090
3061
  }
3091
3062
  }
3092
3063
 
3093
- class ExternalItemDragHandler {
3094
- constructor(externalItem) {
3095
- this.externalItem = externalItem;
3096
- this.type = EDraggableType.PALETTE_ITEM;
3097
- this.onPointerDownRect = RectExtensions.initialize();
3098
- this.difference = PointExtensions.initialize();
3064
+ const F_NODE_INPUT = new InjectionToken('F_NODE_INPUT');
3065
+ class FNodeInputBase extends FConnectorBase {
3066
+ constructor() {
3067
+ super(...arguments);
3068
+ this.isConnected = false;
3069
+ }
3070
+ get canBeConnected() {
3071
+ return !this.disabled && (this.multiple ? true : !this.isConnected);
3072
+ }
3073
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeInputBase, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
3074
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FNodeInputBase, usesInheritance: true, ngImport: i0 }); }
3075
+ }
3076
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeInputBase, decorators: [{
3077
+ type: Directive
3078
+ }] });
3079
+
3080
+ function isNodeInput(element) {
3081
+ return !!element.closest('[fNodeInput]');
3082
+ }
3083
+
3084
+ const F_NODE = new InjectionToken('F_NODE');
3085
+ class FNodeBase {
3086
+ constructor() {
3087
+ this.stateChanges = new Subject();
3088
+ this._position = PointExtensions.initialize();
3099
3089
  }
3100
- getStyle(position) {
3101
- return `position: absolute; left: 0; top: 0; transform: translate(${position.x}px, ${position.y}px)`;
3090
+ isContains(element) {
3091
+ return this.hostElement.contains(element);
3102
3092
  }
3103
- initialize() {
3104
- this.onPointerDownRect = this.getExternalItemRect();
3105
- this.placeholder = DomElementExtensions.deepCloneNode(this.externalItem.hostElement);
3106
- document.body.appendChild(this.placeholder);
3093
+ redraw() {
3094
+ this.hostElement.setAttribute('style', 'transform: translate(' + this.position.x + 'px,' + this.position.y + 'px)');
3107
3095
  }
3108
- getExternalItemRect() {
3109
- const rect = this.externalItem.hostElement.getBoundingClientRect();
3110
- const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
3111
- const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
3112
- const offsetTop = rect.top + scrollTop;
3113
- const offsetLeft = rect.left + scrollLeft;
3114
- return RectExtensions.initialize(offsetLeft, offsetTop, rect.width, rect.height);
3096
+ deselect() {
3097
+ this.hostElement.classList.remove(F_SELECTED_CLASS);
3115
3098
  }
3116
- move(difference) {
3117
- this.difference = difference;
3118
- const position = Point.fromPoint(this.onPointerDownRect).add(this.difference);
3119
- this.placeholder.setAttribute('style', this.getStyle(position));
3099
+ select() {
3100
+ this.hostElement.classList.add(F_SELECTED_CLASS);
3120
3101
  }
3121
- getPlaceholderRect() {
3122
- return RectExtensions.fromElement(this.placeholder);
3102
+ isSelected() {
3103
+ return this.hostElement.classList.contains(F_SELECTED_CLASS);
3123
3104
  }
3124
- complete() {
3125
- document.body.removeChild(this.placeholder);
3105
+ updatePosition(position) {
3106
+ this._position = position;
3107
+ }
3108
+ completeDrag() {
3109
+ this.positionChange.emit(this.position);
3126
3110
  }
3127
3111
  }
3128
3112
 
3129
- class ExternalItemPrepareDragSequence {
3130
- get transform() {
3131
- return this.fComponentsStore.fCanvas.transform;
3113
+ let uniqueId$4 = 0;
3114
+ class FNodeInputDirective extends FNodeInputBase {
3115
+ get disabled() {
3116
+ return this.isDisabled;
3132
3117
  }
3133
- get flowHost() {
3134
- return this.fComponentsStore.fFlow.hostElement;
3118
+ set disabled(isDisabled) {
3119
+ const value = BooleanExtensions.castToBoolean(isDisabled);
3120
+ if (value !== this.isDisabled) {
3121
+ this.isDisabled = value;
3122
+ this.stateChanges.next();
3123
+ }
3135
3124
  }
3136
- constructor(fComponentsStore, fDraggableDataContext, fExternalItemService) {
3125
+ get hostElement() {
3126
+ return this.elementReference.nativeElement;
3127
+ }
3128
+ constructor(elementReference, fNode, fComponentsStore) {
3129
+ super();
3130
+ this.elementReference = elementReference;
3131
+ this.fNode = fNode;
3137
3132
  this.fComponentsStore = fComponentsStore;
3138
- this.fDraggableDataContext = fDraggableDataContext;
3139
- this.fExternalItemService = fExternalItemService;
3133
+ this.id = `f-node-input-${uniqueId$4++}`;
3134
+ this.multiple = true;
3135
+ this.isDisabled = false;
3136
+ this.isConnected = false;
3140
3137
  }
3141
- handle(event) {
3142
- if (isExternalItem(event.targetElement)) {
3143
- const item = this.fExternalItemService.getItem(getExternalItem(event.targetElement));
3144
- if (!item) {
3145
- throw new Error('External item not found');
3146
- }
3147
- const pointerPositionInFlow = Point.fromPoint(event.getPosition()).elementTransform(this.flowHost);
3148
- this.fDraggableDataContext.onPointerDownScale = 1;
3149
- this.fDraggableDataContext.onPointerDownPosition = pointerPositionInFlow.div(1);
3150
- this.fDraggableDataContext.draggableItems = [
3151
- new ExternalItemDragHandler(item)
3152
- ];
3138
+ ngOnInit() {
3139
+ if (!this.fNode) {
3140
+ throw new Error('fNodeInput must be inside f-node');
3153
3141
  }
3142
+ this.fComponentsStore.addInput(this);
3143
+ this.fNode.addConnector(this);
3154
3144
  }
3155
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ExternalItemPrepareDragSequence, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: FExternalItemService }], target: i0.ɵɵFactoryTarget.Injectable }); }
3156
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ExternalItemPrepareDragSequence }); }
3145
+ setConnected(isConnected) {
3146
+ this.isConnected = isConnected;
3147
+ this.hostElement.classList.toggle('f-node-input-connected', isConnected);
3148
+ }
3149
+ ngOnDestroy() {
3150
+ this.fNode.removeConnector(this);
3151
+ this.fComponentsStore.removeInput(this);
3152
+ }
3153
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeInputDirective, deps: [{ token: i0.ElementRef }, { token: F_NODE }, { token: FComponentsStore }], target: i0.ɵɵFactoryTarget.Directive }); }
3154
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FNodeInputDirective, selector: "[fNodeInput]", inputs: { id: ["fNodeInputId", "id"], multiple: ["fNodeInputMultiple", "multiple"], disabled: ["fNodeInputDisabled", "disabled"] }, host: { properties: { "attr.id": "id", "class.f-node-input-multiple": "multiple", "class.f-node-input-disabled": "disabled", "class.f-node-input-not-connectable": "!canBeConnected" }, classAttribute: "f-component f-node-input" }, providers: [{ provide: F_NODE_INPUT, useExisting: FNodeInputDirective }], exportAs: ["fNodeInput"], usesInheritance: true, ngImport: i0 }); }
3157
3155
  }
3158
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ExternalItemPrepareDragSequence, decorators: [{
3159
- type: Injectable
3160
- }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: FExternalItemService }] });
3156
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeInputDirective, decorators: [{
3157
+ type: Directive,
3158
+ args: [{
3159
+ selector: "[fNodeInput]",
3160
+ exportAs: 'fNodeInput',
3161
+ host: {
3162
+ '[attr.id]': 'id',
3163
+ class: "f-component f-node-input",
3164
+ '[class.f-node-input-multiple]': 'multiple',
3165
+ '[class.f-node-input-disabled]': 'disabled',
3166
+ '[class.f-node-input-not-connectable]': '!canBeConnected',
3167
+ },
3168
+ providers: [{ provide: F_NODE_INPUT, useExisting: FNodeInputDirective }],
3169
+ }]
3170
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: FNodeBase, decorators: [{
3171
+ type: Inject,
3172
+ args: [F_NODE]
3173
+ }] }, { type: FComponentsStore }], propDecorators: { id: [{
3174
+ type: Input,
3175
+ args: ['fNodeInputId']
3176
+ }], multiple: [{
3177
+ type: Input,
3178
+ args: ['fNodeInputMultiple']
3179
+ }], disabled: [{
3180
+ type: Input,
3181
+ args: ['fNodeInputDisabled']
3182
+ }] } });
3161
3183
 
3162
- class ExternalItemOnPointerUp {
3163
- get flowHost() {
3164
- return this.fComponentsStore.fFlow.hostElement;
3165
- }
3166
- get fCreateNode() {
3167
- return this.fComponentsStore.fDraggable.fCreateNode;
3184
+ const F_NODE_OUTLET = new InjectionToken('F_NODE_OUTLET');
3185
+ class FNodeOutletBase extends FConnectorBase {
3186
+ constructor() {
3187
+ super(...arguments);
3188
+ this.isConnected = false;
3189
+ this.outputs = [];
3168
3190
  }
3169
- constructor(fComponentsStore, fDraggableDataContext, getElementRectInFlowHandler) {
3170
- this.fComponentsStore = fComponentsStore;
3171
- this.fDraggableDataContext = fDraggableDataContext;
3172
- this.getElementRectInFlowHandler = getElementRectInFlowHandler;
3191
+ get canBeConnected() {
3192
+ return !this.disabled;
3173
3193
  }
3174
- handle(event) {
3175
- const pointerPositionInFlow = Point.fromPoint(event.getPosition()).elementTransform(this.flowHost);
3176
- let difference = pointerPositionInFlow.div(this.fDraggableDataContext.onPointerDownScale).sub(this.fDraggableDataContext.onPointerDownPosition);
3177
- const isDragPaletteItem = this.fDraggableDataContext.draggableItems.some((x) => x.type === EDraggableType.PALETTE_ITEM);
3178
- if (isDragPaletteItem) {
3179
- const dragHandler = this.fDraggableDataContext.draggableItems[0];
3180
- dragHandler.move(difference);
3181
- const isPointerInCanvasRect = document.elementsFromPoint(event.getPosition().x, event.getPosition().y).some((x) => x === this.flowHost);
3182
- if (isPointerInCanvasRect) {
3183
- const rectInCanvas = this.getElementRectInFlowHandler.handle(dragHandler.placeholder);
3184
- this.fCreateNode.emit(new CreateNodeEvent(rectInCanvas, dragHandler.externalItem.data));
3185
- }
3186
- dragHandler.complete();
3187
- }
3194
+ setOutputs(outputs) {
3195
+ this.outputs = outputs;
3188
3196
  }
3189
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ExternalItemOnPointerUp, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: GetElementRectInFlowHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
3190
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ExternalItemOnPointerUp }); }
3197
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeOutletBase, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
3198
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FNodeOutletBase, usesInheritance: true, ngImport: i0 }); }
3191
3199
  }
3192
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: ExternalItemOnPointerUp, decorators: [{
3193
- type: Injectable
3194
- }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: GetElementRectInFlowHandler }] });
3200
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeOutletBase, decorators: [{
3201
+ type: Directive
3202
+ }] });
3195
3203
 
3196
- const EXTERNAL_ITEM_PROVIDERS = [
3197
- ExternalItemOnPointerUp,
3198
- ExternalItemPrepareDragSequence
3199
- ];
3204
+ function isNodeOutlet(element) {
3205
+ return !!element.closest('[fNodeOutlet]');
3206
+ }
3200
3207
 
3201
- class ConnectionDragHandler {
3202
- constructor(getInputRectInFlowHandler, getOutputRectInFlowHandler, getConnectionVectorHandler, connection) {
3203
- this.getInputRectInFlowHandler = getInputRectInFlowHandler;
3204
- this.getOutputRectInFlowHandler = getOutputRectInFlowHandler;
3205
- this.getConnectionVectorHandler = getConnectionVectorHandler;
3206
- this.connection = connection;
3207
- this.type = EDraggableType.CONNECTION;
3208
- this.onPointerDownVector = VectorExtensions.initialize();
3209
- this.fromConnectorSide = EConnectorSide.BOTTOM;
3210
- this.toConnectorSide = EConnectorSide.TOP;
3208
+ let uniqueId$3 = 0;
3209
+ class FNodeOutletDirective extends FNodeOutletBase {
3210
+ get disabled() {
3211
+ return this.isDisabled;
3211
3212
  }
3212
- initialize() {
3213
- const fromConnector = this.getOutputRectInFlowHandler.handle(this.connection.outputId);
3214
- this.fromConnectorSide = fromConnector.side;
3215
- const toConnector = this.getInputRectInFlowHandler.handle(this.connection.inputId);
3216
- this.toConnectorSide = toConnector.side;
3217
- this.onPointerDownVector = this.getConnectionVectorHandler.handle(new GetConnectionVectorRequest(fromConnector.rect, toConnector.rect, this.connection.behavior, fromConnector.side, toConnector.side));
3213
+ set disabled(isDisabled) {
3214
+ const value = BooleanExtensions.castToBoolean(isDisabled);
3215
+ if (value !== this.isDisabled) {
3216
+ this.isDisabled = value;
3217
+ this.stateChanges.next();
3218
+ }
3219
+ }
3220
+ get hostElement() {
3221
+ return this.elementReference.nativeElement;
3222
+ }
3223
+ constructor(elementReference, fNode, fComponentsStore) {
3224
+ super();
3225
+ this.elementReference = elementReference;
3226
+ this.fNode = fNode;
3227
+ this.fComponentsStore = fComponentsStore;
3228
+ this.id = `f-node-outlet-${uniqueId$3++}`;
3229
+ this.isDisabled = false;
3230
+ this.isConnectionFromOutlet = false;
3231
+ }
3232
+ ngOnInit() {
3233
+ if (!this.fNode) {
3234
+ throw new Error('fNodeOutlet must be inside f-node');
3235
+ }
3236
+ this.fComponentsStore.addOutlet(this);
3237
+ }
3238
+ ngOnDestroy() {
3239
+ this.fComponentsStore.removeOutlet(this);
3240
+ }
3241
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeOutletDirective, deps: [{ token: i0.ElementRef }, { token: F_NODE }, { token: FComponentsStore }], target: i0.ɵɵFactoryTarget.Directive }); }
3242
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FNodeOutletDirective, selector: "[fNodeOutlet]", inputs: { id: ["fNodeOutletId", "id"], disabled: ["fNodeOutletDisabled", "disabled"], isConnectionFromOutlet: "isConnectionFromOutlet" }, host: { properties: { "attr.id": "id", "class.f-node-outlet-disabled": "disabled" }, classAttribute: "f-component f-node-outlet" }, providers: [{ provide: F_NODE_OUTLET, useExisting: FNodeOutletDirective }], exportAs: ["fNodeOutlet"], usesInheritance: true, ngImport: i0 }); }
3243
+ }
3244
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeOutletDirective, decorators: [{
3245
+ type: Directive,
3246
+ args: [{
3247
+ selector: "[fNodeOutlet]",
3248
+ exportAs: 'fNodeOutlet',
3249
+ host: {
3250
+ '[attr.id]': 'id',
3251
+ class: "f-component f-node-outlet",
3252
+ '[class.f-node-outlet-disabled]': 'disabled'
3253
+ },
3254
+ providers: [{ provide: F_NODE_OUTLET, useExisting: FNodeOutletDirective }],
3255
+ }]
3256
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: FNodeBase, decorators: [{
3257
+ type: Inject,
3258
+ args: [F_NODE]
3259
+ }] }, { type: FComponentsStore }], propDecorators: { id: [{
3260
+ type: Input,
3261
+ args: ['fNodeOutletId']
3262
+ }], disabled: [{
3263
+ type: Input,
3264
+ args: ['fNodeOutletDisabled']
3265
+ }], isConnectionFromOutlet: [{
3266
+ type: Input
3267
+ }] } });
3268
+
3269
+ const F_NODE_OUTPUT = new InjectionToken('F_NODE_OUTPUT');
3270
+ class FNodeOutputBase extends FConnectorBase {
3271
+ constructor() {
3272
+ super(...arguments);
3273
+ this.isConnected = false;
3218
3274
  }
3219
- move(difference) {
3220
- const fromPoint = Point.fromPoint(this.onPointerDownVector.point1).add(difference);
3221
- const toPoint = Point.fromPoint(this.onPointerDownVector.point2).add(difference);
3222
- this.connection.setVector(fromPoint, this.fromConnectorSide, toPoint, this.toConnectorSide);
3223
- this.connection.redraw();
3275
+ get canBeConnected() {
3276
+ return !this.disabled && !this.isConnected;
3224
3277
  }
3278
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeOutputBase, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
3279
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FNodeOutputBase, usesInheritance: true, ngImport: i0 }); }
3225
3280
  }
3281
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeOutputBase, decorators: [{
3282
+ type: Directive
3283
+ }] });
3226
3284
 
3227
- class ConnectionSourceDragHandler {
3228
- constructor(getInputRectInFlowHandler, getOutputRectInFlowHandler, getConnectionVectorHandler, connection) {
3229
- this.getInputRectInFlowHandler = getInputRectInFlowHandler;
3230
- this.getOutputRectInFlowHandler = getOutputRectInFlowHandler;
3231
- this.getConnectionVectorHandler = getConnectionVectorHandler;
3232
- this.connection = connection;
3233
- this.type = EDraggableType.CONNECTION;
3234
- this.fromConnectorRect = RectExtensions.initialize();
3235
- this.fromConnectorSide = EConnectorSide.BOTTOM;
3236
- this.toConnectorRect = RectExtensions.initialize();
3237
- this.toConnectorSide = EConnectorSide.TOP;
3238
- }
3239
- initialize() {
3240
- const fromConnector = this.getOutputRectInFlowHandler.handle(this.connection.outputId);
3241
- this.fromConnectorRect = fromConnector.rect;
3242
- this.fromConnectorSide = fromConnector.side;
3243
- const toConnector = this.getInputRectInFlowHandler.handle(this.connection.inputId);
3244
- this.toConnectorRect = toConnector.rect;
3245
- this.toConnectorSide = toConnector.side;
3246
- }
3247
- move(difference) {
3248
- const fromConnectorRect = RectExtensions.addPoint(this.fromConnectorRect, difference);
3249
- const vector = this.getConnectionVectorHandler.handle(new GetConnectionVectorRequest(fromConnectorRect, this.toConnectorRect, this.connection.behavior, this.fromConnectorSide, this.toConnectorSide));
3250
- this.connection.setVector(vector.point1, this.fromConnectorSide, vector.point2, this.toConnectorSide);
3251
- this.connection.redraw();
3252
- }
3285
+ function isNodeOutput(element) {
3286
+ return !!element.closest('[fNodeOutput]');
3253
3287
  }
3254
3288
 
3255
- class ConnectionTargetDragHandler {
3256
- constructor(getInputRectInFlowHandler, getOutputRectInFlowHandler, getConnectionVectorHandler, connection) {
3257
- this.getInputRectInFlowHandler = getInputRectInFlowHandler;
3258
- this.getOutputRectInFlowHandler = getOutputRectInFlowHandler;
3259
- this.getConnectionVectorHandler = getConnectionVectorHandler;
3260
- this.connection = connection;
3261
- this.type = EDraggableType.CONNECTION;
3262
- this.fromConnectorRect = RectExtensions.initialize();
3263
- this.fromConnectorSide = EConnectorSide.BOTTOM;
3264
- this.toConnectorRect = RectExtensions.initialize();
3265
- this.toConnectorSide = EConnectorSide.TOP;
3289
+ let uniqueId$2 = 0;
3290
+ class FNodeOutputDirective extends FNodeOutputBase {
3291
+ get disabled() {
3292
+ return this.isDisabled;
3266
3293
  }
3267
- initialize() {
3268
- const fromConnector = this.getOutputRectInFlowHandler.handle(this.connection.outputId);
3269
- this.fromConnectorRect = fromConnector.rect;
3270
- this.fromConnectorSide = fromConnector.side;
3271
- const toConnector = this.getInputRectInFlowHandler.handle(this.connection.inputId);
3272
- this.toConnectorRect = toConnector.rect;
3273
- this.toConnectorSide = toConnector.side;
3294
+ set disabled(isDisabled) {
3295
+ const value = BooleanExtensions.castToBoolean(isDisabled);
3296
+ if (value !== this.isDisabled) {
3297
+ this.isDisabled = value;
3298
+ this.stateChanges.next();
3299
+ }
3274
3300
  }
3275
- move(difference) {
3276
- const toConnectorRect = RectExtensions.addPoint(this.toConnectorRect, difference);
3277
- const vector = this.getConnectionVectorHandler.handle(new GetConnectionVectorRequest(this.fromConnectorRect, toConnectorRect, this.connection.behavior, this.fromConnectorSide, this.toConnectorSide));
3278
- this.connection.setVector(vector.point1, this.fromConnectorSide, vector.point2, this.toConnectorSide);
3279
- this.connection.redraw();
3301
+ get hostElement() {
3302
+ return this.elementReference.nativeElement;
3280
3303
  }
3281
- }
3282
-
3283
- class NodeDragHandler {
3284
- constructor(fDraggableDataContext, fNode) {
3285
- this.fDraggableDataContext = fDraggableDataContext;
3304
+ constructor(elementReference, fNode, fComponentsStore) {
3305
+ super();
3306
+ this.elementReference = elementReference;
3286
3307
  this.fNode = fNode;
3287
- this.type = EDraggableType.NODE;
3288
- this.onPointerDownPosition = PointExtensions.initialize();
3289
- this.onPointerDownPosition = this.fNode.position;
3308
+ this.fComponentsStore = fComponentsStore;
3309
+ this.id = `f-node-output-${uniqueId$2++}`;
3310
+ this.isDisabled = false;
3311
+ this.isConnected = false;
3290
3312
  }
3291
- move(difference) {
3292
- const position = Point.fromPoint(this.onPointerDownPosition).add(difference);
3293
- this.fNode.updatePosition(position);
3294
- this.fNode.redraw();
3295
- this.fDraggableDataContext.fLineAlignment?.handle(difference);
3313
+ ngOnInit() {
3314
+ if (!this.fNode) {
3315
+ throw new Error('fNodeOutput must be inside f-node');
3316
+ }
3317
+ this.fComponentsStore.addOutput(this);
3318
+ this.fNode.addConnector(this);
3296
3319
  }
3297
- complete() {
3298
- this.fNode.completeDrag();
3320
+ setConnected(isConnected) {
3321
+ this.isConnected = isConnected;
3322
+ this.hostElement.classList.toggle('f-node-output-connected', isConnected);
3323
+ }
3324
+ ngOnDestroy() {
3325
+ this.fNode.removeConnector(this);
3326
+ this.fComponentsStore.removeOutput(this);
3299
3327
  }
3328
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeOutputDirective, deps: [{ token: i0.ElementRef }, { token: F_NODE }, { token: FComponentsStore }], target: i0.ɵɵFactoryTarget.Directive }); }
3329
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FNodeOutputDirective, selector: "[fNodeOutput]", inputs: { id: ["fNodeOutputId", "id"], disabled: ["fNodeOutputDisabled", "disabled"] }, host: { properties: { "attr.id": "id", "class.f-node-output-disabled": "disabled" }, classAttribute: "f-component f-node-output" }, providers: [{ provide: F_NODE_OUTPUT, useExisting: FNodeOutputDirective }], exportAs: ["fNodeOutput"], usesInheritance: true, ngImport: i0 }); }
3300
3330
  }
3331
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeOutputDirective, decorators: [{
3332
+ type: Directive,
3333
+ args: [{
3334
+ selector: "[fNodeOutput]",
3335
+ exportAs: 'fNodeOutput',
3336
+ host: {
3337
+ '[attr.id]': 'id',
3338
+ class: "f-component f-node-output",
3339
+ '[class.f-node-output-disabled]': 'disabled',
3340
+ },
3341
+ providers: [{ provide: F_NODE_OUTPUT, useExisting: FNodeOutputDirective }],
3342
+ }]
3343
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: FNodeBase, decorators: [{
3344
+ type: Inject,
3345
+ args: [F_NODE]
3346
+ }] }, { type: FComponentsStore }], propDecorators: { id: [{
3347
+ type: Input,
3348
+ args: ['fNodeOutputId']
3349
+ }], disabled: [{
3350
+ type: Input,
3351
+ args: ['fNodeOutputDisabled']
3352
+ }] } });
3301
3353
 
3302
- class IsConnectionUnderNodeHandler {
3303
- get transform() {
3304
- return this.fComponentsStore.fCanvas.transform;
3305
- }
3306
- get flowHost() {
3307
- return this.fComponentsStore.fFlow.hostElement;
3308
- }
3309
- constructor(fComponentsStore, fDraggableDataContext, getElementRectInFlowHandler, getOutgoingConnectionsHandler, getIncomingConnectionsHandler) {
3310
- this.fComponentsStore = fComponentsStore;
3311
- this.fDraggableDataContext = fDraggableDataContext;
3312
- this.getElementRectInFlowHandler = getElementRectInFlowHandler;
3313
- this.getOutgoingConnectionsHandler = getOutgoingConnectionsHandler;
3314
- this.getIncomingConnectionsHandler = getIncomingConnectionsHandler;
3354
+ const F_DRAG_HANDLE = new InjectionToken('F_DRAG_HANDLE');
3355
+ class FDragHandleDirective {
3356
+ get disabled() {
3357
+ return this.isDisabled;
3315
3358
  }
3316
- handle() {
3317
- const isValid = this.isValidRequest();
3318
- if (!isValid) {
3319
- return;
3320
- }
3321
- const fNode = this.fDraggableDataContext.draggableItems[0].fNode;
3322
- const outputsOfNode = this.getOutputsForNode(fNode);
3323
- const inputsOfNode = this.getInputsForNode(fNode);
3324
- const isCantBeConnectedByOutput = outputsOfNode.some((x) => !x.canBeConnected);
3325
- const isCantBeConnectedByInput = this.fComponentsStore.fConnections.some((x) => {
3326
- return inputsOfNode.find((input) => input.id === x.inputId);
3327
- });
3328
- if (!isCantBeConnectedByInput && outputsOfNode.length && !isCantBeConnectedByOutput && inputsOfNode.length) {
3329
- const output = outputsOfNode[0];
3330
- const input = inputsOfNode[0];
3331
- const outgoingConnections = this.getOutgoingConnectionsHandler.handle([output]);
3332
- const incomingConnections = this.getIncomingConnectionsHandler.handle([input]);
3333
- if (outgoingConnections.length === 0 && incomingConnections.length === 0) {
3334
- const connections = this.findConnectionsUnderNode(fNode);
3335
- if (connections.length) {
3336
- }
3337
- }
3359
+ set disabled(isDisabled) {
3360
+ const value = BooleanExtensions.castToBoolean(isDisabled);
3361
+ if (value !== this.isDisabled) {
3362
+ this.isDisabled = value;
3363
+ this.stateChanges.next();
3338
3364
  }
3339
3365
  }
3340
- isValidRequest() {
3341
- const result = this.fDraggableDataContext.draggableItems.length === 1 &&
3342
- this.fDraggableDataContext.draggableItems[0].type === EDraggableType.NODE;
3343
- return result;
3366
+ get hostElement() {
3367
+ return this.elementReference.nativeElement;
3344
3368
  }
3345
- getOutputsForNode(node) {
3346
- return this.fComponentsStore.fOutputs.filter((x) => node.isContains(x.hostElement));
3369
+ constructor(elementReference, _parentNode) {
3370
+ this.elementReference = elementReference;
3371
+ this.stateChanges = new Subject();
3372
+ this.isDisabled = false;
3373
+ this._parentNode = _parentNode;
3347
3374
  }
3348
- getInputsForNode(node) {
3349
- return this.fComponentsStore.fInputs.filter((x) => node.isContains(x.hostElement));
3375
+ ngOnDestroy() {
3376
+ this.stateChanges.complete();
3350
3377
  }
3351
- findConnectionsUnderNode(node) {
3352
- const nodeRect = this.getElementRectInFlowHandler.handle(node.hostElement);
3353
- return this.fComponentsStore.fConnections.filter((x) => {
3354
- const intersection = RectExtensions.intersectionWithVector(nodeRect, x.vector.point1, x.vector.point2);
3355
- return (intersection || []).length > 0;
3356
- });
3378
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FDragHandleDirective, deps: [{ token: i0.ElementRef }, { token: F_NODE, optional: true, skipSelf: true }], target: i0.ɵɵFactoryTarget.Directive }); }
3379
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FDragHandleDirective, isStandalone: true, selector: "[fDragHandle]", inputs: { disabled: ["fDragHandleDisabled", "disabled"] }, host: { properties: { "class.f-drag-handle-disabled": "disabled" }, classAttribute: "f-drag-handle f-component" }, providers: [{ provide: F_DRAG_HANDLE, useExisting: FDragHandleDirective }], ngImport: i0 }); }
3380
+ }
3381
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FDragHandleDirective, decorators: [{
3382
+ type: Directive,
3383
+ args: [{
3384
+ selector: "[fDragHandle]",
3385
+ standalone: true,
3386
+ host: {
3387
+ class: "f-drag-handle f-component",
3388
+ '[class.f-drag-handle-disabled]': 'disabled'
3389
+ },
3390
+ providers: [{ provide: F_DRAG_HANDLE, useExisting: FDragHandleDirective }],
3391
+ }]
3392
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: undefined, decorators: [{
3393
+ type: Inject,
3394
+ args: [F_NODE]
3395
+ }, {
3396
+ type: Optional
3397
+ }, {
3398
+ type: SkipSelf
3399
+ }] }], propDecorators: { disabled: [{
3400
+ type: Input,
3401
+ args: ['fDragHandleDisabled']
3402
+ }] } });
3403
+
3404
+ function isNodeDragHandle(element) {
3405
+ const dragHandle = getClosestDragHandle(element);
3406
+ return !!dragHandle && !isElementOrParentExcluded(element);
3407
+ }
3408
+ function isElementOrParentExcluded(element) {
3409
+ const isContains = isElementContainsClass(element);
3410
+ const parentElement = element.parentElement;
3411
+ const dragHandle = getClosestDragHandle(parentElement);
3412
+ if (!isContains && !!dragHandle) {
3413
+ return isElementOrParentExcluded(parentElement);
3357
3414
  }
3358
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: IsConnectionUnderNodeHandler, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: GetElementRectInFlowHandler }, { token: GetOutgoingConnectionsHandler }, { token: GetIncomingConnectionsHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
3359
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: IsConnectionUnderNodeHandler }); }
3415
+ return isContains;
3416
+ }
3417
+ function getClosestDragHandle(element) {
3418
+ return element.closest('.f-drag-handle');
3419
+ }
3420
+ function isElementContainsClass(element) {
3421
+ return element.classList.contains('f-drag-handle-disabled');
3360
3422
  }
3361
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: IsConnectionUnderNodeHandler, decorators: [{
3362
- type: Injectable
3363
- }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: GetElementRectInFlowHandler }, { type: GetOutgoingConnectionsHandler }, { type: GetIncomingConnectionsHandler }] });
3364
3423
 
3365
- class NodeOnPointerUp {
3366
- get transform() {
3367
- return this.fComponentsStore.fCanvas.transform;
3368
- }
3369
- get flowHost() {
3370
- return this.fComponentsStore.fFlow.hostElement;
3371
- }
3372
- constructor(fComponentsStore, fDraggableDataContext, isConnectionUnderNodeHandler) {
3373
- this.fComponentsStore = fComponentsStore;
3374
- this.fDraggableDataContext = fDraggableDataContext;
3375
- this.isConnectionUnderNodeHandler = isConnectionUnderNodeHandler;
3376
- }
3377
- handle(event) {
3378
- const pointerPositionInFlow = Point.fromPoint(event.getPosition()).elementTransform(this.flowHost);
3379
- let difference = pointerPositionInFlow.div(this.fDraggableDataContext.onPointerDownScale).sub(this.fDraggableDataContext.onPointerDownPosition);
3380
- const isDragNodes = this.fDraggableDataContext.draggableItems.some((x) => x.type === EDraggableType.NODE);
3381
- if (isDragNodes) {
3382
- const nearestIntersection = this.fDraggableDataContext.fLineAlignment?.findNearestCoordinate(difference);
3383
- if (nearestIntersection) {
3384
- difference.x = nearestIntersection.xResult.value ? (difference.x - nearestIntersection.xResult.distance) : difference.x;
3385
- difference.y = nearestIntersection.yResult.value ? (difference.y - nearestIntersection.yResult.distance) : difference.y;
3386
- }
3387
- this.fDraggableDataContext.draggableItems.forEach((x) => {
3388
- x.move(difference);
3389
- x.complete?.();
3424
+ class FResizeObserver extends Observable {
3425
+ constructor(element) {
3426
+ super(subscriber => {
3427
+ const observer = new ResizeObserver(entries => {
3428
+ subscriber.next(entries);
3390
3429
  });
3391
- this.isConnectionUnderNodeHandler.handle();
3392
- this.fDraggableDataContext.fLineAlignment?.complete();
3393
- }
3430
+ observer.observe(element);
3431
+ return function unsubscribe() {
3432
+ observer.unobserve(element);
3433
+ observer.disconnect();
3434
+ };
3435
+ });
3394
3436
  }
3395
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: NodeOnPointerUp, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: IsConnectionUnderNodeHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
3396
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: NodeOnPointerUp }); }
3397
3437
  }
3398
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: NodeOnPointerUp, decorators: [{
3399
- type: Injectable
3400
- }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: IsConnectionUnderNodeHandler }] });
3401
3438
 
3402
- class NodePrepareDragSequence {
3403
- get transform() {
3404
- return this.fComponentsStore.fCanvas.transform;
3439
+ let uniqueId$1 = 0;
3440
+ class FNodeComponent extends FNodeBase {
3441
+ set position(value) {
3442
+ this._position = PointExtensions.castToPoint(value);
3443
+ this.refresh();
3405
3444
  }
3406
- get flowHost() {
3407
- return this.fComponentsStore.fFlow.hostElement;
3445
+ get position() {
3446
+ return this._position;
3408
3447
  }
3409
- constructor(fComponentsStore, fDraggableDataContext, updateNodeLayerHandler, getInputRectInFlowHandler, getOutputRectInFlowHandler, getOutgoingConnectionsHandler, getIncomingConnectionsHandler, getConnectionVectorHandler) {
3448
+ get hostElement() {
3449
+ return this.elementReference.nativeElement;
3450
+ }
3451
+ constructor(elementReference, fComponentsStore) {
3452
+ super();
3453
+ this.elementReference = elementReference;
3410
3454
  this.fComponentsStore = fComponentsStore;
3411
- this.fDraggableDataContext = fDraggableDataContext;
3412
- this.updateNodeLayerHandler = updateNodeLayerHandler;
3413
- this.getInputRectInFlowHandler = getInputRectInFlowHandler;
3414
- this.getOutputRectInFlowHandler = getOutputRectInFlowHandler;
3415
- this.getOutgoingConnectionsHandler = getOutgoingConnectionsHandler;
3416
- this.getIncomingConnectionsHandler = getIncomingConnectionsHandler;
3417
- this.getConnectionVectorHandler = getConnectionVectorHandler;
3455
+ this.subscriptions$ = new Subscription();
3456
+ this.id = `f-node-${uniqueId$1++}`;
3457
+ this.positionChange = new EventEmitter();
3458
+ this.disabled = false;
3459
+ this.connectors = [];
3418
3460
  }
3419
- handle(event) {
3420
- const node = this.fComponentsStore.findNode(event.targetElement);
3421
- const pointerPositionInFlow = Point.fromPoint(event.getPosition()).elementTransform(this.flowHost);
3422
- if (node && !node.disabled && !this.fDraggableDataContext.draggableItems.length) {
3423
- if (isNodeDragHandle(event.targetElement)) {
3424
- if (!this.fDraggableDataContext.selectedItems.includes(node)) {
3425
- this.fDraggableDataContext.selectedItems.push(node);
3426
- node.select();
3427
- }
3428
- this.updateNodeLayerHandler.handle(node);
3429
- const itemsToDrag = this.calculateDraggableConnectionsAndNodes();
3430
- const draggedNodes = itemsToDrag.filter((x) => {
3431
- return x.type === EDraggableType.NODE;
3432
- }).map((x) => x.fNode);
3433
- this.fDraggableDataContext.fLineAlignment?.initialize(this.fComponentsStore.fNodes, draggedNodes);
3434
- this.fDraggableDataContext.onPointerDownScale = this.transform.scale;
3435
- this.fDraggableDataContext.onPointerDownPosition = pointerPositionInFlow.div(this.transform.scale);
3436
- this.fDraggableDataContext.draggableItems = itemsToDrag;
3437
- }
3438
- }
3461
+ ngOnInit() {
3462
+ super.redraw();
3463
+ this.fComponentsStore.addNode(this);
3439
3464
  }
3440
- calculateDraggableConnectionsAndNodes() {
3441
- let itemsToDrag = [];
3442
- const selectedNodes = this.fDraggableDataContext.selectedItems.map((x) => {
3443
- return this.fComponentsStore.findNode(x.hostElement);
3444
- }).filter((x) => !!x);
3445
- const nodeDragHandlers = selectedNodes.map((x) => new NodeDragHandler(this.fDraggableDataContext, x));
3446
- itemsToDrag = nodeDragHandlers;
3447
- const allOutputIds = selectedNodes.reduce((result, x) => {
3448
- return result.concat(this.getOutputsForNode(x));
3449
- }, []).map((x) => x.id);
3450
- const allInputIds = selectedNodes.reduce((result, x) => {
3451
- return result.concat(this.getInputsForNode(x));
3452
- }, []).map((x) => x.id);
3453
- nodeDragHandlers.forEach((nodeHandler) => {
3454
- const outputConnections = this.getOutgoingConnectionsHandler.handle(this.getOutputsForNode(nodeHandler.fNode));
3455
- outputConnections.forEach((c) => {
3456
- if (allInputIds.includes(c.inputId)) {
3457
- itemsToDrag.push(new ConnectionDragHandler(this.getInputRectInFlowHandler, this.getOutputRectInFlowHandler, this.getConnectionVectorHandler, c));
3458
- }
3459
- else {
3460
- itemsToDrag.push(new ConnectionSourceDragHandler(this.getInputRectInFlowHandler, this.getOutputRectInFlowHandler, this.getConnectionVectorHandler, c));
3461
- }
3462
- });
3463
- const inputConnections = this.getIncomingConnectionsHandler.handle(this.getInputsForNode(nodeHandler.fNode));
3464
- inputConnections.forEach((c) => {
3465
- if (allOutputIds.includes(c.outputId)) {
3466
- const index = itemsToDrag.findIndex((x) => x.type === EDraggableType.CONNECTION && x.connection.id === c.id);
3467
- if (index !== -1) {
3468
- itemsToDrag.push(new ConnectionDragHandler(this.getInputRectInFlowHandler, this.getOutputRectInFlowHandler, this.getConnectionVectorHandler, c));
3469
- }
3470
- }
3471
- else {
3472
- itemsToDrag.push(new ConnectionTargetDragHandler(this.getInputRectInFlowHandler, this.getOutputRectInFlowHandler, this.getConnectionVectorHandler, c));
3473
- }
3465
+ ngAfterViewInit() {
3466
+ this.subscriptions$.add(this.subscribeOnResizeChanges());
3467
+ }
3468
+ subscribeOnResizeChanges() {
3469
+ return new FResizeObserver(this.hostElement).pipe(startWith(null)).subscribe(() => {
3470
+ this.connectors.forEach((connector) => {
3471
+ connector.side = new GetConnectorSideInNodeHandler().handle(connector.hostElement, this.hostElement);
3474
3472
  });
3473
+ this.fComponentsStore.changes.next();
3475
3474
  });
3476
- return itemsToDrag;
3477
3475
  }
3478
- getInputsForNode(node) {
3479
- return this.fComponentsStore.fInputs.filter((x) => node.isContains(x.hostElement));
3476
+ addConnector(connector) {
3477
+ this.connectors.push(connector);
3480
3478
  }
3481
- getOutputsForNode(node) {
3482
- return this.fComponentsStore.fOutputs.filter((x) => node.isContains(x.hostElement));
3479
+ removeConnector(connector) {
3480
+ const index = this.connectors.indexOf(connector);
3481
+ if (index !== -1) {
3482
+ this.connectors.splice(index, 1);
3483
+ }
3483
3484
  }
3484
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: NodePrepareDragSequence, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: UpdateNodeLayerHandler }, { token: GetInputRectInFlowHandler }, { token: GetOutputRectInFlowHandler }, { token: GetOutgoingConnectionsHandler }, { token: GetIncomingConnectionsHandler }, { token: GetConnectionVectorHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
3485
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: NodePrepareDragSequence }); }
3485
+ refresh() {
3486
+ this.stateChanges.next();
3487
+ }
3488
+ ngOnDestroy() {
3489
+ this.fComponentsStore.removeNode(this);
3490
+ this.stateChanges.complete();
3491
+ this.subscriptions$.unsubscribe();
3492
+ }
3493
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeComponent, deps: [{ token: i0.ElementRef }, { token: FComponentsStore }], target: i0.ɵɵFactoryTarget.Component }); }
3494
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.9", type: FNodeComponent, selector: "f-node", inputs: { id: "id", position: ["fNodePosition", "position"], disabled: "disabled" }, outputs: { positionChange: "fNodePositionChange" }, host: { properties: { "attr.id": "id", "class.f-node-disabled": "disabled" }, classAttribute: "f-node f-component" }, providers: [
3495
+ { provide: F_NODE, useExisting: FNodeComponent }
3496
+ ], exportAs: ["fComponent"], usesInheritance: true, ngImport: i0, template: "<ng-content></ng-content>\n", styles: [":host{position:absolute!important;left:0;top:0;pointer-events:all;transform-origin:0 0;-webkit-user-select:none;user-select:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3486
3497
  }
3487
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: NodePrepareDragSequence, decorators: [{
3488
- type: Injectable
3489
- }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: UpdateNodeLayerHandler }, { type: GetInputRectInFlowHandler }, { type: GetOutputRectInFlowHandler }, { type: GetOutgoingConnectionsHandler }, { type: GetIncomingConnectionsHandler }, { type: GetConnectionVectorHandler }] });
3498
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FNodeComponent, decorators: [{
3499
+ type: Component,
3500
+ args: [{ selector: "f-node", exportAs: "fComponent", changeDetection: ChangeDetectionStrategy.OnPush, host: {
3501
+ '[attr.id]': 'id',
3502
+ class: "f-node f-component",
3503
+ '[class.f-node-disabled]': 'disabled',
3504
+ }, providers: [
3505
+ { provide: F_NODE, useExisting: FNodeComponent }
3506
+ ], template: "<ng-content></ng-content>\n", styles: [":host{position:absolute!important;left:0;top:0;pointer-events:all;transform-origin:0 0;-webkit-user-select:none;user-select:none}\n"] }]
3507
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: FComponentsStore }], propDecorators: { id: [{
3508
+ type: Input
3509
+ }], position: [{
3510
+ type: Input,
3511
+ args: ['fNodePosition']
3512
+ }], positionChange: [{
3513
+ type: Output,
3514
+ args: ['fNodePositionChange']
3515
+ }], disabled: [{
3516
+ type: Input
3517
+ }] } });
3490
3518
 
3491
- const NODE_PROVIDERS = [
3492
- NodeOnPointerUp,
3493
- NodePrepareDragSequence,
3494
- IsConnectionUnderNodeHandler
3495
- ];
3519
+ function isNode(element) {
3520
+ return !!element.closest('f-node');
3521
+ }
3496
3522
 
3497
- class SingleSelectOnPointerDown {
3498
- constructor(fComponentsStore, fDraggableDataContext, getConnectionHandler) {
3523
+ const F_ZOOM = new InjectionToken('F_ZOOM');
3524
+ class FZoomBase {
3525
+ get flowHost() {
3526
+ return this.fComponentsStore.flowHost;
3527
+ }
3528
+ get fCanvas() {
3529
+ return this.fComponentsStore.fCanvas;
3530
+ }
3531
+ constructor(fComponentsStore) {
3499
3532
  this.fComponentsStore = fComponentsStore;
3500
- this.fDraggableDataContext = fDraggableDataContext;
3501
- this.getConnectionHandler = getConnectionHandler;
3533
+ this.isEnabled = false;
3534
+ this.listeners = EventExtensions.emptyListener();
3502
3535
  }
3503
- handle(event) {
3504
- const node = this.fComponentsStore.findNode(event.targetElement);
3505
- const connection = this.getConnectionHandler.handle(event.targetElement);
3506
- this.deselectAll(node, event);
3507
- this.resetSelectionIfNotMultiselect(event);
3508
- if (node) {
3509
- if (!this.fDraggableDataContext.selectedItems.includes(node)) {
3510
- this.fDraggableDataContext.selectedItems.push(node);
3511
- }
3512
- else {
3513
- this.fDraggableDataContext.selectedItems.splice(this.fDraggableDataContext.selectedItems.indexOf(node), 1);
3514
- }
3536
+ toggleZoom() {
3537
+ if (this.isEnabled) {
3538
+ this.subscribe();
3515
3539
  }
3516
- else if (connection) {
3517
- if (!this.fDraggableDataContext.selectedItems.includes(connection)) {
3518
- this.fDraggableDataContext.selectedItems.push(connection);
3519
- }
3520
- else {
3521
- this.fDraggableDataContext.selectedItems.splice(this.fDraggableDataContext.selectedItems.indexOf(connection), 1);
3522
- }
3540
+ else {
3541
+ this.unsubscribe();
3523
3542
  }
3524
- this.selectIfNotSelected();
3525
- }
3526
- deselectAll(node, event) {
3527
- this.fDraggableDataContext.selectedItems.forEach((x) => {
3528
- if (x !== node || (!isNodeOutlet(event.targetElement) && !isNodeOutput(event.targetElement))) {
3529
- x.deselect();
3530
- }
3531
- });
3532
3543
  }
3533
- resetSelectionIfNotMultiselect(event) {
3534
- const isMultiselect = MouseEventExtensions.isCommandButton(event.originalEvent) ||
3535
- MouseEventExtensions.isShiftPressed(event.originalEvent);
3536
- if (!isMultiselect) {
3537
- this.fDraggableDataContext.selectedItems = [];
3544
+ subscribe() {
3545
+ this.listeners();
3546
+ if (!this.flowHost) {
3547
+ return;
3538
3548
  }
3549
+ this.flowHost.addEventListener('wheel', this.onWheel.bind(this));
3550
+ this.flowHost.addEventListener('dblclick', this.onDoubleClick.bind(this));
3551
+ this.listeners = () => {
3552
+ this.flowHost.removeEventListener('wheel', this.onWheel.bind(this));
3553
+ this.flowHost.removeEventListener('dblclick', this.onDoubleClick.bind(this));
3554
+ };
3539
3555
  }
3540
- selectIfNotSelected() {
3541
- this.fDraggableDataContext.selectedItems.forEach((x) => {
3542
- if (!x.isSelected()) {
3543
- x.select();
3544
- }
3545
- });
3546
- }
3547
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SingleSelectOnPointerDown, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: GetConnectionHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
3548
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SingleSelectOnPointerDown }); }
3549
- }
3550
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SingleSelectOnPointerDown, decorators: [{
3551
- type: Injectable
3552
- }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: GetConnectionHandler }] });
3553
-
3554
- const SINGLE_SELECT_PROVIDERS = [
3555
- SingleSelectOnPointerDown
3556
- ];
3557
-
3558
- class SelectionChangeEvent {
3559
- constructor(nodes, connections) {
3560
- this.nodes = nodes;
3561
- this.connections = connections;
3556
+ getScale() {
3557
+ return this.fCanvas.transform.scale || 1;
3562
3558
  }
3563
- }
3564
-
3565
- class GetCanBeSelectedItemsHandler {
3566
- get fNodes() {
3567
- return this.fComponentsStore.fNodes;
3559
+ onWheel(event) {
3560
+ event.preventDefault();
3561
+ if (this.fComponentsStore.fDraggable?.isDragStarted) {
3562
+ return;
3563
+ }
3564
+ let result = this.getScale();
3565
+ const direction = event.deltaY > 0 ? -1 : 1;
3566
+ const step = this.step;
3567
+ result = result + step * direction;
3568
+ result = Math.max(this.minimum, Math.min(result, this.maximum));
3569
+ const pointerPositionInFlow = new Point(event.clientX, event.clientY).elementTransform(this.flowHost);
3570
+ this.fCanvas.setZoom(result, pointerPositionInFlow);
3571
+ this.fCanvas.redraw();
3572
+ this.fCanvas.completeDrag();
3568
3573
  }
3569
- get fConnections() {
3570
- return this.fComponentsStore.fConnections;
3574
+ onDoubleClick(event) {
3575
+ event.preventDefault();
3576
+ if (this.fComponentsStore.fDraggable?.isDragStarted || isNode(event.target)) {
3577
+ return;
3578
+ }
3579
+ let result = this.getScale();
3580
+ const direction = 1;
3581
+ const step = this.dblClickStep;
3582
+ result = result + step * direction;
3583
+ result = Math.max(this.minimum, Math.min(result, this.maximum));
3584
+ const pointerPositionInFlow = new Point(event.clientX, event.clientY).elementTransform(this.flowHost);
3585
+ this.fCanvas.setZoom(result, pointerPositionInFlow);
3586
+ this.fCanvas.redrawWithAnimation();
3587
+ this.fCanvas.completeDrag();
3571
3588
  }
3572
- get transform() {
3573
- return this.fComponentsStore.fCanvas.transform;
3589
+ onZoomToCenter(deltaY, position) {
3590
+ const preventDefault = () => {
3591
+ };
3592
+ const rect = RectExtensions.fromElement(this.flowHost);
3593
+ this.onWheel({
3594
+ deltaY, preventDefault, clientX: position?.x || rect.gravityCenter.x, clientY: position?.y || rect.gravityCenter.y
3595
+ });
3574
3596
  }
3575
- constructor(fComponentsStore, fDraggableDataContext, getElementRectInFlowHandler) {
3576
- this.fComponentsStore = fComponentsStore;
3577
- this.fDraggableDataContext = fDraggableDataContext;
3578
- this.getElementRectInFlowHandler = getElementRectInFlowHandler;
3597
+ zoomIn(position) {
3598
+ this.onZoomToCenter(-1, position);
3579
3599
  }
3580
- handle() {
3581
- const nodeRects = this.getNodesWithRects();
3582
- const lineRects = this.getConnectionsWithRects();
3583
- const result = [...nodeRects, ...lineRects].filter((x) => {
3584
- return !this.fDraggableDataContext.selectedItems.includes(x.element);
3585
- });
3586
- return result;
3600
+ zoomOut(position) {
3601
+ this.onZoomToCenter(1, position);
3587
3602
  }
3588
- getNodesWithRects() {
3589
- return this.fNodes.map((x) => {
3590
- const rect = this.getElementRectInFlowHandler.handle(x.hostElement);
3591
- return {
3592
- element: x,
3593
- rect: RectExtensions.mult(rect, this.transform.scale)
3594
- };
3595
- });
3603
+ reset() {
3604
+ this.fCanvas.resetZoom();
3605
+ this.fCanvas.redraw();
3606
+ this.fCanvas.completeDrag();
3596
3607
  }
3597
- getConnectionsWithRects() {
3598
- return this.fConnections.map((x) => {
3599
- const rect = this.getElementRectInFlowHandler.handle(x.boundingElement);
3600
- return {
3601
- element: x,
3602
- rect: RectExtensions.mult(rect, this.transform.scale)
3603
- };
3604
- });
3608
+ unsubscribe() {
3609
+ this.listeners();
3610
+ this.listeners = EventExtensions.emptyListener();
3605
3611
  }
3606
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: GetCanBeSelectedItemsHandler, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: GetElementRectInFlowHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
3607
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: GetCanBeSelectedItemsHandler }); }
3608
3612
  }
3609
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: GetCanBeSelectedItemsHandler, decorators: [{
3610
- type: Injectable
3611
- }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: GetElementRectInFlowHandler }] });
3612
3613
 
3613
- class SelectionAreaDragHandle {
3614
- get canvasPosition() {
3615
- return Point.fromPoint(this.fComponentsStore.fCanvas.transform.position).add(this.fComponentsStore.fCanvas.transform.scaledPosition);
3614
+ class FZoomDirective extends FZoomBase {
3615
+ get fFlowZoom() {
3616
+ return this.isEnabled;
3616
3617
  }
3617
- constructor(fComponentsStore, fDraggableDataContext, injector) {
3618
- this.fComponentsStore = fComponentsStore;
3619
- this.fDraggableDataContext = fDraggableDataContext;
3620
- this.injector = injector;
3621
- this.type = EDraggableType.SELECTION;
3622
- this.canBeSelected = [];
3623
- this.selectedByMove = [];
3618
+ set fFlowZoom(isEnabled) {
3619
+ const value = BooleanExtensions.castToBoolean(isEnabled);
3620
+ if (value !== this.isEnabled) {
3621
+ this.isEnabled = value;
3622
+ this.toggleZoom();
3623
+ }
3624
3624
  }
3625
- initialize() {
3626
- this.canBeSelected = this.injector.get(GetCanBeSelectedItemsHandler).handle();
3627
- this.fDraggableDataContext.fSelectionArea?.show();
3628
- this.fDraggableDataContext.fSelectionArea?.draw({
3629
- left: this.fDraggableDataContext.onPointerDownPosition.x,
3630
- top: this.fDraggableDataContext.onPointerDownPosition.y,
3631
- width: 0,
3632
- height: 0
3633
- });
3625
+ constructor(fComponentsStore) {
3626
+ super(fComponentsStore);
3627
+ this.minimum = 0.1;
3628
+ this.maximum = 4;
3629
+ this.step = 0.1;
3630
+ this.dblClickStep = 0.5;
3634
3631
  }
3635
- move(difference) {
3636
- const currentPoint = Point.fromPoint(difference).add(this.fDraggableDataContext.onPointerDownPosition);
3637
- const x = Math.min(this.fDraggableDataContext.onPointerDownPosition.x, currentPoint.x);
3638
- const y = Math.min(this.fDraggableDataContext.onPointerDownPosition.y, currentPoint.y);
3639
- const width = Math.abs(difference.x);
3640
- const height = Math.abs(difference.y);
3641
- this.fDraggableDataContext.fSelectionArea?.draw({ left: x, top: y, width, height });
3642
- this.selectedByMove = [];
3643
- this.canBeSelected.forEach((item) => {
3644
- item.element.deselect();
3645
- const itemRect = RectExtensions.addPoint(item.rect, this.canvasPosition);
3646
- const isIntersect = RectExtensions.intersectionWithRect(itemRect, RectExtensions.initialize(x, y, width, height));
3647
- if (isIntersect) {
3648
- item.element.select();
3649
- this.selectedByMove.push(item.element);
3650
- }
3651
- });
3632
+ ngAfterViewInit() {
3633
+ super.toggleZoom();
3652
3634
  }
3653
- complete() {
3654
- this.fDraggableDataContext.fSelectionArea?.hide();
3655
- this.fDraggableDataContext.selectedItems.push(...this.selectedByMove);
3635
+ ngOnDestroy() {
3636
+ super.unsubscribe();
3656
3637
  }
3638
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FZoomDirective, deps: [{ token: FComponentsStore }], target: i0.ɵɵFactoryTarget.Directive }); }
3639
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FZoomDirective, selector: "f-canvas[fZoom]", inputs: { fFlowZoom: ["fZoom", "fFlowZoom"], minimum: ["fZoomMinimum", "minimum"], maximum: ["fZoomMaximum", "maximum"], step: ["fZoomStep", "step"], dblClickStep: ["fZoomDblClickStep", "dblClickStep"] }, host: { classAttribute: "f-zoom f-component" }, providers: [{ provide: F_ZOOM, useExisting: FZoomDirective }], exportAs: ["fComponent"], usesInheritance: true, ngImport: i0 }); }
3640
+ }
3641
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FZoomDirective, decorators: [{
3642
+ type: Directive,
3643
+ args: [{
3644
+ selector: "f-canvas[fZoom]",
3645
+ exportAs: 'fComponent',
3646
+ host: {
3647
+ 'class': 'f-zoom f-component'
3648
+ },
3649
+ providers: [{ provide: F_ZOOM, useExisting: FZoomDirective }],
3650
+ }]
3651
+ }], ctorParameters: () => [{ type: FComponentsStore }], propDecorators: { fFlowZoom: [{
3652
+ type: Input,
3653
+ args: ['fZoom']
3654
+ }], minimum: [{
3655
+ type: Input,
3656
+ args: ['fZoomMinimum']
3657
+ }], maximum: [{
3658
+ type: Input,
3659
+ args: ['fZoomMaximum']
3660
+ }], step: [{
3661
+ type: Input,
3662
+ args: ['fZoomStep']
3663
+ }], dblClickStep: [{
3664
+ type: Input,
3665
+ args: ['fZoomDblClickStep']
3666
+ }] } });
3667
+
3668
+ function mixinChangeZoom(base) {
3669
+ return class extends base {
3670
+ setZoom(scaleValue, toPosition) {
3671
+ if (scaleValue !== this.transform.scale) {
3672
+ const summaryPosition = PointExtensions.sum(this.transform.scaledPosition, this.transform.position);
3673
+ const newX = toPosition.x - (toPosition.x - summaryPosition.x) * scaleValue / this.transform.scale;
3674
+ const newY = toPosition.y - (toPosition.y - summaryPosition.y) * scaleValue / this.transform.scale;
3675
+ this.transform.scale = scaleValue;
3676
+ this.transform.scaledPosition = PointExtensions.sub(PointExtensions.initialize(newX, newY), this.transform.position);
3677
+ }
3678
+ }
3679
+ setScalePosition(value) {
3680
+ this.transform.scaledPosition = value;
3681
+ }
3682
+ resetZoom() {
3683
+ this.transform.scale = 1;
3684
+ this.transform.scaledPosition = PointExtensions.initialize();
3685
+ }
3686
+ constructor(...args) {
3687
+ super(...args);
3688
+ }
3689
+ };
3657
3690
  }
3658
3691
 
3659
- class SelectionAreaPrepareDragSequence {
3660
- get fFlow() {
3661
- return this.fComponentsStore.fFlow;
3662
- }
3663
- constructor(fComponentsStore, fDraggableDataContext, injector) {
3664
- this.fComponentsStore = fComponentsStore;
3665
- this.fDraggableDataContext = fDraggableDataContext;
3666
- this.injector = injector;
3667
- }
3668
- handle(event) {
3669
- const pointerPositionInFlow = Point.fromPoint(event.getPosition()).elementTransform(this.fFlow.hostElement);
3670
- if (MouseEventExtensions.isShiftPressed(event.originalEvent) && this.fDraggableDataContext.fSelectionArea) {
3671
- this.fDraggableDataContext.draggableItems = [
3672
- new SelectionAreaDragHandle(this.fComponentsStore, this.fDraggableDataContext, this.injector)
3673
- ];
3674
- this.fDraggableDataContext.onPointerDownScale = 1;
3675
- this.fDraggableDataContext.onPointerDownPosition = pointerPositionInFlow.div(1);
3692
+ function mixinFitToParent(base) {
3693
+ return class extends base {
3694
+ fitToParent(rect, parentRect, points) {
3695
+ this.transform.scaledPosition = PointExtensions.initialize();
3696
+ this.transform.position = this.getZeroPositionWithoutScale(points);
3697
+ const itemsContainerWidth = rect.width / this.transform.scale;
3698
+ const itemsContainerHeight = rect.height / this.transform.scale;
3699
+ if ((itemsContainerWidth > parentRect.width || itemsContainerHeight > parentRect.height) ||
3700
+ itemsContainerWidth < parentRect.width && itemsContainerHeight < parentRect.height) {
3701
+ this.transform.scale = Math.min(parentRect.width / itemsContainerWidth, parentRect.height / itemsContainerHeight);
3702
+ }
3703
+ const newX = (parentRect.width - itemsContainerWidth * this.transform.scale) / 2 - this.transform.position.x * this.transform.scale;
3704
+ const newY = (parentRect.height - itemsContainerHeight * this.transform.scale) / 2 - this.transform.position.y * this.transform.scale;
3705
+ this.transform.position = PointExtensions.initialize(newX, newY);
3676
3706
  }
3677
- }
3678
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SelectionAreaPrepareDragSequence, deps: [{ token: FComponentsStore }, { token: FDraggableDataContext }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable }); }
3679
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SelectionAreaPrepareDragSequence }); }
3707
+ getZeroPositionWithoutScale(points) {
3708
+ const xPoint = points.length ? Math.min(...points.map((point) => point.x)) : 0;
3709
+ const yPoint = points.length ? Math.min(...points.map((point) => point.y)) : 0;
3710
+ return PointExtensions.initialize(xPoint, yPoint);
3711
+ }
3712
+ constructor(...args) {
3713
+ super(...args);
3714
+ }
3715
+ };
3680
3716
  }
3681
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SelectionAreaPrepareDragSequence, decorators: [{
3682
- type: Injectable
3683
- }], ctorParameters: () => [{ type: FComponentsStore }, { type: FDraggableDataContext }, { type: i0.Injector }] });
3684
3717
 
3685
- class SelectionAreaOnPointerUp {
3686
- constructor(fDraggableDataContext) {
3687
- this.fDraggableDataContext = fDraggableDataContext;
3688
- }
3689
- handle(event) {
3690
- const isSelection = this.fDraggableDataContext.draggableItems.some((x) => x.type === EDraggableType.SELECTION);
3691
- if (isSelection) {
3692
- this.fDraggableDataContext.draggableItems.forEach((x) => {
3693
- x.complete?.();
3694
- });
3718
+ function mixinOneToOneCentering(base) {
3719
+ return class extends base {
3720
+ oneToOneCentering(rect, parentRect, points) {
3721
+ this.transform.scaledPosition = PointExtensions.initialize();
3722
+ this.transform.position = this.getZeroPositionWithoutScale(points);
3723
+ const itemsContainerWidth = rect.width / this.transform.scale;
3724
+ const itemsContainerHeight = rect.height / this.transform.scale;
3725
+ this.transform.scale = 1;
3726
+ const newX = (parentRect.width - itemsContainerWidth * this.transform.scale) / 2 - this.transform.position.x * this.transform.scale;
3727
+ const newY = (parentRect.height - itemsContainerHeight * this.transform.scale) / 2 - this.transform.position.y * this.transform.scale;
3728
+ this.transform.position = PointExtensions.initialize(newX, newY);
3695
3729
  }
3696
- }
3697
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SelectionAreaOnPointerUp, deps: [{ token: FDraggableDataContext }], target: i0.ɵɵFactoryTarget.Injectable }); }
3698
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SelectionAreaOnPointerUp }); }
3730
+ getZeroPositionWithoutScale(points) {
3731
+ const xPoint = points.length ? Math.min(...points.map((point) => point.x)) : 0;
3732
+ const yPoint = points.length ? Math.min(...points.map((point) => point.y)) : 0;
3733
+ return PointExtensions.initialize(xPoint, yPoint);
3734
+ }
3735
+ constructor(...args) {
3736
+ super(...args);
3737
+ }
3738
+ };
3699
3739
  }
3700
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SelectionAreaOnPointerUp, decorators: [{
3701
- type: Injectable
3702
- }], ctorParameters: () => [{ type: FDraggableDataContext }] });
3703
3740
 
3704
- const SELECTION_AREA_PROVIDERS = [
3705
- GetCanBeSelectedItemsHandler,
3706
- SelectionAreaPrepareDragSequence,
3707
- SelectionAreaOnPointerUp,
3708
- ];
3741
+ function mixinChangePosition(base) {
3742
+ return class extends base {
3743
+ getPosition() {
3744
+ return this.transform.position;
3745
+ }
3746
+ setPosition(position) {
3747
+ this.transform.position = PointExtensions.copy(position);
3748
+ }
3749
+ constructor(...args) {
3750
+ super(...args);
3751
+ }
3752
+ };
3753
+ }
3709
3754
 
3710
- const F_DRAGGABLE = new InjectionToken('F_DRAGGABLE');
3711
- class FDraggableBase extends IDragAndDropBase {
3712
- constructor(ngZone) {
3713
- super(ngZone);
3755
+ const F_CANVAS = new InjectionToken('F_CANVAS');
3756
+ const MIXIN_BASE = mixinChangePosition(mixinFitToParent(mixinOneToOneCentering(mixinChangeZoom(class {
3757
+ constructor(transform) {
3758
+ this.transform = transform;
3714
3759
  }
3715
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FDraggableBase, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive }); }
3716
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FDraggableBase, usesInheritance: true, ngImport: i0 }); }
3760
+ }))));
3761
+ class FCanvasBase extends MIXIN_BASE {
3762
+ constructor() {
3763
+ super(TransformModelExtensions.default());
3764
+ }
3765
+ completeDrag() {
3766
+ const position = PointExtensions.sum(this.transform.position, this.transform.scaledPosition);
3767
+ this.fCanvasChange.emit(new FCanvasChangeEvent(position, this.transform.scale));
3768
+ }
3769
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FCanvasBase, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3770
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FCanvasBase, usesInheritance: true, ngImport: i0 }); }
3717
3771
  }
3718
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FDraggableBase, decorators: [{
3772
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FCanvasBase, decorators: [{
3719
3773
  type: Directive
3720
- }], ctorParameters: () => [{ type: i0.NgZone }] });
3774
+ }], ctorParameters: () => [] });
3721
3775
 
3722
- class FDraggableDirective extends FDraggableBase {
3776
+ class FCanvasComponent extends FCanvasBase {
3777
+ set position(value) {
3778
+ if (!value) {
3779
+ return;
3780
+ }
3781
+ const position = PointExtensions.sum(this.transform.position, this.transform.scaledPosition);
3782
+ if (!PointExtensions.isEqual(position, value)) {
3783
+ this.transform.position = value;
3784
+ this.transform.scaledPosition = PointExtensions.initialize();
3785
+ this.redraw();
3786
+ }
3787
+ }
3788
+ set scale(value) {
3789
+ if (!value) {
3790
+ return;
3791
+ }
3792
+ this.transform.scale = value;
3793
+ this.redraw();
3794
+ }
3795
+ get fNodes() {
3796
+ return this.fComponentsStore.fNodes;
3797
+ }
3723
3798
  get hostElement() {
3724
3799
  return this.elementReference.nativeElement;
3725
3800
  }
3726
- constructor(elementReference, fDraggableDataContext, ngZone, injector, fComponentsStore, document) {
3727
- super(ngZone);
3801
+ constructor(getAllNodesRectHandler, selectAllHandler, elementReference, fComponentsStore) {
3802
+ super();
3803
+ this.getAllNodesRectHandler = getAllNodesRectHandler;
3804
+ this.selectAllHandler = selectAllHandler;
3728
3805
  this.elementReference = elementReference;
3729
- this.fDraggableDataContext = fDraggableDataContext;
3730
- this.injector = injector;
3731
3806
  this.fComponentsStore = fComponentsStore;
3732
- this.subscriptions$ = new Subscription();
3733
- this.disabled = false;
3734
- this.fSelectionChange = new EventEmitter();
3735
- // @Output()
3736
- // public override fConnectionIntersectNode: EventEmitter<ConnectionIntersectNodeEvent> = new EventEmitter<ConnectionIntersectNodeEvent>();
3737
- this.fCreateNode = new EventEmitter();
3738
- this.fReassignConnection = new EventEmitter();
3739
- this.fCreateConnection = new EventEmitter();
3740
- this.document = document;
3807
+ this.fCanvasChange = new EventEmitter();
3741
3808
  }
3742
3809
  ngOnInit() {
3743
- this.fComponentsStore.fDraggable = this;
3744
- }
3745
- ngAfterViewInit() {
3746
- super.subscribe(this.document);
3747
- }
3748
- onPointerDown(event) {
3749
- this.fDraggableDataContext.reset();
3750
- let result = event.isMouseLeftButton();
3751
- this.injector.get(SingleSelectOnPointerDown).handle(event);
3752
- this.injector.get(ReassignConnectionPrepareDragSequence).handle(event);
3753
- this.injector.get(CreateConnectionPrepareDragSequence).handle(event);
3754
- return result;
3810
+ this.fComponentsStore.fCanvas = this;
3755
3811
  }
3756
- prepareDragSequence(event) {
3757
- this.injector.get(SelectionAreaPrepareDragSequence).handle(event);
3758
- this.injector.get(NodePrepareDragSequence).handle(event);
3759
- this.injector.get(CanvasPrepareDragSequence).handle(event);
3760
- this.injector.get(ExternalItemPrepareDragSequence).handle(event);
3761
- this.fDraggableDataContext.draggableItems.forEach((item) => {
3762
- item.initialize?.();
3763
- });
3764
- this.emitSelectionChangeEvent();
3765
- if (this.fDraggableDataContext.draggableItems.length > 0) {
3766
- this.hostElement.classList.add('f-dragging');
3767
- }
3812
+ redraw() {
3813
+ this.fComponentsStore.fBackground?.setTransform(this.transform);
3814
+ this.hostElement.setAttribute("style", `transform: ${TransformModelExtensions.toString(this.transform)}`);
3768
3815
  }
3769
- onPointerMove(event) {
3770
- const pointerPositionInCanvas = Point.fromPoint(event.getPosition()).elementTransform(this.hostElement);
3771
- const difference = pointerPositionInCanvas.div(this.fDraggableDataContext.onPointerDownScale).sub(this.fDraggableDataContext.onPointerDownPosition);
3772
- this.fDraggableDataContext.draggableItems.forEach((item) => {
3773
- item.move(difference);
3774
- });
3816
+ redrawWithAnimation() {
3817
+ this.fComponentsStore.fBackground?.setTransform(this.transform);
3818
+ this.hostElement.setAttribute("style", `transition: transform 0.15s ease-in-out; transform: ${TransformModelExtensions.toString(this.transform)}`);
3819
+ setTimeout(() => {
3820
+ this.redraw();
3821
+ }, 150);
3775
3822
  }
3776
- onPointerUp(event) {
3777
- this.injector.get(ReassignConnectionOnPointerUp).handle(event);
3778
- this.injector.get(CreateConnectionOnPointerUp).handle(event);
3779
- this.injector.get(SelectionAreaOnPointerUp).handle(event);
3780
- this.injector.get(NodeOnPointerUp).handle(event);
3781
- this.injector.get(CanvasOnPointerUp).handle(event);
3782
- this.injector.get(ExternalItemOnPointerUp).handle(event);
3783
- this.hostElement.classList.remove('f-dragging');
3784
- this.fDraggableDataContext.reset();
3823
+ fitToScreen(toCenter = PointExtensions.initialize(), animated = true) {
3824
+ const fNodesRect = this.getAllNodesRectHandler.handle();
3825
+ const rect = RectExtensions.addPointToSize(fNodesRect, Point.fromPoint(toCenter).mult(2));
3826
+ this.fitToParent(rect, RectExtensions.fromElement(this.fComponentsStore.fFlow.hostElement), this.fNodes.map((x) => {
3827
+ return Point.fromPoint(x.position).sub(toCenter);
3828
+ }));
3829
+ animated ? this.redrawWithAnimation() : this.redraw();
3830
+ this.completeDrag();
3785
3831
  }
3786
- emitSelectionChangeEvent() {
3787
- let selectedNodes = [];
3788
- let selectedConnections = [];
3789
- this.fDraggableDataContext.selectedItems.forEach((x) => {
3790
- if (x.hostElement.classList.contains('f-node')) {
3791
- selectedNodes.push(x.hostElement.id);
3792
- }
3793
- else {
3794
- selectedConnections.push(x.hostElement.id);
3795
- }
3796
- });
3797
- this.fSelectionChange.emit(new SelectionChangeEvent(selectedNodes, selectedConnections));
3832
+ oneToOne() {
3833
+ const fNodesRect = this.getAllNodesRectHandler.handle();
3834
+ this.oneToOneCentering(fNodesRect, RectExtensions.fromElement(this.fComponentsStore.fFlow.hostElement), this.fNodes.map((x) => {
3835
+ return Point.fromPoint(x.position).sub(new Point(0, 0));
3836
+ }));
3837
+ this.redrawWithAnimation();
3838
+ this.completeDrag();
3798
3839
  }
3799
- ngOnDestroy() {
3800
- super.unsubscribe();
3801
- this.subscriptions$.unsubscribe();
3840
+ selectAll() {
3841
+ this.selectAllHandler.handle();
3802
3842
  }
3803
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FDraggableDirective, deps: [{ token: i0.ElementRef }, { token: FDraggableDataContext }, { token: i0.NgZone }, { token: i0.Injector }, { token: FComponentsStore }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Directive }); }
3804
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: FDraggableDirective, selector: "f-flow[fDraggable]", inputs: { disabled: ["fDraggableDisabled", "disabled"] }, outputs: { fSelectionChange: "fSelectionChange", fCreateNode: "fCreateNode", fReassignConnection: "fReassignConnection", fCreateConnection: "fCreateConnection" }, providers: [
3805
- { provide: F_DRAGGABLE, useExisting: FDraggableDirective }
3806
- ], exportAs: ["fDraggable"], usesInheritance: true, ngImport: i0 }); }
3843
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FCanvasComponent, deps: [{ token: GetAllNodesRectHandler }, { token: SelectAllHandler }, { token: i0.ElementRef }, { token: FComponentsStore }], target: i0.ɵɵFactoryTarget.Component }); }
3844
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.9", type: FCanvasComponent, selector: "f-canvas", inputs: { position: "position", scale: "scale" }, outputs: { fCanvasChange: "fCanvasChange" }, host: { classAttribute: "f-component f-canvas" }, providers: [{ provide: F_CANVAS, useExisting: FCanvasComponent }], viewQueries: [{ propertyName: "fNodesContainer", first: true, predicate: ["fNodesContainer"], descendants: true, static: true }], exportAs: ["fComponent"], usesInheritance: true, ngImport: i0, template: "<ng-container>\n <div>\n <ng-content select=\"f-connection\"></ng-content>\n <ng-content select=\"f-connection-for-create\"></ng-content>\n </div>\n <div #fNodesContainer>\n <ng-content select=\"f-node\"></ng-content>\n </div>\n</ng-container>\n", styles: [":host{position:absolute;overflow:visible;width:100%;height:100%;left:0;top:0;transform-origin:0 0;pointer-events:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3807
3845
  }
3808
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FDraggableDirective, decorators: [{
3809
- type: Directive,
3810
- args: [{
3811
- selector: "f-flow[fDraggable]",
3812
- exportAs: 'fDraggable',
3813
- providers: [
3814
- { provide: F_DRAGGABLE, useExisting: FDraggableDirective }
3815
- ]
3816
- }]
3817
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: FDraggableDataContext }, { type: i0.NgZone }, { type: i0.Injector }, { type: FComponentsStore }, { type: undefined, decorators: [{
3818
- type: Inject,
3819
- args: [DOCUMENT]
3820
- }] }], propDecorators: { disabled: [{
3821
- type: Input,
3822
- args: ['fDraggableDisabled']
3823
- }], fSelectionChange: [{
3824
- type: Output
3825
- }], fCreateNode: [{
3826
- type: Output
3827
- }], fReassignConnection: [{
3828
- type: Output
3829
- }], fCreateConnection: [{
3846
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: FCanvasComponent, decorators: [{
3847
+ type: Component,
3848
+ args: [{ selector: 'f-canvas', exportAs: 'fComponent', host: {
3849
+ 'class': 'f-component f-canvas',
3850
+ }, providers: [{ provide: F_CANVAS, useExisting: FCanvasComponent }], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container>\n <div>\n <ng-content select=\"f-connection\"></ng-content>\n <ng-content select=\"f-connection-for-create\"></ng-content>\n </div>\n <div #fNodesContainer>\n <ng-content select=\"f-node\"></ng-content>\n </div>\n</ng-container>\n", styles: [":host{position:absolute;overflow:visible;width:100%;height:100%;left:0;top:0;transform-origin:0 0;pointer-events:none}\n"] }]
3851
+ }], ctorParameters: () => [{ type: GetAllNodesRectHandler }, { type: SelectAllHandler }, { type: i0.ElementRef }, { type: FComponentsStore }], propDecorators: { fCanvasChange: [{
3830
3852
  type: Output
3853
+ }], position: [{
3854
+ type: Input
3855
+ }], scale: [{
3856
+ type: Input
3857
+ }], fNodesContainer: [{
3858
+ type: ViewChild,
3859
+ args: ['fNodesContainer', { static: true }]
3831
3860
  }] } });
3832
3861
 
3862
+ const F_FLOW = new InjectionToken('F_FLOW');
3863
+
3833
3864
  const F_PARENT = new InjectionToken('F_PARENT');
3834
3865
 
3835
3866
  let uniqueId = 0;