@reformer/core 2.0.1 → 3.0.0

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.
@@ -4,7 +4,7 @@
4
4
  * Реализует FormContext для behavior схем
5
5
  */
6
6
  import type { GroupNode } from '../nodes/group-node';
7
- import type { GroupNodeWithControls } from '../types/group-node-proxy';
7
+ import type { FormProxy } from '../types/form-proxy';
8
8
  import type { FormContext } from '../types/form-context';
9
9
  import type { FieldPathNode } from '../types/field-path';
10
10
  /**
@@ -18,7 +18,7 @@ export declare class BehaviorContextImpl<TForm> implements FormContext<TForm> {
18
18
  /**
19
19
  * Форма с типизированным Proxy-доступом к полям
20
20
  */
21
- readonly form: GroupNodeWithControls<TForm>;
21
+ readonly form: FormProxy<TForm>;
22
22
  private _form;
23
23
  constructor(form: GroupNode<TForm>);
24
24
  /**
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import type { GroupNode } from '../nodes/group-node';
7
7
  import type { FormContext } from '../types/form-context';
8
- import type { GroupNodeWithControls } from '../types/group-node-proxy';
8
+ import type { FormProxy } from '../types/form-proxy';
9
9
  /**
10
10
  * Базовая реализация FormContext
11
11
  *
@@ -17,7 +17,7 @@ export declare class FormContextImpl<TForm> implements FormContext<TForm> {
17
17
  /**
18
18
  * Форма с типизированным Proxy-доступом к полям
19
19
  */
20
- readonly form: GroupNodeWithControls<TForm>;
20
+ readonly form: FormProxy<TForm>;
21
21
  protected readonly _groupNode: GroupNode<TForm>;
22
22
  constructor(groupNode: GroupNode<TForm>);
23
23
  /**
@@ -12,7 +12,7 @@ import type { ReadonlySignal } from '@preact/signals-core';
12
12
  import { FormNode, type SetValueOptions } from './form-node';
13
13
  import type { FieldStatus, ValidationError, FormFields } from '../types';
14
14
  import type { FormSchema } from '../types/deep-schema';
15
- import type { GroupNodeWithControls } from '../types/group-node-proxy';
15
+ import type { FormProxy } from '../types/form-proxy';
16
16
  /**
17
17
  * ArrayNode - массив форм с реактивным состоянием
18
18
  *
@@ -76,7 +76,7 @@ export declare class ArrayNode<T extends FormFields> extends FormNode<T[]> {
76
76
  * @param index - Индекс элемента
77
77
  * @returns Типизированный GroupNode или undefined если индекс вне границ
78
78
  */
79
- at(index: number): GroupNodeWithControls<T> | undefined;
79
+ at(index: number): FormProxy<T> | undefined;
80
80
  getValue(): T[];
81
81
  setValue(values: T[], options?: SetValueOptions): void;
82
82
  patchValue(values: (T | undefined)[]): void;
@@ -158,13 +158,13 @@ export declare class ArrayNode<T extends FormFields> extends FormNode<T[]> {
158
158
  * Итерировать по элементам массива
159
159
  * @param callback - Функция, вызываемая для каждого элемента с типизированным GroupNode
160
160
  */
161
- forEach(callback: (item: GroupNodeWithControls<T>, index: number) => void): void;
161
+ forEach(callback: (item: FormProxy<T>, index: number) => void): void;
162
162
  /**
163
163
  * Маппинг элементов массива
164
164
  * @param callback - Функция преобразования с типизированным GroupNode
165
165
  * @returns Новый массив результатов
166
166
  */
167
- map<R>(callback: (item: GroupNodeWithControls<T>, index: number) => R): R[];
167
+ map<R>(callback: (item: FormProxy<T>, index: number) => R): R[];
168
168
  /**
169
169
  * Создать новый элемент массива на основе схемы
170
170
  * @param initialValue - Начальные значения
@@ -13,7 +13,7 @@
13
13
  import type { ReadonlySignal } from '@preact/signals-core';
14
14
  import { FormNode, type SetValueOptions } from './form-node';
15
15
  import type { ValidationError, FieldStatus, ValidationSchemaFn, ValidatorRegistration, FormSchema, GroupNodeConfig, FormValue } from '../types';
16
- import type { GroupNodeWithControls } from '../types/group-node-proxy';
16
+ import type { FormProxy } from '../types/form-proxy';
17
17
  import type { BehaviorSchemaFn } from '../behavior/types';
18
18
  /**
19
19
  * GroupNode - узел для группы полей
@@ -184,7 +184,7 @@ export declare class GroupNode<T> extends FormNode<T> {
184
184
  * console.log(proxy.email.value); // Прямой доступ к полю
185
185
  * ```
186
186
  */
187
- getProxy(): GroupNodeWithControls<T>;
187
+ getProxy(): FormProxy<T>;
188
188
  /**
189
189
  * Получить все поля формы как итератор
190
190
  */
@@ -22,7 +22,7 @@
22
22
  * });
23
23
  * ```
24
24
  */
25
- import type { GroupNodeWithControls } from './group-node-proxy';
25
+ import type { FormProxy } from './form-proxy';
26
26
  import type { FieldPathNode } from './field-path';
27
27
  /**
28
28
  * Единый контекст для работы с формой
@@ -62,7 +62,7 @@ export interface FormContext<TForm> {
62
62
  * ctx.form.items.clear()
63
63
  * ```
64
64
  */
65
- readonly form: GroupNodeWithControls<TForm>;
65
+ readonly form: FormProxy<TForm>;
66
66
  /**
67
67
  * Безопасно установить значение поля по строковому пути или FieldPath
68
68
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Типы для Proxy-доступа к полям GroupNode
2
+ * Типы для Proxy-доступа к полям формы
3
3
  *
4
4
  * Решает проблему типизации, когда GroupNode<T> использует Proxy для прямого доступа к полям.
5
5
  * TypeScript не может автоматически определить правильные типы для вложенных форм и массивов.
@@ -16,7 +16,7 @@
16
16
  * items: Array<{ title: string }>;
17
17
  * }
18
18
  *
19
- * const form: GroupNodeWithControls<MyForm> = new GroupNode(schema);
19
+ * const form: FormProxy<MyForm> = new GroupNode(schema);
20
20
  *
21
21
  * // TypeScript знает, что это FieldNode<string>
22
22
  * form.name.setValue('John');
@@ -36,9 +36,9 @@ type ArrayNode<_T> = any;
36
36
  * Мапит тип модели данных T на правильные типы узлов формы
37
37
  *
38
38
  * Рекурсивно определяет типы узлов на основе структуры данных:
39
- * - `T[K] extends Array<infer U>` где U - объект → `ArrayNodeWithControls<U>`
39
+ * - `T[K] extends Array<infer U>` где U - объект → `FormArrayProxy<U>`
40
40
  * - `T[K] extends Array<infer U>` где U - примитив → `FieldNode<T[K]>` (массив как обычное поле)
41
- * - `T[K] extends object` → `GroupNodeWithControls<T[K]>` (вложенная форма с типизацией)
41
+ * - `T[K] extends object` → `FormProxy<T[K]>` (вложенная форма с типизацией)
42
42
  * - `T[K]` примитив → `FieldNode<T[K]>` (простое поле)
43
43
  *
44
44
  * Использует NonNullable для правильной обработки опциональных полей
@@ -48,8 +48,8 @@ type ArrayNode<_T> = any;
48
48
  *
49
49
  * @template T - Тип модели данных формы
50
50
  */
51
- export type FormNodeControls<T> = {
52
- [K in keyof T]: NonNullable<T[K]> extends Array<infer U> ? U extends FormFields ? ArrayNodeWithControls<U> : FieldNode<T[K]> : NonNullable<T[K]> extends FormFields ? NonNullable<T[K]> extends Date | File | Blob ? FieldNode<T[K]> : GroupNodeWithControls<NonNullable<T[K]>> : FieldNode<T[K]>;
51
+ export type FormControlsProxy<T> = {
52
+ [K in keyof T]: NonNullable<T[K]> extends Array<infer U> ? U extends FormFields ? FormArrayProxy<U> : FieldNode<T[K]> : NonNullable<T[K]> extends FormFields ? NonNullable<T[K]> extends Date | File | Blob ? FieldNode<T[K]> : FormProxy<NonNullable<T[K]>> : FieldNode<T[K]>;
53
53
  };
54
54
  /**
55
55
  * Комбинированный тип для GroupNode с Proxy доступом к полям
@@ -72,7 +72,7 @@ export type FormNodeControls<T> = {
72
72
  * };
73
73
  * }
74
74
  *
75
- * const form: GroupNodeWithControls<UserForm> = new GroupNode(schema);
75
+ * const form: FormProxy<UserForm> = new GroupNode(schema);
76
76
  *
77
77
  * // Доступ к методам GroupNode
78
78
  * await form.validate();
@@ -84,7 +84,7 @@ export type FormNodeControls<T> = {
84
84
  * form.profile.name.setValue('John');
85
85
  * ```
86
86
  */
87
- export type GroupNodeWithControls<T> = GroupNode<T> & FormNodeControls<T>;
87
+ export type FormProxy<T> = GroupNode<T> & FormControlsProxy<T>;
88
88
  /**
89
89
  * Комбинированный тип для ArrayNode с Proxy доступом к элементам
90
90
  *
@@ -102,7 +102,7 @@ export type GroupNodeWithControls<T> = GroupNode<T> & FormNodeControls<T>;
102
102
  * completed: boolean;
103
103
  * }
104
104
  *
105
- * const todos: ArrayNodeWithControls<TodoItem> = new ArrayNode(schema);
105
+ * const todos: FormArrayProxy<TodoItem> = new ArrayNode(schema);
106
106
  *
107
107
  * // Доступ к методам ArrayNode
108
108
  * todos.push({ title: 'New todo', completed: false });
@@ -117,19 +117,19 @@ export type GroupNodeWithControls<T> = GroupNode<T> & FormNodeControls<T>;
117
117
  * });
118
118
  * ```
119
119
  */
120
- export type ArrayNodeWithControls<T extends FormFields> = ArrayNode<T> & {
120
+ export type FormArrayProxy<T extends FormFields> = ArrayNode<T> & {
121
121
  /**
122
122
  * Безопасный доступ к элементу массива по индексу
123
123
  * Возвращает GroupNode с типизированными полями или undefined
124
124
  */
125
- at(index: number): GroupNodeWithControls<T> | undefined;
125
+ at(index: number): FormProxy<T> | undefined;
126
126
  /**
127
127
  * Итерация по элементам массива с типизированными элементами
128
128
  */
129
- forEach(callback: (item: GroupNodeWithControls<T>, index: number) => void): void;
129
+ forEach(callback: (item: FormProxy<T>, index: number) => void): void;
130
130
  /**
131
131
  * Маппинг элементов массива с типизированными элементами
132
132
  */
133
- map<R>(callback: (item: GroupNodeWithControls<T>, index: number) => R): R[];
133
+ map<R>(callback: (item: FormProxy<T>, index: number) => R): R[];
134
134
  };
135
135
  export {};
@@ -64,7 +64,7 @@ export type { FieldPath, FieldPathNode } from '../types/field-path';
64
64
  export type { ContextualValidatorFn, ContextualAsyncValidatorFn, TreeValidatorFn, ConditionFn, ValidateOptions, ValidateAsyncOptions, ValidateTreeOptions, ValidationSchemaFn, ValidatorRegistration, } from './validation-schema';
65
65
  export type { FormSchema, ArrayConfig } from './deep-schema';
66
66
  export type { FormContext } from './form-context';
67
- export type { FormNodeControls, GroupNodeWithControls, ArrayNodeWithControls, } from './group-node-proxy';
67
+ export type { FormControlsProxy, FormProxy, FormArrayProxy } from './form-proxy';
68
68
  import type { BehaviorSchemaFn } from '../behavior/types';
69
69
  import type { FormSchema } from './deep-schema';
70
70
  import type { ValidationSchemaFn } from './validation-schema';
@@ -2,20 +2,20 @@
2
2
  * Фабричная функция для создания формы с правильной типизацией
3
3
  *
4
4
  * Решает проблему с типизацией конструктора GroupNode, который возвращает
5
- * Proxy (GroupNodeWithControls), но TypeScript не может это вывести автоматически.
5
+ * Proxy (FormProxy), но TypeScript не может это вывести автоматически.
6
6
  *
7
7
  * @group Utilities
8
8
  *
9
9
  * @example
10
10
  * ```typescript
11
11
  * // Вместо:
12
- * const form: GroupNodeWithControls<MyForm> = new GroupNode<MyForm>(config);
12
+ * const form: FormProxy<MyForm> = new GroupNode<MyForm>(config);
13
13
  *
14
14
  * // Используйте:
15
15
  * const form = createForm<MyForm>(config);
16
16
  * ```
17
17
  */
18
- import type { GroupNodeWithControls, GroupNodeConfig, FormSchema } from '../types';
18
+ import type { FormProxy, GroupNodeConfig, FormSchema } from '../types';
19
19
  /**
20
20
  * Создать форму с полной конфигурацией (form, behavior, validation)
21
21
  *
@@ -43,7 +43,7 @@ import type { GroupNodeWithControls, GroupNodeConfig, FormSchema } from '../type
43
43
  * form.email.setValue('test@mail.com');
44
44
  * ```
45
45
  */
46
- export declare function createForm<T>(config: GroupNodeConfig<T>): GroupNodeWithControls<T>;
46
+ export declare function createForm<T>(config: GroupNodeConfig<T>): FormProxy<T>;
47
47
  /**
48
48
  * Создать форму только со схемой полей (обратная совместимость)
49
49
  *
@@ -58,4 +58,4 @@ export declare function createForm<T>(config: GroupNodeConfig<T>): GroupNodeWith
58
58
  * });
59
59
  * ```
60
60
  */
61
- export declare function createForm<T>(schema: FormSchema<T>): GroupNodeWithControls<T>;
61
+ export declare function createForm<T>(schema: FormSchema<T>): FormProxy<T>;
@@ -3,7 +3,7 @@
3
3
  */
4
4
  import type { GroupNode } from '../nodes/group-node';
5
5
  import type { FieldNode } from '../nodes/field-node';
6
- import type { GroupNodeWithControls } from '../types/group-node-proxy';
6
+ import type { FormProxy } from '../types/form-proxy';
7
7
  import type { FormContext } from '../types/form-context';
8
8
  /**
9
9
  * Реализация контекста валидации для отдельного поля
@@ -15,7 +15,7 @@ export declare class ValidationContextImpl<TForm, TField> implements FormContext
15
15
  /**
16
16
  * Форма с типизированным Proxy-доступом к полям
17
17
  */
18
- readonly form: GroupNodeWithControls<TForm>;
18
+ readonly form: FormProxy<TForm>;
19
19
  constructor(form: GroupNode<TForm>, _fieldKey: keyof TForm, control: FieldNode<TField>);
20
20
  /**
21
21
  * Получить текущее значение поля (внутренний метод для validation-applicator)
@@ -37,7 +37,7 @@ export declare class TreeValidationContextImpl<TForm> implements FormContext<TFo
37
37
  /**
38
38
  * Форма с типизированным Proxy-доступом к полям
39
39
  */
40
- readonly form: GroupNodeWithControls<TForm>;
40
+ readonly form: FormProxy<TForm>;
41
41
  constructor(form: GroupNode<TForm>);
42
42
  /**
43
43
  * Безопасно установить значение поля по строковому пути
@@ -55,7 +55,7 @@ export declare class ArrayValidationContextImpl<TForm, TItem> implements FormCon
55
55
  /**
56
56
  * Форма с типизированным Proxy-доступом к полям
57
57
  */
58
- readonly form: GroupNodeWithControls<TForm>;
58
+ readonly form: FormProxy<TForm>;
59
59
  constructor(form: GroupNode<TForm>, _fieldKey: keyof TForm, arrayValue: TItem[]);
60
60
  /**
61
61
  * Получить текущее значение массива (для валидатора)
package/llms.txt CHANGED
@@ -7,7 +7,7 @@
7
7
  | What | Where |
8
8
  | ------------------------------------------------------------------------------------------- | --------------------------- |
9
9
  | `createForm`, `useFormControl`, `useFormControlValue`, `validateForm` | `@reformer/core` |
10
- | `ValidationSchemaFn`, `BehaviorSchemaFn`, `FieldPath`, `GroupNodeWithControls`, `FieldNode` | `@reformer/core` |
10
+ | `ValidationSchemaFn`, `BehaviorSchemaFn`, `FieldPath`, `FormProxy`, `FieldNode` | `@reformer/core` |
11
11
  | `FormSchema`, `FieldConfig`, `ArrayNode` | `@reformer/core` |
12
12
  | `required`, `min`, `max`, `minLength`, `maxLength`, `email` | `@reformer/core/validators` |
13
13
  | `pattern`, `url`, `phone`, `number`, `date` | `@reformer/core/validators` |
@@ -48,7 +48,7 @@ const { value, errors, disabled } = useFormControl(control.loanType);
48
48
  ```typescript
49
49
  import { createForm, useFormControl } from '@reformer/core';
50
50
  import { required, email } from '@reformer/core/validators';
51
- import type { GroupNodeWithControls } from '@reformer/core';
51
+ import type { FormProxy } from '@reformer/core';
52
52
 
53
53
  // 1. Define form type
54
54
  interface ContactForm {
@@ -105,7 +105,7 @@ function ContactFormComponent() {
105
105
 
106
106
  // 4. Pass form to child components via props (NOT context!)
107
107
  interface FormStepProps {
108
- form: GroupNodeWithControls<ContactForm>;
108
+ form: FormProxy<ContactForm>;
109
109
  }
110
110
 
111
111
  function FormStep({ form }: FormStepProps) {
@@ -218,7 +218,7 @@ transformers.trim, transformers.toUpperCase, transformers.toLowerCase, transform
218
218
 
219
219
  // BehaviorContext interface:
220
220
  interface BehaviorContext<TForm> {
221
- form: GroupNodeWithControls<TForm>; // Form proxy with typed field access
221
+ form: FormProxy<TForm>; // Form proxy with typed field access
222
222
  setFieldValue: (path: string, value: any) => void;
223
223
  // To READ field values, use: ctx.form.fieldName.value.value
224
224
  }
@@ -374,7 +374,7 @@ import type {
374
374
  ValidationSchemaFn,
375
375
  BehaviorSchemaFn,
376
376
  FieldPath,
377
- GroupNodeWithControls,
377
+ FormProxy,
378
378
  FieldNode,
379
379
  } from '@reformer/core';
380
380
 
@@ -536,13 +536,13 @@ form.items.push({ id: '1', name: 'Item' }); // Array operations
536
536
  ### createForm Returns a Proxy
537
537
 
538
538
  ```typescript
539
- // createForm() returns GroupNodeWithControls<T> (a Proxy wrapper around GroupNode)
539
+ // createForm() returns FormProxy<T> (a Proxy wrapper around GroupNode)
540
540
  // This enables type-safe field access:
541
541
  const form = createForm<MyForm>({...});
542
542
 
543
543
  form.email // FieldNode<string> - TypeScript knows the type!
544
544
  form.address.city // FieldNode<string> - nested access works
545
- form.items.at(0) // GroupNodeWithControls<ItemType> - array items
545
+ form.items.at(0) // FormProxy<ItemType> - array items
546
546
 
547
547
  // IMPORTANT: Proxy doesn't pass instanceof checks!
548
548
  // Use type guards instead:
@@ -1014,7 +1014,7 @@ function ShadcnFormField({ control, label }: FormFieldProps<string>) {
1014
1014
  | `FieldSchema` | `FieldConfig<T>` | Type for individual field config |
1015
1015
  | `when()` | `applyWhen()` | Conditional validation function |
1016
1016
  | `FormFields` | `FieldNode<T>` | Type for field nodes |
1017
- | `FormInstance<T>` | `GroupNodeWithControls<T>` | Form type for component props |
1017
+ | `FormInstance<T>` | `FormProxy<T>` | Form type for component props |
1018
1018
  | `useArrayField()` | `form.items.push/map/removeAt` | Use ArrayNode methods directly |
1019
1019
  | `FormProvider` | `<Component form={form} />` | Pass form via props, no context |
1020
1020
  | `formState` | `form.valid`, `form.dirty`, etc. | Separate signals on form |
@@ -1183,8 +1183,8 @@ const first = form.items[0]; // undefined or error
1183
1183
  const second = form.items[1]; // undefined or error
1184
1184
 
1185
1185
  // CORRECT - use .at() method
1186
- const first = form.items.at(0); // GroupNodeWithControls<ItemType> | undefined
1187
- const second = form.items.at(1); // GroupNodeWithControls<ItemType> | undefined
1186
+ const first = form.items.at(0); // FormProxy<ItemType> | undefined
1187
+ const second = form.items.at(1); // FormProxy<ItemType> | undefined
1188
1188
 
1189
1189
  // CORRECT - iterate with map (most common pattern)
1190
1190
  form.items.map((item, index) => {
@@ -1217,7 +1217,7 @@ form.items.at(index); // Get item at index (NOT it
1217
1217
  ### Rendering Arrays
1218
1218
 
1219
1219
  ```tsx
1220
- function ItemsList({ form }: { form: GroupNodeWithControls<MyForm> }) {
1220
+ function ItemsList({ form }: { form: FormProxy<MyForm> }) {
1221
1221
  const { length } = useFormControl(form.items);
1222
1222
 
1223
1223
  return (
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reformer/core",
3
- "version": "2.0.1",
3
+ "version": "3.0.0",
4
4
  "description": "Reactive form state management library for React with signals-based architecture",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -24,6 +24,7 @@
24
24
  "scripts": {
25
25
  "generate:llms": "npx tsx scripts/generate-llms.ts",
26
26
  "build": "npm run generate:llms && vite build && tsc -p tsconfig.json",
27
+ "build:stackblitz": "vite build && tsc -p tsconfig.json",
27
28
  "dev": "vite",
28
29
  "test": "vitest",
29
30
  "test:watch": "vitest watch"