@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
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { Signal } from '@preact/signals-core';
|
|
2
|
+
import { CompiledSchema } from './schema/compiled';
|
|
3
|
+
/**
|
|
4
|
+
* Хуки жизненного цикла узла схемы. Каждый хук опционален; повторная регистрация перезаписывает
|
|
5
|
+
* предыдущее значение.
|
|
6
|
+
*
|
|
7
|
+
* @group Schema
|
|
8
|
+
*/
|
|
9
|
+
export interface NodeLifecycleHooks {
|
|
10
|
+
/** Срабатывает один раз при mount узла. Может вернуть cleanup-функцию. */
|
|
11
|
+
onMount?: () => void | (() => void);
|
|
12
|
+
/** Срабатывает один раз при unmount узла. */
|
|
13
|
+
onUnmount?: () => void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Хранилище переопределений одной области схемы. Ключ каждой карты — `selector` узла: он же
|
|
17
|
+
* идентификатор узла в скомпилированной схеме области ({@link SchemaNodeId}).
|
|
18
|
+
*
|
|
19
|
+
* @group Schema
|
|
20
|
+
*/
|
|
21
|
+
export interface SchemaOverrideMaps {
|
|
22
|
+
hiddenOverrides: Map<string, boolean | null>;
|
|
23
|
+
propsOverrides: Map<string, Record<string, unknown> | null>;
|
|
24
|
+
refRegistry: Map<string, {
|
|
25
|
+
current: any;
|
|
26
|
+
}>;
|
|
27
|
+
/** Условия скрытия узлов: selector → реактивное условие. */
|
|
28
|
+
conditionRegistry: Map<string, () => boolean>;
|
|
29
|
+
/** Реактивные эффекты, живущие, пока область смонтирована (`renderEffect`). */
|
|
30
|
+
effectRegistry: Array<() => void | (() => void)>;
|
|
31
|
+
/** Обработчики событий компонентов: selector → { имя пропа → обработчик }. */
|
|
32
|
+
callbackRegistry: Map<string, Map<string, (...args: any[]) => any>>;
|
|
33
|
+
/** Хуки жизненного цикла узла: selector → { onMount, onUnmount }. */
|
|
34
|
+
lifecycleRegistry: Map<string, NodeLifecycleHooks>;
|
|
35
|
+
/** Общий счётчик изменений области. Узлы на него не подписываются — см. `versionFor`. */
|
|
36
|
+
version: Signal<number>;
|
|
37
|
+
/**
|
|
38
|
+
* Версия-сигнал одного селектора (создаётся лениво). Узел подписывается только на сигнал СВОЕГО
|
|
39
|
+
* селектора, поэтому `setHidden` / `patchProps` уведомляют один узел, а не всё дерево.
|
|
40
|
+
*/
|
|
41
|
+
versionFor(selector: string): Signal<number>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Управление одним узлом схемы. Получается через `schema.node(selector)`.
|
|
45
|
+
*
|
|
46
|
+
* @group Schema
|
|
47
|
+
*/
|
|
48
|
+
export interface SchemaNodeControl {
|
|
49
|
+
/** Принудительно скрыть или показать узел, минуя условие `hideWhen`. */
|
|
50
|
+
setHidden(value: boolean): this;
|
|
51
|
+
/** Убрать принудительное значение — снова действует условие `hideWhen`. */
|
|
52
|
+
resetHidden(): this;
|
|
53
|
+
/** Подмешать объект в `componentProps` узла. */
|
|
54
|
+
patchProps(partial: Record<string, unknown>): this;
|
|
55
|
+
/** Убрать подмешанные пропсы. */
|
|
56
|
+
resetProps(): this;
|
|
57
|
+
/**
|
|
58
|
+
* Ref на компонент узла. Создаётся один раз на селектор; рендерер вешает его на компонент.
|
|
59
|
+
* Компонент обязан принимать `ref`.
|
|
60
|
+
*/
|
|
61
|
+
getRef<H>(): {
|
|
62
|
+
current: H | null;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* @internal Записать условие скрытия узла (`hideWhen`). Возвращает снятие: оно убирает условие,
|
|
66
|
+
* только если его не сменило более позднее.
|
|
67
|
+
*/
|
|
68
|
+
addHideCondition(condition: () => boolean): () => void;
|
|
69
|
+
/**
|
|
70
|
+
* @internal Записать обработчик проп-события компонента узла (`onComponentEvent`). Возвращает
|
|
71
|
+
* снятие: оно убирает обработчик, только если его не сменил более поздний.
|
|
72
|
+
*/
|
|
73
|
+
addEventHandler(event: string, handler: (...args: any[]) => any): () => void;
|
|
74
|
+
/**
|
|
75
|
+
* @internal Записать хук жизненного цикла узла (`onMount`, `onUnmount`). Возвращает снятие: оно
|
|
76
|
+
* убирает хук, только если его не сменил более поздний.
|
|
77
|
+
*/
|
|
78
|
+
addLifecycleHook<K extends keyof NodeLifecycleHooks>(hook: K, value: NonNullable<NodeLifecycleHooks[K]>): () => void;
|
|
79
|
+
/** @internal Селектор узла. */
|
|
80
|
+
__selector: string;
|
|
81
|
+
/** @internal Хранилище области — его читает рендерер. */
|
|
82
|
+
__overrideMaps: SchemaOverrideMaps;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Схема одной области: адресует узлы по `selector`.
|
|
86
|
+
*
|
|
87
|
+
* @group Schema
|
|
88
|
+
*/
|
|
89
|
+
export interface SchemaScope {
|
|
90
|
+
/** Управление узлом области по его `selector`. */
|
|
91
|
+
node(selector: string): SchemaNodeControl;
|
|
92
|
+
/**
|
|
93
|
+
* @internal Записать эффект, живущий, пока область смонтирована (`renderEffect`). Возвращает
|
|
94
|
+
* снятие.
|
|
95
|
+
*/
|
|
96
|
+
addRenderEffect(effect: () => void | (() => void)): () => void;
|
|
97
|
+
/** @internal Хранилище области — его читает рендерер. */
|
|
98
|
+
__overrideMaps: SchemaOverrideMaps;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Схема-контроллер сборки: области по под-моделям.
|
|
102
|
+
*
|
|
103
|
+
* @group Schema
|
|
104
|
+
*/
|
|
105
|
+
export interface SchemaController {
|
|
106
|
+
/**
|
|
107
|
+
* Область под-модели: корня сборки, строки массива или группы подформы. Создаётся при первом
|
|
108
|
+
* обращении; повторное обращение отдаёт ту же область.
|
|
109
|
+
*/
|
|
110
|
+
scopeOf(subModel: object): SchemaScope;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Схема области поверх хранилища: `node(selector)` → управление узлом.
|
|
114
|
+
*
|
|
115
|
+
* @param maps - Хранилище области; по умолчанию создаётся новое.
|
|
116
|
+
* @group Schema
|
|
117
|
+
*/
|
|
118
|
+
export declare function createSchemaScope(maps?: SchemaOverrideMaps): SchemaScope;
|
|
119
|
+
/**
|
|
120
|
+
* Схема-контроллер одной сборки формы.
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```typescript
|
|
124
|
+
* const controller = createSchemaController();
|
|
125
|
+
* const root = controller.scopeOf(model);
|
|
126
|
+
* root.node('mortgage').setHidden(true);
|
|
127
|
+
*
|
|
128
|
+
* controller.scopeOf(model.items.at(0)); // область строки — свои селекторы
|
|
129
|
+
* ```
|
|
130
|
+
*
|
|
131
|
+
* @group Schema
|
|
132
|
+
*/
|
|
133
|
+
export declare function createSchemaController(): SchemaController;
|
|
134
|
+
/**
|
|
135
|
+
* Селекторы, на которые в области записаны правила, но которых нет в её скомпилированной схеме.
|
|
136
|
+
* Такое правило ничего не делает — сборка и рендерер в dev предупреждают о нём.
|
|
137
|
+
*
|
|
138
|
+
* Ref в проверку не входит: его разрешено брать по абсолютному пути модели
|
|
139
|
+
* (`phones.0.number`), а такой строки при сборке может ещё не быть.
|
|
140
|
+
*
|
|
141
|
+
* @param maps - Хранилище области.
|
|
142
|
+
* @param compiled - Скомпилированная схема области ({@link CompiledSchema}).
|
|
143
|
+
* @returns Селекторы с правилами, не найденные в схеме области.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```typescript
|
|
147
|
+
* const scope = controller.scopeOf(model);
|
|
148
|
+
* unknownSchemaSelectors(scope.__overrideMaps, bundle.render.tree!); // ['mortgage'] — узла нет
|
|
149
|
+
* ```
|
|
150
|
+
*
|
|
151
|
+
* @group Schema
|
|
152
|
+
*/
|
|
153
|
+
export declare function unknownSchemaSelectors(maps: SchemaOverrideMaps, compiled: CompiledSchema): string[];
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Поддерево схемы для под-модели: содержимое строки массива (`item`) или подформы (`part`).
|
|
3
|
+
*
|
|
4
|
+
* Билдер поддерева зовут два места — сборка формы и рендерер. Оба обязаны получить ОДНО дерево:
|
|
5
|
+
* на объектах его узлов держится идентичность (ключи рендера, записи схемы-контроллера), а сам
|
|
6
|
+
* билдер не обязан быть чистым. Поэтому дерево строится один раз на пару «билдер + под-модель»
|
|
7
|
+
* и дальше отдаётся из памяти.
|
|
8
|
+
*
|
|
9
|
+
* Память привязана к под-модели: исчезла строка массива — исчезли и её поддеревья.
|
|
10
|
+
*
|
|
11
|
+
* @group Utilities
|
|
12
|
+
* @module form/schema-subtree
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Поддерево схемы для под-модели — результат `builder(subModel)`, один на пару.
|
|
16
|
+
*
|
|
17
|
+
* @typeParam N - Тип узла, который возвращает билдер.
|
|
18
|
+
* @param builder - Билдер поддерева: `item` узла-массива или `part` узла-подформы.
|
|
19
|
+
* @param subModel - Под-модель строки массива или группы.
|
|
20
|
+
* @returns Узел поддерева; повторный вызов с той же парой отдаёт тот же объект.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* const row = model.items.at(0);
|
|
25
|
+
* schemaSubtree(itemSchema, row) === schemaSubtree(itemSchema, row); // true
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function schemaSubtree<N>(builder: (subModel: any) => N, subModel: object): N;
|
|
@@ -1,46 +1,51 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { FormNode } from './nodes/form-node';
|
|
1
|
+
import { FormNode } from './types/nodes';
|
|
3
2
|
/**
|
|
4
|
-
* Связать
|
|
3
|
+
* Связать ручку модели с её нодой формы.
|
|
5
4
|
*
|
|
6
|
-
* Вызывается движком при сборке формы (`createForm`/{@link createFormFromModel}) для каждого
|
|
7
|
-
*
|
|
5
|
+
* Вызывается движком при сборке формы (`createForm`/{@link createFormFromModel}) для каждого поля,
|
|
6
|
+
* группы и массива под-форм; у группы в реестре лежит её лицо {@link FormGroup} с нодами полей.
|
|
7
|
+
* Прикладной код обычно этот реестр не заполняет напрямую.
|
|
8
8
|
*
|
|
9
|
-
* @param signal -
|
|
10
|
-
* @param node - Нода формы, отвечающая за
|
|
9
|
+
* @param signal - Ручка из {@link FormModel}: сигнал листа, узел-массив или узел-группа дерева `model.$`
|
|
10
|
+
* @param node - Нода формы, отвечающая за эту часть модели
|
|
11
11
|
*
|
|
12
|
-
* @example
|
|
12
|
+
* @example Ручка модели указывает на ноду другой сборки
|
|
13
13
|
* ```typescript
|
|
14
14
|
* import { registerSignalNode } from '@reformer/core';
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
* const node = group.getFieldByPath('profile.email');
|
|
18
|
-
* if (sig && node) registerSignalNode(sig, node);
|
|
16
|
+
* registerSignalNode(model.$.profile.email, profileForm.email);
|
|
19
17
|
* ```
|
|
20
18
|
*
|
|
21
|
-
* @see {@link getNodeForSignal} - обратный поиск ноды по
|
|
19
|
+
* @see {@link getNodeForSignal} - обратный поиск ноды по ручке
|
|
22
20
|
* @group Utilities
|
|
23
21
|
*/
|
|
24
|
-
export declare function registerSignalNode(signal:
|
|
22
|
+
export declare function registerSignalNode(signal: object, node: FormNode<any>): void;
|
|
25
23
|
/**
|
|
26
|
-
* Найти ноду формы по
|
|
24
|
+
* Найти ноду формы по ручке модели.
|
|
27
25
|
*
|
|
28
|
-
* Используется state-операциями behavior (`enableWhen`/`disableWhen`)
|
|
29
|
-
* валидации в ноды. Возвращает `undefined`, если форма
|
|
30
|
-
*
|
|
26
|
+
* Используется state-операциями behavior (`enableWhen`/`disableWhen`), подключением под-схем
|
|
27
|
+
* (`apply`/`applyEach`) и роутингом ошибок валидации в ноды. Возвращает `undefined`, если форма
|
|
28
|
+
* ещё не построена или эта часть модели в форме не материализована (например, массив без
|
|
29
|
+
* item-схемы).
|
|
31
30
|
*
|
|
32
|
-
* @param signal -
|
|
33
|
-
* @returns Нода формы
|
|
31
|
+
* @param signal - Ручка из {@link FormModel}: `model.$.<поле>`, `model.$.<группа>`, `model.$.<массив>`
|
|
32
|
+
* @returns Нода формы — поля, группы или массива — либо `undefined`
|
|
34
33
|
*
|
|
35
34
|
* @example Роутинг ошибок валидации в ноду поля
|
|
36
35
|
* ```typescript
|
|
37
36
|
* import { getNodeForSignal } from '@reformer/core';
|
|
38
37
|
*
|
|
39
38
|
* const sig = model.$.email;
|
|
40
|
-
* getNodeForSignal(sig)?.
|
|
39
|
+
* getNodeForSignal(sig)?.setIssues([{ code: 'required' }]);
|
|
41
40
|
* ```
|
|
42
41
|
*
|
|
43
|
-
* @
|
|
42
|
+
* @example Нода группы и строки массива
|
|
43
|
+
* ```typescript
|
|
44
|
+
* getNodeForSignal(model.$.address)?.disable(); // группа целиком
|
|
45
|
+
* getNodeForSignal(model.$.phones[0])?.markAsTouched(); // форма строки массива
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @see {@link registerSignalNode} - регистрация связи ручка→нода
|
|
44
49
|
* @group Utilities
|
|
45
50
|
*/
|
|
46
|
-
export declare function getNodeForSignal(signal:
|
|
51
|
+
export declare function getNodeForSignal(signal: object): FormNode<any> | undefined;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { ReadonlySignal } from '@preact/signals-core';
|
|
2
|
+
import { ValidationResult } from './validation/types';
|
|
3
|
+
/**
|
|
4
|
+
* Итог отправки: `submitted` — обработчик отработал, `invalid` / `error` / `cancelled` —
|
|
5
|
+
* проверка не пропустила (обработчик не вызывался), `failed` — обработчик бросил исключение.
|
|
6
|
+
*
|
|
7
|
+
* `cancelled` — проверку отправки сменила следующая (вторая отправка, живой прогон) либо модель
|
|
8
|
+
* изменилась, пока проверка шла: правила видели прежние значения, и отправлять новые нельзя.
|
|
9
|
+
* Замечаний такой итог не несёт — отправку повторяют.
|
|
10
|
+
*
|
|
11
|
+
* @group Form
|
|
12
|
+
*/
|
|
13
|
+
export type SubmitResult<TResult> = {
|
|
14
|
+
readonly status: 'submitted';
|
|
15
|
+
readonly result: TResult;
|
|
16
|
+
} | {
|
|
17
|
+
readonly status: 'invalid' | 'error' | 'cancelled';
|
|
18
|
+
readonly validation: ValidationResult;
|
|
19
|
+
} | {
|
|
20
|
+
readonly status: 'failed';
|
|
21
|
+
readonly error: unknown;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Итог проверки для действия по её результату (отправка, переход шага).
|
|
25
|
+
*
|
|
26
|
+
* @group Form
|
|
27
|
+
*/
|
|
28
|
+
export interface ActionCheck<T> {
|
|
29
|
+
/** Результат проверки. */
|
|
30
|
+
readonly result: ValidationResult;
|
|
31
|
+
/** Значения модели после проверки; при `stale === false` — ровно те, что видели правила. */
|
|
32
|
+
readonly values: T;
|
|
33
|
+
/** Проверка успешна, но модель с тех пор изменилась: её успех относится к прежним значениям. */
|
|
34
|
+
readonly stale: boolean;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Зависимости отправки. Явные, чтобы модуль не тянул ни модель, ни ноды формы.
|
|
38
|
+
*
|
|
39
|
+
* @group Form
|
|
40
|
+
*/
|
|
41
|
+
export interface SubmissionDependencies<T> {
|
|
42
|
+
/**
|
|
43
|
+
* Проверка перед отправкой — попытка отправки: замечания раскрыты, при необходимости вся форма
|
|
44
|
+
* тронута. `undefined` — правил нет: обработчик получает {@link SubmissionDependencies.values}.
|
|
45
|
+
*/
|
|
46
|
+
readonly check: (() => Promise<ActionCheck<T>>) | undefined;
|
|
47
|
+
/** Значения без проверки. */
|
|
48
|
+
readonly values: () => T;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Отправка формы.
|
|
52
|
+
*
|
|
53
|
+
* @group Form
|
|
54
|
+
*/
|
|
55
|
+
export interface FormSubmission<T> {
|
|
56
|
+
/** Идёт ли отправка: работает обработчик. Пока идёт проверка, — `false`. */
|
|
57
|
+
readonly submitting: ReadonlySignal<boolean>;
|
|
58
|
+
/**
|
|
59
|
+
* Отправить: один прогон всех правил; при успехе — обработчик со значениями модели.
|
|
60
|
+
*
|
|
61
|
+
* Обработчик получает ровно те значения, которые видели правила. Пока идёт async-правило,
|
|
62
|
+
* форма не заперта (`submitting` ещё `false`); если модель за это время изменилась — правкой
|
|
63
|
+
* пользователя, загрузкой, записью поведения после таймера или запроса, — итог `cancelled`,
|
|
64
|
+
* обработчик не вызывается.
|
|
65
|
+
*
|
|
66
|
+
* Значения — модель целиком, с выключенными полями: их правила не считаются, но данные
|
|
67
|
+
* принадлежат модели. Убрать их из отправки — забота обработчика либо
|
|
68
|
+
* `enableWhen(…, { resetOnDisable: true })`.
|
|
69
|
+
*
|
|
70
|
+
* Исключение обработчика наружу не выходит: итог `failed` с этим исключением.
|
|
71
|
+
*/
|
|
72
|
+
submit<TResult>(handler: (values: T) => TResult | Promise<TResult>): Promise<SubmitResult<TResult>>;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Создать отправку формы.
|
|
76
|
+
*
|
|
77
|
+
* Обычно её создаёт сборка (`createForm` → `bundle.submission`). Прямой вызов нужен там, где
|
|
78
|
+
* сборки нет: визард в разметке без `createForm` отправляет значения формы без проверки.
|
|
79
|
+
*
|
|
80
|
+
* @typeParam T - Форма данных.
|
|
81
|
+
* @param dependencies - {@link SubmissionDependencies}: проверка перед действием и значения.
|
|
82
|
+
* @returns {@link FormSubmission}.
|
|
83
|
+
*
|
|
84
|
+
* @example Без проверки — значения формы как есть
|
|
85
|
+
* ```typescript
|
|
86
|
+
* const submission = createSubmission<Profile>({ check: undefined, values: () => form.getValue() });
|
|
87
|
+
* const outcome = await submission.submit(api.save);
|
|
88
|
+
* if (outcome.status === 'failed') showToast('Не удалось сохранить');
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* @group Form
|
|
92
|
+
*/
|
|
93
|
+
export declare function createSubmission<T>(dependencies: SubmissionDependencies<T>): FormSubmission<T>;
|
|
@@ -1,97 +1,38 @@
|
|
|
1
|
-
import { FormNode } from './nodes
|
|
2
|
-
import { FieldNode } from './nodes/field-node';
|
|
3
|
-
import { GroupNode } from './nodes/group-node';
|
|
4
|
-
import { ArrayNode } from './nodes/array-node';
|
|
5
|
-
import { FormValue } from './types/index';
|
|
1
|
+
import { FormArray, FormControl, FormGroup, FormNode } from './types/nodes';
|
|
6
2
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* Проверяет базовые свойства, общие для всех типов узлов
|
|
10
|
-
*
|
|
11
|
-
* @group Utilities
|
|
12
|
-
* @category Type Guards
|
|
13
|
-
*
|
|
14
|
-
* @param value - Значение для проверки
|
|
15
|
-
* @returns true если value является FormNode
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* ```typescript
|
|
19
|
-
* if (isFormNode(value)) {
|
|
20
|
-
* value.setValue(newValue);
|
|
21
|
-
* value.validate();
|
|
22
|
-
* }
|
|
23
|
-
* ```
|
|
24
|
-
*/
|
|
25
|
-
export declare function isFormNode(value: unknown): value is FormNode<FormValue>;
|
|
26
|
-
/**
|
|
27
|
-
* Проверить, является ли значение FieldNode (примитивное поле)
|
|
28
|
-
*
|
|
29
|
-
* FieldNode представляет примитивное поле формы (string, number, boolean и т.д.)
|
|
30
|
-
* и имеет валидаторы, но не имеет вложенных полей или элементов массива
|
|
31
|
-
*
|
|
32
|
-
* @group Utilities
|
|
33
|
-
* @category Type Guards
|
|
34
|
-
*
|
|
35
|
-
* @param value - Значение для проверки
|
|
36
|
-
* @returns true если value является FieldNode
|
|
3
|
+
* Нода формы любого вида — поле, группа или массив под-форм.
|
|
37
4
|
*
|
|
38
5
|
* @example
|
|
39
6
|
* ```typescript
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* node.asyncValidators; // OK
|
|
43
|
-
* node.markAsTouched(); // OK
|
|
44
|
-
* }
|
|
7
|
+
* const node = getNodeForSignal(model.$.email);
|
|
8
|
+
* if (isFormNode(node)) node.markAsTouched();
|
|
45
9
|
* ```
|
|
46
10
|
*/
|
|
47
|
-
export declare function
|
|
11
|
+
export declare function isFormNode(value: unknown): value is FormNode<unknown>;
|
|
48
12
|
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* GroupNode представляет объект с вложенными полями формы: имеет навигацию по полям
|
|
52
|
-
* (`getFieldByPath`/`fields`) и НЕ имеет array-методов (`items`/`push`/`removeAt`).
|
|
53
|
-
*
|
|
54
|
-
* @param value - Значение для проверки
|
|
55
|
-
* @returns true если value является GroupNode
|
|
13
|
+
* Поле формы — нода над листом модели с пропсами компонента.
|
|
56
14
|
*
|
|
57
15
|
* @example
|
|
58
16
|
* ```typescript
|
|
59
|
-
* if (
|
|
60
|
-
* node.getFieldByPath('user.email'); // OK
|
|
61
|
-
* }
|
|
17
|
+
* if (isFormControl(node)) node.updateComponentProps({ placeholder: 'Email' });
|
|
62
18
|
* ```
|
|
63
19
|
*/
|
|
64
|
-
export declare function
|
|
20
|
+
export declare function isFormControl(value: unknown): value is FormControl<unknown>;
|
|
65
21
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* ArrayNode представляет массив вложенных форм (обычно GroupNode)
|
|
69
|
-
* и имеет array-like методы (push, removeAt, at)
|
|
70
|
-
*
|
|
71
|
-
* @param value - Значение для проверки
|
|
72
|
-
* @returns true если value является ArrayNode
|
|
22
|
+
* Группа полей — её прокси с нодами полей по именам.
|
|
73
23
|
*
|
|
74
24
|
* @example
|
|
75
25
|
* ```typescript
|
|
76
|
-
* if (
|
|
77
|
-
* node.push(); // OK - добавить элемент
|
|
78
|
-
* node.removeAt(0); // OK - удалить элемент
|
|
79
|
-
* const item = node.at(0); // OK - получить элемент
|
|
80
|
-
* }
|
|
26
|
+
* if (isFormGroup(node)) node.markAsTouched();
|
|
81
27
|
* ```
|
|
82
28
|
*/
|
|
83
|
-
export declare function
|
|
29
|
+
export declare function isFormGroup(value: unknown): value is FormGroup<Record<string, unknown>>;
|
|
84
30
|
/**
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* Полезно для логирования и отладки
|
|
88
|
-
*
|
|
89
|
-
* @param node - Узел для проверки
|
|
90
|
-
* @returns Строковое название типа узла
|
|
31
|
+
* Массив под-форм.
|
|
91
32
|
*
|
|
92
33
|
* @example
|
|
93
34
|
* ```typescript
|
|
94
|
-
*
|
|
35
|
+
* if (isFormArray(node)) node.push();
|
|
95
36
|
* ```
|
|
96
37
|
*/
|
|
97
|
-
export declare function
|
|
38
|
+
export declare function isFormArray(value: unknown): value is FormArray<object>;
|
|
@@ -1,109 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Контракт замечания валидации.
|
|
3
3
|
*
|
|
4
|
-
* Базовый
|
|
5
|
-
*
|
|
6
|
-
* и платформенные биндинги. Файл не импортирует ничего — это лист графа зависимостей.
|
|
4
|
+
* Базовый словарь, на который опираются ноды формы, слой валидации и платформенные биндинги.
|
|
5
|
+
* Файл не импортирует ничего — это лист графа зависимостей.
|
|
7
6
|
*
|
|
8
|
-
* Живёт в `form/types/`, а не в слое модели:
|
|
9
|
-
*
|
|
7
|
+
* Живёт в `form/types/`, а не в слое модели: замечание — понятие формы, а модель этих типов
|
|
8
|
+
* не использует (и импортировать их оттуда запрещено границей model⇏form).
|
|
10
9
|
* Наружу отдаётся через `form/types/index`.
|
|
11
10
|
*
|
|
12
11
|
* @group Types
|
|
13
12
|
* @module form/types/contracts
|
|
14
13
|
*/
|
|
15
14
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* @category Core Types
|
|
21
|
-
*/
|
|
22
|
-
export type FormValue = string | number | boolean | null | undefined | Date | File | FormValue[] | {
|
|
23
|
-
[key: string]: FormValue;
|
|
24
|
-
};
|
|
25
|
-
/**
|
|
26
|
-
* Синхронная функция валидации
|
|
27
|
-
* @group Types
|
|
28
|
-
* @category Validation Types
|
|
29
|
-
*/
|
|
30
|
-
export type ValidatorFn<T = FormValue> = (value: T) => ValidationError | null;
|
|
31
|
-
/**
|
|
32
|
-
* Опции для асинхронного валидатора
|
|
33
|
-
* @group Types
|
|
34
|
-
* @category Validation Types
|
|
35
|
-
*/
|
|
36
|
-
export interface AsyncValidatorOptions {
|
|
37
|
-
/**
|
|
38
|
-
* AbortSignal для отмены валидации
|
|
39
|
-
* Позволяет отменить асинхронную операцию при новой валидации
|
|
40
|
-
*/
|
|
41
|
-
signal?: AbortSignal;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Асинхронная функция валидации
|
|
45
|
-
*
|
|
46
|
-
* @param value - Значение для валидации
|
|
47
|
-
* @param options - Опции валидации (опционально)
|
|
48
|
-
* @returns Promise с ошибкой валидации или null если значение валидно
|
|
15
|
+
* Замечание валидации: что нарушено (`code`) и с какими числами (`params`). Текста у замечания
|
|
16
|
+
* нет — отображаемую строку по коду даёт слой представления (`resolveIssueMessage` из
|
|
17
|
+
* `@reformer/core/i18n`): словарь формы → словарь локали → встроенный английский → сам код.
|
|
18
|
+
* Поэтому одно и то же замечание показывается на любом языке без повторной проверки.
|
|
49
19
|
*
|
|
50
20
|
* @example
|
|
51
|
-
* ```
|
|
52
|
-
*
|
|
53
|
-
* const
|
|
54
|
-
* const exists = await checkEmail(value);
|
|
55
|
-
* return exists ? { code: 'exists', message: 'Email already exists' } : null;
|
|
56
|
-
* };
|
|
57
|
-
*
|
|
58
|
-
* // Валидатор с поддержкой отмены
|
|
59
|
-
* const emailExistsAbortable: AsyncValidatorFn<string> = async (value, options) => {
|
|
60
|
-
* const exists = await fetch(`/api/check-email?email=${value}`, {
|
|
61
|
-
* signal: options?.signal // Передаём signal в fetch для отмены запроса
|
|
62
|
-
* });
|
|
63
|
-
* return exists ? { code: 'exists', message: 'Email already exists' } : null;
|
|
64
|
-
* };
|
|
21
|
+
* ```ts
|
|
22
|
+
* const tooShort: ValidationIssue = { code: 'minLength', params: { minLength: 8 } };
|
|
23
|
+
* const softLimit: ValidationIssue = { code: 'loanAmount.high', severity: 'warning' };
|
|
65
24
|
* ```
|
|
66
25
|
*
|
|
67
26
|
* @group Types
|
|
68
27
|
* @category Validation Types
|
|
69
28
|
*/
|
|
70
|
-
export
|
|
71
|
-
/**
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
*/
|
|
76
|
-
|
|
77
|
-
code: string;
|
|
78
|
-
/**
|
|
79
|
-
* Готовый текст ошибки. Пустая строка — «автор правила текста не задавал»: отображаемую строку
|
|
80
|
-
* тогда даёт резолвер по `code` (словарь локали `validation.<code>`).
|
|
81
|
-
*/
|
|
82
|
-
message: string;
|
|
83
|
-
/** Ключ сообщения в словаре приложения; при наличии в активной локали важнее `message`. */
|
|
84
|
-
messageKey?: string;
|
|
85
|
-
params?: Record<string, FormValue>;
|
|
86
|
-
/** Severity level: 'error' (default) blocks submission, 'warning' shows message but allows submission */
|
|
87
|
-
severity?: 'error' | 'warning';
|
|
29
|
+
export interface ValidationIssue {
|
|
30
|
+
/** Код правила: встроенный (`required`, `minLength`) либо свой (`loanAmount.required`). */
|
|
31
|
+
readonly code: string;
|
|
32
|
+
/** Значения для подстановки в текст: порог правила, фактическое значение. */
|
|
33
|
+
readonly params?: Readonly<Record<string, unknown>>;
|
|
34
|
+
/** `'error'` (по умолчанию) блокирует отправку, `'warning'` показывается, но не блокирует. */
|
|
35
|
+
readonly severity?: 'error' | 'warning';
|
|
88
36
|
}
|
|
89
|
-
/**
|
|
90
|
-
* Опции для фильтрации ошибок в методе getErrors()
|
|
91
|
-
* @group Types
|
|
92
|
-
* @category Validation Types
|
|
93
|
-
*/
|
|
94
|
-
export interface ErrorFilterOptions {
|
|
95
|
-
/** Фильтр по коду ошибки */
|
|
96
|
-
code?: string | string[];
|
|
97
|
-
/** Фильтр по сообщению (поддерживает частичное совпадение) */
|
|
98
|
-
message?: string;
|
|
99
|
-
/** Фильтр по параметрам ошибки */
|
|
100
|
-
params?: Record<string, FormValue>;
|
|
101
|
-
/** Кастомный предикат для фильтрации */
|
|
102
|
-
predicate?: (error: ValidationError) => boolean;
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Статус поля формы
|
|
106
|
-
* @group Types
|
|
107
|
-
* @category Core Types
|
|
108
|
-
*/
|
|
109
|
-
export type FieldStatus = 'valid' | 'invalid' | 'pending' | 'disabled';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Signal } from '@preact/signals-core';
|
|
2
|
+
import { ComponentRef } from './schema-node';
|
|
3
|
+
/**
|
|
4
|
+
* Конфигурация поля формы ({@link FormControl}): сигнал значения из модели и то, что нода берёт
|
|
5
|
+
* из узла схемы.
|
|
6
|
+
*
|
|
7
|
+
* В схеме формы поле записывают узлом `{ model: model.$.field, component, componentProps }`;
|
|
8
|
+
* сборка `createFormFromModel` превращает узел в этот конфиг сама. Правил валидации в конфиге нет —
|
|
9
|
+
* они живут в схеме валидации (`defineValidation`, `@reformer/core/validation`).
|
|
10
|
+
*
|
|
11
|
+
* @group Types
|
|
12
|
+
* @category Configuration Types
|
|
13
|
+
*/
|
|
14
|
+
export interface FieldConfig<T> {
|
|
15
|
+
/**
|
|
16
|
+
* Сигнал значения из {@link FormModel} — источник истины значения поля. Нода значением не
|
|
17
|
+
* владеет, а ссылается на этот сигнал.
|
|
18
|
+
*/
|
|
19
|
+
valueSignal: Signal<T>;
|
|
20
|
+
/**
|
|
21
|
+
* UI-компонент поля. Опционален: core-часть можно использовать без ссылки на компонент
|
|
22
|
+
* (значение и состояние работают без UI; компонент нужен только для рендеринга).
|
|
23
|
+
*/
|
|
24
|
+
component?: ComponentRef;
|
|
25
|
+
componentProps?: any;
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
}
|