ngx-select-angle
Version:
A component for selecting an angle between 0 and 360 degrees in the Angular framework
173 lines • 22.3 kB
JavaScript
import { Component, HostListener, Input, ViewChild, forwardRef, } from '@angular/core';
import { FormControl, NG_VALIDATORS, NG_VALUE_ACCESSOR, Validators, } from '@angular/forms';
import * as i0 from "@angular/core";
import * as i1 from "./ngx-select-angle.service";
export class NgxSelectAngleComponent {
constructor(
// @Inject(DOCUMENT) private document: Document,
_selectAngleService, _renderer) {
this._selectAngleService = _selectAngleService;
this._renderer = _renderer;
this._size = 60;
this._color = '#1f2667';
this._strokeWidth = 2;
this._pointerWidth = 4;
this.isDisabled = false;
this.myControl = new FormControl([0, [Validators.min(0), Validators.max(360)]]);
this.position = { x: 0, y: 0 };
this.dragging = false;
this.tooltip = '';
this._onChange = (value) => { };
this._onTouched = () => { };
this._validatorOnChange = () => { };
}
set size(s) {
this._size = s ?? 60;
}
set strokeWidth(s) {
this._strokeWidth = s ?? 2;
}
set pointerWidth(s) {
this._pointerWidth = s ?? 4;
}
set color(s) {
this._color = s ?? '#1f2667';
}
writeValue(value) {
this.myControl.setValue(+value);
let deg = this.myControl.value;
let transform = 'translateZ(0px) rotate(' + deg + 'deg)';
this.tooltip = deg + '\xb0';
this._renderer.setStyle(this.pointer.nativeElement, 'transform', transform);
}
validate(control) {
return this.myControl.errors;
}
registerOnValidatorChange(fn) {
this._validatorOnChange = fn;
}
registerOnChange(fn) {
this._onChange = fn;
}
registerOnTouched(fn) {
this._onTouched = fn;
}
setDisabledState(disabled) {
this.isDisabled = disabled;
if (disabled)
this.myControl.disable();
else
this.myControl.enable();
}
ngOnInit() { }
/**
* End dragging
* on document mouse up
* @param ev mouse event | touch event
*/
onMouseUp(ev) {
this.dragging = false;
}
/**
* End dragging
* on document touch end
* @param ev mouse event | touch event
*/
onTouchEnd(ev) {
this.dragging = false;
}
/**
* Start dragging
* on mouse or touch down
* @param ev mouse event | touch event
*/
onMouseDown(ev) {
ev.preventDefault();
ev.stopPropagation();
this.position = this._selectAngleService.getOffsetPosition(ev, this.selectAngle.nativeElement);
this.dragging = true;
this.updateAngle();
}
/**
* Move
* on mouse or touch move
* @param ev mouse event | touch event
*/
onMouseMove(ev) {
if (!this.dragging) {
return;
}
ev.preventDefault();
ev.stopPropagation();
this.position = this._selectAngleService.getOffsetPosition(ev, this.selectAngle.nativeElement);
this.updateAngle();
}
/**
* get angle and update view
*/
updateAngle() {
let x2 = this.position.x;
let y2 = this.position.y;
let radians = Math.atan2(y2 - this._size / 2, x2 - this._size / 2);
let e = radians * (180 / Math.PI);
e = 90 + e;
e < 0 && (e = 360 + e);
e = Math.round(e);
let transform = 'translateZ(0px) rotate(' + e + 'deg)';
let deg = Math.round(e);
this.tooltip = deg + '\xb0';
this.myControl.setValue(deg);
// this.pointer.nativeElement.style.transform = transform;
this._renderer.setStyle(this.pointer.nativeElement, 'transform', transform);
this._onChange(deg);
}
}
NgxSelectAngleComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: NgxSelectAngleComponent, deps: [{ token: i1.NgxSelectAngleService }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
NgxSelectAngleComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.3", type: NgxSelectAngleComponent, selector: "ngx-select-angle", inputs: { size: "size", strokeWidth: "strokeWidth", pointerWidth: "pointerWidth", color: "color" }, host: { listeners: { "document:mouseup": "onMouseUp($event)", "document:touchend": "onTouchEnd($event)" } }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => NgxSelectAngleComponent),
multi: true,
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => NgxSelectAngleComponent),
multi: true,
},
], viewQueries: [{ propertyName: "selectAngle", first: true, predicate: ["selectAngle"], descendants: true, static: true }, { propertyName: "pointer", first: true, predicate: ["pointer"], descendants: true, static: true }], ngImport: i0, template: "<div\r\n #selectAngle\r\n class=\"select-angle\"\r\n [title]=\"tooltip\"\r\n (mousedown)=\"onMouseDown($event)\"\r\n (touchstart)=\"onMouseDown($event)\"\r\n (mousemove)=\"onMouseMove($event)\"\r\n (touchmove)=\"onMouseMove($event)\"\r\n [style.width.px]=\"_size\"\r\n [style.height.px]=\"_size\"\r\n [style.borderColor]=\"_color\"\r\n [style.borderWidth.px]=\"_strokeWidth\"\r\n>\r\n <div class=\"pointer-container\" #pointer [style.width.px]=\"_pointerWidth\">\r\n <div\r\n class=\"angle-pointer\"\r\n [style.width.px]=\"_pointerWidth\"\r\n [style.height.px]=\"_pointerWidth\"\r\n [style.background]=\"_color\"\r\n ></div>\r\n </div>\r\n</div>\r\n", styles: [".select-angle{border:2px #1f2667 solid;position:relative;display:flex;align-items:center;justify-content:center;border-radius:100%;width:60px;height:60px}.select-angle .pointer-container{position:relative;width:6px;height:100%;pointer-events:none}.select-angle .pointer-container .angle-pointer{position:absolute;width:6px;height:6px;top:2px;border-radius:100%;background:#1f2667}\n"] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: NgxSelectAngleComponent, decorators: [{
type: Component,
args: [{ selector: 'ngx-select-angle', providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => NgxSelectAngleComponent),
multi: true,
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => NgxSelectAngleComponent),
multi: true,
},
], template: "<div\r\n #selectAngle\r\n class=\"select-angle\"\r\n [title]=\"tooltip\"\r\n (mousedown)=\"onMouseDown($event)\"\r\n (touchstart)=\"onMouseDown($event)\"\r\n (mousemove)=\"onMouseMove($event)\"\r\n (touchmove)=\"onMouseMove($event)\"\r\n [style.width.px]=\"_size\"\r\n [style.height.px]=\"_size\"\r\n [style.borderColor]=\"_color\"\r\n [style.borderWidth.px]=\"_strokeWidth\"\r\n>\r\n <div class=\"pointer-container\" #pointer [style.width.px]=\"_pointerWidth\">\r\n <div\r\n class=\"angle-pointer\"\r\n [style.width.px]=\"_pointerWidth\"\r\n [style.height.px]=\"_pointerWidth\"\r\n [style.background]=\"_color\"\r\n ></div>\r\n </div>\r\n</div>\r\n", styles: [".select-angle{border:2px #1f2667 solid;position:relative;display:flex;align-items:center;justify-content:center;border-radius:100%;width:60px;height:60px}.select-angle .pointer-container{position:relative;width:6px;height:100%;pointer-events:none}.select-angle .pointer-container .angle-pointer{position:absolute;width:6px;height:6px;top:2px;border-radius:100%;background:#1f2667}\n"] }]
}], ctorParameters: function () { return [{ type: i1.NgxSelectAngleService }, { type: i0.Renderer2 }]; }, propDecorators: { size: [{
type: Input
}], strokeWidth: [{
type: Input
}], pointerWidth: [{
type: Input
}], color: [{
type: Input
}], selectAngle: [{
type: ViewChild,
args: ['selectAngle', { static: true }]
}], pointer: [{
type: ViewChild,
args: ['pointer', { static: true }]
}], onMouseUp: [{
type: HostListener,
args: ['document:mouseup', ['$event']]
}], onTouchEnd: [{
type: HostListener,
args: ['document:touchend', ['$event']]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXNlbGVjdC1hbmdsZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtc2VsZWN0LWFuZ2xlL3NyYy9saWIvbmd4LXNlbGVjdC1hbmdsZS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtc2VsZWN0LWFuZ2xlL3NyYy9saWIvbmd4LXNlbGVjdC1hbmdsZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUVULFlBQVksRUFDWixLQUFLLEVBR0wsU0FBUyxFQUNULFVBQVUsR0FDWCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBR0wsV0FBVyxFQUNYLGFBQWEsRUFDYixpQkFBaUIsRUFHakIsVUFBVSxHQUNYLE1BQU0sZ0JBQWdCLENBQUM7OztBQW9CeEIsTUFBTSxPQUFPLHVCQUF1QjtJQWdDbEM7SUFDRSxpREFBaUQ7SUFDekMsbUJBQTBDLEVBQzFDLFNBQW9CO1FBRHBCLHdCQUFtQixHQUFuQixtQkFBbUIsQ0FBdUI7UUFDMUMsY0FBUyxHQUFULFNBQVMsQ0FBVztRQWhDOUIsVUFBSyxHQUFHLEVBQUUsQ0FBQztRQUNYLFdBQU0sR0FBRyxTQUFTLENBQUM7UUFDbkIsaUJBQVksR0FBRyxDQUFDLENBQUM7UUFDakIsa0JBQWEsR0FBRyxDQUFDLENBQUM7UUFhbEIsZUFBVSxHQUFHLEtBQUssQ0FBQztRQUNuQixjQUFTLEdBQUcsSUFBSSxXQUFXLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0UsYUFBUSxHQUFHLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7UUFDMUIsYUFBUSxHQUFHLEtBQUssQ0FBQztRQUNqQixZQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ2IsY0FBUyxHQUFHLENBQUMsS0FBVSxFQUFFLEVBQUUsR0FBRSxDQUFDLENBQUM7UUFDL0IsZUFBVSxHQUFHLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQztRQUN0Qix1QkFBa0IsR0FBRyxHQUFHLEVBQUUsR0FBRSxDQUFDLENBQUM7SUFVM0IsQ0FBQztJQTdCSixJQUFhLElBQUksQ0FBQyxDQUFTO1FBQ3pCLElBQUksQ0FBQyxLQUFLLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUN2QixDQUFDO0lBQ0QsSUFBYSxXQUFXLENBQUMsQ0FBUztRQUNoQyxJQUFJLENBQUMsWUFBWSxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDN0IsQ0FBQztJQUNELElBQWEsWUFBWSxDQUFDLENBQVM7UUFDakMsSUFBSSxDQUFDLGFBQWEsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzlCLENBQUM7SUFDRCxJQUFhLEtBQUssQ0FBQyxDQUFTO1FBQzFCLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLFNBQVMsQ0FBQztJQUMvQixDQUFDO0lBbUJELFVBQVUsQ0FBQyxLQUFVO1FBQ25CLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDaEMsSUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUM7UUFDL0IsSUFBSSxTQUFTLEdBQUcseUJBQXlCLEdBQUcsR0FBRyxHQUFHLE1BQU0sQ0FBQztRQUN6RCxJQUFJLENBQUMsT0FBTyxHQUFHLEdBQUcsR0FBRyxNQUFNLENBQUM7UUFDNUIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLEVBQUUsV0FBVyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQzlFLENBQUM7SUFFRCxRQUFRLENBQUMsT0FBd0I7UUFDL0IsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQztJQUMvQixDQUFDO0lBQ0QseUJBQXlCLENBQUUsRUFBYztRQUN2QyxJQUFJLENBQUMsa0JBQWtCLEdBQUcsRUFBRSxDQUFDO0lBQy9CLENBQUM7SUFFRCxnQkFBZ0IsQ0FBQyxFQUFPO1FBQ3RCLElBQUksQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDO0lBQ3RCLENBQUM7SUFDRCxpQkFBaUIsQ0FBQyxFQUFPO1FBQ3ZCLElBQUksQ0FBQyxVQUFVLEdBQUcsRUFBRSxDQUFDO0lBQ3ZCLENBQUM7SUFDRCxnQkFBZ0IsQ0FBRSxRQUFpQjtRQUNqQyxJQUFJLENBQUMsVUFBVSxHQUFHLFFBQVEsQ0FBQztRQUMzQixJQUFJLFFBQVE7WUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxDQUFDOztZQUNsQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQy9CLENBQUM7SUFFRCxRQUFRLEtBQVUsQ0FBQztJQUVuQjs7OztPQUlHO0lBRUgsU0FBUyxDQUFDLEVBQTJCO1FBQ25DLElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDO0lBQ3hCLENBQUM7SUFDRDs7OztPQUlHO0lBRUgsVUFBVSxDQUFDLEVBQTJCO1FBQ3BDLElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDO0lBQ3hCLENBQUM7SUFDRDs7OztPQUlHO0lBQ0gsV0FBVyxDQUFDLEVBQTJCO1FBQ3JDLEVBQUUsQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUNwQixFQUFFLENBQUMsZUFBZSxFQUFFLENBQUM7UUFDckIsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsaUJBQWlCLENBQ3hELEVBQUUsRUFDRixJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FDL0IsQ0FBQztRQUNGLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUNyQixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILFdBQVcsQ0FBQyxFQUEyQjtRQUNyQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRTtZQUNsQixPQUFPO1NBQ1I7UUFFRCxFQUFFLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDcEIsRUFBRSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixDQUFDLGlCQUFpQixDQUN4RCxFQUFFLEVBQ0YsSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQy9CLENBQUM7UUFDRixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7SUFDckIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsV0FBVztRQUNULElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1FBQ3pCLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1FBQ3pCLElBQUksT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxLQUFLLEdBQUcsQ0FBQyxFQUFFLEVBQUUsR0FBRyxJQUFJLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ25FLElBQUksQ0FBQyxHQUFHLE9BQU8sR0FBRyxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDbEMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDWCxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUN2QixDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNsQixJQUFJLFNBQVMsR0FBRyx5QkFBeUIsR0FBRyxDQUFDLEdBQUcsTUFBTSxDQUFDO1FBQ3ZELElBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDeEIsSUFBSSxDQUFDLE9BQU8sR0FBRyxHQUFHLEdBQUcsTUFBTSxDQUFDO1FBRTVCLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzdCLDBEQUEwRDtRQUMxRCxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsRUFBRSxXQUFXLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDNUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN0QixDQUFDOztvSEExSVUsdUJBQXVCO3dHQUF2Qix1QkFBdUIsNFBBYnZCO1FBQ1Q7WUFDRSxPQUFPLEVBQUUsaUJBQWlCO1lBQzFCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsdUJBQXVCLENBQUM7WUFDdEQsS0FBSyxFQUFFLElBQUk7U0FDWjtRQUNEO1lBQ0UsT0FBTyxFQUFFLGFBQWE7WUFDdEIsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyx1QkFBdUIsQ0FBQztZQUN0RCxLQUFLLEVBQUUsSUFBSTtTQUNaO0tBQ0YsdVBDckNILGtyQkFzQkE7MkZEaUJhLHVCQUF1QjtrQkFqQm5DLFNBQVM7K0JBQ0Usa0JBQWtCLGFBR2pCO3dCQUNUOzRCQUNFLE9BQU8sRUFBRSxpQkFBaUI7NEJBQzFCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLHdCQUF3QixDQUFDOzRCQUN0RCxLQUFLLEVBQUUsSUFBSTt5QkFDWjt3QkFDRDs0QkFDRSxPQUFPLEVBQUUsYUFBYTs0QkFDdEIsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsd0JBQXdCLENBQUM7NEJBQ3RELEtBQUssRUFBRSxJQUFJO3lCQUNaO3FCQUNGO29JQVNZLElBQUk7c0JBQWhCLEtBQUs7Z0JBR08sV0FBVztzQkFBdkIsS0FBSztnQkFHTyxZQUFZO3NCQUF4QixLQUFLO2dCQUdPLEtBQUs7c0JBQWpCLEtBQUs7Z0JBYU4sV0FBVztzQkFEVixTQUFTO3VCQUFDLGFBQWEsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBRzFDLE9BQU87c0JBRE4sU0FBUzt1QkFBQyxTQUFTLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQTBDdEMsU0FBUztzQkFEUixZQUFZO3VCQUFDLGtCQUFrQixFQUFFLENBQUMsUUFBUSxDQUFDO2dCQVU1QyxVQUFVO3NCQURULFlBQVk7dUJBQUMsbUJBQW1CLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb21wb25lbnQsXG4gIEVsZW1lbnRSZWYsXG4gIEhvc3RMaXN0ZW5lcixcbiAgSW5wdXQsXG4gIE9uSW5pdCxcbiAgUmVuZGVyZXIyLFxuICBWaWV3Q2hpbGQsXG4gIGZvcndhcmRSZWYsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgQWJzdHJhY3RDb250cm9sLFxuICBDb250cm9sVmFsdWVBY2Nlc3NvcixcbiAgRm9ybUNvbnRyb2wsXG4gIE5HX1ZBTElEQVRPUlMsXG4gIE5HX1ZBTFVFX0FDQ0VTU09SLFxuICBWYWxpZGF0aW9uRXJyb3JzLFxuICBWYWxpZGF0b3IsXG4gIFZhbGlkYXRvcnMsXG59IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IE5neFNlbGVjdEFuZ2xlU2VydmljZSB9IGZyb20gJy4vbmd4LXNlbGVjdC1hbmdsZS5zZXJ2aWNlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LXNlbGVjdC1hbmdsZScsXG4gIHRlbXBsYXRlVXJsOiAnLi9uZ3gtc2VsZWN0LWFuZ2xlLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vbmd4LXNlbGVjdC1hbmdsZS5jb21wb25lbnQuc2NzcyddLFxuICBwcm92aWRlcnM6IFtcbiAgICB7XG4gICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IE5neFNlbGVjdEFuZ2xlQ29tcG9uZW50KSxcbiAgICAgIG11bHRpOiB0cnVlLFxuICAgIH0sXG4gICAge1xuICAgICAgcHJvdmlkZTogTkdfVkFMSURBVE9SUyxcbiAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IE5neFNlbGVjdEFuZ2xlQ29tcG9uZW50KSxcbiAgICAgIG11bHRpOiB0cnVlLFxuICAgIH0sXG4gIF0sXG59KVxuZXhwb3J0IGNsYXNzIE5neFNlbGVjdEFuZ2xlQ29tcG9uZW50XG4gIGltcGxlbWVudHMgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE9uSW5pdCwgVmFsaWRhdG9yXG57XG4gIF9zaXplID0gNjA7XG4gIF9jb2xvciA9ICcjMWYyNjY3JztcbiAgX3N0cm9rZVdpZHRoID0gMjtcbiAgX3BvaW50ZXJXaWR0aCA9IDQ7XG4gIEBJbnB1dCgpIHNldCBzaXplKHM6IG51bWJlcikge1xuICAgIHRoaXMuX3NpemUgPSBzID8/IDYwO1xuICB9XG4gIEBJbnB1dCgpIHNldCBzdHJva2VXaWR0aChzOiBudW1iZXIpIHtcbiAgICB0aGlzLl9zdHJva2VXaWR0aCA9IHMgPz8gMjtcbiAgfVxuICBASW5wdXQoKSBzZXQgcG9pbnRlcldpZHRoKHM6IG51bWJlcikge1xuICAgIHRoaXMuX3BvaW50ZXJXaWR0aCA9IHMgPz8gNDtcbiAgfVxuICBASW5wdXQoKSBzZXQgY29sb3Ioczogc3RyaW5nKSB7XG4gICAgdGhpcy5fY29sb3IgPSBzID8/ICcjMWYyNjY3JztcbiAgfVxuICBpc0Rpc2FibGVkID0gZmFsc2U7XG4gIG15Q29udHJvbCA9IG5ldyBGb3JtQ29udHJvbChbMCwgW1ZhbGlkYXRvcnMubWluKDApLCBWYWxpZGF0b3JzLm1heCgzNjApXV0pO1xuICBwb3NpdGlvbiA9IHsgeDogMCwgeTogMCB9O1xuICBkcmFnZ2luZyA9IGZhbHNlO1xuICB0b29sdGlwID0gJyc7XG4gIF9vbkNoYW5nZSA9ICh2YWx1ZTogYW55KSA9PiB7fTtcbiAgX29uVG91Y2hlZCA9ICgpID0+IHt9O1xuICBfdmFsaWRhdG9yT25DaGFuZ2UgPSAoKSA9PiB7fTtcblxuICBAVmlld0NoaWxkKCdzZWxlY3RBbmdsZScsIHsgc3RhdGljOiB0cnVlIH0pXG4gIHNlbGVjdEFuZ2xlITogRWxlbWVudFJlZjxIVE1MRGl2RWxlbWVudD47XG4gIEBWaWV3Q2hpbGQoJ3BvaW50ZXInLCB7IHN0YXRpYzogdHJ1ZSB9KVxuICBwb2ludGVyITogRWxlbWVudFJlZjxIVE1MRGl2RWxlbWVudD47XG4gIGNvbnN0cnVjdG9yKFxuICAgIC8vICBASW5qZWN0KERPQ1VNRU5UKSBwcml2YXRlIGRvY3VtZW50OiBEb2N1bWVudCxcbiAgICBwcml2YXRlIF9zZWxlY3RBbmdsZVNlcnZpY2U6IE5neFNlbGVjdEFuZ2xlU2VydmljZSxcbiAgICBwcml2YXRlIF9yZW5kZXJlcjogUmVuZGVyZXIyXG4gICkge31cbiAgd3JpdGVWYWx1ZSh2YWx1ZTogYW55KTogdm9pZCB7XG4gICAgdGhpcy5teUNvbnRyb2wuc2V0VmFsdWUoK3ZhbHVlKTtcbiAgICBsZXQgZGVnID0gdGhpcy5teUNvbnRyb2wudmFsdWU7XG4gICAgbGV0IHRyYW5zZm9ybSA9ICd0cmFuc2xhdGVaKDBweCkgcm90YXRlKCcgKyBkZWcgKyAnZGVnKSc7XG4gICAgdGhpcy50b29sdGlwID0gZGVnICsgJ1xceGIwJztcbiAgICB0aGlzLl9yZW5kZXJlci5zZXRTdHlsZSh0aGlzLnBvaW50ZXIubmF0aXZlRWxlbWVudCwgJ3RyYW5zZm9ybScsIHRyYW5zZm9ybSk7XG4gIH1cblxuICB2YWxpZGF0ZShjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpOiBWYWxpZGF0aW9uRXJyb3JzIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMubXlDb250cm9sLmVycm9ycztcbiAgfVxuICByZWdpc3Rlck9uVmFsaWRhdG9yQ2hhbmdlPyhmbjogKCkgPT4gdm9pZCk6IHZvaWQge1xuICAgIHRoaXMuX3ZhbGlkYXRvck9uQ2hhbmdlID0gZm47XG4gIH1cblxuICByZWdpc3Rlck9uQ2hhbmdlKGZuOiBhbnkpOiB2b2lkIHtcbiAgICB0aGlzLl9vbkNoYW5nZSA9IGZuO1xuICB9XG4gIHJlZ2lzdGVyT25Ub3VjaGVkKGZuOiBhbnkpOiB2b2lkIHtcbiAgICB0aGlzLl9vblRvdWNoZWQgPSBmbjtcbiAgfVxuICBzZXREaXNhYmxlZFN0YXRlPyhkaXNhYmxlZDogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuaXNEaXNhYmxlZCA9IGRpc2FibGVkO1xuICAgIGlmIChkaXNhYmxlZCkgdGhpcy5teUNvbnRyb2wuZGlzYWJsZSgpO1xuICAgIGVsc2UgdGhpcy5teUNvbnRyb2wuZW5hYmxlKCk7XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHt9XG5cbiAgLyoqXG4gICAqIEVuZCBkcmFnZ2luZ1xuICAgKiBvbiBkb2N1bWVudCBtb3VzZSB1cFxuICAgKiBAcGFyYW0gZXYgbW91c2UgZXZlbnQgfCB0b3VjaCBldmVudFxuICAgKi9cbiAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6bW91c2V1cCcsIFsnJGV2ZW50J10pXG4gIG9uTW91c2VVcChldjogTW91c2VFdmVudCB8IFRvdWNoRXZlbnQpIHtcbiAgICB0aGlzLmRyYWdnaW5nID0gZmFsc2U7XG4gIH1cbiAgLyoqXG4gICAqIEVuZCBkcmFnZ2luZ1xuICAgKiBvbiBkb2N1bWVudCB0b3VjaCBlbmRcbiAgICogQHBhcmFtIGV2IG1vdXNlIGV2ZW50IHwgdG91Y2ggZXZlbnRcbiAgICovXG4gIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50OnRvdWNoZW5kJywgWyckZXZlbnQnXSlcbiAgb25Ub3VjaEVuZChldjogTW91c2VFdmVudCB8IFRvdWNoRXZlbnQpIHtcbiAgICB0aGlzLmRyYWdnaW5nID0gZmFsc2U7XG4gIH1cbiAgLyoqXG4gICAqIFN0YXJ0IGRyYWdnaW5nXG4gICAqIG9uIG1vdXNlIG9yIHRvdWNoIGRvd25cbiAgICogQHBhcmFtIGV2IG1vdXNlIGV2ZW50IHwgdG91Y2ggZXZlbnRcbiAgICovXG4gIG9uTW91c2VEb3duKGV2OiBNb3VzZUV2ZW50IHwgVG91Y2hFdmVudCkge1xuICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XG4gICAgZXYuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgdGhpcy5wb3NpdGlvbiA9IHRoaXMuX3NlbGVjdEFuZ2xlU2VydmljZS5nZXRPZmZzZXRQb3NpdGlvbihcbiAgICAgIGV2LFxuICAgICAgdGhpcy5zZWxlY3RBbmdsZS5uYXRpdmVFbGVtZW50XG4gICAgKTtcbiAgICB0aGlzLmRyYWdnaW5nID0gdHJ1ZTtcbiAgICB0aGlzLnVwZGF0ZUFuZ2xlKCk7XG4gIH1cblxuICAvKipcbiAgICogTW92ZVxuICAgKiBvbiBtb3VzZSBvciB0b3VjaCBtb3ZlXG4gICAqIEBwYXJhbSBldiBtb3VzZSBldmVudCB8IHRvdWNoIGV2ZW50XG4gICAqL1xuICBvbk1vdXNlTW92ZShldjogTW91c2VFdmVudCB8IFRvdWNoRXZlbnQpIHtcbiAgICBpZiAoIXRoaXMuZHJhZ2dpbmcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGV2LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIHRoaXMucG9zaXRpb24gPSB0aGlzLl9zZWxlY3RBbmdsZVNlcnZpY2UuZ2V0T2Zmc2V0UG9zaXRpb24oXG4gICAgICBldixcbiAgICAgIHRoaXMuc2VsZWN0QW5nbGUubmF0aXZlRWxlbWVudFxuICAgICk7XG4gICAgdGhpcy51cGRhdGVBbmdsZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIGdldCBhbmdsZSBhbmQgdXBkYXRlIHZpZXdcbiAgICovXG4gIHVwZGF0ZUFuZ2xlKCkge1xuICAgIGxldCB4MiA9IHRoaXMucG9zaXRpb24ueDtcbiAgICBsZXQgeTIgPSB0aGlzLnBvc2l0aW9uLnk7XG4gICAgbGV0IHJhZGlhbnMgPSBNYXRoLmF0YW4yKHkyIC0gdGhpcy5fc2l6ZSAvIDIsIHgyIC0gdGhpcy5fc2l6ZSAvIDIpO1xuICAgIGxldCBlID0gcmFkaWFucyAqICgxODAgLyBNYXRoLlBJKTtcbiAgICBlID0gOTAgKyBlO1xuICAgIGUgPCAwICYmIChlID0gMzYwICsgZSk7XG4gICAgZSA9IE1hdGgucm91bmQoZSk7XG4gICAgbGV0IHRyYW5zZm9ybSA9ICd0cmFuc2xhdGVaKDBweCkgcm90YXRlKCcgKyBlICsgJ2RlZyknO1xuICAgIGxldCBkZWcgPSBNYXRoLnJvdW5kKGUpO1xuICAgIHRoaXMudG9vbHRpcCA9IGRlZyArICdcXHhiMCc7XG5cbiAgICB0aGlzLm15Q29udHJvbC5zZXRWYWx1ZShkZWcpO1xuICAgIC8vIHRoaXMucG9pbnRlci5uYXRpdmVFbGVtZW50LnN0eWxlLnRyYW5zZm9ybSA9IHRyYW5zZm9ybTtcbiAgICB0aGlzLl9yZW5kZXJlci5zZXRTdHlsZSh0aGlzLnBvaW50ZXIubmF0aXZlRWxlbWVudCwgJ3RyYW5zZm9ybScsIHRyYW5zZm9ybSk7XG4gICAgdGhpcy5fb25DaGFuZ2UoZGVnKTtcbiAgfVxufVxuIiwiPGRpdlxyXG4gICNzZWxlY3RBbmdsZVxyXG4gIGNsYXNzPVwic2VsZWN0LWFuZ2xlXCJcclxuICBbdGl0bGVdPVwidG9vbHRpcFwiXHJcbiAgKG1vdXNlZG93bik9XCJvbk1vdXNlRG93bigkZXZlbnQpXCJcclxuICAodG91Y2hzdGFydCk9XCJvbk1vdXNlRG93bigkZXZlbnQpXCJcclxuICAobW91c2Vtb3ZlKT1cIm9uTW91c2VNb3ZlKCRldmVudClcIlxyXG4gICh0b3VjaG1vdmUpPVwib25Nb3VzZU1vdmUoJGV2ZW50KVwiXHJcbiAgW3N0eWxlLndpZHRoLnB4XT1cIl9zaXplXCJcclxuICBbc3R5bGUuaGVpZ2h0LnB4XT1cIl9zaXplXCJcclxuICBbc3R5bGUuYm9yZGVyQ29sb3JdPVwiX2NvbG9yXCJcclxuICBbc3R5bGUuYm9yZGVyV2lkdGgucHhdPVwiX3N0cm9rZVdpZHRoXCJcclxuPlxyXG4gIDxkaXYgY2xhc3M9XCJwb2ludGVyLWNvbnRhaW5lclwiICNwb2ludGVyIFtzdHlsZS53aWR0aC5weF09XCJfcG9pbnRlcldpZHRoXCI+XHJcbiAgICA8ZGl2XHJcbiAgICAgIGNsYXNzPVwiYW5nbGUtcG9pbnRlclwiXHJcbiAgICAgIFtzdHlsZS53aWR0aC5weF09XCJfcG9pbnRlcldpZHRoXCJcclxuICAgICAgW3N0eWxlLmhlaWdodC5weF09XCJfcG9pbnRlcldpZHRoXCJcclxuICAgICAgW3N0eWxlLmJhY2tncm91bmRdPVwiX2NvbG9yXCJcclxuICAgID48L2Rpdj5cclxuICA8L2Rpdj5cclxuPC9kaXY+XHJcbiJdfQ==