@kuzntsv/uikit 1.0.39 → 1.0.42

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,9 +1,10 @@
1
1
  {
2
2
  "name": "@kuzntsv/uikit",
3
- "version": "1.0.39",
3
+ "version": "1.0.42",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^22.2.2",
6
- "@angular/core": "^22.2.2"
6
+ "@angular/core": "^22.2.2",
7
+ "zod": "^4.6.7"
7
8
  },
8
9
  "dependencies": {
9
10
  "tslib": "^2.8.1"
@@ -1,5 +1,5 @@
1
1
  import * as i0 from "@angular/core";
2
- import { AfterViewInit, ElementRef, EnvironmentProviders, InjectionToken, OnDestroy, OnInit, PipeTransform } from "@angular/core";
2
+ import { AfterViewInit, ElementRef, EnvironmentProviders, InjectionToken, OnDestroy, OnInit, PipeTransform, WritableSignal } from "@angular/core";
3
3
  import { NotificationService, RoleService } from "@kuzntsv/uikit";
4
4
  import { Observable, Subject, Subscription } from "rxjs";
5
5
  import { SelectionModel } from "@angular/cdk/collections";
@@ -7,11 +7,13 @@ import { MatMenuTrigger } from "@angular/material/menu";
7
7
  import { MatPaginator } from "@angular/material/paginator";
8
8
  import { MatSort } from "@angular/material/sort";
9
9
  import { MatTableDataSource } from "@angular/material/table";
10
+ import z, { z as z$1 } from "zod";
10
11
  import { FormControl, FormGroup } from "@angular/forms";
11
12
  import { MatDialog, MatDialogRef } from "@angular/material/dialog";
12
13
  import { SafeUrl } from "@angular/platform-browser";
13
14
  import { CanActivateFn, Router } from "@angular/router";
14
- import { HttpClient, HttpContext, HttpParams } from "@angular/common/http";
15
+ import { HttpClient, HttpContext, HttpParams, HttpResourceRef } from "@angular/common/http";
16
+ import { FieldTree } from "@angular/forms/signals";
15
17
  import { MatAutocompleteSelectedEvent } from "@angular/material/autocomplete";
16
18
  import { NativeDateAdapter } from "@angular/material/core";
17
19
  interface Authenticate {
@@ -531,12 +533,20 @@ export declare class BaseToolbarComponent {
531
533
  "clickedClearBtn": "clickedClearBtn";
532
534
  }, never, never, true, never>;
533
535
  }
536
+ export declare const BaseSchema: z$1.ZodObject<{
537
+ id: z$1.ZodNumber;
538
+ }, z$1.core.$strip>;
539
+ export type BaseSchemaClass = z$1.infer<typeof BaseSchema>;
540
+ /** @deprecated */
534
541
  export interface BaseClass {
535
542
  id: number;
536
543
  }
544
+ /** Объект передаваемый в диалог формы редактирования, оперирует доменной моделью. */
537
545
  export interface IEditDialogData<T, K = any> {
538
546
  action: Action;
547
+ /** Здесь всегда доменная модель */
539
548
  entity: T;
549
+ /** Дополнительные данные, например, фото. */
540
550
  extraData?: K;
541
551
  }
542
552
  export declare enum Action {
@@ -812,7 +822,7 @@ export declare class BasePageClass<T> implements OnDestroy {
812
822
  openDialog(entityComponent: any, data: IEditDialogData<T>, dialog: any): any;
813
823
  openDialogRemoveConfirm(removalMessage: string): MatDialogRef<DialogComponent> | undefined;
814
824
  protected onMiddleButton(baseUrl: string, queryParamName?: string, queryParamValue?: string): ($event: MouseEvent, item: T | undefined, contextMenu: MatMenuTrigger) => void;
815
- protected onActionMiddleButton(baseUrl: string, queryParamName?: string, queryParamValue?: string): ($event: MouseEvent, item: T) => void;
825
+ protected onActionMiddleButton(baseUrl: string, queryParamName?: string, queryParamValue?: string): ($event: MouseEvent, item: T | undefined) => void;
816
826
  protected dateToString(date: string | number | Date): string | null;
817
827
  static ɵfac: i0.ɵɵFactoryDeclaration<BasePageClass<any>, never>;
818
828
  static ɵdir: i0.ɵɵDirectiveDeclaration<BasePageClass<any>, never, never, {}, {}, never, never, true, never>;
@@ -841,6 +851,260 @@ export declare abstract class BaseServiceClass<T extends BaseClass> {
841
851
  static ɵfac: i0.ɵɵFactoryDeclaration<BaseServiceClass<any>, never>;
842
852
  static ɵprov: i0.ɵɵInjectableDeclaration<any>;
843
853
  }
854
+ export declare abstract class BaseSignalEditClass<TDomain extends Record<string, any>, TForm extends Record<string, any> = TDomain> implements OnDestroy {
855
+ /** Заголовок. */
856
+ abstract title: string;
857
+ /** Данные диалога. */
858
+ protected abstract dialogData: WritableSignal<IEditDialogData<TDomain>>;
859
+ protected formAction: import("@angular/core").Signal<Action>;
860
+ protected formActionIsAdd: import("@angular/core").Signal<boolean>;
861
+ protected formActionIsEdit: import("@angular/core").Signal<boolean>;
862
+ protected domainModel: import("@angular/core").Signal<TDomain>;
863
+ protected formModel: WritableSignal<TForm>;
864
+ /** Форма. */
865
+ protected abstract form: FieldTree<TForm>;
866
+ /** Ссылка на диалог. */
867
+ protected abstract dialogRef?: MatDialogRef<any, IEditDialogData<TDomain> | null>;
868
+ /** Сервис индикатор загрузки. */
869
+ protected loaderService: LoaderService;
870
+ /** Сервис уведомлений. */
871
+ protected notificationService: NotificationService;
872
+ /** Объект для отписки (вызывается метод unsubscribe при уничтожении компонента).
873
+ * @deprecated
874
+ */
875
+ protected subscription: Subscription;
876
+ /**
877
+ * Маппинг: Домен -> Форма.
878
+ * Реализация по умолчанию делает поверхностную копию. Наследник может её переопределить.
879
+ */
880
+ protected domainModelToFormModel(domainModel: TDomain): TForm;
881
+ /**
882
+ * Маппинг: Форма -> Домен.
883
+ * Реализация по умолчанию объединяет старый домен и новые поля формы.
884
+ */
885
+ protected formModelToDomainModel(formModel: TForm, originalDomain?: TDomain): TDomain;
886
+ ngOnDestroy(): void;
887
+ onNoClick(event: MouseEvent): void;
888
+ onSubmit(): void;
889
+ static ɵfac: i0.ɵɵFactoryDeclaration<BaseSignalEditClass<any, any>, never>;
890
+ static ɵdir: i0.ɵɵDirectiveDeclaration<BaseSignalEditClass<any, any>, never, never, {}, {}, never, never, true, never>;
891
+ }
892
+ type FilterValue = string | number | boolean | readonly string[] | readonly number[] | null | undefined;
893
+ type SafeFilterState = Readonly<Record<string, FilterValue>>;
894
+ type CleanFilterValue = Exclude<FilterValue, null | undefined>;
895
+ type CleanFilterState = Readonly<Record<string, CleanFilterValue>>;
896
+ declare function cleanFilterParams(filters: SafeFilterState): CleanFilterState;
897
+ export declare class BaseSignalFilterClass implements OnDestroy {
898
+ /** Сервис индикатор загрузки. */
899
+ protected loaderService: LoaderService;
900
+ /** Сервис уведомлений. */
901
+ protected notificationService: NotificationService;
902
+ /** Время на успокоение значения фильтра. */
903
+ defaultDebounceTime: number;
904
+ /**
905
+ * writable-сигнал, Принимаем текущее реактивное состояние фильтров с родительской страницы.
906
+ * Родитель передает значение через [(filters)]="pageFilters()".
907
+ * При любом изменении полей ввода обновляйте сигнал целиком через метод update.
908
+ *
909
+ * @example
910
+ * updateCategory(newCategory: string) {
911
+ * this.filters.update(prev => ({ ...prev, category: newCategory }));
912
+ * }
913
+ */
914
+ initialValues: import("@angular/core").InputSignal<Readonly<Record<string, FilterValue>>>;
915
+ /** Входной сигнал для сброса состояния формы. */
916
+ clearFilter: import("@angular/core").InputSignal<any>;
917
+ filterChange: import("@angular/core").OutputEmitterRef<Readonly<Record<string, FilterValue>>>;
918
+ filter: import("@angular/core").WritableSignal<Readonly<Record<string, FilterValue>>>;
919
+ /**
920
+ * Объект для отписки от внутренних подписок (например, valueChanges у FormControl).
921
+ * Метод unsubscribe вызывается при уничтожении компонента.
922
+ */
923
+ subscription: Subscription;
924
+ ngOnDestroy(): void;
925
+ static ɵfac: i0.ɵɵFactoryDeclaration<BaseSignalFilterClass, never>;
926
+ static ɵdir: i0.ɵɵDirectiveDeclaration<BaseSignalFilterClass, never, never, {
927
+ "initialValues": {
928
+ "alias": "initialValues";
929
+ "required": false;
930
+ "isSignal": true;
931
+ };
932
+ "clearFilter": {
933
+ "alias": "clearFilter";
934
+ "required": false;
935
+ "isSignal": true;
936
+ };
937
+ }, {
938
+ "filterChange": "filterChange";
939
+ }, never, never, true, never>;
940
+ }
941
+ export declare class BaseSignalPageClass<T> implements OnDestroy {
942
+ protected dialog: MatDialog;
943
+ entityService: any;
944
+ entityType: any;
945
+ entityEditComponent: any;
946
+ extraData?: any;
947
+ defaultPageIndex: number;
948
+ defaultPageSize: number;
949
+ dialogEditWidth: string;
950
+ dialogRemoveWidth: string;
951
+ routeAddress: string;
952
+ /** Сообщение при удалении записи(й). */
953
+ removalMessage: string;
954
+ /** Заголовок страницы. */
955
+ pageTitle: string;
956
+ /**
957
+ * Создание записи: вызывается перед открытием диалога.
958
+ */
959
+ beforeOpenDialogOnNewEvent: fnType<T>;
960
+ /**
961
+ * Редактирование записи: вызывается перед открытием диалога.
962
+ */
963
+ beforeOpenDialogOnEditEvent: fnType<T>;
964
+ /**
965
+ * Создание записи: вызывается перед сохранением объекта.
966
+ */
967
+ beforeSaveOnNewEvent: fnType<T>;
968
+ /**
969
+ * Редактирование записи: вызывается перед сохранением объекта.
970
+ */
971
+ beforeSaveOnEditEvent: fnType<T>;
972
+ /**
973
+ * Создание записи: вызывается после сохранения объекта.
974
+ */
975
+ afterSaveOnNewEvent: fnCbType<T>;
976
+ /**
977
+ * Редактирование записи: вызывается после сохранения объекта.
978
+ */
979
+ afterSaveOnEditEvent: fnCbType<T>;
980
+ editorRoles: string[];
981
+ executeRoles: string[];
982
+ /** Список ролей, для которых скрыть элемент. */
983
+ hideRoles: string[];
984
+ /** Загрузка данных. */
985
+ loadData$: Subject<null>;
986
+ /** Загрузка количества записей. */
987
+ loadLength$: Subject<null>;
988
+ /** Очистка фильтра. (для очистки присвоить пустой объект '{}'). */
989
+ clearFilters: import("@angular/core").WritableSignal<any>;
990
+ /** Разрешен выбор нескольких строк. */
991
+ allowMultiSelect: boolean;
992
+ /** Выбранные строки в таблице. */
993
+ selected: T[];
994
+ protected fnGetData: import("@angular/core").WritableSignal<fnGetDataType<T> | null>;
995
+ protected fnGetCount: import("@angular/core").WritableSignal<fnGetCountType<T> | null>;
996
+ protected fnMapEntity: import("@angular/core").WritableSignal<fnMapEntityType<T> | undefined>;
997
+ protected dataResource: import("@angular/core").ResourceRef<T[] | undefined>;
998
+ protected countResource: import("@angular/core").ResourceRef<number | undefined>;
999
+ /** Данные для табличного компонента. */
1000
+ data: import("@angular/core").Signal<T[]>;
1001
+ /** Количество записей по фильтру. */
1002
+ length: import("@angular/core").Signal<number>;
1003
+ /** Доступность кнопки "Изменить". */
1004
+ editBtnDisabled: boolean;
1005
+ /** Доступность кнопки "Удалить". */
1006
+ removeBtnDisabled: boolean;
1007
+ /** Разрешено ли отправлять событие rowDoubleClicked при двойном щелчке мышью. */
1008
+ dblClickedEventEnable: boolean;
1009
+ opt: IContextMenuOptions<T>[];
1010
+ protected router: Router;
1011
+ /** Сервис для работы с LocalStorage. */
1012
+ protected localStorageService: LocalStorageService;
1013
+ /** Сервис индикатор загрузки. */
1014
+ protected loaderService: LoaderService;
1015
+ /** Сервис уведомлений. */
1016
+ protected notificationService: import("@kuzntsv/uikit").INotificationService;
1017
+ /** Объект для отписки (вызывается метод unsubscribe при уничтожении компонента). */
1018
+ subscription: Subscription;
1019
+ private getInitialFilters;
1020
+ private getInitialFilters2;
1021
+ filters: import("@angular/core").WritableSignal<Readonly<Record<string, FilterValue>>>;
1022
+ filters2: import("@angular/core").WritableSignal<Record<string, any>>;
1023
+ /** Состояние сортировки, пагинации. */
1024
+ tableState: import("@angular/core").WritableSignal<ITableState>;
1025
+ constructor();
1026
+ ngOnDestroy(): void;
1027
+ subscribeToLoadData(fnGetData: fnGetDataType<T>, fnGetCount: fnGetCountType<T>, fnMapEntity?: fnMapEntityType<T>): void;
1028
+ setFilter(key: string, value: any): void;
1029
+ onPageChange(pageState: IPageState): void;
1030
+ onSortChange(sortState: ISortState): void;
1031
+ entityFactory(type: new () => T): T;
1032
+ /** Событие изменение выбранных записей. */
1033
+ onSelectionChange(selected: T[]): void;
1034
+ /** Обновление доступности кнопки "Изменить" - вызывается при изменении выбранных записей. */
1035
+ editBtnDisabledUpdate(selected: T[]): void;
1036
+ /** Обновление доступности кнопки "Удалить" - вызывается при изменении выбранных записей. */
1037
+ removeBtnDisabledUpdate(selected: T[]): void;
1038
+ /** Событие двойной клик. */
1039
+ onRowDoubleClicked(): void;
1040
+ /** Событие создание. */
1041
+ newEvent(): void;
1042
+ /** Событие редактирование. */
1043
+ editEvent(): void;
1044
+ /** Событие удаление. */
1045
+ removeEvent(): void;
1046
+ /** Событие обновления данных. */
1047
+ refreshEvent(): void;
1048
+ /** Событие очистки фильтра. */
1049
+ clearEvent(): void;
1050
+ /** Изменение сообщения об удалении. */
1051
+ onRemovalMessageChange(message: string): void;
1052
+ /** Изменение заголовка страницы. */
1053
+ onPageTitleChange(title: string): void;
1054
+ openDialog(entityComponent: any, data: IEditDialogData<T>, dialog: any): any;
1055
+ openDialogRemoveConfirm(removalMessage: string): MatDialogRef<DialogComponent> | undefined;
1056
+ protected onMiddleButton(baseUrl: string, queryParamName?: string, queryParamValue?: string): ($event: MouseEvent, item: T | undefined, contextMenu: MatMenuTrigger) => void;
1057
+ protected onActionMiddleButton(baseUrl: string, queryParamName?: string, queryParamValue?: string): ($event: MouseEvent, item: T | undefined) => void;
1058
+ protected dateToString(date: string | number | Date): string | null;
1059
+ static ɵfac: i0.ɵɵFactoryDeclaration<BaseSignalPageClass<any>, never>;
1060
+ static ɵdir: i0.ɵɵDirectiveDeclaration<BaseSignalPageClass<any>, never, never, {}, {}, never, never, true, never>;
1061
+ }
1062
+ export declare abstract class BaseSignalServiceClass<T extends BaseSchemaClass> {
1063
+ abstract baseRoute: string;
1064
+ abstract entityType: any;
1065
+ protected abstract readonly schema: z.ZodType<T>;
1066
+ protected countRoute: string;
1067
+ protected pageIndexParam: string;
1068
+ protected pageSizeParam: string;
1069
+ protected sortColumnParam: string;
1070
+ protected directionParam: string;
1071
+ protected apiContextName: string;
1072
+ protected http: HttpClient;
1073
+ private readonly _refreshTrigger;
1074
+ refresh(): void;
1075
+ getObjects(): HttpResourceRef<T[] | undefined>;
1076
+ getObject(id: number | (() => number)): HttpResourceRef<T | undefined>;
1077
+ getCount(): HttpResourceRef<number | undefined>;
1078
+ getObjectsByPaging(pageIndex: () => number, pageSize: () => number, sortColumn: () => string, direction: () => string): HttpResourceRef<T[] | undefined>;
1079
+ /**
1080
+ * МЕТОД СОЗДАНИЯ (POST)
1081
+ * Принимает данные БЕЗ id. Тип формируется автоматически через Zod.
1082
+ */
1083
+ newObject(entity: Omit<T, 'id'>): any;
1084
+ /**
1085
+ * Метод для СОЗДАНИЯ объекта (POST)
1086
+ * Тип аргумента генерируется автоматически: это ваш тип T, но БЕЗ поля id.
1087
+ */
1088
+ create(dto: Omit<T, 'id'>): HttpResourceRef<T | undefined>;
1089
+ editObject(entity: T): any;
1090
+ /**
1091
+ * Метод для ОБНОВЛЕНИЯ объекта (PUT / PATCH)
1092
+ * Принимает id и частичный объект (все свойства T становятся необязательными, кроме id)
1093
+ */
1094
+ update(id: number, dto: Partial<Omit<T, 'id'>>): HttpResourceRef<T | undefined>;
1095
+ /**
1096
+ * Метод DELETE (Переписанный под новую архитектуру)
1097
+ * Возвращает Observable. При подписке делает DELETE запрос,
1098
+ * а оператор 'tap' автоматически обновляет список getObjects() при успехе.
1099
+ */
1100
+ deleteObject(entity: T): any;
1101
+ protected getParams(pageIndex: number, pageSize: number, sortColumn: string, direction: string): HttpParams;
1102
+ protected getHttpContext(): {
1103
+ context?: HttpContext;
1104
+ };
1105
+ static ɵfac: i0.ɵɵFactoryDeclaration<BaseSignalServiceClass<any>, never>;
1106
+ static ɵprov: i0.ɵɵInjectableDeclaration<any>;
1107
+ }
844
1108
  export declare class DisableIfRoleDirective {
845
1109
  readonly forbiddenRoles: import("@angular/core").InputSignal<string[]>;
846
1110
  private readonly el;