@reformer/core 7.0.0-beta.1 → 7.0.0-beta.3

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 (40) hide show
  1. package/dist/core/factories/node-factory.d.ts +2 -1
  2. package/dist/core/model/behaviors.d.ts +13 -1
  3. package/dist/core/model/validate-model.d.ts +22 -0
  4. package/dist/core/nodes/field-node.d.ts +3 -3
  5. package/dist/core/nodes/group-node.d.ts +3 -5
  6. package/dist/core/nodes/model-array-node.d.ts +38 -0
  7. package/dist/core/types/validation-schema.d.ts +8 -2
  8. package/dist/core/utils/create-form.d.ts +83 -18
  9. package/dist/core/utils/derived-registry.d.ts +41 -2
  10. package/dist/core/utils/index.d.ts +0 -4
  11. package/dist/core/utils/signal-node-registry.d.ts +38 -4
  12. package/dist/core/validation/validators/email.d.ts +14 -4
  13. package/dist/core/validation/validators/future-date.d.ts +14 -4
  14. package/dist/core/validation/validators/index.d.ts +2 -1
  15. package/dist/core/validation/validators/integer.d.ts +13 -4
  16. package/dist/core/validation/validators/is-date.d.ts +14 -4
  17. package/dist/core/validation/validators/is-number.d.ts +15 -5
  18. package/dist/core/validation/validators/max-age.d.ts +16 -4
  19. package/dist/core/validation/validators/max-date.d.ts +16 -4
  20. package/dist/core/validation/validators/max-length.d.ts +18 -4
  21. package/dist/core/validation/validators/max.d.ts +15 -6
  22. package/dist/core/validation/validators/min-age.d.ts +16 -4
  23. package/dist/core/validation/validators/min-date.d.ts +16 -4
  24. package/dist/core/validation/validators/min-length.d.ts +18 -4
  25. package/dist/core/validation/validators/min.d.ts +15 -6
  26. package/dist/core/validation/validators/multiple-of.d.ts +15 -4
  27. package/dist/core/validation/validators/non-negative.d.ts +13 -4
  28. package/dist/core/validation/validators/non-zero.d.ts +13 -4
  29. package/dist/core/validation/validators/past-date.d.ts +14 -3
  30. package/dist/core/validation/validators/pattern.d.ts +24 -4
  31. package/dist/core/validation/validators/phone.d.ts +28 -4
  32. package/dist/core/validation/validators/required.d.ts +16 -5
  33. package/dist/core/validation/validators/url.d.ts +30 -7
  34. package/dist/hooks/useFormControlValue.d.ts +15 -10
  35. package/dist/index.js +562 -896
  36. package/llms.txt +2576 -2854
  37. package/package.json +2 -2
  38. package/dist/core/utils/abstract-registry.d.ts +0 -74
  39. package/dist/core/utils/form-observer.d.ts +0 -176
  40. package/dist/core/utils/registry-stack.d.ts +0 -69
@@ -9,7 +9,8 @@ import { FormNode } from '../nodes/form-node';
9
9
  * ```typescript
10
10
  * import { NodeFactory } from '@reformer/core';
11
11
  *
12
- * const node = NodeFactory.create({ value: '' }); // → FieldNode<string>
12
+ * const factory = new NodeFactory();
13
+ * const node = factory.createNode({ value: '', component: Input }); // → FieldNode<string>
13
14
  * ```
14
15
  */
15
16
  export declare class NodeFactory {
@@ -67,9 +67,21 @@ export declare function enableWhen(target: ReadonlySignal<unknown>, condition: (
67
67
  resetOnDisable?: boolean;
68
68
  }): BehaviorCleanup;
69
69
  /**
70
- * Условное выключение поля (инверсия {@link enableWhen}).
70
+ * Условное выключение поля (инверсия {@link enableWhen}). Резолвит ноду по сигналу-цели через реестр
71
+ * сигнал→нода и вызывает `disable()`, когда `condition` истинно (+`reset()` при `resetOnDisable`).
72
+ * `condition` реактивен (читает свои сигналы модели).
71
73
  *
72
74
  * @group Model
75
+ * @param target Сигнал-цель поля (`model.$.<path>`).
76
+ * @param condition Реактивное условие; при `true` поле выключается.
77
+ * @param options.resetOnDisable Сбросить значение при выключении (по умолчанию `false`).
78
+ * @returns Cleanup для отписки.
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * // Поле скидки недоступно, пока не выбран промо-тариф
83
+ * disableWhen(model.$.discount, () => model.plan !== 'promo', { resetOnDisable: true });
84
+ * ```
73
85
  */
74
86
  export declare function disableWhen(target: ReadonlySignal<unknown>, condition: () => boolean, options?: {
75
87
  resetOnDisable?: boolean;
@@ -21,6 +21,16 @@ export interface ModelValidationResult {
21
21
  * Синхронная headless-валидация данных. Асинхронные валидаторы пропускаются.
22
22
  *
23
23
  * @group Model
24
+ * @param model - Модель данных ({@link FormModel}), из сигналов которой читаются значения полей.
25
+ * @param schema - Единая схема формы (дерево узлов с `value`/`validators`, `{ when, children }`,
26
+ * секциями массивов). Обходится один раз для сбора активных полей.
27
+ * @returns {@link ModelValidationResult} — `valid` + ошибки по пути поля (без async-валидаторов).
28
+ *
29
+ * @example Быстрая синхронная проверка (например, для gate «можно ли перейти на след. шаг»)
30
+ * ```typescript
31
+ * const res = validateModelSync(model, schema);
32
+ * if (!res.valid) console.log(res.errors); // { 'email': [{ code, message }], ... }
33
+ * ```
24
34
  */
25
35
  export declare function validateModelSync<T>(model: FormModel<T>, schema: unknown): ModelValidationResult;
26
36
  /**
@@ -40,7 +50,19 @@ export declare function validateModel<T>(model: FormModel<T>, schema: unknown):
40
50
  * И поля выключенных веток (`{ when, children }` с ложным условием). Дерево обходится ОДИН раз.
41
51
  *
42
52
  * @group Model
53
+ * @param model - Модель данных ({@link FormModel}) — источник значений полей.
54
+ * @param schema - Единая схема формы (та же, что передавалась в `createForm`).
55
+ * @returns {@link ModelValidationResult} — `valid` + ошибки по пути поля; побочный эффект — ошибки
56
+ * разведены по нодам формы.
43
57
  * @remarks Поля, не материализованные в форме (элементы массива — строятся per-item), не роутятся
44
58
  * в родительскую форму; их ошибки доступны в возвращаемом результате по пути.
59
+ *
60
+ * @example Валидация перед submit (ошибки показываются в UI автоматически)
61
+ * ```typescript
62
+ * const form = createForm({ model, schema });
63
+ * form.touchAll();
64
+ * const res = await validateFormModel(model, schema);
65
+ * if (res.valid) await api.save(model.get());
66
+ * ```
45
67
  */
46
68
  export declare function validateFormModel<T>(model: FormModel<T>, schema: unknown): Promise<ModelValidationResult>;
@@ -196,13 +196,13 @@ export declare class FieldNode<T> extends FormNode<T> {
196
196
  * @example
197
197
  * ```typescript
198
198
  * // Сценарий 1: Instant feedback после submit
199
- * const form = new GroupNode({
199
+ * const form = createForm({
200
200
  * email: {
201
201
  * value: '',
202
202
  * component: Input,
203
203
  * updateOn: 'submit', // Изначально валидация только при submit
204
- * validators: [required, email]
205
- * }
204
+ * validators: [required, email],
205
+ * },
206
206
  * });
207
207
  *
208
208
  * await form.submit(async (values) => {
@@ -134,14 +134,12 @@ export declare class GroupNode<T> extends FormNode<T> {
134
134
  * @example
135
135
  * ```typescript
136
136
  * const form = new GroupNode({
137
- * controls: {
138
- * email: new FieldNode({ value: '' }),
139
- * name: new FieldNode({ value: '' })
140
- * }
137
+ * email: { value: '', component: Input },
138
+ * name: { value: '', component: Input },
141
139
  * });
142
140
  *
143
141
  * const proxy = form.getProxy();
144
- * console.log(proxy.email.value); // Прямой доступ к полю
142
+ * console.log(proxy.email.value.value); // Прямой доступ к полю
145
143
  * ```
146
144
  */
147
145
  getProxy(): FormProxy<T>;
@@ -15,6 +15,44 @@ export interface ModelArrayControl<TItem extends object> {
15
15
  clear(): void;
16
16
  toArray(): TItem[];
17
17
  }
18
+ /**
19
+ * Узел массива, делегирующий данные массиву {@link FormModel} (архитектура M1).
20
+ *
21
+ * В отличие от {@link ArrayNode} (владеет элементами сам), `ModelArrayNode` НЕ владеет данными:
22
+ * массив принадлежит модели, а узел держит per-item формы элементов (привязанные к сигналам
23
+ * под-моделей) и синхронизирует их с длиной массива модели. Мутации (`push`/`removeAt`/`move`/…)
24
+ * делегируются массиву модели; per-item формы кэшируются по идентичности под-модели, поэтому при
25
+ * reorder/повторном рендере не пересоздаются (состояние и валидация сохраняются). Реализует тот же
26
+ * контракт, что ждут секции массива и `useFormControl` (`length`/`value`/`valid`/`errors`/`at`/`push`/…).
27
+ *
28
+ * Обычно создаётся не напрямую, а `createForm({ model, schema })`: когда в схеме встречается узел
29
+ * массива `{ array: model.<field>, item: (item) => itemSchema }`, форма материализует его как
30
+ * `ModelArrayNode` и кладёт под `form.<field>` (совместим с `FormArraySection`).
31
+ *
32
+ * @group Nodes
33
+ *
34
+ * @example Массив как часть формы (через createForm)
35
+ * ```typescript
36
+ * const model = createModel<{ rows: { name: string; qty: number }[] }>({ rows: [] });
37
+ *
38
+ * const rowItem = (item: FormModel<{ name: string; qty: number }>) => ({
39
+ * name: { value: item.$.name, component: Input },
40
+ * qty: { value: item.$.qty, component: Input },
41
+ * });
42
+ *
43
+ * const form = createForm({
44
+ * model,
45
+ * schema: {
46
+ * children: [{ array: model.rows, item: rowItem }],
47
+ * },
48
+ * });
49
+ *
50
+ * const rows = form.rows as unknown as ModelArrayNode<{ name: string; qty: number }>;
51
+ * rows.push({ name: 'A', qty: 1 }); // мутация уезжает в model.rows
52
+ * rows.at(0)?.name.setValue('B'); // правка поля элемента доезжает в под-модель
53
+ * rows.length.value; // 1 (реактивная длина)
54
+ * ```
55
+ */
18
56
  export declare class ModelArrayNode<T extends object> extends FormNode<T[]> {
19
57
  private readonly control;
20
58
  private readonly buildItem;
@@ -6,13 +6,19 @@ import { FormProxy } from './form-proxy';
6
6
  * Принимает значение поля, прокси текущего поля (control) и прокси корня формы (root).
7
7
  * Возвращает ValidationError либо null. Не знает про реестр валидации.
8
8
  *
9
- * @example
9
+ * @example Кастомный валидатор в массиве `validators` поля схемы
10
10
  * ```typescript
11
11
  * const isAdult: Validator<MyForm, number> = (value, control, root) => {
12
12
  * if (value < 18) return { code: 'tooYoung', message: '18+' };
13
13
  * return null;
14
14
  * };
15
- * validate(path.age, isAdult);
15
+ *
16
+ * // Фабрики и кастомные валидаторы кладутся в `validators: [...]` поля:
17
+ * const schema = {
18
+ * children: [
19
+ * { value: model.$.age, component: Input, validators: [required(), isAdult] },
20
+ * ],
21
+ * };
16
22
  * ```
17
23
  */
18
24
  export type Validator<TForm, TField> = (value: TField, control: FormProxy<TField>, root: FormProxy<TForm>) => ValidationError | null;
@@ -21,43 +21,108 @@ export interface CreateFormFromModelArgs<T> {
21
21
  */
22
22
  behavior?: FormBehavior<T>;
23
23
  }
24
+ /**
25
+ * Собрать форму из {@link FormModel} и единой схемы (низкоуровневая фабрика архитектуры M1).
26
+ *
27
+ * Значения принадлежат модели (источник истины), ноды формы держат UI/валидационное состояние и
28
+ * ссылаются на сигналы модели по идентичности (`node.value === model.$.path`). Обходит структуру
29
+ * модели, привязывает конфиг поля (component/componentProps/validators) из схемы, материализует
30
+ * top-level массивы как {@link ModelArrayNode}, заполняет реестр сигнал→нода (для `enableWhen`/
31
+ * роутинга ошибок) и, при наличии, запускает декларативное поведение (cleanup живёт на форме).
32
+ *
33
+ * Обычно вызывается неявно через {@link createForm} с аргументом `{ model, schema }` — прямой вызов
34
+ * нужен редко (например, для построения формы элемента массива).
35
+ *
36
+ * @typeParam T - Тип модели данных формы
37
+ * @param args - Модель, единая схема и (опционально) декларативное поведение {@link CreateFormFromModelArgs}
38
+ * @returns Типизированная форма с Proxy-доступом к полям {@link FormProxy}
39
+ *
40
+ * @example Форма из модели + схемы (эквивалент `createForm({ model, schema })`)
41
+ * ```typescript
42
+ * import { createModel, createFormFromModel } from '@reformer/core';
43
+ *
44
+ * interface Form {
45
+ * email: string;
46
+ * profile: { name: string; age: number };
47
+ * }
48
+ *
49
+ * const model = createModel<Form>({ email: '', profile: { name: '', age: 0 } });
50
+ * const schema = {
51
+ * component: Section,
52
+ * children: [
53
+ * { value: model.$.email, component: Input, validators: [required] },
54
+ * { value: model.$.profile.name, component: Input },
55
+ * ],
56
+ * };
57
+ *
58
+ * const form = createFormFromModel<Form>({ model, schema });
59
+ *
60
+ * // Двусторонняя связь нода ↔ модель:
61
+ * form.email.setValue('user@mail.com');
62
+ * console.log(model.email); // 'user@mail.com'
63
+ * ```
64
+ *
65
+ * @see {@link createForm} - основная фабрика (диспетчеризует сюда при аргументе `{ model, schema }`)
66
+ * @group Utilities
67
+ */
24
68
  export declare function createFormFromModel<T>(args: CreateFormFromModelArgs<T>): FormProxy<T>;
25
69
  /**
26
- * Создать форму с полной конфигурацией (form, behavior, validation)
70
+ * Создать форму из {@link FormModel} + единой схемы (архитектура M1, рекомендуемый путь).
27
71
  *
28
72
  * @group Utilities
29
73
  *
30
- * @param config - Конфигурация формы с полями, поведением и валидацией
74
+ * @param args - Модель данных, единая схема (component/componentProps/validators) и (опционально) поведение
31
75
  * @returns Типизированная форма с Proxy-доступом к полям
32
76
  *
33
- * @example
77
+ * @example Архитектура M1: `createModel` + единая схема + `createForm({ model, schema })`
34
78
  * ```typescript
35
- * const form = createForm<UserForm>({
36
- * form: {
37
- * email: { value: '', component: Input },
38
- * password: { value: '', component: Input },
39
- * },
40
- * validation: (path) => {
41
- * required(path.email);
42
- * email(path.email);
43
- * required(path.password);
44
- * minLength(path.password, 8);
45
- * },
46
- * });
79
+ * import { createModel, createForm, validateFormModel } from '@reformer/core';
80
+ * import { required, email, minLength } from '@reformer/core/validators';
81
+ *
82
+ * interface UserForm {
83
+ * email: string;
84
+ * password: string;
85
+ * }
47
86
  *
48
- * // TypeScript знает о полях:
87
+ * const model = createModel<UserForm>({ email: '', password: '' });
88
+ *
89
+ * const schema = {
90
+ * children: [
91
+ * {
92
+ * value: model.$.email,
93
+ * component: Input,
94
+ * validators: [required(), email()],
95
+ * },
96
+ * {
97
+ * value: model.$.password,
98
+ * component: Input,
99
+ * validators: [required(), minLength(8)],
100
+ * },
101
+ * ],
102
+ * };
103
+ *
104
+ * const form = createForm<UserForm>({ model, schema });
105
+ *
106
+ * // TypeScript знает о полях (нода привязана к сигналу модели):
49
107
  * form.email.setValue('test@mail.com');
108
+ *
109
+ * // Валидация всей модели по схеме (sync + async):
110
+ * const { valid } = await validateFormModel(model, schema);
50
111
  * ```
51
112
  */
52
113
  export declare function createForm<T>(args: CreateFormFromModelArgs<T>): FormProxy<T>;
53
114
  export declare function createForm<T>(config: GroupNodeConfig<T>): FormProxy<T>;
54
115
  /**
55
- * Создать форму только со схемой полей (обратная совместимость)
116
+ * Создать форму только со схемой полей.
117
+ *
118
+ * @deprecated Legacy / back-compat: плоская `FormSchema` с инлайн-значениями (`value: ''`) — путь
119
+ * ДО архитектуры M1. Для нового кода используйте перегрузку `createForm({ model, schema })`
120
+ * (значения принадлежат {@link FormModel}, валидаторы — фабрики в `validators: [...]`).
56
121
  *
57
122
  * @param schema - Схема полей формы
58
123
  * @returns Типизированная форма с Proxy-доступом к полям
59
124
  *
60
- * @example
125
+ * @example Legacy (back-compat) — плоская схема без модели
61
126
  * ```typescript
62
127
  * const form = createForm<UserForm>({
63
128
  * email: { value: '', component: Input },
@@ -1,5 +1,44 @@
1
1
  import { Signal } from '@preact/signals-core';
2
- /** Пометить сигнал производным (вызывают compute/computeFrom). */
2
+ /**
3
+ * Пометить сигнал производным (вычисляемым).
4
+ *
5
+ * Вызывается операторами {@link computeFrom}/`compute` для их сигнала-цели. После этого
6
+ * bulk-сеттеры (`model.set`/`model.patch`, `patchValue`/`setValue`) пропускают это поле, чтобы
7
+ * значение из payload не затирало вычисляемое. Прикладной код напрямую обычно не вызывает.
8
+ *
9
+ * @param signal - Сигнал значения из {@link FormModel}, которым владеет compute
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { markDerived } from '@reformer/core';
14
+ *
15
+ * // Помечаем поле total как вычисляемое — bulk-set его не перезапишет
16
+ * markDerived(model.$.total);
17
+ * ```
18
+ *
19
+ * @see {@link isDerived} - проверка пометки
20
+ * @group Utilities
21
+ */
3
22
  export declare function markDerived(signal: Signal<any>): void;
4
- /** Производный ли сигнал (читают bulk-сеттеры, чтобы не затирать вычисляемые поля). */
23
+ /**
24
+ * Производный ли сигнал (помечен через {@link markDerived}).
25
+ *
26
+ * Читается bulk-сеттерами модели/группы, чтобы не затирать вычисляемые (`computeFrom`) поля
27
+ * значениями из payload.
28
+ *
29
+ * @param signal - Сигнал значения из {@link FormModel}
30
+ * @returns `true`, если сигнал помечен производным
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * import { isDerived } from '@reformer/core';
35
+ *
36
+ * if (!isDerived(model.$.total)) {
37
+ * model.$.total.value = payload.total; // писать в payload-значение только для «ручных» полей
38
+ * }
39
+ * ```
40
+ *
41
+ * @see {@link markDerived} - пометить сигнал производным
42
+ * @group Utilities
43
+ */
5
44
  export declare function isDerived(signal: Signal<any>): boolean;
@@ -4,7 +4,6 @@
4
4
  * Централизованные вспомогательные классы и функции.
5
5
  */
6
6
  export { SubscriptionManager } from './subscription-manager';
7
- export { RegistryStack } from './registry-stack';
8
7
  export { isFormNode, isFieldNode, isGroupNode, isArrayNode, getNodeType } from './type-guards';
9
8
  export { FormErrorHandler, ErrorStrategy } from './error-handler';
10
9
  export { createForm, createFormFromModel } from './create-form';
@@ -13,10 +12,7 @@ export { registerSignalNode, getNodeForSignal } from './signal-node-registry';
13
12
  export { markDerived, isDerived } from './derived-registry';
14
13
  export { uniqueId } from './unique-id';
15
14
  export { safeCallback, runOutsideEffect, safeDebouncedCallback } from './safe-effect';
16
- export { AbstractRegistry } from './abstract-registry';
17
15
  export { FormSubmitter } from './form-submitter';
18
16
  export type { SubmittableForm, SubmitOptions, SubmitResult } from './form-submitter';
19
17
  export { FormStatusMachine } from './status-machine';
20
18
  export type { StatusEvent } from './status-machine';
21
- export { FormObserver } from './form-observer';
22
- export type { FormChangeType, FormChangeEvent, FormChangeCallback, FormObserverOptions, ObservableForm, ObservableFormNode, } from './form-observer';
@@ -1,12 +1,46 @@
1
1
  import { Signal } from '@preact/signals-core';
2
2
  import { FormNode } from '../nodes/form-node';
3
3
  /**
4
- * Связать сигнал модели с его FieldNode.
5
- * @internal
4
+ * Связать сигнал модели с его нодой формы.
5
+ *
6
+ * Вызывается движком при сборке формы (`createForm`/{@link createFormFromModel}) для каждого
7
+ * листового поля. Прикладной код обычно этот реестр не заполняет напрямую.
8
+ *
9
+ * @param signal - Сигнал значения из {@link FormModel} (ручка поля, `model.$.path`)
10
+ * @param node - Нода формы, отвечающая за это поле
11
+ *
12
+ * @example Привязка листовых полей при построении формы
13
+ * ```typescript
14
+ * import { registerSignalNode } from '@reformer/core';
15
+ *
16
+ * const sig = model.signalAt('profile.email');
17
+ * const node = group.getFieldByPath('profile.email');
18
+ * if (sig && node) registerSignalNode(sig, node);
19
+ * ```
20
+ *
21
+ * @see {@link getNodeForSignal} - обратный поиск ноды по сигналу
22
+ * @group Utilities
6
23
  */
7
24
  export declare function registerSignalNode(signal: Signal<any>, node: FormNode<any>): void;
8
25
  /**
9
- * Получить FieldNode по сигналу модели (или undefined, если форма не построена/поле не материализовано,
10
- * например элемент массива в родительской форме).
26
+ * Найти ноду формы по сигналу модели.
27
+ *
28
+ * Используется state-операциями behavior (`enableWhen`/`disableWhen`) и роутингом ошибок
29
+ * валидации в ноды. Возвращает `undefined`, если форма ещё не построена или поле не
30
+ * материализовано в этой форме (например, элемент массива, который строится per-item).
31
+ *
32
+ * @param signal - Сигнал значения из {@link FormModel}
33
+ * @returns Нода формы для этого поля или `undefined`
34
+ *
35
+ * @example Роутинг ошибок валидации в ноду поля
36
+ * ```typescript
37
+ * import { getNodeForSignal } from '@reformer/core';
38
+ *
39
+ * const sig = model.$.email;
40
+ * getNodeForSignal(sig)?.setErrors([{ code: 'required', message: 'Обязательно' }]);
41
+ * ```
42
+ *
43
+ * @see {@link registerSignalNode} - регистрация связи сигнал→нода
44
+ * @group Utilities
11
45
  */
12
46
  export declare function getNodeForSignal(signal: Signal<any>): FormNode<any> | undefined;
@@ -2,12 +2,22 @@ import { Validator, ValidateOptions } from '../../types/validation-schema';
2
2
  /**
3
3
  * Фабрика валидатора формата email.
4
4
  *
5
- * Пустые значения пропускаются (используйте `required` для обязательности).
5
+ * Проверяет по упрощённому regex `^[^\s@]+@[^\s@]+\.[^\s@]+$`. Пустые значения
6
+ * (`''`/`null`/`undefined`) пропускаются (используйте {@link required} для обязательности).
6
7
  *
7
- * @example
8
+ * @param options - Опции валидатора ({@link ValidateOptions}): `message`, `params`
9
+ * @returns Чистый валидатор {@link Validator} для строкового поля
10
+ *
11
+ * @example Проверка формата email
8
12
  * ```typescript
9
- * validate(path.email, email());
10
- * validate(path.email, email({ message: 'Введите корректный email' }));
13
+ * import { required, email } from '@reformer/core/validators';
14
+ *
15
+ * // Внутри FieldConfig схемы формы:
16
+ * email: {
17
+ * value: model.$.email,
18
+ * component: Input,
19
+ * validators: [required(), email({ message: 'Введите корректный email' })],
20
+ * },
11
21
  * ```
12
22
  */
13
23
  export declare function email<TForm = unknown, TField extends string | undefined = string>(options?: ValidateOptions): Validator<TForm, TField>;
@@ -2,12 +2,22 @@ import { Validator, ValidateOptions } from '../../types/validation-schema';
2
2
  /**
3
3
  * Фабрика валидатора, проверяющего что дата не в прошлом.
4
4
  *
5
- * Пустые и невалидные даты пропускаются.
5
+ * Дата не должна быть раньше сегодняшнего дня (сравнение по нормализованным датам).
6
+ * Пустые и невалидные даты пропускаются (используйте {@link required} и {@link isDate}).
6
7
  *
7
- * @example
8
+ * @param options - Опции валидатора ({@link ValidateOptions}): `message`, `params`
9
+ * @returns Чистый валидатор {@link Validator} для поля даты (`string | Date`)
10
+ *
11
+ * @example Дата не в прошлом
8
12
  * ```typescript
9
- * validate(path.eventDate, futureDate());
10
- * validate(path.appointmentDate, futureDate({ message: 'Дата записи должна быть в будущем' }));
13
+ * import { required, futureDate } from '@reformer/core/validators';
14
+ *
15
+ * // Внутри FieldConfig схемы формы:
16
+ * appointmentDate: {
17
+ * value: model.$.appointmentDate,
18
+ * component: DatePicker,
19
+ * validators: [required(), futureDate({ message: 'Дата записи должна быть в будущем' })],
20
+ * },
11
21
  * ```
12
22
  */
13
23
  export declare function futureDate<TForm = unknown, TField extends string | Date | undefined = string | Date>(options?: ValidateOptions): Validator<TForm, TField>;
@@ -2,7 +2,8 @@
2
2
  * Reusable validator factories.
3
3
  *
4
4
  * Все примитивы — фабрики, возвращающие чистый Validator<TForm, TField>.
5
- * Использование: `validate(path.x, required())`, `validate(path.y, min(18))`.
5
+ * Импортируются из `@reformer/core/validators` и передаются в массив `validators`
6
+ * поля схемы формы: `validators: [required(), min(18)]`.
6
7
  */
7
8
  export { required } from './required';
8
9
  export { min } from './min';
@@ -2,12 +2,21 @@ import { Validator, ValidateOptions } from '../../types/validation-schema';
2
2
  /**
3
3
  * Фабрика валидатора, проверяющего что число — целое.
4
4
  *
5
- * Пустые значения и не-числа пропускаются (используйте `required` и `isNumber`).
5
+ * Пустые значения и не-числа пропускаются (используйте {@link required} и {@link isNumber}).
6
6
  *
7
- * @example
7
+ * @param options - Опции валидатора ({@link ValidateOptions}): `message`, `params`
8
+ * @returns Чистый валидатор {@link Validator} для числового поля
9
+ *
10
+ * @example Проверка целого числа
8
11
  * ```typescript
9
- * validate(path.age, integer());
10
- * validate(path.count, integer({ message: 'Должно быть целым числом' }));
12
+ * import { required, integer } from '@reformer/core/validators';
13
+ *
14
+ * // Внутри FieldConfig схемы формы:
15
+ * count: {
16
+ * value: model.$.count,
17
+ * component: Input,
18
+ * validators: [required(), integer({ message: 'Должно быть целым числом' })],
19
+ * },
11
20
  * ```
12
21
  */
13
22
  export declare function integer<TForm = unknown, TField extends number | undefined = number>(options?: ValidateOptions): Validator<TForm, TField>;
@@ -2,12 +2,22 @@ import { Validator, ValidateOptions } from '../../types/validation-schema';
2
2
  /**
3
3
  * Фабрика валидатора, проверяющего что значение — валидная дата.
4
4
  *
5
- * Пустые значения пропускаются (используйте `required` для обязательности).
5
+ * Принимает `Date` или строку, парсимую в дату. Пустые значения (`''`/`null`/`undefined`)
6
+ * пропускаются (используйте {@link required} для обязательности).
6
7
  *
7
- * @example
8
+ * @param options - Опции валидатора ({@link ValidateOptions}): `message`, `params`
9
+ * @returns Чистый валидатор {@link Validator} для поля даты (`string | Date`)
10
+ *
11
+ * @example Проверка валидности даты
8
12
  * ```typescript
9
- * validate(path.birthDate, isDate());
10
- * validate(path.eventDate, isDate({ message: 'Введите корректную дату' }));
13
+ * import { required, isDate } from '@reformer/core/validators';
14
+ *
15
+ * // Внутри FieldConfig схемы формы:
16
+ * eventDate: {
17
+ * value: model.$.eventDate,
18
+ * component: DatePicker,
19
+ * validators: [required(), isDate({ message: 'Введите корректную дату' })],
20
+ * },
11
21
  * ```
12
22
  */
13
23
  export declare function isDate<TForm = unknown, TField extends string | Date | undefined = string | Date>(options?: ValidateOptions): Validator<TForm, TField>;
@@ -2,13 +2,23 @@ import { Validator, ValidateOptions } from '../../types/validation-schema';
2
2
  /**
3
3
  * Фабрика валидатора, проверяющего что значение — конечное число (не NaN, не строка).
4
4
  *
5
- * Пустые значения (`null`/`undefined`) пропускаются (используйте `required` для обязательности).
6
- * В отличие от других number-валидаторов, **не** пропускает не-числа — это его задача.
5
+ * Пустые значения (`null`/`undefined`) пропускаются (используйте {@link required} для
6
+ * обязательности). В отличие от других number-валидаторов, **не** пропускает не-числа
7
+ * и `NaN` — это его задача.
7
8
  *
8
- * @example
9
+ * @param options - Опции валидатора ({@link ValidateOptions}): `message`, `params`
10
+ * @returns Чистый валидатор {@link Validator} для числового поля
11
+ *
12
+ * @example Проверка, что значение — число
9
13
  * ```typescript
10
- * validate(path.amount, isNumber());
11
- * validate(path.amount, isNumber({ message: 'Введите число' }));
14
+ * import { required, isNumber } from '@reformer/core/validators';
15
+ *
16
+ * // Внутри FieldConfig схемы формы:
17
+ * amount: {
18
+ * value: model.$.amount,
19
+ * component: Input,
20
+ * validators: [required(), isNumber({ message: 'Введите число' })],
21
+ * },
12
22
  * ```
13
23
  */
14
24
  export declare function isNumber<TForm = unknown, TField extends number | undefined = number>(options?: ValidateOptions): Validator<TForm, TField>;
@@ -2,12 +2,24 @@ import { Validator, ValidateOptions } from '../../types/validation-schema';
2
2
  /**
3
3
  * Фабрика валидатора максимального возраста (по дате рождения).
4
4
  *
5
- * Пустые и невалидные даты пропускаются.
5
+ * Возраст вычисляется по дате рождения относительно сегодняшнего дня. Пустые и невалидные
6
+ * даты пропускаются (используйте {@link required} и {@link isDate}).
6
7
  *
7
- * @example
8
+ * @param maxAgeValue - Максимально допустимый возраст (в полных годах)
9
+ * @param options - Опции валидатора ({@link ValidateOptions}). В `params` ошибки автоматически
10
+ * попадают `maxAge` и `currentAge`.
11
+ * @returns Чистый валидатор {@link Validator} для поля даты рождения (`string | Date`)
12
+ *
13
+ * @example Максимальный возраст
8
14
  * ```typescript
9
- * validate(path.birthDate, maxAge(65));
10
- * validate(path.birthDate, maxAge(100, { message: 'Проверьте дату рождения' }));
15
+ * import { maxAge } from '@reformer/core/validators';
16
+ *
17
+ * // Внутри FieldConfig схемы формы:
18
+ * birthDate: {
19
+ * value: model.$.birthDate,
20
+ * component: DatePicker,
21
+ * validators: [maxAge(100, { message: 'Проверьте дату рождения' })],
22
+ * },
11
23
  * ```
12
24
  */
13
25
  export declare function maxAge<TForm = unknown, TField extends string | Date | null | undefined = string | Date>(maxAgeValue: number, options?: ValidateOptions): Validator<TForm, TField>;
@@ -2,12 +2,24 @@ import { Validator, ValidateOptions } from '../../types/validation-schema';
2
2
  /**
3
3
  * Фабрика валидатора максимальной даты (включительно).
4
4
  *
5
- * Пустые и невалидные даты пропускаются.
5
+ * Сравнение по нормализованным датам (время обнуляется). Пустые и невалидные даты
6
+ * пропускаются (используйте {@link required} и {@link isDate}).
6
7
  *
7
- * @example
8
+ * @param maxDateValue - Максимально допустимая дата (включительно)
9
+ * @param options - Опции валидатора ({@link ValidateOptions}). В `params` ошибки автоматически
10
+ * попадает `maxDate`.
11
+ * @returns Чистый валидатор {@link Validator} для поля даты (`string | Date`)
12
+ *
13
+ * @example Максимальная дата
8
14
  * ```typescript
9
- * validate(path.birthDate, maxDate(new Date())); // не позже сегодня
10
- * validate(path.endDate, maxDate(new Date('2025-12-31')));
15
+ * import { maxDate } from '@reformer/core/validators';
16
+ *
17
+ * // Внутри FieldConfig схемы формы:
18
+ * birthDate: {
19
+ * value: model.$.birthDate,
20
+ * component: DatePicker,
21
+ * validators: [maxDate(new Date(), { message: 'Дата не может быть в будущем' })],
22
+ * },
11
23
  * ```
12
24
  */
13
25
  export declare function maxDate<TForm = unknown, TField extends string | Date | null | undefined = string | Date>(maxDateValue: Date, options?: ValidateOptions): Validator<TForm, TField>;