@reformer/core 1.0.0-beta.3

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 (150) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +53 -0
  3. package/dist/behaviors.d.ts +2 -0
  4. package/dist/behaviors.js +230 -0
  5. package/dist/core/behavior/behavior-applicator.d.ts +71 -0
  6. package/dist/core/behavior/behavior-applicator.js +92 -0
  7. package/dist/core/behavior/behavior-context.d.ts +29 -0
  8. package/dist/core/behavior/behavior-context.js +38 -0
  9. package/dist/core/behavior/behavior-registry.d.ts +97 -0
  10. package/dist/core/behavior/behavior-registry.js +198 -0
  11. package/dist/core/behavior/behaviors/compute-from.d.ts +41 -0
  12. package/dist/core/behavior/behaviors/compute-from.js +84 -0
  13. package/dist/core/behavior/behaviors/copy-from.d.ts +31 -0
  14. package/dist/core/behavior/behaviors/copy-from.js +64 -0
  15. package/dist/core/behavior/behaviors/enable-when.d.ts +49 -0
  16. package/dist/core/behavior/behaviors/enable-when.js +81 -0
  17. package/dist/core/behavior/behaviors/index.d.ts +11 -0
  18. package/dist/core/behavior/behaviors/index.js +11 -0
  19. package/dist/core/behavior/behaviors/reset-when.d.ts +51 -0
  20. package/dist/core/behavior/behaviors/reset-when.js +63 -0
  21. package/dist/core/behavior/behaviors/revalidate-when.d.ts +30 -0
  22. package/dist/core/behavior/behaviors/revalidate-when.js +51 -0
  23. package/dist/core/behavior/behaviors/sync-fields.d.ts +28 -0
  24. package/dist/core/behavior/behaviors/sync-fields.js +66 -0
  25. package/dist/core/behavior/behaviors/transform-value.d.ts +120 -0
  26. package/dist/core/behavior/behaviors/transform-value.js +110 -0
  27. package/dist/core/behavior/behaviors/watch-field.d.ts +35 -0
  28. package/dist/core/behavior/behaviors/watch-field.js +56 -0
  29. package/dist/core/behavior/compose-behavior.d.ts +106 -0
  30. package/dist/core/behavior/compose-behavior.js +166 -0
  31. package/dist/core/behavior/create-field-path.d.ts +20 -0
  32. package/dist/core/behavior/create-field-path.js +69 -0
  33. package/dist/core/behavior/index.d.ts +12 -0
  34. package/dist/core/behavior/index.js +17 -0
  35. package/dist/core/behavior/types.d.ts +152 -0
  36. package/dist/core/behavior/types.js +7 -0
  37. package/dist/core/context/form-context-impl.d.ts +29 -0
  38. package/dist/core/context/form-context-impl.js +37 -0
  39. package/dist/core/factories/index.d.ts +6 -0
  40. package/dist/core/factories/index.js +6 -0
  41. package/dist/core/factories/node-factory.d.ts +209 -0
  42. package/dist/core/factories/node-factory.js +281 -0
  43. package/dist/core/nodes/array-node.d.ts +308 -0
  44. package/dist/core/nodes/array-node.js +534 -0
  45. package/dist/core/nodes/field-node.d.ts +269 -0
  46. package/dist/core/nodes/field-node.js +510 -0
  47. package/dist/core/nodes/form-node.d.ts +342 -0
  48. package/dist/core/nodes/form-node.js +343 -0
  49. package/dist/core/nodes/group-node/field-registry.d.ts +191 -0
  50. package/dist/core/nodes/group-node/field-registry.js +215 -0
  51. package/dist/core/nodes/group-node/index.d.ts +11 -0
  52. package/dist/core/nodes/group-node/index.js +11 -0
  53. package/dist/core/nodes/group-node/proxy-builder.d.ts +71 -0
  54. package/dist/core/nodes/group-node/proxy-builder.js +161 -0
  55. package/dist/core/nodes/group-node/state-manager.d.ts +184 -0
  56. package/dist/core/nodes/group-node/state-manager.js +265 -0
  57. package/dist/core/nodes/group-node.d.ts +494 -0
  58. package/dist/core/nodes/group-node.js +770 -0
  59. package/dist/core/types/deep-schema.d.ts +78 -0
  60. package/dist/core/types/deep-schema.js +11 -0
  61. package/dist/core/types/field-path.d.ts +42 -0
  62. package/dist/core/types/field-path.js +4 -0
  63. package/dist/core/types/form-context.d.ts +83 -0
  64. package/dist/core/types/form-context.js +25 -0
  65. package/dist/core/types/group-node-proxy.d.ts +135 -0
  66. package/dist/core/types/group-node-proxy.js +31 -0
  67. package/dist/core/types/index.d.ts +163 -0
  68. package/dist/core/types/index.js +4 -0
  69. package/dist/core/types/validation-schema.d.ts +104 -0
  70. package/dist/core/types/validation-schema.js +10 -0
  71. package/dist/core/utils/create-form.d.ts +61 -0
  72. package/dist/core/utils/create-form.js +24 -0
  73. package/dist/core/utils/debounce.d.ts +160 -0
  74. package/dist/core/utils/debounce.js +197 -0
  75. package/dist/core/utils/error-handler.d.ts +180 -0
  76. package/dist/core/utils/error-handler.js +226 -0
  77. package/dist/core/utils/field-path-navigator.d.ts +240 -0
  78. package/dist/core/utils/field-path-navigator.js +374 -0
  79. package/dist/core/utils/index.d.ts +14 -0
  80. package/dist/core/utils/index.js +14 -0
  81. package/dist/core/utils/registry-helpers.d.ts +50 -0
  82. package/dist/core/utils/registry-helpers.js +79 -0
  83. package/dist/core/utils/registry-stack.d.ts +69 -0
  84. package/dist/core/utils/registry-stack.js +86 -0
  85. package/dist/core/utils/resources.d.ts +41 -0
  86. package/dist/core/utils/resources.js +69 -0
  87. package/dist/core/utils/subscription-manager.d.ts +180 -0
  88. package/dist/core/utils/subscription-manager.js +214 -0
  89. package/dist/core/utils/type-guards.d.ts +116 -0
  90. package/dist/core/utils/type-guards.js +169 -0
  91. package/dist/core/validation/core/apply-when.d.ts +28 -0
  92. package/dist/core/validation/core/apply-when.js +41 -0
  93. package/dist/core/validation/core/apply.d.ts +63 -0
  94. package/dist/core/validation/core/apply.js +38 -0
  95. package/dist/core/validation/core/index.d.ts +8 -0
  96. package/dist/core/validation/core/index.js +8 -0
  97. package/dist/core/validation/core/validate-async.d.ts +42 -0
  98. package/dist/core/validation/core/validate-async.js +45 -0
  99. package/dist/core/validation/core/validate-tree.d.ts +35 -0
  100. package/dist/core/validation/core/validate-tree.js +37 -0
  101. package/dist/core/validation/core/validate.d.ts +32 -0
  102. package/dist/core/validation/core/validate.js +38 -0
  103. package/dist/core/validation/field-path.d.ts +43 -0
  104. package/dist/core/validation/field-path.js +147 -0
  105. package/dist/core/validation/index.d.ts +21 -0
  106. package/dist/core/validation/index.js +33 -0
  107. package/dist/core/validation/validate-form.d.ts +85 -0
  108. package/dist/core/validation/validate-form.js +152 -0
  109. package/dist/core/validation/validation-applicator.d.ts +89 -0
  110. package/dist/core/validation/validation-applicator.js +217 -0
  111. package/dist/core/validation/validation-context.d.ts +47 -0
  112. package/dist/core/validation/validation-context.js +75 -0
  113. package/dist/core/validation/validation-registry.d.ts +156 -0
  114. package/dist/core/validation/validation-registry.js +298 -0
  115. package/dist/core/validation/validators/array-validators.d.ts +63 -0
  116. package/dist/core/validation/validators/array-validators.js +86 -0
  117. package/dist/core/validation/validators/date.d.ts +38 -0
  118. package/dist/core/validation/validators/date.js +117 -0
  119. package/dist/core/validation/validators/email.d.ts +44 -0
  120. package/dist/core/validation/validators/email.js +60 -0
  121. package/dist/core/validation/validators/index.d.ts +14 -0
  122. package/dist/core/validation/validators/index.js +14 -0
  123. package/dist/core/validation/validators/max-length.d.ts +45 -0
  124. package/dist/core/validation/validators/max-length.js +60 -0
  125. package/dist/core/validation/validators/max.d.ts +45 -0
  126. package/dist/core/validation/validators/max.js +60 -0
  127. package/dist/core/validation/validators/min-length.d.ts +45 -0
  128. package/dist/core/validation/validators/min-length.js +60 -0
  129. package/dist/core/validation/validators/min.d.ts +45 -0
  130. package/dist/core/validation/validators/min.js +60 -0
  131. package/dist/core/validation/validators/number.d.ts +38 -0
  132. package/dist/core/validation/validators/number.js +90 -0
  133. package/dist/core/validation/validators/pattern.d.ts +47 -0
  134. package/dist/core/validation/validators/pattern.js +62 -0
  135. package/dist/core/validation/validators/phone.d.ts +34 -0
  136. package/dist/core/validation/validators/phone.js +58 -0
  137. package/dist/core/validation/validators/required.d.ts +48 -0
  138. package/dist/core/validation/validators/required.js +69 -0
  139. package/dist/core/validation/validators/url.d.ts +29 -0
  140. package/dist/core/validation/validators/url.js +55 -0
  141. package/dist/create-field-path-CdPF3lIK.js +704 -0
  142. package/dist/hooks/useFormControl.d.ts +48 -0
  143. package/dist/hooks/useFormControl.js +298 -0
  144. package/dist/index.d.ts +10 -0
  145. package/dist/index.js +8 -0
  146. package/dist/node-factory-D7DOnSSN.js +3200 -0
  147. package/dist/validators.d.ts +2 -0
  148. package/dist/validators.js +298 -0
  149. package/llms.txt +847 -0
  150. package/package.json +86 -0
@@ -0,0 +1,269 @@
1
+ /**
2
+ * FieldNode - узел поля формы
3
+ *
4
+ * Представляет одно поле формы с валидацией и состоянием
5
+ * Наследует от FormNode и реализует все его абстрактные методы
6
+ *
7
+ * @group Nodes
8
+ */
9
+ import type { ReadonlySignal } from '@preact/signals-core';
10
+ import { FormNode } from './form-node';
11
+ import type { SetValueOptions } from './form-node';
12
+ import type { FieldConfig, ValidationError } from '../types';
13
+ /**
14
+ * FieldNode - узел для отдельного поля формы
15
+ *
16
+ * @group Nodes
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * const field = new FieldNode({
21
+ * value: '',
22
+ * component: Input,
23
+ * validators: [required, email],
24
+ * });
25
+ *
26
+ * field.setValue('test@mail.com');
27
+ * await field.validate();
28
+ * console.log(field.valid.value); // true
29
+ * ```
30
+ */
31
+ export declare class FieldNode<T> extends FormNode<T> {
32
+ private _value;
33
+ private _errors;
34
+ private _pending;
35
+ private _componentProps;
36
+ readonly value: ReadonlySignal<T>;
37
+ readonly valid: ReadonlySignal<boolean>;
38
+ readonly invalid: ReadonlySignal<boolean>;
39
+ readonly pending: ReadonlySignal<boolean>;
40
+ readonly errors: ReadonlySignal<ValidationError[]>;
41
+ readonly componentProps: ReadonlySignal<Record<string, any>>;
42
+ /**
43
+ * Вычисляемое свойство: нужно ли показывать ошибку
44
+ * Ошибка показывается если поле невалидно И (touched ИЛИ dirty)
45
+ */
46
+ readonly shouldShowError: ReadonlySignal<boolean>;
47
+ private validators;
48
+ private asyncValidators;
49
+ private updateOn;
50
+ private initialValue;
51
+ private currentValidationId;
52
+ private debounceMs;
53
+ private validateDebounceTimer?;
54
+ private validateDebounceResolve?;
55
+ /**
56
+ * Менеджер подписок для централизованного cleanup
57
+ * Использует SubscriptionManager вместо массива для управления подписками
58
+ */
59
+ private disposers;
60
+ readonly component: FieldConfig<T>['component'];
61
+ constructor(config: FieldConfig<T>);
62
+ getValue(): T;
63
+ setValue(value: T, options?: SetValueOptions): void;
64
+ patchValue(value: Partial<T>): void;
65
+ /**
66
+ * Сбросить поле к указанному значению (или к initialValue)
67
+ *
68
+ * @param value - опциональное значение для сброса. Если не указано, используется initialValue
69
+ *
70
+ * @remarks
71
+ * Этот метод:
72
+ * - Устанавливает значение в value или initialValue
73
+ * - Очищает ошибки валидации
74
+ * - Сбрасывает touched/dirty флаги
75
+ * - Устанавливает статус в 'valid'
76
+ *
77
+ * Если вам нужно сбросить к исходному значению, используйте resetToInitial()
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * // Сброс к initialValue
82
+ * field.reset();
83
+ *
84
+ * // Сброс к новому значению
85
+ * field.reset('new value');
86
+ * ```
87
+ */
88
+ reset(value?: T): void;
89
+ /**
90
+ * Сбросить поле к исходному значению (initialValue)
91
+ *
92
+ * @remarks
93
+ * Алиас для reset() без параметров, но более явный:
94
+ * - resetToInitial() - явно показывает намерение вернуться к начальному значению
95
+ * - reset() - может принимать новое значение
96
+ *
97
+ * Полезно когда:
98
+ * - Пользователь нажал "Cancel" - вернуть форму в исходное состояние
99
+ * - Форма была изменена через reset(newValue), но нужно вернуться к самому началу
100
+ * - Явное намерение показать "отмену всех изменений"
101
+ *
102
+ * @example
103
+ * ```typescript
104
+ * const field = new FieldNode({ value: 'initial', component: Input });
105
+ *
106
+ * field.setValue('changed');
107
+ * field.reset('temp value');
108
+ * console.log(field.value.value); // 'temp value'
109
+ *
110
+ * field.resetToInitial();
111
+ * console.log(field.value.value); // 'initial'
112
+ * ```
113
+ */
114
+ resetToInitial(): void;
115
+ /**
116
+ * Запустить валидацию поля
117
+ * @param options - опции валидации
118
+ * @returns `Promise<boolean>` - true если поле валидно
119
+ *
120
+ * @remarks
121
+ * Метод защищен от race conditions через validationId.
122
+ * При быстром вводе только последняя валидация применяет результаты.
123
+ *
124
+ * @example
125
+ * ```typescript
126
+ * // Обычная валидация
127
+ * await field.validate();
128
+ *
129
+ * // С debounce
130
+ * await field.validate({ debounce: 300 });
131
+ * ```
132
+ */
133
+ validate(options?: {
134
+ debounce?: number;
135
+ }): Promise<boolean>;
136
+ /**
137
+ * Немедленная валидация без debounce
138
+ * @private
139
+ * @remarks
140
+ * Защищена от race conditions:
141
+ * - Проверка validationId после синхронной валидации
142
+ * - Проверка перед установкой pending
143
+ * - Проверка после Promise.all
144
+ * - Проверка перед обработкой async результатов
145
+ * - Проверка перед очисткой errors
146
+ */
147
+ private validateImmediate;
148
+ setErrors(errors: ValidationError[]): void;
149
+ clearErrors(): void;
150
+ /**
151
+ * Hook: вызывается после markAsTouched()
152
+ *
153
+ * Для FieldNode: если updateOn === 'blur', запускаем валидацию
154
+ */
155
+ protected onMarkAsTouched(): void;
156
+ /**
157
+ * Hook: вызывается после disable()
158
+ *
159
+ * Для FieldNode: очищаем ошибки валидации
160
+ */
161
+ protected onDisable(): void;
162
+ /**
163
+ * Hook: вызывается после enable()
164
+ *
165
+ * Для FieldNode: запускаем валидацию
166
+ */
167
+ protected onEnable(): void;
168
+ /**
169
+ * Обновляет свойства компонента (например, опции для Select)
170
+ *
171
+ * @example
172
+ * ```typescript
173
+ * // Обновление опций для Select после загрузки справочников
174
+ * form.registrationAddress.city.updateComponentProps({
175
+ * options: cities
176
+ * });
177
+ * ```
178
+ */
179
+ updateComponentProps(props: Partial<Record<string, any>>): void;
180
+ /**
181
+ * Динамически изменяет триггер валидации (updateOn)
182
+ * Полезно для адаптивной валидации - например, переключиться на instant feedback после первого submit
183
+ *
184
+ * @param updateOn - новый триггер валидации: 'change' | 'blur' | 'submit'
185
+ *
186
+ * @example
187
+ * ```typescript
188
+ * // Сценарий 1: Instant feedback после submit
189
+ * const form = new GroupNode({
190
+ * email: {
191
+ * value: '',
192
+ * component: Input,
193
+ * updateOn: 'submit', // Изначально валидация только при submit
194
+ * validators: [required, email]
195
+ * }
196
+ * });
197
+ *
198
+ * await form.submit(async (values) => {
199
+ * // После submit переключаем на instant feedback
200
+ * form.email.setUpdateOn('change');
201
+ * await api.save(values);
202
+ * });
203
+ *
204
+ * // Теперь валидация происходит при каждом изменении
205
+ *
206
+ * // Сценарий 2: Прогрессивное улучшение
207
+ * form.email.setUpdateOn('blur'); // Сначала только при blur
208
+ * // ... пользователь начинает вводить ...
209
+ * form.email.setUpdateOn('change'); // Переключаем на change для real-time feedback
210
+ * ```
211
+ */
212
+ setUpdateOn(updateOn: 'change' | 'blur' | 'submit'): void;
213
+ getUpdateOn(): 'change' | 'blur' | 'submit';
214
+ /**
215
+ * Подписка на изменения значения поля
216
+ * Автоматически отслеживает изменения через @preact/signals effect
217
+ *
218
+ * @param callback - Функция, вызываемая при изменении значения
219
+ * @returns Функция отписки для cleanup
220
+ *
221
+ * @example
222
+ * ```typescript
223
+ * const unsubscribe = form.email.watch((value) => {
224
+ * console.log('Email changed:', value);
225
+ * });
226
+ *
227
+ * // Cleanup
228
+ * useEffect(() => unsubscribe, []);
229
+ * ```
230
+ */
231
+ watch(callback: (value: T) => void | Promise<void>): () => void;
232
+ /**
233
+ * Вычисляемое значение из других полей
234
+ * Автоматически обновляет текущее поле при изменении источников
235
+ *
236
+ * @param sources - Массив ReadonlySignal для отслеживания
237
+ * @param computeFn - Функция вычисления нового значения
238
+ * @returns Функция отписки для cleanup
239
+ *
240
+ * @example
241
+ * ```typescript
242
+ * // Автоматический расчет первоначального взноса (20% от стоимости)
243
+ * const dispose = form.initialPayment.computeFrom(
244
+ * [form.propertyValue.value],
245
+ * (propertyValue) => {
246
+ * return propertyValue ? propertyValue * 0.2 : null;
247
+ * }
248
+ * );
249
+ *
250
+ * // Cleanup
251
+ * useEffect(() => dispose, []);
252
+ * ```
253
+ */
254
+ computeFrom<TSource extends readonly unknown[]>(sources: ReadonlySignal<TSource[number]>[], computeFn: (...values: TSource) => T): () => void;
255
+ /**
256
+ * Очистить все ресурсы и таймеры
257
+ * Должен вызываться при unmount компонента
258
+ *
259
+ * @example
260
+ * ```typescript
261
+ * useEffect(() => {
262
+ * return () => {
263
+ * field.dispose();
264
+ * };
265
+ * }, []);
266
+ * ```
267
+ */
268
+ dispose(): void;
269
+ }