@reformer/core 1.1.0 → 2.0.0-beta.2

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 (99) hide show
  1. package/dist/behaviors-DzYL8kY_.js +499 -0
  2. package/dist/behaviors.d.ts +6 -2
  3. package/dist/behaviors.js +19 -227
  4. package/dist/core/behavior/behavior-context.d.ts +6 -2
  5. package/dist/core/behavior/create-field-path.d.ts +3 -16
  6. package/dist/core/nodes/group-node.d.ts +14 -193
  7. package/dist/core/types/form-context.d.ts +10 -4
  8. package/dist/core/utils/field-path.d.ts +48 -0
  9. package/dist/core/utils/index.d.ts +1 -0
  10. package/dist/core/validation/core/validate-tree.d.ts +10 -4
  11. package/dist/core/validation/field-path.d.ts +3 -39
  12. package/dist/core/validation/validation-context.d.ts +23 -0
  13. package/dist/hooks/types.d.ts +328 -0
  14. package/dist/hooks/useFormControl.d.ts +13 -37
  15. package/dist/hooks/useFormControlValue.d.ts +167 -0
  16. package/dist/hooks/useSignalSubscription.d.ts +17 -0
  17. package/dist/index.d.ts +6 -1
  18. package/dist/index.js +2886 -8
  19. package/dist/{create-field-path-CdPF3lIK.js → registry-helpers-BRxAr6nG.js} +133 -347
  20. package/dist/validators-gXoHPdqM.js +418 -0
  21. package/dist/validators.d.ts +6 -2
  22. package/dist/validators.js +29 -296
  23. package/llms.txt +1283 -22
  24. package/package.json +8 -4
  25. package/dist/core/behavior/behavior-applicator.d.ts +0 -71
  26. package/dist/core/behavior/behavior-applicator.js +0 -92
  27. package/dist/core/behavior/behavior-context.js +0 -38
  28. package/dist/core/behavior/behavior-registry.js +0 -198
  29. package/dist/core/behavior/behaviors/compute-from.js +0 -84
  30. package/dist/core/behavior/behaviors/copy-from.js +0 -64
  31. package/dist/core/behavior/behaviors/enable-when.js +0 -81
  32. package/dist/core/behavior/behaviors/index.js +0 -11
  33. package/dist/core/behavior/behaviors/reset-when.js +0 -63
  34. package/dist/core/behavior/behaviors/revalidate-when.js +0 -51
  35. package/dist/core/behavior/behaviors/sync-fields.js +0 -66
  36. package/dist/core/behavior/behaviors/transform-value.js +0 -110
  37. package/dist/core/behavior/behaviors/watch-field.js +0 -56
  38. package/dist/core/behavior/compose-behavior.js +0 -166
  39. package/dist/core/behavior/create-field-path.js +0 -69
  40. package/dist/core/behavior/index.js +0 -17
  41. package/dist/core/behavior/types.js +0 -7
  42. package/dist/core/context/form-context-impl.js +0 -37
  43. package/dist/core/factories/index.js +0 -6
  44. package/dist/core/factories/node-factory.js +0 -281
  45. package/dist/core/nodes/array-node.js +0 -534
  46. package/dist/core/nodes/field-node.js +0 -510
  47. package/dist/core/nodes/form-node.js +0 -343
  48. package/dist/core/nodes/group-node/field-registry.d.ts +0 -191
  49. package/dist/core/nodes/group-node/field-registry.js +0 -215
  50. package/dist/core/nodes/group-node/index.d.ts +0 -11
  51. package/dist/core/nodes/group-node/index.js +0 -11
  52. package/dist/core/nodes/group-node/proxy-builder.d.ts +0 -71
  53. package/dist/core/nodes/group-node/proxy-builder.js +0 -161
  54. package/dist/core/nodes/group-node/state-manager.d.ts +0 -184
  55. package/dist/core/nodes/group-node/state-manager.js +0 -265
  56. package/dist/core/nodes/group-node.js +0 -770
  57. package/dist/core/types/deep-schema.js +0 -11
  58. package/dist/core/types/field-path.js +0 -4
  59. package/dist/core/types/form-context.js +0 -25
  60. package/dist/core/types/group-node-proxy.js +0 -31
  61. package/dist/core/types/index.js +0 -4
  62. package/dist/core/types/validation-schema.js +0 -10
  63. package/dist/core/utils/create-form.js +0 -24
  64. package/dist/core/utils/debounce.js +0 -197
  65. package/dist/core/utils/error-handler.js +0 -226
  66. package/dist/core/utils/field-path-navigator.js +0 -374
  67. package/dist/core/utils/index.js +0 -14
  68. package/dist/core/utils/registry-helpers.js +0 -79
  69. package/dist/core/utils/registry-stack.js +0 -86
  70. package/dist/core/utils/resources.js +0 -69
  71. package/dist/core/utils/subscription-manager.js +0 -214
  72. package/dist/core/utils/type-guards.js +0 -169
  73. package/dist/core/validation/core/apply-when.js +0 -41
  74. package/dist/core/validation/core/apply.js +0 -38
  75. package/dist/core/validation/core/index.js +0 -8
  76. package/dist/core/validation/core/validate-async.js +0 -45
  77. package/dist/core/validation/core/validate-tree.js +0 -37
  78. package/dist/core/validation/core/validate.js +0 -38
  79. package/dist/core/validation/field-path.js +0 -147
  80. package/dist/core/validation/index.js +0 -33
  81. package/dist/core/validation/validate-form.js +0 -152
  82. package/dist/core/validation/validation-applicator.js +0 -217
  83. package/dist/core/validation/validation-context.js +0 -75
  84. package/dist/core/validation/validation-registry.js +0 -298
  85. package/dist/core/validation/validators/array-validators.js +0 -86
  86. package/dist/core/validation/validators/date.js +0 -117
  87. package/dist/core/validation/validators/email.js +0 -60
  88. package/dist/core/validation/validators/index.js +0 -14
  89. package/dist/core/validation/validators/max-length.js +0 -60
  90. package/dist/core/validation/validators/max.js +0 -60
  91. package/dist/core/validation/validators/min-length.js +0 -60
  92. package/dist/core/validation/validators/min.js +0 -60
  93. package/dist/core/validation/validators/number.js +0 -90
  94. package/dist/core/validation/validators/pattern.js +0 -62
  95. package/dist/core/validation/validators/phone.js +0 -58
  96. package/dist/core/validation/validators/required.js +0 -69
  97. package/dist/core/validation/validators/url.js +0 -55
  98. package/dist/hooks/useFormControl.js +0 -298
  99. package/dist/node-factory-D7DOnSSN.js +0 -3200
@@ -1,215 +0,0 @@
1
- /**
2
- * FieldRegistry - управление полями в GroupNode
3
- *
4
- * Извлечено из GroupNode для соблюдения SRP (Single Responsibility Principle).
5
- * Отвечает только за хранение и управление коллекцией полей формы.
6
- *
7
- * @template T Тип формы (объект)
8
- *
9
- * @example
10
- * ```typescript
11
- * const registry = new FieldRegistry<{ email: string; name: string }>();
12
- * registry.set('email', emailField);
13
- * registry.set('name', nameField);
14
- *
15
- * const emailField = registry.get('email');
16
- * registry.forEach((field, key) => {
17
- * console.log(key, field.value.value);
18
- * });
19
- * ```
20
- */
21
- /**
22
- * Реестр полей формы
23
- *
24
- * Предоставляет типобезопасный доступ к полям формы
25
- * через Map-подобный интерфейс
26
- *
27
- * @template T Тип формы (объект)
28
- */
29
- export class FieldRegistry {
30
- /**
31
- * Внутреннее хранилище полей
32
- * Map обеспечивает быструю lookup производительность O(1)
33
- */
34
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
- fields = new Map();
36
- /**
37
- * Установить поле в реестр
38
- *
39
- * @param key - Ключ поля (имя свойства в типе T)
40
- * @param node - FormNode для этого поля
41
- *
42
- * @example
43
- * ```typescript
44
- * registry.set('email', new FieldNode({ value: '' }));
45
- * ```
46
- */
47
- set(key, node) {
48
- this.fields.set(key, node);
49
- }
50
- /**
51
- * Получить поле из реестра
52
- *
53
- * @param key - Ключ поля
54
- * @returns FormNode или undefined, если поле не найдено
55
- *
56
- * @example
57
- * ```typescript
58
- * const emailField = registry.get('email');
59
- * if (emailField) {
60
- * console.log(emailField.value.value);
61
- * }
62
- * ```
63
- */
64
- get(key) {
65
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
- return this.fields.get(key);
67
- }
68
- /**
69
- * Проверить наличие поля в реестре
70
- *
71
- * @param key - Ключ поля
72
- * @returns true если поле существует
73
- *
74
- * @example
75
- * ```typescript
76
- * if (registry.has('email')) {
77
- * console.log('Email field exists');
78
- * }
79
- * ```
80
- */
81
- has(key) {
82
- return this.fields.has(key);
83
- }
84
- /**
85
- * Удалить поле из реестра
86
- *
87
- * @param key - Ключ поля
88
- * @returns true если поле было удалено, false если поля не было
89
- *
90
- * @example
91
- * ```typescript
92
- * registry.delete('email');
93
- * ```
94
- */
95
- delete(key) {
96
- return this.fields.delete(key);
97
- }
98
- /**
99
- * Перебрать все поля
100
- *
101
- * @param callback - Функция обратного вызова для каждого поля
102
- *
103
- * @example
104
- * ```typescript
105
- * registry.forEach((field, key) => {
106
- * console.log(`${key}: ${field.value.value}`);
107
- * });
108
- * ```
109
- */
110
- forEach(callback) {
111
- this.fields.forEach(callback);
112
- }
113
- /**
114
- * Получить итератор значений (полей)
115
- *
116
- * @returns Итератор по всем полям
117
- *
118
- * @example
119
- * ```typescript
120
- * for (const field of registry.values()) {
121
- * await field.validate();
122
- * }
123
- * ```
124
- */
125
- values() {
126
- return this.fields.values();
127
- }
128
- /**
129
- * Получить итератор пар [ключ, значение]
130
- *
131
- * @returns Итератор по всем записям
132
- *
133
- * @example
134
- * ```typescript
135
- * for (const [key, field] of registry.entries()) {
136
- * console.log(key, field.value.value);
137
- * }
138
- * ```
139
- */
140
- entries() {
141
- return this.fields.entries();
142
- }
143
- /**
144
- * Получить итератор ключей полей
145
- *
146
- * @returns Итератор по всем ключам
147
- *
148
- * @example
149
- * ```typescript
150
- * const fieldNames = Array.from(registry.keys());
151
- * // ['email', 'name', 'age']
152
- * ```
153
- */
154
- keys() {
155
- return this.fields.keys();
156
- }
157
- /**
158
- * Получить количество полей
159
- *
160
- * @returns Количество зарегистрированных полей
161
- *
162
- * @example
163
- * ```typescript
164
- * console.log(`Form has ${registry.size()} fields`);
165
- * ```
166
- */
167
- size() {
168
- return this.fields.size;
169
- }
170
- /**
171
- * Очистить все поля
172
- *
173
- * Удаляет все поля из реестра
174
- *
175
- * @example
176
- * ```typescript
177
- * registry.clear();
178
- * console.log(registry.size()); // 0
179
- * ```
180
- */
181
- clear() {
182
- this.fields.clear();
183
- }
184
- /**
185
- * Получить все поля как массив
186
- *
187
- * Полезно для операций, требующих работу с массивом
188
- *
189
- * @returns Массив всех полей
190
- *
191
- * @example
192
- * ```typescript
193
- * const allValid = registry.toArray().every(field => field.valid.value);
194
- * ```
195
- */
196
- toArray() {
197
- return Array.from(this.fields.values());
198
- }
199
- /**
200
- * Получить Map-представление реестра (readonly)
201
- *
202
- * Используйте для совместимости с существующим кодом
203
- *
204
- * @returns ReadonlyMap с полями
205
- * @internal
206
- *
207
- * @example
208
- * ```typescript
209
- * const mapView = registry.asMap();
210
- * ```
211
- */
212
- asMap() {
213
- return this.fields;
214
- }
215
- }
@@ -1,11 +0,0 @@
1
- /**
2
- * GroupNode modules
3
- *
4
- * Модульная структура для GroupNode:
5
- * - FieldRegistry: Управление коллекцией полей
6
- * - ProxyBuilder: Создание Proxy для типобезопасного доступа к полям
7
- * - StateManager: Управление состоянием формы (signals)
8
- */
9
- export { FieldRegistry } from './field-registry';
10
- export { ProxyBuilder } from './proxy-builder';
11
- export { StateManager } from './state-manager';
@@ -1,11 +0,0 @@
1
- /**
2
- * GroupNode modules
3
- *
4
- * Модульная структура для GroupNode:
5
- * - FieldRegistry: Управление коллекцией полей
6
- * - ProxyBuilder: Создание Proxy для типобезопасного доступа к полям
7
- * - StateManager: Управление состоянием формы (signals)
8
- */
9
- export { FieldRegistry } from './field-registry';
10
- export { ProxyBuilder } from './proxy-builder';
11
- export { StateManager } from './state-manager';
@@ -1,71 +0,0 @@
1
- /**
2
- * ProxyBuilder - создание Proxy для типобезопасного доступа к полям GroupNode
3
- *
4
- * Извлечено из GroupNode для соблюдения SRP (Single Responsibility Principle).
5
- * Отвечает только за создание Proxy с расширенной поддержкой операций.
6
- *
7
- * @template T Тип формы (объект)
8
- *
9
- * @example
10
- * ```typescript
11
- * const fieldRegistry = new FieldRegistry<FormType>();
12
- * const proxyBuilder = new ProxyBuilder(fieldRegistry);
13
- * const proxy = proxyBuilder.build(groupNode);
14
- *
15
- * // Теперь можно обращаться к полям напрямую:
16
- * console.log(proxy.email.value);
17
- * console.log('email' in proxy); // true
18
- * ```
19
- */
20
- import type { GroupNode } from '../group-node';
21
- import type { GroupNodeWithControls } from '../../types/group-node-proxy';
22
- import type { FieldRegistry } from './field-registry';
23
- /**
24
- * Строитель Proxy для GroupNode
25
- *
26
- * Создает Proxy с поддержкой:
27
- * - get: Прямой доступ к полям через точечную нотацию
28
- * - set: Предупреждение о попытке прямой установки полей
29
- * - has: Проверка существования поля ('email' in form)
30
- * - ownKeys: Перечисление всех ключей (Object.keys(form))
31
- * - getOwnPropertyDescriptor: Получение дескрипторов полей
32
- *
33
- * @template T Тип формы (объект)
34
- */
35
- export declare class ProxyBuilder<T> {
36
- private fieldRegistry;
37
- /**
38
- * @param fieldRegistry - Реестр полей для доступа к коллекции
39
- */
40
- constructor(fieldRegistry: FieldRegistry<T>);
41
- /**
42
- * Создать Proxy для GroupNode
43
- *
44
- * Proxy позволяет обращаться к полям формы напрямую:
45
- * - form.email вместо form.fields.get('email')
46
- * - form.address.city вместо form.fields.get('address').fields.get('city')
47
- *
48
- * @param target - GroupNode для которого создается Proxy
49
- * @returns Proxy с типобезопасным доступом к полям
50
- *
51
- * @example
52
- * ```typescript
53
- * const proxy = proxyBuilder.build(groupNode);
54
- *
55
- * // Доступ к полям
56
- * console.log(proxy.email.value); // Работает!
57
- * console.log(proxy.name.value); // Работает!
58
- *
59
- * // Доступ к методам GroupNode
60
- * await proxy.validate(); // Работает!
61
- * proxy.markAsTouched(); // Работает!
62
- *
63
- * // Проверка существования
64
- * if ('email' in proxy) { ... }
65
- *
66
- * // Перечисление ключей
67
- * Object.keys(proxy); // ['email', 'name', ...]
68
- * ```
69
- */
70
- build(target: GroupNode<T>): GroupNodeWithControls<T>;
71
- }
@@ -1,161 +0,0 @@
1
- /**
2
- * ProxyBuilder - создание Proxy для типобезопасного доступа к полям GroupNode
3
- *
4
- * Извлечено из GroupNode для соблюдения SRP (Single Responsibility Principle).
5
- * Отвечает только за создание Proxy с расширенной поддержкой операций.
6
- *
7
- * @template T Тип формы (объект)
8
- *
9
- * @example
10
- * ```typescript
11
- * const fieldRegistry = new FieldRegistry<FormType>();
12
- * const proxyBuilder = new ProxyBuilder(fieldRegistry);
13
- * const proxy = proxyBuilder.build(groupNode);
14
- *
15
- * // Теперь можно обращаться к полям напрямую:
16
- * console.log(proxy.email.value);
17
- * console.log('email' in proxy); // true
18
- * ```
19
- */
20
- /**
21
- * Строитель Proxy для GroupNode
22
- *
23
- * Создает Proxy с поддержкой:
24
- * - get: Прямой доступ к полям через точечную нотацию
25
- * - set: Предупреждение о попытке прямой установки полей
26
- * - has: Проверка существования поля ('email' in form)
27
- * - ownKeys: Перечисление всех ключей (Object.keys(form))
28
- * - getOwnPropertyDescriptor: Получение дескрипторов полей
29
- *
30
- * @template T Тип формы (объект)
31
- */
32
- export class ProxyBuilder {
33
- fieldRegistry;
34
- /**
35
- * @param fieldRegistry - Реестр полей для доступа к коллекции
36
- */
37
- constructor(fieldRegistry) {
38
- this.fieldRegistry = fieldRegistry;
39
- }
40
- /**
41
- * Создать Proxy для GroupNode
42
- *
43
- * Proxy позволяет обращаться к полям формы напрямую:
44
- * - form.email вместо form.fields.get('email')
45
- * - form.address.city вместо form.fields.get('address').fields.get('city')
46
- *
47
- * @param target - GroupNode для которого создается Proxy
48
- * @returns Proxy с типобезопасным доступом к полям
49
- *
50
- * @example
51
- * ```typescript
52
- * const proxy = proxyBuilder.build(groupNode);
53
- *
54
- * // Доступ к полям
55
- * console.log(proxy.email.value); // Работает!
56
- * console.log(proxy.name.value); // Работает!
57
- *
58
- * // Доступ к методам GroupNode
59
- * await proxy.validate(); // Работает!
60
- * proxy.markAsTouched(); // Работает!
61
- *
62
- * // Проверка существования
63
- * if ('email' in proxy) { ... }
64
- *
65
- * // Перечисление ключей
66
- * Object.keys(proxy); // ['email', 'name', ...]
67
- * ```
68
- */
69
- build(target) {
70
- return new Proxy(target, {
71
- /**
72
- * Get trap: Перехват доступа к свойствам
73
- *
74
- * Приоритет:
75
- * 1. Собственные свойства и методы GroupNode (validate, setValue и т.д.)
76
- * 2. Поля формы из fieldRegistry
77
- * 3. undefined для несуществующих свойств
78
- */
79
- get: (target, prop) => {
80
- // Приоритет 1: Собственные свойства и методы GroupNode
81
- // Это важно, чтобы методы validate(), setValue() и т.д. работали корректно
82
- if (prop in target) {
83
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
84
- return target[prop];
85
- }
86
- // Приоритет 2: Поля формы
87
- // Используем fieldRegistry для типобезопасного доступа
88
- if (typeof prop === 'string' && this.fieldRegistry.has(prop)) {
89
- return this.fieldRegistry.get(prop);
90
- }
91
- // Fallback для несуществующих свойств
92
- return undefined;
93
- },
94
- /**
95
- * Set trap: Перехват установки свойств
96
- *
97
- * Запрещает прямую установку значений полей через form.email = value
98
- * Пользователь должен использовать form.email.setValue(value) или form.setValue({...})
99
- */
100
- set: (target, prop, value) => {
101
- // Запретить прямое изменение полей
102
- if (typeof prop === 'string' && this.fieldRegistry.has(prop)) {
103
- if (import.meta.env.DEV) {
104
- console.warn(`[GroupNode] Cannot set field "${prop}" directly. Use .setValue() or .patchValue() instead.\n` +
105
- `Example: form.setValue({ ${prop}: ${JSON.stringify(value)} })`);
106
- }
107
- return false;
108
- }
109
- // Разрешить установку других свойств
110
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
111
- target[prop] = value;
112
- return true;
113
- },
114
- /**
115
- * Has trap: Перехват оператора 'in'
116
- *
117
- * Позволяет проверять существование полей:
118
- * if ('email' in form) { ... }
119
- */
120
- has: (target, prop) => {
121
- // Проверяем наличие в полях
122
- if (typeof prop === 'string' && this.fieldRegistry.has(prop)) {
123
- return true;
124
- }
125
- // Проверяем наличие в самом объекте
126
- return prop in target;
127
- },
128
- /**
129
- * OwnKeys trap: Перехват Object.keys() / Object.getOwnPropertyNames()
130
- *
131
- * Возвращает объединенный список:
132
- * - Ключей самого GroupNode
133
- * - Ключей полей из fieldRegistry
134
- */
135
- ownKeys: (target) => {
136
- const nodeKeys = Reflect.ownKeys(target);
137
- const fieldKeys = Array.from(this.fieldRegistry.keys());
138
- // Используем Set для удаления дубликатов
139
- return [...new Set([...nodeKeys, ...fieldKeys])];
140
- },
141
- /**
142
- * GetOwnPropertyDescriptor trap: Перехват Object.getOwnPropertyDescriptor()
143
- *
144
- * Возвращает дескриптор свойства для полей и свойств GroupNode
145
- * Важно для корректной работы Object.keys() и других рефлексивных операций
146
- */
147
- getOwnPropertyDescriptor: (target, prop) => {
148
- // Дескриптор для полей формы
149
- if (typeof prop === 'string' && this.fieldRegistry.has(prop)) {
150
- return {
151
- enumerable: true, // Поле должно быть перечисляемым
152
- configurable: true, // Поле может быть удалено
153
- // Не указываем writable, т.к. это accessor property через get/set traps
154
- };
155
- }
156
- // Дескриптор для свойств самого объекта
157
- return Reflect.getOwnPropertyDescriptor(target, prop);
158
- },
159
- });
160
- }
161
- }
@@ -1,184 +0,0 @@
1
- /**
2
- * StateManager - управление состоянием GroupNode
3
- *
4
- * Инкапсулирует всю логику создания и управления сигналами состояния:
5
- * - Приватные сигналы (submitting, disabled, formErrors)
6
- * - Публичные computed signals (value, valid, invalid, touched, dirty, pending, errors, status, submitting)
7
- *
8
- * Извлечено из GroupNode для соблюдения SRP (Single Responsibility Principle).
9
- * Отвечает только за логику управления состоянием формы.
10
- *
11
- * @template T Тип формы (объект)
12
- *
13
- * @example
14
- * ```typescript
15
- * class GroupNode {
16
- * private stateManager: StateManager<T>;
17
- *
18
- * constructor(schema: FormSchema<T>) {
19
- * this.fieldRegistry = new FieldRegistry<T>();
20
- * // ... создание полей ...
21
- * this.stateManager = new StateManager(this.fieldRegistry);
22
- *
23
- * // Доступ к computed signals
24
- * this.value = this.stateManager.value;
25
- * this.valid = this.stateManager.valid;
26
- * }
27
- * }
28
- * ```
29
- */
30
- import type { ReadonlySignal } from '@preact/signals-core';
31
- import type { ValidationError, FieldStatus } from '../../types';
32
- import type { FieldRegistry } from './field-registry';
33
- /**
34
- * Менеджер состояния для GroupNode
35
- *
36
- * Создает и управляет всеми сигналами состояния формы:
37
- * - value - значение формы как объект
38
- * - valid/invalid - валидность формы
39
- * - touched/dirty - пользовательское взаимодействие
40
- * - pending - асинхронная валидация в процессе
41
- * - errors - все ошибки валидации (form-level + field-level)
42
- * - status - общий статус формы
43
- * - submitting - флаг отправки формы
44
- *
45
- * @template T Тип формы (объект)
46
- */
47
- export declare class StateManager<T> {
48
- private readonly fieldRegistry;
49
- /**
50
- * Флаг отправки формы
51
- * Устанавливается в true во время отправки формы на сервер
52
- */
53
- private _submitting;
54
- /**
55
- * Флаг disabled состояния
56
- * Если true, форма считается disabled
57
- */
58
- private _disabled;
59
- /**
60
- * Form-level validation errors (не связанные с конкретным полем)
61
- * Используется для server-side errors или кросс-полевой валидации
62
- */
63
- private _formErrors;
64
- /**
65
- * Значение формы как объект
66
- *
67
- * Computed signal, который автоматически пересчитывается при изменении любого поля.
68
- * Использует мемоизацию - если зависимости не изменились, вернет закешированный объект.
69
- *
70
- * @example
71
- * ```typescript
72
- * const form = new GroupNode({ email: { value: 'test@mail.com' } });
73
- * console.log(form.value.value); // { email: 'test@mail.com' }
74
- * ```
75
- */
76
- readonly value: ReadonlySignal<T>;
77
- /**
78
- * Форма валидна?
79
- *
80
- * Computed signal. Форма валидна, если:
81
- * - Нет form-level errors
82
- * - Все поля валидны
83
- */
84
- readonly valid: ReadonlySignal<boolean>;
85
- /**
86
- * Форма невалидна?
87
- *
88
- * Computed signal. Инверсия valid.
89
- */
90
- readonly invalid: ReadonlySignal<boolean>;
91
- /**
92
- * Хотя бы одно поле touched?
93
- *
94
- * Computed signal. Возвращает true, если хотя бы одно поле было touched.
95
- */
96
- readonly touched: ReadonlySignal<boolean>;
97
- /**
98
- * Хотя бы одно поле dirty?
99
- *
100
- * Computed signal. Возвращает true, если хотя бы одно поле изменилось.
101
- */
102
- readonly dirty: ReadonlySignal<boolean>;
103
- /**
104
- * Асинхронная валидация в процессе?
105
- *
106
- * Computed signal. Возвращает true, если хотя бы одно поле находится в pending состоянии.
107
- */
108
- readonly pending: ReadonlySignal<boolean>;
109
- /**
110
- * Все ошибки валидации
111
- *
112
- * Computed signal. Возвращает массив всех ошибок:
113
- * - Form-level errors
114
- * - Field-level errors (из всех вложенных полей)
115
- */
116
- readonly errors: ReadonlySignal<ValidationError[]>;
117
- /**
118
- * Общий статус формы
119
- *
120
- * Computed signal. Возможные значения:
121
- * - 'disabled' - форма disabled
122
- * - 'pending' - асинхронная валидация в процессе
123
- * - 'invalid' - форма невалидна
124
- * - 'valid' - форма валидна
125
- */
126
- readonly status: ReadonlySignal<FieldStatus>;
127
- /**
128
- * Форма в процессе отправки?
129
- *
130
- * Computed signal (обертка над _submitting для read-only доступа).
131
- */
132
- readonly submitting: ReadonlySignal<boolean>;
133
- /**
134
- * Создать менеджер состояния
135
- *
136
- * @param fieldRegistry - реестр полей формы
137
- */
138
- constructor(fieldRegistry: FieldRegistry<T>);
139
- /**
140
- * Установить form-level ошибки
141
- *
142
- * @param errors - массив ошибок валидации
143
- *
144
- * @example
145
- * ```typescript
146
- * // Server-side ошибки
147
- * stateManager.setFormErrors([
148
- * { code: 'server_error', message: 'Пользователь с таким email уже существует' }
149
- * ]);
150
- * ```
151
- */
152
- setFormErrors(errors: ValidationError[]): void;
153
- /**
154
- * Очистить form-level ошибки
155
- */
156
- clearFormErrors(): void;
157
- /**
158
- * Получить form-level ошибки
159
- */
160
- getFormErrors(): ValidationError[];
161
- /**
162
- * Установить флаг submitting
163
- *
164
- * @param value - true если форма отправляется, false если нет
165
- *
166
- * @example
167
- * ```typescript
168
- * stateManager.setSubmitting(true);
169
- * await api.submitForm(form.getValue());
170
- * stateManager.setSubmitting(false);
171
- * ```
172
- */
173
- setSubmitting(value: boolean): void;
174
- /**
175
- * Установить флаг disabled
176
- *
177
- * @param value - true если форма disabled, false если нет
178
- */
179
- setDisabled(value: boolean): void;
180
- /**
181
- * Получить флаг disabled
182
- */
183
- isDisabled(): boolean;
184
- }