cloud-ide-element 1.0.116 → 1.0.119
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.
- package/fesm2022/cloud-ide-element.mjs +719 -101
- package/fesm2022/cloud-ide-element.mjs.map +1 -1
- package/index.d.ts +178 -7
- package/package.json +1 -1
|
@@ -3385,6 +3385,7 @@ class CideEleFloatingContainerService {
|
|
|
3385
3385
|
activeComponents = new Map();
|
|
3386
3386
|
constructor(injector) {
|
|
3387
3387
|
this.injector = injector;
|
|
3388
|
+
// Keyboard shortcuts are now handled by FloatingContainerShortcutsService
|
|
3388
3389
|
}
|
|
3389
3390
|
// Computed properties
|
|
3390
3391
|
visibleContainers = computed(() => Array.from(this.containers().values()).filter(container => container.isVisible), ...(ngDevMode ? [{ debugName: "visibleContainers" }] : []));
|
|
@@ -3394,7 +3395,9 @@ class CideEleFloatingContainerService {
|
|
|
3394
3395
|
show(config) {
|
|
3395
3396
|
const containerId = config.id || this.generateId();
|
|
3396
3397
|
const instanceId = this.generateInstanceId(config.componentId || 'default');
|
|
3397
|
-
|
|
3398
|
+
// Get the highest z-index and add 1 to bring new container to front
|
|
3399
|
+
const maxZIndex = this.getMaxZIndex();
|
|
3400
|
+
const zIndex = maxZIndex + 1;
|
|
3398
3401
|
const now = new Date();
|
|
3399
3402
|
const container = {
|
|
3400
3403
|
id: containerId,
|
|
@@ -3427,40 +3430,64 @@ class CideEleFloatingContainerService {
|
|
|
3427
3430
|
return newContainers;
|
|
3428
3431
|
});
|
|
3429
3432
|
}
|
|
3430
|
-
|
|
3433
|
+
/**
|
|
3434
|
+
* Get the maximum z-index among all visible containers
|
|
3435
|
+
*/
|
|
3436
|
+
getMaxZIndex() {
|
|
3437
|
+
const containers = this.containers();
|
|
3438
|
+
let maxZIndex = 1000; // Base z-index
|
|
3439
|
+
for (const container of containers.values()) {
|
|
3440
|
+
if (container.isVisible && container.zIndex > maxZIndex) {
|
|
3441
|
+
maxZIndex = container.zIndex;
|
|
3442
|
+
}
|
|
3443
|
+
}
|
|
3444
|
+
return maxZIndex;
|
|
3445
|
+
}
|
|
3446
|
+
/**
|
|
3447
|
+
* Bring a container to the front (highest z-index)
|
|
3448
|
+
*/
|
|
3449
|
+
bringToFront(containerId) {
|
|
3450
|
+
const maxZIndex = this.getMaxZIndex();
|
|
3451
|
+
const newZIndex = maxZIndex + 1;
|
|
3452
|
+
console.log(`🎯 [FloatingContainer] Bringing container '${containerId}' to front`);
|
|
3453
|
+
console.log(`🎯 [FloatingContainer] Current max z-index: ${maxZIndex}, new z-index: ${newZIndex}`);
|
|
3431
3454
|
this.containers.update(containers => {
|
|
3432
3455
|
const newContainers = new Map(containers);
|
|
3433
3456
|
const container = newContainers.get(containerId);
|
|
3434
3457
|
if (container) {
|
|
3435
|
-
|
|
3458
|
+
const oldZIndex = container.zIndex;
|
|
3459
|
+
container.zIndex = newZIndex;
|
|
3460
|
+
container.lastAccessed = new Date();
|
|
3436
3461
|
newContainers.set(containerId, container);
|
|
3462
|
+
console.log(`🎯 [FloatingContainer] Container '${containerId}' z-index updated: ${oldZIndex} → ${newZIndex}`);
|
|
3463
|
+
}
|
|
3464
|
+
else {
|
|
3465
|
+
console.warn(`⚠️ [FloatingContainer] Container '${containerId}' not found!`);
|
|
3437
3466
|
}
|
|
3438
3467
|
return newContainers;
|
|
3439
3468
|
});
|
|
3440
3469
|
}
|
|
3441
|
-
|
|
3470
|
+
minimize(containerId) {
|
|
3442
3471
|
this.containers.update(containers => {
|
|
3443
3472
|
const newContainers = new Map(containers);
|
|
3444
3473
|
const container = newContainers.get(containerId);
|
|
3445
3474
|
if (container) {
|
|
3446
|
-
container.
|
|
3475
|
+
container.isMinimized = !container.isMinimized;
|
|
3447
3476
|
newContainers.set(containerId, container);
|
|
3448
3477
|
}
|
|
3449
3478
|
return newContainers;
|
|
3450
3479
|
});
|
|
3451
3480
|
}
|
|
3452
|
-
|
|
3453
|
-
const zIndex = this.nextZIndex();
|
|
3481
|
+
maximize(containerId) {
|
|
3454
3482
|
this.containers.update(containers => {
|
|
3455
3483
|
const newContainers = new Map(containers);
|
|
3456
3484
|
const container = newContainers.get(containerId);
|
|
3457
3485
|
if (container) {
|
|
3458
|
-
container.
|
|
3486
|
+
container.isMaximized = !container.isMaximized;
|
|
3459
3487
|
newContainers.set(containerId, container);
|
|
3460
3488
|
}
|
|
3461
3489
|
return newContainers;
|
|
3462
3490
|
});
|
|
3463
|
-
this.nextZIndex.update(z => z + 1);
|
|
3464
3491
|
}
|
|
3465
3492
|
getContainer(containerId) {
|
|
3466
3493
|
return this.containers().get(containerId);
|
|
@@ -3678,6 +3705,35 @@ class CideEleFloatingContainerService {
|
|
|
3678
3705
|
return container?.isMaximized || false;
|
|
3679
3706
|
});
|
|
3680
3707
|
}
|
|
3708
|
+
getZIndexSignal(containerId) {
|
|
3709
|
+
return computed(() => {
|
|
3710
|
+
const container = this.getContainer(containerId);
|
|
3711
|
+
const zIndex = container?.zIndex || 1000;
|
|
3712
|
+
console.log(`🎯 [FloatingContainer] Z-index signal for '${containerId}': ${zIndex}`);
|
|
3713
|
+
return zIndex;
|
|
3714
|
+
});
|
|
3715
|
+
}
|
|
3716
|
+
/**
|
|
3717
|
+
* Set z-index for a specific container
|
|
3718
|
+
*/
|
|
3719
|
+
setZIndex(containerId, zIndex) {
|
|
3720
|
+
console.log(`🎯 [FloatingContainer] Setting z-index for '${containerId}' to ${zIndex}`);
|
|
3721
|
+
this.containers.update(containers => {
|
|
3722
|
+
const newContainers = new Map(containers);
|
|
3723
|
+
const container = newContainers.get(containerId);
|
|
3724
|
+
if (container) {
|
|
3725
|
+
const oldZIndex = container.zIndex;
|
|
3726
|
+
container.zIndex = zIndex;
|
|
3727
|
+
container.lastAccessed = new Date();
|
|
3728
|
+
newContainers.set(containerId, container);
|
|
3729
|
+
console.log(`🎯 [FloatingContainer] Container '${containerId}' z-index updated: ${oldZIndex} → ${zIndex}`);
|
|
3730
|
+
}
|
|
3731
|
+
else {
|
|
3732
|
+
console.warn(`⚠️ [FloatingContainer] Container '${containerId}' not found for z-index update!`);
|
|
3733
|
+
}
|
|
3734
|
+
return newContainers;
|
|
3735
|
+
});
|
|
3736
|
+
}
|
|
3681
3737
|
/**
|
|
3682
3738
|
* Get visible signal for a container
|
|
3683
3739
|
*/
|
|
@@ -4932,8 +4988,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
|
|
|
4932
4988
|
class CideEleFloatingFileUploaderComponent {
|
|
4933
4989
|
destroyRef = inject(DestroyRef);
|
|
4934
4990
|
fileManagerService = inject(CideEleFileManagerService);
|
|
4991
|
+
// Input data from floating container
|
|
4992
|
+
data = {};
|
|
4935
4993
|
// Signals for reactive state
|
|
4936
|
-
isVisible = signal(
|
|
4994
|
+
isVisible = signal(true, ...(ngDevMode ? [{ debugName: "isVisible" }] : [])); // Set to true by default for floating containers
|
|
4937
4995
|
isMinimized = signal(false, ...(ngDevMode ? [{ debugName: "isMinimized" }] : []));
|
|
4938
4996
|
currentUserId = signal('', ...(ngDevMode ? [{ debugName: "currentUserId" }] : []));
|
|
4939
4997
|
currentGroupId = signal(null, ...(ngDevMode ? [{ debugName: "currentGroupId" }] : []));
|
|
@@ -5015,6 +5073,8 @@ class CideEleFloatingFileUploaderComponent {
|
|
|
5015
5073
|
});
|
|
5016
5074
|
}
|
|
5017
5075
|
ngOnInit() {
|
|
5076
|
+
// Initialize with input data
|
|
5077
|
+
this.initializeWithData();
|
|
5018
5078
|
// Set up drag and drop listeners
|
|
5019
5079
|
this.setupDragAndDrop();
|
|
5020
5080
|
// Set up file input change listeners
|
|
@@ -5022,6 +5082,39 @@ class CideEleFloatingFileUploaderComponent {
|
|
|
5022
5082
|
// Set up window resize listener
|
|
5023
5083
|
this.setupWindowResize();
|
|
5024
5084
|
}
|
|
5085
|
+
initializeWithData() {
|
|
5086
|
+
console.log('🚀 [FloatingFileUploader] Initializing with data:', this.data);
|
|
5087
|
+
// Set user ID if provided
|
|
5088
|
+
if (this.data.userId) {
|
|
5089
|
+
this.currentUserId.set(this.data.userId);
|
|
5090
|
+
console.log('👤 [FloatingFileUploader] User ID set:', this.data.userId);
|
|
5091
|
+
}
|
|
5092
|
+
// Set group ID if provided
|
|
5093
|
+
if (this.data.groupId) {
|
|
5094
|
+
this.currentGroupId.set(this.data.groupId);
|
|
5095
|
+
console.log('🆔 [FloatingFileUploader] Group ID set:', this.data.groupId);
|
|
5096
|
+
// Load existing files for this group
|
|
5097
|
+
this.loadExistingFiles();
|
|
5098
|
+
}
|
|
5099
|
+
// Set visibility to true when component loads
|
|
5100
|
+
this.isVisible.set(true);
|
|
5101
|
+
}
|
|
5102
|
+
loadExistingFiles() {
|
|
5103
|
+
const groupId = this.currentGroupId();
|
|
5104
|
+
if (!groupId)
|
|
5105
|
+
return;
|
|
5106
|
+
console.log('📁 [FloatingFileUploader] Loading existing files for group:', groupId);
|
|
5107
|
+
this.fileManagerService.fetchAndStoreFilesByGroupId(groupId)
|
|
5108
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
5109
|
+
.subscribe({
|
|
5110
|
+
next: (files) => {
|
|
5111
|
+
console.log('📋 [FloatingFileUploader] Files loaded:', files.length);
|
|
5112
|
+
},
|
|
5113
|
+
error: (error) => {
|
|
5114
|
+
console.error('❌ [FloatingFileUploader] Failed to load files:', error);
|
|
5115
|
+
}
|
|
5116
|
+
});
|
|
5117
|
+
}
|
|
5025
5118
|
ngOnDestroy() {
|
|
5026
5119
|
console.log('🧹 [FloatingFileUploader] Component destroyed');
|
|
5027
5120
|
this.removeDragAndDropListeners();
|
|
@@ -5468,7 +5561,7 @@ class CideEleFloatingFileUploaderComponent {
|
|
|
5468
5561
|
}, 100);
|
|
5469
5562
|
}
|
|
5470
5563
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingFileUploaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5471
|
-
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 -->\n@if (isVisible()) {\n<div class=\"floating-uploader\" \n [class.minimized]=\"isMinimized()\" \n [class.animating]=\"isAnimating()\"\n [style.left.px]=\"position().x\"\n [style.top.px]=\"position().y\">\n\n <!-- Header (Draggable) -->\n <div class=\"uploader-header draggable-header\"\n (mousedown)=\"startDrag($event)\"\n (touchstart)=\"startDrag($event)\">\n <div class=\"header-left\">\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 <div class=\"header-actions\">\n <button class=\"action-btn minimize-btn\" (click)=\"toggleMinimize()\" [title]=\"isMinimized() ? 'Expand' : 'Minimize'\">\n <cide-ele-icon size=\"xs\">{{ isMinimized() ? 'expand_more' : 'expand_less' }}</cide-ele-icon>\n </button>\n <button class=\"action-btn close-btn\" (click)=\"close()\" title=\"Close\">\n <cide-ele-icon size=\"xs\">close</cide-ele-icon>\n </button>\n </div>\n </div>\n\n <!-- Content (hidden when minimized) -->\n @if (!isMinimized()) {\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 }\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"] }] });
|
|
5564
|
+
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: "<!-- Floating File Uploader Container -->\n@if (isVisible()) {\n<div class=\"floating-uploader\" \n [class.minimized]=\"isMinimized()\" \n [class.animating]=\"isAnimating()\"\n [style.left.px]=\"position().x\"\n [style.top.px]=\"position().y\">\n\n <!-- Header (Draggable) -->\n <div class=\"uploader-header draggable-header\"\n (mousedown)=\"startDrag($event)\"\n (touchstart)=\"startDrag($event)\">\n <div class=\"header-left\">\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 <div class=\"header-actions\">\n <button class=\"action-btn minimize-btn\" (click)=\"toggleMinimize()\" [title]=\"isMinimized() ? 'Expand' : 'Minimize'\">\n <cide-ele-icon size=\"xs\">{{ isMinimized() ? 'expand_more' : 'expand_less' }}</cide-ele-icon>\n </button>\n <button class=\"action-btn close-btn\" (click)=\"close()\" title=\"Close\">\n <cide-ele-icon size=\"xs\">close</cide-ele-icon>\n </button>\n </div>\n </div>\n\n <!-- Content (hidden when minimized) -->\n @if (!isMinimized()) {\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 }\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"] }] });
|
|
5472
5565
|
}
|
|
5473
5566
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingFileUploaderComponent, decorators: [{
|
|
5474
5567
|
type: Component,
|
|
@@ -5476,7 +5569,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
|
|
|
5476
5569
|
CommonModule,
|
|
5477
5570
|
CideIconComponent
|
|
5478
5571
|
], template: "<!-- Floating File Uploader Container -->\n@if (isVisible()) {\n<div class=\"floating-uploader\" \n [class.minimized]=\"isMinimized()\" \n [class.animating]=\"isAnimating()\"\n [style.left.px]=\"position().x\"\n [style.top.px]=\"position().y\">\n\n <!-- Header (Draggable) -->\n <div class=\"uploader-header draggable-header\"\n (mousedown)=\"startDrag($event)\"\n (touchstart)=\"startDrag($event)\">\n <div class=\"header-left\">\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 <div class=\"header-actions\">\n <button class=\"action-btn minimize-btn\" (click)=\"toggleMinimize()\" [title]=\"isMinimized() ? 'Expand' : 'Minimize'\">\n <cide-ele-icon size=\"xs\">{{ isMinimized() ? 'expand_more' : 'expand_less' }}</cide-ele-icon>\n </button>\n <button class=\"action-btn close-btn\" (click)=\"close()\" title=\"Close\">\n <cide-ele-icon size=\"xs\">close</cide-ele-icon>\n </button>\n </div>\n </div>\n\n <!-- Content (hidden when minimized) -->\n @if (!isMinimized()) {\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 }\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"] }]
|
|
5479
|
-
}], ctorParameters: () => []
|
|
5572
|
+
}], ctorParameters: () => [], propDecorators: { data: [{
|
|
5573
|
+
type: Input
|
|
5574
|
+
}] } });
|
|
5480
5575
|
|
|
5481
5576
|
var floatingFileUploader_component = /*#__PURE__*/Object.freeze({
|
|
5482
5577
|
__proto__: null,
|
|
@@ -5632,6 +5727,510 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
|
|
|
5632
5727
|
type: Output
|
|
5633
5728
|
}] } });
|
|
5634
5729
|
|
|
5730
|
+
class KeyboardShortcutService {
|
|
5731
|
+
shortcuts = new Map();
|
|
5732
|
+
overrides = new Map();
|
|
5733
|
+
keydownListener;
|
|
5734
|
+
constructor() {
|
|
5735
|
+
this.setupGlobalListener();
|
|
5736
|
+
}
|
|
5737
|
+
ngOnDestroy() {
|
|
5738
|
+
this.removeGlobalListener();
|
|
5739
|
+
}
|
|
5740
|
+
/**
|
|
5741
|
+
* Register a new keyboard shortcut
|
|
5742
|
+
*/
|
|
5743
|
+
register(shortcut) {
|
|
5744
|
+
this.shortcuts.set(shortcut.id, shortcut);
|
|
5745
|
+
console.log(`⌨️ [KeyboardShortcut] Registered shortcut: ${shortcut.id} (${this.getKeyDescription(shortcut)})`);
|
|
5746
|
+
}
|
|
5747
|
+
/**
|
|
5748
|
+
* Override an existing shortcut with new key combination
|
|
5749
|
+
*/
|
|
5750
|
+
override(shortcutId, newKey, options) {
|
|
5751
|
+
const originalShortcut = this.shortcuts.get(shortcutId);
|
|
5752
|
+
if (!originalShortcut) {
|
|
5753
|
+
console.warn(`⚠️ [KeyboardShortcut] Cannot override shortcut '${shortcutId}' - not found`);
|
|
5754
|
+
return;
|
|
5755
|
+
}
|
|
5756
|
+
const override = {
|
|
5757
|
+
shortcutId,
|
|
5758
|
+
newKey,
|
|
5759
|
+
newCtrlKey: options?.ctrlKey,
|
|
5760
|
+
newAltKey: options?.altKey,
|
|
5761
|
+
newShiftKey: options?.shiftKey,
|
|
5762
|
+
newMetaKey: options?.metaKey
|
|
5763
|
+
};
|
|
5764
|
+
this.overrides.set(shortcutId, override);
|
|
5765
|
+
console.log(`🔄 [KeyboardShortcut] Override registered for '${shortcutId}': ${this.getKeyDescription({ ...originalShortcut, ...options, key: newKey })}`);
|
|
5766
|
+
}
|
|
5767
|
+
/**
|
|
5768
|
+
* Remove a shortcut
|
|
5769
|
+
*/
|
|
5770
|
+
unregister(shortcutId) {
|
|
5771
|
+
this.shortcuts.delete(shortcutId);
|
|
5772
|
+
this.overrides.delete(shortcutId);
|
|
5773
|
+
console.log(`🗑️ [KeyboardShortcut] Removed shortcut: ${shortcutId}`);
|
|
5774
|
+
}
|
|
5775
|
+
/**
|
|
5776
|
+
* Remove override for a shortcut (restore original key combination)
|
|
5777
|
+
*/
|
|
5778
|
+
removeOverride(shortcutId) {
|
|
5779
|
+
this.overrides.delete(shortcutId);
|
|
5780
|
+
console.log(`🔄 [KeyboardShortcut] Override removed for: ${shortcutId}`);
|
|
5781
|
+
}
|
|
5782
|
+
/**
|
|
5783
|
+
* Get all registered shortcuts
|
|
5784
|
+
*/
|
|
5785
|
+
getAllShortcuts() {
|
|
5786
|
+
return Array.from(this.shortcuts.values());
|
|
5787
|
+
}
|
|
5788
|
+
/**
|
|
5789
|
+
* Get shortcuts by category or filter
|
|
5790
|
+
*/
|
|
5791
|
+
getShortcuts(filter) {
|
|
5792
|
+
const shortcuts = this.getAllShortcuts();
|
|
5793
|
+
return filter ? shortcuts.filter(filter) : shortcuts;
|
|
5794
|
+
}
|
|
5795
|
+
/**
|
|
5796
|
+
* Check if a shortcut is registered
|
|
5797
|
+
*/
|
|
5798
|
+
hasShortcut(shortcutId) {
|
|
5799
|
+
return this.shortcuts.has(shortcutId);
|
|
5800
|
+
}
|
|
5801
|
+
/**
|
|
5802
|
+
* Get shortcut information
|
|
5803
|
+
*/
|
|
5804
|
+
getShortcut(shortcutId) {
|
|
5805
|
+
return this.shortcuts.get(shortcutId);
|
|
5806
|
+
}
|
|
5807
|
+
/**
|
|
5808
|
+
* Clear all shortcuts
|
|
5809
|
+
*/
|
|
5810
|
+
clearAll() {
|
|
5811
|
+
this.shortcuts.clear();
|
|
5812
|
+
this.overrides.clear();
|
|
5813
|
+
console.log(`🧹 [KeyboardShortcut] All shortcuts cleared`);
|
|
5814
|
+
}
|
|
5815
|
+
/**
|
|
5816
|
+
* Set up global keyboard listener
|
|
5817
|
+
*/
|
|
5818
|
+
setupGlobalListener() {
|
|
5819
|
+
this.keydownListener = (event) => {
|
|
5820
|
+
this.handleKeydown(event);
|
|
5821
|
+
};
|
|
5822
|
+
document.addEventListener('keydown', this.keydownListener);
|
|
5823
|
+
console.log(`🎧 [KeyboardShortcut] Global keyboard listener attached`);
|
|
5824
|
+
}
|
|
5825
|
+
/**
|
|
5826
|
+
* Remove global keyboard listener
|
|
5827
|
+
*/
|
|
5828
|
+
removeGlobalListener() {
|
|
5829
|
+
if (this.keydownListener) {
|
|
5830
|
+
document.removeEventListener('keydown', this.keydownListener);
|
|
5831
|
+
this.keydownListener = undefined;
|
|
5832
|
+
console.log(`🎧 [KeyboardShortcut] Global keyboard listener removed`);
|
|
5833
|
+
}
|
|
5834
|
+
}
|
|
5835
|
+
/**
|
|
5836
|
+
* Handle keydown events
|
|
5837
|
+
*/
|
|
5838
|
+
handleKeydown(event) {
|
|
5839
|
+
for (const [shortcutId, shortcut] of this.shortcuts) {
|
|
5840
|
+
if (this.matchesShortcut(event, shortcut)) {
|
|
5841
|
+
// Check for override
|
|
5842
|
+
const override = this.overrides.get(shortcutId);
|
|
5843
|
+
if (override && !this.matchesOverride(event, override)) {
|
|
5844
|
+
continue; // Skip if override doesn't match
|
|
5845
|
+
}
|
|
5846
|
+
if (shortcut.preventDefault !== false) {
|
|
5847
|
+
event.preventDefault();
|
|
5848
|
+
}
|
|
5849
|
+
if (shortcut.stopPropagation) {
|
|
5850
|
+
event.stopPropagation();
|
|
5851
|
+
}
|
|
5852
|
+
console.log(`⌨️ [KeyboardShortcut] Executing shortcut: ${shortcutId}`);
|
|
5853
|
+
shortcut.action();
|
|
5854
|
+
break; // Only execute one shortcut per keydown
|
|
5855
|
+
}
|
|
5856
|
+
}
|
|
5857
|
+
}
|
|
5858
|
+
/**
|
|
5859
|
+
* Check if event matches shortcut
|
|
5860
|
+
*/
|
|
5861
|
+
matchesShortcut(event, shortcut) {
|
|
5862
|
+
return event.key === shortcut.key &&
|
|
5863
|
+
(shortcut.ctrlKey === undefined || event.ctrlKey === shortcut.ctrlKey) &&
|
|
5864
|
+
(shortcut.altKey === undefined || event.altKey === shortcut.altKey) &&
|
|
5865
|
+
(shortcut.shiftKey === undefined || event.shiftKey === shortcut.shiftKey) &&
|
|
5866
|
+
(shortcut.metaKey === undefined || event.metaKey === shortcut.metaKey);
|
|
5867
|
+
}
|
|
5868
|
+
/**
|
|
5869
|
+
* Check if event matches override
|
|
5870
|
+
*/
|
|
5871
|
+
matchesOverride(event, override) {
|
|
5872
|
+
return event.key === override.newKey &&
|
|
5873
|
+
(override.newCtrlKey === undefined || event.ctrlKey === override.newCtrlKey) &&
|
|
5874
|
+
(override.newAltKey === undefined || event.altKey === override.newAltKey) &&
|
|
5875
|
+
(override.newShiftKey === undefined || event.shiftKey === override.newShiftKey) &&
|
|
5876
|
+
(override.newMetaKey === undefined || event.metaKey === override.newMetaKey);
|
|
5877
|
+
}
|
|
5878
|
+
/**
|
|
5879
|
+
* Get human-readable key description
|
|
5880
|
+
*/
|
|
5881
|
+
getKeyDescription(shortcut) {
|
|
5882
|
+
const modifiers = [];
|
|
5883
|
+
if (shortcut.ctrlKey)
|
|
5884
|
+
modifiers.push('Ctrl');
|
|
5885
|
+
if (shortcut.altKey)
|
|
5886
|
+
modifiers.push('Alt');
|
|
5887
|
+
if (shortcut.shiftKey)
|
|
5888
|
+
modifiers.push('Shift');
|
|
5889
|
+
if (shortcut.metaKey)
|
|
5890
|
+
modifiers.push('Meta');
|
|
5891
|
+
return [...modifiers, shortcut.key].join(' + ');
|
|
5892
|
+
}
|
|
5893
|
+
/**
|
|
5894
|
+
* Get key description for a shortcut ID
|
|
5895
|
+
*/
|
|
5896
|
+
getKeyDescriptionForShortcut(shortcutId) {
|
|
5897
|
+
const shortcut = this.shortcuts.get(shortcutId);
|
|
5898
|
+
if (!shortcut)
|
|
5899
|
+
return 'Not found';
|
|
5900
|
+
const override = this.overrides.get(shortcutId);
|
|
5901
|
+
if (override) {
|
|
5902
|
+
return this.getKeyDescription({
|
|
5903
|
+
key: override.newKey,
|
|
5904
|
+
ctrlKey: override.newCtrlKey,
|
|
5905
|
+
altKey: override.newAltKey,
|
|
5906
|
+
shiftKey: override.newShiftKey,
|
|
5907
|
+
metaKey: override.newMetaKey
|
|
5908
|
+
});
|
|
5909
|
+
}
|
|
5910
|
+
return this.getKeyDescription(shortcut);
|
|
5911
|
+
}
|
|
5912
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: KeyboardShortcutService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
5913
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: KeyboardShortcutService, providedIn: 'root' });
|
|
5914
|
+
}
|
|
5915
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: KeyboardShortcutService, decorators: [{
|
|
5916
|
+
type: Injectable,
|
|
5917
|
+
args: [{
|
|
5918
|
+
providedIn: 'root'
|
|
5919
|
+
}]
|
|
5920
|
+
}], ctorParameters: () => [] });
|
|
5921
|
+
|
|
5922
|
+
class FloatingContainerShortcutsService {
|
|
5923
|
+
keyboardShortcutService = inject(KeyboardShortcutService);
|
|
5924
|
+
containerService = inject(CideEleFloatingContainerService);
|
|
5925
|
+
// Z-index layers for different container states
|
|
5926
|
+
Z_INDEX_LAYERS = {
|
|
5927
|
+
HIDDEN: 100, // Hidden containers (behind everything)
|
|
5928
|
+
BACKGROUND: 1000, // Background containers
|
|
5929
|
+
NORMAL: 2000, // Normal visible containers
|
|
5930
|
+
FOCUSED: 3000, // Focused containers
|
|
5931
|
+
MODAL: 4000, // Modal containers
|
|
5932
|
+
TOOLTIP: 5000 // Tooltips and overlays
|
|
5933
|
+
};
|
|
5934
|
+
constructor() {
|
|
5935
|
+
this.registerDefaultShortcuts();
|
|
5936
|
+
}
|
|
5937
|
+
/**
|
|
5938
|
+
* Register default floating container shortcuts using custom key combinations
|
|
5939
|
+
*/
|
|
5940
|
+
registerDefaultShortcuts() {
|
|
5941
|
+
// C + 1: Focus on first container
|
|
5942
|
+
this.keyboardShortcutService.register({
|
|
5943
|
+
id: 'floating-container-focus-first',
|
|
5944
|
+
key: '1',
|
|
5945
|
+
ctrlKey: true,
|
|
5946
|
+
description: 'Focus on first floating container (C+1)',
|
|
5947
|
+
action: () => this.focusFirstContainer(),
|
|
5948
|
+
preventDefault: true
|
|
5949
|
+
});
|
|
5950
|
+
// C + 2: Focus on second container
|
|
5951
|
+
this.keyboardShortcutService.register({
|
|
5952
|
+
id: 'floating-container-focus-second',
|
|
5953
|
+
key: '2',
|
|
5954
|
+
ctrlKey: true,
|
|
5955
|
+
description: 'Focus on second floating container (C+2)',
|
|
5956
|
+
action: () => this.focusContainerByIndex(1),
|
|
5957
|
+
preventDefault: true
|
|
5958
|
+
});
|
|
5959
|
+
// C + 3: Focus on third container
|
|
5960
|
+
this.keyboardShortcutService.register({
|
|
5961
|
+
id: 'floating-container-focus-third',
|
|
5962
|
+
key: '3',
|
|
5963
|
+
ctrlKey: true,
|
|
5964
|
+
description: 'Focus on third floating container (C+3)',
|
|
5965
|
+
action: () => this.focusContainerByIndex(2),
|
|
5966
|
+
preventDefault: true
|
|
5967
|
+
});
|
|
5968
|
+
// C + 4: Focus on fourth container
|
|
5969
|
+
this.keyboardShortcutService.register({
|
|
5970
|
+
id: 'floating-container-focus-fourth',
|
|
5971
|
+
key: '4',
|
|
5972
|
+
ctrlKey: true,
|
|
5973
|
+
description: 'Focus on fourth floating container (C+4)',
|
|
5974
|
+
action: () => this.focusContainerByIndex(3),
|
|
5975
|
+
preventDefault: true
|
|
5976
|
+
});
|
|
5977
|
+
// C + 5: Focus on fifth container
|
|
5978
|
+
this.keyboardShortcutService.register({
|
|
5979
|
+
id: 'floating-container-focus-fifth',
|
|
5980
|
+
key: '5',
|
|
5981
|
+
ctrlKey: true,
|
|
5982
|
+
description: 'Focus on fifth floating container (C+5)',
|
|
5983
|
+
action: () => this.focusContainerByIndex(4),
|
|
5984
|
+
preventDefault: true
|
|
5985
|
+
});
|
|
5986
|
+
// C + N: Cycle to next container
|
|
5987
|
+
this.keyboardShortcutService.register({
|
|
5988
|
+
id: 'floating-container-cycle-forward',
|
|
5989
|
+
key: 'n',
|
|
5990
|
+
ctrlKey: true,
|
|
5991
|
+
description: 'Cycle forward through floating containers (C+N)',
|
|
5992
|
+
action: () => this.cycleToNextContainer(),
|
|
5993
|
+
preventDefault: true
|
|
5994
|
+
});
|
|
5995
|
+
// C + P: Cycle to previous container
|
|
5996
|
+
this.keyboardShortcutService.register({
|
|
5997
|
+
id: 'floating-container-cycle-backward',
|
|
5998
|
+
key: 'p',
|
|
5999
|
+
ctrlKey: true,
|
|
6000
|
+
description: 'Cycle backward through floating containers (C+P)',
|
|
6001
|
+
action: () => this.cycleToPreviousContainer(),
|
|
6002
|
+
preventDefault: true
|
|
6003
|
+
});
|
|
6004
|
+
// C + H: Hide all containers
|
|
6005
|
+
this.keyboardShortcutService.register({
|
|
6006
|
+
id: 'floating-container-hide-all',
|
|
6007
|
+
key: 'h',
|
|
6008
|
+
ctrlKey: true,
|
|
6009
|
+
description: 'Hide all floating containers (C+H)',
|
|
6010
|
+
action: () => this.hideAllContainers(),
|
|
6011
|
+
preventDefault: true
|
|
6012
|
+
});
|
|
6013
|
+
// C + M: Minimize all containers
|
|
6014
|
+
this.keyboardShortcutService.register({
|
|
6015
|
+
id: 'floating-container-minimize-all',
|
|
6016
|
+
key: 'm',
|
|
6017
|
+
ctrlKey: true,
|
|
6018
|
+
description: 'Minimize all floating containers (C+M)',
|
|
6019
|
+
action: () => this.minimizeAllContainers(),
|
|
6020
|
+
preventDefault: true
|
|
6021
|
+
});
|
|
6022
|
+
// C + O: Open file uploader
|
|
6023
|
+
this.keyboardShortcutService.register({
|
|
6024
|
+
id: 'floating-container-open-file-uploader',
|
|
6025
|
+
key: 'o',
|
|
6026
|
+
ctrlKey: true,
|
|
6027
|
+
description: 'Open file uploader (C+O)',
|
|
6028
|
+
action: () => this.openFileUploader(),
|
|
6029
|
+
preventDefault: true
|
|
6030
|
+
});
|
|
6031
|
+
// C + R: Open entity rights sharing
|
|
6032
|
+
this.keyboardShortcutService.register({
|
|
6033
|
+
id: 'floating-container-open-entity-rights',
|
|
6034
|
+
key: 'r',
|
|
6035
|
+
ctrlKey: true,
|
|
6036
|
+
description: 'Open entity rights sharing (C+R)',
|
|
6037
|
+
action: () => this.openEntityRightsSharing(),
|
|
6038
|
+
preventDefault: true
|
|
6039
|
+
});
|
|
6040
|
+
// C + S: Show all containers
|
|
6041
|
+
this.keyboardShortcutService.register({
|
|
6042
|
+
id: 'floating-container-show-all',
|
|
6043
|
+
key: 's',
|
|
6044
|
+
ctrlKey: true,
|
|
6045
|
+
description: 'Show all floating containers (C+S)',
|
|
6046
|
+
action: () => this.showAllContainers(),
|
|
6047
|
+
preventDefault: true
|
|
6048
|
+
});
|
|
6049
|
+
// C + D: Duplicate current container
|
|
6050
|
+
this.keyboardShortcutService.register({
|
|
6051
|
+
id: 'floating-container-duplicate',
|
|
6052
|
+
key: 'd',
|
|
6053
|
+
ctrlKey: true,
|
|
6054
|
+
description: 'Duplicate current container (C+D)',
|
|
6055
|
+
action: () => this.duplicateCurrentContainer(),
|
|
6056
|
+
preventDefault: true
|
|
6057
|
+
});
|
|
6058
|
+
// C + W: Close current container
|
|
6059
|
+
this.keyboardShortcutService.register({
|
|
6060
|
+
id: 'floating-container-close-current',
|
|
6061
|
+
key: 'w',
|
|
6062
|
+
ctrlKey: true,
|
|
6063
|
+
description: 'Close current container (C+W)',
|
|
6064
|
+
action: () => this.closeCurrentContainer(),
|
|
6065
|
+
preventDefault: true
|
|
6066
|
+
});
|
|
6067
|
+
// C + T: Toggle container visibility
|
|
6068
|
+
this.keyboardShortcutService.register({
|
|
6069
|
+
id: 'floating-container-toggle-visibility',
|
|
6070
|
+
key: 't',
|
|
6071
|
+
ctrlKey: true,
|
|
6072
|
+
description: 'Toggle container visibility (C+T)',
|
|
6073
|
+
action: () => this.toggleContainerVisibility(),
|
|
6074
|
+
preventDefault: true
|
|
6075
|
+
});
|
|
6076
|
+
console.log('🎯 [FloatingContainerShortcuts] Custom shortcuts registered (C+1, C+2, C+O, etc.)');
|
|
6077
|
+
}
|
|
6078
|
+
/**
|
|
6079
|
+
* Override a floating container shortcut
|
|
6080
|
+
*/
|
|
6081
|
+
overrideShortcut(shortcutId, newKey, options) {
|
|
6082
|
+
this.keyboardShortcutService.override(shortcutId, newKey, options);
|
|
6083
|
+
}
|
|
6084
|
+
/**
|
|
6085
|
+
* Add a custom floating container shortcut
|
|
6086
|
+
*/
|
|
6087
|
+
addCustomShortcut(shortcut) {
|
|
6088
|
+
this.keyboardShortcutService.register({
|
|
6089
|
+
...shortcut,
|
|
6090
|
+
preventDefault: true
|
|
6091
|
+
});
|
|
6092
|
+
}
|
|
6093
|
+
/**
|
|
6094
|
+
* Remove a floating container shortcut
|
|
6095
|
+
*/
|
|
6096
|
+
removeShortcut(shortcutId) {
|
|
6097
|
+
this.keyboardShortcutService.unregister(shortcutId);
|
|
6098
|
+
}
|
|
6099
|
+
/**
|
|
6100
|
+
* Get all floating container shortcuts
|
|
6101
|
+
*/
|
|
6102
|
+
getShortcuts() {
|
|
6103
|
+
return this.keyboardShortcutService.getShortcuts(shortcut => shortcut.id.startsWith('floating-container-'));
|
|
6104
|
+
}
|
|
6105
|
+
// Action methods
|
|
6106
|
+
cycleToNextContainer() {
|
|
6107
|
+
const visibleContainers = this.containerService.visibleContainers();
|
|
6108
|
+
if (visibleContainers.length === 0)
|
|
6109
|
+
return;
|
|
6110
|
+
// Sort by last accessed time (most recent first)
|
|
6111
|
+
const sortedContainers = visibleContainers.sort((a, b) => b.lastAccessed.getTime() - a.lastAccessed.getTime());
|
|
6112
|
+
// Find current front container
|
|
6113
|
+
const currentFront = sortedContainers[0];
|
|
6114
|
+
const currentIndex = sortedContainers.findIndex(c => c.id === currentFront.id);
|
|
6115
|
+
// Get next container (wrap around)
|
|
6116
|
+
const nextIndex = (currentIndex + 1) % sortedContainers.length;
|
|
6117
|
+
const nextContainer = sortedContainers[nextIndex];
|
|
6118
|
+
this.containerService.bringToFront(nextContainer.id);
|
|
6119
|
+
console.log(`🔄 [FloatingContainerShortcuts] Cycled to container: ${nextContainer.config.title}`);
|
|
6120
|
+
}
|
|
6121
|
+
cycleToPreviousContainer() {
|
|
6122
|
+
const visibleContainers = this.containerService.visibleContainers();
|
|
6123
|
+
if (visibleContainers.length === 0)
|
|
6124
|
+
return;
|
|
6125
|
+
// Sort by last accessed time (most recent first)
|
|
6126
|
+
const sortedContainers = visibleContainers.sort((a, b) => b.lastAccessed.getTime() - a.lastAccessed.getTime());
|
|
6127
|
+
// Find current front container
|
|
6128
|
+
const currentFront = sortedContainers[0];
|
|
6129
|
+
const currentIndex = sortedContainers.findIndex(c => c.id === currentFront.id);
|
|
6130
|
+
// Get previous container (wrap around)
|
|
6131
|
+
const prevIndex = currentIndex === 0 ? sortedContainers.length - 1 : currentIndex - 1;
|
|
6132
|
+
const prevContainer = sortedContainers[prevIndex];
|
|
6133
|
+
this.containerService.bringToFront(prevContainer.id);
|
|
6134
|
+
console.log(`🔄 [FloatingContainerShortcuts] Cycled backwards to container: ${prevContainer.config.title}`);
|
|
6135
|
+
}
|
|
6136
|
+
hideAllContainers() {
|
|
6137
|
+
const visibleContainers = this.containerService.visibleContainers();
|
|
6138
|
+
visibleContainers.forEach(container => {
|
|
6139
|
+
this.containerService.setZIndex(container.id, this.Z_INDEX_LAYERS.HIDDEN);
|
|
6140
|
+
});
|
|
6141
|
+
console.log(`👁️ [FloatingContainerShortcuts] All containers moved to hidden layer (z-index: ${this.Z_INDEX_LAYERS.HIDDEN})`);
|
|
6142
|
+
}
|
|
6143
|
+
focusFirstContainer() {
|
|
6144
|
+
const visibleContainers = this.containerService.visibleContainers();
|
|
6145
|
+
if (visibleContainers.length === 0)
|
|
6146
|
+
return;
|
|
6147
|
+
const firstContainer = visibleContainers[0];
|
|
6148
|
+
this.containerService.bringToFront(firstContainer.id);
|
|
6149
|
+
console.log(`🎯 [FloatingContainerShortcuts] Focused on first container: ${firstContainer.config.title}`);
|
|
6150
|
+
}
|
|
6151
|
+
minimizeAllContainers() {
|
|
6152
|
+
this.containerService.minimizeAll();
|
|
6153
|
+
console.log(`📦 [FloatingContainerShortcuts] All containers minimized`);
|
|
6154
|
+
}
|
|
6155
|
+
focusContainerByIndex(index) {
|
|
6156
|
+
const visibleContainers = this.containerService.visibleContainers();
|
|
6157
|
+
if (visibleContainers.length === 0 || index >= visibleContainers.length) {
|
|
6158
|
+
console.log(`⚠️ [FloatingContainerShortcuts] No container at index ${index}`);
|
|
6159
|
+
return;
|
|
6160
|
+
}
|
|
6161
|
+
const container = visibleContainers[index];
|
|
6162
|
+
this.containerService.bringToFront(container.id);
|
|
6163
|
+
console.log(`🎯 [FloatingContainerShortcuts] Focused on container ${index + 1}: ${container.config.title}`);
|
|
6164
|
+
}
|
|
6165
|
+
openFileUploader() {
|
|
6166
|
+
console.log(`📁 [FloatingContainerShortcuts] Opening file uploader...`);
|
|
6167
|
+
// This would need to be implemented based on your file uploader service
|
|
6168
|
+
// Example: this.fileUploaderService.show();
|
|
6169
|
+
}
|
|
6170
|
+
openEntityRightsSharing() {
|
|
6171
|
+
console.log(`🔐 [FloatingContainerShortcuts] Opening entity rights sharing...`);
|
|
6172
|
+
// This would need to be implemented based on your entity rights service
|
|
6173
|
+
// Example: this.entityRightsService.show();
|
|
6174
|
+
}
|
|
6175
|
+
showAllContainers() {
|
|
6176
|
+
const visibleContainers = this.containerService.visibleContainers();
|
|
6177
|
+
visibleContainers.forEach((container, index) => {
|
|
6178
|
+
// Give each container a slightly different z-index to maintain order
|
|
6179
|
+
const zIndex = this.Z_INDEX_LAYERS.NORMAL + index;
|
|
6180
|
+
this.containerService.setZIndex(container.id, zIndex);
|
|
6181
|
+
});
|
|
6182
|
+
console.log(`👁️ [FloatingContainerShortcuts] All containers moved to normal layer (z-index: ${this.Z_INDEX_LAYERS.NORMAL}+)`);
|
|
6183
|
+
}
|
|
6184
|
+
duplicateCurrentContainer() {
|
|
6185
|
+
const visibleContainers = this.containerService.visibleContainers();
|
|
6186
|
+
if (visibleContainers.length === 0) {
|
|
6187
|
+
console.log(`⚠️ [FloatingContainerShortcuts] No containers to duplicate`);
|
|
6188
|
+
return;
|
|
6189
|
+
}
|
|
6190
|
+
const currentContainer = visibleContainers[0]; // Most recent container
|
|
6191
|
+
console.log(`📋 [FloatingContainerShortcuts] Duplicating container: ${currentContainer.config.title}`);
|
|
6192
|
+
// This would need to be implemented based on your container duplication logic
|
|
6193
|
+
}
|
|
6194
|
+
closeCurrentContainer() {
|
|
6195
|
+
const visibleContainers = this.containerService.visibleContainers();
|
|
6196
|
+
if (visibleContainers.length === 0) {
|
|
6197
|
+
console.log(`⚠️ [FloatingContainerShortcuts] No containers to close`);
|
|
6198
|
+
return;
|
|
6199
|
+
}
|
|
6200
|
+
const currentContainer = visibleContainers[0]; // Most recent container
|
|
6201
|
+
this.containerService.hide(currentContainer.id);
|
|
6202
|
+
console.log(`❌ [FloatingContainerShortcuts] Closed container: ${currentContainer.config.title}`);
|
|
6203
|
+
}
|
|
6204
|
+
toggleContainerVisibility() {
|
|
6205
|
+
const visibleContainers = this.containerService.visibleContainers();
|
|
6206
|
+
if (visibleContainers.length === 0) {
|
|
6207
|
+
console.log(`⚠️ [FloatingContainerShortcuts] No containers to toggle`);
|
|
6208
|
+
return;
|
|
6209
|
+
}
|
|
6210
|
+
// Toggle visibility of the most recent container using z-index
|
|
6211
|
+
const currentContainer = visibleContainers[0];
|
|
6212
|
+
const currentZIndex = currentContainer.zIndex;
|
|
6213
|
+
if (currentZIndex >= this.Z_INDEX_LAYERS.NORMAL) {
|
|
6214
|
+
// Container is visible, move to hidden layer
|
|
6215
|
+
this.containerService.setZIndex(currentContainer.id, this.Z_INDEX_LAYERS.HIDDEN);
|
|
6216
|
+
console.log(`👁️ [FloatingContainerShortcuts] Hidden container (z-index: ${this.Z_INDEX_LAYERS.HIDDEN}): ${currentContainer.config.title}`);
|
|
6217
|
+
}
|
|
6218
|
+
else {
|
|
6219
|
+
// Container is hidden, move to normal layer
|
|
6220
|
+
this.containerService.setZIndex(currentContainer.id, this.Z_INDEX_LAYERS.NORMAL);
|
|
6221
|
+
console.log(`👁️ [FloatingContainerShortcuts] Shown container (z-index: ${this.Z_INDEX_LAYERS.NORMAL}): ${currentContainer.config.title}`);
|
|
6222
|
+
}
|
|
6223
|
+
}
|
|
6224
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: FloatingContainerShortcutsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
6225
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: FloatingContainerShortcutsService, providedIn: 'root' });
|
|
6226
|
+
}
|
|
6227
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: FloatingContainerShortcutsService, decorators: [{
|
|
6228
|
+
type: Injectable,
|
|
6229
|
+
args: [{
|
|
6230
|
+
providedIn: 'root'
|
|
6231
|
+
}]
|
|
6232
|
+
}], ctorParameters: () => [] });
|
|
6233
|
+
|
|
5635
6234
|
/**
|
|
5636
6235
|
<!-- Basic horizontal (left-right) layout -->
|
|
5637
6236
|
<div class="panel-container">
|
|
@@ -9736,6 +10335,7 @@ class CideEleFloatingContainerComponent {
|
|
|
9736
10335
|
closeEvent = new EventEmitter();
|
|
9737
10336
|
minimizeEvent = new EventEmitter();
|
|
9738
10337
|
maximizeEvent = new EventEmitter();
|
|
10338
|
+
clickEvent = new EventEmitter();
|
|
9739
10339
|
containerRef;
|
|
9740
10340
|
// State signals
|
|
9741
10341
|
position = signal({ x: 100, y: 100 }, ...(ngDevMode ? [{ debugName: "position" }] : []));
|
|
@@ -9750,8 +10350,12 @@ class CideEleFloatingContainerComponent {
|
|
|
9750
10350
|
savedPosition = { x: 100, y: 100 }; // Store position before maximizing
|
|
9751
10351
|
savedHeight = ''; // Store height before maximizing
|
|
9752
10352
|
ngAfterViewInit() {
|
|
9753
|
-
//
|
|
9754
|
-
|
|
10353
|
+
// Only center the container if it's at the default position (100, 100)
|
|
10354
|
+
// This prevents position jumping when containers are focused
|
|
10355
|
+
const currentPos = this.position();
|
|
10356
|
+
if (currentPos.x === 100 && currentPos.y === 100) {
|
|
10357
|
+
this.centerContainer();
|
|
10358
|
+
}
|
|
9755
10359
|
}
|
|
9756
10360
|
constructor() {
|
|
9757
10361
|
// Watch for maximize state changes
|
|
@@ -9854,6 +10458,8 @@ class CideEleFloatingContainerComponent {
|
|
|
9854
10458
|
}
|
|
9855
10459
|
// Action methods
|
|
9856
10460
|
onHeaderClick(event) {
|
|
10461
|
+
// Emit click event to bring container to front
|
|
10462
|
+
this.clickEvent.emit(this.computedConfig().id);
|
|
9857
10463
|
// Only minimize if clicking on the header itself, not on buttons
|
|
9858
10464
|
if (this.isMinimized() && !event.target.closest('button')) {
|
|
9859
10465
|
this.minimize();
|
|
@@ -9862,6 +10468,14 @@ class CideEleFloatingContainerComponent {
|
|
|
9862
10468
|
minimize() {
|
|
9863
10469
|
this.minimizeEvent.emit(this.computedConfig().id);
|
|
9864
10470
|
}
|
|
10471
|
+
bringToFront() {
|
|
10472
|
+
// This will be handled by the container service through the manager component
|
|
10473
|
+
// The manager component will call the service's bringToFront method
|
|
10474
|
+
console.log(`🎯 [FloatingContainer] Container '${this.computedConfig().id}' clicked - bringing to front`);
|
|
10475
|
+
// Preserve current position to prevent jumping
|
|
10476
|
+
const currentPos = this.position();
|
|
10477
|
+
console.log(`🎯 [FloatingContainer] Preserving position: x=${currentPos.x}, y=${currentPos.y}`);
|
|
10478
|
+
}
|
|
9865
10479
|
toggleMaximize() {
|
|
9866
10480
|
this.maximizeEvent.emit(this.computedConfig().id);
|
|
9867
10481
|
}
|
|
@@ -9872,7 +10486,7 @@ class CideEleFloatingContainerComponent {
|
|
|
9872
10486
|
return 'linear-gradient(135deg, var(--cide-theme-primary-color) 0%, var(--tw-blue-400) 100%)';
|
|
9873
10487
|
}
|
|
9874
10488
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9875
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideEleFloatingContainerComponent, isStandalone: true, selector: "cide-ele-floating-container", inputs: { config: "config", isMinimized: "isMinimized", isMaximized: "isMaximized", isVisible: "isVisible" }, outputs: { closeEvent: "closeEvent", minimizeEvent: "minimizeEvent", maximizeEvent: "maximizeEvent" }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: `
|
|
10489
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideEleFloatingContainerComponent, isStandalone: true, selector: "cide-ele-floating-container", inputs: { config: "config", isMinimized: "isMinimized", isMaximized: "isMaximized", isVisible: "isVisible" }, outputs: { closeEvent: "closeEvent", minimizeEvent: "minimizeEvent", maximizeEvent: "maximizeEvent", clickEvent: "clickEvent" }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: `
|
|
9876
10490
|
<div
|
|
9877
10491
|
#container
|
|
9878
10492
|
class="tw-fixed tw-z-50 tw-bg-gray-50 tw-bg-opacity-90 tw-backdrop-blur-sm tw-border tw-border-gray-200 tw-border-opacity-50 tw-rounded-xl tw-shadow-lg tw-transition-all tw-duration-200 tw-flex tw-flex-col"
|
|
@@ -10101,6 +10715,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
|
|
|
10101
10715
|
type: Output
|
|
10102
10716
|
}], maximizeEvent: [{
|
|
10103
10717
|
type: Output
|
|
10718
|
+
}], clickEvent: [{
|
|
10719
|
+
type: Output
|
|
10104
10720
|
}], containerRef: [{
|
|
10105
10721
|
type: ViewChild,
|
|
10106
10722
|
args: ['container']
|
|
@@ -10111,94 +10727,96 @@ class CideEleFloatingContainerManagerComponent {
|
|
|
10111
10727
|
// Computed properties
|
|
10112
10728
|
visibleContainers = computed(() => this.containerService.visibleContainers(), ...(ngDevMode ? [{ debugName: "visibleContainers" }] : []));
|
|
10113
10729
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingContainerManagerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10114
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideEleFloatingContainerManagerComponent, isStandalone: true, selector: "cide-ele-floating-container-manager", ngImport: i0, template: `
|
|
10115
|
-
@for (container of visibleContainers(); track container.id) {
|
|
10116
|
-
<cide-ele-floating-container
|
|
10117
|
-
[config]="containerService.getConfigSignal(container.config)"
|
|
10118
|
-
[isMinimized]="containerService.getMinimizedSignal(container.id)"
|
|
10119
|
-
[isMaximized]="containerService.getMaximizedSignal(container.id)"
|
|
10120
|
-
[isVisible]="containerService.getVisibleSignal(container.id)"
|
|
10121
|
-
[style.z-index]="container.
|
|
10122
|
-
(closeEvent)="containerService.onClose($event)"
|
|
10123
|
-
(minimizeEvent)="containerService.onMinimize($event)"
|
|
10124
|
-
(maximizeEvent)="containerService.onMaximize($event)"
|
|
10125
|
-
|
|
10126
|
-
|
|
10127
|
-
@defer
|
|
10128
|
-
|
|
10129
|
-
|
|
10130
|
-
|
|
10131
|
-
[
|
|
10132
|
-
[
|
|
10133
|
-
|
|
10134
|
-
|
|
10135
|
-
|
|
10136
|
-
|
|
10137
|
-
<
|
|
10138
|
-
|
|
10139
|
-
|
|
10140
|
-
|
|
10141
|
-
|
|
10142
|
-
<
|
|
10143
|
-
<p class="tw-text-
|
|
10144
|
-
<
|
|
10145
|
-
|
|
10146
|
-
|
|
10147
|
-
|
|
10148
|
-
|
|
10149
|
-
|
|
10150
|
-
|
|
10151
|
-
|
|
10152
|
-
|
|
10153
|
-
|
|
10154
|
-
|
|
10155
|
-
|
|
10156
|
-
|
|
10730
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideEleFloatingContainerManagerComponent, isStandalone: true, selector: "cide-ele-floating-container-manager", ngImport: i0, template: `
|
|
10731
|
+
@for (container of visibleContainers(); track container.id) {
|
|
10732
|
+
<cide-ele-floating-container
|
|
10733
|
+
[config]="containerService.getConfigSignal(container.config)"
|
|
10734
|
+
[isMinimized]="containerService.getMinimizedSignal(container.id)"
|
|
10735
|
+
[isMaximized]="containerService.getMaximizedSignal(container.id)"
|
|
10736
|
+
[isVisible]="containerService.getVisibleSignal(container.id)"
|
|
10737
|
+
[style.z-index]="containerService.getZIndexSignal(container.id)()"
|
|
10738
|
+
(closeEvent)="containerService.onClose($event)"
|
|
10739
|
+
(minimizeEvent)="containerService.onMinimize($event)"
|
|
10740
|
+
(maximizeEvent)="containerService.onMaximize($event)"
|
|
10741
|
+
(clickEvent)="containerService.bringToFront($event)">
|
|
10742
|
+
|
|
10743
|
+
<!-- Dynamic content loading with @defer for performance -->
|
|
10744
|
+
@defer (when container.isVisible) {
|
|
10745
|
+
<div
|
|
10746
|
+
cideEleFloatingDynamic
|
|
10747
|
+
[componentId]="container.config.componentId || container.config.id"
|
|
10748
|
+
[componentConfig]="containerService.getComponentConfig(container.config)"
|
|
10749
|
+
[isVisible]="container.isVisible">
|
|
10750
|
+
</div>
|
|
10751
|
+
} @placeholder {
|
|
10752
|
+
<div class="tw-flex tw-items-center tw-justify-center tw-p-4">
|
|
10753
|
+
<cide-ele-spinner size="sm"></cide-ele-spinner>
|
|
10754
|
+
<span class="tw-ml-2 tw-text-sm tw-text-gray-600">Loading component...</span>
|
|
10755
|
+
</div>
|
|
10756
|
+
} @error {
|
|
10757
|
+
<div class="tw-flex tw-flex-col tw-items-center tw-justify-center tw-p-4 tw-text-center">
|
|
10758
|
+
<cide-ele-icon class="tw-w-8 tw-h-8 tw-text-red-500 tw-mb-2">error</cide-ele-icon>
|
|
10759
|
+
<p class="tw-text-red-600 tw-font-medium">Failed to load component</p>
|
|
10760
|
+
<p class="tw-text-gray-500 tw-text-sm">Component "{{ container.config.componentId || container.config.id }}" is not available</p>
|
|
10761
|
+
<button
|
|
10762
|
+
cideEleButton
|
|
10763
|
+
variant="outline"
|
|
10764
|
+
size="xs"
|
|
10765
|
+
(click)="containerService.onClose(container.id)"
|
|
10766
|
+
class="tw-mt-2">
|
|
10767
|
+
Close
|
|
10768
|
+
</button>
|
|
10769
|
+
</div>
|
|
10770
|
+
}
|
|
10771
|
+
</cide-ele-floating-container>
|
|
10772
|
+
}
|
|
10773
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: CideEleFloatingContainerComponent, selector: "cide-ele-floating-container", inputs: ["config", "isMinimized", "isMaximized", "isVisible"], outputs: ["closeEvent", "minimizeEvent", "maximizeEvent", "clickEvent"] }, { kind: "component", type: CideSpinnerComponent, selector: "cide-ele-spinner", inputs: ["size", "type"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }], deferBlockDependencies: [() => [Promise.resolve().then(function () { return floatingContainerDynamic_directive; }).then(m => m.CideEleFloatingContainerDynamicDirective)]] });
|
|
10157
10774
|
}
|
|
10158
10775
|
i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingContainerManagerComponent, resolveDeferredDeps: () => [Promise.resolve().then(function () { return floatingContainerDynamic_directive; }).then(m => m.CideEleFloatingContainerDynamicDirective)], resolveMetadata: CideEleFloatingContainerDynamicDirective => ({ decorators: [{
|
|
10159
10776
|
type: Component,
|
|
10160
|
-
args: [{ selector: 'cide-ele-floating-container-manager', standalone: true, imports: [CommonModule, CideEleFloatingContainerComponent, CideEleFloatingContainerDynamicDirective, CideSpinnerComponent, CideEleButtonComponent, CideIconComponent], template: `
|
|
10161
|
-
@for (container of visibleContainers(); track container.id) {
|
|
10162
|
-
<cide-ele-floating-container
|
|
10163
|
-
[config]="containerService.getConfigSignal(container.config)"
|
|
10164
|
-
[isMinimized]="containerService.getMinimizedSignal(container.id)"
|
|
10165
|
-
[isMaximized]="containerService.getMaximizedSignal(container.id)"
|
|
10166
|
-
[isVisible]="containerService.getVisibleSignal(container.id)"
|
|
10167
|
-
[style.z-index]="container.
|
|
10168
|
-
(closeEvent)="containerService.onClose($event)"
|
|
10169
|
-
(minimizeEvent)="containerService.onMinimize($event)"
|
|
10170
|
-
(maximizeEvent)="containerService.onMaximize($event)"
|
|
10171
|
-
|
|
10172
|
-
|
|
10173
|
-
@defer
|
|
10174
|
-
|
|
10175
|
-
|
|
10176
|
-
|
|
10177
|
-
[
|
|
10178
|
-
[
|
|
10179
|
-
|
|
10180
|
-
|
|
10181
|
-
|
|
10182
|
-
|
|
10183
|
-
<
|
|
10184
|
-
|
|
10185
|
-
|
|
10186
|
-
|
|
10187
|
-
|
|
10188
|
-
<
|
|
10189
|
-
<p class="tw-text-
|
|
10190
|
-
<
|
|
10191
|
-
|
|
10192
|
-
|
|
10193
|
-
|
|
10194
|
-
|
|
10195
|
-
|
|
10196
|
-
|
|
10197
|
-
|
|
10198
|
-
|
|
10199
|
-
|
|
10200
|
-
|
|
10201
|
-
|
|
10777
|
+
args: [{ selector: 'cide-ele-floating-container-manager', standalone: true, imports: [CommonModule, CideEleFloatingContainerComponent, CideEleFloatingContainerDynamicDirective, CideSpinnerComponent, CideEleButtonComponent, CideIconComponent], template: `
|
|
10778
|
+
@for (container of visibleContainers(); track container.id) {
|
|
10779
|
+
<cide-ele-floating-container
|
|
10780
|
+
[config]="containerService.getConfigSignal(container.config)"
|
|
10781
|
+
[isMinimized]="containerService.getMinimizedSignal(container.id)"
|
|
10782
|
+
[isMaximized]="containerService.getMaximizedSignal(container.id)"
|
|
10783
|
+
[isVisible]="containerService.getVisibleSignal(container.id)"
|
|
10784
|
+
[style.z-index]="containerService.getZIndexSignal(container.id)()"
|
|
10785
|
+
(closeEvent)="containerService.onClose($event)"
|
|
10786
|
+
(minimizeEvent)="containerService.onMinimize($event)"
|
|
10787
|
+
(maximizeEvent)="containerService.onMaximize($event)"
|
|
10788
|
+
(clickEvent)="containerService.bringToFront($event)">
|
|
10789
|
+
|
|
10790
|
+
<!-- Dynamic content loading with @defer for performance -->
|
|
10791
|
+
@defer (when container.isVisible) {
|
|
10792
|
+
<div
|
|
10793
|
+
cideEleFloatingDynamic
|
|
10794
|
+
[componentId]="container.config.componentId || container.config.id"
|
|
10795
|
+
[componentConfig]="containerService.getComponentConfig(container.config)"
|
|
10796
|
+
[isVisible]="container.isVisible">
|
|
10797
|
+
</div>
|
|
10798
|
+
} @placeholder {
|
|
10799
|
+
<div class="tw-flex tw-items-center tw-justify-center tw-p-4">
|
|
10800
|
+
<cide-ele-spinner size="sm"></cide-ele-spinner>
|
|
10801
|
+
<span class="tw-ml-2 tw-text-sm tw-text-gray-600">Loading component...</span>
|
|
10802
|
+
</div>
|
|
10803
|
+
} @error {
|
|
10804
|
+
<div class="tw-flex tw-flex-col tw-items-center tw-justify-center tw-p-4 tw-text-center">
|
|
10805
|
+
<cide-ele-icon class="tw-w-8 tw-h-8 tw-text-red-500 tw-mb-2">error</cide-ele-icon>
|
|
10806
|
+
<p class="tw-text-red-600 tw-font-medium">Failed to load component</p>
|
|
10807
|
+
<p class="tw-text-gray-500 tw-text-sm">Component "{{ container.config.componentId || container.config.id }}" is not available</p>
|
|
10808
|
+
<button
|
|
10809
|
+
cideEleButton
|
|
10810
|
+
variant="outline"
|
|
10811
|
+
size="xs"
|
|
10812
|
+
(click)="containerService.onClose(container.id)"
|
|
10813
|
+
class="tw-mt-2">
|
|
10814
|
+
Close
|
|
10815
|
+
</button>
|
|
10816
|
+
</div>
|
|
10817
|
+
}
|
|
10818
|
+
</cide-ele-floating-container>
|
|
10819
|
+
}
|
|
10202
10820
|
` }]
|
|
10203
10821
|
}], ctorParameters: null, propDecorators: null }) });
|
|
10204
10822
|
|
|
@@ -10458,5 +11076,5 @@ var floatingContainerDynamic_directive = /*#__PURE__*/Object.freeze({
|
|
|
10458
11076
|
* Generated bundle index. Do not edit.
|
|
10459
11077
|
*/
|
|
10460
11078
|
|
|
10461
|
-
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, ICoreCyfmSave, MFileManager, NotificationService, TooltipDirective };
|
|
11079
|
+
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 };
|
|
10462
11080
|
//# sourceMappingURL=cloud-ide-element.mjs.map
|