UNPKG

@ngx-file-upload/ui

Version:

Angular 16 file upload components for @ngx-file-upload/core

109 lines 18.7 kB
import { Component, Input, ViewChild, ElementRef } from "@angular/core"; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; export class ProgressbarComponent { set duration(duration) { this.animationDuration = Math.max(duration, 0); } set gap(gap) { this.progressbarGap = Math.max(gap, 1); } set parts(count) { this.progressbarParts = Math.max(count, 1); } set progress(progress) { if (progress > 0) { this.updateProgress(progress); } } constructor(renderer, zone) { this.renderer = renderer; this.zone = zone; this.dashArrayCSS = `1`; this.animate = true; this.animationDuration = 250; this.progressbarGap = 1; this.progressBuffer = []; this.isAnimated = false; this.progressbarParts = 1; } ngOnInit() { const { width } = this.progressbar?.nativeElement.getBoundingClientRect() ?? { width: 0 }; /** calculate dasharray */ const gap = this.progressbarParts === 1 ? 0 : this.progressbarGap; const widthWithoutGap = width - (this.progressbarParts * gap); const dashArrayWidth = Math.ceil(widthWithoutGap / this.progressbarParts); this.dashArrayCSS = `${dashArrayWidth} ${gap}`; } updateProgress(progress) { if (this.animate) { this.isAnimated ? this.progressBuffer.push(progress) : this.animateProgress(progress); return; } if (this.progressLine) { const el = this.progressLine.nativeElement; this.renderer.setAttribute(el, "x2", `${progress}%`); } } /** * animate progress * * @see https://javascript.info/js-animation */ animateProgress(progress) { const start = performance.now(); const self = this; const el = this.progressLine?.nativeElement; if (!el) { return; } const curProgress = progress; // new progress state const oldProgress = parseInt(el.getAttribute("x2") ?? '0', 10); // old progress state this.isAnimated = true; this.zone.runOutsideAngular(() => { // should add to service so we dont have to get this multiple times requestAnimationFrame(function animate(time) { // timeFraction goes from 0 to 1 const timeFraction = Math.min((time - start) / self.animationDuration, 1); // const progress = 1 - Math.sin(Math.acos(timeFraction)); const progressed = timeFraction; // set progressed state const progressDelta = curProgress - oldProgress; const newProgress = oldProgress + (progressed * progressDelta); self.renderer.setAttribute(el, "x2", `${newProgress}%`); if (timeFraction < 1) { requestAnimationFrame(animate); return; } if (self.progressBuffer.length > 0) { self.animateProgress(self.progressBuffer.shift()); return; } self.isAnimated = false; }); }); } /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: ProgressbarComponent, deps: [{ token: i0.Renderer2 }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); } /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.2", type: ProgressbarComponent, selector: "ngx-file-upload-ui--progressbar", inputs: { animate: "animate", duration: "duration", gap: "gap", parts: "parts", progress: "progress" }, viewQueries: [{ propertyName: "progressbar", first: true, predicate: ["progressbar"], descendants: true, read: ElementRef, static: true }, { propertyName: "progressLine", first: true, predicate: ["progressLine"], descendants: true, read: ElementRef, static: true }], ngImport: i0, template: "<!--\r\n<div class=\"progressbar\" role=\"progressbar\" [ngStyle]=\"{'flex-basis': progressed + '%'}\"></div>\r\n-->\r\n<svg xmlns=\"http://www.w3.org/2000/svg\" #progressbar class=\"progressbar\">\r\n\r\n <line class=\"background\"\r\n x1=\"0\"\r\n y1=\"50%\"\r\n x2=\"100%\"\r\n y2=\"50%\" \r\n shape-rendering=\"crispEdges\"\r\n style=\"stroke-dashoffset: 0;\"\r\n [ngStyle]=\"{'stroke-dasharray': dashArrayCSS}\">\r\n </line>\r\n \r\n <line \r\n class=\"progress\"\r\n #progressLine\r\n x1=\"0\" \r\n x2=\"0\"\r\n y1=\"50%\"\r\n y2=\"50%\" \r\n shape-rendering=\"crispEdges\"\r\n [ngStyle]=\" {'stroke-dasharray': dashArrayCSS}\">\r\n </line>\r\n</svg>\r\n", styles: [":host{display:block}:host .progressbar{width:100%;height:1rem}:host .progressbar line{stroke-width:.5rem}:host .progressbar .background{stroke:#004261}:host .progressbar .progress{stroke:#0582ca}\n"], dependencies: [{ kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: ProgressbarComponent, decorators: [{ type: Component, args: [{ selector: "ngx-file-upload-ui--progressbar", template: "<!--\r\n<div class=\"progressbar\" role=\"progressbar\" [ngStyle]=\"{'flex-basis': progressed + '%'}\"></div>\r\n-->\r\n<svg xmlns=\"http://www.w3.org/2000/svg\" #progressbar class=\"progressbar\">\r\n\r\n <line class=\"background\"\r\n x1=\"0\"\r\n y1=\"50%\"\r\n x2=\"100%\"\r\n y2=\"50%\" \r\n shape-rendering=\"crispEdges\"\r\n style=\"stroke-dashoffset: 0;\"\r\n [ngStyle]=\"{'stroke-dasharray': dashArrayCSS}\">\r\n </line>\r\n \r\n <line \r\n class=\"progress\"\r\n #progressLine\r\n x1=\"0\" \r\n x2=\"0\"\r\n y1=\"50%\"\r\n y2=\"50%\" \r\n shape-rendering=\"crispEdges\"\r\n [ngStyle]=\" {'stroke-dasharray': dashArrayCSS}\">\r\n </line>\r\n</svg>\r\n", styles: [":host{display:block}:host .progressbar{width:100%;height:1rem}:host .progressbar line{stroke-width:.5rem}:host .progressbar .background{stroke:#004261}:host .progressbar .progress{stroke:#0582ca}\n"] }] }], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i0.NgZone }]; }, propDecorators: { animate: [{ type: Input }], duration: [{ type: Input }], gap: [{ type: Input }], parts: [{ type: Input }], progress: [{ type: Input }], progressbar: [{ type: ViewChild, args: ["progressbar", { read: ElementRef, static: true }] }], progressLine: [{ type: ViewChild, args: ["progressLine", { read: ElementRef, static: true }] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvZ3Jlc3NiYXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy91aS9zcmMvbGliL3Byb2dyZXNzYmFyL3NyYy91aS9wcm9ncmVzc2Jhci50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3VpL3NyYy9saWIvcHJvZ3Jlc3NiYXIvc3JjL3VpL3Byb2dyZXNzYmFyLmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQVUsU0FBUyxFQUFFLFVBQVUsRUFBcUIsTUFBTSxlQUFlLENBQUM7OztBQU9uRyxNQUFNLE9BQU8sb0JBQW9CO0lBTzdCLElBQ1csUUFBUSxDQUFDLFFBQWdCO1FBQ2hDLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNuRCxDQUFDO0lBRUQsSUFDVyxHQUFHLENBQUMsR0FBVztRQUN0QixJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFFRCxJQUNXLEtBQUssQ0FBQyxLQUFhO1FBQzFCLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMvQyxDQUFDO0lBRUQsSUFDVyxRQUFRLENBQUMsUUFBZ0I7UUFDaEMsSUFBSSxRQUFRLEdBQUcsQ0FBQyxFQUFFO1lBQ2QsSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsQ0FBQztTQUNqQztJQUNMLENBQUM7SUFrQkQsWUFDWSxRQUFtQixFQUNuQixJQUFZO1FBRFosYUFBUSxHQUFSLFFBQVEsQ0FBVztRQUNuQixTQUFJLEdBQUosSUFBSSxDQUFRO1FBN0NqQixpQkFBWSxHQUFHLEdBQUcsQ0FBQztRQUduQixZQUFPLEdB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QUFJLEVBQUUsR0FBRyxXQUFXLEdBQUcsQ0FBQyxDQUFDO2dCQUV4RCxJQUFJLFlBQVksR0FBRyxDQUFDLEVBQUU7b0JBQ2xCLHFCQUFxQixDQUFDLE9BQU8sQ0FBQyxDQUFDO29CQUMvQixPQUFPO2lCQUNWO2dCQUVELElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO29CQUNoQyxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxFQUFZLENBQUMsQ0FBQztvQkFDNUQsT0FBTztpQkFDVjtnQkFFRCxJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQztZQUM1QixDQUFDLENBQUMsQ0FBQztRQUNQLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztpSUEzSFEsb0JBQW9CO3FIQUFwQixvQkFBb0Isc1FBdUNJLFVBQVUscUhBR1QsVUFBVSwyQ0NqRGhELDR5QkEwQkE7OzJGRG5CYSxvQkFBb0I7a0JBTGhDLFNBQVM7K0JBQ0ksaUNBQWlDO3FIQVNwQyxPQUFPO3NCQURiLEtBQUs7Z0JBSUssUUFBUTtzQkFEbEIsS0FBSztnQkFNSyxHQUFHO3NCQURiLEtBQUs7Z0JBTUssS0FBSztzQkFEZixLQUFLO2dCQU1LLFFBQVE7c0JBRGxCLEtBQUs7Z0JBa0JFLFdBQVc7c0JBRGxCLFNBQVM7dUJBQUMsYUFBYSxFQUFFLEVBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFDO2dCQUlsRCxZQUFZO3NCQURuQixTQUFTO3VCQUFDLGNBQWMsRUFBRSxFQUFDLElBQUksRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQsIE9uSW5pdCwgVmlld0NoaWxkLCBFbGVtZW50UmVmLCBSZW5kZXJlcjIsIE5nWm9uZSB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICAgIHNlbGVjdG9yOiBcIm5neC1maWxlLXVwbG9hZC11aS0tcHJvZ3Jlc3NiYXJcIixcclxuICAgIHRlbXBsYXRlVXJsOiBcInByb2dyZXNzYmFyLmh0bWxcIixcclxuICAgIHN0eWxlVXJsczogW1wiLi9wcm9ncmVzc2Jhci5zY3NzXCJdXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBQcm9ncmVzc2JhckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XHJcblxyXG4gICAgcHVibGljIGRhc2hBcnJheUNTUyA9IGAxYDtcclxuXHJcbiAgICBASW5wdXQoKVxyXG4gICAgcHVibGljIGFuaW1hdGUgPSB0cnVlO1xyXG5cclxuICAgIEBJbnB1dCgpXHJcbiAgICBwdWJsaWMgc2V0IGR1cmF0aW9uKGR1cmF0aW9uOiBudW1iZXIpIHtcclxuICAgICAgICB0aGlzLmFuaW1hdGlvbkR1cmF0aW9uID0gTWF0aC5tYXgoZHVyYXRpb24sIDApO1xyXG4gICAgfVxyXG5cclxuICAgIEBJbnB1dCgpXHJcbiAgICBwdWJsaWMgc2V0IGdhcChnYXA6IG51bWJlcikge1xyXG4gICAgICAgIHRoaXMucHJvZ3Jlc3NiYXJHYXAgPSBNYXRoLm1heChnYXAsIDEpO1xyXG4gICAgfVxyXG5cclxuICAgIEBJbnB1dCgpXHJcbiAgICBwdWJsaWMgc2V0IHBhcnRzKGNvdW50OiBudW1iZXIpIHtcclxuICAgICAgICB0aGlzLnByb2dyZXNzYmFyUGFydHMgPSBNYXRoLm1heChjb3VudCwgMSk7XHJcbiAgICB9XHJcblxyXG4gICAgQElucHV0KClcclxuICAgIHB1YmxpYyBzZXQgcHJvZ3Jlc3MocHJvZ3Jlc3M6IG51bWJlcikge1xyXG4gICAgICAgIGlmIChwcm9ncmVzcyA+IDApIHtcclxuICAgICAgICAgICAgdGhpcy51cGRhdGVQcm9ncmVzcyhwcm9ncmVzcyk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgYW5pbWF0aW9uRHVyYXRpb24gPSAyNTA7XHJcblxyXG4gICAgcHJpdmF0ZSBwcm9ncmVzc2JhckdhcCA9IDE7XHJcblxyXG4gICAgcHJpdmF0ZSBwcm9ncmVzc0J1ZmZlcjogbnVtYmVyW10gPSBbXTtcclxuXHJcbiAgICBwcml2YXRlIGlzQW5pbWF0ZWQgPSBmYWxzZTtcclxuXHJcbiAgICBwcml2YXRlIHByb2dyZXNzYmFyUGFydHMgPSAxO1xyXG5cclxuICAgIEBWaWV3Q2hpbGQoXCJwcm9ncmVzc2JhclwiLCB7cmVhZDogRWxlbWVudFJlZiwgc3RhdGljOiB0cnVlfSlcclxuICAgIHByaXZhdGUgcHJvZ3Jlc3NiYXI6IEVsZW1lbnRSZWY8U1ZHRWxlbWVudD4gfCB1bmRlZmluZWQ7XHJcblxyXG4gICAgQFZpZXdDaGlsZChcInByb2dyZXNzTGluZVwiLCB7cmVhZDogRWxlbWVudFJlZiwgc3RhdGljOiB0cnVlfSlcclxuICAgIHByaXZhdGUgcHJvZ3Jlc3NMaW5lOiBFbGVtZW50UmVmPFNWR0xpbmVFbGVtZW50PiB8IHVuZGVmaW5lZDtcclxuXHJcbiAgICBwdWJsaWMgY29uc3RydWN0b3IoXHJcbiAgICAgICAgcHJpdmF0ZSByZW5kZXJlcjogUmVuZGVyZXIyLFxyXG4gICAgICAgIHByaXZhdGUgem9uZTogTmdab25lXHJcbiAgICApIHt9XHJcblxyXG4gICAgcHVibGljIG5nT25Jbml0KCkge1xyXG4gICAgICAgIGNvbnN0IHt3aWR0aH0gPSB0aGlzLnByb2dyZXNzYmFyPy5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpID8/IHsgd2lkdGg6IDAgfTtcclxuXHJcbiAgICAgICAgLyoqIGNhbGN1bGF0ZSBkYXNoYXJyYXkgKi9cclxuICAgICAgICBjb25zdCBnYXAgPSB0aGlzLnByb2dyZXNzYmFyUGFydHMgPT09IDEgPyAwIDogdGhpcy5wcm9ncmVzc2JhckdhcDtcclxuICAgICAgICBjb25zdCB3aWR0aFdpdGhvdXRHYXAgPSB3aWR0aCAtICh0aGlzLnByb2dyZXNzYmFyUGFydHMgKiBnYXApO1xyXG4gICAgICAgIGNvbnN0IGRhc2hBcnJheVdpZHRoICA9IE1hdGguY2VpbCh3aWR0aFdpdGhvdXRHYXAgLyB0aGlzLnByb2dyZXNzYmFyUGFydHMpO1xyXG5cclxuICAgICAgICB0aGlzLmRhc2hBcnJheUNTUyA9IGAke2Rhc2hBcnJheVdpZHRofSAke2dhcH1gO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgdXBkYXRlUHJvZ3Jlc3MocHJvZ3Jlc3M6IG51bWJlcikge1xyXG5cclxuICAgICAgICBpZiAodGhpcy5hbmltYXRlKSB7XHJcbiAgICAgICAgICAgIHRoaXMuaXNBbmltYXRlZCA/IHRoaXMucHJvZ3Jlc3NCdWZmZXIucHVzaChwcm9ncmVzcykgOiB0aGlzLmFuaW1hdGVQcm9ncmVzcyhwcm9ncmVzcyk7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0aGlzLnByb2dyZXNzTGluZSkge1xyXG4gICAgICAgICAgICBjb25zdCBlbCA9IHRoaXMucHJvZ3Jlc3NMaW5lLm5hdGl2ZUVsZW1lbnQ7XHJcbiAgICAgICAgICAgIHRoaXMucmVuZGVyZXIuc2V0QXR0cmlidXRlKGVsLCBcIngyXCIsIGAke3Byb2dyZXNzfSVgKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBhbmltYXRlIHByb2dyZXNzXHJcbiAgICAgKlxyXG4gICAgICogQHNlZSBodHRwczovL2phdmFzY3JpcHQuaW5mby9qcy1hbmltYXRpb25cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBhbmltYXRlUHJvZ3Jlc3MocHJvZ3Jlc3M6IG51bWJlcikge1xyXG5cclxuICAgICAgICBjb25zdCBzdGFydCA9IHBlcmZvcm1hbmNlLm5vdygpO1xyXG4gICAgICAgIGNvbnN0IHNlbGYgID0gdGhpcztcclxuICAgICAgICBjb25zdCBlbCAgICA9IHRoaXMucHJvZ3Jlc3NMaW5lPy5uYXRpdmVFbGVtZW50O1xyXG5cclxuICAgICAgICBpZiAoIWVsKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGN1clByb2dyZXNzID0gcHJvZ3Jlc3M7IC8vIG5ldyBwcm9ncmVzcyBzdGF0ZVxyXG4gICAgICAgIGNvbnN0IG9sZFByb2dyZXNzID0gcGFyc2VJbnQoZWwuZ2V0QXR0cmlidXRlKFwieDJcIikgPz8gJzAnLCAxMCk7IC8vIG9sZCBwcm9ncmVzcyBzdGF0ZVxyXG5cclxuICAgICAgICB0aGlzLmlzQW5pbWF0ZWQgPSB0cnVlO1xyXG5cclxuICAgICAgICB0aGlzLnpvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xyXG5cclxuICAgICAgICAgICAgLy8gc2hvdWxkIGFkZCB0byBzZXJ2aWNlIHNvIHdlIGRvbnQgaGF2ZSB0byBnZXQgdGhpcyBtdWx0aXBsZSB0aW1lc1xyXG4gICAgICAgICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoZnVuY3Rpb24gYW5pbWF0ZSh0aW1lKSB7XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gdGltZUZyYWN0aW9uIGdvZXMgZnJvbSAwIHRvIDFcclxuICAgICAgICAgICAgICAgIGNvbnN0IHRpbWVGcmFjdGlvbiA9IE1hdGgubWluKCh0aW1lIC0gc3RhcnQpIC8gc2VsZi5hbmltYXRpb25EdXJhdGlvbiwgMSk7XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gY29uc3QgcHJvZ3Jlc3MgPSAxIC0gTWF0aC5zaW4oTWF0aC5hY29zKHRpbWVGcmFjdGlvbikpO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgcHJvZ3Jlc3NlZCA9IHRpbWVGcmFjdGlvbjtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBzZXQgcHJvZ3Jlc3NlZCBzdGF0ZVxyXG4gICAgICAgICAgICAgICAgY29uc3QgcHJvZ3Jlc3NEZWx0YSA9IGN1clByb2dyZXNzIC0gb2xkUHJvZ3Jlc3M7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBuZXdQcm9ncmVzcyAgID0gb2xkUHJvZ3Jlc3MgKyAocHJvZ3Jlc3NlZCAqIHByb2dyZXNzRGVsdGEpO1xyXG4gICAgICAgICAgICAgICAgc2VsZi5yZW5kZXJlci5zZXRBdHRyaWJ1dGUoZWwsIFwieDJcIiwgYCR7bmV3UHJvZ3Jlc3N9JWApO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmICh0aW1lRnJhY3Rpb24gPCAxKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKGFuaW1hdGUpO1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoc2VsZi5wcm9ncmVzc0J1ZmZlci5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5hbmltYXRlUHJvZ3Jlc3Moc2VsZi5wcm9ncmVzc0J1ZmZlci5zaGlmdCgpIGFzIG51bWJlcik7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIHNlbGYuaXNBbmltYXRlZCA9IGZhbHNlO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxufVxyXG4iLCI8IS0tXHJcbjxkaXYgY2xhc3M9XCJwcm9ncmVzc2JhclwiIHJvbGU9XCJwcm9ncmVzc2JhclwiIFtuZ1N0eWxlXT1cInsnZmxleC1iYXNpcyc6IHByb2dyZXNzZWQgKyAnJSd9XCI+PC9kaXY+XHJcbi0tPlxyXG48c3ZnIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiAjcHJvZ3Jlc3NiYXIgY2xhc3M9XCJwcm9ncmVzc2JhclwiPlxyXG5cclxuICAgIDxsaW5lIGNsYXNzPVwiYmFja2dyb3VuZFwiXHJcbiAgICAgICAgICB4MT1cIjBcIlxyXG4gICAgICAgICAgeTE9XCI1MCVcIlxyXG4gICAgICAgICAgeDI9XCIxMDAlXCJcclxuICAgICAgICAgIHkyPVwiNTAlXCIgXHJcbiAgICAgICAgICBzaGFwZS1yZW5kZXJpbmc9XCJjcmlzcEVkZ2VzXCJcclxuICAgICAgICAgIHN0eWxlPVwic3Ryb2tlLWRhc2hvZmZzZXQ6IDA7XCJcclxuICAgICAgICAgIFtuZ1N0eWxlXT1cInsnc3Ryb2tlLWRhc2hhcnJheSc6IGRhc2hBcnJheUNTU31cIj5cclxuICAgIDwvbGluZT5cclxuICAgIFxyXG4gICAgPGxpbmUgXHJcbiAgICAgICAgICBjbGFzcz1cInByb2dyZXNzXCJcclxuICAgICAgICAgICNwcm9ncmVzc0xpbmVcclxuICAgICAgICAgIHgxPVwiMFwiIFxyXG4gICAgICAgICAgeDI9XCIwXCJcclxuICAgICAgICAgIHkxPVwiNTAlXCJcclxuICAgICAgICAgIHkyPVwiNTAlXCIgXHJcbiAgICAgICAgICBzaGFwZS1yZW5kZXJpbmc9XCJjcmlzcEVkZ2VzXCJcclxuICAgICAgICAgIFtuZ1N0eWxlXT1cIiB7J3N0cm9rZS1kYXNoYXJyYXknOiBkYXNoQXJyYXlDU1N9XCI+XHJcbiAgICA8L2xpbmU+XHJcbjwvc3ZnPlxyXG4iXX0=