cloud-ide-element 1.0.76 → 1.0.77

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.
@@ -4508,6 +4508,326 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
4508
4508
  type: Output
4509
4509
  }] } });
4510
4510
 
4511
+ class CideEleFloatingFileUploaderComponent {
4512
+ destroyRef = inject(DestroyRef);
4513
+ fileManagerService = inject(CideEleFileManagerService);
4514
+ // Signals for reactive state
4515
+ isVisible = signal(false, ...(ngDevMode ? [{ debugName: "isVisible" }] : []));
4516
+ isMinimized = signal(false, ...(ngDevMode ? [{ debugName: "isMinimized" }] : []));
4517
+ uploadQueue = signal([], ...(ngDevMode ? [{ debugName: "uploadQueue" }] : []));
4518
+ isUploading = signal(false, ...(ngDevMode ? [{ debugName: "isUploading" }] : []));
4519
+ uploadProgress = signal(0, ...(ngDevMode ? [{ debugName: "uploadProgress" }] : []));
4520
+ currentUserId = signal('', ...(ngDevMode ? [{ debugName: "currentUserId" }] : []));
4521
+ // Computed values
4522
+ hasUploads = computed(() => this.uploadQueue().length > 0, ...(ngDevMode ? [{ debugName: "hasUploads" }] : []));
4523
+ pendingUploads = computed(() => this.uploadQueue().filter(upload => upload.status === 'pending'), ...(ngDevMode ? [{ debugName: "pendingUploads" }] : []));
4524
+ activeUploads = computed(() => this.uploadQueue().filter(upload => upload.status === 'uploading'), ...(ngDevMode ? [{ debugName: "activeUploads" }] : []));
4525
+ completedUploads = computed(() => this.uploadQueue().filter(upload => upload.status === 'completed'), ...(ngDevMode ? [{ debugName: "completedUploads" }] : []));
4526
+ failedUploads = computed(() => this.uploadQueue().filter(upload => upload.status === 'error'), ...(ngDevMode ? [{ debugName: "failedUploads" }] : []));
4527
+ // Animation states
4528
+ isAnimating = signal(false, ...(ngDevMode ? [{ debugName: "isAnimating" }] : []));
4529
+ constructor() {
4530
+ console.log('🚀 [FloatingFileUploader] Component initialized');
4531
+ }
4532
+ ngOnInit() {
4533
+ // Set up drag and drop listeners
4534
+ this.setupDragAndDrop();
4535
+ // Note: The file manager service uses signals, so we'll handle uploads directly
4536
+ // when files are added to the queue rather than subscribing to service state
4537
+ }
4538
+ ngOnDestroy() {
4539
+ console.log('🧹 [FloatingFileUploader] Component destroyed');
4540
+ this.removeDragAndDropListeners();
4541
+ }
4542
+ /**
4543
+ * Set up drag and drop functionality
4544
+ */
4545
+ setupDragAndDrop() {
4546
+ document.addEventListener('dragover', this.handleDragOver.bind(this));
4547
+ document.addEventListener('dragleave', this.handleDragLeave.bind(this));
4548
+ document.addEventListener('drop', this.handleDrop.bind(this));
4549
+ }
4550
+ /**
4551
+ * Remove drag and drop listeners
4552
+ */
4553
+ removeDragAndDropListeners() {
4554
+ document.removeEventListener('dragover', this.handleDragOver.bind(this));
4555
+ document.removeEventListener('dragleave', this.handleDragLeave.bind(this));
4556
+ document.removeEventListener('drop', this.handleDrop.bind(this));
4557
+ }
4558
+ /**
4559
+ * Handle drag over event
4560
+ */
4561
+ handleDragOver(event) {
4562
+ event.preventDefault();
4563
+ event.stopPropagation();
4564
+ // Show floating uploader when files are dragged over
4565
+ if (event.dataTransfer?.types.includes('Files')) {
4566
+ this.showWithAnimation();
4567
+ }
4568
+ }
4569
+ /**
4570
+ * Handle drag leave event
4571
+ */
4572
+ handleDragLeave(event) {
4573
+ event.preventDefault();
4574
+ event.stopPropagation();
4575
+ // Only hide if leaving the entire document
4576
+ if (!event.relatedTarget || event.relatedTarget === document.body) {
4577
+ this.updateVisibility();
4578
+ }
4579
+ }
4580
+ /**
4581
+ * Handle drop event
4582
+ */
4583
+ handleDrop(event) {
4584
+ event.preventDefault();
4585
+ event.stopPropagation();
4586
+ const files = event.dataTransfer?.files;
4587
+ if (files && files.length > 0) {
4588
+ this.handleFiles(Array.from(files));
4589
+ }
4590
+ }
4591
+ /**
4592
+ * Handle files from drag and drop or file input
4593
+ */
4594
+ handleFiles(files) {
4595
+ console.log('📁 [FloatingFileUploader] Handling files:', files.length);
4596
+ // Add files to the file manager service queue
4597
+ files.forEach(file => {
4598
+ const fileId = this.generateFileId(file);
4599
+ // Create upload progress item
4600
+ const uploadItem = {
4601
+ fileId,
4602
+ fileName: file.name,
4603
+ progress: 0,
4604
+ status: 'pending'
4605
+ };
4606
+ // Add to local queue
4607
+ this.uploadQueue.update(queue => [...queue, uploadItem]);
4608
+ // Start upload using file manager service
4609
+ this.fileManagerService.uploadFile(file, {
4610
+ userId: this.currentUserId(),
4611
+ permissions: ['read', 'write'],
4612
+ tags: []
4613
+ }, (progress) => {
4614
+ this.updateUploadProgress(fileId, progress);
4615
+ })
4616
+ .pipe(takeUntilDestroyed(this.destroyRef))
4617
+ .subscribe({
4618
+ next: (response) => {
4619
+ console.log('✅ [FloatingFileUploader] Upload completed:', response);
4620
+ this.updateUploadStatus(fileId, 'completed', 100, undefined, response);
4621
+ },
4622
+ error: (error) => {
4623
+ console.error('❌ [FloatingFileUploader] Upload failed:', error);
4624
+ this.updateUploadStatus(fileId, 'error', 0, error.message || 'Upload failed');
4625
+ }
4626
+ });
4627
+ });
4628
+ this.updateVisibility();
4629
+ }
4630
+ /**
4631
+ * Update visibility based on upload state
4632
+ */
4633
+ updateVisibility() {
4634
+ const hasActiveUploads = this.activeUploads().length > 0;
4635
+ const hasPendingUploads = this.pendingUploads().length > 0;
4636
+ const hasCompletedUploads = this.completedUploads().length > 0;
4637
+ const hasFailedUploads = this.failedUploads().length > 0;
4638
+ // Show if there are active, pending, or recent completed/failed uploads
4639
+ const shouldShow = hasActiveUploads || hasPendingUploads || hasCompletedUploads || hasFailedUploads;
4640
+ if (shouldShow && !this.isVisible()) {
4641
+ this.showWithAnimation();
4642
+ }
4643
+ else if (!shouldShow && this.isVisible()) {
4644
+ this.hideWithAnimation();
4645
+ }
4646
+ }
4647
+ /**
4648
+ * Show with animation
4649
+ */
4650
+ showWithAnimation() {
4651
+ this.isAnimating.set(true);
4652
+ this.isVisible.set(true);
4653
+ // Remove animation class after animation completes
4654
+ setTimeout(() => {
4655
+ this.isAnimating.set(false);
4656
+ }, 300);
4657
+ }
4658
+ /**
4659
+ * Hide with animation
4660
+ */
4661
+ hideWithAnimation() {
4662
+ this.isAnimating.set(true);
4663
+ // Wait for animation to complete before hiding
4664
+ setTimeout(() => {
4665
+ this.isVisible.set(false);
4666
+ this.isAnimating.set(false);
4667
+ }, 300);
4668
+ }
4669
+ /**
4670
+ * Toggle minimize state
4671
+ */
4672
+ toggleMinimize() {
4673
+ this.isMinimized.set(!this.isMinimized());
4674
+ }
4675
+ /**
4676
+ * Close the floating uploader
4677
+ */
4678
+ close() {
4679
+ this.clearAllUploads();
4680
+ this.hideWithAnimation();
4681
+ }
4682
+ /**
4683
+ * Clear all uploads
4684
+ */
4685
+ clearAllUploads() {
4686
+ this.uploadQueue.set([]);
4687
+ }
4688
+ /**
4689
+ * Clear completed uploads
4690
+ */
4691
+ clearCompletedUploads() {
4692
+ this.uploadQueue.update(queue => queue.filter(upload => upload.status !== 'completed'));
4693
+ }
4694
+ /**
4695
+ * Cancel upload
4696
+ */
4697
+ cancelUpload(fileId) {
4698
+ console.log('🚫 [FloatingFileUploader] Cancelling upload:', fileId);
4699
+ this.fileManagerService.cancelUpload(fileId);
4700
+ this.updateUploadStatus(fileId, 'cancelled', 0);
4701
+ }
4702
+ /**
4703
+ * Retry upload
4704
+ */
4705
+ retryUpload(fileId) {
4706
+ console.log('🔄 [FloatingFileUploader] Retrying upload:', fileId);
4707
+ this.updateUploadStatus(fileId, 'pending', 0);
4708
+ // Note: Actual retry logic would need to be implemented based on stored file data
4709
+ }
4710
+ /**
4711
+ * Update upload progress
4712
+ */
4713
+ updateUploadProgress(fileId, progress) {
4714
+ this.uploadQueue.update(queue => queue.map(upload => upload.fileId === fileId
4715
+ ? { ...upload, progress, status: 'uploading' }
4716
+ : upload));
4717
+ }
4718
+ /**
4719
+ * Update upload status
4720
+ */
4721
+ updateUploadStatus(fileId, status, progress, error, uploadedFile) {
4722
+ this.uploadQueue.update(queue => queue.map(upload => upload.fileId === fileId
4723
+ ? { ...upload, status, progress, error, uploadedFile }
4724
+ : upload));
4725
+ }
4726
+ /**
4727
+ * Get status icon
4728
+ */
4729
+ getStatusIcon(status) {
4730
+ switch (status) {
4731
+ case 'pending': return 'schedule';
4732
+ case 'uploading': return 'cloud_upload';
4733
+ case 'completed': return 'check_circle';
4734
+ case 'error': return 'error';
4735
+ case 'cancelled': return 'cancel';
4736
+ default: return 'help';
4737
+ }
4738
+ }
4739
+ /**
4740
+ * Get status class
4741
+ */
4742
+ getStatusClass(status) {
4743
+ switch (status) {
4744
+ case 'pending': return 'status-pending';
4745
+ case 'uploading': return 'status-uploading';
4746
+ case 'completed': return 'status-completed';
4747
+ case 'error': return 'status-error';
4748
+ case 'cancelled': return 'status-cancelled';
4749
+ default: return 'status-unknown';
4750
+ }
4751
+ }
4752
+ /**
4753
+ * Get file size display
4754
+ */
4755
+ getFileSizeDisplay(size) {
4756
+ if (size === 0)
4757
+ return '0 Bytes';
4758
+ const k = 1024;
4759
+ const sizes = ['Bytes', 'KB', 'MB', 'GB'];
4760
+ const i = Math.floor(Math.log(size) / Math.log(k));
4761
+ return parseFloat((size / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
4762
+ }
4763
+ /**
4764
+ * Get overall progress percentage
4765
+ */
4766
+ getOverallProgress() {
4767
+ const uploads = this.uploadQueue();
4768
+ if (uploads.length === 0)
4769
+ return 0;
4770
+ const totalProgress = uploads.reduce((sum, upload) => sum + upload.progress, 0);
4771
+ return Math.round(totalProgress / uploads.length);
4772
+ }
4773
+ /**
4774
+ * Get upload summary text
4775
+ */
4776
+ getUploadSummary() {
4777
+ const active = this.activeUploads().length;
4778
+ const completed = this.completedUploads().length;
4779
+ const failed = this.failedUploads().length;
4780
+ const pending = this.pendingUploads().length;
4781
+ if (active > 0) {
4782
+ return `${active} uploading`;
4783
+ }
4784
+ else if (completed > 0 && failed === 0) {
4785
+ return `${completed} completed`;
4786
+ }
4787
+ else if (failed > 0) {
4788
+ return `${completed} completed, ${failed} failed`;
4789
+ }
4790
+ else if (pending > 0) {
4791
+ return `${pending} pending`;
4792
+ }
4793
+ return 'No uploads';
4794
+ }
4795
+ /**
4796
+ * Generate unique file ID
4797
+ */
4798
+ generateFileId(file) {
4799
+ return `${file.name}_${file.size}_${Date.now()}`;
4800
+ }
4801
+ /**
4802
+ * Extract file name from file ID
4803
+ */
4804
+ extractFileNameFromId(fileId) {
4805
+ // Extract filename from the fileId format: filename_size_timestamp
4806
+ const parts = fileId.split('_');
4807
+ if (parts.length >= 3) {
4808
+ // Remove the last two parts (size and timestamp) to get the filename
4809
+ return parts.slice(0, -2).join('_');
4810
+ }
4811
+ return fileId;
4812
+ }
4813
+ /**
4814
+ * Set current user ID
4815
+ */
4816
+ setCurrentUserId(userId) {
4817
+ this.currentUserId.set(userId);
4818
+ this.fileManagerService.setUserId(userId);
4819
+ }
4820
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingFileUploaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4821
+ 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 [class.uploading]=\"isUploading()\">\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 (isUploading()) {\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 -->\r\n @if (hasUploads()) {\r\n <div class=\"upload-queue\">\r\n @for (upload of uploadQueue(); track upload.fileId) {\r\n <div class=\"upload-item\" [class]=\"getStatusClass(upload.status)\">\r\n \r\n <!-- File Info -->\r\n <div class=\"file-info\">\r\n <cide-ele-icon class=\"status-icon\" size=\"xs\">{{ getStatusIcon(upload.status) }}</cide-ele-icon>\r\n <div class=\"file-details\">\r\n <div class=\"file-name\">{{ upload.fileName }}</div>\r\n <div class=\"file-status\">\r\n @switch (upload.status) {\r\n @case ('pending') {\r\n <span class=\"text-yellow-600\">Waiting...</span>\r\n }\r\n @case ('uploading') {\r\n <span class=\"text-blue-600\">Uploading...</span>\r\n }\r\n @case ('completed') {\r\n <span class=\"text-green-600\">Completed</span>\r\n }\r\n @case ('error') {\r\n <span class=\"text-red-600\">{{ upload.error || 'Failed' }}</span>\r\n }\r\n @case ('cancelled') {\r\n <span class=\"text-gray-600\">Cancelled</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 (upload.status === 'uploading') {\r\n <div class=\"file-progress\">\r\n <div class=\"progress-bar\">\r\n <div class=\"progress-fill\" [style.width.%]=\"upload.progress\"></div>\r\n </div>\r\n <span class=\"progress-text\">{{ upload.progress }}%</span>\r\n </div>\r\n }\r\n\r\n <!-- Actions -->\r\n <div class=\"upload-actions\">\r\n @switch (upload.status) {\r\n @case ('pending') {\r\n <button class=\"action-btn cancel-btn\" (click)=\"cancelUpload(upload.fileId)\" 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(upload.fileId)\" title=\"Cancel\">\r\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\r\n </button>\r\n }\r\n @case ('completed') {\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\" (click)=\"retryUpload(upload.fileId)\" 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 }\r\n\r\n <!-- Hidden file input for drag & drop -->\r\n <div class=\"hidden-uploader\">\r\n <input type=\"file\" multiple style=\"display: none;\" id=\"floating-file-input\">\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Footer (always visible) -->\r\n <div class=\"uploader-footer\">\r\n <div class=\"footer-stats\">\r\n @if (activeUploads().length > 0) {\r\n <span class=\"stat uploading\">\r\n <cide-ele-icon size=\"xs\">cloud_upload</cide-ele-icon>\r\n {{ activeUploads().length }} uploading\r\n </span>\r\n }\r\n @if (completedUploads().length > 0) {\r\n <span class=\"stat completed\">\r\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\r\n {{ completedUploads().length }} completed\r\n </span>\r\n }\r\n @if (failedUploads().length > 0) {\r\n <span class=\"stat failed\">\r\n <cide-ele-icon size=\"xs\">error</cide-ele-icon>\r\n {{ failedUploads().length }} failed\r\n </span>\r\n }\r\n </div>\r\n </div>\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)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }] });
4822
+ }
4823
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingFileUploaderComponent, decorators: [{
4824
+ type: Component,
4825
+ args: [{ selector: 'cide-ele-floating-file-uploader', standalone: true, imports: [
4826
+ CommonModule,
4827
+ CideIconComponent
4828
+ ], 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 [class.uploading]=\"isUploading()\">\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 (isUploading()) {\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 -->\r\n @if (hasUploads()) {\r\n <div class=\"upload-queue\">\r\n @for (upload of uploadQueue(); track upload.fileId) {\r\n <div class=\"upload-item\" [class]=\"getStatusClass(upload.status)\">\r\n \r\n <!-- File Info -->\r\n <div class=\"file-info\">\r\n <cide-ele-icon class=\"status-icon\" size=\"xs\">{{ getStatusIcon(upload.status) }}</cide-ele-icon>\r\n <div class=\"file-details\">\r\n <div class=\"file-name\">{{ upload.fileName }}</div>\r\n <div class=\"file-status\">\r\n @switch (upload.status) {\r\n @case ('pending') {\r\n <span class=\"text-yellow-600\">Waiting...</span>\r\n }\r\n @case ('uploading') {\r\n <span class=\"text-blue-600\">Uploading...</span>\r\n }\r\n @case ('completed') {\r\n <span class=\"text-green-600\">Completed</span>\r\n }\r\n @case ('error') {\r\n <span class=\"text-red-600\">{{ upload.error || 'Failed' }}</span>\r\n }\r\n @case ('cancelled') {\r\n <span class=\"text-gray-600\">Cancelled</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 (upload.status === 'uploading') {\r\n <div class=\"file-progress\">\r\n <div class=\"progress-bar\">\r\n <div class=\"progress-fill\" [style.width.%]=\"upload.progress\"></div>\r\n </div>\r\n <span class=\"progress-text\">{{ upload.progress }}%</span>\r\n </div>\r\n }\r\n\r\n <!-- Actions -->\r\n <div class=\"upload-actions\">\r\n @switch (upload.status) {\r\n @case ('pending') {\r\n <button class=\"action-btn cancel-btn\" (click)=\"cancelUpload(upload.fileId)\" 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(upload.fileId)\" title=\"Cancel\">\r\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\r\n </button>\r\n }\r\n @case ('completed') {\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\" (click)=\"retryUpload(upload.fileId)\" 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 }\r\n\r\n <!-- Hidden file input for drag & drop -->\r\n <div class=\"hidden-uploader\">\r\n <input type=\"file\" multiple style=\"display: none;\" id=\"floating-file-input\">\r\n </div>\r\n </div>\r\n }\r\n\r\n <!-- Footer (always visible) -->\r\n <div class=\"uploader-footer\">\r\n <div class=\"footer-stats\">\r\n @if (activeUploads().length > 0) {\r\n <span class=\"stat uploading\">\r\n <cide-ele-icon size=\"xs\">cloud_upload</cide-ele-icon>\r\n {{ activeUploads().length }} uploading\r\n </span>\r\n }\r\n @if (completedUploads().length > 0) {\r\n <span class=\"stat completed\">\r\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\r\n {{ completedUploads().length }} completed\r\n </span>\r\n }\r\n @if (failedUploads().length > 0) {\r\n <span class=\"stat failed\">\r\n <cide-ele-icon size=\"xs\">error</cide-ele-icon>\r\n {{ failedUploads().length }} failed\r\n </span>\r\n }\r\n </div>\r\n </div>\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)}\n"] }]
4829
+ }], ctorParameters: () => [] });
4830
+
4511
4831
  class CideTextareaComponent {
4512
4832
  label = '';
4513
4833
  labelHide = false;
@@ -8746,5 +9066,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
8746
9066
  * Generated bundle index. Do not edit.
8747
9067
  */
8748
9068
 
8749
- export { CideCoreFileManagerService, CideEleButtonComponent, CideEleConfirmationModalComponent, CideEleDataGridComponent, CideEleDropdownComponent, CideEleFileImageDirective, CideEleFileInputComponent, CideEleFileManagerService, CideEleGlobalFileUploaderComponent, CideEleGlobalNotificationsComponent, CideEleJsonEditorComponent, CideEleResizerDirective, CideEleSkeletonLoaderComponent, CideEleTabComponent, CideEleToastNotificationComponent, CideElementsService, CideIconComponent, CideInputComponent, CideSelectComponent, CideSelectOptionComponent, CideSpinnerComponent, CideTextareaComponent, ConfirmationService, CoreFileManagerInsertUpdatePayload, DEFAULT_GRID_CONFIG, DropdownManagerService, ICoreCyfmSave, MFileManager, NotificationService, TooltipDirective };
9069
+ export { CideCoreFileManagerService, CideEleButtonComponent, CideEleConfirmationModalComponent, CideEleDataGridComponent, CideEleDropdownComponent, CideEleFileImageDirective, CideEleFileInputComponent, CideEleFileManagerService, CideEleFloatingFileUploaderComponent, CideEleGlobalFileUploaderComponent, CideEleGlobalNotificationsComponent, CideEleJsonEditorComponent, CideEleResizerDirective, CideEleSkeletonLoaderComponent, CideEleTabComponent, CideEleToastNotificationComponent, CideElementsService, CideIconComponent, CideInputComponent, CideSelectComponent, CideSelectOptionComponent, CideSpinnerComponent, CideTextareaComponent, ConfirmationService, CoreFileManagerInsertUpdatePayload, DEFAULT_GRID_CONFIG, DropdownManagerService, ICoreCyfmSave, MFileManager, NotificationService, TooltipDirective };
8750
9070
  //# sourceMappingURL=cloud-ide-element.mjs.map