UNPKG

ngx-flip-card

Version:

Angular component to animate a double-sided card.

206 lines 29.5 kB
import { Component, EventEmitter, Input, Output } from '@angular/core'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; export class NgxFlipCardComponent { constructor() { this._isBackSide = false; this.isBackSideChange = new EventEmitter(); this.animate = true; this.animationDuration = 2500; this.animationEnd = new EventEmitter(); this.canAnimate = false; this.frontRotation = 0; this.backRotation = 180; this.desiredFrontRotation = 0; this.frontZindex = 1; this.backZindex = 0; this.translationZ = 2; this.currentTranslationZ = 0; this.easing = 'linear'; this.direction = 'horizontal'; this.flipOnClick = true; this.timeLastFrame = Date.now(); this.currentAnimationTime = 0; this.animating = false; } set isBackSide(value) { if (value === this._isBackSide) { return; } this._isBackSide = value; this.isBackSideChange.emit(this._isBackSide); this.flipInternal(); } get isBackSide() { return this._isBackSide; } ngOnInit() { } ngAfterViewInit() { this.canAnimate = true; } flipInternal() { this.rotateAction(); } clickHandler() { if (this.flipOnClick) { this.flipCard(); } } flipCard() { this.isBackSide = !this._isBackSide; } rotateAction() { if (!this.animate || !this.canAnimate) { this.rotateFlat(); } else { this.animateRotationStart(); } } rotateFlat() { if (this.isBackSide) { this.frontRotation = 180; this.backRotation = 0; this.frontZindex = 0; this.backZindex = 1; } else { this.frontRotation = 0; this.backRotation = 180; this.frontZindex = 1; this.backZindex = 0; } } animateRotationStart() { this.desiredFrontRotation = this.isBackSide ? 180 : 0; this.timeLastFrame = Date.now(); if (this.animating) { this.currentAnimationTime = this.calculateReverseEasing(); } else { this.currentAnimationTime = 0; } if (this.animationFrameRef) { cancelAnimationFrame(this.animationFrameRef); } this.animationFrameRef = requestAnimationFrame(this.animateLoop.bind(this)); this.animating = true; this.currentTranslationZ = this.translationZ; } animateLoop() { const time = Date.now(); const deltatime = time - this.timeLastFrame; this.timeLastFrame = time; this.currentAnimationTime += deltatime; const amount = this.currentAnimationTime / this.animationDuration; switch (this.easing) { case 'linear': this.frontRotation = this.isBackSide ? Math.min(this.lerp(0, this.desiredFrontRotation, amount), this.desiredFrontRotation) : Math.max(this.lerp(180, this.desiredFrontRotation, amount), this.desiredFrontRotation); break; case 'easeIn': this.frontRotation = this.isBackSide ? Math.min(this.easeIn(0, this.desiredFrontRotation, amount), this.desiredFrontRotation) : Math.max(this.easeIn(180, this.desiredFrontRotation, amount), this.desiredFrontRotation); break; case 'easeOut': this.frontRotation = this.isBackSide ? Math.min(this.easeOut(0, this.desiredFrontRotation, amount), this.desiredFrontRotation) : Math.max(this.easeOut(180, this.desiredFrontRotation, amount), this.desiredFrontRotation); break; case 'easeInOut': this.frontRotation = this.isBackSide ? Math.min(this.easeInOut(0, this.desiredFrontRotation, amount), this.desiredFrontRotation) : Math.max(this.easeInOut(180, this.desiredFrontRotation, amount), this.desiredFrontRotation); break; } if (this.currentAnimationTime >= this.animationDuration) { this.frontRotation = this.desiredFrontRotation; } this.backRotation = this.frontRotation + 180; if (this.isBackSide && this.frontRotation >= 90) { this.frontZindex = 0; this.backZindex = 1; } else if (!this.isBackSide && this.frontRotation <= 90) { this.frontZindex = 1; this.backZindex = 0; } if (this.frontRotation === this.desiredFrontRotation) { this.animationEnded(); return; } this.animationFrameRef = requestAnimationFrame(this.animateLoop.bind(this)); } lerp(a, b, n) { return (1 - n) * a + n * b; } easeIn(a, b, n) { return this.lerp(a, b, n * n); } easeOut(a, b, n) { return this.lerp(a, b, 1 - (1 - n) * (1 - n)); } easeInOut(a, b, n) { return this.lerp(a, b, n < 0.5 ? 2 * n * n : 1 - Math.pow(-2 * n + 2, 2) / 2); } calculateReverseEasing() { if (this.easing === 'linear') { return this.animationDuration - this.currentAnimationTime; } const start = this._isBackSide ? 0 : 180; const end = this._isBackSide ? 180 : 0; // increment 16 milliseconds to simulate animation at 60FPS for (let i = 0; i < this.animationDuration; i += 16) { let inverseValue = 0; switch (this.easing) { case 'easeIn': inverseValue = this.easeIn(start, end, i / this.animationDuration); break; case 'easeOut': inverseValue = this.easeOut(start, end, i / this.animationDuration); break; case 'easeInOut': inverseValue = this.easeInOut(start, end, i / this.animationDuration); break; } if ((this._isBackSide && inverseValue >= this.frontRotation) || (!this._isBackSide && inverseValue <= this.frontRotation)) { return i; } } return 0; } animationEnded() { this.animationEnd.emit(this.isBackSide); this.animating = false; this.currentTranslationZ = 0; } } NgxFlipCardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxFlipCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); NgxFlipCardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: NgxFlipCardComponent, selector: "ngx-flip-card", inputs: { isBackSide: "isBackSide", animate: "animate", animationDuration: "animationDuration", translationZ: "translationZ", easing: "easing", direction: "direction", flipOnClick: "flipOnClick" }, outputs: { isBackSideChange: "isBackSideChange", animationEnd: "animationEnd" }, ngImport: i0, template: "<div class=\"card-container\" (click)=\"clickHandler()\">\n <div class=\"card-side\"\n [ngStyle]=\"{ 'transform': (direction === 'horizontal' ? 'rotateY(' + frontRotation + 'deg)' : 'rotateX(' + frontRotation + 'deg)') + ' translateZ(' + currentTranslationZ + 'px )', 'z-index': frontZindex }\">\n <ng-content select=\"[card-front]\"></ng-content>\n </div>\n <div class=\"card-side\" \n [ngStyle]=\"{ 'transform': (direction === 'horizontal' ? 'rotateY(' + backRotation + 'deg)' : 'rotateX(' + backRotation + 'deg)') + ' translateZ(' + currentTranslationZ + 'px )', 'z-index': backZindex }\">\n <ng-content select=\"[card-back]\"></ng-content>\n </div>\n</div>\n", styles: [".card-container{display:grid;grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(3,1fr);position:relative;perspective:500px;width:-moz-fit-content;width:fit-content}.card-side{grid-row:1 / -1;grid-column:1 / -1;transform-origin:center}\n"], directives: [{ type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: NgxFlipCardComponent, decorators: [{ type: Component, args: [{ selector: 'ngx-flip-card', template: "<div class=\"card-container\" (click)=\"clickHandler()\">\n <div class=\"card-side\"\n [ngStyle]=\"{ 'transform': (direction === 'horizontal' ? 'rotateY(' + frontRotation + 'deg)' : 'rotateX(' + frontRotation + 'deg)') + ' translateZ(' + currentTranslationZ + 'px )', 'z-index': frontZindex }\">\n <ng-content select=\"[card-front]\"></ng-content>\n </div>\n <div class=\"card-side\" \n [ngStyle]=\"{ 'transform': (direction === 'horizontal' ? 'rotateY(' + backRotation + 'deg)' : 'rotateX(' + backRotation + 'deg)') + ' translateZ(' + currentTranslationZ + 'px )', 'z-index': backZindex }\">\n <ng-content select=\"[card-back]\"></ng-content>\n </div>\n</div>\n", styles: [".card-container{display:grid;grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(3,1fr);position:relative;perspective:500px;width:-moz-fit-content;width:fit-content}.card-side{grid-row:1 / -1;grid-column:1 / -1;transform-origin:center}\n"] }] }], ctorParameters: function () { return []; }, propDecorators: { isBackSide: [{ type: Input }], isBackSideChange: [{ type: Output }], animate: [{ type: Input }], animationDuration: [{ type: Input }], animationEnd: [{ type: Output }], translationZ: [{ type: Input }], easing: [{ type: Input }], direction: [{ type: Input }], flipOnClick: [{ type: Input }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWZsaXAtY2FyZC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZmxpcC1jYXJkL3NyYy9saWIvbmd4LWZsaXAtY2FyZC9uZ3gtZmxpcC1jYXJkLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1mbGlwLWNhcmQvc3JjL2xpYi9uZ3gtZmxpcC1jYXJkL25neC1mbGlwLWNhcmQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFpQixTQUFTLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBVSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7OztBQU85RixNQUFNLE9BQU8sb0JBQW9CO0lBa0QvQjtRQWhEUSxnQkFBVyxHQUFZLEtBQUssQ0FBQztRQWdCM0IscUJBQWdCLEdBQUcsSUFBSSxZQUFZLEVBQVcsQ0FBQztRQUVoRCxZQUFPLEdBQVksSUFBSSxDQUFDO1FBRXhCLHNCQUFpQixHQUFXLElBQUksQ0FBQztRQUVoQyxpQkFBWSxHQUFHLElBQUksWUFBWSxFQUFXLENBQUM7UUFFN0MsZUFBVSxHQUFZLEtBQUssQ0FBQztRQUVwQyxrQkFBYSxHQUFXLENBQUMsQ0FBQztRQUMxQixpQkFBWSxHQUFXLEdBQUcsQ0FBQztRQUVuQix5QkFBb0IsR0FBVyxDQUFDLENBQUM7UUFFekMsZ0JBQVcsR0FBVyxDQUFDLENBQUM7UUFDeEIsZUFBVSxHQUFXLENBQUMsQ0FBQztRQUVkLGlCQUFZLEdBQVcsQ0FBQyxDQUFDO1FBQ2xDLHdCQUFtQixHQUFXLENBQUMsQ0FBQztRQUV2QixXQUFNLEdBQWlCLFFBQVEsQ0FBQztRQUVoQyxjQUFTLEdBQXNCLFlBQVksQ0FBQztRQUU1QyxnQkFBVyxHQUFZLElBQUksQ0FBQztRQUU3QixrQkFBYSxHQUFXLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNuQyx5QkFBb0IsR0FBVyxDQUFD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LE1BQU07YUFDVDtZQUVELElBQUcsQ0FBQyxJQUFJLENBQUMsV0FBVyxJQUFJLFlBQVksSUFBSSxJQUFJLENBQUMsYUFBYSxDQUFDO2dCQUNyRCxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsSUFBSSxZQUFZLElBQUksSUFBSSxDQUFDLGFBQWEsQ0FBQyxFQUFDO2dCQUM5RCxPQUFPLENBQUMsQ0FBQzthQUNWO1NBQ0Y7UUFFRCxPQUFPLENBQUMsQ0FBQztJQUNYLENBQUM7SUFFTyxjQUFjO1FBQ3BCLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUN4QyxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztRQUN2QixJQUFJLENBQUMsbUJBQW1CLEdBQUcsQ0FBQyxDQUFDO0lBQy9CLENBQUM7O2tIQXpOVSxvQkFBb0I7c0dBQXBCLG9CQUFvQiw0VUNQakMsaXNCQVVBOzRGREhhLG9CQUFvQjtrQkFMaEMsU0FBUzsrQkFDRSxlQUFlOzBFQVFyQixVQUFVO3NCQURiLEtBQUs7Z0JBZUksZ0JBQWdCO3NCQUF6QixNQUFNO2dCQUVFLE9BQU87c0JBQWYsS0FBSztnQkFFRyxpQkFBaUI7c0JBQXpCLEtBQUs7Z0JBRUksWUFBWTtzQkFBckIsTUFBTTtnQkFZRSxZQUFZO3NCQUFwQixLQUFLO2dCQUdHLE1BQU07c0JBQWQsS0FBSztnQkFFRyxTQUFTO3NCQUFqQixLQUFLO2dCQUVHLFdBQVc7c0JBQW5CLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBZnRlclZpZXdJbml0LCBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE9uSW5pdCwgT3V0cHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1mbGlwLWNhcmQnLFxuICB0ZW1wbGF0ZVVybDogJy4vbmd4LWZsaXAtY2FyZC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL25neC1mbGlwLWNhcmQuY29tcG9uZW50LmNzcyddXG59KVxuZXhwb3J0IGNsYXNzIE5neEZsaXBDYXJkQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdJbml0IHtcblxuICBwcml2YXRlIF9pc0JhY2tTaWRlOiBib29sZWFuID0gZmFsc2U7XG4gIEBJbnB1dCgpXG4gIHNldCBpc0JhY2tTaWRlKHZhbHVlOiBib29sZWFuKSB7XG4gICAgaWYodmFsdWUgPT09IHRoaXMuX2lzQmFja1NpZGUpe1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuX2lzQmFja1NpZGUgPSB2YWx1ZTtcbiAgICB0aGlzLmlzQmFja1NpZGVDaGFuZ2UuZW1pdCh0aGlzLl9pc0JhY2tTaWRlKTtcbiAgICB0aGlzLmZsaXBJbnRlcm5hbCgpO1xuICB9XG5cbiAgZ2V0IGlzQmFja1NpZGUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX2lzQmFja1NpZGU7XG4gIH1cblxuICBAT3V0cHV0KCkgaXNCYWNrU2lkZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4oKTtcblxuICBASW5wdXQoKSBhbmltYXRlOiBib29sZWFuID0gdHJ1ZTtcblxuICBASW5wdXQoKSBhbmltYXRpb25EdXJhdGlvbjogbnVtYmVyID0gMjUwMDtcblxuICBAT3V0cHV0KCkgYW5pbWF0aW9uRW5kID0gbmV3IEV2ZW50RW1pdHRlcjxib29sZWFuPigpO1xuXG4gIHByaXZhdGUgY2FuQW5pbWF0ZTogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIGZyb250Um90YXRpb246IG51bWJlciA9IDA7XG4gIGJhY2tSb3RhdGlvbjogbnVtYmVyID0gMTgwO1xuXG4gIHByaXZhdGUgZGVzaXJlZEZyb250Um90YXRpb246IG51bWJlciA9IDA7XG5cbiAgZnJvbnRaaW5kZXg6IG51bWJlciA9IDE7XG4gIGJhY2taaW5kZXg6IG51bWJlciA9IDA7XG5cbiAgQElucHV0KCkgdHJhbnNsYXRpb25aOiBudW1iZXIgPSAyO1xuICBjdXJyZW50VHJhbnNsYXRpb25aOiBudW1iZXIgPSAwO1xuXG4gIEBJbnB1dCgpIGVhc2luZzogRmxpcENhcmRFYXNlID0gJ2xpbmVhcic7XG5cbiAgQElucHV0KCkgZGlyZWN0aW9uOiBGbGlwQ2FyZERpcmVjdGlvbiA9ICdob3Jpem9udGFsJztcblxuICBASW5wdXQoKSBmbGlwT25DbGljazogYm9vbGVhbiA9IHRydWU7XG5cbiAgcHJpdmF0ZSB0aW1lTGFzdEZyYW1lOiBudW1iZXIgPSBEYXRlLm5vdygpO1xuICBwcml2YXRlIGN1cnJlbnRBbmltYXRpb25UaW1lOiBudW1iZXIgPSAwO1xuICBwcml2YXRlIGFuaW1hdGlvbkZyYW1lUmVmOiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgYW5pbWF0aW5nOiBib29sZWFuID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IoKSB7IH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLmNhbkFuaW1hdGUgPSB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBmbGlwSW50ZXJuYWwoKXtcbiAgICB0aGlzLnJvdGF0ZUFjdGlvbigpO1xuICB9XG5cbiAgY2xpY2tIYW5kbGVyKCkge1xuICAgIGlmKHRoaXMuZmxpcE9uQ2xpY2spe1xuICAgICAgdGhpcy5mbGlwQ2FyZCgpO1xuICAgIH1cbiAgfVxuXG4gIGZsaXBDYXJkKCkge1xuICAgIHRoaXMuaXNCYWNrU2lkZSA9ICF0aGlzLl9pc0JhY2tTaWRlO1xuICB9XG5cbiAgcHJpdmF0ZSByb3RhdGVBY3Rpb24oKXtcbiAgICBpZighdGhpcy5hbmltYXRlIHx8ICF0aGlzLmNhbkFuaW1hdGUpe1xuICAgICAgdGhpcy5yb3RhdGVGbGF0KCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuYW5pbWF0ZVJvdGF0aW9uU3RhcnQoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJvdGF0ZUZsYXQoKXtcbiAgICBpZih0aGlzLmlzQmFja1NpZGUpe1xuICAgICAgdGhpcy5mcm9udFJvdGF0aW9uID0gMTgwO1xuICAgICAgdGhpcy5iYWNrUm90YXRpb24gPSAwO1xuICAgICAgdGhpcy5mcm9udFppbmRleCA9IDA7XG4gICAgICB0aGlzLmJhY2taaW5kZXggPSAxO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmZyb250Um90YXRpb24gPSAwO1xuICAgICAgdGhpcy5iYWNrUm90YXRpb24gPSAxODA7XG4gICAgICB0aGlzLmZyb250WmluZGV4ID0gMTtcbiAgICAgIHRoaXMuYmFja1ppbmRleCA9IDA7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhbmltYXRlUm90YXRpb25TdGFydCgpe1xuICAgIHRoaXMuZGVzaXJlZEZyb250Um90YXRpb24gPSB0aGlzLmlzQmFja1NpZGUgPyAxODAgOiAwO1xuICAgIHRoaXMudGltZUxhc3RGcmFtZSA9IERhdGUubm93KCk7XG5cbiAgICBpZih0aGlzLmFuaW1hdGluZyl7XG4gICAgICB0aGlzLmN1cnJlbnRBbmltYXRpb25UaW1lID0gdGhpcy5jYWxjdWxhdGVSZXZlcnNlRWFzaW5nKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuY3VycmVudEFuaW1hdGlvblRpbWUgPSAwO1xuICAgIH1cblxuICAgIGlmKHRoaXMuYW5pbWF0aW9uRnJhbWVSZWYpe1xuICAgICAgY2FuY2VsQW5pbWF0aW9uRnJhbWUodGhpcy5hbmltYXRpb25GcmFtZVJlZik7XG4gICAgfVxuICAgIHRoaXMuYW5pbWF0aW9uRnJhbWVSZWYgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUodGhpcy5hbmltYXRlTG9vcC5iaW5kKHRoaXMpKTtcbiAgICB0aGlzLmFuaW1hdGluZyA9IHRydWU7XG4gICAgdGhpcy5jdXJyZW50VHJhbnNsYXRpb25aID0gdGhpcy50cmFuc2xhdGlvblo7XG4gIH1cblxuICBwcml2YXRlIGFuaW1hdGVMb29wKCl7XG4gICAgY29uc3QgdGltZSA9IERhdGUubm93KCk7XG4gICAgY29uc3QgZGVsdGF0aW1lID0gdGltZSAtIHRoaXMudGltZUxhc3RGcmFtZTtcbiAgICB0aGlzLnRpbWVMYXN0RnJhbWUgPSB0aW1lO1xuICAgIHRoaXMuY3VycmVudEFuaW1hdGlvblRpbWUgKz0gZGVsdGF0aW1lO1xuICAgIGNvbnN0IGFtb3VudCA9IHRoaXMuY3VycmVudEFuaW1hdGlvblRpbWUgLyB0aGlzLmFuaW1hdGlvbkR1cmF0aW9uO1xuXG4gICAgc3dpdGNoKHRoaXMuZWFzaW5nKXtcbiAgICAgIGNhc2UgJ2xpbmVhcic6XG4gICAgICAgIHRoaXMuZnJvbnRSb3RhdGlvbiA9IHRoaXMuaXNCYWNrU2lkZSA/XG4gICAgICAgICAgTWF0aC5taW4odGhpcy5sZXJwKDAsIHRoaXMuZGVzaXJlZEZyb250Um90YXRpb24sIGFtb3VudCksIHRoaXMuZGVzaXJlZEZyb250Um90YXRpb24pIDpcbiAgICAgICAgICBNYXRoLm1heCh0aGlzLmxlcnAoMTgwLCB0aGlzLmRlc2lyZWRGcm9udFJvdGF0aW9uLCBhbW91bnQpLCB0aGlzLmRlc2lyZWRGcm9udFJvdGF0aW9uKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdlYXNlSW4nOlxuICAgICAgICB0aGlzLmZyb250Um90YXRpb24gPSB0aGlzLmlzQmFja1NpZGUgP1xuICAgICAgICAgIE1hdGgubWluKHRoaXMuZWFzZUluKDAsIHRoaXMuZGVzaXJlZEZyb250Um90YXRpb24sIGFtb3VudCksIHRoaXMuZGVzaXJlZEZyb250Um90YXRpb24pIDpcbiAgICAgICAgICBNYXRoLm1heCh0aGlzLmVhc2VJbigxODAsIHRoaXMuZGVzaXJlZEZyb250Um90YXRpb24sIGFtb3VudCksIHRoaXMuZGVzaXJlZEZyb250Um90YXRpb24pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2Vhc2VPdXQnOlxuICAgICAgICB0aGlzLmZyb250Um90YXRpb24gPSB0aGlzLmlzQmFja1NpZGUgP1xuICAgICAgICAgIE1hdGgubWluKHRoaXMuZWFzZU91dCgwLCB0aGlzLmRlc2lyZWRGcm9udFJvdGF0aW9uLCBhbW91bnQpLCB0aGlzLmRlc2lyZWRGcm9udFJvdGF0aW9uKSA6XG4gICAgICAgICAgTWF0aC5tYXgodGhpcy5lYXNlT3V0KDE4MCwgdGhpcy5kZXNpcmVkRnJvbnRSb3RhdGlvbiwgYW1vdW50KSwgdGhpcy5kZXNpcmVkRnJvbnRSb3RhdGlvbik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnZWFzZUluT3V0JzpcbiAgICAgICAgdGhpcy5mcm9udFJvdGF0aW9uID0gdGhpcy5pc0JhY2tTaWRlID9cbiAgICAgICAgICBNYXRoLm1pbih0aGlzLmVhc2VJbk91dCgwLCB0aGlzLmRlc2lyZWRGcm9udFJvdGF0aW9uLCBhbW91bnQpLCB0aGlzLmRlc2lyZWRGcm9udFJvdGF0aW9uKSA6XG4gICAgICAgICAgTWF0aC5tYXgodGhpcy5lYXNlSW5PdXQoMTgwLCB0aGlzLmRlc2lyZWRGcm9udFJvdGF0aW9uLCBhbW91bnQpLCB0aGlzLmRlc2lyZWRGcm9udFJvdGF0aW9uKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgaWYodGhpcy5jdXJyZW50QW5pbWF0aW9uVGltZSA+PSB0aGlzLmFuaW1hdGlvbkR1cmF0aW9uKXtcbiAgICAgIHRoaXMuZnJvbnRSb3RhdGlvbiA9IHRoaXMuZGVzaXJlZEZyb250Um90YXRpb247XG4gICAgfVxuXG4gICAgdGhpcy5iYWNrUm90YXRpb24gPSB0aGlzLmZyb250Um90YXRpb24gKyAxODA7XG5cbiAgICBpZih0aGlzLmlzQmFja1NpZGUgJiYgdGhpcy5mcm9udFJvdGF0aW9uID49IDkwKXtcbiAgICAgIHRoaXMuZnJvbnRaaW5kZXggPSAwO1xuICAgICAgdGhpcy5iYWNrWmluZGV4ID0gMTtcbiAgICB9IGVsc2UgaWYoIXRoaXMuaXNCYWNrU2lkZSAmJiB0aGlzLmZyb250Um90YXRpb24gPD0gOTApIHtcbiAgICAgIHRoaXMuZnJvbnRaaW5kZXggPSAxO1xuICAgICAgdGhpcy5iYWNrWmluZGV4ID0gMDtcbiAgICB9XG5cbiAgICBpZih0aGlzLmZyb250Um90YXRpb24gPT09IHRoaXMuZGVzaXJlZEZyb250Um90YXRpb24pe1xuICAgICAgdGhpcy5hbmltYXRpb25FbmRlZCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuYW5pbWF0aW9uRnJhbWVSZWYgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUodGhpcy5hbmltYXRlTG9vcC5iaW5kKHRoaXMpKTtcbiAgfVxuXG4gIHByaXZhdGUgbGVycChhOiBudW1iZXIsIGI6IG51bWJlciwgbjogbnVtYmVyKSB7XG4gICAgcmV0dXJuICgxIC0gbikgKiBhICsgbiAqIGI7XG4gIH1cblxuICBwcml2YXRlIGVhc2VJbihhOiBudW1iZXIsIGI6IG51bWJlciwgbjogbnVtYmVyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5sZXJwKGEsIGIsIG4gKiBuKTtcbiAgfVxuXG4gIHByaXZhdGUgZWFzZU91dChhOiBudW1iZXIsIGI6IG51bWJlciwgbjogbnVtYmVyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5sZXJwKGEsIGIsIDEgLSAoMSAtIG4pICogKDEgLSBuKSk7XG4gIH1cblxuICBwcml2YXRlIGVhc2VJbk91dChhOiBudW1iZXIsIGI6IG51bWJlciwgbjogbnVtYmVyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5sZXJwKGEsIGIsIG4gPCAwLjUgPyAyICogbiAqIG4gOiAxIC0gTWF0aC5wb3coLTIgKiBuICsgMiwgMikgLyAyKTtcbiAgfVxuXG4gIHByaXZhdGUgY2FsY3VsYXRlUmV2ZXJzZUVhc2luZygpOiBudW1iZXJ7XG4gICAgaWYodGhpcy5lYXNpbmcgPT09ICdsaW5lYXInKXtcbiAgICAgIHJldHVybiB0aGlzLmFuaW1hdGlvbkR1cmF0aW9uIC0gdGhpcy5jdXJyZW50QW5pbWF0aW9uVGltZTtcbiAgICB9XG5cbiAgICBjb25zdCBzdGFydCA9IHRoaXMuX2lzQmFja1NpZGUgPyAwIDogMTgwO1xuICAgIGNvbnN0IGVuZCA9IHRoaXMuX2lzQmFja1NpZGUgPyAxODAgOiAwO1xuXG4gICAgLy8gaW5jcmVtZW50IDE2IG1pbGxpc2Vjb25kcyB0byBzaW11bGF0ZSBhbmltYXRpb24gYXQgNjBGUFNcbiAgICBmb3IobGV0IGkgPSAwOyBpIDwgdGhpcy5hbmltYXRpb25EdXJhdGlvbjsgaSArPSAxNil7XG4gICAgICBsZXQgaW52ZXJzZVZhbHVlID0gMDtcbiAgICAgIHN3aXRjaCh0aGlzLmVhc2luZyl7XG4gICAgICAgIGNhc2UgJ2Vhc2VJbic6XG4gICAgICAgICAgaW52ZXJzZVZhbHVlID0gdGhpcy5lYXNlSW4oc3RhcnQsIGVuZCwgaSAvIHRoaXMuYW5pbWF0aW9uRHVyYXRpb24pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdlYXNlT3V0JzpcbiAgICAgICAgICBpbnZlcnNlVmFsdWUgPSB0aGlzLmVhc2VPdXQoc3RhcnQsIGVuZCwgaSAvIHRoaXMuYW5pbWF0aW9uRHVyYXRpb24pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdlYXNlSW5PdXQnOlxuICAgICAgICAgIGludmVyc2VWYWx1ZSA9IHRoaXMuZWFzZUluT3V0KHN0YXJ0LCBlbmQsIGkgLyB0aGlzLmFuaW1hdGlvbkR1cmF0aW9uKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgaWYoKHRoaXMuX2lzQmFja1NpZGUgJiYgaW52ZXJzZVZhbHVlID49IHRoaXMuZnJvbnRSb3RhdGlvbikgfHxcbiAgICAgICAgICAgICghdGhpcy5faXNCYWNrU2lkZSAmJiBpbnZlcnNlVmFsdWUgPD0gdGhpcy5mcm9udFJvdGF0aW9uKSl7XG4gICAgICAgIHJldHVybiBpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiAwO1xuICB9XG5cbiAgcHJpdmF0ZSBhbmltYXRpb25FbmRlZCgpe1xuICAgIHRoaXMuYW5pbWF0aW9uRW5kLmVtaXQodGhpcy5pc0JhY2tTaWRlKTtcbiAgICB0aGlzLmFuaW1hdGluZyA9IGZhbHNlO1xuICAgIHRoaXMuY3VycmVudFRyYW5zbGF0aW9uWiA9IDA7XG4gIH1cblxufVxuXG5leHBvcnQgdHlwZSBGbGlwQ2FyZEVhc2UgPSAnbGluZWFyJyB8ICdlYXNlSW4nIHwgJ2Vhc2VPdXQnIHwgJ2Vhc2VJbk91dCc7XG5cbmV4cG9ydCB0eXBlIEZsaXBDYXJkRGlyZWN0aW9uID0gJ2hvcml6b250YWwnIHwgJ3ZlcnRpY2FsJztcbiIsIjxkaXYgY2xhc3M9XCJjYXJkLWNvbnRhaW5lclwiIChjbGljayk9XCJjbGlja0hhbmRsZXIoKVwiPlxuICAgIDxkaXYgY2xhc3M9XCJjYXJkLXNpZGVcIlxuICAgICAgICBbbmdTdHlsZV09XCJ7ICd0cmFuc2Zvcm0nOiAoZGlyZWN0aW9uID09PSAnaG9yaXpvbnRhbCcgPyAncm90YXRlWSgnICsgZnJvbnRSb3RhdGlvbiArICdkZWcpJyA6ICdyb3RhdGVYKCcgKyBmcm9udFJvdGF0aW9uICsgJ2RlZyknKSArICAnIHRyYW5zbGF0ZVooJyArIGN1cnJlbnRUcmFuc2xhdGlvblogKyAncHggKScsICd6LWluZGV4JzogZnJvbnRaaW5kZXggfVwiPlxuICAgICAgICA8bmctY29udGVudCBzZWxlY3Q9XCJbY2FyZC1mcm9udF1cIj48L25nLWNvbnRlbnQ+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImNhcmQtc2lkZVwiIFxuICAgICAgICBbbmdTdHlsZV09XCJ7ICd0cmFuc2Zvcm0nOiAoZGlyZWN0aW9uID09PSAnaG9yaXpvbnRhbCcgPyAncm90YXRlWSgnICsgYmFja1JvdGF0aW9uICsgJ2RlZyknIDogJ3JvdGF0ZVgoJyArIGJhY2tSb3RhdGlvbiArICdkZWcpJykgKyAnIHRyYW5zbGF0ZVooJyArIGN1cnJlbnRUcmFuc2xhdGlvblogKyAncHggKScsICd6LWluZGV4JzogYmFja1ppbmRleCB9XCI+XG4gICAgICAgIDxuZy1jb250ZW50IHNlbGVjdD1cIltjYXJkLWJhY2tdXCI+PC9uZy1jb250ZW50PlxuICAgIDwvZGl2PlxuPC9kaXY+XG4iXX0=