cloud-ide-element 1.0.83 → 1.0.84

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.
@@ -3156,60 +3156,52 @@ class CideEleFloatingFileUploaderComponent {
3156
3156
  isMinimized = signal(false, ...(ngDevMode ? [{ debugName: "isMinimized" }] : []));
3157
3157
  currentUserId = signal('', ...(ngDevMode ? [{ debugName: "currentUserId" }] : []));
3158
3158
  currentGroupId = signal(null, ...(ngDevMode ? [{ debugName: "currentGroupId" }] : []));
3159
- // Local state to maintain completed files visibility
3160
- completedFiles = signal(new Map(), ...(ngDevMode ? [{ debugName: "completedFiles" }] : []));
3159
+ // Local state to maintain all files (pending, active, completed)
3160
+ localFiles = signal(new Map(), ...(ngDevMode ? [{ debugName: "localFiles" }] : []));
3161
3161
  // Use file manager service's upload queue as the single source of truth
3162
3162
  uploadQueue = computed(() => this.fileManagerService.uploadQueue(), ...(ngDevMode ? [{ debugName: "uploadQueue" }] : []));
3163
3163
  activeUploads = computed(() => this.fileManagerService.activeUploads(), ...(ngDevMode ? [{ debugName: "activeUploads" }] : []));
3164
- // Computed values based on file manager service state and local completed files
3165
- hasUploads = computed(() => this.uploadQueue().length > 0 || this.activeUploads().size > 0 || this.completedFiles().size > 0, ...(ngDevMode ? [{ debugName: "hasUploads" }] : []));
3166
- pendingUploads = computed(() => this.uploadQueue().length > 0, ...(ngDevMode ? [{ debugName: "pendingUploads" }] : [])); // All files in queue are pending
3167
- completedUploads = computed(() => {
3168
- const active = this.activeUploads();
3169
- const activeCompleted = Array.from(active.values()).filter(upload => upload.stage === 'complete');
3170
- const localCompleted = Array.from(this.completedFiles().values());
3171
- return [...activeCompleted, ...localCompleted];
3172
- }, ...(ngDevMode ? [{ debugName: "completedUploads" }] : []));
3173
- failedUploads = computed(() => {
3174
- const active = this.activeUploads();
3175
- return Array.from(active.values()).filter(upload => upload.stage === 'error');
3176
- }, ...(ngDevMode ? [{ debugName: "failedUploads" }] : []));
3164
+ // Computed values based on local state only
3165
+ hasUploads = computed(() => this.localFiles().size > 0, ...(ngDevMode ? [{ debugName: "hasUploads" }] : []));
3166
+ pendingUploads = computed(() => Array.from(this.localFiles().values()).filter(file => file.stage === 'pending'), ...(ngDevMode ? [{ debugName: "pendingUploads" }] : []));
3167
+ activeUploadsLocal = computed(() => Array.from(this.localFiles().values()).filter(file => file.stage === 'reading' || file.stage === 'uploading'), ...(ngDevMode ? [{ debugName: "activeUploadsLocal" }] : []));
3168
+ completedUploads = computed(() => Array.from(this.localFiles().values()).filter(file => file.stage === 'complete'), ...(ngDevMode ? [{ debugName: "completedUploads" }] : []));
3169
+ failedUploads = computed(() => Array.from(this.localFiles().values()).filter(file => file.stage === 'error'), ...(ngDevMode ? [{ debugName: "failedUploads" }] : []));
3177
3170
  // Animation states
3178
3171
  isAnimating = signal(false, ...(ngDevMode ? [{ debugName: "isAnimating" }] : []));
3179
3172
  constructor() {
3180
3173
  console.log('🚀 [FloatingFileUploader] Component initialized');
3181
- // Set up effect to monitor file manager service's upload queue
3174
+ // Set up effect to sync files from service to local state
3182
3175
  effect(() => {
3183
3176
  const uploadQueue = this.fileManagerService.uploadQueue();
3184
3177
  const activeUploads = this.fileManagerService.activeUploads();
3185
- const hasUploads = uploadQueue.length > 0 || activeUploads.size > 0 || this.completedFiles().size > 0;
3178
+ const currentLocalFiles = this.localFiles();
3186
3179
  console.log('🔄 [FloatingFileUploader] File manager service queue changed:', {
3187
3180
  queueLength: uploadQueue.length,
3188
3181
  activeUploadsCount: activeUploads.size,
3189
- completedFilesCount: this.completedFiles().size,
3190
- hasUploads,
3191
- currentVisible: this.isVisible(),
3182
+ localFilesCount: currentLocalFiles.size,
3192
3183
  queueFiles: uploadQueue
3193
3184
  });
3194
- // Show floating uploader when files are added to the file manager service queue
3195
- // But don't auto-hide when uploads complete - let user manually close
3196
- if (hasUploads && !this.isVisible()) {
3197
- console.log('👁️ [FloatingFileUploader] Showing floating uploader due to file manager queue');
3198
- this.showWithAnimation();
3199
- }
3200
- // Note: Removed auto-hide logic - floating uploader stays visible until manually closed
3201
- });
3202
- // Set up effect to track completed uploads
3203
- effect(() => {
3204
- const activeUploads = this.fileManagerService.activeUploads();
3205
- const currentCompleted = this.completedFiles();
3206
- // Check for newly completed uploads
3185
+ // Sync pending files from service queue to local state
3186
+ uploadQueue.forEach(fileId => {
3187
+ if (!currentLocalFiles.has(fileId)) {
3188
+ console.log('📝 [FloatingFileUploader] Adding pending file to local state:', fileId);
3189
+ this.addLocalFile(fileId, 'pending');
3190
+ }
3191
+ });
3192
+ // Sync active uploads from service to local state
3207
3193
  activeUploads.forEach((upload, fileId) => {
3208
- if (upload.stage === 'complete' && !currentCompleted.has(fileId)) {
3209
- console.log('✅ [FloatingFileUploader] File completed, adding to local completed files:', fileId);
3210
- this.addCompletedFile(fileId, upload);
3194
+ const localFile = currentLocalFiles.get(fileId);
3195
+ if (!localFile || localFile.stage !== upload.stage) {
3196
+ console.log('🔄 [FloatingFileUploader] Updating local file state:', fileId, upload.stage);
3197
+ this.updateLocalFile(fileId, upload.stage, upload.percentage);
3211
3198
  }
3212
3199
  });
3200
+ // Show floating uploader when files are added
3201
+ if (this.localFiles().size > 0 && !this.isVisible()) {
3202
+ console.log('👁️ [FloatingFileUploader] Showing floating uploader due to local files');
3203
+ this.showWithAnimation();
3204
+ }
3213
3205
  });
3214
3206
  }
3215
3207
  ngOnInit() {
@@ -3358,29 +3350,29 @@ class CideEleFloatingFileUploaderComponent {
3358
3350
  * Close the floating uploader
3359
3351
  */
3360
3352
  close() {
3361
- // Clear completed files when closing
3362
- this.clearCompletedFiles();
3353
+ // Clear all local files when closing
3354
+ this.clearLocalFiles();
3363
3355
  this.hideWithAnimation();
3364
3356
  }
3365
3357
  /**
3366
3358
  * Get upload summary text
3367
3359
  */
3368
3360
  getUploadSummary() {
3369
- const queueLength = this.uploadQueue().length;
3370
- const activeCount = this.activeUploads().size;
3371
- const completed = this.completedUploads().length;
3372
- const failed = this.failedUploads().length;
3373
- if (activeCount > 0) {
3374
- return `${activeCount} uploading`;
3361
+ const pending = this.pendingUploads();
3362
+ const active = this.activeUploadsLocal();
3363
+ const completed = this.completedUploads();
3364
+ const failed = this.failedUploads();
3365
+ if (active.length > 0) {
3366
+ return `${active.length} uploading`;
3375
3367
  }
3376
- else if (completed > 0 && failed === 0) {
3377
- return `${completed} completed`;
3368
+ else if (completed.length > 0 && failed.length === 0) {
3369
+ return `${completed.length} completed`;
3378
3370
  }
3379
- else if (failed > 0) {
3380
- return `${completed} completed, ${failed} failed`;
3371
+ else if (failed.length > 0) {
3372
+ return `${completed.length} completed, ${failed.length} failed`;
3381
3373
  }
3382
- else if (queueLength > 0) {
3383
- return `${queueLength} pending`;
3374
+ else if (pending.length > 0) {
3375
+ return `${pending.length} pending`;
3384
3376
  }
3385
3377
  return 'No uploads';
3386
3378
  }
@@ -3388,11 +3380,11 @@ class CideEleFloatingFileUploaderComponent {
3388
3380
  * Get overall progress percentage
3389
3381
  */
3390
3382
  getOverallProgress() {
3391
- const activeUploads = this.activeUploads();
3392
- if (activeUploads.size === 0)
3383
+ const active = this.activeUploadsLocal();
3384
+ if (active.length === 0)
3393
3385
  return 0;
3394
- const totalProgress = Array.from(activeUploads.values()).reduce((sum, upload) => sum + upload.percentage, 0);
3395
- return Math.round(totalProgress / activeUploads.size);
3386
+ const totalProgress = active.reduce((sum, file) => sum + (file.percentage || 0), 0);
3387
+ return Math.round(totalProgress / active.length);
3396
3388
  }
3397
3389
  /**
3398
3390
  * Get status icon based on upload stage
@@ -3438,25 +3430,49 @@ class CideEleFloatingFileUploaderComponent {
3438
3430
  return fileId;
3439
3431
  }
3440
3432
  /**
3441
- * Add completed file to local state
3433
+ * Add file to local state
3442
3434
  */
3443
- addCompletedFile(fileId, upload) {
3435
+ addLocalFile(fileId, stage, percentage) {
3444
3436
  const fileName = this.getFileNameFromId(fileId);
3445
- this.completedFiles.update(completed => {
3446
- const newCompleted = new Map(completed);
3447
- newCompleted.set(fileId, {
3437
+ this.localFiles.update(files => {
3438
+ const newFiles = new Map(files);
3439
+ newFiles.set(fileId, {
3448
3440
  fileName,
3449
- completedAt: new Date(),
3441
+ stage,
3442
+ percentage,
3443
+ completedAt: stage === 'complete' ? new Date() : undefined,
3450
3444
  groupId: this.currentGroupId() || undefined
3451
3445
  });
3452
- return newCompleted;
3446
+ return newFiles;
3447
+ });
3448
+ }
3449
+ /**
3450
+ * Update local file state
3451
+ */
3452
+ updateLocalFile(fileId, stage, percentage) {
3453
+ this.localFiles.update(files => {
3454
+ const newFiles = new Map(files);
3455
+ const existingFile = newFiles.get(fileId);
3456
+ if (existingFile) {
3457
+ newFiles.set(fileId, {
3458
+ ...existingFile,
3459
+ stage,
3460
+ percentage,
3461
+ completedAt: stage === 'complete' ? new Date() : existingFile.completedAt
3462
+ });
3463
+ }
3464
+ else {
3465
+ // If file doesn't exist locally, add it
3466
+ this.addLocalFile(fileId, stage, percentage);
3467
+ }
3468
+ return newFiles;
3453
3469
  });
3454
3470
  }
3455
3471
  /**
3456
- * Clear all completed files
3472
+ * Clear all local files
3457
3473
  */
3458
- clearCompletedFiles() {
3459
- this.completedFiles.set(new Map());
3474
+ clearLocalFiles() {
3475
+ this.localFiles.set(new Map());
3460
3476
  }
3461
3477
  /**
3462
3478
  * Set current user ID
@@ -3525,14 +3541,14 @@ class CideEleFloatingFileUploaderComponent {
3525
3541
  return this.hasUploads();
3526
3542
  }
3527
3543
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingFileUploaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3528
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideEleFloatingFileUploaderComponent, isStandalone: true, selector: "cide-ele-floating-file-uploader", ngImport: i0, template: "<!-- Floating File Uploader Container -->\r\n@if (isVisible()) {\r\n<div class=\"floating-uploader\" \r\n [class.minimized]=\"isMinimized()\" \r\n [class.animating]=\"isAnimating()\">\r\n\r\n <!-- Header -->\r\n <div class=\"uploader-header\">\r\n <div class=\"header-left\">\r\n <div class=\"upload-icon\">\r\n <cide-ele-icon size=\"sm\">cloud_upload</cide-ele-icon>\r\n </div>\r\n <div class=\"upload-info\">\r\n <div class=\"upload-title\">File Upload</div>\r\n <div class=\"upload-summary\">{{ getUploadSummary() }}</div>\r\n </div>\r\n </div>\r\n \r\n <div class=\"header-actions\">\r\n <button class=\"action-btn minimize-btn\" (click)=\"toggleMinimize()\" [title]=\"isMinimized() ? 'Expand' : 'Minimize'\">\r\n <cide-ele-icon size=\"xs\">{{ isMinimized() ? 'expand_more' : 'expand_less' }}</cide-ele-icon>\r\n </button>\r\n <button class=\"action-btn close-btn\" (click)=\"close()\" title=\"Close\">\r\n <cide-ele-icon size=\"xs\">close</cide-ele-icon>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Content (hidden when minimized) -->\r\n @if (!isMinimized()) {\r\n <div class=\"uploader-content\">\r\n \r\n <!-- Overall Progress Bar -->\r\n @if (uploadQueue().length > 0 || activeUploads().size > 0) {\r\n <div class=\"overall-progress\">\r\n <div class=\"progress-bar\">\r\n <div class=\"progress-fill\" [style.width.%]=\"getOverallProgress()\"></div>\r\n </div>\r\n <div class=\"progress-text\">{{ getOverallProgress() }}%</div>\r\n </div>\r\n }\r\n\r\n <!-- Upload Queue - Show files from file manager service -->\r\n @if (uploadQueue().length > 0 || activeUploads().size > 0 || completedFiles().size > 0) {\r\n <div class=\"upload-queue\">\r\n <!-- Show files in queue (pending) -->\r\n @for (fileId of uploadQueue(); track fileId) {\r\n <div class=\"upload-item status-pending\">\r\n <div class=\"file-info\">\r\n <cide-ele-icon class=\"status-icon\" size=\"xs\">schedule</cide-ele-icon>\r\n <div class=\"file-details\">\r\n <div class=\"file-name\">{{ getFileNameFromId(fileId) }}</div>\r\n <div class=\"file-status\">\r\n <span class=\"text-yellow-600\">Waiting...</span>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"upload-actions\">\r\n <button class=\"action-btn cancel-btn\" (click)=\"cancelUpload(fileId)\" title=\"Cancel\">\r\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n \r\n <!-- Show active uploads -->\r\n @for (entry of activeUploads() | keyvalue; track entry.key) {\r\n <div class=\"upload-item\" [class]=\"getStatusClass(entry.value.stage)\">\r\n <div class=\"file-info\">\r\n <cide-ele-icon class=\"status-icon\" size=\"xs\">{{ getStatusIcon(entry.value.stage) }}</cide-ele-icon>\r\n <div class=\"file-details\">\r\n <div class=\"file-name\">{{ getFileNameFromId(entry.key) }}</div>\r\n <div class=\"file-status\">\r\n @switch (entry.value.stage) {\r\n @case ('reading') {\r\n <span class=\"text-yellow-600\">Reading...</span>\r\n }\r\n @case ('uploading') {\r\n <span class=\"text-blue-600\">Uploading...</span>\r\n }\r\n @case ('complete') {\r\n <span class=\"text-green-600\">Completed</span>\r\n }\r\n @case ('error') {\r\n <span class=\"text-red-600\">Failed</span>\r\n }\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Progress Bar (for uploading files) -->\r\n @if (entry.value.stage === 'uploading') {\r\n <div class=\"file-progress\">\r\n <div class=\"progress-bar\">\r\n <div class=\"progress-fill\" [style.width.%]=\"entry.value.percentage\"></div>\r\n </div>\r\n <span class=\"progress-text\">{{ entry.value.percentage }}%</span>\r\n </div>\r\n }\r\n\r\n <!-- Actions -->\r\n <div class=\"upload-actions\">\r\n @switch (entry.value.stage) {\r\n @case ('reading') {\r\n <button class=\"action-btn cancel-btn\" (click)=\"cancelUpload(entry.key)\" title=\"Cancel\">\r\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\r\n </button>\r\n }\r\n @case ('uploading') {\r\n <button class=\"action-btn cancel-btn\" (click)=\"cancelUpload(entry.key)\" title=\"Cancel\">\r\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\r\n </button>\r\n }\r\n @case ('complete') {\r\n <button class=\"action-btn success-btn\" title=\"Completed\">\r\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\r\n </button>\r\n }\r\n @case ('error') {\r\n <button class=\"action-btn retry-btn\" title=\"Retry\">\r\n <cide-ele-icon size=\"xs\">refresh</cide-ele-icon>\r\n </button>\r\n }\r\n }\r\n </div>\r\n </div>\r\n }\r\n \r\n <!-- Show completed files from local state -->\r\n @for (entry of completedFiles() | keyvalue; track entry.key) {\r\n <div class=\"upload-item status-completed\">\r\n <div class=\"file-info\">\r\n <cide-ele-icon class=\"status-icon\" size=\"xs\">check_circle</cide-ele-icon>\r\n <div class=\"file-details\">\r\n <div class=\"file-name\">{{ entry.value.fileName }}</div>\r\n <div class=\"file-status\">\r\n <span class=\"text-green-600\">Completed</span>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"upload-actions\">\r\n <button class=\"action-btn success-btn\" title=\"Completed\">\r\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n <!-- No uploads message when manually opened -->\r\n <div class=\"no-uploads-message\">\r\n <div class=\"message-content\">\r\n <cide-ele-icon size=\"md\" class=\"message-icon\">cloud_upload</cide-ele-icon>\r\n <div class=\"message-text\">\r\n <h4>No active uploads</h4>\r\n <p>Upload files to see their progress here</p>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n}\r\n", styles: [".floating-uploader{position:fixed;bottom:20px;right:20px;width:320px;max-height:500px;background:#fff;border-radius:12px;box-shadow:0 8px 32px #0000001f;border:1px solid rgba(0,0,0,.08);z-index:1000;overflow:hidden;transition:all .3s cubic-bezier(.4,0,.2,1);transform:translateY(0);opacity:1}.floating-uploader.animating{transition:all .3s cubic-bezier(.4,0,.2,1)}.floating-uploader.minimized .uploader-content{display:none}.floating-uploader.minimized .uploader-footer{border-top:none}.floating-uploader.uploading{border-color:#3b82f6;box-shadow:0 8px 32px #3b82f626}.floating-uploader .uploader-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;background:#f8fafc;border-bottom:1px solid #e2e8f0}.floating-uploader .uploader-header .header-left{display:flex;align-items:center;gap:8px}.floating-uploader .uploader-header .header-left .upload-icon{display:flex;align-items:center;justify-content:center;width:24px;height:24px;background:#3b82f6;border-radius:6px;color:#fff}.floating-uploader .uploader-header .header-left .upload-info .upload-title{font-size:14px;font-weight:600;color:#1e293b;margin:0}.floating-uploader .uploader-header .header-left .upload-info .upload-summary{font-size:12px;color:#64748b;margin:0}.floating-uploader .uploader-header .header-actions{display:flex;gap:4px}.floating-uploader .uploader-header .header-actions .action-btn{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;background:transparent;border-radius:4px;cursor:pointer;transition:background-color .2s;color:#64748b}.floating-uploader .uploader-header .header-actions .action-btn:hover{background:#e2e8f0;color:#1e293b}.floating-uploader .uploader-header .header-actions .action-btn.close-btn:hover{background:#fef2f2;color:#dc2626}.floating-uploader .uploader-content{max-height:400px;overflow-y:auto}.floating-uploader .uploader-content .overall-progress{padding:12px 16px;border-bottom:1px solid #e2e8f0}.floating-uploader .uploader-content .overall-progress .progress-bar{width:100%;height:4px;background:#e2e8f0;border-radius:2px;overflow:hidden;margin-bottom:4px}.floating-uploader .uploader-content .overall-progress .progress-bar .progress-fill{height:100%;background:#3b82f6;transition:width .3s ease}.floating-uploader .uploader-content .overall-progress .progress-text{font-size:12px;color:#64748b;text-align:center;display:block}.floating-uploader .uploader-content .upload-queue .upload-item{display:flex;align-items:center;padding:8px 16px;border-bottom:1px solid #f1f5f9;transition:background-color .2s}.floating-uploader .uploader-content .upload-queue .upload-item:last-child{border-bottom:none}.floating-uploader .uploader-content .upload-queue .upload-item.status-uploading{background:#f0f9ff}.floating-uploader .uploader-content .upload-queue .upload-item.status-completed{background:#f0fdf4}.floating-uploader .uploader-content .upload-queue .upload-item.status-error{background:#fef2f2}.floating-uploader .uploader-content .upload-queue .upload-item .file-info{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .status-icon{flex-shrink:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details{min-width:0;flex:1}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-name{font-size:13px;font-weight:500;color:#1e293b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-status{font-size:11px;margin:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-status span{font-weight:500}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress{display:flex;align-items:center;gap:8px;margin:0 8px;min-width:80px}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar{flex:1;height:3px;background:#e2e8f0;border-radius:2px;overflow:hidden}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar .progress-fill{height:100%;background:#3b82f6;transition:width .3s ease}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-text{font-size:10px;color:#64748b;min-width:24px;text-align:right}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions{display:flex;gap:4px}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn{display:flex;align-items:center;justify-content:center;width:20px;height:20px;border:none;background:transparent;border-radius:4px;cursor:pointer;transition:all .2s;color:#64748b}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn:hover{background:#e2e8f0}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.cancel-btn:hover{background:#fef2f2;color:#dc2626}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.retry-btn:hover{background:#f0f9ff;color:#3b82f6}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.success-btn{color:#16a34a}.floating-uploader .uploader-content .hidden-uploader{display:none}.floating-uploader .uploader-footer{padding:8px 16px;background:#f8fafc;border-top:1px solid #e2e8f0}.floating-uploader .uploader-footer .footer-stats{display:flex;gap:12px;font-size:11px}.floating-uploader .uploader-footer .footer-stats .stat{display:flex;align-items:center;gap:4px;color:#64748b}.floating-uploader .uploader-footer .footer-stats .stat.uploading{color:#3b82f6}.floating-uploader .uploader-footer .footer-stats .stat.completed{color:#16a34a}.floating-uploader .uploader-footer .footer-stats .stat.failed{color:#dc2626}@media (max-width: 640px){.floating-uploader{bottom:10px;right:10px;left:10px;width:auto;max-width:none}}@media (prefers-color-scheme: dark){.floating-uploader{background:#1e293b;border-color:#334155;box-shadow:0 8px 32px #0000004d}.floating-uploader.uploading{border-color:#3b82f6;box-shadow:0 8px 32px #3b82f633}.floating-uploader .uploader-header{background:#334155;border-bottom-color:#475569}.floating-uploader .uploader-header .header-left .upload-icon{background:#3b82f6}.floating-uploader .uploader-header .header-left .upload-info .upload-title{color:#f1f5f9}.floating-uploader .uploader-header .header-left .upload-info .upload-summary,.floating-uploader .uploader-header .header-actions .action-btn{color:#94a3b8}.floating-uploader .uploader-header .header-actions .action-btn:hover{background:#475569;color:#f1f5f9}.floating-uploader .uploader-header .header-actions .action-btn.close-btn:hover{background:#7f1d1d;color:#fca5a5}.floating-uploader .uploader-content .overall-progress{border-bottom-color:#475569}.floating-uploader .uploader-content .overall-progress .progress-bar{background:#475569}.floating-uploader .uploader-content .overall-progress .progress-bar .progress-fill{background:#3b82f6}.floating-uploader .uploader-content .overall-progress .progress-text{color:#94a3b8}.floating-uploader .uploader-content .upload-queue .upload-item{border-bottom-color:#334155}.floating-uploader .uploader-content .upload-queue .upload-item.status-uploading{background:#1e3a8a}.floating-uploader .uploader-content .upload-queue .upload-item.status-completed{background:#14532d}.floating-uploader .uploader-content .upload-queue .upload-item.status-error{background:#7f1d1d}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-name{color:#f1f5f9}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar{background:#475569}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar .progress-fill{background:#3b82f6}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-text,.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn{color:#94a3b8}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn:hover{background:#475569}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.cancel-btn:hover{background:#7f1d1d;color:#fca5a5}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.retry-btn:hover{background:#1e3a8a;color:#60a5fa}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.success-btn{color:#4ade80}.floating-uploader .uploader-footer{background:#334155;border-top-color:#475569}.floating-uploader .uploader-footer .footer-stats .stat{color:#94a3b8}.floating-uploader .uploader-footer .footer-stats .stat.uploading{color:#60a5fa}.floating-uploader .uploader-footer .footer-stats .stat.completed{color:#4ade80}.floating-uploader .uploader-footer .footer-stats .stat.failed{color:#fca5a5}}@keyframes slideInUp{0%{transform:translateY(100%);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes slideOutDown{0%{transform:translateY(0);opacity:1}to{transform:translateY(100%);opacity:0}}.floating-uploader.animating{animation:slideInUp .3s cubic-bezier(.4,0,.2,1)}.floating-uploader.animating.hiding{animation:slideOutDown .3s cubic-bezier(.4,0,.2,1)}.no-uploads-message{padding:2rem;text-align:center;color:#6b7280}.no-uploads-message .message-content{display:flex;flex-direction:column;align-items:center;gap:1rem}.no-uploads-message .message-content .message-icon{color:#9ca3af;opacity:.7}.no-uploads-message .message-content .message-text h4{margin:0 0 .5rem;font-size:1.1rem;font-weight:600;color:#374151}.no-uploads-message .message-content .message-text p{margin:0;font-size:.9rem;color:#6b7280}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "pipe", type: i1.KeyValuePipe, name: "keyvalue" }] });
3544
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideEleFloatingFileUploaderComponent, isStandalone: true, selector: "cide-ele-floating-file-uploader", ngImport: i0, template: "<!-- Floating File Uploader Container -->\r\n@if (isVisible()) {\r\n<div class=\"floating-uploader\" \r\n [class.minimized]=\"isMinimized()\" \r\n [class.animating]=\"isAnimating()\">\r\n\r\n <!-- Header -->\r\n <div class=\"uploader-header\">\r\n <div class=\"header-left\">\r\n <div class=\"upload-icon\">\r\n <cide-ele-icon size=\"sm\">cloud_upload</cide-ele-icon>\r\n </div>\r\n <div class=\"upload-info\">\r\n <div class=\"upload-title\">File Upload</div>\r\n <div class=\"upload-summary\">{{ getUploadSummary() }}</div>\r\n </div>\r\n </div>\r\n \r\n <div class=\"header-actions\">\r\n <button class=\"action-btn minimize-btn\" (click)=\"toggleMinimize()\" [title]=\"isMinimized() ? 'Expand' : 'Minimize'\">\r\n <cide-ele-icon size=\"xs\">{{ isMinimized() ? 'expand_more' : 'expand_less' }}</cide-ele-icon>\r\n </button>\r\n <button class=\"action-btn close-btn\" (click)=\"close()\" title=\"Close\">\r\n <cide-ele-icon size=\"xs\">close</cide-ele-icon>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Content (hidden when minimized) -->\r\n @if (!isMinimized()) {\r\n <div class=\"uploader-content\">\r\n \r\n <!-- Overall Progress Bar -->\r\n @if (uploadQueue().length > 0 || activeUploads().size > 0) {\r\n <div class=\"overall-progress\">\r\n <div class=\"progress-bar\">\r\n <div class=\"progress-fill\" [style.width.%]=\"getOverallProgress()\"></div>\r\n </div>\r\n <div class=\"progress-text\">{{ getOverallProgress() }}%</div>\r\n </div>\r\n }\r\n\r\n <!-- Upload Queue - Show files from local state -->\r\n @if (localFiles().size > 0) {\r\n <div class=\"upload-queue\">\r\n <!-- Show all files from local state -->\r\n @for (entry of localFiles() | keyvalue; track entry.key) {\r\n <div class=\"upload-item\" [class]=\"getStatusClass(entry.value.stage)\">\r\n <div class=\"file-info\">\r\n <cide-ele-icon class=\"status-icon\" size=\"xs\">{{ getStatusIcon(entry.value.stage) }}</cide-ele-icon>\r\n <div class=\"file-details\">\r\n <div class=\"file-name\">{{ entry.value.fileName }}</div>\r\n <div class=\"file-status\">\r\n @switch (entry.value.stage) {\r\n @case ('pending') {\r\n <span class=\"text-yellow-600\">Waiting...</span>\r\n }\r\n @case ('reading') {\r\n <span class=\"text-yellow-600\">Reading...</span>\r\n }\r\n @case ('uploading') {\r\n <span class=\"text-blue-600\">Uploading...</span>\r\n }\r\n @case ('complete') {\r\n <span class=\"text-green-600\">Completed</span>\r\n }\r\n @case ('error') {\r\n <span class=\"text-red-600\">Failed</span>\r\n }\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Progress Bar (for uploading files) -->\r\n @if (entry.value.stage === 'uploading' && entry.value.percentage !== undefined) {\r\n <div class=\"file-progress\">\r\n <div class=\"progress-bar\">\r\n <div class=\"progress-fill\" [style.width.%]=\"entry.value.percentage\"></div>\r\n </div>\r\n <span class=\"progress-text\">{{ entry.value.percentage }}%</span>\r\n </div>\r\n }\r\n\r\n <!-- Actions -->\r\n <div class=\"upload-actions\">\r\n @switch (entry.value.stage) {\r\n @case ('pending') {\r\n <button class=\"action-btn cancel-btn\" (click)=\"cancelUpload(entry.key)\" title=\"Cancel\">\r\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\r\n </button>\r\n }\r\n @case ('reading') {\r\n <button class=\"action-btn cancel-btn\" (click)=\"cancelUpload(entry.key)\" title=\"Cancel\">\r\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\r\n </button>\r\n }\r\n @case ('uploading') {\r\n <button class=\"action-btn cancel-btn\" (click)=\"cancelUpload(entry.key)\" title=\"Cancel\">\r\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\r\n </button>\r\n }\r\n @case ('complete') {\r\n <button class=\"action-btn success-btn\" title=\"Completed\">\r\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\r\n </button>\r\n }\r\n @case ('error') {\r\n <button class=\"action-btn retry-btn\" title=\"Retry\">\r\n <cide-ele-icon size=\"xs\">refresh</cide-ele-icon>\r\n </button>\r\n }\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n <!-- No uploads message when manually opened -->\r\n <div class=\"no-uploads-message\">\r\n <div class=\"message-content\">\r\n <cide-ele-icon size=\"md\" class=\"message-icon\">cloud_upload</cide-ele-icon>\r\n <div class=\"message-text\">\r\n <h4>No active uploads</h4>\r\n <p>Upload files to see their progress here</p>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n}\r\n", styles: [".floating-uploader{position:fixed;bottom:20px;right:20px;width:320px;max-height:500px;background:#fff;border-radius:12px;box-shadow:0 8px 32px #0000001f;border:1px solid rgba(0,0,0,.08);z-index:1000;overflow:hidden;transition:all .3s cubic-bezier(.4,0,.2,1);transform:translateY(0);opacity:1}.floating-uploader.animating{transition:all .3s cubic-bezier(.4,0,.2,1)}.floating-uploader.minimized .uploader-content{display:none}.floating-uploader.minimized .uploader-footer{border-top:none}.floating-uploader.uploading{border-color:#3b82f6;box-shadow:0 8px 32px #3b82f626}.floating-uploader .uploader-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;background:#f8fafc;border-bottom:1px solid #e2e8f0}.floating-uploader .uploader-header .header-left{display:flex;align-items:center;gap:8px}.floating-uploader .uploader-header .header-left .upload-icon{display:flex;align-items:center;justify-content:center;width:24px;height:24px;background:#3b82f6;border-radius:6px;color:#fff}.floating-uploader .uploader-header .header-left .upload-info .upload-title{font-size:14px;font-weight:600;color:#1e293b;margin:0}.floating-uploader .uploader-header .header-left .upload-info .upload-summary{font-size:12px;color:#64748b;margin:0}.floating-uploader .uploader-header .header-actions{display:flex;gap:4px}.floating-uploader .uploader-header .header-actions .action-btn{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;background:transparent;border-radius:4px;cursor:pointer;transition:background-color .2s;color:#64748b}.floating-uploader .uploader-header .header-actions .action-btn:hover{background:#e2e8f0;color:#1e293b}.floating-uploader .uploader-header .header-actions .action-btn.close-btn:hover{background:#fef2f2;color:#dc2626}.floating-uploader .uploader-content{max-height:400px;overflow-y:auto}.floating-uploader .uploader-content .overall-progress{padding:12px 16px;border-bottom:1px solid #e2e8f0}.floating-uploader .uploader-content .overall-progress .progress-bar{width:100%;height:4px;background:#e2e8f0;border-radius:2px;overflow:hidden;margin-bottom:4px}.floating-uploader .uploader-content .overall-progress .progress-bar .progress-fill{height:100%;background:#3b82f6;transition:width .3s ease}.floating-uploader .uploader-content .overall-progress .progress-text{font-size:12px;color:#64748b;text-align:center;display:block}.floating-uploader .uploader-content .upload-queue .upload-item{display:flex;align-items:center;padding:8px 16px;border-bottom:1px solid #f1f5f9;transition:background-color .2s}.floating-uploader .uploader-content .upload-queue .upload-item:last-child{border-bottom:none}.floating-uploader .uploader-content .upload-queue .upload-item.status-uploading{background:#f0f9ff}.floating-uploader .uploader-content .upload-queue .upload-item.status-completed{background:#f0fdf4}.floating-uploader .uploader-content .upload-queue .upload-item.status-error{background:#fef2f2}.floating-uploader .uploader-content .upload-queue .upload-item .file-info{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .status-icon{flex-shrink:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details{min-width:0;flex:1}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-name{font-size:13px;font-weight:500;color:#1e293b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-status{font-size:11px;margin:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-status span{font-weight:500}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress{display:flex;align-items:center;gap:8px;margin:0 8px;min-width:80px}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar{flex:1;height:3px;background:#e2e8f0;border-radius:2px;overflow:hidden}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar .progress-fill{height:100%;background:#3b82f6;transition:width .3s ease}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-text{font-size:10px;color:#64748b;min-width:24px;text-align:right}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions{display:flex;gap:4px}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn{display:flex;align-items:center;justify-content:center;width:20px;height:20px;border:none;background:transparent;border-radius:4px;cursor:pointer;transition:all .2s;color:#64748b}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn:hover{background:#e2e8f0}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.cancel-btn:hover{background:#fef2f2;color:#dc2626}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.retry-btn:hover{background:#f0f9ff;color:#3b82f6}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.success-btn{color:#16a34a}.floating-uploader .uploader-content .hidden-uploader{display:none}.floating-uploader .uploader-footer{padding:8px 16px;background:#f8fafc;border-top:1px solid #e2e8f0}.floating-uploader .uploader-footer .footer-stats{display:flex;gap:12px;font-size:11px}.floating-uploader .uploader-footer .footer-stats .stat{display:flex;align-items:center;gap:4px;color:#64748b}.floating-uploader .uploader-footer .footer-stats .stat.uploading{color:#3b82f6}.floating-uploader .uploader-footer .footer-stats .stat.completed{color:#16a34a}.floating-uploader .uploader-footer .footer-stats .stat.failed{color:#dc2626}@media (max-width: 640px){.floating-uploader{bottom:10px;right:10px;left:10px;width:auto;max-width:none}}@media (prefers-color-scheme: dark){.floating-uploader{background:#1e293b;border-color:#334155;box-shadow:0 8px 32px #0000004d}.floating-uploader.uploading{border-color:#3b82f6;box-shadow:0 8px 32px #3b82f633}.floating-uploader .uploader-header{background:#334155;border-bottom-color:#475569}.floating-uploader .uploader-header .header-left .upload-icon{background:#3b82f6}.floating-uploader .uploader-header .header-left .upload-info .upload-title{color:#f1f5f9}.floating-uploader .uploader-header .header-left .upload-info .upload-summary,.floating-uploader .uploader-header .header-actions .action-btn{color:#94a3b8}.floating-uploader .uploader-header .header-actions .action-btn:hover{background:#475569;color:#f1f5f9}.floating-uploader .uploader-header .header-actions .action-btn.close-btn:hover{background:#7f1d1d;color:#fca5a5}.floating-uploader .uploader-content .overall-progress{border-bottom-color:#475569}.floating-uploader .uploader-content .overall-progress .progress-bar{background:#475569}.floating-uploader .uploader-content .overall-progress .progress-bar .progress-fill{background:#3b82f6}.floating-uploader .uploader-content .overall-progress .progress-text{color:#94a3b8}.floating-uploader .uploader-content .upload-queue .upload-item{border-bottom-color:#334155}.floating-uploader .uploader-content .upload-queue .upload-item.status-uploading{background:#1e3a8a}.floating-uploader .uploader-content .upload-queue .upload-item.status-completed{background:#14532d}.floating-uploader .uploader-content .upload-queue .upload-item.status-error{background:#7f1d1d}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-name{color:#f1f5f9}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar{background:#475569}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar .progress-fill{background:#3b82f6}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-text,.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn{color:#94a3b8}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn:hover{background:#475569}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.cancel-btn:hover{background:#7f1d1d;color:#fca5a5}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.retry-btn:hover{background:#1e3a8a;color:#60a5fa}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.success-btn{color:#4ade80}.floating-uploader .uploader-footer{background:#334155;border-top-color:#475569}.floating-uploader .uploader-footer .footer-stats .stat{color:#94a3b8}.floating-uploader .uploader-footer .footer-stats .stat.uploading{color:#60a5fa}.floating-uploader .uploader-footer .footer-stats .stat.completed{color:#4ade80}.floating-uploader .uploader-footer .footer-stats .stat.failed{color:#fca5a5}}@keyframes slideInUp{0%{transform:translateY(100%);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes slideOutDown{0%{transform:translateY(0);opacity:1}to{transform:translateY(100%);opacity:0}}.floating-uploader.animating{animation:slideInUp .3s cubic-bezier(.4,0,.2,1)}.floating-uploader.animating.hiding{animation:slideOutDown .3s cubic-bezier(.4,0,.2,1)}.no-uploads-message{padding:2rem;text-align:center;color:#6b7280}.no-uploads-message .message-content{display:flex;flex-direction:column;align-items:center;gap:1rem}.no-uploads-message .message-content .message-icon{color:#9ca3af;opacity:.7}.no-uploads-message .message-content .message-text h4{margin:0 0 .5rem;font-size:1.1rem;font-weight:600;color:#374151}.no-uploads-message .message-content .message-text p{margin:0;font-size:.9rem;color:#6b7280}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "pipe", type: i1.KeyValuePipe, name: "keyvalue" }] });
3529
3545
  }
3530
3546
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingFileUploaderComponent, decorators: [{
3531
3547
  type: Component,
3532
3548
  args: [{ selector: 'cide-ele-floating-file-uploader', standalone: true, imports: [
3533
3549
  CommonModule,
3534
3550
  CideIconComponent
3535
- ], template: "<!-- Floating File Uploader Container -->\r\n@if (isVisible()) {\r\n<div class=\"floating-uploader\" \r\n [class.minimized]=\"isMinimized()\" \r\n [class.animating]=\"isAnimating()\">\r\n\r\n <!-- Header -->\r\n <div class=\"uploader-header\">\r\n <div class=\"header-left\">\r\n <div class=\"upload-icon\">\r\n <cide-ele-icon size=\"sm\">cloud_upload</cide-ele-icon>\r\n </div>\r\n <div class=\"upload-info\">\r\n <div class=\"upload-title\">File Upload</div>\r\n <div class=\"upload-summary\">{{ getUploadSummary() }}</div>\r\n </div>\r\n </div>\r\n \r\n <div class=\"header-actions\">\r\n <button class=\"action-btn minimize-btn\" (click)=\"toggleMinimize()\" [title]=\"isMinimized() ? 'Expand' : 'Minimize'\">\r\n <cide-ele-icon size=\"xs\">{{ isMinimized() ? 'expand_more' : 'expand_less' }}</cide-ele-icon>\r\n </button>\r\n <button class=\"action-btn close-btn\" (click)=\"close()\" title=\"Close\">\r\n <cide-ele-icon size=\"xs\">close</cide-ele-icon>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Content (hidden when minimized) -->\r\n @if (!isMinimized()) {\r\n <div class=\"uploader-content\">\r\n \r\n <!-- Overall Progress Bar -->\r\n @if (uploadQueue().length > 0 || activeUploads().size > 0) {\r\n <div class=\"overall-progress\">\r\n <div class=\"progress-bar\">\r\n <div class=\"progress-fill\" [style.width.%]=\"getOverallProgress()\"></div>\r\n </div>\r\n <div class=\"progress-text\">{{ getOverallProgress() }}%</div>\r\n </div>\r\n }\r\n\r\n <!-- Upload Queue - Show files from file manager service -->\r\n @if (uploadQueue().length > 0 || activeUploads().size > 0 || completedFiles().size > 0) {\r\n <div class=\"upload-queue\">\r\n <!-- Show files in queue (pending) -->\r\n @for (fileId of uploadQueue(); track fileId) {\r\n <div class=\"upload-item status-pending\">\r\n <div class=\"file-info\">\r\n <cide-ele-icon class=\"status-icon\" size=\"xs\">schedule</cide-ele-icon>\r\n <div class=\"file-details\">\r\n <div class=\"file-name\">{{ getFileNameFromId(fileId) }}</div>\r\n <div class=\"file-status\">\r\n <span class=\"text-yellow-600\">Waiting...</span>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"upload-actions\">\r\n <button class=\"action-btn cancel-btn\" (click)=\"cancelUpload(fileId)\" title=\"Cancel\">\r\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n \r\n <!-- Show active uploads -->\r\n @for (entry of activeUploads() | keyvalue; track entry.key) {\r\n <div class=\"upload-item\" [class]=\"getStatusClass(entry.value.stage)\">\r\n <div class=\"file-info\">\r\n <cide-ele-icon class=\"status-icon\" size=\"xs\">{{ getStatusIcon(entry.value.stage) }}</cide-ele-icon>\r\n <div class=\"file-details\">\r\n <div class=\"file-name\">{{ getFileNameFromId(entry.key) }}</div>\r\n <div class=\"file-status\">\r\n @switch (entry.value.stage) {\r\n @case ('reading') {\r\n <span class=\"text-yellow-600\">Reading...</span>\r\n }\r\n @case ('uploading') {\r\n <span class=\"text-blue-600\">Uploading...</span>\r\n }\r\n @case ('complete') {\r\n <span class=\"text-green-600\">Completed</span>\r\n }\r\n @case ('error') {\r\n <span class=\"text-red-600\">Failed</span>\r\n }\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Progress Bar (for uploading files) -->\r\n @if (entry.value.stage === 'uploading') {\r\n <div class=\"file-progress\">\r\n <div class=\"progress-bar\">\r\n <div class=\"progress-fill\" [style.width.%]=\"entry.value.percentage\"></div>\r\n </div>\r\n <span class=\"progress-text\">{{ entry.value.percentage }}%</span>\r\n </div>\r\n }\r\n\r\n <!-- Actions -->\r\n <div class=\"upload-actions\">\r\n @switch (entry.value.stage) {\r\n @case ('reading') {\r\n <button class=\"action-btn cancel-btn\" (click)=\"cancelUpload(entry.key)\" title=\"Cancel\">\r\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\r\n </button>\r\n }\r\n @case ('uploading') {\r\n <button class=\"action-btn cancel-btn\" (click)=\"cancelUpload(entry.key)\" title=\"Cancel\">\r\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\r\n </button>\r\n }\r\n @case ('complete') {\r\n <button class=\"action-btn success-btn\" title=\"Completed\">\r\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\r\n </button>\r\n }\r\n @case ('error') {\r\n <button class=\"action-btn retry-btn\" title=\"Retry\">\r\n <cide-ele-icon size=\"xs\">refresh</cide-ele-icon>\r\n </button>\r\n }\r\n }\r\n </div>\r\n </div>\r\n }\r\n \r\n <!-- Show completed files from local state -->\r\n @for (entry of completedFiles() | keyvalue; track entry.key) {\r\n <div class=\"upload-item status-completed\">\r\n <div class=\"file-info\">\r\n <cide-ele-icon class=\"status-icon\" size=\"xs\">check_circle</cide-ele-icon>\r\n <div class=\"file-details\">\r\n <div class=\"file-name\">{{ entry.value.fileName }}</div>\r\n <div class=\"file-status\">\r\n <span class=\"text-green-600\">Completed</span>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"upload-actions\">\r\n <button class=\"action-btn success-btn\" title=\"Completed\">\r\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n <!-- No uploads message when manually opened -->\r\n <div class=\"no-uploads-message\">\r\n <div class=\"message-content\">\r\n <cide-ele-icon size=\"md\" class=\"message-icon\">cloud_upload</cide-ele-icon>\r\n <div class=\"message-text\">\r\n <h4>No active uploads</h4>\r\n <p>Upload files to see their progress here</p>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n}\r\n", styles: [".floating-uploader{position:fixed;bottom:20px;right:20px;width:320px;max-height:500px;background:#fff;border-radius:12px;box-shadow:0 8px 32px #0000001f;border:1px solid rgba(0,0,0,.08);z-index:1000;overflow:hidden;transition:all .3s cubic-bezier(.4,0,.2,1);transform:translateY(0);opacity:1}.floating-uploader.animating{transition:all .3s cubic-bezier(.4,0,.2,1)}.floating-uploader.minimized .uploader-content{display:none}.floating-uploader.minimized .uploader-footer{border-top:none}.floating-uploader.uploading{border-color:#3b82f6;box-shadow:0 8px 32px #3b82f626}.floating-uploader .uploader-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;background:#f8fafc;border-bottom:1px solid #e2e8f0}.floating-uploader .uploader-header .header-left{display:flex;align-items:center;gap:8px}.floating-uploader .uploader-header .header-left .upload-icon{display:flex;align-items:center;justify-content:center;width:24px;height:24px;background:#3b82f6;border-radius:6px;color:#fff}.floating-uploader .uploader-header .header-left .upload-info .upload-title{font-size:14px;font-weight:600;color:#1e293b;margin:0}.floating-uploader .uploader-header .header-left .upload-info .upload-summary{font-size:12px;color:#64748b;margin:0}.floating-uploader .uploader-header .header-actions{display:flex;gap:4px}.floating-uploader .uploader-header .header-actions .action-btn{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;background:transparent;border-radius:4px;cursor:pointer;transition:background-color .2s;color:#64748b}.floating-uploader .uploader-header .header-actions .action-btn:hover{background:#e2e8f0;color:#1e293b}.floating-uploader .uploader-header .header-actions .action-btn.close-btn:hover{background:#fef2f2;color:#dc2626}.floating-uploader .uploader-content{max-height:400px;overflow-y:auto}.floating-uploader .uploader-content .overall-progress{padding:12px 16px;border-bottom:1px solid #e2e8f0}.floating-uploader .uploader-content .overall-progress .progress-bar{width:100%;height:4px;background:#e2e8f0;border-radius:2px;overflow:hidden;margin-bottom:4px}.floating-uploader .uploader-content .overall-progress .progress-bar .progress-fill{height:100%;background:#3b82f6;transition:width .3s ease}.floating-uploader .uploader-content .overall-progress .progress-text{font-size:12px;color:#64748b;text-align:center;display:block}.floating-uploader .uploader-content .upload-queue .upload-item{display:flex;align-items:center;padding:8px 16px;border-bottom:1px solid #f1f5f9;transition:background-color .2s}.floating-uploader .uploader-content .upload-queue .upload-item:last-child{border-bottom:none}.floating-uploader .uploader-content .upload-queue .upload-item.status-uploading{background:#f0f9ff}.floating-uploader .uploader-content .upload-queue .upload-item.status-completed{background:#f0fdf4}.floating-uploader .uploader-content .upload-queue .upload-item.status-error{background:#fef2f2}.floating-uploader .uploader-content .upload-queue .upload-item .file-info{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .status-icon{flex-shrink:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details{min-width:0;flex:1}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-name{font-size:13px;font-weight:500;color:#1e293b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-status{font-size:11px;margin:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-status span{font-weight:500}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress{display:flex;align-items:center;gap:8px;margin:0 8px;min-width:80px}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar{flex:1;height:3px;background:#e2e8f0;border-radius:2px;overflow:hidden}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar .progress-fill{height:100%;background:#3b82f6;transition:width .3s ease}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-text{font-size:10px;color:#64748b;min-width:24px;text-align:right}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions{display:flex;gap:4px}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn{display:flex;align-items:center;justify-content:center;width:20px;height:20px;border:none;background:transparent;border-radius:4px;cursor:pointer;transition:all .2s;color:#64748b}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn:hover{background:#e2e8f0}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.cancel-btn:hover{background:#fef2f2;color:#dc2626}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.retry-btn:hover{background:#f0f9ff;color:#3b82f6}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.success-btn{color:#16a34a}.floating-uploader .uploader-content .hidden-uploader{display:none}.floating-uploader .uploader-footer{padding:8px 16px;background:#f8fafc;border-top:1px solid #e2e8f0}.floating-uploader .uploader-footer .footer-stats{display:flex;gap:12px;font-size:11px}.floating-uploader .uploader-footer .footer-stats .stat{display:flex;align-items:center;gap:4px;color:#64748b}.floating-uploader .uploader-footer .footer-stats .stat.uploading{color:#3b82f6}.floating-uploader .uploader-footer .footer-stats .stat.completed{color:#16a34a}.floating-uploader .uploader-footer .footer-stats .stat.failed{color:#dc2626}@media (max-width: 640px){.floating-uploader{bottom:10px;right:10px;left:10px;width:auto;max-width:none}}@media (prefers-color-scheme: dark){.floating-uploader{background:#1e293b;border-color:#334155;box-shadow:0 8px 32px #0000004d}.floating-uploader.uploading{border-color:#3b82f6;box-shadow:0 8px 32px #3b82f633}.floating-uploader .uploader-header{background:#334155;border-bottom-color:#475569}.floating-uploader .uploader-header .header-left .upload-icon{background:#3b82f6}.floating-uploader .uploader-header .header-left .upload-info .upload-title{color:#f1f5f9}.floating-uploader .uploader-header .header-left .upload-info .upload-summary,.floating-uploader .uploader-header .header-actions .action-btn{color:#94a3b8}.floating-uploader .uploader-header .header-actions .action-btn:hover{background:#475569;color:#f1f5f9}.floating-uploader .uploader-header .header-actions .action-btn.close-btn:hover{background:#7f1d1d;color:#fca5a5}.floating-uploader .uploader-content .overall-progress{border-bottom-color:#475569}.floating-uploader .uploader-content .overall-progress .progress-bar{background:#475569}.floating-uploader .uploader-content .overall-progress .progress-bar .progress-fill{background:#3b82f6}.floating-uploader .uploader-content .overall-progress .progress-text{color:#94a3b8}.floating-uploader .uploader-content .upload-queue .upload-item{border-bottom-color:#334155}.floating-uploader .uploader-content .upload-queue .upload-item.status-uploading{background:#1e3a8a}.floating-uploader .uploader-content .upload-queue .upload-item.status-completed{background:#14532d}.floating-uploader .uploader-content .upload-queue .upload-item.status-error{background:#7f1d1d}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-name{color:#f1f5f9}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar{background:#475569}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar .progress-fill{background:#3b82f6}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-text,.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn{color:#94a3b8}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn:hover{background:#475569}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.cancel-btn:hover{background:#7f1d1d;color:#fca5a5}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.retry-btn:hover{background:#1e3a8a;color:#60a5fa}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.success-btn{color:#4ade80}.floating-uploader .uploader-footer{background:#334155;border-top-color:#475569}.floating-uploader .uploader-footer .footer-stats .stat{color:#94a3b8}.floating-uploader .uploader-footer .footer-stats .stat.uploading{color:#60a5fa}.floating-uploader .uploader-footer .footer-stats .stat.completed{color:#4ade80}.floating-uploader .uploader-footer .footer-stats .stat.failed{color:#fca5a5}}@keyframes slideInUp{0%{transform:translateY(100%);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes slideOutDown{0%{transform:translateY(0);opacity:1}to{transform:translateY(100%);opacity:0}}.floating-uploader.animating{animation:slideInUp .3s cubic-bezier(.4,0,.2,1)}.floating-uploader.animating.hiding{animation:slideOutDown .3s cubic-bezier(.4,0,.2,1)}.no-uploads-message{padding:2rem;text-align:center;color:#6b7280}.no-uploads-message .message-content{display:flex;flex-direction:column;align-items:center;gap:1rem}.no-uploads-message .message-content .message-icon{color:#9ca3af;opacity:.7}.no-uploads-message .message-content .message-text h4{margin:0 0 .5rem;font-size:1.1rem;font-weight:600;color:#374151}.no-uploads-message .message-content .message-text p{margin:0;font-size:.9rem;color:#6b7280}\n"] }]
3551
+ ], template: "<!-- Floating File Uploader Container -->\r\n@if (isVisible()) {\r\n<div class=\"floating-uploader\" \r\n [class.minimized]=\"isMinimized()\" \r\n [class.animating]=\"isAnimating()\">\r\n\r\n <!-- Header -->\r\n <div class=\"uploader-header\">\r\n <div class=\"header-left\">\r\n <div class=\"upload-icon\">\r\n <cide-ele-icon size=\"sm\">cloud_upload</cide-ele-icon>\r\n </div>\r\n <div class=\"upload-info\">\r\n <div class=\"upload-title\">File Upload</div>\r\n <div class=\"upload-summary\">{{ getUploadSummary() }}</div>\r\n </div>\r\n </div>\r\n \r\n <div class=\"header-actions\">\r\n <button class=\"action-btn minimize-btn\" (click)=\"toggleMinimize()\" [title]=\"isMinimized() ? 'Expand' : 'Minimize'\">\r\n <cide-ele-icon size=\"xs\">{{ isMinimized() ? 'expand_more' : 'expand_less' }}</cide-ele-icon>\r\n </button>\r\n <button class=\"action-btn close-btn\" (click)=\"close()\" title=\"Close\">\r\n <cide-ele-icon size=\"xs\">close</cide-ele-icon>\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- Content (hidden when minimized) -->\r\n @if (!isMinimized()) {\r\n <div class=\"uploader-content\">\r\n \r\n <!-- Overall Progress Bar -->\r\n @if (uploadQueue().length > 0 || activeUploads().size > 0) {\r\n <div class=\"overall-progress\">\r\n <div class=\"progress-bar\">\r\n <div class=\"progress-fill\" [style.width.%]=\"getOverallProgress()\"></div>\r\n </div>\r\n <div class=\"progress-text\">{{ getOverallProgress() }}%</div>\r\n </div>\r\n }\r\n\r\n <!-- Upload Queue - Show files from local state -->\r\n @if (localFiles().size > 0) {\r\n <div class=\"upload-queue\">\r\n <!-- Show all files from local state -->\r\n @for (entry of localFiles() | keyvalue; track entry.key) {\r\n <div class=\"upload-item\" [class]=\"getStatusClass(entry.value.stage)\">\r\n <div class=\"file-info\">\r\n <cide-ele-icon class=\"status-icon\" size=\"xs\">{{ getStatusIcon(entry.value.stage) }}</cide-ele-icon>\r\n <div class=\"file-details\">\r\n <div class=\"file-name\">{{ entry.value.fileName }}</div>\r\n <div class=\"file-status\">\r\n @switch (entry.value.stage) {\r\n @case ('pending') {\r\n <span class=\"text-yellow-600\">Waiting...</span>\r\n }\r\n @case ('reading') {\r\n <span class=\"text-yellow-600\">Reading...</span>\r\n }\r\n @case ('uploading') {\r\n <span class=\"text-blue-600\">Uploading...</span>\r\n }\r\n @case ('complete') {\r\n <span class=\"text-green-600\">Completed</span>\r\n }\r\n @case ('error') {\r\n <span class=\"text-red-600\">Failed</span>\r\n }\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Progress Bar (for uploading files) -->\r\n @if (entry.value.stage === 'uploading' && entry.value.percentage !== undefined) {\r\n <div class=\"file-progress\">\r\n <div class=\"progress-bar\">\r\n <div class=\"progress-fill\" [style.width.%]=\"entry.value.percentage\"></div>\r\n </div>\r\n <span class=\"progress-text\">{{ entry.value.percentage }}%</span>\r\n </div>\r\n }\r\n\r\n <!-- Actions -->\r\n <div class=\"upload-actions\">\r\n @switch (entry.value.stage) {\r\n @case ('pending') {\r\n <button class=\"action-btn cancel-btn\" (click)=\"cancelUpload(entry.key)\" title=\"Cancel\">\r\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\r\n </button>\r\n }\r\n @case ('reading') {\r\n <button class=\"action-btn cancel-btn\" (click)=\"cancelUpload(entry.key)\" title=\"Cancel\">\r\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\r\n </button>\r\n }\r\n @case ('uploading') {\r\n <button class=\"action-btn cancel-btn\" (click)=\"cancelUpload(entry.key)\" title=\"Cancel\">\r\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\r\n </button>\r\n }\r\n @case ('complete') {\r\n <button class=\"action-btn success-btn\" title=\"Completed\">\r\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\r\n </button>\r\n }\r\n @case ('error') {\r\n <button class=\"action-btn retry-btn\" title=\"Retry\">\r\n <cide-ele-icon size=\"xs\">refresh</cide-ele-icon>\r\n </button>\r\n }\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n } @else {\r\n <!-- No uploads message when manually opened -->\r\n <div class=\"no-uploads-message\">\r\n <div class=\"message-content\">\r\n <cide-ele-icon size=\"md\" class=\"message-icon\">cloud_upload</cide-ele-icon>\r\n <div class=\"message-text\">\r\n <h4>No active uploads</h4>\r\n <p>Upload files to see their progress here</p>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n}\r\n", styles: [".floating-uploader{position:fixed;bottom:20px;right:20px;width:320px;max-height:500px;background:#fff;border-radius:12px;box-shadow:0 8px 32px #0000001f;border:1px solid rgba(0,0,0,.08);z-index:1000;overflow:hidden;transition:all .3s cubic-bezier(.4,0,.2,1);transform:translateY(0);opacity:1}.floating-uploader.animating{transition:all .3s cubic-bezier(.4,0,.2,1)}.floating-uploader.minimized .uploader-content{display:none}.floating-uploader.minimized .uploader-footer{border-top:none}.floating-uploader.uploading{border-color:#3b82f6;box-shadow:0 8px 32px #3b82f626}.floating-uploader .uploader-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;background:#f8fafc;border-bottom:1px solid #e2e8f0}.floating-uploader .uploader-header .header-left{display:flex;align-items:center;gap:8px}.floating-uploader .uploader-header .header-left .upload-icon{display:flex;align-items:center;justify-content:center;width:24px;height:24px;background:#3b82f6;border-radius:6px;color:#fff}.floating-uploader .uploader-header .header-left .upload-info .upload-title{font-size:14px;font-weight:600;color:#1e293b;margin:0}.floating-uploader .uploader-header .header-left .upload-info .upload-summary{font-size:12px;color:#64748b;margin:0}.floating-uploader .uploader-header .header-actions{display:flex;gap:4px}.floating-uploader .uploader-header .header-actions .action-btn{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;background:transparent;border-radius:4px;cursor:pointer;transition:background-color .2s;color:#64748b}.floating-uploader .uploader-header .header-actions .action-btn:hover{background:#e2e8f0;color:#1e293b}.floating-uploader .uploader-header .header-actions .action-btn.close-btn:hover{background:#fef2f2;color:#dc2626}.floating-uploader .uploader-content{max-height:400px;overflow-y:auto}.floating-uploader .uploader-content .overall-progress{padding:12px 16px;border-bottom:1px solid #e2e8f0}.floating-uploader .uploader-content .overall-progress .progress-bar{width:100%;height:4px;background:#e2e8f0;border-radius:2px;overflow:hidden;margin-bottom:4px}.floating-uploader .uploader-content .overall-progress .progress-bar .progress-fill{height:100%;background:#3b82f6;transition:width .3s ease}.floating-uploader .uploader-content .overall-progress .progress-text{font-size:12px;color:#64748b;text-align:center;display:block}.floating-uploader .uploader-content .upload-queue .upload-item{display:flex;align-items:center;padding:8px 16px;border-bottom:1px solid #f1f5f9;transition:background-color .2s}.floating-uploader .uploader-content .upload-queue .upload-item:last-child{border-bottom:none}.floating-uploader .uploader-content .upload-queue .upload-item.status-uploading{background:#f0f9ff}.floating-uploader .uploader-content .upload-queue .upload-item.status-completed{background:#f0fdf4}.floating-uploader .uploader-content .upload-queue .upload-item.status-error{background:#fef2f2}.floating-uploader .uploader-content .upload-queue .upload-item .file-info{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .status-icon{flex-shrink:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details{min-width:0;flex:1}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-name{font-size:13px;font-weight:500;color:#1e293b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-status{font-size:11px;margin:0}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-status span{font-weight:500}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress{display:flex;align-items:center;gap:8px;margin:0 8px;min-width:80px}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar{flex:1;height:3px;background:#e2e8f0;border-radius:2px;overflow:hidden}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar .progress-fill{height:100%;background:#3b82f6;transition:width .3s ease}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-text{font-size:10px;color:#64748b;min-width:24px;text-align:right}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions{display:flex;gap:4px}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn{display:flex;align-items:center;justify-content:center;width:20px;height:20px;border:none;background:transparent;border-radius:4px;cursor:pointer;transition:all .2s;color:#64748b}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn:hover{background:#e2e8f0}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.cancel-btn:hover{background:#fef2f2;color:#dc2626}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.retry-btn:hover{background:#f0f9ff;color:#3b82f6}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.success-btn{color:#16a34a}.floating-uploader .uploader-content .hidden-uploader{display:none}.floating-uploader .uploader-footer{padding:8px 16px;background:#f8fafc;border-top:1px solid #e2e8f0}.floating-uploader .uploader-footer .footer-stats{display:flex;gap:12px;font-size:11px}.floating-uploader .uploader-footer .footer-stats .stat{display:flex;align-items:center;gap:4px;color:#64748b}.floating-uploader .uploader-footer .footer-stats .stat.uploading{color:#3b82f6}.floating-uploader .uploader-footer .footer-stats .stat.completed{color:#16a34a}.floating-uploader .uploader-footer .footer-stats .stat.failed{color:#dc2626}@media (max-width: 640px){.floating-uploader{bottom:10px;right:10px;left:10px;width:auto;max-width:none}}@media (prefers-color-scheme: dark){.floating-uploader{background:#1e293b;border-color:#334155;box-shadow:0 8px 32px #0000004d}.floating-uploader.uploading{border-color:#3b82f6;box-shadow:0 8px 32px #3b82f633}.floating-uploader .uploader-header{background:#334155;border-bottom-color:#475569}.floating-uploader .uploader-header .header-left .upload-icon{background:#3b82f6}.floating-uploader .uploader-header .header-left .upload-info .upload-title{color:#f1f5f9}.floating-uploader .uploader-header .header-left .upload-info .upload-summary,.floating-uploader .uploader-header .header-actions .action-btn{color:#94a3b8}.floating-uploader .uploader-header .header-actions .action-btn:hover{background:#475569;color:#f1f5f9}.floating-uploader .uploader-header .header-actions .action-btn.close-btn:hover{background:#7f1d1d;color:#fca5a5}.floating-uploader .uploader-content .overall-progress{border-bottom-color:#475569}.floating-uploader .uploader-content .overall-progress .progress-bar{background:#475569}.floating-uploader .uploader-content .overall-progress .progress-bar .progress-fill{background:#3b82f6}.floating-uploader .uploader-content .overall-progress .progress-text{color:#94a3b8}.floating-uploader .uploader-content .upload-queue .upload-item{border-bottom-color:#334155}.floating-uploader .uploader-content .upload-queue .upload-item.status-uploading{background:#1e3a8a}.floating-uploader .uploader-content .upload-queue .upload-item.status-completed{background:#14532d}.floating-uploader .uploader-content .upload-queue .upload-item.status-error{background:#7f1d1d}.floating-uploader .uploader-content .upload-queue .upload-item .file-info .file-details .file-name{color:#f1f5f9}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar{background:#475569}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-bar .progress-fill{background:#3b82f6}.floating-uploader .uploader-content .upload-queue .upload-item .file-progress .progress-text,.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn{color:#94a3b8}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn:hover{background:#475569}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.cancel-btn:hover{background:#7f1d1d;color:#fca5a5}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.retry-btn:hover{background:#1e3a8a;color:#60a5fa}.floating-uploader .uploader-content .upload-queue .upload-item .upload-actions .action-btn.success-btn{color:#4ade80}.floating-uploader .uploader-footer{background:#334155;border-top-color:#475569}.floating-uploader .uploader-footer .footer-stats .stat{color:#94a3b8}.floating-uploader .uploader-footer .footer-stats .stat.uploading{color:#60a5fa}.floating-uploader .uploader-footer .footer-stats .stat.completed{color:#4ade80}.floating-uploader .uploader-footer .footer-stats .stat.failed{color:#fca5a5}}@keyframes slideInUp{0%{transform:translateY(100%);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes slideOutDown{0%{transform:translateY(0);opacity:1}to{transform:translateY(100%);opacity:0}}.floating-uploader.animating{animation:slideInUp .3s cubic-bezier(.4,0,.2,1)}.floating-uploader.animating.hiding{animation:slideOutDown .3s cubic-bezier(.4,0,.2,1)}.no-uploads-message{padding:2rem;text-align:center;color:#6b7280}.no-uploads-message .message-content{display:flex;flex-direction:column;align-items:center;gap:1rem}.no-uploads-message .message-content .message-icon{color:#9ca3af;opacity:.7}.no-uploads-message .message-content .message-text h4{margin:0 0 .5rem;font-size:1.1rem;font-weight:600;color:#374151}.no-uploads-message .message-content .message-text p{margin:0;font-size:.9rem;color:#6b7280}\n"] }]
3536
3552
  }], ctorParameters: () => [] });
3537
3553
 
3538
3554
  class CideEleFileInputComponent {