@reformer/core 5.0.0 → 6.0.0

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 (131) hide show
  1. package/README.md +7 -5
  2. package/dist/behaviors-O9a1Djj9.js +147 -0
  3. package/dist/behaviors.d.ts +131 -4
  4. package/dist/behaviors.js +298 -27
  5. package/dist/core/model/behaviors.d.ts +123 -0
  6. package/dist/core/model/form-model.d.ts +18 -0
  7. package/dist/core/model/index.d.ts +12 -0
  8. package/dist/core/model/types.d.ts +112 -0
  9. package/dist/core/model/validate-model.d.ts +46 -0
  10. package/dist/core/nodes/array-node.d.ts +34 -2
  11. package/dist/core/nodes/group-node.d.ts +19 -71
  12. package/dist/core/nodes/model-array-node.d.ts +71 -0
  13. package/dist/core/types/deep-schema.d.ts +16 -2
  14. package/dist/core/types/form-proxy.d.ts +17 -6
  15. package/dist/core/types/index.d.ts +5 -23
  16. package/dist/core/types/validation-schema.d.ts +15 -66
  17. package/dist/core/utils/create-form.d.ts +24 -0
  18. package/dist/core/utils/derived-registry.d.ts +5 -0
  19. package/dist/core/utils/index.d.ts +4 -4
  20. package/dist/core/utils/signal-node-registry.d.ts +12 -0
  21. package/dist/core/utils/type-guards.d.ts +2 -3
  22. package/dist/core/validation/index.d.ts +5 -11
  23. package/dist/core/validation/validators/email.d.ts +5 -29
  24. package/dist/core/validation/validators/future-date.d.ts +6 -28
  25. package/dist/core/validation/validators/index.d.ts +11 -4
  26. package/dist/core/validation/validators/integer.d.ts +13 -0
  27. package/dist/core/validation/validators/is-date.d.ts +5 -28
  28. package/dist/core/validation/validators/is-number.d.ts +14 -0
  29. package/dist/core/validation/validators/max-age.d.ts +6 -29
  30. package/dist/core/validation/validators/max-date.d.ts +6 -29
  31. package/dist/core/validation/validators/max-length.d.ts +5 -30
  32. package/dist/core/validation/validators/max.d.ts +7 -29
  33. package/dist/core/validation/validators/min-age.d.ts +6 -29
  34. package/dist/core/validation/validators/min-date.d.ts +6 -29
  35. package/dist/core/validation/validators/min-length.d.ts +5 -30
  36. package/dist/core/validation/validators/min.d.ts +7 -29
  37. package/dist/core/validation/validators/multiple-of.d.ts +13 -0
  38. package/dist/core/validation/validators/non-negative.d.ts +13 -0
  39. package/dist/core/validation/validators/non-zero.d.ts +13 -0
  40. package/dist/core/validation/validators/past-date.d.ts +5 -28
  41. package/dist/core/validation/validators/pattern.d.ts +5 -32
  42. package/dist/core/validation/validators/phone.d.ts +9 -19
  43. package/dist/core/validation/validators/required.d.ts +10 -31
  44. package/dist/core/validation/validators/url.d.ts +13 -15
  45. package/dist/index.d.ts +3 -4
  46. package/dist/index.js +1299 -875
  47. package/dist/validators/email.js +7 -9
  48. package/dist/validators/future-date.js +11 -12
  49. package/dist/validators/integer.d.ts +2 -0
  50. package/dist/validators/integer.js +10 -0
  51. package/dist/validators/is-date.js +6 -7
  52. package/dist/validators/is-number.d.ts +2 -0
  53. package/dist/validators/is-number.js +10 -0
  54. package/dist/validators/max-age.js +11 -12
  55. package/dist/validators/max-date.js +11 -12
  56. package/dist/validators/max-length.js +12 -8
  57. package/dist/validators/max.js +5 -6
  58. package/dist/validators/min-age.js +10 -11
  59. package/dist/validators/min-date.js +12 -13
  60. package/dist/validators/min-length.js +12 -8
  61. package/dist/validators/min.js +6 -7
  62. package/dist/validators/multiple-of.d.ts +2 -0
  63. package/dist/validators/multiple-of.js +10 -0
  64. package/dist/validators/non-negative.d.ts +2 -0
  65. package/dist/validators/non-negative.js +10 -0
  66. package/dist/validators/non-zero.d.ts +2 -0
  67. package/dist/validators/non-zero.js +10 -0
  68. package/dist/validators/past-date.js +11 -12
  69. package/dist/validators/pattern.js +6 -7
  70. package/dist/validators/phone.js +14 -32
  71. package/dist/validators/required.js +9 -10
  72. package/dist/validators/url.js +19 -16
  73. package/dist/validators.js +67 -54
  74. package/llms.txt +959 -2584
  75. package/package.json +19 -35
  76. package/dist/behaviors/compute-from.d.ts +0 -2
  77. package/dist/behaviors/compute-from.js +0 -31
  78. package/dist/behaviors/copy-from.d.ts +0 -2
  79. package/dist/behaviors/copy-from.js +0 -29
  80. package/dist/behaviors/enable-when.d.ts +0 -2
  81. package/dist/behaviors/enable-when.js +0 -25
  82. package/dist/behaviors/reset-when.d.ts +0 -2
  83. package/dist/behaviors/reset-when.js +0 -24
  84. package/dist/behaviors/revalidate-when.d.ts +0 -2
  85. package/dist/behaviors/revalidate-when.js +0 -18
  86. package/dist/behaviors/sync-fields.d.ts +0 -2
  87. package/dist/behaviors/sync-fields.js +0 -41
  88. package/dist/behaviors/transform-value.d.ts +0 -2
  89. package/dist/behaviors/transform-value.js +0 -45
  90. package/dist/behaviors/watch-field.d.ts +0 -2
  91. package/dist/behaviors/watch-field.js +0 -21
  92. package/dist/core/behavior/behavior-context.d.ts +0 -47
  93. package/dist/core/behavior/behavior-registry.d.ts +0 -85
  94. package/dist/core/behavior/behaviors/compute-from.d.ts +0 -70
  95. package/dist/core/behavior/behaviors/copy-from.d.ts +0 -56
  96. package/dist/core/behavior/behaviors/enable-when.d.ts +0 -118
  97. package/dist/core/behavior/behaviors/index.d.ts +0 -11
  98. package/dist/core/behavior/behaviors/reset-when.d.ts +0 -64
  99. package/dist/core/behavior/behaviors/revalidate-when.d.ts +0 -53
  100. package/dist/core/behavior/behaviors/sync-fields.d.ts +0 -48
  101. package/dist/core/behavior/behaviors/transform-value.d.ts +0 -192
  102. package/dist/core/behavior/behaviors/watch-field.d.ts +0 -80
  103. package/dist/core/behavior/compose-behavior.d.ts +0 -96
  104. package/dist/core/behavior/index.d.ts +0 -11
  105. package/dist/core/behavior/types.d.ts +0 -146
  106. package/dist/core/types/field-path.d.ts +0 -42
  107. package/dist/core/types/form-context.d.ts +0 -89
  108. package/dist/core/utils/field-path-navigator.d.ts +0 -240
  109. package/dist/core/utils/field-path.d.ts +0 -60
  110. package/dist/core/utils/registry-helpers.d.ts +0 -43
  111. package/dist/core/validation/core/apply-when.d.ts +0 -22
  112. package/dist/core/validation/core/apply.d.ts +0 -52
  113. package/dist/core/validation/core/index.d.ts +0 -8
  114. package/dist/core/validation/core/validate-async.d.ts +0 -36
  115. package/dist/core/validation/core/validate-tree.d.ts +0 -35
  116. package/dist/core/validation/core/validate.d.ts +0 -26
  117. package/dist/core/validation/validate-form.d.ts +0 -48
  118. package/dist/core/validation/validation-applicator.d.ts +0 -70
  119. package/dist/core/validation/validation-context.d.ts +0 -86
  120. package/dist/core/validation/validation-registry.d.ts +0 -142
  121. package/dist/core/validation/validators/array-validators.d.ts +0 -53
  122. package/dist/core/validation/validators/number.d.ts +0 -31
  123. package/dist/field-path-DuKdGcIE.js +0 -66
  124. package/dist/hooks/useHiddenCondition.d.ts +0 -25
  125. package/dist/index-D25LsbRm.js +0 -73
  126. package/dist/registry-helpers-Bv_BJ1s-.js +0 -615
  127. package/dist/safe-effect-Dh8uw81c.js +0 -20
  128. package/dist/validate-C3XiA_zf.js +0 -10
  129. package/dist/validators/number.d.ts +0 -2
  130. package/dist/validators/number.js +0 -35
  131. package/dist/validators-BGsNOgT1.js +0 -207
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reformer/core",
3
- "version": "5.0.0",
3
+ "version": "6.0.0",
4
4
  "description": "Reactive form state management library for React with signals-based architecture",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -55,45 +55,29 @@
55
55
  "types": "./dist/validators/phone.d.ts",
56
56
  "import": "./dist/validators/phone.js"
57
57
  },
58
- "./validators/number": {
59
- "types": "./dist/validators/number.d.ts",
60
- "import": "./dist/validators/number.js"
58
+ "./validators/is-number": {
59
+ "types": "./dist/validators/is-number.d.ts",
60
+ "import": "./dist/validators/is-number.js"
61
61
  },
62
- "./validators/date": {
63
- "types": "./dist/validators/date.d.ts",
64
- "import": "./dist/validators/date.js"
65
- },
66
- "./behaviors/copy-from": {
67
- "types": "./dist/behaviors/copy-from.d.ts",
68
- "import": "./dist/behaviors/copy-from.js"
69
- },
70
- "./behaviors/enable-when": {
71
- "types": "./dist/behaviors/enable-when.d.ts",
72
- "import": "./dist/behaviors/enable-when.js"
62
+ "./validators/integer": {
63
+ "types": "./dist/validators/integer.d.ts",
64
+ "import": "./dist/validators/integer.js"
73
65
  },
74
- "./behaviors/compute-from": {
75
- "types": "./dist/behaviors/compute-from.d.ts",
76
- "import": "./dist/behaviors/compute-from.js"
66
+ "./validators/multiple-of": {
67
+ "types": "./dist/validators/multiple-of.d.ts",
68
+ "import": "./dist/validators/multiple-of.js"
77
69
  },
78
- "./behaviors/watch-field": {
79
- "types": "./dist/behaviors/watch-field.d.ts",
80
- "import": "./dist/behaviors/watch-field.js"
70
+ "./validators/non-negative": {
71
+ "types": "./dist/validators/non-negative.d.ts",
72
+ "import": "./dist/validators/non-negative.js"
81
73
  },
82
- "./behaviors/revalidate-when": {
83
- "types": "./dist/behaviors/revalidate-when.d.ts",
84
- "import": "./dist/behaviors/revalidate-when.js"
74
+ "./validators/non-zero": {
75
+ "types": "./dist/validators/non-zero.d.ts",
76
+ "import": "./dist/validators/non-zero.js"
85
77
  },
86
- "./behaviors/sync-fields": {
87
- "types": "./dist/behaviors/sync-fields.d.ts",
88
- "import": "./dist/behaviors/sync-fields.js"
89
- },
90
- "./behaviors/reset-when": {
91
- "types": "./dist/behaviors/reset-when.d.ts",
92
- "import": "./dist/behaviors/reset-when.js"
93
- },
94
- "./behaviors/transform-value": {
95
- "types": "./dist/behaviors/transform-value.d.ts",
96
- "import": "./dist/behaviors/transform-value.js"
78
+ "./validators/date": {
79
+ "types": "./dist/validators/date.d.ts",
80
+ "import": "./dist/validators/date.js"
97
81
  }
98
82
  },
99
83
  "sideEffects": false,
@@ -1,2 +0,0 @@
1
- export * from '../core/behavior/behaviors/compute-from'
2
- export {}
@@ -1,31 +0,0 @@
1
- import { effect as _ } from "@preact/signals-core";
2
- import { b as v } from "../registry-helpers-Bv_BJ1s-.js";
3
- import { r as V } from "../safe-effect-Dh8uw81c.js";
4
- function N(n, i, s, f) {
5
- const { debounce: p, condition: u } = f || {}, h = (r, E, m) => {
6
- const a = r.getFieldByPath(i.__path);
7
- if (!a) return null;
8
- const o = n.map((e) => r.getFieldByPath(e.__path)).filter((e) => e !== void 0);
9
- return o.length === 0 ? null : _(() => {
10
- o.forEach((e) => e.value.value), m(() => {
11
- if (u) {
12
- const t = r.getValue();
13
- if (!u(t)) return;
14
- }
15
- const e = o.map((t) => t.value.value), l = {};
16
- n.forEach((t, d) => {
17
- const g = t.__path.split(".").pop() || t.__path;
18
- l[g] = e[d];
19
- });
20
- const c = s(l);
21
- a.value.peek() !== c && V(() => {
22
- a.setValue(c, { emitEvent: !1 });
23
- });
24
- });
25
- });
26
- };
27
- v().register(h, { debounce: p });
28
- }
29
- export {
30
- N as computeFrom
31
- };
@@ -1,2 +0,0 @@
1
- export * from '../core/behavior/behaviors/copy-from'
2
- export {}
@@ -1,29 +0,0 @@
1
- import { r as s } from "../safe-effect-Dh8uw81c.js";
2
- import { watchField as d } from "./watch-field.js";
3
- function E(l, c, m) {
4
- const { when: a, fields: o = "all", transform: i, debounce: p } = m || {};
5
- d(
6
- l,
7
- (t, n) => {
8
- if (a) {
9
- const f = n.form.getValue();
10
- if (!a(f)) return;
11
- }
12
- const h = i ? i(t) : t, e = n.form.getFieldByPath(c.__path);
13
- e && s(() => {
14
- if (o === "all" || !o)
15
- e.setValue(h, { emitEvent: !1 });
16
- else {
17
- const f = {};
18
- o.forEach((r) => {
19
- t && typeof t == "object" && (f[r] = t[r]);
20
- }), "patchValue" in e && e.patchValue(f);
21
- }
22
- });
23
- },
24
- { debounce: p }
25
- );
26
- }
27
- export {
28
- E as copyFrom
29
- };
@@ -1,2 +0,0 @@
1
- export * from '../core/behavior/behaviors/enable-when'
2
- export {}
@@ -1,25 +0,0 @@
1
- import { effect as c } from "@preact/signals-core";
2
- import { b } from "../registry-helpers-Bv_BJ1s-.js";
3
- import { r as d } from "../safe-effect-Dh8uw81c.js";
4
- function h(t, n, r) {
5
- const { debounce: o, resetOnDisable: a = !1 } = r || {}, i = (s, m, l) => {
6
- const e = s.getFieldByPath(t.__path);
7
- return e ? c(() => {
8
- const f = s.value.value;
9
- l(() => {
10
- const u = n(f);
11
- d(() => {
12
- u ? e.enable() : (e.disable(), a && e.reset());
13
- });
14
- });
15
- }) : null;
16
- };
17
- b().register(i, { debounce: o });
18
- }
19
- function _(t, n, r) {
20
- h(t, (o) => !n(o), r);
21
- }
22
- export {
23
- _ as disableWhen,
24
- h as enableWhen
25
- };
@@ -1,2 +0,0 @@
1
- export * from '../core/behavior/behaviors/reset-when'
2
- export {}
@@ -1,24 +0,0 @@
1
- import { effect as c } from "@preact/signals-core";
2
- import { b as d } from "../registry-helpers-Bv_BJ1s-.js";
3
- import { r as h } from "../safe-effect-Dh8uw81c.js";
4
- function R(r, n, o) {
5
- const { debounce: s, resetValue: u = null, onlyIfDirty: a = !1 } = o || {}, i = (t, m, l) => {
6
- const e = t.getFieldByPath(r.__path);
7
- return e ? c(() => {
8
- const f = t.value.value;
9
- l(() => {
10
- if (n(f)) {
11
- if (a && !e.dirty.value)
12
- return;
13
- h(() => {
14
- e.setValue(u), e.markAsPristine(), e.markAsUntouched();
15
- });
16
- }
17
- });
18
- }) : null;
19
- };
20
- d().register(i, { debounce: s });
21
- }
22
- export {
23
- R as resetWhen
24
- };
@@ -1,2 +0,0 @@
1
- export * from '../core/behavior/behaviors/revalidate-when'
2
- export {}
@@ -1,18 +0,0 @@
1
- import { effect as d } from "@preact/signals-core";
2
- import { b as h } from "../registry-helpers-Bv_BJ1s-.js";
3
- function p(o, a, i) {
4
- const { debounce: l } = i || {}, u = (t, s, c) => {
5
- const r = t.getFieldByPath(o.__path);
6
- if (!r) return null;
7
- const n = a.map((e) => t.getFieldByPath(e.__path)).filter((e) => e !== void 0);
8
- return n.length === 0 ? null : d(() => {
9
- n.forEach((e) => e.value.value), c(() => {
10
- r.validate();
11
- });
12
- });
13
- };
14
- h().register(u, { debounce: l });
15
- }
16
- export {
17
- p as revalidateWhen
18
- };
@@ -1,2 +0,0 @@
1
- export * from '../core/behavior/behaviors/sync-fields'
2
- export {}
@@ -1,41 +0,0 @@
1
- import { effect as o } from "@preact/signals-core";
2
- import { b as v } from "../registry-helpers-Bv_BJ1s-.js";
3
- import { r as i } from "../safe-effect-Dh8uw81c.js";
4
- function E(u, f, c) {
5
- const { debounce: d, transform: a } = c || {}, p = (n, h, l) => {
6
- const r = n.getFieldByPath(u.__path), s = n.getFieldByPath(f.__path);
7
- if (!r || !s) return null;
8
- let e = !1;
9
- const g = o(() => {
10
- const t = r.value.value;
11
- e || l(() => {
12
- e = !0, i(() => {
13
- try {
14
- const y = a ? a(t) : t;
15
- s.setValue(y, { emitEvent: !1 });
16
- } finally {
17
- e = !1;
18
- }
19
- });
20
- });
21
- }), m = o(() => {
22
- const t = s.value.value;
23
- e || l(() => {
24
- e = !0, i(() => {
25
- try {
26
- r.setValue(t, { emitEvent: !1 });
27
- } finally {
28
- e = !1;
29
- }
30
- });
31
- });
32
- });
33
- return () => {
34
- g(), m();
35
- };
36
- };
37
- v().register(p, { debounce: d });
38
- }
39
- export {
40
- E as syncFields
41
- };
@@ -1,2 +0,0 @@
1
- export * from '../core/behavior/behaviors/transform-value'
2
- export {}
@@ -1,45 +0,0 @@
1
- import { watchField as p } from "./watch-field.js";
2
- function u(e, t, o) {
3
- const { onUserChangeOnly: n = !1, emitEvent: m = !0, debounce: c } = o || {};
4
- p(
5
- e,
6
- (s, i) => {
7
- const a = i.form.getFieldByPath(e.__path);
8
- if (!a || n && !a.touched.value)
9
- return;
10
- const f = t(s);
11
- f !== s && a.setValue(f, { emitEvent: m });
12
- },
13
- { debounce: c }
14
- );
15
- }
16
- function r(e, t) {
17
- return (o, n) => {
18
- u(o, e, { ...t, ...n });
19
- };
20
- }
21
- const h = {
22
- /** Перевести в верхний регистр */
23
- toUpperCase: r((e) => e?.toUpperCase()),
24
- /** Перевести в нижний регистр */
25
- toLowerCase: r((e) => e?.toLowerCase()),
26
- /** Удалить пробелы с краев */
27
- trim: r((e) => e?.trim()),
28
- /** Удалить все пробелы */
29
- removeSpaces: r((e) => e?.replace(/\s/g, "")),
30
- /** Оставить только цифры */
31
- digitsOnly: r((e) => e?.replace(/\D/g, "")),
32
- /** Округлить число */
33
- round: r(
34
- (e) => typeof e == "number" ? Math.round(e) : e
35
- ),
36
- /** Округлить до 2 знаков после запятой */
37
- roundTo2: r(
38
- (e) => typeof e == "number" ? Math.round(e * 100) / 100 : e
39
- )
40
- };
41
- export {
42
- r as createTransformer,
43
- u as transformValue,
44
- h as transformers
45
- };
@@ -1,2 +0,0 @@
1
- export * from '../core/behavior/behaviors/watch-field'
2
- export {}
@@ -1,21 +0,0 @@
1
- import { effect as c } from "@preact/signals-core";
2
- import { b as d } from "../registry-helpers-Bv_BJ1s-.js";
3
- import { r as i } from "../safe-effect-Dh8uw81c.js";
4
- function g(n, r, u) {
5
- const { debounce: a, immediate: f = !1 } = u || {}, s = (l, o, m) => {
6
- const e = l.getFieldByPath(n.__path);
7
- return e ? (f && i(() => {
8
- const t = e.value.value;
9
- r(t, o);
10
- }), c(() => {
11
- const t = e.value.value;
12
- m(() => {
13
- i(() => r(t, o));
14
- });
15
- })) : null;
16
- };
17
- d().register(s, { debounce: a });
18
- }
19
- export {
20
- g as watchField
21
- };
@@ -1,47 +0,0 @@
1
- import { GroupNode } from '../nodes/group-node';
2
- import { FormProxy } from '../types/form-proxy';
3
- import { FormContext } from '../types/form-context';
4
- import { FieldPathNode } from '../types/field-path';
5
- /**
6
- * Реализация {@link FormContext} для behaviors. Создаётся фреймворком и передаётся
7
- * в callback'и behaviors (`watchField`, `computeFrom`, …) — напрямую инстанцировать
8
- * не нужно.
9
- *
10
- * @example
11
- * ```typescript
12
- * import { watchField } from '@reformer/core/behaviors/watch-field';
13
- *
14
- * watchField(path.country, (value, ctx) => {
15
- * // ctx — экземпляр BehaviorContextImpl
16
- * ctx.setFieldValue(path.city, '');
17
- * });
18
- * ```
19
- */
20
- export declare class BehaviorContextImpl<TForm> implements FormContext<TForm> {
21
- /**
22
- * Форма с типизированным Proxy-доступом к полям
23
- */
24
- readonly form: FormProxy<TForm>;
25
- private _form;
26
- constructor(form: GroupNode<TForm>);
27
- /**
28
- * Безопасно установить значение поля по строковому пути или FieldPath
29
- *
30
- * Автоматически использует emitEvent: false для предотвращения циклов
31
- *
32
- * @param path - Строковый путь к полю или FieldPath объект
33
- * @param value - Новое значение
34
- */
35
- setFieldValue(path: string | FieldPathNode<TForm, unknown>, value: unknown): void;
36
- /**
37
- * Получить поле формы по строковому пути
38
- *
39
- * Используется для динамического доступа к вложенным полям, например:
40
- * - `ctx.getFieldByPath('address.city')` -> FieldNode
41
- * - `ctx.getFieldByPath(path.city.__path)` -> FieldNode (для nested behaviors)
42
- *
43
- * @param path - Строковый путь к полю (например "address.city")
44
- * @returns FieldNode или undefined если поле не найдено
45
- */
46
- getFieldByPath(path: string): import('../..').FormNode<import('../types').FormValue> | undefined;
47
- }
@@ -1,85 +0,0 @@
1
- import { GroupNode } from '../nodes/group-node';
2
- import { BehaviorHandlerFn, BehaviorOptions } from './types';
3
- import { AbstractRegistry } from '../utils/abstract-registry';
4
- import { FormFields } from '../types';
5
- /**
6
- * Зарегистрированный behavior с опциями
7
- */
8
- export interface RegisteredBehavior {
9
- /** Handler функция behavior */
10
- handler: BehaviorHandlerFn<FormFields>;
11
- /** Debounce в миллисекундах */
12
- debounce?: number;
13
- }
14
- /**
15
- * Реестр behaviors для формы
16
- *
17
- * Каждый экземпляр GroupNode создает собственный реестр (композиция).
18
- * Устраняет race conditions и изолирует формы друг от друга.
19
- *
20
- * Наследует AbstractRegistry для унификации:
21
- * - Управления global stack
22
- * - Template methods begin/end registration
23
- *
24
- * @example
25
- * ```typescript
26
- * class GroupNode {
27
- * private readonly behaviorRegistry = new BehaviorRegistry();
28
- *
29
- * applyBehaviorSchema(schemaFn) {
30
- * this.behaviorRegistry.beginRegistration(); // Pushes this to stack
31
- * schemaFn(createBehaviorFieldPath(this)); // Uses getCurrent()
32
- * return this.behaviorRegistry.endRegistration(this); // Pops from stack
33
- * }
34
- * }
35
- * ```
36
- */
37
- export declare class BehaviorRegistry extends AbstractRegistry<RegisteredBehavior> {
38
- /**
39
- * Получить текущий активный реестр из context stack
40
- *
41
- * @returns Текущий активный реестр или null
42
- *
43
- * @example
44
- * ```typescript
45
- * // В schema-behaviors.ts
46
- * export function copyFrom(...) {
47
- * const registry = BehaviorRegistry.getCurrent();
48
- * if (registry) {
49
- * registry.register({ ... });
50
- * }
51
- * }
52
- * ```
53
- */
54
- static getCurrent(): BehaviorRegistry | null;
55
- /**
56
- * Зарегистрировать behavior handler
57
- * Вызывается функциями из schema-behaviors.ts
58
- *
59
- * @param handler - BehaviorHandlerFn функция
60
- * @param options - Опции behavior (debounce)
61
- *
62
- * @example
63
- * ```typescript
64
- * const handler = createCopyBehavior(target, source, { when: ... });
65
- * registry.register(handler, { debounce: 300 });
66
- * ```
67
- */
68
- register<T extends FormFields>(handler: BehaviorHandlerFn<T>, options?: BehaviorOptions): void;
69
- /**
70
- * Завершить регистрацию и применить behaviors к форме
71
- * Создает effect подписки для всех зарегистрированных behaviors
72
- *
73
- * @param form - GroupNode формы
74
- * @returns Количество зарегистрированных behaviors и функция cleanup
75
- */
76
- endRegistration<T extends FormFields>(form: GroupNode<T>): {
77
- count: number;
78
- cleanup: () => void;
79
- };
80
- /**
81
- * Создать effect подписку для behavior
82
- * @private
83
- */
84
- private createEffect;
85
- }
@@ -1,70 +0,0 @@
1
- import { FieldPathNode } from '../../types';
2
- import { ComputeFromOptions } from '../types';
3
- /**
4
- * Автоматически вычисляет значение поля на основе других полей
5
- *
6
- * @group Behaviors
7
- * @category Behavior Rules
8
- *
9
- * @param sources - Массив полей-зависимостей
10
- * @param target - Поле для записи результата
11
- * @param computeFn - Функция вычисления (принимает объект с именами полей)
12
- * @param options - Опции (`debounce`, `condition`, `trigger`)
13
- *
14
- * @example Многополевой расчёт — total = price × quantity
15
- * ```typescript
16
- * import { computeFrom, type BehaviorSchemaFn } from '@reformer/core/behaviors';
17
- *
18
- * interface OrderForm {
19
- * price: number;
20
- * quantity: number;
21
- * total: number;
22
- * }
23
- *
24
- * export const orderBehavior: BehaviorSchemaFn<OrderForm> = (path) => {
25
- * computeFrom(
26
- * [path.price, path.quantity],
27
- * path.total,
28
- * (values) =>
29
- * (typeof values.price === 'number' ? values.price : 0) *
30
- * (typeof values.quantity === 'number' ? values.quantity : 0),
31
- * );
32
- * };
33
- * ```
34
- *
35
- * @example Edge case — async-like дорогие вычисления с `debounce` и условием
36
- * ```typescript
37
- * import { computeFrom, type BehaviorSchemaFn } from '@reformer/core/behaviors';
38
- *
39
- * interface MortgageForm {
40
- * loanType: 'mortgage' | 'consumer';
41
- * loanAmount: number;
42
- * loanTerm: number;
43
- * interestRate: number;
44
- * monthlyPayment: number;
45
- * }
46
- *
47
- * function annuity(values: MortgageForm): number {
48
- * const { loanAmount, loanTerm, interestRate } = values;
49
- * if (!loanAmount || !loanTerm || !interestRate) return 0;
50
- * const r = interestRate / 100 / 12;
51
- * const n = loanTerm;
52
- * return Math.round((loanAmount * r * Math.pow(1 + r, n)) / (Math.pow(1 + r, n) - 1));
53
- * }
54
- *
55
- * export const mortgageBehavior: BehaviorSchemaFn<MortgageForm> = (path) => {
56
- * computeFrom(
57
- * [path.loanAmount, path.loanTerm, path.interestRate],
58
- * path.monthlyPayment,
59
- * annuity,
60
- * {
61
- * debounce: 300, // не пересчитываем на каждый keystroke
62
- * condition: (form) => form.loanType === 'mortgage', // считаем только для ипотеки
63
- * },
64
- * );
65
- * };
66
- * ```
67
- *
68
- * @see [docs/llms/20-compute-vs-watch.md](../../../../docs/llms/20-compute-vs-watch.md)
69
- */
70
- export declare function computeFrom<TForm, TTarget>(sources: FieldPathNode<TForm, any>[], target: FieldPathNode<TForm, TTarget>, computeFn: (values: TForm) => TTarget, options?: ComputeFromOptions<TForm>): void;
@@ -1,56 +0,0 @@
1
- import { FieldPathNode } from '../../types';
2
- import { CopyFromOptions } from '../types';
3
- /**
4
- * Копирует значения из одного поля/группы в другое при выполнении условия
5
- *
6
- * @group Behaviors
7
- * @category Behavior Rules
8
- *
9
- * @param source - Откуда копировать
10
- * @param target - Куда копировать
11
- * @param options - Опции копирования (`when`, `fields`, `transform`, `debounce`)
12
- *
13
- * @example Скаляр → скаляр с условием
14
- * ```typescript
15
- * import { copyFrom, type BehaviorSchemaFn } from '@reformer/core/behaviors';
16
- *
17
- * interface ContactForm {
18
- * sameEmail: boolean;
19
- * email: string;
20
- * emailAdditional: string;
21
- * }
22
- *
23
- * export const contactBehavior: BehaviorSchemaFn<ContactForm> = (path) => {
24
- * copyFrom(path.email, path.emailAdditional, {
25
- * when: (form) => form.sameEmail === true,
26
- * });
27
- * };
28
- * ```
29
- *
30
- * @example Копирование группы с подмножеством полей и `transform`
31
- * ```typescript
32
- * import { copyFrom, type BehaviorSchemaFn } from '@reformer/core/behaviors';
33
- *
34
- * interface Address { country: string; region: string; city: string; street: string }
35
- * interface ProfileForm {
36
- * sameAsRegistration: boolean;
37
- * registrationAddress: Address;
38
- * residenceAddress: Address;
39
- * }
40
- *
41
- * export const profileBehavior: BehaviorSchemaFn<ProfileForm> = (path) => {
42
- * copyFrom(path.registrationAddress, path.residenceAddress, {
43
- * when: (form) => form.sameAsRegistration === true,
44
- * fields: ['country', 'region', 'city'], // street НЕ копируем
45
- * transform: (addr) => ({
46
- * ...addr,
47
- * country: addr.country.toUpperCase(), // нормализация при копировании
48
- * }),
49
- * debounce: 200,
50
- * });
51
- * };
52
- * ```
53
- *
54
- * @see [docs/llms/23-copy-from.md](../../../../docs/llms/23-copy-from.md)
55
- */
56
- export declare function copyFrom<TForm, TSource, TTarget>(source: FieldPathNode<TForm, TSource>, target: FieldPathNode<TForm, TTarget>, options?: CopyFromOptions<TSource, TForm>): void;