@sumaris-net/ngx-components 2.6.27 → 2.6.29

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.
@@ -10136,13 +10136,9 @@ class TreeItemEntityUtils {
10136
10136
  }
10137
10137
  static first(node, filterFn) {
10138
10138
  // Node has children: dive into children
10139
- const child = (node.children || []).find((c) => !filterFn || filterFn(c));
10139
+ const child = (node.children || []).find((c) => this.first(c, filterFn));
10140
10140
  if (child)
10141
10141
  return child;
10142
- // Lookup in descendants
10143
- const descendant = (node.children || []).map((c) => this.first(c, filterFn)).find(isNotNil);
10144
- if (descendant)
10145
- return descendant;
10146
10142
  // Node match: use it
10147
10143
  return !filterFn || filterFn(node) ? node : undefined;
10148
10144
  }
@@ -10862,10 +10858,9 @@ const DEFAULT_SETTINGS = {
10862
10858
  const APP_LOCAL_SETTINGS = new InjectionToken('DefaultLocalSettings');
10863
10859
  const APP_LOCAL_SETTINGS_OPTIONS = new InjectionToken('LocalSettingsOptions');
10864
10860
  class LocalSettingsService extends StartableService {
10865
- constructor(translate, platform, storage, environment, defaultSettings, options) {
10861
+ constructor(platform, translate, storage, environment, defaultSettings, options) {
10866
10862
  super(platform);
10867
10863
  this.translate = translate;
10868
- this.platform = platform;
10869
10864
  this.storage = storage;
10870
10865
  this.environment = environment;
10871
10866
  this.defaultSettings = defaultSettings;
@@ -11288,7 +11283,7 @@ class LocalSettingsService extends StartableService {
11288
11283
  return page;
11289
11284
  }
11290
11285
  }
11291
- LocalSettingsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: LocalSettingsService, deps: [{ token: i1$1.TranslateService }, { token: i2$1.Platform }, { token: i2$3.Storage }, { token: ENVIRONMENT }, { token: APP_LOCAL_SETTINGS, optional: true }, { token: APP_LOCAL_SETTINGS_OPTIONS, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
11286
+ LocalSettingsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: LocalSettingsService, deps: [{ token: i2$1.Platform }, { token: i1$1.TranslateService }, { token: i2$3.Storage }, { token: ENVIRONMENT }, { token: APP_LOCAL_SETTINGS, optional: true }, { token: APP_LOCAL_SETTINGS_OPTIONS, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
11292
11287
  LocalSettingsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: LocalSettingsService, providedIn: 'root' });
11293
11288
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: LocalSettingsService, decorators: [{
11294
11289
  type: Injectable,
@@ -11297,7 +11292,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
11297
11292
  //deps: [APP_LOCAL_SETTINGS, APP_LOCAL_SETTINGS_OPTIONS]
11298
11293
  }]
11299
11294
  }], ctorParameters: function () {
11300
- return [{ type: i1$1.TranslateService }, { type: i2$1.Platform }, { type: i2$3.Storage }, { type: Environment, decorators: [{
11295
+ return [{ type: i2$1.Platform }, { type: i1$1.TranslateService }, { type: i2$3.Storage }, { type: Environment, decorators: [{
11301
11296
  type: Inject,
11302
11297
  args: [ENVIRONMENT]
11303
11298
  }] }, { type: undefined, decorators: [{
@@ -22829,10 +22824,10 @@ class AppImageGalleryComponent {
22829
22824
  }
22830
22825
  }
22831
22826
  AppImageGalleryComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: AppImageGalleryComponent, deps: [{ token: ImageService }, { token: i2$1.Platform }, { token: i2$1.AlertController }, { token: i2$1.PopoverController }, { token: i1$1.TranslateService }, { token: i0.ChangeDetectorRef }, { token: ENVIRONMENT, optional: true }], target: i0.ɵɵFactoryTarget.Component });
22832
- AppImageGalleryComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: AppImageGalleryComponent, selector: "app-image-gallery", inputs: { cardColor: "cardColor", debug: "debug", disabled: "disabled", readOnly: "readOnly", mobile: "mobile", mode: "mode", confirmBeforeDelete: "confirmBeforeDelete", showToolbar: "showToolbar", showFabButton: "showFabButton", showTitle: "showTitle", showAddCardButton: "showAddCardButton", addButtonColor: "addButtonColor", dataSource: "dataSource" }, outputs: { onBeforeDeleteRows: "onBeforeDeleteRows", onAfterAddRows: "onAfterAddRows" }, viewQueries: [{ propertyName: "zoomModal", first: true, predicate: ["zoomModal"], descendants: true }, { propertyName: "titlePopover", first: true, predicate: ["titlePopover"], descendants: true }, { propertyName: "swiperRef", first: true, predicate: ["modalSwiper"], descendants: true }], ngImport: i0, template: "\n\n<ion-toolbar color=\"light\" *ngIf=\"showToolbar\">\n <!-- Add -->\n <button mat-icon-button\n *ngIf=\"!readOnly && !mobile && enabled\"\n [title]=\"'COMMON.BTN_ADD'|translate\"\n (click)=\"add()\">\n <mat-icon>add</mat-icon>\n </button>\n\n <ion-buttons slot=\"end\">\n <!-- Toggle view mode -->\n <ion-segment (ionChange)=\"toggleViewMode($event)\" color=\"accent\"\n [value]=\"_colSize\">\n <ion-segment-button [value]=\"4\">\n <mat-icon>view_module</mat-icon>\n </ion-segment-button>\n <ion-segment-button [value]=\"12\">\n <mat-icon>view_list</mat-icon>\n </ion-segment-button>\n </ion-segment>\n </ion-buttons>\n</ion-toolbar>\n\n<div class=\"gallery-container {{this.mode}}\">\n <div *ngIf=\"mobile && zoomActive\" class=\"backdrop\" [style.opacity]=\"zoomScale\"></div>\n\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col *ngFor=\"let row of rows; index as index; trackBy: trackByFn\" [size]=\"_colSize\">\n <ion-card #card\n class=\"image-card\"\n [class.zoom-hover]=\"!mobile\"\n [color]=\"cardColor\"\n *ngVar=\"row|propertyGet: 'currentData'; let image\"\n (click)=\"clickRow(row, index)\"\n tappable\n @fadeInAnimation>\n <figure class=\"card-thumbnail\">\n <img [src]=\"image.url||image.dataUrl\"/>\n </figure>\n\n <!-- toolbar for title (when not hover) -->\n <ion-toolbar color=\"transparent\" class=\"title\">\n <ion-label class=\"card-title\">{{image.title}}</ion-label>\n </ion-toolbar>\n\n <!-- action toolbar (desktop only) shown when hover image -->\n <ion-toolbar #cardToolbar *ngIf=\"!mobile && !readOnly\" color=\"light\" class=\"buttons\">\n\n <!-- edit title button -->\n <button mat-button *ngIf=\"showTitle\" slot=\"start\"\n [disabled]=\"disabled\"\n (click)=\"editTitle($event, row, cardToolbar)\"\n (focusin)=\"showCardToolbar(cardToolbar)\">\n <mat-icon>edit</mat-icon>\n <mat-label>\n <span *ngIf=\"row.currentData.title|isNotNilOrBlank; else editLabel\" translate>IMAGE.GALLERY.BTN_EDIT_TITLE</span>\n <ng-template #editLabel>\n <span translate>IMAGE.GALLERY.BTN_ADD_TITLE</span>\n </ng-template>\n </mat-label>\n </button>\n\n <div class=\"flex-spacer\"></div>\n\n <!-- delete button -->\n <button mat-icon-button slot=\"end\"\n class=\"ion-float-end\"\n [title]=\"'COMMON.BTN_DELETE'|translate\"\n [disabled]=\"disabled\"\n (click)=\"delete($event, row)\">\n <mat-icon>delete</mat-icon>\n </button>\n </ion-toolbar>\n </ion-card>\n </ion-col>\n\n <ion-col *ngIf=\"showAddCardButton && !readOnly\" [size]=\"_colSize\" @fadeInAnimation>\n <ion-card class=\"image-card-button\" color=\"light\"\n (click)=\"add($event)\"\n [disabled]=\"disabled\"\n tappable>\n <ion-card-content>\n <div class=\"icon-container\">\n <ion-icon name=\"camera\" [color]=\"addButtonColor\"></ion-icon>\n <ion-icon name=\"add\" [color]=\"addButtonColor\" class=\"icon-secondary\"></ion-icon>\n </div>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n</div>\n\n<!-- FAB button: add -->\n<ion-fab slot=\"fixed\" vertical=\"bottom\" horizontal=\"end\"\n *ngIf=\"showFabButton && !readOnly\"\n [class.cdk-visually-hidden]=\"disabled\"\n @fadeInOutAnimation>\n\n <ion-fab-button color=\"tertiary\" (click)=\"add($event)\">\n <ion-icon name=\"camera\"></ion-icon>\n <ion-icon name=\"add\" class=\"icon-secondary\" style=\"left: 33px; top: 9px; font-size: 20px;\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n\n<!-- Zoom modal -->\n<ion-modal #zoomModal class=\"stack-modal zoom-modal\"\n [class.modal-fullscreen]=\"mobile\"\n [class.modal-large]=\"!mobile\">\n <ng-template>\n <ion-content class=\"ion-no-padding ion-no-margin\" >\n <!-- Counter -->\n <div class=\"top-left\" *ngVar=\"rows?.length as count\">\n <ion-label color=\"light\">\n {{activeSlideIndex + 1}} / {{count}}\n </ion-label>\n </div>\n\n <!-- zoom button -->\n <div class=\"top-right\">\n <ion-button *ngIf=\"!mobile\" (click)=\"zoom(modalSwiper, true)\" color=\"light\">\n <ion-icon slot=\"icon-only\" name=\"add\"></ion-icon>\n </ion-button>\n <ion-button *ngIf=\"!mobile\" (click)=\"zoom(modalSwiper, false)\" color=\"light\">\n <ion-icon name=\"remove\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n\n <!-- navigation side buttons next/back -->\n <ng-container *ngIf=\"!mobile && (rows|isArrayLength:{greaterThan: 1})\">\n <div class=\"side-buttons prev\"\n (click)=\"slidePrev(modalSwiper)\">\n <ion-icon name=\"chevron-back\"></ion-icon>\n </div>\n <div class=\"side-buttons next\"\n (click)=\"slideNext(modalSwiper)\">\n <ion-icon name=\"chevron-forward\"></ion-icon>\n </div>\n </ng-container>\n\n <!-- image slides -->\n <swiper-container #modalSwiper [modules]=\"swiperModules\" [zoom]=\"true\">\n <swiper-slide *ngFor=\"let row of rows; last as last\">\n <div class=\"swiper-zoom-container\" *ngIf=\"row|propertyGet: 'currentData'; let image\"\n (ngInit)=\"last && initModalSlides(modalSwiper)\">\n <img [src]=\"image.url||image.dataUrl\">\n </div>\n </swiper-slide>\n </swiper-container>\n </ion-content>\n\n <ion-footer>\n <ion-toolbar color=\"light\">\n <ion-row>\n <ion-col size=\"4\" class=\"ion-text-start\">\n <ion-button *ngIf=\"!readOnly\"\n (click)=\"deleteFromModal($event, modalSwiper)\"\n [disabled]=\"disabled\"\n fill=\"clear\" color=\"danger\">\n <mat-icon slot=\"start\">delete</mat-icon>\n {{'COMMON.BTN_DELETE'|translate}}\n </ion-button>\n </ion-col>\n <ion-col size=\"4\">\n </ion-col>\n <ion-col size=\"4\" class=\"ion-text-end\">\n <ion-button (click)=\"zoomModal.dismiss()\" 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)=\"zoomModal.dismiss()\" color=\"tertiary\">\n {{'COMMON.BTN_CLOSE'|translate}}\n </ion-button>\n </ng-template>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n </ion-footer>\n </ng-template>\n</ion-modal>\n\n<ion-popover #titlePopover>\n <ng-template>\n <ion-content class=\"ion-padding\" cdkTrapFocus [cdkTrapFocusAutoCapture]=\"true\" >\n <form [formGroup]=\"_titleForm\">\n <mat-form-field floatLabel=\"auto\">\n <mat-label translate>IMAGE.GALLERY.TITLE</mat-label>\n <input\n matInput\n formControlName=\"title\"\n [readonly]=\"disabled\"\n [appAutofocus]=\"_titleAutofocus\"\n (keydown.control.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n />\n\n </mat-form-field>\n </form>\n </ion-content>\n\n\n <ion-footer>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col>\n\n </ion-col>\n\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"titlePopover.dismiss(null, 'CANCEL')\">\n <ion-label translate>COMMON.BTN_CANCEL</ion-label>\n </ion-button>\n <ion-button\n [fill]=\"disabled ? 'clear' : 'solid'\"\n (click)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n (keyup.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n color=\"tertiary\"\n [disabled]=\"disabled\"\n [title]=\"'COMMON.BTN_VALIDATE_WITH_SHORTCUT_HELP'|translate\">\n <ion-label translate>COMMON.BTN_VALIDATE</ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n </ion-footer>\n </ng-template>\n</ion-popover>\n", styles: [":host{--image-margin-inline: 10px}mat-toolbar,.mat-toolbar-single-row{padding:0;height:42px}ion-card{margin-left:unset;margin-right:unset;margin-inline:var(--image-margin-inline, 10px)}.image-slide{overflow:visible}.image-card{height:calc(100% - 23px);background-color:var(--ion-color-base);z-index:9;--img-scale: 1}.image-card .card-thumbnail{position:relative;overflow:hidden;display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:100%;height:100%}.image-card .card-thumbnail>img{min-height:100%;transition:scale .2s ease-in-out;scale:var(--img-scale);max-height:var(--img-max-height)}.image-card.zoom-hover:hover{--img-scale: 1.2}.image-card ion-toolbar{--top-offset: calc(-1 * var(--ion-toolbar-height));position:absolute}.image-card ion-toolbar.title{--padding-start: 16px;--padding-end: 16px;--ion-color-base: rgba(0,0,0,.45) !important;position:absolute;top:calc(100% + var(--top-offset));transition:opacity .2s ease-in-out}.image-card ion-toolbar.title ion-label{color:#fff}.image-card ion-toolbar.buttons{--padding-start: 4px;--padding-end: 4px;--ion-color-base: var(--ion-color-light) !important;position:absolute;top:100%;transition:transform .2s ease-in-out}.image-card:hover ion-toolbar.buttons,.image-card ion-toolbar.buttons.focused{transform:translateY(var(--top-offset))}.image-card-button{height:calc(100% - var(--image-margin-inline, 0px) * 2 - 3px);transition:.2s ease-in-out;max-width:250px}.image-card-button ion-card-content{height:100%}.image-card-button .icon-container{height:auto;position:relative;top:calc(50% - 75px);display:flex;align-items:center;justify-content:center}.image-card-button ion-icon:first-of-type{font-size:150px;height:150px;position:relative;top:0}.image-card-button ion-icon.icon-secondary{font-size:50px;position:absolute;top:0;left:max(min(50% + 25px,100% - 50px),0px)}.image-card-button ion-button{float:right}.image-card-button:hover{--ion-color-base: var(--ion-color-shade) !important}.image-card-button:hover ion-icon{--ion-color-base: var(--ion-color-shade) !important}.backdrop{height:100vh;width:100vw;background:black;position:absolute;z-index:10}.zoom-modal{-webkit-user-select:none;user-select:none}.zoom-modal .top-left{z-index:14;position:absolute;display:inline-grid;left:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}.zoom-modal .top-right{z-index:14;position:absolute;display:inline-grid;right:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}.zoom-modal .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)}.zoom-modal .side-buttons ion-icon{top:50%;color:#fff;font-size:2.5rem;position:absolute;opacity:0;transition-duration:.15s;transition-timing-function:ease-in}.zoom-modal .side-buttons:hover{cursor:pointer}.zoom-modal .side-buttons:hover ion-icon{opacity:1}.zoom-modal .side-buttons.prev{left:0}.zoom-modal .side-buttons.prev ion-icon{left:var(--side-buttons-margin)}.zoom-modal .side-buttons.next{right:0}.zoom-modal .side-buttons.next ion-icon{right:var(--side-buttons-margin)}.zoom-modal ion-slides{height:100%;background:black}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2$1.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: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i2$1.IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: i2$1.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: i2$1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonFab, selector: "ion-fab", inputs: ["activated", "edge", "horizontal", "vertical"] }, { kind: "component", type: i2$1.IonFabButton, selector: "ion-fab-button", inputs: ["activated", "closeIcon", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "show", "size", "target", "translucent", "type"] }, { kind: "component", type: i2$1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonSegment, selector: "ion-segment", inputs: ["color", "disabled", "mode", "scrollable", "selectOnFocus", "swipeGesture", "value"] }, { kind: "component", type: i2$1.IonSegmentButton, selector: "ion-segment-button", inputs: ["disabled", "layout", "mode", "type", "value"] }, { kind: "component", type: i2$1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: i2$1.IonModal, selector: "ion-modal" }, { kind: "component", type: i2$1.IonPopover, selector: "ion-popover" }, { kind: "directive", type: i2$1.SelectValueAccessor, selector: "ion-select, ion-radio-group, ion-segment, ion-datetime" }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i6$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "directive", type: i1$3.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "directive", type: i1$1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: NgInitDirective, selector: "[ngInit]", outputs: ["ngInit"] }, { kind: "directive", type: AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: NgVarDirective, selector: "[ngVar]", inputs: ["ngVar"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: PropertyGetPipe, name: "propertyGet" }, { kind: "pipe", type: ArrayLengthPipe, name: "isArrayLength" }, { kind: "pipe", type: IsNotNilOrBlankPipe, name: "isNotNilOrBlank" }], animations: [fadeInAnimation, fadeInOutAnimation], changeDetection: i0.ChangeDetectionStrategy.OnPush });
22827
+ AppImageGalleryComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: AppImageGalleryComponent, selector: "app-image-gallery", inputs: { cardColor: "cardColor", debug: "debug", disabled: "disabled", readOnly: "readOnly", mobile: "mobile", mode: "mode", confirmBeforeDelete: "confirmBeforeDelete", showToolbar: "showToolbar", showFabButton: "showFabButton", showTitle: "showTitle", showAddCardButton: "showAddCardButton", addButtonColor: "addButtonColor", dataSource: "dataSource" }, outputs: { onBeforeDeleteRows: "onBeforeDeleteRows", onAfterAddRows: "onAfterAddRows" }, viewQueries: [{ propertyName: "zoomModal", first: true, predicate: ["zoomModal"], descendants: true }, { propertyName: "titlePopover", first: true, predicate: ["titlePopover"], descendants: true }, { propertyName: "swiperRef", first: true, predicate: ["modalSwiper"], descendants: true }], ngImport: i0, template: "\n\n<ion-toolbar color=\"light\" *ngIf=\"showToolbar\">\n <!-- Add -->\n <button mat-icon-button\n *ngIf=\"!readOnly && !mobile && enabled\"\n [title]=\"'COMMON.BTN_ADD'|translate\"\n (click)=\"add()\">\n <mat-icon>add</mat-icon>\n </button>\n\n <ion-buttons slot=\"end\">\n <!-- Toggle view mode -->\n <ion-segment (ionChange)=\"toggleViewMode($event)\" color=\"accent\"\n [value]=\"_colSize\">\n <ion-segment-button [value]=\"4\">\n <mat-icon>view_module</mat-icon>\n </ion-segment-button>\n <ion-segment-button [value]=\"12\">\n <mat-icon>view_list</mat-icon>\n </ion-segment-button>\n </ion-segment>\n </ion-buttons>\n</ion-toolbar>\n\n<div class=\"gallery-container {{this.mode}}\">\n <div *ngIf=\"mobile && zoomActive\" class=\"backdrop\" [style.opacity]=\"zoomScale\"></div>\n\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col *ngFor=\"let row of rows; index as index; trackBy: trackByFn\" [size]=\"_colSize\">\n <ion-card #card\n class=\"image-card\"\n [class.zoom-hover]=\"!mobile\"\n [color]=\"cardColor\"\n *ngVar=\"row|propertyGet: 'currentData'; let image\"\n (click)=\"clickRow(row, index)\"\n tappable\n @fadeInAnimation>\n <figure class=\"card-thumbnail\">\n <img [src]=\"image.url||image.dataUrl\"/>\n </figure>\n\n <!-- toolbar for title (when not hover) -->\n <ion-toolbar color=\"transparent\" class=\"title\" *ngIf=\"image.title\">\n <ion-label class=\"card-title\">{{image.title}}</ion-label>\n </ion-toolbar>\n\n <!-- action toolbar (desktop only) shown when hover image -->\n <ion-toolbar #cardToolbar *ngIf=\"!mobile && !readOnly\" color=\"light\" class=\"buttons\">\n\n <!-- edit title button -->\n <button mat-button *ngIf=\"showTitle\" slot=\"start\"\n [disabled]=\"disabled\"\n (click)=\"editTitle($event, row, cardToolbar)\"\n (focusin)=\"showCardToolbar(cardToolbar)\">\n <mat-icon>edit</mat-icon>\n <mat-label>\n <span *ngIf=\"row.currentData.title|isNotNilOrBlank; else editLabel\" translate>IMAGE.GALLERY.BTN_EDIT_TITLE</span>\n <ng-template #editLabel>\n <span translate>IMAGE.GALLERY.BTN_ADD_TITLE</span>\n </ng-template>\n </mat-label>\n </button>\n\n <div class=\"flex-spacer\"></div>\n\n <!-- delete button -->\n <button mat-icon-button slot=\"end\"\n class=\"ion-float-end\"\n [title]=\"'COMMON.BTN_DELETE'|translate\"\n [disabled]=\"disabled\"\n (click)=\"delete($event, row)\">\n <mat-icon>delete</mat-icon>\n </button>\n </ion-toolbar>\n </ion-card>\n </ion-col>\n\n <ion-col *ngIf=\"showAddCardButton && !readOnly\" [size]=\"_colSize\" @fadeInAnimation>\n <ion-card class=\"image-card-button\" color=\"light\"\n (click)=\"add($event)\"\n [disabled]=\"disabled\"\n tappable>\n <ion-card-content>\n <div class=\"icon-container\">\n <ion-icon name=\"camera\" [color]=\"addButtonColor\"></ion-icon>\n <ion-icon name=\"add\" [color]=\"addButtonColor\" class=\"icon-secondary\"></ion-icon>\n </div>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n</div>\n\n<!-- FAB button: add -->\n<ion-fab slot=\"fixed\" vertical=\"bottom\" horizontal=\"end\"\n *ngIf=\"showFabButton && !readOnly\"\n [class.cdk-visually-hidden]=\"disabled\"\n @fadeInOutAnimation>\n\n <ion-fab-button color=\"tertiary\" (click)=\"add($event)\">\n <ion-icon name=\"camera\"></ion-icon>\n <ion-icon name=\"add\" class=\"icon-secondary\" style=\"left: 33px; top: 9px; font-size: 20px;\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n\n<!-- Zoom modal -->\n<ion-modal #zoomModal class=\"stack-modal zoom-modal\"\n [class.modal-fullscreen]=\"mobile\"\n [class.modal-large]=\"!mobile\">\n <ng-template>\n <ion-content class=\"ion-no-padding ion-no-margin\" >\n <!-- Counter -->\n <div class=\"top-left\" *ngVar=\"rows?.length as count\">\n <ion-label color=\"light\">\n {{activeSlideIndex + 1}} / {{count}}\n </ion-label>\n </div>\n\n <!-- zoom button -->\n <div class=\"top-right\">\n <ion-button *ngIf=\"!mobile\" (click)=\"zoom(modalSwiper, true)\" color=\"light\">\n <ion-icon slot=\"icon-only\" name=\"add\"></ion-icon>\n </ion-button>\n <ion-button *ngIf=\"!mobile\" (click)=\"zoom(modalSwiper, false)\" color=\"light\">\n <ion-icon name=\"remove\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n\n <!-- navigation side buttons next/back -->\n <ng-container *ngIf=\"!mobile && (rows|isArrayLength:{greaterThan: 1})\">\n <div class=\"side-buttons prev\"\n (click)=\"slidePrev(modalSwiper)\">\n <ion-icon name=\"chevron-back\"></ion-icon>\n </div>\n <div class=\"side-buttons next\"\n (click)=\"slideNext(modalSwiper)\">\n <ion-icon name=\"chevron-forward\"></ion-icon>\n </div>\n </ng-container>\n\n <!-- image slides -->\n <swiper-container #modalSwiper [modules]=\"swiperModules\" [zoom]=\"true\">\n <swiper-slide *ngFor=\"let row of rows; last as last\">\n <div class=\"swiper-zoom-container\" *ngIf=\"row|propertyGet: 'currentData'; let image\"\n (ngInit)=\"last && initModalSlides(modalSwiper)\">\n <img [src]=\"image.url||image.dataUrl\">\n </div>\n </swiper-slide>\n </swiper-container>\n </ion-content>\n\n <ion-footer>\n <ion-toolbar color=\"light\">\n <ion-row>\n <ion-col size=\"4\" class=\"ion-text-start\">\n <ion-button *ngIf=\"!readOnly\"\n (click)=\"deleteFromModal($event, modalSwiper)\"\n [disabled]=\"disabled\"\n fill=\"clear\" color=\"danger\">\n <mat-icon slot=\"start\">delete</mat-icon>\n {{'COMMON.BTN_DELETE'|translate}}\n </ion-button>\n </ion-col>\n <ion-col size=\"4\">\n </ion-col>\n <ion-col size=\"4\" class=\"ion-text-end\">\n <ion-button (click)=\"zoomModal.dismiss()\" 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)=\"zoomModal.dismiss()\" color=\"tertiary\">\n {{'COMMON.BTN_CLOSE'|translate}}\n </ion-button>\n </ng-template>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n </ion-footer>\n </ng-template>\n</ion-modal>\n\n<ion-popover #titlePopover>\n <ng-template>\n <ion-content class=\"ion-padding\" cdkTrapFocus [cdkTrapFocusAutoCapture]=\"true\" >\n <form [formGroup]=\"_titleForm\">\n <mat-form-field floatLabel=\"auto\">\n <mat-label translate>IMAGE.GALLERY.TITLE</mat-label>\n <input\n matInput\n formControlName=\"title\"\n [readonly]=\"disabled\"\n [appAutofocus]=\"_titleAutofocus\"\n (keydown.control.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n />\n\n </mat-form-field>\n </form>\n </ion-content>\n\n\n <ion-footer>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col>\n\n </ion-col>\n\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"titlePopover.dismiss(null, 'CANCEL')\">\n <ion-label translate>COMMON.BTN_CANCEL</ion-label>\n </ion-button>\n <ion-button\n [fill]=\"disabled ? 'clear' : 'solid'\"\n (click)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n (keyup.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n color=\"tertiary\"\n [disabled]=\"disabled\"\n [title]=\"'COMMON.BTN_VALIDATE_WITH_SHORTCUT_HELP'|translate\">\n <ion-label translate>COMMON.BTN_VALIDATE</ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n </ion-footer>\n </ng-template>\n</ion-popover>\n", styles: [":host{--image-margin-inline: 10px}mat-toolbar,.mat-toolbar-single-row{padding:0;height:42px}ion-card{margin-left:unset;margin-right:unset;margin-inline:var(--image-margin-inline, 10px)}.image-slide{overflow:visible}.image-card{height:calc(100% - 23px);background-color:var(--ion-color-base);z-index:9;--img-scale: 1}.image-card .card-thumbnail{position:relative;overflow:hidden;display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:100%;height:100%}.image-card .card-thumbnail>img{min-height:100%;transition:scale .2s ease-in-out;scale:var(--img-scale);max-height:var(--img-max-height)}.image-card.zoom-hover:hover{--img-scale: 1.2}.image-card ion-toolbar{--top-offset: calc(-1 * var(--ion-toolbar-height));position:absolute}.image-card ion-toolbar.title{--padding-start: 16px;--padding-end: 16px;--ion-color-base: rgba(0,0,0,.45) !important;position:absolute;top:calc(100% + var(--top-offset));transition:opacity .2s ease-in-out}.image-card ion-toolbar.title ion-label{color:#fff}.image-card ion-toolbar.buttons{--padding-start: 4px;--padding-end: 4px;--ion-color-base: var(--ion-color-light) !important;position:absolute;top:100%;transition:transform .2s ease-in-out}.image-card:hover ion-toolbar.buttons,.image-card ion-toolbar.buttons.focused{transform:translateY(var(--top-offset))}.image-card-button{height:calc(100% - var(--image-margin-inline, 0px) * 2 - 3px);transition:.2s ease-in-out;max-width:250px}.image-card-button ion-card-content{height:100%}.image-card-button .icon-container{height:auto;position:relative;top:calc(50% - 75px);display:flex;align-items:center;justify-content:center}.image-card-button ion-icon:first-of-type{font-size:150px;height:150px;position:relative;top:0}.image-card-button ion-icon.icon-secondary{font-size:50px;position:absolute;top:0;left:max(min(50% + 25px,100% - 50px),0px)}.image-card-button ion-button{float:right}.image-card-button:hover{--ion-color-base: var(--ion-color-shade) !important}.image-card-button:hover ion-icon{--ion-color-base: var(--ion-color-shade) !important}.backdrop{height:100vh;width:100vw;background:black;position:absolute;z-index:10}.zoom-modal{-webkit-user-select:none;user-select:none}.zoom-modal .top-left{z-index:14;position:absolute;display:inline-grid;left:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}.zoom-modal .top-right{z-index:14;position:absolute;display:inline-grid;right:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}.zoom-modal .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)}.zoom-modal .side-buttons ion-icon{top:50%;color:#fff;font-size:2.5rem;position:absolute;opacity:0;transition-duration:.15s;transition-timing-function:ease-in}.zoom-modal .side-buttons:hover{cursor:pointer}.zoom-modal .side-buttons:hover ion-icon{opacity:1}.zoom-modal .side-buttons.prev{left:0}.zoom-modal .side-buttons.prev ion-icon{left:var(--side-buttons-margin)}.zoom-modal .side-buttons.next{right:0}.zoom-modal .side-buttons.next ion-icon{right:var(--side-buttons-margin)}.zoom-modal ion-slides{height:100%;background:black}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2$1.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: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i2$1.IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: i2$1.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: i2$1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonFab, selector: "ion-fab", inputs: ["activated", "edge", "horizontal", "vertical"] }, { kind: "component", type: i2$1.IonFabButton, selector: "ion-fab-button", inputs: ["activated", "closeIcon", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "show", "size", "target", "translucent", "type"] }, { kind: "component", type: i2$1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonSegment, selector: "ion-segment", inputs: ["color", "disabled", "mode", "scrollable", "selectOnFocus", "swipeGesture", "value"] }, { kind: "component", type: i2$1.IonSegmentButton, selector: "ion-segment-button", inputs: ["disabled", "layout", "mode", "type", "value"] }, { kind: "component", type: i2$1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: i2$1.IonModal, selector: "ion-modal" }, { kind: "component", type: i2$1.IonPopover, selector: "ion-popover" }, { kind: "directive", type: i2$1.SelectValueAccessor, selector: "ion-select, ion-radio-group, ion-segment, ion-datetime" }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i6$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "directive", type: i1$3.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "directive", type: i1$1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: NgInitDirective, selector: "[ngInit]", outputs: ["ngInit"] }, { kind: "directive", type: AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: NgVarDirective, selector: "[ngVar]", inputs: ["ngVar"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: PropertyGetPipe, name: "propertyGet" }, { kind: "pipe", type: ArrayLengthPipe, name: "isArrayLength" }, { kind: "pipe", type: IsNotNilOrBlankPipe, name: "isNotNilOrBlank" }], animations: [fadeInAnimation, fadeInOutAnimation], changeDetection: i0.ChangeDetectionStrategy.OnPush });
22833
22828
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: AppImageGalleryComponent, decorators: [{
22834
22829
  type: Component,
22835
- args: [{ selector: 'app-image-gallery', animations: [fadeInAnimation, fadeInOutAnimation], changeDetection: ChangeDetectionStrategy.OnPush, template: "\n\n<ion-toolbar color=\"light\" *ngIf=\"showToolbar\">\n <!-- Add -->\n <button mat-icon-button\n *ngIf=\"!readOnly && !mobile && enabled\"\n [title]=\"'COMMON.BTN_ADD'|translate\"\n (click)=\"add()\">\n <mat-icon>add</mat-icon>\n </button>\n\n <ion-buttons slot=\"end\">\n <!-- Toggle view mode -->\n <ion-segment (ionChange)=\"toggleViewMode($event)\" color=\"accent\"\n [value]=\"_colSize\">\n <ion-segment-button [value]=\"4\">\n <mat-icon>view_module</mat-icon>\n </ion-segment-button>\n <ion-segment-button [value]=\"12\">\n <mat-icon>view_list</mat-icon>\n </ion-segment-button>\n </ion-segment>\n </ion-buttons>\n</ion-toolbar>\n\n<div class=\"gallery-container {{this.mode}}\">\n <div *ngIf=\"mobile && zoomActive\" class=\"backdrop\" [style.opacity]=\"zoomScale\"></div>\n\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col *ngFor=\"let row of rows; index as index; trackBy: trackByFn\" [size]=\"_colSize\">\n <ion-card #card\n class=\"image-card\"\n [class.zoom-hover]=\"!mobile\"\n [color]=\"cardColor\"\n *ngVar=\"row|propertyGet: 'currentData'; let image\"\n (click)=\"clickRow(row, index)\"\n tappable\n @fadeInAnimation>\n <figure class=\"card-thumbnail\">\n <img [src]=\"image.url||image.dataUrl\"/>\n </figure>\n\n <!-- toolbar for title (when not hover) -->\n <ion-toolbar color=\"transparent\" class=\"title\">\n <ion-label class=\"card-title\">{{image.title}}</ion-label>\n </ion-toolbar>\n\n <!-- action toolbar (desktop only) shown when hover image -->\n <ion-toolbar #cardToolbar *ngIf=\"!mobile && !readOnly\" color=\"light\" class=\"buttons\">\n\n <!-- edit title button -->\n <button mat-button *ngIf=\"showTitle\" slot=\"start\"\n [disabled]=\"disabled\"\n (click)=\"editTitle($event, row, cardToolbar)\"\n (focusin)=\"showCardToolbar(cardToolbar)\">\n <mat-icon>edit</mat-icon>\n <mat-label>\n <span *ngIf=\"row.currentData.title|isNotNilOrBlank; else editLabel\" translate>IMAGE.GALLERY.BTN_EDIT_TITLE</span>\n <ng-template #editLabel>\n <span translate>IMAGE.GALLERY.BTN_ADD_TITLE</span>\n </ng-template>\n </mat-label>\n </button>\n\n <div class=\"flex-spacer\"></div>\n\n <!-- delete button -->\n <button mat-icon-button slot=\"end\"\n class=\"ion-float-end\"\n [title]=\"'COMMON.BTN_DELETE'|translate\"\n [disabled]=\"disabled\"\n (click)=\"delete($event, row)\">\n <mat-icon>delete</mat-icon>\n </button>\n </ion-toolbar>\n </ion-card>\n </ion-col>\n\n <ion-col *ngIf=\"showAddCardButton && !readOnly\" [size]=\"_colSize\" @fadeInAnimation>\n <ion-card class=\"image-card-button\" color=\"light\"\n (click)=\"add($event)\"\n [disabled]=\"disabled\"\n tappable>\n <ion-card-content>\n <div class=\"icon-container\">\n <ion-icon name=\"camera\" [color]=\"addButtonColor\"></ion-icon>\n <ion-icon name=\"add\" [color]=\"addButtonColor\" class=\"icon-secondary\"></ion-icon>\n </div>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n</div>\n\n<!-- FAB button: add -->\n<ion-fab slot=\"fixed\" vertical=\"bottom\" horizontal=\"end\"\n *ngIf=\"showFabButton && !readOnly\"\n [class.cdk-visually-hidden]=\"disabled\"\n @fadeInOutAnimation>\n\n <ion-fab-button color=\"tertiary\" (click)=\"add($event)\">\n <ion-icon name=\"camera\"></ion-icon>\n <ion-icon name=\"add\" class=\"icon-secondary\" style=\"left: 33px; top: 9px; font-size: 20px;\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n\n<!-- Zoom modal -->\n<ion-modal #zoomModal class=\"stack-modal zoom-modal\"\n [class.modal-fullscreen]=\"mobile\"\n [class.modal-large]=\"!mobile\">\n <ng-template>\n <ion-content class=\"ion-no-padding ion-no-margin\" >\n <!-- Counter -->\n <div class=\"top-left\" *ngVar=\"rows?.length as count\">\n <ion-label color=\"light\">\n {{activeSlideIndex + 1}} / {{count}}\n </ion-label>\n </div>\n\n <!-- zoom button -->\n <div class=\"top-right\">\n <ion-button *ngIf=\"!mobile\" (click)=\"zoom(modalSwiper, true)\" color=\"light\">\n <ion-icon slot=\"icon-only\" name=\"add\"></ion-icon>\n </ion-button>\n <ion-button *ngIf=\"!mobile\" (click)=\"zoom(modalSwiper, false)\" color=\"light\">\n <ion-icon name=\"remove\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n\n <!-- navigation side buttons next/back -->\n <ng-container *ngIf=\"!mobile && (rows|isArrayLength:{greaterThan: 1})\">\n <div class=\"side-buttons prev\"\n (click)=\"slidePrev(modalSwiper)\">\n <ion-icon name=\"chevron-back\"></ion-icon>\n </div>\n <div class=\"side-buttons next\"\n (click)=\"slideNext(modalSwiper)\">\n <ion-icon name=\"chevron-forward\"></ion-icon>\n </div>\n </ng-container>\n\n <!-- image slides -->\n <swiper-container #modalSwiper [modules]=\"swiperModules\" [zoom]=\"true\">\n <swiper-slide *ngFor=\"let row of rows; last as last\">\n <div class=\"swiper-zoom-container\" *ngIf=\"row|propertyGet: 'currentData'; let image\"\n (ngInit)=\"last && initModalSlides(modalSwiper)\">\n <img [src]=\"image.url||image.dataUrl\">\n </div>\n </swiper-slide>\n </swiper-container>\n </ion-content>\n\n <ion-footer>\n <ion-toolbar color=\"light\">\n <ion-row>\n <ion-col size=\"4\" class=\"ion-text-start\">\n <ion-button *ngIf=\"!readOnly\"\n (click)=\"deleteFromModal($event, modalSwiper)\"\n [disabled]=\"disabled\"\n fill=\"clear\" color=\"danger\">\n <mat-icon slot=\"start\">delete</mat-icon>\n {{'COMMON.BTN_DELETE'|translate}}\n </ion-button>\n </ion-col>\n <ion-col size=\"4\">\n </ion-col>\n <ion-col size=\"4\" class=\"ion-text-end\">\n <ion-button (click)=\"zoomModal.dismiss()\" 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)=\"zoomModal.dismiss()\" color=\"tertiary\">\n {{'COMMON.BTN_CLOSE'|translate}}\n </ion-button>\n </ng-template>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n </ion-footer>\n </ng-template>\n</ion-modal>\n\n<ion-popover #titlePopover>\n <ng-template>\n <ion-content class=\"ion-padding\" cdkTrapFocus [cdkTrapFocusAutoCapture]=\"true\" >\n <form [formGroup]=\"_titleForm\">\n <mat-form-field floatLabel=\"auto\">\n <mat-label translate>IMAGE.GALLERY.TITLE</mat-label>\n <input\n matInput\n formControlName=\"title\"\n [readonly]=\"disabled\"\n [appAutofocus]=\"_titleAutofocus\"\n (keydown.control.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n />\n\n </mat-form-field>\n </form>\n </ion-content>\n\n\n <ion-footer>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col>\n\n </ion-col>\n\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"titlePopover.dismiss(null, 'CANCEL')\">\n <ion-label translate>COMMON.BTN_CANCEL</ion-label>\n </ion-button>\n <ion-button\n [fill]=\"disabled ? 'clear' : 'solid'\"\n (click)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n (keyup.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n color=\"tertiary\"\n [disabled]=\"disabled\"\n [title]=\"'COMMON.BTN_VALIDATE_WITH_SHORTCUT_HELP'|translate\">\n <ion-label translate>COMMON.BTN_VALIDATE</ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n </ion-footer>\n </ng-template>\n</ion-popover>\n", styles: [":host{--image-margin-inline: 10px}mat-toolbar,.mat-toolbar-single-row{padding:0;height:42px}ion-card{margin-left:unset;margin-right:unset;margin-inline:var(--image-margin-inline, 10px)}.image-slide{overflow:visible}.image-card{height:calc(100% - 23px);background-color:var(--ion-color-base);z-index:9;--img-scale: 1}.image-card .card-thumbnail{position:relative;overflow:hidden;display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:100%;height:100%}.image-card .card-thumbnail>img{min-height:100%;transition:scale .2s ease-in-out;scale:var(--img-scale);max-height:var(--img-max-height)}.image-card.zoom-hover:hover{--img-scale: 1.2}.image-card ion-toolbar{--top-offset: calc(-1 * var(--ion-toolbar-height));position:absolute}.image-card ion-toolbar.title{--padding-start: 16px;--padding-end: 16px;--ion-color-base: rgba(0,0,0,.45) !important;position:absolute;top:calc(100% + var(--top-offset));transition:opacity .2s ease-in-out}.image-card ion-toolbar.title ion-label{color:#fff}.image-card ion-toolbar.buttons{--padding-start: 4px;--padding-end: 4px;--ion-color-base: var(--ion-color-light) !important;position:absolute;top:100%;transition:transform .2s ease-in-out}.image-card:hover ion-toolbar.buttons,.image-card ion-toolbar.buttons.focused{transform:translateY(var(--top-offset))}.image-card-button{height:calc(100% - var(--image-margin-inline, 0px) * 2 - 3px);transition:.2s ease-in-out;max-width:250px}.image-card-button ion-card-content{height:100%}.image-card-button .icon-container{height:auto;position:relative;top:calc(50% - 75px);display:flex;align-items:center;justify-content:center}.image-card-button ion-icon:first-of-type{font-size:150px;height:150px;position:relative;top:0}.image-card-button ion-icon.icon-secondary{font-size:50px;position:absolute;top:0;left:max(min(50% + 25px,100% - 50px),0px)}.image-card-button ion-button{float:right}.image-card-button:hover{--ion-color-base: var(--ion-color-shade) !important}.image-card-button:hover ion-icon{--ion-color-base: var(--ion-color-shade) !important}.backdrop{height:100vh;width:100vw;background:black;position:absolute;z-index:10}.zoom-modal{-webkit-user-select:none;user-select:none}.zoom-modal .top-left{z-index:14;position:absolute;display:inline-grid;left:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}.zoom-modal .top-right{z-index:14;position:absolute;display:inline-grid;right:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}.zoom-modal .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)}.zoom-modal .side-buttons ion-icon{top:50%;color:#fff;font-size:2.5rem;position:absolute;opacity:0;transition-duration:.15s;transition-timing-function:ease-in}.zoom-modal .side-buttons:hover{cursor:pointer}.zoom-modal .side-buttons:hover ion-icon{opacity:1}.zoom-modal .side-buttons.prev{left:0}.zoom-modal .side-buttons.prev ion-icon{left:var(--side-buttons-margin)}.zoom-modal .side-buttons.next{right:0}.zoom-modal .side-buttons.next ion-icon{right:var(--side-buttons-margin)}.zoom-modal ion-slides{height:100%;background:black}\n"] }]
22830
+ args: [{ selector: 'app-image-gallery', animations: [fadeInAnimation, fadeInOutAnimation], changeDetection: ChangeDetectionStrategy.OnPush, template: "\n\n<ion-toolbar color=\"light\" *ngIf=\"showToolbar\">\n <!-- Add -->\n <button mat-icon-button\n *ngIf=\"!readOnly && !mobile && enabled\"\n [title]=\"'COMMON.BTN_ADD'|translate\"\n (click)=\"add()\">\n <mat-icon>add</mat-icon>\n </button>\n\n <ion-buttons slot=\"end\">\n <!-- Toggle view mode -->\n <ion-segment (ionChange)=\"toggleViewMode($event)\" color=\"accent\"\n [value]=\"_colSize\">\n <ion-segment-button [value]=\"4\">\n <mat-icon>view_module</mat-icon>\n </ion-segment-button>\n <ion-segment-button [value]=\"12\">\n <mat-icon>view_list</mat-icon>\n </ion-segment-button>\n </ion-segment>\n </ion-buttons>\n</ion-toolbar>\n\n<div class=\"gallery-container {{this.mode}}\">\n <div *ngIf=\"mobile && zoomActive\" class=\"backdrop\" [style.opacity]=\"zoomScale\"></div>\n\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col *ngFor=\"let row of rows; index as index; trackBy: trackByFn\" [size]=\"_colSize\">\n <ion-card #card\n class=\"image-card\"\n [class.zoom-hover]=\"!mobile\"\n [color]=\"cardColor\"\n *ngVar=\"row|propertyGet: 'currentData'; let image\"\n (click)=\"clickRow(row, index)\"\n tappable\n @fadeInAnimation>\n <figure class=\"card-thumbnail\">\n <img [src]=\"image.url||image.dataUrl\"/>\n </figure>\n\n <!-- toolbar for title (when not hover) -->\n <ion-toolbar color=\"transparent\" class=\"title\" *ngIf=\"image.title\">\n <ion-label class=\"card-title\">{{image.title}}</ion-label>\n </ion-toolbar>\n\n <!-- action toolbar (desktop only) shown when hover image -->\n <ion-toolbar #cardToolbar *ngIf=\"!mobile && !readOnly\" color=\"light\" class=\"buttons\">\n\n <!-- edit title button -->\n <button mat-button *ngIf=\"showTitle\" slot=\"start\"\n [disabled]=\"disabled\"\n (click)=\"editTitle($event, row, cardToolbar)\"\n (focusin)=\"showCardToolbar(cardToolbar)\">\n <mat-icon>edit</mat-icon>\n <mat-label>\n <span *ngIf=\"row.currentData.title|isNotNilOrBlank; else editLabel\" translate>IMAGE.GALLERY.BTN_EDIT_TITLE</span>\n <ng-template #editLabel>\n <span translate>IMAGE.GALLERY.BTN_ADD_TITLE</span>\n </ng-template>\n </mat-label>\n </button>\n\n <div class=\"flex-spacer\"></div>\n\n <!-- delete button -->\n <button mat-icon-button slot=\"end\"\n class=\"ion-float-end\"\n [title]=\"'COMMON.BTN_DELETE'|translate\"\n [disabled]=\"disabled\"\n (click)=\"delete($event, row)\">\n <mat-icon>delete</mat-icon>\n </button>\n </ion-toolbar>\n </ion-card>\n </ion-col>\n\n <ion-col *ngIf=\"showAddCardButton && !readOnly\" [size]=\"_colSize\" @fadeInAnimation>\n <ion-card class=\"image-card-button\" color=\"light\"\n (click)=\"add($event)\"\n [disabled]=\"disabled\"\n tappable>\n <ion-card-content>\n <div class=\"icon-container\">\n <ion-icon name=\"camera\" [color]=\"addButtonColor\"></ion-icon>\n <ion-icon name=\"add\" [color]=\"addButtonColor\" class=\"icon-secondary\"></ion-icon>\n </div>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n</div>\n\n<!-- FAB button: add -->\n<ion-fab slot=\"fixed\" vertical=\"bottom\" horizontal=\"end\"\n *ngIf=\"showFabButton && !readOnly\"\n [class.cdk-visually-hidden]=\"disabled\"\n @fadeInOutAnimation>\n\n <ion-fab-button color=\"tertiary\" (click)=\"add($event)\">\n <ion-icon name=\"camera\"></ion-icon>\n <ion-icon name=\"add\" class=\"icon-secondary\" style=\"left: 33px; top: 9px; font-size: 20px;\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n\n<!-- Zoom modal -->\n<ion-modal #zoomModal class=\"stack-modal zoom-modal\"\n [class.modal-fullscreen]=\"mobile\"\n [class.modal-large]=\"!mobile\">\n <ng-template>\n <ion-content class=\"ion-no-padding ion-no-margin\" >\n <!-- Counter -->\n <div class=\"top-left\" *ngVar=\"rows?.length as count\">\n <ion-label color=\"light\">\n {{activeSlideIndex + 1}} / {{count}}\n </ion-label>\n </div>\n\n <!-- zoom button -->\n <div class=\"top-right\">\n <ion-button *ngIf=\"!mobile\" (click)=\"zoom(modalSwiper, true)\" color=\"light\">\n <ion-icon slot=\"icon-only\" name=\"add\"></ion-icon>\n </ion-button>\n <ion-button *ngIf=\"!mobile\" (click)=\"zoom(modalSwiper, false)\" color=\"light\">\n <ion-icon name=\"remove\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n\n <!-- navigation side buttons next/back -->\n <ng-container *ngIf=\"!mobile && (rows|isArrayLength:{greaterThan: 1})\">\n <div class=\"side-buttons prev\"\n (click)=\"slidePrev(modalSwiper)\">\n <ion-icon name=\"chevron-back\"></ion-icon>\n </div>\n <div class=\"side-buttons next\"\n (click)=\"slideNext(modalSwiper)\">\n <ion-icon name=\"chevron-forward\"></ion-icon>\n </div>\n </ng-container>\n\n <!-- image slides -->\n <swiper-container #modalSwiper [modules]=\"swiperModules\" [zoom]=\"true\">\n <swiper-slide *ngFor=\"let row of rows; last as last\">\n <div class=\"swiper-zoom-container\" *ngIf=\"row|propertyGet: 'currentData'; let image\"\n (ngInit)=\"last && initModalSlides(modalSwiper)\">\n <img [src]=\"image.url||image.dataUrl\">\n </div>\n </swiper-slide>\n </swiper-container>\n </ion-content>\n\n <ion-footer>\n <ion-toolbar color=\"light\">\n <ion-row>\n <ion-col size=\"4\" class=\"ion-text-start\">\n <ion-button *ngIf=\"!readOnly\"\n (click)=\"deleteFromModal($event, modalSwiper)\"\n [disabled]=\"disabled\"\n fill=\"clear\" color=\"danger\">\n <mat-icon slot=\"start\">delete</mat-icon>\n {{'COMMON.BTN_DELETE'|translate}}\n </ion-button>\n </ion-col>\n <ion-col size=\"4\">\n </ion-col>\n <ion-col size=\"4\" class=\"ion-text-end\">\n <ion-button (click)=\"zoomModal.dismiss()\" 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)=\"zoomModal.dismiss()\" color=\"tertiary\">\n {{'COMMON.BTN_CLOSE'|translate}}\n </ion-button>\n </ng-template>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n </ion-footer>\n </ng-template>\n</ion-modal>\n\n<ion-popover #titlePopover>\n <ng-template>\n <ion-content class=\"ion-padding\" cdkTrapFocus [cdkTrapFocusAutoCapture]=\"true\" >\n <form [formGroup]=\"_titleForm\">\n <mat-form-field floatLabel=\"auto\">\n <mat-label translate>IMAGE.GALLERY.TITLE</mat-label>\n <input\n matInput\n formControlName=\"title\"\n [readonly]=\"disabled\"\n [appAutofocus]=\"_titleAutofocus\"\n (keydown.control.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n />\n\n </mat-form-field>\n </form>\n </ion-content>\n\n\n <ion-footer>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col>\n\n </ion-col>\n\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"titlePopover.dismiss(null, 'CANCEL')\">\n <ion-label translate>COMMON.BTN_CANCEL</ion-label>\n </ion-button>\n <ion-button\n [fill]=\"disabled ? 'clear' : 'solid'\"\n (click)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n (keyup.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n color=\"tertiary\"\n [disabled]=\"disabled\"\n [title]=\"'COMMON.BTN_VALIDATE_WITH_SHORTCUT_HELP'|translate\">\n <ion-label translate>COMMON.BTN_VALIDATE</ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n </ion-footer>\n </ng-template>\n</ion-popover>\n", styles: [":host{--image-margin-inline: 10px}mat-toolbar,.mat-toolbar-single-row{padding:0;height:42px}ion-card{margin-left:unset;margin-right:unset;margin-inline:var(--image-margin-inline, 10px)}.image-slide{overflow:visible}.image-card{height:calc(100% - 23px);background-color:var(--ion-color-base);z-index:9;--img-scale: 1}.image-card .card-thumbnail{position:relative;overflow:hidden;display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:100%;height:100%}.image-card .card-thumbnail>img{min-height:100%;transition:scale .2s ease-in-out;scale:var(--img-scale);max-height:var(--img-max-height)}.image-card.zoom-hover:hover{--img-scale: 1.2}.image-card ion-toolbar{--top-offset: calc(-1 * var(--ion-toolbar-height));position:absolute}.image-card ion-toolbar.title{--padding-start: 16px;--padding-end: 16px;--ion-color-base: rgba(0,0,0,.45) !important;position:absolute;top:calc(100% + var(--top-offset));transition:opacity .2s ease-in-out}.image-card ion-toolbar.title ion-label{color:#fff}.image-card ion-toolbar.buttons{--padding-start: 4px;--padding-end: 4px;--ion-color-base: var(--ion-color-light) !important;position:absolute;top:100%;transition:transform .2s ease-in-out}.image-card:hover ion-toolbar.buttons,.image-card ion-toolbar.buttons.focused{transform:translateY(var(--top-offset))}.image-card-button{height:calc(100% - var(--image-margin-inline, 0px) * 2 - 3px);transition:.2s ease-in-out;max-width:250px}.image-card-button ion-card-content{height:100%}.image-card-button .icon-container{height:auto;position:relative;top:calc(50% - 75px);display:flex;align-items:center;justify-content:center}.image-card-button ion-icon:first-of-type{font-size:150px;height:150px;position:relative;top:0}.image-card-button ion-icon.icon-secondary{font-size:50px;position:absolute;top:0;left:max(min(50% + 25px,100% - 50px),0px)}.image-card-button ion-button{float:right}.image-card-button:hover{--ion-color-base: var(--ion-color-shade) !important}.image-card-button:hover ion-icon{--ion-color-base: var(--ion-color-shade) !important}.backdrop{height:100vh;width:100vw;background:black;position:absolute;z-index:10}.zoom-modal{-webkit-user-select:none;user-select:none}.zoom-modal .top-left{z-index:14;position:absolute;display:inline-grid;left:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}.zoom-modal .top-right{z-index:14;position:absolute;display:inline-grid;right:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}.zoom-modal .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)}.zoom-modal .side-buttons ion-icon{top:50%;color:#fff;font-size:2.5rem;position:absolute;opacity:0;transition-duration:.15s;transition-timing-function:ease-in}.zoom-modal .side-buttons:hover{cursor:pointer}.zoom-modal .side-buttons:hover ion-icon{opacity:1}.zoom-modal .side-buttons.prev{left:0}.zoom-modal .side-buttons.prev ion-icon{left:var(--side-buttons-margin)}.zoom-modal .side-buttons.next{right:0}.zoom-modal .side-buttons.next ion-icon{right:var(--side-buttons-margin)}.zoom-modal ion-slides{height:100%;background:black}\n"] }]
22836
22831
  }], ctorParameters: function () {
22837
22832
  return [{ type: ImageService }, { type: i2$1.Platform }, { type: i2$1.AlertController }, { type: i2$1.PopoverController }, { type: i1$1.TranslateService }, { type: i0.ChangeDetectorRef }, { type: Environment, decorators: [{
22838
22833
  type: Optional