@flusys/ng-shared 1.1.1-beta → 3.0.0-rc

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,11 +1,11 @@
1
- import * as _angular_core from '@angular/core';
2
- import { Signal, Injector, ResourceRef, model, ElementRef, InjectionToken } from '@angular/core';
3
1
  import { Observable } from 'rxjs';
2
+ import * as _angular_core from '@angular/core';
3
+ import { Signal, Injector, ResourceRef, model, ElementRef, DestroyRef, InjectionToken } from '@angular/core';
4
4
  import * as i1 from '@angular/common';
5
5
  import * as i2 from '@angular/forms';
6
6
  import { ControlValueAccessor } from '@angular/forms';
7
7
  import * as i3 from '@angular/router';
8
- import { CanActivateFn } from '@angular/router';
8
+ import { CanActivateFn, Router, ActivatedRoute } from '@angular/router';
9
9
  import * as i1$1 from 'primeng/autocomplete';
10
10
  import * as i2$1 from 'primeng/avatar';
11
11
  import * as i3$1 from 'primeng/button';
@@ -46,45 +46,190 @@ import * as i36 from 'primeng/tooltip';
46
46
  import * as i37 from 'primeng/treetable';
47
47
  import * as _flusys_ng_shared from '@flusys/ng-shared';
48
48
  import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
49
- import { ApiLoaderService } from '@flusys/ng-core';
50
49
  import { FormValueControl } from '@angular/forms/signals';
50
+ import { MessageService, ConfirmationService } from 'primeng/api';
51
+ import * as _flusys_ng_core from '@flusys/ng-core';
51
52
 
52
53
  /**
53
- * Auth State Provider Interface
54
+ * Centralized Permission Codes
54
55
  *
55
- * Abstracts auth state access for feature packages (form-builder, etc.)
56
- * that need to check authentication status without depending on ng-auth directly.
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.
57
58
  *
58
- * @example
59
- * // In form-builder component
60
- * class PublicFormPageComponent {
61
- * private readonly authStateProvider = inject(AUTH_STATE_PROVIDER);
62
- *
63
- * ngOnInit() {
64
- * this.authStateProvider.initialize().subscribe({
65
- * next: () => this.checkFormAccess(),
66
- * error: () => this.checkFormAccess(),
67
- * });
68
- * }
69
- *
70
- * checkAccess() {
71
- * if (this.authStateProvider.isAuthenticated()) {
72
- * // User is logged in
73
- * }
74
- * }
75
- * }
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)
76
62
  */
77
- interface IAuthStateProvider {
78
- /**
79
- * Signal indicating if user is currently authenticated
80
- */
81
- isAuthenticated: Signal<boolean>;
82
- /**
83
- * Initialize auth state (restore session from cookies/storage)
84
- * Call this before checking isAuthenticated for users returning after login
85
- */
86
- initialize(): Observable<void>;
87
- }
63
+ declare const USER_PERMISSIONS: {
64
+ readonly CREATE: "user.create";
65
+ readonly READ: "user.read";
66
+ readonly UPDATE: "user.update";
67
+ readonly DELETE: "user.delete";
68
+ };
69
+ declare const COMPANY_PERMISSIONS: {
70
+ readonly CREATE: "company.create";
71
+ readonly READ: "company.read";
72
+ readonly UPDATE: "company.update";
73
+ readonly DELETE: "company.delete";
74
+ };
75
+ declare const BRANCH_PERMISSIONS: {
76
+ readonly CREATE: "branch.create";
77
+ readonly READ: "branch.read";
78
+ readonly UPDATE: "branch.update";
79
+ readonly DELETE: "branch.delete";
80
+ };
81
+ declare const ACTION_PERMISSIONS: {
82
+ readonly CREATE: "action.create";
83
+ readonly READ: "action.read";
84
+ readonly UPDATE: "action.update";
85
+ readonly DELETE: "action.delete";
86
+ };
87
+ declare const ROLE_PERMISSIONS: {
88
+ readonly CREATE: "role.create";
89
+ readonly READ: "role.read";
90
+ readonly UPDATE: "role.update";
91
+ readonly DELETE: "role.delete";
92
+ };
93
+ declare const ROLE_ACTION_PERMISSIONS: {
94
+ readonly READ: "role-action.read";
95
+ readonly ASSIGN: "role-action.assign";
96
+ };
97
+ declare const USER_ROLE_PERMISSIONS: {
98
+ readonly READ: "user-role.read";
99
+ readonly ASSIGN: "user-role.assign";
100
+ };
101
+ declare const USER_ACTION_PERMISSIONS: {
102
+ readonly READ: "user-action.read";
103
+ readonly ASSIGN: "user-action.assign";
104
+ };
105
+ declare const COMPANY_ACTION_PERMISSIONS: {
106
+ readonly READ: "company-action.read";
107
+ readonly ASSIGN: "company-action.assign";
108
+ };
109
+ declare const FILE_PERMISSIONS: {
110
+ readonly CREATE: "file.create";
111
+ readonly READ: "file.read";
112
+ readonly UPDATE: "file.update";
113
+ readonly DELETE: "file.delete";
114
+ };
115
+ declare const FOLDER_PERMISSIONS: {
116
+ readonly CREATE: "folder.create";
117
+ readonly READ: "folder.read";
118
+ readonly UPDATE: "folder.update";
119
+ readonly DELETE: "folder.delete";
120
+ };
121
+ declare const STORAGE_CONFIG_PERMISSIONS: {
122
+ readonly CREATE: "storage-config.create";
123
+ readonly READ: "storage-config.read";
124
+ readonly UPDATE: "storage-config.update";
125
+ readonly DELETE: "storage-config.delete";
126
+ };
127
+ declare const EMAIL_CONFIG_PERMISSIONS: {
128
+ readonly CREATE: "email-config.create";
129
+ readonly READ: "email-config.read";
130
+ readonly UPDATE: "email-config.update";
131
+ readonly DELETE: "email-config.delete";
132
+ };
133
+ declare const EMAIL_TEMPLATE_PERMISSIONS: {
134
+ readonly CREATE: "email-template.create";
135
+ readonly READ: "email-template.read";
136
+ readonly UPDATE: "email-template.update";
137
+ readonly DELETE: "email-template.delete";
138
+ };
139
+ declare const FORM_PERMISSIONS: {
140
+ readonly CREATE: "form.create";
141
+ readonly READ: "form.read";
142
+ readonly UPDATE: "form.update";
143
+ readonly DELETE: "form.delete";
144
+ };
145
+ /**
146
+ * All permission codes grouped by module
147
+ */
148
+ declare const PERMISSIONS: {
149
+ readonly USER: {
150
+ readonly CREATE: "user.create";
151
+ readonly READ: "user.read";
152
+ readonly UPDATE: "user.update";
153
+ readonly DELETE: "user.delete";
154
+ };
155
+ readonly COMPANY: {
156
+ readonly CREATE: "company.create";
157
+ readonly READ: "company.read";
158
+ readonly UPDATE: "company.update";
159
+ readonly DELETE: "company.delete";
160
+ };
161
+ readonly BRANCH: {
162
+ readonly CREATE: "branch.create";
163
+ readonly READ: "branch.read";
164
+ readonly UPDATE: "branch.update";
165
+ readonly DELETE: "branch.delete";
166
+ };
167
+ readonly ACTION: {
168
+ readonly CREATE: "action.create";
169
+ readonly READ: "action.read";
170
+ readonly UPDATE: "action.update";
171
+ readonly DELETE: "action.delete";
172
+ };
173
+ readonly ROLE: {
174
+ readonly CREATE: "role.create";
175
+ readonly READ: "role.read";
176
+ readonly UPDATE: "role.update";
177
+ readonly DELETE: "role.delete";
178
+ };
179
+ readonly ROLE_ACTION: {
180
+ readonly READ: "role-action.read";
181
+ readonly ASSIGN: "role-action.assign";
182
+ };
183
+ readonly USER_ROLE: {
184
+ readonly READ: "user-role.read";
185
+ readonly ASSIGN: "user-role.assign";
186
+ };
187
+ readonly USER_ACTION: {
188
+ readonly READ: "user-action.read";
189
+ readonly ASSIGN: "user-action.assign";
190
+ };
191
+ readonly COMPANY_ACTION: {
192
+ readonly READ: "company-action.read";
193
+ readonly ASSIGN: "company-action.assign";
194
+ };
195
+ readonly FILE: {
196
+ readonly CREATE: "file.create";
197
+ readonly READ: "file.read";
198
+ readonly UPDATE: "file.update";
199
+ readonly DELETE: "file.delete";
200
+ };
201
+ readonly FOLDER: {
202
+ readonly CREATE: "folder.create";
203
+ readonly READ: "folder.read";
204
+ readonly UPDATE: "folder.update";
205
+ readonly DELETE: "folder.delete";
206
+ };
207
+ readonly STORAGE_CONFIG: {
208
+ readonly CREATE: "storage-config.create";
209
+ readonly READ: "storage-config.read";
210
+ readonly UPDATE: "storage-config.update";
211
+ readonly DELETE: "storage-config.delete";
212
+ };
213
+ readonly EMAIL_CONFIG: {
214
+ readonly CREATE: "email-config.create";
215
+ readonly READ: "email-config.read";
216
+ readonly UPDATE: "email-config.update";
217
+ readonly DELETE: "email-config.delete";
218
+ };
219
+ readonly EMAIL_TEMPLATE: {
220
+ readonly CREATE: "email-template.create";
221
+ readonly READ: "email-template.read";
222
+ readonly UPDATE: "email-template.update";
223
+ readonly DELETE: "email-template.delete";
224
+ };
225
+ readonly FORM: {
226
+ readonly CREATE: "form.create";
227
+ readonly READ: "form.read";
228
+ readonly UPDATE: "form.update";
229
+ readonly DELETE: "form.delete";
230
+ };
231
+ };
232
+ type PermissionCode = (typeof PERMISSIONS)[keyof typeof PERMISSIONS][keyof (typeof PERMISSIONS)[keyof typeof PERMISSIONS]];
88
233
 
89
234
  /**
90
235
  * Base entity interface - matches backend Identity entity
@@ -143,6 +288,61 @@ interface ILoggedUserInfo {
143
288
  companyLogoId?: string;
144
289
  branchLogoId?: string;
145
290
  }
291
+ /**
292
+ * Simple dropdown item for select components
293
+ */
294
+ interface IDropDown {
295
+ label: string;
296
+ value: string;
297
+ }
298
+ /**
299
+ * Delete operation types
300
+ * - 'delete': Soft delete (sets deletedAt timestamp)
301
+ * - 'restore': Restore soft-deleted item (clears deletedAt)
302
+ * - 'permanent': Permanently delete from database
303
+ */
304
+ type DeleteType = 'delete' | 'restore' | 'permanent';
305
+ /**
306
+ * Delete request payload - matches backend DeleteDto
307
+ */
308
+ interface IDeleteData {
309
+ /** Single ID or array of IDs to delete */
310
+ id: string | string[];
311
+ /** Type of delete operation */
312
+ type: DeleteType;
313
+ }
314
+ /** Action node - checks a single permission */
315
+ interface IActionNode {
316
+ type: 'action';
317
+ actionId: string;
318
+ }
319
+ /** Group node - combines children with AND/OR logic */
320
+ interface IGroupNode {
321
+ type: 'group';
322
+ operator: 'AND' | 'OR';
323
+ children: ILogicNode[];
324
+ }
325
+ /** Permission logic tree (discriminated union of action/group) */
326
+ type ILogicNode = IActionNode | IGroupNode;
327
+
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
+ }
146
346
 
147
347
  /**
148
348
  * Request metadata added by backend ResponseMetaInterceptor
@@ -284,158 +484,6 @@ interface IFileData {
284
484
  createdAt: Date;
285
485
  }
286
486
 
287
- /**
288
- * Company basic info for dropdowns
289
- */
290
- interface ICompanyBasicInfo {
291
- id: string;
292
- name: string;
293
- slug?: string;
294
- }
295
- interface ICompanyApiProvider {
296
- /**
297
- * Get list of companies with pagination
298
- */
299
- getCompanies(filter?: {
300
- page?: number;
301
- pageSize?: number;
302
- search?: string;
303
- [key: string]: any;
304
- }): Observable<IListResponse<ICompanyBasicInfo>>;
305
- }
306
-
307
- /**
308
- * Delete operation types
309
- * - 'delete': Soft delete (sets deletedAt timestamp)
310
- * - 'restore': Restore soft-deleted item (clears deletedAt)
311
- * - 'permanent': Permanently delete from database
312
- */
313
- type DeleteType = 'delete' | 'restore' | 'permanent';
314
- /**
315
- * Delete request payload - matches backend DeleteDto
316
- */
317
- interface IDeleteData {
318
- /** Single ID or array of IDs to delete */
319
- id: string | string[];
320
- /** Type of delete operation */
321
- type: DeleteType;
322
- }
323
-
324
- interface IDropDown {
325
- label: string;
326
- value: string;
327
- }
328
-
329
- interface IPagination {
330
- pageSize: number;
331
- currentPage: number;
332
- }
333
- interface ISort {
334
- [key: string]: 'ASC' | 'DESC';
335
- }
336
- interface IFilter {
337
- [key: string]: any;
338
- }
339
- interface IFilterData {
340
- filter?: IFilter;
341
- pagination?: IPagination;
342
- select?: string[];
343
- sort?: ISort;
344
- withDeleted?: boolean;
345
- extraKey?: string[];
346
- }
347
-
348
- /** Action node - checks a single permission */
349
- interface IActionNode {
350
- type: 'action';
351
- actionId: string;
352
- }
353
- /** Group node - combines children with AND/OR logic */
354
- interface IGroupNode {
355
- type: 'group';
356
- operator: 'AND' | 'OR';
357
- children: ILogicNode[];
358
- }
359
- /** Permission logic tree (discriminated union of action/group) */
360
- type ILogicNode = IActionNode | IGroupNode;
361
-
362
- /**
363
- * User Permission Provider Interface
364
- *
365
- * Abstracts user permission data access operations.
366
- * Implemented by auth package, used by IAM for user permission queries.
367
- *
368
- * @example
369
- * // In IAM component
370
- * class UserActionSelectorComponent {
371
- * private readonly userPermissionProvider = inject(USER_PERMISSION_PROVIDER);
372
- *
373
- * async loadUserBranches(userId: string) {
374
- * const response = await this.userPermissionProvider
375
- * .getUserBranchPermissions(userId, '')
376
- * .toPromise();
377
- * this.branches.set(response?.data ?? []);
378
- * }
379
- * }
380
- */
381
- interface IUserPermissionProvider {
382
- /**
383
- * Get user's branch permissions
384
- */
385
- getUserBranchPermissions(userId: string): Observable<ISingleResponse<any>>;
386
- }
387
-
388
- /**
389
- * User data for dropdowns and selectors
390
- */
391
- interface IUserBasicInfo {
392
- id: string;
393
- name: string;
394
- email: string;
395
- }
396
- /**
397
- * User Provider Interface
398
- *
399
- * Abstracts user data access for IAM and other feature packages.
400
- * Implemented by auth package, used by IAM for user selection in permission assignment.
401
- *
402
- * @example
403
- * // In IAM component
404
- * class UserActionSelectorComponent {
405
- * private readonly userProvider = inject(USER_PROVIDER);
406
- *
407
- * loadUsers() {
408
- * this.userProvider.getUsers({ page: 0, pageSize: 50 }).subscribe(users => {
409
- * this.users.set(users.data);
410
- * });
411
- * }
412
- * }
413
- */
414
- interface IUserProvider {
415
- /**
416
- * Get list of users with pagination
417
- * @param filter Optional filter (page, pageSize, search, etc.)
418
- */
419
- getUsers(filter?: {
420
- page?: number;
421
- pageSize?: number;
422
- search?: string;
423
- companyId?: string;
424
- branchId?: string;
425
- [key: string]: any;
426
- }): Observable<IListResponse<IUserBasicInfo>>;
427
- }
428
-
429
- /** Filter params passed to loadUsers function */
430
- interface IUserSelectFilter {
431
- page: number;
432
- pageSize: number;
433
- search: string;
434
- [key: string]: unknown;
435
- }
436
- /** Function type for loading users */
437
- type LoadUsersFn = (filter: IUserSelectFilter) => Observable<IListResponse<IUserBasicInfo>>;
438
-
439
487
  /**
440
488
  * Basic file info for selectors and displays
441
489
  */
@@ -476,7 +524,6 @@ interface IFileSelectFilter {
476
524
  search: string;
477
525
  contentTypes?: string[];
478
526
  folderId?: string;
479
- [key: string]: unknown;
480
527
  }
481
528
  /**
482
529
  * Function type for loading files
@@ -517,6 +564,79 @@ declare function getFileIconClass(contentType: string): string;
517
564
  */
518
565
  declare function formatFileSize(sizeInKb: string | number): string;
519
566
 
567
+ /**
568
+ * Auth State Provider Interface
569
+ *
570
+ * Abstracts auth state access for feature packages (form-builder, etc.)
571
+ * that need to check authentication status without depending on ng-auth directly.
572
+ */
573
+ interface IAuthStateProvider {
574
+ /** Signal indicating if user is currently authenticated */
575
+ isAuthenticated: Signal<boolean>;
576
+ /** Initialize auth state (restore session from cookies/storage) */
577
+ initialize(): Observable<void>;
578
+ }
579
+ /**
580
+ * User data for dropdowns and selectors
581
+ */
582
+ interface IUserBasicInfo {
583
+ id: string;
584
+ name: string;
585
+ email: string;
586
+ }
587
+ /**
588
+ * User Provider Interface - Abstracts user data access for IAM and other feature packages.
589
+ */
590
+ interface IUserProvider {
591
+ getUsers(filter?: {
592
+ page?: number;
593
+ pageSize?: number;
594
+ search?: string;
595
+ companyId?: string;
596
+ branchId?: string;
597
+ isActive?: boolean;
598
+ }): Observable<IListResponse<IUserBasicInfo>>;
599
+ }
600
+ /** Filter params passed to loadUsers function */
601
+ interface IUserSelectFilter {
602
+ page: number;
603
+ pageSize: number;
604
+ search: string;
605
+ }
606
+ /** Function type for loading users */
607
+ type LoadUsersFn = (filter: IUserSelectFilter) => Observable<IListResponse<IUserBasicInfo>>;
608
+ /**
609
+ * User branch permission data
610
+ */
611
+ interface IUserBranchPermission {
612
+ branchId: string;
613
+ branchName: string;
614
+ companyId: string;
615
+ }
616
+ /**
617
+ * User Permission Provider Interface - Abstracts user permission data access operations.
618
+ */
619
+ interface IUserPermissionProvider {
620
+ getUserBranchPermissions(userId: string): Observable<ISingleResponse<IUserBranchPermission[]>>;
621
+ }
622
+ /**
623
+ * Company basic info for dropdowns
624
+ */
625
+ interface ICompanyBasicInfo {
626
+ id: string;
627
+ name: string;
628
+ slug?: string;
629
+ }
630
+ /**
631
+ * Company API Provider Interface
632
+ */
633
+ interface ICompanyApiProvider {
634
+ getCompanies(filter?: {
635
+ page?: number;
636
+ pageSize?: number;
637
+ search?: string;
638
+ }): Observable<IListResponse<ICompanyBasicInfo>>;
639
+ }
520
640
  /**
521
641
  * User role info for profile display
522
642
  */
@@ -535,89 +655,39 @@ interface IProfileActionInfo {
535
655
  description?: string | null;
536
656
  }
537
657
  /**
538
- * Profile Permission Provider Interface
539
- *
540
- * Abstracts permission data access for profile page.
541
- * Implemented by ng-iam, consumed by ng-auth profile page.
542
- * Optional injection - if not provided, permissions section is hidden.
543
- *
544
- * @example
545
- * // In profile component
546
- * private readonly permissionProvider = inject(PROFILE_PERMISSION_PROVIDER, { optional: true });
547
- *
548
- * ngOnInit() {
549
- * if (this.permissionProvider) {
550
- * this.loadPermissions();
551
- * }
552
- * }
658
+ * Profile Permission Provider Interface - Abstracts permission data access for profile page.
553
659
  */
554
660
  interface IProfilePermissionProvider {
555
- /**
556
- * Get user's assigned roles
557
- * @param userId User ID
558
- * @param branchId Optional branch ID for branch-scoped roles
559
- */
560
661
  getUserRoles(userId: string, branchId?: string): Observable<ISingleResponse<IProfileRoleInfo[]>>;
561
- /**
562
- * Get user's direct actions
563
- * @param userId User ID
564
- * @param branchId Optional branch ID for branch-scoped actions
565
- */
566
662
  getUserActions(userId: string, branchId?: string): Observable<ISingleResponse<IProfileActionInfo[]>>;
567
663
  }
568
-
569
664
  /**
570
665
  * Uploaded file result with file manager ID
571
666
  */
572
667
  interface IProfileUploadResult {
573
- /** File manager ID (UUID) for storing in profilePictureId */
574
668
  id: string;
575
- /** Original file name */
576
669
  name: string;
577
- /** Storage key/path */
578
670
  key: string;
579
- /** File size in bytes */
580
671
  size: number;
581
- /** MIME type */
582
672
  contentType: string;
583
673
  }
584
674
  /**
585
675
  * Profile Upload Options
586
676
  */
587
677
  interface IProfileUploadOptions {
588
- /** Folder path for organizing uploads */
589
678
  folderPath?: string;
590
- /** Enable image compression */
591
679
  compress?: boolean;
592
- /** Max width for image compression */
593
680
  maxWidth?: number;
594
- /** Max height for image compression */
595
681
  maxHeight?: number;
596
682
  }
597
683
  /**
598
- * Profile Upload Provider Interface
599
- *
600
- * Provides file upload functionality for profile pictures.
601
- * Implemented by ng-storage, consumed by ng-auth profile page.
602
- *
603
- * This interface enables ng-auth to use storage functionality
604
- * without directly depending on ng-storage package.
684
+ * Profile Upload Provider Interface - Provides file upload functionality for profile pictures.
605
685
  */
606
686
  interface IProfileUploadProvider {
607
- /**
608
- * Upload profile picture and register in file manager
609
- * Returns file manager ID (UUID) for storing in user.profilePictureId
610
- *
611
- * @param file - File to upload
612
- * @param options - Upload options (compression, folder, etc.)
613
- * @returns Observable with upload result including file manager ID
614
- */
615
687
  uploadProfilePicture(file: File, options?: IProfileUploadOptions): Observable<ISingleResponse<IProfileUploadResult>>;
616
688
  }
617
-
618
689
  /**
619
690
  * Base user interface for list operations
620
- * Extends this with app-specific user fields
621
691
  */
622
692
  interface IUserListItem {
623
693
  id: string;
@@ -625,140 +695,56 @@ interface IUserListItem {
625
695
  email: string;
626
696
  phone?: string;
627
697
  isActive?: boolean;
628
- [key: string]: unknown;
629
698
  }
630
699
  /**
631
700
  * User list action definition
632
- * @template T User type, defaults to IUserListItem
633
701
  */
634
702
  interface IUserListAction<T = IUserListItem> {
635
- /** Unique action identifier */
636
703
  id: string;
637
- /** Display label */
638
704
  label: string;
639
- /** PrimeNG icon class (e.g., 'pi pi-pencil') */
640
705
  icon?: string;
641
- /** Severity for styling (e.g., 'primary', 'danger', 'warning') */
642
706
  severity?: 'primary' | 'secondary' | 'success' | 'info' | 'warn' | 'danger' | 'help' | 'contrast';
643
- /** Permission code required (checked via hasPermission) */
644
707
  permission?: string;
645
- /** Tooltip text */
646
708
  tooltip?: string;
647
- /** Whether action is disabled */
648
709
  disabled?: boolean | ((user: T) => boolean);
649
- /** Whether action is visible */
650
710
  visible?: boolean | ((user: T) => boolean);
651
711
  }
652
712
  /**
653
713
  * Extra column definition for user list
654
714
  */
655
715
  interface IUserListColumn {
656
- /** Column field name */
657
716
  field: string;
658
- /** Column header label */
659
717
  header: string;
660
- /** Column width */
661
718
  width?: string;
662
- /** Whether column is sortable */
663
719
  sortable?: boolean;
664
- /** Whether column is filterable */
665
720
  filterable?: boolean;
666
- /** Custom template type for rendering */
667
721
  templateType?: 'text' | 'badge' | 'date' | 'boolean' | 'custom';
668
722
  }
669
- /**
670
- * User List Provider Interface
671
- *
672
- * Allows consuming applications to extend user list pages with:
673
- * - Extra columns
674
- * - Extra row actions
675
- * - Extra toolbar actions
676
- * - Custom data enrichment
677
- *
678
- * This follows the Provider Interface Pattern:
679
- * - ng-shared defines the interface (this file)
680
- * - Consuming apps (via ng-iam or app-specific) implement the interface
681
- * - ng-auth user list optionally injects and uses the implementation
682
- *
683
- * @template T User type, defaults to IUserListItem
684
- *
685
- * @example
686
- * // In app.config.ts
687
- * providers: [
688
- * { provide: USER_LIST_PROVIDER, useClass: MyUserListProvider },
689
- * ]
690
- *
691
- * // Implementation
692
- * @Injectable({ providedIn: 'root' })
693
- * export class MyUserListProvider implements IUserListProvider {
694
- * getExtraRowActions() {
695
- * return [
696
- * { id: 'assign-role', label: 'Assign Role', icon: 'pi pi-users' },
697
- * ];
698
- * }
699
- * }
700
- */
701
- interface IUserListProvider<T extends IUserListItem = IUserListItem> {
702
- /**
703
- * Get extra columns to display in user list
704
- * @returns Array of extra column definitions
705
- */
706
- getExtraColumns?(): IUserListColumn[];
707
- /**
708
- * Get extra row-level actions (per-user actions)
709
- * Displayed in actions column for each row
710
- * @returns Array of action definitions
711
- */
712
- getExtraRowActions?(): IUserListAction<T>[];
713
- /**
714
- * Get extra toolbar actions
715
- * Displayed in toolbar above the list
716
- * @returns Array of action definitions
717
- */
718
- getExtraToolbarActions?(): IUserListAction<T>[];
719
- /**
720
- * Handle row action click
721
- * @param actionId Action identifier
722
- * @param user User data from the row
723
- */
724
- onRowAction?(actionId: string, user: T): void;
725
- /**
726
- * Handle toolbar action click
727
- * @param actionId Action identifier
728
- * @param selectedUsers Currently selected users (for bulk actions)
729
- */
730
- onToolbarAction?(actionId: string, selectedUsers: T[]): void;
731
- /**
732
- * Enrich user list data with extra fields
733
- * Called after data is loaded from API
734
- * @param users List of users from API
735
- * @returns Observable of enriched users
736
- */
737
- enrichListData?(users: T[]): Observable<T[]>;
738
- /**
739
- * Get extra filters for user list
740
- * @returns Array of filter definitions
741
- */
742
- getExtraFilters?(): IUserListFilter[];
743
- }
744
723
  /**
745
724
  * Extra filter definition for user list
746
725
  */
747
726
  interface IUserListFilter {
748
- /** Filter field name */
749
727
  field: string;
750
- /** Filter label */
751
728
  label: string;
752
- /** Filter type */
753
729
  type: 'text' | 'dropdown' | 'multiselect' | 'date' | 'boolean';
754
- /** Options for dropdown/multiselect */
755
730
  options?: {
756
731
  label: string;
757
732
  value: string | number | boolean;
758
733
  }[];
759
- /** Placeholder text */
760
734
  placeholder?: string;
761
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
+ }
762
748
 
763
749
  declare enum ContactTypeEnum {
764
750
  PHONE = 1,
@@ -780,15 +766,6 @@ declare class CookieService {
780
766
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<CookieService>;
781
767
  }
782
768
 
783
- /**
784
- * Request DTO for fetching file URLs
785
- */
786
- interface GetFilesRequestDto {
787
- id: string;
788
- }
789
- /**
790
- * Response DTO with file information including URL
791
- */
792
769
  interface FilesResponseDto {
793
770
  id: string;
794
771
  name: string;
@@ -797,113 +774,47 @@ interface FilesResponseDto {
797
774
  }
798
775
  /**
799
776
  * Service to fetch file URLs from the backend.
800
- * Uses POST /file-manager/get-files endpoint which:
801
- * - Handles presigned URLs for cloud storage (AWS S3, Azure)
802
- * - Auto-refreshes expired URLs
803
- * - Validates file access permissions
804
- * - Works with all storage providers (Local, S3, Azure, SFTP)
777
+ * Handles presigned URLs for cloud storage, auto-refresh, and caching.
805
778
  */
806
779
  declare class FileUrlService {
807
780
  private readonly http;
808
781
  private readonly appConfig;
809
- /** Cache of file URLs by file ID */
810
- private readonly urlCache;
811
- /**
812
- * Get file URL by ID from cache (reactive signal)
813
- */
782
+ private readonly _cache;
783
+ readonly cache: Signal<Map<string, FilesResponseDto>>;
784
+ /** Get file URL by ID from cache (synchronous) */
814
785
  getFileUrl(fileId: string | null | undefined): string | null;
815
- /**
816
- * Get file URL signal (computed from cache)
817
- */
818
- fileUrlSignal(fileId: string | null | undefined): _angular_core.Signal<string | null>;
819
- /**
820
- * Fetch file URLs from backend and update cache.
821
- * Skips IDs already in cache to prevent duplicate calls.
822
- * Returns Observable of fetched files (including cached ones).
823
- */
786
+ /** Get file URL as computed signal */
787
+ fileUrlSignal(fileId: string | null | undefined): Signal<string | null>;
788
+ /** Fetch file URLs from backend and update cache */
824
789
  fetchFileUrls(fileIds: string[], forceRefresh?: boolean): Observable<FilesResponseDto[]>;
825
- /**
826
- * Fetch a single file URL.
827
- * Uses cache if available to prevent duplicate calls.
828
- * Returns Observable of file info or null if not found.
829
- */
790
+ /** Fetch single file URL (delegates to fetchFileUrls) */
830
791
  fetchSingleFileUrl(fileId: string, forceRefresh?: boolean): Observable<FilesResponseDto | null>;
831
- /**
832
- * Clear the URL cache.
833
- * Useful on logout or when switching contexts.
834
- */
792
+ /** Clear entire cache */
835
793
  clearCache(): void;
836
- /**
837
- * Remove specific file from cache.
838
- */
794
+ /** Remove specific file from cache */
839
795
  removeFromCache(fileId: string): void;
796
+ private addToCache;
797
+ private getFromCache;
840
798
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<FileUrlService, never>;
841
799
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<FileUrlService>;
842
800
  }
843
801
 
844
802
  /**
845
- * Permission Validator Service
846
- *
847
- * Centralized service for permission validation across all packages.
848
- * Provides signal-based state management and reactive permission checking.
849
- *
850
- * Features:
851
- * - Signal-based permission storage
852
- * - Individual permission checks
853
- * - Permission change detection
854
- * - Reactive permission state updates
855
- *
856
- * Usage:
857
- * ```typescript
858
- * // In component
859
- * readonly permissionValidator = inject(PermissionValidatorService);
860
- *
861
- * // Set permissions (typically from auth/IAM)
862
- * this.permissionValidator.setPermissions(['user.view', 'user.create']);
863
- *
864
- * // Check individual permission
865
- * if (this.permissionValidator.hasPermission('user.view')) {
866
- * // Show UI element
867
- * }
868
- *
869
- * // Access current permissions reactively
870
- * const permissions = this.permissionValidator.permissions();
871
- * ```
872
- *
873
- * @packageDocumentation
803
+ * Permission state management service.
804
+ * Provides signal-based storage and permission checking with wildcard support.
874
805
  */
875
806
  declare class PermissionValidatorService {
876
- /**
877
- * Private writable signal for permissions
878
- */
879
807
  private readonly _permissions;
880
- /**
881
- * Readonly permission signal for external consumers
882
- */
883
808
  readonly permissions: _angular_core.Signal<string[]>;
884
- /**
885
- * Private writable signal for loaded state
886
- */
887
809
  private readonly _isLoaded;
888
- /**
889
- * Set permissions (replaces existing permissions)
890
- * @param permissions - Array of permission codes
891
- */
810
+ readonly isLoaded: _angular_core.Signal<boolean>;
811
+ /** Set permissions (replaces existing) */
892
812
  setPermissions(permissions: string[]): void;
893
- /**
894
- * Clear all permissions
895
- */
813
+ /** Clear all permissions */
896
814
  clearPermissions(): void;
897
- /**
898
- * Check if user has a specific permission
899
- * @param permissionCode - Required permission code
900
- * @returns True if user has permission
901
- */
902
- hasPermission(permissionCode: string): boolean;
903
- /**
904
- * Check if permissions are loaded
905
- * @returns True if permissions have been loaded
906
- */
815
+ /** Check if user has permission (supports wildcards: '*', 'module.*') */
816
+ hasPermission(code: string): boolean;
817
+ /** @deprecated Use `isLoaded()` signal instead */
907
818
  isPermissionsLoaded(): boolean;
908
819
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<PermissionValidatorService, never>;
909
820
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<PermissionValidatorService>;
@@ -1015,9 +926,9 @@ declare class IsEmptyImageDirective {
1015
926
  }
1016
927
 
1017
928
  declare class PreventDefaultDirective {
1018
- eventType: _angular_core.InputSignal<"click" | "keydown" | "keyup">;
1019
- preventKey: _angular_core.InputSignal<string | undefined>;
1020
- action: _angular_core.OutputEmitterRef<Event>;
929
+ readonly eventType: _angular_core.InputSignal<"click" | "keydown" | "keyup">;
930
+ readonly preventKey: _angular_core.InputSignal<string | undefined>;
931
+ readonly action: _angular_core.OutputEmitterRef<Event>;
1021
932
  onClick(event: MouseEvent): void;
1022
933
  onKeydown(event: KeyboardEvent): void;
1023
934
  onKeyup(event: KeyboardEvent): void;
@@ -1028,7 +939,7 @@ declare class PreventDefaultDirective {
1028
939
 
1029
940
  declare class AngularModule {
1030
941
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<AngularModule, never>;
1031
- static ɵmod: _angular_core.ɵɵNgModuleDeclaration<AngularModule, never, [typeof i1.CommonModule, typeof i2.FormsModule, typeof i2.ReactiveFormsModule, typeof i3.RouterOutlet, typeof i3.RouterLink, 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 IsEmptyImageDirective, typeof i1.NgOptimizedImage, typeof i1.NgComponentOutlet, typeof PreventDefaultDirective]>;
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]>;
1032
943
  static ɵinj: _angular_core.ɵɵInjectorDeclaration<AngularModule>;
1033
944
  }
1034
945
 
@@ -1104,7 +1015,6 @@ interface IApiService<DtoT, InterfaceT> {
1104
1015
  */
1105
1016
  declare abstract class ApiResourceService<DtoT, InterfaceT> implements IApiService<DtoT, InterfaceT> {
1106
1017
  protected readonly baseUrl: string;
1107
- protected readonly loaderService: ApiLoaderService;
1108
1018
  protected readonly injector: Injector;
1109
1019
  protected readonly http: HttpClient;
1110
1020
  protected readonly moduleApiName: string;
@@ -1119,6 +1029,12 @@ declare abstract class ApiResourceService<DtoT, InterfaceT> implements IApiServi
1119
1029
  private _listResource;
1120
1030
  /** Whether the list resource has been initialized */
1121
1031
  private _resourceInitialized;
1032
+ /**
1033
+ * Signal to track resource initialization for computed signals.
1034
+ * This allows computed signals to re-evaluate when the resource is created.
1035
+ * Without this, computed signals would not detect when _listResource changes from null.
1036
+ */
1037
+ private readonly _resourceInitSignal;
1122
1038
  /** Get or create the list resource (lazy initialization) */
1123
1039
  get listResource(): ResourceRef<IListResponse<InterfaceT> | undefined>;
1124
1040
  /**
@@ -1127,15 +1043,30 @@ declare abstract class ApiResourceService<DtoT, InterfaceT> implements IApiServi
1127
1043
  * Uses runInInjectionContext to support lazy initialization outside constructor.
1128
1044
  */
1129
1045
  initListResource(): void;
1130
- /** Whether data is currently loading */
1046
+ /**
1047
+ * Whether data is currently loading.
1048
+ * Tracks _resourceInitSignal to re-evaluate when resource is created.
1049
+ */
1131
1050
  readonly isLoading: _angular_core.Signal<boolean>;
1132
- /** List data array */
1051
+ /**
1052
+ * List data array.
1053
+ * Tracks _resourceInitSignal to re-evaluate when resource is created.
1054
+ */
1133
1055
  readonly data: _angular_core.Signal<InterfaceT[]>;
1134
- /** Total count of items */
1056
+ /**
1057
+ * Total count of items.
1058
+ * Tracks _resourceInitSignal to re-evaluate when resource is created.
1059
+ */
1135
1060
  readonly total: _angular_core.Signal<number>;
1136
- /** Pagination metadata */
1061
+ /**
1062
+ * Pagination metadata.
1063
+ * Tracks _resourceInitSignal to re-evaluate when resource is created.
1064
+ */
1137
1065
  readonly pageInfo: _angular_core.Signal<_flusys_ng_shared.IPaginationMeta | undefined>;
1138
- /** Whether there are more pages */
1066
+ /**
1067
+ * Whether there are more pages.
1068
+ * Tracks _resourceInitSignal to re-evaluate when resource is created.
1069
+ */
1139
1070
  readonly hasMore: _angular_core.Signal<boolean>;
1140
1071
  constructor(moduleApiName: string, http: HttpClient);
1141
1072
  protected getHttpOptions(endpoint: string, params?: HttpParams): {
@@ -1228,14 +1159,6 @@ declare abstract class ApiResourceService<DtoT, InterfaceT> implements IApiServi
1228
1159
  deleteAsync(deleteDto: IDeleteData): Promise<IMessageResponse>;
1229
1160
  }
1230
1161
 
1231
- declare class IconComponent {
1232
- icon: _angular_core.InputSignal<string>;
1233
- iconType: _angular_core.InputSignal<IconTypeEnum | undefined>;
1234
- protected readonly IconTypeEnum: typeof IconTypeEnum;
1235
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<IconComponent, never>;
1236
- 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>;
1237
- }
1238
-
1239
1162
  /**
1240
1163
  * Base class for form controls that support ALL Angular form patterns:
1241
1164
  *
@@ -1308,6 +1231,31 @@ declare abstract class BaseFormControl<T> implements ControlValueAccessor, FormV
1308
1231
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseFormControl<any>, never>;
1309
1232
  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>;
1310
1233
  }
1234
+ /**
1235
+ * Factory function to provide NG_VALUE_ACCESSOR for a component.
1236
+ * Use in component providers array.
1237
+ *
1238
+ * @example
1239
+ * ```typescript
1240
+ * @Component({
1241
+ * providers: [provideValueAccessor(LazySelectComponent)]
1242
+ * })
1243
+ * export class LazySelectComponent extends BaseFormControl<string | null> {}
1244
+ * ```
1245
+ */
1246
+ declare function provideValueAccessor<T extends new (...args: unknown[]) => ControlValueAccessor>(component: T): {
1247
+ provide: _angular_core.InjectionToken<readonly ControlValueAccessor[]>;
1248
+ useExisting: _angular_core.Type<any>;
1249
+ multi: boolean;
1250
+ };
1251
+
1252
+ declare class IconComponent {
1253
+ icon: _angular_core.InputSignal<string>;
1254
+ iconType: _angular_core.InputSignal<IconTypeEnum | undefined>;
1255
+ protected readonly IconTypeEnum: typeof IconTypeEnum;
1256
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<IconComponent, never>;
1257
+ 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>;
1258
+ }
1311
1259
 
1312
1260
  /**
1313
1261
  * Lazy-loading multi-select component with search, pagination, and select-all.
@@ -1318,31 +1266,28 @@ declare abstract class BaseFormControl<T> implements ControlValueAccessor, FormV
1318
1266
  * - Signal forms: `[formField]="formTree.field"`
1319
1267
  */
1320
1268
  declare class LazyMultiSelectComponent extends BaseFormControl<string[] | null> {
1269
+ private readonly destroyRef;
1270
+ private readonly onDocumentClickBound;
1271
+ readonly pSelectRef: _angular_core.Signal<ElementRef<HTMLDivElement>>;
1321
1272
  readonly placeHolder: _angular_core.InputSignal<string>;
1322
1273
  readonly isEditMode: _angular_core.InputSignal<boolean>;
1323
1274
  readonly isLoading: _angular_core.InputSignal<boolean>;
1324
1275
  readonly total: _angular_core.InputSignal<number | undefined>;
1325
1276
  readonly pagination: _angular_core.InputSignal<IPagination>;
1326
1277
  readonly selectDataList: _angular_core.InputSignal<IDropDown[]>;
1327
- /** Two-way bound value using model() for signal forms compatibility */
1328
1278
  readonly value: _angular_core.ModelSignal<string[] | null>;
1329
1279
  readonly onSearch: _angular_core.OutputEmitterRef<string>;
1330
1280
  readonly onPagination: _angular_core.OutputEmitterRef<IPagination>;
1331
1281
  readonly searchTerm: _angular_core.WritableSignal<string>;
1332
- /** Computed: Display text for selected values (replaces getSelectedValue method) */
1282
+ readonly openOptions: _angular_core.WritableSignal<boolean>;
1333
1283
  readonly selectedValueDisplay: _angular_core.Signal<string>;
1334
- /** Computed: Whether all items are selected (replaces isSelectAll signal) */
1335
1284
  readonly isSelectAll: _angular_core.Signal<boolean>;
1336
1285
  constructor();
1337
- private readonly onScrollBound;
1338
- readonly multiScrollContainer: _angular_core.Signal<ElementRef<HTMLDivElement>>;
1339
1286
  onScroll(event: Event): void;
1340
- readonly pSelectRef: _angular_core.Signal<ElementRef<HTMLDivElement>>;
1341
- openOptions: _angular_core.WritableSignal<boolean>;
1342
1287
  onSelectClick(event: Event): void;
1343
1288
  onOverlayClick(event: Event): void;
1344
- handleDocumentClick(event: MouseEvent): void;
1345
- isSelected(data: IDropDown): boolean | undefined;
1289
+ private handleDocumentClick;
1290
+ isSelected(data: IDropDown): boolean;
1346
1291
  key(option: IDropDown): string;
1347
1292
  selectValue(event: CheckboxChangeEvent, option: IDropDown): void;
1348
1293
  changeSelectAll(event: CheckboxChangeEvent): void;
@@ -1360,6 +1305,10 @@ declare class LazyMultiSelectComponent extends BaseFormControl<string[] | null>
1360
1305
  * - Signal forms: `[formField]="formTree.field"`
1361
1306
  */
1362
1307
  declare class LazySelectComponent extends BaseFormControl<string | null> {
1308
+ private readonly destroyRef;
1309
+ private readonly onScrollBound;
1310
+ private scrollTargetEl;
1311
+ readonly scrollContainer: _angular_core.Signal<ElementRef<HTMLDivElement>>;
1363
1312
  readonly placeHolder: _angular_core.InputSignal<string>;
1364
1313
  readonly optionLabel: _angular_core.InputSignal<string>;
1365
1314
  readonly optionValue: _angular_core.InputSignal<string>;
@@ -1368,16 +1317,12 @@ declare class LazySelectComponent extends BaseFormControl<string | null> {
1368
1317
  readonly total: _angular_core.InputSignal<number | undefined>;
1369
1318
  readonly pagination: _angular_core.InputSignal<IPagination>;
1370
1319
  readonly selectDataList: _angular_core.InputSignal<IDropDown[]>;
1371
- /** Two-way bound value using model() for signal forms compatibility */
1372
1320
  readonly value: _angular_core.ModelSignal<string | null>;
1373
1321
  readonly onSearch: _angular_core.OutputEmitterRef<string>;
1374
1322
  readonly onPagination: _angular_core.OutputEmitterRef<IPagination>;
1375
1323
  readonly searchTerm: _angular_core.WritableSignal<string>;
1324
+ readonly isPanelShow: _angular_core.WritableSignal<boolean>;
1376
1325
  constructor();
1377
- isPanelShow: _angular_core.WritableSignal<boolean>;
1378
- scrollTargetEl: HTMLElement | null;
1379
- private readonly onScrollBound;
1380
- readonly scrollContainer: _angular_core.Signal<ElementRef<HTMLDivElement>>;
1381
1326
  onScroll(event: Event): void;
1382
1327
  showPanel(): void;
1383
1328
  onBlur(): void;
@@ -1385,6 +1330,45 @@ declare class LazySelectComponent extends BaseFormControl<string | null> {
1385
1330
  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>;
1386
1331
  }
1387
1332
 
1333
+ /**
1334
+ * Base class for user selection components.
1335
+ * Provides shared user loading, pagination, and search functionality.
1336
+ *
1337
+ * Subclasses must implement:
1338
+ * - `setupValueEffect()` to track value changes and emit selection events
1339
+ */
1340
+ declare abstract class BaseUserSelectComponent {
1341
+ protected readonly destroyRef: DestroyRef;
1342
+ protected readonly injector: Injector;
1343
+ protected readonly userProvider: IUserProvider;
1344
+ protected abortController: AbortController | null;
1345
+ readonly loadUsers: _angular_core.InputSignal<LoadUsersFn | undefined>;
1346
+ readonly placeHolder: _angular_core.InputSignal<string>;
1347
+ readonly isEditMode: _angular_core.InputSignal<boolean>;
1348
+ readonly filterActive: _angular_core.InputSignal<boolean>;
1349
+ readonly additionalFilters: _angular_core.InputSignal<Record<string, unknown>>;
1350
+ readonly pageSize: _angular_core.InputSignal<number>;
1351
+ readonly onError: _angular_core.OutputEmitterRef<Error>;
1352
+ readonly isLoading: _angular_core.WritableSignal<boolean>;
1353
+ readonly users: _angular_core.WritableSignal<IUserBasicInfo[]>;
1354
+ readonly total: _angular_core.WritableSignal<number | undefined>;
1355
+ readonly pagination: _angular_core.WritableSignal<IPagination>;
1356
+ readonly searchTerm: _angular_core.WritableSignal<string>;
1357
+ readonly dropdownUsers: _angular_core.Signal<IDropDown[]>;
1358
+ constructor();
1359
+ /** Setup effect to track value changes and emit selection events */
1360
+ protected abstract setupValueEffect(): void;
1361
+ handleSearch(search: string): void;
1362
+ handlePagination(pagination: IPagination): void;
1363
+ /** Reload users (useful when filters change externally) */
1364
+ reload(): void;
1365
+ protected fetchUsers(append?: boolean): Promise<void>;
1366
+ /** Load users from USER_PROVIDER with active filter */
1367
+ private loadUsersFromProvider;
1368
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseUserSelectComponent, never>;
1369
+ 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>;
1370
+ }
1371
+
1388
1372
  /**
1389
1373
  * User Select Component - Single user selection with lazy loading.
1390
1374
  *
@@ -1412,35 +1396,12 @@ declare class LazySelectComponent extends BaseFormControl<string | null> {
1412
1396
  * />
1413
1397
  * ```
1414
1398
  */
1415
- declare class UserSelectComponent {
1416
- private readonly destroyRef;
1417
- private readonly userProvider;
1418
- private abortController;
1419
- readonly loadUsers: _angular_core.InputSignal<LoadUsersFn | undefined>;
1420
- readonly placeHolder: _angular_core.InputSignal<string>;
1421
- readonly isEditMode: _angular_core.InputSignal<boolean>;
1422
- readonly filterActive: _angular_core.InputSignal<boolean>;
1423
- readonly additionalFilters: _angular_core.InputSignal<Record<string, unknown>>;
1424
- readonly pageSize: _angular_core.InputSignal<number>;
1399
+ declare class UserSelectComponent extends BaseUserSelectComponent {
1425
1400
  readonly value: _angular_core.ModelSignal<string | null>;
1426
1401
  readonly userSelected: _angular_core.OutputEmitterRef<IUserBasicInfo | null>;
1427
- readonly onError: _angular_core.OutputEmitterRef<Error>;
1428
- readonly isLoading: _angular_core.WritableSignal<boolean>;
1429
- readonly users: _angular_core.WritableSignal<IUserBasicInfo[]>;
1430
- readonly total: _angular_core.WritableSignal<number | undefined>;
1431
- readonly pagination: _angular_core.WritableSignal<IPagination>;
1432
- readonly searchTerm: _angular_core.WritableSignal<string>;
1433
- readonly dropdownUsers: _angular_core.Signal<IDropDown[]>;
1434
- constructor();
1435
- handleSearch(search: string): void;
1436
- handlePagination(pagination: IPagination): void;
1437
- private fetchUsers;
1438
- /** Load users from USER_PROVIDER with active filter */
1439
- private loadUsersFromProvider;
1440
- /** Reload users (useful when filters change externally) */
1441
- reload(): void;
1402
+ protected setupValueEffect(): void;
1442
1403
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<UserSelectComponent, never>;
1443
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<UserSelectComponent, "lib-user-select", 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; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "userSelected": "userSelected"; "onError": "onError"; }, never, never, true, never>;
1404
+ 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>;
1444
1405
  }
1445
1406
 
1446
1407
  /**
@@ -1471,76 +1432,18 @@ declare class UserSelectComponent {
1471
1432
  * />
1472
1433
  * ```
1473
1434
  */
1474
- declare class UserMultiSelectComponent {
1475
- private readonly destroyRef;
1476
- private readonly userProvider;
1477
- private abortController;
1478
- readonly loadUsers: _angular_core.InputSignal<LoadUsersFn | undefined>;
1479
- readonly placeHolder: _angular_core.InputSignal<string>;
1480
- readonly isEditMode: _angular_core.InputSignal<boolean>;
1481
- readonly filterActive: _angular_core.InputSignal<boolean>;
1482
- readonly additionalFilters: _angular_core.InputSignal<Record<string, unknown>>;
1483
- readonly pageSize: _angular_core.InputSignal<number>;
1435
+ declare class UserMultiSelectComponent extends BaseUserSelectComponent {
1484
1436
  readonly value: _angular_core.ModelSignal<string[] | null>;
1485
1437
  readonly usersSelected: _angular_core.OutputEmitterRef<IUserBasicInfo[]>;
1486
- readonly onError: _angular_core.OutputEmitterRef<Error>;
1487
- readonly isLoading: _angular_core.WritableSignal<boolean>;
1488
- readonly users: _angular_core.WritableSignal<IUserBasicInfo[]>;
1489
- readonly total: _angular_core.WritableSignal<number | undefined>;
1490
- readonly pagination: _angular_core.WritableSignal<IPagination>;
1491
- readonly searchTerm: _angular_core.WritableSignal<string>;
1492
- readonly dropdownUsers: _angular_core.Signal<IDropDown[]>;
1493
- constructor();
1494
- handleSearch(search: string): void;
1495
- handlePagination(pagination: IPagination): void;
1496
- private fetchUsers;
1497
- /** Load users from USER_PROVIDER with active filter */
1498
- private loadUsersFromProvider;
1499
- /** Reload users (useful when filters change externally) */
1500
- reload(): void;
1438
+ protected setupValueEffect(): void;
1501
1439
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<UserMultiSelectComponent, never>;
1502
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<UserMultiSelectComponent, "lib-user-multi-select", 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; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "usersSelected": "usersSelected"; "onError": "onError"; }, never, never, true, never>;
1440
+ 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>;
1503
1441
  }
1504
1442
 
1505
1443
  /**
1506
1444
  * File Uploader Component - Drag & drop file upload with type filtering.
1507
1445
  *
1508
1446
  * Pass your own `uploadFile` function - works with any storage API.
1509
- *
1510
- * Features:
1511
- * - Drag & drop support
1512
- * - File type filtering (images, documents, etc.)
1513
- * - Upload progress indication
1514
- * - Multiple file support (optional)
1515
- * - Image compression options
1516
- *
1517
- * @example
1518
- * ```typescript
1519
- * // In component
1520
- * readonly uploadService = inject(UploadService);
1521
- *
1522
- * readonly uploadFile: UploadFileFn = (file, options) =>
1523
- * this.uploadService.uploadSingleFile(file, options);
1524
- * ```
1525
- *
1526
- * ```html
1527
- * <!-- Single image upload -->
1528
- * <lib-file-uploader
1529
- * [uploadFile]="uploadFile"
1530
- * [acceptTypes]="['image/*']"
1531
- * [multiple]="false"
1532
- * (fileUploaded)="onFileUploaded($event)"
1533
- * />
1534
- *
1535
- * <!-- Multiple document upload -->
1536
- * <lib-file-uploader
1537
- * [uploadFile]="uploadFile"
1538
- * [acceptTypes]="FILE_TYPE_FILTERS.DOCUMENTS"
1539
- * [multiple]="true"
1540
- * [maxFiles]="5"
1541
- * (filesUploaded)="onFilesUploaded($event)"
1542
- * />
1543
- * ```
1544
1447
  */
1545
1448
  declare class FileUploaderComponent {
1546
1449
  private readonly messageService;
@@ -1739,63 +1642,340 @@ declare const PROFILE_UPLOAD_PROVIDER: InjectionToken<IProfileUploadProvider>;
1739
1642
  declare const USER_LIST_PROVIDER: InjectionToken<IUserListProvider<IUserListItem>>;
1740
1643
 
1741
1644
  /**
1742
- * Permission Guard
1743
- *
1744
- * Route-level guard for permission-based access control.
1745
- * Validates permissions before allowing navigation.
1746
- *
1747
- * Features:
1748
- * - Single permission check
1749
- * - Complex ILogicNode logic trees
1750
- * - Configurable redirect URL
1751
- * - Debug logging for denied access
1645
+ * Permission Guard - Single permission or ILogicNode check.
1752
1646
  *
1753
1647
  * @example
1754
1648
  * ```typescript
1755
- * // Simple permission check
1756
1649
  * { path: 'users', canActivate: [permissionGuard('user.view')] }
1757
- *
1758
- * // Complex logic
1759
- * { path: 'admin', canActivate: [permissionGuard({
1760
- * id: 'root',
1761
- * type: 'group',
1762
- * operator: 'AND',
1763
- * children: [
1764
- * { id: '1', type: 'action', actionId: 'admin.view' },
1765
- * { id: '2', type: 'action', actionId: 'admin.manage' }
1766
- * ]
1767
- * })] }
1768
- *
1769
- * // With custom redirect
1770
- * { path: 'users', canActivate: [permissionGuard('user.view', '/access-denied')] }
1650
+ * { path: 'admin', canActivate: [permissionGuard(logicNode, '/access-denied')] }
1771
1651
  * ```
1772
1652
  */
1773
1653
  declare function permissionGuard(permission: string | ILogicNode, redirectTo?: string): CanActivateFn;
1774
1654
  /**
1775
- * Any Permission Guard (OR logic)
1776
- *
1777
- * Allows access if user has ANY of the specified permissions.
1655
+ * Any Permission Guard (OR logic) - Access if user has ANY permission.
1778
1656
  *
1779
1657
  * @example
1780
1658
  * ```typescript
1781
- * // Allow if user has view OR create permission
1782
1659
  * { path: 'users', canActivate: [anyPermissionGuard(['user.view', 'user.create'])] }
1783
1660
  * ```
1784
1661
  */
1785
1662
  declare function anyPermissionGuard(permissions: string[], redirectTo?: string): CanActivateFn;
1786
1663
  /**
1787
- * All Permissions Guard (AND logic)
1788
- *
1789
- * Allows access only if user has ALL of the specified permissions.
1664
+ * All Permissions Guard (AND logic) - Access only if user has ALL permissions.
1790
1665
  *
1791
1666
  * @example
1792
1667
  * ```typescript
1793
- * // Allow only if user has BOTH view AND create permissions
1794
1668
  * { path: 'admin', canActivate: [allPermissionsGuard(['admin.view', 'admin.manage'])] }
1795
1669
  * ```
1796
1670
  */
1797
1671
  declare function allPermissionsGuard(permissions: string[], redirectTo?: string): CanActivateFn;
1798
1672
 
1673
+ /**
1674
+ * Base class for form page components that handle create/edit operations.
1675
+ * Provides common functionality for loading existing items, form submission,
1676
+ * navigation, and toast notifications.
1677
+ *
1678
+ * ## Features
1679
+ * - Automatic route parameter handling (loads item when ID is present)
1680
+ * - Edit mode detection based on existing item
1681
+ * - Unified submit handler for create/update operations
1682
+ * - Cancel navigation
1683
+ * - Toast messages for success/validation errors
1684
+ *
1685
+ * ## Usage
1686
+ *
1687
+ * ```typescript
1688
+ * interface IProductFormModel {
1689
+ * name: string;
1690
+ * price: number;
1691
+ * }
1692
+ *
1693
+ * @Component({
1694
+ * selector: 'app-product-form',
1695
+ * standalone: true,
1696
+ * changeDetection: ChangeDetectionStrategy.OnPush,
1697
+ * template: `...`
1698
+ * })
1699
+ * export class ProductFormComponent extends BaseFormPage<IProduct, IProductFormModel> {
1700
+ * private readonly productService = inject(ProductApiService);
1701
+ *
1702
+ * // Form model signal (private writable, public readonly)
1703
+ * private readonly _formModel = signal<IProductFormModel>({ name: '', price: 0 });
1704
+ * readonly formModel = this._formModel.asReadonly();
1705
+ *
1706
+ * // Required abstract implementations
1707
+ * getFormModel(): Signal<IProductFormModel> {
1708
+ * return this.formModel;
1709
+ * }
1710
+ *
1711
+ * getResourceRoute(): string {
1712
+ * return '/products';
1713
+ * }
1714
+ *
1715
+ * getResourceName(): string {
1716
+ * return 'Product';
1717
+ * }
1718
+ *
1719
+ * isFormValid(): boolean {
1720
+ * const model = this.formModel();
1721
+ * return model.name.trim().length > 0 && model.price > 0;
1722
+ * }
1723
+ *
1724
+ * loadItem(id: string): void {
1725
+ * this.isLoading.set(true);
1726
+ * this.productService.findById(id)
1727
+ * .pipe(takeUntilDestroyed(this.destroyRef))
1728
+ * .subscribe({
1729
+ * next: (response) => {
1730
+ * if (response.success && response.data) {
1731
+ * this.existingItem.set(response.data);
1732
+ * this._formModel.set({
1733
+ * name: response.data.name,
1734
+ * price: response.data.price,
1735
+ * });
1736
+ * }
1737
+ * this.isLoading.set(false);
1738
+ * },
1739
+ * error: () => {
1740
+ * this.router.navigate([this.getResourceRoute()]);
1741
+ * this.isLoading.set(false);
1742
+ * },
1743
+ * });
1744
+ * }
1745
+ *
1746
+ * createItem(model: IProductFormModel): Observable<ISingleResponse<IProduct>> {
1747
+ * return this.productService.insert(model);
1748
+ * }
1749
+ *
1750
+ * updateItem(model: IProductFormModel): Observable<ISingleResponse<IProduct>> {
1751
+ * return this.productService.update({ id: this.existingItem()!.id, ...model });
1752
+ * }
1753
+ * }
1754
+ * ```
1755
+ *
1756
+ * @template T The entity/interface type being edited
1757
+ * @template TFormModel The form model interface
1758
+ */
1759
+ declare abstract class BaseFormPage<T, TFormModel> {
1760
+ protected readonly router: Router;
1761
+ protected readonly route: ActivatedRoute;
1762
+ protected readonly messageService: MessageService;
1763
+ protected readonly destroyRef: DestroyRef;
1764
+ protected readonly routeParams: Signal<i3.ParamMap | undefined>;
1765
+ protected initialized: boolean;
1766
+ /** Loading state for async operations */
1767
+ readonly isLoading: _angular_core.WritableSignal<boolean>;
1768
+ /** The existing item when in edit mode, null when creating */
1769
+ readonly existingItem: _angular_core.WritableSignal<T | null>;
1770
+ /** Whether the form is in edit mode (has existing item) */
1771
+ readonly isEditMode: Signal<boolean>;
1772
+ /**
1773
+ * Get the form model signal.
1774
+ * Returns a readonly Signal - implementations should expose their
1775
+ * WritableSignal as readonly through this method.
1776
+ */
1777
+ abstract getFormModel(): Signal<TFormModel>;
1778
+ /**
1779
+ * Get the base route for the resource (used for navigation after save/cancel).
1780
+ * @example '/products' or '/administration/users'
1781
+ */
1782
+ abstract getResourceRoute(): string;
1783
+ /**
1784
+ * Get the display name of the resource for toast messages.
1785
+ * @example 'Product' or 'User'
1786
+ */
1787
+ abstract getResourceName(): string;
1788
+ /**
1789
+ * Validate the current form model.
1790
+ * Return true if the form is valid and can be submitted.
1791
+ */
1792
+ abstract isFormValid(): boolean;
1793
+ /**
1794
+ * Load an existing item by ID.
1795
+ * Should set existingItem and populate formModel on success.
1796
+ * Should handle loading state and navigation on error.
1797
+ */
1798
+ abstract loadItem(id: string): void;
1799
+ /**
1800
+ * Create a new item with the given form model.
1801
+ * Return an Observable that emits the API response.
1802
+ */
1803
+ abstract createItem(model: TFormModel): Observable<unknown>;
1804
+ /**
1805
+ * Update an existing item with the given form model.
1806
+ * Return an Observable that emits the API response.
1807
+ */
1808
+ abstract updateItem(model: TFormModel): Observable<unknown>;
1809
+ constructor();
1810
+ /**
1811
+ * Handle form submission.
1812
+ * Validates the form, then calls createItem or updateItem based on mode.
1813
+ * Shows appropriate toast messages and navigates back on success.
1814
+ */
1815
+ onSubmit(): void;
1816
+ /**
1817
+ * Handle cancel action.
1818
+ * Navigates back to the resource list.
1819
+ */
1820
+ onCancel(): void;
1821
+ /**
1822
+ * Show validation error toast.
1823
+ * Override to customize the validation error message.
1824
+ */
1825
+ protected showValidationError(): void;
1826
+ /**
1827
+ * Show success toast.
1828
+ * @param detail The success message to display
1829
+ */
1830
+ protected showSuccess(detail: string): void;
1831
+ /**
1832
+ * Show error toast.
1833
+ * @param detail The error message to display
1834
+ */
1835
+ protected showError(detail: string): void;
1836
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseFormPage<any, any>, never>;
1837
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<BaseFormPage<any, any>, never, never, {}, {}, never, never, true, never>;
1838
+ }
1839
+
1840
+ /**
1841
+ * Base List Page
1842
+ * Abstract directive providing common signals, computed values, and utilities
1843
+ * for list page components across all feature packages.
1844
+ *
1845
+ * Features:
1846
+ * - Pagination state management (pageSize, currentPage, total)
1847
+ * - Loading state
1848
+ * - CRUD navigation helpers
1849
+ * - Message display utilities
1850
+ * - Delete confirmation with API integration
1851
+ * - Company feature flag support
1852
+ *
1853
+ * Usage:
1854
+ * ```typescript
1855
+ * @Component({ ... })
1856
+ * export class UserListComponent extends BaseListPage<IUser> {
1857
+ * getResourceRoute(): string { return '/users'; }
1858
+ * getDeleteConfirmMessage(user: IUser): string { return `Delete "${user.name}"?`; }
1859
+ * async loadData(): Promise<void> { ... }
1860
+ * }
1861
+ * ```
1862
+ */
1863
+ declare abstract class BaseListPage<T> {
1864
+ protected readonly router: Router;
1865
+ protected readonly messageService: MessageService;
1866
+ protected readonly appConfig: _flusys_ng_core.IAppConfig;
1867
+ protected readonly confirmationService: ConfirmationService;
1868
+ protected readonly destroyRef: DestroyRef;
1869
+ /** Items list */
1870
+ readonly items: _angular_core.WritableSignal<T[]>;
1871
+ /** Loading state */
1872
+ readonly isLoading: _angular_core.WritableSignal<boolean>;
1873
+ /** Total records for pagination */
1874
+ readonly total: _angular_core.WritableSignal<number>;
1875
+ /** Page size */
1876
+ readonly pageSize: _angular_core.WritableSignal<number>;
1877
+ /** First record index (for p-table lazy load) */
1878
+ readonly first: _angular_core.WritableSignal<number>;
1879
+ /** Current page (0-based for API, derived from first/pageSize) */
1880
+ readonly currentPage: _angular_core.Signal<number>;
1881
+ /** Show company info if company feature enabled */
1882
+ readonly showCompanyInfo: _angular_core.Signal<boolean>;
1883
+ /**
1884
+ * Abstract method to load data - must be implemented by subclass
1885
+ */
1886
+ abstract loadData(): Promise<void>;
1887
+ /**
1888
+ * Get the base route for this resource
1889
+ * Used for navigation to create/edit pages
1890
+ * @example '/administration/users' or '/storage/folders'
1891
+ */
1892
+ abstract getResourceRoute(): string;
1893
+ /**
1894
+ * Get the confirmation message for deleting an item
1895
+ * @param item The item to delete
1896
+ * @returns Confirmation message string
1897
+ */
1898
+ abstract getDeleteConfirmMessage(item: T): string;
1899
+ /**
1900
+ * Navigate to create page
1901
+ */
1902
+ onCreate(): void;
1903
+ /**
1904
+ * Navigate to edit page
1905
+ * @param id The ID of the item to edit
1906
+ */
1907
+ onEdit(id: string): void;
1908
+ /**
1909
+ * Handle page change from p-table lazy load
1910
+ */
1911
+ onPageChange(event: {
1912
+ first?: number | null;
1913
+ rows?: number | null;
1914
+ }): void;
1915
+ /**
1916
+ * Get pagination params for API call
1917
+ * Returns 0-based page for backend API
1918
+ */
1919
+ protected getPaginationParams(): {
1920
+ currentPage: number;
1921
+ pageSize: number;
1922
+ };
1923
+ /**
1924
+ * Show success toast message
1925
+ */
1926
+ protected showSuccess(detail: string, summary?: string): void;
1927
+ /**
1928
+ * Show error toast message
1929
+ */
1930
+ protected showError(detail: string, summary?: string): void;
1931
+ /**
1932
+ * Show info toast message
1933
+ */
1934
+ protected showInfo(detail: string, summary?: string): void;
1935
+ /**
1936
+ * Show warning toast message
1937
+ */
1938
+ protected showWarn(detail: string, summary?: string): void;
1939
+ /**
1940
+ * Delete an item with confirmation dialog
1941
+ * @param item The item to delete
1942
+ * @param idGetter Function to extract ID from item
1943
+ * @param deleteApiCall Function that returns Observable for delete API call
1944
+ * @param options Optional configuration
1945
+ */
1946
+ onDelete(item: T, idGetter: (item: T) => string, deleteApiCall: (id: string) => Observable<unknown>, options?: {
1947
+ header?: string;
1948
+ successMessage?: string;
1949
+ errorMessage?: string;
1950
+ }): void;
1951
+ /**
1952
+ * Delete an item with confirmation dialog using async/await
1953
+ * @param item The item to delete
1954
+ * @param idGetter Function to extract ID from item
1955
+ * @param deleteApiCall Async function for delete API call
1956
+ * @param options Optional configuration
1957
+ */
1958
+ onDeleteAsync(item: T, idGetter: (item: T) => string, deleteApiCall: (id: string) => Promise<unknown>, options?: {
1959
+ header?: string;
1960
+ successMessage?: string;
1961
+ errorMessage?: string;
1962
+ }): Promise<void>;
1963
+ /**
1964
+ * Navigate to a route
1965
+ */
1966
+ protected navigateTo(path: string[]): void;
1967
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseListPage<any>, never>;
1968
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<BaseListPage<any>, never, never, {}, {}, never, never, true, never>;
1969
+ }
1970
+
1971
+ /**
1972
+ * Check if user has a specific permission using wildcard matching.
1973
+ * Supports:
1974
+ * - Exact match: 'user.create' matches 'user.create'
1975
+ * - Full wildcard: '*' matches everything
1976
+ * - Module wildcard: 'user.*' matches 'user.create', 'user.read', etc.
1977
+ */
1978
+ declare function hasPermission(requiredPermission: string, userPermissions: string[]): boolean;
1799
1979
  /** Evaluate permission logic (string or ILogicNode) against user permissions */
1800
1980
  declare function evaluatePermission(logic: string | ILogicNode | null | undefined, permissions: string[]): boolean;
1801
1981
  /** Recursively evaluate an ILogicNode tree */
@@ -1805,5 +1985,38 @@ declare function hasAnyPermission(permissionCodes: string[], permissions: string
1805
1985
  /** Check if user has ALL of the specified permissions (AND logic) */
1806
1986
  declare function hasAllPermissions(permissionCodes: string[], permissions: string[]): boolean;
1807
1987
 
1808
- export { AUTH_STATE_PROVIDER, AngularModule, ApiResourceService, ApiResourceService as ApiService, COMPANY_API_PROVIDER, ContactTypeEnum, CookieService, EditModeElementChangerDirective, FILE_TYPE_FILTERS, FileSelectorDialogComponent, FileUploaderComponent, FileUrlService, HasPermissionDirective, IconComponent, IconTypeEnum, IsEmptyImageDirective, LazyMultiSelectComponent, LazySelectComponent, PROFILE_PERMISSION_PROVIDER, PROFILE_UPLOAD_PROVIDER, PermissionValidatorService, PlatformService, PreventDefaultDirective, PrimeModule, USER_LIST_PROVIDER, USER_PERMISSION_PROVIDER, USER_PROVIDER, UserMultiSelectComponent, UserSelectComponent, allPermissionsGuard, anyPermissionGuard, evaluateLogicNode, evaluatePermission, formatFileSize, getAcceptString, getFileIconClass, hasAllPermissions, hasAnyPermission, isFileTypeAllowed, permissionGuard };
1809
- export type { ApiResponse, DeleteType, FilesResponseDto, GetFileUrlsFn, GetFilesRequestDto, 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, IUserCompanyPayload, IUserListAction, IUserListColumn, IUserListFilter, IUserListItem, IUserListProvider, IUserPermissionProvider, IUserProvider, IUserSelectFilter, IValidationError, LoadFilesFn, LoadUsersFn, UploadFileFn };
1988
+ /**
1989
+ * Configuration for scroll pagination behavior
1990
+ */
1991
+ interface ScrollPaginationConfig {
1992
+ /** Distance from bottom to trigger pagination (default: 50px) */
1993
+ threshold?: number;
1994
+ /** Current pagination state */
1995
+ pagination: IPagination;
1996
+ /** Total items available */
1997
+ total: number | undefined;
1998
+ /** Whether currently loading */
1999
+ isLoading: boolean;
2000
+ }
2001
+ /**
2002
+ * Check if scroll has reached near bottom and calculate next page if available.
2003
+ * Returns next pagination if should load more, null otherwise.
2004
+ *
2005
+ * @example
2006
+ * ```typescript
2007
+ * onScroll(event: Event): void {
2008
+ * const nextPagination = checkScrollPagination(event, {
2009
+ * pagination: this.pagination(),
2010
+ * total: this.total(),
2011
+ * isLoading: this.isLoading(),
2012
+ * });
2013
+ * if (nextPagination) {
2014
+ * this.onPagination.emit(nextPagination);
2015
+ * }
2016
+ * }
2017
+ * ```
2018
+ */
2019
+ declare function checkScrollPagination(event: Event, config: ScrollPaginationConfig): IPagination | null;
2020
+
2021
+ 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 };
2022
+ 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, UploadFileFn };