@flusys/ng-shared 1.1.0 → 1.2.0-rc.1

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,65 +1,21 @@
1
+ import * as rxjs from 'rxjs';
1
2
  import { Observable } from 'rxjs';
2
3
  import * as _angular_core from '@angular/core';
3
- import { Signal, Injector, ResourceRef, model, ElementRef, DestroyRef, InjectionToken } from '@angular/core';
4
+ import { Signal, PipeTransform, ResourceRef, ResourceStatus, Injector, model, TemplateRef, OnDestroy, ElementRef, DestroyRef, InjectionToken } from '@angular/core';
5
+ import { HttpContextToken, HttpRequest, HttpHandlerFn, HttpEvent, HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
6
+ import * as i3 from '@angular/router';
7
+ import { ResolveFn, CanActivateFn } from '@angular/router';
4
8
  import * as i1 from '@angular/common';
5
9
  import * as i2 from '@angular/forms';
6
10
  import { ControlValueAccessor } from '@angular/forms';
7
- import * as i3 from '@angular/router';
8
- import { CanActivateFn, Router, ActivatedRoute } from '@angular/router';
9
- import * as i1$1 from 'primeng/autocomplete';
10
- import * as i2$1 from 'primeng/avatar';
11
- import * as i3$1 from 'primeng/button';
12
- import * as i4 from 'primeng/card';
13
- import * as i5 from 'primeng/checkbox';
14
- import { CheckboxChangeEvent } from 'primeng/checkbox';
15
- import * as i6 from 'primeng/confirmdialog';
16
- import * as i7 from 'primeng/datepicker';
17
- import * as i8 from 'primeng/dialog';
18
- import * as i9 from 'primeng/divider';
19
- import * as i10 from 'primeng/fileupload';
20
- import * as i11 from 'primeng/iconfield';
21
- import * as i12 from 'primeng/image';
22
- import * as i13 from 'primeng/inputicon';
23
- import * as i14 from 'primeng/inputnumber';
24
- import * as i15 from 'primeng/inputtext';
25
- import * as i16 from 'primeng/listbox';
26
- import * as i17 from 'primeng/multiselect';
27
- import * as i18 from 'primeng/paginator';
28
- import * as i19 from 'primeng/panel';
29
- import * as i20 from 'primeng/password';
30
- import * as i21 from 'primeng/popover';
31
- import * as i22 from 'primeng/progressbar';
32
- import * as i23 from 'primeng/radiobutton';
33
- import * as i24 from 'primeng/ripple';
34
- import * as i25 from 'primeng/selectbutton';
35
- import * as i26 from 'primeng/select';
36
- import * as i27 from 'primeng/skeleton';
37
- import * as i28 from 'primeng/splitbutton';
38
- import * as i29 from 'primeng/steps';
39
- import * as i30 from 'primeng/table';
40
- import * as i31 from 'primeng/tabs';
41
- import * as i32 from 'primeng/tag';
42
- import * as i33 from 'primeng/textarea';
43
- import * as i34 from 'primeng/toast';
44
- import * as i35 from 'primeng/toggleswitch';
45
- import * as i36 from 'primeng/tooltip';
46
- import * as i37 from 'primeng/treetable';
47
11
  import * as _flusys_ng_shared from '@flusys/ng-shared';
48
- import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
12
+ import { ServiceName } from '@flusys/ng-core';
49
13
  import { FormValueControl } from '@angular/forms/signals';
50
- import { MessageService, ConfirmationService } from 'primeng/api';
51
- import * as _flusys_ng_core from '@flusys/ng-core';
14
+ import * as _angular_platform_browser from '@angular/platform-browser';
15
+ import { CheckboxChangeEvent } from '@flusys/ng-ui';
16
+
17
+ declare const SHARED_MESSAGES: Record<string, string>;
52
18
 
53
- /**
54
- * Centralized Permission Codes
55
- *
56
- * Single source of truth for all permission codes used across the application.
57
- * Use these constants instead of hardcoded strings to prevent typos and enable easy refactoring.
58
- *
59
- * Naming Convention: <entity>.<action>
60
- * - entity: The resource being accessed (e.g., user, role, company)
61
- * - action: The operation being performed (create, read, update, delete, assign)
62
- */
63
19
  declare const USER_PERMISSIONS: {
64
20
  readonly CREATE: "user.create";
65
21
  readonly READ: "user.read";
@@ -124,6 +80,9 @@ declare const STORAGE_CONFIG_PERMISSIONS: {
124
80
  readonly UPDATE: "storage-config.update";
125
81
  readonly DELETE: "storage-config.delete";
126
82
  };
83
+ declare const UPLOAD_CONFIG_PERMISSIONS: {
84
+ readonly DELETE: "upload-config.delete";
85
+ };
127
86
  declare const EMAIL_CONFIG_PERMISSIONS: {
128
87
  readonly CREATE: "email-config.create";
129
88
  readonly READ: "email-config.read";
@@ -142,9 +101,42 @@ declare const FORM_PERMISSIONS: {
142
101
  readonly UPDATE: "form.update";
143
102
  readonly DELETE: "form.delete";
144
103
  };
145
- /**
146
- * All permission codes grouped by module
147
- */
104
+ declare const FORM_RESULT_PERMISSIONS: {
105
+ readonly CREATE: "form-result.create";
106
+ readonly READ: "form-result.read";
107
+ readonly UPDATE: "form-result.update";
108
+ readonly DELETE: "form-result.delete";
109
+ };
110
+ declare const EVENT_PERMISSIONS: {
111
+ readonly CREATE: "event.create";
112
+ readonly READ: "event.read";
113
+ readonly UPDATE: "event.update";
114
+ readonly DELETE: "event.delete";
115
+ };
116
+ declare const NOTIFICATION_PERMISSIONS: {
117
+ readonly CREATE: "notification.create";
118
+ readonly READ: "notification.read";
119
+ readonly UPDATE: "notification.update";
120
+ readonly DELETE: "notification.delete";
121
+ };
122
+ declare const LANGUAGE_PERMISSIONS: {
123
+ readonly CREATE: "language.create";
124
+ readonly READ: "language.read";
125
+ readonly UPDATE: "language.update";
126
+ readonly DELETE: "language.delete";
127
+ };
128
+ declare const TRANSLATION_KEY_PERMISSIONS: {
129
+ readonly CREATE: "translation-key.create";
130
+ readonly READ: "translation-key.read";
131
+ readonly UPDATE: "translation-key.update";
132
+ readonly DELETE: "translation-key.delete";
133
+ };
134
+ declare const TRANSLATION_PERMISSIONS: {
135
+ readonly CREATE: "translation.create";
136
+ readonly READ: "translation.read";
137
+ readonly UPDATE: "translation.update";
138
+ readonly DELETE: "translation.delete";
139
+ };
148
140
  declare const PERMISSIONS: {
149
141
  readonly USER: {
150
142
  readonly CREATE: "user.create";
@@ -228,6 +220,42 @@ declare const PERMISSIONS: {
228
220
  readonly UPDATE: "form.update";
229
221
  readonly DELETE: "form.delete";
230
222
  };
223
+ readonly FORM_RESULT: {
224
+ readonly CREATE: "form-result.create";
225
+ readonly READ: "form-result.read";
226
+ readonly UPDATE: "form-result.update";
227
+ readonly DELETE: "form-result.delete";
228
+ };
229
+ readonly EVENT: {
230
+ readonly CREATE: "event.create";
231
+ readonly READ: "event.read";
232
+ readonly UPDATE: "event.update";
233
+ readonly DELETE: "event.delete";
234
+ };
235
+ readonly NOTIFICATION: {
236
+ readonly CREATE: "notification.create";
237
+ readonly READ: "notification.read";
238
+ readonly UPDATE: "notification.update";
239
+ readonly DELETE: "notification.delete";
240
+ };
241
+ readonly LANGUAGE: {
242
+ readonly CREATE: "language.create";
243
+ readonly READ: "language.read";
244
+ readonly UPDATE: "language.update";
245
+ readonly DELETE: "language.delete";
246
+ };
247
+ readonly TRANSLATION_KEY: {
248
+ readonly CREATE: "translation-key.create";
249
+ readonly READ: "translation-key.read";
250
+ readonly UPDATE: "translation-key.update";
251
+ readonly DELETE: "translation-key.delete";
252
+ };
253
+ readonly TRANSLATION: {
254
+ readonly CREATE: "translation.create";
255
+ readonly READ: "translation.read";
256
+ readonly UPDATE: "translation.update";
257
+ readonly DELETE: "translation.delete";
258
+ };
231
259
  };
232
260
  type PermissionCode = (typeof PERMISSIONS)[keyof typeof PERMISSIONS][keyof (typeof PERMISSIONS)[keyof typeof PERMISSIONS]];
233
261
 
@@ -268,12 +296,6 @@ interface IActivatable {
268
296
  interface IOrderable {
269
297
  serial?: number | null;
270
298
  }
271
- /**
272
- * Entity with metadata JSON field
273
- */
274
- interface IMetadata {
275
- metadata?: Record<string, unknown> | null;
276
- }
277
299
  /**
278
300
  * Logged-in user info - matches backend ILoggedUserInfo
279
301
  */
@@ -325,25 +347,6 @@ interface IGroupNode {
325
347
  /** Permission logic tree (discriminated union of action/group) */
326
348
  type ILogicNode = IActionNode | IGroupNode;
327
349
 
328
- interface IPagination {
329
- pageSize: number;
330
- currentPage: number;
331
- }
332
- interface ISort {
333
- [key: string]: 'ASC' | 'DESC';
334
- }
335
- interface IFilter {
336
- [key: string]: string | number | boolean | null | undefined | string[] | number[];
337
- }
338
- interface IFilterData {
339
- filter?: IFilter;
340
- pagination?: IPagination;
341
- select?: string[];
342
- sort?: ISort;
343
- withDeleted?: boolean;
344
- extraKey?: string[];
345
- }
346
-
347
350
  /**
348
351
  * Request metadata added by backend ResponseMetaInterceptor
349
352
  */
@@ -371,20 +374,14 @@ interface IBulkMeta {
371
374
  failed?: number;
372
375
  total?: number;
373
376
  }
374
- /**
375
- * Validation error detail
376
- */
377
- interface IValidationError {
378
- field: string;
379
- message: string;
380
- constraint?: string;
381
- }
382
377
  /**
383
378
  * Single item response (insert, update, get-by-id)
384
379
  */
385
380
  interface ISingleResponse<T> {
386
381
  success: boolean;
387
382
  message: string;
383
+ messageKey?: string;
384
+ messageVariables?: Record<string, unknown>;
388
385
  data?: T;
389
386
  _meta?: IRequestMeta;
390
387
  }
@@ -394,6 +391,8 @@ interface ISingleResponse<T> {
394
391
  interface IListResponse<T> {
395
392
  success: boolean;
396
393
  message: string;
394
+ messageKey?: string;
395
+ messageVariables?: Record<string, unknown>;
397
396
  data?: T[];
398
397
  meta: IPaginationMeta;
399
398
  _meta?: IRequestMeta;
@@ -404,6 +403,8 @@ interface IListResponse<T> {
404
403
  interface IBulkResponse<T> {
405
404
  success: boolean;
406
405
  message: string;
406
+ messageKey?: string;
407
+ messageVariables?: Record<string, unknown>;
407
408
  data?: T[];
408
409
  meta: IBulkMeta;
409
410
  _meta?: IRequestMeta;
@@ -414,89 +415,35 @@ interface IBulkResponse<T> {
414
415
  interface IMessageResponse {
415
416
  success: boolean;
416
417
  message: string;
418
+ messageKey?: string;
419
+ messageVariables?: Record<string, unknown>;
417
420
  _meta?: IRequestMeta;
418
421
  }
419
- /**
420
- * Error response
421
- */
422
- interface IErrorResponse {
423
- success: false;
424
- message: string;
425
- code?: string;
426
- errors?: IValidationError[];
427
- _meta?: IRequestMeta;
428
- }
429
- /**
430
- * Union type for all API responses
431
- */
432
- type ApiResponse<T> = ISingleResponse<T> | IListResponse<T> | IBulkResponse<T> | IMessageResponse | IErrorResponse;
433
- interface IUserCompanyPayload {
434
- id: string;
435
- name: string;
436
- slug: string;
437
- logoId?: string;
438
- }
439
- interface IUserBranchPayload {
422
+
423
+ interface IFileBasicInfo {
440
424
  id: string;
441
425
  name: string;
442
- slug: string;
443
- logoId?: string;
426
+ contentType: string;
427
+ size: string;
428
+ url: string | null;
444
429
  }
445
- interface ILoginUserData {
446
- id: string;
430
+ interface IUploadedFile {
431
+ id?: string;
447
432
  name: string;
448
- email: string;
449
- phone?: string;
450
- profilePictureId?: string | null;
451
- companyId?: string;
452
- branchId?: string;
453
- company?: IUserCompanyPayload;
454
- branch?: IUserBranchPayload;
455
- }
456
- interface ILoginResponse {
457
- success: boolean;
458
- message: string;
459
- data: {
460
- accessToken: string;
461
- refreshToken: string;
462
- user: ILoginUserData;
463
- };
464
- _meta?: IRequestMeta;
465
- }
466
- interface IRefreshTokenResponse {
467
- success: boolean;
468
- message: string;
469
- data: {
470
- accessToken: string;
471
- refreshToken?: string;
472
- };
473
- _meta?: IRequestMeta;
433
+ key: string;
434
+ size: number;
435
+ contentType: string;
474
436
  }
475
- interface IFileData {
437
+ interface IFolderBasicInfo {
476
438
  id: string;
477
439
  name: string;
478
- originalName: string;
479
- contentType: string;
480
- size: number;
481
- key: string;
482
- url?: string;
483
- thumbnailUrl?: string;
484
- createdAt: Date;
440
+ slug: string;
485
441
  }
486
-
487
- /**
488
- * Basic file info for selectors and displays
489
- */
490
- interface IFileBasicInfo {
442
+ interface IStorageConfigBasicInfo {
491
443
  id: string;
492
444
  name: string;
493
- contentType: string;
494
- size: string;
495
- url: string | null;
445
+ isDefault: boolean;
496
446
  }
497
- /**
498
- * Upload options for file uploader
499
- */
500
447
  interface IFileUploadOptions {
501
448
  storageConfigId?: string;
502
449
  folderPath?: string;
@@ -504,42 +451,20 @@ interface IFileUploadOptions {
504
451
  maxHeight?: number;
505
452
  quality?: number;
506
453
  compress?: boolean;
454
+ isPrivate?: boolean;
507
455
  }
508
- /**
509
- * Uploaded file response
510
- */
511
- interface IUploadedFile {
512
- id?: string;
513
- name: string;
514
- key: string;
515
- size: number;
516
- contentType: string;
517
- }
518
- /**
519
- * Filter params for file selector
520
- */
521
- interface IFileSelectFilter {
456
+ interface ISelectFilter {
522
457
  page: number;
523
458
  pageSize: number;
524
459
  search: string;
460
+ }
461
+ interface IFileSelectFilter extends ISelectFilter {
525
462
  contentTypes?: string[];
526
463
  folderId?: string;
464
+ storageConfigId?: string;
527
465
  }
528
- /**
529
- * Function type for loading files
530
- */
531
- type LoadFilesFn = (filter: IFileSelectFilter) => Observable<IListResponse<IFileBasicInfo>>;
532
- /**
533
- * Function type for uploading a file
534
- */
535
466
  type UploadFileFn = (file: File, options?: IFileUploadOptions) => Observable<ISingleResponse<IUploadedFile>>;
536
- /**
537
- * Function type for getting file URLs (presigned URL refresh)
538
- */
539
- type GetFileUrlsFn = (fileIds: string[]) => Observable<ISingleResponse<IFileBasicInfo[]>>;
540
- /**
541
- * Common file type filters
542
- */
467
+ type UploadMultipleFilesFn = (files: File[], options?: IFileUploadOptions) => Observable<ISingleResponse<IUploadedFile[]>>;
543
468
  declare const FILE_TYPE_FILTERS: {
544
469
  readonly IMAGES: readonly ["image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml"];
545
470
  readonly DOCUMENTS: readonly ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"];
@@ -547,23 +472,26 @@ declare const FILE_TYPE_FILTERS: {
547
472
  readonly AUDIO: readonly ["audio/mpeg", "audio/wav", "audio/ogg", "audio/webm"];
548
473
  readonly ALL: string[];
549
474
  };
550
- /**
551
- * Get accept string for file input from content types
552
- */
553
475
  declare function getAcceptString(contentTypes: string[]): string;
554
- /**
555
- * Check if file matches allowed content types
556
- */
557
476
  declare function isFileTypeAllowed(file: File, allowedTypes: string[]): boolean;
558
- /**
559
- * Get file icon class based on content type
560
- */
561
477
  declare function getFileIconClass(contentType: string): string;
562
- /**
563
- * Format file size for display
564
- */
565
478
  declare function formatFileSize(sizeInKb: string | number): string;
566
479
 
480
+ interface IPagination {
481
+ pageSize: number;
482
+ currentPage: number;
483
+ }
484
+ type ISort = Record<string, 'ASC' | 'DESC'>;
485
+ type IFilter = Record<string, string | number | boolean | null | undefined | string[] | number[]>;
486
+ interface IFilterData {
487
+ filter?: IFilter;
488
+ pagination?: IPagination;
489
+ select?: string[];
490
+ sort?: ISort;
491
+ withDeleted?: boolean;
492
+ extraKey?: string[];
493
+ }
494
+
567
495
  /**
568
496
  * Auth State Provider Interface
569
497
  *
@@ -592,9 +520,8 @@ interface IUserProvider {
592
520
  page?: number;
593
521
  pageSize?: number;
594
522
  search?: string;
595
- companyId?: string;
596
- branchId?: string;
597
523
  isActive?: boolean;
524
+ [key: string]: unknown;
598
525
  }): Observable<IListResponse<IUserBasicInfo>>;
599
526
  }
600
527
  /** Filter params passed to loadUsers function */
@@ -662,99 +589,27 @@ interface IProfilePermissionProvider {
662
589
  getUserActions(userId: string, branchId?: string): Observable<ISingleResponse<IProfileActionInfo[]>>;
663
590
  }
664
591
  /**
665
- * Uploaded file result with file manager ID
666
- */
667
- interface IProfileUploadResult {
668
- id: string;
669
- name: string;
670
- key: string;
671
- size: number;
672
- contentType: string;
673
- }
674
- /**
675
- * Profile Upload Options
676
- */
677
- interface IProfileUploadOptions {
678
- folderPath?: string;
679
- compress?: boolean;
680
- maxWidth?: number;
681
- maxHeight?: number;
682
- }
683
- /**
684
- * Profile Upload Provider Interface - Provides file upload functionality for profile pictures.
685
- */
686
- interface IProfileUploadProvider {
687
- uploadProfilePicture(file: File, options?: IProfileUploadOptions): Observable<ISingleResponse<IProfileUploadResult>>;
688
- }
689
- /**
690
- * Base user interface for list operations
691
- */
692
- interface IUserListItem {
693
- id: string;
694
- name: string;
695
- email: string;
696
- phone?: string;
697
- isActive?: boolean;
698
- }
699
- /**
700
- * User list action definition
701
- */
702
- interface IUserListAction<T = IUserListItem> {
703
- id: string;
704
- label: string;
705
- icon?: string;
706
- severity?: 'primary' | 'secondary' | 'success' | 'info' | 'warn' | 'danger' | 'help' | 'contrast';
707
- permission?: string;
708
- tooltip?: string;
709
- disabled?: boolean | ((user: T) => boolean);
710
- visible?: boolean | ((user: T) => boolean);
711
- }
712
- /**
713
- * Extra column definition for user list
714
- */
715
- interface IUserListColumn {
716
- field: string;
717
- header: string;
718
- width?: string;
719
- sortable?: boolean;
720
- filterable?: boolean;
721
- templateType?: 'text' | 'badge' | 'date' | 'boolean' | 'custom';
722
- }
723
- /**
724
- * Extra filter definition for user list
592
+ * File Provider Interface - Provides file loading and upload functionality.
593
+ * Used by FileSelectorDialogComponent to load files and handle uploads.
725
594
  */
726
- interface IUserListFilter {
727
- field: string;
728
- label: string;
729
- type: 'text' | 'dropdown' | 'multiselect' | 'date' | 'boolean';
730
- options?: {
731
- label: string;
732
- value: string | number | boolean;
733
- }[];
734
- placeholder?: string;
735
- }
736
- /**
737
- * User List Provider Interface - Allows apps to extend user list pages.
738
- */
739
- interface IUserListProvider<T extends IUserListItem = IUserListItem> {
740
- getExtraColumns?(): IUserListColumn[];
741
- getExtraRowActions?(): IUserListAction<T>[];
742
- getExtraToolbarActions?(): IUserListAction<T>[];
743
- onRowAction?(actionId: string, user: T): void;
744
- onToolbarAction?(actionId: string, selectedUsers: T[]): void;
745
- enrichListData?(users: T[]): Observable<T[]>;
746
- getExtraFilters?(): IUserListFilter[];
747
- }
748
-
749
- declare enum ContactTypeEnum {
750
- PHONE = 1,
751
- EMAIL = 2
595
+ interface IFileProvider {
596
+ /** Load files with filtering and pagination */
597
+ loadFiles(filter: IFileSelectFilter): Observable<IListResponse<IFileBasicInfo>>;
598
+ /** Upload a single file and register in file manager */
599
+ uploadFile(file: File, options?: IFileUploadOptions): Observable<ISingleResponse<IUploadedFile>>;
600
+ /** Upload multiple files at once (more efficient batch upload) */
601
+ uploadMultipleFiles?(files: File[], options?: IFileUploadOptions): Observable<ISingleResponse<IUploadedFile[]>>;
602
+ /** Get file URLs by IDs (for refreshing presigned URLs) */
603
+ getFileUrls?(fileIds: string[]): Observable<ISingleResponse<IFileBasicInfo[]>>;
604
+ /** Load folders for folder selector (optional) */
605
+ loadFolders?(filter: ISelectFilter): Observable<IListResponse<IFolderBasicInfo>>;
606
+ /** Load storage configs for config selector (optional) */
607
+ loadStorageConfigs?(filter: ISelectFilter): Observable<IListResponse<IStorageConfigBasicInfo>>;
752
608
  }
753
609
 
754
610
  declare enum IconTypeEnum {
755
- PRIMENG_ICON = 1,
756
- IMAGE_FILE_LINK = 2,
757
- DIRECT_TAG_SVG = 3
611
+ ICON_NAME = 1,
612
+ IMAGE_FILE_LINK = 2
758
613
  }
759
614
 
760
615
  declare class CookieService {
@@ -766,6 +621,17 @@ declare class CookieService {
766
621
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<CookieService>;
767
622
  }
768
623
 
624
+ declare class FaviconService {
625
+ private readonly http;
626
+ private readonly platformService;
627
+ private readonly document;
628
+ private svgTemplate;
629
+ apply(): void;
630
+ private render;
631
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FaviconService, never>;
632
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<FaviconService>;
633
+ }
634
+
769
635
  interface FilesResponseDto {
770
636
  id: string;
771
637
  name: string;
@@ -780,19 +646,11 @@ declare class FileUrlService {
780
646
  private readonly http;
781
647
  private readonly appConfig;
782
648
  private readonly _cache;
783
- readonly cache: Signal<Map<string, FilesResponseDto>>;
784
- /** Get file URL by ID from cache (synchronous) */
785
- getFileUrl(fileId: string | null | undefined): string | null;
786
- /** Get file URL as computed signal */
787
- fileUrlSignal(fileId: string | null | undefined): Signal<string | null>;
649
+ readonly cache: _angular_core.Signal<Map<string, FilesResponseDto>>;
788
650
  /** Fetch file URLs from backend and update cache */
789
651
  fetchFileUrls(fileIds: string[], forceRefresh?: boolean): Observable<FilesResponseDto[]>;
790
652
  /** Fetch single file URL (delegates to fetchFileUrls) */
791
653
  fetchSingleFileUrl(fileId: string, forceRefresh?: boolean): Observable<FilesResponseDto | null>;
792
- /** Clear entire cache */
793
- clearCache(): void;
794
- /** Remove specific file from cache */
795
- removeFromCache(fileId: string): void;
796
654
  private addToCache;
797
655
  private getFromCache;
798
656
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<FileUrlService, never>;
@@ -814,7 +672,8 @@ declare class PermissionValidatorService {
814
672
  clearPermissions(): void;
815
673
  /** Check if user has permission (supports wildcards: '*', 'module.*') */
816
674
  hasPermission(code: string): boolean;
817
- /** @deprecated Use `isLoaded()` signal instead */
675
+ /** Check if user has ANY of the specified permissions (OR logic) */
676
+ hasAnyPermission(code: string[]): boolean;
818
677
  isPermissionsLoaded(): boolean;
819
678
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<PermissionValidatorService, never>;
820
679
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<PermissionValidatorService>;
@@ -827,6 +686,16 @@ declare class PlatformService {
827
686
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<PlatformService>;
828
687
  }
829
688
 
689
+ declare class TranslateService {
690
+ private readonly localizationState;
691
+ private readonly registry;
692
+ translate(key: string, params?: Record<string, string | unknown>): string;
693
+ translateSignal(key: string, params?: Record<string, string | number>): Signal<string>;
694
+ private interpolate;
695
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<TranslateService, never>;
696
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<TranslateService>;
697
+ }
698
+
830
699
  declare class EditModeElementChangerDirective {
831
700
  private readonly el;
832
701
  private readonly ngControl;
@@ -865,20 +734,18 @@ declare class EditModeElementChangerDirective {
865
734
  * @example
866
735
  * // In component
867
736
  * readonly userManageLogic: ILogicNode = {
868
- * id: 'root',
869
737
  * type: 'group',
870
738
  * operator: 'AND',
871
739
  * children: [
872
740
  * {
873
- * id: '1',
874
741
  * type: 'group',
875
742
  * operator: 'OR',
876
743
  * children: [
877
- * { id: '2', type: 'action', actionId: 'user.view' },
878
- * { id: '3', type: 'action', actionId: 'user.create' }
744
+ * { type: 'action', actionId: 'user.view' },
745
+ * { type: 'action', actionId: 'user.create' }
879
746
  * ]
880
747
  * },
881
- * { id: '4', type: 'action', actionId: 'department.manage' }
748
+ * { type: 'action', actionId: 'department.manage' }
882
749
  * ]
883
750
  * };
884
751
  *
@@ -937,313 +804,143 @@ declare class PreventDefaultDirective {
937
804
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<PreventDefaultDirective, "[appPreventDefault]", never, { "eventType": { "alias": "eventType"; "required": false; "isSignal": true; }; "preventKey": { "alias": "preventKey"; "required": false; "isSignal": true; }; }, { "action": "action"; }, never, never, true, never>;
938
805
  }
939
806
 
940
- declare class AngularModule {
941
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<AngularModule, never>;
942
- static ɵmod: _angular_core.ɵɵNgModuleDeclaration<AngularModule, never, [typeof i1.CommonModule, typeof i2.FormsModule, typeof i2.ReactiveFormsModule, typeof i3.RouterOutlet, typeof i3.RouterLink, typeof i3.RouterLinkActive, typeof IsEmptyImageDirective, typeof i1.NgOptimizedImage, typeof i1.NgComponentOutlet, typeof PreventDefaultDirective], [typeof i1.CommonModule, typeof i2.FormsModule, typeof i2.ReactiveFormsModule, typeof i3.RouterOutlet, typeof i3.RouterLink, typeof i3.RouterLinkActive, typeof IsEmptyImageDirective, typeof i1.NgOptimizedImage, typeof i1.NgComponentOutlet, typeof PreventDefaultDirective]>;
943
- static ɵinj: _angular_core.ɵɵInjectorDeclaration<AngularModule>;
944
- }
945
-
946
- declare class PrimeModule {
947
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<PrimeModule, never>;
948
- static ɵmod: _angular_core.ɵɵNgModuleDeclaration<PrimeModule, never, never, [typeof i1$1.AutoCompleteModule, typeof i2$1.AvatarModule, typeof i3$1.ButtonModule, typeof i4.CardModule, typeof i5.CheckboxModule, typeof i6.ConfirmDialogModule, typeof i7.DatePickerModule, typeof i8.DialogModule, typeof i9.DividerModule, typeof i10.FileUploadModule, typeof i11.IconFieldModule, typeof i12.ImageModule, typeof i13.InputIconModule, typeof i14.InputNumberModule, typeof i15.InputTextModule, typeof i16.ListboxModule, typeof i17.MultiSelectModule, typeof i18.PaginatorModule, typeof i19.PanelModule, typeof i20.PasswordModule, typeof i21.PopoverModule, typeof i22.ProgressBarModule, typeof i23.RadioButtonModule, typeof i24.RippleModule, typeof i25.SelectButtonModule, typeof i26.SelectModule, typeof i27.SkeletonModule, typeof i28.SplitButtonModule, typeof i29.StepsModule, typeof i30.TableModule, typeof i31.TabsModule, typeof i32.TagModule, typeof i33.TextareaModule, typeof i34.ToastModule, typeof i35.ToggleSwitchModule, typeof i36.TooltipModule, typeof i37.TreeTableModule]>;
949
- static ɵinj: _angular_core.ɵɵInjectorDeclaration<PrimeModule>;
807
+ declare class TranslatePipe implements PipeTransform {
808
+ private readonly translateAdapter;
809
+ transform(key: string | null | undefined, params?: Record<string, string | number> | null, fallback?: string): string;
810
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<TranslatePipe, never>;
811
+ static ɵpipe: _angular_core.ɵɵPipeDeclaration<TranslatePipe, "translate", true>;
950
812
  }
951
813
 
952
- /** Service names that can be used for feature-specific base URLs */
953
- type ServiceName = 'auth' | 'administration' | 'iam' | 'storage' | 'formBuilder' | 'email';
954
-
955
814
  /**
956
- * Service interface for CRUD operations.
957
- * Matches NestJS shared API controller endpoints:
815
+ * HTTP context token to skip global error toast.
816
+ * Use when component handles error display locally.
958
817
  *
959
- * | Angular Method | HTTP | NestJS Endpoint | Response Type |
960
- * |------------------|--------|------------------------|------------------------|
961
- * | insert() | POST | /{resource}/insert | ISingleResponse<T> |
962
- * | insertMany() | POST | /{resource}/insert-many| IBulkResponse<T> |
963
- * | findById() | POST | /{resource}/get/:id | ISingleResponse<T> |
964
- * | getAll() | POST | /{resource}/get-all | IListResponse<T> |
965
- * | update() | POST | /{resource}/update | ISingleResponse<T> |
966
- * | updateMany() | POST | /{resource}/update-many| IBulkResponse<T> |
967
- * | delete() | POST | /{resource}/delete | IMessageResponse |
818
+ * @example
819
+ * ```typescript
820
+ * this.http.post(url, data, {
821
+ * context: new HttpContext().set(SKIP_ERROR_TOAST, true)
822
+ * });
823
+ * ```
968
824
  */
969
- interface IApiService<DtoT, InterfaceT> {
970
- insert(dto: DtoT): Observable<ISingleResponse<InterfaceT>>;
971
- insertMany(dtos: DtoT[]): Observable<IBulkResponse<InterfaceT>>;
972
- findById(id: string, select?: string[]): Observable<ISingleResponse<InterfaceT>>;
973
- getAll(search: string, filter: IFilterData): Observable<IListResponse<InterfaceT>>;
974
- update(dto: DtoT): Observable<ISingleResponse<InterfaceT>>;
975
- updateMany(dtos: DtoT[]): Observable<IBulkResponse<InterfaceT>>;
976
- delete(deleteDto: IDeleteData): Observable<IMessageResponse>;
977
- }
825
+ declare const SKIP_ERROR_TOAST: HttpContextToken<boolean>;
978
826
  /**
979
- * Abstract base class for API services using Angular 21 resource() API.
980
- * Provides signal-based reactive data fetching with automatic loading states.
981
- * Response types match FLUSYS_NEST backend DTOs.
827
+ * Error Catching Interceptor
828
+ * Displays error messages for failed HTTP requests using backend response.
982
829
  *
983
- * ## Endpoint Mapping
830
+ * Features:
831
+ * - Uses backend's error title (error.error.error) as summary
832
+ * - Uses backend's error message (error.error.message) as detail
833
+ * - Falls back to sensible defaults based on status code
834
+ * - Skip with SKIP_ERROR_TOAST context token for local handling
984
835
  *
985
- * All endpoints use POST method (RPC-style API):
986
- * - `POST /{resource}/insert` - Create single item
987
- * - `POST /{resource}/insert-many` - Create multiple items
988
- * - `POST /{resource}/get/:id` - Get single item by ID
989
- * - `POST /{resource}/get-all?q=` - List with pagination/filter
990
- * - `POST /{resource}/update` - Update single item
991
- * - `POST /{resource}/update-many` - Update multiple items
992
- * - `POST /{resource}/delete` - Delete/restore/permanent delete
836
+ * NOTE: This interceptor only handles error display.
837
+ * For 401 handling and token refresh, use tokenRefreshInterceptor from @flusys/ng-auth.
993
838
  *
994
839
  * @example
995
840
  * ```typescript
996
- * // Define service with global apiBaseUrl
997
- * @Injectable({ providedIn: 'root' })
998
- * export class UserService extends ApiResourceService<UserDto, User> {
999
- * constructor() {
1000
- * super('auth/users', inject(HttpClient));
1001
- * }
1002
- * }
1003
- *
1004
- * // Define service with feature-specific baseUrl
1005
- * @Injectable({ providedIn: 'root' })
1006
- * export class FormService extends ApiResourceService<FormDto, Form> {
1007
- * constructor() {
1008
- * super('form', inject(HttpClient), 'formBuilder');
1009
- * // URL: services.formBuilder.baseUrl + '/form'
1010
- * }
1011
- * }
1012
- *
1013
- * // In component - use signals
1014
- * userService = inject(UserService);
1015
- * users = this.userService.data; // Signal<User[]>
1016
- * isLoading = this.userService.isLoading; // Signal<boolean>
1017
- * total = this.userService.total; // Signal<number>
1018
- *
1019
- * // Trigger fetch
1020
- * this.userService.fetchList('search', { pagination: { currentPage: 0, pageSize: 10 } });
1021
- *
1022
- * // CRUD operations
1023
- * await this.userService.insertAsync({ name: 'John', email: 'john@example.com' });
1024
- * await this.userService.updateAsync({ id: '123', name: 'John Updated' });
1025
- * await this.userService.deleteAsync({ id: '123', type: 'delete' });
841
+ * // In app.config.ts
842
+ * provideHttpClient(
843
+ * withFetch(),
844
+ * withInterceptors([
845
+ * authInterceptor, // from @flusys/ng-auth
846
+ * tokenRefreshInterceptor, // from @flusys/ng-auth
847
+ * errorCatchingInterceptor, // from @flusys/ng-core
848
+ * apiLoaderInterceptor, // from @flusys/ng-core
849
+ * ])
850
+ * )
1026
851
  * ```
1027
852
  */
853
+ declare function errorCatchingInterceptor(req: HttpRequest<unknown>, next: HttpHandlerFn): Observable<HttpEvent<unknown>>;
854
+
855
+ interface IResolverModuleConfig {
856
+ modules: string[];
857
+ fallbackMessages?: Record<string, string>;
858
+ }
859
+ declare function resolveTranslationModule(config: IResolverModuleConfig): ResolveFn<boolean>;
860
+
861
+ declare class AngularModule {
862
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<AngularModule, never>;
863
+ static ɵmod: _angular_core.ɵɵNgModuleDeclaration<AngularModule, never, [typeof i1.CommonModule, typeof i2.FormsModule, typeof i2.ReactiveFormsModule, typeof i3.RouterOutlet, typeof i3.RouterLink, typeof i3.RouterLinkActive, typeof IsEmptyImageDirective, typeof i1.NgOptimizedImage, typeof i1.NgComponentOutlet, typeof PreventDefaultDirective], [typeof i1.CommonModule, typeof i2.FormsModule, typeof i2.ReactiveFormsModule, typeof i3.RouterOutlet, typeof i3.RouterLink, typeof i3.RouterLinkActive, typeof IsEmptyImageDirective, typeof i1.NgOptimizedImage, typeof i1.NgComponentOutlet, typeof PreventDefaultDirective]>;
864
+ static ɵinj: _angular_core.ɵɵInjectorDeclaration<AngularModule>;
865
+ }
866
+
867
+ interface IApiService<DtoT, InterfaceT> {
868
+ insert(dto: DtoT): Promise<ISingleResponse<InterfaceT>>;
869
+ insertMany(dtos: DtoT[]): Promise<IBulkResponse<InterfaceT>>;
870
+ findById(id: string, select?: string[]): Promise<ISingleResponse<InterfaceT>>;
871
+ findByIds(ids: string[], select?: string[] | string): Promise<IListResponse<InterfaceT>>;
872
+ getAll(filter: IFilterData, search?: string): Promise<IListResponse<InterfaceT>>;
873
+ getByFilter(filter: Record<string, unknown>): Promise<ISingleResponse<InterfaceT>>;
874
+ update(dto: DtoT): Promise<ISingleResponse<InterfaceT>>;
875
+ updateMany(dtos: DtoT[]): Promise<IBulkResponse<InterfaceT>>;
876
+ bulkUpsert(toInsert: DtoT[], toUpdate: DtoT[]): Promise<InterfaceT[]>;
877
+ delete(deleteDto: IDeleteData): Promise<IMessageResponse>;
878
+ }
1028
879
  declare abstract class ApiResourceService<DtoT, InterfaceT> implements IApiService<DtoT, InterfaceT> {
1029
- protected readonly baseUrl: string;
1030
- protected readonly injector: Injector;
1031
880
  protected readonly http: HttpClient;
881
+ private readonly _config;
882
+ protected readonly baseUrl: string;
1032
883
  protected readonly moduleApiName: string;
1033
- /** Current search term */
1034
884
  readonly searchTerm: _angular_core.WritableSignal<string>;
1035
- /** Current filter and pagination state */
1036
885
  readonly filterData: _angular_core.WritableSignal<IFilterData>;
1037
- /**
1038
- * Resource for list data - lazy initialized to prevent auto-fetch on service injection.
1039
- * Call initListResource() or any list method (fetchList, reload, etc.) to initialize.
1040
- */
1041
- private _listResource;
1042
- /** Whether the list resource has been initialized */
1043
- private _resourceInitialized;
1044
- /**
1045
- * Signal to track resource initialization for computed signals.
1046
- * This allows computed signals to re-evaluate when the resource is created.
1047
- * Without this, computed signals would not detect when _listResource changes from null.
1048
- */
1049
- private readonly _resourceInitSignal;
1050
- /** Get or create the list resource (lazy initialization) */
1051
- get listResource(): ResourceRef<IListResponse<InterfaceT> | undefined>;
1052
- /**
1053
- * Initialize the list resource. Called automatically when accessing listResource
1054
- * or any list-related computed signals/methods.
1055
- * Uses runInInjectionContext to support lazy initialization outside constructor.
1056
- */
1057
- initListResource(): void;
1058
- /**
1059
- * Whether data is currently loading.
1060
- * Tracks _resourceInitSignal to re-evaluate when resource is created.
1061
- */
886
+ private readonly _active;
887
+ readonly listResource: ResourceRef<IListResponse<InterfaceT> | undefined>;
1062
888
  readonly isLoading: _angular_core.Signal<boolean>;
1063
- /**
1064
- * List data array.
1065
- * Tracks _resourceInitSignal to re-evaluate when resource is created.
1066
- */
1067
889
  readonly data: _angular_core.Signal<InterfaceT[]>;
1068
- /**
1069
- * Total count of items.
1070
- * Tracks _resourceInitSignal to re-evaluate when resource is created.
1071
- */
1072
890
  readonly total: _angular_core.Signal<number>;
1073
- /**
1074
- * Pagination metadata.
1075
- * Tracks _resourceInitSignal to re-evaluate when resource is created.
1076
- */
1077
891
  readonly pageInfo: _angular_core.Signal<_flusys_ng_shared.IPaginationMeta | undefined>;
1078
- /**
1079
- * Whether there are more pages.
1080
- * Tracks _resourceInitSignal to re-evaluate when resource is created.
1081
- */
1082
892
  readonly hasMore: _angular_core.Signal<boolean>;
1083
- /**
1084
- * @param moduleApiName - The API resource path (e.g., 'form' for /form-builder/form)
1085
- * @param http - HttpClient instance
1086
- * @param serviceName - Optional service name for feature-specific base URL (e.g., 'formBuilder')
1087
- */
1088
- constructor(moduleApiName: string, http: HttpClient, serviceName?: ServiceName);
893
+ readonly error: _angular_core.Signal<Error | undefined>;
894
+ readonly status: _angular_core.Signal<ResourceStatus>;
895
+ constructor(moduleApiName: string, serviceName?: ServiceName);
1089
896
  protected getHttpOptions(endpoint: string, params?: HttpParams): {
1090
897
  params?: HttpParams | undefined;
1091
898
  headers: HttpHeaders;
1092
899
  };
1093
- /**
1094
- * Fetch list data (triggers resource initialization and reload)
1095
- */
900
+ private _getAllObs;
901
+ private _activate;
1096
902
  fetchList(search?: string, filter?: Partial<IFilterData>): void;
1097
- /**
1098
- * Update pagination
1099
- */
1100
903
  setPagination(pagination: IPagination): void;
1101
- /**
1102
- * Go to next page
1103
- */
1104
904
  nextPage(): void;
1105
- /**
1106
- * Reset to first page
1107
- */
1108
905
  resetPagination(): void;
1109
- /**
1110
- * Reload current data
1111
- */
1112
906
  reload(): void;
1113
- /**
1114
- * Insert single item (Observable)
1115
- * POST /{resource}/insert
1116
- */
1117
- insert(dto: DtoT): Observable<ISingleResponse<InterfaceT>>;
1118
- /**
1119
- * Insert multiple items (Observable)
1120
- * POST /{resource}/insert-many
1121
- */
1122
- insertMany(dtos: DtoT[]): Observable<IBulkResponse<InterfaceT>>;
1123
- /**
1124
- * Find single item by ID (Observable)
1125
- * POST /{resource}/get/:id
1126
- */
1127
- findById(id: string, select?: string[]): Observable<ISingleResponse<InterfaceT>>;
1128
- /**
1129
- * Get all items with pagination (Observable)
1130
- * POST /{resource}/get-all?q=search
1131
- */
1132
- getAll(search: string, filter: IFilterData): Observable<IListResponse<InterfaceT>>;
1133
- /**
1134
- * Update single item (Observable)
1135
- * POST /{resource}/update
1136
- */
1137
- update(dto: DtoT): Observable<ISingleResponse<InterfaceT>>;
1138
- /**
1139
- * Update multiple items (Observable)
1140
- * POST /{resource}/update-many
1141
- */
1142
- updateMany(dtos: DtoT[]): Observable<IBulkResponse<InterfaceT>>;
1143
- /**
1144
- * Delete items (Observable)
1145
- * POST /{resource}/delete
1146
- * @param deleteDto - { id: string | string[], type: 'delete' | 'restore' | 'permanent' }
1147
- */
1148
- delete(deleteDto: IDeleteData): Observable<IMessageResponse>;
1149
- /**
1150
- * Fetch paginated list (async)
1151
- */
1152
- protected fetchAllAsync(search: string, filter: IFilterData): Promise<IListResponse<InterfaceT>>;
1153
- /**
1154
- * Find single item by ID (async)
1155
- */
1156
- findByIdAsync(id: string, select?: string[]): Promise<ISingleResponse<InterfaceT>>;
1157
- /**
1158
- * Insert single item (async)
1159
- */
1160
- insertAsync(dto: DtoT): Promise<ISingleResponse<InterfaceT>>;
1161
- /**
1162
- * Insert multiple items (async)
1163
- */
1164
- insertManyAsync(dtos: DtoT[]): Promise<IBulkResponse<InterfaceT>>;
1165
- /**
1166
- * Update single item (async)
1167
- */
1168
- updateAsync(dto: DtoT): Promise<ISingleResponse<InterfaceT>>;
1169
- /**
1170
- * Update multiple items (async)
1171
- */
1172
- updateManyAsync(dtos: DtoT[]): Promise<IBulkResponse<InterfaceT>>;
1173
- /**
1174
- * Delete items (async)
1175
- */
1176
- deleteAsync(deleteDto: IDeleteData): Promise<IMessageResponse>;
907
+ private _post;
908
+ insert(dto: DtoT): Promise<ISingleResponse<InterfaceT>>;
909
+ insertMany(dtos: DtoT[]): Promise<IBulkResponse<InterfaceT>>;
910
+ findById(id: string, select?: string[]): Promise<ISingleResponse<InterfaceT>>;
911
+ getAll(filter: IFilterData, search?: string): Promise<IListResponse<InterfaceT>>;
912
+ update(dto: DtoT): Promise<ISingleResponse<InterfaceT>>;
913
+ updateMany(dtos: DtoT[]): Promise<IBulkResponse<InterfaceT>>;
914
+ delete(deleteDto: IDeleteData): Promise<IMessageResponse>;
915
+ findByIds(ids: string[], select?: string[] | string): Promise<IListResponse<InterfaceT>>;
916
+ getByFilter(filter: Record<string, unknown>): Promise<ISingleResponse<InterfaceT>>;
917
+ bulkUpsert(toInsert: DtoT[], toUpdate: DtoT[]): Promise<InterfaceT[]>;
1177
918
  }
1178
919
 
1179
- /**
1180
- * Base class for form controls that support ALL Angular form patterns:
1181
- *
1182
- * 1. **Template-driven forms:** `[(value)]="mySignal"` or `[(ngModel)]="myValue"`
1183
- * 2. **Reactive forms:** `[formControl]="ctrl"` or `formControlName="field"`
1184
- * 3. **Signal forms (Angular 21+):** `[formField]="formTree.field"`
1185
- *
1186
- * Implements both `ControlValueAccessor` (reactive forms) and `FormValueControl` (signal forms).
1187
- *
1188
- * @example
1189
- * ```typescript
1190
- * @Component({
1191
- * providers: [provideValueAccessor(MySelectComponent)]
1192
- * })
1193
- * export class MySelectComponent extends BaseFormControl<string | null> {
1194
- * override readonly value = model<string | null>(null);
1195
- *
1196
- * constructor() {
1197
- * super();
1198
- * this.initializeFormControl();
1199
- * }
1200
- * }
1201
- *
1202
- * // Usage:
1203
- * // Template-driven: <my-select [(value)]="selectedId" />
1204
- * // Reactive forms: <my-select [formControl]="myControl" />
1205
- * // Signal forms: <my-select [formField]="formTree.myField" />
1206
- * ```
1207
- */
1208
920
  declare abstract class BaseFormControl<T> implements ControlValueAccessor, FormValueControl<T> {
1209
921
  protected readonly injector: Injector;
1210
- /**
1211
- * The value model - must be overridden in subclass with model<T>().
1212
- * This property satisfies both:
1213
- * - FormValueControl interface (signal forms)
1214
- * - Internal state for ControlValueAccessor (reactive forms)
1215
- */
1216
922
  abstract readonly value: ReturnType<typeof model<T>>;
1217
- /**
1218
- * Disabled state model - bound to form control disabled state.
1219
- * Using model() to satisfy FormValueControl interface requirements.
1220
- */
1221
923
  readonly disabled: _angular_core.ModelSignal<boolean>;
1222
- /**
1223
- * Touched state model - for validation styling.
1224
- * Using model() to satisfy FormValueControl interface requirements.
1225
- */
1226
924
  readonly touched: _angular_core.ModelSignal<boolean>;
1227
925
  private onChange;
1228
926
  private onTouched;
1229
- private isWritingValue;
927
+ private writeDepth;
1230
928
  /**
1231
- * Initialize the form control synchronization for ControlValueAccessor.
1232
- * Must be called in the subclass constructor after super().
929
+ * Wire up the ControlValueAccessor ↔ signal bridge.
930
+ * Call once at the end of the subclass constructor.
931
+ *
932
+ * Signal-form consumers ([formField]) don't need this — Angular's
933
+ * FormField directive binds directly to `value`.
1233
934
  *
1234
- * Note: For signal forms ([formField]), this is not needed as
1235
- * the FormField directive binds directly to the value model.
935
+ * @example
936
+ * constructor() { super(); this.initializeFormControl(); }
1236
937
  */
1237
938
  protected initializeFormControl(): void;
1238
- /** ControlValueAccessor: Write value from form control to signal */
1239
939
  writeValue(value: T): void;
1240
- /** ControlValueAccessor: Register change callback */
1241
940
  registerOnChange(fn: (value: T) => void): void;
1242
- /** ControlValueAccessor: Register touched callback */
1243
941
  registerOnTouched(fn: () => void): void;
1244
- /** ControlValueAccessor: Set disabled state from form control */
1245
942
  setDisabledState(isDisabled: boolean): void;
1246
- /** Mark the control as touched (call on blur or panel close) */
943
+ /** Call on blur / panel-close to propagate touched state. */
1247
944
  protected markAsTouched(): void;
1248
945
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseFormControl<any>, never>;
1249
946
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<BaseFormControl<any>, never, never, { "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "touched": { "alias": "touched"; "required": false; "isSignal": true; }; }, { "disabled": "disabledChange"; "touched": "touchedChange"; }, never, never, true, never>;
@@ -1266,6 +963,301 @@ declare function provideValueAccessor<T extends new (...args: unknown[]) => Cont
1266
963
  multi: boolean;
1267
964
  };
1268
965
 
966
+ declare class BaseFormTemplateDirective {
967
+ readonly key: _angular_core.InputSignal<string>;
968
+ readonly templateRef: TemplateRef<any>;
969
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseFormTemplateDirective, never>;
970
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<BaseFormTemplateDirective, "ng-template[baseFormTemplate]", never, { "key": { "alias": "baseFormTemplate"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
971
+ }
972
+
973
+ type FormFieldType = 'text' | 'email' | 'password' | 'number' | 'textarea' | 'select' | 'multiselect' | 'date' | 'checkbox' | 'toggle' | 'custom';
974
+ interface IFormSelectOption {
975
+ label: string;
976
+ value: unknown;
977
+ }
978
+ interface IFormField {
979
+ key: string;
980
+ type: FormFieldType;
981
+ label: string;
982
+ placeholder?: string;
983
+ required?: boolean;
984
+ disabled?: boolean;
985
+ fullWidth?: boolean;
986
+ options?: IFormSelectOption[];
987
+ minDate?: Date;
988
+ maxDate?: Date;
989
+ rows?: number;
990
+ min?: number;
991
+ max?: number;
992
+ hint?: string;
993
+ }
994
+
995
+ declare class BaseFormComponent {
996
+ private readonly translateAdapter;
997
+ private readonly router;
998
+ private readonly messageService;
999
+ readonly fields: _angular_core.InputSignal<IFormField[]>;
1000
+ readonly title: _angular_core.InputSignal<string>;
1001
+ readonly createTitle: _angular_core.InputSignal<string>;
1002
+ readonly editTitle: _angular_core.InputSignal<string>;
1003
+ readonly columns: _angular_core.InputSignal<1 | 2 | 3>;
1004
+ readonly submitLabel: _angular_core.InputSignal<string>;
1005
+ readonly cancelLabel: _angular_core.InputSignal<string>;
1006
+ readonly isLoading: _angular_core.InputSignal<boolean>;
1007
+ readonly isEditMode: _angular_core.InputSignal<boolean>;
1008
+ readonly initialValue: _angular_core.InputSignal<Record<string, unknown>>;
1009
+ readonly service: _angular_core.InputSignal<ApiResourceService<unknown, unknown> | null>;
1010
+ readonly editId: _angular_core.InputSignal<string | null>;
1011
+ readonly cancelRoute: _angular_core.InputSignal<string | string[] | null>;
1012
+ readonly navigateOnSuccess: _angular_core.InputSignal<string | string[] | null>;
1013
+ readonly mapToRequest: _angular_core.InputSignal<((data: Record<string, unknown>, editId: string | null) => unknown) | null>;
1014
+ readonly mapFromEntity: _angular_core.InputSignal<((entity: unknown) => Record<string, unknown>) | null>;
1015
+ readonly onSubmit: _angular_core.OutputEmitterRef<Record<string, unknown>>;
1016
+ readonly onCancel: _angular_core.OutputEmitterRef<void>;
1017
+ readonly onValueChange: _angular_core.OutputEmitterRef<Record<string, unknown>>;
1018
+ readonly fieldTemplates: _angular_core.Signal<readonly BaseFormTemplateDirective[]>;
1019
+ private readonly _formData;
1020
+ private readonly _submitted;
1021
+ private readonly _isLoadingInternal;
1022
+ private readonly _touchedFields;
1023
+ private readonly _visiblePasswordFields;
1024
+ readonly formData: _angular_core.Signal<Record<string, unknown>>;
1025
+ readonly submitted: _angular_core.Signal<boolean>;
1026
+ readonly effectiveIsEditMode: _angular_core.Signal<boolean>;
1027
+ readonly effectiveIsLoading: _angular_core.Signal<boolean>;
1028
+ readonly isFormValid: _angular_core.Signal<boolean>;
1029
+ readonly resolvedTitle: _angular_core.Signal<string>;
1030
+ readonly gridClass: _angular_core.Signal<"grid-cols-1" | "grid-cols-1 md:grid-cols-3" | "grid-cols-1 md:grid-cols-2">;
1031
+ constructor();
1032
+ private loadEntity;
1033
+ getFieldValue(key: string): unknown;
1034
+ setFieldValue(key: string, value: unknown): void;
1035
+ markFieldTouched(key: string): void;
1036
+ isPasswordVisible(key: string): boolean;
1037
+ togglePasswordVisibility(key: string): void;
1038
+ isFieldInvalid(field: IFormField): boolean;
1039
+ getFieldTemplate(key: string): TemplateRef<unknown> | null;
1040
+ handleSubmit(): Promise<void>;
1041
+ handleCancel(): void;
1042
+ reset(): void;
1043
+ t(key: string, vars?: Record<string, string | number>): string;
1044
+ private managedSubmit;
1045
+ private checkValidity;
1046
+ private navigateTo;
1047
+ private getDefaultValue;
1048
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseFormComponent, never>;
1049
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<BaseFormComponent, "lib-base-form", never, { "fields": { "alias": "fields"; "required": true; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "createTitle": { "alias": "createTitle"; "required": false; "isSignal": true; }; "editTitle": { "alias": "editTitle"; "required": false; "isSignal": true; }; "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "submitLabel": { "alias": "submitLabel"; "required": false; "isSignal": true; }; "cancelLabel": { "alias": "cancelLabel"; "required": false; "isSignal": true; }; "isLoading": { "alias": "isLoading"; "required": false; "isSignal": true; }; "isEditMode": { "alias": "isEditMode"; "required": false; "isSignal": true; }; "initialValue": { "alias": "initialValue"; "required": false; "isSignal": true; }; "service": { "alias": "service"; "required": false; "isSignal": true; }; "editId": { "alias": "editId"; "required": false; "isSignal": true; }; "cancelRoute": { "alias": "cancelRoute"; "required": false; "isSignal": true; }; "navigateOnSuccess": { "alias": "navigateOnSuccess"; "required": false; "isSignal": true; }; "mapToRequest": { "alias": "mapToRequest"; "required": false; "isSignal": true; }; "mapFromEntity": { "alias": "mapFromEntity"; "required": false; "isSignal": true; }; }, { "onSubmit": "onSubmit"; "onCancel": "onCancel"; "onValueChange": "onValueChange"; }, ["fieldTemplates"], never, true, never>;
1050
+ }
1051
+
1052
+ declare class BaseListTemplateDirective {
1053
+ readonly key: _angular_core.InputSignal<string>;
1054
+ readonly templateRef: TemplateRef<any>;
1055
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseListTemplateDirective, never>;
1056
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<BaseListTemplateDirective, "ng-template[baseListTemplate]", never, { "key": { "alias": "baseListTemplate"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
1057
+ }
1058
+
1059
+ type TableColumnType = 'text' | 'date' | 'tag' | 'boolean' | 'number' | 'custom';
1060
+ type ActionSeverity = 'success' | 'info' | 'warn' | 'danger' | 'secondary' | 'contrast';
1061
+ interface ITagConfig {
1062
+ label?: string;
1063
+ severity: 'success' | 'danger' | 'warn' | 'info' | 'secondary' | 'contrast';
1064
+ }
1065
+ interface ITableColumn {
1066
+ field: string;
1067
+ header: string;
1068
+ type?: TableColumnType;
1069
+ width?: string;
1070
+ minWidth?: string;
1071
+ align?: 'left' | 'center' | 'right';
1072
+ tagMap?: Record<string, ITagConfig>;
1073
+ dateFormat?: string;
1074
+ truncate?: number;
1075
+ hidden?: boolean;
1076
+ }
1077
+ interface ITableAction<T = unknown> {
1078
+ icon: string;
1079
+ tooltip?: string;
1080
+ severity?: ActionSeverity;
1081
+ show?: (item: T) => boolean;
1082
+ disabled?: (item: T) => boolean;
1083
+ handler: (item: T) => void;
1084
+ }
1085
+
1086
+ declare class BaseListComponent {
1087
+ private readonly translateAdapter;
1088
+ private readonly router;
1089
+ private readonly messageService;
1090
+ private readonly confirmationService;
1091
+ readonly columns: _angular_core.InputSignal<ITableColumn[]>;
1092
+ readonly actions: _angular_core.InputSignal<ITableAction<unknown>[]>;
1093
+ readonly title: _angular_core.InputSignal<string>;
1094
+ readonly showCreateButton: _angular_core.InputSignal<boolean>;
1095
+ readonly searchable: _angular_core.InputSignal<boolean>;
1096
+ readonly pageSize: _angular_core.InputSignal<number>;
1097
+ readonly emptyMessage: _angular_core.InputSignal<string>;
1098
+ readonly createButtonLabel: _angular_core.InputSignal<string>;
1099
+ readonly createButtonIcon: _angular_core.InputSignal<string>;
1100
+ readonly data: _angular_core.InputSignal<unknown[]>;
1101
+ readonly total: _angular_core.InputSignal<number>;
1102
+ readonly isLoading: _angular_core.InputSignal<boolean>;
1103
+ readonly service: _angular_core.InputSignal<ApiResourceService<unknown, unknown> | null>;
1104
+ readonly filter: _angular_core.InputSignal<IFilter>;
1105
+ readonly createRoute: _angular_core.InputSignal<string | null>;
1106
+ readonly editRoute: _angular_core.InputSignal<string | null>;
1107
+ readonly deleteConfirmField: _angular_core.InputSignal<string | null>;
1108
+ readonly idField: _angular_core.InputSignal<string>;
1109
+ readonly canEdit: _angular_core.InputSignal<((item: unknown) => boolean) | null>;
1110
+ readonly canDelete: _angular_core.InputSignal<((item: unknown) => boolean) | null>;
1111
+ readonly onCreate: _angular_core.OutputEmitterRef<void>;
1112
+ readonly onLazyLoad: _angular_core.OutputEmitterRef<{
1113
+ first: number;
1114
+ rows: number;
1115
+ }>;
1116
+ readonly onSearch: _angular_core.OutputEmitterRef<string>;
1117
+ readonly columnTemplates: _angular_core.Signal<readonly BaseListTemplateDirective[]>;
1118
+ private readonly _first;
1119
+ private readonly _searchTerm;
1120
+ readonly first: _angular_core.Signal<number>;
1121
+ readonly searchTerm: _angular_core.Signal<string>;
1122
+ readonly effectiveData: _angular_core.Signal<unknown[]>;
1123
+ readonly effectiveTotal: _angular_core.Signal<number>;
1124
+ readonly effectiveIsLoading: _angular_core.Signal<boolean>;
1125
+ readonly effectiveActions: _angular_core.Signal<ITableAction<unknown>[]>;
1126
+ readonly visibleColumns: _angular_core.Signal<ITableColumn[]>;
1127
+ readonly columnCount: _angular_core.Signal<number>;
1128
+ readonly resolvedEmptyMessage: _angular_core.Signal<string>;
1129
+ readonly resolvedCreateLabel: _angular_core.Signal<string>;
1130
+ handleLazyLoad(event: {
1131
+ first?: number | null;
1132
+ rows?: number | null;
1133
+ }): void;
1134
+ onSearchChange(value: string): void;
1135
+ handleCreate(): void;
1136
+ private handleEditItem;
1137
+ private handleDeleteItem;
1138
+ getFieldValue(item: unknown, field: string): unknown;
1139
+ getFieldValueAsString(item: unknown, field: string): string;
1140
+ getTagConfig(col: ITableColumn, value: unknown): ITagConfig | null;
1141
+ getColumnTemplate(field: string): TemplateRef<unknown> | null;
1142
+ truncateText(value: unknown, limit?: number): string;
1143
+ getCellClass(col: ITableColumn): string;
1144
+ t(key: string, vars?: Record<string, string | number>): string;
1145
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseListComponent, never>;
1146
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<BaseListComponent, "lib-base-list", never, { "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "actions": { "alias": "actions"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "showCreateButton": { "alias": "showCreateButton"; "required": false; "isSignal": true; }; "searchable": { "alias": "searchable"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "emptyMessage": { "alias": "emptyMessage"; "required": false; "isSignal": true; }; "createButtonLabel": { "alias": "createButtonLabel"; "required": false; "isSignal": true; }; "createButtonIcon": { "alias": "createButtonIcon"; "required": false; "isSignal": true; }; "data": { "alias": "data"; "required": false; "isSignal": true; }; "total": { "alias": "total"; "required": false; "isSignal": true; }; "isLoading": { "alias": "isLoading"; "required": false; "isSignal": true; }; "service": { "alias": "service"; "required": false; "isSignal": true; }; "filter": { "alias": "filter"; "required": false; "isSignal": true; }; "createRoute": { "alias": "createRoute"; "required": false; "isSignal": true; }; "editRoute": { "alias": "editRoute"; "required": false; "isSignal": true; }; "deleteConfirmField": { "alias": "deleteConfirmField"; "required": false; "isSignal": true; }; "idField": { "alias": "idField"; "required": false; "isSignal": true; }; "canEdit": { "alias": "canEdit"; "required": false; "isSignal": true; }; "canDelete": { "alias": "canDelete"; "required": false; "isSignal": true; }; }, { "onCreate": "onCreate"; "onLazyLoad": "onLazyLoad"; "onSearch": "onSearch"; }, ["columnTemplates"], never, true, never>;
1147
+ }
1148
+
1149
+ declare class FileSelectorDialogComponent {
1150
+ private readonly destroyRef;
1151
+ private readonly translateAdapter;
1152
+ readonly fileProvider: _flusys_ng_shared.IFileProvider | null;
1153
+ private abortController;
1154
+ private searchDebounceTimer;
1155
+ readonly header: _angular_core.InputSignal<string | undefined>;
1156
+ readonly acceptTypes: _angular_core.InputSignal<string[]>;
1157
+ readonly multiple: _angular_core.InputSignal<boolean>;
1158
+ readonly dialogHeader: _angular_core.Signal<string>;
1159
+ readonly maxSelection: _angular_core.InputSignal<number>;
1160
+ readonly pageSize: _angular_core.InputSignal<number>;
1161
+ readonly folderId: _angular_core.InputSignal<string | undefined>;
1162
+ readonly withUploader: _angular_core.InputSignal<boolean>;
1163
+ readonly visible: _angular_core.ModelSignal<boolean>;
1164
+ readonly fileSelected: _angular_core.OutputEmitterRef<IFileBasicInfo>;
1165
+ readonly filesSelected: _angular_core.OutputEmitterRef<IFileBasicInfo[]>;
1166
+ readonly closed: _angular_core.OutputEmitterRef<void>;
1167
+ readonly onError: _angular_core.OutputEmitterRef<Error>;
1168
+ readonly isLoading: _angular_core.WritableSignal<boolean>;
1169
+ readonly files: _angular_core.WritableSignal<IFileBasicInfo[]>;
1170
+ readonly selectedFiles: _angular_core.WritableSignal<IFileBasicInfo[]>;
1171
+ readonly total: _angular_core.WritableSignal<number | undefined>;
1172
+ readonly pagination: _angular_core.WritableSignal<IPagination>;
1173
+ readonly searchTerm: _angular_core.WritableSignal<string>;
1174
+ readonly folders: _angular_core.WritableSignal<IFolderBasicInfo[]>;
1175
+ readonly selectedFolderId: _angular_core.WritableSignal<string | null>;
1176
+ readonly foldersLoading: _angular_core.WritableSignal<boolean>;
1177
+ readonly foldersPagination: _angular_core.WritableSignal<IPagination>;
1178
+ readonly foldersTotal: _angular_core.WritableSignal<number | undefined>;
1179
+ readonly storageConfigs: _angular_core.WritableSignal<IStorageConfigBasicInfo[]>;
1180
+ readonly selectedStorageConfigId: _angular_core.WritableSignal<string | null>;
1181
+ readonly storageConfigsLoading: _angular_core.WritableSignal<boolean>;
1182
+ readonly storageConfigsPagination: _angular_core.WritableSignal<IPagination>;
1183
+ readonly storageConfigsTotal: _angular_core.WritableSignal<number | undefined>;
1184
+ readonly effectiveStorageConfigId: _angular_core.Signal<string | undefined>;
1185
+ readonly uploadFileFn: (file: File, options?: IFileUploadOptions) => rxjs.Observable<_flusys_ng_shared.ISingleResponse<IUploadedFile>>;
1186
+ readonly uploadMultipleFilesFn: ((files: File[], options?: IFileUploadOptions) => rxjs.Observable<_flusys_ng_shared.ISingleResponse<IUploadedFile[]>>) | undefined;
1187
+ constructor();
1188
+ onSearchChange(value: string): void;
1189
+ onScroll(event: Event): void;
1190
+ toggleSelection(file: IFileBasicInfo): void;
1191
+ isSelected(file: IFileBasicInfo): boolean;
1192
+ isFileAllowed(file: IFileBasicInfo): boolean;
1193
+ isImage(file: IFileBasicInfo): boolean;
1194
+ getFileIcon(file: IFileBasicInfo): string;
1195
+ formatSize(size: string): string;
1196
+ onCancel(): void;
1197
+ onConfirm(): void;
1198
+ onDialogHide(): void;
1199
+ onFolderChange(folderId: string | null): void;
1200
+ onFolderSearch(event: {
1201
+ filter: string;
1202
+ }): void;
1203
+ loadFolders(search?: string): Promise<void>;
1204
+ onStorageConfigChange(configId: string | null): void;
1205
+ onStorageConfigSearch(event: {
1206
+ filter: string;
1207
+ }): void;
1208
+ loadStorageConfigs(search?: string): Promise<void>;
1209
+ onFileUploaded(uploadedFile: IUploadedFile): void;
1210
+ private resetState;
1211
+ private fetchFiles;
1212
+ private t;
1213
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FileSelectorDialogComponent, never>;
1214
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FileSelectorDialogComponent, "lib-file-selector-dialog", never, { "header": { "alias": "header"; "required": false; "isSignal": true; }; "acceptTypes": { "alias": "acceptTypes"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "maxSelection": { "alias": "maxSelection"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "folderId": { "alias": "folderId"; "required": false; "isSignal": true; }; "withUploader": { "alias": "withUploader"; "required": false; "isSignal": true; }; "visible": { "alias": "visible"; "required": false; "isSignal": true; }; }, { "visible": "visibleChange"; "fileSelected": "fileSelected"; "filesSelected": "filesSelected"; "closed": "closed"; "onError": "onError"; }, never, never, true, never>;
1215
+ }
1216
+
1217
+ declare class FileUploaderComponent {
1218
+ private readonly messageService;
1219
+ private readonly translateAdapter;
1220
+ private readonly fileProvider;
1221
+ readonly uploadFile: _angular_core.InputSignal<UploadFileFn | undefined>;
1222
+ readonly uploadMultipleFiles: _angular_core.InputSignal<UploadMultipleFilesFn | undefined>;
1223
+ readonly hasUploadCapability: _angular_core.Signal<boolean>;
1224
+ private getUploadFn;
1225
+ private getUploadMultipleFn;
1226
+ readonly acceptTypes: _angular_core.InputSignal<string[]>;
1227
+ readonly multiple: _angular_core.InputSignal<boolean>;
1228
+ readonly maxFiles: _angular_core.InputSignal<number>;
1229
+ readonly maxSizeMb: _angular_core.InputSignal<number>;
1230
+ readonly uploadOptions: _angular_core.InputSignal<IFileUploadOptions>;
1231
+ readonly disabled: _angular_core.InputSignal<boolean>;
1232
+ readonly showPreview: _angular_core.InputSignal<boolean>;
1233
+ readonly autoUpload: _angular_core.InputSignal<boolean>;
1234
+ readonly fileUploaded: _angular_core.OutputEmitterRef<IUploadedFile>;
1235
+ readonly filesUploaded: _angular_core.OutputEmitterRef<IUploadedFile[]>;
1236
+ readonly onError: _angular_core.OutputEmitterRef<Error>;
1237
+ readonly fileSelected: _angular_core.OutputEmitterRef<File[]>;
1238
+ readonly isUploading: _angular_core.WritableSignal<boolean>;
1239
+ readonly isDragOver: _angular_core.WritableSignal<boolean>;
1240
+ readonly uploadProgress: _angular_core.WritableSignal<number>;
1241
+ readonly uploadingFileName: _angular_core.WritableSignal<string>;
1242
+ readonly selectedFiles: _angular_core.WritableSignal<File[]>;
1243
+ readonly acceptString: _angular_core.Signal<string>;
1244
+ readonly acceptTypesDisplay: _angular_core.Signal<string>;
1245
+ onDragOver(event: DragEvent): void;
1246
+ onDragLeave(event: DragEvent): void;
1247
+ onDrop(event: DragEvent): void;
1248
+ onFileSelected(event: Event): void;
1249
+ private handleFiles;
1250
+ removeFile(file: File): void;
1251
+ uploadFiles(files?: File[]): Promise<void>;
1252
+ private uploadBatch;
1253
+ private uploadSequential;
1254
+ getFileIcon(file: File): string;
1255
+ formatSize(bytes: number): string;
1256
+ private t;
1257
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FileUploaderComponent, never>;
1258
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FileUploaderComponent, "lib-file-uploader", never, { "uploadFile": { "alias": "uploadFile"; "required": false; "isSignal": true; }; "uploadMultipleFiles": { "alias": "uploadMultipleFiles"; "required": false; "isSignal": true; }; "acceptTypes": { "alias": "acceptTypes"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "maxFiles": { "alias": "maxFiles"; "required": false; "isSignal": true; }; "maxSizeMb": { "alias": "maxSizeMb"; "required": false; "isSignal": true; }; "uploadOptions": { "alias": "uploadOptions"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "showPreview": { "alias": "showPreview"; "required": false; "isSignal": true; }; "autoUpload": { "alias": "autoUpload"; "required": false; "isSignal": true; }; }, { "fileUploaded": "fileUploaded"; "filesUploaded": "filesUploaded"; "onError": "onError"; "fileSelected": "fileSelected"; }, never, never, true, never>;
1259
+ }
1260
+
1269
1261
  declare class IconComponent {
1270
1262
  icon: _angular_core.InputSignal<string>;
1271
1263
  iconType: _angular_core.InputSignal<IconTypeEnum | undefined>;
@@ -1274,6 +1266,15 @@ declare class IconComponent {
1274
1266
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<IconComponent, "lib-icon", never, { "icon": { "alias": "icon"; "required": true; "isSignal": true; }; "iconType": { "alias": "iconType"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1275
1267
  }
1276
1268
 
1269
+ declare class InlineSvgComponent {
1270
+ readonly src: _angular_core.InputSignal<string>;
1271
+ private readonly http;
1272
+ private readonly sanitizer;
1273
+ readonly svg: _angular_core.ResourceRef<_angular_platform_browser.SafeHtml | undefined>;
1274
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<InlineSvgComponent, never>;
1275
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<InlineSvgComponent, "inline-svg", never, { "src": { "alias": "src"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
1276
+ }
1277
+
1277
1278
  /**
1278
1279
  * Lazy-loading multi-select component with search, pagination, and select-all.
1279
1280
  *
@@ -1282,11 +1283,17 @@ declare class IconComponent {
1282
1283
  * - Reactive forms: `[formControl]="ctrl"` or `formControlName="field"`
1283
1284
  * - Signal forms: `[formField]="formTree.field"`
1284
1285
  */
1285
- declare class LazyMultiSelectComponent extends BaseFormControl<string[] | null> {
1286
- private readonly destroyRef;
1286
+ declare class LazyMultiSelectComponent extends BaseFormControl<string[] | null> implements OnDestroy {
1287
+ private readonly document;
1288
+ private readonly appRef;
1289
+ private readonly translateAdapter;
1287
1290
  private readonly onDocumentClickBound;
1288
1291
  readonly pSelectRef: _angular_core.Signal<ElementRef<HTMLDivElement>>;
1292
+ readonly overlayTemplate: _angular_core.Signal<TemplateRef<unknown>>;
1293
+ private overlayViewRef;
1289
1294
  readonly placeHolder: _angular_core.InputSignal<string>;
1295
+ readonly showClear: _angular_core.InputSignal<boolean>;
1296
+ readonly displayPlaceholder: _angular_core.Signal<string>;
1290
1297
  readonly isEditMode: _angular_core.InputSignal<boolean>;
1291
1298
  readonly isLoading: _angular_core.InputSignal<boolean>;
1292
1299
  readonly total: _angular_core.InputSignal<number | undefined>;
@@ -1298,19 +1305,23 @@ declare class LazyMultiSelectComponent extends BaseFormControl<string[] | null>
1298
1305
  readonly searchTerm: _angular_core.WritableSignal<string>;
1299
1306
  readonly openOptions: _angular_core.WritableSignal<boolean>;
1300
1307
  readonly selectedValueDisplay: _angular_core.Signal<string>;
1308
+ readonly hasSelectedValues: _angular_core.Signal<boolean>;
1301
1309
  readonly isSelectAll: _angular_core.Signal<boolean>;
1302
1310
  constructor();
1311
+ ngOnDestroy(): void;
1303
1312
  onScroll(event: Event): void;
1304
- onSelectClick(event: Event): void;
1313
+ onSelectClick(): void;
1314
+ private openOverlay;
1315
+ private closeOverlay;
1305
1316
  onOverlayClick(event: Event): void;
1306
1317
  private handleDocumentClick;
1307
1318
  isSelected(data: IDropDown): boolean;
1308
- key(option: IDropDown): string;
1309
1319
  selectValue(event: CheckboxChangeEvent, option: IDropDown): void;
1310
1320
  changeSelectAll(event: CheckboxChangeEvent): void;
1311
1321
  clear(event: Event): void;
1322
+ private t;
1312
1323
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<LazyMultiSelectComponent, never>;
1313
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<LazyMultiSelectComponent, "lib-lazy-multi-select", never, { "placeHolder": { "alias": "placeHolder"; "required": false; "isSignal": true; }; "isEditMode": { "alias": "isEditMode"; "required": true; "isSignal": true; }; "isLoading": { "alias": "isLoading"; "required": true; "isSignal": true; }; "total": { "alias": "total"; "required": true; "isSignal": true; }; "pagination": { "alias": "pagination"; "required": true; "isSignal": true; }; "selectDataList": { "alias": "selectDataList"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "onSearch": "onSearch"; "onPagination": "onPagination"; }, never, never, true, never>;
1324
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<LazyMultiSelectComponent, "lib-lazy-multi-select", never, { "placeHolder": { "alias": "placeHolder"; "required": false; "isSignal": true; }; "showClear": { "alias": "showClear"; "required": false; "isSignal": true; }; "isEditMode": { "alias": "isEditMode"; "required": true; "isSignal": true; }; "isLoading": { "alias": "isLoading"; "required": true; "isSignal": true; }; "total": { "alias": "total"; "required": true; "isSignal": true; }; "pagination": { "alias": "pagination"; "required": true; "isSignal": true; }; "selectDataList": { "alias": "selectDataList"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "onSearch": "onSearch"; "onPagination": "onPagination"; }, never, never, true, never>;
1314
1325
  }
1315
1326
 
1316
1327
  /**
@@ -1323,10 +1334,14 @@ declare class LazyMultiSelectComponent extends BaseFormControl<string[] | null>
1323
1334
  */
1324
1335
  declare class LazySelectComponent extends BaseFormControl<string | null> {
1325
1336
  private readonly destroyRef;
1337
+ private readonly translateAdapter;
1326
1338
  private readonly onScrollBound;
1327
1339
  private scrollTargetEl;
1340
+ private isDestroyed;
1328
1341
  readonly scrollContainer: _angular_core.Signal<ElementRef<HTMLDivElement>>;
1329
1342
  readonly placeHolder: _angular_core.InputSignal<string>;
1343
+ readonly showClear: _angular_core.InputSignal<boolean>;
1344
+ readonly displayPlaceholder: _angular_core.Signal<string>;
1330
1345
  readonly optionLabel: _angular_core.InputSignal<string>;
1331
1346
  readonly optionValue: _angular_core.InputSignal<string>;
1332
1347
  readonly isEditMode: _angular_core.InputSignal<boolean>;
@@ -1343,8 +1358,22 @@ declare class LazySelectComponent extends BaseFormControl<string | null> {
1343
1358
  onScroll(event: Event): void;
1344
1359
  showPanel(): void;
1345
1360
  onBlur(): void;
1361
+ private t;
1346
1362
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<LazySelectComponent, never>;
1347
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<LazySelectComponent, "lib-lazy-select", never, { "placeHolder": { "alias": "placeHolder"; "required": false; "isSignal": true; }; "optionLabel": { "alias": "optionLabel"; "required": true; "isSignal": true; }; "optionValue": { "alias": "optionValue"; "required": true; "isSignal": true; }; "isEditMode": { "alias": "isEditMode"; "required": true; "isSignal": true; }; "isLoading": { "alias": "isLoading"; "required": true; "isSignal": true; }; "total": { "alias": "total"; "required": true; "isSignal": true; }; "pagination": { "alias": "pagination"; "required": true; "isSignal": true; }; "selectDataList": { "alias": "selectDataList"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "onSearch": "onSearch"; "onPagination": "onPagination"; }, never, never, true, never>;
1363
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<LazySelectComponent, "lib-lazy-select", never, { "placeHolder": { "alias": "placeHolder"; "required": false; "isSignal": true; }; "showClear": { "alias": "showClear"; "required": false; "isSignal": true; }; "optionLabel": { "alias": "optionLabel"; "required": true; "isSignal": true; }; "optionValue": { "alias": "optionValue"; "required": true; "isSignal": true; }; "isEditMode": { "alias": "isEditMode"; "required": true; "isSignal": true; }; "isLoading": { "alias": "isLoading"; "required": true; "isSignal": true; }; "total": { "alias": "total"; "required": true; "isSignal": true; }; "pagination": { "alias": "pagination"; "required": true; "isSignal": true; }; "selectDataList": { "alias": "selectDataList"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "onSearch": "onSearch"; "onPagination": "onPagination"; }, never, never, true, never>;
1364
+ }
1365
+
1366
+ interface RouterTabItem {
1367
+ id: string | number;
1368
+ label: string;
1369
+ icon?: string;
1370
+ route: string | unknown[];
1371
+ routerLinkActiveExact?: boolean;
1372
+ }
1373
+ declare class RouterTabsComponent {
1374
+ readonly tabs: _angular_core.InputSignal<RouterTabItem[]>;
1375
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<RouterTabsComponent, never>;
1376
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<RouterTabsComponent, "lib-router-tabs", never, { "tabs": { "alias": "tabs"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1348
1377
  }
1349
1378
 
1350
1379
  /**
@@ -1358,6 +1387,7 @@ declare abstract class BaseUserSelectComponent {
1358
1387
  protected readonly destroyRef: DestroyRef;
1359
1388
  protected readonly injector: Injector;
1360
1389
  protected readonly userProvider: IUserProvider;
1390
+ protected readonly translateAdapter: TranslateService;
1361
1391
  protected abortController: AbortController | null;
1362
1392
  readonly loadUsers: _angular_core.InputSignal<LoadUsersFn | undefined>;
1363
1393
  readonly placeHolder: _angular_core.InputSignal<string>;
@@ -1372,6 +1402,7 @@ declare abstract class BaseUserSelectComponent {
1372
1402
  readonly pagination: _angular_core.WritableSignal<IPagination>;
1373
1403
  readonly searchTerm: _angular_core.WritableSignal<string>;
1374
1404
  readonly dropdownUsers: _angular_core.Signal<IDropDown[]>;
1405
+ readonly displayPlaceholder: _angular_core.Signal<string>;
1375
1406
  constructor();
1376
1407
  /** Setup effect to track value changes and emit selection events */
1377
1408
  protected abstract setupValueEffect(): void;
@@ -1382,45 +1413,11 @@ declare abstract class BaseUserSelectComponent {
1382
1413
  protected fetchUsers(append?: boolean): Promise<void>;
1383
1414
  /** Load users from USER_PROVIDER with active filter */
1384
1415
  private loadUsersFromProvider;
1416
+ protected t(key: string, variables?: Record<string, string | number>): string;
1385
1417
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseUserSelectComponent, never>;
1386
1418
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<BaseUserSelectComponent, never, never, { "loadUsers": { "alias": "loadUsers"; "required": false; "isSignal": true; }; "placeHolder": { "alias": "placeHolder"; "required": false; "isSignal": true; }; "isEditMode": { "alias": "isEditMode"; "required": true; "isSignal": true; }; "filterActive": { "alias": "filterActive"; "required": false; "isSignal": true; }; "additionalFilters": { "alias": "additionalFilters"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; }, { "onError": "onError"; }, never, never, true, never>;
1387
1419
  }
1388
1420
 
1389
- /**
1390
- * User Select Component - Single user selection with lazy loading.
1391
- *
1392
- * Uses USER_PROVIDER internally by default, or accepts custom `loadUsers` function.
1393
- *
1394
- * Features:
1395
- * - Search with debouncing (handled by lazy-select)
1396
- * - Infinite scroll pagination
1397
- * - Filter active users by default (configurable)
1398
- * - Supports additional filters via `additionalFilters` input
1399
- *
1400
- * @example
1401
- * ```html
1402
- * <!-- Simple usage - uses USER_PROVIDER internally -->
1403
- * <lib-user-select
1404
- * [(value)]="selectedUserId"
1405
- * [isEditMode]="true"
1406
- * />
1407
- *
1408
- * <!-- With custom loadUsers function -->
1409
- * <lib-user-select
1410
- * [(value)]="selectedUserId"
1411
- * [isEditMode]="true"
1412
- * [loadUsers]="customLoadUsers"
1413
- * />
1414
- * ```
1415
- */
1416
- declare class UserSelectComponent extends BaseUserSelectComponent {
1417
- readonly value: _angular_core.ModelSignal<string | null>;
1418
- readonly userSelected: _angular_core.OutputEmitterRef<IUserBasicInfo | null>;
1419
- protected setupValueEffect(): void;
1420
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<UserSelectComponent, never>;
1421
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<UserSelectComponent, "lib-user-select", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "userSelected": "userSelected"; }, never, never, true, never>;
1422
- }
1423
-
1424
1421
  /**
1425
1422
  * User Multi-Select Component - Multiple user selection with lazy loading.
1426
1423
  *
@@ -1450,136 +1447,48 @@ declare class UserSelectComponent extends BaseUserSelectComponent {
1450
1447
  * ```
1451
1448
  */
1452
1449
  declare class UserMultiSelectComponent extends BaseUserSelectComponent {
1450
+ readonly showClear: _angular_core.InputSignal<boolean>;
1453
1451
  readonly value: _angular_core.ModelSignal<string[] | null>;
1454
1452
  readonly usersSelected: _angular_core.OutputEmitterRef<IUserBasicInfo[]>;
1455
1453
  protected setupValueEffect(): void;
1456
1454
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<UserMultiSelectComponent, never>;
1457
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<UserMultiSelectComponent, "lib-user-multi-select", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "usersSelected": "usersSelected"; }, never, never, true, never>;
1455
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<UserMultiSelectComponent, "lib-user-multi-select", never, { "showClear": { "alias": "showClear"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "usersSelected": "usersSelected"; }, never, never, true, never>;
1458
1456
  }
1459
1457
 
1460
1458
  /**
1461
- * File Uploader Component - Drag & drop file upload with type filtering.
1462
- *
1463
- * Pass your own `uploadFile` function - works with any storage API.
1464
- */
1465
- declare class FileUploaderComponent {
1466
- private readonly messageService;
1467
- readonly uploadFile: _angular_core.InputSignal<UploadFileFn>;
1468
- readonly acceptTypes: _angular_core.InputSignal<string[]>;
1469
- readonly multiple: _angular_core.InputSignal<boolean>;
1470
- readonly maxFiles: _angular_core.InputSignal<number>;
1471
- readonly maxSizeMb: _angular_core.InputSignal<number>;
1472
- readonly uploadOptions: _angular_core.InputSignal<IFileUploadOptions>;
1473
- readonly disabled: _angular_core.InputSignal<boolean>;
1474
- readonly showPreview: _angular_core.InputSignal<boolean>;
1475
- readonly autoUpload: _angular_core.InputSignal<boolean>;
1476
- readonly fileUploaded: _angular_core.OutputEmitterRef<IUploadedFile>;
1477
- readonly filesUploaded: _angular_core.OutputEmitterRef<IUploadedFile[]>;
1478
- readonly onError: _angular_core.OutputEmitterRef<Error>;
1479
- readonly fileSelected: _angular_core.OutputEmitterRef<File[]>;
1480
- readonly isUploading: _angular_core.WritableSignal<boolean>;
1481
- readonly isDragOver: _angular_core.WritableSignal<boolean>;
1482
- readonly uploadProgress: _angular_core.WritableSignal<number>;
1483
- readonly uploadingFileName: _angular_core.WritableSignal<string>;
1484
- readonly selectedFiles: _angular_core.WritableSignal<File[]>;
1485
- readonly acceptString: _angular_core.Signal<string>;
1486
- readonly acceptTypesDisplay: _angular_core.Signal<string>;
1487
- onDragOver(event: DragEvent): void;
1488
- onDragLeave(event: DragEvent): void;
1489
- onDrop(event: DragEvent): void;
1490
- onFileSelected(event: Event): void;
1491
- private handleFiles;
1492
- removeFile(file: File): void;
1493
- uploadFiles(files?: File[]): Promise<void>;
1494
- getFileIcon(file: File): string;
1495
- formatSize(bytes: number): string;
1496
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<FileUploaderComponent, never>;
1497
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<FileUploaderComponent, "lib-file-uploader", never, { "uploadFile": { "alias": "uploadFile"; "required": true; "isSignal": true; }; "acceptTypes": { "alias": "acceptTypes"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "maxFiles": { "alias": "maxFiles"; "required": false; "isSignal": true; }; "maxSizeMb": { "alias": "maxSizeMb"; "required": false; "isSignal": true; }; "uploadOptions": { "alias": "uploadOptions"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "showPreview": { "alias": "showPreview"; "required": false; "isSignal": true; }; "autoUpload": { "alias": "autoUpload"; "required": false; "isSignal": true; }; }, { "fileUploaded": "fileUploaded"; "filesUploaded": "filesUploaded"; "onError": "onError"; "fileSelected": "fileSelected"; }, never, never, true, never>;
1498
- }
1499
-
1500
- /**
1501
- * File Selector Dialog - Browse and select existing files with filtering.
1459
+ * User Select Component - Single user selection with lazy loading.
1502
1460
  *
1503
- * Pass your own `loadFiles` function - works with any storage API.
1461
+ * Uses USER_PROVIDER internally by default, or accepts custom `loadUsers` function.
1504
1462
  *
1505
1463
  * Features:
1506
- * - Search with debouncing
1507
- * - File type filtering
1464
+ * - Search with debouncing (handled by lazy-select)
1508
1465
  * - Infinite scroll pagination
1509
- * - Single or multiple selection
1510
- * - File preview with icons
1466
+ * - Filter active users by default (configurable)
1467
+ * - Supports additional filters via `additionalFilters` input
1511
1468
  *
1512
1469
  * @example
1513
- * ```typescript
1514
- * // In component
1515
- * readonly fileService = inject(FileManagerApiService);
1516
- *
1517
- * readonly loadFiles: LoadFilesFn = (filter) =>
1518
- * this.fileService.getAll(filter.search, {
1519
- * pagination: { currentPage: filter.page, pageSize: filter.pageSize },
1520
- * filter: { contentTypes: filter.contentTypes },
1521
- * }).pipe(
1522
- * map(res => ({
1523
- * ...res,
1524
- * data: res.data?.map(f => ({
1525
- * id: f.id,
1526
- * name: f.name,
1527
- * contentType: f.contentType,
1528
- * size: f.size,
1529
- * url: f.url
1530
- * }))
1531
- * }))
1532
- * );
1533
- * ```
1534
- *
1535
1470
  * ```html
1536
- * <lib-file-selector-dialog
1537
- * [(visible)]="showFileSelector"
1538
- * [loadFiles]="loadFiles"
1539
- * [acceptTypes]="['image/*']"
1540
- * [multiple]="false"
1541
- * (fileSelected)="onFileSelected($event)"
1471
+ * <!-- Simple usage - uses USER_PROVIDER internally -->
1472
+ * <lib-user-select
1473
+ * [(value)]="selectedUserId"
1474
+ * [isEditMode]="true"
1475
+ * />
1476
+ *
1477
+ * <!-- With custom loadUsers function -->
1478
+ * <lib-user-select
1479
+ * [(value)]="selectedUserId"
1480
+ * [isEditMode]="true"
1481
+ * [loadUsers]="customLoadUsers"
1542
1482
  * />
1543
1483
  * ```
1544
1484
  */
1545
- declare class FileSelectorDialogComponent {
1546
- private readonly destroyRef;
1547
- private abortController;
1548
- private searchDebounceTimer;
1549
- readonly loadFiles: _angular_core.InputSignal<LoadFilesFn>;
1550
- readonly header: _angular_core.InputSignal<string>;
1551
- readonly acceptTypes: _angular_core.InputSignal<string[]>;
1552
- readonly multiple: _angular_core.InputSignal<boolean>;
1553
- readonly maxSelection: _angular_core.InputSignal<number>;
1554
- readonly pageSize: _angular_core.InputSignal<number>;
1555
- readonly visible: _angular_core.ModelSignal<boolean>;
1556
- readonly fileSelected: _angular_core.OutputEmitterRef<IFileBasicInfo>;
1557
- readonly filesSelected: _angular_core.OutputEmitterRef<IFileBasicInfo[]>;
1558
- readonly closed: _angular_core.OutputEmitterRef<void>;
1559
- readonly onError: _angular_core.OutputEmitterRef<Error>;
1560
- readonly isLoading: _angular_core.WritableSignal<boolean>;
1561
- readonly files: _angular_core.WritableSignal<IFileBasicInfo[]>;
1562
- readonly selectedFiles: _angular_core.WritableSignal<IFileBasicInfo[]>;
1563
- readonly total: _angular_core.WritableSignal<number | undefined>;
1564
- readonly pagination: _angular_core.WritableSignal<IPagination>;
1565
- readonly searchTerm: _angular_core.WritableSignal<string>;
1566
- readonly acceptString: _angular_core.Signal<string>;
1567
- constructor();
1568
- onSearchChange(value: string): void;
1569
- onScroll(event: Event): void;
1570
- toggleSelection(file: IFileBasicInfo): void;
1571
- isSelected(file: IFileBasicInfo): boolean;
1572
- isFileAllowed(file: IFileBasicInfo): boolean;
1573
- isImage(file: IFileBasicInfo): boolean;
1574
- getFileIcon(file: IFileBasicInfo): string;
1575
- formatSize(size: string): string;
1576
- onCancel(): void;
1577
- onConfirm(): void;
1578
- onDialogHide(): void;
1579
- private resetState;
1580
- private fetchFiles;
1581
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<FileSelectorDialogComponent, never>;
1582
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<FileSelectorDialogComponent, "lib-file-selector-dialog", never, { "loadFiles": { "alias": "loadFiles"; "required": true; "isSignal": true; }; "header": { "alias": "header"; "required": false; "isSignal": true; }; "acceptTypes": { "alias": "acceptTypes"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "maxSelection": { "alias": "maxSelection"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "visible": { "alias": "visible"; "required": false; "isSignal": true; }; }, { "visible": "visibleChange"; "fileSelected": "fileSelected"; "filesSelected": "filesSelected"; "closed": "closed"; "onError": "onError"; }, never, never, true, never>;
1485
+ declare class UserSelectComponent extends BaseUserSelectComponent {
1486
+ readonly showClear: _angular_core.InputSignal<boolean>;
1487
+ readonly value: _angular_core.ModelSignal<string | null>;
1488
+ readonly userSelected: _angular_core.OutputEmitterRef<IUserBasicInfo | null>;
1489
+ protected setupValueEffect(): void;
1490
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<UserSelectComponent, never>;
1491
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<UserSelectComponent, "lib-user-select", never, { "showClear": { "alias": "showClear"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "userSelected": "userSelected"; }, never, never, true, never>;
1583
1492
  }
1584
1493
 
1585
1494
  /**
@@ -1636,27 +1545,19 @@ declare const AUTH_STATE_PROVIDER: InjectionToken<IAuthStateProvider>;
1636
1545
  */
1637
1546
  declare const PROFILE_PERMISSION_PROVIDER: InjectionToken<IProfilePermissionProvider>;
1638
1547
  /**
1639
- * Profile Upload Provider Token
1640
- *
1641
- * Provides file upload functionality for profile pictures.
1642
- * Optional - if not configured or storage not enabled, upload section is hidden.
1643
- * Use with `inject(PROFILE_UPLOAD_PROVIDER, { optional: true })`.
1644
- */
1645
- declare const PROFILE_UPLOAD_PROVIDER: InjectionToken<IProfileUploadProvider>;
1646
- /**
1647
- * User List Provider Token
1548
+ * File Provider Token
1648
1549
  *
1649
- * Provides extra actions, columns, and data enrichment for user list.
1650
- * Optional - if not configured, default user list behavior is used.
1651
- * Use with `inject(USER_LIST_PROVIDER, { optional: true })`.
1550
+ * Provides file loading and upload functionality for file selectors.
1551
+ * Optional - if not configured, file selector requires loadFiles/uploadFile inputs.
1552
+ * Use with `inject(FILE_PROVIDER, { optional: true })`.
1652
1553
  *
1653
1554
  * @example
1654
1555
  * // In app.config.ts
1655
1556
  * providers: [
1656
- * { provide: USER_LIST_PROVIDER, useClass: MyUserListProvider },
1557
+ * { provide: FILE_PROVIDER, useClass: StorageFileProvider },
1657
1558
  * ]
1658
1559
  */
1659
- declare const USER_LIST_PROVIDER: InjectionToken<IUserListProvider<IUserListItem>>;
1560
+ declare const FILE_PROVIDER: InjectionToken<IFileProvider>;
1660
1561
 
1661
1562
  /**
1662
1563
  * Permission Guard - Single permission or ILogicNode check.
@@ -1687,303 +1588,14 @@ declare function anyPermissionGuard(permissions: string[], redirectTo?: string):
1687
1588
  */
1688
1589
  declare function allPermissionsGuard(permissions: string[], redirectTo?: string): CanActivateFn;
1689
1590
 
1690
- /**
1691
- * Base class for form page components that handle create/edit operations.
1692
- * Provides common functionality for loading existing items, form submission,
1693
- * navigation, and toast notifications.
1694
- *
1695
- * ## Features
1696
- * - Automatic route parameter handling (loads item when ID is present)
1697
- * - Edit mode detection based on existing item
1698
- * - Unified submit handler for create/update operations
1699
- * - Cancel navigation
1700
- * - Toast messages for success/validation errors
1701
- *
1702
- * ## Usage
1703
- *
1704
- * ```typescript
1705
- * interface IProductFormModel {
1706
- * name: string;
1707
- * price: number;
1708
- * }
1709
- *
1710
- * @Component({
1711
- * selector: 'app-product-form',
1712
- * standalone: true,
1713
- * changeDetection: ChangeDetectionStrategy.OnPush,
1714
- * template: `...`
1715
- * })
1716
- * export class ProductFormComponent extends BaseFormPage<IProduct, IProductFormModel> {
1717
- * private readonly productService = inject(ProductApiService);
1718
- *
1719
- * // Form model signal (private writable, public readonly)
1720
- * private readonly _formModel = signal<IProductFormModel>({ name: '', price: 0 });
1721
- * readonly formModel = this._formModel.asReadonly();
1722
- *
1723
- * // Required abstract implementations
1724
- * getFormModel(): Signal<IProductFormModel> {
1725
- * return this.formModel;
1726
- * }
1727
- *
1728
- * getResourceRoute(): string {
1729
- * return '/products';
1730
- * }
1731
- *
1732
- * getResourceName(): string {
1733
- * return 'Product';
1734
- * }
1735
- *
1736
- * isFormValid(): boolean {
1737
- * const model = this.formModel();
1738
- * return model.name.trim().length > 0 && model.price > 0;
1739
- * }
1740
- *
1741
- * loadItem(id: string): void {
1742
- * this.isLoading.set(true);
1743
- * this.productService.findById(id)
1744
- * .pipe(takeUntilDestroyed(this.destroyRef))
1745
- * .subscribe({
1746
- * next: (response) => {
1747
- * if (response.success && response.data) {
1748
- * this.existingItem.set(response.data);
1749
- * this._formModel.set({
1750
- * name: response.data.name,
1751
- * price: response.data.price,
1752
- * });
1753
- * }
1754
- * this.isLoading.set(false);
1755
- * },
1756
- * error: () => {
1757
- * this.router.navigate([this.getResourceRoute()]);
1758
- * this.isLoading.set(false);
1759
- * },
1760
- * });
1761
- * }
1762
- *
1763
- * createItem(model: IProductFormModel): Observable<ISingleResponse<IProduct>> {
1764
- * return this.productService.insert(model);
1765
- * }
1766
- *
1767
- * updateItem(model: IProductFormModel): Observable<ISingleResponse<IProduct>> {
1768
- * return this.productService.update({ id: this.existingItem()!.id, ...model });
1769
- * }
1770
- * }
1771
- * ```
1772
- *
1773
- * @template T The entity/interface type being edited
1774
- * @template TFormModel The form model interface
1775
- */
1776
- declare abstract class BaseFormPage<T, TFormModel> {
1777
- protected readonly router: Router;
1778
- protected readonly route: ActivatedRoute;
1779
- protected readonly messageService: MessageService;
1780
- protected readonly destroyRef: DestroyRef;
1781
- protected readonly routeParams: Signal<i3.ParamMap | undefined>;
1782
- protected initialized: boolean;
1783
- /** Loading state for async operations */
1784
- readonly isLoading: _angular_core.WritableSignal<boolean>;
1785
- /** The existing item when in edit mode, null when creating */
1786
- readonly existingItem: _angular_core.WritableSignal<T | null>;
1787
- /** Whether the form is in edit mode (has existing item) */
1788
- readonly isEditMode: Signal<boolean>;
1789
- /**
1790
- * Get the form model signal.
1791
- * Returns a readonly Signal - implementations should expose their
1792
- * WritableSignal as readonly through this method.
1793
- */
1794
- abstract getFormModel(): Signal<TFormModel>;
1795
- /**
1796
- * Get the base route for the resource (used for navigation after save/cancel).
1797
- * @example '/products' or '/administration/users'
1798
- */
1799
- abstract getResourceRoute(): string;
1800
- /**
1801
- * Get the display name of the resource for toast messages.
1802
- * @example 'Product' or 'User'
1803
- */
1804
- abstract getResourceName(): string;
1805
- /**
1806
- * Validate the current form model.
1807
- * Return true if the form is valid and can be submitted.
1808
- */
1809
- abstract isFormValid(): boolean;
1810
- /**
1811
- * Load an existing item by ID.
1812
- * Should set existingItem and populate formModel on success.
1813
- * Should handle loading state and navigation on error.
1814
- */
1815
- abstract loadItem(id: string): void;
1816
- /**
1817
- * Create a new item with the given form model.
1818
- * Return an Observable that emits the API response.
1819
- */
1820
- abstract createItem(model: TFormModel): Observable<unknown>;
1821
- /**
1822
- * Update an existing item with the given form model.
1823
- * Return an Observable that emits the API response.
1824
- */
1825
- abstract updateItem(model: TFormModel): Observable<unknown>;
1826
- constructor();
1827
- /**
1828
- * Handle form submission.
1829
- * Validates the form, then calls createItem or updateItem based on mode.
1830
- * Shows appropriate toast messages and navigates back on success.
1831
- */
1832
- onSubmit(): void;
1833
- /**
1834
- * Handle cancel action.
1835
- * Navigates back to the resource list.
1836
- */
1837
- onCancel(): void;
1838
- /**
1839
- * Show validation error toast.
1840
- * Override to customize the validation error message.
1841
- */
1842
- protected showValidationError(): void;
1843
- /**
1844
- * Show success toast.
1845
- * @param detail The success message to display
1846
- */
1847
- protected showSuccess(detail: string): void;
1848
- /**
1849
- * Show error toast.
1850
- * @param detail The error message to display
1851
- */
1852
- protected showError(detail: string): void;
1853
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseFormPage<any, any>, never>;
1854
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<BaseFormPage<any, any>, never, never, {}, {}, never, never, true, never>;
1855
- }
1856
-
1857
- /**
1858
- * Base List Page
1859
- * Abstract directive providing common signals, computed values, and utilities
1860
- * for list page components across all feature packages.
1861
- *
1862
- * Features:
1863
- * - Pagination state management (pageSize, currentPage, total)
1864
- * - Loading state
1865
- * - CRUD navigation helpers
1866
- * - Message display utilities
1867
- * - Delete confirmation with API integration
1868
- * - Company feature flag support
1869
- *
1870
- * Usage:
1871
- * ```typescript
1872
- * @Component({ ... })
1873
- * export class UserListComponent extends BaseListPage<IUser> {
1874
- * getResourceRoute(): string { return '/users'; }
1875
- * getDeleteConfirmMessage(user: IUser): string { return `Delete "${user.name}"?`; }
1876
- * async loadData(): Promise<void> { ... }
1877
- * }
1878
- * ```
1879
- */
1880
- declare abstract class BaseListPage<T> {
1881
- protected readonly router: Router;
1882
- protected readonly messageService: MessageService;
1883
- protected readonly appConfig: _flusys_ng_core.IAppConfig;
1884
- protected readonly confirmationService: ConfirmationService;
1885
- protected readonly destroyRef: DestroyRef;
1886
- /** Items list */
1887
- readonly items: _angular_core.WritableSignal<T[]>;
1888
- /** Loading state */
1889
- readonly isLoading: _angular_core.WritableSignal<boolean>;
1890
- /** Total records for pagination */
1891
- readonly total: _angular_core.WritableSignal<number>;
1892
- /** Page size */
1893
- readonly pageSize: _angular_core.WritableSignal<number>;
1894
- /** First record index (for p-table lazy load) */
1895
- readonly first: _angular_core.WritableSignal<number>;
1896
- /** Current page (0-based for API, derived from first/pageSize) */
1897
- readonly currentPage: _angular_core.Signal<number>;
1898
- /** Show company info if company feature enabled */
1899
- readonly showCompanyInfo: _angular_core.Signal<boolean>;
1900
- /**
1901
- * Abstract method to load data - must be implemented by subclass
1902
- */
1903
- abstract loadData(): Promise<void>;
1904
- /**
1905
- * Get the base route for this resource
1906
- * Used for navigation to create/edit pages
1907
- * @example '/administration/users' or '/storage/folders'
1908
- */
1909
- abstract getResourceRoute(): string;
1910
- /**
1911
- * Get the confirmation message for deleting an item
1912
- * @param item The item to delete
1913
- * @returns Confirmation message string
1914
- */
1915
- abstract getDeleteConfirmMessage(item: T): string;
1916
- /**
1917
- * Navigate to create page
1918
- */
1919
- onCreate(): void;
1920
- /**
1921
- * Navigate to edit page
1922
- * @param id The ID of the item to edit
1923
- */
1924
- onEdit(id: string): void;
1925
- /**
1926
- * Handle page change from p-table lazy load
1927
- */
1928
- onPageChange(event: {
1929
- first?: number | null;
1930
- rows?: number | null;
1931
- }): void;
1932
- /**
1933
- * Get pagination params for API call
1934
- * Returns 0-based page for backend API
1935
- */
1936
- protected getPaginationParams(): {
1937
- currentPage: number;
1938
- pageSize: number;
1939
- };
1940
- /**
1941
- * Show success toast message
1942
- */
1943
- protected showSuccess(detail: string, summary?: string): void;
1944
- /**
1945
- * Show error toast message
1946
- */
1947
- protected showError(detail: string, summary?: string): void;
1948
- /**
1949
- * Show info toast message
1950
- */
1951
- protected showInfo(detail: string, summary?: string): void;
1952
- /**
1953
- * Show warning toast message
1954
- */
1955
- protected showWarn(detail: string, summary?: string): void;
1956
- /**
1957
- * Delete an item with confirmation dialog
1958
- * @param item The item to delete
1959
- * @param idGetter Function to extract ID from item
1960
- * @param deleteApiCall Function that returns Observable for delete API call
1961
- * @param options Optional configuration
1962
- */
1963
- onDelete(item: T, idGetter: (item: T) => string, deleteApiCall: (id: string) => Observable<unknown>, options?: {
1964
- header?: string;
1965
- successMessage?: string;
1966
- errorMessage?: string;
1967
- }): void;
1968
- /**
1969
- * Delete an item with confirmation dialog using async/await
1970
- * @param item The item to delete
1971
- * @param idGetter Function to extract ID from item
1972
- * @param deleteApiCall Async function for delete API call
1973
- * @param options Optional configuration
1974
- */
1975
- onDeleteAsync(item: T, idGetter: (item: T) => string, deleteApiCall: (id: string) => Promise<unknown>, options?: {
1976
- header?: string;
1977
- successMessage?: string;
1978
- errorMessage?: string;
1979
- }): Promise<void>;
1980
- /**
1981
- * Navigate to a route
1982
- */
1983
- protected navigateTo(path: string[]): void;
1984
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseListPage<any>, never>;
1985
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<BaseListPage<any>, never, never, {}, {}, never, never, true, never>;
1986
- }
1591
+ declare function localToUtc(dateStr: string, timeStr: string, timezone: string): Date;
1592
+ declare function utcToLocal(utcDate: Date | string, timezone: string): {
1593
+ date: string;
1594
+ time: string;
1595
+ display: string;
1596
+ };
1597
+ declare function formatInTimezone(utcDate: Date | string, timezone: string, options?: Intl.DateTimeFormatOptions): string;
1598
+ declare function getUserTimezone(): string;
1987
1599
 
1988
1600
  /**
1989
1601
  * Check if user has a specific permission using wildcard matching.
@@ -2035,5 +1647,5 @@ interface ScrollPaginationConfig {
2035
1647
  */
2036
1648
  declare function checkScrollPagination(event: Event, config: ScrollPaginationConfig): IPagination | null;
2037
1649
 
2038
- export { ACTION_PERMISSIONS, AUTH_STATE_PROVIDER, AngularModule, ApiResourceService, ApiResourceService as ApiService, BRANCH_PERMISSIONS, BaseFormControl, BaseFormPage, BaseListPage, BaseUserSelectComponent, COMPANY_ACTION_PERMISSIONS, COMPANY_API_PROVIDER, COMPANY_PERMISSIONS, ContactTypeEnum, CookieService, EMAIL_CONFIG_PERMISSIONS, EMAIL_TEMPLATE_PERMISSIONS, EditModeElementChangerDirective, FILE_PERMISSIONS, FILE_TYPE_FILTERS, FOLDER_PERMISSIONS, FORM_PERMISSIONS, FileSelectorDialogComponent, FileUploaderComponent, FileUrlService, HasPermissionDirective, IconComponent, IconTypeEnum, IsEmptyImageDirective, LazyMultiSelectComponent, LazySelectComponent, PERMISSIONS, PROFILE_PERMISSION_PROVIDER, PROFILE_UPLOAD_PROVIDER, PermissionValidatorService, PlatformService, PreventDefaultDirective, PrimeModule, ROLE_ACTION_PERMISSIONS, ROLE_PERMISSIONS, STORAGE_CONFIG_PERMISSIONS, USER_ACTION_PERMISSIONS, USER_LIST_PROVIDER, USER_PERMISSIONS, USER_PERMISSION_PROVIDER, USER_PROVIDER, USER_ROLE_PERMISSIONS, UserMultiSelectComponent, UserSelectComponent, allPermissionsGuard, anyPermissionGuard, checkScrollPagination, evaluateLogicNode, evaluatePermission, formatFileSize, getAcceptString, getFileIconClass, hasAllPermissions, hasAnyPermission, hasPermission, isFileTypeAllowed, permissionGuard, provideValueAccessor };
2039
- export type { ApiResponse, DeleteType, FilesResponseDto, GetFileUrlsFn, IActionNode, IActivatable, IApiService, IAuthStateProvider, IBaseEntity, IBulkMeta, IBulkResponse, ICompanyApiProvider, ICompanyBasicInfo, IDeleteData, IDropDown, IErrorResponse, IFileBasicInfo, IFileData, IFileSelectFilter, IFileUploadOptions, IFilter, IFilterData, IGroupNode, IListResponse, ILoggedUserInfo, ILogicNode, ILoginResponse, ILoginUserData, IMessageResponse, IMetadata, IOrderable, IPagination, IPaginationMeta, IProfileActionInfo, IProfilePermissionProvider, IProfileRoleInfo, IProfileUploadOptions, IProfileUploadProvider, IProfileUploadResult, IRefreshTokenResponse, IRequestMeta, ISingleResponse, ISoftDeletable, ISort, ITimestampable, IUploadedFile, IUserBasicInfo, IUserBranchPayload, IUserBranchPermission, IUserCompanyPayload, IUserListAction, IUserListColumn, IUserListFilter, IUserListItem, IUserListProvider, IUserPermissionProvider, IUserProvider, IUserSelectFilter, IValidationError, LoadFilesFn, LoadUsersFn, PermissionCode, ScrollPaginationConfig, ServiceName, UploadFileFn };
1650
+ export { ACTION_PERMISSIONS, AUTH_STATE_PROVIDER, AngularModule, ApiResourceService, ApiResourceService as ApiService, BRANCH_PERMISSIONS, BaseFormComponent, BaseFormControl, BaseFormTemplateDirective, BaseListComponent, BaseListTemplateDirective, BaseUserSelectComponent, COMPANY_ACTION_PERMISSIONS, COMPANY_API_PROVIDER, COMPANY_PERMISSIONS, CookieService, EMAIL_CONFIG_PERMISSIONS, EMAIL_TEMPLATE_PERMISSIONS, EVENT_PERMISSIONS, EditModeElementChangerDirective, FILE_PERMISSIONS, FILE_PROVIDER, FILE_TYPE_FILTERS, FOLDER_PERMISSIONS, FORM_PERMISSIONS, FORM_RESULT_PERMISSIONS, FaviconService, FileSelectorDialogComponent, FileUploaderComponent, FileUrlService, HasPermissionDirective, IconComponent, IconTypeEnum, InlineSvgComponent, IsEmptyImageDirective, LANGUAGE_PERMISSIONS, LazyMultiSelectComponent, LazySelectComponent, NOTIFICATION_PERMISSIONS, PERMISSIONS, PROFILE_PERMISSION_PROVIDER, PermissionValidatorService, PlatformService, PreventDefaultDirective, ROLE_ACTION_PERMISSIONS, ROLE_PERMISSIONS, RouterTabsComponent, SHARED_MESSAGES, SKIP_ERROR_TOAST, STORAGE_CONFIG_PERMISSIONS, TRANSLATION_KEY_PERMISSIONS, TRANSLATION_PERMISSIONS, TranslatePipe, TranslateService, UPLOAD_CONFIG_PERMISSIONS, USER_ACTION_PERMISSIONS, USER_PERMISSIONS, USER_PERMISSION_PROVIDER, USER_PROVIDER, USER_ROLE_PERMISSIONS, UserMultiSelectComponent, UserSelectComponent, allPermissionsGuard, anyPermissionGuard, checkScrollPagination, errorCatchingInterceptor, evaluateLogicNode, evaluatePermission, formatFileSize, formatInTimezone, getAcceptString, getFileIconClass, getUserTimezone, hasAllPermissions, hasAnyPermission, hasPermission, isFileTypeAllowed, localToUtc, permissionGuard, provideValueAccessor, resolveTranslationModule, utcToLocal };
1651
+ export type { ActionSeverity, DeleteType, FilesResponseDto, FormFieldType, IActionNode, IActivatable, IApiService, IAuthStateProvider, IBaseEntity, IBulkMeta, IBulkResponse, ICompanyApiProvider, ICompanyBasicInfo, IDeleteData, IDropDown, IFileBasicInfo, IFileProvider, IFileSelectFilter, IFileUploadOptions, IFilter, IFilterData, IFolderBasicInfo, IFormField, IFormSelectOption, IGroupNode, IListResponse, ILoggedUserInfo, ILogicNode, IMessageResponse, IOrderable, IPagination, IPaginationMeta, IProfileActionInfo, IProfilePermissionProvider, IProfileRoleInfo, IRequestMeta, IResolverModuleConfig, ISelectFilter, ISingleResponse, ISoftDeletable, ISort, IStorageConfigBasicInfo, ITableAction, ITableColumn, ITagConfig, ITimestampable, IUploadedFile, IUserBasicInfo, IUserBranchPermission, IUserPermissionProvider, IUserProvider, IUserSelectFilter, LoadUsersFn, PermissionCode, RouterTabItem, ScrollPaginationConfig, TableColumnType, UploadFileFn, UploadMultipleFilesFn };