@flusys/ng-shared 0.1.0-beta.3 → 1.0.0-beta

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,20 +1,22 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, PLATFORM_ID, Injectable, DOCUMENT, REQUEST, signal, computed, ElementRef, input, effect, Directive, TemplateRef, ViewContainerRef, output, HostListener, NgModule, resource, Component, Injector, model, runInInjectionContext, untracked, forwardRef, viewChild, ChangeDetectionStrategy, InjectionToken } from '@angular/core';
2
+ import { inject, PLATFORM_ID, Injectable, DOCUMENT, REQUEST, signal, computed, ElementRef, input, effect, Directive, TemplateRef, ViewContainerRef, output, HostListener, NgModule, Injector, runInInjectionContext, resource, Component, model, untracked, forwardRef, viewChild, ChangeDetectionStrategy, InjectionToken, DestroyRef, afterNextRender, isDevMode } from '@angular/core';
3
3
  import * as i1 from '@angular/common';
4
4
  import { isPlatformServer, CommonModule, NgOptimizedImage, NgComponentOutlet, DatePipe } from '@angular/common';
5
5
  import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
6
6
  import { APP_CONFIG, getServiceUrl, ApiLoaderService } from '@flusys/ng-core';
7
- import { of, firstValueFrom, skip, debounceTime, distinctUntilChanged, tap as tap$1 } from 'rxjs';
7
+ import { of, firstValueFrom, skip, debounceTime, distinctUntilChanged, tap as tap$1, map as map$1 } from 'rxjs';
8
8
  import { tap, catchError, map } from 'rxjs/operators';
9
- import * as i4 from '@angular/forms';
10
- import { NgControl, ReactiveFormsModule, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
9
+ import * as i1$2 from '@angular/forms';
10
+ import { NgControl, FormsModule, ReactiveFormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
11
11
  import { RouterOutlet, RouterLink, Router } from '@angular/router';
12
12
  import { AutoCompleteModule } from 'primeng/autocomplete';
13
+ import * as i1$3 from 'primeng/button';
13
14
  import { ButtonModule } from 'primeng/button';
14
15
  import { CardModule } from 'primeng/card';
15
16
  import * as i2 from 'primeng/checkbox';
16
17
  import { CheckboxModule } from 'primeng/checkbox';
17
18
  import { DatePickerModule } from 'primeng/datepicker';
19
+ import * as i6 from 'primeng/dialog';
18
20
  import { DialogModule } from 'primeng/dialog';
19
21
  import { DividerModule } from 'primeng/divider';
20
22
  import { FileUploadModule } from 'primeng/fileupload';
@@ -30,6 +32,7 @@ import { PaginatorModule } from 'primeng/paginator';
30
32
  import { PanelModule } from 'primeng/panel';
31
33
  import { PasswordModule } from 'primeng/password';
32
34
  import { PopoverModule } from 'primeng/popover';
35
+ import * as i2$1 from 'primeng/progressbar';
33
36
  import { ProgressBarModule } from 'primeng/progressbar';
34
37
  import { RadioButtonModule } from 'primeng/radiobutton';
35
38
  import { RippleModule } from 'primeng/ripple';
@@ -46,10 +49,81 @@ import { ToggleSwitchModule } from 'primeng/toggleswitch';
46
49
  import { TooltipModule } from 'primeng/tooltip';
47
50
  import { TreeTableModule } from 'primeng/treetable';
48
51
  import { toSignal, toObservable } from '@angular/core/rxjs-interop';
52
+ import * as i4 from 'primeng/api';
53
+ import { MessageService } from 'primeng/api';
49
54
 
50
55
  ;
51
56
  ;
52
57
 
58
+ /**
59
+ * Common file type filters
60
+ */
61
+ const FILE_TYPE_FILTERS = {
62
+ IMAGES: ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml'],
63
+ DOCUMENTS: [
64
+ 'application/pdf',
65
+ 'application/msword',
66
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
67
+ 'application/vnd.ms-excel',
68
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
69
+ ],
70
+ VIDEOS: ['video/mp4', 'video/webm', 'video/ogg', 'video/quicktime'],
71
+ AUDIO: ['audio/mpeg', 'audio/wav', 'audio/ogg', 'audio/webm'],
72
+ ALL: [],
73
+ };
74
+ /**
75
+ * Get accept string for file input from content types
76
+ */
77
+ function getAcceptString(contentTypes) {
78
+ if (!contentTypes.length)
79
+ return '*/*';
80
+ return contentTypes.join(',');
81
+ }
82
+ /**
83
+ * Check if file matches allowed content types
84
+ */
85
+ function isFileTypeAllowed(file, allowedTypes) {
86
+ if (!allowedTypes.length)
87
+ return true;
88
+ return allowedTypes.some((type) => {
89
+ if (type.endsWith('/*')) {
90
+ return file.type.startsWith(type.replace('/*', '/'));
91
+ }
92
+ return file.type === type;
93
+ });
94
+ }
95
+ /**
96
+ * Get file icon class based on content type
97
+ */
98
+ function getFileIconClass(contentType) {
99
+ if (contentType.startsWith('image/'))
100
+ return 'pi pi-image';
101
+ if (contentType.startsWith('video/'))
102
+ return 'pi pi-video';
103
+ if (contentType.startsWith('audio/'))
104
+ return 'pi pi-volume-up';
105
+ if (contentType.includes('pdf'))
106
+ return 'pi pi-file-pdf';
107
+ if (contentType.includes('word') || contentType.includes('document'))
108
+ return 'pi pi-file-word';
109
+ if (contentType.includes('excel') || contentType.includes('spreadsheet'))
110
+ return 'pi pi-file-excel';
111
+ return 'pi pi-file';
112
+ }
113
+ /**
114
+ * Format file size for display
115
+ */
116
+ function formatFileSize(sizeInKb) {
117
+ const kb = typeof sizeInKb === 'string' ? parseFloat(sizeInKb) : sizeInKb;
118
+ if (kb < 1024)
119
+ return `${kb.toFixed(1)} KB`;
120
+ const mb = kb / 1024;
121
+ if (mb < 1024)
122
+ return `${mb.toFixed(1)} MB`;
123
+ const gb = mb / 1024;
124
+ return `${gb.toFixed(2)} GB`;
125
+ }
126
+
53
127
  var ContactTypeEnum;
54
128
  (function (ContactTypeEnum) {
55
129
  ContactTypeEnum[ContactTypeEnum["PHONE"] = 1] = "PHONE";
@@ -68,10 +142,10 @@ class PlatformService {
68
142
  get isServer() {
69
143
  return isPlatformServer(this.platformId);
70
144
  }
71
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: PlatformService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
72
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: PlatformService, providedIn: 'root' });
145
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: PlatformService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
146
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: PlatformService, providedIn: 'root' });
73
147
  }
74
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: PlatformService, decorators: [{
148
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: PlatformService, decorators: [{
75
149
  type: Injectable,
76
150
  args: [{
77
151
  providedIn: 'root'
@@ -85,10 +159,10 @@ class CookieService {
85
159
  get() {
86
160
  return !this.platformService.isServer ? this.doc.cookie : this.request?.headers.get('cookie') ?? "";
87
161
  }
88
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: CookieService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
89
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: CookieService, providedIn: 'root' });
162
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: CookieService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
163
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: CookieService, providedIn: 'root' });
90
164
  }
91
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: CookieService, decorators: [{
165
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: CookieService, decorators: [{
92
166
  type: Injectable,
93
167
  args: [{
94
168
  providedIn: 'root',
@@ -135,10 +209,7 @@ class FileUrlService {
135
209
  const cache = new Map(this.urlCache());
136
210
  files.forEach((file) => cache.set(file.id, file));
137
211
  this.urlCache.set(cache);
138
- }), catchError((error) => {
139
- console.error('Failed to fetch file URLs:', error);
140
- return of([]);
141
- }));
212
+ }), catchError(() => of([])));
142
213
  }
143
214
  /**
144
215
  * Fetch a single file URL.
@@ -162,10 +233,10 @@ class FileUrlService {
162
233
  cache.delete(fileId);
163
234
  this.urlCache.set(cache);
164
235
  }
165
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: FileUrlService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
166
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: FileUrlService, providedIn: 'root' });
236
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: FileUrlService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
237
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: FileUrlService, providedIn: 'root' });
167
238
  }
168
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: FileUrlService, decorators: [{
239
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: FileUrlService, decorators: [{
169
240
  type: Injectable,
170
241
  args: [{ providedIn: 'root' }]
171
242
  }] });
@@ -247,10 +318,10 @@ class PermissionValidatorService {
247
318
  isPermissionsLoaded() {
248
319
  return this._isLoaded();
249
320
  }
250
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: PermissionValidatorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
251
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: PermissionValidatorService, providedIn: 'root' });
321
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: PermissionValidatorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
322
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: PermissionValidatorService, providedIn: 'root' });
252
323
  }
253
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: PermissionValidatorService, decorators: [{
324
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: PermissionValidatorService, decorators: [{
254
325
  type: Injectable,
255
326
  args: [{
256
327
  providedIn: 'root',
@@ -268,11 +339,6 @@ class EditModeElementChangerDirective {
268
339
  this.updateControl(editMode);
269
340
  });
270
341
  }
271
- ngAfterViewInit() {
272
- const editMode = this.isEditMode();
273
- this.updateElement(editMode);
274
- this.updateControl(editMode);
275
- }
276
342
  updateControl(editMode) {
277
343
  if (!editMode)
278
344
  this.ngControl?.control?.disable();
@@ -284,44 +350,41 @@ class EditModeElementChangerDirective {
284
350
  if (inputElement instanceof HTMLInputElement) {
285
351
  if (!editMode) {
286
352
  inputElement.setAttribute('readonly', 'true');
287
- inputElement?.classList.add('edit-mode-element-css');
353
+ inputElement.classList.add('edit-mode-element-css');
288
354
  }
289
355
  else {
290
356
  inputElement.removeAttribute('readonly');
291
- inputElement?.classList.remove('edit-mode-element-css');
357
+ inputElement.classList.remove('edit-mode-element-css');
292
358
  }
293
359
  }
294
- if (inputElement.tagName == 'P-SELECT') {
360
+ if (inputElement.tagName === 'P-SELECT') {
295
361
  if (!editMode) {
296
- inputElement.classList.add('edit-mode-element-css');
297
- inputElement.classList.add('overflow-hidden');
362
+ inputElement.classList.add('edit-mode-element-css', 'overflow-hidden');
298
363
  inputElement.querySelector('.p-select-dropdown').style.display = 'none';
299
364
  inputElement.querySelector('.p-select-label').classList.add('edit-mode-element-css');
300
365
  }
301
366
  else {
302
- inputElement.classList.remove("edit-mode-element-css");
367
+ inputElement.classList.remove('edit-mode-element-css', 'overflow-hidden');
303
368
  inputElement.querySelector('.p-select-dropdown').style.display = 'flex';
304
- inputElement.querySelector('.p-select-label').classList.remove("edit-mode-element-css");
305
- inputElement.classList.remove('overflow-hidden');
369
+ inputElement.querySelector('.p-select-label').classList.remove('edit-mode-element-css');
306
370
  }
307
371
  }
308
- if (inputElement.tagName == 'P-CALENDAR') {
372
+ if (inputElement.tagName === 'P-CALENDAR') {
373
+ const firstChild = inputElement.firstElementChild;
309
374
  if (!editMode) {
310
- inputElement.firstElementChild.children[0]?.classList.add('edit-mode-element-css');
311
- inputElement.firstElementChild.children[0]?.classList.add('cursor-auto');
312
- inputElement.firstElementChild.children[1]?.classList.add('hidden');
375
+ firstChild?.children[0]?.classList.add('edit-mode-element-css', 'cursor-auto');
376
+ firstChild?.children[1]?.classList.add('hidden');
313
377
  }
314
378
  else {
315
- inputElement.firstElementChild.children[0]?.classList.remove('edit-mode-element-css');
316
- inputElement.firstElementChild.children[0]?.classList.remove('cursor-auto');
317
- inputElement.firstElementChild.children[1]?.classList.remove('hidden');
379
+ firstChild?.children[0]?.classList.remove('edit-mode-element-css', 'cursor-auto');
380
+ firstChild?.children[1]?.classList.remove('hidden');
318
381
  }
319
382
  }
320
383
  }
321
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: EditModeElementChangerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
322
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.0", type: EditModeElementChangerDirective, isStandalone: true, selector: "[appEditModeElementChanger]", inputs: { isEditMode: { classPropertyName: "isEditMode", publicName: "isEditMode", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
384
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: EditModeElementChangerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
385
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.3", type: EditModeElementChangerDirective, isStandalone: true, selector: "[appEditModeElementChanger]", inputs: { isEditMode: { classPropertyName: "isEditMode", publicName: "isEditMode", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
323
386
  }
324
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: EditModeElementChangerDirective, decorators: [{
387
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: EditModeElementChangerDirective, decorators: [{
325
388
  type: Directive,
326
389
  args: [{
327
390
  selector: '[appEditModeElementChanger]',
@@ -478,10 +541,10 @@ class HasPermissionDirective {
478
541
  this.viewCreated = false;
479
542
  }
480
543
  }
481
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: HasPermissionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
482
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.0", type: HasPermissionDirective, isStandalone: true, selector: "[hasPermission]", inputs: { hasPermission: { classPropertyName: "hasPermission", publicName: "hasPermission", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
544
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: HasPermissionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
545
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.3", type: HasPermissionDirective, isStandalone: true, selector: "[hasPermission]", inputs: { hasPermission: { classPropertyName: "hasPermission", publicName: "hasPermission", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
483
546
  }
484
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: HasPermissionDirective, decorators: [{
547
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: HasPermissionDirective, decorators: [{
485
548
  type: Directive,
486
549
  args: [{
487
550
  selector: '[hasPermission]',
@@ -503,10 +566,10 @@ class IsEmptyImageDirective {
503
566
  onError() {
504
567
  this.hasError.set(true);
505
568
  }
506
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: IsEmptyImageDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
507
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.0", type: IsEmptyImageDirective, isStandalone: true, selector: "img", inputs: { src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "error": "onError()" }, properties: { "src": "imageSrc()" } }, ngImport: i0 });
569
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: IsEmptyImageDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
570
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.3", type: IsEmptyImageDirective, isStandalone: true, selector: "img", inputs: { src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "error": "onError()" }, properties: { "src": "imageSrc()" } }, ngImport: i0 });
508
571
  }
509
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: IsEmptyImageDirective, decorators: [{
572
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: IsEmptyImageDirective, decorators: [{
510
573
  type: Directive,
511
574
  args: [{
512
575
  selector: 'img',
@@ -543,13 +606,12 @@ class PreventDefaultDirective {
543
606
  }
544
607
  processEvent(event) {
545
608
  event.preventDefault();
546
- if (this.action)
547
- this.action.emit(event);
609
+ this.action.emit(event);
548
610
  }
549
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: PreventDefaultDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
550
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.0", type: PreventDefaultDirective, isStandalone: true, selector: "[appPreventDefault]", inputs: { eventType: { classPropertyName: "eventType", publicName: "eventType", isSignal: true, isRequired: false, transformFunction: null }, preventKey: { classPropertyName: "preventKey", publicName: "preventKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, host: { listeners: { "click": "onClick($event)", "keydown": "onKeydown($event)", "keyup": "onKeyup($event)" } }, ngImport: i0 });
611
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: PreventDefaultDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
612
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.3", type: PreventDefaultDirective, isStandalone: true, selector: "[appPreventDefault]", inputs: { eventType: { classPropertyName: "eventType", publicName: "eventType", isSignal: true, isRequired: false, transformFunction: null }, preventKey: { classPropertyName: "preventKey", publicName: "preventKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { action: "action" }, host: { listeners: { "click": "onClick($event)", "keydown": "onKeydown($event)", "keyup": "onKeyup($event)" } }, ngImport: i0 });
551
613
  }
552
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: PreventDefaultDirective, decorators: [{
614
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: PreventDefaultDirective, decorators: [{
553
615
  type: Directive,
554
616
  args: [{
555
617
  selector: '[appPreventDefault]',
@@ -567,60 +629,62 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
567
629
  }] } });
568
630
 
569
631
  class AngularModule {
570
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: AngularModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
571
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.1.0", ngImport: i0, type: AngularModule, imports: [CommonModule,
632
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AngularModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
633
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.1.3", ngImport: i0, type: AngularModule, imports: [CommonModule,
634
+ FormsModule,
635
+ ReactiveFormsModule,
572
636
  RouterOutlet,
573
637
  RouterLink,
574
638
  IsEmptyImageDirective,
575
639
  NgOptimizedImage,
576
640
  NgComponentOutlet,
577
641
  PreventDefaultDirective], exports: [CommonModule,
578
- ReactiveFormsModule,
579
642
  FormsModule,
643
+ ReactiveFormsModule,
580
644
  RouterOutlet,
581
645
  RouterLink,
582
646
  IsEmptyImageDirective,
583
647
  NgOptimizedImage,
584
648
  NgComponentOutlet,
585
649
  PreventDefaultDirective] });
586
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: AngularModule, providers: [
587
- DatePipe,
588
- ], imports: [CommonModule, CommonModule,
589
- ReactiveFormsModule,
590
- FormsModule] });
650
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AngularModule, providers: [DatePipe], imports: [CommonModule,
651
+ FormsModule,
652
+ ReactiveFormsModule, CommonModule,
653
+ FormsModule,
654
+ ReactiveFormsModule] });
591
655
  }
592
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: AngularModule, decorators: [{
656
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: AngularModule, decorators: [{
593
657
  type: NgModule,
594
658
  args: [{
595
659
  imports: [
596
660
  CommonModule,
661
+ FormsModule,
662
+ ReactiveFormsModule,
597
663
  RouterOutlet,
598
664
  RouterLink,
599
665
  IsEmptyImageDirective,
600
666
  NgOptimizedImage,
601
667
  NgComponentOutlet,
602
- PreventDefaultDirective
603
- ],
604
- providers: [
605
- DatePipe,
668
+ PreventDefaultDirective,
606
669
  ],
670
+ providers: [DatePipe],
607
671
  exports: [
608
672
  CommonModule,
609
- ReactiveFormsModule,
610
673
  FormsModule,
674
+ ReactiveFormsModule,
611
675
  RouterOutlet,
612
676
  RouterLink,
613
677
  IsEmptyImageDirective,
614
678
  NgOptimizedImage,
615
679
  NgComponentOutlet,
616
- PreventDefaultDirective
680
+ PreventDefaultDirective,
617
681
  ],
618
682
  }]
619
683
  }] });
620
684
 
621
685
  class PrimeModule {
622
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: PrimeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
623
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.1.0", ngImport: i0, type: PrimeModule, exports: [InputTextModule,
686
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: PrimeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
687
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.1.3", ngImport: i0, type: PrimeModule, exports: [InputTextModule,
624
688
  TagModule,
625
689
  SelectButtonModule,
626
690
  PasswordModule,
@@ -653,7 +717,7 @@ class PrimeModule {
653
717
  TabsModule,
654
718
  DialogModule,
655
719
  TreeTableModule] });
656
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: PrimeModule, imports: [InputTextModule,
720
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: PrimeModule, imports: [InputTextModule,
657
721
  TagModule,
658
722
  SelectButtonModule,
659
723
  PasswordModule,
@@ -687,7 +751,7 @@ class PrimeModule {
687
751
  DialogModule,
688
752
  TreeTableModule] });
689
753
  }
690
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: PrimeModule, decorators: [{
754
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: PrimeModule, decorators: [{
691
755
  type: NgModule,
692
756
  args: [{
693
757
  exports: [
@@ -775,6 +839,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
775
839
  class ApiResourceService {
776
840
  baseUrl;
777
841
  loaderService = inject(ApiLoaderService);
842
+ injector = inject(Injector);
778
843
  http;
779
844
  moduleApiName;
780
845
  // ==========================================================================
@@ -789,22 +854,54 @@ class ApiResourceService {
789
854
  select: [],
790
855
  sort: {},
791
856
  }, ...(ngDevMode ? [{ debugName: "filterData" }] : []));
792
- /** Resource for list data - uses IListResponse matching backend */
793
- listResource;
857
+ /**
858
+ * Resource for list data - lazy initialized to prevent auto-fetch on service injection.
859
+ * Call initListResource() or any list method (fetchList, reload, etc.) to initialize.
860
+ */
861
+ _listResource = null;
862
+ /** Whether the list resource has been initialized */
863
+ _resourceInitialized = false;
864
+ /** Get or create the list resource (lazy initialization) */
865
+ get listResource() {
866
+ if (!this._listResource) {
867
+ this.initListResource();
868
+ }
869
+ return this._listResource;
870
+ }
871
+ /**
872
+ * Initialize the list resource. Called automatically when accessing listResource
873
+ * or any list-related computed signals/methods.
874
+ * Uses runInInjectionContext to support lazy initialization outside constructor.
875
+ */
876
+ initListResource() {
877
+ if (this._resourceInitialized)
878
+ return;
879
+ this._resourceInitialized = true;
880
+ runInInjectionContext(this.injector, () => {
881
+ this._listResource = resource({ ...(ngDevMode ? { debugName: "_listResource" } : {}), params: () => ({
882
+ search: this.searchTerm(),
883
+ filter: this.filterData(),
884
+ }),
885
+ loader: async ({ params }) => {
886
+ const { search, filter } = params;
887
+ return this.fetchAllAsync(search, filter);
888
+ } });
889
+ });
890
+ }
794
891
  // ==========================================================================
795
892
  // Computed State Accessors
796
893
  // ==========================================================================
797
894
  /** Whether data is currently loading */
798
- isLoading = computed(() => this.listResource.isLoading(), ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
895
+ isLoading = computed(() => this._listResource?.isLoading() ?? false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
799
896
  /** List data array */
800
- data = computed(() => this.listResource.value()?.data ?? [], ...(ngDevMode ? [{ debugName: "data" }] : []));
897
+ data = computed(() => this._listResource?.value()?.data ?? [], ...(ngDevMode ? [{ debugName: "data" }] : []));
801
898
  /** Total count of items */
802
- total = computed(() => this.listResource.value()?.meta?.total ?? 0, ...(ngDevMode ? [{ debugName: "total" }] : []));
899
+ total = computed(() => this._listResource?.value()?.meta?.total ?? 0, ...(ngDevMode ? [{ debugName: "total" }] : []));
803
900
  /** Pagination metadata */
804
- pageInfo = computed(() => this.listResource.value()?.meta, ...(ngDevMode ? [{ debugName: "pageInfo" }] : []));
901
+ pageInfo = computed(() => this._listResource?.value()?.meta, ...(ngDevMode ? [{ debugName: "pageInfo" }] : []));
805
902
  /** Whether there are more pages */
806
903
  hasMore = computed(() => {
807
- const meta = this.listResource.value()?.meta;
904
+ const meta = this._listResource?.value()?.meta;
808
905
  if (!meta)
809
906
  return false;
810
907
  return meta.hasMore ?? (meta.page + 1) * meta.pageSize < meta.total;
@@ -813,15 +910,7 @@ class ApiResourceService {
813
910
  this.moduleApiName = moduleApiName;
814
911
  this.baseUrl = inject(APP_CONFIG).apiBaseUrl + '/' + moduleApiName;
815
912
  this.http = http;
816
- // Create resource that reacts to search and filter changes
817
- this.listResource = resource({ ...(ngDevMode ? { debugName: "listResource" } : {}), params: () => ({
818
- search: this.searchTerm(),
819
- filter: this.filterData(),
820
- }),
821
- loader: async ({ params }) => {
822
- const { search, filter } = params;
823
- return this.fetchAllAsync(search, filter);
824
- } });
913
+ // Resource is now lazy-initialized, not created in constructor
825
914
  }
826
915
  getHttpOptions(endpoint, params) {
827
916
  return {
@@ -835,9 +924,10 @@ class ApiResourceService {
835
924
  // List Management Methods
836
925
  // ==========================================================================
837
926
  /**
838
- * Fetch list data (triggers resource reload)
927
+ * Fetch list data (triggers resource initialization and reload)
839
928
  */
840
929
  fetchList(search = '', filter) {
930
+ this.initListResource();
841
931
  this.searchTerm.set(search);
842
932
  if (filter) {
843
933
  this.filterData.update((prev) => ({ ...prev, ...filter }));
@@ -847,12 +937,14 @@ class ApiResourceService {
847
937
  * Update pagination
848
938
  */
849
939
  setPagination(pagination) {
940
+ this.initListResource();
850
941
  this.filterData.update((prev) => ({ ...prev, pagination }));
851
942
  }
852
943
  /**
853
944
  * Go to next page
854
945
  */
855
946
  nextPage() {
947
+ this.initListResource();
856
948
  this.filterData.update((prev) => ({
857
949
  ...prev,
858
950
  pagination: {
@@ -865,6 +957,7 @@ class ApiResourceService {
865
957
  * Reset to first page
866
958
  */
867
959
  resetPagination() {
960
+ this.initListResource();
868
961
  this.filterData.update((prev) => ({
869
962
  ...prev,
870
963
  pagination: { currentPage: 0, pageSize: prev.pagination?.pageSize ?? 10 },
@@ -874,7 +967,9 @@ class ApiResourceService {
874
967
  * Reload current data
875
968
  */
876
969
  reload() {
877
- this.listResource.reload();
970
+ if (this._listResource) {
971
+ this._listResource.reload();
972
+ }
878
973
  }
879
974
  // ==========================================================================
880
975
  // Observable-based API Methods (IApiService interface)
@@ -984,8 +1079,8 @@ class IconComponent {
984
1079
  icon = input.required(...(ngDevMode ? [{ debugName: "icon" }] : []));
985
1080
  iconType = input(IconTypeEnum.PRIMENG_ICON, ...(ngDevMode ? [{ debugName: "iconType" }] : []));
986
1081
  IconTypeEnum = IconTypeEnum; // Needed for template reference
987
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: IconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
988
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: IconComponent, isStandalone: true, selector: "lib-icon", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: true, transformFunction: null }, iconType: { classPropertyName: "iconType", publicName: "iconType", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
1082
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: IconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1083
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: IconComponent, isStandalone: true, selector: "lib-icon", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: true, transformFunction: null }, iconType: { classPropertyName: "iconType", publicName: "iconType", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
989
1084
  @if(icon()){ @if(iconType()==IconTypeEnum.PRIMENG_ICON){
990
1085
  <i [ngClass]="icon()"></i>
991
1086
  }@else if(iconType()==IconTypeEnum.IMAGE_FILE_LINK){
@@ -995,7 +1090,7 @@ class IconComponent {
995
1090
  }@else{ I } }
996
1091
  `, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: IsEmptyImageDirective, selector: "img", inputs: ["src"] }] });
997
1092
  }
998
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: IconComponent, decorators: [{
1093
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: IconComponent, decorators: [{
999
1094
  type: Component,
1000
1095
  args: [{
1001
1096
  selector: 'lib-icon',
@@ -1109,10 +1204,10 @@ class BaseFormControl {
1109
1204
  this.onTouched();
1110
1205
  }
1111
1206
  }
1112
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BaseFormControl, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1113
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.0", type: BaseFormControl, isStandalone: true, inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange", touched: "touchedChange" }, ngImport: i0 });
1207
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: BaseFormControl, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1208
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.3", type: BaseFormControl, isStandalone: true, inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange", touched: "touchedChange" }, ngImport: i0 });
1114
1209
  }
1115
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: BaseFormControl, decorators: [{
1210
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: BaseFormControl, decorators: [{
1116
1211
  type: Directive
1117
1212
  }], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }] } });
1118
1213
  /**
@@ -1189,8 +1284,6 @@ class LazyMultiSelectComponent extends BaseFormControl {
1189
1284
  })), { initialValue: this.searchTerm() });
1190
1285
  });
1191
1286
  }
1192
- // Signal to toggle panel
1193
- scrollTargetEl = null;
1194
1287
  onScrollBound = this.onScroll.bind(this);
1195
1288
  multiScrollContainer = viewChild.required('multiScrollContainer');
1196
1289
  onScroll(event) {
@@ -1254,10 +1347,10 @@ class LazyMultiSelectComponent extends BaseFormControl {
1254
1347
  event.stopPropagation();
1255
1348
  this.value.set([]);
1256
1349
  }
1257
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: LazyMultiSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1258
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: LazyMultiSelectComponent, isStandalone: true, selector: "lib-lazy-multi-select", inputs: { placeHolder: { classPropertyName: "placeHolder", publicName: "placeHolder", isSignal: true, isRequired: false, transformFunction: null }, isEditMode: { classPropertyName: "isEditMode", publicName: "isEditMode", isSignal: true, isRequired: true, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: true, transformFunction: null }, total: { classPropertyName: "total", publicName: "total", isSignal: true, isRequired: true, transformFunction: null }, pagination: { classPropertyName: "pagination", publicName: "pagination", isSignal: true, isRequired: true, transformFunction: null }, selectDataList: { classPropertyName: "selectDataList", publicName: "selectDataList", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", onSearch: "onSearch", onPagination: "onPagination" }, host: { listeners: { "document:click": "handleDocumentClick($event)" } }, providers: [provideValueAccessor(LazyMultiSelectComponent)], viewQueries: [{ propertyName: "multiScrollContainer", first: true, predicate: ["multiScrollContainer"], descendants: true, isSignal: true }, { propertyName: "pSelectRef", first: true, predicate: ["pSelect"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"p-select w-full\" #pSelect (click)=\"onSelectClick($event)\"\n [class.p-disabled]=\"disabled()\">\n @if(selectedValueDisplay()){\n <span class=\"p-select-label\">{{selectedValueDisplay()}}</span>\n }@else {\n <span class=\"p-select-label p-placeholder\">{{placeHolder()}}</span>\n }\n <span class=\"p-select-clear-icon\" (click)=\"clear($event)\"><i class=\"pi pi-times\"></i></span>\n <div class=\"p-select-dropdown\">\n <span class=\"p-select-dropdown-icon flex items-center\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"\n data-p-icon=\"chevron-down\" class=\"p-multiselect-dropdown-icon p-icon ng-star-inserted\"\n data-pc-section=\"triggericon\" aria-hidden=\"true\" pc75=\"\">\n <path\n d=\"M7.01744 10.398C6.91269 10.3985 6.8089 10.378 6.71215 10.3379C6.61541 10.2977 6.52766 10.2386 6.45405 10.1641L1.13907 4.84913C1.03306 4.69404 0.985221 4.5065 1.00399 4.31958C1.02276 4.13266 1.10693 3.95838 1.24166 3.82747C1.37639 3.69655 1.55301 3.61742 1.74039 3.60402C1.92777 3.59062 2.11386 3.64382 2.26584 3.75424L7.01744 8.47394L11.769 3.75424C11.9189 3.65709 12.097 3.61306 12.2748 3.62921C12.4527 3.64535 12.6199 3.72073 12.7498 3.84328C12.8797 3.96582 12.9647 4.12842 12.9912 4.30502C13.0177 4.48162 12.9841 4.662 12.8958 4.81724L7.58083 10.1322C7.50996 10.2125 7.42344 10.2775 7.32656 10.3232C7.22968 10.3689 7.12449 10.3944 7.01744 10.398Z\"\n fill=\"currentColor\"></path>\n </svg>\n </span>\n </div>\n @if(openOptions()){\n <div class=\"p-select-overlay\" (click)=\"onOverlayClick($event)\">\n <div class=\"p-select-header flex flex-row gap-2 items-center\">\n <p-checkbox binary=\"true\" (onChange)=\"changeSelectAll($event)\" [ngModel]=\"isSelectAll()\" [disabled]=\"disabled()\"/>\n <input type=\"text\" pInputText class=\"w-full\" [ngModel]=\"searchTerm()\"\n (ngModelChange)=\"searchTerm.set($event)\" [ngModelOptions]=\"{ standalone: true }\"\n placeholder=\"Search...\" />\n </div>\n <div class=\"p-select-list-container\" (scroll)=\"onScroll($event)\">\n <ul class=\"p-select-list\">\n @for (data of selectDataList(); track key(data); let i = $index) {\n <li class=\"p-select-option flex flex-row gap-2 items-center\"\n [ngClass]=\"{ 'p-select-option-selected': isSelected(data) }\">\n <p-checkbox binary=\"true\" (onChange)=\"selectValue($event,data)\" [ngModel]=\"isSelected(data)\" [disabled]=\"disabled()\" />\n <span>{{data.label}}</span>\n </li>\n }\n </ul>\n </div>\n </div>\n }\n</div>", styles: [".p-select-overlay{top:33px;z-index:1004;transform-origin:center top;margin-top:2px}.p-select-option:hover{background:var(--p-select-option-focus-background);color:var(--p-select-option-focus-color)}.p-select-list-container{max-height:200px}.p-select-option.p-select-option-selected{background:var(--p-select-option-selected-background);color:var(--p-select-option-selected-color)}.p-select-option.p-select-option-selected:hover{background:var(--p-select-option-selected-focus-background);color:var(--p-select-option-selected-focus-color)}\n"], dependencies: [{ kind: "ngmodule", type: PrimeModule }, { kind: "directive", type: i1$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "component", type: i2.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["hostName", "value", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "inputStyle", "styleClass", "inputClass", "indeterminate", "formControl", "checkboxIcon", "readonly", "autofocus", "trueValue", "falseValue", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1350
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: LazyMultiSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1351
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: LazyMultiSelectComponent, isStandalone: true, selector: "lib-lazy-multi-select", inputs: { placeHolder: { classPropertyName: "placeHolder", publicName: "placeHolder", isSignal: true, isRequired: false, transformFunction: null }, isEditMode: { classPropertyName: "isEditMode", publicName: "isEditMode", isSignal: true, isRequired: true, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: true, transformFunction: null }, total: { classPropertyName: "total", publicName: "total", isSignal: true, isRequired: true, transformFunction: null }, pagination: { classPropertyName: "pagination", publicName: "pagination", isSignal: true, isRequired: true, transformFunction: null }, selectDataList: { classPropertyName: "selectDataList", publicName: "selectDataList", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", onSearch: "onSearch", onPagination: "onPagination" }, host: { listeners: { "document:click": "handleDocumentClick($event)" } }, providers: [provideValueAccessor(LazyMultiSelectComponent)], viewQueries: [{ propertyName: "multiScrollContainer", first: true, predicate: ["multiScrollContainer"], descendants: true, isSignal: true }, { propertyName: "pSelectRef", first: true, predicate: ["pSelect"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"p-select w-full\" #pSelect (click)=\"onSelectClick($event)\"\n [class.p-disabled]=\"disabled()\">\n @if(selectedValueDisplay()){\n <span class=\"p-select-label\">{{selectedValueDisplay()}}</span>\n }@else {\n <span class=\"p-select-label p-placeholder\">{{placeHolder()}}</span>\n }\n <span class=\"p-select-clear-icon\" (click)=\"clear($event)\"><i class=\"pi pi-times\"></i></span>\n <div class=\"p-select-dropdown\">\n <span class=\"p-select-dropdown-icon flex items-center\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"\n data-p-icon=\"chevron-down\" class=\"p-multiselect-dropdown-icon p-icon ng-star-inserted\"\n data-pc-section=\"triggericon\" aria-hidden=\"true\" pc75=\"\">\n <path\n d=\"M7.01744 10.398C6.91269 10.3985 6.8089 10.378 6.71215 10.3379C6.61541 10.2977 6.52766 10.2386 6.45405 10.1641L1.13907 4.84913C1.03306 4.69404 0.985221 4.5065 1.00399 4.31958C1.02276 4.13266 1.10693 3.95838 1.24166 3.82747C1.37639 3.69655 1.55301 3.61742 1.74039 3.60402C1.92777 3.59062 2.11386 3.64382 2.26584 3.75424L7.01744 8.47394L11.769 3.75424C11.9189 3.65709 12.097 3.61306 12.2748 3.62921C12.4527 3.64535 12.6199 3.72073 12.7498 3.84328C12.8797 3.96582 12.9647 4.12842 12.9912 4.30502C13.0177 4.48162 12.9841 4.662 12.8958 4.81724L7.58083 10.1322C7.50996 10.2125 7.42344 10.2775 7.32656 10.3232C7.22968 10.3689 7.12449 10.3944 7.01744 10.398Z\"\n fill=\"currentColor\"></path>\n </svg>\n </span>\n </div>\n @if(openOptions()){\n <div class=\"p-select-overlay\" (click)=\"onOverlayClick($event)\">\n <div class=\"p-select-header flex flex-row gap-2 items-center\">\n <p-checkbox binary=\"true\" (onChange)=\"changeSelectAll($event)\" [ngModel]=\"isSelectAll()\" [disabled]=\"disabled()\"/>\n <input type=\"text\" pInputText class=\"w-full\" [ngModel]=\"searchTerm()\"\n (ngModelChange)=\"searchTerm.set($event)\" [ngModelOptions]=\"{ standalone: true }\"\n placeholder=\"Search...\" />\n </div>\n <div class=\"p-select-list-container\" (scroll)=\"onScroll($event)\">\n <ul class=\"p-select-list\">\n @for (data of selectDataList(); track key(data); let i = $index) {\n <li class=\"p-select-option flex flex-row gap-2 items-center\"\n [ngClass]=\"{ 'p-select-option-selected': isSelected(data) }\">\n <p-checkbox binary=\"true\" (onChange)=\"selectValue($event,data)\" [ngModel]=\"isSelected(data)\" [disabled]=\"disabled()\" />\n <span>{{data.label}}</span>\n </li>\n }\n </ul>\n </div>\n </div>\n }\n</div>", styles: [".p-select-overlay{top:33px;z-index:1004;transform-origin:center top;margin-top:2px}.p-select-option:hover{background:var(--p-select-option-focus-background);color:var(--p-select-option-focus-color)}.p-select-list-container{max-height:200px}.p-select-option.p-select-option-selected{background:var(--p-select-option-selected-background);color:var(--p-select-option-selected-color)}.p-select-option.p-select-option-selected:hover{background:var(--p-select-option-selected-focus-background);color:var(--p-select-option-selected-focus-color)}\n"], dependencies: [{ kind: "ngmodule", type: PrimeModule }, { kind: "directive", type: i1$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "component", type: i2.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["hostName", "value", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "inputStyle", "styleClass", "inputClass", "indeterminate", "formControl", "checkboxIcon", "readonly", "autofocus", "trueValue", "falseValue", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }, { kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1259
1352
  }
1260
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: LazyMultiSelectComponent, decorators: [{
1353
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: LazyMultiSelectComponent, decorators: [{
1261
1354
  type: Component,
1262
1355
  args: [{ selector: 'lib-lazy-multi-select', imports: [PrimeModule, AngularModule], changeDetection: ChangeDetectionStrategy.OnPush, providers: [provideValueAccessor(LazyMultiSelectComponent)], template: "<div class=\"p-select w-full\" #pSelect (click)=\"onSelectClick($event)\"\n [class.p-disabled]=\"disabled()\">\n @if(selectedValueDisplay()){\n <span class=\"p-select-label\">{{selectedValueDisplay()}}</span>\n }@else {\n <span class=\"p-select-label p-placeholder\">{{placeHolder()}}</span>\n }\n <span class=\"p-select-clear-icon\" (click)=\"clear($event)\"><i class=\"pi pi-times\"></i></span>\n <div class=\"p-select-dropdown\">\n <span class=\"p-select-dropdown-icon flex items-center\">\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"\n data-p-icon=\"chevron-down\" class=\"p-multiselect-dropdown-icon p-icon ng-star-inserted\"\n data-pc-section=\"triggericon\" aria-hidden=\"true\" pc75=\"\">\n <path\n d=\"M7.01744 10.398C6.91269 10.3985 6.8089 10.378 6.71215 10.3379C6.61541 10.2977 6.52766 10.2386 6.45405 10.1641L1.13907 4.84913C1.03306 4.69404 0.985221 4.5065 1.00399 4.31958C1.02276 4.13266 1.10693 3.95838 1.24166 3.82747C1.37639 3.69655 1.55301 3.61742 1.74039 3.60402C1.92777 3.59062 2.11386 3.64382 2.26584 3.75424L7.01744 8.47394L11.769 3.75424C11.9189 3.65709 12.097 3.61306 12.2748 3.62921C12.4527 3.64535 12.6199 3.72073 12.7498 3.84328C12.8797 3.96582 12.9647 4.12842 12.9912 4.30502C13.0177 4.48162 12.9841 4.662 12.8958 4.81724L7.58083 10.1322C7.50996 10.2125 7.42344 10.2775 7.32656 10.3232C7.22968 10.3689 7.12449 10.3944 7.01744 10.398Z\"\n fill=\"currentColor\"></path>\n </svg>\n </span>\n </div>\n @if(openOptions()){\n <div class=\"p-select-overlay\" (click)=\"onOverlayClick($event)\">\n <div class=\"p-select-header flex flex-row gap-2 items-center\">\n <p-checkbox binary=\"true\" (onChange)=\"changeSelectAll($event)\" [ngModel]=\"isSelectAll()\" [disabled]=\"disabled()\"/>\n <input type=\"text\" pInputText class=\"w-full\" [ngModel]=\"searchTerm()\"\n (ngModelChange)=\"searchTerm.set($event)\" [ngModelOptions]=\"{ standalone: true }\"\n placeholder=\"Search...\" />\n </div>\n <div class=\"p-select-list-container\" (scroll)=\"onScroll($event)\">\n <ul class=\"p-select-list\">\n @for (data of selectDataList(); track key(data); let i = $index) {\n <li class=\"p-select-option flex flex-row gap-2 items-center\"\n [ngClass]=\"{ 'p-select-option-selected': isSelected(data) }\">\n <p-checkbox binary=\"true\" (onChange)=\"selectValue($event,data)\" [ngModel]=\"isSelected(data)\" [disabled]=\"disabled()\" />\n <span>{{data.label}}</span>\n </li>\n }\n </ul>\n </div>\n </div>\n }\n</div>", styles: [".p-select-overlay{top:33px;z-index:1004;transform-origin:center top;margin-top:2px}.p-select-option:hover{background:var(--p-select-option-focus-background);color:var(--p-select-option-focus-color)}.p-select-list-container{max-height:200px}.p-select-option.p-select-option-selected{background:var(--p-select-option-selected-background);color:var(--p-select-option-selected-color)}.p-select-option.p-select-option-selected:hover{background:var(--p-select-option-selected-focus-background);color:var(--p-select-option-selected-focus-color)}\n"] }]
1263
1356
  }], ctorParameters: () => [], propDecorators: { placeHolder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeHolder", required: false }] }], isEditMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "isEditMode", required: true }] }], isLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLoading", required: true }] }], total: [{ type: i0.Input, args: [{ isSignal: true, alias: "total", required: true }] }], pagination: [{ type: i0.Input, args: [{ isSignal: true, alias: "pagination", required: true }] }], selectDataList: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectDataList", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], onSearch: [{ type: i0.Output, args: ["onSearch"] }], onPagination: [{ type: i0.Output, args: ["onPagination"] }], multiScrollContainer: [{ type: i0.ViewChild, args: ['multiScrollContainer', { isSignal: true }] }], pSelectRef: [{ type: i0.ViewChild, args: ['pSelect', { isSignal: true }] }], handleDocumentClick: [{
@@ -1331,9 +1424,6 @@ class LazySelectComponent extends BaseFormControl {
1331
1424
  target.addEventListener('scroll', this.onScrollBound);
1332
1425
  this.scrollTargetEl = target;
1333
1426
  }
1334
- else {
1335
- console.warn('.p-select-list-container not found after panel show');
1336
- }
1337
1427
  }, 0);
1338
1428
  }
1339
1429
  else {
@@ -1346,10 +1436,10 @@ class LazySelectComponent extends BaseFormControl {
1346
1436
  onBlur() {
1347
1437
  this.markAsTouched();
1348
1438
  }
1349
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: LazySelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1350
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.1.0", type: LazySelectComponent, isStandalone: true, selector: "lib-lazy-select", inputs: { placeHolder: { classPropertyName: "placeHolder", publicName: "placeHolder", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: true, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: true, transformFunction: null }, isEditMode: { classPropertyName: "isEditMode", publicName: "isEditMode", isSignal: true, isRequired: true, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: true, transformFunction: null }, total: { classPropertyName: "total", publicName: "total", isSignal: true, isRequired: true, transformFunction: null }, pagination: { classPropertyName: "pagination", publicName: "pagination", isSignal: true, isRequired: true, transformFunction: null }, selectDataList: { classPropertyName: "selectDataList", publicName: "selectDataList", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", onSearch: "onSearch", onPagination: "onPagination" }, providers: [provideValueAccessor(LazySelectComponent)], viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div #scrollContainer class=\"lib-scroll-container\">\n <p-select\n [options]=\"selectDataList()\"\n [(ngModel)]=\"value\"\n [optionLabel]=\"optionLabel()\"\n [optionValue]=\"optionValue()\"\n [filter]=\"true\"\n [showClear]=\"true\"\n [placeholder]=\"placeHolder()\"\n [disabled]=\"disabled()\"\n class=\"w-full\"\n appEditModeElementChanger\n [isEditMode]=\"isEditMode()\"\n (click)=\"showPanel()\"\n (onBlur)=\"onBlur()\">\n <ng-template let-filter #filter>\n <input\n pInputText\n [ngModel]=\"searchTerm()\"\n (ngModelChange)=\"searchTerm.set($event)\"\n [ngModelOptions]=\"{standalone:true}\"\n class=\"w-full\" />\n </ng-template>\n <ng-template #selectedItem let-selectedOption>\n {{ selectedOption[optionLabel()] }}\n </ng-template>\n <ng-template let-item #item>\n {{ item[optionLabel()] }}\n </ng-template>\n </p-select>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: PrimeModule }, { kind: "directive", type: i1$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "component", type: i3.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "directive", type: EditModeElementChangerDirective, selector: "[appEditModeElementChanger]", inputs: ["isEditMode"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1439
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: LazySelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1440
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.1.3", type: LazySelectComponent, isStandalone: true, selector: "lib-lazy-select", inputs: { placeHolder: { classPropertyName: "placeHolder", publicName: "placeHolder", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: true, transformFunction: null }, optionValue: { classPropertyName: "optionValue", publicName: "optionValue", isSignal: true, isRequired: true, transformFunction: null }, isEditMode: { classPropertyName: "isEditMode", publicName: "isEditMode", isSignal: true, isRequired: true, transformFunction: null }, isLoading: { classPropertyName: "isLoading", publicName: "isLoading", isSignal: true, isRequired: true, transformFunction: null }, total: { classPropertyName: "total", publicName: "total", isSignal: true, isRequired: true, transformFunction: null }, pagination: { classPropertyName: "pagination", publicName: "pagination", isSignal: true, isRequired: true, transformFunction: null }, selectDataList: { classPropertyName: "selectDataList", publicName: "selectDataList", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", onSearch: "onSearch", onPagination: "onPagination" }, providers: [provideValueAccessor(LazySelectComponent)], viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div #scrollContainer class=\"lib-scroll-container\">\n <p-select\n [options]=\"selectDataList()\"\n [(ngModel)]=\"value\"\n [optionLabel]=\"optionLabel()\"\n [optionValue]=\"optionValue()\"\n [filter]=\"true\"\n [showClear]=\"true\"\n [placeholder]=\"placeHolder()\"\n [disabled]=\"disabled()\"\n class=\"w-full\"\n appEditModeElementChanger\n [isEditMode]=\"isEditMode()\"\n (click)=\"showPanel()\"\n (onBlur)=\"onBlur()\">\n <ng-template let-filter #filter>\n <input\n pInputText\n [ngModel]=\"searchTerm()\"\n (ngModelChange)=\"searchTerm.set($event)\"\n [ngModelOptions]=\"{standalone:true}\"\n class=\"w-full\" />\n </ng-template>\n <ng-template #selectedItem let-selectedOption>\n {{ selectedOption[optionLabel()] }}\n </ng-template>\n <ng-template let-item #item>\n {{ item[optionLabel()] }}\n </ng-template>\n </p-select>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: PrimeModule }, { kind: "directive", type: i1$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "component", type: i3.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "directive", type: EditModeElementChangerDirective, selector: "[appEditModeElementChanger]", inputs: ["isEditMode"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1351
1441
  }
1352
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: LazySelectComponent, decorators: [{
1442
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: LazySelectComponent, decorators: [{
1353
1443
  type: Component,
1354
1444
  args: [{ selector: 'lib-lazy-select', imports: [
1355
1445
  AngularModule,
@@ -1412,7 +1502,1207 @@ const USER_PERMISSION_PROVIDER = new InjectionToken('USER_PERMISSION_PROVIDER',
1412
1502
  throw new Error('USER_PERMISSION_PROVIDER not configured. Please provide an implementation in app.config.ts');
1413
1503
  },
1414
1504
  });
1505
+ /**
1506
+ * Auth State Provider Token
1507
+ *
1508
+ * Provides auth state access for feature packages (form-builder, etc.)
1509
+ */
1510
+ const AUTH_STATE_PROVIDER = new InjectionToken('AUTH_STATE_PROVIDER', {
1511
+ providedIn: 'root',
1512
+ factory: () => {
1513
+ throw new Error('AUTH_STATE_PROVIDER not configured. Please provide an implementation in app.config.ts');
1514
+ },
1515
+ });
1516
+
1517
+ const DEFAULT_PAGE_SIZE$2 = 20;
1518
+ /**
1519
+ * User Select Component - Single user selection with lazy loading.
1520
+ *
1521
+ * Uses USER_PROVIDER internally by default, or accepts custom `loadUsers` function.
1522
+ *
1523
+ * Features:
1524
+ * - Search with debouncing (handled by lazy-select)
1525
+ * - Infinite scroll pagination
1526
+ * - Filter active users by default (configurable)
1527
+ * - Supports additional filters via `additionalFilters` input
1528
+ *
1529
+ * @example
1530
+ * ```html
1531
+ * <!-- Simple usage - uses USER_PROVIDER internally -->
1532
+ * <lib-user-select
1533
+ * [(value)]="selectedUserId"
1534
+ * [isEditMode]="true"
1535
+ * />
1536
+ *
1537
+ * <!-- With custom loadUsers function -->
1538
+ * <lib-user-select
1539
+ * [(value)]="selectedUserId"
1540
+ * [isEditMode]="true"
1541
+ * [loadUsers]="customLoadUsers"
1542
+ * />
1543
+ * ```
1544
+ */
1545
+ class UserSelectComponent {
1546
+ destroyRef = inject(DestroyRef);
1547
+ userProvider = inject(USER_PROVIDER);
1548
+ abortController = null;
1549
+ // Optional: custom function to load users (uses USER_PROVIDER if not provided)
1550
+ loadUsers = input(...(ngDevMode ? [undefined, { debugName: "loadUsers" }] : []));
1551
+ // Inputs
1552
+ placeHolder = input('Select User', ...(ngDevMode ? [{ debugName: "placeHolder" }] : []));
1553
+ isEditMode = input.required(...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
1554
+ filterActive = input(true, ...(ngDevMode ? [{ debugName: "filterActive" }] : []));
1555
+ additionalFilters = input({}, ...(ngDevMode ? [{ debugName: "additionalFilters" }] : []));
1556
+ pageSize = input(DEFAULT_PAGE_SIZE$2, ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
1557
+ // Two-way bound value
1558
+ value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
1559
+ // Outputs
1560
+ userSelected = output();
1561
+ onError = output();
1562
+ // Internal state
1563
+ isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
1564
+ users = signal([], ...(ngDevMode ? [{ debugName: "users" }] : []));
1565
+ total = signal(undefined, ...(ngDevMode ? [{ debugName: "total" }] : []));
1566
+ pagination = signal({ pageSize: DEFAULT_PAGE_SIZE$2, currentPage: 0 }, ...(ngDevMode ? [{ debugName: "pagination" }] : []));
1567
+ searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
1568
+ // Computed dropdown data
1569
+ dropdownUsers = computed(() => this.users().map((user) => ({
1570
+ label: user.name || user.email,
1571
+ value: user.id,
1572
+ })), ...(ngDevMode ? [{ debugName: "dropdownUsers" }] : []));
1573
+ constructor() {
1574
+ // Cleanup on destroy
1575
+ this.destroyRef.onDestroy(() => {
1576
+ this.abortController?.abort();
1577
+ });
1578
+ // Update page size from input
1579
+ effect(() => {
1580
+ const size = this.pageSize();
1581
+ untracked(() => {
1582
+ this.pagination.update((p) => ({ ...p, pageSize: size }));
1583
+ });
1584
+ });
1585
+ // Load initial users after render
1586
+ afterNextRender(() => {
1587
+ this.fetchUsers();
1588
+ });
1589
+ // Emit selected user when value changes
1590
+ effect(() => {
1591
+ const selectedId = this.value();
1592
+ const users = this.users();
1593
+ untracked(() => {
1594
+ if (selectedId) {
1595
+ const user = users.find((u) => u.id === selectedId);
1596
+ this.userSelected.emit(user ?? null);
1597
+ }
1598
+ else {
1599
+ this.userSelected.emit(null);
1600
+ }
1601
+ });
1602
+ });
1603
+ }
1604
+ handleSearch(search) {
1605
+ this.searchTerm.set(search);
1606
+ this.pagination.update((p) => ({ ...p, currentPage: 0 }));
1607
+ this.users.set([]);
1608
+ this.fetchUsers();
1609
+ }
1610
+ handlePagination(pagination) {
1611
+ this.pagination.set(pagination);
1612
+ this.fetchUsers(true);
1613
+ }
1614
+ async fetchUsers(append = false) {
1615
+ if (this.isLoading())
1616
+ return;
1617
+ // Cancel previous request
1618
+ this.abortController?.abort();
1619
+ this.abortController = new AbortController();
1620
+ this.isLoading.set(true);
1621
+ try {
1622
+ const pag = this.pagination();
1623
+ const filter = {
1624
+ page: pag.currentPage,
1625
+ pageSize: pag.pageSize,
1626
+ search: this.searchTerm(),
1627
+ ...this.additionalFilters(),
1628
+ };
1629
+ // Use custom loadUsers if provided, otherwise use USER_PROVIDER
1630
+ const customLoadUsers = this.loadUsers();
1631
+ const response = await firstValueFrom(customLoadUsers
1632
+ ? customLoadUsers(filter)
1633
+ : this.loadUsersFromProvider(filter));
1634
+ if (response.success && response.data) {
1635
+ if (append) {
1636
+ this.users.update((current) => [...current, ...response.data]);
1637
+ }
1638
+ else {
1639
+ this.users.set(response.data);
1640
+ }
1641
+ this.total.set(response.meta?.total);
1642
+ }
1643
+ }
1644
+ catch (error) {
1645
+ if (error.name !== 'AbortError') {
1646
+ this.onError.emit(error);
1647
+ }
1648
+ }
1649
+ finally {
1650
+ this.isLoading.set(false);
1651
+ }
1652
+ }
1653
+ /** Load users from USER_PROVIDER with active filter */
1654
+ loadUsersFromProvider(filter) {
1655
+ return this.userProvider
1656
+ .getUsers({
1657
+ page: filter.page,
1658
+ pageSize: filter.pageSize,
1659
+ search: filter.search,
1660
+ isActive: this.filterActive() ? true : undefined,
1661
+ })
1662
+ .pipe(map$1((res) => ({
1663
+ ...res,
1664
+ data: res.data?.map((u) => ({
1665
+ id: u.id,
1666
+ name: u.name,
1667
+ email: u.email,
1668
+ })),
1669
+ })));
1670
+ }
1671
+ /** Reload users (useful when filters change externally) */
1672
+ reload() {
1673
+ this.pagination.update((p) => ({ ...p, currentPage: 0 }));
1674
+ this.users.set([]);
1675
+ this.fetchUsers();
1676
+ }
1677
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: UserSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1678
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.3", type: UserSelectComponent, isStandalone: true, selector: "lib-user-select", inputs: { loadUsers: { classPropertyName: "loadUsers", publicName: "loadUsers", isSignal: true, isRequired: false, transformFunction: null }, placeHolder: { classPropertyName: "placeHolder", publicName: "placeHolder", isSignal: true, isRequired: false, transformFunction: null }, isEditMode: { classPropertyName: "isEditMode", publicName: "isEditMode", isSignal: true, isRequired: true, transformFunction: null }, filterActive: { classPropertyName: "filterActive", publicName: "filterActive", isSignal: true, isRequired: false, transformFunction: null }, additionalFilters: { classPropertyName: "additionalFilters", publicName: "additionalFilters", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", userSelected: "userSelected", onError: "onError" }, ngImport: i0, template: `
1679
+ <lib-lazy-select
1680
+ [(value)]="value"
1681
+ [placeHolder]="placeHolder()"
1682
+ [optionLabel]="'label'"
1683
+ [optionValue]="'value'"
1684
+ [isEditMode]="isEditMode()"
1685
+ [isLoading]="isLoading()"
1686
+ [total]="total()"
1687
+ [pagination]="pagination()"
1688
+ [selectDataList]="dropdownUsers()"
1689
+ (onSearch)="handleSearch($event)"
1690
+ (onPagination)="handlePagination($event)"
1691
+ />
1692
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: LazySelectComponent, selector: "lib-lazy-select", inputs: ["placeHolder", "optionLabel", "optionValue", "isEditMode", "isLoading", "total", "pagination", "selectDataList", "value"], outputs: ["valueChange", "onSearch", "onPagination"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1693
+ }
1694
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: UserSelectComponent, decorators: [{
1695
+ type: Component,
1696
+ args: [{
1697
+ selector: 'lib-user-select',
1698
+ standalone: true,
1699
+ imports: [AngularModule, PrimeModule, LazySelectComponent],
1700
+ template: `
1701
+ <lib-lazy-select
1702
+ [(value)]="value"
1703
+ [placeHolder]="placeHolder()"
1704
+ [optionLabel]="'label'"
1705
+ [optionValue]="'value'"
1706
+ [isEditMode]="isEditMode()"
1707
+ [isLoading]="isLoading()"
1708
+ [total]="total()"
1709
+ [pagination]="pagination()"
1710
+ [selectDataList]="dropdownUsers()"
1711
+ (onSearch)="handleSearch($event)"
1712
+ (onPagination)="handlePagination($event)"
1713
+ />
1714
+ `,
1715
+ changeDetection: ChangeDetectionStrategy.OnPush,
1716
+ }]
1717
+ }], ctorParameters: () => [], propDecorators: { loadUsers: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadUsers", required: false }] }], placeHolder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeHolder", required: false }] }], isEditMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "isEditMode", required: true }] }], filterActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterActive", required: false }] }], additionalFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "additionalFilters", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], userSelected: [{ type: i0.Output, args: ["userSelected"] }], onError: [{ type: i0.Output, args: ["onError"] }] } });
1718
+
1719
+ const DEFAULT_PAGE_SIZE$1 = 20;
1720
+ /**
1721
+ * User Multi-Select Component - Multiple user selection with lazy loading.
1722
+ *
1723
+ * Uses USER_PROVIDER internally by default, or accepts custom `loadUsers` function.
1724
+ *
1725
+ * Features:
1726
+ * - Search with debouncing (handled by lazy-multi-select)
1727
+ * - Infinite scroll pagination
1728
+ * - Select all / deselect all
1729
+ * - Filter active users by default (configurable)
1730
+ * - Supports additional filters via `additionalFilters` input
1731
+ *
1732
+ * @example
1733
+ * ```html
1734
+ * <!-- Simple usage - uses USER_PROVIDER internally -->
1735
+ * <lib-user-multi-select
1736
+ * [(value)]="selectedUserIds"
1737
+ * [isEditMode]="true"
1738
+ * />
1739
+ *
1740
+ * <!-- With custom loadUsers function -->
1741
+ * <lib-user-multi-select
1742
+ * [(value)]="selectedUserIds"
1743
+ * [isEditMode]="true"
1744
+ * [loadUsers]="customLoadUsers"
1745
+ * />
1746
+ * ```
1747
+ */
1748
+ class UserMultiSelectComponent {
1749
+ destroyRef = inject(DestroyRef);
1750
+ userProvider = inject(USER_PROVIDER);
1751
+ abortController = null;
1752
+ // Optional: custom function to load users (uses USER_PROVIDER if not provided)
1753
+ loadUsers = input(...(ngDevMode ? [undefined, { debugName: "loadUsers" }] : []));
1754
+ // Inputs
1755
+ placeHolder = input('Select Users', ...(ngDevMode ? [{ debugName: "placeHolder" }] : []));
1756
+ isEditMode = input.required(...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
1757
+ filterActive = input(true, ...(ngDevMode ? [{ debugName: "filterActive" }] : []));
1758
+ additionalFilters = input({}, ...(ngDevMode ? [{ debugName: "additionalFilters" }] : []));
1759
+ pageSize = input(DEFAULT_PAGE_SIZE$1, ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
1760
+ // Two-way bound value
1761
+ value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
1762
+ // Outputs
1763
+ usersSelected = output();
1764
+ onError = output();
1765
+ // Internal state
1766
+ isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
1767
+ users = signal([], ...(ngDevMode ? [{ debugName: "users" }] : []));
1768
+ total = signal(undefined, ...(ngDevMode ? [{ debugName: "total" }] : []));
1769
+ pagination = signal({ pageSize: DEFAULT_PAGE_SIZE$1, currentPage: 0 }, ...(ngDevMode ? [{ debugName: "pagination" }] : []));
1770
+ searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
1771
+ // Computed dropdown data
1772
+ dropdownUsers = computed(() => this.users().map((user) => ({
1773
+ label: user.name || user.email,
1774
+ value: user.id,
1775
+ })), ...(ngDevMode ? [{ debugName: "dropdownUsers" }] : []));
1776
+ constructor() {
1777
+ // Cleanup on destroy
1778
+ this.destroyRef.onDestroy(() => {
1779
+ this.abortController?.abort();
1780
+ });
1781
+ // Update page size from input
1782
+ effect(() => {
1783
+ const size = this.pageSize();
1784
+ untracked(() => {
1785
+ this.pagination.update((p) => ({ ...p, pageSize: size }));
1786
+ });
1787
+ });
1788
+ // Load initial users after render
1789
+ afterNextRender(() => {
1790
+ this.fetchUsers();
1791
+ });
1792
+ // Emit selected users when value changes
1793
+ effect(() => {
1794
+ const selectedIds = this.value() ?? [];
1795
+ const users = this.users();
1796
+ untracked(() => {
1797
+ const selectedUsers = users.filter((u) => selectedIds.includes(u.id));
1798
+ this.usersSelected.emit(selectedUsers);
1799
+ });
1800
+ });
1801
+ }
1802
+ handleSearch(search) {
1803
+ this.searchTerm.set(search);
1804
+ this.pagination.update((p) => ({ ...p, currentPage: 0 }));
1805
+ this.users.set([]);
1806
+ this.fetchUsers();
1807
+ }
1808
+ handlePagination(pagination) {
1809
+ this.pagination.set(pagination);
1810
+ this.fetchUsers(true);
1811
+ }
1812
+ async fetchUsers(append = false) {
1813
+ if (this.isLoading())
1814
+ return;
1815
+ // Cancel previous request
1816
+ this.abortController?.abort();
1817
+ this.abortController = new AbortController();
1818
+ this.isLoading.set(true);
1819
+ try {
1820
+ const pag = this.pagination();
1821
+ const filter = {
1822
+ page: pag.currentPage,
1823
+ pageSize: pag.pageSize,
1824
+ search: this.searchTerm(),
1825
+ ...this.additionalFilters(),
1826
+ };
1827
+ // Use custom loadUsers if provided, otherwise use USER_PROVIDER
1828
+ const customLoadUsers = this.loadUsers();
1829
+ const response = await firstValueFrom(customLoadUsers
1830
+ ? customLoadUsers(filter)
1831
+ : this.loadUsersFromProvider(filter));
1832
+ if (response.success && response.data) {
1833
+ if (append) {
1834
+ this.users.update((current) => [...current, ...response.data]);
1835
+ }
1836
+ else {
1837
+ this.users.set(response.data);
1838
+ }
1839
+ this.total.set(response.meta?.total);
1840
+ }
1841
+ }
1842
+ catch (error) {
1843
+ if (error.name !== 'AbortError') {
1844
+ this.onError.emit(error);
1845
+ }
1846
+ }
1847
+ finally {
1848
+ this.isLoading.set(false);
1849
+ }
1850
+ }
1851
+ /** Load users from USER_PROVIDER with active filter */
1852
+ loadUsersFromProvider(filter) {
1853
+ return this.userProvider
1854
+ .getUsers({
1855
+ page: filter.page,
1856
+ pageSize: filter.pageSize,
1857
+ search: filter.search,
1858
+ isActive: this.filterActive() ? true : undefined,
1859
+ })
1860
+ .pipe(map$1((res) => ({
1861
+ ...res,
1862
+ data: res.data?.map((u) => ({
1863
+ id: u.id,
1864
+ name: u.name,
1865
+ email: u.email,
1866
+ })),
1867
+ })));
1868
+ }
1869
+ /** Reload users (useful when filters change externally) */
1870
+ reload() {
1871
+ this.pagination.update((p) => ({ ...p, currentPage: 0 }));
1872
+ this.users.set([]);
1873
+ this.fetchUsers();
1874
+ }
1875
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: UserMultiSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1876
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.3", type: UserMultiSelectComponent, isStandalone: true, selector: "lib-user-multi-select", inputs: { loadUsers: { classPropertyName: "loadUsers", publicName: "loadUsers", isSignal: true, isRequired: false, transformFunction: null }, placeHolder: { classPropertyName: "placeHolder", publicName: "placeHolder", isSignal: true, isRequired: false, transformFunction: null }, isEditMode: { classPropertyName: "isEditMode", publicName: "isEditMode", isSignal: true, isRequired: true, transformFunction: null }, filterActive: { classPropertyName: "filterActive", publicName: "filterActive", isSignal: true, isRequired: false, transformFunction: null }, additionalFilters: { classPropertyName: "additionalFilters", publicName: "additionalFilters", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", usersSelected: "usersSelected", onError: "onError" }, ngImport: i0, template: `
1877
+ <lib-lazy-multi-select
1878
+ [(value)]="value"
1879
+ [placeHolder]="placeHolder()"
1880
+ [isEditMode]="isEditMode()"
1881
+ [isLoading]="isLoading()"
1882
+ [total]="total()"
1883
+ [pagination]="pagination()"
1884
+ [selectDataList]="dropdownUsers()"
1885
+ (onSearch)="handleSearch($event)"
1886
+ (onPagination)="handlePagination($event)"
1887
+ />
1888
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "ngmodule", type: PrimeModule }, { kind: "component", type: LazyMultiSelectComponent, selector: "lib-lazy-multi-select", inputs: ["placeHolder", "isEditMode", "isLoading", "total", "pagination", "selectDataList", "value"], outputs: ["valueChange", "onSearch", "onPagination"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1889
+ }
1890
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: UserMultiSelectComponent, decorators: [{
1891
+ type: Component,
1892
+ args: [{
1893
+ selector: 'lib-user-multi-select',
1894
+ standalone: true,
1895
+ imports: [AngularModule, PrimeModule, LazyMultiSelectComponent],
1896
+ template: `
1897
+ <lib-lazy-multi-select
1898
+ [(value)]="value"
1899
+ [placeHolder]="placeHolder()"
1900
+ [isEditMode]="isEditMode()"
1901
+ [isLoading]="isLoading()"
1902
+ [total]="total()"
1903
+ [pagination]="pagination()"
1904
+ [selectDataList]="dropdownUsers()"
1905
+ (onSearch)="handleSearch($event)"
1906
+ (onPagination)="handlePagination($event)"
1907
+ />
1908
+ `,
1909
+ changeDetection: ChangeDetectionStrategy.OnPush,
1910
+ }]
1911
+ }], ctorParameters: () => [], propDecorators: { loadUsers: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadUsers", required: false }] }], placeHolder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeHolder", required: false }] }], isEditMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "isEditMode", required: true }] }], filterActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterActive", required: false }] }], additionalFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "additionalFilters", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], usersSelected: [{ type: i0.Output, args: ["usersSelected"] }], onError: [{ type: i0.Output, args: ["onError"] }] } });
1912
+
1913
+ /**
1914
+ * File Uploader Component - Drag & drop file upload with type filtering.
1915
+ *
1916
+ * Pass your own `uploadFile` function - works with any storage API.
1917
+ *
1918
+ * Features:
1919
+ * - Drag & drop support
1920
+ * - File type filtering (images, documents, etc.)
1921
+ * - Upload progress indication
1922
+ * - Multiple file support (optional)
1923
+ * - Image compression options
1924
+ *
1925
+ * @example
1926
+ * ```typescript
1927
+ * // In component
1928
+ * readonly uploadService = inject(UploadService);
1929
+ *
1930
+ * readonly uploadFile: UploadFileFn = (file, options) =>
1931
+ * this.uploadService.uploadSingleFile(file, options);
1932
+ * ```
1933
+ *
1934
+ * ```html
1935
+ * <!-- Single image upload -->
1936
+ * <lib-file-uploader
1937
+ * [uploadFile]="uploadFile"
1938
+ * [acceptTypes]="['image/*']"
1939
+ * [multiple]="false"
1940
+ * (fileUploaded)="onFileUploaded($event)"
1941
+ * />
1942
+ *
1943
+ * <!-- Multiple document upload -->
1944
+ * <lib-file-uploader
1945
+ * [uploadFile]="uploadFile"
1946
+ * [acceptTypes]="FILE_TYPE_FILTERS.DOCUMENTS"
1947
+ * [multiple]="true"
1948
+ * [maxFiles]="5"
1949
+ * (filesUploaded)="onFilesUploaded($event)"
1950
+ * />
1951
+ * ```
1952
+ */
1953
+ class FileUploaderComponent {
1954
+ messageService = inject(MessageService);
1955
+ // Required: function to upload file
1956
+ uploadFile = input.required(...(ngDevMode ? [{ debugName: "uploadFile" }] : []));
1957
+ // Inputs
1958
+ acceptTypes = input([], ...(ngDevMode ? [{ debugName: "acceptTypes" }] : []));
1959
+ multiple = input(false, ...(ngDevMode ? [{ debugName: "multiple" }] : []));
1960
+ maxFiles = input(10, ...(ngDevMode ? [{ debugName: "maxFiles" }] : []));
1961
+ maxSizeMb = input(10, ...(ngDevMode ? [{ debugName: "maxSizeMb" }] : []));
1962
+ uploadOptions = input({}, ...(ngDevMode ? [{ debugName: "uploadOptions" }] : []));
1963
+ disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
1964
+ showPreview = input(true, ...(ngDevMode ? [{ debugName: "showPreview" }] : []));
1965
+ autoUpload = input(true, ...(ngDevMode ? [{ debugName: "autoUpload" }] : []));
1966
+ // Outputs
1967
+ fileUploaded = output();
1968
+ filesUploaded = output();
1969
+ onError = output();
1970
+ fileSelected = output();
1971
+ // Internal state
1972
+ isUploading = signal(false, ...(ngDevMode ? [{ debugName: "isUploading" }] : []));
1973
+ isDragOver = signal(false, ...(ngDevMode ? [{ debugName: "isDragOver" }] : []));
1974
+ uploadProgress = signal(0, ...(ngDevMode ? [{ debugName: "uploadProgress" }] : []));
1975
+ uploadingFileName = signal('', ...(ngDevMode ? [{ debugName: "uploadingFileName" }] : []));
1976
+ selectedFiles = signal([], ...(ngDevMode ? [{ debugName: "selectedFiles" }] : []));
1977
+ // Computed
1978
+ acceptString = computed(() => getAcceptString(this.acceptTypes()), ...(ngDevMode ? [{ debugName: "acceptString" }] : []));
1979
+ acceptTypesDisplay = computed(() => {
1980
+ const types = this.acceptTypes();
1981
+ if (!types.length)
1982
+ return '';
1983
+ // Check if types match predefined filters
1984
+ const typesStr = JSON.stringify(types);
1985
+ if (typesStr === JSON.stringify(FILE_TYPE_FILTERS.IMAGES))
1986
+ return 'Images';
1987
+ if (typesStr === JSON.stringify(FILE_TYPE_FILTERS.DOCUMENTS))
1988
+ return 'Documents';
1989
+ if (typesStr === JSON.stringify(FILE_TYPE_FILTERS.VIDEOS))
1990
+ return 'Videos';
1991
+ if (typesStr === JSON.stringify(FILE_TYPE_FILTERS.AUDIO))
1992
+ return 'Audio';
1993
+ return types.map(t => t.split('/')[1] || t).join(', ');
1994
+ }, ...(ngDevMode ? [{ debugName: "acceptTypesDisplay" }] : []));
1995
+ onDragOver(event) {
1996
+ event.preventDefault();
1997
+ event.stopPropagation();
1998
+ if (!this.disabled() && !this.isUploading()) {
1999
+ this.isDragOver.set(true);
2000
+ }
2001
+ }
2002
+ onDragLeave(event) {
2003
+ event.preventDefault();
2004
+ event.stopPropagation();
2005
+ this.isDragOver.set(false);
2006
+ }
2007
+ onDrop(event) {
2008
+ event.preventDefault();
2009
+ event.stopPropagation();
2010
+ this.isDragOver.set(false);
2011
+ if (this.disabled() || this.isUploading())
2012
+ return;
2013
+ const files = event.dataTransfer?.files;
2014
+ if (files?.length) {
2015
+ this.handleFiles(Array.from(files));
2016
+ }
2017
+ }
2018
+ onFileSelected(event) {
2019
+ const input = event.target;
2020
+ const files = input.files;
2021
+ if (files?.length) {
2022
+ this.handleFiles(Array.from(files));
2023
+ }
2024
+ // Reset input to allow selecting same file again
2025
+ input.value = '';
2026
+ }
2027
+ handleFiles(files) {
2028
+ // Filter by type
2029
+ const allowedTypes = this.acceptTypes();
2030
+ const validFiles = files.filter(file => {
2031
+ if (!isFileTypeAllowed(file, allowedTypes)) {
2032
+ this.messageService.add({
2033
+ severity: 'warn',
2034
+ summary: 'Invalid File Type',
2035
+ detail: `File type not allowed: ${file.name}`,
2036
+ });
2037
+ return false;
2038
+ }
2039
+ return true;
2040
+ });
2041
+ // Filter by size
2042
+ const maxSize = this.maxSizeMb() * 1024 * 1024;
2043
+ const sizeValidFiles = validFiles.filter(file => {
2044
+ if (file.size > maxSize) {
2045
+ this.messageService.add({
2046
+ severity: 'warn',
2047
+ summary: 'File Too Large',
2048
+ detail: `${file.name} exceeds ${this.maxSizeMb()}MB limit`,
2049
+ });
2050
+ return false;
2051
+ }
2052
+ return true;
2053
+ });
2054
+ // Limit number of files
2055
+ const limitedFiles = this.multiple()
2056
+ ? sizeValidFiles.slice(0, this.maxFiles())
2057
+ : sizeValidFiles.slice(0, 1);
2058
+ if (!limitedFiles.length)
2059
+ return;
2060
+ this.selectedFiles.set(limitedFiles);
2061
+ this.fileSelected.emit(limitedFiles);
2062
+ if (this.autoUpload()) {
2063
+ this.uploadFiles(limitedFiles);
2064
+ }
2065
+ }
2066
+ removeFile(file) {
2067
+ this.selectedFiles.update(files => files.filter(f => f !== file));
2068
+ }
2069
+ async uploadFiles(files) {
2070
+ const filesToUpload = files ?? this.selectedFiles();
2071
+ if (!filesToUpload.length || this.isUploading())
2072
+ return;
2073
+ this.isUploading.set(true);
2074
+ const uploadedFiles = [];
2075
+ try {
2076
+ for (const file of filesToUpload) {
2077
+ this.uploadingFileName.set(file.name);
2078
+ this.uploadProgress.set(0);
2079
+ const response = await firstValueFrom(this.uploadFile()(file, this.uploadOptions()));
2080
+ if (response.success && response.data) {
2081
+ uploadedFiles.push(response.data);
2082
+ this.fileUploaded.emit(response.data);
2083
+ }
2084
+ else {
2085
+ throw new Error(response.message || 'Upload failed');
2086
+ }
2087
+ }
2088
+ this.filesUploaded.emit(uploadedFiles);
2089
+ this.selectedFiles.set([]);
2090
+ this.messageService.add({
2091
+ severity: 'success',
2092
+ summary: 'Upload Complete',
2093
+ detail: `${uploadedFiles.length} file(s) uploaded successfully`,
2094
+ });
2095
+ }
2096
+ catch (error) {
2097
+ this.messageService.add({
2098
+ severity: 'error',
2099
+ summary: 'Upload Failed',
2100
+ detail: error.message || 'Failed to upload file',
2101
+ });
2102
+ this.onError.emit(error);
2103
+ }
2104
+ finally {
2105
+ this.isUploading.set(false);
2106
+ this.uploadingFileName.set('');
2107
+ this.uploadProgress.set(0);
2108
+ }
2109
+ }
2110
+ getFileIcon(file) {
2111
+ return getFileIconClass(file.type);
2112
+ }
2113
+ formatSize(bytes) {
2114
+ const kb = bytes / 1024;
2115
+ if (kb < 1024)
2116
+ return `${kb.toFixed(1)} KB`;
2117
+ const mb = kb / 1024;
2118
+ return `${mb.toFixed(1)} MB`;
2119
+ }
2120
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: FileUploaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2121
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: FileUploaderComponent, isStandalone: true, selector: "lib-file-uploader", inputs: { uploadFile: { classPropertyName: "uploadFile", publicName: "uploadFile", isSignal: true, isRequired: true, transformFunction: null }, acceptTypes: { classPropertyName: "acceptTypes", publicName: "acceptTypes", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, maxFiles: { classPropertyName: "maxFiles", publicName: "maxFiles", isSignal: true, isRequired: false, transformFunction: null }, maxSizeMb: { classPropertyName: "maxSizeMb", publicName: "maxSizeMb", isSignal: true, isRequired: false, transformFunction: null }, uploadOptions: { classPropertyName: "uploadOptions", publicName: "uploadOptions", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, showPreview: { classPropertyName: "showPreview", publicName: "showPreview", isSignal: true, isRequired: false, transformFunction: null }, autoUpload: { classPropertyName: "autoUpload", publicName: "autoUpload", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { fileUploaded: "fileUploaded", filesUploaded: "filesUploaded", onError: "onError", fileSelected: "fileSelected" }, ngImport: i0, template: `
2122
+ <div
2123
+ class="file-uploader"
2124
+ [class.drag-over]="isDragOver()"
2125
+ [class.disabled]="disabled()"
2126
+ (dragover)="onDragOver($event)"
2127
+ (dragleave)="onDragLeave($event)"
2128
+ (drop)="onDrop($event)"
2129
+ >
2130
+ <!-- Upload Area -->
2131
+ <div class="upload-area" (click)="fileInput.click()">
2132
+ @if (isUploading()) {
2133
+ <div class="uploading-state">
2134
+ <i class="pi pi-spin pi-spinner text-4xl text-primary"></i>
2135
+ <p class="mt-2">Uploading {{ uploadingFileName() }}...</p>
2136
+ @if (uploadProgress() > 0) {
2137
+ <p-progressBar [value]="uploadProgress()" [showValue]="true" />
2138
+ }
2139
+ </div>
2140
+ } @else {
2141
+ <div class="idle-state text-center">
2142
+ <i class="pi pi-cloud-upload text-4xl text-primary"></i>
2143
+ <p class="mt-2 mb-1 font-semibold">
2144
+ {{ multiple() ? 'Drop files here or click to upload' : 'Drop file here or click to upload' }}
2145
+ </p>
2146
+ <p class="text-sm text-color-secondary">
2147
+ @if (acceptTypesDisplay()) {
2148
+ Allowed: {{ acceptTypesDisplay() }}
2149
+ } @else {
2150
+ All file types allowed
2151
+ }
2152
+ @if (maxSizeMb()) {
2153
+ (Max {{ maxSizeMb() }}MB)
2154
+ }
2155
+ </p>
2156
+ </div>
2157
+ }
2158
+ </div>
2159
+
2160
+ <!-- Hidden File Input -->
2161
+ <input
2162
+ #fileInput
2163
+ type="file"
2164
+ [accept]="acceptString()"
2165
+ [multiple]="multiple()"
2166
+ [disabled]="disabled() || isUploading()"
2167
+ (change)="onFileSelected($event)"
2168
+ class="hidden"
2169
+ />
2170
+
2171
+ <!-- Selected Files Preview -->
2172
+ @if (selectedFiles().length > 0 && showPreview()) {
2173
+ <div class="selected-files mt-3">
2174
+ @for (file of selectedFiles(); track file.name) {
2175
+ <div class="file-item flex align-items-center gap-2 p-2 border-round surface-border border-1 mb-2">
2176
+ <i [class]="getFileIcon(file)"></i>
2177
+ <span class="flex-1 text-overflow-ellipsis overflow-hidden">{{ file.name }}</span>
2178
+ <span class="text-sm text-color-secondary">{{ formatSize(file.size) }}</span>
2179
+ <button
2180
+ pButton
2181
+ type="button"
2182
+ icon="pi pi-times"
2183
+ class="p-button-text p-button-rounded p-button-sm"
2184
+ (click)="removeFile(file)"
2185
+ [disabled]="isUploading()"
2186
+ ></button>
2187
+ </div>
2188
+ }
2189
+ </div>
2190
+ }
2191
+ </div>
2192
+ `, isInline: true, styles: [".file-uploader{width:100%}.upload-area{border:2px dashed var(--surface-border);border-radius:var(--border-radius);padding:2rem;cursor:pointer;transition:all .2s;background:var(--surface-ground)}.upload-area:hover{border-color:var(--primary-color);background:var(--surface-hover)}.drag-over .upload-area{border-color:var(--primary-color);background:var(--primary-100)}.disabled .upload-area{opacity:.6;cursor:not-allowed}.hidden{display:none}\n"], dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "ngmodule", type: PrimeModule }, { kind: "directive", type: i1$3.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "component", type: i2$1.ProgressBar, selector: "p-progressBar, p-progressbar, p-progress-bar", inputs: ["value", "showValue", "styleClass", "valueStyleClass", "unit", "mode", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2193
+ }
2194
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: FileUploaderComponent, decorators: [{
2195
+ type: Component,
2196
+ args: [{ selector: 'lib-file-uploader', standalone: true, imports: [AngularModule, PrimeModule], template: `
2197
+ <div
2198
+ class="file-uploader"
2199
+ [class.drag-over]="isDragOver()"
2200
+ [class.disabled]="disabled()"
2201
+ (dragover)="onDragOver($event)"
2202
+ (dragleave)="onDragLeave($event)"
2203
+ (drop)="onDrop($event)"
2204
+ >
2205
+ <!-- Upload Area -->
2206
+ <div class="upload-area" (click)="fileInput.click()">
2207
+ @if (isUploading()) {
2208
+ <div class="uploading-state">
2209
+ <i class="pi pi-spin pi-spinner text-4xl text-primary"></i>
2210
+ <p class="mt-2">Uploading {{ uploadingFileName() }}...</p>
2211
+ @if (uploadProgress() > 0) {
2212
+ <p-progressBar [value]="uploadProgress()" [showValue]="true" />
2213
+ }
2214
+ </div>
2215
+ } @else {
2216
+ <div class="idle-state text-center">
2217
+ <i class="pi pi-cloud-upload text-4xl text-primary"></i>
2218
+ <p class="mt-2 mb-1 font-semibold">
2219
+ {{ multiple() ? 'Drop files here or click to upload' : 'Drop file here or click to upload' }}
2220
+ </p>
2221
+ <p class="text-sm text-color-secondary">
2222
+ @if (acceptTypesDisplay()) {
2223
+ Allowed: {{ acceptTypesDisplay() }}
2224
+ } @else {
2225
+ All file types allowed
2226
+ }
2227
+ @if (maxSizeMb()) {
2228
+ (Max {{ maxSizeMb() }}MB)
2229
+ }
2230
+ </p>
2231
+ </div>
2232
+ }
2233
+ </div>
2234
+
2235
+ <!-- Hidden File Input -->
2236
+ <input
2237
+ #fileInput
2238
+ type="file"
2239
+ [accept]="acceptString()"
2240
+ [multiple]="multiple()"
2241
+ [disabled]="disabled() || isUploading()"
2242
+ (change)="onFileSelected($event)"
2243
+ class="hidden"
2244
+ />
2245
+
2246
+ <!-- Selected Files Preview -->
2247
+ @if (selectedFiles().length > 0 && showPreview()) {
2248
+ <div class="selected-files mt-3">
2249
+ @for (file of selectedFiles(); track file.name) {
2250
+ <div class="file-item flex align-items-center gap-2 p-2 border-round surface-border border-1 mb-2">
2251
+ <i [class]="getFileIcon(file)"></i>
2252
+ <span class="flex-1 text-overflow-ellipsis overflow-hidden">{{ file.name }}</span>
2253
+ <span class="text-sm text-color-secondary">{{ formatSize(file.size) }}</span>
2254
+ <button
2255
+ pButton
2256
+ type="button"
2257
+ icon="pi pi-times"
2258
+ class="p-button-text p-button-rounded p-button-sm"
2259
+ (click)="removeFile(file)"
2260
+ [disabled]="isUploading()"
2261
+ ></button>
2262
+ </div>
2263
+ }
2264
+ </div>
2265
+ }
2266
+ </div>
2267
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".file-uploader{width:100%}.upload-area{border:2px dashed var(--surface-border);border-radius:var(--border-radius);padding:2rem;cursor:pointer;transition:all .2s;background:var(--surface-ground)}.upload-area:hover{border-color:var(--primary-color);background:var(--surface-hover)}.drag-over .upload-area{border-color:var(--primary-color);background:var(--primary-100)}.disabled .upload-area{opacity:.6;cursor:not-allowed}.hidden{display:none}\n"] }]
2268
+ }], propDecorators: { uploadFile: [{ type: i0.Input, args: [{ isSignal: true, alias: "uploadFile", required: true }] }], acceptTypes: [{ type: i0.Input, args: [{ isSignal: true, alias: "acceptTypes", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], maxFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFiles", required: false }] }], maxSizeMb: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSizeMb", required: false }] }], uploadOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "uploadOptions", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], showPreview: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPreview", required: false }] }], autoUpload: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoUpload", required: false }] }], fileUploaded: [{ type: i0.Output, args: ["fileUploaded"] }], filesUploaded: [{ type: i0.Output, args: ["filesUploaded"] }], onError: [{ type: i0.Output, args: ["onError"] }], fileSelected: [{ type: i0.Output, args: ["fileSelected"] }] } });
2269
+
2270
+ const DEFAULT_PAGE_SIZE = 20;
2271
+ /**
2272
+ * File Selector Dialog - Browse and select existing files with filtering.
2273
+ *
2274
+ * Pass your own `loadFiles` function - works with any storage API.
2275
+ *
2276
+ * Features:
2277
+ * - Search with debouncing
2278
+ * - File type filtering
2279
+ * - Infinite scroll pagination
2280
+ * - Single or multiple selection
2281
+ * - File preview with icons
2282
+ *
2283
+ * @example
2284
+ * ```typescript
2285
+ * // In component
2286
+ * readonly fileService = inject(FileManagerApiService);
2287
+ *
2288
+ * readonly loadFiles: LoadFilesFn = (filter) =>
2289
+ * this.fileService.getAll(filter.search, {
2290
+ * pagination: { currentPage: filter.page, pageSize: filter.pageSize },
2291
+ * filter: { contentTypes: filter.contentTypes },
2292
+ * }).pipe(
2293
+ * map(res => ({
2294
+ * ...res,
2295
+ * data: res.data?.map(f => ({
2296
+ * id: f.id,
2297
+ * name: f.name,
2298
+ * contentType: f.contentType,
2299
+ * size: f.size,
2300
+ * url: f.url
2301
+ * }))
2302
+ * }))
2303
+ * );
2304
+ * ```
2305
+ *
2306
+ * ```html
2307
+ * <lib-file-selector-dialog
2308
+ * [(visible)]="showFileSelector"
2309
+ * [loadFiles]="loadFiles"
2310
+ * [acceptTypes]="['image/*']"
2311
+ * [multiple]="false"
2312
+ * (fileSelected)="onFileSelected($event)"
2313
+ * />
2314
+ * ```
2315
+ */
2316
+ class FileSelectorDialogComponent {
2317
+ destroyRef = inject(DestroyRef);
2318
+ abortController = null;
2319
+ searchDebounceTimer = null;
2320
+ // Required: function to load files
2321
+ loadFiles = input.required(...(ngDevMode ? [{ debugName: "loadFiles" }] : []));
2322
+ // Inputs
2323
+ header = input('Select File', ...(ngDevMode ? [{ debugName: "header" }] : []));
2324
+ acceptTypes = input([], ...(ngDevMode ? [{ debugName: "acceptTypes" }] : []));
2325
+ multiple = input(false, ...(ngDevMode ? [{ debugName: "multiple" }] : []));
2326
+ maxSelection = input(10, ...(ngDevMode ? [{ debugName: "maxSelection" }] : []));
2327
+ pageSize = input(DEFAULT_PAGE_SIZE, ...(ngDevMode ? [{ debugName: "pageSize" }] : []));
2328
+ // Two-way visibility binding
2329
+ visible = model(false, ...(ngDevMode ? [{ debugName: "visible" }] : []));
2330
+ // Outputs
2331
+ fileSelected = output();
2332
+ filesSelected = output();
2333
+ closed = output();
2334
+ onError = output();
2335
+ // Internal state
2336
+ isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
2337
+ files = signal([], ...(ngDevMode ? [{ debugName: "files" }] : []));
2338
+ selectedFiles = signal([], ...(ngDevMode ? [{ debugName: "selectedFiles" }] : []));
2339
+ total = signal(undefined, ...(ngDevMode ? [{ debugName: "total" }] : []));
2340
+ pagination = signal({ pageSize: DEFAULT_PAGE_SIZE, currentPage: 0 }, ...(ngDevMode ? [{ debugName: "pagination" }] : []));
2341
+ searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
2342
+ // Computed
2343
+ acceptString = computed(() => getAcceptString(this.acceptTypes()), ...(ngDevMode ? [{ debugName: "acceptString" }] : []));
2344
+ constructor() {
2345
+ this.destroyRef.onDestroy(() => {
2346
+ this.abortController?.abort();
2347
+ if (this.searchDebounceTimer) {
2348
+ clearTimeout(this.searchDebounceTimer);
2349
+ }
2350
+ });
2351
+ // Load files when dialog becomes visible
2352
+ effect(() => {
2353
+ const isVisible = this.visible();
2354
+ if (isVisible) {
2355
+ untracked(() => {
2356
+ this.resetState();
2357
+ this.fetchFiles();
2358
+ });
2359
+ }
2360
+ });
2361
+ // Update page size from input
2362
+ effect(() => {
2363
+ const size = this.pageSize();
2364
+ untracked(() => {
2365
+ this.pagination.update((p) => ({ ...p, pageSize: size }));
2366
+ });
2367
+ });
2368
+ }
2369
+ onSearchChange(value) {
2370
+ // Debounce search
2371
+ if (this.searchDebounceTimer) {
2372
+ clearTimeout(this.searchDebounceTimer);
2373
+ }
2374
+ this.searchDebounceTimer = setTimeout(() => {
2375
+ this.searchTerm.set(value);
2376
+ this.pagination.update((p) => ({ ...p, currentPage: 0 }));
2377
+ this.files.set([]);
2378
+ this.fetchFiles();
2379
+ }, 500);
2380
+ }
2381
+ onScroll(event) {
2382
+ const el = event.target;
2383
+ const nearBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - 50;
2384
+ if (nearBottom && !this.isLoading()) {
2385
+ const pag = this.pagination();
2386
+ const nextPage = pag.currentPage + 1;
2387
+ const hasMore = nextPage * pag.pageSize < (this.total() ?? 0);
2388
+ if (hasMore) {
2389
+ this.pagination.update((p) => ({ ...p, currentPage: nextPage }));
2390
+ this.fetchFiles(true);
2391
+ }
2392
+ }
2393
+ }
2394
+ toggleSelection(file) {
2395
+ if (!this.isFileAllowed(file))
2396
+ return;
2397
+ if (this.multiple()) {
2398
+ const selected = this.selectedFiles();
2399
+ const isSelected = selected.some((f) => f.id === file.id);
2400
+ if (isSelected) {
2401
+ this.selectedFiles.update((files) => files.filter((f) => f.id !== file.id));
2402
+ }
2403
+ else if (selected.length < this.maxSelection()) {
2404
+ this.selectedFiles.update((files) => [...files, file]);
2405
+ }
2406
+ }
2407
+ else {
2408
+ this.selectedFiles.set([file]);
2409
+ }
2410
+ }
2411
+ isSelected(file) {
2412
+ return this.selectedFiles().some((f) => f.id === file.id);
2413
+ }
2414
+ isFileAllowed(file) {
2415
+ const allowedTypes = this.acceptTypes();
2416
+ if (!allowedTypes.length)
2417
+ return true;
2418
+ return allowedTypes.some((type) => {
2419
+ if (type.endsWith('/*')) {
2420
+ return file.contentType.startsWith(type.replace('/*', '/'));
2421
+ }
2422
+ return file.contentType === type;
2423
+ });
2424
+ }
2425
+ isImage(file) {
2426
+ return file.contentType.startsWith('image/') && !!file.url;
2427
+ }
2428
+ getFileIcon(file) {
2429
+ return getFileIconClass(file.contentType);
2430
+ }
2431
+ formatSize(size) {
2432
+ return formatFileSize(size);
2433
+ }
2434
+ onCancel() {
2435
+ this.visible.set(false);
2436
+ }
2437
+ onConfirm() {
2438
+ const selected = this.selectedFiles();
2439
+ if (selected.length === 0)
2440
+ return;
2441
+ if (this.multiple()) {
2442
+ this.filesSelected.emit(selected);
2443
+ }
2444
+ else {
2445
+ this.fileSelected.emit(selected[0]);
2446
+ }
2447
+ this.visible.set(false);
2448
+ }
2449
+ onDialogHide() {
2450
+ this.closed.emit();
2451
+ }
2452
+ resetState() {
2453
+ this.files.set([]);
2454
+ this.selectedFiles.set([]);
2455
+ this.searchTerm.set('');
2456
+ this.pagination.set({ pageSize: this.pageSize(), currentPage: 0 });
2457
+ this.total.set(undefined);
2458
+ }
2459
+ async fetchFiles(append = false) {
2460
+ if (this.isLoading())
2461
+ return;
2462
+ this.abortController?.abort();
2463
+ this.abortController = new AbortController();
2464
+ this.isLoading.set(true);
2465
+ try {
2466
+ const pag = this.pagination();
2467
+ const filter = {
2468
+ page: pag.currentPage,
2469
+ pageSize: pag.pageSize,
2470
+ search: this.searchTerm(),
2471
+ contentTypes: this.acceptTypes().length ? this.acceptTypes() : undefined,
2472
+ };
2473
+ const response = await firstValueFrom(this.loadFiles()(filter));
2474
+ if (response.success && response.data) {
2475
+ if (append) {
2476
+ this.files.update((current) => [...current, ...response.data]);
2477
+ }
2478
+ else {
2479
+ this.files.set(response.data);
2480
+ }
2481
+ this.total.set(response.meta?.total);
2482
+ }
2483
+ }
2484
+ catch (error) {
2485
+ if (error.name !== 'AbortError') {
2486
+ this.onError.emit(error);
2487
+ }
2488
+ }
2489
+ finally {
2490
+ this.isLoading.set(false);
2491
+ }
2492
+ }
2493
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: FileSelectorDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2494
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.3", type: FileSelectorDialogComponent, isStandalone: true, selector: "lib-file-selector-dialog", inputs: { loadFiles: { classPropertyName: "loadFiles", publicName: "loadFiles", isSignal: true, isRequired: true, transformFunction: null }, header: { classPropertyName: "header", publicName: "header", isSignal: true, isRequired: false, transformFunction: null }, acceptTypes: { classPropertyName: "acceptTypes", publicName: "acceptTypes", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, maxSelection: { classPropertyName: "maxSelection", publicName: "maxSelection", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { visible: "visibleChange", fileSelected: "fileSelected", filesSelected: "filesSelected", closed: "closed", onError: "onError" }, ngImport: i0, template: `
2495
+ <p-dialog
2496
+ [header]="header()"
2497
+ [(visible)]="visible"
2498
+ [modal]="true"
2499
+ [closable]="true"
2500
+ [draggable]="false"
2501
+ [resizable]="false"
2502
+ [style]="{ width: '800px', maxHeight: '90vh' }"
2503
+ (onHide)="onDialogHide()"
2504
+ >
2505
+ <!-- Search Bar -->
2506
+ <div class="flex gap-2 mb-3">
2507
+ <span class="p-input-icon-left flex-1">
2508
+ <i class="pi pi-search"></i>
2509
+ <input
2510
+ pInputText
2511
+ type="text"
2512
+ [ngModel]="searchTerm()"
2513
+ (ngModelChange)="onSearchChange($event)"
2514
+ placeholder="Search files..."
2515
+ class="w-full"
2516
+ />
2517
+ </span>
2518
+ @if (multiple()) {
2519
+ <span class="text-sm text-color-secondary align-self-center">
2520
+ {{ selectedFiles().length }} selected
2521
+ </span>
2522
+ }
2523
+ </div>
2524
+
2525
+ <!-- File Grid -->
2526
+ <div
2527
+ class="file-grid"
2528
+ #scrollContainer
2529
+ (scroll)="onScroll($event)"
2530
+ >
2531
+ @if (isLoading() && files().length === 0) {
2532
+ <div class="flex justify-content-center p-4">
2533
+ <i class="pi pi-spin pi-spinner text-4xl"></i>
2534
+ </div>
2535
+ } @else if (files().length === 0) {
2536
+ <div class="text-center p-4 text-color-secondary">
2537
+ <i class="pi pi-inbox text-4xl mb-2"></i>
2538
+ <p>No files found</p>
2539
+ </div>
2540
+ } @else {
2541
+ @for (file of files(); track file.id) {
2542
+ <div
2543
+ class="file-card"
2544
+ [class.selected]="isSelected(file)"
2545
+ [class.disabled]="!isFileAllowed(file)"
2546
+ (click)="toggleSelection(file)"
2547
+ >
2548
+ <!-- File Preview -->
2549
+ <div class="file-preview">
2550
+ @if (isImage(file) && file.url) {
2551
+ <img [src]="file.url" [alt]="file.name" class="preview-image" />
2552
+ } @else {
2553
+ <i [class]="getFileIcon(file)" class="preview-icon"></i>
2554
+ }
2555
+ @if (isSelected(file)) {
2556
+ <div class="selected-overlay">
2557
+ <i class="pi pi-check"></i>
2558
+ </div>
2559
+ }
2560
+ </div>
2561
+
2562
+ <!-- File Info -->
2563
+ <div class="file-info">
2564
+ <span class="file-name" [title]="file.name">{{ file.name }}</span>
2565
+ <span class="file-size">{{ formatSize(file.size) }}</span>
2566
+ </div>
2567
+ </div>
2568
+ }
2569
+
2570
+ @if (isLoading()) {
2571
+ <div class="flex justify-content-center p-2 w-full">
2572
+ <i class="pi pi-spin pi-spinner"></i>
2573
+ </div>
2574
+ }
2575
+ }
2576
+ </div>
2577
+
2578
+ <!-- Footer -->
2579
+ <ng-template pTemplate="footer">
2580
+ <button
2581
+ pButton
2582
+ label="Cancel"
2583
+ class="p-button-text"
2584
+ (click)="onCancel()"
2585
+ ></button>
2586
+ <button
2587
+ pButton
2588
+ [label]="multiple() ? 'Select (' + selectedFiles().length + ')' : 'Select'"
2589
+ [disabled]="selectedFiles().length === 0"
2590
+ (click)="onConfirm()"
2591
+ ></button>
2592
+ </ng-template>
2593
+ </p-dialog>
2594
+ `, isInline: true, styles: [".file-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:1rem;max-height:400px;overflow-y:auto;padding:.5rem}.file-card{border:2px solid var(--surface-border);border-radius:var(--border-radius);cursor:pointer;transition:all .2s;overflow:hidden}.file-card:hover:not(.disabled){border-color:var(--primary-color)}.file-card.selected{border-color:var(--primary-color);background:var(--primary-50)}.file-card.disabled{opacity:.5;cursor:not-allowed}.file-preview{position:relative;height:100px;display:flex;align-items:center;justify-content:center;background:var(--surface-ground)}.preview-image{width:100%;height:100%;object-fit:cover}.preview-icon{font-size:3rem;color:var(--text-color-secondary)}.selected-overlay{position:absolute;inset:0;background:rgba(var(--primary-color-rgb),.3);display:flex;align-items:center;justify-content:center}.selected-overlay i{font-size:2rem;color:var(--primary-color);background:#fff;border-radius:50%;padding:.5rem}.file-info{padding:.5rem;text-align:center}.file-name{display:block;font-size:.875rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.file-size{display:block;font-size:.75rem;color:var(--text-color-secondary)}\n"], dependencies: [{ kind: "ngmodule", type: AngularModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: IsEmptyImageDirective, selector: "img", inputs: ["src"] }, { kind: "ngmodule", type: PrimeModule }, { kind: "directive", type: i1$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "directive", type: i4.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i1$3.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "component", type: i6.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2595
+ }
2596
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: FileSelectorDialogComponent, decorators: [{
2597
+ type: Component,
2598
+ args: [{ selector: 'lib-file-selector-dialog', standalone: true, imports: [AngularModule, PrimeModule], template: `
2599
+ <p-dialog
2600
+ [header]="header()"
2601
+ [(visible)]="visible"
2602
+ [modal]="true"
2603
+ [closable]="true"
2604
+ [draggable]="false"
2605
+ [resizable]="false"
2606
+ [style]="{ width: '800px', maxHeight: '90vh' }"
2607
+ (onHide)="onDialogHide()"
2608
+ >
2609
+ <!-- Search Bar -->
2610
+ <div class="flex gap-2 mb-3">
2611
+ <span class="p-input-icon-left flex-1">
2612
+ <i class="pi pi-search"></i>
2613
+ <input
2614
+ pInputText
2615
+ type="text"
2616
+ [ngModel]="searchTerm()"
2617
+ (ngModelChange)="onSearchChange($event)"
2618
+ placeholder="Search files..."
2619
+ class="w-full"
2620
+ />
2621
+ </span>
2622
+ @if (multiple()) {
2623
+ <span class="text-sm text-color-secondary align-self-center">
2624
+ {{ selectedFiles().length }} selected
2625
+ </span>
2626
+ }
2627
+ </div>
2628
+
2629
+ <!-- File Grid -->
2630
+ <div
2631
+ class="file-grid"
2632
+ #scrollContainer
2633
+ (scroll)="onScroll($event)"
2634
+ >
2635
+ @if (isLoading() && files().length === 0) {
2636
+ <div class="flex justify-content-center p-4">
2637
+ <i class="pi pi-spin pi-spinner text-4xl"></i>
2638
+ </div>
2639
+ } @else if (files().length === 0) {
2640
+ <div class="text-center p-4 text-color-secondary">
2641
+ <i class="pi pi-inbox text-4xl mb-2"></i>
2642
+ <p>No files found</p>
2643
+ </div>
2644
+ } @else {
2645
+ @for (file of files(); track file.id) {
2646
+ <div
2647
+ class="file-card"
2648
+ [class.selected]="isSelected(file)"
2649
+ [class.disabled]="!isFileAllowed(file)"
2650
+ (click)="toggleSelection(file)"
2651
+ >
2652
+ <!-- File Preview -->
2653
+ <div class="file-preview">
2654
+ @if (isImage(file) && file.url) {
2655
+ <img [src]="file.url" [alt]="file.name" class="preview-image" />
2656
+ } @else {
2657
+ <i [class]="getFileIcon(file)" class="preview-icon"></i>
2658
+ }
2659
+ @if (isSelected(file)) {
2660
+ <div class="selected-overlay">
2661
+ <i class="pi pi-check"></i>
2662
+ </div>
2663
+ }
2664
+ </div>
2665
+
2666
+ <!-- File Info -->
2667
+ <div class="file-info">
2668
+ <span class="file-name" [title]="file.name">{{ file.name }}</span>
2669
+ <span class="file-size">{{ formatSize(file.size) }}</span>
2670
+ </div>
2671
+ </div>
2672
+ }
2673
+
2674
+ @if (isLoading()) {
2675
+ <div class="flex justify-content-center p-2 w-full">
2676
+ <i class="pi pi-spin pi-spinner"></i>
2677
+ </div>
2678
+ }
2679
+ }
2680
+ </div>
2681
+
2682
+ <!-- Footer -->
2683
+ <ng-template pTemplate="footer">
2684
+ <button
2685
+ pButton
2686
+ label="Cancel"
2687
+ class="p-button-text"
2688
+ (click)="onCancel()"
2689
+ ></button>
2690
+ <button
2691
+ pButton
2692
+ [label]="multiple() ? 'Select (' + selectedFiles().length + ')' : 'Select'"
2693
+ [disabled]="selectedFiles().length === 0"
2694
+ (click)="onConfirm()"
2695
+ ></button>
2696
+ </ng-template>
2697
+ </p-dialog>
2698
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".file-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:1rem;max-height:400px;overflow-y:auto;padding:.5rem}.file-card{border:2px solid var(--surface-border);border-radius:var(--border-radius);cursor:pointer;transition:all .2s;overflow:hidden}.file-card:hover:not(.disabled){border-color:var(--primary-color)}.file-card.selected{border-color:var(--primary-color);background:var(--primary-50)}.file-card.disabled{opacity:.5;cursor:not-allowed}.file-preview{position:relative;height:100px;display:flex;align-items:center;justify-content:center;background:var(--surface-ground)}.preview-image{width:100%;height:100%;object-fit:cover}.preview-icon{font-size:3rem;color:var(--text-color-secondary)}.selected-overlay{position:absolute;inset:0;background:rgba(var(--primary-color-rgb),.3);display:flex;align-items:center;justify-content:center}.selected-overlay i{font-size:2rem;color:var(--primary-color);background:#fff;border-radius:50%;padding:.5rem}.file-info{padding:.5rem;text-align:center}.file-name{display:block;font-size:.875rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.file-size{display:block;font-size:.75rem;color:var(--text-color-secondary)}\n"] }]
2699
+ }], ctorParameters: () => [], propDecorators: { loadFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadFiles", required: true }] }], header: [{ type: i0.Input, args: [{ isSignal: true, alias: "header", required: false }] }], acceptTypes: [{ type: i0.Input, args: [{ isSignal: true, alias: "acceptTypes", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], maxSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSelection", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }, { type: i0.Output, args: ["visibleChange"] }], fileSelected: [{ type: i0.Output, args: ["fileSelected"] }], filesSelected: [{ type: i0.Output, args: ["filesSelected"] }], closed: [{ type: i0.Output, args: ["closed"] }], onError: [{ type: i0.Output, args: ["onError"] }] } });
1415
2700
 
2701
+ /** Log only in dev mode */
2702
+ const devLog = (message) => {
2703
+ if (isDevMode())
2704
+ console.log(message);
2705
+ };
1416
2706
  /**
1417
2707
  * Permission Guard
1418
2708
  *
@@ -1451,14 +2741,14 @@ function permissionGuard(permission, redirectTo = '/') {
1451
2741
  const router = inject(Router);
1452
2742
  // Check if permissions are loaded
1453
2743
  if (!permissionValidator.isPermissionsLoaded()) {
1454
- console.warn('[permissionGuard] Permissions not loaded, denying access to route');
2744
+ devLog('[permissionGuard] Permissions not loaded, denying access to route');
1455
2745
  return router.createUrlTree([redirectTo]);
1456
2746
  }
1457
2747
  const userPermissions = permissionValidator.permissions();
1458
2748
  const hasPermission = evaluatePermission(permission, userPermissions);
1459
2749
  if (!hasPermission) {
1460
2750
  const permissionCode = typeof permission === 'string' ? permission : 'complex-logic';
1461
- console.warn(`[permissionGuard] Access denied - missing permission: ${permissionCode}`);
2751
+ devLog(`[permissionGuard] Access denied - missing permission: ${permissionCode}`);
1462
2752
  return router.createUrlTree([redirectTo]);
1463
2753
  }
1464
2754
  return true;
@@ -1481,18 +2771,18 @@ function anyPermissionGuard(permissions, redirectTo = '/') {
1481
2771
  const router = inject(Router);
1482
2772
  // Validate permissions array
1483
2773
  if (!permissions || permissions.length === 0) {
1484
- console.warn('[anyPermissionGuard] Empty permissions array provided, denying access');
2774
+ devLog('[anyPermissionGuard] Empty permissions array provided, denying access');
1485
2775
  return router.createUrlTree([redirectTo]);
1486
2776
  }
1487
2777
  // Check if permissions are loaded
1488
2778
  if (!permissionValidator.isPermissionsLoaded()) {
1489
- console.warn('[anyPermissionGuard] Permissions not loaded, denying access to route');
2779
+ devLog('[anyPermissionGuard] Permissions not loaded, denying access to route');
1490
2780
  return router.createUrlTree([redirectTo]);
1491
2781
  }
1492
2782
  const userPermissions = permissionValidator.permissions();
1493
2783
  const hasPermission = hasAnyPermission(permissions, userPermissions);
1494
2784
  if (!hasPermission) {
1495
- console.warn(`[anyPermissionGuard] Access denied - missing any of: ${permissions.join(', ')}`);
2785
+ devLog(`[anyPermissionGuard] Access denied - missing any of: ${permissions.join(', ')}`);
1496
2786
  return router.createUrlTree([redirectTo]);
1497
2787
  }
1498
2788
  return true;
@@ -1515,18 +2805,18 @@ function allPermissionsGuard(permissions, redirectTo = '/') {
1515
2805
  const router = inject(Router);
1516
2806
  // Validate permissions array
1517
2807
  if (!permissions || permissions.length === 0) {
1518
- console.warn('[allPermissionsGuard] Empty permissions array provided, denying access');
2808
+ devLog('[allPermissionsGuard] Empty permissions array provided, denying access');
1519
2809
  return router.createUrlTree([redirectTo]);
1520
2810
  }
1521
2811
  // Check if permissions are loaded
1522
2812
  if (!permissionValidator.isPermissionsLoaded()) {
1523
- console.warn('[allPermissionsGuard] Permissions not loaded, denying access to route');
2813
+ devLog('[allPermissionsGuard] Permissions not loaded, denying access to route');
1524
2814
  return router.createUrlTree([redirectTo]);
1525
2815
  }
1526
2816
  const userPermissions = permissionValidator.permissions();
1527
2817
  const hasPermission = hasAllPermissions(permissions, userPermissions);
1528
2818
  if (!hasPermission) {
1529
- console.warn(`[allPermissionsGuard] Access denied - missing all of: ${permissions.join(', ')}`);
2819
+ devLog(`[allPermissionsGuard] Access denied - missing all of: ${permissions.join(', ')}`);
1530
2820
  return router.createUrlTree([redirectTo]);
1531
2821
  }
1532
2822
  return true;
@@ -1539,5 +2829,5 @@ function allPermissionsGuard(permissions, redirectTo = '/') {
1539
2829
  * Generated bundle index. Do not edit.
1540
2830
  */
1541
2831
 
1542
- export { AngularModule, ApiResourceService, ApiResourceService as ApiService, COMPANY_API_PROVIDER, ContactTypeEnum, CookieService, EditModeElementChangerDirective, FileUrlService, HasPermissionDirective, IconComponent, IconTypeEnum, IsEmptyImageDirective, LazyMultiSelectComponent, LazySelectComponent, PermissionValidatorService, PlatformService, PreventDefaultDirective, PrimeModule, USER_PERMISSION_PROVIDER, USER_PROVIDER, allPermissionsGuard, anyPermissionGuard, evaluateLogicNode, evaluatePermission, hasAllPermissions, hasAnyPermission, permissionGuard };
2832
+ export { AUTH_STATE_PROVIDER, AngularModule, ApiResourceService, ApiResourceService as ApiService, COMPANY_API_PROVIDER, ContactTypeEnum, CookieService, EditModeElementChangerDirective, FILE_TYPE_FILTERS, FileSelectorDialogComponent, FileUploaderComponent, FileUrlService, HasPermissionDirective, IconComponent, IconTypeEnum, IsEmptyImageDirective, LazyMultiSelectComponent, LazySelectComponent, PermissionValidatorService, PlatformService, PreventDefaultDirective, PrimeModule, USER_PERMISSION_PROVIDER, USER_PROVIDER, UserMultiSelectComponent, UserSelectComponent, allPermissionsGuard, anyPermissionGuard, evaluateLogicNode, evaluatePermission, formatFileSize, getAcceptString, getFileIconClass, hasAllPermissions, hasAnyPermission, isFileTypeAllowed, permissionGuard };
1543
2833
  //# sourceMappingURL=flusys-ng-shared.mjs.map