@reformer/core 1.1.0-beta.8 → 2.0.0-beta.2
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.
- package/dist/behaviors-DzYL8kY_.js +499 -0
- package/dist/behaviors.js +14 -14
- package/dist/core/behavior/create-field-path.d.ts +3 -16
- package/dist/core/nodes/group-node.d.ts +14 -193
- package/dist/core/utils/field-path.d.ts +48 -0
- package/dist/core/utils/index.d.ts +1 -0
- package/dist/core/validation/field-path.d.ts +3 -39
- package/dist/core/validation/validation-context.d.ts +23 -0
- package/dist/hooks/types.d.ts +328 -0
- package/dist/hooks/useFormControl.d.ts +13 -37
- package/dist/hooks/useFormControlValue.d.ts +167 -0
- package/dist/hooks/useSignalSubscription.d.ts +17 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +492 -986
- package/dist/{registry-helpers-BfCZcMkO.js → registry-helpers-BRxAr6nG.js} +136 -72
- package/dist/{validators-DjXtDVoE.js → validators-gXoHPdqM.js} +194 -231
- package/dist/validators.js +25 -25
- package/llms.txt +317 -172
- package/package.json +8 -4
- package/dist/behaviors-BRaiR-UY.js +0 -528
- package/dist/core/behavior/behavior-applicator.d.ts +0 -71
- package/dist/core/nodes/group-node/field-registry.d.ts +0 -191
- package/dist/core/nodes/group-node/index.d.ts +0 -11
- package/dist/core/nodes/group-node/proxy-builder.d.ts +0 -71
- package/dist/core/nodes/group-node/state-manager.d.ts +0 -184
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { d, w as
|
|
2
|
-
import { i as
|
|
3
|
-
import { i as R,
|
|
4
|
-
import { g as
|
|
5
|
-
import { V as
|
|
6
|
-
import { R as
|
|
7
|
-
import { v4 as
|
|
8
|
-
import { useRef as
|
|
9
|
-
class
|
|
1
|
+
import { d as y, w as u, E, r as U } from "./behaviors-DzYL8kY_.js";
|
|
2
|
+
import { i as Ee } from "./behaviors-DzYL8kY_.js";
|
|
3
|
+
import { i as T, a as R, A as j, V as q, T as K } from "./validators-gXoHPdqM.js";
|
|
4
|
+
import { g as be, c as Ve, d as we, v as Ae, b as ke } from "./validators-gXoHPdqM.js";
|
|
5
|
+
import { V as H, B as W, c as I } from "./registry-helpers-BRxAr6nG.js";
|
|
6
|
+
import { R as Fe, a as Oe, e as Pe, b as Te, g as Re, t as Ie } from "./registry-helpers-BRxAr6nG.js";
|
|
7
|
+
import { v4 as z } from "uuid";
|
|
8
|
+
import B, { useRef as L, useCallback as S } from "react";
|
|
9
|
+
class O {
|
|
10
10
|
// ============================================================================
|
|
11
11
|
// Protected состояние (для Template Method паттерна)
|
|
12
12
|
// ============================================================================
|
|
@@ -14,17 +14,17 @@ class A {
|
|
|
14
14
|
* Пользователь взаимодействовал с узлом (touched)
|
|
15
15
|
* Protected: наследники могут читать/изменять через методы
|
|
16
16
|
*/
|
|
17
|
-
_touched =
|
|
17
|
+
_touched = y(!1);
|
|
18
18
|
/**
|
|
19
19
|
* Значение узла было изменено (dirty)
|
|
20
20
|
* Protected: наследники могут читать/изменять через методы
|
|
21
21
|
*/
|
|
22
|
-
_dirty =
|
|
22
|
+
_dirty = y(!1);
|
|
23
23
|
/**
|
|
24
24
|
* Текущий статус узла
|
|
25
25
|
* Protected: наследники могут читать/изменять через методы
|
|
26
26
|
*/
|
|
27
|
-
_status =
|
|
27
|
+
_status = y("valid");
|
|
28
28
|
// ============================================================================
|
|
29
29
|
// Публичные computed signals (readonly для внешнего мира)
|
|
30
30
|
// ============================================================================
|
|
@@ -32,33 +32,33 @@ class A {
|
|
|
32
32
|
* Пользователь взаимодействовал с узлом (touched)
|
|
33
33
|
* Computed из _touched для предоставления readonly интерфейса
|
|
34
34
|
*/
|
|
35
|
-
touched =
|
|
35
|
+
touched = u(() => this._touched.value);
|
|
36
36
|
/**
|
|
37
37
|
* Пользователь не взаимодействовал с узлом (untouched)
|
|
38
38
|
*/
|
|
39
|
-
untouched =
|
|
39
|
+
untouched = u(() => !this._touched.value);
|
|
40
40
|
/**
|
|
41
41
|
* Значение узла было изменено (dirty)
|
|
42
42
|
* Computed из _dirty для предоставления readonly интерфейса
|
|
43
43
|
*/
|
|
44
|
-
dirty =
|
|
44
|
+
dirty = u(() => this._dirty.value);
|
|
45
45
|
/**
|
|
46
46
|
* Значение узла не было изменено (pristine)
|
|
47
47
|
*/
|
|
48
|
-
pristine =
|
|
48
|
+
pristine = u(() => !this._dirty.value);
|
|
49
49
|
/**
|
|
50
50
|
* Текущий статус узла
|
|
51
51
|
* Computed из _status для предоставления readonly интерфейса
|
|
52
52
|
*/
|
|
53
|
-
status =
|
|
53
|
+
status = u(() => this._status.value);
|
|
54
54
|
/**
|
|
55
55
|
* Узел отключен (disabled)
|
|
56
56
|
*/
|
|
57
|
-
disabled =
|
|
57
|
+
disabled = u(() => this._status.value === "disabled");
|
|
58
58
|
/**
|
|
59
59
|
* Узел включен (enabled)
|
|
60
60
|
*/
|
|
61
|
-
enabled =
|
|
61
|
+
enabled = u(() => this._status.value !== "disabled");
|
|
62
62
|
/**
|
|
63
63
|
* Получить ошибки валидации с фильтрацией
|
|
64
64
|
*
|
|
@@ -283,7 +283,7 @@ class A {
|
|
|
283
283
|
onEnable() {
|
|
284
284
|
}
|
|
285
285
|
}
|
|
286
|
-
class
|
|
286
|
+
class P {
|
|
287
287
|
/**
|
|
288
288
|
* Хранилище подписок
|
|
289
289
|
* Ключ: уникальный идентификатор подписки
|
|
@@ -451,8 +451,8 @@ class _ {
|
|
|
451
451
|
this.clear();
|
|
452
452
|
}
|
|
453
453
|
}
|
|
454
|
-
var
|
|
455
|
-
class
|
|
454
|
+
var w = /* @__PURE__ */ ((r) => (r.THROW = "throw", r.LOG = "log", r.CONVERT = "convert", r))(w || {});
|
|
455
|
+
class F {
|
|
456
456
|
/**
|
|
457
457
|
* Обработать ошибку согласно заданной стратегии
|
|
458
458
|
*
|
|
@@ -584,7 +584,7 @@ class E {
|
|
|
584
584
|
return typeof e == "object" && e !== null && "code" in e && "message" in e && typeof e.code == "string" && typeof e.message == "string";
|
|
585
585
|
}
|
|
586
586
|
}
|
|
587
|
-
class
|
|
587
|
+
class J extends O {
|
|
588
588
|
// ============================================================================
|
|
589
589
|
// Приватные сигналы
|
|
590
590
|
// ============================================================================
|
|
@@ -625,13 +625,13 @@ class I extends A {
|
|
|
625
625
|
* Менеджер подписок для централизованного cleanup
|
|
626
626
|
* Использует SubscriptionManager вместо массива для управления подписками
|
|
627
627
|
*/
|
|
628
|
-
disposers = new
|
|
628
|
+
disposers = new P();
|
|
629
629
|
component;
|
|
630
630
|
// ============================================================================
|
|
631
631
|
// Конструктор
|
|
632
632
|
// ============================================================================
|
|
633
633
|
constructor(e) {
|
|
634
|
-
super(), this.initialValue = e.value, this.validators = e.validators || [], this.asyncValidators = e.asyncValidators || [], this.updateOn = e.updateOn || "blur", this.debounceMs = e.debounce || 0, this.component = e.component, this._value =
|
|
634
|
+
super(), this.initialValue = e.value, this.validators = e.validators || [], this.asyncValidators = e.asyncValidators || [], this.updateOn = e.updateOn || "blur", this.debounceMs = e.debounce || 0, this.component = e.component, this._value = y(e.value), this._errors = y([]), this._pending = y(!1), this._componentProps = y(e.componentProps || {}), e.disabled && (this._status.value = "disabled"), this.value = u(() => this._value.value), this.valid = u(() => this._status.value === "valid"), this.invalid = u(() => this._status.value === "invalid"), this.pending = u(() => this._pending.value), this.errors = u(() => this._errors.value), this.componentProps = u(() => this._componentProps.value), this.shouldShowError = u(
|
|
635
635
|
() => this._status.value === "invalid" && (this._touched.value || this._dirty.value)
|
|
636
636
|
);
|
|
637
637
|
}
|
|
@@ -766,14 +766,14 @@ class I extends A {
|
|
|
766
766
|
return !1;
|
|
767
767
|
this._pending.value = !0, this._status.value = "pending";
|
|
768
768
|
const s = await Promise.all(
|
|
769
|
-
this.asyncValidators.map(async (
|
|
769
|
+
this.asyncValidators.map(async (o) => {
|
|
770
770
|
try {
|
|
771
|
-
return await
|
|
772
|
-
} catch (
|
|
773
|
-
return
|
|
774
|
-
|
|
771
|
+
return await o(this._value.value);
|
|
772
|
+
} catch (n) {
|
|
773
|
+
return F.handle(
|
|
774
|
+
n,
|
|
775
775
|
"FieldNode AsyncValidator",
|
|
776
|
-
|
|
776
|
+
w.CONVERT
|
|
777
777
|
);
|
|
778
778
|
}
|
|
779
779
|
})
|
|
@@ -896,7 +896,7 @@ class I extends A {
|
|
|
896
896
|
* ```
|
|
897
897
|
*/
|
|
898
898
|
watch(e) {
|
|
899
|
-
const t =
|
|
899
|
+
const t = E(() => {
|
|
900
900
|
const s = this.value.value;
|
|
901
901
|
e(s);
|
|
902
902
|
}), i = `watch-${Date.now()}-${Math.random()}`;
|
|
@@ -925,9 +925,9 @@ class I extends A {
|
|
|
925
925
|
* ```
|
|
926
926
|
*/
|
|
927
927
|
computeFrom(e, t) {
|
|
928
|
-
const i =
|
|
929
|
-
const a = e.map((
|
|
930
|
-
this.setValue(
|
|
928
|
+
const i = E(() => {
|
|
929
|
+
const a = e.map((n) => n.value), o = t(...a);
|
|
930
|
+
this.setValue(o, { emitEvent: !1 });
|
|
931
931
|
}), s = `computeFrom-${Date.now()}-${Math.random()}`;
|
|
932
932
|
return this.disposers.add(s, i);
|
|
933
933
|
}
|
|
@@ -948,7 +948,7 @@ class I extends A {
|
|
|
948
948
|
this.disposers.dispose(), this.validateDebounceTimer && (clearTimeout(this.validateDebounceTimer), this.validateDebounceTimer = void 0);
|
|
949
949
|
}
|
|
950
950
|
}
|
|
951
|
-
class
|
|
951
|
+
class Y {
|
|
952
952
|
form;
|
|
953
953
|
constructor(e) {
|
|
954
954
|
this.form = e;
|
|
@@ -1006,25 +1006,31 @@ class N {
|
|
|
1006
1006
|
console.warn(`Field ${t} not found in GroupNode`);
|
|
1007
1007
|
continue;
|
|
1008
1008
|
}
|
|
1009
|
-
if (!R(s)) {
|
|
1010
|
-
process.env.NODE_ENV !== "production" && console.warn(`Validation can only run on FieldNode, skipping ${t}`);
|
|
1009
|
+
if (!T(s) && !R(s)) {
|
|
1010
|
+
process.env.NODE_ENV !== "production" && console.warn(`Validation can only run on FieldNode or ArrayNode, skipping ${t}`);
|
|
1011
1011
|
continue;
|
|
1012
1012
|
}
|
|
1013
|
-
const a = []
|
|
1014
|
-
|
|
1015
|
-
|
|
1013
|
+
const a = [];
|
|
1014
|
+
let o;
|
|
1015
|
+
if (R(s)) {
|
|
1016
|
+
const n = s.getValue();
|
|
1017
|
+
o = new j(this.form, t, n);
|
|
1018
|
+
} else
|
|
1019
|
+
o = new q(this.form, t, s);
|
|
1020
|
+
for (const n of i)
|
|
1021
|
+
if (!(n.condition && !this.checkCondition(n.condition)))
|
|
1016
1022
|
try {
|
|
1017
|
-
let
|
|
1018
|
-
const
|
|
1019
|
-
|
|
1020
|
-
} catch (
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
+
let l = null;
|
|
1024
|
+
const d = o.value(), m = n.validator;
|
|
1025
|
+
n.type === "sync" ? l = m(d, o) : n.type === "async" && (l = await m(d, o)), l && a.push(l);
|
|
1026
|
+
} catch (l) {
|
|
1027
|
+
F.handle(
|
|
1028
|
+
l,
|
|
1023
1029
|
`ValidationApplicator: validator for ${t}`,
|
|
1024
|
-
|
|
1030
|
+
w.LOG
|
|
1025
1031
|
);
|
|
1026
1032
|
}
|
|
1027
|
-
a.length > 0 ? s.setErrors(a) : s.errors.value.length > 0 && !s.errors.value.some((
|
|
1033
|
+
a.length > 0 ? s.setErrors(a) : s.errors.value.length > 0 && !s.errors.value.some((n) => n.code !== "contextual") && s.clearErrors();
|
|
1028
1034
|
}
|
|
1029
1035
|
}
|
|
1030
1036
|
/**
|
|
@@ -1037,7 +1043,7 @@ class N {
|
|
|
1037
1043
|
*/
|
|
1038
1044
|
applyTreeValidators(e) {
|
|
1039
1045
|
for (const t of e) {
|
|
1040
|
-
const i = new
|
|
1046
|
+
const i = new K(this.form);
|
|
1041
1047
|
if (!(t.condition && !this.checkCondition(t.condition)))
|
|
1042
1048
|
try {
|
|
1043
1049
|
if (t.type !== "tree")
|
|
@@ -1046,15 +1052,15 @@ class N {
|
|
|
1046
1052
|
if (s && t.options && "targetField" in t.options) {
|
|
1047
1053
|
const a = t.options.targetField;
|
|
1048
1054
|
if (a) {
|
|
1049
|
-
const
|
|
1050
|
-
if (
|
|
1051
|
-
const
|
|
1052
|
-
|
|
1055
|
+
const o = this.form.getFieldByPath(String(a));
|
|
1056
|
+
if (o && T(o)) {
|
|
1057
|
+
const n = o.errors.value;
|
|
1058
|
+
o.setErrors([...n, s]);
|
|
1053
1059
|
}
|
|
1054
1060
|
}
|
|
1055
1061
|
}
|
|
1056
1062
|
} catch (s) {
|
|
1057
|
-
|
|
1063
|
+
F.handle(s, "ValidationApplicator: tree validator", w.LOG);
|
|
1058
1064
|
}
|
|
1059
1065
|
}
|
|
1060
1066
|
}
|
|
@@ -1075,57 +1081,7 @@ class N {
|
|
|
1075
1081
|
return e.conditionFn(i);
|
|
1076
1082
|
}
|
|
1077
1083
|
}
|
|
1078
|
-
class
|
|
1079
|
-
form;
|
|
1080
|
-
behaviorRegistry;
|
|
1081
|
-
constructor(e, t) {
|
|
1082
|
-
this.form = e, this.behaviorRegistry = t;
|
|
1083
|
-
}
|
|
1084
|
-
/**
|
|
1085
|
-
* Применить behavior схему к форме
|
|
1086
|
-
*
|
|
1087
|
-
* Этапы:
|
|
1088
|
-
* 1. Начать регистрацию (beginRegistration)
|
|
1089
|
-
* 2. Выполнить схему (регистрация behaviors)
|
|
1090
|
-
* 3. Завершить регистрацию (endRegistration) - применить behaviors
|
|
1091
|
-
* 4. Вернуть функцию cleanup для отписки
|
|
1092
|
-
*
|
|
1093
|
-
* @param schemaFn Функция-схема behavior
|
|
1094
|
-
* @returns Функция отписки от всех behaviors
|
|
1095
|
-
*
|
|
1096
|
-
* @example
|
|
1097
|
-
* ```typescript
|
|
1098
|
-
* const cleanup = behaviorApplicator.apply((path) => {
|
|
1099
|
-
* copyFrom(path.residenceAddress, path.registrationAddress, {
|
|
1100
|
-
* when: (form) => form.sameAsRegistration === true
|
|
1101
|
-
* });
|
|
1102
|
-
*
|
|
1103
|
-
* enableWhen(path.propertyValue, (form) => form.loanType === 'mortgage');
|
|
1104
|
-
*
|
|
1105
|
-
* computeFrom(
|
|
1106
|
-
* path.initialPayment,
|
|
1107
|
-
* [path.propertyValue],
|
|
1108
|
-
* (propertyValue) => propertyValue ? propertyValue * 0.2 : null
|
|
1109
|
-
* );
|
|
1110
|
-
* });
|
|
1111
|
-
*
|
|
1112
|
-
* // Cleanup при unmount
|
|
1113
|
-
* useEffect(() => cleanup, []);
|
|
1114
|
-
* ```
|
|
1115
|
-
*/
|
|
1116
|
-
apply(e) {
|
|
1117
|
-
this.behaviorRegistry.beginRegistration();
|
|
1118
|
-
try {
|
|
1119
|
-
const t = S();
|
|
1120
|
-
e(t);
|
|
1121
|
-
const i = this.form.getProxy();
|
|
1122
|
-
return this.behaviorRegistry.endRegistration(i).cleanup;
|
|
1123
|
-
} catch (t) {
|
|
1124
|
-
throw E.handle(t, "BehaviorApplicator", g.THROW), t;
|
|
1125
|
-
}
|
|
1126
|
-
}
|
|
1127
|
-
}
|
|
1128
|
-
class O {
|
|
1084
|
+
class Q {
|
|
1129
1085
|
/**
|
|
1130
1086
|
* Парсит путь в массив сегментов
|
|
1131
1087
|
*
|
|
@@ -1154,8 +1110,8 @@ class O {
|
|
|
1154
1110
|
const t = [];
|
|
1155
1111
|
let i = "", s = !1;
|
|
1156
1112
|
for (let a = 0; a < e.length; a++) {
|
|
1157
|
-
const
|
|
1158
|
-
|
|
1113
|
+
const o = e[a];
|
|
1114
|
+
o === "[" ? (s = !0, i += o) : o === "]" ? (s = !1, i += o) : o === "." && !s ? i && (this.addSegment(t, i), i = "") : i += o;
|
|
1159
1115
|
}
|
|
1160
1116
|
return i && this.addSegment(t, i), t;
|
|
1161
1117
|
}
|
|
@@ -1245,26 +1201,26 @@ class O {
|
|
|
1245
1201
|
if (s.length === 0)
|
|
1246
1202
|
throw new Error("Cannot set value: empty path");
|
|
1247
1203
|
let a = e;
|
|
1248
|
-
for (let
|
|
1249
|
-
const
|
|
1250
|
-
let
|
|
1251
|
-
if (
|
|
1252
|
-
if (!Array.isArray(
|
|
1253
|
-
throw new Error(`Expected array at path segment: ${
|
|
1254
|
-
a =
|
|
1204
|
+
for (let n = 0; n < s.length - 1; n++) {
|
|
1205
|
+
const l = s[n];
|
|
1206
|
+
let d = a[l.key];
|
|
1207
|
+
if (l.index !== void 0) {
|
|
1208
|
+
if (!Array.isArray(d))
|
|
1209
|
+
throw new Error(`Expected array at path segment: ${l.key}, but got ${typeof d}`);
|
|
1210
|
+
a = d[l.index];
|
|
1255
1211
|
} else
|
|
1256
|
-
|
|
1212
|
+
d == null && (a[l.key] = {}, d = a[l.key]), a = d;
|
|
1257
1213
|
}
|
|
1258
|
-
const
|
|
1259
|
-
if (
|
|
1260
|
-
const
|
|
1261
|
-
if (!Array.isArray(
|
|
1214
|
+
const o = s[s.length - 1];
|
|
1215
|
+
if (o.index !== void 0) {
|
|
1216
|
+
const n = a[o.key];
|
|
1217
|
+
if (!Array.isArray(n))
|
|
1262
1218
|
throw new Error(
|
|
1263
|
-
`Expected array at path segment: ${
|
|
1219
|
+
`Expected array at path segment: ${o.key}, but got ${typeof n}`
|
|
1264
1220
|
);
|
|
1265
|
-
o
|
|
1221
|
+
n[o.index] = i;
|
|
1266
1222
|
} else
|
|
1267
|
-
a[
|
|
1223
|
+
a[o.key] = i;
|
|
1268
1224
|
}
|
|
1269
1225
|
/**
|
|
1270
1226
|
* Получить значение из FormNode по пути
|
|
@@ -1365,24 +1321,24 @@ class O {
|
|
|
1365
1321
|
let s = e;
|
|
1366
1322
|
for (const a of i) {
|
|
1367
1323
|
if (s == null) return null;
|
|
1368
|
-
const
|
|
1369
|
-
if (
|
|
1370
|
-
if (s =
|
|
1324
|
+
const o = s;
|
|
1325
|
+
if (o.fields && o.fields instanceof Map) {
|
|
1326
|
+
if (s = o.fields.get(a.key), a.index === void 0) {
|
|
1371
1327
|
if (s == null) return null;
|
|
1372
1328
|
continue;
|
|
1373
1329
|
}
|
|
1374
|
-
} else if (a.index !== void 0 &&
|
|
1375
|
-
const
|
|
1376
|
-
if (!Array.isArray(
|
|
1330
|
+
} else if (a.index !== void 0 && o.items) {
|
|
1331
|
+
const n = o.items.value || o.items;
|
|
1332
|
+
if (!Array.isArray(n) || (s = n[a.index], s == null)) return null;
|
|
1377
1333
|
continue;
|
|
1378
1334
|
} else if (a.index === void 0) {
|
|
1379
|
-
if (s =
|
|
1335
|
+
if (s = o[a.key], s == null) return null;
|
|
1380
1336
|
continue;
|
|
1381
1337
|
}
|
|
1382
1338
|
if (s && a.index !== void 0 && s.items) {
|
|
1383
|
-
const
|
|
1384
|
-
if (!Array.isArray(
|
|
1385
|
-
s =
|
|
1339
|
+
const n = s.items.value || s.items;
|
|
1340
|
+
if (!Array.isArray(n)) return null;
|
|
1341
|
+
s = n[a.index];
|
|
1386
1342
|
} else if (s && a.index !== void 0 && !s.items)
|
|
1387
1343
|
return null;
|
|
1388
1344
|
if (s == null) return null;
|
|
@@ -1390,531 +1346,55 @@ class O {
|
|
|
1390
1346
|
return s;
|
|
1391
1347
|
}
|
|
1392
1348
|
}
|
|
1393
|
-
class
|
|
1394
|
-
/**
|
|
1395
|
-
* Внутреннее хранилище полей
|
|
1396
|
-
* Map обеспечивает быструю lookup производительность O(1)
|
|
1397
|
-
*/
|
|
1398
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1399
|
-
fields = /* @__PURE__ */ new Map();
|
|
1400
|
-
/**
|
|
1401
|
-
* Установить поле в реестр
|
|
1402
|
-
*
|
|
1403
|
-
* @param key - Ключ поля (имя свойства в типе T)
|
|
1404
|
-
* @param node - FormNode для этого поля
|
|
1405
|
-
*
|
|
1406
|
-
* @example
|
|
1407
|
-
* ```typescript
|
|
1408
|
-
* registry.set('email', new FieldNode({ value: '' }));
|
|
1409
|
-
* ```
|
|
1410
|
-
*/
|
|
1411
|
-
set(e, t) {
|
|
1412
|
-
this.fields.set(e, t);
|
|
1413
|
-
}
|
|
1414
|
-
/**
|
|
1415
|
-
* Получить поле из реестра
|
|
1416
|
-
*
|
|
1417
|
-
* @param key - Ключ поля
|
|
1418
|
-
* @returns FormNode или undefined, если поле не найдено
|
|
1419
|
-
*
|
|
1420
|
-
* @example
|
|
1421
|
-
* ```typescript
|
|
1422
|
-
* const emailField = registry.get('email');
|
|
1423
|
-
* if (emailField) {
|
|
1424
|
-
* console.log(emailField.value.value);
|
|
1425
|
-
* }
|
|
1426
|
-
* ```
|
|
1427
|
-
*/
|
|
1428
|
-
get(e) {
|
|
1429
|
-
return this.fields.get(e);
|
|
1430
|
-
}
|
|
1431
|
-
/**
|
|
1432
|
-
* Проверить наличие поля в реестре
|
|
1433
|
-
*
|
|
1434
|
-
* @param key - Ключ поля
|
|
1435
|
-
* @returns true если поле существует
|
|
1436
|
-
*
|
|
1437
|
-
* @example
|
|
1438
|
-
* ```typescript
|
|
1439
|
-
* if (registry.has('email')) {
|
|
1440
|
-
* console.log('Email field exists');
|
|
1441
|
-
* }
|
|
1442
|
-
* ```
|
|
1443
|
-
*/
|
|
1444
|
-
has(e) {
|
|
1445
|
-
return this.fields.has(e);
|
|
1446
|
-
}
|
|
1447
|
-
/**
|
|
1448
|
-
* Удалить поле из реестра
|
|
1449
|
-
*
|
|
1450
|
-
* @param key - Ключ поля
|
|
1451
|
-
* @returns true если поле было удалено, false если поля не было
|
|
1452
|
-
*
|
|
1453
|
-
* @example
|
|
1454
|
-
* ```typescript
|
|
1455
|
-
* registry.delete('email');
|
|
1456
|
-
* ```
|
|
1457
|
-
*/
|
|
1458
|
-
delete(e) {
|
|
1459
|
-
return this.fields.delete(e);
|
|
1460
|
-
}
|
|
1461
|
-
/**
|
|
1462
|
-
* Перебрать все поля
|
|
1463
|
-
*
|
|
1464
|
-
* @param callback - Функция обратного вызова для каждого поля
|
|
1465
|
-
*
|
|
1466
|
-
* @example
|
|
1467
|
-
* ```typescript
|
|
1468
|
-
* registry.forEach((field, key) => {
|
|
1469
|
-
* console.log(`${key}: ${field.value.value}`);
|
|
1470
|
-
* });
|
|
1471
|
-
* ```
|
|
1472
|
-
*/
|
|
1473
|
-
forEach(e) {
|
|
1474
|
-
this.fields.forEach(e);
|
|
1475
|
-
}
|
|
1476
|
-
/**
|
|
1477
|
-
* Получить итератор значений (полей)
|
|
1478
|
-
*
|
|
1479
|
-
* @returns Итератор по всем полям
|
|
1480
|
-
*
|
|
1481
|
-
* @example
|
|
1482
|
-
* ```typescript
|
|
1483
|
-
* for (const field of registry.values()) {
|
|
1484
|
-
* await field.validate();
|
|
1485
|
-
* }
|
|
1486
|
-
* ```
|
|
1487
|
-
*/
|
|
1488
|
-
values() {
|
|
1489
|
-
return this.fields.values();
|
|
1490
|
-
}
|
|
1491
|
-
/**
|
|
1492
|
-
* Получить итератор пар [ключ, значение]
|
|
1493
|
-
*
|
|
1494
|
-
* @returns Итератор по всем записям
|
|
1495
|
-
*
|
|
1496
|
-
* @example
|
|
1497
|
-
* ```typescript
|
|
1498
|
-
* for (const [key, field] of registry.entries()) {
|
|
1499
|
-
* console.log(key, field.value.value);
|
|
1500
|
-
* }
|
|
1501
|
-
* ```
|
|
1502
|
-
*/
|
|
1503
|
-
entries() {
|
|
1504
|
-
return this.fields.entries();
|
|
1505
|
-
}
|
|
1506
|
-
/**
|
|
1507
|
-
* Получить итератор ключей полей
|
|
1508
|
-
*
|
|
1509
|
-
* @returns Итератор по всем ключам
|
|
1510
|
-
*
|
|
1511
|
-
* @example
|
|
1512
|
-
* ```typescript
|
|
1513
|
-
* const fieldNames = Array.from(registry.keys());
|
|
1514
|
-
* // ['email', 'name', 'age']
|
|
1515
|
-
* ```
|
|
1516
|
-
*/
|
|
1517
|
-
keys() {
|
|
1518
|
-
return this.fields.keys();
|
|
1519
|
-
}
|
|
1520
|
-
/**
|
|
1521
|
-
* Получить количество полей
|
|
1522
|
-
*
|
|
1523
|
-
* @returns Количество зарегистрированных полей
|
|
1524
|
-
*
|
|
1525
|
-
* @example
|
|
1526
|
-
* ```typescript
|
|
1527
|
-
* console.log(`Form has ${registry.size()} fields`);
|
|
1528
|
-
* ```
|
|
1529
|
-
*/
|
|
1530
|
-
size() {
|
|
1531
|
-
return this.fields.size;
|
|
1532
|
-
}
|
|
1533
|
-
/**
|
|
1534
|
-
* Очистить все поля
|
|
1535
|
-
*
|
|
1536
|
-
* Удаляет все поля из реестра
|
|
1537
|
-
*
|
|
1538
|
-
* @example
|
|
1539
|
-
* ```typescript
|
|
1540
|
-
* registry.clear();
|
|
1541
|
-
* console.log(registry.size()); // 0
|
|
1542
|
-
* ```
|
|
1543
|
-
*/
|
|
1544
|
-
clear() {
|
|
1545
|
-
this.fields.clear();
|
|
1546
|
-
}
|
|
1547
|
-
/**
|
|
1548
|
-
* Получить все поля как массив
|
|
1549
|
-
*
|
|
1550
|
-
* Полезно для операций, требующих работу с массивом
|
|
1551
|
-
*
|
|
1552
|
-
* @returns Массив всех полей
|
|
1553
|
-
*
|
|
1554
|
-
* @example
|
|
1555
|
-
* ```typescript
|
|
1556
|
-
* const allValid = registry.toArray().every(field => field.valid.value);
|
|
1557
|
-
* ```
|
|
1558
|
-
*/
|
|
1559
|
-
toArray() {
|
|
1560
|
-
return Array.from(this.fields.values());
|
|
1561
|
-
}
|
|
1562
|
-
/**
|
|
1563
|
-
* Получить Map-представление реестра (readonly)
|
|
1564
|
-
*
|
|
1565
|
-
* Используйте для совместимости с существующим кодом
|
|
1566
|
-
*
|
|
1567
|
-
* @returns ReadonlyMap с полями
|
|
1568
|
-
* @internal
|
|
1569
|
-
*
|
|
1570
|
-
* @example
|
|
1571
|
-
* ```typescript
|
|
1572
|
-
* const mapView = registry.asMap();
|
|
1573
|
-
* ```
|
|
1574
|
-
*/
|
|
1575
|
-
asMap() {
|
|
1576
|
-
return this.fields;
|
|
1577
|
-
}
|
|
1578
|
-
}
|
|
1579
|
-
class G {
|
|
1580
|
-
/**
|
|
1581
|
-
* @param fieldRegistry - Реестр полей для доступа к коллекции
|
|
1582
|
-
*/
|
|
1583
|
-
constructor(e) {
|
|
1584
|
-
this.fieldRegistry = e;
|
|
1585
|
-
}
|
|
1586
|
-
/**
|
|
1587
|
-
* Создать Proxy для GroupNode
|
|
1588
|
-
*
|
|
1589
|
-
* Proxy позволяет обращаться к полям формы напрямую:
|
|
1590
|
-
* - form.email вместо form.fields.get('email')
|
|
1591
|
-
* - form.address.city вместо form.fields.get('address').fields.get('city')
|
|
1592
|
-
*
|
|
1593
|
-
* @param target - GroupNode для которого создается Proxy
|
|
1594
|
-
* @returns Proxy с типобезопасным доступом к полям
|
|
1595
|
-
*
|
|
1596
|
-
* @example
|
|
1597
|
-
* ```typescript
|
|
1598
|
-
* const proxy = proxyBuilder.build(groupNode);
|
|
1599
|
-
*
|
|
1600
|
-
* // Доступ к полям
|
|
1601
|
-
* console.log(proxy.email.value); // Работает!
|
|
1602
|
-
* console.log(proxy.name.value); // Работает!
|
|
1603
|
-
*
|
|
1604
|
-
* // Доступ к методам GroupNode
|
|
1605
|
-
* await proxy.validate(); // Работает!
|
|
1606
|
-
* proxy.markAsTouched(); // Работает!
|
|
1607
|
-
*
|
|
1608
|
-
* // Проверка существования
|
|
1609
|
-
* if ('email' in proxy) { ... }
|
|
1610
|
-
*
|
|
1611
|
-
* // Перечисление ключей
|
|
1612
|
-
* Object.keys(proxy); // ['email', 'name', ...]
|
|
1613
|
-
* ```
|
|
1614
|
-
*/
|
|
1615
|
-
build(e) {
|
|
1616
|
-
return new Proxy(e, {
|
|
1617
|
-
/**
|
|
1618
|
-
* Get trap: Перехват доступа к свойствам
|
|
1619
|
-
*
|
|
1620
|
-
* Приоритет:
|
|
1621
|
-
* 1. Собственные свойства и методы GroupNode (validate, setValue и т.д.)
|
|
1622
|
-
* 2. Поля формы из fieldRegistry
|
|
1623
|
-
* 3. undefined для несуществующих свойств
|
|
1624
|
-
*/
|
|
1625
|
-
get: (t, i) => {
|
|
1626
|
-
if (i in t)
|
|
1627
|
-
return t[i];
|
|
1628
|
-
if (typeof i == "string" && this.fieldRegistry.has(i))
|
|
1629
|
-
return this.fieldRegistry.get(i);
|
|
1630
|
-
},
|
|
1631
|
-
/**
|
|
1632
|
-
* Set trap: Перехват установки свойств
|
|
1633
|
-
*
|
|
1634
|
-
* Запрещает прямую установку значений полей через form.email = value
|
|
1635
|
-
* Пользователь должен использовать form.email.setValue(value) или form.setValue({...})
|
|
1636
|
-
*/
|
|
1637
|
-
set: (t, i, s) => typeof i == "string" && this.fieldRegistry.has(i) ? !1 : (t[i] = s, !0),
|
|
1638
|
-
/**
|
|
1639
|
-
* Has trap: Перехват оператора 'in'
|
|
1640
|
-
*
|
|
1641
|
-
* Позволяет проверять существование полей:
|
|
1642
|
-
* if ('email' in form) { ... }
|
|
1643
|
-
*/
|
|
1644
|
-
has: (t, i) => typeof i == "string" && this.fieldRegistry.has(i) ? !0 : i in t,
|
|
1645
|
-
/**
|
|
1646
|
-
* OwnKeys trap: Перехват Object.keys() / Object.getOwnPropertyNames()
|
|
1647
|
-
*
|
|
1648
|
-
* Возвращает объединенный список:
|
|
1649
|
-
* - Ключей самого GroupNode
|
|
1650
|
-
* - Ключей полей из fieldRegistry
|
|
1651
|
-
*/
|
|
1652
|
-
ownKeys: (t) => {
|
|
1653
|
-
const i = Reflect.ownKeys(t), s = Array.from(this.fieldRegistry.keys());
|
|
1654
|
-
return [.../* @__PURE__ */ new Set([...i, ...s])];
|
|
1655
|
-
},
|
|
1656
|
-
/**
|
|
1657
|
-
* GetOwnPropertyDescriptor trap: Перехват Object.getOwnPropertyDescriptor()
|
|
1658
|
-
*
|
|
1659
|
-
* Возвращает дескриптор свойства для полей и свойств GroupNode
|
|
1660
|
-
* Важно для корректной работы Object.keys() и других рефлексивных операций
|
|
1661
|
-
*/
|
|
1662
|
-
getOwnPropertyDescriptor: (t, i) => typeof i == "string" && this.fieldRegistry.has(i) ? {
|
|
1663
|
-
enumerable: !0,
|
|
1664
|
-
// Поле должно быть перечисляемым
|
|
1665
|
-
configurable: !0
|
|
1666
|
-
// Поле может быть удалено
|
|
1667
|
-
// Не указываем writable, т.к. это accessor property через get/set traps
|
|
1668
|
-
} : Reflect.getOwnPropertyDescriptor(t, i)
|
|
1669
|
-
});
|
|
1670
|
-
}
|
|
1671
|
-
}
|
|
1672
|
-
class U {
|
|
1673
|
-
// ============================================================================
|
|
1674
|
-
// Конструктор
|
|
1675
|
-
// ============================================================================
|
|
1676
|
-
/**
|
|
1677
|
-
* Создать менеджер состояния
|
|
1678
|
-
*
|
|
1679
|
-
* @param fieldRegistry - реестр полей формы
|
|
1680
|
-
*/
|
|
1681
|
-
constructor(e) {
|
|
1682
|
-
this.fieldRegistry = e, this._submitting = d(!1), this._disabled = d(!1), this._formErrors = d([]), this.value = l(() => {
|
|
1683
|
-
const t = {};
|
|
1684
|
-
return this.fieldRegistry.forEach((i, s) => {
|
|
1685
|
-
t[s] = i.value.value;
|
|
1686
|
-
}), t;
|
|
1687
|
-
}), this.valid = l(() => this._formErrors.value.length > 0 ? !1 : Array.from(this.fieldRegistry.values()).every((i) => i.valid.value)), this.invalid = l(() => !this.valid.value), this.pending = l(
|
|
1688
|
-
() => Array.from(this.fieldRegistry.values()).some((t) => t.pending.value)
|
|
1689
|
-
), this.touched = l(
|
|
1690
|
-
() => Array.from(this.fieldRegistry.values()).some((t) => t.touched.value)
|
|
1691
|
-
), this.dirty = l(
|
|
1692
|
-
() => Array.from(this.fieldRegistry.values()).some((t) => t.dirty.value)
|
|
1693
|
-
), this.errors = l(() => {
|
|
1694
|
-
const t = [];
|
|
1695
|
-
return t.push(...this._formErrors.value), this.fieldRegistry.forEach((i) => {
|
|
1696
|
-
t.push(...i.errors.value);
|
|
1697
|
-
}), t;
|
|
1698
|
-
}), this.status = l(() => this._disabled.value ? "disabled" : this.pending.value ? "pending" : this.invalid.value ? "invalid" : "valid"), this.submitting = l(() => this._submitting.value);
|
|
1699
|
-
}
|
|
1700
|
-
// ============================================================================
|
|
1701
|
-
// Приватные сигналы (мутабельные)
|
|
1702
|
-
// ============================================================================
|
|
1703
|
-
/**
|
|
1704
|
-
* Флаг отправки формы
|
|
1705
|
-
* Устанавливается в true во время отправки формы на сервер
|
|
1706
|
-
*/
|
|
1707
|
-
_submitting;
|
|
1708
|
-
/**
|
|
1709
|
-
* Флаг disabled состояния
|
|
1710
|
-
* Если true, форма считается disabled
|
|
1711
|
-
*/
|
|
1712
|
-
_disabled;
|
|
1713
|
-
/**
|
|
1714
|
-
* Form-level validation errors (не связанные с конкретным полем)
|
|
1715
|
-
* Используется для server-side errors или кросс-полевой валидации
|
|
1716
|
-
*/
|
|
1717
|
-
_formErrors;
|
|
1718
|
-
// ============================================================================
|
|
1719
|
-
// Публичные computed signals (read-only)
|
|
1720
|
-
// ============================================================================
|
|
1721
|
-
/**
|
|
1722
|
-
* Значение формы как объект
|
|
1723
|
-
*
|
|
1724
|
-
* Computed signal, который автоматически пересчитывается при изменении любого поля.
|
|
1725
|
-
* Использует мемоизацию - если зависимости не изменились, вернет закешированный объект.
|
|
1726
|
-
*
|
|
1727
|
-
* @example
|
|
1728
|
-
* ```typescript
|
|
1729
|
-
* const form = new GroupNode({ email: { value: 'test@mail.com' } });
|
|
1730
|
-
* console.log(form.value.value); // { email: 'test@mail.com' }
|
|
1731
|
-
* ```
|
|
1732
|
-
*/
|
|
1733
|
-
value;
|
|
1734
|
-
/**
|
|
1735
|
-
* Форма валидна?
|
|
1736
|
-
*
|
|
1737
|
-
* Computed signal. Форма валидна, если:
|
|
1738
|
-
* - Нет form-level errors
|
|
1739
|
-
* - Все поля валидны
|
|
1740
|
-
*/
|
|
1741
|
-
valid;
|
|
1742
|
-
/**
|
|
1743
|
-
* Форма невалидна?
|
|
1744
|
-
*
|
|
1745
|
-
* Computed signal. Инверсия valid.
|
|
1746
|
-
*/
|
|
1747
|
-
invalid;
|
|
1748
|
-
/**
|
|
1749
|
-
* Хотя бы одно поле touched?
|
|
1750
|
-
*
|
|
1751
|
-
* Computed signal. Возвращает true, если хотя бы одно поле было touched.
|
|
1752
|
-
*/
|
|
1753
|
-
touched;
|
|
1754
|
-
/**
|
|
1755
|
-
* Хотя бы одно поле dirty?
|
|
1756
|
-
*
|
|
1757
|
-
* Computed signal. Возвращает true, если хотя бы одно поле изменилось.
|
|
1758
|
-
*/
|
|
1759
|
-
dirty;
|
|
1760
|
-
/**
|
|
1761
|
-
* Асинхронная валидация в процессе?
|
|
1762
|
-
*
|
|
1763
|
-
* Computed signal. Возвращает true, если хотя бы одно поле находится в pending состоянии.
|
|
1764
|
-
*/
|
|
1765
|
-
pending;
|
|
1766
|
-
/**
|
|
1767
|
-
* Все ошибки валидации
|
|
1768
|
-
*
|
|
1769
|
-
* Computed signal. Возвращает массив всех ошибок:
|
|
1770
|
-
* - Form-level errors
|
|
1771
|
-
* - Field-level errors (из всех вложенных полей)
|
|
1772
|
-
*/
|
|
1773
|
-
errors;
|
|
1774
|
-
/**
|
|
1775
|
-
* Общий статус формы
|
|
1776
|
-
*
|
|
1777
|
-
* Computed signal. Возможные значения:
|
|
1778
|
-
* - 'disabled' - форма disabled
|
|
1779
|
-
* - 'pending' - асинхронная валидация в процессе
|
|
1780
|
-
* - 'invalid' - форма невалидна
|
|
1781
|
-
* - 'valid' - форма валидна
|
|
1782
|
-
*/
|
|
1783
|
-
status;
|
|
1784
|
-
/**
|
|
1785
|
-
* Форма в процессе отправки?
|
|
1786
|
-
*
|
|
1787
|
-
* Computed signal (обертка над _submitting для read-only доступа).
|
|
1788
|
-
*/
|
|
1789
|
-
submitting;
|
|
1790
|
-
// ============================================================================
|
|
1791
|
-
// Публичные методы для управления состоянием
|
|
1792
|
-
// ============================================================================
|
|
1793
|
-
/**
|
|
1794
|
-
* Установить form-level ошибки
|
|
1795
|
-
*
|
|
1796
|
-
* @param errors - массив ошибок валидации
|
|
1797
|
-
*
|
|
1798
|
-
* @example
|
|
1799
|
-
* ```typescript
|
|
1800
|
-
* // Server-side ошибки
|
|
1801
|
-
* stateManager.setFormErrors([
|
|
1802
|
-
* { code: 'server_error', message: 'Пользователь с таким email уже существует' }
|
|
1803
|
-
* ]);
|
|
1804
|
-
* ```
|
|
1805
|
-
*/
|
|
1806
|
-
setFormErrors(e) {
|
|
1807
|
-
this._formErrors.value = e;
|
|
1808
|
-
}
|
|
1809
|
-
/**
|
|
1810
|
-
* Очистить form-level ошибки
|
|
1811
|
-
*/
|
|
1812
|
-
clearFormErrors() {
|
|
1813
|
-
this._formErrors.value = [];
|
|
1814
|
-
}
|
|
1815
|
-
/**
|
|
1816
|
-
* Получить form-level ошибки
|
|
1817
|
-
*/
|
|
1818
|
-
getFormErrors() {
|
|
1819
|
-
return this._formErrors.value;
|
|
1820
|
-
}
|
|
1821
|
-
/**
|
|
1822
|
-
* Установить флаг submitting
|
|
1823
|
-
*
|
|
1824
|
-
* @param value - true если форма отправляется, false если нет
|
|
1825
|
-
*
|
|
1826
|
-
* @example
|
|
1827
|
-
* ```typescript
|
|
1828
|
-
* stateManager.setSubmitting(true);
|
|
1829
|
-
* await api.submitForm(form.getValue());
|
|
1830
|
-
* stateManager.setSubmitting(false);
|
|
1831
|
-
* ```
|
|
1832
|
-
*/
|
|
1833
|
-
setSubmitting(e) {
|
|
1834
|
-
this._submitting.value = e;
|
|
1835
|
-
}
|
|
1836
|
-
/**
|
|
1837
|
-
* Установить флаг disabled
|
|
1838
|
-
*
|
|
1839
|
-
* @param value - true если форма disabled, false если нет
|
|
1840
|
-
*/
|
|
1841
|
-
setDisabled(e) {
|
|
1842
|
-
this._disabled.value = e;
|
|
1843
|
-
}
|
|
1844
|
-
/**
|
|
1845
|
-
* Получить флаг disabled
|
|
1846
|
-
*/
|
|
1847
|
-
isDisabled() {
|
|
1848
|
-
return this._disabled.value;
|
|
1849
|
-
}
|
|
1850
|
-
}
|
|
1851
|
-
class m extends A {
|
|
1349
|
+
class b extends O {
|
|
1852
1350
|
// ============================================================================
|
|
1853
1351
|
// Приватные поля
|
|
1854
1352
|
// ============================================================================
|
|
1855
|
-
id =
|
|
1856
|
-
/**
|
|
1857
|
-
* Реестр полей формы
|
|
1858
|
-
* Использует FieldRegistry для инкапсуляции логики управления коллекцией полей
|
|
1859
|
-
*/
|
|
1860
|
-
fieldRegistry;
|
|
1353
|
+
id = z();
|
|
1861
1354
|
/**
|
|
1862
|
-
*
|
|
1863
|
-
* Использует ProxyBuilder для создания Proxy с расширенной функциональностью
|
|
1355
|
+
* Коллекция полей формы (упрощённый Map вместо FieldRegistry)
|
|
1864
1356
|
*/
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
* Менеджер состояния формы
|
|
1868
|
-
* Инкапсулирует всю логику создания и управления сигналами состояния
|
|
1869
|
-
* Извлечен из GroupNode для соблюдения SRP
|
|
1870
|
-
*/
|
|
1871
|
-
stateManager;
|
|
1357
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1358
|
+
_fields = /* @__PURE__ */ new Map();
|
|
1872
1359
|
/**
|
|
1873
1360
|
* Менеджер подписок для централизованного cleanup
|
|
1874
|
-
* Использует SubscriptionManager вместо массива для управления подписками
|
|
1875
1361
|
*/
|
|
1876
|
-
disposers = new
|
|
1362
|
+
disposers = new P();
|
|
1877
1363
|
/**
|
|
1878
1364
|
* Ссылка на Proxy-инстанс для использования в BehaviorContext
|
|
1879
|
-
* Устанавливается в конструкторе до применения behavior schema
|
|
1880
1365
|
*/
|
|
1881
1366
|
_proxyInstance;
|
|
1882
1367
|
/**
|
|
1883
1368
|
* Навигатор для работы с путями к полям
|
|
1884
|
-
* Использует композицию вместо дублирования логики парсинга путей
|
|
1885
1369
|
*/
|
|
1886
|
-
pathNavigator = new
|
|
1370
|
+
pathNavigator = new Q();
|
|
1887
1371
|
/**
|
|
1888
1372
|
* Фабрика для создания узлов формы
|
|
1889
|
-
* Использует композицию для централизованного создания FieldNode/GroupNode/ArrayNode
|
|
1890
1373
|
*/
|
|
1891
|
-
nodeFactory = new
|
|
1374
|
+
nodeFactory = new X();
|
|
1892
1375
|
/**
|
|
1893
1376
|
* Реестр валидаторов для этой формы
|
|
1894
|
-
* Использует композицию вместо глобального Singleton
|
|
1895
|
-
* Обеспечивает полную изоляцию форм друг от друга
|
|
1896
1377
|
*/
|
|
1897
|
-
validationRegistry = new
|
|
1378
|
+
validationRegistry = new H();
|
|
1898
1379
|
/**
|
|
1899
1380
|
* Реестр behaviors для этой формы
|
|
1900
|
-
* Использует композицию вместо глобального Singleton
|
|
1901
|
-
* Обеспечивает полную изоляцию форм друг от друга
|
|
1902
1381
|
*/
|
|
1903
|
-
behaviorRegistry = new
|
|
1382
|
+
behaviorRegistry = new W();
|
|
1904
1383
|
/**
|
|
1905
1384
|
* Аппликатор для применения валидаторов к форме
|
|
1906
|
-
* Извлечен из GroupNode для соблюдения SRP
|
|
1907
|
-
* Использует композицию для управления процессом валидации
|
|
1908
|
-
*/
|
|
1909
|
-
validationApplicator = new N(this);
|
|
1910
|
-
/**
|
|
1911
|
-
* Аппликатор для применения behavior схемы к форме
|
|
1912
|
-
* Извлечен из GroupNode для соблюдения SRP
|
|
1913
|
-
* Использует композицию для управления процессом применения behaviors
|
|
1914
1385
|
*/
|
|
1915
|
-
|
|
1386
|
+
validationApplicator = new Y(this);
|
|
1387
|
+
// ============================================================================
|
|
1388
|
+
// Приватные сигналы состояния (inline из StateManager)
|
|
1916
1389
|
// ============================================================================
|
|
1917
|
-
|
|
1390
|
+
/** Флаг отправки формы */
|
|
1391
|
+
_submitting = y(!1);
|
|
1392
|
+
/** Флаг disabled состояния */
|
|
1393
|
+
_disabled = y(!1);
|
|
1394
|
+
/** Form-level validation errors */
|
|
1395
|
+
_formErrors = y([]);
|
|
1396
|
+
// ============================================================================
|
|
1397
|
+
// Публичные computed signals
|
|
1918
1398
|
// ============================================================================
|
|
1919
1399
|
value;
|
|
1920
1400
|
valid;
|
|
@@ -1926,36 +1406,78 @@ class m extends A {
|
|
|
1926
1406
|
status;
|
|
1927
1407
|
submitting;
|
|
1928
1408
|
constructor(e) {
|
|
1929
|
-
super()
|
|
1409
|
+
super();
|
|
1930
1410
|
const t = "form" in e, i = t ? e.form : e, s = t ? e.behavior : void 0, a = t ? e.validation : void 0;
|
|
1931
|
-
for (const [
|
|
1932
|
-
const
|
|
1933
|
-
this.
|
|
1411
|
+
for (const [n, l] of Object.entries(i)) {
|
|
1412
|
+
const d = this.createNode(l);
|
|
1413
|
+
this._fields.set(n, d);
|
|
1934
1414
|
}
|
|
1935
|
-
this.
|
|
1936
|
-
|
|
1937
|
-
|
|
1415
|
+
this.value = u(() => {
|
|
1416
|
+
const n = {};
|
|
1417
|
+
return this._fields.forEach((l, d) => {
|
|
1418
|
+
n[d] = l.value.value;
|
|
1419
|
+
}), n;
|
|
1420
|
+
}), this.valid = u(() => this._formErrors.value.length > 0 ? !1 : Array.from(this._fields.values()).every((n) => n.valid.value)), this.invalid = u(() => !this.valid.value), this.pending = u(
|
|
1421
|
+
() => Array.from(this._fields.values()).some((n) => n.pending.value)
|
|
1422
|
+
), this.touched = u(
|
|
1423
|
+
() => Array.from(this._fields.values()).some((n) => n.touched.value)
|
|
1424
|
+
), this.dirty = u(
|
|
1425
|
+
() => Array.from(this._fields.values()).some((n) => n.dirty.value)
|
|
1426
|
+
), this.errors = u(() => {
|
|
1427
|
+
const n = [...this._formErrors.value];
|
|
1428
|
+
return this._fields.forEach((l) => {
|
|
1429
|
+
n.push(...l.errors.value);
|
|
1430
|
+
}), n;
|
|
1431
|
+
}), this.status = u(() => this._disabled.value ? "disabled" : this.pending.value ? "pending" : this.invalid.value ? "invalid" : "valid"), this.submitting = u(() => this._submitting.value);
|
|
1432
|
+
const o = this.buildProxy();
|
|
1433
|
+
return this._proxyInstance = o, s && this.applyBehaviorSchema(s), a && this.applyValidationSchema(a), o;
|
|
1434
|
+
}
|
|
1435
|
+
// ============================================================================
|
|
1436
|
+
// Приватный метод для создания Proxy (inline из ProxyBuilder)
|
|
1437
|
+
// ============================================================================
|
|
1438
|
+
/**
|
|
1439
|
+
* Создать Proxy для типобезопасного доступа к полям
|
|
1440
|
+
*/
|
|
1441
|
+
buildProxy() {
|
|
1442
|
+
const e = this;
|
|
1443
|
+
return new Proxy(this, {
|
|
1444
|
+
get: (t, i) => {
|
|
1445
|
+
if (i in t)
|
|
1446
|
+
return t[i];
|
|
1447
|
+
if (typeof i == "string" && e._fields.has(i))
|
|
1448
|
+
return e._fields.get(i);
|
|
1449
|
+
},
|
|
1450
|
+
set: (t, i, s) => typeof i == "string" && e._fields.has(i) ? !1 : (t[i] = s, !0),
|
|
1451
|
+
has: (t, i) => typeof i == "string" && e._fields.has(i) ? !0 : i in t,
|
|
1452
|
+
ownKeys: (t) => {
|
|
1453
|
+
const i = Reflect.ownKeys(t), s = Array.from(e._fields.keys());
|
|
1454
|
+
return [.../* @__PURE__ */ new Set([...i, ...s])];
|
|
1455
|
+
},
|
|
1456
|
+
getOwnPropertyDescriptor: (t, i) => typeof i == "string" && e._fields.has(i) ? { enumerable: !0, configurable: !0 } : Reflect.getOwnPropertyDescriptor(t, i)
|
|
1457
|
+
});
|
|
1938
1458
|
}
|
|
1939
1459
|
// ============================================================================
|
|
1940
1460
|
// Реализация абстрактных методов FormNode
|
|
1941
1461
|
// ============================================================================
|
|
1942
1462
|
getValue() {
|
|
1943
1463
|
const e = {};
|
|
1944
|
-
return this.
|
|
1464
|
+
return this._fields.forEach((t, i) => {
|
|
1945
1465
|
e[i] = t.getValue();
|
|
1946
1466
|
}), e;
|
|
1947
1467
|
}
|
|
1948
1468
|
setValue(e, t) {
|
|
1949
1469
|
for (const [i, s] of Object.entries(e)) {
|
|
1950
|
-
const a = this.
|
|
1470
|
+
const a = this._fields.get(i);
|
|
1951
1471
|
a && a.setValue(s, t);
|
|
1952
1472
|
}
|
|
1953
1473
|
}
|
|
1954
1474
|
patchValue(e) {
|
|
1955
|
-
|
|
1956
|
-
const
|
|
1957
|
-
|
|
1958
|
-
|
|
1475
|
+
U(() => {
|
|
1476
|
+
for (const [t, i] of Object.entries(e)) {
|
|
1477
|
+
const s = this._fields.get(t);
|
|
1478
|
+
s && i !== void 0 && s.setValue(i);
|
|
1479
|
+
}
|
|
1480
|
+
});
|
|
1959
1481
|
}
|
|
1960
1482
|
/**
|
|
1961
1483
|
* Сбросить форму к указанным значениям (или к initialValues)
|
|
@@ -1975,103 +1497,47 @@ class m extends A {
|
|
|
1975
1497
|
* ```
|
|
1976
1498
|
*/
|
|
1977
1499
|
reset(e) {
|
|
1978
|
-
this.
|
|
1500
|
+
this._fields.forEach((t, i) => {
|
|
1979
1501
|
const s = e?.[i];
|
|
1980
1502
|
t.reset(s);
|
|
1981
1503
|
});
|
|
1982
1504
|
}
|
|
1983
1505
|
/**
|
|
1984
1506
|
* Сбросить форму к исходным значениям (initialValues)
|
|
1985
|
-
*
|
|
1986
|
-
* @remarks
|
|
1987
|
-
* Рекурсивно вызывает resetToInitial() для всех полей формы.
|
|
1988
|
-
* Более явный способ сброса к начальным значениям по сравнению с reset()
|
|
1989
|
-
*
|
|
1990
|
-
* Полезно когда:
|
|
1991
|
-
* - Пользователь нажал "Cancel" - полная отмена изменений
|
|
1992
|
-
* - Форма была изменена через reset(newValues), но нужно вернуться к самому началу
|
|
1993
|
-
* - Явное намерение показать "отмена всех изменений"
|
|
1994
|
-
*
|
|
1995
|
-
* @example
|
|
1996
|
-
* ```typescript
|
|
1997
|
-
* const form = new GroupNode({
|
|
1998
|
-
* email: { value: 'initial@mail.com', component: Input },
|
|
1999
|
-
* name: { value: 'John', component: Input }
|
|
2000
|
-
* });
|
|
2001
|
-
*
|
|
2002
|
-
* form.email.setValue('changed@mail.com');
|
|
2003
|
-
* form.reset({ email: 'temp@mail.com', name: 'Jane' });
|
|
2004
|
-
* console.log(form.getValue()); // { email: 'temp@mail.com', name: 'Jane' }
|
|
2005
|
-
*
|
|
2006
|
-
* form.resetToInitial();
|
|
2007
|
-
* console.log(form.getValue()); // { email: 'initial@mail.com', name: 'John' }
|
|
2008
|
-
* ```
|
|
2009
1507
|
*/
|
|
2010
1508
|
resetToInitial() {
|
|
2011
|
-
this.
|
|
1509
|
+
this._fields.forEach((e) => {
|
|
2012
1510
|
"resetToInitial" in e && typeof e.resetToInitial == "function" ? e.resetToInitial() : e.reset();
|
|
2013
1511
|
});
|
|
2014
1512
|
}
|
|
2015
1513
|
async validate() {
|
|
2016
|
-
this.clearErrors(), await Promise.all(Array.from(this.
|
|
1514
|
+
this.clearErrors(), await Promise.all(Array.from(this._fields.values()).map((t) => t.validate()));
|
|
2017
1515
|
const e = this.validationRegistry.getValidators();
|
|
2018
|
-
return e && e.length > 0 && await this.applyContextualValidators(e), Array.from(this.
|
|
1516
|
+
return e && e.length > 0 && await this.applyContextualValidators(e), Array.from(this._fields.values()).every((t) => t.valid.value);
|
|
2019
1517
|
}
|
|
2020
1518
|
/**
|
|
2021
1519
|
* Установить form-level validation errors
|
|
2022
|
-
* Используется для server-side validation или кросс-полевых ошибок
|
|
2023
|
-
*
|
|
2024
|
-
* @param errors - массив ошибок уровня формы
|
|
2025
|
-
*
|
|
2026
|
-
* @example
|
|
2027
|
-
* ```typescript
|
|
2028
|
-
* // Server-side validation после submit
|
|
2029
|
-
* try {
|
|
2030
|
-
* await api.createUser(form.getValue());
|
|
2031
|
-
* } catch (error) {
|
|
2032
|
-
* form.setErrors([
|
|
2033
|
-
* { code: 'duplicate_email', message: 'Email уже используется' }
|
|
2034
|
-
* ]);
|
|
2035
|
-
* }
|
|
2036
|
-
* ```
|
|
2037
1520
|
*/
|
|
2038
1521
|
setErrors(e) {
|
|
2039
|
-
this.
|
|
1522
|
+
this._formErrors.value = e;
|
|
2040
1523
|
}
|
|
2041
1524
|
/**
|
|
2042
1525
|
* Очистить все errors (form-level + field-level)
|
|
2043
1526
|
*/
|
|
2044
1527
|
clearErrors() {
|
|
2045
|
-
this.
|
|
1528
|
+
this._formErrors.value = [], this._fields.forEach((e) => e.clearErrors());
|
|
2046
1529
|
}
|
|
2047
1530
|
/**
|
|
2048
1531
|
* Получить поле по ключу
|
|
2049
|
-
*
|
|
2050
|
-
* Публичный метод для доступа к полю из fieldRegistry
|
|
2051
|
-
*
|
|
2052
|
-
* @param key - Ключ поля
|
|
2053
|
-
* @returns FormNode или undefined, если поле не найдено
|
|
2054
|
-
*
|
|
2055
|
-
* @example
|
|
2056
|
-
* ```typescript
|
|
2057
|
-
* const emailField = form.getField('email');
|
|
2058
|
-
* if (emailField) {
|
|
2059
|
-
* console.log(emailField.value.value);
|
|
2060
|
-
* }
|
|
2061
|
-
* ```
|
|
2062
1532
|
*/
|
|
2063
1533
|
getField(e) {
|
|
2064
|
-
return this.
|
|
1534
|
+
return this._fields.get(e);
|
|
2065
1535
|
}
|
|
2066
1536
|
/**
|
|
2067
|
-
* Получить Map всех полей формы
|
|
2068
|
-
*
|
|
2069
|
-
* Используется в FieldPathNavigator для навигации по полям
|
|
2070
|
-
*
|
|
2071
|
-
* @returns Map полей формы
|
|
1537
|
+
* Получить Map всех полей формы (для совместимости)
|
|
2072
1538
|
*/
|
|
2073
1539
|
get fields() {
|
|
2074
|
-
return this.
|
|
1540
|
+
return this._fields;
|
|
2075
1541
|
}
|
|
2076
1542
|
/**
|
|
2077
1543
|
* Получить Proxy-инстанс для прямого доступа к полям
|
|
@@ -2104,72 +1570,39 @@ class m extends A {
|
|
|
2104
1570
|
}
|
|
2105
1571
|
/**
|
|
2106
1572
|
* Получить все поля формы как итератор
|
|
2107
|
-
*
|
|
2108
|
-
* Предоставляет доступ к внутренним полям для валидации и других операций
|
|
2109
|
-
*
|
|
2110
|
-
* @returns Итератор по всем полям формы
|
|
2111
|
-
*
|
|
2112
|
-
* @example
|
|
2113
|
-
* ```typescript
|
|
2114
|
-
* // Валидация всех полей
|
|
2115
|
-
* await Promise.all(
|
|
2116
|
-
* Array.from(form.getAllFields()).map(field => field.validate())
|
|
2117
|
-
* );
|
|
2118
|
-
* ```
|
|
2119
1573
|
*/
|
|
2120
1574
|
getAllFields() {
|
|
2121
|
-
return this.
|
|
1575
|
+
return this._fields.values();
|
|
2122
1576
|
}
|
|
2123
1577
|
// ============================================================================
|
|
2124
1578
|
// Protected hooks (Template Method pattern)
|
|
2125
1579
|
// ============================================================================
|
|
2126
|
-
/**
|
|
2127
|
-
* Hook: вызывается после markAsTouched()
|
|
2128
|
-
*
|
|
2129
|
-
* Для GroupNode: рекурсивно помечаем все дочерние поля как touched
|
|
2130
|
-
*/
|
|
2131
1580
|
onMarkAsTouched() {
|
|
2132
|
-
this.
|
|
1581
|
+
this._fields.forEach((e) => e.markAsTouched());
|
|
2133
1582
|
}
|
|
2134
|
-
/**
|
|
2135
|
-
* Hook: вызывается после markAsUntouched()
|
|
2136
|
-
*
|
|
2137
|
-
* Для GroupNode: рекурсивно помечаем все дочерние поля как untouched
|
|
2138
|
-
*/
|
|
2139
1583
|
onMarkAsUntouched() {
|
|
2140
|
-
this.
|
|
1584
|
+
this._fields.forEach((e) => e.markAsUntouched());
|
|
2141
1585
|
}
|
|
2142
|
-
/**
|
|
2143
|
-
* Hook: вызывается после markAsDirty()
|
|
2144
|
-
*
|
|
2145
|
-
* Для GroupNode: рекурсивно помечаем все дочерние поля как dirty
|
|
2146
|
-
*/
|
|
2147
1586
|
onMarkAsDirty() {
|
|
2148
|
-
this.
|
|
1587
|
+
this._fields.forEach((e) => e.markAsDirty());
|
|
2149
1588
|
}
|
|
2150
|
-
/**
|
|
2151
|
-
* Hook: вызывается после markAsPristine()
|
|
2152
|
-
*
|
|
2153
|
-
* Для GroupNode: рекурсивно помечаем все дочерние поля как pristine
|
|
2154
|
-
*/
|
|
2155
1589
|
onMarkAsPristine() {
|
|
2156
|
-
this.
|
|
1590
|
+
this._fields.forEach((e) => e.markAsPristine());
|
|
2157
1591
|
}
|
|
2158
1592
|
// ============================================================================
|
|
2159
1593
|
// Дополнительные методы (из FormStore)
|
|
2160
1594
|
// ============================================================================
|
|
2161
1595
|
/**
|
|
2162
1596
|
* Отправить форму
|
|
2163
|
-
* Валидирует форму и вызывает onSubmit если форма валидна
|
|
2164
1597
|
*/
|
|
2165
1598
|
async submit(e) {
|
|
2166
1599
|
if (this.markAsTouched(), !await this.validate())
|
|
2167
1600
|
return null;
|
|
2168
|
-
this.
|
|
1601
|
+
this._submitting.value = !0;
|
|
2169
1602
|
try {
|
|
2170
1603
|
return await e(this.getValue());
|
|
2171
1604
|
} finally {
|
|
2172
|
-
this.
|
|
1605
|
+
this._submitting.value = !1;
|
|
2173
1606
|
}
|
|
2174
1607
|
}
|
|
2175
1608
|
/**
|
|
@@ -2181,7 +1614,7 @@ class m extends A {
|
|
|
2181
1614
|
applyValidationSchema(e) {
|
|
2182
1615
|
this.validationRegistry.beginRegistration();
|
|
2183
1616
|
try {
|
|
2184
|
-
const t =
|
|
1617
|
+
const t = I();
|
|
2185
1618
|
e(t);
|
|
2186
1619
|
const i = this.getProxy();
|
|
2187
1620
|
this.validationRegistry.endRegistration(i);
|
|
@@ -2191,44 +1624,16 @@ class m extends A {
|
|
|
2191
1624
|
}
|
|
2192
1625
|
/**
|
|
2193
1626
|
* Применить behavior schema к форме
|
|
2194
|
-
*
|
|
2195
|
-
* ✅ РЕФАКТОРИНГ: Делегирование BehaviorApplicator (SRP)
|
|
2196
|
-
*
|
|
2197
|
-
* Логика применения behavior схемы извлечена в BehaviorApplicator для:
|
|
2198
|
-
* - Соблюдения Single Responsibility Principle
|
|
2199
|
-
* - Уменьшения размера GroupNode (~50 строк)
|
|
2200
|
-
* - Улучшения тестируемости
|
|
2201
|
-
* - Консистентности с ValidationApplicator
|
|
2202
|
-
*
|
|
2203
|
-
* @param schemaFn Функция описания поведения формы
|
|
2204
1627
|
* @returns Функция cleanup для отписки от всех behaviors
|
|
2205
|
-
*
|
|
2206
|
-
* @example
|
|
2207
|
-
* ```typescript
|
|
2208
|
-
* import { copyFrom, enableWhen, computeFrom } from '@/lib/forms/core/behaviors';
|
|
2209
|
-
*
|
|
2210
|
-
* const behaviorSchema: BehaviorSchemaFn<MyForm> = (path) => {
|
|
2211
|
-
* copyFrom(path.residenceAddress, path.registrationAddress, {
|
|
2212
|
-
* when: (form) => form.sameAsRegistration === true
|
|
2213
|
-
* });
|
|
2214
|
-
*
|
|
2215
|
-
* enableWhen(path.propertyValue, (form) => form.loanType === 'mortgage');
|
|
2216
|
-
*
|
|
2217
|
-
* computeFrom(
|
|
2218
|
-
* path.initialPayment,
|
|
2219
|
-
* [path.propertyValue],
|
|
2220
|
-
* (propertyValue) => propertyValue ? propertyValue * 0.2 : null
|
|
2221
|
-
* );
|
|
2222
|
-
* };
|
|
2223
|
-
*
|
|
2224
|
-
* const cleanup = form.applyBehaviorSchema(behaviorSchema);
|
|
2225
|
-
*
|
|
2226
|
-
* // Cleanup при unmount
|
|
2227
|
-
* useEffect(() => cleanup, []);
|
|
2228
|
-
* ```
|
|
2229
1628
|
*/
|
|
2230
1629
|
applyBehaviorSchema(e) {
|
|
2231
|
-
|
|
1630
|
+
this.behaviorRegistry.beginRegistration();
|
|
1631
|
+
try {
|
|
1632
|
+
const t = I();
|
|
1633
|
+
return e(t), this.behaviorRegistry.endRegistration(this.getProxy()).cleanup;
|
|
1634
|
+
} catch (t) {
|
|
1635
|
+
throw console.error("Error applying behavior schema:", t), t;
|
|
1636
|
+
}
|
|
2232
1637
|
}
|
|
2233
1638
|
/**
|
|
2234
1639
|
* Получить вложенное поле по пути
|
|
@@ -2267,7 +1672,7 @@ class m extends A {
|
|
|
2267
1672
|
return;
|
|
2268
1673
|
let i = this;
|
|
2269
1674
|
for (const s of t) {
|
|
2270
|
-
if (!(i instanceof
|
|
1675
|
+
if (!(i instanceof b) || (i = i.getField(s.key), !i)) return;
|
|
2271
1676
|
if (s.index !== void 0)
|
|
2272
1677
|
if ("at" in i && "length" in i && typeof i.at == "function") {
|
|
2273
1678
|
const a = i.at(s.index);
|
|
@@ -2319,40 +1724,17 @@ class m extends A {
|
|
|
2319
1724
|
// ============================================================================
|
|
2320
1725
|
/**
|
|
2321
1726
|
* Связывает два поля: при изменении source автоматически обновляется target
|
|
2322
|
-
* Поддерживает опциональную трансформацию значения
|
|
2323
|
-
*
|
|
2324
|
-
* @param sourceKey - Ключ поля-источника
|
|
2325
|
-
* @param targetKey - Ключ поля-цели
|
|
2326
|
-
* @param transform - Опциональная функция трансформации значения
|
|
2327
|
-
* @returns Функция отписки для cleanup
|
|
2328
|
-
*
|
|
2329
|
-
* @example
|
|
2330
|
-
* ```typescript
|
|
2331
|
-
* // Автоматический расчет минимального взноса от стоимости недвижимости
|
|
2332
|
-
* const dispose = form.linkFields(
|
|
2333
|
-
* 'propertyValue',
|
|
2334
|
-
* 'initialPayment',
|
|
2335
|
-
* (propertyValue) => propertyValue ? propertyValue * 0.2 : null
|
|
2336
|
-
* );
|
|
2337
|
-
*
|
|
2338
|
-
* // При изменении propertyValue → автоматически обновится initialPayment
|
|
2339
|
-
* form.propertyValue.setValue(1000000);
|
|
2340
|
-
* // initialPayment станет 200000
|
|
2341
|
-
*
|
|
2342
|
-
* // Cleanup
|
|
2343
|
-
* useEffect(() => dispose, []);
|
|
2344
|
-
* ```
|
|
2345
1727
|
*/
|
|
2346
1728
|
linkFields(e, t, i) {
|
|
2347
|
-
const s = this.
|
|
1729
|
+
const s = this._fields.get(e), a = this._fields.get(t);
|
|
2348
1730
|
if (!s || !a)
|
|
2349
1731
|
return () => {
|
|
2350
1732
|
};
|
|
2351
|
-
const
|
|
2352
|
-
const
|
|
2353
|
-
a.setValue(
|
|
2354
|
-
}),
|
|
2355
|
-
return this.disposers.add(
|
|
1733
|
+
const o = E(() => {
|
|
1734
|
+
const l = s.value.value, d = i ? i(l) : l;
|
|
1735
|
+
a.setValue(d, { emitEvent: !1 });
|
|
1736
|
+
}), n = `linkFields-${Date.now()}-${Math.random()}`;
|
|
1737
|
+
return this.disposers.add(n, o);
|
|
2356
1738
|
}
|
|
2357
1739
|
/**
|
|
2358
1740
|
* Подписка на изменения вложенного поля по строковому пути
|
|
@@ -2386,52 +1768,34 @@ class m extends A {
|
|
|
2386
1768
|
if (!i)
|
|
2387
1769
|
return () => {
|
|
2388
1770
|
};
|
|
2389
|
-
const s =
|
|
2390
|
-
const
|
|
2391
|
-
t(
|
|
1771
|
+
const s = E(() => {
|
|
1772
|
+
const o = i.value.value;
|
|
1773
|
+
t(o);
|
|
2392
1774
|
}), a = `watchField-${Date.now()}-${Math.random()}`;
|
|
2393
1775
|
return this.disposers.add(a, s);
|
|
2394
1776
|
}
|
|
2395
1777
|
/**
|
|
2396
1778
|
* Hook: вызывается после disable()
|
|
2397
|
-
*
|
|
2398
|
-
* Для GroupNode: рекурсивно отключаем все дочерние поля
|
|
2399
1779
|
*/
|
|
2400
1780
|
onDisable() {
|
|
2401
|
-
this.
|
|
2402
|
-
e.disable();
|
|
2403
|
-
});
|
|
1781
|
+
this._disabled.value = !0, this._fields.forEach((e) => e.disable());
|
|
2404
1782
|
}
|
|
2405
1783
|
/**
|
|
2406
1784
|
* Hook: вызывается после enable()
|
|
2407
|
-
*
|
|
2408
|
-
* Для GroupNode: рекурсивно включаем все дочерние поля
|
|
2409
1785
|
*/
|
|
2410
1786
|
onEnable() {
|
|
2411
|
-
this.
|
|
2412
|
-
e.enable();
|
|
2413
|
-
});
|
|
1787
|
+
this._disabled.value = !1, this._fields.forEach((e) => e.enable());
|
|
2414
1788
|
}
|
|
2415
1789
|
/**
|
|
2416
1790
|
* Очистить все ресурсы узла
|
|
2417
|
-
* Рекурсивно очищает все subscriptions и дочерние узлы
|
|
2418
|
-
*
|
|
2419
|
-
* @example
|
|
2420
|
-
* ```typescript
|
|
2421
|
-
* useEffect(() => {
|
|
2422
|
-
* return () => {
|
|
2423
|
-
* form.dispose();
|
|
2424
|
-
* };
|
|
2425
|
-
* }, []);
|
|
2426
|
-
* ```
|
|
2427
1791
|
*/
|
|
2428
1792
|
dispose() {
|
|
2429
|
-
this.disposers.dispose(), this.
|
|
1793
|
+
this.disposers.dispose(), this._fields.forEach((e) => {
|
|
2430
1794
|
"dispose" in e && typeof e.dispose == "function" && e.dispose();
|
|
2431
1795
|
});
|
|
2432
1796
|
}
|
|
2433
1797
|
}
|
|
2434
|
-
class
|
|
1798
|
+
class C extends O {
|
|
2435
1799
|
// ============================================================================
|
|
2436
1800
|
// Приватные поля
|
|
2437
1801
|
// ============================================================================
|
|
@@ -2442,7 +1806,7 @@ class F extends A {
|
|
|
2442
1806
|
* Менеджер подписок для централизованного cleanup
|
|
2443
1807
|
* Использует SubscriptionManager вместо массива для управления подписками
|
|
2444
1808
|
*/
|
|
2445
|
-
disposers = new
|
|
1809
|
+
disposers = new P();
|
|
2446
1810
|
// ============================================================================
|
|
2447
1811
|
// Приватные поля для сохранения схем
|
|
2448
1812
|
// ============================================================================
|
|
@@ -2464,15 +1828,15 @@ class F extends A {
|
|
|
2464
1828
|
// Конструктор
|
|
2465
1829
|
// ============================================================================
|
|
2466
1830
|
constructor(e, t = []) {
|
|
2467
|
-
super(), this.itemSchema = e, this.initialItems = t, this.items =
|
|
1831
|
+
super(), this.itemSchema = e, this.initialItems = t, this.items = y([]);
|
|
2468
1832
|
for (const i of t)
|
|
2469
1833
|
this.push(i);
|
|
2470
|
-
this.length =
|
|
1834
|
+
this.length = u(() => this.items.value.length), this.value = u(() => this.items.value.map((i) => i.value.value)), this.valid = u(() => this.items.value.every((i) => i.valid.value)), this.invalid = u(() => !this.valid.value), this.pending = u(() => this.items.value.some((i) => i.pending.value)), this.touched = u(() => this.items.value.some((i) => i.touched.value)), this.dirty = u(() => this.items.value.some((i) => i.dirty.value)), this.errors = u(() => {
|
|
2471
1835
|
const i = [];
|
|
2472
1836
|
return this.items.value.forEach((s) => {
|
|
2473
1837
|
i.push(...s.errors.value);
|
|
2474
1838
|
}), i;
|
|
2475
|
-
}), this.status =
|
|
1839
|
+
}), this.status = u(() => this.pending.value ? "pending" : this.invalid.value ? "invalid" : "valid");
|
|
2476
1840
|
}
|
|
2477
1841
|
// ============================================================================
|
|
2478
1842
|
// CRUD операции
|
|
@@ -2655,7 +2019,7 @@ class F extends A {
|
|
|
2655
2019
|
*/
|
|
2656
2020
|
createItem(e) {
|
|
2657
2021
|
if (this.isGroupSchema(this.itemSchema)) {
|
|
2658
|
-
const t = new
|
|
2022
|
+
const t = new b(this.itemSchema);
|
|
2659
2023
|
return e && t.patchValue(e), this.validationSchemaFn && "applyValidationSchema" in t && t.applyValidationSchema(this.validationSchemaFn), this.behaviorSchemaFn && "applyBehaviorSchema" in t && t.applyBehaviorSchema(this.behaviorSchemaFn), t;
|
|
2660
2024
|
}
|
|
2661
2025
|
throw new Error(
|
|
@@ -2742,10 +2106,10 @@ class F extends A {
|
|
|
2742
2106
|
* ```
|
|
2743
2107
|
*/
|
|
2744
2108
|
watchItems(e, t) {
|
|
2745
|
-
const i =
|
|
2746
|
-
const a = this.items.value.map((
|
|
2747
|
-
if (
|
|
2748
|
-
return
|
|
2109
|
+
const i = E(() => {
|
|
2110
|
+
const a = this.items.value.map((o) => {
|
|
2111
|
+
if (o instanceof b)
|
|
2112
|
+
return o.getFieldByPath(e)?.value.value;
|
|
2749
2113
|
});
|
|
2750
2114
|
t(a);
|
|
2751
2115
|
}), s = `watchItems-${Date.now()}-${Math.random()}`;
|
|
@@ -2774,7 +2138,7 @@ class F extends A {
|
|
|
2774
2138
|
* ```
|
|
2775
2139
|
*/
|
|
2776
2140
|
watchLength(e) {
|
|
2777
|
-
const t =
|
|
2141
|
+
const t = E(() => {
|
|
2778
2142
|
const s = this.length.value;
|
|
2779
2143
|
e(s);
|
|
2780
2144
|
}), i = `watchLength-${Date.now()}-${Math.random()}`;
|
|
@@ -2841,7 +2205,7 @@ class F extends A {
|
|
|
2841
2205
|
});
|
|
2842
2206
|
}
|
|
2843
2207
|
}
|
|
2844
|
-
class
|
|
2208
|
+
class X {
|
|
2845
2209
|
/**
|
|
2846
2210
|
* Создает узел формы на основе конфигурации
|
|
2847
2211
|
*
|
|
@@ -2891,16 +2255,16 @@ class L {
|
|
|
2891
2255
|
if (Array.isArray(e) && e.length >= 1)
|
|
2892
2256
|
return this.createArrayNodeFromArray(e);
|
|
2893
2257
|
if (this.isFieldConfig(e))
|
|
2894
|
-
return new
|
|
2258
|
+
return new J(e);
|
|
2895
2259
|
if (this.isArrayConfig(e)) {
|
|
2896
2260
|
const t = e;
|
|
2897
|
-
return new
|
|
2261
|
+
return new C(
|
|
2898
2262
|
t.schema,
|
|
2899
2263
|
t.initialItems
|
|
2900
2264
|
);
|
|
2901
2265
|
}
|
|
2902
2266
|
if (this.isGroupConfig(e))
|
|
2903
|
-
return new
|
|
2267
|
+
return new b(e);
|
|
2904
2268
|
throw new Error(
|
|
2905
2269
|
`NodeFactory: Unknown node config. Expected FieldConfig, GroupConfig, or ArrayConfig, but got: ${JSON.stringify(
|
|
2906
2270
|
e
|
|
@@ -2938,7 +2302,7 @@ class L {
|
|
|
2938
2302
|
this.isGroupConfig(t) && s.push(this.extractValues(t));
|
|
2939
2303
|
for (const a of i)
|
|
2940
2304
|
this.isGroupConfig(a) ? s.push(this.extractValues(a)) : s.push(a);
|
|
2941
|
-
return new
|
|
2305
|
+
return new C(t, s);
|
|
2942
2306
|
}
|
|
2943
2307
|
/**
|
|
2944
2308
|
* Извлечь значения из схемы (рекурсивно)
|
|
@@ -3057,7 +2421,7 @@ class L {
|
|
|
3057
2421
|
return e != null && typeof e == "object" && !this.isFieldConfig(e) && !this.isArrayConfig(e);
|
|
3058
2422
|
}
|
|
3059
2423
|
}
|
|
3060
|
-
class
|
|
2424
|
+
class fe {
|
|
3061
2425
|
/**
|
|
3062
2426
|
* Создать Debouncer с заданной задержкой
|
|
3063
2427
|
*
|
|
@@ -3182,10 +2546,10 @@ class ee {
|
|
|
3182
2546
|
return this.timer !== void 0;
|
|
3183
2547
|
}
|
|
3184
2548
|
}
|
|
3185
|
-
function
|
|
3186
|
-
return new
|
|
2549
|
+
function ve(r) {
|
|
2550
|
+
return new b(r);
|
|
3187
2551
|
}
|
|
3188
|
-
function
|
|
2552
|
+
function Z(r) {
|
|
3189
2553
|
return {
|
|
3190
2554
|
type: "static",
|
|
3191
2555
|
load: async () => ({
|
|
@@ -3194,7 +2558,7 @@ function j(r) {
|
|
|
3194
2558
|
})
|
|
3195
2559
|
};
|
|
3196
2560
|
}
|
|
3197
|
-
function
|
|
2561
|
+
function ee(r) {
|
|
3198
2562
|
let e = null;
|
|
3199
2563
|
return {
|
|
3200
2564
|
type: "preload",
|
|
@@ -3210,7 +2574,7 @@ function K(r) {
|
|
|
3210
2574
|
}
|
|
3211
2575
|
};
|
|
3212
2576
|
}
|
|
3213
|
-
function
|
|
2577
|
+
function te(r) {
|
|
3214
2578
|
return {
|
|
3215
2579
|
type: "partial",
|
|
3216
2580
|
load: async (e) => {
|
|
@@ -3223,104 +2587,255 @@ function z(r) {
|
|
|
3223
2587
|
}
|
|
3224
2588
|
};
|
|
3225
2589
|
}
|
|
3226
|
-
const
|
|
3227
|
-
static:
|
|
3228
|
-
preload:
|
|
3229
|
-
partial:
|
|
2590
|
+
const pe = {
|
|
2591
|
+
static: Z,
|
|
2592
|
+
preload: ee,
|
|
2593
|
+
partial: te
|
|
3230
2594
|
};
|
|
3231
|
-
|
|
2595
|
+
var V = { exports: {} }, k = {};
|
|
2596
|
+
var D;
|
|
2597
|
+
function ie() {
|
|
2598
|
+
if (D) return k;
|
|
2599
|
+
D = 1;
|
|
2600
|
+
var r = B;
|
|
2601
|
+
function e(c, f) {
|
|
2602
|
+
return c === f && (c !== 0 || 1 / c === 1 / f) || c !== c && f !== f;
|
|
2603
|
+
}
|
|
2604
|
+
var t = typeof Object.is == "function" ? Object.is : e, i = r.useState, s = r.useEffect, a = r.useLayoutEffect, o = r.useDebugValue;
|
|
2605
|
+
function n(c, f) {
|
|
2606
|
+
var h = f(), v = i({ inst: { value: h, getSnapshot: f } }), p = v[0].inst, g = v[1];
|
|
2607
|
+
return a(
|
|
2608
|
+
function() {
|
|
2609
|
+
p.value = h, p.getSnapshot = f, l(p) && g({ inst: p });
|
|
2610
|
+
},
|
|
2611
|
+
[c, h, f]
|
|
2612
|
+
), s(
|
|
2613
|
+
function() {
|
|
2614
|
+
return l(p) && g({ inst: p }), c(function() {
|
|
2615
|
+
l(p) && g({ inst: p });
|
|
2616
|
+
});
|
|
2617
|
+
},
|
|
2618
|
+
[c]
|
|
2619
|
+
), o(h), h;
|
|
2620
|
+
}
|
|
2621
|
+
function l(c) {
|
|
2622
|
+
var f = c.getSnapshot;
|
|
2623
|
+
c = c.value;
|
|
2624
|
+
try {
|
|
2625
|
+
var h = f();
|
|
2626
|
+
return !t(c, h);
|
|
2627
|
+
} catch {
|
|
2628
|
+
return !0;
|
|
2629
|
+
}
|
|
2630
|
+
}
|
|
2631
|
+
function d(c, f) {
|
|
2632
|
+
return f();
|
|
2633
|
+
}
|
|
2634
|
+
var m = typeof window > "u" || typeof window.document > "u" || typeof window.document.createElement > "u" ? d : n;
|
|
2635
|
+
return k.useSyncExternalStore = r.useSyncExternalStore !== void 0 ? r.useSyncExternalStore : m, k;
|
|
2636
|
+
}
|
|
2637
|
+
var x = {};
|
|
2638
|
+
var N;
|
|
2639
|
+
function se() {
|
|
2640
|
+
return N || (N = 1, process.env.NODE_ENV !== "production" && (function() {
|
|
2641
|
+
function r(h, v) {
|
|
2642
|
+
return h === v && (h !== 0 || 1 / h === 1 / v) || h !== h && v !== v;
|
|
2643
|
+
}
|
|
2644
|
+
function e(h, v) {
|
|
2645
|
+
m || s.startTransition === void 0 || (m = !0, console.error(
|
|
2646
|
+
"You are using an outdated, pre-release alpha of React 18 that does not support useSyncExternalStore. The use-sync-external-store shim will not work correctly. Upgrade to a newer pre-release."
|
|
2647
|
+
));
|
|
2648
|
+
var p = v();
|
|
2649
|
+
if (!c) {
|
|
2650
|
+
var g = v();
|
|
2651
|
+
a(p, g) || (console.error(
|
|
2652
|
+
"The result of getSnapshot should be cached to avoid an infinite loop"
|
|
2653
|
+
), c = !0);
|
|
2654
|
+
}
|
|
2655
|
+
g = o({
|
|
2656
|
+
inst: { value: p, getSnapshot: v }
|
|
2657
|
+
});
|
|
2658
|
+
var _ = g[0].inst, A = g[1];
|
|
2659
|
+
return l(
|
|
2660
|
+
function() {
|
|
2661
|
+
_.value = p, _.getSnapshot = v, t(_) && A({ inst: _ });
|
|
2662
|
+
},
|
|
2663
|
+
[h, p, v]
|
|
2664
|
+
), n(
|
|
2665
|
+
function() {
|
|
2666
|
+
return t(_) && A({ inst: _ }), h(function() {
|
|
2667
|
+
t(_) && A({ inst: _ });
|
|
2668
|
+
});
|
|
2669
|
+
},
|
|
2670
|
+
[h]
|
|
2671
|
+
), d(p), p;
|
|
2672
|
+
}
|
|
2673
|
+
function t(h) {
|
|
2674
|
+
var v = h.getSnapshot;
|
|
2675
|
+
h = h.value;
|
|
2676
|
+
try {
|
|
2677
|
+
var p = v();
|
|
2678
|
+
return !a(h, p);
|
|
2679
|
+
} catch {
|
|
2680
|
+
return !0;
|
|
2681
|
+
}
|
|
2682
|
+
}
|
|
2683
|
+
function i(h, v) {
|
|
2684
|
+
return v();
|
|
2685
|
+
}
|
|
2686
|
+
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ < "u" && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart == "function" && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
|
|
2687
|
+
var s = B, a = typeof Object.is == "function" ? Object.is : r, o = s.useState, n = s.useEffect, l = s.useLayoutEffect, d = s.useDebugValue, m = !1, c = !1, f = typeof window > "u" || typeof window.document > "u" || typeof window.document.createElement > "u" ? i : e;
|
|
2688
|
+
x.useSyncExternalStore = s.useSyncExternalStore !== void 0 ? s.useSyncExternalStore : f, typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ < "u" && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop == "function" && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
|
|
2689
|
+
})()), x;
|
|
2690
|
+
}
|
|
2691
|
+
var M;
|
|
2692
|
+
function re() {
|
|
2693
|
+
return M || (M = 1, process.env.NODE_ENV === "production" ? V.exports = ie() : V.exports = se()), V.exports;
|
|
2694
|
+
}
|
|
2695
|
+
var $ = re();
|
|
2696
|
+
function ae(r, e) {
|
|
3232
2697
|
if (r === e) return !0;
|
|
3233
2698
|
if (r.length !== e.length) return !1;
|
|
3234
2699
|
for (let t = 0; t < r.length; t++)
|
|
3235
2700
|
if (r[t] !== e[t]) return !1;
|
|
3236
2701
|
return !0;
|
|
3237
2702
|
}
|
|
3238
|
-
function
|
|
3239
|
-
const
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
if (r.value.value, r.disabled.value, r.errors.value, r.pending.value, r.valid.value, r.invalid.value, r.touched.value, r.shouldShowError.value, r.componentProps.value, a) {
|
|
3255
|
-
a = !1;
|
|
2703
|
+
function G(r, e, t) {
|
|
2704
|
+
const i = L(null);
|
|
2705
|
+
if (i.current === null) {
|
|
2706
|
+
const o = {};
|
|
2707
|
+
for (const n in r)
|
|
2708
|
+
o[n] = r[n].value;
|
|
2709
|
+
i.current = { ...o, __snapshot: null };
|
|
2710
|
+
}
|
|
2711
|
+
const s = S(
|
|
2712
|
+
(o) => {
|
|
2713
|
+
let n = !0;
|
|
2714
|
+
return E(() => {
|
|
2715
|
+
for (const d in r)
|
|
2716
|
+
r[d].value;
|
|
2717
|
+
if (n) {
|
|
2718
|
+
n = !1;
|
|
3256
2719
|
return;
|
|
3257
2720
|
}
|
|
3258
|
-
|
|
2721
|
+
o();
|
|
3259
2722
|
});
|
|
3260
2723
|
},
|
|
3261
2724
|
[r]
|
|
3262
|
-
),
|
|
3263
|
-
const
|
|
3264
|
-
|
|
3265
|
-
value
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
componentProps: o
|
|
3274
|
-
}), s.snapshot;
|
|
3275
|
-
}, [r]);
|
|
3276
|
-
return w(t, i, i);
|
|
3277
|
-
}
|
|
3278
|
-
function H(r) {
|
|
3279
|
-
const e = V({
|
|
3280
|
-
snapshot: null,
|
|
3281
|
-
value: r.value.value,
|
|
3282
|
-
length: r.length.value,
|
|
3283
|
-
errors: r.errors.value,
|
|
3284
|
-
pending: r.pending.value,
|
|
3285
|
-
valid: r.valid.value,
|
|
3286
|
-
invalid: r.invalid.value,
|
|
3287
|
-
touched: r.touched.value,
|
|
3288
|
-
dirty: r.dirty.value
|
|
3289
|
-
}), t = y(
|
|
3290
|
-
(s) => {
|
|
3291
|
-
let a = !0;
|
|
3292
|
-
return v(() => {
|
|
3293
|
-
if (r.value.value, r.length.value, r.errors.value, r.pending.value, r.valid.value, r.invalid.value, r.touched.value, r.dirty.value, a) {
|
|
3294
|
-
a = !1;
|
|
3295
|
-
return;
|
|
2725
|
+
), a = S(() => {
|
|
2726
|
+
const o = i.current, n = {};
|
|
2727
|
+
for (const d in r)
|
|
2728
|
+
n[d] = r[d].value;
|
|
2729
|
+
let l = !1;
|
|
2730
|
+
for (const d of e) {
|
|
2731
|
+
const { key: m, useShallowArrayEqual: c } = d, f = n[m], h = o[m];
|
|
2732
|
+
if (c) {
|
|
2733
|
+
if (!ae(h, f)) {
|
|
2734
|
+
l = !0;
|
|
2735
|
+
break;
|
|
3296
2736
|
}
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
2737
|
+
} else if (h !== f) {
|
|
2738
|
+
l = !0;
|
|
2739
|
+
break;
|
|
2740
|
+
}
|
|
2741
|
+
}
|
|
2742
|
+
if (!l && o.__snapshot)
|
|
2743
|
+
return o.__snapshot;
|
|
2744
|
+
for (const d in r)
|
|
2745
|
+
o[d] = n[d];
|
|
2746
|
+
return o.__snapshot = t(n), o.__snapshot;
|
|
2747
|
+
}, [r, t]);
|
|
2748
|
+
return $.useSyncExternalStore(s, a, a);
|
|
2749
|
+
}
|
|
2750
|
+
function ne(r) {
|
|
2751
|
+
const e = {
|
|
2752
|
+
value: r.value,
|
|
2753
|
+
disabled: r.disabled,
|
|
2754
|
+
errors: r.errors,
|
|
2755
|
+
pending: r.pending,
|
|
2756
|
+
valid: r.valid,
|
|
2757
|
+
invalid: r.invalid,
|
|
2758
|
+
touched: r.touched,
|
|
2759
|
+
shouldShowError: r.shouldShowError,
|
|
2760
|
+
componentProps: r.componentProps
|
|
2761
|
+
}, t = [
|
|
2762
|
+
{ key: "value" },
|
|
2763
|
+
{ key: "disabled" },
|
|
2764
|
+
{ key: "errors", useShallowArrayEqual: !0 },
|
|
2765
|
+
{ key: "pending" },
|
|
2766
|
+
{ key: "valid" },
|
|
2767
|
+
{ key: "invalid" },
|
|
2768
|
+
{ key: "touched" },
|
|
2769
|
+
{ key: "shouldShowError" },
|
|
2770
|
+
{ key: "componentProps" }
|
|
2771
|
+
], i = S(
|
|
2772
|
+
(s) => ({
|
|
2773
|
+
value: s.value,
|
|
2774
|
+
pending: s.pending,
|
|
2775
|
+
disabled: s.disabled,
|
|
2776
|
+
errors: s.errors,
|
|
2777
|
+
valid: s.valid,
|
|
2778
|
+
invalid: s.invalid,
|
|
2779
|
+
touched: s.touched,
|
|
2780
|
+
shouldShowError: s.shouldShowError,
|
|
2781
|
+
componentProps: s.componentProps
|
|
2782
|
+
}),
|
|
2783
|
+
[]
|
|
2784
|
+
);
|
|
2785
|
+
return G(e, t, i);
|
|
3315
2786
|
}
|
|
3316
|
-
function
|
|
3317
|
-
const e =
|
|
3318
|
-
value: r.value
|
|
3319
|
-
|
|
3320
|
-
|
|
2787
|
+
function oe(r) {
|
|
2788
|
+
const e = {
|
|
2789
|
+
value: r.value,
|
|
2790
|
+
length: r.length,
|
|
2791
|
+
errors: r.errors,
|
|
2792
|
+
pending: r.pending,
|
|
2793
|
+
valid: r.valid,
|
|
2794
|
+
invalid: r.invalid,
|
|
2795
|
+
touched: r.touched,
|
|
2796
|
+
dirty: r.dirty
|
|
2797
|
+
}, t = [
|
|
2798
|
+
{ key: "value" },
|
|
2799
|
+
{ key: "length" },
|
|
2800
|
+
{ key: "errors", useShallowArrayEqual: !0 },
|
|
2801
|
+
{ key: "pending" },
|
|
2802
|
+
{ key: "valid" },
|
|
2803
|
+
{ key: "invalid" },
|
|
2804
|
+
{ key: "touched" },
|
|
2805
|
+
{ key: "dirty" }
|
|
2806
|
+
], i = S(
|
|
2807
|
+
(s) => ({
|
|
2808
|
+
value: s.value,
|
|
2809
|
+
length: s.length,
|
|
2810
|
+
pending: s.pending,
|
|
2811
|
+
errors: s.errors,
|
|
2812
|
+
valid: s.valid,
|
|
2813
|
+
invalid: s.invalid,
|
|
2814
|
+
touched: s.touched,
|
|
2815
|
+
dirty: s.dirty
|
|
2816
|
+
}),
|
|
2817
|
+
[]
|
|
2818
|
+
);
|
|
2819
|
+
return G(e, t, i);
|
|
2820
|
+
}
|
|
2821
|
+
function ye(r) {
|
|
2822
|
+
const e = r && "length" in r && "map" in r;
|
|
2823
|
+
return r ? e ? oe(r) : ne(r) : {
|
|
2824
|
+
value: [],
|
|
2825
|
+
length: 0,
|
|
2826
|
+
pending: !1,
|
|
2827
|
+
errors: [],
|
|
2828
|
+
valid: !0,
|
|
2829
|
+
invalid: !1,
|
|
2830
|
+
touched: !1,
|
|
2831
|
+
dirty: !1
|
|
2832
|
+
};
|
|
2833
|
+
}
|
|
2834
|
+
function me(r) {
|
|
2835
|
+
const e = L({ value: r.value.value }), t = S(
|
|
3321
2836
|
(s) => {
|
|
3322
2837
|
let a = !0;
|
|
3323
|
-
return
|
|
2838
|
+
return E(() => {
|
|
3324
2839
|
if (r.value.value, a) {
|
|
3325
2840
|
a = !1;
|
|
3326
2841
|
return;
|
|
@@ -3329,52 +2844,43 @@ function ie(r) {
|
|
|
3329
2844
|
});
|
|
3330
2845
|
},
|
|
3331
2846
|
[r]
|
|
3332
|
-
), i =
|
|
2847
|
+
), i = S(() => {
|
|
3333
2848
|
const s = r.value.value;
|
|
3334
|
-
return e.current.value === s ? e.current.
|
|
2849
|
+
return e.current.value === s ? e.current.value : (e.current.value = s, s);
|
|
3335
2850
|
}, [r]);
|
|
3336
|
-
return
|
|
3337
|
-
}
|
|
3338
|
-
function re(r) {
|
|
3339
|
-
const e = r && "length" in r && "map" in r;
|
|
3340
|
-
return r ? e ? H(r) : W(r) : {
|
|
3341
|
-
value: [],
|
|
3342
|
-
length: 0,
|
|
3343
|
-
pending: !1,
|
|
3344
|
-
errors: [],
|
|
3345
|
-
valid: !0,
|
|
3346
|
-
invalid: !1,
|
|
3347
|
-
touched: !1,
|
|
3348
|
-
dirty: !1
|
|
3349
|
-
};
|
|
2851
|
+
return $.useSyncExternalStore(t, i, i);
|
|
3350
2852
|
}
|
|
3351
2853
|
export {
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
2854
|
+
C as ArrayNode,
|
|
2855
|
+
fe as Debouncer,
|
|
2856
|
+
w as ErrorStrategy,
|
|
2857
|
+
J as FieldNode,
|
|
2858
|
+
Q as FieldPathNavigator,
|
|
2859
|
+
F as FormErrorHandler,
|
|
2860
|
+
O as FormNode,
|
|
2861
|
+
b as GroupNode,
|
|
2862
|
+
X as NodeFactory,
|
|
2863
|
+
Fe as RegistryStack,
|
|
2864
|
+
pe as Resources,
|
|
2865
|
+
P as SubscriptionManager,
|
|
2866
|
+
Ee as behaviors,
|
|
2867
|
+
I as createFieldPath,
|
|
2868
|
+
ve as createForm,
|
|
2869
|
+
Oe as extractKey,
|
|
2870
|
+
Pe as extractPath,
|
|
2871
|
+
Te as getCurrentBehaviorRegistry,
|
|
2872
|
+
Re as getCurrentValidationRegistry,
|
|
2873
|
+
be as getNodeType,
|
|
2874
|
+
R as isArrayNode,
|
|
2875
|
+
T as isFieldNode,
|
|
2876
|
+
Ve as isFormNode,
|
|
2877
|
+
we as isGroupNode,
|
|
2878
|
+
te as partialResource,
|
|
2879
|
+
ee as preloadResource,
|
|
2880
|
+
Z as staticResource,
|
|
2881
|
+
Ie as toFieldPath,
|
|
2882
|
+
ye as useFormControl,
|
|
2883
|
+
me as useFormControlValue,
|
|
2884
|
+
Ae as validateForm,
|
|
2885
|
+
ke as validators
|
|
3380
2886
|
};
|