@rdlabo/ionic-angular-photo-editor 19.0.3 → 20.0.1
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/fesm2022/rdlabo-ionic-angular-photo-editor.mjs +153 -168
- package/fesm2022/rdlabo-ionic-angular-photo-editor.mjs.map +1 -1
- package/index.d.ts +132 -5
- package/package.json +4 -3
- package/lib/dictionaries.d.ts +0 -4
- package/lib/filter-preset.d.ts +0 -2
- package/lib/ion-components.d.ts +0 -2
- package/lib/pages/photo-editor.page.d.ts +0 -43
- package/lib/pages/photo-viewer.page.d.ts +0 -26
- package/lib/photoEditorErrors.d.ts +0 -5
- package/lib/service/helper.service.d.ts +0 -9
- package/lib/service/photo-file.service.d.ts +0 -16
- package/lib/types.d.ts +0 -48
- package/public-api.d.ts +0 -4
|
@@ -1,17 +1,18 @@
|
|
|
1
|
+
import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
|
|
1
2
|
import * as i0 from '@angular/core';
|
|
2
|
-
import {
|
|
3
|
-
import { CommonModule
|
|
3
|
+
import { inject, signal, input, effect, viewChild, ElementRef, computed, ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, Injectable } from '@angular/core';
|
|
4
|
+
import { CommonModule } from '@angular/common';
|
|
4
5
|
import { FormsModule } from '@angular/forms';
|
|
5
6
|
import * as i1 from '@ionic/angular/standalone';
|
|
6
7
|
import { IonHeader, IonToolbar, IonButtons, IonButton, IonIcon, IonContent, IonFooter, IonText, IonRange, ModalController, IonicSlides, ActionSheetController, Platform } from '@ionic/angular/standalone';
|
|
7
8
|
import ImageEditor from 'tui-image-editor';
|
|
8
9
|
import { toObservable } from '@angular/core/rxjs-interop';
|
|
9
10
|
import { addIcons } from 'ionicons';
|
|
10
|
-
import {
|
|
11
|
+
import { removeOutline, closeOutline, checkmarkOutline, refreshOutline, squareOutline, tabletLandscapeOutline, expandOutline, sunnyOutline, colorFilterOutline, cropOutline, send } from 'ionicons/icons';
|
|
11
12
|
import { Navigation, Zoom } from 'swiper/modules';
|
|
12
|
-
import { fromEvent, zipWith, withLatestFrom, throttleTime } from 'rxjs';
|
|
13
|
+
import { Subscription, fromEvent, zipWith, withLatestFrom, throttleTime } from 'rxjs';
|
|
13
14
|
import { register } from 'swiper/element/bundle';
|
|
14
|
-
import {
|
|
15
|
+
import { CameraSource, CameraResultType, Camera } from '@capacitor/camera';
|
|
15
16
|
|
|
16
17
|
const filterPreset = (dictionary) => [
|
|
17
18
|
{
|
|
@@ -56,46 +57,6 @@ const filterPreset = (dictionary) => [
|
|
|
56
57
|
// },
|
|
57
58
|
];
|
|
58
59
|
|
|
59
|
-
class HelperService {
|
|
60
|
-
constructor() { }
|
|
61
|
-
initializeViewerIcons() {
|
|
62
|
-
addIcons({
|
|
63
|
-
closeOutline,
|
|
64
|
-
removeOutline,
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
initializeEditorIcons() {
|
|
68
|
-
addIcons({
|
|
69
|
-
closeOutline,
|
|
70
|
-
send,
|
|
71
|
-
cropOutline,
|
|
72
|
-
colorFilterOutline,
|
|
73
|
-
sunnyOutline,
|
|
74
|
-
expandOutline,
|
|
75
|
-
tabletLandscapeOutline,
|
|
76
|
-
squareOutline,
|
|
77
|
-
refreshOutline,
|
|
78
|
-
checkmarkOutline,
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
waitToFindDom(nativeElement, selector) {
|
|
82
|
-
return new Promise((resolve) => {
|
|
83
|
-
const interval = setInterval(() => {
|
|
84
|
-
const find = nativeElement.querySelector(selector);
|
|
85
|
-
if (find) {
|
|
86
|
-
clearInterval(interval);
|
|
87
|
-
resolve();
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: HelperService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
93
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: HelperService }); }
|
|
94
|
-
}
|
|
95
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.1", ngImport: i0, type: HelperService, decorators: [{
|
|
96
|
-
type: Injectable
|
|
97
|
-
}], ctorParameters: () => [] });
|
|
98
|
-
|
|
99
60
|
const ionComponents = [IonHeader, IonToolbar, IonButtons, IonButton, IonIcon, IonContent, IonFooter, IonText, IonRange];
|
|
100
61
|
|
|
101
62
|
const dictionaryForEditor = () => ({
|
|
@@ -125,42 +86,81 @@ const dictionaryForService = () => ({
|
|
|
125
86
|
cancel: 'キャンセル',
|
|
126
87
|
});
|
|
127
88
|
|
|
89
|
+
const initializeViewerIcons = () => {
|
|
90
|
+
addIcons({
|
|
91
|
+
closeOutline,
|
|
92
|
+
removeOutline,
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
const initializeEditorIcons = () => {
|
|
96
|
+
addIcons({
|
|
97
|
+
closeOutline,
|
|
98
|
+
send,
|
|
99
|
+
cropOutline,
|
|
100
|
+
colorFilterOutline,
|
|
101
|
+
sunnyOutline,
|
|
102
|
+
expandOutline,
|
|
103
|
+
tabletLandscapeOutline,
|
|
104
|
+
squareOutline,
|
|
105
|
+
refreshOutline,
|
|
106
|
+
checkmarkOutline,
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
const waitToFindDom = (nativeElement, selector) => {
|
|
110
|
+
return new Promise((resolve) => {
|
|
111
|
+
const interval = setInterval(() => {
|
|
112
|
+
const find = nativeElement.querySelector(selector);
|
|
113
|
+
if (find) {
|
|
114
|
+
clearInterval(interval);
|
|
115
|
+
resolve();
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
|
|
128
121
|
class PhotoEditorPage {
|
|
129
|
-
set labels(d) {
|
|
130
|
-
this.dictionary = Object.assign(this.dictionary, d);
|
|
131
|
-
this.filterPreset = filterPreset(this.dictionary);
|
|
132
|
-
}
|
|
133
122
|
constructor() {
|
|
134
|
-
this.
|
|
135
|
-
this.
|
|
136
|
-
this.requireSquare = false
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
this
|
|
140
|
-
this
|
|
141
|
-
|
|
123
|
+
this.modalCtrl = inject(ModalController);
|
|
124
|
+
this.dictionary = signal(dictionaryForEditor());
|
|
125
|
+
this.requireSquare = input(false, {
|
|
126
|
+
transform: coerceBooleanProperty,
|
|
127
|
+
});
|
|
128
|
+
this.labels = input(undefined);
|
|
129
|
+
this.setLabels = effect(() => {
|
|
130
|
+
if (this.labels()) {
|
|
131
|
+
this.dictionary.update((value) => ({ ...value, ...this.labels() }));
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
this.value = input.required();
|
|
135
|
+
this.editorRef = viewChild.required('imageEditor');
|
|
136
|
+
this.ionContent = viewChild.required(IonContent, { read: ElementRef });
|
|
137
|
+
this.filters = signal([]);
|
|
138
|
+
this.footerMenu = signal('menu');
|
|
139
|
+
this.currentCrop = signal('cover');
|
|
140
|
+
this.currentRotate = signal(0);
|
|
141
|
+
this.photoCrop = signal({
|
|
142
142
|
width: 0,
|
|
143
143
|
height: 0,
|
|
144
144
|
});
|
|
145
|
-
this
|
|
146
|
-
this.
|
|
147
|
-
this
|
|
145
|
+
this.isCropped = signal(false);
|
|
146
|
+
this.adoptFilter = signal(undefined);
|
|
147
|
+
this.filterPreset = computed(() => filterPreset(this.dictionary()));
|
|
148
|
+
this.footerMenu$ = toObservable(this.footerMenu);
|
|
148
149
|
this.initSubscription$ = [];
|
|
149
150
|
this.filterImageSize = 240;
|
|
150
|
-
this.service = inject(HelperService);
|
|
151
|
-
this.modalCtrl = inject(ModalController);
|
|
152
151
|
this.canvasContainerObserver = new MutationObserver((mutationsList) => {
|
|
153
152
|
if (mutationsList.find((mutation) => mutation.type === 'attributes' && mutation.attributeName === 'style')) {
|
|
154
153
|
// Cover the image editor with the parent element
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
154
|
+
const editorRef = this.editorRef();
|
|
155
|
+
editorRef.nativeElement.style.minWidth = mutationsList[0].target.parentElement.style.maxWidth;
|
|
156
|
+
editorRef.nativeElement.style.minHeight = mutationsList[0].target.parentElement.style.maxHeight;
|
|
157
|
+
this.photoCrop.set({
|
|
158
158
|
width: mutationsList[0].target.parentElement.querySelector('canvas').width,
|
|
159
159
|
height: mutationsList[0].target.parentElement.querySelector('canvas').height,
|
|
160
160
|
});
|
|
161
161
|
}
|
|
162
162
|
});
|
|
163
|
-
|
|
163
|
+
initializeEditorIcons();
|
|
164
164
|
}
|
|
165
165
|
ngOnInit() {
|
|
166
166
|
this.initSubscription$.push(this.footerMenu$.subscribe((value) => {
|
|
@@ -169,7 +169,7 @@ class PhotoEditorPage {
|
|
|
169
169
|
}
|
|
170
170
|
if (value === 'crop') {
|
|
171
171
|
this.editorInstance.startDrawingMode('CROPPER');
|
|
172
|
-
this.changeCrop(this.requireSquare ? '1' : 'cover');
|
|
172
|
+
this.changeCrop(this.requireSquare() ? '1' : 'cover');
|
|
173
173
|
}
|
|
174
174
|
}));
|
|
175
175
|
}
|
|
@@ -177,62 +177,62 @@ class PhotoEditorPage {
|
|
|
177
177
|
this.initSubscription$.forEach((subscription) => subscription.unsubscribe());
|
|
178
178
|
}
|
|
179
179
|
async ionViewDidEnter() {
|
|
180
|
-
this.editorInstance = new ImageEditor(this.editorRef.nativeElement, {
|
|
181
|
-
cssMaxWidth: this.ionContent.
|
|
182
|
-
cssMaxHeight: this.ionContent.
|
|
180
|
+
this.editorInstance = new ImageEditor(this.editorRef().nativeElement, {
|
|
181
|
+
cssMaxWidth: this.ionContent().nativeElement.clientWidth - 32,
|
|
182
|
+
cssMaxHeight: this.ionContent().nativeElement.clientHeight - 32,
|
|
183
183
|
});
|
|
184
|
-
|
|
185
|
-
this.canvasContainerObserver.observe(this.editorRef.nativeElement.querySelector('.tui-image-editor-canvas-container'), {
|
|
184
|
+
waitToFindDom(this.editorRef().nativeElement, '.tui-image-editor-canvas-container').then(() => {
|
|
185
|
+
this.canvasContainerObserver.observe(this.editorRef().nativeElement.querySelector('.tui-image-editor-canvas-container'), {
|
|
186
186
|
attributes: true,
|
|
187
187
|
childList: false,
|
|
188
188
|
subtree: true,
|
|
189
189
|
});
|
|
190
190
|
});
|
|
191
|
-
const blob = await fetch(this.value).then((res) => res.blob());
|
|
191
|
+
const blob = await fetch(this.value()).then((res) => res.blob());
|
|
192
192
|
await this.editorInstance.loadImageFromFile(new File([blob], 'data.png', { type: blob.type }));
|
|
193
|
-
this
|
|
193
|
+
this.footerMenu.set(this.requireSquare() ? 'crop' : 'menu');
|
|
194
194
|
}
|
|
195
195
|
ionViewDidLeave() {
|
|
196
196
|
this.editorInstance.destroy();
|
|
197
197
|
this.canvasContainerObserver.disconnect();
|
|
198
198
|
}
|
|
199
199
|
changeCrop(crop) {
|
|
200
|
-
const rect = crop === 'cover' ? this
|
|
200
|
+
const rect = crop === 'cover' ? this.photoCrop().width / this.photoCrop().height : crop === '16/9' ? 16 / 9 : 1;
|
|
201
201
|
this.editorInstance.setCropzoneRect(crop !== 'auto' ? rect : undefined);
|
|
202
|
-
this
|
|
202
|
+
this.currentCrop.set(crop);
|
|
203
203
|
}
|
|
204
204
|
async rotate() {
|
|
205
205
|
this.editorInstance.stopDrawingMode();
|
|
206
206
|
await this.editorInstance.rotate(90);
|
|
207
|
-
this
|
|
207
|
+
this.currentRotate.update((value) => value + 90);
|
|
208
208
|
this.editorInstance.startDrawingMode('CROPPER');
|
|
209
|
-
requestAnimationFrame(() => this.changeCrop(this
|
|
209
|
+
requestAnimationFrame(() => this.changeCrop(this.currentCrop()));
|
|
210
210
|
}
|
|
211
211
|
async closeCrop(type) {
|
|
212
|
-
if (this
|
|
212
|
+
if (this.footerMenu() === 'crop') {
|
|
213
213
|
if (type === 'cancel') {
|
|
214
|
-
await this.editorInstance.rotate(this
|
|
214
|
+
await this.editorInstance.rotate(this.currentRotate() * -1);
|
|
215
215
|
}
|
|
216
216
|
else {
|
|
217
217
|
await this.editorInstance.crop(this.editorInstance.getCropzoneRect());
|
|
218
|
-
this
|
|
218
|
+
this.isCropped.set(true);
|
|
219
219
|
}
|
|
220
|
-
this
|
|
221
|
-
this
|
|
220
|
+
this.currentRotate.set(0);
|
|
221
|
+
this.currentCrop.set('cover');
|
|
222
222
|
this.editorInstance.stopDrawingMode();
|
|
223
223
|
}
|
|
224
|
-
else if (this
|
|
224
|
+
else if (this.footerMenu() === 'brightness') {
|
|
225
225
|
if (type === 'cancel' && this.editorInstance.hasFilter('brightness')) {
|
|
226
226
|
await this.editorInstance.removeFilter('brightness');
|
|
227
227
|
}
|
|
228
228
|
}
|
|
229
|
-
this
|
|
229
|
+
this.footerMenu.set('menu');
|
|
230
230
|
}
|
|
231
231
|
async changeRange(event) {
|
|
232
232
|
if (this.editorInstance.hasFilter('brightness')) {
|
|
233
233
|
await this.editorInstance.removeFilter('brightness');
|
|
234
234
|
}
|
|
235
|
-
this.editorInstance.applyFilter('brightness', {
|
|
235
|
+
await this.editorInstance.applyFilter('brightness', {
|
|
236
236
|
brightness: Number(event.detail.value) / 255,
|
|
237
237
|
});
|
|
238
238
|
}
|
|
@@ -244,13 +244,13 @@ class PhotoEditorPage {
|
|
|
244
244
|
const filters = [];
|
|
245
245
|
const defaultInstance = new ImageEditor(document.createElement('div'), {
|
|
246
246
|
cssMaxWidth: this.filterImageSize,
|
|
247
|
-
cssMaxHeight: (this
|
|
247
|
+
cssMaxHeight: (this.photoCrop().height * this.filterImageSize) / this.photoCrop().width,
|
|
248
248
|
});
|
|
249
249
|
const blob = await fetch(this.editorInstance.toDataURL({
|
|
250
|
-
multiplier: this.filterImageSize / this
|
|
250
|
+
multiplier: this.filterImageSize / this.photoCrop().width,
|
|
251
251
|
})).then((res) => res.blob());
|
|
252
252
|
await defaultInstance.loadImageFromFile(new File([blob], 'defaultInstance.png', { type: blob.type }));
|
|
253
|
-
for (const filter of this.filterPreset) {
|
|
253
|
+
for (const filter of this.filterPreset()) {
|
|
254
254
|
if (filter.type !== 'Default') {
|
|
255
255
|
await defaultInstance.applyFilter(filter.type, filter.option);
|
|
256
256
|
}
|
|
@@ -260,68 +260,70 @@ class PhotoEditorPage {
|
|
|
260
260
|
option: filter.option,
|
|
261
261
|
data: defaultInstance.toDataURL(),
|
|
262
262
|
width: this.filterImageSize,
|
|
263
|
-
height: (this
|
|
263
|
+
height: (this.photoCrop().height * this.filterImageSize) / this.photoCrop().width,
|
|
264
264
|
});
|
|
265
265
|
if (filter.type !== 'Default') {
|
|
266
266
|
await defaultInstance.removeFilter(filter.type);
|
|
267
267
|
}
|
|
268
268
|
}
|
|
269
|
-
this
|
|
269
|
+
this.filters.set(filters);
|
|
270
270
|
defaultInstance.destroy();
|
|
271
271
|
}
|
|
272
272
|
async filterImage(filter) {
|
|
273
|
-
if (this
|
|
274
|
-
await this.editorInstance.removeFilter(this
|
|
273
|
+
if (this.adoptFilter()) {
|
|
274
|
+
await this.editorInstance.removeFilter(this.adoptFilter().type);
|
|
275
275
|
}
|
|
276
276
|
if (filter.type === 'Default') {
|
|
277
|
-
this
|
|
277
|
+
this.adoptFilter.set(undefined);
|
|
278
278
|
return;
|
|
279
279
|
}
|
|
280
280
|
await this.editorInstance.applyFilter(filter.type, filter.option);
|
|
281
|
-
this
|
|
281
|
+
this.adoptFilter.set(filter);
|
|
282
282
|
}
|
|
283
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
284
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
283
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: PhotoEditorPage, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
284
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: PhotoEditorPage, isStandalone: true, selector: "app-editor-image", inputs: { requireSquare: { classPropertyName: "requireSquare", publicName: "requireSquare", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "editorRef", first: true, predicate: ["imageEditor"], descendants: true, isSignal: true }, { propertyName: "ionContent", first: true, predicate: IonContent, descendants: true, read: ElementRef, isSignal: true }], ngImport: i0, template: "<ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"start\"\n ><ion-button (click)=\"modalCtrl.dismiss()\"><ion-icon name=\"close-outline\" slot=\"icon-only\"></ion-icon></ion-button\n ></ion-buttons>\n <ion-buttons slot=\"end\">\n <ion-button color=\"photo-editor-primary\" fill=\"outline\" [disabled]=\"!['menu', 'filter'].includes(footerMenu())\" (click)=\"imageSave()\">\n {{ dictionary().save }}\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\" [scrollY]=\"false\">\n <div #imageEditor></div>\n</ion-content>\n<ion-footer>\n <ion-toolbar>\n @if (this.footerMenu() === 'menu') {\n <aside class=\"ion-justify-content-center\">\n <button (click)=\"footerMenu.set('crop')\">\n <ion-text>{{ dictionary().crop }}</ion-text>\n <ion-icon name=\"crop-outline\" size=\"large\"></ion-icon>\n </button>\n <button (click)=\"footerMenu.set('filter')\">\n <ion-text>{{ dictionary().filter }}</ion-text>\n <ion-icon name=\"color-filter-outline\" size=\"large\"></ion-icon>\n </button>\n <button (click)=\"footerMenu.set('brightness')\">\n <ion-text>{{ dictionary().brightness }}</ion-text>\n <ion-icon name=\"sunny-outline\" size=\"large\"></ion-icon>\n </button>\n </aside>\n }\n\n @if (this.footerMenu() === 'filter') {\n <aside>\n @for (item of filters(); track item) {\n <button (click)=\"filterImage(item)\">\n <ion-text>{{ item.name }}</ion-text>\n <span class=\"image-filter-box\" [style.background-image]=\"'url(' + item.data + ')'\"></span>\n </button>\n }\n </aside>\n }\n\n @if (this.footerMenu() === 'crop' && !requireSquare()) {\n <ion-buttons class=\"ion-justify-content-center submenu-icon-buttons\">\n <ion-button (click)=\"changeCrop('cover')\" [color]=\"currentCrop() === 'cover' ? 'success' : undefined\">\n <ion-icon name=\"expand-outline\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n <ion-button (click)=\"changeCrop('16/9')\" [color]=\"currentCrop() === '16/9' ? 'success' : undefined\">\n <ion-icon name=\"tablet-landscape-outline\" slot=\"icon-only\" style=\"transform: scale(1, 0.8)\"></ion-icon>\n </ion-button>\n <ion-button (click)=\"changeCrop('1')\" [color]=\"currentCrop() === '1' ? 'success' : undefined\">\n <ion-icon name=\"square-outline\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n <ion-button (click)=\"changeCrop('auto')\" [color]=\"currentCrop() === 'auto' ? 'success' : undefined\">\n <ion-icon name=\"crop-outline\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n <ion-button (click)=\"rotate()\"><ion-icon name=\"refresh-outline\" slot=\"icon-only\"></ion-icon></ion-button>\n </ion-buttons>\n }\n\n @if (['brightness'].includes(this.footerMenu())) {\n <div class=\"ion-padding ion-margin\">\n <ion-range [pin]=\"true\" [min]=\"-100\" [max]=\"100\" (ionChange)=\"changeRange($any($event))\"></ion-range>\n </div>\n }\n </ion-toolbar>\n @if (this.footerMenu() !== 'menu') {\n <ion-toolbar mode=\"md\">\n @if (this.footerMenu() === 'filter') {\n <ion-buttons class=\"ion-justify-content-center\" style=\"margin: 0 8px\">\n <ion-button fill=\"outline\" shape=\"round\" (click)=\"this.footerMenu.set('menu')\">\u623B\u308B</ion-button>\n </ion-buttons>\n } @else {\n <ion-buttons slot=\"start\" style=\"min-width: 60px\">\n @if (!requireSquare() || isCropped()) {\n <ion-button (click)=\"closeCrop('cancel')\"><ion-icon name=\"close-outline\" slot=\"icon-only\"></ion-icon></ion-button>\n }</ion-buttons\n ><ion-text class=\"footer-title\">\n @if (footerMenu() === 'crop') {\n {{ dictionary().crop }}\n } @else if (footerMenu() === 'brightness') {\n {{ dictionary().brightness }}\n }</ion-text\n ><ion-buttons slot=\"end\"\n ><ion-button (click)=\"closeCrop('apply')\"\n ><ion-icon name=\"checkmark-outline\" color=\"photo-editor-success\" slot=\"icon-only\"></ion-icon></ion-button\n ></ion-buttons>\n }\n </ion-toolbar>\n }\n</ion-footer>\n", styles: [":host{--editor-background: var(--ion-photo-editor-background, --ion-color-step-100, #2a2a2a);--editor-background-tint: var(--ion-photo-editor-background-tint, --ion-color-step-200, #414141);--editor-color: var(--ion-photo-editor-color, --ion-color-step-950, #f0f0f0);--editor-color-tint: var(--ion-photo-editor-color-tint, --ion-color-step-850, #dbdbdb);--ion-color-photo-editor-primary: var(--ion-photo-editor-primary, --ion-color-primary, #4d8dff);--ion-color-photo-editor-danger: var(--ion-photo-editor-danger, #f24c58);--ion-color-photo-editor-success: var(--ion-photo-editor-success, #2dd55b)}.ion-color-photo-editor-primary{--ion-color-base: var(--ion-color-photo-editor-primary)}.ion-color-photo-editor-danger{--ion-color-base: var(--ion-color-photo-editor-danger)}.ion-color-photo-editor-success{--ion-color-base: var(--ion-color-photo-editor-success)}ion-content,ion-toolbar,ion-header,ion-footer{background:var(--editor-background)!important;--background: var(--editor-background) !important}\n", "ion-content{--background: var(--editor-background)}ion-content>div{width:100%;height:100%;max-width:100%;max-height:100%;display:grid;align-items:center;justify-items:center}aside{display:flex;overflow-x:scroll;margin-top:16px;min-height:120px}aside ion-icon{color:var(--editor-color);border:1px solid var(--editor-background-tint);border-radius:50%;padding:16px}aside button{width:120px;display:block;flex:1;background:transparent;margin:0 8px 16px}aside button ion-text{display:block;color:var(--editor-color);margin-bottom:8px;font-size:.8rem}aside button span.image-filter-box{width:96px;height:64px;border-radius:8px;overflow:hidden;display:block;background-position:center,center;background-size:cover}ion-header ion-button,ion-footer ion-button{--color: var(--editor-color) !important}ion-footer ion-toolbar ion-text.footer-title{color:var(--editor-color)!important;display:block;text-align:center}ion-footer ion-toolbar ion-range{--bar-background: var(--editor-color);--bar-background-active: var(--editor-color);--bar-height: 2px;--bar-border-radius: 8px;--knob-background: var(--editor-color);--knob-size: 20px;--pin-background: none;--pin-color: var(--editor-color)}ion-footer ion-toolbar ion-buttons[slot=start] ion-button,ion-footer ion-toolbar ion-buttons[slot=end] ion-button{--background: var(--editor-background-tint) !important;--border-radius: 50%;margin:0 8px;min-width:32px;min-height:32px}ion-footer ion-toolbar ion-buttons.submenu-icon-buttons ion-button{margin:16px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: i1.IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: i1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i1.IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i1.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: i1.IonRange, selector: "ion-range", inputs: ["activeBarStart", "color", "debounce", "disabled", "dualKnobs", "label", "labelPlacement", "max", "min", "mode", "name", "pin", "pinFormatter", "snaps", "step", "ticks", "value"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
285
285
|
}
|
|
286
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
286
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: PhotoEditorPage, decorators: [{
|
|
287
287
|
type: Component,
|
|
288
|
-
args: [{ selector: 'app-editor-image', imports: [CommonModule, FormsModule,
|
|
289
|
-
}], ctorParameters: () => []
|
|
290
|
-
type: Input
|
|
291
|
-
}], value: [{
|
|
292
|
-
type: Input
|
|
293
|
-
}], labels: [{
|
|
294
|
-
type: Input
|
|
295
|
-
}], editorRef: [{
|
|
296
|
-
type: ViewChild,
|
|
297
|
-
args: ['imageEditor', { static: true }]
|
|
298
|
-
}], ionContent: [{
|
|
299
|
-
type: ViewChild,
|
|
300
|
-
args: [IonContent]
|
|
301
|
-
}] } });
|
|
288
|
+
args: [{ selector: 'app-editor-image', imports: [CommonModule, FormsModule, ...ionComponents], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"start\"\n ><ion-button (click)=\"modalCtrl.dismiss()\"><ion-icon name=\"close-outline\" slot=\"icon-only\"></ion-icon></ion-button\n ></ion-buttons>\n <ion-buttons slot=\"end\">\n <ion-button color=\"photo-editor-primary\" fill=\"outline\" [disabled]=\"!['menu', 'filter'].includes(footerMenu())\" (click)=\"imageSave()\">\n {{ dictionary().save }}\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\" [scrollY]=\"false\">\n <div #imageEditor></div>\n</ion-content>\n<ion-footer>\n <ion-toolbar>\n @if (this.footerMenu() === 'menu') {\n <aside class=\"ion-justify-content-center\">\n <button (click)=\"footerMenu.set('crop')\">\n <ion-text>{{ dictionary().crop }}</ion-text>\n <ion-icon name=\"crop-outline\" size=\"large\"></ion-icon>\n </button>\n <button (click)=\"footerMenu.set('filter')\">\n <ion-text>{{ dictionary().filter }}</ion-text>\n <ion-icon name=\"color-filter-outline\" size=\"large\"></ion-icon>\n </button>\n <button (click)=\"footerMenu.set('brightness')\">\n <ion-text>{{ dictionary().brightness }}</ion-text>\n <ion-icon name=\"sunny-outline\" size=\"large\"></ion-icon>\n </button>\n </aside>\n }\n\n @if (this.footerMenu() === 'filter') {\n <aside>\n @for (item of filters(); track item) {\n <button (click)=\"filterImage(item)\">\n <ion-text>{{ item.name }}</ion-text>\n <span class=\"image-filter-box\" [style.background-image]=\"'url(' + item.data + ')'\"></span>\n </button>\n }\n </aside>\n }\n\n @if (this.footerMenu() === 'crop' && !requireSquare()) {\n <ion-buttons class=\"ion-justify-content-center submenu-icon-buttons\">\n <ion-button (click)=\"changeCrop('cover')\" [color]=\"currentCrop() === 'cover' ? 'success' : undefined\">\n <ion-icon name=\"expand-outline\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n <ion-button (click)=\"changeCrop('16/9')\" [color]=\"currentCrop() === '16/9' ? 'success' : undefined\">\n <ion-icon name=\"tablet-landscape-outline\" slot=\"icon-only\" style=\"transform: scale(1, 0.8)\"></ion-icon>\n </ion-button>\n <ion-button (click)=\"changeCrop('1')\" [color]=\"currentCrop() === '1' ? 'success' : undefined\">\n <ion-icon name=\"square-outline\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n <ion-button (click)=\"changeCrop('auto')\" [color]=\"currentCrop() === 'auto' ? 'success' : undefined\">\n <ion-icon name=\"crop-outline\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n <ion-button (click)=\"rotate()\"><ion-icon name=\"refresh-outline\" slot=\"icon-only\"></ion-icon></ion-button>\n </ion-buttons>\n }\n\n @if (['brightness'].includes(this.footerMenu())) {\n <div class=\"ion-padding ion-margin\">\n <ion-range [pin]=\"true\" [min]=\"-100\" [max]=\"100\" (ionChange)=\"changeRange($any($event))\"></ion-range>\n </div>\n }\n </ion-toolbar>\n @if (this.footerMenu() !== 'menu') {\n <ion-toolbar mode=\"md\">\n @if (this.footerMenu() === 'filter') {\n <ion-buttons class=\"ion-justify-content-center\" style=\"margin: 0 8px\">\n <ion-button fill=\"outline\" shape=\"round\" (click)=\"this.footerMenu.set('menu')\">\u623B\u308B</ion-button>\n </ion-buttons>\n } @else {\n <ion-buttons slot=\"start\" style=\"min-width: 60px\">\n @if (!requireSquare() || isCropped()) {\n <ion-button (click)=\"closeCrop('cancel')\"><ion-icon name=\"close-outline\" slot=\"icon-only\"></ion-icon></ion-button>\n }</ion-buttons\n ><ion-text class=\"footer-title\">\n @if (footerMenu() === 'crop') {\n {{ dictionary().crop }}\n } @else if (footerMenu() === 'brightness') {\n {{ dictionary().brightness }}\n }</ion-text\n ><ion-buttons slot=\"end\"\n ><ion-button (click)=\"closeCrop('apply')\"\n ><ion-icon name=\"checkmark-outline\" color=\"photo-editor-success\" slot=\"icon-only\"></ion-icon></ion-button\n ></ion-buttons>\n }\n </ion-toolbar>\n }\n</ion-footer>\n", styles: [":host{--editor-background: var(--ion-photo-editor-background, --ion-color-step-100, #2a2a2a);--editor-background-tint: var(--ion-photo-editor-background-tint, --ion-color-step-200, #414141);--editor-color: var(--ion-photo-editor-color, --ion-color-step-950, #f0f0f0);--editor-color-tint: var(--ion-photo-editor-color-tint, --ion-color-step-850, #dbdbdb);--ion-color-photo-editor-primary: var(--ion-photo-editor-primary, --ion-color-primary, #4d8dff);--ion-color-photo-editor-danger: var(--ion-photo-editor-danger, #f24c58);--ion-color-photo-editor-success: var(--ion-photo-editor-success, #2dd55b)}.ion-color-photo-editor-primary{--ion-color-base: var(--ion-color-photo-editor-primary)}.ion-color-photo-editor-danger{--ion-color-base: var(--ion-color-photo-editor-danger)}.ion-color-photo-editor-success{--ion-color-base: var(--ion-color-photo-editor-success)}ion-content,ion-toolbar,ion-header,ion-footer{background:var(--editor-background)!important;--background: var(--editor-background) !important}\n", "ion-content{--background: var(--editor-background)}ion-content>div{width:100%;height:100%;max-width:100%;max-height:100%;display:grid;align-items:center;justify-items:center}aside{display:flex;overflow-x:scroll;margin-top:16px;min-height:120px}aside ion-icon{color:var(--editor-color);border:1px solid var(--editor-background-tint);border-radius:50%;padding:16px}aside button{width:120px;display:block;flex:1;background:transparent;margin:0 8px 16px}aside button ion-text{display:block;color:var(--editor-color);margin-bottom:8px;font-size:.8rem}aside button span.image-filter-box{width:96px;height:64px;border-radius:8px;overflow:hidden;display:block;background-position:center,center;background-size:cover}ion-header ion-button,ion-footer ion-button{--color: var(--editor-color) !important}ion-footer ion-toolbar ion-text.footer-title{color:var(--editor-color)!important;display:block;text-align:center}ion-footer ion-toolbar ion-range{--bar-background: var(--editor-color);--bar-background-active: var(--editor-color);--bar-height: 2px;--bar-border-radius: 8px;--knob-background: var(--editor-color);--knob-size: 20px;--pin-background: none;--pin-color: var(--editor-color)}ion-footer ion-toolbar ion-buttons[slot=start] ion-button,ion-footer ion-toolbar ion-buttons[slot=end] ion-button{--background: var(--editor-background-tint) !important;--border-radius: 50%;margin:0 8px;min-width:32px;min-height:32px}ion-footer ion-toolbar ion-buttons.submenu-icon-buttons ion-button{margin:16px}\n"] }]
|
|
289
|
+
}], ctorParameters: () => [] });
|
|
302
290
|
|
|
303
291
|
class PhotoViewerPage {
|
|
304
|
-
set labels(d) {
|
|
305
|
-
this.dictionary = Object.assign(this.dictionary, d);
|
|
306
|
-
}
|
|
307
292
|
constructor() {
|
|
308
|
-
this.
|
|
309
|
-
this.
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
this.
|
|
313
|
-
|
|
293
|
+
this.imageUrls = input.required();
|
|
294
|
+
this.index = input(0, {
|
|
295
|
+
transform: coerceNumberProperty,
|
|
296
|
+
});
|
|
297
|
+
this.isCircle = input(false, {
|
|
298
|
+
transform: coerceBooleanProperty,
|
|
299
|
+
});
|
|
300
|
+
this.enableDelete = input(false, {
|
|
301
|
+
transform: coerceBooleanProperty,
|
|
302
|
+
});
|
|
303
|
+
this.enableFooterSafeArea = input(false, {
|
|
304
|
+
transform: coerceBooleanProperty,
|
|
305
|
+
});
|
|
306
|
+
this.labels = input();
|
|
307
|
+
this.setLabels = effect(() => {
|
|
308
|
+
if (this.labels()) {
|
|
309
|
+
this.dictionary.update((value) => ({ ...value, ...this.labels() }));
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
this.swiper = viewChild.required('swiper');
|
|
313
|
+
this.dictionary = signal(dictionaryForViewer());
|
|
314
|
+
this.watchSwipe$ = new Subscription();
|
|
314
315
|
this.modalCtrl = inject(ModalController);
|
|
315
316
|
this.el = inject(ElementRef);
|
|
316
|
-
this.service = inject(HelperService);
|
|
317
317
|
register();
|
|
318
|
-
|
|
318
|
+
initializeViewerIcons();
|
|
319
319
|
}
|
|
320
320
|
async ngOnInit() {
|
|
321
|
-
|
|
322
|
-
|
|
321
|
+
waitToFindDom(this.el.nativeElement, 'swiper-container').then(() => {
|
|
322
|
+
const index = this.index();
|
|
323
|
+
const swiper = this.swiper();
|
|
324
|
+
Object.assign(swiper.nativeElement, {
|
|
323
325
|
modules: [Navigation, Zoom, IonicSlides],
|
|
324
|
-
initialSlide:
|
|
326
|
+
initialSlide: index,
|
|
325
327
|
slidesPerView: 1,
|
|
326
328
|
pagination: {
|
|
327
329
|
enabled: true,
|
|
@@ -329,12 +331,12 @@ class PhotoViewerPage {
|
|
|
329
331
|
},
|
|
330
332
|
zoom: true,
|
|
331
333
|
});
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
334
|
+
swiper.nativeElement.initialize();
|
|
335
|
+
swiper.nativeElement.swiper.zoom.enable();
|
|
336
|
+
swiper.nativeElement.swiper.activeIndex = index;
|
|
337
|
+
swiper.nativeElement.swiper.update();
|
|
336
338
|
});
|
|
337
|
-
this.watchSwipe
|
|
339
|
+
this.watchSwipe$.add(fromEvent(this.el.nativeElement, 'touchstart')
|
|
338
340
|
.pipe(zipWith(fromEvent(this.el.nativeElement, 'touchend').pipe(withLatestFrom(fromEvent(this.el.nativeElement, 'touchmove')))), throttleTime(1))
|
|
339
341
|
.subscribe(([touchstart, [_, touchmove]]) => {
|
|
340
342
|
const touchstartClientX = touchstart.touches ? touchstart.touches[0].clientX : touchstart.detail[1].clientX;
|
|
@@ -343,7 +345,7 @@ class PhotoViewerPage {
|
|
|
343
345
|
const touchmoveClientY = touchmove.touches ? touchmove.touches[0].clientY : touchmove.detail[1].clientY;
|
|
344
346
|
const xDiff = touchstartClientX - touchmoveClientX;
|
|
345
347
|
const yDiff = touchstartClientY - touchmoveClientY;
|
|
346
|
-
const slides = this.swiper.nativeElement.querySelectorAll('swiper-slide');
|
|
348
|
+
const slides = this.swiper().nativeElement.querySelectorAll('swiper-slide');
|
|
347
349
|
const isZoomed = Array.from(slides).find((slide) => {
|
|
348
350
|
return ['swiper-slide-zoomed', 'swiper-slide-active'].every((c) => slide.classList.contains(c));
|
|
349
351
|
});
|
|
@@ -352,43 +354,26 @@ class PhotoViewerPage {
|
|
|
352
354
|
this.watchSwipe$.unsubscribe();
|
|
353
355
|
this.modalCtrl.dismiss();
|
|
354
356
|
}
|
|
355
|
-
});
|
|
357
|
+
}));
|
|
356
358
|
}
|
|
357
359
|
ngOnDestroy() {
|
|
358
|
-
|
|
359
|
-
this.watchSwipe$.unsubscribe();
|
|
360
|
-
}
|
|
360
|
+
this.watchSwipe$.unsubscribe();
|
|
361
361
|
}
|
|
362
362
|
remove() {
|
|
363
363
|
this.modalCtrl.dismiss({
|
|
364
364
|
delete: {
|
|
365
|
-
index: this.swiper.nativeElement.swiper.activeIndex,
|
|
366
|
-
value: this.imageUrls[this.swiper.nativeElement.swiper.activeIndex],
|
|
365
|
+
index: this.swiper().nativeElement.swiper.activeIndex,
|
|
366
|
+
value: this.imageUrls()[this.swiper().nativeElement.swiper.activeIndex],
|
|
367
367
|
},
|
|
368
368
|
});
|
|
369
369
|
}
|
|
370
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
371
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
370
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: PhotoViewerPage, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
371
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: PhotoViewerPage, isStandalone: true, selector: "app-photo-image", inputs: { imageUrls: { classPropertyName: "imageUrls", publicName: "imageUrls", isSignal: true, isRequired: true, transformFunction: null }, index: { classPropertyName: "index", publicName: "index", isSignal: true, isRequired: false, transformFunction: null }, isCircle: { classPropertyName: "isCircle", publicName: "isCircle", isSignal: true, isRequired: false, transformFunction: null }, enableDelete: { classPropertyName: "enableDelete", publicName: "enableDelete", isSignal: true, isRequired: false, transformFunction: null }, enableFooterSafeArea: { classPropertyName: "enableFooterSafeArea", publicName: "enableFooterSafeArea", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "swiper", first: true, predicate: ["swiper"], descendants: true, isSignal: true }], ngImport: i0, template: "<ion-header [translucent]=\"true\">\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-button (click)=\"modalCtrl.dismiss()\" class=\"viewer-close-button\">\n <ion-icon name=\"close-outline\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </ion-buttons>\n @if (enableDelete()) {\n <ion-buttons slot=\"end\">\n <ion-button color=\"photo-editor-danger\" fill=\"outline\" (click)=\"remove()\">{{ dictionary().delete }}</ion-button>\n </ion-buttons>\n }\n </ion-toolbar>\n</ion-header>\n\n<ion-content [fullscreen]=\"true\">\n <swiper-container #swiper>\n @for (url of imageUrls(); track url) {\n <swiper-slide>\n <div class=\"swiper-zoom-container\"><img [src]=\"url\" alt=\"\" [class.circle]=\"isCircle()\" /></div>\n </swiper-slide>\n }\n </swiper-container>\n</ion-content>\n\n@if (enableFooterSafeArea()) {\n <!-- use for safe area-->\n <ion-footer>\n <ion-toolbar style=\"--border-width: 0; --min-height: 0\"></ion-toolbar>\n </ion-footer>\n}\n", styles: [":host{--editor-background: var(--ion-photo-editor-background, --ion-color-step-100, #2a2a2a);--editor-background-tint: var(--ion-photo-editor-background-tint, --ion-color-step-200, #414141);--editor-color: var(--ion-photo-editor-color, --ion-color-step-950, #f0f0f0);--editor-color-tint: var(--ion-photo-editor-color-tint, --ion-color-step-850, #dbdbdb);--ion-color-photo-editor-primary: var(--ion-photo-editor-primary, --ion-color-primary, #4d8dff);--ion-color-photo-editor-danger: var(--ion-photo-editor-danger, #f24c58);--ion-color-photo-editor-success: var(--ion-photo-editor-success, #2dd55b)}.ion-color-photo-editor-primary{--ion-color-base: var(--ion-color-photo-editor-primary)}.ion-color-photo-editor-danger{--ion-color-base: var(--ion-color-photo-editor-danger)}.ion-color-photo-editor-success{--ion-color-base: var(--ion-color-photo-editor-success)}ion-content,ion-toolbar,ion-header,ion-footer{background:var(--editor-background)!important;--background: var(--editor-background) !important}\n", "ion-button.viewer-close-button{--color: var(--editor-color) !important}img.circle{border-radius:50%;display:block;padding:16px}swiper-container{height:100%;max-height:100%}swiper-slide{height:100%;max-height:100%;display:flex;justify-content:center;align-items:center}swiper-slide img{display:block;object-fit:contain;max-width:100%;max-height:100%}\n"], dependencies: [{ kind: "component", type: i1.IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: i1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i1.IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
372
372
|
}
|
|
373
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
373
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: PhotoViewerPage, decorators: [{
|
|
374
374
|
type: Component,
|
|
375
|
-
args: [{ selector: 'app-photo-image', imports: [
|
|
376
|
-
}], ctorParameters: () => []
|
|
377
|
-
type: Input
|
|
378
|
-
}], index: [{
|
|
379
|
-
type: Input
|
|
380
|
-
}], isCircle: [{
|
|
381
|
-
type: Input
|
|
382
|
-
}], enableDelete: [{
|
|
383
|
-
type: Input
|
|
384
|
-
}], enableFooterSafeArea: [{
|
|
385
|
-
type: Input
|
|
386
|
-
}], labels: [{
|
|
387
|
-
type: Input
|
|
388
|
-
}], swiper: [{
|
|
389
|
-
type: ViewChild,
|
|
390
|
-
args: ['swiper']
|
|
391
|
-
}] } });
|
|
375
|
+
args: [{ selector: 'app-photo-image', imports: [...ionComponents], schemas: [CUSTOM_ELEMENTS_SCHEMA], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-header [translucent]=\"true\">\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-button (click)=\"modalCtrl.dismiss()\" class=\"viewer-close-button\">\n <ion-icon name=\"close-outline\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </ion-buttons>\n @if (enableDelete()) {\n <ion-buttons slot=\"end\">\n <ion-button color=\"photo-editor-danger\" fill=\"outline\" (click)=\"remove()\">{{ dictionary().delete }}</ion-button>\n </ion-buttons>\n }\n </ion-toolbar>\n</ion-header>\n\n<ion-content [fullscreen]=\"true\">\n <swiper-container #swiper>\n @for (url of imageUrls(); track url) {\n <swiper-slide>\n <div class=\"swiper-zoom-container\"><img [src]=\"url\" alt=\"\" [class.circle]=\"isCircle()\" /></div>\n </swiper-slide>\n }\n </swiper-container>\n</ion-content>\n\n@if (enableFooterSafeArea()) {\n <!-- use for safe area-->\n <ion-footer>\n <ion-toolbar style=\"--border-width: 0; --min-height: 0\"></ion-toolbar>\n </ion-footer>\n}\n", styles: [":host{--editor-background: var(--ion-photo-editor-background, --ion-color-step-100, #2a2a2a);--editor-background-tint: var(--ion-photo-editor-background-tint, --ion-color-step-200, #414141);--editor-color: var(--ion-photo-editor-color, --ion-color-step-950, #f0f0f0);--editor-color-tint: var(--ion-photo-editor-color-tint, --ion-color-step-850, #dbdbdb);--ion-color-photo-editor-primary: var(--ion-photo-editor-primary, --ion-color-primary, #4d8dff);--ion-color-photo-editor-danger: var(--ion-photo-editor-danger, #f24c58);--ion-color-photo-editor-success: var(--ion-photo-editor-success, #2dd55b)}.ion-color-photo-editor-primary{--ion-color-base: var(--ion-color-photo-editor-primary)}.ion-color-photo-editor-danger{--ion-color-base: var(--ion-color-photo-editor-danger)}.ion-color-photo-editor-success{--ion-color-base: var(--ion-color-photo-editor-success)}ion-content,ion-toolbar,ion-header,ion-footer{background:var(--editor-background)!important;--background: var(--editor-background) !important}\n", "ion-button.viewer-close-button{--color: var(--editor-color) !important}img.circle{border-radius:50%;display:block;padding:16px}swiper-container{height:100%;max-height:100%}swiper-slide{height:100%;max-height:100%;display:flex;justify-content:center;align-items:center}swiper-slide img{display:block;object-fit:contain;max-width:100%;max-height:100%}\n"] }]
|
|
376
|
+
}], ctorParameters: () => [] });
|
|
392
377
|
|
|
393
378
|
var PhotoEditorErrors;
|
|
394
379
|
(function (PhotoEditorErrors) {
|
|
@@ -402,13 +387,13 @@ class PhotoFileService {
|
|
|
402
387
|
this.$photoMaxSize = signal(1000);
|
|
403
388
|
this.actionSheetCtrl = inject(ActionSheetController);
|
|
404
389
|
this.platform = inject(Platform);
|
|
405
|
-
this.dictionary = dictionaryForService();
|
|
390
|
+
this.dictionary = signal(dictionaryForService());
|
|
406
391
|
}
|
|
407
392
|
set photoMaxSize(value) {
|
|
408
393
|
this.$photoMaxSize.set(value);
|
|
409
394
|
}
|
|
410
395
|
set labels(d) {
|
|
411
|
-
this.dictionary
|
|
396
|
+
this.dictionary.update((value) => ({ ...value, ...d }));
|
|
412
397
|
}
|
|
413
398
|
async loadPhoto(limit) {
|
|
414
399
|
/**
|
|
@@ -420,19 +405,19 @@ class PhotoFileService {
|
|
|
420
405
|
const actionSheet = await this.actionSheetCtrl.create({
|
|
421
406
|
buttons: [
|
|
422
407
|
{
|
|
423
|
-
text: this.dictionary.camera,
|
|
408
|
+
text: this.dictionary().camera,
|
|
424
409
|
handler: () => {
|
|
425
410
|
actionSheet.dismiss('camera');
|
|
426
411
|
},
|
|
427
412
|
},
|
|
428
413
|
{
|
|
429
|
-
text: this.dictionary.album,
|
|
414
|
+
text: this.dictionary().album,
|
|
430
415
|
handler: () => {
|
|
431
416
|
actionSheet.dismiss('album');
|
|
432
417
|
},
|
|
433
418
|
},
|
|
434
419
|
{
|
|
435
|
-
text: this.dictionary.cancel,
|
|
420
|
+
text: this.dictionary().cancel,
|
|
436
421
|
role: 'cancel',
|
|
437
422
|
},
|
|
438
423
|
],
|
|
@@ -481,7 +466,7 @@ class PhotoFileService {
|
|
|
481
466
|
return Promise.reject(PhotoEditorErrors.initialize);
|
|
482
467
|
}
|
|
483
468
|
return new Promise((resolve, reject) => {
|
|
484
|
-
const cancelMethod = (
|
|
469
|
+
const cancelMethod = () => {
|
|
485
470
|
inputFile.removeEventListener('cancel', cancelMethod, false);
|
|
486
471
|
inputFile.removeEventListener('change', changeMethod, false);
|
|
487
472
|
reject(PhotoEditorErrors.cancel);
|
|
@@ -526,15 +511,15 @@ class PhotoFileService {
|
|
|
526
511
|
defaultInstance.destroy();
|
|
527
512
|
return dataUrl;
|
|
528
513
|
}
|
|
529
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
530
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
514
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: PhotoFileService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
515
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: PhotoFileService, providedIn: 'root' }); }
|
|
531
516
|
}
|
|
532
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
517
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: PhotoFileService, decorators: [{
|
|
533
518
|
type: Injectable,
|
|
534
519
|
args: [{
|
|
535
520
|
providedIn: 'root',
|
|
536
521
|
}]
|
|
537
|
-
}]
|
|
522
|
+
}] });
|
|
538
523
|
|
|
539
524
|
/*
|
|
540
525
|
* Public API Surface of photo-editor
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rdlabo-ionic-angular-photo-editor.mjs","sources":["../../../projects/photo-editor/src/lib/filter-preset.ts","../../../projects/photo-editor/src/lib/service/helper.service.ts","../../../projects/photo-editor/src/lib/ion-components.ts","../../../projects/photo-editor/src/lib/dictionaries.ts","../../../projects/photo-editor/src/lib/pages/photo-editor.page.ts","../../../projects/photo-editor/src/lib/pages/photo-editor.page.html","../../../projects/photo-editor/src/lib/pages/photo-viewer.page.ts","../../../projects/photo-editor/src/lib/pages/photo-viewer.page.html","../../../projects/photo-editor/src/lib/photoEditorErrors.ts","../../../projects/photo-editor/src/lib/service/photo-file.service.ts","../../../projects/photo-editor/src/public-api.ts","../../../projects/photo-editor/src/rdlabo-ionic-angular-photo-editor.ts"],"sourcesContent":["import { IDictionaryForEditor, IFilterPreset } from './types';\n\nexport const filterPreset = (dictionary: IDictionaryForEditor): IFilterPreset[] => [\n {\n name: dictionary.original,\n type: 'Default',\n option: null,\n },\n // {\n // name: dictionary.invert,\n // type: 'Invert',\n // option: null,\n // },\n {\n name: dictionary.sepia,\n type: 'Sepia',\n option: null,\n },\n {\n name: dictionary.vintage,\n type: 'vintage',\n option: null,\n },\n {\n name: 'ぼかし',\n type: 'Blur',\n option: { blur: 0.1 },\n },\n {\n name: dictionary.grayscale,\n type: 'Grayscale',\n option: null,\n },\n // {\n // name: dictionary.sharpen,\n // type: 'Sharpen',\n // option: null,\n // },\n // {\n // name: dictionary.emboss,\n // type: 'Emboss',\n // option: null,\n // },\n];\n","import { Injectable } from '@angular/core';\nimport { addIcons } from 'ionicons';\nimport {\n checkmarkOutline,\n closeOutline,\n colorFilterOutline,\n cropOutline,\n expandOutline,\n refreshOutline,\n removeOutline,\n send,\n squareOutline,\n sunnyOutline,\n tabletLandscapeOutline,\n} from 'ionicons/icons';\n\n@Injectable()\nexport class HelperService {\n constructor() {}\n\n initializeViewerIcons(): void {\n addIcons({\n closeOutline,\n removeOutline,\n });\n }\n\n initializeEditorIcons(): void {\n addIcons({\n closeOutline,\n send,\n cropOutline,\n colorFilterOutline,\n sunnyOutline,\n expandOutline,\n tabletLandscapeOutline,\n squareOutline,\n refreshOutline,\n checkmarkOutline,\n });\n }\n\n waitToFindDom(nativeElement: HTMLElement, selector: string): Promise<void> {\n return new Promise<void>((resolve) => {\n const interval = setInterval(() => {\n const find = nativeElement.querySelector(selector);\n if (find) {\n clearInterval(interval);\n resolve();\n }\n });\n });\n }\n}\n","import { IonButton, IonButtons, IonContent, IonFooter, IonHeader, IonIcon, IonRange, IonText, IonToolbar } from '@ionic/angular/standalone';\n\nexport const ionComponents = [IonHeader, IonToolbar, IonButtons, IonButton, IonIcon, IonContent, IonFooter, IonText, IonRange];\n","import { IDictionaryForEditor, IDictionaryForService, IDictionaryForViewer } from './types';\n\nexport const dictionaryForEditor = (): IDictionaryForEditor => ({\n // UI labels\n save: '保存',\n crop: '切り抜き・回転',\n filter: 'フィルター',\n brightness: '明るさ',\n\n // Filter labels\n original: 'オリジナル',\n invert: '反転',\n sepia: 'セピア',\n vintage: 'ヴィンテージ',\n blur: 'ぼかし',\n grayscale: 'グレースケール',\n sharpen: '輪郭',\n emboss: 'エンボス',\n});\n\nexport const dictionaryForViewer = (): IDictionaryForViewer => ({\n // UI labels\n delete: '削除',\n});\n\nexport const dictionaryForService = (): IDictionaryForService => ({\n // UI labels\n camera: 'カメラ撮影',\n album: 'アルバムから選択',\n cancel: 'キャンセル',\n});\n","import { Component, ElementRef, inject, Input, OnDestroy, OnInit, signal, ViewChild } from '@angular/core';\nimport { CommonModule, NgOptimizedImage } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { IonContent, ModalController, RangeCustomEvent, ViewDidEnter, ViewDidLeave } from '@ionic/angular/standalone';\nimport ImageEditor from 'tui-image-editor';\nimport { filterPreset } from '../filter-preset';\nimport { Subscription } from 'rxjs';\nimport { toObservable } from '@angular/core/rxjs-interop';\nimport { IDictionaryForEditor, IFilter, IPhotoEditorDismiss, ISize } from '../types';\nimport { HelperService } from '../service/helper.service';\nimport { ionComponents } from '../ion-components';\nimport { dictionaryForEditor } from '../dictionaries';\n\n@Component({\n selector: 'app-editor-image',\n templateUrl: './photo-editor.page.html',\n styleUrls: ['./core.scss', './photo-editor.page.scss'],\n imports: [CommonModule, FormsModule, NgOptimizedImage, ...ionComponents],\n providers: [HelperService],\n})\nexport class PhotoEditorPage implements OnInit, OnDestroy, ViewDidEnter, ViewDidLeave {\n protected dictionary: IDictionaryForEditor = dictionaryForEditor();\n protected filterPreset = filterPreset(this.dictionary);\n\n @Input() requireSquare: boolean = false;\n @Input() value!: string;\n @Input() set labels(d: IDictionaryForEditor) {\n this.dictionary = Object.assign(this.dictionary, d);\n this.filterPreset = filterPreset(this.dictionary);\n }\n\n @ViewChild('imageEditor', { static: true }) editorRef!: ElementRef;\n @ViewChild(IonContent) ionContent!: {\n el: IonContent & HTMLElement;\n };\n\n $filters = signal<IFilter[]>([]);\n $footerMenu = signal<'filter' | 'menu' | 'crop' | 'brightness'>('menu');\n $currentCrop = signal<'cover' | '16/9' | '1' | 'auto'>('cover');\n $currentRotate = signal<number>(0);\n $photoCrop = signal<ISize>({\n width: 0,\n height: 0,\n });\n $isCropped = signal<boolean>(false);\n\n private footerMenu$ = toObservable(this.$footerMenu);\n private $adoptFilter = signal<IFilter | undefined>(undefined);\n private editorInstance!: ImageEditor;\n private initSubscription$: Subscription[] = [];\n private readonly filterImageSize = 240;\n private readonly service = inject(HelperService);\n\n modalCtrl = inject(ModalController);\n\n private canvasContainerObserver: MutationObserver = new MutationObserver((mutationsList: MutationRecord[]) => {\n if (mutationsList.find((mutation) => mutation.type === 'attributes' && mutation.attributeName === 'style')) {\n // Cover the image editor with the parent element\n this.editorRef.nativeElement.style.minWidth = mutationsList[0].target.parentElement!.style.maxWidth;\n this.editorRef.nativeElement.style.minHeight = mutationsList[0].target.parentElement!.style.maxHeight;\n\n this.$photoCrop.set({\n width: mutationsList[0].target.parentElement!.querySelector('canvas')!.width,\n height: mutationsList[0].target.parentElement!.querySelector('canvas')!.height,\n });\n }\n });\n\n constructor() {\n this.service.initializeEditorIcons();\n }\n\n ngOnInit() {\n this.initSubscription$.push(\n this.footerMenu$.subscribe((value) => {\n if (value === 'filter') {\n this.initializeFilterMenu().then();\n }\n if (value === 'crop') {\n this.editorInstance.startDrawingMode('CROPPER');\n this.changeCrop(this.requireSquare ? '1' : 'cover');\n }\n }),\n );\n }\n\n ngOnDestroy() {\n this.initSubscription$.forEach((subscription) => subscription.unsubscribe());\n }\n\n async ionViewDidEnter() {\n this.editorInstance = new ImageEditor(this.editorRef.nativeElement, {\n cssMaxWidth: this.ionContent.el.clientWidth - 32,\n cssMaxHeight: this.ionContent.el.clientHeight - 32,\n });\n this.service.waitToFindDom(this.editorRef.nativeElement, '.tui-image-editor-canvas-container').then(() => {\n this.canvasContainerObserver.observe(this.editorRef.nativeElement.querySelector('.tui-image-editor-canvas-container'), {\n attributes: true,\n childList: false,\n subtree: true,\n });\n });\n const blob = await fetch(this.value).then((res) => res.blob());\n await this.editorInstance.loadImageFromFile(new File([blob], 'data.png', { type: blob.type }));\n this.$footerMenu.set(this.requireSquare ? 'crop' : 'menu');\n }\n\n ionViewDidLeave() {\n this.editorInstance.destroy();\n this.canvasContainerObserver.disconnect();\n }\n\n changeCrop(crop: 'cover' | '16/9' | '1' | 'auto') {\n const rect = crop === 'cover' ? this.$photoCrop().width / this.$photoCrop().height : crop === '16/9' ? 16 / 9 : 1;\n this.editorInstance.setCropzoneRect(crop !== 'auto' ? rect : undefined);\n this.$currentCrop.set(crop);\n }\n\n async rotate() {\n this.editorInstance.stopDrawingMode();\n await this.editorInstance.rotate(90);\n this.$currentRotate.update((value) => value + 90);\n this.editorInstance.startDrawingMode('CROPPER');\n requestAnimationFrame(() => this.changeCrop(this.$currentCrop()));\n }\n\n async closeCrop(type: 'cancel' | 'apply') {\n if (this.$footerMenu() === 'crop') {\n if (type === 'cancel') {\n await this.editorInstance.rotate(this.$currentRotate() * -1);\n } else {\n await this.editorInstance.crop(this.editorInstance.getCropzoneRect());\n this.$isCropped.set(true);\n }\n this.$currentRotate.set(0);\n this.$currentCrop.set('cover');\n this.editorInstance.stopDrawingMode();\n } else if (this.$footerMenu() === 'brightness') {\n if (type === 'cancel' && this.editorInstance.hasFilter('brightness')) {\n await this.editorInstance.removeFilter('brightness');\n }\n }\n this.$footerMenu.set('menu');\n }\n\n async changeRange(event: RangeCustomEvent) {\n if (this.editorInstance.hasFilter('brightness')) {\n await this.editorInstance.removeFilter('brightness');\n }\n this.editorInstance.applyFilter('brightness', {\n brightness: Number(event.detail.value) / 255,\n });\n }\n\n imageSave() {\n const value = this.editorInstance.toDataURL();\n this.modalCtrl.dismiss({ value } as IPhotoEditorDismiss);\n }\n\n private async initializeFilterMenu() {\n const filters: IFilter[] = [];\n\n const defaultInstance = new ImageEditor(document.createElement('div'), {\n cssMaxWidth: this.filterImageSize,\n cssMaxHeight: (this.$photoCrop().height * this.filterImageSize) / this.$photoCrop().width,\n });\n const blob = await fetch(\n this.editorInstance.toDataURL({\n multiplier: this.filterImageSize / this.$photoCrop().width,\n }),\n ).then((res) => res.blob());\n await defaultInstance.loadImageFromFile(new File([blob], 'defaultInstance.png', { type: blob.type }));\n\n for (const filter of this.filterPreset) {\n if (filter.type !== 'Default') {\n await defaultInstance.applyFilter(filter.type, filter.option);\n }\n filters.push({\n name: filter.name,\n type: filter.type,\n option: filter.option,\n data: defaultInstance.toDataURL(),\n width: this.filterImageSize,\n height: (this.$photoCrop().height * this.filterImageSize) / this.$photoCrop().width,\n });\n if (filter.type !== 'Default') {\n await defaultInstance.removeFilter(filter.type);\n }\n }\n this.$filters.set(filters);\n defaultInstance.destroy();\n }\n\n async filterImage(filter: IFilter) {\n if (this.$adoptFilter()) {\n await this.editorInstance.removeFilter(this.$adoptFilter()!.type);\n }\n if (filter.type === 'Default') {\n this.$adoptFilter.set(undefined);\n return;\n }\n await this.editorInstance.applyFilter(filter.type, filter.option);\n this.$adoptFilter.set(filter);\n }\n}\n","<ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"start\"\n ><ion-button (click)=\"modalCtrl.dismiss()\"><ion-icon name=\"close-outline\" slot=\"icon-only\"></ion-icon></ion-button\n ></ion-buttons>\n <ion-buttons slot=\"end\">\n <ion-button\n color=\"photo-editor-primary\"\n fill=\"outline\"\n [disabled]=\"!['menu', 'filter'].includes($footerMenu())\"\n (click)=\"imageSave()\"\n >\n {{ dictionary.save }}\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\" [scrollY]=\"false\">\n <div #imageEditor></div>\n</ion-content>\n<ion-footer>\n <ion-toolbar>\n @if (this.$footerMenu() === 'menu') {\n <aside class=\"ion-justify-content-center\">\n <button (click)=\"$footerMenu.set('crop')\">\n <ion-text>{{ dictionary.crop }}</ion-text>\n <ion-icon name=\"crop-outline\" size=\"large\"></ion-icon>\n </button>\n <button (click)=\"$footerMenu.set('filter')\">\n <ion-text>{{ dictionary.filter }}</ion-text>\n <ion-icon name=\"color-filter-outline\" size=\"large\"></ion-icon>\n </button>\n <button (click)=\"$footerMenu.set('brightness')\">\n <ion-text>{{ dictionary.brightness }}</ion-text>\n <ion-icon name=\"sunny-outline\" size=\"large\"></ion-icon>\n </button>\n </aside>\n }\n\n @if (this.$footerMenu() === 'filter') {\n <aside>\n @for (item of $filters(); track item) {\n <button (click)=\"filterImage(item)\">\n <ion-text>{{ item.name }}</ion-text>\n <span class=\"image-filter-box\" [style.background-image]=\"'url(' + item.data + ')'\"></span>\n </button>\n }\n </aside>\n }\n\n @if (this.$footerMenu() === 'crop' && !requireSquare) {\n <ion-buttons class=\"ion-justify-content-center submenu-icon-buttons\">\n <ion-button (click)=\"changeCrop('cover')\" [color]=\"$currentCrop() === 'cover' ? 'success' : undefined\">\n <ion-icon name=\"expand-outline\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n <ion-button (click)=\"changeCrop('16/9')\" [color]=\"$currentCrop() === '16/9' ? 'success' : undefined\">\n <ion-icon name=\"tablet-landscape-outline\" slot=\"icon-only\" style=\"transform: scale(1, 0.8)\"></ion-icon>\n </ion-button>\n <ion-button (click)=\"changeCrop('1')\" [color]=\"$currentCrop() === '1' ? 'success' : undefined\">\n <ion-icon name=\"square-outline\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n <ion-button (click)=\"changeCrop('auto')\" [color]=\"$currentCrop() === 'auto' ? 'success' : undefined\">\n <ion-icon name=\"crop-outline\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n <ion-button (click)=\"rotate()\"><ion-icon name=\"refresh-outline\" slot=\"icon-only\"></ion-icon></ion-button>\n </ion-buttons>\n }\n\n @if (['brightness'].includes(this.$footerMenu())) {\n <div class=\"ion-padding ion-margin\">\n <ion-range [pin]=\"true\" [min]=\"-100\" [max]=\"100\" (ionChange)=\"changeRange($any($event))\"></ion-range>\n </div>\n }\n </ion-toolbar>\n @if (this.$footerMenu() !== 'menu') {\n <ion-toolbar mode=\"md\">\n @if (this.$footerMenu() === 'filter') {\n <ion-buttons class=\"ion-justify-content-center\" style=\"margin: 0 8px\">\n <ion-button fill=\"outline\" shape=\"round\" (click)=\"this.$footerMenu.set('menu')\">戻る</ion-button>\n </ion-buttons>\n } @else {\n <ion-buttons slot=\"start\" style=\"min-width: 60px\">\n @if (!requireSquare || $isCropped()) {\n <ion-button (click)=\"closeCrop('cancel')\"><ion-icon name=\"close-outline\" slot=\"icon-only\"></ion-icon></ion-button>\n }</ion-buttons\n ><ion-text class=\"footer-title\">\n @if ($footerMenu() === 'crop') {\n {{ dictionary.crop }}\n } @else if ($footerMenu() === 'brightness') {\n {{ dictionary.brightness }}\n }</ion-text\n ><ion-buttons slot=\"end\"\n ><ion-button (click)=\"closeCrop('apply')\"\n ><ion-icon name=\"checkmark-outline\" color=\"photo-editor-success\" slot=\"icon-only\"></ion-icon></ion-button\n ></ion-buttons>\n }\n </ion-toolbar>\n }\n</ion-footer>\n","import { Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, inject, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';\nimport { IonicSlides, ModalController } from '@ionic/angular/standalone';\nimport { Navigation, Zoom } from 'swiper/modules';\nimport { fromEvent, Subscription, throttleTime, withLatestFrom, zipWith } from 'rxjs';\nimport { NgFor, NgIf } from '@angular/common';\nimport { SwiperContainer } from 'swiper/element';\nimport { ionComponents } from '../ion-components';\nimport { HelperService } from '../service/helper.service';\nimport { IDictionaryForViewer, IPhotoViewerDismiss } from '../types';\nimport { register } from 'swiper/element/bundle';\nimport { dictionaryForViewer } from '../dictionaries';\n\n@Component({\n selector: 'app-photo-image',\n templateUrl: './photo-viewer.page.html',\n styleUrls: ['./core.scss', './photo-viewer.page.scss'],\n imports: [NgFor, NgIf, ...ionComponents],\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\n providers: [HelperService],\n})\nexport class PhotoViewerPage implements OnInit, OnDestroy {\n protected dictionary: IDictionaryForViewer = dictionaryForViewer();\n\n @Input() imageUrls: string[] = [];\n @Input() index: number = 0;\n @Input() isCircle = false;\n @Input() enableDelete = false;\n @Input() enableFooterSafeArea = false;\n @Input() set labels(d: IDictionaryForViewer) {\n this.dictionary = Object.assign(this.dictionary, d);\n }\n\n @ViewChild('swiper') swiper!: ElementRef<SwiperContainer>;\n\n watchSwipe$!: Subscription;\n readonly modalCtrl = inject(ModalController);\n private readonly el = inject(ElementRef);\n private readonly service = inject(HelperService);\n\n constructor() {\n register();\n this.service.initializeViewerIcons();\n }\n\n async ngOnInit() {\n this.service.waitToFindDom(this.el.nativeElement, 'swiper-container').then(() => {\n Object.assign(this.swiper.nativeElement, {\n modules: [Navigation, Zoom, IonicSlides],\n initialSlide: this.index,\n slidesPerView: 1,\n pagination: {\n enabled: true,\n clickable: true,\n },\n zoom: true,\n });\n this.swiper.nativeElement.initialize();\n this.swiper.nativeElement.swiper.zoom.enable();\n\n this.swiper.nativeElement.swiper.activeIndex = this.index;\n this.swiper.nativeElement.swiper.update();\n });\n\n this.watchSwipe$ = fromEvent<TouchEvent>(this.el.nativeElement, 'touchstart')\n .pipe(\n zipWith(\n fromEvent<TouchEvent>(this.el.nativeElement, 'touchend').pipe(\n withLatestFrom(fromEvent<TouchEvent>(this.el.nativeElement, 'touchmove')),\n ),\n ),\n throttleTime(1),\n )\n .subscribe(([touchstart, [_, touchmove]]) => {\n const touchstartClientX = touchstart.touches ? touchstart.touches[0].clientX : (touchstart as any).detail[1].clientX;\n const touchmoveClientX = touchmove.touches ? touchmove.touches[0].clientX : (touchmove as any).detail[1].clientX;\n\n const touchstartClientY = touchstart.touches ? touchstart.touches[0].clientY : (touchstart as any).detail[1].clientY;\n const touchmoveClientY = touchmove.touches ? touchmove.touches[0].clientY : (touchmove as any).detail[1].clientY;\n\n const xDiff = touchstartClientX - touchmoveClientX;\n const yDiff = touchstartClientY - touchmoveClientY;\n\n const slides = (this.swiper as any).nativeElement.querySelectorAll('swiper-slide') as HTMLElement[];\n const isZoomed = Array.from(slides).find((slide: HTMLElement) => {\n return ['swiper-slide-zoomed', 'swiper-slide-active'].every((c) => slide.classList.contains(c));\n });\n\n const threshold = touchmove.touches ? -50 : -5;\n\n if (!isZoomed && Math.abs(xDiff) < Math.abs(threshold) && yDiff < threshold && touchstart.timeStamp <= touchmove.timeStamp) {\n this.watchSwipe$.unsubscribe();\n this.modalCtrl.dismiss();\n }\n });\n }\n\n ngOnDestroy() {\n if (this.watchSwipe$ && !this.watchSwipe$.closed) {\n this.watchSwipe$.unsubscribe();\n }\n }\n\n remove() {\n this.modalCtrl.dismiss({\n delete: {\n index: this.swiper.nativeElement.swiper.activeIndex,\n value: this.imageUrls[this.swiper.nativeElement.swiper.activeIndex],\n },\n } as IPhotoViewerDismiss);\n }\n}\n","<ion-header [translucent]=\"true\">\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-button (click)=\"modalCtrl.dismiss()\" class=\"viewer-close-button\">\n <ion-icon name=\"close-outline\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </ion-buttons>\n @if (enableDelete) {\n <ion-buttons slot=\"end\">\n <ion-button color=\"photo-editor-danger\" fill=\"outline\" (click)=\"remove()\">{{ dictionary.delete }}</ion-button>\n </ion-buttons>\n }\n </ion-toolbar>\n</ion-header>\n\n<ion-content [fullscreen]=\"true\">\n <swiper-container #swiper>\n @for (url of imageUrls; track url) {\n <swiper-slide>\n <div class=\"swiper-zoom-container\"><img [src]=\"url\" alt=\"\" [class.circle]=\"isCircle\" /></div>\n </swiper-slide>\n }\n </swiper-container>\n</ion-content>\n\n@if (enableFooterSafeArea) {\n <!-- use for safe area-->\n <ion-footer>\n <ion-toolbar style=\"--border-width: 0; --min-height: 0\"></ion-toolbar>\n </ion-footer>\n}\n","export enum PhotoEditorErrors {\n 'initialize' = 'input dom is not found',\n 'cancel' = 'user canceled',\n 'type' = 'upload file is not image.',\n}\n","import { inject, Injectable, signal } from '@angular/core';\nimport { ActionSheetController, Platform } from '@ionic/angular/standalone';\nimport { Camera, CameraResultType, CameraSource, ImageOptions } from '@capacitor/camera';\nimport ImageEditor from 'tui-image-editor';\nimport { PhotoEditorErrors } from '../photoEditorErrors';\nimport { dictionaryForService } from '../dictionaries';\nimport { IDictionaryForService } from '../types';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class PhotoFileService {\n private readonly $photoMaxSize = signal<number>(1000);\n private readonly actionSheetCtrl = inject(ActionSheetController);\n private readonly platform = inject(Platform);\n private dictionary: IDictionaryForService = dictionaryForService();\n\n constructor() {}\n\n set photoMaxSize(value: number) {\n this.$photoMaxSize.set(value);\n }\n\n set labels(d: IDictionaryForService) {\n this.dictionary = Object.assign(this.dictionary, d);\n }\n\n async loadPhoto(limit: number): Promise<string[]> {\n /**\n * Using Input for browser\n */\n if (!this.platform.is('capacitor')) {\n return this.getPictureFromBrowser();\n }\n\n const actionSheet = await this.actionSheetCtrl.create({\n buttons: [\n {\n text: this.dictionary.camera,\n handler: () => {\n actionSheet.dismiss('camera');\n },\n },\n {\n text: this.dictionary.album,\n handler: () => {\n actionSheet.dismiss('album');\n },\n },\n {\n text: this.dictionary.cancel,\n role: 'cancel',\n },\n ],\n });\n await actionSheet.present();\n const { data } = await actionSheet.onDidDismiss<'camera' | 'album'>();\n if (!data) {\n return Promise.reject(PhotoEditorErrors.cancel);\n }\n\n if (data === 'camera') {\n const defaultCamera: ImageOptions = {\n quality: 100,\n width: this.$photoMaxSize(),\n allowEditing: false,\n resultType: CameraResultType.DataUrl,\n source: CameraSource.Camera,\n presentationStyle: 'popover',\n };\n const image = await Camera.getPhoto(defaultCamera).catch(() => undefined);\n if (!image?.dataUrl) {\n return Promise.reject(PhotoEditorErrors.cancel);\n }\n\n if (!image.dataUrl.includes('capacitor://localhost')) {\n return [image.dataUrl];\n }\n return Promise.all([image.dataUrl].map(async (image) => await this.loadPhotoFromFilePath(image)));\n }\n\n if (data === 'album') {\n const images = await Camera.pickImages({\n quality: 100,\n width: this.$photoMaxSize(),\n limit,\n presentationStyle: 'popover',\n }).catch(() => undefined);\n\n if (!images) {\n return Promise.reject(PhotoEditorErrors.cancel);\n }\n\n return Promise.all(images.photos.map(async (image) => await this.loadPhotoFromFilePath(image.webPath)));\n }\n\n // Not run on this line. This is for lint\n return [];\n }\n\n private getPictureFromBrowser(): Promise<string[]> {\n const inputFile: HTMLInputElement | null = document.querySelector('input#browserPhotoUploader');\n\n if (!inputFile) {\n return Promise.reject(PhotoEditorErrors.initialize);\n }\n\n return new Promise((resolve, reject) => {\n const cancelMethod = (e: Event) => {\n inputFile!.removeEventListener('cancel', cancelMethod, false);\n inputFile!.removeEventListener('change', changeMethod, false);\n\n reject(PhotoEditorErrors.cancel);\n };\n const changeMethod = (e: Event) => {\n inputFile!.removeEventListener('cancel', cancelMethod, false);\n inputFile!.removeEventListener('change', changeMethod, false);\n\n if (!(e.target as HTMLInputElement).files || !(e.target as HTMLInputElement).files![0]) {\n reject(PhotoEditorErrors.cancel);\n }\n const file = (e.target as HTMLInputElement).files![0];\n const reader = new FileReader();\n\n reader.onload = (() => {\n if (file.type.indexOf('image') < 0) {\n reject(PhotoEditorErrors.type);\n }\n\n return async (event) => {\n inputFile.value = '';\n const result = event.target!.result as string;\n const data = await this.loadPhotoFromFilePath(result);\n resolve([data]);\n };\n })();\n\n reader.readAsDataURL(file);\n };\n\n inputFile!.addEventListener('cancel', cancelMethod, false);\n inputFile!.addEventListener('change', changeMethod, false);\n inputFile.click();\n });\n }\n\n private async loadPhotoFromFilePath(filePath: string): Promise<string> {\n const defaultInstance = new ImageEditor(document.createElement('div'), {\n cssMaxWidth: this.$photoMaxSize(),\n cssMaxHeight: this.$photoMaxSize(),\n });\n const blob = await fetch(filePath).then((res) => res.blob());\n const loaded = await defaultInstance.loadImageFromFile(new File([blob], 'data.png', { type: blob.type }));\n\n const maxSize = Math.max(loaded.newWidth, loaded.newHeight);\n const dataUrl = defaultInstance.toDataURL({\n multiplier: this.$photoMaxSize() / maxSize,\n });\n defaultInstance.destroy();\n\n return dataUrl;\n }\n}\n","/*\n * Public API Surface of photo-editor\n */\n\nexport * from './lib/pages/photo-editor.page';\nexport * from './lib/pages/photo-viewer.page';\nexport * from './lib/service/photo-file.service';\nexport * from './lib/types';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rdlabo-ionic-angular-photo-editor.mjs","sources":["../../../projects/photo-editor/src/lib/filter-preset.ts","../../../projects/photo-editor/src/lib/ion-components.ts","../../../projects/photo-editor/src/lib/dictionaries.ts","../../../projects/photo-editor/src/lib/pages/util.ts","../../../projects/photo-editor/src/lib/pages/photo-editor/photo-editor.page.ts","../../../projects/photo-editor/src/lib/pages/photo-editor/photo-editor.page.html","../../../projects/photo-editor/src/lib/pages/photo-viewer/photo-viewer.page.ts","../../../projects/photo-editor/src/lib/pages/photo-viewer/photo-viewer.page.html","../../../projects/photo-editor/src/lib/photoEditorErrors.ts","../../../projects/photo-editor/src/lib/services/photo-file.service.ts","../../../projects/photo-editor/src/public-api.ts","../../../projects/photo-editor/src/rdlabo-ionic-angular-photo-editor.ts"],"sourcesContent":["import { IDictionaryForEditor, IFilterPreset } from './types';\n\nexport const filterPreset = (dictionary: IDictionaryForEditor): IFilterPreset[] => [\n {\n name: dictionary.original,\n type: 'Default',\n option: null,\n },\n // {\n // name: dictionary.invert,\n // type: 'Invert',\n // option: null,\n // },\n {\n name: dictionary.sepia,\n type: 'Sepia',\n option: null,\n },\n {\n name: dictionary.vintage,\n type: 'vintage',\n option: null,\n },\n {\n name: 'ぼかし',\n type: 'Blur',\n option: { blur: 0.1 },\n },\n {\n name: dictionary.grayscale,\n type: 'Grayscale',\n option: null,\n },\n // {\n // name: dictionary.sharpen,\n // type: 'Sharpen',\n // option: null,\n // },\n // {\n // name: dictionary.emboss,\n // type: 'Emboss',\n // option: null,\n // },\n];\n","import { IonButton, IonButtons, IonContent, IonFooter, IonHeader, IonIcon, IonRange, IonText, IonToolbar } from '@ionic/angular/standalone';\n\nexport const ionComponents = [IonHeader, IonToolbar, IonButtons, IonButton, IonIcon, IonContent, IonFooter, IonText, IonRange];\n","import { IDictionaryForEditor, IDictionaryForService, IDictionaryForViewer } from './types';\n\nexport const dictionaryForEditor = (): IDictionaryForEditor => ({\n // UI labels\n save: '保存',\n crop: '切り抜き・回転',\n filter: 'フィルター',\n brightness: '明るさ',\n\n // Filter labels\n original: 'オリジナル',\n invert: '反転',\n sepia: 'セピア',\n vintage: 'ヴィンテージ',\n blur: 'ぼかし',\n grayscale: 'グレースケール',\n sharpen: '輪郭',\n emboss: 'エンボス',\n});\n\nexport const dictionaryForViewer = (): IDictionaryForViewer => ({\n // UI labels\n delete: '削除',\n});\n\nexport const dictionaryForService = (): IDictionaryForService => ({\n // UI labels\n camera: 'カメラ撮影',\n album: 'アルバムから選択',\n cancel: 'キャンセル',\n});\n","import { addIcons } from 'ionicons';\nimport {\n checkmarkOutline,\n closeOutline,\n colorFilterOutline,\n cropOutline,\n expandOutline,\n refreshOutline,\n removeOutline,\n send,\n squareOutline,\n sunnyOutline,\n tabletLandscapeOutline,\n} from 'ionicons/icons';\n\nexport const initializeViewerIcons = (): void => {\n addIcons({\n closeOutline,\n removeOutline,\n });\n};\n\nexport const initializeEditorIcons = (): void => {\n addIcons({\n closeOutline,\n send,\n cropOutline,\n colorFilterOutline,\n sunnyOutline,\n expandOutline,\n tabletLandscapeOutline,\n squareOutline,\n refreshOutline,\n checkmarkOutline,\n });\n};\n\nexport const waitToFindDom = (nativeElement: HTMLElement, selector: string): Promise<void> => {\n return new Promise<void>((resolve) => {\n const interval = setInterval(() => {\n const find = nativeElement.querySelector(selector);\n if (find) {\n clearInterval(interval);\n resolve();\n }\n });\n });\n};\n","import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n effect,\n ElementRef,\n inject,\n input,\n OnDestroy,\n OnInit,\n signal,\n viewChild,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { IonContent, ModalController, RangeCustomEvent, ViewDidEnter, ViewDidLeave } from '@ionic/angular/standalone';\nimport ImageEditor from 'tui-image-editor';\nimport { filterPreset } from '../../filter-preset';\nimport { Subscription } from 'rxjs';\nimport { toObservable } from '@angular/core/rxjs-interop';\nimport { IDictionaryForEditor, IFilter, IPhotoEditorDismiss, ISize } from '../../types';\nimport { ionComponents } from '../../ion-components';\nimport { dictionaryForEditor } from '../../dictionaries';\nimport { initializeEditorIcons, waitToFindDom } from '../util';\n\n@Component({\n selector: 'app-editor-image',\n templateUrl: './photo-editor.page.html',\n styleUrls: ['../core.scss', './photo-editor.page.scss'],\n imports: [CommonModule, FormsModule, ...ionComponents],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class PhotoEditorPage implements OnInit, OnDestroy, ViewDidEnter, ViewDidLeave {\n readonly modalCtrl = inject(ModalController);\n\n protected readonly dictionary = signal<IDictionaryForEditor>(dictionaryForEditor());\n\n readonly requireSquare = input<boolean, BooleanInput>(false, {\n transform: coerceBooleanProperty,\n });\n readonly labels = input<Partial<IDictionaryForEditor> | undefined>(undefined);\n readonly setLabels = effect(() => {\n if (this.labels()) {\n this.dictionary.update((value) => ({ ...value, ...this.labels() }));\n }\n });\n readonly value = input.required<string>();\n\n readonly editorRef = viewChild.required<ElementRef>('imageEditor');\n readonly ionContent = viewChild.required(IonContent, { read: ElementRef });\n\n readonly filters = signal<IFilter[]>([]);\n readonly footerMenu = signal<'filter' | 'menu' | 'crop' | 'brightness'>('menu');\n readonly currentCrop = signal<'cover' | '16/9' | '1' | 'auto'>('cover');\n readonly currentRotate = signal<number>(0);\n readonly photoCrop = signal<ISize>({\n width: 0,\n height: 0,\n });\n readonly isCropped = signal<boolean>(false);\n private readonly adoptFilter = signal<IFilter | undefined>(undefined);\n protected readonly filterPreset = computed(() => filterPreset(this.dictionary()));\n\n private readonly footerMenu$ = toObservable(this.footerMenu);\n\n private readonly initSubscription$: Subscription[] = [];\n private readonly filterImageSize = 240;\n private editorInstance!: ImageEditor;\n\n private canvasContainerObserver: MutationObserver = new MutationObserver((mutationsList: MutationRecord[]) => {\n if (mutationsList.find((mutation) => mutation.type === 'attributes' && mutation.attributeName === 'style')) {\n // Cover the image editor with the parent element\n const editorRef = this.editorRef();\n editorRef.nativeElement.style.minWidth = mutationsList[0].target.parentElement!.style.maxWidth;\n editorRef.nativeElement.style.minHeight = mutationsList[0].target.parentElement!.style.maxHeight;\n\n this.photoCrop.set({\n width: mutationsList[0].target.parentElement!.querySelector('canvas')!.width,\n height: mutationsList[0].target.parentElement!.querySelector('canvas')!.height,\n });\n }\n });\n\n constructor() {\n initializeEditorIcons();\n }\n\n ngOnInit() {\n this.initSubscription$.push(\n this.footerMenu$.subscribe((value) => {\n if (value === 'filter') {\n this.initializeFilterMenu().then();\n }\n if (value === 'crop') {\n this.editorInstance.startDrawingMode('CROPPER');\n this.changeCrop(this.requireSquare() ? '1' : 'cover');\n }\n }),\n );\n }\n\n ngOnDestroy() {\n this.initSubscription$.forEach((subscription) => subscription.unsubscribe());\n }\n\n async ionViewDidEnter() {\n this.editorInstance = new ImageEditor(this.editorRef().nativeElement, {\n cssMaxWidth: this.ionContent().nativeElement.clientWidth - 32,\n cssMaxHeight: this.ionContent().nativeElement.clientHeight - 32,\n });\n waitToFindDom(this.editorRef().nativeElement, '.tui-image-editor-canvas-container').then(() => {\n this.canvasContainerObserver.observe(this.editorRef().nativeElement.querySelector('.tui-image-editor-canvas-container'), {\n attributes: true,\n childList: false,\n subtree: true,\n });\n });\n const blob = await fetch(this.value()).then((res) => res.blob());\n await this.editorInstance.loadImageFromFile(new File([blob], 'data.png', { type: blob.type }));\n this.footerMenu.set(this.requireSquare() ? 'crop' : 'menu');\n }\n\n ionViewDidLeave() {\n this.editorInstance.destroy();\n this.canvasContainerObserver.disconnect();\n }\n\n changeCrop(crop: 'cover' | '16/9' | '1' | 'auto') {\n const rect = crop === 'cover' ? this.photoCrop().width / this.photoCrop().height : crop === '16/9' ? 16 / 9 : 1;\n this.editorInstance.setCropzoneRect(crop !== 'auto' ? rect : undefined);\n this.currentCrop.set(crop);\n }\n\n async rotate() {\n this.editorInstance.stopDrawingMode();\n await this.editorInstance.rotate(90);\n this.currentRotate.update((value) => value + 90);\n this.editorInstance.startDrawingMode('CROPPER');\n requestAnimationFrame(() => this.changeCrop(this.currentCrop()));\n }\n\n async closeCrop(type: 'cancel' | 'apply') {\n if (this.footerMenu() === 'crop') {\n if (type === 'cancel') {\n await this.editorInstance.rotate(this.currentRotate() * -1);\n } else {\n await this.editorInstance.crop(this.editorInstance.getCropzoneRect());\n this.isCropped.set(true);\n }\n this.currentRotate.set(0);\n this.currentCrop.set('cover');\n this.editorInstance.stopDrawingMode();\n } else if (this.footerMenu() === 'brightness') {\n if (type === 'cancel' && this.editorInstance.hasFilter('brightness')) {\n await this.editorInstance.removeFilter('brightness');\n }\n }\n this.footerMenu.set('menu');\n }\n\n async changeRange(event: RangeCustomEvent) {\n if (this.editorInstance.hasFilter('brightness')) {\n await this.editorInstance.removeFilter('brightness');\n }\n await this.editorInstance.applyFilter('brightness', {\n brightness: Number(event.detail.value) / 255,\n });\n }\n\n imageSave() {\n const value = this.editorInstance.toDataURL();\n this.modalCtrl.dismiss({ value } as IPhotoEditorDismiss);\n }\n\n private async initializeFilterMenu() {\n const filters: IFilter[] = [];\n\n const defaultInstance = new ImageEditor(document.createElement('div'), {\n cssMaxWidth: this.filterImageSize,\n cssMaxHeight: (this.photoCrop().height * this.filterImageSize) / this.photoCrop().width,\n });\n const blob = await fetch(\n this.editorInstance.toDataURL({\n multiplier: this.filterImageSize / this.photoCrop().width,\n }),\n ).then((res) => res.blob());\n await defaultInstance.loadImageFromFile(new File([blob], 'defaultInstance.png', { type: blob.type }));\n\n for (const filter of this.filterPreset()) {\n if (filter.type !== 'Default') {\n await defaultInstance.applyFilter(filter.type, filter.option);\n }\n filters.push({\n name: filter.name,\n type: filter.type,\n option: filter.option,\n data: defaultInstance.toDataURL(),\n width: this.filterImageSize,\n height: (this.photoCrop().height * this.filterImageSize) / this.photoCrop().width,\n });\n if (filter.type !== 'Default') {\n await defaultInstance.removeFilter(filter.type);\n }\n }\n this.filters.set(filters);\n defaultInstance.destroy();\n }\n\n async filterImage(filter: IFilter) {\n if (this.adoptFilter()) {\n await this.editorInstance.removeFilter(this.adoptFilter()!.type);\n }\n if (filter.type === 'Default') {\n this.adoptFilter.set(undefined);\n return;\n }\n await this.editorInstance.applyFilter(filter.type, filter.option);\n this.adoptFilter.set(filter);\n }\n}\n","<ion-header>\n <ion-toolbar>\n <ion-buttons slot=\"start\"\n ><ion-button (click)=\"modalCtrl.dismiss()\"><ion-icon name=\"close-outline\" slot=\"icon-only\"></ion-icon></ion-button\n ></ion-buttons>\n <ion-buttons slot=\"end\">\n <ion-button color=\"photo-editor-primary\" fill=\"outline\" [disabled]=\"!['menu', 'filter'].includes(footerMenu())\" (click)=\"imageSave()\">\n {{ dictionary().save }}\n </ion-button>\n </ion-buttons>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"ion-padding\" [scrollY]=\"false\">\n <div #imageEditor></div>\n</ion-content>\n<ion-footer>\n <ion-toolbar>\n @if (this.footerMenu() === 'menu') {\n <aside class=\"ion-justify-content-center\">\n <button (click)=\"footerMenu.set('crop')\">\n <ion-text>{{ dictionary().crop }}</ion-text>\n <ion-icon name=\"crop-outline\" size=\"large\"></ion-icon>\n </button>\n <button (click)=\"footerMenu.set('filter')\">\n <ion-text>{{ dictionary().filter }}</ion-text>\n <ion-icon name=\"color-filter-outline\" size=\"large\"></ion-icon>\n </button>\n <button (click)=\"footerMenu.set('brightness')\">\n <ion-text>{{ dictionary().brightness }}</ion-text>\n <ion-icon name=\"sunny-outline\" size=\"large\"></ion-icon>\n </button>\n </aside>\n }\n\n @if (this.footerMenu() === 'filter') {\n <aside>\n @for (item of filters(); track item) {\n <button (click)=\"filterImage(item)\">\n <ion-text>{{ item.name }}</ion-text>\n <span class=\"image-filter-box\" [style.background-image]=\"'url(' + item.data + ')'\"></span>\n </button>\n }\n </aside>\n }\n\n @if (this.footerMenu() === 'crop' && !requireSquare()) {\n <ion-buttons class=\"ion-justify-content-center submenu-icon-buttons\">\n <ion-button (click)=\"changeCrop('cover')\" [color]=\"currentCrop() === 'cover' ? 'success' : undefined\">\n <ion-icon name=\"expand-outline\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n <ion-button (click)=\"changeCrop('16/9')\" [color]=\"currentCrop() === '16/9' ? 'success' : undefined\">\n <ion-icon name=\"tablet-landscape-outline\" slot=\"icon-only\" style=\"transform: scale(1, 0.8)\"></ion-icon>\n </ion-button>\n <ion-button (click)=\"changeCrop('1')\" [color]=\"currentCrop() === '1' ? 'success' : undefined\">\n <ion-icon name=\"square-outline\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n <ion-button (click)=\"changeCrop('auto')\" [color]=\"currentCrop() === 'auto' ? 'success' : undefined\">\n <ion-icon name=\"crop-outline\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n <ion-button (click)=\"rotate()\"><ion-icon name=\"refresh-outline\" slot=\"icon-only\"></ion-icon></ion-button>\n </ion-buttons>\n }\n\n @if (['brightness'].includes(this.footerMenu())) {\n <div class=\"ion-padding ion-margin\">\n <ion-range [pin]=\"true\" [min]=\"-100\" [max]=\"100\" (ionChange)=\"changeRange($any($event))\"></ion-range>\n </div>\n }\n </ion-toolbar>\n @if (this.footerMenu() !== 'menu') {\n <ion-toolbar mode=\"md\">\n @if (this.footerMenu() === 'filter') {\n <ion-buttons class=\"ion-justify-content-center\" style=\"margin: 0 8px\">\n <ion-button fill=\"outline\" shape=\"round\" (click)=\"this.footerMenu.set('menu')\">戻る</ion-button>\n </ion-buttons>\n } @else {\n <ion-buttons slot=\"start\" style=\"min-width: 60px\">\n @if (!requireSquare() || isCropped()) {\n <ion-button (click)=\"closeCrop('cancel')\"><ion-icon name=\"close-outline\" slot=\"icon-only\"></ion-icon></ion-button>\n }</ion-buttons\n ><ion-text class=\"footer-title\">\n @if (footerMenu() === 'crop') {\n {{ dictionary().crop }}\n } @else if (footerMenu() === 'brightness') {\n {{ dictionary().brightness }}\n }</ion-text\n ><ion-buttons slot=\"end\"\n ><ion-button (click)=\"closeCrop('apply')\"\n ><ion-icon name=\"checkmark-outline\" color=\"photo-editor-success\" slot=\"icon-only\"></ion-icon></ion-button\n ></ion-buttons>\n }\n </ion-toolbar>\n }\n</ion-footer>\n","import {\n ChangeDetectionStrategy,\n Component,\n CUSTOM_ELEMENTS_SCHEMA,\n effect,\n ElementRef,\n inject,\n input,\n OnDestroy,\n OnInit,\n signal,\n viewChild,\n} from '@angular/core';\nimport { IonicSlides, ModalController } from '@ionic/angular/standalone';\nimport { Navigation, Zoom } from 'swiper/modules';\nimport { fromEvent, Subscription, throttleTime, withLatestFrom, zipWith } from 'rxjs';\nimport { SwiperContainer } from 'swiper/element';\nimport { ionComponents } from '../../ion-components';\nimport { IDictionaryForViewer, IPhotoViewerDismiss } from '../../types';\nimport { register } from 'swiper/element/bundle';\nimport { dictionaryForViewer } from '../../dictionaries';\nimport { BooleanInput, coerceBooleanProperty, coerceNumberProperty, NumberInput } from '@angular/cdk/coercion';\nimport { initializeViewerIcons, waitToFindDom } from '../util';\n\n@Component({\n selector: 'app-photo-image',\n templateUrl: './photo-viewer.page.html',\n styleUrls: ['../core.scss', './photo-viewer.page.scss'],\n imports: [...ionComponents],\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class PhotoViewerPage implements OnInit, OnDestroy {\n readonly imageUrls = input.required<string[]>();\n readonly index = input<number, NumberInput>(0, {\n transform: coerceNumberProperty,\n });\n readonly isCircle = input<boolean, BooleanInput>(false, {\n transform: coerceBooleanProperty,\n });\n readonly enableDelete = input<boolean, BooleanInput>(false, {\n transform: coerceBooleanProperty,\n });\n readonly enableFooterSafeArea = input<boolean, BooleanInput>(false, {\n transform: coerceBooleanProperty,\n });\n readonly labels = input<Partial<IDictionaryForViewer>>();\n readonly setLabels = effect(() => {\n if (this.labels()) {\n this.dictionary.update((value) => ({ ...value, ...this.labels() }));\n }\n });\n\n readonly swiper = viewChild.required<ElementRef<SwiperContainer>>('swiper');\n protected readonly dictionary = signal<IDictionaryForViewer>(dictionaryForViewer());\n\n readonly watchSwipe$ = new Subscription();\n readonly modalCtrl = inject(ModalController);\n private readonly el = inject(ElementRef);\n\n constructor() {\n register();\n initializeViewerIcons();\n }\n\n async ngOnInit() {\n waitToFindDom(this.el.nativeElement, 'swiper-container').then(() => {\n const index = this.index();\n const swiper = this.swiper();\n Object.assign(swiper.nativeElement, {\n modules: [Navigation, Zoom, IonicSlides],\n initialSlide: index,\n slidesPerView: 1,\n pagination: {\n enabled: true,\n clickable: true,\n },\n zoom: true,\n });\n swiper.nativeElement.initialize();\n swiper.nativeElement.swiper.zoom.enable();\n\n swiper.nativeElement.swiper.activeIndex = index;\n swiper.nativeElement.swiper.update();\n });\n\n this.watchSwipe$.add(\n fromEvent<TouchEvent>(this.el.nativeElement, 'touchstart')\n .pipe(\n zipWith(\n fromEvent<TouchEvent>(this.el.nativeElement, 'touchend').pipe(\n withLatestFrom(fromEvent<TouchEvent>(this.el.nativeElement, 'touchmove')),\n ),\n ),\n throttleTime(1),\n )\n .subscribe(([touchstart, [_, touchmove]]) => {\n const touchstartClientX = touchstart.touches ? touchstart.touches[0].clientX : (touchstart as any).detail[1].clientX;\n const touchmoveClientX = touchmove.touches ? touchmove.touches[0].clientX : (touchmove as any).detail[1].clientX;\n\n const touchstartClientY = touchstart.touches ? touchstart.touches[0].clientY : (touchstart as any).detail[1].clientY;\n const touchmoveClientY = touchmove.touches ? touchmove.touches[0].clientY : (touchmove as any).detail[1].clientY;\n\n const xDiff = touchstartClientX - touchmoveClientX;\n const yDiff = touchstartClientY - touchmoveClientY;\n\n const slides = (this.swiper() as any).nativeElement.querySelectorAll('swiper-slide') as HTMLElement[];\n const isZoomed = Array.from(slides).find((slide: HTMLElement) => {\n return ['swiper-slide-zoomed', 'swiper-slide-active'].every((c) => slide.classList.contains(c));\n });\n\n const threshold = touchmove.touches ? -50 : -5;\n\n if (!isZoomed && Math.abs(xDiff) < Math.abs(threshold) && yDiff < threshold && touchstart.timeStamp <= touchmove.timeStamp) {\n this.watchSwipe$.unsubscribe();\n this.modalCtrl.dismiss();\n }\n }),\n );\n }\n\n ngOnDestroy() {\n this.watchSwipe$.unsubscribe();\n }\n\n remove() {\n this.modalCtrl.dismiss({\n delete: {\n index: this.swiper().nativeElement.swiper.activeIndex,\n value: this.imageUrls()[this.swiper().nativeElement.swiper.activeIndex],\n },\n } as IPhotoViewerDismiss);\n }\n}\n","<ion-header [translucent]=\"true\">\n <ion-toolbar>\n <ion-buttons slot=\"start\">\n <ion-button (click)=\"modalCtrl.dismiss()\" class=\"viewer-close-button\">\n <ion-icon name=\"close-outline\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </ion-buttons>\n @if (enableDelete()) {\n <ion-buttons slot=\"end\">\n <ion-button color=\"photo-editor-danger\" fill=\"outline\" (click)=\"remove()\">{{ dictionary().delete }}</ion-button>\n </ion-buttons>\n }\n </ion-toolbar>\n</ion-header>\n\n<ion-content [fullscreen]=\"true\">\n <swiper-container #swiper>\n @for (url of imageUrls(); track url) {\n <swiper-slide>\n <div class=\"swiper-zoom-container\"><img [src]=\"url\" alt=\"\" [class.circle]=\"isCircle()\" /></div>\n </swiper-slide>\n }\n </swiper-container>\n</ion-content>\n\n@if (enableFooterSafeArea()) {\n <!-- use for safe area-->\n <ion-footer>\n <ion-toolbar style=\"--border-width: 0; --min-height: 0\"></ion-toolbar>\n </ion-footer>\n}\n","export enum PhotoEditorErrors {\n initialize = 'input dom is not found',\n cancel = 'user canceled',\n type = 'upload file is not image.',\n}\n","import { inject, Injectable, signal } from '@angular/core';\nimport { ActionSheetController, Platform } from '@ionic/angular/standalone';\nimport { Camera, CameraResultType, CameraSource, ImageOptions } from '@capacitor/camera';\nimport ImageEditor from 'tui-image-editor';\nimport { PhotoEditorErrors } from '../photoEditorErrors';\nimport { dictionaryForService } from '../dictionaries';\nimport { IDictionaryForService } from '../types';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class PhotoFileService {\n private readonly $photoMaxSize = signal<number>(1000);\n private readonly actionSheetCtrl = inject(ActionSheetController);\n private readonly platform = inject(Platform);\n private readonly dictionary = signal<IDictionaryForService>(dictionaryForService());\n\n set photoMaxSize(value: number) {\n this.$photoMaxSize.set(value);\n }\n\n set labels(d: IDictionaryForService) {\n this.dictionary.update((value) => ({ ...value, ...d }));\n }\n\n async loadPhoto(limit: number): Promise<string[]> {\n /**\n * Using Input for browser\n */\n if (!this.platform.is('capacitor')) {\n return this.getPictureFromBrowser();\n }\n\n const actionSheet = await this.actionSheetCtrl.create({\n buttons: [\n {\n text: this.dictionary().camera,\n handler: () => {\n actionSheet.dismiss('camera');\n },\n },\n {\n text: this.dictionary().album,\n handler: () => {\n actionSheet.dismiss('album');\n },\n },\n {\n text: this.dictionary().cancel,\n role: 'cancel',\n },\n ],\n });\n await actionSheet.present();\n const { data } = await actionSheet.onDidDismiss<'camera' | 'album'>();\n if (!data) {\n return Promise.reject(PhotoEditorErrors.cancel);\n }\n\n if (data === 'camera') {\n const defaultCamera: ImageOptions = {\n quality: 100,\n width: this.$photoMaxSize(),\n allowEditing: false,\n resultType: CameraResultType.DataUrl,\n source: CameraSource.Camera,\n presentationStyle: 'popover',\n };\n const image = await Camera.getPhoto(defaultCamera).catch(() => undefined);\n if (!image?.dataUrl) {\n return Promise.reject(PhotoEditorErrors.cancel);\n }\n\n if (!image.dataUrl.includes('capacitor://localhost')) {\n return [image.dataUrl];\n }\n return Promise.all([image.dataUrl].map(async (image) => await this.loadPhotoFromFilePath(image)));\n }\n\n if (data === 'album') {\n const images = await Camera.pickImages({\n quality: 100,\n width: this.$photoMaxSize(),\n limit,\n presentationStyle: 'popover',\n }).catch(() => undefined);\n\n if (!images) {\n return Promise.reject(PhotoEditorErrors.cancel);\n }\n\n return Promise.all(images.photos.map(async (image) => await this.loadPhotoFromFilePath(image.webPath)));\n }\n\n // Not run on this line. This is for lint\n return [];\n }\n\n private getPictureFromBrowser(): Promise<string[]> {\n const inputFile: HTMLInputElement | null = document.querySelector('input#browserPhotoUploader');\n\n if (!inputFile) {\n return Promise.reject(PhotoEditorErrors.initialize);\n }\n\n return new Promise((resolve, reject) => {\n const cancelMethod = () => {\n inputFile!.removeEventListener('cancel', cancelMethod, false);\n inputFile!.removeEventListener('change', changeMethod, false);\n\n reject(PhotoEditorErrors.cancel);\n };\n const changeMethod = (e: Event) => {\n inputFile!.removeEventListener('cancel', cancelMethod, false);\n inputFile!.removeEventListener('change', changeMethod, false);\n\n if (!(e.target as HTMLInputElement).files || !(e.target as HTMLInputElement).files![0]) {\n reject(PhotoEditorErrors.cancel);\n }\n const file = (e.target as HTMLInputElement).files![0];\n const reader = new FileReader();\n\n reader.onload = (() => {\n if (file.type.indexOf('image') < 0) {\n reject(PhotoEditorErrors.type);\n }\n\n return async (event) => {\n inputFile.value = '';\n const result = event.target!.result as string;\n const data = await this.loadPhotoFromFilePath(result);\n resolve([data]);\n };\n })();\n\n reader.readAsDataURL(file);\n };\n\n inputFile!.addEventListener('cancel', cancelMethod, false);\n inputFile!.addEventListener('change', changeMethod, false);\n inputFile.click();\n });\n }\n\n private async loadPhotoFromFilePath(filePath: string): Promise<string> {\n const defaultInstance = new ImageEditor(document.createElement('div'), {\n cssMaxWidth: this.$photoMaxSize(),\n cssMaxHeight: this.$photoMaxSize(),\n });\n const blob = await fetch(filePath).then((res) => res.blob());\n const loaded = await defaultInstance.loadImageFromFile(new File([blob], 'data.png', { type: blob.type }));\n\n const maxSize = Math.max(loaded.newWidth, loaded.newHeight);\n const dataUrl = defaultInstance.toDataURL({\n multiplier: this.$photoMaxSize() / maxSize,\n });\n defaultInstance.destroy();\n\n return dataUrl;\n }\n}\n","/*\n * Public API Surface of photo-editor\n */\n\nexport * from './lib/pages/photo-editor/photo-editor.page';\nexport * from './lib/pages/photo-viewer/photo-viewer.page';\nexport * from './lib/services/photo-file.service';\nexport * from './lib/types';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/index.d.ts
CHANGED
|
@@ -1,5 +1,132 @@
|
|
|
1
|
-
|
|
2
|
-
*
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import * as _rdlabo_ionic_angular_photo_editor from '@rdlabo/ionic-angular-photo-editor';
|
|
2
|
+
import * as _angular_core from '@angular/core';
|
|
3
|
+
import { OnInit, OnDestroy, ElementRef } from '@angular/core';
|
|
4
|
+
import { BooleanInput, NumberInput } from '@angular/cdk/coercion';
|
|
5
|
+
import { ViewDidEnter, ViewDidLeave, ModalController, RangeCustomEvent } from '@ionic/angular/standalone';
|
|
6
|
+
import { Subscription } from 'rxjs';
|
|
7
|
+
import { SwiperContainer } from 'swiper/element';
|
|
8
|
+
|
|
9
|
+
interface IFilter {
|
|
10
|
+
name: string;
|
|
11
|
+
type: string;
|
|
12
|
+
option: any;
|
|
13
|
+
data: string;
|
|
14
|
+
width: number;
|
|
15
|
+
height: number;
|
|
16
|
+
}
|
|
17
|
+
interface ISize {
|
|
18
|
+
width: number;
|
|
19
|
+
height: number;
|
|
20
|
+
}
|
|
21
|
+
interface IDictionaryForEditor {
|
|
22
|
+
save: string;
|
|
23
|
+
crop: string;
|
|
24
|
+
filter: string;
|
|
25
|
+
brightness: string;
|
|
26
|
+
original: string;
|
|
27
|
+
invert: string;
|
|
28
|
+
sepia: string;
|
|
29
|
+
vintage: string;
|
|
30
|
+
blur: string;
|
|
31
|
+
grayscale: string;
|
|
32
|
+
sharpen: string;
|
|
33
|
+
emboss: string;
|
|
34
|
+
}
|
|
35
|
+
interface IFilterPreset {
|
|
36
|
+
name: string;
|
|
37
|
+
type: string;
|
|
38
|
+
option: any;
|
|
39
|
+
}
|
|
40
|
+
interface IPhotoEditorDismiss {
|
|
41
|
+
value: string;
|
|
42
|
+
}
|
|
43
|
+
interface IPhotoViewerDismiss {
|
|
44
|
+
delete: {
|
|
45
|
+
index: number;
|
|
46
|
+
value: string;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
interface IDictionaryForViewer {
|
|
50
|
+
delete: string;
|
|
51
|
+
}
|
|
52
|
+
interface IDictionaryForService {
|
|
53
|
+
camera: string;
|
|
54
|
+
album: string;
|
|
55
|
+
cancel: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
declare class PhotoEditorPage implements OnInit, OnDestroy, ViewDidEnter, ViewDidLeave {
|
|
59
|
+
readonly modalCtrl: ModalController;
|
|
60
|
+
protected readonly dictionary: _angular_core.WritableSignal<IDictionaryForEditor>;
|
|
61
|
+
readonly requireSquare: _angular_core.InputSignalWithTransform<boolean, BooleanInput>;
|
|
62
|
+
readonly labels: _angular_core.InputSignal<Partial<IDictionaryForEditor> | undefined>;
|
|
63
|
+
readonly setLabels: _angular_core.EffectRef;
|
|
64
|
+
readonly value: _angular_core.InputSignal<string>;
|
|
65
|
+
readonly editorRef: _angular_core.Signal<ElementRef<any>>;
|
|
66
|
+
readonly ionContent: _angular_core.Signal<ElementRef<any>>;
|
|
67
|
+
readonly filters: _angular_core.WritableSignal<IFilter[]>;
|
|
68
|
+
readonly footerMenu: _angular_core.WritableSignal<"menu" | "filter" | "crop" | "brightness">;
|
|
69
|
+
readonly currentCrop: _angular_core.WritableSignal<"1" | "cover" | "16/9" | "auto">;
|
|
70
|
+
readonly currentRotate: _angular_core.WritableSignal<number>;
|
|
71
|
+
readonly photoCrop: _angular_core.WritableSignal<ISize>;
|
|
72
|
+
readonly isCropped: _angular_core.WritableSignal<boolean>;
|
|
73
|
+
private readonly adoptFilter;
|
|
74
|
+
protected readonly filterPreset: _angular_core.Signal<_rdlabo_ionic_angular_photo_editor.IFilterPreset[]>;
|
|
75
|
+
private readonly footerMenu$;
|
|
76
|
+
private readonly initSubscription$;
|
|
77
|
+
private readonly filterImageSize;
|
|
78
|
+
private editorInstance;
|
|
79
|
+
private canvasContainerObserver;
|
|
80
|
+
constructor();
|
|
81
|
+
ngOnInit(): void;
|
|
82
|
+
ngOnDestroy(): void;
|
|
83
|
+
ionViewDidEnter(): Promise<void>;
|
|
84
|
+
ionViewDidLeave(): void;
|
|
85
|
+
changeCrop(crop: 'cover' | '16/9' | '1' | 'auto'): void;
|
|
86
|
+
rotate(): Promise<void>;
|
|
87
|
+
closeCrop(type: 'cancel' | 'apply'): Promise<void>;
|
|
88
|
+
changeRange(event: RangeCustomEvent): Promise<void>;
|
|
89
|
+
imageSave(): void;
|
|
90
|
+
private initializeFilterMenu;
|
|
91
|
+
filterImage(filter: IFilter): Promise<void>;
|
|
92
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<PhotoEditorPage, never>;
|
|
93
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<PhotoEditorPage, "app-editor-image", never, { "requireSquare": { "alias": "requireSquare"; "required": false; "isSignal": true; }; "labels": { "alias": "labels"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
declare class PhotoViewerPage implements OnInit, OnDestroy {
|
|
97
|
+
readonly imageUrls: _angular_core.InputSignal<string[]>;
|
|
98
|
+
readonly index: _angular_core.InputSignalWithTransform<number, NumberInput>;
|
|
99
|
+
readonly isCircle: _angular_core.InputSignalWithTransform<boolean, BooleanInput>;
|
|
100
|
+
readonly enableDelete: _angular_core.InputSignalWithTransform<boolean, BooleanInput>;
|
|
101
|
+
readonly enableFooterSafeArea: _angular_core.InputSignalWithTransform<boolean, BooleanInput>;
|
|
102
|
+
readonly labels: _angular_core.InputSignal<Partial<IDictionaryForViewer> | undefined>;
|
|
103
|
+
readonly setLabels: _angular_core.EffectRef;
|
|
104
|
+
readonly swiper: _angular_core.Signal<ElementRef<SwiperContainer>>;
|
|
105
|
+
protected readonly dictionary: _angular_core.WritableSignal<IDictionaryForViewer>;
|
|
106
|
+
readonly watchSwipe$: Subscription;
|
|
107
|
+
readonly modalCtrl: ModalController;
|
|
108
|
+
private readonly el;
|
|
109
|
+
constructor();
|
|
110
|
+
ngOnInit(): Promise<void>;
|
|
111
|
+
ngOnDestroy(): void;
|
|
112
|
+
remove(): void;
|
|
113
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<PhotoViewerPage, never>;
|
|
114
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<PhotoViewerPage, "app-photo-image", never, { "imageUrls": { "alias": "imageUrls"; "required": true; "isSignal": true; }; "index": { "alias": "index"; "required": false; "isSignal": true; }; "isCircle": { "alias": "isCircle"; "required": false; "isSignal": true; }; "enableDelete": { "alias": "enableDelete"; "required": false; "isSignal": true; }; "enableFooterSafeArea": { "alias": "enableFooterSafeArea"; "required": false; "isSignal": true; }; "labels": { "alias": "labels"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
declare class PhotoFileService {
|
|
118
|
+
private readonly $photoMaxSize;
|
|
119
|
+
private readonly actionSheetCtrl;
|
|
120
|
+
private readonly platform;
|
|
121
|
+
private readonly dictionary;
|
|
122
|
+
set photoMaxSize(value: number);
|
|
123
|
+
set labels(d: IDictionaryForService);
|
|
124
|
+
loadPhoto(limit: number): Promise<string[]>;
|
|
125
|
+
private getPictureFromBrowser;
|
|
126
|
+
private loadPhotoFromFilePath;
|
|
127
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<PhotoFileService, never>;
|
|
128
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<PhotoFileService>;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export { PhotoEditorPage, PhotoFileService, PhotoViewerPage };
|
|
132
|
+
export type { IDictionaryForEditor, IDictionaryForService, IDictionaryForViewer, IFilter, IFilterPreset, IPhotoEditorDismiss, IPhotoViewerDismiss, ISize };
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rdlabo/ionic-angular-photo-editor",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "20.0.1",
|
|
4
4
|
"peerDependencies": {
|
|
5
|
-
"@angular/
|
|
6
|
-
"@angular/
|
|
5
|
+
"@angular/cdk": "^20.0.0",
|
|
6
|
+
"@angular/common": "^20.0.0",
|
|
7
|
+
"@angular/core": "^20.0.0",
|
|
7
8
|
"@capacitor/camera": ">=6.0.0 <8.0.0",
|
|
8
9
|
"@capacitor/core": ">=6.0.0 <8.0.0",
|
|
9
10
|
"@ionic/angular": "^8.0.0",
|
package/lib/dictionaries.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { IDictionaryForEditor, IDictionaryForService, IDictionaryForViewer } from './types';
|
|
2
|
-
export declare const dictionaryForEditor: () => IDictionaryForEditor;
|
|
3
|
-
export declare const dictionaryForViewer: () => IDictionaryForViewer;
|
|
4
|
-
export declare const dictionaryForService: () => IDictionaryForService;
|
package/lib/filter-preset.d.ts
DELETED
package/lib/ion-components.d.ts
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import { IonButton, IonButtons, IonContent, IonFooter, IonHeader, IonIcon, IonRange, IonText, IonToolbar } from '@ionic/angular/standalone';
|
|
2
|
-
export declare const ionComponents: (typeof IonButton | typeof IonButtons | typeof IonContent | typeof IonFooter | typeof IonHeader | typeof IonText | typeof IonToolbar | typeof IonIcon | typeof IonRange)[];
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { ElementRef, OnDestroy, OnInit } from '@angular/core';
|
|
2
|
-
import { IonContent, ModalController, RangeCustomEvent, ViewDidEnter, ViewDidLeave } from '@ionic/angular/standalone';
|
|
3
|
-
import { IDictionaryForEditor, IFilter, ISize } from '../types';
|
|
4
|
-
import * as i0 from "@angular/core";
|
|
5
|
-
export declare class PhotoEditorPage implements OnInit, OnDestroy, ViewDidEnter, ViewDidLeave {
|
|
6
|
-
protected dictionary: IDictionaryForEditor;
|
|
7
|
-
protected filterPreset: import("../types").IFilterPreset[];
|
|
8
|
-
requireSquare: boolean;
|
|
9
|
-
value: string;
|
|
10
|
-
set labels(d: IDictionaryForEditor);
|
|
11
|
-
editorRef: ElementRef;
|
|
12
|
-
ionContent: {
|
|
13
|
-
el: IonContent & HTMLElement;
|
|
14
|
-
};
|
|
15
|
-
$filters: import("@angular/core").WritableSignal<IFilter[]>;
|
|
16
|
-
$footerMenu: import("@angular/core").WritableSignal<"filter" | "menu" | "crop" | "brightness">;
|
|
17
|
-
$currentCrop: import("@angular/core").WritableSignal<"auto" | "1" | "cover" | "16/9">;
|
|
18
|
-
$currentRotate: import("@angular/core").WritableSignal<number>;
|
|
19
|
-
$photoCrop: import("@angular/core").WritableSignal<ISize>;
|
|
20
|
-
$isCropped: import("@angular/core").WritableSignal<boolean>;
|
|
21
|
-
private footerMenu$;
|
|
22
|
-
private $adoptFilter;
|
|
23
|
-
private editorInstance;
|
|
24
|
-
private initSubscription$;
|
|
25
|
-
private readonly filterImageSize;
|
|
26
|
-
private readonly service;
|
|
27
|
-
modalCtrl: ModalController;
|
|
28
|
-
private canvasContainerObserver;
|
|
29
|
-
constructor();
|
|
30
|
-
ngOnInit(): void;
|
|
31
|
-
ngOnDestroy(): void;
|
|
32
|
-
ionViewDidEnter(): Promise<void>;
|
|
33
|
-
ionViewDidLeave(): void;
|
|
34
|
-
changeCrop(crop: 'cover' | '16/9' | '1' | 'auto'): void;
|
|
35
|
-
rotate(): Promise<void>;
|
|
36
|
-
closeCrop(type: 'cancel' | 'apply'): Promise<void>;
|
|
37
|
-
changeRange(event: RangeCustomEvent): Promise<void>;
|
|
38
|
-
imageSave(): void;
|
|
39
|
-
private initializeFilterMenu;
|
|
40
|
-
filterImage(filter: IFilter): Promise<void>;
|
|
41
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<PhotoEditorPage, never>;
|
|
42
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<PhotoEditorPage, "app-editor-image", never, { "requireSquare": { "alias": "requireSquare"; "required": false; }; "value": { "alias": "value"; "required": false; }; "labels": { "alias": "labels"; "required": false; }; }, {}, never, never, true, never>;
|
|
43
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { ElementRef, OnDestroy, OnInit } from '@angular/core';
|
|
2
|
-
import { ModalController } from '@ionic/angular/standalone';
|
|
3
|
-
import { Subscription } from 'rxjs';
|
|
4
|
-
import { SwiperContainer } from 'swiper/element';
|
|
5
|
-
import { IDictionaryForViewer } from '../types';
|
|
6
|
-
import * as i0 from "@angular/core";
|
|
7
|
-
export declare class PhotoViewerPage implements OnInit, OnDestroy {
|
|
8
|
-
protected dictionary: IDictionaryForViewer;
|
|
9
|
-
imageUrls: string[];
|
|
10
|
-
index: number;
|
|
11
|
-
isCircle: boolean;
|
|
12
|
-
enableDelete: boolean;
|
|
13
|
-
enableFooterSafeArea: boolean;
|
|
14
|
-
set labels(d: IDictionaryForViewer);
|
|
15
|
-
swiper: ElementRef<SwiperContainer>;
|
|
16
|
-
watchSwipe$: Subscription;
|
|
17
|
-
readonly modalCtrl: ModalController;
|
|
18
|
-
private readonly el;
|
|
19
|
-
private readonly service;
|
|
20
|
-
constructor();
|
|
21
|
-
ngOnInit(): Promise<void>;
|
|
22
|
-
ngOnDestroy(): void;
|
|
23
|
-
remove(): void;
|
|
24
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<PhotoViewerPage, never>;
|
|
25
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<PhotoViewerPage, "app-photo-image", never, { "imageUrls": { "alias": "imageUrls"; "required": false; }; "index": { "alias": "index"; "required": false; }; "isCircle": { "alias": "isCircle"; "required": false; }; "enableDelete": { "alias": "enableDelete"; "required": false; }; "enableFooterSafeArea": { "alias": "enableFooterSafeArea"; "required": false; }; "labels": { "alias": "labels"; "required": false; }; }, {}, never, never, true, never>;
|
|
26
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import * as i0 from "@angular/core";
|
|
2
|
-
export declare class HelperService {
|
|
3
|
-
constructor();
|
|
4
|
-
initializeViewerIcons(): void;
|
|
5
|
-
initializeEditorIcons(): void;
|
|
6
|
-
waitToFindDom(nativeElement: HTMLElement, selector: string): Promise<void>;
|
|
7
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<HelperService, never>;
|
|
8
|
-
static ɵprov: i0.ɵɵInjectableDeclaration<HelperService>;
|
|
9
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { IDictionaryForService } from '../types';
|
|
2
|
-
import * as i0 from "@angular/core";
|
|
3
|
-
export declare class PhotoFileService {
|
|
4
|
-
private readonly $photoMaxSize;
|
|
5
|
-
private readonly actionSheetCtrl;
|
|
6
|
-
private readonly platform;
|
|
7
|
-
private dictionary;
|
|
8
|
-
constructor();
|
|
9
|
-
set photoMaxSize(value: number);
|
|
10
|
-
set labels(d: IDictionaryForService);
|
|
11
|
-
loadPhoto(limit: number): Promise<string[]>;
|
|
12
|
-
private getPictureFromBrowser;
|
|
13
|
-
private loadPhotoFromFilePath;
|
|
14
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<PhotoFileService, never>;
|
|
15
|
-
static ɵprov: i0.ɵɵInjectableDeclaration<PhotoFileService>;
|
|
16
|
-
}
|
package/lib/types.d.ts
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
export interface IFilter {
|
|
2
|
-
name: string;
|
|
3
|
-
type: string;
|
|
4
|
-
option: any;
|
|
5
|
-
data: string;
|
|
6
|
-
width: number;
|
|
7
|
-
height: number;
|
|
8
|
-
}
|
|
9
|
-
export interface ISize {
|
|
10
|
-
width: number;
|
|
11
|
-
height: number;
|
|
12
|
-
}
|
|
13
|
-
export interface IDictionaryForEditor {
|
|
14
|
-
save: string;
|
|
15
|
-
crop: string;
|
|
16
|
-
filter: string;
|
|
17
|
-
brightness: string;
|
|
18
|
-
original: string;
|
|
19
|
-
invert: string;
|
|
20
|
-
sepia: string;
|
|
21
|
-
vintage: string;
|
|
22
|
-
blur: string;
|
|
23
|
-
grayscale: string;
|
|
24
|
-
sharpen: string;
|
|
25
|
-
emboss: string;
|
|
26
|
-
}
|
|
27
|
-
export interface IFilterPreset {
|
|
28
|
-
name: string;
|
|
29
|
-
type: string;
|
|
30
|
-
option: any;
|
|
31
|
-
}
|
|
32
|
-
export interface IPhotoEditorDismiss {
|
|
33
|
-
value: string;
|
|
34
|
-
}
|
|
35
|
-
export interface IPhotoViewerDismiss {
|
|
36
|
-
delete: {
|
|
37
|
-
index: number;
|
|
38
|
-
value: string;
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
export interface IDictionaryForViewer {
|
|
42
|
-
delete: string;
|
|
43
|
-
}
|
|
44
|
-
export interface IDictionaryForService {
|
|
45
|
-
camera: string;
|
|
46
|
-
album: string;
|
|
47
|
-
cancel: string;
|
|
48
|
-
}
|
package/public-api.d.ts
DELETED