ngx-kit 6.1.0 → 6.3.0
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/README.md +3 -3
- package/angle-selector/README.md +34 -34
- package/box-shadow/README.md +33 -33
- package/color-picker/README.md +49 -49
- package/data-table/README.md +113 -113
- package/date-picker/README.md +69 -69
- package/dialog/README.md +92 -92
- package/drawer-menu/README.md +110 -62
- package/dropzone/README.md +422 -422
- package/fesm2022/ngx-kit-angle-selector.mjs +2 -2
- package/fesm2022/ngx-kit-angle-selector.mjs.map +1 -1
- package/fesm2022/ngx-kit-box-shadow.mjs +2 -2
- package/fesm2022/ngx-kit-box-shadow.mjs.map +1 -1
- package/fesm2022/ngx-kit-color-picker.mjs +4 -4
- package/fesm2022/ngx-kit-color-picker.mjs.map +1 -1
- package/fesm2022/ngx-kit-data-table.mjs +2 -2
- package/fesm2022/ngx-kit-data-table.mjs.map +1 -1
- package/fesm2022/ngx-kit-date-picker.mjs +1324 -200
- package/fesm2022/ngx-kit-date-picker.mjs.map +1 -1
- package/fesm2022/ngx-kit-dialog.mjs +2 -2
- package/fesm2022/ngx-kit-dialog.mjs.map +1 -1
- package/fesm2022/ngx-kit-drawer-menu.mjs +302 -140
- package/fesm2022/ngx-kit-drawer-menu.mjs.map +1 -1
- package/fesm2022/ngx-kit-dropzone.mjs +2 -2
- package/fesm2022/ngx-kit-dropzone.mjs.map +1 -1
- package/fesm2022/ngx-kit-form-field.mjs.map +1 -1
- package/fesm2022/ngx-kit-gallery.mjs +2 -2
- package/fesm2022/ngx-kit-gallery.mjs.map +1 -1
- package/fesm2022/ngx-kit-gradient-picker.mjs.map +1 -1
- package/fesm2022/ngx-kit-image-editor.mjs +75 -11
- package/fesm2022/ngx-kit-image-editor.mjs.map +1 -1
- package/fesm2022/ngx-kit-menu.mjs +8 -8
- package/fesm2022/ngx-kit-menu.mjs.map +1 -1
- package/fesm2022/ngx-kit-message.mjs +2 -2
- package/fesm2022/ngx-kit-message.mjs.map +1 -1
- package/fesm2022/ngx-kit-notify.mjs.map +1 -1
- package/fesm2022/ngx-kit-shared.mjs +2 -2
- package/fesm2022/ngx-kit-shared.mjs.map +1 -1
- package/fesm2022/ngx-kit-time-picker.mjs +2 -2
- package/fesm2022/ngx-kit-time-picker.mjs.map +1 -1
- package/gallery/README.md +71 -71
- package/gradient-picker/README.md +41 -41
- package/menu/README.md +85 -85
- package/message/README.md +70 -70
- package/notify/README.md +58 -58
- package/package.json +1 -1
- package/shared/README.md +117 -117
- package/time-picker/README.md +95 -95
- package/types/ngx-kit-date-picker.d.ts +303 -36
- package/types/ngx-kit-drawer-menu.d.ts +97 -86
- package/types/ngx-kit-dropzone.d.ts +5 -5
- package/types/ngx-kit-image-editor.d.ts +29 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { output, HostListener, Directive, InjectionToken, input, inject, signal, computed, effect, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
2
|
+
import { output, HostListener, Directive, InjectionToken, input, inject, signal, viewChild, computed, effect, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/forms';
|
|
4
4
|
import { FormsModule } from '@angular/forms';
|
|
5
5
|
import { SliderComponent } from 'ngx-kit/shared';
|
|
@@ -259,9 +259,11 @@ class NgxImageEditorLocalization {
|
|
|
259
259
|
Cancel = 'Cancel';
|
|
260
260
|
Save = 'Save';
|
|
261
261
|
Saving = 'Saving…';
|
|
262
|
+
Reset = 'Reset';
|
|
262
263
|
}
|
|
263
264
|
const DEFAULT_NGX_IMAGE_EDITOR_LOCALIZATION = new NgxImageEditorLocalization();
|
|
264
265
|
|
|
266
|
+
const ALL_FILTERS = ['none', 'grayscale', 'sepia', 'invert', 'cartoon'];
|
|
265
267
|
/**
|
|
266
268
|
* ویرایشگر تصویر: کراپ + چرخش + روشنایی/کنتراست/اشباع + فیلترهای آماده
|
|
267
269
|
* (سیاهوسفید، سپیا، معکوس، کارتونی) + فشردهسازی خروجی. کاملاً روی Canvas
|
|
@@ -272,6 +274,15 @@ const DEFAULT_NGX_IMAGE_EDITOR_LOCALIZATION = new NgxImageEditorLocalization();
|
|
|
272
274
|
* (createWorkingCopy)، نه روی تصویر اصلی که ممکنه چند مگاپیکسل باشه — وگرنه
|
|
273
275
|
* درگکردن اسلایدرها/گوشههای کراپ رو کاربر حس تاخیر میکرد. فقط لحظهی
|
|
274
276
|
* save()، رندر نهایی از روی تصویر اصلیِ کامل انجام میشه.
|
|
277
|
+
*
|
|
278
|
+
* اندازهی صحنه (stage) با panelSize کنترل میشه: عرض همیشه ۱۰۰٪ عرضِ
|
|
279
|
+
* والدِ کامپوننته (با ResizeObserver اندازهگیری میشه، پس با تغییر سایز
|
|
280
|
+
* صفحه/layout هم زنده هماهنگ میمونه)، ارتفاع دقیقاً همون چیزیه که کاربر با
|
|
281
|
+
* panelSize میده. تصویر همیشه با یک مقیاسِ «contain» واقعی (هم بر اساس
|
|
282
|
+
* عرض، هم بر اساس ارتفاع — هرکدوم تنگتره) جا داده میشه، پس کلِ تصویر
|
|
283
|
+
* همیشه در محدودهی همین باکس دیده میشه، صرفنظر از اندازهی واقعیِ فایل.
|
|
284
|
+
* سقفِ مقیاس هم ۱ هست، یعنی تصاویر کوچیک بزرگنمایی نمیشن (که باعثِ محو
|
|
285
|
+
* شدنشون میشد).
|
|
275
286
|
*/
|
|
276
287
|
class NgxImageEditorComponent {
|
|
277
288
|
source = input(null, /* @ts-ignore */
|
|
@@ -285,9 +296,12 @@ class NgxImageEditorComponent {
|
|
|
285
296
|
...(ngDevMode ? [{ debugName: "outputMaxHeight" }] : /* istanbul ignore next */ []));
|
|
286
297
|
outputType = input('image/jpeg', /* @ts-ignore */
|
|
287
298
|
...(ngDevMode ? [{ debugName: "outputType" }] : /* istanbul ignore next */ []));
|
|
288
|
-
/**
|
|
289
|
-
|
|
290
|
-
|
|
299
|
+
/**
|
|
300
|
+
* کدوم فیلترها نشون داده بشن (و به چه ترتیبی). اگه ندید، هر ۵ تا نشون داده
|
|
301
|
+
* میشن. آرایهی خالی یعنی کلِ بخشِ فیلتر مخفی بشه.
|
|
302
|
+
*/
|
|
303
|
+
filters = input(ALL_FILTERS, /* @ts-ignore */
|
|
304
|
+
...(ngDevMode ? [{ debugName: "filters" }] : /* istanbul ignore next */ []));
|
|
291
305
|
quality = input(0.92, /* @ts-ignore */
|
|
292
306
|
...(ngDevMode ? [{ debugName: "quality" }] : /* istanbul ignore next */ []));
|
|
293
307
|
defaultLocalization = inject(NGX_IMAGE_EDITOR_LOCALIZATION);
|
|
@@ -305,6 +319,11 @@ class NgxImageEditorComponent {
|
|
|
305
319
|
...(ngDevMode ? [{ debugName: "originalImage" }] : /* istanbul ignore next */ []));
|
|
306
320
|
workingCanvas = signal(null, /* @ts-ignore */
|
|
307
321
|
...(ngDevMode ? [{ debugName: "workingCanvas" }] : /* istanbul ignore next */ []));
|
|
322
|
+
stageWrapEl = viewChild('stageWrap', /* @ts-ignore */
|
|
323
|
+
...(ngDevMode ? [{ debugName: "stageWrapEl" }] : /* istanbul ignore next */ []));
|
|
324
|
+
/** عرضِ واقعیِ رندرشدهی کانتینر؛ چون عرض همیشه ۱۰۰٪ (fluid) هست، باید زنده اندازهگیری بشه */
|
|
325
|
+
containerWidth = signal(0, /* @ts-ignore */
|
|
326
|
+
...(ngDevMode ? [{ debugName: "containerWidth" }] : /* istanbul ignore next */ []));
|
|
308
327
|
rotation = signal(0, /* @ts-ignore */
|
|
309
328
|
...(ngDevMode ? [{ debugName: "rotation" }] : /* istanbul ignore next */ []));
|
|
310
329
|
brightness = signal(100, /* @ts-ignore */
|
|
@@ -325,6 +344,17 @@ class NgxImageEditorComponent {
|
|
|
325
344
|
filter: this.filterPreset(),
|
|
326
345
|
}), /* @ts-ignore */
|
|
327
346
|
...(ngDevMode ? [{ debugName: "adjustments" }] : /* istanbul ignore next */ []));
|
|
347
|
+
filterLabels = computed(() => {
|
|
348
|
+
const t = this.localize();
|
|
349
|
+
return {
|
|
350
|
+
none: t.None,
|
|
351
|
+
grayscale: t.Grayscale,
|
|
352
|
+
sepia: t.Sepia,
|
|
353
|
+
invert: t.Invert,
|
|
354
|
+
cartoon: t.Cartoon,
|
|
355
|
+
};
|
|
356
|
+
}, /* @ts-ignore */
|
|
357
|
+
...(ngDevMode ? [{ debugName: "filterLabels" }] : /* istanbul ignore next */ []));
|
|
328
358
|
/** تصویرِ (کوچیکشدهیِ) چرخیده — پایهی نمایش صحنهی کراپ */
|
|
329
359
|
rotatedWorkingCanvas = computed(() => {
|
|
330
360
|
const wc = this.workingCanvas();
|
|
@@ -333,11 +363,21 @@ class NgxImageEditorComponent {
|
|
|
333
363
|
return renderRotated(wc, wc.width, wc.height, this.rotation());
|
|
334
364
|
}, /* @ts-ignore */
|
|
335
365
|
...(ngDevMode ? [{ debugName: "rotatedWorkingCanvas" }] : /* istanbul ignore next */ []));
|
|
366
|
+
panelSize = computed(() => {
|
|
367
|
+
return this.stageWrapEl()?.nativeElement.getBoundingClientRect().height ?? 0;
|
|
368
|
+
}, /* @ts-ignore */
|
|
369
|
+
...(ngDevMode ? [{ debugName: "panelSize" }] : /* istanbul ignore next */ []));
|
|
370
|
+
/**
|
|
371
|
+
* مقیاسِ «contain» واقعی: کوچیکترینِ نسبتِ عرض و ارتفاع (هرکدوم تنگتره)
|
|
372
|
+
* تعیینکنندهست، و سقفش هم ۱ هست تا تصاویر کوچیک بزرگنمایی نشن.
|
|
373
|
+
*/
|
|
336
374
|
displayScale = computed(() => {
|
|
337
375
|
const rc = this.rotatedWorkingCanvas();
|
|
338
|
-
|
|
376
|
+
const containerW = this.containerWidth();
|
|
377
|
+
const panelH = this.panelSize();
|
|
378
|
+
if (!rc || rc.width <= 0 || rc.height <= 0 || containerW <= 0 || panelH <= 0)
|
|
339
379
|
return 1;
|
|
340
|
-
return Math.min(
|
|
380
|
+
return Math.min(containerW / rc.width, panelH / rc.height, 1);
|
|
341
381
|
}, /* @ts-ignore */
|
|
342
382
|
...(ngDevMode ? [{ debugName: "displayScale" }] : /* istanbul ignore next */ []));
|
|
343
383
|
stageImageUrl = computed(() => {
|
|
@@ -401,13 +441,37 @@ class NgxImageEditorComponent {
|
|
|
401
441
|
this.crop.set({ x: 0, y: 0, width: rc.width, height: rc.height });
|
|
402
442
|
}
|
|
403
443
|
});
|
|
444
|
+
// اگه فیلترِ فعلاً انتخابشده دیگه توی لیستِ مجازِ filters() نباشه (مثلاً
|
|
445
|
+
// مصرفکننده cartoon رو غیرفعال کرده درحالیکه کاربر روش بود)، برو روی
|
|
446
|
+
// اولین فیلترِ مجاز؛ اگه لیست خالی باشه (کلاً فیلتر مخفیه)، روی none بمون.
|
|
447
|
+
effect(() => {
|
|
448
|
+
const allowed = this.filters();
|
|
449
|
+
if (allowed.length && !allowed.includes(this.filterPreset())) {
|
|
450
|
+
this.filterPreset.set(allowed[0]);
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
// اندازهگیریِ زندهی عرضِ واقعیِ کانتینر — چون عرض همیشه ۱۰۰٪ (fluid)ه،
|
|
454
|
+
// فقط با ResizeObserver میشه فهمید الان چند پیکسله (نه یه عددِ ثابتِ ورودی).
|
|
455
|
+
effect((onCleanup) => {
|
|
456
|
+
const el = this.stageWrapEl()?.nativeElement;
|
|
457
|
+
if (!el)
|
|
458
|
+
return;
|
|
459
|
+
this.containerWidth.set(el.getBoundingClientRect().width);
|
|
460
|
+
const ro = new ResizeObserver((entries) => {
|
|
461
|
+
const width = entries[0]?.contentRect.width;
|
|
462
|
+
if (width != null)
|
|
463
|
+
this.containerWidth.set(width);
|
|
464
|
+
});
|
|
465
|
+
ro.observe(el);
|
|
466
|
+
onCleanup(() => ro.disconnect());
|
|
467
|
+
});
|
|
404
468
|
}
|
|
405
469
|
resetAdjustments() {
|
|
406
470
|
this.rotation.set(0);
|
|
407
471
|
this.brightness.set(100);
|
|
408
472
|
this.contrast.set(100);
|
|
409
473
|
this.saturation.set(100);
|
|
410
|
-
this.filterPreset.set('none');
|
|
474
|
+
this.filterPreset.set(this.filters()[0] ?? 'none');
|
|
411
475
|
}
|
|
412
476
|
rotateBy(delta) {
|
|
413
477
|
this.rotation.update((r) => {
|
|
@@ -509,16 +573,16 @@ class NgxImageEditorComponent {
|
|
|
509
573
|
}
|
|
510
574
|
}
|
|
511
575
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxImageEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
512
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: NgxImageEditorComponent, isStandalone: true, selector: "ngx-image-editor", inputs: { source: { classPropertyName: "source", publicName: "source", isSignal: true, isRequired: false, transformFunction: null }, aspectRatio: { classPropertyName: "aspectRatio", publicName: "aspectRatio", isSignal: true, isRequired: false, transformFunction: null }, outputMaxWidth: { classPropertyName: "outputMaxWidth", publicName: "outputMaxWidth", isSignal: true, isRequired: false, transformFunction: null }, outputMaxHeight: { classPropertyName: "outputMaxHeight", publicName: "outputMaxHeight", isSignal: true, isRequired: false, transformFunction: null }, outputType: { classPropertyName: "outputType", publicName: "outputType", isSignal: true, isRequired: false, transformFunction: null }, displayMaxWidth: { classPropertyName: "displayMaxWidth", publicName: "displayMaxWidth", isSignal: true, isRequired: false, transformFunction: null }, quality: { classPropertyName: "quality", publicName: "quality", isSignal: true, isRequired: false, transformFunction: null }, localize: { classPropertyName: "localize", publicName: "localize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { saved: "saved", cancelled: "cancelled" }, host: { classAttribute: "ngx-image-editor-host" }, ngImport: i0, template: "@if (loading()) {\n <div class=\"ngx-ie-state\">{{ localize().LoadingImage }}</div>\n} @else if (loadError()) {\n <div class=\"ngx-ie-state ngx-ie-state--error\">{{ loadError() }}</div>\n} @else if (stageImageUrl()) {\n <div class=\"ngx-ie-layout\">\n <div class=\"ngx-ie-stage-wrap\">\n <div\n class=\"ngx-ie-stage\"\n [style.width.px]=\"stageSize().width\"\n [style.height.px]=\"stageSize().height\">\n <img class=\"ngx-ie-stage-img\" [src]=\"stageImageUrl()\" alt=\"\" draggable=\"false\" />\n\n <div\n class=\"ngx-ie-crop-box\"\n [style.left]=\"cropOverlayStyle().left\"\n [style.top]=\"cropOverlayStyle().top\"\n [style.width]=\"cropOverlayStyle().width\"\n [style.height]=\"cropOverlayStyle().height\"\n ngxPointerDrag\n (dragStart)=\"onMoveDragStart()\"\n (dragMove)=\"onMoveDragMove($event)\">\n <span\n class=\"ngx-ie-handle ngx-ie-handle--nw\"\n ngxPointerDrag\n (dragStart)=\"onResizeDragStart()\"\n (dragMove)=\"onResizeDragMove('nw', $event)\"></span>\n <span\n class=\"ngx-ie-handle ngx-ie-handle--ne\"\n ngxPointerDrag\n (dragStart)=\"onResizeDragStart()\"\n (dragMove)=\"onResizeDragMove('ne', $event)\"></span>\n <span\n class=\"ngx-ie-handle ngx-ie-handle--sw\"\n ngxPointerDrag\n (dragStart)=\"onResizeDragStart()\"\n (dragMove)=\"onResizeDragMove('sw', $event)\"></span>\n <span\n class=\"ngx-ie-handle ngx-ie-handle--se\"\n ngxPointerDrag\n (dragStart)=\"onResizeDragStart()\"\n (dragMove)=\"onResizeDragMove('se', $event)\"></span>\n </div>\n </div>\n </div>\n\n <div class=\"ngx-ie-panel\">\n <div class=\"ngx-ie-preview\">\n @if (previewUrl(); as url) {\n <img [src]=\"url\" alt=\"Preview\" />\n }\n </div>\n\n <div class=\"ngx-ie-row ngx-ie-rotate-row\">\n <button type=\"button\" (click)=\"rotateBy(-90)\" title=\"Rotate 90\u00B0 left\">\u27F2 90</button>\n <button type=\"button\" (click)=\"rotateBy(90)\" title=\"Rotate 90\u00B0 right\">\u27F3 90</button>\n </div>\n\n <label class=\"ngx-ie-field\">\n <span>{{ localize().Rotation }} ({{ rotation() }}\u00B0)</span>\n <slider\n [ngModel]=\"rotation()\"\n (ngModelChange)=\"rotation.set($event)\"\n [min]=\"-180\"\n [max]=\"180\"></slider>\n </label>\n\n <label class=\"ngx-ie-field\">\n <span>{{ localize().Brightness }} ({{ brightness() }}%)</span>\n <slider\n [ngModel]=\"brightness()\"\n (ngModelChange)=\"brightness.set($event)\"\n [min]=\"0\"\n [max]=\"200\"></slider>\n </label>\n\n <label class=\"ngx-ie-field\">\n <span>{{ localize().Contrast }} ({{ contrast() }}%)</span>\n <slider\n [ngModel]=\"contrast()\"\n (ngModelChange)=\"contrast.set($event)\"\n [min]=\"0\"\n [max]=\"200\"></slider>\n </label>\n\n <label class=\"ngx-ie-field\">\n <span>{{ localize().Saturation }} ({{ saturation() }}%)</span>\n <slider\n [ngModel]=\"saturation()\"\n (ngModelChange)=\"saturation.set($event)\"\n [min]=\"0\"\n [max]=\"200\"></slider>\n </label>\n\n <div class=\"ngx-ie-field\">\n <span>{{ localize().Filter }}</span>\n <div class=\"ngx-ie-filter-row\">\n <button\n type=\"button\"\n [class.active]=\"filterPreset() === 'none'\"\n (click)=\"setFilter('none')\">\n {{ localize().None }}\n </button>\n <button\n type=\"button\"\n [class.active]=\"filterPreset() === 'grayscale'\"\n (click)=\"setFilter('grayscale')\">\n {{ localize().Grayscale }}\n </button>\n <button\n type=\"button\"\n [class.active]=\"filterPreset() === 'sepia'\"\n (click)=\"setFilter('sepia')\">\n {{ localize().Sepia }}\n </button>\n <button\n type=\"button\"\n [class.active]=\"filterPreset() === 'invert'\"\n (click)=\"setFilter('invert')\">\n {{ localize().Invert }}\n </button>\n <button\n type=\"button\"\n [class.active]=\"filterPreset() === 'cartoon'\"\n (click)=\"setFilter('cartoon')\">\n {{ localize().Cartoon }}\n </button>\n </div>\n </div>\n\n <div class=\"ngx-ie-row ngx-ie-actions\">\n <button type=\"button\" class=\"ngx-ie-btn-secondary\" (click)=\"cancel()\">\n {{ localize().Cancel }}\n </button>\n <button type=\"button\" class=\"ngx-ie-btn-primary\" [disabled]=\"saving()\" (click)=\"save()\">\n {{ saving() ? localize().Saving : localize().Save }}\n </button>\n </div>\n </div>\n </div>\n}\n", styles: [":host{display:block}.ngx-ie-state{padding:2rem;text-align:center;color:light-dark(#6b7280,#9ca3af)}.ngx-ie-state--error{color:light-dark(#b91c1c,#f87171)}.ngx-ie-layout{display:flex;flex-wrap:wrap;gap:1.25rem}.ngx-ie-stage-wrap{display:flex;align-items:flex-start;justify-content:center;padding:.5rem;background:light-dark(#f3f4f6,#18181b);border-radius:10px;overflow:hidden}.ngx-ie-stage{position:relative;touch-action:none;-webkit-user-select:none;user-select:none;direction:ltr}.ngx-ie-stage-img{display:block;inline-size:100%;block-size:100%;border-radius:4px;pointer-events:none;background:#fff;background-image:linear-gradient(45deg,#ccc 25%,transparent 25%),linear-gradient(-45deg,#ccc 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#ccc 75%),linear-gradient(-45deg,transparent 75%,#ccc 75%);background-size:16px 16px;background-position:0 0,0 8px,8px -8px,-8px 0px}.ngx-ie-crop-box{position:absolute;box-sizing:border-box;border:2px solid #2563eb;box-shadow:0 0 0 9999px #00000073;cursor:move;touch-action:none}.ngx-ie-handle{position:absolute;inline-size:14px;block-size:14px;background:#fff;border:2px solid #2563eb;border-radius:50%;touch-action:none}.ngx-ie-handle--nw{inset-inline-start:-7px;inset-block-start:-7px;cursor:nwse-resize}.ngx-ie-handle--ne{inset-inline-end:-7px;inset-block-start:-7px;cursor:nesw-resize}.ngx-ie-handle--sw{inset-inline-start:-7px;inset-block-end:-7px;cursor:nesw-resize}.ngx-ie-handle--se{inset-inline-end:-7px;inset-block-end:-7px;cursor:nwse-resize}.ngx-ie-panel{flex:1;min-inline-size:240px;display:flex;flex-direction:column;gap:.75rem}.ngx-ie-preview{display:flex;align-items:center;justify-content:center;min-block-size:100px;background:light-dark(#f3f4f6,#18181b);border-radius:8px;overflow:hidden}.ngx-ie-preview img{max-inline-size:100%;max-block-size:160px;display:block;background:#fff;background-image:linear-gradient(45deg,#ccc 25%,transparent 25%),linear-gradient(-45deg,#ccc 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#ccc 75%),linear-gradient(-45deg,transparent 75%,#ccc 75%);background-size:16px 16px;background-position:0 0,0 8px,8px -8px,-8px 0px}.ngx-ie-field{display:flex;flex-direction:column;gap:.3rem;font-size:.8rem;color:light-dark(#374151,#d4d4d8)}.ngx-ie-row{display:flex;gap:.5rem}.ngx-ie-rotate-row button,.ngx-ie-filter-row button{appearance:none;border:1px solid light-dark(#e5e7eb,#33333a);background:light-dark(#ffffff,#232327);color:light-dark(#374151,#d4d4d8);border-radius:999px;padding:.4rem .85rem;font-size:.75rem;cursor:pointer;transition:background-color .15s ease,border-color .15s ease,transform .15s ease,color .15s ease}.ngx-ie-rotate-row button:hover,.ngx-ie-filter-row button:hover{background:light-dark(#f3f4f6,#2c2c31);transform:translateY(-1px)}.ngx-ie-rotate-row button:active,.ngx-ie-filter-row button:active{transform:translateY(0)}.ngx-ie-rotate-row button.active,.ngx-ie-filter-row button.active{background:light-dark(#2563eb,#3b82f6);border-color:light-dark(#2563eb,#3b82f6);color:#fff;box-shadow:0 2px 10px light-dark(rgba(37,99,235,.3),rgba(59,130,246,.3))}.ngx-ie-filter-row{display:flex;flex-wrap:wrap;gap:.4rem}.ngx-ie-actions{margin-block-start:auto;justify-content:flex-end}.ngx-ie-btn-primary,.ngx-ie-btn-secondary{appearance:none;border:none;border-radius:8px;padding:.55rem 1.1rem;font-size:.85rem;cursor:pointer;font-weight:500;transition:transform .15s ease,box-shadow .15s ease,opacity .15s ease}.ngx-ie-btn-primary:hover,.ngx-ie-btn-secondary:hover{transform:translateY(-1px)}.ngx-ie-btn-primary:active,.ngx-ie-btn-secondary:active{transform:translateY(0)}.ngx-ie-btn-primary{background:light-dark(#2563eb,#3b82f6);color:#fff;box-shadow:0 2px 10px light-dark(rgba(37,99,235,.25),rgba(59,130,246,.25))}.ngx-ie-btn-primary:disabled{opacity:.6;cursor:not-allowed;transform:none}.ngx-ie-btn-secondary{background:light-dark(#e5e7eb,#3f3f46);color:light-dark(#374151,#e4e4e7)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: SliderComponent, selector: "slider", inputs: ["step", "min", "max", "background", "isBgTransparent"], outputs: ["change"] }, { kind: "directive", type: NgxPointerDragDirective, selector: "[ngxPointerDrag]", outputs: ["dragStart", "dragMove", "dragEnd"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
576
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: NgxImageEditorComponent, isStandalone: true, selector: "ngx-image-editor", inputs: { source: { classPropertyName: "source", publicName: "source", isSignal: true, isRequired: false, transformFunction: null }, aspectRatio: { classPropertyName: "aspectRatio", publicName: "aspectRatio", isSignal: true, isRequired: false, transformFunction: null }, outputMaxWidth: { classPropertyName: "outputMaxWidth", publicName: "outputMaxWidth", isSignal: true, isRequired: false, transformFunction: null }, outputMaxHeight: { classPropertyName: "outputMaxHeight", publicName: "outputMaxHeight", isSignal: true, isRequired: false, transformFunction: null }, outputType: { classPropertyName: "outputType", publicName: "outputType", isSignal: true, isRequired: false, transformFunction: null }, filters: { classPropertyName: "filters", publicName: "filters", isSignal: true, isRequired: false, transformFunction: null }, quality: { classPropertyName: "quality", publicName: "quality", isSignal: true, isRequired: false, transformFunction: null }, localize: { classPropertyName: "localize", publicName: "localize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { saved: "saved", cancelled: "cancelled" }, host: { classAttribute: "ngx-image-editor-host" }, viewQueries: [{ propertyName: "stageWrapEl", first: true, predicate: ["stageWrap"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (loading()) {\r\n <div class=\"ngx-ie-state\">{{ localize().LoadingImage }}</div>\r\n} @else if (loadError()) {\r\n <div class=\"ngx-ie-state ngx-ie-state--error\">{{ loadError() }}</div>\r\n} @else if (stageImageUrl()) {\r\n <div class=\"ngx-ie-layout\">\r\n <div class=\"ngx-ie-stage-wrap\" #stageWrap>\r\n <div\r\n class=\"ngx-ie-stage\"\r\n [style.width.px]=\"stageSize().width\"\r\n [style.height.px]=\"stageSize().height\">\r\n <img class=\"ngx-ie-stage-img\" [src]=\"stageImageUrl()\" alt=\"\" draggable=\"false\" />\r\n\r\n <div\r\n class=\"ngx-ie-crop-box\"\r\n [style.left]=\"cropOverlayStyle().left\"\r\n [style.top]=\"cropOverlayStyle().top\"\r\n [style.width]=\"cropOverlayStyle().width\"\r\n [style.height]=\"cropOverlayStyle().height\"\r\n ngxPointerDrag\r\n (dragStart)=\"onMoveDragStart()\"\r\n (dragMove)=\"onMoveDragMove($event)\">\r\n <span\r\n class=\"ngx-ie-handle ngx-ie-handle--nw\"\r\n ngxPointerDrag\r\n (dragStart)=\"onResizeDragStart()\"\r\n (dragMove)=\"onResizeDragMove('nw', $event)\"></span>\r\n <span\r\n class=\"ngx-ie-handle ngx-ie-handle--ne\"\r\n ngxPointerDrag\r\n (dragStart)=\"onResizeDragStart()\"\r\n (dragMove)=\"onResizeDragMove('ne', $event)\"></span>\r\n <span\r\n class=\"ngx-ie-handle ngx-ie-handle--sw\"\r\n ngxPointerDrag\r\n (dragStart)=\"onResizeDragStart()\"\r\n (dragMove)=\"onResizeDragMove('sw', $event)\"></span>\r\n <span\r\n class=\"ngx-ie-handle ngx-ie-handle--se\"\r\n ngxPointerDrag\r\n (dragStart)=\"onResizeDragStart()\"\r\n (dragMove)=\"onResizeDragMove('se', $event)\"></span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"ngx-ie-panel-row\">\r\n <div class=\"ngx-ie-panel\">\r\n <div class=\"ngx-ie-preview\">\r\n @if (previewUrl(); as url) {\r\n <img [src]=\"url\" alt=\"Preview\" />\r\n }\r\n </div>\r\n\r\n <div class=\"ngx-ie-row ngx-ie-rotate-row\">\r\n <button type=\"button\" (click)=\"rotateBy(-90)\" title=\"Rotate 90\u00B0 left\">\u27F2 90</button>\r\n <button type=\"button\" (click)=\"rotateBy(90)\" title=\"Rotate 90\u00B0 right\">\u27F3 90</button>\r\n </div>\r\n\r\n <div class=\"ngx-ie-field\">\r\n <slider\r\n [ngModel]=\"rotation()\"\r\n (ngModelChange)=\"rotation.set($event)\"\r\n [min]=\"-180\"\r\n [max]=\"180\">\r\n <span>{{ localize().Rotation }} ({{ rotation() }}\u00B0)</span>\r\n </slider>\r\n\r\n <button\r\n type=\"button\"\r\n (click)=\"rotation.set(0)\"\r\n class=\"ngx-ie-btn-secondary\"\r\n [title]=\"localize().Reset\">\r\n x\r\n </button>\r\n </div>\r\n\r\n <div class=\"ngx-ie-field\">\r\n <slider\r\n [ngModel]=\"brightness()\"\r\n (ngModelChange)=\"brightness.set($event)\"\r\n [min]=\"0\"\r\n [max]=\"200\">\r\n <span>{{ localize().Brightness }} ({{ brightness() }}%)</span>\r\n </slider>\r\n <button\r\n type=\"button\"\r\n (click)=\"brightness.set(100)\"\r\n class=\"ngx-ie-btn-secondary\"\r\n [title]=\"localize().Reset\">\r\n x\r\n </button>\r\n </div>\r\n\r\n <div class=\"ngx-ie-field\">\r\n <slider\r\n [ngModel]=\"contrast()\"\r\n (ngModelChange)=\"contrast.set($event)\"\r\n [min]=\"0\"\r\n [max]=\"200\">\r\n <span>{{ localize().Contrast }} ({{ contrast() }}%)</span>\r\n </slider>\r\n <button\r\n type=\"button\"\r\n (click)=\"contrast.set(100)\"\r\n class=\"ngx-ie-btn-secondary\"\r\n [title]=\"localize().Reset\">\r\n x\r\n </button>\r\n </div>\r\n\r\n <div class=\"ngx-ie-field\">\r\n <slider\r\n [ngModel]=\"saturation()\"\r\n (ngModelChange)=\"saturation.set($event)\"\r\n [min]=\"0\"\r\n [max]=\"200\">\r\n <span>{{ localize().Saturation }} ({{ saturation() }}%)</span>\r\n </slider>\r\n <button\r\n type=\"button\"\r\n (click)=\"saturation.set(100)\"\r\n class=\"ngx-ie-btn-secondary\"\r\n [title]=\"localize().Reset\">\r\n x\r\n </button>\r\n </div>\r\n\r\n @if (filters().length) {\r\n <div>\r\n <span>{{ localize().Filter }}</span>\r\n <div class=\"ngx-ie-filter-row\">\r\n @for (f of filters(); track f) {\r\n <button type=\"button\" [class.active]=\"filterPreset() === f\" (click)=\"setFilter(f)\">\r\n {{ filterLabels()[f] }}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n <div class=\"ngx-ie-row ngx-ie-actions\">\r\n <button type=\"button\" class=\"ngx-ie-btn-secondary\" (click)=\"cancel()\">\r\n {{ localize().Cancel }}\r\n </button>\r\n <button type=\"button\" class=\"ngx-ie-btn-primary\" [disabled]=\"saving()\" (click)=\"save()\">\r\n {{ saving() ? localize().Saving : localize().Save }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n}\r\n", styles: ["@charset \"UTF-8\";:host{display:block;min-height:70dvh;--ngx-image-editor-panel-width: 25%}.ngx-ie-state{padding:2rem;text-align:center;color:light-dark(#6b7280,#9ca3af)}.ngx-ie-state--error{color:light-dark(#b91c1c,#f87171)}.ngx-ie-layout{display:grid;grid-template-columns:1fr var(--ngx-image-editor-panel-width, 30%);gap:1.25rem;height:100%}.ngx-ie-stage-wrap{width:100%;display:flex;align-items:center;justify-content:center;background:light-dark(#f3f4f6,#18181b);border-radius:10px;overflow:hidden;flex-shrink:0}.ngx-ie-stage{position:relative;touch-action:none;-webkit-user-select:none;user-select:none;direction:ltr}.ngx-ie-stage-img{display:block;inline-size:100%;block-size:100%;border-radius:4px;pointer-events:none;background:#fff;background-image:linear-gradient(45deg,#ccc 25%,transparent 25%),linear-gradient(-45deg,#ccc 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#ccc 75%),linear-gradient(-45deg,transparent 75%,#ccc 75%);background-size:16px 16px;background-position:0 0,0 8px,8px -8px,-8px 0px}.ngx-ie-crop-box{position:absolute;box-sizing:border-box;border:2px solid #2563eb;box-shadow:0 0 0 9999px #00000073;cursor:move;touch-action:none}.ngx-ie-handle{position:absolute;inline-size:14px;block-size:14px;background:#fff;border:2px solid #2563eb;border-radius:50%;touch-action:none}.ngx-ie-handle--nw{inset-inline-start:-7px;inset-block-start:-7px;cursor:nwse-resize}.ngx-ie-handle--ne{inset-inline-end:-7px;inset-block-start:-7px;cursor:nesw-resize}.ngx-ie-handle--sw{inset-inline-start:-7px;inset-block-end:-7px;cursor:nesw-resize}.ngx-ie-handle--se{inset-inline-end:-7px;inset-block-end:-7px;cursor:nwse-resize}.ngx-ie-panel{flex:1;display:flex;flex-direction:column;gap:.75rem}.ngx-ie-panel-row{display:flex;flex-wrap:wrap;gap:1.25rem}.ngx-ie-preview{display:flex;align-items:center;justify-content:center;min-block-size:100px;background:light-dark(#f3f4f6,#18181b);border-radius:8px;overflow:hidden}.ngx-ie-preview img{max-inline-size:100%;max-block-size:160px;display:block;background:#fff;background-image:linear-gradient(45deg,#ccc 25%,transparent 25%),linear-gradient(-45deg,#ccc 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#ccc 75%),linear-gradient(-45deg,transparent 75%,#ccc 75%);background-size:16px 16px;background-position:0 0,0 8px,8px -8px,-8px 0px}.ngx-ie-field{display:flex;gap:.3rem;align-items:flex-end}.ngx-ie-field slider{flex:1}.ngx-ie-row{display:flex;gap:.5rem}.ngx-ie-rotate-row button,.ngx-ie-filter-row button{appearance:none;border:1px solid light-dark(#e5e7eb,#33333a);background:light-dark(#ffffff,#232327);color:light-dark(#374151,#d4d4d8);border-radius:999px;padding:.4rem .85rem;font-size:.75rem;cursor:pointer;transition:background-color .15s ease,border-color .15s ease,transform .15s ease,color .15s ease}.ngx-ie-rotate-row button:hover,.ngx-ie-filter-row button:hover{background:light-dark(#f3f4f6,#2c2c31);transform:translateY(-1px)}.ngx-ie-rotate-row button:active,.ngx-ie-filter-row button:active{transform:translateY(0)}.ngx-ie-rotate-row button.active,.ngx-ie-filter-row button.active{background:light-dark(#2563eb,#3b82f6);border-color:light-dark(#2563eb,#3b82f6);color:#fff;box-shadow:0 2px 10px light-dark(rgba(37,99,235,.3),rgba(59,130,246,.3))}.ngx-ie-filter-row{display:flex;flex-wrap:wrap;gap:.4rem}.ngx-ie-actions{margin-block-start:auto;justify-content:flex-end}.ngx-ie-btn-primary,.ngx-ie-btn-secondary{appearance:none;border:none;border-radius:8px;padding:.55rem 1.1rem;font-size:.85rem;cursor:pointer;font-weight:500;transition:transform .15s ease,box-shadow .15s ease,opacity .15s ease}.ngx-ie-btn-primary:hover,.ngx-ie-btn-secondary:hover{transform:translateY(-1px)}.ngx-ie-btn-primary:active,.ngx-ie-btn-secondary:active{transform:translateY(0)}.ngx-ie-btn-primary{background:light-dark(#2563eb,#3b82f6);color:#fff;box-shadow:0 2px 10px light-dark(rgba(37,99,235,.25),rgba(59,130,246,.25))}.ngx-ie-btn-primary:disabled{opacity:.6;cursor:not-allowed;transform:none}.ngx-ie-btn-secondary{background:light-dark(#e5e7eb,#3f3f46);color:light-dark(#374151,#e4e4e7)}@media(max-width:768px){:host{height:unset!important}.ngx-ie-layout{display:flex;flex-direction:column}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: SliderComponent, selector: "slider", inputs: ["step", "min", "max", "background", "isBgTransparent"], outputs: ["change"] }, { kind: "directive", type: NgxPointerDragDirective, selector: "[ngxPointerDrag]", outputs: ["dragStart", "dragMove", "dragEnd"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
513
577
|
}
|
|
514
578
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxImageEditorComponent, decorators: [{
|
|
515
579
|
type: Component,
|
|
516
|
-
args: [{ selector: 'ngx-image-editor', standalone: true, imports: [FormsModule, SliderComponent, NgxPointerDragDirective], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'ngx-image-editor-host' }, template: "@if (loading()) {\n <div class=\"ngx-ie-state\">{{ localize().LoadingImage }}</div>\n} @else if (loadError()) {\n <div class=\"ngx-ie-state ngx-ie-state--error\">{{ loadError() }}</div>\n} @else if (stageImageUrl()) {\n <div class=\"ngx-ie-layout\">\n <div class=\"ngx-ie-stage-wrap\">\n <div\n class=\"ngx-ie-stage\"\n [style.width.px]=\"stageSize().width\"\n [style.height.px]=\"stageSize().height\">\n <img class=\"ngx-ie-stage-img\" [src]=\"stageImageUrl()\" alt=\"\" draggable=\"false\" />\n\n <div\n class=\"ngx-ie-crop-box\"\n [style.left]=\"cropOverlayStyle().left\"\n [style.top]=\"cropOverlayStyle().top\"\n [style.width]=\"cropOverlayStyle().width\"\n [style.height]=\"cropOverlayStyle().height\"\n ngxPointerDrag\n (dragStart)=\"onMoveDragStart()\"\n (dragMove)=\"onMoveDragMove($event)\">\n <span\n class=\"ngx-ie-handle ngx-ie-handle--nw\"\n ngxPointerDrag\n (dragStart)=\"onResizeDragStart()\"\n (dragMove)=\"onResizeDragMove('nw', $event)\"></span>\n <span\n class=\"ngx-ie-handle ngx-ie-handle--ne\"\n ngxPointerDrag\n (dragStart)=\"onResizeDragStart()\"\n (dragMove)=\"onResizeDragMove('ne', $event)\"></span>\n <span\n class=\"ngx-ie-handle ngx-ie-handle--sw\"\n ngxPointerDrag\n (dragStart)=\"onResizeDragStart()\"\n (dragMove)=\"onResizeDragMove('sw', $event)\"></span>\n <span\n class=\"ngx-ie-handle ngx-ie-handle--se\"\n ngxPointerDrag\n (dragStart)=\"onResizeDragStart()\"\n (dragMove)=\"onResizeDragMove('se', $event)\"></span>\n </div>\n </div>\n </div>\n\n <div class=\"ngx-ie-panel\">\n <div class=\"ngx-ie-preview\">\n @if (previewUrl(); as url) {\n <img [src]=\"url\" alt=\"Preview\" />\n }\n </div>\n\n <div class=\"ngx-ie-row ngx-ie-rotate-row\">\n <button type=\"button\" (click)=\"rotateBy(-90)\" title=\"Rotate 90\u00B0 left\">\u27F2 90</button>\n <button type=\"button\" (click)=\"rotateBy(90)\" title=\"Rotate 90\u00B0 right\">\u27F3 90</button>\n </div>\n\n <label class=\"ngx-ie-field\">\n <span>{{ localize().Rotation }} ({{ rotation() }}\u00B0)</span>\n <slider\n [ngModel]=\"rotation()\"\n (ngModelChange)=\"rotation.set($event)\"\n [min]=\"-180\"\n [max]=\"180\"></slider>\n </label>\n\n <label class=\"ngx-ie-field\">\n <span>{{ localize().Brightness }} ({{ brightness() }}%)</span>\n <slider\n [ngModel]=\"brightness()\"\n (ngModelChange)=\"brightness.set($event)\"\n [min]=\"0\"\n [max]=\"200\"></slider>\n </label>\n\n <label class=\"ngx-ie-field\">\n <span>{{ localize().Contrast }} ({{ contrast() }}%)</span>\n <slider\n [ngModel]=\"contrast()\"\n (ngModelChange)=\"contrast.set($event)\"\n [min]=\"0\"\n [max]=\"200\"></slider>\n </label>\n\n <label class=\"ngx-ie-field\">\n <span>{{ localize().Saturation }} ({{ saturation() }}%)</span>\n <slider\n [ngModel]=\"saturation()\"\n (ngModelChange)=\"saturation.set($event)\"\n [min]=\"0\"\n [max]=\"200\"></slider>\n </label>\n\n <div class=\"ngx-ie-field\">\n <span>{{ localize().Filter }}</span>\n <div class=\"ngx-ie-filter-row\">\n <button\n type=\"button\"\n [class.active]=\"filterPreset() === 'none'\"\n (click)=\"setFilter('none')\">\n {{ localize().None }}\n </button>\n <button\n type=\"button\"\n [class.active]=\"filterPreset() === 'grayscale'\"\n (click)=\"setFilter('grayscale')\">\n {{ localize().Grayscale }}\n </button>\n <button\n type=\"button\"\n [class.active]=\"filterPreset() === 'sepia'\"\n (click)=\"setFilter('sepia')\">\n {{ localize().Sepia }}\n </button>\n <button\n type=\"button\"\n [class.active]=\"filterPreset() === 'invert'\"\n (click)=\"setFilter('invert')\">\n {{ localize().Invert }}\n </button>\n <button\n type=\"button\"\n [class.active]=\"filterPreset() === 'cartoon'\"\n (click)=\"setFilter('cartoon')\">\n {{ localize().Cartoon }}\n </button>\n </div>\n </div>\n\n <div class=\"ngx-ie-row ngx-ie-actions\">\n <button type=\"button\" class=\"ngx-ie-btn-secondary\" (click)=\"cancel()\">\n {{ localize().Cancel }}\n </button>\n <button type=\"button\" class=\"ngx-ie-btn-primary\" [disabled]=\"saving()\" (click)=\"save()\">\n {{ saving() ? localize().Saving : localize().Save }}\n </button>\n </div>\n </div>\n </div>\n}\n", styles: [":host{display:block}.ngx-ie-state{padding:2rem;text-align:center;color:light-dark(#6b7280,#9ca3af)}.ngx-ie-state--error{color:light-dark(#b91c1c,#f87171)}.ngx-ie-layout{display:flex;flex-wrap:wrap;gap:1.25rem}.ngx-ie-stage-wrap{display:flex;align-items:flex-start;justify-content:center;padding:.5rem;background:light-dark(#f3f4f6,#18181b);border-radius:10px;overflow:hidden}.ngx-ie-stage{position:relative;touch-action:none;-webkit-user-select:none;user-select:none;direction:ltr}.ngx-ie-stage-img{display:block;inline-size:100%;block-size:100%;border-radius:4px;pointer-events:none;background:#fff;background-image:linear-gradient(45deg,#ccc 25%,transparent 25%),linear-gradient(-45deg,#ccc 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#ccc 75%),linear-gradient(-45deg,transparent 75%,#ccc 75%);background-size:16px 16px;background-position:0 0,0 8px,8px -8px,-8px 0px}.ngx-ie-crop-box{position:absolute;box-sizing:border-box;border:2px solid #2563eb;box-shadow:0 0 0 9999px #00000073;cursor:move;touch-action:none}.ngx-ie-handle{position:absolute;inline-size:14px;block-size:14px;background:#fff;border:2px solid #2563eb;border-radius:50%;touch-action:none}.ngx-ie-handle--nw{inset-inline-start:-7px;inset-block-start:-7px;cursor:nwse-resize}.ngx-ie-handle--ne{inset-inline-end:-7px;inset-block-start:-7px;cursor:nesw-resize}.ngx-ie-handle--sw{inset-inline-start:-7px;inset-block-end:-7px;cursor:nesw-resize}.ngx-ie-handle--se{inset-inline-end:-7px;inset-block-end:-7px;cursor:nwse-resize}.ngx-ie-panel{flex:1;min-inline-size:240px;display:flex;flex-direction:column;gap:.75rem}.ngx-ie-preview{display:flex;align-items:center;justify-content:center;min-block-size:100px;background:light-dark(#f3f4f6,#18181b);border-radius:8px;overflow:hidden}.ngx-ie-preview img{max-inline-size:100%;max-block-size:160px;display:block;background:#fff;background-image:linear-gradient(45deg,#ccc 25%,transparent 25%),linear-gradient(-45deg,#ccc 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#ccc 75%),linear-gradient(-45deg,transparent 75%,#ccc 75%);background-size:16px 16px;background-position:0 0,0 8px,8px -8px,-8px 0px}.ngx-ie-field{display:flex;flex-direction:column;gap:.3rem;font-size:.8rem;color:light-dark(#374151,#d4d4d8)}.ngx-ie-row{display:flex;gap:.5rem}.ngx-ie-rotate-row button,.ngx-ie-filter-row button{appearance:none;border:1px solid light-dark(#e5e7eb,#33333a);background:light-dark(#ffffff,#232327);color:light-dark(#374151,#d4d4d8);border-radius:999px;padding:.4rem .85rem;font-size:.75rem;cursor:pointer;transition:background-color .15s ease,border-color .15s ease,transform .15s ease,color .15s ease}.ngx-ie-rotate-row button:hover,.ngx-ie-filter-row button:hover{background:light-dark(#f3f4f6,#2c2c31);transform:translateY(-1px)}.ngx-ie-rotate-row button:active,.ngx-ie-filter-row button:active{transform:translateY(0)}.ngx-ie-rotate-row button.active,.ngx-ie-filter-row button.active{background:light-dark(#2563eb,#3b82f6);border-color:light-dark(#2563eb,#3b82f6);color:#fff;box-shadow:0 2px 10px light-dark(rgba(37,99,235,.3),rgba(59,130,246,.3))}.ngx-ie-filter-row{display:flex;flex-wrap:wrap;gap:.4rem}.ngx-ie-actions{margin-block-start:auto;justify-content:flex-end}.ngx-ie-btn-primary,.ngx-ie-btn-secondary{appearance:none;border:none;border-radius:8px;padding:.55rem 1.1rem;font-size:.85rem;cursor:pointer;font-weight:500;transition:transform .15s ease,box-shadow .15s ease,opacity .15s ease}.ngx-ie-btn-primary:hover,.ngx-ie-btn-secondary:hover{transform:translateY(-1px)}.ngx-ie-btn-primary:active,.ngx-ie-btn-secondary:active{transform:translateY(0)}.ngx-ie-btn-primary{background:light-dark(#2563eb,#3b82f6);color:#fff;box-shadow:0 2px 10px light-dark(rgba(37,99,235,.25),rgba(59,130,246,.25))}.ngx-ie-btn-primary:disabled{opacity:.6;cursor:not-allowed;transform:none}.ngx-ie-btn-secondary{background:light-dark(#e5e7eb,#3f3f46);color:light-dark(#374151,#e4e4e7)}\n"] }]
|
|
517
|
-
}], ctorParameters: () => [], propDecorators: { source: [{ type: i0.Input, args: [{ isSignal: true, alias: "source", required: false }] }], aspectRatio: [{ type: i0.Input, args: [{ isSignal: true, alias: "aspectRatio", required: false }] }], outputMaxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "outputMaxWidth", required: false }] }], outputMaxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "outputMaxHeight", required: false }] }], outputType: [{ type: i0.Input, args: [{ isSignal: true, alias: "outputType", required: false }] }],
|
|
580
|
+
args: [{ selector: 'ngx-image-editor', standalone: true, imports: [FormsModule, SliderComponent, NgxPointerDragDirective], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'ngx-image-editor-host' }, template: "@if (loading()) {\r\n <div class=\"ngx-ie-state\">{{ localize().LoadingImage }}</div>\r\n} @else if (loadError()) {\r\n <div class=\"ngx-ie-state ngx-ie-state--error\">{{ loadError() }}</div>\r\n} @else if (stageImageUrl()) {\r\n <div class=\"ngx-ie-layout\">\r\n <div class=\"ngx-ie-stage-wrap\" #stageWrap>\r\n <div\r\n class=\"ngx-ie-stage\"\r\n [style.width.px]=\"stageSize().width\"\r\n [style.height.px]=\"stageSize().height\">\r\n <img class=\"ngx-ie-stage-img\" [src]=\"stageImageUrl()\" alt=\"\" draggable=\"false\" />\r\n\r\n <div\r\n class=\"ngx-ie-crop-box\"\r\n [style.left]=\"cropOverlayStyle().left\"\r\n [style.top]=\"cropOverlayStyle().top\"\r\n [style.width]=\"cropOverlayStyle().width\"\r\n [style.height]=\"cropOverlayStyle().height\"\r\n ngxPointerDrag\r\n (dragStart)=\"onMoveDragStart()\"\r\n (dragMove)=\"onMoveDragMove($event)\">\r\n <span\r\n class=\"ngx-ie-handle ngx-ie-handle--nw\"\r\n ngxPointerDrag\r\n (dragStart)=\"onResizeDragStart()\"\r\n (dragMove)=\"onResizeDragMove('nw', $event)\"></span>\r\n <span\r\n class=\"ngx-ie-handle ngx-ie-handle--ne\"\r\n ngxPointerDrag\r\n (dragStart)=\"onResizeDragStart()\"\r\n (dragMove)=\"onResizeDragMove('ne', $event)\"></span>\r\n <span\r\n class=\"ngx-ie-handle ngx-ie-handle--sw\"\r\n ngxPointerDrag\r\n (dragStart)=\"onResizeDragStart()\"\r\n (dragMove)=\"onResizeDragMove('sw', $event)\"></span>\r\n <span\r\n class=\"ngx-ie-handle ngx-ie-handle--se\"\r\n ngxPointerDrag\r\n (dragStart)=\"onResizeDragStart()\"\r\n (dragMove)=\"onResizeDragMove('se', $event)\"></span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"ngx-ie-panel-row\">\r\n <div class=\"ngx-ie-panel\">\r\n <div class=\"ngx-ie-preview\">\r\n @if (previewUrl(); as url) {\r\n <img [src]=\"url\" alt=\"Preview\" />\r\n }\r\n </div>\r\n\r\n <div class=\"ngx-ie-row ngx-ie-rotate-row\">\r\n <button type=\"button\" (click)=\"rotateBy(-90)\" title=\"Rotate 90\u00B0 left\">\u27F2 90</button>\r\n <button type=\"button\" (click)=\"rotateBy(90)\" title=\"Rotate 90\u00B0 right\">\u27F3 90</button>\r\n </div>\r\n\r\n <div class=\"ngx-ie-field\">\r\n <slider\r\n [ngModel]=\"rotation()\"\r\n (ngModelChange)=\"rotation.set($event)\"\r\n [min]=\"-180\"\r\n [max]=\"180\">\r\n <span>{{ localize().Rotation }} ({{ rotation() }}\u00B0)</span>\r\n </slider>\r\n\r\n <button\r\n type=\"button\"\r\n (click)=\"rotation.set(0)\"\r\n class=\"ngx-ie-btn-secondary\"\r\n [title]=\"localize().Reset\">\r\n x\r\n </button>\r\n </div>\r\n\r\n <div class=\"ngx-ie-field\">\r\n <slider\r\n [ngModel]=\"brightness()\"\r\n (ngModelChange)=\"brightness.set($event)\"\r\n [min]=\"0\"\r\n [max]=\"200\">\r\n <span>{{ localize().Brightness }} ({{ brightness() }}%)</span>\r\n </slider>\r\n <button\r\n type=\"button\"\r\n (click)=\"brightness.set(100)\"\r\n class=\"ngx-ie-btn-secondary\"\r\n [title]=\"localize().Reset\">\r\n x\r\n </button>\r\n </div>\r\n\r\n <div class=\"ngx-ie-field\">\r\n <slider\r\n [ngModel]=\"contrast()\"\r\n (ngModelChange)=\"contrast.set($event)\"\r\n [min]=\"0\"\r\n [max]=\"200\">\r\n <span>{{ localize().Contrast }} ({{ contrast() }}%)</span>\r\n </slider>\r\n <button\r\n type=\"button\"\r\n (click)=\"contrast.set(100)\"\r\n class=\"ngx-ie-btn-secondary\"\r\n [title]=\"localize().Reset\">\r\n x\r\n </button>\r\n </div>\r\n\r\n <div class=\"ngx-ie-field\">\r\n <slider\r\n [ngModel]=\"saturation()\"\r\n (ngModelChange)=\"saturation.set($event)\"\r\n [min]=\"0\"\r\n [max]=\"200\">\r\n <span>{{ localize().Saturation }} ({{ saturation() }}%)</span>\r\n </slider>\r\n <button\r\n type=\"button\"\r\n (click)=\"saturation.set(100)\"\r\n class=\"ngx-ie-btn-secondary\"\r\n [title]=\"localize().Reset\">\r\n x\r\n </button>\r\n </div>\r\n\r\n @if (filters().length) {\r\n <div>\r\n <span>{{ localize().Filter }}</span>\r\n <div class=\"ngx-ie-filter-row\">\r\n @for (f of filters(); track f) {\r\n <button type=\"button\" [class.active]=\"filterPreset() === f\" (click)=\"setFilter(f)\">\r\n {{ filterLabels()[f] }}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n <div class=\"ngx-ie-row ngx-ie-actions\">\r\n <button type=\"button\" class=\"ngx-ie-btn-secondary\" (click)=\"cancel()\">\r\n {{ localize().Cancel }}\r\n </button>\r\n <button type=\"button\" class=\"ngx-ie-btn-primary\" [disabled]=\"saving()\" (click)=\"save()\">\r\n {{ saving() ? localize().Saving : localize().Save }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n}\r\n", styles: ["@charset \"UTF-8\";:host{display:block;min-height:70dvh;--ngx-image-editor-panel-width: 25%}.ngx-ie-state{padding:2rem;text-align:center;color:light-dark(#6b7280,#9ca3af)}.ngx-ie-state--error{color:light-dark(#b91c1c,#f87171)}.ngx-ie-layout{display:grid;grid-template-columns:1fr var(--ngx-image-editor-panel-width, 30%);gap:1.25rem;height:100%}.ngx-ie-stage-wrap{width:100%;display:flex;align-items:center;justify-content:center;background:light-dark(#f3f4f6,#18181b);border-radius:10px;overflow:hidden;flex-shrink:0}.ngx-ie-stage{position:relative;touch-action:none;-webkit-user-select:none;user-select:none;direction:ltr}.ngx-ie-stage-img{display:block;inline-size:100%;block-size:100%;border-radius:4px;pointer-events:none;background:#fff;background-image:linear-gradient(45deg,#ccc 25%,transparent 25%),linear-gradient(-45deg,#ccc 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#ccc 75%),linear-gradient(-45deg,transparent 75%,#ccc 75%);background-size:16px 16px;background-position:0 0,0 8px,8px -8px,-8px 0px}.ngx-ie-crop-box{position:absolute;box-sizing:border-box;border:2px solid #2563eb;box-shadow:0 0 0 9999px #00000073;cursor:move;touch-action:none}.ngx-ie-handle{position:absolute;inline-size:14px;block-size:14px;background:#fff;border:2px solid #2563eb;border-radius:50%;touch-action:none}.ngx-ie-handle--nw{inset-inline-start:-7px;inset-block-start:-7px;cursor:nwse-resize}.ngx-ie-handle--ne{inset-inline-end:-7px;inset-block-start:-7px;cursor:nesw-resize}.ngx-ie-handle--sw{inset-inline-start:-7px;inset-block-end:-7px;cursor:nesw-resize}.ngx-ie-handle--se{inset-inline-end:-7px;inset-block-end:-7px;cursor:nwse-resize}.ngx-ie-panel{flex:1;display:flex;flex-direction:column;gap:.75rem}.ngx-ie-panel-row{display:flex;flex-wrap:wrap;gap:1.25rem}.ngx-ie-preview{display:flex;align-items:center;justify-content:center;min-block-size:100px;background:light-dark(#f3f4f6,#18181b);border-radius:8px;overflow:hidden}.ngx-ie-preview img{max-inline-size:100%;max-block-size:160px;display:block;background:#fff;background-image:linear-gradient(45deg,#ccc 25%,transparent 25%),linear-gradient(-45deg,#ccc 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#ccc 75%),linear-gradient(-45deg,transparent 75%,#ccc 75%);background-size:16px 16px;background-position:0 0,0 8px,8px -8px,-8px 0px}.ngx-ie-field{display:flex;gap:.3rem;align-items:flex-end}.ngx-ie-field slider{flex:1}.ngx-ie-row{display:flex;gap:.5rem}.ngx-ie-rotate-row button,.ngx-ie-filter-row button{appearance:none;border:1px solid light-dark(#e5e7eb,#33333a);background:light-dark(#ffffff,#232327);color:light-dark(#374151,#d4d4d8);border-radius:999px;padding:.4rem .85rem;font-size:.75rem;cursor:pointer;transition:background-color .15s ease,border-color .15s ease,transform .15s ease,color .15s ease}.ngx-ie-rotate-row button:hover,.ngx-ie-filter-row button:hover{background:light-dark(#f3f4f6,#2c2c31);transform:translateY(-1px)}.ngx-ie-rotate-row button:active,.ngx-ie-filter-row button:active{transform:translateY(0)}.ngx-ie-rotate-row button.active,.ngx-ie-filter-row button.active{background:light-dark(#2563eb,#3b82f6);border-color:light-dark(#2563eb,#3b82f6);color:#fff;box-shadow:0 2px 10px light-dark(rgba(37,99,235,.3),rgba(59,130,246,.3))}.ngx-ie-filter-row{display:flex;flex-wrap:wrap;gap:.4rem}.ngx-ie-actions{margin-block-start:auto;justify-content:flex-end}.ngx-ie-btn-primary,.ngx-ie-btn-secondary{appearance:none;border:none;border-radius:8px;padding:.55rem 1.1rem;font-size:.85rem;cursor:pointer;font-weight:500;transition:transform .15s ease,box-shadow .15s ease,opacity .15s ease}.ngx-ie-btn-primary:hover,.ngx-ie-btn-secondary:hover{transform:translateY(-1px)}.ngx-ie-btn-primary:active,.ngx-ie-btn-secondary:active{transform:translateY(0)}.ngx-ie-btn-primary{background:light-dark(#2563eb,#3b82f6);color:#fff;box-shadow:0 2px 10px light-dark(rgba(37,99,235,.25),rgba(59,130,246,.25))}.ngx-ie-btn-primary:disabled{opacity:.6;cursor:not-allowed;transform:none}.ngx-ie-btn-secondary{background:light-dark(#e5e7eb,#3f3f46);color:light-dark(#374151,#e4e4e7)}@media(max-width:768px){:host{height:unset!important}.ngx-ie-layout{display:flex;flex-direction:column}}\n"] }]
|
|
581
|
+
}], ctorParameters: () => [], propDecorators: { source: [{ type: i0.Input, args: [{ isSignal: true, alias: "source", required: false }] }], aspectRatio: [{ type: i0.Input, args: [{ isSignal: true, alias: "aspectRatio", required: false }] }], outputMaxWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "outputMaxWidth", required: false }] }], outputMaxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "outputMaxHeight", required: false }] }], outputType: [{ type: i0.Input, args: [{ isSignal: true, alias: "outputType", required: false }] }], filters: [{ type: i0.Input, args: [{ isSignal: true, alias: "filters", required: false }] }], quality: [{ type: i0.Input, args: [{ isSignal: true, alias: "quality", required: false }] }], localize: [{ type: i0.Input, args: [{ isSignal: true, alias: "localize", required: false }] }], saved: [{ type: i0.Output, args: ["saved"] }], cancelled: [{ type: i0.Output, args: ["cancelled"] }], stageWrapEl: [{ type: i0.ViewChild, args: ['stageWrap', { isSignal: true }] }] } });
|
|
518
582
|
|
|
519
583
|
/**
|
|
520
584
|
* Generated bundle index. Do not edit.
|
|
521
585
|
*/
|
|
522
586
|
|
|
523
|
-
export { NgxImageEditorComponent, NgxPointerDragDirective, applyCartoonEffect, canvasToBlob, createWorkingCopy, fitWithin, loadImage, renderComposite, renderRotated };
|
|
587
|
+
export { DEFAULT_NGX_IMAGE_EDITOR_LOCALIZATION, NGX_IMAGE_EDITOR_LOCALIZATION, NgxImageEditorComponent, NgxImageEditorLocalization, NgxPointerDragDirective, applyCartoonEffect, canvasToBlob, createWorkingCopy, fitWithin, loadImage, renderComposite, renderRotated };
|
|
524
588
|
//# sourceMappingURL=ngx-kit-image-editor.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngx-kit-image-editor.mjs","sources":["../../../projects/libs/image-editor/directives/pointer-drag.directive.ts","../../../projects/libs/image-editor/utils/image-io.ts","../../../projects/libs/image-editor/utils/cartoonify.ts","../../../projects/libs/image-editor/utils/render-pipeline.ts","../../../projects/libs/image-editor/types/localization.ts","../../../projects/libs/image-editor/components/image-editor.component.ts","../../../projects/libs/image-editor/components/image-editor.component.html","../../../projects/libs/image-editor/ngx-kit-image-editor.ts"],"sourcesContent":["import { Directive, HostListener, output } from '@angular/core';\n\nexport interface NgxPointerDragDelta {\n dx: number;\n dy: number;\n}\n\n/**\n * درگ عمومی روی پایهی Pointer Events + setPointerCapture (دقیقاً همون\n * تکنیکی که در ngx-kit/data-table برای ریسایز ستون استفاده شده) — نیازی به\n * listener سطح document نداره چون بعد از setPointerCapture، رویدادهای\n * pointermove/pointerup حتی بیرون از محدودهی المنت هم به خودش میرسن.\n *\n * dx/dy تجمعی از لحظهی pointerdown هستن (نه دلتای بین دو move متوالی)، چون\n * معمولاً مصرفکننده میخواد «موقعیت شروع + دلتای کل» رو حساب کنه، نه جمع\n * تدریجی گرد شوندهی دلتاهای ریز.\n */\n@Directive({\n selector: '[ngxPointerDrag]',\n standalone: true,\n})\nexport class NgxPointerDragDirective {\n dragStart = output<void>();\n dragMove = output<NgxPointerDragDelta>();\n dragEnd = output<void>();\n\n private dragging = false;\n private startX = 0;\n private startY = 0;\n\n @HostListener('pointerdown', ['$event'])\n onPointerDown(ev: PointerEvent): void {\n ev.preventDefault();\n ev.stopPropagation();\n this.dragging = true;\n this.startX = ev.clientX;\n this.startY = ev.clientY;\n (ev.target as HTMLElement).setPointerCapture(ev.pointerId);\n this.dragStart.emit();\n }\n\n @HostListener('pointermove', ['$event'])\n onPointerMove(ev: PointerEvent): void {\n if (!this.dragging) return;\n this.dragMove.emit({ dx: ev.clientX - this.startX, dy: ev.clientY - this.startY });\n }\n\n @HostListener('pointerup')\n @HostListener('pointercancel')\n onPointerUp(): void {\n if (!this.dragging) return;\n this.dragging = false;\n this.dragEnd.emit();\n }\n}\n","/** یه File/Blob/data-URL/URL رو به یک HTMLImageElement بارگذاریشده تبدیل میکنه */\nexport function loadImage(source: File | Blob | string): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n // برای URLهای cross-origin لازم میشه، وگرنه canvas بعداً «tainted» میشه\n // و toBlob/toDataURL با SecurityError شکست میخوره.\n img.crossOrigin = 'anonymous';\n\n const objectUrl = typeof source === 'string' ? null : URL.createObjectURL(source);\n const url = objectUrl ?? (source as string);\n\n img.onload = () => {\n if (objectUrl) URL.revokeObjectURL(objectUrl);\n resolve(img);\n };\n img.onerror = () => {\n if (objectUrl) URL.revokeObjectURL(objectUrl);\n reject(new Error('Failed to load image'));\n };\n img.src = url;\n });\n}\n\n/** canvas.toBlob بهصورت Promise، بههمراه fallback برای مرورگرهای قدیمیتر */\nexport function canvasToBlob(\n canvas: HTMLCanvasElement,\n type = 'image/jpeg',\n quality = 0.92,\n): Promise<Blob> {\n return new Promise((resolve, reject) => {\n canvas.toBlob(\n (blob) => {\n if (blob) resolve(blob);\n else reject(new Error('Failed to convert canvas to blob'));\n },\n type,\n quality,\n );\n });\n}\n\n/**\n * یه کپیِ کوچیکشده از تصویر اصلی میسازه که کل UI ویرایشگر (چرخش، کراپ،\n * پیشنمایش فیلترها/کارتونی) روی همین کار میکنه، نه روی تصویر اصلی که\n * ممکنه چند مگاپیکسل باشه. این باعث میشه درگکردنِ اسلایدرها یا لبههای\n * کراپ روون بمونه؛ خروجی نهایی (save) همیشه از روی تصویر اصلیِ کامل رندر\n * میشه، نه از روی این کپی.\n */\nexport function createWorkingCopy(img: HTMLImageElement, maxSize = 1200): HTMLCanvasElement {\n const { width, height } = fitWithin(img.naturalWidth, img.naturalHeight, maxSize, maxSize);\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext('2d')!;\n ctx.drawImage(img, 0, 0, width, height);\n return canvas;\n}\n\n/** ابعاد جدید رو طوری حساب میکنه که از maxWidth/maxHeight بیشتر نشه، با حفظ نسبت تصویر */\nexport function fitWithin(\n width: number,\n height: number,\n maxWidth?: number,\n maxHeight?: number,\n): { width: number; height: number } {\n if (!maxWidth && !maxHeight) return { width, height };\n let ratio = 1;\n if (maxWidth) ratio = Math.min(ratio, maxWidth / width);\n if (maxHeight) ratio = Math.min(ratio, maxHeight / height);\n if (ratio >= 1) return { width, height };\n return { width: Math.round(width * ratio), height: Math.round(height * ratio) };\n}\n","/**\n * افکت «کارتونی»: چون ctx.filter استاندارد چیزی شبیه cartoon نداره (فقط\n * brightness/contrast/saturate/grayscale/sepia/invert/blur/hue-rotate)، این\n * یکی رو واقعاً با پردازش پیکسلی پیاده کردیم؛ دو مرحله:\n *\n * ۱) Posterize: هر کانال رنگ به تعداد محدودی سطح گرد میشه (پهنههای رنگیِ\n * صاف و یکدست، حسِ کارتونی رنگ میده).\n * ۲) لبهیابی Sobel روی نسخهی خاکستریِ تصویر: هرجا شدت لبه از حد آستانه\n * بیشتر باشه، پیکسل تیره میشه (حسِ خط دور کارتونی).\n *\n * روی خودِ ImageData کار میکنه، پس هزینهش با اندازهی تصویر خطیست؛ برای\n * تصاویر خیلی بزرگ (>~3000px) بهتره قبلش resize بشه (که در کامپوننت اصلی\n * با fitWithin قبل از اعمال فیلتر انجام میشه).\n */\nexport function applyCartoonEffect(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n options: { levels?: number; edgeThreshold?: number } = {},\n): void {\n const levels = options.levels ?? 5;\n const edgeThreshold = options.edgeThreshold ?? 80;\n\n const imageData = ctx.getImageData(0, 0, width, height);\n const src = imageData.data;\n\n // ۱) خاکستری برای Sobel\n const gray = new Uint8ClampedArray(width * height);\n for (let i = 0, p = 0; i < src.length; i += 4, p++) {\n gray[p] = (src[i] * 0.299 + src[i + 1] * 0.587 + src[i + 2] * 0.114) | 0;\n }\n\n // ۲) Posterize رنگها\n const step = 255 / (levels - 1);\n for (let i = 0; i < src.length; i += 4) {\n src[i] = Math.round(Math.round(src[i] / step) * step);\n src[i + 1] = Math.round(Math.round(src[i + 1] / step) * step);\n src[i + 2] = Math.round(Math.round(src[i + 2] / step) * step);\n }\n\n // ۳) Sobel روی gray، خط دور تیره روی src\n const gxKernel = [-1, 0, 1, -2, 0, 2, -1, 0, 1];\n const gyKernel = [-1, -2, -1, 0, 0, 0, 1, 2, 1];\n\n for (let y = 1; y < height - 1; y++) {\n for (let x = 1; x < width - 1; x++) {\n let gx = 0;\n let gy = 0;\n let k = 0;\n for (let dy = -1; dy <= 1; dy++) {\n for (let dx = -1; dx <= 1; dx++) {\n const v = gray[(y + dy) * width + (x + dx)];\n gx += v * gxKernel[k];\n gy += v * gyKernel[k];\n k++;\n }\n }\n const magnitude = Math.sqrt(gx * gx + gy * gy);\n if (magnitude > edgeThreshold) {\n const idx = (y * width + x) * 4;\n src[idx] = 20;\n src[idx + 1] = 20;\n src[idx + 2] = 20;\n }\n }\n }\n\n ctx.putImageData(imageData, 0, 0);\n}\n","import { NgxCropRect, NgxImageEditorAdjustments } from '../contracts/image-editor-types';\nimport { applyCartoonEffect } from './cartoonify';\nimport { fitWithin } from './image-io';\n\n/** تصویر مبدأ رو با زاویهی دادهشده روی یه canvas جدید (به اندازهی bounding-box نتیجه) میچرخونه */\nexport function renderRotated(\n source: CanvasImageSource,\n width: number,\n height: number,\n degrees: number,\n): HTMLCanvasElement {\n const rad = (degrees * Math.PI) / 180;\n const sin = Math.abs(Math.sin(rad));\n const cos = Math.abs(Math.cos(rad));\n const newW = Math.max(1, Math.round(width * cos + height * sin));\n const newH = Math.max(1, Math.round(width * sin + height * cos));\n\n const canvas = document.createElement('canvas');\n canvas.width = newW;\n canvas.height = newH;\n const ctx = canvas.getContext('2d')!;\n ctx.translate(newW / 2, newH / 2);\n ctx.rotate(rad);\n ctx.drawImage(source, -width / 2, -height / 2, width, height);\n return canvas;\n}\n\nfunction buildCssFilter(adjustments: NgxImageEditorAdjustments): string {\n const parts = [\n `brightness(${adjustments.brightness}%)`,\n `contrast(${adjustments.contrast}%)`,\n `saturate(${adjustments.saturation}%)`,\n ];\n if (adjustments.filter === 'grayscale') parts.push('grayscale(1)');\n if (adjustments.filter === 'sepia') parts.push('sepia(1)');\n if (adjustments.filter === 'invert') parts.push('invert(1)');\n return parts.join(' ');\n}\n\n/**\n * کراپ + فیلترها رو روی یه canvas خروجی میسازه. brightness/contrast/\n * saturation/grayscale/sepia/invert همه با ctx.filter بومیِ Canvas 2D انجام\n * میشن (شتابدهیشده توسط مرورگر، بدون حلقهی پیکسلی دستی)؛ فقط cartoon\n * (که معادل بومی نداره) با پردازش پیکسلی جدا انجام میشه.\n *\n * maxWidth/maxHeight برای دو حالت استفاده میشه: پیشنمایش زنده (عدد کوچیک،\n * برای واکنشگرا موندن حین کشیدن اسلایدرها) و خروجی نهایی (بدون محدودیت یا\n * محدودیت دلخواه کاربر).\n */\nexport function renderComposite(\n source: CanvasImageSource,\n sourceWidth: number,\n sourceHeight: number,\n crop: NgxCropRect,\n adjustments: NgxImageEditorAdjustments,\n maxWidth?: number,\n maxHeight?: number,\n): HTMLCanvasElement {\n const { width: outW, height: outH } = fitWithin(crop.width, crop.height, maxWidth, maxHeight);\n\n const canvas = document.createElement('canvas');\n canvas.width = Math.max(1, outW);\n canvas.height = Math.max(1, outH);\n const ctx = canvas.getContext('2d')!;\n\n ctx.filter = buildCssFilter(adjustments);\n ctx.drawImage(source, crop.x, crop.y, crop.width, crop.height, 0, 0, canvas.width, canvas.height);\n ctx.filter = 'none';\n\n if (adjustments.filter === 'cartoon') {\n applyCartoonEffect(ctx, canvas.width, canvas.height);\n }\n\n return canvas;\n}\n","import { InjectionToken } from '@angular/core';\r\n\r\nexport const NGX_IMAGE_EDITOR_LOCALIZATION = new InjectionToken<NgxImageEditorLocalization>(\r\n 'ngx-image-localization',\r\n {\r\n factory: () => DEFAULT_NGX_IMAGE_EDITOR_LOCALIZATION,\r\n },\r\n);\r\n\r\nexport class NgxImageEditorLocalization {\r\n LoadingImage = 'Loading image…';\r\n Rotation = 'Fine rotation';\r\n Brightness = 'Brightness';\r\n Contrast = 'Contrast';\r\n Saturation = 'Saturation';\r\n Filter = 'Filter';\r\n None = 'None';\r\n Grayscale = 'Grayscale';\r\n Sepia = 'Sepia';\r\n Invert = 'Invert';\r\n Cartoon = 'Cartoon';\r\n Cancel = 'Cancel';\r\n Save = 'Save';\r\n Saving = 'Saving…';\r\n}\r\nexport const DEFAULT_NGX_IMAGE_EDITOR_LOCALIZATION = new NgxImageEditorLocalization();\r\n","import {\n ChangeDetectionStrategy,\n Component,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { SliderComponent } from 'ngx-kit/shared';\nimport {\n NgxCropRect,\n NgxImageEditorAdjustments,\n NgxImageEditorResult,\n NgxImageFilterPreset,\n} from '../contracts/image-editor-types';\nimport { NgxPointerDragDelta, NgxPointerDragDirective } from '../directives/pointer-drag.directive';\nimport { canvasToBlob, createWorkingCopy, loadImage } from '../utils/image-io';\nimport { renderComposite, renderRotated } from '../utils/render-pipeline';\nimport { Corner } from '../types/Corner';\nimport { NGX_IMAGE_EDITOR_LOCALIZATION, NgxImageEditorLocalization } from '../types/localization';\n\n/**\n * ویرایشگر تصویر: کراپ + چرخش + روشنایی/کنتراست/اشباع + فیلترهای آماده\n * (سیاهوسفید، سپیا، معکوس، کارتونی) + فشردهسازی خروجی. کاملاً روی Canvas\n * خام پیاده شده، بدون هیچ وابستگی خارجیای.\n *\n * نکتهی مهمِ معماری: تمام تعامل زنده (چرخوندن، جابهجا/ریسایز کراپباکس،\n * پیشنمایش فیلترها حتی کارتونی) روی یه کپیِ کوچیکشده از تصویر انجام میشه\n * (createWorkingCopy)، نه روی تصویر اصلی که ممکنه چند مگاپیکسل باشه — وگرنه\n * درگکردن اسلایدرها/گوشههای کراپ رو کاربر حس تاخیر میکرد. فقط لحظهی\n * save()، رندر نهایی از روی تصویر اصلیِ کامل انجام میشه.\n */\n@Component({\n selector: 'ngx-image-editor',\n standalone: true,\n imports: [FormsModule, SliderComponent, NgxPointerDragDirective],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './image-editor.component.html',\n styleUrl: './image-editor.component.scss',\n host: { class: 'ngx-image-editor-host' },\n})\nexport class NgxImageEditorComponent {\n source = input<File | Blob | string | null>(null);\n /** قفل نسبتِ کراپ (مثلاً ۱ برای آواتار مربعی)؛ undefined یعنی آزاد */\n aspectRatio = input<number | undefined>(undefined);\n outputMaxWidth = input<number | undefined>(undefined);\n outputMaxHeight = input<number | undefined>(undefined);\n outputType = input<'image/jpeg' | 'image/png' | 'image/webp'>('image/jpeg');\n /** حداکثر عرض نمایشِ ناحیهی کراپ روی صفحه (پیکسل) */\n displayMaxWidth = input<number>(420);\n quality = input(0.92);\n\n defaultLocalization = inject(NGX_IMAGE_EDITOR_LOCALIZATION);\n localize = input<NgxImageEditorLocalization>(this.defaultLocalization);\n\n saved = output<NgxImageEditorResult>();\n cancelled = output<void>();\n\n protected readonly loading = signal(false);\n protected readonly saving = signal(false);\n protected readonly loadError = signal<string | null>(null);\n\n private readonly originalImage = signal<HTMLImageElement | null>(null);\n private readonly workingCanvas = signal<HTMLCanvasElement | null>(null);\n\n protected readonly rotation = signal(0);\n protected readonly brightness = signal(100);\n protected readonly contrast = signal(100);\n protected readonly saturation = signal(100);\n protected readonly filterPreset = signal<NgxImageFilterPreset>('none');\n\n protected readonly crop = signal<NgxCropRect>({ x: 0, y: 0, width: 0, height: 0 });\n\n protected readonly adjustments = computed<NgxImageEditorAdjustments>(() => ({\n brightness: this.brightness(),\n contrast: this.contrast(),\n saturation: this.saturation(),\n rotation: this.rotation(),\n filter: this.filterPreset(),\n }));\n\n /** تصویرِ (کوچیکشدهیِ) چرخیده — پایهی نمایش صحنهی کراپ */\n protected readonly rotatedWorkingCanvas = computed(() => {\n const wc = this.workingCanvas();\n if (!wc) return null;\n return renderRotated(wc, wc.width, wc.height, this.rotation());\n });\n\n protected readonly displayScale = computed(() => {\n const rc = this.rotatedWorkingCanvas();\n if (!rc) return 1;\n return Math.min(1, this.displayMaxWidth() / rc.width);\n });\n\n protected readonly stageImageUrl = computed(() => {\n const rc = this.rotatedWorkingCanvas();\n return rc ? rc.toDataURL('image/png') : null;\n });\n\n protected readonly stageSize = computed(() => {\n const rc = this.rotatedWorkingCanvas();\n const scale = this.displayScale();\n return rc ? { width: rc.width * scale, height: rc.height * scale } : { width: 0, height: 0 };\n });\n\n protected readonly cropOverlayStyle = computed(() => {\n const scale = this.displayScale();\n const c = this.crop();\n return {\n left: `${c.x * scale}px`,\n top: `${c.y * scale}px`,\n width: `${c.width * scale}px`,\n height: `${c.height * scale}px`,\n };\n });\n\n /** پیشنمایش نهایی (کوچیک، حداکثر ۴۸۰ پیکسل) — شامل همهچیز، حتی افکت کارتونی */\n protected readonly previewUrl = computed(() => {\n const rc = this.rotatedWorkingCanvas();\n const c = this.crop();\n if (!rc || c.width <= 0 || c.height <= 0) return null;\n const canvas = renderComposite(rc, rc.width, rc.height, c, this.adjustments(), 480, 480);\n return canvas.toDataURL('image/png');\n });\n\n private moveSnapshot: NgxCropRect | null = null;\n private resizeSnapshot: NgxCropRect | null = null;\n\n constructor() {\n // بارگذاری تصویر هروقت source عوض بشه\n effect(() => {\n const src = this.source();\n if (!src) {\n this.originalImage.set(null);\n this.workingCanvas.set(null);\n return;\n }\n this.loading.set(true);\n this.loadError.set(null);\n loadImage(src)\n .then((img) => {\n this.originalImage.set(img);\n this.workingCanvas.set(createWorkingCopy(img));\n this.resetAdjustments();\n })\n .catch((err) => this.loadError.set(err?.message ?? 'Failed to load image'))\n .finally(() => this.loading.set(false));\n });\n\n // هر وقت چرخیدهشده عوض بشه (بارگذاریِ تصویر جدید یا چرخش)، کراپ روی کل قاب ریست بشه\n effect(() => {\n const rc = this.rotatedWorkingCanvas();\n if (rc) {\n this.crop.set({ x: 0, y: 0, width: rc.width, height: rc.height });\n }\n });\n }\n\n private resetAdjustments(): void {\n this.rotation.set(0);\n this.brightness.set(100);\n this.contrast.set(100);\n this.saturation.set(100);\n this.filterPreset.set('none');\n }\n\n protected rotateBy(delta: number): void {\n this.rotation.update((r) => {\n let next = r + delta;\n if (next > 180) next -= 360;\n if (next < -180) next += 360;\n return next;\n });\n }\n\n protected setFilter(preset: NgxImageFilterPreset): void {\n this.filterPreset.set(preset);\n }\n\n // ---------- درگ جابهجاییِ کل کراپباکس ----------\n protected onMoveDragStart(): void {\n this.moveSnapshot = { ...this.crop() };\n }\n\n protected onMoveDragMove(delta: NgxPointerDragDelta): void {\n const rc = this.rotatedWorkingCanvas();\n const snap = this.moveSnapshot;\n if (!rc || !snap) return;\n const scale = this.displayScale();\n const dxSrc = delta.dx / scale;\n const dySrc = delta.dy / scale;\n const maxX = Math.max(0, rc.width - snap.width);\n const maxY = Math.max(0, rc.height - snap.height);\n const x = Math.min(Math.max(0, snap.x + dxSrc), maxX);\n const y = Math.min(Math.max(0, snap.y + dySrc), maxY);\n this.crop.set({ ...snap, x, y });\n }\n\n // ---------- درگ ریسایز از گوشهها ----------\n protected onResizeDragStart(): void {\n this.resizeSnapshot = { ...this.crop() };\n }\n\n protected onResizeDragMove(corner: Corner, delta: NgxPointerDragDelta): void {\n const rc = this.rotatedWorkingCanvas();\n const snap = this.resizeSnapshot;\n if (!rc || !snap) return;\n\n const scale = this.displayScale();\n const dxSrc = delta.dx / scale;\n const dySrc = delta.dy / scale;\n const minSize = 24;\n\n let { x, y, width, height } = snap;\n\n if (corner === 'nw' || corner === 'sw') {\n const newX = Math.min(snap.x + dxSrc, snap.x + snap.width - minSize);\n x = Math.max(0, newX);\n width = snap.x + snap.width - x;\n }\n if (corner === 'ne' || corner === 'se') {\n width = Math.min(Math.max(minSize, snap.width + dxSrc), rc.width - snap.x);\n }\n if (corner === 'nw' || corner === 'ne') {\n const newY = Math.min(snap.y + dySrc, snap.y + snap.height - minSize);\n y = Math.max(0, newY);\n height = snap.y + snap.height - y;\n }\n if (corner === 'sw' || corner === 'se') {\n height = Math.min(Math.max(minSize, snap.height + dySrc), rc.height - snap.y);\n }\n\n const ratio = this.aspectRatio();\n if (ratio) {\n height = width / ratio;\n }\n\n this.crop.set({ x, y, width, height });\n }\n\n protected cancel(): void {\n this.cancelled.emit();\n }\n\n async save(): Promise<void> {\n const original = this.originalImage();\n const working = this.workingCanvas();\n if (!original || !working) return;\n\n this.saving.set(true);\n try {\n // نسبت مقیاس بین کپیِ کوچیکشده (که کراپ/چرخش روش تعریف شده) و تصویر\n // اصلیِ کامل. چون createWorkingCopy مقیاس یکنواخت (همجهت) اعمال\n // میکنه، همین یه ضریب برای هر دو بعد و بعد از چرخش هم معتبر میمونه.\n const scaleToOriginal = original.naturalWidth / working.width;\n\n const rotatedFull = renderRotated(\n original,\n original.naturalWidth,\n original.naturalHeight,\n this.rotation(),\n );\n\n const c = this.crop();\n const cropInFullRes: NgxCropRect = {\n x: c.x * scaleToOriginal,\n y: c.y * scaleToOriginal,\n width: c.width * scaleToOriginal,\n height: c.height * scaleToOriginal,\n };\n\n const finalCanvas = renderComposite(\n rotatedFull,\n rotatedFull.width,\n rotatedFull.height,\n cropInFullRes,\n this.adjustments(),\n this.outputMaxWidth(),\n this.outputMaxHeight(),\n );\n\n const type = this.outputType();\n const blob = await canvasToBlob(finalCanvas, type, this.quality());\n const dataUrl = finalCanvas.toDataURL(type, this.quality());\n this.saved.emit({ blob, dataUrl, width: finalCanvas.width, height: finalCanvas.height });\n } finally {\n this.saving.set(false);\n }\n }\n}\n","@if (loading()) {\n <div class=\"ngx-ie-state\">{{ localize().LoadingImage }}</div>\n} @else if (loadError()) {\n <div class=\"ngx-ie-state ngx-ie-state--error\">{{ loadError() }}</div>\n} @else if (stageImageUrl()) {\n <div class=\"ngx-ie-layout\">\n <div class=\"ngx-ie-stage-wrap\">\n <div\n class=\"ngx-ie-stage\"\n [style.width.px]=\"stageSize().width\"\n [style.height.px]=\"stageSize().height\">\n <img class=\"ngx-ie-stage-img\" [src]=\"stageImageUrl()\" alt=\"\" draggable=\"false\" />\n\n <div\n class=\"ngx-ie-crop-box\"\n [style.left]=\"cropOverlayStyle().left\"\n [style.top]=\"cropOverlayStyle().top\"\n [style.width]=\"cropOverlayStyle().width\"\n [style.height]=\"cropOverlayStyle().height\"\n ngxPointerDrag\n (dragStart)=\"onMoveDragStart()\"\n (dragMove)=\"onMoveDragMove($event)\">\n <span\n class=\"ngx-ie-handle ngx-ie-handle--nw\"\n ngxPointerDrag\n (dragStart)=\"onResizeDragStart()\"\n (dragMove)=\"onResizeDragMove('nw', $event)\"></span>\n <span\n class=\"ngx-ie-handle ngx-ie-handle--ne\"\n ngxPointerDrag\n (dragStart)=\"onResizeDragStart()\"\n (dragMove)=\"onResizeDragMove('ne', $event)\"></span>\n <span\n class=\"ngx-ie-handle ngx-ie-handle--sw\"\n ngxPointerDrag\n (dragStart)=\"onResizeDragStart()\"\n (dragMove)=\"onResizeDragMove('sw', $event)\"></span>\n <span\n class=\"ngx-ie-handle ngx-ie-handle--se\"\n ngxPointerDrag\n (dragStart)=\"onResizeDragStart()\"\n (dragMove)=\"onResizeDragMove('se', $event)\"></span>\n </div>\n </div>\n </div>\n\n <div class=\"ngx-ie-panel\">\n <div class=\"ngx-ie-preview\">\n @if (previewUrl(); as url) {\n <img [src]=\"url\" alt=\"Preview\" />\n }\n </div>\n\n <div class=\"ngx-ie-row ngx-ie-rotate-row\">\n <button type=\"button\" (click)=\"rotateBy(-90)\" title=\"Rotate 90° left\">⟲ 90</button>\n <button type=\"button\" (click)=\"rotateBy(90)\" title=\"Rotate 90° right\">⟳ 90</button>\n </div>\n\n <label class=\"ngx-ie-field\">\n <span>{{ localize().Rotation }} ({{ rotation() }}°)</span>\n <slider\n [ngModel]=\"rotation()\"\n (ngModelChange)=\"rotation.set($event)\"\n [min]=\"-180\"\n [max]=\"180\"></slider>\n </label>\n\n <label class=\"ngx-ie-field\">\n <span>{{ localize().Brightness }} ({{ brightness() }}%)</span>\n <slider\n [ngModel]=\"brightness()\"\n (ngModelChange)=\"brightness.set($event)\"\n [min]=\"0\"\n [max]=\"200\"></slider>\n </label>\n\n <label class=\"ngx-ie-field\">\n <span>{{ localize().Contrast }} ({{ contrast() }}%)</span>\n <slider\n [ngModel]=\"contrast()\"\n (ngModelChange)=\"contrast.set($event)\"\n [min]=\"0\"\n [max]=\"200\"></slider>\n </label>\n\n <label class=\"ngx-ie-field\">\n <span>{{ localize().Saturation }} ({{ saturation() }}%)</span>\n <slider\n [ngModel]=\"saturation()\"\n (ngModelChange)=\"saturation.set($event)\"\n [min]=\"0\"\n [max]=\"200\"></slider>\n </label>\n\n <div class=\"ngx-ie-field\">\n <span>{{ localize().Filter }}</span>\n <div class=\"ngx-ie-filter-row\">\n <button\n type=\"button\"\n [class.active]=\"filterPreset() === 'none'\"\n (click)=\"setFilter('none')\">\n {{ localize().None }}\n </button>\n <button\n type=\"button\"\n [class.active]=\"filterPreset() === 'grayscale'\"\n (click)=\"setFilter('grayscale')\">\n {{ localize().Grayscale }}\n </button>\n <button\n type=\"button\"\n [class.active]=\"filterPreset() === 'sepia'\"\n (click)=\"setFilter('sepia')\">\n {{ localize().Sepia }}\n </button>\n <button\n type=\"button\"\n [class.active]=\"filterPreset() === 'invert'\"\n (click)=\"setFilter('invert')\">\n {{ localize().Invert }}\n </button>\n <button\n type=\"button\"\n [class.active]=\"filterPreset() === 'cartoon'\"\n (click)=\"setFilter('cartoon')\">\n {{ localize().Cartoon }}\n </button>\n </div>\n </div>\n\n <div class=\"ngx-ie-row ngx-ie-actions\">\n <button type=\"button\" class=\"ngx-ie-btn-secondary\" (click)=\"cancel()\">\n {{ localize().Cancel }}\n </button>\n <button type=\"button\" class=\"ngx-ie-btn-primary\" [disabled]=\"saving()\" (click)=\"save()\">\n {{ saving() ? localize().Saving : localize().Save }}\n </button>\n </div>\n </div>\n </div>\n}\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":"ngx-kit-image-editor.mjs","sources":["../../../projects/libs/image-editor/directives/pointer-drag.directive.ts","../../../projects/libs/image-editor/utils/image-io.ts","../../../projects/libs/image-editor/utils/cartoonify.ts","../../../projects/libs/image-editor/utils/render-pipeline.ts","../../../projects/libs/image-editor/tokens/localization.ts","../../../projects/libs/image-editor/components/image-editor.component.ts","../../../projects/libs/image-editor/components/image-editor.component.html","../../../projects/libs/image-editor/ngx-kit-image-editor.ts"],"sourcesContent":["import { Directive, HostListener, output } from '@angular/core';\n\nexport interface NgxPointerDragDelta {\n dx: number;\n dy: number;\n}\n\n/**\n * درگ عمومی روی پایهی Pointer Events + setPointerCapture (دقیقاً همون\n * تکنیکی که در ngx-kit/data-table برای ریسایز ستون استفاده شده) — نیازی به\n * listener سطح document نداره چون بعد از setPointerCapture، رویدادهای\n * pointermove/pointerup حتی بیرون از محدودهی المنت هم به خودش میرسن.\n *\n * dx/dy تجمعی از لحظهی pointerdown هستن (نه دلتای بین دو move متوالی)، چون\n * معمولاً مصرفکننده میخواد «موقعیت شروع + دلتای کل» رو حساب کنه، نه جمع\n * تدریجی گرد شوندهی دلتاهای ریز.\n */\n@Directive({\n selector: '[ngxPointerDrag]',\n standalone: true,\n})\nexport class NgxPointerDragDirective {\n dragStart = output<void>();\n dragMove = output<NgxPointerDragDelta>();\n dragEnd = output<void>();\n\n private dragging = false;\n private startX = 0;\n private startY = 0;\n\n @HostListener('pointerdown', ['$event'])\n onPointerDown(ev: PointerEvent): void {\n ev.preventDefault();\n ev.stopPropagation();\n this.dragging = true;\n this.startX = ev.clientX;\n this.startY = ev.clientY;\n (ev.target as HTMLElement).setPointerCapture(ev.pointerId);\n this.dragStart.emit();\n }\n\n @HostListener('pointermove', ['$event'])\n onPointerMove(ev: PointerEvent): void {\n if (!this.dragging) return;\n this.dragMove.emit({ dx: ev.clientX - this.startX, dy: ev.clientY - this.startY });\n }\n\n @HostListener('pointerup')\n @HostListener('pointercancel')\n onPointerUp(): void {\n if (!this.dragging) return;\n this.dragging = false;\n this.dragEnd.emit();\n }\n}\n","/** یه File/Blob/data-URL/URL رو به یک HTMLImageElement بارگذاریشده تبدیل میکنه */\nexport function loadImage(source: File | Blob | string): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n // برای URLهای cross-origin لازم میشه، وگرنه canvas بعداً «tainted» میشه\n // و toBlob/toDataURL با SecurityError شکست میخوره.\n img.crossOrigin = 'anonymous';\n\n const objectUrl = typeof source === 'string' ? null : URL.createObjectURL(source);\n const url = objectUrl ?? (source as string);\n\n img.onload = () => {\n if (objectUrl) URL.revokeObjectURL(objectUrl);\n resolve(img);\n };\n img.onerror = () => {\n if (objectUrl) URL.revokeObjectURL(objectUrl);\n reject(new Error('Failed to load image'));\n };\n img.src = url;\n });\n}\n\n/** canvas.toBlob بهصورت Promise، بههمراه fallback برای مرورگرهای قدیمیتر */\nexport function canvasToBlob(\n canvas: HTMLCanvasElement,\n type = 'image/jpeg',\n quality = 0.92,\n): Promise<Blob> {\n return new Promise((resolve, reject) => {\n canvas.toBlob(\n (blob) => {\n if (blob) resolve(blob);\n else reject(new Error('Failed to convert canvas to blob'));\n },\n type,\n quality,\n );\n });\n}\n\n/**\n * یه کپیِ کوچیکشده از تصویر اصلی میسازه که کل UI ویرایشگر (چرخش، کراپ،\n * پیشنمایش فیلترها/کارتونی) روی همین کار میکنه، نه روی تصویر اصلی که\n * ممکنه چند مگاپیکسل باشه. این باعث میشه درگکردنِ اسلایدرها یا لبههای\n * کراپ روون بمونه؛ خروجی نهایی (save) همیشه از روی تصویر اصلیِ کامل رندر\n * میشه، نه از روی این کپی.\n */\nexport function createWorkingCopy(img: HTMLImageElement, maxSize = 1200): HTMLCanvasElement {\n const { width, height } = fitWithin(img.naturalWidth, img.naturalHeight, maxSize, maxSize);\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext('2d')!;\n ctx.drawImage(img, 0, 0, width, height);\n return canvas;\n}\n\n/** ابعاد جدید رو طوری حساب میکنه که از maxWidth/maxHeight بیشتر نشه، با حفظ نسبت تصویر */\nexport function fitWithin(\n width: number,\n height: number,\n maxWidth?: number,\n maxHeight?: number,\n): { width: number; height: number } {\n if (!maxWidth && !maxHeight) return { width, height };\n let ratio = 1;\n if (maxWidth) ratio = Math.min(ratio, maxWidth / width);\n if (maxHeight) ratio = Math.min(ratio, maxHeight / height);\n if (ratio >= 1) return { width, height };\n return { width: Math.round(width * ratio), height: Math.round(height * ratio) };\n}\n","/**\n * افکت «کارتونی»: چون ctx.filter استاندارد چیزی شبیه cartoon نداره (فقط\n * brightness/contrast/saturate/grayscale/sepia/invert/blur/hue-rotate)، این\n * یکی رو واقعاً با پردازش پیکسلی پیاده کردیم؛ دو مرحله:\n *\n * ۱) Posterize: هر کانال رنگ به تعداد محدودی سطح گرد میشه (پهنههای رنگیِ\n * صاف و یکدست، حسِ کارتونی رنگ میده).\n * ۲) لبهیابی Sobel روی نسخهی خاکستریِ تصویر: هرجا شدت لبه از حد آستانه\n * بیشتر باشه، پیکسل تیره میشه (حسِ خط دور کارتونی).\n *\n * روی خودِ ImageData کار میکنه، پس هزینهش با اندازهی تصویر خطیست؛ برای\n * تصاویر خیلی بزرگ (>~3000px) بهتره قبلش resize بشه (که در کامپوننت اصلی\n * با fitWithin قبل از اعمال فیلتر انجام میشه).\n */\nexport function applyCartoonEffect(\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n options: { levels?: number; edgeThreshold?: number } = {},\n): void {\n const levels = options.levels ?? 5;\n const edgeThreshold = options.edgeThreshold ?? 80;\n\n const imageData = ctx.getImageData(0, 0, width, height);\n const src = imageData.data;\n\n // ۱) خاکستری برای Sobel\n const gray = new Uint8ClampedArray(width * height);\n for (let i = 0, p = 0; i < src.length; i += 4, p++) {\n gray[p] = (src[i] * 0.299 + src[i + 1] * 0.587 + src[i + 2] * 0.114) | 0;\n }\n\n // ۲) Posterize رنگها\n const step = 255 / (levels - 1);\n for (let i = 0; i < src.length; i += 4) {\n src[i] = Math.round(Math.round(src[i] / step) * step);\n src[i + 1] = Math.round(Math.round(src[i + 1] / step) * step);\n src[i + 2] = Math.round(Math.round(src[i + 2] / step) * step);\n }\n\n // ۳) Sobel روی gray، خط دور تیره روی src\n const gxKernel = [-1, 0, 1, -2, 0, 2, -1, 0, 1];\n const gyKernel = [-1, -2, -1, 0, 0, 0, 1, 2, 1];\n\n for (let y = 1; y < height - 1; y++) {\n for (let x = 1; x < width - 1; x++) {\n let gx = 0;\n let gy = 0;\n let k = 0;\n for (let dy = -1; dy <= 1; dy++) {\n for (let dx = -1; dx <= 1; dx++) {\n const v = gray[(y + dy) * width + (x + dx)];\n gx += v * gxKernel[k];\n gy += v * gyKernel[k];\n k++;\n }\n }\n const magnitude = Math.sqrt(gx * gx + gy * gy);\n if (magnitude > edgeThreshold) {\n const idx = (y * width + x) * 4;\n src[idx] = 20;\n src[idx + 1] = 20;\n src[idx + 2] = 20;\n }\n }\n }\n\n ctx.putImageData(imageData, 0, 0);\n}\n","import { NgxCropRect, NgxImageEditorAdjustments } from '../contracts/image-editor-types';\nimport { applyCartoonEffect } from './cartoonify';\nimport { fitWithin } from './image-io';\n\n/** تصویر مبدأ رو با زاویهی دادهشده روی یه canvas جدید (به اندازهی bounding-box نتیجه) میچرخونه */\nexport function renderRotated(\n source: CanvasImageSource,\n width: number,\n height: number,\n degrees: number,\n): HTMLCanvasElement {\n const rad = (degrees * Math.PI) / 180;\n const sin = Math.abs(Math.sin(rad));\n const cos = Math.abs(Math.cos(rad));\n const newW = Math.max(1, Math.round(width * cos + height * sin));\n const newH = Math.max(1, Math.round(width * sin + height * cos));\n\n const canvas = document.createElement('canvas');\n canvas.width = newW;\n canvas.height = newH;\n const ctx = canvas.getContext('2d')!;\n ctx.translate(newW / 2, newH / 2);\n ctx.rotate(rad);\n ctx.drawImage(source, -width / 2, -height / 2, width, height);\n return canvas;\n}\n\nfunction buildCssFilter(adjustments: NgxImageEditorAdjustments): string {\n const parts = [\n `brightness(${adjustments.brightness}%)`,\n `contrast(${adjustments.contrast}%)`,\n `saturate(${adjustments.saturation}%)`,\n ];\n if (adjustments.filter === 'grayscale') parts.push('grayscale(1)');\n if (adjustments.filter === 'sepia') parts.push('sepia(1)');\n if (adjustments.filter === 'invert') parts.push('invert(1)');\n return parts.join(' ');\n}\n\n/**\n * کراپ + فیلترها رو روی یه canvas خروجی میسازه. brightness/contrast/\n * saturation/grayscale/sepia/invert همه با ctx.filter بومیِ Canvas 2D انجام\n * میشن (شتابدهیشده توسط مرورگر، بدون حلقهی پیکسلی دستی)؛ فقط cartoon\n * (که معادل بومی نداره) با پردازش پیکسلی جدا انجام میشه.\n *\n * maxWidth/maxHeight برای دو حالت استفاده میشه: پیشنمایش زنده (عدد کوچیک،\n * برای واکنشگرا موندن حین کشیدن اسلایدرها) و خروجی نهایی (بدون محدودیت یا\n * محدودیت دلخواه کاربر).\n */\nexport function renderComposite(\n source: CanvasImageSource,\n sourceWidth: number,\n sourceHeight: number,\n crop: NgxCropRect,\n adjustments: NgxImageEditorAdjustments,\n maxWidth?: number,\n maxHeight?: number,\n): HTMLCanvasElement {\n const { width: outW, height: outH } = fitWithin(crop.width, crop.height, maxWidth, maxHeight);\n\n const canvas = document.createElement('canvas');\n canvas.width = Math.max(1, outW);\n canvas.height = Math.max(1, outH);\n const ctx = canvas.getContext('2d')!;\n\n ctx.filter = buildCssFilter(adjustments);\n ctx.drawImage(source, crop.x, crop.y, crop.width, crop.height, 0, 0, canvas.width, canvas.height);\n ctx.filter = 'none';\n\n if (adjustments.filter === 'cartoon') {\n applyCartoonEffect(ctx, canvas.width, canvas.height);\n }\n\n return canvas;\n}\n","import { InjectionToken } from '@angular/core';\r\n\r\nexport const NGX_IMAGE_EDITOR_LOCALIZATION = new InjectionToken<NgxImageEditorLocalization>(\r\n 'ngx-image-localization',\r\n {\r\n factory: () => DEFAULT_NGX_IMAGE_EDITOR_LOCALIZATION,\r\n },\r\n);\r\n\r\nexport class NgxImageEditorLocalization {\r\n LoadingImage = 'Loading image…';\r\n Rotation = 'Fine rotation';\r\n Brightness = 'Brightness';\r\n Contrast = 'Contrast';\r\n Saturation = 'Saturation';\r\n Filter = 'Filter';\r\n None = 'None';\r\n Grayscale = 'Grayscale';\r\n Sepia = 'Sepia';\r\n Invert = 'Invert';\r\n Cartoon = 'Cartoon';\r\n Cancel = 'Cancel';\r\n Save = 'Save';\r\n Saving = 'Saving…';\r\n Reset = 'Reset';\r\n}\r\nexport const DEFAULT_NGX_IMAGE_EDITOR_LOCALIZATION = new NgxImageEditorLocalization();\r\n","import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n ElementRef,\r\n computed,\r\n effect,\r\n inject,\r\n input,\r\n output,\r\n signal,\r\n viewChild,\r\n} from '@angular/core';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { SliderComponent } from 'ngx-kit/shared';\r\nimport {\r\n NgxCropRect,\r\n NgxImageEditorAdjustments,\r\n NgxImageEditorResult,\r\n NgxImageFilterPreset,\r\n} from '../contracts/image-editor-types';\r\nimport { NgxPointerDragDelta, NgxPointerDragDirective } from '../directives/pointer-drag.directive';\r\nimport { canvasToBlob, createWorkingCopy, loadImage } from '../utils/image-io';\r\nimport { renderComposite, renderRotated } from '../utils/render-pipeline';\r\nimport { Corner } from '../types/corner';\r\nimport { NGX_IMAGE_EDITOR_LOCALIZATION, NgxImageEditorLocalization } from '../tokens/localization';\r\n\r\nconst ALL_FILTERS: NgxImageFilterPreset[] = ['none', 'grayscale', 'sepia', 'invert', 'cartoon'];\r\n\r\n/**\r\n * ویرایشگر تصویر: کراپ + چرخش + روشنایی/کنتراست/اشباع + فیلترهای آماده\r\n * (سیاهوسفید، سپیا، معکوس، کارتونی) + فشردهسازی خروجی. کاملاً روی Canvas\r\n * خام پیاده شده، بدون هیچ وابستگی خارجیای.\r\n *\r\n * نکتهی مهمِ معماری: تمام تعامل زنده (چرخوندن، جابهجا/ریسایز کراپباکس،\r\n * پیشنمایش فیلترها حتی کارتونی) روی یه کپیِ کوچیکشده از تصویر انجام میشه\r\n * (createWorkingCopy)، نه روی تصویر اصلی که ممکنه چند مگاپیکسل باشه — وگرنه\r\n * درگکردن اسلایدرها/گوشههای کراپ رو کاربر حس تاخیر میکرد. فقط لحظهی\r\n * save()، رندر نهایی از روی تصویر اصلیِ کامل انجام میشه.\r\n *\r\n * اندازهی صحنه (stage) با panelSize کنترل میشه: عرض همیشه ۱۰۰٪ عرضِ\r\n * والدِ کامپوننته (با ResizeObserver اندازهگیری میشه، پس با تغییر سایز\r\n * صفحه/layout هم زنده هماهنگ میمونه)، ارتفاع دقیقاً همون چیزیه که کاربر با\r\n * panelSize میده. تصویر همیشه با یک مقیاسِ «contain» واقعی (هم بر اساس\r\n * عرض، هم بر اساس ارتفاع — هرکدوم تنگتره) جا داده میشه، پس کلِ تصویر\r\n * همیشه در محدودهی همین باکس دیده میشه، صرفنظر از اندازهی واقعیِ فایل.\r\n * سقفِ مقیاس هم ۱ هست، یعنی تصاویر کوچیک بزرگنمایی نمیشن (که باعثِ محو\r\n * شدنشون میشد).\r\n */\r\n@Component({\r\n selector: 'ngx-image-editor',\r\n standalone: true,\r\n imports: [FormsModule, SliderComponent, NgxPointerDragDirective],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './image-editor.component.html',\r\n styleUrl: './image-editor.component.scss',\r\n host: { class: 'ngx-image-editor-host' },\r\n})\r\nexport class NgxImageEditorComponent {\r\n source = input<File | Blob | string | null>(null);\r\n /** قفل نسبتِ کراپ (مثلاً ۱ برای آواتار مربعی)؛ undefined یعنی آزاد */\r\n aspectRatio = input<number | undefined>(undefined);\r\n outputMaxWidth = input<number | undefined>(undefined);\r\n outputMaxHeight = input<number | undefined>(undefined);\r\n outputType = input<'image/jpeg' | 'image/png' | 'image/webp'>('image/jpeg');\r\n\r\n /**\r\n * کدوم فیلترها نشون داده بشن (و به چه ترتیبی). اگه ندید، هر ۵ تا نشون داده\r\n * میشن. آرایهی خالی یعنی کلِ بخشِ فیلتر مخفی بشه.\r\n */\r\n filters = input<NgxImageFilterPreset[]>(ALL_FILTERS);\r\n quality = input(0.92);\r\n\r\n defaultLocalization = inject(NGX_IMAGE_EDITOR_LOCALIZATION);\r\n localize = input<NgxImageEditorLocalization>(this.defaultLocalization);\r\n\r\n saved = output<NgxImageEditorResult>();\r\n cancelled = output<void>();\r\n\r\n protected readonly loading = signal(false);\r\n protected readonly saving = signal(false);\r\n protected readonly loadError = signal<string | null>(null);\r\n\r\n private readonly originalImage = signal<HTMLImageElement | null>(null);\r\n private readonly workingCanvas = signal<HTMLCanvasElement | null>(null);\r\n private readonly stageWrapEl = viewChild<ElementRef<HTMLElement>>('stageWrap');\r\n /** عرضِ واقعیِ رندرشدهی کانتینر؛ چون عرض همیشه ۱۰۰٪ (fluid) هست، باید زنده اندازهگیری بشه */\r\n private readonly containerWidth = signal(0);\r\n\r\n protected readonly rotation = signal(0);\r\n protected readonly brightness = signal(100);\r\n protected readonly contrast = signal(100);\r\n protected readonly saturation = signal(100);\r\n protected readonly filterPreset = signal<NgxImageFilterPreset>('none');\r\n\r\n protected readonly crop = signal<NgxCropRect>({ x: 0, y: 0, width: 0, height: 0 });\r\n\r\n protected readonly adjustments = computed<NgxImageEditorAdjustments>(() => ({\r\n brightness: this.brightness(),\r\n contrast: this.contrast(),\r\n saturation: this.saturation(),\r\n rotation: this.rotation(),\r\n filter: this.filterPreset(),\r\n }));\r\n\r\n protected readonly filterLabels = computed<Record<NgxImageFilterPreset, string>>(() => {\r\n const t = this.localize();\r\n return {\r\n none: t.None,\r\n grayscale: t.Grayscale,\r\n sepia: t.Sepia,\r\n invert: t.Invert,\r\n cartoon: t.Cartoon,\r\n };\r\n });\r\n\r\n /** تصویرِ (کوچیکشدهیِ) چرخیده — پایهی نمایش صحنهی کراپ */\r\n protected readonly rotatedWorkingCanvas = computed(() => {\r\n const wc = this.workingCanvas();\r\n if (!wc) return null;\r\n return renderRotated(wc, wc.width, wc.height, this.rotation());\r\n });\r\n\r\n protected readonly panelSize = computed(() => {\r\n return this.stageWrapEl()?.nativeElement.getBoundingClientRect().height ?? 0;\r\n });\r\n\r\n /**\r\n * مقیاسِ «contain» واقعی: کوچیکترینِ نسبتِ عرض و ارتفاع (هرکدوم تنگتره)\r\n * تعیینکنندهست، و سقفش هم ۱ هست تا تصاویر کوچیک بزرگنمایی نشن.\r\n */\r\n protected readonly displayScale = computed(() => {\r\n const rc = this.rotatedWorkingCanvas();\r\n const containerW = this.containerWidth();\r\n const panelH = this.panelSize();\r\n if (!rc || rc.width <= 0 || rc.height <= 0 || containerW <= 0 || panelH <= 0) return 1;\r\n return Math.min(containerW / rc.width, panelH / rc.height, 1);\r\n });\r\n\r\n protected readonly stageImageUrl = computed(() => {\r\n const rc = this.rotatedWorkingCanvas();\r\n return rc ? rc.toDataURL('image/png') : null;\r\n });\r\n\r\n protected readonly stageSize = computed(() => {\r\n const rc = this.rotatedWorkingCanvas();\r\n const scale = this.displayScale();\r\n return rc ? { width: rc.width * scale, height: rc.height * scale } : { width: 0, height: 0 };\r\n });\r\n\r\n protected readonly cropOverlayStyle = computed(() => {\r\n const scale = this.displayScale();\r\n const c = this.crop();\r\n return {\r\n left: `${c.x * scale}px`,\r\n top: `${c.y * scale}px`,\r\n width: `${c.width * scale}px`,\r\n height: `${c.height * scale}px`,\r\n };\r\n });\r\n\r\n /** پیشنمایش نهایی (کوچیک، حداکثر ۴۸۰ پیکسل) — شامل همهچیز، حتی افکت کارتونی */\r\n protected readonly previewUrl = computed(() => {\r\n const rc = this.rotatedWorkingCanvas();\r\n const c = this.crop();\r\n if (!rc || c.width <= 0 || c.height <= 0) return null;\r\n const canvas = renderComposite(rc, rc.width, rc.height, c, this.adjustments(), 480, 480);\r\n return canvas.toDataURL('image/png');\r\n });\r\n\r\n private moveSnapshot: NgxCropRect | null = null;\r\n private resizeSnapshot: NgxCropRect | null = null;\r\n\r\n constructor() {\r\n // بارگذاری تصویر هروقت source عوض بشه\r\n effect(() => {\r\n const src = this.source();\r\n if (!src) {\r\n this.originalImage.set(null);\r\n this.workingCanvas.set(null);\r\n return;\r\n }\r\n this.loading.set(true);\r\n this.loadError.set(null);\r\n loadImage(src)\r\n .then((img) => {\r\n this.originalImage.set(img);\r\n this.workingCanvas.set(createWorkingCopy(img));\r\n this.resetAdjustments();\r\n })\r\n .catch((err) => this.loadError.set(err?.message ?? 'Failed to load image'))\r\n .finally(() => this.loading.set(false));\r\n });\r\n\r\n // هر وقت چرخیدهشده عوض بشه (بارگذاریِ تصویر جدید یا چرخش)، کراپ روی کل قاب ریست بشه\r\n effect(() => {\r\n const rc = this.rotatedWorkingCanvas();\r\n if (rc) {\r\n this.crop.set({ x: 0, y: 0, width: rc.width, height: rc.height });\r\n }\r\n });\r\n\r\n // اگه فیلترِ فعلاً انتخابشده دیگه توی لیستِ مجازِ filters() نباشه (مثلاً\r\n // مصرفکننده cartoon رو غیرفعال کرده درحالیکه کاربر روش بود)، برو روی\r\n // اولین فیلترِ مجاز؛ اگه لیست خالی باشه (کلاً فیلتر مخفیه)، روی none بمون.\r\n effect(() => {\r\n const allowed = this.filters();\r\n if (allowed.length && !allowed.includes(this.filterPreset())) {\r\n this.filterPreset.set(allowed[0]);\r\n }\r\n });\r\n\r\n // اندازهگیریِ زندهی عرضِ واقعیِ کانتینر — چون عرض همیشه ۱۰۰٪ (fluid)ه،\r\n // فقط با ResizeObserver میشه فهمید الان چند پیکسله (نه یه عددِ ثابتِ ورودی).\r\n effect((onCleanup) => {\r\n const el = this.stageWrapEl()?.nativeElement;\r\n if (!el) return;\r\n this.containerWidth.set(el.getBoundingClientRect().width);\r\n const ro = new ResizeObserver((entries) => {\r\n const width = entries[0]?.contentRect.width;\r\n if (width != null) this.containerWidth.set(width);\r\n });\r\n ro.observe(el);\r\n onCleanup(() => ro.disconnect());\r\n });\r\n }\r\n\r\n private resetAdjustments(): void {\r\n this.rotation.set(0);\r\n this.brightness.set(100);\r\n this.contrast.set(100);\r\n this.saturation.set(100);\r\n this.filterPreset.set(this.filters()[0] ?? 'none');\r\n }\r\n\r\n protected rotateBy(delta: number): void {\r\n this.rotation.update((r) => {\r\n let next = r + delta;\r\n if (next > 180) next -= 360;\r\n if (next < -180) next += 360;\r\n return next;\r\n });\r\n }\r\n\r\n protected setFilter(preset: NgxImageFilterPreset): void {\r\n this.filterPreset.set(preset);\r\n }\r\n\r\n // ---------- درگ جابهجاییِ کل کراپباکس ----------\r\n protected onMoveDragStart(): void {\r\n this.moveSnapshot = { ...this.crop() };\r\n }\r\n\r\n protected onMoveDragMove(delta: NgxPointerDragDelta): void {\r\n const rc = this.rotatedWorkingCanvas();\r\n const snap = this.moveSnapshot;\r\n if (!rc || !snap) return;\r\n const scale = this.displayScale();\r\n const dxSrc = delta.dx / scale;\r\n const dySrc = delta.dy / scale;\r\n const maxX = Math.max(0, rc.width - snap.width);\r\n const maxY = Math.max(0, rc.height - snap.height);\r\n const x = Math.min(Math.max(0, snap.x + dxSrc), maxX);\r\n const y = Math.min(Math.max(0, snap.y + dySrc), maxY);\r\n this.crop.set({ ...snap, x, y });\r\n }\r\n\r\n // ---------- درگ ریسایز از گوشهها ----------\r\n protected onResizeDragStart(): void {\r\n this.resizeSnapshot = { ...this.crop() };\r\n }\r\n\r\n protected onResizeDragMove(corner: Corner, delta: NgxPointerDragDelta): void {\r\n const rc = this.rotatedWorkingCanvas();\r\n const snap = this.resizeSnapshot;\r\n if (!rc || !snap) return;\r\n\r\n const scale = this.displayScale();\r\n const dxSrc = delta.dx / scale;\r\n const dySrc = delta.dy / scale;\r\n const minSize = 24;\r\n\r\n let { x, y, width, height } = snap;\r\n\r\n if (corner === 'nw' || corner === 'sw') {\r\n const newX = Math.min(snap.x + dxSrc, snap.x + snap.width - minSize);\r\n x = Math.max(0, newX);\r\n width = snap.x + snap.width - x;\r\n }\r\n if (corner === 'ne' || corner === 'se') {\r\n width = Math.min(Math.max(minSize, snap.width + dxSrc), rc.width - snap.x);\r\n }\r\n if (corner === 'nw' || corner === 'ne') {\r\n const newY = Math.min(snap.y + dySrc, snap.y + snap.height - minSize);\r\n y = Math.max(0, newY);\r\n height = snap.y + snap.height - y;\r\n }\r\n if (corner === 'sw' || corner === 'se') {\r\n height = Math.min(Math.max(minSize, snap.height + dySrc), rc.height - snap.y);\r\n }\r\n\r\n const ratio = this.aspectRatio();\r\n if (ratio) {\r\n height = width / ratio;\r\n }\r\n\r\n this.crop.set({ x, y, width, height });\r\n }\r\n\r\n protected cancel(): void {\r\n this.cancelled.emit();\r\n }\r\n\r\n async save(): Promise<void> {\r\n const original = this.originalImage();\r\n const working = this.workingCanvas();\r\n if (!original || !working) return;\r\n\r\n this.saving.set(true);\r\n try {\r\n // نسبت مقیاس بین کپیِ کوچیکشده (که کراپ/چرخش روش تعریف شده) و تصویر\r\n // اصلیِ کامل. چون createWorkingCopy مقیاس یکنواخت (همجهت) اعمال\r\n // میکنه، همین یه ضریب برای هر دو بعد و بعد از چرخش هم معتبر میمونه.\r\n const scaleToOriginal = original.naturalWidth / working.width;\r\n\r\n const rotatedFull = renderRotated(\r\n original,\r\n original.naturalWidth,\r\n original.naturalHeight,\r\n this.rotation(),\r\n );\r\n\r\n const c = this.crop();\r\n const cropInFullRes: NgxCropRect = {\r\n x: c.x * scaleToOriginal,\r\n y: c.y * scaleToOriginal,\r\n width: c.width * scaleToOriginal,\r\n height: c.height * scaleToOriginal,\r\n };\r\n\r\n const finalCanvas = renderComposite(\r\n rotatedFull,\r\n rotatedFull.width,\r\n rotatedFull.height,\r\n cropInFullRes,\r\n this.adjustments(),\r\n this.outputMaxWidth(),\r\n this.outputMaxHeight(),\r\n );\r\n\r\n const type = this.outputType();\r\n const blob = await canvasToBlob(finalCanvas, type, this.quality());\r\n const dataUrl = finalCanvas.toDataURL(type, this.quality());\r\n this.saved.emit({ blob, dataUrl, width: finalCanvas.width, height: finalCanvas.height });\r\n } finally {\r\n this.saving.set(false);\r\n }\r\n }\r\n}\r\n","@if (loading()) {\r\n <div class=\"ngx-ie-state\">{{ localize().LoadingImage }}</div>\r\n} @else if (loadError()) {\r\n <div class=\"ngx-ie-state ngx-ie-state--error\">{{ loadError() }}</div>\r\n} @else if (stageImageUrl()) {\r\n <div class=\"ngx-ie-layout\">\r\n <div class=\"ngx-ie-stage-wrap\" #stageWrap>\r\n <div\r\n class=\"ngx-ie-stage\"\r\n [style.width.px]=\"stageSize().width\"\r\n [style.height.px]=\"stageSize().height\">\r\n <img class=\"ngx-ie-stage-img\" [src]=\"stageImageUrl()\" alt=\"\" draggable=\"false\" />\r\n\r\n <div\r\n class=\"ngx-ie-crop-box\"\r\n [style.left]=\"cropOverlayStyle().left\"\r\n [style.top]=\"cropOverlayStyle().top\"\r\n [style.width]=\"cropOverlayStyle().width\"\r\n [style.height]=\"cropOverlayStyle().height\"\r\n ngxPointerDrag\r\n (dragStart)=\"onMoveDragStart()\"\r\n (dragMove)=\"onMoveDragMove($event)\">\r\n <span\r\n class=\"ngx-ie-handle ngx-ie-handle--nw\"\r\n ngxPointerDrag\r\n (dragStart)=\"onResizeDragStart()\"\r\n (dragMove)=\"onResizeDragMove('nw', $event)\"></span>\r\n <span\r\n class=\"ngx-ie-handle ngx-ie-handle--ne\"\r\n ngxPointerDrag\r\n (dragStart)=\"onResizeDragStart()\"\r\n (dragMove)=\"onResizeDragMove('ne', $event)\"></span>\r\n <span\r\n class=\"ngx-ie-handle ngx-ie-handle--sw\"\r\n ngxPointerDrag\r\n (dragStart)=\"onResizeDragStart()\"\r\n (dragMove)=\"onResizeDragMove('sw', $event)\"></span>\r\n <span\r\n class=\"ngx-ie-handle ngx-ie-handle--se\"\r\n ngxPointerDrag\r\n (dragStart)=\"onResizeDragStart()\"\r\n (dragMove)=\"onResizeDragMove('se', $event)\"></span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"ngx-ie-panel-row\">\r\n <div class=\"ngx-ie-panel\">\r\n <div class=\"ngx-ie-preview\">\r\n @if (previewUrl(); as url) {\r\n <img [src]=\"url\" alt=\"Preview\" />\r\n }\r\n </div>\r\n\r\n <div class=\"ngx-ie-row ngx-ie-rotate-row\">\r\n <button type=\"button\" (click)=\"rotateBy(-90)\" title=\"Rotate 90° left\">⟲ 90</button>\r\n <button type=\"button\" (click)=\"rotateBy(90)\" title=\"Rotate 90° right\">⟳ 90</button>\r\n </div>\r\n\r\n <div class=\"ngx-ie-field\">\r\n <slider\r\n [ngModel]=\"rotation()\"\r\n (ngModelChange)=\"rotation.set($event)\"\r\n [min]=\"-180\"\r\n [max]=\"180\">\r\n <span>{{ localize().Rotation }} ({{ rotation() }}°)</span>\r\n </slider>\r\n\r\n <button\r\n type=\"button\"\r\n (click)=\"rotation.set(0)\"\r\n class=\"ngx-ie-btn-secondary\"\r\n [title]=\"localize().Reset\">\r\n x\r\n </button>\r\n </div>\r\n\r\n <div class=\"ngx-ie-field\">\r\n <slider\r\n [ngModel]=\"brightness()\"\r\n (ngModelChange)=\"brightness.set($event)\"\r\n [min]=\"0\"\r\n [max]=\"200\">\r\n <span>{{ localize().Brightness }} ({{ brightness() }}%)</span>\r\n </slider>\r\n <button\r\n type=\"button\"\r\n (click)=\"brightness.set(100)\"\r\n class=\"ngx-ie-btn-secondary\"\r\n [title]=\"localize().Reset\">\r\n x\r\n </button>\r\n </div>\r\n\r\n <div class=\"ngx-ie-field\">\r\n <slider\r\n [ngModel]=\"contrast()\"\r\n (ngModelChange)=\"contrast.set($event)\"\r\n [min]=\"0\"\r\n [max]=\"200\">\r\n <span>{{ localize().Contrast }} ({{ contrast() }}%)</span>\r\n </slider>\r\n <button\r\n type=\"button\"\r\n (click)=\"contrast.set(100)\"\r\n class=\"ngx-ie-btn-secondary\"\r\n [title]=\"localize().Reset\">\r\n x\r\n </button>\r\n </div>\r\n\r\n <div class=\"ngx-ie-field\">\r\n <slider\r\n [ngModel]=\"saturation()\"\r\n (ngModelChange)=\"saturation.set($event)\"\r\n [min]=\"0\"\r\n [max]=\"200\">\r\n <span>{{ localize().Saturation }} ({{ saturation() }}%)</span>\r\n </slider>\r\n <button\r\n type=\"button\"\r\n (click)=\"saturation.set(100)\"\r\n class=\"ngx-ie-btn-secondary\"\r\n [title]=\"localize().Reset\">\r\n x\r\n </button>\r\n </div>\r\n\r\n @if (filters().length) {\r\n <div>\r\n <span>{{ localize().Filter }}</span>\r\n <div class=\"ngx-ie-filter-row\">\r\n @for (f of filters(); track f) {\r\n <button type=\"button\" [class.active]=\"filterPreset() === f\" (click)=\"setFilter(f)\">\r\n {{ filterLabels()[f] }}\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n <div class=\"ngx-ie-row ngx-ie-actions\">\r\n <button type=\"button\" class=\"ngx-ie-btn-secondary\" (click)=\"cancel()\">\r\n {{ localize().Cancel }}\r\n </button>\r\n <button type=\"button\" class=\"ngx-ie-btn-primary\" [disabled]=\"saving()\" (click)=\"save()\">\r\n {{ saving() ? localize().Saving : localize().Save }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -180,18 +180,18 @@ class NgxMenuItem {
|
|
|
180
180
|
this.menuContext?.close();
|
|
181
181
|
}
|
|
182
182
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxMenuItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
183
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.4", type: NgxMenuItem, isStandalone: true, selector: "ngx-menu-item,[ngx-menu-item]", host: { listeners: { "click": "onClick()" } }, exportAs: ["NgxMenuItem"], ngImport: i0, template: `
|
|
184
|
-
<div class="ngx-menu-item">
|
|
185
|
-
<ng-content></ng-content>
|
|
186
|
-
</div>
|
|
183
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.4", type: NgxMenuItem, isStandalone: true, selector: "ngx-menu-item,[ngx-menu-item]", host: { listeners: { "click": "onClick()" } }, exportAs: ["NgxMenuItem"], ngImport: i0, template: `
|
|
184
|
+
<div class="ngx-menu-item">
|
|
185
|
+
<ng-content></ng-content>
|
|
186
|
+
</div>
|
|
187
187
|
`, isInline: true, styles: [".ngx-menu-item{box-sizing:border-box;outline:0;padding:var(--ngx-menu-item-padding, 6px 12px);transition:all .3s}.ngx-menu-item:hover{cursor:pointer;background-color:var(--ngx-menu-item-hover-bg, #9bc6ff68)}\n"] });
|
|
188
188
|
}
|
|
189
189
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxMenuItem, decorators: [{
|
|
190
190
|
type: Component,
|
|
191
|
-
args: [{ selector: 'ngx-menu-item,[ngx-menu-item]', template: `
|
|
192
|
-
<div class="ngx-menu-item">
|
|
193
|
-
<ng-content></ng-content>
|
|
194
|
-
</div>
|
|
191
|
+
args: [{ selector: 'ngx-menu-item,[ngx-menu-item]', template: `
|
|
192
|
+
<div class="ngx-menu-item">
|
|
193
|
+
<ng-content></ng-content>
|
|
194
|
+
</div>
|
|
195
195
|
`, exportAs: 'NgxMenuItem', styles: [".ngx-menu-item{box-sizing:border-box;outline:0;padding:var(--ngx-menu-item-padding, 6px 12px);transition:all .3s}.ngx-menu-item:hover{cursor:pointer;background-color:var(--ngx-menu-item-hover-bg, #9bc6ff68)}\n"] }]
|
|
196
196
|
}], propDecorators: { onClick: [{
|
|
197
197
|
type: HostListener,
|