UNPKG

ngx-diagrams

Version:

This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 7.2.0.

660 lines 74 kB
/** * @fileoverview added by tsickle * Generated from: lib/containers/diagram/diagram.component.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { Component, Input, Renderer2, Output, EventEmitter, ViewChild, ViewContainerRef, ElementRef, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; import { DiagramModel } from '../../models/diagram.model'; import { NodeModel } from '../../models/node.model'; import { BehaviorSubject, combineLatest, ReplaySubject } from 'rxjs'; import { filter, takeUntil } from 'rxjs/operators'; import { MoveCanvasAction, SelectingAction, LinkCreatedAction } from '../../actions'; import { MoveItemsAction } from '../../actions/move-items.action'; import { PointModel } from '../../models/point.model'; import { PortModel } from '../../models/port.model'; import { some } from 'lodash'; export class NgxDiagramComponent { /** * @param {?} renderer * @param {?} cdRef */ constructor(renderer, cdRef) { this.renderer = renderer; this.cdRef = cdRef; this.allowCanvasZoon = true; this.allowCanvasTranslation = true; this.inverseZoom = true; this.allowLooseLinks = true; this.actionStartedFiring = new EventEmitter(); this.actionStillFiring = new EventEmitter(); this.actionStoppedFiring = new EventEmitter(); this.action$ = new BehaviorSubject(null); this.destroyed$ = new ReplaySubject(1); this.mouseUpListener = (/** * @return {?} */ () => { }); this.mouseMoveListener = (/** * @return {?} */ () => { }); this.onMouseUp = (/** * @param {?} event * @return {?} */ (event) => { /** @type {?} */ const diagramEngine = this.diagramModel.getDiagramEngine(); /** @type {?} */ const action = this.action$.getValue(); // are we going to connect a link to something? if (action instanceof MoveItemsAction) { /** @type {?} */ const element = this.getMouseElement(event); action.selectionModels.forEach((/** * @param {?} model * @return {?} */ model => { // only care about points connecting to things if (!(model.model instanceof PointModel)) { return; } if (element && element.model instanceof PortModel && !diagramEngine.isModelLocked(element.model)) { /** @type {?} */ const link = model.model.getLink(); if (link.getTargetPort() !== null) { // if this was a valid link already and we are adding a node in the middle, create 2 links from the original if (link.getTargetPort() !== element.model && link.getSourcePort() !== element.model) { /** @type {?} */ const targetPort = link.getTargetPort(); /** @type {?} */ const newLink = link.clone({}); newLink.setSourcePort(element.model); newLink.setTargetPort(targetPort); link.setTargetPort(element.model); targetPort.removeLink(link); newLink.removePointsBefore(newLink.getPoints()[link.getPointIndex(model.model)]); link.removePointsAfter(model.model); diagramEngine.getDiagramModel().addLink(newLink); // if we are connecting to the same target or source, destroy tweener points } else if (link.getTargetPort() === element.model) { link.removePointsAfter(model.model); } else if (link.getSourcePort() === element.model) { link.removePointsBefore(model.model); } } else { link.setTargetPort(element.model); /** @type {?} */ const targetPort = link.getTargetPort(); /** @type {?} */ const srcPort = link.getSourcePort(); if (targetPort.id !== srcPort.id) { // link is valid, fire the event this.startFiringAction(new LinkCreatedAction(event.clientX, event.clientY, link)); } } } })); // check for / destroy any loose links in any models which have been moved if (!this.allowLooseLinks) { action.selectionModels.forEach((/** * @param {?} model * @return {?} */ model => { // only care about points connecting to things if (!(model.model instanceof PointModel)) { return; } /** @type {?} */ const selectedPoint = model.model; /** @type {?} */ const link = selectedPoint.getLink(); if (link.getSourcePort() === null || link.getTargetPort() === null) { link.destroy(); } })); } // destroy any invalid links action.selectionModels.forEach((/** * @param {?} model * @return {?} */ model => { // only care about points connecting to things if (!(model.model instanceof PointModel)) { return; } /** @type {?} */ const link = model.model.getLink(); /** @type {?} */ const sourcePort = link.getSourcePort(); /** @type {?} */ const targetPort = link.getTargetPort(); if (sourcePort !== null && targetPort !== null) { if (!sourcePort.canLinkToPort(targetPort)) { // link not allowed link.destroy(); } else if (some(Object.values(targetPort.getLinks()), (/** * @param {?} l * @return {?} */ (l) => l !== link && (l.getSourcePort() === sourcePort || l.getTargetPort() === sourcePort)))) { // link is a duplicate link.destroy(); } } })); this.stopFiringAction(); } else { this.stopFiringAction(); } this.mouseUpListener(); this.mouseMoveListener(); this.action$.next(null); }); this.onMouseMove = (/** * @param {?} event * @return {?} */ (event) => { /** @type {?} */ const action = this.action$.getValue(); if (action === null || action === undefined) { return; } if (action instanceof SelectingAction) { /** @type {?} */ const relative = this.diagramModel.getDiagramEngine().getRelativePoint(event.clientX, event.clientY); Object.values(this.diagramModel.getNodes()).forEach((/** * @param {?} node * @return {?} */ node => { if (((/** @type {?} */ (action))).containsElement(node.getCoords(), this.diagramModel)) { node.setSelected(); } else { node.setSelected(false); } })); Object.values(this.diagramModel.getLinks()).forEach((/** * @param {?} link * @return {?} */ link => { /** @type {?} */ let allSelected = true; link.getPoints().forEach((/** * @param {?} point * @return {?} */ point => { if (((/** @type {?} */ (action))).containsElement(point.getCoords(), this.diagramModel)) { point.setSelected(); } else { point.setSelected(false); allSelected = false; } })); if (allSelected) { link.setSelected(); } })); action.mouseX2 = relative.x; action.mouseY2 = relative.y; this.fireAction(); this.action$.next(action); return; } else if (action instanceof MoveItemsAction) { /** @type {?} */ const coords = { x: event.clientX - action.mouseX, y: event.clientY - action.mouseY }; /** @type {?} */ const amountZoom = this.diagramModel.getZoomLevel() / 100; action.selectionModels.forEach((/** * @param {?} model * @return {?} */ model => { // in this case we need to also work out the relative grid position if (model.model instanceof NodeModel || (model.model instanceof PointModel && !model.model.isConnectedToPort())) { /** @type {?} */ const newCoords = { x: model.initialX + coords.x / amountZoom, y: model.initialY + coords.y / amountZoom }; model.model.setCoords(this.diagramModel.getGridPosition(newCoords)); if (model.model instanceof NodeModel) { // update port coordinates as well Object.values(model.model.getPorts()).forEach((/** * @param {?} port * @return {?} */ port => { /** @type {?} */ const portCoords = this.diagramModel.getDiagramEngine().getPortCoords(port); port.updateCoords(portCoords); })); } } else if (model.model instanceof PointModel) { // we want points that are connected to ports, to not necessarily snap to grid // this stuff needs to be pixel perfect, dont touch it /** @type {?} */ const newCoords = this.diagramModel.getGridPosition({ x: coords.x / amountZoom, y: coords.y / amountZoom }); model.model.setCoords({ x: model.initialX + newCoords.x, y: model.initialY + newCoords.y }); } })); this.fireAction(); } else if (action instanceof MoveCanvasAction) { if (this.allowCanvasTranslation) { this.diagramModel.setOffset(action.initialOffsetX + (event.clientX - action.mouseX), action.initialOffsetY + (event.clientY - action.mouseY)); this.fireAction(); } } }); } // TODO: handle destruction of container, resseting all observables to avoid memory leaks! /** * @return {?} */ ngOnInit() { if (this.diagramModel) { this.diagramModel.getDiagramEngine().setCanvas(this.canvas.nativeElement); this.nodes$ = this.diagramModel.selectNodes(); this.links$ = this.diagramModel.selectLinks(); this.nodesRendered$ = new BehaviorSubject(false); this.nodes$.pipe(takeUntil(this.destroyed$)).subscribe((/** * @param {?} nodes * @return {?} */ nodes => { this.nodesRendered$.next(false); Object.values(nodes).forEach((/** * @param {?} node * @return {?} */ node => { if (!node.getPainted()) { this.diagramModel.getDiagramEngine().generateWidgetForNode(node, this.nodesLayer); node.setPainted(); this.cdRef.detectChanges(); } })); this.nodesRendered$.next(true); })); } } /** * @return {?} */ ngOnDestroy() { this.destroyed$.next(true); this.destroyed$.complete(); } /** * @return {?} */ ngAfterViewInit() { combineLatest([this.nodesRendered$, this.links$]) .pipe(takeUntil(this.destroyed$), filter((/** * @param {?} __0 * @return {?} */ ([nodesRendered, _]) => !!nodesRendered))) .subscribe((/** * @param {?} __0 * @return {?} */ ([_, links]) => { Object.values(links).forEach((/** * @param {?} link * @return {?} */ link => { if (!link.getPainted()) { if (link.getSourcePort() !== null) { /** @type {?} */ const portCenter = this.diagramModel.getDiagramEngine().getPortCenter(link.getSourcePort()); link.getPoints()[0].setCoords(portCenter); /** @type {?} */ const portCoords = this.diagramModel.getDiagramEngine().getPortCoords(link.getSourcePort()); link.getSourcePort().updateCoords(portCoords); } if (link.getTargetPort() !== null) { /** @type {?} */ const portCenter = this.diagramModel.getDiagramEngine().getPortCenter(link.getTargetPort()); link.getPoints()[link.getPoints().length - 1].setCoords(portCenter); /** @type {?} */ const portCoords = this.diagramModel.getDiagramEngine().getPortCoords(link.getTargetPort()); link.getTargetPort().updateCoords(portCoords); } this.diagramModel.getDiagramEngine().generateWidgetForLink(link, this.linksLayer); link.setPainted(); this.cdRef.detectChanges(); } })); })); } /** * fire the action registered and notify subscribers * @return {?} */ fireAction() { if (this.action$.value) { this.actionStillFiring.emit(this.action$.value); } } /** * Unregister the action, post firing and notify subscribers * @param {?=} shouldSkipEvent * @return {?} */ stopFiringAction(shouldSkipEvent) { if (!shouldSkipEvent) { this.actionStoppedFiring.emit(this.action$.value); } this.action$.next(null); } /** * Register the new action, pre firing and notify subscribers * @param {?} action * @return {?} */ startFiringAction(action) { this.action$.next(action); this.actionStartedFiring.emit(action); } /** * @return {?} */ selectAction() { return this.action$; } /** * @return {?} */ shouldDrawSelectionBox() { /** @type {?} */ const action = this.action$.getValue(); if (action instanceof SelectingAction) { action.getBoxDimensions(); return true; } return false; } /** * @param {?} event * @return {?} */ getMouseElement(event) { /** @type {?} */ const target = (/** @type {?} */ (event.target)); // is it a port? /** @type {?} */ let element = target.closest('[data-portid]'); if (element) { // get the relevant node and return the port. /** @type {?} */ const nodeEl = target.closest('[data-nodeid]'); return { model: this.diagramModel.getNode(nodeEl.getAttribute('data-nodeid')).getPort(element.getAttribute('data-portid')), element }; } // look for a point element = target.closest('[data-pointid]'); if (element) { return { model: this.diagramModel.getLink(element.getAttribute('data-linkid')).getPointModel(element.getAttribute('data-pointid')), element }; } // look for a link element = target.closest('[data-linkid]'); if (element) { return { model: this.diagramModel.getLink(element.getAttribute('data-linkid')), element }; } // a node maybe element = target.closest('[data-nodeid]'); if (element) { return { model: this.diagramModel.getNode(element.getAttribute('data-nodeid')), element }; } // just the canvas return null; } /** * @param {?} event * @return {?} */ onMouseDown(event) { if (event.button === 3) { return; } /** @type {?} */ const selectedModel = this.getMouseElement(event); // canvas selected if (selectedModel === null) { // multiple selection if (event.shiftKey) { // initiate multiple selection selector /** @type {?} */ const relative = this.diagramModel.getDiagramEngine().getRelativePoint(event.clientX, event.clientY); this.startFiringAction(new SelectingAction(relative.x, relative.y)); } else { // drag canvas action this.diagramModel.clearSelection(); this.startFiringAction(new MoveCanvasAction(event.clientX, event.clientY, this.diagramModel)); } } else if (selectedModel.model instanceof PortModel) { // its a port element, we want to drag a link if (!this.diagramModel.getDiagramEngine().isModelLocked(selectedModel.model)) { /** @type {?} */ const relative = this.diagramModel.getDiagramEngine().getRelativeMousePoint(event); /** @type {?} */ const sourcePort = selectedModel.model; /** @type {?} */ const link = sourcePort.createLinkModel(); link.setSourcePort(sourcePort); if (link) { link.removeMiddlePoints(); if (link.getSourcePort() !== sourcePort) { link.setSourcePort(sourcePort); } link.setTargetPort(null); link.getFirstPoint().setCoords(relative); link.getLastPoint().setCoords(relative); this.diagramModel.clearSelection(); link.getLastPoint().setSelected(); this.diagramModel.addLink(link); this.startFiringAction(new MoveItemsAction(event.clientX, event.clientY, this.diagramModel.getDiagramEngine())); } } else { this.diagramModel.clearSelection(); } } else { // its some other element, probably want to move it if (!event.shiftKey && !selectedModel.model.getSelected()) { this.diagramModel.clearSelection(); } selectedModel.model.setSelected(); this.startFiringAction(new MoveItemsAction(event.clientX, event.clientY, this.diagramModel.getDiagramEngine())); } // create mouseMove and mouseUp listeners this.mouseMoveListener = this.renderer.listen(document, 'mousemove', this.onMouseMove); this.mouseUpListener = this.renderer.listen(document, 'mouseup', this.onMouseUp); } /** * @param {?} event * @return {?} */ onMouseWheel(event) { if (this.allowCanvasZoon) { event.preventDefault(); event.stopPropagation(); /** @type {?} */ const currentZoomLevel = this.diagramModel.getZoomLevel(); /** @type {?} */ const oldZoomFactor = currentZoomLevel / 100; /** @type {?} */ let scrollDelta = this.inverseZoom ? -event.deltaY : event.deltaY; // check if it is pinch gesture if (event.ctrlKey && scrollDelta % 1 !== 0) { /* Chrome and Firefox sends wheel event with deltaY that have fractional part, also `ctrlKey` prop of the event is true though ctrl isn't pressed */ scrollDelta /= 3; } else { scrollDelta /= 60; } if (currentZoomLevel + scrollDelta > 10) { this.diagramModel.setZoomLevel(currentZoomLevel + scrollDelta); } /** @type {?} */ const zoomFactor = this.diagramModel.getZoomLevel() / 100; /** @type {?} */ const boundingRect = ((/** @type {?} */ (event.currentTarget))).getBoundingClientRect(); /** @type {?} */ const clientWidth = boundingRect.width; /** @type {?} */ const clientHeight = boundingRect.height; // compute difference between rect before and after scroll /** @type {?} */ const widthDiff = clientWidth * zoomFactor - clientWidth * oldZoomFactor; /** @type {?} */ const heightDiff = clientHeight * zoomFactor - clientHeight * oldZoomFactor; // compute mouse coords relative to canvas /** @type {?} */ const clientX = event.clientX - boundingRect.left; /** @type {?} */ const clientY = event.clientY - boundingRect.top; // compute width and height increment factor /** @type {?} */ const xFactor = (clientX - this.diagramModel.getOffsetX()) / oldZoomFactor / clientWidth; /** @type {?} */ const yFactor = (clientY - this.diagramModel.getOffsetY()) / oldZoomFactor / clientHeight; this.diagramModel.setOffset(this.diagramModel.getOffsetX() - widthDiff * xFactor, this.diagramModel.getOffsetY() - heightDiff * yFactor); } } } NgxDiagramComponent.decorators = [ { type: Component, args: [{ selector: 'ngdx-diagram', template: "<div class=\"ngdx-diagram\" #canvas (mousedown)=\"onMouseDown($event)\" (wheel)=\"onMouseWheel($event)\">\n\t<!-- Nodes Layer -->\n\t<div\n\t\tclass=\"ngdx-nodes-layer\"\n\t\t[ngStyle]=\"{\n\t\t\ttransform:\n\t\t\t\t'translate(' +\n\t\t\t\t(diagramModel.selectOffsetX() | async) +\n\t\t\t\t'px, ' +\n\t\t\t\t(diagramModel.selectOffsetY() | async) +\n\t\t\t\t'px) scale(' +\n\t\t\t\t(diagramModel.selectZoomLevel() | async) / 100.0 +\n\t\t\t\t')'\n\t\t}\"\n\t>\n\t\t<ng-template #nodesLayer></ng-template>\n\t</div>\n\n\t<!-- Links Layer -->\n\t<div\n\t\tclass=\"ngdx-links-layer\"\n\t\t[ngStyle]=\"{\n\t\t\ttransform:\n\t\t\t\t'translate(' +\n\t\t\t\t(diagramModel.selectOffsetX() | async) +\n\t\t\t\t'px, ' +\n\t\t\t\t(diagramModel.selectOffsetY() | async) +\n\t\t\t\t'px) scale(' +\n\t\t\t\t(diagramModel.selectZoomLevel() | async) / 100.0 +\n\t\t\t\t')'\n\t\t}\"\n\t>\n\t\t<ng-template #linksLayer></ng-template>\n\t</div>\n\n\t<!-- Selection Box -->\n\t<div\n\t\t*ngIf=\"shouldDrawSelectionBox() && selectAction() | async as action\"\n\t\tclass=\"selector\"\n\t\t[ngStyle]=\"{\n\t\t\ttop: action.dimensions.top + 'px',\n\t\t\tleft: action.dimensions.left + 'px',\n\t\t\twidth: action.dimensions.width + 'px',\n\t\t\theight: action.dimensions.height + 'px'\n\t\t}\"\n\t></div>\n</div>\n", changeDetection: ChangeDetectionStrategy.OnPush, styles: [".ngdx-diagram{position:relative;flex-grow:1;display:flex;cursor:move;overflow:hidden}.ngdx-diagram .selector{position:absolute;background-color:rgba(0,192,255,.2);border:2px solid #00c0ff}.ngdx-diagram .ngdx-nodes-layer{position:absolute;height:100%;width:100%;transform-origin:0 0;overflow:visible!important;pointer-events:none;z-index:150;top:0;bottom:0;left:0;right:0}.ngdx-diagram .ngdx-links-layer{position:absolute;height:100%;width:100%;transform-origin:0 0;overflow:visible!important;pointer-events:none;z-index:100;top:0;bottom:0;left:0;right:0}"] }] } ]; /** @nocollapse */ NgxDiagramComponent.ctorParameters = () => [ { type: Renderer2 }, { type: ChangeDetectorRef } ]; NgxDiagramComponent.propDecorators = { diagramModel: [{ type: Input, args: ['model',] }], allowCanvasZoon: [{ type: Input }], allowCanvasTranslation: [{ type: Input }], inverseZoom: [{ type: Input }], allowLooseLinks: [{ type: Input }], actionStartedFiring: [{ type: Output }], actionStillFiring: [{ type: Output }], actionStoppedFiring: [{ type: Output }], nodesLayer: [{ type: ViewChild, args: ['nodesLayer', { read: ViewContainerRef, static: true },] }], linksLayer: [{ type: ViewChild, args: ['linksLayer', { read: ViewContainerRef, static: true },] }], canvas: [{ type: ViewChild, args: ['canvas', { read: ElementRef, static: true },] }] }; if (false) { /** @type {?} */ NgxDiagramComponent.prototype.diagramModel; /** @type {?} */ NgxDiagramComponent.prototype.allowCanvasZoon; /** @type {?} */ NgxDiagramComponent.prototype.allowCanvasTranslation; /** @type {?} */ NgxDiagramComponent.prototype.inverseZoom; /** @type {?} */ NgxDiagramComponent.prototype.allowLooseLinks; /** @type {?} */ NgxDiagramComponent.prototype.actionStartedFiring; /** @type {?} */ NgxDiagramComponent.prototype.actionStillFiring; /** @type {?} */ NgxDiagramComponent.prototype.actionStoppedFiring; /** @type {?} */ NgxDiagramComponent.prototype.nodesLayer; /** @type {?} */ NgxDiagramComponent.prototype.linksLayer; /** @type {?} */ NgxDiagramComponent.prototype.canvas; /** * @type {?} * @private */ NgxDiagramComponent.prototype.nodes$; /** * @type {?} * @private */ NgxDiagramComponent.prototype.links$; /** * @type {?} * @private */ NgxDiagramComponent.prototype.action$; /** * @type {?} * @private */ NgxDiagramComponent.prototype.nodesRendered$; /** * @type {?} * @private */ NgxDiagramComponent.prototype.destroyed$; /** * @type {?} * @private */ NgxDiagramComponent.prototype.mouseUpListener; /** * @type {?} * @private */ NgxDiagramComponent.prototype.mouseMoveListener; /** @type {?} */ NgxDiagramComponent.prototype.onMouseUp; /** @type {?} */ NgxDiagramComponent.prototype.onMouseMove; /** * @type {?} * @private */ NgxDiagramComponent.prototype.renderer; /** * @type {?} * @private */ NgxDiagramComponent.prototype.cdRef; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlhZ3JhbS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtZGlhZ3JhbXMvIiwic291cmNlcyI6WyJsaWIvY29udGFpbmVycy9kaWFncmFtL2RpYWdyYW0uY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsT0FBTyxFQUNOLFNBQVMsRUFFVCxLQUFLLEVBQ0wsU0FBUyxFQUNULE1BQU0sRUFDTixZQUFZLEVBQ1osU0FBUyxFQUNULGdCQUFnQixFQUNoQixVQUFVLEVBRVYsdUJBQXVCLEVBQ3ZCLGlCQUFpQixFQUVqQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDMUQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRXBELE9BQU8sRUFBRSxlQUFlLEVBQWMsYUFBYSxFQUFFLGFBQWEsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNqRixPQUFPLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ25ELE9BQU8sRUFBYyxnQkFBZ0IsRUFBRSxlQUFlLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFakcsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2xFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUV0RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDcEQsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLFFBQVEsQ0FBQztBQVE5QixNQUFNLE9BQU8sbUJBQW1COzs7OztJQXlCL0IsWUFBb0IsUUFBbUIsRUFBVSxLQUF3QjtRQUFyRCxhQUFRLEdBQVIsUUFBUSxDQUFXO1FBQVUsVUFBSyxHQUFMLEtBQUssQ0FBbUI7UUF0QmhFLG9CQUFlLEdBQUcsSUFBSSxDQUFDO1FBQ3ZCLDJCQUFzQixHQUFHLElBQUksQ0FB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QkFDaEUsU0FBUyxTQUFDLFFBQVEsRUFBRSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTs7OztJQVp2RCwyQ0FBMkM7O0lBQzNDLDhDQUFnQzs7SUFDaEMscURBQXVDOztJQUN2QywwQ0FBNEI7O0lBQzVCLDhDQUFnQzs7SUFFaEMsa0RBQTZFOztJQUM3RSxnREFBMkU7O0lBQzNFLGtEQUE2RTs7SUFFN0UseUNBQWdHOztJQUNoRyx5Q0FBZ0c7O0lBQ2hHLHFDQUE0RTs7Ozs7SUFFNUUscUNBQXVEOzs7OztJQUN2RCxxQ0FBdUQ7Ozs7O0lBQ3ZELHNDQUF5RTs7Ozs7SUFDekUsNkNBQWlEOzs7OztJQUNqRCx5Q0FBa0U7Ozs7O0lBRWxFLDhDQUFtQzs7Ozs7SUFDbkMsZ0RBQXFDOztJQXNKckMsd0NBK0ZFOztJQUVGLDBDQThFRTs7Ozs7SUFuVVUsdUNBQTJCOzs7OztJQUFFLG9DQUFnQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG5cdENvbXBvbmVudCxcblx0T25Jbml0LFxuXHRJbnB1dCxcblx0UmVuZGVyZXIyLFxuXHRPdXRwdXQsXG5cdEV2ZW50RW1pdHRlcixcblx0Vmlld0NoaWxkLFxuXHRWaWV3Q29udGFpbmVyUmVmLFxuXHRFbGVtZW50UmVmLFxuXHRBZnRlclZpZXdJbml0LFxuXHRDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcblx0Q2hhbmdlRGV0ZWN0b3JSZWYsXG5cdE9uRGVzdHJveVxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IERpYWdyYW1Nb2RlbCB9IGZyb20gJy4uLy4uL21vZGVscy9kaWFncmFtLm1vZGVsJztcbmltcG9ydCB7IE5vZGVNb2Rlb