@reformer/core 2.0.0-beta.7 → 2.0.0-beta.8
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 +26 -12
- 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 +11 -15
- package/dist/core/nodes/field-node.d.ts +43 -24
- package/dist/core/nodes/form-node.d.ts +18 -20
- package/dist/core/nodes/group-node.d.ts +25 -21
- 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 +26 -26
- package/dist/core/types/form-proxy.d.ts +1 -31
- package/dist/core/types/index.d.ts +16 -4
- 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 +1 -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 +8 -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 +34 -7
- 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 +38 -14
- package/dist/core/validation/validation-registry.d.ts +11 -20
- 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 +1031 -714
- 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 +7878 -311
- package/package.json +83 -9
- package/dist/behaviors-DyPzh2-X.js +0 -508
- 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--8-OogF8.js +0 -477
- package/dist/validators-CWdzevnC.js +0 -397
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 F {
|
|
|
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 F {
|
|
|
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 F {
|
|
|
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 [i,
|
|
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 F {
|
|
|
283
285
|
onEnable() {
|
|
284
286
|
}
|
|
285
287
|
}
|
|
286
|
-
class
|
|
288
|
+
class D {
|
|
287
289
|
/**
|
|
288
290
|
* Хранилище подписок
|
|
289
291
|
* Ключ: уникальный идентификатор подписки
|
|
@@ -451,161 +453,196 @@ class C {
|
|
|
451
453
|
this.clear();
|
|
452
454
|
}
|
|
453
455
|
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
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}`;
|
|
457
473
|
}
|
|
458
|
-
|
|
459
|
-
|
|
474
|
+
class Z {
|
|
475
|
+
/** Внутренний сигнал статуса */
|
|
476
|
+
_status;
|
|
477
|
+
/** Публичный read-only сигнал статуса */
|
|
478
|
+
status;
|
|
479
|
+
/** Поле валидно */
|
|
480
|
+
valid;
|
|
481
|
+
/** Поле невалидно */
|
|
482
|
+
invalid;
|
|
483
|
+
/** Идет валидация */
|
|
484
|
+
pending;
|
|
485
|
+
/** Поле отключено */
|
|
486
|
+
disabled;
|
|
460
487
|
/**
|
|
461
|
-
*
|
|
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
|
+
* Начать валидацию
|
|
462
495
|
*
|
|
463
|
-
*
|
|
464
|
-
* @param context Контекст ошибки для логирования (например, 'AsyncValidator', 'BehaviorRegistry')
|
|
465
|
-
* @param strategy Стратегия обработки (THROW | LOG | CONVERT)
|
|
466
|
-
* @returns ValidationError если strategy = CONVERT, undefined если strategy = LOG, никогда не возвращается если strategy = THROW
|
|
496
|
+
* Переводит статус в 'pending' если поле не отключено
|
|
467
497
|
*
|
|
468
498
|
* @example
|
|
469
499
|
* ```typescript
|
|
470
|
-
*
|
|
471
|
-
*
|
|
472
|
-
*
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
500
|
+
* statusMachine.startValidation();
|
|
501
|
+
* // status: 'pending'
|
|
502
|
+
* ```
|
|
503
|
+
*/
|
|
504
|
+
startValidation() {
|
|
505
|
+
this._status.value !== "disabled" && (this._status.value = "pending");
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Завершить валидацию
|
|
477
509
|
*
|
|
478
|
-
*
|
|
479
|
-
* try {
|
|
480
|
-
* nonCriticalOperation();
|
|
481
|
-
* } catch (error) {
|
|
482
|
-
* FormErrorHandler.handle(error, 'NonCritical', ErrorStrategy.LOG);
|
|
483
|
-
* // Продолжаем выполнение
|
|
484
|
-
* }
|
|
510
|
+
* @param hasErrors - Есть ли ошибки валидации
|
|
485
511
|
*
|
|
486
|
-
*
|
|
487
|
-
*
|
|
488
|
-
*
|
|
489
|
-
*
|
|
490
|
-
*
|
|
491
|
-
*
|
|
492
|
-
*
|
|
493
|
-
*
|
|
494
|
-
*
|
|
495
|
-
* return validationError;
|
|
496
|
-
* }
|
|
512
|
+
* @example
|
|
513
|
+
* ```typescript
|
|
514
|
+
* // Валидация успешна
|
|
515
|
+
* statusMachine.completeValidation(false);
|
|
516
|
+
* // status: 'valid'
|
|
517
|
+
*
|
|
518
|
+
* // Есть ошибки
|
|
519
|
+
* statusMachine.completeValidation(true);
|
|
520
|
+
* // status: 'invalid'
|
|
497
521
|
* ```
|
|
498
522
|
*/
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
switch (r) {
|
|
502
|
-
case "throw":
|
|
503
|
-
throw e;
|
|
504
|
-
case "log":
|
|
505
|
-
return;
|
|
506
|
-
case "convert":
|
|
507
|
-
return {
|
|
508
|
-
code: "validator_error",
|
|
509
|
-
message: i,
|
|
510
|
-
params: { field: t }
|
|
511
|
-
};
|
|
512
|
-
}
|
|
523
|
+
completeValidation(e) {
|
|
524
|
+
(this._status.value === "pending" || this._status.value !== "disabled") && (this._status.value = e ? "invalid" : "valid");
|
|
513
525
|
}
|
|
514
526
|
/**
|
|
515
|
-
*
|
|
527
|
+
* Установить ошибки напрямую (без перехода через pending)
|
|
516
528
|
*
|
|
517
|
-
*
|
|
518
|
-
* - Error объекты → error.message
|
|
519
|
-
* - Строки → возвращает как есть
|
|
520
|
-
* - Объекты с message → извлекает message
|
|
521
|
-
* - Другое → String(error)
|
|
529
|
+
* Используется для синхронной валидации или установки ошибок извне
|
|
522
530
|
*
|
|
523
|
-
* @param
|
|
524
|
-
* @returns Сообщение ошибки
|
|
525
|
-
* @private
|
|
531
|
+
* @param hasErrors - Есть ли ошибки
|
|
526
532
|
*
|
|
527
533
|
* @example
|
|
528
534
|
* ```typescript
|
|
529
|
-
*
|
|
530
|
-
* // '
|
|
531
|
-
*
|
|
532
|
-
|
|
533
|
-
|
|
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
|
+
* Отключить поле
|
|
534
544
|
*
|
|
535
|
-
*
|
|
536
|
-
* // 'Object error'
|
|
545
|
+
* Переводит статус в 'disabled'
|
|
537
546
|
*
|
|
538
|
-
*
|
|
539
|
-
*
|
|
547
|
+
* @example
|
|
548
|
+
* ```typescript
|
|
549
|
+
* statusMachine.disable();
|
|
550
|
+
* // status: 'disabled'
|
|
540
551
|
* ```
|
|
541
552
|
*/
|
|
542
|
-
|
|
543
|
-
|
|
553
|
+
disable() {
|
|
554
|
+
this._status.value = "disabled";
|
|
544
555
|
}
|
|
545
556
|
/**
|
|
546
|
-
*
|
|
557
|
+
* Включить поле
|
|
547
558
|
*
|
|
548
|
-
*
|
|
549
|
-
*
|
|
550
|
-
* @param code Код ошибки
|
|
551
|
-
* @param message Сообщение ошибки
|
|
552
|
-
* @param field Поле (опционально)
|
|
553
|
-
* @returns ValidationError объект
|
|
559
|
+
* @param hasErrors - Есть ли ошибки (определяет valid/invalid)
|
|
554
560
|
*
|
|
555
561
|
* @example
|
|
556
562
|
* ```typescript
|
|
557
|
-
*
|
|
558
|
-
*
|
|
559
|
-
*
|
|
560
|
-
*
|
|
561
|
-
*
|
|
562
|
-
* // { code: 'required', message: 'This field is required', field: 'email' }
|
|
563
|
+
* statusMachine.enable(false);
|
|
564
|
+
* // status: 'valid'
|
|
565
|
+
*
|
|
566
|
+
* statusMachine.enable(true);
|
|
567
|
+
* // status: 'invalid'
|
|
563
568
|
* ```
|
|
564
569
|
*/
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
code: e,
|
|
568
|
-
message: t,
|
|
569
|
-
params: r ? { field: r } : void 0
|
|
570
|
-
};
|
|
570
|
+
enable(e = !1) {
|
|
571
|
+
this._status.value = e ? "invalid" : "valid";
|
|
571
572
|
}
|
|
572
573
|
/**
|
|
573
|
-
*
|
|
574
|
-
*
|
|
575
|
-
* Type guard для ValidationError
|
|
574
|
+
* Обработать событие (альтернативный API)
|
|
576
575
|
*
|
|
577
|
-
* @param
|
|
578
|
-
* @returns true если value является ValidationError
|
|
576
|
+
* @param event - Событие для обработки
|
|
579
577
|
*
|
|
580
578
|
* @example
|
|
581
579
|
* ```typescript
|
|
582
|
-
*
|
|
583
|
-
*
|
|
584
|
-
* }
|
|
580
|
+
* statusMachine.dispatch({ type: 'START_VALIDATION' });
|
|
581
|
+
* statusMachine.dispatch({ type: 'VALIDATION_FAILURE' });
|
|
585
582
|
* ```
|
|
586
583
|
*/
|
|
587
|
-
|
|
588
|
-
|
|
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";
|
|
589
617
|
}
|
|
590
618
|
}
|
|
591
|
-
class
|
|
619
|
+
class ee extends C {
|
|
592
620
|
// ============================================================================
|
|
593
621
|
// Приватные сигналы
|
|
594
622
|
// ============================================================================
|
|
595
623
|
_value;
|
|
596
624
|
_errors;
|
|
597
|
-
// _touched, _dirty
|
|
598
|
-
|
|
625
|
+
// _touched, _dirty наследуются от FormNode (protected)
|
|
626
|
+
// _status управляется через statusMachine
|
|
599
627
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
600
628
|
_componentProps;
|
|
629
|
+
/**
|
|
630
|
+
* State machine для управления статусом поля
|
|
631
|
+
* Централизует логику переходов между valid/invalid/pending/disabled
|
|
632
|
+
*/
|
|
633
|
+
statusMachine;
|
|
601
634
|
// ============================================================================
|
|
602
635
|
// Публичные computed signals
|
|
603
636
|
// ============================================================================
|
|
604
637
|
value;
|
|
638
|
+
// valid, invalid, pending, status, disabled берутся из statusMachine
|
|
605
639
|
valid;
|
|
606
640
|
invalid;
|
|
607
|
-
// touched, dirty, status наследуются от FormNode
|
|
608
641
|
pending;
|
|
642
|
+
// Override status и disabled из базового класса
|
|
643
|
+
status;
|
|
644
|
+
disabled;
|
|
645
|
+
// touched, dirty наследуются от FormNode
|
|
609
646
|
errors;
|
|
610
647
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
611
648
|
componentProps;
|
|
@@ -621,23 +658,26 @@ class Q extends F {
|
|
|
621
658
|
asyncValidators;
|
|
622
659
|
updateOn;
|
|
623
660
|
initialValue;
|
|
624
|
-
currentValidationId = 0;
|
|
625
661
|
currentAbortController;
|
|
626
662
|
debounceMs;
|
|
627
663
|
validateDebounceTimer;
|
|
628
|
-
|
|
664
|
+
/**
|
|
665
|
+
* Pending debounced validation state
|
|
666
|
+
* Contains resolve function and AbortController for cancellation
|
|
667
|
+
*/
|
|
668
|
+
pendingValidation;
|
|
629
669
|
/**
|
|
630
670
|
* Менеджер подписок для централизованного cleanup
|
|
631
671
|
* Использует SubscriptionManager вместо массива для управления подписками
|
|
632
672
|
*/
|
|
633
|
-
disposers = new
|
|
673
|
+
disposers = new D();
|
|
634
674
|
component;
|
|
635
675
|
// ============================================================================
|
|
636
676
|
// Конструктор
|
|
637
677
|
// ============================================================================
|
|
638
678
|
constructor(e) {
|
|
639
|
-
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 =
|
|
640
|
-
() => 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)
|
|
641
681
|
);
|
|
642
682
|
}
|
|
643
683
|
// ============================================================================
|
|
@@ -649,12 +689,12 @@ class Q extends F {
|
|
|
649
689
|
setValue(e, t) {
|
|
650
690
|
if (this._value.value = e, this._dirty.value = !0, t?.emitEvent === !1)
|
|
651
691
|
return;
|
|
652
|
-
const
|
|
692
|
+
const s = this.validators.length > 0 || this.asyncValidators.length > 0, i = this._errors.value.length > 0;
|
|
653
693
|
if (this.updateOn === "change") {
|
|
654
694
|
this.validate();
|
|
655
695
|
return;
|
|
656
696
|
}
|
|
657
|
-
i &&
|
|
697
|
+
i && s && this.validate();
|
|
658
698
|
}
|
|
659
699
|
patchValue(e) {
|
|
660
700
|
this.setValue(e);
|
|
@@ -683,7 +723,7 @@ class Q extends F {
|
|
|
683
723
|
* ```
|
|
684
724
|
*/
|
|
685
725
|
reset(e) {
|
|
686
|
-
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);
|
|
687
727
|
}
|
|
688
728
|
/**
|
|
689
729
|
* Сбросить поле к исходному значению (initialValue)
|
|
@@ -713,13 +753,25 @@ class Q extends F {
|
|
|
713
753
|
resetToInitial() {
|
|
714
754
|
this.reset(this.initialValue);
|
|
715
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
|
+
}
|
|
716
768
|
/**
|
|
717
769
|
* Запустить валидацию поля
|
|
718
770
|
* @param options - опции валидации
|
|
719
771
|
* @returns `Promise<boolean>` - true если поле валидно
|
|
720
772
|
*
|
|
721
773
|
* @remarks
|
|
722
|
-
* Метод защищен от race conditions через
|
|
774
|
+
* Метод защищен от race conditions через AbortController.
|
|
723
775
|
* При быстром вводе только последняя валидация применяет результаты.
|
|
724
776
|
*
|
|
725
777
|
* @example
|
|
@@ -733,86 +785,102 @@ class Q extends F {
|
|
|
733
785
|
*/
|
|
734
786
|
async validate(e) {
|
|
735
787
|
const t = e?.debounce ?? this.debounceMs;
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
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) {
|
|
794
|
+
i(!1);
|
|
741
795
|
return;
|
|
742
796
|
}
|
|
743
|
-
|
|
744
|
-
r(
|
|
745
|
-
|
|
746
|
-
|
|
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
|
+
});
|
|
747
808
|
}
|
|
748
809
|
/**
|
|
749
810
|
* Немедленная валидация без debounce
|
|
750
811
|
* @private
|
|
812
|
+
* @param providedController - AbortController from debounced validate()
|
|
751
813
|
* @remarks
|
|
752
814
|
* Защищена от race conditions через AbortController:
|
|
753
|
-
* - Отменяет предыдущую валидацию при запуске новой
|
|
815
|
+
* - Отменяет предыдущую валидацию при запуске новой (if no controller provided)
|
|
754
816
|
* - Передаёт AbortSignal в async валидаторы для отмены операций (например, fetch)
|
|
755
817
|
* - Проверяет signal.aborted в ключевых точках
|
|
756
818
|
*/
|
|
757
|
-
async validateImmediate() {
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
const
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
for (const a of this.validators) {
|
|
765
|
-
const n = a(this._value.value);
|
|
766
|
-
n && r.push(n);
|
|
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);
|
|
767
826
|
}
|
|
768
|
-
if (
|
|
827
|
+
if (s.aborted)
|
|
769
828
|
return !1;
|
|
770
|
-
if (
|
|
771
|
-
|
|
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)
|
|
833
|
+
return !1;
|
|
834
|
+
}
|
|
772
835
|
if (this.asyncValidators.length > 0) {
|
|
773
|
-
if (
|
|
836
|
+
if (s.aborted)
|
|
774
837
|
return !1;
|
|
775
|
-
this.
|
|
838
|
+
this.statusMachine.startValidation();
|
|
776
839
|
try {
|
|
777
|
-
const
|
|
778
|
-
this.asyncValidators.map(async (
|
|
779
|
-
if (
|
|
840
|
+
const n = await Promise.all(
|
|
841
|
+
this.asyncValidators.map(async (l) => {
|
|
842
|
+
if (s.aborted)
|
|
780
843
|
throw new DOMException("Validation aborted", "AbortError");
|
|
781
844
|
try {
|
|
782
|
-
const
|
|
783
|
-
if (
|
|
845
|
+
const u = await l(this._value.value, { signal: s });
|
|
846
|
+
if (s.aborted)
|
|
784
847
|
throw new DOMException("Validation aborted", "AbortError");
|
|
785
|
-
return
|
|
786
|
-
} catch (
|
|
787
|
-
if (
|
|
788
|
-
throw
|
|
789
|
-
return
|
|
790
|
-
|
|
848
|
+
return u;
|
|
849
|
+
} catch (u) {
|
|
850
|
+
if (u instanceof DOMException && u.name === "AbortError")
|
|
851
|
+
throw u;
|
|
852
|
+
return S.handle(
|
|
853
|
+
u,
|
|
791
854
|
"FieldNode AsyncValidator",
|
|
792
855
|
V.CONVERT
|
|
793
856
|
);
|
|
794
857
|
}
|
|
795
858
|
})
|
|
796
859
|
);
|
|
797
|
-
if (
|
|
860
|
+
if (s.aborted)
|
|
798
861
|
return !1;
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
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")
|
|
805
871
|
return !1;
|
|
806
|
-
throw
|
|
872
|
+
throw n;
|
|
807
873
|
}
|
|
808
874
|
}
|
|
809
|
-
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"));
|
|
810
876
|
}
|
|
811
877
|
setErrors(e) {
|
|
812
|
-
this._errors.value = e
|
|
878
|
+
this._errors.value = e;
|
|
879
|
+
const t = e.some((s) => s.severity !== "warning");
|
|
880
|
+
this.statusMachine.setErrors(t);
|
|
813
881
|
}
|
|
814
882
|
clearErrors() {
|
|
815
|
-
this._errors.value = [], this.
|
|
883
|
+
this._errors.value = [], this.statusMachine.setErrors(!1);
|
|
816
884
|
}
|
|
817
885
|
// ============================================================================
|
|
818
886
|
// Protected hooks (Template Method pattern)
|
|
@@ -828,18 +896,18 @@ class Q extends F {
|
|
|
828
896
|
/**
|
|
829
897
|
* Hook: вызывается после disable()
|
|
830
898
|
*
|
|
831
|
-
* Для FieldNode: очищаем ошибки
|
|
899
|
+
* Для FieldNode: синхронизируем statusMachine и очищаем ошибки
|
|
832
900
|
*/
|
|
833
901
|
onDisable() {
|
|
834
|
-
this._errors.value = [];
|
|
902
|
+
this.statusMachine.disable(), this._errors.value = [];
|
|
835
903
|
}
|
|
836
904
|
/**
|
|
837
905
|
* Hook: вызывается после enable()
|
|
838
906
|
*
|
|
839
|
-
* Для FieldNode: запускаем валидацию
|
|
907
|
+
* Для FieldNode: синхронизируем statusMachine и запускаем валидацию
|
|
840
908
|
*/
|
|
841
909
|
onEnable() {
|
|
842
|
-
this.validate();
|
|
910
|
+
this.statusMachine.enable(this._errors.value.length > 0), this.validate();
|
|
843
911
|
}
|
|
844
912
|
/**
|
|
845
913
|
* Обновляет свойства компонента (например, опции для Select)
|
|
@@ -904,25 +972,35 @@ class Q extends F {
|
|
|
904
972
|
* Подписка на изменения значения поля
|
|
905
973
|
* Автоматически отслеживает изменения через @preact/signals effect
|
|
906
974
|
*
|
|
907
|
-
* @param callback - Функция, вызываемая при изменении
|
|
975
|
+
* @param callback - Функция, вызываемая при изменении значения.
|
|
976
|
+
* Для async операций передается AbortSignal во втором параметре.
|
|
908
977
|
* @returns Функция отписки для cleanup
|
|
909
978
|
*
|
|
910
979
|
* @example
|
|
911
980
|
* ```typescript
|
|
981
|
+
* // Синхронный callback
|
|
912
982
|
* const unsubscribe = form.email.watch((value) => {
|
|
913
983
|
* console.log('Email changed:', value);
|
|
914
984
|
* });
|
|
915
985
|
*
|
|
986
|
+
* // Асинхронный callback с поддержкой отмены
|
|
987
|
+
* const unsubscribe = form.email.watch(async (value, signal) => {
|
|
988
|
+
* const result = await fetch('/api/validate', { signal });
|
|
989
|
+
* // ...
|
|
990
|
+
* });
|
|
991
|
+
*
|
|
916
992
|
* // Cleanup
|
|
917
993
|
* useEffect(() => unsubscribe, []);
|
|
918
994
|
* ```
|
|
919
995
|
*/
|
|
920
996
|
watch(e) {
|
|
921
|
-
const t =
|
|
922
|
-
const
|
|
923
|
-
e(
|
|
924
|
-
}),
|
|
925
|
-
return this.disposers.add(
|
|
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
|
+
});
|
|
926
1004
|
}
|
|
927
1005
|
/**
|
|
928
1006
|
* Вычисляемое значение из других полей
|
|
@@ -947,11 +1025,11 @@ class Q extends F {
|
|
|
947
1025
|
* ```
|
|
948
1026
|
*/
|
|
949
1027
|
computeFrom(e, t) {
|
|
950
|
-
const
|
|
951
|
-
const
|
|
1028
|
+
const s = m(() => {
|
|
1029
|
+
const r = e.map((o) => o.value), n = t(...r);
|
|
952
1030
|
this.setValue(n, { emitEvent: !1 });
|
|
953
|
-
}), i =
|
|
954
|
-
return this.disposers.add(i,
|
|
1031
|
+
}), i = A(w.ComputeFrom);
|
|
1032
|
+
return this.disposers.add(i, s);
|
|
955
1033
|
}
|
|
956
1034
|
/**
|
|
957
1035
|
* Очистить все ресурсы и таймеры
|
|
@@ -960,9 +1038,9 @@ class Q extends F {
|
|
|
960
1038
|
* @remarks
|
|
961
1039
|
* Освобождает все ресурсы:
|
|
962
1040
|
* - Отписывает все subscriptions через SubscriptionManager
|
|
963
|
-
* -
|
|
964
|
-
*
|
|
965
|
-
* -
|
|
1041
|
+
* - Отменяет pending/running валидации через cancelPendingValidation()
|
|
1042
|
+
*
|
|
1043
|
+
* Использует try-finally для гарантированного cleanup даже при ошибках.
|
|
966
1044
|
*
|
|
967
1045
|
* @example
|
|
968
1046
|
* ```typescript
|
|
@@ -974,10 +1052,14 @@ class Q extends F {
|
|
|
974
1052
|
* ```
|
|
975
1053
|
*/
|
|
976
1054
|
dispose() {
|
|
977
|
-
|
|
1055
|
+
try {
|
|
1056
|
+
this.disposers.dispose();
|
|
1057
|
+
} finally {
|
|
1058
|
+
this.cancelPendingValidation();
|
|
1059
|
+
}
|
|
978
1060
|
}
|
|
979
1061
|
}
|
|
980
|
-
class
|
|
1062
|
+
class te {
|
|
981
1063
|
form;
|
|
982
1064
|
constructor(e) {
|
|
983
1065
|
this.form = e;
|
|
@@ -993,8 +1075,8 @@ class X {
|
|
|
993
1075
|
* @param validators Зарегистрированные валидаторы
|
|
994
1076
|
*/
|
|
995
1077
|
async apply(e) {
|
|
996
|
-
const { validatorsByField: t, treeValidators:
|
|
997
|
-
await this.applyFieldValidators(t), this.applyTreeValidators(
|
|
1078
|
+
const { validatorsByField: t, treeValidators: s } = this.groupValidators(e);
|
|
1079
|
+
await this.applyFieldValidators(t), this.applyTreeValidators(s);
|
|
998
1080
|
}
|
|
999
1081
|
/**
|
|
1000
1082
|
* Группировка валидаторов по типам
|
|
@@ -1007,15 +1089,15 @@ class X {
|
|
|
1007
1089
|
* @returns Сгруппированные валидаторы
|
|
1008
1090
|
*/
|
|
1009
1091
|
groupValidators(e) {
|
|
1010
|
-
const t = /* @__PURE__ */ new Map(),
|
|
1092
|
+
const t = /* @__PURE__ */ new Map(), s = [];
|
|
1011
1093
|
for (const i of e)
|
|
1012
1094
|
if (i.type === "tree")
|
|
1013
|
-
|
|
1095
|
+
s.push(i);
|
|
1014
1096
|
else {
|
|
1015
|
-
const
|
|
1016
|
-
|
|
1097
|
+
const r = t.get(i.fieldPath) || [];
|
|
1098
|
+
r.push(i), t.set(i.fieldPath, r);
|
|
1017
1099
|
}
|
|
1018
|
-
return { validatorsByField: t, treeValidators:
|
|
1100
|
+
return { validatorsByField: t, treeValidators: s };
|
|
1019
1101
|
}
|
|
1020
1102
|
/**
|
|
1021
1103
|
* Применение field валидаторов к полям
|
|
@@ -1029,44 +1111,44 @@ class X {
|
|
|
1029
1111
|
* @param validatorsByField Валидаторы, сгруппированные по полям
|
|
1030
1112
|
*/
|
|
1031
1113
|
async applyFieldValidators(e) {
|
|
1032
|
-
for (const [t,
|
|
1114
|
+
for (const [t, s] of e) {
|
|
1033
1115
|
const i = this.form.getFieldByPath(t);
|
|
1034
1116
|
if (!i) {
|
|
1035
1117
|
console.warn(`Field ${t} not found in GroupNode`);
|
|
1036
1118
|
continue;
|
|
1037
1119
|
}
|
|
1038
|
-
if (!
|
|
1120
|
+
if (!M(i) && !N(i)) {
|
|
1039
1121
|
process.env.NODE_ENV !== "production" && console.warn(`Validation can only run on FieldNode or ArrayNode, skipping ${t}`);
|
|
1040
1122
|
continue;
|
|
1041
1123
|
}
|
|
1042
|
-
const
|
|
1124
|
+
const r = [];
|
|
1043
1125
|
let n;
|
|
1044
|
-
if (
|
|
1126
|
+
if (N(i)) {
|
|
1045
1127
|
const o = i.getValue();
|
|
1046
|
-
n = new
|
|
1128
|
+
n = new z(this.form, t, o);
|
|
1047
1129
|
} else
|
|
1048
|
-
n = new
|
|
1049
|
-
for (const o of
|
|
1130
|
+
n = new J(this.form, t, i);
|
|
1131
|
+
for (const o of s)
|
|
1050
1132
|
if (!(o.condition && !this.checkCondition(o.condition)))
|
|
1051
1133
|
try {
|
|
1052
1134
|
let l = null;
|
|
1053
|
-
const
|
|
1135
|
+
const u = n.value();
|
|
1054
1136
|
if (o.type === "sync") {
|
|
1055
|
-
const
|
|
1056
|
-
l =
|
|
1137
|
+
const v = o.validator;
|
|
1138
|
+
l = v(u, n);
|
|
1057
1139
|
} else if (o.type === "async") {
|
|
1058
|
-
const
|
|
1059
|
-
l = await
|
|
1140
|
+
const v = o.validator;
|
|
1141
|
+
l = await v(u, n);
|
|
1060
1142
|
}
|
|
1061
|
-
l &&
|
|
1143
|
+
l && r.push(l);
|
|
1062
1144
|
} catch (l) {
|
|
1063
|
-
|
|
1145
|
+
S.handle(
|
|
1064
1146
|
l,
|
|
1065
1147
|
`ValidationApplicator: validator for ${t}`,
|
|
1066
1148
|
V.LOG
|
|
1067
1149
|
);
|
|
1068
1150
|
}
|
|
1069
|
-
|
|
1151
|
+
r.length > 0 ? i.setErrors(r) : i.clearErrors();
|
|
1070
1152
|
}
|
|
1071
1153
|
}
|
|
1072
1154
|
/**
|
|
@@ -1079,24 +1161,24 @@ class X {
|
|
|
1079
1161
|
*/
|
|
1080
1162
|
applyTreeValidators(e) {
|
|
1081
1163
|
for (const t of e) {
|
|
1082
|
-
const
|
|
1164
|
+
const s = new Y(this.form);
|
|
1083
1165
|
if (!(t.condition && !this.checkCondition(t.condition)))
|
|
1084
1166
|
try {
|
|
1085
1167
|
if (t.type !== "tree")
|
|
1086
1168
|
continue;
|
|
1087
|
-
const i = t.validator,
|
|
1088
|
-
if (
|
|
1169
|
+
const i = t.validator, r = i(s);
|
|
1170
|
+
if (r && t.options && "targetField" in t.options) {
|
|
1089
1171
|
const n = t.options.targetField;
|
|
1090
1172
|
if (n) {
|
|
1091
1173
|
const o = this.form.getFieldByPath(String(n));
|
|
1092
|
-
if (o &&
|
|
1174
|
+
if (o && M(o)) {
|
|
1093
1175
|
const l = o.errors.value;
|
|
1094
|
-
o.setErrors([...l,
|
|
1176
|
+
o.setErrors([...l, r]);
|
|
1095
1177
|
}
|
|
1096
1178
|
}
|
|
1097
1179
|
}
|
|
1098
1180
|
} catch (i) {
|
|
1099
|
-
|
|
1181
|
+
S.handle(i, "ValidationApplicator: tree validator", V.LOG);
|
|
1100
1182
|
}
|
|
1101
1183
|
}
|
|
1102
1184
|
}
|
|
@@ -1113,11 +1195,11 @@ class X {
|
|
|
1113
1195
|
const t = this.form.getFieldByPath(e.fieldPath);
|
|
1114
1196
|
if (!t)
|
|
1115
1197
|
return !1;
|
|
1116
|
-
const
|
|
1117
|
-
return e.conditionFn(
|
|
1198
|
+
const s = t.value.value;
|
|
1199
|
+
return e.conditionFn(s);
|
|
1118
1200
|
}
|
|
1119
1201
|
}
|
|
1120
|
-
class
|
|
1202
|
+
class se {
|
|
1121
1203
|
/**
|
|
1122
1204
|
* Парсит путь в массив сегментов
|
|
1123
1205
|
*
|
|
@@ -1144,22 +1226,22 @@ class Z {
|
|
|
1144
1226
|
*/
|
|
1145
1227
|
parsePath(e) {
|
|
1146
1228
|
const t = [];
|
|
1147
|
-
let
|
|
1148
|
-
for (let
|
|
1149
|
-
const n = e[
|
|
1150
|
-
n === "[" ? (i = !0,
|
|
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;
|
|
1151
1233
|
}
|
|
1152
|
-
return
|
|
1234
|
+
return s && this.addSegment(t, s), t;
|
|
1153
1235
|
}
|
|
1154
1236
|
/**
|
|
1155
1237
|
* Добавляет сегмент в массив, обрабатывая массивы
|
|
1156
1238
|
* @private
|
|
1157
1239
|
*/
|
|
1158
1240
|
addSegment(e, t) {
|
|
1159
|
-
const
|
|
1160
|
-
|
|
1161
|
-
key:
|
|
1162
|
-
index: parseInt(
|
|
1241
|
+
const s = t.match(/^(.+)\[(\d+)\]$/);
|
|
1242
|
+
s ? e.push({
|
|
1243
|
+
key: s[1],
|
|
1244
|
+
index: parseInt(s[2], 10)
|
|
1163
1245
|
}) : e.push({ key: t });
|
|
1164
1246
|
}
|
|
1165
1247
|
/**
|
|
@@ -1194,13 +1276,13 @@ class Z {
|
|
|
1194
1276
|
* ```
|
|
1195
1277
|
*/
|
|
1196
1278
|
getValueByPath(e, t) {
|
|
1197
|
-
const
|
|
1279
|
+
const s = this.parsePath(t);
|
|
1198
1280
|
let i = e;
|
|
1199
|
-
for (const
|
|
1281
|
+
for (const r of s) {
|
|
1200
1282
|
if (i == null) return;
|
|
1201
|
-
if (i = i[
|
|
1283
|
+
if (i = i[r.key], r.index !== void 0) {
|
|
1202
1284
|
if (!Array.isArray(i)) return;
|
|
1203
|
-
i = i[
|
|
1285
|
+
i = i[r.index];
|
|
1204
1286
|
}
|
|
1205
1287
|
}
|
|
1206
1288
|
return i;
|
|
@@ -1232,31 +1314,31 @@ class Z {
|
|
|
1232
1314
|
* // obj3.items[0].title === 'New'
|
|
1233
1315
|
* ```
|
|
1234
1316
|
*/
|
|
1235
|
-
setValueByPath(e, t,
|
|
1317
|
+
setValueByPath(e, t, s) {
|
|
1236
1318
|
const i = this.parsePath(t);
|
|
1237
1319
|
if (i.length === 0)
|
|
1238
1320
|
throw new Error("Cannot set value: empty path");
|
|
1239
|
-
let
|
|
1321
|
+
let r = e;
|
|
1240
1322
|
for (let o = 0; o < i.length - 1; o++) {
|
|
1241
1323
|
const l = i[o];
|
|
1242
|
-
let
|
|
1324
|
+
let u = r[l.key];
|
|
1243
1325
|
if (l.index !== void 0) {
|
|
1244
|
-
if (!Array.isArray(
|
|
1245
|
-
throw new Error(`Expected array at path segment: ${l.key}, but got ${typeof
|
|
1246
|
-
|
|
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];
|
|
1247
1329
|
} else
|
|
1248
|
-
|
|
1330
|
+
u == null && (r[l.key] = {}, u = r[l.key]), r = u;
|
|
1249
1331
|
}
|
|
1250
1332
|
const n = i[i.length - 1];
|
|
1251
1333
|
if (n.index !== void 0) {
|
|
1252
|
-
const o =
|
|
1334
|
+
const o = r[n.key];
|
|
1253
1335
|
if (!Array.isArray(o))
|
|
1254
1336
|
throw new Error(
|
|
1255
1337
|
`Expected array at path segment: ${n.key}, but got ${typeof o}`
|
|
1256
1338
|
);
|
|
1257
|
-
o[n.index] =
|
|
1339
|
+
o[n.index] = s;
|
|
1258
1340
|
} else
|
|
1259
|
-
|
|
1341
|
+
r[n.key] = s;
|
|
1260
1342
|
}
|
|
1261
1343
|
/**
|
|
1262
1344
|
* Получить значение из FormNode по пути
|
|
@@ -1293,9 +1375,9 @@ class Z {
|
|
|
1293
1375
|
* ```
|
|
1294
1376
|
*/
|
|
1295
1377
|
getFormNodeValue(e, t) {
|
|
1296
|
-
const
|
|
1297
|
-
if (
|
|
1298
|
-
return this.isFormNode(
|
|
1378
|
+
const s = this.getNodeByPath(e, t);
|
|
1379
|
+
if (s != null)
|
|
1380
|
+
return this.isFormNode(s) ? s.value.value : s;
|
|
1299
1381
|
}
|
|
1300
1382
|
/**
|
|
1301
1383
|
* Type guard для проверки, является ли объект FormNode
|
|
@@ -1353,40 +1435,177 @@ class Z {
|
|
|
1353
1435
|
* ```
|
|
1354
1436
|
*/
|
|
1355
1437
|
getNodeByPath(e, t) {
|
|
1356
|
-
const
|
|
1438
|
+
const s = this.parsePath(t);
|
|
1357
1439
|
let i = e;
|
|
1358
|
-
for (const
|
|
1440
|
+
for (const r of s) {
|
|
1359
1441
|
if (i == null) return null;
|
|
1360
1442
|
const n = i;
|
|
1361
1443
|
if (n.fields && n.fields instanceof Map) {
|
|
1362
|
-
if (i = n.fields.get(
|
|
1444
|
+
if (i = n.fields.get(r.key), r.index === void 0) {
|
|
1363
1445
|
if (i == null) return null;
|
|
1364
1446
|
continue;
|
|
1365
1447
|
}
|
|
1366
|
-
} else if (
|
|
1448
|
+
} else if (r.index !== void 0 && n.items) {
|
|
1367
1449
|
const o = n.items.value || n.items;
|
|
1368
|
-
if (!Array.isArray(o) || (i = o[
|
|
1450
|
+
if (!Array.isArray(o) || (i = o[r.index], i == null)) return null;
|
|
1369
1451
|
continue;
|
|
1370
|
-
} else if (
|
|
1371
|
-
if (i = n[
|
|
1452
|
+
} else if (r.index === void 0) {
|
|
1453
|
+
if (i = n[r.key], i == null) return null;
|
|
1372
1454
|
continue;
|
|
1373
1455
|
}
|
|
1374
|
-
if (i &&
|
|
1456
|
+
if (i && r.index !== void 0 && i.items) {
|
|
1375
1457
|
const o = i.items.value || i.items;
|
|
1376
1458
|
if (!Array.isArray(o)) return null;
|
|
1377
|
-
i = o[
|
|
1378
|
-
} else if (i &&
|
|
1459
|
+
i = o[r.index];
|
|
1460
|
+
} else if (i && r.index !== void 0 && !i.items)
|
|
1379
1461
|
return null;
|
|
1380
1462
|
if (i == null) return null;
|
|
1381
1463
|
}
|
|
1382
1464
|
return i;
|
|
1383
1465
|
}
|
|
1384
1466
|
}
|
|
1385
|
-
|
|
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 {
|
|
1386
1605
|
// ============================================================================
|
|
1387
1606
|
// Приватные поля
|
|
1388
1607
|
// ============================================================================
|
|
1389
|
-
id =
|
|
1608
|
+
id = crypto.randomUUID();
|
|
1390
1609
|
/**
|
|
1391
1610
|
* Коллекция полей формы (упрощённый Map вместо FieldRegistry)
|
|
1392
1611
|
*/
|
|
@@ -1395,7 +1614,7 @@ class w extends F {
|
|
|
1395
1614
|
/**
|
|
1396
1615
|
* Менеджер подписок для централизованного cleanup
|
|
1397
1616
|
*/
|
|
1398
|
-
disposers = new
|
|
1617
|
+
disposers = new D();
|
|
1399
1618
|
/**
|
|
1400
1619
|
* Ссылка на Proxy-инстанс для использования в BehaviorContext
|
|
1401
1620
|
*/
|
|
@@ -1403,32 +1622,35 @@ class w extends F {
|
|
|
1403
1622
|
/**
|
|
1404
1623
|
* Навигатор для работы с путями к полям
|
|
1405
1624
|
*/
|
|
1406
|
-
pathNavigator = new
|
|
1625
|
+
pathNavigator = new se();
|
|
1407
1626
|
/**
|
|
1408
1627
|
* Фабрика для создания узлов формы
|
|
1409
1628
|
*/
|
|
1410
|
-
nodeFactory = new
|
|
1629
|
+
nodeFactory = new ne();
|
|
1411
1630
|
/**
|
|
1412
1631
|
* Реестр валидаторов для этой формы
|
|
1632
|
+
* Может быть инжектирован через config._validationRegistry для тестирования
|
|
1413
1633
|
*/
|
|
1414
|
-
validationRegistry
|
|
1634
|
+
validationRegistry;
|
|
1415
1635
|
/**
|
|
1416
1636
|
* Реестр behaviors для этой формы
|
|
1637
|
+
* Может быть инжектирован через config._behaviorRegistry для тестирования
|
|
1417
1638
|
*/
|
|
1418
|
-
behaviorRegistry
|
|
1639
|
+
behaviorRegistry;
|
|
1419
1640
|
/**
|
|
1420
1641
|
* Аппликатор для применения валидаторов к форме
|
|
1421
1642
|
*/
|
|
1422
|
-
validationApplicator = new
|
|
1643
|
+
validationApplicator = new te(this);
|
|
1423
1644
|
// ============================================================================
|
|
1424
1645
|
// Приватные сигналы состояния (inline из StateManager)
|
|
1425
1646
|
// ============================================================================
|
|
1426
|
-
/**
|
|
1427
|
-
|
|
1647
|
+
/** Управление отправкой формы */
|
|
1648
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1649
|
+
formSubmitter;
|
|
1428
1650
|
/** Флаг disabled состояния */
|
|
1429
|
-
_disabled =
|
|
1651
|
+
_disabled = g(!1);
|
|
1430
1652
|
/** Form-level validation errors */
|
|
1431
|
-
_formErrors =
|
|
1653
|
+
_formErrors = g([]);
|
|
1432
1654
|
// ============================================================================
|
|
1433
1655
|
// Публичные computed signals
|
|
1434
1656
|
// ============================================================================
|
|
@@ -1442,76 +1664,56 @@ class w extends F {
|
|
|
1442
1664
|
status;
|
|
1443
1665
|
submitting;
|
|
1444
1666
|
constructor(e) {
|
|
1445
|
-
super();
|
|
1446
|
-
const t = "form" in e,
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
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);
|
|
1450
1673
|
}
|
|
1451
|
-
this.value =
|
|
1452
|
-
const
|
|
1453
|
-
return this._fields.forEach((
|
|
1454
|
-
|
|
1455
|
-
}),
|
|
1456
|
-
})
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
}), n;
|
|
1467
|
-
}), this.status = u(() => this._disabled.value ? "disabled" : this.pending.value ? "pending" : this.invalid.value ? "invalid" : "valid"), this.submitting = u(() => this._submitting.value), this._proxyInstance = this.buildProxy(), i && this.applyBehaviorSchema(i), a && this.applyValidationSchema(a);
|
|
1468
|
-
}
|
|
1469
|
-
// ============================================================================
|
|
1470
|
-
// Приватный метод для создания 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
|
|
1471
1689
|
// ============================================================================
|
|
1472
1690
|
/**
|
|
1473
1691
|
* Создать Proxy для типобезопасного доступа к полям
|
|
1692
|
+
* @see buildFormProxy
|
|
1474
1693
|
*/
|
|
1475
1694
|
buildProxy() {
|
|
1476
|
-
|
|
1477
|
-
return new Proxy(this, {
|
|
1478
|
-
get: (t, r) => {
|
|
1479
|
-
if (r in t)
|
|
1480
|
-
return t[r];
|
|
1481
|
-
if (typeof r == "string" && e._fields.has(r)) {
|
|
1482
|
-
const i = e._fields.get(r);
|
|
1483
|
-
return i && typeof i.getProxy == "function" ? i.getProxy() : i;
|
|
1484
|
-
}
|
|
1485
|
-
},
|
|
1486
|
-
set: (t, r, i) => typeof r == "string" && e._fields.has(r) ? !1 : (t[r] = i, !0),
|
|
1487
|
-
has: (t, r) => typeof r == "string" && e._fields.has(r) ? !0 : r in t,
|
|
1488
|
-
ownKeys: (t) => {
|
|
1489
|
-
const r = Reflect.ownKeys(t), i = Array.from(e._fields.keys());
|
|
1490
|
-
return [.../* @__PURE__ */ new Set([...r, ...i])];
|
|
1491
|
-
},
|
|
1492
|
-
getOwnPropertyDescriptor: (t, r) => typeof r == "string" && e._fields.has(r) ? { enumerable: !0, configurable: !0 } : Reflect.getOwnPropertyDescriptor(t, r)
|
|
1493
|
-
});
|
|
1695
|
+
return re(this, this._fields);
|
|
1494
1696
|
}
|
|
1495
1697
|
// ============================================================================
|
|
1496
1698
|
// Реализация абстрактных методов FormNode
|
|
1497
1699
|
// ============================================================================
|
|
1498
1700
|
getValue() {
|
|
1499
1701
|
const e = {};
|
|
1500
|
-
return this._fields.forEach((t,
|
|
1501
|
-
e[
|
|
1702
|
+
return this._fields.forEach((t, s) => {
|
|
1703
|
+
e[s] = t.getValue();
|
|
1502
1704
|
}), e;
|
|
1503
1705
|
}
|
|
1504
1706
|
setValue(e, t) {
|
|
1505
|
-
for (const [
|
|
1506
|
-
const
|
|
1507
|
-
|
|
1707
|
+
for (const [s, i] of Object.entries(e)) {
|
|
1708
|
+
const r = this._fields.get(s);
|
|
1709
|
+
r && r.setValue(i, t);
|
|
1508
1710
|
}
|
|
1509
1711
|
}
|
|
1510
1712
|
patchValue(e) {
|
|
1511
1713
|
j(() => {
|
|
1512
|
-
for (const [t,
|
|
1714
|
+
for (const [t, s] of Object.entries(e)) {
|
|
1513
1715
|
const i = this._fields.get(t);
|
|
1514
|
-
i &&
|
|
1716
|
+
i && s !== void 0 && i.setValue(s, { emitEvent: !1 });
|
|
1515
1717
|
}
|
|
1516
1718
|
});
|
|
1517
1719
|
}
|
|
@@ -1533,8 +1735,8 @@ class w extends F {
|
|
|
1533
1735
|
* ```
|
|
1534
1736
|
*/
|
|
1535
1737
|
reset(e) {
|
|
1536
|
-
this._fields.forEach((t,
|
|
1537
|
-
const i = e?.[
|
|
1738
|
+
this._fields.forEach((t, s) => {
|
|
1739
|
+
const i = e?.[s];
|
|
1538
1740
|
t.reset(i);
|
|
1539
1741
|
});
|
|
1540
1742
|
}
|
|
@@ -1549,7 +1751,9 @@ class w extends F {
|
|
|
1549
1751
|
async validate() {
|
|
1550
1752
|
this.clearErrors(), await Promise.all(Array.from(this._fields.values()).map((t) => t.validate()));
|
|
1551
1753
|
const e = this.validationRegistry.getValidators();
|
|
1552
|
-
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
|
+
);
|
|
1553
1757
|
}
|
|
1554
1758
|
/**
|
|
1555
1759
|
* Установить form-level validation errors
|
|
@@ -1602,7 +1806,7 @@ class w extends F {
|
|
|
1602
1806
|
* ```
|
|
1603
1807
|
*/
|
|
1604
1808
|
getProxy() {
|
|
1605
|
-
return this._proxyInstance || this;
|
|
1809
|
+
return this._proxyInstance || (this._proxyInstance = this.buildProxy()), this._proxyInstance;
|
|
1606
1810
|
}
|
|
1607
1811
|
/**
|
|
1608
1812
|
* Получить все поля формы как итератор
|
|
@@ -1630,16 +1834,23 @@ class w extends F {
|
|
|
1630
1834
|
// ============================================================================
|
|
1631
1835
|
/**
|
|
1632
1836
|
* Отправить форму
|
|
1837
|
+
*
|
|
1838
|
+
* @param onSubmit - Callback для отправки данных
|
|
1839
|
+
* @param options - Опции submit (skipValidation, skipTouch)
|
|
1840
|
+
* @returns Результат от onSubmit или null если валидация не пройдена
|
|
1633
1841
|
*/
|
|
1634
|
-
async submit(e) {
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
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);
|
|
1643
1854
|
}
|
|
1644
1855
|
/**
|
|
1645
1856
|
* Применить validation schema к форме
|
|
@@ -1650,10 +1861,10 @@ class w extends F {
|
|
|
1650
1861
|
applyValidationSchema(e) {
|
|
1651
1862
|
this.validationRegistry.beginRegistration();
|
|
1652
1863
|
try {
|
|
1653
|
-
const t =
|
|
1864
|
+
const t = I();
|
|
1654
1865
|
e(t);
|
|
1655
|
-
const
|
|
1656
|
-
this.validationRegistry.endRegistration(
|
|
1866
|
+
const s = this.getProxy();
|
|
1867
|
+
this.validationRegistry.endRegistration(s);
|
|
1657
1868
|
} catch (t) {
|
|
1658
1869
|
throw console.error("Error applying validation schema:", t), t;
|
|
1659
1870
|
}
|
|
@@ -1665,7 +1876,7 @@ class w extends F {
|
|
|
1665
1876
|
applyBehaviorSchema(e) {
|
|
1666
1877
|
this.behaviorRegistry.beginRegistration();
|
|
1667
1878
|
try {
|
|
1668
|
-
const t =
|
|
1879
|
+
const t = I();
|
|
1669
1880
|
return e(t), this.behaviorRegistry.endRegistration(this.getProxy()).cleanup;
|
|
1670
1881
|
} catch (t) {
|
|
1671
1882
|
throw console.error("Error applying behavior schema:", t), t;
|
|
@@ -1706,18 +1917,18 @@ class w extends F {
|
|
|
1706
1917
|
const t = this.pathNavigator.parsePath(e);
|
|
1707
1918
|
if (t.length === 0)
|
|
1708
1919
|
return;
|
|
1709
|
-
let
|
|
1920
|
+
let s = this;
|
|
1710
1921
|
for (const i of t) {
|
|
1711
|
-
if (!(
|
|
1922
|
+
if (!(s instanceof k) || (s = s.getField(i.key), !s)) return;
|
|
1712
1923
|
if (i.index !== void 0)
|
|
1713
|
-
if ("at" in
|
|
1714
|
-
const
|
|
1715
|
-
if (!
|
|
1716
|
-
|
|
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;
|
|
1717
1928
|
} else
|
|
1718
1929
|
return;
|
|
1719
1930
|
}
|
|
1720
|
-
return
|
|
1931
|
+
return s;
|
|
1721
1932
|
}
|
|
1722
1933
|
/**
|
|
1723
1934
|
* Применить contextual валидаторы к полям
|
|
@@ -1761,15 +1972,16 @@ class w extends F {
|
|
|
1761
1972
|
/**
|
|
1762
1973
|
* Связывает два поля: при изменении source автоматически обновляется target
|
|
1763
1974
|
*/
|
|
1764
|
-
linkFields(e, t,
|
|
1765
|
-
const i = this._fields.get(e),
|
|
1766
|
-
if (!i || !
|
|
1767
|
-
|
|
1768
|
-
};
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
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);
|
|
1773
1985
|
return this.disposers.add(o, n);
|
|
1774
1986
|
}
|
|
1775
1987
|
/**
|
|
@@ -1800,15 +2012,14 @@ class w extends F {
|
|
|
1800
2012
|
* ```
|
|
1801
2013
|
*/
|
|
1802
2014
|
watchField(e, t) {
|
|
1803
|
-
const
|
|
1804
|
-
if (!
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
const n = r.value.value;
|
|
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;
|
|
1809
2020
|
t(n);
|
|
1810
|
-
}),
|
|
1811
|
-
return this.disposers.add(
|
|
2021
|
+
}), r = A(w.WatchField);
|
|
2022
|
+
return this.disposers.add(r, i);
|
|
1812
2023
|
}
|
|
1813
2024
|
/**
|
|
1814
2025
|
* Hook: вызывается после disable()
|
|
@@ -1831,7 +2042,7 @@ class w extends F {
|
|
|
1831
2042
|
});
|
|
1832
2043
|
}
|
|
1833
2044
|
}
|
|
1834
|
-
class
|
|
2045
|
+
class L extends C {
|
|
1835
2046
|
// ============================================================================
|
|
1836
2047
|
// Приватные поля
|
|
1837
2048
|
// ============================================================================
|
|
@@ -1842,9 +2053,9 @@ class N extends F {
|
|
|
1842
2053
|
* Менеджер подписок для централизованного cleanup
|
|
1843
2054
|
* Использует SubscriptionManager вместо массива для управления подписками
|
|
1844
2055
|
*/
|
|
1845
|
-
disposers = new
|
|
2056
|
+
disposers = new D();
|
|
1846
2057
|
/** Array-level validation errors (e.g., "минимум 1 элемент") */
|
|
1847
|
-
_arrayErrors =
|
|
2058
|
+
_arrayErrors = g([]);
|
|
1848
2059
|
// ============================================================================
|
|
1849
2060
|
// Приватные поля для сохранения схем
|
|
1850
2061
|
// ============================================================================
|
|
@@ -1866,15 +2077,15 @@ class N extends F {
|
|
|
1866
2077
|
// Конструктор
|
|
1867
2078
|
// ============================================================================
|
|
1868
2079
|
constructor(e, t = []) {
|
|
1869
|
-
super(), this.itemSchema = e, this.initialItems = t, this.items =
|
|
1870
|
-
for (const
|
|
1871
|
-
this.push(
|
|
1872
|
-
this.length =
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
2080
|
+
super(), this.itemSchema = e, this.initialItems = t, this.items = g([]);
|
|
2081
|
+
for (const i of t)
|
|
2082
|
+
this.push(i);
|
|
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;
|
|
1878
2089
|
}
|
|
1879
2090
|
// ============================================================================
|
|
1880
2091
|
// CRUD операции
|
|
@@ -1890,9 +2101,23 @@ class N extends F {
|
|
|
1890
2101
|
/**
|
|
1891
2102
|
* Удалить элемент по индексу
|
|
1892
2103
|
* @param index - Индекс элемента для удаления
|
|
2104
|
+
*
|
|
2105
|
+
* @remarks
|
|
2106
|
+
* Вызывает dispose() на удаляемом элементе для очистки подписок
|
|
1893
2107
|
*/
|
|
1894
2108
|
removeAt(e) {
|
|
1895
|
-
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();
|
|
1896
2121
|
}
|
|
1897
2122
|
/**
|
|
1898
2123
|
* Вставить элемент в массив
|
|
@@ -1900,16 +2125,30 @@ class N extends F {
|
|
|
1900
2125
|
* @param initialValue - Начальные значения для нового элемента
|
|
1901
2126
|
*/
|
|
1902
2127
|
insert(e, t) {
|
|
1903
|
-
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
|
+
);
|
|
1904
2136
|
return;
|
|
1905
|
-
|
|
1906
|
-
|
|
2137
|
+
}
|
|
2138
|
+
const s = this.createItem(t), i = [...this.items.value];
|
|
2139
|
+
i.splice(e, 0, s), this.items.value = i;
|
|
1907
2140
|
}
|
|
1908
2141
|
/**
|
|
1909
2142
|
* Удалить все элементы массива
|
|
2143
|
+
*
|
|
2144
|
+
* @remarks
|
|
2145
|
+
* Вызывает dispose() на всех элементах для очистки подписок
|
|
1910
2146
|
*/
|
|
1911
2147
|
clear() {
|
|
1912
|
-
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
|
+
});
|
|
1913
2152
|
}
|
|
1914
2153
|
/**
|
|
1915
2154
|
* Получить элемент по индексу
|
|
@@ -1928,12 +2167,13 @@ class N extends F {
|
|
|
1928
2167
|
return this.items.value.map((e) => e.getValue());
|
|
1929
2168
|
}
|
|
1930
2169
|
setValue(e, t) {
|
|
1931
|
-
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);
|
|
1932
2172
|
});
|
|
1933
2173
|
}
|
|
1934
2174
|
patchValue(e) {
|
|
1935
|
-
e.forEach((t,
|
|
1936
|
-
this.items.value[
|
|
2175
|
+
e.forEach((t, s) => {
|
|
2176
|
+
this.items.value[s] && t !== void 0 && this.items.value[s].patchValue(t);
|
|
1937
2177
|
});
|
|
1938
2178
|
}
|
|
1939
2179
|
/**
|
|
@@ -2061,9 +2301,9 @@ class N extends F {
|
|
|
2061
2301
|
* @param callback - Функция, вызываемая для каждого элемента с типизированным GroupNode proxy
|
|
2062
2302
|
*/
|
|
2063
2303
|
forEach(e) {
|
|
2064
|
-
this.items.value.forEach((t,
|
|
2304
|
+
this.items.value.forEach((t, s) => {
|
|
2065
2305
|
const i = t.getProxy();
|
|
2066
|
-
e(i,
|
|
2306
|
+
e(i, s);
|
|
2067
2307
|
});
|
|
2068
2308
|
}
|
|
2069
2309
|
/**
|
|
@@ -2072,9 +2312,9 @@ class N extends F {
|
|
|
2072
2312
|
* @returns Новый массив результатов
|
|
2073
2313
|
*/
|
|
2074
2314
|
map(e) {
|
|
2075
|
-
return this.items.value.map((t,
|
|
2315
|
+
return this.items.value.map((t, s) => {
|
|
2076
2316
|
const i = t.getProxy();
|
|
2077
|
-
return e(i,
|
|
2317
|
+
return e(i, s);
|
|
2078
2318
|
});
|
|
2079
2319
|
}
|
|
2080
2320
|
// ============================================================================
|
|
@@ -2086,7 +2326,7 @@ class N extends F {
|
|
|
2086
2326
|
*/
|
|
2087
2327
|
createItem(e) {
|
|
2088
2328
|
if (this.isGroupSchema(this.itemSchema)) {
|
|
2089
|
-
const t = new
|
|
2329
|
+
const t = new k(this.itemSchema);
|
|
2090
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;
|
|
2091
2331
|
}
|
|
2092
2332
|
throw new Error(
|
|
@@ -2173,14 +2413,14 @@ class N extends F {
|
|
|
2173
2413
|
* ```
|
|
2174
2414
|
*/
|
|
2175
2415
|
watchItems(e, t) {
|
|
2176
|
-
const
|
|
2177
|
-
const
|
|
2178
|
-
if (n instanceof
|
|
2416
|
+
const s = m(() => {
|
|
2417
|
+
const r = this.items.value.map((n) => {
|
|
2418
|
+
if (n instanceof k)
|
|
2179
2419
|
return n.getFieldByPath(e)?.value.value;
|
|
2180
2420
|
});
|
|
2181
|
-
t(
|
|
2182
|
-
}), i =
|
|
2183
|
-
return this.disposers.add(i,
|
|
2421
|
+
t(r);
|
|
2422
|
+
}), i = A(w.WatchItems);
|
|
2423
|
+
return this.disposers.add(i, s);
|
|
2184
2424
|
}
|
|
2185
2425
|
/**
|
|
2186
2426
|
* Подписка на изменение длины массива
|
|
@@ -2205,11 +2445,11 @@ class N extends F {
|
|
|
2205
2445
|
* ```
|
|
2206
2446
|
*/
|
|
2207
2447
|
watchLength(e) {
|
|
2208
|
-
const t =
|
|
2448
|
+
const t = m(() => {
|
|
2209
2449
|
const i = this.length.value;
|
|
2210
2450
|
e(i);
|
|
2211
|
-
}),
|
|
2212
|
-
return this.disposers.add(
|
|
2451
|
+
}), s = A(w.WatchLength);
|
|
2452
|
+
return this.disposers.add(s, t);
|
|
2213
2453
|
}
|
|
2214
2454
|
/**
|
|
2215
2455
|
* Очистить все ресурсы узла
|
|
@@ -2272,7 +2512,7 @@ class N extends F {
|
|
|
2272
2512
|
});
|
|
2273
2513
|
}
|
|
2274
2514
|
}
|
|
2275
|
-
class
|
|
2515
|
+
class ne {
|
|
2276
2516
|
/**
|
|
2277
2517
|
* Создает узел формы на основе конфигурации
|
|
2278
2518
|
*
|
|
@@ -2322,16 +2562,16 @@ class ee {
|
|
|
2322
2562
|
if (Array.isArray(e) && e.length >= 1)
|
|
2323
2563
|
return this.createArrayNodeFromArray(e);
|
|
2324
2564
|
if (this.isFieldConfig(e))
|
|
2325
|
-
return new
|
|
2565
|
+
return new ee(e);
|
|
2326
2566
|
if (this.isArrayConfig(e)) {
|
|
2327
2567
|
const t = e;
|
|
2328
|
-
return new
|
|
2568
|
+
return new L(
|
|
2329
2569
|
t.schema,
|
|
2330
2570
|
t.initialItems
|
|
2331
2571
|
);
|
|
2332
2572
|
}
|
|
2333
2573
|
if (this.isGroupConfig(e))
|
|
2334
|
-
return new
|
|
2574
|
+
return new k(e);
|
|
2335
2575
|
throw new Error(
|
|
2336
2576
|
`NodeFactory: Unknown node config. Expected FieldConfig, GroupConfig, or ArrayConfig, but got: ${JSON.stringify(
|
|
2337
2577
|
e
|
|
@@ -2365,11 +2605,11 @@ class ee {
|
|
|
2365
2605
|
*/
|
|
2366
2606
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2367
2607
|
createArrayNodeFromArray(e) {
|
|
2368
|
-
const [t, ...
|
|
2608
|
+
const [t, ...s] = e, i = [];
|
|
2369
2609
|
this.isGroupConfig(t) && i.push(this.extractValues(t));
|
|
2370
|
-
for (const
|
|
2371
|
-
this.isGroupConfig(
|
|
2372
|
-
return new
|
|
2610
|
+
for (const r of s)
|
|
2611
|
+
this.isGroupConfig(r) ? i.push(this.extractValues(r)) : i.push(r);
|
|
2612
|
+
return new L(t, i);
|
|
2373
2613
|
}
|
|
2374
2614
|
/**
|
|
2375
2615
|
* Извлечь значения из схемы (рекурсивно)
|
|
@@ -2407,8 +2647,8 @@ class ee {
|
|
|
2407
2647
|
return e.map((t) => this.extractValues(t));
|
|
2408
2648
|
if (this.isGroupConfig(e)) {
|
|
2409
2649
|
const t = {};
|
|
2410
|
-
for (const [
|
|
2411
|
-
t[
|
|
2650
|
+
for (const [s, i] of Object.entries(e))
|
|
2651
|
+
t[s] = this.extractValues(i);
|
|
2412
2652
|
return t;
|
|
2413
2653
|
}
|
|
2414
2654
|
return e;
|
|
@@ -2488,299 +2728,334 @@ class ee {
|
|
|
2488
2728
|
return e != null && typeof e == "object" && !this.isFieldConfig(e) && !this.isArrayConfig(e);
|
|
2489
2729
|
}
|
|
2490
2730
|
}
|
|
2491
|
-
|
|
2731
|
+
function ge(a) {
|
|
2732
|
+
return new k(a).getProxy();
|
|
2733
|
+
}
|
|
2734
|
+
class be {
|
|
2492
2735
|
/**
|
|
2493
|
-
*
|
|
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;
|
|
2750
|
+
/**
|
|
2751
|
+
* Подписаться на события изменения
|
|
2494
2752
|
*
|
|
2495
|
-
* @param
|
|
2753
|
+
* @param callback - Функция обработки события
|
|
2754
|
+
* @returns Функция отписки
|
|
2496
2755
|
*
|
|
2497
2756
|
* @example
|
|
2498
2757
|
* ```typescript
|
|
2499
|
-
* const
|
|
2500
|
-
*
|
|
2758
|
+
* const unsubscribe = observer.subscribe((event) => {
|
|
2759
|
+
* // Отправить событие в analytics
|
|
2760
|
+
* analytics.track('form_change', event);
|
|
2761
|
+
* });
|
|
2501
2762
|
* ```
|
|
2502
2763
|
*/
|
|
2503
|
-
|
|
2504
|
-
this.
|
|
2764
|
+
subscribe(e) {
|
|
2765
|
+
return this.listeners.add(e), () => this.listeners.delete(e);
|
|
2505
2766
|
}
|
|
2506
2767
|
/**
|
|
2507
|
-
*
|
|
2508
|
-
* @private
|
|
2509
|
-
*/
|
|
2510
|
-
timer;
|
|
2511
|
-
/**
|
|
2512
|
-
* Отложить выполнение функции
|
|
2768
|
+
* Включить трассировку формы
|
|
2513
2769
|
*
|
|
2514
|
-
*
|
|
2515
|
-
* и
|
|
2770
|
+
* Подписывается на изменения основных сигналов формы
|
|
2771
|
+
* и вызывает listeners при каждом изменении
|
|
2516
2772
|
*
|
|
2517
|
-
* @
|
|
2518
|
-
* @returns Promise, который разрешается результатом функции
|
|
2773
|
+
* @returns Функция для отключения трассировки
|
|
2519
2774
|
*
|
|
2520
2775
|
* @example
|
|
2521
2776
|
* ```typescript
|
|
2522
|
-
* const
|
|
2523
|
-
*
|
|
2524
|
-
* // Первый вызов - запланирован через 300мс
|
|
2525
|
-
* debouncer.debounce(async () => console.log('First'));
|
|
2777
|
+
* const dispose = observer.enableTracing();
|
|
2526
2778
|
*
|
|
2527
|
-
* //
|
|
2528
|
-
*
|
|
2529
|
-
*
|
|
2530
|
-
* // Через 300мс выведет только: "Second"
|
|
2779
|
+
* // Позже, для отключения
|
|
2780
|
+
* dispose();
|
|
2531
2781
|
* ```
|
|
2532
2782
|
*/
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
}
|
|
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
|
+
};
|
|
2548
2857
|
}
|
|
2549
2858
|
/**
|
|
2550
|
-
*
|
|
2859
|
+
* Наблюдать за конкретным полем
|
|
2551
2860
|
*
|
|
2552
|
-
*
|
|
2553
|
-
*
|
|
2861
|
+
* @param path - Путь к полю
|
|
2862
|
+
* @returns Функция для отключения наблюдения
|
|
2554
2863
|
*
|
|
2555
2864
|
* @example
|
|
2556
2865
|
* ```typescript
|
|
2557
|
-
*
|
|
2558
|
-
*
|
|
2559
|
-
* debouncer.debounce(async () => {
|
|
2560
|
-
* console.log('This will not execute');
|
|
2561
|
-
* });
|
|
2562
|
-
*
|
|
2563
|
-
* debouncer.cancel(); // Отменяем вызов
|
|
2866
|
+
* // Наблюдать за полем email
|
|
2867
|
+
* const dispose = observer.watchField('email');
|
|
2564
2868
|
* ```
|
|
2565
2869
|
*/
|
|
2566
|
-
|
|
2567
|
-
|
|
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());
|
|
2568
2905
|
}
|
|
2569
2906
|
/**
|
|
2570
|
-
*
|
|
2571
|
-
*
|
|
2572
|
-
* Полезно когда нужно принудительно выполнить действие сейчас,
|
|
2573
|
-
* игнорируя debounce.
|
|
2574
|
-
*
|
|
2575
|
-
* @param fn Функция для немедленного выполнения
|
|
2576
|
-
* @returns Promise с результатом функции
|
|
2577
|
-
*
|
|
2578
|
-
* @example
|
|
2579
|
-
* ```typescript
|
|
2580
|
-
* const debouncer = new Debouncer(300);
|
|
2581
|
-
*
|
|
2582
|
-
* // Запланировано через 300мс
|
|
2583
|
-
* debouncer.debounce(async () => console.log('Delayed'));
|
|
2584
|
-
*
|
|
2585
|
-
* // Отменяем отложенный и выполняем немедленно
|
|
2586
|
-
* await debouncer.flush(async () => console.log('Immediate'));
|
|
2587
|
-
* // Выведет: "Immediate" (сразу)
|
|
2588
|
-
* // "Delayed" не выполнится (отменен)
|
|
2589
|
-
* ```
|
|
2907
|
+
* Отправить событие всем listeners
|
|
2590
2908
|
*/
|
|
2591
|
-
|
|
2592
|
-
|
|
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
|
+
}));
|
|
2593
2916
|
}
|
|
2594
2917
|
/**
|
|
2595
|
-
* Проверить,
|
|
2596
|
-
*
|
|
2597
|
-
* @returns true если есть запланированный вызов
|
|
2598
|
-
*
|
|
2599
|
-
* @example
|
|
2600
|
-
* ```typescript
|
|
2601
|
-
* const debouncer = new Debouncer(300);
|
|
2602
|
-
*
|
|
2603
|
-
* console.log(debouncer.isPending()); // false
|
|
2604
|
-
*
|
|
2605
|
-
* debouncer.debounce(() => console.log('Test'));
|
|
2606
|
-
* console.log(debouncer.isPending()); // true
|
|
2607
|
-
*
|
|
2608
|
-
* // Через 300мс
|
|
2609
|
-
* console.log(debouncer.isPending()); // false
|
|
2610
|
-
* ```
|
|
2918
|
+
* Проверить, нужно ли отслеживать тип события
|
|
2611
2919
|
*/
|
|
2612
|
-
|
|
2613
|
-
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();
|
|
2614
2935
|
}
|
|
2615
2936
|
}
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
}
|
|
2628
|
-
|
|
2629
|
-
let e = null;
|
|
2630
|
-
return {
|
|
2631
|
-
type: "preload",
|
|
2632
|
-
load: async (t) => {
|
|
2633
|
-
if (!e) {
|
|
2634
|
-
const r = await s(t);
|
|
2635
|
-
e = {
|
|
2636
|
-
items: r,
|
|
2637
|
-
totalCount: r.length
|
|
2638
|
-
};
|
|
2639
|
-
}
|
|
2640
|
-
return e;
|
|
2641
|
-
}
|
|
2642
|
-
};
|
|
2643
|
-
}
|
|
2644
|
-
function ie(s) {
|
|
2645
|
-
return {
|
|
2646
|
-
type: "partial",
|
|
2647
|
-
load: async (e) => {
|
|
2648
|
-
const t = await s(e);
|
|
2649
|
-
return {
|
|
2650
|
-
items: t,
|
|
2651
|
-
totalCount: t.length
|
|
2652
|
-
// Можно расширить для поддержки серверной пагинации
|
|
2653
|
-
};
|
|
2654
|
-
}
|
|
2655
|
-
};
|
|
2656
|
-
}
|
|
2657
|
-
const me = {
|
|
2658
|
-
static: te,
|
|
2659
|
-
preload: re,
|
|
2660
|
-
partial: ie
|
|
2661
|
-
};
|
|
2662
|
-
var A = { exports: {} }, x = {};
|
|
2663
|
-
var I;
|
|
2664
|
-
function se() {
|
|
2665
|
-
if (I) return x;
|
|
2666
|
-
I = 1;
|
|
2667
|
-
var s = L;
|
|
2668
|
-
function e(c, f) {
|
|
2669
|
-
return c === f && (c !== 0 || 1 / c === 1 / f) || c !== c && f !== f;
|
|
2670
|
-
}
|
|
2671
|
-
var t = typeof Object.is == "function" ? Object.is : e, r = s.useState, i = s.useEffect, a = s.useLayoutEffect, n = s.useDebugValue;
|
|
2672
|
-
function o(c, f) {
|
|
2673
|
-
var d = f(), v = r({ inst: { value: d, getSnapshot: f } }), p = v[0].inst, g = v[1];
|
|
2674
|
-
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(
|
|
2675
2950
|
function() {
|
|
2676
|
-
|
|
2951
|
+
y.value = c, y.getSnapshot = f, l(y) && E({ inst: y });
|
|
2677
2952
|
},
|
|
2678
|
-
[
|
|
2953
|
+
[h, c, f]
|
|
2679
2954
|
), i(
|
|
2680
2955
|
function() {
|
|
2681
|
-
return l(
|
|
2682
|
-
l(
|
|
2956
|
+
return l(y) && E({ inst: y }), h(function() {
|
|
2957
|
+
l(y) && E({ inst: y });
|
|
2683
2958
|
});
|
|
2684
2959
|
},
|
|
2685
|
-
[
|
|
2686
|
-
), n(
|
|
2960
|
+
[h]
|
|
2961
|
+
), n(c), c;
|
|
2687
2962
|
}
|
|
2688
|
-
function l(
|
|
2689
|
-
var f =
|
|
2690
|
-
|
|
2963
|
+
function l(h) {
|
|
2964
|
+
var f = h.getSnapshot;
|
|
2965
|
+
h = h.value;
|
|
2691
2966
|
try {
|
|
2692
|
-
var
|
|
2693
|
-
return !t(
|
|
2967
|
+
var c = f();
|
|
2968
|
+
return !t(h, c);
|
|
2694
2969
|
} catch {
|
|
2695
2970
|
return !0;
|
|
2696
2971
|
}
|
|
2697
2972
|
}
|
|
2698
|
-
function h
|
|
2973
|
+
function u(h, f) {
|
|
2699
2974
|
return f();
|
|
2700
2975
|
}
|
|
2701
|
-
var
|
|
2702
|
-
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;
|
|
2703
2978
|
}
|
|
2704
|
-
var
|
|
2705
|
-
var
|
|
2706
|
-
function
|
|
2707
|
-
return
|
|
2708
|
-
function
|
|
2709
|
-
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;
|
|
2710
2985
|
}
|
|
2711
|
-
function e(
|
|
2712
|
-
|
|
2986
|
+
function e(c, p) {
|
|
2987
|
+
v || i.startTransition === void 0 || (v = !0, console.error(
|
|
2713
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."
|
|
2714
2989
|
));
|
|
2715
|
-
var
|
|
2716
|
-
if (!
|
|
2717
|
-
var
|
|
2718
|
-
|
|
2990
|
+
var y = p();
|
|
2991
|
+
if (!h) {
|
|
2992
|
+
var E = p();
|
|
2993
|
+
r(y, E) || (console.error(
|
|
2719
2994
|
"The result of getSnapshot should be cached to avoid an infinite loop"
|
|
2720
|
-
),
|
|
2995
|
+
), h = !0);
|
|
2721
2996
|
}
|
|
2722
|
-
|
|
2723
|
-
inst: { value:
|
|
2997
|
+
E = n({
|
|
2998
|
+
inst: { value: y, getSnapshot: p }
|
|
2724
2999
|
});
|
|
2725
|
-
var _ =
|
|
3000
|
+
var _ = E[0].inst, F = E[1];
|
|
2726
3001
|
return l(
|
|
2727
3002
|
function() {
|
|
2728
|
-
_.value =
|
|
3003
|
+
_.value = y, _.getSnapshot = p, t(_) && F({ inst: _ });
|
|
2729
3004
|
},
|
|
2730
|
-
[
|
|
3005
|
+
[c, y, p]
|
|
2731
3006
|
), o(
|
|
2732
3007
|
function() {
|
|
2733
|
-
return t(_) &&
|
|
2734
|
-
t(_) &&
|
|
3008
|
+
return t(_) && F({ inst: _ }), c(function() {
|
|
3009
|
+
t(_) && F({ inst: _ });
|
|
2735
3010
|
});
|
|
2736
3011
|
},
|
|
2737
|
-
[
|
|
2738
|
-
),
|
|
3012
|
+
[c]
|
|
3013
|
+
), u(y), y;
|
|
2739
3014
|
}
|
|
2740
|
-
function t(
|
|
2741
|
-
var
|
|
2742
|
-
|
|
3015
|
+
function t(c) {
|
|
3016
|
+
var p = c.getSnapshot;
|
|
3017
|
+
c = c.value;
|
|
2743
3018
|
try {
|
|
2744
|
-
var
|
|
2745
|
-
return !
|
|
3019
|
+
var y = p();
|
|
3020
|
+
return !r(c, y);
|
|
2746
3021
|
} catch {
|
|
2747
3022
|
return !0;
|
|
2748
3023
|
}
|
|
2749
3024
|
}
|
|
2750
|
-
function
|
|
2751
|
-
return
|
|
3025
|
+
function s(c, p) {
|
|
3026
|
+
return p();
|
|
2752
3027
|
}
|
|
2753
3028
|
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ < "u" && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart == "function" && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
|
|
2754
|
-
var i =
|
|
2755
|
-
|
|
2756
|
-
})()),
|
|
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;
|
|
2757
3032
|
}
|
|
2758
|
-
var
|
|
2759
|
-
function
|
|
2760
|
-
return
|
|
3033
|
+
var $;
|
|
3034
|
+
function ue() {
|
|
3035
|
+
return $ || ($ = 1, process.env.NODE_ENV === "production" ? x.exports = oe() : x.exports = le()), x.exports;
|
|
2761
3036
|
}
|
|
2762
|
-
var
|
|
2763
|
-
function
|
|
2764
|
-
if (
|
|
2765
|
-
if (
|
|
2766
|
-
for (let t = 0; t <
|
|
2767
|
-
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;
|
|
2768
3043
|
return !0;
|
|
2769
3044
|
}
|
|
2770
|
-
function
|
|
2771
|
-
const
|
|
2772
|
-
if (
|
|
3045
|
+
function q(a, e, t) {
|
|
3046
|
+
const s = P(null);
|
|
3047
|
+
if (s.current === null) {
|
|
2773
3048
|
const n = {};
|
|
2774
|
-
for (const o in
|
|
2775
|
-
n[o] =
|
|
2776
|
-
|
|
3049
|
+
for (const o in a)
|
|
3050
|
+
n[o] = a[o].value;
|
|
3051
|
+
s.current = { ...n, __snapshot: null };
|
|
2777
3052
|
}
|
|
2778
3053
|
const i = b(
|
|
2779
3054
|
(n) => {
|
|
2780
3055
|
let o = !0;
|
|
2781
|
-
return
|
|
2782
|
-
for (const
|
|
2783
|
-
|
|
3056
|
+
return m(() => {
|
|
3057
|
+
for (const u in a)
|
|
3058
|
+
a[u].value;
|
|
2784
3059
|
if (o) {
|
|
2785
3060
|
o = !1;
|
|
2786
3061
|
return;
|
|
@@ -2788,43 +3063,43 @@ function $(s, e, t) {
|
|
|
2788
3063
|
n();
|
|
2789
3064
|
});
|
|
2790
3065
|
},
|
|
2791
|
-
[
|
|
2792
|
-
),
|
|
2793
|
-
const n =
|
|
2794
|
-
for (const
|
|
2795
|
-
o[
|
|
3066
|
+
[a]
|
|
3067
|
+
), r = b(() => {
|
|
3068
|
+
const n = s.current, o = {};
|
|
3069
|
+
for (const u in a)
|
|
3070
|
+
o[u] = a[u].value;
|
|
2796
3071
|
let l = !1;
|
|
2797
|
-
for (const
|
|
2798
|
-
const { key:
|
|
2799
|
-
if (
|
|
2800
|
-
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)) {
|
|
2801
3076
|
l = !0;
|
|
2802
3077
|
break;
|
|
2803
3078
|
}
|
|
2804
|
-
} else if (
|
|
3079
|
+
} else if (c !== f) {
|
|
2805
3080
|
l = !0;
|
|
2806
3081
|
break;
|
|
2807
3082
|
}
|
|
2808
3083
|
}
|
|
2809
3084
|
if (!l && n.__snapshot)
|
|
2810
3085
|
return n.__snapshot;
|
|
2811
|
-
for (const
|
|
2812
|
-
n[
|
|
3086
|
+
for (const u in a)
|
|
3087
|
+
n[u] = o[u];
|
|
2813
3088
|
return n.__snapshot = t(o), n.__snapshot;
|
|
2814
|
-
}, [
|
|
2815
|
-
return
|
|
3089
|
+
}, [a, t]);
|
|
3090
|
+
return R.useSyncExternalStore(i, r, r);
|
|
2816
3091
|
}
|
|
2817
|
-
function
|
|
3092
|
+
function de(a) {
|
|
2818
3093
|
const e = {
|
|
2819
|
-
value:
|
|
2820
|
-
disabled:
|
|
2821
|
-
errors:
|
|
2822
|
-
pending:
|
|
2823
|
-
valid:
|
|
2824
|
-
invalid:
|
|
2825
|
-
touched:
|
|
2826
|
-
shouldShowError:
|
|
2827
|
-
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
|
|
2828
3103
|
}, t = [
|
|
2829
3104
|
{ key: "value" },
|
|
2830
3105
|
{ key: "disabled" },
|
|
@@ -2835,7 +3110,7 @@ function le(s) {
|
|
|
2835
3110
|
{ key: "touched" },
|
|
2836
3111
|
{ key: "shouldShowError" },
|
|
2837
3112
|
{ key: "componentProps" }
|
|
2838
|
-
],
|
|
3113
|
+
], s = b(
|
|
2839
3114
|
(i) => ({
|
|
2840
3115
|
value: i.value,
|
|
2841
3116
|
pending: i.pending,
|
|
@@ -2849,18 +3124,18 @@ function le(s) {
|
|
|
2849
3124
|
}),
|
|
2850
3125
|
[]
|
|
2851
3126
|
);
|
|
2852
|
-
return
|
|
3127
|
+
return q(e, t, s);
|
|
2853
3128
|
}
|
|
2854
|
-
function
|
|
3129
|
+
function ce(a) {
|
|
2855
3130
|
const e = {
|
|
2856
|
-
value:
|
|
2857
|
-
length:
|
|
2858
|
-
errors:
|
|
2859
|
-
pending:
|
|
2860
|
-
valid:
|
|
2861
|
-
invalid:
|
|
2862
|
-
touched:
|
|
2863
|
-
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
|
|
2864
3139
|
}, t = [
|
|
2865
3140
|
{ key: "value" },
|
|
2866
3141
|
{ key: "length" },
|
|
@@ -2870,7 +3145,7 @@ function ue(s) {
|
|
|
2870
3145
|
{ key: "invalid" },
|
|
2871
3146
|
{ key: "touched" },
|
|
2872
3147
|
{ key: "dirty" }
|
|
2873
|
-
],
|
|
3148
|
+
], s = b(
|
|
2874
3149
|
(i) => ({
|
|
2875
3150
|
value: i.value,
|
|
2876
3151
|
length: i.length,
|
|
@@ -2883,11 +3158,11 @@ function ue(s) {
|
|
|
2883
3158
|
}),
|
|
2884
3159
|
[]
|
|
2885
3160
|
);
|
|
2886
|
-
return
|
|
3161
|
+
return q(e, t, s);
|
|
2887
3162
|
}
|
|
2888
|
-
function
|
|
2889
|
-
const e =
|
|
2890
|
-
return
|
|
3163
|
+
function Ee(a) {
|
|
3164
|
+
const e = a && "length" in a && "map" in a;
|
|
3165
|
+
return a ? e ? ce(a) : de(a) : {
|
|
2891
3166
|
value: [],
|
|
2892
3167
|
length: 0,
|
|
2893
3168
|
pending: !1,
|
|
@@ -2898,57 +3173,99 @@ function ge(s) {
|
|
|
2898
3173
|
dirty: !1
|
|
2899
3174
|
};
|
|
2900
3175
|
}
|
|
2901
|
-
function _e(
|
|
2902
|
-
const e =
|
|
3176
|
+
function _e(a) {
|
|
3177
|
+
const e = P({ value: a.value.value }), t = b(
|
|
2903
3178
|
(i) => {
|
|
2904
|
-
let
|
|
2905
|
-
return
|
|
2906
|
-
if (
|
|
2907
|
-
|
|
3179
|
+
let r = !0;
|
|
3180
|
+
return m(() => {
|
|
3181
|
+
if (a.value.value, r) {
|
|
3182
|
+
r = !1;
|
|
2908
3183
|
return;
|
|
2909
3184
|
}
|
|
2910
3185
|
i();
|
|
2911
3186
|
});
|
|
2912
3187
|
},
|
|
2913
|
-
[
|
|
2914
|
-
),
|
|
2915
|
-
const i =
|
|
3188
|
+
[a]
|
|
3189
|
+
), s = b(() => {
|
|
3190
|
+
const i = a.value.value;
|
|
2916
3191
|
return e.current.value === i ? e.current.value : (e.current.value = i, i);
|
|
2917
|
-
}, [
|
|
2918
|
-
return
|
|
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;
|
|
3202
|
+
return;
|
|
3203
|
+
}
|
|
3204
|
+
i();
|
|
3205
|
+
});
|
|
3206
|
+
},
|
|
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);
|
|
2919
3232
|
}
|
|
2920
3233
|
export {
|
|
2921
|
-
|
|
2922
|
-
|
|
3234
|
+
ke as AbstractRegistry,
|
|
3235
|
+
L as ArrayNode,
|
|
2923
3236
|
V as ErrorStrategy,
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
D as
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
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,
|
|
3249
|
+
I as createFieldPath,
|
|
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,
|
|
2951
3267
|
_e as useFormControlValue,
|
|
2952
|
-
|
|
2953
|
-
|
|
3268
|
+
Ve as useHiddenCondition,
|
|
3269
|
+
Re as validateForm,
|
|
3270
|
+
Me as validators
|
|
2954
3271
|
};
|