@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,11 +1,10 @@
1
- import { FieldNode } from '../nodes/field-node';
2
- import { FormValue } from '../types/index';
1
+ import { FormControl } from '../../../form/types/index';
3
2
  /**
4
3
  * React-хук для подписки только на значение поля.
5
4
  *
6
5
  * Оптимизированная версия {@link useFormControl}, которая подписывается
7
6
  * только на сигнал `value`. Компонент не будет ре-рендериться при изменении
8
- * `errors`, `touched`, `valid` и других свойств состояния.
7
+ * `issues`, `touched`, `valid` и других свойств состояния.
9
8
  *
10
9
  * ## Когда использовать
11
10
  *
@@ -16,21 +15,21 @@ import { FormValue } from '../types/index';
16
15
  *
17
16
  * ## Когда НЕ использовать
18
17
  *
19
- * Если компоненту нужны `errors`, `touched`, `disabled` или другие свойства -
18
+ * Если компоненту нужны `issues`, `touched`, `disabled` или другие свойства -
20
19
  * используйте {@link useFormControl}. Множественные подписки на один контрол
21
20
  * через разные хуки менее эффективны, чем одна подписка через `useFormControl`.
22
21
  *
23
22
  * @typeParam T - Тип значения поля
24
- * @param control - FieldNode для подписки на значение
23
+ * @param control - FormControl для подписки на значение
25
24
  * @returns Текущее значение поля
26
25
  *
27
26
  * @example Условный рендеринг секции
28
27
  * ```tsx
29
- * import { useFormControlValue } from '@reformer/core';
28
+ * import { useFormControlValue } from '@reformer/core/react';
30
29
  *
31
30
  * interface FormFields {
32
- * hasShipping: FieldNode<boolean>;
33
- * shippingAddress: GroupNode<AddressFields>;
31
+ * hasShipping: FormControl<boolean>;
32
+ * shippingAddress: FormGroup<AddressFields>;
34
33
  * }
35
34
  *
36
35
  * function ShippingSection({ form }: { form: FormFields }) {
@@ -53,8 +52,8 @@ import { FormValue } from '../types/index';
53
52
  * @example Динамические опции на основе другого поля
54
53
  * ```tsx
55
54
  * interface FormFields {
56
- * country: FieldNode<string>;
57
- * city: FieldNode<string>;
55
+ * country: FormControl<string>;
56
+ * city: FormControl<string>;
58
57
  * }
59
58
  *
60
59
  * function CitySelect({ form }: { form: FormFields }) {
@@ -93,14 +92,14 @@ import { FormValue } from '../types/index';
93
92
  *
94
93
  * // Хук вызывается на уровне компонента-строки (не в цикле — Rules of Hooks).
95
94
  * // Доступ к полям элемента — через Proxy: item.quantity, item.price.
96
- * function OrderRow({ item }: { item: FormProxy<OrderItem> }) {
95
+ * function OrderRow({ item }: { item: FormGroup<OrderItem> }) {
97
96
  * const quantity = useFormControlValue(item.quantity);
98
97
  * const price = useFormControlValue(item.price);
99
98
  *
100
99
  * return <span>Итого: ${(quantity * price).toFixed(2)}</span>;
101
100
  * }
102
101
  *
103
- * function OrderList({ items }: { items: ArrayNode<OrderItem> }) {
102
+ * function OrderList({ items }: { items: FormArray<OrderItem> }) {
104
103
  * return (
105
104
  * <div>
106
105
  * {items.map((item, index) => (
@@ -114,7 +113,7 @@ import { FormValue } from '../types/index';
114
113
  * @example Preview значения
115
114
  * ```tsx
116
115
  * interface MarkdownEditorProps {
117
- * control: FieldNode<string>;
116
+ * control: FormControl<string>;
118
117
  * }
119
118
  *
120
119
  * function MarkdownPreview({ control }: MarkdownEditorProps) {
@@ -133,7 +132,8 @@ import { FormValue } from '../types/index';
133
132
  *
134
133
  * // Основной редактор использует useFormControl для полного состояния
135
134
  * function MarkdownEditor({ control }: MarkdownEditorProps) {
136
- * const { value, shouldShowError, errors } = useFormControl(control);
135
+ * const { value, shouldShowIssues, issues } = useFormControl(control);
136
+ * const message = useIssueMessage(); // из '@reformer/core/react'
137
137
  *
138
138
  * return (
139
139
  * <div className="editor-container">
@@ -141,7 +141,7 @@ import { FormValue } from '../types/index';
141
141
  * value={value}
142
142
  * onChange={e => control.setValue(e.target.value)}
143
143
  * />
144
- * {shouldShowError && <span className="error">{errors[0]?.message}</span>}
144
+ * {shouldShowIssues && <span className="error">{message(issues[0])}</span>}
145
145
  *
146
146
  * {/* Preview обновляется только при изменении value *}
147
147
  * <MarkdownPreview control={control} />
@@ -152,7 +152,7 @@ import { FormValue } from '../types/index';
152
152
  *
153
153
  * @example Счётчик символов
154
154
  * ```tsx
155
- * function CharacterCounter({ control, max }: { control: FieldNode<string>; max: number }) {
155
+ * function CharacterCounter({ control, max }: { control: FormControl<string>; max: number }) {
156
156
  * const value = useFormControlValue(control);
157
157
  * const remaining = max - value.length;
158
158
  *
@@ -165,8 +165,8 @@ import { FormValue } from '../types/index';
165
165
  * ```
166
166
  *
167
167
  * @see {@link useFormControl} - для полного состояния поля
168
- * @see {@link FieldNode} - тип контрола поля
168
+ * @see {@link FormControl} - тип контрола поля
169
169
  *
170
170
  * @group React Hooks
171
171
  */
172
- export declare function useFormControlValue<T extends FormValue>(control: FieldNode<T>): T;
172
+ export declare function useFormControlValue<T>(control: FormControl<T>): T;
@@ -9,9 +9,17 @@ export type ExtractSignalValues<T extends SignalMap> = {
9
9
  export interface SignalConfig<K extends string> {
10
10
  key: K;
11
11
  useShallowArrayEqual?: boolean;
12
+ /**
13
+ * Сравнивать объект поверхностно: новый объект с теми же значениями (`updateComponentProps`
14
+ * теми же пропсами) снапшот не меняет.
15
+ */
16
+ useShallowObjectEqual?: boolean;
12
17
  }
13
18
  /**
14
- * Хук для подписки на набор сигналов с кешированием
19
+ * Хук для подписки на набор сигналов с кешированием.
20
+ *
21
+ * Подписка — только на сигналы из `configs`: их смена пересобирает снапшот. Остальные сигналы
22
+ * `signals` в снапшот попадают значением на момент сборки и сами компонент не будят.
15
23
  * @internal
16
24
  */
17
25
  export declare function useSignalSubscription<TSignals extends SignalMap, TSnapshot extends ExtractSignalValues<TSignals>>(signals: TSignals, configs: SignalConfig<Extract<keyof TSignals, string>>[], buildSnapshot: (values: ExtractSignalValues<TSignals>) => TSnapshot,
@@ -0,0 +1,18 @@
1
+ import { I18nHandle } from '../../../i18n/translator';
2
+ /** Имя контекста и одновременно маркер, по которому страж ищет его копии в сборках. */
3
+ export declare const I18N_CONTEXT_MARKER = "ReformerI18nContext";
4
+ /** Что видит компонент: ручка активной локали и состояние её загрузки. */
5
+ export interface I18nContextValue extends I18nHandle {
6
+ /** Идёт загрузка другого языка; на экране пока прежний. Без загрузчика всегда `false`. */
7
+ readonly pending: boolean;
8
+ /** Ошибка последней загрузки языка. */
9
+ readonly error: unknown;
10
+ /**
11
+ * Повторить загрузку языка, которая упала (`error` задан). Без загрузчика и без ошибки ничего
12
+ * не делает.
13
+ */
14
+ readonly retry: () => void;
15
+ }
16
+ /** Значение контекста для локали: ручка плюс состояние загрузки. */
17
+ export declare function contextValue(handle: I18nHandle, pending: boolean, error: unknown, retry?: () => void): I18nContextValue;
18
+ export declare const I18nContext: import('react').Context<I18nContextValue>;
@@ -0,0 +1,65 @@
1
+ import { ValidationIssue } from '../../../form/types/contracts';
2
+ import { Messages } from '../../../i18n/locale';
3
+ import { MessageValues } from '../../../i18n/message-format';
4
+ import { IssueMessages } from '../../../i18n/validation-message';
5
+ import { I18nContextValue } from './context';
6
+ /**
7
+ * Активная локаль: перевод ключей приложения, форматирование чисел, дат и размеров, состояние
8
+ * загрузки языка. Без провайдера — английский с пустым словарём.
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * function LangBadge() {
13
+ * const { code, pending, t } = useI18n();
14
+ * return <span aria-busy={pending}>{t('app.language')}: {code}</span>;
15
+ * }
16
+ * ```
17
+ */
18
+ export declare function useI18n(): I18nContextValue;
19
+ /**
20
+ * Переводчик пакета: ищет ключ в локали провайдера, а при промахе берёт встроенную английскую
21
+ * таблицу этого пакета. Так пакет говорит по-английски без провайдера и не зависит от того, знает
22
+ * ли локаль его ключи. Тип ключа выводится из таблицы — опечатка в ключе не скомпилируется.
23
+ *
24
+ * `defaults` должен быть стабильной ссылкой (импорт JSON-модуля), иначе переводчик будет
25
+ * пересоздаваться на каждый рендер.
26
+ *
27
+ * @param defaults - Встроенная английская таблица пакета.
28
+ * @returns Функция `(ключ, значения?) => строка`; её идентичность меняется вместе с локалью.
29
+ *
30
+ * @example
31
+ * ```tsx
32
+ * import en from './locale/en.json';
33
+ *
34
+ * const useKitMessages = () => useMessages(en);
35
+ *
36
+ * function ClearButton() {
37
+ * const t = useKitMessages();
38
+ * return <button aria-label={t('kit.select.clear')} />;
39
+ * }
40
+ * ```
41
+ */
42
+ export declare function useMessages<D extends Messages>(defaults: D): (key: keyof D & string, values?: MessageValues) => string;
43
+ /**
44
+ * Резолвер текста замечания валидации: словарь формы → словарь активной локали по коду →
45
+ * встроенный английский → код. Идентичность функции меняется вместе с локалью и словарём,
46
+ * поэтому показанные замечания переводятся при смене языка без повторной валидации.
47
+ *
48
+ * `FormField` из `@reformer/cdk` использует его сам; вызывайте напрямую, если рисуете замечания
49
+ * своим компонентом.
50
+ *
51
+ * @param messages - Словарь формы (`defineIssueMessages`). Стабильная ссылка — константа
52
+ * модуля, иначе резолвер будет пересоздаваться на каждый рендер.
53
+ *
54
+ * @example
55
+ * ```tsx
56
+ * const messages = defineIssueMessages({ 'phone.required': 'Укажите телефон' });
57
+ *
58
+ * function FieldIssues({ control }: { control: FormControl<string> }) {
59
+ * const message = useIssueMessage(messages);
60
+ * const { issues } = useFormControl(control);
61
+ * return <>{issues.map((issue) => <span key={issue.code}>{message(issue)}</span>)}</>;
62
+ * }
63
+ * ```
64
+ */
65
+ export declare function useIssueMessage(messages?: IssueMessages): (issue: ValidationIssue) => string;
@@ -0,0 +1,59 @@
1
+ import { ReactElement, ReactNode } from 'react';
2
+ import { FormLocale } from '../../../i18n/locale';
3
+ import { LocaleLoad } from '../../../i18n/locale-store';
4
+ /** Режим «готовая локаль». */
5
+ export interface I18nStaticProviderProps {
6
+ /** Локаль. Смена объекта переключает язык сразу. */
7
+ locale: FormLocale;
8
+ children?: ReactNode;
9
+ }
10
+ /** Режим «провайдер грузит сам». */
11
+ export interface I18nLoadingProviderProps {
12
+ /** Код языка. Смена кода запускает загрузку; до её конца на экране прежний язык. */
13
+ lang: string;
14
+ /**
15
+ * Загрузчик локалей — обычно результат `createLocaleLoader`. Нужна СТАБИЛЬНАЯ ссылка (модульная
16
+ * константа, `useMemo`): новый загрузчик — новое хранилище, и язык запрашивается у него заново.
17
+ * На экране тем временем остаётся прежняя локаль, но инлайн-стрелка гоняла бы запрос на каждый
18
+ * рендер родителя.
19
+ */
20
+ load: LocaleLoad;
21
+ /**
22
+ * Что показать, пока не загружена самая первая локаль. По умолчанию — ничего: иначе на кадр
23
+ * мелькнул бы встроенный английский. Если локаль уже в кэше загрузчика (`load.preload(lang)`
24
+ * до монтирования), первый рендер синхронный и `fallback` не показывается. Упала первая
25
+ * загрузка — дети показываются на встроенном английском, ошибка — в `useI18n().error`,
26
+ * повторить — `useI18n().retry()`.
27
+ */
28
+ fallback?: ReactNode;
29
+ /** Отказ загрузки. Язык на экране при этом не меняется. */
30
+ onError?: (error: unknown, lang: string) => void;
31
+ children?: ReactNode;
32
+ }
33
+ export type I18nProviderProps = I18nStaticProviderProps | I18nLoadingProviderProps;
34
+ /**
35
+ * Провайдер локализации для подписей компонентов, ошибок валидации и авторских подписей формы.
36
+ * Без провайдера компоненты говорят встроенным английским.
37
+ *
38
+ * При смене `lang` на экране остаётся прежний язык, пока новый не загрузится (`useI18n().pending`
39
+ * — для индикатора). При быстром переключении применяется только последний запрос. Вложенный
40
+ * провайдер заменяет локаль для своего поддерева целиком.
41
+ *
42
+ * @example Провайдер грузит локаль сам
43
+ * ```tsx
44
+ * const [lang, setLang] = useState('ru');
45
+ *
46
+ * <I18nProvider lang={lang} load={loadLocale}>
47
+ * <LangSwitch value={lang} onChange={setLang} />
48
+ * <CreditForm />
49
+ * </I18nProvider>
50
+ * ```
51
+ *
52
+ * @example Готовая локаль — SSR и тесты
53
+ * ```tsx
54
+ * import { ru } from '@reformer/ui-kit/locale/ru';
55
+ *
56
+ * <I18nProvider locale={ru}><CreditForm /></I18nProvider>
57
+ * ```
58
+ */
59
+ export declare function I18nProvider(props: I18nProviderProps): ReactElement | null;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Модуль `platforms/react` — биндинги ядра к React.
3
+ *
4
+ * Единственное место в пакете, где есть runtime-зависимость от `react` и
5
+ * `use-sync-external-store`: слои `model` и `form` от React свободны и в рантайме, и в типах
6
+ * (компонент узла схемы для них — непрозрачная ссылка `ComponentRef`). Хуки читают
7
+ * сигналы нод формы через `useSyncExternalStore` и отдают плоские снапшоты
8
+ * ({@link FieldControlState}/{@link ArrayControlState}) в рендер.
9
+ *
10
+ * Состав barrel'а отдаёт вход `@reformer/core/react` (`src/react.ts`); корень `@reformer/core` его
11
+ * не реэкспортирует.
12
+ *
13
+ * @group Platforms
14
+ * @module platforms/react
15
+ */
16
+ export { useFormControl } from './hooks/useFormControl';
17
+ export { useFormControlValue } from './hooks/useFormControlValue';
18
+ export { useArrayLength } from './hooks/useArrayLength';
19
+ export { useFormValidation } from './hooks/use-form-validation';
20
+ export type { UseFormValidationArgs, UseFormValidationResult } from './hooks/use-form-validation';
21
+ export { useFormBundle } from './hooks/use-form-bundle';
22
+ export type { FormBundleLike } from './hooks/use-form-bundle';
23
+ export { useFormFlow } from './hooks/use-form-flow';
24
+ export type { FormFlowSnapshot } from './hooks/use-form-flow';
25
+ export { FormBundleContext, useFormBundleContext } from './form-bundle-context';
26
+ export type { FieldControlState, ArrayControlState } from './hooks/types';
27
+ export { getFieldAdapter, bindFieldProps, FIELD_WRAPPER_ONLY_PROPS, } from './field-binding/field-adapter';
28
+ export type { FieldAdapter, FieldAdapterCarrier, FieldSeam } from './field-binding/field-adapter';
29
+ export { makeElementFieldHandle, useFieldHandleRef } from './field-binding/field-handle';
30
+ export type { FieldHandle } from './field-binding/field-handle';
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Подпуть `@reformer/core/react` — привязка ядра к React: хуки нод формы, связка поля с контролом,
3
+ * контекст сборки и React-часть локализации.
4
+ *
5
+ * Единственный вход пакета с зависимостью от `react`. Корень `@reformer/core` и остальные сабпаты
6
+ * от React свободны, поэтому `react` и `react-dom` — необязательные peer-зависимости: они нужны
7
+ * только тому, кто импортирует этот вход.
8
+ *
9
+ * Контекст локализации обязан существовать в одном экземпляре на все пакеты `@reformer/*`:
10
+ * пакеты получают его отсюда как внешнюю зависимость и не включают в свою сборку
11
+ * (страж — `scripts/check-i18n-singleton.mjs`).
12
+ *
13
+ * @group Platforms
14
+ * @module react
15
+ * @mergeModuleWith <project>
16
+ */
17
+ export * from './platforms/react/index';
18
+ export { I18nProvider } from './platforms/react/i18n/provider';
19
+ export type { I18nProviderProps, I18nStaticProviderProps, I18nLoadingProviderProps, } from './platforms/react/i18n/provider';
20
+ export { useI18n, useMessages, useIssueMessage } from './platforms/react/i18n/hooks';
21
+ export { I18N_CONTEXT_MARKER } from './platforms/react/i18n/context';
22
+ export type { I18nContextValue } from './platforms/react/i18n/context';