ngx-kit 7.3.1 → 7.3.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"ngx-kit-dropzone.mjs","sources":["../../../projects/libs/dropzone/services/ngx-dropzone-http-upload.service.ts","../../../projects/libs/dropzone/services/ngx-dropzone-upload.token.ts","../../../projects/libs/dropzone/utils/file-matching.ts","../../../projects/libs/dropzone/components/dropzone.component.ts","../../../projects/libs/dropzone/components/dropzone.component.html","../../../projects/libs/dropzone/ngx-kit-dropzone.ts"],"sourcesContent":["import {\n HttpClient,\n HttpEvent,\n HttpEventType,\n HttpHeaders,\n HttpResponse,\n HttpUploadProgressEvent,\n} from '@angular/common/http';\nimport { Injectable, inject } from '@angular/core';\nimport { Observable, filter, map } from 'rxjs';\nimport {\n NgxDropzoneUploadEvent,\n NgxDropzoneUploadRequest,\n NgxDropzoneUploadService,\n} from '../contracts/dropzone-upload';\n\n@Injectable({ providedIn: 'root' })\nexport class NgxDropzoneHttpUploadService implements NgxDropzoneUploadService {\n private readonly http = inject(HttpClient);\n\n upload<TResponse = unknown>(\n request: NgxDropzoneUploadRequest,\n ): Observable<NgxDropzoneUploadEvent<TResponse>> {\n const body = new FormData();\n body.append(request.alias, request.file, request.file.name);\n\n for (const [key, value] of Object.entries(request.data ?? {})) {\n body.append(key, value instanceof Blob ? value : String(value));\n }\n\n const headers =\n request.headers instanceof HttpHeaders ? request.headers : new HttpHeaders(request.headers);\n\n return this.http\n .post<TResponse>(request.url, body, {\n headers,\n withCredentials: request.withCredentials ?? false,\n observe: 'events',\n reportProgress: true,\n })\n .pipe(\n filter(\n (event): event is HttpUploadProgressEvent | HttpResponse<TResponse> =>\n event.type === HttpEventType.UploadProgress || event.type === HttpEventType.Response,\n ),\n map((event): NgxDropzoneUploadEvent<TResponse> => {\n if (event.type === HttpEventType.UploadProgress) {\n const total = event.total;\n\n return {\n type: 'progress',\n loaded: event.loaded,\n total,\n percent: total ? Math.min(100, Math.round((event.loaded / total) * 100)) : 0,\n };\n }\n\n return {\n type: 'response',\n response: event.body as TResponse,\n status: event.status,\n headers: event.headers,\n };\n }),\n );\n }\n}\n","import { InjectionToken, inject } from '@angular/core';\nimport { NgxDropzoneHttpUploadService } from './ngx-dropzone-http-upload.service';\nimport { NgxDropzoneUploadService } from '../contracts/dropzone-upload';\n\n/**\n * Upload adapter used by ngx-dropzone.\n *\n * Default: Angular HttpClient.\n * Override this token at application/component level to use Axios or any\n * other upload implementation.\n */\nexport const NGX_DROPZONE_UPLOAD_SERVICE = new InjectionToken<NgxDropzoneUploadService>(\n 'NGX_DROPZONE_UPLOAD_SERVICE',\n {\n providedIn: 'root',\n factory: () => inject(NgxDropzoneHttpUploadService),\n },\n);\n","/**\n * چک می‌کنه یه فایل با pattern رشته‌ای accept (مثل input[type=file])\n * مطابقت داره یا نه. پشتیبانی می‌شه از:\n * - MIME کامل: \"image/png\"\n * - MIME با wildcard: \"image/*\"\n * - پسوند فایل: \".png\", \".jpg\"\n * - لیست کاما-جدا از موارد بالا: \"image/*,.pdf,.docx\"\n */\nexport function matchesAccept(file: File, accept?: string): boolean {\n if (!accept || accept.trim() === '') return true;\n\n const patterns = accept\n .split(',')\n .map((p) => p.trim().toLowerCase())\n .filter(Boolean);\n\n if (!patterns.length) return true;\n\n const fileName = file.name.toLowerCase();\n const fileType = (file.type || '').toLowerCase();\n\n return patterns.some((pattern) => {\n if (pattern.startsWith('.')) {\n return fileName.endsWith(pattern);\n }\n if (pattern.endsWith('/*')) {\n const prefix = pattern.slice(0, -1); // \"image/\"\n return fileType.startsWith(prefix);\n }\n return fileType === pattern;\n });\n}\n\n/** تبدیل بایت به یه رشته‌ی خوانا (KB/MB/GB) */\nexport function formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B';\n const units = ['B', 'KB', 'MB', 'GB', 'TB'];\n const i = Math.floor(Math.log(bytes) / Math.log(1024));\n const value = bytes / Math.pow(1024, i);\n return `${value.toFixed(i === 0 ? 0 : 1)} ${units[i]}`;\n}\n\n/** استخراج فایل‌های واقعی از یک DataTransfer، شامل پیمایش بازگشتیِ پوشه‌ها (وقتی مرورگر پشتیبانی کنه) */\nexport async function extractFilesFromDataTransfer(dataTransfer: DataTransfer): Promise<File[]> {\n const items = Array.from(dataTransfer.items || []);\n const hasEntrySupport = items.length > 0 && typeof items[0].webkitGetAsEntry === 'function';\n\n if (!hasEntrySupport) {\n return Array.from(dataTransfer.files || []);\n }\n\n const entries = items\n .map((item) => item.webkitGetAsEntry?.())\n .filter((e): e is FileSystemEntry => !!e);\n\n if (!entries.length) {\n return Array.from(dataTransfer.files || []);\n }\n\n const files: File[] = [];\n await Promise.all(entries.map((entry) => walkEntry(entry, files)));\n return files;\n}\n\nfunction walkEntry(entry: FileSystemEntry, out: File[]): Promise<void> {\n return new Promise((resolve) => {\n if (entry.isFile) {\n (entry as FileSystemFileEntry).file(\n (file) => {\n out.push(file);\n resolve();\n },\n () => resolve(),\n );\n } else if (entry.isDirectory) {\n const reader = (entry as FileSystemDirectoryEntry).createReader();\n const readAll: FileSystemEntry[] = [];\n const readBatch = () => {\n reader.readEntries(\n async (batch) => {\n if (!batch.length) {\n await Promise.all(readAll.map((e) => walkEntry(e, out)));\n resolve();\n return;\n }\n readAll.push(...batch);\n readBatch();\n },\n () => resolve(),\n );\n };\n readBatch();\n } else {\n resolve();\n }\n });\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n OnDestroy,\n computed,\n inject,\n input,\n output,\n signal,\n viewChild,\n} from '@angular/core';\nimport { Subscription, finalize } from 'rxjs';\nimport {\n NgxDropzoneFile,\n NgxDropzoneRejectedFile,\n NgxDropzoneRejectionReason,\n} from '../contracts/dropzone-file';\nimport {\n NgxDropzoneUploadProgressEvent,\n NgxDropzoneUploadService,\n} from '../contracts/dropzone-upload';\nimport { NGX_DROPZONE_UPLOAD_SERVICE } from '../services/ngx-dropzone-upload.token';\nimport { extractFilesFromDataTransfer, formatBytes, matchesAccept } from '../utils/file-matching';\n\nlet uidCounter = 0;\nfunction nextId(): string {\n return `ngx-dz-${Date.now().toString(36)}-${uidCounter++}`;\n}\n\nexport type NgxDropzoneUploadMode = 'all' | 'single';\n\n@Component({\n selector: 'ngx-dropzone',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './dropzone.component.html',\n styleUrl: './dropzone.component.scss',\n host: {\n class: 'ngx-dropzone-host',\n },\n})\nexport class NgxDropzoneComponent implements OnDestroy {\n /** الگوی accept مثل input[type=file]: \"image/*\", \".pdf,.docx\" و ... */\n accept = input<string>('');\n multiple = input<boolean>(true);\n /** حداکثر حجم هر فایل به بایت؛ undefined یعنی بدون محدودیت */\n maxFileSize = input<number | undefined>(undefined);\n /** حداکثر تعداد فایل مجاز؛ undefined یعنی بدون محدودیت */\n maxFiles = input<number | undefined>(undefined);\n disabled = input<boolean>(false);\n /** نمایش لیست/پیش‌نمایش فایل‌های انتخاب‌شده داخل خودِ کامپوننت */\n showFileList = input<boolean>(true);\n\n /** Upload endpoint. */\n uploadUrl = input<string>('');\n /** Multipart form-data field name. */\n uploadAlias = input<string>('file');\n /** Automatically enqueue newly accepted files for upload. */\n autoUpload = input<boolean>(false);\n /** Maximum number of simultaneous uploads. */\n maxParallel = input<number>(3);\n /**\n * Manual upload behavior:\n * - all: one \"Upload all\" action uploads all pending files.\n * - single: every pending row gets its own Upload button.\n */\n uploadMode = input<NgxDropzoneUploadMode>('all');\n /** Extra multipart form fields sent with every file. */\n uploadData = input<Record<string, string | Blob | number | boolean>>({});\n /** Optional request headers. */\n uploadHeaders = input<Record<string, string | string[]>>({});\n /** Send credentials/cookies with the upload request. */\n uploadWithCredentials = input<boolean>(false);\n\n filesAdded = output<File[]>();\n filesRejected = output<NgxDropzoneRejectedFile[]>();\n filesChange = output<File[]>();\n\n /** Emitted when an individual upload starts. */\n uploadStarted = output<NgxDropzoneFile>();\n /** Emitted for every upload progress update. */\n uploadProgress = output<NgxDropzoneUploadProgressEvent>();\n /** Emitted after a file is successfully uploaded. */\n uploadSuccess = output<NgxDropzoneFile>();\n /** Emitted when an upload fails. */\n uploadError = output<{ item: NgxDropzoneFile; error: unknown }>();\n\n protected readonly files = signal<NgxDropzoneFile[]>([]);\n protected readonly isDragging = signal(false);\n private dragCounter = 0;\n\n private readonly uploadService = inject<NgxDropzoneUploadService>(NGX_DROPZONE_UPLOAD_SERVICE);\n private readonly fileInput = viewChild<ElementRef<HTMLInputElement>>('fileInput');\n private readonly uploadSubscriptions = new Map<string, Subscription>();\n private readonly uploadQueue: string[] = [];\n private activeUploads = 0;\n private readonly activeUploadIds = new Set<string>();\n\n protected readonly pendingCount = computed(\n () => this.files().filter((item) => this.isPending(item)).length,\n );\n\n protected readonly hasUploadConfiguration = computed(() => this.uploadUrl().trim().length > 0);\n\n protected readonly hint = computed(() => {\n const parts: string[] = [];\n const accept = this.accept();\n if (accept) parts.push(accept);\n const max = this.maxFileSize();\n if (max) parts.push(`max ${formatBytes(max)}`);\n return parts.join(' · ');\n });\n\n protected formatSize(bytes: number): string {\n return formatBytes(bytes);\n }\n\n protected isPending(item: NgxDropzoneFile): boolean {\n return item.status === 'pending' || item.status === 'accepted';\n }\n\n protected trackById(_index: number, item: NgxDropzoneFile): string {\n return item.id;\n }\n\n ngOnDestroy(): void {\n for (const subscription of this.uploadSubscriptions.values()) {\n subscription.unsubscribe();\n }\n this.uploadSubscriptions.clear();\n\n for (const item of this.files()) {\n if (item.previewUrl) URL.revokeObjectURL(item.previewUrl);\n }\n }\n\n protected onDragEnter(ev: DragEvent): void {\n ev.preventDefault();\n if (this.disabled()) return;\n this.dragCounter++;\n this.isDragging.set(true);\n }\n\n protected onDragOver(ev: DragEvent): void {\n ev.preventDefault();\n if (ev.dataTransfer) {\n ev.dataTransfer.dropEffect = this.disabled() ? 'none' : 'copy';\n }\n }\n\n protected onDragLeave(ev: DragEvent): void {\n ev.preventDefault();\n if (this.disabled()) return;\n this.dragCounter = Math.max(0, this.dragCounter - 1);\n if (this.dragCounter === 0) this.isDragging.set(false);\n }\n\n protected async onDrop(ev: DragEvent): Promise<void> {\n ev.preventDefault();\n this.dragCounter = 0;\n this.isDragging.set(false);\n if (this.disabled() || !ev.dataTransfer) return;\n\n const files = await extractFilesFromDataTransfer(ev.dataTransfer);\n this.handleIncomingFiles(files);\n }\n\n protected onBrowseClick(): void {\n if (this.disabled()) return;\n this.fileInput()?.nativeElement.click();\n }\n\n protected onKeydown(ev: KeyboardEvent): void {\n if (ev.key === 'Enter' || ev.key === ' ') {\n ev.preventDefault();\n this.onBrowseClick();\n }\n }\n\n protected onFileInputChange(ev: Event): void {\n const input = ev.target as HTMLInputElement;\n const files = Array.from(input.files ?? []);\n this.handleIncomingFiles(files);\n input.value = '';\n }\n\n protected removeFile(id: string): void {\n const target = this.files().find((f) => f.id === id);\n this.uploadSubscriptions.get(id)?.unsubscribe();\n this.uploadSubscriptions.delete(id);\n\n // Unsubscribing an HttpClient upload cancels the request. Release its\n // concurrency slot immediately; finalize() will see that the id is no\n // longer active and won't decrement twice.\n if (this.activeUploadIds.delete(id)) {\n this.activeUploads = Math.max(0, this.activeUploads - 1);\n }\n\n if (target?.previewUrl) URL.revokeObjectURL(target.previewUrl);\n\n this.files.update((list) => list.filter((f) => f.id !== id));\n\n // Remove stale queue entries. The queue is intentionally lazy, so an\n // entry can safely remain until pumpQueue() sees that it no longer exists.\n this.emitCurrentFiles();\n this.pumpQueue();\n }\n\n protected uploadAll(): void {\n this.enqueueUploads(\n this.files()\n .filter((item) => this.isPending(item))\n .map((item) => item.id),\n );\n }\n\n protected uploadSingle(id: string): void {\n this.enqueueUploads([id]);\n }\n\n protected retryUpload(id: string): void {\n this.files.update((list) =>\n list.map((item) =>\n item.id === id ? { ...item, status: 'pending', progress: 0, error: undefined } : item,\n ),\n );\n this.enqueueUploads([id]);\n }\n\n private handleIncomingFiles(incoming: File[]): void {\n if (!incoming.length) return;\n\n const accepted: NgxDropzoneFile[] = [];\n const rejected: NgxDropzoneRejectedFile[] = [];\n\n // A single-file dropzone behaves like a native single-select input:\n // selecting another file replaces the previous one.\n const existingCount = this.multiple() ? this.files().length : 0;\n const maxFiles = this.maxFiles();\n const maxSize = this.maxFileSize();\n const isMultiple = this.multiple();\n\n const pool = isMultiple ? incoming : incoming.slice(0, 1);\n\n for (const file of pool) {\n let reason: NgxDropzoneRejectionReason | undefined;\n\n if (!matchesAccept(file, this.accept())) {\n reason = 'type';\n } else if (maxSize != null && file.size > maxSize) {\n reason = 'size';\n } else if (maxFiles != null && existingCount + accepted.length >= maxFiles) {\n reason = 'count';\n }\n\n if (reason) {\n rejected.push({ file, reason });\n continue;\n }\n\n const isImage = file.type.startsWith('image/');\n accepted.push({\n id: nextId(),\n file,\n previewUrl: isImage ? URL.createObjectURL(file) : undefined,\n status: 'accepted',\n progress: 0,\n });\n }\n\n if (accepted.length) {\n if (!isMultiple) {\n for (const previous of this.files()) {\n this.uploadSubscriptions.get(previous.id)?.unsubscribe();\n this.uploadSubscriptions.delete(previous.id);\n this.activeUploadIds.delete(previous.id);\n if (previous.previewUrl) URL.revokeObjectURL(previous.previewUrl);\n }\n this.activeUploads = this.activeUploadIds.size;\n }\n\n this.files.update((list) => (isMultiple ? [...list, ...accepted] : accepted));\n this.filesAdded.emit(accepted.map((a) => a.file));\n this.emitCurrentFiles();\n\n if (this.autoUpload()) {\n this.enqueueUploads(accepted.map((item) => item.id));\n }\n }\n\n if (rejected.length) {\n this.filesRejected.emit(rejected);\n }\n }\n\n private enqueueUploads(ids: string[]): void {\n if (!this.uploadUrl().trim()) {\n const error = new Error('ngx-dropzone: uploadUrl is required for uploading files.');\n for (const id of ids) this.markUploadError(id, error, false);\n return;\n }\n\n const queued = new Set(this.uploadQueue);\n for (const id of ids) {\n const item = this.files().find((file) => file.id === id);\n if (!item || !this.isPending(item) || queued.has(id)) continue;\n this.uploadQueue.push(id);\n queued.add(id);\n }\n\n this.pumpQueue();\n }\n\n private pumpQueue(): void {\n const limit = Math.max(1, Math.floor(this.maxParallel() || 1));\n\n while (this.activeUploads < limit && this.uploadQueue.length) {\n const id = this.uploadQueue.shift()!;\n const item = this.files().find((file) => file.id === id);\n\n if (!item || !this.isPending(item)) continue;\n\n this.startUpload(item);\n }\n }\n\n private startUpload(item: NgxDropzoneFile): void {\n this.activeUploads++;\n this.activeUploadIds.add(item.id);\n\n this.updateFile(item.id, {\n status: 'uploading',\n progress: 0,\n error: undefined,\n });\n\n const current = this.files().find((file) => file.id === item.id);\n if (current) this.uploadStarted.emit(current);\n\n let subscription: Subscription;\n\n try {\n subscription = this.uploadService\n .upload({\n url: this.uploadUrl(),\n alias: this.uploadAlias() || 'file',\n file: item.file,\n data: this.uploadData(),\n headers: this.uploadHeaders(),\n withCredentials: this.uploadWithCredentials(),\n })\n .pipe(finalize(() => this.finishUpload(item.id)))\n .subscribe({\n next: (event) => {\n if (event.type === 'progress') {\n this.updateFile(item.id, {\n progress: event.percent,\n });\n\n const updated = this.files().find((file) => file.id === item.id);\n if (updated) {\n this.uploadProgress.emit({\n item: updated,\n loaded: event.loaded,\n total: event.total,\n percent: event.percent,\n });\n }\n return;\n }\n\n this.updateFile(item.id, {\n status: 'uploaded',\n progress: 100,\n response: event.response,\n error: undefined,\n });\n\n const updated = this.files().find((file) => file.id === item.id);\n if (updated) this.uploadSuccess.emit(updated);\n },\n error: (error) => {\n this.markUploadError(item.id, error, true);\n },\n });\n } catch (error) {\n this.markUploadError(item.id, error, true);\n this.finishUpload(item.id);\n return;\n }\n\n if (!subscription.closed) this.uploadSubscriptions.set(item.id, subscription);\n }\n\n private markUploadError(id: string, error: unknown, releaseActiveSlot: boolean): void {\n this.updateFile(id, {\n status: 'error',\n error,\n });\n\n const item = this.files().find((file) => file.id === id);\n if (item) this.uploadError.emit({ item, error });\n\n if (!releaseActiveSlot) {\n this.pumpQueue();\n }\n }\n\n private finishUpload(id: string): void {\n this.uploadSubscriptions.delete(id);\n\n if (this.activeUploadIds.delete(id)) {\n this.activeUploads = Math.max(0, this.activeUploads - 1);\n }\n\n this.pumpQueue();\n }\n\n private updateFile(id: string, patch: Partial<NgxDropzoneFile>): void {\n this.files.update((list) =>\n list.map((item) => (item.id === id ? { ...item, ...patch } : item)),\n );\n }\n\n private emitCurrentFiles(): void {\n this.filesChange.emit(this.files().map((f) => f.file));\n }\n}\n","<div\n class=\"ngx-dropzone\"\n [class.dragging]=\"isDragging()\"\n [class.disabled]=\"disabled()\"\n [class.has-files]=\"files().length > 0\"\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-disabled]=\"disabled()\"\n (click)=\"onBrowseClick()\"\n (keydown)=\"onKeydown($event)\"\n (dragenter)=\"onDragEnter($event)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n <input\n #fileInput\n type=\"file\"\n class=\"ngx-dropzone-input\"\n [accept]=\"accept()\"\n [multiple]=\"multiple()\"\n [disabled]=\"disabled()\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"onFileInputChange($event)\" />\n\n <div class=\"ngx-dropzone-icon-wrap\">\n <ng-content select=\"[dropzone-icon]\">\n <svg class=\"ngx-dropzone-icon\" viewBox=\"0 0 24 24\" fill=\"none\" width=\"30\" height=\"30\">\n <path\n d=\"M12 16V4M12 4l-4 4M12 4l4 4M4 16v2a2 2 0 002 2h12a2 2 0 002-2v-2\"\n stroke=\"currentColor\"\n stroke-width=\"1.8\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </ng-content>\n </div>\n\n <div class=\"ngx-dropzone-text\">\n <ng-content>\n <strong>Drop files here</strong>\n <span>or click to browse</span>\n </ng-content>\n </div>\n\n @if (hint()) {\n <div class=\"ngx-dropzone-hint\">{{ hint() }}</div>\n }\n</div>\n\n@if (!autoUpload() && uploadMode() === 'all' && pendingCount() > 0) {\n <div class=\"ngx-dropzone-actions\">\n <button\n type=\"button\"\n class=\"ngx-dropzone-upload-all\"\n [disabled]=\"disabled() || !hasUploadConfiguration()\"\n (click)=\"uploadAll(); $event.stopPropagation()\">\n Upload all\n <span>{{ pendingCount() }}</span>\n </button>\n </div>\n}\n\n@if (showFileList() && files().length) {\n <ul class=\"ngx-dropzone-list\">\n @for (item of files(); track item.id) {\n <li class=\"ngx-dropzone-item\" [class.is-uploading]=\"item.status === 'uploading'\">\n <div class=\"ngx-dropzone-thumb-wrap\">\n @if (item.previewUrl) {\n <img class=\"ngx-dropzone-thumb\" [src]=\"item.previewUrl\" [alt]=\"item.file.name\" />\n } @else {\n <span class=\"ngx-dropzone-file-icon\">📄</span>\n }\n </div>\n\n <div class=\"ngx-dropzone-meta\">\n <span class=\"ngx-dropzone-name\" [title]=\"item.file.name\">{{ item.file.name }}</span>\n <span class=\"ngx-dropzone-size\">{{ formatSize(item.file.size) }}</span>\n\n @if (item.status === 'uploading' || item.status === 'uploaded') {\n <div\n class=\"ngx-dropzone-progress\"\n role=\"progressbar\"\n [attr.aria-valuenow]=\"item.progress\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n [attr.aria-label]=\"'Upload progress for ' + item.file.name\">\n <span class=\"ngx-dropzone-progress-bar\" [style.width.%]=\"item.progress\"></span>\n </div>\n <span class=\"ngx-dropzone-progress-text\">{{ item.progress }}%</span>\n }\n\n @if (item.status === 'error') {\n <span class=\"ngx-dropzone-error\">Upload failed</span>\n }\n </div>\n\n <div class=\"ngx-dropzone-row-actions\">\n @if (!autoUpload() && uploadMode() === 'single' && isPending(item)) {\n <button\n type=\"button\"\n class=\"ngx-dropzone-upload\"\n [disabled]=\"disabled() || !hasUploadConfiguration()\"\n [attr.aria-label]=\"'Upload ' + item.file.name\"\n (click)=\"uploadSingle(item.id); $event.stopPropagation()\">\n Upload\n </button>\n }\n\n @if (item.status === 'error') {\n <button\n type=\"button\"\n class=\"ngx-dropzone-retry\"\n [disabled]=\"disabled() || !hasUploadConfiguration()\"\n [attr.aria-label]=\"'Retry upload for ' + item.file.name\"\n (click)=\"retryUpload(item.id); $event.stopPropagation()\">\n Retry\n </button>\n }\n\n @if (item.status === 'uploaded') {\n <span class=\"ngx-dropzone-status success\" aria-label=\"Uploaded\">✓</span>\n } @else if (item.status === 'uploading') {\n <span class=\"ngx-dropzone-status uploading\" aria-label=\"Uploading\"></span>\n } @else if (item.status === 'error') {\n <span class=\"ngx-dropzone-status error\" aria-label=\"Upload failed\">!</span>\n } @else {\n <span class=\"ngx-dropzone-status pending\" aria-label=\"Pending\">•</span>\n }\n\n <button\n type=\"button\"\n class=\"ngx-dropzone-remove\"\n [attr.aria-label]=\"'Remove ' + item.file.name\"\n (click)=\"removeFile(item.id); $event.stopPropagation()\">\n ✕\n </button>\n </div>\n </li>\n }\n </ul>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;MAiBa,4BAA4B,CAAA;AACtB,IAAA,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC;AAE1C,IAAA,MAAM,CACJ,OAAiC,EAAA;AAEjC,QAAA,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE;AAC3B,QAAA,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;AAE3D,QAAA,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE;YAC7D,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,YAAY,IAAI,GAAG,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QACjE;QAEA,MAAM,OAAO,GACX,OAAO,CAAC,OAAO,YAAY,WAAW,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC;QAE7F,OAAO,IAAI,CAAC;AACT,aAAA,IAAI,CAAY,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE;YAClC,OAAO;AACP,YAAA,eAAe,EAAE,OAAO,CAAC,eAAe,IAAI,KAAK;AACjD,YAAA,OAAO,EAAE,QAAQ;AACjB,YAAA,cAAc,EAAE,IAAI;SACrB;AACA,aAAA,IAAI,CACH,MAAM,CACJ,CAAC,KAAK,KACJ,KAAK,CAAC,IAAI,KAAK,aAAa,CAAC,cAAc,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,CAAC,QAAQ,CACvF,EACD,GAAG,CAAC,CAAC,KAAK,KAAuC;YAC/C,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,CAAC,cAAc,EAAE;AAC/C,gBAAA,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK;gBAEzB,OAAO;AACL,oBAAA,IAAI,EAAE,UAAU;oBAChB,MAAM,EAAE,KAAK,CAAC,MAAM;oBACpB,KAAK;AACL,oBAAA,OAAO,EAAE,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC;iBAC7E;YACH;YAEA,OAAO;AACL,gBAAA,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE,KAAK,CAAC,IAAiB;gBACjC,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,OAAO,EAAE,KAAK,CAAC,OAAO;aACvB;QACH,CAAC,CAAC,CACH;IACL;uGAhDW,4BAA4B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAA5B,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,4BAA4B,cADf,MAAM,EAAA,CAAA;;2FACnB,4BAA4B,EAAA,UAAA,EAAA,CAAA;kBADxC,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;ACZlC;;;;;;AAMG;MACU,2BAA2B,GAAG,IAAI,cAAc,CAC3D,6BAA6B,EAC7B;AACE,IAAA,UAAU,EAAE,MAAM;AAClB,IAAA,OAAO,EAAE,MAAM,MAAM,CAAC,4BAA4B,CAAC;AACpD,CAAA;;AChBH;;;;;;;AAOG;AACG,SAAU,aAAa,CAAC,IAAU,EAAE,MAAe,EAAA;IACvD,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE;AAAE,QAAA,OAAO,IAAI;IAEhD,MAAM,QAAQ,GAAG;SACd,KAAK,CAAC,GAAG;AACT,SAAA,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE;SACjC,MAAM,CAAC,OAAO,CAAC;IAElB,IAAI,CAAC,QAAQ,CAAC,MAAM;AAAE,QAAA,OAAO,IAAI;IAEjC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;AACxC,IAAA,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,EAAE,WAAW,EAAE;AAEhD,IAAA,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,KAAI;AAC/B,QAAA,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;AAC3B,YAAA,OAAO,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC;QACnC;AACA,QAAA,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;AAC1B,YAAA,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACpC,YAAA,OAAO,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC;QACpC;QACA,OAAO,QAAQ,KAAK,OAAO;AAC7B,IAAA,CAAC,CAAC;AACJ;AAEA;AACM,SAAU,WAAW,CAAC,KAAa,EAAA;IACvC,IAAI,KAAK,KAAK,CAAC;AAAE,QAAA,OAAO,KAAK;AAC7B,IAAA,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;IAC3C,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACtD,IAAA,MAAM,KAAK,GAAG,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IACvC,OAAO,CAAA,EAAG,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA,CAAA,EAAI,KAAK,CAAC,CAAC,CAAC,CAAA,CAAE;AACxD;AAEA;AACO,eAAe,4BAA4B,CAAC,YAA0B,EAAA;AAC3E,IAAA,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,IAAI,EAAE,CAAC;AAClD,IAAA,MAAM,eAAe,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,gBAAgB,KAAK,UAAU;IAE3F,IAAI,CAAC,eAAe,EAAE;QACpB,OAAO,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,IAAI,EAAE,CAAC;IAC7C;IAEA,MAAM,OAAO,GAAG;SACb,GAAG,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,gBAAgB,IAAI;SACvC,MAAM,CAAC,CAAC,CAAC,KAA2B,CAAC,CAAC,CAAC,CAAC;AAE3C,IAAA,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;QACnB,OAAO,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,IAAI,EAAE,CAAC;IAC7C;IAEA,MAAM,KAAK,GAAW,EAAE;IACxB,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;AAClE,IAAA,OAAO,KAAK;AACd;AAEA,SAAS,SAAS,CAAC,KAAsB,EAAE,GAAW,EAAA;AACpD,IAAA,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,KAAI;AAC7B,QAAA,IAAI,KAAK,CAAC,MAAM,EAAE;AACf,YAAA,KAA6B,CAAC,IAAI,CACjC,CAAC,IAAI,KAAI;AACP,gBAAA,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;AACd,gBAAA,OAAO,EAAE;AACX,YAAA,CAAC,EACD,MAAM,OAAO,EAAE,CAChB;QACH;AAAO,aAAA,IAAI,KAAK,CAAC,WAAW,EAAE;AAC5B,YAAA,MAAM,MAAM,GAAI,KAAkC,CAAC,YAAY,EAAE;YACjE,MAAM,OAAO,GAAsB,EAAE;YACrC,MAAM,SAAS,GAAG,MAAK;AACrB,gBAAA,MAAM,CAAC,WAAW,CAChB,OAAO,KAAK,KAAI;AACd,oBAAA,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;wBACjB,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;AACxD,wBAAA,OAAO,EAAE;wBACT;oBACF;AACA,oBAAA,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;AACtB,oBAAA,SAAS,EAAE;AACb,gBAAA,CAAC,EACD,MAAM,OAAO,EAAE,CAChB;AACH,YAAA,CAAC;AACD,YAAA,SAAS,EAAE;QACb;aAAO;AACL,YAAA,OAAO,EAAE;QACX;AACF,IAAA,CAAC,CAAC;AACJ;;ACvEA,IAAI,UAAU,GAAG,CAAC;AAClB,SAAS,MAAM,GAAA;AACb,IAAA,OAAO,CAAA,OAAA,EAAU,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA,CAAA,EAAI,UAAU,EAAE,EAAE;AAC5D;MAca,oBAAoB,CAAA;;IAE/B,MAAM,GAAG,KAAK,CAAS,EAAE;+EAAC;IAC1B,QAAQ,GAAG,KAAK,CAAU,IAAI;iFAAC;;IAE/B,WAAW,GAAG,KAAK,CAAqB,SAAS;oFAAC;;IAElD,QAAQ,GAAG,KAAK,CAAqB,SAAS;iFAAC;IAC/C,QAAQ,GAAG,KAAK,CAAU,KAAK;iFAAC;;IAEhC,YAAY,GAAG,KAAK,CAAU,IAAI;qFAAC;;IAGnC,SAAS,GAAG,KAAK,CAAS,EAAE;kFAAC;;IAE7B,WAAW,GAAG,KAAK,CAAS,MAAM;oFAAC;;IAEnC,UAAU,GAAG,KAAK,CAAU,KAAK;mFAAC;;IAElC,WAAW,GAAG,KAAK,CAAS,CAAC;oFAAC;AAC9B;;;;AAIG;IACH,UAAU,GAAG,KAAK,CAAwB,KAAK;mFAAC;;IAEhD,UAAU,GAAG,KAAK,CAAmD,EAAE;mFAAC;;IAExE,aAAa,GAAG,KAAK,CAAoC,EAAE;sFAAC;;IAE5D,qBAAqB,GAAG,KAAK,CAAU,KAAK;8FAAC;IAE7C,UAAU,GAAG,MAAM,EAAU;IAC7B,aAAa,GAAG,MAAM,EAA6B;IACnD,WAAW,GAAG,MAAM,EAAU;;IAG9B,aAAa,GAAG,MAAM,EAAmB;;IAEzC,cAAc,GAAG,MAAM,EAAkC;;IAEzD,aAAa,GAAG,MAAM,EAAmB;;IAEzC,WAAW,GAAG,MAAM,EAA6C;IAE9C,KAAK,GAAG,MAAM,CAAoB,EAAE;8EAAC;IACrC,UAAU,GAAG,MAAM,CAAC,KAAK;mFAAC;IACrC,WAAW,GAAG,CAAC;AAEN,IAAA,aAAa,GAAG,MAAM,CAA2B,2BAA2B,CAAC;IAC7E,SAAS,GAAG,SAAS,CAA+B,WAAW;kFAAC;AAChE,IAAA,mBAAmB,GAAG,IAAI,GAAG,EAAwB;IACrD,WAAW,GAAa,EAAE;IACnC,aAAa,GAAG,CAAC;AACR,IAAA,eAAe,GAAG,IAAI,GAAG,EAAU;IAEjC,YAAY,GAAG,QAAQ,CACxC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM;qFACjE;AAEkB,IAAA,sBAAsB,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;+FAAC;AAE3E,IAAA,IAAI,GAAG,QAAQ,CAAC,MAAK;QACtC,MAAM,KAAK,GAAa,EAAE;AAC1B,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE;AAC5B,QAAA,IAAI,MAAM;AAAE,YAAA,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;AAC9B,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE;AAC9B,QAAA,IAAI,GAAG;YAAE,KAAK,CAAC,IAAI,CAAC,CAAA,IAAA,EAAO,WAAW,CAAC,GAAG,CAAC,CAAA,CAAE,CAAC;AAC9C,QAAA,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;IAC1B,CAAC;6EAAC;AAEQ,IAAA,UAAU,CAAC,KAAa,EAAA;AAChC,QAAA,OAAO,WAAW,CAAC,KAAK,CAAC;IAC3B;AAEU,IAAA,SAAS,CAAC,IAAqB,EAAA;QACvC,OAAO,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,UAAU;IAChE;IAEU,SAAS,CAAC,MAAc,EAAE,IAAqB,EAAA;QACvD,OAAO,IAAI,CAAC,EAAE;IAChB;IAEA,WAAW,GAAA;QACT,KAAK,MAAM,YAAY,IAAI,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,EAAE;YAC5D,YAAY,CAAC,WAAW,EAAE;QAC5B;AACA,QAAA,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE;QAEhC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,EAAE;YAC/B,IAAI,IAAI,CAAC,UAAU;AAAE,gBAAA,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC;QAC3D;IACF;AAEU,IAAA,WAAW,CAAC,EAAa,EAAA;QACjC,EAAE,CAAC,cAAc,EAAE;QACnB,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE;QACrB,IAAI,CAAC,WAAW,EAAE;AAClB,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;IAC3B;AAEU,IAAA,UAAU,CAAC,EAAa,EAAA;QAChC,EAAE,CAAC,cAAc,EAAE;AACnB,QAAA,IAAI,EAAE,CAAC,YAAY,EAAE;AACnB,YAAA,EAAE,CAAC,YAAY,CAAC,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,MAAM,GAAG,MAAM;QAChE;IACF;AAEU,IAAA,WAAW,CAAC,EAAa,EAAA;QACjC,EAAE,CAAC,cAAc,EAAE;QACnB,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE;AACrB,QAAA,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;AACpD,QAAA,IAAI,IAAI,CAAC,WAAW,KAAK,CAAC;AAAE,YAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;IACxD;IAEU,MAAM,MAAM,CAAC,EAAa,EAAA;QAClC,EAAE,CAAC,cAAc,EAAE;AACnB,QAAA,IAAI,CAAC,WAAW,GAAG,CAAC;AACpB,QAAA,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;QAC1B,IAAI,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC,YAAY;YAAE;QAEzC,MAAM,KAAK,GAAG,MAAM,4BAA4B,CAAC,EAAE,CAAC,YAAY,CAAC;AACjE,QAAA,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC;IACjC;IAEU,aAAa,GAAA;QACrB,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE;QACrB,IAAI,CAAC,SAAS,EAAE,EAAE,aAAa,CAAC,KAAK,EAAE;IACzC;AAEU,IAAA,SAAS,CAAC,EAAiB,EAAA;AACnC,QAAA,IAAI,EAAE,CAAC,GAAG,KAAK,OAAO,IAAI,EAAE,CAAC,GAAG,KAAK,GAAG,EAAE;YACxC,EAAE,CAAC,cAAc,EAAE;YACnB,IAAI,CAAC,aAAa,EAAE;QACtB;IACF;AAEU,IAAA,iBAAiB,CAAC,EAAS,EAAA;AACnC,QAAA,MAAM,KAAK,GAAG,EAAE,CAAC,MAA0B;AAC3C,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;AAC3C,QAAA,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC;AAC/B,QAAA,KAAK,CAAC,KAAK,GAAG,EAAE;IAClB;AAEU,IAAA,UAAU,CAAC,EAAU,EAAA;QAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;QACpD,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE;AAC/C,QAAA,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,CAAC;;;;QAKnC,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE;AACnC,YAAA,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;QAC1D;QAEA,IAAI,MAAM,EAAE,UAAU;AAAE,YAAA,GAAG,CAAC,eAAe,CAAC,MAAM,CAAC,UAAU,CAAC;QAE9D,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;;;QAI5D,IAAI,CAAC,gBAAgB,EAAE;QACvB,IAAI,CAAC,SAAS,EAAE;IAClB;IAEU,SAAS,GAAA;AACjB,QAAA,IAAI,CAAC,cAAc,CACjB,IAAI,CAAC,KAAK;AACP,aAAA,MAAM,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aACrC,GAAG,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC,CAC1B;IACH;AAEU,IAAA,YAAY,CAAC,EAAU,EAAA;AAC/B,QAAA,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC;IAC3B;AAEU,IAAA,WAAW,CAAC,EAAU,EAAA;QAC9B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,KACrB,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,KACZ,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI,CACtF,CACF;AACD,QAAA,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC;IAC3B;AAEQ,IAAA,mBAAmB,CAAC,QAAgB,EAAA;QAC1C,IAAI,CAAC,QAAQ,CAAC,MAAM;YAAE;QAEtB,MAAM,QAAQ,GAAsB,EAAE;QACtC,MAAM,QAAQ,GAA8B,EAAE;;;AAI9C,QAAA,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,MAAM,GAAG,CAAC;AAC/D,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE;AAChC,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE;AAClC,QAAA,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE;AAElC,QAAA,MAAM,IAAI,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;AAEzD,QAAA,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE;AACvB,YAAA,IAAI,MAA8C;YAElD,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE;gBACvC,MAAM,GAAG,MAAM;YACjB;iBAAO,IAAI,OAAO,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,GAAG,OAAO,EAAE;gBACjD,MAAM,GAAG,MAAM;YACjB;AAAO,iBAAA,IAAI,QAAQ,IAAI,IAAI,IAAI,aAAa,GAAG,QAAQ,CAAC,MAAM,IAAI,QAAQ,EAAE;gBAC1E,MAAM,GAAG,OAAO;YAClB;YAEA,IAAI,MAAM,EAAE;gBACV,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;gBAC/B;YACF;YAEA,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;YAC9C,QAAQ,CAAC,IAAI,CAAC;gBACZ,EAAE,EAAE,MAAM,EAAE;gBACZ,IAAI;AACJ,gBAAA,UAAU,EAAE,OAAO,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,SAAS;AAC3D,gBAAA,MAAM,EAAE,UAAU;AAClB,gBAAA,QAAQ,EAAE,CAAC;AACZ,aAAA,CAAC;QACJ;AAEA,QAAA,IAAI,QAAQ,CAAC,MAAM,EAAE;YACnB,IAAI,CAAC,UAAU,EAAE;gBACf,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,KAAK,EAAE,EAAE;AACnC,oBAAA,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE;oBACxD,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC5C,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACxC,IAAI,QAAQ,CAAC,UAAU;AAAE,wBAAA,GAAG,CAAC,eAAe,CAAC,QAAQ,CAAC,UAAU,CAAC;gBACnE;gBACA,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI;YAChD;AAEA,YAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,MAAM,UAAU,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC;AAC7E,YAAA,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;YACjD,IAAI,CAAC,gBAAgB,EAAE;AAEvB,YAAA,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE;AACrB,gBAAA,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC;YACtD;QACF;AAEA,QAAA,IAAI,QAAQ,CAAC,MAAM,EAAE;AACnB,YAAA,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC;QACnC;IACF;AAEQ,IAAA,cAAc,CAAC,GAAa,EAAA;QAClC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE;AAC5B,YAAA,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,0DAA0D,CAAC;YACnF,KAAK,MAAM,EAAE,IAAI,GAAG;gBAAE,IAAI,CAAC,eAAe,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC;YAC5D;QACF;QAEA,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC;AACxC,QAAA,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE;YACpB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC;AACxD,YAAA,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;gBAAE;AACtD,YAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;AACzB,YAAA,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QAChB;QAEA,IAAI,CAAC,SAAS,EAAE;IAClB;IAEQ,SAAS,GAAA;QACf,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC;AAE9D,QAAA,OAAO,IAAI,CAAC,aAAa,GAAG,KAAK,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE;YAC5D,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,EAAG;YACpC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC;YAExD,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;gBAAE;AAEpC,YAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QACxB;IACF;AAEQ,IAAA,WAAW,CAAC,IAAqB,EAAA;QACvC,IAAI,CAAC,aAAa,EAAE;QACpB,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;AAEjC,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE;AACvB,YAAA,MAAM,EAAE,WAAW;AACnB,YAAA,QAAQ,EAAE,CAAC;AACX,YAAA,KAAK,EAAE,SAAS;AACjB,SAAA,CAAC;QAEF,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;AAChE,QAAA,IAAI,OAAO;AAAE,YAAA,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC;AAE7C,QAAA,IAAI,YAA0B;AAE9B,QAAA,IAAI;YACF,YAAY,GAAG,IAAI,CAAC;AACjB,iBAAA,MAAM,CAAC;AACN,gBAAA,GAAG,EAAE,IAAI,CAAC,SAAS,EAAE;AACrB,gBAAA,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,MAAM;gBACnC,IAAI,EAAE,IAAI,CAAC,IAAI;AACf,gBAAA,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE;AACvB,gBAAA,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE;AAC7B,gBAAA,eAAe,EAAE,IAAI,CAAC,qBAAqB,EAAE;aAC9C;AACA,iBAAA,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC/C,iBAAA,SAAS,CAAC;AACT,gBAAA,IAAI,EAAE,CAAC,KAAK,KAAI;AACd,oBAAA,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE;AAC7B,wBAAA,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE;4BACvB,QAAQ,EAAE,KAAK,CAAC,OAAO;AACxB,yBAAA,CAAC;wBAEF,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;wBAChE,IAAI,OAAO,EAAE;AACX,4BAAA,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC;AACvB,gCAAA,IAAI,EAAE,OAAO;gCACb,MAAM,EAAE,KAAK,CAAC,MAAM;gCACpB,KAAK,EAAE,KAAK,CAAC,KAAK;gCAClB,OAAO,EAAE,KAAK,CAAC,OAAO;AACvB,6BAAA,CAAC;wBACJ;wBACA;oBACF;AAEA,oBAAA,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE;AACvB,wBAAA,MAAM,EAAE,UAAU;AAClB,wBAAA,QAAQ,EAAE,GAAG;wBACb,QAAQ,EAAE,KAAK,CAAC,QAAQ;AACxB,wBAAA,KAAK,EAAE,SAAS;AACjB,qBAAA,CAAC;oBAEF,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;AAChE,oBAAA,IAAI,OAAO;AAAE,wBAAA,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC;gBAC/C,CAAC;AACD,gBAAA,KAAK,EAAE,CAAC,KAAK,KAAI;oBACf,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC;gBAC5C,CAAC;AACF,aAAA,CAAC;QACN;QAAE,OAAO,KAAK,EAAE;YACd,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC;AAC1C,YAAA,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B;QACF;QAEA,IAAI,CAAC,YAAY,CAAC,MAAM;YAAE,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,YAAY,CAAC;IAC/E;AAEQ,IAAA,eAAe,CAAC,EAAU,EAAE,KAAc,EAAE,iBAA0B,EAAA;AAC5E,QAAA,IAAI,CAAC,UAAU,CAAC,EAAE,EAAE;AAClB,YAAA,MAAM,EAAE,OAAO;YACf,KAAK;AACN,SAAA,CAAC;QAEF,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC;AACxD,QAAA,IAAI,IAAI;YAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QAEhD,IAAI,CAAC,iBAAiB,EAAE;YACtB,IAAI,CAAC,SAAS,EAAE;QAClB;IACF;AAEQ,IAAA,YAAY,CAAC,EAAU,EAAA;AAC7B,QAAA,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,CAAC;QAEnC,IAAI,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE;AACnC,YAAA,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;QAC1D;QAEA,IAAI,CAAC,SAAS,EAAE;IAClB;IAEQ,UAAU,CAAC,EAAU,EAAE,KAA+B,EAAA;AAC5D,QAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,KACrB,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,MAAM,IAAI,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC,CACpE;IACH;IAEQ,gBAAgB,GAAA;QACtB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;IACxD;uGAjYW,oBAAoB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAApB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,oBAAoB,s1EC1CjC,u/JA6IA,EAAA,MAAA,EAAA,CAAA,+hMAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FDnGa,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBAVhC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,cAAc,cACZ,IAAI,EAAA,eAAA,EACC,uBAAuB,CAAC,MAAM,EAAA,IAAA,EAGzC;AACJ,wBAAA,KAAK,EAAE,mBAAmB;AAC3B,qBAAA,EAAA,QAAA,EAAA,u/JAAA,EAAA,MAAA,EAAA,CAAA,+hMAAA,CAAA,EAAA;43DAqDoE,WAAW,EAAA,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,EAAA,EAAA,CAAA;;AE7FlF;;AAEG;;;;"}
1
+ {"version":3,"file":"ngx-kit-dropzone.mjs","sources":["../../../projects/libs/dropzone/services/ngx-dropzone-http-upload.service.ts","../../../projects/libs/dropzone/services/ngx-dropzone-upload.token.ts","../../../projects/libs/dropzone/utils/file-matching.ts","../../../projects/libs/dropzone/components/dropzone.component.ts","../../../projects/libs/dropzone/components/dropzone.component.html","../../../projects/libs/dropzone/ngx-kit-dropzone.ts"],"sourcesContent":["import {\n HttpClient,\n HttpEvent,\n HttpEventType,\n HttpHeaders,\n HttpResponse,\n HttpUploadProgressEvent,\n} from '@angular/common/http';\nimport { Injectable, inject } from '@angular/core';\nimport { Observable, filter, map } from 'rxjs';\nimport {\n NgxDropzoneUploadEvent,\n NgxDropzoneUploadRequest,\n NgxDropzoneUploadService,\n} from '../contracts/dropzone-upload';\n\n@Injectable({ providedIn: 'root' })\nexport class NgxDropzoneHttpUploadService implements NgxDropzoneUploadService {\n private readonly http = inject(HttpClient);\n\n upload<TResponse = unknown>(\n request: NgxDropzoneUploadRequest,\n ): Observable<NgxDropzoneUploadEvent<TResponse>> {\n const body = new FormData();\n body.append(request.alias, request.file, request.file.name);\n\n for (const [key, value] of Object.entries(request.data ?? {})) {\n body.append(key, value instanceof Blob ? value : String(value));\n }\n\n const headers =\n request.headers instanceof HttpHeaders ? request.headers : new HttpHeaders(request.headers);\n\n return this.http\n .post<TResponse>(request.url, body, {\n headers,\n withCredentials: request.withCredentials ?? false,\n observe: 'events',\n reportProgress: true,\n })\n .pipe(\n filter(\n (event): event is HttpUploadProgressEvent | HttpResponse<TResponse> =>\n event.type === HttpEventType.UploadProgress || event.type === HttpEventType.Response,\n ),\n map((event): NgxDropzoneUploadEvent<TResponse> => {\n if (event.type === HttpEventType.UploadProgress) {\n const total = event.total;\n\n return {\n type: 'progress',\n loaded: event.loaded,\n total,\n percent: total ? Math.min(100, Math.round((event.loaded / total) * 100)) : 0,\n };\n }\n\n return {\n type: 'response',\n response: event.body as TResponse,\n status: event.status,\n headers: event.headers,\n };\n }),\n );\n }\n}\n","import { InjectionToken, inject } from '@angular/core';\nimport { NgxDropzoneHttpUploadService } from './ngx-dropzone-http-upload.service';\nimport { NgxDropzoneUploadService } from '../contracts/dropzone-upload';\n\n/**\n * Upload adapter used by ngx-dropzone.\n *\n * Default: Angular HttpClient.\n * Override this token at application/component level to use Axios or any\n * other upload implementation.\n */\nexport const NGX_DROPZONE_UPLOAD_SERVICE = new InjectionToken<NgxDropzoneUploadService>(\n 'NGX_DROPZONE_UPLOAD_SERVICE',\n {\n providedIn: 'root',\n factory: () => inject(NgxDropzoneHttpUploadService),\n },\n);\n","/**\n * چک می‌کنه یه فایل با pattern رشته‌ای accept (مثل input[type=file])\n * مطابقت داره یا نه. پشتیبانی می‌شه از:\n * - MIME کامل: \"image/png\"\n * - MIME با wildcard: \"image/*\"\n * - پسوند فایل: \".png\", \".jpg\"\n * - لیست کاما-جدا از موارد بالا: \"image/*,.pdf,.docx\"\n */\nexport function matchesAccept(file: File, accept?: string): boolean {\n if (!accept || accept.trim() === '') return true;\n\n const patterns = accept\n .split(',')\n .map((p) => p.trim().toLowerCase())\n .filter(Boolean);\n\n if (!patterns.length) return true;\n\n const fileName = file.name.toLowerCase();\n const fileType = (file.type || '').toLowerCase();\n\n return patterns.some((pattern) => {\n if (pattern.startsWith('.')) {\n return fileName.endsWith(pattern);\n }\n if (pattern.endsWith('/*')) {\n const prefix = pattern.slice(0, -1); // \"image/\"\n return fileType.startsWith(prefix);\n }\n return fileType === pattern;\n });\n}\n\n/** تبدیل بایت به یه رشته‌ی خوانا (KB/MB/GB) */\nexport function formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B';\n const units = ['B', 'KB', 'MB', 'GB', 'TB'];\n const i = Math.floor(Math.log(bytes) / Math.log(1024));\n const value = bytes / Math.pow(1024, i);\n return `${value.toFixed(i === 0 ? 0 : 1)} ${units[i]}`;\n}\n\n/** استخراج فایل‌های واقعی از یک DataTransfer، شامل پیمایش بازگشتیِ پوشه‌ها (وقتی مرورگر پشتیبانی کنه) */\nexport async function extractFilesFromDataTransfer(dataTransfer: DataTransfer): Promise<File[]> {\n const items = Array.from(dataTransfer.items || []);\n const hasEntrySupport = items.length > 0 && typeof items[0].webkitGetAsEntry === 'function';\n\n if (!hasEntrySupport) {\n return Array.from(dataTransfer.files || []);\n }\n\n const entries = items\n .map((item) => item.webkitGetAsEntry?.())\n .filter((e): e is FileSystemEntry => !!e);\n\n if (!entries.length) {\n return Array.from(dataTransfer.files || []);\n }\n\n const files: File[] = [];\n await Promise.all(entries.map((entry) => walkEntry(entry, files)));\n return files;\n}\n\nfunction walkEntry(entry: FileSystemEntry, out: File[]): Promise<void> {\n return new Promise((resolve) => {\n if (entry.isFile) {\n (entry as FileSystemFileEntry).file(\n (file) => {\n out.push(file);\n resolve();\n },\n () => resolve(),\n );\n } else if (entry.isDirectory) {\n const reader = (entry as FileSystemDirectoryEntry).createReader();\n const readAll: FileSystemEntry[] = [];\n const readBatch = () => {\n reader.readEntries(\n async (batch) => {\n if (!batch.length) {\n await Promise.all(readAll.map((e) => walkEntry(e, out)));\n resolve();\n return;\n }\n readAll.push(...batch);\n readBatch();\n },\n () => resolve(),\n );\n };\n readBatch();\n } else {\n resolve();\n }\n });\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n OnDestroy,\n computed,\n inject,\n input,\n output,\n signal,\n viewChild,\n} from '@angular/core';\nimport { Subscription, finalize } from 'rxjs';\nimport {\n NgxDropzoneFile,\n NgxDropzoneRejectedFile,\n NgxDropzoneRejectionReason,\n} from '../contracts/dropzone-file';\nimport {\n NgxDropzoneUploadProgressEvent,\n NgxDropzoneUploadService,\n} from '../contracts/dropzone-upload';\nimport { NGX_DROPZONE_UPLOAD_SERVICE } from '../services/ngx-dropzone-upload.token';\nimport { extractFilesFromDataTransfer, formatBytes, matchesAccept } from '../utils/file-matching';\n\nlet uidCounter = 0;\nfunction nextId(): string {\n return `ngx-dz-${Date.now().toString(36)}-${uidCounter++}`;\n}\n\nexport type NgxDropzoneUploadMode = 'all' | 'single';\n\n@Component({\n selector: 'ngx-dropzone',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './dropzone.component.html',\n styleUrl: './dropzone.component.scss',\n host: {\n class: 'ngx-dropzone-host',\n },\n})\nexport class NgxDropzone implements OnDestroy {\n /** الگوی accept مثل input[type=file]: \"image/*\", \".pdf,.docx\" و ... */\n accept = input<string>('');\n multiple = input<boolean>(true);\n /** حداکثر حجم هر فایل به بایت؛ undefined یعنی بدون محدودیت */\n maxFileSize = input<number | undefined>(undefined);\n /** حداکثر تعداد فایل مجاز؛ undefined یعنی بدون محدودیت */\n maxFiles = input<number | undefined>(undefined);\n disabled = input<boolean>(false);\n /** نمایش لیست/پیش‌نمایش فایل‌های انتخاب‌شده داخل خودِ کامپوننت */\n showFileList = input<boolean>(true);\n\n /** Upload endpoint. */\n uploadUrl = input<string>('');\n /** Multipart form-data field name. */\n uploadAlias = input<string>('file');\n /** Automatically enqueue newly accepted files for upload. */\n autoUpload = input<boolean>(false);\n /** Maximum number of simultaneous uploads. */\n maxParallel = input<number>(3);\n /**\n * Manual upload behavior:\n * - all: one \"Upload all\" action uploads all pending files.\n * - single: every pending row gets its own Upload button.\n */\n uploadMode = input<NgxDropzoneUploadMode>('all');\n /** Extra multipart form fields sent with every file. */\n uploadData = input<Record<string, string | Blob | number | boolean>>({});\n /** Optional request headers. */\n uploadHeaders = input<Record<string, string | string[]>>({});\n /** Send credentials/cookies with the upload request. */\n uploadWithCredentials = input<boolean>(false);\n\n filesAdded = output<File[]>();\n filesRejected = output<NgxDropzoneRejectedFile[]>();\n filesChange = output<File[]>();\n\n /** Emitted when an individual upload starts. */\n uploadStarted = output<NgxDropzoneFile>();\n /** Emitted for every upload progress update. */\n uploadProgress = output<NgxDropzoneUploadProgressEvent>();\n /** Emitted after a file is successfully uploaded. */\n uploadSuccess = output<NgxDropzoneFile>();\n /** Emitted when an upload fails. */\n uploadError = output<{ item: NgxDropzoneFile; error: unknown }>();\n\n protected readonly files = signal<NgxDropzoneFile[]>([]);\n protected readonly isDragging = signal(false);\n private dragCounter = 0;\n\n private readonly uploadService = inject<NgxDropzoneUploadService>(NGX_DROPZONE_UPLOAD_SERVICE);\n private readonly fileInput = viewChild<ElementRef<HTMLInputElement>>('fileInput');\n private readonly uploadSubscriptions = new Map<string, Subscription>();\n private readonly uploadQueue: string[] = [];\n private activeUploads = 0;\n private readonly activeUploadIds = new Set<string>();\n\n protected readonly pendingCount = computed(\n () => this.files().filter((item) => this.isPending(item)).length,\n );\n\n protected readonly hasUploadConfiguration = computed(() => this.uploadUrl().trim().length > 0);\n\n protected readonly hint = computed(() => {\n const parts: string[] = [];\n const accept = this.accept();\n if (accept) parts.push(accept);\n const max = this.maxFileSize();\n if (max) parts.push(`max ${formatBytes(max)}`);\n return parts.join(' · ');\n });\n\n protected formatSize(bytes: number): string {\n return formatBytes(bytes);\n }\n\n protected isPending(item: NgxDropzoneFile): boolean {\n return item.status === 'pending' || item.status === 'accepted';\n }\n\n protected trackById(_index: number, item: NgxDropzoneFile): string {\n return item.id;\n }\n\n ngOnDestroy(): void {\n for (const subscription of this.uploadSubscriptions.values()) {\n subscription.unsubscribe();\n }\n this.uploadSubscriptions.clear();\n\n for (const item of this.files()) {\n if (item.previewUrl) URL.revokeObjectURL(item.previewUrl);\n }\n }\n\n protected onDragEnter(ev: DragEvent): void {\n ev.preventDefault();\n if (this.disabled()) return;\n this.dragCounter++;\n this.isDragging.set(true);\n }\n\n protected onDragOver(ev: DragEvent): void {\n ev.preventDefault();\n if (ev.dataTransfer) {\n ev.dataTransfer.dropEffect = this.disabled() ? 'none' : 'copy';\n }\n }\n\n protected onDragLeave(ev: DragEvent): void {\n ev.preventDefault();\n if (this.disabled()) return;\n this.dragCounter = Math.max(0, this.dragCounter - 1);\n if (this.dragCounter === 0) this.isDragging.set(false);\n }\n\n protected async onDrop(ev: DragEvent): Promise<void> {\n ev.preventDefault();\n this.dragCounter = 0;\n this.isDragging.set(false);\n if (this.disabled() || !ev.dataTransfer) return;\n\n const files = await extractFilesFromDataTransfer(ev.dataTransfer);\n this.handleIncomingFiles(files);\n }\n\n protected onBrowseClick(): void {\n if (this.disabled()) return;\n this.fileInput()?.nativeElement.click();\n }\n\n protected onKeydown(ev: KeyboardEvent): void {\n if (ev.key === 'Enter' || ev.key === ' ') {\n ev.preventDefault();\n this.onBrowseClick();\n }\n }\n\n protected onFileInputChange(ev: Event): void {\n const input = ev.target as HTMLInputElement;\n const files = Array.from(input.files ?? []);\n this.handleIncomingFiles(files);\n input.value = '';\n }\n\n protected removeFile(id: string): void {\n const target = this.files().find((f) => f.id === id);\n this.uploadSubscriptions.get(id)?.unsubscribe();\n this.uploadSubscriptions.delete(id);\n\n // Unsubscribing an HttpClient upload cancels the request. Release its\n // concurrency slot immediately; finalize() will see that the id is no\n // longer active and won't decrement twice.\n if (this.activeUploadIds.delete(id)) {\n this.activeUploads = Math.max(0, this.activeUploads - 1);\n }\n\n if (target?.previewUrl) URL.revokeObjectURL(target.previewUrl);\n\n this.files.update((list) => list.filter((f) => f.id !== id));\n\n // Remove stale queue entries. The queue is intentionally lazy, so an\n // entry can safely remain until pumpQueue() sees that it no longer exists.\n this.emitCurrentFiles();\n this.pumpQueue();\n }\n\n protected uploadAll(): void {\n this.enqueueUploads(\n this.files()\n .filter((item) => this.isPending(item))\n .map((item) => item.id),\n );\n }\n\n protected uploadSingle(id: string): void {\n this.enqueueUploads([id]);\n }\n\n protected retryUpload(id: string): void {\n this.files.update((list) =>\n list.map((item) =>\n item.id === id ? { ...item, status: 'pending', progress: 0, error: undefined } : item,\n ),\n );\n this.enqueueUploads([id]);\n }\n\n private handleIncomingFiles(incoming: File[]): void {\n if (!incoming.length) return;\n\n const accepted: NgxDropzoneFile[] = [];\n const rejected: NgxDropzoneRejectedFile[] = [];\n\n // A single-file dropzone behaves like a native single-select input:\n // selecting another file replaces the previous one.\n const existingCount = this.multiple() ? this.files().length : 0;\n const maxFiles = this.maxFiles();\n const maxSize = this.maxFileSize();\n const isMultiple = this.multiple();\n\n const pool = isMultiple ? incoming : incoming.slice(0, 1);\n\n for (const file of pool) {\n let reason: NgxDropzoneRejectionReason | undefined;\n\n if (!matchesAccept(file, this.accept())) {\n reason = 'type';\n } else if (maxSize != null && file.size > maxSize) {\n reason = 'size';\n } else if (maxFiles != null && existingCount + accepted.length >= maxFiles) {\n reason = 'count';\n }\n\n if (reason) {\n rejected.push({ file, reason });\n continue;\n }\n\n const isImage = file.type.startsWith('image/');\n accepted.push({\n id: nextId(),\n file,\n previewUrl: isImage ? URL.createObjectURL(file) : undefined,\n status: 'accepted',\n progress: 0,\n });\n }\n\n if (accepted.length) {\n if (!isMultiple) {\n for (const previous of this.files()) {\n this.uploadSubscriptions.get(previous.id)?.unsubscribe();\n this.uploadSubscriptions.delete(previous.id);\n this.activeUploadIds.delete(previous.id);\n if (previous.previewUrl) URL.revokeObjectURL(previous.previewUrl);\n }\n this.activeUploads = this.activeUploadIds.size;\n }\n\n this.files.update((list) => (isMultiple ? [...list, ...accepted] : accepted));\n this.filesAdded.emit(accepted.map((a) => a.file));\n this.emitCurrentFiles();\n\n if (this.autoUpload()) {\n this.enqueueUploads(accepted.map((item) => item.id));\n }\n }\n\n if (rejected.length) {\n this.filesRejected.emit(rejected);\n }\n }\n\n private enqueueUploads(ids: string[]): void {\n if (!this.uploadUrl().trim()) {\n const error = new Error('ngx-dropzone: uploadUrl is required for uploading files.');\n for (const id of ids) this.markUploadError(id, error, false);\n return;\n }\n\n const queued = new Set(this.uploadQueue);\n for (const id of ids) {\n const item = this.files().find((file) => file.id === id);\n if (!item || !this.isPending(item) || queued.has(id)) continue;\n this.uploadQueue.push(id);\n queued.add(id);\n }\n\n this.pumpQueue();\n }\n\n private pumpQueue(): void {\n const limit = Math.max(1, Math.floor(this.maxParallel() || 1));\n\n while (this.activeUploads < limit && this.uploadQueue.length) {\n const id = this.uploadQueue.shift()!;\n const item = this.files().find((file) => file.id === id);\n\n if (!item || !this.isPending(item)) continue;\n\n this.startUpload(item);\n }\n }\n\n private startUpload(item: NgxDropzoneFile): void {\n this.activeUploads++;\n this.activeUploadIds.add(item.id);\n\n this.updateFile(item.id, {\n status: 'uploading',\n progress: 0,\n error: undefined,\n });\n\n const current = this.files().find((file) => file.id === item.id);\n if (current) this.uploadStarted.emit(current);\n\n let subscription: Subscription;\n\n try {\n subscription = this.uploadService\n .upload({\n url: this.uploadUrl(),\n alias: this.uploadAlias() || 'file',\n file: item.file,\n data: this.uploadData(),\n headers: this.uploadHeaders(),\n withCredentials: this.uploadWithCredentials(),\n })\n .pipe(finalize(() => this.finishUpload(item.id)))\n .subscribe({\n next: (event) => {\n if (event.type === 'progress') {\n this.updateFile(item.id, {\n progress: event.percent,\n });\n\n const updated = this.files().find((file) => file.id === item.id);\n if (updated) {\n this.uploadProgress.emit({\n item: updated,\n loaded: event.loaded,\n total: event.total,\n percent: event.percent,\n });\n }\n return;\n }\n\n this.updateFile(item.id, {\n status: 'uploaded',\n progress: 100,\n response: event.response,\n error: undefined,\n });\n\n const updated = this.files().find((file) => file.id === item.id);\n if (updated) this.uploadSuccess.emit(updated);\n },\n error: (error) => {\n this.markUploadError(item.id, error, true);\n },\n });\n } catch (error) {\n this.markUploadError(item.id, error, true);\n this.finishUpload(item.id);\n return;\n }\n\n if (!subscription.closed) this.uploadSubscriptions.set(item.id, subscription);\n }\n\n private markUploadError(id: string, error: unknown, releaseActiveSlot: boolean): void {\n this.updateFile(id, {\n status: 'error',\n error,\n });\n\n const item = this.files().find((file) => file.id === id);\n if (item) this.uploadError.emit({ item, error });\n\n if (!releaseActiveSlot) {\n this.pumpQueue();\n }\n }\n\n private finishUpload(id: string): void {\n this.uploadSubscriptions.delete(id);\n\n if (this.activeUploadIds.delete(id)) {\n this.activeUploads = Math.max(0, this.activeUploads - 1);\n }\n\n this.pumpQueue();\n }\n\n private updateFile(id: string, patch: Partial<NgxDropzoneFile>): void {\n this.files.update((list) =>\n list.map((item) => (item.id === id ? { ...item, ...patch } : item)),\n );\n }\n\n private emitCurrentFiles(): void {\n this.filesChange.emit(this.files().map((f) => f.file));\n }\n}\n","<div\n class=\"ngx-dropzone\"\n [class.dragging]=\"isDragging()\"\n [class.disabled]=\"disabled()\"\n [class.has-files]=\"files().length > 0\"\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-disabled]=\"disabled()\"\n (click)=\"onBrowseClick()\"\n (keydown)=\"onKeydown($event)\"\n (dragenter)=\"onDragEnter($event)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n <input\n #fileInput\n type=\"file\"\n class=\"ngx-dropzone-input\"\n [accept]=\"accept()\"\n [multiple]=\"multiple()\"\n [disabled]=\"disabled()\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"onFileInputChange($event)\" />\n\n <div class=\"ngx-dropzone-icon-wrap\">\n <ng-content select=\"[dropzone-icon]\">\n <svg class=\"ngx-dropzone-icon\" viewBox=\"0 0 24 24\" fill=\"none\" width=\"30\" height=\"30\">\n <path\n d=\"M12 16V4M12 4l-4 4M12 4l4 4M4 16v2a2 2 0 002 2h12a2 2 0 002-2v-2\"\n stroke=\"currentColor\"\n stroke-width=\"1.8\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </ng-content>\n </div>\n\n <div class=\"ngx-dropzone-text\">\n <ng-content>\n <strong>Drop files here</strong>\n <span>or click to browse</span>\n </ng-content>\n </div>\n\n @if (hint()) {\n <div class=\"ngx-dropzone-hint\">{{ hint() }}</div>\n }\n</div>\n\n@if (!autoUpload() && uploadMode() === 'all' && pendingCount() > 0) {\n <div class=\"ngx-dropzone-actions\">\n <button\n type=\"button\"\n class=\"ngx-dropzone-upload-all\"\n [disabled]=\"disabled() || !hasUploadConfiguration()\"\n (click)=\"uploadAll(); $event.stopPropagation()\">\n Upload all\n <span>{{ pendingCount() }}</span>\n </button>\n </div>\n}\n\n@if (showFileList() && files().length) {\n <ul class=\"ngx-dropzone-list\">\n @for (item of files(); track item.id) {\n <li class=\"ngx-dropzone-item\" [class.is-uploading]=\"item.status === 'uploading'\">\n <div class=\"ngx-dropzone-thumb-wrap\">\n @if (item.previewUrl) {\n <img class=\"ngx-dropzone-thumb\" [src]=\"item.previewUrl\" [alt]=\"item.file.name\" />\n } @else {\n <span class=\"ngx-dropzone-file-icon\">📄</span>\n }\n </div>\n\n <div class=\"ngx-dropzone-meta\">\n <span class=\"ngx-dropzone-name\" [title]=\"item.file.name\">{{ item.file.name }}</span>\n <span class=\"ngx-dropzone-size\">{{ formatSize(item.file.size) }}</span>\n\n @if (item.status === 'uploading' || item.status === 'uploaded') {\n <div\n class=\"ngx-dropzone-progress\"\n role=\"progressbar\"\n [attr.aria-valuenow]=\"item.progress\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n [attr.aria-label]=\"'Upload progress for ' + item.file.name\">\n <span class=\"ngx-dropzone-progress-bar\" [style.width.%]=\"item.progress\"></span>\n </div>\n <span class=\"ngx-dropzone-progress-text\">{{ item.progress }}%</span>\n }\n\n @if (item.status === 'error') {\n <span class=\"ngx-dropzone-error\">Upload failed</span>\n }\n </div>\n\n <div class=\"ngx-dropzone-row-actions\">\n @if (!autoUpload() && uploadMode() === 'single' && isPending(item)) {\n <button\n type=\"button\"\n class=\"ngx-dropzone-upload\"\n [disabled]=\"disabled() || !hasUploadConfiguration()\"\n [attr.aria-label]=\"'Upload ' + item.file.name\"\n (click)=\"uploadSingle(item.id); $event.stopPropagation()\">\n Upload\n </button>\n }\n\n @if (item.status === 'error') {\n <button\n type=\"button\"\n class=\"ngx-dropzone-retry\"\n [disabled]=\"disabled() || !hasUploadConfiguration()\"\n [attr.aria-label]=\"'Retry upload for ' + item.file.name\"\n (click)=\"retryUpload(item.id); $event.stopPropagation()\">\n Retry\n </button>\n }\n\n @if (item.status === 'uploaded') {\n <span class=\"ngx-dropzone-status success\" aria-label=\"Uploaded\">✓</span>\n } @else if (item.status === 'uploading') {\n <span class=\"ngx-dropzone-status uploading\" aria-label=\"Uploading\"></span>\n } @else if (item.status === 'error') {\n <span class=\"ngx-dropzone-status error\" aria-label=\"Upload failed\">!</span>\n } @else {\n <span class=\"ngx-dropzone-status pending\" aria-label=\"Pending\">•</span>\n }\n\n <button\n type=\"button\"\n class=\"ngx-dropzone-remove\"\n [attr.aria-label]=\"'Remove ' + item.file.name\"\n (click)=\"removeFile(item.id); $event.stopPropagation()\">\n ✕\n </button>\n </div>\n </li>\n }\n </ul>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -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
- this.saved.emit({ blob, dataUrl, width: finalCanvas.width, height: finalCanvas.height });
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: NgxImageEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
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: NgxImageEditorComponent, decorators: [{
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, NgxImageEditorComponent, NgxImageEditorLocalization, NgxPointerDragDirective, applyCartoonEffect, canvasToBlob, createWorkingCopy, fitWithin, loadImage, renderComposite, renderRotated };
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