ngx-kit 7.3.2 → 7.4.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/fesm2022/ngx-kit-box-shadow.mjs +2 -2
- package/fesm2022/ngx-kit-box-shadow.mjs.map +1 -1
- package/fesm2022/ngx-kit-date-picker.mjs +27 -22
- package/fesm2022/ngx-kit-date-picker.mjs.map +1 -1
- package/fesm2022/ngx-kit-dialog.mjs +6 -5
- package/fesm2022/ngx-kit-dialog.mjs.map +1 -1
- package/fesm2022/ngx-kit-dropzone.mjs +5 -5
- package/fesm2022/ngx-kit-dropzone.mjs.map +1 -1
- package/fesm2022/ngx-kit-image-editor.mjs +14 -26
- package/fesm2022/ngx-kit-image-editor.mjs.map +1 -1
- package/fesm2022/ngx-kit-media-control-mse-media-engine-CtP97cb9.mjs +326 -0
- package/fesm2022/ngx-kit-media-control-mse-media-engine-CtP97cb9.mjs.map +1 -0
- package/fesm2022/ngx-kit-media-control.mjs +1847 -0
- package/fesm2022/ngx-kit-media-control.mjs.map +1 -0
- package/media-control/README.md +349 -0
- package/package.json +5 -1
- package/types/ngx-kit-date-picker.d.ts +1 -1
- package/types/ngx-kit-dialog.d.ts +1 -2
- package/types/ngx-kit-dropzone.d.ts +4 -4
- package/types/ngx-kit-image-editor.d.ts +10 -27
- package/types/ngx-kit-media-control.d.ts +671 -0
|
@@ -264,27 +264,7 @@ class NgxImageEditorLocalization {
|
|
|
264
264
|
const DEFAULT_NGX_IMAGE_EDITOR_LOCALIZATION = new NgxImageEditorLocalization();
|
|
265
265
|
|
|
266
266
|
const ALL_FILTERS = ['none', 'grayscale', 'sepia', 'invert', 'cartoon'];
|
|
267
|
-
|
|
268
|
-
* ویرایشگر تصویر: کراپ + چرخش + روشنایی/کنتراست/اشباع + فیلترهای آماده
|
|
269
|
-
* (سیاهوسفید، سپیا، معکوس، کارتونی) + فشردهسازی خروجی. کاملاً روی Canvas
|
|
270
|
-
* خام پیاده شده، بدون هیچ وابستگی خارجیای.
|
|
271
|
-
*
|
|
272
|
-
* نکتهی مهمِ معماری: تمام تعامل زنده (چرخوندن، جابهجا/ریسایز کراپباکس،
|
|
273
|
-
* پیشنمایش فیلترها حتی کارتونی) روی یه کپیِ کوچیکشده از تصویر انجام میشه
|
|
274
|
-
* (createWorkingCopy)، نه روی تصویر اصلی که ممکنه چند مگاپیکسل باشه — وگرنه
|
|
275
|
-
* درگکردن اسلایدرها/گوشههای کراپ رو کاربر حس تاخیر میکرد. فقط لحظهی
|
|
276
|
-
* save()، رندر نهایی از روی تصویر اصلیِ کامل انجام میشه.
|
|
277
|
-
*
|
|
278
|
-
* اندازهی صحنه (stage) با panelSize کنترل میشه: عرض همیشه ۱۰۰٪ عرضِ
|
|
279
|
-
* والدِ کامپوننته (با ResizeObserver اندازهگیری میشه، پس با تغییر سایز
|
|
280
|
-
* صفحه/layout هم زنده هماهنگ میمونه)، ارتفاع دقیقاً همون چیزیه که کاربر با
|
|
281
|
-
* panelSize میده. تصویر همیشه با یک مقیاسِ «contain» واقعی (هم بر اساس
|
|
282
|
-
* عرض، هم بر اساس ارتفاع — هرکدوم تنگتره) جا داده میشه، پس کلِ تصویر
|
|
283
|
-
* همیشه در محدودهی همین باکس دیده میشه، صرفنظر از اندازهی واقعیِ فایل.
|
|
284
|
-
* سقفِ مقیاس هم ۱ هست، یعنی تصاویر کوچیک بزرگنمایی نمیشن (که باعثِ محو
|
|
285
|
-
* شدنشون میشد).
|
|
286
|
-
*/
|
|
287
|
-
class NgxImageEditorComponent {
|
|
267
|
+
class NgxImageEditor {
|
|
288
268
|
source = input(null, /* @ts-ignore */
|
|
289
269
|
...(ngDevMode ? [{ debugName: "source" }] : /* istanbul ignore next */ []));
|
|
290
270
|
/** قفل نسبتِ کراپ (مثلاً ۱ برای آواتار مربعی)؛ undefined یعنی آزاد */
|
|
@@ -566,16 +546,24 @@ class NgxImageEditorComponent {
|
|
|
566
546
|
const type = this.outputType();
|
|
567
547
|
const blob = await canvasToBlob(finalCanvas, type, this.quality());
|
|
568
548
|
const dataUrl = finalCanvas.toDataURL(type, this.quality());
|
|
569
|
-
|
|
549
|
+
const file = new File([blob], '', { type });
|
|
550
|
+
this.saved.emit({
|
|
551
|
+
blob,
|
|
552
|
+
dataUrl,
|
|
553
|
+
width: finalCanvas.width,
|
|
554
|
+
height: finalCanvas.height,
|
|
555
|
+
file,
|
|
556
|
+
type,
|
|
557
|
+
});
|
|
570
558
|
}
|
|
571
559
|
finally {
|
|
572
560
|
this.saving.set(false);
|
|
573
561
|
}
|
|
574
562
|
}
|
|
575
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type:
|
|
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()) {\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\" #stageWrap>\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-row\">\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 <div class=\"ngx-ie-field\">\n <slider\n [ngModel]=\"rotation()\"\n (ngModelChange)=\"rotation.set($event)\"\n [min]=\"-180\"\n [max]=\"180\">\n <span>{{ localize().Rotation }} ({{ rotation() }}\u00B0)</span>\n </slider>\n\n <button\n type=\"button\"\n (click)=\"rotation.set(0)\"\n class=\"ngx-ie-btn-secondary\"\n [title]=\"localize().Reset\">\n x\n </button>\n </div>\n\n <div class=\"ngx-ie-field\">\n <slider\n [ngModel]=\"brightness()\"\n (ngModelChange)=\"brightness.set($event)\"\n [min]=\"0\"\n [max]=\"200\">\n <span>{{ localize().Brightness }} ({{ brightness() }}%)</span>\n </slider>\n <button\n type=\"button\"\n (click)=\"brightness.set(100)\"\n class=\"ngx-ie-btn-secondary\"\n [title]=\"localize().Reset\">\n x\n </button>\n </div>\n\n <div class=\"ngx-ie-field\">\n <slider\n [ngModel]=\"contrast()\"\n (ngModelChange)=\"contrast.set($event)\"\n [min]=\"0\"\n [max]=\"200\">\n <span>{{ localize().Contrast }} ({{ contrast() }}%)</span>\n </slider>\n <button\n type=\"button\"\n (click)=\"contrast.set(100)\"\n class=\"ngx-ie-btn-secondary\"\n [title]=\"localize().Reset\">\n x\n </button>\n </div>\n\n <div class=\"ngx-ie-field\">\n <slider\n [ngModel]=\"saturation()\"\n (ngModelChange)=\"saturation.set($event)\"\n [min]=\"0\"\n [max]=\"200\">\n <span>{{ localize().Saturation }} ({{ saturation() }}%)</span>\n </slider>\n <button\n type=\"button\"\n (click)=\"saturation.set(100)\"\n class=\"ngx-ie-btn-secondary\"\n [title]=\"localize().Reset\">\n x\n </button>\n </div>\n\n @if (filters().length) {\n <div>\n <span>{{ localize().Filter }}</span>\n <div class=\"ngx-ie-filter-row\">\n @for (f of filters(); track f) {\n <button type=\"button\" [class.active]=\"filterPreset() === f\" (click)=\"setFilter(f)\">\n {{ filterLabels()[f] }}\n </button>\n }\n </div>\n </div>\n }\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 </div>\n}\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 });
|
|
563
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxImageEditor, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
564
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: NgxImageEditor, 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()) {\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\" #stageWrap>\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-row\">\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 <div class=\"ngx-ie-field\">\n <slider\n [ngModel]=\"rotation()\"\n (ngModelChange)=\"rotation.set($event)\"\n [min]=\"-180\"\n [max]=\"180\">\n <span>{{ localize().Rotation }} ({{ rotation() }}\u00B0)</span>\n </slider>\n\n <button\n type=\"button\"\n (click)=\"rotation.set(0)\"\n class=\"ngx-ie-btn-secondary\"\n [title]=\"localize().Reset\">\n x\n </button>\n </div>\n\n <div class=\"ngx-ie-field\">\n <slider\n [ngModel]=\"brightness()\"\n (ngModelChange)=\"brightness.set($event)\"\n [min]=\"0\"\n [max]=\"200\">\n <span>{{ localize().Brightness }} ({{ brightness() }}%)</span>\n </slider>\n <button\n type=\"button\"\n (click)=\"brightness.set(100)\"\n class=\"ngx-ie-btn-secondary\"\n [title]=\"localize().Reset\">\n x\n </button>\n </div>\n\n <div class=\"ngx-ie-field\">\n <slider\n [ngModel]=\"contrast()\"\n (ngModelChange)=\"contrast.set($event)\"\n [min]=\"0\"\n [max]=\"200\">\n <span>{{ localize().Contrast }} ({{ contrast() }}%)</span>\n </slider>\n <button\n type=\"button\"\n (click)=\"contrast.set(100)\"\n class=\"ngx-ie-btn-secondary\"\n [title]=\"localize().Reset\">\n x\n </button>\n </div>\n\n <div class=\"ngx-ie-field\">\n <slider\n [ngModel]=\"saturation()\"\n (ngModelChange)=\"saturation.set($event)\"\n [min]=\"0\"\n [max]=\"200\">\n <span>{{ localize().Saturation }} ({{ saturation() }}%)</span>\n </slider>\n <button\n type=\"button\"\n (click)=\"saturation.set(100)\"\n class=\"ngx-ie-btn-secondary\"\n [title]=\"localize().Reset\">\n x\n </button>\n </div>\n\n @if (filters().length) {\n <div>\n <span>{{ localize().Filter }}</span>\n <div class=\"ngx-ie-filter-row\">\n @for (f of filters(); track f) {\n <button type=\"button\" [class.active]=\"filterPreset() === f\" (click)=\"setFilter(f)\">\n {{ filterLabels()[f] }}\n </button>\n }\n </div>\n </div>\n }\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 </div>\n}\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 });
|
|
577
565
|
}
|
|
578
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type:
|
|
566
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: NgxImageEditor, decorators: [{
|
|
579
567
|
type: Component,
|
|
580
568
|
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\" #stageWrap>\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-row\">\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 <div class=\"ngx-ie-field\">\n <slider\n [ngModel]=\"rotation()\"\n (ngModelChange)=\"rotation.set($event)\"\n [min]=\"-180\"\n [max]=\"180\">\n <span>{{ localize().Rotation }} ({{ rotation() }}\u00B0)</span>\n </slider>\n\n <button\n type=\"button\"\n (click)=\"rotation.set(0)\"\n class=\"ngx-ie-btn-secondary\"\n [title]=\"localize().Reset\">\n x\n </button>\n </div>\n\n <div class=\"ngx-ie-field\">\n <slider\n [ngModel]=\"brightness()\"\n (ngModelChange)=\"brightness.set($event)\"\n [min]=\"0\"\n [max]=\"200\">\n <span>{{ localize().Brightness }} ({{ brightness() }}%)</span>\n </slider>\n <button\n type=\"button\"\n (click)=\"brightness.set(100)\"\n class=\"ngx-ie-btn-secondary\"\n [title]=\"localize().Reset\">\n x\n </button>\n </div>\n\n <div class=\"ngx-ie-field\">\n <slider\n [ngModel]=\"contrast()\"\n (ngModelChange)=\"contrast.set($event)\"\n [min]=\"0\"\n [max]=\"200\">\n <span>{{ localize().Contrast }} ({{ contrast() }}%)</span>\n </slider>\n <button\n type=\"button\"\n (click)=\"contrast.set(100)\"\n class=\"ngx-ie-btn-secondary\"\n [title]=\"localize().Reset\">\n x\n </button>\n </div>\n\n <div class=\"ngx-ie-field\">\n <slider\n [ngModel]=\"saturation()\"\n (ngModelChange)=\"saturation.set($event)\"\n [min]=\"0\"\n [max]=\"200\">\n <span>{{ localize().Saturation }} ({{ saturation() }}%)</span>\n </slider>\n <button\n type=\"button\"\n (click)=\"saturation.set(100)\"\n class=\"ngx-ie-btn-secondary\"\n [title]=\"localize().Reset\">\n x\n </button>\n </div>\n\n @if (filters().length) {\n <div>\n <span>{{ localize().Filter }}</span>\n <div class=\"ngx-ie-filter-row\">\n @for (f of filters(); track f) {\n <button type=\"button\" [class.active]=\"filterPreset() === f\" (click)=\"setFilter(f)\">\n {{ filterLabels()[f] }}\n </button>\n }\n </div>\n </div>\n }\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 </div>\n}\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
569
|
}], 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 }] }] } });
|
|
@@ -584,5 +572,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImpor
|
|
|
584
572
|
* Generated bundle index. Do not edit.
|
|
585
573
|
*/
|
|
586
574
|
|
|
587
|
-
export { DEFAULT_NGX_IMAGE_EDITOR_LOCALIZATION, NGX_IMAGE_EDITOR_LOCALIZATION,
|
|
575
|
+
export { DEFAULT_NGX_IMAGE_EDITOR_LOCALIZATION, NGX_IMAGE_EDITOR_LOCALIZATION, NgxImageEditor, NgxImageEditorLocalization, NgxPointerDragDirective, applyCartoonEffect, canvasToBlob, createWorkingCopy, fitWithin, loadImage, renderComposite, renderRotated };
|
|
588
576
|
//# 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/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';\n\nexport const NGX_IMAGE_EDITOR_LOCALIZATION = new InjectionToken<NgxImageEditorLocalization>(\n 'ngx-image-localization',\n {\n factory: () => DEFAULT_NGX_IMAGE_EDITOR_LOCALIZATION,\n },\n);\n\nexport class NgxImageEditorLocalization {\n LoadingImage = 'Loading image…';\n Rotation = 'Fine rotation';\n Brightness = 'Brightness';\n Contrast = 'Contrast';\n Saturation = 'Saturation';\n Filter = 'Filter';\n None = 'None';\n Grayscale = 'Grayscale';\n Sepia = 'Sepia';\n Invert = 'Invert';\n Cartoon = 'Cartoon';\n Cancel = 'Cancel';\n Save = 'Save';\n Saving = 'Saving…';\n Reset = 'Reset';\n}\nexport const DEFAULT_NGX_IMAGE_EDITOR_LOCALIZATION = new NgxImageEditorLocalization();\n","import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n viewChild,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { SliderComponent } from 'ngx-kit/core';\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 '../tokens/localization';\n\nconst ALL_FILTERS: NgxImageFilterPreset[] = ['none', 'grayscale', 'sepia', 'invert', 'cartoon'];\n\n/**\n * ویرایشگر تصویر: کراپ + چرخش + روشنایی/کنتراست/اشباع + فیلترهای آماده\n * (سیاهوسفید، سپیا، معکوس، کارتونی) + فشردهسازی خروجی. کاملاً روی Canvas\n * خام پیاده شده، بدون هیچ وابستگی خارجیای.\n *\n * نکتهی مهمِ معماری: تمام تعامل زنده (چرخوندن، جابهجا/ریسایز کراپباکس،\n * پیشنمایش فیلترها حتی کارتونی) روی یه کپیِ کوچیکشده از تصویر انجام میشه\n * (createWorkingCopy)، نه روی تصویر اصلی که ممکنه چند مگاپیکسل باشه — وگرنه\n * درگکردن اسلایدرها/گوشههای کراپ رو کاربر حس تاخیر میکرد. فقط لحظهی\n * save()، رندر نهایی از روی تصویر اصلیِ کامل انجام میشه.\n *\n * اندازهی صحنه (stage) با panelSize کنترل میشه: عرض همیشه ۱۰۰٪ عرضِ\n * والدِ کامپوننته (با ResizeObserver اندازهگیری میشه، پس با تغییر سایز\n * صفحه/layout هم زنده هماهنگ میمونه)، ارتفاع دقیقاً همون چیزیه که کاربر با\n * panelSize میده. تصویر همیشه با یک مقیاسِ «contain» واقعی (هم بر اساس\n * عرض، هم بر اساس ارتفاع — هرکدوم تنگتره) جا داده میشه، پس کلِ تصویر\n * همیشه در محدودهی همین باکس دیده میشه، صرفنظر از اندازهی واقعیِ فایل.\n * سقفِ مقیاس هم ۱ هست، یعنی تصاویر کوچیک بزرگنمایی نمیشن (که باعثِ محو\n * شدنشون میشد).\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 /**\n * کدوم فیلترها نشون داده بشن (و به چه ترتیبی). اگه ندید، هر ۵ تا نشون داده\n * میشن. آرایهی خالی یعنی کلِ بخشِ فیلتر مخفی بشه.\n */\n filters = input<NgxImageFilterPreset[]>(ALL_FILTERS);\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 private readonly stageWrapEl = viewChild<ElementRef<HTMLElement>>('stageWrap');\n /** عرضِ واقعیِ رندرشدهی کانتینر؛ چون عرض همیشه ۱۰۰٪ (fluid) هست، باید زنده اندازهگیری بشه */\n private readonly containerWidth = signal(0);\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 protected readonly filterLabels = computed<Record<NgxImageFilterPreset, string>>(() => {\n const t = this.localize();\n return {\n none: t.None,\n grayscale: t.Grayscale,\n sepia: t.Sepia,\n invert: t.Invert,\n cartoon: t.Cartoon,\n };\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 panelSize = computed(() => {\n return this.stageWrapEl()?.nativeElement.getBoundingClientRect().height ?? 0;\n });\n\n /**\n * مقیاسِ «contain» واقعی: کوچیکترینِ نسبتِ عرض و ارتفاع (هرکدوم تنگتره)\n * تعیینکنندهست، و سقفش هم ۱ هست تا تصاویر کوچیک بزرگنمایی نشن.\n */\n protected readonly displayScale = computed(() => {\n const rc = this.rotatedWorkingCanvas();\n const containerW = this.containerWidth();\n const panelH = this.panelSize();\n if (!rc || rc.width <= 0 || rc.height <= 0 || containerW <= 0 || panelH <= 0) return 1;\n return Math.min(containerW / rc.width, panelH / rc.height, 1);\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 // اگه فیلترِ فعلاً انتخابشده دیگه توی لیستِ مجازِ filters() نباشه (مثلاً\n // مصرفکننده cartoon رو غیرفعال کرده درحالیکه کاربر روش بود)، برو روی\n // اولین فیلترِ مجاز؛ اگه لیست خالی باشه (کلاً فیلتر مخفیه)، روی none بمون.\n effect(() => {\n const allowed = this.filters();\n if (allowed.length && !allowed.includes(this.filterPreset())) {\n this.filterPreset.set(allowed[0]);\n }\n });\n\n // اندازهگیریِ زندهی عرضِ واقعیِ کانتینر — چون عرض همیشه ۱۰۰٪ (fluid)ه،\n // فقط با ResizeObserver میشه فهمید الان چند پیکسله (نه یه عددِ ثابتِ ورودی).\n effect((onCleanup) => {\n const el = this.stageWrapEl()?.nativeElement;\n if (!el) return;\n this.containerWidth.set(el.getBoundingClientRect().width);\n const ro = new ResizeObserver((entries) => {\n const width = entries[0]?.contentRect.width;\n if (width != null) this.containerWidth.set(width);\n });\n ro.observe(el);\n onCleanup(() => ro.disconnect());\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(this.filters()[0] ?? '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\" #stageWrap>\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-row\">\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 <div class=\"ngx-ie-field\">\n <slider\n [ngModel]=\"rotation()\"\n (ngModelChange)=\"rotation.set($event)\"\n [min]=\"-180\"\n [max]=\"180\">\n <span>{{ localize().Rotation }} ({{ rotation() }}°)</span>\n </slider>\n\n <button\n type=\"button\"\n (click)=\"rotation.set(0)\"\n class=\"ngx-ie-btn-secondary\"\n [title]=\"localize().Reset\">\n x\n </button>\n </div>\n\n <div class=\"ngx-ie-field\">\n <slider\n [ngModel]=\"brightness()\"\n (ngModelChange)=\"brightness.set($event)\"\n [min]=\"0\"\n [max]=\"200\">\n <span>{{ localize().Brightness }} ({{ brightness() }}%)</span>\n </slider>\n <button\n type=\"button\"\n (click)=\"brightness.set(100)\"\n class=\"ngx-ie-btn-secondary\"\n [title]=\"localize().Reset\">\n x\n </button>\n </div>\n\n <div class=\"ngx-ie-field\">\n <slider\n [ngModel]=\"contrast()\"\n (ngModelChange)=\"contrast.set($event)\"\n [min]=\"0\"\n [max]=\"200\">\n <span>{{ localize().Contrast }} ({{ contrast() }}%)</span>\n </slider>\n <button\n type=\"button\"\n (click)=\"contrast.set(100)\"\n class=\"ngx-ie-btn-secondary\"\n [title]=\"localize().Reset\">\n x\n </button>\n </div>\n\n <div class=\"ngx-ie-field\">\n <slider\n [ngModel]=\"saturation()\"\n (ngModelChange)=\"saturation.set($event)\"\n [min]=\"0\"\n [max]=\"200\">\n <span>{{ localize().Saturation }} ({{ saturation() }}%)</span>\n </slider>\n <button\n type=\"button\"\n (click)=\"saturation.set(100)\"\n class=\"ngx-ie-btn-secondary\"\n [title]=\"localize().Reset\">\n x\n </button>\n </div>\n\n @if (filters().length) {\n <div>\n <span>{{ localize().Filter }}</span>\n <div class=\"ngx-ie-filter-row\">\n @for (f of filters(); track f) {\n <button type=\"button\" [class.active]=\"filterPreset() === f\" (click)=\"setFilter(f)\">\n {{ filterLabels()[f] }}\n </button>\n }\n </div>\n </div>\n }\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 </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';\n\nexport const NGX_IMAGE_EDITOR_LOCALIZATION = new InjectionToken<NgxImageEditorLocalization>(\n 'ngx-image-localization',\n {\n factory: () => DEFAULT_NGX_IMAGE_EDITOR_LOCALIZATION,\n },\n);\n\nexport class NgxImageEditorLocalization {\n LoadingImage = 'Loading image…';\n Rotation = 'Fine rotation';\n Brightness = 'Brightness';\n Contrast = 'Contrast';\n Saturation = 'Saturation';\n Filter = 'Filter';\n None = 'None';\n Grayscale = 'Grayscale';\n Sepia = 'Sepia';\n Invert = 'Invert';\n Cartoon = 'Cartoon';\n Cancel = 'Cancel';\n Save = 'Save';\n Saving = 'Saving…';\n Reset = 'Reset';\n}\nexport const DEFAULT_NGX_IMAGE_EDITOR_LOCALIZATION = new NgxImageEditorLocalization();\n","import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n viewChild,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { SliderComponent } from 'ngx-kit/core';\nimport {\n NgxCropRect,\n NgxImageEditorAdjustments,\n NgxImageEditorResult,\n NgxImageFilterPreset,\n type NgxImageFileType,\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 '../tokens/localization';\n\nconst ALL_FILTERS: NgxImageFilterPreset[] = ['none', 'grayscale', 'sepia', 'invert', 'cartoon'];\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 NgxImageEditor {\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<NgxImageFileType>('image/jpeg');\n\n /**\n * کدوم فیلترها نشون داده بشن (و به چه ترتیبی). اگه ندید، هر ۵ تا نشون داده\n * میشن. آرایهی خالی یعنی کلِ بخشِ فیلتر مخفی بشه.\n */\n filters = input<NgxImageFilterPreset[]>(ALL_FILTERS);\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 private readonly stageWrapEl = viewChild<ElementRef<HTMLElement>>('stageWrap');\n /** عرضِ واقعیِ رندرشدهی کانتینر؛ چون عرض همیشه ۱۰۰٪ (fluid) هست، باید زنده اندازهگیری بشه */\n private readonly containerWidth = signal(0);\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 protected readonly filterLabels = computed<Record<NgxImageFilterPreset, string>>(() => {\n const t = this.localize();\n return {\n none: t.None,\n grayscale: t.Grayscale,\n sepia: t.Sepia,\n invert: t.Invert,\n cartoon: t.Cartoon,\n };\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 panelSize = computed(() => {\n return this.stageWrapEl()?.nativeElement.getBoundingClientRect().height ?? 0;\n });\n\n /**\n * مقیاسِ «contain» واقعی: کوچیکترینِ نسبتِ عرض و ارتفاع (هرکدوم تنگتره)\n * تعیینکنندهست، و سقفش هم ۱ هست تا تصاویر کوچیک بزرگنمایی نشن.\n */\n protected readonly displayScale = computed(() => {\n const rc = this.rotatedWorkingCanvas();\n const containerW = this.containerWidth();\n const panelH = this.panelSize();\n if (!rc || rc.width <= 0 || rc.height <= 0 || containerW <= 0 || panelH <= 0) return 1;\n return Math.min(containerW / rc.width, panelH / rc.height, 1);\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 // اگه فیلترِ فعلاً انتخابشده دیگه توی لیستِ مجازِ filters() نباشه (مثلاً\n // مصرفکننده cartoon رو غیرفعال کرده درحالیکه کاربر روش بود)، برو روی\n // اولین فیلترِ مجاز؛ اگه لیست خالی باشه (کلاً فیلتر مخفیه)، روی none بمون.\n effect(() => {\n const allowed = this.filters();\n if (allowed.length && !allowed.includes(this.filterPreset())) {\n this.filterPreset.set(allowed[0]);\n }\n });\n\n // اندازهگیریِ زندهی عرضِ واقعیِ کانتینر — چون عرض همیشه ۱۰۰٪ (fluid)ه،\n // فقط با ResizeObserver میشه فهمید الان چند پیکسله (نه یه عددِ ثابتِ ورودی).\n effect((onCleanup) => {\n const el = this.stageWrapEl()?.nativeElement;\n if (!el) return;\n this.containerWidth.set(el.getBoundingClientRect().width);\n const ro = new ResizeObserver((entries) => {\n const width = entries[0]?.contentRect.width;\n if (width != null) this.containerWidth.set(width);\n });\n ro.observe(el);\n onCleanup(() => ro.disconnect());\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(this.filters()[0] ?? '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 const file = new File([blob], '', { type });\n this.saved.emit({\n blob,\n dataUrl,\n width: finalCanvas.width,\n height: finalCanvas.height,\n file,\n type,\n });\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\" #stageWrap>\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-row\">\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 <div class=\"ngx-ie-field\">\n <slider\n [ngModel]=\"rotation()\"\n (ngModelChange)=\"rotation.set($event)\"\n [min]=\"-180\"\n [max]=\"180\">\n <span>{{ localize().Rotation }} ({{ rotation() }}°)</span>\n </slider>\n\n <button\n type=\"button\"\n (click)=\"rotation.set(0)\"\n class=\"ngx-ie-btn-secondary\"\n [title]=\"localize().Reset\">\n x\n </button>\n </div>\n\n <div class=\"ngx-ie-field\">\n <slider\n [ngModel]=\"brightness()\"\n (ngModelChange)=\"brightness.set($event)\"\n [min]=\"0\"\n [max]=\"200\">\n <span>{{ localize().Brightness }} ({{ brightness() }}%)</span>\n </slider>\n <button\n type=\"button\"\n (click)=\"brightness.set(100)\"\n class=\"ngx-ie-btn-secondary\"\n [title]=\"localize().Reset\">\n x\n </button>\n </div>\n\n <div class=\"ngx-ie-field\">\n <slider\n [ngModel]=\"contrast()\"\n (ngModelChange)=\"contrast.set($event)\"\n [min]=\"0\"\n [max]=\"200\">\n <span>{{ localize().Contrast }} ({{ contrast() }}%)</span>\n </slider>\n <button\n type=\"button\"\n (click)=\"contrast.set(100)\"\n class=\"ngx-ie-btn-secondary\"\n [title]=\"localize().Reset\">\n x\n </button>\n </div>\n\n <div class=\"ngx-ie-field\">\n <slider\n [ngModel]=\"saturation()\"\n (ngModelChange)=\"saturation.set($event)\"\n [min]=\"0\"\n [max]=\"200\">\n <span>{{ localize().Saturation }} ({{ saturation() }}%)</span>\n </slider>\n <button\n type=\"button\"\n (click)=\"saturation.set(100)\"\n class=\"ngx-ie-btn-secondary\"\n [title]=\"localize().Reset\">\n x\n </button>\n </div>\n\n @if (filters().length) {\n <div>\n <span>{{ localize().Filter }}</span>\n <div class=\"ngx-ie-filter-row\">\n @for (f of filters(); track f) {\n <button type=\"button\" [class.active]=\"filterPreset() === f\" (click)=\"setFilter(f)\">\n {{ filterLabels()[f] }}\n </button>\n }\n </div>\n </div>\n }\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 </div>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|