@reformer/core 11.0.0-beta.4 → 11.0.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/form/create-form.d.ts +11 -9
- package/dist/form/factories/node-factory.d.ts +17 -16
- package/dist/form/nodes/array-node.d.ts +3 -3
- package/dist/form/nodes/field-node.d.ts +6 -3
- package/dist/form/nodes/group-node.d.ts +7 -7
- package/dist/form/nodes/model-array-node.d.ts +2 -2
- package/dist/form/types/deep-schema.d.ts +5 -5
- package/dist/form/validators/email.d.ts +5 -6
- package/dist/form/validators/file-type.d.ts +5 -6
- package/dist/form/validators/future-date.d.ts +5 -6
- package/dist/form/validators/index.d.ts +3 -2
- package/dist/form/validators/integer.d.ts +5 -6
- package/dist/form/validators/is-date.d.ts +5 -6
- package/dist/form/validators/is-number.d.ts +5 -6
- package/dist/form/validators/max-age.d.ts +5 -6
- package/dist/form/validators/max-date.d.ts +5 -6
- package/dist/form/validators/max-file-size.d.ts +5 -6
- package/dist/form/validators/max-files.d.ts +5 -6
- package/dist/form/validators/max-length.d.ts +6 -7
- package/dist/form/validators/max-total-file-size.d.ts +5 -6
- package/dist/form/validators/max.d.ts +6 -7
- package/dist/form/validators/min-age.d.ts +5 -6
- package/dist/form/validators/min-date.d.ts +5 -6
- package/dist/form/validators/min-file-size.d.ts +5 -6
- package/dist/form/validators/min-files.d.ts +5 -6
- package/dist/form/validators/min-length.d.ts +6 -7
- package/dist/form/validators/min.d.ts +6 -7
- package/dist/form/validators/multiple-of.d.ts +5 -6
- package/dist/form/validators/non-negative.d.ts +5 -6
- package/dist/form/validators/non-zero.d.ts +5 -6
- package/dist/form/validators/past-date.d.ts +5 -6
- package/dist/form/validators/pattern.d.ts +6 -14
- package/dist/form/validators/phone.d.ts +5 -6
- package/dist/form/validators/required.d.ts +7 -12
- package/dist/form/validators/url.d.ts +7 -12
- package/dist/index.js +26 -23
- package/docs/llms/02-quick-start.md +6 -6
- package/docs/llms/03-api-signatures.md +3 -3
- package/docs/llms/05-common-mistakes.md +1 -1
- package/docs/llms/09-formschema.md +11 -11
- package/docs/llms/10-arrays.md +4 -4
- package/docs/llms/14-extended-mistakes.md +1 -1
- package/docs/llms/15-project-structure.md +8 -7
- package/docs/llms/16-ui-components.md +6 -6
- package/docs/llms/17-nonexistent-api.md +2 -2
- package/docs/llms/29-async-preload.md +4 -4
- package/docs/llms/30-type-safety-recipes.md +1 -1
- package/llms-index.json +1 -0
- package/llms.txt +2043 -224
- package/package.json +2 -1
|
@@ -12,14 +12,13 @@ import { Validator, ValidateOptions } from '../types/validation-schema';
|
|
|
12
12
|
*
|
|
13
13
|
* @example Минимальная дата
|
|
14
14
|
* ```typescript
|
|
15
|
+
* import { defineValidationSchema, validate } from '@reformer/core/validation';
|
|
15
16
|
* import { required, minDate } from '@reformer/core/validators';
|
|
16
17
|
*
|
|
17
|
-
* //
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* validators: [required(), minDate(new Date(), { message: 'Дата не раньше сегодня' })],
|
|
22
|
-
* },
|
|
18
|
+
* // Правила живут в отдельной схеме над МОДЕЛЬЮ — layout-схема валидаторов не несёт.
|
|
19
|
+
* const validation = defineValidationSchema<MyForm>(({ model }) => {
|
|
20
|
+
* validate(model.$.startDate, [required(), minDate(new Date(), { message: 'Дата не раньше сегодня' })]);
|
|
21
|
+
* });
|
|
23
22
|
* ```
|
|
24
23
|
*/
|
|
25
24
|
export declare function minDate<TForm = unknown, TField extends string | Date | null | undefined = string | Date>(minDateValue: Date, options?: ValidateOptions): Validator<TForm, TField>;
|
|
@@ -15,14 +15,13 @@ import { Validator, ValidateOptions } from '../types/validation-schema';
|
|
|
15
15
|
*
|
|
16
16
|
* @example Отсев пустых файлов
|
|
17
17
|
* ```typescript
|
|
18
|
+
* import { defineValidationSchema, validate } from '@reformer/core/validation';
|
|
18
19
|
* import { minFileSize } from '@reformer/core/validators';
|
|
19
20
|
*
|
|
20
|
-
* //
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* validators: [minFileSize(1, { message: 'Файл пустой' })],
|
|
25
|
-
* },
|
|
21
|
+
* // Правила живут в отдельной схеме над МОДЕЛЬЮ — layout-схема валидаторов не несёт.
|
|
22
|
+
* const validation = defineValidationSchema<MyForm>(({ model }) => {
|
|
23
|
+
* validate(model.$.documents, [minFileSize(1, { message: 'Файл пустой' })]);
|
|
24
|
+
* });
|
|
26
25
|
* ```
|
|
27
26
|
*/
|
|
28
27
|
export declare function minFileSize<TForm = unknown, TField = unknown>(minSize: number, options?: ValidateOptions): Validator<TForm, TField>;
|
|
@@ -13,14 +13,13 @@ import { Validator, ValidateOptions } from '../types/validation-schema';
|
|
|
13
13
|
*
|
|
14
14
|
* @example Не менее двух документов
|
|
15
15
|
* ```typescript
|
|
16
|
+
* import { defineValidationSchema, validate } from '@reformer/core/validation';
|
|
16
17
|
* import { required, minFiles } from '@reformer/core/validators';
|
|
17
18
|
*
|
|
18
|
-
* //
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* validators: [required(), minFiles(2, { message: 'Приложите минимум 2 документа' })],
|
|
23
|
-
* },
|
|
19
|
+
* // Правила живут в отдельной схеме над МОДЕЛЬЮ — layout-схема валидаторов не несёт.
|
|
20
|
+
* const validation = defineValidationSchema<MyForm>(({ model }) => {
|
|
21
|
+
* validate(model.$.documents, [required(), minFiles(2, { message: 'Приложите минимум 2 документа' })]);
|
|
22
|
+
* });
|
|
24
23
|
* ```
|
|
25
24
|
*/
|
|
26
25
|
export declare function minFiles<TForm = unknown, TField = unknown>(min: number, options?: ValidateOptions): Validator<TForm, TField>;
|
|
@@ -13,15 +13,14 @@ import { Validator, ValidateOptions } from '../types/validation-schema';
|
|
|
13
13
|
*
|
|
14
14
|
* @example Минимальная длина строки
|
|
15
15
|
* ```typescript
|
|
16
|
+
* import { defineValidationSchema, validate } from '@reformer/core/validation';
|
|
16
17
|
* import { required, minLength } from '@reformer/core/validators';
|
|
17
18
|
*
|
|
18
|
-
* //
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* validators: [required(), minLength(8, { message: 'Минимум 8 символов' })],
|
|
24
|
-
* },
|
|
19
|
+
* // Правила живут в отдельной схеме над МОДЕЛЬЮ — layout-схема валидаторов не несёт.
|
|
20
|
+
* const validation = defineValidationSchema<MyForm>(({ model }) => {
|
|
21
|
+
* validate(model.$.name, [minLength(2)]);
|
|
22
|
+
* validate(model.$.password, [required(), minLength(8, { message: 'Минимум 8 символов' })]);
|
|
23
|
+
* });
|
|
25
24
|
* ```
|
|
26
25
|
*/
|
|
27
26
|
export declare function minLength<TForm = unknown, TField = unknown>(minLen: number, options?: ValidateOptions): Validator<TForm, TField>;
|
|
@@ -11,15 +11,14 @@ import { Validator, ValidateOptions } from '../types/validation-schema';
|
|
|
11
11
|
*
|
|
12
12
|
* @example Минимальное значение числового поля
|
|
13
13
|
* ```typescript
|
|
14
|
+
* import { defineValidationSchema, validate } from '@reformer/core/validation';
|
|
14
15
|
* import { required, min } from '@reformer/core/validators';
|
|
15
16
|
*
|
|
16
|
-
* //
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* validators: [required(), min(1, { message: 'Минимум 1' })],
|
|
22
|
-
* },
|
|
17
|
+
* // Правила живут в отдельной схеме над МОДЕЛЬЮ — layout-схема валидаторов не несёт.
|
|
18
|
+
* const validation = defineValidationSchema<MyForm>(({ model }) => {
|
|
19
|
+
* validate(model.$.age, [min(18)]);
|
|
20
|
+
* validate(model.$.quantity, [required(), min(1, { message: 'Минимум 1' })]);
|
|
21
|
+
* });
|
|
23
22
|
* ```
|
|
24
23
|
*/
|
|
25
24
|
export declare function min<TForm = unknown, TField extends number | null | undefined = number>(minValue: number, options?: ValidateOptions): Validator<TForm, TField>;
|
|
@@ -11,14 +11,13 @@ import { Validator, ValidateOptions } from '../types/validation-schema';
|
|
|
11
11
|
*
|
|
12
12
|
* @example Проверка кратности
|
|
13
13
|
* ```typescript
|
|
14
|
+
* import { defineValidationSchema, validate } from '@reformer/core/validation';
|
|
14
15
|
* import { multipleOf } from '@reformer/core/validators';
|
|
15
16
|
*
|
|
16
|
-
* //
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* validators: [multipleOf(0.5, { message: 'Только шаг 0.5' })],
|
|
21
|
-
* },
|
|
17
|
+
* // Правила живут в отдельной схеме над МОДЕЛЬЮ — layout-схема валидаторов не несёт.
|
|
18
|
+
* const validation = defineValidationSchema<MyForm>(({ model }) => {
|
|
19
|
+
* validate(model.$.rating, [multipleOf(0.5, { message: 'Только шаг 0.5' })]);
|
|
20
|
+
* });
|
|
22
21
|
* ```
|
|
23
22
|
*/
|
|
24
23
|
export declare function multipleOf<TForm = unknown, TField extends number | null | undefined = number>(divisor: number, options?: ValidateOptions): Validator<TForm, TField>;
|
|
@@ -9,14 +9,13 @@ import { Validator, ValidateOptions } from '../types/validation-schema';
|
|
|
9
9
|
*
|
|
10
10
|
* @example Проверка неотрицательности
|
|
11
11
|
* ```typescript
|
|
12
|
+
* import { defineValidationSchema, validate } from '@reformer/core/validation';
|
|
12
13
|
* import { nonNegative } from '@reformer/core/validators';
|
|
13
14
|
*
|
|
14
|
-
* //
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* validators: [nonNegative({ message: 'Баланс не может быть отрицательным' })],
|
|
19
|
-
* },
|
|
15
|
+
* // Правила живут в отдельной схеме над МОДЕЛЬЮ — layout-схема валидаторов не несёт.
|
|
16
|
+
* const validation = defineValidationSchema<MyForm>(({ model }) => {
|
|
17
|
+
* validate(model.$.balance, [nonNegative({ message: 'Баланс не может быть отрицательным' })]);
|
|
18
|
+
* });
|
|
20
19
|
* ```
|
|
21
20
|
*/
|
|
22
21
|
export declare function nonNegative<TForm = unknown, TField extends number | null | undefined = number>(options?: ValidateOptions): Validator<TForm, TField>;
|
|
@@ -9,14 +9,13 @@ import { Validator, ValidateOptions } from '../types/validation-schema';
|
|
|
9
9
|
*
|
|
10
10
|
* @example Проверка «не ноль»
|
|
11
11
|
* ```typescript
|
|
12
|
+
* import { defineValidationSchema, validate } from '@reformer/core/validation';
|
|
12
13
|
* import { nonZero } from '@reformer/core/validators';
|
|
13
14
|
*
|
|
14
|
-
* //
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* validators: [nonZero({ message: 'Не может быть нулём' })],
|
|
19
|
-
* },
|
|
15
|
+
* // Правила живут в отдельной схеме над МОДЕЛЬЮ — layout-схема валидаторов не несёт.
|
|
16
|
+
* const validation = defineValidationSchema<MyForm>(({ model }) => {
|
|
17
|
+
* validate(model.$.divisor, [nonZero({ message: 'Не может быть нулём' })]);
|
|
18
|
+
* });
|
|
20
19
|
* ```
|
|
21
20
|
*/
|
|
22
21
|
export declare function nonZero<TForm = unknown, TField extends number | null | undefined = number>(options?: ValidateOptions): Validator<TForm, TField>;
|
|
@@ -10,14 +10,13 @@ import { Validator, ValidateOptions } from '../types/validation-schema';
|
|
|
10
10
|
*
|
|
11
11
|
* @example Дата не в будущем
|
|
12
12
|
* ```typescript
|
|
13
|
+
* import { defineValidationSchema, validate } from '@reformer/core/validation';
|
|
13
14
|
* import { required, pastDate } from '@reformer/core/validators';
|
|
14
15
|
*
|
|
15
|
-
* //
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* validators: [required(), pastDate({ message: 'Дата рождения не может быть в будущем' })],
|
|
20
|
-
* },
|
|
16
|
+
* // Правила живут в отдельной схеме над МОДЕЛЬЮ — layout-схема валидаторов не несёт.
|
|
17
|
+
* const validation = defineValidationSchema<MyForm>(({ model }) => {
|
|
18
|
+
* validate(model.$.birthDate, [required(), pastDate({ message: 'Дата рождения не может быть в будущем' })]);
|
|
19
|
+
* });
|
|
21
20
|
* ```
|
|
22
21
|
*/
|
|
23
22
|
export declare function pastDate<TForm = unknown, TField extends string | Date | null | undefined = string | Date>(options?: ValidateOptions): Validator<TForm, TField>;
|
|
@@ -12,22 +12,14 @@ import { Validator, ValidateOptions } from '../types/validation-schema';
|
|
|
12
12
|
*
|
|
13
13
|
* @example Проверка по регулярному выражению
|
|
14
14
|
* ```typescript
|
|
15
|
+
* import { defineValidationSchema, validate } from '@reformer/core/validation';
|
|
15
16
|
* import { required, pattern } from '@reformer/core/validators';
|
|
16
17
|
*
|
|
17
|
-
* //
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* },
|
|
23
|
-
* phone: {
|
|
24
|
-
* value: model.$.phone,
|
|
25
|
-
* component: InputMask,
|
|
26
|
-
* validators: [
|
|
27
|
-
* required(),
|
|
28
|
-
* pattern(/^\+7 \(\d{3}\) \d{3}-\d{2}-\d{2}$/, { message: 'Формат +7 (999) 123-45-67' }),
|
|
29
|
-
* ],
|
|
30
|
-
* },
|
|
18
|
+
* // Правила живут в отдельной схеме над МОДЕЛЬЮ — layout-схема валидаторов не несёт.
|
|
19
|
+
* const validation = defineValidationSchema<MyForm>(({ model }) => {
|
|
20
|
+
* validate(model.$.name, [pattern(/^[a-zA-Zа-яА-Я]+$/, { message: 'Только буквы' })]);
|
|
21
|
+
* validate(model.$.phone, [required(), pattern(/^\+7 \(\d{3}\) \d{3}-\d{2}-\d{2}$/, { message: 'Формат +7 (999) 123-45-67' })]);
|
|
22
|
+
* });
|
|
31
23
|
* ```
|
|
32
24
|
*/
|
|
33
25
|
export declare function pattern<TForm = unknown, TField extends string | null | undefined = string>(regex: RegExp, options?: ValidateOptions): Validator<TForm, TField>;
|
|
@@ -28,14 +28,13 @@ export interface PhoneValidatorOptions extends ValidateOptions {
|
|
|
28
28
|
*
|
|
29
29
|
* @example Проверка номера телефона
|
|
30
30
|
* ```typescript
|
|
31
|
+
* import { defineValidationSchema, validate } from '@reformer/core/validation';
|
|
31
32
|
* import { required, phone } from '@reformer/core/validators';
|
|
32
33
|
*
|
|
33
|
-
* //
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* validators: [required(), phone({ format: 'ru' })],
|
|
38
|
-
* },
|
|
34
|
+
* // Правила живут в отдельной схеме над МОДЕЛЬЮ — layout-схема валидаторов не несёт.
|
|
35
|
+
* const validation = defineValidationSchema<MyForm>(({ model }) => {
|
|
36
|
+
* validate(model.$.phone, [required(), phone({ format: 'ru' })]);
|
|
37
|
+
* });
|
|
39
38
|
* ```
|
|
40
39
|
*/
|
|
41
40
|
export declare function phone<TForm = unknown, TField extends string | null | undefined = string>(options?: PhoneValidatorOptions): Validator<TForm, TField>;
|
|
@@ -13,20 +13,15 @@ import { Validator, ValidateOptions } from '../types/validation-schema';
|
|
|
13
13
|
*
|
|
14
14
|
* @example Обязательные поля в схеме формы
|
|
15
15
|
* ```typescript
|
|
16
|
+
* import { defineValidationSchema, validate } from '@reformer/core/validation';
|
|
16
17
|
* import { required } from '@reformer/core/validators';
|
|
17
18
|
*
|
|
18
|
-
* //
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* },
|
|
25
|
-
* agreeToTerms: {
|
|
26
|
-
* value: model.$.agreeToTerms,
|
|
27
|
-
* component: Checkbox,
|
|
28
|
-
* validators: [required({ message: 'Необходимо принять условия' })],
|
|
29
|
-
* },
|
|
19
|
+
* // Правила живут в отдельной схеме над МОДЕЛЬЮ — layout-схема валидаторов не несёт.
|
|
20
|
+
* const validation = defineValidationSchema<MyForm>(({ model }) => {
|
|
21
|
+
* validate(model.$.email, [required()]);
|
|
22
|
+
* validate(model.$.phone, [required({ message: 'Укажите номер телефона' })]);
|
|
23
|
+
* validate(model.$.agreeToTerms, [required({ message: 'Необходимо принять условия' })]);
|
|
24
|
+
* });
|
|
30
25
|
* ```
|
|
31
26
|
*/
|
|
32
27
|
export declare function required<TForm = unknown, TField = unknown>(options?: ValidateOptions): Validator<TForm, TField>;
|
|
@@ -24,20 +24,15 @@ export interface UrlValidatorOptions extends ValidateOptions {
|
|
|
24
24
|
*
|
|
25
25
|
* @example Проверка URL
|
|
26
26
|
* ```typescript
|
|
27
|
+
* import { defineValidationSchema, validate } from '@reformer/core/validation';
|
|
27
28
|
* import { required, url } from '@reformer/core/validators';
|
|
28
29
|
*
|
|
29
|
-
* //
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* }
|
|
35
|
-
* // Требовать протокол и ограничить схему только https:
|
|
36
|
-
* homepage: {
|
|
37
|
-
* value: model.$.homepage,
|
|
38
|
-
* component: Input,
|
|
39
|
-
* validators: [url({ requireProtocol: true, allowedProtocols: ['https'] })],
|
|
40
|
-
* },
|
|
30
|
+
* // Правила живут в отдельной схеме над МОДЕЛЬЮ — layout-схема валидаторов не несёт.
|
|
31
|
+
* const validation = defineValidationSchema<MyForm>(({ model }) => {
|
|
32
|
+
* validate(model.$.website, [required(), url({ message: 'Введите корректный URL' })]);
|
|
33
|
+
* // Требовать протокол и ограничить схему только https:
|
|
34
|
+
* validate(model.$.homepage, [url({ requireProtocol: true, allowedProtocols: ['https'] })]);
|
|
35
|
+
* });
|
|
41
36
|
* ```
|
|
42
37
|
*/
|
|
43
38
|
export declare function url<TForm = unknown, TField extends string | null | undefined = string>(options?: UrlValidatorOptions): Validator<TForm, TField>;
|
package/dist/index.js
CHANGED
|
@@ -772,7 +772,7 @@ class de extends M {
|
|
|
772
772
|
*
|
|
773
773
|
* @example
|
|
774
774
|
* ```typescript
|
|
775
|
-
* const field = new FieldNode({ value: 'initial', component:
|
|
775
|
+
* const field = new FieldNode({ value: 'initial', component: InputField });
|
|
776
776
|
*
|
|
777
777
|
* field.setValue('changed');
|
|
778
778
|
* field.reset('temp value');
|
|
@@ -965,12 +965,14 @@ class de extends M {
|
|
|
965
965
|
* @param updateOn - новый триггер валидации: 'change' | 'blur' | 'submit'
|
|
966
966
|
*
|
|
967
967
|
* @example
|
|
968
|
+
* Пример node-level: плоская схема с инлайн-значениями (back-compat путь до M1). В layout-схеме
|
|
969
|
+
* `createForm({ model, schema })` поля `validators` нет — правила живут в `defineValidationSchema`.
|
|
968
970
|
* ```typescript
|
|
969
971
|
* // Сценарий 1: Instant feedback после submit
|
|
970
972
|
* const form = createForm({
|
|
971
973
|
* email: {
|
|
972
974
|
* value: '',
|
|
973
|
-
* component:
|
|
975
|
+
* component: InputField,
|
|
974
976
|
* updateOn: 'submit', // Изначально валидация только при submit
|
|
975
977
|
* validators: [required, email],
|
|
976
978
|
* },
|
|
@@ -1436,8 +1438,8 @@ class A extends M {
|
|
|
1436
1438
|
* @example
|
|
1437
1439
|
* ```typescript
|
|
1438
1440
|
* const form = new GroupNode({
|
|
1439
|
-
* email: { value: '', component:
|
|
1440
|
-
* name: { value: '', component:
|
|
1441
|
+
* email: { value: '', component: InputField },
|
|
1442
|
+
* name: { value: '', component: InputField },
|
|
1441
1443
|
* });
|
|
1442
1444
|
*
|
|
1443
1445
|
* const proxy = form.getProxy();
|
|
@@ -1511,11 +1513,11 @@ class A extends M {
|
|
|
1511
1513
|
* @example
|
|
1512
1514
|
* ```typescript
|
|
1513
1515
|
* const form = new GroupNode({
|
|
1514
|
-
* email: { value: '', component:
|
|
1516
|
+
* email: { value: '', component: InputField },
|
|
1515
1517
|
* address: {
|
|
1516
|
-
* city: { value: '', component:
|
|
1518
|
+
* city: { value: '', component: InputField }
|
|
1517
1519
|
* },
|
|
1518
|
-
* items: [{ name: { value: '', component:
|
|
1520
|
+
* items: [{ name: { value: '', component: InputField } }]
|
|
1519
1521
|
* });
|
|
1520
1522
|
*
|
|
1521
1523
|
* form.getFieldByPath('email'); // FieldNode
|
|
@@ -1892,7 +1894,7 @@ class W extends M {
|
|
|
1892
1894
|
* @example
|
|
1893
1895
|
* ```typescript
|
|
1894
1896
|
* const arrayNode = new ArrayNode(
|
|
1895
|
-
* { name: { value: '', component:
|
|
1897
|
+
* { name: { value: '', component: InputField } },
|
|
1896
1898
|
* [{ name: 'Initial 1' }, { name: 'Initial 2' }]
|
|
1897
1899
|
* );
|
|
1898
1900
|
*
|
|
@@ -2104,28 +2106,29 @@ class ve {
|
|
|
2104
2106
|
* ```typescript
|
|
2105
2107
|
* const factory = new NodeFactory();
|
|
2106
2108
|
*
|
|
2109
|
+
* Конфиг node-level (не layout-схема M1, где `validators` уже нет).
|
|
2107
2110
|
* // FieldNode
|
|
2108
2111
|
* const field = factory.createNode({
|
|
2109
2112
|
* value: 'test@mail.com',
|
|
2110
|
-
* component:
|
|
2113
|
+
* component: InputField,
|
|
2111
2114
|
* validators: [required, email]
|
|
2112
2115
|
* });
|
|
2113
2116
|
*
|
|
2114
2117
|
* // GroupNode
|
|
2115
2118
|
* const group = factory.createNode({
|
|
2116
|
-
* email: { value: '', component:
|
|
2117
|
-
* password: { value: '', component:
|
|
2119
|
+
* email: { value: '', component: InputField },
|
|
2120
|
+
* password: { value: '', component: InputField }
|
|
2118
2121
|
* });
|
|
2119
2122
|
*
|
|
2120
2123
|
* // ArrayNode (объект)
|
|
2121
2124
|
* const array = factory.createNode({
|
|
2122
|
-
* schema: { title: { value: '', component:
|
|
2125
|
+
* schema: { title: { value: '', component: InputField } },
|
|
2123
2126
|
* initialItems: [{ title: 'Item 1' }]
|
|
2124
2127
|
* });
|
|
2125
2128
|
*
|
|
2126
2129
|
* // ArrayNode (массив) - новый формат
|
|
2127
2130
|
* const array2 = factory.createNode([
|
|
2128
|
-
* { title: { value: '', component:
|
|
2131
|
+
* { title: { value: '', component: InputField } }, // schema
|
|
2129
2132
|
* { title: 'Item 1' }, // initial item 1
|
|
2130
2133
|
* { title: 'Item 2' } // initial item 2
|
|
2131
2134
|
* ]);
|
|
@@ -2167,7 +2170,7 @@ class ve {
|
|
|
2167
2170
|
*
|
|
2168
2171
|
* // Массив с начальными элементами
|
|
2169
2172
|
* const array = factory.createArrayNodeFromArray([
|
|
2170
|
-
* { title: { value: '', component:
|
|
2173
|
+
* { title: { value: '', component: InputField } }, // schema
|
|
2171
2174
|
* { title: 'Item 1' }, // initial value
|
|
2172
2175
|
* { title: 'Item 2' } // initial value
|
|
2173
2176
|
* ]);
|
|
@@ -2188,7 +2191,7 @@ class ve {
|
|
|
2188
2191
|
* ✅ НОВОЕ: Извлечено из GroupNode для централизации логики
|
|
2189
2192
|
*
|
|
2190
2193
|
* Преобразует схему формы в объект со значениями:
|
|
2191
|
-
* - `{ name: { value: 'John', component:
|
|
2194
|
+
* - `{ name: { value: 'John', component: InputField } } → { name: 'John' }`
|
|
2192
2195
|
* - Поддерживает вложенные группы
|
|
2193
2196
|
* - Поддерживает массивы
|
|
2194
2197
|
*
|
|
@@ -2200,10 +2203,10 @@ class ve {
|
|
|
2200
2203
|
* const factory = new NodeFactory();
|
|
2201
2204
|
*
|
|
2202
2205
|
* const schema = {
|
|
2203
|
-
* name: { value: 'John', component:
|
|
2204
|
-
* age: { value: 30, component:
|
|
2206
|
+
* name: { value: 'John', component: InputField },
|
|
2207
|
+
* age: { value: 30, component: InputField },
|
|
2205
2208
|
* address: {
|
|
2206
|
-
* city: { value: 'Moscow', component:
|
|
2209
|
+
* city: { value: 'Moscow', component: InputField }
|
|
2207
2210
|
* }
|
|
2208
2211
|
* };
|
|
2209
2212
|
*
|
|
@@ -2238,7 +2241,7 @@ class ve {
|
|
|
2238
2241
|
* ```typescript
|
|
2239
2242
|
* const factory = new NodeFactory();
|
|
2240
2243
|
*
|
|
2241
|
-
* factory.isFieldConfig({ value: '', component:
|
|
2244
|
+
* factory.isFieldConfig({ value: '', component: InputField }); // true
|
|
2242
2245
|
* factory.isFieldConfig({ email: { value: '' } }); // false
|
|
2243
2246
|
* factory.isFieldConfig(null); // false
|
|
2244
2247
|
* ```
|
|
@@ -2263,7 +2266,7 @@ class ve {
|
|
|
2263
2266
|
* const factory = new NodeFactory();
|
|
2264
2267
|
*
|
|
2265
2268
|
* factory.isArrayConfig({ schema: {}, initialItems: [] }); // true
|
|
2266
|
-
* factory.isArrayConfig({ value: '', component:
|
|
2269
|
+
* factory.isArrayConfig({ value: '', component: InputField }); // false
|
|
2267
2270
|
* factory.isArrayConfig({ email: { value: '' } }); // false
|
|
2268
2271
|
* ```
|
|
2269
2272
|
*/
|
|
@@ -2286,11 +2289,11 @@ class ve {
|
|
|
2286
2289
|
* const factory = new NodeFactory();
|
|
2287
2290
|
*
|
|
2288
2291
|
* factory.isGroupConfig({
|
|
2289
|
-
* email: { value: '', component:
|
|
2290
|
-
* password: { value: '', component:
|
|
2292
|
+
* email: { value: '', component: InputField },
|
|
2293
|
+
* password: { value: '', component: InputField }
|
|
2291
2294
|
* }); // true
|
|
2292
2295
|
*
|
|
2293
|
-
* factory.isGroupConfig({ value: '', component:
|
|
2296
|
+
* factory.isGroupConfig({ value: '', component: InputField }); // false
|
|
2294
2297
|
* factory.isGroupConfig({ schema: {} }); // false
|
|
2295
2298
|
* factory.isGroupConfig(null); // false
|
|
2296
2299
|
* ```
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
import { createCoreForm, createModel, useFormBundle, type FormProxy } from '@reformer/core';
|
|
19
19
|
import { defineValidationSchema, validate, validateModel } from '@reformer/core/validation';
|
|
20
20
|
import { required, email } from '@reformer/core/validators';
|
|
21
|
-
import { FormField,
|
|
21
|
+
import { FormField, InputField, Button } from '@reformer/ui-kit';
|
|
22
22
|
|
|
23
23
|
// 1. Define form type as `type` alias (not `interface` — see Recipe 2)
|
|
24
24
|
type ContactForm = {
|
|
@@ -34,12 +34,12 @@ const model = createModel<ContactForm>({ name: '', email: '' });
|
|
|
34
34
|
const schema = {
|
|
35
35
|
name: {
|
|
36
36
|
value: model.$.name,
|
|
37
|
-
component:
|
|
37
|
+
component: InputField,
|
|
38
38
|
componentProps: { label: 'Name', placeholder: 'Your name' },
|
|
39
39
|
},
|
|
40
40
|
email: {
|
|
41
41
|
value: model.$.email,
|
|
42
|
-
component:
|
|
42
|
+
component: InputField,
|
|
43
43
|
componentProps: { label: 'Email', type: 'email' },
|
|
44
44
|
},
|
|
45
45
|
};
|
|
@@ -113,13 +113,13 @@ const model = createModel<MyForm>({ properties: [] });
|
|
|
113
113
|
const propertyItem = (item: FormModel<PropertyItem>) => ({
|
|
114
114
|
type: {
|
|
115
115
|
value: item.$.type,
|
|
116
|
-
component:
|
|
116
|
+
component: SelectField,
|
|
117
117
|
componentProps: { label: 'Тип', options: [/* ... */] },
|
|
118
118
|
},
|
|
119
|
-
description: { value: item.$.description, component:
|
|
119
|
+
description: { value: item.$.description, component: TextareaField, componentProps: { label: 'Описание' } },
|
|
120
120
|
estimatedValue: {
|
|
121
121
|
value: item.$.estimatedValue,
|
|
122
|
-
component:
|
|
122
|
+
component: InputField,
|
|
123
123
|
componentProps: { label: 'Стоимость', type: 'number' },
|
|
124
124
|
},
|
|
125
125
|
});
|
|
@@ -72,9 +72,9 @@ const model = createModel<Loan>({ email: '', age: 0, amount: 0 });
|
|
|
72
72
|
const form = createForm({
|
|
73
73
|
model,
|
|
74
74
|
schema: {
|
|
75
|
-
email: { value: model.$.email, component:
|
|
76
|
-
age: { value: model.$.age, component:
|
|
77
|
-
amount: { value: model.$.amount, component:
|
|
75
|
+
email: { value: model.$.email, component: InputField },
|
|
76
|
+
age: { value: model.$.age, component: InputField },
|
|
77
|
+
amount: { value: model.$.amount, component: InputField },
|
|
78
78
|
},
|
|
79
79
|
});
|
|
80
80
|
|
|
@@ -93,7 +93,7 @@ computeFrom([model.$.price, model.$.quantity], model.$.total, (price, qty) => pr
|
|
|
93
93
|
```typescript
|
|
94
94
|
// ❌ WRONG - дерево { value, validators } и позиционная строка удалены
|
|
95
95
|
const schema = {
|
|
96
|
-
email: { value: model.$.email, component:
|
|
96
|
+
email: { value: model.$.email, component: InputField, validators: [required(), email()] },
|
|
97
97
|
};
|
|
98
98
|
validate(path.email, required(), 'Email is required'); // старая сигнатура validate() — удалена
|
|
99
99
|
|
|
@@ -10,7 +10,7 @@ layout-схеме НЕТ — правила живут в отдельной с
|
|
|
10
10
|
```typescript
|
|
11
11
|
{
|
|
12
12
|
value: model.$.fieldName, // сигнал модели (PathAwareSignal) — обязателен
|
|
13
|
-
component:
|
|
13
|
+
component: InputField, // React-компонент
|
|
14
14
|
componentProps?: object, // пропсы (label, placeholder, options, type, ...)
|
|
15
15
|
disabled?: boolean,
|
|
16
16
|
updateOn?: 'change' | 'blur' | 'submit',
|
|
@@ -28,7 +28,7 @@ layout-схеме НЕТ — правила живут в отдельной с
|
|
|
28
28
|
import { createModel, createForm } from '@reformer/core';
|
|
29
29
|
import { defineValidationSchema, validate } from '@reformer/core/validation';
|
|
30
30
|
import { required } from '@reformer/core/validators';
|
|
31
|
-
import {
|
|
31
|
+
import { InputField, SelectField, CheckboxField } from '@reformer/ui-kit';
|
|
32
32
|
|
|
33
33
|
const model = createModel<MyForm>({ name: '', age: null, agree: false, status: 'active' });
|
|
34
34
|
|
|
@@ -40,22 +40,22 @@ const myValidation = defineValidationSchema<MyForm>(({ model }) => {
|
|
|
40
40
|
const schema = {
|
|
41
41
|
name: {
|
|
42
42
|
value: model.$.name,
|
|
43
|
-
component:
|
|
43
|
+
component: InputField,
|
|
44
44
|
componentProps: { label: 'Name', placeholder: 'Enter name' },
|
|
45
45
|
},
|
|
46
46
|
age: {
|
|
47
47
|
value: model.$.age,
|
|
48
|
-
component:
|
|
48
|
+
component: InputField,
|
|
49
49
|
componentProps: { type: 'number', label: 'Age' },
|
|
50
50
|
},
|
|
51
51
|
agree: {
|
|
52
52
|
value: model.$.agree,
|
|
53
|
-
component:
|
|
53
|
+
component: CheckboxField,
|
|
54
54
|
componentProps: { label: 'I agree to terms' },
|
|
55
55
|
},
|
|
56
56
|
status: {
|
|
57
57
|
value: model.$.status,
|
|
58
|
-
component:
|
|
58
|
+
component: SelectField,
|
|
59
59
|
componentProps: {
|
|
60
60
|
label: 'Status',
|
|
61
61
|
options: [
|
|
@@ -79,9 +79,9 @@ const form = createForm<MyForm>({ model, schema });
|
|
|
79
79
|
import type { FormModel } from '@reformer/core';
|
|
80
80
|
|
|
81
81
|
const addressNodes = (m: FormModel<Address>) => ({
|
|
82
|
-
street: { value: m.$.street, component:
|
|
83
|
-
city: { value: m.$.city, component:
|
|
84
|
-
zip: { value: m.$.zip, component:
|
|
82
|
+
street: { value: m.$.street, component: InputField, componentProps: { label: 'Street' } },
|
|
83
|
+
city: { value: m.$.city, component: InputField, componentProps: { label: 'City' } },
|
|
84
|
+
zip: { value: m.$.zip, component: InputField, componentProps: { label: 'ZIP' } },
|
|
85
85
|
});
|
|
86
86
|
|
|
87
87
|
const schema = {
|
|
@@ -98,8 +98,8 @@ const schema = {
|
|
|
98
98
|
import type { FormModel } from '@reformer/core';
|
|
99
99
|
|
|
100
100
|
const itemSchema = (item: FormModel<Item>) => ({
|
|
101
|
-
id: { value: item.$.id, component:
|
|
102
|
-
name: { value: item.$.name, component:
|
|
101
|
+
id: { value: item.$.id, component: InputField, componentProps: { label: 'ID' } },
|
|
102
|
+
name: { value: item.$.name, component: InputField, componentProps: { label: 'Name' } },
|
|
103
103
|
});
|
|
104
104
|
|
|
105
105
|
const schema = {
|
package/docs/llms/10-arrays.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
```typescript
|
|
9
9
|
import { createModel, createForm, type FormModel } from '@reformer/core';
|
|
10
|
-
import {
|
|
10
|
+
import { InputField } from '@reformer/ui-kit';
|
|
11
11
|
|
|
12
12
|
type Item = { id: string; name: string; price: number };
|
|
13
13
|
type MyForm = { items: Item[] };
|
|
@@ -16,9 +16,9 @@ const model = createModel<MyForm>({ items: [] });
|
|
|
16
16
|
|
|
17
17
|
// под-схема одного элемента (item.$.field — сигнал под-модели)
|
|
18
18
|
const itemSchema = (item: FormModel<Item>) => ({
|
|
19
|
-
id: { value: item.$.id, component:
|
|
20
|
-
name: { value: item.$.name, component:
|
|
21
|
-
price: { value: item.$.price, component:
|
|
19
|
+
id: { value: item.$.id, component: InputField },
|
|
20
|
+
name: { value: item.$.name, component: InputField },
|
|
21
|
+
price: { value: item.$.price, component: InputField, componentProps: { type: 'number' } },
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
const schema = {
|
|
@@ -71,7 +71,7 @@ import { revalidateWhen, type ValidationError } from '@reformer/core';
|
|
|
71
71
|
// ❌ старое (УДАЛЕНО): дерево { value, validators }, ModelValidator (value, scope, root), validateFormModel
|
|
72
72
|
const legacyRule: ModelValidator<number, unknown, Form> = (_value, _scope, root) =>
|
|
73
73
|
root.field1 > root.field2 ? { code: 'error', message: 'Invalid' } : null;
|
|
74
|
-
const legacySchema = { field1: { value: model.$.field1, component:
|
|
74
|
+
const legacySchema = { field1: { value: model.$.field1, component: InputField, validators: [legacyRule] } };
|
|
75
75
|
validateFormModel(model, legacySchema);
|
|
76
76
|
|
|
77
77
|
// ✅ новое: cross-правило — обычная функция над снапшотом (model.get()), не читает scope/root
|