@reformer/core 1.1.0 → 2.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 (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,12 +1,5 @@
1
- /**
2
- * Валидатор обязательного поля
3
- *
4
- * @group Validation
5
- * @category Validators
6
- * @module validators/required
7
- */
8
- import type { ValidateOptions } from '../../types/validation-schema';
9
- import type { FieldPathNode } from '../../types';
1
+ import { ValidateOptions } from '../../types/validation-schema';
2
+ import { FieldPathNode } from '../../types';
10
3
  /**
11
4
  * Валидатор обязательного поля
12
5
  *
@@ -1,12 +1,5 @@
1
- /**
2
- * Валидатор URL
3
- *
4
- * @group Validation
5
- * @category Validators
6
- * @module validators/url
7
- */
8
- import type { ValidateOptions } from '../../types/validation-schema';
9
- import type { FieldPathNode } from '../../types';
1
+ import { ValidateOptions } from '../../types/validation-schema';
2
+ import { FieldPathNode } from '../../types';
10
3
  /**
11
4
  * Адаптер для URL валидатора
12
5
  * Поддерживает опциональные поля (string | undefined)
@@ -0,0 +1,29 @@
1
+ function r(t) {
2
+ if (t == null || t === "")
3
+ return null;
4
+ if (t instanceof Date)
5
+ return isNaN(t.getTime()) ? null : t;
6
+ if (typeof t == "string") {
7
+ const n = new Date(t);
8
+ return isNaN(n.getTime()) ? null : n;
9
+ }
10
+ return null;
11
+ }
12
+ function e() {
13
+ const t = /* @__PURE__ */ new Date();
14
+ return t.setHours(0, 0, 0, 0), t;
15
+ }
16
+ function o(t) {
17
+ const n = new Date(t);
18
+ return n.setHours(0, 0, 0, 0), n;
19
+ }
20
+ function i(t) {
21
+ const n = e();
22
+ return Math.floor((n.getTime() - t.getTime()) / (365.25 * 24 * 60 * 60 * 1e3));
23
+ }
24
+ export {
25
+ i as c,
26
+ e as g,
27
+ o as n,
28
+ r as p
29
+ };
@@ -0,0 +1,66 @@
1
+ function c() {
2
+ return _("");
3
+ }
4
+ function _(t) {
5
+ return new Proxy({}, {
6
+ get(r, i) {
7
+ if (typeof i == "symbol")
8
+ return;
9
+ if (i === "__path" || i === "__fieldPath")
10
+ return t || i;
11
+ if (i === "__key") {
12
+ const n = t.split(".");
13
+ return n[n.length - 1] || i;
14
+ }
15
+ if (i === "then" || i === "catch" || i === "finally" || i === "constructor" || i === "toString" || i === "valueOf" || i === "toJSON")
16
+ return;
17
+ const f = t ? `${t}.${i}` : i, a = {
18
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
+ __key: i,
20
+ __path: f,
21
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
+ __formType: void 0,
23
+ __fieldType: void 0
24
+ };
25
+ return new Proxy(a, {
26
+ get(n, e) {
27
+ if (typeof e != "symbol") {
28
+ if (e === "__path" || e === "__fieldPath") return f;
29
+ if (e === "__key") return i;
30
+ if (e !== "__formType" && e !== "__fieldType" && !(e === "then" || e === "catch" || e === "finally" || e === "constructor" || e === "toString" || e === "valueOf" || e === "toJSON"))
31
+ return _(`${f}.${e}`);
32
+ }
33
+ }
34
+ });
35
+ }
36
+ });
37
+ }
38
+ function u(t) {
39
+ if (typeof t == "string")
40
+ return t;
41
+ if (t && typeof t == "object") {
42
+ const r = t.__path;
43
+ if (typeof r == "string")
44
+ return r;
45
+ }
46
+ throw new Error("Invalid field path node: " + JSON.stringify(t));
47
+ }
48
+ function y(t) {
49
+ const r = u(t);
50
+ return _(r);
51
+ }
52
+ function l(t) {
53
+ if (t && typeof t == "object" && "__key" in t)
54
+ return t.__key;
55
+ if (typeof t == "string") {
56
+ const r = t.split(".");
57
+ return r[r.length - 1];
58
+ }
59
+ throw new Error("Invalid field path node");
60
+ }
61
+ export {
62
+ l as a,
63
+ c,
64
+ u as e,
65
+ y as t
66
+ };
@@ -0,0 +1,328 @@
1
+ import { ValidationError } from '../core/types';
2
+ /**
3
+ * Состояние поля формы, возвращаемое хуком {@link useFormControl} для {@link FieldNode}.
4
+ *
5
+ * Содержит реактивные данные поля: значение, состояние валидации, флаги взаимодействия
6
+ * и пользовательские props для компонентов.
7
+ *
8
+ * @typeParam T - Тип значения поля (string, number, boolean и т.д.)
9
+ *
10
+ * @example Базовое использование
11
+ * ```tsx
12
+ * interface Props {
13
+ * control: FieldNode<string>;
14
+ * }
15
+ *
16
+ * function TextField({ control }: Props) {
17
+ * const state = useFormControl(control);
18
+ *
19
+ * return (
20
+ * <div>
21
+ * <input
22
+ * value={state.value}
23
+ * disabled={state.disabled}
24
+ * onChange={e => control.setValue(e.target.value)}
25
+ * />
26
+ * {state.shouldShowError && state.errors[0] && (
27
+ * <span className="error">{state.errors[0].message}</span>
28
+ * )}
29
+ * </div>
30
+ * );
31
+ * }
32
+ * ```
33
+ *
34
+ * @see {@link useFormControl} - хук для получения состояния
35
+ * @see {@link ArrayControlState} - состояние для массивов
36
+ *
37
+ * @group Types
38
+ */
39
+ export interface FieldControlState<T> {
40
+ /**
41
+ * Текущее значение поля.
42
+ *
43
+ * @example
44
+ * ```tsx
45
+ * const { value } = useFormControl(emailField);
46
+ * console.log(value); // "user@example.com"
47
+ * ```
48
+ */
49
+ value: T;
50
+ /**
51
+ * Флаг асинхронной валидации или загрузки.
52
+ * `true` когда выполняется асинхронный валидатор.
53
+ *
54
+ * @example
55
+ * ```tsx
56
+ * const { pending } = useFormControl(usernameField);
57
+ *
58
+ * return (
59
+ * <div>
60
+ * <input {...props} />
61
+ * {pending && <Spinner size="small" />}
62
+ * </div>
63
+ * );
64
+ * ```
65
+ */
66
+ pending: boolean;
67
+ /**
68
+ * Флаг отключения поля.
69
+ * `true` когда поле недоступно для редактирования.
70
+ *
71
+ * @example
72
+ * ```tsx
73
+ * const { disabled, value } = useFormControl(field);
74
+ *
75
+ * return (
76
+ * <input
77
+ * value={value}
78
+ * disabled={disabled}
79
+ * className={disabled ? 'opacity-50' : ''}
80
+ * />
81
+ * );
82
+ * ```
83
+ */
84
+ disabled: boolean;
85
+ /**
86
+ * Массив ошибок валидации.
87
+ * Пустой массив означает отсутствие ошибок.
88
+ *
89
+ * @example
90
+ * ```tsx
91
+ * const { errors } = useFormControl(field);
92
+ *
93
+ * return (
94
+ * <ul className="error-list">
95
+ * {errors.map((error, i) => (
96
+ * <li key={i}>{error.message}</li>
97
+ * ))}
98
+ * </ul>
99
+ * );
100
+ * ```
101
+ */
102
+ errors: ValidationError[];
103
+ /**
104
+ * Флаг валидности поля.
105
+ * `true` когда поле прошло все валидации (errors.length === 0).
106
+ *
107
+ * @example
108
+ * ```tsx
109
+ * const { valid } = useFormControl(field);
110
+ *
111
+ * return (
112
+ * <input className={valid ? 'border-green' : 'border-gray'} />
113
+ * );
114
+ * ```
115
+ */
116
+ valid: boolean;
117
+ /**
118
+ * Флаг невалидности поля.
119
+ * `true` когда есть ошибки валидации (errors.length > 0).
120
+ * Противоположность {@link valid}.
121
+ *
122
+ * @example
123
+ * ```tsx
124
+ * const { invalid } = useFormControl(field);
125
+ *
126
+ * return (
127
+ * <input
128
+ * aria-invalid={invalid}
129
+ * className={invalid ? 'border-red' : ''}
130
+ * />
131
+ * );
132
+ * ```
133
+ */
134
+ invalid: boolean;
135
+ /**
136
+ * Флаг взаимодействия с полем.
137
+ * `true` после того как поле потеряло фокус (blur) хотя бы один раз.
138
+ *
139
+ * @example
140
+ * ```tsx
141
+ * const { touched, invalid } = useFormControl(field);
142
+ *
143
+ * // Показываем ошибку только после взаимодействия
144
+ * const showError = touched && invalid;
145
+ * ```
146
+ */
147
+ touched: boolean;
148
+ /**
149
+ * Флаг для отображения ошибки.
150
+ * Комбинация touched && invalid - удобный shortcut для UI.
151
+ *
152
+ * @example
153
+ * ```tsx
154
+ * const { shouldShowError, errors } = useFormControl(field);
155
+ *
156
+ * return (
157
+ * <div>
158
+ * <input {...props} />
159
+ * {shouldShowError && (
160
+ * <span className="error">{errors[0]?.message}</span>
161
+ * )}
162
+ * </div>
163
+ * );
164
+ * ```
165
+ */
166
+ shouldShowError: boolean;
167
+ /**
168
+ * Пользовательские props для передачи в UI-компоненты.
169
+ * Устанавливаются через {@link FieldNode.setComponentProps}.
170
+ *
171
+ * @example
172
+ * ```tsx
173
+ * // Установка props
174
+ * field.setComponentProps({
175
+ * placeholder: 'Enter email...',
176
+ * maxLength: 100,
177
+ * autoComplete: 'email'
178
+ * });
179
+ *
180
+ * // Использование в компоненте
181
+ * const { componentProps, value } = useFormControl(field);
182
+ *
183
+ * return (
184
+ * <input
185
+ * value={value}
186
+ * placeholder={componentProps.placeholder}
187
+ * maxLength={componentProps.maxLength}
188
+ * autoComplete={componentProps.autoComplete}
189
+ * />
190
+ * );
191
+ * ```
192
+ */
193
+ componentProps: Record<string, any>;
194
+ }
195
+ /**
196
+ * Состояние массива формы, возвращаемое хуком {@link useFormControl} для {@link ArrayNode}.
197
+ *
198
+ * Содержит реактивные данные массива: значения элементов, длину, состояние валидации
199
+ * и флаги взаимодействия.
200
+ *
201
+ * @typeParam T - Тип элемента массива (обычно объект с полями формы)
202
+ *
203
+ * @example Список с динамическим добавлением
204
+ * ```tsx
205
+ * interface Phone {
206
+ * type: string;
207
+ * number: string;
208
+ * }
209
+ *
210
+ * interface Props {
211
+ * control: ArrayNode<Phone>;
212
+ * }
213
+ *
214
+ * function PhoneList({ control }: Props) {
215
+ * const { length, valid } = useFormControl(control);
216
+ *
217
+ * return (
218
+ * <div>
219
+ * {control.map((item, index) => (
220
+ * <PhoneItem
221
+ * key={item.id}
222
+ * control={item}
223
+ * onRemove={() => control.remove(index)}
224
+ * />
225
+ * ))}
226
+ *
227
+ * {length === 0 && <p>No phones added</p>}
228
+ *
229
+ * <button onClick={() => control.push({ type: 'mobile', number: '' })}>
230
+ * Add Phone
231
+ * </button>
232
+ *
233
+ * {!valid && <p className="error">Please fix phone errors</p>}
234
+ * </div>
235
+ * );
236
+ * }
237
+ * ```
238
+ *
239
+ * @see {@link useFormControl} - хук для получения состояния
240
+ * @see {@link FieldControlState} - состояние для полей
241
+ *
242
+ * @group Types
243
+ */
244
+ export interface ArrayControlState<T> {
245
+ /**
246
+ * Массив текущих значений всех элементов.
247
+ *
248
+ * @example
249
+ * ```tsx
250
+ * const { value } = useFormControl(phonesArray);
251
+ * console.log(value);
252
+ * // [{ type: 'mobile', number: '+1234567890' }, { type: 'home', number: '+0987654321' }]
253
+ * ```
254
+ */
255
+ value: T[];
256
+ /**
257
+ * Количество элементов в массиве.
258
+ * Эквивалентно value.length, но оптимизировано для реактивности.
259
+ *
260
+ * @example
261
+ * ```tsx
262
+ * const { length } = useFormControl(itemsArray);
263
+ *
264
+ * return (
265
+ * <div>
266
+ * <span>Items: {length}</span>
267
+ * {length >= 10 && <span>Maximum reached</span>}
268
+ * </div>
269
+ * );
270
+ * ```
271
+ */
272
+ length: number;
273
+ /**
274
+ * Флаг асинхронной валидации.
275
+ * `true` когда выполняется асинхронный валидатор массива или любого элемента.
276
+ */
277
+ pending: boolean;
278
+ /**
279
+ * Массив ошибок валидации уровня массива.
280
+ * Не включает ошибки отдельных элементов.
281
+ *
282
+ * @example
283
+ * ```tsx
284
+ * // Валидатор массива
285
+ * validators.apply(phonesArray, {
286
+ * validator: (phones) => phones.length >= 1,
287
+ * message: 'At least one phone required'
288
+ * });
289
+ *
290
+ * // В компоненте
291
+ * const { errors } = useFormControl(phonesArray);
292
+ * // errors содержит ошибку "At least one phone required" если массив пуст
293
+ * ```
294
+ */
295
+ errors: ValidationError[];
296
+ /**
297
+ * Флаг валидности массива и всех его элементов.
298
+ * `true` только когда массив и все вложенные элементы валидны.
299
+ */
300
+ valid: boolean;
301
+ /**
302
+ * Флаг невалидности.
303
+ * `true` когда есть ошибки в массиве или любом элементе.
304
+ */
305
+ invalid: boolean;
306
+ /**
307
+ * Флаг взаимодействия.
308
+ * `true` после взаимодействия с любым элементом массива.
309
+ */
310
+ touched: boolean;
311
+ /**
312
+ * Флаг изменения.
313
+ * `true` когда значение массива отличается от начального.
314
+ *
315
+ * @example
316
+ * ```tsx
317
+ * const { dirty } = useFormControl(itemsArray);
318
+ *
319
+ * return (
320
+ * <div>
321
+ * {dirty && <span>* Unsaved changes</span>}
322
+ * <button disabled={!dirty}>Save</button>
323
+ * </div>
324
+ * );
325
+ * ```
326
+ */
327
+ dirty: boolean;
328
+ }
@@ -0,0 +1,31 @@
1
+ import { ArrayNode } from '../core/nodes/array-node';
2
+ import { FormFields } from '../core/types';
3
+ /**
4
+ * React-хук для подписки только на длину массива.
5
+ *
6
+ * Оптимизированная версия {@link useFormControl} для ArrayNode, которая
7
+ * подписывается только на сигнал `length`. Компонент не будет ре-рендериться
8
+ * при изменении значений вложенных полей.
9
+ *
10
+ * @typeParam T - Тип элемента массива
11
+ * @param control - ArrayNode для подписки
12
+ * @returns Текущая длина массива
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * function ArrayRenderer({ arrayNode }) {
17
+ * const length = useArrayLength(arrayNode);
18
+ *
19
+ * return (
20
+ * <div>
21
+ * {arrayNode.map((item, index) => (
22
+ * <ItemRenderer key={item.id} item={item} />
23
+ * ))}
24
+ * </div>
25
+ * );
26
+ * }
27
+ * ```
28
+ *
29
+ * @group React Hooks
30
+ */
31
+ export declare function useArrayLength<T extends FormFields>(control: ArrayNode<T>): number;
@@ -1,48 +1,24 @@
1
- import type { FieldNode } from '../core/nodes/field-node';
2
- import type { ArrayNode } from '../core/nodes/array-node';
3
- import type { FormValue, ValidationError, FormFields } from '../core/types';
1
+ import { FieldNode } from '../core/nodes/field-node';
2
+ import { ArrayNode } from '../core/nodes/array-node';
3
+ import { FormValue, FormFields } from '../core/types';
4
+ import { FieldControlState, ArrayControlState } from './types';
4
5
  /**
5
- * @internal
6
- */
7
- interface FieldControlState<T> {
8
- value: T;
9
- pending: boolean;
10
- disabled: boolean;
11
- errors: ValidationError[];
12
- valid: boolean;
13
- invalid: boolean;
14
- touched: boolean;
15
- shouldShowError: boolean;
16
- componentProps: Record<string, any>;
17
- }
18
- /**
19
- * @internal
20
- */
21
- interface ArrayControlState<T> {
22
- value: T[];
23
- length: number;
24
- pending: boolean;
25
- errors: ValidationError[];
26
- valid: boolean;
27
- invalid: boolean;
28
- touched: boolean;
29
- dirty: boolean;
30
- }
31
- /**
32
- * Хук для получения только значения поля без подписки на errors, valid и т.д.
33
- * Используйте когда нужно только значение для условного рендеринга.
6
+ * React-хук для подписки на состояние {@link ArrayNode}.
7
+ *
8
+ * @typeParam T - Тип элемента массива
9
+ * @param control - ArrayNode или undefined
10
+ * @returns Состояние массива {@link ArrayControlState}
34
11
  *
35
- * @group React Hooks
36
- */
37
- export declare function useFormControlValue<T extends FormValue>(control: FieldNode<T>): T;
38
- /**
39
- * Хук для работы с ArrayNode - возвращает состояние массива с подписками на сигналы
40
12
  * @group React Hooks
41
13
  */
42
14
  export declare function useFormControl<T extends FormFields>(control: ArrayNode<T> | undefined): ArrayControlState<T>;
43
15
  /**
44
- * Хук для работы с FieldNode - возвращает состояние поля с подписками на сигналы
16
+ * React-хук для подписки на состояние {@link FieldNode}.
17
+ *
18
+ * @typeParam T - Тип значения поля
19
+ * @param control - FieldNode для подписки
20
+ * @returns Состояние поля {@link FieldControlState}
21
+ *
45
22
  * @group React Hooks
46
23
  */
47
24
  export declare function useFormControl<T extends FormValue>(control: FieldNode<T>): FieldControlState<T>;
48
- export {};