@reformer/core 10.2.0 → 11.0.0-beta.10

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 (285) hide show
  1. package/README.md +90 -68
  2. package/dist/behaviors-value-D05z3my6.js +109 -0
  3. package/dist/behaviors.d.ts +1 -1
  4. package/dist/behaviors.js +376 -211
  5. package/dist/create-model-DPSG3I0O.js +30 -0
  6. package/dist/date-utils-90-qZbse.js +43 -0
  7. package/dist/en-HP8XEych.js +44 -0
  8. package/dist/form/aggregate-signals.d.ts +21 -63
  9. package/dist/form/behaviors/collections.d.ts +84 -0
  10. package/dist/form/behaviors/context.d.ts +56 -0
  11. package/dist/form/behaviors/index.d.ts +30 -0
  12. package/dist/form/behaviors/internals.d.ts +41 -0
  13. package/dist/form/{behaviors-node.d.ts → behaviors/node.d.ts} +28 -5
  14. package/dist/form/behaviors/operators.d.ts +59 -0
  15. package/dist/form/behaviors/schema-operators.d.ts +83 -0
  16. package/dist/form/behaviors/types.d.ts +37 -0
  17. package/dist/form/create-form.d.ts +59 -70
  18. package/dist/form/flow/flow.d.ts +87 -0
  19. package/dist/form/form-bundle.d.ts +153 -0
  20. package/dist/form/form-level.d.ts +121 -0
  21. package/dist/form/form-proxy-builder.d.ts +6 -22
  22. package/dist/form/index.d.ts +23 -27
  23. package/dist/form/nodes/form-array-node.d.ts +100 -0
  24. package/dist/form/nodes/form-control-node.d.ts +73 -0
  25. package/dist/form/nodes/form-group-node.d.ts +66 -0
  26. package/dist/form/nodes/node-kind.d.ts +29 -0
  27. package/dist/form/nodes/state/availability.d.ts +6 -0
  28. package/dist/form/nodes/state/component.d.ts +6 -0
  29. package/dist/form/nodes/state/index.d.ts +12 -0
  30. package/dist/form/nodes/state/interaction.d.ts +13 -0
  31. package/dist/form/nodes/state/issues.d.ts +9 -0
  32. package/dist/form/nodes/state/pending.d.ts +6 -0
  33. package/dist/form/schema/compile.d.ts +59 -0
  34. package/dist/form/schema/compiled.d.ts +143 -0
  35. package/dist/form/schema/row-key.d.ts +11 -0
  36. package/dist/form/schema-controller.d.ts +159 -0
  37. package/dist/form/schema-subtree.d.ts +28 -0
  38. package/dist/form/signal-node-registry.d.ts +27 -22
  39. package/dist/form/submission.d.ts +93 -0
  40. package/dist/form/type-guards.d.ts +14 -73
  41. package/dist/form/types/contracts.d.ts +21 -91
  42. package/dist/form/types/field-config.d.ts +27 -0
  43. package/dist/form/types/index.d.ts +5 -91
  44. package/dist/form/types/nodes.d.ts +159 -0
  45. package/dist/form/types/schema-node.d.ts +148 -50
  46. package/dist/form/types/validation-schema.d.ts +24 -41
  47. package/dist/form/validation/context.d.ts +67 -0
  48. package/dist/form/validation/index.d.ts +24 -28
  49. package/dist/form/validation/operators.d.ts +101 -0
  50. package/dist/form/validation/run.d.ts +120 -0
  51. package/dist/form/validation/strategy.d.ts +89 -0
  52. package/dist/form/validation/types.d.ts +83 -0
  53. package/dist/form/validators/date-utils.d.ts +42 -0
  54. package/dist/form/validators/email.d.ts +23 -0
  55. package/dist/form/{validation/validators → validators}/file-type.d.ts +10 -10
  56. package/dist/form/{validation/validators → validators}/file-utils.d.ts +3 -2
  57. package/dist/form/validators/future-date.d.ts +23 -0
  58. package/dist/form/{validation/validators → validators}/index.d.ts +7 -4
  59. package/dist/form/validators/integer.d.ts +22 -0
  60. package/dist/form/validators/is-date.d.ts +24 -0
  61. package/dist/form/validators/is-number.d.ts +25 -0
  62. package/dist/form/validators/max-age.d.ts +28 -0
  63. package/dist/form/validators/max-date.d.ts +25 -0
  64. package/dist/form/{validation/validators → validators}/max-file-size.d.ts +10 -10
  65. package/dist/form/validators/max-files.d.ts +26 -0
  66. package/dist/form/validators/max-length.d.ts +33 -0
  67. package/dist/form/validators/max-total-file-size.d.ts +26 -0
  68. package/dist/form/validators/max.d.ts +26 -0
  69. package/dist/form/validators/min-age.d.ts +27 -0
  70. package/dist/form/validators/min-date.d.ts +25 -0
  71. package/dist/form/{validation/validators → validators}/min-file-size.d.ts +10 -10
  72. package/dist/form/validators/min-files.d.ts +27 -0
  73. package/dist/form/validators/min-length.d.ts +33 -0
  74. package/dist/form/validators/min.d.ts +26 -0
  75. package/dist/form/validators/multiple-of.d.ts +25 -0
  76. package/dist/form/validators/non-negative.d.ts +22 -0
  77. package/dist/form/validators/non-zero.d.ts +22 -0
  78. package/dist/form/validators/past-date.d.ts +23 -0
  79. package/dist/form/validators/pattern.d.ts +26 -0
  80. package/dist/form/{validation/validators → validators}/phone.d.ts +11 -11
  81. package/dist/form/validators/required.d.ts +29 -0
  82. package/dist/form/validators/url.d.ts +45 -0
  83. package/dist/form/validators/validation-issue.d.ts +8 -0
  84. package/dist/i18n/descriptor.d.ts +54 -0
  85. package/dist/i18n/en.json.d.ts +49 -0
  86. package/dist/i18n/loader.d.ts +71 -0
  87. package/dist/i18n/locale-store.d.ts +46 -0
  88. package/dist/i18n/locale.d.ts +90 -0
  89. package/dist/i18n/message-format.d.ts +136 -0
  90. package/dist/i18n/resolve-localized.d.ts +17 -0
  91. package/dist/i18n/ru.json.d.ts +49 -0
  92. package/dist/i18n/translator.d.ts +61 -0
  93. package/dist/i18n/validation-message.d.ts +53 -0
  94. package/dist/i18n.d.ts +26 -0
  95. package/dist/i18n.js +86 -0
  96. package/dist/index.d.ts +18 -6
  97. package/dist/index.js +932 -2779
  98. package/dist/loader-BWkigpVe.js +52 -0
  99. package/dist/locale/en.d.ts +2 -0
  100. package/dist/locale/en.js +5 -0
  101. package/dist/locale/en.json +45 -0
  102. package/dist/locale/index.d.ts +18 -0
  103. package/dist/locale/ru.d.ts +2 -0
  104. package/dist/locale/ru.js +44 -0
  105. package/dist/locale/ru.json +45 -0
  106. package/dist/locale-CG54AU2Q.js +219 -0
  107. package/dist/locale.d.ts +2 -0
  108. package/dist/locale.js +9 -0
  109. package/dist/{state → model}/behaviors-value.d.ts +24 -6
  110. package/dist/{state/form-model.d.ts → model/create-model.d.ts} +18 -4
  111. package/dist/{state → model}/derived-registry.d.ts +1 -1
  112. package/dist/model/index.d.ts +42 -0
  113. package/dist/model/model-nodes.d.ts +190 -0
  114. package/dist/model/model-signals-proxy.d.ts +63 -0
  115. package/dist/model/model-value-proxy.d.ts +84 -0
  116. package/dist/{state → model}/safe-effect.d.ts +50 -2
  117. package/dist/model/types.d.ts +239 -0
  118. package/dist/model.d.ts +2 -0
  119. package/dist/model.js +27 -0
  120. package/dist/node-kind-C-r6ZMdo.js +15 -0
  121. package/dist/platforms/react/field-binding/field-adapter.d.ts +87 -0
  122. package/dist/platforms/react/field-binding/field-handle.d.ts +53 -0
  123. package/dist/platforms/react/form-bundle-context.d.ts +27 -0
  124. package/dist/{form → platforms/react}/hooks/types.d.ts +60 -38
  125. package/dist/platforms/react/hooks/use-form-bundle.d.ts +41 -0
  126. package/dist/platforms/react/hooks/use-form-flow.d.ts +40 -0
  127. package/dist/{form → platforms/react}/hooks/use-form-validation.d.ts +13 -7
  128. package/dist/{form → platforms/react}/hooks/useArrayLength.d.ts +6 -6
  129. package/dist/{form → platforms/react}/hooks/useFormControl.d.ts +7 -9
  130. package/dist/{form → platforms/react}/hooks/useFormControlValue.d.ts +18 -18
  131. package/dist/{form → platforms/react}/hooks/useSignalSubscription.d.ts +9 -1
  132. package/dist/platforms/react/i18n/context.d.ts +18 -0
  133. package/dist/platforms/react/i18n/hooks.d.ts +65 -0
  134. package/dist/platforms/react/i18n/provider.d.ts +59 -0
  135. package/dist/platforms/react/index.d.ts +30 -0
  136. package/dist/react.d.ts +22 -0
  137. package/dist/react.js +505 -0
  138. package/dist/runtime-token.d.ts +22 -0
  139. package/dist/safe-effect-BazLOv1g.js +669 -0
  140. package/dist/schema-controller-CpiO2JoK.js +143 -0
  141. package/dist/signals.d.ts +15 -9
  142. package/dist/signals.js +11 -6
  143. package/dist/strategy-DzvnsWLh.js +375 -0
  144. package/dist/type-guards-D-N_5Ddh.js +19 -0
  145. package/dist/validation-issue-B9mjI8jz.js +7 -0
  146. package/dist/validation-message-Ced9MGxs.js +194 -0
  147. package/dist/validation.d.ts +1 -1
  148. package/dist/validation.js +11 -165
  149. package/dist/validators/email.d.ts +1 -1
  150. package/dist/validators/email.js +5 -8
  151. package/dist/validators/future-date.d.ts +1 -1
  152. package/dist/validators/future-date.js +10 -13
  153. package/dist/validators/integer.d.ts +1 -1
  154. package/dist/validators/integer.js +4 -7
  155. package/dist/validators/is-date.d.ts +1 -1
  156. package/dist/validators/is-date.js +5 -8
  157. package/dist/validators/is-number.d.ts +1 -1
  158. package/dist/validators/is-number.js +4 -7
  159. package/dist/validators/max-age.d.ts +1 -1
  160. package/dist/validators/max-age.js +8 -12
  161. package/dist/validators/max-date.d.ts +1 -1
  162. package/dist/validators/max-date.js +10 -13
  163. package/dist/validators/max-length.d.ts +1 -1
  164. package/dist/validators/max-length.js +7 -10
  165. package/dist/validators/max.d.ts +1 -1
  166. package/dist/validators/max.js +4 -7
  167. package/dist/validators/min-age.d.ts +1 -1
  168. package/dist/validators/min-age.js +10 -11
  169. package/dist/validators/min-date.d.ts +1 -1
  170. package/dist/validators/min-date.js +8 -11
  171. package/dist/validators/min-length.d.ts +1 -1
  172. package/dist/validators/min-length.js +4 -7
  173. package/dist/validators/min.d.ts +1 -1
  174. package/dist/validators/min.js +4 -7
  175. package/dist/validators/multiple-of.d.ts +1 -1
  176. package/dist/validators/multiple-of.js +11 -10
  177. package/dist/validators/non-negative.d.ts +1 -1
  178. package/dist/validators/non-negative.js +2 -5
  179. package/dist/validators/non-zero.d.ts +1 -1
  180. package/dist/validators/non-zero.js +4 -7
  181. package/dist/validators/past-date.d.ts +1 -1
  182. package/dist/validators/past-date.js +10 -13
  183. package/dist/validators/pattern.d.ts +1 -1
  184. package/dist/validators/pattern.js +5 -8
  185. package/dist/validators/phone.d.ts +1 -1
  186. package/dist/validators/phone.js +10 -11
  187. package/dist/validators/required.d.ts +1 -1
  188. package/dist/validators/required.js +4 -7
  189. package/dist/validators/url.d.ts +1 -1
  190. package/dist/validators/url.js +48 -17
  191. package/dist/validators.d.ts +1 -5
  192. package/dist/validators.js +98 -154
  193. package/docs/llms/01-api-reference.md +89 -0
  194. package/docs/llms/02-quick-start.md +181 -0
  195. package/docs/llms/03-api-signatures.md +494 -0
  196. package/docs/llms/04-common-patterns.md +204 -0
  197. package/docs/llms/05-common-mistakes.md +192 -0
  198. package/docs/llms/06-troubleshooting.md +16 -0
  199. package/docs/llms/07-complete-import.md +130 -0
  200. package/docs/llms/08-form-types.md +54 -0
  201. package/docs/llms/09-formschema.md +191 -0
  202. package/docs/llms/10-arrays.md +241 -0
  203. package/docs/llms/11-async-watchfield.md +53 -0
  204. package/docs/llms/12-array-cleanup.md +31 -0
  205. package/docs/llms/13-multi-step.md +162 -0
  206. package/docs/llms/14-extended-mistakes.md +101 -0
  207. package/docs/llms/15-project-structure.md +279 -0
  208. package/docs/llms/16-ui-components.md +229 -0
  209. package/docs/llms/17-nonexistent-api.md +278 -0
  210. package/docs/llms/18-conditional-fields.md +222 -0
  211. package/docs/llms/19-reading-values.md +100 -0
  212. package/docs/llms/20-compute-vs-watch.md +153 -0
  213. package/docs/llms/21-array-operations.md +163 -0
  214. package/docs/llms/22-cycle-detection.md +86 -0
  215. package/docs/llms/23-copy-from.md +141 -0
  216. package/docs/llms/24-sync-fields.md +115 -0
  217. package/docs/llms/25-reset-when.md +122 -0
  218. package/docs/llms/26-transform-value.md +136 -0
  219. package/docs/llms/27-revalidate-when.md +133 -0
  220. package/docs/llms/28-submit-and-reset.md +409 -0
  221. package/docs/llms/29-async-preload.md +203 -0
  222. package/docs/llms/30-type-safety-recipes.md +213 -0
  223. package/docs/llms/31-async-validator-debounce.md +178 -0
  224. package/docs/llms/32-async-options-loading.md +108 -0
  225. package/docs/llms/33-validation-strategy.md +305 -0
  226. package/docs/llms/34-i18n.md +298 -0
  227. package/docs/llms/35-unified-contract.md +309 -0
  228. package/docs/llms/36-issue-messages.md +284 -0
  229. package/docs/llms/37-compiled-schema.md +332 -0
  230. package/docs/llms/38-form-flow.md +396 -0
  231. package/llms-index.json +1 -0
  232. package/llms.txt +10014 -3826
  233. package/package.json +77 -15
  234. package/dist/behaviors-node-DGEFMTQu.js +0 -18
  235. package/dist/behaviors-value-C7dSEhCc.js +0 -134
  236. package/dist/date-utils-dTT_x_Be.js +0 -31
  237. package/dist/derived-registry-CluZCQ7U.js +0 -16
  238. package/dist/form/behaviors.d.ts +0 -133
  239. package/dist/form/error-handler.d.ts +0 -166
  240. package/dist/form/factories/index.d.ts +0 -6
  241. package/dist/form/factories/node-factory.d.ts +0 -188
  242. package/dist/form/form-submitter.d.ts +0 -125
  243. package/dist/form/nodes/array-node.d.ts +0 -360
  244. package/dist/form/nodes/field-node.d.ts +0 -294
  245. package/dist/form/nodes/form-node.d.ts +0 -340
  246. package/dist/form/nodes/group-node.d.ts +0 -288
  247. package/dist/form/nodes/model-array-node.d.ts +0 -121
  248. package/dist/form/status-machine.d.ts +0 -153
  249. package/dist/form/types/deep-schema.d.ts +0 -116
  250. package/dist/form/types/form-proxy.d.ts +0 -141
  251. package/dist/form/unique-id.d.ts +0 -53
  252. package/dist/form/validation/validators/date-utils.d.ts +0 -30
  253. package/dist/form/validation/validators/email.d.ts +0 -23
  254. package/dist/form/validation/validators/future-date.d.ts +0 -23
  255. package/dist/form/validation/validators/integer.d.ts +0 -22
  256. package/dist/form/validation/validators/is-date.d.ts +0 -23
  257. package/dist/form/validation/validators/is-number.d.ts +0 -24
  258. package/dist/form/validation/validators/max-age.d.ts +0 -25
  259. package/dist/form/validation/validators/max-date.d.ts +0 -25
  260. package/dist/form/validation/validators/max-files.d.ts +0 -26
  261. package/dist/form/validation/validators/max-length.d.ts +0 -27
  262. package/dist/form/validation/validators/max-total-file-size.d.ts +0 -26
  263. package/dist/form/validation/validators/max.d.ts +0 -25
  264. package/dist/form/validation/validators/min-age.d.ts +0 -25
  265. package/dist/form/validation/validators/min-date.d.ts +0 -25
  266. package/dist/form/validation/validators/min-files.d.ts +0 -26
  267. package/dist/form/validation/validators/min-length.d.ts +0 -27
  268. package/dist/form/validation/validators/min.d.ts +0 -25
  269. package/dist/form/validation/validators/multiple-of.d.ts +0 -24
  270. package/dist/form/validation/validators/non-negative.d.ts +0 -22
  271. package/dist/form/validation/validators/non-zero.d.ts +0 -22
  272. package/dist/form/validation/validators/past-date.d.ts +0 -23
  273. package/dist/form/validation/validators/pattern.d.ts +0 -33
  274. package/dist/form/validation/validators/required.d.ts +0 -32
  275. package/dist/form/validation/validators/url.d.ts +0 -43
  276. package/dist/form/validation-schema.d.ts +0 -106
  277. package/dist/form/validation-strategy.d.ts +0 -55
  278. package/dist/form/validators.d.ts +0 -6
  279. package/dist/form-model-DYCzGGKF.js +0 -286
  280. package/dist/state/index.d.ts +0 -31
  281. package/dist/state/subscription-manager.d.ts +0 -180
  282. package/dist/state/types.d.ts +0 -144
  283. package/dist/state.d.ts +0 -2
  284. package/dist/state.js +0 -21
  285. package/dist/subscription-manager-705bls97.js +0 -171
@@ -1,91 +1,5 @@
1
- import { FormSchema } from './deep-schema';
2
- import { FormNode } from '../nodes/form-node';
3
- export type { FormValue, UnknownFormValue, ValidatorFn, AsyncValidatorOptions, AsyncValidatorFn, ValidationError, ErrorFilterOptions, FieldStatus, } from './contracts';
4
- export type { FieldConfig } from './deep-schema';
5
- export type { Validator, AsyncValidator, ConditionFn, ValidateOptions, ValidateAsyncOptions, } from './validation-schema';
6
- export type { FormSchema, ArrayConfig } from './deep-schema';
7
- export type { FormSchemaNode, SchemaArrayControl, SchemaValidator } from './schema-node';
8
- export type { FormControlsProxy, FormProxy, FormArrayProxy } from './form-proxy';
9
- /**
10
- * Конфигурация GroupNode.
11
- *
12
- * Под M1 группа создаётся из плоской {@link FormSchema} (дерево field-конфигов). Обёртка
13
- * `{ form }` сохранена для совместимости вызова, legacy behavior/validation-схемы удалены (Ф7).
14
- *
15
- * @group Types
16
- * @category Configuration Types
17
- */
18
- export interface GroupNodeConfig<T> {
19
- /** Схема структуры формы (поля и их конфигурация) */
20
- form: FormSchema<T>;
21
- }
22
- /**
23
- * Тип для Record с unknown значениями
24
- * Используется вместо инлайнового `Record<string, unknown>`
25
- * @internal
26
- */
27
- export type UnknownRecord = Record<string, unknown>;
28
- /**
29
- * Интерфейс для узлов с методом applyValidationSchema
30
- * @internal
31
- */
32
- export interface WithValidationSchema {
33
- applyValidationSchema(schemaFn: unknown): void;
34
- }
35
- /**
36
- * Интерфейс для узлов с методом applyBehaviorSchema
37
- * @internal
38
- */
39
- export interface WithBehaviorSchema {
40
- applyBehaviorSchema(schemaFn: unknown): void;
41
- }
42
- /**
43
- * Интерфейс для узлов, похожих на ArrayNode (с методом at)
44
- * Используется для duck typing при обходе путей
45
- * @internal
46
- */
47
- export interface ArrayNodeLike {
48
- at(index: number): FormNode<unknown> | undefined;
49
- length: unknown;
50
- }
51
- /**
52
- * Конфиг с полем schema (для ArrayConfig)
53
- * @internal
54
- */
55
- export interface ConfigWithSchema {
56
- schema: unknown;
57
- initialItems?: unknown[];
58
- }
59
- /**
60
- * Конфиг с полем value (для извлечения значений)
61
- * @internal
62
- */
63
- export interface ConfigWithValue {
64
- value: unknown;
65
- }
66
- /**
67
- * Тип для путей к полям (field paths)
68
- * Используется в навигации по полям вместо any
69
- * @internal
70
- */
71
- export type FieldPathSegment = {
72
- key: string;
73
- index?: number;
74
- };
75
- /**
76
- * Тип для коллбэков и обработчиков событий
77
- * Используется вместо (...args: any[]) => any
78
- * @internal
79
- */
80
- export type UnknownCallback = (...args: unknown[]) => unknown;
81
- /**
82
- * Тип для проверки на функцию в conditional types
83
- * Используется вместо Function для type narrowing
84
- * @internal
85
- */
86
- export type AnyFunction = (...args: never[]) => unknown;
87
- /**
88
- * Тип для результатов загрузки ресурсов
89
- * @internal
90
- */
91
- export type ResourceLoadResult = unknown;
1
+ export type { ValidationIssue } from './contracts';
2
+ export type { FieldConfig } from './field-config';
3
+ export type { RuleOptions } from './validation-schema';
4
+ export type { ComponentRef, FormSchemaNode, SchemaFieldNode, SchemaArrayNode, SchemaPartNode, SchemaContainerNode, SchemaChild, SchemaValueHandle, SchemaArrayHandle, SchemaGroupHandle, SchemaArrayControl, } from './schema-node';
5
+ export type { FormNode, FormControl, FormGroup, FormArray, FormFields } from './nodes';
@@ -0,0 +1,159 @@
1
+ import { ReadonlySignal } from '@preact/signals-core';
2
+ import { ValidationIssue } from './contracts';
3
+ import { ComponentRef } from './schema-node';
4
+ /**
5
+ * Общий контракт ноды формы — поля, группы и массива под-форм.
6
+ *
7
+ * Значением нода не владеет: источник истины — модель (`model.$.<путь>`), нода держит состояние
8
+ * взаимодействия (`touched`, `dirty`), доступность и замечания валидации.
9
+ *
10
+ * @typeParam T - Значение ноды
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const { form } = createForm<{ email: string }>({ initial: { email: '' } });
15
+ * form.email.setValue('user@mail.com');
16
+ * form.email.markAsTouched();
17
+ * form.valid.value; // true — замечаний нет
18
+ * ```
19
+ */
20
+ export interface FormNode<T> {
21
+ /** Текущее значение. */
22
+ readonly value: ReadonlySignal<T>;
23
+ /** Замечаний, которые блокируют отправку, нет; нода включена и не ждёт проверки. */
24
+ readonly valid: ReadonlySignal<boolean>;
25
+ /** Есть блокирующие замечания; нода включена и не ждёт проверки. */
26
+ readonly invalid: ReadonlySignal<boolean>;
27
+ /** Идёт асинхронная проверка. */
28
+ readonly pending: ReadonlySignal<boolean>;
29
+ /** Нода отключена: её замечания сняты, в проверку она не входит. */
30
+ readonly disabled: ReadonlySignal<boolean>;
31
+ /** Пользователь взаимодействовал с нодой. */
32
+ readonly touched: ReadonlySignal<boolean>;
33
+ /** Значение меняли после создания или сброса. */
34
+ readonly dirty: ReadonlySignal<boolean>;
35
+ /** Замечания ноды; у группы и массива — свои и всех детей. */
36
+ readonly issues: ReadonlySignal<readonly ValidationIssue[]>;
37
+ /**
38
+ * Собственные замечания ноды — без замечаний детей: у группы и массива это правила на их ручке
39
+ * (`minLength` массива, `cross` группы), у поля — то же, что `issues`.
40
+ */
41
+ readonly ownIssues: ReadonlySignal<readonly ValidationIssue[]>;
42
+ /** Значение без подписки. */
43
+ getValue(): T;
44
+ /** Записать значение в модель. */
45
+ setValue(value: T): void;
46
+ /**
47
+ * Вернуть значение и состояние к начальным; с аргументом — к переданному значению. В цель
48
+ * `compute` значение не пишется (кроме явного `reset(значение)` самого поля): ею владеет
49
+ * поведение — сбрасывается только состояние.
50
+ */
51
+ reset(value?: T): void;
52
+ markAsTouched(): void;
53
+ markAsUntouched(): void;
54
+ enable(): void;
55
+ disable(): void;
56
+ /** Поставить замечания извне (ответ сервера, своя проверка). */
57
+ setIssues(issues: readonly ValidationIssue[]): void;
58
+ clearIssues(): void;
59
+ }
60
+ /**
61
+ * Поле формы: нода над листом модели и состояние его компонента.
62
+ *
63
+ * @typeParam T - Значение поля
64
+ */
65
+ export interface FormControl<T> extends FormNode<T> {
66
+ /** Компонент поля из узла схемы. */
67
+ readonly component: ComponentRef | undefined;
68
+ /** Пропсы компонента: из узла схемы и правок {@link FormControl.updateComponentProps}. */
69
+ readonly componentProps: ReadonlySignal<Readonly<Record<string, unknown>>>;
70
+ /**
71
+ * Показывать ли состояние ошибки (`aria-invalid`, рамка): поле невалидно и его трогали или
72
+ * меняли. Предупреждение (`severity: 'warning'`) поле невалидным не делает — тексты замечаний
73
+ * показывают по {@link FormControl.shouldShowIssues}.
74
+ */
75
+ readonly shouldShowError: ReadonlySignal<boolean>;
76
+ /**
77
+ * Показывать ли тексты замечаний: у поля есть замечания — ошибки или предупреждения, — и его
78
+ * трогали или меняли. Условия те же, что у {@link FormControl.shouldShowError} (не выключено,
79
+ * проверка не идёт), но в счёт идёт любое замечание, а не только блокирующее.
80
+ */
81
+ readonly shouldShowIssues: ReadonlySignal<boolean>;
82
+ /** Слить правку в пропсы компонента (например, опции после загрузки справочника). */
83
+ updateComponentProps(patch: Record<string, unknown>): void;
84
+ }
85
+ /**
86
+ * Массив под-форм: строка — {@link FormGroup} над элементом массива модели.
87
+ *
88
+ * Данными массив не владеет: мутации уходят в массив модели, формы строк держатся за под-модели
89
+ * и при `move`/`swap` не пересоздаются.
90
+ *
91
+ * Индексы (`at`, `keyAt`, `insert`, `removeAt`, `move`, `swap`) — по строкам формы. Элемент `null`
92
+ * в массиве модели строкой не становится, и индекс строки может не совпасть с индексом модели.
93
+ *
94
+ * @typeParam T - Элемент массива
95
+ */
96
+ export interface FormArray<T extends object> extends FormNode<T[]> {
97
+ /** Число строк; чтение в эффекте или `computed` подписывает на изменения. */
98
+ readonly length: number;
99
+ at(index: number): FormGroup<T> | undefined;
100
+ map<R>(callback: (row: FormGroup<T>, index: number) => R): R[];
101
+ forEach(callback: (row: FormGroup<T>, index: number) => void): void;
102
+ /** Стабильный ключ строки: держится за элемент модели и не меняется при `move` и `swap`. */
103
+ keyAt(index: number): string;
104
+ /** Добавить строку; без значения — по шаблону массива модели (`arrayOf(blank)`). */
105
+ push(item?: T): void;
106
+ insert(index: number, item?: T): void;
107
+ removeAt(index: number): void;
108
+ move(from: number, to: number): void;
109
+ swap(first: number, second: number): void;
110
+ clear(): void;
111
+ }
112
+ /**
113
+ * Признак «объект-группа»: обычный объект, а не массив, дата, файл, функция или примитив.
114
+ * `extends object` ловит и `interface`, и `type` (интерфейс не приводится к `Record`).
115
+ * Значение неизвестной формы (`unknown`, `{}`) — поле: у него нет известных полей, и словарь
116
+ * `Record<string, unknown>` остаётся группой полей, а не группой групп — иначе такая группа не
117
+ * приводилась бы к `FormGroup<any>` внутри обобщённых типов (контекст React, элементы списка).
118
+ *
119
+ * @internal
120
+ */
121
+ type IsGroupObject<V> = V extends ReadonlyArray<unknown> ? false : V extends Date | File | Blob ? false : V extends (...args: never[]) => unknown ? false : V extends object ? Record<never, never> extends V ? false : true : false;
122
+ /** `T` — это `any`. @internal */
123
+ type IsAny<T> = 0 extends 1 & T ? true : false;
124
+ /**
125
+ * Ноды полей группы по именам полей данных: массив объектов — {@link FormArray}, объект —
126
+ * {@link FormGroup}, остальное (примитивы, массивы примитивов, даты, файлы) — {@link FormControl}.
127
+ * Опциональность снята: нода есть у каждого поля, опционально лишь значение.
128
+ *
129
+ * `FormFields<any>` — нестрогий словарь: так группа любой формы приводится к `FormGroup<any>`
130
+ * (контекст React, обобщённые компоненты), а не упирается в отображение полей типа `any`.
131
+ *
132
+ * @typeParam T - Значение группы
133
+ */
134
+ export type FormFields<T> = IsAny<T> extends true ? Record<string, any> : {
135
+ [K in keyof T]-?: NonNullable<T[K]> extends ReadonlyArray<infer U> ? IsGroupObject<U> extends true ? FormArray<U & object> : FormControl<T[K]> : IsGroupObject<NonNullable<T[K]>> extends true ? FormGroup<NonNullable<T[K]>> : FormControl<T[K]>;
136
+ };
137
+ /**
138
+ * Группа полей: нода над группой модели и доступ к нодам полей.
139
+ *
140
+ * `form.email` — нода поля; поле с именем члена {@link FormNode} (`value`, `issues`, `reset`, …)
141
+ * недостижимо точкой и доступно через `form.$`: `form.$.value`. Остальные имена полей данных
142
+ * (`id`, `status`, `fields`, `submit`, …) ничем не затенены.
143
+ *
144
+ * @typeParam T - Значение группы
145
+ *
146
+ * @example
147
+ * ```typescript
148
+ * interface Order { status: string; value: number; customer: { name: string } }
149
+ * const { form } = createForm<Order>({ initial: { status: 'new', value: 0, customer: { name: '' } } });
150
+ * form.status.setValue('paid'); // поле данных
151
+ * form.$.value.setValue(100); // поле, затенённое членом ноды
152
+ * form.customer.name.markAsTouched();
153
+ * ```
154
+ */
155
+ export type FormGroup<T> = FormNode<T> & Omit<FormFields<T>, keyof FormNode<T>> & {
156
+ /** Ноды всех полей по имени, включая затенённые членами {@link FormNode}. */
157
+ readonly $: FormFields<T>;
158
+ };
159
+ export {};
@@ -1,17 +1,22 @@
1
- import { ElementType } from 'react';
2
- import { ValidationError } from './contracts';
1
+ import { Signal } from '../../signals';
3
2
  /**
4
- * Валидатор поля схемы (legacy). Дерево-движок, вызывавший `validators` узла как
5
- * `(value, scope, root)`, удалён — живые правила это `Rule<T>` в `validate(sig, [...])`
6
- * (`@reformer/core/validation`). Тип остаётся широким по параметрам для совместимости
7
- * узлов, всё ещё несущих `validators` (гетерогенные контракты `ValidatorFn`/`Validator`).
3
+ * Ссылка на компонент узла схемы: то, что слой представления умеет нарисовать. Для React это
4
+ * компонент (функция либо объект `forwardRef`/`memo`) или имя HTML-тега (`'div'`, `'h3'`).
5
+ *
6
+ * Ядро ссылку не интерпретирует и о слое представления не знает: она доезжает до рендерера как
7
+ * есть, а к типу своего UI-слоя её приводит уже он.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * const byComponent: ComponentRef = Input; // React-компонент
12
+ * const byTag: ComponentRef = 'section'; // HTML-тег
13
+ * ```
8
14
  *
9
15
  * @group Types
10
16
  */
11
- export type SchemaValidator = (value: any, ...rest: any[]) => ValidationError | null | Promise<ValidationError | null>;
17
+ export type ComponentRef = string | object;
12
18
  /**
13
- * Минимальный контракт реактивного массива модели ({@link FormSchemaNode.array}).
14
- * Совпадает по форме с рантайм-фасадом `model.<array>` (см. `ModelArray`); рендерерский
19
+ * Контракт реактивного массива модели — фасада `model.<массив>`. Рендерерский
15
20
  * `RenderModelArrayControl` — его расширение (добавляет `move`).
16
21
  *
17
22
  * @group Types
@@ -22,62 +27,155 @@ export interface SchemaArrayControl {
22
27
  /** Реактивная длина. */
23
28
  readonly length: number;
24
29
  at(index: number): unknown;
25
- push(item: unknown): void;
30
+ push(item?: unknown): void;
26
31
  removeAt(index: number): void;
27
32
  }
28
33
  /**
29
- * Узел единой схемы M1 — layout-дерево, обходимое `createForm({ model, schema })`
30
- * и рендерерами (schema-валидация живёт отдельно — `@reformer/core/validation`).
34
+ * Ручка значения из дерева `model.$`: лист (`model.$.email`) или массив целиком
35
+ * (`model.$.tags`). Группа ручкой значения не является — у неё нет пути.
31
36
  *
32
- * Узел совмещает несколько ролей (различаются рантаймом по форме):
33
- * - **поле** — несёт `value: Signal` (сигнал модели `model.$.x`) + `component`/`validators`;
34
- * - **массив** — `{ array: model.<path>, item(itemModel) }`;
35
- * - **контейнер/ветка** — вложенные узлы (`children`), опц. условие `when`;
36
- * - **record-of-fields** — под-узлы под произвольными именованными ключами (индексная сигнатура).
37
+ * @group Types
38
+ */
39
+ export type SchemaValueHandle = Signal<any> & {
40
+ readonly __path: string;
41
+ };
42
+ /**
43
+ * Ручка массива из дерева `model.$` (`model.$.phones`) — ручка значения с длиной.
37
44
  *
38
- * Индексная сигнатура (`[key: string]: unknown`) отражает свободный рекурсивный обход: под-узлы
39
- * допустимы под любым ключом. Известные поля типизированы (даёт автокомплит и проверку их типов).
45
+ * @group Types
46
+ */
47
+ export type SchemaArrayHandle = SchemaValueHandle & {
48
+ readonly length: number;
49
+ };
50
+ /**
51
+ * Ручка группы из дерева `model.$` (`model.$.address`).
40
52
  *
41
53
  * @group Types
42
54
  */
43
- export interface FormSchemaNode {
55
+ export interface SchemaGroupHandle {
56
+ peek(): object | null | undefined;
57
+ /** Признак «не ручка значения»: у листа и массива путь есть, у группы — нет. */
58
+ readonly __path?: never;
59
+ }
60
+ /** Ключи, общие для узла любого вида. */
61
+ interface SchemaNodeBase {
44
62
  /**
45
- * «Ручка» значения поля — маркер узла-поля. Обычно сигнал модели (`model.$.<path>`), но форма
46
- * зависит от таргета (для массива `model.$.x` — дерево сигналов; в renderer-типах сужается до
47
- * `Signal`). Движок разбирает узел как поле рантаймом по `value instanceof Signal`.
63
+ * UI-компонент либо нативный HTML-тег (`'div'`, `'p'`, `'h3'`) для презентационной вёрстки
64
+ * прямо в схеме. Опционален: ядро работает без UI и `component` не интерпретирует — он доезжает
65
+ * до рендерера как есть.
48
66
  */
49
- value?: unknown;
67
+ component?: ComponentRef;
50
68
  /**
51
- * UI-компонент либо нативный HTML-тег (`'div'`, `'p'`, `'h3'`) для презентационной вёрстки
52
- * прямо в схеме. Опционален: core-часть работает без UI (значение/валидация) и `component`
53
- * не интерпретирует — он доезжает до рендерера как есть.
69
+ * Пропсы компонента. Вложенных узлов здесь нет: обход схемы в пропсы не заглядывает, дети узла
70
+ * пишутся в `children`.
54
71
  */
55
- component?: ElementType;
56
- /** Props компонента. Также «клапан» для вложенности под-узлов (напр. steps визарда). */
57
72
  componentProps?: Record<string, unknown>;
58
- validators?: SchemaValidator[];
59
- asyncValidators?: SchemaValidator[];
60
- updateOn?: 'change' | 'blur' | 'submit';
61
- disabled?: boolean;
62
- /** Задержка (мс) перед запуском асинхронной валидации. */
63
- debounce?: number;
64
- /** Идентификатор узла (для wizard/tabs/renderBehavior). */
73
+ /** Идентификатор узла: по нему узел адресуют поведение (`schema.node(...)`) и шаги визарда. */
65
74
  selector?: string;
66
- testId?: string;
67
- /** Дочерние узлы (даёт контекстную типизацию вложенным литералам — value/validators/when). */
68
- children?: readonly FormSchemaNode[];
69
- /** Условие включения поддерева (branch-узел `{ when, children }`). */
70
- when?: (scope: any, root: any) => boolean;
71
- /** Реактивный массив модели (`model.<path>`) — маркер узла-массива (вместе с `item`). */
72
- array?: SchemaArrayControl;
73
- /** Схема элемента массива: под-модель элемента → узел поддерева. */
74
- item?: (itemModel: any) => FormSchemaNode;
75
75
  /**
76
- * Значение нового элемента массива для кнопки «Добавить»: либо готовое значение,
77
- * либо фабрика `() => value`. Тип не различает варианты (union `unknown | (() => unknown)`
78
- * схлопывается в `unknown`) — рантайм различает по `typeof initialValue === 'function'`.
76
+ * Прежний ключ привязки поля — его нет: пишите `model: model.$.<поле>`.
77
+ *
78
+ * Запрет объявлен явно: в `children` узел стоит в объединении с реактивным текстом
79
+ * (`Signal`, у которого есть `value`), и без него прежний ключ проходил проверку лишних ключей.
80
+ */
81
+ value?: never;
82
+ /** Прежний ключ привязки массива — его нет: пишите `model: model.$.<массив>` вместе с `item`. */
83
+ array?: never;
84
+ }
85
+ /**
86
+ * Поле: узел, привязанный к ручке значения — листу или массиву целиком (мультивыбор, теги, файлы).
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * { model: model.$.email, component: Input, componentProps: { label: 'Email' } }
91
+ * ```
92
+ *
93
+ * @group Types
94
+ */
95
+ export interface SchemaFieldNode extends SchemaNodeBase {
96
+ /** Привязка поля — ручка значения `model.$.<лист | массив>`. */
97
+ model: SchemaValueHandle;
98
+ /**
99
+ * Поле создаётся отключённым — и остаётся: это постоянная блокировка (вычисляемые `total`,
100
+ * `fullName`). `enable()` группы, массива или формы её не снимает; снимает только явный
101
+ * `enable()` самого поля либо оператор `enableWhen` на нём.
102
+ */
103
+ disabled?: boolean;
104
+ item?: never;
105
+ part?: never;
106
+ children?: never;
107
+ }
108
+ /**
109
+ * Массив под-форм: у каждой строки своя форма, разметку строки строит `item`.
110
+ *
111
+ * @example
112
+ * ```ts
113
+ * { model: model.$.phones, component: FieldArray, item: (row) => ({ children: [...] }) }
114
+ * ```
115
+ *
116
+ * @group Types
117
+ */
118
+ export interface SchemaArrayNode extends SchemaNodeBase {
119
+ /** Привязка — ручка массива `model.$.<массив>`. */
120
+ model: SchemaArrayHandle;
121
+ /** Схема строки: под-модель строки → узел поддерева. */
122
+ item: (model: any) => FormSchemaNode;
123
+ /**
124
+ * Шаблон нового элемента массива для кнопки «Добавить»: либо готовое значение, либо фабрика
125
+ * `() => value`. Запасной путь — для форм, чья модель создаётся из данных без кода: шаблон,
126
+ * объявленный в модели (`arrayOf(blank)`), главнее.
127
+ *
128
+ * Тип не различает варианты (union `unknown | (() => unknown)` схлопывается в `unknown`) —
129
+ * рантайм различает по `typeof initialValue === 'function'`.
79
130
  */
80
131
  initialValue?: unknown;
81
- /** Свободная вложенность: record-of-fields и произвольные под-узлы. */
82
- [key: string]: unknown;
132
+ part?: never;
133
+ children?: never;
134
+ }
135
+ /**
136
+ * Подформа: часть схемы, подключённая к группе модели. Часть объявляется один раз и подключается
137
+ * к любой группе той же формы данных; привязки внутри части идут через `$` полученной под-модели.
138
+ *
139
+ * @example
140
+ * ```ts
141
+ * { model: model.$.registrationAddress, part: address }
142
+ * ```
143
+ *
144
+ * @group Types
145
+ */
146
+ export interface SchemaPartNode extends SchemaNodeBase {
147
+ /** Привязка — ручка группы `model.$.<группа>`. */
148
+ model: SchemaGroupHandle;
149
+ /** Часть схемы: под-модель группы → узел поддерева. */
150
+ part: (model: any) => FormSchemaNode;
151
+ item?: never;
152
+ children?: never;
153
+ }
154
+ /** Ребёнок контейнера: вложенный узел либо текстовая часть — литерал, число, сигнал модели. */
155
+ export type SchemaChild = FormSchemaNode | string | number | Signal<any>;
156
+ /**
157
+ * Контейнер: узел с детьми (секция, шаг визарда, html-тег). Текст — такой же ребёнок, как узел:
158
+ * ядро его не интерпретирует, а рендерер выводит на своём месте в порядке следования.
159
+ *
160
+ * @example
161
+ * ```ts
162
+ * { component: Section, componentProps: { title: 'Контакты' }, children: [phoneField, emailField] }
163
+ * ```
164
+ *
165
+ * @group Types
166
+ */
167
+ export interface SchemaContainerNode extends SchemaNodeBase {
168
+ children?: readonly SchemaChild[];
169
+ model?: never;
170
+ item?: never;
171
+ part?: never;
83
172
  }
173
+ /**
174
+ * Узел схемы формы: поле, массив под-форм, подформа или контейнер — см. описание модуля.
175
+ *
176
+ * Тип закрыт: опечатка в ключе, группа без `part` и `item` не на массиве — ошибки компиляции.
177
+ *
178
+ * @group Types
179
+ */
180
+ export type FormSchemaNode = SchemaFieldNode | SchemaArrayNode | SchemaPartNode | SchemaContainerNode;
181
+ export {};
@@ -1,49 +1,32 @@
1
- import { FormValue, ValidationError } from './index';
2
- import { FormModel } from '../../state/types';
3
1
  /**
4
- * Чистый синхронный валидатор поля (legacy-сигнатура `(value, scope, root)`).
2
+ * Типы фабрик валидаторов (`@reformer/core/validators`).
5
3
  *
6
- * @deprecated Осиротевший остаток удалённого дерево-движка (`validateFormModel`). Живой контракт —
7
- * `Rule<T> = (value) => ValidationError | null` из `@reformer/core/validation`: правила
8
- * передаются в `validate(sig, [rules])` внутри `defineValidationSchema` и запускаются
9
- * `validateModel(model, schema)`. Cross-field — оператор `cross(sig, (f) => …)` над снапшотом
10
- * `model.get()` (третий аргумент `root` больше не нужен). Тип экспортируется только ради
11
- * обратной совместимости (`SchemaValidator`-union).
4
+ * Контракт валидации — `@reformer/core/validation`: `defineValidation` + операторы
5
+ * (`validate`/`validateAsync`/`validateWhen`/`cross`/`apply`/`applyEach`) и раннер
6
+ * `validateModel(model, definition)`; правила там — `Rule<T> = (value) => issue | null`.
12
7
  */
13
- export type Validator<TForm, TField> = (value: TField, scope: unknown, root: FormModel<TForm>) => ValidationError | null;
14
8
  /**
15
- * Чистый асинхронный валидатор поля. Та же тройка аргументов `(value, scope, root)`, что у
16
- * {@link Validator}, но возвращает `Promise`.
9
+ * Опции валидатора-фабрики (`required()`/`pattern()`/…). Передаются вторым (или последним)
10
+ * аргументом в фабрику и попадают в возвращаемое {@link ValidationIssue}.
17
11
  *
18
- * @deprecated Осиротевший остаток удалённого оператора `validateAsync` (Ф7). Рантаймом не
19
- * потребляется — живой async-путь узла поля использует `AsyncValidatorFn` `(value, { signal })`.
20
- * Экспортируется только ради обратной совместимости.
21
- */
22
- export type AsyncValidator<TForm, TField> = (value: TField, scope: unknown, root: FormModel<TForm>) => Promise<ValidationError | null>;
23
- /**
24
- * Функция-предикат `(value) => boolean`.
12
+ * Текста среди опций нет: правило сообщает только код и параметры, а строку по коду даёт слой
13
+ * представления (`resolveIssueMessage` из `@reformer/core/i18n`). Нужен свой текст для
14
+ * конкретного поля — дайте правилу свой код и запись в словаре формы.
25
15
  *
26
- * @deprecated Осиротевший остаток удалённого оператора `applyWhen` (Ф7). Рантаймом не
27
- * потребляется; экспортируется только ради обратной совместимости.
28
- */
29
- export type ConditionFn<T> = (value: T) => boolean;
30
- /**
31
- * Опции валидатора-фабрики (`required()`/`pattern()`/…). Передаются вторым (или последним)
32
- * аргументом в фабрику и попадают в возвращаемую {@link ValidationError}.
33
- */
34
- export interface ValidateOptions {
35
- /** Готовое сообщение об ошибке. Если не задано, валидаторы кладут `''`, и отображаемый текст
36
- * резолвится из `code` (см. резолвер сообщений в `@reformer/cdk`). */
37
- message?: string;
38
- /** Параметры ошибки (подстановка в шаблон сообщения / i18n). */
39
- params?: Record<string, FormValue>;
40
- }
41
- /**
42
- * @deprecated Осиротевший остаток удалённого оператора `validateAsync` (Ф7): опция `debounce`
43
- * подключалась тем оператором, которого больше нет. Рантаймом не потребляется; экспортируется
44
- * только ради обратной совместимости.
16
+ * @example
17
+ * ```ts
18
+ * // правило
19
+ * required({ code: 'loanAmount.required' });
20
+ * // словарь формы (`defineIssueMessages`)
21
+ * const messages = defineIssueMessages({ 'loanAmount.required': 'Укажите сумму кредита' });
22
+ * ```
45
23
  */
46
- export interface ValidateAsyncOptions extends ValidateOptions {
47
- /** Задержка перед выполнением валидации (в мс). */
48
- debounce?: number;
24
+ export interface RuleOptions {
25
+ /**
26
+ * Свой код вместо встроенного. По нему текст ищется сначала в словаре формы, затем в локали
27
+ * (`validation.<code>`); принято именовать `<поле>.<правило>`.
28
+ */
29
+ code?: string;
30
+ /** Дополнительные параметры замечания: подставляются в текст поверх параметров правила. */
31
+ params?: Readonly<Record<string, unknown>>;
49
32
  }
@@ -0,0 +1,67 @@
1
+ import { FormModel, PathAwareSignal } from '../../model/types';
2
+ import { ValidationIssue } from '../types/contracts';
3
+ import { ValidationFailure } from './types';
4
+ /** Сток одного прогона: модель scope, накопленные ошибки, незавершённые async-правила, гейты. */
5
+ export interface VContext {
6
+ /**
7
+ * Модель текущей области — источник снапшота для `cross` и модель для `apply`. В корне прогона
8
+ * это вся модель; внутри `apply(ручка, схема)` / `applyEach` — под-модель группы или строки.
9
+ */
10
+ model: FormModel<unknown>;
11
+ /**
12
+ * Накопленные ошибки по сигналу (ключ — идентичность `PathAwareSignal`). Здесь и поля выключенной
13
+ * ветки `validateWhen` — с пустым списком: при разносе их прежние ошибки гасятся.
14
+ */
15
+ issues: Map<PathAwareSignal<unknown>, ValidationIssue[]>;
16
+ /**
17
+ * Поля, правила которых в этом прогоне действительно выполнялись — ветка активна. Только их разнос
18
+ * с `touch` помечает тронутыми: поле выключенной ветки пользователь не видел.
19
+ */
20
+ checked: Set<PathAwareSignal<unknown>>;
21
+ /** Незавершённые async-правила (раннер их дожидается). */
22
+ pending: Promise<void>[];
23
+ /** Поля с async-правилами: на время ожидания раннер держит их ноды в `pending`. */
24
+ asyncFields: Set<PathAwareSignal<unknown>>;
25
+ /**
26
+ * Правила, которые не вернули результат. Список — один на весь прогон: области `apply` /
27
+ * `applyEach` получают поверхностную копию контекста и пишут в ту же ссылку.
28
+ */
29
+ failures: ValidationFailure[];
30
+ /** Стек активных условий `validateWhen` (все должны быть истинны, чтобы правило сработало). */
31
+ whenStack: Array<() => boolean>;
32
+ /** Отмена устаревшего прогона: прокидывается в async-правила, гасит роутинг после await. */
33
+ signal: AbortSignal;
34
+ /**
35
+ * Определение, правила которого исполняются сейчас: корень прогона либо схема, подключённая
36
+ * `apply` / `applyEach`. Замечание помечается им: так разнос отличает замечания одного
37
+ * определения, полученные разными прогонами (шаг и вся форма), от замечаний чужого.
38
+ */
39
+ origin: object;
40
+ /** Замечания по полю и определению-источнику. Одна ссылка на весь прогон, как `failures`. */
41
+ origins: Map<PathAwareSignal<unknown>, Map<object, ValidationIssue[]>>;
42
+ /** Определения, исполненные в прогоне: за их замечания на проверенных полях прогон отвечает. */
43
+ executed: Set<object>;
44
+ }
45
+ /**
46
+ * Открыть ambient-окно на время `fn` и закрыть его в `finally`.
47
+ *
48
+ * Единственный способ установить контекст: прямое присваивание `current` из другого модуля
49
+ * невозможно. Сохранение/восстановление `prev` делает вложенный прогон безопасным.
50
+ */
51
+ export declare function runWithContext<R>(ctx: VContext, fn: () => R): R;
52
+ /** Контекст активного прогона либо понятная ошибка, если оператор вызван вне схемы. */
53
+ export declare function requireCtx(op: string): VContext;
54
+ /**
55
+ * «Тронуть» сигнал: гарантирует его наличие в замечаниях прогона (даже пустым) → он попадёт в
56
+ * очистку. Возвращает список текущего определения ({@link VContext.origin}): в него и пишут правила.
57
+ */
58
+ export declare function touch(ctx: VContext, sig: PathAwareSignal<unknown>): ValidationIssue[];
59
+ /** Исполнить определение: его замечания помечаются им же. */
60
+ export declare function withOrigin(ctx: VContext, origin: object, fn: () => void): void;
61
+ /** Активна ли текущая ветка (все `validateWhen`-условия истинны). */
62
+ export declare const gated: (ctx: VContext) => boolean;
63
+ /**
64
+ * Правила поля выполняются: ветка активна. Поле запоминается проверенным ({@link VContext.checked}).
65
+ * Без активной ветки — `false`, и поле остаётся только в `issues` для гашения.
66
+ */
67
+ export declare function checking(ctx: VContext, sig: PathAwareSignal<unknown>): boolean;