@reformer/core 1.0.0 → 1.1.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.
package/README.md CHANGED
@@ -3,10 +3,13 @@
3
3
  [![npm version](https://img.shields.io/npm/v/@reformer/core.svg)](https://www.npmjs.com/package/@reformer/core)
4
4
  [![npm downloads](https://img.shields.io/npm/dm/@reformer/core.svg)](https://www.npmjs.com/package/@reformer/core)
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
6
- [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/~/github.com/AlexandrBukhtatyy/ReFormer/tree/main/projects/react-playground?file=projects/react-playground/src/App.tsx)
7
6
 
8
7
  Reactive form state management library for React with signals-based architecture.
9
8
 
9
+ ## Playground
10
+
11
+ [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz_small.svg)](https://stackblitz.com/~/github.com/AlexandrBukhtatyy/ReFormer/tree/main/projects/react-playground?file=projects/react-playground/src/App.tsx)
12
+
10
13
  ## Documentation
11
14
 
12
15
  Full documentation is available at [https://alexandrbukhtatyy.github.io/ReFormer/](https://alexandrbukhtatyy.github.io/ReFormer/)
@@ -22,7 +25,7 @@ Full documentation is available at [https://alexandrbukhtatyy.github.io/ReFormer
22
25
  ## Installation
23
26
 
24
27
  ```bash
25
- npm install @reformer/core
28
+ npm install @reformer/core@beta # Active development is underway, so you can try beta
26
29
  ```
27
30
 
28
31
  ## Quick Start
@@ -39,15 +42,7 @@ import {
39
42
  FieldNode,
40
43
  } from '@reformer/core';
41
44
 
42
- // 1. Define form interface
43
- interface RegistrationForm {
44
- username: string;
45
- email: string;
46
- password: string;
47
- confirmPassword: string;
48
- }
49
-
50
- // 2. Simple FormField component
45
+ // 0. Simple FormField component
51
46
  function FormField({ label, control }: { label: string; control: FieldNode<string> }) {
52
47
  const { value, errors } = useFormControl(control);
53
48
 
@@ -64,47 +59,61 @@ function FormField({ label, control }: { label: string; control: FieldNode<strin
64
59
  );
65
60
  }
66
61
 
67
- // 3. Registration form component
62
+ // 1. Define form interface
63
+ interface RegistrationForm {
64
+ username: string;
65
+ email: string;
66
+ password: string;
67
+ confirmPassword: string;
68
+ }
69
+
70
+ // 2. Form schema
71
+ const formSchema = {
72
+ username: { value: '' },
73
+ email: { value: '' },
74
+ password: { value: '' },
75
+ confirmPassword: { value: '' },
76
+ };
77
+
78
+ // 3. Validation schema
79
+ validationSchema = (path) => {
80
+ required(path.username);
81
+
82
+ required(path.email);
83
+ email(path.email);
84
+
85
+ required(path.password);
86
+ required(path.confirmPassword);
87
+
88
+ // Cross-field validation: passwords must match
89
+ validate(path.confirmPassword, (value, ctx) => {
90
+ const password = ctx.form.password.value.value;
91
+ if (value && password && value !== password) {
92
+ return { code: 'mismatch', message: 'Passwords do not match' };
93
+ }
94
+ return null;
95
+ });
96
+ };
97
+
98
+ // 4. Behavior schema
99
+ behavior = (path) => {
100
+ // Clear confirmPassword when password changes (if not empty)
101
+ watchField(path.password, (_, ctx) => {
102
+ const confirmValue = ctx.form.confirmPassword.value.value;
103
+ if (confirmValue) {
104
+ ctx.form.confirmPassword.setValue('', { emitEvent: false });
105
+ }
106
+ });
107
+ };
108
+
109
+ // 5. Registration form component
68
110
  function RegistrationFormExample() {
69
111
  const form = useMemo(
70
112
  () =>
71
113
  createForm<RegistrationForm>({
72
- // Form schema
73
- form: {
74
- username: { value: '' },
75
- email: { value: '' },
76
- password: { value: '' },
77
- confirmPassword: { value: '' },
78
- },
79
-
80
- // Validation schema
81
- validation: (path) => {
82
- required(path.username);
83
- required(path.email);
84
- email(path.email);
85
- required(path.password);
86
- required(path.confirmPassword);
87
-
88
- // Cross-field validation: passwords must match
89
- validate(path.confirmPassword, (value, ctx) => {
90
- const password = ctx.form.password.value.value;
91
- if (value && password && value !== password) {
92
- return { code: 'mismatch', message: 'Passwords do not match' };
93
- }
94
- return null;
95
- });
96
- },
97
-
98
- // Behavior schema
99
- behavior: (path) => {
100
- // Clear confirmPassword when password changes (if not empty)
101
- watchField(path.password, (_, ctx) => {
102
- const confirmValue = ctx.form.confirmPassword.value.value;
103
- if (confirmValue) {
104
- ctx.form.confirmPassword.setValue('', { emitEvent: false });
105
- }
106
- });
107
- },
114
+ form: formSchema,
115
+ validation: validationSchema,
116
+ behavior: behaviorSchema,
108
117
  }),
109
118
  []
110
119
  );
@@ -13,13 +13,19 @@ import { TreeValidatorFn, ValidateTreeOptions } from '../../types';
13
13
  * @group Validation
14
14
  * @category Core Functions
15
15
  *
16
+ * @remarks
17
+ * Параметр `ctx` в callback требует явной типизации для корректного вывода типов:
18
+ * ```typescript
19
+ * validateTree((ctx: { form: MyFormType }) => { ... });
20
+ * ```
21
+ *
16
22
  * @example
17
23
  * ```typescript
24
+ * // Явная типизация ctx для избежания implicit any
18
25
  * validateTree(
19
- * (ctx: ValidationContext<TForm, TField>) => {
20
- * const form = ctx.formValue();
21
- * if (form.initialPayment && form.propertyValue) {
22
- * if (form.initialPayment > form.propertyValue) {
26
+ * (ctx: { form: MyForm }) => {
27
+ * if (ctx.form.initialPayment && ctx.form.propertyValue) {
28
+ * if (ctx.form.initialPayment > ctx.form.propertyValue) {
23
29
  * return {
24
30
  * code: 'initialPaymentTooHigh',
25
31
  * message: 'Первоначальный взнос не может превышать стоимость',
@@ -13,13 +13,19 @@ import { getCurrentValidationRegistry } from '../../utils/registry-helpers';
13
13
  * @group Validation
14
14
  * @category Core Functions
15
15
  *
16
+ * @remarks
17
+ * Параметр `ctx` в callback требует явной типизации для корректного вывода типов:
18
+ * ```typescript
19
+ * validateTree((ctx: { form: MyFormType }) => { ... });
20
+ * ```
21
+ *
16
22
  * @example
17
23
  * ```typescript
24
+ * // Явная типизация ctx для избежания implicit any
18
25
  * validateTree(
19
- * (ctx: ValidationContext<TForm, TField>) => {
20
- * const form = ctx.formValue();
21
- * if (form.initialPayment && form.propertyValue) {
22
- * if (form.initialPayment > form.propertyValue) {
26
+ * (ctx: { form: MyForm }) => {
27
+ * if (ctx.form.initialPayment && ctx.form.propertyValue) {
28
+ * if (ctx.form.initialPayment > ctx.form.propertyValue) {
23
29
  * return {
24
30
  * code: 'initialPaymentTooHigh',
25
31
  * message: 'Первоначальный взнос не может превышать стоимость',