cloud-ide-layout 1.0.22 → 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,18 +1,19 @@
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
- import { cidePath, hostManagerRoutesUrl, coreRoutesUrl, designConfigRoutesUrl } from 'cloud-ide-lms-model';
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';
6
6
  import { map, filter, tap, catchError, shareReplay, take, distinctUntilChanged } from 'rxjs/operators';
7
7
  import * as i2 from '@angular/router';
8
8
  import { Router, NavigationEnd, RouteReuseStrategy, RouterModule } from '@angular/router';
9
9
  import { Title } from '@angular/platform-browser';
10
- import { CideEleFileManagerService, CideElementsService, CideInputComponent, CideIconComponent, CideEleResizerDirective, TooltipDirective, CideSpinnerComponent, CideEleSkeletonLoaderComponent } from 'cloud-ide-element';
10
+ import { CideEleFileManagerService, CideElementsService, CideInputComponent, CideIconComponent, CideEleDropdownComponent, CideEleResizerDirective, TooltipDirective, CideSpinnerComponent, CideEleSkeletonLoaderComponent } from 'cloud-ide-element';
11
11
  import * as i1 from '@angular/common';
12
12
  import { CommonModule, NgClass, NgFor, NgIf, isPlatformBrowser } from '@angular/common';
13
+ import { CloudIdeAuthService, authGuard } from 'cloud-ide-auth';
13
14
  import { trigger, state, transition, style, animate } from '@angular/animations';
14
15
  import { merge } from 'lodash';
15
- import { authGuard } from 'cloud-ide-auth';
16
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
16
17
 
17
18
  class CloudIdeLayoutService {
18
19
  constructor() { }
@@ -288,6 +289,7 @@ class AppStateService {
288
289
  constructor() {
289
290
  // Initialize file manager base URL on app startup
290
291
  this.fileManagerService.setBaseUrl(cidePath.join([hostManagerRoutesUrl.cideSuiteHost, coreRoutesUrl?.module, coreRoutesUrl?.fileManager]));
292
+ this.fileManagerService.setObjectIdEndpoint(cidePath.join([hostManagerRoutesUrl.cideSuiteHost, commonRoutesUrl?.module, commonRoutesUrl?.generateObjectId]));
291
293
  // Load initial state from localStorage
292
294
  this.loadFromLocalStorage();
293
295
  // Save to localStorage whenever state changes
@@ -1282,9 +1284,45 @@ class CideLytHeaderWrapperComponent extends CideLytSharedWrapperComponent {
1282
1284
  sypg_page_code: "cide_lyt_header"
1283
1285
  };
1284
1286
  syen_photo = {};
1287
+ // More Options Dropdown Configuration
1288
+ moreOptionsItems = [
1289
+ {
1290
+ id: 'settings',
1291
+ label: 'Settings',
1292
+ icon: 'settings',
1293
+ iconColor: 'tw-text-gray-500'
1294
+ },
1295
+ {
1296
+ id: 'help',
1297
+ label: 'Help & Support',
1298
+ icon: 'help',
1299
+ iconColor: 'tw-text-gray-500'
1300
+ },
1301
+ {
1302
+ id: 'divider',
1303
+ label: '',
1304
+ divider: true
1305
+ },
1306
+ {
1307
+ id: 'logout',
1308
+ label: 'Logout',
1309
+ icon: 'logout',
1310
+ iconColor: 'tw-text-red-500',
1311
+ textColor: 'tw-text-red-600',
1312
+ hoverBgColor: 'hover:tw-bg-red-50'
1313
+ }
1314
+ ];
1315
+ moreOptionsConfig = {
1316
+ triggerIcon: 'more_vert',
1317
+ triggerSize: 'sm',
1318
+ menuPosition: 'auto',
1319
+ menuWidth: 'tw-w-48',
1320
+ usePortal: true
1321
+ };
1285
1322
  headerService = inject(CideLytHeaderService);
1286
1323
  fileManagerService = inject(CideLytFileManagerService);
1287
1324
  router = inject(Router);
1325
+ authService = inject(CloudIdeAuthService);
1288
1326
  constructor() {
1289
1327
  super();
1290
1328
  }
@@ -1345,12 +1383,82 @@ class CideLytHeaderWrapperComponent extends CideLytSharedWrapperComponent {
1345
1383
  }
1346
1384
  }
1347
1385
  }
1386
+ /**
1387
+ * Handle more options dropdown item clicks
1388
+ * @param item The clicked dropdown item
1389
+ */
1390
+ onMoreOptionsClick(item) {
1391
+ console.log('🔍 [HeaderComponent] More options clicked:', item);
1392
+ switch (item.id) {
1393
+ case 'settings':
1394
+ this.navigateToSettings();
1395
+ break;
1396
+ case 'help':
1397
+ this.navigateToHelp();
1398
+ break;
1399
+ case 'logout':
1400
+ this.handleLogout();
1401
+ break;
1402
+ default:
1403
+ console.log('🔍 [HeaderComponent] Unknown option:', item.id);
1404
+ }
1405
+ }
1406
+ /**
1407
+ * Navigate to settings page
1408
+ */
1409
+ navigateToSettings() {
1410
+ console.log('🔍 [HeaderComponent] Navigating to settings...');
1411
+ // TODO: Implement settings navigation
1412
+ // this.router.navigate(['/settings']);
1413
+ }
1414
+ /**
1415
+ * Navigate to help and support page
1416
+ */
1417
+ navigateToHelp() {
1418
+ console.log('🔍 [HeaderComponent] Navigating to help...');
1419
+ // TODO: Implement help navigation
1420
+ // this.router.navigate(['/help']);
1421
+ }
1422
+ /**
1423
+ * Handle user logout
1424
+ * Uses the auth service to sign out and navigate to login page
1425
+ */
1426
+ handleLogout() {
1427
+ console.log('🔍 [HeaderComponent] Logging out user...');
1428
+ // Show confirmation dialog
1429
+ if (confirm('Are you sure you want to logout?')) {
1430
+ try {
1431
+ // Use the auth service to sign out
1432
+ this.authService.signOut();
1433
+ // Navigate to login page
1434
+ this.router.navigate(['/auth/sign-in']).then(success => {
1435
+ if (success) {
1436
+ console.log('✅ [HeaderComponent] Successfully logged out and navigated to login page');
1437
+ }
1438
+ else {
1439
+ console.error('❌ [HeaderComponent] Failed to navigate to login page');
1440
+ // Fallback: reload the page to force navigation
1441
+ window.location.href = '/auth/sign-in';
1442
+ }
1443
+ }).catch(error => {
1444
+ console.error('❌ [HeaderComponent] Navigation error:', error);
1445
+ // Fallback: reload the page to force navigation
1446
+ window.location.href = '/auth/sign-in';
1447
+ });
1448
+ }
1449
+ catch (error) {
1450
+ console.error('❌ [HeaderComponent] Logout error:', error);
1451
+ // Still try to navigate to login page even if logout fails
1452
+ this.router.navigate(['/auth/sign-in']);
1453
+ }
1454
+ }
1455
+ }
1348
1456
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytHeaderWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1349
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.7", type: CideLytHeaderWrapperComponent, isStandalone: true, selector: "cide-lyt-header-wrapper", usesInheritance: true, ngImport: i0, template: "<header id=\"cide-lyt-header-wrapper\" class=\"cide-lyt-header tw-w-full tw-select-none cide-lyt-header-wrapper-hide\">\n <!-- Logo Section -->\n <div class=\"header-logo-container tw-cursor-pointer\" \n (click)=\"onLogoClick()\" \n (keydown.enter)=\"onLogoClick()\" \n (keydown.space)=\"onLogoClick()\"\n tabindex=\"0\" \n role=\"button\"\n aria-label=\"Navigate to home\"\n title=\"Click to go to control panel home\">\n <img [src]=\"'data:image/png;base64,' + syen_photo.cyfm_file_base64\"\n [alt]=\"syen_photo.cyfm_alt_text ? syen_photo.cyfm_alt_text : 'Entity Logo'\">\n </div>\n <!-- Search Section -->\n <div class=\"header-search-container\">\n <cide-ele-input id=\"cide_lyt_header_search\" placeholder=\"Search...\" leadingIcon=\"search\" size=\"md\"></cide-ele-input>\n </div>\n \n <!-- Icons Section -->\n <div class=\"header-icons-container\">\n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-icon>dashboard</cide-ele-icon>\n <div class=\"header-tooltip\">Dashboard</div>\n </div>\n \n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-icon>notifications</cide-ele-icon>\n <div class=\"header-badge\">3</div>\n <div class=\"header-tooltip\">Notifications</div>\n </div>\n \n <div class=\"header-divider\"></div>\n \n <div class=\"header-icon user-profile\" (mouseenter)=\"updateTooltipPosition($event)\">\n <div class=\"profile-avatar\">AK</div>\n <div class=\"header-tooltip\">My Account</div>\n </div>\n \n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-icon>more_vert</cide-ele-icon>\n <div class=\"header-tooltip\">More Options</div>\n </div>\n </div>\n</header>", styles: [".cide-lyt-header{display:flex;align-items:center;justify-content:space-between;background:linear-gradient(to right,#fffffff2,#f9fafbf2);box-shadow:0 2px 8px #00000008;padding:0 1rem;position:relative;z-index:20;transition:all .3s cubic-bezier(.4,0,.2,1);will-change:transform;border-bottom:1px solid rgba(229,231,235,.8);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.header-logo-container{height:100%;display:flex;align-items:center;padding:.5rem 0;position:relative;transition:all .3s cubic-bezier(.4,0,.2,1);border-radius:8px;outline:none}.header-logo-container img{height:30px;max-height:100%;transition:all .3s ease;border-radius:5px;overflow:hidden;box-shadow:0 1px 4px #0000000d}.header-logo-container:hover img{transform:scale(1.03);filter:brightness(1.05);box-shadow:0 2px 6px #00000014}.header-logo-container:after{content:\"\";position:absolute;top:-50%;left:-50%;width:200%;height:200%;background:linear-gradient(to bottom right,#fff0,#ffffff4d,#fff0);transform:rotate(30deg);opacity:0;transition:transform .6s ease,opacity .6s ease;pointer-events:none}.header-logo-container:hover:after,.header-logo-container:focus:after{opacity:1;transform:rotate(30deg) translate(50%,50%)}.header-search-container{flex-grow:1;max-width:600px;margin:0 2rem;position:relative;transition:all .3s ease}::ng-deep .header-search-container #cide_lyt_header_search{width:100%;background-color:#f9fafbcc;border-radius:20px!important;transition:all .3s ease;overflow:visible;transform:translateZ(0)}::ng-deep .header-search-container #cide_lyt_header_search:hover{box-shadow:0 3px 12px #00000014;background-color:#fff;transform:translateY(-1px)}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-input{background-color:transparent;font-size:.85rem!important;letter-spacing:.01em}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-leading-icon{color:#6b7280b3!important;font-size:1.1rem!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within{transform:translateY(-1px) scale(1.01)}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-input{border-color:#3b82f6!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-leading-icon{color:#3b82f6!important}.header-icons-container{display:flex;align-items:center;gap:1rem}.header-icon{position:relative;width:32px;height:32px;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;color:#374151;border-radius:.4rem;margin:0 2px}.header-icon:before{content:\"\";position:absolute;inset:0;background-color:#3b82f61a;border-radius:.5rem;opacity:0;transform:scale(.8);transition:all .2s cubic-bezier(.4,0,.2,1)}.header-icon:hover:before{opacity:1;transform:scale(1)}.header-icon:hover{color:#3b82f6}.header-icon:active{transform:scale(.95)}.header-tooltip{position:absolute;bottom:-26px;left:50%;transform:translate(-50%);background-color:#374151e6;color:#fff;padding:.25rem .6rem;border-radius:.25rem;font-size:.7rem;white-space:nowrap;opacity:0;pointer-events:none;transition:all .2s cubic-bezier(.4,0,.2,1);z-index:1000;box-shadow:0 2px 5px #0003;letter-spacing:.01em;will-change:transform,opacity}.header-tooltip:before{content:\"\";position:absolute;bottom:100%;left:50%;transform:translate(-50%);border-width:5px;border-style:solid;border-color:transparent transparent rgba(55,65,81,.9) transparent}.header-icon:hover .header-tooltip{opacity:1;transform:translate(-50%) translateY(0)}.header-badge{position:absolute;top:0;right:0;min-width:16px;height:16px;border-radius:8px;background-color:#ef4444;color:#fff;font-size:9px;display:flex;align-items:center;justify-content:center;padding:0 4px;box-shadow:0 1px 3px #ef44444d;font-weight:600;z-index:2;transition:all .2s ease}.header-icon:hover .header-badge{transform:scale(1.1)}.header-divider{height:20px;width:1px;background-color:#e5e7ebcc;margin:0 6px}.profile-avatar{width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;font-size:.75rem;font-weight:600;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 6px #2563eb33;transition:all .2s cubic-bezier(.4,0,.2,1);letter-spacing:-.5px}.header-icon:hover .profile-avatar{transform:scale(1.08);box-shadow:0 3px 8px #2563eb4d}.header-avatar{width:36px;height:36px;border-radius:50%;overflow:hidden;transition:all .2s cubic-bezier(.4,0,.2,1);border:2px solid transparent;box-shadow:0 2px 4px #0000001a}.header-avatar:hover{border-color:#3b82f6;transform:scale(1.05);box-shadow:0 3px 6px #3b82f64d}@media (max-width: 768px){.header-search-container{margin:0 1rem}.header-icons-container{gap:.5rem}}@media (max-width: 640px){.header-search-container{max-width:200px;margin:0 .5rem}}\n"], dependencies: [{ kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "size"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }] });
1457
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.7", type: CideLytHeaderWrapperComponent, isStandalone: true, selector: "cide-lyt-header-wrapper", usesInheritance: true, ngImport: i0, template: "<header id=\"cide-lyt-header-wrapper\" class=\"cide-lyt-header tw-w-full tw-select-none cide-lyt-header-wrapper-hide\">\n <!-- Logo Section -->\n <div class=\"header-logo-container tw-cursor-pointer\" \n (click)=\"onLogoClick()\" \n (keydown.enter)=\"onLogoClick()\" \n (keydown.space)=\"onLogoClick()\"\n tabindex=\"0\" \n role=\"button\"\n aria-label=\"Navigate to home\"\n title=\"Click to go to control panel home\">\n <img [src]=\"'data:image/png;base64,' + syen_photo.cyfm_file_base64\"\n [alt]=\"syen_photo.cyfm_alt_text ? syen_photo.cyfm_alt_text : 'Entity Logo'\">\n </div>\n <!-- Search Section -->\n <div class=\"header-search-container\">\n <cide-ele-input id=\"cide_lyt_header_search\" placeholder=\"Search...\" leadingIcon=\"search\" size=\"md\"></cide-ele-input>\n </div>\n \n <!-- Icons Section -->\n <div class=\"header-icons-container\">\n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-icon>dashboard</cide-ele-icon>\n <div class=\"header-tooltip\">Dashboard</div>\n </div>\n \n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-icon>notifications</cide-ele-icon>\n <div class=\"header-badge\">3</div>\n <div class=\"header-tooltip\">Notifications</div>\n </div>\n \n <div class=\"header-divider\"></div>\n \n <div class=\"header-icon user-profile\" (mouseenter)=\"updateTooltipPosition($event)\">\n <div class=\"profile-avatar\">AK</div>\n <div class=\"header-tooltip\">My Account</div>\n </div>\n \n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown\n [items]=\"moreOptionsItems\"\n [config]=\"moreOptionsConfig\"\n (itemClick)=\"onMoreOptionsClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">More Options</div>\n </div>\n </div>\n</header>", styles: [".cide-lyt-header{display:flex;align-items:center;justify-content:space-between;background:linear-gradient(to right,#fffffff2,#f9fafbf2);box-shadow:0 2px 8px #00000008;padding:0 1rem;position:relative;z-index:20;transition:all .3s cubic-bezier(.4,0,.2,1);will-change:transform;border-bottom:1px solid rgba(229,231,235,.8);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.header-logo-container{height:100%;display:flex;align-items:center;padding:.5rem 0;position:relative;transition:all .3s cubic-bezier(.4,0,.2,1);border-radius:8px;outline:none}.header-logo-container img{height:30px;max-height:100%;transition:all .3s ease;border-radius:5px;overflow:hidden;box-shadow:0 1px 4px #0000000d}.header-logo-container:hover img{transform:scale(1.03);filter:brightness(1.05);box-shadow:0 2px 6px #00000014}.header-logo-container:after{content:\"\";position:absolute;top:-50%;left:-50%;width:200%;height:200%;background:linear-gradient(to bottom right,#fff0,#ffffff4d,#fff0);transform:rotate(30deg);opacity:0;transition:transform .6s ease,opacity .6s ease;pointer-events:none}.header-logo-container:hover:after,.header-logo-container:focus:after{opacity:1;transform:rotate(30deg) translate(50%,50%)}.header-search-container{flex-grow:1;max-width:600px;margin:0 2rem;position:relative;transition:all .3s ease}::ng-deep .header-search-container #cide_lyt_header_search{width:100%;background-color:#f9fafbcc;border-radius:20px!important;transition:all .3s ease;overflow:visible;transform:translateZ(0)}::ng-deep .header-search-container #cide_lyt_header_search:hover{box-shadow:0 3px 12px #00000014;background-color:#fff;transform:translateY(-1px)}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-input{background-color:transparent;font-size:.85rem!important;letter-spacing:.01em}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-leading-icon{color:#6b7280b3!important;font-size:1.1rem!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within{transform:translateY(-1px) scale(1.01)}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-input{border-color:#3b82f6!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-leading-icon{color:#3b82f6!important}.header-icons-container{display:flex;align-items:center;gap:1rem}.header-icon{position:relative;width:32px;height:32px;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;color:#374151;border-radius:.4rem;margin:0 2px}.header-icon:before{content:\"\";position:absolute;inset:0;background-color:#3b82f61a;border-radius:.5rem;opacity:0;transform:scale(.8);transition:all .2s cubic-bezier(.4,0,.2,1)}.header-icon:hover:before{opacity:1;transform:scale(1)}.header-icon:hover{color:#3b82f6}.header-icon:active{transform:scale(.95)}.header-tooltip{position:absolute;bottom:-26px;left:50%;transform:translate(-50%);background-color:#374151e6;color:#fff;padding:.25rem .6rem;border-radius:.25rem;font-size:.7rem;white-space:nowrap;opacity:0;pointer-events:none;transition:all .2s cubic-bezier(.4,0,.2,1);z-index:1000;box-shadow:0 2px 5px #0003;letter-spacing:.01em;will-change:transform,opacity}.header-tooltip:before{content:\"\";position:absolute;bottom:100%;left:50%;transform:translate(-50%);border-width:5px;border-style:solid;border-color:transparent transparent rgba(55,65,81,.9) transparent}.header-icon:hover .header-tooltip{opacity:1;transform:translate(-50%) translateY(0)}.header-badge{position:absolute;top:0;right:0;min-width:16px;height:16px;border-radius:8px;background-color:#ef4444;color:#fff;font-size:9px;display:flex;align-items:center;justify-content:center;padding:0 4px;box-shadow:0 1px 3px #ef44444d;font-weight:600;z-index:2;transition:all .2s ease}.header-icon:hover .header-badge{transform:scale(1.1)}.header-divider{height:20px;width:1px;background-color:#e5e7ebcc;margin:0 6px}.profile-avatar{width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;font-size:.75rem;font-weight:600;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 6px #2563eb33;transition:all .2s cubic-bezier(.4,0,.2,1);letter-spacing:-.5px}.header-icon:hover .profile-avatar{transform:scale(1.08);box-shadow:0 3px 8px #2563eb4d}.header-avatar{width:36px;height:36px;border-radius:50%;overflow:hidden;transition:all .2s cubic-bezier(.4,0,.2,1);border:2px solid transparent;box-shadow:0 2px 4px #0000001a}.header-avatar:hover{border-color:#3b82f6;transform:scale(1.05);box-shadow:0 3px 6px #3b82f64d}@media (max-width: 768px){.header-search-container{margin:0 1rem}.header-icons-container{gap:.5rem}}@media (max-width: 640px){.header-search-container{max-width:200px;margin:0 .5rem}}\n"], dependencies: [{ kind: "component", type: CideInputComponent, selector: "cide-ele-input", inputs: ["fill", "label", "labelHide", "disabled", "clearInput", "labelPlacement", "labelDir", "placeholder", "leadingIcon", "trailingIcon", "helperText", "helperTextCollapse", "hideHelperAndErrorText", "errorText", "maxlength", "minlength", "required", "autocapitalize", "autocomplete", "type", "width", "id", "ngModel", "option", "min", "max", "size"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: CideIconComponent, selector: "cide-ele-icon", inputs: ["size", "type", "toolTip"] }, { kind: "component", type: CideEleDropdownComponent, selector: "cide-ele-dropdown", inputs: ["items", "config", "triggerTemplate", "menuTemplate"], outputs: ["itemClick", "dropdownToggle"] }] });
1350
1458
  }
1351
1459
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: CideLytHeaderWrapperComponent, decorators: [{
1352
1460
  type: Component,
1353
- args: [{ selector: 'cide-lyt-header-wrapper', standalone: true, imports: [CideInputComponent, CommonModule, CideIconComponent], template: "<header id=\"cide-lyt-header-wrapper\" class=\"cide-lyt-header tw-w-full tw-select-none cide-lyt-header-wrapper-hide\">\n <!-- Logo Section -->\n <div class=\"header-logo-container tw-cursor-pointer\" \n (click)=\"onLogoClick()\" \n (keydown.enter)=\"onLogoClick()\" \n (keydown.space)=\"onLogoClick()\"\n tabindex=\"0\" \n role=\"button\"\n aria-label=\"Navigate to home\"\n title=\"Click to go to control panel home\">\n <img [src]=\"'data:image/png;base64,' + syen_photo.cyfm_file_base64\"\n [alt]=\"syen_photo.cyfm_alt_text ? syen_photo.cyfm_alt_text : 'Entity Logo'\">\n </div>\n <!-- Search Section -->\n <div class=\"header-search-container\">\n <cide-ele-input id=\"cide_lyt_header_search\" placeholder=\"Search...\" leadingIcon=\"search\" size=\"md\"></cide-ele-input>\n </div>\n \n <!-- Icons Section -->\n <div class=\"header-icons-container\">\n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-icon>dashboard</cide-ele-icon>\n <div class=\"header-tooltip\">Dashboard</div>\n </div>\n \n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-icon>notifications</cide-ele-icon>\n <div class=\"header-badge\">3</div>\n <div class=\"header-tooltip\">Notifications</div>\n </div>\n \n <div class=\"header-divider\"></div>\n \n <div class=\"header-icon user-profile\" (mouseenter)=\"updateTooltipPosition($event)\">\n <div class=\"profile-avatar\">AK</div>\n <div class=\"header-tooltip\">My Account</div>\n </div>\n \n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-icon>more_vert</cide-ele-icon>\n <div class=\"header-tooltip\">More Options</div>\n </div>\n </div>\n</header>", styles: [".cide-lyt-header{display:flex;align-items:center;justify-content:space-between;background:linear-gradient(to right,#fffffff2,#f9fafbf2);box-shadow:0 2px 8px #00000008;padding:0 1rem;position:relative;z-index:20;transition:all .3s cubic-bezier(.4,0,.2,1);will-change:transform;border-bottom:1px solid rgba(229,231,235,.8);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.header-logo-container{height:100%;display:flex;align-items:center;padding:.5rem 0;position:relative;transition:all .3s cubic-bezier(.4,0,.2,1);border-radius:8px;outline:none}.header-logo-container img{height:30px;max-height:100%;transition:all .3s ease;border-radius:5px;overflow:hidden;box-shadow:0 1px 4px #0000000d}.header-logo-container:hover img{transform:scale(1.03);filter:brightness(1.05);box-shadow:0 2px 6px #00000014}.header-logo-container:after{content:\"\";position:absolute;top:-50%;left:-50%;width:200%;height:200%;background:linear-gradient(to bottom right,#fff0,#ffffff4d,#fff0);transform:rotate(30deg);opacity:0;transition:transform .6s ease,opacity .6s ease;pointer-events:none}.header-logo-container:hover:after,.header-logo-container:focus:after{opacity:1;transform:rotate(30deg) translate(50%,50%)}.header-search-container{flex-grow:1;max-width:600px;margin:0 2rem;position:relative;transition:all .3s ease}::ng-deep .header-search-container #cide_lyt_header_search{width:100%;background-color:#f9fafbcc;border-radius:20px!important;transition:all .3s ease;overflow:visible;transform:translateZ(0)}::ng-deep .header-search-container #cide_lyt_header_search:hover{box-shadow:0 3px 12px #00000014;background-color:#fff;transform:translateY(-1px)}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-input{background-color:transparent;font-size:.85rem!important;letter-spacing:.01em}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-leading-icon{color:#6b7280b3!important;font-size:1.1rem!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within{transform:translateY(-1px) scale(1.01)}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-input{border-color:#3b82f6!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-leading-icon{color:#3b82f6!important}.header-icons-container{display:flex;align-items:center;gap:1rem}.header-icon{position:relative;width:32px;height:32px;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;color:#374151;border-radius:.4rem;margin:0 2px}.header-icon:before{content:\"\";position:absolute;inset:0;background-color:#3b82f61a;border-radius:.5rem;opacity:0;transform:scale(.8);transition:all .2s cubic-bezier(.4,0,.2,1)}.header-icon:hover:before{opacity:1;transform:scale(1)}.header-icon:hover{color:#3b82f6}.header-icon:active{transform:scale(.95)}.header-tooltip{position:absolute;bottom:-26px;left:50%;transform:translate(-50%);background-color:#374151e6;color:#fff;padding:.25rem .6rem;border-radius:.25rem;font-size:.7rem;white-space:nowrap;opacity:0;pointer-events:none;transition:all .2s cubic-bezier(.4,0,.2,1);z-index:1000;box-shadow:0 2px 5px #0003;letter-spacing:.01em;will-change:transform,opacity}.header-tooltip:before{content:\"\";position:absolute;bottom:100%;left:50%;transform:translate(-50%);border-width:5px;border-style:solid;border-color:transparent transparent rgba(55,65,81,.9) transparent}.header-icon:hover .header-tooltip{opacity:1;transform:translate(-50%) translateY(0)}.header-badge{position:absolute;top:0;right:0;min-width:16px;height:16px;border-radius:8px;background-color:#ef4444;color:#fff;font-size:9px;display:flex;align-items:center;justify-content:center;padding:0 4px;box-shadow:0 1px 3px #ef44444d;font-weight:600;z-index:2;transition:all .2s ease}.header-icon:hover .header-badge{transform:scale(1.1)}.header-divider{height:20px;width:1px;background-color:#e5e7ebcc;margin:0 6px}.profile-avatar{width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;font-size:.75rem;font-weight:600;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 6px #2563eb33;transition:all .2s cubic-bezier(.4,0,.2,1);letter-spacing:-.5px}.header-icon:hover .profile-avatar{transform:scale(1.08);box-shadow:0 3px 8px #2563eb4d}.header-avatar{width:36px;height:36px;border-radius:50%;overflow:hidden;transition:all .2s cubic-bezier(.4,0,.2,1);border:2px solid transparent;box-shadow:0 2px 4px #0000001a}.header-avatar:hover{border-color:#3b82f6;transform:scale(1.05);box-shadow:0 3px 6px #3b82f64d}@media (max-width: 768px){.header-search-container{margin:0 1rem}.header-icons-container{gap:.5rem}}@media (max-width: 640px){.header-search-container{max-width:200px;margin:0 .5rem}}\n"] }]
1461
+ args: [{ selector: 'cide-lyt-header-wrapper', standalone: true, imports: [CideInputComponent, CommonModule, CideIconComponent, CideEleDropdownComponent], template: "<header id=\"cide-lyt-header-wrapper\" class=\"cide-lyt-header tw-w-full tw-select-none cide-lyt-header-wrapper-hide\">\n <!-- Logo Section -->\n <div class=\"header-logo-container tw-cursor-pointer\" \n (click)=\"onLogoClick()\" \n (keydown.enter)=\"onLogoClick()\" \n (keydown.space)=\"onLogoClick()\"\n tabindex=\"0\" \n role=\"button\"\n aria-label=\"Navigate to home\"\n title=\"Click to go to control panel home\">\n <img [src]=\"'data:image/png;base64,' + syen_photo.cyfm_file_base64\"\n [alt]=\"syen_photo.cyfm_alt_text ? syen_photo.cyfm_alt_text : 'Entity Logo'\">\n </div>\n <!-- Search Section -->\n <div class=\"header-search-container\">\n <cide-ele-input id=\"cide_lyt_header_search\" placeholder=\"Search...\" leadingIcon=\"search\" size=\"md\"></cide-ele-input>\n </div>\n \n <!-- Icons Section -->\n <div class=\"header-icons-container\">\n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-icon>dashboard</cide-ele-icon>\n <div class=\"header-tooltip\">Dashboard</div>\n </div>\n \n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-icon>notifications</cide-ele-icon>\n <div class=\"header-badge\">3</div>\n <div class=\"header-tooltip\">Notifications</div>\n </div>\n \n <div class=\"header-divider\"></div>\n \n <div class=\"header-icon user-profile\" (mouseenter)=\"updateTooltipPosition($event)\">\n <div class=\"profile-avatar\">AK</div>\n <div class=\"header-tooltip\">My Account</div>\n </div>\n \n <div class=\"header-icon\" (mouseenter)=\"updateTooltipPosition($event)\">\n <cide-ele-dropdown\n [items]=\"moreOptionsItems\"\n [config]=\"moreOptionsConfig\"\n (itemClick)=\"onMoreOptionsClick($event)\">\n </cide-ele-dropdown>\n <div class=\"header-tooltip\">More Options</div>\n </div>\n </div>\n</header>", styles: [".cide-lyt-header{display:flex;align-items:center;justify-content:space-between;background:linear-gradient(to right,#fffffff2,#f9fafbf2);box-shadow:0 2px 8px #00000008;padding:0 1rem;position:relative;z-index:20;transition:all .3s cubic-bezier(.4,0,.2,1);will-change:transform;border-bottom:1px solid rgba(229,231,235,.8);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.header-logo-container{height:100%;display:flex;align-items:center;padding:.5rem 0;position:relative;transition:all .3s cubic-bezier(.4,0,.2,1);border-radius:8px;outline:none}.header-logo-container img{height:30px;max-height:100%;transition:all .3s ease;border-radius:5px;overflow:hidden;box-shadow:0 1px 4px #0000000d}.header-logo-container:hover img{transform:scale(1.03);filter:brightness(1.05);box-shadow:0 2px 6px #00000014}.header-logo-container:after{content:\"\";position:absolute;top:-50%;left:-50%;width:200%;height:200%;background:linear-gradient(to bottom right,#fff0,#ffffff4d,#fff0);transform:rotate(30deg);opacity:0;transition:transform .6s ease,opacity .6s ease;pointer-events:none}.header-logo-container:hover:after,.header-logo-container:focus:after{opacity:1;transform:rotate(30deg) translate(50%,50%)}.header-search-container{flex-grow:1;max-width:600px;margin:0 2rem;position:relative;transition:all .3s ease}::ng-deep .header-search-container #cide_lyt_header_search{width:100%;background-color:#f9fafbcc;border-radius:20px!important;transition:all .3s ease;overflow:visible;transform:translateZ(0)}::ng-deep .header-search-container #cide_lyt_header_search:hover{box-shadow:0 3px 12px #00000014;background-color:#fff;transform:translateY(-1px)}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-input{background-color:transparent;font-size:.85rem!important;letter-spacing:.01em}::ng-deep .header-search-container #cide_lyt_header_search .cide-input-leading-icon{color:#6b7280b3!important;font-size:1.1rem!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within{transform:translateY(-1px) scale(1.01)}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-input{border-color:#3b82f6!important}::ng-deep .header-search-container #cide_lyt_header_search:focus-within .cide-input-leading-icon{color:#3b82f6!important}.header-icons-container{display:flex;align-items:center;gap:1rem}.header-icon{position:relative;width:32px;height:32px;display:flex;align-items:center;justify-content:center;transition:all .2s cubic-bezier(.4,0,.2,1);cursor:pointer;color:#374151;border-radius:.4rem;margin:0 2px}.header-icon:before{content:\"\";position:absolute;inset:0;background-color:#3b82f61a;border-radius:.5rem;opacity:0;transform:scale(.8);transition:all .2s cubic-bezier(.4,0,.2,1)}.header-icon:hover:before{opacity:1;transform:scale(1)}.header-icon:hover{color:#3b82f6}.header-icon:active{transform:scale(.95)}.header-tooltip{position:absolute;bottom:-26px;left:50%;transform:translate(-50%);background-color:#374151e6;color:#fff;padding:.25rem .6rem;border-radius:.25rem;font-size:.7rem;white-space:nowrap;opacity:0;pointer-events:none;transition:all .2s cubic-bezier(.4,0,.2,1);z-index:1000;box-shadow:0 2px 5px #0003;letter-spacing:.01em;will-change:transform,opacity}.header-tooltip:before{content:\"\";position:absolute;bottom:100%;left:50%;transform:translate(-50%);border-width:5px;border-style:solid;border-color:transparent transparent rgba(55,65,81,.9) transparent}.header-icon:hover .header-tooltip{opacity:1;transform:translate(-50%) translateY(0)}.header-badge{position:absolute;top:0;right:0;min-width:16px;height:16px;border-radius:8px;background-color:#ef4444;color:#fff;font-size:9px;display:flex;align-items:center;justify-content:center;padding:0 4px;box-shadow:0 1px 3px #ef44444d;font-weight:600;z-index:2;transition:all .2s ease}.header-icon:hover .header-badge{transform:scale(1.1)}.header-divider{height:20px;width:1px;background-color:#e5e7ebcc;margin:0 6px}.profile-avatar{width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;font-size:.75rem;font-weight:600;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 6px #2563eb33;transition:all .2s cubic-bezier(.4,0,.2,1);letter-spacing:-.5px}.header-icon:hover .profile-avatar{transform:scale(1.08);box-shadow:0 3px 8px #2563eb4d}.header-avatar{width:36px;height:36px;border-radius:50%;overflow:hidden;transition:all .2s cubic-bezier(.4,0,.2,1);border:2px solid transparent;box-shadow:0 2px 4px #0000001a}.header-avatar:hover{border-color:#3b82f6;transform:scale(1.05);box-shadow:0 3px 6px #3b82f64d}@media (max-width: 768px){.header-search-container{margin:0 1rem}.header-icons-container{gap:.5rem}}@media (max-width: 640px){.header-search-container{max-width:200px;margin:0 .5rem}}\n"] }]
1354
1462
  }], ctorParameters: () => [] });
1355
1463
 
1356
1464
  class CideLytUserStatusService {
@@ -2544,8 +2652,8 @@ class CideLytSidedrawerWrapperComponent {
2544
2652
  }
2545
2653
  ngOnInit() {
2546
2654
  // Initialize the component map (You'd likely populate this from a config or service)
2547
- this.componentMap['drowar_notes'] = () => import('./cloud-ide-layout-sidedrawer-notes.component-C5cJd6Nf.mjs').then(m => m.CideLytSidedrawerNotesComponent);
2548
- this.componentMap['drawer_theme'] = () => import('./cloud-ide-layout-drawer-theme.component-B-7FQRAk.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);
2549
2657
  }
2550
2658
  async loadComponent(configFor) {
2551
2659
  console.log('🔍 SIDEDRAWER - Loading component:', configFor, 'Current tab:', this.currentTabId);
@@ -2917,7 +3025,7 @@ const layoutControlPannelChildRoutes = [{
2917
3025
  },
2918
3026
  {
2919
3027
  path: "home",
2920
- loadComponent: () => import('./cloud-ide-layout-home-wrapper.component-CRqB9B-k.mjs').then(c => c.CideLytHomeWrapperComponent),
3028
+ loadComponent: () => import('./cloud-ide-layout-home-wrapper.component-DEec7PZk.mjs').then(c => c.CideLytHomeWrapperComponent),
2921
3029
  canActivate: [authGuard],
2922
3030
  data: {
2923
3031
  reuseTab: true, // For CustomRouteReuseStrategy
@@ -3174,6 +3282,550 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
3174
3282
  }]
3175
3283
  }] });
3176
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
+
3177
3829
  /*
3178
3830
  * Public API Surface of cloud-ide-layout
3179
3831
  */
@@ -3182,5 +3834,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImpor
3182
3834
  * Generated bundle index. Do not edit.
3183
3835
  */
3184
3836
 
3185
- 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 };
3186
- //# sourceMappingURL=cloud-ide-layout-cloud-ide-layout-G4z9orRq.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