cloud-ide-layout 1.0.23 → 1.0.24

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, inject, signal, computed, effect, Component, ElementRef, HostListener, ViewContainerRef, ViewChild, ViewChildren, InjectionToken, PLATFORM_ID } from '@angular/core';
2
+ import { Injectable, inject, signal, computed, effect, Component, ElementRef, HostListener, ViewContainerRef, ViewChild, ViewChildren, InjectionToken, PLATFORM_ID, DestroyRef, Input, Directive } from '@angular/core';
3
3
  import { HttpClient } from '@angular/common/http';
4
4
  import { cidePath, hostManagerRoutesUrl, coreRoutesUrl, commonRoutesUrl, designConfigRoutesUrl } from 'cloud-ide-lms-model';
5
5
  import { Observable, throwError, of, BehaviorSubject, interval, take as take$1 } from 'rxjs';
@@ -13,6 +13,7 @@ import { CommonModule, NgClass, NgFor, NgIf, isPlatformBrowser } from '@angular/
13
13
  import { CloudIdeAuthService, authGuard } from 'cloud-ide-auth';
14
14
  import { trigger, state, transition, style, animate } from '@angular/animations';
15
15
  import { merge } from 'lodash';
16
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
16
17
 
17
18
  class CloudIdeLayoutService {
18
19
  constructor() { }
@@ -2651,8 +2652,8 @@ class CideLytSidedrawerWrapperComponent {
2651
2652
  }
2652
2653
  ngOnInit() {
2653
2654
  // Initialize the component map (You'd likely populate this from a config or service)
2654
- this.componentMap['drowar_notes'] = () => import('./cloud-ide-layout-sidedrawer-notes.component-B4p_uGox.mjs').then(m => m.CideLytSidedrawerNotesComponent);
2655
- this.componentMap['drawer_theme'] = () => import('./cloud-ide-layout-drawer-theme.component-B-VlqH0O.mjs').then(m => m.CideLytDrawerThemeComponent);
2655
+ this.componentMap['drowar_notes'] = () => import('./cloud-ide-layout-sidedrawer-notes.component-GT7A-85i.mjs').then(m => m.CideLytSidedrawerNotesComponent);
2656
+ this.componentMap['drawer_theme'] = () => import('./cloud-ide-layout-drawer-theme.component-B4u9LnTe.mjs').then(m => m.CideLytDrawerThemeComponent);
2656
2657
  }
2657
2658
  async loadComponent(configFor) {
2658
2659
  console.log('🔍 SIDEDRAWER - Loading component:', configFor, 'Current tab:', this.currentTabId);
@@ -3024,7 +3025,7 @@ const layoutControlPannelChildRoutes = [{
3024
3025
  },
3025
3026
  {
3026
3027
  path: "home",
3027
- loadComponent: () => import('./cloud-ide-layout-home-wrapper.component-DtB5EqE3.mjs').then(c => c.CideLytHomeWrapperComponent),
3028
+ loadComponent: () => import('./cloud-ide-layout-home-wrapper.component-DEec7PZk.mjs').then(c => c.CideLytHomeWrapperComponent),
3028
3029
  canActivate: [authGuard],
3029
3030
  data: {
3030
3031
  reuseTab: true, // For CustomRouteReuseStrategy
@@ -3281,6 +3282,550 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
3281
3282
  }]
3282
3283
  }] });
3283
3284
 
3285
+ class CideLytFloatingUploadService {
3286
+ destroyRef = inject(DestroyRef);
3287
+ // Private signals for state management
3288
+ _uploadQueue = signal([], ...(ngDevMode ? [{ debugName: "_uploadQueue" }] : []));
3289
+ _isUploading = signal(false, ...(ngDevMode ? [{ debugName: "_isUploading" }] : []));
3290
+ _uploadProgress = signal(0, ...(ngDevMode ? [{ debugName: "_uploadProgress" }] : []));
3291
+ _isVisible = signal(false, ...(ngDevMode ? [{ debugName: "_isVisible" }] : []));
3292
+ _currentUserId = signal('', ...(ngDevMode ? [{ debugName: "_currentUserId" }] : []));
3293
+ // Public readonly signals
3294
+ uploadQueue = this._uploadQueue.asReadonly();
3295
+ isUploading = this._isUploading.asReadonly();
3296
+ uploadProgress = this._uploadProgress.asReadonly();
3297
+ isVisible = this._isVisible.asReadonly();
3298
+ currentUserId = this._currentUserId.asReadonly();
3299
+ // Computed values
3300
+ hasUploads = computed(() => this._uploadQueue().length > 0, ...(ngDevMode ? [{ debugName: "hasUploads" }] : []));
3301
+ pendingUploads = computed(() => this._uploadQueue().filter(upload => upload.status === 'pending'), ...(ngDevMode ? [{ debugName: "pendingUploads" }] : []));
3302
+ activeUploads = computed(() => this._uploadQueue().filter(upload => upload.status === 'uploading'), ...(ngDevMode ? [{ debugName: "activeUploads" }] : []));
3303
+ completedUploads = computed(() => this._uploadQueue().filter(upload => upload.status === 'completed'), ...(ngDevMode ? [{ debugName: "completedUploads" }] : []));
3304
+ failedUploads = computed(() => this._uploadQueue().filter(upload => upload.status === 'error'), ...(ngDevMode ? [{ debugName: "failedUploads" }] : []));
3305
+ // BehaviorSubjects for external subscriptions
3306
+ uploadQueueSubject = new BehaviorSubject([]);
3307
+ isUploadingSubject = new BehaviorSubject(false);
3308
+ uploadProgressSubject = new BehaviorSubject(0);
3309
+ isVisibleSubject = new BehaviorSubject(false);
3310
+ currentUserIdSubject = new BehaviorSubject('');
3311
+ // Public observables
3312
+ uploadQueue$ = this.uploadQueueSubject.asObservable();
3313
+ isUploading$ = this.isUploadingSubject.asObservable();
3314
+ uploadProgress$ = this.uploadProgressSubject.asObservable();
3315
+ isVisible$ = this.isVisibleSubject.asObservable();
3316
+ currentUserId$ = this.currentUserIdSubject.asObservable();
3317
+ constructor() {
3318
+ console.log('🚀 [FloatingUploadService] Service initialized');
3319
+ }
3320
+ /**
3321
+ * Set the current user ID
3322
+ */
3323
+ setCurrentUserId(userId) {
3324
+ console.log('👤 [FloatingUploadService] Setting user ID:', userId);
3325
+ this._currentUserId.set(userId);
3326
+ this.currentUserIdSubject.next(userId);
3327
+ }
3328
+ /**
3329
+ * Add files to upload queue
3330
+ */
3331
+ addFilesToQueue(files) {
3332
+ console.log('📁 [FloatingUploadService] Adding files to queue:', files.length);
3333
+ const newUploads = files.map(file => ({
3334
+ fileId: this.generateFileId(),
3335
+ fileName: file.name,
3336
+ progress: 0,
3337
+ status: 'pending'
3338
+ }));
3339
+ const currentQueue = this._uploadQueue();
3340
+ const updatedQueue = [...currentQueue, ...newUploads];
3341
+ this._uploadQueue.set(updatedQueue);
3342
+ this.uploadQueueSubject.next(updatedQueue);
3343
+ this.updateVisibility();
3344
+ }
3345
+ /**
3346
+ * Update upload status
3347
+ */
3348
+ updateUploadStatus(fileId, status, progress, error, uploadedFile) {
3349
+ console.log('🔄 [FloatingUploadService] Updating upload status:', fileId, status, progress);
3350
+ const currentQueue = this._uploadQueue();
3351
+ const updatedQueue = currentQueue.map(upload => upload.fileId === fileId
3352
+ ? { ...upload, status, progress, error, uploadedFile }
3353
+ : upload);
3354
+ this._uploadQueue.set(updatedQueue);
3355
+ this.uploadQueueSubject.next(updatedQueue);
3356
+ this.updateUploadingState();
3357
+ this.updateVisibility();
3358
+ }
3359
+ /**
3360
+ * Cancel upload
3361
+ */
3362
+ cancelUpload(fileId) {
3363
+ console.log('🚫 [FloatingUploadService] Cancelling upload:', fileId);
3364
+ this.updateUploadStatus(fileId, 'cancelled', 0);
3365
+ }
3366
+ /**
3367
+ * Remove upload from queue
3368
+ */
3369
+ removeUpload(fileId) {
3370
+ console.log('🗑️ [FloatingUploadService] Removing upload:', fileId);
3371
+ const currentQueue = this._uploadQueue();
3372
+ const updatedQueue = currentQueue.filter(upload => upload.fileId !== fileId);
3373
+ this._uploadQueue.set(updatedQueue);
3374
+ this.uploadQueueSubject.next(updatedQueue);
3375
+ this.updateUploadingState();
3376
+ this.updateVisibility();
3377
+ }
3378
+ /**
3379
+ * Clear all uploads
3380
+ */
3381
+ clearAllUploads() {
3382
+ console.log('🧹 [FloatingUploadService] Clearing all uploads');
3383
+ this._uploadQueue.set([]);
3384
+ this.uploadQueueSubject.next([]);
3385
+ this._isUploading.set(false);
3386
+ this.isUploadingSubject.next(false);
3387
+ this._uploadProgress.set(0);
3388
+ this.uploadProgressSubject.next(0);
3389
+ this._isVisible.set(false);
3390
+ this.isVisibleSubject.next(false);
3391
+ }
3392
+ /**
3393
+ * Clear completed uploads
3394
+ */
3395
+ clearCompletedUploads() {
3396
+ console.log('✅ [FloatingUploadService] Clearing completed uploads');
3397
+ const currentQueue = this._uploadQueue();
3398
+ const updatedQueue = currentQueue.filter(upload => upload.status !== 'completed');
3399
+ this._uploadQueue.set(updatedQueue);
3400
+ this.uploadQueueSubject.next(updatedQueue);
3401
+ this.updateUploadingState();
3402
+ this.updateVisibility();
3403
+ }
3404
+ /**
3405
+ * Handle all uploads complete
3406
+ */
3407
+ handleAllUploadsComplete(event) {
3408
+ console.log('🎉 [FloatingUploadService] All uploads complete:', event);
3409
+ // Update all pending/uploading files to completed
3410
+ const currentQueue = this._uploadQueue();
3411
+ const updatedQueue = currentQueue.map(upload => {
3412
+ if (upload.status === 'pending' || upload.status === 'uploading') {
3413
+ return { ...upload, status: 'completed', progress: 100 };
3414
+ }
3415
+ return upload;
3416
+ });
3417
+ this._uploadQueue.set(updatedQueue);
3418
+ this.uploadQueueSubject.next(updatedQueue);
3419
+ this.updateUploadingState();
3420
+ }
3421
+ /**
3422
+ * Show the floating uploader
3423
+ */
3424
+ show() {
3425
+ console.log('👁️ [FloatingUploadService] Showing floating uploader');
3426
+ this._isVisible.set(true);
3427
+ this.isVisibleSubject.next(true);
3428
+ }
3429
+ /**
3430
+ * Hide the floating uploader
3431
+ */
3432
+ hide() {
3433
+ console.log('🙈 [FloatingUploadService] Hiding floating uploader');
3434
+ this._isVisible.set(false);
3435
+ this.isVisibleSubject.next(false);
3436
+ }
3437
+ /**
3438
+ * Update uploading state based on queue
3439
+ */
3440
+ updateUploadingState() {
3441
+ const activeUploads = this.activeUploads();
3442
+ const isUploading = activeUploads.length > 0;
3443
+ this._isUploading.set(isUploading);
3444
+ this.isUploadingSubject.next(isUploading);
3445
+ if (isUploading) {
3446
+ const totalProgress = activeUploads.reduce((sum, upload) => sum + upload.progress, 0);
3447
+ const averageProgress = Math.round(totalProgress / activeUploads.length);
3448
+ this._uploadProgress.set(averageProgress);
3449
+ this.uploadProgressSubject.next(averageProgress);
3450
+ }
3451
+ else {
3452
+ this._uploadProgress.set(0);
3453
+ this.uploadProgressSubject.next(0);
3454
+ }
3455
+ }
3456
+ /**
3457
+ * Update visibility based on upload state
3458
+ */
3459
+ updateVisibility() {
3460
+ const hasActiveUploads = this.activeUploads().length > 0;
3461
+ const hasPendingUploads = this.pendingUploads().length > 0;
3462
+ const hasCompletedUploads = this.completedUploads().length > 0;
3463
+ const hasFailedUploads = this.failedUploads().length > 0;
3464
+ // Show if there are active, pending, or recent completed/failed uploads
3465
+ const shouldShow = hasActiveUploads || hasPendingUploads || hasCompletedUploads || hasFailedUploads;
3466
+ if (shouldShow && !this._isVisible()) {
3467
+ this.show();
3468
+ }
3469
+ else if (!shouldShow && this._isVisible()) {
3470
+ this.hide();
3471
+ }
3472
+ }
3473
+ /**
3474
+ * Generate unique file ID
3475
+ */
3476
+ generateFileId() {
3477
+ return `upload_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
3478
+ }
3479
+ /**
3480
+ * Get upload by ID
3481
+ */
3482
+ getUploadById(fileId) {
3483
+ return this._uploadQueue().find(upload => upload.fileId === fileId);
3484
+ }
3485
+ /**
3486
+ * Get upload statistics
3487
+ */
3488
+ getUploadStats() {
3489
+ const queue = this._uploadQueue();
3490
+ return {
3491
+ total: queue.length,
3492
+ pending: queue.filter(u => u.status === 'pending').length,
3493
+ uploading: queue.filter(u => u.status === 'uploading').length,
3494
+ completed: queue.filter(u => u.status === 'completed').length,
3495
+ failed: queue.filter(u => u.status === 'error').length,
3496
+ cancelled: queue.filter(u => u.status === 'cancelled').length
3497
+ };
3498
+ }
3499
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytFloatingUploadService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3500
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytFloatingUploadService, providedIn: 'root' });
3501
+ }
3502
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytFloatingUploadService, decorators: [{
3503
+ type: Injectable,
3504
+ args: [{
3505
+ providedIn: 'root'
3506
+ }]
3507
+ }], ctorParameters: () => [] });
3508
+
3509
+ class CideLytFloatingFileUploaderComponent {
3510
+ destroyRef = inject(DestroyRef);
3511
+ floatingUploadService = inject(CideLytFloatingUploadService);
3512
+ // Signals for reactive state
3513
+ isVisible = signal(false, ...(ngDevMode ? [{ debugName: "isVisible" }] : []));
3514
+ isMinimized = signal(false, ...(ngDevMode ? [{ debugName: "isMinimized" }] : []));
3515
+ uploadQueue = signal([], ...(ngDevMode ? [{ debugName: "uploadQueue" }] : []));
3516
+ isUploading = signal(false, ...(ngDevMode ? [{ debugName: "isUploading" }] : []));
3517
+ uploadProgress = signal(0, ...(ngDevMode ? [{ debugName: "uploadProgress" }] : []));
3518
+ currentUserId = signal('', ...(ngDevMode ? [{ debugName: "currentUserId" }] : []));
3519
+ // Computed values
3520
+ hasUploads = computed(() => this.uploadQueue().length > 0, ...(ngDevMode ? [{ debugName: "hasUploads" }] : []));
3521
+ pendingUploads = computed(() => this.uploadQueue().filter(upload => upload.status === 'pending'), ...(ngDevMode ? [{ debugName: "pendingUploads" }] : []));
3522
+ activeUploads = computed(() => this.uploadQueue().filter(upload => upload.status === 'uploading'), ...(ngDevMode ? [{ debugName: "activeUploads" }] : []));
3523
+ completedUploads = computed(() => this.uploadQueue().filter(upload => upload.status === 'completed'), ...(ngDevMode ? [{ debugName: "completedUploads" }] : []));
3524
+ failedUploads = computed(() => this.uploadQueue().filter(upload => upload.status === 'error'), ...(ngDevMode ? [{ debugName: "failedUploads" }] : []));
3525
+ // Animation states
3526
+ isAnimating = signal(false, ...(ngDevMode ? [{ debugName: "isAnimating" }] : []));
3527
+ constructor() {
3528
+ console.log('🚀 [FloatingFileUploader] Component initialized');
3529
+ }
3530
+ ngOnInit() {
3531
+ // Subscribe to upload service state changes
3532
+ this.floatingUploadService.uploadQueue$
3533
+ .pipe(takeUntilDestroyed(this.destroyRef))
3534
+ .subscribe(queue => {
3535
+ this.uploadQueue.set(queue);
3536
+ this.updateVisibility();
3537
+ });
3538
+ this.floatingUploadService.isUploading$
3539
+ .pipe(takeUntilDestroyed(this.destroyRef))
3540
+ .subscribe(isUploading => {
3541
+ this.isUploading.set(isUploading);
3542
+ });
3543
+ this.floatingUploadService.uploadProgress$
3544
+ .pipe(takeUntilDestroyed(this.destroyRef))
3545
+ .subscribe(progress => {
3546
+ this.uploadProgress.set(progress);
3547
+ });
3548
+ this.floatingUploadService.isVisible$
3549
+ .pipe(takeUntilDestroyed(this.destroyRef))
3550
+ .subscribe(visible => {
3551
+ this.isVisible.set(visible);
3552
+ });
3553
+ this.floatingUploadService.currentUserId$
3554
+ .pipe(takeUntilDestroyed(this.destroyRef))
3555
+ .subscribe(userId => {
3556
+ this.currentUserId.set(userId);
3557
+ });
3558
+ }
3559
+ ngOnDestroy() {
3560
+ console.log('🧹 [FloatingFileUploader] Component destroyed');
3561
+ }
3562
+ /**
3563
+ * Update visibility based on upload state
3564
+ */
3565
+ updateVisibility() {
3566
+ const hasActiveUploads = this.activeUploads().length > 0;
3567
+ const hasPendingUploads = this.pendingUploads().length > 0;
3568
+ const hasCompletedUploads = this.completedUploads().length > 0;
3569
+ const hasFailedUploads = this.failedUploads().length > 0;
3570
+ // Show if there are active, pending, or recent completed/failed uploads
3571
+ const shouldShow = hasActiveUploads || hasPendingUploads || hasCompletedUploads || hasFailedUploads;
3572
+ if (shouldShow && !this.isVisible()) {
3573
+ this.showWithAnimation();
3574
+ }
3575
+ else if (!shouldShow && this.isVisible()) {
3576
+ this.hideWithAnimation();
3577
+ }
3578
+ }
3579
+ /**
3580
+ * Show with animation
3581
+ */
3582
+ showWithAnimation() {
3583
+ this.isAnimating.set(true);
3584
+ this.isVisible.set(true);
3585
+ // Remove animation class after animation completes
3586
+ setTimeout(() => {
3587
+ this.isAnimating.set(false);
3588
+ }, 300);
3589
+ }
3590
+ /**
3591
+ * Hide with animation
3592
+ */
3593
+ hideWithAnimation() {
3594
+ this.isAnimating.set(true);
3595
+ // Wait for animation to complete before hiding
3596
+ setTimeout(() => {
3597
+ this.isVisible.set(false);
3598
+ this.isAnimating.set(false);
3599
+ }, 300);
3600
+ }
3601
+ /**
3602
+ * Toggle minimize state
3603
+ */
3604
+ toggleMinimize() {
3605
+ this.isMinimized.set(!this.isMinimized());
3606
+ }
3607
+ /**
3608
+ * Close the floating uploader
3609
+ */
3610
+ close() {
3611
+ this.floatingUploadService.clearAllUploads();
3612
+ this.hideWithAnimation();
3613
+ }
3614
+ /**
3615
+ * Handle file upload completion
3616
+ */
3617
+ onUploadComplete(event) {
3618
+ console.log('✅ [FloatingFileUploader] Upload completed:', event);
3619
+ this.floatingUploadService.updateUploadStatus(event.fileId, 'completed', 100, undefined, event.uploadedFile);
3620
+ }
3621
+ /**
3622
+ * Handle upload error
3623
+ */
3624
+ onUploadError(event) {
3625
+ console.error('❌ [FloatingFileUploader] Upload error:', event);
3626
+ this.floatingUploadService.updateUploadStatus(event.fileId, 'error', 0, event.error);
3627
+ }
3628
+ /**
3629
+ * Handle upload cancellation
3630
+ */
3631
+ onUploadCancelled(fileId) {
3632
+ console.log('🚫 [FloatingFileUploader] Upload cancelled:', fileId);
3633
+ this.floatingUploadService.cancelUpload(fileId);
3634
+ }
3635
+ /**
3636
+ * Handle all uploads complete
3637
+ */
3638
+ onAllUploadsComplete(event) {
3639
+ console.log('🎉 [FloatingFileUploader] All uploads complete:', event);
3640
+ this.floatingUploadService.handleAllUploadsComplete(event);
3641
+ }
3642
+ /**
3643
+ * Get status icon
3644
+ */
3645
+ getStatusIcon(status) {
3646
+ switch (status) {
3647
+ case 'pending': return 'schedule';
3648
+ case 'uploading': return 'cloud_upload';
3649
+ case 'completed': return 'check_circle';
3650
+ case 'error': return 'error';
3651
+ case 'cancelled': return 'cancel';
3652
+ default: return 'help';
3653
+ }
3654
+ }
3655
+ /**
3656
+ * Get status class
3657
+ */
3658
+ getStatusClass(status) {
3659
+ switch (status) {
3660
+ case 'pending': return 'status-pending';
3661
+ case 'uploading': return 'status-uploading';
3662
+ case 'completed': return 'status-completed';
3663
+ case 'error': return 'status-error';
3664
+ case 'cancelled': return 'status-cancelled';
3665
+ default: return 'status-unknown';
3666
+ }
3667
+ }
3668
+ /**
3669
+ * Get file size display
3670
+ */
3671
+ getFileSizeDisplay(size) {
3672
+ if (size === 0)
3673
+ return '0 Bytes';
3674
+ const k = 1024;
3675
+ const sizes = ['Bytes', 'KB', 'MB', 'GB'];
3676
+ const i = Math.floor(Math.log(size) / Math.log(k));
3677
+ return parseFloat((size / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
3678
+ }
3679
+ /**
3680
+ * Get overall progress percentage
3681
+ */
3682
+ getOverallProgress() {
3683
+ const uploads = this.uploadQueue();
3684
+ if (uploads.length === 0)
3685
+ return 0;
3686
+ const totalProgress = uploads.reduce((sum, upload) => sum + upload.progress, 0);
3687
+ return Math.round(totalProgress / uploads.length);
3688
+ }
3689
+ /**
3690
+ * Get upload summary text
3691
+ */
3692
+ getUploadSummary() {
3693
+ const active = this.activeUploads().length;
3694
+ const completed = this.completedUploads().length;
3695
+ const failed = this.failedUploads().length;
3696
+ const pending = this.pendingUploads().length;
3697
+ if (active > 0) {
3698
+ return `${active} uploading`;
3699
+ }
3700
+ else if (completed > 0 && failed === 0) {
3701
+ return `${completed} completed`;
3702
+ }
3703
+ else if (failed > 0) {
3704
+ return `${completed} completed, ${failed} failed`;
3705
+ }
3706
+ else if (pending > 0) {
3707
+ return `${pending} pending`;
3708
+ }
3709
+ return 'No uploads';
3710
+ }
3711
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytFloatingFileUploaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3712
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: CideLytFloatingFileUploaderComponent, isStandalone: true, selector: "cide-layout-floating-file-uploader", ngImport: i0, template: "<!-- Floating File Uploader Container -->\n@if (isVisible()) {\n<div class=\"floating-uploader\" \n [class.minimized]=\"isMinimized()\" \n [class.animating]=\"isAnimating()\"\n [class.uploading]=\"isUploading()\">\n\n <!-- Header -->\n <div class=\"uploader-header\">\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 <!-- Overall Progress Bar -->\n @if (isUploading()) {\n <div class=\"overall-progress\">\n <div class=\"progress-bar\">\n <div class=\"progress-fill\" [style.width.%]=\"getOverallProgress()\"></div>\n </div>\n <div class=\"progress-text\">{{ getOverallProgress() }}%</div>\n </div>\n }\n\n <!-- Upload Queue -->\n @if (hasUploads()) {\n <div class=\"upload-queue\">\n @for (upload of uploadQueue(); track upload.fileId) {\n <div class=\"upload-item\" [class]=\"getStatusClass(upload.status)\">\n \n <!-- File Info -->\n <div class=\"file-info\">\n <cide-ele-icon class=\"status-icon\" size=\"xs\">{{ getStatusIcon(upload.status) }}</cide-ele-icon>\n <div class=\"file-details\">\n <div class=\"file-name\">{{ upload.fileName }}</div>\n <div class=\"file-status\">\n @switch (upload.status) {\n @case ('pending') {\n <span class=\"text-yellow-600\">Waiting...</span>\n }\n @case ('uploading') {\n <span class=\"text-blue-600\">Uploading...</span>\n }\n @case ('completed') {\n <span class=\"text-green-600\">Completed</span>\n }\n @case ('error') {\n <span class=\"text-red-600\">{{ upload.error || 'Failed' }}</span>\n }\n @case ('cancelled') {\n <span class=\"text-gray-600\">Cancelled</span>\n }\n }\n </div>\n </div>\n </div>\n\n <!-- Progress Bar (for uploading files) -->\n @if (upload.status === 'uploading') {\n <div class=\"file-progress\">\n <div class=\"progress-bar\">\n <div class=\"progress-fill\" [style.width.%]=\"upload.progress\"></div>\n </div>\n <span class=\"progress-text\">{{ upload.progress }}%</span>\n </div>\n }\n\n <!-- Actions -->\n <div class=\"upload-actions\">\n @switch (upload.status) {\n @case ('pending') {\n <button class=\"action-btn cancel-btn\" (click)=\"onUploadCancelled(upload.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)=\"onUploadCancelled(upload.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('completed') {\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 }\n\n <!-- Hidden file input for drag & drop -->\n <div class=\"hidden-uploader\">\n <input type=\"file\" multiple style=\"display: none;\" id=\"floating-file-input\">\n </div>\n </div>\n }\n\n <!-- Footer (always visible) -->\n <div class=\"uploader-footer\">\n <div class=\"footer-stats\">\n @if (activeUploads().length > 0) {\n <span class=\"stat uploading\">\n <cide-ele-icon size=\"xs\">cloud_upload</cide-ele-icon>\n {{ activeUploads().length }} uploading\n </span>\n }\n @if (completedUploads().length > 0) {\n <span class=\"stat completed\">\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\n {{ completedUploads().length }} completed\n </span>\n }\n @if (failedUploads().length > 0) {\n <span class=\"stat failed\">\n <cide-ele-icon size=\"xs\">error</cide-ele-icon>\n {{ failedUploads().length }} failed\n </span>\n }\n </div>\n </div>\n</div>\n}\n", styles: [".floating-uploader{position:fixed;bottom:20px;right:20px;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 .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 .overall-progress{padding:12px 16px;border-bottom:1px solid #e2e8f0}.floating-uploader .uploader-content .overall-progress .progress-bar{width:100%;height:4px;background:#e2e8f0;border-radius:2px;overflow:hidden;margin-bottom:4px}.floating-uploader .uploader-content .overall-progress .progress-bar .progress-fill{height:100%;background:#3b82f6;transition:width .3s ease}.floating-uploader .uploader-content .overall-progress .progress-text{font-size:12px;color:#64748b;text-align:center;display:block}.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 .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 .overall-progress{border-bottom-color:#475569}.floating-uploader .uploader-content .overall-progress .progress-bar{background:#475569}.floating-uploader .uploader-content .overall-progress .progress-bar .progress-fill{background:#3b82f6}.floating-uploader .uploader-content .overall-progress .progress-text{color:#94a3b8}.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)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }] });
3713
+ }
3714
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytFloatingFileUploaderComponent, decorators: [{
3715
+ type: Component,
3716
+ args: [{ selector: 'cide-layout-floating-file-uploader', standalone: true, imports: [
3717
+ CommonModule,
3718
+ CideIconComponent
3719
+ ], template: "<!-- Floating File Uploader Container -->\n@if (isVisible()) {\n<div class=\"floating-uploader\" \n [class.minimized]=\"isMinimized()\" \n [class.animating]=\"isAnimating()\"\n [class.uploading]=\"isUploading()\">\n\n <!-- Header -->\n <div class=\"uploader-header\">\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 <!-- Overall Progress Bar -->\n @if (isUploading()) {\n <div class=\"overall-progress\">\n <div class=\"progress-bar\">\n <div class=\"progress-fill\" [style.width.%]=\"getOverallProgress()\"></div>\n </div>\n <div class=\"progress-text\">{{ getOverallProgress() }}%</div>\n </div>\n }\n\n <!-- Upload Queue -->\n @if (hasUploads()) {\n <div class=\"upload-queue\">\n @for (upload of uploadQueue(); track upload.fileId) {\n <div class=\"upload-item\" [class]=\"getStatusClass(upload.status)\">\n \n <!-- File Info -->\n <div class=\"file-info\">\n <cide-ele-icon class=\"status-icon\" size=\"xs\">{{ getStatusIcon(upload.status) }}</cide-ele-icon>\n <div class=\"file-details\">\n <div class=\"file-name\">{{ upload.fileName }}</div>\n <div class=\"file-status\">\n @switch (upload.status) {\n @case ('pending') {\n <span class=\"text-yellow-600\">Waiting...</span>\n }\n @case ('uploading') {\n <span class=\"text-blue-600\">Uploading...</span>\n }\n @case ('completed') {\n <span class=\"text-green-600\">Completed</span>\n }\n @case ('error') {\n <span class=\"text-red-600\">{{ upload.error || 'Failed' }}</span>\n }\n @case ('cancelled') {\n <span class=\"text-gray-600\">Cancelled</span>\n }\n }\n </div>\n </div>\n </div>\n\n <!-- Progress Bar (for uploading files) -->\n @if (upload.status === 'uploading') {\n <div class=\"file-progress\">\n <div class=\"progress-bar\">\n <div class=\"progress-fill\" [style.width.%]=\"upload.progress\"></div>\n </div>\n <span class=\"progress-text\">{{ upload.progress }}%</span>\n </div>\n }\n\n <!-- Actions -->\n <div class=\"upload-actions\">\n @switch (upload.status) {\n @case ('pending') {\n <button class=\"action-btn cancel-btn\" (click)=\"onUploadCancelled(upload.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)=\"onUploadCancelled(upload.fileId)\" title=\"Cancel\">\n <cide-ele-icon size=\"xs\">cancel</cide-ele-icon>\n </button>\n }\n @case ('completed') {\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 }\n\n <!-- Hidden file input for drag & drop -->\n <div class=\"hidden-uploader\">\n <input type=\"file\" multiple style=\"display: none;\" id=\"floating-file-input\">\n </div>\n </div>\n }\n\n <!-- Footer (always visible) -->\n <div class=\"uploader-footer\">\n <div class=\"footer-stats\">\n @if (activeUploads().length > 0) {\n <span class=\"stat uploading\">\n <cide-ele-icon size=\"xs\">cloud_upload</cide-ele-icon>\n {{ activeUploads().length }} uploading\n </span>\n }\n @if (completedUploads().length > 0) {\n <span class=\"stat completed\">\n <cide-ele-icon size=\"xs\">check_circle</cide-ele-icon>\n {{ completedUploads().length }} completed\n </span>\n }\n @if (failedUploads().length > 0) {\n <span class=\"stat failed\">\n <cide-ele-icon size=\"xs\">error</cide-ele-icon>\n {{ failedUploads().length }} failed\n </span>\n }\n </div>\n </div>\n</div>\n}\n", styles: [".floating-uploader{position:fixed;bottom:20px;right:20px;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 .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 .overall-progress{padding:12px 16px;border-bottom:1px solid #e2e8f0}.floating-uploader .uploader-content .overall-progress .progress-bar{width:100%;height:4px;background:#e2e8f0;border-radius:2px;overflow:hidden;margin-bottom:4px}.floating-uploader .uploader-content .overall-progress .progress-bar .progress-fill{height:100%;background:#3b82f6;transition:width .3s ease}.floating-uploader .uploader-content .overall-progress .progress-text{font-size:12px;color:#64748b;text-align:center;display:block}.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 .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 .overall-progress{border-bottom-color:#475569}.floating-uploader .uploader-content .overall-progress .progress-bar{background:#475569}.floating-uploader .uploader-content .overall-progress .progress-bar .progress-fill{background:#3b82f6}.floating-uploader .uploader-content .overall-progress .progress-text{color:#94a3b8}.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)}\n"] }]
3720
+ }], ctorParameters: () => [] });
3721
+
3722
+ class CideLytLayoutWithFloatingUploaderComponent {
3723
+ destroyRef = inject(DestroyRef);
3724
+ floatingUploadService = inject(CideLytFloatingUploadService);
3725
+ // Signals for reactive state
3726
+ isVisible = signal(false, ...(ngDevMode ? [{ debugName: "isVisible" }] : []));
3727
+ uploadCount = signal(0, ...(ngDevMode ? [{ debugName: "uploadCount" }] : []));
3728
+ // Computed values
3729
+ hasUploads = computed(() => this.uploadCount() > 0, ...(ngDevMode ? [{ debugName: "hasUploads" }] : []));
3730
+ constructor() {
3731
+ console.log('🚀 [LayoutWithFloatingUploader] Component initialized');
3732
+ }
3733
+ ngOnInit() {
3734
+ // Subscribe to floating upload service state
3735
+ this.floatingUploadService.isVisible$
3736
+ .pipe(takeUntilDestroyed(this.destroyRef))
3737
+ .subscribe(visible => {
3738
+ this.isVisible.set(visible);
3739
+ });
3740
+ this.floatingUploadService.uploadQueue$
3741
+ .pipe(takeUntilDestroyed(this.destroyRef))
3742
+ .subscribe(queue => {
3743
+ this.uploadCount.set(queue.length);
3744
+ });
3745
+ }
3746
+ ngOnDestroy() {
3747
+ console.log('🧹 [LayoutWithFloatingUploader] Component destroyed');
3748
+ }
3749
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytLayoutWithFloatingUploaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3750
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.7", type: CideLytLayoutWithFloatingUploaderComponent, isStandalone: true, selector: "cide-layout-with-floating-uploader", ngImport: i0, template: "<!-- Layout with Floating Uploader -->\r\n<div class=\"layout-container\">\r\n <!-- Main Content Slot -->\r\n <ng-content></ng-content>\r\n \r\n <!-- Floating File Uploader -->\r\n <cide-layout-floating-file-uploader></cide-layout-floating-file-uploader>\r\n</div>\r\n\r\n", styles: [".layout-container{position:relative;width:100%;height:100%;min-height:100vh}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: CideLytFloatingFileUploaderComponent, selector: "cide-layout-floating-file-uploader" }] });
3751
+ }
3752
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytLayoutWithFloatingUploaderComponent, decorators: [{
3753
+ type: Component,
3754
+ args: [{ selector: 'cide-layout-with-floating-uploader', standalone: true, imports: [
3755
+ CommonModule,
3756
+ CideLytFloatingFileUploaderComponent
3757
+ ], template: "<!-- Layout with Floating Uploader -->\r\n<div class=\"layout-container\">\r\n <!-- Main Content Slot -->\r\n <ng-content></ng-content>\r\n \r\n <!-- Floating File Uploader -->\r\n <cide-layout-floating-file-uploader></cide-layout-floating-file-uploader>\r\n</div>\r\n\r\n", styles: [".layout-container{position:relative;width:100%;height:100%;min-height:100vh}\n"] }]
3758
+ }], ctorParameters: () => [] });
3759
+
3760
+ class CideLytFloatingUploadTriggerDirective {
3761
+ elementRef = inject(ElementRef);
3762
+ floatingUploadService = inject(CideLytFloatingUploadService);
3763
+ userId = '';
3764
+ constructor() {
3765
+ console.log('🎯 [FloatingUploadTrigger] Directive initialized');
3766
+ }
3767
+ onFileChange(event) {
3768
+ const input = event.target;
3769
+ const files = input.files;
3770
+ if (files && files.length > 0) {
3771
+ console.log('📁 [FloatingUploadTrigger] Files selected:', files.length);
3772
+ // Set user ID if provided
3773
+ if (this.userId) {
3774
+ this.floatingUploadService.setCurrentUserId(this.userId);
3775
+ }
3776
+ // Add files to floating uploader queue
3777
+ this.floatingUploadService.addFilesToQueue(Array.from(files));
3778
+ // Reset the input to allow selecting the same files again
3779
+ input.value = '';
3780
+ }
3781
+ }
3782
+ onDragOver(event) {
3783
+ event.preventDefault();
3784
+ event.stopPropagation();
3785
+ }
3786
+ onDragEnter(event) {
3787
+ event.preventDefault();
3788
+ event.stopPropagation();
3789
+ }
3790
+ onDrop(event) {
3791
+ event.preventDefault();
3792
+ event.stopPropagation();
3793
+ const files = event.dataTransfer?.files;
3794
+ if (files && files.length > 0) {
3795
+ console.log('📁 [FloatingUploadTrigger] Files dropped:', files.length);
3796
+ // Set user ID if provided
3797
+ if (this.userId) {
3798
+ this.floatingUploadService.setCurrentUserId(this.userId);
3799
+ }
3800
+ // Add files to floating uploader queue
3801
+ this.floatingUploadService.addFilesToQueue(Array.from(files));
3802
+ }
3803
+ }
3804
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytFloatingUploadTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
3805
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.1.7", type: CideLytFloatingUploadTriggerDirective, isStandalone: true, selector: "[cideFloatingUploadTrigger]", inputs: { userId: "userId" }, host: { listeners: { "change": "onFileChange($event)", "dragover": "onDragOver($event)", "dragenter": "onDragEnter($event)", "drop": "onDrop($event)" } }, ngImport: i0 });
3806
+ }
3807
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytFloatingUploadTriggerDirective, decorators: [{
3808
+ type: Directive,
3809
+ args: [{
3810
+ selector: '[cideFloatingUploadTrigger]',
3811
+ standalone: true
3812
+ }]
3813
+ }], ctorParameters: () => [], propDecorators: { userId: [{
3814
+ type: Input
3815
+ }], onFileChange: [{
3816
+ type: HostListener,
3817
+ args: ['change', ['$event']]
3818
+ }], onDragOver: [{
3819
+ type: HostListener,
3820
+ args: ['dragover', ['$event']]
3821
+ }], onDragEnter: [{
3822
+ type: HostListener,
3823
+ args: ['dragenter', ['$event']]
3824
+ }], onDrop: [{
3825
+ type: HostListener,
3826
+ args: ['drop', ['$event']]
3827
+ }] } });
3828
+
3284
3829
  /*
3285
3830
  * Public API Surface of cloud-ide-layout
3286
3831
  */
@@ -3289,5 +3834,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
3289
3834
  * Generated bundle index. Do not edit.
3290
3835
  */
3291
3836
 
3292
- export { AppStateHelperService as A, CideLytSharedWrapperComponent as C, ENVIRONMENT_CONFIG as E, CideLytSidebarService as a, CideLytRequestService as b, CideLytSidedrawerService as c, CideLytThemeService as d, CloudIdeLayoutService as e, CloudIdeLayoutComponent as f, CideLytSharedService as g, layoutControlPannelChildRoutes as h, CustomRouteReuseStrategy as i, AppStateService as j, CideLytUserStatusService as k, layoutRoutes as l, CacheManagerService as m, CideLytFileManagerService as n, processThemeVariable as p, setCSSVariable as s, themeFactory as t };
3293
- //# sourceMappingURL=cloud-ide-layout-cloud-ide-layout-urOTUFvE.mjs.map
3837
+ export { AppStateHelperService as A, CideLytSharedWrapperComponent as C, ENVIRONMENT_CONFIG as E, CideLytSidebarService as a, CideLytRequestService as b, CideLytSidedrawerService as c, CideLytThemeService as d, CloudIdeLayoutService as e, CloudIdeLayoutComponent as f, CideLytSharedService as g, layoutControlPannelChildRoutes as h, CustomRouteReuseStrategy as i, AppStateService as j, CideLytUserStatusService as k, layoutRoutes as l, CacheManagerService as m, CideLytFileManagerService as n, CideLytFloatingFileUploaderComponent as o, processThemeVariable as p, CideLytLayoutWithFloatingUploaderComponent as q, CideLytFloatingUploadService as r, setCSSVariable as s, themeFactory as t, CideLytFloatingUploadTriggerDirective as u };
3838
+ //# sourceMappingURL=cloud-ide-layout-cloud-ide-layout-RD9NYgsO.mjs.map