@sumaris-net/ngx-components 18.25.4 → 18.25.6

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 (34) hide show
  1. package/doc/changelog.md +12 -0
  2. package/esm2022/public_api.mjs +4 -1
  3. package/esm2022/src/app/core/form/properties/properties.form.mjs +1 -1
  4. package/esm2022/src/app/core/table/testing/nested-table.testing.mjs +1 -1
  5. package/esm2022/src/app/core/table/testing/table.testing.mjs +1 -1
  6. package/esm2022/src/app/core/table/testing/table2.testing.mjs +1 -1
  7. package/esm2022/src/app/shared/form/field.component.mjs +1 -1
  8. package/esm2022/src/app/shared/image/gallery/image-gallery.component.mjs +82 -82
  9. package/esm2022/src/app/shared/image/gallery/image-gallery.model.mjs +2 -0
  10. package/esm2022/src/app/shared/image/gallery/image-gallery.module.mjs +8 -3
  11. package/esm2022/src/app/shared/image/gallery/slideshow/image-gallery-slideshow.component.mjs +685 -0
  12. package/esm2022/src/app/shared/image/gallery/testing/gallery.testing.mjs +16 -9
  13. package/esm2022/src/app/shared/material/autocomplete/material.autocomplete.directive.mjs +25 -0
  14. package/esm2022/src/app/shared/material/autocomplete/material.autocomplete.mjs +20 -18
  15. package/esm2022/src/app/shared/material/autocomplete/material.autocomplete.module.mjs +6 -5
  16. package/esm2022/src/app/shared/material/autocomplete/testing/autocomplete.test.mjs +5 -4
  17. package/esm2022/src/app/shared/named-filter/named-filter-selector.component.mjs +1 -1
  18. package/fesm2022/sumaris-net.ngx-components.mjs +817 -111
  19. package/fesm2022/sumaris-net.ngx-components.mjs.map +1 -1
  20. package/package.json +1 -1
  21. package/public_api.d.ts +3 -0
  22. package/src/app/shared/image/gallery/image-gallery.component.d.ts +42 -21
  23. package/src/app/shared/image/gallery/image-gallery.model.d.ts +11 -0
  24. package/src/app/shared/image/gallery/image-gallery.module.d.ts +10 -9
  25. package/src/app/shared/image/gallery/slideshow/image-gallery-slideshow.component.d.ts +149 -0
  26. package/src/app/shared/image/gallery/testing/gallery.testing.d.ts +6 -1
  27. package/src/app/shared/material/autocomplete/material.autocomplete.d.ts +8 -9
  28. package/src/app/shared/material/autocomplete/material.autocomplete.directive.d.ts +9 -0
  29. package/src/app/shared/material/autocomplete/material.autocomplete.module.d.ts +18 -17
  30. package/src/assets/i18n/en-US.json +6 -0
  31. package/src/assets/i18n/en.json +6 -0
  32. package/src/assets/i18n/fr.json +6 -0
  33. package/src/assets/manifest.json +1 -1
  34. package/src/theme/_ngx-components.scss +15 -5
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sumaris-net/ngx-components",
3
3
  "description": "SUMARiS Angular components",
4
- "version": "18.25.4",
4
+ "version": "18.25.6",
5
5
  "author": "contact@e-is.pro",
6
6
  "license": "AGPL-3.0",
7
7
  "readmeFilename": "README.md",
package/public_api.d.ts CHANGED
@@ -13,6 +13,7 @@ export * from './src/app/shared/material/boolean/boolean.module';
13
13
  export { MatBooleanField } from './src/app/shared/material/boolean/material.boolean';
14
14
  export * from './src/app/shared/material/autocomplete/material.autocomplete.module';
15
15
  export * from './src/app/shared/material/autocomplete/material.autocomplete';
16
+ export * from './src/app/shared/material/autocomplete/material.autocomplete.directive';
16
17
  export * from './src/app/shared/material/autocomplete/material.autocomplete.config';
17
18
  export * from './src/app/shared/material/autocomplete/material.autocomplete.utils';
18
19
  export * from './src/app/shared/material/chips/chips.module';
@@ -47,6 +48,7 @@ export * from './src/app/shared/guard/component-dirty.guard';
47
48
  export * from './src/app/shared/upload-file/upload-file.model';
48
49
  export * from './src/app/shared/upload-file/upload-file-popover.component';
49
50
  export * from './src/app/shared/upload-file/upload-file.component';
51
+ export * from './src/app/shared/image/gallery/slideshow/image-gallery-slideshow.component';
50
52
  export * from './src/app/shared/image/gallery/image-gallery.component';
51
53
  export * from './src/app/shared/image/gallery/image-gallery.module';
52
54
  export * from './src/app/shared/image/image.model';
@@ -365,3 +367,4 @@ export * from './src/app/social/job/testing/job.testing.module';
365
367
  export * from './src/app/social/job/testing/job-progression.testing';
366
368
  export * from './src/app/social/job/testing/job-progression.testing.service';
367
369
  export * from './src/app/core/table/testing/table-validator.service';
370
+ export * from './src/app/shared/image/gallery/image-gallery.model';
@@ -1,4 +1,4 @@
1
- import { AfterContentChecked, ChangeDetectorRef, ElementRef, EventEmitter, OnDestroy, OnInit, TemplateRef } from '@angular/core';
1
+ import { AfterContentChecked, ChangeDetectorRef, EventEmitter, OnDestroy, OnInit, TemplateRef } from '@angular/core';
2
2
  import { BehaviorSubject, Subject, Subscription } from 'rxjs';
3
3
  import { TableDataSource, TableElement } from '@e-is/ngx-material-table';
4
4
  import { Environment } from '../../../../environments/environment.class';
@@ -9,15 +9,12 @@ import { CollectionViewer, ListRange } from '@angular/cdk/collections';
9
9
  import { TranslateService } from '@ngx-translate/core';
10
10
  import { AppColors } from '../../types';
11
11
  import { FormGroup } from '@angular/forms';
12
+ import { PromiseEvent } from '../../events';
12
13
  import { PredefinedColors } from '@ionic/core';
13
- import { Swiper } from 'swiper/types';
14
14
  import { ImageOptions } from '@capacitor/camera';
15
+ import { GalleryMode, ImageEditEvent, ImageExportFormat } from './image-gallery.model';
15
16
  import * as i0 from "@angular/core";
16
- export type GalleryMode = 'mosaic' | 'list';
17
- export interface ISwiper extends Swiper {
18
- activeIndex: number;
19
- imagesLoaded: number;
20
- }
17
+ export type ImageGalleryZoomPresentation = 'modal' | 'inline';
21
18
  export interface ImageGallerySizes {
22
19
  mosaic: ImageSize | string;
23
20
  list: ImageSize | string;
@@ -40,10 +37,13 @@ export declare class AppImageGalleryComponent<T extends Image> implements OnInit
40
37
  protected _titleForm: FormGroup;
41
38
  protected _titleAutofocus: boolean;
42
39
  protected _slidesSubscription: Subscription;
43
- protected _swiper: Swiper;
44
- protected swiperModules: ((opts: any) => void)[];
45
40
  protected zoomActive: boolean;
46
41
  protected zoomScale: number;
42
+ protected _mouseZoomEnabled: boolean;
43
+ protected _rotationEnabled: boolean;
44
+ protected _cropEnabled: boolean;
45
+ /** Whether the inline slideshow overlay is currently shown (only relevant when zoomPresentation === 'inline'). */
46
+ protected _inlineSlideshowActive: boolean;
47
47
  viewChange: BehaviorSubject<ListRange>;
48
48
  cardColor: string | PredefinedColors;
49
49
  debug: boolean;
@@ -68,20 +68,37 @@ export declare class AppImageGalleryComponent<T extends Image> implements OnInit
68
68
  }>;
69
69
  imageSizes: ImageGallerySizes;
70
70
  imageSizeQueryParam: string;
71
+ /** Enable mouse-wheel zoom and mouse-drag pan in the slideshow (defaults to true on desktop). */
72
+ enableMouseZoom: boolean;
73
+ /** Zoom step applied on each mouse-wheel tick (default 0.3). */
74
+ wheelZoomStep: number;
75
+ /** Maximum zoom ratio reachable via mouse wheel (default 3). */
76
+ maxZoomRatio: number;
77
+ /** Enable 90° rotation buttons in the slideshow (defaults to true). */
78
+ enableRotation: boolean;
79
+ /** Enable the crop tool in the slideshow (defaults to true). */
80
+ enableCrop: boolean;
81
+ /** Image format used when emitting the edited (cropped/rotated) image. */
82
+ imageExportFormat: ImageExportFormat;
83
+ /** Export quality, applied only when imageExportFormat is 'jpeg' (0 to 1). */
84
+ imageExportQuality: number;
85
+ /** Where to show the slideshow: in a full-screen modal (default), or inline, as an overlay over the gallery itself (desktop only). */
86
+ zoomPresentation: ImageGalleryZoomPresentation;
87
+ /** Height of the inline slideshow overlay (CSS value, e.g. '60vh'). Only used when zoomPresentation is 'inline'. */
88
+ inlineZoomHeight: string;
71
89
  set dataSource(dataSource: TableDataSource<T, any, any, any>);
72
90
  get dataSource(): TableDataSource<T, any, any, any>;
73
91
  get enabled(): boolean;
74
92
  get rows(): TableElement<T>[] | ReadonlyArray<TableElement<T>>;
75
93
  get rowCount(): number;
76
- get activeIndex(): number;
77
94
  zoomModal: IonModal;
78
95
  titlePopover: IonPopover;
79
- swiperRef: ElementRef;
80
- onBeforeDeleteRows: EventEmitter<import("../../events").PromiseEvent<boolean, {
96
+ onBeforeDeleteRows: EventEmitter<PromiseEvent<boolean, {
81
97
  rows: TableElement<T>[];
82
98
  }>>;
83
99
  onAfterAddRows: EventEmitter<TableElement<T>[]>;
84
100
  onAfterEditRow: EventEmitter<TableElement<T>>;
101
+ onAfterEditImage: EventEmitter<ImageEditEvent<T>>;
85
102
  click: EventEmitter<T>;
86
103
  showTooltip: boolean;
87
104
  constructor(imageService: ImageService, platform: Platform, alterCtrl: AlertController, translate: TranslateService, cd: ChangeDetectorRef, environment?: Environment);
@@ -108,14 +125,15 @@ export declare class AppImageGalleryComponent<T extends Image> implements OnInit
108
125
  protected _observeRenderChanges(): void;
109
126
  protected getTableUnknownDataSourceError(): Error;
110
127
  protected clickRow(row: TableElement<T>, index: number): Promise<void>;
111
- protected activeSlideIndex: number;
112
- protected getSwiper(swiperElement?: any): Swiper;
113
- protected onSlideChange(swiperElement: any): void;
114
- protected initModalSlides(swiperElement: any): void;
115
- protected zoom(swiperElement: any, zoomIn: boolean): Promise<void>;
116
- protected deleteFromModal(event: any, swiperElement: any): Promise<boolean>;
117
- protected slidePrev(swiperElement: any): Promise<void>;
118
- protected slideNext(swiperElement: any): Promise<void>;
128
+ protected closeInlineSlideshow(): void;
129
+ /**
130
+ * Handles a delete request coming from the slideshow component (either inline or in the modal):
131
+ * runs the same confirmation/deletion flow as a card's delete button, then resolves the promise
132
+ * so the slideshow knows whether to reset its zoom or close.
133
+ */
134
+ protected onSlideshowDeleteRequested(promiseEvent: PromiseEvent<boolean, {
135
+ row: TableElement<T>;
136
+ }>): Promise<void>;
119
137
  protected canDeleteRows(rows: TableElement<T>[], opts?: {
120
138
  interactive?: boolean;
121
139
  }): Promise<boolean>;
@@ -124,7 +142,7 @@ export declare class AppImageGalleryComponent<T extends Image> implements OnInit
124
142
  };
125
143
  protected markForCheck(): void;
126
144
  static ɵfac: i0.ɵɵFactoryDeclaration<AppImageGalleryComponent<any>, [null, null, null, null, null, { optional: true; }]>;
127
- static ɵcmp: i0.ɵɵComponentDeclaration<AppImageGalleryComponent<any>, "app-image-gallery", never, { "cardColor": { "alias": "cardColor"; "required": false; }; "debug": { "alias": "debug"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "readOnly": { "alias": "readOnly"; "required": false; }; "mobile": { "alias": "mobile"; "required": false; }; "mode": { "alias": "mode"; "required": false; }; "confirmBeforeDelete": { "alias": "confirmBeforeDelete"; "required": false; }; "showToolbar": { "alias": "showToolbar"; "required": false; }; "showFabButton": { "alias": "showFabButton"; "required": false; }; "showTitle": { "alias": "showTitle"; "required": false; }; "showAddToolbarButton": { "alias": "showAddToolbarButton"; "required": false; }; "showAddTextButton": { "alias": "showAddTextButton"; "required": false; }; "showAddCardButton": { "alias": "showAddCardButton"; "required": false; }; "showCardToolbar": { "alias": "showCardToolbar"; "required": false; }; "addButtonColor": { "alias": "addButtonColor"; "required": false; }; "addButtonText": { "alias": "addButtonText"; "required": false; }; "cardTemplate": { "alias": "cardTemplate"; "required": false; }; "imageSizes": { "alias": "imageSizes"; "required": false; }; "imageSizeQueryParam": { "alias": "imageSizeQueryParam"; "required": false; }; "dataSource": { "alias": "dataSource"; "required": false; }; }, { "onBeforeDeleteRows": "onBeforeDeleteRows"; "onAfterAddRows": "onAfterAddRows"; "onAfterEditRow": "onAfterEditRow"; "click": "click"; }, never, ["ion-buttons[slot=start]", "ion-buttons[slot=end]"], false, never>;
145
+ static ɵcmp: i0.ɵɵComponentDeclaration<AppImageGalleryComponent<any>, "app-image-gallery", never, { "cardColor": { "alias": "cardColor"; "required": false; }; "debug": { "alias": "debug"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "readOnly": { "alias": "readOnly"; "required": false; }; "mobile": { "alias": "mobile"; "required": false; }; "mode": { "alias": "mode"; "required": false; }; "confirmBeforeDelete": { "alias": "confirmBeforeDelete"; "required": false; }; "showToolbar": { "alias": "showToolbar"; "required": false; }; "showFabButton": { "alias": "showFabButton"; "required": false; }; "showTitle": { "alias": "showTitle"; "required": false; }; "showAddToolbarButton": { "alias": "showAddToolbarButton"; "required": false; }; "showAddTextButton": { "alias": "showAddTextButton"; "required": false; }; "showAddCardButton": { "alias": "showAddCardButton"; "required": false; }; "showCardToolbar": { "alias": "showCardToolbar"; "required": false; }; "addButtonColor": { "alias": "addButtonColor"; "required": false; }; "addButtonText": { "alias": "addButtonText"; "required": false; }; "cardTemplate": { "alias": "cardTemplate"; "required": false; }; "imageSizes": { "alias": "imageSizes"; "required": false; }; "imageSizeQueryParam": { "alias": "imageSizeQueryParam"; "required": false; }; "enableMouseZoom": { "alias": "enableMouseZoom"; "required": false; }; "wheelZoomStep": { "alias": "wheelZoomStep"; "required": false; }; "maxZoomRatio": { "alias": "maxZoomRatio"; "required": false; }; "enableRotation": { "alias": "enableRotation"; "required": false; }; "enableCrop": { "alias": "enableCrop"; "required": false; }; "imageExportFormat": { "alias": "imageExportFormat"; "required": false; }; "imageExportQuality": { "alias": "imageExportQuality"; "required": false; }; "zoomPresentation": { "alias": "zoomPresentation"; "required": false; }; "inlineZoomHeight": { "alias": "inlineZoomHeight"; "required": false; }; "dataSource": { "alias": "dataSource"; "required": false; }; }, { "onBeforeDeleteRows": "onBeforeDeleteRows"; "onAfterAddRows": "onAfterAddRows"; "onAfterEditRow": "onAfterEditRow"; "onAfterEditImage": "onAfterEditImage"; "click": "click"; }, never, ["ion-buttons[slot=start]", "ion-buttons[slot=end]"], false, never>;
128
146
  static ngAcceptInputType_debug: unknown;
129
147
  static ngAcceptInputType_disabled: unknown;
130
148
  static ngAcceptInputType_readOnly: unknown;
@@ -136,4 +154,7 @@ export declare class AppImageGalleryComponent<T extends Image> implements OnInit
136
154
  static ngAcceptInputType_showAddTextButton: unknown;
137
155
  static ngAcceptInputType_showAddCardButton: unknown;
138
156
  static ngAcceptInputType_showCardToolbar: unknown;
157
+ static ngAcceptInputType_enableMouseZoom: unknown;
158
+ static ngAcceptInputType_enableRotation: unknown;
159
+ static ngAcceptInputType_enableCrop: unknown;
139
160
  }
@@ -0,0 +1,11 @@
1
+ import { Image } from '../image.model';
2
+ import { TableElement } from '@e-is/ngx-material-table';
3
+ export type GalleryMode = 'mosaic' | 'list';
4
+ export type ImageExportFormat = 'png' | 'jpeg';
5
+ export interface ImageEditEvent<T extends Image = Image> {
6
+ row: TableElement<T>;
7
+ image: T;
8
+ dataUrl: string;
9
+ blob: Blob;
10
+ format: ImageExportFormat;
11
+ }
@@ -1,15 +1,16 @@
1
1
  import * as i0 from "@angular/core";
2
2
  import * as i1 from "./image-gallery.component";
3
- import * as i2 from "@angular/common";
4
- import * as i3 from "@ionic/angular";
5
- import * as i4 from "@angular/forms";
6
- import * as i5 from "../../material/material.module";
7
- import * as i6 from "../../pipes/pipes.module";
8
- import * as i7 from "../../directives/directives.module";
9
- import * as i8 from "@ngx-translate/core";
10
- import * as i9 from "../../rx-state/rx-state.module";
3
+ import * as i2 from "./slideshow/image-gallery-slideshow.component";
4
+ import * as i3 from "@angular/common";
5
+ import * as i4 from "@ionic/angular";
6
+ import * as i5 from "@angular/forms";
7
+ import * as i6 from "../../material/material.module";
8
+ import * as i7 from "../../pipes/pipes.module";
9
+ import * as i8 from "../../directives/directives.module";
10
+ import * as i9 from "@ngx-translate/core";
11
+ import * as i10 from "../../rx-state/rx-state.module";
11
12
  export declare class ImageGalleryModule {
12
13
  static ɵfac: i0.ɵɵFactoryDeclaration<ImageGalleryModule, never>;
13
- static ɵmod: i0.ɵɵNgModuleDeclaration<ImageGalleryModule, [typeof i1.AppImageGalleryComponent], [typeof i2.CommonModule, typeof i3.IonicModule, typeof i4.ReactiveFormsModule, typeof i5.SharedMaterialModule, typeof i6.SharedPipesModule, typeof i7.SharedDirectivesModule, typeof i8.TranslateModule, typeof i9.RxStateModule], [typeof i3.IonicModule, typeof i8.TranslateModule, typeof i1.AppImageGalleryComponent]>;
14
+ static ɵmod: i0.ɵɵNgModuleDeclaration<ImageGalleryModule, [typeof i1.AppImageGalleryComponent, typeof i2.AppImageGallerySlideshowComponent], [typeof i3.CommonModule, typeof i4.IonicModule, typeof i5.ReactiveFormsModule, typeof i6.SharedMaterialModule, typeof i7.SharedPipesModule, typeof i8.SharedDirectivesModule, typeof i9.TranslateModule, typeof i10.RxStateModule], [typeof i4.IonicModule, typeof i9.TranslateModule, typeof i1.AppImageGalleryComponent, typeof i2.AppImageGallerySlideshowComponent]>;
14
15
  static ɵinj: i0.ɵɵInjectorDeclaration<ImageGalleryModule>;
15
16
  }
@@ -0,0 +1,149 @@
1
+ import { ChangeDetectorRef, ElementRef, EventEmitter, OnDestroy } from '@angular/core';
2
+ import { TableElement } from '@e-is/ngx-material-table';
3
+ import { AlertController } from '@ionic/angular';
4
+ import { TranslateService } from '@ngx-translate/core';
5
+ import { Swiper } from 'swiper/types';
6
+ import { Image, ImageSize } from '../../image.model';
7
+ import { ImageEditEvent, ImageExportFormat } from '../image-gallery.model';
8
+ import * as i0 from "@angular/core";
9
+ interface CropRect {
10
+ x: number;
11
+ y: number;
12
+ width: number;
13
+ height: number;
14
+ }
15
+ type CropHandle = 'move' | 'nw' | 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w';
16
+ /**
17
+ * The zoom/pan/rotate/crop slideshow shown when clicking an image in `AppImageGalleryComponent`.
18
+ * Extracted into its own component so the exact same slideshow can be presented either inside an
19
+ * `ion-modal` (default), or inline as an overlay directly within the gallery, without any duplication.
20
+ */
21
+ export declare class AppImageGallerySlideshowComponent<T extends Image = Image> implements OnDestroy {
22
+ protected alterCtrl: AlertController;
23
+ protected translate: TranslateService;
24
+ protected cd: ChangeDetectorRef;
25
+ protected activeSlideIndex: number;
26
+ protected swiperModules: ((opts: any) => void)[];
27
+ protected _swiper: Swiper;
28
+ protected _zoomState: {
29
+ scale: number;
30
+ tx: number;
31
+ ty: number;
32
+ };
33
+ protected _rotation: number;
34
+ protected _dragState: {
35
+ startX: number;
36
+ startY: number;
37
+ startTx: number;
38
+ startTy: number;
39
+ } | null;
40
+ protected _wheelListener: ((e: WheelEvent) => void) | null;
41
+ protected _wheelEl: HTMLElement | null;
42
+ protected _cropToolActive: boolean;
43
+ protected _cropRect: CropRect;
44
+ protected _cropOverlayRect: {
45
+ width: number;
46
+ height: number;
47
+ } | null;
48
+ protected _cropDragState: {
49
+ handle: CropHandle;
50
+ startX: number;
51
+ startY: number;
52
+ startRect: CropRect;
53
+ } | null;
54
+ protected readonly _cropHandles: CropHandle[];
55
+ rows: TableElement<T>[] | ReadonlyArray<TableElement<T>>;
56
+ selectedIndex: number;
57
+ mobile: boolean;
58
+ readOnly: boolean;
59
+ disabled: boolean;
60
+ debug: boolean;
61
+ mouseZoomEnabled: boolean;
62
+ wheelZoomStep: number;
63
+ maxZoomRatio: number;
64
+ rotationEnabled: boolean;
65
+ cropEnabled: boolean;
66
+ imageExportFormat: ImageExportFormat;
67
+ imageExportQuality: number;
68
+ imageSizeQueryParam: string;
69
+ modalImageSize: ImageSize | string;
70
+ /** Requests deletion of the given row. The caller (gallery) owns the confirmation/deletion logic and resolves the promise with whether it actually happened. */
71
+ deleteRequested: EventEmitter<import("../../../events").PromiseEvent<boolean, {
72
+ row: TableElement<T>;
73
+ }>>;
74
+ closeRequested: EventEmitter<void>;
75
+ afterEditImage: EventEmitter<ImageEditEvent<T>>;
76
+ afterEditRow: EventEmitter<TableElement<T>>;
77
+ swiperRef: ElementRef;
78
+ showTooltip: boolean;
79
+ protected get hasPendingEdit(): boolean;
80
+ constructor(alterCtrl: AlertController, translate: TranslateService, cd: ChangeDetectorRef);
81
+ ngOnDestroy(): void;
82
+ protected getSwiper(swiperElement?: any): Swiper;
83
+ protected onSlideChange(swiperElement: any): void;
84
+ protected onSwiperInit(swiperElement: any): void;
85
+ /**
86
+ * Swiper's own touch/mouse-drag-to-swipe gesture is captured very early (before our crop overlay's
87
+ * own mousedown handler can stop it), so it must be disabled upfront whenever the crop tool is active
88
+ * -- otherwise dragging inside the crop selection ends up sliding to the next/previous image instead.
89
+ * Prev/next arrow buttons keep working, since they call the Swiper API directly.
90
+ */
91
+ protected _updateSwiperTouchMove(swiperElement: any): void;
92
+ protected zoom(swiperElement: any, zoomIn: boolean): Promise<void>;
93
+ protected requestDelete(swiperElement: any): Promise<boolean>;
94
+ protected slidePrev(swiperElement: any): Promise<void>;
95
+ protected slideNext(swiperElement: any): Promise<void>;
96
+ protected getImageSizeQueryParams(): {
97
+ [key: string]: any;
98
+ };
99
+ protected discardEdit(swiperElement: any): void;
100
+ protected resetCrop(_swiperElement: any): void;
101
+ protected toggleCropTool(swiperElement: any): void;
102
+ protected validateEdit(swiperElement: any): Promise<void>;
103
+ protected _resetEditState(swiperElement: any): void;
104
+ protected onWindowResize(): void;
105
+ protected rotate(swiperElement: any, direction: 'left' | 'right'): void;
106
+ /**
107
+ * Constrains the displayed image so that, even once rotated 90°/270° via CSS transform,
108
+ * its visual bounding box always fits inside the slide container (no overflow).
109
+ */
110
+ protected _updateEditImageSize(swiperElement: any, retriesLeft?: number): void;
111
+ protected _getImageNaturalSize(imgEl: HTMLElement): {
112
+ width: number;
113
+ height: number;
114
+ } | null;
115
+ protected onCropPointerDown(event: MouseEvent | TouchEvent, swiperElement: any, handle: CropHandle): void;
116
+ protected onCropPointerMove(event: MouseEvent | TouchEvent, _swiperElement: any): void;
117
+ protected onCropPointerUp(_event: MouseEvent | TouchEvent, swiperElement?: any): void;
118
+ protected _computeCropRect(handle: CropHandle, start: CropRect, dx: number, dy: number): CropRect;
119
+ protected _getEventPoint(event: MouseEvent | TouchEvent): {
120
+ x: number;
121
+ y: number;
122
+ };
123
+ protected _updateCropOverlayPosition(swiperElement: any, retriesLeft?: number): {
124
+ width: number;
125
+ height: number;
126
+ } | null;
127
+ protected _renderEditedImage(image: Image, rotation: number, cropRect: CropRect): Promise<HTMLCanvasElement>;
128
+ protected _loadImageElement(src: string): Promise<HTMLImageElement>;
129
+ protected onPointerDown(event: MouseEvent, swiperElement: any): void;
130
+ protected onPointerMove(event: MouseEvent, swiperElement: any): void;
131
+ protected onPointerUp(event: MouseEvent, swiperElement?: any): void;
132
+ protected _resetZoom(swiperElement?: any): void;
133
+ protected _setupWheelZoom(swiperElement: any): void;
134
+ protected _cleanupWheelZoom(): void;
135
+ protected _applyZoom(swiperElement: any): void;
136
+ protected _clampTranslations(swiperElement: any): void;
137
+ protected _getActiveZoomWrapEl(swiperElement: any): HTMLElement | null;
138
+ protected markForCheck(): void;
139
+ static ɵfac: i0.ɵɵFactoryDeclaration<AppImageGallerySlideshowComponent<any>, never>;
140
+ static ɵcmp: i0.ɵɵComponentDeclaration<AppImageGallerySlideshowComponent<any>, "app-image-gallery-slideshow", never, { "rows": { "alias": "rows"; "required": false; }; "selectedIndex": { "alias": "selectedIndex"; "required": false; }; "mobile": { "alias": "mobile"; "required": false; }; "readOnly": { "alias": "readOnly"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "debug": { "alias": "debug"; "required": false; }; "mouseZoomEnabled": { "alias": "mouseZoomEnabled"; "required": false; }; "wheelZoomStep": { "alias": "wheelZoomStep"; "required": false; }; "maxZoomRatio": { "alias": "maxZoomRatio"; "required": false; }; "rotationEnabled": { "alias": "rotationEnabled"; "required": false; }; "cropEnabled": { "alias": "cropEnabled"; "required": false; }; "imageExportFormat": { "alias": "imageExportFormat"; "required": false; }; "imageExportQuality": { "alias": "imageExportQuality"; "required": false; }; "imageSizeQueryParam": { "alias": "imageSizeQueryParam"; "required": false; }; "modalImageSize": { "alias": "modalImageSize"; "required": false; }; }, { "deleteRequested": "deleteRequested"; "closeRequested": "closeRequested"; "afterEditImage": "afterEditImage"; "afterEditRow": "afterEditRow"; }, never, never, false, never>;
141
+ static ngAcceptInputType_mobile: unknown;
142
+ static ngAcceptInputType_readOnly: unknown;
143
+ static ngAcceptInputType_disabled: unknown;
144
+ static ngAcceptInputType_debug: unknown;
145
+ static ngAcceptInputType_mouseZoomEnabled: unknown;
146
+ static ngAcceptInputType_rotationEnabled: unknown;
147
+ static ngAcceptInputType_cropEnabled: unknown;
148
+ }
149
+ export {};
@@ -1,13 +1,18 @@
1
1
  import { OnDestroy, OnInit } from '@angular/core';
2
+ import { ActivatedRoute } from '@angular/router';
2
3
  import { ImageAttachment, ImageAttachmentService } from './gallery.service.testing';
3
4
  import { EntitiesTableDataSource } from '../../../../core/table/entities-table-datasource.class';
4
5
  import { ImageAttachmentFilter } from './gallegry.model.testing';
6
+ import { ImageGalleryZoomPresentation } from '../image-gallery.component';
5
7
  import * as i0 from "@angular/core";
6
8
  export declare class GalleryTestPage implements OnInit, OnDestroy {
7
9
  protected dataService: ImageAttachmentService;
10
+ protected route: ActivatedRoute;
8
11
  private _subscription;
9
12
  readonly dataSource: EntitiesTableDataSource<ImageAttachment, ImageAttachmentFilter>;
10
- constructor(dataService: ImageAttachmentService);
13
+ zoomPresentation: ImageGalleryZoomPresentation;
14
+ protected debug: boolean;
15
+ constructor(dataService: ImageAttachmentService, route: ActivatedRoute);
11
16
  ngOnInit(): void;
12
17
  ngOnDestroy(): void;
13
18
  save(): void;
@@ -1,4 +1,4 @@
1
- import { AfterViewInit, ChangeDetectorRef, ElementRef, EventEmitter, Injector, OnDestroy, OnInit, Renderer2 } from '@angular/core';
1
+ import { AfterViewInit, ChangeDetectorRef, ElementRef, EventEmitter, Injector, OnDestroy, OnInit, Renderer2, TemplateRef } from '@angular/core';
2
2
  import { ControlValueAccessor, FormGroupDirective, UntypedFormControl } from '@angular/forms';
3
3
  import { BehaviorSubject, Observable } from 'rxjs';
4
4
  import { SuggestFn } from '../../services/entity-service.class';
@@ -9,7 +9,6 @@ import { MatAutocomplete, MatAutocompleteSelectedEvent, MatAutocompleteTrigger }
9
9
  import { IonSearchbar, ModalController } from '@ionic/angular';
10
10
  import { MatAutocompleteFieldConfig } from './material.autocomplete.config';
11
11
  import { AppFloatLabelType, DisplayFn, EqualsFn } from '../../types';
12
- import { TemplateRef } from '@angular/core';
13
12
  import * as i0 from "@angular/core";
14
13
  export interface MatAutocompleteFieldSelectChange {
15
14
  source: MatSelect | MatAutocomplete;
@@ -63,8 +62,8 @@ export declare class MatAutocompleteField implements OnInit, AfterViewInit, OnDe
63
62
  required: boolean;
64
63
  hideRequiredMarker: boolean;
65
64
  mobile: boolean;
66
- showListHeader: boolean;
67
- showListFooter: boolean;
65
+ showPanelHeader: boolean;
66
+ showPanelFooter: boolean;
68
67
  clearable: boolean;
69
68
  debounceTime: number;
70
69
  displaySeparator: string | null;
@@ -130,8 +129,8 @@ export declare class MatAutocompleteField implements OnInit, AfterViewInit, OnDe
130
129
  matInputText: ElementRef<HTMLInputElement>;
131
130
  autocomplete: MatAutocomplete;
132
131
  autocompleteTrigger: MatAutocompleteTrigger;
133
- listHeaderTemplate?: TemplateRef<any>;
134
- listFooterTemplate?: TemplateRef<any>;
132
+ panelHeaderTemplate?: TemplateRef<any>;
133
+ panelFooterTemplate?: TemplateRef<any>;
135
134
  showTooltip: boolean;
136
135
  constructor(injector: Injector, el: ElementRef<HTMLElement>, cd: ChangeDetectorRef, modalController: ModalController, renderer: Renderer2, formGroupDir: FormGroupDirective);
137
136
  get itemCount(): number;
@@ -201,12 +200,12 @@ export declare class MatAutocompleteField implements OnInit, AfterViewInit, OnDe
201
200
  protected onBackspace(event: Event): void;
202
201
  protected toggleFavoriteClick(event: UIEvent, value: any): void;
203
202
  static ɵfac: i0.ɵɵFactoryDeclaration<MatAutocompleteField, [null, null, null, null, null, { optional: true; }]>;
204
- static ɵcmp: i0.ɵɵComponentDeclaration<MatAutocompleteField, "mat-autocomplete-field", never, { "equals": { "alias": "equals"; "required": false; }; "logPrefix": { "alias": "logPrefix"; "required": false; }; "formControl": { "alias": "formControl"; "required": false; }; "formControlName": { "alias": "formControlName"; "required": false; }; "floatLabel": { "alias": "floatLabel"; "required": false; }; "label": { "alias": "label"; "required": false; }; "appearance": { "alias": "appearance"; "required": false; }; "subscriptSizing": { "alias": "subscriptSizing"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "suggestFn": { "alias": "suggestFn"; "required": false; }; "required": { "alias": "required"; "required": false; }; "hideRequiredMarker": { "alias": "hideRequiredMarker"; "required": false; }; "mobile": { "alias": "mobile"; "required": false; }; "showListHeader": { "alias": "showListHeader"; "required": false; }; "showListFooter": { "alias": "showListFooter"; "required": false; }; "clearable": { "alias": "clearable"; "required": false; }; "debounceTime": { "alias": "debounceTime"; "required": false; }; "displaySeparator": { "alias": "displaySeparator"; "required": false; }; "displayWith": { "alias": "displayWith"; "required": false; }; "displayAttributes": { "alias": "displayAttributes"; "required": false; }; "displayColumnSizes": { "alias": "displayColumnSizes"; "required": false; }; "displayColumnNames": { "alias": "displayColumnNames"; "required": false; }; "highlightAccent": { "alias": "highlightAccent"; "required": false; }; "showAllOnFocus": { "alias": "showAllOnFocus"; "required": false; }; "showPanelOnFocus": { "alias": "showPanelOnFocus"; "required": false; }; "reloadItemsOnFocus": { "alias": "reloadItemsOnFocus"; "required": false; }; "clearInvalidValueOnBlur": { "alias": "clearInvalidValueOnBlur"; "required": false; }; "autofocus": { "alias": "autofocus"; "required": false; }; "config": { "alias": "config"; "required": false; }; "i18nPrefix": { "alias": "i18nPrefix"; "required": false; }; "noResultMessage": { "alias": "noResultMessage"; "required": false; }; "panelClass": { "alias": "panelClass"; "required": false; }; "panelWidth": { "alias": "panelWidth"; "required": false; }; "disableRipple": { "alias": "disableRipple"; "required": false; }; "matAutocompletePosition": { "alias": "matAutocompletePosition"; "required": false; }; "multiple": { "alias": "multiple"; "required": false; }; "fetchMoreThreshold": { "alias": "fetchMoreThreshold"; "required": false; }; "suggestLengthThreshold": { "alias": "suggestLengthThreshold"; "required": false; }; "showLoadingSpinner": { "alias": "showLoadingSpinner"; "required": false; }; "debug": { "alias": "debug"; "required": false; }; "showSearchBar": { "alias": "showSearchBar"; "required": false; }; "stickySearchBar": { "alias": "stickySearchBar"; "required": false; }; "applyImplicitValue": { "alias": "applyImplicitValue"; "required": false; }; "dropButtonTitle": { "alias": "dropButtonTitle"; "required": false; }; "clearButtonTitle": { "alias": "clearButtonTitle"; "required": false; }; "trimSearchText": { "alias": "trimSearchText"; "required": false; }; "splitSearchText": { "alias": "splitSearchText"; "required": false; }; "selectInputContentOnFocus": { "alias": "selectInputContentOnFocus"; "required": false; }; "selectInputContentOnFocusDelay": { "alias": "selectInputContentOnFocusDelay"; "required": false; }; "previewImplicitValue": { "alias": "previewImplicitValue"; "required": false; }; "showFavorites": { "alias": "showFavorites"; "required": false; }; "toggleFavoriteTitle": { "alias": "toggleFavoriteTitle"; "required": false; }; "favoriteItems": { "alias": "favoriteItems"; "required": false; }; "colSizes": { "alias": "colSizes"; "required": false; }; "classList": { "alias": "class"; "required": false; }; "filter": { "alias": "filter"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "tabindex": { "alias": "tabindex"; "required": false; }; "items": { "alias": "items"; "required": false; }; }, { "clicked": "click"; "blurred": "blur"; "focused": "focus"; "dropButtonClick": "dropButtonClick"; "keydownEscape": "keydown.escape"; "keydownBackspace": "keydown.backspace"; "keyupEnter": "keyup.enter"; "arrowUp": "arrowUp"; "arrowDown": "arrowDown"; "enter": "enter"; "selectionChange": "selectionChange"; "openedChange": "openedChange"; "toggleFavorite": "toggleFavorite"; }, ["listHeaderTemplate", "listFooterTemplate"], ["[matAfter]", "[matPrefix]", "[matSuffix]", "mat-error,[matError]", "mat-hint:not([align='end']),[matHint]", "mat-hint[align='end']"], false, never>;
203
+ static ɵcmp: i0.ɵɵComponentDeclaration<MatAutocompleteField, "mat-autocomplete-field", never, { "equals": { "alias": "equals"; "required": false; }; "logPrefix": { "alias": "logPrefix"; "required": false; }; "formControl": { "alias": "formControl"; "required": false; }; "formControlName": { "alias": "formControlName"; "required": false; }; "floatLabel": { "alias": "floatLabel"; "required": false; }; "label": { "alias": "label"; "required": false; }; "appearance": { "alias": "appearance"; "required": false; }; "subscriptSizing": { "alias": "subscriptSizing"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "suggestFn": { "alias": "suggestFn"; "required": false; }; "required": { "alias": "required"; "required": false; }; "hideRequiredMarker": { "alias": "hideRequiredMarker"; "required": false; }; "mobile": { "alias": "mobile"; "required": false; }; "showPanelHeader": { "alias": "showPanelHeader"; "required": false; }; "showPanelFooter": { "alias": "showPanelFooter"; "required": false; }; "clearable": { "alias": "clearable"; "required": false; }; "debounceTime": { "alias": "debounceTime"; "required": false; }; "displaySeparator": { "alias": "displaySeparator"; "required": false; }; "displayWith": { "alias": "displayWith"; "required": false; }; "displayAttributes": { "alias": "displayAttributes"; "required": false; }; "displayColumnSizes": { "alias": "displayColumnSizes"; "required": false; }; "displayColumnNames": { "alias": "displayColumnNames"; "required": false; }; "highlightAccent": { "alias": "highlightAccent"; "required": false; }; "showAllOnFocus": { "alias": "showAllOnFocus"; "required": false; }; "showPanelOnFocus": { "alias": "showPanelOnFocus"; "required": false; }; "reloadItemsOnFocus": { "alias": "reloadItemsOnFocus"; "required": false; }; "clearInvalidValueOnBlur": { "alias": "clearInvalidValueOnBlur"; "required": false; }; "autofocus": { "alias": "autofocus"; "required": false; }; "config": { "alias": "config"; "required": false; }; "i18nPrefix": { "alias": "i18nPrefix"; "required": false; }; "noResultMessage": { "alias": "noResultMessage"; "required": false; }; "panelClass": { "alias": "panelClass"; "required": false; }; "panelWidth": { "alias": "panelWidth"; "required": false; }; "disableRipple": { "alias": "disableRipple"; "required": false; }; "matAutocompletePosition": { "alias": "matAutocompletePosition"; "required": false; }; "multiple": { "alias": "multiple"; "required": false; }; "fetchMoreThreshold": { "alias": "fetchMoreThreshold"; "required": false; }; "suggestLengthThreshold": { "alias": "suggestLengthThreshold"; "required": false; }; "showLoadingSpinner": { "alias": "showLoadingSpinner"; "required": false; }; "debug": { "alias": "debug"; "required": false; }; "showSearchBar": { "alias": "showSearchBar"; "required": false; }; "stickySearchBar": { "alias": "stickySearchBar"; "required": false; }; "applyImplicitValue": { "alias": "applyImplicitValue"; "required": false; }; "dropButtonTitle": { "alias": "dropButtonTitle"; "required": false; }; "clearButtonTitle": { "alias": "clearButtonTitle"; "required": false; }; "trimSearchText": { "alias": "trimSearchText"; "required": false; }; "splitSearchText": { "alias": "splitSearchText"; "required": false; }; "selectInputContentOnFocus": { "alias": "selectInputContentOnFocus"; "required": false; }; "selectInputContentOnFocusDelay": { "alias": "selectInputContentOnFocusDelay"; "required": false; }; "previewImplicitValue": { "alias": "previewImplicitValue"; "required": false; }; "showFavorites": { "alias": "showFavorites"; "required": false; }; "toggleFavoriteTitle": { "alias": "toggleFavoriteTitle"; "required": false; }; "favoriteItems": { "alias": "favoriteItems"; "required": false; }; "colSizes": { "alias": "colSizes"; "required": false; }; "classList": { "alias": "class"; "required": false; }; "filter": { "alias": "filter"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; "tabindex": { "alias": "tabindex"; "required": false; }; "items": { "alias": "items"; "required": false; }; }, { "clicked": "click"; "blurred": "blur"; "focused": "focus"; "dropButtonClick": "dropButtonClick"; "keydownEscape": "keydown.escape"; "keydownBackspace": "keydown.backspace"; "keyupEnter": "keyup.enter"; "arrowUp": "arrowUp"; "arrowDown": "arrowDown"; "enter": "enter"; "selectionChange": "selectionChange"; "openedChange": "openedChange"; "toggleFavorite": "toggleFavorite"; }, ["panelHeaderTemplate", "panelFooterTemplate"], ["[matAfter]", "[matPrefix]", "[matSuffix]", "mat-error,[matError]", "mat-hint:not([align='end']),[matHint]", "mat-hint[align='end']"], false, never>;
205
204
  static ngAcceptInputType_required: unknown;
206
205
  static ngAcceptInputType_hideRequiredMarker: unknown;
207
206
  static ngAcceptInputType_mobile: unknown;
208
- static ngAcceptInputType_showListHeader: unknown;
209
- static ngAcceptInputType_showListFooter: unknown;
207
+ static ngAcceptInputType_showPanelHeader: unknown;
208
+ static ngAcceptInputType_showPanelFooter: unknown;
210
209
  static ngAcceptInputType_clearable: unknown;
211
210
  static ngAcceptInputType_debounceTime: unknown;
212
211
  static ngAcceptInputType_highlightAccent: unknown;
@@ -0,0 +1,9 @@
1
+ import * as i0 from "@angular/core";
2
+ export declare class MaterialAutocompleteHeaderDirective {
3
+ static ɵfac: i0.ɵɵFactoryDeclaration<MaterialAutocompleteHeaderDirective, never>;
4
+ static ɵdir: i0.ɵɵDirectiveDeclaration<MaterialAutocompleteHeaderDirective, "ng-template[panelHeader]", never, {}, {}, never, never, false, never>;
5
+ }
6
+ export declare class MaterialAutocompleteFooterDirective {
7
+ static ɵfac: i0.ɵɵFactoryDeclaration<MaterialAutocompleteFooterDirective, never>;
8
+ static ɵdir: i0.ɵɵDirectiveDeclaration<MaterialAutocompleteFooterDirective, "ng-template[panelFooter]", never, {}, {}, never, never, false, never>;
9
+ }
@@ -1,23 +1,24 @@
1
1
  import * as i0 from "@angular/core";
2
2
  import * as i1 from "./material.autocomplete";
3
- import * as i2 from "@angular/common";
4
- import * as i3 from "@ionic/angular";
5
- import * as i4 from "@angular/cdk/scrolling";
6
- import * as i5 from "@angular/forms";
7
- import * as i6 from "../../pipes/pipes.module";
8
- import * as i7 from "../../directives/directives.module";
9
- import * as i8 from "../../rx-state/rx-state.module";
10
- import * as i9 from "@angular/material/core";
11
- import * as i10 from "@angular/material/autocomplete";
12
- import * as i11 from "@angular/material/form-field";
13
- import * as i12 from "@angular/material/input";
14
- import * as i13 from "@angular/material/icon";
15
- import * as i14 from "@angular/material/button";
16
- import * as i15 from "@angular/material/select";
17
- import * as i16 from "@ngx-translate/core";
18
- import * as i17 from "@angular/material/tooltip";
3
+ import * as i2 from "./material.autocomplete.directive";
4
+ import * as i3 from "@angular/common";
5
+ import * as i4 from "@ionic/angular";
6
+ import * as i5 from "@angular/cdk/scrolling";
7
+ import * as i6 from "@angular/forms";
8
+ import * as i7 from "../../pipes/pipes.module";
9
+ import * as i8 from "../../directives/directives.module";
10
+ import * as i9 from "../../rx-state/rx-state.module";
11
+ import * as i10 from "@angular/material/core";
12
+ import * as i11 from "@angular/material/autocomplete";
13
+ import * as i12 from "@angular/material/form-field";
14
+ import * as i13 from "@angular/material/input";
15
+ import * as i14 from "@angular/material/icon";
16
+ import * as i15 from "@angular/material/button";
17
+ import * as i16 from "@angular/material/select";
18
+ import * as i17 from "@ngx-translate/core";
19
+ import * as i18 from "@angular/material/tooltip";
19
20
  export declare class SharedMatAutocompleteModule {
20
21
  static ɵfac: i0.ɵɵFactoryDeclaration<SharedMatAutocompleteModule, never>;
21
- static ɵmod: i0.ɵɵNgModuleDeclaration<SharedMatAutocompleteModule, [typeof i1.MatAutocompleteField], [typeof i2.CommonModule, typeof i3.IonicModule, typeof i4.ScrollingModule, typeof i5.ReactiveFormsModule, typeof i6.SharedPipesModule, typeof i7.SharedDirectivesModule, typeof i8.RxStateModule, typeof i9.MatCommonModule, typeof i10.MatAutocompleteModule, typeof i11.MatFormFieldModule, typeof i12.MatInputModule, typeof i13.MatIconModule, typeof i14.MatButtonModule, typeof i15.MatSelectModule, typeof i9.MatRippleModule, typeof i16.TranslateModule, typeof i17.MatTooltip], [typeof i10.MatAutocompleteModule, typeof i1.MatAutocompleteField]>;
22
+ static ɵmod: i0.ɵɵNgModuleDeclaration<SharedMatAutocompleteModule, [typeof i1.MatAutocompleteField, typeof i2.MaterialAutocompleteHeaderDirective, typeof i2.MaterialAutocompleteFooterDirective], [typeof i3.CommonModule, typeof i4.IonicModule, typeof i5.ScrollingModule, typeof i6.ReactiveFormsModule, typeof i7.SharedPipesModule, typeof i8.SharedDirectivesModule, typeof i9.RxStateModule, typeof i10.MatCommonModule, typeof i11.MatAutocompleteModule, typeof i12.MatFormFieldModule, typeof i13.MatInputModule, typeof i14.MatIconModule, typeof i15.MatButtonModule, typeof i16.MatSelectModule, typeof i10.MatRippleModule, typeof i17.TranslateModule, typeof i18.MatTooltip], [typeof i11.MatAutocompleteModule, typeof i1.MatAutocompleteField, typeof i2.MaterialAutocompleteHeaderDirective, typeof i2.MaterialAutocompleteFooterDirective]>;
22
23
  static ɵinj: i0.ɵɵInjectorDeclaration<SharedMatAutocompleteModule>;
23
24
  }
@@ -661,6 +661,12 @@
661
661
  "GALLERY": {
662
662
  "BTN_EDIT_TITLE": "Edit title",
663
663
  "BTN_ADD_TITLE": "Add a title",
664
+ "BTN_ROTATE_LEFT": "Rotate left",
665
+ "BTN_ROTATE_RIGHT": "Rotate right",
666
+ "BTN_CROP_ACTIVATE": "Crop",
667
+ "BTN_CROP_DEACTIVATE": "Hide crop",
668
+ "BTN_CROP_RESET": "Reset crop",
669
+ "ERROR_EDIT_IMAGE": "Unable to save the edited image",
664
670
  "TITLE": "Title"
665
671
  }
666
672
  },
@@ -661,6 +661,12 @@
661
661
  "GALLERY": {
662
662
  "BTN_EDIT_TITLE": "Edit title",
663
663
  "BTN_ADD_TITLE": "Add a title",
664
+ "BTN_ROTATE_LEFT": "Rotate left",
665
+ "BTN_ROTATE_RIGHT": "Rotate right",
666
+ "BTN_CROP_ACTIVATE": "Crop",
667
+ "BTN_CROP_DEACTIVATE": "Hide crop",
668
+ "BTN_CROP_RESET": "Reset crop",
669
+ "ERROR_EDIT_IMAGE": "Unable to save the edited image",
664
670
  "TITLE": "Title"
665
671
  }
666
672
  },
@@ -663,6 +663,12 @@
663
663
  "GALLERY": {
664
664
  "BTN_EDIT_TITLE": "Éditer le titre",
665
665
  "BTN_ADD_TITLE": "Ajouter un titre",
666
+ "BTN_ROTATE_LEFT": "Pivoter à gauche",
667
+ "BTN_ROTATE_RIGHT": "Pivoter à droite",
668
+ "BTN_CROP_ACTIVATE": "Recadrer",
669
+ "BTN_CROP_DEACTIVATE": "Masquer le recadrage",
670
+ "BTN_CROP_RESET": "Réinitialiser le recadrage",
671
+ "ERROR_EDIT_IMAGE": "Impossible d'enregistrer l'image modifiée",
666
672
  "TITLE": "Titre"
667
673
  }
668
674
  },
@@ -2,7 +2,7 @@
2
2
  "name": "ngx-sumaris-components",
3
3
  "short_name": "ngx-sumaris-components",
4
4
  "manifest_version": 1,
5
- "version": "18.25.4",
5
+ "version": "18.25.6",
6
6
  "default_locale": "fr",
7
7
  "description": "Angular components for building beautiful and responsive Apps",
8
8
  "icons": [{
@@ -194,6 +194,12 @@ mat-option {
194
194
  padding: 0 !important;
195
195
  }
196
196
  }
197
+
198
+ /* hide pseudo checkbox, in the footer*/
199
+ &.mat-pseudo-checkbox-hidden mat-pseudo-checkbox {
200
+ visibility: hidden;
201
+ display: none;
202
+ }
197
203
  }
198
204
 
199
205
  mat-option:not(:last-of-type) {
@@ -389,12 +395,14 @@ ion-list,
389
395
  /* Offset due to mat-pseudo-checkbox */
390
396
  padding-left: 32px;
391
397
  }
392
- &.column {
398
+ &.sticky {
393
399
  /* Set header as sticky*/
394
400
  position: -webkit-sticky;
395
401
  position: sticky;
396
- top: 0;
402
+ top: var(--top, 0);
397
403
  z-index: 1001;
404
+ }
405
+ &.column {
398
406
  background-color: var(--ion-color-secondary);
399
407
  border-bottom: 1px solid #{$app-select-option-border-color};
400
408
  color: var(--ion-color-secondary-contrast);
@@ -402,16 +410,16 @@ ion-list,
402
410
  @include font-size(12px);
403
411
  font-weight: 500;
404
412
  height: 20px;
413
+ --top: var(--header-column-top, 0);
405
414
  ion-col {
406
415
  white-space: nowrap;
407
416
  text-overflow: ellipsis;
408
417
  }
409
418
  &.mat-select-searchbar-sticky {
410
419
  /* offset because of the searchbar height */
411
- top: var(--ion-searchbar-height, 58px);
420
+ --header-column-top: var(--ion-searchbar-height, 58px);
412
421
  }
413
422
  }
414
-
415
423
  }
416
424
 
417
425
  ion-row.ion-list-footer,
@@ -422,7 +430,7 @@ ion-list,
422
430
  /* Set footer as sticky*/
423
431
  position: -webkit-sticky;
424
432
  position: sticky;
425
- bottom: 0;
433
+ bottom: var(--footer-bottom, 0);
426
434
  z-index: 1001;
427
435
  border-top: 1px solid #{$app-select-option-border-color};
428
436
  background-color: var(--ion-toolbar-background, #{$ion-toolbar-background});
@@ -438,6 +446,8 @@ ion-list,
438
446
  white-space: nowrap;
439
447
  text-overflow: ellipsis;
440
448
  }
449
+
450
+
441
451
  }
442
452
 
443
453
  ion-row {