cloud-ide-element 1.0.119 → 1.0.121
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/cloud-ide-element.mjs +305 -474
- package/fesm2022/cloud-ide-element.mjs.map +1 -1
- package/index.d.ts +77 -104
- package/package.json +1 -1
|
@@ -4990,9 +4990,8 @@ class CideEleFloatingFileUploaderComponent {
|
|
|
4990
4990
|
fileManagerService = inject(CideEleFileManagerService);
|
|
4991
4991
|
// Input data from floating container
|
|
4992
4992
|
data = {};
|
|
4993
|
-
// Signals for reactive state
|
|
4993
|
+
// Signals for reactive state (simplified for floating container)
|
|
4994
4994
|
isVisible = signal(true, ...(ngDevMode ? [{ debugName: "isVisible" }] : [])); // Set to true by default for floating containers
|
|
4995
|
-
isMinimized = signal(false, ...(ngDevMode ? [{ debugName: "isMinimized" }] : []));
|
|
4996
4995
|
currentUserId = signal('', ...(ngDevMode ? [{ debugName: "currentUserId" }] : []));
|
|
4997
4996
|
currentGroupId = signal(null, ...(ngDevMode ? [{ debugName: "currentGroupId" }] : []));
|
|
4998
4997
|
// Use file manager service as the single source of truth
|
|
@@ -5016,23 +5015,27 @@ class CideEleFloatingFileUploaderComponent {
|
|
|
5016
5015
|
hasFilesToShow = computed(() => {
|
|
5017
5016
|
return this.hasActiveUploads() || this.allFilesForGroup().length > 0;
|
|
5018
5017
|
}, ...(ngDevMode ? [{ debugName: "hasFilesToShow" }] : []));
|
|
5018
|
+
// Count methods for template
|
|
5019
|
+
getUploadingCount() {
|
|
5020
|
+
return this.activeUploadsLocal().length;
|
|
5021
|
+
}
|
|
5022
|
+
getCompletedCount() {
|
|
5023
|
+
return this.completedUploads().length;
|
|
5024
|
+
}
|
|
5025
|
+
getFailedCount() {
|
|
5026
|
+
return this.failedUploads().length;
|
|
5027
|
+
}
|
|
5019
5028
|
// Animation states
|
|
5020
5029
|
isAnimating = signal(false, ...(ngDevMode ? [{ debugName: "isAnimating" }] : []));
|
|
5021
|
-
// Drag functionality
|
|
5022
|
-
isDragging = signal(false, ...(ngDevMode ? [{ debugName: "isDragging" }] : []));
|
|
5023
|
-
position = signal({ x: 0, y: 0 }, ...(ngDevMode ? [{ debugName: "position" }] : []));
|
|
5024
|
-
dragOffset = { x: 0, y: 0 };
|
|
5030
|
+
// Drag functionality removed - handled by floating container
|
|
5025
5031
|
// File drag and drop functionality
|
|
5026
5032
|
isDragOver = signal(false, ...(ngDevMode ? [{ debugName: "isDragOver" }] : []));
|
|
5027
|
-
// Window resize handler
|
|
5028
|
-
windowResizeHandler;
|
|
5033
|
+
// Window resize handler removed - handled by floating container
|
|
5029
5034
|
// Cached dimensions for performance
|
|
5030
|
-
|
|
5031
|
-
lastDimensionUpdate = 0;
|
|
5035
|
+
// Cached dimensions removed - handled by floating container
|
|
5032
5036
|
constructor() {
|
|
5033
5037
|
console.log('🚀 [FloatingFileUploader] Component initialized');
|
|
5034
|
-
//
|
|
5035
|
-
this.initializePosition();
|
|
5038
|
+
// Position initialization removed - handled by floating container
|
|
5036
5039
|
// Consolidated effect for all visibility logic - SINGLE SOURCE OF TRUTH
|
|
5037
5040
|
effect(() => {
|
|
5038
5041
|
const hasActiveUploads = this.hasActiveUploads();
|
|
@@ -5079,8 +5082,7 @@ class CideEleFloatingFileUploaderComponent {
|
|
|
5079
5082
|
this.setupDragAndDrop();
|
|
5080
5083
|
// Set up file input change listeners
|
|
5081
5084
|
this.setupFileInputListeners();
|
|
5082
|
-
//
|
|
5083
|
-
this.setupWindowResize();
|
|
5085
|
+
// Window resize setup removed - handled by floating container
|
|
5084
5086
|
}
|
|
5085
5087
|
initializeWithData() {
|
|
5086
5088
|
console.log('🚀 [FloatingFileUploader] Initializing with data:', this.data);
|
|
@@ -5119,10 +5121,7 @@ class CideEleFloatingFileUploaderComponent {
|
|
|
5119
5121
|
console.log('🧹 [FloatingFileUploader] Component destroyed');
|
|
5120
5122
|
this.removeDragAndDropListeners();
|
|
5121
5123
|
this.removeFileInputListeners();
|
|
5122
|
-
//
|
|
5123
|
-
if (this.windowResizeHandler) {
|
|
5124
|
-
window.removeEventListener('resize', this.windowResizeHandler);
|
|
5125
|
-
}
|
|
5124
|
+
// Window resize cleanup removed - handled by floating container
|
|
5126
5125
|
}
|
|
5127
5126
|
/**
|
|
5128
5127
|
* Set up drag and drop functionality
|
|
@@ -5249,20 +5248,7 @@ class CideEleFloatingFileUploaderComponent {
|
|
|
5249
5248
|
this.isAnimating.set(false);
|
|
5250
5249
|
}, 300);
|
|
5251
5250
|
}
|
|
5252
|
-
|
|
5253
|
-
* Toggle minimize state
|
|
5254
|
-
*/
|
|
5255
|
-
toggleMinimize() {
|
|
5256
|
-
this.isMinimized.set(!this.isMinimized());
|
|
5257
|
-
}
|
|
5258
|
-
/**
|
|
5259
|
-
* Close the floating uploader
|
|
5260
|
-
*/
|
|
5261
|
-
close() {
|
|
5262
|
-
// Don't clear files from service - just hide the uploader
|
|
5263
|
-
// Files will be fetched from API when "Show Files" is clicked
|
|
5264
|
-
this.hideWithAnimation();
|
|
5265
|
-
}
|
|
5251
|
+
// Minimize and close functionality removed - handled by floating container
|
|
5266
5252
|
/**
|
|
5267
5253
|
* Get upload summary text
|
|
5268
5254
|
*/
|
|
@@ -5432,143 +5418,15 @@ class CideEleFloatingFileUploaderComponent {
|
|
|
5432
5418
|
});
|
|
5433
5419
|
});
|
|
5434
5420
|
}
|
|
5435
|
-
/**
|
|
5436
|
-
* Update cached dimensions (throttled for performance)
|
|
5437
|
-
*/
|
|
5438
|
-
updateCachedDimensions() {
|
|
5439
|
-
const now = Date.now();
|
|
5440
|
-
// Only update dimensions every 100ms to avoid excessive DOM queries
|
|
5441
|
-
if (now - this.lastDimensionUpdate < 100) {
|
|
5442
|
-
return;
|
|
5443
|
-
}
|
|
5444
|
-
const uploaderElement = document.querySelector('.floating-uploader');
|
|
5445
|
-
if (uploaderElement) {
|
|
5446
|
-
this.cachedDimensions = {
|
|
5447
|
-
width: uploaderElement.offsetWidth,
|
|
5448
|
-
height: uploaderElement.offsetHeight
|
|
5449
|
-
};
|
|
5450
|
-
this.lastDimensionUpdate = now;
|
|
5451
|
-
}
|
|
5452
|
-
}
|
|
5453
|
-
/**
|
|
5454
|
-
* Start dragging the uploader
|
|
5455
|
-
*/
|
|
5456
|
-
startDrag(event) {
|
|
5457
|
-
event.preventDefault();
|
|
5458
|
-
const clientX = event instanceof MouseEvent ? event.clientX : event.touches[0].clientX;
|
|
5459
|
-
const clientY = event instanceof MouseEvent ? event.clientY : event.touches[0].clientY;
|
|
5460
|
-
const currentPos = this.position();
|
|
5461
|
-
this.dragOffset = {
|
|
5462
|
-
x: clientX - currentPos.x,
|
|
5463
|
-
y: clientY - currentPos.y
|
|
5464
|
-
};
|
|
5465
|
-
this.isDragging.set(true);
|
|
5466
|
-
// Update cached dimensions at the start of drag for better performance
|
|
5467
|
-
this.updateCachedDimensions();
|
|
5468
|
-
// Add event listeners for drag and end
|
|
5469
|
-
const moveHandler = (e) => this.onDrag(e);
|
|
5470
|
-
const endHandler = () => this.endDrag(moveHandler, endHandler);
|
|
5471
|
-
document.addEventListener('mousemove', moveHandler, { passive: false });
|
|
5472
|
-
document.addEventListener('mouseup', endHandler);
|
|
5473
|
-
document.addEventListener('touchmove', moveHandler, { passive: false });
|
|
5474
|
-
document.addEventListener('touchend', endHandler);
|
|
5475
|
-
// Prevent text selection during drag
|
|
5476
|
-
document.body.style.userSelect = 'none';
|
|
5477
|
-
}
|
|
5478
|
-
/**
|
|
5479
|
-
* Handle dragging movement
|
|
5480
|
-
*/
|
|
5481
|
-
onDrag(event) {
|
|
5482
|
-
if (!this.isDragging())
|
|
5483
|
-
return;
|
|
5484
|
-
event.preventDefault();
|
|
5485
|
-
const clientX = event instanceof MouseEvent ? event.clientX : event.touches[0].clientX;
|
|
5486
|
-
const clientY = event instanceof MouseEvent ? event.clientY : event.touches[0].clientY;
|
|
5487
|
-
const newX = clientX - this.dragOffset.x;
|
|
5488
|
-
const newY = clientY - this.dragOffset.y;
|
|
5489
|
-
// Constrain to viewport bounds using cached dimensions for performance
|
|
5490
|
-
const viewportWidth = window.innerWidth;
|
|
5491
|
-
const viewportHeight = window.innerHeight;
|
|
5492
|
-
// Use cached dimensions instead of DOM queries for better performance
|
|
5493
|
-
const uploaderWidth = this.cachedDimensions.width;
|
|
5494
|
-
const uploaderHeight = this.cachedDimensions.height;
|
|
5495
|
-
// Ensure uploader stays within viewport bounds
|
|
5496
|
-
const constrainedX = Math.max(0, Math.min(newX, viewportWidth - uploaderWidth));
|
|
5497
|
-
const constrainedY = Math.max(0, Math.min(newY, viewportHeight - uploaderHeight));
|
|
5498
|
-
this.position.set({ x: constrainedX, y: constrainedY });
|
|
5499
|
-
}
|
|
5500
|
-
/**
|
|
5501
|
-
* End dragging
|
|
5502
|
-
*/
|
|
5503
|
-
endDrag(moveHandler, endHandler) {
|
|
5504
|
-
this.isDragging.set(false);
|
|
5505
|
-
// Remove event listeners
|
|
5506
|
-
document.removeEventListener('mousemove', moveHandler);
|
|
5507
|
-
document.removeEventListener('mouseup', endHandler);
|
|
5508
|
-
document.removeEventListener('touchmove', moveHandler);
|
|
5509
|
-
document.removeEventListener('touchend', endHandler);
|
|
5510
|
-
// Restore text selection
|
|
5511
|
-
document.body.style.userSelect = '';
|
|
5512
|
-
}
|
|
5513
|
-
/**
|
|
5514
|
-
* Set up window resize listener to keep uploader within bounds
|
|
5515
|
-
*/
|
|
5516
|
-
setupWindowResize() {
|
|
5517
|
-
const handleResize = () => {
|
|
5518
|
-
const currentPos = this.position();
|
|
5519
|
-
const viewportWidth = window.innerWidth;
|
|
5520
|
-
const viewportHeight = window.innerHeight;
|
|
5521
|
-
// Update cached dimensions on resize
|
|
5522
|
-
this.updateCachedDimensions();
|
|
5523
|
-
// Use cached dimensions for performance
|
|
5524
|
-
const uploaderWidth = this.cachedDimensions.width;
|
|
5525
|
-
const uploaderHeight = this.cachedDimensions.height;
|
|
5526
|
-
// Constrain position to new viewport bounds
|
|
5527
|
-
const constrainedX = Math.max(0, Math.min(currentPos.x, viewportWidth - uploaderWidth));
|
|
5528
|
-
const constrainedY = Math.max(0, Math.min(currentPos.y, viewportHeight - uploaderHeight));
|
|
5529
|
-
// Update position if it changed
|
|
5530
|
-
if (constrainedX !== currentPos.x || constrainedY !== currentPos.y) {
|
|
5531
|
-
this.position.set({ x: constrainedX, y: constrainedY });
|
|
5532
|
-
console.log('📐 [FloatingFileUploader] Position adjusted for window resize:', { x: constrainedX, y: constrainedY });
|
|
5533
|
-
}
|
|
5534
|
-
};
|
|
5535
|
-
window.addEventListener('resize', handleResize);
|
|
5536
|
-
// Store reference for cleanup
|
|
5537
|
-
this.windowResizeHandler = handleResize;
|
|
5538
|
-
}
|
|
5539
|
-
/**
|
|
5540
|
-
* Initialize default position
|
|
5541
|
-
*/
|
|
5542
|
-
initializePosition() {
|
|
5543
|
-
// Set initial position to bottom-right corner
|
|
5544
|
-
const viewportWidth = window.innerWidth;
|
|
5545
|
-
const viewportHeight = window.innerHeight;
|
|
5546
|
-
// Initialize cached dimensions with defaults
|
|
5547
|
-
this.cachedDimensions = { width: 320, height: 300 };
|
|
5548
|
-
// Use cached dimensions for initial positioning
|
|
5549
|
-
const uploaderWidth = this.cachedDimensions.width;
|
|
5550
|
-
const uploaderHeight = this.cachedDimensions.height;
|
|
5551
|
-
// Ensure initial position is within bounds
|
|
5552
|
-
const initialX = Math.max(20, viewportWidth - uploaderWidth - 20);
|
|
5553
|
-
const initialY = Math.max(20, viewportHeight - uploaderHeight - 20);
|
|
5554
|
-
this.position.set({
|
|
5555
|
-
x: initialX,
|
|
5556
|
-
y: initialY
|
|
5557
|
-
});
|
|
5558
|
-
// Update dimensions after a short delay to get actual rendered size
|
|
5559
|
-
setTimeout(() => {
|
|
5560
|
-
this.updateCachedDimensions();
|
|
5561
|
-
}, 100);
|
|
5562
|
-
}
|
|
5563
5421
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingFileUploaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
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"] }] });
|
|
5422
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideEleFloatingFileUploaderComponent, isStandalone: true, selector: "cide-ele-floating-file-uploader", inputs: { data: "data" }, ngImport: i0, template: "<!-- File Uploader Content (No absolute positioning - works within floating container) -->\n@if (isVisible()) {\n<div class=\"tw-w-full tw-max-h-[500px] tw-bg-white tw-rounded-xl tw-shadow-lg tw-border tw-border-gray-200 tw-overflow-hidden tw-transition-all tw-duration-300\">\n <!-- Simple header without window controls (floating container handles these) -->\n <div class=\"tw-flex tw-items-center tw-justify-between tw-px-4 tw-py-3 tw-bg-gray-50 tw-border-b tw-border-gray-200\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <div class=\"tw-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-bg-blue-600 tw-rounded-md tw-text-white\">\n <cide-ele-icon size=\"sm\">cloud_upload</cide-ele-icon>\n </div>\n <div>\n <div class=\"tw-text-sm tw-font-semibold tw-text-gray-900\">{{ data.title || 'File Upload' }}</div>\n <div class=\"tw-text-xs tw-text-gray-500\">{{ getUploadSummary() }}</div>\n </div>\n </div>\n </div>\n\n <!-- Content -->\n <div class=\"tw-max-h-[400px] tw-overflow-y-auto\">\n \n <!-- Drag and Drop Zone -->\n <div class=\"tw-m-2 tw-p-3 tw-border-2 tw-border-dashed tw-border-gray-300 tw-rounded-md tw-bg-gray-50 tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-center hover:tw-border-blue-500 hover:tw-bg-blue-50\" \n [class.tw-border-blue-500]=\"isDragOver()\"\n [class.tw-bg-blue-100]=\"isDragOver()\"\n [class.tw-scale-105]=\"isDragOver()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\" \n (drop)=\"onDrop($event)\" \n (click)=\"triggerFileInput()\">\n \n <!-- Hidden file input -->\n <input #fileInput \n type=\"file\" \n [multiple]=\"data.multiple !== false\" \n [accept]=\"data.allowedFileTypes?.join(',') || '*/*'\" \n (change)=\"onFileInputChange($event)\" \n class=\"tw-hidden\">\n \n <div class=\"tw-flex tw-flex-col tw-items-center tw-gap-2\">\n <cide-ele-icon class=\"tw-text-gray-400 tw-transition-colors tw-duration-200\" \n [class.tw-text-blue-500]=\"isDragOver()\"\n size=\"sm\">cloud_upload</cide-ele-icon>\n \n <div>\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-700\">\n {{ isDragOver() ? 'Drop files here' : 'Drag files here or click to browse' }}\n </div>\n @if (data.description) {\n <div class=\"tw-text-xs tw-text-gray-500 tw-mt-1\">{{ data.description }}</div>\n }\n </div>\n </div>\n </div>\n \n <!-- Upload Queue - Show files from service state -->\n @if (allFilesForGroup().length > 0) {\n <div class=\"tw-space-y-0\">\n <!-- Show all files from service state -->\n @for (file of allFilesForGroup(); track file.fileId) {\n <div class=\"tw-flex tw-items-center tw-px-4 tw-py-2 tw-border-b tw-border-gray-100 tw-transition-colors tw-duration-200\"\n [class.tw-bg-blue-50]=\"file.stage === 'uploading'\"\n [class.tw-bg-green-50]=\"file.stage === 'complete'\"\n [class.tw-bg-red-50]=\"file.stage === 'error'\">\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-flex-1 tw-min-w-0\">\n <cide-ele-icon class=\"tw-flex-shrink-0\" size=\"xs\">{{ getStatusIcon(file.stage) }}</cide-ele-icon>\n <div class=\"tw-min-w-0 tw-flex-1\">\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\">{{ file.fileName }}</div>\n <div class=\"tw-text-xs\">\n @switch (file.stage) {\n @case ('pending') {\n <span class=\"tw-text-yellow-600 tw-font-medium\">Waiting...</span>\n }\n @case ('reading') {\n <span class=\"tw-text-yellow-600 tw-font-medium\">Reading...</span>\n }\n @case ('uploading') {\n <span class=\"tw-text-blue-600 tw-font-medium\">Uploading...</span>\n }\n @case ('complete') {\n <span class=\"tw-text-green-600 tw-font-medium\">Completed</span>\n }\n @case ('error') {\n <span class=\"tw-text-red-600 tw-font-medium\">Failed</span>\n }\n }\n </div>\n </div>\n </div>\n\n <!-- Progress Bar (only for uploading files) -->\n @if (file.stage === 'uploading' && file.percentage !== undefined) {\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-ml-2 tw-min-w-[80px]\">\n <div class=\"tw-flex-1 tw-h-1 tw-bg-gray-200 tw-rounded-full tw-overflow-hidden\">\n <div class=\"tw-h-full tw-bg-blue-500 tw-transition-all tw-duration-300\" [style.width.%]=\"file.percentage\"></div>\n </div>\n <span class=\"tw-text-xs tw-text-gray-500 tw-min-w-[24px] tw-text-right\">{{ file.percentage }}%</span>\n </div>\n }\n\n <!-- Actions -->\n <div class=\"tw-flex tw-gap-1 tw-ml-2\">\n @switch (file.stage) {\n @case ('pending') {\n <button class=\"tw-flex tw-items-center tw-justify-center tw-w-5 tw-h-5 tw-border-none tw-bg-transparent tw-rounded tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-gray-400 hover:tw-bg-red-50 hover:tw-text-red-600\" \n (click)=\"cancelUpload(file.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('reading') {\n <button class=\"tw-flex tw-items-center tw-justify-center tw-w-5 tw-h-5 tw-border-none tw-bg-transparent tw-rounded tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-gray-400 hover:tw-bg-red-50 hover:tw-text-red-600\" \n (click)=\"cancelUpload(file.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('uploading') {\n <button class=\"tw-flex tw-items-center tw-justify-center tw-w-5 tw-h-5 tw-border-none tw-bg-transparent tw-rounded tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-gray-400 hover:tw-bg-red-50 hover:tw-text-red-600\" \n (click)=\"cancelUpload(file.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('complete') {\n <button class=\"tw-flex tw-items-center tw-justify-center tw-w-5 tw-h-5 tw-border-none tw-bg-transparent tw-rounded tw-cursor-pointer tw-text-green-600\" title=\"Completed\">\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\n </button>\n }\n @case ('error') {\n <button class=\"tw-flex tw-items-center tw-justify-center tw-w-5 tw-h-5 tw-border-none tw-bg-transparent tw-rounded tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-gray-400 hover:tw-bg-blue-50 hover:tw-text-blue-600\" \n title=\"Retry\">\n <cide-ele-icon size=\"xs\">refresh</cide-ele-icon>\n </button>\n }\n }\n </div>\n </div>\n }\n </div>\n } @else {\n <!-- No uploads message when manually opened -->\n <div class=\"tw-p-8 tw-text-center tw-text-gray-500\">\n <div class=\"tw-flex tw-flex-col tw-items-center tw-gap-4\">\n <cide-ele-icon size=\"md\" class=\"tw-text-gray-300 tw-opacity-70\">cloud_upload</cide-ele-icon>\n <div>\n <h4 class=\"tw-text-lg tw-font-semibold tw-text-gray-700 tw-mb-2\">No active uploads</h4>\n <p class=\"tw-text-sm tw-text-gray-500\">Upload files to see their progress here</p>\n </div>\n </div>\n </div>\n }\n </div>\n\n <!-- Footer -->\n <div class=\"tw-px-4 tw-py-2 tw-bg-gray-50 tw-border-t tw-border-gray-200\">\n <div class=\"tw-flex tw-gap-3 tw-text-xs\">\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-blue-600\" \n [class.tw-text-blue-600]=\"hasActiveUploads()\">\n <cide-ele-icon size=\"xs\">upload</cide-ele-icon>\n <span>{{ getUploadingCount() }} uploading</span>\n </div>\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-green-600\">\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\n <span>{{ getCompletedCount() }} completed</span>\n </div>\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-red-600\" \n [class.tw-text-red-600]=\"getFailedCount() > 0\">\n <cide-ele-icon size=\"xs\">error</cide-ele-icon>\n <span>{{ getFailedCount() }} failed</span>\n </div>\n </div>\n </div>\n</div>\n}", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }] });
|
|
5565
5423
|
}
|
|
5566
5424
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingFileUploaderComponent, decorators: [{
|
|
5567
5425
|
type: Component,
|
|
5568
5426
|
args: [{ selector: 'cide-ele-floating-file-uploader', standalone: true, imports: [
|
|
5569
5427
|
CommonModule,
|
|
5570
5428
|
CideIconComponent
|
|
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"] }]
|
|
5429
|
+
], template: "<!-- File Uploader Content (No absolute positioning - works within floating container) -->\n@if (isVisible()) {\n<div class=\"tw-w-full tw-max-h-[500px] tw-bg-white tw-rounded-xl tw-shadow-lg tw-border tw-border-gray-200 tw-overflow-hidden tw-transition-all tw-duration-300\">\n <!-- Simple header without window controls (floating container handles these) -->\n <div class=\"tw-flex tw-items-center tw-justify-between tw-px-4 tw-py-3 tw-bg-gray-50 tw-border-b tw-border-gray-200\">\n <div class=\"tw-flex tw-items-center tw-gap-2\">\n <div class=\"tw-flex tw-items-center tw-justify-center tw-w-6 tw-h-6 tw-bg-blue-600 tw-rounded-md tw-text-white\">\n <cide-ele-icon size=\"sm\">cloud_upload</cide-ele-icon>\n </div>\n <div>\n <div class=\"tw-text-sm tw-font-semibold tw-text-gray-900\">{{ data.title || 'File Upload' }}</div>\n <div class=\"tw-text-xs tw-text-gray-500\">{{ getUploadSummary() }}</div>\n </div>\n </div>\n </div>\n\n <!-- Content -->\n <div class=\"tw-max-h-[400px] tw-overflow-y-auto\">\n \n <!-- Drag and Drop Zone -->\n <div class=\"tw-m-2 tw-p-3 tw-border-2 tw-border-dashed tw-border-gray-300 tw-rounded-md tw-bg-gray-50 tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-center hover:tw-border-blue-500 hover:tw-bg-blue-50\" \n [class.tw-border-blue-500]=\"isDragOver()\"\n [class.tw-bg-blue-100]=\"isDragOver()\"\n [class.tw-scale-105]=\"isDragOver()\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\" \n (drop)=\"onDrop($event)\" \n (click)=\"triggerFileInput()\">\n \n <!-- Hidden file input -->\n <input #fileInput \n type=\"file\" \n [multiple]=\"data.multiple !== false\" \n [accept]=\"data.allowedFileTypes?.join(',') || '*/*'\" \n (change)=\"onFileInputChange($event)\" \n class=\"tw-hidden\">\n \n <div class=\"tw-flex tw-flex-col tw-items-center tw-gap-2\">\n <cide-ele-icon class=\"tw-text-gray-400 tw-transition-colors tw-duration-200\" \n [class.tw-text-blue-500]=\"isDragOver()\"\n size=\"sm\">cloud_upload</cide-ele-icon>\n \n <div>\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-700\">\n {{ isDragOver() ? 'Drop files here' : 'Drag files here or click to browse' }}\n </div>\n @if (data.description) {\n <div class=\"tw-text-xs tw-text-gray-500 tw-mt-1\">{{ data.description }}</div>\n }\n </div>\n </div>\n </div>\n \n <!-- Upload Queue - Show files from service state -->\n @if (allFilesForGroup().length > 0) {\n <div class=\"tw-space-y-0\">\n <!-- Show all files from service state -->\n @for (file of allFilesForGroup(); track file.fileId) {\n <div class=\"tw-flex tw-items-center tw-px-4 tw-py-2 tw-border-b tw-border-gray-100 tw-transition-colors tw-duration-200\"\n [class.tw-bg-blue-50]=\"file.stage === 'uploading'\"\n [class.tw-bg-green-50]=\"file.stage === 'complete'\"\n [class.tw-bg-red-50]=\"file.stage === 'error'\">\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-flex-1 tw-min-w-0\">\n <cide-ele-icon class=\"tw-flex-shrink-0\" size=\"xs\">{{ getStatusIcon(file.stage) }}</cide-ele-icon>\n <div class=\"tw-min-w-0 tw-flex-1\">\n <div class=\"tw-text-sm tw-font-medium tw-text-gray-900 tw-truncate\">{{ file.fileName }}</div>\n <div class=\"tw-text-xs\">\n @switch (file.stage) {\n @case ('pending') {\n <span class=\"tw-text-yellow-600 tw-font-medium\">Waiting...</span>\n }\n @case ('reading') {\n <span class=\"tw-text-yellow-600 tw-font-medium\">Reading...</span>\n }\n @case ('uploading') {\n <span class=\"tw-text-blue-600 tw-font-medium\">Uploading...</span>\n }\n @case ('complete') {\n <span class=\"tw-text-green-600 tw-font-medium\">Completed</span>\n }\n @case ('error') {\n <span class=\"tw-text-red-600 tw-font-medium\">Failed</span>\n }\n }\n </div>\n </div>\n </div>\n\n <!-- Progress Bar (only for uploading files) -->\n @if (file.stage === 'uploading' && file.percentage !== undefined) {\n <div class=\"tw-flex tw-items-center tw-gap-2 tw-ml-2 tw-min-w-[80px]\">\n <div class=\"tw-flex-1 tw-h-1 tw-bg-gray-200 tw-rounded-full tw-overflow-hidden\">\n <div class=\"tw-h-full tw-bg-blue-500 tw-transition-all tw-duration-300\" [style.width.%]=\"file.percentage\"></div>\n </div>\n <span class=\"tw-text-xs tw-text-gray-500 tw-min-w-[24px] tw-text-right\">{{ file.percentage }}%</span>\n </div>\n }\n\n <!-- Actions -->\n <div class=\"tw-flex tw-gap-1 tw-ml-2\">\n @switch (file.stage) {\n @case ('pending') {\n <button class=\"tw-flex tw-items-center tw-justify-center tw-w-5 tw-h-5 tw-border-none tw-bg-transparent tw-rounded tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-gray-400 hover:tw-bg-red-50 hover:tw-text-red-600\" \n (click)=\"cancelUpload(file.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('reading') {\n <button class=\"tw-flex tw-items-center tw-justify-center tw-w-5 tw-h-5 tw-border-none tw-bg-transparent tw-rounded tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-gray-400 hover:tw-bg-red-50 hover:tw-text-red-600\" \n (click)=\"cancelUpload(file.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('uploading') {\n <button class=\"tw-flex tw-items-center tw-justify-center tw-w-5 tw-h-5 tw-border-none tw-bg-transparent tw-rounded tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-gray-400 hover:tw-bg-red-50 hover:tw-text-red-600\" \n (click)=\"cancelUpload(file.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('complete') {\n <button class=\"tw-flex tw-items-center tw-justify-center tw-w-5 tw-h-5 tw-border-none tw-bg-transparent tw-rounded tw-cursor-pointer tw-text-green-600\" title=\"Completed\">\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\n </button>\n }\n @case ('error') {\n <button class=\"tw-flex tw-items-center tw-justify-center tw-w-5 tw-h-5 tw-border-none tw-bg-transparent tw-rounded tw-cursor-pointer tw-transition-all tw-duration-200 tw-text-gray-400 hover:tw-bg-blue-50 hover:tw-text-blue-600\" \n title=\"Retry\">\n <cide-ele-icon size=\"xs\">refresh</cide-ele-icon>\n </button>\n }\n }\n </div>\n </div>\n }\n </div>\n } @else {\n <!-- No uploads message when manually opened -->\n <div class=\"tw-p-8 tw-text-center tw-text-gray-500\">\n <div class=\"tw-flex tw-flex-col tw-items-center tw-gap-4\">\n <cide-ele-icon size=\"md\" class=\"tw-text-gray-300 tw-opacity-70\">cloud_upload</cide-ele-icon>\n <div>\n <h4 class=\"tw-text-lg tw-font-semibold tw-text-gray-700 tw-mb-2\">No active uploads</h4>\n <p class=\"tw-text-sm tw-text-gray-500\">Upload files to see their progress here</p>\n </div>\n </div>\n </div>\n }\n </div>\n\n <!-- Footer -->\n <div class=\"tw-px-4 tw-py-2 tw-bg-gray-50 tw-border-t tw-border-gray-200\">\n <div class=\"tw-flex tw-gap-3 tw-text-xs\">\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-blue-600\" \n [class.tw-text-blue-600]=\"hasActiveUploads()\">\n <cide-ele-icon size=\"xs\">upload</cide-ele-icon>\n <span>{{ getUploadingCount() }} uploading</span>\n </div>\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-green-600\">\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\n <span>{{ getCompletedCount() }} completed</span>\n </div>\n <div class=\"tw-flex tw-items-center tw-gap-1 tw-text-red-600\" \n [class.tw-text-red-600]=\"getFailedCount() > 0\">\n <cide-ele-icon size=\"xs\">error</cide-ele-icon>\n <span>{{ getFailedCount() }} failed</span>\n </div>\n </div>\n </div>\n</div>\n}" }]
|
|
5572
5430
|
}], ctorParameters: () => [], propDecorators: { data: [{
|
|
5573
5431
|
type: Input
|
|
5574
5432
|
}] } });
|
|
@@ -5919,318 +5777,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
|
|
|
5919
5777
|
}]
|
|
5920
5778
|
}], ctorParameters: () => [] });
|
|
5921
5779
|
|
|
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
|
-
|
|
6234
5780
|
/**
|
|
6235
5781
|
<!-- Basic horizontal (left-right) layout -->
|
|
6236
5782
|
<div class="panel-container">
|
|
@@ -11067,6 +10613,291 @@ var floatingContainerDynamic_directive = /*#__PURE__*/Object.freeze({
|
|
|
11067
10613
|
CideEleFloatingContainerDynamicDirective: CideEleFloatingContainerDynamicDirective
|
|
11068
10614
|
});
|
|
11069
10615
|
|
|
10616
|
+
class FloatingContainerShortcutsService {
|
|
10617
|
+
keyboardShortcutService = inject(KeyboardShortcutService);
|
|
10618
|
+
containerService = inject(CideEleFloatingContainerService);
|
|
10619
|
+
// Z-index layers for different container states
|
|
10620
|
+
Z_INDEX_LAYERS = {
|
|
10621
|
+
HIDDEN: 100, // Hidden containers (behind everything)
|
|
10622
|
+
BACKGROUND: 1000, // Background containers
|
|
10623
|
+
NORMAL: 2000, // Normal visible containers
|
|
10624
|
+
FOCUSED: 3000, // Focused containers
|
|
10625
|
+
MODAL: 4000, // Modal containers
|
|
10626
|
+
TOOLTIP: 5000 // Tooltips and overlays
|
|
10627
|
+
};
|
|
10628
|
+
constructor() {
|
|
10629
|
+
this.registerDefaultShortcuts();
|
|
10630
|
+
}
|
|
10631
|
+
/**
|
|
10632
|
+
* Register default floating container shortcuts
|
|
10633
|
+
*/
|
|
10634
|
+
registerDefaultShortcuts() {
|
|
10635
|
+
console.log('🎯 [FloatingContainerShortcuts] Registering default shortcuts');
|
|
10636
|
+
// Alt + 1, Alt + 2, etc. - Focus specific containers
|
|
10637
|
+
this.registerNumberShortcuts();
|
|
10638
|
+
// Alt + N - New container
|
|
10639
|
+
this.keyboardShortcutService.register({
|
|
10640
|
+
id: 'floating-container-new',
|
|
10641
|
+
key: 'n',
|
|
10642
|
+
altKey: true,
|
|
10643
|
+
description: 'Create new floating container',
|
|
10644
|
+
action: () => this.openNewContainer(),
|
|
10645
|
+
preventDefault: true
|
|
10646
|
+
});
|
|
10647
|
+
// Alt + P - Previous container
|
|
10648
|
+
this.keyboardShortcutService.register({
|
|
10649
|
+
id: 'floating-container-previous',
|
|
10650
|
+
key: 'p',
|
|
10651
|
+
altKey: true,
|
|
10652
|
+
description: 'Focus previous container',
|
|
10653
|
+
action: () => this.focusPreviousContainer(),
|
|
10654
|
+
preventDefault: true
|
|
10655
|
+
});
|
|
10656
|
+
// Alt + H - Hide all containers
|
|
10657
|
+
this.keyboardShortcutService.register({
|
|
10658
|
+
id: 'floating-container-hide-all',
|
|
10659
|
+
key: 'h',
|
|
10660
|
+
altKey: true,
|
|
10661
|
+
description: 'Hide all containers',
|
|
10662
|
+
action: () => this.hideAllContainers(),
|
|
10663
|
+
preventDefault: true
|
|
10664
|
+
});
|
|
10665
|
+
// Alt + S - Show all containers
|
|
10666
|
+
this.keyboardShortcutService.register({
|
|
10667
|
+
id: 'floating-container-show-all',
|
|
10668
|
+
key: 's',
|
|
10669
|
+
altKey: true,
|
|
10670
|
+
description: 'Show all containers',
|
|
10671
|
+
action: () => this.showAllContainers(),
|
|
10672
|
+
preventDefault: true
|
|
10673
|
+
});
|
|
10674
|
+
// Alt + M - Minimize all containers
|
|
10675
|
+
this.keyboardShortcutService.register({
|
|
10676
|
+
id: 'floating-container-minimize-all',
|
|
10677
|
+
key: 'm',
|
|
10678
|
+
altKey: true,
|
|
10679
|
+
description: 'Minimize all containers',
|
|
10680
|
+
action: () => this.minimizeAllContainers(),
|
|
10681
|
+
preventDefault: true
|
|
10682
|
+
});
|
|
10683
|
+
// Alt + W - Close current container
|
|
10684
|
+
this.keyboardShortcutService.register({
|
|
10685
|
+
id: 'floating-container-close-current',
|
|
10686
|
+
key: 'w',
|
|
10687
|
+
altKey: true,
|
|
10688
|
+
description: 'Close current container',
|
|
10689
|
+
action: () => this.closeCurrentContainer(),
|
|
10690
|
+
preventDefault: true
|
|
10691
|
+
});
|
|
10692
|
+
// Alt + D - Duplicate current container
|
|
10693
|
+
this.keyboardShortcutService.register({
|
|
10694
|
+
id: 'floating-container-duplicate',
|
|
10695
|
+
key: 'd',
|
|
10696
|
+
altKey: true,
|
|
10697
|
+
description: 'Duplicate current container',
|
|
10698
|
+
action: () => this.duplicateCurrentContainer(),
|
|
10699
|
+
preventDefault: true
|
|
10700
|
+
});
|
|
10701
|
+
// Alt + T - Toggle container visibility
|
|
10702
|
+
this.keyboardShortcutService.register({
|
|
10703
|
+
id: 'floating-container-toggle-visibility',
|
|
10704
|
+
key: 't',
|
|
10705
|
+
altKey: true,
|
|
10706
|
+
description: 'Toggle container visibility',
|
|
10707
|
+
action: () => this.toggleContainerVisibility(),
|
|
10708
|
+
preventDefault: true
|
|
10709
|
+
});
|
|
10710
|
+
// Alt + O - Open file uploader
|
|
10711
|
+
this.keyboardShortcutService.register({
|
|
10712
|
+
id: 'floating-container-open-file-uploader',
|
|
10713
|
+
key: 'o',
|
|
10714
|
+
altKey: true,
|
|
10715
|
+
description: 'Open file uploader',
|
|
10716
|
+
action: () => this.openFileUploader(),
|
|
10717
|
+
preventDefault: true
|
|
10718
|
+
});
|
|
10719
|
+
// Alt + R - Open entity rights sharing
|
|
10720
|
+
this.keyboardShortcutService.register({
|
|
10721
|
+
id: 'floating-container-open-entity-rights',
|
|
10722
|
+
key: 'r',
|
|
10723
|
+
altKey: true,
|
|
10724
|
+
description: 'Open entity rights sharing',
|
|
10725
|
+
action: () => this.openEntityRightsSharing(),
|
|
10726
|
+
preventDefault: true
|
|
10727
|
+
});
|
|
10728
|
+
console.log('✅ [FloatingContainerShortcuts] Default shortcuts registered');
|
|
10729
|
+
}
|
|
10730
|
+
/**
|
|
10731
|
+
* Register number shortcuts (Alt + 1, Alt + 2, etc.)
|
|
10732
|
+
*/
|
|
10733
|
+
registerNumberShortcuts() {
|
|
10734
|
+
for (let i = 1; i <= 9; i++) {
|
|
10735
|
+
this.keyboardShortcutService.register({
|
|
10736
|
+
id: `floating-container-focus-${i}`,
|
|
10737
|
+
key: i.toString(),
|
|
10738
|
+
altKey: true,
|
|
10739
|
+
description: `Focus container ${i}`,
|
|
10740
|
+
action: () => this.focusContainerByIndex(i - 1),
|
|
10741
|
+
preventDefault: true
|
|
10742
|
+
});
|
|
10743
|
+
}
|
|
10744
|
+
}
|
|
10745
|
+
/**
|
|
10746
|
+
* Open new floating container
|
|
10747
|
+
*/
|
|
10748
|
+
openNewContainer() {
|
|
10749
|
+
console.log('🎯 [FloatingContainerShortcuts] Opening new container');
|
|
10750
|
+
const containerId = this.containerService.show({
|
|
10751
|
+
id: 'new-container-' + Date.now(),
|
|
10752
|
+
title: 'New Container',
|
|
10753
|
+
width: '400px',
|
|
10754
|
+
height: '300px'
|
|
10755
|
+
});
|
|
10756
|
+
console.log('✅ [FloatingContainerShortcuts] New container created:', containerId);
|
|
10757
|
+
}
|
|
10758
|
+
/**
|
|
10759
|
+
* Focus previous container
|
|
10760
|
+
*/
|
|
10761
|
+
focusPreviousContainer() {
|
|
10762
|
+
console.log('🎯 [FloatingContainerShortcuts] Focusing previous container');
|
|
10763
|
+
const containers = this.containerService.visibleContainers();
|
|
10764
|
+
if (containers.length > 0) {
|
|
10765
|
+
// For now, just focus the last container
|
|
10766
|
+
const previousIndex = containers.length - 1;
|
|
10767
|
+
this.containerService.bringToFront(containers[previousIndex].id);
|
|
10768
|
+
}
|
|
10769
|
+
}
|
|
10770
|
+
/**
|
|
10771
|
+
* Hide all containers
|
|
10772
|
+
*/
|
|
10773
|
+
hideAllContainers() {
|
|
10774
|
+
console.log('🎯 [FloatingContainerShortcuts] Hiding all containers');
|
|
10775
|
+
const containers = this.containerService.visibleContainers();
|
|
10776
|
+
containers.forEach(container => {
|
|
10777
|
+
this.containerService.setZIndex(container.id, this.Z_INDEX_LAYERS.HIDDEN);
|
|
10778
|
+
});
|
|
10779
|
+
console.log('✅ [FloatingContainerShortcuts] All containers hidden');
|
|
10780
|
+
}
|
|
10781
|
+
/**
|
|
10782
|
+
* Show all containers
|
|
10783
|
+
*/
|
|
10784
|
+
showAllContainers() {
|
|
10785
|
+
console.log('🎯 [FloatingContainerShortcuts] Showing all containers');
|
|
10786
|
+
const containers = this.containerService.visibleContainers();
|
|
10787
|
+
containers.forEach((container, index) => {
|
|
10788
|
+
this.containerService.setZIndex(container.id, this.Z_INDEX_LAYERS.NORMAL + index);
|
|
10789
|
+
});
|
|
10790
|
+
console.log('✅ [FloatingContainerShortcuts] All containers shown');
|
|
10791
|
+
}
|
|
10792
|
+
/**
|
|
10793
|
+
* Minimize all containers
|
|
10794
|
+
*/
|
|
10795
|
+
minimizeAllContainers() {
|
|
10796
|
+
console.log('🎯 [FloatingContainerShortcuts] Minimizing all containers');
|
|
10797
|
+
const containers = this.containerService.visibleContainers();
|
|
10798
|
+
containers.forEach(container => {
|
|
10799
|
+
// Implement minimize logic here
|
|
10800
|
+
console.log('📦 [FloatingContainerShortcuts] Minimizing container:', container.id);
|
|
10801
|
+
});
|
|
10802
|
+
console.log('✅ [FloatingContainerShortcuts] All containers minimized');
|
|
10803
|
+
}
|
|
10804
|
+
/**
|
|
10805
|
+
* Focus container by index
|
|
10806
|
+
*/
|
|
10807
|
+
focusContainerByIndex(index) {
|
|
10808
|
+
console.log('🎯 [FloatingContainerShortcuts] Focusing container at index:', index);
|
|
10809
|
+
const containers = this.containerService.visibleContainers();
|
|
10810
|
+
if (containers[index]) {
|
|
10811
|
+
this.containerService.bringToFront(containers[index].id);
|
|
10812
|
+
console.log('✅ [FloatingContainerShortcuts] Container focused:', containers[index].id);
|
|
10813
|
+
}
|
|
10814
|
+
else {
|
|
10815
|
+
console.warn('⚠️ [FloatingContainerShortcuts] Container not found at index:', index);
|
|
10816
|
+
}
|
|
10817
|
+
}
|
|
10818
|
+
/**
|
|
10819
|
+
* Open file uploader
|
|
10820
|
+
*/
|
|
10821
|
+
openFileUploader() {
|
|
10822
|
+
console.log('🎯 [FloatingContainerShortcuts] Opening file uploader');
|
|
10823
|
+
// Implement file uploader opening logic here
|
|
10824
|
+
console.log('✅ [FloatingContainerShortcuts] File uploader opened');
|
|
10825
|
+
}
|
|
10826
|
+
/**
|
|
10827
|
+
* Open entity rights sharing
|
|
10828
|
+
*/
|
|
10829
|
+
openEntityRightsSharing() {
|
|
10830
|
+
console.log('🎯 [FloatingContainerShortcuts] Opening entity rights sharing');
|
|
10831
|
+
// Implement entity rights sharing opening logic here
|
|
10832
|
+
console.log('✅ [FloatingContainerShortcuts] Entity rights sharing opened');
|
|
10833
|
+
}
|
|
10834
|
+
/**
|
|
10835
|
+
* Duplicate current container
|
|
10836
|
+
*/
|
|
10837
|
+
duplicateCurrentContainer() {
|
|
10838
|
+
console.log('🎯 [FloatingContainerShortcuts] Duplicating current container');
|
|
10839
|
+
const containers = this.containerService.visibleContainers();
|
|
10840
|
+
if (containers.length > 0) {
|
|
10841
|
+
const containerToDuplicate = containers[containers.length - 1]; // Use last container
|
|
10842
|
+
const newContainerId = this.containerService.show({
|
|
10843
|
+
id: 'duplicate-' + Date.now(),
|
|
10844
|
+
title: `${containerToDuplicate.config.title} (Copy)`,
|
|
10845
|
+
width: containerToDuplicate.config.width,
|
|
10846
|
+
height: containerToDuplicate.config.height
|
|
10847
|
+
});
|
|
10848
|
+
console.log('✅ [FloatingContainerShortcuts] Container duplicated:', newContainerId);
|
|
10849
|
+
}
|
|
10850
|
+
else {
|
|
10851
|
+
console.warn('⚠️ [FloatingContainerShortcuts] No container to duplicate');
|
|
10852
|
+
}
|
|
10853
|
+
}
|
|
10854
|
+
/**
|
|
10855
|
+
* Close current container
|
|
10856
|
+
*/
|
|
10857
|
+
closeCurrentContainer() {
|
|
10858
|
+
console.log('🎯 [FloatingContainerShortcuts] Closing current container');
|
|
10859
|
+
const containers = this.containerService.visibleContainers();
|
|
10860
|
+
if (containers.length > 0) {
|
|
10861
|
+
const containerToClose = containers[containers.length - 1]; // Use last container
|
|
10862
|
+
this.containerService.hide(containerToClose.id);
|
|
10863
|
+
console.log('✅ [FloatingContainerShortcuts] Container closed:', containerToClose.id);
|
|
10864
|
+
}
|
|
10865
|
+
else {
|
|
10866
|
+
console.warn('⚠️ [FloatingContainerShortcuts] No container to close');
|
|
10867
|
+
}
|
|
10868
|
+
}
|
|
10869
|
+
/**
|
|
10870
|
+
* Toggle container visibility
|
|
10871
|
+
*/
|
|
10872
|
+
toggleContainerVisibility() {
|
|
10873
|
+
console.log('🎯 [FloatingContainerShortcuts] Toggling container visibility');
|
|
10874
|
+
const containers = this.containerService.visibleContainers();
|
|
10875
|
+
if (containers.length > 0) {
|
|
10876
|
+
const containerToToggle = containers[containers.length - 1]; // Use last container
|
|
10877
|
+
const currentZIndex = this.containerService.getZIndexSignal(containerToToggle.id)();
|
|
10878
|
+
if (currentZIndex === this.Z_INDEX_LAYERS.HIDDEN) {
|
|
10879
|
+
this.containerService.setZIndex(containerToToggle.id, this.Z_INDEX_LAYERS.NORMAL);
|
|
10880
|
+
console.log('✅ [FloatingContainerShortcuts] Container shown:', containerToToggle.id);
|
|
10881
|
+
}
|
|
10882
|
+
else {
|
|
10883
|
+
this.containerService.setZIndex(containerToToggle.id, this.Z_INDEX_LAYERS.HIDDEN);
|
|
10884
|
+
console.log('✅ [FloatingContainerShortcuts] Container hidden:', containerToToggle.id);
|
|
10885
|
+
}
|
|
10886
|
+
}
|
|
10887
|
+
else {
|
|
10888
|
+
console.warn('⚠️ [FloatingContainerShortcuts] No container to toggle');
|
|
10889
|
+
}
|
|
10890
|
+
}
|
|
10891
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: FloatingContainerShortcutsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
10892
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: FloatingContainerShortcutsService, providedIn: 'root' });
|
|
10893
|
+
}
|
|
10894
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: FloatingContainerShortcutsService, decorators: [{
|
|
10895
|
+
type: Injectable,
|
|
10896
|
+
args: [{
|
|
10897
|
+
providedIn: 'root'
|
|
10898
|
+
}]
|
|
10899
|
+
}], ctorParameters: () => [] });
|
|
10900
|
+
|
|
11070
10901
|
/*
|
|
11071
10902
|
* Public API Surface of cloud-ide-element
|
|
11072
10903
|
* Here we can add what need to be exported from library
|