ngx-flip-card
Version:
Angular component to animate a double-sided card.
206 lines • 29.5 kB
JavaScript
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=