@flusys/ng-shared 5.0.1 → 5.0.4

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flusys/ng-shared",
3
- "version": "5.0.1",
3
+ "version": "5.0.4",
4
4
  "description": "Shared components and utilities for FLUSYS Angular packages",
5
5
  "license": "MIT",
6
6
  "peerDependencies": {
@@ -8,7 +8,7 @@
8
8
  "@angular/core": ">=21.0.0",
9
9
  "@angular/forms": ">=21.0.0",
10
10
  "@angular/router": ">=21.0.0",
11
- "@flusys/ng-core": ">=5.0.1",
11
+ "@flusys/ng-core": ">=5.0.4",
12
12
  "@primeuix/themes": ">=1.0.0",
13
13
  "primeicons": ">=7.0.0",
14
14
  "primeng": ">=21.0.0",
@@ -2,6 +2,7 @@ import * as rxjs from 'rxjs';
2
2
  import { Observable } from 'rxjs';
3
3
  import * as _angular_core from '@angular/core';
4
4
  import { Signal, PipeTransform, ResourceRef, ResourceStatus, Injector, model, OnDestroy, ElementRef, TemplateRef, DestroyRef, InjectionToken } from '@angular/core';
5
+ import { HttpContextToken, HttpRequest, HttpHandlerFn, HttpEvent, HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
5
6
  import * as i3 from '@angular/router';
6
7
  import { ResolveFn, CanActivateFn, Router, ActivatedRoute } from '@angular/router';
7
8
  import * as i1 from '@angular/common';
@@ -49,9 +50,9 @@ import * as i38 from 'primeng/treetable';
49
50
  import * as i39 from 'primeng/progressspinner';
50
51
  import * as i40 from 'primeng/colorpicker';
51
52
  import * as _flusys_ng_shared from '@flusys/ng-shared';
52
- import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
53
- import { FormValueControl } from '@angular/forms/signals';
54
53
  import * as _flusys_ng_core from '@flusys/ng-core';
54
+ import { ServiceName } from '@flusys/ng-core';
55
+ import { FormValueControl } from '@angular/forms/signals';
55
56
  import { MessageService, ConfirmationService } from 'primeng/api';
56
57
 
57
58
  declare const SHARED_MESSAGES: Record<string, string>;
@@ -120,6 +121,9 @@ declare const STORAGE_CONFIG_PERMISSIONS: {
120
121
  readonly UPDATE: "storage-config.update";
121
122
  readonly DELETE: "storage-config.delete";
122
123
  };
124
+ declare const UPLOAD_CONFIG_PERMISSIONS: {
125
+ readonly DELETE: "upload-config.delete";
126
+ };
123
127
  declare const EMAIL_CONFIG_PERMISSIONS: {
124
128
  readonly CREATE: "email-config.create";
125
129
  readonly READ: "email-config.read";
@@ -138,18 +142,18 @@ declare const FORM_PERMISSIONS: {
138
142
  readonly UPDATE: "form.update";
139
143
  readonly DELETE: "form.delete";
140
144
  };
145
+ declare const FORM_RESULT_PERMISSIONS: {
146
+ readonly CREATE: "form-result.create";
147
+ readonly READ: "form-result.read";
148
+ readonly UPDATE: "form-result.update";
149
+ readonly DELETE: "form-result.delete";
150
+ };
141
151
  declare const EVENT_PERMISSIONS: {
142
152
  readonly CREATE: "event.create";
143
153
  readonly READ: "event.read";
144
154
  readonly UPDATE: "event.update";
145
155
  readonly DELETE: "event.delete";
146
156
  };
147
- declare const EVENT_PARTICIPANT_PERMISSIONS: {
148
- readonly CREATE: "event-participant.create";
149
- readonly READ: "event-participant.read";
150
- readonly UPDATE: "event-participant.update";
151
- readonly DELETE: "event-participant.delete";
152
- };
153
157
  declare const NOTIFICATION_PERMISSIONS: {
154
158
  readonly CREATE: "notification.create";
155
159
  readonly READ: "notification.read";
@@ -174,6 +178,127 @@ declare const TRANSLATION_PERMISSIONS: {
174
178
  readonly UPDATE: "translation.update";
175
179
  readonly DELETE: "translation.delete";
176
180
  };
181
+ declare const PERMISSIONS: {
182
+ readonly USER: {
183
+ readonly CREATE: "user.create";
184
+ readonly READ: "user.read";
185
+ readonly UPDATE: "user.update";
186
+ readonly DELETE: "user.delete";
187
+ };
188
+ readonly COMPANY: {
189
+ readonly CREATE: "company.create";
190
+ readonly READ: "company.read";
191
+ readonly UPDATE: "company.update";
192
+ readonly DELETE: "company.delete";
193
+ };
194
+ readonly BRANCH: {
195
+ readonly CREATE: "branch.create";
196
+ readonly READ: "branch.read";
197
+ readonly UPDATE: "branch.update";
198
+ readonly DELETE: "branch.delete";
199
+ };
200
+ readonly ACTION: {
201
+ readonly CREATE: "action.create";
202
+ readonly READ: "action.read";
203
+ readonly UPDATE: "action.update";
204
+ readonly DELETE: "action.delete";
205
+ };
206
+ readonly ROLE: {
207
+ readonly CREATE: "role.create";
208
+ readonly READ: "role.read";
209
+ readonly UPDATE: "role.update";
210
+ readonly DELETE: "role.delete";
211
+ };
212
+ readonly ROLE_ACTION: {
213
+ readonly READ: "role-action.read";
214
+ readonly ASSIGN: "role-action.assign";
215
+ };
216
+ readonly USER_ROLE: {
217
+ readonly READ: "user-role.read";
218
+ readonly ASSIGN: "user-role.assign";
219
+ };
220
+ readonly USER_ACTION: {
221
+ readonly READ: "user-action.read";
222
+ readonly ASSIGN: "user-action.assign";
223
+ };
224
+ readonly COMPANY_ACTION: {
225
+ readonly READ: "company-action.read";
226
+ readonly ASSIGN: "company-action.assign";
227
+ };
228
+ readonly FILE: {
229
+ readonly CREATE: "file.create";
230
+ readonly READ: "file.read";
231
+ readonly UPDATE: "file.update";
232
+ readonly DELETE: "file.delete";
233
+ };
234
+ readonly FOLDER: {
235
+ readonly CREATE: "folder.create";
236
+ readonly READ: "folder.read";
237
+ readonly UPDATE: "folder.update";
238
+ readonly DELETE: "folder.delete";
239
+ };
240
+ readonly STORAGE_CONFIG: {
241
+ readonly CREATE: "storage-config.create";
242
+ readonly READ: "storage-config.read";
243
+ readonly UPDATE: "storage-config.update";
244
+ readonly DELETE: "storage-config.delete";
245
+ };
246
+ readonly EMAIL_CONFIG: {
247
+ readonly CREATE: "email-config.create";
248
+ readonly READ: "email-config.read";
249
+ readonly UPDATE: "email-config.update";
250
+ readonly DELETE: "email-config.delete";
251
+ };
252
+ readonly EMAIL_TEMPLATE: {
253
+ readonly CREATE: "email-template.create";
254
+ readonly READ: "email-template.read";
255
+ readonly UPDATE: "email-template.update";
256
+ readonly DELETE: "email-template.delete";
257
+ };
258
+ readonly FORM: {
259
+ readonly CREATE: "form.create";
260
+ readonly READ: "form.read";
261
+ readonly UPDATE: "form.update";
262
+ readonly DELETE: "form.delete";
263
+ };
264
+ readonly FORM_RESULT: {
265
+ readonly CREATE: "form-result.create";
266
+ readonly READ: "form-result.read";
267
+ readonly UPDATE: "form-result.update";
268
+ readonly DELETE: "form-result.delete";
269
+ };
270
+ readonly EVENT: {
271
+ readonly CREATE: "event.create";
272
+ readonly READ: "event.read";
273
+ readonly UPDATE: "event.update";
274
+ readonly DELETE: "event.delete";
275
+ };
276
+ readonly NOTIFICATION: {
277
+ readonly CREATE: "notification.create";
278
+ readonly READ: "notification.read";
279
+ readonly UPDATE: "notification.update";
280
+ readonly DELETE: "notification.delete";
281
+ };
282
+ readonly LANGUAGE: {
283
+ readonly CREATE: "language.create";
284
+ readonly READ: "language.read";
285
+ readonly UPDATE: "language.update";
286
+ readonly DELETE: "language.delete";
287
+ };
288
+ readonly TRANSLATION_KEY: {
289
+ readonly CREATE: "translation-key.create";
290
+ readonly READ: "translation-key.read";
291
+ readonly UPDATE: "translation-key.update";
292
+ readonly DELETE: "translation-key.delete";
293
+ };
294
+ readonly TRANSLATION: {
295
+ readonly CREATE: "translation.create";
296
+ readonly READ: "translation.read";
297
+ readonly UPDATE: "translation.update";
298
+ readonly DELETE: "translation.delete";
299
+ };
300
+ };
301
+ type PermissionCode = (typeof PERMISSIONS)[keyof typeof PERMISSIONS][keyof (typeof PERMISSIONS)[keyof typeof PERMISSIONS]];
177
302
 
178
303
  /**
179
304
  * Base entity interface - matches backend Identity entity
@@ -290,14 +415,6 @@ interface IBulkMeta {
290
415
  failed?: number;
291
416
  total?: number;
292
417
  }
293
- /**
294
- * Validation error detail
295
- */
296
- interface IValidationError {
297
- field: string;
298
- message: string;
299
- constraint?: string;
300
- }
301
418
  /**
302
419
  * Single item response (insert, update, get-by-id)
303
420
  */
@@ -343,32 +460,6 @@ interface IMessageResponse {
343
460
  messageVariables?: Record<string, unknown>;
344
461
  _meta?: IRequestMeta;
345
462
  }
346
- /**
347
- * Error response
348
- */
349
- interface IErrorResponse {
350
- success: false;
351
- message: string;
352
- messageKey?: string;
353
- messageVariables?: Record<string, unknown>;
354
- errors?: IValidationError[];
355
- _meta?: IRequestMeta;
356
- }
357
- /**
358
- * Union type for all API responses
359
- */
360
- type ApiResponse<T> = ISingleResponse<T> | IListResponse<T> | IBulkResponse<T> | IMessageResponse | IErrorResponse;
361
- interface IFileData {
362
- id: string;
363
- name: string;
364
- originalName: string;
365
- contentType: string;
366
- size: number;
367
- key: string;
368
- url?: string;
369
- thumbnailUrl?: string;
370
- createdAt: Date;
371
- }
372
463
 
373
464
  interface IFileBasicInfo {
374
465
  id: string;
@@ -413,10 +504,8 @@ interface IFileSelectFilter extends ISelectFilter {
413
504
  folderId?: string;
414
505
  storageConfigId?: string;
415
506
  }
416
- type LoadFilesFn = (filter: IFileSelectFilter) => Observable<IListResponse<IFileBasicInfo>>;
417
507
  type UploadFileFn = (file: File, options?: IFileUploadOptions) => Observable<ISingleResponse<IUploadedFile>>;
418
508
  type UploadMultipleFilesFn = (files: File[], options?: IFileUploadOptions) => Observable<ISingleResponse<IUploadedFile[]>>;
419
- type GetFileUrlsFn = (fileIds: string[]) => Observable<ISingleResponse<IFileBasicInfo[]>>;
420
509
  declare const FILE_TYPE_FILTERS: {
421
510
  readonly IMAGES: readonly ["image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml"];
422
511
  readonly DOCUMENTS: readonly ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/vnd.ms-excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"];
@@ -472,9 +561,8 @@ interface IUserProvider {
472
561
  page?: number;
473
562
  pageSize?: number;
474
563
  search?: string;
475
- companyId?: string;
476
- branchId?: string;
477
564
  isActive?: boolean;
565
+ [key: string]: any;
478
566
  }): Observable<IListResponse<IUserBasicInfo>>;
479
567
  }
480
568
  /** Filter params passed to loadUsers function */
@@ -541,65 +629,6 @@ interface IProfilePermissionProvider {
541
629
  getUserRoles(userId: string, branchId?: string): Observable<ISingleResponse<IProfileRoleInfo[]>>;
542
630
  getUserActions(userId: string, branchId?: string): Observable<ISingleResponse<IProfileActionInfo[]>>;
543
631
  }
544
- /**
545
- * Base user interface for list operations
546
- */
547
- interface IUserListItem {
548
- id: string;
549
- name: string;
550
- email: string;
551
- phone?: string;
552
- isActive?: boolean;
553
- }
554
- /**
555
- * User list action definition
556
- */
557
- interface IUserListAction<T = IUserListItem> {
558
- id: string;
559
- label: string;
560
- icon?: string;
561
- severity?: 'primary' | 'secondary' | 'success' | 'info' | 'warn' | 'danger' | 'help' | 'contrast';
562
- permission?: string;
563
- tooltip?: string;
564
- disabled?: boolean | ((user: T) => boolean);
565
- visible?: boolean | ((user: T) => boolean);
566
- }
567
- /**
568
- * Extra column definition for user list
569
- */
570
- interface IUserListColumn {
571
- field: string;
572
- header: string;
573
- width?: string;
574
- sortable?: boolean;
575
- filterable?: boolean;
576
- templateType?: 'text' | 'badge' | 'date' | 'boolean' | 'custom';
577
- }
578
- /**
579
- * Extra filter definition for user list
580
- */
581
- interface IUserListFilter {
582
- field: string;
583
- label: string;
584
- type: 'text' | 'dropdown' | 'multiselect' | 'date' | 'boolean';
585
- options?: {
586
- label: string;
587
- value: string | number | boolean;
588
- }[];
589
- placeholder?: string;
590
- }
591
- /**
592
- * User List Provider Interface - Allows apps to extend user list pages.
593
- */
594
- interface IUserListProvider<T extends IUserListItem = IUserListItem> {
595
- getExtraColumns?(): IUserListColumn[];
596
- getExtraRowActions?(): IUserListAction<T>[];
597
- getExtraToolbarActions?(): IUserListAction<T>[];
598
- onRowAction?(actionId: string, user: T): void;
599
- onToolbarAction?(actionId: string, selectedUsers: T[]): void;
600
- enrichListData?(users: T[]): Observable<T[]>;
601
- getExtraFilters?(): IUserListFilter[];
602
- }
603
632
  /**
604
633
  * File Provider Interface - Provides file loading and upload functionality.
605
634
  * Used by FileSelectorDialogComponent to load files and handle uploads.
@@ -648,19 +677,11 @@ declare class FileUrlService {
648
677
  private readonly http;
649
678
  private readonly appConfig;
650
679
  private readonly _cache;
651
- readonly cache: Signal<Map<string, FilesResponseDto>>;
652
- /** Get file URL by ID from cache (synchronous) */
653
- getFileUrl(fileId: string | null | undefined): string | null;
654
- /** Get file URL as computed signal */
655
- fileUrlSignal(fileId: string | null | undefined): Signal<string | null>;
680
+ readonly cache: _angular_core.Signal<Map<string, FilesResponseDto>>;
656
681
  /** Fetch file URLs from backend and update cache */
657
682
  fetchFileUrls(fileIds: string[], forceRefresh?: boolean): Observable<FilesResponseDto[]>;
658
683
  /** Fetch single file URL (delegates to fetchFileUrls) */
659
684
  fetchSingleFileUrl(fileId: string, forceRefresh?: boolean): Observable<FilesResponseDto | null>;
660
- /** Clear entire cache */
661
- clearCache(): void;
662
- /** Remove specific file from cache */
663
- removeFromCache(fileId: string): void;
664
685
  private addToCache;
665
686
  private getFromCache;
666
687
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<FileUrlService, never>;
@@ -682,6 +703,8 @@ declare class PermissionValidatorService {
682
703
  clearPermissions(): void;
683
704
  /** Check if user has permission (supports wildcards: '*', 'module.*') */
684
705
  hasPermission(code: string): boolean;
706
+ /** Check if user has ANY of the specified permissions (OR logic) */
707
+ hasAnyPermission(code: string[]): boolean;
685
708
  isPermissionsLoaded(): boolean;
686
709
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<PermissionValidatorService, never>;
687
710
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<PermissionValidatorService>;
@@ -694,6 +717,16 @@ declare class PlatformService {
694
717
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<PlatformService>;
695
718
  }
696
719
 
720
+ declare class TranslateService {
721
+ private readonly localizationState;
722
+ translate(key: string, params?: Record<string, string | unknown>): string;
723
+ translateSignal(key: string, params?: Record<string, string | number>): Signal<string>;
724
+ private getFromFallback;
725
+ private interpolate;
726
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<TranslateService, never>;
727
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<TranslateService>;
728
+ }
729
+
697
730
  declare class EditModeElementChangerDirective {
698
731
  private readonly el;
699
732
  private readonly ngControl;
@@ -804,14 +837,52 @@ declare class PreventDefaultDirective {
804
837
 
805
838
  declare class TranslatePipe implements PipeTransform {
806
839
  private readonly translateAdapter;
807
- private readonly fallbackMessages;
808
840
  transform(key: string | null | undefined, params?: Record<string, string | number> | null, fallback?: string): string;
809
- private getFromFallback;
810
- private interpolate;
811
841
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TranslatePipe, never>;
812
842
  static ɵpipe: _angular_core.ɵɵPipeDeclaration<TranslatePipe, "translate", true>;
813
843
  }
814
844
 
845
+ /**
846
+ * HTTP context token to skip global error toast.
847
+ * Use when component handles error display locally.
848
+ *
849
+ * @example
850
+ * ```typescript
851
+ * this.http.post(url, data, {
852
+ * context: new HttpContext().set(SKIP_ERROR_TOAST, true)
853
+ * });
854
+ * ```
855
+ */
856
+ declare const SKIP_ERROR_TOAST: HttpContextToken<boolean>;
857
+ /**
858
+ * Error Catching Interceptor
859
+ * Displays error messages for failed HTTP requests using backend response.
860
+ *
861
+ * Features:
862
+ * - Uses backend's error title (error.error.error) as summary
863
+ * - Uses backend's error message (error.error.message) as detail
864
+ * - Falls back to sensible defaults based on status code
865
+ * - Skip with SKIP_ERROR_TOAST context token for local handling
866
+ *
867
+ * NOTE: This interceptor only handles error display.
868
+ * For 401 handling and token refresh, use tokenRefreshInterceptor from @flusys/ng-auth.
869
+ *
870
+ * @example
871
+ * ```typescript
872
+ * // In app.config.ts
873
+ * provideHttpClient(
874
+ * withFetch(),
875
+ * withInterceptors([
876
+ * authInterceptor, // from @flusys/ng-auth
877
+ * tokenRefreshInterceptor, // from @flusys/ng-auth
878
+ * errorCatchingInterceptor, // from @flusys/ng-core
879
+ * apiLoaderInterceptor, // from @flusys/ng-core
880
+ * ])
881
+ * )
882
+ * ```
883
+ */
884
+ declare function errorCatchingInterceptor(req: HttpRequest<unknown>, next: HttpHandlerFn): Observable<HttpEvent<unknown>>;
885
+
815
886
  interface IResolverModuleConfig {
816
887
  modules: string[];
817
888
  fallbackMessages?: Record<string, string>;
@@ -830,7 +901,6 @@ declare class PrimeModule {
830
901
  static ɵinj: _angular_core.ɵɵInjectorDeclaration<PrimeModule>;
831
902
  }
832
903
 
833
- type ServiceName = 'auth' | 'administration' | 'iam' | 'storage' | 'formBuilder' | 'email' | 'eventManager' | 'notification' | 'localization';
834
904
  interface IApiService<DtoT, InterfaceT> {
835
905
  insert(dto: DtoT): Promise<ISingleResponse<InterfaceT>>;
836
906
  insertMany(dtos: DtoT[]): Promise<IBulkResponse<InterfaceT>>;
@@ -840,12 +910,13 @@ interface IApiService<DtoT, InterfaceT> {
840
910
  getByFilter(filter: Record<string, unknown>): Promise<ISingleResponse<InterfaceT>>;
841
911
  update(dto: DtoT): Promise<ISingleResponse<InterfaceT>>;
842
912
  updateMany(dtos: DtoT[]): Promise<IBulkResponse<InterfaceT>>;
843
- bulkUpsert(toInsert: Array<DtoT>, toUpdate: Array<DtoT>): Promise<Array<InterfaceT>>;
913
+ bulkUpsert(toInsert: DtoT[], toUpdate: DtoT[]): Promise<InterfaceT[]>;
844
914
  delete(deleteDto: IDeleteData): Promise<IMessageResponse>;
845
915
  }
846
916
  declare abstract class ApiResourceService<DtoT, InterfaceT> implements IApiService<DtoT, InterfaceT> {
847
- protected readonly baseUrl: string;
848
917
  protected readonly http: HttpClient;
918
+ private readonly _config;
919
+ protected readonly baseUrl: string;
849
920
  protected readonly moduleApiName: string;
850
921
  readonly searchTerm: _angular_core.WritableSignal<string>;
851
922
  readonly filterData: _angular_core.WritableSignal<IFilterData>;
@@ -858,97 +929,55 @@ declare abstract class ApiResourceService<DtoT, InterfaceT> implements IApiServi
858
929
  readonly hasMore: _angular_core.Signal<boolean>;
859
930
  readonly error: _angular_core.Signal<Error | undefined>;
860
931
  readonly status: _angular_core.Signal<ResourceStatus>;
861
- constructor(moduleApiName: string, http: HttpClient, serviceName?: ServiceName);
932
+ constructor(moduleApiName: string, serviceName?: ServiceName);
862
933
  protected getHttpOptions(endpoint: string, params?: HttpParams): {
863
934
  params?: HttpParams | undefined;
864
935
  headers: HttpHeaders;
865
936
  };
866
937
  private _getAllObs;
938
+ private _activate;
867
939
  fetchList(search?: string, filter?: Partial<IFilterData>): void;
868
940
  setPagination(pagination: IPagination): void;
869
941
  nextPage(): void;
870
942
  resetPagination(): void;
871
943
  reload(): void;
944
+ private _post;
872
945
  insert(dto: DtoT): Promise<ISingleResponse<InterfaceT>>;
873
946
  insertMany(dtos: DtoT[]): Promise<IBulkResponse<InterfaceT>>;
874
947
  findById(id: string, select?: string[]): Promise<ISingleResponse<InterfaceT>>;
875
948
  getAll(filter: IFilterData, search?: string): Promise<IListResponse<InterfaceT>>;
876
949
  update(dto: DtoT): Promise<ISingleResponse<InterfaceT>>;
877
950
  updateMany(dtos: DtoT[]): Promise<IBulkResponse<InterfaceT>>;
951
+ delete(deleteDto: IDeleteData): Promise<IMessageResponse>;
878
952
  findByIds(ids: string[], select?: string[] | string): Promise<IListResponse<InterfaceT>>;
879
- bulkUpsert(toInsert: Array<DtoT>, toUpdate: Array<DtoT>): Promise<Array<InterfaceT>>;
880
953
  getByFilter(filter: Record<string, unknown>): Promise<ISingleResponse<InterfaceT>>;
881
- delete(deleteDto: IDeleteData): Promise<IMessageResponse>;
954
+ bulkUpsert(toInsert: DtoT[], toUpdate: DtoT[]): Promise<InterfaceT[]>;
882
955
  }
883
956
 
884
- /**
885
- * Base class for form controls that support ALL Angular form patterns:
886
- *
887
- * 1. **Template-driven forms:** `[(value)]="mySignal"` or `[(ngModel)]="myValue"`
888
- * 2. **Reactive forms:** `[formControl]="ctrl"` or `formControlName="field"`
889
- * 3. **Signal forms (Angular 21+):** `[formField]="formTree.field"`
890
- *
891
- * Implements both `ControlValueAccessor` (reactive forms) and `FormValueControl` (signal forms).
892
- *
893
- * @example
894
- * ```typescript
895
- * @Component({
896
- * providers: [provideValueAccessor(MySelectComponent)]
897
- * })
898
- * export class MySelectComponent extends BaseFormControl<string | null> {
899
- * override readonly value = model<string | null>(null);
900
- *
901
- * constructor() {
902
- * super();
903
- * this.initializeFormControl();
904
- * }
905
- * }
906
- *
907
- * // Usage:
908
- * // Template-driven: <my-select [(value)]="selectedId" />
909
- * // Reactive forms: <my-select [formControl]="myControl" />
910
- * // Signal forms: <my-select [formField]="formTree.myField" />
911
- * ```
912
- */
913
957
  declare abstract class BaseFormControl<T> implements ControlValueAccessor, FormValueControl<T> {
914
958
  protected readonly injector: Injector;
915
- /**
916
- * The value model - must be overridden in subclass with model<T>().
917
- * This property satisfies both:
918
- * - FormValueControl interface (signal forms)
919
- * - Internal state for ControlValueAccessor (reactive forms)
920
- */
921
959
  abstract readonly value: ReturnType<typeof model<T>>;
922
- /**
923
- * Disabled state model - bound to form control disabled state.
924
- * Using model() to satisfy FormValueControl interface requirements.
925
- */
926
960
  readonly disabled: _angular_core.ModelSignal<boolean>;
927
- /**
928
- * Touched state model - for validation styling.
929
- * Using model() to satisfy FormValueControl interface requirements.
930
- */
931
961
  readonly touched: _angular_core.ModelSignal<boolean>;
932
962
  private onChange;
933
963
  private onTouched;
934
- private isWritingValue;
964
+ private writeDepth;
935
965
  /**
936
- * Initialize the form control synchronization for ControlValueAccessor.
937
- * Must be called in the subclass constructor after super().
966
+ * Wire up the ControlValueAccessor ↔ signal bridge.
967
+ * Call once at the end of the subclass constructor.
968
+ *
969
+ * Signal-form consumers ([formField]) don't need this — Angular's
970
+ * FormField directive binds directly to `value`.
938
971
  *
939
- * Note: For signal forms ([formField]), this is not needed as
940
- * the FormField directive binds directly to the value model.
972
+ * @example
973
+ * constructor() { super(); this.initializeFormControl(); }
941
974
  */
942
975
  protected initializeFormControl(): void;
943
- /** ControlValueAccessor: Write value from form control to signal */
944
976
  writeValue(value: T): void;
945
- /** ControlValueAccessor: Register change callback */
946
977
  registerOnChange(fn: (value: T) => void): void;
947
- /** ControlValueAccessor: Register touched callback */
948
978
  registerOnTouched(fn: () => void): void;
949
- /** ControlValueAccessor: Set disabled state from form control */
950
979
  setDisabledState(isDisabled: boolean): void;
951
- /** Mark the control as touched (call on blur or panel close) */
980
+ /** Call on blur / panel-close to propagate touched state. */
952
981
  protected markAsTouched(): void;
953
982
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<BaseFormControl<any>, never>;
954
983
  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>;
@@ -1190,7 +1219,7 @@ declare abstract class BaseUserSelectComponent {
1190
1219
  protected readonly destroyRef: DestroyRef;
1191
1220
  protected readonly injector: Injector;
1192
1221
  protected readonly userProvider: IUserProvider;
1193
- protected readonly translateAdapter: _flusys_ng_core.ITranslateAdapter | null;
1222
+ protected readonly translateAdapter: TranslateService;
1194
1223
  protected abortController: AbortController | null;
1195
1224
  readonly loadUsers: _angular_core.InputSignal<LoadUsersFn | undefined>;
1196
1225
  readonly placeHolder: _angular_core.InputSignal<string>;
@@ -1481,7 +1510,7 @@ declare abstract class BaseFormPage<T, TFormModel> {
1481
1510
  protected readonly route: ActivatedRoute;
1482
1511
  protected readonly messageService: MessageService;
1483
1512
  protected readonly destroyRef: DestroyRef;
1484
- protected readonly translateAdapter: _flusys_ng_core.ITranslateAdapter | null;
1513
+ protected readonly translateAdapter: TranslateService | null;
1485
1514
  protected readonly routeParams: Signal<i3.ParamMap | undefined>;
1486
1515
  protected initialized: boolean;
1487
1516
  /** Loading state for async operations */
@@ -1591,7 +1620,7 @@ declare abstract class BaseListPage<T> {
1591
1620
  protected readonly appConfig: _flusys_ng_core.IAppConfig;
1592
1621
  protected readonly confirmationService: ConfirmationService;
1593
1622
  protected readonly destroyRef: DestroyRef;
1594
- protected readonly translateAdapter: _flusys_ng_core.ITranslateAdapter | null;
1623
+ protected readonly translateAdapter: TranslateService | null;
1595
1624
  /** Items list */
1596
1625
  readonly items: _angular_core.WritableSignal<T[]>;
1597
1626
  /** Loading state */
@@ -1753,5 +1782,5 @@ interface ScrollPaginationConfig {
1753
1782
  */
1754
1783
  declare function checkScrollPagination(event: Event, config: ScrollPaginationConfig): IPagination | null;
1755
1784
 
1756
- export { ACTION_PERMISSIONS, AUTH_STATE_PROVIDER, AngularModule, ApiResourceService, ApiResourceService as ApiService, BRANCH_PERMISSIONS, BaseFormControl, BaseFormPage, BaseListPage, BaseUserSelectComponent, COMPANY_ACTION_PERMISSIONS, COMPANY_API_PROVIDER, COMPANY_PERMISSIONS, CookieService, EMAIL_CONFIG_PERMISSIONS, EMAIL_TEMPLATE_PERMISSIONS, EVENT_PARTICIPANT_PERMISSIONS, EVENT_PERMISSIONS, EditModeElementChangerDirective, FILE_PERMISSIONS, FILE_PROVIDER, FILE_TYPE_FILTERS, FOLDER_PERMISSIONS, FORM_PERMISSIONS, FileSelectorDialogComponent, FileUploaderComponent, FileUrlService, HasPermissionDirective, IconComponent, IconTypeEnum, IsEmptyImageDirective, LANGUAGE_PERMISSIONS, LazyMultiSelectComponent, LazySelectComponent, NOTIFICATION_PERMISSIONS, PROFILE_PERMISSION_PROVIDER, PermissionValidatorService, PlatformService, PreventDefaultDirective, PrimeModule, ROLE_ACTION_PERMISSIONS, ROLE_PERMISSIONS, SHARED_MESSAGES, STORAGE_CONFIG_PERMISSIONS, TRANSLATION_KEY_PERMISSIONS, TRANSLATION_PERMISSIONS, TranslatePipe, USER_ACTION_PERMISSIONS, USER_PERMISSIONS, USER_PERMISSION_PROVIDER, USER_PROVIDER, USER_ROLE_PERMISSIONS, UserMultiSelectComponent, UserSelectComponent, allPermissionsGuard, anyPermissionGuard, checkScrollPagination, evaluateLogicNode, evaluatePermission, formatFileSize, formatInTimezone, getAcceptString, getFileIconClass, getUserTimezone, hasAllPermissions, hasAnyPermission, hasPermission, isFileTypeAllowed, localToUtc, permissionGuard, provideValueAccessor, resolveTranslationModule, utcToLocal };
1757
- export type { ApiResponse, DeleteType, FilesResponseDto, GetFileUrlsFn, IActionNode, IActivatable, IApiService, IAuthStateProvider, IBaseEntity, IBulkMeta, IBulkResponse, ICompanyApiProvider, ICompanyBasicInfo, IDeleteData, IDropDown, IErrorResponse, IFileBasicInfo, IFileData, IFileProvider, IFileSelectFilter, IFileUploadOptions, IFilter, IFilterData, IFolderBasicInfo, IGroupNode, IListResponse, ILoggedUserInfo, ILogicNode, IMessageResponse, IOrderable, IPagination, IPaginationMeta, IProfileActionInfo, IProfilePermissionProvider, IProfileRoleInfo, IRequestMeta, IResolverModuleConfig, ISelectFilter, ISingleResponse, ISoftDeletable, ISort, IStorageConfigBasicInfo, ITimestampable, IUploadedFile, IUserBasicInfo, IUserBranchPermission, IUserListAction, IUserListColumn, IUserListFilter, IUserListItem, IUserListProvider, IUserPermissionProvider, IUserProvider, IUserSelectFilter, IValidationError, LoadFilesFn, LoadUsersFn, ScrollPaginationConfig, ServiceName, UploadFileFn, UploadMultipleFilesFn };
1785
+ export { ACTION_PERMISSIONS, AUTH_STATE_PROVIDER, AngularModule, ApiResourceService, ApiResourceService as ApiService, BRANCH_PERMISSIONS, BaseFormControl, BaseFormPage, BaseListPage, BaseUserSelectComponent, COMPANY_ACTION_PERMISSIONS, COMPANY_API_PROVIDER, COMPANY_PERMISSIONS, CookieService, EMAIL_CONFIG_PERMISSIONS, EMAIL_TEMPLATE_PERMISSIONS, EVENT_PERMISSIONS, EditModeElementChangerDirective, FILE_PERMISSIONS, FILE_PROVIDER, FILE_TYPE_FILTERS, FOLDER_PERMISSIONS, FORM_PERMISSIONS, FORM_RESULT_PERMISSIONS, FileSelectorDialogComponent, FileUploaderComponent, FileUrlService, HasPermissionDirective, IconComponent, IconTypeEnum, IsEmptyImageDirective, LANGUAGE_PERMISSIONS, LazyMultiSelectComponent, LazySelectComponent, NOTIFICATION_PERMISSIONS, PERMISSIONS, PROFILE_PERMISSION_PROVIDER, PermissionValidatorService, PlatformService, PreventDefaultDirective, PrimeModule, ROLE_ACTION_PERMISSIONS, ROLE_PERMISSIONS, 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 };
1786
+ export type { DeleteType, FilesResponseDto, IActionNode, IActivatable, IApiService, IAuthStateProvider, IBaseEntity, IBulkMeta, IBulkResponse, ICompanyApiProvider, ICompanyBasicInfo, IDeleteData, IDropDown, IFileBasicInfo, IFileProvider, IFileSelectFilter, IFileUploadOptions, IFilter, IFilterData, IFolderBasicInfo, IGroupNode, IListResponse, ILoggedUserInfo, ILogicNode, IMessageResponse, IOrderable, IPagination, IPaginationMeta, IProfileActionInfo, IProfilePermissionProvider, IProfileRoleInfo, IRequestMeta, IResolverModuleConfig, ISelectFilter, ISingleResponse, ISoftDeletable, ISort, IStorageConfigBasicInfo, ITimestampable, IUploadedFile, IUserBasicInfo, IUserBranchPermission, IUserPermissionProvider, IUserProvider, IUserSelectFilter, LoadUsersFn, PermissionCode, ScrollPaginationConfig, UploadFileFn, UploadMultipleFilesFn };