@flusys/ng-shared 1.1.0-beta → 1.1.0

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
 
@@ -1038,6 +949,9 @@ declare class PrimeModule {
1038
949
  static ɵinj: _angular_core.ɵɵInjectorDeclaration<PrimeModule>;
1039
950
  }
1040
951
 
952
+ /** Service names that can be used for feature-specific base URLs */
953
+ type ServiceName = 'auth' | 'administration' | 'iam' | 'storage' | 'formBuilder' | 'email';
954
+
1041
955
  /**
1042
956
  * Service interface for CRUD operations.
1043
957
  * Matches NestJS shared API controller endpoints:
@@ -1079,11 +993,20 @@ interface IApiService<DtoT, InterfaceT> {
1079
993
  *
1080
994
  * @example
1081
995
  * ```typescript
1082
- * // Define service
996
+ * // Define service with global apiBaseUrl
1083
997
  * @Injectable({ providedIn: 'root' })
1084
998
  * export class UserService extends ApiResourceService<UserDto, User> {
1085
- * constructor(http: HttpClient) {
1086
- * super('users', http);
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'
1087
1010
  * }
1088
1011
  * }
1089
1012
  *
@@ -1104,7 +1027,6 @@ interface IApiService<DtoT, InterfaceT> {
1104
1027
  */
1105
1028
  declare abstract class ApiResourceService<DtoT, InterfaceT> implements IApiService<DtoT, InterfaceT> {
1106
1029
  protected readonly baseUrl: string;
1107
- protected readonly loaderService: ApiLoaderService;
1108
1030
  protected readonly injector: Injector;
1109
1031
  protected readonly http: HttpClient;
1110
1032
  protected readonly moduleApiName: string;
@@ -1119,6 +1041,12 @@ declare abstract class ApiResourceService<DtoT, InterfaceT> implements IApiServi
1119
1041
  private _listResource;
1120
1042
  /** Whether the list resource has been initialized */
1121
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;
1122
1050
  /** Get or create the list resource (lazy initialization) */
1123
1051
  get listResource(): ResourceRef<IListResponse<InterfaceT> | undefined>;
1124
1052
  /**
@@ -1127,17 +1055,37 @@ declare abstract class ApiResourceService<DtoT, InterfaceT> implements IApiServi
1127
1055
  * Uses runInInjectionContext to support lazy initialization outside constructor.
1128
1056
  */
1129
1057
  initListResource(): void;
1130
- /** Whether data is currently loading */
1058
+ /**
1059
+ * Whether data is currently loading.
1060
+ * Tracks _resourceInitSignal to re-evaluate when resource is created.
1061
+ */
1131
1062
  readonly isLoading: _angular_core.Signal<boolean>;
1132
- /** List data array */
1063
+ /**
1064
+ * List data array.
1065
+ * Tracks _resourceInitSignal to re-evaluate when resource is created.
1066
+ */
1133
1067
  readonly data: _angular_core.Signal<InterfaceT[]>;
1134
- /** Total count of items */
1068
+ /**
1069
+ * Total count of items.
1070
+ * Tracks _resourceInitSignal to re-evaluate when resource is created.
1071
+ */
1135
1072
  readonly total: _angular_core.Signal<number>;
1136
- /** Pagination metadata */
1073
+ /**
1074
+ * Pagination metadata.
1075
+ * Tracks _resourceInitSignal to re-evaluate when resource is created.
1076
+ */
1137
1077
  readonly pageInfo: _angular_core.Signal<_flusys_ng_shared.IPaginationMeta | undefined>;
1138
- /** Whether there are more pages */
1078
+ /**
1079
+ * Whether there are more pages.
1080
+ * Tracks _resourceInitSignal to re-evaluate when resource is created.
1081
+ */
1139
1082
  readonly hasMore: _angular_core.Signal<boolean>;
1140
- constructor(moduleApiName: string, http: HttpClient);
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);
1141
1089
  protected getHttpOptions(endpoint: string, params?: HttpParams): {
1142
1090
  params?: HttpParams | undefined;
1143
1091
  headers: HttpHeaders;
@@ -1228,14 +1176,6 @@ declare abstract class ApiResourceService<DtoT, InterfaceT> implements IApiServi
1228
1176
  deleteAsync(deleteDto: IDeleteData): Promise<IMessageResponse>;
1229
1177
  }
1230
1178
 
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
1179
  /**
1240
1180
  * Base class for form controls that support ALL Angular form patterns:
1241
1181
  *
@@ -1308,6 +1248,31 @@ declare abstract class BaseFormControl<T> implements ControlValueAccessor, FormV
1308
1248
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseFormControl<any>, never>;
1309
1249
  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
1250
  }
1251
+ /**
1252
+ * Factory function to provide NG_VALUE_ACCESSOR for a component.
1253
+ * Use in component providers array.
1254
+ *
1255
+ * @example
1256
+ * ```typescript
1257
+ * @Component({
1258
+ * providers: [provideValueAccessor(LazySelectComponent)]
1259
+ * })
1260
+ * export class LazySelectComponent extends BaseFormControl<string | null> {}
1261
+ * ```
1262
+ */
1263
+ declare function provideValueAccessor<T extends new (...args: unknown[]) => ControlValueAccessor>(component: T): {
1264
+ provide: _angular_core.InjectionToken<readonly ControlValueAccessor[]>;
1265
+ useExisting: _angular_core.Type<any>;
1266
+ multi: boolean;
1267
+ };
1268
+
1269
+ declare class IconComponent {
1270
+ icon: _angular_core.InputSignal<string>;
1271
+ iconType: _angular_core.InputSignal<IconTypeEnum | undefined>;
1272
+ protected readonly IconTypeEnum: typeof IconTypeEnum;
1273
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<IconComponent, never>;
1274
+ 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
+ }
1311
1276
 
1312
1277
  /**
1313
1278
  * Lazy-loading multi-select component with search, pagination, and select-all.
@@ -1318,31 +1283,28 @@ declare abstract class BaseFormControl<T> implements ControlValueAccessor, FormV
1318
1283
  * - Signal forms: `[formField]="formTree.field"`
1319
1284
  */
1320
1285
  declare class LazyMultiSelectComponent extends BaseFormControl<string[] | null> {
1286
+ private readonly destroyRef;
1287
+ private readonly onDocumentClickBound;
1288
+ readonly pSelectRef: _angular_core.Signal<ElementRef<HTMLDivElement>>;
1321
1289
  readonly placeHolder: _angular_core.InputSignal<string>;
1322
1290
  readonly isEditMode: _angular_core.InputSignal<boolean>;
1323
1291
  readonly isLoading: _angular_core.InputSignal<boolean>;
1324
1292
  readonly total: _angular_core.InputSignal<number | undefined>;
1325
1293
  readonly pagination: _angular_core.InputSignal<IPagination>;
1326
1294
  readonly selectDataList: _angular_core.InputSignal<IDropDown[]>;
1327
- /** Two-way bound value using model() for signal forms compatibility */
1328
1295
  readonly value: _angular_core.ModelSignal<string[] | null>;
1329
1296
  readonly onSearch: _angular_core.OutputEmitterRef<string>;
1330
1297
  readonly onPagination: _angular_core.OutputEmitterRef<IPagination>;
1331
1298
  readonly searchTerm: _angular_core.WritableSignal<string>;
1332
- /** Computed: Display text for selected values (replaces getSelectedValue method) */
1299
+ readonly openOptions: _angular_core.WritableSignal<boolean>;
1333
1300
  readonly selectedValueDisplay: _angular_core.Signal<string>;
1334
- /** Computed: Whether all items are selected (replaces isSelectAll signal) */
1335
1301
  readonly isSelectAll: _angular_core.Signal<boolean>;
1336
1302
  constructor();
1337
- private readonly onScrollBound;
1338
- readonly multiScrollContainer: _angular_core.Signal<ElementRef<HTMLDivElement>>;
1339
1303
  onScroll(event: Event): void;
1340
- readonly pSelectRef: _angular_core.Signal<ElementRef<HTMLDivElement>>;
1341
- openOptions: _angular_core.WritableSignal<boolean>;
1342
1304
  onSelectClick(event: Event): void;
1343
1305
  onOverlayClick(event: Event): void;
1344
- handleDocumentClick(event: MouseEvent): void;
1345
- isSelected(data: IDropDown): boolean | undefined;
1306
+ private handleDocumentClick;
1307
+ isSelected(data: IDropDown): boolean;
1346
1308
  key(option: IDropDown): string;
1347
1309
  selectValue(event: CheckboxChangeEvent, option: IDropDown): void;
1348
1310
  changeSelectAll(event: CheckboxChangeEvent): void;
@@ -1360,6 +1322,10 @@ declare class LazyMultiSelectComponent extends BaseFormControl<string[] | null>
1360
1322
  * - Signal forms: `[formField]="formTree.field"`
1361
1323
  */
1362
1324
  declare class LazySelectComponent extends BaseFormControl<string | null> {
1325
+ private readonly destroyRef;
1326
+ private readonly onScrollBound;
1327
+ private scrollTargetEl;
1328
+ readonly scrollContainer: _angular_core.Signal<ElementRef<HTMLDivElement>>;
1363
1329
  readonly placeHolder: _angular_core.InputSignal<string>;
1364
1330
  readonly optionLabel: _angular_core.InputSignal<string>;
1365
1331
  readonly optionValue: _angular_core.InputSignal<string>;
@@ -1368,16 +1334,12 @@ declare class LazySelectComponent extends BaseFormControl<string | null> {
1368
1334
  readonly total: _angular_core.InputSignal<number | undefined>;
1369
1335
  readonly pagination: _angular_core.InputSignal<IPagination>;
1370
1336
  readonly selectDataList: _angular_core.InputSignal<IDropDown[]>;
1371
- /** Two-way bound value using model() for signal forms compatibility */
1372
1337
  readonly value: _angular_core.ModelSignal<string | null>;
1373
1338
  readonly onSearch: _angular_core.OutputEmitterRef<string>;
1374
1339
  readonly onPagination: _angular_core.OutputEmitterRef<IPagination>;
1375
1340
  readonly searchTerm: _angular_core.WritableSignal<string>;
1341
+ readonly isPanelShow: _angular_core.WritableSignal<boolean>;
1376
1342
  constructor();
1377
- isPanelShow: _angular_core.WritableSignal<boolean>;
1378
- scrollTargetEl: HTMLElement | null;
1379
- private readonly onScrollBound;
1380
- readonly scrollContainer: _angular_core.Signal<ElementRef<HTMLDivElement>>;
1381
1343
  onScroll(event: Event): void;
1382
1344
  showPanel(): void;
1383
1345
  onBlur(): void;
@@ -1385,6 +1347,45 @@ declare class LazySelectComponent extends BaseFormControl<string | null> {
1385
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>;
1386
1348
  }
1387
1349
 
1350
+ /**
1351
+ * Base class for user selection components.
1352
+ * Provides shared user loading, pagination, and search functionality.
1353
+ *
1354
+ * Subclasses must implement:
1355
+ * - `setupValueEffect()` to track value changes and emit selection events
1356
+ */
1357
+ declare abstract class BaseUserSelectComponent {
1358
+ protected readonly destroyRef: DestroyRef;
1359
+ protected readonly injector: Injector;
1360
+ protected readonly userProvider: IUserProvider;
1361
+ protected abortController: AbortController | null;
1362
+ readonly loadUsers: _angular_core.InputSignal<LoadUsersFn | undefined>;
1363
+ readonly placeHolder: _angular_core.InputSignal<string>;
1364
+ readonly isEditMode: _angular_core.InputSignal<boolean>;
1365
+ readonly filterActive: _angular_core.InputSignal<boolean>;
1366
+ readonly additionalFilters: _angular_core.InputSignal<Record<string, unknown>>;
1367
+ readonly pageSize: _angular_core.InputSignal<number>;
1368
+ readonly onError: _angular_core.OutputEmitterRef<Error>;
1369
+ readonly isLoading: _angular_core.WritableSignal<boolean>;
1370
+ readonly users: _angular_core.WritableSignal<IUserBasicInfo[]>;
1371
+ readonly total: _angular_core.WritableSignal<number | undefined>;
1372
+ readonly pagination: _angular_core.WritableSignal<IPagination>;
1373
+ readonly searchTerm: _angular_core.WritableSignal<string>;
1374
+ readonly dropdownUsers: _angular_core.Signal<IDropDown[]>;
1375
+ constructor();
1376
+ /** Setup effect to track value changes and emit selection events */
1377
+ protected abstract setupValueEffect(): void;
1378
+ handleSearch(search: string): void;
1379
+ handlePagination(pagination: IPagination): void;
1380
+ /** Reload users (useful when filters change externally) */
1381
+ reload(): void;
1382
+ protected fetchUsers(append?: boolean): Promise<void>;
1383
+ /** Load users from USER_PROVIDER with active filter */
1384
+ private loadUsersFromProvider;
1385
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseUserSelectComponent, never>;
1386
+ 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
+ }
1388
+
1388
1389
  /**
1389
1390
  * User Select Component - Single user selection with lazy loading.
1390
1391
  *
@@ -1412,35 +1413,12 @@ declare class LazySelectComponent extends BaseFormControl<string | null> {
1412
1413
  * />
1413
1414
  * ```
1414
1415
  */
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>;
1416
+ declare class UserSelectComponent extends BaseUserSelectComponent {
1425
1417
  readonly value: _angular_core.ModelSignal<string | null>;
1426
1418
  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;
1419
+ protected setupValueEffect(): void;
1442
1420
  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>;
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>;
1444
1422
  }
1445
1423
 
1446
1424
  /**
@@ -1471,76 +1449,18 @@ declare class UserSelectComponent {
1471
1449
  * />
1472
1450
  * ```
1473
1451
  */
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>;
1452
+ declare class UserMultiSelectComponent extends BaseUserSelectComponent {
1484
1453
  readonly value: _angular_core.ModelSignal<string[] | null>;
1485
1454
  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;
1455
+ protected setupValueEffect(): void;
1501
1456
  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>;
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>;
1503
1458
  }
1504
1459
 
1505
1460
  /**
1506
1461
  * File Uploader Component - Drag & drop file upload with type filtering.
1507
1462
  *
1508
1463
  * 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
1464
  */
1545
1465
  declare class FileUploaderComponent {
1546
1466
  private readonly messageService;
@@ -1739,63 +1659,340 @@ declare const PROFILE_UPLOAD_PROVIDER: InjectionToken<IProfileUploadProvider>;
1739
1659
  declare const USER_LIST_PROVIDER: InjectionToken<IUserListProvider<IUserListItem>>;
1740
1660
 
1741
1661
  /**
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
1662
+ * Permission Guard - Single permission or ILogicNode check.
1752
1663
  *
1753
1664
  * @example
1754
1665
  * ```typescript
1755
- * // Simple permission check
1756
1666
  * { 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')] }
1667
+ * { path: 'admin', canActivate: [permissionGuard(logicNode, '/access-denied')] }
1771
1668
  * ```
1772
1669
  */
1773
1670
  declare function permissionGuard(permission: string | ILogicNode, redirectTo?: string): CanActivateFn;
1774
1671
  /**
1775
- * Any Permission Guard (OR logic)
1776
- *
1777
- * Allows access if user has ANY of the specified permissions.
1672
+ * Any Permission Guard (OR logic) - Access if user has ANY permission.
1778
1673
  *
1779
1674
  * @example
1780
1675
  * ```typescript
1781
- * // Allow if user has view OR create permission
1782
1676
  * { path: 'users', canActivate: [anyPermissionGuard(['user.view', 'user.create'])] }
1783
1677
  * ```
1784
1678
  */
1785
1679
  declare function anyPermissionGuard(permissions: string[], redirectTo?: string): CanActivateFn;
1786
1680
  /**
1787
- * All Permissions Guard (AND logic)
1788
- *
1789
- * Allows access only if user has ALL of the specified permissions.
1681
+ * All Permissions Guard (AND logic) - Access only if user has ALL permissions.
1790
1682
  *
1791
1683
  * @example
1792
1684
  * ```typescript
1793
- * // Allow only if user has BOTH view AND create permissions
1794
1685
  * { path: 'admin', canActivate: [allPermissionsGuard(['admin.view', 'admin.manage'])] }
1795
1686
  * ```
1796
1687
  */
1797
1688
  declare function allPermissionsGuard(permissions: string[], redirectTo?: string): CanActivateFn;
1798
1689
 
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
+ }
1987
+
1988
+ /**
1989
+ * Check if user has a specific permission using wildcard matching.
1990
+ * Supports:
1991
+ * - Exact match: 'user.create' matches 'user.create'
1992
+ * - Full wildcard: '*' matches everything
1993
+ * - Module wildcard: 'user.*' matches 'user.create', 'user.read', etc.
1994
+ */
1995
+ declare function hasPermission(requiredPermission: string, userPermissions: string[]): boolean;
1799
1996
  /** Evaluate permission logic (string or ILogicNode) against user permissions */
1800
1997
  declare function evaluatePermission(logic: string | ILogicNode | null | undefined, permissions: string[]): boolean;
1801
1998
  /** Recursively evaluate an ILogicNode tree */
@@ -1805,5 +2002,38 @@ declare function hasAnyPermission(permissionCodes: string[], permissions: string
1805
2002
  /** Check if user has ALL of the specified permissions (AND logic) */
1806
2003
  declare function hasAllPermissions(permissionCodes: string[], permissions: string[]): boolean;
1807
2004
 
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 };
2005
+ /**
2006
+ * Configuration for scroll pagination behavior
2007
+ */
2008
+ interface ScrollPaginationConfig {
2009
+ /** Distance from bottom to trigger pagination (default: 50px) */
2010
+ threshold?: number;
2011
+ /** Current pagination state */
2012
+ pagination: IPagination;
2013
+ /** Total items available */
2014
+ total: number | undefined;
2015
+ /** Whether currently loading */
2016
+ isLoading: boolean;
2017
+ }
2018
+ /**
2019
+ * Check if scroll has reached near bottom and calculate next page if available.
2020
+ * Returns next pagination if should load more, null otherwise.
2021
+ *
2022
+ * @example
2023
+ * ```typescript
2024
+ * onScroll(event: Event): void {
2025
+ * const nextPagination = checkScrollPagination(event, {
2026
+ * pagination: this.pagination(),
2027
+ * total: this.total(),
2028
+ * isLoading: this.isLoading(),
2029
+ * });
2030
+ * if (nextPagination) {
2031
+ * this.onPagination.emit(nextPagination);
2032
+ * }
2033
+ * }
2034
+ * ```
2035
+ */
2036
+ declare function checkScrollPagination(event: Event, config: ScrollPaginationConfig): IPagination | null;
2037
+
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 };