@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
@@ -0,0 +1,52 @@
1
+ import { e as p } from "./locale-CG54AU2Q.js";
2
+ function u(t) {
3
+ const n = t.messages;
4
+ return n !== null && typeof n == "object";
5
+ }
6
+ function y(t) {
7
+ if (t != null) {
8
+ if (typeof t != "object" || Array.isArray(t))
9
+ throw new TypeError("источник локали вернул не объект");
10
+ return u(t) ? t : { messages: t };
11
+ }
12
+ }
13
+ function g(t) {
14
+ const n = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map(), r = (e) => {
15
+ const i = n.get(e);
16
+ if (i !== void 0) return Promise.resolve(i);
17
+ const c = o.get(e);
18
+ if (c !== void 0) return c;
19
+ const l = Promise.all(t.map(async (s) => y(await s(e)))).then((s) => {
20
+ let a = { code: e, messages: {} };
21
+ for (const f of s)
22
+ f !== void 0 && (a = p(a, f));
23
+ return a = { ...a, code: e }, n.set(e, a), a;
24
+ }).finally(() => {
25
+ o.delete(e);
26
+ });
27
+ return o.set(e, l), l;
28
+ };
29
+ return Object.assign(r, {
30
+ peek: (e) => n.get(e),
31
+ preload: r
32
+ });
33
+ }
34
+ function h(t, n) {
35
+ return async (o) => {
36
+ const r = t(o), e = await fetch(r, n);
37
+ if (!e.ok)
38
+ throw new Error(`локаль «${o}»: ${r} ответил ${e.status}`);
39
+ return await e.json();
40
+ };
41
+ }
42
+ function d(t) {
43
+ return (n) => {
44
+ const o = n.split("-")[0].toLowerCase(), e = (Object.prototype.hasOwnProperty.call(t, n) ? t[n] : void 0) ?? (Object.prototype.hasOwnProperty.call(t, o) ? t[o] : void 0);
45
+ return e === void 0 ? null : e();
46
+ };
47
+ }
48
+ export {
49
+ d as b,
50
+ g as c,
51
+ h as f
52
+ };
@@ -0,0 +1,2 @@
1
+ import { FormLocale } from '../i18n/locale';
2
+ export declare const en: FormLocale;
@@ -0,0 +1,5 @@
1
+ import { m as e } from "../en-HP8XEych.js";
2
+ const o = { code: "en", weekStartsOn: 0, messages: e };
3
+ export {
4
+ o as en
5
+ };
@@ -0,0 +1,45 @@
1
+ {
2
+ "code": "en",
3
+ "weekStartsOn": 0,
4
+ "messages": {
5
+ "format.fileSize.b": "{value} B",
6
+ "format.fileSize.kb": "{value} KB",
7
+ "format.fileSize.mb": "{value} MB",
8
+ "format.fileSize.gb": "{value} GB",
9
+ "format.fileSize.tb": "{value} TB",
10
+ "validation.required": "This field is required",
11
+ "validation.pattern": "Invalid format",
12
+ "validation.email": "Enter a valid email address",
13
+ "validation.url": "Enter a valid URL",
14
+ "validation.url_protocol": "The URL must use one of these protocols: {allowedProtocols}",
15
+ "validation.phone": "Enter a valid phone number",
16
+ "validation.min": "Must be at least {min}",
17
+ "validation.max": "Must be at most {max}",
18
+ "validation.minLength": "Enter at least {minLength, plural, one{# character} other{# characters}}",
19
+ "validation.maxLength": "Enter no more than {maxLength, plural, one{# character} other{# characters}}",
20
+ "validation.minItems": "At least {minLength, plural, one{# item} other{# items}}",
21
+ "validation.maxItems": "No more than {maxLength, plural, one{# item} other{# items}}",
22
+ "validation.isNumber": "Enter a number",
23
+ "validation.integer": "Enter a whole number",
24
+ "validation.multipleOf": "Must be a multiple of {multipleOf}",
25
+ "validation.nonNegative": "Must not be negative",
26
+ "validation.nonZero": "Must not be zero",
27
+ "validation.date_invalid": "Enter a valid date",
28
+ "validation.date_min": "The date must not be earlier than {minDate}",
29
+ "validation.date_max": "The date must not be later than {maxDate}",
30
+ "validation.date_past": "The date must not be in the past",
31
+ "validation.date_future": "The date must not be in the future",
32
+ "validation.date_min_age": "Age must be at least {minAge}",
33
+ "validation.date_max_age": "Age must be at most {maxAge}",
34
+ "validation.fileType": "File {fileName} has a type that is not allowed. Allowed: {accept}",
35
+ "validation.maxFileSize": "File {fileName} is larger than {maxFileSize}",
36
+ "validation.minFileSize": "File {fileName} is smaller than {minFileSize}",
37
+ "validation.maxFiles": "No more than {maxFiles, plural, one{# file} other{# files}}",
38
+ "validation.minFiles": "At least {minFiles, plural, one{# file} other{# files}}",
39
+ "validation.maxTotalFileSize": "The total size of the files exceeds {maxTotalFileSize}",
40
+ "validation.fileExists": "File {fileName} has already been added",
41
+ "validation.uploadAborted": "Upload cancelled",
42
+ "validation.uploadFailed": "Failed to upload {fileName}",
43
+ "validation.ruleFailed": "Could not check this field. Try again"
44
+ }
45
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Подпуть `@reformer/core/locale` — загрузчик встроенных локалей ядра (тексты ошибок валидации,
3
+ * единицы размера файла). Приложению с ui-kit он не нужен: `loadKitLocale` из
4
+ * `@reformer/ui-kit/locale` уже включает словари ядра и cdk.
5
+ *
6
+ * @module locale
7
+ */
8
+ /** Языки, которые ядро поставляет само. */
9
+ export declare const CORE_LOCALES: readonly string[];
10
+ /**
11
+ * Источник локалей ядра для `createLocaleLoader`: чанк нужного языка по запросу.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const loadLocale = createLocaleLoader([loadCoreLocale, fetchMessages((code) => `/locales/${code}.json`)]);
16
+ * ```
17
+ */
18
+ export declare const loadCoreLocale: import('../i18n').LocaleSource;
@@ -0,0 +1,2 @@
1
+ import { FormLocale } from '../i18n/locale';
2
+ export declare const ru: FormLocale;
@@ -0,0 +1,44 @@
1
+ const a = {
2
+ "format.fileSize.b": "{value} Б",
3
+ "format.fileSize.kb": "{value} КБ",
4
+ "format.fileSize.mb": "{value} МБ",
5
+ "format.fileSize.gb": "{value} ГБ",
6
+ "format.fileSize.tb": "{value} ТБ",
7
+ "validation.required": "Обязательное поле",
8
+ "validation.pattern": "Неверный формат",
9
+ "validation.email": "Введите корректный email",
10
+ "validation.url": "Введите корректный адрес (URL)",
11
+ "validation.url_protocol": "Адрес должен начинаться с одного из протоколов: {allowedProtocols}",
12
+ "validation.phone": "Введите корректный номер телефона",
13
+ "validation.min": "Не меньше {min}",
14
+ "validation.max": "Не больше {max}",
15
+ "validation.minLength": "Не меньше {minLength, plural, one{# символа} few{# символов} many{# символов} other{# символа}}",
16
+ "validation.maxLength": "Не больше {maxLength, plural, one{# символа} few{# символов} many{# символов} other{# символа}}",
17
+ "validation.minItems": "Не меньше {minLength, plural, one{# элемента} few{# элементов} many{# элементов} other{# элемента}}",
18
+ "validation.maxItems": "Не больше {maxLength, plural, one{# элемента} few{# элементов} many{# элементов} other{# элемента}}",
19
+ "validation.isNumber": "Введите число",
20
+ "validation.integer": "Введите целое число",
21
+ "validation.multipleOf": "Число должно быть кратно {multipleOf}",
22
+ "validation.nonNegative": "Число не может быть отрицательным",
23
+ "validation.nonZero": "Число не может быть нулём",
24
+ "validation.date_invalid": "Введите корректную дату",
25
+ "validation.date_min": "Дата не раньше {minDate}",
26
+ "validation.date_max": "Дата не позже {maxDate}",
27
+ "validation.date_past": "Дата не может быть в прошлом",
28
+ "validation.date_future": "Дата не может быть в будущем",
29
+ "validation.date_min_age": "Возраст не меньше {minAge, plural, one{# года} few{# лет} many{# лет} other{# года}}",
30
+ "validation.date_max_age": "Возраст не больше {maxAge, plural, one{# года} few{# лет} many{# лет} other{# года}}",
31
+ "validation.fileType": "Недопустимый тип файла {fileName}. Разрешено: {accept}",
32
+ "validation.maxFileSize": "Файл {fileName} больше {maxFileSize}",
33
+ "validation.minFileSize": "Файл {fileName} меньше {minFileSize}",
34
+ "validation.maxFiles": "Не больше {maxFiles, plural, one{# файла} few{# файлов} many{# файлов} other{# файла}}",
35
+ "validation.minFiles": "Не меньше {minFiles, plural, one{# файла} few{# файлов} many{# файлов} other{# файла}}",
36
+ "validation.maxTotalFileSize": "Суммарный размер файлов больше {maxTotalFileSize}",
37
+ "validation.fileExists": "Файл {fileName} уже добавлен",
38
+ "validation.uploadAborted": "Загрузка прервана",
39
+ "validation.uploadFailed": "Не удалось загрузить файл {fileName}",
40
+ "validation.ruleFailed": "Не удалось проверить поле. Повторите попытку"
41
+ }, i = a, e = { code: "ru", weekStartsOn: 1, messages: i };
42
+ export {
43
+ e as ru
44
+ };
@@ -0,0 +1,45 @@
1
+ {
2
+ "code": "ru",
3
+ "weekStartsOn": 1,
4
+ "messages": {
5
+ "format.fileSize.b": "{value} Б",
6
+ "format.fileSize.kb": "{value} КБ",
7
+ "format.fileSize.mb": "{value} МБ",
8
+ "format.fileSize.gb": "{value} ГБ",
9
+ "format.fileSize.tb": "{value} ТБ",
10
+ "validation.required": "Обязательное поле",
11
+ "validation.pattern": "Неверный формат",
12
+ "validation.email": "Введите корректный email",
13
+ "validation.url": "Введите корректный адрес (URL)",
14
+ "validation.url_protocol": "Адрес должен начинаться с одного из протоколов: {allowedProtocols}",
15
+ "validation.phone": "Введите корректный номер телефона",
16
+ "validation.min": "Не меньше {min}",
17
+ "validation.max": "Не больше {max}",
18
+ "validation.minLength": "Не меньше {minLength, plural, one{# символа} few{# символов} many{# символов} other{# символа}}",
19
+ "validation.maxLength": "Не больше {maxLength, plural, one{# символа} few{# символов} many{# символов} other{# символа}}",
20
+ "validation.minItems": "Не меньше {minLength, plural, one{# элемента} few{# элементов} many{# элементов} other{# элемента}}",
21
+ "validation.maxItems": "Не больше {maxLength, plural, one{# элемента} few{# элементов} many{# элементов} other{# элемента}}",
22
+ "validation.isNumber": "Введите число",
23
+ "validation.integer": "Введите целое число",
24
+ "validation.multipleOf": "Число должно быть кратно {multipleOf}",
25
+ "validation.nonNegative": "Число не может быть отрицательным",
26
+ "validation.nonZero": "Число не может быть нулём",
27
+ "validation.date_invalid": "Введите корректную дату",
28
+ "validation.date_min": "Дата не раньше {minDate}",
29
+ "validation.date_max": "Дата не позже {maxDate}",
30
+ "validation.date_past": "Дата не может быть в прошлом",
31
+ "validation.date_future": "Дата не может быть в будущем",
32
+ "validation.date_min_age": "Возраст не меньше {minAge, plural, one{# года} few{# лет} many{# лет} other{# года}}",
33
+ "validation.date_max_age": "Возраст не больше {maxAge, plural, one{# года} few{# лет} many{# лет} other{# года}}",
34
+ "validation.fileType": "Недопустимый тип файла {fileName}. Разрешено: {accept}",
35
+ "validation.maxFileSize": "Файл {fileName} больше {maxFileSize}",
36
+ "validation.minFileSize": "Файл {fileName} меньше {minFileSize}",
37
+ "validation.maxFiles": "Не больше {maxFiles, plural, one{# файла} few{# файлов} many{# файлов} other{# файла}}",
38
+ "validation.minFiles": "Не меньше {minFiles, plural, one{# файла} few{# файлов} many{# файлов} other{# файла}}",
39
+ "validation.maxTotalFileSize": "Суммарный размер файлов больше {maxTotalFileSize}",
40
+ "validation.fileExists": "Файл {fileName} уже добавлен",
41
+ "validation.uploadAborted": "Загрузка прервана",
42
+ "validation.uploadFailed": "Не удалось загрузить файл {fileName}",
43
+ "validation.ruleFailed": "Не удалось проверить поле. Повторите попытку"
44
+ }
45
+ }
@@ -0,0 +1,219 @@
1
+ class v extends Error {
2
+ name = "MessageSyntaxError";
3
+ }
4
+ const O = (t) => `⟦${t}⟧`, w = 100, L = new RegExp("\\p{Pattern_White_Space}", "u"), _ = /[\p{White_Space}\p{Pattern_Syntax}]/u, $ = /* @__PURE__ */ new Map(), y = /* @__PURE__ */ new Map(), x = /* @__PURE__ */ new Map();
5
+ function E(t) {
6
+ let e = x.get(t);
7
+ if (e === void 0) {
8
+ try {
9
+ Intl.getCanonicalLocales(t), e = t;
10
+ } catch {
11
+ e = "en", process.env.NODE_ENV !== "production" && console.warn(
12
+ `[@reformer/core/i18n] код языка «${t}» не BCP 47 — числа, даты и формы слов форматируются по en.`
13
+ );
14
+ }
15
+ x.set(t, e);
16
+ }
17
+ return e;
18
+ }
19
+ function M(t) {
20
+ try {
21
+ return String(t);
22
+ } catch {
23
+ return "";
24
+ }
25
+ }
26
+ function b(t) {
27
+ let e = 0, n = 0;
28
+ const r = (s) => {
29
+ throw new v(`${s} (позиция ${e}) в сообщении: ${t}`);
30
+ }, i = (s, o) => s === "{" || s === "}" || s === "<" || s === ">" || o && s === "#", l = () => {
31
+ for (; e < t.length && L.test(t[e]); ) e++;
32
+ }, m = () => {
33
+ const s = e;
34
+ for (; e < t.length && !_.test(t[e]); ) e++;
35
+ return e === s && r("ожидалось имя"), t.slice(s, e);
36
+ }, p = (s) => {
37
+ if (s !== "plural" || t[e] !== "=") return m();
38
+ const o = e++;
39
+ (t[e] === "+" || t[e] === "-") && e++;
40
+ const f = e;
41
+ for (; e < t.length && t[e] >= "0" && t[e] <= "9"; ) e++;
42
+ return (e === f || !Number.isSafeInteger(Number(t.slice(f, e)))) && r("после «=» ожидалось целое число"), t.slice(o, e);
43
+ }, c = (s) => {
44
+ if (e++, t[e] === "'")
45
+ return e++, "'";
46
+ if (!i(t[e], s)) return "'";
47
+ let o = "";
48
+ for (; e < t.length; )
49
+ if (t[e] !== "'") o += t[e++];
50
+ else if (t[e + 1] === "'")
51
+ o += "'", e += 2;
52
+ else
53
+ return e++, o;
54
+ return o;
55
+ }, a = (s, o) => {
56
+ const f = [];
57
+ let h = "";
58
+ const g = () => {
59
+ h !== "" && (f.push({ kind: "text", value: h }), h = "");
60
+ };
61
+ for (; e < t.length; ) {
62
+ const d = t[e];
63
+ if (d === "}") {
64
+ s || r("непарная «}» — литерал пишется как '}'");
65
+ break;
66
+ }
67
+ d === "'" ? h += c(o !== null) : d === "#" && o !== null ? (e++, g(), f.push({ kind: "number", name: o })) : d === "{" ? (g(), f.push(N())) : (h += d, e++);
68
+ }
69
+ return g(), f;
70
+ }, u = (s, o, f) => {
71
+ const h = /* @__PURE__ */ new Map();
72
+ for (l(); e < t.length && t[e] !== "}"; ) {
73
+ const g = p(o);
74
+ h.has(g) && r(`ветка «${g}» в «${s}, ${o}» повторяется`), l(), t[e] !== "{" && r(`ожидалась «{» после ветки «${g}»`), e++, h.set(g, a(!0, f)), t[e] !== "}" && r(`ветка «${g}» не закрыта`), e++, l();
75
+ }
76
+ return t[e] !== "}" && r(`«${s}, ${o}» не закрыт «}»`), e++, h.has("other") || r(`в «${s}, ${o}» нет обязательной ветки other`), h;
77
+ }, N = () => {
78
+ n === w && r(`вложенность аргументов глубже ${w} уровней`), n++, e++, l();
79
+ const s = m();
80
+ l();
81
+ let o;
82
+ if (t[e] === "}")
83
+ e++, o = { kind: "arg", name: s };
84
+ else {
85
+ t[e] !== "," && r(`ожидались «,» или «}» после аргумента «${s}»`), e++, l();
86
+ const f = m();
87
+ f !== "plural" && f !== "select" && r(`неизвестный тип «${f}» у «${s}» — поддерживаются plural и select`), l(), t[e] !== "," && r(`ожидалась «,» после «${f}»`), e++, o = {
88
+ kind: f,
89
+ name: s,
90
+ branches: u(s, f, f === "plural" ? s : null)
91
+ };
92
+ }
93
+ return n--, o;
94
+ };
95
+ return a(!1, null);
96
+ }
97
+ function j(t, e, n, r = {}) {
98
+ const i = r.onMissingArgument ?? O, l = (p) => {
99
+ const c = e[p];
100
+ return typeof c == "number" && Number.isFinite(c) ? c : null;
101
+ }, m = (p) => {
102
+ let c = "";
103
+ for (const a of p)
104
+ if (a.kind === "text") c += a.value;
105
+ else if (a.kind === "arg")
106
+ c += e[a.name] === void 0 ? i(a.name) : M(e[a.name]);
107
+ else if (a.kind === "number") {
108
+ const u = l(a.name);
109
+ c += u === null ? i(a.name) : A(n).format(u);
110
+ } else if (a.kind === "plural") {
111
+ const u = l(a.name);
112
+ c += u === null ? i(a.name) : m(
113
+ a.branches.get(`=${u}`) ?? a.branches.get(P(n).select(u)) ?? a.branches.get("other")
114
+ );
115
+ } else {
116
+ const u = e[a.name];
117
+ c += u === void 0 ? i(a.name) : m(a.branches.get(M(u)) ?? a.branches.get("other"));
118
+ }
119
+ return c;
120
+ };
121
+ return m(t);
122
+ }
123
+ function P(t) {
124
+ let e = $.get(t);
125
+ return e === void 0 && $.set(t, e = new Intl.PluralRules(E(t))), e;
126
+ }
127
+ function A(t) {
128
+ let e = y.get(t);
129
+ return e === void 0 && y.set(t, e = new Intl.NumberFormat(E(t))), e;
130
+ }
131
+ function F(t, e = {}) {
132
+ const n = /* @__PURE__ */ new Map();
133
+ return (r, i = {}) => {
134
+ let l = n.get(r);
135
+ return l === void 0 && n.set(r, l = b(r)), j(l, i, t, e);
136
+ };
137
+ }
138
+ const I = Object.freeze({
139
+ code: "en",
140
+ messages: Object.freeze({})
141
+ });
142
+ function C(t, e) {
143
+ const { messages: n, ...r } = e;
144
+ return {
145
+ ...t,
146
+ ...r,
147
+ messages: n === void 0 ? t.messages : { ...t.messages, ...n }
148
+ };
149
+ }
150
+ function S(t, e) {
151
+ return Object.prototype.hasOwnProperty.call(t, e);
152
+ }
153
+ function k(t, e = /* @__PURE__ */ new Set()) {
154
+ for (const n of t)
155
+ if (n.kind !== "text" && (e.add(n.name), n.kind === "plural" || n.kind === "select"))
156
+ for (const r of n.branches.values()) k(r, e);
157
+ return e;
158
+ }
159
+ function D(t, e) {
160
+ const n = [], r = /* @__PURE__ */ new Map();
161
+ for (const [i, l] of Object.entries(t)) {
162
+ if (typeof l != "string") {
163
+ n.push({ key: i, kind: "syntax", message: "сообщение не является строкой" });
164
+ continue;
165
+ }
166
+ try {
167
+ r.set(i, b(l));
168
+ } catch (m) {
169
+ n.push({
170
+ key: i,
171
+ kind: "syntax",
172
+ message: m instanceof Error ? m.message : String(m)
173
+ });
174
+ }
175
+ }
176
+ if (e === void 0) return n;
177
+ for (const i of Object.keys(t))
178
+ S(e, i) || n.push({ key: i, kind: "extra", message: "ключа нет в образце" });
179
+ for (const [i, l] of Object.entries(e)) {
180
+ if (!S(t, i)) {
181
+ n.push({ key: i, kind: "missing", message: "ключ есть в образце, но не переведён" });
182
+ continue;
183
+ }
184
+ const m = r.get(i);
185
+ if (m === void 0) continue;
186
+ let p;
187
+ try {
188
+ if (typeof l != "string") throw new TypeError("сообщение не является строкой");
189
+ p = b(l);
190
+ } catch (u) {
191
+ n.push({
192
+ key: i,
193
+ kind: "syntax",
194
+ message: `в образце: ${u instanceof Error ? u.message : String(u)}`
195
+ });
196
+ continue;
197
+ }
198
+ const c = [...k(p)].sort().join(", "), a = [...k(m)].sort().join(", ");
199
+ c !== a && n.push({
200
+ key: i,
201
+ kind: "arguments",
202
+ message: `образец ждёт {${c}}, словарь — {${a}}`
203
+ });
204
+ }
205
+ return n;
206
+ }
207
+ export {
208
+ I as D,
209
+ v as M,
210
+ F as c,
211
+ C as e,
212
+ j as f,
213
+ S as h,
214
+ E as i,
215
+ k as m,
216
+ b as p,
217
+ M as t,
218
+ D as v
219
+ };
@@ -0,0 +1,2 @@
1
+ export * from './locale/index'
2
+ export {}
package/dist/locale.js ADDED
@@ -0,0 +1,9 @@
1
+ import { b as e } from "./loader-BWkigpVe.js";
2
+ const n = ["en", "ru"], t = e({
3
+ en: () => import("./locale/en.js").then((o) => o.en),
4
+ ru: () => import("./locale/ru.js").then((o) => o.ru)
5
+ });
6
+ export {
7
+ n as CORE_LOCALES,
8
+ t as loadCoreLocale
9
+ };
@@ -4,6 +4,12 @@ export type BehaviorCleanup = () => void;
4
4
  /**
5
5
  * Вычисляемое поле: `target = fn(...sourceValues)` при изменении источников.
6
6
  *
7
+ * Примитив модели: цель вычисляемой НЕ помечает. Поэтому массовая запись (`model.set`,
8
+ * `model.patch`, `model.reset`) её перезаписывает, а `isDirty()` её учитывает — до следующей смены
9
+ * источников. Оператор поведения `computeFrom` из `@reformer/core/behaviors` цель помечает
10
+ * (`markDerived`) и защищён от циклов: массовая запись такую цель не трогает. В поведении формы
11
+ * нужен оператор; примитив — для модели без формы.
12
+ *
7
13
  * @group Model
8
14
  * @param sources Сигналы-источники (`model.$.a`, `model.$.b`).
9
15
  * @param target Сигнал-цель (`model.$.total`).
@@ -16,7 +22,7 @@ export type BehaviorCleanup = () => void;
16
22
  * computeFrom([model.$.price, model.$.qty], model.$.total, (price, qty) => price * qty);
17
23
  * ```
18
24
  */
19
- export declare function computeFrom<R>(sources: ReadonlySignal<any>[], target: Signal<R>, fn: (...values: any[]) => R, options?: {
25
+ export declare function computeFrom<R>(sources: ReadonlySignal<any>[], target: Signal<R>, fn: (...values: any[]) => NoInfer<R>, options?: {
20
26
  when?: (...values: any[]) => boolean;
21
27
  }): BehaviorCleanup;
22
28
  /**
@@ -59,6 +65,18 @@ export declare function watchField<T>(source: ReadonlySignal<T>, cb: (value: T)
59
65
  * ```
60
66
  */
61
67
  export declare function transformValue<T>(target: Signal<T>, transformer: (value: T) => T): BehaviorCleanup;
68
+ /**
69
+ * Опции {@link resetWhen}. Без `resetValue` поле сбрасывается в `null`, поэтому `resetValue`
70
+ * обязателен, если `null` не входит в тип поля: `resetWhen(model.$.promoCode, cond)` для поля
71
+ * `string` не компилируется — нужно `{ resetValue: '' }`.
72
+ *
73
+ * @group Behaviors
74
+ */
75
+ export type ResetWhenOptionsArg<T> = null extends T ? [options?: {
76
+ resetValue?: NoInfer<T>;
77
+ }] : [options: {
78
+ resetValue: NoInfer<T>;
79
+ }];
62
80
  /**
63
81
  * Сброс значения поля к `resetValue` (по умолчанию `null`), когда `condition` истинно.
64
82
  *
@@ -68,12 +86,12 @@ export declare function transformValue<T>(target: Signal<T>, transformer: (value
68
86
  * resetWhen(model.$.cardNumber, () => model.paymentType !== 'card', { resetValue: '' });
69
87
  * ```
70
88
  */
71
- export declare function resetWhen<T>(target: Signal<T>, condition: () => boolean, options?: {
72
- resetValue?: T;
73
- }): BehaviorCleanup;
89
+ export declare function resetWhen<T>(target: Signal<T>, condition: () => boolean, ...[options]: ResetWhenOptionsArg<T>): BehaviorCleanup;
74
90
  /**
75
91
  * Двусторонняя синхронизация двух полей (опционально с трансформом `a → b`).
76
- * Сходимость обеспечивается peek-guard'ом; флаг предотвращает лишние круги.
92
+ * Сходимость обеспечивается peek-guard'ом; флаг предотвращает лишние круги. При создании источник —
93
+ * `a`: `b` получает его значение (через `transform`), обратной записи при создании нет. Записи в
94
+ * оба поля в одном тике — побеждает последняя.
77
95
  *
78
96
  * @group Model
79
97
  * @example
@@ -81,7 +99,7 @@ export declare function resetWhen<T>(target: Signal<T>, condition: () => boolean
81
99
  * syncFields(model.$.field1, model.$.field2);
82
100
  * ```
83
101
  */
84
- export declare function syncFields<T>(a: Signal<T>, b: Signal<T>, options?: {
102
+ export declare function syncFields<T>(a: Signal<T>, b: Signal<NoInfer<T>>, options?: {
85
103
  transform?: (value: T) => T;
86
104
  }): BehaviorCleanup;
87
105
  /**
@@ -3,15 +3,29 @@ import { FormModel, PathAwareSignal } from './types';
3
3
  * Обойти ВСЕ листовые сигналы модели (включая элементы массивов), вызвав `visit` на каждом.
4
4
  *
5
5
  * Внутри реактивного `effect` служит подпиской «любое поле изменилось»: `visit(sig => void sig.value)`
6
- * подписывает на значения листьев, а обход массивов через `items.value` — на их состав. Так строятся
7
- * триггеры `change`/`blur` стратегий валидации (см. `createFormValidation`), тем же паттерном, что
8
- * `revalidateWhen`, но без ручного перечисления зависимостей.
6
+ * подписывает на значения листьев, а обход массивов через `items.value` — на их состав. Тот же
7
+ * паттерн, что `revalidateWhen`, но без ручного перечисления зависимостей.
8
+ *
9
+ * Сами массивы обход не посещает — только их элементы. Поле, привязанное к массиву целиком
10
+ * (мультивыбор), живёт на сигнале массива; чтобы увидеть и его, берите {@link eachValueSignal}.
9
11
  *
10
12
  * @group Model
11
13
  */
12
14
  export declare function eachLeafSignal<T>(model: FormModel<T>, visit: (signal: PathAwareSignal<unknown>) => void): void;
13
15
  /**
14
- * Создать реактивную модель данных формы (слой M1).
16
+ * Обойти ВСЕ ручки значений модели: листья (включая элементы массивов) И сами массивы.
17
+ *
18
+ * Отличие от {@link eachLeafSignal} — узлы-массивы: массив бывает одним значением поля
19
+ * (`{ model: model.$.tags, component }`), и нода такого поля привязана к сигналу массива, а не
20
+ * к сигналам элементов. Обходчику, которому нужна именно НОДА поля (стратегия `blur` подписывается
21
+ * на её `touched`), одних листьев мало — он не увидел бы мультивыбор. Так строятся триггеры
22
+ * `change`/`blur` стратегий валидации (см. `createFormValidation`).
23
+ *
24
+ * @group Model
25
+ */
26
+ export declare function eachValueSignal<T>(model: FormModel<T>, visit: (signal: PathAwareSignal<unknown>) => void): void;
27
+ /**
28
+ * Создать реактивную модель данных формы.
15
29
  *
16
30
  * @group Model
17
31
  * @param initial Начальные значения (объект). Определяют форму данных и initial-снимок.
@@ -3,7 +3,7 @@ import { Signal } from '@preact/signals-core';
3
3
  * Пометить сигнал производным (вычисляемым).
4
4
  *
5
5
  * Вызывается операторами {@link computeFrom}/`compute` для их сигнала-цели. После этого
6
- * bulk-сеттеры (`model.set`/`model.patch`, `patchValue`/`setValue`) пропускают это поле, чтобы
6
+ * bulk-сеттеры (`model.set`/`model.patch`, `setValue` группы формы) пропускают это поле, чтобы
7
7
  * значение из payload не затирало вычисляемое. Прикладной код напрямую обычно не вызывает.
8
8
  *
9
9
  * Идемпотентна на уровне флага: повторные вызовы наращивают счётчик ссылок, чтобы каждый оператор,
@@ -0,0 +1,42 @@
1
+ /**
2
+ * `@reformer/core/model` — низкоуровневый реактивный субстрат и barrel модуля `model`.
3
+ *
4
+ * Это «прокси-объект с сигналами» и инструментарий для построения доменных модулей поверх него
5
+ * (form, table, …). Модуль СТРОГО реактивный: НИЧЕГО связанного с формами/валидацией/схемами здесь
6
+ * нет — только модель, value-операции, producer-флаг и утилиты субстрата. Граница model⇏form
7
+ * зафиксирована ESLint-правилом (`no-restricted-imports` на `src/model/**`).
8
+ *
9
+ * Реактивный рантайм (`signal/computed/effect/…`) живёт в отдельном subpath `@reformer/core/signals`
10
+ * (единый владелец `@preact/signals-core`) — импортируй его оттуда; здесь он НЕ реэкспортируется,
11
+ * чтобы зонтичный barrel `.` не разрастался рантаймом.
12
+ *
13
+ * Состав (реэкспорты — из тех же файлов, что использует зонтик `.`, поэтому `.` и `/model` — один
14
+ * module-инстанс: общий `derived`-WeakMap, единая идентичность `Signal`):
15
+ * - **модель** — `createModel` + типы `FormModel`/`ModelArray`/… + `PathAwareSignal`;
16
+ * - **шаблон элемента массива** — `arrayOf(blank)`: что кладёт `push()` без значения;
17
+ * - **обход значений** — `eachLeafSignal` (листья) и `eachValueSignal` (листья и массивы целиком);
18
+ * - **ручка → фасад** — `modelOf(model.$.<группа | массив>)`: под-модель или фасад массива;
19
+ * - **value-операции** (реактивные правила) — `computeFrom`/`copyFrom`/`watchField`/`transformValue`/
20
+ * `resetWhen`/`syncFields`/`revalidateWhen`;
21
+ * - **producer-owned флаг** — `markDerived`/`isDerived`/`unmarkDerived`;
22
+ * - **утилиты субстрата** — `runOutsideEffect`/`safeCallback`/`safeDebouncedCallback` и
23
+ * `deferredWritesSettled` (дождаться отложенных записей текущего тика);
24
+ * - **сравнение значений** — `deepEqual`, на нём стоят `isDirty` и сверка «модель изменилась».
25
+ *
26
+ * Запасной шаблон элемента массива модель принимает от того, кто строит её извне (сборка формы
27
+ * передаёт `initialValue` узла-массива); что это узел схемы, модель не знает.
28
+ *
29
+ * @group Model
30
+ * @module model
31
+ */
32
+ export { createModel, eachLeafSignal, eachValueSignal } from './create-model';
33
+ export { arrayOf } from './model-nodes';
34
+ export type { DeepPartial, FormModel, ModelArray, ModelArraySignals, ModelGroupSignals, ModelObject, ModelValue, ModelSignals, ModelApi, PathAwareSignal, } from './types';
35
+ export { isModelContainerSignal, isValueSignal } from './model-signals-proxy';
36
+ export { modelOf } from './model-value-proxy';
37
+ export type { ModelOf } from './model-value-proxy';
38
+ export { computeFrom, copyFrom, watchField, transformValue, resetWhen, syncFields, revalidateWhen, } from './behaviors-value';
39
+ export type { BehaviorCleanup, ResetWhenOptionsArg } from './behaviors-value';
40
+ export { markDerived, isDerived, unmarkDerived } from './derived-registry';
41
+ export { runOutsideEffect, safeCallback, safeDebouncedCallback, deferredWritesSettled, } from './safe-effect';
42
+ export { deepEqual } from './model-nodes';