@reformer/core 2.0.1 → 4.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.
- package/dist/behaviors/compute-from.d.ts +2 -0
- package/dist/behaviors/compute-from.js +31 -0
- package/dist/behaviors/copy-from.d.ts +2 -0
- package/dist/behaviors/copy-from.js +29 -0
- package/dist/behaviors/enable-when.d.ts +2 -0
- package/dist/behaviors/enable-when.js +25 -0
- package/dist/behaviors/reset-when.d.ts +2 -0
- package/dist/behaviors/reset-when.js +24 -0
- package/dist/behaviors/revalidate-when.d.ts +2 -0
- package/dist/behaviors/revalidate-when.js +18 -0
- package/dist/behaviors/sync-fields.d.ts +2 -0
- package/dist/behaviors/sync-fields.js +41 -0
- package/dist/behaviors/transform-value.d.ts +2 -0
- package/dist/behaviors/transform-value.js +45 -0
- package/dist/behaviors/watch-field.d.ts +2 -0
- package/dist/behaviors/watch-field.js +21 -0
- package/dist/behaviors.js +26 -19
- package/dist/core/behavior/behavior-context.d.ts +27 -13
- package/dist/core/behavior/behavior-registry.d.ts +15 -27
- package/dist/core/behavior/behaviors/compute-from.d.ts +50 -21
- package/dist/core/behavior/behaviors/copy-from.d.ts +39 -14
- package/dist/core/behavior/behaviors/enable-when.d.ts +88 -19
- package/dist/core/behavior/behaviors/reset-when.d.ts +31 -18
- package/dist/core/behavior/behaviors/revalidate-when.d.ts +40 -17
- package/dist/core/behavior/behaviors/sync-fields.d.ts +34 -14
- package/dist/core/behavior/behaviors/transform-value.d.ts +116 -44
- package/dist/core/behavior/behaviors/watch-field.d.ts +66 -21
- package/dist/core/behavior/compose-behavior.d.ts +2 -12
- package/dist/core/behavior/index.d.ts +0 -1
- package/dist/core/behavior/types.d.ts +2 -8
- package/dist/core/factories/node-factory.d.ts +6 -29
- package/dist/core/nodes/array-node.d.ts +42 -22
- package/dist/core/nodes/field-node.d.ts +51 -26
- package/dist/core/nodes/form-node.d.ts +18 -20
- package/dist/core/nodes/group-node.d.ts +26 -22
- package/dist/core/types/deep-schema.d.ts +2 -12
- package/dist/core/types/field-path.d.ts +1 -1
- package/dist/core/types/form-context.d.ts +27 -27
- package/dist/core/types/{group-node-proxy.d.ts → form-proxy.d.ts} +12 -42
- package/dist/core/types/index.d.ts +52 -6
- package/dist/core/types/validation-schema.d.ts +3 -12
- package/dist/core/utils/abstract-registry.d.ts +74 -0
- package/dist/core/utils/aggregate-signals.d.ts +71 -0
- package/dist/core/utils/create-form.d.ts +3 -20
- package/dist/core/utils/error-handler.d.ts +1 -18
- package/dist/core/utils/field-path-navigator.d.ts +1 -1
- package/dist/core/utils/field-path.d.ts +23 -11
- package/dist/core/utils/form-observer.d.ts +176 -0
- package/dist/core/utils/form-proxy-builder.d.ts +25 -0
- package/dist/core/utils/form-submitter.d.ts +121 -0
- package/dist/core/utils/index.d.ts +9 -2
- package/dist/core/utils/registry-helpers.d.ts +0 -7
- package/dist/core/utils/safe-effect.d.ts +73 -0
- package/dist/core/utils/status-machine.d.ts +153 -0
- package/dist/core/utils/type-guards.d.ts +5 -23
- package/dist/core/utils/unique-id.d.ts +53 -0
- package/dist/core/validation/core/apply-when.d.ts +3 -9
- package/dist/core/validation/core/apply.d.ts +2 -13
- package/dist/core/validation/core/validate-async.d.ts +2 -8
- package/dist/core/validation/core/validate-tree.d.ts +0 -6
- package/dist/core/validation/core/validate.d.ts +1 -7
- package/dist/core/validation/index.d.ts +8 -2
- package/dist/core/validation/validate-form.d.ts +1 -38
- package/dist/core/validation/validation-applicator.d.ts +2 -21
- package/dist/core/validation/validation-context.d.ts +59 -43
- package/dist/core/validation/validation-registry.d.ts +11 -25
- package/dist/core/validation/validators/array-validators.d.ts +2 -12
- package/dist/core/validation/validators/date-utils.d.ts +26 -0
- package/dist/core/validation/validators/email.d.ts +2 -9
- package/dist/core/validation/validators/future-date.d.ts +35 -0
- package/dist/core/validation/validators/index.d.ts +7 -1
- package/dist/core/validation/validators/is-date.d.ts +36 -0
- package/dist/core/validation/validators/max-age.d.ts +36 -0
- package/dist/core/validation/validators/max-date.d.ts +36 -0
- package/dist/core/validation/validators/max-length.d.ts +3 -10
- package/dist/core/validation/validators/max.d.ts +3 -10
- package/dist/core/validation/validators/min-age.d.ts +36 -0
- package/dist/core/validation/validators/min-date.d.ts +36 -0
- package/dist/core/validation/validators/min-length.d.ts +3 -10
- package/dist/core/validation/validators/min.d.ts +3 -10
- package/dist/core/validation/validators/number.d.ts +2 -9
- package/dist/core/validation/validators/past-date.d.ts +35 -0
- package/dist/core/validation/validators/pattern.d.ts +2 -9
- package/dist/core/validation/validators/phone.d.ts +2 -9
- package/dist/core/validation/validators/required.d.ts +2 -9
- package/dist/core/validation/validators/url.d.ts +2 -9
- package/dist/date-utils-xUWFslTj.js +29 -0
- package/dist/field-path-DuKdGcIE.js +66 -0
- package/dist/hooks/types.d.ts +1 -1
- package/dist/hooks/useArrayLength.d.ts +31 -0
- package/dist/hooks/useFormControl.d.ts +4 -4
- package/dist/hooks/useFormControlValue.d.ts +2 -2
- package/dist/hooks/useHiddenCondition.d.ts +25 -0
- package/dist/hooks/useSignalSubscription.d.ts +1 -1
- package/dist/index-D25LsbRm.js +73 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1171 -786
- package/dist/registry-helpers-Bv_BJ1s-.js +615 -0
- package/dist/safe-effect-Dh8uw81c.js +20 -0
- package/dist/validate-C3XiA_zf.js +10 -0
- package/dist/validators/email.d.ts +2 -0
- package/dist/validators/email.js +13 -0
- package/dist/validators/future-date.d.ts +2 -0
- package/dist/validators/future-date.js +20 -0
- package/dist/validators/is-date.d.ts +2 -0
- package/dist/validators/is-date.js +12 -0
- package/dist/validators/max-age.d.ts +2 -0
- package/dist/validators/max-age.js +20 -0
- package/dist/validators/max-date.d.ts +2 -0
- package/dist/validators/max-date.js +20 -0
- package/dist/validators/max-length.d.ts +2 -0
- package/dist/validators/max-length.js +11 -0
- package/dist/validators/max.d.ts +2 -0
- package/dist/validators/max.js +11 -0
- package/dist/validators/min-age.d.ts +2 -0
- package/dist/validators/min-age.js +20 -0
- package/dist/validators/min-date.d.ts +2 -0
- package/dist/validators/min-date.js +20 -0
- package/dist/validators/min-length.d.ts +2 -0
- package/dist/validators/min-length.js +11 -0
- package/dist/validators/min.d.ts +2 -0
- package/dist/validators/min.js +11 -0
- package/dist/validators/number.d.ts +2 -0
- package/dist/validators/number.js +35 -0
- package/dist/validators/past-date.d.ts +2 -0
- package/dist/validators/past-date.js +20 -0
- package/dist/validators/pattern.d.ts +2 -0
- package/dist/validators/pattern.js +11 -0
- package/dist/validators/phone.d.ts +2 -0
- package/dist/validators/phone.js +35 -0
- package/dist/validators/required.d.ts +2 -0
- package/dist/validators/required.js +15 -0
- package/dist/validators/url.d.ts +2 -0
- package/dist/validators/url.js +19 -0
- package/dist/validators-BGsNOgT1.js +207 -0
- package/dist/validators.js +54 -29
- package/llms.txt +7885 -318
- package/package.json +83 -8
- package/dist/behaviors-DzYL8kY_.js +0 -499
- package/dist/core/behavior/create-field-path.d.ts +0 -7
- package/dist/core/context/form-context-impl.d.ts +0 -29
- package/dist/core/utils/debounce.d.ts +0 -160
- package/dist/core/utils/resources.d.ts +0 -41
- package/dist/core/validation/field-path.d.ts +0 -7
- package/dist/core/validation/validators/date.d.ts +0 -38
- package/dist/registry-helpers-BRxAr6nG.js +0 -490
- package/dist/validators-gXoHPdqM.js +0 -418
package/dist/index.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
|
|
1
|
+
import { signal as g, computed as d, effect as m, batch as j } from "@preact/signals-core";
|
|
2
|
+
import { F as S, E as V, V as K, B as H } from "./registry-helpers-Bv_BJ1s-.js";
|
|
3
|
+
import { A as ke, R as xe, b as Fe, g as Te } from "./registry-helpers-Bv_BJ1s-.js";
|
|
4
|
+
import { i as M, a as N, A as z, V as J, T as Y } from "./validators-BGsNOgT1.js";
|
|
5
|
+
import { g as Pe, c as Ce, d as De, v as Re, b as Me } from "./validators-BGsNOgT1.js";
|
|
6
|
+
import { c as I } from "./field-path-DuKdGcIE.js";
|
|
7
|
+
import { a as Ie, e as Le, t as Be } from "./field-path-DuKdGcIE.js";
|
|
8
|
+
import U, { useRef as P, useCallback as b, useSyncExternalStore as Q } from "react";
|
|
9
|
+
import { i as $e } from "./index-D25LsbRm.js";
|
|
10
|
+
import { r as We, s as qe, a as je } from "./safe-effect-Dh8uw81c.js";
|
|
11
|
+
class C {
|
|
10
12
|
// ============================================================================
|
|
11
13
|
// Protected состояние (для Template Method паттерна)
|
|
12
14
|
// ============================================================================
|
|
@@ -14,17 +16,17 @@ class O {
|
|
|
14
16
|
* Пользователь взаимодействовал с узлом (touched)
|
|
15
17
|
* Protected: наследники могут читать/изменять через методы
|
|
16
18
|
*/
|
|
17
|
-
_touched =
|
|
19
|
+
_touched = g(!1);
|
|
18
20
|
/**
|
|
19
21
|
* Значение узла было изменено (dirty)
|
|
20
22
|
* Protected: наследники могут читать/изменять через методы
|
|
21
23
|
*/
|
|
22
|
-
_dirty =
|
|
24
|
+
_dirty = g(!1);
|
|
23
25
|
/**
|
|
24
26
|
* Текущий статус узла
|
|
25
27
|
* Protected: наследники могут читать/изменять через методы
|
|
26
28
|
*/
|
|
27
|
-
_status =
|
|
29
|
+
_status = g("valid");
|
|
28
30
|
// ============================================================================
|
|
29
31
|
// Публичные computed signals (readonly для внешнего мира)
|
|
30
32
|
// ============================================================================
|
|
@@ -32,33 +34,33 @@ class O {
|
|
|
32
34
|
* Пользователь взаимодействовал с узлом (touched)
|
|
33
35
|
* Computed из _touched для предоставления readonly интерфейса
|
|
34
36
|
*/
|
|
35
|
-
touched =
|
|
37
|
+
touched = d(() => this._touched.value);
|
|
36
38
|
/**
|
|
37
39
|
* Пользователь не взаимодействовал с узлом (untouched)
|
|
38
40
|
*/
|
|
39
|
-
untouched =
|
|
41
|
+
untouched = d(() => !this._touched.value);
|
|
40
42
|
/**
|
|
41
43
|
* Значение узла было изменено (dirty)
|
|
42
44
|
* Computed из _dirty для предоставления readonly интерфейса
|
|
43
45
|
*/
|
|
44
|
-
dirty =
|
|
46
|
+
dirty = d(() => this._dirty.value);
|
|
45
47
|
/**
|
|
46
48
|
* Значение узла не было изменено (pristine)
|
|
47
49
|
*/
|
|
48
|
-
pristine =
|
|
50
|
+
pristine = d(() => !this._dirty.value);
|
|
49
51
|
/**
|
|
50
52
|
* Текущий статус узла
|
|
51
53
|
* Computed из _status для предоставления readonly интерфейса
|
|
52
54
|
*/
|
|
53
|
-
status =
|
|
55
|
+
status = d(() => this._status.value);
|
|
54
56
|
/**
|
|
55
57
|
* Узел отключен (disabled)
|
|
56
58
|
*/
|
|
57
|
-
disabled =
|
|
59
|
+
disabled = d(() => this._status.value === "disabled");
|
|
58
60
|
/**
|
|
59
61
|
* Узел включен (enabled)
|
|
60
62
|
*/
|
|
61
|
-
enabled =
|
|
63
|
+
enabled = d(() => this._status.value !== "disabled");
|
|
62
64
|
/**
|
|
63
65
|
* Получить ошибки валидации с фильтрацией
|
|
64
66
|
*
|
|
@@ -100,17 +102,17 @@ class O {
|
|
|
100
102
|
*/
|
|
101
103
|
getErrors(e) {
|
|
102
104
|
const t = this.errors.value;
|
|
103
|
-
return e ? t.filter((
|
|
104
|
-
if (e.code !== void 0 && !(Array.isArray(e.code) ? e.code : [e.code]).includes(
|
|
105
|
+
return e ? t.filter((s) => {
|
|
106
|
+
if (e.code !== void 0 && !(Array.isArray(e.code) ? e.code : [e.code]).includes(s.code) || e.message !== void 0 && !s.message.toLowerCase().includes(e.message.toLowerCase()))
|
|
105
107
|
return !1;
|
|
106
108
|
if (e.params !== void 0) {
|
|
107
|
-
if (!
|
|
109
|
+
if (!s.params)
|
|
108
110
|
return !1;
|
|
109
|
-
for (const [
|
|
110
|
-
if (
|
|
111
|
+
for (const [i, r] of Object.entries(e.params))
|
|
112
|
+
if (s.params[i] !== r)
|
|
111
113
|
return !1;
|
|
112
114
|
}
|
|
113
|
-
return !(e.predicate !== void 0 && !e.predicate(
|
|
115
|
+
return !(e.predicate !== void 0 && !e.predicate(s));
|
|
114
116
|
}) : t;
|
|
115
117
|
}
|
|
116
118
|
// ============================================================================
|
|
@@ -283,7 +285,7 @@ class O {
|
|
|
283
285
|
onEnable() {
|
|
284
286
|
}
|
|
285
287
|
}
|
|
286
|
-
class
|
|
288
|
+
class D {
|
|
287
289
|
/**
|
|
288
290
|
* Хранилище подписок
|
|
289
291
|
* Ключ: уникальный идентификатор подписки
|
|
@@ -451,157 +453,196 @@ class P {
|
|
|
451
453
|
this.clear();
|
|
452
454
|
}
|
|
453
455
|
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
+
const w = {
|
|
457
|
+
/** FieldNode.watch() */
|
|
458
|
+
Watch: "watch",
|
|
459
|
+
/** FieldNode.computeFrom() */
|
|
460
|
+
ComputeFrom: "computeFrom",
|
|
461
|
+
/** GroupNode.linkFields() */
|
|
462
|
+
LinkFields: "linkFields",
|
|
463
|
+
/** GroupNode.watchField() */
|
|
464
|
+
WatchField: "watchField",
|
|
465
|
+
/** ArrayNode.watchItems() */
|
|
466
|
+
WatchItems: "watchItems",
|
|
467
|
+
/** ArrayNode.watchLength() */
|
|
468
|
+
WatchLength: "watchLength"
|
|
469
|
+
};
|
|
470
|
+
let X = 0;
|
|
471
|
+
function A(a) {
|
|
472
|
+
return `${a}-${++X}`;
|
|
473
|
+
}
|
|
474
|
+
class Z {
|
|
475
|
+
/** Внутренний сигнал статуса */
|
|
476
|
+
_status;
|
|
477
|
+
/** Публичный read-only сигнал статуса */
|
|
478
|
+
status;
|
|
479
|
+
/** Поле валидно */
|
|
480
|
+
valid;
|
|
481
|
+
/** Поле невалидно */
|
|
482
|
+
invalid;
|
|
483
|
+
/** Идет валидация */
|
|
484
|
+
pending;
|
|
485
|
+
/** Поле отключено */
|
|
486
|
+
disabled;
|
|
456
487
|
/**
|
|
457
|
-
*
|
|
488
|
+
* @param initial - Начальный статус (по умолчанию 'valid')
|
|
489
|
+
*/
|
|
490
|
+
constructor(e = "valid") {
|
|
491
|
+
this._status = g(e), this.status = d(() => this._status.value), this.valid = d(() => this._status.value === "valid"), this.invalid = d(() => this._status.value === "invalid"), this.pending = d(() => this._status.value === "pending"), this.disabled = d(() => this._status.value === "disabled");
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Начать валидацию
|
|
458
495
|
*
|
|
459
|
-
*
|
|
460
|
-
* @param context Контекст ошибки для логирования (например, 'AsyncValidator', 'BehaviorRegistry')
|
|
461
|
-
* @param strategy Стратегия обработки (THROW | LOG | CONVERT)
|
|
462
|
-
* @returns ValidationError если strategy = CONVERT, undefined если strategy = LOG, никогда не возвращается если strategy = THROW
|
|
496
|
+
* Переводит статус в 'pending' если поле не отключено
|
|
463
497
|
*
|
|
464
498
|
* @example
|
|
465
499
|
* ```typescript
|
|
466
|
-
*
|
|
467
|
-
*
|
|
468
|
-
*
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
500
|
+
* statusMachine.startValidation();
|
|
501
|
+
* // status: 'pending'
|
|
502
|
+
* ```
|
|
503
|
+
*/
|
|
504
|
+
startValidation() {
|
|
505
|
+
this._status.value !== "disabled" && (this._status.value = "pending");
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Завершить валидацию
|
|
473
509
|
*
|
|
474
|
-
*
|
|
475
|
-
* try {
|
|
476
|
-
* nonCriticalOperation();
|
|
477
|
-
* } catch (error) {
|
|
478
|
-
* FormErrorHandler.handle(error, 'NonCritical', ErrorStrategy.LOG);
|
|
479
|
-
* // Продолжаем выполнение
|
|
480
|
-
* }
|
|
510
|
+
* @param hasErrors - Есть ли ошибки валидации
|
|
481
511
|
*
|
|
482
|
-
*
|
|
483
|
-
*
|
|
484
|
-
*
|
|
485
|
-
*
|
|
486
|
-
*
|
|
487
|
-
*
|
|
488
|
-
*
|
|
489
|
-
*
|
|
490
|
-
*
|
|
491
|
-
* return validationError;
|
|
492
|
-
* }
|
|
512
|
+
* @example
|
|
513
|
+
* ```typescript
|
|
514
|
+
* // Валидация успешна
|
|
515
|
+
* statusMachine.completeValidation(false);
|
|
516
|
+
* // status: 'valid'
|
|
517
|
+
*
|
|
518
|
+
* // Есть ошибки
|
|
519
|
+
* statusMachine.completeValidation(true);
|
|
520
|
+
* // status: 'invalid'
|
|
493
521
|
* ```
|
|
494
522
|
*/
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
switch (i) {
|
|
498
|
-
case "throw":
|
|
499
|
-
throw e;
|
|
500
|
-
case "log":
|
|
501
|
-
return;
|
|
502
|
-
case "convert":
|
|
503
|
-
return {
|
|
504
|
-
code: "validator_error",
|
|
505
|
-
message: s,
|
|
506
|
-
params: { field: t }
|
|
507
|
-
};
|
|
508
|
-
}
|
|
523
|
+
completeValidation(e) {
|
|
524
|
+
(this._status.value === "pending" || this._status.value !== "disabled") && (this._status.value = e ? "invalid" : "valid");
|
|
509
525
|
}
|
|
510
526
|
/**
|
|
511
|
-
*
|
|
527
|
+
* Установить ошибки напрямую (без перехода через pending)
|
|
512
528
|
*
|
|
513
|
-
*
|
|
514
|
-
* - Error объекты → error.message
|
|
515
|
-
* - Строки → возвращает как есть
|
|
516
|
-
* - Объекты с message → извлекает message
|
|
517
|
-
* - Другое → String(error)
|
|
529
|
+
* Используется для синхронной валидации или установки ошибок извне
|
|
518
530
|
*
|
|
519
|
-
* @param
|
|
520
|
-
* @returns Сообщение ошибки
|
|
521
|
-
* @private
|
|
531
|
+
* @param hasErrors - Есть ли ошибки
|
|
522
532
|
*
|
|
523
533
|
* @example
|
|
524
534
|
* ```typescript
|
|
525
|
-
*
|
|
526
|
-
* // '
|
|
527
|
-
*
|
|
528
|
-
|
|
529
|
-
|
|
535
|
+
* statusMachine.setErrors(true);
|
|
536
|
+
* // status: 'invalid'
|
|
537
|
+
* ```
|
|
538
|
+
*/
|
|
539
|
+
setErrors(e) {
|
|
540
|
+
this._status.value !== "disabled" && (this._status.value = e ? "invalid" : "valid");
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Отключить поле
|
|
530
544
|
*
|
|
531
|
-
*
|
|
532
|
-
* // 'Object error'
|
|
545
|
+
* Переводит статус в 'disabled'
|
|
533
546
|
*
|
|
534
|
-
*
|
|
535
|
-
*
|
|
547
|
+
* @example
|
|
548
|
+
* ```typescript
|
|
549
|
+
* statusMachine.disable();
|
|
550
|
+
* // status: 'disabled'
|
|
536
551
|
* ```
|
|
537
552
|
*/
|
|
538
|
-
|
|
539
|
-
|
|
553
|
+
disable() {
|
|
554
|
+
this._status.value = "disabled";
|
|
540
555
|
}
|
|
541
556
|
/**
|
|
542
|
-
*
|
|
543
|
-
*
|
|
544
|
-
* Утилитная функция для создания ValidationError объектов
|
|
557
|
+
* Включить поле
|
|
545
558
|
*
|
|
546
|
-
* @param
|
|
547
|
-
* @param message Сообщение ошибки
|
|
548
|
-
* @param field Поле (опционально)
|
|
549
|
-
* @returns ValidationError объект
|
|
559
|
+
* @param hasErrors - Есть ли ошибки (определяет valid/invalid)
|
|
550
560
|
*
|
|
551
561
|
* @example
|
|
552
562
|
* ```typescript
|
|
553
|
-
*
|
|
554
|
-
*
|
|
555
|
-
*
|
|
556
|
-
*
|
|
557
|
-
*
|
|
558
|
-
* // { code: 'required', message: 'This field is required', field: 'email' }
|
|
563
|
+
* statusMachine.enable(false);
|
|
564
|
+
* // status: 'valid'
|
|
565
|
+
*
|
|
566
|
+
* statusMachine.enable(true);
|
|
567
|
+
* // status: 'invalid'
|
|
559
568
|
* ```
|
|
560
569
|
*/
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
code: e,
|
|
564
|
-
message: t,
|
|
565
|
-
params: i ? { field: i } : void 0
|
|
566
|
-
};
|
|
570
|
+
enable(e = !1) {
|
|
571
|
+
this._status.value = e ? "invalid" : "valid";
|
|
567
572
|
}
|
|
568
573
|
/**
|
|
569
|
-
*
|
|
570
|
-
*
|
|
571
|
-
* Type guard для ValidationError
|
|
574
|
+
* Обработать событие (альтернативный API)
|
|
572
575
|
*
|
|
573
|
-
* @param
|
|
574
|
-
* @returns true если value является ValidationError
|
|
576
|
+
* @param event - Событие для обработки
|
|
575
577
|
*
|
|
576
578
|
* @example
|
|
577
579
|
* ```typescript
|
|
578
|
-
*
|
|
579
|
-
*
|
|
580
|
-
* }
|
|
580
|
+
* statusMachine.dispatch({ type: 'START_VALIDATION' });
|
|
581
|
+
* statusMachine.dispatch({ type: 'VALIDATION_FAILURE' });
|
|
581
582
|
* ```
|
|
582
583
|
*/
|
|
583
|
-
|
|
584
|
-
|
|
584
|
+
dispatch(e) {
|
|
585
|
+
switch (e.type) {
|
|
586
|
+
case "START_VALIDATION":
|
|
587
|
+
this.startValidation();
|
|
588
|
+
break;
|
|
589
|
+
case "VALIDATION_SUCCESS":
|
|
590
|
+
this.completeValidation(!1);
|
|
591
|
+
break;
|
|
592
|
+
case "VALIDATION_FAILURE":
|
|
593
|
+
this.completeValidation(!0);
|
|
594
|
+
break;
|
|
595
|
+
case "DISABLE":
|
|
596
|
+
this.disable();
|
|
597
|
+
break;
|
|
598
|
+
case "ENABLE":
|
|
599
|
+
this.enable(e.hasErrors);
|
|
600
|
+
break;
|
|
601
|
+
case "SET_ERRORS":
|
|
602
|
+
this.setErrors(e.hasErrors);
|
|
603
|
+
break;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
/**
|
|
607
|
+
* Получить текущий статус
|
|
608
|
+
*/
|
|
609
|
+
getStatus() {
|
|
610
|
+
return this._status.value;
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Проверить, можно ли начать валидацию
|
|
614
|
+
*/
|
|
615
|
+
canValidate() {
|
|
616
|
+
return this._status.value !== "disabled";
|
|
585
617
|
}
|
|
586
618
|
}
|
|
587
|
-
class
|
|
619
|
+
class ee extends C {
|
|
588
620
|
// ============================================================================
|
|
589
621
|
// Приватные сигналы
|
|
590
622
|
// ============================================================================
|
|
591
623
|
_value;
|
|
592
624
|
_errors;
|
|
593
|
-
// _touched, _dirty
|
|
594
|
-
|
|
625
|
+
// _touched, _dirty наследуются от FormNode (protected)
|
|
626
|
+
// _status управляется через statusMachine
|
|
595
627
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
596
628
|
_componentProps;
|
|
629
|
+
/**
|
|
630
|
+
* State machine для управления статусом поля
|
|
631
|
+
* Централизует логику переходов между valid/invalid/pending/disabled
|
|
632
|
+
*/
|
|
633
|
+
statusMachine;
|
|
597
634
|
// ============================================================================
|
|
598
635
|
// Публичные computed signals
|
|
599
636
|
// ============================================================================
|
|
600
637
|
value;
|
|
638
|
+
// valid, invalid, pending, status, disabled берутся из statusMachine
|
|
601
639
|
valid;
|
|
602
640
|
invalid;
|
|
603
|
-
// touched, dirty, status наследуются от FormNode
|
|
604
641
|
pending;
|
|
642
|
+
// Override status и disabled из базового класса
|
|
643
|
+
status;
|
|
644
|
+
disabled;
|
|
645
|
+
// touched, dirty наследуются от FormNode
|
|
605
646
|
errors;
|
|
606
647
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
607
648
|
componentProps;
|
|
@@ -617,22 +658,26 @@ class J extends O {
|
|
|
617
658
|
asyncValidators;
|
|
618
659
|
updateOn;
|
|
619
660
|
initialValue;
|
|
620
|
-
|
|
661
|
+
currentAbortController;
|
|
621
662
|
debounceMs;
|
|
622
663
|
validateDebounceTimer;
|
|
623
|
-
|
|
664
|
+
/**
|
|
665
|
+
* Pending debounced validation state
|
|
666
|
+
* Contains resolve function and AbortController for cancellation
|
|
667
|
+
*/
|
|
668
|
+
pendingValidation;
|
|
624
669
|
/**
|
|
625
670
|
* Менеджер подписок для централизованного cleanup
|
|
626
671
|
* Использует SubscriptionManager вместо массива для управления подписками
|
|
627
672
|
*/
|
|
628
|
-
disposers = new
|
|
673
|
+
disposers = new D();
|
|
629
674
|
component;
|
|
630
675
|
// ============================================================================
|
|
631
676
|
// Конструктор
|
|
632
677
|
// ============================================================================
|
|
633
678
|
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 =
|
|
635
|
-
() => this.
|
|
679
|
+
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 = g(e.value), this._errors = g([]), this._componentProps = g(e.componentProps || {}), this.statusMachine = new Z(e.disabled ? "disabled" : "valid"), this.value = d(() => this._value.value), this.valid = d(() => this.statusMachine.valid.value), this.invalid = d(() => this.statusMachine.invalid.value), this.pending = d(() => this.statusMachine.pending.value), this.status = d(() => this.statusMachine.status.value), this.disabled = d(() => this.statusMachine.disabled.value), this.errors = d(() => this._errors.value), this.componentProps = d(() => this._componentProps.value), this.shouldShowError = d(
|
|
680
|
+
() => this.statusMachine.invalid.value && (this._touched.value || this._dirty.value)
|
|
636
681
|
);
|
|
637
682
|
}
|
|
638
683
|
// ============================================================================
|
|
@@ -644,12 +689,12 @@ class J extends O {
|
|
|
644
689
|
setValue(e, t) {
|
|
645
690
|
if (this._value.value = e, this._dirty.value = !0, t?.emitEvent === !1)
|
|
646
691
|
return;
|
|
647
|
-
const
|
|
692
|
+
const s = this.validators.length > 0 || this.asyncValidators.length > 0, i = this._errors.value.length > 0;
|
|
648
693
|
if (this.updateOn === "change") {
|
|
649
694
|
this.validate();
|
|
650
695
|
return;
|
|
651
696
|
}
|
|
652
|
-
|
|
697
|
+
i && s && this.validate();
|
|
653
698
|
}
|
|
654
699
|
patchValue(e) {
|
|
655
700
|
this.setValue(e);
|
|
@@ -678,7 +723,7 @@ class J extends O {
|
|
|
678
723
|
* ```
|
|
679
724
|
*/
|
|
680
725
|
reset(e) {
|
|
681
|
-
this._value.value = e !== void 0 ? e : this.initialValue, this._errors.value = [], this._touched.value = !1, this._dirty.value = !1, this.
|
|
726
|
+
this._value.value = e !== void 0 ? e : this.initialValue, this._errors.value = [], this._touched.value = !1, this._dirty.value = !1, this.statusMachine.setErrors(!1);
|
|
682
727
|
}
|
|
683
728
|
/**
|
|
684
729
|
* Сбросить поле к исходному значению (initialValue)
|
|
@@ -708,13 +753,25 @@ class J extends O {
|
|
|
708
753
|
resetToInitial() {
|
|
709
754
|
this.reset(this.initialValue);
|
|
710
755
|
}
|
|
756
|
+
/**
|
|
757
|
+
* Cancel any pending validation (debounced or running)
|
|
758
|
+
* @private
|
|
759
|
+
* @remarks
|
|
760
|
+
* Centralizes all cancellation logic:
|
|
761
|
+
* - Aborts pending debounced validation and resolves its promise
|
|
762
|
+
* - Clears debounce timer
|
|
763
|
+
* - Aborts currently running async validation
|
|
764
|
+
*/
|
|
765
|
+
cancelPendingValidation() {
|
|
766
|
+
this.pendingValidation && (this.pendingValidation.abortController.abort(), this.pendingValidation.resolve(!1), this.pendingValidation = void 0), this.validateDebounceTimer && (clearTimeout(this.validateDebounceTimer), this.validateDebounceTimer = void 0), this.currentAbortController && (this.currentAbortController.abort(), this.currentAbortController = void 0);
|
|
767
|
+
}
|
|
711
768
|
/**
|
|
712
769
|
* Запустить валидацию поля
|
|
713
770
|
* @param options - опции валидации
|
|
714
771
|
* @returns `Promise<boolean>` - true если поле валидно
|
|
715
772
|
*
|
|
716
773
|
* @remarks
|
|
717
|
-
* Метод защищен от race conditions через
|
|
774
|
+
* Метод защищен от race conditions через AbortController.
|
|
718
775
|
* При быстром вводе только последняя валидация применяет результаты.
|
|
719
776
|
*
|
|
720
777
|
* @example
|
|
@@ -728,69 +785,102 @@ class J extends O {
|
|
|
728
785
|
*/
|
|
729
786
|
async validate(e) {
|
|
730
787
|
const t = e?.debounce ?? this.debounceMs;
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
788
|
+
if (this.cancelPendingValidation(), t <= 0 || this.asyncValidators.length === 0)
|
|
789
|
+
return this.validateImmediate();
|
|
790
|
+
const s = new AbortController();
|
|
791
|
+
return new Promise((i) => {
|
|
792
|
+
this.pendingValidation = { resolve: i, abortController: s }, this.validateDebounceTimer = setTimeout(async () => {
|
|
793
|
+
if (this.validateDebounceTimer = void 0, s.signal.aborted) {
|
|
735
794
|
i(!1);
|
|
736
795
|
return;
|
|
737
796
|
}
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
797
|
+
this.pendingValidation = void 0;
|
|
798
|
+
const r = await this.validateImmediate(s);
|
|
799
|
+
i(r);
|
|
800
|
+
}, t), s.signal.addEventListener(
|
|
801
|
+
"abort",
|
|
802
|
+
() => {
|
|
803
|
+
this.validateDebounceTimer && (clearTimeout(this.validateDebounceTimer), this.validateDebounceTimer = void 0), i(!1);
|
|
804
|
+
},
|
|
805
|
+
{ once: !0 }
|
|
806
|
+
);
|
|
807
|
+
});
|
|
742
808
|
}
|
|
743
809
|
/**
|
|
744
810
|
* Немедленная валидация без debounce
|
|
745
811
|
* @private
|
|
812
|
+
* @param providedController - AbortController from debounced validate()
|
|
746
813
|
* @remarks
|
|
747
|
-
* Защищена от race conditions:
|
|
748
|
-
* -
|
|
749
|
-
* -
|
|
750
|
-
* -
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
const
|
|
756
|
-
for (const
|
|
757
|
-
const
|
|
758
|
-
|
|
814
|
+
* Защищена от race conditions через AbortController:
|
|
815
|
+
* - Отменяет предыдущую валидацию при запуске новой (if no controller provided)
|
|
816
|
+
* - Передаёт AbortSignal в async валидаторы для отмены операций (например, fetch)
|
|
817
|
+
* - Проверяет signal.aborted в ключевых точках
|
|
818
|
+
*/
|
|
819
|
+
async validateImmediate(e) {
|
|
820
|
+
const t = e ?? new AbortController();
|
|
821
|
+
e || this.currentAbortController?.abort(), this.currentAbortController = t;
|
|
822
|
+
const { signal: s } = t, i = [];
|
|
823
|
+
for (const n of this.validators) {
|
|
824
|
+
const o = n(this._value.value);
|
|
825
|
+
o && i.push(o);
|
|
759
826
|
}
|
|
760
|
-
if (
|
|
827
|
+
if (s.aborted)
|
|
761
828
|
return !1;
|
|
762
|
-
if (
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
if (
|
|
829
|
+
if (i.length > 0) {
|
|
830
|
+
this._errors.value = i;
|
|
831
|
+
const n = i.some((o) => o.severity !== "warning");
|
|
832
|
+
if (this.statusMachine.setErrors(n), n)
|
|
766
833
|
return !1;
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
try {
|
|
771
|
-
return await o(this._value.value);
|
|
772
|
-
} catch (n) {
|
|
773
|
-
return F.handle(
|
|
774
|
-
n,
|
|
775
|
-
"FieldNode AsyncValidator",
|
|
776
|
-
w.CONVERT
|
|
777
|
-
);
|
|
778
|
-
}
|
|
779
|
-
})
|
|
780
|
-
);
|
|
781
|
-
if (e !== this.currentValidationId || (this._pending.value = !1, e !== this.currentValidationId))
|
|
834
|
+
}
|
|
835
|
+
if (this.asyncValidators.length > 0) {
|
|
836
|
+
if (s.aborted)
|
|
782
837
|
return !1;
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
838
|
+
this.statusMachine.startValidation();
|
|
839
|
+
try {
|
|
840
|
+
const n = await Promise.all(
|
|
841
|
+
this.asyncValidators.map(async (l) => {
|
|
842
|
+
if (s.aborted)
|
|
843
|
+
throw new DOMException("Validation aborted", "AbortError");
|
|
844
|
+
try {
|
|
845
|
+
const u = await l(this._value.value, { signal: s });
|
|
846
|
+
if (s.aborted)
|
|
847
|
+
throw new DOMException("Validation aborted", "AbortError");
|
|
848
|
+
return u;
|
|
849
|
+
} catch (u) {
|
|
850
|
+
if (u instanceof DOMException && u.name === "AbortError")
|
|
851
|
+
throw u;
|
|
852
|
+
return S.handle(
|
|
853
|
+
u,
|
|
854
|
+
"FieldNode AsyncValidator",
|
|
855
|
+
V.CONVERT
|
|
856
|
+
);
|
|
857
|
+
}
|
|
858
|
+
})
|
|
859
|
+
);
|
|
860
|
+
if (s.aborted)
|
|
861
|
+
return !1;
|
|
862
|
+
const o = n.filter(Boolean);
|
|
863
|
+
if (o.length > 0) {
|
|
864
|
+
this._errors.value = o;
|
|
865
|
+
const l = o.some((u) => u.severity !== "warning");
|
|
866
|
+
if (this.statusMachine.completeValidation(l), l)
|
|
867
|
+
return !1;
|
|
868
|
+
}
|
|
869
|
+
} catch (n) {
|
|
870
|
+
if (n instanceof DOMException && n.name === "AbortError")
|
|
871
|
+
return !1;
|
|
872
|
+
throw n;
|
|
873
|
+
}
|
|
786
874
|
}
|
|
787
|
-
return
|
|
875
|
+
return s.aborted ? !1 : ((this.validators.length > 0 || this.asyncValidators.length > 0) && (this._errors.value = [], this.statusMachine.completeValidation(!1)), !this._errors.value.some((n) => n.severity !== "warning"));
|
|
788
876
|
}
|
|
789
877
|
setErrors(e) {
|
|
790
|
-
this._errors.value = e
|
|
878
|
+
this._errors.value = e;
|
|
879
|
+
const t = e.some((s) => s.severity !== "warning");
|
|
880
|
+
this.statusMachine.setErrors(t);
|
|
791
881
|
}
|
|
792
882
|
clearErrors() {
|
|
793
|
-
this._errors.value = [], this.
|
|
883
|
+
this._errors.value = [], this.statusMachine.setErrors(!1);
|
|
794
884
|
}
|
|
795
885
|
// ============================================================================
|
|
796
886
|
// Protected hooks (Template Method pattern)
|
|
@@ -806,18 +896,18 @@ class J extends O {
|
|
|
806
896
|
/**
|
|
807
897
|
* Hook: вызывается после disable()
|
|
808
898
|
*
|
|
809
|
-
* Для FieldNode: очищаем ошибки
|
|
899
|
+
* Для FieldNode: синхронизируем statusMachine и очищаем ошибки
|
|
810
900
|
*/
|
|
811
901
|
onDisable() {
|
|
812
|
-
this._errors.value = [];
|
|
902
|
+
this.statusMachine.disable(), this._errors.value = [];
|
|
813
903
|
}
|
|
814
904
|
/**
|
|
815
905
|
* Hook: вызывается после enable()
|
|
816
906
|
*
|
|
817
|
-
* Для FieldNode: запускаем валидацию
|
|
907
|
+
* Для FieldNode: синхронизируем statusMachine и запускаем валидацию
|
|
818
908
|
*/
|
|
819
909
|
onEnable() {
|
|
820
|
-
this.validate();
|
|
910
|
+
this.statusMachine.enable(this._errors.value.length > 0), this.validate();
|
|
821
911
|
}
|
|
822
912
|
/**
|
|
823
913
|
* Обновляет свойства компонента (например, опции для Select)
|
|
@@ -882,25 +972,35 @@ class J extends O {
|
|
|
882
972
|
* Подписка на изменения значения поля
|
|
883
973
|
* Автоматически отслеживает изменения через @preact/signals effect
|
|
884
974
|
*
|
|
885
|
-
* @param callback - Функция, вызываемая при изменении
|
|
975
|
+
* @param callback - Функция, вызываемая при изменении значения.
|
|
976
|
+
* Для async операций передается AbortSignal во втором параметре.
|
|
886
977
|
* @returns Функция отписки для cleanup
|
|
887
978
|
*
|
|
888
979
|
* @example
|
|
889
980
|
* ```typescript
|
|
981
|
+
* // Синхронный callback
|
|
890
982
|
* const unsubscribe = form.email.watch((value) => {
|
|
891
983
|
* console.log('Email changed:', value);
|
|
892
984
|
* });
|
|
893
985
|
*
|
|
986
|
+
* // Асинхронный callback с поддержкой отмены
|
|
987
|
+
* const unsubscribe = form.email.watch(async (value, signal) => {
|
|
988
|
+
* const result = await fetch('/api/validate', { signal });
|
|
989
|
+
* // ...
|
|
990
|
+
* });
|
|
991
|
+
*
|
|
894
992
|
* // Cleanup
|
|
895
993
|
* useEffect(() => unsubscribe, []);
|
|
896
994
|
* ```
|
|
897
995
|
*/
|
|
898
996
|
watch(e) {
|
|
899
|
-
const t =
|
|
900
|
-
const
|
|
901
|
-
e(
|
|
902
|
-
}), i =
|
|
903
|
-
return this.disposers.add(i,
|
|
997
|
+
const t = new AbortController(), s = m(() => {
|
|
998
|
+
const r = this.value.value;
|
|
999
|
+
e(r, t.signal);
|
|
1000
|
+
}), i = A(w.Watch);
|
|
1001
|
+
return this.disposers.add(i, () => {
|
|
1002
|
+
t.abort(), s();
|
|
1003
|
+
});
|
|
904
1004
|
}
|
|
905
1005
|
/**
|
|
906
1006
|
* Вычисляемое значение из других полей
|
|
@@ -925,16 +1025,23 @@ class J extends O {
|
|
|
925
1025
|
* ```
|
|
926
1026
|
*/
|
|
927
1027
|
computeFrom(e, t) {
|
|
928
|
-
const
|
|
929
|
-
const
|
|
930
|
-
this.setValue(
|
|
931
|
-
}),
|
|
932
|
-
return this.disposers.add(
|
|
1028
|
+
const s = m(() => {
|
|
1029
|
+
const r = e.map((o) => o.value), n = t(...r);
|
|
1030
|
+
this.setValue(n, { emitEvent: !1 });
|
|
1031
|
+
}), i = A(w.ComputeFrom);
|
|
1032
|
+
return this.disposers.add(i, s);
|
|
933
1033
|
}
|
|
934
1034
|
/**
|
|
935
1035
|
* Очистить все ресурсы и таймеры
|
|
936
1036
|
* Должен вызываться при unmount компонента
|
|
937
1037
|
*
|
|
1038
|
+
* @remarks
|
|
1039
|
+
* Освобождает все ресурсы:
|
|
1040
|
+
* - Отписывает все subscriptions через SubscriptionManager
|
|
1041
|
+
* - Отменяет pending/running валидации через cancelPendingValidation()
|
|
1042
|
+
*
|
|
1043
|
+
* Использует try-finally для гарантированного cleanup даже при ошибках.
|
|
1044
|
+
*
|
|
938
1045
|
* @example
|
|
939
1046
|
* ```typescript
|
|
940
1047
|
* useEffect(() => {
|
|
@@ -945,10 +1052,14 @@ class J extends O {
|
|
|
945
1052
|
* ```
|
|
946
1053
|
*/
|
|
947
1054
|
dispose() {
|
|
948
|
-
|
|
1055
|
+
try {
|
|
1056
|
+
this.disposers.dispose();
|
|
1057
|
+
} finally {
|
|
1058
|
+
this.cancelPendingValidation();
|
|
1059
|
+
}
|
|
949
1060
|
}
|
|
950
1061
|
}
|
|
951
|
-
class
|
|
1062
|
+
class te {
|
|
952
1063
|
form;
|
|
953
1064
|
constructor(e) {
|
|
954
1065
|
this.form = e;
|
|
@@ -964,8 +1075,8 @@ class Y {
|
|
|
964
1075
|
* @param validators Зарегистрированные валидаторы
|
|
965
1076
|
*/
|
|
966
1077
|
async apply(e) {
|
|
967
|
-
const { validatorsByField: t, treeValidators:
|
|
968
|
-
await this.applyFieldValidators(t), this.applyTreeValidators(
|
|
1078
|
+
const { validatorsByField: t, treeValidators: s } = this.groupValidators(e);
|
|
1079
|
+
await this.applyFieldValidators(t), this.applyTreeValidators(s);
|
|
969
1080
|
}
|
|
970
1081
|
/**
|
|
971
1082
|
* Группировка валидаторов по типам
|
|
@@ -978,15 +1089,15 @@ class Y {
|
|
|
978
1089
|
* @returns Сгруппированные валидаторы
|
|
979
1090
|
*/
|
|
980
1091
|
groupValidators(e) {
|
|
981
|
-
const t = /* @__PURE__ */ new Map(),
|
|
982
|
-
for (const
|
|
983
|
-
if (
|
|
984
|
-
|
|
1092
|
+
const t = /* @__PURE__ */ new Map(), s = [];
|
|
1093
|
+
for (const i of e)
|
|
1094
|
+
if (i.type === "tree")
|
|
1095
|
+
s.push(i);
|
|
985
1096
|
else {
|
|
986
|
-
const
|
|
987
|
-
|
|
1097
|
+
const r = t.get(i.fieldPath) || [];
|
|
1098
|
+
r.push(i), t.set(i.fieldPath, r);
|
|
988
1099
|
}
|
|
989
|
-
return { validatorsByField: t, treeValidators:
|
|
1100
|
+
return { validatorsByField: t, treeValidators: s };
|
|
990
1101
|
}
|
|
991
1102
|
/**
|
|
992
1103
|
* Применение field валидаторов к полям
|
|
@@ -1000,37 +1111,44 @@ class Y {
|
|
|
1000
1111
|
* @param validatorsByField Валидаторы, сгруппированные по полям
|
|
1001
1112
|
*/
|
|
1002
1113
|
async applyFieldValidators(e) {
|
|
1003
|
-
for (const [t,
|
|
1004
|
-
const
|
|
1005
|
-
if (!
|
|
1114
|
+
for (const [t, s] of e) {
|
|
1115
|
+
const i = this.form.getFieldByPath(t);
|
|
1116
|
+
if (!i) {
|
|
1006
1117
|
console.warn(`Field ${t} not found in GroupNode`);
|
|
1007
1118
|
continue;
|
|
1008
1119
|
}
|
|
1009
|
-
if (!
|
|
1120
|
+
if (!M(i) && !N(i)) {
|
|
1010
1121
|
process.env.NODE_ENV !== "production" && console.warn(`Validation can only run on FieldNode or ArrayNode, skipping ${t}`);
|
|
1011
1122
|
continue;
|
|
1012
1123
|
}
|
|
1013
|
-
const
|
|
1014
|
-
let
|
|
1015
|
-
if (
|
|
1016
|
-
const
|
|
1017
|
-
|
|
1124
|
+
const r = [];
|
|
1125
|
+
let n;
|
|
1126
|
+
if (N(i)) {
|
|
1127
|
+
const o = i.getValue();
|
|
1128
|
+
n = new z(this.form, t, o);
|
|
1018
1129
|
} else
|
|
1019
|
-
|
|
1020
|
-
for (const
|
|
1021
|
-
if (!(
|
|
1130
|
+
n = new J(this.form, t, i);
|
|
1131
|
+
for (const o of s)
|
|
1132
|
+
if (!(o.condition && !this.checkCondition(o.condition)))
|
|
1022
1133
|
try {
|
|
1023
1134
|
let l = null;
|
|
1024
|
-
const
|
|
1025
|
-
|
|
1135
|
+
const u = n.value();
|
|
1136
|
+
if (o.type === "sync") {
|
|
1137
|
+
const v = o.validator;
|
|
1138
|
+
l = v(u, n);
|
|
1139
|
+
} else if (o.type === "async") {
|
|
1140
|
+
const v = o.validator;
|
|
1141
|
+
l = await v(u, n);
|
|
1142
|
+
}
|
|
1143
|
+
l && r.push(l);
|
|
1026
1144
|
} catch (l) {
|
|
1027
|
-
|
|
1145
|
+
S.handle(
|
|
1028
1146
|
l,
|
|
1029
1147
|
`ValidationApplicator: validator for ${t}`,
|
|
1030
|
-
|
|
1148
|
+
V.LOG
|
|
1031
1149
|
);
|
|
1032
1150
|
}
|
|
1033
|
-
|
|
1151
|
+
r.length > 0 ? i.setErrors(r) : i.clearErrors();
|
|
1034
1152
|
}
|
|
1035
1153
|
}
|
|
1036
1154
|
/**
|
|
@@ -1043,24 +1161,24 @@ class Y {
|
|
|
1043
1161
|
*/
|
|
1044
1162
|
applyTreeValidators(e) {
|
|
1045
1163
|
for (const t of e) {
|
|
1046
|
-
const
|
|
1164
|
+
const s = new Y(this.form);
|
|
1047
1165
|
if (!(t.condition && !this.checkCondition(t.condition)))
|
|
1048
1166
|
try {
|
|
1049
1167
|
if (t.type !== "tree")
|
|
1050
1168
|
continue;
|
|
1051
|
-
const
|
|
1052
|
-
if (
|
|
1053
|
-
const
|
|
1054
|
-
if (
|
|
1055
|
-
const o = this.form.getFieldByPath(String(
|
|
1056
|
-
if (o &&
|
|
1057
|
-
const
|
|
1058
|
-
o.setErrors([...
|
|
1169
|
+
const i = t.validator, r = i(s);
|
|
1170
|
+
if (r && t.options && "targetField" in t.options) {
|
|
1171
|
+
const n = t.options.targetField;
|
|
1172
|
+
if (n) {
|
|
1173
|
+
const o = this.form.getFieldByPath(String(n));
|
|
1174
|
+
if (o && M(o)) {
|
|
1175
|
+
const l = o.errors.value;
|
|
1176
|
+
o.setErrors([...l, r]);
|
|
1059
1177
|
}
|
|
1060
1178
|
}
|
|
1061
1179
|
}
|
|
1062
|
-
} catch (
|
|
1063
|
-
|
|
1180
|
+
} catch (i) {
|
|
1181
|
+
S.handle(i, "ValidationApplicator: tree validator", V.LOG);
|
|
1064
1182
|
}
|
|
1065
1183
|
}
|
|
1066
1184
|
}
|
|
@@ -1077,11 +1195,11 @@ class Y {
|
|
|
1077
1195
|
const t = this.form.getFieldByPath(e.fieldPath);
|
|
1078
1196
|
if (!t)
|
|
1079
1197
|
return !1;
|
|
1080
|
-
const
|
|
1081
|
-
return e.conditionFn(
|
|
1198
|
+
const s = t.value.value;
|
|
1199
|
+
return e.conditionFn(s);
|
|
1082
1200
|
}
|
|
1083
1201
|
}
|
|
1084
|
-
class
|
|
1202
|
+
class se {
|
|
1085
1203
|
/**
|
|
1086
1204
|
* Парсит путь в массив сегментов
|
|
1087
1205
|
*
|
|
@@ -1108,22 +1226,22 @@ class Q {
|
|
|
1108
1226
|
*/
|
|
1109
1227
|
parsePath(e) {
|
|
1110
1228
|
const t = [];
|
|
1111
|
-
let
|
|
1112
|
-
for (let
|
|
1113
|
-
const
|
|
1114
|
-
|
|
1229
|
+
let s = "", i = !1;
|
|
1230
|
+
for (let r = 0; r < e.length; r++) {
|
|
1231
|
+
const n = e[r];
|
|
1232
|
+
n === "[" ? (i = !0, s += n) : n === "]" ? (i = !1, s += n) : n === "." && !i ? s && (this.addSegment(t, s), s = "") : s += n;
|
|
1115
1233
|
}
|
|
1116
|
-
return
|
|
1234
|
+
return s && this.addSegment(t, s), t;
|
|
1117
1235
|
}
|
|
1118
1236
|
/**
|
|
1119
1237
|
* Добавляет сегмент в массив, обрабатывая массивы
|
|
1120
1238
|
* @private
|
|
1121
1239
|
*/
|
|
1122
1240
|
addSegment(e, t) {
|
|
1123
|
-
const
|
|
1124
|
-
|
|
1125
|
-
key:
|
|
1126
|
-
index: parseInt(
|
|
1241
|
+
const s = t.match(/^(.+)\[(\d+)\]$/);
|
|
1242
|
+
s ? e.push({
|
|
1243
|
+
key: s[1],
|
|
1244
|
+
index: parseInt(s[2], 10)
|
|
1127
1245
|
}) : e.push({ key: t });
|
|
1128
1246
|
}
|
|
1129
1247
|
/**
|
|
@@ -1158,16 +1276,16 @@ class Q {
|
|
|
1158
1276
|
* ```
|
|
1159
1277
|
*/
|
|
1160
1278
|
getValueByPath(e, t) {
|
|
1161
|
-
const
|
|
1162
|
-
let
|
|
1163
|
-
for (const
|
|
1164
|
-
if (
|
|
1165
|
-
if (
|
|
1166
|
-
if (!Array.isArray(
|
|
1167
|
-
|
|
1279
|
+
const s = this.parsePath(t);
|
|
1280
|
+
let i = e;
|
|
1281
|
+
for (const r of s) {
|
|
1282
|
+
if (i == null) return;
|
|
1283
|
+
if (i = i[r.key], r.index !== void 0) {
|
|
1284
|
+
if (!Array.isArray(i)) return;
|
|
1285
|
+
i = i[r.index];
|
|
1168
1286
|
}
|
|
1169
1287
|
}
|
|
1170
|
-
return
|
|
1288
|
+
return i;
|
|
1171
1289
|
}
|
|
1172
1290
|
/**
|
|
1173
1291
|
* Устанавливает значение по пути в объекте (мутирует объект)
|
|
@@ -1196,31 +1314,31 @@ class Q {
|
|
|
1196
1314
|
* // obj3.items[0].title === 'New'
|
|
1197
1315
|
* ```
|
|
1198
1316
|
*/
|
|
1199
|
-
setValueByPath(e, t,
|
|
1200
|
-
const
|
|
1201
|
-
if (
|
|
1317
|
+
setValueByPath(e, t, s) {
|
|
1318
|
+
const i = this.parsePath(t);
|
|
1319
|
+
if (i.length === 0)
|
|
1202
1320
|
throw new Error("Cannot set value: empty path");
|
|
1203
|
-
let
|
|
1204
|
-
for (let
|
|
1205
|
-
const l =
|
|
1206
|
-
let
|
|
1321
|
+
let r = e;
|
|
1322
|
+
for (let o = 0; o < i.length - 1; o++) {
|
|
1323
|
+
const l = i[o];
|
|
1324
|
+
let u = r[l.key];
|
|
1207
1325
|
if (l.index !== void 0) {
|
|
1208
|
-
if (!Array.isArray(
|
|
1209
|
-
throw new Error(`Expected array at path segment: ${l.key}, but got ${typeof
|
|
1210
|
-
|
|
1326
|
+
if (!Array.isArray(u))
|
|
1327
|
+
throw new Error(`Expected array at path segment: ${l.key}, but got ${typeof u}`);
|
|
1328
|
+
r = u[l.index];
|
|
1211
1329
|
} else
|
|
1212
|
-
|
|
1330
|
+
u == null && (r[l.key] = {}, u = r[l.key]), r = u;
|
|
1213
1331
|
}
|
|
1214
|
-
const
|
|
1215
|
-
if (
|
|
1216
|
-
const
|
|
1217
|
-
if (!Array.isArray(
|
|
1332
|
+
const n = i[i.length - 1];
|
|
1333
|
+
if (n.index !== void 0) {
|
|
1334
|
+
const o = r[n.key];
|
|
1335
|
+
if (!Array.isArray(o))
|
|
1218
1336
|
throw new Error(
|
|
1219
|
-
`Expected array at path segment: ${
|
|
1337
|
+
`Expected array at path segment: ${n.key}, but got ${typeof o}`
|
|
1220
1338
|
);
|
|
1221
|
-
n
|
|
1339
|
+
o[n.index] = s;
|
|
1222
1340
|
} else
|
|
1223
|
-
|
|
1341
|
+
r[n.key] = s;
|
|
1224
1342
|
}
|
|
1225
1343
|
/**
|
|
1226
1344
|
* Получить значение из FormNode по пути
|
|
@@ -1257,9 +1375,9 @@ class Q {
|
|
|
1257
1375
|
* ```
|
|
1258
1376
|
*/
|
|
1259
1377
|
getFormNodeValue(e, t) {
|
|
1260
|
-
const
|
|
1261
|
-
if (
|
|
1262
|
-
return this.isFormNode(
|
|
1378
|
+
const s = this.getNodeByPath(e, t);
|
|
1379
|
+
if (s != null)
|
|
1380
|
+
return this.isFormNode(s) ? s.value.value : s;
|
|
1263
1381
|
}
|
|
1264
1382
|
/**
|
|
1265
1383
|
* Type guard для проверки, является ли объект FormNode
|
|
@@ -1317,40 +1435,177 @@ class Q {
|
|
|
1317
1435
|
* ```
|
|
1318
1436
|
*/
|
|
1319
1437
|
getNodeByPath(e, t) {
|
|
1320
|
-
const
|
|
1321
|
-
let
|
|
1322
|
-
for (const
|
|
1323
|
-
if (
|
|
1324
|
-
const
|
|
1325
|
-
if (
|
|
1326
|
-
if (
|
|
1327
|
-
if (
|
|
1438
|
+
const s = this.parsePath(t);
|
|
1439
|
+
let i = e;
|
|
1440
|
+
for (const r of s) {
|
|
1441
|
+
if (i == null) return null;
|
|
1442
|
+
const n = i;
|
|
1443
|
+
if (n.fields && n.fields instanceof Map) {
|
|
1444
|
+
if (i = n.fields.get(r.key), r.index === void 0) {
|
|
1445
|
+
if (i == null) return null;
|
|
1328
1446
|
continue;
|
|
1329
1447
|
}
|
|
1330
|
-
} else if (
|
|
1331
|
-
const
|
|
1332
|
-
if (!Array.isArray(
|
|
1448
|
+
} else if (r.index !== void 0 && n.items) {
|
|
1449
|
+
const o = n.items.value || n.items;
|
|
1450
|
+
if (!Array.isArray(o) || (i = o[r.index], i == null)) return null;
|
|
1333
1451
|
continue;
|
|
1334
|
-
} else if (
|
|
1335
|
-
if (
|
|
1452
|
+
} else if (r.index === void 0) {
|
|
1453
|
+
if (i = n[r.key], i == null) return null;
|
|
1336
1454
|
continue;
|
|
1337
1455
|
}
|
|
1338
|
-
if (
|
|
1339
|
-
const
|
|
1340
|
-
if (!Array.isArray(
|
|
1341
|
-
|
|
1342
|
-
} else if (
|
|
1456
|
+
if (i && r.index !== void 0 && i.items) {
|
|
1457
|
+
const o = i.items.value || i.items;
|
|
1458
|
+
if (!Array.isArray(o)) return null;
|
|
1459
|
+
i = o[r.index];
|
|
1460
|
+
} else if (i && r.index !== void 0 && !i.items)
|
|
1343
1461
|
return null;
|
|
1344
|
-
if (
|
|
1462
|
+
if (i == null) return null;
|
|
1345
1463
|
}
|
|
1346
|
-
return
|
|
1464
|
+
return i;
|
|
1347
1465
|
}
|
|
1348
1466
|
}
|
|
1349
|
-
|
|
1467
|
+
function W(a) {
|
|
1468
|
+
const { getChildren: e, ownErrors: t, disabled: s } = a, i = d(() => t.value.length > 0 ? !1 : e().every((h) => h.disabled.value || h.valid.value)), r = d(() => !i.value), n = d(() => e().some((h) => h.pending.value)), o = d(() => e().some((h) => h.touched.value)), l = d(() => e().some((h) => h.dirty.value)), u = d(() => {
|
|
1469
|
+
const h = [...t.value];
|
|
1470
|
+
for (const f of e())
|
|
1471
|
+
h.push(...f.errors.value);
|
|
1472
|
+
return h;
|
|
1473
|
+
}), v = d(() => s?.value ? "disabled" : n.value ? "pending" : r.value ? "invalid" : "valid");
|
|
1474
|
+
return {
|
|
1475
|
+
valid: i,
|
|
1476
|
+
invalid: r,
|
|
1477
|
+
pending: n,
|
|
1478
|
+
touched: o,
|
|
1479
|
+
dirty: l,
|
|
1480
|
+
errors: u,
|
|
1481
|
+
status: v
|
|
1482
|
+
};
|
|
1483
|
+
}
|
|
1484
|
+
function ie(a) {
|
|
1485
|
+
return typeof a == "object" && a !== null && "getProxy" in a && typeof a.getProxy == "function";
|
|
1486
|
+
}
|
|
1487
|
+
function re(a, e) {
|
|
1488
|
+
return new Proxy(a, {
|
|
1489
|
+
get: (t, s) => {
|
|
1490
|
+
if (s in t)
|
|
1491
|
+
return t[s];
|
|
1492
|
+
if (typeof s == "string" && e.has(s)) {
|
|
1493
|
+
const i = e.get(s);
|
|
1494
|
+
return i && ie(i) ? i.getProxy() : i;
|
|
1495
|
+
}
|
|
1496
|
+
},
|
|
1497
|
+
set: (t, s, i) => typeof s == "string" && e.has(s) ? !1 : (t[s] = i, !0),
|
|
1498
|
+
has: (t, s) => typeof s == "string" && e.has(s) ? !0 : s in t,
|
|
1499
|
+
ownKeys: (t) => {
|
|
1500
|
+
const s = Reflect.ownKeys(t), i = Array.from(e.keys());
|
|
1501
|
+
return [.../* @__PURE__ */ new Set([...s, ...i])];
|
|
1502
|
+
},
|
|
1503
|
+
getOwnPropertyDescriptor: (t, s) => typeof s == "string" && e.has(s) ? { enumerable: !0, configurable: !0 } : Reflect.getOwnPropertyDescriptor(t, s)
|
|
1504
|
+
});
|
|
1505
|
+
}
|
|
1506
|
+
class ae {
|
|
1507
|
+
/**
|
|
1508
|
+
* @param form - Форма для отправки
|
|
1509
|
+
*/
|
|
1510
|
+
constructor(e) {
|
|
1511
|
+
this.form = e;
|
|
1512
|
+
}
|
|
1513
|
+
/** Внутренний сигнал состояния отправки */
|
|
1514
|
+
_submitting = g(!1);
|
|
1515
|
+
/** Публичный read-only сигнал состояния отправки */
|
|
1516
|
+
submitting = d(() => this._submitting.value);
|
|
1517
|
+
/**
|
|
1518
|
+
* Отправить форму
|
|
1519
|
+
*
|
|
1520
|
+
* Процесс:
|
|
1521
|
+
* 1. Помечает все поля как touched (для отображения ошибок)
|
|
1522
|
+
* 2. Валидирует форму
|
|
1523
|
+
* 3. Если валидация успешна - вызывает onSubmit
|
|
1524
|
+
* 4. Управляет состоянием submitting
|
|
1525
|
+
*
|
|
1526
|
+
* @param onSubmit - Callback для отправки данных
|
|
1527
|
+
* @param options - Опции submit
|
|
1528
|
+
* @returns Результат от onSubmit или null если валидация не пройдена
|
|
1529
|
+
*
|
|
1530
|
+
* @example
|
|
1531
|
+
* ```typescript
|
|
1532
|
+
* const result = await submitter.submit(async (values) => {
|
|
1533
|
+
* const response = await fetch('/api/form', {
|
|
1534
|
+
* method: 'POST',
|
|
1535
|
+
* body: JSON.stringify(values)
|
|
1536
|
+
* });
|
|
1537
|
+
* return response.json();
|
|
1538
|
+
* });
|
|
1539
|
+
*
|
|
1540
|
+
* if (result === null) {
|
|
1541
|
+
* console.log('Форма не прошла валидацию');
|
|
1542
|
+
* }
|
|
1543
|
+
* ```
|
|
1544
|
+
*/
|
|
1545
|
+
async submit(e, t) {
|
|
1546
|
+
const { skipValidation: s = !1, skipTouch: i = !1 } = t || {};
|
|
1547
|
+
if (i || this.form.markAsTouched(), !s && !await this.form.validate())
|
|
1548
|
+
return null;
|
|
1549
|
+
this._submitting.value = !0;
|
|
1550
|
+
try {
|
|
1551
|
+
return await e(this.form.getValue());
|
|
1552
|
+
} finally {
|
|
1553
|
+
this._submitting.value = !1;
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
/**
|
|
1557
|
+
* Отправить форму с расширенным результатом
|
|
1558
|
+
*
|
|
1559
|
+
* В отличие от submit(), возвращает объект с информацией об успехе/ошибке
|
|
1560
|
+
*
|
|
1561
|
+
* @param onSubmit - Callback для отправки данных
|
|
1562
|
+
* @param options - Опции submit
|
|
1563
|
+
* @returns Объект SubmitResult с данными и статусом
|
|
1564
|
+
*
|
|
1565
|
+
* @example
|
|
1566
|
+
* ```typescript
|
|
1567
|
+
* const result = await submitter.submitWithResult(async (values) => {
|
|
1568
|
+
* return await api.saveForm(values);
|
|
1569
|
+
* });
|
|
1570
|
+
*
|
|
1571
|
+
* if (result.success) {
|
|
1572
|
+
* console.log('Сохранено:', result.data);
|
|
1573
|
+
* } else if (result.error) {
|
|
1574
|
+
* console.error('Ошибка:', result.error.message);
|
|
1575
|
+
* } else {
|
|
1576
|
+
* console.log('Валидация не пройдена');
|
|
1577
|
+
* }
|
|
1578
|
+
* ```
|
|
1579
|
+
*/
|
|
1580
|
+
async submitWithResult(e, t) {
|
|
1581
|
+
const { skipValidation: s = !1, skipTouch: i = !1 } = t || {};
|
|
1582
|
+
if (i || this.form.markAsTouched(), !s && !await this.form.validate())
|
|
1583
|
+
return { success: !1, data: null };
|
|
1584
|
+
this._submitting.value = !0;
|
|
1585
|
+
try {
|
|
1586
|
+
return { success: !0, data: await e(this.form.getValue()) };
|
|
1587
|
+
} catch (r) {
|
|
1588
|
+
return {
|
|
1589
|
+
success: !1,
|
|
1590
|
+
data: null,
|
|
1591
|
+
error: r instanceof Error ? r : new Error(String(r))
|
|
1592
|
+
};
|
|
1593
|
+
} finally {
|
|
1594
|
+
this._submitting.value = !1;
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
/**
|
|
1598
|
+
* Проверить, идет ли отправка формы
|
|
1599
|
+
*/
|
|
1600
|
+
isSubmitting() {
|
|
1601
|
+
return this._submitting.value;
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
class k extends C {
|
|
1350
1605
|
// ============================================================================
|
|
1351
1606
|
// Приватные поля
|
|
1352
1607
|
// ============================================================================
|
|
1353
|
-
id =
|
|
1608
|
+
id = crypto.randomUUID();
|
|
1354
1609
|
/**
|
|
1355
1610
|
* Коллекция полей формы (упрощённый Map вместо FieldRegistry)
|
|
1356
1611
|
*/
|
|
@@ -1359,7 +1614,7 @@ class b extends O {
|
|
|
1359
1614
|
/**
|
|
1360
1615
|
* Менеджер подписок для централизованного cleanup
|
|
1361
1616
|
*/
|
|
1362
|
-
disposers = new
|
|
1617
|
+
disposers = new D();
|
|
1363
1618
|
/**
|
|
1364
1619
|
* Ссылка на Proxy-инстанс для использования в BehaviorContext
|
|
1365
1620
|
*/
|
|
@@ -1367,32 +1622,35 @@ class b extends O {
|
|
|
1367
1622
|
/**
|
|
1368
1623
|
* Навигатор для работы с путями к полям
|
|
1369
1624
|
*/
|
|
1370
|
-
pathNavigator = new
|
|
1625
|
+
pathNavigator = new se();
|
|
1371
1626
|
/**
|
|
1372
1627
|
* Фабрика для создания узлов формы
|
|
1373
1628
|
*/
|
|
1374
|
-
nodeFactory = new
|
|
1629
|
+
nodeFactory = new ne();
|
|
1375
1630
|
/**
|
|
1376
1631
|
* Реестр валидаторов для этой формы
|
|
1632
|
+
* Может быть инжектирован через config._validationRegistry для тестирования
|
|
1377
1633
|
*/
|
|
1378
|
-
validationRegistry
|
|
1634
|
+
validationRegistry;
|
|
1379
1635
|
/**
|
|
1380
1636
|
* Реестр behaviors для этой формы
|
|
1637
|
+
* Может быть инжектирован через config._behaviorRegistry для тестирования
|
|
1381
1638
|
*/
|
|
1382
|
-
behaviorRegistry
|
|
1639
|
+
behaviorRegistry;
|
|
1383
1640
|
/**
|
|
1384
1641
|
* Аппликатор для применения валидаторов к форме
|
|
1385
1642
|
*/
|
|
1386
|
-
validationApplicator = new
|
|
1643
|
+
validationApplicator = new te(this);
|
|
1387
1644
|
// ============================================================================
|
|
1388
1645
|
// Приватные сигналы состояния (inline из StateManager)
|
|
1389
1646
|
// ============================================================================
|
|
1390
|
-
/**
|
|
1391
|
-
|
|
1647
|
+
/** Управление отправкой формы */
|
|
1648
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1649
|
+
formSubmitter;
|
|
1392
1650
|
/** Флаг disabled состояния */
|
|
1393
|
-
_disabled =
|
|
1651
|
+
_disabled = g(!1);
|
|
1394
1652
|
/** Form-level validation errors */
|
|
1395
|
-
_formErrors =
|
|
1653
|
+
_formErrors = g([]);
|
|
1396
1654
|
// ============================================================================
|
|
1397
1655
|
// Публичные computed signals
|
|
1398
1656
|
// ============================================================================
|
|
@@ -1406,76 +1664,56 @@ class b extends O {
|
|
|
1406
1664
|
status;
|
|
1407
1665
|
submitting;
|
|
1408
1666
|
constructor(e) {
|
|
1409
|
-
super();
|
|
1410
|
-
const t = "form" in e, i = t ? e.form : e,
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
this.
|
|
1667
|
+
super(), this.formSubmitter = new ae(this);
|
|
1668
|
+
const t = "form" in e, s = t ? e : void 0, i = t ? e.form : e, r = t ? e.behavior : void 0, n = t ? e.validation : void 0;
|
|
1669
|
+
this.validationRegistry = s?._validationRegistry ?? new K(), this.behaviorRegistry = s?._behaviorRegistry ?? new H();
|
|
1670
|
+
for (const [l, u] of Object.entries(i)) {
|
|
1671
|
+
const v = this.createNode(u);
|
|
1672
|
+
this._fields.set(l, v);
|
|
1414
1673
|
}
|
|
1415
|
-
this.value =
|
|
1416
|
-
const
|
|
1417
|
-
return this._fields.forEach((
|
|
1418
|
-
|
|
1419
|
-
}),
|
|
1420
|
-
})
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
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)
|
|
1674
|
+
this.value = d(() => {
|
|
1675
|
+
const l = {};
|
|
1676
|
+
return this._fields.forEach((u, v) => {
|
|
1677
|
+
l[v] = u.value.value;
|
|
1678
|
+
}), l;
|
|
1679
|
+
});
|
|
1680
|
+
const o = W({
|
|
1681
|
+
getChildren: () => Array.from(this._fields.values()),
|
|
1682
|
+
ownErrors: this._formErrors,
|
|
1683
|
+
disabled: this._disabled
|
|
1684
|
+
});
|
|
1685
|
+
this.valid = o.valid, this.invalid = o.invalid, this.pending = o.pending, this.touched = o.touched, this.dirty = o.dirty, this.errors = o.errors, this.status = o.status, this.submitting = this.formSubmitter.submitting, r && this.applyBehaviorSchema(r), n && this.applyValidationSchema(n);
|
|
1686
|
+
}
|
|
1687
|
+
// ============================================================================
|
|
1688
|
+
// Приватный метод для создания Proxy
|
|
1437
1689
|
// ============================================================================
|
|
1438
1690
|
/**
|
|
1439
1691
|
* Создать Proxy для типобезопасного доступа к полям
|
|
1692
|
+
* @see buildFormProxy
|
|
1440
1693
|
*/
|
|
1441
1694
|
buildProxy() {
|
|
1442
|
-
|
|
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
|
-
});
|
|
1695
|
+
return re(this, this._fields);
|
|
1458
1696
|
}
|
|
1459
1697
|
// ============================================================================
|
|
1460
1698
|
// Реализация абстрактных методов FormNode
|
|
1461
1699
|
// ============================================================================
|
|
1462
1700
|
getValue() {
|
|
1463
1701
|
const e = {};
|
|
1464
|
-
return this._fields.forEach((t,
|
|
1465
|
-
e[
|
|
1702
|
+
return this._fields.forEach((t, s) => {
|
|
1703
|
+
e[s] = t.getValue();
|
|
1466
1704
|
}), e;
|
|
1467
1705
|
}
|
|
1468
1706
|
setValue(e, t) {
|
|
1469
|
-
for (const [
|
|
1470
|
-
const
|
|
1471
|
-
|
|
1707
|
+
for (const [s, i] of Object.entries(e)) {
|
|
1708
|
+
const r = this._fields.get(s);
|
|
1709
|
+
r && r.setValue(i, t);
|
|
1472
1710
|
}
|
|
1473
1711
|
}
|
|
1474
1712
|
patchValue(e) {
|
|
1475
|
-
|
|
1476
|
-
for (const [t,
|
|
1477
|
-
const
|
|
1478
|
-
|
|
1713
|
+
j(() => {
|
|
1714
|
+
for (const [t, s] of Object.entries(e)) {
|
|
1715
|
+
const i = this._fields.get(t);
|
|
1716
|
+
i && s !== void 0 && i.setValue(s, { emitEvent: !1 });
|
|
1479
1717
|
}
|
|
1480
1718
|
});
|
|
1481
1719
|
}
|
|
@@ -1497,9 +1735,9 @@ class b extends O {
|
|
|
1497
1735
|
* ```
|
|
1498
1736
|
*/
|
|
1499
1737
|
reset(e) {
|
|
1500
|
-
this._fields.forEach((t,
|
|
1501
|
-
const
|
|
1502
|
-
t.reset(
|
|
1738
|
+
this._fields.forEach((t, s) => {
|
|
1739
|
+
const i = e?.[s];
|
|
1740
|
+
t.reset(i);
|
|
1503
1741
|
});
|
|
1504
1742
|
}
|
|
1505
1743
|
/**
|
|
@@ -1513,7 +1751,9 @@ class b extends O {
|
|
|
1513
1751
|
async validate() {
|
|
1514
1752
|
this.clearErrors(), await Promise.all(Array.from(this._fields.values()).map((t) => t.validate()));
|
|
1515
1753
|
const e = this.validationRegistry.getValidators();
|
|
1516
|
-
return e && e.length > 0 && await this.applyContextualValidators(e), Array.from(this._fields.values()).every(
|
|
1754
|
+
return e && e.length > 0 && await this.applyContextualValidators(e), Array.from(this._fields.values()).every(
|
|
1755
|
+
(t) => t.valid.value || t.disabled.value
|
|
1756
|
+
);
|
|
1517
1757
|
}
|
|
1518
1758
|
/**
|
|
1519
1759
|
* Установить form-level validation errors
|
|
@@ -1566,7 +1806,7 @@ class b extends O {
|
|
|
1566
1806
|
* ```
|
|
1567
1807
|
*/
|
|
1568
1808
|
getProxy() {
|
|
1569
|
-
return this._proxyInstance || this;
|
|
1809
|
+
return this._proxyInstance || (this._proxyInstance = this.buildProxy()), this._proxyInstance;
|
|
1570
1810
|
}
|
|
1571
1811
|
/**
|
|
1572
1812
|
* Получить все поля формы как итератор
|
|
@@ -1594,16 +1834,23 @@ class b extends O {
|
|
|
1594
1834
|
// ============================================================================
|
|
1595
1835
|
/**
|
|
1596
1836
|
* Отправить форму
|
|
1837
|
+
*
|
|
1838
|
+
* @param onSubmit - Callback для отправки данных
|
|
1839
|
+
* @param options - Опции submit (skipValidation, skipTouch)
|
|
1840
|
+
* @returns Результат от onSubmit или null если валидация не пройдена
|
|
1597
1841
|
*/
|
|
1598
|
-
async submit(e) {
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1842
|
+
async submit(e, t) {
|
|
1843
|
+
return this.formSubmitter.submit(e, t);
|
|
1844
|
+
}
|
|
1845
|
+
/**
|
|
1846
|
+
* Отправить форму с расширенным результатом
|
|
1847
|
+
*
|
|
1848
|
+
* @param onSubmit - Callback для отправки данных
|
|
1849
|
+
* @param options - Опции submit
|
|
1850
|
+
* @returns Объект SubmitResult с данными, статусом и возможной ошибкой
|
|
1851
|
+
*/
|
|
1852
|
+
async submitWithResult(e, t) {
|
|
1853
|
+
return this.formSubmitter.submitWithResult(e, t);
|
|
1607
1854
|
}
|
|
1608
1855
|
/**
|
|
1609
1856
|
* Применить validation schema к форме
|
|
@@ -1616,8 +1863,8 @@ class b extends O {
|
|
|
1616
1863
|
try {
|
|
1617
1864
|
const t = I();
|
|
1618
1865
|
e(t);
|
|
1619
|
-
const
|
|
1620
|
-
this.validationRegistry.endRegistration(
|
|
1866
|
+
const s = this.getProxy();
|
|
1867
|
+
this.validationRegistry.endRegistration(s);
|
|
1621
1868
|
} catch (t) {
|
|
1622
1869
|
throw console.error("Error applying validation schema:", t), t;
|
|
1623
1870
|
}
|
|
@@ -1670,18 +1917,18 @@ class b extends O {
|
|
|
1670
1917
|
const t = this.pathNavigator.parsePath(e);
|
|
1671
1918
|
if (t.length === 0)
|
|
1672
1919
|
return;
|
|
1673
|
-
let
|
|
1674
|
-
for (const
|
|
1675
|
-
if (!(
|
|
1676
|
-
if (
|
|
1677
|
-
if ("at" in
|
|
1678
|
-
const
|
|
1679
|
-
if (!
|
|
1680
|
-
|
|
1920
|
+
let s = this;
|
|
1921
|
+
for (const i of t) {
|
|
1922
|
+
if (!(s instanceof k) || (s = s.getField(i.key), !s)) return;
|
|
1923
|
+
if (i.index !== void 0)
|
|
1924
|
+
if ("at" in s && "length" in s && typeof s.at == "function") {
|
|
1925
|
+
const r = s.at(i.index);
|
|
1926
|
+
if (!r) return;
|
|
1927
|
+
s = r;
|
|
1681
1928
|
} else
|
|
1682
1929
|
return;
|
|
1683
1930
|
}
|
|
1684
|
-
return
|
|
1931
|
+
return s;
|
|
1685
1932
|
}
|
|
1686
1933
|
/**
|
|
1687
1934
|
* Применить contextual валидаторы к полям
|
|
@@ -1725,16 +1972,17 @@ class b extends O {
|
|
|
1725
1972
|
/**
|
|
1726
1973
|
* Связывает два поля: при изменении source автоматически обновляется target
|
|
1727
1974
|
*/
|
|
1728
|
-
linkFields(e, t,
|
|
1729
|
-
const
|
|
1730
|
-
if (!
|
|
1731
|
-
|
|
1732
|
-
};
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1975
|
+
linkFields(e, t, s) {
|
|
1976
|
+
const i = this._fields.get(e), r = this._fields.get(t);
|
|
1977
|
+
if (!i || !r) {
|
|
1978
|
+
const l = i ? t : e;
|
|
1979
|
+
throw new Error(`GroupNode.linkFields: field "${String(l)}" not found`);
|
|
1980
|
+
}
|
|
1981
|
+
const n = m(() => {
|
|
1982
|
+
const l = i.value.value, u = s ? s(l) : l;
|
|
1983
|
+
r.setValue(u, { emitEvent: !1 });
|
|
1984
|
+
}), o = A(w.LinkFields);
|
|
1985
|
+
return this.disposers.add(o, n);
|
|
1738
1986
|
}
|
|
1739
1987
|
/**
|
|
1740
1988
|
* Подписка на изменения вложенного поля по строковому пути
|
|
@@ -1764,15 +2012,14 @@ class b extends O {
|
|
|
1764
2012
|
* ```
|
|
1765
2013
|
*/
|
|
1766
2014
|
watchField(e, t) {
|
|
1767
|
-
const
|
|
1768
|
-
if (!
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
return this.disposers.add(a, s);
|
|
2015
|
+
const s = this.getFieldByPath(e);
|
|
2016
|
+
if (!s)
|
|
2017
|
+
throw new Error(`GroupNode.watchField: field "${e}" not found`);
|
|
2018
|
+
const i = m(() => {
|
|
2019
|
+
const n = s.value.value;
|
|
2020
|
+
t(n);
|
|
2021
|
+
}), r = A(w.WatchField);
|
|
2022
|
+
return this.disposers.add(r, i);
|
|
1776
2023
|
}
|
|
1777
2024
|
/**
|
|
1778
2025
|
* Hook: вызывается после disable()
|
|
@@ -1795,7 +2042,7 @@ class b extends O {
|
|
|
1795
2042
|
});
|
|
1796
2043
|
}
|
|
1797
2044
|
}
|
|
1798
|
-
class
|
|
2045
|
+
class L extends C {
|
|
1799
2046
|
// ============================================================================
|
|
1800
2047
|
// Приватные поля
|
|
1801
2048
|
// ============================================================================
|
|
@@ -1806,7 +2053,9 @@ class C extends O {
|
|
|
1806
2053
|
* Менеджер подписок для централизованного cleanup
|
|
1807
2054
|
* Использует SubscriptionManager вместо массива для управления подписками
|
|
1808
2055
|
*/
|
|
1809
|
-
disposers = new
|
|
2056
|
+
disposers = new D();
|
|
2057
|
+
/** Array-level validation errors (e.g., "минимум 1 элемент") */
|
|
2058
|
+
_arrayErrors = g([]);
|
|
1810
2059
|
// ============================================================================
|
|
1811
2060
|
// Приватные поля для сохранения схем
|
|
1812
2061
|
// ============================================================================
|
|
@@ -1828,15 +2077,15 @@ class C extends O {
|
|
|
1828
2077
|
// Конструктор
|
|
1829
2078
|
// ============================================================================
|
|
1830
2079
|
constructor(e, t = []) {
|
|
1831
|
-
super(), this.itemSchema = e, this.initialItems = t, this.items =
|
|
2080
|
+
super(), this.itemSchema = e, this.initialItems = t, this.items = g([]);
|
|
1832
2081
|
for (const i of t)
|
|
1833
2082
|
this.push(i);
|
|
1834
|
-
this.length =
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
2083
|
+
this.length = d(() => this.items.value.length), this.value = d(() => this.items.value.map((i) => i.value.value));
|
|
2084
|
+
const s = W({
|
|
2085
|
+
getChildren: () => this.items.value,
|
|
2086
|
+
ownErrors: this._arrayErrors
|
|
2087
|
+
});
|
|
2088
|
+
this.valid = s.valid, this.invalid = s.invalid, this.pending = s.pending, this.touched = s.touched, this.dirty = s.dirty, this.errors = s.errors, this.status = s.status;
|
|
1840
2089
|
}
|
|
1841
2090
|
// ============================================================================
|
|
1842
2091
|
// CRUD операции
|
|
@@ -1852,9 +2101,23 @@ class C extends O {
|
|
|
1852
2101
|
/**
|
|
1853
2102
|
* Удалить элемент по индексу
|
|
1854
2103
|
* @param index - Индекс элемента для удаления
|
|
2104
|
+
*
|
|
2105
|
+
* @remarks
|
|
2106
|
+
* Вызывает dispose() на удаляемом элементе для очистки подписок
|
|
1855
2107
|
*/
|
|
1856
2108
|
removeAt(e) {
|
|
1857
|
-
e < 0 || e >= this.items.value.length
|
|
2109
|
+
if (e < 0 || e >= this.items.value.length) {
|
|
2110
|
+
S.handle(
|
|
2111
|
+
new Error(
|
|
2112
|
+
`ArrayNode.removeAt: index ${e} out of bounds (length: ${this.items.value.length})`
|
|
2113
|
+
),
|
|
2114
|
+
"ArrayNode.removeAt",
|
|
2115
|
+
V.LOG
|
|
2116
|
+
);
|
|
2117
|
+
return;
|
|
2118
|
+
}
|
|
2119
|
+
const t = this.items.value[e];
|
|
2120
|
+
this.items.value = this.items.value.filter((s, i) => i !== e), t && "dispose" in t && typeof t.dispose == "function" && t.dispose();
|
|
1858
2121
|
}
|
|
1859
2122
|
/**
|
|
1860
2123
|
* Вставить элемент в массив
|
|
@@ -1862,24 +2125,40 @@ class C extends O {
|
|
|
1862
2125
|
* @param initialValue - Начальные значения для нового элемента
|
|
1863
2126
|
*/
|
|
1864
2127
|
insert(e, t) {
|
|
1865
|
-
if (e < 0 || e > this.items.value.length)
|
|
2128
|
+
if (e < 0 || e > this.items.value.length) {
|
|
2129
|
+
S.handle(
|
|
2130
|
+
new Error(
|
|
2131
|
+
`ArrayNode.insert: index ${e} out of bounds (length: ${this.items.value.length})`
|
|
2132
|
+
),
|
|
2133
|
+
"ArrayNode.insert",
|
|
2134
|
+
V.LOG
|
|
2135
|
+
);
|
|
1866
2136
|
return;
|
|
1867
|
-
|
|
1868
|
-
s.
|
|
2137
|
+
}
|
|
2138
|
+
const s = this.createItem(t), i = [...this.items.value];
|
|
2139
|
+
i.splice(e, 0, s), this.items.value = i;
|
|
1869
2140
|
}
|
|
1870
2141
|
/**
|
|
1871
2142
|
* Удалить все элементы массива
|
|
2143
|
+
*
|
|
2144
|
+
* @remarks
|
|
2145
|
+
* Вызывает dispose() на всех элементах для очистки подписок
|
|
1872
2146
|
*/
|
|
1873
2147
|
clear() {
|
|
1874
|
-
this.items.value
|
|
2148
|
+
const e = [...this.items.value];
|
|
2149
|
+
this.items.value = [], e.forEach((t) => {
|
|
2150
|
+
"dispose" in t && typeof t.dispose == "function" && t.dispose();
|
|
2151
|
+
});
|
|
1875
2152
|
}
|
|
1876
2153
|
/**
|
|
1877
2154
|
* Получить элемент по индексу
|
|
1878
2155
|
* @param index - Индекс элемента
|
|
1879
|
-
* @returns Типизированный GroupNode или undefined если индекс вне границ
|
|
2156
|
+
* @returns Типизированный GroupNode proxy или undefined если индекс вне границ
|
|
1880
2157
|
*/
|
|
1881
2158
|
at(e) {
|
|
1882
|
-
|
|
2159
|
+
const t = this.items.value[e];
|
|
2160
|
+
if (t)
|
|
2161
|
+
return t.getProxy();
|
|
1883
2162
|
}
|
|
1884
2163
|
// ============================================================================
|
|
1885
2164
|
// Реализация абстрактных методов
|
|
@@ -1888,12 +2167,13 @@ class C extends O {
|
|
|
1888
2167
|
return this.items.value.map((e) => e.getValue());
|
|
1889
2168
|
}
|
|
1890
2169
|
setValue(e, t) {
|
|
1891
|
-
this.clear(), e.forEach((
|
|
2170
|
+
this.clear(), e.forEach((s) => this.push(s)), t?.emitEvent !== !1 && this.validate().catch((s) => {
|
|
2171
|
+
S.handle(s, "ArrayNode.setValue", V.LOG);
|
|
1892
2172
|
});
|
|
1893
2173
|
}
|
|
1894
2174
|
patchValue(e) {
|
|
1895
|
-
e.forEach((t,
|
|
1896
|
-
this.items.value[
|
|
2175
|
+
e.forEach((t, s) => {
|
|
2176
|
+
this.items.value[s] && t !== void 0 && this.items.value[s].patchValue(t);
|
|
1897
2177
|
});
|
|
1898
2178
|
}
|
|
1899
2179
|
/**
|
|
@@ -1914,7 +2194,7 @@ class C extends O {
|
|
|
1914
2194
|
* ```
|
|
1915
2195
|
*/
|
|
1916
2196
|
reset(e) {
|
|
1917
|
-
this.clear(), e && e.forEach((t) => this.push(t));
|
|
2197
|
+
this._arrayErrors.value = [], this.clear(), e && e.forEach((t) => this.push(t));
|
|
1918
2198
|
}
|
|
1919
2199
|
/**
|
|
1920
2200
|
* Сбросить массив к исходным значениям (initialItems)
|
|
@@ -1945,15 +2225,38 @@ class C extends O {
|
|
|
1945
2225
|
* ```
|
|
1946
2226
|
*/
|
|
1947
2227
|
resetToInitial() {
|
|
1948
|
-
this.clear(), this.initialItems.forEach((e) => this.push(e));
|
|
2228
|
+
this._arrayErrors.value = [], this.clear(), this.initialItems.forEach((e) => this.push(e));
|
|
1949
2229
|
}
|
|
1950
2230
|
async validate() {
|
|
1951
2231
|
return (await Promise.all(this.items.value.map((t) => t.validate()))).every(Boolean);
|
|
1952
2232
|
}
|
|
2233
|
+
/**
|
|
2234
|
+
* Установить array-level validation errors
|
|
2235
|
+
*
|
|
2236
|
+
* @param errors - Массив ошибок валидации уровня массива
|
|
2237
|
+
*
|
|
2238
|
+
* @example
|
|
2239
|
+
* ```typescript
|
|
2240
|
+
* arrayNode.setErrors([{
|
|
2241
|
+
* code: 'minItems',
|
|
2242
|
+
* message: 'Минимум 1 элемент обязателен',
|
|
2243
|
+
* }]);
|
|
2244
|
+
* ```
|
|
2245
|
+
*/
|
|
1953
2246
|
setErrors(e) {
|
|
2247
|
+
this._arrayErrors.value = e;
|
|
1954
2248
|
}
|
|
2249
|
+
/**
|
|
2250
|
+
* Очистить все errors (array-level + item-level)
|
|
2251
|
+
*
|
|
2252
|
+
* @example
|
|
2253
|
+
* ```typescript
|
|
2254
|
+
* arrayNode.clearErrors();
|
|
2255
|
+
* console.log(arrayNode.errors.value); // []
|
|
2256
|
+
* ```
|
|
2257
|
+
*/
|
|
1955
2258
|
clearErrors() {
|
|
1956
|
-
this.items.value.forEach((e) => e.clearErrors());
|
|
2259
|
+
this._arrayErrors.value = [], this.items.value.forEach((e) => e.clearErrors());
|
|
1957
2260
|
}
|
|
1958
2261
|
// ============================================================================
|
|
1959
2262
|
// Protected hooks (Template Method pattern)
|
|
@@ -1995,20 +2298,24 @@ class C extends O {
|
|
|
1995
2298
|
// ============================================================================
|
|
1996
2299
|
/**
|
|
1997
2300
|
* Итерировать по элементам массива
|
|
1998
|
-
* @param callback - Функция, вызываемая для каждого элемента с типизированным GroupNode
|
|
2301
|
+
* @param callback - Функция, вызываемая для каждого элемента с типизированным GroupNode proxy
|
|
1999
2302
|
*/
|
|
2000
2303
|
forEach(e) {
|
|
2001
|
-
this.items.value.forEach((t,
|
|
2002
|
-
|
|
2304
|
+
this.items.value.forEach((t, s) => {
|
|
2305
|
+
const i = t.getProxy();
|
|
2306
|
+
e(i, s);
|
|
2003
2307
|
});
|
|
2004
2308
|
}
|
|
2005
2309
|
/**
|
|
2006
2310
|
* Маппинг элементов массива
|
|
2007
|
-
* @param callback - Функция преобразования с типизированным GroupNode
|
|
2311
|
+
* @param callback - Функция преобразования с типизированным GroupNode proxy
|
|
2008
2312
|
* @returns Новый массив результатов
|
|
2009
2313
|
*/
|
|
2010
2314
|
map(e) {
|
|
2011
|
-
return this.items.value.map((t,
|
|
2315
|
+
return this.items.value.map((t, s) => {
|
|
2316
|
+
const i = t.getProxy();
|
|
2317
|
+
return e(i, s);
|
|
2318
|
+
});
|
|
2012
2319
|
}
|
|
2013
2320
|
// ============================================================================
|
|
2014
2321
|
// Private методы
|
|
@@ -2019,7 +2326,7 @@ class C extends O {
|
|
|
2019
2326
|
*/
|
|
2020
2327
|
createItem(e) {
|
|
2021
2328
|
if (this.isGroupSchema(this.itemSchema)) {
|
|
2022
|
-
const t = new
|
|
2329
|
+
const t = new k(this.itemSchema);
|
|
2023
2330
|
return e && t.patchValue(e), this.validationSchemaFn && "applyValidationSchema" in t && t.applyValidationSchema(this.validationSchemaFn), this.behaviorSchemaFn && "applyBehaviorSchema" in t && t.applyBehaviorSchema(this.behaviorSchemaFn), t;
|
|
2024
2331
|
}
|
|
2025
2332
|
throw new Error(
|
|
@@ -2106,14 +2413,14 @@ class C extends O {
|
|
|
2106
2413
|
* ```
|
|
2107
2414
|
*/
|
|
2108
2415
|
watchItems(e, t) {
|
|
2109
|
-
const
|
|
2110
|
-
const
|
|
2111
|
-
if (
|
|
2112
|
-
return
|
|
2416
|
+
const s = m(() => {
|
|
2417
|
+
const r = this.items.value.map((n) => {
|
|
2418
|
+
if (n instanceof k)
|
|
2419
|
+
return n.getFieldByPath(e)?.value.value;
|
|
2113
2420
|
});
|
|
2114
|
-
t(
|
|
2115
|
-
}),
|
|
2116
|
-
return this.disposers.add(
|
|
2421
|
+
t(r);
|
|
2422
|
+
}), i = A(w.WatchItems);
|
|
2423
|
+
return this.disposers.add(i, s);
|
|
2117
2424
|
}
|
|
2118
2425
|
/**
|
|
2119
2426
|
* Подписка на изменение длины массива
|
|
@@ -2138,11 +2445,11 @@ class C extends O {
|
|
|
2138
2445
|
* ```
|
|
2139
2446
|
*/
|
|
2140
2447
|
watchLength(e) {
|
|
2141
|
-
const t =
|
|
2142
|
-
const
|
|
2143
|
-
e(
|
|
2144
|
-
}),
|
|
2145
|
-
return this.disposers.add(
|
|
2448
|
+
const t = m(() => {
|
|
2449
|
+
const i = this.length.value;
|
|
2450
|
+
e(i);
|
|
2451
|
+
}), s = A(w.WatchLength);
|
|
2452
|
+
return this.disposers.add(s, t);
|
|
2146
2453
|
}
|
|
2147
2454
|
/**
|
|
2148
2455
|
* Очистить все ресурсы узла
|
|
@@ -2205,7 +2512,7 @@ class C extends O {
|
|
|
2205
2512
|
});
|
|
2206
2513
|
}
|
|
2207
2514
|
}
|
|
2208
|
-
class
|
|
2515
|
+
class ne {
|
|
2209
2516
|
/**
|
|
2210
2517
|
* Создает узел формы на основе конфигурации
|
|
2211
2518
|
*
|
|
@@ -2255,16 +2562,16 @@ class X {
|
|
|
2255
2562
|
if (Array.isArray(e) && e.length >= 1)
|
|
2256
2563
|
return this.createArrayNodeFromArray(e);
|
|
2257
2564
|
if (this.isFieldConfig(e))
|
|
2258
|
-
return new
|
|
2565
|
+
return new ee(e);
|
|
2259
2566
|
if (this.isArrayConfig(e)) {
|
|
2260
2567
|
const t = e;
|
|
2261
|
-
return new
|
|
2568
|
+
return new L(
|
|
2262
2569
|
t.schema,
|
|
2263
2570
|
t.initialItems
|
|
2264
2571
|
);
|
|
2265
2572
|
}
|
|
2266
2573
|
if (this.isGroupConfig(e))
|
|
2267
|
-
return new
|
|
2574
|
+
return new k(e);
|
|
2268
2575
|
throw new Error(
|
|
2269
2576
|
`NodeFactory: Unknown node config. Expected FieldConfig, GroupConfig, or ArrayConfig, but got: ${JSON.stringify(
|
|
2270
2577
|
e
|
|
@@ -2298,11 +2605,11 @@ class X {
|
|
|
2298
2605
|
*/
|
|
2299
2606
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2300
2607
|
createArrayNodeFromArray(e) {
|
|
2301
|
-
const [t, ...
|
|
2302
|
-
this.isGroupConfig(t) &&
|
|
2303
|
-
for (const
|
|
2304
|
-
this.isGroupConfig(
|
|
2305
|
-
return new
|
|
2608
|
+
const [t, ...s] = e, i = [];
|
|
2609
|
+
this.isGroupConfig(t) && i.push(this.extractValues(t));
|
|
2610
|
+
for (const r of s)
|
|
2611
|
+
this.isGroupConfig(r) ? i.push(this.extractValues(r)) : i.push(r);
|
|
2612
|
+
return new L(t, i);
|
|
2306
2613
|
}
|
|
2307
2614
|
/**
|
|
2308
2615
|
* Извлечь значения из схемы (рекурсивно)
|
|
@@ -2340,8 +2647,8 @@ class X {
|
|
|
2340
2647
|
return e.map((t) => this.extractValues(t));
|
|
2341
2648
|
if (this.isGroupConfig(e)) {
|
|
2342
2649
|
const t = {};
|
|
2343
|
-
for (const [
|
|
2344
|
-
t[
|
|
2650
|
+
for (const [s, i] of Object.entries(e))
|
|
2651
|
+
t[s] = this.extractValues(i);
|
|
2345
2652
|
return t;
|
|
2346
2653
|
}
|
|
2347
2654
|
return e;
|
|
@@ -2421,343 +2728,378 @@ class X {
|
|
|
2421
2728
|
return e != null && typeof e == "object" && !this.isFieldConfig(e) && !this.isArrayConfig(e);
|
|
2422
2729
|
}
|
|
2423
2730
|
}
|
|
2424
|
-
|
|
2731
|
+
function ge(a) {
|
|
2732
|
+
return new k(a).getProxy();
|
|
2733
|
+
}
|
|
2734
|
+
class be {
|
|
2735
|
+
/**
|
|
2736
|
+
* @param form - Форма для наблюдения
|
|
2737
|
+
* @param options - Опции observer
|
|
2738
|
+
*/
|
|
2739
|
+
constructor(e, t) {
|
|
2740
|
+
this.form = e, this.options = {
|
|
2741
|
+
enableLogging: !1,
|
|
2742
|
+
eventTypes: ["value", "status", "errors", "touched", "dirty"],
|
|
2743
|
+
pathFilter: [],
|
|
2744
|
+
...t
|
|
2745
|
+
};
|
|
2746
|
+
}
|
|
2747
|
+
listeners = /* @__PURE__ */ new Set();
|
|
2748
|
+
disposers = [];
|
|
2749
|
+
options;
|
|
2425
2750
|
/**
|
|
2426
|
-
*
|
|
2751
|
+
* Подписаться на события изменения
|
|
2427
2752
|
*
|
|
2428
|
-
* @param
|
|
2753
|
+
* @param callback - Функция обработки события
|
|
2754
|
+
* @returns Функция отписки
|
|
2429
2755
|
*
|
|
2430
2756
|
* @example
|
|
2431
2757
|
* ```typescript
|
|
2432
|
-
* const
|
|
2433
|
-
*
|
|
2758
|
+
* const unsubscribe = observer.subscribe((event) => {
|
|
2759
|
+
* // Отправить событие в analytics
|
|
2760
|
+
* analytics.track('form_change', event);
|
|
2761
|
+
* });
|
|
2434
2762
|
* ```
|
|
2435
2763
|
*/
|
|
2436
|
-
|
|
2437
|
-
this.
|
|
2764
|
+
subscribe(e) {
|
|
2765
|
+
return this.listeners.add(e), () => this.listeners.delete(e);
|
|
2438
2766
|
}
|
|
2439
2767
|
/**
|
|
2440
|
-
*
|
|
2441
|
-
* @private
|
|
2442
|
-
*/
|
|
2443
|
-
timer;
|
|
2444
|
-
/**
|
|
2445
|
-
* Отложить выполнение функции
|
|
2768
|
+
* Включить трассировку формы
|
|
2446
2769
|
*
|
|
2447
|
-
*
|
|
2448
|
-
* и
|
|
2770
|
+
* Подписывается на изменения основных сигналов формы
|
|
2771
|
+
* и вызывает listeners при каждом изменении
|
|
2449
2772
|
*
|
|
2450
|
-
* @
|
|
2451
|
-
* @returns Promise, который разрешается результатом функции
|
|
2773
|
+
* @returns Функция для отключения трассировки
|
|
2452
2774
|
*
|
|
2453
2775
|
* @example
|
|
2454
2776
|
* ```typescript
|
|
2455
|
-
* const
|
|
2456
|
-
*
|
|
2457
|
-
* // Первый вызов - запланирован через 300мс
|
|
2458
|
-
* debouncer.debounce(async () => console.log('First'));
|
|
2459
|
-
*
|
|
2460
|
-
* // Второй вызов через 100мс - отменяет первый, запланирован через 300мс
|
|
2461
|
-
* debouncer.debounce(async () => console.log('Second'));
|
|
2777
|
+
* const dispose = observer.enableTracing();
|
|
2462
2778
|
*
|
|
2463
|
-
* //
|
|
2779
|
+
* // Позже, для отключения
|
|
2780
|
+
* dispose();
|
|
2464
2781
|
* ```
|
|
2465
2782
|
*/
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
}
|
|
2783
|
+
enableTracing() {
|
|
2784
|
+
if (this.shouldTrack("value")) {
|
|
2785
|
+
let e = this.form.value.value;
|
|
2786
|
+
const t = m(() => {
|
|
2787
|
+
const s = this.form.value.value;
|
|
2788
|
+
s !== e && (this.emit({
|
|
2789
|
+
type: "value",
|
|
2790
|
+
path: "",
|
|
2791
|
+
timestamp: Date.now(),
|
|
2792
|
+
oldValue: e,
|
|
2793
|
+
newValue: s
|
|
2794
|
+
}), e = s);
|
|
2795
|
+
});
|
|
2796
|
+
this.disposers.push(t);
|
|
2797
|
+
}
|
|
2798
|
+
if (this.shouldTrack("status")) {
|
|
2799
|
+
let e = this.form.status.value;
|
|
2800
|
+
const t = m(() => {
|
|
2801
|
+
const s = this.form.status.value;
|
|
2802
|
+
s !== e && (this.emit({
|
|
2803
|
+
type: "status",
|
|
2804
|
+
path: "",
|
|
2805
|
+
timestamp: Date.now(),
|
|
2806
|
+
oldValue: e,
|
|
2807
|
+
newValue: s
|
|
2808
|
+
}), e = s);
|
|
2809
|
+
});
|
|
2810
|
+
this.disposers.push(t);
|
|
2811
|
+
}
|
|
2812
|
+
if (this.shouldTrack("errors")) {
|
|
2813
|
+
let e = this.form.errors.value;
|
|
2814
|
+
const t = m(() => {
|
|
2815
|
+
const s = this.form.errors.value;
|
|
2816
|
+
s !== e && (this.emit({
|
|
2817
|
+
type: "errors",
|
|
2818
|
+
path: "",
|
|
2819
|
+
timestamp: Date.now(),
|
|
2820
|
+
oldValue: e,
|
|
2821
|
+
newValue: s
|
|
2822
|
+
}), e = s);
|
|
2823
|
+
});
|
|
2824
|
+
this.disposers.push(t);
|
|
2825
|
+
}
|
|
2826
|
+
if (this.shouldTrack("touched")) {
|
|
2827
|
+
let e = this.form.touched.value;
|
|
2828
|
+
const t = m(() => {
|
|
2829
|
+
const s = this.form.touched.value;
|
|
2830
|
+
s !== e && (this.emit({
|
|
2831
|
+
type: "touched",
|
|
2832
|
+
path: "",
|
|
2833
|
+
timestamp: Date.now(),
|
|
2834
|
+
oldValue: e,
|
|
2835
|
+
newValue: s
|
|
2836
|
+
}), e = s);
|
|
2837
|
+
});
|
|
2838
|
+
this.disposers.push(t);
|
|
2839
|
+
}
|
|
2840
|
+
if (this.shouldTrack("dirty")) {
|
|
2841
|
+
let e = this.form.dirty.value;
|
|
2842
|
+
const t = m(() => {
|
|
2843
|
+
const s = this.form.dirty.value;
|
|
2844
|
+
s !== e && (this.emit({
|
|
2845
|
+
type: "dirty",
|
|
2846
|
+
path: "",
|
|
2847
|
+
timestamp: Date.now(),
|
|
2848
|
+
oldValue: e,
|
|
2849
|
+
newValue: s
|
|
2850
|
+
}), e = s);
|
|
2851
|
+
});
|
|
2852
|
+
this.disposers.push(t);
|
|
2853
|
+
}
|
|
2854
|
+
return () => {
|
|
2855
|
+
this.disposers.forEach((e) => e()), this.disposers = [];
|
|
2856
|
+
};
|
|
2481
2857
|
}
|
|
2482
2858
|
/**
|
|
2483
|
-
*
|
|
2859
|
+
* Наблюдать за конкретным полем
|
|
2484
2860
|
*
|
|
2485
|
-
*
|
|
2486
|
-
*
|
|
2861
|
+
* @param path - Путь к полю
|
|
2862
|
+
* @returns Функция для отключения наблюдения
|
|
2487
2863
|
*
|
|
2488
2864
|
* @example
|
|
2489
2865
|
* ```typescript
|
|
2490
|
-
*
|
|
2491
|
-
*
|
|
2492
|
-
* debouncer.debounce(async () => {
|
|
2493
|
-
* console.log('This will not execute');
|
|
2494
|
-
* });
|
|
2495
|
-
*
|
|
2496
|
-
* debouncer.cancel(); // Отменяем вызов
|
|
2866
|
+
* // Наблюдать за полем email
|
|
2867
|
+
* const dispose = observer.watchField('email');
|
|
2497
2868
|
* ```
|
|
2498
2869
|
*/
|
|
2499
|
-
|
|
2500
|
-
|
|
2870
|
+
watchField(e) {
|
|
2871
|
+
const t = this.form.getFieldByPath(e);
|
|
2872
|
+
if (!t)
|
|
2873
|
+
return () => {
|
|
2874
|
+
};
|
|
2875
|
+
const s = [];
|
|
2876
|
+
if (this.shouldTrack("value")) {
|
|
2877
|
+
let i = t.value.value;
|
|
2878
|
+
const r = m(() => {
|
|
2879
|
+
const n = t.value.value;
|
|
2880
|
+
n !== i && (this.emit({
|
|
2881
|
+
type: "value",
|
|
2882
|
+
path: e,
|
|
2883
|
+
timestamp: Date.now(),
|
|
2884
|
+
oldValue: i,
|
|
2885
|
+
newValue: n
|
|
2886
|
+
}), i = n);
|
|
2887
|
+
});
|
|
2888
|
+
s.push(r);
|
|
2889
|
+
}
|
|
2890
|
+
if (this.shouldTrack("status")) {
|
|
2891
|
+
let i = t.status.value;
|
|
2892
|
+
const r = m(() => {
|
|
2893
|
+
const n = t.status.value;
|
|
2894
|
+
n !== i && (this.emit({
|
|
2895
|
+
type: "status",
|
|
2896
|
+
path: e,
|
|
2897
|
+
timestamp: Date.now(),
|
|
2898
|
+
oldValue: i,
|
|
2899
|
+
newValue: n
|
|
2900
|
+
}), i = n);
|
|
2901
|
+
});
|
|
2902
|
+
s.push(r);
|
|
2903
|
+
}
|
|
2904
|
+
return () => s.forEach((i) => i());
|
|
2501
2905
|
}
|
|
2502
2906
|
/**
|
|
2503
|
-
*
|
|
2504
|
-
*
|
|
2505
|
-
* Полезно когда нужно принудительно выполнить действие сейчас,
|
|
2506
|
-
* игнорируя debounce.
|
|
2507
|
-
*
|
|
2508
|
-
* @param fn Функция для немедленного выполнения
|
|
2509
|
-
* @returns Promise с результатом функции
|
|
2510
|
-
*
|
|
2511
|
-
* @example
|
|
2512
|
-
* ```typescript
|
|
2513
|
-
* const debouncer = new Debouncer(300);
|
|
2514
|
-
*
|
|
2515
|
-
* // Запланировано через 300мс
|
|
2516
|
-
* debouncer.debounce(async () => console.log('Delayed'));
|
|
2517
|
-
*
|
|
2518
|
-
* // Отменяем отложенный и выполняем немедленно
|
|
2519
|
-
* await debouncer.flush(async () => console.log('Immediate'));
|
|
2520
|
-
* // Выведет: "Immediate" (сразу)
|
|
2521
|
-
* // "Delayed" не выполнится (отменен)
|
|
2522
|
-
* ```
|
|
2907
|
+
* Отправить событие всем listeners
|
|
2523
2908
|
*/
|
|
2524
|
-
|
|
2525
|
-
|
|
2909
|
+
emit(e) {
|
|
2910
|
+
this.matchesPathFilter(e.path) && (this.options.enableLogging && console.log(`[FormObserver] ${e.type} at "${e.path || "root"}":`, e.newValue), this.listeners.forEach((t) => {
|
|
2911
|
+
try {
|
|
2912
|
+
t(e);
|
|
2913
|
+
} catch {
|
|
2914
|
+
}
|
|
2915
|
+
}));
|
|
2526
2916
|
}
|
|
2527
2917
|
/**
|
|
2528
|
-
* Проверить,
|
|
2529
|
-
*
|
|
2530
|
-
* @returns true если есть запланированный вызов
|
|
2531
|
-
*
|
|
2532
|
-
* @example
|
|
2533
|
-
* ```typescript
|
|
2534
|
-
* const debouncer = new Debouncer(300);
|
|
2535
|
-
*
|
|
2536
|
-
* console.log(debouncer.isPending()); // false
|
|
2537
|
-
*
|
|
2538
|
-
* debouncer.debounce(() => console.log('Test'));
|
|
2539
|
-
* console.log(debouncer.isPending()); // true
|
|
2540
|
-
*
|
|
2541
|
-
* // Через 300мс
|
|
2542
|
-
* console.log(debouncer.isPending()); // false
|
|
2543
|
-
* ```
|
|
2918
|
+
* Проверить, нужно ли отслеживать тип события
|
|
2544
2919
|
*/
|
|
2545
|
-
|
|
2546
|
-
return this.
|
|
2920
|
+
shouldTrack(e) {
|
|
2921
|
+
return this.options.eventTypes.includes(e);
|
|
2922
|
+
}
|
|
2923
|
+
/**
|
|
2924
|
+
* Проверить, соответствует ли путь фильтру
|
|
2925
|
+
*/
|
|
2926
|
+
matchesPathFilter(e) {
|
|
2927
|
+
const { pathFilter: t } = this.options;
|
|
2928
|
+
return !t || Array.isArray(t) && t.length === 0 ? !0 : t instanceof RegExp ? t.test(e) : t.includes(e);
|
|
2929
|
+
}
|
|
2930
|
+
/**
|
|
2931
|
+
* Очистить все подписки и disposers
|
|
2932
|
+
*/
|
|
2933
|
+
dispose() {
|
|
2934
|
+
this.disposers.forEach((e) => e()), this.disposers = [], this.listeners.clear();
|
|
2547
2935
|
}
|
|
2548
2936
|
}
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
}
|
|
2561
|
-
|
|
2562
|
-
let e = null;
|
|
2563
|
-
return {
|
|
2564
|
-
type: "preload",
|
|
2565
|
-
load: async (t) => {
|
|
2566
|
-
if (!e) {
|
|
2567
|
-
const i = await r(t);
|
|
2568
|
-
e = {
|
|
2569
|
-
items: i,
|
|
2570
|
-
totalCount: i.length
|
|
2571
|
-
};
|
|
2572
|
-
}
|
|
2573
|
-
return e;
|
|
2574
|
-
}
|
|
2575
|
-
};
|
|
2576
|
-
}
|
|
2577
|
-
function te(r) {
|
|
2578
|
-
return {
|
|
2579
|
-
type: "partial",
|
|
2580
|
-
load: async (e) => {
|
|
2581
|
-
const t = await r(e);
|
|
2582
|
-
return {
|
|
2583
|
-
items: t,
|
|
2584
|
-
totalCount: t.length
|
|
2585
|
-
// Можно расширить для поддержки серверной пагинации
|
|
2586
|
-
};
|
|
2587
|
-
}
|
|
2588
|
-
};
|
|
2589
|
-
}
|
|
2590
|
-
const pe = {
|
|
2591
|
-
static: Z,
|
|
2592
|
-
preload: ee,
|
|
2593
|
-
partial: te
|
|
2594
|
-
};
|
|
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(
|
|
2937
|
+
var x = { exports: {} }, T = {};
|
|
2938
|
+
var B;
|
|
2939
|
+
function oe() {
|
|
2940
|
+
if (B) return T;
|
|
2941
|
+
B = 1;
|
|
2942
|
+
var a = U;
|
|
2943
|
+
function e(h, f) {
|
|
2944
|
+
return h === f && (h !== 0 || 1 / h === 1 / f) || h !== h && f !== f;
|
|
2945
|
+
}
|
|
2946
|
+
var t = typeof Object.is == "function" ? Object.is : e, s = a.useState, i = a.useEffect, r = a.useLayoutEffect, n = a.useDebugValue;
|
|
2947
|
+
function o(h, f) {
|
|
2948
|
+
var c = f(), p = s({ inst: { value: c, getSnapshot: f } }), y = p[0].inst, E = p[1];
|
|
2949
|
+
return r(
|
|
2608
2950
|
function() {
|
|
2609
|
-
|
|
2951
|
+
y.value = c, y.getSnapshot = f, l(y) && E({ inst: y });
|
|
2610
2952
|
},
|
|
2611
|
-
[
|
|
2612
|
-
),
|
|
2953
|
+
[h, c, f]
|
|
2954
|
+
), i(
|
|
2613
2955
|
function() {
|
|
2614
|
-
return l(
|
|
2615
|
-
l(
|
|
2956
|
+
return l(y) && E({ inst: y }), h(function() {
|
|
2957
|
+
l(y) && E({ inst: y });
|
|
2616
2958
|
});
|
|
2617
2959
|
},
|
|
2618
|
-
[
|
|
2619
|
-
),
|
|
2960
|
+
[h]
|
|
2961
|
+
), n(c), c;
|
|
2620
2962
|
}
|
|
2621
|
-
function l(
|
|
2622
|
-
var f =
|
|
2623
|
-
|
|
2963
|
+
function l(h) {
|
|
2964
|
+
var f = h.getSnapshot;
|
|
2965
|
+
h = h.value;
|
|
2624
2966
|
try {
|
|
2625
|
-
var
|
|
2626
|
-
return !t(
|
|
2967
|
+
var c = f();
|
|
2968
|
+
return !t(h, c);
|
|
2627
2969
|
} catch {
|
|
2628
2970
|
return !0;
|
|
2629
2971
|
}
|
|
2630
2972
|
}
|
|
2631
|
-
function
|
|
2973
|
+
function u(h, f) {
|
|
2632
2974
|
return f();
|
|
2633
2975
|
}
|
|
2634
|
-
var
|
|
2635
|
-
return
|
|
2976
|
+
var v = typeof window > "u" || typeof window.document > "u" || typeof window.document.createElement > "u" ? u : o;
|
|
2977
|
+
return T.useSyncExternalStore = a.useSyncExternalStore !== void 0 ? a.useSyncExternalStore : v, T;
|
|
2636
2978
|
}
|
|
2637
|
-
var
|
|
2638
|
-
var
|
|
2639
|
-
function
|
|
2640
|
-
return
|
|
2641
|
-
function
|
|
2642
|
-
return
|
|
2979
|
+
var O = {};
|
|
2980
|
+
var G;
|
|
2981
|
+
function le() {
|
|
2982
|
+
return G || (G = 1, process.env.NODE_ENV !== "production" && (function() {
|
|
2983
|
+
function a(c, p) {
|
|
2984
|
+
return c === p && (c !== 0 || 1 / c === 1 / p) || c !== c && p !== p;
|
|
2643
2985
|
}
|
|
2644
|
-
function e(
|
|
2645
|
-
|
|
2986
|
+
function e(c, p) {
|
|
2987
|
+
v || i.startTransition === void 0 || (v = !0, console.error(
|
|
2646
2988
|
"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
2989
|
));
|
|
2648
|
-
var
|
|
2649
|
-
if (!
|
|
2650
|
-
var
|
|
2651
|
-
|
|
2990
|
+
var y = p();
|
|
2991
|
+
if (!h) {
|
|
2992
|
+
var E = p();
|
|
2993
|
+
r(y, E) || (console.error(
|
|
2652
2994
|
"The result of getSnapshot should be cached to avoid an infinite loop"
|
|
2653
|
-
),
|
|
2995
|
+
), h = !0);
|
|
2654
2996
|
}
|
|
2655
|
-
|
|
2656
|
-
inst: { value:
|
|
2997
|
+
E = n({
|
|
2998
|
+
inst: { value: y, getSnapshot: p }
|
|
2657
2999
|
});
|
|
2658
|
-
var _ =
|
|
3000
|
+
var _ = E[0].inst, F = E[1];
|
|
2659
3001
|
return l(
|
|
2660
3002
|
function() {
|
|
2661
|
-
_.value =
|
|
3003
|
+
_.value = y, _.getSnapshot = p, t(_) && F({ inst: _ });
|
|
2662
3004
|
},
|
|
2663
|
-
[
|
|
2664
|
-
),
|
|
3005
|
+
[c, y, p]
|
|
3006
|
+
), o(
|
|
2665
3007
|
function() {
|
|
2666
|
-
return t(_) &&
|
|
2667
|
-
t(_) &&
|
|
3008
|
+
return t(_) && F({ inst: _ }), c(function() {
|
|
3009
|
+
t(_) && F({ inst: _ });
|
|
2668
3010
|
});
|
|
2669
3011
|
},
|
|
2670
|
-
[
|
|
2671
|
-
),
|
|
3012
|
+
[c]
|
|
3013
|
+
), u(y), y;
|
|
2672
3014
|
}
|
|
2673
|
-
function t(
|
|
2674
|
-
var
|
|
2675
|
-
|
|
3015
|
+
function t(c) {
|
|
3016
|
+
var p = c.getSnapshot;
|
|
3017
|
+
c = c.value;
|
|
2676
3018
|
try {
|
|
2677
|
-
var
|
|
2678
|
-
return !
|
|
3019
|
+
var y = p();
|
|
3020
|
+
return !r(c, y);
|
|
2679
3021
|
} catch {
|
|
2680
3022
|
return !0;
|
|
2681
3023
|
}
|
|
2682
3024
|
}
|
|
2683
|
-
function
|
|
2684
|
-
return
|
|
3025
|
+
function s(c, p) {
|
|
3026
|
+
return p();
|
|
2685
3027
|
}
|
|
2686
3028
|
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ < "u" && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart == "function" && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
|
|
2687
|
-
var
|
|
2688
|
-
|
|
2689
|
-
})()),
|
|
3029
|
+
var i = U, r = typeof Object.is == "function" ? Object.is : a, n = i.useState, o = i.useEffect, l = i.useLayoutEffect, u = i.useDebugValue, v = !1, h = !1, f = typeof window > "u" || typeof window.document > "u" || typeof window.document.createElement > "u" ? s : e;
|
|
3030
|
+
O.useSyncExternalStore = i.useSyncExternalStore !== void 0 ? i.useSyncExternalStore : f, typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ < "u" && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop == "function" && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
|
|
3031
|
+
})()), O;
|
|
2690
3032
|
}
|
|
2691
|
-
var
|
|
2692
|
-
function
|
|
2693
|
-
return
|
|
3033
|
+
var $;
|
|
3034
|
+
function ue() {
|
|
3035
|
+
return $ || ($ = 1, process.env.NODE_ENV === "production" ? x.exports = oe() : x.exports = le()), x.exports;
|
|
2694
3036
|
}
|
|
2695
|
-
var
|
|
2696
|
-
function
|
|
2697
|
-
if (
|
|
2698
|
-
if (
|
|
2699
|
-
for (let t = 0; t <
|
|
2700
|
-
if (
|
|
3037
|
+
var R = ue();
|
|
3038
|
+
function he(a, e) {
|
|
3039
|
+
if (a === e) return !0;
|
|
3040
|
+
if (a.length !== e.length) return !1;
|
|
3041
|
+
for (let t = 0; t < a.length; t++)
|
|
3042
|
+
if (a[t] !== e[t]) return !1;
|
|
2701
3043
|
return !0;
|
|
2702
3044
|
}
|
|
2703
|
-
function
|
|
2704
|
-
const
|
|
2705
|
-
if (
|
|
2706
|
-
const
|
|
2707
|
-
for (const
|
|
2708
|
-
o
|
|
2709
|
-
|
|
2710
|
-
}
|
|
2711
|
-
const
|
|
2712
|
-
(
|
|
2713
|
-
let
|
|
2714
|
-
return
|
|
2715
|
-
for (const
|
|
2716
|
-
|
|
2717
|
-
if (
|
|
2718
|
-
|
|
3045
|
+
function q(a, e, t) {
|
|
3046
|
+
const s = P(null);
|
|
3047
|
+
if (s.current === null) {
|
|
3048
|
+
const n = {};
|
|
3049
|
+
for (const o in a)
|
|
3050
|
+
n[o] = a[o].value;
|
|
3051
|
+
s.current = { ...n, __snapshot: null };
|
|
3052
|
+
}
|
|
3053
|
+
const i = b(
|
|
3054
|
+
(n) => {
|
|
3055
|
+
let o = !0;
|
|
3056
|
+
return m(() => {
|
|
3057
|
+
for (const u in a)
|
|
3058
|
+
a[u].value;
|
|
3059
|
+
if (o) {
|
|
3060
|
+
o = !1;
|
|
2719
3061
|
return;
|
|
2720
3062
|
}
|
|
2721
|
-
|
|
3063
|
+
n();
|
|
2722
3064
|
});
|
|
2723
3065
|
},
|
|
2724
|
-
[
|
|
2725
|
-
),
|
|
2726
|
-
const
|
|
2727
|
-
for (const
|
|
2728
|
-
|
|
3066
|
+
[a]
|
|
3067
|
+
), r = b(() => {
|
|
3068
|
+
const n = s.current, o = {};
|
|
3069
|
+
for (const u in a)
|
|
3070
|
+
o[u] = a[u].value;
|
|
2729
3071
|
let l = !1;
|
|
2730
|
-
for (const
|
|
2731
|
-
const { key:
|
|
2732
|
-
if (
|
|
2733
|
-
if (!
|
|
3072
|
+
for (const u of e) {
|
|
3073
|
+
const { key: v, useShallowArrayEqual: h } = u, f = o[v], c = n[v];
|
|
3074
|
+
if (h) {
|
|
3075
|
+
if (!he(c, f)) {
|
|
2734
3076
|
l = !0;
|
|
2735
3077
|
break;
|
|
2736
3078
|
}
|
|
2737
|
-
} else if (
|
|
3079
|
+
} else if (c !== f) {
|
|
2738
3080
|
l = !0;
|
|
2739
3081
|
break;
|
|
2740
3082
|
}
|
|
2741
3083
|
}
|
|
2742
|
-
if (!l &&
|
|
2743
|
-
return
|
|
2744
|
-
for (const
|
|
2745
|
-
|
|
2746
|
-
return
|
|
2747
|
-
}, [
|
|
2748
|
-
return
|
|
3084
|
+
if (!l && n.__snapshot)
|
|
3085
|
+
return n.__snapshot;
|
|
3086
|
+
for (const u in a)
|
|
3087
|
+
n[u] = o[u];
|
|
3088
|
+
return n.__snapshot = t(o), n.__snapshot;
|
|
3089
|
+
}, [a, t]);
|
|
3090
|
+
return R.useSyncExternalStore(i, r, r);
|
|
2749
3091
|
}
|
|
2750
|
-
function
|
|
3092
|
+
function de(a) {
|
|
2751
3093
|
const e = {
|
|
2752
|
-
value:
|
|
2753
|
-
disabled:
|
|
2754
|
-
errors:
|
|
2755
|
-
pending:
|
|
2756
|
-
valid:
|
|
2757
|
-
invalid:
|
|
2758
|
-
touched:
|
|
2759
|
-
shouldShowError:
|
|
2760
|
-
componentProps:
|
|
3094
|
+
value: a.value,
|
|
3095
|
+
disabled: a.disabled,
|
|
3096
|
+
errors: a.errors,
|
|
3097
|
+
pending: a.pending,
|
|
3098
|
+
valid: a.valid,
|
|
3099
|
+
invalid: a.invalid,
|
|
3100
|
+
touched: a.touched,
|
|
3101
|
+
shouldShowError: a.shouldShowError,
|
|
3102
|
+
componentProps: a.componentProps
|
|
2761
3103
|
}, t = [
|
|
2762
3104
|
{ key: "value" },
|
|
2763
3105
|
{ key: "disabled" },
|
|
@@ -2768,32 +3110,32 @@ function ne(r) {
|
|
|
2768
3110
|
{ key: "touched" },
|
|
2769
3111
|
{ key: "shouldShowError" },
|
|
2770
3112
|
{ key: "componentProps" }
|
|
2771
|
-
],
|
|
2772
|
-
(
|
|
2773
|
-
value:
|
|
2774
|
-
pending:
|
|
2775
|
-
disabled:
|
|
2776
|
-
errors:
|
|
2777
|
-
valid:
|
|
2778
|
-
invalid:
|
|
2779
|
-
touched:
|
|
2780
|
-
shouldShowError:
|
|
2781
|
-
componentProps:
|
|
3113
|
+
], s = b(
|
|
3114
|
+
(i) => ({
|
|
3115
|
+
value: i.value,
|
|
3116
|
+
pending: i.pending,
|
|
3117
|
+
disabled: i.disabled,
|
|
3118
|
+
errors: i.errors,
|
|
3119
|
+
valid: i.valid,
|
|
3120
|
+
invalid: i.invalid,
|
|
3121
|
+
touched: i.touched,
|
|
3122
|
+
shouldShowError: i.shouldShowError,
|
|
3123
|
+
componentProps: i.componentProps
|
|
2782
3124
|
}),
|
|
2783
3125
|
[]
|
|
2784
3126
|
);
|
|
2785
|
-
return
|
|
3127
|
+
return q(e, t, s);
|
|
2786
3128
|
}
|
|
2787
|
-
function
|
|
3129
|
+
function ce(a) {
|
|
2788
3130
|
const e = {
|
|
2789
|
-
value:
|
|
2790
|
-
length:
|
|
2791
|
-
errors:
|
|
2792
|
-
pending:
|
|
2793
|
-
valid:
|
|
2794
|
-
invalid:
|
|
2795
|
-
touched:
|
|
2796
|
-
dirty:
|
|
3131
|
+
value: a.value,
|
|
3132
|
+
length: a.length,
|
|
3133
|
+
errors: a.errors,
|
|
3134
|
+
pending: a.pending,
|
|
3135
|
+
valid: a.valid,
|
|
3136
|
+
invalid: a.invalid,
|
|
3137
|
+
touched: a.touched,
|
|
3138
|
+
dirty: a.dirty
|
|
2797
3139
|
}, t = [
|
|
2798
3140
|
{ key: "value" },
|
|
2799
3141
|
{ key: "length" },
|
|
@@ -2803,24 +3145,24 @@ function oe(r) {
|
|
|
2803
3145
|
{ key: "invalid" },
|
|
2804
3146
|
{ key: "touched" },
|
|
2805
3147
|
{ key: "dirty" }
|
|
2806
|
-
],
|
|
2807
|
-
(
|
|
2808
|
-
value:
|
|
2809
|
-
length:
|
|
2810
|
-
pending:
|
|
2811
|
-
errors:
|
|
2812
|
-
valid:
|
|
2813
|
-
invalid:
|
|
2814
|
-
touched:
|
|
2815
|
-
dirty:
|
|
3148
|
+
], s = b(
|
|
3149
|
+
(i) => ({
|
|
3150
|
+
value: i.value,
|
|
3151
|
+
length: i.length,
|
|
3152
|
+
pending: i.pending,
|
|
3153
|
+
errors: i.errors,
|
|
3154
|
+
valid: i.valid,
|
|
3155
|
+
invalid: i.invalid,
|
|
3156
|
+
touched: i.touched,
|
|
3157
|
+
dirty: i.dirty
|
|
2816
3158
|
}),
|
|
2817
3159
|
[]
|
|
2818
3160
|
);
|
|
2819
|
-
return
|
|
3161
|
+
return q(e, t, s);
|
|
2820
3162
|
}
|
|
2821
|
-
function
|
|
2822
|
-
const e =
|
|
2823
|
-
return
|
|
3163
|
+
function Ee(a) {
|
|
3164
|
+
const e = a && "length" in a && "map" in a;
|
|
3165
|
+
return a ? e ? ce(a) : de(a) : {
|
|
2824
3166
|
value: [],
|
|
2825
3167
|
length: 0,
|
|
2826
3168
|
pending: !1,
|
|
@@ -2831,56 +3173,99 @@ function ye(r) {
|
|
|
2831
3173
|
dirty: !1
|
|
2832
3174
|
};
|
|
2833
3175
|
}
|
|
2834
|
-
function
|
|
2835
|
-
const e =
|
|
2836
|
-
(
|
|
2837
|
-
let
|
|
2838
|
-
return
|
|
2839
|
-
if (
|
|
2840
|
-
|
|
3176
|
+
function _e(a) {
|
|
3177
|
+
const e = P({ value: a.value.value }), t = b(
|
|
3178
|
+
(i) => {
|
|
3179
|
+
let r = !0;
|
|
3180
|
+
return m(() => {
|
|
3181
|
+
if (a.value.value, r) {
|
|
3182
|
+
r = !1;
|
|
3183
|
+
return;
|
|
3184
|
+
}
|
|
3185
|
+
i();
|
|
3186
|
+
});
|
|
3187
|
+
},
|
|
3188
|
+
[a]
|
|
3189
|
+
), s = b(() => {
|
|
3190
|
+
const i = a.value.value;
|
|
3191
|
+
return e.current.value === i ? e.current.value : (e.current.value = i, i);
|
|
3192
|
+
}, [a]);
|
|
3193
|
+
return R.useSyncExternalStore(t, s, s);
|
|
3194
|
+
}
|
|
3195
|
+
function Se(a) {
|
|
3196
|
+
const e = P({ length: a.length.value }), t = b(
|
|
3197
|
+
(i) => {
|
|
3198
|
+
let r = !0;
|
|
3199
|
+
return m(() => {
|
|
3200
|
+
if (a.length.value, r) {
|
|
3201
|
+
r = !1;
|
|
2841
3202
|
return;
|
|
2842
3203
|
}
|
|
2843
|
-
|
|
3204
|
+
i();
|
|
2844
3205
|
});
|
|
2845
3206
|
},
|
|
2846
|
-
[
|
|
2847
|
-
),
|
|
2848
|
-
const
|
|
2849
|
-
return e.current.
|
|
2850
|
-
}, [
|
|
2851
|
-
return
|
|
3207
|
+
[a]
|
|
3208
|
+
), s = b(() => {
|
|
3209
|
+
const i = a.length.value;
|
|
3210
|
+
return e.current.length === i ? e.current.length : (e.current.length = i, i);
|
|
3211
|
+
}, [a]);
|
|
3212
|
+
return R.useSyncExternalStore(t, s, s);
|
|
3213
|
+
}
|
|
3214
|
+
function Ve(a, e, t) {
|
|
3215
|
+
const s = b(
|
|
3216
|
+
(r) => {
|
|
3217
|
+
const n = e, o = [];
|
|
3218
|
+
for (const l of Object.keys(n)) {
|
|
3219
|
+
const u = n[l];
|
|
3220
|
+
if (u && typeof u == "object" && u.value && typeof u.value.subscribe == "function") {
|
|
3221
|
+
const v = u.value.subscribe(r);
|
|
3222
|
+
o.push(v);
|
|
3223
|
+
}
|
|
3224
|
+
}
|
|
3225
|
+
return () => {
|
|
3226
|
+
o.forEach((l) => l());
|
|
3227
|
+
};
|
|
3228
|
+
},
|
|
3229
|
+
[e]
|
|
3230
|
+
), i = b(() => a ? a(e, t) : !1, [a, e, t]);
|
|
3231
|
+
return Q(s, i, i);
|
|
2852
3232
|
}
|
|
2853
3233
|
export {
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
3234
|
+
ke as AbstractRegistry,
|
|
3235
|
+
L as ArrayNode,
|
|
3236
|
+
V as ErrorStrategy,
|
|
3237
|
+
ee as FieldNode,
|
|
3238
|
+
se as FieldPathNavigator,
|
|
3239
|
+
S as FormErrorHandler,
|
|
3240
|
+
C as FormNode,
|
|
3241
|
+
be as FormObserver,
|
|
3242
|
+
Z as FormStatusMachine,
|
|
3243
|
+
ae as FormSubmitter,
|
|
3244
|
+
k as GroupNode,
|
|
3245
|
+
ne as NodeFactory,
|
|
3246
|
+
xe as RegistryStack,
|
|
3247
|
+
D as SubscriptionManager,
|
|
3248
|
+
$e as behaviors,
|
|
2867
3249
|
I as createFieldPath,
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
3250
|
+
ge as createForm,
|
|
3251
|
+
Ie as extractKey,
|
|
3252
|
+
Le as extractPath,
|
|
3253
|
+
Fe as getCurrentBehaviorRegistry,
|
|
3254
|
+
Te as getCurrentValidationRegistry,
|
|
3255
|
+
Pe as getNodeType,
|
|
3256
|
+
N as isArrayNode,
|
|
3257
|
+
M as isFieldNode,
|
|
3258
|
+
Ce as isFormNode,
|
|
3259
|
+
De as isGroupNode,
|
|
3260
|
+
We as runOutsideEffect,
|
|
3261
|
+
qe as safeCallback,
|
|
3262
|
+
je as safeDebouncedCallback,
|
|
3263
|
+
Be as toFieldPath,
|
|
3264
|
+
A as uniqueId,
|
|
3265
|
+
Se as useArrayLength,
|
|
3266
|
+
Ee as useFormControl,
|
|
3267
|
+
_e as useFormControlValue,
|
|
3268
|
+
Ve as useHiddenCondition,
|
|
3269
|
+
Re as validateForm,
|
|
3270
|
+
Me as validators
|
|
2886
3271
|
};
|