@reformer/core 10.1.0 → 11.0.0-beta.1

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.
Files changed (67) hide show
  1. package/dist/{behaviors-node-DUrqAqp1.js → behaviors-node-DGEFMTQu.js} +1 -1
  2. package/dist/{behaviors-value-lCpqicfa.js → behaviors-value-C7dSEhCc.js} +43 -57
  3. package/dist/behaviors.js +108 -107
  4. package/dist/derived-registry-CluZCQ7U.js +16 -0
  5. package/dist/form/form-submitter.d.ts +0 -4
  6. package/dist/form/hooks/types.d.ts +3 -3
  7. package/dist/form/hooks/use-form-validation.d.ts +48 -0
  8. package/dist/form/index.d.ts +2 -3
  9. package/dist/form/nodes/array-node.d.ts +0 -84
  10. package/dist/form/nodes/form-node.d.ts +0 -14
  11. package/dist/form/nodes/group-node.d.ts +0 -4
  12. package/dist/form/status-machine.d.ts +0 -38
  13. package/dist/form/types/contracts.d.ts +0 -6
  14. package/dist/form/types/deep-schema.d.ts +0 -9
  15. package/dist/form/types/index.d.ts +4 -38
  16. package/dist/form/types/schema-node.d.ts +13 -16
  17. package/dist/form/types/validation-schema.d.ts +0 -25
  18. package/dist/form/unique-id.d.ts +3 -11
  19. package/dist/form/validation-schema.d.ts +16 -3
  20. package/dist/form/validation-strategy.d.ts +55 -0
  21. package/dist/form/validators.d.ts +8 -3
  22. package/dist/form-model-DYCzGGKF.js +286 -0
  23. package/dist/index.d.ts +1 -1
  24. package/dist/index.js +477 -648
  25. package/dist/runtime-token.d.ts +23 -0
  26. package/dist/state/form-model.d.ts +12 -1
  27. package/dist/state.js +17 -15
  28. package/dist/subscription-manager-705bls97.js +171 -0
  29. package/dist/validation.js +133 -81
  30. package/dist/validators.d.ts +0 -4
  31. package/dist/validators.js +88 -122
  32. package/docs/llms/01-api-reference.md +63 -0
  33. package/docs/llms/02-quick-start.md +143 -0
  34. package/docs/llms/03-api-signatures.md +273 -0
  35. package/docs/llms/04-common-patterns.md +202 -0
  36. package/docs/llms/05-common-mistakes.md +167 -0
  37. package/docs/llms/06-troubleshooting.md +11 -0
  38. package/docs/llms/07-complete-import.md +99 -0
  39. package/docs/llms/08-form-types.md +47 -0
  40. package/docs/llms/09-formschema.md +143 -0
  41. package/docs/llms/10-arrays.md +161 -0
  42. package/docs/llms/11-async-watchfield.md +53 -0
  43. package/docs/llms/12-array-cleanup.md +31 -0
  44. package/docs/llms/13-multi-step.md +91 -0
  45. package/docs/llms/14-extended-mistakes.md +98 -0
  46. package/docs/llms/15-project-structure.md +125 -0
  47. package/docs/llms/16-ui-components.md +189 -0
  48. package/docs/llms/17-nonexistent-api.md +93 -0
  49. package/docs/llms/18-conditional-fields.md +183 -0
  50. package/docs/llms/19-reading-values.md +59 -0
  51. package/docs/llms/20-compute-vs-watch.md +138 -0
  52. package/docs/llms/21-array-operations.md +113 -0
  53. package/docs/llms/22-cycle-detection.md +86 -0
  54. package/docs/llms/23-copy-from.md +141 -0
  55. package/docs/llms/24-sync-fields.md +114 -0
  56. package/docs/llms/25-reset-when.md +115 -0
  57. package/docs/llms/26-transform-value.md +136 -0
  58. package/docs/llms/27-revalidate-when.md +132 -0
  59. package/docs/llms/28-submit-and-reset.md +259 -0
  60. package/docs/llms/29-async-preload.md +193 -0
  61. package/docs/llms/30-type-safety-recipes.md +159 -0
  62. package/docs/llms/31-async-validator-debounce.md +135 -0
  63. package/docs/llms/32-async-options-loading.md +108 -0
  64. package/docs/llms/33-validation-strategy.md +193 -0
  65. package/llms.txt +435 -1580
  66. package/package.json +33 -10
  67. package/dist/form-model-C8Fi83k4.js +0 -439
package/llms.txt CHANGED
@@ -37,6 +37,7 @@
37
37
  - 30-type-safety-recipes.md — type-safety-recipes
38
38
  - 31-async-validator-debounce.md — async-validator-debounce
39
39
  - 32-async-options-loading.md — async-options-loading
40
+ - 33-validation-strategy.md — useFormValidation — Единый выбор стратегии валидации
40
41
  - API Reference (auto-generated from JSDoc)
41
42
 
42
43
  ## 1. 1. API Reference
@@ -4113,39 +4114,215 @@ loadOptionsOn(model.$.carBrand, form.carModel, fetchCarModels, { resetTarget: tr
4113
4114
  - [29-async-preload.md](29-async-preload.md) — preload данных при инициализации
4114
4115
  - [31-async-validator-debounce.md](31-async-validator-debounce.md) — async **валидация** (не options)
4115
4116
 
4116
- ## 77. API Reference
4117
+ ## 77. Purpose
4117
4118
 
4118
- _Auto-generated from JSDoc on public exports._
4119
+ Одна декларативная точка выбора «когда прогонять схему валидации» вместо ручной разводки
4120
+ `markAsTouched` + `validateModel` + `revalidateWhen` + `useState(pending)`. Аддитивный слой над
4121
+ функциональной схемой (`@reformer/core/validation`): переиспользует `validateModel` как
4122
+ ЕДИНСТВЕННЫЙ движок (роутинг ошибок в ноды, отмена устаревших прогонов, дедуп по `(model, schema)`),
4123
+ второго движка не заводит. Node-level `updateOn` / `debounce` на самой ноде поля (legacy-триггеры)
4124
+ этот API НЕ трогает.
4119
4125
 
4120
- ### AnyFunction
4126
+ Стратегия определяет только момент запуска и раскрытие ошибок — сами правила остаются в отдельной
4127
+ `defineValidationSchema<T>(({ model }) => …)`.
4121
4128
 
4122
- **Kind:** `type`
4129
+ ## 78. API
4123
4130
 
4124
- Тип для проверки на функцию в conditional types
4125
- Используется вместо Function для type narrowing
4131
+ Основной способ — React-хук `useFormValidation` из `@reformer/core` (рядом с `useFormControl`).
4132
+ Под ним — headless-фабрика `createFormValidation` из `@reformer/core/validation` (для SSR / тестов /
4133
+ не-React потребителей).
4126
4134
 
4127
- **Signature:**
4128
4135
  ```typescript
4129
- export type AnyFunction = (...args: never[]) => unknown;
4136
+ // React (@reformer/core)
4137
+ function useFormValidation<T>(args: {
4138
+ model: FormModel<T>;
4139
+ schema: ValidationSchema<T>; // СТАБИЛЬНАЯ ссылка (module-level const / useMemo)
4140
+ strategy?: ValidationStrategyKind; // default 'submit'
4141
+ debounce?: number; // мс, для live-фаз (change / live-часть afterFirstSubmit)
4142
+ liveAfterSubmit?: 'change' | 'blur'; // default 'change'
4143
+ }): { submit: () => Promise<boolean>; validate: () => Promise<boolean>; isValidating: boolean };
4144
+
4145
+ // headless (@reformer/core/validation)
4146
+ type ValidationStrategyKind = 'submit' | 'blur' | 'change' | 'afterFirstSubmit';
4147
+ interface ValidationStrategyOptions {
4148
+ strategy?: ValidationStrategyKind;
4149
+ debounce?: number;
4150
+ liveAfterSubmit?: 'change' | 'blur';
4151
+ }
4152
+ interface FormValidationController {
4153
+ validate(): Promise<boolean>; // полный прогон, touch:true (раскрыть ВСЕ ошибки); переводит afterFirstSubmit в live-фазу
4154
+ start(): () => void; // армит реактивные подписки (ТОЛЬКО на клиенте) → dispose
4155
+ dispose(): void;
4156
+ readonly isValidating: boolean;
4157
+ readonly validating: ReadonlySignal<boolean>;
4158
+ }
4159
+ function createFormValidation<T>(
4160
+ model: FormModel<T>,
4161
+ schema: ValidationSchema<T>,
4162
+ options?: ValidationStrategyOptions,
4163
+ ): FormValidationController;
4130
4164
  ```
4131
4165
 
4132
- _Source: src/form/types/index.ts_
4166
+ - `useFormValidation` мемоизирует контроллер по `[model, schema, strategy, debounce, liveAfterSubmit]`,
4167
+ армит стратегию в `useEffect` (SSR-safe), а `submit()` = `controller.validate()`.
4168
+ - `createFormValidation` ЧИСТА до `start()` (никаких подписок) → SSR-safe; `start()` возвращает
4169
+ `dispose` и арминует триггеры только на клиенте.
4133
4170
 
4134
- ### ArrayConfig
4171
+ ### Стратегии
4135
4172
 
4136
- **Kind:** `interface`
4173
+ | strategy | когда прогон | touch | раскрытие ошибок |
4174
+ | --- | --- | --- | --- |
4175
+ | `submit` (default) | только `validate()` / `submit()` | `true` | всё на submit |
4176
+ | `blur` | смена `touched` поля (потеря фокуса) | `false` | только сблюренные (по `touched`) |
4177
+ | `change` | на каждый ввод (+ `debounce`) | `false` | только редактированные (по `dirty`) |
4178
+ | `afterFirstSubmit` | тихо до 1-го submit, затем live (`liveAfterSubmit: 'change'` \| `'blur'`, default `'change'`) | `true` один раз на 1-м submit, дальше `false` | тихо → раскрыть всё на submit → далее live |
4137
4179
 
4138
- Конфигурация массива
4180
+ ## 79. Examples
4181
+
4182
+ ### Простая форма — afterFirstSubmit + debounce
4183
+
4184
+ Тихо до первой отправки, `submit()` раскрывает все ошибки и переводит форму в живую фазу
4185
+ (дальше проверка на ввод с задержкой 400 мс). `submit()` сам метит `touched` — ручной
4186
+ `markAsTouched` не нужен.
4187
+
4188
+ ```tsx
4189
+ import { createModel, createForm, useFormValidation } from '@reformer/core';
4190
+ import { defineValidationSchema, validate } from '@reformer/core/validation';
4191
+ import { required, email, minLength } from '@reformer/core/validators';
4192
+
4193
+ type RegistrationData = { username: string; email: string; password: string };
4194
+
4195
+ // Схема — стабильный module-level const (иначе ломается дедуп раннера).
4196
+ const registrationValidation = defineValidationSchema<RegistrationData>(({ model }) => {
4197
+ validate(model.$.username, [required(), minLength(3)]);
4198
+ validate(model.$.email, [required(), email()]);
4199
+ validate(model.$.password, [required(), minLength(8)]);
4200
+ });
4201
+
4202
+ function RegistrationForm() {
4203
+ const model = useMemo(() => createModel<RegistrationData>({ username: '', email: '', password: '' }), []);
4204
+ const form = useMemo(() => createForm({ model }), [model]);
4205
+
4206
+ const { submit, isValidating } = useFormValidation({
4207
+ model,
4208
+ schema: registrationValidation,
4209
+ strategy: 'afterFirstSubmit',
4210
+ debounce: 400,
4211
+ });
4212
+
4213
+ const onSubmit = async (e: React.FormEvent) => {
4214
+ e.preventDefault();
4215
+ if (await submit()) await api.save(model.get()); // true = нет блокирующих ошибок
4216
+ };
4217
+
4218
+ return (
4219
+ <form onSubmit={onSubmit}>
4220
+ <FormField control={form.username} />
4221
+ <FormField control={form.email} />
4222
+ <FormField control={form.password} />
4223
+ <button type="submit" disabled={isValidating}>Отправить</button>
4224
+ </form>
4225
+ );
4226
+ }
4227
+ ```
4228
+
4229
+ ### Wizard — live-стратегия внутри активного шага
4230
+
4231
+ `defineSteps(..., { strategy })` задаёт ЖИВУЮ стратегию ВНУТРИ шага; `useWizardStepValidation`
4232
+ арминует её под текущий шаг (`currentStep` из `FormWizardContext`) и снимает при смене шага / unmount.
4233
+ Per-step gate (`validateStep` на «Далее») и `validateAll` (submit) при этом НЕ меняются — стратегия
4234
+ добавляет живой слой ПОВЕРХ них. No-op, если `strategy` не задана / `'submit'` / у шага нет правил.
4235
+
4236
+ ```tsx
4237
+ import { defineSteps, useWizardStepValidation, FormWizard } from '@reformer/cdk/form-wizard';
4238
+
4239
+ const config = defineSteps<'loan' | 'applicant' | 'confirm', CreditForm>(model, {
4240
+ steps: { loan: loanStep, applicant: applicantStep, confirm: null }, // confirm — без правил, ЯВНО
4241
+ extras: crossFieldRules, // применяются только в validateAll (submit)
4242
+ strategy: 'blur', // живая валидация полей текущего шага при потере фокуса
4243
+ });
4244
+
4245
+ function LoanStepBody() {
4246
+ useWizardStepValidation(config); // армит 'blur' под активный шаг, снимает при переходе
4247
+ return <>{/* поля шага */}</>;
4248
+ }
4249
+
4250
+ <FormWizard form={form} config={config}>
4251
+ <LoanStepBody />
4252
+ </FormWizard>;
4253
+ ```
4254
+
4255
+ ### Headless / SSR / тесты — createFormValidation
4256
+
4257
+ ```typescript
4258
+ import { createFormValidation } from '@reformer/core/validation';
4259
+
4260
+ const ctrl = createFormValidation(model, registrationValidation, {
4261
+ strategy: 'afterFirstSubmit',
4262
+ debounce: 300,
4263
+ });
4264
+ const dispose = ctrl.start(); // ТОЛЬКО на клиенте (в React — из useEffect)
4265
+ const ok = await ctrl.validate(); // submit → раскрыть все ошибки
4266
+ dispose();
4267
+ ```
4268
+
4269
+ ## 80. Anti-patterns
4139
4270
 
4140
- **Signature:**
4141
4271
  ```typescript
4142
- export interface ArrayConfig<T extends object> {
4143
- itemSchema: FormSchema<T>;
4144
- initial?: Partial<T>[];
4272
+ // ❌ schema пересоздаётся каждый рендер → контроллер и дедуп раннера ломаются
4273
+ function MyForm() {
4274
+ const schema = defineValidationSchema<Form>(({ model }) => { … }); // новая ссылка на каждый рендер
4275
+ useFormValidation({ model, schema, strategy: 'change' });
4276
+ }
4277
+
4278
+ // ✅ Стабильная ссылка: module-level const (или useMemo с пустыми deps)
4279
+ const formValidation = defineValidationSchema<Form>(({ model }) => { … });
4280
+ function MyForm() {
4281
+ useFormValidation({ model, schema: formValidation, strategy: 'change' });
4145
4282
  }
4146
4283
  ```
4147
4284
 
4148
- _Source: src/form/types/deep-schema.ts_
4285
+ ```typescript
4286
+ // ❌ Node-level updateOn (Слой B) И активная schema-стратегия на ОДНОМ поле → оба пишут ошибки в ноду → мерцание
4287
+ // узел поля: { updateOn: 'blur', … } + useFormValidation({ strategy: 'blur', schema: включает это же поле })
4288
+
4289
+ // ✅ Одно поле обслуживает ОДИН слой: либо node-level updateOn, либо schema-стратегия — не оба сразу
4290
+ ```
4291
+
4292
+ ```typescript
4293
+ // ❌ start() на сервере — арминует реактивные подписки при SSR
4294
+ const ctrl = createFormValidation(model, schema, { strategy: 'change' });
4295
+ ctrl.start(); // на сервере подписок быть не должно
4296
+
4297
+ // ✅ Фабрика чиста до start(); армить только на клиенте (useFormValidation делает это в useEffect)
4298
+ const ctrl = createFormValidation(model, schema, { strategy: 'change' });
4299
+ if (typeof window !== 'undefined') ctrl.start();
4300
+ ```
4301
+
4302
+ ## 81. See also
4303
+
4304
+ - [28-submit-and-reset.md](./28-submit-and-reset.md) — submit-флоу и `validateModel` (движок под стратегией)
4305
+ - [27-revalidate-when.md](./27-revalidate-when.md) — ручные триггеры перевалидации (низкоуровневый примитив)
4306
+ - [31-async-validator-debounce.md](./31-async-validator-debounce.md) — async-правила и отмена устаревших прогонов
4307
+ - [13-multi-step.md](./13-multi-step.md) — per-step / полная валидация wizard (`validateStep` / `validateAll`)
4308
+
4309
+ ## 82. API Reference
4310
+
4311
+ _Auto-generated from JSDoc on public exports._
4312
+
4313
+ ### AnyFunction
4314
+
4315
+ **Kind:** `type`
4316
+
4317
+ Тип для проверки на функцию в conditional types
4318
+ Используется вместо Function для type narrowing
4319
+
4320
+ **Signature:**
4321
+ ```typescript
4322
+ export type AnyFunction = (...args: never[]) => unknown;
4323
+ ```
4324
+
4325
+ _Source: src/form/types/index.ts_
4149
4326
 
4150
4327
  ### ArrayControlState
4151
4328
 
@@ -4291,7 +4468,7 @@ return (
4291
4468
  <PhoneItem
4292
4469
  key={item.id}
4293
4470
  control={item}
4294
- onRemove={() => control.remove(index)}
4471
+ onRemove={() => control.removeAt(index)}
4295
4472
  />
4296
4473
  ))}
4297
4474
 
@@ -4359,28 +4536,6 @@ export interface ArrayNodeLike {
4359
4536
 
4360
4537
  _Source: src/form/types/index.ts_
4361
4538
 
4362
- ### AsyncValidator
4363
-
4364
- **Kind:** `type`
4365
-
4366
- Чистый асинхронный валидатор поля. Та же тройка аргументов `(value, scope, root)`, что у
4367
- {@link Validator}, но возвращает `Promise`.
4368
-
4369
- **Signature:**
4370
- ```typescript
4371
- export type AsyncValidator<TForm, TField> = (
4372
- value: TField,
4373
- scope: unknown,
4374
- root: FormModel<TForm>
4375
- ) => Promise<ValidationError | null>;
4376
- ```
4377
-
4378
- **Deprecated:** Осиротевший остаток удалённого оператора `validateAsync` (Ф7). Рантаймом не
4379
- потребляется — живой async-путь узла поля использует `AsyncValidatorFn` `(value, { signal })`.
4380
- Экспортируется только ради обратной совместимости.
4381
-
4382
- _Source: src/form/types/validation-schema.ts_
4383
-
4384
4539
  ### AsyncValidatorFn
4385
4540
 
4386
4541
  **Kind:** `type`
@@ -4484,22 +4639,6 @@ computeFrom([model.$.price, model.$.qty], model.$.total, (price, qty) => price *
4484
4639
 
4485
4640
  _Source: src/state/behaviors-value.ts_
4486
4641
 
4487
- ### ConditionFn
4488
-
4489
- **Kind:** `type`
4490
-
4491
- Функция-предикат `(value) => boolean`.
4492
-
4493
- **Signature:**
4494
- ```typescript
4495
- export type ConditionFn<T> = (value: T) => boolean;
4496
- ```
4497
-
4498
- **Deprecated:** Осиротевший остаток удалённого оператора `applyWhen` (Ф7). Рантаймом не
4499
- потребляется; экспортируется только ради обратной совместимости.
4500
-
4501
- _Source: src/form/types/validation-schema.ts_
4502
-
4503
4642
  ### ConfigWithSchema
4504
4643
 
4505
4644
  **Kind:** `interface`
@@ -4554,6 +4693,40 @@ copyFrom(model.$.email, model.$.emailAdditional, { when: () => model.sameEmail }
4554
4693
 
4555
4694
  _Source: src/state/behaviors-value.ts_
4556
4695
 
4696
+ ### CORE_RUNTIME_TOKEN
4697
+
4698
+ **Kind:** `const`
4699
+
4700
+ Штамп копии рантайма ядра.
4701
+
4702
+ Единственное назначение — быть объектом, уникальным в пределах ОДНОЙ копии модуля. Две
4703
+ независимо загруженные копии `@reformer/core` дадут два разных объекта, и по их несовпадению
4704
+ guard распознаёт дубль рантайма.
4705
+
4706
+ Почему именно объект, а не строка с версией: две копии ОДНОЙ версии ломают всё ровно так же,
4707
+ как две копии разных версий, — раздваиваются модульные `WeakMap` (`derived-registry`,
4708
+ `signal-node-registry`) и перестают работать проверки `instanceof Signal`. Сравнение версий
4709
+ такой случай пропустило бы.
4710
+
4711
+ **Signature:**
4712
+ ```typescript
4713
+ export const CORE_RUNTIME_TOKEN: object
4714
+ ```
4715
+
4716
+ **Examples:**
4717
+
4718
+ ```ts
4719
+ import { CORE_RUNTIME_TOKEN } from '@reformer/core';
4720
+ import { stampRuntime } from '@reformer/form-registry/guard';
4721
+
4722
+ stampRuntime('@reformer/core', CORE_RUNTIME_TOKEN);
4723
+ ```
4724
+
4725
+ **See also:**
4726
+ - `@reformer/form-registry/guard`
4727
+
4728
+ _Source: src/runtime-token.ts_
4729
+
4557
4730
  ### createForm
4558
4731
 
4559
4732
  **Kind:** `function`
@@ -4759,43 +4932,6 @@ disableWhen(model.$.discount, () => model.plan !== 'promo', { resetOnDisable: tr
4759
4932
 
4760
4933
  _Source: src/form/behaviors-node.ts_
4761
4934
 
4762
- ### email
4763
-
4764
- **Kind:** `function`
4765
-
4766
- Фабрика валидатора формата email.
4767
-
4768
- Проверяет по упрощённому regex `^[^\s@]+@[^\s@]+\.[^\s@]+$`. Пустые значения
4769
- (`''`/`null`/`undefined`) пропускаются (используйте {@link required} для обязательности).
4770
-
4771
- **Signature:**
4772
- ```typescript
4773
- export function email<TForm = unknown, TField extends string | null | undefined = string>(
4774
- options?: ValidateOptions
4775
- ): Validator<TForm, TField>
4776
- ```
4777
-
4778
- **Parameters:**
4779
- - `options` — - Опции валидатора ({@link ValidateOptions}): `message`, `params`
4780
-
4781
- **Returns:** Чистый валидатор {@link Validator} для строкового поля
4782
-
4783
- **Examples:**
4784
-
4785
- Проверка формата email
4786
- ```typescript
4787
- import { required, email } from '@reformer/core/validators';
4788
-
4789
- // Внутри FieldConfig схемы формы:
4790
- email: {
4791
- value: model.$.email,
4792
- component: Input,
4793
- validators: [required(), email({ message: 'Введите корректный email' })],
4794
- },
4795
- ```
4796
-
4797
- _Source: src/form/validation/validators/email.ts_
4798
-
4799
4935
  ### enableWhen
4800
4936
 
4801
4937
  **Kind:** `function`
@@ -5085,12 +5221,12 @@ export interface FieldControlState<T> {
5085
5221
 
5086
5222
  /**
5087
5223
  * Пользовательские props для передачи в UI-компоненты.
5088
- * Устанавливаются через {@link FieldNode.setComponentProps}.
5224
+ * Устанавливаются через {@link FieldNode.updateComponentProps}.
5089
5225
  *
5090
5226
  * @example
5091
5227
  * ```tsx
5092
5228
  * // Установка props
5093
- * field.setComponentProps({
5229
+ * field.updateComponentProps({
5094
5230
  * placeholder: 'Enter email...',
5095
5231
  * maxLength: 100,
5096
5232
  * autoComplete: 'email'
@@ -5190,23 +5326,6 @@ console.log(field.valid.value); // true
5190
5326
 
5191
5327
  _Source: src/form/nodes/field-node.ts_
5192
5328
 
5193
- ### FieldPathSegment
5194
-
5195
- **Kind:** `type`
5196
-
5197
- Тип для путей к полям (field paths)
5198
- Используется в навигации по полям вместо any
5199
-
5200
- **Signature:**
5201
- ```typescript
5202
- export type FieldPathSegment = {
5203
- key: string;
5204
- index?: number;
5205
- };
5206
- ```
5207
-
5208
- _Source: src/form/types/index.ts_
5209
-
5210
5329
  ### FieldStatus
5211
5330
 
5212
5331
  **Kind:** `type`
@@ -5220,70 +5339,6 @@ export type FieldStatus = 'valid' | 'invalid' | 'pending' | 'disabled';
5220
5339
 
5221
5340
  _Source: src/form/types/contracts.ts_
5222
5341
 
5223
- ### FileLike
5224
-
5225
- **Kind:** `interface`
5226
-
5227
- Минимальный файлоподобный контракт, с которым работают file-валидаторы:
5228
- нативный `File`, сериализуемый дескриптор загруженного файла и т.п.
5229
-
5230
- **Signature:**
5231
- ```typescript
5232
- export interface FileLike {
5233
- name: string;
5234
- size?: number;
5235
- type?: string;
5236
- }
5237
- ```
5238
-
5239
- _Source: src/form/validation/validators/file-utils.ts_
5240
-
5241
- ### fileType
5242
-
5243
- **Kind:** `function`
5244
-
5245
- Фабрика валидатора типа файла.
5246
-
5247
- Проверяет каждый файл против accept-строки в синтаксисе нативного атрибута
5248
- `<input type="file" accept>`: расширения (`.pdf`), точные MIME (`image/png`),
5249
- wildcard-категории (`image/*`), список через запятую. Матчинг регистронезависимый,
5250
- по `type` и/или расширению из `name` ({@link matchesFileAccept}).
5251
-
5252
- Нужен потому, что нативный `accept` — только подсказка пикеру: на drag-and-drop
5253
- и «All files» он не действует. Пустые значения (`null`/`undefined`/`''`/`[]`)
5254
- пропускаются (используйте {@link required} для обязательности).
5255
-
5256
- **Signature:**
5257
- ```typescript
5258
- export function fileType<TForm = unknown, TField = unknown>(
5259
- accept: string,
5260
- options?: ValidateOptions
5261
- ): Validator<TForm, TField>
5262
- ```
5263
-
5264
- **Parameters:**
5265
- - `accept` — - Accept-строка допустимых типов, например `'image/*,.pdf'`
5266
- - `options` — - Опции валидатора ({@link ValidateOptions}). В `params` ошибки автоматически
5267
- попадают `accept` и `fileName` (первый нарушивший файл).
5268
-
5269
- **Returns:** Чистый валидатор {@link Validator} для файла или массива файлов
5270
-
5271
- **Examples:**
5272
-
5273
- Только изображения и PDF
5274
- ```typescript
5275
- import { fileType } from '@reformer/core/validators';
5276
-
5277
- // Внутри FieldConfig схемы формы:
5278
- documents: {
5279
- value: model.$.documents,
5280
- component: FileUploadField,
5281
- validators: [fileType('image/*,.pdf', { message: 'Только изображения или PDF' })],
5282
- },
5283
- ```
5284
-
5285
- _Source: src/form/validation/validators/file-type.ts_
5286
-
5287
5342
  ### FormArrayProxy
5288
5343
 
5289
5344
  **Kind:** `type`
@@ -5664,19 +5719,25 @@ export interface FormSchemaNode {
5664
5719
  component?: ElementType;
5665
5720
  /** Props компонента. Также «клапан» для вложенности под-узлов (напр. steps визарда). */
5666
5721
  componentProps?: Record<string, unknown>;
5667
- validators?: SchemaValidator[];
5668
- asyncValidators?: SchemaValidator[];
5669
5722
  updateOn?: 'change' | 'blur' | 'submit';
5670
5723
  disabled?: boolean;
5671
5724
  /** Задержка (мс) перед запуском асинхронной валидации. */
5672
5725
  debounce?: number;
5673
5726
  /** Идентификатор узла (для wizard/tabs/renderBehavior). */
5674
5727
  selector?: string;
5728
+ /**
5729
+ * ⚠️ Рантайм этого поля НЕ ЧИТАЕТ — `renderer-react` берёт testId из `componentProps.testId`
5730
+ * (иначе выводит из пути сигнала). Поле оставлено только потому, что `RenderSchemaNode`
5731
+ * рендерера объявляет свой одноимённый; пишите `componentProps: { testId: '…' }`.
5732
+ */
5675
5733
  testId?: string;
5676
- /** Дочерние узлы (даёт контекстную типизацию вложенным литералам — value/validators/when). */
5677
- children?: readonly FormSchemaNode[];
5678
- /** Условие включения поддерева (branch-узел `{ when, children }`). */
5679
- when?: (scope: any, root: any) => boolean;
5734
+ /**
5735
+ * Содержимое узла: под-узлы (даёт контекстную типизацию вложенным литералам — value/validators/when)
5736
+ * и текстовые части. Текст (литерал, число, сигнал модели) — такой же ребёнок, как узел: core его
5737
+ * не интерпретирует (обход пропускает примитивы и не спускается внутрь сигнала), а рендерер
5738
+ * выводит на своём месте в порядке следования.
5739
+ */
5740
+ children?: readonly (FormSchemaNode | string | number | Signal<any>)[];
5680
5741
  /** Реактивный массив модели (`model.<path>`) — маркер узла-массива (вместе с `item`). */
5681
5742
  array?: SchemaArrayControl;
5682
5743
  /** Схема элемента массива: под-модель элемента → узел поддерева. */
@@ -5694,43 +5755,6 @@ export interface FormSchemaNode {
5694
5755
 
5695
5756
  _Source: src/form/types/schema-node.ts_
5696
5757
 
5697
- ### FormStatusMachine
5698
-
5699
- **Kind:** `class`
5700
-
5701
- FormStatusMachine - управляет состоянием поля формы
5702
-
5703
- Предоставляет:
5704
- - Единый источник истины для статуса
5705
- - Computed signals для derived состояний (valid, invalid, pending, disabled)
5706
- - Валидацию переходов между состояниями
5707
-
5708
- **Signature:**
5709
- ```typescript
5710
- export class FormStatusMachine {
5711
- /** Внутренний сигнал статуса */ /* … */ }
5712
- ```
5713
-
5714
- **Examples:**
5715
-
5716
- ```typescript
5717
- const statusMachine = new FormStatusMachine('valid');
5718
-
5719
- // Начало валидации
5720
- statusMachine.startValidation();
5721
- console.log(statusMachine.pending.value); // true
5722
-
5723
- // Завершение валидации с ошибками
5724
- statusMachine.completeValidation(true);
5725
- console.log(statusMachine.invalid.value); // true
5726
-
5727
- // Отключение поля
5728
- statusMachine.disable();
5729
- console.log(statusMachine.disabled.value); // true
5730
- ```
5731
-
5732
- _Source: src/form/status-machine.ts_
5733
-
5734
5758
  ### FormSubmitter
5735
5759
 
5736
5760
  **Kind:** `class`
@@ -5784,44 +5808,6 @@ export type FormValue =
5784
5808
 
5785
5809
  _Source: src/form/types/contracts.ts_
5786
5810
 
5787
- ### futureDate
5788
-
5789
- **Kind:** `function`
5790
-
5791
- Фабрика валидатора, проверяющего что дата не в прошлом.
5792
-
5793
- Дата не должна быть раньше сегодняшнего дня (сравнение по нормализованным датам).
5794
- Пустые и невалидные даты пропускаются (используйте {@link required} и {@link isDate}).
5795
-
5796
- **Signature:**
5797
- ```typescript
5798
- export function futureDate<
5799
- TForm = unknown,
5800
- TField extends string | Date | null | undefined = string | Date,
5801
- >(options?: ValidateOptions): Validator<TForm, TField>
5802
- ```
5803
-
5804
- **Parameters:**
5805
- - `options` — - Опции валидатора ({@link ValidateOptions}): `message`, `params`
5806
-
5807
- **Returns:** Чистый валидатор {@link Validator} для поля даты (`string | Date`)
5808
-
5809
- **Examples:**
5810
-
5811
- Дата не в прошлом
5812
- ```typescript
5813
- import { required, futureDate } from '@reformer/core/validators';
5814
-
5815
- // Внутри FieldConfig схемы формы:
5816
- appointmentDate: {
5817
- value: model.$.appointmentDate,
5818
- component: DatePicker,
5819
- validators: [required(), futureDate({ message: 'Дата записи должна быть в будущем' })],
5820
- },
5821
- ```
5822
-
5823
- _Source: src/form/validation/validators/future-date.ts_
5824
-
5825
5811
  ### getNodeForSignal
5826
5812
 
5827
5813
  **Kind:** `function`
@@ -5937,42 +5923,6 @@ export interface GroupNodeConfig<T> {
5937
5923
 
5938
5924
  _Source: src/form/types/index.ts_
5939
5925
 
5940
- ### integer
5941
-
5942
- **Kind:** `function`
5943
-
5944
- Фабрика валидатора, проверяющего что число — целое.
5945
-
5946
- Пустые значения и не-числа пропускаются (используйте {@link required} и {@link isNumber}).
5947
-
5948
- **Signature:**
5949
- ```typescript
5950
- export function integer<TForm = unknown, TField extends number | null | undefined = number>(
5951
- options?: ValidateOptions
5952
- ): Validator<TForm, TField>
5953
- ```
5954
-
5955
- **Parameters:**
5956
- - `options` — - Опции валидатора ({@link ValidateOptions}): `message`, `params`
5957
-
5958
- **Returns:** Чистый валидатор {@link Validator} для числового поля
5959
-
5960
- **Examples:**
5961
-
5962
- Проверка целого числа
5963
- ```typescript
5964
- import { required, integer } from '@reformer/core/validators';
5965
-
5966
- // Внутри FieldConfig схемы формы:
5967
- count: {
5968
- value: model.$.count,
5969
- component: Input,
5970
- validators: [required(), integer({ message: 'Должно быть целым числом' })],
5971
- },
5972
- ```
5973
-
5974
- _Source: src/form/validation/validators/integer.ts_
5975
-
5976
5926
  ### isArrayNode
5977
5927
 
5978
5928
  **Kind:** `function`
@@ -6004,49 +5954,11 @@ if (isArrayNode(node)) {
6004
5954
 
6005
5955
  _Source: src/form/type-guards.ts_
6006
5956
 
6007
- ### isDate
5957
+ ### isDerived
6008
5958
 
6009
5959
  **Kind:** `function`
6010
5960
 
6011
- Фабрика валидатора, проверяющего что значение — валидная дата.
6012
-
6013
- Принимает `Date` или строку, парсимую в дату. Пустые значения (`''`/`null`/`undefined`)
6014
- пропускаются (используйте {@link required} для обязательности).
6015
-
6016
- **Signature:**
6017
- ```typescript
6018
- export function isDate<
6019
- TForm = unknown,
6020
- TField extends string | Date | null | undefined = string | Date,
6021
- >(options?: ValidateOptions): Validator<TForm, TField>
6022
- ```
6023
-
6024
- **Parameters:**
6025
- - `options` — - Опции валидатора ({@link ValidateOptions}): `message`, `params`
6026
-
6027
- **Returns:** Чистый валидатор {@link Validator} для поля даты (`string | Date`)
6028
-
6029
- **Examples:**
6030
-
6031
- Проверка валидности даты
6032
- ```typescript
6033
- import { required, isDate } from '@reformer/core/validators';
6034
-
6035
- // Внутри FieldConfig схемы формы:
6036
- eventDate: {
6037
- value: model.$.eventDate,
6038
- component: DatePicker,
6039
- validators: [required(), isDate({ message: 'Введите корректную дату' })],
6040
- },
6041
- ```
6042
-
6043
- _Source: src/form/validation/validators/is-date.ts_
6044
-
6045
- ### isDerived
6046
-
6047
- **Kind:** `function`
6048
-
6049
- Производный ли сигнал (помечен через {@link markDerived}).
5961
+ Производный ли сигнал (помечен через {@link markDerived}).
6050
5962
 
6051
5963
  Читается bulk-сеттерами модели/группы, чтобы не затирать вычисляемые (`computeFrom`) поля
6052
5964
  значениями из payload.
@@ -6087,733 +5999,119 @@ FieldNode представляет примитивное поле формы (s
6087
5999
 
6088
6000
  **Signature:**
6089
6001
  ```typescript
6090
- export function isFieldNode(value: unknown): value is FieldNode<FormValue>
6091
- ```
6092
-
6093
- **Parameters:**
6094
- - `value` — - Значение для проверки
6095
-
6096
- **Returns:** true если value является FieldNode
6097
-
6098
- **Examples:**
6099
-
6100
- ```typescript
6101
- if (isFieldNode(node)) {
6102
- node.validators; // OK
6103
- node.asyncValidators; // OK
6104
- node.markAsTouched(); // OK
6105
- }
6106
- ```
6107
-
6108
- _Source: src/form/type-guards.ts_
6109
-
6110
- ### isFileLike
6111
-
6112
- **Kind:** `function`
6113
-
6114
- Проверяет, что значение файлоподобно: объект со строковым `name` и опциональными
6115
- числовым `size` / строковым `type`.
6116
-
6117
- **Signature:**
6118
- ```typescript
6119
- export function isFileLike(value: unknown): value is FileLike
6120
- ```
6121
-
6122
- **Parameters:**
6123
- - `value` — - Проверяемое значение
6124
-
6125
- **Returns:** `true`, если значение соответствует {@link FileLike}
6126
-
6127
- _Source: src/form/validation/validators/file-utils.ts_
6128
-
6129
- ### isFormNode
6130
-
6131
- **Kind:** `function`
6132
-
6133
- Проверить, является ли значение любым FormNode
6134
-
6135
- Проверяет базовые свойства, общие для всех типов узлов
6136
-
6137
- **Signature:**
6138
- ```typescript
6139
- export function isFormNode(value: unknown): value is FormNode<FormValue>
6140
- ```
6141
-
6142
- **Parameters:**
6143
- - `value` — - Значение для проверки
6144
-
6145
- **Returns:** true если value является FormNode
6146
-
6147
- **Examples:**
6148
-
6149
- ```typescript
6150
- if (isFormNode(value)) {
6151
- value.setValue(newValue);
6152
- value.validate();
6153
- }
6154
- ```
6155
-
6156
- _Source: src/form/type-guards.ts_
6157
-
6158
- ### isGroupNode
6159
-
6160
- **Kind:** `function`
6161
-
6162
- Проверить, является ли значение GroupNode (объект с вложенными полями)
6163
-
6164
- GroupNode представляет объект с вложенными полями формы: имеет навигацию по полям
6165
- (`getFieldByPath`/`fields`) и НЕ имеет array-методов (`items`/`push`/`removeAt`).
6166
-
6167
- **Signature:**
6168
- ```typescript
6169
- export function isGroupNode(value: unknown): value is GroupNode<object>
6170
- ```
6171
-
6172
- **Parameters:**
6173
- - `value` — - Значение для проверки
6174
-
6175
- **Returns:** true если value является GroupNode
6176
-
6177
- **Examples:**
6178
-
6179
- ```typescript
6180
- if (isGroupNode(node)) {
6181
- node.getFieldByPath('user.email'); // OK
6182
- }
6183
- ```
6184
-
6185
- _Source: src/form/type-guards.ts_
6186
-
6187
- ### isNumber
6188
-
6189
- **Kind:** `function`
6190
-
6191
- Фабрика валидатора, проверяющего что значение — конечное число (не NaN, не строка).
6192
-
6193
- Пустые значения (`null`/`undefined`) пропускаются (используйте {@link required} для
6194
- обязательности). В отличие от других number-валидаторов, **не** пропускает не-числа
6195
- и `NaN` — это его задача.
6196
-
6197
- **Signature:**
6198
- ```typescript
6199
- export function isNumber<TForm = unknown, TField extends number | null | undefined = number>(
6200
- options?: ValidateOptions
6201
- ): Validator<TForm, TField>
6202
- ```
6203
-
6204
- **Parameters:**
6205
- - `options` — - Опции валидатора ({@link ValidateOptions}): `message`, `params`
6206
-
6207
- **Returns:** Чистый валидатор {@link Validator} для числового поля
6208
-
6209
- **Examples:**
6210
-
6211
- Проверка, что значение — число
6212
- ```typescript
6213
- import { required, isNumber } from '@reformer/core/validators';
6214
-
6215
- // Внутри FieldConfig схемы формы:
6216
- amount: {
6217
- value: model.$.amount,
6218
- component: Input,
6219
- validators: [required(), isNumber({ message: 'Введите число' })],
6220
- },
6221
- ```
6222
-
6223
- _Source: src/form/validation/validators/is-number.ts_
6224
-
6225
- ### markDerived
6226
-
6227
- **Kind:** `function`
6228
-
6229
- Пометить сигнал производным (вычисляемым).
6230
-
6231
- Вызывается операторами {@link computeFrom}/`compute` для их сигнала-цели. После этого
6232
- bulk-сеттеры (`model.set`/`model.patch`, `patchValue`/`setValue`) пропускают это поле, чтобы
6233
- значение из payload не затирало вычисляемое. Прикладной код напрямую обычно не вызывает.
6234
-
6235
- Идемпотентна на уровне флага: повторные вызовы наращивают счётчик ссылок, чтобы каждый оператор,
6236
- пишущий в этот сигнал, был сбалансирован своим {@link unmarkDerived} при dispose.
6237
-
6238
- **Signature:**
6239
- ```typescript
6240
- export function markDerived(signal: Signal<any>): void
6241
- ```
6242
-
6243
- **Parameters:**
6244
- - `signal` — - Сигнал значения из {@link FormModel}, которым владеет compute
6245
-
6246
- **Examples:**
6247
-
6248
- ```typescript
6249
- import { markDerived } from '@reformer/core';
6250
-
6251
- // Помечаем поле total как вычисляемое — bulk-set его не перезапишет
6252
- markDerived(model.$.total);
6253
- ```
6254
-
6255
- **See also:**
6256
- - {@link isDerived} - проверка пометки
6257
- - {@link unmarkDerived} - снять пометку при dispose оператора
6258
-
6259
- _Source: src/state/derived-registry.ts_
6260
-
6261
- ### matchesFileAccept
6262
-
6263
- **Kind:** `function`
6264
-
6265
- Проверяет файл против accept-паттерна в синтаксисе нативного атрибута
6266
- `<input type="file" accept>`: список через запятую из расширений (`.pdf`),
6267
- точных MIME (`image/png`) и wildcard-категорий (`image/*`). Регистронезависимо.
6268
-
6269
- Нужен собственный матчер, потому что `accept` у нативного input — только подсказка
6270
- пикеру: на drag-and-drop и на программное значение он не действует.
6271
-
6272
- **Signature:**
6273
- ```typescript
6274
- export function matchesFileAccept(file: Pick<FileLike, 'name' | 'type'>, accept: string): boolean
6275
- ```
6276
-
6277
- **Parameters:**
6278
- - `file` — - Файлоподобное значение (`name` + опциональный `type`)
6279
- - `accept` — - Accept-строка; пустая/пробельная строка матчит всё
6280
-
6281
- **Returns:** `true`, если файл подходит хотя бы под один паттерн
6282
-
6283
- _Source: src/form/validation/validators/file-utils.ts_
6284
-
6285
- ### max
6286
-
6287
- **Kind:** `function`
6288
-
6289
- Фабрика валидатора максимального числового значения.
6290
-
6291
- Пустые значения (`null`/`undefined`) пропускаются (используйте {@link required} для обязательности).
6292
-
6293
- **Signature:**
6294
- ```typescript
6295
- export function max<TForm = unknown, TField extends number | null | undefined = number>(
6296
- maxValue: number,
6297
- options?: ValidateOptions
6298
- ): Validator<TForm, TField>
6299
- ```
6300
-
6301
- **Parameters:**
6302
- - `maxValue` — - Максимально допустимое значение (включительно)
6303
- - `options` — - Опции валидатора ({@link ValidateOptions}). В `params` ошибки автоматически
6304
- попадают `max` и `actual`.
6305
-
6306
- **Returns:** Чистый валидатор {@link Validator} для числового поля
6307
-
6308
- **Examples:**
6309
-
6310
- Максимальное значение числового поля
6311
- ```typescript
6312
- import { required, max } from '@reformer/core/validators';
6313
-
6314
- // Внутри FieldConfig схемы формы:
6315
- quantity: { value: model.$.quantity, component: Input, validators: [max(100)] },
6316
- discount: {
6317
- value: model.$.discount,
6318
- component: Input,
6319
- validators: [required(), max(50, { message: 'Не более 50%' })],
6320
- },
6321
- ```
6322
-
6323
- _Source: src/form/validation/validators/max.ts_
6324
-
6325
- ### maxAge
6326
-
6327
- **Kind:** `function`
6328
-
6329
- Фабрика валидатора максимального возраста (по дате рождения).
6330
-
6331
- Возраст вычисляется по дате рождения относительно сегодняшнего дня. Пустые и невалидные
6332
- даты пропускаются (используйте {@link required} и {@link isDate}).
6333
-
6334
- **Signature:**
6335
- ```typescript
6336
- export function maxAge<
6337
- TForm = unknown,
6338
- TField extends string | Date | null | undefined = string | Date,
6339
- >(maxAgeValue: number, options?: ValidateOptions): Validator<TForm, TField>
6340
- ```
6341
-
6342
- **Parameters:**
6343
- - `maxAgeValue` — - Максимально допустимый возраст (в полных годах)
6344
- - `options` — - Опции валидатора ({@link ValidateOptions}). В `params` ошибки автоматически
6345
- попадают `maxAge` и `currentAge`.
6346
-
6347
- **Returns:** Чистый валидатор {@link Validator} для поля даты рождения (`string | Date`)
6348
-
6349
- **Examples:**
6350
-
6351
- Максимальный возраст
6352
- ```typescript
6353
- import { maxAge } from '@reformer/core/validators';
6354
-
6355
- // Внутри FieldConfig схемы формы:
6356
- birthDate: {
6357
- value: model.$.birthDate,
6358
- component: DatePicker,
6359
- validators: [maxAge(100, { message: 'Проверьте дату рождения' })],
6360
- },
6361
- ```
6362
-
6363
- _Source: src/form/validation/validators/max-age.ts_
6364
-
6365
- ### maxDate
6366
-
6367
- **Kind:** `function`
6368
-
6369
- Фабрика валидатора максимальной даты (включительно).
6370
-
6371
- Сравнение по нормализованным датам (время обнуляется). Пустые и невалидные даты
6372
- пропускаются (используйте {@link required} и {@link isDate}).
6373
-
6374
- **Signature:**
6375
- ```typescript
6376
- export function maxDate<
6377
- TForm = unknown,
6378
- TField extends string | Date | null | undefined = string | Date,
6379
- >(maxDateValue: Date, options?: ValidateOptions): Validator<TForm, TField>
6380
- ```
6381
-
6382
- **Parameters:**
6383
- - `maxDateValue` — - Максимально допустимая дата (включительно)
6384
- - `options` — - Опции валидатора ({@link ValidateOptions}). В `params` ошибки автоматически
6385
- попадает `maxDate`.
6386
-
6387
- **Returns:** Чистый валидатор {@link Validator} для поля даты (`string | Date`)
6388
-
6389
- **Examples:**
6390
-
6391
- Максимальная дата
6392
- ```typescript
6393
- import { maxDate } from '@reformer/core/validators';
6394
-
6395
- // Внутри FieldConfig схемы формы:
6396
- birthDate: {
6397
- value: model.$.birthDate,
6398
- component: DatePicker,
6399
- validators: [maxDate(new Date(), { message: 'Дата не может быть в будущем' })],
6400
- },
6401
- ```
6402
-
6403
- _Source: src/form/validation/validators/max-date.ts_
6404
-
6405
- ### maxFiles
6406
-
6407
- **Kind:** `function`
6408
-
6409
- Фабрика валидатора максимального количества файлов.
6410
-
6411
- Работает с массивом файлов (одиночный файл считается как 1). Пустые значения
6412
- (`null`/`undefined`/`''`/`[]`) пропускаются (используйте {@link required}
6413
- для обязательности).
6414
-
6415
- **Signature:**
6416
- ```typescript
6417
- export function maxFiles<TForm = unknown, TField = unknown>(
6418
- max: number,
6419
- options?: ValidateOptions
6420
- ): Validator<TForm, TField>
6421
- ```
6422
-
6423
- **Parameters:**
6424
- - `max` — - Максимально допустимое количество файлов (включительно)
6425
- - `options` — - Опции валидатора ({@link ValidateOptions}). В `params` ошибки автоматически
6426
- попадают `maxFiles` и `actualCount`.
6427
-
6428
- **Returns:** Чистый валидатор {@link Validator} для файла или массива файлов
6429
-
6430
- **Examples:**
6431
-
6432
- Не более трёх вложений
6433
- ```typescript
6434
- import { maxFiles } from '@reformer/core/validators';
6435
-
6436
- // Внутри FieldConfig схемы формы:
6437
- documents: {
6438
- value: model.$.documents,
6439
- component: FileUploadField,
6440
- validators: [maxFiles(3, { message: 'Максимум 3 файла' })],
6441
- },
6442
- ```
6443
-
6444
- _Source: src/form/validation/validators/max-files.ts_
6445
-
6446
- ### maxFileSize
6447
-
6448
- **Kind:** `function`
6449
-
6450
- Фабрика валидатора максимального размера файла.
6451
-
6452
- Работает с одиночным файлом или массивом (`File` либо файлоподобный дескриптор с
6453
- `name`/`size`). Проверяется каждый файл; в ошибку попадает первый нарушивший.
6454
- Пустые значения (`null`/`undefined`/`''`/`[]`) и элементы без числового `size`
6455
- (например, дескриптор загруженного файла без размера) пропускаются
6456
- (используйте {@link required} для обязательности).
6457
-
6458
- **Signature:**
6459
- ```typescript
6460
- export function maxFileSize<TForm = unknown, TField = unknown>(
6461
- maxSize: number,
6462
- options?: ValidateOptions
6463
- ): Validator<TForm, TField>
6464
- ```
6465
-
6466
- **Parameters:**
6467
- - `maxSize` — - Максимально допустимый размер файла в байтах (включительно)
6468
- - `options` — - Опции валидатора ({@link ValidateOptions}). В `params` ошибки автоматически
6469
- попадают `maxFileSize`, `fileName` и `actualSize`.
6470
-
6471
- **Returns:** Чистый валидатор {@link Validator} для файла или массива файлов
6472
-
6473
- **Examples:**
6474
-
6475
- Ограничение размера вложений
6476
- ```typescript
6477
- import { maxFileSize } from '@reformer/core/validators';
6478
-
6479
- // Внутри FieldConfig схемы формы:
6480
- documents: {
6481
- value: model.$.documents,
6482
- component: FileUploadField,
6483
- validators: [maxFileSize(5 * 1024 * 1024, { message: 'Файл больше 5 МБ' })],
6484
- },
6485
- ```
6486
-
6487
- _Source: src/form/validation/validators/max-file-size.ts_
6488
-
6489
- ### maxLength
6490
-
6491
- **Kind:** `function`
6492
-
6493
- Фабрика валидатора максимальной длины строки или массива.
6494
-
6495
- Работает со строкой или массивом (проверяется `value.length`). Пустые значения
6496
- (`null`/`undefined`/`''`) и значения без числового `length` пропускаются
6497
- (используйте {@link required} для обязательности).
6498
-
6499
- **Signature:**
6500
- ```typescript
6501
- export function maxLength<TForm = unknown, TField = unknown>(
6502
- maxLen: number,
6503
- options?: ValidateOptions
6504
- ): Validator<TForm, TField>
6505
- ```
6506
-
6507
- **Parameters:**
6508
- - `maxLen` — - Максимально допустимая длина (включительно)
6509
- - `options` — - Опции валидатора ({@link ValidateOptions}). В `params` ошибки автоматически
6510
- попадают `maxLength` и `actualLength`.
6511
-
6512
- **Returns:** Чистый валидатор {@link Validator} для строки или массива
6513
-
6514
- **Examples:**
6515
-
6516
- Максимальная длина строки
6517
- ```typescript
6518
- import { maxLength } from '@reformer/core/validators';
6519
-
6520
- // Внутри FieldConfig схемы формы:
6521
- name: { value: model.$.name, component: Input, validators: [maxLength(50)] },
6522
- bio: {
6523
- value: model.$.bio,
6524
- component: Textarea,
6525
- validators: [maxLength(500, { message: 'Максимум 500 символов' })],
6526
- },
6527
- ```
6528
-
6529
- _Source: src/form/validation/validators/max-length.ts_
6530
-
6531
- ### maxTotalFileSize
6532
-
6533
- **Kind:** `function`
6534
-
6535
- Фабрика валидатора суммарного размера всех файлов.
6536
-
6537
- Складывает `size` всех файлов значения (элементы без числового `size` в сумму
6538
- не входят). Пустые значения (`null`/`undefined`/`''`/`[]`) пропускаются
6539
- (используйте {@link required} для обязательности).
6540
-
6541
- **Signature:**
6542
- ```typescript
6543
- export function maxTotalFileSize<TForm = unknown, TField = unknown>(
6544
- maxTotal: number,
6545
- options?: ValidateOptions
6546
- ): Validator<TForm, TField>
6547
- ```
6548
-
6549
- **Parameters:**
6550
- - `maxTotal` — - Максимально допустимый суммарный размер в байтах (включительно)
6551
- - `options` — - Опции валидатора ({@link ValidateOptions}). В `params` ошибки автоматически
6552
- попадают `maxTotalFileSize` и `actualTotal`.
6553
-
6554
- **Returns:** Чистый валидатор {@link Validator} для файла или массива файлов
6555
-
6556
- **Examples:**
6557
-
6558
- Суммарно не более 20 МБ
6559
- ```typescript
6560
- import { maxTotalFileSize } from '@reformer/core/validators';
6561
-
6562
- // Внутри FieldConfig схемы формы:
6563
- documents: {
6564
- value: model.$.documents,
6565
- component: FileUploadField,
6566
- validators: [maxTotalFileSize(20 * 1024 * 1024, { message: 'Суммарно не более 20 МБ' })],
6567
- },
6568
- ```
6569
-
6570
- _Source: src/form/validation/validators/max-total-file-size.ts_
6571
-
6572
- ### min
6573
-
6574
- **Kind:** `function`
6575
-
6576
- Фабрика валидатора минимального числового значения.
6577
-
6578
- Пустые значения (`null`/`undefined`) пропускаются (используйте {@link required} для обязательности).
6579
-
6580
- **Signature:**
6581
- ```typescript
6582
- export function min<TForm = unknown, TField extends number | null | undefined = number>(
6583
- minValue: number,
6584
- options?: ValidateOptions
6585
- ): Validator<TForm, TField>
6586
- ```
6587
-
6588
- **Parameters:**
6589
- - `minValue` — - Минимально допустимое значение (включительно)
6590
- - `options` — - Опции валидатора ({@link ValidateOptions}). В `params` ошибки автоматически
6591
- попадают `min` и `actual`.
6592
-
6593
- **Returns:** Чистый валидатор {@link Validator} для числового поля
6594
-
6595
- **Examples:**
6596
-
6597
- Минимальное значение числового поля
6598
- ```typescript
6599
- import { required, min } from '@reformer/core/validators';
6600
-
6601
- // Внутри FieldConfig схемы формы:
6602
- age: { value: model.$.age, component: Input, validators: [min(18)] },
6603
- quantity: {
6604
- value: model.$.quantity,
6605
- component: Input,
6606
- validators: [required(), min(1, { message: 'Минимум 1' })],
6607
- },
6608
- ```
6609
-
6610
- _Source: src/form/validation/validators/min.ts_
6611
-
6612
- ### minAge
6613
-
6614
- **Kind:** `function`
6615
-
6616
- Фабрика валидатора минимального возраста (по дате рождения).
6617
-
6618
- Возраст вычисляется по дате рождения относительно сегодняшнего дня. Пустые и невалидные
6619
- даты пропускаются (используйте {@link required} и {@link isDate}).
6620
-
6621
- **Signature:**
6622
- ```typescript
6623
- export function minAge<
6624
- TForm = unknown,
6625
- TField extends string | Date | null | undefined = string | Date,
6626
- >(minAgeValue: number, options?: ValidateOptions): Validator<TForm, TField>
6627
- ```
6628
-
6629
- **Parameters:**
6630
- - `minAgeValue` — - Минимально допустимый возраст (в полных годах)
6631
- - `options` — - Опции валидатора ({@link ValidateOptions}). В `params` ошибки автоматически
6632
- попадают `minAge` и `currentAge`.
6633
-
6634
- **Returns:** Чистый валидатор {@link Validator} для поля даты рождения (`string | Date`)
6635
-
6636
- **Examples:**
6637
-
6638
- Минимальный возраст
6639
- ```typescript
6640
- import { required, minAge } from '@reformer/core/validators';
6641
-
6642
- // Внутри FieldConfig схемы формы:
6643
- birthDate: {
6644
- value: model.$.birthDate,
6645
- component: DatePicker,
6646
- validators: [required(), minAge(18, { message: 'Вам должно быть не менее 18 лет' })],
6647
- },
6648
- ```
6649
-
6650
- _Source: src/form/validation/validators/min-age.ts_
6651
-
6652
- ### minDate
6653
-
6654
- **Kind:** `function`
6655
-
6656
- Фабрика валидатора минимальной даты (включительно).
6657
-
6658
- Сравнение по нормализованным датам (время обнуляется). Пустые и невалидные даты
6659
- пропускаются (используйте {@link required} и {@link isDate}).
6660
-
6661
- **Signature:**
6662
- ```typescript
6663
- export function minDate<
6664
- TForm = unknown,
6665
- TField extends string | Date | null | undefined = string | Date,
6666
- >(minDateValue: Date, options?: ValidateOptions): Validator<TForm, TField>
6002
+ export function isFieldNode(value: unknown): value is FieldNode<FormValue>
6667
6003
  ```
6668
6004
 
6669
6005
  **Parameters:**
6670
- - `minDateValue` — - Минимально допустимая дата (включительно)
6671
- - `options` — - Опции валидатора ({@link ValidateOptions}). В `params` ошибки автоматически
6672
- попадает `minDate`.
6006
+ - `value` — - Значение для проверки
6673
6007
 
6674
- **Returns:** Чистый валидатор {@link Validator} для поля даты (`string | Date`)
6008
+ **Returns:** true если value является FieldNode
6675
6009
 
6676
6010
  **Examples:**
6677
6011
 
6678
- Минимальная дата
6679
6012
  ```typescript
6680
- import { required, minDate } from '@reformer/core/validators';
6681
-
6682
- // Внутри FieldConfig схемы формы:
6683
- startDate: {
6684
- value: model.$.startDate,
6685
- component: DatePicker,
6686
- validators: [required(), minDate(new Date(), { message: 'Дата не раньше сегодня' })],
6687
- },
6013
+ if (isFieldNode(node)) {
6014
+ node.validators; // OK
6015
+ node.asyncValidators; // OK
6016
+ node.markAsTouched(); // OK
6017
+ }
6688
6018
  ```
6689
6019
 
6690
- _Source: src/form/validation/validators/min-date.ts_
6020
+ _Source: src/form/type-guards.ts_
6691
6021
 
6692
- ### minFiles
6022
+ ### isFormNode
6693
6023
 
6694
6024
  **Kind:** `function`
6695
6025
 
6696
- Фабрика валидатора минимального количества файлов.
6026
+ Проверить, является ли значение любым FormNode
6697
6027
 
6698
- Работает с массивом файлов (одиночный файл считается как 1). Пустые значения
6699
- (`null`/`undefined`/`''`/`[]`) пропускаются — «нужен хотя бы один файл» выражается
6700
- связкой `required()` + `minFiles(n)`, как и у {@link minLength}.
6028
+ Проверяет базовые свойства, общие для всех типов узлов
6701
6029
 
6702
6030
  **Signature:**
6703
6031
  ```typescript
6704
- export function minFiles<TForm = unknown, TField = unknown>(
6705
- min: number,
6706
- options?: ValidateOptions
6707
- ): Validator<TForm, TField>
6032
+ export function isFormNode(value: unknown): value is FormNode<FormValue>
6708
6033
  ```
6709
6034
 
6710
6035
  **Parameters:**
6711
- - `min` — - Минимально допустимое количество файлов (включительно)
6712
- - `options` — - Опции валидатора ({@link ValidateOptions}). В `params` ошибки автоматически
6713
- попадают `minFiles` и `actualCount`.
6036
+ - `value` — - Значение для проверки
6714
6037
 
6715
- **Returns:** Чистый валидатор {@link Validator} для файла или массива файлов
6038
+ **Returns:** true если value является FormNode
6716
6039
 
6717
6040
  **Examples:**
6718
6041
 
6719
- Не менее двух документов
6720
6042
  ```typescript
6721
- import { required, minFiles } from '@reformer/core/validators';
6722
-
6723
- // Внутри FieldConfig схемы формы:
6724
- documents: {
6725
- value: model.$.documents,
6726
- component: FileUploadField,
6727
- validators: [required(), minFiles(2, { message: 'Приложите минимум 2 документа' })],
6728
- },
6043
+ if (isFormNode(value)) {
6044
+ value.setValue(newValue);
6045
+ value.validate();
6046
+ }
6729
6047
  ```
6730
6048
 
6731
- _Source: src/form/validation/validators/min-files.ts_
6049
+ _Source: src/form/type-guards.ts_
6732
6050
 
6733
- ### minFileSize
6051
+ ### isGroupNode
6734
6052
 
6735
6053
  **Kind:** `function`
6736
6054
 
6737
- Фабрика валидатора минимального размера файла.
6055
+ Проверить, является ли значение GroupNode (объект с вложенными полями)
6738
6056
 
6739
- Работает с одиночным файлом или массивом (`File` либо файлоподобный дескриптор с
6740
- `name`/`size`). Проверяется каждый файл; в ошибку попадает первый нарушивший.
6741
- Типовой сценарий — отсев пустых (0-байтовых) файлов: `minFileSize(1)`.
6742
- Пустые значения (`null`/`undefined`/`''`/`[]`) и элементы без числового `size`
6743
- пропускаются (используйте {@link required} для обязательности).
6057
+ GroupNode представляет объект с вложенными полями формы: имеет навигацию по полям
6058
+ (`getFieldByPath`/`fields`) и НЕ имеет array-методов (`items`/`push`/`removeAt`).
6744
6059
 
6745
6060
  **Signature:**
6746
6061
  ```typescript
6747
- export function minFileSize<TForm = unknown, TField = unknown>(
6748
- minSize: number,
6749
- options?: ValidateOptions
6750
- ): Validator<TForm, TField>
6062
+ export function isGroupNode(value: unknown): value is GroupNode<object>
6751
6063
  ```
6752
6064
 
6753
6065
  **Parameters:**
6754
- - `minSize` — - Минимально допустимый размер файла в байтах (включительно)
6755
- - `options` — - Опции валидатора ({@link ValidateOptions}). В `params` ошибки автоматически
6756
- попадают `minFileSize`, `fileName` и `actualSize`.
6066
+ - `value` — - Значение для проверки
6757
6067
 
6758
- **Returns:** Чистый валидатор {@link Validator} для файла или массива файлов
6068
+ **Returns:** true если value является GroupNode
6759
6069
 
6760
6070
  **Examples:**
6761
6071
 
6762
- Отсев пустых файлов
6763
6072
  ```typescript
6764
- import { minFileSize } from '@reformer/core/validators';
6765
-
6766
- // Внутри FieldConfig схемы формы:
6767
- documents: {
6768
- value: model.$.documents,
6769
- component: FileUploadField,
6770
- validators: [minFileSize(1, { message: 'Файл пустой' })],
6771
- },
6073
+ if (isGroupNode(node)) {
6074
+ node.getFieldByPath('user.email'); // OK
6075
+ }
6772
6076
  ```
6773
6077
 
6774
- _Source: src/form/validation/validators/min-file-size.ts_
6078
+ _Source: src/form/type-guards.ts_
6775
6079
 
6776
- ### minLength
6080
+ ### markDerived
6777
6081
 
6778
6082
  **Kind:** `function`
6779
6083
 
6780
- Фабрика валидатора минимальной длины строки или массива.
6084
+ Пометить сигнал производным (вычисляемым).
6085
+
6086
+ Вызывается операторами {@link computeFrom}/`compute` для их сигнала-цели. После этого
6087
+ bulk-сеттеры (`model.set`/`model.patch`, `patchValue`/`setValue`) пропускают это поле, чтобы
6088
+ значение из payload не затирало вычисляемое. Прикладной код напрямую обычно не вызывает.
6781
6089
 
6782
- Работает со строкой или массивом (проверяется `value.length`). Пустые значения
6783
- (`null`/`undefined`/`''`) и значения без числового `length` пропускаются
6784
- (используйте {@link required} для обязательности).
6090
+ Идемпотентна на уровне флага: повторные вызовы наращивают счётчик ссылок, чтобы каждый оператор,
6091
+ пишущий в этот сигнал, был сбалансирован своим {@link unmarkDerived} при dispose.
6785
6092
 
6786
6093
  **Signature:**
6787
6094
  ```typescript
6788
- export function minLength<TForm = unknown, TField = unknown>(
6789
- minLen: number,
6790
- options?: ValidateOptions
6791
- ): Validator<TForm, TField>
6095
+ export function markDerived(signal: Signal<any>): void
6792
6096
  ```
6793
6097
 
6794
6098
  **Parameters:**
6795
- - `minLen` — - Минимально допустимая длина (включительно)
6796
- - `options` — - Опции валидатора ({@link ValidateOptions}). В `params` ошибки автоматически
6797
- попадают `minLength` и `actualLength`.
6798
-
6799
- **Returns:** Чистый валидатор {@link Validator} для строки или массива
6099
+ - `signal` — - Сигнал значения из {@link FormModel}, которым владеет compute
6800
6100
 
6801
6101
  **Examples:**
6802
6102
 
6803
- Минимальная длина строки
6804
6103
  ```typescript
6805
- import { required, minLength } from '@reformer/core/validators';
6104
+ import { markDerived } from '@reformer/core';
6806
6105
 
6807
- // Внутри FieldConfig схемы формы:
6808
- name: { value: model.$.name, component: Input, validators: [minLength(2)] },
6809
- password: {
6810
- value: model.$.password,
6811
- component: Input,
6812
- validators: [required(), minLength(8, { message: 'Минимум 8 символов' })],
6813
- },
6106
+ // Помечаем поле total как вычисляемое — bulk-set его не перезапишет
6107
+ markDerived(model.$.total);
6814
6108
  ```
6815
6109
 
6816
- _Source: src/form/validation/validators/min-length.ts_
6110
+ **See also:**
6111
+ - {@link isDerived} - проверка пометки
6112
+ - {@link unmarkDerived} - снять пометку при dispose оператора
6113
+
6114
+ _Source: src/state/derived-registry.ts_
6817
6115
 
6818
6116
  ### ModelApi
6819
6117
 
@@ -7017,358 +6315,105 @@ _Source: src/state/types.ts_
7017
6315
  - примитив → значение
7018
6316
 
7019
6317
  **Signature:**
7020
- ```typescript
7021
- export type ModelValue<V> =
7022
- NonNullable<V> extends ReadonlyArray<infer U>
7023
- ? ModelArray<U>
7024
- : NonNullable<V> extends Opaque
7025
- ? V
7026
- : NonNullable<V> extends object
7027
- ? FormModel<NonNullable<V>>
7028
- : V;
7029
- ```
7030
-
7031
- _Source: src/state/types.ts_
7032
-
7033
- ### multipleOf
7034
-
7035
- **Kind:** `function`
7036
-
7037
- Фабрика валидатора, проверяющего что число кратно заданному.
7038
-
7039
- Пустые значения и не-числа пропускаются (используйте {@link required} и {@link isNumber}).
7040
-
7041
- **Signature:**
7042
- ```typescript
7043
- export function multipleOf<TForm = unknown, TField extends number | null | undefined = number>(
7044
- divisor: number,
7045
- options?: ValidateOptions
7046
- ): Validator<TForm, TField>
7047
- ```
7048
-
7049
- **Parameters:**
7050
- - `divisor` — - Делитель: значение должно быть кратно ему
7051
- - `options` — - Опции валидатора ({@link ValidateOptions}). В `params` ошибки автоматически
7052
- попадает `multipleOf` (делитель).
7053
-
7054
- **Returns:** Чистый валидатор {@link Validator} для числового поля
7055
-
7056
- **Examples:**
7057
-
7058
- Проверка кратности
7059
- ```typescript
7060
- import { multipleOf } from '@reformer/core/validators';
7061
-
7062
- // Внутри FieldConfig схемы формы:
7063
- rating: {
7064
- value: model.$.rating,
7065
- component: Input,
7066
- validators: [multipleOf(0.5, { message: 'Только шаг 0.5' })],
7067
- },
7068
- ```
7069
-
7070
- _Source: src/form/validation/validators/multiple-of.ts_
7071
-
7072
- ### NodeFactory
7073
-
7074
- **Kind:** `class`
7075
-
7076
- Фабрика для создания узлов формы.
7077
-
7078
- Определяет тип конфига и создаёт соответствующий узел (FieldNode, GroupNode, ArrayNode).
7079
- Используется внутри `getReformerForm`/`group`/`array` — явно вызывать обычно не нужно.
7080
-
7081
- **Signature:**
7082
- ```typescript
7083
- export class NodeFactory {
7084
- /**
7085
- * Создает узел формы на основе конфигурации
7086
- *
7087
- * ✅ ОБНОВЛЕНО: Теперь поддерживает массивы напрямую
7088
- *
7089
- * Автоматически определяет тип узла:
7090
- * - FieldNode: имеет value и component
7091
- * - ArrayNode: массив [schema, ...items] или { schema, initialItems }
7092
- * - GroupNode: объект без value, component, schema
7093
- *
7094
- * @param config Конфигурация узла
7095
- * @returns Экземпляр FieldNode, GroupNode или ArrayNode
7096
- * @throws Error если конфиг не соответствует ни одному типу
7097
- *
7098
- * @example
7099
- * ```typescript
7100
- * const factory = new NodeFactory();
7101
- *
7102
- * // FieldNode
7103
- * const field = factory.createNode({
7104
- * value: 'test@mail.com',
7105
- * component: Input,
7106
- * validators: [required, email]
7107
- * });
7108
- *
7109
- * // GroupNode
7110
- * const group = factory.createNode({
7111
- * email: { value: '', component: Input },
7112
- * password: { value: '', component: Input }
7113
- * });
7114
- *
7115
- * // ArrayNode (объект)
7116
- * const array = factory.createNode({
7117
- * schema: { title: { value: '', component: Input } },
7118
- * initialItems: [{ title: 'Item 1' }]
7119
- * });
7120
- *
7121
- * // ArrayNode (массив) - новый формат
7122
- * const array2 = factory.createNode([
7123
- * { title: { value: '', component: Input } }, // schema
7124
- * { title: 'Item 1' }, // initial item 1
7125
- * { title: 'Item 2' } // initial item 2
7126
- * ]);
7127
- * ```
7128
- */ /* … */ }
7129
- ```
7130
-
7131
- **Examples:**
7132
-
7133
- ```typescript
7134
- import { NodeFactory } from '@reformer/core';
7135
-
7136
- const factory = new NodeFactory();
7137
- const node = factory.createNode({ value: '', component: Input }); // → FieldNode<string>
7138
- ```
7139
-
7140
- _Source: src/form/factories/node-factory.ts_
7141
-
7142
- ### nonNegative
7143
-
7144
- **Kind:** `function`
7145
-
7146
- Фабрика валидатора, проверяющего что число неотрицательное (`≥ 0`).
7147
-
7148
- Пустые значения и не-числа пропускаются (используйте {@link required} и {@link isNumber}).
7149
-
7150
- **Signature:**
7151
- ```typescript
7152
- export function nonNegative<TForm = unknown, TField extends number | null | undefined = number>(
7153
- options?: ValidateOptions
7154
- ): Validator<TForm, TField>
7155
- ```
7156
-
7157
- **Parameters:**
7158
- - `options` — - Опции валидатора ({@link ValidateOptions}): `message`, `params`
7159
-
7160
- **Returns:** Чистый валидатор {@link Validator} для числового поля
7161
-
7162
- **Examples:**
7163
-
7164
- Проверка неотрицательности
7165
- ```typescript
7166
- import { nonNegative } from '@reformer/core/validators';
7167
-
7168
- // Внутри FieldConfig схемы формы:
7169
- balance: {
7170
- value: model.$.balance,
7171
- component: Input,
7172
- validators: [nonNegative({ message: 'Баланс не может быть отрицательным' })],
7173
- },
7174
- ```
7175
-
7176
- _Source: src/form/validation/validators/non-negative.ts_
7177
-
7178
- ### nonZero
7179
-
7180
- **Kind:** `function`
7181
-
7182
- Фабрика валидатора, проверяющего что число не равно нулю.
7183
-
7184
- Пустые значения и не-числа пропускаются (используйте {@link required} и {@link isNumber}).
7185
-
7186
- **Signature:**
7187
- ```typescript
7188
- export function nonZero<TForm = unknown, TField extends number | null | undefined = number>(
7189
- options?: ValidateOptions
7190
- ): Validator<TForm, TField>
7191
- ```
7192
-
7193
- **Parameters:**
7194
- - `options` — - Опции валидатора ({@link ValidateOptions}): `message`, `params`
7195
-
7196
- **Returns:** Чистый валидатор {@link Validator} для числового поля
7197
-
7198
- **Examples:**
7199
-
7200
- Проверка «не ноль»
7201
- ```typescript
7202
- import { nonZero } from '@reformer/core/validators';
7203
-
7204
- // Внутри FieldConfig схемы формы:
7205
- divisor: {
7206
- value: model.$.divisor,
7207
- component: Input,
7208
- validators: [nonZero({ message: 'Не может быть нулём' })],
7209
- },
7210
- ```
7211
-
7212
- _Source: src/form/validation/validators/non-zero.ts_
7213
-
7214
- ### pastDate
7215
-
7216
- **Kind:** `function`
7217
-
7218
- Фабрика валидатора, проверяющего что дата не в будущем.
7219
-
7220
- Дата не должна быть позже сегодняшнего дня (сравнение по нормализованным датам).
7221
- Пустые и невалидные даты пропускаются (используйте {@link required} и {@link isDate}).
7222
-
7223
- **Signature:**
7224
- ```typescript
7225
- export function pastDate<
7226
- TForm = unknown,
7227
- TField extends string | Date | null | undefined = string | Date,
7228
- >(options?: ValidateOptions): Validator<TForm, TField>
7229
- ```
7230
-
7231
- **Parameters:**
7232
- - `options` — - Опции валидатора ({@link ValidateOptions}): `message`, `params`
7233
-
7234
- **Returns:** Чистый валидатор {@link Validator} для поля даты (`string | Date`)
7235
-
7236
- **Examples:**
7237
-
7238
- Дата не в будущем
7239
- ```typescript
7240
- import { required, pastDate } from '@reformer/core/validators';
7241
-
7242
- // Внутри FieldConfig схемы формы:
7243
- birthDate: {
7244
- value: model.$.birthDate,
7245
- component: DatePicker,
7246
- validators: [required(), pastDate({ message: 'Дата рождения не может быть в будущем' })],
7247
- },
7248
- ```
7249
-
7250
- _Source: src/form/validation/validators/past-date.ts_
7251
-
7252
- ### PathAwareSignal
7253
-
7254
- **Kind:** `type`
7255
-
7256
- Сигнал, который знает свой путь в модели (`'personalData.lastName'`).
7257
- Используется как «ручка поля»: и привязка value в схеме, и идентичность для testId/devtools.
7258
-
7259
- **Signature:**
7260
- ```typescript
7261
- export type PathAwareSignal<T> = Signal<T> & {
7262
- /** Путь поля в модели (dot-нотация). На элементах массива включает индекс. */
7263
- readonly __path: string;
7264
- };
7265
- ```
7266
-
7267
- _Source: src/state/types.ts_
7268
-
7269
- ### pattern
7270
-
7271
- **Kind:** `function`
7272
-
7273
- Фабрика валидатора регулярного выражения.
7274
-
7275
- Пустые значения (`''`/`null`/`undefined`) пропускаются (используйте {@link required}
7276
- для обязательности).
7277
-
7278
- **Signature:**
7279
- ```typescript
7280
- export function pattern<TForm = unknown, TField extends string | null | undefined = string>(
7281
- regex: RegExp,
7282
- options?: ValidateOptions
7283
- ): Validator<TForm, TField>
7284
- ```
7285
-
7286
- **Parameters:**
7287
- - `regex` — - Регулярное выражение для проверки значения
7288
- - `options` — - Опции валидатора ({@link ValidateOptions}). В `params` ошибки автоматически
7289
- попадает `pattern` (строка-источник regex).
7290
-
7291
- **Returns:** Чистый валидатор {@link Validator} для строкового поля
7292
-
7293
- **Examples:**
7294
-
7295
- Проверка по регулярному выражению
7296
- ```typescript
7297
- import { required, pattern } from '@reformer/core/validators';
7298
-
7299
- // Внутри FieldConfig схемы формы:
7300
- name: {
7301
- value: model.$.name,
7302
- component: Input,
7303
- validators: [pattern(/^[a-zA-Zа-яА-Я]+$/, { message: 'Только буквы' })],
7304
- },
7305
- phone: {
7306
- value: model.$.phone,
7307
- component: InputMask,
7308
- validators: [
7309
- required(),
7310
- pattern(/^\+7 \(\d{3}\) \d{3}-\d{2}-\d{2}$/, { message: 'Формат +7 (999) 123-45-67' }),
7311
- ],
7312
- },
6318
+ ```typescript
6319
+ export type ModelValue<V> =
6320
+ NonNullable<V> extends ReadonlyArray<infer U>
6321
+ ? ModelArray<U>
6322
+ : NonNullable<V> extends Opaque
6323
+ ? V
6324
+ : NonNullable<V> extends object
6325
+ ? FormModel<NonNullable<V>>
6326
+ : V;
7313
6327
  ```
7314
6328
 
7315
- _Source: src/form/validation/validators/pattern.ts_
6329
+ _Source: src/state/types.ts_
7316
6330
 
7317
- ### phone
6331
+ ### NodeFactory
7318
6332
 
7319
- **Kind:** `function`
6333
+ **Kind:** `class`
7320
6334
 
7321
- Фабрика валидатора номера телефона.
6335
+ Фабрика для создания узлов формы.
7322
6336
 
7323
- Проверяет значение по regex выбранного {@link PhoneFormat}. Пустые значения
7324
- (`''`/`null`/`undefined`) пропускаются (используйте {@link required} для обязательности).
6337
+ Определяет тип конфига и создаёт соответствующий узел (FieldNode, GroupNode, ArrayNode).
6338
+ Используется внутри `getReformerForm`/`group`/`array` — явно вызывать обычно не нужно.
7325
6339
 
7326
6340
  **Signature:**
7327
6341
  ```typescript
7328
- export function phone<TForm = unknown, TField extends string | null | undefined = string>(
7329
- options?: PhoneValidatorOptions
7330
- ): Validator<TForm, TField>
6342
+ export class NodeFactory {
6343
+ /**
6344
+ * Создает узел формы на основе конфигурации
6345
+ *
6346
+ * ✅ ОБНОВЛЕНО: Теперь поддерживает массивы напрямую
6347
+ *
6348
+ * Автоматически определяет тип узла:
6349
+ * - FieldNode: имеет value и component
6350
+ * - ArrayNode: массив [schema, ...items] или { schema, initialItems }
6351
+ * - GroupNode: объект без value, component, schema
6352
+ *
6353
+ * @param config Конфигурация узла
6354
+ * @returns Экземпляр FieldNode, GroupNode или ArrayNode
6355
+ * @throws Error если конфиг не соответствует ни одному типу
6356
+ *
6357
+ * @example
6358
+ * ```typescript
6359
+ * const factory = new NodeFactory();
6360
+ *
6361
+ * // FieldNode
6362
+ * const field = factory.createNode({
6363
+ * value: 'test@mail.com',
6364
+ * component: Input,
6365
+ * validators: [required, email]
6366
+ * });
6367
+ *
6368
+ * // GroupNode
6369
+ * const group = factory.createNode({
6370
+ * email: { value: '', component: Input },
6371
+ * password: { value: '', component: Input }
6372
+ * });
6373
+ *
6374
+ * // ArrayNode (объект)
6375
+ * const array = factory.createNode({
6376
+ * schema: { title: { value: '', component: Input } },
6377
+ * initialItems: [{ title: 'Item 1' }]
6378
+ * });
6379
+ *
6380
+ * // ArrayNode (массив) - новый формат
6381
+ * const array2 = factory.createNode([
6382
+ * { title: { value: '', component: Input } }, // schema
6383
+ * { title: 'Item 1' }, // initial item 1
6384
+ * { title: 'Item 2' } // initial item 2
6385
+ * ]);
6386
+ * ```
6387
+ */ /* … */ }
7331
6388
  ```
7332
6389
 
7333
- **Parameters:**
7334
- - `options` — - Опции валидатора {@link PhoneValidatorOptions}. В `params` ошибки
7335
- автоматически попадает выбранный `format`.
7336
-
7337
- **Returns:** Чистый валидатор {@link Validator} для строкового поля
7338
-
7339
6390
  **Examples:**
7340
6391
 
7341
- Проверка номера телефона
7342
6392
  ```typescript
7343
- import { required, phone } from '@reformer/core/validators';
6393
+ import { NodeFactory } from '@reformer/core';
7344
6394
 
7345
- // Внутри FieldConfig схемы формы:
7346
- phone: {
7347
- value: model.$.phone,
7348
- component: Input,
7349
- validators: [required(), phone({ format: 'ru' })],
7350
- },
6395
+ const factory = new NodeFactory();
6396
+ const node = factory.createNode({ value: '', component: Input }); // → FieldNode<string>
7351
6397
  ```
7352
6398
 
7353
- _Source: src/form/validation/validators/phone.ts_
6399
+ _Source: src/form/factories/node-factory.ts_
7354
6400
 
7355
- ### PhoneFormat
6401
+ ### PathAwareSignal
7356
6402
 
7357
6403
  **Kind:** `type`
7358
6404
 
7359
- Формат проверки номера телефона для валидатора {@link phone}.
7360
-
7361
- - `international` — международный формат E.164 (`+?[1-9]\d{1,14}`);
7362
- - `ru` — российские номера (`+7`/`7`/`8`, коды `4`/`8`/`9`, с разделителями);
7363
- - `us` — североамериканские номера (NANP);
7364
- - `any` — свободный формат: цифры, скобки и разделители (по умолчанию).
6405
+ Сигнал, который знает свой путь в модели (`'personalData.lastName'`).
6406
+ Используется как «ручка поля»: и привязка value в схеме, и идентичность для testId/devtools.
7365
6407
 
7366
6408
  **Signature:**
7367
6409
  ```typescript
7368
- export type PhoneFormat = 'international' | 'ru' | 'us' | 'any';
6410
+ export type PathAwareSignal<T> = Signal<T> & {
6411
+ /** Путь поля в модели (dot-нотация). На элементах массива включает индекс. */
6412
+ readonly __path: string;
6413
+ };
7369
6414
  ```
7370
6415
 
7371
- _Source: src/form/validation/validators/phone.ts_
6416
+ _Source: src/state/types.ts_
7372
6417
 
7373
6418
  ### registerSignalNode
7374
6419
 
@@ -7404,52 +6449,6 @@ if (sig && node) registerSignalNode(sig, node);
7404
6449
 
7405
6450
  _Source: src/form/signal-node-registry.ts_
7406
6451
 
7407
- ### required
7408
-
7409
- **Kind:** `function`
7410
-
7411
- Фабрика валидатора обязательного поля.
7412
-
7413
- Возвращает чистую функцию-валидатор `(value, control, root)`. Передаётся в `validate()`.
7414
-
7415
- Пустыми считаются: `null`, `undefined`, `''` (пустая строка), `[]` (пустой массив —
7416
- обязательный multi-select / FormArray без выбранных элементов).
7417
- Для boolean полей требуется значение `true`.
7418
-
7419
- **Signature:**
7420
- ```typescript
7421
- export function required<TForm = unknown, TField = unknown>(
7422
- options?: ValidateOptions
7423
- ): Validator<TForm, TField>
7424
- ```
7425
-
7426
- **Parameters:**
7427
- - `options` — - Опции валидатора ({@link ValidateOptions}): `message`, `params`
7428
-
7429
- **Returns:** Чистый валидатор {@link Validator} для поля схемы
7430
-
7431
- **Examples:**
7432
-
7433
- Обязательные поля в схеме формы
7434
- ```typescript
7435
- import { required } from '@reformer/core/validators';
7436
-
7437
- // Внутри FieldConfig схемы формы:
7438
- email: { value: model.$.email, component: Input, validators: [required()] },
7439
- phone: {
7440
- value: model.$.phone,
7441
- component: Input,
7442
- validators: [required({ message: 'Укажите номер телефона' })],
7443
- },
7444
- agreeToTerms: {
7445
- value: model.$.agreeToTerms,
7446
- component: Checkbox,
7447
- validators: [required({ message: 'Необходимо принять условия' })],
7448
- },
7449
- ```
7450
-
7451
- _Source: src/form/validation/validators/required.ts_
7452
-
7453
6452
  ### resetWhen
7454
6453
 
7455
6454
  **Kind:** `function`
@@ -7473,19 +6472,6 @@ resetWhen(model.$.cardNumber, () => model.paymentType !== 'card', { resetValue:
7473
6472
 
7474
6473
  _Source: src/state/behaviors-value.ts_
7475
6474
 
7476
- ### ResourceLoadResult
7477
-
7478
- **Kind:** `type`
7479
-
7480
- Тип для результатов загрузки ресурсов
7481
-
7482
- **Signature:**
7483
- ```typescript
7484
- export type ResourceLoadResult = unknown;
7485
- ```
7486
-
7487
- _Source: src/form/types/index.ts_
7488
-
7489
6475
  ### revalidateWhen
7490
6476
 
7491
6477
  **Kind:** `function`
@@ -7643,25 +6629,6 @@ export interface SchemaArrayControl {
7643
6629
 
7644
6630
  _Source: src/form/types/schema-node.ts_
7645
6631
 
7646
- ### SchemaValidator
7647
-
7648
- **Kind:** `type`
7649
-
7650
- Валидатор поля схемы (legacy). Дерево-движок, вызывавший `validators` узла как
7651
- `(value, scope, root)`, удалён — живые правила это `Rule<T>` в `validate(sig, [...])`
7652
- (`@reformer/core/validation`). Тип остаётся широким по параметрам для совместимости
7653
- узлов, всё ещё несущих `validators` (гетерогенные контракты `ValidatorFn`/`Validator`).
7654
-
7655
- **Signature:**
7656
- ```typescript
7657
- export type SchemaValidator = (
7658
- value: any,
7659
- ...rest: any[]
7660
- ) => ValidationError | null | Promise<ValidationError | null>;
7661
- ```
7662
-
7663
- _Source: src/form/types/schema-node.ts_
7664
-
7665
6632
  ### SetValueOptions
7666
6633
 
7667
6634
  **Kind:** `interface`
@@ -7673,32 +6640,13 @@ _Source: src/form/types/schema-node.ts_
7673
6640
  export interface SetValueOptions {
7674
6641
  /** Не вызывать событие изменения (не триггерить валидацию) */
7675
6642
  emitEvent?: boolean;
7676
- /** Обновить только этот узел, не распространять на родителей */
7677
- onlySelf?: boolean;
6643
+ // onlySelf удалён в 7.0: опция объявлялась, но не была реализована ни одной из четырёх
6644
+ // реализаций setValue — передача значения ни на что не влияла.
7678
6645
  }
7679
6646
  ```
7680
6647
 
7681
6648
  _Source: src/form/nodes/form-node.ts_
7682
6649
 
7683
- ### StatusEvent
7684
-
7685
- **Kind:** `type`
7686
-
7687
- События для State Machine
7688
-
7689
- **Signature:**
7690
- ```typescript
7691
- export type StatusEvent =
7692
- | { type: 'START_VALIDATION' }
7693
- | { type: 'VALIDATION_SUCCESS' }
7694
- | { type: 'VALIDATION_FAILURE' }
7695
- | { type: 'DISABLE' }
7696
- | { type: 'ENABLE'; hasErrors?: boolean }
7697
- | { type: 'SET_ERRORS'; hasErrors: boolean };
7698
- ```
7699
-
7700
- _Source: src/form/status-machine.ts_
7701
-
7702
6650
  ### SubmitOptions
7703
6651
 
7704
6652
  **Kind:** `interface`
@@ -7825,27 +6773,6 @@ syncFields(model.$.field1, model.$.field2);
7825
6773
 
7826
6774
  _Source: src/state/behaviors-value.ts_
7827
6775
 
7828
- ### toFileArray
7829
-
7830
- **Kind:** `function`
7831
-
7832
- Нормализует значение file-поля в массив файлоподобных элементов.
7833
-
7834
- Одиночный {@link FileLike} оборачивается в массив; из массива отбираются только
7835
- файлоподобные элементы. Для прочих значений — `null` (валидатор пропускает).
7836
-
7837
- **Signature:**
7838
- ```typescript
7839
- export function toFileArray(value: unknown): FileLike[] | null
7840
- ```
7841
-
7842
- **Parameters:**
7843
- - `value` — - Значение поля (`FileLike`, `FileLike[]` или что-то ещё)
7844
-
7845
- **Returns:** Массив файлоподобных элементов или `null`
7846
-
7847
- _Source: src/form/validation/validators/file-utils.ts_
7848
-
7849
6776
  ### transformValue
7850
6777
 
7851
6778
  **Kind:** `function`
@@ -7869,61 +6796,6 @@ transformValue(model.$.promoCode, (v) => (v ?? '').toUpperCase());
7869
6796
 
7870
6797
  _Source: src/state/behaviors-value.ts_
7871
6798
 
7872
- ### uniqueId
7873
-
7874
- **Kind:** `function`
7875
-
7876
- Генерирует уникальный идентификатор с указанным префиксом.
7877
-
7878
- **Signature:**
7879
- ```typescript
7880
- export function uniqueId(prefix: SubscriptionKeyType): string
7881
- ```
7882
-
7883
- **Parameters:**
7884
- - `prefix` — - Префикс для идентификатора (используйте {@link SubscriptionKey}).
7885
-
7886
- **Returns:** Уникальный идентификатор в формате `${prefix}-${counter}`.
7887
-
7888
- **Examples:**
7889
-
7890
- ```typescript
7891
- import { uniqueId, SubscriptionKey } from '@reformer/core';
7892
-
7893
- uniqueId(SubscriptionKey.WatchField); // → 'watchField-1'
7894
- uniqueId(SubscriptionKey.WatchField); // → 'watchField-2'
7895
- ```
7896
-
7897
- _Source: src/form/unique-id.ts_
7898
-
7899
- ### UnknownCallback
7900
-
7901
- **Kind:** `type`
7902
-
7903
- Тип для коллбэков и обработчиков событий
7904
- Используется вместо (...args: any[]) => any
7905
-
7906
- **Signature:**
7907
- ```typescript
7908
- export type UnknownCallback = (...args: unknown[]) => unknown;
7909
- ```
7910
-
7911
- _Source: src/form/types/index.ts_
7912
-
7913
- ### UnknownFormValue
7914
-
7915
- **Kind:** `type`
7916
-
7917
- Type-safe alternative to 'any' for unknown form values
7918
- Requires explicit type checking before use
7919
-
7920
- **Signature:**
7921
- ```typescript
7922
- export type UnknownFormValue = unknown;
7923
- ```
7924
-
7925
- _Source: src/form/types/contracts.ts_
7926
-
7927
6799
  ### UnknownRecord
7928
6800
 
7929
6801
  **Kind:** `type`
@@ -7974,50 +6846,6 @@ onDispose(() => unmarkDerived(model.$.total)); // при снятии compute с
7974
6846
 
7975
6847
  _Source: src/state/derived-registry.ts_
7976
6848
 
7977
- ### url
7978
-
7979
- **Kind:** `function`
7980
-
7981
- Фабрика валидатора URL.
7982
-
7983
- Пустые значения (`''`/`null`/`undefined`) пропускаются (используйте {@link required}
7984
- для обязательности). При `requireProtocol` протокол обязателен; `allowedProtocols`
7985
- дополнительно ограничивает набор допустимых протоколов.
7986
-
7987
- **Signature:**
7988
- ```typescript
7989
- export function url<TForm = unknown, TField extends string | null | undefined = string>(
7990
- options?: UrlValidatorOptions
7991
- ): Validator<TForm, TField>
7992
- ```
7993
-
7994
- **Parameters:**
7995
- - `options` — - Опции валидатора {@link UrlValidatorOptions}
7996
-
7997
- **Returns:** Чистый валидатор {@link Validator} для строкового поля
7998
-
7999
- **Examples:**
8000
-
8001
- Проверка URL
8002
- ```typescript
8003
- import { required, url } from '@reformer/core/validators';
8004
-
8005
- // Внутри FieldConfig схемы формы:
8006
- website: {
8007
- value: model.$.website,
8008
- component: Input,
8009
- validators: [required(), url({ message: 'Введите корректный URL' })],
8010
- },
8011
- // Требовать протокол и ограничить схему только https:
8012
- homepage: {
8013
- value: model.$.homepage,
8014
- component: Input,
8015
- validators: [url({ requireProtocol: true, allowedProtocols: ['https'] })],
8016
- },
8017
- ```
8018
-
8019
- _Source: src/form/validation/validators/url.ts_
8020
-
8021
6849
  ### useArrayLength
8022
6850
 
8023
6851
  **Kind:** `function`
@@ -8166,7 +6994,7 @@ onChange={e => control.setValue(e.target.checked)}
8166
6994
  }
8167
6995
 
8168
6996
  // Использование
8169
- control.setComponentProps({
6997
+ control.updateComponentProps({
8170
6998
  label: 'Accept terms and conditions',
8171
6999
  hint: 'Required to continue'
8172
7000
  });
@@ -8222,7 +7050,7 @@ control.push({ street: '', city: '' });
8222
7050
  };
8223
7051
 
8224
7052
  const handleRemove = (index: number) => {
8225
- control.remove(index);
7053
+ control.removeAt(index);
8226
7054
  };
8227
7055
 
8228
7056
  return (
@@ -8471,23 +7299,80 @@ return (
8471
7299
 
8472
7300
  _Source: src/form/hooks/useFormControlValue.ts_
8473
7301
 
8474
- ### ValidateAsyncOptions
7302
+ ### useFormValidation
7303
+
7304
+ **Kind:** `function`
7305
+
7306
+ Декларативный выбор стратегии валидации формы: одна точка вместо ручной разводки
7307
+ `validateModel`/`revalidateWhen`. Собирает стабильный {@link createFormValidation}-контроллер,
7308
+ армит реактивную стратегию на клиенте (`useEffect` → SSR-safe) и отдаёт `submit`/`isValidating`.
7309
+
7310
+ Схема-валидации — **стабильная ссылка** (обязанность вызывающего): контроллер мемоизируется по
7311
+ `[model, schema, strategy, debounce, liveAfterSubmit]`.
7312
+
7313
+ **Signature:**
7314
+ ```typescript
7315
+ export function useFormValidation<T>(args: UseFormValidationArgs<T>): UseFormValidationResult
7316
+ ```
7317
+
7318
+ **Examples:**
7319
+
7320
+ ```tsx
7321
+ const validation = defineValidationSchema<Form>(({ model }) => { ... }); // module-level
7322
+
7323
+ function MyForm() {
7324
+ const { submit, isValidating } = useFormValidation({
7325
+ model, schema: validation, strategy: 'afterFirstSubmit', debounce: 300,
7326
+ });
7327
+ const onSubmit = async (e: React.FormEvent) => {
7328
+ e.preventDefault();
7329
+ if (await submit()) await api.save(model.get());
7330
+ };
7331
+ return <form onSubmit={onSubmit}>{ ... }<button disabled={isValidating}>Отправить</button></form>;
7332
+ }
7333
+ ```
7334
+
7335
+ _Source: src/form/hooks/use-form-validation.ts_
7336
+
7337
+ ### UseFormValidationArgs
8475
7338
 
8476
7339
  **Kind:** `interface`
8477
7340
 
8478
7341
  **Signature:**
8479
7342
  ```typescript
8480
- export interface ValidateAsyncOptions extends ValidateOptions {
8481
- /** Задержка перед выполнением валидации (в мс). */
7343
+ export interface UseFormValidationArgs<T> {
7344
+ /** Модель данных формы. */
7345
+ model: FormModel<T>;
7346
+ /** Схема валидации. **Стабильная ссылка** (module-level `const` / `useMemo`) — иначе ломается дедуп раннера. */
7347
+ schema: ValidationSchema<T>;
7348
+ /** Стратегия запуска. Default `'submit'`. */
7349
+ strategy?: ValidationStrategyKind;
7350
+ /** Debounce (мс) для live-фаз (`change` / live-часть `afterFirstSubmit`). */
8482
7351
  debounce?: number;
7352
+ /** Режим live-фазы для `afterFirstSubmit`. Default `'change'`. */
7353
+ liveAfterSubmit?: 'change' | 'blur';
8483
7354
  }
8484
7355
  ```
8485
7356
 
8486
- **Deprecated:** Осиротевший остаток удалённого оператора `validateAsync` (Ф7): опция `debounce`
8487
- подключалась тем оператором, которого больше нет. Рантаймом не потребляется; экспортируется
8488
- только ради обратной совместимости.
7357
+ _Source: src/form/hooks/use-form-validation.ts_
8489
7358
 
8490
- _Source: src/form/types/validation-schema.ts_
7359
+ ### UseFormValidationResult
7360
+
7361
+ **Kind:** `interface`
7362
+
7363
+ **Signature:**
7364
+ ```typescript
7365
+ export interface UseFormValidationResult {
7366
+ /** Полный прогон + раскрытие ошибок (`touch:true`); для `onSubmit`. Стабильная ссылка. */
7367
+ submit: () => Promise<boolean>;
7368
+ /** Алиас `submit` для не-submit сценариев. */
7369
+ validate: () => Promise<boolean>;
7370
+ /** Идёт ли прогон (submit или live) — для блокировки кнопки. */
7371
+ isValidating: boolean;
7372
+ }
7373
+ ```
7374
+
7375
+ _Source: src/form/hooks/use-form-validation.ts_
8491
7376
 
8492
7377
  ### ValidateOptions
8493
7378
 
@@ -8591,33 +7476,3 @@ watchField(model.$.country, async (country) => {
8591
7476
  ```
8592
7477
 
8593
7478
  _Source: src/state/behaviors-value.ts_
8594
-
8595
- ### WithBehaviorSchema
8596
-
8597
- **Kind:** `interface`
8598
-
8599
- Интерфейс для узлов с методом applyBehaviorSchema
8600
-
8601
- **Signature:**
8602
- ```typescript
8603
- export interface WithBehaviorSchema {
8604
- applyBehaviorSchema(schemaFn: unknown): void;
8605
- }
8606
- ```
8607
-
8608
- _Source: src/form/types/index.ts_
8609
-
8610
- ### WithValidationSchema
8611
-
8612
- **Kind:** `interface`
8613
-
8614
- Интерфейс для узлов с методом applyValidationSchema
8615
-
8616
- **Signature:**
8617
- ```typescript
8618
- export interface WithValidationSchema {
8619
- applyValidationSchema(schemaFn: unknown): void;
8620
- }
8621
- ```
8622
-
8623
- _Source: src/form/types/index.ts_