@reformer/core 9.0.0 → 9.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -57
- package/dist/behaviors-node-BMOI2JJF.js +26 -0
- package/dist/behaviors-value-lCpqicfa.js +148 -0
- package/dist/behaviors.d.ts +2 -133
- package/dist/behaviors.js +148 -147
- package/dist/{core/utils → form}/aggregate-signals.d.ts +2 -2
- package/dist/form/behaviors-node.d.ts +55 -0
- package/dist/form/behaviors.d.ts +133 -0
- package/dist/{core/utils → form}/create-form.d.ts +5 -4
- package/dist/{core/utils → form}/error-handler.d.ts +1 -1
- package/dist/{core → form}/factories/node-factory.d.ts +1 -1
- package/dist/{core/utils → form}/form-proxy-builder.d.ts +2 -2
- package/dist/{core/utils → form}/form-submitter.d.ts +6 -1
- package/dist/{hooks → form/hooks}/types.d.ts +31 -1
- package/dist/{hooks → form/hooks}/useArrayLength.d.ts +1 -1
- package/dist/{hooks → form/hooks}/useFormControl.d.ts +3 -3
- package/dist/{hooks → form/hooks}/useFormControlValue.d.ts +2 -2
- package/dist/{hooks → form/hooks}/useSignalSubscription.d.ts +8 -1
- package/dist/form/index.d.ts +36 -0
- package/dist/{core → form}/nodes/array-node.d.ts +1 -1
- package/dist/{core → form}/nodes/field-node.d.ts +1 -1
- package/dist/{core → form}/nodes/form-node.d.ts +1 -1
- package/dist/{core → form}/nodes/group-node.d.ts +34 -4
- package/dist/{core → form}/nodes/model-array-node.d.ts +10 -3
- package/dist/{core/utils → form}/signal-node-registry.d.ts +1 -1
- package/dist/{core/utils → form}/status-machine.d.ts +1 -1
- package/dist/{core/utils → form}/type-guards.d.ts +5 -5
- package/dist/{core/types/index.d.ts → form/types/contracts.d.ts} +11 -90
- package/dist/{core → form}/types/deep-schema.d.ts +23 -1
- package/dist/{core → form}/types/form-proxy.d.ts +26 -1
- package/dist/form/types/index.d.ts +91 -0
- package/dist/{core → form}/types/schema-node.d.ts +1 -1
- package/dist/{core → form}/types/validation-schema.d.ts +19 -9
- package/dist/{core/model/validate-model.d.ts → form/validate-model-core.d.ts} +25 -25
- package/dist/form/validate-model.d.ts +27 -0
- package/dist/{core → form}/validation/validators/required.d.ts +2 -1
- package/dist/form/validators.d.ts +6 -0
- package/dist/form-model-C8Fi83k4.js +439 -0
- package/dist/index.d.ts +11 -16
- package/dist/index.js +666 -1011
- package/dist/{core/model/behaviors.d.ts → state/behaviors-value.d.ts} +0 -38
- package/dist/{core/utils → state}/derived-registry.d.ts +29 -0
- package/dist/state/form-model.d.ts +26 -0
- package/dist/state/index.d.ts +31 -0
- package/dist/state/safe-effect.d.ts +93 -0
- package/dist/{core/model → state}/types.d.ts +14 -11
- package/dist/state.d.ts +2 -0
- package/dist/state.js +19 -0
- package/dist/validators/email.d.ts +1 -1
- package/dist/validators/future-date.d.ts +1 -1
- package/dist/validators/integer.d.ts +1 -1
- package/dist/validators/is-date.d.ts +1 -1
- package/dist/validators/is-number.d.ts +1 -1
- package/dist/validators/max-age.d.ts +1 -1
- package/dist/validators/max-date.d.ts +1 -1
- package/dist/validators/max-length.d.ts +1 -1
- package/dist/validators/max.d.ts +1 -1
- package/dist/validators/min-age.d.ts +1 -1
- package/dist/validators/min-date.d.ts +1 -1
- package/dist/validators/min-length.d.ts +1 -1
- package/dist/validators/min.d.ts +1 -1
- package/dist/validators/multiple-of.d.ts +1 -1
- package/dist/validators/non-negative.d.ts +1 -1
- package/dist/validators/non-zero.d.ts +1 -1
- package/dist/validators/past-date.d.ts +1 -1
- package/dist/validators/pattern.d.ts +1 -1
- package/dist/validators/pattern.js +7 -6
- package/dist/validators/phone.d.ts +1 -1
- package/dist/validators/required.d.ts +1 -1
- package/dist/validators/required.js +5 -9
- package/dist/validators/url.d.ts +1 -1
- package/dist/validators.d.ts +6 -6
- package/llms.txt +307 -166
- package/package.json +5 -1
- package/dist/behaviors-O9a1Djj9.js +0 -147
- package/dist/core/model/form-model.d.ts +0 -18
- package/dist/core/model/index.d.ts +0 -12
- package/dist/core/utils/index.d.ts +0 -18
- package/dist/core/utils/safe-effect.d.ts +0 -73
- /package/dist/{core → form}/factories/index.d.ts +0 -0
- /package/dist/{core/utils → form}/unique-id.d.ts +0 -0
- /package/dist/{core → form}/validation/index.d.ts +0 -0
- /package/dist/{core → form}/validation/validators/date-utils.d.ts +0 -0
- /package/dist/{core → form}/validation/validators/email.d.ts +0 -0
- /package/dist/{core → form}/validation/validators/future-date.d.ts +0 -0
- /package/dist/{core → form}/validation/validators/index.d.ts +0 -0
- /package/dist/{core → form}/validation/validators/integer.d.ts +0 -0
- /package/dist/{core → form}/validation/validators/is-date.d.ts +0 -0
- /package/dist/{core → form}/validation/validators/is-number.d.ts +0 -0
- /package/dist/{core → form}/validation/validators/max-age.d.ts +0 -0
- /package/dist/{core → form}/validation/validators/max-date.d.ts +0 -0
- /package/dist/{core → form}/validation/validators/max-length.d.ts +0 -0
- /package/dist/{core → form}/validation/validators/max.d.ts +0 -0
- /package/dist/{core → form}/validation/validators/min-age.d.ts +0 -0
- /package/dist/{core → form}/validation/validators/min-date.d.ts +0 -0
- /package/dist/{core → form}/validation/validators/min-length.d.ts +0 -0
- /package/dist/{core → form}/validation/validators/min.d.ts +0 -0
- /package/dist/{core → form}/validation/validators/multiple-of.d.ts +0 -0
- /package/dist/{core → form}/validation/validators/non-negative.d.ts +0 -0
- /package/dist/{core → form}/validation/validators/non-zero.d.ts +0 -0
- /package/dist/{core → form}/validation/validators/past-date.d.ts +0 -0
- /package/dist/{core → form}/validation/validators/pattern.d.ts +0 -0
- /package/dist/{core → form}/validation/validators/phone.d.ts +0 -0
- /package/dist/{core → form}/validation/validators/url.d.ts +0 -0
- /package/dist/{core/utils → state}/subscription-manager.d.ts +0 -0
package/llms.txt
CHANGED
|
@@ -242,7 +242,7 @@ model.properties.length; // реактивная длина
|
|
|
242
242
|
```typescript
|
|
243
243
|
// Модель данных (источник истины значений)
|
|
244
244
|
createModel<T extends object>(initial: T): FormModel<T>
|
|
245
|
-
// model.get() / model.set(
|
|
245
|
+
// model.get() / model.set(full) / model.patch(partial) / model.isDirty()
|
|
246
246
|
// model.reset() / model.captureInitial() / model.signalAt(path)
|
|
247
247
|
// model.$.field → PathAwareSignal<FieldType> (escape-hatch к сигналу)
|
|
248
248
|
// model.arrayField → ModelArray<Item> (push/removeAt/insertAt/move/swap/clear/at/map/length)
|
|
@@ -937,20 +937,21 @@ const form = createForm<MyForm>({ model, schema });
|
|
|
937
937
|
|
|
938
938
|
### Nested Objects
|
|
939
939
|
|
|
940
|
-
Вложенная группа —
|
|
941
|
-
|
|
940
|
+
Вложенная группа модели — это сама по себе под-модель `FormModel<Sub>` (доступна как `model.<group>`,
|
|
941
|
+
с `.$`/API). Удобно вынести в builder, принимающий `FormModel<Sub>` — симметрично builder'у элемента
|
|
942
|
+
массива. Сигналы под-модели идентичны корневым: `model.address.$.city === model.$.address.city`.
|
|
942
943
|
|
|
943
944
|
```typescript
|
|
944
|
-
import type {
|
|
945
|
+
import type { FormModel } from '@reformer/core';
|
|
945
946
|
|
|
946
|
-
const addressNodes = (
|
|
947
|
-
street: { value:
|
|
948
|
-
city: { value:
|
|
949
|
-
zip: { value:
|
|
947
|
+
const addressNodes = (m: FormModel<Address>) => ({
|
|
948
|
+
street: { value: m.$.street, component: Input, componentProps: { label: 'Street' } },
|
|
949
|
+
city: { value: m.$.city, component: Input, componentProps: { label: 'City' } },
|
|
950
|
+
zip: { value: m.$.zip, component: Input, componentProps: { label: 'ZIP' } },
|
|
950
951
|
});
|
|
951
952
|
|
|
952
953
|
const schema = {
|
|
953
|
-
address: addressNodes(model
|
|
954
|
+
address: addressNodes(model.address),
|
|
954
955
|
};
|
|
955
956
|
```
|
|
956
957
|
|
|
@@ -1963,11 +1964,12 @@ const count = useArrayLength(control.items);
|
|
|
1963
1964
|
// value-доступ (реактивно внутри effect/computed, запись присваиванием)
|
|
1964
1965
|
model.email; // читать
|
|
1965
1966
|
model.email = 'a@b.c'; // писать
|
|
1966
|
-
model.address.city; // вложенное поле
|
|
1967
|
+
model.address.city; // вложенное поле (model.address — под-модель FormModel<Address>)
|
|
1967
1968
|
|
|
1968
1969
|
// через сигнал (escape-hatch)
|
|
1969
1970
|
model.$.email.value; // реактивное чтение/запись
|
|
1970
1971
|
model.$.email.peek(); // нереактивный снимок
|
|
1972
|
+
model.$.address.city.value; // сигнал вложенного поля (≡ model.address.$.city у под-модели)
|
|
1971
1973
|
|
|
1972
1974
|
// весь объект
|
|
1973
1975
|
model.get(); // снимок { email, address: { city }, ... } — для submit
|
|
@@ -2962,7 +2964,7 @@ A: Передай в колбэк под-схему только этого по
|
|
|
2962
2964
|
// Модель (источник истины значений):
|
|
2963
2965
|
interface ModelApi<T> {
|
|
2964
2966
|
get(): T; // снимок значений — для submit
|
|
2965
|
-
set(value:
|
|
2967
|
+
set(value: T): void; // полная установка (все ключи T)
|
|
2966
2968
|
patch(value: Partial<T>): void; // частичное слияние
|
|
2967
2969
|
isDirty(): boolean; // отличаются ли значения от initial-снимка
|
|
2968
2970
|
reset(): void; // вернуть к initial-снимку
|
|
@@ -3083,7 +3085,7 @@ import { createModel, validateModel } from '@reformer/core';
|
|
|
3083
3085
|
|
|
3084
3086
|
async function processFormPayload(rawData: Partial<MyForm>) {
|
|
3085
3087
|
const model = createModel<MyForm>(initialValues);
|
|
3086
|
-
model.
|
|
3088
|
+
model.patch(rawData); // частичный load данных
|
|
3087
3089
|
|
|
3088
3090
|
const result = await validateModel(model, schema); // без нод — просто данные
|
|
3089
3091
|
if (!result.valid) return { ok: false, errors: result.errors };
|
|
@@ -3166,8 +3168,8 @@ race-guard через deps). Динамические `componentProps` (опци
|
|
|
3166
3168
|
|
|
3167
3169
|
```typescript
|
|
3168
3170
|
// Модель:
|
|
3169
|
-
model.set(value:
|
|
3170
|
-
model.patch(value: Partial<T>): void; // частичное слияние (
|
|
3171
|
+
model.set(value: T): void; // полная установка значений (load полного DTO). Не меняет initial.
|
|
3172
|
+
model.patch(value: Partial<T>): void; // частичное слияние (только переданные ключи). Не меняет initial.
|
|
3171
3173
|
model.reset(): void; // вернуть к initial-снимку
|
|
3172
3174
|
model.captureInitial(): void; // сделать текущие значения новым initial-снимком
|
|
3173
3175
|
|
|
@@ -3695,7 +3697,7 @@ _Auto-generated from JSDoc on public exports._
|
|
|
3695
3697
|
export type AnyFunction = (...args: never[]) => unknown;
|
|
3696
3698
|
```
|
|
3697
3699
|
|
|
3698
|
-
_Source: src/
|
|
3700
|
+
_Source: src/form/types/index.ts_
|
|
3699
3701
|
|
|
3700
3702
|
### ArrayConfig
|
|
3701
3703
|
|
|
@@ -3711,7 +3713,7 @@ export interface ArrayConfig<T extends object> {
|
|
|
3711
3713
|
}
|
|
3712
3714
|
```
|
|
3713
3715
|
|
|
3714
|
-
_Source: src/
|
|
3716
|
+
_Source: src/form/types/deep-schema.ts_
|
|
3715
3717
|
|
|
3716
3718
|
### ArrayControlState
|
|
3717
3719
|
|
|
@@ -3815,6 +3817,23 @@ export interface ArrayControlState<T> {
|
|
|
3815
3817
|
* ```
|
|
3816
3818
|
*/
|
|
3817
3819
|
dirty: boolean;
|
|
3820
|
+
|
|
3821
|
+
/**
|
|
3822
|
+
* Флаг отключения массива.
|
|
3823
|
+
* `true` когда массив отключён (`ArrayNode.disable()`), в том числе через
|
|
3824
|
+
* распространение disable от родительской группы.
|
|
3825
|
+
*
|
|
3826
|
+
* Используйте для отключения UI-действий добавления/удаления, когда массив
|
|
3827
|
+
* структурно неизменяем.
|
|
3828
|
+
*
|
|
3829
|
+
* @example
|
|
3830
|
+
* ```tsx
|
|
3831
|
+
* const { disabled } = useFormControl(itemsArray);
|
|
3832
|
+
*
|
|
3833
|
+
* return <button disabled={disabled} onClick={() => control.push()}>Add</button>;
|
|
3834
|
+
* ```
|
|
3835
|
+
*/
|
|
3836
|
+
disabled: boolean;
|
|
3818
3837
|
}
|
|
3819
3838
|
```
|
|
3820
3839
|
|
|
@@ -3860,7 +3879,7 @@ Add Phone
|
|
|
3860
3879
|
- {@link useFormControl} - хук для получения состояния
|
|
3861
3880
|
- {@link FieldControlState} - состояние для полей
|
|
3862
3881
|
|
|
3863
|
-
_Source: src/hooks/types.ts_
|
|
3882
|
+
_Source: src/form/hooks/types.ts_
|
|
3864
3883
|
|
|
3865
3884
|
### ArrayNode
|
|
3866
3885
|
|
|
@@ -3889,7 +3908,7 @@ array.at(0)?.title.setValue('Updated');
|
|
|
3889
3908
|
console.log(array.length.value); // 1
|
|
3890
3909
|
```
|
|
3891
3910
|
|
|
3892
|
-
_Source: src/
|
|
3911
|
+
_Source: src/form/nodes/array-node.ts_
|
|
3893
3912
|
|
|
3894
3913
|
### ArrayNodeLike
|
|
3895
3914
|
|
|
@@ -3906,15 +3925,14 @@ export interface ArrayNodeLike {
|
|
|
3906
3925
|
}
|
|
3907
3926
|
```
|
|
3908
3927
|
|
|
3909
|
-
_Source: src/
|
|
3928
|
+
_Source: src/form/types/index.ts_
|
|
3910
3929
|
|
|
3911
3930
|
### AsyncValidator
|
|
3912
3931
|
|
|
3913
3932
|
**Kind:** `type`
|
|
3914
3933
|
|
|
3915
3934
|
Чистый асинхронный валидатор поля. Та же тройка аргументов `(value, scope, root)`, что у
|
|
3916
|
-
{@link Validator}, но возвращает `Promise`.
|
|
3917
|
-
`validateAsync(path, validator, { debounce })`.
|
|
3935
|
+
{@link Validator}, но возвращает `Promise`.
|
|
3918
3936
|
|
|
3919
3937
|
**Signature:**
|
|
3920
3938
|
```typescript
|
|
@@ -3925,7 +3943,11 @@ export type AsyncValidator<TForm, TField> = (
|
|
|
3925
3943
|
) => Promise<ValidationError | null>;
|
|
3926
3944
|
```
|
|
3927
3945
|
|
|
3928
|
-
|
|
3946
|
+
**Deprecated:** Осиротевший остаток удалённого оператора `validateAsync` (Ф7). Рантаймом не
|
|
3947
|
+
потребляется — живой async-путь узла поля использует `AsyncValidatorFn` `(value, { signal })`.
|
|
3948
|
+
Экспортируется только ради обратной совместимости.
|
|
3949
|
+
|
|
3950
|
+
_Source: src/form/types/validation-schema.ts_
|
|
3929
3951
|
|
|
3930
3952
|
### AsyncValidatorFn
|
|
3931
3953
|
|
|
@@ -3965,7 +3987,7 @@ const emailExistsAbortable: AsyncValidatorFn<string> = async (value, options) =>
|
|
|
3965
3987
|
};
|
|
3966
3988
|
```
|
|
3967
3989
|
|
|
3968
|
-
_Source: src/
|
|
3990
|
+
_Source: src/form/types/contracts.ts_
|
|
3969
3991
|
|
|
3970
3992
|
### AsyncValidatorOptions
|
|
3971
3993
|
|
|
@@ -3984,7 +4006,7 @@ export interface AsyncValidatorOptions {
|
|
|
3984
4006
|
}
|
|
3985
4007
|
```
|
|
3986
4008
|
|
|
3987
|
-
_Source: src/
|
|
4009
|
+
_Source: src/form/types/contracts.ts_
|
|
3988
4010
|
|
|
3989
4011
|
### BehaviorCleanup
|
|
3990
4012
|
|
|
@@ -3997,7 +4019,7 @@ _Source: src/core/types/index.ts_
|
|
|
3997
4019
|
export type BehaviorCleanup = () => void;
|
|
3998
4020
|
```
|
|
3999
4021
|
|
|
4000
|
-
_Source: src/
|
|
4022
|
+
_Source: src/state/behaviors-value.ts_
|
|
4001
4023
|
|
|
4002
4024
|
### computeFrom
|
|
4003
4025
|
|
|
@@ -4028,20 +4050,23 @@ export function computeFrom<R>(
|
|
|
4028
4050
|
computeFrom([model.$.price, model.$.qty], model.$.total, (price, qty) => price * qty);
|
|
4029
4051
|
```
|
|
4030
4052
|
|
|
4031
|
-
_Source: src/
|
|
4053
|
+
_Source: src/state/behaviors-value.ts_
|
|
4032
4054
|
|
|
4033
4055
|
### ConditionFn
|
|
4034
4056
|
|
|
4035
4057
|
**Kind:** `type`
|
|
4036
4058
|
|
|
4037
|
-
|
|
4059
|
+
Функция-предикат `(value) => boolean`.
|
|
4038
4060
|
|
|
4039
4061
|
**Signature:**
|
|
4040
4062
|
```typescript
|
|
4041
4063
|
export type ConditionFn<T> = (value: T) => boolean;
|
|
4042
4064
|
```
|
|
4043
4065
|
|
|
4044
|
-
|
|
4066
|
+
**Deprecated:** Осиротевший остаток удалённого оператора `applyWhen` (Ф7). Рантаймом не
|
|
4067
|
+
потребляется; экспортируется только ради обратной совместимости.
|
|
4068
|
+
|
|
4069
|
+
_Source: src/form/types/validation-schema.ts_
|
|
4045
4070
|
|
|
4046
4071
|
### ConfigWithSchema
|
|
4047
4072
|
|
|
@@ -4057,7 +4082,7 @@ export interface ConfigWithSchema {
|
|
|
4057
4082
|
}
|
|
4058
4083
|
```
|
|
4059
4084
|
|
|
4060
|
-
_Source: src/
|
|
4085
|
+
_Source: src/form/types/index.ts_
|
|
4061
4086
|
|
|
4062
4087
|
### ConfigWithValue
|
|
4063
4088
|
|
|
@@ -4072,7 +4097,7 @@ export interface ConfigWithValue {
|
|
|
4072
4097
|
}
|
|
4073
4098
|
```
|
|
4074
4099
|
|
|
4075
|
-
_Source: src/
|
|
4100
|
+
_Source: src/form/types/index.ts_
|
|
4076
4101
|
|
|
4077
4102
|
### copyFrom
|
|
4078
4103
|
|
|
@@ -4095,7 +4120,7 @@ export function copyFrom<T>(
|
|
|
4095
4120
|
copyFrom(model.$.email, model.$.emailAdditional, { when: () => model.sameEmail });
|
|
4096
4121
|
```
|
|
4097
4122
|
|
|
4098
|
-
_Source: src/
|
|
4123
|
+
_Source: src/state/behaviors-value.ts_
|
|
4099
4124
|
|
|
4100
4125
|
### createForm
|
|
4101
4126
|
|
|
@@ -4151,7 +4176,7 @@ form.email.setValue('test@mail.com');
|
|
|
4151
4176
|
const { valid } = await validateFormModel(model, schema);
|
|
4152
4177
|
```
|
|
4153
4178
|
|
|
4154
|
-
_Source: src/
|
|
4179
|
+
_Source: src/form/create-form.ts_
|
|
4155
4180
|
|
|
4156
4181
|
### createFormFromModel
|
|
4157
4182
|
|
|
@@ -4194,6 +4219,7 @@ const schema = {
|
|
|
4194
4219
|
component: Section,
|
|
4195
4220
|
children: [
|
|
4196
4221
|
{ value: model.$.email, component: Input, validators: [required] },
|
|
4222
|
+
// вложенная группа: `model.$.profile.name` (≡ под-модель `model.profile.$.name` — тот же сигнал)
|
|
4197
4223
|
{ value: model.$.profile.name, component: Input },
|
|
4198
4224
|
],
|
|
4199
4225
|
};
|
|
@@ -4208,7 +4234,7 @@ console.log(model.email); // 'user@mail.com'
|
|
|
4208
4234
|
**See also:**
|
|
4209
4235
|
- {@link createForm} - основная фабрика (диспетчеризует сюда при аргументе `{ model, schema }`)
|
|
4210
4236
|
|
|
4211
|
-
_Source: src/
|
|
4237
|
+
_Source: src/form/create-form.ts_
|
|
4212
4238
|
|
|
4213
4239
|
### CreateFormFromModelArgs
|
|
4214
4240
|
|
|
@@ -4235,7 +4261,7 @@ export interface CreateFormFromModelArgs<T> {
|
|
|
4235
4261
|
}
|
|
4236
4262
|
```
|
|
4237
4263
|
|
|
4238
|
-
_Source: src/
|
|
4264
|
+
_Source: src/form/create-form.ts_
|
|
4239
4265
|
|
|
4240
4266
|
### createModel
|
|
4241
4267
|
|
|
@@ -4256,14 +4282,22 @@ export function createModel<T extends object>(initial: T): FormModel<T>
|
|
|
4256
4282
|
**Examples:**
|
|
4257
4283
|
|
|
4258
4284
|
```typescript
|
|
4259
|
-
const model = createModel<{ email: string;
|
|
4285
|
+
const model = createModel<{ email: string; profile: { name: string }; tags: string[] }>({
|
|
4286
|
+
email: '',
|
|
4287
|
+
profile: { name: '' },
|
|
4288
|
+
tags: [],
|
|
4289
|
+
});
|
|
4260
4290
|
model.email = 'a@b.c';
|
|
4261
|
-
model.$.email.value;
|
|
4291
|
+
model.$.email.value; // 'a@b.c' (сигнал)
|
|
4292
|
+
// вложенная объект-группа — под-модель FormModel (value-доступ + `.$` + API):
|
|
4293
|
+
model.profile.name = 'Ada'; // value-запись
|
|
4294
|
+
model.$.profile.name.value; // 'Ada' (сигнал; ≡ model.profile.$.name у под-модели)
|
|
4295
|
+
model.profile.get(); // { name: 'Ada' }
|
|
4262
4296
|
model.tags.push('x');
|
|
4263
|
-
model.get();
|
|
4297
|
+
model.get(); // { email: 'a@b.c', profile: { name: 'Ada' }, tags: ['x'] }
|
|
4264
4298
|
```
|
|
4265
4299
|
|
|
4266
|
-
_Source: src/
|
|
4300
|
+
_Source: src/state/form-model.ts_
|
|
4267
4301
|
|
|
4268
4302
|
### disableWhen
|
|
4269
4303
|
|
|
@@ -4295,7 +4329,7 @@ export function disableWhen(
|
|
|
4295
4329
|
disableWhen(model.$.discount, () => model.plan !== 'promo', { resetOnDisable: true });
|
|
4296
4330
|
```
|
|
4297
4331
|
|
|
4298
|
-
_Source: src/
|
|
4332
|
+
_Source: src/form/behaviors-node.ts_
|
|
4299
4333
|
|
|
4300
4334
|
### email
|
|
4301
4335
|
|
|
@@ -4332,7 +4366,7 @@ validators: [required(), email({ message: 'Введите корректный e
|
|
|
4332
4366
|
},
|
|
4333
4367
|
```
|
|
4334
4368
|
|
|
4335
|
-
_Source: src/
|
|
4369
|
+
_Source: src/form/validation/validators/email.ts_
|
|
4336
4370
|
|
|
4337
4371
|
### enableWhen
|
|
4338
4372
|
|
|
@@ -4346,6 +4380,15 @@ _Source: src/core/validation/validators/email.ts_
|
|
|
4346
4380
|
⚠️ Поле должно быть материализовано в форме (`createForm`) — иначе ноды в реестре нет (например,
|
|
4347
4381
|
элемент массива, который строится per-item).
|
|
4348
4382
|
|
|
4383
|
+
⚠️ Если то же поле одновременно является целью `compute`/`computeFrom`, обязательно ограничь
|
|
4384
|
+
compute тем же условием (`when`), что и это `enableWhen`. Механизмы не согласованы: `enableWhen`
|
|
4385
|
+
работает со статус-машиной ноды (enable/disable/reset), а `compute` пишет `target.value` напрямую
|
|
4386
|
+
в сигнал модели и проверяет только собственный `options.when` — состояние `disabled` он НЕ смотрит.
|
|
4387
|
+
Поэтому при выключенном поле любое изменение зависимости compute молча заново заполнит его (а с
|
|
4388
|
+
`resetOnDisable` — перезапишет только что сброшенное значение), и так как `getValue()`/`submit`
|
|
4389
|
+
включают disabled-поля, мусор утечёт в payload. Это аналог правила #13 гайда add-behavior,
|
|
4390
|
+
которое сегодня сформулировано только для `copyFrom`; для `compute` то же ограничение обязательно.
|
|
4391
|
+
|
|
4349
4392
|
**Signature:**
|
|
4350
4393
|
```typescript
|
|
4351
4394
|
export function enableWhen(
|
|
@@ -4359,9 +4402,15 @@ export function enableWhen(
|
|
|
4359
4402
|
|
|
4360
4403
|
```typescript
|
|
4361
4404
|
enableWhen(model.$.propertyValue, () => model.loanType === 'mortgage', { resetOnDisable: true });
|
|
4405
|
+
|
|
4406
|
+
// Поле-цель compute, которое ТАКЖЕ в resetOnDisable enableWhen: compute обязан нести тот же when,
|
|
4407
|
+
// иначе initialPayment заново заполнится в выключенном состоянии и утечёт в submit.
|
|
4408
|
+
compute(model.$.initialPayment, () => model.propertyValue * 0.2, {
|
|
4409
|
+
when: () => model.loanType === 'mortgage',
|
|
4410
|
+
});
|
|
4362
4411
|
```
|
|
4363
4412
|
|
|
4364
|
-
_Source: src/
|
|
4413
|
+
_Source: src/form/behaviors-node.ts_
|
|
4365
4414
|
|
|
4366
4415
|
### ErrorFilterOptions
|
|
4367
4416
|
|
|
@@ -4386,7 +4435,7 @@ export interface ErrorFilterOptions {
|
|
|
4386
4435
|
}
|
|
4387
4436
|
```
|
|
4388
4437
|
|
|
4389
|
-
_Source: src/
|
|
4438
|
+
_Source: src/form/types/contracts.ts_
|
|
4390
4439
|
|
|
4391
4440
|
### ErrorStrategy
|
|
4392
4441
|
|
|
@@ -4419,7 +4468,7 @@ export enum ErrorStrategy {
|
|
|
4419
4468
|
}
|
|
4420
4469
|
```
|
|
4421
4470
|
|
|
4422
|
-
_Source: src/
|
|
4471
|
+
_Source: src/form/error-handler.ts_
|
|
4423
4472
|
|
|
4424
4473
|
### FieldConfig
|
|
4425
4474
|
|
|
@@ -4457,7 +4506,7 @@ export interface FieldConfig<T> {
|
|
|
4457
4506
|
}
|
|
4458
4507
|
```
|
|
4459
4508
|
|
|
4460
|
-
_Source: src/
|
|
4509
|
+
_Source: src/form/types/deep-schema.ts_
|
|
4461
4510
|
|
|
4462
4511
|
### FieldControlState
|
|
4463
4512
|
|
|
@@ -4633,6 +4682,21 @@ export interface FieldControlState<T> {
|
|
|
4633
4682
|
* ```
|
|
4634
4683
|
*/
|
|
4635
4684
|
componentProps: Record<string, unknown>;
|
|
4685
|
+
|
|
4686
|
+
/**
|
|
4687
|
+
* Флаг изменения поля.
|
|
4688
|
+
* `true` когда значение поля отличается от начального.
|
|
4689
|
+
*
|
|
4690
|
+
* Реактивный аналог `control.dirty` — паритет с {@link ArrayControlState.dirty}.
|
|
4691
|
+
*
|
|
4692
|
+
* @example
|
|
4693
|
+
* ```tsx
|
|
4694
|
+
* const { dirty } = useFormControl(field);
|
|
4695
|
+
*
|
|
4696
|
+
* return dirty ? <span className="badge">Изменено</span> : null;
|
|
4697
|
+
* ```
|
|
4698
|
+
*/
|
|
4699
|
+
dirty: boolean;
|
|
4636
4700
|
}
|
|
4637
4701
|
```
|
|
4638
4702
|
|
|
@@ -4666,7 +4730,7 @@ onChange={e => control.setValue(e.target.value)}
|
|
|
4666
4730
|
- {@link useFormControl} - хук для получения состояния
|
|
4667
4731
|
- {@link ArrayControlState} - состояние для массивов
|
|
4668
4732
|
|
|
4669
|
-
_Source: src/hooks/types.ts_
|
|
4733
|
+
_Source: src/form/hooks/types.ts_
|
|
4670
4734
|
|
|
4671
4735
|
### FieldNode
|
|
4672
4736
|
|
|
@@ -4696,7 +4760,7 @@ await field.validate();
|
|
|
4696
4760
|
console.log(field.valid.value); // true
|
|
4697
4761
|
```
|
|
4698
4762
|
|
|
4699
|
-
_Source: src/
|
|
4763
|
+
_Source: src/form/nodes/field-node.ts_
|
|
4700
4764
|
|
|
4701
4765
|
### FieldPathSegment
|
|
4702
4766
|
|
|
@@ -4713,7 +4777,7 @@ export type FieldPathSegment = {
|
|
|
4713
4777
|
};
|
|
4714
4778
|
```
|
|
4715
4779
|
|
|
4716
|
-
_Source: src/
|
|
4780
|
+
_Source: src/form/types/index.ts_
|
|
4717
4781
|
|
|
4718
4782
|
### FieldStatus
|
|
4719
4783
|
|
|
@@ -4726,7 +4790,7 @@ _Source: src/core/types/index.ts_
|
|
|
4726
4790
|
export type FieldStatus = 'valid' | 'invalid' | 'pending' | 'disabled';
|
|
4727
4791
|
```
|
|
4728
4792
|
|
|
4729
|
-
_Source: src/
|
|
4793
|
+
_Source: src/form/types/contracts.ts_
|
|
4730
4794
|
|
|
4731
4795
|
### FormArrayProxy
|
|
4732
4796
|
|
|
@@ -4780,7 +4844,7 @@ todos.forEach((item, i) => {
|
|
|
4780
4844
|
});
|
|
4781
4845
|
```
|
|
4782
4846
|
|
|
4783
|
-
_Source: src/
|
|
4847
|
+
_Source: src/form/types/form-proxy.ts_
|
|
4784
4848
|
|
|
4785
4849
|
### FormControlsProxy
|
|
4786
4850
|
|
|
@@ -4812,7 +4876,7 @@ export type FormControlsProxy<T> = {
|
|
|
4812
4876
|
};
|
|
4813
4877
|
```
|
|
4814
4878
|
|
|
4815
|
-
_Source: src/
|
|
4879
|
+
_Source: src/form/types/form-proxy.ts_
|
|
4816
4880
|
|
|
4817
4881
|
### FormErrorHandler
|
|
4818
4882
|
|
|
@@ -4894,20 +4958,22 @@ try {
|
|
|
4894
4958
|
}
|
|
4895
4959
|
```
|
|
4896
4960
|
|
|
4897
|
-
_Source: src/
|
|
4961
|
+
_Source: src/form/error-handler.ts_
|
|
4898
4962
|
|
|
4899
4963
|
### FormModel
|
|
4900
4964
|
|
|
4901
4965
|
**Kind:** `type`
|
|
4902
4966
|
|
|
4903
|
-
FormModel —
|
|
4967
|
+
FormModel — под-модель объекта `T`: value-доступ ({@link ModelObject}) + `.$`-сигналы + {@link ModelApi}
|
|
4968
|
+
(get/set/patch/isDirty/reset/signalAt). Вложенные объекты-группы модели — тоже {@link FormModel}
|
|
4969
|
+
(доступны как `model.<group>`), поэтому `model.<group>.$.<field>` эквивалентно `model.$.<group>.<field>`.
|
|
4904
4970
|
|
|
4905
4971
|
**Signature:**
|
|
4906
4972
|
```typescript
|
|
4907
4973
|
export type FormModel<T> = ModelObject<T> & ModelApi<T>;
|
|
4908
4974
|
```
|
|
4909
4975
|
|
|
4910
|
-
_Source: src/
|
|
4976
|
+
_Source: src/state/types.ts_
|
|
4911
4977
|
|
|
4912
4978
|
### FormNode
|
|
4913
4979
|
|
|
@@ -4947,7 +5013,7 @@ form.email instanceof FormNode; // true
|
|
|
4947
5013
|
form.email.markAsTouched();
|
|
4948
5014
|
```
|
|
4949
5015
|
|
|
4950
|
-
_Source: src/
|
|
5016
|
+
_Source: src/form/nodes/form-node.ts_
|
|
4951
5017
|
|
|
4952
5018
|
### FormProxy
|
|
4953
5019
|
|
|
@@ -4960,7 +5026,27 @@ _Source: src/core/nodes/form-node.ts_
|
|
|
4960
5026
|
|
|
4961
5027
|
**Signature:**
|
|
4962
5028
|
```typescript
|
|
4963
|
-
export type FormProxy<T> = GroupNode<T> &
|
|
5029
|
+
export type FormProxy<T> = GroupNode<T> &
|
|
5030
|
+
// Исключаем имена, совпадающие с членами GroupNode: для них `form.<name>` возвращает член узла,
|
|
5031
|
+
// а не поле. Оставлять их в полевом пространстве — значит пересекать, напр., ReadonlySignal<FieldStatus>
|
|
5032
|
+
// с FieldNode<string> и молча компилировать невозможный тип. Escape-hatch — `form.$` ниже.
|
|
5033
|
+
Omit<FormControlsProxy<T>, keyof GroupNode<T>> & {
|
|
5034
|
+
/**
|
|
5035
|
+
* Escape-hatch пространство имён «controls»: типобезопасный доступ ко ВСЕМ полям формы
|
|
5036
|
+
* по имени, включая поля, чьи имена совпадают с членами {@link GroupNode}
|
|
5037
|
+
* (`value`/`status`/`id`/`errors`/…), недостижимые через `form.<name>`.
|
|
5038
|
+
*
|
|
5039
|
+
* @example
|
|
5040
|
+
* ```typescript
|
|
5041
|
+
* // модель: { status: string; email: string }
|
|
5042
|
+
* form.status; // ReadonlySignal<FieldStatus> — агрегат GroupNode (не поле!)
|
|
5043
|
+
* form.$.status; // FieldNode<string> — поле пользователя
|
|
5044
|
+
* form.$.status.setValue('active');
|
|
5045
|
+
* form.$.email; // FieldNode<string> — так же доступны и незатенённые поля
|
|
5046
|
+
* ```
|
|
5047
|
+
*/
|
|
5048
|
+
readonly $: FormControlsProxy<T>;
|
|
5049
|
+
};
|
|
4964
5050
|
```
|
|
4965
5051
|
|
|
4966
5052
|
**Examples:**
|
|
@@ -4986,7 +5072,7 @@ form.email.setValue('test@mail.com');
|
|
|
4986
5072
|
form.profile.name.setValue('John');
|
|
4987
5073
|
```
|
|
4988
5074
|
|
|
4989
|
-
_Source: src/
|
|
5075
|
+
_Source: src/form/types/form-proxy.ts_
|
|
4990
5076
|
|
|
4991
5077
|
### FormSchema
|
|
4992
5078
|
|
|
@@ -5007,16 +5093,18 @@ _Source: src/core/types/form-proxy.ts_
|
|
|
5007
5093
|
**Signature:**
|
|
5008
5094
|
```typescript
|
|
5009
5095
|
export type FormSchema<T> = {
|
|
5096
|
+
// Листовые позиции используют NonEmptyFieldConfig: пустой `{}` (частая опечатка) отклоняется
|
|
5097
|
+
// на этапе компиляции, но каждое свойство FieldConfig по отдельности остаётся опциональным.
|
|
5010
5098
|
[K in keyof T]: NonNullable<T[K]> extends string | number | boolean
|
|
5011
|
-
?
|
|
5099
|
+
? NonEmptyFieldConfig<T[K]>
|
|
5012
5100
|
: NonNullable<T[K]> extends Array<infer U>
|
|
5013
5101
|
? U extends string | number | boolean
|
|
5014
|
-
?
|
|
5102
|
+
? NonEmptyFieldConfig<T[K]>
|
|
5015
5103
|
: U extends Date | File | Blob | AnyFunction
|
|
5016
|
-
?
|
|
5104
|
+
? NonEmptyFieldConfig<T[K]>
|
|
5017
5105
|
: [FormSchema<U>]
|
|
5018
5106
|
: NonNullable<T[K]> extends Date | File | Blob | AnyFunction
|
|
5019
|
-
?
|
|
5107
|
+
? NonEmptyFieldConfig<T[K]>
|
|
5020
5108
|
: FormSchema<NonNullable<T[K]>>;
|
|
5021
5109
|
};
|
|
5022
5110
|
```
|
|
@@ -5049,7 +5137,7 @@ const schema: FormSchema<Form> = {
|
|
|
5049
5137
|
};
|
|
5050
5138
|
```
|
|
5051
5139
|
|
|
5052
|
-
_Source: src/
|
|
5140
|
+
_Source: src/form/types/deep-schema.ts_
|
|
5053
5141
|
|
|
5054
5142
|
### FormSchemaNode
|
|
5055
5143
|
|
|
@@ -5108,7 +5196,7 @@ export interface FormSchemaNode {
|
|
|
5108
5196
|
}
|
|
5109
5197
|
```
|
|
5110
5198
|
|
|
5111
|
-
_Source: src/
|
|
5199
|
+
_Source: src/form/types/schema-node.ts_
|
|
5112
5200
|
|
|
5113
5201
|
### FormStatusMachine
|
|
5114
5202
|
|
|
@@ -5145,7 +5233,7 @@ statusMachine.disable();
|
|
|
5145
5233
|
console.log(statusMachine.disabled.value); // true
|
|
5146
5234
|
```
|
|
5147
5235
|
|
|
5148
|
-
_Source: src/
|
|
5236
|
+
_Source: src/form/status-machine.ts_
|
|
5149
5237
|
|
|
5150
5238
|
### FormSubmitter
|
|
5151
5239
|
|
|
@@ -5175,7 +5263,7 @@ if (submitter.submitting.value) {
|
|
|
5175
5263
|
}
|
|
5176
5264
|
```
|
|
5177
5265
|
|
|
5178
|
-
_Source: src/
|
|
5266
|
+
_Source: src/form/form-submitter.ts_
|
|
5179
5267
|
|
|
5180
5268
|
### FormValue
|
|
5181
5269
|
|
|
@@ -5198,7 +5286,7 @@ export type FormValue =
|
|
|
5198
5286
|
| { [key: string]: FormValue };
|
|
5199
5287
|
```
|
|
5200
5288
|
|
|
5201
|
-
_Source: src/
|
|
5289
|
+
_Source: src/form/types/contracts.ts_
|
|
5202
5290
|
|
|
5203
5291
|
### futureDate
|
|
5204
5292
|
|
|
@@ -5236,7 +5324,7 @@ validators: [required(), futureDate({ message: 'Дата записи должн
|
|
|
5236
5324
|
},
|
|
5237
5325
|
```
|
|
5238
5326
|
|
|
5239
|
-
_Source: src/
|
|
5327
|
+
_Source: src/form/validation/validators/future-date.ts_
|
|
5240
5328
|
|
|
5241
5329
|
### getNodeForSignal
|
|
5242
5330
|
|
|
@@ -5271,7 +5359,7 @@ getNodeForSignal(sig)?.setErrors([{ code: 'required', message: 'Обязател
|
|
|
5271
5359
|
**See also:**
|
|
5272
5360
|
- {@link registerSignalNode} - регистрация связи сигнал→нода
|
|
5273
5361
|
|
|
5274
|
-
_Source: src/
|
|
5362
|
+
_Source: src/form/signal-node-registry.ts_
|
|
5275
5363
|
|
|
5276
5364
|
### getNodeType
|
|
5277
5365
|
|
|
@@ -5297,7 +5385,7 @@ export function getNodeType(node: unknown): string
|
|
|
5297
5385
|
console.log('Node type:', getNodeType(node)); // "FieldNode" | "GroupNode" | "ArrayNode" | "FormNode" | "Unknown"
|
|
5298
5386
|
```
|
|
5299
5387
|
|
|
5300
|
-
_Source: src/
|
|
5388
|
+
_Source: src/form/type-guards.ts_
|
|
5301
5389
|
|
|
5302
5390
|
### GroupNode
|
|
5303
5391
|
|
|
@@ -5332,7 +5420,7 @@ await proxy.validate();
|
|
|
5332
5420
|
console.log(proxy.valid.value);
|
|
5333
5421
|
```
|
|
5334
5422
|
|
|
5335
|
-
_Source: src/
|
|
5423
|
+
_Source: src/form/nodes/group-node.ts_
|
|
5336
5424
|
|
|
5337
5425
|
### GroupNodeConfig
|
|
5338
5426
|
|
|
@@ -5351,7 +5439,7 @@ export interface GroupNodeConfig<T> {
|
|
|
5351
5439
|
}
|
|
5352
5440
|
```
|
|
5353
5441
|
|
|
5354
|
-
_Source: src/
|
|
5442
|
+
_Source: src/form/types/index.ts_
|
|
5355
5443
|
|
|
5356
5444
|
### integer
|
|
5357
5445
|
|
|
@@ -5387,7 +5475,7 @@ validators: [required(), integer({ message: 'Должно быть целым ч
|
|
|
5387
5475
|
},
|
|
5388
5476
|
```
|
|
5389
5477
|
|
|
5390
|
-
_Source: src/
|
|
5478
|
+
_Source: src/form/validation/validators/integer.ts_
|
|
5391
5479
|
|
|
5392
5480
|
### isArrayNode
|
|
5393
5481
|
|
|
@@ -5418,7 +5506,7 @@ if (isArrayNode(node)) {
|
|
|
5418
5506
|
}
|
|
5419
5507
|
```
|
|
5420
5508
|
|
|
5421
|
-
_Source: src/
|
|
5509
|
+
_Source: src/form/type-guards.ts_
|
|
5422
5510
|
|
|
5423
5511
|
### isDate
|
|
5424
5512
|
|
|
@@ -5455,7 +5543,7 @@ validators: [required(), isDate({ message: 'Введите корректную
|
|
|
5455
5543
|
},
|
|
5456
5544
|
```
|
|
5457
5545
|
|
|
5458
|
-
_Source: src/
|
|
5546
|
+
_Source: src/form/validation/validators/is-date.ts_
|
|
5459
5547
|
|
|
5460
5548
|
### isDerived
|
|
5461
5549
|
|
|
@@ -5489,7 +5577,7 @@ if (!isDerived(model.$.total)) {
|
|
|
5489
5577
|
**See also:**
|
|
5490
5578
|
- {@link markDerived} - пометить сигнал производным
|
|
5491
5579
|
|
|
5492
|
-
_Source: src/
|
|
5580
|
+
_Source: src/state/derived-registry.ts_
|
|
5493
5581
|
|
|
5494
5582
|
### isFieldNode
|
|
5495
5583
|
|
|
@@ -5520,7 +5608,7 @@ if (isFieldNode(node)) {
|
|
|
5520
5608
|
}
|
|
5521
5609
|
```
|
|
5522
5610
|
|
|
5523
|
-
_Source: src/
|
|
5611
|
+
_Source: src/form/type-guards.ts_
|
|
5524
5612
|
|
|
5525
5613
|
### isFormNode
|
|
5526
5614
|
|
|
@@ -5549,7 +5637,7 @@ if (isFormNode(value)) {
|
|
|
5549
5637
|
}
|
|
5550
5638
|
```
|
|
5551
5639
|
|
|
5552
|
-
_Source: src/
|
|
5640
|
+
_Source: src/form/type-guards.ts_
|
|
5553
5641
|
|
|
5554
5642
|
### isGroupNode
|
|
5555
5643
|
|
|
@@ -5578,7 +5666,7 @@ if (isGroupNode(node)) {
|
|
|
5578
5666
|
}
|
|
5579
5667
|
```
|
|
5580
5668
|
|
|
5581
|
-
_Source: src/
|
|
5669
|
+
_Source: src/form/type-guards.ts_
|
|
5582
5670
|
|
|
5583
5671
|
### isNumber
|
|
5584
5672
|
|
|
@@ -5616,7 +5704,7 @@ validators: [required(), isNumber({ message: 'Введите число' })],
|
|
|
5616
5704
|
},
|
|
5617
5705
|
```
|
|
5618
5706
|
|
|
5619
|
-
_Source: src/
|
|
5707
|
+
_Source: src/form/validation/validators/is-number.ts_
|
|
5620
5708
|
|
|
5621
5709
|
### markDerived
|
|
5622
5710
|
|
|
@@ -5628,6 +5716,9 @@ _Source: src/core/validation/validators/is-number.ts_
|
|
|
5628
5716
|
bulk-сеттеры (`model.set`/`model.patch`, `patchValue`/`setValue`) пропускают это поле, чтобы
|
|
5629
5717
|
значение из payload не затирало вычисляемое. Прикладной код напрямую обычно не вызывает.
|
|
5630
5718
|
|
|
5719
|
+
Идемпотентна на уровне флага: повторные вызовы наращивают счётчик ссылок, чтобы каждый оператор,
|
|
5720
|
+
пишущий в этот сигнал, был сбалансирован своим {@link unmarkDerived} при dispose.
|
|
5721
|
+
|
|
5631
5722
|
**Signature:**
|
|
5632
5723
|
```typescript
|
|
5633
5724
|
export function markDerived(signal: Signal<any>): void
|
|
@@ -5647,8 +5738,9 @@ markDerived(model.$.total);
|
|
|
5647
5738
|
|
|
5648
5739
|
**See also:**
|
|
5649
5740
|
- {@link isDerived} - проверка пометки
|
|
5741
|
+
- {@link unmarkDerived} - снять пометку при dispose оператора
|
|
5650
5742
|
|
|
5651
|
-
_Source: src/
|
|
5743
|
+
_Source: src/state/derived-registry.ts_
|
|
5652
5744
|
|
|
5653
5745
|
### max
|
|
5654
5746
|
|
|
@@ -5688,7 +5780,7 @@ validators: [required(), max(50, { message: 'Не более 50%' })],
|
|
|
5688
5780
|
},
|
|
5689
5781
|
```
|
|
5690
5782
|
|
|
5691
|
-
_Source: src/
|
|
5783
|
+
_Source: src/form/validation/validators/max.ts_
|
|
5692
5784
|
|
|
5693
5785
|
### maxAge
|
|
5694
5786
|
|
|
@@ -5728,7 +5820,7 @@ validators: [maxAge(100, { message: 'Проверьте дату рождени
|
|
|
5728
5820
|
},
|
|
5729
5821
|
```
|
|
5730
5822
|
|
|
5731
|
-
_Source: src/
|
|
5823
|
+
_Source: src/form/validation/validators/max-age.ts_
|
|
5732
5824
|
|
|
5733
5825
|
### maxDate
|
|
5734
5826
|
|
|
@@ -5768,7 +5860,7 @@ validators: [maxDate(new Date(), { message: 'Дата не может быть
|
|
|
5768
5860
|
},
|
|
5769
5861
|
```
|
|
5770
5862
|
|
|
5771
|
-
_Source: src/
|
|
5863
|
+
_Source: src/form/validation/validators/max-date.ts_
|
|
5772
5864
|
|
|
5773
5865
|
### maxLength
|
|
5774
5866
|
|
|
@@ -5810,7 +5902,7 @@ validators: [maxLength(500, { message: 'Максимум 500 символов' }
|
|
|
5810
5902
|
},
|
|
5811
5903
|
```
|
|
5812
5904
|
|
|
5813
|
-
_Source: src/
|
|
5905
|
+
_Source: src/form/validation/validators/max-length.ts_
|
|
5814
5906
|
|
|
5815
5907
|
### min
|
|
5816
5908
|
|
|
@@ -5850,7 +5942,7 @@ validators: [required(), min(1, { message: 'Минимум 1' })],
|
|
|
5850
5942
|
},
|
|
5851
5943
|
```
|
|
5852
5944
|
|
|
5853
|
-
_Source: src/
|
|
5945
|
+
_Source: src/form/validation/validators/min.ts_
|
|
5854
5946
|
|
|
5855
5947
|
### minAge
|
|
5856
5948
|
|
|
@@ -5890,7 +5982,7 @@ validators: [required(), minAge(18, { message: 'Вам должно быть н
|
|
|
5890
5982
|
},
|
|
5891
5983
|
```
|
|
5892
5984
|
|
|
5893
|
-
_Source: src/
|
|
5985
|
+
_Source: src/form/validation/validators/min-age.ts_
|
|
5894
5986
|
|
|
5895
5987
|
### minDate
|
|
5896
5988
|
|
|
@@ -5930,7 +6022,7 @@ validators: [required(), minDate(new Date(), { message: 'Дата не рань
|
|
|
5930
6022
|
},
|
|
5931
6023
|
```
|
|
5932
6024
|
|
|
5933
|
-
_Source: src/
|
|
6025
|
+
_Source: src/form/validation/validators/min-date.ts_
|
|
5934
6026
|
|
|
5935
6027
|
### minLength
|
|
5936
6028
|
|
|
@@ -5972,13 +6064,13 @@ validators: [required(), minLength(8, { message: 'Минимум 8 символ
|
|
|
5972
6064
|
},
|
|
5973
6065
|
```
|
|
5974
6066
|
|
|
5975
|
-
_Source: src/
|
|
6067
|
+
_Source: src/form/validation/validators/min-length.ts_
|
|
5976
6068
|
|
|
5977
6069
|
### ModelApi
|
|
5978
6070
|
|
|
5979
6071
|
**Kind:** `interface`
|
|
5980
6072
|
|
|
5981
|
-
API уровня модели (доступно на
|
|
6073
|
+
API уровня модели (доступно на корне, под-моделях вложенных объектов-групп и элементов массива).
|
|
5982
6074
|
|
|
5983
6075
|
⚠️ Имена методов (`$`/`get`/`set`/`patch`/`isDirty`/`reset`/`signalAt`/`captureInitial`)
|
|
5984
6076
|
зарезервированы: одноимённое поле формы их затеняет (редкий краевой случай).
|
|
@@ -5991,12 +6083,11 @@ export interface ModelApi<T> {
|
|
|
5991
6083
|
/** Снимок значений (без подписки) — для submit. */
|
|
5992
6084
|
get(): T;
|
|
5993
6085
|
/**
|
|
5994
|
-
*
|
|
5995
|
-
*
|
|
5996
|
-
*
|
|
5997
|
-
* `patch({ ...defaults, ...dto })` явно. Не меняет initial-снимок.
|
|
6086
|
+
* Полная установка значений: принимает объект целиком (все ключи `T`) и записывает их в модель.
|
|
6087
|
+
* Производными полями (цели `compute`) владеет compute — их значения из payload игнорируются.
|
|
6088
|
+
* Не меняет initial-снимок. Для частичного обновления (только переданные ключи) — {@link ModelApi.patch}.
|
|
5998
6089
|
*/
|
|
5999
|
-
set(value:
|
|
6090
|
+
set(value: T): void;
|
|
6000
6091
|
/**
|
|
6001
6092
|
* Частичное слияние значений (load/patch с сервера): обновляет только переданные ключи,
|
|
6002
6093
|
* отсутствующие ключи НЕ трогаются. Не меняет initial-снимок.
|
|
@@ -6013,7 +6104,7 @@ export interface ModelApi<T> {
|
|
|
6013
6104
|
}
|
|
6014
6105
|
```
|
|
6015
6106
|
|
|
6016
|
-
_Source: src/
|
|
6107
|
+
_Source: src/state/types.ts_
|
|
6017
6108
|
|
|
6018
6109
|
### ModelArray
|
|
6019
6110
|
|
|
@@ -6059,7 +6150,7 @@ export interface ModelArray<U> {
|
|
|
6059
6150
|
}
|
|
6060
6151
|
```
|
|
6061
6152
|
|
|
6062
|
-
_Source: src/
|
|
6153
|
+
_Source: src/state/types.ts_
|
|
6063
6154
|
|
|
6064
6155
|
### ModelArrayControl
|
|
6065
6156
|
|
|
@@ -6082,7 +6173,7 @@ export interface ModelArrayControl<TItem extends object> {
|
|
|
6082
6173
|
}
|
|
6083
6174
|
```
|
|
6084
6175
|
|
|
6085
|
-
_Source: src/
|
|
6176
|
+
_Source: src/form/nodes/model-array-node.ts_
|
|
6086
6177
|
|
|
6087
6178
|
### ModelArrayNode
|
|
6088
6179
|
|
|
@@ -6130,14 +6221,15 @@ rows.at(0)?.name.setValue('B'); // правка поля элемента д
|
|
|
6130
6221
|
rows.length.value; // 1 (реактивная длина)
|
|
6131
6222
|
```
|
|
6132
6223
|
|
|
6133
|
-
_Source: src/
|
|
6224
|
+
_Source: src/form/nodes/model-array-node.ts_
|
|
6134
6225
|
|
|
6135
6226
|
### ModelObject
|
|
6136
6227
|
|
|
6137
6228
|
**Kind:** `type`
|
|
6138
6229
|
|
|
6139
|
-
value
|
|
6140
|
-
внутри `effect`/`computed`, запись — присваиванием).
|
|
6230
|
+
Карта value-полей объекта (value-половина {@link FormModel}): поля доступны как обычные свойства
|
|
6231
|
+
(чтение реактивно внутри `effect`/`computed`, запись — присваиванием). Вложенные объекты-поля
|
|
6232
|
+
резолвятся в под-модели {@link FormModel} (см. {@link ModelValue}), массивы — в {@link ModelArray}.
|
|
6141
6233
|
|
|
6142
6234
|
**Signature:**
|
|
6143
6235
|
```typescript
|
|
@@ -6146,7 +6238,7 @@ export type ModelObject<T> = {
|
|
|
6146
6238
|
};
|
|
6147
6239
|
```
|
|
6148
6240
|
|
|
6149
|
-
_Source: src/
|
|
6241
|
+
_Source: src/state/types.ts_
|
|
6150
6242
|
|
|
6151
6243
|
### ModelSignals
|
|
6152
6244
|
|
|
@@ -6162,7 +6254,7 @@ export type ModelSignals<T> = {
|
|
|
6162
6254
|
};
|
|
6163
6255
|
```
|
|
6164
6256
|
|
|
6165
|
-
_Source: src/
|
|
6257
|
+
_Source: src/state/types.ts_
|
|
6166
6258
|
|
|
6167
6259
|
### ModelValidationResult
|
|
6168
6260
|
|
|
@@ -6179,7 +6271,7 @@ export interface ModelValidationResult {
|
|
|
6179
6271
|
}
|
|
6180
6272
|
```
|
|
6181
6273
|
|
|
6182
|
-
_Source: src/
|
|
6274
|
+
_Source: src/form/validate-model-core.ts_
|
|
6183
6275
|
|
|
6184
6276
|
### ModelValidator
|
|
6185
6277
|
|
|
@@ -6200,7 +6292,7 @@ export type ModelValidator<TValue = unknown, TModel = unknown, TRoot = unknown>
|
|
|
6200
6292
|
) => ValidationError | null | Promise<ValidationError | null>;
|
|
6201
6293
|
```
|
|
6202
6294
|
|
|
6203
|
-
_Source: src/
|
|
6295
|
+
_Source: src/form/validate-model-core.ts_
|
|
6204
6296
|
|
|
6205
6297
|
### ModelValue
|
|
6206
6298
|
|
|
@@ -6209,7 +6301,8 @@ _Source: src/core/model/validate-model.ts_
|
|
|
6209
6301
|
Значение поля в value-доступе модели:
|
|
6210
6302
|
- массив → {@link ModelArray}
|
|
6211
6303
|
- спец-объект (Date/File/Blob) → как есть
|
|
6212
|
-
- объект →
|
|
6304
|
+
- объект → под-модель {@link FormModel} (value-доступ + `.$`-сигналы + API get/set/patch/…);
|
|
6305
|
+
промоутится рантаймом (`makeFormModel`); сигналы идентичны `model.$.<path>`
|
|
6213
6306
|
- примитив → значение
|
|
6214
6307
|
|
|
6215
6308
|
**Signature:**
|
|
@@ -6220,11 +6313,11 @@ export type ModelValue<V> =
|
|
|
6220
6313
|
: NonNullable<V> extends Opaque
|
|
6221
6314
|
? V
|
|
6222
6315
|
: NonNullable<V> extends object
|
|
6223
|
-
?
|
|
6316
|
+
? FormModel<NonNullable<V>>
|
|
6224
6317
|
: V;
|
|
6225
6318
|
```
|
|
6226
6319
|
|
|
6227
|
-
_Source: src/
|
|
6320
|
+
_Source: src/state/types.ts_
|
|
6228
6321
|
|
|
6229
6322
|
### multipleOf
|
|
6230
6323
|
|
|
@@ -6263,7 +6356,7 @@ validators: [multipleOf(0.5, { message: 'Только шаг 0.5' })],
|
|
|
6263
6356
|
},
|
|
6264
6357
|
```
|
|
6265
6358
|
|
|
6266
|
-
_Source: src/
|
|
6359
|
+
_Source: src/form/validation/validators/multiple-of.ts_
|
|
6267
6360
|
|
|
6268
6361
|
### NodeFactory
|
|
6269
6362
|
|
|
@@ -6333,7 +6426,7 @@ const factory = new NodeFactory();
|
|
|
6333
6426
|
const node = factory.createNode({ value: '', component: Input }); // → FieldNode<string>
|
|
6334
6427
|
```
|
|
6335
6428
|
|
|
6336
|
-
_Source: src/
|
|
6429
|
+
_Source: src/form/factories/node-factory.ts_
|
|
6337
6430
|
|
|
6338
6431
|
### nonNegative
|
|
6339
6432
|
|
|
@@ -6369,7 +6462,7 @@ validators: [nonNegative({ message: 'Баланс не может быть от
|
|
|
6369
6462
|
},
|
|
6370
6463
|
```
|
|
6371
6464
|
|
|
6372
|
-
_Source: src/
|
|
6465
|
+
_Source: src/form/validation/validators/non-negative.ts_
|
|
6373
6466
|
|
|
6374
6467
|
### nonZero
|
|
6375
6468
|
|
|
@@ -6405,7 +6498,7 @@ validators: [nonZero({ message: 'Не может быть нулём' })],
|
|
|
6405
6498
|
},
|
|
6406
6499
|
```
|
|
6407
6500
|
|
|
6408
|
-
_Source: src/
|
|
6501
|
+
_Source: src/form/validation/validators/non-zero.ts_
|
|
6409
6502
|
|
|
6410
6503
|
### pastDate
|
|
6411
6504
|
|
|
@@ -6442,7 +6535,7 @@ validators: [required(), pastDate({ message: 'Дата рождения не м
|
|
|
6442
6535
|
},
|
|
6443
6536
|
```
|
|
6444
6537
|
|
|
6445
|
-
_Source: src/
|
|
6538
|
+
_Source: src/form/validation/validators/past-date.ts_
|
|
6446
6539
|
|
|
6447
6540
|
### PathAwareSignal
|
|
6448
6541
|
|
|
@@ -6459,7 +6552,7 @@ export type PathAwareSignal<T> = Signal<T> & {
|
|
|
6459
6552
|
};
|
|
6460
6553
|
```
|
|
6461
6554
|
|
|
6462
|
-
_Source: src/
|
|
6555
|
+
_Source: src/state/types.ts_
|
|
6463
6556
|
|
|
6464
6557
|
### pattern
|
|
6465
6558
|
|
|
@@ -6507,7 +6600,7 @@ pattern(/^\+7 \(\d{3}\) \d{3}-\d{2}-\d{2}$/, { message: 'Формат +7 (999) 1
|
|
|
6507
6600
|
},
|
|
6508
6601
|
```
|
|
6509
6602
|
|
|
6510
|
-
_Source: src/
|
|
6603
|
+
_Source: src/form/validation/validators/pattern.ts_
|
|
6511
6604
|
|
|
6512
6605
|
### phone
|
|
6513
6606
|
|
|
@@ -6545,7 +6638,7 @@ validators: [required(), phone({ format: 'ru' })],
|
|
|
6545
6638
|
},
|
|
6546
6639
|
```
|
|
6547
6640
|
|
|
6548
|
-
_Source: src/
|
|
6641
|
+
_Source: src/form/validation/validators/phone.ts_
|
|
6549
6642
|
|
|
6550
6643
|
### PhoneFormat
|
|
6551
6644
|
|
|
@@ -6563,7 +6656,7 @@ _Source: src/core/validation/validators/phone.ts_
|
|
|
6563
6656
|
export type PhoneFormat = 'international' | 'ru' | 'us' | 'any';
|
|
6564
6657
|
```
|
|
6565
6658
|
|
|
6566
|
-
_Source: src/
|
|
6659
|
+
_Source: src/form/validation/validators/phone.ts_
|
|
6567
6660
|
|
|
6568
6661
|
### registerSignalNode
|
|
6569
6662
|
|
|
@@ -6597,7 +6690,7 @@ if (sig && node) registerSignalNode(sig, node);
|
|
|
6597
6690
|
**See also:**
|
|
6598
6691
|
- {@link getNodeForSignal} - обратный поиск ноды по сигналу
|
|
6599
6692
|
|
|
6600
|
-
_Source: src/
|
|
6693
|
+
_Source: src/form/signal-node-registry.ts_
|
|
6601
6694
|
|
|
6602
6695
|
### required
|
|
6603
6696
|
|
|
@@ -6607,7 +6700,8 @@ _Source: src/core/utils/signal-node-registry.ts_
|
|
|
6607
6700
|
|
|
6608
6701
|
Возвращает чистую функцию-валидатор `(value, control, root)`. Передаётся в `validate()`.
|
|
6609
6702
|
|
|
6610
|
-
Пустыми считаются: `null`, `undefined`, `''` (пустая строка)
|
|
6703
|
+
Пустыми считаются: `null`, `undefined`, `''` (пустая строка), `[]` (пустой массив —
|
|
6704
|
+
обязательный multi-select / FormArray без выбранных элементов).
|
|
6611
6705
|
Для boolean полей требуется значение `true`.
|
|
6612
6706
|
|
|
6613
6707
|
**Signature:**
|
|
@@ -6642,7 +6736,7 @@ validators: [required({ message: 'Необходимо принять услов
|
|
|
6642
6736
|
},
|
|
6643
6737
|
```
|
|
6644
6738
|
|
|
6645
|
-
_Source: src/
|
|
6739
|
+
_Source: src/form/validation/validators/required.ts_
|
|
6646
6740
|
|
|
6647
6741
|
### resetWhen
|
|
6648
6742
|
|
|
@@ -6665,7 +6759,7 @@ export function resetWhen<T>(
|
|
|
6665
6759
|
resetWhen(model.$.cardNumber, () => model.paymentType !== 'card', { resetValue: '' });
|
|
6666
6760
|
```
|
|
6667
6761
|
|
|
6668
|
-
_Source: src/
|
|
6762
|
+
_Source: src/state/behaviors-value.ts_
|
|
6669
6763
|
|
|
6670
6764
|
### ResourceLoadResult
|
|
6671
6765
|
|
|
@@ -6678,7 +6772,7 @@ _Source: src/core/model/behaviors.ts_
|
|
|
6678
6772
|
export type ResourceLoadResult = unknown;
|
|
6679
6773
|
```
|
|
6680
6774
|
|
|
6681
|
-
_Source: src/
|
|
6775
|
+
_Source: src/form/types/index.ts_
|
|
6682
6776
|
|
|
6683
6777
|
### revalidateWhen
|
|
6684
6778
|
|
|
@@ -6701,36 +6795,41 @@ export function revalidateWhen(
|
|
|
6701
6795
|
revalidateWhen([model.$.maxAmount], () => validateFormModel(model, schema));
|
|
6702
6796
|
```
|
|
6703
6797
|
|
|
6704
|
-
_Source: src/
|
|
6798
|
+
_Source: src/state/behaviors-value.ts_
|
|
6705
6799
|
|
|
6706
6800
|
### runOutsideEffect
|
|
6707
6801
|
|
|
6708
6802
|
**Kind:** `function`
|
|
6709
6803
|
|
|
6710
|
-
Выполняет функцию вне контекста effect
|
|
6804
|
+
Выполняет функцию вне контекста effect (отложенная запись на микротаск).
|
|
6711
6805
|
|
|
6712
|
-
|
|
6806
|
+
Сбои fn (синхронный throw и async-rejection) маршрутизируются dev-логгером (logDeferError), а не
|
|
6807
|
+
всплывают неперехваченными. Возвращает отменитель: вызов до срабатывания микротаска отменяет запись
|
|
6808
|
+
(liveness-охрана — не писать против снесённого узла при dispose в том же тике).
|
|
6713
6809
|
|
|
6714
6810
|
**Signature:**
|
|
6715
6811
|
```typescript
|
|
6716
|
-
export function runOutsideEffect(fn: () => void | Promise<void>): void
|
|
6812
|
+
export function runOutsideEffect(fn: () => void | Promise<void>): () => void
|
|
6717
6813
|
```
|
|
6718
6814
|
|
|
6719
6815
|
**Parameters:**
|
|
6720
6816
|
- `fn` — - Функция для выполнения
|
|
6721
6817
|
|
|
6818
|
+
**Returns:** Отменитель ещё не выполненной записи (no-op, если запись уже выполнена)
|
|
6819
|
+
|
|
6722
6820
|
**Examples:**
|
|
6723
6821
|
|
|
6724
6822
|
```typescript
|
|
6725
6823
|
effect(() => {
|
|
6726
6824
|
const value = signal.value;
|
|
6727
|
-
runOutsideEffect(() => {
|
|
6825
|
+
const cancel = runOutsideEffect(() => {
|
|
6728
6826
|
otherSignal.value = transform(value);
|
|
6729
6827
|
});
|
|
6828
|
+
onDispose(cancel); // отменить ожидающую запись, если узел снесут в этом же тике
|
|
6730
6829
|
});
|
|
6731
6830
|
```
|
|
6732
6831
|
|
|
6733
|
-
_Source: src/
|
|
6832
|
+
_Source: src/state/safe-effect.ts_
|
|
6734
6833
|
|
|
6735
6834
|
### safeCallback
|
|
6736
6835
|
|
|
@@ -6738,8 +6837,8 @@ _Source: src/core/utils/safe-effect.ts_
|
|
|
6738
6837
|
|
|
6739
6838
|
Создает callback, который выполняется вне контекста effect
|
|
6740
6839
|
|
|
6741
|
-
|
|
6742
|
-
|
|
6840
|
+
Откладывает вызов через {@link runOutsideEffect} — то есть получает маршрутизацию ошибок и
|
|
6841
|
+
обработку async-rejection «бесплатно».
|
|
6743
6842
|
|
|
6744
6843
|
**Signature:**
|
|
6745
6844
|
```typescript
|
|
@@ -6769,7 +6868,7 @@ effect(() => {
|
|
|
6769
6868
|
});
|
|
6770
6869
|
```
|
|
6771
6870
|
|
|
6772
|
-
_Source: src/
|
|
6871
|
+
_Source: src/state/safe-effect.ts_
|
|
6773
6872
|
|
|
6774
6873
|
### safeDebouncedCallback
|
|
6775
6874
|
|
|
@@ -6777,7 +6876,9 @@ _Source: src/core/utils/safe-effect.ts_
|
|
|
6777
6876
|
|
|
6778
6877
|
Создает версию callback с поддержкой debounce, безопасную для effect
|
|
6779
6878
|
|
|
6780
|
-
|
|
6879
|
+
`withDebounce` уже откладывает вызов (таймер) — этого достаточно для выхода из effect-контекста,
|
|
6880
|
+
поэтому дополнительного `queueMicrotask` нет (устранён двойной defer). Сбои callback (в т.ч.
|
|
6881
|
+
async-rejection) маршрутизируются dev-логгером (logDeferError).
|
|
6781
6882
|
|
|
6782
6883
|
**Signature:**
|
|
6783
6884
|
```typescript
|
|
@@ -6805,7 +6906,7 @@ return effect(() => {
|
|
|
6805
6906
|
});
|
|
6806
6907
|
```
|
|
6807
6908
|
|
|
6808
|
-
_Source: src/
|
|
6909
|
+
_Source: src/state/safe-effect.ts_
|
|
6809
6910
|
|
|
6810
6911
|
### SchemaArrayControl
|
|
6811
6912
|
|
|
@@ -6828,7 +6929,7 @@ export interface SchemaArrayControl {
|
|
|
6828
6929
|
}
|
|
6829
6930
|
```
|
|
6830
6931
|
|
|
6831
|
-
_Source: src/
|
|
6932
|
+
_Source: src/form/types/schema-node.ts_
|
|
6832
6933
|
|
|
6833
6934
|
### SchemaValidator
|
|
6834
6935
|
|
|
@@ -6847,7 +6948,7 @@ export type SchemaValidator = (
|
|
|
6847
6948
|
) => ValidationError | null | Promise<ValidationError | null>;
|
|
6848
6949
|
```
|
|
6849
6950
|
|
|
6850
|
-
_Source: src/
|
|
6951
|
+
_Source: src/form/types/schema-node.ts_
|
|
6851
6952
|
|
|
6852
6953
|
### SetValueOptions
|
|
6853
6954
|
|
|
@@ -6865,7 +6966,7 @@ export interface SetValueOptions {
|
|
|
6865
6966
|
}
|
|
6866
6967
|
```
|
|
6867
6968
|
|
|
6868
|
-
_Source: src/
|
|
6969
|
+
_Source: src/form/nodes/form-node.ts_
|
|
6869
6970
|
|
|
6870
6971
|
### StatusEvent
|
|
6871
6972
|
|
|
@@ -6884,7 +6985,7 @@ export type StatusEvent =
|
|
|
6884
6985
|
| { type: 'SET_ERRORS'; hasErrors: boolean };
|
|
6885
6986
|
```
|
|
6886
6987
|
|
|
6887
|
-
_Source: src/
|
|
6988
|
+
_Source: src/form/status-machine.ts_
|
|
6888
6989
|
|
|
6889
6990
|
### SubmitOptions
|
|
6890
6991
|
|
|
@@ -6902,7 +7003,7 @@ export interface SubmitOptions {
|
|
|
6902
7003
|
}
|
|
6903
7004
|
```
|
|
6904
7005
|
|
|
6905
|
-
_Source: src/
|
|
7006
|
+
_Source: src/form/form-submitter.ts_
|
|
6906
7007
|
|
|
6907
7008
|
### SubmitResult
|
|
6908
7009
|
|
|
@@ -6922,7 +7023,7 @@ export interface SubmitResult<R> {
|
|
|
6922
7023
|
}
|
|
6923
7024
|
```
|
|
6924
7025
|
|
|
6925
|
-
_Source: src/
|
|
7026
|
+
_Source: src/form/form-submitter.ts_
|
|
6926
7027
|
|
|
6927
7028
|
### SubmittableForm
|
|
6928
7029
|
|
|
@@ -6943,7 +7044,7 @@ export interface SubmittableForm<T extends object> {
|
|
|
6943
7044
|
}
|
|
6944
7045
|
```
|
|
6945
7046
|
|
|
6946
|
-
_Source: src/
|
|
7047
|
+
_Source: src/form/form-submitter.ts_
|
|
6947
7048
|
|
|
6948
7049
|
### SubscriptionManager
|
|
6949
7050
|
|
|
@@ -6986,7 +7087,7 @@ class FieldNode {
|
|
|
6986
7087
|
}
|
|
6987
7088
|
```
|
|
6988
7089
|
|
|
6989
|
-
_Source: src/
|
|
7090
|
+
_Source: src/state/subscription-manager.ts_
|
|
6990
7091
|
|
|
6991
7092
|
### syncFields
|
|
6992
7093
|
|
|
@@ -7010,7 +7111,7 @@ export function syncFields<T>(
|
|
|
7010
7111
|
syncFields(model.$.field1, model.$.field2);
|
|
7011
7112
|
```
|
|
7012
7113
|
|
|
7013
|
-
_Source: src/
|
|
7114
|
+
_Source: src/state/behaviors-value.ts_
|
|
7014
7115
|
|
|
7015
7116
|
### transformValue
|
|
7016
7117
|
|
|
@@ -7033,7 +7134,7 @@ export function transformValue<T>(
|
|
|
7033
7134
|
transformValue(model.$.promoCode, (v) => (v ?? '').toUpperCase());
|
|
7034
7135
|
```
|
|
7035
7136
|
|
|
7036
|
-
_Source: src/
|
|
7137
|
+
_Source: src/state/behaviors-value.ts_
|
|
7037
7138
|
|
|
7038
7139
|
### uniqueId
|
|
7039
7140
|
|
|
@@ -7060,7 +7161,7 @@ uniqueId(SubscriptionKey.WatchField); // → 'watchField-1'
|
|
|
7060
7161
|
uniqueId(SubscriptionKey.WatchField); // → 'watchField-2'
|
|
7061
7162
|
```
|
|
7062
7163
|
|
|
7063
|
-
_Source: src/
|
|
7164
|
+
_Source: src/form/unique-id.ts_
|
|
7064
7165
|
|
|
7065
7166
|
### UnknownCallback
|
|
7066
7167
|
|
|
@@ -7074,7 +7175,7 @@ _Source: src/core/utils/unique-id.ts_
|
|
|
7074
7175
|
export type UnknownCallback = (...args: unknown[]) => unknown;
|
|
7075
7176
|
```
|
|
7076
7177
|
|
|
7077
|
-
_Source: src/
|
|
7178
|
+
_Source: src/form/types/index.ts_
|
|
7078
7179
|
|
|
7079
7180
|
### UnknownFormValue
|
|
7080
7181
|
|
|
@@ -7088,7 +7189,7 @@ Requires explicit type checking before use
|
|
|
7088
7189
|
export type UnknownFormValue = unknown;
|
|
7089
7190
|
```
|
|
7090
7191
|
|
|
7091
|
-
_Source: src/
|
|
7192
|
+
_Source: src/form/types/contracts.ts_
|
|
7092
7193
|
|
|
7093
7194
|
### UnknownRecord
|
|
7094
7195
|
|
|
@@ -7102,7 +7203,43 @@ _Source: src/core/types/index.ts_
|
|
|
7102
7203
|
export type UnknownRecord = Record<string, unknown>;
|
|
7103
7204
|
```
|
|
7104
7205
|
|
|
7105
|
-
_Source: src/
|
|
7206
|
+
_Source: src/form/types/index.ts_
|
|
7207
|
+
|
|
7208
|
+
### unmarkDerived
|
|
7209
|
+
|
|
7210
|
+
**Kind:** `function`
|
|
7211
|
+
|
|
7212
|
+
Снять пометку производного сигнала (обратная операция к {@link markDerived}).
|
|
7213
|
+
|
|
7214
|
+
Вызывается из очистки (`onDispose`) оператора `compute`/`computeFrom`, когда поведение снимается,
|
|
7215
|
+
но модель/сигнал продолжают жить (динамическая перекоммутация: удалить под-схему → сохранить модель
|
|
7216
|
+
→ bulk-set). Без этого сигнал остаётся помеченным навсегда, и bulk-сеттеры навсегда пропускают
|
|
7217
|
+
поле, которое больше ничем не вычисляется.
|
|
7218
|
+
|
|
7219
|
+
Учитывает счётчик ссылок: пометка снимается только когда снят последний владелец. Вызов на
|
|
7220
|
+
непомеченном сигнале — безопасный no-op.
|
|
7221
|
+
|
|
7222
|
+
**Signature:**
|
|
7223
|
+
```typescript
|
|
7224
|
+
export function unmarkDerived(signal: Signal<any>): void
|
|
7225
|
+
```
|
|
7226
|
+
|
|
7227
|
+
**Parameters:**
|
|
7228
|
+
- `signal` — - Сигнал значения из {@link FormModel}, ранее помеченный {@link markDerived}
|
|
7229
|
+
|
|
7230
|
+
**Examples:**
|
|
7231
|
+
|
|
7232
|
+
```typescript
|
|
7233
|
+
import { markDerived, unmarkDerived } from '@reformer/core';
|
|
7234
|
+
|
|
7235
|
+
markDerived(model.$.total);
|
|
7236
|
+
onDispose(() => unmarkDerived(model.$.total)); // при снятии compute снова разрешаем bulk-set
|
|
7237
|
+
```
|
|
7238
|
+
|
|
7239
|
+
**See also:**
|
|
7240
|
+
- {@link markDerived} - пометить сигнал производным
|
|
7241
|
+
|
|
7242
|
+
_Source: src/state/derived-registry.ts_
|
|
7106
7243
|
|
|
7107
7244
|
### url
|
|
7108
7245
|
|
|
@@ -7146,7 +7283,7 @@ validators: [url({ requireProtocol: true, allowedProtocols: ['https'] })],
|
|
|
7146
7283
|
},
|
|
7147
7284
|
```
|
|
7148
7285
|
|
|
7149
|
-
_Source: src/
|
|
7286
|
+
_Source: src/form/validation/validators/url.ts_
|
|
7150
7287
|
|
|
7151
7288
|
### useArrayLength
|
|
7152
7289
|
|
|
@@ -7184,7 +7321,7 @@ function ArrayRenderer({ arrayNode }) {
|
|
|
7184
7321
|
}
|
|
7185
7322
|
```
|
|
7186
7323
|
|
|
7187
|
-
_Source: src/hooks/useArrayLength.ts_
|
|
7324
|
+
_Source: src/form/hooks/useArrayLength.ts_
|
|
7188
7325
|
|
|
7189
7326
|
### useFormControl
|
|
7190
7327
|
|
|
@@ -7418,7 +7555,7 @@ return <div>Items: {length}</div>;
|
|
|
7418
7555
|
- {@link FieldControlState} - тип состояния для FieldNode
|
|
7419
7556
|
- {@link ArrayControlState} - тип состояния для ArrayNode
|
|
7420
7557
|
|
|
7421
|
-
_Source: src/hooks/useFormControl.ts_
|
|
7558
|
+
_Source: src/form/hooks/useFormControl.ts_
|
|
7422
7559
|
|
|
7423
7560
|
### useFormControlValue
|
|
7424
7561
|
|
|
@@ -7599,23 +7736,25 @@ return (
|
|
|
7599
7736
|
- {@link useFormControl} - для полного состояния поля
|
|
7600
7737
|
- {@link FieldNode} - тип контрола поля
|
|
7601
7738
|
|
|
7602
|
-
_Source: src/hooks/useFormControlValue.ts_
|
|
7739
|
+
_Source: src/form/hooks/useFormControlValue.ts_
|
|
7603
7740
|
|
|
7604
7741
|
### ValidateAsyncOptions
|
|
7605
7742
|
|
|
7606
7743
|
**Kind:** `interface`
|
|
7607
7744
|
|
|
7608
|
-
Опции для функции validateAsync.
|
|
7609
|
-
|
|
7610
7745
|
**Signature:**
|
|
7611
7746
|
```typescript
|
|
7612
7747
|
export interface ValidateAsyncOptions extends ValidateOptions {
|
|
7613
|
-
/** Задержка перед выполнением валидации (в мс) */
|
|
7748
|
+
/** Задержка перед выполнением валидации (в мс). */
|
|
7614
7749
|
debounce?: number;
|
|
7615
7750
|
}
|
|
7616
7751
|
```
|
|
7617
7752
|
|
|
7618
|
-
|
|
7753
|
+
**Deprecated:** Осиротевший остаток удалённого оператора `validateAsync` (Ф7): опция `debounce`
|
|
7754
|
+
подключалась тем оператором, которого больше нет. Рантаймом не потребляется; экспортируется
|
|
7755
|
+
только ради обратной совместимости.
|
|
7756
|
+
|
|
7757
|
+
_Source: src/form/types/validation-schema.ts_
|
|
7619
7758
|
|
|
7620
7759
|
### validateFormModel
|
|
7621
7760
|
|
|
@@ -7649,7 +7788,7 @@ const res = await validateFormModel(model, schema);
|
|
|
7649
7788
|
if (res.valid) await api.save(model.get());
|
|
7650
7789
|
```
|
|
7651
7790
|
|
|
7652
|
-
_Source: src/
|
|
7791
|
+
_Source: src/form/validate-model.ts_
|
|
7653
7792
|
|
|
7654
7793
|
### validateModel
|
|
7655
7794
|
|
|
@@ -7672,7 +7811,7 @@ const res = await validateModel(model, schema);
|
|
|
7672
7811
|
if (!res.valid) console.log(res.errors); // { 'email': [{ code, message }], ... }
|
|
7673
7812
|
```
|
|
7674
7813
|
|
|
7675
|
-
_Source: src/
|
|
7814
|
+
_Source: src/form/validate-model-core.ts_
|
|
7676
7815
|
|
|
7677
7816
|
### validateModelSync
|
|
7678
7817
|
|
|
@@ -7703,25 +7842,27 @@ const res = validateModelSync(model, schema);
|
|
|
7703
7842
|
if (!res.valid) console.log(res.errors); // { 'email': [{ code, message }], ... }
|
|
7704
7843
|
```
|
|
7705
7844
|
|
|
7706
|
-
_Source: src/
|
|
7845
|
+
_Source: src/form/validate-model-core.ts_
|
|
7707
7846
|
|
|
7708
7847
|
### ValidateOptions
|
|
7709
7848
|
|
|
7710
7849
|
**Kind:** `interface`
|
|
7711
7850
|
|
|
7712
|
-
Опции
|
|
7851
|
+
Опции валидатора-фабрики (`required()`/`pattern()`/…). Передаются вторым (или последним)
|
|
7852
|
+
аргументом в фабрику и попадают в возвращаемую {@link ValidationError}.
|
|
7713
7853
|
|
|
7714
7854
|
**Signature:**
|
|
7715
7855
|
```typescript
|
|
7716
7856
|
export interface ValidateOptions {
|
|
7717
|
-
/**
|
|
7857
|
+
/** Готовое сообщение об ошибке. Если не задано, валидаторы кладут `''`, и отображаемый текст
|
|
7858
|
+
* резолвится из `code` (см. резолвер сообщений в `@reformer/cdk`). */
|
|
7718
7859
|
message?: string;
|
|
7719
|
-
/** Параметры ошибки */
|
|
7860
|
+
/** Параметры ошибки (подстановка в шаблон сообщения / i18n). */
|
|
7720
7861
|
params?: Record<string, FormValue>;
|
|
7721
7862
|
}
|
|
7722
7863
|
```
|
|
7723
7864
|
|
|
7724
|
-
_Source: src/
|
|
7865
|
+
_Source: src/form/types/validation-schema.ts_
|
|
7725
7866
|
|
|
7726
7867
|
### ValidationError
|
|
7727
7868
|
|
|
@@ -7740,7 +7881,7 @@ export interface ValidationError {
|
|
|
7740
7881
|
}
|
|
7741
7882
|
```
|
|
7742
7883
|
|
|
7743
|
-
_Source: src/
|
|
7884
|
+
_Source: src/form/types/contracts.ts_
|
|
7744
7885
|
|
|
7745
7886
|
### Validator
|
|
7746
7887
|
|
|
@@ -7788,7 +7929,7 @@ children: [
|
|
|
7788
7929
|
};
|
|
7789
7930
|
```
|
|
7790
7931
|
|
|
7791
|
-
_Source: src/
|
|
7932
|
+
_Source: src/form/types/validation-schema.ts_
|
|
7792
7933
|
|
|
7793
7934
|
### ValidatorFn
|
|
7794
7935
|
|
|
@@ -7801,7 +7942,7 @@ _Source: src/core/types/validation-schema.ts_
|
|
|
7801
7942
|
export type ValidatorFn<T = FormValue> = (value: T) => ValidationError | null;
|
|
7802
7943
|
```
|
|
7803
7944
|
|
|
7804
|
-
_Source: src/
|
|
7945
|
+
_Source: src/form/types/contracts.ts_
|
|
7805
7946
|
|
|
7806
7947
|
### watchField
|
|
7807
7948
|
|
|
@@ -7828,7 +7969,7 @@ watchField(model.$.country, async (country) => {
|
|
|
7828
7969
|
});
|
|
7829
7970
|
```
|
|
7830
7971
|
|
|
7831
|
-
_Source: src/
|
|
7972
|
+
_Source: src/state/behaviors-value.ts_
|
|
7832
7973
|
|
|
7833
7974
|
### WithBehaviorSchema
|
|
7834
7975
|
|
|
@@ -7843,7 +7984,7 @@ export interface WithBehaviorSchema {
|
|
|
7843
7984
|
}
|
|
7844
7985
|
```
|
|
7845
7986
|
|
|
7846
|
-
_Source: src/
|
|
7987
|
+
_Source: src/form/types/index.ts_
|
|
7847
7988
|
|
|
7848
7989
|
### WithValidationSchema
|
|
7849
7990
|
|
|
@@ -7858,4 +7999,4 @@ export interface WithValidationSchema {
|
|
|
7858
7999
|
}
|
|
7859
8000
|
```
|
|
7860
8001
|
|
|
7861
|
-
_Source: src/
|
|
8002
|
+
_Source: src/form/types/index.ts_
|