UNPKG

@hugogo/angular-grid-layout-hugo

Version:

Grid Layout with draggable and resizable items for Angular

163 lines 31.4 kB
import { ChangeDetectionStrategy, Component, ContentChildren, ElementRef, Inject, Input, NgZone, Renderer2, ViewChild } from '@angular/core'; import { BehaviorSubject, iif, merge, NEVER, Subject } from 'rxjs'; import { exhaustMap, filter, map, startWith, switchMap, take, takeUntil } from 'rxjs/operators'; import { ktdMouseOrTouchDown, ktdMouseOrTouchEnd, ktdPointerClient } from '../utils/pointer.utils'; import { GRID_ITEM_GET_RENDER_DATA_TOKEN } from '../grid.definitions'; import { KTD_GRID_DRAG_HANDLE } from '../directives/drag-handle'; import { KTD_GRID_RESIZE_HANDLE } from '../directives/resize-handle'; import { KtdGridService } from '../grid.service'; import { ktdOutsideZone } from '../utils/operators'; import { coerceBooleanProperty } from '../coercion/boolean-property'; import { coerceNumberProperty } from '../coercion/number-property'; export class KtdGridItemComponent { constructor(elementRef, gridService, renderer, ngZone, getItemRenderData) { this.elementRef = elementRef; this.gridService = gridService; this.renderer = renderer; this.ngZone = ngZone; this.getItemRenderData = getItemRenderData; /** CSS transition style. Note that for more performance is preferable only make transition on transform property. */ this.transition = 'transform 500ms ease, width 500ms ease, height 500ms ease'; this._dragStartThreshold = 0; this._draggable = true; this._draggable$ = new BehaviorSubject(this._draggable); this._resizable = true; this._resizable$ = new BehaviorSubject(this._resizable); this.dragStartSubject = new Subject(); this.resizeStartSubject = new Subject(); this.subscriptions = []; this.dragStart$ = this.dragStartSubject.asObservable(); this.resizeStart$ = this.resizeStartSubject.asObservable(); } /** Id of the grid item. This property is strictly compulsory. */ get id() { return this._id; } set id(val) { this._id = val; } /** Minimum amount of pixels that the user should move before it starts the drag sequence. */ get dragStartThreshold() { return this._dragStartThreshold; } set dragStartThreshold(val) { this._dragStartThreshold = coerceNumberProperty(val); } /** Whether the item is draggable or not. Defaults to true. */ get draggable() { return this._draggable; } set draggable(val) { this._draggable = coerceBooleanProperty(val); this._draggable$.next(this._draggable); } /** Whether the item is resizable or not. Defaults to true. */ get resizable() { return this._resizable; } set resizable(val) { this._resizable = coerceBooleanProperty(val); this._resizable$.next(this._resizable); } ngOnInit() { const gridItemRenderData = this.getItemRenderData(this.id); this.setStyles(gridItemRenderData); } ngAfterContentInit() { this.subscriptions.push(this._dragStart$().subscribe(this.dragStartSubject), this._resizeStart$().subscribe(this.resizeStartSubject)); } ngOnDestroy() { this.subscriptions.forEach(sub => sub.unsubscribe()); } setStyles({ top, left, width, height }) { // transform is 6x times faster than top/left this.renderer.setStyle(this.elementRef.nativeElement, 'transform', `translateX(${left}) translateY(${top})`); this.renderer.setStyle(this.elementRef.nativeElement, 'display', `block`); this.renderer.setStyle(this.elementRef.nativeElement, 'transition', this.transition); if (width != null) { this.renderer.setStyle(this.elementRef.nativeElement, 'width', width); } if (height != null) { this.renderer.setStyle(this.elementRef.nativeElement, 'height', height); } } _dragStart$() { return this._draggable$.pipe(switchMap((draggable) => { if (!draggable) { return NEVER; } else { return this._dragHandles.changes.pipe(startWith(this._dragHandles), switchMap((dragHandles) => { return iif(() => dragHandles.length > 0, merge(...dragHandles.toArray().map(dragHandle => ktdMouseOrTouchDown(dragHandle.element.nativeElement, 1))), ktdMouseOrTouchDown(this.elementRef.nativeElement, 1)).pipe(exhaustMap((startEvent) => { // If the event started from an element with the native HTML drag&drop, it'll interfere // with our own dragging (e.g. `img` tags do it by default). Prevent the default action // to stop it from happening. Note that preventing on `dragstart` also seems to work, but // it's flaky and it fails if the user drags it away quickly. Also note that we only want // to do this for `mousedown` since doing the same for `touchstart` will stop any `click` // events from firing on touch devices. if (startEvent.target && startEvent.target.draggable && startEvent.type === 'mousedown') { startEvent.preventDefault(); } const startPointer = ktdPointerClient(startEvent); return this.gridService.mouseOrTouchMove$(document).pipe(takeUntil(ktdMouseOrTouchEnd(document, 1)), ktdOutsideZone(this.ngZone), filter((moveEvent) => { moveEvent.preventDefault(); const movePointer = ktdPointerClient(moveEvent); const distanceX = Math.abs(startPointer.clientX - movePointer.clientX); const distanceY = Math.abs(startPointer.clientY - movePointer.clientY); // When this conditions returns true mean that we are over threshold. return distanceX + distanceY >= this.dragStartThreshold; }), take(1), // Return the original start event map(() => startEvent)); })); })); } })); } _resizeStart$() { return this._resizable$.pipe(switchMap((resizable) => { if (!resizable) { // Side effect to hide the resizeElem if resize is disabled. this.renderer.setStyle(this.resizeElem.nativeElement, 'display', 'none'); return NEVER; } else { return this._resizeHandles.changes.pipe(startWith(this._resizeHandles), switchMap((resizeHandles) => { if (resizeHandles.length > 0) { // Side effect to hide the resizeElem if there are resize handles. this.renderer.setStyle(this.resizeElem.nativeElement, 'display', 'none'); return merge(...resizeHandles.toArray().map(resizeHandle => ktdMouseOrTouchDown(resizeHandle.element.nativeElement, 1))); } else { this.renderer.setStyle(this.resizeElem.nativeElement, 'display', 'block'); return ktdMouseOrTouchDown(this.resizeElem.nativeElement, 1); } })); } })); } } KtdGridItemComponent.decorators = [ { type: Component, args: [{ selector: 'ktd-grid-item', template: "<ng-content></ng-content>\n<div #resizeElem class=\"grid-item-resize-icon\"></div>\n", changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:none;overflow:hidden;z-index:1}:host,:host div{position:absolute}:host div{-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none;z-index:10}:host div.grid-item-resize-icon{bottom:0;color:inherit;cursor:se-resize;height:20px;right:0;width:20px}:host div.grid-item-resize-icon:after{border-bottom:2px solid;border-right:2px solid;bottom:3px;content:\"\";height:5px;position:absolute;right:3px;width:5px}.display-none{display:none!important}"] },] } ]; KtdGridItemComponent.ctorParameters = () => [ { type: ElementRef }, { type: KtdGridService }, { type: Renderer2 }, { type: NgZone }, { type: undefined, decorators: [{ type: Inject, args: [GRID_ITEM_GET_RENDER_DATA_TOKEN,] }] } ]; KtdGridItemComponent.propDecorators = { _dragHandles: [{ type: ContentChildren, args: [KTD_GRID_DRAG_HANDLE, { descendants: true },] }], _resizeHandles: [{ type: ContentChildren, args: [KTD_GRID_RESIZE_HANDLE, { descendants: true },] }], resizeElem: [{ type: ViewChild, args: ['resizeElem', { static: true, read: ElementRef },] }], transition: [{ type: Input }], id: [{ type: Input }], dragStartThreshold: [{ type: Input }], draggable: [{ type: Input }], resizable: [{ type: Input }] }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JpZC1pdGVtLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIuLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyLWdyaWQtbGF5b3V0LWh1Z28vc3JjLyIsInNvdXJjZXMiOlsibGliL2dyaWQtaXRlbS9ncmlkLWl0ZW0uY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDZSx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsZUFBZSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBZ0MsU0FBUyxFQUNqSixTQUFTLEVBQ1osTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLGVBQWUsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBYyxPQUFPLEVBQWdCLE1BQU0sTUFBTSxDQUFDO0FBQzdGLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNoRyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsa0JBQWtCLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNuRyxPQUFPLEVBQUUsK0JBQStCLEVBQWtDLE1BQU0scUJBQXFCLENBQUM7QUFDdEcsT0FBTyxFQUFFLG9CQUFvQixFQUFxQixNQUFNLDJCQUEyQixDQUFDO0FBQ3BGLE9BQU8sRUFBRSxzQkFBc0IsRUFBdUIsTUFBTSw2QkFBNkIsQ0FBQztBQUMxRixPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDakQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3BELE9BQU8sRUFBZ0IscUJBQXFCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUNuRixPQUFPLEVBQUUsb0JBQW9CLEVBQWUsTUFBTSw2QkFBNkIsQ0FBQztBQVFoRixNQUFNLE9BQU8sb0JBQW9CO0lB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Q29udGVudEluaXQsIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIENvbnRlbnRDaGlsZHJlbiwgRWxlbWVudFJlZiwgSW5qZWN0LCBJbnB1dCwgTmdab25lLCBPbkRlc3Ryb3ksIE9uSW5pdCwgUXVlcnlMaXN0LCBSZW5kZXJlcjIsXG4gICAgVmlld0NoaWxkXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBpaWYsIG1lcmdlLCBORVZFUiwgT2JzZXJ2YWJsZSwgU3ViamVjdCwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBleGhhdXN0TWFwLCBmaWx0ZXIsIG1hcCwgc3RhcnRXaXRoLCBzd2l0Y2hNYXAsIHRha2UsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IGt0ZE1vdXNlT3JUb3VjaERvd24sIGt0ZE1vdXNlT3JUb3VjaEVuZCwga3RkUG9pbnRlckNsaWVudCB9IGZyb20gJy4uL3V0aWxzL3BvaW50ZXIudXRpbHMnO1xuaW1wb3J0IHsgR1JJRF9JVEVNX0dFVF9SRU5ERVJfREFUQV9UT0tFTiwgS3RkR3JpZEl0ZW1SZW5kZXJEYXRhVG9rZW5UeXBlIH0gZnJvbSAnLi4vZ3JpZC5kZWZpbml0aW9ucyc7XG5pbXBvcnQgeyBLVERfR1JJRF9EUkFHX0hBTkRMRSwgS3RkR3JpZERyYWdIYW5kbGUgfSBmcm9tICcuLi9kaXJlY3RpdmVzL2RyYWctaGFuZGxlJztcbmltcG9ydCB7IEtURF9HUklEX1JFU0laRV9IQU5ETEUsIEt0ZEdyaWRSZXNpemVIYW5kbGUgfSBmcm9tICcuLi9kaXJlY3RpdmVzL3Jlc2l6ZS1oYW5kbGUnO1xuaW1wb3J0IHsgS3RkR3JpZFNlcnZpY2UgfSBmcm9tICcuLi9ncmlkLnNlcnZpY2UnO1xuaW1wb3J0IHsga3RkT3V0c2lkZVpvbmUgfSBmcm9tICcuLi91dGlscy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQm9vbGVhbklucHV0LCBjb2VyY2VCb29sZWFuUHJvcGVydHkgfSBmcm9tICcuLi9jb2VyY2lvbi9ib29sZWFuLXByb3BlcnR5JztcbmltcG9ydCB7IGNvZXJjZU51bWJlclByb3BlcnR5LCBOdW1iZXJJbnB1dCB9IGZyb20gJy4uL2NvZXJjaW9uL251bWJlci1wcm9wZXJ0eSc7XG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAna3RkLWdyaWQtaXRlbScsXG4gICAgdGVtcGxhdGVVcmw6ICcuL2dyaWQtaXRlbS5jb21wb25lbnQuaHRtbCcsXG4gICAgc3R5bGVVcmxzOiBbJy4vZ3JpZC1pdGVtLmNvbXBvbmVudC5zY3NzJ10sXG4gICAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2hcbn0pXG5leHBvcnQgY2xhc3MgS3RkR3JpZEl0ZW1Db21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSwgQWZ0ZXJDb250ZW50SW5pdCB7XG4gICAgLyoqIEVsZW1lbnRzIHRoYXQgY2FuIGJlIHVzZWQgdG8gZHJhZyB0aGUgZ3JpZCBpdGVtLiAqL1xuICAgIEBDb250ZW50Q2hpbGRyZW4oS1REX0dSSURfRFJBR19IQU5ETEUsIHtkZXNjZW5kYW50czogdHJ1ZX0pIF9kcmFnSGFuZGxlczogUXVlcnlMaXN0PEt0ZEdyaWREcmFnSGFuZGxlPjtcbiAgICBAQ29udGVudENoaWxkcmVuKEtURF9HUklEX1JFU0laRV9IQU5ETEUsIHtkZXNjZW5kYW50czogdHJ1ZX0pIF9yZXNpemVIYW5kbGVzOiBRdWVyeUxpc3Q8S3RkR3JpZFJlc2l6ZUhhbmRsZT47XG4gICAgQFZpZXdDaGlsZCgncmVzaXplRWxlbScsIHtzdGF0aWM6IHRydWUsIHJlYWQ6IEVsZW1lbnRSZWZ9KSByZXNpemVFbGVtOiBFbGVtZW50UmVmO1xuXG4gICAgLyoqIENTUyB0cmFuc2l0aW9uIHN0eWxlLiBOb3RlIHRoYXQgZm9yIG1vcmUgcGVyZm9ybWFuY2UgaXMgcHJlZmVyYWJsZSBvbmx5IG1ha2UgdHJhbnNpdGlvbiBvbiB0cmFuc2Zvcm0gcHJvcGVydHkuICovXG4gICAgQElucHV0KCkgdHJhbnNpdGlvbjogc3RyaW5nID0gJ3RyYW5zZm9ybSA1MDBtcyBlYXNlLCB3aWR0aCA1MDBtcyBlYXNlLCBoZWlnaHQgNTAwbXMgZWFzZSc7XG5cbiAgICBkcmFnU3RhcnQkOiBPYnNlcnZhYmxlPE1vdXNlRXZlbnQgfCBUb3VjaEV2ZW50PjtcbiAgICByZXNpemVTdGFydCQ6IE9ic2VydmFibGU8TW91c2VFdmVudCB8IFRvdWNoRXZlbnQ+O1xuXG4gICAgLyoqIElkIG9mIHRoZSBncmlkIGl0ZW0uIFRoaXMgcHJvcGVydHkgaXMgc3RyaWN0bHkgY29tcHVsc29yeS4gKi9cbiAgICBASW5wdXQoKVxuICAgIGdldCBpZCgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5faWQ7XG4gICAgfVxuXG4gICAgc2V0IGlkKHZhbDogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuX2lkID0gdmFsO1xuICAgIH1cblxuICAgIHByaXZhdGUgX2lkOiBzdHJpbmc7XG5cbiAgICAvKiogTWluaW11bSBhbW91bnQgb2YgcGl4ZWxzIHRoYXQgdGhlIHVzZXIgc2hvdWxkIG1vdmUgYmVmb3JlIGl0IHN0YXJ0cyB0aGUgZHJhZyBzZXF1ZW5jZS4gKi9cbiAgICBASW5wdXQoKVxuICAgIGdldCBkcmFnU3RhcnRUaHJlc2hvbGQoKTogbnVtYmVyIHsgcmV0dXJuIHRoaXMuX2RyYWdTdGFydFRocmVzaG9sZDsgfVxuXG4gICAgc2V0IGRyYWdTdGFydFRocmVzaG9sZCh2YWw6IG51bWJlcikge1xuICAgICAgICB0aGlzLl9kcmFnU3RhcnRUaHJlc2hvbGQgPSBjb2VyY2VOdW1iZXJQcm9wZXJ0eSh2YWwpO1xuICAgIH1cblxuICAgIHByaXZhdGUgX2RyYWdTdGFydFRocmVzaG9sZDogbnVtYmVyID0gMDtcblxuXG4gICAgLyoqIFdoZXRoZXIgdGhlIGl0ZW0gaXMgZHJhZ2dhYmxlIG9yIG5vdC4gRGVmYXVsdHMgdG8gdHJ1ZS4gKi9cbiAgICBASW5wdXQoKVxuICAgIGdldCBkcmFnZ2FibGUoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9kcmFnZ2FibGU7XG4gICAgfVxuXG4gICAgc2V0IGRyYWdnYWJsZSh2YWw6IGJvb2xlYW4pIHtcbiAgICAgICAgdGhpcy5fZHJhZ2dhYmxlID0gY29lcmNlQm9vbGVhblByb3BlcnR5KHZhbCk7XG4gICAgICAgIHRoaXMuX2RyYWdnYWJsZSQubmV4dCh0aGlzLl9kcmFnZ2FibGUpO1xuICAgIH1cblxuICAgIHByaXZhdGUgX2RyYWdnYWJsZTogYm9vbGVhbiA9IHRydWU7XG4gICAgcHJpdmF0ZSBfZHJhZ2dhYmxlJDogQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPih0aGlzLl9kcmFnZ2FibGUpO1xuXG4gICAgLyoqIFdoZXRoZXIgdGhlIGl0ZW0gaXMgcmVzaXphYmxlIG9yIG5vdC4gRGVmYXVsdHMgdG8gdHJ1ZS4gKi9cbiAgICBASW5wdXQoKVxuICAgIGdldCByZXNpemFibGUoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9yZXNpemFibGU7XG4gICAgfVxuXG4gICAgc2V0IHJlc2l6YWJsZSh2YWw6IGJvb2xlYW4pIHtcbiAgICAgICAgdGhpcy5fcmVzaXphYmxlID0gY29lcmNlQm9vbGVhblByb3BlcnR5KHZhbCk7XG4gICAgICAgIHRoaXMuX3Jlc2l6YWJsZSQubmV4dCh0aGlzLl9yZXNpemFibGUpO1xuICAgIH1cblxuICAgIHByaXZhdGUgX3Jlc2l6YWJsZTogYm9vbGVhbiA9IHRydWU7XG4gICAgcHJpdmF0ZSBfcmVzaXphYmxlJDogQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPih0aGlzLl9yZXNpemFibGUpO1xuXG4gICAgcHJpdmF0ZSBkcmFnU3RhcnRTdWJqZWN0OiBTdWJqZWN0PE1vdXNlRXZlbnQgfCBUb3VjaEV2ZW50PiA9IG5ldyBTdWJqZWN0PE1vdXNlRXZlbnQgfCBUb3VjaEV2ZW50PigpO1xuICAgIHByaXZhdGUgcmVzaXplU3RhcnRTdWJqZWN0OiBTdWJqZWN0PE1vdXNlRXZlbnQgfCBUb3VjaEV2ZW50PiA9IG5ldyBTdWJqZWN0PE1vdXNlRXZlbnQgfCBUb3VjaEV2ZW50PigpO1xuXG4gICAgcHJpdmF0ZSBzdWJzY3JpcHRpb25zOiBTdWJzY3JpcHRpb25bXSA9IFtdO1xuXG4gICAgY29uc3RydWN0b3IocHVibGljIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWYsXG4gICAgICAgICAgICAgICAgcHJpdmF0ZSBncmlkU2VydmljZTogS3RkR3JpZFNlcnZpY2UsXG4gICAgICAgICAgICAgICAgcHJpdmF0ZSByZW5kZXJlcjogUmVuZGVyZXIyLFxuICAgICAgICAgICAgICAgIHByaXZhdGUgbmdab25lOiBOZ1pvbmUsXG4gICAgICAgICAgICAgICAgQEluamVjdChHUklEX0lURU1fR0VUX1JFTkRFUl9EQVRBX1RPS0VOKSBwcml2YXRlIGdldEl0ZW1SZW5kZXJEYXRhOiBLdGRHcmlkSXRlbVJlbmRlckRhdGFUb2tlblR5cGUpIHtcbiAgICAgICAgdGhpcy5kcmFnU3RhcnQkID0gdGhpcy5kcmFnU3RhcnRTdWJqZWN0LmFzT2JzZXJ2YWJsZSgpO1xuICAgICAgICB0aGlzLnJlc2l6ZVN0YXJ0JCA9IHRoaXMucmVzaXplU3RhcnRTdWJqZWN0LmFzT2JzZXJ2YWJsZSgpO1xuICAgIH1cblxuICAgIG5nT25Jbml0KCkge1xuICAgICAgICBjb25zdCBncmlkSXRlbVJlbmRlckRhdGEgPSB0aGlzLmdldEl0ZW1SZW5kZXJEYXRhKHRoaXMuaWQpITtcbiAgICAgICAgdGhpcy5zZXRTdHlsZXMoZ3JpZEl0ZW1SZW5kZXJEYXRhKTtcbiAgICB9XG5cbiAgICBuZ0FmdGVyQ29udGVudEluaXQoKSB7XG4gICAgICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5wdXNoKFxuICAgICAgICAgICAgdGhpcy5fZHJhZ1N0YXJ0JCgpLnN1YnNjcmliZSh0aGlzLmRyYWdTdGFydFN1YmplY3QpLFxuICAgICAgICAgICAgdGhpcy5fcmVzaXplU3RhcnQkKCkuc3Vic2NyaWJlKHRoaXMucmVzaXplU3RhcnRTdWJqZWN0KSxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBuZ09uRGVzdHJveSgpIHtcbiAgICAgICAgdGhpcy5zdWJzY3JpcHRpb25zLmZvckVhY2goc3ViID0+IHN1Yi51bnN1YnNjcmliZSgpKTtcbiAgICB9XG5cbiAgICBzZXRTdHlsZXMoe3RvcCwgbGVmdCwgd2lkdGgsIGhlaWdodH06IHsgdG9wOiBzdHJpbmcsIGxlZnQ6IHN0cmluZywgd2lkdGg/OiBzdHJpbmcsIGhlaWdodD86IHN0cmluZyB9KSB7XG4gICAgICAgIC8vIHRyYW5zZm9ybSBpcyA2eCB0aW1lcyBmYXN0ZXIgdGhhbiB0b3AvbGVmdFxuICAgICAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LCAndHJhbnNmb3JtJywgYHRyYW5zbGF0ZVgoJHtsZWZ0fSkgdHJhbnNsYXRlWSgke3RvcH0pYCk7XG4gICAgICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsICdkaXNwbGF5JywgYGJsb2NrYCk7XG4gICAgICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsICd0cmFuc2l0aW9uJywgdGhpcy50cmFuc2l0aW9uKTtcbiAgICAgICAgaWYgKHdpZHRoICE9IG51bGwpIHsgdGhpcy5yZW5kZXJlci5zZXRTdHlsZSh0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgJ3dpZHRoJywgd2lkdGgpOyB9XG4gICAgICAgIGlmIChoZWlnaHQgIT0gbnVsbCkge3RoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsICdoZWlnaHQnLCBoZWlnaHQpOyB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfZHJhZ1N0YXJ0JCgpOiBPYnNlcnZhYmxlPE1vdXNlRXZlbnQgfCBUb3VjaEV2ZW50PiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9kcmFnZ2FibGUkLnBpcGUoXG4gICAgICAgICAgICBzd2l0Y2hNYXAoKGRyYWdnYWJsZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghZHJhZ2dhYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBORVZFUjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fZHJhZ0hhbmRsZXMuY2hhbmdlcy5waXBlKFxuICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRXaXRoKHRoaXMuX2RyYWdIYW5kbGVzKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaE1hcCgoZHJhZ0hhbmRsZXM6IFF1ZXJ5TGlzdDxLdGRHcmlkRHJhZ0hhbmRsZT4pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaWlmKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoKSA9PiBkcmFnSGFuZGxlcy5sZW5ndGggPiAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXJnZSguLi5kcmFnSGFuZGxlcy50b0FycmF5KCkubWFwKGRyYWdIYW5kbGUgPT4ga3RkTW91c2VPclRvdWNoRG93bihkcmFnSGFuZGxlLmVsZW1lbnQubmF0aXZlRWxlbWVudCwgMSkpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga3RkTW91c2VPclRvdWNoRG93bih0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgMSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4aGF1c3RNYXAoKHN0YXJ0RXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBldmVudCBzdGFydGVkIGZyb20gYW4gZWxlbWVudCB3aXRoIHRoZSBuYXRpdmUgSFRNTCBkcmFnJmRyb3AsIGl0J2xsIGludGVyZmVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gd2l0aCBvdXIgb3duIGRyYWdnaW5nIChlLmcuIGBpbWdgIHRhZ3MgZG8gaXQgYnkgZGVmYXVsdCkuIFByZXZlbnQgdGhlIGRlZmF1bHQgYWN0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0byBzdG9wIGl0IGZyb20gaGFwcGVuaW5nLiBOb3RlIHRoYXQgcHJldmVudGluZyBvbiBgZHJhZ3N0YXJ0YCBhbHNvIHNlZW1zIHRvIHdvcmssIGJ1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXQncyBmbGFreSBhbmQgaXQgZmFpbHMgaWYgdGhlIHVzZXIgZHJhZ3MgaXQgYXdheSBxdWlja2x5LiBBbHNvIG5vdGUgdGhhdCB3ZSBvbmx5IHdhbnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRvIGRvIHRoaXMgZm9yIGBtb3VzZWRvd25gIHNpbmNlIGRvaW5nIHRoZSBzYW1lIGZvciBgdG91Y2hzdGFydGAgd2lsbCBzdG9wIGFueSBgY2xpY2tgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBldmVudHMgZnJvbSBmaXJpbmcgb24gdG91Y2ggZGV2aWNlcy5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdGFydEV2ZW50LnRhcmdldCAmJiAoc3RhcnRFdmVudC50YXJnZXQgYXMgSFRNTEVsZW1lbnQpLmRyYWdnYWJsZSAmJiBzdGFydEV2ZW50LnR5cGUgPT09ICdtb3VzZWRvd24nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRFdmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdGFydFBvaW50ZXIgPSBrdGRQb2ludGVyQ2xpZW50KHN0YXJ0RXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ3JpZFNlcnZpY2UubW91c2VPclRvdWNoTW92ZSQoZG9jdW1lbnQpLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFrZVVudGlsKGt0ZE1vdXNlT3JUb3VjaEVuZChkb2N1bWVudCwgMSkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGt0ZE91dHNpZGVab25lKHRoaXMubmdab25lKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXIoKG1vdmVFdmVudCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb3ZlRXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbW92ZVBvaW50ZXIgPSBrdGRQb2ludGVyQ2xpZW50KG1vdmVFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRpc3RhbmNlWCA9IE1hdGguYWJzKHN0YXJ0UG9pbnRlci5jbGllbnRYIC0gbW92ZVBvaW50ZXIuY2xpZW50WCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRpc3RhbmNlWSA9IE1hdGguYWJzKHN0YXJ0UG9pbnRlci5jbGllbnRZIC0gbW92ZVBvaW50ZXIuY2xpZW50WSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdoZW4gdGhpcyBjb25kaXRpb25zIHJldHVybnMgdHJ1ZSBtZWFuIHRoYXQgd2UgYXJlIG92ZXIgdGhyZXNob2xkLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGlzdGFuY2VYICsgZGlzdGFuY2VZID49IHRoaXMuZHJhZ1N0YXJ0VGhyZXNob2xkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRha2UoMSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmV0dXJuIHRoZSBvcmlnaW5hbCBzdGFydCBldmVudFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcCgoKSA9PiBzdGFydEV2ZW50KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgX3Jlc2l6ZVN0YXJ0JCgpOiBPYnNlcnZhYmxlPE1vdXNlRXZlbnQgfCBUb3VjaEV2ZW50PiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9yZXNpemFibGUkLnBpcGUoXG4gICAgICAgICAgICBzd2l0Y2hNYXAoKHJlc2l6YWJsZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghcmVzaXphYmxlKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFNpZGUgZWZmZWN0IHRvIGhpZGUgdGhlIHJlc2l6ZUVsZW0gaWYgcmVzaXplIGlzIGRpc2FibGVkLlxuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKHRoaXMucmVzaXplRWxlbS5uYXRpdmVFbGVtZW50LCAnZGlzcGxheScsICdub25lJyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBORVZFUjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fcmVzaXplSGFuZGxlcy5jaGFuZ2VzLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICBzdGFydFdpdGgodGhpcy5fcmVzaXplSGFuZGxlcyksXG4gICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2hNYXAoKHJlc2l6ZUhhbmRsZXM6IFF1ZXJ5TGlzdDxLdGRHcmlkUmVzaXplSGFuZGxlPikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXNpemVIYW5kbGVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2lkZSBlZmZlY3QgdG8gaGlkZSB0aGUgcmVzaXplRWxlbSBpZiB0aGVyZSBhcmUgcmVzaXplIGhhbmRsZXMuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5yZXNpemVFbGVtLm5hdGl2ZUVsZW1lbnQsICdkaXNwbGF5JywgJ25vbmUnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1lcmdlKC4uLnJlc2l6ZUhhbmRsZXMudG9BcnJheSgpLm1hcChyZXNpemVIYW5kbGUgPT4ga3RkTW91c2VPclRvdWNoRG93bihyZXNpemVIYW5kbGUuZWxlbWVudC5uYXRpdmVFbGVtZW50LCAxKSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUodGhpcy5yZXNpemVFbGVtLm5hdGl2ZUVsZW1lbnQsICdkaXNwbGF5JywgJ2Jsb2NrJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBrdGRNb3VzZU9yVG91Y2hEb3duKHRoaXMucmVzaXplRWxlbS5uYXRpdmVFbGVtZW50LCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgfVxuXG5cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmVcbiAgICBzdGF0aWMgbmdBY2NlcHRJbnB1dFR5cGVfZHJhZ2dhYmxlOiBCb29sZWFuSW5wdXQ7XG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lXG4gICAgc3RhdGljIG5nQWNjZXB0SW5wdXRUeXBlX3Jlc2l6YWJsZTogQm9vbGVhbklucHV0O1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZVxuICAgIHN0YXRpYyBuZ0FjY2VwdElucHV0VHlwZV9kcmFnU3RhcnRUaHJlc2hvbGQ6IE51bWJlcklucHV0O1xuXG59XG4iXX0=