cloud-ide-element 1.0.114 → 1.0.116

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.
@@ -3375,11 +3375,467 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
3375
3375
  }]
3376
3376
  }], ctorParameters: () => [] });
3377
3377
 
3378
+ class CideEleFloatingContainerService {
3379
+ injector;
3380
+ containers = signal(new Map(), ...(ngDevMode ? [{ debugName: "containers" }] : []));
3381
+ nextZIndex = signal(1000, ...(ngDevMode ? [{ debugName: "nextZIndex" }] : []));
3382
+ instanceCounter = signal(0, ...(ngDevMode ? [{ debugName: "instanceCounter" }] : []));
3383
+ // Dynamic component management
3384
+ componentRegistry = new Map();
3385
+ activeComponents = new Map();
3386
+ constructor(injector) {
3387
+ this.injector = injector;
3388
+ }
3389
+ // Computed properties
3390
+ visibleContainers = computed(() => Array.from(this.containers().values()).filter(container => container.isVisible), ...(ngDevMode ? [{ debugName: "visibleContainers" }] : []));
3391
+ minimizedContainers = computed(() => Array.from(this.containers().values()).filter(container => container.isMinimized), ...(ngDevMode ? [{ debugName: "minimizedContainers" }] : []));
3392
+ maximizedContainers = computed(() => Array.from(this.containers().values()).filter(container => container.isMaximized), ...(ngDevMode ? [{ debugName: "maximizedContainers" }] : []));
3393
+ // Container management methods
3394
+ show(config) {
3395
+ const containerId = config.id || this.generateId();
3396
+ const instanceId = this.generateInstanceId(config.componentId || 'default');
3397
+ const zIndex = this.nextZIndex();
3398
+ const now = new Date();
3399
+ const container = {
3400
+ id: containerId,
3401
+ config: { ...config, id: containerId },
3402
+ isVisible: true,
3403
+ isMinimized: false,
3404
+ isMaximized: false,
3405
+ zIndex,
3406
+ instanceId,
3407
+ componentType: config.componentId || 'default',
3408
+ createdAt: now,
3409
+ lastAccessed: now
3410
+ };
3411
+ this.containers.update(containers => {
3412
+ const newContainers = new Map(containers);
3413
+ newContainers.set(containerId, container);
3414
+ return newContainers;
3415
+ });
3416
+ this.nextZIndex.update(z => z + 1);
3417
+ return containerId;
3418
+ }
3419
+ hide(containerId) {
3420
+ this.containers.update(containers => {
3421
+ const newContainers = new Map(containers);
3422
+ const container = newContainers.get(containerId);
3423
+ if (container) {
3424
+ container.isVisible = false;
3425
+ newContainers.set(containerId, container);
3426
+ }
3427
+ return newContainers;
3428
+ });
3429
+ }
3430
+ minimize(containerId) {
3431
+ this.containers.update(containers => {
3432
+ const newContainers = new Map(containers);
3433
+ const container = newContainers.get(containerId);
3434
+ if (container) {
3435
+ container.isMinimized = !container.isMinimized;
3436
+ newContainers.set(containerId, container);
3437
+ }
3438
+ return newContainers;
3439
+ });
3440
+ }
3441
+ maximize(containerId) {
3442
+ this.containers.update(containers => {
3443
+ const newContainers = new Map(containers);
3444
+ const container = newContainers.get(containerId);
3445
+ if (container) {
3446
+ container.isMaximized = !container.isMaximized;
3447
+ newContainers.set(containerId, container);
3448
+ }
3449
+ return newContainers;
3450
+ });
3451
+ }
3452
+ bringToFront(containerId) {
3453
+ const zIndex = this.nextZIndex();
3454
+ this.containers.update(containers => {
3455
+ const newContainers = new Map(containers);
3456
+ const container = newContainers.get(containerId);
3457
+ if (container) {
3458
+ container.zIndex = zIndex;
3459
+ newContainers.set(containerId, container);
3460
+ }
3461
+ return newContainers;
3462
+ });
3463
+ this.nextZIndex.update(z => z + 1);
3464
+ }
3465
+ getContainer(containerId) {
3466
+ return this.containers().get(containerId);
3467
+ }
3468
+ isVisible(containerId) {
3469
+ const container = this.getContainer(containerId);
3470
+ return container ? container.isVisible : false;
3471
+ }
3472
+ isMinimized(containerId) {
3473
+ const container = this.getContainer(containerId);
3474
+ return container ? container.isMinimized : false;
3475
+ }
3476
+ isMaximized(containerId) {
3477
+ const container = this.getContainer(containerId);
3478
+ return container ? container.isMaximized : false;
3479
+ }
3480
+ hideAll() {
3481
+ this.containers.update(containers => {
3482
+ const newContainers = new Map(containers);
3483
+ for (const [id, container] of newContainers) {
3484
+ container.isVisible = false;
3485
+ newContainers.set(id, container);
3486
+ }
3487
+ return newContainers;
3488
+ });
3489
+ }
3490
+ minimizeAll() {
3491
+ this.containers.update(containers => {
3492
+ const newContainers = new Map(containers);
3493
+ for (const [id, container] of newContainers) {
3494
+ if (container.isVisible) {
3495
+ container.isMinimized = true;
3496
+ newContainers.set(id, container);
3497
+ }
3498
+ }
3499
+ return newContainers;
3500
+ });
3501
+ }
3502
+ generateId() {
3503
+ return `floating-container-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
3504
+ }
3505
+ generateInstanceId(componentType) {
3506
+ const counter = this.instanceCounter() + 1;
3507
+ this.instanceCounter.update(c => c + 1);
3508
+ return `${componentType}-instance-${counter}-${Date.now()}`;
3509
+ }
3510
+ // Multiple instance management methods
3511
+ getInstancesByComponentType(componentType) {
3512
+ return Array.from(this.containers().values())
3513
+ .filter(container => container.componentType === componentType);
3514
+ }
3515
+ getActiveInstancesByComponentType(componentType) {
3516
+ return Array.from(this.containers().values())
3517
+ .filter(container => container.componentType === componentType && container.isVisible);
3518
+ }
3519
+ getInstanceCount(componentType) {
3520
+ return this.getInstancesByComponentType(componentType).length;
3521
+ }
3522
+ getActiveInstanceCount(componentType) {
3523
+ return this.getActiveInstancesByComponentType(componentType).length;
3524
+ }
3525
+ // Close all instances of a component type
3526
+ closeAllInstancesOfType(componentType) {
3527
+ const instances = this.getInstancesByComponentType(componentType);
3528
+ instances.forEach(instance => {
3529
+ this.hide(instance.id);
3530
+ });
3531
+ }
3532
+ // Minimize all instances of a component type
3533
+ minimizeAllInstancesOfType(componentType) {
3534
+ const instances = this.getActiveInstancesByComponentType(componentType);
3535
+ instances.forEach(instance => {
3536
+ this.minimize(instance.id);
3537
+ });
3538
+ }
3539
+ // Bring all instances of a component type to front
3540
+ bringAllInstancesToFront(componentType) {
3541
+ const instances = this.getActiveInstancesByComponentType(componentType);
3542
+ instances.forEach(instance => {
3543
+ this.bringToFront(instance.id);
3544
+ });
3545
+ }
3546
+ // Get instance by unique instance ID
3547
+ getInstanceByInstanceId(instanceId) {
3548
+ return Array.from(this.containers().values())
3549
+ .find(container => container.instanceId === instanceId);
3550
+ }
3551
+ // Update last accessed time
3552
+ updateLastAccessed(containerId) {
3553
+ this.containers.update(containers => {
3554
+ const newContainers = new Map(containers);
3555
+ const container = newContainers.get(containerId);
3556
+ if (container) {
3557
+ container.lastAccessed = new Date();
3558
+ newContainers.set(containerId, container);
3559
+ }
3560
+ return newContainers;
3561
+ });
3562
+ }
3563
+ // ===== DYNAMIC COMPONENT MANAGEMENT =====
3564
+ /**
3565
+ * Register a component for dynamic loading
3566
+ */
3567
+ registerComponent(componentId, componentType) {
3568
+ this.componentRegistry.set(componentId, componentType);
3569
+ }
3570
+ /**
3571
+ * Unregister a component
3572
+ */
3573
+ unregisterComponent(componentId) {
3574
+ this.componentRegistry.delete(componentId);
3575
+ }
3576
+ /**
3577
+ * Get registered component type
3578
+ */
3579
+ getComponentType(componentId) {
3580
+ return this.componentRegistry.get(componentId);
3581
+ }
3582
+ /**
3583
+ * Check if component is registered
3584
+ */
3585
+ isComponentRegistered(componentId) {
3586
+ return this.componentRegistry.has(componentId);
3587
+ }
3588
+ /**
3589
+ * Get registered component IDs
3590
+ */
3591
+ getRegisteredComponentIds() {
3592
+ return Array.from(this.componentRegistry.keys());
3593
+ }
3594
+ /**
3595
+ * Create and load component dynamically
3596
+ */
3597
+ loadComponent(componentId, viewContainer, config) {
3598
+ const componentType = this.componentRegistry.get(componentId);
3599
+ if (!componentType) {
3600
+ return null;
3601
+ }
3602
+ try {
3603
+ viewContainer.clear();
3604
+ const componentRef = viewContainer.createComponent(componentType, {
3605
+ injector: this.injector
3606
+ });
3607
+ // Set inputs if provided
3608
+ if (config?.inputs) {
3609
+ Object.keys(config.inputs).forEach(key => {
3610
+ if (componentRef.instance && typeof componentRef.instance === 'object' && key in componentRef.instance) {
3611
+ componentRef.instance[key] = config.inputs[key];
3612
+ }
3613
+ });
3614
+ }
3615
+ // Set outputs if provided
3616
+ if (config?.outputs) {
3617
+ Object.keys(config.outputs).forEach(key => {
3618
+ if (componentRef.instance && typeof componentRef.instance === 'object' && key in componentRef.instance) {
3619
+ const output = componentRef.instance[key];
3620
+ if (output && typeof output.subscribe === 'function') {
3621
+ output.subscribe(config.outputs[key]);
3622
+ }
3623
+ }
3624
+ });
3625
+ }
3626
+ this.activeComponents.set(componentId, componentRef);
3627
+ return componentRef;
3628
+ }
3629
+ catch (error) {
3630
+ return null;
3631
+ }
3632
+ }
3633
+ /**
3634
+ * Destroy component
3635
+ */
3636
+ destroyComponent(componentId) {
3637
+ const componentRef = this.activeComponents.get(componentId);
3638
+ if (componentRef) {
3639
+ componentRef.destroy();
3640
+ this.activeComponents.delete(componentId);
3641
+ }
3642
+ }
3643
+ /**
3644
+ * Get active component count
3645
+ */
3646
+ getActiveComponentCount() {
3647
+ return this.activeComponents.size;
3648
+ }
3649
+ /**
3650
+ * Clear all active components
3651
+ */
3652
+ clearActiveComponents() {
3653
+ this.activeComponents.forEach(componentRef => componentRef.destroy());
3654
+ this.activeComponents.clear();
3655
+ }
3656
+ // ===== CONTAINER MANAGER FUNCTIONALITY =====
3657
+ /**
3658
+ * Get config signal for a container
3659
+ */
3660
+ getConfigSignal(config) {
3661
+ return signal(config);
3662
+ }
3663
+ /**
3664
+ * Get minimized signal for a container
3665
+ */
3666
+ getMinimizedSignal(containerId) {
3667
+ return computed(() => {
3668
+ const container = this.getContainer(containerId);
3669
+ return container?.isMinimized || false;
3670
+ });
3671
+ }
3672
+ /**
3673
+ * Get maximized signal for a container
3674
+ */
3675
+ getMaximizedSignal(containerId) {
3676
+ return computed(() => {
3677
+ const container = this.getContainer(containerId);
3678
+ return container?.isMaximized || false;
3679
+ });
3680
+ }
3681
+ /**
3682
+ * Get visible signal for a container
3683
+ */
3684
+ getVisibleSignal(containerId) {
3685
+ return computed(() => {
3686
+ const container = this.getContainer(containerId);
3687
+ return container?.isVisible || false;
3688
+ });
3689
+ }
3690
+ /**
3691
+ * Get component config for dynamic loading
3692
+ */
3693
+ getComponentConfig(config) {
3694
+ if (config.componentConfig) {
3695
+ return {
3696
+ componentId: config.componentId || config.id,
3697
+ inputs: config.componentConfig.inputs,
3698
+ outputs: config.componentConfig.outputs
3699
+ };
3700
+ }
3701
+ return undefined;
3702
+ }
3703
+ /**
3704
+ * Handle container close event
3705
+ */
3706
+ onClose(containerId) {
3707
+ this.hide(containerId);
3708
+ }
3709
+ /**
3710
+ * Handle container minimize event
3711
+ */
3712
+ onMinimize(containerId) {
3713
+ this.minimize(containerId);
3714
+ }
3715
+ /**
3716
+ * Handle container maximize event
3717
+ */
3718
+ onMaximize(containerId) {
3719
+ this.maximize(containerId);
3720
+ }
3721
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingContainerService, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
3722
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingContainerService, providedIn: 'root' });
3723
+ }
3724
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingContainerService, decorators: [{
3725
+ type: Injectable,
3726
+ args: [{
3727
+ providedIn: 'root'
3728
+ }]
3729
+ }], ctorParameters: () => [{ type: i0.Injector }] });
3730
+
3731
+ class CideEleFloatingFileUploaderService {
3732
+ containerService = inject(CideEleFloatingContainerService);
3733
+ constructor() {
3734
+ // Auto-register file uploader component on service initialization
3735
+ this.initializeFileUploader();
3736
+ }
3737
+ async initializeFileUploader() {
3738
+ // Check if already registered to avoid duplicate registration
3739
+ if (this.containerService.isComponentRegistered('file-uploader')) {
3740
+ console.log('✅ File uploader component already registered');
3741
+ return;
3742
+ }
3743
+ try {
3744
+ // Use relative import to avoid circular dependency
3745
+ const module = await Promise.resolve().then(function () { return floatingFileUploader_component; });
3746
+ if (module.CideEleFloatingFileUploaderComponent) {
3747
+ this.containerService.registerComponent('file-uploader', module.CideEleFloatingFileUploaderComponent);
3748
+ console.log('✅ File uploader component registered successfully');
3749
+ }
3750
+ }
3751
+ catch (error) {
3752
+ console.error('❌ Failed to register file uploader component:', error);
3753
+ }
3754
+ }
3755
+ /**
3756
+ * Show file uploader in floating container
3757
+ */
3758
+ async show(data) {
3759
+ console.log('🚀 Showing file uploader...');
3760
+ console.log('📋 Current registered components:', this.containerService.getRegisteredComponentIds());
3761
+ // Ensure component is registered before showing
3762
+ if (!this.containerService.isComponentRegistered('file-uploader')) {
3763
+ console.log('📝 File uploader component not registered, registering now...');
3764
+ await this.initializeFileUploader();
3765
+ console.log('📋 Components after registration:', this.containerService.getRegisteredComponentIds());
3766
+ }
3767
+ else {
3768
+ console.log('✅ File uploader component already registered');
3769
+ }
3770
+ const config = {
3771
+ id: 'file-uploader-main',
3772
+ title: 'File Uploader',
3773
+ icon: 'cloud_upload',
3774
+ width: '500px',
3775
+ height: '400px',
3776
+ minWidth: '400px',
3777
+ minHeight: '300px',
3778
+ resizable: true,
3779
+ draggable: true,
3780
+ closable: true,
3781
+ minimizable: true,
3782
+ maximizable: true,
3783
+ componentId: 'file-uploader',
3784
+ componentConfig: data ? {
3785
+ inputs: { data },
3786
+ outputs: {}
3787
+ } : undefined
3788
+ };
3789
+ const containerId = this.containerService.show(config);
3790
+ console.log('✅ Container created with ID:', containerId);
3791
+ return containerId;
3792
+ }
3793
+ /**
3794
+ * Hide file uploader
3795
+ */
3796
+ hide() {
3797
+ this.containerService.hide('file-uploader-main');
3798
+ }
3799
+ /**
3800
+ * Show file uploader with specific group ID
3801
+ */
3802
+ async showWithGroupId(groupId, additionalData) {
3803
+ const data = {
3804
+ groupId,
3805
+ ...additionalData
3806
+ };
3807
+ return this.show(data);
3808
+ }
3809
+ /**
3810
+ * Show file uploader for user with specific settings
3811
+ */
3812
+ async showForUser(userId, settings) {
3813
+ const data = {
3814
+ userId,
3815
+ allowedTypes: ['image/*', 'application/pdf', 'text/*'],
3816
+ maxFileSize: 10485760, // 10MB
3817
+ multiple: true,
3818
+ autoUpload: false,
3819
+ ...settings
3820
+ };
3821
+ return this.show(data);
3822
+ }
3823
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingFileUploaderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3824
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingFileUploaderService, providedIn: 'root' });
3825
+ }
3826
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingFileUploaderService, decorators: [{
3827
+ type: Injectable,
3828
+ args: [{
3829
+ providedIn: 'root'
3830
+ }]
3831
+ }], ctorParameters: () => [] });
3832
+
3378
3833
  class CideEleFileInputComponent {
3379
3834
  fileManagerService = inject(CideEleFileManagerService);
3380
3835
  notificationService = inject(NotificationService);
3381
3836
  elementService = inject(CideElementsService);
3382
3837
  destroyRef = inject(DestroyRef);
3838
+ floatingFileUploaderService = inject(CideEleFloatingFileUploaderService);
3383
3839
  // private readonly pendingTasks = inject(PendingTasks); // TODO: Fix PendingTasks API usage
3384
3840
  // Traditional @Input() decorators
3385
3841
  label = 'Choose file';
@@ -4123,8 +4579,59 @@ class CideEleFileInputComponent {
4123
4579
  /**
4124
4580
  * Show floating uploader (alias for showUploader for template)
4125
4581
  */
4126
- showFloatingUploaderDialog() {
4127
- this.showUploader();
4582
+ async showFloatingUploaderDialog() {
4583
+ console.log('👁️ [FileInput] Opening floating file uploader via dedicated service');
4584
+ if (!this.showFloatingUploaderSignal()) {
4585
+ console.log('⚠️ [FileInput] Floating uploader is disabled');
4586
+ return;
4587
+ }
4588
+ const groupId = this.groupId();
4589
+ if (groupId) {
4590
+ console.log("✅ [FileInput] Has existing group ID:", groupId);
4591
+ // Use the dedicated floating file uploader service
4592
+ try {
4593
+ await this.floatingFileUploaderService.showWithGroupId(groupId, {
4594
+ allowedTypes: this.acceptSignal() ? this.acceptSignal().split(',') : undefined,
4595
+ multiple: this.multipleSignal(),
4596
+ autoUpload: this.autoUploadSignal(),
4597
+ userId: this.uploadDataSignal().userId
4598
+ });
4599
+ console.log('✅ [FileInput] Floating file uploader opened successfully');
4600
+ }
4601
+ catch (error) {
4602
+ console.error('❌ [FileInput] Failed to open floating file uploader:', error);
4603
+ this.notificationService.error('❌ Failed to open file uploader', { duration: 0 });
4604
+ }
4605
+ }
4606
+ else {
4607
+ console.log('⚠️ [FileInput] No group ID yet - generating one and opening uploader');
4608
+ // Generate a new group ID and open the uploader
4609
+ this.fileManagerService.generateObjectId().subscribe({
4610
+ next: async (response) => {
4611
+ const newGroupId = response.data?.objectId;
4612
+ console.log('🆔 [FileInput] Generated new group ID for uploader:', newGroupId);
4613
+ this.groupId.set(newGroupId);
4614
+ // Use the dedicated floating file uploader service
4615
+ try {
4616
+ await this.floatingFileUploaderService.showWithGroupId(newGroupId, {
4617
+ allowedTypes: this.acceptSignal() ? this.acceptSignal().split(',') : undefined,
4618
+ multiple: this.multipleSignal(),
4619
+ autoUpload: this.autoUploadSignal(),
4620
+ userId: this.uploadDataSignal().userId
4621
+ });
4622
+ console.log('✅ [FileInput] Floating file uploader opened successfully');
4623
+ }
4624
+ catch (error) {
4625
+ console.error('❌ [FileInput] Failed to open floating file uploader:', error);
4626
+ this.notificationService.error('❌ Failed to open file uploader', { duration: 0 });
4627
+ }
4628
+ },
4629
+ error: (error) => {
4630
+ console.error('❌ [FileInput] Failed to generate group ID for uploader:', error);
4631
+ this.notificationService.error('❌ Failed to open file uploader', { duration: 0 });
4632
+ }
4633
+ });
4634
+ }
4128
4635
  }
4129
4636
  /**
4130
4637
  * Get dynamic classes for drag and drop zone
@@ -4971,6 +5478,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
4971
5478
  ], 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
5479
  }], ctorParameters: () => [] });
4973
5480
 
5481
+ var floatingFileUploader_component = /*#__PURE__*/Object.freeze({
5482
+ __proto__: null,
5483
+ CideEleFloatingFileUploaderComponent: CideEleFloatingFileUploaderComponent
5484
+ });
5485
+
4974
5486
  class CideTextareaComponent {
4975
5487
  label = '';
4976
5488
  labelHide = false;
@@ -9200,6 +9712,743 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
9200
9712
  type: Output
9201
9713
  }] } });
9202
9714
 
9715
+ class CideEleFloatingContainerComponent {
9716
+ config = signal({
9717
+ id: '',
9718
+ title: 'Floating Container',
9719
+ icon: 'widgets',
9720
+ headerColor: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
9721
+ width: '400px',
9722
+ height: 'auto',
9723
+ minWidth: '300px',
9724
+ minHeight: '200px',
9725
+ maxWidth: '90vw',
9726
+ maxHeight: '90vh',
9727
+ resizable: true,
9728
+ draggable: true,
9729
+ closable: true,
9730
+ minimizable: true,
9731
+ maximizable: true
9732
+ }, ...(ngDevMode ? [{ debugName: "config" }] : []));
9733
+ isMinimized;
9734
+ isMaximized;
9735
+ isVisible;
9736
+ closeEvent = new EventEmitter();
9737
+ minimizeEvent = new EventEmitter();
9738
+ maximizeEvent = new EventEmitter();
9739
+ containerRef;
9740
+ // State signals
9741
+ position = signal({ x: 100, y: 100 }, ...(ngDevMode ? [{ debugName: "position" }] : []));
9742
+ isDragging = signal(false, ...(ngDevMode ? [{ debugName: "isDragging" }] : []));
9743
+ isResizing = signal(false, ...(ngDevMode ? [{ debugName: "isResizing" }] : []));
9744
+ // Computed properties
9745
+ computedConfig = computed(() => this.config(), ...(ngDevMode ? [{ debugName: "computedConfig" }] : []));
9746
+ dragStart = { x: 0, y: 0 };
9747
+ resizeStart = { x: 0, y: 0, width: 0, height: 0 };
9748
+ originalPosition = { x: 0, y: 0 };
9749
+ originalSize = { width: 0, height: 0 };
9750
+ savedPosition = { x: 100, y: 100 }; // Store position before maximizing
9751
+ savedHeight = ''; // Store height before maximizing
9752
+ ngAfterViewInit() {
9753
+ // Center the container on screen
9754
+ this.centerContainer();
9755
+ }
9756
+ constructor() {
9757
+ // Watch for maximize state changes
9758
+ effect(() => {
9759
+ const isMaximized = this.isMaximized();
9760
+ if (isMaximized && !this.savedHeight) {
9761
+ // Save current height when maximizing
9762
+ this.savedHeight = this.containerRef?.nativeElement?.style.height || this.config().height || '500px';
9763
+ }
9764
+ else if (!isMaximized && this.savedHeight) {
9765
+ // Restore height when unmaximizing
9766
+ this.savedHeight = '';
9767
+ }
9768
+ });
9769
+ }
9770
+ ngOnDestroy() {
9771
+ // Clean up any event listeners if needed
9772
+ }
9773
+ centerContainer() {
9774
+ if (this.containerRef?.nativeElement) {
9775
+ if (this.isMaximized()) {
9776
+ // For maximized state, position with equal margins (20px from all sides)
9777
+ this.position.set({ x: 20, y: 20 });
9778
+ }
9779
+ else {
9780
+ // For normal state, center based on container size
9781
+ const rect = this.containerRef.nativeElement.getBoundingClientRect();
9782
+ const centerX = (window.innerWidth - rect.width) / 2;
9783
+ const centerY = (window.innerHeight - rect.height) / 2;
9784
+ this.position.set({ x: Math.max(0, centerX), y: Math.max(0, centerY) });
9785
+ }
9786
+ }
9787
+ }
9788
+ startDrag(event) {
9789
+ if (!this.computedConfig().draggable)
9790
+ return;
9791
+ event.preventDefault();
9792
+ event.stopPropagation();
9793
+ this.isDragging.set(true);
9794
+ this.dragStart = { x: event.clientX, y: event.clientY };
9795
+ this.originalPosition = { ...this.position() };
9796
+ document.addEventListener('mousemove', this.onDragMove.bind(this));
9797
+ document.addEventListener('mouseup', this.onDragEnd.bind(this));
9798
+ }
9799
+ onDragMove(event) {
9800
+ if (!this.isDragging())
9801
+ return;
9802
+ const deltaX = event.clientX - this.dragStart.x;
9803
+ const deltaY = event.clientY - this.dragStart.y;
9804
+ const newX = Math.max(0, Math.min(window.innerWidth - 300, this.originalPosition.x + deltaX));
9805
+ const newY = Math.max(0, Math.min(window.innerHeight - 100, this.originalPosition.y + deltaY));
9806
+ this.position.set({ x: newX, y: newY });
9807
+ }
9808
+ onDragEnd() {
9809
+ this.isDragging.set(false);
9810
+ document.removeEventListener('mousemove', this.onDragMove.bind(this));
9811
+ document.removeEventListener('mouseup', this.onDragEnd.bind(this));
9812
+ }
9813
+ startResize(event) {
9814
+ if (!this.computedConfig().resizable)
9815
+ return;
9816
+ event.preventDefault();
9817
+ event.stopPropagation();
9818
+ this.isResizing.set(true);
9819
+ this.resizeStart = {
9820
+ x: event.clientX,
9821
+ y: event.clientY,
9822
+ width: this.containerRef.nativeElement.offsetWidth,
9823
+ height: this.containerRef.nativeElement.offsetHeight
9824
+ };
9825
+ this.originalSize = { ...this.resizeStart };
9826
+ document.addEventListener('mousemove', this.onResizeMove.bind(this));
9827
+ document.addEventListener('mouseup', this.onResizeEnd.bind(this));
9828
+ }
9829
+ onResizeMove(event) {
9830
+ if (!this.isResizing())
9831
+ return;
9832
+ const deltaX = event.clientX - this.resizeStart.x;
9833
+ const deltaY = event.clientY - this.resizeStart.y;
9834
+ const newWidth = Math.max(300, this.originalSize.width + deltaX);
9835
+ const newHeight = Math.max(200, this.originalSize.height + deltaY);
9836
+ this.containerRef.nativeElement.style.width = `${newWidth}px`;
9837
+ this.containerRef.nativeElement.style.height = `${newHeight}px`;
9838
+ }
9839
+ onResizeEnd() {
9840
+ this.isResizing.set(false);
9841
+ document.removeEventListener('mousemove', this.onResizeMove.bind(this));
9842
+ document.removeEventListener('mouseup', this.onResizeEnd.bind(this));
9843
+ }
9844
+ // Mouse event handlers for container
9845
+ onMouseDown(event) {
9846
+ // Prevent text selection during drag
9847
+ event.preventDefault();
9848
+ }
9849
+ onMouseMove(event) {
9850
+ // Handle any additional mouse move logic if needed
9851
+ }
9852
+ onMouseUp(event) {
9853
+ // Handle any additional mouse up logic if needed
9854
+ }
9855
+ // Action methods
9856
+ onHeaderClick(event) {
9857
+ // Only minimize if clicking on the header itself, not on buttons
9858
+ if (this.isMinimized() && !event.target.closest('button')) {
9859
+ this.minimize();
9860
+ }
9861
+ }
9862
+ minimize() {
9863
+ this.minimizeEvent.emit(this.computedConfig().id);
9864
+ }
9865
+ toggleMaximize() {
9866
+ this.maximizeEvent.emit(this.computedConfig().id);
9867
+ }
9868
+ close() {
9869
+ this.closeEvent.emit(this.computedConfig().id);
9870
+ }
9871
+ getHeaderBackground() {
9872
+ return 'linear-gradient(135deg, var(--cide-theme-primary-color) 0%, var(--tw-blue-400) 100%)';
9873
+ }
9874
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
9875
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideEleFloatingContainerComponent, isStandalone: true, selector: "cide-ele-floating-container", inputs: { config: "config", isMinimized: "isMinimized", isMaximized: "isMaximized", isVisible: "isVisible" }, outputs: { closeEvent: "closeEvent", minimizeEvent: "minimizeEvent", maximizeEvent: "maximizeEvent" }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: `
9876
+ <div
9877
+ #container
9878
+ 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"
9879
+ [style.left.px]="isMaximized() ? 20 : position().x"
9880
+ [style.top.px]="isMaximized() ? 20 : position().y"
9881
+ [style.width]="isMaximized() ? 'calc(100vw - 40px)' : (config().width || '400px')"
9882
+ [style.height]="isMaximized() ? 'calc(100vh - 40px)' : (isMinimized() ? 'auto' : (savedHeight || config().height || '500px'))"
9883
+ [style.min-width]="config().minWidth || '300px'"
9884
+ [style.min-height]="isMinimized() ? 'auto' : (config().minHeight || '200px')"
9885
+ [style.max-width]="config().maxWidth || '90vw'"
9886
+ [style.max-height]="config().maxHeight || '90vh'"
9887
+ [class.tw-cursor-move]="isDragging()"
9888
+ [class.tw-select-none]="true"
9889
+ (mousedown)="onMouseDown($event)"
9890
+ (mousemove)="onMouseMove($event)"
9891
+ (mouseup)="onMouseUp($event)"
9892
+ (mouseleave)="onMouseUp($event)">
9893
+
9894
+ <!-- Header -->
9895
+ <div
9896
+ 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"
9897
+ [style.background]="getHeaderBackground()"
9898
+ (mousedown)="startDrag($event)"
9899
+ (click)="onHeaderClick($event)">
9900
+
9901
+ <!-- Title Section -->
9902
+ <div class="tw-flex tw-items-center tw-space-x-2 tw-text-white">
9903
+ @if (config().icon) {
9904
+ <cide-ele-icon class="tw-w-4 tw-h-4">{{ config().icon }}</cide-ele-icon>
9905
+ }
9906
+ <h2 class="tw-text-sm tw-font-medium tw-truncate">{{ config().title }}</h2>
9907
+ @if (isMinimized()) {
9908
+ <span class="tw-text-xs tw-opacity-75">(Click to restore)</span>
9909
+ }
9910
+ </div>
9911
+
9912
+ <!-- Action Buttons -->
9913
+ <div class="tw-flex tw-items-center tw-space-x-1">
9914
+ @if (config().minimizable !== false) {
9915
+ <button
9916
+ cideEleButton
9917
+ variant="ghost"
9918
+ size="xs"
9919
+ type="button"
9920
+ (click)="minimize(); $event.stopPropagation()"
9921
+ 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"
9922
+ [title]="isMinimized() ? 'Restore' : 'Minimize'">
9923
+ <cide-ele-icon class="tw-w-3 tw-h-3">{{ isMinimized() ? 'open_in_full' : 'remove' }}</cide-ele-icon>
9924
+ </button>
9925
+ }
9926
+ @if (config().maximizable !== false) {
9927
+ <button
9928
+ cideEleButton
9929
+ variant="ghost"
9930
+ size="xs"
9931
+ type="button"
9932
+ (click)="toggleMaximize(); $event.stopPropagation()"
9933
+ 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"
9934
+ [title]="isMaximized() ? 'Restore' : 'Maximize'">
9935
+ <cide-ele-icon class="tw-w-3 tw-h-3">{{ isMaximized() ? 'fullscreen_exit' : 'fullscreen' }}</cide-ele-icon>
9936
+ </button>
9937
+ }
9938
+ @if (config().closable !== false) {
9939
+ <button
9940
+ cideEleButton
9941
+ variant="ghost"
9942
+ size="xs"
9943
+ type="button"
9944
+ (click)="close(); $event.stopPropagation()"
9945
+ 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"
9946
+ title="Close">
9947
+ <cide-ele-icon class="tw-w-3 tw-h-3">close</cide-ele-icon>
9948
+ </button>
9949
+ }
9950
+ </div>
9951
+ </div>
9952
+
9953
+ <!-- Content with @defer for performance -->
9954
+ @if (!isMinimized()) {
9955
+ <div
9956
+ class="tw-flex-1 tw-overflow-auto tw-overflow-x-hidden floating-container-content tw-bg-gray-50 tw-bg-opacity-90"
9957
+ [style.height]="isMaximized() ? 'calc(100vh - 100px)' : 'auto'"
9958
+ [style.min-height]="'200px'">
9959
+ @defer (when !isMinimized() && isVisible()) {
9960
+ <div class="tw-p-4 tw-min-h-full">
9961
+ <ng-content></ng-content>
9962
+ </div>
9963
+ } @placeholder {
9964
+ <div class="tw-flex tw-items-center tw-justify-center tw-p-4 tw-min-h-[200px]">
9965
+ <cide-ele-spinner size="sm"></cide-ele-spinner>
9966
+ <span class="tw-ml-2 tw-text-sm tw-text-gray-600">Loading content...</span>
9967
+ </div>
9968
+ }
9969
+ </div>
9970
+ }
9971
+
9972
+ <!-- Resize Handle (if resizable) -->
9973
+ @if (config().resizable !== false) {
9974
+ <div
9975
+ 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"
9976
+ (mousedown)="startResize($event)">
9977
+ </div>
9978
+ }
9979
+ </div>
9980
+ `, 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"] }] });
9981
+ }
9982
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingContainerComponent, decorators: [{
9983
+ type: Component,
9984
+ args: [{ selector: 'cide-ele-floating-container', standalone: true, imports: [CommonModule, CideEleButtonComponent, CideIconComponent, CideSpinnerComponent], template: `
9985
+ <div
9986
+ #container
9987
+ 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"
9988
+ [style.left.px]="isMaximized() ? 20 : position().x"
9989
+ [style.top.px]="isMaximized() ? 20 : position().y"
9990
+ [style.width]="isMaximized() ? 'calc(100vw - 40px)' : (config().width || '400px')"
9991
+ [style.height]="isMaximized() ? 'calc(100vh - 40px)' : (isMinimized() ? 'auto' : (savedHeight || config().height || '500px'))"
9992
+ [style.min-width]="config().minWidth || '300px'"
9993
+ [style.min-height]="isMinimized() ? 'auto' : (config().minHeight || '200px')"
9994
+ [style.max-width]="config().maxWidth || '90vw'"
9995
+ [style.max-height]="config().maxHeight || '90vh'"
9996
+ [class.tw-cursor-move]="isDragging()"
9997
+ [class.tw-select-none]="true"
9998
+ (mousedown)="onMouseDown($event)"
9999
+ (mousemove)="onMouseMove($event)"
10000
+ (mouseup)="onMouseUp($event)"
10001
+ (mouseleave)="onMouseUp($event)">
10002
+
10003
+ <!-- Header -->
10004
+ <div
10005
+ 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"
10006
+ [style.background]="getHeaderBackground()"
10007
+ (mousedown)="startDrag($event)"
10008
+ (click)="onHeaderClick($event)">
10009
+
10010
+ <!-- Title Section -->
10011
+ <div class="tw-flex tw-items-center tw-space-x-2 tw-text-white">
10012
+ @if (config().icon) {
10013
+ <cide-ele-icon class="tw-w-4 tw-h-4">{{ config().icon }}</cide-ele-icon>
10014
+ }
10015
+ <h2 class="tw-text-sm tw-font-medium tw-truncate">{{ config().title }}</h2>
10016
+ @if (isMinimized()) {
10017
+ <span class="tw-text-xs tw-opacity-75">(Click to restore)</span>
10018
+ }
10019
+ </div>
10020
+
10021
+ <!-- Action Buttons -->
10022
+ <div class="tw-flex tw-items-center tw-space-x-1">
10023
+ @if (config().minimizable !== false) {
10024
+ <button
10025
+ cideEleButton
10026
+ variant="ghost"
10027
+ size="xs"
10028
+ type="button"
10029
+ (click)="minimize(); $event.stopPropagation()"
10030
+ 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"
10031
+ [title]="isMinimized() ? 'Restore' : 'Minimize'">
10032
+ <cide-ele-icon class="tw-w-3 tw-h-3">{{ isMinimized() ? 'open_in_full' : 'remove' }}</cide-ele-icon>
10033
+ </button>
10034
+ }
10035
+ @if (config().maximizable !== false) {
10036
+ <button
10037
+ cideEleButton
10038
+ variant="ghost"
10039
+ size="xs"
10040
+ type="button"
10041
+ (click)="toggleMaximize(); $event.stopPropagation()"
10042
+ 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"
10043
+ [title]="isMaximized() ? 'Restore' : 'Maximize'">
10044
+ <cide-ele-icon class="tw-w-3 tw-h-3">{{ isMaximized() ? 'fullscreen_exit' : 'fullscreen' }}</cide-ele-icon>
10045
+ </button>
10046
+ }
10047
+ @if (config().closable !== false) {
10048
+ <button
10049
+ cideEleButton
10050
+ variant="ghost"
10051
+ size="xs"
10052
+ type="button"
10053
+ (click)="close(); $event.stopPropagation()"
10054
+ 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"
10055
+ title="Close">
10056
+ <cide-ele-icon class="tw-w-3 tw-h-3">close</cide-ele-icon>
10057
+ </button>
10058
+ }
10059
+ </div>
10060
+ </div>
10061
+
10062
+ <!-- Content with @defer for performance -->
10063
+ @if (!isMinimized()) {
10064
+ <div
10065
+ class="tw-flex-1 tw-overflow-auto tw-overflow-x-hidden floating-container-content tw-bg-gray-50 tw-bg-opacity-90"
10066
+ [style.height]="isMaximized() ? 'calc(100vh - 100px)' : 'auto'"
10067
+ [style.min-height]="'200px'">
10068
+ @defer (when !isMinimized() && isVisible()) {
10069
+ <div class="tw-p-4 tw-min-h-full">
10070
+ <ng-content></ng-content>
10071
+ </div>
10072
+ } @placeholder {
10073
+ <div class="tw-flex tw-items-center tw-justify-center tw-p-4 tw-min-h-[200px]">
10074
+ <cide-ele-spinner size="sm"></cide-ele-spinner>
10075
+ <span class="tw-ml-2 tw-text-sm tw-text-gray-600">Loading content...</span>
10076
+ </div>
10077
+ }
10078
+ </div>
10079
+ }
10080
+
10081
+ <!-- Resize Handle (if resizable) -->
10082
+ @if (config().resizable !== false) {
10083
+ <div
10084
+ 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"
10085
+ (mousedown)="startResize($event)">
10086
+ </div>
10087
+ }
10088
+ </div>
10089
+ `, 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"] }]
10090
+ }], ctorParameters: () => [], propDecorators: { config: [{
10091
+ type: Input
10092
+ }], isMinimized: [{
10093
+ type: Input
10094
+ }], isMaximized: [{
10095
+ type: Input
10096
+ }], isVisible: [{
10097
+ type: Input
10098
+ }], closeEvent: [{
10099
+ type: Output
10100
+ }], minimizeEvent: [{
10101
+ type: Output
10102
+ }], maximizeEvent: [{
10103
+ type: Output
10104
+ }], containerRef: [{
10105
+ type: ViewChild,
10106
+ args: ['container']
10107
+ }] } });
10108
+
10109
+ class CideEleFloatingContainerManagerComponent {
10110
+ containerService = inject(CideEleFloatingContainerService);
10111
+ // Computed properties
10112
+ visibleContainers = computed(() => this.containerService.visibleContainers(), ...(ngDevMode ? [{ debugName: "visibleContainers" }] : []));
10113
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingContainerManagerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
10114
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideEleFloatingContainerManagerComponent, isStandalone: true, selector: "cide-ele-floating-container-manager", ngImport: i0, template: `
10115
+ @for (container of visibleContainers(); track container.id) {
10116
+ <cide-ele-floating-container
10117
+ [config]="containerService.getConfigSignal(container.config)"
10118
+ [isMinimized]="containerService.getMinimizedSignal(container.id)"
10119
+ [isMaximized]="containerService.getMaximizedSignal(container.id)"
10120
+ [isVisible]="containerService.getVisibleSignal(container.id)"
10121
+ [style.z-index]="container.zIndex"
10122
+ (closeEvent)="containerService.onClose($event)"
10123
+ (minimizeEvent)="containerService.onMinimize($event)"
10124
+ (maximizeEvent)="containerService.onMaximize($event)">
10125
+
10126
+ <!-- Dynamic content loading with @defer for performance -->
10127
+ @defer (when container.isVisible) {
10128
+ <div
10129
+ cideEleFloatingDynamic
10130
+ [componentId]="container.config.componentId || container.config.id"
10131
+ [componentConfig]="containerService.getComponentConfig(container.config)"
10132
+ [isVisible]="container.isVisible">
10133
+ </div>
10134
+ } @placeholder {
10135
+ <div class="tw-flex tw-items-center tw-justify-center tw-p-4">
10136
+ <cide-ele-spinner size="sm"></cide-ele-spinner>
10137
+ <span class="tw-ml-2 tw-text-sm tw-text-gray-600">Loading component...</span>
10138
+ </div>
10139
+ } @error {
10140
+ <div class="tw-flex tw-flex-col tw-items-center tw-justify-center tw-p-4 tw-text-center">
10141
+ <cide-ele-icon class="tw-w-8 tw-h-8 tw-text-red-500 tw-mb-2">error</cide-ele-icon>
10142
+ <p class="tw-text-red-600 tw-font-medium">Failed to load component</p>
10143
+ <p class="tw-text-gray-500 tw-text-sm">Component "{{ container.config.componentId || container.config.id }}" is not available</p>
10144
+ <button
10145
+ cideEleButton
10146
+ variant="outline"
10147
+ size="xs"
10148
+ (click)="containerService.onClose(container.id)"
10149
+ class="tw-mt-2">
10150
+ Close
10151
+ </button>
10152
+ </div>
10153
+ }
10154
+ </cide-ele-floating-container>
10155
+ }
10156
+ `, 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)]] });
10157
+ }
10158
+ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingContainerManagerComponent, resolveDeferredDeps: () => [Promise.resolve().then(function () { return floatingContainerDynamic_directive; }).then(m => m.CideEleFloatingContainerDynamicDirective)], resolveMetadata: CideEleFloatingContainerDynamicDirective => ({ decorators: [{
10159
+ type: Component,
10160
+ args: [{ selector: 'cide-ele-floating-container-manager', standalone: true, imports: [CommonModule, CideEleFloatingContainerComponent, CideEleFloatingContainerDynamicDirective, CideSpinnerComponent, CideEleButtonComponent, CideIconComponent], template: `
10161
+ @for (container of visibleContainers(); track container.id) {
10162
+ <cide-ele-floating-container
10163
+ [config]="containerService.getConfigSignal(container.config)"
10164
+ [isMinimized]="containerService.getMinimizedSignal(container.id)"
10165
+ [isMaximized]="containerService.getMaximizedSignal(container.id)"
10166
+ [isVisible]="containerService.getVisibleSignal(container.id)"
10167
+ [style.z-index]="container.zIndex"
10168
+ (closeEvent)="containerService.onClose($event)"
10169
+ (minimizeEvent)="containerService.onMinimize($event)"
10170
+ (maximizeEvent)="containerService.onMaximize($event)">
10171
+
10172
+ <!-- Dynamic content loading with @defer for performance -->
10173
+ @defer (when container.isVisible) {
10174
+ <div
10175
+ cideEleFloatingDynamic
10176
+ [componentId]="container.config.componentId || container.config.id"
10177
+ [componentConfig]="containerService.getComponentConfig(container.config)"
10178
+ [isVisible]="container.isVisible">
10179
+ </div>
10180
+ } @placeholder {
10181
+ <div class="tw-flex tw-items-center tw-justify-center tw-p-4">
10182
+ <cide-ele-spinner size="sm"></cide-ele-spinner>
10183
+ <span class="tw-ml-2 tw-text-sm tw-text-gray-600">Loading component...</span>
10184
+ </div>
10185
+ } @error {
10186
+ <div class="tw-flex tw-flex-col tw-items-center tw-justify-center tw-p-4 tw-text-center">
10187
+ <cide-ele-icon class="tw-w-8 tw-h-8 tw-text-red-500 tw-mb-2">error</cide-ele-icon>
10188
+ <p class="tw-text-red-600 tw-font-medium">Failed to load component</p>
10189
+ <p class="tw-text-gray-500 tw-text-sm">Component "{{ container.config.componentId || container.config.id }}" is not available</p>
10190
+ <button
10191
+ cideEleButton
10192
+ variant="outline"
10193
+ size="xs"
10194
+ (click)="containerService.onClose(container.id)"
10195
+ class="tw-mt-2">
10196
+ Close
10197
+ </button>
10198
+ </div>
10199
+ }
10200
+ </cide-ele-floating-container>
10201
+ }
10202
+ ` }]
10203
+ }], ctorParameters: null, propDecorators: null }) });
10204
+
10205
+ class CideEleFloatingFeaturesService {
10206
+ containerService = inject(CideEleFloatingContainerService);
10207
+ constructor() {
10208
+ // File uploader is handled by its own dedicated service
10209
+ // Entity rights sharing is handled by its own dedicated service
10210
+ }
10211
+ // Generic method to show any floating feature
10212
+ showFeature(featureId, config) {
10213
+ return this.containerService.show({ ...config, id: featureId });
10214
+ }
10215
+ // Generic method for showing any component dynamically
10216
+ showComponent(containerId, componentId, title, componentType, config = {}) {
10217
+ const containerConfig = {
10218
+ id: containerId,
10219
+ title,
10220
+ icon: 'widgets',
10221
+ width: '400px',
10222
+ height: '500px',
10223
+ minWidth: '300px',
10224
+ minHeight: '200px',
10225
+ resizable: true,
10226
+ draggable: true,
10227
+ closable: true,
10228
+ minimizable: true,
10229
+ maximizable: true,
10230
+ componentId,
10231
+ ...config
10232
+ };
10233
+ // Register component if provided
10234
+ if (componentType) {
10235
+ this.registerComponent(componentId, componentType);
10236
+ }
10237
+ return this.containerService.show(containerConfig);
10238
+ }
10239
+ /**
10240
+ * Generic method for showing any component with input data
10241
+ *
10242
+ * @example
10243
+ * // Pass data to a component
10244
+ * this.floatingFeaturesService.showComponentWithData(
10245
+ * 'my-component-container',
10246
+ * 'my-component',
10247
+ * 'My Component Title',
10248
+ * {
10249
+ * data: {
10250
+ * userId: '123',
10251
+ * userName: 'John Doe',
10252
+ * settings: { theme: 'dark' }
10253
+ * },
10254
+ * outputs: {
10255
+ * onSave: (data) => console.log('Save event:', data),
10256
+ * onCancel: () => console.log('Cancel clicked')
10257
+ * }
10258
+ * },
10259
+ * {
10260
+ * width: '600px',
10261
+ * height: '400px',
10262
+ * icon: 'settings'
10263
+ * }
10264
+ * );
10265
+ */
10266
+ showComponentWithData(containerId, componentId, title, componentData, containerConfig = {}) {
10267
+ const config = {
10268
+ id: containerId,
10269
+ title,
10270
+ icon: 'widgets',
10271
+ width: '400px',
10272
+ height: '500px',
10273
+ minWidth: '300px',
10274
+ minHeight: '200px',
10275
+ resizable: true,
10276
+ draggable: true,
10277
+ closable: true,
10278
+ minimizable: true,
10279
+ maximizable: true,
10280
+ componentId,
10281
+ componentConfig: {
10282
+ inputs: componentData.data,
10283
+ outputs: componentData.outputs || {}
10284
+ },
10285
+ ...containerConfig
10286
+ };
10287
+ return this.containerService.show(config);
10288
+ }
10289
+ // Show multiple instances of the same component
10290
+ showMultipleInstances(componentId, titlePrefix, count, config = {}) {
10291
+ const containerIds = [];
10292
+ for (let i = 1; i <= count; i++) {
10293
+ const containerId = `${componentId}-instance-${i}-${Date.now()}`;
10294
+ const title = `${titlePrefix} ${i}`;
10295
+ const containerConfig = {
10296
+ id: containerId,
10297
+ title,
10298
+ icon: 'widgets',
10299
+ width: '400px',
10300
+ height: '500px',
10301
+ minWidth: '300px',
10302
+ minHeight: '200px',
10303
+ resizable: true,
10304
+ draggable: true,
10305
+ closable: true,
10306
+ minimizable: true,
10307
+ maximizable: true,
10308
+ componentId,
10309
+ ...config
10310
+ };
10311
+ const id = this.containerService.show(containerConfig);
10312
+ containerIds.push(id);
10313
+ }
10314
+ return containerIds;
10315
+ }
10316
+ // Get all instances of a component type
10317
+ getInstancesOfType(componentType) {
10318
+ return this.containerService.getInstancesByComponentType(componentType);
10319
+ }
10320
+ // Get active instances of a component type
10321
+ getActiveInstancesOfType(componentType) {
10322
+ return this.containerService.getActiveInstancesByComponentType(componentType);
10323
+ }
10324
+ // Close all instances of a component type
10325
+ closeAllInstancesOfType(componentType) {
10326
+ this.containerService.closeAllInstancesOfType(componentType);
10327
+ }
10328
+ // Minimize all instances of a component type
10329
+ minimizeAllInstancesOfType(componentType) {
10330
+ this.containerService.minimizeAllInstancesOfType(componentType);
10331
+ }
10332
+ // Get instance count for a component type
10333
+ getInstanceCount(componentType) {
10334
+ return this.containerService.getInstanceCount(componentType);
10335
+ }
10336
+ // Get active instance count for a component type
10337
+ getActiveInstanceCount(componentType) {
10338
+ return this.containerService.getActiveInstanceCount(componentType);
10339
+ }
10340
+ // Register a component for dynamic loading
10341
+ registerComponent(componentId, componentType) {
10342
+ this.containerService.registerComponent(componentId, componentType);
10343
+ }
10344
+ // Unregister a component
10345
+ unregisterComponent(componentId) {
10346
+ this.containerService.unregisterComponent(componentId);
10347
+ }
10348
+ hideFeature(featureId) {
10349
+ this.containerService.hide(featureId);
10350
+ }
10351
+ // Utility methods
10352
+ bringToFront(featureId) {
10353
+ this.containerService.bringToFront(featureId);
10354
+ }
10355
+ minimize(featureId) {
10356
+ this.containerService.minimize(featureId);
10357
+ }
10358
+ maximize(featureId) {
10359
+ this.containerService.maximize(featureId);
10360
+ }
10361
+ isVisible(featureId) {
10362
+ return this.containerService.isVisible(featureId);
10363
+ }
10364
+ hideAll() {
10365
+ this.containerService.hideAll();
10366
+ }
10367
+ minimizeAll() {
10368
+ this.containerService.minimizeAll();
10369
+ }
10370
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingFeaturesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
10371
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingFeaturesService, providedIn: 'root' });
10372
+ }
10373
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingFeaturesService, decorators: [{
10374
+ type: Injectable,
10375
+ args: [{
10376
+ providedIn: 'root'
10377
+ }]
10378
+ }], ctorParameters: () => [] });
10379
+
10380
+ class CideEleFloatingContainerDynamicDirective {
10381
+ viewContainer;
10382
+ containerService;
10383
+ componentId;
10384
+ componentConfig;
10385
+ isVisible = true;
10386
+ componentRef = null;
10387
+ constructor(viewContainer, containerService) {
10388
+ this.viewContainer = viewContainer;
10389
+ this.containerService = containerService;
10390
+ }
10391
+ ngOnInit() {
10392
+ if (this.isVisible && this.componentId) {
10393
+ this.loadComponent();
10394
+ }
10395
+ }
10396
+ ngOnDestroy() {
10397
+ this.destroyComponent();
10398
+ }
10399
+ ngOnChanges() {
10400
+ if (this.isVisible && this.componentId && !this.componentRef) {
10401
+ this.loadComponent();
10402
+ }
10403
+ else if (!this.isVisible && this.componentRef) {
10404
+ this.destroyComponent();
10405
+ }
10406
+ }
10407
+ loadComponent() {
10408
+ if (this.componentId && this.containerService.isComponentRegistered(this.componentId)) {
10409
+ this.componentRef = this.containerService.loadComponent(this.componentId, this.viewContainer, this.componentConfig);
10410
+ }
10411
+ else {
10412
+ console.warn(`Component '${this.componentId}' is not registered. Available components:`, this.containerService.getRegisteredComponentIds());
10413
+ // Retry after a short delay in case registration is still in progress
10414
+ setTimeout(() => {
10415
+ if (this.containerService.isComponentRegistered(this.componentId)) {
10416
+ this.componentRef = this.containerService.loadComponent(this.componentId, this.viewContainer, this.componentConfig);
10417
+ }
10418
+ else {
10419
+ console.error(`Component '${this.componentId}' still not registered after retry`);
10420
+ }
10421
+ }, 100);
10422
+ }
10423
+ }
10424
+ destroyComponent() {
10425
+ if (this.componentRef) {
10426
+ this.componentRef.destroy();
10427
+ this.componentRef = null;
10428
+ }
10429
+ }
10430
+ 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 });
10431
+ 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 });
10432
+ }
10433
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideEleFloatingContainerDynamicDirective, decorators: [{
10434
+ type: Directive,
10435
+ args: [{
10436
+ selector: '[cideEleFloatingDynamic]',
10437
+ standalone: true
10438
+ }]
10439
+ }], ctorParameters: () => [{ type: i0.ViewContainerRef }, { type: CideEleFloatingContainerService }], propDecorators: { componentId: [{
10440
+ type: Input
10441
+ }], componentConfig: [{
10442
+ type: Input
10443
+ }], isVisible: [{
10444
+ type: Input
10445
+ }] } });
10446
+
10447
+ var floatingContainerDynamic_directive = /*#__PURE__*/Object.freeze({
10448
+ __proto__: null,
10449
+ CideEleFloatingContainerDynamicDirective: CideEleFloatingContainerDynamicDirective
10450
+ });
10451
+
9203
10452
  /*
9204
10453
  * Public API Surface of cloud-ide-element
9205
10454
  * Here we can add what need to be exported from library
@@ -9209,5 +10458,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
9209
10458
  * Generated bundle index. Do not edit.
9210
10459
  */
9211
10460
 
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 };
10461
+ export { CideCoreFileManagerService, CideEleButtonComponent, CideEleConfirmationModalComponent, CideEleDataGridComponent, CideEleDropdownComponent, CideEleFileImageDirective, CideEleFileInputComponent, CideEleFileManagerService, CideEleFloatingContainerComponent, CideEleFloatingContainerDynamicDirective, CideEleFloatingContainerManagerComponent, CideEleFloatingContainerService, CideEleFloatingFeaturesService, CideEleFloatingFileUploaderComponent, CideEleFloatingFileUploaderService, CideEleGlobalNotificationsComponent, CideEleJsonEditorComponent, CideEleResizerDirective, CideEleSkeletonLoaderComponent, CideEleTabComponent, CideEleToastNotificationComponent, CideElementsService, CideIconComponent, CideInputComponent, CideSelectComponent, CideSelectOptionComponent, CideSpinnerComponent, CideTextareaComponent, ConfirmationService, CoreFileManagerInsertUpdatePayload, DEFAULT_GRID_CONFIG, DropdownManagerService, ICoreCyfmSave, MFileManager, NotificationService, TooltipDirective };
9213
10462
  //# sourceMappingURL=cloud-ide-element.mjs.map