cloud-ide-element 1.0.114 → 1.0.115
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 +1155 -2
- package/fesm2022/cloud-ide-element.mjs.map +1 -1
- package/index.d.ts +265 -5
- package/package.json +1 -1
|
@@ -3380,6 +3380,7 @@ class CideEleFileInputComponent {
|
|
|
3380
3380
|
notificationService = inject(NotificationService);
|
|
3381
3381
|
elementService = inject(CideElementsService);
|
|
3382
3382
|
destroyRef = inject(DestroyRef);
|
|
3383
|
+
// Removed direct injection to avoid circular dependency
|
|
3383
3384
|
// private readonly pendingTasks = inject(PendingTasks); // TODO: Fix PendingTasks API usage
|
|
3384
3385
|
// Traditional @Input() decorators
|
|
3385
3386
|
label = 'Choose file';
|
|
@@ -4124,7 +4125,36 @@ class CideEleFileInputComponent {
|
|
|
4124
4125
|
* Show floating uploader (alias for showUploader for template)
|
|
4125
4126
|
*/
|
|
4126
4127
|
showFloatingUploaderDialog() {
|
|
4127
|
-
|
|
4128
|
+
console.log('👁️ [FileInput] Opening floating file uploader via file manager service');
|
|
4129
|
+
if (!this.showFloatingUploaderSignal()) {
|
|
4130
|
+
console.log('⚠️ [FileInput] Floating uploader is disabled');
|
|
4131
|
+
return;
|
|
4132
|
+
}
|
|
4133
|
+
const groupId = this.groupId();
|
|
4134
|
+
if (groupId) {
|
|
4135
|
+
console.log("✅ [FileInput] Has existing group ID:", groupId);
|
|
4136
|
+
// Use the file manager service to trigger the floating uploader
|
|
4137
|
+
this.fileManagerService.triggerFloatingUploaderShow(groupId);
|
|
4138
|
+
console.log('✅ [FileInput] Floating file uploader triggered successfully');
|
|
4139
|
+
}
|
|
4140
|
+
else {
|
|
4141
|
+
console.log('⚠️ [FileInput] No group ID yet - generating one and opening uploader');
|
|
4142
|
+
// Generate a new group ID and open the uploader
|
|
4143
|
+
this.fileManagerService.generateObjectId().subscribe({
|
|
4144
|
+
next: (response) => {
|
|
4145
|
+
const newGroupId = response.data?.objectId;
|
|
4146
|
+
console.log('🆔 [FileInput] Generated new group ID for uploader:', newGroupId);
|
|
4147
|
+
this.groupId.set(newGroupId);
|
|
4148
|
+
// Use the file manager service to trigger the floating uploader
|
|
4149
|
+
this.fileManagerService.triggerFloatingUploaderShow(newGroupId);
|
|
4150
|
+
console.log('✅ [FileInput] Floating file uploader triggered successfully');
|
|
4151
|
+
},
|
|
4152
|
+
error: (error) => {
|
|
4153
|
+
console.error('❌ [FileInput] Failed to generate group ID for uploader:', error);
|
|
4154
|
+
this.notificationService.error('❌ Failed to open file uploader', { duration: 0 });
|
|
4155
|
+
}
|
|
4156
|
+
});
|
|
4157
|
+
}
|
|
4128
4158
|
}
|
|
4129
4159
|
/**
|
|
4130
4160
|
* Get dynamic classes for drag and drop zone
|
|
@@ -4971,6 +5001,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
|
|
|
4971
5001
|
], 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"] }]
|
|
4972
5002
|
}], ctorParameters: () => [] });
|
|
4973
5003
|
|
|
5004
|
+
var floatingFileUploader_component = /*#__PURE__*/Object.freeze({
|
|
5005
|
+
__proto__: null,
|
|
5006
|
+
CideEleFloatingFileUploaderComponent: CideEleFloatingFileUploaderComponent
|
|
5007
|
+
});
|
|
5008
|
+
|
|
4974
5009
|
class CideTextareaComponent {
|
|
4975
5010
|
label = '';
|
|
4976
5011
|
labelHide = false;
|
|
@@ -9200,6 +9235,1124 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
|
|
|
9200
9235
|
type: Output
|
|
9201
9236
|
}] } });
|
|
9202
9237
|
|
|
9238
|
+
class CideEleFloatingContainerComponent {
|
|
9239
|
+
config = signal({
|
|
9240
|
+
id: '',
|
|
9241
|
+
title: 'Floating Container',
|
|
9242
|
+
icon: 'widgets',
|
|
9243
|
+
headerColor: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
9244
|
+
width: '400px',
|
|
9245
|
+
height: 'auto',
|
|
9246
|
+
minWidth: '300px',
|
|
9247
|
+
minHeight: '200px',
|
|
9248
|
+
maxWidth: '90vw',
|
|
9249
|
+
maxHeight: '90vh',
|
|
9250
|
+
resizable: true,
|
|
9251
|
+
draggable: true,
|
|
9252
|
+
closable: true,
|
|
9253
|
+
minimizable: true,
|
|
9254
|
+
maximizable: true
|
|
9255
|
+
}, ...(ngDevMode ? [{ debugName: "config" }] : []));
|
|
9256
|
+
isMinimized;
|
|
9257
|
+
isMaximized;
|
|
9258
|
+
isVisible;
|
|
9259
|
+
closeEvent = new EventEmitter();
|
|
9260
|
+
minimizeEvent = new EventEmitter();
|
|
9261
|
+
maximizeEvent = new EventEmitter();
|
|
9262
|
+
containerRef;
|
|
9263
|
+
// State signals
|
|
9264
|
+
position = signal({ x: 100, y: 100 }, ...(ngDevMode ? [{ debugName: "position" }] : []));
|
|
9265
|
+
isDragging = signal(false, ...(ngDevMode ? [{ debugName: "isDragging" }] : []));
|
|
9266
|
+
isResizing = signal(false, ...(ngDevMode ? [{ debugName: "isResizing" }] : []));
|
|
9267
|
+
// Computed properties
|
|
9268
|
+
computedConfig = computed(() => this.config(), ...(ngDevMode ? [{ debugName: "computedConfig" }] : []));
|
|
9269
|
+
dragStart = { x: 0, y: 0 };
|
|
9270
|
+
resizeStart = { x: 0, y: 0, width: 0, height: 0 };
|
|
9271
|
+
originalPosition = { x: 0, y: 0 };
|
|
9272
|
+
originalSize = { width: 0, height: 0 };
|
|
9273
|
+
savedPosition = { x: 100, y: 100 }; // Store position before maximizing
|
|
9274
|
+
savedHeight = ''; // Store height before maximizing
|
|
9275
|
+
ngAfterViewInit() {
|
|
9276
|
+
// Center the container on screen
|
|
9277
|
+
this.centerContainer();
|
|
9278
|
+
}
|
|
9279
|
+
constructor() {
|
|
9280
|
+
// Watch for maximize state changes
|
|
9281
|
+
effect(() => {
|
|
9282
|
+
const isMaximized = this.isMaximized();
|
|
9283
|
+
if (isMaximized && !this.savedHeight) {
|
|
9284
|
+
// Save current height when maximizing
|
|
9285
|
+
this.savedHeight = this.containerRef?.nativeElement?.style.height || this.config().height || '500px';
|
|
9286
|
+
}
|
|
9287
|
+
else if (!isMaximized && this.savedHeight) {
|
|
9288
|
+
// Restore height when unmaximizing
|
|
9289
|
+
this.savedHeight = '';
|
|
9290
|
+
}
|
|
9291
|
+
});
|
|
9292
|
+
}
|
|
9293
|
+
ngOnDestroy() {
|
|
9294
|
+
// Clean up any event listeners if needed
|
|
9295
|
+
}
|
|
9296
|
+
centerContainer() {
|
|
9297
|
+
if (this.containerRef?.nativeElement) {
|
|
9298
|
+
if (this.isMaximized()) {
|
|
9299
|
+
// For maximized state, position with equal margins (20px from all sides)
|
|
9300
|
+
this.position.set({ x: 20, y: 20 });
|
|
9301
|
+
}
|
|
9302
|
+
else {
|
|
9303
|
+
// For normal state, center based on container size
|
|
9304
|
+
const rect = this.containerRef.nativeElement.getBoundingClientRect();
|
|
9305
|
+
const centerX = (window.innerWidth - rect.width) / 2;
|
|
9306
|
+
const centerY = (window.innerHeight - rect.height) / 2;
|
|
9307
|
+
this.position.set({ x: Math.max(0, centerX), y: Math.max(0, centerY) });
|
|
9308
|
+
}
|
|
9309
|
+
}
|
|
9310
|
+
}
|
|
9311
|
+
startDrag(event) {
|
|
9312
|
+
if (!this.computedConfig().draggable)
|
|
9313
|
+
return;
|
|
9314
|
+
event.preventDefault();
|
|
9315
|
+
event.stopPropagation();
|
|
9316
|
+
this.isDragging.set(true);
|
|
9317
|
+
this.dragStart = { x: event.clientX, y: event.clientY };
|
|
9318
|
+
this.originalPosition = { ...this.position() };
|
|
9319
|
+
document.addEventListener('mousemove', this.onDragMove.bind(this));
|
|
9320
|
+
document.addEventListener('mouseup', this.onDragEnd.bind(this));
|
|
9321
|
+
}
|
|
9322
|
+
onDragMove(event) {
|
|
9323
|
+
if (!this.isDragging())
|
|
9324
|
+
return;
|
|
9325
|
+
const deltaX = event.clientX - this.dragStart.x;
|
|
9326
|
+
const deltaY = event.clientY - this.dragStart.y;
|
|
9327
|
+
const newX = Math.max(0, Math.min(window.innerWidth - 300, this.originalPosition.x + deltaX));
|
|
9328
|
+
const newY = Math.max(0, Math.min(window.innerHeight - 100, this.originalPosition.y + deltaY));
|
|
9329
|
+
this.position.set({ x: newX, y: newY });
|
|
9330
|
+
}
|
|
9331
|
+
onDragEnd() {
|
|
9332
|
+
this.isDragging.set(false);
|
|
9333
|
+
document.removeEventListener('mousemove', this.onDragMove.bind(this));
|
|
9334
|
+
document.removeEventListener('mouseup', this.onDragEnd.bind(this));
|
|
9335
|
+
}
|
|
9336
|
+
startResize(event) {
|
|
9337
|
+
if (!this.computedConfig().resizable)
|
|
9338
|
+
return;
|
|
9339
|
+
event.preventDefault();
|
|
9340
|
+
event.stopPropagation();
|
|
9341
|
+
this.isResizing.set(true);
|
|
9342
|
+
this.resizeStart = {
|
|
9343
|
+
x: event.clientX,
|
|
9344
|
+
y: event.clientY,
|
|
9345
|
+
width: this.containerRef.nativeElement.offsetWidth,
|
|
9346
|
+
height: this.containerRef.nativeElement.offsetHeight
|
|
9347
|
+
};
|
|
9348
|
+
this.originalSize = { ...this.resizeStart };
|
|
9349
|
+
document.addEventListener('mousemove', this.onResizeMove.bind(this));
|
|
9350
|
+
document.addEventListener('mouseup', this.onResizeEnd.bind(this));
|
|
9351
|
+
}
|
|
9352
|
+
onResizeMove(event) {
|
|
9353
|
+
if (!this.isResizing())
|
|
9354
|
+
return;
|
|
9355
|
+
const deltaX = event.clientX - this.resizeStart.x;
|
|
9356
|
+
const deltaY = event.clientY - this.resizeStart.y;
|
|
9357
|
+
const newWidth = Math.max(300, this.originalSize.width + deltaX);
|
|
9358
|
+
const newHeight = Math.max(200, this.originalSize.height + deltaY);
|
|
9359
|
+
this.containerRef.nativeElement.style.width = `${newWidth}px`;
|
|
9360
|
+
this.containerRef.nativeElement.style.height = `${newHeight}px`;
|
|
9361
|
+
}
|
|
9362
|
+
onResizeEnd() {
|
|
9363
|
+
this.isResizing.set(false);
|
|
9364
|
+
document.removeEventListener('mousemove', this.onResizeMove.bind(this));
|
|
9365
|
+
document.removeEventListener('mouseup', this.onResizeEnd.bind(this));
|
|
9366
|
+
}
|
|
9367
|
+
// Mouse event handlers for container
|
|
9368
|
+
onMouseDown(event) {
|
|
9369
|
+
// Prevent text selection during drag
|
|
9370
|
+
event.preventDefault();
|
|
9371
|
+
}
|
|
9372
|
+
onMouseMove(event) {
|
|
9373
|
+
// Handle any additional mouse move logic if needed
|
|
9374
|
+
}
|
|
9375
|
+
onMouseUp(event) {
|
|
9376
|
+
// Handle any additional mouse up logic if needed
|
|
9377
|
+
}
|
|
9378
|
+
// Action methods
|
|
9379
|
+
onHeaderClick(event) {
|
|
9380
|
+
// Only minimize if clicking on the header itself, not on buttons
|
|
9381
|
+
if (this.isMinimized() && !event.target.closest('button')) {
|
|
9382
|
+
this.minimize();
|
|
9383
|
+
}
|
|
9384
|
+
}
|
|
9385
|
+
minimize() {
|
|
9386
|
+
this.minimizeEvent.emit(this.computedConfig().id);
|
|
9387
|
+
}
|
|
9388
|
+
toggleMaximize() {
|
|
9389
|
+
this.maximizeEvent.emit(this.computedConfig().id);
|
|
9390
|
+
}
|
|
9391
|
+
close() {
|
|
9392
|
+
this.closeEvent.emit(this.computedConfig().id);
|
|
9393
|
+
}
|
|
9394
|
+
getHeaderBackground() {
|
|
9395
|
+
return 'linear-gradient(135deg, var(--cide-theme-primary-color) 0%, var(--tw-blue-400) 100%)';
|
|
9396
|
+
}
|
|
9397
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9398
|
+
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: `
|
|
9399
|
+
<div
|
|
9400
|
+
#container
|
|
9401
|
+
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"
|
|
9402
|
+
[style.left.px]="isMaximized() ? 20 : position().x"
|
|
9403
|
+
[style.top.px]="isMaximized() ? 20 : position().y"
|
|
9404
|
+
[style.width]="isMaximized() ? 'calc(100vw - 40px)' : (config().width || '400px')"
|
|
9405
|
+
[style.height]="isMaximized() ? 'calc(100vh - 40px)' : (isMinimized() ? 'auto' : (savedHeight || config().height || '500px'))"
|
|
9406
|
+
[style.min-width]="config().minWidth || '300px'"
|
|
9407
|
+
[style.min-height]="isMinimized() ? 'auto' : (config().minHeight || '200px')"
|
|
9408
|
+
[style.max-width]="config().maxWidth || '90vw'"
|
|
9409
|
+
[style.max-height]="config().maxHeight || '90vh'"
|
|
9410
|
+
[class.tw-cursor-move]="isDragging()"
|
|
9411
|
+
[class.tw-select-none]="true"
|
|
9412
|
+
(mousedown)="onMouseDown($event)"
|
|
9413
|
+
(mousemove)="onMouseMove($event)"
|
|
9414
|
+
(mouseup)="onMouseUp($event)"
|
|
9415
|
+
(mouseleave)="onMouseUp($event)">
|
|
9416
|
+
|
|
9417
|
+
<!-- Header -->
|
|
9418
|
+
<div
|
|
9419
|
+
class="tw-flex tw-items-center tw-justify-between tw-px-3 tw-py-2 tw-border-b tw-border-gray-200 tw-border-opacity-30 tw-rounded-t-xl tw-cursor-move tw-transition-all tw-duration-200 tw-shadow-sm tw-flex-shrink-0"
|
|
9420
|
+
[style.background]="getHeaderBackground()"
|
|
9421
|
+
(mousedown)="startDrag($event)"
|
|
9422
|
+
(click)="onHeaderClick($event)">
|
|
9423
|
+
|
|
9424
|
+
<!-- Title Section -->
|
|
9425
|
+
<div class="tw-flex tw-items-center tw-space-x-2 tw-text-white">
|
|
9426
|
+
@if (config().icon) {
|
|
9427
|
+
<cide-ele-icon class="tw-w-4 tw-h-4">{{ config().icon }}</cide-ele-icon>
|
|
9428
|
+
}
|
|
9429
|
+
<h2 class="tw-text-sm tw-font-medium tw-truncate">{{ config().title }}</h2>
|
|
9430
|
+
@if (isMinimized()) {
|
|
9431
|
+
<span class="tw-text-xs tw-opacity-75">(Click to restore)</span>
|
|
9432
|
+
}
|
|
9433
|
+
</div>
|
|
9434
|
+
|
|
9435
|
+
<!-- Action Buttons -->
|
|
9436
|
+
<div class="tw-flex tw-items-center tw-space-x-1">
|
|
9437
|
+
@if (config().minimizable !== false) {
|
|
9438
|
+
<button
|
|
9439
|
+
cideEleButton
|
|
9440
|
+
variant="ghost"
|
|
9441
|
+
size="xs"
|
|
9442
|
+
type="button"
|
|
9443
|
+
(click)="minimize(); $event.stopPropagation()"
|
|
9444
|
+
class="tw-w-6 tw-h-6 tw-rounded-lg tw-text-white hover:tw-bg-white hover:tw-bg-opacity-20 tw-transition-all tw-duration-200"
|
|
9445
|
+
[title]="isMinimized() ? 'Restore' : 'Minimize'">
|
|
9446
|
+
<cide-ele-icon class="tw-w-3 tw-h-3">{{ isMinimized() ? 'open_in_full' : 'remove' }}</cide-ele-icon>
|
|
9447
|
+
</button>
|
|
9448
|
+
}
|
|
9449
|
+
@if (config().maximizable !== false) {
|
|
9450
|
+
<button
|
|
9451
|
+
cideEleButton
|
|
9452
|
+
variant="ghost"
|
|
9453
|
+
size="xs"
|
|
9454
|
+
type="button"
|
|
9455
|
+
(click)="toggleMaximize(); $event.stopPropagation()"
|
|
9456
|
+
class="tw-w-6 tw-h-6 tw-rounded-lg tw-text-white hover:tw-bg-white hover:tw-bg-opacity-20 tw-transition-all tw-duration-200"
|
|
9457
|
+
[title]="isMaximized() ? 'Restore' : 'Maximize'">
|
|
9458
|
+
<cide-ele-icon class="tw-w-3 tw-h-3">{{ isMaximized() ? 'fullscreen_exit' : 'fullscreen' }}</cide-ele-icon>
|
|
9459
|
+
</button>
|
|
9460
|
+
}
|
|
9461
|
+
@if (config().closable !== false) {
|
|
9462
|
+
<button
|
|
9463
|
+
cideEleButton
|
|
9464
|
+
variant="ghost"
|
|
9465
|
+
size="xs"
|
|
9466
|
+
type="button"
|
|
9467
|
+
(click)="close(); $event.stopPropagation()"
|
|
9468
|
+
class="tw-w-6 tw-h-6 tw-rounded-lg tw-text-white hover:tw-bg-white hover:tw-bg-opacity-20 tw-transition-all tw-duration-200"
|
|
9469
|
+
title="Close">
|
|
9470
|
+
<cide-ele-icon class="tw-w-3 tw-h-3">close</cide-ele-icon>
|
|
9471
|
+
</button>
|
|
9472
|
+
}
|
|
9473
|
+
</div>
|
|
9474
|
+
</div>
|
|
9475
|
+
|
|
9476
|
+
<!-- Content with @defer for performance -->
|
|
9477
|
+
@if (!isMinimized()) {
|
|
9478
|
+
<div
|
|
9479
|
+
class="tw-flex-1 tw-overflow-auto tw-overflow-x-hidden floating-container-content tw-bg-gray-50 tw-bg-opacity-90"
|
|
9480
|
+
[style.height]="isMaximized() ? 'calc(100vh - 100px)' : 'auto'"
|
|
9481
|
+
[style.min-height]="'200px'">
|
|
9482
|
+
@defer (when !isMinimized() && isVisible()) {
|
|
9483
|
+
<div class="tw-p-4 tw-min-h-full">
|
|
9484
|
+
<ng-content></ng-content>
|
|
9485
|
+
</div>
|
|
9486
|
+
} @placeholder {
|
|
9487
|
+
<div class="tw-flex tw-items-center tw-justify-center tw-p-4 tw-min-h-[200px]">
|
|
9488
|
+
<cide-ele-spinner size="sm"></cide-ele-spinner>
|
|
9489
|
+
<span class="tw-ml-2 tw-text-sm tw-text-gray-600">Loading content...</span>
|
|
9490
|
+
</div>
|
|
9491
|
+
}
|
|
9492
|
+
</div>
|
|
9493
|
+
}
|
|
9494
|
+
|
|
9495
|
+
<!-- Resize Handle (if resizable) -->
|
|
9496
|
+
@if (config().resizable !== false) {
|
|
9497
|
+
<div
|
|
9498
|
+
class="tw-absolute tw-bottom-0 tw-right-0 tw-w-3 tw-h-3 tw-cursor-se-resize tw-bg-gray-300 tw-opacity-50 hover:tw-opacity-100"
|
|
9499
|
+
(mousedown)="startResize($event)">
|
|
9500
|
+
</div>
|
|
9501
|
+
}
|
|
9502
|
+
</div>
|
|
9503
|
+
`, isInline: true, styles: [".tw-cursor-move{cursor:move!important}.tw-cursor-se-resize{cursor:se-resize!important}.floating-container-content{overflow-y:auto;overflow-x:hidden;scrollbar-width:thin;scrollbar-color:#cbd5e1 #f1f5f9;position:relative;flex:1;display:flex;flex-direction:column}.floating-container-content::-webkit-scrollbar{width:8px}.floating-container-content::-webkit-scrollbar-track{background:#f8fafc;border-radius:4px;margin:4px}.floating-container-content::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:4px;transition:background-color .2s ease;border:1px solid #e2e8f0}.floating-container-content::-webkit-scrollbar-thumb:hover{background:#94a3b8;border-color:#cbd5e1}.floating-container-content::-webkit-scrollbar-thumb:active{background:#64748b}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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"] }, { kind: "component", type: CideSpinnerComponent, selector: "cide-ele-spinner", inputs: ["size", "type"] }] });
|
|
9504
|
+
}
|
|
9505
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingContainerComponent, decorators: [{
|
|
9506
|
+
type: Component,
|
|
9507
|
+
args: [{ selector: 'cide-ele-floating-container', standalone: true, imports: [CommonModule, CideEleButtonComponent, CideIconComponent, CideSpinnerComponent], template: `
|
|
9508
|
+
<div
|
|
9509
|
+
#container
|
|
9510
|
+
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"
|
|
9511
|
+
[style.left.px]="isMaximized() ? 20 : position().x"
|
|
9512
|
+
[style.top.px]="isMaximized() ? 20 : position().y"
|
|
9513
|
+
[style.width]="isMaximized() ? 'calc(100vw - 40px)' : (config().width || '400px')"
|
|
9514
|
+
[style.height]="isMaximized() ? 'calc(100vh - 40px)' : (isMinimized() ? 'auto' : (savedHeight || config().height || '500px'))"
|
|
9515
|
+
[style.min-width]="config().minWidth || '300px'"
|
|
9516
|
+
[style.min-height]="isMinimized() ? 'auto' : (config().minHeight || '200px')"
|
|
9517
|
+
[style.max-width]="config().maxWidth || '90vw'"
|
|
9518
|
+
[style.max-height]="config().maxHeight || '90vh'"
|
|
9519
|
+
[class.tw-cursor-move]="isDragging()"
|
|
9520
|
+
[class.tw-select-none]="true"
|
|
9521
|
+
(mousedown)="onMouseDown($event)"
|
|
9522
|
+
(mousemove)="onMouseMove($event)"
|
|
9523
|
+
(mouseup)="onMouseUp($event)"
|
|
9524
|
+
(mouseleave)="onMouseUp($event)">
|
|
9525
|
+
|
|
9526
|
+
<!-- Header -->
|
|
9527
|
+
<div
|
|
9528
|
+
class="tw-flex tw-items-center tw-justify-between tw-px-3 tw-py-2 tw-border-b tw-border-gray-200 tw-border-opacity-30 tw-rounded-t-xl tw-cursor-move tw-transition-all tw-duration-200 tw-shadow-sm tw-flex-shrink-0"
|
|
9529
|
+
[style.background]="getHeaderBackground()"
|
|
9530
|
+
(mousedown)="startDrag($event)"
|
|
9531
|
+
(click)="onHeaderClick($event)">
|
|
9532
|
+
|
|
9533
|
+
<!-- Title Section -->
|
|
9534
|
+
<div class="tw-flex tw-items-center tw-space-x-2 tw-text-white">
|
|
9535
|
+
@if (config().icon) {
|
|
9536
|
+
<cide-ele-icon class="tw-w-4 tw-h-4">{{ config().icon }}</cide-ele-icon>
|
|
9537
|
+
}
|
|
9538
|
+
<h2 class="tw-text-sm tw-font-medium tw-truncate">{{ config().title }}</h2>
|
|
9539
|
+
@if (isMinimized()) {
|
|
9540
|
+
<span class="tw-text-xs tw-opacity-75">(Click to restore)</span>
|
|
9541
|
+
}
|
|
9542
|
+
</div>
|
|
9543
|
+
|
|
9544
|
+
<!-- Action Buttons -->
|
|
9545
|
+
<div class="tw-flex tw-items-center tw-space-x-1">
|
|
9546
|
+
@if (config().minimizable !== false) {
|
|
9547
|
+
<button
|
|
9548
|
+
cideEleButton
|
|
9549
|
+
variant="ghost"
|
|
9550
|
+
size="xs"
|
|
9551
|
+
type="button"
|
|
9552
|
+
(click)="minimize(); $event.stopPropagation()"
|
|
9553
|
+
class="tw-w-6 tw-h-6 tw-rounded-lg tw-text-white hover:tw-bg-white hover:tw-bg-opacity-20 tw-transition-all tw-duration-200"
|
|
9554
|
+
[title]="isMinimized() ? 'Restore' : 'Minimize'">
|
|
9555
|
+
<cide-ele-icon class="tw-w-3 tw-h-3">{{ isMinimized() ? 'open_in_full' : 'remove' }}</cide-ele-icon>
|
|
9556
|
+
</button>
|
|
9557
|
+
}
|
|
9558
|
+
@if (config().maximizable !== false) {
|
|
9559
|
+
<button
|
|
9560
|
+
cideEleButton
|
|
9561
|
+
variant="ghost"
|
|
9562
|
+
size="xs"
|
|
9563
|
+
type="button"
|
|
9564
|
+
(click)="toggleMaximize(); $event.stopPropagation()"
|
|
9565
|
+
class="tw-w-6 tw-h-6 tw-rounded-lg tw-text-white hover:tw-bg-white hover:tw-bg-opacity-20 tw-transition-all tw-duration-200"
|
|
9566
|
+
[title]="isMaximized() ? 'Restore' : 'Maximize'">
|
|
9567
|
+
<cide-ele-icon class="tw-w-3 tw-h-3">{{ isMaximized() ? 'fullscreen_exit' : 'fullscreen' }}</cide-ele-icon>
|
|
9568
|
+
</button>
|
|
9569
|
+
}
|
|
9570
|
+
@if (config().closable !== false) {
|
|
9571
|
+
<button
|
|
9572
|
+
cideEleButton
|
|
9573
|
+
variant="ghost"
|
|
9574
|
+
size="xs"
|
|
9575
|
+
type="button"
|
|
9576
|
+
(click)="close(); $event.stopPropagation()"
|
|
9577
|
+
class="tw-w-6 tw-h-6 tw-rounded-lg tw-text-white hover:tw-bg-white hover:tw-bg-opacity-20 tw-transition-all tw-duration-200"
|
|
9578
|
+
title="Close">
|
|
9579
|
+
<cide-ele-icon class="tw-w-3 tw-h-3">close</cide-ele-icon>
|
|
9580
|
+
</button>
|
|
9581
|
+
}
|
|
9582
|
+
</div>
|
|
9583
|
+
</div>
|
|
9584
|
+
|
|
9585
|
+
<!-- Content with @defer for performance -->
|
|
9586
|
+
@if (!isMinimized()) {
|
|
9587
|
+
<div
|
|
9588
|
+
class="tw-flex-1 tw-overflow-auto tw-overflow-x-hidden floating-container-content tw-bg-gray-50 tw-bg-opacity-90"
|
|
9589
|
+
[style.height]="isMaximized() ? 'calc(100vh - 100px)' : 'auto'"
|
|
9590
|
+
[style.min-height]="'200px'">
|
|
9591
|
+
@defer (when !isMinimized() && isVisible()) {
|
|
9592
|
+
<div class="tw-p-4 tw-min-h-full">
|
|
9593
|
+
<ng-content></ng-content>
|
|
9594
|
+
</div>
|
|
9595
|
+
} @placeholder {
|
|
9596
|
+
<div class="tw-flex tw-items-center tw-justify-center tw-p-4 tw-min-h-[200px]">
|
|
9597
|
+
<cide-ele-spinner size="sm"></cide-ele-spinner>
|
|
9598
|
+
<span class="tw-ml-2 tw-text-sm tw-text-gray-600">Loading content...</span>
|
|
9599
|
+
</div>
|
|
9600
|
+
}
|
|
9601
|
+
</div>
|
|
9602
|
+
}
|
|
9603
|
+
|
|
9604
|
+
<!-- Resize Handle (if resizable) -->
|
|
9605
|
+
@if (config().resizable !== false) {
|
|
9606
|
+
<div
|
|
9607
|
+
class="tw-absolute tw-bottom-0 tw-right-0 tw-w-3 tw-h-3 tw-cursor-se-resize tw-bg-gray-300 tw-opacity-50 hover:tw-opacity-100"
|
|
9608
|
+
(mousedown)="startResize($event)">
|
|
9609
|
+
</div>
|
|
9610
|
+
}
|
|
9611
|
+
</div>
|
|
9612
|
+
`, styles: [".tw-cursor-move{cursor:move!important}.tw-cursor-se-resize{cursor:se-resize!important}.floating-container-content{overflow-y:auto;overflow-x:hidden;scrollbar-width:thin;scrollbar-color:#cbd5e1 #f1f5f9;position:relative;flex:1;display:flex;flex-direction:column}.floating-container-content::-webkit-scrollbar{width:8px}.floating-container-content::-webkit-scrollbar-track{background:#f8fafc;border-radius:4px;margin:4px}.floating-container-content::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:4px;transition:background-color .2s ease;border:1px solid #e2e8f0}.floating-container-content::-webkit-scrollbar-thumb:hover{background:#94a3b8;border-color:#cbd5e1}.floating-container-content::-webkit-scrollbar-thumb:active{background:#64748b}\n"] }]
|
|
9613
|
+
}], ctorParameters: () => [], propDecorators: { config: [{
|
|
9614
|
+
type: Input
|
|
9615
|
+
}], isMinimized: [{
|
|
9616
|
+
type: Input
|
|
9617
|
+
}], isMaximized: [{
|
|
9618
|
+
type: Input
|
|
9619
|
+
}], isVisible: [{
|
|
9620
|
+
type: Input
|
|
9621
|
+
}], closeEvent: [{
|
|
9622
|
+
type: Output
|
|
9623
|
+
}], minimizeEvent: [{
|
|
9624
|
+
type: Output
|
|
9625
|
+
}], maximizeEvent: [{
|
|
9626
|
+
type: Output
|
|
9627
|
+
}], containerRef: [{
|
|
9628
|
+
type: ViewChild,
|
|
9629
|
+
args: ['container']
|
|
9630
|
+
}] } });
|
|
9631
|
+
|
|
9632
|
+
class CideEleFloatingContainerService {
|
|
9633
|
+
injector;
|
|
9634
|
+
containers = signal(new Map(), ...(ngDevMode ? [{ debugName: "containers" }] : []));
|
|
9635
|
+
nextZIndex = signal(1000, ...(ngDevMode ? [{ debugName: "nextZIndex" }] : []));
|
|
9636
|
+
instanceCounter = signal(0, ...(ngDevMode ? [{ debugName: "instanceCounter" }] : []));
|
|
9637
|
+
// Dynamic component management
|
|
9638
|
+
componentRegistry = new Map();
|
|
9639
|
+
activeComponents = new Map();
|
|
9640
|
+
constructor(injector) {
|
|
9641
|
+
this.injector = injector;
|
|
9642
|
+
}
|
|
9643
|
+
// Computed properties
|
|
9644
|
+
visibleContainers = computed(() => Array.from(this.containers().values()).filter(container => container.isVisible), ...(ngDevMode ? [{ debugName: "visibleContainers" }] : []));
|
|
9645
|
+
minimizedContainers = computed(() => Array.from(this.containers().values()).filter(container => container.isMinimized), ...(ngDevMode ? [{ debugName: "minimizedContainers" }] : []));
|
|
9646
|
+
maximizedContainers = computed(() => Array.from(this.containers().values()).filter(container => container.isMaximized), ...(ngDevMode ? [{ debugName: "maximizedContainers" }] : []));
|
|
9647
|
+
// Container management methods
|
|
9648
|
+
show(config) {
|
|
9649
|
+
const containerId = config.id || this.generateId();
|
|
9650
|
+
const instanceId = this.generateInstanceId(config.componentId || 'default');
|
|
9651
|
+
const zIndex = this.nextZIndex();
|
|
9652
|
+
const now = new Date();
|
|
9653
|
+
const container = {
|
|
9654
|
+
id: containerId,
|
|
9655
|
+
config: { ...config, id: containerId },
|
|
9656
|
+
isVisible: true,
|
|
9657
|
+
isMinimized: false,
|
|
9658
|
+
isMaximized: false,
|
|
9659
|
+
zIndex,
|
|
9660
|
+
instanceId,
|
|
9661
|
+
componentType: config.componentId || 'default',
|
|
9662
|
+
createdAt: now,
|
|
9663
|
+
lastAccessed: now
|
|
9664
|
+
};
|
|
9665
|
+
this.containers.update(containers => {
|
|
9666
|
+
const newContainers = new Map(containers);
|
|
9667
|
+
newContainers.set(containerId, container);
|
|
9668
|
+
return newContainers;
|
|
9669
|
+
});
|
|
9670
|
+
this.nextZIndex.update(z => z + 1);
|
|
9671
|
+
return containerId;
|
|
9672
|
+
}
|
|
9673
|
+
hide(containerId) {
|
|
9674
|
+
this.containers.update(containers => {
|
|
9675
|
+
const newContainers = new Map(containers);
|
|
9676
|
+
const container = newContainers.get(containerId);
|
|
9677
|
+
if (container) {
|
|
9678
|
+
container.isVisible = false;
|
|
9679
|
+
newContainers.set(containerId, container);
|
|
9680
|
+
}
|
|
9681
|
+
return newContainers;
|
|
9682
|
+
});
|
|
9683
|
+
}
|
|
9684
|
+
minimize(containerId) {
|
|
9685
|
+
this.containers.update(containers => {
|
|
9686
|
+
const newContainers = new Map(containers);
|
|
9687
|
+
const container = newContainers.get(containerId);
|
|
9688
|
+
if (container) {
|
|
9689
|
+
container.isMinimized = !container.isMinimized;
|
|
9690
|
+
newContainers.set(containerId, container);
|
|
9691
|
+
}
|
|
9692
|
+
return newContainers;
|
|
9693
|
+
});
|
|
9694
|
+
}
|
|
9695
|
+
maximize(containerId) {
|
|
9696
|
+
this.containers.update(containers => {
|
|
9697
|
+
const newContainers = new Map(containers);
|
|
9698
|
+
const container = newContainers.get(containerId);
|
|
9699
|
+
if (container) {
|
|
9700
|
+
container.isMaximized = !container.isMaximized;
|
|
9701
|
+
newContainers.set(containerId, container);
|
|
9702
|
+
}
|
|
9703
|
+
return newContainers;
|
|
9704
|
+
});
|
|
9705
|
+
}
|
|
9706
|
+
bringToFront(containerId) {
|
|
9707
|
+
const zIndex = this.nextZIndex();
|
|
9708
|
+
this.containers.update(containers => {
|
|
9709
|
+
const newContainers = new Map(containers);
|
|
9710
|
+
const container = newContainers.get(containerId);
|
|
9711
|
+
if (container) {
|
|
9712
|
+
container.zIndex = zIndex;
|
|
9713
|
+
newContainers.set(containerId, container);
|
|
9714
|
+
}
|
|
9715
|
+
return newContainers;
|
|
9716
|
+
});
|
|
9717
|
+
this.nextZIndex.update(z => z + 1);
|
|
9718
|
+
}
|
|
9719
|
+
getContainer(containerId) {
|
|
9720
|
+
return this.containers().get(containerId);
|
|
9721
|
+
}
|
|
9722
|
+
isVisible(containerId) {
|
|
9723
|
+
const container = this.getContainer(containerId);
|
|
9724
|
+
return container ? container.isVisible : false;
|
|
9725
|
+
}
|
|
9726
|
+
isMinimized(containerId) {
|
|
9727
|
+
const container = this.getContainer(containerId);
|
|
9728
|
+
return container ? container.isMinimized : false;
|
|
9729
|
+
}
|
|
9730
|
+
isMaximized(containerId) {
|
|
9731
|
+
const container = this.getContainer(containerId);
|
|
9732
|
+
return container ? container.isMaximized : false;
|
|
9733
|
+
}
|
|
9734
|
+
hideAll() {
|
|
9735
|
+
this.containers.update(containers => {
|
|
9736
|
+
const newContainers = new Map(containers);
|
|
9737
|
+
for (const [id, container] of newContainers) {
|
|
9738
|
+
container.isVisible = false;
|
|
9739
|
+
newContainers.set(id, container);
|
|
9740
|
+
}
|
|
9741
|
+
return newContainers;
|
|
9742
|
+
});
|
|
9743
|
+
}
|
|
9744
|
+
minimizeAll() {
|
|
9745
|
+
this.containers.update(containers => {
|
|
9746
|
+
const newContainers = new Map(containers);
|
|
9747
|
+
for (const [id, container] of newContainers) {
|
|
9748
|
+
if (container.isVisible) {
|
|
9749
|
+
container.isMinimized = true;
|
|
9750
|
+
newContainers.set(id, container);
|
|
9751
|
+
}
|
|
9752
|
+
}
|
|
9753
|
+
return newContainers;
|
|
9754
|
+
});
|
|
9755
|
+
}
|
|
9756
|
+
generateId() {
|
|
9757
|
+
return `floating-container-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
9758
|
+
}
|
|
9759
|
+
generateInstanceId(componentType) {
|
|
9760
|
+
const counter = this.instanceCounter() + 1;
|
|
9761
|
+
this.instanceCounter.update(c => c + 1);
|
|
9762
|
+
return `${componentType}-instance-${counter}-${Date.now()}`;
|
|
9763
|
+
}
|
|
9764
|
+
// Multiple instance management methods
|
|
9765
|
+
getInstancesByComponentType(componentType) {
|
|
9766
|
+
return Array.from(this.containers().values())
|
|
9767
|
+
.filter(container => container.componentType === componentType);
|
|
9768
|
+
}
|
|
9769
|
+
getActiveInstancesByComponentType(componentType) {
|
|
9770
|
+
return Array.from(this.containers().values())
|
|
9771
|
+
.filter(container => container.componentType === componentType && container.isVisible);
|
|
9772
|
+
}
|
|
9773
|
+
getInstanceCount(componentType) {
|
|
9774
|
+
return this.getInstancesByComponentType(componentType).length;
|
|
9775
|
+
}
|
|
9776
|
+
getActiveInstanceCount(componentType) {
|
|
9777
|
+
return this.getActiveInstancesByComponentType(componentType).length;
|
|
9778
|
+
}
|
|
9779
|
+
// Close all instances of a component type
|
|
9780
|
+
closeAllInstancesOfType(componentType) {
|
|
9781
|
+
const instances = this.getInstancesByComponentType(componentType);
|
|
9782
|
+
instances.forEach(instance => {
|
|
9783
|
+
this.hide(instance.id);
|
|
9784
|
+
});
|
|
9785
|
+
}
|
|
9786
|
+
// Minimize all instances of a component type
|
|
9787
|
+
minimizeAllInstancesOfType(componentType) {
|
|
9788
|
+
const instances = this.getActiveInstancesByComponentType(componentType);
|
|
9789
|
+
instances.forEach(instance => {
|
|
9790
|
+
this.minimize(instance.id);
|
|
9791
|
+
});
|
|
9792
|
+
}
|
|
9793
|
+
// Bring all instances of a component type to front
|
|
9794
|
+
bringAllInstancesToFront(componentType) {
|
|
9795
|
+
const instances = this.getActiveInstancesByComponentType(componentType);
|
|
9796
|
+
instances.forEach(instance => {
|
|
9797
|
+
this.bringToFront(instance.id);
|
|
9798
|
+
});
|
|
9799
|
+
}
|
|
9800
|
+
// Get instance by unique instance ID
|
|
9801
|
+
getInstanceByInstanceId(instanceId) {
|
|
9802
|
+
return Array.from(this.containers().values())
|
|
9803
|
+
.find(container => container.instanceId === instanceId);
|
|
9804
|
+
}
|
|
9805
|
+
// Update last accessed time
|
|
9806
|
+
updateLastAccessed(containerId) {
|
|
9807
|
+
this.containers.update(containers => {
|
|
9808
|
+
const newContainers = new Map(containers);
|
|
9809
|
+
const container = newContainers.get(containerId);
|
|
9810
|
+
if (container) {
|
|
9811
|
+
container.lastAccessed = new Date();
|
|
9812
|
+
newContainers.set(containerId, container);
|
|
9813
|
+
}
|
|
9814
|
+
return newContainers;
|
|
9815
|
+
});
|
|
9816
|
+
}
|
|
9817
|
+
// ===== DYNAMIC COMPONENT MANAGEMENT =====
|
|
9818
|
+
/**
|
|
9819
|
+
* Register a component for dynamic loading
|
|
9820
|
+
*/
|
|
9821
|
+
registerComponent(componentId, componentType) {
|
|
9822
|
+
this.componentRegistry.set(componentId, componentType);
|
|
9823
|
+
}
|
|
9824
|
+
/**
|
|
9825
|
+
* Unregister a component
|
|
9826
|
+
*/
|
|
9827
|
+
unregisterComponent(componentId) {
|
|
9828
|
+
this.componentRegistry.delete(componentId);
|
|
9829
|
+
}
|
|
9830
|
+
/**
|
|
9831
|
+
* Get registered component type
|
|
9832
|
+
*/
|
|
9833
|
+
getComponentType(componentId) {
|
|
9834
|
+
return this.componentRegistry.get(componentId);
|
|
9835
|
+
}
|
|
9836
|
+
/**
|
|
9837
|
+
* Check if component is registered
|
|
9838
|
+
*/
|
|
9839
|
+
isComponentRegistered(componentId) {
|
|
9840
|
+
return this.componentRegistry.has(componentId);
|
|
9841
|
+
}
|
|
9842
|
+
/**
|
|
9843
|
+
* Get registered component IDs
|
|
9844
|
+
*/
|
|
9845
|
+
getRegisteredComponentIds() {
|
|
9846
|
+
return Array.from(this.componentRegistry.keys());
|
|
9847
|
+
}
|
|
9848
|
+
/**
|
|
9849
|
+
* Create and load component dynamically
|
|
9850
|
+
*/
|
|
9851
|
+
loadComponent(componentId, viewContainer, config) {
|
|
9852
|
+
const componentType = this.componentRegistry.get(componentId);
|
|
9853
|
+
if (!componentType) {
|
|
9854
|
+
return null;
|
|
9855
|
+
}
|
|
9856
|
+
try {
|
|
9857
|
+
viewContainer.clear();
|
|
9858
|
+
const componentRef = viewContainer.createComponent(componentType, {
|
|
9859
|
+
injector: this.injector
|
|
9860
|
+
});
|
|
9861
|
+
// Set inputs if provided
|
|
9862
|
+
if (config?.inputs) {
|
|
9863
|
+
Object.keys(config.inputs).forEach(key => {
|
|
9864
|
+
if (componentRef.instance && typeof componentRef.instance === 'object' && key in componentRef.instance) {
|
|
9865
|
+
componentRef.instance[key] = config.inputs[key];
|
|
9866
|
+
}
|
|
9867
|
+
});
|
|
9868
|
+
}
|
|
9869
|
+
// Set outputs if provided
|
|
9870
|
+
if (config?.outputs) {
|
|
9871
|
+
Object.keys(config.outputs).forEach(key => {
|
|
9872
|
+
if (componentRef.instance && typeof componentRef.instance === 'object' && key in componentRef.instance) {
|
|
9873
|
+
const output = componentRef.instance[key];
|
|
9874
|
+
if (output && typeof output.subscribe === 'function') {
|
|
9875
|
+
output.subscribe(config.outputs[key]);
|
|
9876
|
+
}
|
|
9877
|
+
}
|
|
9878
|
+
});
|
|
9879
|
+
}
|
|
9880
|
+
this.activeComponents.set(componentId, componentRef);
|
|
9881
|
+
return componentRef;
|
|
9882
|
+
}
|
|
9883
|
+
catch (error) {
|
|
9884
|
+
return null;
|
|
9885
|
+
}
|
|
9886
|
+
}
|
|
9887
|
+
/**
|
|
9888
|
+
* Destroy component
|
|
9889
|
+
*/
|
|
9890
|
+
destroyComponent(componentId) {
|
|
9891
|
+
const componentRef = this.activeComponents.get(componentId);
|
|
9892
|
+
if (componentRef) {
|
|
9893
|
+
componentRef.destroy();
|
|
9894
|
+
this.activeComponents.delete(componentId);
|
|
9895
|
+
}
|
|
9896
|
+
}
|
|
9897
|
+
/**
|
|
9898
|
+
* Get active component count
|
|
9899
|
+
*/
|
|
9900
|
+
getActiveComponentCount() {
|
|
9901
|
+
return this.activeComponents.size;
|
|
9902
|
+
}
|
|
9903
|
+
/**
|
|
9904
|
+
* Clear all active components
|
|
9905
|
+
*/
|
|
9906
|
+
clearActiveComponents() {
|
|
9907
|
+
this.activeComponents.forEach(componentRef => componentRef.destroy());
|
|
9908
|
+
this.activeComponents.clear();
|
|
9909
|
+
}
|
|
9910
|
+
// ===== CONTAINER MANAGER FUNCTIONALITY =====
|
|
9911
|
+
/**
|
|
9912
|
+
* Get config signal for a container
|
|
9913
|
+
*/
|
|
9914
|
+
getConfigSignal(config) {
|
|
9915
|
+
return signal(config);
|
|
9916
|
+
}
|
|
9917
|
+
/**
|
|
9918
|
+
* Get minimized signal for a container
|
|
9919
|
+
*/
|
|
9920
|
+
getMinimizedSignal(containerId) {
|
|
9921
|
+
return computed(() => {
|
|
9922
|
+
const container = this.getContainer(containerId);
|
|
9923
|
+
return container?.isMinimized || false;
|
|
9924
|
+
});
|
|
9925
|
+
}
|
|
9926
|
+
/**
|
|
9927
|
+
* Get maximized signal for a container
|
|
9928
|
+
*/
|
|
9929
|
+
getMaximizedSignal(containerId) {
|
|
9930
|
+
return computed(() => {
|
|
9931
|
+
const container = this.getContainer(containerId);
|
|
9932
|
+
return container?.isMaximized || false;
|
|
9933
|
+
});
|
|
9934
|
+
}
|
|
9935
|
+
/**
|
|
9936
|
+
* Get visible signal for a container
|
|
9937
|
+
*/
|
|
9938
|
+
getVisibleSignal(containerId) {
|
|
9939
|
+
return computed(() => {
|
|
9940
|
+
const container = this.getContainer(containerId);
|
|
9941
|
+
return container?.isVisible || false;
|
|
9942
|
+
});
|
|
9943
|
+
}
|
|
9944
|
+
/**
|
|
9945
|
+
* Get component config for dynamic loading
|
|
9946
|
+
*/
|
|
9947
|
+
getComponentConfig(config) {
|
|
9948
|
+
if (config.componentConfig) {
|
|
9949
|
+
return {
|
|
9950
|
+
componentId: config.componentId || config.id,
|
|
9951
|
+
inputs: config.componentConfig.inputs,
|
|
9952
|
+
outputs: config.componentConfig.outputs
|
|
9953
|
+
};
|
|
9954
|
+
}
|
|
9955
|
+
return undefined;
|
|
9956
|
+
}
|
|
9957
|
+
/**
|
|
9958
|
+
* Handle container close event
|
|
9959
|
+
*/
|
|
9960
|
+
onClose(containerId) {
|
|
9961
|
+
this.hide(containerId);
|
|
9962
|
+
}
|
|
9963
|
+
/**
|
|
9964
|
+
* Handle container minimize event
|
|
9965
|
+
*/
|
|
9966
|
+
onMinimize(containerId) {
|
|
9967
|
+
this.minimize(containerId);
|
|
9968
|
+
}
|
|
9969
|
+
/**
|
|
9970
|
+
* Handle container maximize event
|
|
9971
|
+
*/
|
|
9972
|
+
onMaximize(containerId) {
|
|
9973
|
+
this.maximize(containerId);
|
|
9974
|
+
}
|
|
9975
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingContainerService, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
9976
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingContainerService, providedIn: 'root' });
|
|
9977
|
+
}
|
|
9978
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingContainerService, decorators: [{
|
|
9979
|
+
type: Injectable,
|
|
9980
|
+
args: [{
|
|
9981
|
+
providedIn: 'root'
|
|
9982
|
+
}]
|
|
9983
|
+
}], ctorParameters: () => [{ type: i0.Injector }] });
|
|
9984
|
+
|
|
9985
|
+
class CideEleFloatingContainerManagerComponent {
|
|
9986
|
+
containerService = inject(CideEleFloatingContainerService);
|
|
9987
|
+
// Computed properties
|
|
9988
|
+
visibleContainers = computed(() => this.containerService.visibleContainers(), ...(ngDevMode ? [{ debugName: "visibleContainers" }] : []));
|
|
9989
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingContainerManagerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9990
|
+
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: `
|
|
9991
|
+
@for (container of visibleContainers(); track container.id) {
|
|
9992
|
+
<cide-ele-floating-container
|
|
9993
|
+
[config]="containerService.getConfigSignal(container.config)"
|
|
9994
|
+
[isMinimized]="containerService.getMinimizedSignal(container.id)"
|
|
9995
|
+
[isMaximized]="containerService.getMaximizedSignal(container.id)"
|
|
9996
|
+
[isVisible]="containerService.getVisibleSignal(container.id)"
|
|
9997
|
+
[style.z-index]="container.zIndex"
|
|
9998
|
+
(closeEvent)="containerService.onClose($event)"
|
|
9999
|
+
(minimizeEvent)="containerService.onMinimize($event)"
|
|
10000
|
+
(maximizeEvent)="containerService.onMaximize($event)">
|
|
10001
|
+
|
|
10002
|
+
<!-- Dynamic content loading with @defer for performance -->
|
|
10003
|
+
@defer (when container.isVisible) {
|
|
10004
|
+
<div
|
|
10005
|
+
cideEleFloatingDynamic
|
|
10006
|
+
[componentId]="container.config.componentId || container.config.id"
|
|
10007
|
+
[componentConfig]="containerService.getComponentConfig(container.config)"
|
|
10008
|
+
[isVisible]="container.isVisible">
|
|
10009
|
+
</div>
|
|
10010
|
+
} @placeholder {
|
|
10011
|
+
<div class="tw-flex tw-items-center tw-justify-center tw-p-4">
|
|
10012
|
+
<cide-ele-spinner size="sm"></cide-ele-spinner>
|
|
10013
|
+
<span class="tw-ml-2 tw-text-sm tw-text-gray-600">Loading component...</span>
|
|
10014
|
+
</div>
|
|
10015
|
+
} @error {
|
|
10016
|
+
<div class="tw-flex tw-flex-col tw-items-center tw-justify-center tw-p-4 tw-text-center">
|
|
10017
|
+
<cide-ele-icon class="tw-w-8 tw-h-8 tw-text-red-500 tw-mb-2">error</cide-ele-icon>
|
|
10018
|
+
<p class="tw-text-red-600 tw-font-medium">Failed to load component</p>
|
|
10019
|
+
<p class="tw-text-gray-500 tw-text-sm">Component "{{ container.config.componentId || container.config.id }}" is not available</p>
|
|
10020
|
+
<button
|
|
10021
|
+
cideEleButton
|
|
10022
|
+
variant="outline"
|
|
10023
|
+
size="xs"
|
|
10024
|
+
(click)="containerService.onClose(container.id)"
|
|
10025
|
+
class="tw-mt-2">
|
|
10026
|
+
Close
|
|
10027
|
+
</button>
|
|
10028
|
+
</div>
|
|
10029
|
+
}
|
|
10030
|
+
</cide-ele-floating-container>
|
|
10031
|
+
}
|
|
10032
|
+
`, 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"] }, { 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)]] });
|
|
10033
|
+
}
|
|
10034
|
+
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: [{
|
|
10035
|
+
type: Component,
|
|
10036
|
+
args: [{ selector: 'cide-ele-floating-container-manager', standalone: true, imports: [CommonModule, CideEleFloatingContainerComponent, CideEleFloatingContainerDynamicDirective, CideSpinnerComponent, CideEleButtonComponent, CideIconComponent], template: `
|
|
10037
|
+
@for (container of visibleContainers(); track container.id) {
|
|
10038
|
+
<cide-ele-floating-container
|
|
10039
|
+
[config]="containerService.getConfigSignal(container.config)"
|
|
10040
|
+
[isMinimized]="containerService.getMinimizedSignal(container.id)"
|
|
10041
|
+
[isMaximized]="containerService.getMaximizedSignal(container.id)"
|
|
10042
|
+
[isVisible]="containerService.getVisibleSignal(container.id)"
|
|
10043
|
+
[style.z-index]="container.zIndex"
|
|
10044
|
+
(closeEvent)="containerService.onClose($event)"
|
|
10045
|
+
(minimizeEvent)="containerService.onMinimize($event)"
|
|
10046
|
+
(maximizeEvent)="containerService.onMaximize($event)">
|
|
10047
|
+
|
|
10048
|
+
<!-- Dynamic content loading with @defer for performance -->
|
|
10049
|
+
@defer (when container.isVisible) {
|
|
10050
|
+
<div
|
|
10051
|
+
cideEleFloatingDynamic
|
|
10052
|
+
[componentId]="container.config.componentId || container.config.id"
|
|
10053
|
+
[componentConfig]="containerService.getComponentConfig(container.config)"
|
|
10054
|
+
[isVisible]="container.isVisible">
|
|
10055
|
+
</div>
|
|
10056
|
+
} @placeholder {
|
|
10057
|
+
<div class="tw-flex tw-items-center tw-justify-center tw-p-4">
|
|
10058
|
+
<cide-ele-spinner size="sm"></cide-ele-spinner>
|
|
10059
|
+
<span class="tw-ml-2 tw-text-sm tw-text-gray-600">Loading component...</span>
|
|
10060
|
+
</div>
|
|
10061
|
+
} @error {
|
|
10062
|
+
<div class="tw-flex tw-flex-col tw-items-center tw-justify-center tw-p-4 tw-text-center">
|
|
10063
|
+
<cide-ele-icon class="tw-w-8 tw-h-8 tw-text-red-500 tw-mb-2">error</cide-ele-icon>
|
|
10064
|
+
<p class="tw-text-red-600 tw-font-medium">Failed to load component</p>
|
|
10065
|
+
<p class="tw-text-gray-500 tw-text-sm">Component "{{ container.config.componentId || container.config.id }}" is not available</p>
|
|
10066
|
+
<button
|
|
10067
|
+
cideEleButton
|
|
10068
|
+
variant="outline"
|
|
10069
|
+
size="xs"
|
|
10070
|
+
(click)="containerService.onClose(container.id)"
|
|
10071
|
+
class="tw-mt-2">
|
|
10072
|
+
Close
|
|
10073
|
+
</button>
|
|
10074
|
+
</div>
|
|
10075
|
+
}
|
|
10076
|
+
</cide-ele-floating-container>
|
|
10077
|
+
}
|
|
10078
|
+
` }]
|
|
10079
|
+
}], ctorParameters: null, propDecorators: null }) });
|
|
10080
|
+
|
|
10081
|
+
class CideEleFloatingFeaturesService {
|
|
10082
|
+
containerService = inject(CideEleFloatingContainerService);
|
|
10083
|
+
constructor() {
|
|
10084
|
+
// Auto-register file uploader component on service initialization
|
|
10085
|
+
this.initializeFileUploader();
|
|
10086
|
+
// Entity rights sharing is handled by its own dedicated service
|
|
10087
|
+
}
|
|
10088
|
+
async initializeFileUploader() {
|
|
10089
|
+
// Check if already registered to avoid duplicate registration
|
|
10090
|
+
if (this.containerService.isComponentRegistered('file-uploader')) {
|
|
10091
|
+
console.log('✅ File uploader component already registered');
|
|
10092
|
+
return;
|
|
10093
|
+
}
|
|
10094
|
+
try {
|
|
10095
|
+
// Use relative import to avoid circular dependency
|
|
10096
|
+
const module = await Promise.resolve().then(function () { return floatingFileUploader_component; });
|
|
10097
|
+
if (module.CideEleFloatingFileUploaderComponent) {
|
|
10098
|
+
this.containerService.registerComponent('file-uploader', module.CideEleFloatingFileUploaderComponent);
|
|
10099
|
+
console.log('✅ File uploader component registered successfully');
|
|
10100
|
+
}
|
|
10101
|
+
}
|
|
10102
|
+
catch (error) {
|
|
10103
|
+
console.error('❌ Failed to register file uploader component:', error);
|
|
10104
|
+
}
|
|
10105
|
+
}
|
|
10106
|
+
// File Uploader
|
|
10107
|
+
async showFileUploader(componentType, inputData) {
|
|
10108
|
+
// Ensure component is registered before showing
|
|
10109
|
+
if (!this.containerService.isComponentRegistered('file-uploader')) {
|
|
10110
|
+
console.log('📝 File uploader component not registered, registering now...');
|
|
10111
|
+
await this.initializeFileUploader();
|
|
10112
|
+
}
|
|
10113
|
+
const config = {
|
|
10114
|
+
id: 'file-uploader-main',
|
|
10115
|
+
title: 'File Uploader',
|
|
10116
|
+
icon: 'cloud_upload',
|
|
10117
|
+
width: '500px',
|
|
10118
|
+
height: '400px',
|
|
10119
|
+
minWidth: '400px',
|
|
10120
|
+
minHeight: '300px',
|
|
10121
|
+
resizable: true,
|
|
10122
|
+
draggable: true,
|
|
10123
|
+
closable: true,
|
|
10124
|
+
minimizable: true,
|
|
10125
|
+
maximizable: true,
|
|
10126
|
+
componentId: 'file-uploader',
|
|
10127
|
+
componentConfig: inputData ? {
|
|
10128
|
+
inputs: inputData,
|
|
10129
|
+
outputs: {}
|
|
10130
|
+
} : undefined
|
|
10131
|
+
};
|
|
10132
|
+
// Register component if provided
|
|
10133
|
+
if (componentType) {
|
|
10134
|
+
this.registerComponent('file-uploader', componentType);
|
|
10135
|
+
}
|
|
10136
|
+
return this.containerService.show(config);
|
|
10137
|
+
}
|
|
10138
|
+
hideFileUploader() {
|
|
10139
|
+
this.containerService.hide('file-uploader-main');
|
|
10140
|
+
}
|
|
10141
|
+
// Show file uploader with specific container ID (for multiple instances)
|
|
10142
|
+
showFileUploaderInstance(containerId, componentType, config = {}) {
|
|
10143
|
+
const defaultConfig = {
|
|
10144
|
+
id: containerId,
|
|
10145
|
+
title: 'File Uploader',
|
|
10146
|
+
icon: 'cloud_upload',
|
|
10147
|
+
width: '500px',
|
|
10148
|
+
height: '400px',
|
|
10149
|
+
minWidth: '400px',
|
|
10150
|
+
minHeight: '300px',
|
|
10151
|
+
resizable: true,
|
|
10152
|
+
draggable: true,
|
|
10153
|
+
closable: true,
|
|
10154
|
+
minimizable: true,
|
|
10155
|
+
maximizable: true,
|
|
10156
|
+
componentId: 'file-uploader',
|
|
10157
|
+
...config
|
|
10158
|
+
};
|
|
10159
|
+
// Register component if provided
|
|
10160
|
+
if (componentType) {
|
|
10161
|
+
this.registerComponent('file-uploader', componentType);
|
|
10162
|
+
}
|
|
10163
|
+
return this.containerService.show(defaultConfig);
|
|
10164
|
+
}
|
|
10165
|
+
// Generic method to show any floating feature
|
|
10166
|
+
showFeature(featureId, config) {
|
|
10167
|
+
return this.containerService.show({ ...config, id: featureId });
|
|
10168
|
+
}
|
|
10169
|
+
// Generic method for showing any component dynamically
|
|
10170
|
+
showComponent(containerId, componentId, title, componentType, config = {}) {
|
|
10171
|
+
const containerConfig = {
|
|
10172
|
+
id: containerId,
|
|
10173
|
+
title,
|
|
10174
|
+
icon: 'widgets',
|
|
10175
|
+
width: '400px',
|
|
10176
|
+
height: '500px',
|
|
10177
|
+
minWidth: '300px',
|
|
10178
|
+
minHeight: '200px',
|
|
10179
|
+
resizable: true,
|
|
10180
|
+
draggable: true,
|
|
10181
|
+
closable: true,
|
|
10182
|
+
minimizable: true,
|
|
10183
|
+
maximizable: true,
|
|
10184
|
+
componentId,
|
|
10185
|
+
...config
|
|
10186
|
+
};
|
|
10187
|
+
// Register component if provided
|
|
10188
|
+
if (componentType) {
|
|
10189
|
+
this.registerComponent(componentId, componentType);
|
|
10190
|
+
}
|
|
10191
|
+
return this.containerService.show(containerConfig);
|
|
10192
|
+
}
|
|
10193
|
+
// Show multiple instances of the same component
|
|
10194
|
+
showMultipleInstances(componentId, titlePrefix, count, config = {}) {
|
|
10195
|
+
const containerIds = [];
|
|
10196
|
+
for (let i = 1; i <= count; i++) {
|
|
10197
|
+
const containerId = `${componentId}-instance-${i}-${Date.now()}`;
|
|
10198
|
+
const title = `${titlePrefix} ${i}`;
|
|
10199
|
+
const containerConfig = {
|
|
10200
|
+
id: containerId,
|
|
10201
|
+
title,
|
|
10202
|
+
icon: 'widgets',
|
|
10203
|
+
width: '400px',
|
|
10204
|
+
height: '500px',
|
|
10205
|
+
minWidth: '300px',
|
|
10206
|
+
minHeight: '200px',
|
|
10207
|
+
resizable: true,
|
|
10208
|
+
draggable: true,
|
|
10209
|
+
closable: true,
|
|
10210
|
+
minimizable: true,
|
|
10211
|
+
maximizable: true,
|
|
10212
|
+
componentId,
|
|
10213
|
+
...config
|
|
10214
|
+
};
|
|
10215
|
+
const id = this.containerService.show(containerConfig);
|
|
10216
|
+
containerIds.push(id);
|
|
10217
|
+
}
|
|
10218
|
+
return containerIds;
|
|
10219
|
+
}
|
|
10220
|
+
// Get all instances of a component type
|
|
10221
|
+
getInstancesOfType(componentType) {
|
|
10222
|
+
return this.containerService.getInstancesByComponentType(componentType);
|
|
10223
|
+
}
|
|
10224
|
+
// Get active instances of a component type
|
|
10225
|
+
getActiveInstancesOfType(componentType) {
|
|
10226
|
+
return this.containerService.getActiveInstancesByComponentType(componentType);
|
|
10227
|
+
}
|
|
10228
|
+
// Close all instances of a component type
|
|
10229
|
+
closeAllInstancesOfType(componentType) {
|
|
10230
|
+
this.containerService.closeAllInstancesOfType(componentType);
|
|
10231
|
+
}
|
|
10232
|
+
// Minimize all instances of a component type
|
|
10233
|
+
minimizeAllInstancesOfType(componentType) {
|
|
10234
|
+
this.containerService.minimizeAllInstancesOfType(componentType);
|
|
10235
|
+
}
|
|
10236
|
+
// Get instance count for a component type
|
|
10237
|
+
getInstanceCount(componentType) {
|
|
10238
|
+
return this.containerService.getInstanceCount(componentType);
|
|
10239
|
+
}
|
|
10240
|
+
// Get active instance count for a component type
|
|
10241
|
+
getActiveInstanceCount(componentType) {
|
|
10242
|
+
return this.containerService.getActiveInstanceCount(componentType);
|
|
10243
|
+
}
|
|
10244
|
+
// Register a component for dynamic loading
|
|
10245
|
+
registerComponent(componentId, componentType) {
|
|
10246
|
+
this.containerService.registerComponent(componentId, componentType);
|
|
10247
|
+
}
|
|
10248
|
+
// Unregister a component
|
|
10249
|
+
unregisterComponent(componentId) {
|
|
10250
|
+
this.containerService.unregisterComponent(componentId);
|
|
10251
|
+
}
|
|
10252
|
+
hideFeature(featureId) {
|
|
10253
|
+
this.containerService.hide(featureId);
|
|
10254
|
+
}
|
|
10255
|
+
// Utility methods
|
|
10256
|
+
bringToFront(featureId) {
|
|
10257
|
+
this.containerService.bringToFront(featureId);
|
|
10258
|
+
}
|
|
10259
|
+
minimize(featureId) {
|
|
10260
|
+
this.containerService.minimize(featureId);
|
|
10261
|
+
}
|
|
10262
|
+
maximize(featureId) {
|
|
10263
|
+
this.containerService.maximize(featureId);
|
|
10264
|
+
}
|
|
10265
|
+
isVisible(featureId) {
|
|
10266
|
+
return this.containerService.isVisible(featureId);
|
|
10267
|
+
}
|
|
10268
|
+
hideAll() {
|
|
10269
|
+
this.containerService.hideAll();
|
|
10270
|
+
}
|
|
10271
|
+
minimizeAll() {
|
|
10272
|
+
this.containerService.minimizeAll();
|
|
10273
|
+
}
|
|
10274
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingFeaturesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
10275
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingFeaturesService, providedIn: 'root' });
|
|
10276
|
+
}
|
|
10277
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingFeaturesService, decorators: [{
|
|
10278
|
+
type: Injectable,
|
|
10279
|
+
args: [{
|
|
10280
|
+
providedIn: 'root'
|
|
10281
|
+
}]
|
|
10282
|
+
}], ctorParameters: () => [] });
|
|
10283
|
+
|
|
10284
|
+
class CideEleFloatingContainerDynamicDirective {
|
|
10285
|
+
viewContainer;
|
|
10286
|
+
containerService;
|
|
10287
|
+
componentId;
|
|
10288
|
+
componentConfig;
|
|
10289
|
+
isVisible = true;
|
|
10290
|
+
componentRef = null;
|
|
10291
|
+
constructor(viewContainer, containerService) {
|
|
10292
|
+
this.viewContainer = viewContainer;
|
|
10293
|
+
this.containerService = containerService;
|
|
10294
|
+
}
|
|
10295
|
+
ngOnInit() {
|
|
10296
|
+
if (this.isVisible && this.componentId) {
|
|
10297
|
+
this.loadComponent();
|
|
10298
|
+
}
|
|
10299
|
+
}
|
|
10300
|
+
ngOnDestroy() {
|
|
10301
|
+
this.destroyComponent();
|
|
10302
|
+
}
|
|
10303
|
+
ngOnChanges() {
|
|
10304
|
+
if (this.isVisible && this.componentId && !this.componentRef) {
|
|
10305
|
+
this.loadComponent();
|
|
10306
|
+
}
|
|
10307
|
+
else if (!this.isVisible && this.componentRef) {
|
|
10308
|
+
this.destroyComponent();
|
|
10309
|
+
}
|
|
10310
|
+
}
|
|
10311
|
+
loadComponent() {
|
|
10312
|
+
if (this.componentId && this.containerService.isComponentRegistered(this.componentId)) {
|
|
10313
|
+
this.componentRef = this.containerService.loadComponent(this.componentId, this.viewContainer, this.componentConfig);
|
|
10314
|
+
}
|
|
10315
|
+
else {
|
|
10316
|
+
console.warn(`Component '${this.componentId}' is not registered. Available components:`, this.containerService.getRegisteredComponentIds());
|
|
10317
|
+
// Retry after a short delay in case registration is still in progress
|
|
10318
|
+
setTimeout(() => {
|
|
10319
|
+
if (this.containerService.isComponentRegistered(this.componentId)) {
|
|
10320
|
+
this.componentRef = this.containerService.loadComponent(this.componentId, this.viewContainer, this.componentConfig);
|
|
10321
|
+
}
|
|
10322
|
+
else {
|
|
10323
|
+
console.error(`Component '${this.componentId}' still not registered after retry`);
|
|
10324
|
+
}
|
|
10325
|
+
}, 100);
|
|
10326
|
+
}
|
|
10327
|
+
}
|
|
10328
|
+
destroyComponent() {
|
|
10329
|
+
if (this.componentRef) {
|
|
10330
|
+
this.componentRef.destroy();
|
|
10331
|
+
this.componentRef = null;
|
|
10332
|
+
}
|
|
10333
|
+
}
|
|
10334
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingContainerDynamicDirective, deps: [{ token: i0.ViewContainerRef }, { token: CideEleFloatingContainerService }], target: i0.ɵɵFactoryTarget.Directive });
|
|
10335
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.1.7", type: CideEleFloatingContainerDynamicDirective, isStandalone: true, selector: "[cideEleFloatingDynamic]", inputs: { componentId: "componentId", componentConfig: "componentConfig", isVisible: "isVisible" }, usesOnChanges: true, ngImport: i0 });
|
|
10336
|
+
}
|
|
10337
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingContainerDynamicDirective, decorators: [{
|
|
10338
|
+
type: Directive,
|
|
10339
|
+
args: [{
|
|
10340
|
+
selector: '[cideEleFloatingDynamic]',
|
|
10341
|
+
standalone: true
|
|
10342
|
+
}]
|
|
10343
|
+
}], ctorParameters: () => [{ type: i0.ViewContainerRef }, { type: CideEleFloatingContainerService }], propDecorators: { componentId: [{
|
|
10344
|
+
type: Input
|
|
10345
|
+
}], componentConfig: [{
|
|
10346
|
+
type: Input
|
|
10347
|
+
}], isVisible: [{
|
|
10348
|
+
type: Input
|
|
10349
|
+
}] } });
|
|
10350
|
+
|
|
10351
|
+
var floatingContainerDynamic_directive = /*#__PURE__*/Object.freeze({
|
|
10352
|
+
__proto__: null,
|
|
10353
|
+
CideEleFloatingContainerDynamicDirective: CideEleFloatingContainerDynamicDirective
|
|
10354
|
+
});
|
|
10355
|
+
|
|
9203
10356
|
/*
|
|
9204
10357
|
* Public API Surface of cloud-ide-element
|
|
9205
10358
|
* Here we can add what need to be exported from library
|
|
@@ -9209,5 +10362,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
|
|
|
9209
10362
|
* Generated bundle index. Do not edit.
|
|
9210
10363
|
*/
|
|
9211
10364
|
|
|
9212
|
-
export { CideCoreFileManagerService, CideEleButtonComponent, CideEleConfirmationModalComponent, CideEleDataGridComponent, CideEleDropdownComponent, CideEleFileImageDirective, CideEleFileInputComponent, CideEleFileManagerService, CideEleFloatingFileUploaderComponent, CideEleGlobalNotificationsComponent, CideEleJsonEditorComponent, CideEleResizerDirective, CideEleSkeletonLoaderComponent, CideEleTabComponent, CideEleToastNotificationComponent, CideElementsService, CideIconComponent, CideInputComponent, CideSelectComponent, CideSelectOptionComponent, CideSpinnerComponent, CideTextareaComponent, ConfirmationService, CoreFileManagerInsertUpdatePayload, DEFAULT_GRID_CONFIG, DropdownManagerService, ICoreCyfmSave, MFileManager, NotificationService, TooltipDirective };
|
|
10365
|
+
export { CideCoreFileManagerService, CideEleButtonComponent, CideEleConfirmationModalComponent, CideEleDataGridComponent, CideEleDropdownComponent, CideEleFileImageDirective, CideEleFileInputComponent, CideEleFileManagerService, CideEleFloatingContainerComponent, CideEleFloatingContainerDynamicDirective, CideEleFloatingContainerManagerComponent, CideEleFloatingContainerService, CideEleFloatingFeaturesService, CideEleFloatingFileUploaderComponent, CideEleGlobalNotificationsComponent, CideEleJsonEditorComponent, CideEleResizerDirective, CideEleSkeletonLoaderComponent, CideEleTabComponent, CideEleToastNotificationComponent, CideElementsService, CideIconComponent, CideInputComponent, CideSelectComponent, CideSelectOptionComponent, CideSpinnerComponent, CideTextareaComponent, ConfirmationService, CoreFileManagerInsertUpdatePayload, DEFAULT_GRID_CONFIG, DropdownManagerService, ICoreCyfmSave, MFileManager, NotificationService, TooltipDirective };
|
|
9213
10366
|
//# sourceMappingURL=cloud-ide-element.mjs.map
|