@sumaris-net/ngx-components 18.26.14-alpha1 → 18.26.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/doc/changelog.md +4 -2
  2. package/esm2022/src/app/core/menu/menu.component.mjs +3 -3
  3. package/esm2022/src/app/core/services/platform.service.mjs +37 -7
  4. package/esm2022/src/app/core/settings/settings.page.mjs +8 -4
  5. package/esm2022/src/app/shared/capacitor/plugins.mjs +2 -1
  6. package/esm2022/src/app/shared/image/gallery/image-gallery.component.mjs +3 -3
  7. package/esm2022/src/app/shared/image/gallery/slideshow/image-gallery-slideshow.component.mjs +2 -2
  8. package/esm2022/src/app/shared/platforms.mjs +23 -1
  9. package/esm2022/src/app/shared/upload-file/upload-file-popover.component.mjs +4 -10
  10. package/esm2022/src/app/shared/upload-file/upload-file.component.mjs +4 -41
  11. package/esm2022/src/app/shared/upload-file/upload-file.model.mjs +1 -1
  12. package/esm2022/src/app/shared/version/versions.mjs +10 -3
  13. package/esm2022/src/app/social/feed/feed.component.mjs +3 -3
  14. package/fesm2022/sumaris-net.ngx-components.mjs +89 -68
  15. package/fesm2022/sumaris-net.ngx-components.mjs.map +1 -1
  16. package/package.json +14 -13
  17. package/src/app/core/services/platform.service.d.ts +2 -0
  18. package/src/app/core/settings/settings.page.d.ts +1 -1
  19. package/src/app/shared/capacitor/plugins.d.ts +1 -0
  20. package/src/app/shared/platforms.d.ts +1 -0
  21. package/src/app/shared/upload-file/upload-file-popover.component.d.ts +1 -5
  22. package/src/app/shared/upload-file/upload-file.component.d.ts +2 -6
  23. package/src/app/shared/upload-file/upload-file.model.d.ts +0 -7
  24. package/src/assets/i18n/en-US.json +0 -2
  25. package/src/assets/i18n/en.json +0 -2
  26. package/src/assets/i18n/fr.json +0 -2
  27. package/src/assets/manifest.json +1 -1
  28. package/src/theme/_ngx-components.table.scss +5 -0
@@ -734,11 +734,11 @@ export class AppImageGallerySlideshowComponent {
734
734
  this.cd.markForCheck();
735
735
  }
736
736
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AppImageGallerySlideshowComponent, deps: [{ token: i1.AlertController }, { token: i2.TranslateService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
737
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AppImageGallerySlideshowComponent, selector: "app-image-gallery-slideshow", inputs: { rows: "rows", selectedIndex: "selectedIndex", mobile: ["mobile", "mobile", booleanAttribute], readOnly: ["readOnly", "readOnly", booleanAttribute], disabled: ["disabled", "disabled", booleanAttribute], debug: ["debug", "debug", booleanAttribute], enableMouseZoom: ["enableMouseZoom", "enableMouseZoom", booleanAttribute], wheelZoomStep: "wheelZoomStep", maxZoomRatio: "maxZoomRatio", enableRotate: ["enableRotate", "enableRotate", booleanAttribute], enableCrop: ["enableCrop", "enableCrop", booleanAttribute], editionFormat: "editionFormat", editionQuality: "editionQuality", imageSizeQueryParam: "imageSizeQueryParam", modalImageSize: "modalImageSize", enableLoop: ["enableLoop", "enableLoop", booleanAttribute], canFetchMore: ["canFetchMore", "canFetchMore", booleanAttribute] }, outputs: { deleteRequested: "deleteRequested", closeRequested: "closeRequested", afterEditImage: "afterEditImage", afterEditRow: "afterEditRow", previousSlide: "previousSlide", nextSlide: "nextSlide", fetchMore: "fetchMore" }, host: { listeners: { "window:resize": "onWindowResize()" } }, viewQueries: [{ propertyName: "swiperRef", first: true, predicate: ["swiperContainer"], descendants: true }], ngImport: i0, template: "<ion-content\n class=\"ion-no-padding ion-no-margin\"\n (mousedown)=\"onPointerDown($event, swiperContainer)\"\n (mousemove)=\"onPointerMove($event, swiperContainer)\"\n (mouseup)=\"onPointerUp($event, swiperContainer)\"\n (mouseleave)=\"onPointerUp($event, swiperContainer)\"\n (touchmove)=\"onCropPointerMove($event, swiperContainer)\"\n (touchend)=\"onCropPointerUp($event, swiperContainer)\"\n (touchcancel)=\"onCropPointerUp($event, swiperContainer)\"\n>\n @let count = rows?.length || 0;\n <!-- Counter -->\n <div class=\"top-left\">\n <ion-label color=\"light\">{{ _activeIndex + 1 }} / {{ count }}</ion-label>\n </div>\n\n <!-- zoom / rotation / crop buttons: all shown together, no \"enter edit mode\" step needed -->\n <div class=\"top-right\">\n @if (!mobile) {\n <ion-fab-button size=\"small\" (click)=\"zoom(swiperContainer, true)\" color=\"light\">\n <ion-icon name=\"search\"></ion-icon>\n <ion-icon class=\"icon-secondary\" name=\"add\"></ion-icon>\n </ion-fab-button>\n <ion-fab-button size=\"small\" (click)=\"zoom(swiperContainer, false)\" color=\"light\">\n <ion-icon name=\"search\"></ion-icon>\n <ion-icon class=\"icon-secondary\" name=\"remove\"></ion-icon>\n </ion-fab-button>\n }\n @if (!readOnly && enableRotate) {\n <ion-fab-button\n size=\"small\"\n (click)=\"rotate(swiperContainer, 'left')\"\n color=\"light\"\n [title]=\"!showTooltip ? ('IMAGE.GALLERY.BTN_ROTATE_LEFT' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('IMAGE.GALLERY.BTN_ROTATE_LEFT' | translate) : ''\"\n >\n <mat-icon>rotate_left</mat-icon>\n </ion-fab-button>\n <ion-fab-button\n size=\"small\"\n (click)=\"rotate(swiperContainer, 'right')\"\n color=\"light\"\n [title]=\"!showTooltip ? ('IMAGE.GALLERY.BTN_ROTATE_RIGHT' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('IMAGE.GALLERY.BTN_ROTATE_RIGHT' | translate) : ''\"\n >\n <mat-icon>rotate_right</mat-icon>\n </ion-fab-button>\n }\n @if (!readOnly && enableCrop) {\n <ion-fab-button\n size=\"small\"\n (click)=\"toggleCropTool(swiperContainer)\"\n [color]=\"_cropToolActive ? 'tertiary' : 'light'\"\n [title]=\"\n !showTooltip\n ? ((_cropToolActive ? 'IMAGE.GALLERY.BTN_CROP_DEACTIVATE' : 'IMAGE.GALLERY.BTN_CROP_ACTIVATE') | translate)\n : ''\n \"\n [matTooltip]=\"\n showTooltip\n ? ((_cropToolActive ? 'IMAGE.GALLERY.BTN_CROP_DEACTIVATE' : 'IMAGE.GALLERY.BTN_CROP_ACTIVATE') | translate)\n : ''\n \"\n >\n <mat-icon>crop</mat-icon>\n </ion-fab-button>\n @if (_cropToolActive) {\n <ion-fab-button\n size=\"small\"\n (click)=\"resetCrop(swiperContainer)\"\n color=\"light\"\n [title]=\"!showTooltip ? ('IMAGE.GALLERY.BTN_CROP_RESET' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('IMAGE.GALLERY.BTN_CROP_RESET' | translate) : ''\"\n >\n <mat-icon>crop_free</mat-icon>\n </ion-fab-button>\n }\n }\n </div>\n\n <!-- navigation side buttons next/back: hidden while a crop/rotation edit is pending, to keep the focus on validating/cancelling it -->\n <ng-container *ngIf=\"!mobile && !hasPendingEdit && (rows | isArrayLength: { greaterThan: 1 })\">\n <div class=\"side-buttons prev\" [class.disabled]=\"isPrevDisabled\" (click)=\"slidePrev(swiperContainer)\">\n <ion-icon name=\"chevron-back\"></ion-icon>\n </div>\n <div class=\"side-buttons next\" [class.disabled]=\"isNextDisabled\" (click)=\"slideNext(swiperContainer)\">\n <ion-icon name=\"chevron-forward\"></ion-icon>\n </div>\n </ng-container>\n\n <!-- image slides -->\n <swiper-container\n #swiperContainer\n [modules]=\"swiperModules\"\n [zoom]=\"!enableMouseZoom\"\n [initialSlide]=\"selectedIndex\"\n (swiperslidechange)=\"onSlideChange(swiperContainer)\"\n (swiperinit)=\"onSwiperInit(swiperContainer)\"\n >\n @for (row of rows; track row.id; let index = $index) {\n <ng-container *ngTemplateOutlet=\"slideTemplate; context: { image: row.currentData, index }\"></ng-container>\n }\n </swiper-container>\n</ion-content>\n\n<ion-footer>\n <ion-toolbar color=\"light\">\n @if (!hasPendingEdit) {\n <ion-row>\n <ion-col size=\"4\" class=\"ion-text-start\">\n @if (!readOnly) {\n <ion-button\n (click)=\"requestDelete(swiperContainer)\"\n [disabled]=\"disabled\"\n fill=\"clear\"\n color=\"danger\"\n >\n <mat-icon slot=\"start\">delete</mat-icon>\n {{ 'COMMON.BTN_DELETE' | translate }}\n </ion-button>\n }\n </ion-col>\n <ion-col size=\"4\"></ion-col>\n <ion-col size=\"4\" class=\"ion-text-end\">\n <ion-button (click)=\"closeRequested.emit()\" color=\"tertiary\" fill=\"clear\" *ngIf=\"mobile; else desktop\">\n <ion-icon slot=\"start\" name=\"close\"></ion-icon>\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n <ng-template #desktop>\n <ion-button (click)=\"closeRequested.emit()\" color=\"tertiary\">\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n </ng-template>\n </ion-col>\n </ion-row>\n } @else {\n <!-- A crop or rotation change is pending: ask for an explicit validation before exporting the image -->\n <ion-row>\n <ion-col size=\"12\" class=\"ion-text-end\">\n <ion-button\n (click)=\"discardEdit(swiperContainer)\"\n color=\"dark\"\n fill=\"clear\"\n [title]=\"!showTooltip ? ('IMAGE.GALLERY.BTN_CANCEL_EDIT' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('IMAGE.GALLERY.BTN_CANCEL_EDIT' | translate) : ''\"\n >\n <ion-icon slot=\"start\" name=\"arrow-undo\"></ion-icon>\n {{ 'COMMON.BTN_CANCEL' | translate }}\n </ion-button>\n <ion-button (click)=\"validateEdit(swiperContainer)\" color=\"danger\">\n <ion-icon slot=\"start\" name=\"checkmark\"></ion-icon>\n {{ 'COMMON.BTN_VALIDATE' | translate }}\n </ion-button>\n </ion-col>\n </ion-row>\n }\n </ion-toolbar>\n</ion-footer>\n\n<ng-template #slideTemplate let-image=\"image\" let-index=\"index\">\n <swiper-slide>\n <div class=\"swiper-zoom-container\" [class.cdk-visually-hidden]=\"!_swiper && index !== selectedIndex\">\n\n <!-- the image -->\n @if (image?.url) {\n <ion-img class=\"swiper-zoom-target\" [src]=\"image.url | appendQueryParams: getImageSizeQueryParams()\" />\n } @else {\n <img [src]=\"image.dataUrl\" [alt]=\"image.title\" />\n }\n\n <!-- crop overlay: only rendered for the active slide -->\n @if (!readOnly && enableCrop && _cropToolActive && index === _activeIndex) {\n <div\n class=\"crop-overlay\"\n (mousedown)=\"onCropPointerDown($event, swiperContainer, 'move')\"\n (touchstart)=\"onCropPointerDown($event, swiperContainer, 'move')\"\n >\n <!-- darkened mask around the selection: clipped to the image bounds -->\n <div class=\"crop-mask\">\n <div\n class=\"crop-mask-rect\"\n [style.left.%]=\"_cropRect.x * 100\"\n [style.top.%]=\"_cropRect.y * 100\"\n [style.width.%]=\"_cropRect.width * 100\"\n [style.height.%]=\"_cropRect.height * 100\"\n ></div>\n </div>\n\n <!-- interactive selection border, grid & drag handles: never clipped, so corner/edge handles\n remain fully grabbable even when the selection touches the image bounds -->\n <div\n class=\"crop-rect\"\n [style.left.%]=\"_cropRect.x * 100\"\n [style.top.%]=\"_cropRect.y * 100\"\n [style.width.%]=\"_cropRect.width * 100\"\n [style.height.%]=\"_cropRect.height * 100\"\n >\n <div class=\"crop-grid\">\n <span class=\"line v\" style=\"left: 33.333%\"></span>\n <span class=\"line v\" style=\"left: 66.666%\"></span>\n <span class=\"line h\" style=\"top: 33.333%\"></span>\n <span class=\"line h\" style=\"top: 66.666%\"></span>\n </div>\n @for (handle of _cropHandles; track handle) {\n <div\n class=\"crop-handle {{ handle }}\"\n (mousedown)=\"onCropPointerDown($event, swiperContainer, handle)\"\n (touchstart)=\"onCropPointerDown($event, swiperContainer, handle)\"\n ></div>\n }\n </div>\n </div>\n }\n </div>\n </swiper-slide>\n</ng-template>\n", styles: [":host{display:flex;flex-direction:column;height:100%;-webkit-user-select:none;user-select:none}:host ion-content{flex:1 1 auto}:host .top-left{z-index:14;position:absolute;display:inline-grid;left:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}:host .top-right{z-index:14;position:absolute;display:inline-grid;right:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}:host .side-buttons{--side-buttons-width: 120px;--side-buttons-margin: calc(var(--side-buttons-width) / 3);z-index:13;position:absolute;top:0;bottom:0;width:var(--side-buttons-width)}:host .side-buttons ion-icon{top:50%;color:#fff;background:#00000080;padding:4px;border-radius:50%;font-size:2.5rem;position:absolute;opacity:0;transition-duration:.15s;transition-timing-function:ease-in}:host .side-buttons:hover{cursor:pointer}:host .side-buttons:hover ion-icon{opacity:1}:host .side-buttons.prev{left:0}:host .side-buttons.prev ion-icon{left:var(--side-buttons-margin)}:host .side-buttons.next{right:0}:host .side-buttons.next ion-icon{right:var(--side-buttons-margin)}:host .side-buttons.disabled{pointer-events:none}:host swiper-container{height:100%;background:#000}:host .swiper-zoom-container{position:relative}:host ion-fab-button .icon-secondary{top:11px;left:6px;height:14px}:host .crop-overlay{position:absolute;z-index:15;cursor:move;touch-action:none;animation:crop-overlay-fade-in .15s ease-in}:host .crop-overlay .crop-mask{position:absolute;inset:0;overflow:hidden;pointer-events:none}:host .crop-overlay .crop-mask .crop-mask-rect{position:absolute;box-shadow:0 0 0 2000px #0009}:host .crop-overlay .crop-rect{position:absolute;box-sizing:border-box;border:1px solid rgba(255,255,255,.95);cursor:move;touch-action:none}:host .crop-overlay .crop-rect .crop-grid{position:absolute;inset:0;pointer-events:none}:host .crop-overlay .crop-rect .crop-grid .line{position:absolute;background:#ffffff73}:host .crop-overlay .crop-rect .crop-grid .line.v{top:0;bottom:0;width:1px}:host .crop-overlay .crop-rect .crop-grid .line.h{left:0;right:0;height:1px}:host .crop-overlay .crop-rect .crop-handle{position:absolute;width:16px;height:16px;margin:-8px;background:#fff;border:1px solid rgba(0,0,0,.45);border-radius:50%;box-shadow:0 1px 4px #00000080;transition:transform .12s ease;touch-action:none}:host .crop-overlay .crop-rect .crop-handle:hover{transform:scale(1.3)}:host .crop-overlay .crop-rect .crop-handle.nw{left:0;top:0;cursor:nwse-resize}:host .crop-overlay .crop-rect .crop-handle.n{left:50%;top:0;cursor:ns-resize}:host .crop-overlay .crop-rect .crop-handle.ne{left:100%;top:0;cursor:nesw-resize}:host .crop-overlay .crop-rect .crop-handle.e{left:100%;top:50%;cursor:ew-resize}:host .crop-overlay .crop-rect .crop-handle.se{left:100%;top:100%;cursor:nwse-resize}:host .crop-overlay .crop-rect .crop-handle.s{left:50%;top:100%;cursor:ns-resize}:host .crop-overlay .crop-rect .crop-handle.sw{left:0;top:100%;cursor:nesw-resize}:host .crop-overlay .crop-rect .crop-handle.w{left:0;top:50%;cursor:ew-resize}@keyframes crop-overlay-fade-in{0%{opacity:0}to{opacity:1}}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i1.IonFabButton, selector: "ion-fab-button", inputs: ["activated", "closeIcon", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "show", "size", "target", "translucent", "type"] }, { kind: "component", type: i1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i1.IonImg, selector: "ion-img", inputs: ["alt", "src"] }, { kind: "component", type: i1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i1.IonRow, selector: "ion-row" }, { kind: "component", type: i1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: i6.ArrayLengthPipe, name: "isArrayLength" }, { kind: "pipe", type: i7.AppendQueryParamsPipePipe, name: "appendQueryParams" }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
737
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AppImageGallerySlideshowComponent, selector: "app-image-gallery-slideshow", inputs: { rows: "rows", selectedIndex: "selectedIndex", mobile: ["mobile", "mobile", booleanAttribute], readOnly: ["readOnly", "readOnly", booleanAttribute], disabled: ["disabled", "disabled", booleanAttribute], debug: ["debug", "debug", booleanAttribute], enableMouseZoom: ["enableMouseZoom", "enableMouseZoom", booleanAttribute], wheelZoomStep: "wheelZoomStep", maxZoomRatio: "maxZoomRatio", enableRotate: ["enableRotate", "enableRotate", booleanAttribute], enableCrop: ["enableCrop", "enableCrop", booleanAttribute], editionFormat: "editionFormat", editionQuality: "editionQuality", imageSizeQueryParam: "imageSizeQueryParam", modalImageSize: "modalImageSize", enableLoop: ["enableLoop", "enableLoop", booleanAttribute], canFetchMore: ["canFetchMore", "canFetchMore", booleanAttribute] }, outputs: { deleteRequested: "deleteRequested", closeRequested: "closeRequested", afterEditImage: "afterEditImage", afterEditRow: "afterEditRow", previousSlide: "previousSlide", nextSlide: "nextSlide", fetchMore: "fetchMore" }, host: { listeners: { "window:resize": "onWindowResize()" } }, viewQueries: [{ propertyName: "swiperRef", first: true, predicate: ["swiperContainer"], descendants: true }], ngImport: i0, template: "<ion-content\n class=\"ion-no-padding ion-no-margin\"\n (mousedown)=\"onPointerDown($event, swiperContainer)\"\n (mousemove)=\"onPointerMove($event, swiperContainer)\"\n (mouseup)=\"onPointerUp($event, swiperContainer)\"\n (mouseleave)=\"onPointerUp($event, swiperContainer)\"\n (touchmove)=\"onCropPointerMove($event, swiperContainer)\"\n (touchend)=\"onCropPointerUp($event, swiperContainer)\"\n (touchcancel)=\"onCropPointerUp($event, swiperContainer)\"\n>\n @let count = rows?.length || 0;\n <!-- Counter -->\n <div class=\"top-left\">\n <ion-label color=\"light\">{{ _activeIndex + 1 }} / {{ count }}</ion-label>\n </div>\n\n <!-- zoom / rotation / crop buttons: all shown together, no \"enter edit mode\" step needed -->\n <div class=\"top-right\">\n @if (!mobile) {\n <ion-fab-button size=\"small\" (click)=\"zoom(swiperContainer, true)\" color=\"light\">\n <ion-icon name=\"search\"></ion-icon>\n <ion-icon class=\"icon-secondary\" name=\"add\"></ion-icon>\n </ion-fab-button>\n <ion-fab-button size=\"small\" (click)=\"zoom(swiperContainer, false)\" color=\"light\">\n <ion-icon name=\"search\"></ion-icon>\n <ion-icon class=\"icon-secondary\" name=\"remove\"></ion-icon>\n </ion-fab-button>\n }\n @if (!readOnly && enableRotate) {\n <ion-fab-button\n size=\"small\"\n (click)=\"rotate(swiperContainer, 'left')\"\n color=\"light\"\n [title]=\"!showTooltip ? ('IMAGE.GALLERY.BTN_ROTATE_LEFT' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('IMAGE.GALLERY.BTN_ROTATE_LEFT' | translate) : ''\"\n >\n <mat-icon>rotate_left</mat-icon>\n </ion-fab-button>\n <ion-fab-button\n size=\"small\"\n (click)=\"rotate(swiperContainer, 'right')\"\n color=\"light\"\n [title]=\"!showTooltip ? ('IMAGE.GALLERY.BTN_ROTATE_RIGHT' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('IMAGE.GALLERY.BTN_ROTATE_RIGHT' | translate) : ''\"\n >\n <mat-icon>rotate_right</mat-icon>\n </ion-fab-button>\n }\n @if (!readOnly && enableCrop) {\n <ion-fab-button\n size=\"small\"\n (click)=\"toggleCropTool(swiperContainer)\"\n [color]=\"_cropToolActive ? 'tertiary' : 'light'\"\n [title]=\"\n !showTooltip\n ? ((_cropToolActive ? 'IMAGE.GALLERY.BTN_CROP_DEACTIVATE' : 'IMAGE.GALLERY.BTN_CROP_ACTIVATE') | translate)\n : ''\n \"\n [matTooltip]=\"\n showTooltip\n ? ((_cropToolActive ? 'IMAGE.GALLERY.BTN_CROP_DEACTIVATE' : 'IMAGE.GALLERY.BTN_CROP_ACTIVATE') | translate)\n : ''\n \"\n >\n <mat-icon>crop</mat-icon>\n </ion-fab-button>\n @if (_cropToolActive) {\n <ion-fab-button\n size=\"small\"\n (click)=\"resetCrop(swiperContainer)\"\n color=\"light\"\n [title]=\"!showTooltip ? ('IMAGE.GALLERY.BTN_CROP_RESET' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('IMAGE.GALLERY.BTN_CROP_RESET' | translate) : ''\"\n >\n <mat-icon>crop_free</mat-icon>\n </ion-fab-button>\n }\n }\n </div>\n\n <!-- navigation side buttons next/back: hidden while a crop/rotation edit is pending, to keep the focus on validating/cancelling it -->\n <ng-container *ngIf=\"!mobile && !hasPendingEdit && (rows | isArrayLength: { greaterThan: 1 })\">\n <div class=\"side-buttons prev\" [class.disabled]=\"isPrevDisabled\" (click)=\"slidePrev(swiperContainer)\">\n <ion-icon name=\"chevron-back\"></ion-icon>\n </div>\n <div class=\"side-buttons next\" [class.disabled]=\"isNextDisabled\" (click)=\"slideNext(swiperContainer)\">\n <ion-icon name=\"chevron-forward\"></ion-icon>\n </div>\n </ng-container>\n\n <!-- image slides -->\n <swiper-container\n #swiperContainer\n [modules]=\"swiperModules\"\n [zoom]=\"!enableMouseZoom\"\n [initialSlide]=\"selectedIndex\"\n (swiperslidechange)=\"onSlideChange(swiperContainer)\"\n (swiperinit)=\"onSwiperInit(swiperContainer)\"\n >\n @for (row of rows; track row.id; let index = $index) {\n <ng-container *ngTemplateOutlet=\"slideTemplate; context: { image: row.currentData, index }\"></ng-container>\n }\n </swiper-container>\n</ion-content>\n\n<ion-footer>\n <ion-toolbar color=\"light\">\n @if (!hasPendingEdit) {\n <ion-row>\n <ion-col size=\"4\" class=\"ion-text-start\">\n @if (!readOnly) {\n <ion-button\n (click)=\"requestDelete(swiperContainer)\"\n [disabled]=\"disabled\"\n fill=\"clear\"\n color=\"danger\"\n >\n <mat-icon slot=\"start\">delete</mat-icon>\n {{ 'COMMON.BTN_DELETE' | translate }}\n </ion-button>\n }\n </ion-col>\n <ion-col size=\"4\"></ion-col>\n <ion-col size=\"4\" class=\"ion-text-end\">\n <ion-button (click)=\"closeRequested.emit()\" color=\"tertiary\" fill=\"clear\" *ngIf=\"mobile; else desktop\">\n <ion-icon slot=\"start\" name=\"close\"></ion-icon>\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n <ng-template #desktop>\n <ion-button (click)=\"closeRequested.emit()\" color=\"tertiary\">\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n </ng-template>\n </ion-col>\n </ion-row>\n } @else {\n <!-- A crop or rotation change is pending: ask for an explicit validation before exporting the image -->\n <ion-row>\n <ion-col size=\"12\" class=\"ion-text-end\">\n <ion-button\n (click)=\"discardEdit(swiperContainer)\"\n color=\"dark\"\n fill=\"clear\"\n [title]=\"!showTooltip ? ('IMAGE.GALLERY.BTN_CANCEL_EDIT' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('IMAGE.GALLERY.BTN_CANCEL_EDIT' | translate) : ''\"\n >\n <ion-icon slot=\"start\" name=\"arrow-undo\"></ion-icon>\n {{ 'COMMON.BTN_CANCEL' | translate }}\n </ion-button>\n <ion-button (click)=\"validateEdit(swiperContainer)\" color=\"danger\">\n <ion-icon slot=\"start\" name=\"checkmark\"></ion-icon>\n {{ 'COMMON.BTN_VALIDATE' | translate }}\n </ion-button>\n </ion-col>\n </ion-row>\n }\n </ion-toolbar>\n</ion-footer>\n\n<ng-template #slideTemplate let-image=\"image\" let-index=\"index\">\n <swiper-slide>\n <div class=\"swiper-zoom-container\" [class.cdk-visually-hidden]=\"!_swiper && index !== selectedIndex\">\n\n <!-- the image -->\n @if (image?.url) {\n <ion-img class=\"swiper-zoom-target\" [src]=\"image.url | appendQueryParams: getImageSizeQueryParams()\" />\n } @else {\n <img [src]=\"image.dataUrl\" [alt]=\"image.title\" />\n }\n\n <!-- crop overlay: only rendered for the active slide -->\n @if (!readOnly && enableCrop && _cropToolActive && index === _activeIndex) {\n <div\n class=\"crop-overlay\"\n (mousedown)=\"onCropPointerDown($event, swiperContainer, 'move')\"\n (touchstart)=\"onCropPointerDown($event, swiperContainer, 'move')\"\n >\n <!-- darkened mask around the selection: clipped to the image bounds -->\n <div class=\"crop-mask\">\n <div\n class=\"crop-mask-rect\"\n [style.left.%]=\"_cropRect.x * 100\"\n [style.top.%]=\"_cropRect.y * 100\"\n [style.width.%]=\"_cropRect.width * 100\"\n [style.height.%]=\"_cropRect.height * 100\"\n ></div>\n </div>\n\n <!-- interactive selection border, grid & drag handles: never clipped, so corner/edge handles\n remain fully grabbable even when the selection touches the image bounds -->\n <div\n class=\"crop-rect\"\n [style.left.%]=\"_cropRect.x * 100\"\n [style.top.%]=\"_cropRect.y * 100\"\n [style.width.%]=\"_cropRect.width * 100\"\n [style.height.%]=\"_cropRect.height * 100\"\n >\n <div class=\"crop-grid\">\n <span class=\"line v\" style=\"left: 33.333%\"></span>\n <span class=\"line v\" style=\"left: 66.666%\"></span>\n <span class=\"line h\" style=\"top: 33.333%\"></span>\n <span class=\"line h\" style=\"top: 66.666%\"></span>\n </div>\n @for (handle of _cropHandles; track handle) {\n <div\n class=\"crop-handle {{ handle }}\"\n (mousedown)=\"onCropPointerDown($event, swiperContainer, handle)\"\n (touchstart)=\"onCropPointerDown($event, swiperContainer, handle)\"\n ></div>\n }\n </div>\n </div>\n }\n </div>\n </swiper-slide>\n</ng-template>\n", styles: [":host{display:flex;flex-direction:column;height:100%;-webkit-user-select:none;user-select:none}:host ion-content{flex:1 1 auto}:host .top-left{z-index:14;position:absolute;display:inline-grid;left:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}:host .top-right{z-index:14;position:absolute;display:inline-grid;right:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}:host .side-buttons{--side-buttons-width: 120px;--side-buttons-margin: calc(var(--side-buttons-width) / 3);z-index:13;position:absolute;top:0;bottom:0;width:var(--side-buttons-width)}:host .side-buttons ion-icon{top:50%;color:#fff;background:rgba(0,0,0,.5);padding:4px;border-radius:50%;font-size:2.5rem;position:absolute;opacity:0;transition-duration:.15s;transition-timing-function:ease-in}:host .side-buttons:hover{cursor:pointer}:host .side-buttons:hover ion-icon{opacity:1}:host .side-buttons.prev{left:0}:host .side-buttons.prev ion-icon{left:var(--side-buttons-margin)}:host .side-buttons.next{right:0}:host .side-buttons.next ion-icon{right:var(--side-buttons-margin)}:host .side-buttons.disabled{pointer-events:none}:host swiper-container{height:100%;background:#000}:host .swiper-zoom-container{position:relative}:host ion-fab-button .icon-secondary{top:11px;left:6px;height:14px}:host .crop-overlay{position:absolute;z-index:15;cursor:move;touch-action:none;animation:crop-overlay-fade-in .15s ease-in}:host .crop-overlay .crop-mask{position:absolute;top:0;right:0;bottom:0;left:0;overflow:hidden;pointer-events:none}:host .crop-overlay .crop-mask .crop-mask-rect{position:absolute;box-shadow:0 0 0 2000px rgba(0,0,0,.6)}:host .crop-overlay .crop-rect{position:absolute;box-sizing:border-box;border:1px solid rgba(255,255,255,.95);cursor:move;touch-action:none}:host .crop-overlay .crop-rect .crop-grid{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none}:host .crop-overlay .crop-rect .crop-grid .line{position:absolute;background:rgba(255,255,255,.45)}:host .crop-overlay .crop-rect .crop-grid .line.v{top:0;bottom:0;width:1px}:host .crop-overlay .crop-rect .crop-grid .line.h{left:0;right:0;height:1px}:host .crop-overlay .crop-rect .crop-handle{position:absolute;width:16px;height:16px;margin:-8px;background:#fff;border:1px solid rgba(0,0,0,.45);border-radius:50%;box-shadow:0 1px 4px rgba(0,0,0,.5);transition:transform .12s ease;touch-action:none}:host .crop-overlay .crop-rect .crop-handle:hover{transform:scale(1.3)}:host .crop-overlay .crop-rect .crop-handle.nw{left:0;top:0;cursor:nwse-resize}:host .crop-overlay .crop-rect .crop-handle.n{left:50%;top:0;cursor:ns-resize}:host .crop-overlay .crop-rect .crop-handle.ne{left:100%;top:0;cursor:nesw-resize}:host .crop-overlay .crop-rect .crop-handle.e{left:100%;top:50%;cursor:ew-resize}:host .crop-overlay .crop-rect .crop-handle.se{left:100%;top:100%;cursor:nwse-resize}:host .crop-overlay .crop-rect .crop-handle.s{left:50%;top:100%;cursor:ns-resize}:host .crop-overlay .crop-rect .crop-handle.sw{left:0;top:100%;cursor:nesw-resize}:host .crop-overlay .crop-rect .crop-handle.w{left:0;top:50%;cursor:ew-resize}@keyframes crop-overlay-fade-in{0%{opacity:0}to{opacity:1}}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i1.IonFabButton, selector: "ion-fab-button", inputs: ["activated", "closeIcon", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "show", "size", "target", "translucent", "type"] }, { kind: "component", type: i1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i1.IonImg, selector: "ion-img", inputs: ["alt", "src"] }, { kind: "component", type: i1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i1.IonRow, selector: "ion-row" }, { kind: "component", type: i1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: i6.ArrayLengthPipe, name: "isArrayLength" }, { kind: "pipe", type: i7.AppendQueryParamsPipePipe, name: "appendQueryParams" }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
738
738
  }
739
739
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AppImageGallerySlideshowComponent, decorators: [{
740
740
  type: Component,
741
- args: [{ selector: 'app-image-gallery-slideshow', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-content\n class=\"ion-no-padding ion-no-margin\"\n (mousedown)=\"onPointerDown($event, swiperContainer)\"\n (mousemove)=\"onPointerMove($event, swiperContainer)\"\n (mouseup)=\"onPointerUp($event, swiperContainer)\"\n (mouseleave)=\"onPointerUp($event, swiperContainer)\"\n (touchmove)=\"onCropPointerMove($event, swiperContainer)\"\n (touchend)=\"onCropPointerUp($event, swiperContainer)\"\n (touchcancel)=\"onCropPointerUp($event, swiperContainer)\"\n>\n @let count = rows?.length || 0;\n <!-- Counter -->\n <div class=\"top-left\">\n <ion-label color=\"light\">{{ _activeIndex + 1 }} / {{ count }}</ion-label>\n </div>\n\n <!-- zoom / rotation / crop buttons: all shown together, no \"enter edit mode\" step needed -->\n <div class=\"top-right\">\n @if (!mobile) {\n <ion-fab-button size=\"small\" (click)=\"zoom(swiperContainer, true)\" color=\"light\">\n <ion-icon name=\"search\"></ion-icon>\n <ion-icon class=\"icon-secondary\" name=\"add\"></ion-icon>\n </ion-fab-button>\n <ion-fab-button size=\"small\" (click)=\"zoom(swiperContainer, false)\" color=\"light\">\n <ion-icon name=\"search\"></ion-icon>\n <ion-icon class=\"icon-secondary\" name=\"remove\"></ion-icon>\n </ion-fab-button>\n }\n @if (!readOnly && enableRotate) {\n <ion-fab-button\n size=\"small\"\n (click)=\"rotate(swiperContainer, 'left')\"\n color=\"light\"\n [title]=\"!showTooltip ? ('IMAGE.GALLERY.BTN_ROTATE_LEFT' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('IMAGE.GALLERY.BTN_ROTATE_LEFT' | translate) : ''\"\n >\n <mat-icon>rotate_left</mat-icon>\n </ion-fab-button>\n <ion-fab-button\n size=\"small\"\n (click)=\"rotate(swiperContainer, 'right')\"\n color=\"light\"\n [title]=\"!showTooltip ? ('IMAGE.GALLERY.BTN_ROTATE_RIGHT' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('IMAGE.GALLERY.BTN_ROTATE_RIGHT' | translate) : ''\"\n >\n <mat-icon>rotate_right</mat-icon>\n </ion-fab-button>\n }\n @if (!readOnly && enableCrop) {\n <ion-fab-button\n size=\"small\"\n (click)=\"toggleCropTool(swiperContainer)\"\n [color]=\"_cropToolActive ? 'tertiary' : 'light'\"\n [title]=\"\n !showTooltip\n ? ((_cropToolActive ? 'IMAGE.GALLERY.BTN_CROP_DEACTIVATE' : 'IMAGE.GALLERY.BTN_CROP_ACTIVATE') | translate)\n : ''\n \"\n [matTooltip]=\"\n showTooltip\n ? ((_cropToolActive ? 'IMAGE.GALLERY.BTN_CROP_DEACTIVATE' : 'IMAGE.GALLERY.BTN_CROP_ACTIVATE') | translate)\n : ''\n \"\n >\n <mat-icon>crop</mat-icon>\n </ion-fab-button>\n @if (_cropToolActive) {\n <ion-fab-button\n size=\"small\"\n (click)=\"resetCrop(swiperContainer)\"\n color=\"light\"\n [title]=\"!showTooltip ? ('IMAGE.GALLERY.BTN_CROP_RESET' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('IMAGE.GALLERY.BTN_CROP_RESET' | translate) : ''\"\n >\n <mat-icon>crop_free</mat-icon>\n </ion-fab-button>\n }\n }\n </div>\n\n <!-- navigation side buttons next/back: hidden while a crop/rotation edit is pending, to keep the focus on validating/cancelling it -->\n <ng-container *ngIf=\"!mobile && !hasPendingEdit && (rows | isArrayLength: { greaterThan: 1 })\">\n <div class=\"side-buttons prev\" [class.disabled]=\"isPrevDisabled\" (click)=\"slidePrev(swiperContainer)\">\n <ion-icon name=\"chevron-back\"></ion-icon>\n </div>\n <div class=\"side-buttons next\" [class.disabled]=\"isNextDisabled\" (click)=\"slideNext(swiperContainer)\">\n <ion-icon name=\"chevron-forward\"></ion-icon>\n </div>\n </ng-container>\n\n <!-- image slides -->\n <swiper-container\n #swiperContainer\n [modules]=\"swiperModules\"\n [zoom]=\"!enableMouseZoom\"\n [initialSlide]=\"selectedIndex\"\n (swiperslidechange)=\"onSlideChange(swiperContainer)\"\n (swiperinit)=\"onSwiperInit(swiperContainer)\"\n >\n @for (row of rows; track row.id; let index = $index) {\n <ng-container *ngTemplateOutlet=\"slideTemplate; context: { image: row.currentData, index }\"></ng-container>\n }\n </swiper-container>\n</ion-content>\n\n<ion-footer>\n <ion-toolbar color=\"light\">\n @if (!hasPendingEdit) {\n <ion-row>\n <ion-col size=\"4\" class=\"ion-text-start\">\n @if (!readOnly) {\n <ion-button\n (click)=\"requestDelete(swiperContainer)\"\n [disabled]=\"disabled\"\n fill=\"clear\"\n color=\"danger\"\n >\n <mat-icon slot=\"start\">delete</mat-icon>\n {{ 'COMMON.BTN_DELETE' | translate }}\n </ion-button>\n }\n </ion-col>\n <ion-col size=\"4\"></ion-col>\n <ion-col size=\"4\" class=\"ion-text-end\">\n <ion-button (click)=\"closeRequested.emit()\" color=\"tertiary\" fill=\"clear\" *ngIf=\"mobile; else desktop\">\n <ion-icon slot=\"start\" name=\"close\"></ion-icon>\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n <ng-template #desktop>\n <ion-button (click)=\"closeRequested.emit()\" color=\"tertiary\">\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n </ng-template>\n </ion-col>\n </ion-row>\n } @else {\n <!-- A crop or rotation change is pending: ask for an explicit validation before exporting the image -->\n <ion-row>\n <ion-col size=\"12\" class=\"ion-text-end\">\n <ion-button\n (click)=\"discardEdit(swiperContainer)\"\n color=\"dark\"\n fill=\"clear\"\n [title]=\"!showTooltip ? ('IMAGE.GALLERY.BTN_CANCEL_EDIT' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('IMAGE.GALLERY.BTN_CANCEL_EDIT' | translate) : ''\"\n >\n <ion-icon slot=\"start\" name=\"arrow-undo\"></ion-icon>\n {{ 'COMMON.BTN_CANCEL' | translate }}\n </ion-button>\n <ion-button (click)=\"validateEdit(swiperContainer)\" color=\"danger\">\n <ion-icon slot=\"start\" name=\"checkmark\"></ion-icon>\n {{ 'COMMON.BTN_VALIDATE' | translate }}\n </ion-button>\n </ion-col>\n </ion-row>\n }\n </ion-toolbar>\n</ion-footer>\n\n<ng-template #slideTemplate let-image=\"image\" let-index=\"index\">\n <swiper-slide>\n <div class=\"swiper-zoom-container\" [class.cdk-visually-hidden]=\"!_swiper && index !== selectedIndex\">\n\n <!-- the image -->\n @if (image?.url) {\n <ion-img class=\"swiper-zoom-target\" [src]=\"image.url | appendQueryParams: getImageSizeQueryParams()\" />\n } @else {\n <img [src]=\"image.dataUrl\" [alt]=\"image.title\" />\n }\n\n <!-- crop overlay: only rendered for the active slide -->\n @if (!readOnly && enableCrop && _cropToolActive && index === _activeIndex) {\n <div\n class=\"crop-overlay\"\n (mousedown)=\"onCropPointerDown($event, swiperContainer, 'move')\"\n (touchstart)=\"onCropPointerDown($event, swiperContainer, 'move')\"\n >\n <!-- darkened mask around the selection: clipped to the image bounds -->\n <div class=\"crop-mask\">\n <div\n class=\"crop-mask-rect\"\n [style.left.%]=\"_cropRect.x * 100\"\n [style.top.%]=\"_cropRect.y * 100\"\n [style.width.%]=\"_cropRect.width * 100\"\n [style.height.%]=\"_cropRect.height * 100\"\n ></div>\n </div>\n\n <!-- interactive selection border, grid & drag handles: never clipped, so corner/edge handles\n remain fully grabbable even when the selection touches the image bounds -->\n <div\n class=\"crop-rect\"\n [style.left.%]=\"_cropRect.x * 100\"\n [style.top.%]=\"_cropRect.y * 100\"\n [style.width.%]=\"_cropRect.width * 100\"\n [style.height.%]=\"_cropRect.height * 100\"\n >\n <div class=\"crop-grid\">\n <span class=\"line v\" style=\"left: 33.333%\"></span>\n <span class=\"line v\" style=\"left: 66.666%\"></span>\n <span class=\"line h\" style=\"top: 33.333%\"></span>\n <span class=\"line h\" style=\"top: 66.666%\"></span>\n </div>\n @for (handle of _cropHandles; track handle) {\n <div\n class=\"crop-handle {{ handle }}\"\n (mousedown)=\"onCropPointerDown($event, swiperContainer, handle)\"\n (touchstart)=\"onCropPointerDown($event, swiperContainer, handle)\"\n ></div>\n }\n </div>\n </div>\n }\n </div>\n </swiper-slide>\n</ng-template>\n", styles: [":host{display:flex;flex-direction:column;height:100%;-webkit-user-select:none;user-select:none}:host ion-content{flex:1 1 auto}:host .top-left{z-index:14;position:absolute;display:inline-grid;left:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}:host .top-right{z-index:14;position:absolute;display:inline-grid;right:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}:host .side-buttons{--side-buttons-width: 120px;--side-buttons-margin: calc(var(--side-buttons-width) / 3);z-index:13;position:absolute;top:0;bottom:0;width:var(--side-buttons-width)}:host .side-buttons ion-icon{top:50%;color:#fff;background:#00000080;padding:4px;border-radius:50%;font-size:2.5rem;position:absolute;opacity:0;transition-duration:.15s;transition-timing-function:ease-in}:host .side-buttons:hover{cursor:pointer}:host .side-buttons:hover ion-icon{opacity:1}:host .side-buttons.prev{left:0}:host .side-buttons.prev ion-icon{left:var(--side-buttons-margin)}:host .side-buttons.next{right:0}:host .side-buttons.next ion-icon{right:var(--side-buttons-margin)}:host .side-buttons.disabled{pointer-events:none}:host swiper-container{height:100%;background:#000}:host .swiper-zoom-container{position:relative}:host ion-fab-button .icon-secondary{top:11px;left:6px;height:14px}:host .crop-overlay{position:absolute;z-index:15;cursor:move;touch-action:none;animation:crop-overlay-fade-in .15s ease-in}:host .crop-overlay .crop-mask{position:absolute;inset:0;overflow:hidden;pointer-events:none}:host .crop-overlay .crop-mask .crop-mask-rect{position:absolute;box-shadow:0 0 0 2000px #0009}:host .crop-overlay .crop-rect{position:absolute;box-sizing:border-box;border:1px solid rgba(255,255,255,.95);cursor:move;touch-action:none}:host .crop-overlay .crop-rect .crop-grid{position:absolute;inset:0;pointer-events:none}:host .crop-overlay .crop-rect .crop-grid .line{position:absolute;background:#ffffff73}:host .crop-overlay .crop-rect .crop-grid .line.v{top:0;bottom:0;width:1px}:host .crop-overlay .crop-rect .crop-grid .line.h{left:0;right:0;height:1px}:host .crop-overlay .crop-rect .crop-handle{position:absolute;width:16px;height:16px;margin:-8px;background:#fff;border:1px solid rgba(0,0,0,.45);border-radius:50%;box-shadow:0 1px 4px #00000080;transition:transform .12s ease;touch-action:none}:host .crop-overlay .crop-rect .crop-handle:hover{transform:scale(1.3)}:host .crop-overlay .crop-rect .crop-handle.nw{left:0;top:0;cursor:nwse-resize}:host .crop-overlay .crop-rect .crop-handle.n{left:50%;top:0;cursor:ns-resize}:host .crop-overlay .crop-rect .crop-handle.ne{left:100%;top:0;cursor:nesw-resize}:host .crop-overlay .crop-rect .crop-handle.e{left:100%;top:50%;cursor:ew-resize}:host .crop-overlay .crop-rect .crop-handle.se{left:100%;top:100%;cursor:nwse-resize}:host .crop-overlay .crop-rect .crop-handle.s{left:50%;top:100%;cursor:ns-resize}:host .crop-overlay .crop-rect .crop-handle.sw{left:0;top:100%;cursor:nesw-resize}:host .crop-overlay .crop-rect .crop-handle.w{left:0;top:50%;cursor:ew-resize}@keyframes crop-overlay-fade-in{0%{opacity:0}to{opacity:1}}\n"] }]
741
+ args: [{ selector: 'app-image-gallery-slideshow', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-content\n class=\"ion-no-padding ion-no-margin\"\n (mousedown)=\"onPointerDown($event, swiperContainer)\"\n (mousemove)=\"onPointerMove($event, swiperContainer)\"\n (mouseup)=\"onPointerUp($event, swiperContainer)\"\n (mouseleave)=\"onPointerUp($event, swiperContainer)\"\n (touchmove)=\"onCropPointerMove($event, swiperContainer)\"\n (touchend)=\"onCropPointerUp($event, swiperContainer)\"\n (touchcancel)=\"onCropPointerUp($event, swiperContainer)\"\n>\n @let count = rows?.length || 0;\n <!-- Counter -->\n <div class=\"top-left\">\n <ion-label color=\"light\">{{ _activeIndex + 1 }} / {{ count }}</ion-label>\n </div>\n\n <!-- zoom / rotation / crop buttons: all shown together, no \"enter edit mode\" step needed -->\n <div class=\"top-right\">\n @if (!mobile) {\n <ion-fab-button size=\"small\" (click)=\"zoom(swiperContainer, true)\" color=\"light\">\n <ion-icon name=\"search\"></ion-icon>\n <ion-icon class=\"icon-secondary\" name=\"add\"></ion-icon>\n </ion-fab-button>\n <ion-fab-button size=\"small\" (click)=\"zoom(swiperContainer, false)\" color=\"light\">\n <ion-icon name=\"search\"></ion-icon>\n <ion-icon class=\"icon-secondary\" name=\"remove\"></ion-icon>\n </ion-fab-button>\n }\n @if (!readOnly && enableRotate) {\n <ion-fab-button\n size=\"small\"\n (click)=\"rotate(swiperContainer, 'left')\"\n color=\"light\"\n [title]=\"!showTooltip ? ('IMAGE.GALLERY.BTN_ROTATE_LEFT' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('IMAGE.GALLERY.BTN_ROTATE_LEFT' | translate) : ''\"\n >\n <mat-icon>rotate_left</mat-icon>\n </ion-fab-button>\n <ion-fab-button\n size=\"small\"\n (click)=\"rotate(swiperContainer, 'right')\"\n color=\"light\"\n [title]=\"!showTooltip ? ('IMAGE.GALLERY.BTN_ROTATE_RIGHT' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('IMAGE.GALLERY.BTN_ROTATE_RIGHT' | translate) : ''\"\n >\n <mat-icon>rotate_right</mat-icon>\n </ion-fab-button>\n }\n @if (!readOnly && enableCrop) {\n <ion-fab-button\n size=\"small\"\n (click)=\"toggleCropTool(swiperContainer)\"\n [color]=\"_cropToolActive ? 'tertiary' : 'light'\"\n [title]=\"\n !showTooltip\n ? ((_cropToolActive ? 'IMAGE.GALLERY.BTN_CROP_DEACTIVATE' : 'IMAGE.GALLERY.BTN_CROP_ACTIVATE') | translate)\n : ''\n \"\n [matTooltip]=\"\n showTooltip\n ? ((_cropToolActive ? 'IMAGE.GALLERY.BTN_CROP_DEACTIVATE' : 'IMAGE.GALLERY.BTN_CROP_ACTIVATE') | translate)\n : ''\n \"\n >\n <mat-icon>crop</mat-icon>\n </ion-fab-button>\n @if (_cropToolActive) {\n <ion-fab-button\n size=\"small\"\n (click)=\"resetCrop(swiperContainer)\"\n color=\"light\"\n [title]=\"!showTooltip ? ('IMAGE.GALLERY.BTN_CROP_RESET' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('IMAGE.GALLERY.BTN_CROP_RESET' | translate) : ''\"\n >\n <mat-icon>crop_free</mat-icon>\n </ion-fab-button>\n }\n }\n </div>\n\n <!-- navigation side buttons next/back: hidden while a crop/rotation edit is pending, to keep the focus on validating/cancelling it -->\n <ng-container *ngIf=\"!mobile && !hasPendingEdit && (rows | isArrayLength: { greaterThan: 1 })\">\n <div class=\"side-buttons prev\" [class.disabled]=\"isPrevDisabled\" (click)=\"slidePrev(swiperContainer)\">\n <ion-icon name=\"chevron-back\"></ion-icon>\n </div>\n <div class=\"side-buttons next\" [class.disabled]=\"isNextDisabled\" (click)=\"slideNext(swiperContainer)\">\n <ion-icon name=\"chevron-forward\"></ion-icon>\n </div>\n </ng-container>\n\n <!-- image slides -->\n <swiper-container\n #swiperContainer\n [modules]=\"swiperModules\"\n [zoom]=\"!enableMouseZoom\"\n [initialSlide]=\"selectedIndex\"\n (swiperslidechange)=\"onSlideChange(swiperContainer)\"\n (swiperinit)=\"onSwiperInit(swiperContainer)\"\n >\n @for (row of rows; track row.id; let index = $index) {\n <ng-container *ngTemplateOutlet=\"slideTemplate; context: { image: row.currentData, index }\"></ng-container>\n }\n </swiper-container>\n</ion-content>\n\n<ion-footer>\n <ion-toolbar color=\"light\">\n @if (!hasPendingEdit) {\n <ion-row>\n <ion-col size=\"4\" class=\"ion-text-start\">\n @if (!readOnly) {\n <ion-button\n (click)=\"requestDelete(swiperContainer)\"\n [disabled]=\"disabled\"\n fill=\"clear\"\n color=\"danger\"\n >\n <mat-icon slot=\"start\">delete</mat-icon>\n {{ 'COMMON.BTN_DELETE' | translate }}\n </ion-button>\n }\n </ion-col>\n <ion-col size=\"4\"></ion-col>\n <ion-col size=\"4\" class=\"ion-text-end\">\n <ion-button (click)=\"closeRequested.emit()\" color=\"tertiary\" fill=\"clear\" *ngIf=\"mobile; else desktop\">\n <ion-icon slot=\"start\" name=\"close\"></ion-icon>\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n <ng-template #desktop>\n <ion-button (click)=\"closeRequested.emit()\" color=\"tertiary\">\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n </ng-template>\n </ion-col>\n </ion-row>\n } @else {\n <!-- A crop or rotation change is pending: ask for an explicit validation before exporting the image -->\n <ion-row>\n <ion-col size=\"12\" class=\"ion-text-end\">\n <ion-button\n (click)=\"discardEdit(swiperContainer)\"\n color=\"dark\"\n fill=\"clear\"\n [title]=\"!showTooltip ? ('IMAGE.GALLERY.BTN_CANCEL_EDIT' | translate) : ''\"\n [matTooltip]=\"showTooltip ? ('IMAGE.GALLERY.BTN_CANCEL_EDIT' | translate) : ''\"\n >\n <ion-icon slot=\"start\" name=\"arrow-undo\"></ion-icon>\n {{ 'COMMON.BTN_CANCEL' | translate }}\n </ion-button>\n <ion-button (click)=\"validateEdit(swiperContainer)\" color=\"danger\">\n <ion-icon slot=\"start\" name=\"checkmark\"></ion-icon>\n {{ 'COMMON.BTN_VALIDATE' | translate }}\n </ion-button>\n </ion-col>\n </ion-row>\n }\n </ion-toolbar>\n</ion-footer>\n\n<ng-template #slideTemplate let-image=\"image\" let-index=\"index\">\n <swiper-slide>\n <div class=\"swiper-zoom-container\" [class.cdk-visually-hidden]=\"!_swiper && index !== selectedIndex\">\n\n <!-- the image -->\n @if (image?.url) {\n <ion-img class=\"swiper-zoom-target\" [src]=\"image.url | appendQueryParams: getImageSizeQueryParams()\" />\n } @else {\n <img [src]=\"image.dataUrl\" [alt]=\"image.title\" />\n }\n\n <!-- crop overlay: only rendered for the active slide -->\n @if (!readOnly && enableCrop && _cropToolActive && index === _activeIndex) {\n <div\n class=\"crop-overlay\"\n (mousedown)=\"onCropPointerDown($event, swiperContainer, 'move')\"\n (touchstart)=\"onCropPointerDown($event, swiperContainer, 'move')\"\n >\n <!-- darkened mask around the selection: clipped to the image bounds -->\n <div class=\"crop-mask\">\n <div\n class=\"crop-mask-rect\"\n [style.left.%]=\"_cropRect.x * 100\"\n [style.top.%]=\"_cropRect.y * 100\"\n [style.width.%]=\"_cropRect.width * 100\"\n [style.height.%]=\"_cropRect.height * 100\"\n ></div>\n </div>\n\n <!-- interactive selection border, grid & drag handles: never clipped, so corner/edge handles\n remain fully grabbable even when the selection touches the image bounds -->\n <div\n class=\"crop-rect\"\n [style.left.%]=\"_cropRect.x * 100\"\n [style.top.%]=\"_cropRect.y * 100\"\n [style.width.%]=\"_cropRect.width * 100\"\n [style.height.%]=\"_cropRect.height * 100\"\n >\n <div class=\"crop-grid\">\n <span class=\"line v\" style=\"left: 33.333%\"></span>\n <span class=\"line v\" style=\"left: 66.666%\"></span>\n <span class=\"line h\" style=\"top: 33.333%\"></span>\n <span class=\"line h\" style=\"top: 66.666%\"></span>\n </div>\n @for (handle of _cropHandles; track handle) {\n <div\n class=\"crop-handle {{ handle }}\"\n (mousedown)=\"onCropPointerDown($event, swiperContainer, handle)\"\n (touchstart)=\"onCropPointerDown($event, swiperContainer, handle)\"\n ></div>\n }\n </div>\n </div>\n }\n </div>\n </swiper-slide>\n</ng-template>\n", styles: [":host{display:flex;flex-direction:column;height:100%;-webkit-user-select:none;user-select:none}:host ion-content{flex:1 1 auto}:host .top-left{z-index:14;position:absolute;display:inline-grid;left:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}:host .top-right{z-index:14;position:absolute;display:inline-grid;right:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}:host .side-buttons{--side-buttons-width: 120px;--side-buttons-margin: calc(var(--side-buttons-width) / 3);z-index:13;position:absolute;top:0;bottom:0;width:var(--side-buttons-width)}:host .side-buttons ion-icon{top:50%;color:#fff;background:rgba(0,0,0,.5);padding:4px;border-radius:50%;font-size:2.5rem;position:absolute;opacity:0;transition-duration:.15s;transition-timing-function:ease-in}:host .side-buttons:hover{cursor:pointer}:host .side-buttons:hover ion-icon{opacity:1}:host .side-buttons.prev{left:0}:host .side-buttons.prev ion-icon{left:var(--side-buttons-margin)}:host .side-buttons.next{right:0}:host .side-buttons.next ion-icon{right:var(--side-buttons-margin)}:host .side-buttons.disabled{pointer-events:none}:host swiper-container{height:100%;background:#000}:host .swiper-zoom-container{position:relative}:host ion-fab-button .icon-secondary{top:11px;left:6px;height:14px}:host .crop-overlay{position:absolute;z-index:15;cursor:move;touch-action:none;animation:crop-overlay-fade-in .15s ease-in}:host .crop-overlay .crop-mask{position:absolute;top:0;right:0;bottom:0;left:0;overflow:hidden;pointer-events:none}:host .crop-overlay .crop-mask .crop-mask-rect{position:absolute;box-shadow:0 0 0 2000px rgba(0,0,0,.6)}:host .crop-overlay .crop-rect{position:absolute;box-sizing:border-box;border:1px solid rgba(255,255,255,.95);cursor:move;touch-action:none}:host .crop-overlay .crop-rect .crop-grid{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none}:host .crop-overlay .crop-rect .crop-grid .line{position:absolute;background:rgba(255,255,255,.45)}:host .crop-overlay .crop-rect .crop-grid .line.v{top:0;bottom:0;width:1px}:host .crop-overlay .crop-rect .crop-grid .line.h{left:0;right:0;height:1px}:host .crop-overlay .crop-rect .crop-handle{position:absolute;width:16px;height:16px;margin:-8px;background:#fff;border:1px solid rgba(0,0,0,.45);border-radius:50%;box-shadow:0 1px 4px rgba(0,0,0,.5);transition:transform .12s ease;touch-action:none}:host .crop-overlay .crop-rect .crop-handle:hover{transform:scale(1.3)}:host .crop-overlay .crop-rect .crop-handle.nw{left:0;top:0;cursor:nwse-resize}:host .crop-overlay .crop-rect .crop-handle.n{left:50%;top:0;cursor:ns-resize}:host .crop-overlay .crop-rect .crop-handle.ne{left:100%;top:0;cursor:nesw-resize}:host .crop-overlay .crop-rect .crop-handle.e{left:100%;top:50%;cursor:ew-resize}:host .crop-overlay .crop-rect .crop-handle.se{left:100%;top:100%;cursor:nwse-resize}:host .crop-overlay .crop-rect .crop-handle.s{left:50%;top:100%;cursor:ns-resize}:host .crop-overlay .crop-rect .crop-handle.sw{left:0;top:100%;cursor:nesw-resize}:host .crop-overlay .crop-rect .crop-handle.w{left:0;top:50%;cursor:ew-resize}@keyframes crop-overlay-fade-in{0%{opacity:0}to{opacity:1}}\n"] }]
742
742
  }], ctorParameters: () => [{ type: i1.AlertController }, { type: i2.TranslateService }, { type: i0.ChangeDetectorRef }], propDecorators: { rows: [{
743
743
  type: Input
744
744
  }], selectedIndex: [{
@@ -78,4 +78,26 @@ export function isMobile(win) {
78
78
  export function isPrint(win) {
79
79
  return matchMedia(win, 'print');
80
80
  }
81
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxhdGZvcm1zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9zaGFyZWQvcGxhdGZvcm1zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztTQUVTO0FBRVQsTUFBTSxNQUFNLEdBQUc7SUFDYixTQUFTLEVBQUUsSUFBSTtJQUNmLE1BQU0sRUFBRSxJQUFJO0lBQ1osT0FBTyxFQUFFLElBQUk7SUFDYixTQUFTLEVBQUUsSUFBSTtDQUNoQixDQUFDO0FBRUYsTUFBTSxVQUFVLFVBQVUsQ0FBQyxHQUFXLEVBQUUsS0FBYTtJQUNuRCxPQUFPLEdBQUcsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDO0FBQ3ZDLENBQUM7QUFFRCxNQUFNLFVBQVUsWUFBWSxDQUFDLEdBQVc7SUFDdEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUN0QixNQUFNLENBQUMsU0FBUyxHQUFHLEdBQUcsQ0FBQyxTQUFTLENBQUMsU0FBUyxJQUFJLEdBQUcsQ0FBQyxTQUFTLENBQUMsTUFBTSxJQUFLLE1BQWMsQ0FBQyxLQUFLLENBQUM7SUFDOUYsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDLFNBQVMsQ0FBQztBQUMxQixDQUFDO0FBRUQsTUFBTSxVQUFVLGFBQWEsQ0FBQyxHQUFXLEVBQUUsSUFBWTtJQUNyRCxNQUFNLFNBQVMsR0FBVyxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDNUMsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBQzlCLENBQUM7QUFFRCxNQUFNLFVBQVUsU0FBUyxDQUFDLEdBQVk7SUFDcEMsT0FBTyxhQUFhLENBQUMsR0FBRyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0FBQ3hDLENBQUM7QUFFRCxNQUFNLFVBQVUsU0FBUyxDQUFDLEdBQVk7SUFDcEMsT0FBTyxhQUFhLENBQUMsR0FBRyxFQUFFLGFBQWEsQ0FBQyxDQUFDO0FBQzNDLENBQUM7QUFFRCxNQUFNLFVBQVUsUUFBUSxDQUFDLEdBQVk7SUFDbkMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxvQkFBb0IsSUFBSSxhQUFhLENBQUMsR0FBRyxFQUFFLFlBQVksQ0FBQyxDQUFDO0FBQ2pGLENBQUM7QUFFRCxNQUFNLFVBQVUsUUFBUSxDQUFDLEdBQVk7SUFDbkMsT0FBTyxhQUFhLENBQUMsR0FBRyxFQUFFLFlBQVksQ0FBQyxDQUFDO0FBQzFDLENBQUM7QUFFRCxNQUFNLFVBQVUsTUFBTSxDQUFDLEdBQVk7SUFDakMsT0FBTyxhQUFhLENBQUMsR0FBRyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBQ3JDLENBQUM7QUFFRCxNQUFNLFVBQVUsU0FBUyxDQUFDLEdBQVk7SUFDcEMsT0FBTyxVQUFVLENBQUMsR0FBRyxFQUFFLHNCQUFzQixDQUFDLENBQUM7QUFDakQsQ0FBQztBQUVELE1BQU0sVUFBVSxNQUFNLENBQUMsR0FBVztJQUNoQyxtQkFBbUI7SUFDbkIsSUFBSSxhQUFhLENBQUMsR0FBRyxFQUFFLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDaEMsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsVUFBVTtJQUNWLElBQUksYUFBYSxDQUFDLEdBQUcsRUFBRSxZQUFZLENBQUMsSUFBSSxTQUFTLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUN2RCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUM7QUFFRCxNQUFNLFVBQVUsT0FBTyxDQUFDLEdBQVc7SUFDakMscUJBQXFCO0lBQ3JCLE9BQU8sYUFBYSxDQUFDLEdBQUcsRUFBRSxZQUFZLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUM3RCxDQUFDO0FBRUQsTUFBTSxVQUFVLEtBQUssQ0FBQyxHQUFXO0lBQy9CLE9BQU8sYUFBYSxDQUFDLEdBQUcsRUFBRSxjQUFjLENBQUMsSUFBSSxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDM0QsQ0FBQztBQUVELE1BQU0sVUFBVSxTQUFTLENBQUMsR0FBVztJQUNuQyxPQUFPLGFBQWEsQ0FBQyxHQUFHLEVBQUUsZUFBZSxDQUFDLENBQUM7QUFDN0MsQ0FBQztBQUVELE1BQU0sVUFBVSxXQUFXLENBQUMsR0FBUTtJQUNsQyxJQUFJLE1BQU0sQ0FBQyxTQUFTLEtBQUssSUFBSSxJQUFJLE1BQU0sQ0FBQyxTQUFTLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDaEUsTUFBTSxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLElBQUksR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7SUFDOUQsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDLFNBQVMsQ0FBQztBQUMxQixDQUFDO0FBRUQsTUFBTSxVQUFVLFFBQVEsQ0FBQyxHQUFXO0lBQ2xDLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxJQUFJLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUMxRCxNQUFNLENBQUMsTUFBTTtZQUNYLFNBQVMsQ0FBQyxHQUFHLENBQUM7Z0JBQ2QsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUNqQyxzRkFBc0Y7Z0JBQ3RGLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDeEMsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQztBQUN2QixDQUFDO0FBRUQsTUFBTSxVQUFVLE9BQU8sQ0FBQyxHQUFZO0lBQ2xDLE9BQU8sVUFBVSxDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQztBQUNsQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogLS0tXG4gKiBTb3VyY2U6IGh0dHBzOi8vZ2l0aHViLmNvbS9pb25pYy10ZWFtL2lvbmljLWZyYW1ld29yay9ibG9iL2IwZDUzY2E3MzYxOTU4NTY3MWQ4Y2Y0ZGMyNGU0N2Y4MjY0OTVhMGEvY29yZS9zcmMvdXRpbHMvcGxhdGZvcm0udHNcbiAqIC0tLSAqL1xuXG5jb25zdCBfY2FjaGUgPSB7XG4gIHVzZXJBZ2VudDogbnVsbCxcbiAgbW9iaWxlOiBudWxsLFxuICBjb3Jkb3ZhOiBudWxsLFxuICBjYXBhY2l0b3I6IG51bGwsXG59O1xuXG5leHBvcnQgZnVuY3Rpb24gbWF0Y2hNZWRpYSh3aW46IFdpbmRvdywgcXVlcnk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gd2luLm1hdGNoTWVkaWEocXVlcnkpLm1hdGNoZXM7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRVc2VyQWdlbnQod2luOiBXaW5kb3cpOiBzdHJpbmcge1xuICBpZiAoIV9jYWNoZS51c2VyQWdlbnQpIHtcbiAgICBfY2FjaGUudXNlckFnZW50ID0gd2luLm5hdmlnYXRvci51c2VyQWdlbnQgfHwgd2luLm5hdmlnYXRvci52ZW5kb3IgfHwgKHdpbmRvdyBhcyBhbnkpLm9wZXJhO1xuICB9XG4gIHJldHVybiBfY2FjaGUudXNlckFnZW50O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdGVzdFVzZXJBZ2VudCh3aW46IFdpbmRvdywgZXhwcjogUmVnRXhwKSB7XG4gIGNvbnN0IHVzZXJBZ2VudDogc3RyaW5nID0gZ2V0VXNlckFnZW50KHdpbik7XG4gIHJldHVybiBleHByLnRlc3QodXNlckFnZW50KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzV2luZG93cyh3aW4/OiBXaW5kb3cpIHtcbiAgcmV0dXJuIHRlc3RVc2VyQWdlbnQod2luLCAvd2luZG93cy9pKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzRmlyZWZveCh3aW4/OiBXaW5kb3cpIHtcbiAgcmV0dXJuIHRlc3RVc2VyQWdlbnQod2luLCAvIGZpcmVmb3hcXC8vaSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1NhZmFyaSh3aW4/OiBXaW5kb3cpIHtcbiAgcmV0dXJuICFpc0Nocm9tZSh3aW4pIC8qRXhjbHVkZSBjaHJvbWl1bSovICYmIHRlc3RVc2VyQWdlbnQod2luLCAvIHNhZmFyaVxcLy9pKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzQ2hyb21lKHdpbj86IFdpbmRvdykge1xuICByZXR1cm4gdGVzdFVzZXJBZ2VudCh3aW4sIC8gY2hyb21lXFwvL2kpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNFZGdlKHdpbj86IFdpbmRvdykge1xuICByZXR1cm4gdGVzdFVzZXJBZ2VudCh3aW4sIC9lZGdlL2kpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNUb3VjaFVpKHdpbj86IFdpbmRvdykge1xuICByZXR1cm4gbWF0Y2hNZWRpYSh3aW4sICcoYW55LXBvaW50ZXI6Y29hcnNlKScpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNJcGFkKHdpbjogV2luZG93KSB7XG4gIC8vIGlPUyAxMiBhbmQgYmVsb3dcbiAgaWYgKHRlc3RVc2VyQWdlbnQod2luLCAvaVBhZC9pKSkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLy8gaU9TIDEzK1xuICBpZiAodGVzdFVzZXJBZ2VudCh3aW4sIC9NYWNpbnRvc2gvaSkgJiYgaXNUb3VjaFVpKHdpbikpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzTWFjT1Mod2luOiBXaW5kb3cpIHtcbiAgLy8gaU9TIChidXQgbm90IGlQYWQpXG4gIHJldHVybiB0ZXN0VXNlckFnZW50KHdpbiwgL01hY2ludG9zaC9pKSAmJiAhaXNUb3VjaFVpKHdpbik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0lPUyh3aW46IFdpbmRvdykge1xuICByZXR1cm4gdGVzdFVzZXJBZ2VudCh3aW4sIC9pUGhvbmV8aVBvZC9pKSB8fCBpc0lwYWQod2luKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzQW5kcm9pZCh3aW46IFdpbmRvdykge1xuICByZXR1cm4gdGVzdFVzZXJBZ2VudCh3aW4sIC9hbmRyb2lkfHNpbmsvaSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0NhcGFjaXRvcih3aW46IGFueSk6IGJvb2xlYW4ge1xuICBpZiAoX2NhY2hlLmNhcGFjaXRvciA9PT0gbnVsbCB8fCBfY2FjaGUuY2FwYWNpdG9yID09PSB1bmRlZmluZWQpIHtcbiAgICBfY2FjaGUuY2FwYWNpdG9yID0gISEod2luWydDYXBhY2l0b3InXSB8fCB3aW5bJ2NhcGFjaXRvciddKTtcbiAgfVxuICByZXR1cm4gX2NhY2hlLmNhcGFjaXRvcjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzTW9iaWxlKHdpbjogV2luZG93KSB7XG4gIGlmIChfY2FjaGUubW9iaWxlID09PSBudWxsIHx8IF9jYWNoZS5tb2JpbGUgPT09IHVuZGVmaW5lZCkge1xuICAgIF9jYWNoZS5tb2JpbGUgPVxuICAgICAgaXNBbmRyb2lkKHdpbikgfHxcbiAgICAgIChpc0lPUyh3aW5kb3cpICYmIGlzVG91Y2hVaSh3aW4pKSB8fFxuICAgICAgLy8gV29ya2Fyb3VuZCwgZm9yIE1TIFdpbmRvd3MgdG91Y2ggc2NyZWVuIChkZXRlY3RlZCBhcyBtb2JpbGUsIGJ1dCBmb3JjZWQgYXMgZGVza3RvcClcbiAgICAgIChpc1RvdWNoVWkod2luKSAmJiAhaXNXaW5kb3dzKHdpbikpO1xuICB9XG4gIHJldHVybiBfY2FjaGUubW9iaWxlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNQcmludCh3aW4/OiBXaW5kb3cpIHtcbiAgcmV0dXJuIG1hdGNoTWVkaWEod2luLCAncHJpbnQnKTtcbn1cbiJdfQ==
81
+ export function isWebAnimationsSupported() {
82
+ if (typeof document === 'undefined' || typeof Element === 'undefined') {
83
+ return false;
84
+ }
85
+ if (typeof Element.prototype.animate !== 'function') {
86
+ return false;
87
+ }
88
+ try {
89
+ // Test minimal
90
+ const el = document.createElement('div');
91
+ // On n’append plus forcément au body
92
+ const animation = el.animate([{ opacity: 0.5, offset: 0.5 }, { opacity: 1 }], { duration: 1 });
93
+ animation.cancel();
94
+ console.debug('[app] Web animations are well supported');
95
+ return true;
96
+ }
97
+ catch {
98
+ // Continue
99
+ }
100
+ console.warn('[app] Web animations are not supported');
101
+ return false;
102
+ }
103
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGxhdGZvcm1zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9zaGFyZWQvcGxhdGZvcm1zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztTQUVTO0FBRVQsTUFBTSxNQUFNLEdBQUc7SUFDYixTQUFTLEVBQUUsSUFBSTtJQUNmLE1BQU0sRUFBRSxJQUFJO0lBQ1osT0FBTyxFQUFFLElBQUk7SUFDYixTQUFTLEVBQUUsSUFBSTtDQUNoQixDQUFDO0FBRUYsTUFBTSxVQUFVLFVBQVUsQ0FBQyxHQUFXLEVBQUUsS0FBYTtJQUNuRCxPQUFPLEdBQUcsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDO0FBQ3ZDLENBQUM7QUFFRCxNQUFNLFVBQVUsWUFBWSxDQUFDLEdBQVc7SUFDdEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUN0QixNQUFNLENBQUMsU0FBUyxHQUFHLEdBQUcsQ0FBQyxTQUFTLENBQUMsU0FBUyxJQUFJLEdBQUcsQ0FBQyxTQUFTLENBQUMsTUFBTSxJQUFLLE1BQWMsQ0FBQyxLQUFLLENBQUM7SUFDOUYsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDLFNBQVMsQ0FBQztBQUMxQixDQUFDO0FBRUQsTUFBTSxVQUFVLGFBQWEsQ0FBQyxHQUFXLEVBQUUsSUFBWTtJQUNyRCxNQUFNLFNBQVMsR0FBVyxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDNUMsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBQzlCLENBQUM7QUFFRCxNQUFNLFVBQVUsU0FBUyxDQUFDLEdBQVk7SUFDcEMsT0FBTyxhQUFhLENBQUMsR0FBRyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0FBQ3hDLENBQUM7QUFFRCxNQUFNLFVBQVUsU0FBUyxDQUFDLEdBQVk7SUFDcEMsT0FBTyxhQUFhLENBQUMsR0FBRyxFQUFFLGFBQWEsQ0FBQyxDQUFDO0FBQzND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QUNmLENBQUM7SUFFRCxJQUFJLE9BQU8sT0FBTyxDQUFDLFNBQVMsQ0FBQyxPQUFPLEtBQUssVUFBVSxFQUFFLENBQUM7UUFDcEQsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQsSUFBSSxDQUFDO1FBQ0gsZUFBZTtRQUNmLE1BQU0sRUFBRSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFekMscUNBQXFDO1FBQ3JDLE1BQU0sU0FBUyxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQzFCLENBQUMsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUMvQyxFQUFFLFFBQVEsRUFBRSxDQUFDLEVBQUUsQ0FDaEIsQ0FBQztRQUNGLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUVuQixPQUFPLENBQUMsS0FBSyxDQUFDLHlDQUF5QyxDQUFDLENBQUM7UUFDekQsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsV0FBVztJQUNiLENBQUM7SUFFRCxPQUFPLENBQUMsSUFBSSxDQUFDLHdDQUF3QyxDQUFDLENBQUM7SUFDdkQsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogLS0tXG4gKiBTb3VyY2U6IGh0dHBzOi8vZ2l0aHViLmNvbS9pb25pYy10ZWFtL2lvbmljLWZyYW1ld29yay9ibG9iL2IwZDUzY2E3MzYxOTU4NTY3MWQ4Y2Y0ZGMyNGU0N2Y4MjY0OTVhMGEvY29yZS9zcmMvdXRpbHMvcGxhdGZvcm0udHNcbiAqIC0tLSAqL1xuXG5jb25zdCBfY2FjaGUgPSB7XG4gIHVzZXJBZ2VudDogbnVsbCxcbiAgbW9iaWxlOiBudWxsLFxuICBjb3Jkb3ZhOiBudWxsLFxuICBjYXBhY2l0b3I6IG51bGwsXG59O1xuXG5leHBvcnQgZnVuY3Rpb24gbWF0Y2hNZWRpYSh3aW46IFdpbmRvdywgcXVlcnk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gd2luLm1hdGNoTWVkaWEocXVlcnkpLm1hdGNoZXM7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRVc2VyQWdlbnQod2luOiBXaW5kb3cpOiBzdHJpbmcge1xuICBpZiAoIV9jYWNoZS51c2VyQWdlbnQpIHtcbiAgICBfY2FjaGUudXNlckFnZW50ID0gd2luLm5hdmlnYXRvci51c2VyQWdlbnQgfHwgd2luLm5hdmlnYXRvci52ZW5kb3IgfHwgKHdpbmRvdyBhcyBhbnkpLm9wZXJhO1xuICB9XG4gIHJldHVybiBfY2FjaGUudXNlckFnZW50O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdGVzdFVzZXJBZ2VudCh3aW46IFdpbmRvdywgZXhwcjogUmVnRXhwKSB7XG4gIGNvbnN0IHVzZXJBZ2VudDogc3RyaW5nID0gZ2V0VXNlckFnZW50KHdpbik7XG4gIHJldHVybiBleHByLnRlc3QodXNlckFnZW50KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzV2luZG93cyh3aW4/OiBXaW5kb3cpIHtcbiAgcmV0dXJuIHRlc3RVc2VyQWdlbnQod2luLCAvd2luZG93cy9pKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzRmlyZWZveCh3aW4/OiBXaW5kb3cpIHtcbiAgcmV0dXJuIHRlc3RVc2VyQWdlbnQod2luLCAvIGZpcmVmb3hcXC8vaSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1NhZmFyaSh3aW4/OiBXaW5kb3cpIHtcbiAgcmV0dXJuICFpc0Nocm9tZSh3aW4pIC8qRXhjbHVkZSBjaHJvbWl1bSovICYmIHRlc3RVc2VyQWdlbnQod2luLCAvIHNhZmFyaVxcLy9pKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzQ2hyb21lKHdpbj86IFdpbmRvdykge1xuICByZXR1cm4gdGVzdFVzZXJBZ2VudCh3aW4sIC8gY2hyb21lXFwvL2kpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNFZGdlKHdpbj86IFdpbmRvdykge1xuICByZXR1cm4gdGVzdFVzZXJBZ2VudCh3aW4sIC9lZGdlL2kpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNUb3VjaFVpKHdpbj86IFdpbmRvdykge1xuICByZXR1cm4gbWF0Y2hNZWRpYSh3aW4sICcoYW55LXBvaW50ZXI6Y29hcnNlKScpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNJcGFkKHdpbjogV2luZG93KSB7XG4gIC8vIGlPUyAxMiBhbmQgYmVsb3dcbiAgaWYgKHRlc3RVc2VyQWdlbnQod2luLCAvaVBhZC9pKSkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLy8gaU9TIDEzK1xuICBpZiAodGVzdFVzZXJBZ2VudCh3aW4sIC9NYWNpbnRvc2gvaSkgJiYgaXNUb3VjaFVpKHdpbikpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzTWFjT1Mod2luOiBXaW5kb3cpIHtcbiAgLy8gaU9TIChidXQgbm90IGlQYWQpXG4gIHJldHVybiB0ZXN0VXNlckFnZW50KHdpbiwgL01hY2ludG9zaC9pKSAmJiAhaXNUb3VjaFVpKHdpbik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0lPUyh3aW46IFdpbmRvdykge1xuICByZXR1cm4gdGVzdFVzZXJBZ2VudCh3aW4sIC9pUGhvbmV8aVBvZC9pKSB8fCBpc0lwYWQod2luKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzQW5kcm9pZCh3aW46IFdpbmRvdykge1xuICByZXR1cm4gdGVzdFVzZXJBZ2VudCh3aW4sIC9hbmRyb2lkfHNpbmsvaSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0NhcGFjaXRvcih3aW46IGFueSk6IGJvb2xlYW4ge1xuICBpZiAoX2NhY2hlLmNhcGFjaXRvciA9PT0gbnVsbCB8fCBfY2FjaGUuY2FwYWNpdG9yID09PSB1bmRlZmluZWQpIHtcbiAgICBfY2FjaGUuY2FwYWNpdG9yID0gISEod2luWydDYXBhY2l0b3InXSB8fCB3aW5bJ2NhcGFjaXRvciddKTtcbiAgfVxuICByZXR1cm4gX2NhY2hlLmNhcGFjaXRvcjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzTW9iaWxlKHdpbjogV2luZG93KSB7XG4gIGlmIChfY2FjaGUubW9iaWxlID09PSBudWxsIHx8IF9jYWNoZS5tb2JpbGUgPT09IHVuZGVmaW5lZCkge1xuICAgIF9jYWNoZS5tb2JpbGUgPVxuICAgICAgaXNBbmRyb2lkKHdpbikgfHxcbiAgICAgIChpc0lPUyh3aW5kb3cpICYmIGlzVG91Y2hVaSh3aW4pKSB8fFxuICAgICAgLy8gV29ya2Fyb3VuZCwgZm9yIE1TIFdpbmRvd3MgdG91Y2ggc2NyZWVuIChkZXRlY3RlZCBhcyBtb2JpbGUsIGJ1dCBmb3JjZWQgYXMgZGVza3RvcClcbiAgICAgIChpc1RvdWNoVWkod2luKSAmJiAhaXNXaW5kb3dzKHdpbikpO1xuICB9XG4gIHJldHVybiBfY2FjaGUubW9iaWxlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNQcmludCh3aW4/OiBXaW5kb3cpIHtcbiAgcmV0dXJuIG1hdGNoTWVkaWEod2luLCAncHJpbnQnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzV2ViQW5pbWF0aW9uc1N1cHBvcnRlZCgpOiBib29sZWFuIHtcbiAgaWYgKHR5cGVvZiBkb2N1bWVudCA9PT0gJ3VuZGVmaW5lZCcgfHwgdHlwZW9mIEVsZW1lbnQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBFbGVtZW50LnByb3RvdHlwZS5hbmltYXRlICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgdHJ5IHtcbiAgICAvLyBUZXN0IG1pbmltYWxcbiAgICBjb25zdCBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuXG4gICAgLy8gT24gbuKAmWFwcGVuZCBwbHVzIGZvcmPDqW1lbnQgYXUgYm9keVxuICAgIGNvbnN0IGFuaW1hdGlvbiA9IGVsLmFuaW1hdGUoXG4gICAgICBbeyBvcGFjaXR5OiAwLjUsIG9mZnNldDogMC41IH0sIHsgb3BhY2l0eTogMSB9XSxcbiAgICAgIHsgZHVyYXRpb246IDEgfVxuICAgICk7XG4gICAgYW5pbWF0aW9uLmNhbmNlbCgpO1xuXG4gICAgY29uc29sZS5kZWJ1ZygnW2FwcF0gV2ViIGFuaW1hdGlvbnMgYXJlIHdlbGwgc3VwcG9ydGVkJyk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0gY2F0Y2gge1xuICAgIC8vIENvbnRpbnVlXG4gIH1cblxuICBjb25zb2xlLndhcm4oJ1thcHBdIFdlYiBhbmltYXRpb25zIGFyZSBub3Qgc3VwcG9ydGVkJyk7XG4gIHJldHVybiBmYWxzZTtcbn1cbiJdfQ==
@@ -10,14 +10,12 @@ export class UploadFilePopover {
10
10
  cd;
11
11
  uploader;
12
12
  fileExtension;
13
- fileExtensionsExcluded = [];
14
13
  title;
15
14
  uniqueFile = false;
16
15
  instantUpload = false;
17
16
  uploadFn;
18
17
  deleteFn;
19
18
  maxParallelUpload;
20
- maxFileSizeMb;
21
19
  autoHideDropArea = false;
22
20
  okButtonText = 'COMMON.BTN_IMPORT';
23
21
  cancelButtonText = 'COMMON.BTN_CANCEL';
@@ -27,7 +25,7 @@ export class UploadFilePopover {
27
25
  return this.uploader.files;
28
26
  }
29
27
  get disabled() {
30
- return this.importing || isEmptyArray(this.files) || this.files.every((file) => file.error);
28
+ return this.importing || isEmptyArray(this.files);
31
29
  }
32
30
  get valid() {
33
31
  return isNotEmptyArray(this.files);
@@ -84,18 +82,16 @@ export class UploadFilePopover {
84
82
  }
85
83
  }
86
84
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: UploadFilePopover, deps: [{ token: i1.PopoverController }, { token: i2.TranslateService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
87
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: UploadFilePopover, selector: "app-upload-file-popover", inputs: { fileExtension: "fileExtension", fileExtensionsExcluded: "fileExtensionsExcluded", title: "title", uniqueFile: "uniqueFile", instantUpload: "instantUpload", uploadFn: "uploadFn", deleteFn: "deleteFn", maxParallelUpload: "maxParallelUpload", maxFileSizeMb: "maxFileSizeMb", autoHideDropArea: "autoHideDropArea", okButtonText: "okButtonText", cancelButtonText: "cancelButtonText" }, viewQueries: [{ propertyName: "uploader", first: true, predicate: ["uploader"], descendants: true, static: true }], ngImport: i0, template: "<ion-content class=\"ion-no-padding\" scrollY=\"false\">\n <app-upload-file\n #uploader\n [uploadFn]=\"uploadFn\"\n [deleteFn]=\"deleteFn\"\n [fileExtension]=\"fileExtension\"\n [fileExtensionsExcluded]=\"fileExtensionsExcluded\"\n [instantUpload]=\"instantUpload\"\n [uniqueFile]=\"uniqueFile\"\n [maxParallelUpload]=\"maxParallelUpload\"\n [maxFileSizeMb]=\"maxFileSizeMb\"\n [autoHideDropArea]=\"autoHideDropArea\"\n ></app-upload-file>\n</ion-content>\n\n<ion-footer>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding ion-nowrap\" >\n <ion-col>\n @if (importing) {\n <div class=\"importing-info\">\n <ion-text color=\"medium\"><small translate>FILE.UPLOAD.IMPORTING</small></ion-text>\n &nbsp;\n <ion-spinner name=\"dots\" color=\"accent\"></ion-spinner>\n </div>\n }\n @if (error) {\n <ion-item lines=\"none\" color=\"transparent\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"ion-text-wrap\">\n <small [innerHTML]=\"error | translate\"></small>\n </ion-label>\n </ion-item>\n }\n </ion-col>\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"cancel()\">\n <ion-label [innerHTML]=\"cancelButtonText | translate\"></ion-label>\n </ion-button>\n <ion-button\n [fill]=\"disabled ? 'clear' : 'solid'\"\n (click)=\"onValidate($event)\"\n (keyup.enter)=\"onValidate($event)\"\n color=\"tertiary\"\n [disabled]=\"disabled\"\n >\n <ion-label [innerHTML]=\"okButtonText | translate\"></ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n</ion-footer>\n", styles: [".importing-info{padding-inline-start:var(--ion-padding);display:inline-flex;flex-wrap:nowrap;padding-top:8px}\n"], dependencies: [{ kind: "component", type: i1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i1.IonRow, selector: "ion-row" }, { kind: "component", type: i1.IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: i1.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: i1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "directive", type: i2.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "component", type: i3.UploadFileComponent, selector: "app-upload-file", inputs: ["fileExtension", "fileExtensionsExcluded", "uniqueFile", "instantUpload", "uploadFn", "deleteFn", "maxParallelUpload", "maxFileSizeMb", "autoHideDropArea"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
85
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: UploadFilePopover, selector: "app-upload-file-popover", inputs: { fileExtension: "fileExtension", title: "title", uniqueFile: "uniqueFile", instantUpload: "instantUpload", uploadFn: "uploadFn", deleteFn: "deleteFn", maxParallelUpload: "maxParallelUpload", autoHideDropArea: "autoHideDropArea", okButtonText: "okButtonText", cancelButtonText: "cancelButtonText" }, viewQueries: [{ propertyName: "uploader", first: true, predicate: ["uploader"], descendants: true, static: true }], ngImport: i0, template: "<ion-content class=\"ion-no-padding\" scrollY=\"false\">\n <app-upload-file\n #uploader\n [uploadFn]=\"uploadFn\"\n [deleteFn]=\"deleteFn\"\n [fileExtension]=\"fileExtension\"\n [instantUpload]=\"instantUpload\"\n [uniqueFile]=\"uniqueFile\"\n [maxParallelUpload]=\"maxParallelUpload\"\n [autoHideDropArea]=\"autoHideDropArea\"\n ></app-upload-file>\n</ion-content>\n\n<ion-footer>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding ion-nowrap\" >\n <ion-col>\n @if (importing) {\n <div class=\"importing-info\">\n <ion-text color=\"medium\"><small translate>FILE.UPLOAD.IMPORTING</small></ion-text>\n &nbsp;\n <ion-spinner name=\"dots\" color=\"accent\"></ion-spinner>\n </div>\n }\n @if (error) {\n <ion-item lines=\"none\" color=\"transparent\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"ion-text-wrap\">\n <small [innerHTML]=\"error | translate\"></small>\n </ion-label>\n </ion-item>\n }\n </ion-col>\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"cancel()\">\n <ion-label [innerHTML]=\"cancelButtonText | translate\"></ion-label>\n </ion-button>\n <ion-button\n [fill]=\"disabled ? 'clear' : 'solid'\"\n (click)=\"onValidate($event)\"\n (keyup.enter)=\"onValidate($event)\"\n color=\"tertiary\"\n [disabled]=\"disabled\"\n >\n <ion-label [innerHTML]=\"okButtonText | translate\"></ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n</ion-footer>\n", styles: [".importing-info{padding-inline-start:var(--ion-padding);display:inline-flex;flex-wrap:nowrap;padding-top:8px}\n"], dependencies: [{ kind: "component", type: i1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i1.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i1.IonRow, selector: "ion-row" }, { kind: "component", type: i1.IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: i1.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: i1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "directive", type: i2.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "component", type: i3.UploadFileComponent, selector: "app-upload-file", inputs: ["fileExtension", "uniqueFile", "instantUpload", "uploadFn", "deleteFn", "maxParallelUpload", "autoHideDropArea"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
88
86
  }
89
87
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: UploadFilePopover, decorators: [{
90
88
  type: Component,
91
- args: [{ selector: 'app-upload-file-popover', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-content class=\"ion-no-padding\" scrollY=\"false\">\n <app-upload-file\n #uploader\n [uploadFn]=\"uploadFn\"\n [deleteFn]=\"deleteFn\"\n [fileExtension]=\"fileExtension\"\n [fileExtensionsExcluded]=\"fileExtensionsExcluded\"\n [instantUpload]=\"instantUpload\"\n [uniqueFile]=\"uniqueFile\"\n [maxParallelUpload]=\"maxParallelUpload\"\n [maxFileSizeMb]=\"maxFileSizeMb\"\n [autoHideDropArea]=\"autoHideDropArea\"\n ></app-upload-file>\n</ion-content>\n\n<ion-footer>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding ion-nowrap\" >\n <ion-col>\n @if (importing) {\n <div class=\"importing-info\">\n <ion-text color=\"medium\"><small translate>FILE.UPLOAD.IMPORTING</small></ion-text>\n &nbsp;\n <ion-spinner name=\"dots\" color=\"accent\"></ion-spinner>\n </div>\n }\n @if (error) {\n <ion-item lines=\"none\" color=\"transparent\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"ion-text-wrap\">\n <small [innerHTML]=\"error | translate\"></small>\n </ion-label>\n </ion-item>\n }\n </ion-col>\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"cancel()\">\n <ion-label [innerHTML]=\"cancelButtonText | translate\"></ion-label>\n </ion-button>\n <ion-button\n [fill]=\"disabled ? 'clear' : 'solid'\"\n (click)=\"onValidate($event)\"\n (keyup.enter)=\"onValidate($event)\"\n color=\"tertiary\"\n [disabled]=\"disabled\"\n >\n <ion-label [innerHTML]=\"okButtonText | translate\"></ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n</ion-footer>\n", styles: [".importing-info{padding-inline-start:var(--ion-padding);display:inline-flex;flex-wrap:nowrap;padding-top:8px}\n"] }]
89
+ args: [{ selector: 'app-upload-file-popover', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-content class=\"ion-no-padding\" scrollY=\"false\">\n <app-upload-file\n #uploader\n [uploadFn]=\"uploadFn\"\n [deleteFn]=\"deleteFn\"\n [fileExtension]=\"fileExtension\"\n [instantUpload]=\"instantUpload\"\n [uniqueFile]=\"uniqueFile\"\n [maxParallelUpload]=\"maxParallelUpload\"\n [autoHideDropArea]=\"autoHideDropArea\"\n ></app-upload-file>\n</ion-content>\n\n<ion-footer>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding ion-nowrap\" >\n <ion-col>\n @if (importing) {\n <div class=\"importing-info\">\n <ion-text color=\"medium\"><small translate>FILE.UPLOAD.IMPORTING</small></ion-text>\n &nbsp;\n <ion-spinner name=\"dots\" color=\"accent\"></ion-spinner>\n </div>\n }\n @if (error) {\n <ion-item lines=\"none\" color=\"transparent\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"ion-text-wrap\">\n <small [innerHTML]=\"error | translate\"></small>\n </ion-label>\n </ion-item>\n }\n </ion-col>\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"cancel()\">\n <ion-label [innerHTML]=\"cancelButtonText | translate\"></ion-label>\n </ion-button>\n <ion-button\n [fill]=\"disabled ? 'clear' : 'solid'\"\n (click)=\"onValidate($event)\"\n (keyup.enter)=\"onValidate($event)\"\n color=\"tertiary\"\n [disabled]=\"disabled\"\n >\n <ion-label [innerHTML]=\"okButtonText | translate\"></ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n</ion-footer>\n", styles: [".importing-info{padding-inline-start:var(--ion-padding);display:inline-flex;flex-wrap:nowrap;padding-top:8px}\n"] }]
92
90
  }], ctorParameters: () => [{ type: i1.PopoverController }, { type: i2.TranslateService }, { type: i0.ChangeDetectorRef }], propDecorators: { uploader: [{
93
91
  type: ViewChild,
94
92
  args: ['uploader', { static: true }]
95
93
  }], fileExtension: [{
96
94
  type: Input
97
- }], fileExtensionsExcluded: [{
98
- type: Input
99
95
  }], title: [{
100
96
  type: Input
101
97
  }], uniqueFile: [{
@@ -108,8 +104,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
108
104
  type: Input
109
105
  }], maxParallelUpload: [{
110
106
  type: Input
111
- }], maxFileSizeMb: [{
112
- type: Input
113
107
  }], autoHideDropArea: [{
114
108
  type: Input
115
109
  }], okButtonText: [{
@@ -117,4 +111,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
117
111
  }], cancelButtonText: [{
118
112
  type: Input
119
113
  }] } });
120
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBsb2FkLWZpbGUtcG9wb3Zlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBwL3NoYXJlZC91cGxvYWQtZmlsZS91cGxvYWQtZmlsZS1wb3BvdmVyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvc2hhcmVkL3VwbG9hZC1maWxlL3VwbG9hZC1maWxlLXBvcG92ZXIuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLHVCQUF1QixFQUFxQixTQUFTLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUkzSCxPQUFPLEVBQUUsWUFBWSxFQUFFLGVBQWUsRUFBRSxlQUFlLEVBQUUsTUFBTSxjQUFjLENBQUM7Ozs7O0FBa0M5RSxNQUFNLE9BQU8saUJBQWlCO0lBZ0NoQjtJQUNBO0lBQ0E7SUFqQzZCLFFBQVEsQ0FBc0I7SUFFOUQsYUFBYSxDQUFTO0lBQ3RCLHNCQUFzQixHQUFhLEVBQUUsQ0FBQztJQUN0QyxLQUFLLENBQVM7SUFDZCxVQUFVLEdBQUcsS0FBSyxDQUFDO0lBQ25CLGFBQWEsR0FBRyxLQUFLLENBQUM7SUFDdEIsUUFBUSxDQUFvQjtJQUM1QixRQUFRLENBQW9CO0lBQzVCLGlCQUFpQixDQUFTO0lBQzFCLGFBQWEsQ0FBUztJQUN0QixnQkFBZ0IsR0FBRyxLQUFLLENBQUM7SUFDekIsWUFBWSxHQUFHLG1CQUFtQixDQUFDO0lBQ25DLGdCQUFnQixHQUFHLG1CQUFtQixDQUFDO0lBRWhELFNBQVMsR0FBRyxLQUFLLENBQUM7SUFDbEIsS0FBSyxDQUFTO0lBRWQsSUFBSSxLQUFLO1FBQ1AsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQztJQUM3QixDQUFDO0lBRUQsSUFBSSxRQUFRO1FBQ1YsT0FBTyxJQUFJLENBQUMsU0FBUyxJQUFJLFlBQVks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akIsaUJBQWlCLHlqQkN0QzlCLGcxREFvREE7OzRGRGRhLGlCQUFpQjtrQkFQN0IsU0FBUzsrQkFDRSx5QkFBeUIsaUJBR3BCLGlCQUFpQixDQUFDLElBQUksbUJBQ3BCLHVCQUF1QixDQUFDLE1BQU07cUpBR04sUUFBUTtzQkFBaEQsU0FBUzt1QkFBQyxVQUFVLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUU5QixhQUFhO3NCQUFyQixLQUFLO2dCQUNHLHNCQUFzQjtzQkFBOUIsS0FBSztnQkFDRyxLQUFLO3NCQUFiLEtBQUs7Z0JBQ0csVUFBVTtzQkFBbEIsS0FBSztnQkFDRyxhQUFhO3NCQUFyQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxpQkFBaUI7c0JBQXpCLEtBQUs7Z0JBQ0csYUFBYTtzQkFBckIsS0FBSztnQkFDRyxnQkFBZ0I7c0JBQXhCLEtBQUs7Z0JBQ0csWUFBWTtzQkFBcEIsS0FBSztnQkFDRyxnQkFBZ0I7c0JBQXhCLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ2hhbmdlRGV0ZWN0b3JSZWYsIENvbXBvbmVudCwgSW5wdXQsIFZpZXdDaGlsZCwgVmlld0VuY2Fwc3VsYXRpb24gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFBvcG92ZXJDb250cm9sbGVyIH0gZnJvbSAnQGlvbmljL2FuZ3VsYXInO1xuaW1wb3J0IHsgVXBsb2FkRmlsZUNvbXBvbmVudCB9IGZyb20gJy4vdXBsb2FkLWZpbGUuY29tcG9uZW50JztcbmltcG9ydCB7IEZpbGVEZWxldGVGbiwgRmlsZVVwbG9hZEZuLCBVcGxvYWRGaWxlIH0gZnJvbSAnLi91cGxvYWQtZmlsZS5tb2RlbCc7XG5pbXBvcnQgeyBpc0VtcHR5QXJyYXksIGlzTm90RW1wdHlBcnJheSwgaXNOb3ROaWxPckJsYW5rIH0gZnJvbSAnLi4vZnVuY3Rpb25zJztcbmltcG9ydCB7IFRyYW5zbGF0ZVNlcnZpY2UgfSBmcm9tICdAbmd4LXRyYW5zbGF0ZS9jb3JlJztcblxuZXhwb3J0IGludGVyZmFjZSBVcGxvYWRGaWxlUG9wb3Zlck9wdGlvbnM8VD4ge1xuICB0aXRsZT86IHN0cmluZztcblxuICB1cGxvYWRGbjogRmlsZVVwbG9hZEZuPFQ+O1xuICBkZWxldGVGbj86IEZpbGVEZWxldGVGbjxhbnk+O1xuXG4gIGluc3RhbnRVcGxvYWQ/OiBib29sZWFuO1xuICB1bmlxdWVGaWxlPzogYm9vbGVhbjtcbiAgZmlsZUV4dGVuc2lvbj86IHN0cmluZztcbiAgZmlsZUV4dGVuc2lvbnNFeGNsdWRlZD86IHN0cmluZ1tdO1xuICBtYXhQYXJhbGxlbFVwbG9hZD86IG51bWJlcjtcbiAgbWF4RmlsZVNpemVNYj86IG51bWJlcjtcbiAgYXV0b0hpZGVEcm9wQXJlYT86IGJvb2xlYW47XG5cbiAgb2tCdXR0b25UZXh0Pzogc3RyaW5nO1xuICBjYW5jZWxCdXR0b25UZXh0Pzogc3RyaW5nO1xuXG4gIC8vIFByb3BlcnRpZXMgb2YgaW9uLXBvcG92ZXJcbiAgYmFja2Ryb3BEaXNtaXNzPzogYm9vbGVhbjsgLy8gZmFsc2UgYnkgZGVmYXVsdFxuICBrZXlib2FyZENsb3NlPzogYm9vbGVhbjsgLy8gZmFsc2UgYnkgZGVmYXVsdFxuICB0cmFuc2x1Y2VudD86IGJvb2xlYW47IC8vIHRydWUgYnkgZGVmYXVsdFxuICBjc3NDbGFzcz86IHN0cmluZyB8IHN0cmluZ1tdO1xufVxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdhcHAtdXBsb2FkLWZpbGUtcG9wb3ZlcicsXG4gIHRlbXBsYXRlVXJsOiAnLi91cGxvYWQtZmlsZS1wb3BvdmVyLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vdXBsb2FkLWZpbGUtcG9wb3Zlci5jb21wb25lbnQuc2NzcyddLFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgVXBsb2FkRmlsZVBvcG92ZXIgaW1wbGVtZW50cyBVcGxvYWRGaWxlUG9wb3Zlck9wdGlvbnM8YW55PiB7XG4gIEBWaWV3Q2hpbGQoJ3VwbG9hZGVyJywgeyBzdGF0aWM6IHRydWUgfSkgdXBsb2FkZXI6IFVwbG9hZEZpbGVDb21wb25lbnQ7XG5cbiAgQElucHV0KCkgZmlsZUV4dGVuc2lvbjogc3RyaW5nO1xuICBASW5wdXQoKSBmaWxlRXh0ZW5zaW9uc0V4Y2x1ZGVkOiBzdHJpbmdbXSA9IFtdO1xuICBASW5wdXQoKSB0aXRsZTogc3RyaW5nO1xuICBASW5wdXQoKSB1bmlxdWVGaWxlID0gZmFsc2U7XG4gIEBJbnB1dCgpIGluc3RhbnRVcGxvYWQgPSBmYWxzZTtcbiAgQElucHV0KCkgdXBsb2FkRm46IEZpbGVVcGxvYWRGbjxhbnk+O1xuICBASW5wdXQoKSBkZWxldGVGbjogRmlsZURlbGV0ZUZuPGFueT47XG4gIEBJbnB1dCgpIG1heFBhcmFsbGVsVXBsb2FkOiBudW1iZXI7XG4gIEBJbnB1dCgpIG1heEZpbGVTaXplTWI6IG51bWJlcjtcbiAgQElucHV0KCkgYXV0b0hpZGVEcm9wQXJlYSA9IGZhbHNlO1xuICBASW5wdXQoKSBva0J1dHRvblRleHQgPSAnQ09NTU9OLkJUTl9JTVBPUlQnO1xuICBASW5wdXQoKSBjYW5jZWxCdXR0b25UZXh0ID0gJ0NPTU1PTi5CVE5fQ0FOQ0VMJztcblxuICBpbXBvcnRpbmcgPSBmYWxzZTtcbiAgZXJyb3I6IHN0cmluZztcblxuICBnZXQgZmlsZXMoKTogVXBsb2FkRmlsZTxhbnk+W10ge1xuICAgIHJldHVybiB0aGlzLnVwbG9hZGVyLmZpbGVzO1xuICB9XG5cbiAgZ2V0IGRpc2FibGVkKCkge1xuICAgIHJldHVybiB0aGlzLmltcG9ydGluZyB8fCBpc0VtcHR5QXJyYXkodGhpcy5maWxlcykgfHwgdGhpcy5maWxlcy5ldmVyeSgoZmlsZSkgPT4gZmlsZS5lcnJvcik7XG4gIH1cblxuICBnZXQgdmFsaWQoKSB7XG4gICAgcmV0dXJuIGlzTm90RW1wdHlBcnJheSh0aGlzLmZpbGVzKTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByb3RlY3RlZCBwb3BvdmVyQ29udHJvbGxlcjogUG9wb3ZlckNvbnRyb2xsZXIsXG4gICAgcHJvdGVjdGVkIHRyYW5zbGF0ZTogVHJhbnNsYXRlU2VydmljZSxcbiAgICBwcm90ZWN0ZWQgY2Q6IENoYW5nZURldGVjdG9yUmVmXG4gICkge31cblxuICBhc3luYyBvblZhbGlkYXRlKGV2ZW50OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgIGV2ZW50Py5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgIC8vIEF2b2lkIG11bHRpcGxlIGNhbGxcbiAgICBpZiAodGhpcy5pbXBvcnRpbmcpIHJldHVybjtcblxuICAgIGNvbnNvbGUuZGVidWcoJ1t1cGxvYWQtZmlsZS1wb3BvdmVyXSBWYWxpZGF0ZSBmb3JtOiB3aWxsIHVwbG9hZCBhbGwgZmlsZXMuLi4nKTtcblxuICAgIHRyeSB7XG4gICAgICB0aGlzLmltcG9ydGluZyA9IHRydWU7XG4gICAgICB0aGlzLnJlc2V0RXJyb3IoKTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gV2FpdCBwcm9jZXNzaW5nIGZpbGVzIGZpbmlzaGVkXG4gICAgICAgIGF3YWl0IHRoaXMudXBsb2FkZXIud2FpdElkbGUoKTtcblxuICAgICAgICAvLyB1cGxvYWQgYWxsIGZpbGVzXG4gICAgICAgIGF3YWl0IHRoaXMudXBsb2FkZXIudXBsb2FkRmlsZXMoKTtcblxuICAgICAgICBjb25zdCBmaWxlczogVXBsb2FkRmlsZTxhbnk+W10gPSAodGhpcy51cGxvYWRlci5wcm9jZXNzZWRGaWxlcyB8fCBbXSkuZmlsdGVyKChmaWxlKSA9PiAhZmlsZS5kZWxldGluZyk7IC8vIFJlbW92ZSBkZWxldGluZyBmaWxlIChkZWxldGlvbiBpbiBwcm9ncmVzcylcblxuICAgICAgICAvLyBOb3RoaW5nIHRvIHVwbG9hZDogY2xvc2UgcG9wb3ZlclxuICAgICAgICBpZiAoaXNFbXB0eUFycmF5KGZpbGVzKSkgcmV0dXJuIHRoaXMuY2FuY2VsKCk7XG5cbiAgICAgICAgLy8gY2hlY2sgZXJyb3JzXG4gICAgICAgIGNvbnN0IGVycm9ycyA9IGZpbGVzLm1hcCgoZmlsZSkgPT4gZmlsZS5lcnJvcikuZmlsdGVyKGlzTm90TmlsT3JCbGFuayk7XG5cbiAgICAgICAgLy8gSWYgZXJyb3I6IHN0b3BcbiAgICAgICAgaWYgKGVycm9ycy5sZW5ndGgpIHtcbiAgICAgICAgICBlcnJvcnMuZm9yRWFjaCgoZXJyb3IpID0+IGNvbnNvbGUuZXJyb3IoZXJyb3IpKTtcbiAgICAgICAgICB0aHJvdyB7IG1lc3NhZ2U6ICdGSUxFLlVQTE9BRC5FUlJPUicgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHJldHVybiBmaWxlc1xuICAgICAgICBhd2FpdCB0aGlzLnBvcG92ZXJDb250cm9sbGVyLmRpc21pc3MoZmlsZXMpO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHRoaXMuZXJyb3IgPSAoZXJyICYmIGVyci5tZXNzYWdlKSB8fCBlcnI7XG4gICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMuaW1wb3J0aW5nID0gZmFsc2U7XG4gICAgICB0aGlzLmNkLm1hcmtGb3JDaGVjaygpO1xuICAgIH1cbiAgfVxuXG4gIGNhbmNlbCgpIHtcbiAgICByZXR1cm4gdGhpcy5wb3BvdmVyQ29udHJvbGxlci5kaXNtaXNzKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgcmVzZXRFcnJvcigpIHtcbiAgICBpZiAodGhpcy5lcnJvcikge1xuICAgICAgdGhpcy5lcnJvciA9IG51bGw7XG4gICAgICB0aGlzLmNkLm1hcmtGb3JDaGVjaygpO1xuICAgIH1cbiAgfVxufVxuIiwiPGlvbi1jb250ZW50IGNsYXNzPVwiaW9uLW5vLXBhZGRpbmdcIiBzY3JvbGxZPVwiZmFsc2VcIj5cbiAgPGFwcC11cGxvYWQtZmlsZVxuICAgICN1cGxvYWRlclxuICAgIFt1cGxvYWRGbl09XCJ1cGxvYWRGblwiXG4gICAgW2RlbGV0ZUZuXT1cImRlbGV0ZUZuXCJcbiAgICBbZmlsZUV4dGVuc2lvbl09XCJmaWxlRXh0ZW5zaW9uXCJcbiAgICBbZmlsZUV4dGVuc2lvbnNFeGNsdWRlZF09XCJmaWxlRXh0ZW5zaW9uc0V4Y2x1ZGVkXCJcbiAgICBbaW5zdGFudFVwbG9hZF09XCJpbnN0YW50VXBsb2FkXCJcbiAgICBbdW5pcXVlRmlsZV09XCJ1bmlxdWVGaWxlXCJcbiAgICBbbWF4UGFyYWxsZWxVcGxvYWRdPVwibWF4UGFyYWxsZWxVcGxvYWRcIlxuICAgIFttYXhGaWxlU2l6ZU1iXT1cIm1heEZpbGVTaXplTWJcIlxuICAgIFthdXRvSGlkZURyb3BBcmVhXT1cImF1dG9IaWRlRHJvcEFyZWFcIlxuICA+PC9hcHAtdXBsb2FkLWZpbGU+XG48L2lvbi1jb250ZW50PlxuXG48aW9uLWZvb3Rlcj5cbiAgPGlvbi10b29sYmFyPlxuICAgIDxpb24tcm93IGNsYXNzPVwiaW9uLW5vLXBhZGRpbmcgaW9uLW5vd3JhcFwiID5cbiAgICAgIDxpb24tY29sPlxuICAgICAgICBAaWYgKGltcG9ydGluZykge1xuICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbXBvcnRpbmctaW5mb1wiPlxuICAgICAgICAgICAgPGlvbi10ZXh0IGNvbG9yPVwibWVkaXVtXCI+PHNtYWxsIHRyYW5zbGF0ZT5GSUxFLlVQTE9BRC5JTVBPUlRJTkc8L3NtYWxsPjwvaW9uLXRleHQ+XG4gICAgICAgICAgICAmbmJzcDtcbiAgICAgICAgICAgIDxpb24tc3Bpbm5lciBuYW1lPVwiZG90c1wiIGNvbG9yPVwiYWNjZW50XCI+PC9pb24tc3Bpbm5lcj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgfVxuICAgICAgICBAaWYgKGVycm9yKSB7XG4gICAgICAgICAgPGlvbi1pdGVtIGxpbmVzPVwibm9uZVwiIGNvbG9yPVwidHJhbnNwYXJlbnRcIj5cbiAgICAgICAgICAgIDxpb24taWNvbiBjb2xvcj1cImRhbmdlclwiIHNsb3Q9XCJzdGFydFwiIG5hbWU9XCJhbGVydC1jaXJjbGVcIj48L2lvbi1pY29uPlxuICAgICAgICAgICAgPGlvbi1sYWJlbCBjb2xvcj1cImRhbmdlclwiIGNsYXNzPVwiaW9uLXRleHQtd3JhcFwiPlxuICAgICAgICAgICAgICA8c21hbGwgW2lubmVySFRNTF09XCJlcnJvciB8IHRyYW5zbGF0ZVwiPjwvc21hbGw+XG4gICAgICAgICAgICA8L2lvbi1sYWJlbD5cbiAgICAgICAgICA8L2lvbi1pdGVtPlxuICAgICAgICB9XG4gICAgICA8L2lvbi1jb2w+XG4gICAgICA8aW9uLWNvbCBzaXplPVwiYXV0b1wiPlxuICAgICAgICA8aW9uLWJ1dHRvbiBmaWxsPVwiY2xlYXJcIiBjb2xvcj1cImRhcmtcIiAoY2xpY2spPVwiY2FuY2VsKClcIj5cbiAgICAgICAgICA8aW9uLWxhYmVsIFtpbm5lckhUTUxdPVwiY2FuY2VsQnV0dG9uVGV4dCB8IHRyYW5zbGF0ZVwiPjwvaW9uLWxhYmVsPlxuICAgICAgICA8L2lvbi1idXR0b24+XG4gICAgICAgIDxpb24tYnV0dG9uXG4gICAgICAgICAgW2ZpbGxdPVwiZGlzYWJsZWQgPyAnY2xlYXInIDogJ3NvbGlkJ1wiXG4gICAgICAgICAgKGNsaWNrKT1cIm9uVmFsaWRhdGUoJGV2ZW50KVwiXG4gICAgICAgICAgKGtleXVwLmVudGVyKT1cIm9uVmFsaWRhdGUoJGV2ZW50KVwiXG4gICAgICAgICAgY29sb3I9XCJ0ZXJ0aWFyeVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxpb24tbGFiZWwgW2lubmVySFRNTF09XCJva0J1dHRvblRleHQgfCB0cmFuc2xhdGVcIj48L2lvbi1sYWJlbD5cbiAgICAgICAgPC9pb24tYnV0dG9uPlxuICAgICAgPC9pb24tY29sPlxuICAgIDwvaW9uLXJvdz5cbiAgPC9pb24tdG9vbGJhcj5cbjwvaW9uLWZvb3Rlcj5cbiJdfQ==
114
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBsb2FkLWZpbGUtcG9wb3Zlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBwL3NoYXJlZC91cGxvYWQtZmlsZS91cGxvYWQtZmlsZS1wb3BvdmVyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvc2hhcmVkL3VwbG9hZC1maWxlL3VwbG9hZC1maWxlLXBvcG92ZXIuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLHVCQUF1QixFQUFxQixTQUFTLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUkzSCxPQUFPLEVBQUUsWUFBWSxFQUFFLGVBQWUsRUFBRSxlQUFlLEVBQUUsTUFBTSxjQUFjLENBQUM7Ozs7O0FBZ0M5RSxNQUFNLE9BQU8saUJBQWlCO0lBOEJoQjtJQUNBO0lBQ0E7SUEvQjZCLFFBQVEsQ0FBc0I7SUFFOUQsYUFBYSxDQUFTO0lBQ3RCLEtBQUssQ0FBUztJQUNkLFVBQVUsR0FBRyxLQUFLLENBQUM7SUFDbkIsYUFBYSxHQUFHLEtBQUssQ0FBQztJQUN0QixRQUFRLENBQW9CO0lBQzVCLFFBQVEsQ0FBb0I7SUFDNUIsaUJBQWlCLENBQVM7SUFDMUIsZ0JBQWdCLEdBQUcsS0FBSyxDQUFDO0lBQ3pCLFlBQVksR0FBRyxtQkFBbUIsQ0FBQztJQUNuQyxnQkFBZ0IsR0FBRyxtQkFBbUIsQ0FBQztJQUVoRCxTQUFTLEdBQUcsS0FBSyxDQUFDO0lBQ2xCLEtBQUssQ0FBUztJQUVkLElBQUksS0FBSztRQUNQLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUM7SUFDN0IsQ0FBQztJQUVELElBQUksUUFBUTtRQUNWLE9BQU8sSUFBSSxDQUFDLFNBQVMsSUFBSSxZQUFZLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3BELENBQUM7SUFF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c0JBQWhELFNBQVM7dUJBQUMsVUFBVSxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtnQkFFOUIsYUFBYTtzQkFBckIsS0FBSztnQkFDRyxLQUFLO3NCQUFiLEtBQUs7Z0JBQ0csVUFBVTtzQkFBbEIsS0FBSztnQkFDRyxhQUFhO3NCQUFyQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csUUFBUTtzQkFBaEIsS0FBSztnQkFDRyxpQkFBaUI7c0JBQXpCLEtBQUs7Z0JBQ0csZ0JBQWdCO3NCQUF4QixLQUFLO2dCQUNHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBQ0csZ0JBQWdCO3NCQUF4QixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENoYW5nZURldGVjdG9yUmVmLCBDb21wb25lbnQsIElucHV0LCBWaWV3Q2hpbGQsIFZpZXdFbmNhcHN1bGF0aW9uIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBQb3BvdmVyQ29udHJvbGxlciB9IGZyb20gJ0Bpb25pYy9hbmd1bGFyJztcbmltcG9ydCB7IFVwbG9hZEZpbGVDb21wb25lbnQgfSBmcm9tICcuL3VwbG9hZC1maWxlLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBGaWxlRGVsZXRlRm4sIEZpbGVVcGxvYWRGbiwgVXBsb2FkRmlsZSB9IGZyb20gJy4vdXBsb2FkLWZpbGUubW9kZWwnO1xuaW1wb3J0IHsgaXNFbXB0eUFycmF5LCBpc05vdEVtcHR5QXJyYXksIGlzTm90TmlsT3JCbGFuayB9IGZyb20gJy4uL2Z1bmN0aW9ucyc7XG5pbXBvcnQgeyBUcmFuc2xhdGVTZXJ2aWNlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgVXBsb2FkRmlsZVBvcG92ZXJPcHRpb25zPFQ+IHtcbiAgdGl0bGU/OiBzdHJpbmc7XG5cbiAgdXBsb2FkRm46IEZpbGVVcGxvYWRGbjxUPjtcbiAgZGVsZXRlRm4/OiBGaWxlRGVsZXRlRm48YW55PjtcblxuICBpbnN0YW50VXBsb2FkPzogYm9vbGVhbjtcbiAgdW5pcXVlRmlsZT86IGJvb2xlYW47XG4gIGZpbGVFeHRlbnNpb24/OiBzdHJpbmc7XG4gIG1heFBhcmFsbGVsVXBsb2FkPzogbnVtYmVyO1xuICBhdXRvSGlkZURyb3BBcmVhPzogYm9vbGVhbjtcblxuICBva0J1dHRvblRleHQ/OiBzdHJpbmc7XG4gIGNhbmNlbEJ1dHRvblRleHQ/OiBzdHJpbmc7XG5cbiAgLy8gUHJvcGVydGllcyBvZiBpb24tcG9wb3ZlclxuICBiYWNrZHJvcERpc21pc3M/OiBib29sZWFuOyAvLyBmYWxzZSBieSBkZWZhdWx0XG4gIGtleWJvYXJkQ2xvc2U/OiBib29sZWFuOyAvLyBmYWxzZSBieSBkZWZhdWx0XG4gIHRyYW5zbHVjZW50PzogYm9vbGVhbjsgLy8gdHJ1ZSBieSBkZWZhdWx0XG4gIGNzc0NsYXNzPzogc3RyaW5nIHwgc3RyaW5nW107XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2FwcC11cGxvYWQtZmlsZS1wb3BvdmVyJyxcbiAgdGVtcGxhdGVVcmw6ICcuL3VwbG9hZC1maWxlLXBvcG92ZXIuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi91cGxvYWQtZmlsZS1wb3BvdmVyLmNvbXBvbmVudC5zY3NzJ10sXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBVcGxvYWRGaWxlUG9wb3ZlciBpbXBsZW1lbnRzIFVwbG9hZEZpbGVQb3BvdmVyT3B0aW9uczxhbnk+IHtcbiAgQFZpZXdDaGlsZCgndXBsb2FkZXInLCB7IHN0YXRpYzogdHJ1ZSB9KSB1cGxvYWRlcjogVXBsb2FkRmlsZUNvbXBvbmVudDtcblxuICBASW5wdXQoKSBmaWxlRXh0ZW5zaW9uOiBzdHJpbmc7XG4gIEBJbnB1dCgpIHRpdGxlOiBzdHJpbmc7XG4gIEBJbnB1dCgpIHVuaXF1ZUZpbGUgPSBmYWxzZTtcbiAgQElucHV0KCkgaW5zdGFudFVwbG9hZCA9IGZhbHNlO1xuICBASW5wdXQoKSB1cGxvYWRGbjogRmlsZVVwbG9hZEZuPGFueT47XG4gIEBJbnB1dCgpIGRlbGV0ZUZuOiBGaWxlRGVsZXRlRm48YW55PjtcbiAgQElucHV0KCkgbWF4UGFyYWxsZWxVcGxvYWQ6IG51bWJlcjtcbiAgQElucHV0KCkgYXV0b0hpZGVEcm9wQXJlYSA9IGZhbHNlO1xuICBASW5wdXQoKSBva0J1dHRvblRleHQgPSAnQ09NTU9OLkJUTl9JTVBPUlQnO1xuICBASW5wdXQoKSBjYW5jZWxCdXR0b25UZXh0ID0gJ0NPTU1PTi5CVE5fQ0FOQ0VMJztcblxuICBpbXBvcnRpbmcgPSBmYWxzZTtcbiAgZXJyb3I6IHN0cmluZztcblxuICBnZXQgZmlsZXMoKTogVXBsb2FkRmlsZTxhbnk+W10ge1xuICAgIHJldHVybiB0aGlzLnVwbG9hZGVyLmZpbGVzO1xuICB9XG5cbiAgZ2V0IGRpc2FibGVkKCkge1xuICAgIHJldHVybiB0aGlzLmltcG9ydGluZyB8fCBpc0VtcHR5QXJyYXkodGhpcy5maWxlcyk7XG4gIH1cblxuICBnZXQgdmFsaWQoKSB7XG4gICAgcmV0dXJuIGlzTm90RW1wdHlBcnJheSh0aGlzLmZpbGVzKTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByb3RlY3RlZCBwb3BvdmVyQ29udHJvbGxlcjogUG9wb3ZlckNvbnRyb2xsZXIsXG4gICAgcHJvdGVjdGVkIHRyYW5zbGF0ZTogVHJhbnNsYXRlU2VydmljZSxcbiAgICBwcm90ZWN0ZWQgY2Q6IENoYW5nZURldGVjdG9yUmVmXG4gICkge31cblxuICBhc3luYyBvblZhbGlkYXRlKGV2ZW50OiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgIGV2ZW50Py5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgIC8vIEF2b2lkIG11bHRpcGxlIGNhbGxcbiAgICBpZiAodGhpcy5pbXBvcnRpbmcpIHJldHVybjtcblxuICAgIGNvbnNvbGUuZGVidWcoJ1t1cGxvYWQtZmlsZS1wb3BvdmVyXSBWYWxpZGF0ZSBmb3JtOiB3aWxsIHVwbG9hZCBhbGwgZmlsZXMuLi4nKTtcblxuICAgIHRyeSB7XG4gICAgICB0aGlzLmltcG9ydGluZyA9IHRydWU7XG4gICAgICB0aGlzLnJlc2V0RXJyb3IoKTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gV2FpdCBwcm9jZXNzaW5nIGZpbGVzIGZpbmlzaGVkXG4gICAgICAgIGF3YWl0IHRoaXMudXBsb2FkZXIud2FpdElkbGUoKTtcblxuICAgICAgICAvLyB1cGxvYWQgYWxsIGZpbGVzXG4gICAgICAgIGF3YWl0IHRoaXMudXBsb2FkZXIudXBsb2FkRmlsZXMoKTtcblxuICAgICAgICBjb25zdCBmaWxlczogVXBsb2FkRmlsZTxhbnk+W10gPSAodGhpcy51cGxvYWRlci5wcm9jZXNzZWRGaWxlcyB8fCBbXSkuZmlsdGVyKChmaWxlKSA9PiAhZmlsZS5kZWxldGluZyk7IC8vIFJlbW92ZSBkZWxldGluZyBmaWxlIChkZWxldGlvbiBpbiBwcm9ncmVzcylcblxuICAgICAgICAvLyBOb3RoaW5nIHRvIHVwbG9hZDogY2xvc2UgcG9wb3ZlclxuICAgICAgICBpZiAoaXNFbXB0eUFycmF5KGZpbGVzKSkgcmV0dXJuIHRoaXMuY2FuY2VsKCk7XG5cbiAgICAgICAgLy8gY2hlY2sgZXJyb3JzXG4gICAgICAgIGNvbnN0IGVycm9ycyA9IGZpbGVzLm1hcCgoZmlsZSkgPT4gZmlsZS5lcnJvcikuZmlsdGVyKGlzTm90TmlsT3JCbGFuayk7XG5cbiAgICAgICAgLy8gSWYgZXJyb3I6IHN0b3BcbiAgICAgICAgaWYgKGVycm9ycy5sZW5ndGgpIHtcbiAgICAgICAgICBlcnJvcnMuZm9yRWFjaCgoZXJyb3IpID0+IGNvbnNvbGUuZXJyb3IoZXJyb3IpKTtcbiAgICAgICAgICB0aHJvdyB7IG1lc3NhZ2U6ICdGSUxFLlVQTE9BRC5FUlJPUicgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHJldHVybiBmaWxlc1xuICAgICAgICBhd2FpdCB0aGlzLnBvcG92ZXJDb250cm9sbGVyLmRpc21pc3MoZmlsZXMpO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHRoaXMuZXJyb3IgPSAoZXJyICYmIGVyci5tZXNzYWdlKSB8fCBlcnI7XG4gICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMuaW1wb3J0aW5nID0gZmFsc2U7XG4gICAgICB0aGlzLmNkLm1hcmtGb3JDaGVjaygpO1xuICAgIH1cbiAgfVxuXG4gIGNhbmNlbCgpIHtcbiAgICByZXR1cm4gdGhpcy5wb3BvdmVyQ29udHJvbGxlci5kaXNtaXNzKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgcmVzZXRFcnJvcigpIHtcbiAgICBpZiAodGhpcy5lcnJvcikge1xuICAgICAgdGhpcy5lcnJvciA9IG51bGw7XG4gICAgICB0aGlzLmNkLm1hcmtGb3JDaGVjaygpO1xuICAgIH1cbiAgfVxufVxuIiwiPGlvbi1jb250ZW50IGNsYXNzPVwiaW9uLW5vLXBhZGRpbmdcIiBzY3JvbGxZPVwiZmFsc2VcIj5cbiAgPGFwcC11cGxvYWQtZmlsZVxuICAgICN1cGxvYWRlclxuICAgIFt1cGxvYWRGbl09XCJ1cGxvYWRGblwiXG4gICAgW2RlbGV0ZUZuXT1cImRlbGV0ZUZuXCJcbiAgICBbZmlsZUV4dGVuc2lvbl09XCJmaWxlRXh0ZW5zaW9uXCJcbiAgICBbaW5zdGFudFVwbG9hZF09XCJpbnN0YW50VXBsb2FkXCJcbiAgICBbdW5pcXVlRmlsZV09XCJ1bmlxdWVGaWxlXCJcbiAgICBbbWF4UGFyYWxsZWxVcGxvYWRdPVwibWF4UGFyYWxsZWxVcGxvYWRcIlxuICAgIFthdXRvSGlkZURyb3BBcmVhXT1cImF1dG9IaWRlRHJvcEFyZWFcIlxuICA+PC9hcHAtdXBsb2FkLWZpbGU+XG48L2lvbi1jb250ZW50PlxuXG48aW9uLWZvb3Rlcj5cbiAgPGlvbi10b29sYmFyPlxuICAgIDxpb24tcm93IGNsYXNzPVwiaW9uLW5vLXBhZGRpbmcgaW9uLW5vd3JhcFwiID5cbiAgICAgIDxpb24tY29sPlxuICAgICAgICBAaWYgKGltcG9ydGluZykge1xuICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbXBvcnRpbmctaW5mb1wiPlxuICAgICAgICAgICAgPGlvbi10ZXh0IGNvbG9yPVwibWVkaXVtXCI+PHNtYWxsIHRyYW5zbGF0ZT5GSUxFLlVQTE9BRC5JTVBPUlRJTkc8L3NtYWxsPjwvaW9uLXRleHQ+XG4gICAgICAgICAgICAmbmJzcDtcbiAgICAgICAgICAgIDxpb24tc3Bpbm5lciBuYW1lPVwiZG90c1wiIGNvbG9yPVwiYWNjZW50XCI+PC9pb24tc3Bpbm5lcj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgfVxuICAgICAgICBAaWYgKGVycm9yKSB7XG4gICAgICAgICAgPGlvbi1pdGVtIGxpbmVzPVwibm9uZVwiIGNvbG9yPVwidHJhbnNwYXJlbnRcIj5cbiAgICAgICAgICAgIDxpb24taWNvbiBjb2xvcj1cImRhbmdlclwiIHNsb3Q9XCJzdGFydFwiIG5hbWU9XCJhbGVydC1jaXJjbGVcIj48L2lvbi1pY29uPlxuICAgICAgICAgICAgPGlvbi1sYWJlbCBjb2xvcj1cImRhbmdlclwiIGNsYXNzPVwiaW9uLXRleHQtd3JhcFwiPlxuICAgICAgICAgICAgICA8c21hbGwgW2lubmVySFRNTF09XCJlcnJvciB8IHRyYW5zbGF0ZVwiPjwvc21hbGw+XG4gICAgICAgICAgICA8L2lvbi1sYWJlbD5cbiAgICAgICAgICA8L2lvbi1pdGVtPlxuICAgICAgICB9XG4gICAgICA8L2lvbi1jb2w+XG4gICAgICA8aW9uLWNvbCBzaXplPVwiYXV0b1wiPlxuICAgICAgICA8aW9uLWJ1dHRvbiBmaWxsPVwiY2xlYXJcIiBjb2xvcj1cImRhcmtcIiAoY2xpY2spPVwiY2FuY2VsKClcIj5cbiAgICAgICAgICA8aW9uLWxhYmVsIFtpbm5lckhUTUxdPVwiY2FuY2VsQnV0dG9uVGV4dCB8IHRyYW5zbGF0ZVwiPjwvaW9uLWxhYmVsPlxuICAgICAgICA8L2lvbi1idXR0b24+XG4gICAgICAgIDxpb24tYnV0dG9uXG4gICAgICAgICAgW2ZpbGxdPVwiZGlzYWJsZWQgPyAnY2xlYXInIDogJ3NvbGlkJ1wiXG4gICAgICAgICAgKGNsaWNrKT1cIm9uVmFsaWRhdGUoJGV2ZW50KVwiXG4gICAgICAgICAgKGtleXVwLmVudGVyKT1cIm9uVmFsaWRhdGUoJGV2ZW50KVwiXG4gICAgICAgICAgY29sb3I9XCJ0ZXJ0aWFyeVwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxpb24tbGFiZWwgW2lubmVySFRNTF09XCJva0J1dHRvblRleHQgfCB0cmFuc2xhdGVcIj48L2lvbi1sYWJlbD5cbiAgICAgICAgPC9pb24tYnV0dG9uPlxuICAgICAgPC9pb24tY29sPlxuICAgIDwvaW9uLXJvdz5cbiAgPC9pb24tdG9vbGJhcj5cbjwvaW9uLWZvb3Rlcj5cbiJdfQ==