@sumaris-net/ngx-components 18.25.16 → 18.25.18

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.
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.16",
4
+ "version": "18.25.18",
5
5
  "author": "contact@e-is.pro",
6
6
  "license": "AGPL-3.0",
7
7
  "readmeFilename": "README.md",
@@ -91,6 +91,7 @@ export declare class EntitiesAsyncTableDataSource<T extends IEntity<T, ID>, F =
91
91
  editing: boolean;
92
92
  }): Promise<R | undefined>;
93
93
  getData(): T[];
94
+ get canFetchMore(): boolean;
94
95
  fetchMore(opts?: {
95
96
  emitEvent: boolean;
96
97
  }): Promise<boolean>;
@@ -90,6 +90,7 @@ export declare class EntitiesTableDataSource<T extends IEntity<T, ID>, F = any,
90
90
  editing: boolean;
91
91
  }): Promise<R | undefined>;
92
92
  getData(): T[];
93
+ get canFetchMore(): boolean;
93
94
  fetchMore(opts?: {
94
95
  emitEvent: boolean;
95
96
  }): Promise<boolean>;
@@ -12,7 +12,7 @@ import { FormGroup } from '@angular/forms';
12
12
  import { PromiseEvent } from '../../events';
13
13
  import { PredefinedColors } from '@ionic/core';
14
14
  import { ImageOptions } from '@capacitor/camera';
15
- import { GalleryMode, ImageEditEvent, ImageEditFormat } from './image-gallery.model';
15
+ import { GalleryMode, ImageEditEvent, ImageEditFormat, ImageGallerySlideChangeEvent } from './image-gallery.model';
16
16
  import * as i0 from "@angular/core";
17
17
  export type ImageGallerySlideshowMode = 'modal' | 'inline';
18
18
  export interface ImageGallerySizes {
@@ -76,13 +76,21 @@ export declare class AppImageGalleryComponent<T extends Image> implements OnInit
76
76
  /** Enable the crop tool in the slideshow (defaults to true). */
77
77
  enableCrop: boolean;
78
78
  /** Image format used when emitting the edited (cropped/rotated) image. */
79
- imageExportFormat: ImageEditFormat;
80
- /** Export quality, applied only when imageExportFormat is 'jpeg' (0 to 1). */
81
- imageExportQuality: number;
79
+ editionFormat: ImageEditFormat;
80
+ /** Export quality, applied only when editionFormat is 'jpeg' (0 to 1). */
81
+ editionQuality: number;
82
82
  /** Where to show the slideshow: in a full-screen modal (default), or inline, as an overlay over the gallery itself (desktop only). */
83
83
  slideshowMode: ImageGallerySlideshowMode;
84
84
  /** Height of the inline slideshow overlay (CSS value, e.g. '60vh'). Only used when zoomPresentation is 'inline'. */
85
85
  inlineZoomHeight: string;
86
+ /** Whether reaching the last (resp. first) image should wrap around to the first (resp. last) one. Default true. */
87
+ enableSlideshowLoop: boolean;
88
+ /**
89
+ * Whether more rows may exist beyond the ones currently loaded (e.g. a further page, not yet fetched).
90
+ * When true, reaching the last image asks the parent (via `fetchMore`) instead of looping/stopping.
91
+ * The gallery has no opinion on how fetching is actually done: it's entirely up to the parent.
92
+ */
93
+ canFetchMore: boolean;
86
94
  set dataSource(dataSource: TableDataSource<T, any, any, any>);
87
95
  get dataSource(): TableDataSource<T, any, any, any>;
88
96
  get enabled(): boolean;
@@ -97,6 +105,15 @@ export declare class AppImageGalleryComponent<T extends Image> implements OnInit
97
105
  onAfterEditRow: EventEmitter<TableElement<T>>;
98
106
  onAfterEditImage: EventEmitter<ImageEditEvent<T>>;
99
107
  click: EventEmitter<TableElement<T>>;
108
+ /** Emitted from the slideshow whenever the active slide moves backward (previous image). */
109
+ previousSlide: EventEmitter<ImageGallerySlideChangeEvent<T>>;
110
+ /** Emitted from the slideshow whenever the active slide moves forward (next image). */
111
+ nextSlide: EventEmitter<ImageGallerySlideChangeEvent<T>>;
112
+ /**
113
+ * Forwarded as-is from the slideshow when reaching the last image while `canFetchMore` is true: the
114
+ * parent must fetch the next page (however it does so) and resolve with whether new rows were added.
115
+ */
116
+ fetchMore: EventEmitter<PromiseEvent<boolean, void>>;
100
117
  showTooltip: boolean;
101
118
  constructor(imageService: ImageService, platform: Platform, alterCtrl: AlertController, translate: TranslateService, cd: ChangeDetectorRef, environment?: Environment);
102
119
  ngOnInit(): void;
@@ -127,7 +144,7 @@ export declare class AppImageGalleryComponent<T extends Image> implements OnInit
127
144
  * Can be called from outside the component (e.g. to open the gallery directly on a given image).
128
145
  */
129
146
  openSlideshow(event: Event | undefined, row: TableElement<T>): Promise<void>;
130
- protected closeInlineSlideshow(): void;
147
+ closeSlideshow(role?: string): Promise<boolean>;
131
148
  /**
132
149
  * Handles a delete request coming from the slideshow component (either inline or in the modal):
133
150
  * runs the same confirmation/deletion flow as a card's delete button, then resolves the promise
@@ -144,7 +161,7 @@ export declare class AppImageGalleryComponent<T extends Image> implements OnInit
144
161
  };
145
162
  protected markForCheck(): void;
146
163
  static ɵfac: i0.ɵɵFactoryDeclaration<AppImageGalleryComponent<any>, [null, null, null, null, null, { optional: true; }]>;
147
- 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; }; "enableRotate": { "alias": "enableRotate"; "required": false; }; "enableCrop": { "alias": "enableCrop"; "required": false; }; "imageExportFormat": { "alias": "imageExportFormat"; "required": false; }; "imageExportQuality": { "alias": "imageExportQuality"; "required": false; }; "slideshowMode": { "alias": "slideshowMode"; "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>;
164
+ 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; }; "enableRotate": { "alias": "enableRotate"; "required": false; }; "enableCrop": { "alias": "enableCrop"; "required": false; }; "editionFormat": { "alias": "editionFormat"; "required": false; }; "editionQuality": { "alias": "editionQuality"; "required": false; }; "slideshowMode": { "alias": "slideshowMode"; "required": false; }; "inlineZoomHeight": { "alias": "inlineZoomHeight"; "required": false; }; "enableSlideshowLoop": { "alias": "enableSlideshowLoop"; "required": false; }; "canFetchMore": { "alias": "canFetchMore"; "required": false; }; "dataSource": { "alias": "dataSource"; "required": false; }; }, { "onBeforeDeleteRows": "onBeforeDeleteRows"; "onAfterAddRows": "onAfterAddRows"; "onAfterEditRow": "onAfterEditRow"; "onAfterEditImage": "onAfterEditImage"; "click": "click"; "previousSlide": "previousSlide"; "nextSlide": "nextSlide"; "fetchMore": "fetchMore"; }, never, ["ion-buttons[slot=start]", "ion-buttons[slot=end]"], false, never>;
148
165
  static ngAcceptInputType_debug: unknown;
149
166
  static ngAcceptInputType_disabled: unknown;
150
167
  static ngAcceptInputType_readOnly: unknown;
@@ -159,4 +176,6 @@ export declare class AppImageGalleryComponent<T extends Image> implements OnInit
159
176
  static ngAcceptInputType_enableMouseZoom: unknown;
160
177
  static ngAcceptInputType_enableRotate: unknown;
161
178
  static ngAcceptInputType_enableCrop: unknown;
179
+ static ngAcceptInputType_enableSlideshowLoop: unknown;
180
+ static ngAcceptInputType_canFetchMore: unknown;
162
181
  }
@@ -9,3 +9,7 @@ export interface ImageEditEvent<T extends Image = Image> {
9
9
  blob: Blob;
10
10
  format: ImageEditFormat;
11
11
  }
12
+ export interface ImageGallerySlideChangeEvent<T extends Image = Image> {
13
+ index: number;
14
+ row: TableElement<T>;
15
+ }
@@ -4,7 +4,7 @@ import { AlertController } from '@ionic/angular';
4
4
  import { TranslateService } from '@ngx-translate/core';
5
5
  import { Swiper } from 'swiper/types';
6
6
  import { Image, ImageSize } from '../../image.model';
7
- import { ImageEditEvent, ImageEditFormat } from '../image-gallery.model';
7
+ import { ImageEditEvent, ImageEditFormat, ImageGallerySlideChangeEvent } from '../image-gallery.model';
8
8
  import * as i0 from "@angular/core";
9
9
  interface CropRect {
10
10
  x: number;
@@ -39,6 +39,7 @@ export declare class AppImageGallerySlideshowComponent<T extends Image = Image>
39
39
  } | null;
40
40
  protected _wheelListener: ((e: WheelEvent) => void) | null;
41
41
  protected _wheelEl: HTMLElement | null;
42
+ protected readonly _defaultCropInset = 0.15;
42
43
  protected _cropToolActive: boolean;
43
44
  protected _cropRect: CropRect;
44
45
  protected _cropOverlayRect: {
@@ -52,6 +53,7 @@ export declare class AppImageGallerySlideshowComponent<T extends Image = Image>
52
53
  startRect: CropRect;
53
54
  } | null;
54
55
  protected readonly _cropHandles: CropHandle[];
56
+ protected _pendingSlideDirection: 'prev' | 'next' | null;
55
57
  rows: TableElement<T>[] | ReadonlyArray<TableElement<T>>;
56
58
  selectedIndex: number;
57
59
  mobile: boolean;
@@ -63,10 +65,14 @@ export declare class AppImageGallerySlideshowComponent<T extends Image = Image>
63
65
  maxZoomRatio: number;
64
66
  enableRotate: boolean;
65
67
  enableCrop: boolean;
66
- editOutputFormat: ImageEditFormat;
67
- editOutputQuality: number;
68
+ editionFormat: ImageEditFormat;
69
+ editionQuality: number;
68
70
  imageSizeQueryParam: string;
69
71
  modalImageSize: ImageSize | string;
72
+ /** Whether reaching the last (resp. first) slide should wrap around to the first (resp. last) one. Default true. */
73
+ enableLoop: boolean;
74
+ /** Whether more rows may exist beyond the ones currently loaded (e.g. a further page, not yet fetched). When true, reaching the last slide asks the parent (via `fetchMore`) instead of looping/stopping. */
75
+ canFetchMore: boolean;
70
76
  /** Requests deletion of the given row. The caller (gallery) owns the confirmation/deletion logic and resolves the promise with whether it actually happened. */
71
77
  deleteRequested: EventEmitter<import("../../../events").PromiseEvent<boolean, {
72
78
  row: TableElement<T>;
@@ -74,13 +80,39 @@ export declare class AppImageGallerySlideshowComponent<T extends Image = Image>
74
80
  closeRequested: EventEmitter<void>;
75
81
  afterEditImage: EventEmitter<ImageEditEvent<T>>;
76
82
  afterEditRow: EventEmitter<TableElement<T>>;
83
+ /** Emitted whenever the active slide moves backward (previous image), whether triggered by the side button, a swipe, or looping past the first slide. */
84
+ previousSlide: EventEmitter<ImageGallerySlideChangeEvent<T>>;
85
+ /** Emitted whenever the active slide moves forward (next image), whether triggered by the side button, a swipe, or looping past the last slide. */
86
+ nextSlide: EventEmitter<ImageGallerySlideChangeEvent<T>>;
87
+ /**
88
+ * Emitted when reaching the last slide while `canFetchMore` is true: the parent is expected to fetch
89
+ * the next page (however it does so) and resolve with whether new rows were actually added.
90
+ */
91
+ fetchMore: EventEmitter<import("../../../events").PromiseEvent<boolean, void>>;
77
92
  swiperRef: ElementRef;
78
93
  showTooltip: boolean;
79
94
  protected get hasPendingEdit(): boolean;
95
+ /** No "fetch previous page" concept exists: reaching the first slide can only loop, or stop. */
96
+ protected get isPrevDisabled(): boolean;
97
+ protected get isNextDisabled(): boolean;
80
98
  constructor(alterCtrl: AlertController, translate: TranslateService, cd: ChangeDetectorRef);
81
99
  ngOnDestroy(): void;
82
100
  protected getSwiper(swiperElement?: any): Swiper;
101
+ /**
102
+ * Waits (a few animation frames) until Swiper's own slides array reflects at least `minCount` items.
103
+ * Needed after `fetchMore`: the new `<swiper-slide>` elements come from the `rows` input re-rendering,
104
+ * which may not have reached the DOM by the time the parent's returned promise resolves.
105
+ */
106
+ protected _waitForSlideCount(swiper: Swiper, minCount: number, retriesLeft?: number): Promise<boolean>;
83
107
  protected onSlideChange(swiperElement: any): void;
108
+ /**
109
+ * Emits `previousSlide`/`nextSlide` from the actual index change, covering side buttons as well as touch
110
+ * swipes. When `slidePrev()`/`slideNext()` triggered the change, their explicit intent is used (since with
111
+ * exactly 2 slides, a "step" and a manual "wrap" produce the very same index change and can't be told apart
112
+ * from the indexes alone). Otherwise (a plain touch swipe) Swiper never wraps on its own (no `loop` mode
113
+ * configured here), so a simple index comparison is unambiguous.
114
+ */
115
+ protected _emitSlideChange(previousIndex: number, activeIndex: number): void;
84
116
  protected onSwiperInit(swiperElement: any): void;
85
117
  /**
86
118
  * Swiper's own touch/mouse-drag-to-swipe gesture is captured very early (before our crop overlay's
@@ -98,6 +130,7 @@ export declare class AppImageGallerySlideshowComponent<T extends Image = Image>
98
130
  };
99
131
  protected discardEdit(swiperElement: any): void;
100
132
  protected resetCrop(_swiperElement: any): void;
133
+ protected _createDefaultCropRect(): CropRect;
101
134
  protected toggleCropTool(swiperElement: any): void;
102
135
  protected validateEdit(swiperElement: any): Promise<void>;
103
136
  protected _resetEditState(swiperElement: any): void;
@@ -137,7 +170,7 @@ export declare class AppImageGallerySlideshowComponent<T extends Image = Image>
137
170
  protected _getActiveZoomWrapEl(swiperElement: any): HTMLElement | null;
138
171
  protected markForCheck(): void;
139
172
  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; }; "enableMouseZoom": { "alias": "enableMouseZoom"; "required": false; }; "wheelZoomStep": { "alias": "wheelZoomStep"; "required": false; }; "maxZoomRatio": { "alias": "maxZoomRatio"; "required": false; }; "enableRotate": { "alias": "enableRotate"; "required": false; }; "enableCrop": { "alias": "enableCrop"; "required": false; }; "editOutputFormat": { "alias": "editOutputFormat"; "required": false; }; "editOutputQuality": { "alias": "editOutputQuality"; "required": false; }; "imageSizeQueryParam": { "alias": "imageSizeQueryParam"; "required": false; }; "modalImageSize": { "alias": "modalImageSize"; "required": false; }; }, { "deleteRequested": "deleteRequested"; "closeRequested": "closeRequested"; "afterEditImage": "afterEditImage"; "afterEditRow": "afterEditRow"; }, never, never, false, never>;
173
+ 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; }; "enableMouseZoom": { "alias": "enableMouseZoom"; "required": false; }; "wheelZoomStep": { "alias": "wheelZoomStep"; "required": false; }; "maxZoomRatio": { "alias": "maxZoomRatio"; "required": false; }; "enableRotate": { "alias": "enableRotate"; "required": false; }; "enableCrop": { "alias": "enableCrop"; "required": false; }; "editionFormat": { "alias": "editionFormat"; "required": false; }; "editionQuality": { "alias": "editionQuality"; "required": false; }; "imageSizeQueryParam": { "alias": "imageSizeQueryParam"; "required": false; }; "modalImageSize": { "alias": "modalImageSize"; "required": false; }; "enableLoop": { "alias": "enableLoop"; "required": false; }; "canFetchMore": { "alias": "canFetchMore"; "required": false; }; }, { "deleteRequested": "deleteRequested"; "closeRequested": "closeRequested"; "afterEditImage": "afterEditImage"; "afterEditRow": "afterEditRow"; "previousSlide": "previousSlide"; "nextSlide": "nextSlide"; "fetchMore": "fetchMore"; }, never, never, false, never>;
141
174
  static ngAcceptInputType_mobile: unknown;
142
175
  static ngAcceptInputType_readOnly: unknown;
143
176
  static ngAcceptInputType_disabled: unknown;
@@ -145,5 +178,7 @@ export declare class AppImageGallerySlideshowComponent<T extends Image = Image>
145
178
  static ngAcceptInputType_enableMouseZoom: unknown;
146
179
  static ngAcceptInputType_enableRotate: unknown;
147
180
  static ngAcceptInputType_enableCrop: unknown;
181
+ static ngAcceptInputType_enableLoop: unknown;
182
+ static ngAcceptInputType_canFetchMore: unknown;
148
183
  }
149
184
  export {};
@@ -11,12 +11,14 @@ export declare class GalleryTestPage implements OnInit, OnDestroy {
11
11
  private _subscription;
12
12
  readonly dataSource: EntitiesTableDataSource<ImageAttachment, ImageAttachmentFilter>;
13
13
  protected slideshowMode: ImageGallerySlideshowMode;
14
+ protected enableSlideshowLoop: boolean;
14
15
  protected debug: boolean;
15
16
  constructor(dataService: ImageAttachmentService, route: ActivatedRoute);
16
17
  ngOnInit(): void;
17
18
  ngOnDestroy(): void;
18
19
  save(): void;
19
20
  toggleZoomPresentation(): void;
21
+ toggleSlideshowLoop(): void;
20
22
  toggleDebug(): void;
21
23
  static ɵfac: i0.ɵɵFactoryDeclaration<GalleryTestPage, never>;
22
24
  static ɵcmp: i0.ɵɵComponentDeclaration<GalleryTestPage, "app-gallery-test-page", never, {}, {}, never, never, false, never>;
@@ -18,7 +18,7 @@ export interface InputElement extends FocusableElement {
18
18
  }
19
19
  export declare function isInputElement(object: any): object is InputElement;
20
20
  export declare function asInputElement<T = any>(object: ElementRef<T>): InputElement | undefined;
21
- export declare function tabindexComparator(a: InputElement, b: InputElement): 1 | 0 | -1;
21
+ export declare function tabindexComparator(a: InputElement, b: InputElement): 0 | 1 | -1;
22
22
  export interface CanGainFocusOptions {
23
23
  minTabindex?: number;
24
24
  maxTabindex?: number;
@@ -666,7 +666,9 @@
666
666
  "BTN_CROP_ACTIVATE": "Crop",
667
667
  "BTN_CROP_DEACTIVATE": "Hide crop",
668
668
  "BTN_CROP_RESET": "Reset crop",
669
+ "BTN_CANCEL_EDIT": "Cancel changes",
669
670
  "BTN_ENABLE_MODAL_ZOOM": "Open in a modal?",
671
+ "BTN_ENABLE_LOOP": "Loop slideshow",
670
672
  "ERROR_EDIT_IMAGE": "Unable to save the edited image",
671
673
  "TITLE": "Title"
672
674
  }
@@ -666,7 +666,9 @@
666
666
  "BTN_CROP_ACTIVATE": "Crop",
667
667
  "BTN_CROP_DEACTIVATE": "Hide crop",
668
668
  "BTN_CROP_RESET": "Reset crop",
669
+ "BTN_CANCEL_EDIT": "Cancel changes",
669
670
  "BTN_ENABLE_MODAL_ZOOM": "Open in a modal?",
671
+ "BTN_ENABLE_LOOP": "Loop slideshow",
670
672
  "ERROR_EDIT_IMAGE": "Unable to save the edited image",
671
673
  "TITLE": "Title"
672
674
  }
@@ -668,7 +668,9 @@
668
668
  "BTN_CROP_ACTIVATE": "Recadrer",
669
669
  "BTN_CROP_DEACTIVATE": "Masquer le recadrage",
670
670
  "BTN_CROP_RESET": "Réinitialiser le recadrage",
671
+ "BTN_CANCEL_EDIT": "Annuler les modifications",
671
672
  "BTN_ENABLE_MODAL_ZOOM": "Ouvrir dans une modale ?",
673
+ "BTN_ENABLE_LOOP": "Boucler le diaporama",
672
674
  "ERROR_EDIT_IMAGE": "Impossible d'enregistrer l'image modifiée",
673
675
  "TITLE": "Titre"
674
676
  }
@@ -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.16",
5
+ "version": "18.25.18",
6
6
  "default_locale": "fr",
7
7
  "description": "Angular components for building beautiful and responsive Apps",
8
8
  "icons": [{