@reformer/core 1.1.0 → 2.0.0-beta.11

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.
Files changed (221) hide show
  1. package/dist/behaviors/compute-from.d.ts +2 -0
  2. package/dist/behaviors/compute-from.js +31 -0
  3. package/dist/behaviors/copy-from.d.ts +2 -0
  4. package/dist/behaviors/copy-from.js +29 -0
  5. package/dist/behaviors/enable-when.d.ts +2 -0
  6. package/dist/behaviors/enable-when.js +25 -0
  7. package/dist/behaviors/reset-when.d.ts +2 -0
  8. package/dist/behaviors/reset-when.js +24 -0
  9. package/dist/behaviors/revalidate-when.d.ts +2 -0
  10. package/dist/behaviors/revalidate-when.js +18 -0
  11. package/dist/behaviors/sync-fields.d.ts +2 -0
  12. package/dist/behaviors/sync-fields.js +41 -0
  13. package/dist/behaviors/transform-value.d.ts +2 -0
  14. package/dist/behaviors/transform-value.js +45 -0
  15. package/dist/behaviors/watch-field.d.ts +2 -0
  16. package/dist/behaviors/watch-field.js +21 -0
  17. package/dist/behaviors.d.ts +6 -2
  18. package/dist/behaviors.js +27 -228
  19. package/dist/core/behavior/behavior-context.d.ts +32 -14
  20. package/dist/core/behavior/behavior-registry.d.ts +15 -27
  21. package/dist/core/behavior/behaviors/compute-from.d.ts +50 -21
  22. package/dist/core/behavior/behaviors/copy-from.d.ts +39 -14
  23. package/dist/core/behavior/behaviors/enable-when.d.ts +88 -19
  24. package/dist/core/behavior/behaviors/reset-when.d.ts +31 -18
  25. package/dist/core/behavior/behaviors/revalidate-when.d.ts +40 -17
  26. package/dist/core/behavior/behaviors/sync-fields.d.ts +34 -14
  27. package/dist/core/behavior/behaviors/transform-value.d.ts +116 -44
  28. package/dist/core/behavior/behaviors/watch-field.d.ts +66 -21
  29. package/dist/core/behavior/compose-behavior.d.ts +2 -12
  30. package/dist/core/behavior/index.d.ts +0 -1
  31. package/dist/core/behavior/types.d.ts +2 -8
  32. package/dist/core/factories/node-factory.d.ts +6 -29
  33. package/dist/core/nodes/array-node.d.ts +42 -22
  34. package/dist/core/nodes/field-node.d.ts +51 -26
  35. package/dist/core/nodes/form-node.d.ts +18 -20
  36. package/dist/core/nodes/group-node.d.ts +37 -212
  37. package/dist/core/types/deep-schema.d.ts +2 -12
  38. package/dist/core/types/field-path.d.ts +1 -1
  39. package/dist/core/types/form-context.d.ts +36 -30
  40. package/dist/core/types/{group-node-proxy.d.ts → form-proxy.d.ts} +12 -42
  41. package/dist/core/types/index.d.ts +52 -6
  42. package/dist/core/types/validation-schema.d.ts +3 -12
  43. package/dist/core/utils/abstract-registry.d.ts +74 -0
  44. package/dist/core/utils/aggregate-signals.d.ts +71 -0
  45. package/dist/core/utils/create-form.d.ts +3 -20
  46. package/dist/core/utils/error-handler.d.ts +1 -18
  47. package/dist/core/utils/field-path-navigator.d.ts +1 -1
  48. package/dist/core/{validation → utils}/field-path.d.ts +23 -6
  49. package/dist/core/utils/form-observer.d.ts +176 -0
  50. package/dist/core/utils/form-proxy-builder.d.ts +25 -0
  51. package/dist/core/utils/form-submitter.d.ts +121 -0
  52. package/dist/core/utils/index.d.ts +10 -2
  53. package/dist/core/utils/registry-helpers.d.ts +0 -7
  54. package/dist/core/utils/safe-effect.d.ts +73 -0
  55. package/dist/core/utils/status-machine.d.ts +153 -0
  56. package/dist/core/utils/type-guards.d.ts +5 -23
  57. package/dist/core/utils/unique-id.d.ts +53 -0
  58. package/dist/core/validation/core/apply-when.d.ts +3 -9
  59. package/dist/core/validation/core/apply.d.ts +2 -13
  60. package/dist/core/validation/core/validate-async.d.ts +2 -8
  61. package/dist/core/validation/core/validate-tree.d.ts +10 -10
  62. package/dist/core/validation/core/validate.d.ts +1 -7
  63. package/dist/core/validation/index.d.ts +8 -2
  64. package/dist/core/validation/validate-form.d.ts +1 -38
  65. package/dist/core/validation/validation-applicator.d.ts +2 -21
  66. package/dist/core/validation/validation-context.d.ts +67 -28
  67. package/dist/core/validation/validation-registry.d.ts +11 -25
  68. package/dist/core/validation/validators/array-validators.d.ts +2 -12
  69. package/dist/core/validation/validators/date-utils.d.ts +26 -0
  70. package/dist/core/validation/validators/email.d.ts +2 -9
  71. package/dist/core/validation/validators/future-date.d.ts +35 -0
  72. package/dist/core/validation/validators/index.d.ts +7 -1
  73. package/dist/core/validation/validators/is-date.d.ts +36 -0
  74. package/dist/core/validation/validators/max-age.d.ts +36 -0
  75. package/dist/core/validation/validators/max-date.d.ts +36 -0
  76. package/dist/core/validation/validators/max-length.d.ts +3 -10
  77. package/dist/core/validation/validators/max.d.ts +3 -10
  78. package/dist/core/validation/validators/min-age.d.ts +36 -0
  79. package/dist/core/validation/validators/min-date.d.ts +36 -0
  80. package/dist/core/validation/validators/min-length.d.ts +3 -10
  81. package/dist/core/validation/validators/min.d.ts +3 -10
  82. package/dist/core/validation/validators/number.d.ts +2 -9
  83. package/dist/core/validation/validators/past-date.d.ts +35 -0
  84. package/dist/core/validation/validators/pattern.d.ts +2 -9
  85. package/dist/core/validation/validators/phone.d.ts +2 -9
  86. package/dist/core/validation/validators/required.d.ts +2 -9
  87. package/dist/core/validation/validators/url.d.ts +2 -9
  88. package/dist/date-utils-xUWFslTj.js +29 -0
  89. package/dist/field-path-DuKdGcIE.js +66 -0
  90. package/dist/hooks/types.d.ts +328 -0
  91. package/dist/hooks/useArrayLength.d.ts +31 -0
  92. package/dist/hooks/useFormControl.d.ts +15 -39
  93. package/dist/hooks/useFormControlValue.d.ts +167 -0
  94. package/dist/hooks/useHiddenCondition.d.ts +25 -0
  95. package/dist/hooks/useSignalSubscription.d.ts +17 -0
  96. package/dist/index-D25LsbRm.js +73 -0
  97. package/dist/index.d.ts +8 -1
  98. package/dist/index.js +3271 -8
  99. package/dist/registry-helpers-Bv_BJ1s-.js +615 -0
  100. package/dist/safe-effect-Dh8uw81c.js +20 -0
  101. package/dist/validate-C3XiA_zf.js +10 -0
  102. package/dist/validators/email.d.ts +2 -0
  103. package/dist/validators/email.js +13 -0
  104. package/dist/validators/future-date.d.ts +2 -0
  105. package/dist/validators/future-date.js +20 -0
  106. package/dist/validators/is-date.d.ts +2 -0
  107. package/dist/validators/is-date.js +12 -0
  108. package/dist/validators/max-age.d.ts +2 -0
  109. package/dist/validators/max-age.js +20 -0
  110. package/dist/validators/max-date.d.ts +2 -0
  111. package/dist/validators/max-date.js +20 -0
  112. package/dist/validators/max-length.d.ts +2 -0
  113. package/dist/validators/max-length.js +11 -0
  114. package/dist/validators/max.d.ts +2 -0
  115. package/dist/validators/max.js +11 -0
  116. package/dist/validators/min-age.d.ts +2 -0
  117. package/dist/validators/min-age.js +20 -0
  118. package/dist/validators/min-date.d.ts +2 -0
  119. package/dist/validators/min-date.js +20 -0
  120. package/dist/validators/min-length.d.ts +2 -0
  121. package/dist/validators/min-length.js +11 -0
  122. package/dist/validators/min.d.ts +2 -0
  123. package/dist/validators/min.js +11 -0
  124. package/dist/validators/number.d.ts +2 -0
  125. package/dist/validators/number.js +35 -0
  126. package/dist/validators/past-date.d.ts +2 -0
  127. package/dist/validators/past-date.js +20 -0
  128. package/dist/validators/pattern.d.ts +2 -0
  129. package/dist/validators/pattern.js +11 -0
  130. package/dist/validators/phone.d.ts +2 -0
  131. package/dist/validators/phone.js +35 -0
  132. package/dist/validators/required.d.ts +2 -0
  133. package/dist/validators/required.js +15 -0
  134. package/dist/validators/url.d.ts +2 -0
  135. package/dist/validators/url.js +19 -0
  136. package/dist/validators-BGsNOgT1.js +207 -0
  137. package/dist/validators.d.ts +6 -2
  138. package/dist/validators.js +54 -296
  139. package/llms.txt +8887 -59
  140. package/package.json +87 -8
  141. package/dist/core/behavior/behavior-applicator.d.ts +0 -71
  142. package/dist/core/behavior/behavior-applicator.js +0 -92
  143. package/dist/core/behavior/behavior-context.js +0 -38
  144. package/dist/core/behavior/behavior-registry.js +0 -198
  145. package/dist/core/behavior/behaviors/compute-from.js +0 -84
  146. package/dist/core/behavior/behaviors/copy-from.js +0 -64
  147. package/dist/core/behavior/behaviors/enable-when.js +0 -81
  148. package/dist/core/behavior/behaviors/index.js +0 -11
  149. package/dist/core/behavior/behaviors/reset-when.js +0 -63
  150. package/dist/core/behavior/behaviors/revalidate-when.js +0 -51
  151. package/dist/core/behavior/behaviors/sync-fields.js +0 -66
  152. package/dist/core/behavior/behaviors/transform-value.js +0 -110
  153. package/dist/core/behavior/behaviors/watch-field.js +0 -56
  154. package/dist/core/behavior/compose-behavior.js +0 -166
  155. package/dist/core/behavior/create-field-path.d.ts +0 -20
  156. package/dist/core/behavior/create-field-path.js +0 -69
  157. package/dist/core/behavior/index.js +0 -17
  158. package/dist/core/behavior/types.js +0 -7
  159. package/dist/core/context/form-context-impl.d.ts +0 -29
  160. package/dist/core/context/form-context-impl.js +0 -37
  161. package/dist/core/factories/index.js +0 -6
  162. package/dist/core/factories/node-factory.js +0 -281
  163. package/dist/core/nodes/array-node.js +0 -534
  164. package/dist/core/nodes/field-node.js +0 -510
  165. package/dist/core/nodes/form-node.js +0 -343
  166. package/dist/core/nodes/group-node/field-registry.d.ts +0 -191
  167. package/dist/core/nodes/group-node/field-registry.js +0 -215
  168. package/dist/core/nodes/group-node/index.d.ts +0 -11
  169. package/dist/core/nodes/group-node/index.js +0 -11
  170. package/dist/core/nodes/group-node/proxy-builder.d.ts +0 -71
  171. package/dist/core/nodes/group-node/proxy-builder.js +0 -161
  172. package/dist/core/nodes/group-node/state-manager.d.ts +0 -184
  173. package/dist/core/nodes/group-node/state-manager.js +0 -265
  174. package/dist/core/nodes/group-node.js +0 -770
  175. package/dist/core/types/deep-schema.js +0 -11
  176. package/dist/core/types/field-path.js +0 -4
  177. package/dist/core/types/form-context.js +0 -25
  178. package/dist/core/types/group-node-proxy.js +0 -31
  179. package/dist/core/types/index.js +0 -4
  180. package/dist/core/types/validation-schema.js +0 -10
  181. package/dist/core/utils/create-form.js +0 -24
  182. package/dist/core/utils/debounce.d.ts +0 -160
  183. package/dist/core/utils/debounce.js +0 -197
  184. package/dist/core/utils/error-handler.js +0 -226
  185. package/dist/core/utils/field-path-navigator.js +0 -374
  186. package/dist/core/utils/index.js +0 -14
  187. package/dist/core/utils/registry-helpers.js +0 -79
  188. package/dist/core/utils/registry-stack.js +0 -86
  189. package/dist/core/utils/resources.d.ts +0 -41
  190. package/dist/core/utils/resources.js +0 -69
  191. package/dist/core/utils/subscription-manager.js +0 -214
  192. package/dist/core/utils/type-guards.js +0 -169
  193. package/dist/core/validation/core/apply-when.js +0 -41
  194. package/dist/core/validation/core/apply.js +0 -38
  195. package/dist/core/validation/core/index.js +0 -8
  196. package/dist/core/validation/core/validate-async.js +0 -45
  197. package/dist/core/validation/core/validate-tree.js +0 -37
  198. package/dist/core/validation/core/validate.js +0 -38
  199. package/dist/core/validation/field-path.js +0 -147
  200. package/dist/core/validation/index.js +0 -33
  201. package/dist/core/validation/validate-form.js +0 -152
  202. package/dist/core/validation/validation-applicator.js +0 -217
  203. package/dist/core/validation/validation-context.js +0 -75
  204. package/dist/core/validation/validation-registry.js +0 -298
  205. package/dist/core/validation/validators/array-validators.js +0 -86
  206. package/dist/core/validation/validators/date.d.ts +0 -38
  207. package/dist/core/validation/validators/date.js +0 -117
  208. package/dist/core/validation/validators/email.js +0 -60
  209. package/dist/core/validation/validators/index.js +0 -14
  210. package/dist/core/validation/validators/max-length.js +0 -60
  211. package/dist/core/validation/validators/max.js +0 -60
  212. package/dist/core/validation/validators/min-length.js +0 -60
  213. package/dist/core/validation/validators/min.js +0 -60
  214. package/dist/core/validation/validators/number.js +0 -90
  215. package/dist/core/validation/validators/pattern.js +0 -62
  216. package/dist/core/validation/validators/phone.js +0 -58
  217. package/dist/core/validation/validators/required.js +0 -69
  218. package/dist/core/validation/validators/url.js +0 -55
  219. package/dist/create-field-path-CdPF3lIK.js +0 -704
  220. package/dist/hooks/useFormControl.js +0 -298
  221. package/dist/node-factory-D7DOnSSN.js +0 -3200
@@ -1,3 +1,7 @@
1
+ import { BehaviorSchemaFn } from '../behavior/types';
2
+ import { FormSchema } from './deep-schema';
3
+ import { ValidationSchemaFn } from './validation-schema';
4
+ import { FormNode } from '../nodes/form-node';
1
5
  /**
2
6
  * Represents any valid form value type
3
7
  * Use this instead of 'any' for form values to maintain type safety
@@ -20,12 +24,46 @@ export type UnknownFormValue = unknown;
20
24
  * @category Validation Types
21
25
  */
22
26
  export type ValidatorFn<T = FormValue> = (value: T) => ValidationError | null;
27
+ /**
28
+ * Опции для асинхронного валидатора
29
+ * @group Types
30
+ * @category Validation Types
31
+ */
32
+ export interface AsyncValidatorOptions {
33
+ /**
34
+ * AbortSignal для отмены валидации
35
+ * Позволяет отменить асинхронную операцию при новой валидации
36
+ */
37
+ signal?: AbortSignal;
38
+ }
23
39
  /**
24
40
  * Асинхронная функция валидации
41
+ *
42
+ * @param value - Значение для валидации
43
+ * @param options - Опции валидации (опционально)
44
+ * @returns Promise с ошибкой валидации или null если значение валидно
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * // Простой валидатор (без поддержки отмены)
49
+ * const emailExists: AsyncValidatorFn<string> = async (value) => {
50
+ * const exists = await checkEmail(value);
51
+ * return exists ? { code: 'exists', message: 'Email already exists' } : null;
52
+ * };
53
+ *
54
+ * // Валидатор с поддержкой отмены
55
+ * const emailExistsAbortable: AsyncValidatorFn<string> = async (value, options) => {
56
+ * const exists = await fetch(`/api/check-email?email=${value}`, {
57
+ * signal: options?.signal // Передаём signal в fetch для отмены запроса
58
+ * });
59
+ * return exists ? { code: 'exists', message: 'Email already exists' } : null;
60
+ * };
61
+ * ```
62
+ *
25
63
  * @group Types
26
64
  * @category Validation Types
27
65
  */
28
- export type AsyncValidatorFn<T = FormValue> = (value: T) => Promise<ValidationError | null>;
66
+ export type AsyncValidatorFn<T = FormValue> = (value: T, options?: AsyncValidatorOptions) => Promise<ValidationError | null>;
29
67
  /**
30
68
  * Ошибка валидации
31
69
  * @group Types
@@ -64,10 +102,7 @@ export type { FieldPath, FieldPathNode } from '../types/field-path';
64
102
  export type { ContextualValidatorFn, ContextualAsyncValidatorFn, TreeValidatorFn, ConditionFn, ValidateOptions, ValidateAsyncOptions, ValidateTreeOptions, ValidationSchemaFn, ValidatorRegistration, } from './validation-schema';
65
103
  export type { FormSchema, ArrayConfig } from './deep-schema';
66
104
  export type { FormContext } from './form-context';
67
- export type { FormNodeControls, GroupNodeWithControls, ArrayNodeWithControls, } from './group-node-proxy';
68
- import type { BehaviorSchemaFn } from '../behavior/types';
69
- import type { FormSchema } from './deep-schema';
70
- import type { ValidationSchemaFn } from './validation-schema';
105
+ export type { FormControlsProxy, FormProxy, FormArrayProxy } from './form-proxy';
71
106
  /**
72
107
  * Конфигурация GroupNode с поддержкой схем
73
108
  * Используется для создания форм с автоматическим применением behavior и validation схем
@@ -82,6 +117,18 @@ export interface GroupNodeConfig<T> {
82
117
  behavior?: BehaviorSchemaFn<T>;
83
118
  /** Схема валидации (required, email, minLength и т.д.) */
84
119
  validation?: ValidationSchemaFn<T>;
120
+ /**
121
+ * Опциональный ValidationRegistry для dependency injection
122
+ * Используется для тестирования с mock-реестрами
123
+ * @internal
124
+ */
125
+ _validationRegistry?: unknown;
126
+ /**
127
+ * Опциональный BehaviorRegistry для dependency injection
128
+ * Используется для тестирования с mock-реестрами
129
+ * @internal
130
+ */
131
+ _behaviorRegistry?: unknown;
85
132
  }
86
133
  /**
87
134
  * Тип для Record с unknown значениями
@@ -112,7 +159,6 @@ export interface ArrayNodeLike {
112
159
  at(index: number): FormNode<unknown> | undefined;
113
160
  length: unknown;
114
161
  }
115
- import type { FormNode } from '../nodes/form-node';
116
162
  /**
117
163
  * Конфиг с полем schema (для ArrayConfig)
118
164
  * @internal
@@ -1,15 +1,6 @@
1
- /**
2
- * Типы для validation schema паттерна
3
- *
4
- * Основано на Angular Signal Forms подходе:
5
- * - Валидация определяется отдельно от схемы полей
6
- * - Поддержка условной валидации (applyWhen)
7
- * - Cross-field валидация (validateTree)
8
- * - Асинхронная валидация с контекстом
9
- */
10
- import type { FormFields, ValidationError } from './index';
11
- import type { FieldPath } from './field-path';
12
- import type { FormContext } from './form-context';
1
+ import { FormFields, ValidationError } from './index';
2
+ import { FieldPath } from './field-path';
3
+ import { FormContext } from './form-context';
13
4
  /**
14
5
  * Функция валидации поля с контекстом
15
6
  *
@@ -0,0 +1,74 @@
1
+ import { RegistryStack } from './registry-stack';
2
+ /**
3
+ * Базовый класс для реестров (BehaviorRegistry, ValidationRegistry).
4
+ *
5
+ * Реализует паттерн Template Method для управления регистрацией:
6
+ * `beginRegistration()` → `onBeginRegistration()`, `endRegistration()` → `onEndRegistration()`.
7
+ *
8
+ * @typeParam TRegistration - Тип регистрируемых элементов.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { AbstractRegistry } from '@reformer/core';
13
+ *
14
+ * class MyRegistry extends AbstractRegistry<{ name: string }> {
15
+ * protected onEndRegistration(items: { name: string }[]) {
16
+ * console.log('Registered', items.length);
17
+ * }
18
+ * }
19
+ * ```
20
+ */
21
+ export declare abstract class AbstractRegistry<TRegistration> {
22
+ /** Флаг активной регистрации */
23
+ protected isRegistering: boolean;
24
+ /** Массив зарегистрированных элементов */
25
+ protected registrations: TRegistration[];
26
+ /**
27
+ * Получить стек для конкретного класса реестра
28
+ * Создает новый стек если не существует
29
+ *
30
+ * @param ctor - Конструктор класса реестра
31
+ * @returns RegistryStack для данного класса
32
+ */
33
+ protected static getStack<T extends AbstractRegistry<any>>(ctor: new (...args: any[]) => T): RegistryStack<T>;
34
+ /**
35
+ * Получить текущий активный реестр из стека
36
+ * Должен быть переопределен в наследниках как static метод
37
+ *
38
+ * @param ctor - Конструктор класса реестра
39
+ * @returns Текущий активный реестр или null
40
+ */
41
+ protected static getCurrentFromStack<T extends AbstractRegistry<any>>(ctor: new (...args: any[]) => T): T | null;
42
+ /**
43
+ * Начать регистрацию
44
+ *
45
+ * Помещает this в global stack для изоляции форм
46
+ * Вызывает hook onBeginRegistration()
47
+ */
48
+ beginRegistration(): void;
49
+ /**
50
+ * Проверить, активна ли регистрация
51
+ */
52
+ isActive(): boolean;
53
+ /**
54
+ * Получить зарегистрированные элементы
55
+ */
56
+ getRegistrations(): TRegistration[];
57
+ /**
58
+ * Hook: вызывается в начале регистрации
59
+ * Может быть переопределен в наследниках для инициализации
60
+ */
61
+ protected onBeginRegistration(): void;
62
+ /**
63
+ * Завершить регистрацию и извлечь из стека
64
+ *
65
+ * @param registryName - Имя реестра для отладки
66
+ */
67
+ protected completeRegistration(registryName: string): void;
68
+ /**
69
+ * Отменить регистрацию без применения
70
+ *
71
+ * @param registryName - Имя реестра для отладки
72
+ */
73
+ cancelRegistration(registryName: string): void;
74
+ }
@@ -0,0 +1,71 @@
1
+ import { ReadonlySignal, Signal } from '@preact/signals-core';
2
+ import { FieldStatus, ValidationError } from '../types';
3
+ import { FormNode } from '../nodes/form-node';
4
+ /**
5
+ * Функция получения дочерних узлов
6
+ * Возвращает массив FormNode для агрегации состояния
7
+ */
8
+ type GetChildrenFn<T> = () => FormNode<T>[];
9
+ /**
10
+ * Результат создания агрегированных сигналов
11
+ */
12
+ export interface AggregateSignals {
13
+ /** Все дочерние узлы валидны и нет собственных ошибок */
14
+ valid: ReadonlySignal<boolean>;
15
+ /** Есть ошибки (инверсия valid) */
16
+ invalid: ReadonlySignal<boolean>;
17
+ /** Хотя бы один дочерний узел в состоянии pending */
18
+ pending: ReadonlySignal<boolean>;
19
+ /** Хотя бы один дочерний узел touched */
20
+ touched: ReadonlySignal<boolean>;
21
+ /** Хотя бы один дочерний узел dirty */
22
+ dirty: ReadonlySignal<boolean>;
23
+ /** Собственные ошибки + ошибки всех дочерних узлов */
24
+ errors: ReadonlySignal<ValidationError[]>;
25
+ /** Статус: disabled > pending > invalid > valid */
26
+ status: ReadonlySignal<FieldStatus>;
27
+ }
28
+ /**
29
+ * Опции для создания агрегированных сигналов
30
+ */
31
+ export interface AggregateSignalsOptions<T> {
32
+ /** Функция получения дочерних узлов */
33
+ getChildren: GetChildrenFn<T>;
34
+ /** Signal с собственными ошибками контейнера (form-level или array-level) */
35
+ ownErrors: Signal<ValidationError[]>;
36
+ /** Опциональный signal disabled состояния (для GroupNode) */
37
+ disabled?: Signal<boolean>;
38
+ }
39
+ /**
40
+ * Создать агрегированные computed signals для контейнерного узла
41
+ *
42
+ * Используется в GroupNode и ArrayNode для унификации логики
43
+ * вычисления состояния на основе дочерних узлов.
44
+ *
45
+ * @param options - Опции конфигурации
46
+ * @returns Объект с computed signals
47
+ *
48
+ * @example GroupNode
49
+ * ```typescript
50
+ * const signals = createAggregateSignals({
51
+ * getChildren: () => Array.from(this._fields.values()),
52
+ * ownErrors: this._formErrors,
53
+ * disabled: this._disabled,
54
+ * });
55
+ * this.valid = signals.valid;
56
+ * this.invalid = signals.invalid;
57
+ * // ...
58
+ * ```
59
+ *
60
+ * @example ArrayNode
61
+ * ```typescript
62
+ * const signals = createAggregateSignals({
63
+ * getChildren: () => this.items.value,
64
+ * ownErrors: this._arrayErrors,
65
+ * });
66
+ * this.valid = signals.valid;
67
+ * // ...
68
+ * ```
69
+ */
70
+ export declare function createAggregateSignals<T>(options: AggregateSignalsOptions<T>): AggregateSignals;
71
+ export {};
@@ -1,21 +1,4 @@
1
- /**
2
- * Фабричная функция для создания формы с правильной типизацией
3
- *
4
- * Решает проблему с типизацией конструктора GroupNode, который возвращает
5
- * Proxy (GroupNodeWithControls), но TypeScript не может это вывести автоматически.
6
- *
7
- * @group Utilities
8
- *
9
- * @example
10
- * ```typescript
11
- * // Вместо:
12
- * const form: GroupNodeWithControls<MyForm> = new GroupNode<MyForm>(config);
13
- *
14
- * // Используйте:
15
- * const form = createForm<MyForm>(config);
16
- * ```
17
- */
18
- import type { GroupNodeWithControls, GroupNodeConfig, FormSchema } from '../types';
1
+ import { FormProxy, GroupNodeConfig, FormSchema } from '../types';
19
2
  /**
20
3
  * Создать форму с полной конфигурацией (form, behavior, validation)
21
4
  *
@@ -43,7 +26,7 @@ import type { GroupNodeWithControls, GroupNodeConfig, FormSchema } from '../type
43
26
  * form.email.setValue('test@mail.com');
44
27
  * ```
45
28
  */
46
- export declare function createForm<T>(config: GroupNodeConfig<T>): GroupNodeWithControls<T>;
29
+ export declare function createForm<T>(config: GroupNodeConfig<T>): FormProxy<T>;
47
30
  /**
48
31
  * Создать форму только со схемой полей (обратная совместимость)
49
32
  *
@@ -58,4 +41,4 @@ export declare function createForm<T>(config: GroupNodeConfig<T>): GroupNodeWith
58
41
  * });
59
42
  * ```
60
43
  */
61
- export declare function createForm<T>(schema: FormSchema<T>): GroupNodeWithControls<T>;
44
+ export declare function createForm<T>(schema: FormSchema<T>): FormProxy<T>;
@@ -1,21 +1,4 @@
1
- /**
2
- * FormErrorHandler - централизованная обработка ошибок в формах
3
- *
4
- * Устраняет несогласованность обработки ошибок между:
5
- * - field-node.ts (логирует и конвертирует в ValidationError)
6
- * - behavior-applicator.ts (логирует и пробрасывает)
7
- * - validation-applicator.ts (логирует и проглатывает)
8
- *
9
- * @example
10
- * ```typescript
11
- * try {
12
- * await validator(value);
13
- * } catch (error) {
14
- * return FormErrorHandler.handle(error, 'AsyncValidator', ErrorStrategy.CONVERT);
15
- * }
16
- * ```
17
- */
18
- import type { ValidationError } from '../types';
1
+ import { ValidationError } from '../types';
19
2
  /**
20
3
  * Стратегия обработки ошибок
21
4
  *
@@ -1,4 +1,4 @@
1
- import type { UnknownRecord } from '../types';
1
+ import { UnknownRecord } from '../types';
2
2
  /**
3
3
  * Сегмент пути к полю формы
4
4
  *
@@ -1,7 +1,4 @@
1
- /**
2
- * FieldPath proxy - типобезопасный доступ к путям полей формы
3
- */
4
- import type { FieldPath, FieldPathNode } from '../types';
1
+ import { FieldPath, FieldPathNode } from '../types';
5
2
  /**
6
3
  * Создать FieldPath proxy для формы
7
4
  *
@@ -14,7 +11,17 @@ import type { FieldPath, FieldPathNode } from '../types';
14
11
  */
15
12
  export declare function createFieldPath<T>(): FieldPath<T>;
16
13
  /**
17
- * Извлечь путь из FieldPathNode
14
+ * Извлечь строковый путь из {@link FieldPathNode}.
15
+ *
16
+ * @param node - Узел `FieldPathNode` либо строка-путь.
17
+ * @returns Путь вида `"a.b.c"`.
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * import { extractPath } from '@reformer/core';
22
+ *
23
+ * const path = (renderPath) => extractPath(renderPath.user.email); // → 'user.email'
24
+ * ```
18
25
  */
19
26
  export declare function extractPath(node: FieldPathNode<unknown, unknown> | unknown): string;
20
27
  /**
@@ -38,6 +45,16 @@ export declare function extractPath(node: FieldPathNode<unknown, unknown> | unkn
38
45
  */
39
46
  export declare function toFieldPath<T>(node: FieldPathNode<unknown, T, never> | FieldPathNode<any, T, any>): FieldPath<T>;
40
47
  /**
41
- * Извлечь ключ поля из FieldPathNode
48
+ * Извлечь имя последнего сегмента ({@link FieldPathSegment}) пути.
49
+ *
50
+ * @param node - Узел `FieldPathNode` либо строка-путь.
51
+ * @returns Имя поля без префикса родителя (последний сегмент).
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * import { extractKey } from '@reformer/core';
56
+ *
57
+ * extractKey(path.user.email); // → 'email'
58
+ * ```
42
59
  */
43
60
  export declare function extractKey(node: FieldPathNode<unknown, unknown> | unknown): string;
@@ -0,0 +1,176 @@
1
+ import { FormFields, FormValue, FieldStatus, ValidationError } from '../types';
2
+ /**
3
+ * Тип события изменения в форме
4
+ */
5
+ export type FormChangeType = 'value' | 'status' | 'errors' | 'touched' | 'dirty';
6
+ /**
7
+ * Событие изменения в форме
8
+ */
9
+ export interface FormChangeEvent {
10
+ /** Тип изменения */
11
+ type: FormChangeType;
12
+ /** Путь к полю */
13
+ path: string;
14
+ /** Timestamp события */
15
+ timestamp: number;
16
+ /** Старое значение */
17
+ oldValue?: unknown;
18
+ /** Новое значение */
19
+ newValue: unknown;
20
+ }
21
+ /**
22
+ * Интерфейс узла формы для observer
23
+ */
24
+ export interface ObservableFormNode {
25
+ value: {
26
+ value: FormValue;
27
+ };
28
+ status: {
29
+ value: FieldStatus;
30
+ };
31
+ errors: {
32
+ value: ValidationError[];
33
+ };
34
+ touched: {
35
+ value: boolean;
36
+ };
37
+ dirty: {
38
+ value: boolean;
39
+ };
40
+ }
41
+ /**
42
+ * Интерфейс формы для observer
43
+ */
44
+ export interface ObservableForm<T extends FormFields> {
45
+ value: {
46
+ value: T;
47
+ };
48
+ status: {
49
+ value: FieldStatus;
50
+ };
51
+ errors: {
52
+ value: ValidationError[];
53
+ };
54
+ touched: {
55
+ value: boolean;
56
+ };
57
+ dirty: {
58
+ value: boolean;
59
+ };
60
+ getFieldByPath(path: string): ObservableFormNode | undefined;
61
+ }
62
+ /**
63
+ * Callback для обработки событий изменения
64
+ */
65
+ export type FormChangeCallback = (event: FormChangeEvent) => void;
66
+ /**
67
+ * Опции для FormObserver
68
+ */
69
+ export interface FormObserverOptions {
70
+ /** Включить логирование в консоль (по умолчанию true в DEV) */
71
+ enableLogging?: boolean;
72
+ /** Фильтр типов событий */
73
+ eventTypes?: FormChangeType[];
74
+ /** Фильтр путей полей (regex или массив) */
75
+ pathFilter?: RegExp | string[];
76
+ }
77
+ /**
78
+ * FormObserver - мониторинг изменений в форме
79
+ *
80
+ * Полезен для:
81
+ * - Отладки сложных форм
82
+ * - Логирования изменений для аудита
83
+ * - Синхронизации с внешними системами
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * const observer = new FormObserver(form, {
88
+ * enableLogging: true,
89
+ * eventTypes: ['value', 'errors']
90
+ * });
91
+ *
92
+ * // Подписка на события
93
+ * const unsubscribe = observer.subscribe((event) => {
94
+ * console.log(`${event.type} at ${event.path}:`, event.newValue);
95
+ * });
96
+ *
97
+ * // Включить трассировку
98
+ * const disposeTracing = observer.enableTracing();
99
+ *
100
+ * // Cleanup
101
+ * unsubscribe();
102
+ * disposeTracing();
103
+ * ```
104
+ */
105
+ export declare class FormObserver<T extends FormFields> {
106
+ private readonly form;
107
+ private listeners;
108
+ private disposers;
109
+ private options;
110
+ /**
111
+ * @param form - Форма для наблюдения
112
+ * @param options - Опции observer
113
+ */
114
+ constructor(form: ObservableForm<T>, options?: FormObserverOptions);
115
+ /**
116
+ * Подписаться на события изменения
117
+ *
118
+ * @param callback - Функция обработки события
119
+ * @returns Функция отписки
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * const unsubscribe = observer.subscribe((event) => {
124
+ * // Отправить событие в analytics
125
+ * analytics.track('form_change', event);
126
+ * });
127
+ * ```
128
+ */
129
+ subscribe(callback: FormChangeCallback): () => void;
130
+ /**
131
+ * Включить трассировку формы
132
+ *
133
+ * Подписывается на изменения основных сигналов формы
134
+ * и вызывает listeners при каждом изменении
135
+ *
136
+ * @returns Функция для отключения трассировки
137
+ *
138
+ * @example
139
+ * ```typescript
140
+ * const dispose = observer.enableTracing();
141
+ *
142
+ * // Позже, для отключения
143
+ * dispose();
144
+ * ```
145
+ */
146
+ enableTracing(): () => void;
147
+ /**
148
+ * Наблюдать за конкретным полем
149
+ *
150
+ * @param path - Путь к полю
151
+ * @returns Функция для отключения наблюдения
152
+ *
153
+ * @example
154
+ * ```typescript
155
+ * // Наблюдать за полем email
156
+ * const dispose = observer.watchField('email');
157
+ * ```
158
+ */
159
+ watchField(path: string): () => void;
160
+ /**
161
+ * Отправить событие всем listeners
162
+ */
163
+ private emit;
164
+ /**
165
+ * Проверить, нужно ли отслеживать тип события
166
+ */
167
+ private shouldTrack;
168
+ /**
169
+ * Проверить, соответствует ли путь фильтру
170
+ */
171
+ private matchesPathFilter;
172
+ /**
173
+ * Очистить все подписки и disposers
174
+ */
175
+ dispose(): void;
176
+ }
@@ -0,0 +1,25 @@
1
+ import { FormNode } from '../nodes/form-node';
2
+ import { FormProxy } from '../types/form-proxy';
3
+ /**
4
+ * Создать Proxy для типобезопасного доступа к полям GroupNode
5
+ *
6
+ * Proxy обеспечивает:
7
+ * - Доступ к полям через точечную нотацию (form.email, form.address.city)
8
+ * - Приоритет собственных свойств GroupNode над полями
9
+ * - Цепочку proxy для вложенных GroupNode
10
+ * - Блокировку прямого присваивания полям (только через setValue/patchValue)
11
+ *
12
+ * @param target - GroupNode для которого создаётся proxy
13
+ * @param fields - Map полей формы
14
+ * @returns Типизированный Proxy
15
+ *
16
+ * @internal
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * const proxy = buildFormProxy(groupNode, groupNode._fields);
21
+ * proxy.email.setValue('test@example.com');
22
+ * console.log(proxy.email.value.value);
23
+ * ```
24
+ */
25
+ export declare function buildFormProxy<T>(target: FormNode<T>, fields: Map<keyof T, FormNode<unknown>>): FormProxy<T>;