@flusys/ng-shared 1.1.1-beta → 1.2.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,90 +1,263 @@
1
- import * as _angular_core from '@angular/core';
2
- import { Signal, Injector, ResourceRef, model, ElementRef, InjectionToken } from '@angular/core';
1
+ import * as rxjs from 'rxjs';
3
2
  import { Observable } from 'rxjs';
3
+ import * as _angular_core from '@angular/core';
4
+ import { Signal, PipeTransform, ResourceRef, ResourceStatus, Injector, model, TemplateRef, OnDestroy, ElementRef, DestroyRef, InjectionToken } from '@angular/core';
5
+ import { HttpContextToken, HttpRequest, HttpHandlerFn, HttpEvent, HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
6
+ import * as i3 from '@angular/router';
7
+ import { ResolveFn, CanActivateFn } from '@angular/router';
4
8
  import * as i1 from '@angular/common';
5
9
  import * as i2 from '@angular/forms';
6
10
  import { ControlValueAccessor } from '@angular/forms';
7
- import * as i3 from '@angular/router';
8
- import { CanActivateFn } from '@angular/router';
9
- import * as i1$1 from 'primeng/autocomplete';
10
- import * as i2$1 from 'primeng/avatar';
11
- import * as i3$1 from 'primeng/button';
12
- import * as i4 from 'primeng/card';
13
- import * as i5 from 'primeng/checkbox';
14
- import { CheckboxChangeEvent } from 'primeng/checkbox';
15
- import * as i6 from 'primeng/confirmdialog';
16
- import * as i7 from 'primeng/datepicker';
17
- import * as i8 from 'primeng/dialog';
18
- import * as i9 from 'primeng/divider';
19
- import * as i10 from 'primeng/fileupload';
20
- import * as i11 from 'primeng/iconfield';
21
- import * as i12 from 'primeng/image';
22
- import * as i13 from 'primeng/inputicon';
23
- import * as i14 from 'primeng/inputnumber';
24
- import * as i15 from 'primeng/inputtext';
25
- import * as i16 from 'primeng/listbox';
26
- import * as i17 from 'primeng/multiselect';
27
- import * as i18 from 'primeng/paginator';
28
- import * as i19 from 'primeng/panel';
29
- import * as i20 from 'primeng/password';
30
- import * as i21 from 'primeng/popover';
31
- import * as i22 from 'primeng/progressbar';
32
- import * as i23 from 'primeng/radiobutton';
33
- import * as i24 from 'primeng/ripple';
34
- import * as i25 from 'primeng/selectbutton';
35
- import * as i26 from 'primeng/select';
36
- import * as i27 from 'primeng/skeleton';
37
- import * as i28 from 'primeng/splitbutton';
38
- import * as i29 from 'primeng/steps';
39
- import * as i30 from 'primeng/table';
40
- import * as i31 from 'primeng/tabs';
41
- import * as i32 from 'primeng/tag';
42
- import * as i33 from 'primeng/textarea';
43
- import * as i34 from 'primeng/toast';
44
- import * as i35 from 'primeng/toggleswitch';
45
- import * as i36 from 'primeng/tooltip';
46
- import * as i37 from 'primeng/treetable';
47
11
  import * as _flusys_ng_shared from '@flusys/ng-shared';
48
- import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
49
- import { ApiLoaderService } from '@flusys/ng-core';
12
+ import { ServiceName } from '@flusys/ng-core';
50
13
  import { FormValueControl } from '@angular/forms/signals';
14
+ import * as _angular_platform_browser from '@angular/platform-browser';
15
+ import { CheckboxChangeEvent } from '@flusys/ng-ui';
51
16
 
52
- /**
53
- * Auth State Provider Interface
54
- *
55
- * Abstracts auth state access for feature packages (form-builder, etc.)
56
- * that need to check authentication status without depending on ng-auth directly.
57
- *
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
- * }
76
- */
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
- }
17
+ declare const SHARED_MESSAGES: Record<string, string>;
18
+
19
+ declare const USER_PERMISSIONS: {
20
+ readonly CREATE: "user.create";
21
+ readonly READ: "user.read";
22
+ readonly UPDATE: "user.update";
23
+ readonly DELETE: "user.delete";
24
+ };
25
+ declare const COMPANY_PERMISSIONS: {
26
+ readonly CREATE: "company.create";
27
+ readonly READ: "company.read";
28
+ readonly UPDATE: "company.update";
29
+ readonly DELETE: "company.delete";
30
+ };
31
+ declare const BRANCH_PERMISSIONS: {
32
+ readonly CREATE: "branch.create";
33
+ readonly READ: "branch.read";
34
+ readonly UPDATE: "branch.update";
35
+ readonly DELETE: "branch.delete";
36
+ };
37
+ declare const ACTION_PERMISSIONS: {
38
+ readonly CREATE: "action.create";
39
+ readonly READ: "action.read";
40
+ readonly UPDATE: "action.update";
41
+ readonly DELETE: "action.delete";
42
+ };
43
+ declare const ROLE_PERMISSIONS: {
44
+ readonly CREATE: "role.create";
45
+ readonly READ: "role.read";
46
+ readonly UPDATE: "role.update";
47
+ readonly DELETE: "role.delete";
48
+ };
49
+ declare const ROLE_ACTION_PERMISSIONS: {
50
+ readonly READ: "role-action.read";
51
+ readonly ASSIGN: "role-action.assign";
52
+ };
53
+ declare const USER_ROLE_PERMISSIONS: {
54
+ readonly READ: "user-role.read";
55
+ readonly ASSIGN: "user-role.assign";
56
+ };
57
+ declare const USER_ACTION_PERMISSIONS: {
58
+ readonly READ: "user-action.read";
59
+ readonly ASSIGN: "user-action.assign";
60
+ };
61
+ declare const COMPANY_ACTION_PERMISSIONS: {
62
+ readonly READ: "company-action.read";
63
+ readonly ASSIGN: "company-action.assign";
64
+ };
65
+ declare const FILE_PERMISSIONS: {
66
+ readonly CREATE: "file.create";
67
+ readonly READ: "file.read";
68
+ readonly UPDATE: "file.update";
69
+ readonly DELETE: "file.delete";
70
+ };
71
+ declare const FOLDER_PERMISSIONS: {
72
+ readonly CREATE: "folder.create";
73
+ readonly READ: "folder.read";
74
+ readonly UPDATE: "folder.update";
75
+ readonly DELETE: "folder.delete";
76
+ };
77
+ declare const STORAGE_CONFIG_PERMISSIONS: {
78
+ readonly CREATE: "storage-config.create";
79
+ readonly READ: "storage-config.read";
80
+ readonly UPDATE: "storage-config.update";
81
+ readonly DELETE: "storage-config.delete";
82
+ };
83
+ declare const UPLOAD_CONFIG_PERMISSIONS: {
84
+ readonly DELETE: "upload-config.delete";
85
+ };
86
+ declare const EMAIL_CONFIG_PERMISSIONS: {
87
+ readonly CREATE: "email-config.create";
88
+ readonly READ: "email-config.read";
89
+ readonly UPDATE: "email-config.update";
90
+ readonly DELETE: "email-config.delete";
91
+ };
92
+ declare const EMAIL_TEMPLATE_PERMISSIONS: {
93
+ readonly CREATE: "email-template.create";
94
+ readonly READ: "email-template.read";
95
+ readonly UPDATE: "email-template.update";
96
+ readonly DELETE: "email-template.delete";
97
+ };
98
+ declare const FORM_PERMISSIONS: {
99
+ readonly CREATE: "form.create";
100
+ readonly READ: "form.read";
101
+ readonly UPDATE: "form.update";
102
+ readonly DELETE: "form.delete";
103
+ };
104
+ declare const FORM_RESULT_PERMISSIONS: {
105
+ readonly CREATE: "form-result.create";
106
+ readonly READ: "form-result.read";
107
+ readonly UPDATE: "form-result.update";
108
+ readonly DELETE: "form-result.delete";
109
+ };
110
+ declare const EVENT_PERMISSIONS: {
111
+ readonly CREATE: "event.create";
112
+ readonly READ: "event.read";
113
+ readonly UPDATE: "event.update";
114
+ readonly DELETE: "event.delete";
115
+ };
116
+ declare const NOTIFICATION_PERMISSIONS: {
117
+ readonly CREATE: "notification.create";
118
+ readonly READ: "notification.read";
119
+ readonly UPDATE: "notification.update";
120
+ readonly DELETE: "notification.delete";
121
+ };
122
+ declare const LANGUAGE_PERMISSIONS: {
123
+ readonly CREATE: "language.create";
124
+ readonly READ: "language.read";
125
+ readonly UPDATE: "language.update";
126
+ readonly DELETE: "language.delete";
127
+ };
128
+ declare const TRANSLATION_KEY_PERMISSIONS: {
129
+ readonly CREATE: "translation-key.create";
130
+ readonly READ: "translation-key.read";
131
+ readonly UPDATE: "translation-key.update";
132
+ readonly DELETE: "translation-key.delete";
133
+ };
134
+ declare const TRANSLATION_PERMISSIONS: {
135
+ readonly CREATE: "translation.create";
136
+ readonly READ: "translation.read";
137
+ readonly UPDATE: "translation.update";
138
+ readonly DELETE: "translation.delete";
139
+ };
140
+ declare const PERMISSIONS: {
141
+ readonly USER: {
142
+ readonly CREATE: "user.create";
143
+ readonly READ: "user.read";
144
+ readonly UPDATE: "user.update";
145
+ readonly DELETE: "user.delete";
146
+ };
147
+ readonly COMPANY: {
148
+ readonly CREATE: "company.create";
149
+ readonly READ: "company.read";
150
+ readonly UPDATE: "company.update";
151
+ readonly DELETE: "company.delete";
152
+ };
153
+ readonly BRANCH: {
154
+ readonly CREATE: "branch.create";
155
+ readonly READ: "branch.read";
156
+ readonly UPDATE: "branch.update";
157
+ readonly DELETE: "branch.delete";
158
+ };
159
+ readonly ACTION: {
160
+ readonly CREATE: "action.create";
161
+ readonly READ: "action.read";
162
+ readonly UPDATE: "action.update";
163
+ readonly DELETE: "action.delete";
164
+ };
165
+ readonly ROLE: {
166
+ readonly CREATE: "role.create";
167
+ readonly READ: "role.read";
168
+ readonly UPDATE: "role.update";
169
+ readonly DELETE: "role.delete";
170
+ };
171
+ readonly ROLE_ACTION: {
172
+ readonly READ: "role-action.read";
173
+ readonly ASSIGN: "role-action.assign";
174
+ };
175
+ readonly USER_ROLE: {
176
+ readonly READ: "user-role.read";
177
+ readonly ASSIGN: "user-role.assign";
178
+ };
179
+ readonly USER_ACTION: {
180
+ readonly READ: "user-action.read";
181
+ readonly ASSIGN: "user-action.assign";
182
+ };
183
+ readonly COMPANY_ACTION: {
184
+ readonly READ: "company-action.read";
185
+ readonly ASSIGN: "company-action.assign";
186
+ };
187
+ readonly FILE: {
188
+ readonly CREATE: "file.create";
189
+ readonly READ: "file.read";
190
+ readonly UPDATE: "file.update";
191
+ readonly DELETE: "file.delete";
192
+ };
193
+ readonly FOLDER: {
194
+ readonly CREATE: "folder.create";
195
+ readonly READ: "folder.read";
196
+ readonly UPDATE: "folder.update";
197
+ readonly DELETE: "folder.delete";
198
+ };
199
+ readonly STORAGE_CONFIG: {
200
+ readonly CREATE: "storage-config.create";
201
+ readonly READ: "storage-config.read";
202
+ readonly UPDATE: "storage-config.update";
203
+ readonly DELETE: "storage-config.delete";
204
+ };
205
+ readonly EMAIL_CONFIG: {
206
+ readonly CREATE: "email-config.create";
207
+ readonly READ: "email-config.read";
208
+ readonly UPDATE: "email-config.update";
209
+ readonly DELETE: "email-config.delete";
210
+ };
211
+ readonly EMAIL_TEMPLATE: {
212
+ readonly CREATE: "email-template.create";
213
+ readonly READ: "email-template.read";
214
+ readonly UPDATE: "email-template.update";
215
+ readonly DELETE: "email-template.delete";
216
+ };
217
+ readonly FORM: {
218
+ readonly CREATE: "form.create";
219
+ readonly READ: "form.read";
220
+ readonly UPDATE: "form.update";
221
+ readonly DELETE: "form.delete";
222
+ };
223
+ readonly FORM_RESULT: {
224
+ readonly CREATE: "form-result.create";
225
+ readonly READ: "form-result.read";
226
+ readonly UPDATE: "form-result.update";
227
+ readonly DELETE: "form-result.delete";
228
+ };
229
+ readonly EVENT: {
230
+ readonly CREATE: "event.create";
231
+ readonly READ: "event.read";
232
+ readonly UPDATE: "event.update";
233
+ readonly DELETE: "event.delete";
234
+ };
235
+ readonly NOTIFICATION: {
236
+ readonly CREATE: "notification.create";
237
+ readonly READ: "notification.read";
238
+ readonly UPDATE: "notification.update";
239
+ readonly DELETE: "notification.delete";
240
+ };
241
+ readonly LANGUAGE: {
242
+ readonly CREATE: "language.create";
243
+ readonly READ: "language.read";
244
+ readonly UPDATE: "language.update";
245
+ readonly DELETE: "language.delete";
246
+ };
247
+ readonly TRANSLATION_KEY: {
248
+ readonly CREATE: "translation-key.create";
249
+ readonly READ: "translation-key.read";
250
+ readonly UPDATE: "translation-key.update";
251
+ readonly DELETE: "translation-key.delete";
252
+ };
253
+ readonly TRANSLATION: {
254
+ readonly CREATE: "translation.create";
255
+ readonly READ: "translation.read";
256
+ readonly UPDATE: "translation.update";
257
+ readonly DELETE: "translation.delete";
258
+ };
259
+ };
260
+ type PermissionCode = (typeof PERMISSIONS)[keyof typeof PERMISSIONS][keyof (typeof PERMISSIONS)[keyof typeof PERMISSIONS]];
88
261
 
89
262
  /**
90
263
  * Base entity interface - matches backend Identity entity
@@ -123,12 +296,6 @@ interface IActivatable {
123
296
  interface IOrderable {
124
297
  serial?: number | null;
125
298
  }
126
- /**
127
- * Entity with metadata JSON field
128
- */
129
- interface IMetadata {
130
- metadata?: Record<string, unknown> | null;
131
- }
132
299
  /**
133
300
  * Logged-in user info - matches backend ILoggedUserInfo
134
301
  */
@@ -143,6 +310,42 @@ interface ILoggedUserInfo {
143
310
  companyLogoId?: string;
144
311
  branchLogoId?: string;
145
312
  }
313
+ /**
314
+ * Simple dropdown item for select components
315
+ */
316
+ interface IDropDown {
317
+ label: string;
318
+ value: string;
319
+ }
320
+ /**
321
+ * Delete operation types
322
+ * - 'delete': Soft delete (sets deletedAt timestamp)
323
+ * - 'restore': Restore soft-deleted item (clears deletedAt)
324
+ * - 'permanent': Permanently delete from database
325
+ */
326
+ type DeleteType = 'delete' | 'restore' | 'permanent';
327
+ /**
328
+ * Delete request payload - matches backend DeleteDto
329
+ */
330
+ interface IDeleteData {
331
+ /** Single ID or array of IDs to delete */
332
+ id: string | string[];
333
+ /** Type of delete operation */
334
+ type: DeleteType;
335
+ }
336
+ /** Action node - checks a single permission */
337
+ interface IActionNode {
338
+ type: 'action';
339
+ actionId: string;
340
+ }
341
+ /** Group node - combines children with AND/OR logic */
342
+ interface IGroupNode {
343
+ type: 'group';
344
+ operator: 'AND' | 'OR';
345
+ children: ILogicNode[];
346
+ }
347
+ /** Permission logic tree (discriminated union of action/group) */
348
+ type ILogicNode = IActionNode | IGroupNode;
146
349
 
147
350
  /**
148
351
  * Request metadata added by backend ResponseMetaInterceptor
@@ -171,20 +374,14 @@ interface IBulkMeta {
171
374
  failed?: number;
172
375
  total?: number;
173
376
  }
174
- /**
175
- * Validation error detail
176
- */
177
- interface IValidationError {
178
- field: string;
179
- message: string;
180
- constraint?: string;
181
- }
182
377
  /**
183
378
  * Single item response (insert, update, get-by-id)
184
379
  */
185
380
  interface ISingleResponse<T> {
186
381
  success: boolean;
187
382
  message: string;
383
+ messageKey?: string;
384
+ messageVariables?: Record<string, unknown>;
188
385
  data?: T;
189
386
  _meta?: IRequestMeta;
190
387
  }
@@ -194,6 +391,8 @@ interface ISingleResponse<T> {
194
391
  interface IListResponse<T> {
195
392
  success: boolean;
196
393
  message: string;
394
+ messageKey?: string;
395
+ messageVariables?: Record<string, unknown>;
197
396
  data?: T[];
198
397
  meta: IPaginationMeta;
199
398
  _meta?: IRequestMeta;
@@ -204,6 +403,8 @@ interface IListResponse<T> {
204
403
  interface IBulkResponse<T> {
205
404
  success: boolean;
206
405
  message: string;
406
+ messageKey?: string;
407
+ messageVariables?: Record<string, unknown>;
207
408
  data?: T[];
208
409
  meta: IBulkMeta;
209
410
  _meta?: IRequestMeta;
@@ -214,128 +415,74 @@ interface IBulkResponse<T> {
214
415
  interface IMessageResponse {
215
416
  success: boolean;
216
417
  message: string;
418
+ messageKey?: string;
419
+ messageVariables?: Record<string, unknown>;
217
420
  _meta?: IRequestMeta;
218
421
  }
219
- /**
220
- * Error response
221
- */
222
- interface IErrorResponse {
223
- success: false;
224
- message: string;
225
- code?: string;
226
- errors?: IValidationError[];
227
- _meta?: IRequestMeta;
228
- }
229
- /**
230
- * Union type for all API responses
231
- */
232
- type ApiResponse<T> = ISingleResponse<T> | IListResponse<T> | IBulkResponse<T> | IMessageResponse | IErrorResponse;
233
- interface IUserCompanyPayload {
422
+
423
+ interface IFileBasicInfo {
234
424
  id: string;
235
425
  name: string;
236
- slug: string;
237
- logoId?: string;
426
+ contentType: string;
427
+ size: string;
428
+ url: string | null;
238
429
  }
239
- interface IUserBranchPayload {
240
- id: string;
430
+ interface IUploadedFile {
431
+ id?: string;
241
432
  name: string;
242
- slug: string;
243
- logoId?: string;
433
+ key: string;
434
+ size: number;
435
+ contentType: string;
244
436
  }
245
- interface ILoginUserData {
437
+ interface IFolderBasicInfo {
246
438
  id: string;
247
439
  name: string;
248
- email: string;
249
- phone?: string;
250
- profilePictureId?: string | null;
251
- companyId?: string;
252
- branchId?: string;
253
- company?: IUserCompanyPayload;
254
- branch?: IUserBranchPayload;
255
- }
256
- interface ILoginResponse {
257
- success: boolean;
258
- message: string;
259
- data: {
260
- accessToken: string;
261
- refreshToken: string;
262
- user: ILoginUserData;
263
- };
264
- _meta?: IRequestMeta;
265
- }
266
- interface IRefreshTokenResponse {
267
- success: boolean;
268
- message: string;
269
- data: {
270
- accessToken: string;
271
- refreshToken?: string;
272
- };
273
- _meta?: IRequestMeta;
440
+ slug: string;
274
441
  }
275
- interface IFileData {
442
+ interface IStorageConfigBasicInfo {
276
443
  id: string;
277
444
  name: string;
278
- originalName: string;
279
- contentType: string;
280
- size: number;
281
- key: string;
282
- url?: string;
283
- thumbnailUrl?: string;
284
- createdAt: Date;
445
+ isDefault: boolean;
285
446
  }
286
-
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>>;
447
+ interface IFileUploadOptions {
448
+ storageConfigId?: string;
449
+ folderPath?: string;
450
+ maxWidth?: number;
451
+ maxHeight?: number;
452
+ quality?: number;
453
+ compress?: boolean;
454
+ isPrivate?: boolean;
305
455
  }
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;
456
+ interface ISelectFilter {
457
+ page: number;
458
+ pageSize: number;
459
+ search: string;
322
460
  }
323
-
324
- interface IDropDown {
325
- label: string;
326
- value: string;
461
+ interface IFileSelectFilter extends ISelectFilter {
462
+ contentTypes?: string[];
463
+ folderId?: string;
464
+ storageConfigId?: string;
327
465
  }
466
+ type UploadFileFn = (file: File, options?: IFileUploadOptions) => Observable<ISingleResponse<IUploadedFile>>;
467
+ type UploadMultipleFilesFn = (files: File[], options?: IFileUploadOptions) => Observable<ISingleResponse<IUploadedFile[]>>;
468
+ declare const FILE_TYPE_FILTERS: {
469
+ readonly IMAGES: readonly ["image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml"];
470
+ readonly DOCUMENTS: readonly ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"];
471
+ readonly VIDEOS: readonly ["video/mp4", "video/webm", "video/ogg", "video/quicktime"];
472
+ readonly AUDIO: readonly ["audio/mpeg", "audio/wav", "audio/ogg", "audio/webm"];
473
+ readonly ALL: string[];
474
+ };
475
+ declare function getAcceptString(contentTypes: string[]): string;
476
+ declare function isFileTypeAllowed(file: File, allowedTypes: string[]): boolean;
477
+ declare function getFileIconClass(contentType: string): string;
478
+ declare function formatFileSize(sizeInKb: string | number): string;
328
479
 
329
480
  interface IPagination {
330
481
  pageSize: number;
331
482
  currentPage: number;
332
483
  }
333
- interface ISort {
334
- [key: string]: 'ASC' | 'DESC';
335
- }
336
- interface IFilter {
337
- [key: string]: any;
338
- }
484
+ type ISort = Record<string, 'ASC' | 'DESC'>;
485
+ type IFilter = Record<string, string | number | boolean | null | undefined | string[] | number[]>;
339
486
  interface IFilterData {
340
487
  filter?: IFilter;
341
488
  pagination?: IPagination;
@@ -345,46 +492,18 @@ interface IFilterData {
345
492
  extraKey?: string[];
346
493
  }
347
494
 
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
495
  /**
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);
496
+ * Auth State Provider Interface
372
497
  *
373
- * async loadUserBranches(userId: string) {
374
- * const response = await this.userPermissionProvider
375
- * .getUserBranchPermissions(userId, '')
376
- * .toPromise();
377
- * this.branches.set(response?.data ?? []);
378
- * }
379
- * }
498
+ * Abstracts auth state access for feature packages (form-builder, etc.)
499
+ * that need to check authentication status without depending on ng-auth directly.
380
500
  */
381
- interface IUserPermissionProvider {
382
- /**
383
- * Get user's branch permissions
384
- */
385
- getUserBranchPermissions(userId: string): Observable<ISingleResponse<any>>;
501
+ interface IAuthStateProvider {
502
+ /** Signal indicating if user is currently authenticated */
503
+ isAuthenticated: Signal<boolean>;
504
+ /** Initialize auth state (restore session from cookies/storage) */
505
+ initialize(): Observable<void>;
386
506
  }
387
-
388
507
  /**
389
508
  * User data for dropdowns and selectors
390
509
  */
@@ -394,381 +513,103 @@ interface IUserBasicInfo {
394
513
  email: string;
395
514
  }
396
515
  /**
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
- * }
516
+ * User Provider Interface - Abstracts user data access for IAM and other feature packages.
413
517
  */
414
518
  interface IUserProvider {
415
- /**
416
- * Get list of users with pagination
417
- * @param filter Optional filter (page, pageSize, search, etc.)
418
- */
419
519
  getUsers(filter?: {
420
520
  page?: number;
421
521
  pageSize?: number;
422
522
  search?: string;
423
- companyId?: string;
424
- branchId?: string;
425
- [key: string]: any;
523
+ isActive?: boolean;
524
+ [key: string]: unknown;
426
525
  }): Observable<IListResponse<IUserBasicInfo>>;
427
526
  }
428
-
429
527
  /** Filter params passed to loadUsers function */
430
528
  interface IUserSelectFilter {
431
529
  page: number;
432
530
  pageSize: number;
433
531
  search: string;
434
- [key: string]: unknown;
435
532
  }
436
533
  /** Function type for loading users */
437
534
  type LoadUsersFn = (filter: IUserSelectFilter) => Observable<IListResponse<IUserBasicInfo>>;
438
-
439
535
  /**
440
- * Basic file info for selectors and displays
536
+ * User branch permission data
441
537
  */
442
- interface IFileBasicInfo {
443
- id: string;
444
- name: string;
445
- contentType: string;
446
- size: string;
447
- url: string | null;
538
+ interface IUserBranchPermission {
539
+ branchId: string;
540
+ branchName: string;
541
+ companyId: string;
448
542
  }
449
543
  /**
450
- * Upload options for file uploader
544
+ * User Permission Provider Interface - Abstracts user permission data access operations.
451
545
  */
452
- interface IFileUploadOptions {
453
- storageConfigId?: string;
454
- folderPath?: string;
455
- maxWidth?: number;
456
- maxHeight?: number;
457
- quality?: number;
458
- compress?: boolean;
546
+ interface IUserPermissionProvider {
547
+ getUserBranchPermissions(userId: string): Observable<ISingleResponse<IUserBranchPermission[]>>;
459
548
  }
460
549
  /**
461
- * Uploaded file response
550
+ * Company basic info for dropdowns
462
551
  */
463
- interface IUploadedFile {
464
- id?: string;
552
+ interface ICompanyBasicInfo {
553
+ id: string;
465
554
  name: string;
466
- key: string;
467
- size: number;
468
- contentType: string;
555
+ slug?: string;
469
556
  }
470
557
  /**
471
- * Filter params for file selector
558
+ * Company API Provider Interface
472
559
  */
473
- interface IFileSelectFilter {
474
- page: number;
475
- pageSize: number;
476
- search: string;
477
- contentTypes?: string[];
478
- folderId?: string;
479
- [key: string]: unknown;
560
+ interface ICompanyApiProvider {
561
+ getCompanies(filter?: {
562
+ page?: number;
563
+ pageSize?: number;
564
+ search?: string;
565
+ }): Observable<IListResponse<ICompanyBasicInfo>>;
480
566
  }
481
- /**
482
- * Function type for loading files
483
- */
484
- type LoadFilesFn = (filter: IFileSelectFilter) => Observable<IListResponse<IFileBasicInfo>>;
485
- /**
486
- * Function type for uploading a file
487
- */
488
- type UploadFileFn = (file: File, options?: IFileUploadOptions) => Observable<ISingleResponse<IUploadedFile>>;
489
- /**
490
- * Function type for getting file URLs (presigned URL refresh)
491
- */
492
- type GetFileUrlsFn = (fileIds: string[]) => Observable<ISingleResponse<IFileBasicInfo[]>>;
493
- /**
494
- * Common file type filters
495
- */
496
- declare const FILE_TYPE_FILTERS: {
497
- readonly IMAGES: readonly ["image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml"];
498
- readonly DOCUMENTS: readonly ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"];
499
- readonly VIDEOS: readonly ["video/mp4", "video/webm", "video/ogg", "video/quicktime"];
500
- readonly AUDIO: readonly ["audio/mpeg", "audio/wav", "audio/ogg", "audio/webm"];
501
- readonly ALL: string[];
502
- };
503
- /**
504
- * Get accept string for file input from content types
505
- */
506
- declare function getAcceptString(contentTypes: string[]): string;
507
- /**
508
- * Check if file matches allowed content types
509
- */
510
- declare function isFileTypeAllowed(file: File, allowedTypes: string[]): boolean;
511
- /**
512
- * Get file icon class based on content type
513
- */
514
- declare function getFileIconClass(contentType: string): string;
515
- /**
516
- * Format file size for display
517
- */
518
- declare function formatFileSize(sizeInKb: string | number): string;
519
-
520
567
  /**
521
568
  * User role info for profile display
522
569
  */
523
570
  interface IProfileRoleInfo {
524
571
  id: string;
525
572
  name: string;
526
- description?: string | null;
527
- }
528
- /**
529
- * User action info for profile display
530
- */
531
- interface IProfileActionInfo {
532
- id: string;
533
- name: string;
534
- code: string;
535
- description?: string | null;
536
- }
537
- /**
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
- * }
553
- */
554
- 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
- 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
- getUserActions(userId: string, branchId?: string): Observable<ISingleResponse<IProfileActionInfo[]>>;
567
- }
568
-
569
- /**
570
- * Uploaded file result with file manager ID
571
- */
572
- interface IProfileUploadResult {
573
- /** File manager ID (UUID) for storing in profilePictureId */
574
- id: string;
575
- /** Original file name */
576
- name: string;
577
- /** Storage key/path */
578
- key: string;
579
- /** File size in bytes */
580
- size: number;
581
- /** MIME type */
582
- contentType: string;
583
- }
584
- /**
585
- * Profile Upload Options
586
- */
587
- interface IProfileUploadOptions {
588
- /** Folder path for organizing uploads */
589
- folderPath?: string;
590
- /** Enable image compression */
591
- compress?: boolean;
592
- /** Max width for image compression */
593
- maxWidth?: number;
594
- /** Max height for image compression */
595
- maxHeight?: number;
596
- }
597
- /**
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.
605
- */
606
- 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
- uploadProfilePicture(file: File, options?: IProfileUploadOptions): Observable<ISingleResponse<IProfileUploadResult>>;
616
- }
617
-
618
- /**
619
- * Base user interface for list operations
620
- * Extends this with app-specific user fields
621
- */
622
- interface IUserListItem {
623
- id: string;
624
- name: string;
625
- email: string;
626
- phone?: string;
627
- isActive?: boolean;
628
- [key: string]: unknown;
629
- }
630
- /**
631
- * User list action definition
632
- * @template T User type, defaults to IUserListItem
633
- */
634
- interface IUserListAction<T = IUserListItem> {
635
- /** Unique action identifier */
636
- id: string;
637
- /** Display label */
638
- label: string;
639
- /** PrimeNG icon class (e.g., 'pi pi-pencil') */
640
- icon?: string;
641
- /** Severity for styling (e.g., 'primary', 'danger', 'warning') */
642
- severity?: 'primary' | 'secondary' | 'success' | 'info' | 'warn' | 'danger' | 'help' | 'contrast';
643
- /** Permission code required (checked via hasPermission) */
644
- permission?: string;
645
- /** Tooltip text */
646
- tooltip?: string;
647
- /** Whether action is disabled */
648
- disabled?: boolean | ((user: T) => boolean);
649
- /** Whether action is visible */
650
- visible?: boolean | ((user: T) => boolean);
651
- }
652
- /**
653
- * Extra column definition for user list
654
- */
655
- interface IUserListColumn {
656
- /** Column field name */
657
- field: string;
658
- /** Column header label */
659
- header: string;
660
- /** Column width */
661
- width?: string;
662
- /** Whether column is sortable */
663
- sortable?: boolean;
664
- /** Whether column is filterable */
665
- filterable?: boolean;
666
- /** Custom template type for rendering */
667
- templateType?: 'text' | 'badge' | 'date' | 'boolean' | 'custom';
668
- }
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[];
573
+ description?: string | null;
743
574
  }
744
575
  /**
745
- * Extra filter definition for user list
576
+ * User action info for profile display
746
577
  */
747
- interface IUserListFilter {
748
- /** Filter field name */
749
- field: string;
750
- /** Filter label */
751
- label: string;
752
- /** Filter type */
753
- type: 'text' | 'dropdown' | 'multiselect' | 'date' | 'boolean';
754
- /** Options for dropdown/multiselect */
755
- options?: {
756
- label: string;
757
- value: string | number | boolean;
758
- }[];
759
- /** Placeholder text */
760
- placeholder?: string;
578
+ interface IProfileActionInfo {
579
+ id: string;
580
+ name: string;
581
+ code: string;
582
+ description?: string | null;
761
583
  }
762
-
763
- declare enum ContactTypeEnum {
764
- PHONE = 1,
765
- EMAIL = 2
584
+ /**
585
+ * Profile Permission Provider Interface - Abstracts permission data access for profile page.
586
+ */
587
+ interface IProfilePermissionProvider {
588
+ getUserRoles(userId: string, branchId?: string): Observable<ISingleResponse<IProfileRoleInfo[]>>;
589
+ getUserActions(userId: string, branchId?: string): Observable<ISingleResponse<IProfileActionInfo[]>>;
590
+ }
591
+ /**
592
+ * File Provider Interface - Provides file loading and upload functionality.
593
+ * Used by FileSelectorDialogComponent to load files and handle uploads.
594
+ */
595
+ interface IFileProvider {
596
+ /** Load files with filtering and pagination */
597
+ loadFiles(filter: IFileSelectFilter): Observable<IListResponse<IFileBasicInfo>>;
598
+ /** Upload a single file and register in file manager */
599
+ uploadFile(file: File, options?: IFileUploadOptions): Observable<ISingleResponse<IUploadedFile>>;
600
+ /** Upload multiple files at once (more efficient batch upload) */
601
+ uploadMultipleFiles?(files: File[], options?: IFileUploadOptions): Observable<ISingleResponse<IUploadedFile[]>>;
602
+ /** Get file URLs by IDs (for refreshing presigned URLs) */
603
+ getFileUrls?(fileIds: string[]): Observable<ISingleResponse<IFileBasicInfo[]>>;
604
+ /** Load folders for folder selector (optional) */
605
+ loadFolders?(filter: ISelectFilter): Observable<IListResponse<IFolderBasicInfo>>;
606
+ /** Load storage configs for config selector (optional) */
607
+ loadStorageConfigs?(filter: ISelectFilter): Observable<IListResponse<IStorageConfigBasicInfo>>;
766
608
  }
767
609
 
768
610
  declare enum IconTypeEnum {
769
- PRIMENG_ICON = 1,
770
- IMAGE_FILE_LINK = 2,
771
- DIRECT_TAG_SVG = 3
611
+ ICON_NAME = 1,
612
+ IMAGE_FILE_LINK = 2
772
613
  }
773
614
 
774
615
  declare class CookieService {
@@ -780,15 +621,17 @@ declare class CookieService {
780
621
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<CookieService>;
781
622
  }
782
623
 
783
- /**
784
- * Request DTO for fetching file URLs
785
- */
786
- interface GetFilesRequestDto {
787
- id: string;
624
+ declare class FaviconService {
625
+ private readonly http;
626
+ private readonly platformService;
627
+ private readonly document;
628
+ private svgTemplate;
629
+ apply(): void;
630
+ private render;
631
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FaviconService, never>;
632
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<FaviconService>;
788
633
  }
789
- /**
790
- * Response DTO with file information including URL
791
- */
634
+
792
635
  interface FilesResponseDto {
793
636
  id: string;
794
637
  name: string;
@@ -797,113 +640,40 @@ interface FilesResponseDto {
797
640
  }
798
641
  /**
799
642
  * 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)
643
+ * Handles presigned URLs for cloud storage, auto-refresh, and caching.
805
644
  */
806
645
  declare class FileUrlService {
807
646
  private readonly http;
808
647
  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
- */
814
- 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
- */
648
+ private readonly _cache;
649
+ readonly cache: _angular_core.Signal<Map<string, FilesResponseDto>>;
650
+ /** Fetch file URLs from backend and update cache */
824
651
  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
- */
652
+ /** Fetch single file URL (delegates to fetchFileUrls) */
830
653
  fetchSingleFileUrl(fileId: string, forceRefresh?: boolean): Observable<FilesResponseDto | null>;
831
- /**
832
- * Clear the URL cache.
833
- * Useful on logout or when switching contexts.
834
- */
835
- clearCache(): void;
836
- /**
837
- * Remove specific file from cache.
838
- */
839
- removeFromCache(fileId: string): void;
654
+ private addToCache;
655
+ private getFromCache;
840
656
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<FileUrlService, never>;
841
657
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<FileUrlService>;
842
658
  }
843
659
 
844
660
  /**
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
661
+ * Permission state management service.
662
+ * Provides signal-based storage and permission checking with wildcard support.
874
663
  */
875
664
  declare class PermissionValidatorService {
876
- /**
877
- * Private writable signal for permissions
878
- */
879
665
  private readonly _permissions;
880
- /**
881
- * Readonly permission signal for external consumers
882
- */
883
666
  readonly permissions: _angular_core.Signal<string[]>;
884
- /**
885
- * Private writable signal for loaded state
886
- */
887
667
  private readonly _isLoaded;
888
- /**
889
- * Set permissions (replaces existing permissions)
890
- * @param permissions - Array of permission codes
891
- */
668
+ readonly isLoaded: _angular_core.Signal<boolean>;
669
+ /** Set permissions (replaces existing) */
892
670
  setPermissions(permissions: string[]): void;
893
- /**
894
- * Clear all permissions
895
- */
671
+ /** Clear all permissions */
896
672
  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
- */
673
+ /** Check if user has permission (supports wildcards: '*', 'module.*') */
674
+ hasPermission(code: string): boolean;
675
+ /** Check if user has ANY of the specified permissions (OR logic) */
676
+ hasAnyPermission(code: string[]): boolean;
907
677
  isPermissionsLoaded(): boolean;
908
678
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<PermissionValidatorService, never>;
909
679
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<PermissionValidatorService>;
@@ -916,6 +686,16 @@ declare class PlatformService {
916
686
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<PlatformService>;
917
687
  }
918
688
 
689
+ declare class TranslateService {
690
+ private readonly localizationState;
691
+ private readonly registry;
692
+ translate(key: string, params?: Record<string, string | unknown>): string;
693
+ translateSignal(key: string, params?: Record<string, string | number>): Signal<string>;
694
+ private interpolate;
695
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<TranslateService, never>;
696
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<TranslateService>;
697
+ }
698
+
919
699
  declare class EditModeElementChangerDirective {
920
700
  private readonly el;
921
701
  private readonly ngControl;
@@ -954,20 +734,18 @@ declare class EditModeElementChangerDirective {
954
734
  * @example
955
735
  * // In component
956
736
  * readonly userManageLogic: ILogicNode = {
957
- * id: 'root',
958
737
  * type: 'group',
959
738
  * operator: 'AND',
960
739
  * children: [
961
740
  * {
962
- * id: '1',
963
741
  * type: 'group',
964
742
  * operator: 'OR',
965
743
  * children: [
966
- * { id: '2', type: 'action', actionId: 'user.view' },
967
- * { id: '3', type: 'action', actionId: 'user.create' }
744
+ * { type: 'action', actionId: 'user.view' },
745
+ * { type: 'action', actionId: 'user.create' }
968
746
  * ]
969
747
  * },
970
- * { id: '4', type: 'action', actionId: 'department.manage' }
748
+ * { type: 'action', actionId: 'department.manage' }
971
749
  * ]
972
750
  * };
973
751
  *
@@ -1015,9 +793,9 @@ declare class IsEmptyImageDirective {
1015
793
  }
1016
794
 
1017
795
  declare class PreventDefaultDirective {
1018
- eventType: _angular_core.InputSignal<"click" | "keydown" | "keyup">;
1019
- preventKey: _angular_core.InputSignal<string | undefined>;
1020
- action: _angular_core.OutputEmitterRef<Event>;
796
+ readonly eventType: _angular_core.InputSignal<"click" | "keydown" | "keyup">;
797
+ readonly preventKey: _angular_core.InputSignal<string | undefined>;
798
+ readonly action: _angular_core.OutputEmitterRef<Event>;
1021
799
  onClick(event: MouseEvent): void;
1022
800
  onKeydown(event: KeyboardEvent): void;
1023
801
  onKeyup(event: KeyboardEvent): void;
@@ -1026,206 +804,458 @@ declare class PreventDefaultDirective {
1026
804
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<PreventDefaultDirective, "[appPreventDefault]", never, { "eventType": { "alias": "eventType"; "required": false; "isSignal": true; }; "preventKey": { "alias": "preventKey"; "required": false; "isSignal": true; }; }, { "action": "action"; }, never, never, true, never>;
1027
805
  }
1028
806
 
1029
- declare class AngularModule {
1030
- 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]>;
1032
- static ɵinj: _angular_core.ɵɵInjectorDeclaration<AngularModule>;
1033
- }
1034
-
1035
- declare class PrimeModule {
1036
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<PrimeModule, never>;
1037
- static ɵmod: _angular_core.ɵɵNgModuleDeclaration<PrimeModule, never, never, [typeof i1$1.AutoCompleteModule, typeof i2$1.AvatarModule, typeof i3$1.ButtonModule, typeof i4.CardModule, typeof i5.CheckboxModule, typeof i6.ConfirmDialogModule, typeof i7.DatePickerModule, typeof i8.DialogModule, typeof i9.DividerModule, typeof i10.FileUploadModule, typeof i11.IconFieldModule, typeof i12.ImageModule, typeof i13.InputIconModule, typeof i14.InputNumberModule, typeof i15.InputTextModule, typeof i16.ListboxModule, typeof i17.MultiSelectModule, typeof i18.PaginatorModule, typeof i19.PanelModule, typeof i20.PasswordModule, typeof i21.PopoverModule, typeof i22.ProgressBarModule, typeof i23.RadioButtonModule, typeof i24.RippleModule, typeof i25.SelectButtonModule, typeof i26.SelectModule, typeof i27.SkeletonModule, typeof i28.SplitButtonModule, typeof i29.StepsModule, typeof i30.TableModule, typeof i31.TabsModule, typeof i32.TagModule, typeof i33.TextareaModule, typeof i34.ToastModule, typeof i35.ToggleSwitchModule, typeof i36.TooltipModule, typeof i37.TreeTableModule]>;
1038
- static ɵinj: _angular_core.ɵɵInjectorDeclaration<PrimeModule>;
807
+ declare class TranslatePipe implements PipeTransform {
808
+ private readonly translateAdapter;
809
+ transform(key: string | null | undefined, params?: Record<string, string | number> | null, fallback?: string): string;
810
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<TranslatePipe, never>;
811
+ static ɵpipe: _angular_core.ɵɵPipeDeclaration<TranslatePipe, "translate", true>;
1039
812
  }
1040
813
 
1041
814
  /**
1042
- * Service interface for CRUD operations.
1043
- * Matches NestJS shared API controller endpoints:
815
+ * HTTP context token to skip global error toast.
816
+ * Use when component handles error display locally.
1044
817
  *
1045
- * | Angular Method | HTTP | NestJS Endpoint | Response Type |
1046
- * |------------------|--------|------------------------|------------------------|
1047
- * | insert() | POST | /{resource}/insert | ISingleResponse<T> |
1048
- * | insertMany() | POST | /{resource}/insert-many| IBulkResponse<T> |
1049
- * | findById() | POST | /{resource}/get/:id | ISingleResponse<T> |
1050
- * | getAll() | POST | /{resource}/get-all | IListResponse<T> |
1051
- * | update() | POST | /{resource}/update | ISingleResponse<T> |
1052
- * | updateMany() | POST | /{resource}/update-many| IBulkResponse<T> |
1053
- * | delete() | POST | /{resource}/delete | IMessageResponse |
818
+ * @example
819
+ * ```typescript
820
+ * this.http.post(url, data, {
821
+ * context: new HttpContext().set(SKIP_ERROR_TOAST, true)
822
+ * });
823
+ * ```
1054
824
  */
1055
- interface IApiService<DtoT, InterfaceT> {
1056
- insert(dto: DtoT): Observable<ISingleResponse<InterfaceT>>;
1057
- insertMany(dtos: DtoT[]): Observable<IBulkResponse<InterfaceT>>;
1058
- findById(id: string, select?: string[]): Observable<ISingleResponse<InterfaceT>>;
1059
- getAll(search: string, filter: IFilterData): Observable<IListResponse<InterfaceT>>;
1060
- update(dto: DtoT): Observable<ISingleResponse<InterfaceT>>;
1061
- updateMany(dtos: DtoT[]): Observable<IBulkResponse<InterfaceT>>;
1062
- delete(deleteDto: IDeleteData): Observable<IMessageResponse>;
1063
- }
825
+ declare const SKIP_ERROR_TOAST: HttpContextToken<boolean>;
1064
826
  /**
1065
- * Abstract base class for API services using Angular 21 resource() API.
1066
- * Provides signal-based reactive data fetching with automatic loading states.
1067
- * Response types match FLUSYS_NEST backend DTOs.
827
+ * Error Catching Interceptor
828
+ * Displays error messages for failed HTTP requests using backend response.
1068
829
  *
1069
- * ## Endpoint Mapping
830
+ * Features:
831
+ * - Uses backend's error title (error.error.error) as summary
832
+ * - Uses backend's error message (error.error.message) as detail
833
+ * - Falls back to sensible defaults based on status code
834
+ * - Skip with SKIP_ERROR_TOAST context token for local handling
1070
835
  *
1071
- * All endpoints use POST method (RPC-style API):
1072
- * - `POST /{resource}/insert` - Create single item
1073
- * - `POST /{resource}/insert-many` - Create multiple items
1074
- * - `POST /{resource}/get/:id` - Get single item by ID
1075
- * - `POST /{resource}/get-all?q=` - List with pagination/filter
1076
- * - `POST /{resource}/update` - Update single item
1077
- * - `POST /{resource}/update-many` - Update multiple items
1078
- * - `POST /{resource}/delete` - Delete/restore/permanent delete
836
+ * NOTE: This interceptor only handles error display.
837
+ * For 401 handling and token refresh, use tokenRefreshInterceptor from @flusys/ng-auth.
1079
838
  *
1080
839
  * @example
1081
840
  * ```typescript
1082
- * // Define service
1083
- * @Injectable({ providedIn: 'root' })
1084
- * export class UserService extends ApiResourceService<UserDto, User> {
1085
- * constructor(http: HttpClient) {
1086
- * super('users', http);
1087
- * }
1088
- * }
1089
- *
1090
- * // In component - use signals
1091
- * userService = inject(UserService);
1092
- * users = this.userService.data; // Signal<User[]>
1093
- * isLoading = this.userService.isLoading; // Signal<boolean>
1094
- * total = this.userService.total; // Signal<number>
1095
- *
1096
- * // Trigger fetch
1097
- * this.userService.fetchList('search', { pagination: { currentPage: 0, pageSize: 10 } });
1098
- *
1099
- * // CRUD operations
1100
- * await this.userService.insertAsync({ name: 'John', email: 'john@example.com' });
1101
- * await this.userService.updateAsync({ id: '123', name: 'John Updated' });
1102
- * await this.userService.deleteAsync({ id: '123', type: 'delete' });
841
+ * // In app.config.ts
842
+ * provideHttpClient(
843
+ * withFetch(),
844
+ * withInterceptors([
845
+ * authInterceptor, // from @flusys/ng-auth
846
+ * tokenRefreshInterceptor, // from @flusys/ng-auth
847
+ * errorCatchingInterceptor, // from @flusys/ng-core
848
+ * apiLoaderInterceptor, // from @flusys/ng-core
849
+ * ])
850
+ * )
1103
851
  * ```
1104
852
  */
853
+ declare function errorCatchingInterceptor(req: HttpRequest<unknown>, next: HttpHandlerFn): Observable<HttpEvent<unknown>>;
854
+
855
+ interface IResolverModuleConfig {
856
+ modules: string[];
857
+ fallbackMessages?: Record<string, string>;
858
+ }
859
+ declare function resolveTranslationModule(config: IResolverModuleConfig): ResolveFn<boolean>;
860
+
861
+ declare class AngularModule {
862
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<AngularModule, never>;
863
+ static ɵmod: _angular_core.ɵɵNgModuleDeclaration<AngularModule, never, [typeof i1.CommonModule, typeof i2.FormsModule, typeof i2.ReactiveFormsModule, typeof i3.RouterOutlet, typeof i3.RouterLink, typeof i3.RouterLinkActive, typeof IsEmptyImageDirective, typeof i1.NgOptimizedImage, typeof i1.NgComponentOutlet, typeof PreventDefaultDirective], [typeof i1.CommonModule, typeof i2.FormsModule, typeof i2.ReactiveFormsModule, typeof i3.RouterOutlet, typeof i3.RouterLink, typeof i3.RouterLinkActive, typeof IsEmptyImageDirective, typeof i1.NgOptimizedImage, typeof i1.NgComponentOutlet, typeof PreventDefaultDirective]>;
864
+ static ɵinj: _angular_core.ɵɵInjectorDeclaration<AngularModule>;
865
+ }
866
+
867
+ interface IApiService<DtoT, InterfaceT> {
868
+ insert(dto: DtoT): Promise<ISingleResponse<InterfaceT>>;
869
+ insertMany(dtos: DtoT[]): Promise<IBulkResponse<InterfaceT>>;
870
+ findById(id: string, select?: string[]): Promise<ISingleResponse<InterfaceT>>;
871
+ findByIds(ids: string[], select?: string[] | string): Promise<IListResponse<InterfaceT>>;
872
+ getAll(filter: IFilterData, search?: string): Promise<IListResponse<InterfaceT>>;
873
+ getByFilter(filter: Record<string, unknown>): Promise<ISingleResponse<InterfaceT>>;
874
+ update(dto: DtoT): Promise<ISingleResponse<InterfaceT>>;
875
+ updateMany(dtos: DtoT[]): Promise<IBulkResponse<InterfaceT>>;
876
+ bulkUpsert(toInsert: DtoT[], toUpdate: DtoT[]): Promise<InterfaceT[]>;
877
+ delete(deleteDto: IDeleteData): Promise<IMessageResponse>;
878
+ }
1105
879
  declare abstract class ApiResourceService<DtoT, InterfaceT> implements IApiService<DtoT, InterfaceT> {
1106
- protected readonly baseUrl: string;
1107
- protected readonly loaderService: ApiLoaderService;
1108
- protected readonly injector: Injector;
1109
880
  protected readonly http: HttpClient;
881
+ private readonly _config;
882
+ protected readonly baseUrl: string;
1110
883
  protected readonly moduleApiName: string;
1111
- /** Current search term */
1112
884
  readonly searchTerm: _angular_core.WritableSignal<string>;
1113
- /** Current filter and pagination state */
1114
885
  readonly filterData: _angular_core.WritableSignal<IFilterData>;
1115
- /**
1116
- * Resource for list data - lazy initialized to prevent auto-fetch on service injection.
1117
- * Call initListResource() or any list method (fetchList, reload, etc.) to initialize.
1118
- */
1119
- private _listResource;
1120
- /** Whether the list resource has been initialized */
1121
- private _resourceInitialized;
1122
- /** Get or create the list resource (lazy initialization) */
1123
- get listResource(): ResourceRef<IListResponse<InterfaceT> | undefined>;
1124
- /**
1125
- * Initialize the list resource. Called automatically when accessing listResource
1126
- * or any list-related computed signals/methods.
1127
- * Uses runInInjectionContext to support lazy initialization outside constructor.
1128
- */
1129
- initListResource(): void;
1130
- /** Whether data is currently loading */
886
+ private readonly _active;
887
+ readonly listResource: ResourceRef<IListResponse<InterfaceT> | undefined>;
1131
888
  readonly isLoading: _angular_core.Signal<boolean>;
1132
- /** List data array */
1133
889
  readonly data: _angular_core.Signal<InterfaceT[]>;
1134
- /** Total count of items */
1135
890
  readonly total: _angular_core.Signal<number>;
1136
- /** Pagination metadata */
1137
891
  readonly pageInfo: _angular_core.Signal<_flusys_ng_shared.IPaginationMeta | undefined>;
1138
- /** Whether there are more pages */
1139
892
  readonly hasMore: _angular_core.Signal<boolean>;
1140
- constructor(moduleApiName: string, http: HttpClient);
893
+ readonly error: _angular_core.Signal<Error | undefined>;
894
+ readonly status: _angular_core.Signal<ResourceStatus>;
895
+ constructor(moduleApiName: string, serviceName?: ServiceName);
1141
896
  protected getHttpOptions(endpoint: string, params?: HttpParams): {
1142
897
  params?: HttpParams | undefined;
1143
898
  headers: HttpHeaders;
1144
899
  };
1145
- /**
1146
- * Fetch list data (triggers resource initialization and reload)
1147
- */
900
+ private _getAllObs;
901
+ private _activate;
1148
902
  fetchList(search?: string, filter?: Partial<IFilterData>): void;
1149
- /**
1150
- * Update pagination
1151
- */
1152
903
  setPagination(pagination: IPagination): void;
1153
- /**
1154
- * Go to next page
1155
- */
1156
904
  nextPage(): void;
1157
- /**
1158
- * Reset to first page
1159
- */
1160
905
  resetPagination(): void;
1161
- /**
1162
- * Reload current data
1163
- */
1164
906
  reload(): void;
907
+ private _post;
908
+ insert(dto: DtoT): Promise<ISingleResponse<InterfaceT>>;
909
+ insertMany(dtos: DtoT[]): Promise<IBulkResponse<InterfaceT>>;
910
+ findById(id: string, select?: string[]): Promise<ISingleResponse<InterfaceT>>;
911
+ getAll(filter: IFilterData, search?: string): Promise<IListResponse<InterfaceT>>;
912
+ update(dto: DtoT): Promise<ISingleResponse<InterfaceT>>;
913
+ updateMany(dtos: DtoT[]): Promise<IBulkResponse<InterfaceT>>;
914
+ delete(deleteDto: IDeleteData): Promise<IMessageResponse>;
915
+ findByIds(ids: string[], select?: string[] | string): Promise<IListResponse<InterfaceT>>;
916
+ getByFilter(filter: Record<string, unknown>): Promise<ISingleResponse<InterfaceT>>;
917
+ bulkUpsert(toInsert: DtoT[], toUpdate: DtoT[]): Promise<InterfaceT[]>;
918
+ }
919
+
920
+ declare abstract class BaseFormControl<T> implements ControlValueAccessor, FormValueControl<T> {
921
+ protected readonly injector: Injector;
922
+ abstract readonly value: ReturnType<typeof model<T>>;
923
+ readonly disabled: _angular_core.ModelSignal<boolean>;
924
+ readonly touched: _angular_core.ModelSignal<boolean>;
925
+ private onChange;
926
+ private onTouched;
927
+ private writeDepth;
1165
928
  /**
1166
- * Insert single item (Observable)
1167
- * POST /{resource}/insert
1168
- */
1169
- insert(dto: DtoT): Observable<ISingleResponse<InterfaceT>>;
1170
- /**
1171
- * Insert multiple items (Observable)
1172
- * POST /{resource}/insert-many
1173
- */
1174
- insertMany(dtos: DtoT[]): Observable<IBulkResponse<InterfaceT>>;
1175
- /**
1176
- * Find single item by ID (Observable)
1177
- * POST /{resource}/get/:id
1178
- */
1179
- findById(id: string, select?: string[]): Observable<ISingleResponse<InterfaceT>>;
1180
- /**
1181
- * Get all items with pagination (Observable)
1182
- * POST /{resource}/get-all?q=search
1183
- */
1184
- getAll(search: string, filter: IFilterData): Observable<IListResponse<InterfaceT>>;
1185
- /**
1186
- * Update single item (Observable)
1187
- * POST /{resource}/update
1188
- */
1189
- update(dto: DtoT): Observable<ISingleResponse<InterfaceT>>;
1190
- /**
1191
- * Update multiple items (Observable)
1192
- * POST /{resource}/update-many
1193
- */
1194
- updateMany(dtos: DtoT[]): Observable<IBulkResponse<InterfaceT>>;
1195
- /**
1196
- * Delete items (Observable)
1197
- * POST /{resource}/delete
1198
- * @param deleteDto - { id: string | string[], type: 'delete' | 'restore' | 'permanent' }
1199
- */
1200
- delete(deleteDto: IDeleteData): Observable<IMessageResponse>;
1201
- /**
1202
- * Fetch paginated list (async)
1203
- */
1204
- protected fetchAllAsync(search: string, filter: IFilterData): Promise<IListResponse<InterfaceT>>;
1205
- /**
1206
- * Find single item by ID (async)
1207
- */
1208
- findByIdAsync(id: string, select?: string[]): Promise<ISingleResponse<InterfaceT>>;
1209
- /**
1210
- * Insert single item (async)
1211
- */
1212
- insertAsync(dto: DtoT): Promise<ISingleResponse<InterfaceT>>;
1213
- /**
1214
- * Insert multiple items (async)
1215
- */
1216
- insertManyAsync(dtos: DtoT[]): Promise<IBulkResponse<InterfaceT>>;
1217
- /**
1218
- * Update single item (async)
1219
- */
1220
- updateAsync(dto: DtoT): Promise<ISingleResponse<InterfaceT>>;
1221
- /**
1222
- * Update multiple items (async)
1223
- */
1224
- updateManyAsync(dtos: DtoT[]): Promise<IBulkResponse<InterfaceT>>;
1225
- /**
1226
- * Delete items (async)
929
+ * Wire up the ControlValueAccessor ↔ signal bridge.
930
+ * Call once at the end of the subclass constructor.
931
+ *
932
+ * Signal-form consumers ([formField]) don't need this — Angular's
933
+ * FormField directive binds directly to `value`.
934
+ *
935
+ * @example
936
+ * constructor() { super(); this.initializeFormControl(); }
1227
937
  */
1228
- deleteAsync(deleteDto: IDeleteData): Promise<IMessageResponse>;
938
+ protected initializeFormControl(): void;
939
+ writeValue(value: T): void;
940
+ registerOnChange(fn: (value: T) => void): void;
941
+ registerOnTouched(fn: () => void): void;
942
+ setDisabledState(isDisabled: boolean): void;
943
+ /** Call on blur / panel-close to propagate touched state. */
944
+ protected markAsTouched(): void;
945
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseFormControl<any>, never>;
946
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<BaseFormControl<any>, never, never, { "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "touched": { "alias": "touched"; "required": false; "isSignal": true; }; }, { "disabled": "disabledChange"; "touched": "touchedChange"; }, never, never, true, never>;
947
+ }
948
+ /**
949
+ * Factory function to provide NG_VALUE_ACCESSOR for a component.
950
+ * Use in component providers array.
951
+ *
952
+ * @example
953
+ * ```typescript
954
+ * @Component({
955
+ * providers: [provideValueAccessor(LazySelectComponent)]
956
+ * })
957
+ * export class LazySelectComponent extends BaseFormControl<string | null> {}
958
+ * ```
959
+ */
960
+ declare function provideValueAccessor<T extends new (...args: unknown[]) => ControlValueAccessor>(component: T): {
961
+ provide: _angular_core.InjectionToken<readonly ControlValueAccessor[]>;
962
+ useExisting: _angular_core.Type<any>;
963
+ multi: boolean;
964
+ };
965
+
966
+ declare class BaseFormTemplateDirective {
967
+ readonly key: _angular_core.InputSignal<string>;
968
+ readonly templateRef: TemplateRef<any>;
969
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseFormTemplateDirective, never>;
970
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<BaseFormTemplateDirective, "ng-template[baseFormTemplate]", never, { "key": { "alias": "baseFormTemplate"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
971
+ }
972
+
973
+ type FormFieldType = 'text' | 'email' | 'password' | 'number' | 'textarea' | 'select' | 'multiselect' | 'date' | 'checkbox' | 'toggle' | 'custom';
974
+ interface IFormSelectOption {
975
+ label: string;
976
+ value: unknown;
977
+ }
978
+ interface IFormField {
979
+ key: string;
980
+ type: FormFieldType;
981
+ label: string;
982
+ placeholder?: string;
983
+ required?: boolean;
984
+ disabled?: boolean;
985
+ fullWidth?: boolean;
986
+ options?: IFormSelectOption[];
987
+ minDate?: Date;
988
+ maxDate?: Date;
989
+ rows?: number;
990
+ min?: number;
991
+ max?: number;
992
+ hint?: string;
993
+ }
994
+
995
+ declare class BaseFormComponent {
996
+ private readonly translateAdapter;
997
+ private readonly router;
998
+ private readonly messageService;
999
+ readonly fields: _angular_core.InputSignal<IFormField[]>;
1000
+ readonly title: _angular_core.InputSignal<string>;
1001
+ readonly createTitle: _angular_core.InputSignal<string>;
1002
+ readonly editTitle: _angular_core.InputSignal<string>;
1003
+ readonly columns: _angular_core.InputSignal<1 | 2 | 3>;
1004
+ readonly submitLabel: _angular_core.InputSignal<string>;
1005
+ readonly cancelLabel: _angular_core.InputSignal<string>;
1006
+ readonly isLoading: _angular_core.InputSignal<boolean>;
1007
+ readonly isEditMode: _angular_core.InputSignal<boolean>;
1008
+ readonly initialValue: _angular_core.InputSignal<Record<string, unknown>>;
1009
+ readonly service: _angular_core.InputSignal<ApiResourceService<unknown, unknown> | null>;
1010
+ readonly editId: _angular_core.InputSignal<string | null>;
1011
+ readonly cancelRoute: _angular_core.InputSignal<string | string[] | null>;
1012
+ readonly navigateOnSuccess: _angular_core.InputSignal<string | string[] | null>;
1013
+ readonly mapToRequest: _angular_core.InputSignal<((data: Record<string, unknown>, editId: string | null) => unknown) | null>;
1014
+ readonly mapFromEntity: _angular_core.InputSignal<((entity: unknown) => Record<string, unknown>) | null>;
1015
+ readonly onSubmit: _angular_core.OutputEmitterRef<Record<string, unknown>>;
1016
+ readonly onCancel: _angular_core.OutputEmitterRef<void>;
1017
+ readonly onValueChange: _angular_core.OutputEmitterRef<Record<string, unknown>>;
1018
+ readonly fieldTemplates: _angular_core.Signal<readonly BaseFormTemplateDirective[]>;
1019
+ private readonly _formData;
1020
+ private readonly _submitted;
1021
+ private readonly _isLoadingInternal;
1022
+ private readonly _touchedFields;
1023
+ private readonly _visiblePasswordFields;
1024
+ readonly formData: _angular_core.Signal<Record<string, unknown>>;
1025
+ readonly submitted: _angular_core.Signal<boolean>;
1026
+ readonly effectiveIsEditMode: _angular_core.Signal<boolean>;
1027
+ readonly effectiveIsLoading: _angular_core.Signal<boolean>;
1028
+ readonly isFormValid: _angular_core.Signal<boolean>;
1029
+ readonly resolvedTitle: _angular_core.Signal<string>;
1030
+ readonly gridClass: _angular_core.Signal<"grid-cols-1" | "grid-cols-1 md:grid-cols-3" | "grid-cols-1 md:grid-cols-2">;
1031
+ constructor();
1032
+ private loadEntity;
1033
+ getFieldValue(key: string): unknown;
1034
+ setFieldValue(key: string, value: unknown): void;
1035
+ markFieldTouched(key: string): void;
1036
+ isPasswordVisible(key: string): boolean;
1037
+ togglePasswordVisibility(key: string): void;
1038
+ isFieldInvalid(field: IFormField): boolean;
1039
+ getFieldTemplate(key: string): TemplateRef<unknown> | null;
1040
+ handleSubmit(): Promise<void>;
1041
+ handleCancel(): void;
1042
+ reset(): void;
1043
+ t(key: string, vars?: Record<string, string | number>): string;
1044
+ private managedSubmit;
1045
+ private checkValidity;
1046
+ private navigateTo;
1047
+ private getDefaultValue;
1048
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseFormComponent, never>;
1049
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<BaseFormComponent, "lib-base-form", never, { "fields": { "alias": "fields"; "required": true; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "createTitle": { "alias": "createTitle"; "required": false; "isSignal": true; }; "editTitle": { "alias": "editTitle"; "required": false; "isSignal": true; }; "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "submitLabel": { "alias": "submitLabel"; "required": false; "isSignal": true; }; "cancelLabel": { "alias": "cancelLabel"; "required": false; "isSignal": true; }; "isLoading": { "alias": "isLoading"; "required": false; "isSignal": true; }; "isEditMode": { "alias": "isEditMode"; "required": false; "isSignal": true; }; "initialValue": { "alias": "initialValue"; "required": false; "isSignal": true; }; "service": { "alias": "service"; "required": false; "isSignal": true; }; "editId": { "alias": "editId"; "required": false; "isSignal": true; }; "cancelRoute": { "alias": "cancelRoute"; "required": false; "isSignal": true; }; "navigateOnSuccess": { "alias": "navigateOnSuccess"; "required": false; "isSignal": true; }; "mapToRequest": { "alias": "mapToRequest"; "required": false; "isSignal": true; }; "mapFromEntity": { "alias": "mapFromEntity"; "required": false; "isSignal": true; }; }, { "onSubmit": "onSubmit"; "onCancel": "onCancel"; "onValueChange": "onValueChange"; }, ["fieldTemplates"], never, true, never>;
1050
+ }
1051
+
1052
+ declare class BaseListTemplateDirective {
1053
+ readonly key: _angular_core.InputSignal<string>;
1054
+ readonly templateRef: TemplateRef<any>;
1055
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseListTemplateDirective, never>;
1056
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<BaseListTemplateDirective, "ng-template[baseListTemplate]", never, { "key": { "alias": "baseListTemplate"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
1057
+ }
1058
+
1059
+ type TableColumnType = 'text' | 'date' | 'tag' | 'boolean' | 'number' | 'custom';
1060
+ type ActionSeverity = 'success' | 'info' | 'warn' | 'danger' | 'secondary' | 'contrast';
1061
+ interface ITagConfig {
1062
+ label?: string;
1063
+ severity: 'success' | 'danger' | 'warn' | 'info' | 'secondary' | 'contrast';
1064
+ }
1065
+ interface ITableColumn {
1066
+ field: string;
1067
+ header: string;
1068
+ type?: TableColumnType;
1069
+ width?: string;
1070
+ minWidth?: string;
1071
+ align?: 'left' | 'center' | 'right';
1072
+ tagMap?: Record<string, ITagConfig>;
1073
+ dateFormat?: string;
1074
+ truncate?: number;
1075
+ hidden?: boolean;
1076
+ }
1077
+ interface ITableAction<T = unknown> {
1078
+ icon: string;
1079
+ tooltip?: string;
1080
+ severity?: ActionSeverity;
1081
+ show?: (item: T) => boolean;
1082
+ disabled?: (item: T) => boolean;
1083
+ handler: (item: T) => void;
1084
+ }
1085
+
1086
+ declare class BaseListComponent {
1087
+ private readonly translateAdapter;
1088
+ private readonly router;
1089
+ private readonly messageService;
1090
+ private readonly confirmationService;
1091
+ readonly columns: _angular_core.InputSignal<ITableColumn[]>;
1092
+ readonly actions: _angular_core.InputSignal<ITableAction<unknown>[]>;
1093
+ readonly title: _angular_core.InputSignal<string>;
1094
+ readonly showCreateButton: _angular_core.InputSignal<boolean>;
1095
+ readonly searchable: _angular_core.InputSignal<boolean>;
1096
+ readonly pageSize: _angular_core.InputSignal<number>;
1097
+ readonly emptyMessage: _angular_core.InputSignal<string>;
1098
+ readonly createButtonLabel: _angular_core.InputSignal<string>;
1099
+ readonly createButtonIcon: _angular_core.InputSignal<string>;
1100
+ readonly data: _angular_core.InputSignal<unknown[]>;
1101
+ readonly total: _angular_core.InputSignal<number>;
1102
+ readonly isLoading: _angular_core.InputSignal<boolean>;
1103
+ readonly service: _angular_core.InputSignal<ApiResourceService<unknown, unknown> | null>;
1104
+ readonly filter: _angular_core.InputSignal<IFilter>;
1105
+ readonly createRoute: _angular_core.InputSignal<string | null>;
1106
+ readonly editRoute: _angular_core.InputSignal<string | null>;
1107
+ readonly deleteConfirmField: _angular_core.InputSignal<string | null>;
1108
+ readonly idField: _angular_core.InputSignal<string>;
1109
+ readonly canEdit: _angular_core.InputSignal<((item: unknown) => boolean) | null>;
1110
+ readonly canDelete: _angular_core.InputSignal<((item: unknown) => boolean) | null>;
1111
+ readonly onCreate: _angular_core.OutputEmitterRef<void>;
1112
+ readonly onLazyLoad: _angular_core.OutputEmitterRef<{
1113
+ first: number;
1114
+ rows: number;
1115
+ }>;
1116
+ readonly onSearch: _angular_core.OutputEmitterRef<string>;
1117
+ readonly columnTemplates: _angular_core.Signal<readonly BaseListTemplateDirective[]>;
1118
+ private readonly _first;
1119
+ private readonly _searchTerm;
1120
+ readonly first: _angular_core.Signal<number>;
1121
+ readonly searchTerm: _angular_core.Signal<string>;
1122
+ readonly effectiveData: _angular_core.Signal<unknown[]>;
1123
+ readonly effectiveTotal: _angular_core.Signal<number>;
1124
+ readonly effectiveIsLoading: _angular_core.Signal<boolean>;
1125
+ readonly effectiveActions: _angular_core.Signal<ITableAction<unknown>[]>;
1126
+ readonly visibleColumns: _angular_core.Signal<ITableColumn[]>;
1127
+ readonly columnCount: _angular_core.Signal<number>;
1128
+ readonly resolvedEmptyMessage: _angular_core.Signal<string>;
1129
+ readonly resolvedCreateLabel: _angular_core.Signal<string>;
1130
+ handleLazyLoad(event: {
1131
+ first?: number | null;
1132
+ rows?: number | null;
1133
+ }): void;
1134
+ onSearchChange(value: string): void;
1135
+ handleCreate(): void;
1136
+ private handleEditItem;
1137
+ private handleDeleteItem;
1138
+ getFieldValue(item: unknown, field: string): unknown;
1139
+ getFieldValueAsString(item: unknown, field: string): string;
1140
+ getTagConfig(col: ITableColumn, value: unknown): ITagConfig | null;
1141
+ getColumnTemplate(field: string): TemplateRef<unknown> | null;
1142
+ truncateText(value: unknown, limit?: number): string;
1143
+ getCellClass(col: ITableColumn): string;
1144
+ t(key: string, vars?: Record<string, string | number>): string;
1145
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseListComponent, never>;
1146
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<BaseListComponent, "lib-base-list", never, { "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "actions": { "alias": "actions"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "showCreateButton": { "alias": "showCreateButton"; "required": false; "isSignal": true; }; "searchable": { "alias": "searchable"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "emptyMessage": { "alias": "emptyMessage"; "required": false; "isSignal": true; }; "createButtonLabel": { "alias": "createButtonLabel"; "required": false; "isSignal": true; }; "createButtonIcon": { "alias": "createButtonIcon"; "required": false; "isSignal": true; }; "data": { "alias": "data"; "required": false; "isSignal": true; }; "total": { "alias": "total"; "required": false; "isSignal": true; }; "isLoading": { "alias": "isLoading"; "required": false; "isSignal": true; }; "service": { "alias": "service"; "required": false; "isSignal": true; }; "filter": { "alias": "filter"; "required": false; "isSignal": true; }; "createRoute": { "alias": "createRoute"; "required": false; "isSignal": true; }; "editRoute": { "alias": "editRoute"; "required": false; "isSignal": true; }; "deleteConfirmField": { "alias": "deleteConfirmField"; "required": false; "isSignal": true; }; "idField": { "alias": "idField"; "required": false; "isSignal": true; }; "canEdit": { "alias": "canEdit"; "required": false; "isSignal": true; }; "canDelete": { "alias": "canDelete"; "required": false; "isSignal": true; }; }, { "onCreate": "onCreate"; "onLazyLoad": "onLazyLoad"; "onSearch": "onSearch"; }, ["columnTemplates"], never, true, never>;
1147
+ }
1148
+
1149
+ declare class FileSelectorDialogComponent {
1150
+ private readonly destroyRef;
1151
+ private readonly translateAdapter;
1152
+ readonly fileProvider: _flusys_ng_shared.IFileProvider | null;
1153
+ private abortController;
1154
+ private searchDebounceTimer;
1155
+ readonly header: _angular_core.InputSignal<string | undefined>;
1156
+ readonly acceptTypes: _angular_core.InputSignal<string[]>;
1157
+ readonly multiple: _angular_core.InputSignal<boolean>;
1158
+ readonly dialogHeader: _angular_core.Signal<string>;
1159
+ readonly maxSelection: _angular_core.InputSignal<number>;
1160
+ readonly pageSize: _angular_core.InputSignal<number>;
1161
+ readonly folderId: _angular_core.InputSignal<string | undefined>;
1162
+ readonly withUploader: _angular_core.InputSignal<boolean>;
1163
+ readonly visible: _angular_core.ModelSignal<boolean>;
1164
+ readonly fileSelected: _angular_core.OutputEmitterRef<IFileBasicInfo>;
1165
+ readonly filesSelected: _angular_core.OutputEmitterRef<IFileBasicInfo[]>;
1166
+ readonly closed: _angular_core.OutputEmitterRef<void>;
1167
+ readonly onError: _angular_core.OutputEmitterRef<Error>;
1168
+ readonly isLoading: _angular_core.WritableSignal<boolean>;
1169
+ readonly files: _angular_core.WritableSignal<IFileBasicInfo[]>;
1170
+ readonly selectedFiles: _angular_core.WritableSignal<IFileBasicInfo[]>;
1171
+ readonly total: _angular_core.WritableSignal<number | undefined>;
1172
+ readonly pagination: _angular_core.WritableSignal<IPagination>;
1173
+ readonly searchTerm: _angular_core.WritableSignal<string>;
1174
+ readonly folders: _angular_core.WritableSignal<IFolderBasicInfo[]>;
1175
+ readonly selectedFolderId: _angular_core.WritableSignal<string | null>;
1176
+ readonly foldersLoading: _angular_core.WritableSignal<boolean>;
1177
+ readonly foldersPagination: _angular_core.WritableSignal<IPagination>;
1178
+ readonly foldersTotal: _angular_core.WritableSignal<number | undefined>;
1179
+ readonly storageConfigs: _angular_core.WritableSignal<IStorageConfigBasicInfo[]>;
1180
+ readonly selectedStorageConfigId: _angular_core.WritableSignal<string | null>;
1181
+ readonly storageConfigsLoading: _angular_core.WritableSignal<boolean>;
1182
+ readonly storageConfigsPagination: _angular_core.WritableSignal<IPagination>;
1183
+ readonly storageConfigsTotal: _angular_core.WritableSignal<number | undefined>;
1184
+ readonly effectiveStorageConfigId: _angular_core.Signal<string | undefined>;
1185
+ readonly uploadFileFn: (file: File, options?: IFileUploadOptions) => rxjs.Observable<_flusys_ng_shared.ISingleResponse<IUploadedFile>>;
1186
+ readonly uploadMultipleFilesFn: ((files: File[], options?: IFileUploadOptions) => rxjs.Observable<_flusys_ng_shared.ISingleResponse<IUploadedFile[]>>) | undefined;
1187
+ constructor();
1188
+ onSearchChange(value: string): void;
1189
+ onScroll(event: Event): void;
1190
+ toggleSelection(file: IFileBasicInfo): void;
1191
+ isSelected(file: IFileBasicInfo): boolean;
1192
+ isFileAllowed(file: IFileBasicInfo): boolean;
1193
+ isImage(file: IFileBasicInfo): boolean;
1194
+ getFileIcon(file: IFileBasicInfo): string;
1195
+ formatSize(size: string): string;
1196
+ onCancel(): void;
1197
+ onConfirm(): void;
1198
+ onDialogHide(): void;
1199
+ onFolderChange(folderId: string | null): void;
1200
+ onFolderSearch(event: {
1201
+ filter: string;
1202
+ }): void;
1203
+ loadFolders(search?: string): Promise<void>;
1204
+ onStorageConfigChange(configId: string | null): void;
1205
+ onStorageConfigSearch(event: {
1206
+ filter: string;
1207
+ }): void;
1208
+ loadStorageConfigs(search?: string): Promise<void>;
1209
+ onFileUploaded(uploadedFile: IUploadedFile): void;
1210
+ private resetState;
1211
+ private fetchFiles;
1212
+ private t;
1213
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FileSelectorDialogComponent, never>;
1214
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FileSelectorDialogComponent, "lib-file-selector-dialog", never, { "header": { "alias": "header"; "required": false; "isSignal": true; }; "acceptTypes": { "alias": "acceptTypes"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "maxSelection": { "alias": "maxSelection"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "folderId": { "alias": "folderId"; "required": false; "isSignal": true; }; "withUploader": { "alias": "withUploader"; "required": false; "isSignal": true; }; "visible": { "alias": "visible"; "required": false; "isSignal": true; }; }, { "visible": "visibleChange"; "fileSelected": "fileSelected"; "filesSelected": "filesSelected"; "closed": "closed"; "onError": "onError"; }, never, never, true, never>;
1215
+ }
1216
+
1217
+ declare class FileUploaderComponent {
1218
+ private readonly messageService;
1219
+ private readonly translateAdapter;
1220
+ private readonly fileProvider;
1221
+ readonly uploadFile: _angular_core.InputSignal<UploadFileFn | undefined>;
1222
+ readonly uploadMultipleFiles: _angular_core.InputSignal<UploadMultipleFilesFn | undefined>;
1223
+ readonly hasUploadCapability: _angular_core.Signal<boolean>;
1224
+ private getUploadFn;
1225
+ private getUploadMultipleFn;
1226
+ readonly acceptTypes: _angular_core.InputSignal<string[]>;
1227
+ readonly multiple: _angular_core.InputSignal<boolean>;
1228
+ readonly maxFiles: _angular_core.InputSignal<number>;
1229
+ readonly maxSizeMb: _angular_core.InputSignal<number>;
1230
+ readonly uploadOptions: _angular_core.InputSignal<IFileUploadOptions>;
1231
+ readonly disabled: _angular_core.InputSignal<boolean>;
1232
+ readonly showPreview: _angular_core.InputSignal<boolean>;
1233
+ readonly autoUpload: _angular_core.InputSignal<boolean>;
1234
+ readonly fileUploaded: _angular_core.OutputEmitterRef<IUploadedFile>;
1235
+ readonly filesUploaded: _angular_core.OutputEmitterRef<IUploadedFile[]>;
1236
+ readonly onError: _angular_core.OutputEmitterRef<Error>;
1237
+ readonly fileSelected: _angular_core.OutputEmitterRef<File[]>;
1238
+ readonly isUploading: _angular_core.WritableSignal<boolean>;
1239
+ readonly isDragOver: _angular_core.WritableSignal<boolean>;
1240
+ readonly uploadProgress: _angular_core.WritableSignal<number>;
1241
+ readonly uploadingFileName: _angular_core.WritableSignal<string>;
1242
+ readonly selectedFiles: _angular_core.WritableSignal<File[]>;
1243
+ readonly acceptString: _angular_core.Signal<string>;
1244
+ readonly acceptTypesDisplay: _angular_core.Signal<string>;
1245
+ onDragOver(event: DragEvent): void;
1246
+ onDragLeave(event: DragEvent): void;
1247
+ onDrop(event: DragEvent): void;
1248
+ onFileSelected(event: Event): void;
1249
+ private handleFiles;
1250
+ removeFile(file: File): void;
1251
+ uploadFiles(files?: File[]): Promise<void>;
1252
+ private uploadBatch;
1253
+ private uploadSequential;
1254
+ getFileIcon(file: File): string;
1255
+ formatSize(bytes: number): string;
1256
+ private t;
1257
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FileUploaderComponent, never>;
1258
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FileUploaderComponent, "lib-file-uploader", never, { "uploadFile": { "alias": "uploadFile"; "required": false; "isSignal": true; }; "uploadMultipleFiles": { "alias": "uploadMultipleFiles"; "required": false; "isSignal": true; }; "acceptTypes": { "alias": "acceptTypes"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "maxFiles": { "alias": "maxFiles"; "required": false; "isSignal": true; }; "maxSizeMb": { "alias": "maxSizeMb"; "required": false; "isSignal": true; }; "uploadOptions": { "alias": "uploadOptions"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "showPreview": { "alias": "showPreview"; "required": false; "isSignal": true; }; "autoUpload": { "alias": "autoUpload"; "required": false; "isSignal": true; }; }, { "fileUploaded": "fileUploaded"; "filesUploaded": "filesUploaded"; "onError": "onError"; "fileSelected": "fileSelected"; }, never, never, true, never>;
1229
1259
  }
1230
1260
 
1231
1261
  declare class IconComponent {
@@ -1236,77 +1266,13 @@ declare class IconComponent {
1236
1266
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<IconComponent, "lib-icon", never, { "icon": { "alias": "icon"; "required": true; "isSignal": true; }; "iconType": { "alias": "iconType"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1237
1267
  }
1238
1268
 
1239
- /**
1240
- * Base class for form controls that support ALL Angular form patterns:
1241
- *
1242
- * 1. **Template-driven forms:** `[(value)]="mySignal"` or `[(ngModel)]="myValue"`
1243
- * 2. **Reactive forms:** `[formControl]="ctrl"` or `formControlName="field"`
1244
- * 3. **Signal forms (Angular 21+):** `[formField]="formTree.field"`
1245
- *
1246
- * Implements both `ControlValueAccessor` (reactive forms) and `FormValueControl` (signal forms).
1247
- *
1248
- * @example
1249
- * ```typescript
1250
- * @Component({
1251
- * providers: [provideValueAccessor(MySelectComponent)]
1252
- * })
1253
- * export class MySelectComponent extends BaseFormControl<string | null> {
1254
- * override readonly value = model<string | null>(null);
1255
- *
1256
- * constructor() {
1257
- * super();
1258
- * this.initializeFormControl();
1259
- * }
1260
- * }
1261
- *
1262
- * // Usage:
1263
- * // Template-driven: <my-select [(value)]="selectedId" />
1264
- * // Reactive forms: <my-select [formControl]="myControl" />
1265
- * // Signal forms: <my-select [formField]="formTree.myField" />
1266
- * ```
1267
- */
1268
- declare abstract class BaseFormControl<T> implements ControlValueAccessor, FormValueControl<T> {
1269
- protected readonly injector: Injector;
1270
- /**
1271
- * The value model - must be overridden in subclass with model<T>().
1272
- * This property satisfies both:
1273
- * - FormValueControl interface (signal forms)
1274
- * - Internal state for ControlValueAccessor (reactive forms)
1275
- */
1276
- abstract readonly value: ReturnType<typeof model<T>>;
1277
- /**
1278
- * Disabled state model - bound to form control disabled state.
1279
- * Using model() to satisfy FormValueControl interface requirements.
1280
- */
1281
- readonly disabled: _angular_core.ModelSignal<boolean>;
1282
- /**
1283
- * Touched state model - for validation styling.
1284
- * Using model() to satisfy FormValueControl interface requirements.
1285
- */
1286
- readonly touched: _angular_core.ModelSignal<boolean>;
1287
- private onChange;
1288
- private onTouched;
1289
- private isWritingValue;
1290
- /**
1291
- * Initialize the form control synchronization for ControlValueAccessor.
1292
- * Must be called in the subclass constructor after super().
1293
- *
1294
- * Note: For signal forms ([formField]), this is not needed as
1295
- * the FormField directive binds directly to the value model.
1296
- */
1297
- protected initializeFormControl(): void;
1298
- /** ControlValueAccessor: Write value from form control to signal */
1299
- writeValue(value: T): void;
1300
- /** ControlValueAccessor: Register change callback */
1301
- registerOnChange(fn: (value: T) => void): void;
1302
- /** ControlValueAccessor: Register touched callback */
1303
- registerOnTouched(fn: () => void): void;
1304
- /** ControlValueAccessor: Set disabled state from form control */
1305
- setDisabledState(isDisabled: boolean): void;
1306
- /** Mark the control as touched (call on blur or panel close) */
1307
- protected markAsTouched(): void;
1308
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseFormControl<any>, never>;
1309
- 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>;
1269
+ declare class InlineSvgComponent {
1270
+ readonly src: _angular_core.InputSignal<string>;
1271
+ private readonly http;
1272
+ private readonly sanitizer;
1273
+ readonly svg: _angular_core.ResourceRef<_angular_platform_browser.SafeHtml | undefined>;
1274
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<InlineSvgComponent, never>;
1275
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<InlineSvgComponent, "inline-svg", never, { "src": { "alias": "src"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
1310
1276
  }
1311
1277
 
1312
1278
  /**
@@ -1317,38 +1283,45 @@ declare abstract class BaseFormControl<T> implements ControlValueAccessor, FormV
1317
1283
  * - Reactive forms: `[formControl]="ctrl"` or `formControlName="field"`
1318
1284
  * - Signal forms: `[formField]="formTree.field"`
1319
1285
  */
1320
- declare class LazyMultiSelectComponent extends BaseFormControl<string[] | null> {
1286
+ declare class LazyMultiSelectComponent extends BaseFormControl<string[] | null> implements OnDestroy {
1287
+ private readonly document;
1288
+ private readonly appRef;
1289
+ private readonly translateAdapter;
1290
+ private readonly onDocumentClickBound;
1291
+ readonly pSelectRef: _angular_core.Signal<ElementRef<HTMLDivElement>>;
1292
+ readonly overlayTemplate: _angular_core.Signal<TemplateRef<unknown>>;
1293
+ private overlayViewRef;
1321
1294
  readonly placeHolder: _angular_core.InputSignal<string>;
1295
+ readonly showClear: _angular_core.InputSignal<boolean>;
1296
+ readonly displayPlaceholder: _angular_core.Signal<string>;
1322
1297
  readonly isEditMode: _angular_core.InputSignal<boolean>;
1323
1298
  readonly isLoading: _angular_core.InputSignal<boolean>;
1324
1299
  readonly total: _angular_core.InputSignal<number | undefined>;
1325
1300
  readonly pagination: _angular_core.InputSignal<IPagination>;
1326
1301
  readonly selectDataList: _angular_core.InputSignal<IDropDown[]>;
1327
- /** Two-way bound value using model() for signal forms compatibility */
1328
1302
  readonly value: _angular_core.ModelSignal<string[] | null>;
1329
1303
  readonly onSearch: _angular_core.OutputEmitterRef<string>;
1330
1304
  readonly onPagination: _angular_core.OutputEmitterRef<IPagination>;
1331
1305
  readonly searchTerm: _angular_core.WritableSignal<string>;
1332
- /** Computed: Display text for selected values (replaces getSelectedValue method) */
1306
+ readonly openOptions: _angular_core.WritableSignal<boolean>;
1333
1307
  readonly selectedValueDisplay: _angular_core.Signal<string>;
1334
- /** Computed: Whether all items are selected (replaces isSelectAll signal) */
1308
+ readonly hasSelectedValues: _angular_core.Signal<boolean>;
1335
1309
  readonly isSelectAll: _angular_core.Signal<boolean>;
1336
1310
  constructor();
1337
- private readonly onScrollBound;
1338
- readonly multiScrollContainer: _angular_core.Signal<ElementRef<HTMLDivElement>>;
1311
+ ngOnDestroy(): void;
1339
1312
  onScroll(event: Event): void;
1340
- readonly pSelectRef: _angular_core.Signal<ElementRef<HTMLDivElement>>;
1341
- openOptions: _angular_core.WritableSignal<boolean>;
1342
- onSelectClick(event: Event): void;
1313
+ onSelectClick(): void;
1314
+ private openOverlay;
1315
+ private closeOverlay;
1343
1316
  onOverlayClick(event: Event): void;
1344
- handleDocumentClick(event: MouseEvent): void;
1345
- isSelected(data: IDropDown): boolean | undefined;
1346
- key(option: IDropDown): string;
1317
+ private handleDocumentClick;
1318
+ isSelected(data: IDropDown): boolean;
1347
1319
  selectValue(event: CheckboxChangeEvent, option: IDropDown): void;
1348
1320
  changeSelectAll(event: CheckboxChangeEvent): void;
1349
1321
  clear(event: Event): void;
1322
+ private t;
1350
1323
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<LazyMultiSelectComponent, never>;
1351
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<LazyMultiSelectComponent, "lib-lazy-multi-select", never, { "placeHolder": { "alias": "placeHolder"; "required": false; "isSignal": true; }; "isEditMode": { "alias": "isEditMode"; "required": true; "isSignal": true; }; "isLoading": { "alias": "isLoading"; "required": true; "isSignal": true; }; "total": { "alias": "total"; "required": true; "isSignal": true; }; "pagination": { "alias": "pagination"; "required": true; "isSignal": true; }; "selectDataList": { "alias": "selectDataList"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "onSearch": "onSearch"; "onPagination": "onPagination"; }, never, never, true, never>;
1324
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<LazyMultiSelectComponent, "lib-lazy-multi-select", never, { "placeHolder": { "alias": "placeHolder"; "required": false; "isSignal": true; }; "showClear": { "alias": "showClear"; "required": false; "isSignal": true; }; "isEditMode": { "alias": "isEditMode"; "required": true; "isSignal": true; }; "isLoading": { "alias": "isLoading"; "required": true; "isSignal": true; }; "total": { "alias": "total"; "required": true; "isSignal": true; }; "pagination": { "alias": "pagination"; "required": true; "isSignal": true; }; "selectDataList": { "alias": "selectDataList"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "onSearch": "onSearch"; "onPagination": "onPagination"; }, never, never, true, never>;
1352
1325
  }
1353
1326
 
1354
1327
  /**
@@ -1360,7 +1333,15 @@ declare class LazyMultiSelectComponent extends BaseFormControl<string[] | null>
1360
1333
  * - Signal forms: `[formField]="formTree.field"`
1361
1334
  */
1362
1335
  declare class LazySelectComponent extends BaseFormControl<string | null> {
1336
+ private readonly destroyRef;
1337
+ private readonly translateAdapter;
1338
+ private readonly onScrollBound;
1339
+ private scrollTargetEl;
1340
+ private isDestroyed;
1341
+ readonly scrollContainer: _angular_core.Signal<ElementRef<HTMLDivElement>>;
1363
1342
  readonly placeHolder: _angular_core.InputSignal<string>;
1343
+ readonly showClear: _angular_core.InputSignal<boolean>;
1344
+ readonly displayPlaceholder: _angular_core.Signal<string>;
1364
1345
  readonly optionLabel: _angular_core.InputSignal<string>;
1365
1346
  readonly optionValue: _angular_core.InputSignal<string>;
1366
1347
  readonly isEditMode: _angular_core.InputSignal<boolean>;
@@ -1368,62 +1349,52 @@ declare class LazySelectComponent extends BaseFormControl<string | null> {
1368
1349
  readonly total: _angular_core.InputSignal<number | undefined>;
1369
1350
  readonly pagination: _angular_core.InputSignal<IPagination>;
1370
1351
  readonly selectDataList: _angular_core.InputSignal<IDropDown[]>;
1371
- /** Two-way bound value using model() for signal forms compatibility */
1372
1352
  readonly value: _angular_core.ModelSignal<string | null>;
1373
1353
  readonly onSearch: _angular_core.OutputEmitterRef<string>;
1374
1354
  readonly onPagination: _angular_core.OutputEmitterRef<IPagination>;
1375
1355
  readonly searchTerm: _angular_core.WritableSignal<string>;
1356
+ readonly isPanelShow: _angular_core.WritableSignal<boolean>;
1376
1357
  constructor();
1377
- isPanelShow: _angular_core.WritableSignal<boolean>;
1378
- scrollTargetEl: HTMLElement | null;
1379
- private readonly onScrollBound;
1380
- readonly scrollContainer: _angular_core.Signal<ElementRef<HTMLDivElement>>;
1381
1358
  onScroll(event: Event): void;
1382
1359
  showPanel(): void;
1383
1360
  onBlur(): void;
1361
+ private t;
1384
1362
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<LazySelectComponent, never>;
1385
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<LazySelectComponent, "lib-lazy-select", never, { "placeHolder": { "alias": "placeHolder"; "required": false; "isSignal": true; }; "optionLabel": { "alias": "optionLabel"; "required": true; "isSignal": true; }; "optionValue": { "alias": "optionValue"; "required": true; "isSignal": true; }; "isEditMode": { "alias": "isEditMode"; "required": true; "isSignal": true; }; "isLoading": { "alias": "isLoading"; "required": true; "isSignal": true; }; "total": { "alias": "total"; "required": true; "isSignal": true; }; "pagination": { "alias": "pagination"; "required": true; "isSignal": true; }; "selectDataList": { "alias": "selectDataList"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "onSearch": "onSearch"; "onPagination": "onPagination"; }, never, never, true, never>;
1363
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<LazySelectComponent, "lib-lazy-select", never, { "placeHolder": { "alias": "placeHolder"; "required": false; "isSignal": true; }; "showClear": { "alias": "showClear"; "required": false; "isSignal": true; }; "optionLabel": { "alias": "optionLabel"; "required": true; "isSignal": true; }; "optionValue": { "alias": "optionValue"; "required": true; "isSignal": true; }; "isEditMode": { "alias": "isEditMode"; "required": true; "isSignal": true; }; "isLoading": { "alias": "isLoading"; "required": true; "isSignal": true; }; "total": { "alias": "total"; "required": true; "isSignal": true; }; "pagination": { "alias": "pagination"; "required": true; "isSignal": true; }; "selectDataList": { "alias": "selectDataList"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "onSearch": "onSearch"; "onPagination": "onPagination"; }, never, never, true, never>;
1364
+ }
1365
+
1366
+ interface RouterTabItem {
1367
+ id: string | number;
1368
+ label: string;
1369
+ icon?: string;
1370
+ route: string | unknown[];
1371
+ routerLinkActiveExact?: boolean;
1372
+ }
1373
+ declare class RouterTabsComponent {
1374
+ readonly tabs: _angular_core.InputSignal<RouterTabItem[]>;
1375
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<RouterTabsComponent, never>;
1376
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<RouterTabsComponent, "lib-router-tabs", never, { "tabs": { "alias": "tabs"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1386
1377
  }
1387
1378
 
1388
1379
  /**
1389
- * User Select Component - Single user selection with lazy loading.
1390
- *
1391
- * Uses USER_PROVIDER internally by default, or accepts custom `loadUsers` function.
1392
- *
1393
- * Features:
1394
- * - Search with debouncing (handled by lazy-select)
1395
- * - Infinite scroll pagination
1396
- * - Filter active users by default (configurable)
1397
- * - Supports additional filters via `additionalFilters` input
1398
- *
1399
- * @example
1400
- * ```html
1401
- * <!-- Simple usage - uses USER_PROVIDER internally -->
1402
- * <lib-user-select
1403
- * [(value)]="selectedUserId"
1404
- * [isEditMode]="true"
1405
- * />
1380
+ * Base class for user selection components.
1381
+ * Provides shared user loading, pagination, and search functionality.
1406
1382
  *
1407
- * <!-- With custom loadUsers function -->
1408
- * <lib-user-select
1409
- * [(value)]="selectedUserId"
1410
- * [isEditMode]="true"
1411
- * [loadUsers]="customLoadUsers"
1412
- * />
1413
- * ```
1383
+ * Subclasses must implement:
1384
+ * - `setupValueEffect()` to track value changes and emit selection events
1414
1385
  */
1415
- declare class UserSelectComponent {
1416
- private readonly destroyRef;
1417
- private readonly userProvider;
1418
- private abortController;
1386
+ declare abstract class BaseUserSelectComponent {
1387
+ protected readonly destroyRef: DestroyRef;
1388
+ protected readonly injector: Injector;
1389
+ protected readonly userProvider: IUserProvider;
1390
+ protected readonly translateAdapter: TranslateService;
1391
+ protected abortController: AbortController | null;
1419
1392
  readonly loadUsers: _angular_core.InputSignal<LoadUsersFn | undefined>;
1420
1393
  readonly placeHolder: _angular_core.InputSignal<string>;
1421
1394
  readonly isEditMode: _angular_core.InputSignal<boolean>;
1422
1395
  readonly filterActive: _angular_core.InputSignal<boolean>;
1423
1396
  readonly additionalFilters: _angular_core.InputSignal<Record<string, unknown>>;
1424
1397
  readonly pageSize: _angular_core.InputSignal<number>;
1425
- readonly value: _angular_core.ModelSignal<string | null>;
1426
- readonly userSelected: _angular_core.OutputEmitterRef<IUserBasicInfo | null>;
1427
1398
  readonly onError: _angular_core.OutputEmitterRef<Error>;
1428
1399
  readonly isLoading: _angular_core.WritableSignal<boolean>;
1429
1400
  readonly users: _angular_core.WritableSignal<IUserBasicInfo[]>;
@@ -1431,16 +1402,20 @@ declare class UserSelectComponent {
1431
1402
  readonly pagination: _angular_core.WritableSignal<IPagination>;
1432
1403
  readonly searchTerm: _angular_core.WritableSignal<string>;
1433
1404
  readonly dropdownUsers: _angular_core.Signal<IDropDown[]>;
1405
+ readonly displayPlaceholder: _angular_core.Signal<string>;
1434
1406
  constructor();
1407
+ /** Setup effect to track value changes and emit selection events */
1408
+ protected abstract setupValueEffect(): void;
1435
1409
  handleSearch(search: string): void;
1436
1410
  handlePagination(pagination: IPagination): void;
1437
- private fetchUsers;
1438
- /** Load users from USER_PROVIDER with active filter */
1439
- private loadUsersFromProvider;
1440
1411
  /** Reload users (useful when filters change externally) */
1441
1412
  reload(): void;
1442
- 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>;
1413
+ protected fetchUsers(append?: boolean): Promise<void>;
1414
+ /** Load users from USER_PROVIDER with active filter */
1415
+ private loadUsersFromProvider;
1416
+ protected t(key: string, variables?: Record<string, string | number>): string;
1417
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseUserSelectComponent, never>;
1418
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<BaseUserSelectComponent, never, never, { "loadUsers": { "alias": "loadUsers"; "required": false; "isSignal": true; }; "placeHolder": { "alias": "placeHolder"; "required": false; "isSignal": true; }; "isEditMode": { "alias": "isEditMode"; "required": true; "isSignal": true; }; "filterActive": { "alias": "filterActive"; "required": false; "isSignal": true; }; "additionalFilters": { "alias": "additionalFilters"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; }, { "onError": "onError"; }, never, never, true, never>;
1444
1419
  }
1445
1420
 
1446
1421
  /**
@@ -1471,195 +1446,49 @@ declare class UserSelectComponent {
1471
1446
  * />
1472
1447
  * ```
1473
1448
  */
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>;
1449
+ declare class UserMultiSelectComponent extends BaseUserSelectComponent {
1450
+ readonly showClear: _angular_core.InputSignal<boolean>;
1484
1451
  readonly value: _angular_core.ModelSignal<string[] | null>;
1485
1452
  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;
1453
+ protected setupValueEffect(): void;
1501
1454
  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>;
1455
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<UserMultiSelectComponent, "lib-user-multi-select", never, { "showClear": { "alias": "showClear"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "usersSelected": "usersSelected"; }, never, never, true, never>;
1503
1456
  }
1504
1457
 
1505
1458
  /**
1506
- * File Uploader Component - Drag & drop file upload with type filtering.
1459
+ * User Select Component - Single user selection with lazy loading.
1507
1460
  *
1508
- * Pass your own `uploadFile` function - works with any storage API.
1461
+ * Uses USER_PROVIDER internally by default, or accepts custom `loadUsers` function.
1509
1462
  *
1510
1463
  * 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
1464
+ * - Search with debouncing (handled by lazy-select)
1465
+ * - Infinite scroll pagination
1466
+ * - Filter active users by default (configurable)
1467
+ * - Supports additional filters via `additionalFilters` input
1516
1468
  *
1517
1469
  * @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
1470
  * ```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)"
1471
+ * <!-- Simple usage - uses USER_PROVIDER internally -->
1472
+ * <lib-user-select
1473
+ * [(value)]="selectedUserId"
1474
+ * [isEditMode]="true"
1542
1475
  * />
1543
- * ```
1544
- */
1545
- declare class FileUploaderComponent {
1546
- private readonly messageService;
1547
- readonly uploadFile: _angular_core.InputSignal<UploadFileFn>;
1548
- readonly acceptTypes: _angular_core.InputSignal<string[]>;
1549
- readonly multiple: _angular_core.InputSignal<boolean>;
1550
- readonly maxFiles: _angular_core.InputSignal<number>;
1551
- readonly maxSizeMb: _angular_core.InputSignal<number>;
1552
- readonly uploadOptions: _angular_core.InputSignal<IFileUploadOptions>;
1553
- readonly disabled: _angular_core.InputSignal<boolean>;
1554
- readonly showPreview: _angular_core.InputSignal<boolean>;
1555
- readonly autoUpload: _angular_core.InputSignal<boolean>;
1556
- readonly fileUploaded: _angular_core.OutputEmitterRef<IUploadedFile>;
1557
- readonly filesUploaded: _angular_core.OutputEmitterRef<IUploadedFile[]>;
1558
- readonly onError: _angular_core.OutputEmitterRef<Error>;
1559
- readonly fileSelected: _angular_core.OutputEmitterRef<File[]>;
1560
- readonly isUploading: _angular_core.WritableSignal<boolean>;
1561
- readonly isDragOver: _angular_core.WritableSignal<boolean>;
1562
- readonly uploadProgress: _angular_core.WritableSignal<number>;
1563
- readonly uploadingFileName: _angular_core.WritableSignal<string>;
1564
- readonly selectedFiles: _angular_core.WritableSignal<File[]>;
1565
- readonly acceptString: _angular_core.Signal<string>;
1566
- readonly acceptTypesDisplay: _angular_core.Signal<string>;
1567
- onDragOver(event: DragEvent): void;
1568
- onDragLeave(event: DragEvent): void;
1569
- onDrop(event: DragEvent): void;
1570
- onFileSelected(event: Event): void;
1571
- private handleFiles;
1572
- removeFile(file: File): void;
1573
- uploadFiles(files?: File[]): Promise<void>;
1574
- getFileIcon(file: File): string;
1575
- formatSize(bytes: number): string;
1576
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<FileUploaderComponent, never>;
1577
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<FileUploaderComponent, "lib-file-uploader", never, { "uploadFile": { "alias": "uploadFile"; "required": true; "isSignal": true; }; "acceptTypes": { "alias": "acceptTypes"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "maxFiles": { "alias": "maxFiles"; "required": false; "isSignal": true; }; "maxSizeMb": { "alias": "maxSizeMb"; "required": false; "isSignal": true; }; "uploadOptions": { "alias": "uploadOptions"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "showPreview": { "alias": "showPreview"; "required": false; "isSignal": true; }; "autoUpload": { "alias": "autoUpload"; "required": false; "isSignal": true; }; }, { "fileUploaded": "fileUploaded"; "filesUploaded": "filesUploaded"; "onError": "onError"; "fileSelected": "fileSelected"; }, never, never, true, never>;
1578
- }
1579
-
1580
- /**
1581
- * File Selector Dialog - Browse and select existing files with filtering.
1582
- *
1583
- * Pass your own `loadFiles` function - works with any storage API.
1584
- *
1585
- * Features:
1586
- * - Search with debouncing
1587
- * - File type filtering
1588
- * - Infinite scroll pagination
1589
- * - Single or multiple selection
1590
- * - File preview with icons
1591
- *
1592
- * @example
1593
- * ```typescript
1594
- * // In component
1595
- * readonly fileService = inject(FileManagerApiService);
1596
- *
1597
- * readonly loadFiles: LoadFilesFn = (filter) =>
1598
- * this.fileService.getAll(filter.search, {
1599
- * pagination: { currentPage: filter.page, pageSize: filter.pageSize },
1600
- * filter: { contentTypes: filter.contentTypes },
1601
- * }).pipe(
1602
- * map(res => ({
1603
- * ...res,
1604
- * data: res.data?.map(f => ({
1605
- * id: f.id,
1606
- * name: f.name,
1607
- * contentType: f.contentType,
1608
- * size: f.size,
1609
- * url: f.url
1610
- * }))
1611
- * }))
1612
- * );
1613
- * ```
1614
1476
  *
1615
- * ```html
1616
- * <lib-file-selector-dialog
1617
- * [(visible)]="showFileSelector"
1618
- * [loadFiles]="loadFiles"
1619
- * [acceptTypes]="['image/*']"
1620
- * [multiple]="false"
1621
- * (fileSelected)="onFileSelected($event)"
1477
+ * <!-- With custom loadUsers function -->
1478
+ * <lib-user-select
1479
+ * [(value)]="selectedUserId"
1480
+ * [isEditMode]="true"
1481
+ * [loadUsers]="customLoadUsers"
1622
1482
  * />
1623
1483
  * ```
1624
1484
  */
1625
- declare class FileSelectorDialogComponent {
1626
- private readonly destroyRef;
1627
- private abortController;
1628
- private searchDebounceTimer;
1629
- readonly loadFiles: _angular_core.InputSignal<LoadFilesFn>;
1630
- readonly header: _angular_core.InputSignal<string>;
1631
- readonly acceptTypes: _angular_core.InputSignal<string[]>;
1632
- readonly multiple: _angular_core.InputSignal<boolean>;
1633
- readonly maxSelection: _angular_core.InputSignal<number>;
1634
- readonly pageSize: _angular_core.InputSignal<number>;
1635
- readonly visible: _angular_core.ModelSignal<boolean>;
1636
- readonly fileSelected: _angular_core.OutputEmitterRef<IFileBasicInfo>;
1637
- readonly filesSelected: _angular_core.OutputEmitterRef<IFileBasicInfo[]>;
1638
- readonly closed: _angular_core.OutputEmitterRef<void>;
1639
- readonly onError: _angular_core.OutputEmitterRef<Error>;
1640
- readonly isLoading: _angular_core.WritableSignal<boolean>;
1641
- readonly files: _angular_core.WritableSignal<IFileBasicInfo[]>;
1642
- readonly selectedFiles: _angular_core.WritableSignal<IFileBasicInfo[]>;
1643
- readonly total: _angular_core.WritableSignal<number | undefined>;
1644
- readonly pagination: _angular_core.WritableSignal<IPagination>;
1645
- readonly searchTerm: _angular_core.WritableSignal<string>;
1646
- readonly acceptString: _angular_core.Signal<string>;
1647
- constructor();
1648
- onSearchChange(value: string): void;
1649
- onScroll(event: Event): void;
1650
- toggleSelection(file: IFileBasicInfo): void;
1651
- isSelected(file: IFileBasicInfo): boolean;
1652
- isFileAllowed(file: IFileBasicInfo): boolean;
1653
- isImage(file: IFileBasicInfo): boolean;
1654
- getFileIcon(file: IFileBasicInfo): string;
1655
- formatSize(size: string): string;
1656
- onCancel(): void;
1657
- onConfirm(): void;
1658
- onDialogHide(): void;
1659
- private resetState;
1660
- private fetchFiles;
1661
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<FileSelectorDialogComponent, never>;
1662
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<FileSelectorDialogComponent, "lib-file-selector-dialog", never, { "loadFiles": { "alias": "loadFiles"; "required": true; "isSignal": true; }; "header": { "alias": "header"; "required": false; "isSignal": true; }; "acceptTypes": { "alias": "acceptTypes"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "maxSelection": { "alias": "maxSelection"; "required": false; "isSignal": true; }; "pageSize": { "alias": "pageSize"; "required": false; "isSignal": true; }; "visible": { "alias": "visible"; "required": false; "isSignal": true; }; }, { "visible": "visibleChange"; "fileSelected": "fileSelected"; "filesSelected": "filesSelected"; "closed": "closed"; "onError": "onError"; }, never, never, true, never>;
1485
+ declare class UserSelectComponent extends BaseUserSelectComponent {
1486
+ readonly showClear: _angular_core.InputSignal<boolean>;
1487
+ readonly value: _angular_core.ModelSignal<string | null>;
1488
+ readonly userSelected: _angular_core.OutputEmitterRef<IUserBasicInfo | null>;
1489
+ protected setupValueEffect(): void;
1490
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<UserSelectComponent, never>;
1491
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<UserSelectComponent, "lib-user-select", never, { "showClear": { "alias": "showClear"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "userSelected": "userSelected"; }, never, never, true, never>;
1663
1492
  }
1664
1493
 
1665
1494
  /**
@@ -1716,86 +1545,66 @@ declare const AUTH_STATE_PROVIDER: InjectionToken<IAuthStateProvider>;
1716
1545
  */
1717
1546
  declare const PROFILE_PERMISSION_PROVIDER: InjectionToken<IProfilePermissionProvider>;
1718
1547
  /**
1719
- * Profile Upload Provider Token
1720
- *
1721
- * Provides file upload functionality for profile pictures.
1722
- * Optional - if not configured or storage not enabled, upload section is hidden.
1723
- * Use with `inject(PROFILE_UPLOAD_PROVIDER, { optional: true })`.
1724
- */
1725
- declare const PROFILE_UPLOAD_PROVIDER: InjectionToken<IProfileUploadProvider>;
1726
- /**
1727
- * User List Provider Token
1548
+ * File Provider Token
1728
1549
  *
1729
- * Provides extra actions, columns, and data enrichment for user list.
1730
- * Optional - if not configured, default user list behavior is used.
1731
- * Use with `inject(USER_LIST_PROVIDER, { optional: true })`.
1550
+ * Provides file loading and upload functionality for file selectors.
1551
+ * Optional - if not configured, file selector requires loadFiles/uploadFile inputs.
1552
+ * Use with `inject(FILE_PROVIDER, { optional: true })`.
1732
1553
  *
1733
1554
  * @example
1734
1555
  * // In app.config.ts
1735
1556
  * providers: [
1736
- * { provide: USER_LIST_PROVIDER, useClass: MyUserListProvider },
1557
+ * { provide: FILE_PROVIDER, useClass: StorageFileProvider },
1737
1558
  * ]
1738
1559
  */
1739
- declare const USER_LIST_PROVIDER: InjectionToken<IUserListProvider<IUserListItem>>;
1560
+ declare const FILE_PROVIDER: InjectionToken<IFileProvider>;
1740
1561
 
1741
1562
  /**
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
1563
+ * Permission Guard - Single permission or ILogicNode check.
1752
1564
  *
1753
1565
  * @example
1754
1566
  * ```typescript
1755
- * // Simple permission check
1756
1567
  * { 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')] }
1568
+ * { path: 'admin', canActivate: [permissionGuard(logicNode, '/access-denied')] }
1771
1569
  * ```
1772
1570
  */
1773
1571
  declare function permissionGuard(permission: string | ILogicNode, redirectTo?: string): CanActivateFn;
1774
1572
  /**
1775
- * Any Permission Guard (OR logic)
1776
- *
1777
- * Allows access if user has ANY of the specified permissions.
1573
+ * Any Permission Guard (OR logic) - Access if user has ANY permission.
1778
1574
  *
1779
1575
  * @example
1780
1576
  * ```typescript
1781
- * // Allow if user has view OR create permission
1782
1577
  * { path: 'users', canActivate: [anyPermissionGuard(['user.view', 'user.create'])] }
1783
1578
  * ```
1784
1579
  */
1785
1580
  declare function anyPermissionGuard(permissions: string[], redirectTo?: string): CanActivateFn;
1786
1581
  /**
1787
- * All Permissions Guard (AND logic)
1788
- *
1789
- * Allows access only if user has ALL of the specified permissions.
1582
+ * All Permissions Guard (AND logic) - Access only if user has ALL permissions.
1790
1583
  *
1791
1584
  * @example
1792
1585
  * ```typescript
1793
- * // Allow only if user has BOTH view AND create permissions
1794
1586
  * { path: 'admin', canActivate: [allPermissionsGuard(['admin.view', 'admin.manage'])] }
1795
1587
  * ```
1796
1588
  */
1797
1589
  declare function allPermissionsGuard(permissions: string[], redirectTo?: string): CanActivateFn;
1798
1590
 
1591
+ declare function localToUtc(dateStr: string, timeStr: string, timezone: string): Date;
1592
+ declare function utcToLocal(utcDate: Date | string, timezone: string): {
1593
+ date: string;
1594
+ time: string;
1595
+ display: string;
1596
+ };
1597
+ declare function formatInTimezone(utcDate: Date | string, timezone: string, options?: Intl.DateTimeFormatOptions): string;
1598
+ declare function getUserTimezone(): string;
1599
+
1600
+ /**
1601
+ * Check if user has a specific permission using wildcard matching.
1602
+ * Supports:
1603
+ * - Exact match: 'user.create' matches 'user.create'
1604
+ * - Full wildcard: '*' matches everything
1605
+ * - Module wildcard: 'user.*' matches 'user.create', 'user.read', etc.
1606
+ */
1607
+ declare function hasPermission(requiredPermission: string, userPermissions: string[]): boolean;
1799
1608
  /** Evaluate permission logic (string or ILogicNode) against user permissions */
1800
1609
  declare function evaluatePermission(logic: string | ILogicNode | null | undefined, permissions: string[]): boolean;
1801
1610
  /** Recursively evaluate an ILogicNode tree */
@@ -1805,5 +1614,38 @@ declare function hasAnyPermission(permissionCodes: string[], permissions: string
1805
1614
  /** Check if user has ALL of the specified permissions (AND logic) */
1806
1615
  declare function hasAllPermissions(permissionCodes: string[], permissions: string[]): boolean;
1807
1616
 
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 };
1617
+ /**
1618
+ * Configuration for scroll pagination behavior
1619
+ */
1620
+ interface ScrollPaginationConfig {
1621
+ /** Distance from bottom to trigger pagination (default: 50px) */
1622
+ threshold?: number;
1623
+ /** Current pagination state */
1624
+ pagination: IPagination;
1625
+ /** Total items available */
1626
+ total: number | undefined;
1627
+ /** Whether currently loading */
1628
+ isLoading: boolean;
1629
+ }
1630
+ /**
1631
+ * Check if scroll has reached near bottom and calculate next page if available.
1632
+ * Returns next pagination if should load more, null otherwise.
1633
+ *
1634
+ * @example
1635
+ * ```typescript
1636
+ * onScroll(event: Event): void {
1637
+ * const nextPagination = checkScrollPagination(event, {
1638
+ * pagination: this.pagination(),
1639
+ * total: this.total(),
1640
+ * isLoading: this.isLoading(),
1641
+ * });
1642
+ * if (nextPagination) {
1643
+ * this.onPagination.emit(nextPagination);
1644
+ * }
1645
+ * }
1646
+ * ```
1647
+ */
1648
+ declare function checkScrollPagination(event: Event, config: ScrollPaginationConfig): IPagination | null;
1649
+
1650
+ export { ACTION_PERMISSIONS, AUTH_STATE_PROVIDER, AngularModule, ApiResourceService, ApiResourceService as ApiService, BRANCH_PERMISSIONS, BaseFormComponent, BaseFormControl, BaseFormTemplateDirective, BaseListComponent, BaseListTemplateDirective, BaseUserSelectComponent, COMPANY_ACTION_PERMISSIONS, COMPANY_API_PROVIDER, COMPANY_PERMISSIONS, CookieService, EMAIL_CONFIG_PERMISSIONS, EMAIL_TEMPLATE_PERMISSIONS, EVENT_PERMISSIONS, EditModeElementChangerDirective, FILE_PERMISSIONS, FILE_PROVIDER, FILE_TYPE_FILTERS, FOLDER_PERMISSIONS, FORM_PERMISSIONS, FORM_RESULT_PERMISSIONS, FaviconService, FileSelectorDialogComponent, FileUploaderComponent, FileUrlService, HasPermissionDirective, IconComponent, IconTypeEnum, InlineSvgComponent, IsEmptyImageDirective, LANGUAGE_PERMISSIONS, LazyMultiSelectComponent, LazySelectComponent, NOTIFICATION_PERMISSIONS, PERMISSIONS, PROFILE_PERMISSION_PROVIDER, PermissionValidatorService, PlatformService, PreventDefaultDirective, ROLE_ACTION_PERMISSIONS, ROLE_PERMISSIONS, RouterTabsComponent, SHARED_MESSAGES, SKIP_ERROR_TOAST, STORAGE_CONFIG_PERMISSIONS, TRANSLATION_KEY_PERMISSIONS, TRANSLATION_PERMISSIONS, TranslatePipe, TranslateService, UPLOAD_CONFIG_PERMISSIONS, USER_ACTION_PERMISSIONS, USER_PERMISSIONS, USER_PERMISSION_PROVIDER, USER_PROVIDER, USER_ROLE_PERMISSIONS, UserMultiSelectComponent, UserSelectComponent, allPermissionsGuard, anyPermissionGuard, checkScrollPagination, errorCatchingInterceptor, evaluateLogicNode, evaluatePermission, formatFileSize, formatInTimezone, getAcceptString, getFileIconClass, getUserTimezone, hasAllPermissions, hasAnyPermission, hasPermission, isFileTypeAllowed, localToUtc, permissionGuard, provideValueAccessor, resolveTranslationModule, utcToLocal };
1651
+ export type { ActionSeverity, DeleteType, FilesResponseDto, FormFieldType, IActionNode, IActivatable, IApiService, IAuthStateProvider, IBaseEntity, IBulkMeta, IBulkResponse, ICompanyApiProvider, ICompanyBasicInfo, IDeleteData, IDropDown, IFileBasicInfo, IFileProvider, IFileSelectFilter, IFileUploadOptions, IFilter, IFilterData, IFolderBasicInfo, IFormField, IFormSelectOption, IGroupNode, IListResponse, ILoggedUserInfo, ILogicNode, IMessageResponse, IOrderable, IPagination, IPaginationMeta, IProfileActionInfo, IProfilePermissionProvider, IProfileRoleInfo, IRequestMeta, IResolverModuleConfig, ISelectFilter, ISingleResponse, ISoftDeletable, ISort, IStorageConfigBasicInfo, ITableAction, ITableColumn, ITagConfig, ITimestampable, IUploadedFile, IUserBasicInfo, IUserBranchPermission, IUserPermissionProvider, IUserProvider, IUserSelectFilter, LoadUsersFn, PermissionCode, RouterTabItem, ScrollPaginationConfig, TableColumnType, UploadFileFn, UploadMultipleFilesFn };