@reformer/core 11.0.0-beta.7 → 11.0.0-beta.9
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 +90 -68
- package/dist/behaviors-value-HA_Q03hc.js +108 -0
- package/dist/behaviors.js +382 -217
- package/dist/create-model-BvcbNPgL.js +30 -0
- package/dist/date-utils-90-qZbse.js +43 -0
- package/dist/{en-CjAqn7h0.js → en-HP8XEych.js} +6 -3
- package/dist/form/aggregate-signals.d.ts +21 -63
- package/dist/form/behaviors/collections.d.ts +42 -8
- package/dist/form/behaviors/context.d.ts +37 -4
- package/dist/form/behaviors/index.d.ts +6 -4
- package/dist/form/behaviors/internals.d.ts +9 -3
- package/dist/form/behaviors/node.d.ts +25 -2
- package/dist/form/behaviors/operators.d.ts +17 -9
- package/dist/form/behaviors/schema-operators.d.ts +78 -0
- package/dist/form/behaviors/types.d.ts +25 -5
- package/dist/form/create-form.d.ts +57 -70
- package/dist/form/flow/flow.d.ts +87 -0
- package/dist/form/form-bundle.d.ts +153 -0
- package/dist/form/form-config-base.d.ts +46 -0
- package/dist/form/form-level.d.ts +121 -0
- package/dist/form/form-proxy-builder.d.ts +6 -22
- package/dist/form/index.d.ts +20 -20
- package/dist/form/nodes/form-array-node.d.ts +100 -0
- package/dist/form/nodes/form-control-node.d.ts +73 -0
- package/dist/form/nodes/form-group-node.d.ts +66 -0
- package/dist/form/nodes/node-kind.d.ts +29 -0
- package/dist/form/nodes/state/availability.d.ts +6 -0
- package/dist/form/nodes/state/component.d.ts +6 -0
- package/dist/form/nodes/state/index.d.ts +12 -0
- package/dist/form/nodes/state/interaction.d.ts +13 -0
- package/dist/form/nodes/state/issues.d.ts +9 -0
- package/dist/form/nodes/state/pending.d.ts +6 -0
- package/dist/form/schema/compile.d.ts +59 -0
- package/dist/form/schema/compiled.d.ts +143 -0
- package/dist/form/schema/row-key.d.ts +11 -0
- package/dist/form/schema-controller.d.ts +153 -0
- package/dist/form/schema-subtree.d.ts +28 -0
- package/dist/form/signal-node-registry.d.ts +27 -22
- package/dist/form/submission.d.ts +93 -0
- package/dist/form/type-guards.d.ts +14 -73
- package/dist/form/types/contracts.d.ts +19 -92
- package/dist/form/types/field-config.d.ts +27 -0
- package/dist/form/types/index.d.ts +5 -57
- package/dist/form/types/nodes.d.ts +159 -0
- package/dist/form/types/schema-node.d.ts +147 -46
- package/dist/form/types/validation-schema.d.ts +23 -27
- package/dist/form/validation/context.d.ts +46 -6
- package/dist/form/validation/index.d.ts +9 -8
- package/dist/form/validation/operators.d.ts +71 -17
- package/dist/form/validation/run.d.ts +93 -18
- package/dist/form/validation/strategy.d.ts +41 -13
- package/dist/form/validation/types.d.ts +74 -19
- package/dist/form/validators/date-utils.d.ts +13 -1
- package/dist/form/validators/email.d.ts +8 -7
- package/dist/form/validators/file-type.d.ts +8 -7
- package/dist/form/validators/file-utils.d.ts +2 -1
- package/dist/form/validators/future-date.d.ts +8 -7
- package/dist/form/validators/index.d.ts +1 -1
- package/dist/form/validators/integer.d.ts +8 -7
- package/dist/form/validators/is-date.d.ts +11 -9
- package/dist/form/validators/is-number.d.ts +11 -9
- package/dist/form/validators/max-age.d.ts +13 -9
- package/dist/form/validators/max-date.d.ts +8 -7
- package/dist/form/validators/max-file-size.d.ts +8 -7
- package/dist/form/validators/max-files.d.ts +8 -7
- package/dist/form/validators/max-length.d.ts +14 -7
- package/dist/form/validators/max-total-file-size.d.ts +8 -7
- package/dist/form/validators/max.d.ts +10 -8
- package/dist/form/validators/min-age.d.ts +12 -9
- package/dist/form/validators/min-date.d.ts +8 -7
- package/dist/form/validators/min-file-size.d.ts +8 -7
- package/dist/form/validators/min-files.d.ts +11 -9
- package/dist/form/validators/min-length.d.ts +14 -7
- package/dist/form/validators/min.d.ts +10 -8
- package/dist/form/validators/multiple-of.d.ts +10 -8
- package/dist/form/validators/non-negative.d.ts +8 -7
- package/dist/form/validators/non-zero.d.ts +8 -7
- package/dist/form/validators/past-date.d.ts +8 -7
- package/dist/form/validators/pattern.d.ts +9 -8
- package/dist/form/validators/phone.d.ts +8 -7
- package/dist/form/validators/required.d.ts +11 -9
- package/dist/form/validators/url.d.ts +20 -13
- package/dist/form/validators/validation-issue.d.ts +8 -0
- package/dist/i18n/descriptor.d.ts +1 -1
- package/dist/i18n/en.json.d.ts +5 -1
- package/dist/i18n/locale-store.d.ts +7 -0
- package/dist/i18n/message-format.d.ts +24 -4
- package/dist/i18n/ru.json.d.ts +5 -1
- package/dist/i18n/translator.d.ts +11 -0
- package/dist/i18n/validation-message.d.ts +42 -7
- package/dist/i18n.d.ts +7 -12
- package/dist/i18n.js +66 -283
- package/dist/index.d.ts +16 -7
- package/dist/index.js +958 -2798
- package/dist/loader-BWkigpVe.js +52 -0
- package/dist/locale/en.js +1 -1
- package/dist/locale/en.json +4 -1
- package/dist/locale/ru.js +4 -1
- package/dist/locale/ru.json +4 -1
- package/dist/locale-CG54AU2Q.js +219 -0
- package/dist/locale.js +1 -1
- package/dist/model/behaviors-value.d.ts +24 -6
- package/dist/model/create-model.d.ts +2 -2
- package/dist/model/derived-registry.d.ts +1 -1
- package/dist/model/index.d.ts +16 -5
- package/dist/model/model-nodes.d.ts +138 -8
- package/dist/model/model-signals-proxy.d.ts +11 -5
- package/dist/model/model-value-proxy.d.ts +84 -3
- package/dist/model/safe-effect.d.ts +33 -1
- package/dist/model/types.d.ts +70 -17
- package/dist/model.js +21 -17
- package/dist/node-kind-C-r6ZMdo.js +15 -0
- package/dist/platforms/react/field-binding/field-adapter.d.ts +1 -1
- package/dist/platforms/react/field-binding/field-handle.d.ts +5 -2
- package/dist/platforms/react/form-bundle-context.d.ts +27 -0
- package/dist/platforms/react/hooks/types.d.ts +57 -38
- package/dist/platforms/react/hooks/use-form-bundle.d.ts +19 -4
- package/dist/platforms/react/hooks/use-form-flow.d.ts +40 -0
- package/dist/platforms/react/hooks/use-form-validation.d.ts +12 -6
- package/dist/platforms/react/hooks/useArrayLength.d.ts +6 -6
- package/dist/platforms/react/hooks/useFormControl.d.ts +7 -9
- package/dist/platforms/react/hooks/useFormControlValue.d.ts +18 -19
- package/dist/platforms/react/hooks/useSignalSubscription.d.ts +9 -1
- package/dist/platforms/react/i18n/context.d.ts +6 -1
- package/dist/platforms/react/i18n/hooks.d.ts +16 -10
- package/dist/platforms/react/i18n/provider.d.ts +9 -2
- package/dist/platforms/react/index.d.ts +7 -4
- package/dist/react.d.ts +22 -0
- package/dist/react.js +505 -0
- package/dist/runtime-token.d.ts +1 -2
- package/dist/safe-effect-BbtX3KuN.js +643 -0
- package/dist/schema-controller-CpiO2JoK.js +143 -0
- package/dist/signals.d.ts +15 -9
- package/dist/signals.js +11 -6
- package/dist/strategy-CoFSemuP.js +375 -0
- package/dist/type-guards-D-N_5Ddh.js +19 -0
- package/dist/validation-issue-B9mjI8jz.js +7 -0
- package/dist/validation-message-Ced9MGxs.js +194 -0
- package/dist/validation.js +9 -8
- package/dist/validators/email.js +5 -5
- package/dist/validators/future-date.js +8 -8
- package/dist/validators/integer.js +3 -3
- package/dist/validators/is-date.js +4 -4
- package/dist/validators/is-number.js +4 -4
- package/dist/validators/max-age.js +8 -9
- package/dist/validators/max-date.js +8 -8
- package/dist/validators/max-length.js +7 -7
- package/dist/validators/max.js +4 -4
- package/dist/validators/min-age.js +10 -8
- package/dist/validators/min-date.js +3 -3
- package/dist/validators/min-length.js +5 -5
- package/dist/validators/min.js +4 -4
- package/dist/validators/multiple-of.js +11 -7
- package/dist/validators/non-negative.js +3 -3
- package/dist/validators/non-zero.js +3 -3
- package/dist/validators/past-date.js +8 -8
- package/dist/validators/pattern.js +5 -5
- package/dist/validators/phone.js +11 -9
- package/dist/validators/required.js +2 -2
- package/dist/validators/url.js +48 -12
- package/dist/validators.js +17 -17
- package/docs/llms/01-api-reference.md +60 -34
- package/docs/llms/02-quick-start.md +111 -80
- package/docs/llms/03-api-signatures.md +368 -153
- package/docs/llms/04-common-patterns.md +58 -56
- package/docs/llms/05-common-mistakes.md +69 -44
- package/docs/llms/06-troubleshooting.md +14 -9
- package/docs/llms/07-complete-import.md +74 -43
- package/docs/llms/08-form-types.md +11 -4
- package/docs/llms/09-formschema.md +131 -83
- package/docs/llms/10-arrays.md +119 -69
- package/docs/llms/11-async-watchfield.md +2 -2
- package/docs/llms/13-multi-step.md +134 -63
- package/docs/llms/14-extended-mistakes.md +20 -17
- package/docs/llms/15-project-structure.md +221 -74
- package/docs/llms/16-ui-components.md +55 -42
- package/docs/llms/17-nonexistent-api.md +199 -32
- package/docs/llms/18-conditional-fields.md +66 -32
- package/docs/llms/19-reading-values.md +15 -3
- package/docs/llms/20-compute-vs-watch.md +16 -10
- package/docs/llms/21-array-operations.md +76 -26
- package/docs/llms/22-cycle-detection.md +1 -1
- package/docs/llms/23-copy-from.md +2 -2
- package/docs/llms/24-sync-fields.md +6 -5
- package/docs/llms/25-reset-when.md +14 -7
- package/docs/llms/26-transform-value.md +4 -4
- package/docs/llms/27-revalidate-when.md +16 -15
- package/docs/llms/28-submit-and-reset.md +276 -128
- package/docs/llms/29-async-preload.md +40 -30
- package/docs/llms/30-type-safety-recipes.md +105 -51
- package/docs/llms/31-async-validator-debounce.md +96 -53
- package/docs/llms/33-validation-strategy.md +178 -66
- package/docs/llms/34-i18n.md +69 -43
- package/docs/llms/35-unified-contract.md +307 -0
- package/docs/llms/36-issue-messages.md +284 -0
- package/docs/llms/37-compiled-schema.md +332 -0
- package/docs/llms/38-form-flow.md +397 -0
- package/llms-index.json +1 -1
- package/llms.txt +6968 -3278
- package/package.json +23 -4
- package/dist/behaviors-value-C7dSEhCc.js +0 -134
- package/dist/create-model-B8U-COv-.js +0 -103
- package/dist/date-utils-dTT_x_Be.js +0 -31
- package/dist/form/create-core-form.d.ts +0 -70
- package/dist/form/factories/index.d.ts +0 -6
- package/dist/form/factories/node-factory.d.ts +0 -189
- package/dist/form/form-submitter.d.ts +0 -121
- package/dist/form/nodes/array-node.d.ts +0 -276
- package/dist/form/nodes/field-node.d.ts +0 -297
- package/dist/form/nodes/form-node.d.ts +0 -326
- package/dist/form/nodes/group-node.d.ts +0 -284
- package/dist/form/nodes/model-array-node.d.ts +0 -121
- package/dist/form/nodes/subscription-manager.d.ts +0 -180
- package/dist/form/status-machine.d.ts +0 -115
- package/dist/form/types/deep-schema.d.ts +0 -107
- package/dist/form/types/form-proxy.d.ts +0 -141
- package/dist/form/unique-id.d.ts +0 -45
- package/dist/form/validation/config.d.ts +0 -73
- package/dist/form/validation/error-handler.d.ts +0 -166
- package/dist/form/validators/validation-error.d.ts +0 -8
- package/dist/index-BrNkQj1y.js +0 -105
- package/dist/loader-Dv_Hl7JC.js +0 -216
- package/dist/model-signals-proxy-2vqS243J.js +0 -250
- package/dist/node-DGEFMTQu.js +0 -18
- package/dist/strategy-BXS_gBfz.js +0 -170
- package/dist/validation-error-B-U3RsV0.js +0 -11
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CompiledSchema } from './schema/compiled';
|
|
2
|
+
import { FormGroup } from './types/index';
|
|
2
3
|
import { FormSchemaNode } from './types/schema-node';
|
|
3
4
|
import { FormModel } from '../model/types';
|
|
4
5
|
import { FormBehavior } from './behaviors';
|
|
6
|
+
import { SchemaController } from './schema-controller';
|
|
7
|
+
import { FormFlow } from './flow/flow';
|
|
5
8
|
/**
|
|
6
|
-
* Аргументы
|
|
9
|
+
* Аргументы сборки формы из модели: данные приходят из {@link FormModel},
|
|
7
10
|
* конфиг полей (component/componentProps) — из единой схемы.
|
|
8
11
|
*
|
|
9
12
|
* @group Utilities
|
|
@@ -12,33 +15,43 @@ export interface CreateFormFromModelArgs<T> {
|
|
|
12
15
|
/** Реактивная модель данных (источник истины значений). */
|
|
13
16
|
model: FormModel<T>;
|
|
14
17
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
18
|
+
* Схема — дерево узлов {@link FormSchemaNode}. Сборка обходит её и привязывает конфиг поля к
|
|
19
|
+
* ноде по идентичности ручки (`node.model === model.$.<path>`). Опциональна.
|
|
17
20
|
*/
|
|
18
21
|
schema?: FormSchemaNode;
|
|
19
22
|
/**
|
|
20
23
|
* Декларативная схема поведения ({@link defineFormBehavior}). Запускается ПОСЛЕ построения нод и
|
|
21
|
-
* заполнения реестра сигнал→нода; cleanup живёт на форме и
|
|
24
|
+
* заполнения реестра сигнал→нода; cleanup живёт на форме и снимается вместе с ней.
|
|
22
25
|
*/
|
|
23
26
|
behavior?: FormBehavior<T>;
|
|
27
|
+
/**
|
|
28
|
+
* Схема-контроллер сборки: через него поведение получает `schema` своей области. Его передаёт
|
|
29
|
+
* сборка одним вызовом, чтобы правила узлов (`hideWhen`, `onComponentEvent`) дошли до рендерера.
|
|
30
|
+
* Без него поведение пишет правила в собственный контроллер, который никто не читает.
|
|
31
|
+
*/
|
|
32
|
+
schemaController?: SchemaController;
|
|
33
|
+
/** Поток шагов сборки: его получает поведение (`defineFormBehavior(({ flow }) => …)`). */
|
|
34
|
+
flow?: FormFlow;
|
|
24
35
|
}
|
|
25
36
|
/**
|
|
26
|
-
* Собрать форму из {@link FormModel} и единой схемы (низкоуровневая фабрика
|
|
37
|
+
* Собрать форму из {@link FormModel} и единой схемы (низкоуровневая фабрика).
|
|
27
38
|
*
|
|
28
39
|
* Значения принадлежат модели (источник истины), ноды формы держат UI/валидационное состояние и
|
|
29
|
-
* ссылаются на сигналы модели по
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* роутинга ошибок) и, при наличии, запускает декларативное
|
|
40
|
+
* ссылаются на сигналы модели по идентичности. Обходит структуру модели и строит ноды по виду её
|
|
41
|
+
* узлов, привязывает конфиг поля (component/componentProps) из схемы, материализует массивы
|
|
42
|
+
* под-форм ({@link FormArray}, на любой глубине), заполняет реестр ручка→нода (для
|
|
43
|
+
* `enableWhen`, `apply`/`applyEach` и роутинга ошибок) и, при наличии, запускает декларативное
|
|
44
|
+
* поведение (cleanup живёт на форме).
|
|
33
45
|
*
|
|
34
|
-
* Обычно вызывается
|
|
35
|
-
* нужен
|
|
46
|
+
* Обычно вызывается сборкой одним вызовом (`createForm`): она строит дерево схемы, зовёт эту
|
|
47
|
+
* фабрику и собирает валидацию. Прямой вызов нужен там, где бандл не нужен, — форма элемента
|
|
48
|
+
* массива, тесты, свой слой сборки.
|
|
36
49
|
*
|
|
37
50
|
* @typeParam T - Тип модели данных формы
|
|
38
51
|
* @param args - Модель, единая схема и (опционально) декларативное поведение {@link CreateFormFromModelArgs}
|
|
39
|
-
* @returns
|
|
52
|
+
* @returns Группа формы {@link FormGroup} с нодами полей по именам
|
|
40
53
|
*
|
|
41
|
-
* @example Форма из модели
|
|
54
|
+
* @example Форма из модели и схемы
|
|
42
55
|
* ```typescript
|
|
43
56
|
* import { createModel, createFormFromModel } from '@reformer/core';
|
|
44
57
|
*
|
|
@@ -51,10 +64,10 @@ export interface CreateFormFromModelArgs<T> {
|
|
|
51
64
|
* const schema = {
|
|
52
65
|
* component: Section,
|
|
53
66
|
* children: [
|
|
54
|
-
* // Layout несёт только component/componentProps; правила — в отдельной
|
|
55
|
-
* {
|
|
67
|
+
* // Layout несёт только component/componentProps; правила — в отдельной ValidationDefinition.
|
|
68
|
+
* { model: model.$.email, component: Input },
|
|
56
69
|
* // вложенная группа: `model.$.profile.name` (≡ под-модель `model.profile.$.name` — тот же сигнал)
|
|
57
|
-
* {
|
|
70
|
+
* { model: model.$.profile.name, component: Input },
|
|
58
71
|
* ],
|
|
59
72
|
* };
|
|
60
73
|
*
|
|
@@ -65,69 +78,43 @@ export interface CreateFormFromModelArgs<T> {
|
|
|
65
78
|
* console.log(model.email); // 'user@mail.com'
|
|
66
79
|
* ```
|
|
67
80
|
*
|
|
68
|
-
* @see
|
|
81
|
+
* @see `createForm` — сборка одним вызовом: модель, форма, валидация и дерево для рендера
|
|
69
82
|
* @group Utilities
|
|
70
83
|
*/
|
|
71
|
-
export declare function createFormFromModel<T>(args: CreateFormFromModelArgs<T>):
|
|
84
|
+
export declare function createFormFromModel<T>(args: CreateFormFromModelArgs<T>): FormGroup<T>;
|
|
72
85
|
/**
|
|
73
|
-
*
|
|
86
|
+
* Снять форму, собранную {@link createFormFromModel}: поведение формы и подписки нод (массивы
|
|
87
|
+
* под-форм следят за моделью). Значения модели остаются. Идемпотентно.
|
|
74
88
|
*
|
|
75
|
-
*
|
|
89
|
+
* Сборку одним вызовом снимают целиком — `bundle.dispose()`: вместе с формой она снимает живую
|
|
90
|
+
* проверку и отменяет идущие проверки. Этот вызов нужен своим слоям сборки поверх
|
|
91
|
+
* {@link createFormFromModel}.
|
|
76
92
|
*
|
|
77
|
-
* @param
|
|
78
|
-
* @returns Типизированная форма с Proxy-доступом к полям
|
|
93
|
+
* @param form - Форма из {@link createFormFromModel}.
|
|
79
94
|
*
|
|
80
|
-
* @example
|
|
95
|
+
* @example
|
|
81
96
|
* ```typescript
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
* interface UserForm {
|
|
87
|
-
* email: string;
|
|
88
|
-
* password: string;
|
|
89
|
-
* }
|
|
90
|
-
*
|
|
91
|
-
* const model = createModel<UserForm>({ email: '', password: '' });
|
|
92
|
-
*
|
|
93
|
-
* // Layout-схема НЕ несёт validators — только component/componentProps.
|
|
94
|
-
* const schema = {
|
|
95
|
-
* children: [
|
|
96
|
-
* { value: model.$.email, component: Input },
|
|
97
|
-
* { value: model.$.password, component: Input },
|
|
98
|
-
* ],
|
|
99
|
-
* };
|
|
100
|
-
*
|
|
101
|
-
* const form = createForm<UserForm>({ model, schema });
|
|
102
|
-
* form.email.setValue('test@mail.com');
|
|
103
|
-
*
|
|
104
|
-
* // Валидация — ОТДЕЛЬНАЯ схема, прогон внешним раннером (ошибки сами доезжают до нод):
|
|
105
|
-
* const validation = defineValidationSchema<UserForm>(({ model }) => {
|
|
106
|
-
* validate(model.$.email, [required(), email()]);
|
|
107
|
-
* validate(model.$.password, [required(), minLength(8)]);
|
|
108
|
-
* });
|
|
109
|
-
* const ok = await validateModel(model, validation);
|
|
97
|
+
* const form = createFormFromModel<Profile>({ model, schema, behavior });
|
|
98
|
+
* // … форма больше не нужна
|
|
99
|
+
* disposeForm(form);
|
|
110
100
|
* ```
|
|
101
|
+
*
|
|
102
|
+
* @group Utilities
|
|
111
103
|
*/
|
|
112
|
-
export declare function
|
|
113
|
-
export declare function createForm<T>(config: GroupNodeConfig<T>): FormProxy<T>;
|
|
104
|
+
export declare function disposeForm<T>(form: FormGroup<T>): void;
|
|
114
105
|
/**
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
* @deprecated Legacy / back-compat: плоская `FormSchema` с инлайн-значениями (`value: ''`) — путь
|
|
118
|
-
* ДО архитектуры M1. Для нового кода используйте перегрузку `createForm({ model, schema })`
|
|
119
|
-
* (значения принадлежат {@link FormModel}, а правила — отдельной схеме `defineValidationSchema`,
|
|
120
|
-
* которую прогоняет `validateModel`; поля `validators` у узла layout-схемы нет).
|
|
106
|
+
* Аргументы {@link createFormFromCompiled}: вместо авторского дерева — его компиляция.
|
|
121
107
|
*
|
|
122
|
-
* @
|
|
123
|
-
|
|
108
|
+
* @internal
|
|
109
|
+
*/
|
|
110
|
+
export interface CreateFormFromCompiledArgs<T> extends Omit<CreateFormFromModelArgs<T>, 'schema'> {
|
|
111
|
+
/** Скомпилированная схема области модели; без неё у полей нет конфига из схемы. */
|
|
112
|
+
compiled?: CompiledSchema;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Форма из модели и скомпилированной схемы. Её зовут {@link createFormFromModel}, сборка одним
|
|
116
|
+
* вызовом (`createForm`) и форма строки массива — каждая со своей компиляцией.
|
|
124
117
|
*
|
|
125
|
-
* @
|
|
126
|
-
* ```typescript
|
|
127
|
-
* const form = createForm<UserForm>({
|
|
128
|
-
* email: { value: '', component: Input },
|
|
129
|
-
* password: { value: '', component: Input },
|
|
130
|
-
* });
|
|
131
|
-
* ```
|
|
118
|
+
* @internal
|
|
132
119
|
*/
|
|
133
|
-
export declare function
|
|
120
|
+
export declare function createFormFromCompiled<T>(args: CreateFormFromCompiledArgs<T>): FormGroup<T>;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { ReadonlySignal } from '@preact/signals-core';
|
|
2
|
+
import { ValidationResult } from '../validation/types';
|
|
3
|
+
/**
|
|
4
|
+
* Почему поток остался на шаге: `invalid` — у шага блокирующие замечания, `error` — правило не
|
|
5
|
+
* вернуло результат, `cancelled` — прогон отменён либо результат проверки устарел (поток перевели,
|
|
6
|
+
* модель формы изменилась, пока шла проверка шага), `edge` — дальше (или раньше) шагов нет,
|
|
7
|
+
* `locked` — шаг недоступен, пока не пройден предыдущий, `current` — `goTo` на шаг, на котором поток
|
|
8
|
+
* уже стоит.
|
|
9
|
+
*
|
|
10
|
+
* @group Form
|
|
11
|
+
*/
|
|
12
|
+
export type FlowStayReason = 'invalid' | 'error' | 'cancelled' | 'edge' | 'locked' | 'current';
|
|
13
|
+
/**
|
|
14
|
+
* Итог перехода: поток перешёл на другой шаг либо остался — с причиной и, если шаг проверялся,
|
|
15
|
+
* результатом проверки.
|
|
16
|
+
*
|
|
17
|
+
* @group Form
|
|
18
|
+
*/
|
|
19
|
+
export type FlowTransition = {
|
|
20
|
+
readonly status: 'moved';
|
|
21
|
+
readonly from: string;
|
|
22
|
+
readonly to: string;
|
|
23
|
+
} | {
|
|
24
|
+
readonly status: 'stayed';
|
|
25
|
+
readonly step: string;
|
|
26
|
+
readonly reason: FlowStayReason;
|
|
27
|
+
readonly validation?: ValidationResult;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Поток шагов формы.
|
|
31
|
+
*
|
|
32
|
+
* @group Form
|
|
33
|
+
*/
|
|
34
|
+
export interface FormFlow {
|
|
35
|
+
/** Идентификаторы шагов по порядку. */
|
|
36
|
+
readonly steps: readonly string[];
|
|
37
|
+
/** Текущий шаг. */
|
|
38
|
+
readonly current: ReadonlySignal<string>;
|
|
39
|
+
/** Номер текущего шага с нуля. */
|
|
40
|
+
readonly index: ReadonlySignal<number>;
|
|
41
|
+
/** Пройденные шаги: правила шага прошли при переходе дальше. */
|
|
42
|
+
readonly completed: ReadonlySignal<ReadonlySet<string>>;
|
|
43
|
+
readonly isFirst: ReadonlySignal<boolean>;
|
|
44
|
+
readonly isLast: ReadonlySignal<boolean>;
|
|
45
|
+
/** Идёт ли проверка шага в `next()`. */
|
|
46
|
+
readonly validating: ReadonlySignal<boolean>;
|
|
47
|
+
/** Можно ли перейти на шаг: первый — всегда, остальные — после прохождения предыдущего. */
|
|
48
|
+
canGoTo(stepId: string): boolean;
|
|
49
|
+
/** Проверить правила текущего шага и при успехе перейти к следующему. */
|
|
50
|
+
next(): Promise<FlowTransition>;
|
|
51
|
+
/** Вернуться на шаг назад; пройденными остаются только шаги до него. */
|
|
52
|
+
previous(): FlowTransition;
|
|
53
|
+
/** Перейти на шаг; неизвестный шаг — исключение. */
|
|
54
|
+
goTo(stepId: string): FlowTransition;
|
|
55
|
+
/** Вернуться на первый шаг и забыть пройденные. */
|
|
56
|
+
reset(): void;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Опции {@link createFormFlow}.
|
|
60
|
+
*
|
|
61
|
+
* @group Form
|
|
62
|
+
*/
|
|
63
|
+
export interface FormFlowOptions {
|
|
64
|
+
/** Идентификаторы шагов по порядку; не пустой список без повторов. */
|
|
65
|
+
readonly steps: readonly string[];
|
|
66
|
+
/** Проверка шага при `next()`; без неё шаг проходится без проверки. */
|
|
67
|
+
readonly validateStep?: (stepId: string) => Promise<ValidationResult>;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Создать поток шагов.
|
|
71
|
+
*
|
|
72
|
+
* @param options - {@link FormFlowOptions}: шаги и проверка шага.
|
|
73
|
+
* @returns {@link FormFlow} на первом шаге.
|
|
74
|
+
* @throws Error если шагов нет или идентификатор повторяется.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* const flow = createFormFlow({ steps: ['loan', 'contacts', 'confirm'] });
|
|
79
|
+
*
|
|
80
|
+
* await flow.next(); // { status: 'moved', from: 'loan', to: 'contacts' }
|
|
81
|
+
* flow.canGoTo('confirm'); // false — шаг contacts ещё не пройден
|
|
82
|
+
* flow.goTo('loan'); // { status: 'moved', from: 'contacts', to: 'loan' }
|
|
83
|
+
* ```
|
|
84
|
+
*
|
|
85
|
+
* @group Form
|
|
86
|
+
*/
|
|
87
|
+
export declare function createFormFlow(options: FormFlowOptions): FormFlow;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { FormModel } from '../model/types';
|
|
2
|
+
import { FormBehavior } from './behaviors';
|
|
3
|
+
import { SchemaController, SchemaNodeControl } from './schema-controller';
|
|
4
|
+
import { CompiledSchema } from './schema/compiled';
|
|
5
|
+
import { FormSchemaNode } from './types/schema-node';
|
|
6
|
+
import { FormGroup } from './types/index';
|
|
7
|
+
import { FormFlowConfig, FormLevel, FormValidation } from './form-level';
|
|
8
|
+
import { ValidationDefinition } from './validation';
|
|
9
|
+
/**
|
|
10
|
+
* Дерево, собранное реестром из документа схемы (JSON), и то, что реестр хочет донести до
|
|
11
|
+
* рендерера вместе с ним.
|
|
12
|
+
*
|
|
13
|
+
* @group Utilities
|
|
14
|
+
*/
|
|
15
|
+
export interface ResolvedSchema {
|
|
16
|
+
/** Корневой узел дерева. */
|
|
17
|
+
tree: FormSchemaNode;
|
|
18
|
+
/** Обёртка поля — компонент, которым рендерер оборачивает каждое поле. */
|
|
19
|
+
fieldWrapper?: unknown;
|
|
20
|
+
/** Граница ошибок — компонент, которым рендерер оборачивает дерево. */
|
|
21
|
+
errorBoundary?: unknown;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Реестр, умеющий превратить документ схемы в дерево. Метод необязателен: у интерфейса реестра
|
|
25
|
+
* есть сторонние реализации, и ядро документ само не разбирает.
|
|
26
|
+
*
|
|
27
|
+
* @group Utilities
|
|
28
|
+
*/
|
|
29
|
+
export interface SchemaResolver {
|
|
30
|
+
resolveSchema?(document: unknown, model: FormModel<never>): ResolvedSchema;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Часть бандла для рендерера: скомпилированная схема и схема-контроллер сборки.
|
|
34
|
+
*
|
|
35
|
+
* @group Utilities
|
|
36
|
+
*/
|
|
37
|
+
export interface FormRender {
|
|
38
|
+
/** Скомпилированная схема корневой области; `undefined`, если схема не задана. */
|
|
39
|
+
readonly tree: CompiledSchema | undefined;
|
|
40
|
+
/** Схема-контроллер сборки: области корня, строк массивов и подформ. */
|
|
41
|
+
readonly controller: SchemaController;
|
|
42
|
+
/** Управление узлом КОРНЕВОЙ области по его `selector`. */
|
|
43
|
+
node(selector: string): SchemaNodeControl;
|
|
44
|
+
/** Обёртка поля из реестра (JSON-вариант). */
|
|
45
|
+
readonly fieldWrapper?: unknown;
|
|
46
|
+
/** Граница ошибок из реестра (JSON-вариант). */
|
|
47
|
+
readonly errorBoundary?: unknown;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Результат {@link createForm}: модель, форма, часть для рендерера и уровень формы
|
|
51
|
+
* ({@link FormLevel}) — `validate()`, `validateStep(id)`, поток шагов и отправка
|
|
52
|
+
* `submission.submit(handler)`.
|
|
53
|
+
*
|
|
54
|
+
* @typeParam T - Форма данных модели.
|
|
55
|
+
* @group Utilities
|
|
56
|
+
*/
|
|
57
|
+
export interface FormBundle<T> extends FormLevel<T> {
|
|
58
|
+
readonly model: FormModel<T>;
|
|
59
|
+
readonly form: FormGroup<T>;
|
|
60
|
+
readonly render: FormRender;
|
|
61
|
+
/**
|
|
62
|
+
* Снять сборку: поведение формы, подписки нод, живую проверку; идущие проверки — полная, шага,
|
|
63
|
+
* отправки — получают `cancelled`. Значения модели остаются. Идемпотентно.
|
|
64
|
+
*
|
|
65
|
+
* Владелец сборки — тот, кто вызвал `createForm`: вне React (тесты, сервер, своя оболочка)
|
|
66
|
+
* снимайте её этим вызовом, когда форма больше не нужна.
|
|
67
|
+
*/
|
|
68
|
+
dispose(): void;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Конфиг {@link createForm}.
|
|
72
|
+
*
|
|
73
|
+
* @typeParam T - Форма данных модели.
|
|
74
|
+
* @group Utilities
|
|
75
|
+
*/
|
|
76
|
+
export interface CreateFormConfig<T> {
|
|
77
|
+
/** Начальные значения — из них создаётся модель. Взаимоисключимо с `model`. */
|
|
78
|
+
initial?: T;
|
|
79
|
+
/** Готовая модель (если создана отдельной фабрикой). Приоритетнее `initial`. */
|
|
80
|
+
model?: FormModel<T>;
|
|
81
|
+
/**
|
|
82
|
+
* Схема формы: билдер дерева `(model) => узел` либо документ (JSON) — тогда нужен `registry`.
|
|
83
|
+
* Билдер, а не готовое дерево: узлы держат ручки модели (`model: model.$.email`), и построить
|
|
84
|
+
* дерево до модели нечем.
|
|
85
|
+
*/
|
|
86
|
+
schema?: ((model: FormModel<T>) => FormSchemaNode) | object;
|
|
87
|
+
/** Реестр JSON-варианта: превращает документ схемы в дерево. */
|
|
88
|
+
registry?: SchemaResolver;
|
|
89
|
+
/** Поведение формы: значения, состояние нод и правила узлов схемы. */
|
|
90
|
+
behavior?: FormBehavior<T>;
|
|
91
|
+
/**
|
|
92
|
+
* Правила валидации: готовый набор либо {@link FormValidation} — полный набор `rules`, правила
|
|
93
|
+
* вне шагов `extras` и стратегия живой проверки. Без `rules` полный набор собирается из правил
|
|
94
|
+
* шагов потока и `extras`.
|
|
95
|
+
*/
|
|
96
|
+
validation?: FormValidation<T> | ValidationDefinition<T>;
|
|
97
|
+
/**
|
|
98
|
+
* Поток шагов: `{ steps: [{ id, rules }] }`. Идентификатор шага — `selector` узла шага в схеме;
|
|
99
|
+
* `next()` потока проверяет правила текущего шага.
|
|
100
|
+
*/
|
|
101
|
+
flow?: FormFlowConfig<T>;
|
|
102
|
+
/**
|
|
103
|
+
* Правка модели ДО сборки формы. Нужна там, где значение обязано существовать к моменту
|
|
104
|
+
* построения нод — например, массив, наполняемый из вычислений (реактивные `onChange` на
|
|
105
|
+
* инициализации не срабатывают). Модель, созданная из `initial`, снимает точку отсчёта после
|
|
106
|
+
* `seed` — сброс его правки не откатывает; точкой отсчёта переданной `model` управляет владелец.
|
|
107
|
+
*/
|
|
108
|
+
seed?: (model: FormModel<T>) => void;
|
|
109
|
+
/** Донастройка ПОСЛЕ сборки: получает готовый бандл. */
|
|
110
|
+
setup?: (bundle: FormBundle<T>) => void;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Собрать модель, форму, уровень формы (проверка, отправка, поток шагов) и дерево для рендера за
|
|
114
|
+
* один проход.
|
|
115
|
+
*
|
|
116
|
+
* @typeParam T - Форма данных модели.
|
|
117
|
+
* @param config - {@link CreateFormConfig}: (`initial` | `model`) + опц. `schema`, `registry`,
|
|
118
|
+
* `behavior`, `validation`, `flow`, `seed`, `setup`.
|
|
119
|
+
* @returns {@link FormBundle} — `{ model, form, render, flow, validate, validateStep, submission, … }`.
|
|
120
|
+
*
|
|
121
|
+
* @example Рендерер по TS-схеме
|
|
122
|
+
* ```tsx
|
|
123
|
+
* const credit = useFormBundle(() =>
|
|
124
|
+
* createForm<CreditForm>({
|
|
125
|
+
* model: createCreditModel(),
|
|
126
|
+
* schema: creditSchema, // (model) => узел
|
|
127
|
+
* behavior: creditBehavior,
|
|
128
|
+
* validation: { extras: crossRules },
|
|
129
|
+
* flow: { steps: [{ id: 'loan', rules: loanRules }, { id: 'confirm' }] },
|
|
130
|
+
* })
|
|
131
|
+
* );
|
|
132
|
+
* return <FormRenderer form={credit} settings={{ fieldWrapper: FormField }} />;
|
|
133
|
+
* ```
|
|
134
|
+
*
|
|
135
|
+
* @example React-руками — та же сборка, разметка в JSX
|
|
136
|
+
* ```tsx
|
|
137
|
+
* const credit = useFormBundle(() => createForm<CreditForm>({ initial, schema: creditSchema }));
|
|
138
|
+
* const send = async () => {
|
|
139
|
+
* const result = await credit.submission.submit(api.send);
|
|
140
|
+
* if (result.status === 'invalid') showHint('Проверьте форму');
|
|
141
|
+
* };
|
|
142
|
+
* return <FormField control={credit.form.loanType} />;
|
|
143
|
+
* ```
|
|
144
|
+
*
|
|
145
|
+
* @example JSON — документ схемы и реестр
|
|
146
|
+
* ```tsx
|
|
147
|
+
* const credit = useFormBundle(() =>
|
|
148
|
+
* createForm<CreditForm>({ model: createCreditModel(), schema: creditJson, registry })
|
|
149
|
+
* );
|
|
150
|
+
* return <FormRenderer form={credit} />;
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
export declare function createForm<T extends object>(config: CreateFormConfig<T>): FormBundle<T>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { FormModel } from '../model/types';
|
|
2
|
+
import { FormBehavior } from './behaviors';
|
|
3
|
+
import { FormGroup } from './types/index';
|
|
4
|
+
import { FormFlowConfig, FormLevel, FormValidation } from './form-level';
|
|
5
|
+
import { ValidationDefinition } from './validation';
|
|
6
|
+
/**
|
|
7
|
+
* Общая часть конфига всех фабрик формы.
|
|
8
|
+
*
|
|
9
|
+
* @typeParam T - Форма данных модели.
|
|
10
|
+
* @typeParam B - Бандл конкретной фабрики (его получает {@link CreateFormConfigBase.setup}).
|
|
11
|
+
*/
|
|
12
|
+
export interface CreateFormConfigBase<T, B> {
|
|
13
|
+
/** Начальные значения — из них создаётся модель. Взаимоисключимо с `model`. */
|
|
14
|
+
initial?: T;
|
|
15
|
+
/** Готовая модель (если создана отдельной фабрикой). Приоритетнее `initial`. */
|
|
16
|
+
model?: FormModel<T>;
|
|
17
|
+
/** Декларативное поведение модели (compute/copyFrom/enableWhen/onChange). */
|
|
18
|
+
behavior?: FormBehavior<T>;
|
|
19
|
+
/** Правила валидации: готовый набор либо {@link FormValidation} с `extras` и стратегией. */
|
|
20
|
+
validation?: FormValidation<T> | ValidationDefinition<T>;
|
|
21
|
+
/** Поток шагов: идентификатор шага и его правила — {@link FormFlowConfig}. */
|
|
22
|
+
flow?: FormFlowConfig<T>;
|
|
23
|
+
/**
|
|
24
|
+
* Правка модели ДО сборки формы. Нужна там, где значение обязано существовать к моменту
|
|
25
|
+
* построения нод — например, массив, наполняемый из вычислений (реактивные `onChange` на
|
|
26
|
+
* инициализации не срабатывают). Модель, созданная из `initial`, снимает точку отсчёта после
|
|
27
|
+
* `seed` — сброс его правки не откатывает; точкой отсчёта переданной `model` управляет владелец.
|
|
28
|
+
*/
|
|
29
|
+
seed?: (model: FormModel<T>) => void;
|
|
30
|
+
/** Донастройка ПОСЛЕ сборки: получает готовый бандл фабрики. */
|
|
31
|
+
setup?: (bundle: B) => void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Общая часть результата фабрик: модель, форма и уровень формы ({@link FormLevel}) — проверка,
|
|
35
|
+
* отправка и поток шагов.
|
|
36
|
+
*/
|
|
37
|
+
export interface CoreForm<T> extends FormLevel<T> {
|
|
38
|
+
readonly model: FormModel<T>;
|
|
39
|
+
readonly form: FormGroup<T>;
|
|
40
|
+
/**
|
|
41
|
+
* Снять сборку: форму (`disposeForm` — поведение, подписки нод) и уровень формы (живая
|
|
42
|
+
* проверка, идущие проверки). Фабрика обязана задать его ПОСЛЕ `...level`: `dispose` уровня
|
|
43
|
+
* форму не снимает.
|
|
44
|
+
*/
|
|
45
|
+
dispose(): void;
|
|
46
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { ReadonlySignal } from '@preact/signals-core';
|
|
2
|
+
import { FormModel } from '../model/types';
|
|
3
|
+
import { FormFlow } from './flow/flow';
|
|
4
|
+
import { FormSubmission } from './submission';
|
|
5
|
+
import { FormValidationController, ValidationStrategyKind } from './validation/strategy';
|
|
6
|
+
import { ValidationDefinition, ValidationResult } from './validation/types';
|
|
7
|
+
/**
|
|
8
|
+
* Правила валидации формы и стратегия живой проверки.
|
|
9
|
+
*
|
|
10
|
+
* ⚠️ `rules` и `extras` обязаны быть **стабильными ссылками** (`defineValidation` в модуле): отмена
|
|
11
|
+
* устаревших прогонов ключится по паре «модель + правила».
|
|
12
|
+
*
|
|
13
|
+
* @group Form
|
|
14
|
+
*/
|
|
15
|
+
export interface FormValidation<T> {
|
|
16
|
+
/** Полный набор правил. Без него собирается из правил шагов потока и `extras`. */
|
|
17
|
+
rules?: ValidationDefinition<T>;
|
|
18
|
+
/** Правила, которые проверяются только целиком (отправка), но не по шагам. */
|
|
19
|
+
extras?: ValidationDefinition<T>;
|
|
20
|
+
/** Когда запускать живую проверку. По умолчанию `'submit'` — живой проверки нет. */
|
|
21
|
+
strategy?: ValidationStrategyKind;
|
|
22
|
+
debounce?: number;
|
|
23
|
+
/** Режим живой фазы для `afterFirstSubmit`. По умолчанию `'change'`. */
|
|
24
|
+
liveAfterSubmit?: 'change' | 'blur';
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Шаг потока: идентификатор (он же `selector` узла шага в схеме) и правила шага.
|
|
28
|
+
*
|
|
29
|
+
* @group Form
|
|
30
|
+
*/
|
|
31
|
+
export interface FlowStep<T> {
|
|
32
|
+
readonly id: string;
|
|
33
|
+
/** Правила шага; `null` или без поля — шаг без правил. */
|
|
34
|
+
readonly rules?: ValidationDefinition<T> | null;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Поток шагов в конфиге сборки.
|
|
38
|
+
*
|
|
39
|
+
* @group Form
|
|
40
|
+
*/
|
|
41
|
+
export interface FormFlowConfig<T> {
|
|
42
|
+
readonly steps: readonly FlowStep<T>[];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Правила формы и контроллер живой проверки — его армирует `useFormBundle`.
|
|
46
|
+
*
|
|
47
|
+
* @group Form
|
|
48
|
+
*/
|
|
49
|
+
export interface FormValidationState<T> {
|
|
50
|
+
/** Полный набор правил (стабильная ссылка). */
|
|
51
|
+
readonly rules: ValidationDefinition<T>;
|
|
52
|
+
readonly controller: FormValidationController;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Уровень формы в бандле сборки.
|
|
56
|
+
*
|
|
57
|
+
* @group Form
|
|
58
|
+
*/
|
|
59
|
+
export interface FormLevel<T> {
|
|
60
|
+
/** Поток шагов; без `flow` в конфиге — `undefined`. */
|
|
61
|
+
readonly flow: FormFlow | undefined;
|
|
62
|
+
/** Идёт ли проверка: полная или шага. */
|
|
63
|
+
readonly validating: ReadonlySignal<boolean>;
|
|
64
|
+
/** Правила и контроллер живой проверки; без правил — `undefined`. */
|
|
65
|
+
readonly validation: FormValidationState<T> | undefined;
|
|
66
|
+
/**
|
|
67
|
+
* Отправка: `submission.submit(handler)` — один прогон всех правил и обработчик со значениями,
|
|
68
|
+
* которые они видели; `submission.submitting` — идёт ли обработчик.
|
|
69
|
+
*/
|
|
70
|
+
readonly submission: FormSubmission<T>;
|
|
71
|
+
/**
|
|
72
|
+
* Проверить всю форму и показать замечания. Поля выключенных нод (`enableWhen`, `disable()`)
|
|
73
|
+
* не учитываются — статус совпадает с `valid` формы.
|
|
74
|
+
*
|
|
75
|
+
* Правила читают модель в момент вызова. Исключение — вызов в одном тике со сборкой формы или
|
|
76
|
+
* правкой поля: поведение ещё пишет отложенно (колбэк `onChange`, сброс `resetOnDisable`), и
|
|
77
|
+
* проверка сначала дожидается этих записей; `validating` поднят сразу. Так же ведут себя
|
|
78
|
+
* `validateStep` и отправка.
|
|
79
|
+
*
|
|
80
|
+
* Попыткой отправки проверка не считается: стратегия `afterFirstSubmit` остаётся в тихой фазе.
|
|
81
|
+
*/
|
|
82
|
+
validate(): Promise<ValidationResult>;
|
|
83
|
+
/**
|
|
84
|
+
* Проверить шаг потока (без выключенных полей); неизвестный шаг — исключение.
|
|
85
|
+
*
|
|
86
|
+
* Это отчёт о шаге, как `validate` — о форме. Переход делает `flow.next()`: он сверяет модель
|
|
87
|
+
* и не переходит, если её изменили, пока шла проверка шага.
|
|
88
|
+
*/
|
|
89
|
+
validateStep(stepId: string): Promise<ValidationResult>;
|
|
90
|
+
/**
|
|
91
|
+
* Снять уровень формы: подписки и таймеры живой проверки; идущие проверки — полная, шага,
|
|
92
|
+
* отправки — получают `cancelled`, и их замечания на ноды не ложатся. Идемпотентно. Ноды формы
|
|
93
|
+
* уровень не снимает — это делает сборка (`bundle.dispose()`).
|
|
94
|
+
*/
|
|
95
|
+
dispose(): void;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Собрать уровень формы: правила, контроллер живой проверки, поток шагов и отправку.
|
|
99
|
+
*
|
|
100
|
+
* @typeParam T - Форма данных модели.
|
|
101
|
+
* @param model - Модель формы.
|
|
102
|
+
* @param config - Правила (`validation`) и поток (`flow`).
|
|
103
|
+
* @returns {@link FormLevel}.
|
|
104
|
+
* @throws Error если в потоке повторяется шаг.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* const level = createFormLevel(model, {
|
|
109
|
+
* validation: { extras: crossRules },
|
|
110
|
+
* flow: { steps: [{ id: 'loan', rules: loanRules }, { id: 'confirm' }] },
|
|
111
|
+
* });
|
|
112
|
+
* const result = await level.submission.submit(sendApplication);
|
|
113
|
+
* if (result.status === 'invalid') showErrors();
|
|
114
|
+
* ```
|
|
115
|
+
*
|
|
116
|
+
* @group Form
|
|
117
|
+
*/
|
|
118
|
+
export declare function createFormLevel<T>(model: FormModel<T>, config: {
|
|
119
|
+
validation?: FormValidation<T> | ValidationDefinition<T>;
|
|
120
|
+
flow?: FormFlowConfig<T>;
|
|
121
|
+
}): FormLevel<T>;
|
|
@@ -1,25 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { FormGroup } from './types/nodes';
|
|
2
|
+
import { InternalFormNode } from './nodes/node-kind';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Прокси группы над её сырым узлом.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* - Приоритет собственных свойств GroupNode над полями
|
|
9
|
-
* - Цепочку proxy для вложенных GroupNode
|
|
10
|
-
* - Блокировку прямого присваивания полям (только через setValue/patchValue)
|
|
11
|
-
*
|
|
12
|
-
* @param target - GroupNode для которого создаётся proxy
|
|
13
|
-
* @param fields - Map полей формы
|
|
14
|
-
* @returns Типизированный Proxy
|
|
15
|
-
*
|
|
16
|
-
* @internal
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```typescript
|
|
20
|
-
* const proxy = buildFormProxy(groupNode, groupNode._fields);
|
|
21
|
-
* proxy.email.setValue('test@example.com');
|
|
22
|
-
* console.log(proxy.email.value.value);
|
|
23
|
-
* ```
|
|
6
|
+
* @param target - Сырой узел группы
|
|
7
|
+
* @param children - Сырые ноды полей по именам
|
|
24
8
|
*/
|
|
25
|
-
export declare function buildFormProxy<T>(target:
|
|
9
|
+
export declare function buildFormProxy<T>(target: InternalFormNode<T>, children: ReadonlyMap<string, InternalFormNode>): FormGroup<T>;
|