cloud-ide-element 1.0.97 → 1.0.98
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.
|
@@ -3297,6 +3297,24 @@ class CideEleFloatingFileUploaderComponent {
|
|
|
3297
3297
|
activeUploadsLocal = computed(() => Array.from(this.activeUploads().values()).filter(upload => upload.stage === 'reading' || upload.stage === 'uploading'), ...(ngDevMode ? [{ debugName: "activeUploadsLocal" }] : []));
|
|
3298
3298
|
completedUploads = computed(() => Array.from(this.activeUploads().values()).filter(upload => upload.stage === 'complete'), ...(ngDevMode ? [{ debugName: "completedUploads" }] : []));
|
|
3299
3299
|
failedUploads = computed(() => Array.from(this.activeUploads().values()).filter(upload => upload.stage === 'error'), ...(ngDevMode ? [{ debugName: "failedUploads" }] : []));
|
|
3300
|
+
// Check if there are any files to display (active uploads OR fetched files for current group)
|
|
3301
|
+
hasFilesToShow = computed(() => {
|
|
3302
|
+
const hasActiveUploads = this.hasActiveUploads();
|
|
3303
|
+
const allFiles = this.getAllFiles();
|
|
3304
|
+
const hasFiles = allFiles.length > 0;
|
|
3305
|
+
const currentGroupId = this.currentGroupId();
|
|
3306
|
+
const fetchedFiles = currentGroupId ? this.fileManagerService.getFetchedFilesByGroupId(currentGroupId) : [];
|
|
3307
|
+
console.log('🔍 [FloatingFileUploader] hasFilesToShow check:', {
|
|
3308
|
+
hasActiveUploads,
|
|
3309
|
+
allFilesCount: allFiles.length,
|
|
3310
|
+
hasFiles,
|
|
3311
|
+
currentGroupId,
|
|
3312
|
+
fetchedFilesCount: fetchedFiles.length,
|
|
3313
|
+
fetchedFiles: fetchedFiles.map(f => ({ id: f.cyfm_id || f.id, name: f.cyfm_name || f.name })),
|
|
3314
|
+
allFiles: allFiles.map(f => ({ id: f.fileId, name: f.fileName, stage: f.stage }))
|
|
3315
|
+
});
|
|
3316
|
+
return hasActiveUploads || hasFiles;
|
|
3317
|
+
}, ...(ngDevMode ? [{ debugName: "hasFilesToShow" }] : []));
|
|
3300
3318
|
// Animation states
|
|
3301
3319
|
isAnimating = signal(false, ...(ngDevMode ? [{ debugName: "isAnimating" }] : []));
|
|
3302
3320
|
// Drag functionality
|
|
@@ -3318,14 +3336,16 @@ class CideEleFloatingFileUploaderComponent {
|
|
|
3318
3336
|
effect(() => {
|
|
3319
3337
|
const hasActiveUploads = this.hasActiveUploads();
|
|
3320
3338
|
const hasUploads = this.hasUploads();
|
|
3339
|
+
const hasFilesToShow = this.hasFilesToShow();
|
|
3321
3340
|
console.log('🔄 [FloatingFileUploader] Service state changed:', {
|
|
3322
3341
|
hasActiveUploads,
|
|
3323
3342
|
hasUploads,
|
|
3343
|
+
hasFilesToShow,
|
|
3324
3344
|
queueLength: this.uploadQueue().length,
|
|
3325
3345
|
activeUploadsCount: this.activeUploads().size,
|
|
3326
3346
|
activeUploads: Array.from(this.activeUploads().entries())
|
|
3327
3347
|
});
|
|
3328
|
-
// Show floating uploader when there are active uploads
|
|
3348
|
+
// Show floating uploader when there are active uploads OR files to show
|
|
3329
3349
|
if (hasActiveUploads && !this.isVisible()) {
|
|
3330
3350
|
console.log('👁️ [FloatingFileUploader] Showing floating uploader due to active uploads');
|
|
3331
3351
|
this.showWithAnimation();
|
|
@@ -3334,10 +3354,15 @@ class CideEleFloatingFileUploaderComponent {
|
|
|
3334
3354
|
// Set up effect to listen for manual show trigger from service
|
|
3335
3355
|
effect(() => {
|
|
3336
3356
|
const shouldShow = this.fileManagerService.showFloatingUploader();
|
|
3357
|
+
const hasFilesToShow = this.hasFilesToShow();
|
|
3337
3358
|
if (shouldShow && !this.isVisible()) {
|
|
3338
3359
|
console.log('👁️ [FloatingFileUploader] Showing floating uploader due to service trigger');
|
|
3339
3360
|
this.showWithAnimation();
|
|
3340
3361
|
}
|
|
3362
|
+
else if (shouldShow && hasFilesToShow && !this.isVisible()) {
|
|
3363
|
+
console.log('👁️ [FloatingFileUploader] Showing floating uploader due to files available');
|
|
3364
|
+
this.showWithAnimation();
|
|
3365
|
+
}
|
|
3341
3366
|
});
|
|
3342
3367
|
}
|
|
3343
3368
|
ngOnInit() {
|
|
@@ -3661,6 +3686,14 @@ class CideEleFloatingFileUploaderComponent {
|
|
|
3661
3686
|
console.log('✅ [FloatingFileUploader] Files fetched and stored:', files.length);
|
|
3662
3687
|
// Force show the uploader after files are loaded
|
|
3663
3688
|
this.showWithAnimation();
|
|
3689
|
+
// Debug: Check what files are available now
|
|
3690
|
+
setTimeout(() => {
|
|
3691
|
+
const allFiles = this.getAllFiles();
|
|
3692
|
+
console.log('🔍 [FloatingFileUploader] Files available after fetch:', {
|
|
3693
|
+
allFilesCount: allFiles.length,
|
|
3694
|
+
files: allFiles.map(f => ({ id: f.fileId, name: f.fileName, stage: f.stage }))
|
|
3695
|
+
});
|
|
3696
|
+
}, 100);
|
|
3664
3697
|
},
|
|
3665
3698
|
error: (error) => {
|
|
3666
3699
|
console.error('❌ [FloatingFileUploader] Failed to fetch files:', error);
|
|
@@ -4869,7 +4902,7 @@ class CideEleFileInputComponent {
|
|
|
4869
4902
|
useExisting: CideEleFileInputComponent,
|
|
4870
4903
|
multi: true
|
|
4871
4904
|
}
|
|
4872
|
-
], usesOnChanges: true, ngImport: i0, template: "<div class=\"cide-file-input\">\n <!-- Label (shown when not in preview box mode or when preview box mode but no label override) -->\n @if (labelSignal() && !isPreviewBoxMode()) {\n <label class=\"cide-file-input-label\" [attr.for]=\"'cide-file-input-' + id()\">\n {{ labelSignal() }}@if (requiredSignal()) {<span class=\"cide-file-input-required\"> *</span>}\n </label>\n }\n \n <!-- Preview Box Mode -->\n @if (isPreviewBoxMode()) {\n <div class=\"cide-file-input-preview-box-container\">\n <!-- Hidden file input -->\n <input\n type=\"file\"\n [attr.id]=\"'cide-file-input-' + id()\"\n [attr.accept]=\"acceptSignal()\"\n [attr.multiple]=\"multipleSignal() ? true : null\"\n [disabled]=\"disabledSignal()\"\n (change)=\"onFileSelected($event)\"\n class=\"cide-file-input-hidden\"\n />\n \n <!-- Preview Box -->\n <div \n class=\"cide-file-input-preview-box\"\n [class.cide-file-input-preview-box-disabled]=\"disabledSignal()\"\n [class.cide-file-input-preview-box-has-image]=\"hasImages()\"\n [class.cide-file-input-preview-box-drag-over]=\"isDragOver()\"\n [style.width]=\"previewWidthSignal()\"\n [style.height]=\"previewHeightSignal()\"\n (click)=\"triggerFileSelect()\"\n (dragover)=\"onDragOver($event)\"\n (dragenter)=\"onDragEnter($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n [attr.title]=\"disabledSignal() ? 'File selection disabled' : placeholderTextSignal()\">\n \n <!-- No Image State -->\n @if (!hasImages()) {\n <div class=\"cide-file-input-preview-box-placeholder\">\n <div class=\"cide-file-input-preview-box-icon\">\n <cide-ele-icon>{{ isDragOver() ? '\uD83D\uDCC1' : placeholderIconSignal() }}</cide-ele-icon>\n </div>\n <div class=\"cide-file-input-preview-box-text\">\n {{ isDragOver() ? 'Drop files here...' : placeholderTextSignal() }}\n </div>\n </div>\n }\n \n <!-- Image Preview State -->\n @if (hasImages()) {\n <div class=\"cide-file-input-preview-box-content\">\n <img \n [src]=\"previewUrls()[0]\" \n [alt]=\"fileNames()[0] || 'Preview image'\"\n class=\"cide-file-input-preview-box-image\">\n <div class=\"cide-file-input-preview-box-overlay\">\n <div class=\"cide-file-input-preview-box-overlay-text\">Click to change</div>\n </div>\n @if (!disabledSignal()) {\n <button \n type=\"button\" \n class=\"cide-file-input-preview-box-remove\"\n (click)=\"clearFiles(); $event.stopPropagation()\"\n title=\"Remove image\">\n \u00D7\n </button>\n }\n </div>\n }\n </div>\n \n <!-- File name display for preview box mode -->\n @if (hasImages() && fileNames().length && showFileNameSignal()) {\n <div class=\"cide-file-input-preview-box-filename\">\n {{ fileNames()[0] }}\n </div>\n }\n </div>\n }\n\n <!-- Standard Mode -->\n @if (!isPreviewBoxMode()) {\n <!-- Hidden file input -->\n <input\n type=\"file\"\n [attr.id]=\"'cide-file-input-' + id()\"\n [attr.accept]=\"acceptSignal()\"\n [attr.multiple]=\"multipleSignal() ? true : null\"\n [disabled]=\"disabledSignal()\"\n (change)=\"onFileSelected($event)\"\n class=\"cide-file-input-hidden\"\n />\n \n <!-- Modern Drag and Drop Zone -->\n <div \n class=\"cide-file-input-drop-zone\"\n [class.cide-file-input-drag-over]=\"isDragOver()\"\n [class.cide-file-input-disabled]=\"disabledSignal()\"\n [class.cide-file-input-has-files]=\"hasFiles()\"\n (click)=\"triggerFileSelect()\"\n (dragover)=\"onDragOver($event)\"\n (dragenter)=\"onDragEnter($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n \n <div class=\"cide-file-input-drop-content\">\n <!-- Icon and Text -->\n <div class=\"cide-file-input-drop-main\">\n <cide-ele-icon class=\"cide-file-input-drop-icon\" size=\"sm\">\n {{ isDragOver() ? 'file_download' : (hasFiles() ? 'check_circle' : 'cloud_upload') }}\n </cide-ele-icon>\n \n <div class=\"cide-file-input-drop-text\">\n @if (isDragOver()) {\n <span class=\"cide-file-input-drop-title\">Drop files here</span>\n } @else if (hasFiles()) {\n <span class=\"cide-file-input-drop-title\">\n @if (multipleSignal() && fileNames().length > 1) {\n {{ fileNames().length }} files selected\n } @else {\n {{ fileNames()[0] }}\n }\n </span>\n @if (totalFileSize() > 0) {\n <span class=\"cide-file-input-drop-subtitle\">{{ fileSizeInMB() }} MB</span>\n }\n } @else {\n <span class=\"cide-file-input-drop-title\">\n {{ multipleSignal() ? 'Choose files or drag here' : 'Choose file or drag here' }}\n </span>\n }\n </div>\n </div>\n \n <!-- Action Buttons -->\n <div class=\"cide-file-input-drop-actions\">\n @if (hasFiles()) {\n <button type=\"button\" \n class=\"cide-file-input-action-btn cide-file-input-clear-btn\" \n (click)=\"clearFiles(); $event.stopPropagation()\"\n title=\"Clear files\">\n <cide-ele-icon size=\"xs\">close</cide-ele-icon>\n </button>\n }\n </div>\n </div>\n </div>\n }\n \n <!-- Image Preview Section (only for standard mode) -->\n @if (isImagePreviewAvailable() && !isPreviewBoxMode()) {\n <div class=\"cide-file-input-preview\">\n <div class=\"cide-file-input-preview-label\">Preview:</div>\n <div class=\"cide-file-input-preview-container\">\n @for (previewUrl of previewUrls(); track previewUrl; let i = $index) {\n <div \n class=\"cide-file-input-preview-item\"\n [style.width]=\"previewWidthSignal()\"\n [style.height]=\"previewHeightSignal()\">\n <button \n type=\"button\" \n class=\"cide-file-input-preview-remove\"\n (click)=\"removePreview(i)\"\n title=\"Remove image\">\n \u00D7\n </button>\n <img \n [src]=\"previewUrl\" \n [alt]=\"fileNames()[i] || 'Preview image'\"\n class=\"cide-file-input-preview-image\"\n loading=\"lazy\">\n <div class=\"cide-file-input-preview-filename\">{{ fileNames()[i] }}</div>\n </div>\n }\n </div>\n </div>\n }\n \n <!-- Upload Status and Show Files Button (only for multiple file inputs) -->\n @if (multiple && showFloatingUploaderSignal() && (getUploadCount() > 0 || hasActiveUploads() || hasEverUploaded())) {\n <div class=\"cide-file-input-upload-status\">\n <div class=\"cide-file-input-upload-count\">\n <cide-ele-icon size=\"sm\">cloud_upload</cide-ele-icon>\n <span class=\"upload-count-text\">\n @if (hasActiveUploads()) {\n {{ getActiveUploadCount() }} uploading\n } @else if (getUploadCount() > 0) {\n {{ getUploadCount() }} completed\n } @else if (hasEverUploaded()) {\n View uploads\n }\n </span>\n </div>\n <button \n type=\"button\" \n class=\"cide-file-input-show-files-icon\"\n (click)=\"showFloatingUploaderDialog()\"\n title=\"View upload progress and history\">\n <cide-ele-icon size=\"sm\">visibility</cide-ele-icon>\n </button>\n </div>\n }\n \n @if (errorTextSignal()) {\n <div class=\"cide-file-input-error\">{{ errorTextSignal() }}</div>\n }\n @if (helperTextSignal() && !errorTextSignal()) {\n <div class=\"cide-file-input-helper\">{{ helperTextSignal() }}</div>\n }\n</div> ", styles: [".cide-file-input{display:flex;flex-direction:column;gap:.5rem}.cide-file-input-drop-zone{border:2px dashed #d1d5db;border-radius:8px;background:#f9fafb;cursor:pointer;transition:all .2s ease;min-height:60px}.cide-file-input-drop-zone:hover{border-color:#3b82f6;background:#f0f9ff}.cide-file-input-drop-zone.cide-file-input-drag-over{border-color:#3b82f6;background:#dbeafe;transform:scale(1.01)}.cide-file-input-drop-zone.cide-file-input-disabled{opacity:.5;cursor:not-allowed}.cide-file-input-drop-zone.cide-file-input-disabled:hover{border-color:#d1d5db;background:#f9fafb;transform:none}.cide-file-input-drop-zone.cide-file-input-has-files{border-color:#10b981;background:#f0fdf4}.cide-file-input-drop-zone.cide-file-input-has-files:hover{border-color:#059669;background:#ecfdf5}.cide-file-input-drop-content{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;gap:12px}.cide-file-input-drop-main{display:flex;align-items:center;gap:10px;flex:1;min-width:0}.cide-file-input-drop-icon{color:#6b7280;transition:color .2s ease;flex-shrink:0}.cide-file-input-drag-over .cide-file-input-drop-icon{color:#3b82f6}.cide-file-input-has-files .cide-file-input-drop-icon{color:#10b981}.cide-file-input-drop-text{display:flex;flex-direction:column;gap:2px;min-width:0}.cide-file-input-drop-title{font-size:14px;font-weight:500;color:#374151;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cide-file-input-drag-over .cide-file-input-drop-title{color:#1d4ed8}.cide-file-input-has-files .cide-file-input-drop-title{color:#065f46}.cide-file-input-drop-subtitle{font-size:12px;color:#6b7280}.cide-file-input-has-files .cide-file-input-drop-subtitle{color:#047857}.cide-file-input-drop-actions{display:flex;gap:4px;flex-shrink:0}.cide-file-input-action-btn{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;border-radius:4px;background:transparent;cursor:pointer;transition:all .2s ease}.cide-file-input-action-btn:hover{background:#0000000d}.cide-file-input-action-btn.cide-file-input-clear-btn{color:#dc2626}.cide-file-input-action-btn.cide-file-input-clear-btn:hover{background:#fef2f2;color:#b91c1c}.cide-file-input-label{font-weight:500;margin-bottom:.25rem}.cide-file-input-required{color:#d32f2f;font-weight:700}.cide-file-input-wrapper{display:flex;align-items:center;gap:.5rem;border:2px dashed transparent;border-radius:.5rem;padding:.5rem;transition:all .2s ease-in-out}.cide-file-input-wrapper.cide-file-input-drag-over{border-color:#3b82f6;background-color:#eff6ff;transform:scale(1.02)}.cide-file-input-element{flex:1}.cide-file-input-clear{background:none;border:none;color:#d32f2f;cursor:pointer;font-size:.9rem}.cide-file-input-files{font-size:.95rem;color:#333;margin-top:.25rem}.cide-file-input-multiple-count{display:inline-flex;align-items:center;gap:.5rem;padding:.5rem 1rem;background-color:#f0f9ff;border:1px solid #0ea5e9;border-radius:.5rem;color:#0369a1;font-weight:500;font-size:.9rem}.cide-file-input-size{margin-top:.5rem;padding:.25rem .5rem;background-color:#f3f4f6;border-radius:.25rem;font-size:.75rem;color:#4b5563;font-weight:500}.cide-file-input-error{color:#d32f2f;font-size:.9rem}.cide-file-input-helper{color:#666;font-size:.9rem}.cide-file-input-preview{margin-top:.75rem;padding:.75rem;background-color:#f8f9fa;border:1px solid #e1e5e9;border-radius:.375rem}.cide-file-input-preview-label{font-weight:500;margin-bottom:.5rem;color:#374151;font-size:.875rem}.cide-file-input-preview-container{display:flex;flex-wrap:wrap;gap:.75rem}.cide-file-input-preview-item{position:relative;display:flex;flex-direction:column;border:1px solid #d1d5db;border-radius:.5rem;overflow:hidden;background-color:#fff;box-shadow:0 1px 3px #0000001a;transition:box-shadow .2s ease-in-out}.cide-file-input-preview-item:hover{box-shadow:0 4px 6px -1px #0000001a}.cide-file-input-preview-image{width:100%;height:calc(100% - 2rem);object-fit:cover;object-position:center;background-color:#f3f4f6}.cide-file-input-preview-filename{padding:.375rem .5rem;background-color:#f9fafbf2;border-top:1px solid #e5e7eb;font-size:.75rem;color:#374151;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-height:2rem;display:flex;align-items:center;justify-content:center}.cide-file-input-preview-remove{position:absolute;top:.25rem;right:.25rem;width:1.5rem;height:1.5rem;background-color:#ef4444e6;color:#fff;border:none;border-radius:50%;font-size:1rem;font-weight:700;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:10;transition:all .2s ease-in-out}.cide-file-input-preview-remove:hover{background-color:#dc2626f2;transform:scale(1.1)}.cide-file-input-preview-remove:focus{outline:2px solid #3b82f6;outline-offset:2px}.cide-file-input-hidden{display:none}.cide-file-input-preview-box-container{display:flex;flex-direction:column;gap:.5rem}.cide-file-input-preview-box{position:relative;border:2px dashed #d1d5db;border-radius:.5rem;cursor:pointer;background-color:#f9fafb;display:flex;align-items:center;justify-content:center;overflow:hidden;transition:all .2s ease-in-out}.cide-file-input-preview-box:hover{border-color:#3b82f6;background-color:#eff6ff}.cide-file-input-preview-box.cide-file-input-preview-box-disabled{cursor:not-allowed;opacity:.6;background-color:#f3f4f6}.cide-file-input-preview-box.cide-file-input-preview-box-disabled:hover{border-color:#d1d5db;background-color:#f3f4f6}.cide-file-input-preview-box.cide-file-input-preview-box-has-image{border-style:solid;border-color:#e5e7eb;padding:0}.cide-file-input-preview-box.cide-file-input-preview-box-has-image:hover{border-color:#3b82f6}.cide-file-input-preview-box.cide-file-input-preview-box-has-image:hover .cide-file-input-preview-box-overlay{opacity:1}.cide-file-input-preview-box.cide-file-input-preview-box-drag-over{border-color:#3b82f6!important;background-color:#eff6ff!important;transform:scale(1.02);box-shadow:0 0 0 4px #3b82f61a}.cide-file-input-preview-box.cide-file-input-preview-box-drag-over .cide-file-input-preview-box-placeholder .cide-file-input-preview-box-icon{color:#3b82f6;transform:scale(1.1)}.cide-file-input-preview-box.cide-file-input-preview-box-drag-over .cide-file-input-preview-box-placeholder .cide-file-input-preview-box-text{color:#3b82f6;font-weight:600}.cide-file-input-preview-box-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;padding:1rem;text-align:center}.cide-file-input-preview-box-icon{font-size:2rem;color:#6b7280}.cide-file-input-preview-box-text{font-size:.875rem;color:#6b7280;font-weight:500}.cide-file-input-preview-box-content{position:relative;width:100%;height:100%;display:flex;align-items:center;justify-content:center}.cide-file-input-preview-box-image{width:100%;height:100%;object-fit:cover;object-position:center}.cide-file-input-preview-box-overlay{position:absolute;inset:0;background-color:#0009;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .2s ease-in-out}.cide-file-input-preview-box-overlay-text{color:#fff;font-size:.875rem;font-weight:500;text-align:center}.cide-file-input-preview-box-remove{position:absolute;top:.375rem;right:.375rem;width:1.5rem;height:1.5rem;background-color:#ef4444e6;color:#fff;border:none;border-radius:50%;font-size:1rem;font-weight:700;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:20;transition:all .2s ease-in-out}.cide-file-input-preview-box-remove:hover{background-color:#dc2626f2;transform:scale(1.1)}.cide-file-input-preview-box-remove:focus{outline:2px solid #3b82f6;outline-offset:2px}.cide-file-input-preview-box-filename{font-size:.75rem;color:#374151;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding:.25rem .5rem;background-color:#f3f4f6;border-radius:.25rem;margin-top:.25rem}@media (max-width: 640px){.cide-file-input-preview-container{justify-content:center}.cide-file-input-preview-item{min-width:120px;max-width:150px}.cide-file-input-preview-box-icon{font-size:1.5rem}.cide-file-input-preview-box-text{font-size:.75rem}}.cide-file-input-upload-status{display:flex;align-items:center;justify-content:space-between;padding:.5rem .75rem;background:#f8fafc;border:1px solid #e2e8f0;border-radius:.375rem;margin-top:.5rem;gap:.75rem}.cide-file-input-upload-status .cide-file-input-upload-count{display:flex;align-items:center;gap:.5rem;color:#64748b;font-size:.875rem;font-weight:500}.cide-file-input-upload-status .cide-file-input-upload-count .upload-count-text{color:#1e293b}.cide-file-input-upload-status .cide-file-input-show-files-icon{display:flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;background:transparent;color:#6b7280;border:none;border-radius:.25rem;cursor:pointer;transition:all .2s ease}.cide-file-input-upload-status .cide-file-input-show-files-icon:hover{background:#f3f4f6;color:#3b82f6}.cide-file-input-upload-status .cide-file-input-show-files-icon:active{background:#e5e7eb}@media (prefers-color-scheme: dark){.cide-file-input-drop-zone{border-color:#475569;background:#334155}.cide-file-input-drop-zone:hover{border-color:#3b82f6;background:#1e3a8a}.cide-file-input-drop-zone.cide-file-input-drag-over{border-color:#60a5fa;background:#1e40af}.cide-file-input-drop-zone.cide-file-input-has-files{border-color:#10b981;background:#064e3b}.cide-file-input-drop-zone.cide-file-input-has-files:hover{border-color:#059669;background:#065f46}.cide-file-input-drop-icon{color:#94a3b8}.cide-file-input-drag-over .cide-file-input-drop-icon{color:#60a5fa}.cide-file-input-has-files .cide-file-input-drop-icon{color:#34d399}.cide-file-input-drop-title{color:#f1f5f9}.cide-file-input-drag-over .cide-file-input-drop-title{color:#93c5fd}.cide-file-input-has-files .cide-file-input-drop-title{color:#6ee7b7}.cide-file-input-drop-subtitle{color:#94a3b8}.cide-file-input-has-files .cide-file-input-drop-subtitle{color:#a7f3d0}.cide-file-input-action-btn:hover{background:#ffffff1a}.cide-file-input-action-btn.cide-file-input-clear-btn{color:#f87171}.cide-file-input-action-btn.cide-file-input-clear-btn:hover{background:#7f1d1d;color:#fca5a5}.cide-file-input-upload-status{background:#1e293b;border-color:#334155}.cide-file-input-upload-status .cide-file-input-upload-count{color:#94a3b8}.cide-file-input-upload-status .cide-file-input-upload-count .upload-count-text{color:#f1f5f9}.cide-file-input-upload-status .cide-file-input-show-files-icon{color:#94a3b8}.cide-file-input-upload-status .cide-file-input-show-files-icon:hover{background:#374151;color:#60a5fa}.cide-file-input-upload-status .cide-file-input-show-files-icon:active{background:#4b5563}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }] });
|
|
4905
|
+
], usesOnChanges: true, ngImport: i0, template: "<div class=\"cide-file-input\">\n <!-- Label (shown when not in preview box mode or when preview box mode but no label override) -->\n @if (labelSignal() && !isPreviewBoxMode()) {\n <label class=\"cide-file-input-label\" [attr.for]=\"'cide-file-input-' + id()\">\n {{ labelSignal() }}@if (requiredSignal()) {<span class=\"cide-file-input-required\"> *</span>}\n </label>\n }\n \n <!-- Preview Box Mode -->\n @if (isPreviewBoxMode()) {\n <div class=\"cide-file-input-preview-box-container\">\n <!-- Hidden file input -->\n <input\n type=\"file\"\n [attr.id]=\"'cide-file-input-' + id()\"\n [attr.accept]=\"acceptSignal()\"\n [attr.multiple]=\"multipleSignal() ? true : null\"\n [disabled]=\"disabledSignal()\"\n (change)=\"onFileSelected($event)\"\n class=\"cide-file-input-hidden\"\n />\n \n <!-- Preview Box -->\n <div \n class=\"cide-file-input-preview-box\"\n [class.cide-file-input-preview-box-disabled]=\"disabledSignal()\"\n [class.cide-file-input-preview-box-has-image]=\"hasImages()\"\n [class.cide-file-input-preview-box-drag-over]=\"isDragOver()\"\n [style.width]=\"previewWidthSignal()\"\n [style.height]=\"previewHeightSignal()\"\n (click)=\"triggerFileSelect()\"\n (dragover)=\"onDragOver($event)\"\n (dragenter)=\"onDragEnter($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n [attr.title]=\"disabledSignal() ? 'File selection disabled' : placeholderTextSignal()\">\n \n <!-- No Image State -->\n @if (!hasImages()) {\n <div class=\"cide-file-input-preview-box-placeholder\">\n <div class=\"cide-file-input-preview-box-icon\">\n <cide-ele-icon>{{ isDragOver() ? '\uD83D\uDCC1' : placeholderIconSignal() }}</cide-ele-icon>\n </div>\n <div class=\"cide-file-input-preview-box-text\">\n {{ isDragOver() ? 'Drop files here...' : placeholderTextSignal() }}\n </div>\n </div>\n }\n \n <!-- Image Preview State -->\n @if (hasImages()) {\n <div class=\"cide-file-input-preview-box-content\">\n <img \n [src]=\"previewUrls()[0]\" \n [alt]=\"fileNames()[0] || 'Preview image'\"\n class=\"cide-file-input-preview-box-image\">\n <div class=\"cide-file-input-preview-box-overlay\">\n <div class=\"cide-file-input-preview-box-overlay-text\">Click to change</div>\n </div>\n @if (!disabledSignal()) {\n <button \n type=\"button\" \n class=\"cide-file-input-preview-box-remove\"\n (click)=\"clearFiles(); $event.stopPropagation()\"\n title=\"Remove image\">\n \u00D7\n </button>\n }\n </div>\n }\n </div>\n \n <!-- File name display for preview box mode -->\n @if (hasImages() && fileNames().length && showFileNameSignal()) {\n <div class=\"cide-file-input-preview-box-filename\">\n {{ fileNames()[0] }}\n </div>\n }\n </div>\n }\n\n <!-- Standard Mode -->\n @if (!isPreviewBoxMode()) {\n <!-- Hidden file input -->\n <input\n type=\"file\"\n [attr.id]=\"'cide-file-input-' + id()\"\n [attr.accept]=\"acceptSignal()\"\n [attr.multiple]=\"multipleSignal() ? true : null\"\n [disabled]=\"disabledSignal()\"\n (change)=\"onFileSelected($event)\"\n class=\"cide-file-input-hidden\"\n />\n \n <!-- Modern Drag and Drop Zone -->\n <div \n class=\"cide-file-input-drop-zone\"\n [class.cide-file-input-drag-over]=\"isDragOver()\"\n [class.cide-file-input-disabled]=\"disabledSignal()\"\n [class.cide-file-input-has-files]=\"hasFiles()\"\n (click)=\"triggerFileSelect()\"\n (dragover)=\"onDragOver($event)\"\n (dragenter)=\"onDragEnter($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n \n <div class=\"cide-file-input-drop-content\">\n <!-- Icon and Text -->\n <div class=\"cide-file-input-drop-main\">\n <cide-ele-icon class=\"cide-file-input-drop-icon\" size=\"sm\">\n {{ isDragOver() ? 'file_download' : (hasFiles() ? 'check_circle' : 'cloud_upload') }}\n </cide-ele-icon>\n \n <div class=\"cide-file-input-drop-text\">\n @if (isDragOver()) {\n <span class=\"cide-file-input-drop-title\">Drop files here</span>\n } @else if (hasFiles()) {\n <span class=\"cide-file-input-drop-title\">\n @if (multipleSignal() && fileNames().length > 1) {\n {{ fileNames().length }} files selected\n } @else {\n {{ fileNames()[0] }}\n }\n </span>\n @if (totalFileSize() > 0) {\n <span class=\"cide-file-input-drop-subtitle\">{{ fileSizeInMB() }} MB</span>\n }\n } @else {\n <span class=\"cide-file-input-drop-title\">\n {{ multipleSignal() ? 'Choose files or drag here' : 'Choose file or drag here' }}\n </span>\n }\n </div>\n </div>\n \n <!-- Action Buttons -->\n <div class=\"cide-file-input-drop-actions\">\n @if (hasFiles()) {\n <button type=\"button\" \n class=\"cide-file-input-action-btn cide-file-input-clear-btn\" \n (click)=\"clearFiles(); $event.stopPropagation()\"\n title=\"Clear files\">\n <cide-ele-icon size=\"xs\">close</cide-ele-icon>\n </button>\n }\n </div>\n </div>\n </div>\n }\n \n <!-- Image Preview Section (only for standard mode) -->\n @if (isImagePreviewAvailable() && !isPreviewBoxMode()) {\n <div class=\"cide-file-input-preview\">\n <div class=\"cide-file-input-preview-label\">Preview:</div>\n <div class=\"cide-file-input-preview-container\">\n @for (previewUrl of previewUrls(); track previewUrl; let i = $index) {\n <div \n class=\"cide-file-input-preview-item\"\n [style.width]=\"previewWidthSignal()\"\n [style.height]=\"previewHeightSignal()\">\n <button \n type=\"button\" \n class=\"cide-file-input-preview-remove\"\n (click)=\"removePreview(i)\"\n title=\"Remove image\">\n \u00D7\n </button>\n <img \n [src]=\"previewUrl\" \n [alt]=\"fileNames()[i] || 'Preview image'\"\n class=\"cide-file-input-preview-image\"\n loading=\"lazy\">\n <div class=\"cide-file-input-preview-filename\">{{ fileNames()[i] }}</div>\n </div>\n }\n </div>\n </div>\n }\n \n <!-- Upload Status and Show Files Button (only for multiple file inputs) -->\n @if (multiple && showFloatingUploaderSignal() && (getUploadCount() > 0 || hasActiveUploads() || hasEverUploaded())) {\n <div class=\"cide-file-input-upload-status\">\n <div class=\"cide-file-input-upload-count\">\n <cide-ele-icon size=\"sm\">cloud_upload</cide-ele-icon>\n <span class=\"upload-count-text\">\n @if (hasActiveUploads()) {\n {{ getActiveUploadCount() }} uploading\n } @else if (getUploadCount() > 0) {\n {{ getUploadCount() }} completed\n } @else if (hasEverUploaded()) {\n View uploads\n }\n </span>\n </div>\n <button \n type=\"button\" \n class=\"cide-file-input-show-files-icon\"\n (click)=\"showFloatingUploaderDialog()\"\n title=\"View upload progress and history\">\n <cide-ele-icon size=\"sm\">visibility</cide-ele-icon>\n </button>\n </div>\n }\n \n @if (errorTextSignal()) {\n <div class=\"cide-file-input-error\">{{ errorTextSignal() }}</div>\n }\n @if (helperTextSignal() && !errorTextSignal()) {\n <div class=\"cide-file-input-helper\">{{ helperTextSignal() }}</div>\n }\n</div> ", styles: [".cide-file-input{display:flex;flex-direction:column;gap:.5rem}.cide-file-input-drop-zone{border:2px dashed #d1d5db;border-radius:8px;background:#f9fafb;cursor:pointer;transition:all .2s ease;min-height:60px}.cide-file-input-drop-zone:hover{border-color:#3b82f6;background:#f0f9ff}.cide-file-input-drop-zone.cide-file-input-drag-over{border-color:#3b82f6;background:#dbeafe;transform:scale(1.01)}.cide-file-input-drop-zone.cide-file-input-disabled{opacity:.5;cursor:not-allowed}.cide-file-input-drop-zone.cide-file-input-disabled:hover{border-color:#d1d5db;background:#f9fafb;transform:none}.cide-file-input-drop-zone.cide-file-input-has-files{border-color:#10b981;background:#f0fdf4}.cide-file-input-drop-zone.cide-file-input-has-files:hover{border-color:#059669;background:#ecfdf5}.cide-file-input-drop-content{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;gap:12px}.cide-file-input-drop-main{display:flex;align-items:center;gap:10px;flex:1;min-width:0}.cide-file-input-drop-icon{color:#6b7280;transition:color .2s ease;flex-shrink:0}.cide-file-input-drag-over .cide-file-input-drop-icon{color:#3b82f6}.cide-file-input-has-files .cide-file-input-drop-icon{color:#10b981}.cide-file-input-drop-text{display:flex;flex-direction:column;gap:2px;min-width:0}.cide-file-input-drop-title{font-size:14px;font-weight:500;color:#374151;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cide-file-input-drag-over .cide-file-input-drop-title{color:#1d4ed8}.cide-file-input-has-files .cide-file-input-drop-title{color:#065f46}.cide-file-input-drop-subtitle{font-size:12px;color:#6b7280}.cide-file-input-has-files .cide-file-input-drop-subtitle{color:#047857}.cide-file-input-drop-actions{display:flex;gap:4px;flex-shrink:0}.cide-file-input-action-btn{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;border-radius:4px;background:transparent;cursor:pointer;transition:all .2s ease}.cide-file-input-action-btn:hover{background:#0000000d}.cide-file-input-action-btn.cide-file-input-clear-btn{color:#dc2626}.cide-file-input-action-btn.cide-file-input-clear-btn:hover{background:#fef2f2;color:#b91c1c}.cide-file-input-label{display:block;font-size:.875rem;font-weight:500;color:#374151;margin-bottom:.375rem;line-height:1.25}.cide-file-input-required{color:#d32f2f;font-weight:700}.cide-file-input-wrapper{display:flex;align-items:center;gap:.5rem;border:2px dashed transparent;border-radius:.5rem;padding:.5rem;transition:all .2s ease-in-out}.cide-file-input-wrapper.cide-file-input-drag-over{border-color:#3b82f6;background-color:#eff6ff;transform:scale(1.02)}.cide-file-input-element{flex:1}.cide-file-input-clear{background:none;border:none;color:#d32f2f;cursor:pointer;font-size:.9rem}.cide-file-input-files{font-size:.95rem;color:#333;margin-top:.25rem}.cide-file-input-multiple-count{display:inline-flex;align-items:center;gap:.5rem;padding:.5rem 1rem;background-color:#f0f9ff;border:1px solid #0ea5e9;border-radius:.5rem;color:#0369a1;font-weight:500;font-size:.9rem}.cide-file-input-size{margin-top:.5rem;padding:.25rem .5rem;background-color:#f3f4f6;border-radius:.25rem;font-size:.75rem;color:#4b5563;font-weight:500}.cide-file-input-error{color:#d32f2f;font-size:.9rem}.cide-file-input-helper{color:#666;font-size:.9rem}.cide-file-input-preview{margin-top:.75rem;padding:.75rem;background-color:#f8f9fa;border:1px solid #e1e5e9;border-radius:.375rem}.cide-file-input-preview-label{font-weight:500;margin-bottom:.5rem;color:#374151;font-size:.875rem}.cide-file-input-preview-container{display:flex;flex-wrap:wrap;gap:.75rem}.cide-file-input-preview-item{position:relative;display:flex;flex-direction:column;border:1px solid #d1d5db;border-radius:.5rem;overflow:hidden;background-color:#fff;box-shadow:0 1px 3px #0000001a;transition:box-shadow .2s ease-in-out}.cide-file-input-preview-item:hover{box-shadow:0 4px 6px -1px #0000001a}.cide-file-input-preview-image{width:100%;height:calc(100% - 2rem);object-fit:cover;object-position:center;background-color:#f3f4f6}.cide-file-input-preview-filename{padding:.375rem .5rem;background-color:#f9fafbf2;border-top:1px solid #e5e7eb;font-size:.75rem;color:#374151;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-height:2rem;display:flex;align-items:center;justify-content:center}.cide-file-input-preview-remove{position:absolute;top:.25rem;right:.25rem;width:1.5rem;height:1.5rem;background-color:#ef4444e6;color:#fff;border:none;border-radius:50%;font-size:1rem;font-weight:700;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:10;transition:all .2s ease-in-out}.cide-file-input-preview-remove:hover{background-color:#dc2626f2;transform:scale(1.1)}.cide-file-input-preview-remove:focus{outline:2px solid #3b82f6;outline-offset:2px}.cide-file-input-hidden{display:none}.cide-file-input-preview-box-container{display:flex;flex-direction:column;gap:.5rem}.cide-file-input-preview-box{position:relative;border:2px dashed #d1d5db;border-radius:.5rem;cursor:pointer;background-color:#f9fafb;display:flex;align-items:center;justify-content:center;overflow:hidden;transition:all .2s ease-in-out}.cide-file-input-preview-box:hover{border-color:#3b82f6;background-color:#eff6ff}.cide-file-input-preview-box.cide-file-input-preview-box-disabled{cursor:not-allowed;opacity:.6;background-color:#f3f4f6}.cide-file-input-preview-box.cide-file-input-preview-box-disabled:hover{border-color:#d1d5db;background-color:#f3f4f6}.cide-file-input-preview-box.cide-file-input-preview-box-has-image{border-style:solid;border-color:#e5e7eb;padding:0}.cide-file-input-preview-box.cide-file-input-preview-box-has-image:hover{border-color:#3b82f6}.cide-file-input-preview-box.cide-file-input-preview-box-has-image:hover .cide-file-input-preview-box-overlay{opacity:1}.cide-file-input-preview-box.cide-file-input-preview-box-drag-over{border-color:#3b82f6!important;background-color:#eff6ff!important;transform:scale(1.02);box-shadow:0 0 0 4px #3b82f61a}.cide-file-input-preview-box.cide-file-input-preview-box-drag-over .cide-file-input-preview-box-placeholder .cide-file-input-preview-box-icon{color:#3b82f6;transform:scale(1.1)}.cide-file-input-preview-box.cide-file-input-preview-box-drag-over .cide-file-input-preview-box-placeholder .cide-file-input-preview-box-text{color:#3b82f6;font-weight:600}.cide-file-input-preview-box-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;padding:1rem;text-align:center}.cide-file-input-preview-box-icon{font-size:2rem;color:#6b7280}.cide-file-input-preview-box-text{font-size:.875rem;color:#6b7280;font-weight:500}.cide-file-input-preview-box-content{position:relative;width:100%;height:100%;display:flex;align-items:center;justify-content:center}.cide-file-input-preview-box-image{width:100%;height:100%;object-fit:cover;object-position:center}.cide-file-input-preview-box-overlay{position:absolute;inset:0;background-color:#0009;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .2s ease-in-out}.cide-file-input-preview-box-overlay-text{color:#fff;font-size:.875rem;font-weight:500;text-align:center}.cide-file-input-preview-box-remove{position:absolute;top:.375rem;right:.375rem;width:1.5rem;height:1.5rem;background-color:#ef4444e6;color:#fff;border:none;border-radius:50%;font-size:1rem;font-weight:700;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:20;transition:all .2s ease-in-out}.cide-file-input-preview-box-remove:hover{background-color:#dc2626f2;transform:scale(1.1)}.cide-file-input-preview-box-remove:focus{outline:2px solid #3b82f6;outline-offset:2px}.cide-file-input-preview-box-filename{font-size:.75rem;color:#374151;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding:.25rem .5rem;background-color:#f3f4f6;border-radius:.25rem;margin-top:.25rem}@media (max-width: 640px){.cide-file-input-preview-container{justify-content:center}.cide-file-input-preview-item{min-width:120px;max-width:150px}.cide-file-input-preview-box-icon{font-size:1.5rem}.cide-file-input-preview-box-text{font-size:.75rem}}.cide-file-input-upload-status{display:flex;align-items:center;justify-content:space-between;padding:.25rem 0;margin-top:.375rem;gap:.5rem}.cide-file-input-upload-status .cide-file-input-upload-count{display:flex;align-items:center;gap:.5rem;color:#64748b;font-size:.875rem;font-weight:500}.cide-file-input-upload-status .cide-file-input-upload-count .upload-count-text{color:#1e293b}.cide-file-input-upload-status .cide-file-input-show-files-icon{display:flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;background:transparent;color:#6b7280;border:none;border-radius:.25rem;cursor:pointer;transition:all .2s ease}.cide-file-input-upload-status .cide-file-input-show-files-icon:hover{background:#f3f4f6;color:#3b82f6}.cide-file-input-upload-status .cide-file-input-show-files-icon:active{background:#e5e7eb}@media (prefers-color-scheme: dark){.cide-file-input-label{color:#f9fafb}.cide-file-input-required{color:#f87171}.cide-file-input-drop-zone{border-color:#475569;background:#334155}.cide-file-input-drop-zone:hover{border-color:#3b82f6;background:#1e3a8a}.cide-file-input-drop-zone.cide-file-input-drag-over{border-color:#60a5fa;background:#1e40af}.cide-file-input-drop-zone.cide-file-input-has-files{border-color:#10b981;background:#064e3b}.cide-file-input-drop-zone.cide-file-input-has-files:hover{border-color:#059669;background:#065f46}.cide-file-input-drop-icon{color:#94a3b8}.cide-file-input-drag-over .cide-file-input-drop-icon{color:#60a5fa}.cide-file-input-has-files .cide-file-input-drop-icon{color:#34d399}.cide-file-input-drop-title{color:#f1f5f9}.cide-file-input-drag-over .cide-file-input-drop-title{color:#93c5fd}.cide-file-input-has-files .cide-file-input-drop-title{color:#6ee7b7}.cide-file-input-drop-subtitle{color:#94a3b8}.cide-file-input-has-files .cide-file-input-drop-subtitle{color:#a7f3d0}.cide-file-input-action-btn:hover{background:#ffffff1a}.cide-file-input-action-btn.cide-file-input-clear-btn{color:#f87171}.cide-file-input-action-btn.cide-file-input-clear-btn:hover{background:#7f1d1d;color:#fca5a5}.cide-file-input-upload-status .cide-file-input-upload-count{color:#94a3b8}.cide-file-input-upload-status .cide-file-input-upload-count .upload-count-text{color:#f1f5f9}.cide-file-input-upload-status .cide-file-input-show-files-icon{color:#94a3b8}.cide-file-input-upload-status .cide-file-input-show-files-icon:hover{background:#374151;color:#60a5fa}.cide-file-input-upload-status .cide-file-input-show-files-icon:active{background:#4b5563}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }] });
|
|
4873
4906
|
}
|
|
4874
4907
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFileInputComponent, decorators: [{
|
|
4875
4908
|
type: Component,
|
|
@@ -4884,7 +4917,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
|
|
|
4884
4917
|
useExisting: CideEleFileInputComponent,
|
|
4885
4918
|
multi: true
|
|
4886
4919
|
}
|
|
4887
|
-
], template: "<div class=\"cide-file-input\">\n <!-- Label (shown when not in preview box mode or when preview box mode but no label override) -->\n @if (labelSignal() && !isPreviewBoxMode()) {\n <label class=\"cide-file-input-label\" [attr.for]=\"'cide-file-input-' + id()\">\n {{ labelSignal() }}@if (requiredSignal()) {<span class=\"cide-file-input-required\"> *</span>}\n </label>\n }\n \n <!-- Preview Box Mode -->\n @if (isPreviewBoxMode()) {\n <div class=\"cide-file-input-preview-box-container\">\n <!-- Hidden file input -->\n <input\n type=\"file\"\n [attr.id]=\"'cide-file-input-' + id()\"\n [attr.accept]=\"acceptSignal()\"\n [attr.multiple]=\"multipleSignal() ? true : null\"\n [disabled]=\"disabledSignal()\"\n (change)=\"onFileSelected($event)\"\n class=\"cide-file-input-hidden\"\n />\n \n <!-- Preview Box -->\n <div \n class=\"cide-file-input-preview-box\"\n [class.cide-file-input-preview-box-disabled]=\"disabledSignal()\"\n [class.cide-file-input-preview-box-has-image]=\"hasImages()\"\n [class.cide-file-input-preview-box-drag-over]=\"isDragOver()\"\n [style.width]=\"previewWidthSignal()\"\n [style.height]=\"previewHeightSignal()\"\n (click)=\"triggerFileSelect()\"\n (dragover)=\"onDragOver($event)\"\n (dragenter)=\"onDragEnter($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n [attr.title]=\"disabledSignal() ? 'File selection disabled' : placeholderTextSignal()\">\n \n <!-- No Image State -->\n @if (!hasImages()) {\n <div class=\"cide-file-input-preview-box-placeholder\">\n <div class=\"cide-file-input-preview-box-icon\">\n <cide-ele-icon>{{ isDragOver() ? '\uD83D\uDCC1' : placeholderIconSignal() }}</cide-ele-icon>\n </div>\n <div class=\"cide-file-input-preview-box-text\">\n {{ isDragOver() ? 'Drop files here...' : placeholderTextSignal() }}\n </div>\n </div>\n }\n \n <!-- Image Preview State -->\n @if (hasImages()) {\n <div class=\"cide-file-input-preview-box-content\">\n <img \n [src]=\"previewUrls()[0]\" \n [alt]=\"fileNames()[0] || 'Preview image'\"\n class=\"cide-file-input-preview-box-image\">\n <div class=\"cide-file-input-preview-box-overlay\">\n <div class=\"cide-file-input-preview-box-overlay-text\">Click to change</div>\n </div>\n @if (!disabledSignal()) {\n <button \n type=\"button\" \n class=\"cide-file-input-preview-box-remove\"\n (click)=\"clearFiles(); $event.stopPropagation()\"\n title=\"Remove image\">\n \u00D7\n </button>\n }\n </div>\n }\n </div>\n \n <!-- File name display for preview box mode -->\n @if (hasImages() && fileNames().length && showFileNameSignal()) {\n <div class=\"cide-file-input-preview-box-filename\">\n {{ fileNames()[0] }}\n </div>\n }\n </div>\n }\n\n <!-- Standard Mode -->\n @if (!isPreviewBoxMode()) {\n <!-- Hidden file input -->\n <input\n type=\"file\"\n [attr.id]=\"'cide-file-input-' + id()\"\n [attr.accept]=\"acceptSignal()\"\n [attr.multiple]=\"multipleSignal() ? true : null\"\n [disabled]=\"disabledSignal()\"\n (change)=\"onFileSelected($event)\"\n class=\"cide-file-input-hidden\"\n />\n \n <!-- Modern Drag and Drop Zone -->\n <div \n class=\"cide-file-input-drop-zone\"\n [class.cide-file-input-drag-over]=\"isDragOver()\"\n [class.cide-file-input-disabled]=\"disabledSignal()\"\n [class.cide-file-input-has-files]=\"hasFiles()\"\n (click)=\"triggerFileSelect()\"\n (dragover)=\"onDragOver($event)\"\n (dragenter)=\"onDragEnter($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n \n <div class=\"cide-file-input-drop-content\">\n <!-- Icon and Text -->\n <div class=\"cide-file-input-drop-main\">\n <cide-ele-icon class=\"cide-file-input-drop-icon\" size=\"sm\">\n {{ isDragOver() ? 'file_download' : (hasFiles() ? 'check_circle' : 'cloud_upload') }}\n </cide-ele-icon>\n \n <div class=\"cide-file-input-drop-text\">\n @if (isDragOver()) {\n <span class=\"cide-file-input-drop-title\">Drop files here</span>\n } @else if (hasFiles()) {\n <span class=\"cide-file-input-drop-title\">\n @if (multipleSignal() && fileNames().length > 1) {\n {{ fileNames().length }} files selected\n } @else {\n {{ fileNames()[0] }}\n }\n </span>\n @if (totalFileSize() > 0) {\n <span class=\"cide-file-input-drop-subtitle\">{{ fileSizeInMB() }} MB</span>\n }\n } @else {\n <span class=\"cide-file-input-drop-title\">\n {{ multipleSignal() ? 'Choose files or drag here' : 'Choose file or drag here' }}\n </span>\n }\n </div>\n </div>\n \n <!-- Action Buttons -->\n <div class=\"cide-file-input-drop-actions\">\n @if (hasFiles()) {\n <button type=\"button\" \n class=\"cide-file-input-action-btn cide-file-input-clear-btn\" \n (click)=\"clearFiles(); $event.stopPropagation()\"\n title=\"Clear files\">\n <cide-ele-icon size=\"xs\">close</cide-ele-icon>\n </button>\n }\n </div>\n </div>\n </div>\n }\n \n <!-- Image Preview Section (only for standard mode) -->\n @if (isImagePreviewAvailable() && !isPreviewBoxMode()) {\n <div class=\"cide-file-input-preview\">\n <div class=\"cide-file-input-preview-label\">Preview:</div>\n <div class=\"cide-file-input-preview-container\">\n @for (previewUrl of previewUrls(); track previewUrl; let i = $index) {\n <div \n class=\"cide-file-input-preview-item\"\n [style.width]=\"previewWidthSignal()\"\n [style.height]=\"previewHeightSignal()\">\n <button \n type=\"button\" \n class=\"cide-file-input-preview-remove\"\n (click)=\"removePreview(i)\"\n title=\"Remove image\">\n \u00D7\n </button>\n <img \n [src]=\"previewUrl\" \n [alt]=\"fileNames()[i] || 'Preview image'\"\n class=\"cide-file-input-preview-image\"\n loading=\"lazy\">\n <div class=\"cide-file-input-preview-filename\">{{ fileNames()[i] }}</div>\n </div>\n }\n </div>\n </div>\n }\n \n <!-- Upload Status and Show Files Button (only for multiple file inputs) -->\n @if (multiple && showFloatingUploaderSignal() && (getUploadCount() > 0 || hasActiveUploads() || hasEverUploaded())) {\n <div class=\"cide-file-input-upload-status\">\n <div class=\"cide-file-input-upload-count\">\n <cide-ele-icon size=\"sm\">cloud_upload</cide-ele-icon>\n <span class=\"upload-count-text\">\n @if (hasActiveUploads()) {\n {{ getActiveUploadCount() }} uploading\n } @else if (getUploadCount() > 0) {\n {{ getUploadCount() }} completed\n } @else if (hasEverUploaded()) {\n View uploads\n }\n </span>\n </div>\n <button \n type=\"button\" \n class=\"cide-file-input-show-files-icon\"\n (click)=\"showFloatingUploaderDialog()\"\n title=\"View upload progress and history\">\n <cide-ele-icon size=\"sm\">visibility</cide-ele-icon>\n </button>\n </div>\n }\n \n @if (errorTextSignal()) {\n <div class=\"cide-file-input-error\">{{ errorTextSignal() }}</div>\n }\n @if (helperTextSignal() && !errorTextSignal()) {\n <div class=\"cide-file-input-helper\">{{ helperTextSignal() }}</div>\n }\n</div> ", styles: [".cide-file-input{display:flex;flex-direction:column;gap:.5rem}.cide-file-input-drop-zone{border:2px dashed #d1d5db;border-radius:8px;background:#f9fafb;cursor:pointer;transition:all .2s ease;min-height:60px}.cide-file-input-drop-zone:hover{border-color:#3b82f6;background:#f0f9ff}.cide-file-input-drop-zone.cide-file-input-drag-over{border-color:#3b82f6;background:#dbeafe;transform:scale(1.01)}.cide-file-input-drop-zone.cide-file-input-disabled{opacity:.5;cursor:not-allowed}.cide-file-input-drop-zone.cide-file-input-disabled:hover{border-color:#d1d5db;background:#f9fafb;transform:none}.cide-file-input-drop-zone.cide-file-input-has-files{border-color:#10b981;background:#f0fdf4}.cide-file-input-drop-zone.cide-file-input-has-files:hover{border-color:#059669;background:#ecfdf5}.cide-file-input-drop-content{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;gap:12px}.cide-file-input-drop-main{display:flex;align-items:center;gap:10px;flex:1;min-width:0}.cide-file-input-drop-icon{color:#6b7280;transition:color .2s ease;flex-shrink:0}.cide-file-input-drag-over .cide-file-input-drop-icon{color:#3b82f6}.cide-file-input-has-files .cide-file-input-drop-icon{color:#10b981}.cide-file-input-drop-text{display:flex;flex-direction:column;gap:2px;min-width:0}.cide-file-input-drop-title{font-size:14px;font-weight:500;color:#374151;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cide-file-input-drag-over .cide-file-input-drop-title{color:#1d4ed8}.cide-file-input-has-files .cide-file-input-drop-title{color:#065f46}.cide-file-input-drop-subtitle{font-size:12px;color:#6b7280}.cide-file-input-has-files .cide-file-input-drop-subtitle{color:#047857}.cide-file-input-drop-actions{display:flex;gap:4px;flex-shrink:0}.cide-file-input-action-btn{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;border-radius:4px;background:transparent;cursor:pointer;transition:all .2s ease}.cide-file-input-action-btn:hover{background:#0000000d}.cide-file-input-action-btn.cide-file-input-clear-btn{color:#dc2626}.cide-file-input-action-btn.cide-file-input-clear-btn:hover{background:#fef2f2;color:#b91c1c}.cide-file-input-label{font-weight:500;margin-bottom:.25rem}.cide-file-input-required{color:#d32f2f;font-weight:700}.cide-file-input-wrapper{display:flex;align-items:center;gap:.5rem;border:2px dashed transparent;border-radius:.5rem;padding:.5rem;transition:all .2s ease-in-out}.cide-file-input-wrapper.cide-file-input-drag-over{border-color:#3b82f6;background-color:#eff6ff;transform:scale(1.02)}.cide-file-input-element{flex:1}.cide-file-input-clear{background:none;border:none;color:#d32f2f;cursor:pointer;font-size:.9rem}.cide-file-input-files{font-size:.95rem;color:#333;margin-top:.25rem}.cide-file-input-multiple-count{display:inline-flex;align-items:center;gap:.5rem;padding:.5rem 1rem;background-color:#f0f9ff;border:1px solid #0ea5e9;border-radius:.5rem;color:#0369a1;font-weight:500;font-size:.9rem}.cide-file-input-size{margin-top:.5rem;padding:.25rem .5rem;background-color:#f3f4f6;border-radius:.25rem;font-size:.75rem;color:#4b5563;font-weight:500}.cide-file-input-error{color:#d32f2f;font-size:.9rem}.cide-file-input-helper{color:#666;font-size:.9rem}.cide-file-input-preview{margin-top:.75rem;padding:.75rem;background-color:#f8f9fa;border:1px solid #e1e5e9;border-radius:.375rem}.cide-file-input-preview-label{font-weight:500;margin-bottom:.5rem;color:#374151;font-size:.875rem}.cide-file-input-preview-container{display:flex;flex-wrap:wrap;gap:.75rem}.cide-file-input-preview-item{position:relative;display:flex;flex-direction:column;border:1px solid #d1d5db;border-radius:.5rem;overflow:hidden;background-color:#fff;box-shadow:0 1px 3px #0000001a;transition:box-shadow .2s ease-in-out}.cide-file-input-preview-item:hover{box-shadow:0 4px 6px -1px #0000001a}.cide-file-input-preview-image{width:100%;height:calc(100% - 2rem);object-fit:cover;object-position:center;background-color:#f3f4f6}.cide-file-input-preview-filename{padding:.375rem .5rem;background-color:#f9fafbf2;border-top:1px solid #e5e7eb;font-size:.75rem;color:#374151;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-height:2rem;display:flex;align-items:center;justify-content:center}.cide-file-input-preview-remove{position:absolute;top:.25rem;right:.25rem;width:1.5rem;height:1.5rem;background-color:#ef4444e6;color:#fff;border:none;border-radius:50%;font-size:1rem;font-weight:700;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:10;transition:all .2s ease-in-out}.cide-file-input-preview-remove:hover{background-color:#dc2626f2;transform:scale(1.1)}.cide-file-input-preview-remove:focus{outline:2px solid #3b82f6;outline-offset:2px}.cide-file-input-hidden{display:none}.cide-file-input-preview-box-container{display:flex;flex-direction:column;gap:.5rem}.cide-file-input-preview-box{position:relative;border:2px dashed #d1d5db;border-radius:.5rem;cursor:pointer;background-color:#f9fafb;display:flex;align-items:center;justify-content:center;overflow:hidden;transition:all .2s ease-in-out}.cide-file-input-preview-box:hover{border-color:#3b82f6;background-color:#eff6ff}.cide-file-input-preview-box.cide-file-input-preview-box-disabled{cursor:not-allowed;opacity:.6;background-color:#f3f4f6}.cide-file-input-preview-box.cide-file-input-preview-box-disabled:hover{border-color:#d1d5db;background-color:#f3f4f6}.cide-file-input-preview-box.cide-file-input-preview-box-has-image{border-style:solid;border-color:#e5e7eb;padding:0}.cide-file-input-preview-box.cide-file-input-preview-box-has-image:hover{border-color:#3b82f6}.cide-file-input-preview-box.cide-file-input-preview-box-has-image:hover .cide-file-input-preview-box-overlay{opacity:1}.cide-file-input-preview-box.cide-file-input-preview-box-drag-over{border-color:#3b82f6!important;background-color:#eff6ff!important;transform:scale(1.02);box-shadow:0 0 0 4px #3b82f61a}.cide-file-input-preview-box.cide-file-input-preview-box-drag-over .cide-file-input-preview-box-placeholder .cide-file-input-preview-box-icon{color:#3b82f6;transform:scale(1.1)}.cide-file-input-preview-box.cide-file-input-preview-box-drag-over .cide-file-input-preview-box-placeholder .cide-file-input-preview-box-text{color:#3b82f6;font-weight:600}.cide-file-input-preview-box-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;padding:1rem;text-align:center}.cide-file-input-preview-box-icon{font-size:2rem;color:#6b7280}.cide-file-input-preview-box-text{font-size:.875rem;color:#6b7280;font-weight:500}.cide-file-input-preview-box-content{position:relative;width:100%;height:100%;display:flex;align-items:center;justify-content:center}.cide-file-input-preview-box-image{width:100%;height:100%;object-fit:cover;object-position:center}.cide-file-input-preview-box-overlay{position:absolute;inset:0;background-color:#0009;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .2s ease-in-out}.cide-file-input-preview-box-overlay-text{color:#fff;font-size:.875rem;font-weight:500;text-align:center}.cide-file-input-preview-box-remove{position:absolute;top:.375rem;right:.375rem;width:1.5rem;height:1.5rem;background-color:#ef4444e6;color:#fff;border:none;border-radius:50%;font-size:1rem;font-weight:700;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:20;transition:all .2s ease-in-out}.cide-file-input-preview-box-remove:hover{background-color:#dc2626f2;transform:scale(1.1)}.cide-file-input-preview-box-remove:focus{outline:2px solid #3b82f6;outline-offset:2px}.cide-file-input-preview-box-filename{font-size:.75rem;color:#374151;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding:.25rem .5rem;background-color:#f3f4f6;border-radius:.25rem;margin-top:.25rem}@media (max-width: 640px){.cide-file-input-preview-container{justify-content:center}.cide-file-input-preview-item{min-width:120px;max-width:150px}.cide-file-input-preview-box-icon{font-size:1.5rem}.cide-file-input-preview-box-text{font-size:.75rem}}.cide-file-input-upload-status{display:flex;align-items:center;justify-content:space-between;padding:.5rem .75rem;background:#f8fafc;border:1px solid #e2e8f0;border-radius:.375rem;margin-top:.5rem;gap:.75rem}.cide-file-input-upload-status .cide-file-input-upload-count{display:flex;align-items:center;gap:.5rem;color:#64748b;font-size:.875rem;font-weight:500}.cide-file-input-upload-status .cide-file-input-upload-count .upload-count-text{color:#1e293b}.cide-file-input-upload-status .cide-file-input-show-files-icon{display:flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;background:transparent;color:#6b7280;border:none;border-radius:.25rem;cursor:pointer;transition:all .2s ease}.cide-file-input-upload-status .cide-file-input-show-files-icon:hover{background:#f3f4f6;color:#3b82f6}.cide-file-input-upload-status .cide-file-input-show-files-icon:active{background:#e5e7eb}@media (prefers-color-scheme: dark){.cide-file-input-drop-zone{border-color:#475569;background:#334155}.cide-file-input-drop-zone:hover{border-color:#3b82f6;background:#1e3a8a}.cide-file-input-drop-zone.cide-file-input-drag-over{border-color:#60a5fa;background:#1e40af}.cide-file-input-drop-zone.cide-file-input-has-files{border-color:#10b981;background:#064e3b}.cide-file-input-drop-zone.cide-file-input-has-files:hover{border-color:#059669;background:#065f46}.cide-file-input-drop-icon{color:#94a3b8}.cide-file-input-drag-over .cide-file-input-drop-icon{color:#60a5fa}.cide-file-input-has-files .cide-file-input-drop-icon{color:#34d399}.cide-file-input-drop-title{color:#f1f5f9}.cide-file-input-drag-over .cide-file-input-drop-title{color:#93c5fd}.cide-file-input-has-files .cide-file-input-drop-title{color:#6ee7b7}.cide-file-input-drop-subtitle{color:#94a3b8}.cide-file-input-has-files .cide-file-input-drop-subtitle{color:#a7f3d0}.cide-file-input-action-btn:hover{background:#ffffff1a}.cide-file-input-action-btn.cide-file-input-clear-btn{color:#f87171}.cide-file-input-action-btn.cide-file-input-clear-btn:hover{background:#7f1d1d;color:#fca5a5}.cide-file-input-upload-status{background:#1e293b;border-color:#334155}.cide-file-input-upload-status .cide-file-input-upload-count{color:#94a3b8}.cide-file-input-upload-status .cide-file-input-upload-count .upload-count-text{color:#f1f5f9}.cide-file-input-upload-status .cide-file-input-show-files-icon{color:#94a3b8}.cide-file-input-upload-status .cide-file-input-show-files-icon:hover{background:#374151;color:#60a5fa}.cide-file-input-upload-status .cide-file-input-show-files-icon:active{background:#4b5563}}\n"] }]
|
|
4920
|
+
], template: "<div class=\"cide-file-input\">\n <!-- Label (shown when not in preview box mode or when preview box mode but no label override) -->\n @if (labelSignal() && !isPreviewBoxMode()) {\n <label class=\"cide-file-input-label\" [attr.for]=\"'cide-file-input-' + id()\">\n {{ labelSignal() }}@if (requiredSignal()) {<span class=\"cide-file-input-required\"> *</span>}\n </label>\n }\n \n <!-- Preview Box Mode -->\n @if (isPreviewBoxMode()) {\n <div class=\"cide-file-input-preview-box-container\">\n <!-- Hidden file input -->\n <input\n type=\"file\"\n [attr.id]=\"'cide-file-input-' + id()\"\n [attr.accept]=\"acceptSignal()\"\n [attr.multiple]=\"multipleSignal() ? true : null\"\n [disabled]=\"disabledSignal()\"\n (change)=\"onFileSelected($event)\"\n class=\"cide-file-input-hidden\"\n />\n \n <!-- Preview Box -->\n <div \n class=\"cide-file-input-preview-box\"\n [class.cide-file-input-preview-box-disabled]=\"disabledSignal()\"\n [class.cide-file-input-preview-box-has-image]=\"hasImages()\"\n [class.cide-file-input-preview-box-drag-over]=\"isDragOver()\"\n [style.width]=\"previewWidthSignal()\"\n [style.height]=\"previewHeightSignal()\"\n (click)=\"triggerFileSelect()\"\n (dragover)=\"onDragOver($event)\"\n (dragenter)=\"onDragEnter($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n [attr.title]=\"disabledSignal() ? 'File selection disabled' : placeholderTextSignal()\">\n \n <!-- No Image State -->\n @if (!hasImages()) {\n <div class=\"cide-file-input-preview-box-placeholder\">\n <div class=\"cide-file-input-preview-box-icon\">\n <cide-ele-icon>{{ isDragOver() ? '\uD83D\uDCC1' : placeholderIconSignal() }}</cide-ele-icon>\n </div>\n <div class=\"cide-file-input-preview-box-text\">\n {{ isDragOver() ? 'Drop files here...' : placeholderTextSignal() }}\n </div>\n </div>\n }\n \n <!-- Image Preview State -->\n @if (hasImages()) {\n <div class=\"cide-file-input-preview-box-content\">\n <img \n [src]=\"previewUrls()[0]\" \n [alt]=\"fileNames()[0] || 'Preview image'\"\n class=\"cide-file-input-preview-box-image\">\n <div class=\"cide-file-input-preview-box-overlay\">\n <div class=\"cide-file-input-preview-box-overlay-text\">Click to change</div>\n </div>\n @if (!disabledSignal()) {\n <button \n type=\"button\" \n class=\"cide-file-input-preview-box-remove\"\n (click)=\"clearFiles(); $event.stopPropagation()\"\n title=\"Remove image\">\n \u00D7\n </button>\n }\n </div>\n }\n </div>\n \n <!-- File name display for preview box mode -->\n @if (hasImages() && fileNames().length && showFileNameSignal()) {\n <div class=\"cide-file-input-preview-box-filename\">\n {{ fileNames()[0] }}\n </div>\n }\n </div>\n }\n\n <!-- Standard Mode -->\n @if (!isPreviewBoxMode()) {\n <!-- Hidden file input -->\n <input\n type=\"file\"\n [attr.id]=\"'cide-file-input-' + id()\"\n [attr.accept]=\"acceptSignal()\"\n [attr.multiple]=\"multipleSignal() ? true : null\"\n [disabled]=\"disabledSignal()\"\n (change)=\"onFileSelected($event)\"\n class=\"cide-file-input-hidden\"\n />\n \n <!-- Modern Drag and Drop Zone -->\n <div \n class=\"cide-file-input-drop-zone\"\n [class.cide-file-input-drag-over]=\"isDragOver()\"\n [class.cide-file-input-disabled]=\"disabledSignal()\"\n [class.cide-file-input-has-files]=\"hasFiles()\"\n (click)=\"triggerFileSelect()\"\n (dragover)=\"onDragOver($event)\"\n (dragenter)=\"onDragEnter($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\">\n \n <div class=\"cide-file-input-drop-content\">\n <!-- Icon and Text -->\n <div class=\"cide-file-input-drop-main\">\n <cide-ele-icon class=\"cide-file-input-drop-icon\" size=\"sm\">\n {{ isDragOver() ? 'file_download' : (hasFiles() ? 'check_circle' : 'cloud_upload') }}\n </cide-ele-icon>\n \n <div class=\"cide-file-input-drop-text\">\n @if (isDragOver()) {\n <span class=\"cide-file-input-drop-title\">Drop files here</span>\n } @else if (hasFiles()) {\n <span class=\"cide-file-input-drop-title\">\n @if (multipleSignal() && fileNames().length > 1) {\n {{ fileNames().length }} files selected\n } @else {\n {{ fileNames()[0] }}\n }\n </span>\n @if (totalFileSize() > 0) {\n <span class=\"cide-file-input-drop-subtitle\">{{ fileSizeInMB() }} MB</span>\n }\n } @else {\n <span class=\"cide-file-input-drop-title\">\n {{ multipleSignal() ? 'Choose files or drag here' : 'Choose file or drag here' }}\n </span>\n }\n </div>\n </div>\n \n <!-- Action Buttons -->\n <div class=\"cide-file-input-drop-actions\">\n @if (hasFiles()) {\n <button type=\"button\" \n class=\"cide-file-input-action-btn cide-file-input-clear-btn\" \n (click)=\"clearFiles(); $event.stopPropagation()\"\n title=\"Clear files\">\n <cide-ele-icon size=\"xs\">close</cide-ele-icon>\n </button>\n }\n </div>\n </div>\n </div>\n }\n \n <!-- Image Preview Section (only for standard mode) -->\n @if (isImagePreviewAvailable() && !isPreviewBoxMode()) {\n <div class=\"cide-file-input-preview\">\n <div class=\"cide-file-input-preview-label\">Preview:</div>\n <div class=\"cide-file-input-preview-container\">\n @for (previewUrl of previewUrls(); track previewUrl; let i = $index) {\n <div \n class=\"cide-file-input-preview-item\"\n [style.width]=\"previewWidthSignal()\"\n [style.height]=\"previewHeightSignal()\">\n <button \n type=\"button\" \n class=\"cide-file-input-preview-remove\"\n (click)=\"removePreview(i)\"\n title=\"Remove image\">\n \u00D7\n </button>\n <img \n [src]=\"previewUrl\" \n [alt]=\"fileNames()[i] || 'Preview image'\"\n class=\"cide-file-input-preview-image\"\n loading=\"lazy\">\n <div class=\"cide-file-input-preview-filename\">{{ fileNames()[i] }}</div>\n </div>\n }\n </div>\n </div>\n }\n \n <!-- Upload Status and Show Files Button (only for multiple file inputs) -->\n @if (multiple && showFloatingUploaderSignal() && (getUploadCount() > 0 || hasActiveUploads() || hasEverUploaded())) {\n <div class=\"cide-file-input-upload-status\">\n <div class=\"cide-file-input-upload-count\">\n <cide-ele-icon size=\"sm\">cloud_upload</cide-ele-icon>\n <span class=\"upload-count-text\">\n @if (hasActiveUploads()) {\n {{ getActiveUploadCount() }} uploading\n } @else if (getUploadCount() > 0) {\n {{ getUploadCount() }} completed\n } @else if (hasEverUploaded()) {\n View uploads\n }\n </span>\n </div>\n <button \n type=\"button\" \n class=\"cide-file-input-show-files-icon\"\n (click)=\"showFloatingUploaderDialog()\"\n title=\"View upload progress and history\">\n <cide-ele-icon size=\"sm\">visibility</cide-ele-icon>\n </button>\n </div>\n }\n \n @if (errorTextSignal()) {\n <div class=\"cide-file-input-error\">{{ errorTextSignal() }}</div>\n }\n @if (helperTextSignal() && !errorTextSignal()) {\n <div class=\"cide-file-input-helper\">{{ helperTextSignal() }}</div>\n }\n</div> ", styles: [".cide-file-input{display:flex;flex-direction:column;gap:.5rem}.cide-file-input-drop-zone{border:2px dashed #d1d5db;border-radius:8px;background:#f9fafb;cursor:pointer;transition:all .2s ease;min-height:60px}.cide-file-input-drop-zone:hover{border-color:#3b82f6;background:#f0f9ff}.cide-file-input-drop-zone.cide-file-input-drag-over{border-color:#3b82f6;background:#dbeafe;transform:scale(1.01)}.cide-file-input-drop-zone.cide-file-input-disabled{opacity:.5;cursor:not-allowed}.cide-file-input-drop-zone.cide-file-input-disabled:hover{border-color:#d1d5db;background:#f9fafb;transform:none}.cide-file-input-drop-zone.cide-file-input-has-files{border-color:#10b981;background:#f0fdf4}.cide-file-input-drop-zone.cide-file-input-has-files:hover{border-color:#059669;background:#ecfdf5}.cide-file-input-drop-content{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;gap:12px}.cide-file-input-drop-main{display:flex;align-items:center;gap:10px;flex:1;min-width:0}.cide-file-input-drop-icon{color:#6b7280;transition:color .2s ease;flex-shrink:0}.cide-file-input-drag-over .cide-file-input-drop-icon{color:#3b82f6}.cide-file-input-has-files .cide-file-input-drop-icon{color:#10b981}.cide-file-input-drop-text{display:flex;flex-direction:column;gap:2px;min-width:0}.cide-file-input-drop-title{font-size:14px;font-weight:500;color:#374151;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cide-file-input-drag-over .cide-file-input-drop-title{color:#1d4ed8}.cide-file-input-has-files .cide-file-input-drop-title{color:#065f46}.cide-file-input-drop-subtitle{font-size:12px;color:#6b7280}.cide-file-input-has-files .cide-file-input-drop-subtitle{color:#047857}.cide-file-input-drop-actions{display:flex;gap:4px;flex-shrink:0}.cide-file-input-action-btn{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;border-radius:4px;background:transparent;cursor:pointer;transition:all .2s ease}.cide-file-input-action-btn:hover{background:#0000000d}.cide-file-input-action-btn.cide-file-input-clear-btn{color:#dc2626}.cide-file-input-action-btn.cide-file-input-clear-btn:hover{background:#fef2f2;color:#b91c1c}.cide-file-input-label{display:block;font-size:.875rem;font-weight:500;color:#374151;margin-bottom:.375rem;line-height:1.25}.cide-file-input-required{color:#d32f2f;font-weight:700}.cide-file-input-wrapper{display:flex;align-items:center;gap:.5rem;border:2px dashed transparent;border-radius:.5rem;padding:.5rem;transition:all .2s ease-in-out}.cide-file-input-wrapper.cide-file-input-drag-over{border-color:#3b82f6;background-color:#eff6ff;transform:scale(1.02)}.cide-file-input-element{flex:1}.cide-file-input-clear{background:none;border:none;color:#d32f2f;cursor:pointer;font-size:.9rem}.cide-file-input-files{font-size:.95rem;color:#333;margin-top:.25rem}.cide-file-input-multiple-count{display:inline-flex;align-items:center;gap:.5rem;padding:.5rem 1rem;background-color:#f0f9ff;border:1px solid #0ea5e9;border-radius:.5rem;color:#0369a1;font-weight:500;font-size:.9rem}.cide-file-input-size{margin-top:.5rem;padding:.25rem .5rem;background-color:#f3f4f6;border-radius:.25rem;font-size:.75rem;color:#4b5563;font-weight:500}.cide-file-input-error{color:#d32f2f;font-size:.9rem}.cide-file-input-helper{color:#666;font-size:.9rem}.cide-file-input-preview{margin-top:.75rem;padding:.75rem;background-color:#f8f9fa;border:1px solid #e1e5e9;border-radius:.375rem}.cide-file-input-preview-label{font-weight:500;margin-bottom:.5rem;color:#374151;font-size:.875rem}.cide-file-input-preview-container{display:flex;flex-wrap:wrap;gap:.75rem}.cide-file-input-preview-item{position:relative;display:flex;flex-direction:column;border:1px solid #d1d5db;border-radius:.5rem;overflow:hidden;background-color:#fff;box-shadow:0 1px 3px #0000001a;transition:box-shadow .2s ease-in-out}.cide-file-input-preview-item:hover{box-shadow:0 4px 6px -1px #0000001a}.cide-file-input-preview-image{width:100%;height:calc(100% - 2rem);object-fit:cover;object-position:center;background-color:#f3f4f6}.cide-file-input-preview-filename{padding:.375rem .5rem;background-color:#f9fafbf2;border-top:1px solid #e5e7eb;font-size:.75rem;color:#374151;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-height:2rem;display:flex;align-items:center;justify-content:center}.cide-file-input-preview-remove{position:absolute;top:.25rem;right:.25rem;width:1.5rem;height:1.5rem;background-color:#ef4444e6;color:#fff;border:none;border-radius:50%;font-size:1rem;font-weight:700;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:10;transition:all .2s ease-in-out}.cide-file-input-preview-remove:hover{background-color:#dc2626f2;transform:scale(1.1)}.cide-file-input-preview-remove:focus{outline:2px solid #3b82f6;outline-offset:2px}.cide-file-input-hidden{display:none}.cide-file-input-preview-box-container{display:flex;flex-direction:column;gap:.5rem}.cide-file-input-preview-box{position:relative;border:2px dashed #d1d5db;border-radius:.5rem;cursor:pointer;background-color:#f9fafb;display:flex;align-items:center;justify-content:center;overflow:hidden;transition:all .2s ease-in-out}.cide-file-input-preview-box:hover{border-color:#3b82f6;background-color:#eff6ff}.cide-file-input-preview-box.cide-file-input-preview-box-disabled{cursor:not-allowed;opacity:.6;background-color:#f3f4f6}.cide-file-input-preview-box.cide-file-input-preview-box-disabled:hover{border-color:#d1d5db;background-color:#f3f4f6}.cide-file-input-preview-box.cide-file-input-preview-box-has-image{border-style:solid;border-color:#e5e7eb;padding:0}.cide-file-input-preview-box.cide-file-input-preview-box-has-image:hover{border-color:#3b82f6}.cide-file-input-preview-box.cide-file-input-preview-box-has-image:hover .cide-file-input-preview-box-overlay{opacity:1}.cide-file-input-preview-box.cide-file-input-preview-box-drag-over{border-color:#3b82f6!important;background-color:#eff6ff!important;transform:scale(1.02);box-shadow:0 0 0 4px #3b82f61a}.cide-file-input-preview-box.cide-file-input-preview-box-drag-over .cide-file-input-preview-box-placeholder .cide-file-input-preview-box-icon{color:#3b82f6;transform:scale(1.1)}.cide-file-input-preview-box.cide-file-input-preview-box-drag-over .cide-file-input-preview-box-placeholder .cide-file-input-preview-box-text{color:#3b82f6;font-weight:600}.cide-file-input-preview-box-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;padding:1rem;text-align:center}.cide-file-input-preview-box-icon{font-size:2rem;color:#6b7280}.cide-file-input-preview-box-text{font-size:.875rem;color:#6b7280;font-weight:500}.cide-file-input-preview-box-content{position:relative;width:100%;height:100%;display:flex;align-items:center;justify-content:center}.cide-file-input-preview-box-image{width:100%;height:100%;object-fit:cover;object-position:center}.cide-file-input-preview-box-overlay{position:absolute;inset:0;background-color:#0009;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .2s ease-in-out}.cide-file-input-preview-box-overlay-text{color:#fff;font-size:.875rem;font-weight:500;text-align:center}.cide-file-input-preview-box-remove{position:absolute;top:.375rem;right:.375rem;width:1.5rem;height:1.5rem;background-color:#ef4444e6;color:#fff;border:none;border-radius:50%;font-size:1rem;font-weight:700;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:20;transition:all .2s ease-in-out}.cide-file-input-preview-box-remove:hover{background-color:#dc2626f2;transform:scale(1.1)}.cide-file-input-preview-box-remove:focus{outline:2px solid #3b82f6;outline-offset:2px}.cide-file-input-preview-box-filename{font-size:.75rem;color:#374151;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;padding:.25rem .5rem;background-color:#f3f4f6;border-radius:.25rem;margin-top:.25rem}@media (max-width: 640px){.cide-file-input-preview-container{justify-content:center}.cide-file-input-preview-item{min-width:120px;max-width:150px}.cide-file-input-preview-box-icon{font-size:1.5rem}.cide-file-input-preview-box-text{font-size:.75rem}}.cide-file-input-upload-status{display:flex;align-items:center;justify-content:space-between;padding:.25rem 0;margin-top:.375rem;gap:.5rem}.cide-file-input-upload-status .cide-file-input-upload-count{display:flex;align-items:center;gap:.5rem;color:#64748b;font-size:.875rem;font-weight:500}.cide-file-input-upload-status .cide-file-input-upload-count .upload-count-text{color:#1e293b}.cide-file-input-upload-status .cide-file-input-show-files-icon{display:flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;background:transparent;color:#6b7280;border:none;border-radius:.25rem;cursor:pointer;transition:all .2s ease}.cide-file-input-upload-status .cide-file-input-show-files-icon:hover{background:#f3f4f6;color:#3b82f6}.cide-file-input-upload-status .cide-file-input-show-files-icon:active{background:#e5e7eb}@media (prefers-color-scheme: dark){.cide-file-input-label{color:#f9fafb}.cide-file-input-required{color:#f87171}.cide-file-input-drop-zone{border-color:#475569;background:#334155}.cide-file-input-drop-zone:hover{border-color:#3b82f6;background:#1e3a8a}.cide-file-input-drop-zone.cide-file-input-drag-over{border-color:#60a5fa;background:#1e40af}.cide-file-input-drop-zone.cide-file-input-has-files{border-color:#10b981;background:#064e3b}.cide-file-input-drop-zone.cide-file-input-has-files:hover{border-color:#059669;background:#065f46}.cide-file-input-drop-icon{color:#94a3b8}.cide-file-input-drag-over .cide-file-input-drop-icon{color:#60a5fa}.cide-file-input-has-files .cide-file-input-drop-icon{color:#34d399}.cide-file-input-drop-title{color:#f1f5f9}.cide-file-input-drag-over .cide-file-input-drop-title{color:#93c5fd}.cide-file-input-has-files .cide-file-input-drop-title{color:#6ee7b7}.cide-file-input-drop-subtitle{color:#94a3b8}.cide-file-input-has-files .cide-file-input-drop-subtitle{color:#a7f3d0}.cide-file-input-action-btn:hover{background:#ffffff1a}.cide-file-input-action-btn.cide-file-input-clear-btn{color:#f87171}.cide-file-input-action-btn.cide-file-input-clear-btn:hover{background:#7f1d1d;color:#fca5a5}.cide-file-input-upload-status .cide-file-input-upload-count{color:#94a3b8}.cide-file-input-upload-status .cide-file-input-upload-count .upload-count-text{color:#f1f5f9}.cide-file-input-upload-status .cide-file-input-show-files-icon{color:#94a3b8}.cide-file-input-upload-status .cide-file-input-show-files-icon:hover{background:#374151;color:#60a5fa}.cide-file-input-upload-status .cide-file-input-show-files-icon:active{background:#4b5563}}\n"] }]
|
|
4888
4921
|
}], ctorParameters: () => [], propDecorators: { label: [{
|
|
4889
4922
|
type: Input
|
|
4890
4923
|
}], accept: [{
|