cloud-ide-element 1.0.120 → 1.0.121

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.
@@ -5015,6 +5015,16 @@ class CideEleFloatingFileUploaderComponent {
5015
5015
  hasFilesToShow = computed(() => {
5016
5016
  return this.hasActiveUploads() || this.allFilesForGroup().length > 0;
5017
5017
  }, ...(ngDevMode ? [{ debugName: "hasFilesToShow" }] : []));
5018
+ // Count methods for template
5019
+ getUploadingCount() {
5020
+ return this.activeUploadsLocal().length;
5021
+ }
5022
+ getCompletedCount() {
5023
+ return this.completedUploads().length;
5024
+ }
5025
+ getFailedCount() {
5026
+ return this.failedUploads().length;
5027
+ }
5018
5028
  // Animation states
5019
5029
  isAnimating = signal(false, ...(ngDevMode ? [{ debugName: "isAnimating" }] : []));
5020
5030
  // Drag functionality removed - handled by floating container
@@ -5409,14 +5419,14 @@ class CideEleFloatingFileUploaderComponent {
5409
5419
  });
5410
5420
  }
5411
5421
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingFileUploaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5412
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideEleFloatingFileUploaderComponent, isStandalone: true, selector: "cide-ele-floating-file-uploader", inputs: { data: "data" }, ngImport: i0, template: "<!-- File Uploader Content (No absolute positioning - works within floating container) -->\n@if (isVisible()) {\n<div class=\"file-uploader-content\">\n <!-- Simple header without window controls (floating container handles these) -->\n <div class=\"uploader-header\">\n <div class=\"upload-icon\">\n <cide-ele-icon size=\"sm\">cloud_upload</cide-ele-icon>\n </div>\n <div class=\"upload-info\">\n <div class=\"upload-title\">File Upload</div>\n <div class=\"upload-summary\">{{ getUploadSummary() }}</div>\n </div>\n </div>\n\n <!-- Content -->\n <div class=\"uploader-content\">\n \n <!-- Drag and Drop Zone -->\n <div class=\"upload-zone\" \n [class.drag-over]=\"isDragOver()\" \n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\" \n (drop)=\"onDrop($event)\" \n (click)=\"triggerFileInput()\">\n \n <!-- Hidden file input -->\n <input #fileInput \n type=\"file\" \n [multiple]=\"true\" \n [accept]=\"'*/*'\" \n (change)=\"onFileInputChange($event)\" \n style=\"display: none;\">\n \n <div class=\"upload-zone-content\">\n <cide-ele-icon class=\"upload-icon\" size=\"sm\">cloud_upload</cide-ele-icon>\n \n <div class=\"upload-text\">\n <div class=\"upload-title\">\n {{ isDragOver() ? 'Drop files here' : 'Drag files here or click to browse' }}\n </div>\n </div>\n </div>\n </div>\n \n <!-- Upload Queue - Show files from service state -->\n @if (allFilesForGroup().length > 0) {\n <div class=\"upload-queue\">\n <!-- Show all files from service state -->\n @for (file of allFilesForGroup(); track file.fileId) {\n <div class=\"upload-item\" [class]=\"getStatusClass(file.stage)\">\n <div class=\"file-info\">\n <cide-ele-icon class=\"status-icon\" size=\"xs\">{{ getStatusIcon(file.stage) }}</cide-ele-icon>\n <div class=\"file-details\">\n <div class=\"file-name\">{{ file.fileName }}</div>\n <div class=\"file-status\">\n @switch (file.stage) {\n @case ('pending') {\n <span class=\"text-yellow-600\">Waiting...</span>\n }\n @case ('reading') {\n <span class=\"text-yellow-600\">Reading...</span>\n }\n @case ('uploading') {\n <span class=\"text-blue-600\">Uploading...</span>\n }\n @case ('complete') {\n <span class=\"text-green-600\">Completed</span>\n }\n @case ('error') {\n <span class=\"text-red-600\">Failed</span>\n }\n }\n </div>\n </div>\n </div>\n\n <!-- Progress Bar (only for uploading files) -->\n @if (file.stage === 'uploading' && file.percentage !== undefined) {\n <div class=\"file-progress\">\n <div class=\"progress-bar\">\n <div class=\"progress-fill\" [style.width.%]=\"file.percentage\"></div>\n </div>\n <span class=\"progress-text\">{{ file.percentage }}%</span>\n </div>\n }\n\n <!-- Actions -->\n <div class=\"upload-actions\">\n @switch (file.stage) {\n @case ('pending') {\n <button class=\"action-btn cancel-btn\" (click)=\"cancelUpload(file.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('reading') {\n <button class=\"action-btn cancel-btn\" (click)=\"cancelUpload(file.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('uploading') {\n <button class=\"action-btn cancel-btn\" (click)=\"cancelUpload(file.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('complete') {\n <button class=\"action-btn success-btn\" title=\"Completed\">\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\n </button>\n }\n @case ('error') {\n <button class=\"action-btn retry-btn\" title=\"Retry\">\n <cide-ele-icon size=\"xs\">refresh</cide-ele-icon>\n </button>\n }\n }\n </div>\n </div>\n }\n </div>\n } @else {\n <!-- No uploads message when manually opened -->\n <div class=\"no-uploads-message\">\n <div class=\"message-content\">\n <cide-ele-icon size=\"md\" class=\"message-icon\">cloud_upload</cide-ele-icon>\n <div class=\"message-text\">\n <h4>No active uploads</h4>\n <p>Upload files to see their progress here</p>\n </div>\n </div>\n </div>\n }\n </div>\n</div>\n}\n", styles: [".floating-uploader{position:fixed;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.draggable-header{cursor:move;-webkit-user-select:none;user-select:none}.floating-uploader .uploader-header.draggable-header:hover{background:#f1f5f9}.floating-uploader .uploader-header.draggable-header:active{background:#e2e8f0;cursor:grabbing}.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 .upload-zone{margin:8px 16px;padding:12px;border:2px dashed #d1d5db;border-radius:6px;background:#f9fafb;cursor:pointer;transition:all .2s ease;text-align:center}.floating-uploader .uploader-content .upload-zone:hover{border-color:#3b82f6;background:#f0f9ff}.floating-uploader .uploader-content .upload-zone.drag-over{border-color:#3b82f6;background:#dbeafe;transform:scale(1.01)}.floating-uploader .uploader-content .upload-zone .upload-zone-content{display:flex;flex-direction:column;align-items:center;gap:6px}.floating-uploader .uploader-content .upload-zone .upload-zone-content .upload-icon{color:#6b7280;transition:color .2s ease}.floating-uploader .uploader-content .upload-zone .upload-zone-content .upload-text .upload-title{font-size:13px;font-weight:500;color:#374151;margin:0;line-height:1.2}.floating-uploader .uploader-content .upload-zone:hover .upload-zone-content .upload-icon{color:#3b82f6}.floating-uploader .uploader-content .upload-zone.drag-over .upload-zone-content .upload-icon{color:#1d4ed8}.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.draggable-header:hover{background:#475569}.floating-uploader .uploader-header.draggable-header:active{background:#64748b}.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 .upload-zone{border-color:#475569;background:#334155}.floating-uploader .uploader-content .upload-zone:hover{border-color:#3b82f6;background:#1e3a8a}.floating-uploader .uploader-content .upload-zone.drag-over{border-color:#60a5fa;background:#1e40af}.floating-uploader .uploader-content .upload-zone .upload-zone-content .upload-icon{color:#94a3b8}.floating-uploader .uploader-content .upload-zone .upload-zone-content .upload-text .upload-title{color:#f1f5f9}.floating-uploader .uploader-content .upload-zone:hover .upload-zone-content .upload-icon{color:#60a5fa}.floating-uploader .uploader-content .upload-zone.drag-over .upload-zone-content .upload-icon{color:#93c5fd}.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"] }] });
5422
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideEleFloatingFileUploaderComponent, isStandalone: true, selector: "cide-ele-floating-file-uploader", inputs: { data: "data" }, ngImport: i0, template: "<!-- File Uploader Content (No absolute positioning - works within floating container) -->\n@if (isVisible()) {\n<div class=\"tw-w-full tw-max-h-[500px] tw-bg-white tw-rounded-xl tw-shadow-lg tw-border tw-border-gray-200 tw-overflow-hidden tw-transition-all tw-duration-300\">\n <!-- Simple header without window controls (floating container handles these) -->\n <div class=\"tw-flex tw-items-center tw-justify-between tw-px-4 tw-py-3 tw-bg-gray-50 tw-border-b tw-border-gray-200\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <div class=\"tw-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-bg-blue-600 tw-rounded-md tw-text-white\">\n <cide-ele-icon size=\"sm\">cloud_upload</cide-ele-icon>\n </div>\n <div>\n <div class=\"tw-text-sm tw-font-semibold tw-text-gray-900\">{{ data.title || 'File Upload' }}</div>\n <div class=\"tw-text-xs tw-text-gray-500\">{{ getUploadSummary() }}</div>\n </div>\n </div>\n </div>\n\n <!-- Content -->\n <div class=\"tw-max-h-[400px] tw-overflow-y-auto\">\n \n <!-- Drag and Drop Zone -->\n <div class=\"tw-m-2 tw-p-3 tw-border-2 tw-border-dashed tw-border-gray-300 tw-rounded-md tw-bg-gray-50 tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-center hover:tw-border-blue-500 hover:tw-bg-blue-50\" \n [class.tw-border-blue-500]=\"isDragOver()\"\n [class.tw-bg-blue-100]=\"isDragOver()\"\n [class.tw-scale-105]=\"isDragOver()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\" \n (drop)=\"onDrop($event)\" \n (click)=\"triggerFileInput()\">\n \n <!-- Hidden file input -->\n <input #fileInput \n type=\"file\" \n [multiple]=\"data.multiple !== false\" \n [accept]=\"data.allowedFileTypes?.join(',') || '*/*'\" \n (change)=\"onFileInputChange($event)\" \n class=\"tw-hidden\">\n \n <div class=\"tw-flex tw-flex-col tw-items-center tw-gap-2\">\n <cide-ele-icon class=\"tw-text-gray-400 tw-transition-colors tw-duration-200\" \n [class.tw-text-blue-500]=\"isDragOver()\"\n size=\"sm\">cloud_upload</cide-ele-icon>\n \n <div>\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-700\">\n {{ isDragOver() ? 'Drop files here' : 'Drag files here or click to browse' }}\n </div>\n @if (data.description) {\n <div class=\"tw-text-xs tw-text-gray-500 tw-mt-1\">{{ data.description }}</div>\n }\n </div>\n </div>\n </div>\n \n <!-- Upload Queue - Show files from service state -->\n @if (allFilesForGroup().length > 0) {\n <div class=\"tw-space-y-0\">\n <!-- Show all files from service state -->\n @for (file of allFilesForGroup(); track file.fileId) {\n <div class=\"tw-flex tw-items-center tw-px-4 tw-py-2 tw-border-b tw-border-gray-100 tw-transition-colors tw-duration-200\"\n [class.tw-bg-blue-50]=\"file.stage === 'uploading'\"\n [class.tw-bg-green-50]=\"file.stage === 'complete'\"\n [class.tw-bg-red-50]=\"file.stage === 'error'\">\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-flex-1 tw-min-w-0\">\n <cide-ele-icon class=\"tw-flex-shrink-0\" size=\"xs\">{{ getStatusIcon(file.stage) }}</cide-ele-icon>\n <div class=\"tw-min-w-0 tw-flex-1\">\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\">{{ file.fileName }}</div>\n <div class=\"tw-text-xs\">\n @switch (file.stage) {\n @case ('pending') {\n <span class=\"tw-text-yellow-600 tw-font-medium\">Waiting...</span>\n }\n @case ('reading') {\n <span class=\"tw-text-yellow-600 tw-font-medium\">Reading...</span>\n }\n @case ('uploading') {\n <span class=\"tw-text-blue-600 tw-font-medium\">Uploading...</span>\n }\n @case ('complete') {\n <span class=\"tw-text-green-600 tw-font-medium\">Completed</span>\n }\n @case ('error') {\n <span class=\"tw-text-red-600 tw-font-medium\">Failed</span>\n }\n }\n </div>\n </div>\n </div>\n\n <!-- Progress Bar (only for uploading files) -->\n @if (file.stage === 'uploading' && file.percentage !== undefined) {\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-ml-2 tw-min-w-[80px]\">\n <div class=\"tw-flex-1 tw-h-1 tw-bg-gray-200 tw-rounded-full tw-overflow-hidden\">\n <div class=\"tw-h-full tw-bg-blue-500 tw-transition-all tw-duration-300\" [style.width.%]=\"file.percentage\"></div>\n </div>\n <span class=\"tw-text-xs tw-text-gray-500 tw-min-w-[24px] tw-text-right\">{{ file.percentage }}%</span>\n </div>\n }\n\n <!-- Actions -->\n <div class=\"tw-flex tw-gap-1 tw-ml-2\">\n @switch (file.stage) {\n @case ('pending') {\n <button class=\"tw-flex tw-items-center tw-justify-center tw-w-5 tw-h-5 tw-border-none tw-bg-transparent tw-rounded tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-gray-400 hover:tw-bg-red-50 hover:tw-text-red-600\" \n (click)=\"cancelUpload(file.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('reading') {\n <button class=\"tw-flex tw-items-center tw-justify-center tw-w-5 tw-h-5 tw-border-none tw-bg-transparent tw-rounded tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-gray-400 hover:tw-bg-red-50 hover:tw-text-red-600\" \n (click)=\"cancelUpload(file.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('uploading') {\n <button class=\"tw-flex tw-items-center tw-justify-center tw-w-5 tw-h-5 tw-border-none tw-bg-transparent tw-rounded tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-gray-400 hover:tw-bg-red-50 hover:tw-text-red-600\" \n (click)=\"cancelUpload(file.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('complete') {\n <button class=\"tw-flex tw-items-center tw-justify-center tw-w-5 tw-h-5 tw-border-none tw-bg-transparent tw-rounded tw-cursor-pointer tw-text-green-600\" title=\"Completed\">\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\n </button>\n }\n @case ('error') {\n <button class=\"tw-flex tw-items-center tw-justify-center tw-w-5 tw-h-5 tw-border-none tw-bg-transparent tw-rounded tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-gray-400 hover:tw-bg-blue-50 hover:tw-text-blue-600\" \n title=\"Retry\">\n <cide-ele-icon size=\"xs\">refresh</cide-ele-icon>\n </button>\n }\n }\n </div>\n </div>\n }\n </div>\n } @else {\n <!-- No uploads message when manually opened -->\n <div class=\"tw-p-8 tw-text-center tw-text-gray-500\">\n <div class=\"tw-flex tw-flex-col tw-items-center tw-gap-4\">\n <cide-ele-icon size=\"md\" class=\"tw-text-gray-300 tw-opacity-70\">cloud_upload</cide-ele-icon>\n <div>\n <h4 class=\"tw-text-lg tw-font-semibold tw-text-gray-700 tw-mb-2\">No active uploads</h4>\n <p class=\"tw-text-sm tw-text-gray-500\">Upload files to see their progress here</p>\n </div>\n </div>\n </div>\n }\n </div>\n\n <!-- Footer -->\n <div class=\"tw-px-4 tw-py-2 tw-bg-gray-50 tw-border-t tw-border-gray-200\">\n <div class=\"tw-flex tw-gap-3 tw-text-xs\">\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-blue-600\" \n [class.tw-text-blue-600]=\"hasActiveUploads()\">\n <cide-ele-icon size=\"xs\">upload</cide-ele-icon>\n <span>{{ getUploadingCount() }} uploading</span>\n </div>\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-green-600\">\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\n <span>{{ getCompletedCount() }} completed</span>\n </div>\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-red-600\" \n [class.tw-text-red-600]=\"getFailedCount() > 0\">\n <cide-ele-icon size=\"xs\">error</cide-ele-icon>\n <span>{{ getFailedCount() }} failed</span>\n </div>\n </div>\n </div>\n</div>\n}", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }] });
5413
5423
  }
5414
5424
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingFileUploaderComponent, decorators: [{
5415
5425
  type: Component,
5416
5426
  args: [{ selector: 'cide-ele-floating-file-uploader', standalone: true, imports: [
5417
5427
  CommonModule,
5418
5428
  CideIconComponent
5419
- ], template: "<!-- File Uploader Content (No absolute positioning - works within floating container) -->\n@if (isVisible()) {\n<div class=\"file-uploader-content\">\n <!-- Simple header without window controls (floating container handles these) -->\n <div class=\"uploader-header\">\n <div class=\"upload-icon\">\n <cide-ele-icon size=\"sm\">cloud_upload</cide-ele-icon>\n </div>\n <div class=\"upload-info\">\n <div class=\"upload-title\">File Upload</div>\n <div class=\"upload-summary\">{{ getUploadSummary() }}</div>\n </div>\n </div>\n\n <!-- Content -->\n <div class=\"uploader-content\">\n \n <!-- Drag and Drop Zone -->\n <div class=\"upload-zone\" \n [class.drag-over]=\"isDragOver()\" \n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\" \n (drop)=\"onDrop($event)\" \n (click)=\"triggerFileInput()\">\n \n <!-- Hidden file input -->\n <input #fileInput \n type=\"file\" \n [multiple]=\"true\" \n [accept]=\"'*/*'\" \n (change)=\"onFileInputChange($event)\" \n style=\"display: none;\">\n \n <div class=\"upload-zone-content\">\n <cide-ele-icon class=\"upload-icon\" size=\"sm\">cloud_upload</cide-ele-icon>\n \n <div class=\"upload-text\">\n <div class=\"upload-title\">\n {{ isDragOver() ? 'Drop files here' : 'Drag files here or click to browse' }}\n </div>\n </div>\n </div>\n </div>\n \n <!-- Upload Queue - Show files from service state -->\n @if (allFilesForGroup().length > 0) {\n <div class=\"upload-queue\">\n <!-- Show all files from service state -->\n @for (file of allFilesForGroup(); track file.fileId) {\n <div class=\"upload-item\" [class]=\"getStatusClass(file.stage)\">\n <div class=\"file-info\">\n <cide-ele-icon class=\"status-icon\" size=\"xs\">{{ getStatusIcon(file.stage) }}</cide-ele-icon>\n <div class=\"file-details\">\n <div class=\"file-name\">{{ file.fileName }}</div>\n <div class=\"file-status\">\n @switch (file.stage) {\n @case ('pending') {\n <span class=\"text-yellow-600\">Waiting...</span>\n }\n @case ('reading') {\n <span class=\"text-yellow-600\">Reading...</span>\n }\n @case ('uploading') {\n <span class=\"text-blue-600\">Uploading...</span>\n }\n @case ('complete') {\n <span class=\"text-green-600\">Completed</span>\n }\n @case ('error') {\n <span class=\"text-red-600\">Failed</span>\n }\n }\n </div>\n </div>\n </div>\n\n <!-- Progress Bar (only for uploading files) -->\n @if (file.stage === 'uploading' && file.percentage !== undefined) {\n <div class=\"file-progress\">\n <div class=\"progress-bar\">\n <div class=\"progress-fill\" [style.width.%]=\"file.percentage\"></div>\n </div>\n <span class=\"progress-text\">{{ file.percentage }}%</span>\n </div>\n }\n\n <!-- Actions -->\n <div class=\"upload-actions\">\n @switch (file.stage) {\n @case ('pending') {\n <button class=\"action-btn cancel-btn\" (click)=\"cancelUpload(file.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('reading') {\n <button class=\"action-btn cancel-btn\" (click)=\"cancelUpload(file.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('uploading') {\n <button class=\"action-btn cancel-btn\" (click)=\"cancelUpload(file.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('complete') {\n <button class=\"action-btn success-btn\" title=\"Completed\">\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\n </button>\n }\n @case ('error') {\n <button class=\"action-btn retry-btn\" title=\"Retry\">\n <cide-ele-icon size=\"xs\">refresh</cide-ele-icon>\n </button>\n }\n }\n </div>\n </div>\n }\n </div>\n } @else {\n <!-- No uploads message when manually opened -->\n <div class=\"no-uploads-message\">\n <div class=\"message-content\">\n <cide-ele-icon size=\"md\" class=\"message-icon\">cloud_upload</cide-ele-icon>\n <div class=\"message-text\">\n <h4>No active uploads</h4>\n <p>Upload files to see their progress here</p>\n </div>\n </div>\n </div>\n }\n </div>\n</div>\n}\n", styles: [".floating-uploader{position:fixed;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.draggable-header{cursor:move;-webkit-user-select:none;user-select:none}.floating-uploader .uploader-header.draggable-header:hover{background:#f1f5f9}.floating-uploader .uploader-header.draggable-header:active{background:#e2e8f0;cursor:grabbing}.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 .upload-zone{margin:8px 16px;padding:12px;border:2px dashed #d1d5db;border-radius:6px;background:#f9fafb;cursor:pointer;transition:all .2s ease;text-align:center}.floating-uploader .uploader-content .upload-zone:hover{border-color:#3b82f6;background:#f0f9ff}.floating-uploader .uploader-content .upload-zone.drag-over{border-color:#3b82f6;background:#dbeafe;transform:scale(1.01)}.floating-uploader .uploader-content .upload-zone .upload-zone-content{display:flex;flex-direction:column;align-items:center;gap:6px}.floating-uploader .uploader-content .upload-zone .upload-zone-content .upload-icon{color:#6b7280;transition:color .2s ease}.floating-uploader .uploader-content .upload-zone .upload-zone-content .upload-text .upload-title{font-size:13px;font-weight:500;color:#374151;margin:0;line-height:1.2}.floating-uploader .uploader-content .upload-zone:hover .upload-zone-content .upload-icon{color:#3b82f6}.floating-uploader .uploader-content .upload-zone.drag-over .upload-zone-content .upload-icon{color:#1d4ed8}.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.draggable-header:hover{background:#475569}.floating-uploader .uploader-header.draggable-header:active{background:#64748b}.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 .upload-zone{border-color:#475569;background:#334155}.floating-uploader .uploader-content .upload-zone:hover{border-color:#3b82f6;background:#1e3a8a}.floating-uploader .uploader-content .upload-zone.drag-over{border-color:#60a5fa;background:#1e40af}.floating-uploader .uploader-content .upload-zone .upload-zone-content .upload-icon{color:#94a3b8}.floating-uploader .uploader-content .upload-zone .upload-zone-content .upload-text .upload-title{color:#f1f5f9}.floating-uploader .uploader-content .upload-zone:hover .upload-zone-content .upload-icon{color:#60a5fa}.floating-uploader .uploader-content .upload-zone.drag-over .upload-zone-content .upload-icon{color:#93c5fd}.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"] }]
5429
+ ], template: "<!-- File Uploader Content (No absolute positioning - works within floating container) -->\n@if (isVisible()) {\n<div class=\"tw-w-full tw-max-h-[500px] tw-bg-white tw-rounded-xl tw-shadow-lg tw-border tw-border-gray-200 tw-overflow-hidden tw-transition-all tw-duration-300\">\n <!-- Simple header without window controls (floating container handles these) -->\n <div class=\"tw-flex tw-items-center tw-justify-between tw-px-4 tw-py-3 tw-bg-gray-50 tw-border-b tw-border-gray-200\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <div class=\"tw-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-bg-blue-600 tw-rounded-md tw-text-white\">\n <cide-ele-icon size=\"sm\">cloud_upload</cide-ele-icon>\n </div>\n <div>\n <div class=\"tw-text-sm tw-font-semibold tw-text-gray-900\">{{ data.title || 'File Upload' }}</div>\n <div class=\"tw-text-xs tw-text-gray-500\">{{ getUploadSummary() }}</div>\n </div>\n </div>\n </div>\n\n <!-- Content -->\n <div class=\"tw-max-h-[400px] tw-overflow-y-auto\">\n \n <!-- Drag and Drop Zone -->\n <div class=\"tw-m-2 tw-p-3 tw-border-2 tw-border-dashed tw-border-gray-300 tw-rounded-md tw-bg-gray-50 tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-center hover:tw-border-blue-500 hover:tw-bg-blue-50\" \n [class.tw-border-blue-500]=\"isDragOver()\"\n [class.tw-bg-blue-100]=\"isDragOver()\"\n [class.tw-scale-105]=\"isDragOver()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\" \n (drop)=\"onDrop($event)\" \n (click)=\"triggerFileInput()\">\n \n <!-- Hidden file input -->\n <input #fileInput \n type=\"file\" \n [multiple]=\"data.multiple !== false\" \n [accept]=\"data.allowedFileTypes?.join(',') || '*/*'\" \n (change)=\"onFileInputChange($event)\" \n class=\"tw-hidden\">\n \n <div class=\"tw-flex tw-flex-col tw-items-center tw-gap-2\">\n <cide-ele-icon class=\"tw-text-gray-400 tw-transition-colors tw-duration-200\" \n [class.tw-text-blue-500]=\"isDragOver()\"\n size=\"sm\">cloud_upload</cide-ele-icon>\n \n <div>\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-700\">\n {{ isDragOver() ? 'Drop files here' : 'Drag files here or click to browse' }}\n </div>\n @if (data.description) {\n <div class=\"tw-text-xs tw-text-gray-500 tw-mt-1\">{{ data.description }}</div>\n }\n </div>\n </div>\n </div>\n \n <!-- Upload Queue - Show files from service state -->\n @if (allFilesForGroup().length > 0) {\n <div class=\"tw-space-y-0\">\n <!-- Show all files from service state -->\n @for (file of allFilesForGroup(); track file.fileId) {\n <div class=\"tw-flex tw-items-center tw-px-4 tw-py-2 tw-border-b tw-border-gray-100 tw-transition-colors tw-duration-200\"\n [class.tw-bg-blue-50]=\"file.stage === 'uploading'\"\n [class.tw-bg-green-50]=\"file.stage === 'complete'\"\n [class.tw-bg-red-50]=\"file.stage === 'error'\">\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-flex-1 tw-min-w-0\">\n <cide-ele-icon class=\"tw-flex-shrink-0\" size=\"xs\">{{ getStatusIcon(file.stage) }}</cide-ele-icon>\n <div class=\"tw-min-w-0 tw-flex-1\">\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\">{{ file.fileName }}</div>\n <div class=\"tw-text-xs\">\n @switch (file.stage) {\n @case ('pending') {\n <span class=\"tw-text-yellow-600 tw-font-medium\">Waiting...</span>\n }\n @case ('reading') {\n <span class=\"tw-text-yellow-600 tw-font-medium\">Reading...</span>\n }\n @case ('uploading') {\n <span class=\"tw-text-blue-600 tw-font-medium\">Uploading...</span>\n }\n @case ('complete') {\n <span class=\"tw-text-green-600 tw-font-medium\">Completed</span>\n }\n @case ('error') {\n <span class=\"tw-text-red-600 tw-font-medium\">Failed</span>\n }\n }\n </div>\n </div>\n </div>\n\n <!-- Progress Bar (only for uploading files) -->\n @if (file.stage === 'uploading' && file.percentage !== undefined) {\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-ml-2 tw-min-w-[80px]\">\n <div class=\"tw-flex-1 tw-h-1 tw-bg-gray-200 tw-rounded-full tw-overflow-hidden\">\n <div class=\"tw-h-full tw-bg-blue-500 tw-transition-all tw-duration-300\" [style.width.%]=\"file.percentage\"></div>\n </div>\n <span class=\"tw-text-xs tw-text-gray-500 tw-min-w-[24px] tw-text-right\">{{ file.percentage }}%</span>\n </div>\n }\n\n <!-- Actions -->\n <div class=\"tw-flex tw-gap-1 tw-ml-2\">\n @switch (file.stage) {\n @case ('pending') {\n <button class=\"tw-flex tw-items-center tw-justify-center tw-w-5 tw-h-5 tw-border-none tw-bg-transparent tw-rounded tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-gray-400 hover:tw-bg-red-50 hover:tw-text-red-600\" \n (click)=\"cancelUpload(file.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('reading') {\n <button class=\"tw-flex tw-items-center tw-justify-center tw-w-5 tw-h-5 tw-border-none tw-bg-transparent tw-rounded tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-gray-400 hover:tw-bg-red-50 hover:tw-text-red-600\" \n (click)=\"cancelUpload(file.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('uploading') {\n <button class=\"tw-flex tw-items-center tw-justify-center tw-w-5 tw-h-5 tw-border-none tw-bg-transparent tw-rounded tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-gray-400 hover:tw-bg-red-50 hover:tw-text-red-600\" \n (click)=\"cancelUpload(file.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('complete') {\n <button class=\"tw-flex tw-items-center tw-justify-center tw-w-5 tw-h-5 tw-border-none tw-bg-transparent tw-rounded tw-cursor-pointer tw-text-green-600\" title=\"Completed\">\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\n </button>\n }\n @case ('error') {\n <button class=\"tw-flex tw-items-center tw-justify-center tw-w-5 tw-h-5 tw-border-none tw-bg-transparent tw-rounded tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-gray-400 hover:tw-bg-blue-50 hover:tw-text-blue-600\" \n title=\"Retry\">\n <cide-ele-icon size=\"xs\">refresh</cide-ele-icon>\n </button>\n }\n }\n </div>\n </div>\n }\n </div>\n } @else {\n <!-- No uploads message when manually opened -->\n <div class=\"tw-p-8 tw-text-center tw-text-gray-500\">\n <div class=\"tw-flex tw-flex-col tw-items-center tw-gap-4\">\n <cide-ele-icon size=\"md\" class=\"tw-text-gray-300 tw-opacity-70\">cloud_upload</cide-ele-icon>\n <div>\n <h4 class=\"tw-text-lg tw-font-semibold tw-text-gray-700 tw-mb-2\">No active uploads</h4>\n <p class=\"tw-text-sm tw-text-gray-500\">Upload files to see their progress here</p>\n </div>\n </div>\n </div>\n }\n </div>\n\n <!-- Footer -->\n <div class=\"tw-px-4 tw-py-2 tw-bg-gray-50 tw-border-t tw-border-gray-200\">\n <div class=\"tw-flex tw-gap-3 tw-text-xs\">\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-blue-600\" \n [class.tw-text-blue-600]=\"hasActiveUploads()\">\n <cide-ele-icon size=\"xs\">upload</cide-ele-icon>\n <span>{{ getUploadingCount() }} uploading</span>\n </div>\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-green-600\">\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\n <span>{{ getCompletedCount() }} completed</span>\n </div>\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-red-600\" \n [class.tw-text-red-600]=\"getFailedCount() > 0\">\n <cide-ele-icon size=\"xs\">error</cide-ele-icon>\n <span>{{ getFailedCount() }} failed</span>\n </div>\n </div>\n </div>\n</div>\n}" }]
5420
5430
  }], ctorParameters: () => [], propDecorators: { data: [{
5421
5431
  type: Input
5422
5432
  }] } });
@@ -5767,477 +5777,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
5767
5777
  }]
5768
5778
  }], ctorParameters: () => [] });
5769
5779
 
5770
- class FloatingContainerShortcutsService {
5771
- keyboardShortcutService = inject(KeyboardShortcutService);
5772
- containerService = inject(CideEleFloatingContainerService);
5773
- // Z-index layers for different container states
5774
- Z_INDEX_LAYERS = {
5775
- HIDDEN: 100, // Hidden containers (behind everything)
5776
- BACKGROUND: 1000, // Background containers
5777
- NORMAL: 2000, // Normal visible containers
5778
- FOCUSED: 3000, // Focused containers
5779
- MODAL: 4000, // Modal containers
5780
- TOOLTIP: 5000 // Tooltips and overlays
5781
- };
5782
- constructor() {
5783
- this.registerDefaultShortcuts();
5784
- }
5785
- /**
5786
- * Register default floating container shortcuts using custom key combinations
5787
- */
5788
- registerDefaultShortcuts() {
5789
- // C + 1: Focus on first container
5790
- this.keyboardShortcutService.register({
5791
- id: 'floating-container-focus-first',
5792
- key: '1',
5793
- ctrlKey: true,
5794
- description: 'Focus on first floating container (C+1)',
5795
- action: () => this.focusFirstContainer(),
5796
- preventDefault: true
5797
- });
5798
- // C + 2: Focus on second container
5799
- this.keyboardShortcutService.register({
5800
- id: 'floating-container-focus-second',
5801
- key: '2',
5802
- ctrlKey: true,
5803
- description: 'Focus on second floating container (C+2)',
5804
- action: () => this.focusContainerByIndex(1),
5805
- preventDefault: true
5806
- });
5807
- // C + 3: Focus on third container
5808
- this.keyboardShortcutService.register({
5809
- id: 'floating-container-focus-third',
5810
- key: '3',
5811
- ctrlKey: true,
5812
- description: 'Focus on third floating container (C+3)',
5813
- action: () => this.focusContainerByIndex(2),
5814
- preventDefault: true
5815
- });
5816
- // C + 4: Focus on fourth container
5817
- this.keyboardShortcutService.register({
5818
- id: 'floating-container-focus-fourth',
5819
- key: '4',
5820
- ctrlKey: true,
5821
- description: 'Focus on fourth floating container (C+4)',
5822
- action: () => this.focusContainerByIndex(3),
5823
- preventDefault: true
5824
- });
5825
- // C + 5: Focus on fifth container
5826
- this.keyboardShortcutService.register({
5827
- id: 'floating-container-focus-fifth',
5828
- key: '5',
5829
- ctrlKey: true,
5830
- description: 'Focus on fifth floating container (C+5)',
5831
- action: () => this.focusContainerByIndex(4),
5832
- preventDefault: true
5833
- });
5834
- // C + N: Cycle to next container
5835
- this.keyboardShortcutService.register({
5836
- id: 'floating-container-cycle-forward',
5837
- key: 'n',
5838
- ctrlKey: true,
5839
- description: 'Cycle forward through floating containers (C+N)',
5840
- action: () => this.cycleToNextContainer(),
5841
- preventDefault: true
5842
- });
5843
- // C + P: Cycle to previous container
5844
- this.keyboardShortcutService.register({
5845
- id: 'floating-container-cycle-backward',
5846
- key: 'p',
5847
- ctrlKey: true,
5848
- description: 'Cycle backward through floating containers (C+P)',
5849
- action: () => this.cycleToPreviousContainer(),
5850
- preventDefault: true
5851
- });
5852
- // C + H: Hide all containers
5853
- this.keyboardShortcutService.register({
5854
- id: 'floating-container-hide-all',
5855
- key: 'h',
5856
- ctrlKey: true,
5857
- description: 'Hide all floating containers (C+H)',
5858
- action: () => this.hideAllContainers(),
5859
- preventDefault: true
5860
- });
5861
- // C + M: Minimize all containers
5862
- this.keyboardShortcutService.register({
5863
- id: 'floating-container-minimize-all',
5864
- key: 'm',
5865
- ctrlKey: true,
5866
- description: 'Minimize all floating containers (C+M)',
5867
- action: () => this.minimizeAllContainers(),
5868
- preventDefault: true
5869
- });
5870
- // C + O: Open file uploader
5871
- this.keyboardShortcutService.register({
5872
- id: 'floating-container-open-file-uploader',
5873
- key: 'o',
5874
- ctrlKey: true,
5875
- description: 'Open file uploader (C+O)',
5876
- action: () => this.openFileUploader(),
5877
- preventDefault: true
5878
- });
5879
- // C + R: Open entity rights sharing
5880
- this.keyboardShortcutService.register({
5881
- id: 'floating-container-open-entity-rights',
5882
- key: 'r',
5883
- ctrlKey: true,
5884
- description: 'Open entity rights sharing (C+R)',
5885
- action: () => this.openEntityRightsSharing(),
5886
- preventDefault: true
5887
- });
5888
- // C + S: Show all containers
5889
- this.keyboardShortcutService.register({
5890
- id: 'floating-container-show-all',
5891
- key: 's',
5892
- ctrlKey: true,
5893
- description: 'Show all floating containers (C+S)',
5894
- action: () => this.showAllContainers(),
5895
- preventDefault: true
5896
- });
5897
- // C + D: Duplicate current container
5898
- this.keyboardShortcutService.register({
5899
- id: 'floating-container-duplicate',
5900
- key: 'd',
5901
- ctrlKey: true,
5902
- description: 'Duplicate current container (C+D)',
5903
- action: () => this.duplicateCurrentContainer(),
5904
- preventDefault: true
5905
- });
5906
- // C + W: Close current container
5907
- this.keyboardShortcutService.register({
5908
- id: 'floating-container-close-current',
5909
- key: 'w',
5910
- ctrlKey: true,
5911
- description: 'Close current container (C+W)',
5912
- action: () => this.closeCurrentContainer(),
5913
- preventDefault: true
5914
- });
5915
- // C + T: Toggle container visibility
5916
- this.keyboardShortcutService.register({
5917
- id: 'floating-container-toggle-visibility',
5918
- key: 't',
5919
- ctrlKey: true,
5920
- description: 'Toggle container visibility (C+T)',
5921
- action: () => this.toggleContainerVisibility(),
5922
- preventDefault: true
5923
- });
5924
- console.log('🎯 [FloatingContainerShortcuts] Custom shortcuts registered (C+1, C+2, C+O, etc.)');
5925
- }
5926
- /**
5927
- * Override a floating container shortcut
5928
- */
5929
- overrideShortcut(shortcutId, newKey, options) {
5930
- this.keyboardShortcutService.override(shortcutId, newKey, options);
5931
- }
5932
- /**
5933
- * Add a custom floating container shortcut
5934
- */
5935
- addCustomShortcut(shortcut) {
5936
- this.keyboardShortcutService.register({
5937
- ...shortcut,
5938
- preventDefault: true
5939
- });
5940
- }
5941
- /**
5942
- * Remove a floating container shortcut
5943
- */
5944
- removeShortcut(shortcutId) {
5945
- this.keyboardShortcutService.unregister(shortcutId);
5946
- }
5947
- /**
5948
- * Get all floating container shortcuts
5949
- */
5950
- getShortcuts() {
5951
- return this.keyboardShortcutService.getShortcuts(shortcut => shortcut.id.startsWith('floating-container-'));
5952
- }
5953
- // Action methods
5954
- cycleToNextContainer() {
5955
- const visibleContainers = this.containerService.visibleContainers();
5956
- if (visibleContainers.length === 0)
5957
- return;
5958
- // Sort by last accessed time (most recent first)
5959
- const sortedContainers = visibleContainers.sort((a, b) => b.lastAccessed.getTime() - a.lastAccessed.getTime());
5960
- // Find current front container
5961
- const currentFront = sortedContainers[0];
5962
- const currentIndex = sortedContainers.findIndex(c => c.id === currentFront.id);
5963
- // Get next container (wrap around)
5964
- const nextIndex = (currentIndex + 1) % sortedContainers.length;
5965
- const nextContainer = sortedContainers[nextIndex];
5966
- this.containerService.bringToFront(nextContainer.id);
5967
- console.log(`🔄 [FloatingContainerShortcuts] Cycled to container: ${nextContainer.config.title}`);
5968
- }
5969
- cycleToPreviousContainer() {
5970
- const visibleContainers = this.containerService.visibleContainers();
5971
- if (visibleContainers.length === 0)
5972
- return;
5973
- // Sort by last accessed time (most recent first)
5974
- const sortedContainers = visibleContainers.sort((a, b) => b.lastAccessed.getTime() - a.lastAccessed.getTime());
5975
- // Find current front container
5976
- const currentFront = sortedContainers[0];
5977
- const currentIndex = sortedContainers.findIndex(c => c.id === currentFront.id);
5978
- // Get previous container (wrap around)
5979
- const prevIndex = currentIndex === 0 ? sortedContainers.length - 1 : currentIndex - 1;
5980
- const prevContainer = sortedContainers[prevIndex];
5981
- this.containerService.bringToFront(prevContainer.id);
5982
- console.log(`🔄 [FloatingContainerShortcuts] Cycled backwards to container: ${prevContainer.config.title}`);
5983
- }
5984
- hideAllContainers() {
5985
- const visibleContainers = this.containerService.visibleContainers();
5986
- visibleContainers.forEach(container => {
5987
- this.containerService.setZIndex(container.id, this.Z_INDEX_LAYERS.HIDDEN);
5988
- });
5989
- console.log(`👁️ [FloatingContainerShortcuts] All containers moved to hidden layer (z-index: ${this.Z_INDEX_LAYERS.HIDDEN})`);
5990
- }
5991
- focusFirstContainer() {
5992
- const visibleContainers = this.containerService.visibleContainers();
5993
- if (visibleContainers.length === 0)
5994
- return;
5995
- const firstContainer = visibleContainers[0];
5996
- this.containerService.bringToFront(firstContainer.id);
5997
- console.log(`🎯 [FloatingContainerShortcuts] Focused on first container: ${firstContainer.config.title}`);
5998
- }
5999
- minimizeAllContainers() {
6000
- this.containerService.minimizeAll();
6001
- console.log(`📦 [FloatingContainerShortcuts] All containers minimized`);
6002
- }
6003
- focusContainerByIndex(index) {
6004
- const visibleContainers = this.containerService.visibleContainers();
6005
- if (visibleContainers.length === 0 || index >= visibleContainers.length) {
6006
- console.log(`⚠️ [FloatingContainerShortcuts] No container at index ${index}`);
6007
- return;
6008
- }
6009
- const container = visibleContainers[index];
6010
- this.containerService.bringToFront(container.id);
6011
- console.log(`🎯 [FloatingContainerShortcuts] Focused on container ${index + 1}: ${container.config.title}`);
6012
- }
6013
- openFileUploader() {
6014
- console.log(`📁 [FloatingContainerShortcuts] Opening file uploader...`);
6015
- // This would need to be implemented based on your file uploader service
6016
- // Example: this.fileUploaderService.show();
6017
- }
6018
- openEntityRightsSharing() {
6019
- console.log(`🔐 [FloatingContainerShortcuts] Opening entity rights sharing...`);
6020
- // This would need to be implemented based on your entity rights service
6021
- // Example: this.entityRightsService.show();
6022
- }
6023
- showAllContainers() {
6024
- const visibleContainers = this.containerService.visibleContainers();
6025
- visibleContainers.forEach((container, index) => {
6026
- // Give each container a slightly different z-index to maintain order
6027
- const zIndex = this.Z_INDEX_LAYERS.NORMAL + index;
6028
- this.containerService.setZIndex(container.id, zIndex);
6029
- });
6030
- console.log(`👁️ [FloatingContainerShortcuts] All containers moved to normal layer (z-index: ${this.Z_INDEX_LAYERS.NORMAL}+)`);
6031
- }
6032
- duplicateCurrentContainer() {
6033
- const visibleContainers = this.containerService.visibleContainers();
6034
- if (visibleContainers.length === 0) {
6035
- console.log(`⚠️ [FloatingContainerShortcuts] No containers to duplicate`);
6036
- return;
6037
- }
6038
- const currentContainer = visibleContainers[0]; // Most recent container
6039
- console.log(`📋 [FloatingContainerShortcuts] Duplicating container: ${currentContainer.config.title}`);
6040
- // This would need to be implemented based on your container duplication logic
6041
- }
6042
- closeCurrentContainer() {
6043
- const visibleContainers = this.containerService.visibleContainers();
6044
- if (visibleContainers.length === 0) {
6045
- console.log(`⚠️ [FloatingContainerShortcuts] No containers to close`);
6046
- return;
6047
- }
6048
- const currentContainer = visibleContainers[0]; // Most recent container
6049
- this.containerService.hide(currentContainer.id);
6050
- console.log(`❌ [FloatingContainerShortcuts] Closed container: ${currentContainer.config.title}`);
6051
- }
6052
- toggleContainerVisibility() {
6053
- const visibleContainers = this.containerService.visibleContainers();
6054
- if (visibleContainers.length === 0) {
6055
- console.log(`⚠️ [FloatingContainerShortcuts] No containers to toggle`);
6056
- return;
6057
- }
6058
- // Toggle visibility of the most recent container using z-index
6059
- const currentContainer = visibleContainers[0];
6060
- const currentZIndex = currentContainer.zIndex;
6061
- if (currentZIndex >= this.Z_INDEX_LAYERS.NORMAL) {
6062
- // Container is visible, move to hidden layer
6063
- this.containerService.setZIndex(currentContainer.id, this.Z_INDEX_LAYERS.HIDDEN);
6064
- console.log(`👁️ [FloatingContainerShortcuts] Hidden container (z-index: ${this.Z_INDEX_LAYERS.HIDDEN}): ${currentContainer.config.title}`);
6065
- }
6066
- else {
6067
- // Container is hidden, move to normal layer
6068
- this.containerService.setZIndex(currentContainer.id, this.Z_INDEX_LAYERS.NORMAL);
6069
- console.log(`👁️ [FloatingContainerShortcuts] Shown container (z-index: ${this.Z_INDEX_LAYERS.NORMAL}): ${currentContainer.config.title}`);
6070
- }
6071
- }
6072
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: FloatingContainerShortcutsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
6073
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: FloatingContainerShortcutsService, providedIn: 'root' });
6074
- }
6075
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: FloatingContainerShortcutsService, decorators: [{
6076
- type: Injectable,
6077
- args: [{
6078
- providedIn: 'root'
6079
- }]
6080
- }], ctorParameters: () => [] });
6081
-
6082
- class AppShortcutService {
6083
- keyboardShortcutService = inject(KeyboardShortcutService);
6084
- registeredShortcuts = new Map();
6085
- /**
6086
- * Register shortcuts from app component
6087
- * @param shortcuts Array of shortcut configurations
6088
- */
6089
- registerShortcuts(shortcuts) {
6090
- console.log('🎯 [AppShortcut] Registering app shortcuts:', shortcuts.length);
6091
- shortcuts.forEach(config => {
6092
- const shortcutId = `app-${config.eventName}`;
6093
- // Convert AppShortcutConfig to KeyboardShortcut format
6094
- this.keyboardShortcutService.register({
6095
- id: shortcutId,
6096
- key: config.key,
6097
- ctrlKey: config.ctrlKey,
6098
- altKey: config.altKey,
6099
- shiftKey: config.shiftKey,
6100
- metaKey: config.metaKey,
6101
- description: config.description,
6102
- action: () => {
6103
- console.log(`🎯 [AppShortcut] Executing app shortcut: ${config.eventName}`);
6104
- this.executeAppEvent(config.eventName);
6105
- },
6106
- preventDefault: config.preventDefault !== false,
6107
- stopPropagation: config.stopPropagation || false
6108
- });
6109
- // Store the configuration
6110
- this.registeredShortcuts.set(shortcutId, config);
6111
- console.log(`✅ [AppShortcut] Registered shortcut: ${shortcutId} (${this.getKeyDescription(config)})`);
6112
- });
6113
- }
6114
- /**
6115
- * Unregister shortcuts by event names
6116
- * @param eventNames Array of event names to unregister
6117
- */
6118
- unregisterShortcuts(eventNames) {
6119
- console.log('🗑️ [AppShortcut] Unregistering app shortcuts:', eventNames);
6120
- eventNames.forEach(eventName => {
6121
- const shortcutId = `app-${eventName}`;
6122
- if (this.registeredShortcuts.has(shortcutId)) {
6123
- this.keyboardShortcutService.unregister(shortcutId);
6124
- this.registeredShortcuts.delete(shortcutId);
6125
- console.log(`✅ [AppShortcut] Unregistered shortcut: ${shortcutId}`);
6126
- }
6127
- else {
6128
- console.warn(`⚠️ [AppShortcut] Shortcut not found: ${shortcutId}`);
6129
- }
6130
- });
6131
- }
6132
- /**
6133
- * Get all registered app shortcuts
6134
- */
6135
- getRegisteredShortcuts() {
6136
- return Array.from(this.registeredShortcuts.values());
6137
- }
6138
- /**
6139
- * Check if a shortcut is registered
6140
- * @param eventName Event name to check
6141
- */
6142
- isShortcutRegistered(eventName) {
6143
- const shortcutId = `app-${eventName}`;
6144
- return this.registeredShortcuts.has(shortcutId);
6145
- }
6146
- /**
6147
- * Update an existing shortcut
6148
- * @param eventName Event name to update
6149
- * @param newConfig New shortcut configuration
6150
- */
6151
- updateShortcut(eventName, newConfig) {
6152
- const shortcutId = `app-${eventName}`;
6153
- if (this.registeredShortcuts.has(shortcutId)) {
6154
- // Unregister old shortcut
6155
- this.keyboardShortcutService.unregister(shortcutId);
6156
- // Register new shortcut
6157
- this.keyboardShortcutService.register({
6158
- id: shortcutId,
6159
- key: newConfig.key,
6160
- ctrlKey: newConfig.ctrlKey,
6161
- altKey: newConfig.altKey,
6162
- shiftKey: newConfig.shiftKey,
6163
- metaKey: newConfig.metaKey,
6164
- description: newConfig.description,
6165
- action: () => {
6166
- console.log(`🎯 [AppShortcut] Executing updated app shortcut: ${eventName}`);
6167
- this.executeAppEvent(eventName);
6168
- },
6169
- preventDefault: newConfig.preventDefault !== false,
6170
- stopPropagation: newConfig.stopPropagation || false
6171
- });
6172
- // Update stored configuration
6173
- this.registeredShortcuts.set(shortcutId, newConfig);
6174
- console.log(`🔄 [AppShortcut] Updated shortcut: ${shortcutId}`);
6175
- }
6176
- else {
6177
- console.warn(`⚠️ [AppShortcut] Shortcut not found for update: ${shortcutId}`);
6178
- }
6179
- }
6180
- /**
6181
- * Clear all app shortcuts
6182
- */
6183
- clearAllShortcuts() {
6184
- console.log('🧹 [AppShortcut] Clearing all app shortcuts');
6185
- const shortcutIds = Array.from(this.registeredShortcuts.keys());
6186
- shortcutIds.forEach(shortcutId => {
6187
- this.keyboardShortcutService.unregister(shortcutId);
6188
- });
6189
- this.registeredShortcuts.clear();
6190
- console.log('✅ [AppShortcut] All app shortcuts cleared');
6191
- }
6192
- /**
6193
- * Get shortcut information for help/documentation
6194
- */
6195
- getShortcutHelp() {
6196
- return Array.from(this.registeredShortcuts.values()).map(config => ({
6197
- eventName: config.eventName,
6198
- description: config.description,
6199
- keys: this.getKeyDescription(config)
6200
- }));
6201
- }
6202
- /**
6203
- * Execute app event (this would be implemented by the app component)
6204
- * @param eventName Name of the event to execute
6205
- */
6206
- executeAppEvent(eventName) {
6207
- // This method should be overridden by the app component
6208
- // or connected to an event emitter system
6209
- console.log(`🎯 [AppShortcut] Executing app event: ${eventName}`);
6210
- // Emit custom event that the app component can listen to
6211
- const customEvent = new CustomEvent('app-shortcut-triggered', {
6212
- detail: { eventName }
6213
- });
6214
- window.dispatchEvent(customEvent);
6215
- }
6216
- /**
6217
- * Get human-readable key description
6218
- */
6219
- getKeyDescription(config) {
6220
- const modifiers = [];
6221
- if (config.ctrlKey)
6222
- modifiers.push('Ctrl');
6223
- if (config.altKey)
6224
- modifiers.push('Alt');
6225
- if (config.shiftKey)
6226
- modifiers.push('Shift');
6227
- if (config.metaKey)
6228
- modifiers.push('Meta');
6229
- return [...modifiers, config.key].join(' + ');
6230
- }
6231
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: AppShortcutService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
6232
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: AppShortcutService, providedIn: 'root' });
6233
- }
6234
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: AppShortcutService, decorators: [{
6235
- type: Injectable,
6236
- args: [{
6237
- providedIn: 'root'
6238
- }]
6239
- }] });
6240
-
6241
5780
  /**
6242
5781
  <!-- Basic horizontal (left-right) layout -->
6243
5782
  <div class="panel-container">
@@ -11074,6 +10613,291 @@ var floatingContainerDynamic_directive = /*#__PURE__*/Object.freeze({
11074
10613
  CideEleFloatingContainerDynamicDirective: CideEleFloatingContainerDynamicDirective
11075
10614
  });
11076
10615
 
10616
+ class FloatingContainerShortcutsService {
10617
+ keyboardShortcutService = inject(KeyboardShortcutService);
10618
+ containerService = inject(CideEleFloatingContainerService);
10619
+ // Z-index layers for different container states
10620
+ Z_INDEX_LAYERS = {
10621
+ HIDDEN: 100, // Hidden containers (behind everything)
10622
+ BACKGROUND: 1000, // Background containers
10623
+ NORMAL: 2000, // Normal visible containers
10624
+ FOCUSED: 3000, // Focused containers
10625
+ MODAL: 4000, // Modal containers
10626
+ TOOLTIP: 5000 // Tooltips and overlays
10627
+ };
10628
+ constructor() {
10629
+ this.registerDefaultShortcuts();
10630
+ }
10631
+ /**
10632
+ * Register default floating container shortcuts
10633
+ */
10634
+ registerDefaultShortcuts() {
10635
+ console.log('🎯 [FloatingContainerShortcuts] Registering default shortcuts');
10636
+ // Alt + 1, Alt + 2, etc. - Focus specific containers
10637
+ this.registerNumberShortcuts();
10638
+ // Alt + N - New container
10639
+ this.keyboardShortcutService.register({
10640
+ id: 'floating-container-new',
10641
+ key: 'n',
10642
+ altKey: true,
10643
+ description: 'Create new floating container',
10644
+ action: () => this.openNewContainer(),
10645
+ preventDefault: true
10646
+ });
10647
+ // Alt + P - Previous container
10648
+ this.keyboardShortcutService.register({
10649
+ id: 'floating-container-previous',
10650
+ key: 'p',
10651
+ altKey: true,
10652
+ description: 'Focus previous container',
10653
+ action: () => this.focusPreviousContainer(),
10654
+ preventDefault: true
10655
+ });
10656
+ // Alt + H - Hide all containers
10657
+ this.keyboardShortcutService.register({
10658
+ id: 'floating-container-hide-all',
10659
+ key: 'h',
10660
+ altKey: true,
10661
+ description: 'Hide all containers',
10662
+ action: () => this.hideAllContainers(),
10663
+ preventDefault: true
10664
+ });
10665
+ // Alt + S - Show all containers
10666
+ this.keyboardShortcutService.register({
10667
+ id: 'floating-container-show-all',
10668
+ key: 's',
10669
+ altKey: true,
10670
+ description: 'Show all containers',
10671
+ action: () => this.showAllContainers(),
10672
+ preventDefault: true
10673
+ });
10674
+ // Alt + M - Minimize all containers
10675
+ this.keyboardShortcutService.register({
10676
+ id: 'floating-container-minimize-all',
10677
+ key: 'm',
10678
+ altKey: true,
10679
+ description: 'Minimize all containers',
10680
+ action: () => this.minimizeAllContainers(),
10681
+ preventDefault: true
10682
+ });
10683
+ // Alt + W - Close current container
10684
+ this.keyboardShortcutService.register({
10685
+ id: 'floating-container-close-current',
10686
+ key: 'w',
10687
+ altKey: true,
10688
+ description: 'Close current container',
10689
+ action: () => this.closeCurrentContainer(),
10690
+ preventDefault: true
10691
+ });
10692
+ // Alt + D - Duplicate current container
10693
+ this.keyboardShortcutService.register({
10694
+ id: 'floating-container-duplicate',
10695
+ key: 'd',
10696
+ altKey: true,
10697
+ description: 'Duplicate current container',
10698
+ action: () => this.duplicateCurrentContainer(),
10699
+ preventDefault: true
10700
+ });
10701
+ // Alt + T - Toggle container visibility
10702
+ this.keyboardShortcutService.register({
10703
+ id: 'floating-container-toggle-visibility',
10704
+ key: 't',
10705
+ altKey: true,
10706
+ description: 'Toggle container visibility',
10707
+ action: () => this.toggleContainerVisibility(),
10708
+ preventDefault: true
10709
+ });
10710
+ // Alt + O - Open file uploader
10711
+ this.keyboardShortcutService.register({
10712
+ id: 'floating-container-open-file-uploader',
10713
+ key: 'o',
10714
+ altKey: true,
10715
+ description: 'Open file uploader',
10716
+ action: () => this.openFileUploader(),
10717
+ preventDefault: true
10718
+ });
10719
+ // Alt + R - Open entity rights sharing
10720
+ this.keyboardShortcutService.register({
10721
+ id: 'floating-container-open-entity-rights',
10722
+ key: 'r',
10723
+ altKey: true,
10724
+ description: 'Open entity rights sharing',
10725
+ action: () => this.openEntityRightsSharing(),
10726
+ preventDefault: true
10727
+ });
10728
+ console.log('✅ [FloatingContainerShortcuts] Default shortcuts registered');
10729
+ }
10730
+ /**
10731
+ * Register number shortcuts (Alt + 1, Alt + 2, etc.)
10732
+ */
10733
+ registerNumberShortcuts() {
10734
+ for (let i = 1; i <= 9; i++) {
10735
+ this.keyboardShortcutService.register({
10736
+ id: `floating-container-focus-${i}`,
10737
+ key: i.toString(),
10738
+ altKey: true,
10739
+ description: `Focus container ${i}`,
10740
+ action: () => this.focusContainerByIndex(i - 1),
10741
+ preventDefault: true
10742
+ });
10743
+ }
10744
+ }
10745
+ /**
10746
+ * Open new floating container
10747
+ */
10748
+ openNewContainer() {
10749
+ console.log('🎯 [FloatingContainerShortcuts] Opening new container');
10750
+ const containerId = this.containerService.show({
10751
+ id: 'new-container-' + Date.now(),
10752
+ title: 'New Container',
10753
+ width: '400px',
10754
+ height: '300px'
10755
+ });
10756
+ console.log('✅ [FloatingContainerShortcuts] New container created:', containerId);
10757
+ }
10758
+ /**
10759
+ * Focus previous container
10760
+ */
10761
+ focusPreviousContainer() {
10762
+ console.log('🎯 [FloatingContainerShortcuts] Focusing previous container');
10763
+ const containers = this.containerService.visibleContainers();
10764
+ if (containers.length > 0) {
10765
+ // For now, just focus the last container
10766
+ const previousIndex = containers.length - 1;
10767
+ this.containerService.bringToFront(containers[previousIndex].id);
10768
+ }
10769
+ }
10770
+ /**
10771
+ * Hide all containers
10772
+ */
10773
+ hideAllContainers() {
10774
+ console.log('🎯 [FloatingContainerShortcuts] Hiding all containers');
10775
+ const containers = this.containerService.visibleContainers();
10776
+ containers.forEach(container => {
10777
+ this.containerService.setZIndex(container.id, this.Z_INDEX_LAYERS.HIDDEN);
10778
+ });
10779
+ console.log('✅ [FloatingContainerShortcuts] All containers hidden');
10780
+ }
10781
+ /**
10782
+ * Show all containers
10783
+ */
10784
+ showAllContainers() {
10785
+ console.log('🎯 [FloatingContainerShortcuts] Showing all containers');
10786
+ const containers = this.containerService.visibleContainers();
10787
+ containers.forEach((container, index) => {
10788
+ this.containerService.setZIndex(container.id, this.Z_INDEX_LAYERS.NORMAL + index);
10789
+ });
10790
+ console.log('✅ [FloatingContainerShortcuts] All containers shown');
10791
+ }
10792
+ /**
10793
+ * Minimize all containers
10794
+ */
10795
+ minimizeAllContainers() {
10796
+ console.log('🎯 [FloatingContainerShortcuts] Minimizing all containers');
10797
+ const containers = this.containerService.visibleContainers();
10798
+ containers.forEach(container => {
10799
+ // Implement minimize logic here
10800
+ console.log('📦 [FloatingContainerShortcuts] Minimizing container:', container.id);
10801
+ });
10802
+ console.log('✅ [FloatingContainerShortcuts] All containers minimized');
10803
+ }
10804
+ /**
10805
+ * Focus container by index
10806
+ */
10807
+ focusContainerByIndex(index) {
10808
+ console.log('🎯 [FloatingContainerShortcuts] Focusing container at index:', index);
10809
+ const containers = this.containerService.visibleContainers();
10810
+ if (containers[index]) {
10811
+ this.containerService.bringToFront(containers[index].id);
10812
+ console.log('✅ [FloatingContainerShortcuts] Container focused:', containers[index].id);
10813
+ }
10814
+ else {
10815
+ console.warn('⚠️ [FloatingContainerShortcuts] Container not found at index:', index);
10816
+ }
10817
+ }
10818
+ /**
10819
+ * Open file uploader
10820
+ */
10821
+ openFileUploader() {
10822
+ console.log('🎯 [FloatingContainerShortcuts] Opening file uploader');
10823
+ // Implement file uploader opening logic here
10824
+ console.log('✅ [FloatingContainerShortcuts] File uploader opened');
10825
+ }
10826
+ /**
10827
+ * Open entity rights sharing
10828
+ */
10829
+ openEntityRightsSharing() {
10830
+ console.log('🎯 [FloatingContainerShortcuts] Opening entity rights sharing');
10831
+ // Implement entity rights sharing opening logic here
10832
+ console.log('✅ [FloatingContainerShortcuts] Entity rights sharing opened');
10833
+ }
10834
+ /**
10835
+ * Duplicate current container
10836
+ */
10837
+ duplicateCurrentContainer() {
10838
+ console.log('🎯 [FloatingContainerShortcuts] Duplicating current container');
10839
+ const containers = this.containerService.visibleContainers();
10840
+ if (containers.length > 0) {
10841
+ const containerToDuplicate = containers[containers.length - 1]; // Use last container
10842
+ const newContainerId = this.containerService.show({
10843
+ id: 'duplicate-' + Date.now(),
10844
+ title: `${containerToDuplicate.config.title} (Copy)`,
10845
+ width: containerToDuplicate.config.width,
10846
+ height: containerToDuplicate.config.height
10847
+ });
10848
+ console.log('✅ [FloatingContainerShortcuts] Container duplicated:', newContainerId);
10849
+ }
10850
+ else {
10851
+ console.warn('⚠️ [FloatingContainerShortcuts] No container to duplicate');
10852
+ }
10853
+ }
10854
+ /**
10855
+ * Close current container
10856
+ */
10857
+ closeCurrentContainer() {
10858
+ console.log('🎯 [FloatingContainerShortcuts] Closing current container');
10859
+ const containers = this.containerService.visibleContainers();
10860
+ if (containers.length > 0) {
10861
+ const containerToClose = containers[containers.length - 1]; // Use last container
10862
+ this.containerService.hide(containerToClose.id);
10863
+ console.log('✅ [FloatingContainerShortcuts] Container closed:', containerToClose.id);
10864
+ }
10865
+ else {
10866
+ console.warn('⚠️ [FloatingContainerShortcuts] No container to close');
10867
+ }
10868
+ }
10869
+ /**
10870
+ * Toggle container visibility
10871
+ */
10872
+ toggleContainerVisibility() {
10873
+ console.log('🎯 [FloatingContainerShortcuts] Toggling container visibility');
10874
+ const containers = this.containerService.visibleContainers();
10875
+ if (containers.length > 0) {
10876
+ const containerToToggle = containers[containers.length - 1]; // Use last container
10877
+ const currentZIndex = this.containerService.getZIndexSignal(containerToToggle.id)();
10878
+ if (currentZIndex === this.Z_INDEX_LAYERS.HIDDEN) {
10879
+ this.containerService.setZIndex(containerToToggle.id, this.Z_INDEX_LAYERS.NORMAL);
10880
+ console.log('✅ [FloatingContainerShortcuts] Container shown:', containerToToggle.id);
10881
+ }
10882
+ else {
10883
+ this.containerService.setZIndex(containerToToggle.id, this.Z_INDEX_LAYERS.HIDDEN);
10884
+ console.log('✅ [FloatingContainerShortcuts] Container hidden:', containerToToggle.id);
10885
+ }
10886
+ }
10887
+ else {
10888
+ console.warn('⚠️ [FloatingContainerShortcuts] No container to toggle');
10889
+ }
10890
+ }
10891
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: FloatingContainerShortcutsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
10892
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: FloatingContainerShortcutsService, providedIn: 'root' });
10893
+ }
10894
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: FloatingContainerShortcutsService, decorators: [{
10895
+ type: Injectable,
10896
+ args: [{
10897
+ providedIn: 'root'
10898
+ }]
10899
+ }], ctorParameters: () => [] });
10900
+
11077
10901
  /*
11078
10902
  * Public API Surface of cloud-ide-element
11079
10903
  * Here we can add what need to be exported from library
@@ -11083,5 +10907,5 @@ var floatingContainerDynamic_directive = /*#__PURE__*/Object.freeze({
11083
10907
  * Generated bundle index. Do not edit.
11084
10908
  */
11085
10909
 
11086
- export { AppShortcutService, CideCoreFileManagerService, CideEleButtonComponent, CideEleConfirmationModalComponent, CideEleDataGridComponent, CideEleDropdownComponent, CideEleFileImageDirective, CideEleFileInputComponent, CideEleFileManagerService, CideEleFloatingContainerComponent, CideEleFloatingContainerDynamicDirective, CideEleFloatingContainerManagerComponent, CideEleFloatingContainerService, CideEleFloatingFeaturesService, CideEleFloatingFileUploaderComponent, CideEleFloatingFileUploaderService, CideEleGlobalNotificationsComponent, CideEleJsonEditorComponent, CideEleResizerDirective, CideEleSkeletonLoaderComponent, CideEleTabComponent, CideEleToastNotificationComponent, CideElementsService, CideIconComponent, CideInputComponent, CideSelectComponent, CideSelectOptionComponent, CideSpinnerComponent, CideTextareaComponent, ConfirmationService, CoreFileManagerInsertUpdatePayload, DEFAULT_GRID_CONFIG, DropdownManagerService, FloatingContainerShortcutsService, ICoreCyfmSave, KeyboardShortcutService, MFileManager, NotificationService, TooltipDirective };
10910
+ export { CideCoreFileManagerService, CideEleButtonComponent, CideEleConfirmationModalComponent, CideEleDataGridComponent, CideEleDropdownComponent, CideEleFileImageDirective, CideEleFileInputComponent, CideEleFileManagerService, CideEleFloatingContainerComponent, CideEleFloatingContainerDynamicDirective, CideEleFloatingContainerManagerComponent, CideEleFloatingContainerService, CideEleFloatingFeaturesService, CideEleFloatingFileUploaderComponent, CideEleFloatingFileUploaderService, CideEleGlobalNotificationsComponent, CideEleJsonEditorComponent, CideEleResizerDirective, CideEleSkeletonLoaderComponent, CideEleTabComponent, CideEleToastNotificationComponent, CideElementsService, CideIconComponent, CideInputComponent, CideSelectComponent, CideSelectOptionComponent, CideSpinnerComponent, CideTextareaComponent, ConfirmationService, CoreFileManagerInsertUpdatePayload, DEFAULT_GRID_CONFIG, DropdownManagerService, FloatingContainerShortcutsService, ICoreCyfmSave, KeyboardShortcutService, MFileManager, NotificationService, TooltipDirective };
11087
10911
  //# sourceMappingURL=cloud-ide-element.mjs.map