@reformer/core 11.0.0-beta.1 → 11.0.0-beta.10
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-D05z3my6.js +109 -0
- package/dist/behaviors.d.ts +1 -1
- package/dist/behaviors.js +376 -211
- package/dist/create-model-DPSG3I0O.js +30 -0
- package/dist/date-utils-90-qZbse.js +43 -0
- package/dist/en-HP8XEych.js +44 -0
- package/dist/form/aggregate-signals.d.ts +21 -63
- package/dist/form/behaviors/collections.d.ts +84 -0
- package/dist/form/behaviors/context.d.ts +56 -0
- package/dist/form/behaviors/index.d.ts +30 -0
- package/dist/form/behaviors/internals.d.ts +41 -0
- package/dist/form/{behaviors-node.d.ts → behaviors/node.d.ts} +28 -5
- package/dist/form/behaviors/operators.d.ts +59 -0
- package/dist/form/behaviors/schema-operators.d.ts +83 -0
- package/dist/form/behaviors/types.d.ts +37 -0
- package/dist/form/create-form.d.ts +59 -70
- package/dist/form/flow/flow.d.ts +87 -0
- package/dist/form/form-bundle.d.ts +153 -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 +23 -24
- 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 +159 -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 +21 -85
- 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 +25 -17
- package/dist/form/validation/context.d.ts +67 -0
- package/dist/form/validation/index.d.ts +24 -28
- package/dist/form/validation/operators.d.ts +101 -0
- package/dist/form/validation/run.d.ts +120 -0
- package/dist/form/validation/strategy.d.ts +89 -0
- package/dist/form/validation/types.d.ts +83 -0
- package/dist/form/validators/date-utils.d.ts +42 -0
- package/dist/form/validators/email.d.ts +23 -0
- package/dist/form/{validation/validators → validators}/file-type.d.ts +10 -10
- package/dist/form/{validation/validators → validators}/file-utils.d.ts +3 -2
- package/dist/form/validators/future-date.d.ts +23 -0
- package/dist/form/{validation/validators → validators}/index.d.ts +7 -4
- package/dist/form/validators/integer.d.ts +22 -0
- package/dist/form/validators/is-date.d.ts +24 -0
- package/dist/form/validators/is-number.d.ts +25 -0
- package/dist/form/validators/max-age.d.ts +28 -0
- package/dist/form/validators/max-date.d.ts +25 -0
- package/dist/form/{validation/validators → validators}/max-file-size.d.ts +10 -10
- package/dist/form/validators/max-files.d.ts +26 -0
- package/dist/form/validators/max-length.d.ts +33 -0
- package/dist/form/validators/max-total-file-size.d.ts +26 -0
- package/dist/form/validators/max.d.ts +26 -0
- package/dist/form/validators/min-age.d.ts +27 -0
- package/dist/form/validators/min-date.d.ts +25 -0
- package/dist/form/{validation/validators → validators}/min-file-size.d.ts +10 -10
- package/dist/form/validators/min-files.d.ts +27 -0
- package/dist/form/validators/min-length.d.ts +33 -0
- package/dist/form/validators/min.d.ts +26 -0
- package/dist/form/validators/multiple-of.d.ts +25 -0
- package/dist/form/validators/non-negative.d.ts +22 -0
- package/dist/form/validators/non-zero.d.ts +22 -0
- package/dist/form/validators/past-date.d.ts +23 -0
- package/dist/form/validators/pattern.d.ts +26 -0
- package/dist/form/{validation/validators → validators}/phone.d.ts +11 -11
- package/dist/form/validators/required.d.ts +29 -0
- package/dist/form/validators/url.d.ts +45 -0
- package/dist/form/validators/validation-issue.d.ts +8 -0
- package/dist/i18n/descriptor.d.ts +54 -0
- package/dist/i18n/en.json.d.ts +49 -0
- package/dist/i18n/loader.d.ts +71 -0
- package/dist/i18n/locale-store.d.ts +46 -0
- package/dist/i18n/locale.d.ts +90 -0
- package/dist/i18n/message-format.d.ts +136 -0
- package/dist/i18n/resolve-localized.d.ts +17 -0
- package/dist/i18n/ru.json.d.ts +49 -0
- package/dist/i18n/translator.d.ts +61 -0
- package/dist/i18n/validation-message.d.ts +53 -0
- package/dist/i18n.d.ts +26 -0
- package/dist/i18n.js +86 -0
- package/dist/index.d.ts +17 -5
- package/dist/index.js +942 -2601
- package/dist/loader-BWkigpVe.js +52 -0
- package/dist/locale/en.d.ts +2 -0
- package/dist/locale/en.js +5 -0
- package/dist/locale/en.json +45 -0
- package/dist/locale/index.d.ts +18 -0
- package/dist/locale/ru.d.ts +2 -0
- package/dist/locale/ru.js +44 -0
- package/dist/locale/ru.json +45 -0
- package/dist/locale-CG54AU2Q.js +219 -0
- package/dist/locale.d.ts +2 -0
- package/dist/locale.js +9 -0
- package/dist/{state → model}/behaviors-value.d.ts +24 -6
- package/dist/{state/form-model.d.ts → model/create-model.d.ts} +18 -4
- package/dist/{state → model}/derived-registry.d.ts +1 -1
- package/dist/model/index.d.ts +42 -0
- package/dist/model/model-nodes.d.ts +190 -0
- package/dist/model/model-signals-proxy.d.ts +63 -0
- package/dist/model/model-value-proxy.d.ts +84 -0
- package/dist/{state → model}/safe-effect.d.ts +50 -2
- package/dist/model/types.d.ts +239 -0
- package/dist/model.d.ts +2 -0
- package/dist/model.js +27 -0
- package/dist/node-kind-C-r6ZMdo.js +15 -0
- package/dist/platforms/react/field-binding/field-adapter.d.ts +87 -0
- package/dist/platforms/react/field-binding/field-handle.d.ts +53 -0
- package/dist/platforms/react/form-bundle-context.d.ts +27 -0
- package/dist/{form → platforms/react}/hooks/types.d.ts +58 -36
- package/dist/platforms/react/hooks/use-form-bundle.d.ts +41 -0
- package/dist/platforms/react/hooks/use-form-flow.d.ts +40 -0
- package/dist/{form → platforms/react}/hooks/use-form-validation.d.ts +13 -7
- package/dist/{form → platforms/react}/hooks/useArrayLength.d.ts +6 -6
- package/dist/{form → platforms/react}/hooks/useFormControl.d.ts +7 -9
- package/dist/{form → platforms/react}/hooks/useFormControlValue.d.ts +18 -18
- package/dist/{form → platforms/react}/hooks/useSignalSubscription.d.ts +9 -1
- package/dist/platforms/react/i18n/context.d.ts +18 -0
- package/dist/platforms/react/i18n/hooks.d.ts +65 -0
- package/dist/platforms/react/i18n/provider.d.ts +59 -0
- package/dist/platforms/react/index.d.ts +30 -0
- 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-BazLOv1g.js +669 -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-DzvnsWLh.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.d.ts +1 -1
- package/dist/validation.js +11 -165
- package/dist/validators/email.d.ts +1 -1
- package/dist/validators/email.js +5 -8
- package/dist/validators/future-date.d.ts +1 -1
- package/dist/validators/future-date.js +10 -13
- package/dist/validators/integer.d.ts +1 -1
- package/dist/validators/integer.js +4 -7
- package/dist/validators/is-date.d.ts +1 -1
- package/dist/validators/is-date.js +5 -8
- package/dist/validators/is-number.d.ts +1 -1
- package/dist/validators/is-number.js +4 -7
- package/dist/validators/max-age.d.ts +1 -1
- package/dist/validators/max-age.js +8 -12
- package/dist/validators/max-date.d.ts +1 -1
- package/dist/validators/max-date.js +10 -13
- package/dist/validators/max-length.d.ts +1 -1
- package/dist/validators/max-length.js +7 -10
- package/dist/validators/max.d.ts +1 -1
- package/dist/validators/max.js +4 -7
- package/dist/validators/min-age.d.ts +1 -1
- package/dist/validators/min-age.js +10 -11
- package/dist/validators/min-date.d.ts +1 -1
- package/dist/validators/min-date.js +8 -11
- package/dist/validators/min-length.d.ts +1 -1
- package/dist/validators/min-length.js +4 -7
- package/dist/validators/min.d.ts +1 -1
- package/dist/validators/min.js +4 -7
- package/dist/validators/multiple-of.d.ts +1 -1
- package/dist/validators/multiple-of.js +11 -10
- package/dist/validators/non-negative.d.ts +1 -1
- package/dist/validators/non-negative.js +2 -5
- package/dist/validators/non-zero.d.ts +1 -1
- package/dist/validators/non-zero.js +4 -7
- package/dist/validators/past-date.d.ts +1 -1
- package/dist/validators/past-date.js +10 -13
- package/dist/validators/pattern.d.ts +1 -1
- package/dist/validators/pattern.js +5 -8
- package/dist/validators/phone.d.ts +1 -1
- package/dist/validators/phone.js +10 -11
- package/dist/validators/required.d.ts +1 -1
- package/dist/validators/required.js +4 -7
- package/dist/validators/url.d.ts +1 -1
- package/dist/validators/url.js +48 -17
- package/dist/validators.d.ts +1 -1
- package/dist/validators.js +86 -108
- package/docs/llms/01-api-reference.md +60 -34
- package/docs/llms/02-quick-start.md +112 -74
- package/docs/llms/03-api-signatures.md +369 -148
- 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 +132 -84
- package/docs/llms/10-arrays.md +141 -61
- 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 +224 -70
- package/docs/llms/16-ui-components.md +86 -46
- package/docs/llms/17-nonexistent-api.md +217 -32
- package/docs/llms/18-conditional-fields.md +71 -32
- package/docs/llms/19-reading-values.md +45 -4
- package/docs/llms/20-compute-vs-watch.md +25 -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 +278 -128
- package/docs/llms/29-async-preload.md +41 -31
- 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 +298 -0
- package/docs/llms/35-unified-contract.md +309 -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 +396 -0
- package/llms-index.json +1 -0
- package/llms.txt +10690 -3089
- package/package.json +48 -9
- package/dist/behaviors-node-DGEFMTQu.js +0 -18
- package/dist/behaviors-value-C7dSEhCc.js +0 -134
- package/dist/date-utils-dTT_x_Be.js +0 -31
- package/dist/derived-registry-CluZCQ7U.js +0 -16
- package/dist/form/behaviors.d.ts +0 -133
- package/dist/form/error-handler.d.ts +0 -166
- package/dist/form/factories/index.d.ts +0 -6
- package/dist/form/factories/node-factory.d.ts +0 -188
- 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 -294
- 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/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/validators/date-utils.d.ts +0 -30
- package/dist/form/validation/validators/email.d.ts +0 -23
- package/dist/form/validation/validators/future-date.d.ts +0 -23
- package/dist/form/validation/validators/integer.d.ts +0 -22
- package/dist/form/validation/validators/is-date.d.ts +0 -23
- package/dist/form/validation/validators/is-number.d.ts +0 -24
- package/dist/form/validation/validators/max-age.d.ts +0 -25
- package/dist/form/validation/validators/max-date.d.ts +0 -25
- package/dist/form/validation/validators/max-files.d.ts +0 -26
- package/dist/form/validation/validators/max-length.d.ts +0 -27
- package/dist/form/validation/validators/max-total-file-size.d.ts +0 -26
- package/dist/form/validation/validators/max.d.ts +0 -25
- package/dist/form/validation/validators/min-age.d.ts +0 -25
- package/dist/form/validation/validators/min-date.d.ts +0 -25
- package/dist/form/validation/validators/min-files.d.ts +0 -26
- package/dist/form/validation/validators/min-length.d.ts +0 -27
- package/dist/form/validation/validators/min.d.ts +0 -25
- package/dist/form/validation/validators/multiple-of.d.ts +0 -24
- package/dist/form/validation/validators/non-negative.d.ts +0 -22
- package/dist/form/validation/validators/non-zero.d.ts +0 -22
- package/dist/form/validation/validators/past-date.d.ts +0 -23
- package/dist/form/validation/validators/pattern.d.ts +0 -33
- package/dist/form/validation/validators/required.d.ts +0 -32
- package/dist/form/validation/validators/url.d.ts +0 -43
- package/dist/form/validation-schema.d.ts +0 -106
- package/dist/form/validation-strategy.d.ts +0 -55
- package/dist/form/validators.d.ts +0 -11
- package/dist/form-model-DYCzGGKF.js +0 -286
- package/dist/state/index.d.ts +0 -31
- package/dist/state/subscription-manager.d.ts +0 -180
- package/dist/state/types.d.ts +0 -144
- package/dist/state.d.ts +0 -2
- package/dist/state.js +0 -21
- package/dist/subscription-manager-705bls97.js +0 -171
package/dist/model.d.ts
ADDED
package/dist/model.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { c as s, e as r, a as l } from "./create-model-DPSG3I0O.js";
|
|
2
|
+
import { a as d, g as o, f as t, d as c, i as f, b as n, c as m, m as u, r as p, s as b, e as g, u as h } from "./safe-effect-BazLOv1g.js";
|
|
3
|
+
import { c as k, a as v, r as D, b as F, s as x, t as y, w as C } from "./behaviors-value-D05z3my6.js";
|
|
4
|
+
export {
|
|
5
|
+
d as arrayOf,
|
|
6
|
+
k as computeFrom,
|
|
7
|
+
v as copyFrom,
|
|
8
|
+
s as createModel,
|
|
9
|
+
o as deepEqual,
|
|
10
|
+
t as deferredWritesSettled,
|
|
11
|
+
r as eachLeafSignal,
|
|
12
|
+
l as eachValueSignal,
|
|
13
|
+
c as isDerived,
|
|
14
|
+
f as isModelContainerSignal,
|
|
15
|
+
n as isValueSignal,
|
|
16
|
+
m as markDerived,
|
|
17
|
+
u as modelOf,
|
|
18
|
+
D as resetWhen,
|
|
19
|
+
F as revalidateWhen,
|
|
20
|
+
p as runOutsideEffect,
|
|
21
|
+
b as safeCallback,
|
|
22
|
+
g as safeDebouncedCallback,
|
|
23
|
+
x as syncFields,
|
|
24
|
+
y as transformValue,
|
|
25
|
+
h as unmarkDerived,
|
|
26
|
+
C as watchField
|
|
27
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const n = Symbol.for("@reformer/core/form-node-kind"), e = Symbol.for("@reformer/core/form-node-raw");
|
|
2
|
+
function t(r) {
|
|
3
|
+
if (typeof r != "object" || r === null) return;
|
|
4
|
+
const o = r[n];
|
|
5
|
+
return o === "control" || o === "group" || o === "array" ? o : void 0;
|
|
6
|
+
}
|
|
7
|
+
function f(r) {
|
|
8
|
+
return r[e] ?? r;
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
n as N,
|
|
12
|
+
e as R,
|
|
13
|
+
t as k,
|
|
14
|
+
f as r
|
|
15
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Адаптер поля — как свести value-based seam формы (`value` + `onChange(value)` + `onBlur`) к
|
|
3
|
+
* контракту конкретного контрола. Чистые данные и чистые функции (без React): один механизм на
|
|
4
|
+
* всех, кто связывает поле с контролом, — `FormField.Control` из `@reformer/cdk` и рендерер
|
|
5
|
+
* `@reformer/renderer-react`.
|
|
6
|
+
*
|
|
7
|
+
* Контрол объявляет свой диалект статикой `reformerAdapter` (см. {@link getFieldAdapter}), поэтому
|
|
8
|
+
* отдельные «field-версии» компонентов не нужны: в `component` поля кладётся сам компонент.
|
|
9
|
+
*
|
|
10
|
+
* @module platforms/react/field-binding
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Адаптер поля: описывает диалект контрола (`checked`/`onCheckedChange`, `value`/`onValueChange`,
|
|
14
|
+
* DOM-событие в `onChange`, …). Все ключи необязательны — по умолчанию seam проходит как есть.
|
|
15
|
+
*
|
|
16
|
+
* @example Radix Checkbox
|
|
17
|
+
* ```ts
|
|
18
|
+
* const checkedAdapter: FieldAdapter = {
|
|
19
|
+
* valueProp: 'checked',
|
|
20
|
+
* changeProp: 'onCheckedChange',
|
|
21
|
+
* fromEmit: (c) => c === true,
|
|
22
|
+
* toValue: (v) => v ?? false,
|
|
23
|
+
* };
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export interface FieldAdapter {
|
|
27
|
+
/** Проп, из которого контрол читает значение (по умолчанию `'value'`). */
|
|
28
|
+
valueProp?: string;
|
|
29
|
+
/** Колбэк, через который контрол эмитит изменение (по умолчанию `'onChange'`). */
|
|
30
|
+
changeProp?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Эмит контрола → значение поля (по умолчанию — как есть). `rest` — прочие props контрола
|
|
33
|
+
* (например, чтобы достать `options` при резолве значения).
|
|
34
|
+
*/
|
|
35
|
+
fromEmit?: (arg: unknown, rest: Record<string, unknown>) => unknown;
|
|
36
|
+
/** Значение поля → `valueProp` контрола (коэрсия `null`/`undefined`; по умолчанию — как есть). */
|
|
37
|
+
toValue?: (value: unknown) => unknown;
|
|
38
|
+
/** Проброс blur нестандартным каналом (по умолчанию — `onBlur`). */
|
|
39
|
+
bindBlur?: (onBlur: () => void) => Record<string, unknown>;
|
|
40
|
+
/** Ключи, которые убрать из `componentProps` перед спредом в контрол. */
|
|
41
|
+
strip?: string[];
|
|
42
|
+
/**
|
|
43
|
+
* Передавать ли контролу ноду формы пропом `control` (только рендерер). По умолчанию `false`:
|
|
44
|
+
* issues/touched обслуживает обёртка поля. Ставь `true`, если контрол сам вызывает
|
|
45
|
+
* `useFormControl(control)`.
|
|
46
|
+
*/
|
|
47
|
+
passControl?: boolean;
|
|
48
|
+
}
|
|
49
|
+
/** Компонент, объявивший свой диалект статикой. */
|
|
50
|
+
export interface FieldAdapterCarrier {
|
|
51
|
+
reformerAdapter?: FieldAdapter;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Props, которые адресованы обёртке поля, а не контролу: `labelTooltip` рисует `FormField` у
|
|
55
|
+
* подписи. Они приходят в общем мешке `componentProps`, и без среза утекли бы в DOM контрола.
|
|
56
|
+
*/
|
|
57
|
+
export declare const FIELD_WRAPPER_ONLY_PROPS: readonly string[];
|
|
58
|
+
/**
|
|
59
|
+
* Адаптер, объявленный компонентом статикой `reformerAdapter`, либо `undefined`.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* Checkbox.reformerAdapter = checkedAdapter;
|
|
64
|
+
* getFieldAdapter(Checkbox); // → checkedAdapter
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export declare function getFieldAdapter(component: unknown): FieldAdapter | undefined;
|
|
68
|
+
/** Seam поля: текущее значение и value-based колбэки. */
|
|
69
|
+
export interface FieldSeam {
|
|
70
|
+
value: unknown;
|
|
71
|
+
onChange: (value: unknown) => void;
|
|
72
|
+
onBlur: () => void;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Props контрола под адаптер: срезает служебные ключи обёртки и `strip` адаптера, кладёт значение
|
|
76
|
+
* в `valueProp` (через `toValue`), вешает `changeProp`, который прогоняет эмит контрола через
|
|
77
|
+
* `fromEmit` в value-based `onChange` поля, и пробрасывает blur (`bindBlur` либо `onBlur`).
|
|
78
|
+
* Без адаптера seam проходит как есть (`value` / `onChange` / `onBlur`).
|
|
79
|
+
*
|
|
80
|
+
* `componentProps` спредятся ПЕРВЫМИ — seam их перекрывает при совпадении ключей.
|
|
81
|
+
*
|
|
82
|
+
* @param adapter - Адаптер контрола или `undefined` (value-based контрол).
|
|
83
|
+
* @param seam - Значение поля и его колбэки.
|
|
84
|
+
* @param componentProps - Прочие props контрола.
|
|
85
|
+
* @returns Плоский объект props для спреда в контрол.
|
|
86
|
+
*/
|
|
87
|
+
export declare function bindFieldProps(adapter: FieldAdapter | undefined, seam: FieldSeam, componentProps?: Record<string, unknown>): Record<string, unknown>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Ref, RefObject } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Базовый императивный контракт поля формы.
|
|
4
|
+
*
|
|
5
|
+
* Обёртка поля (`FormField.Control` из `@reformer/cdk`, рендерер `@reformer/renderer-react`)
|
|
6
|
+
* строит его из DOM-узла контрола. Композиты со своим handle (`open`/`close`/`reload`/…) отдают
|
|
7
|
+
* его как есть — он расширяет этот контракт.
|
|
8
|
+
*
|
|
9
|
+
* Достаётся из render-схемы по селектору:
|
|
10
|
+
* `schema.node(sel).getRef<FieldHandle>().current?.focus()`.
|
|
11
|
+
*
|
|
12
|
+
* Покрывает ТОЛЬКО императивные действия. Реактивное состояние (value / disabled / options /
|
|
13
|
+
* validation) живёт в behaviors и через handle не дублируется.
|
|
14
|
+
*/
|
|
15
|
+
export interface FieldHandle {
|
|
16
|
+
/** Сфокусировать поле (делегирует на DOM-элемент контрола). */
|
|
17
|
+
focus(): void;
|
|
18
|
+
/** Снять фокус. */
|
|
19
|
+
blur(): void;
|
|
20
|
+
/** Проскроллить поле в область видимости. */
|
|
21
|
+
scrollIntoView(opts?: ScrollIntoViewOptions): void;
|
|
22
|
+
/** Живой DOM-элемент поля (или `null` до монтирования / для размонтированной ноды). */
|
|
23
|
+
getElement(): HTMLElement | null;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Собирает базовый {@link FieldHandle}, делегирующий на DOM-элемент по ссылке `el`.
|
|
27
|
+
* Все вызовы null-safe: до монтирования (`el.current === null`) — no-op, без исключений.
|
|
28
|
+
*/
|
|
29
|
+
export declare function makeElementFieldHandle(el: RefObject<HTMLElement | null>): FieldHandle;
|
|
30
|
+
/**
|
|
31
|
+
* Ref для контрола поля + императивный handle для потребителя.
|
|
32
|
+
*
|
|
33
|
+
* Возвращённый ref вешается на контрол. На `outerRef` публикуется:
|
|
34
|
+
* - handle самого контрола, если тот его реализует (`useImperativeHandle` композита);
|
|
35
|
+
* - иначе — базовый {@link FieldHandle}, построенный из DOM-узла контрола.
|
|
36
|
+
*
|
|
37
|
+
* Хук вызывается безусловно; вешать ref на контрол стоит только при заданном `outerRef` —
|
|
38
|
+
* так function-компонент без ref-поддержки не получает лишний ref.
|
|
39
|
+
*
|
|
40
|
+
* @param outerRef - ref потребителя (из `forwardRef` или `schema.node(sel).getRef()`).
|
|
41
|
+
* @returns ref, который нужно передать контролу.
|
|
42
|
+
*/
|
|
43
|
+
export declare function useFieldHandleRef<H = FieldHandle>(outerRef: Ref<H> | undefined): RefObject<unknown>;
|
|
44
|
+
/**
|
|
45
|
+
* Что публиковать потребителю по ref контрола: handle композита как есть, иначе (DOM-узел или
|
|
46
|
+
* ещё пусто) — базовый {@link FieldHandle}, читающий узел лениво из `inner`. С `cache` базовый
|
|
47
|
+
* handle создаётся один раз и дальше переиспользуется.
|
|
48
|
+
*
|
|
49
|
+
* @internal Экспортируется для юнит-тестов.
|
|
50
|
+
*/
|
|
51
|
+
export declare function resolveFieldHandle(inner: RefObject<unknown>, cache?: {
|
|
52
|
+
current: FieldHandle | null;
|
|
53
|
+
}): unknown;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { FormBundle } from '../../form/form-bundle';
|
|
2
|
+
/**
|
|
3
|
+
* Контекст сборки. Значение — бандл `createForm`; вне рендерера — `null`.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```tsx
|
|
7
|
+
* <FormBundleContext.Provider value={bundle}>
|
|
8
|
+
* <MyWizard />
|
|
9
|
+
* </FormBundleContext.Provider>
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export declare const FormBundleContext: import('react').Context<FormBundle<any> | null>;
|
|
13
|
+
/**
|
|
14
|
+
* Бандл сборки, внутри которой отрисован компонент; `null` — компонент стоит вне рендерера
|
|
15
|
+
* (например, визард в разметке React-руками получает форму и поток шагов пропсами).
|
|
16
|
+
*
|
|
17
|
+
* @typeParam T - Форма данных модели.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* function StepFooter() {
|
|
22
|
+
* const bundle = useFormBundleContext<CreditForm>();
|
|
23
|
+
* return <button onClick={() => void bundle?.validate()}>Проверить</button>;
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function useFormBundleContext<T = unknown>(): FormBundle<T> | null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ValidationIssue } from '../../../form/types/index';
|
|
2
2
|
/**
|
|
3
|
-
* Состояние поля формы, возвращаемое хуком {@link useFormControl} для {@link
|
|
3
|
+
* Состояние поля формы, возвращаемое хуком {@link useFormControl} для {@link FormControl}.
|
|
4
4
|
*
|
|
5
5
|
* Содержит реактивные данные поля: значение, состояние валидации, флаги взаимодействия
|
|
6
6
|
* и пользовательские props для компонентов.
|
|
@@ -10,11 +10,12 @@ import { ValidationError } from '../types/index';
|
|
|
10
10
|
* @example Базовое использование
|
|
11
11
|
* ```tsx
|
|
12
12
|
* interface Props {
|
|
13
|
-
* control:
|
|
13
|
+
* control: FormControl<string>;
|
|
14
14
|
* }
|
|
15
15
|
*
|
|
16
16
|
* function TextField({ control }: Props) {
|
|
17
17
|
* const state = useFormControl(control);
|
|
18
|
+
* const message = useIssueMessage(); // из '@reformer/core/react'
|
|
18
19
|
*
|
|
19
20
|
* return (
|
|
20
21
|
* <div>
|
|
@@ -23,8 +24,8 @@ import { ValidationError } from '../types/index';
|
|
|
23
24
|
* disabled={state.disabled}
|
|
24
25
|
* onChange={e => control.setValue(e.target.value)}
|
|
25
26
|
* />
|
|
26
|
-
* {state.
|
|
27
|
-
* <span className="error">{state.
|
|
27
|
+
* {state.shouldShowIssues && state.issues[0] && (
|
|
28
|
+
* <span className="error">{message(state.issues[0])}</span>
|
|
28
29
|
* )}
|
|
29
30
|
* </div>
|
|
30
31
|
* );
|
|
@@ -88,21 +89,22 @@ export interface FieldControlState<T> {
|
|
|
88
89
|
*
|
|
89
90
|
* @example
|
|
90
91
|
* ```tsx
|
|
91
|
-
* const {
|
|
92
|
+
* const { issues } = useFormControl(field);
|
|
93
|
+
* const message = useIssueMessage(); // из '@reformer/core/react'
|
|
92
94
|
*
|
|
93
95
|
* return (
|
|
94
96
|
* <ul className="error-list">
|
|
95
|
-
* {
|
|
96
|
-
* <li key={i}>{error
|
|
97
|
+
* {issues.map((error, i) => (
|
|
98
|
+
* <li key={i}>{message(error)}</li>
|
|
97
99
|
* ))}
|
|
98
100
|
* </ul>
|
|
99
101
|
* );
|
|
100
102
|
* ```
|
|
101
103
|
*/
|
|
102
|
-
|
|
104
|
+
issues: ValidationIssue[];
|
|
103
105
|
/**
|
|
104
106
|
* Флаг валидности поля.
|
|
105
|
-
* `true` когда поле прошло все валидации (
|
|
107
|
+
* `true` когда поле прошло все валидации (issues.length === 0).
|
|
106
108
|
*
|
|
107
109
|
* @example
|
|
108
110
|
* ```tsx
|
|
@@ -116,7 +118,7 @@ export interface FieldControlState<T> {
|
|
|
116
118
|
valid: boolean;
|
|
117
119
|
/**
|
|
118
120
|
* Флаг невалидности поля.
|
|
119
|
-
* `true` когда есть ошибки валидации (
|
|
121
|
+
* `true` когда есть ошибки валидации (issues.length > 0).
|
|
120
122
|
* Противоположность {@link valid}.
|
|
121
123
|
*
|
|
122
124
|
* @example
|
|
@@ -146,27 +148,44 @@ export interface FieldControlState<T> {
|
|
|
146
148
|
*/
|
|
147
149
|
touched: boolean;
|
|
148
150
|
/**
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
+
* Показывать ли состояние ошибки — `aria-invalid`, рамку: поле невалидно и его трогали или
|
|
152
|
+
* меняли. Предупреждение (`severity: 'warning'`) поле невалидным не делает, поэтому для текстов
|
|
153
|
+
* замечаний есть {@link FieldControlState.shouldShowIssues}.
|
|
151
154
|
*
|
|
152
155
|
* @example
|
|
153
156
|
* ```tsx
|
|
154
|
-
* const { shouldShowError
|
|
157
|
+
* const { shouldShowError } = useFormControl(field);
|
|
158
|
+
*
|
|
159
|
+
* return <input {...props} aria-invalid={shouldShowError} />;
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
shouldShowError: boolean;
|
|
163
|
+
/**
|
|
164
|
+
* Показывать ли тексты замечаний: у поля есть замечания — ошибки или предупреждения, — и его
|
|
165
|
+
* трогали или меняли.
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```tsx
|
|
169
|
+
* const { shouldShowError, shouldShowIssues, issues } = useFormControl(field);
|
|
170
|
+
* const message = useIssueMessage(); // из '@reformer/core/react'
|
|
155
171
|
*
|
|
156
172
|
* return (
|
|
157
173
|
* <div>
|
|
158
|
-
* <input {...props} />
|
|
159
|
-
* {
|
|
160
|
-
*
|
|
161
|
-
*
|
|
174
|
+
* <input {...props} aria-invalid={shouldShowError} />
|
|
175
|
+
* {shouldShowIssues &&
|
|
176
|
+
* issues.map((issue) => (
|
|
177
|
+
* <span key={issue.code} className={issue.severity === 'warning' ? 'warning' : 'error'}>
|
|
178
|
+
* {message(issue)}
|
|
179
|
+
* </span>
|
|
180
|
+
* ))}
|
|
162
181
|
* </div>
|
|
163
182
|
* );
|
|
164
183
|
* ```
|
|
165
184
|
*/
|
|
166
|
-
|
|
185
|
+
shouldShowIssues: boolean;
|
|
167
186
|
/**
|
|
168
187
|
* Пользовательские props для передачи в UI-компоненты.
|
|
169
|
-
* Устанавливаются через {@link
|
|
188
|
+
* Устанавливаются через {@link FormControl.updateComponentProps}.
|
|
170
189
|
*
|
|
171
190
|
* @example
|
|
172
191
|
* ```tsx
|
|
@@ -207,7 +226,7 @@ export interface FieldControlState<T> {
|
|
|
207
226
|
dirty: boolean;
|
|
208
227
|
}
|
|
209
228
|
/**
|
|
210
|
-
* Состояние массива формы, возвращаемое хуком {@link useFormControl} для {@link
|
|
229
|
+
* Состояние массива формы, возвращаемое хуком {@link useFormControl} для {@link FormArray}.
|
|
211
230
|
*
|
|
212
231
|
* Содержит реактивные данные массива: значения элементов, длину, состояние валидации
|
|
213
232
|
* и флаги взаимодействия.
|
|
@@ -222,7 +241,7 @@ export interface FieldControlState<T> {
|
|
|
222
241
|
* }
|
|
223
242
|
*
|
|
224
243
|
* interface Props {
|
|
225
|
-
* control:
|
|
244
|
+
* control: FormArray<Phone>;
|
|
226
245
|
* }
|
|
227
246
|
*
|
|
228
247
|
* function PhoneList({ control }: Props) {
|
|
@@ -232,7 +251,7 @@ export interface FieldControlState<T> {
|
|
|
232
251
|
* <div>
|
|
233
252
|
* {control.map((item, index) => (
|
|
234
253
|
* <PhoneItem
|
|
235
|
-
* key={
|
|
254
|
+
* key={control.keyAt(index)}
|
|
236
255
|
* control={item}
|
|
237
256
|
* onRemove={() => control.removeAt(index)}
|
|
238
257
|
* />
|
|
@@ -244,7 +263,7 @@ export interface FieldControlState<T> {
|
|
|
244
263
|
* Add Phone
|
|
245
264
|
* </button>
|
|
246
265
|
*
|
|
247
|
-
* {!valid && <p className="error">Please fix phone
|
|
266
|
+
* {!valid && <p className="error">Please fix phone issues</p>}
|
|
248
267
|
* </div>
|
|
249
268
|
* );
|
|
250
269
|
* }
|
|
@@ -290,23 +309,24 @@ export interface ArrayControlState<T> {
|
|
|
290
309
|
*/
|
|
291
310
|
pending: boolean;
|
|
292
311
|
/**
|
|
293
|
-
*
|
|
294
|
-
* Не включает ошибки отдельных элементов.
|
|
312
|
+
* Замечания массива: собственные (правила на ручке массива) и замечания всех его строк.
|
|
295
313
|
*
|
|
296
314
|
* @example
|
|
297
315
|
* ```tsx
|
|
298
|
-
* //
|
|
299
|
-
*
|
|
300
|
-
* validator: (phones) => phones.length >= 1,
|
|
301
|
-
* message: 'At least one phone required'
|
|
302
|
-
* });
|
|
316
|
+
* // Правило массива — в схеме валидации
|
|
317
|
+
* validate(model.$.phones, [minLength(1, { code: 'phones.minLength' })]);
|
|
303
318
|
*
|
|
304
319
|
* // В компоненте
|
|
305
|
-
* const {
|
|
306
|
-
* //
|
|
320
|
+
* const { issues } = useFormControl(phonesArray);
|
|
321
|
+
* // для пустого массива issues содержит замечание с кодом 'phones.minLength'
|
|
307
322
|
* ```
|
|
308
323
|
*/
|
|
309
|
-
|
|
324
|
+
issues: ValidationIssue[];
|
|
325
|
+
/**
|
|
326
|
+
* Собственные замечания массива — только правила на его ручке (`minLength` и т.п.), без
|
|
327
|
+
* замечаний строк. Их показывает ошибка уровня массива (`FieldArray.Error`).
|
|
328
|
+
*/
|
|
329
|
+
ownIssues: ValidationIssue[];
|
|
310
330
|
/**
|
|
311
331
|
* Флаг валидности массива и всех его элементов.
|
|
312
332
|
* `true` только когда массив и все вложенные элементы валидны.
|
|
@@ -324,7 +344,9 @@ export interface ArrayControlState<T> {
|
|
|
324
344
|
touched: boolean;
|
|
325
345
|
/**
|
|
326
346
|
* Флаг изменения.
|
|
327
|
-
* `true`
|
|
347
|
+
* `true` после правки любого элемента или изменения состава через форму (`push`, `removeAt`,
|
|
348
|
+
* `move`, `setValue`…). Как у поля, запись в модель (загрузка данных) и операция, которая состав
|
|
349
|
+
* не поменяла, изменением не считаются; снимает `reset`.
|
|
328
350
|
*
|
|
329
351
|
* @example
|
|
330
352
|
* ```tsx
|
|
@@ -341,7 +363,7 @@ export interface ArrayControlState<T> {
|
|
|
341
363
|
dirty: boolean;
|
|
342
364
|
/**
|
|
343
365
|
* Флаг отключения массива.
|
|
344
|
-
* `true` когда массив отключён (`
|
|
366
|
+
* `true` когда массив отключён (`FormArray.disable()`), в том числе через
|
|
345
367
|
* распространение disable от родительской группы.
|
|
346
368
|
*
|
|
347
369
|
* Используйте для отключения UI-действий добавления/удаления, когда массив
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { FormValidationController } from '../../../form/validation/strategy';
|
|
2
|
+
/** Минимум, который хук ожидает от бандла: контроллер живой валидации и снятие — оба опционально. */
|
|
3
|
+
export interface FormBundleLike {
|
|
4
|
+
validation?: {
|
|
5
|
+
controller: FormValidationController;
|
|
6
|
+
};
|
|
7
|
+
/** Снять сборку: поведение, подписки нод, живую проверку. Есть у всех фабрик семейства. */
|
|
8
|
+
dispose?(): void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Собрать форму один раз и держать её стабильной; живую стратегию валидации армировать в эффекте
|
|
12
|
+
* (не при SSR — там эффекты не выполняются); при размонтировании снять сборку.
|
|
13
|
+
*
|
|
14
|
+
* @typeParam B - Тип бандла конкретной фабрики.
|
|
15
|
+
* @param factory - Фабрика бандла, обычно `() => createForm({…})`. Сборкой владеет хук: при
|
|
16
|
+
* размонтировании он вызывает её `dispose()`, поэтому фабрика должна собирать НОВУЮ форму, а не
|
|
17
|
+
* возвращать чужую, живущую дольше компонента.
|
|
18
|
+
* @returns Стабильный бандл.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* const credit = useFormBundle(() => createForm<CreditForm>({ model: createCreditModel() }));
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @remarks
|
|
26
|
+
* Передавайте именно фабрику: `useState` трактует функцию как ленивый инициализатор, а некоторые
|
|
27
|
+
* части бандла сами являются функциями (`RenderSchemaProxy`), поэтому `useFormBundle(bundle.render)`
|
|
28
|
+
* вызвал бы её вместо сохранения.
|
|
29
|
+
*
|
|
30
|
+
* Сборка снимается микрозадачей после размонтирования, а не в самой очистке эффекта (см. шапку
|
|
31
|
+
* модуля): код, который сразу после размонтирования пишет в модель, ещё видит живое поведение.
|
|
32
|
+
*
|
|
33
|
+
* **Ограничение StrictMode (только разработка).** StrictMode вызывает ленивый инициализатор
|
|
34
|
+
* `useState` дважды, и фабрика на монтирование срабатывает два раза. Второй бандл React
|
|
35
|
+
* выбрасывает до коммита: хук его не видит, поэтому не армирует и не снимает. Живая проверка у
|
|
36
|
+
* него не запущена, но поведение (`compute`, `onChange`, …) работает, пока бандл не соберёт
|
|
37
|
+
* сборщик мусора. В production инициализатор вызывается один раз и утечки нет. Побочные эффекты
|
|
38
|
+
* на создание (запрос данных в фабрике или в `setup`) в разработке поэтому тоже срабатывают
|
|
39
|
+
* дважды — запускайте их из поведения формы или из эффекта компонента.
|
|
40
|
+
*/
|
|
41
|
+
export declare function useFormBundle<B extends FormBundleLike>(factory: () => B): B;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { FormFlow } from '../../../form/flow/flow';
|
|
2
|
+
/**
|
|
3
|
+
* Состояние потока на момент рендера.
|
|
4
|
+
*
|
|
5
|
+
* @group React
|
|
6
|
+
*/
|
|
7
|
+
export interface FormFlowSnapshot {
|
|
8
|
+
/** Текущий шаг. */
|
|
9
|
+
readonly current: string;
|
|
10
|
+
/** Номер текущего шага с нуля. */
|
|
11
|
+
readonly index: number;
|
|
12
|
+
/** Пройденные шаги. */
|
|
13
|
+
readonly completed: ReadonlySet<string>;
|
|
14
|
+
readonly isFirst: boolean;
|
|
15
|
+
readonly isLast: boolean;
|
|
16
|
+
/** Идёт ли проверка шага. */
|
|
17
|
+
readonly validating: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Подписаться на поток шагов: компонент перерисовывается при смене шага, пройденных шагов и
|
|
21
|
+
* состояния проверки. Переходы — методами самого потока (`flow.next()`, `flow.goTo(id)`).
|
|
22
|
+
*
|
|
23
|
+
* @param flow - Поток шагов (`bundle.flow`).
|
|
24
|
+
* @returns {@link FormFlowSnapshot}.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```tsx
|
|
28
|
+
* function Steps({ flow }: { flow: FormFlow }) {
|
|
29
|
+
* const { current, isLast, validating } = useFormFlow(flow);
|
|
30
|
+
* return (
|
|
31
|
+
* <button disabled={isLast || validating} onClick={() => void flow.next()}>
|
|
32
|
+
* Далее ({current})
|
|
33
|
+
* </button>
|
|
34
|
+
* );
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @group React
|
|
39
|
+
*/
|
|
40
|
+
export declare function useFormFlow(flow: FormFlow): FormFlowSnapshot;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { FormModel } from '
|
|
2
|
-
import {
|
|
3
|
-
import { ValidationStrategyKind } from '
|
|
1
|
+
import { FormModel } from '../../../model/types';
|
|
2
|
+
import { ValidationDefinition } from '../../../form/validation';
|
|
3
|
+
import { ValidationStrategyKind } from '../../../form/validation/strategy';
|
|
4
4
|
export interface UseFormValidationArgs<T> {
|
|
5
5
|
/** Модель данных формы. */
|
|
6
6
|
model: FormModel<T>;
|
|
7
7
|
/** Схема валидации. **Стабильная ссылка** (module-level `const` / `useMemo`) — иначе ломается дедуп раннера. */
|
|
8
|
-
schema:
|
|
8
|
+
schema: ValidationDefinition<T>;
|
|
9
9
|
/** Стратегия запуска. Default `'submit'`. */
|
|
10
10
|
strategy?: ValidationStrategyKind;
|
|
11
11
|
/** Debounce (мс) для live-фаз (`change` / live-часть `afterFirstSubmit`). */
|
|
@@ -14,9 +14,15 @@ export interface UseFormValidationArgs<T> {
|
|
|
14
14
|
liveAfterSubmit?: 'change' | 'blur';
|
|
15
15
|
}
|
|
16
16
|
export interface UseFormValidationResult {
|
|
17
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* Попытка отправки: полный прогон; при замечаниях раскрыта вся форма, `afterFirstSubmit`
|
|
19
|
+
* переходит в живую фазу. `true` — только статус `valid`. Для `onSubmit`. Стабильная ссылка.
|
|
20
|
+
*/
|
|
18
21
|
submit: () => Promise<boolean>;
|
|
19
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* Проверка без отправки: полный прогон, раскрыты замечания проверенных полей, фаза
|
|
24
|
+
* `afterFirstSubmit` не меняется. Для кнопки «Проверить». Стабильная ссылка.
|
|
25
|
+
*/
|
|
20
26
|
validate: () => Promise<boolean>;
|
|
21
27
|
/** Идёт ли прогон (submit или live) — для блокировки кнопки. */
|
|
22
28
|
isValidating: boolean;
|
|
@@ -31,7 +37,7 @@ export interface UseFormValidationResult {
|
|
|
31
37
|
*
|
|
32
38
|
* @example
|
|
33
39
|
* ```tsx
|
|
34
|
-
* const validation =
|
|
40
|
+
* const validation = defineValidation<Form>(({ model }) => { ... }); // module-level
|
|
35
41
|
*
|
|
36
42
|
* function MyForm() {
|
|
37
43
|
* const { submit, isValidating } = useFormValidation({
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FormArray } from '../../../form/types/index';
|
|
2
2
|
/**
|
|
3
3
|
* React-хук для подписки только на длину массива.
|
|
4
4
|
*
|
|
5
|
-
* Оптимизированная версия {@link useFormControl} для
|
|
6
|
-
* подписывается только на
|
|
5
|
+
* Оптимизированная версия {@link useFormControl} для FormArray, которая
|
|
6
|
+
* подписывается только на длину массива. Компонент не будет ре-рендериться
|
|
7
7
|
* при изменении значений вложенных полей.
|
|
8
8
|
*
|
|
9
9
|
* @typeParam T - Тип элемента массива
|
|
10
|
-
* @param control -
|
|
10
|
+
* @param control - FormArray для подписки
|
|
11
11
|
* @returns Текущая длина массива
|
|
12
12
|
*
|
|
13
13
|
* @example
|
|
@@ -18,7 +18,7 @@ import { ArrayNode } from '../nodes/array-node';
|
|
|
18
18
|
* return (
|
|
19
19
|
* <div>
|
|
20
20
|
* {arrayNode.map((item, index) => (
|
|
21
|
-
* <ItemRenderer key={
|
|
21
|
+
* <ItemRenderer key={arrayNode.keyAt(index)} item={item} />
|
|
22
22
|
* ))}
|
|
23
23
|
* </div>
|
|
24
24
|
* );
|
|
@@ -27,4 +27,4 @@ import { ArrayNode } from '../nodes/array-node';
|
|
|
27
27
|
*
|
|
28
28
|
* @group React Hooks
|
|
29
29
|
*/
|
|
30
|
-
export declare function useArrayLength<T extends object>(control:
|
|
30
|
+
export declare function useArrayLength<T extends object>(control: FormArray<T>): number;
|
|
@@ -1,24 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ArrayNode } from '../nodes/array-node';
|
|
3
|
-
import { FormValue } from '../types/index';
|
|
1
|
+
import { FormArray, FormControl } from '../../../form/types/index';
|
|
4
2
|
import { FieldControlState, ArrayControlState } from './types';
|
|
5
3
|
/**
|
|
6
|
-
* React-хук для подписки на состояние {@link
|
|
4
|
+
* React-хук для подписки на состояние {@link FormArray}.
|
|
7
5
|
*
|
|
8
6
|
* @typeParam T - Тип элемента массива
|
|
9
|
-
* @param control -
|
|
7
|
+
* @param control - FormArray или undefined
|
|
10
8
|
* @returns Состояние массива {@link ArrayControlState}
|
|
11
9
|
*
|
|
12
10
|
* @group React Hooks
|
|
13
11
|
*/
|
|
14
|
-
export declare function useFormControl<T extends object>(control:
|
|
12
|
+
export declare function useFormControl<T extends object>(control: FormArray<T> | undefined): ArrayControlState<T>;
|
|
15
13
|
/**
|
|
16
|
-
* React-хук для подписки на состояние {@link
|
|
14
|
+
* React-хук для подписки на состояние {@link FormControl}.
|
|
17
15
|
*
|
|
18
16
|
* @typeParam T - Тип значения поля
|
|
19
|
-
* @param control -
|
|
17
|
+
* @param control - FormControl для подписки
|
|
20
18
|
* @returns Состояние поля {@link FieldControlState}
|
|
21
19
|
*
|
|
22
20
|
* @group React Hooks
|
|
23
21
|
*/
|
|
24
|
-
export declare function useFormControl<T
|
|
22
|
+
export declare function useFormControl<T>(control: FormControl<T>): FieldControlState<T>;
|