UNPKG

@foblex/flow

Version:

An Angular library designed to simplify the creation and manipulation of dynamic flow. Provides components for flows, nodes, and connections, automating node manipulation and inter-node connections.

92 lines 15.3 kB
import { __decorate } from "tslib"; import { Point, RectExtensions } from '@foblex/2d'; import { FindInputAtPositionRequest } from './find-input-at-position.request'; import { inject, Injectable } from '@angular/core'; import { BrowserService } from '@foblex/platform'; import { FExecutionRegister, FMediator } from '@foblex/mediator'; import { FComponentsStore } from '../../../f-storage'; import { CalculateClosestInputRequest } from '../calculate-closest-input'; import * as i0 from "@angular/core"; let FindInputAtPositionExecution = class FindInputAtPositionExecution { _fMediator = inject(FMediator); _fComponentsStore = inject(FComponentsStore); _fBrowser = inject(BrowserService); get _transform() { return this._fComponentsStore.fCanvas.transform; } get _fHost() { return this._fComponentsStore.fFlow.hostElement; } get _fNodes() { return this._fComponentsStore.fNodes; } get _fSnapConnection() { return this._fComponentsStore.fSnapConnection; } handle(payload) { const fInputs = this._findInputsAtPosition(payload); return fInputs.length > 0 ? fInputs[0] : undefined; } _findInputsAtPosition(request) { const result = []; result.push(...this._getConnectableInputsAtPosition(request)); const fClosestInput = this._calculateClosetInput(request); if (fClosestInput) { result.unshift(fClosestInput.fConnector); } const fInput = this._getFirstConnectableInputOfNodeAtPosition(request); if (fInput) { result.push(fInput); } return result; } _getConnectableInputsAtPosition(request) { return request.canBeConnectedInputs.filter((x) => { return RectExtensions.isIncludePoint(x.fRect, this._getPointInFlow(request.pointerPosition)); }).map((x) => x.fConnector); } _getPointInFlow(position) { return Point.fromPoint(position) .elementTransform(this._fHost) .sub(this._transform.scaledPosition).sub(this._transform.position) .div(this._transform.scale); } //if the closest input is valid, return it _calculateClosetInput(request) { if (!this._fSnapConnection) { return undefined; } const fClosestInput = this._fMediator.execute(new CalculateClosestInputRequest(this._getPointInFlow(request.pointerPosition), request.canBeConnectedInputs)); return this._isValidClosestInput(fClosestInput) ? fClosestInput : undefined; } _isValidClosestInput(fClosestInput) { return !!fClosestInput && fClosestInput.distance < this._fSnapConnection.fSnapThreshold; } //if node placed in position and fConnectOnNode is true, return the first connectable input of the node _getFirstConnectableInputOfNodeAtPosition(request) { return this._getElementsFromPoint(request.pointerPosition) .map((x) => this._findConnectableNode(x)) .filter((x) => !!x) .map((x) => this._findFirstConnectableInputOfNode(request.canBeConnectedInputs, x)) .find((x) => !!x); } _getElementsFromPoint(position) { return this._fBrowser.document.elementsFromPoint(position.x, position.y); } _findConnectableNode(element) { return this._fNodes.find((x) => x.isContains(element) && x.fConnectOnNode); } _findFirstConnectableInputOfNode(connectableInputs, fNode) { return connectableInputs.find((x) => x.fConnector.fNodeId === fNode.fId)?.fConnector; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FindInputAtPositionExecution, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FindInputAtPositionExecution }); }; FindInputAtPositionExecution = __decorate([ FExecutionRegister(FindInputAtPositionRequest) ], FindInputAtPositionExecution); export { FindInputAtPositionExecution }; i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FindInputAtPositionExecution, decorators: [{ type: Injectable }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmluZC1pbnB1dC1hdC1wb3NpdGlvbi5leGVjdXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9mLWZsb3cvc3JjL2RvbWFpbi9mLWNvbm5lY3RvcnMvZmluZC1pbnB1dC1hdC1wb3NpdGlvbi9maW5kLWlucHV0LWF0LXBvc2l0aW9uLmV4ZWN1dGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUEyQixLQUFLLEVBQUUsY0FBYyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQzVFLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQzlFLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25ELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNsRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsU0FBUyxFQUFjLE1BQU0sa0JBQWtCLENBQUM7QUFHN0UsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFdEQsT0FBTyxFQUFFLDRCQUE0QixFQUFFLE1BQU0sNEJBQTRCLENBQUM7O0FBTW5FLElBQU0sNEJBQTRCLEdBQWxDLE1BQU0sNEJBQTRCO0lBRy9CLFVBQVUsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDL0IsaUJBQWlCLEdBQUcsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDN0MsU0FBUyxHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQztJQUUzQyxJQUFZLFVBQVU7UUFDcEIsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBUSxDQUFDLFNBQVMsQ0FBQztJQUNuRCxDQUFDO0lBRUQsSUFBWSxNQUFNO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQU0sQ0FBQyxXQUFXLENBQUM7SUFDbkQsQ0FBQztJQUVELElBQVksT0FB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Qyw0QkFBNEIsQ0FnR3hDOzs0RkFoR1ksNEJBQTRCO2tCQUZ4QyxVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSVBvaW50LCBJVHJhbnNmb3JtTW9kZWwsIFBvaW50LCBSZWN0RXh0ZW5zaW9ucyB9IGZyb20gJ0Bmb2JsZXgvMmQnO1xuaW1wb3J0IHsgRmluZElucHV0QXRQb3NpdGlvblJlcXVlc3QgfSBmcm9tICcuL2ZpbmQtaW5wdXQtYXQtcG9zaXRpb24ucmVxdWVzdCc7XG5pbXBvcnQgeyBpbmplY3QsIEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEJyb3dzZXJTZXJ2aWNlIH0gZnJvbSAnQGZvYmxleC9wbGF0Zm9ybSc7XG5pbXBvcnQgeyBGRXhlY3V0aW9uUmVnaXN0ZXIsIEZNZWRpYXRvciwgSUV4ZWN1dGlvbiB9IGZyb20gJ0Bmb2JsZXgvbWVkaWF0b3InO1xuaW1wb3J0IHsgRkNvbm5lY3RvckJhc2UgfSBmcm9tICcuLi8uLi8uLi9mLWNvbm5lY3RvcnMnO1xuaW1wb3J0IHsgRk5vZGVCYXNlIH0gZnJvbSAnLi4vLi4vLi4vZi1ub2RlJztcbmltcG9ydCB7IEZDb21wb25lbnRzU3RvcmUgfSBmcm9tICcuLi8uLi8uLi9mLXN0b3JhZ2UnO1xuaW1wb3J0IHsgSUNsb3Nlc3RJbnB1dCB9IGZyb20gJy4uL2ktY2xvc2VzdC1pbnB1dCc7XG5pbXBvcnQgeyBDYWxjdWxhdGVDbG9zZXN0SW5wdXRSZXF1ZXN0IH0gZnJvbSAnLi4vY2FsY3VsYXRlLWNsb3Nlc3QtaW5wdXQnO1xuaW1wb3J0IHsgRlNuYXBDb25uZWN0aW9uQ29tcG9uZW50IH0gZnJvbSAnLi4vLi4vLi4vZi1jb25uZWN0aW9uJztcbmltcG9ydCB7IElDb25uZWN0b3JBbmRSZWN0IH0gZnJvbSAnLi4vaS1jb25uZWN0b3ItYW5kLXJlY3QnO1xuXG5ASW5qZWN0YWJsZSgpXG5ARkV4ZWN1dGlvblJlZ2lzdGVyKEZpbmRJbnB1dEF0UG9zaXRpb25SZXF1ZXN0KVxuZXhwb3J0IGNsYXNzIEZpbmRJbnB1dEF0UG9zaXRpb25FeGVjdXRpb25cbiAgaW1wbGVtZW50cyBJRXhlY3V0aW9uPEZpbmRJbnB1dEF0UG9zaXRpb25SZXF1ZXN0LCBGQ29ubmVjdG9yQmFzZSB8IHVuZGVmaW5lZD4ge1xuXG4gIHByaXZhdGUgX2ZNZWRpYXRvciA9IGluamVjdChGTWVkaWF0b3IpO1xuICBwcml2YXRlIF9mQ29tcG9uZW50c1N0b3JlID0gaW5qZWN0KEZDb21wb25lbnRzU3RvcmUpO1xuICBwcml2YXRlIF9mQnJvd3NlciA9IGluamVjdChCcm93c2VyU2VydmljZSk7XG5cbiAgcHJpdmF0ZSBnZXQgX3RyYW5zZm9ybSgpOiBJVHJhbnNmb3JtTW9kZWwge1xuICAgIHJldHVybiB0aGlzLl9mQ29tcG9uZW50c1N0b3JlLmZDYW52YXMhLnRyYW5zZm9ybTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0IF9mSG9zdCgpOiBIVE1MRWxlbWVudCB7XG4gICAgcmV0dXJuIHRoaXMuX2ZDb21wb25lbnRzU3RvcmUuZkZsb3chLmhvc3RFbGVtZW50O1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgX2ZOb2RlcygpOiBGTm9kZUJhc2VbXSB7XG4gICAgcmV0dXJuIHRoaXMuX2ZDb21wb25lbnRzU3RvcmUuZk5vZGVzO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgX2ZTbmFwQ29ubmVjdGlvbigpOiBGU25hcENvbm5lY3Rpb25Db21wb25lbnQgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLl9mQ29tcG9uZW50c1N0b3JlLmZTbmFwQ29ubmVjdGlvbiBhcyBGU25hcENvbm5lY3Rpb25Db21wb25lbnQ7XG4gIH1cblxuICBwdWJsaWMgaGFuZGxlKHBheWxvYWQ6IEZpbmRJbnB1dEF0UG9zaXRpb25SZXF1ZXN0KTogRkNvbm5lY3RvckJhc2UgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGZJbnB1dHMgPSB0aGlzLl9maW5kSW5wdXRzQXRQb3NpdGlvbihwYXlsb2FkLCk7XG4gICAgcmV0dXJuIGZJbnB1dHMubGVuZ3RoID4gMCA/IGZJbnB1dHNbIDAgXSA6IHVuZGVmaW5lZDtcbiAgfVxuXG4gIHByaXZhdGUgX2ZpbmRJbnB1dHNBdFBvc2l0aW9uKHJlcXVlc3Q6IEZpbmRJbnB1dEF0UG9zaXRpb25SZXF1ZXN0KTogRkNvbm5lY3RvckJhc2VbXSB7XG4gICAgY29uc3QgcmVzdWx0OiBGQ29ubmVjdG9yQmFzZVtdID0gW107XG5cbiAgICByZXN1bHQucHVzaCguLi50aGlzLl9nZXRDb25uZWN0YWJsZUlucHV0c0F0UG9zaXRpb24ocmVxdWVzdCkpO1xuXG4gICAgY29uc3QgZkNsb3Nlc3RJbnB1dCA9IHRoaXMuX2NhbGN1bGF0ZUNsb3NldElucHV0KHJlcXVlc3QpO1xuICAgIGlmIChmQ2xvc2VzdElucHV0KSB7XG4gICAgICByZXN1bHQudW5zaGlmdChmQ2xvc2VzdElucHV0LmZDb25uZWN0b3IpO1xuICAgIH1cblxuICAgIGNvbnN0IGZJbnB1dCA9IHRoaXMuX2dldEZpcnN0Q29ubmVjdGFibGVJbnB1dE9mTm9kZUF0UG9zaXRpb24ocmVxdWVzdCk7XG4gICAgaWYgKGZJbnB1dCkge1xuICAgICAgcmVzdWx0LnB1c2goZklucHV0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgcHJpdmF0ZSBfZ2V0Q29ubmVjdGFibGVJbnB1dHNBdFBvc2l0aW9uKHJlcXVlc3Q6IEZpbmRJbnB1dEF0UG9zaXRpb25SZXF1ZXN0KTogRkNvbm5lY3RvckJhc2VbXSB7XG4gICAgcmV0dXJuIHJlcXVlc3QuY2FuQmVDb25uZWN0ZWRJbnB1dHMuZmlsdGVyKCh4KSA9PiB7XG4gICAgICByZXR1cm4gUmVjdEV4dGVuc2lvbnMuaXNJbmNsdWRlUG9pbnQoeC5mUmVjdCwgdGhpcy5fZ2V0UG9pbnRJbkZsb3cocmVxdWVzdC5wb2ludGVyUG9zaXRpb24pKTtcbiAgICB9KS5tYXAoKHgpID0+IHguZkNvbm5lY3Rvcik7XG4gIH1cblxuICBwcml2YXRlIF9nZXRQb2ludEluRmxvdyhwb3NpdGlvbjogSVBvaW50KTogSVBvaW50IHtcbiAgICByZXR1cm4gUG9pbnQuZnJvbVBvaW50KHBvc2l0aW9uKVxuICAgICAgLmVsZW1lbnRUcmFuc2Zvcm0odGhpcy5fZkhvc3QpXG4gICAgICAuc3ViKHRoaXMuX3RyYW5zZm9ybS5zY2FsZWRQb3NpdGlvbikuc3ViKHRoaXMuX3RyYW5zZm9ybS5wb3NpdGlvbilcbiAgICAgIC5kaXYodGhpcy5fdHJhbnNmb3JtLnNjYWxlKTtcbiAgfVxuXG4gIC8vaWYgdGhlIGNsb3Nlc3QgaW5wdXQgaXMgdmFsaWQsIHJldHVybiBpdFxuICBwcml2YXRlIF9jYWxjdWxhdGVDbG9zZXRJbnB1dChyZXF1ZXN0OiBGaW5kSW5wdXRBdFBvc2l0aW9uUmVxdWVzdCk6IElDbG9zZXN0SW5wdXQgfCB1bmRlZmluZWQge1xuICAgIGlmICghdGhpcy5fZlNuYXBDb25uZWN0aW9uKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGNvbnN0IGZDbG9zZXN0SW5wdXQgPSB0aGlzLl9mTWVkaWF0b3IuZXhlY3V0ZTxJQ2xvc2VzdElucHV0IHwgdW5kZWZpbmVkPihcbiAgICAgIG5ldyBDYWxjdWxhdGVDbG9zZXN0SW5wdXRSZXF1ZXN0KHRoaXMuX2dldFBvaW50SW5GbG93KHJlcXVlc3QucG9pbnRlclBvc2l0aW9uKSwgcmVxdWVzdC5jYW5CZUNvbm5lY3RlZElucHV0cylcbiAgICApO1xuXG4gICAgcmV0dXJuIHRoaXMuX2lzVmFsaWRDbG9zZXN0SW5wdXQoZkNsb3Nlc3RJbnB1dCkgPyBmQ2xvc2VzdElucHV0IDogdW5kZWZpbmVkO1xuICB9XG5cbiAgcHJpdmF0ZSBfaXNWYWxpZENsb3Nlc3RJbnB1dChmQ2xvc2VzdElucHV0OiBJQ2xvc2VzdElucHV0IHwgdW5kZWZpbmVkKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhZkNsb3Nlc3RJbnB1dCAmJiBmQ2xvc2VzdElucHV0LmRpc3RhbmNlIDwgdGhpcy5fZlNuYXBDb25uZWN0aW9uIS5mU25hcFRocmVzaG9sZDtcbiAgfVxuXG4gIC8vaWYgbm9kZSBwbGFjZWQgaW4gcG9zaXRpb24gYW5kIGZDb25uZWN0T25Ob2RlIGlzIHRydWUsIHJldHVybiB0aGUgZmlyc3QgY29ubmVjdGFibGUgaW5wdXQgb2YgdGhlIG5vZGVcbiAgcHJpdmF0ZSBfZ2V0Rmlyc3RDb25uZWN0YWJsZUlucHV0T2ZOb2RlQXRQb3NpdGlvbihyZXF1ZXN0OiBGaW5kSW5wdXRBdFBvc2l0aW9uUmVxdWVzdCk6IEZDb25uZWN0b3JCYXNlIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5fZ2V0RWxlbWVudHNGcm9tUG9pbnQocmVxdWVzdC5wb2ludGVyUG9zaXRpb24pXG4gICAgICAubWFwKCh4KSA9PiB0aGlzLl9maW5kQ29ubmVjdGFibGVOb2RlKHgpKVxuICAgICAgLmZpbHRlcigoeCkgPT4gISF4KVxuICAgICAgLm1hcCgoeCkgPT4gdGhpcy5fZmluZEZpcnN0Q29ubmVjdGFibGVJbnB1dE9mTm9kZShyZXF1ZXN0LmNhbkJlQ29ubmVjdGVkSW5wdXRzLCB4KSlcbiAgICAgIC5maW5kKCh4KSA9PiAhIXgpO1xuICB9XG5cbiAgcHJpdmF0ZSBfZ2V0RWxlbWVudHNGcm9tUG9pbnQocG9zaXRpb246IElQb2ludCk6IEhUTUxFbGVtZW50W10ge1xuICAgIHJldHVybiB0aGlzLl9mQnJvd3Nlci5kb2N1bWVudC5lbGVtZW50c0Zyb21Qb2ludChwb3NpdGlvbi54LCBwb3NpdGlvbi55KSBhcyBIVE1MRWxlbWVudFtdO1xuICB9XG5cbiAgcHJpdmF0ZSBfZmluZENvbm5lY3RhYmxlTm9kZShlbGVtZW50OiBIVE1MRWxlbWVudCk6IEZOb2RlQmFzZSB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuX2ZOb2Rlcy5maW5kKCh4KSA9PiB4LmlzQ29udGFpbnMoZWxlbWVudCkgJiYgeC5mQ29ubmVjdE9uTm9kZSk7XG4gIH1cblxuICBwcml2YXRlIF9maW5kRmlyc3RDb25uZWN0YWJsZUlucHV0T2ZOb2RlKGNvbm5lY3RhYmxlSW5wdXRzOiBJQ29ubmVjdG9yQW5kUmVjdFtdLCBmTm9kZTogRk5vZGVCYXNlKTogRkNvbm5lY3RvckJhc2UgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiBjb25uZWN0YWJsZUlucHV0cy5maW5kKCh4KSA9PiB4LmZDb25uZWN0b3IuZk5vZGVJZCA9PT0gZk5vZGUuZklkKT8uZkNvbm5lY3RvclxuICB9XG59XG4iXX0=