@websolutespa/bom-mixer-forms 1.8.1 → 1.9.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @websolutespa/bom-mixer-forms
2
2
 
3
+ ## 1.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Added: useFormSchema
8
+
3
9
  ## 1.8.1
4
10
 
5
11
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -11,10 +11,10 @@ declare class EventEmitter {
11
11
  once(event: string, listener: (...args: any[]) => any): void;
12
12
  }
13
13
 
14
- declare class FormAbstractCollection<T extends FormControls> extends FormAbstract {
14
+ declare class FormAbstractCollection<U extends Record<string, FormValue> | FormValue[], T extends FormControls> extends FormAbstract<U> {
15
15
  controls_: T;
16
16
  constructor(controls: T, validators?: (FormValidator | FormValidator[]));
17
- initControl_(controlOrValue: FormAbstract | any, key: any): FormAbstract;
17
+ initControl_(controlOrValue: FormAbstract | FormValue, key: any): FormAbstract;
18
18
  protected setInitialOptions(options?: FormOptions): void;
19
19
  protected checkAsyncPropState_(key: keyof FormFlags, option?: FormActivator, root?: FormCollection): Promise<boolean>;
20
20
  updateState_(): void;
@@ -34,7 +34,7 @@ declare class FormAbstractCollection<T extends FormControls> extends FormAbstrac
34
34
  protected reduce_(callback: Function, result: any): any;
35
35
  protected all_(key: (keyof FormAbstract), value: any): boolean;
36
36
  protected any_(key: (keyof FormAbstract), value: any): boolean;
37
- protected map_(): FormAbstract[];
37
+ protected map_(): FormAbstract<any>[];
38
38
  get controls(): T;
39
39
  set controls(controls: T);
40
40
  set disabled(disabled: boolean);
@@ -42,12 +42,8 @@ declare class FormAbstractCollection<T extends FormControls> extends FormAbstrac
42
42
  set hidden(hidden: boolean);
43
43
  set submitted(submitted: boolean);
44
44
  set touched(touched: boolean);
45
- get value(): {
46
- [key: string]: FormValue;
47
- };
48
- set value(value: {
49
- [key: string]: FormValue;
50
- });
45
+ get value(): U;
46
+ set value(value: U);
51
47
  get errors(): {
52
48
  [key: string]: any;
53
49
  };
@@ -56,11 +52,11 @@ declare class FormAbstractCollection<T extends FormControls> extends FormAbstrac
56
52
  });
57
53
  }
58
54
 
59
- declare class FormArray extends FormAbstractCollection<FormAbstract[]> {
60
- constructor(controls?: FormAbstract[], validators?: FormValidator | FormValidator[], initialOptions?: FormOptions);
55
+ declare class FormArray<T extends FormValue[] = FormValue[]> extends FormAbstractCollection<T, FormArrayControls> {
56
+ constructor(controls?: FormArrayControls, validators?: FormValidator | FormValidator[], initialOptions?: FormOptions);
61
57
  forEach_(callback: (control: FormAbstract, key: number) => any): void;
62
- map_(): FormAbstract[];
63
- get value(): FormValue[];
58
+ map_(): FormArrayControls;
59
+ get value(): T;
64
60
  get length(): number;
65
61
  protected init(control: FormAbstract, key: number): void;
66
62
  set(control: FormAbstract, key: number): void;
@@ -69,25 +65,19 @@ declare class FormArray extends FormAbstractCollection<FormAbstract[]> {
69
65
  insert(control: FormAbstract, key: number): void;
70
66
  remove(control: FormAbstract): void;
71
67
  removeKey(key: number): void;
72
- at(key: number): FormAbstract;
68
+ at(key: number): FormAbstract<any>;
73
69
  }
74
- declare function formArray(controls?: FormAbstract[], validators?: FormValidator | FormValidator[]): FormArray;
70
+ declare function formArray(controls?: FormArrayControls, validators?: FormValidator | FormValidator[]): FormArray<any[]>;
75
71
 
76
72
  declare class FormControl extends FormAbstract {
77
73
  constructor(value?: FormValue, validators?: FormValidator | FormValidator[], initialOptions?: FormOptions);
78
74
  }
79
75
  declare function formControl(value?: FormValue, validators?: FormValidator | FormValidator[]): FormControl;
80
76
 
81
- declare class FormGroup extends FormAbstractCollection<{
82
- [key: string]: FormAbstract;
83
- }> {
84
- constructor(controls?: {
85
- [key: string]: FormAbstract | any;
86
- }, validators?: FormValidator | FormValidator[], initialOptions?: FormOptions);
77
+ declare class FormGroup<T extends Record<string, FormValue> = FormValue> extends FormAbstractCollection<T, FormGroupControls> {
78
+ constructor(controls?: FormGroupControls, validators?: FormValidator | FormValidator[], initialOptions?: FormOptions);
87
79
  }
88
- declare function formGroup(controls?: {
89
- [key: string]: FormAbstract | FormValue;
90
- }, validators?: FormValidator | FormValidator[]): FormGroup;
80
+ declare function formGroup(controls?: FormGroupControls, validators?: FormValidator | FormValidator[]): FormGroup<any>;
91
81
 
92
82
  type FormValue = any;
93
83
  type FormValueGroup = {
@@ -121,10 +111,10 @@ type FormOptions = {
121
111
  type ValidationError = {
122
112
  [key: string]: any;
123
113
  };
124
- type FormControls = {
125
- [key: string]: FormAbstract | FormValue;
126
- } | FormAbstract[];
127
- type FormCollection = FormAbstractCollection<FormControls>;
114
+ type FormGroupControls = Record<string, FormAbstract | FormValue>;
115
+ type FormArrayControls = FormAbstract[];
116
+ type FormControls = FormGroupControls | FormArrayControls;
117
+ type FormCollection = FormAbstractCollection<Record<string, any> | any[], FormControls>;
128
118
  type FormActivator = boolean | ((value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormCollection) => boolean | Promise<boolean>);
129
119
  type FormValidator = (value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormCollection) => null | ValidationError;
130
120
  type FormAsyncValidator = (value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormCollection) => Promise<null | ValidationError>;
@@ -144,9 +134,7 @@ type FormFlags = {
144
134
  untouched: boolean;
145
135
  unsubmitted: boolean;
146
136
  };
147
- type FormErrors = {
148
- [key: string]: any;
149
- };
137
+ type FormErrors = Record<string, any>;
150
138
  type FormValidationError = {
151
139
  key: string;
152
140
  value: FormValue;
@@ -176,18 +164,14 @@ type IFormBuilderControlSchema = {
176
164
  children?: IFormBuilderSchema;
177
165
  customData?: Record<string, any>;
178
166
  };
179
- type IFormBuilderGroupSchema = {
180
- [key: string]: IFormBuilderControlSchema;
181
- };
167
+ type IFormBuilderGroupSchema = Record<string, IFormBuilderControlSchema>;
182
168
  type IFormBuilderArraySchema = IFormBuilderControlSchema[];
183
- type IFormBuilderGroupValues = {
184
- [key: string]: FormGroup | FormArray | FormControl;
185
- };
169
+ type IFormBuilderGroupValues = Record<string, FormGroup | FormArray | FormControl>;
186
170
  type IFormBuilderSchema = IFormBuilderGroupSchema | IFormBuilderArraySchema;
187
171
 
188
- declare class FormAbstract extends EventEmitter {
172
+ declare class FormAbstract<T = any> extends EventEmitter {
189
173
  errors_: ValidationError;
190
- value_: FormValue;
174
+ value_: T | null;
191
175
  validators_: FormValidator[];
192
176
  state_: FormFlags;
193
177
  name?: string | number;
@@ -247,8 +231,8 @@ declare class FormAbstract extends EventEmitter {
247
231
  get pristine(): boolean;
248
232
  get untouched(): boolean;
249
233
  get unsubmitted(): boolean;
250
- get value(): any;
251
- set value(value: any);
234
+ get value(): T | null;
235
+ set value(value: T | null);
252
236
  }
253
237
 
254
238
  declare function validValue(value: FormValue): any;
@@ -317,6 +301,17 @@ declare function useControl<T>(control: FormAbstract): [FormState<T>, (value: T
317
301
 
318
302
  declare function useForm<T, U extends (FormGroup | FormArray)>(factory: () => U, deps?: DependencyList): [FormState<T>, (value: any) => void, () => void, () => void, U];
319
303
 
320
- declare function useFormBuilder<T, U extends (FormGroup | FormArray)>(schema: IFormBuilderSchema, deps?: DependencyList): [FormState<T>, (value: Partial<T>) => void, () => void, () => void, U];
304
+ /**
305
+ * @deprecated Since version 1.9.0. Will be deleted in version 1.10.0. Use useFormSchema instead.
306
+ */
307
+ declare function useFormBuilder<T extends (Record<string, FormValue> | FormValue[]) = Record<string, FormValue>, U extends (T extends FormValue[] ? FormArray<T> : FormGroup<T>) = T extends FormValue[] ? FormArray<T> : FormGroup<T>>(schema: IFormBuilderSchema, deps?: DependencyList): [FormState<T>, (value: Partial<T>) => void, () => void, () => void, U];
308
+
309
+ declare function useFormSchema<T extends (Record<string, FormValue> | FormValue[]) = Record<string, FormValue>, U extends (T extends FormValue[] ? FormArray<T> : FormGroup<T>) = T extends FormValue[] ? FormArray<T> : FormGroup<T>>(schema: IFormBuilderSchema, deps?: DependencyList): {
310
+ state: FormState<T>;
311
+ setValue: (value: Partial<T>) => void;
312
+ setTouched: () => void;
313
+ reset: () => void;
314
+ form: U;
315
+ };
321
316
 
322
- export { ControlType, EmailValidator, FormAbstract, FormAbstractCollection, FormActivator, FormArray, FormAsyncValidator, FormCollection, FormControl, FormControls, FormErrors, FormFlags, FormGroup, FormOptions, FormState, FormValidationError, FormValidationErrors, FormValidator, FormValue, FormValueArray, FormValueGroup, IControlParam, IFormBuilderArraySchema, IFormBuilderControlSchema, IFormBuilderGroupSchema, IFormBuilderGroupValues, IFormBuilderSchema, IFormOption, MatchValidator, MaxLengthValidator, MaxValidator, MinLengthValidator, MinValidator, NullValidator, PatternValidator, RequiredIfValidator, RequiredTrueValidator, RequiredValidator, ValidationError, formArray, formControl, formGroup, mapErrors_, stringToValue, useControl, useForm, useFormBuilder, validValue, valueToString };
317
+ export { ControlType, EmailValidator, FormAbstract, FormAbstractCollection, FormActivator, FormArray, FormArrayControls, FormAsyncValidator, FormCollection, FormControl, FormControls, FormErrors, FormFlags, FormGroup, FormGroupControls, FormOptions, FormState, FormValidationError, FormValidationErrors, FormValidator, FormValue, FormValueArray, FormValueGroup, IControlParam, IFormBuilderArraySchema, IFormBuilderControlSchema, IFormBuilderGroupSchema, IFormBuilderGroupValues, IFormBuilderSchema, IFormOption, MatchValidator, MaxLengthValidator, MaxValidator, MinLengthValidator, MinValidator, NullValidator, PatternValidator, RequiredIfValidator, RequiredTrueValidator, RequiredValidator, ValidationError, formArray, formControl, formGroup, mapErrors_, stringToValue, useControl, useForm, useFormBuilder, useFormSchema, validValue, valueToString };
package/dist/index.js CHANGED
@@ -78,6 +78,7 @@ __export(src_exports, {
78
78
  useControl: () => useControl,
79
79
  useForm: () => useForm,
80
80
  useFormBuilder: () => useFormBuilder,
81
+ useFormSchema: () => useFormSchema,
81
82
  validValue: () => validValue,
82
83
  valueToString: () => valueToString
83
84
  });
@@ -1115,6 +1116,73 @@ function mapSchema_(schema) {
1115
1116
  return mapControl_(schema);
1116
1117
  }
1117
1118
  }
1119
+
1120
+ // src/hooks/useFormSchema/useFormSchema.ts
1121
+ var import_react4 = require("react");
1122
+ function useFormSchema(schema, deps = []) {
1123
+ const form = (0, import_react4.useMemo)(() => {
1124
+ if (Array.isArray(schema)) {
1125
+ return mapArray_2(schema);
1126
+ } else {
1127
+ return mapGroup_2(schema);
1128
+ }
1129
+ }, deps);
1130
+ const setValue = (0, import_react4.useCallback)((value) => {
1131
+ form.patch(value);
1132
+ }, deps);
1133
+ const setTouched = (0, import_react4.useCallback)(() => {
1134
+ form.touched = true;
1135
+ }, deps);
1136
+ const reset = (0, import_react4.useCallback)(() => {
1137
+ form.reset();
1138
+ }, deps);
1139
+ const [state, setState] = (0, import_react4.useState)({
1140
+ value: form.value,
1141
+ flags: form.state,
1142
+ errors: mapErrors_(form.errors)
1143
+ });
1144
+ (0, import_react4.useEffect)(() => {
1145
+ const onChange = (value) => {
1146
+ const newState = { value, flags: form.state, errors: mapErrors_(form.errors) };
1147
+ };
1148
+ form.on("change", onChange);
1149
+ form.revalidate_();
1150
+ return () => form.off("change", onChange);
1151
+ }, deps);
1152
+ return {
1153
+ form,
1154
+ state,
1155
+ setTouched,
1156
+ setValue,
1157
+ reset
1158
+ };
1159
+ }
1160
+ function mapGroup_2(children, schema) {
1161
+ const controls = {};
1162
+ Object.keys(children).forEach((key) => {
1163
+ controls[key] = mapSchema_2(__spreadValues({ name: key }, children[key]));
1164
+ });
1165
+ const group = new FormGroup(controls, schema == null ? void 0 : schema.validators, schema);
1166
+ return group;
1167
+ }
1168
+ function mapArray_2(children, schema) {
1169
+ const controls = children.map((x) => mapSchema_2(x));
1170
+ const array = new FormArray(controls, schema == null ? void 0 : schema.validators, schema);
1171
+ return array;
1172
+ }
1173
+ function mapControl_2(schema) {
1174
+ return new FormControl(schema.value, schema.validators, schema);
1175
+ }
1176
+ function mapSchema_2(schema) {
1177
+ switch (schema.schema) {
1178
+ case "group":
1179
+ return mapGroup_2(schema.children || {}, schema);
1180
+ case "array":
1181
+ return mapArray_2(schema.children || [], schema);
1182
+ default:
1183
+ return mapControl_2(schema);
1184
+ }
1185
+ }
1118
1186
  // Annotate the CommonJS export names for ESM import in node:
1119
1187
  0 && (module.exports = {
1120
1188
  EmailValidator,
@@ -1141,6 +1209,7 @@ function mapSchema_(schema) {
1141
1209
  useControl,
1142
1210
  useForm,
1143
1211
  useFormBuilder,
1212
+ useFormSchema,
1144
1213
  validValue,
1145
1214
  valueToString
1146
1215
  });
package/dist/index.mjs CHANGED
@@ -1067,6 +1067,73 @@ function mapSchema_(schema) {
1067
1067
  return mapControl_(schema);
1068
1068
  }
1069
1069
  }
1070
+
1071
+ // src/hooks/useFormSchema/useFormSchema.ts
1072
+ import { useCallback as useCallback4, useEffect as useEffect4, useMemo as useMemo3, useState as useState4 } from "react";
1073
+ function useFormSchema(schema, deps = []) {
1074
+ const form = useMemo3(() => {
1075
+ if (Array.isArray(schema)) {
1076
+ return mapArray_2(schema);
1077
+ } else {
1078
+ return mapGroup_2(schema);
1079
+ }
1080
+ }, deps);
1081
+ const setValue = useCallback4((value) => {
1082
+ form.patch(value);
1083
+ }, deps);
1084
+ const setTouched = useCallback4(() => {
1085
+ form.touched = true;
1086
+ }, deps);
1087
+ const reset = useCallback4(() => {
1088
+ form.reset();
1089
+ }, deps);
1090
+ const [state, setState] = useState4({
1091
+ value: form.value,
1092
+ flags: form.state,
1093
+ errors: mapErrors_(form.errors)
1094
+ });
1095
+ useEffect4(() => {
1096
+ const onChange = (value) => {
1097
+ const newState = { value, flags: form.state, errors: mapErrors_(form.errors) };
1098
+ };
1099
+ form.on("change", onChange);
1100
+ form.revalidate_();
1101
+ return () => form.off("change", onChange);
1102
+ }, deps);
1103
+ return {
1104
+ form,
1105
+ state,
1106
+ setTouched,
1107
+ setValue,
1108
+ reset
1109
+ };
1110
+ }
1111
+ function mapGroup_2(children, schema) {
1112
+ const controls = {};
1113
+ Object.keys(children).forEach((key) => {
1114
+ controls[key] = mapSchema_2(__spreadValues({ name: key }, children[key]));
1115
+ });
1116
+ const group = new FormGroup(controls, schema == null ? void 0 : schema.validators, schema);
1117
+ return group;
1118
+ }
1119
+ function mapArray_2(children, schema) {
1120
+ const controls = children.map((x) => mapSchema_2(x));
1121
+ const array = new FormArray(controls, schema == null ? void 0 : schema.validators, schema);
1122
+ return array;
1123
+ }
1124
+ function mapControl_2(schema) {
1125
+ return new FormControl(schema.value, schema.validators, schema);
1126
+ }
1127
+ function mapSchema_2(schema) {
1128
+ switch (schema.schema) {
1129
+ case "group":
1130
+ return mapGroup_2(schema.children || {}, schema);
1131
+ case "array":
1132
+ return mapArray_2(schema.children || [], schema);
1133
+ default:
1134
+ return mapControl_2(schema);
1135
+ }
1136
+ }
1070
1137
  export {
1071
1138
  EmailValidator,
1072
1139
  FormAbstract,
@@ -1092,6 +1159,7 @@ export {
1092
1159
  useControl,
1093
1160
  useForm,
1094
1161
  useFormBuilder,
1162
+ useFormSchema,
1095
1163
  validValue,
1096
1164
  valueToString
1097
1165
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@websolutespa/bom-mixer-forms",
3
- "version": "1.8.1",
3
+ "version": "1.9.0",
4
4
  "description": "Mixer Forms module of the BOM Repository",
5
5
  "keywords": [
6
6
  "bom",
@@ -3,7 +3,10 @@ import { FormAbstract } from './form-abstract';
3
3
  import { FormControl } from './form-control';
4
4
  import { FormActivator, FormCollection, FormControls, FormFlags, FormOptions, FormValidator, FormValue } from './types';
5
5
 
6
- export class FormAbstractCollection<T extends FormControls> extends FormAbstract {
6
+ export class FormAbstractCollection<
7
+ U extends Record<string, FormValue> | FormValue[],
8
+ T extends FormControls> extends FormAbstract<U
9
+ > {
7
10
 
8
11
  controls_: T;
9
12
 
@@ -16,7 +19,7 @@ export class FormAbstractCollection<T extends FormControls> extends FormAbstract
16
19
  });
17
20
  }
18
21
 
19
- initControl_(controlOrValue: FormAbstract | any, key: any): FormAbstract {
22
+ initControl_(controlOrValue: FormAbstract | FormValue, key: any): FormAbstract {
20
23
  const control = controlOrValue instanceof FormAbstract ? controlOrValue : new FormControl(controlOrValue);
21
24
  control.name = key;
22
25
  control.parent = this;
@@ -283,18 +286,18 @@ export class FormAbstractCollection<T extends FormControls> extends FormAbstract
283
286
  });
284
287
  }
285
288
 
286
- get value(): { [key: string]: FormValue } {
287
- return this.reduce_((result: { [key: string]: FormValue }, control: FormAbstract, key: string) => {
289
+ get value(): U {
290
+ return this.reduce_((result: U, control: FormAbstract, key: string) => {
288
291
  if (control.enabled) {
289
- result[key] = control.value;
292
+ result[key as keyof U] = control.value;
290
293
  }
291
294
  return result;
292
295
  }, {});
293
296
  }
294
297
 
295
- set value(value: { [key: string]: FormValue }) {
298
+ set value(value: U) {
296
299
  this.forEach_((control: FormAbstract, key: string) => {
297
- control.value = value[key];
300
+ control.value = value[key as keyof U];
298
301
  });
299
302
  }
300
303
 
@@ -3,11 +3,11 @@ import { EventEmitter } from './event-emitter';
3
3
  import { ControlType, FormActivator, FormCollection, FormFlags, FormOptions, FormValidator, FormValue, ValidationError } from './types';
4
4
  import { validValue } from './utils';
5
5
 
6
- export class FormAbstract extends EventEmitter {
6
+ export class FormAbstract<T = any> extends EventEmitter {
7
7
 
8
8
  // callbacks_: Function[] = [];
9
9
  errors_: ValidationError;
10
- value_: FormValue;
10
+ value_: T | null;
11
11
  validators_: FormValidator[];
12
12
  state_: FormFlags;
13
13
  name?: string | number;
@@ -1,10 +1,10 @@
1
1
  import { FormAbstract } from './form-abstract';
2
2
  import { FormAbstractCollection } from './form-abstract-collection';
3
- import { FormOptions, FormValidator, FormValue } from './types';
3
+ import { FormArrayControls, FormOptions, FormValidator, FormValue } from './types';
4
4
 
5
- export class FormArray extends FormAbstractCollection<FormAbstract[]> {
5
+ export class FormArray<T extends FormValue[] = FormValue[]> extends FormAbstractCollection<T, FormArrayControls> {
6
6
 
7
- constructor(controls: FormAbstract[] = [], validators?: FormValidator | FormValidator[], initialOptions?: FormOptions) {
7
+ constructor(controls: FormArrayControls = [], validators?: FormValidator | FormValidator[], initialOptions?: FormOptions) {
8
8
  super(controls, validators);
9
9
  this.setInitialOptions(initialOptions);
10
10
  // this.revalidate_();
@@ -18,8 +18,8 @@ export class FormArray extends FormAbstractCollection<FormAbstract[]> {
18
18
  return this.controls;
19
19
  }
20
20
 
21
- get value(): FormValue[] {
22
- return this.reduce_((result: FormValue[], control: FormAbstract, key: number) => {
21
+ get value(): T {
22
+ return this.reduce_((result: T, control: FormAbstract, key: number) => {
23
23
  result[key] = control.value;
24
24
  return result;
25
25
  }, []); // init as array
@@ -73,6 +73,6 @@ export class FormArray extends FormAbstractCollection<FormAbstract[]> {
73
73
  }
74
74
  }
75
75
 
76
- export function formArray(controls: FormAbstract[] = [], validators?: FormValidator | FormValidator[]) {
76
+ export function formArray(controls: FormArrayControls = [], validators?: FormValidator | FormValidator[]) {
77
77
  return new FormArray(controls, validators);
78
78
  }
@@ -1,15 +1,14 @@
1
- import { FormAbstract } from './form-abstract';
2
1
  import { FormAbstractCollection } from './form-abstract-collection';
3
- import { FormOptions, FormValidator, FormValue } from './types';
2
+ import { FormGroupControls, FormOptions, FormValidator, FormValue } from './types';
4
3
 
5
- export class FormGroup extends FormAbstractCollection<{ [key: string]: FormAbstract }> {
6
- constructor(controls: { [key: string]: FormAbstract | any } = {}, validators?: FormValidator | FormValidator[], initialOptions?: FormOptions) {
4
+ export class FormGroup<T extends Record<string, FormValue> = FormValue> extends FormAbstractCollection<T, FormGroupControls> {
5
+ constructor(controls: FormGroupControls = {}, validators?: FormValidator | FormValidator[], initialOptions?: FormOptions) {
7
6
  super(controls, validators);
8
7
  this.setInitialOptions(initialOptions);
9
8
  // this.revalidate_();
10
9
  }
11
10
  }
12
11
 
13
- export function formGroup(controls: { [key: string]: FormAbstract | FormValue } = {}, validators?: FormValidator | FormValidator[]) {
12
+ export function formGroup(controls: FormGroupControls = {}, validators?: FormValidator | FormValidator[]) {
14
13
  return new FormGroup(controls, validators);
15
14
  }
@@ -34,8 +34,10 @@ export type ValidationError = {
34
34
  [key: string]: any
35
35
  };
36
36
 
37
- export type FormControls = { [key: string]: FormAbstract | FormValue } | FormAbstract[];
38
- export type FormCollection = FormAbstractCollection<FormControls>;
37
+ export type FormGroupControls = Record<string, FormAbstract | FormValue>;
38
+ export type FormArrayControls = FormAbstract[];
39
+ export type FormControls = FormGroupControls | FormArrayControls;
40
+ export type FormCollection = FormAbstractCollection<Record<string, any> | any[], FormControls>;
39
41
  export type FormActivator = boolean | ((value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormCollection) => boolean | Promise<boolean>);
40
42
  export type FormValidator = (value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormCollection) => null | ValidationError;
41
43
  export type FormAsyncValidator = (value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormCollection) => Promise<null | ValidationError>;
@@ -57,7 +59,7 @@ export type FormFlags = {
57
59
  unsubmitted: boolean;
58
60
  };
59
61
  // export type FormFlags = { [key: string]: boolean };
60
- export type FormErrors = { [key: string]: any };
62
+ export type FormErrors = Record<string, any>;
61
63
  export type FormValidationError = { key: string, value: FormValue };
62
64
  export type FormValidationErrors = FormValidationError[];
63
65
 
@@ -86,7 +88,7 @@ export type IFormBuilderControlSchema = {
86
88
  customData?: Record<string, any>;
87
89
  };
88
90
 
89
- export type IFormBuilderGroupSchema = { [key: string]: IFormBuilderControlSchema };
91
+ export type IFormBuilderGroupSchema = Record<string, IFormBuilderControlSchema>;
90
92
  export type IFormBuilderArraySchema = IFormBuilderControlSchema[];
91
- export type IFormBuilderGroupValues = { [key: string]: FormGroup | FormArray | FormControl };
93
+ export type IFormBuilderGroupValues = Record<string, FormGroup | FormArray | FormControl>;
92
94
  export type IFormBuilderSchema = IFormBuilderGroupSchema | IFormBuilderArraySchema;
@@ -1,4 +1,5 @@
1
1
  export { useControl } from './useControl/useControl';
2
2
  export { useForm } from './useForm/useForm';
3
3
  export { useFormBuilder } from './useFormBuilder/useFormBuilder';
4
+ export { useFormSchema } from './useFormSchema/useFormSchema';
4
5
 
@@ -1,8 +1,14 @@
1
1
  import { DependencyList, useCallback, useEffect, useMemo, useState } from 'react';
2
2
  import { FormArray, FormControl, FormGroup, FormState, mapErrors_ } from '../../forms';
3
- import { IFormBuilderArraySchema, IFormBuilderControlSchema, IFormBuilderGroupSchema, IFormBuilderGroupValues, IFormBuilderSchema } from '../../forms/types';
3
+ import { FormValue, IFormBuilderArraySchema, IFormBuilderControlSchema, IFormBuilderGroupSchema, IFormBuilderGroupValues, IFormBuilderSchema } from '../../forms/types';
4
4
 
5
- export function useFormBuilder<T, U extends (FormGroup | FormArray)>(
5
+ /**
6
+ * @deprecated Since version 1.9.0. Will be deleted in version 1.10.0. Use useFormSchema instead.
7
+ */
8
+ export function useFormBuilder<
9
+ T extends (Record<string, FormValue> | FormValue[]) = Record<string, FormValue>,
10
+ U extends (T extends FormValue[] ? FormArray<T> : FormGroup<T>) = T extends FormValue[] ? FormArray<T> : FormGroup<T>
11
+ >(
6
12
  schema: IFormBuilderSchema,
7
13
  deps: DependencyList = []
8
14
  ): [FormState<T>, (value: Partial<T>) => void, () => void, () => void, U] {
@@ -0,0 +1,105 @@
1
+ import { DependencyList, useCallback, useEffect, useMemo, useState } from 'react';
2
+ import { FormArray, FormControl, FormGroup, FormState, mapErrors_ } from '../../forms';
3
+ import { FormValue, IFormBuilderArraySchema, IFormBuilderControlSchema, IFormBuilderGroupSchema, IFormBuilderGroupValues, IFormBuilderSchema } from '../../forms/types';
4
+
5
+ export function useFormSchema<
6
+ T extends (Record<string, FormValue> | FormValue[]) = Record<string, FormValue>,
7
+ U extends (T extends FormValue[] ? FormArray<T> : FormGroup<T>) = T extends FormValue[] ? FormArray<T> : FormGroup<T>
8
+ >(
9
+ schema: IFormBuilderSchema,
10
+ deps: DependencyList = []
11
+ ): {
12
+ state: FormState<T>,
13
+ setValue: (value: Partial<T>) => void,
14
+ setTouched: () => void,
15
+ reset: () => void,
16
+ form: U,
17
+ } {
18
+ const form: U = useMemo<U>(() => {
19
+ // console.log(' useFormSchema.rebuild', schema);
20
+ if (Array.isArray(schema)) {
21
+ return mapArray_(schema) as U;
22
+ } else {
23
+ return mapGroup_(schema) as U;
24
+ }
25
+ // eslint-disable-next-line react-hooks/exhaustive-deps
26
+ }, deps);
27
+
28
+ const setValue = useCallback((value: Partial<T>) => {
29
+ form.patch(value);
30
+ // eslint-disable-next-line react-hooks/exhaustive-deps
31
+ }, deps);
32
+
33
+ const setTouched = useCallback(() => {
34
+ form.touched = true;
35
+ // eslint-disable-next-line react-hooks/exhaustive-deps
36
+ }, deps);
37
+
38
+ const reset = useCallback(() => {
39
+ form.reset();
40
+ // eslint-disable-next-line react-hooks/exhaustive-deps
41
+ }, deps);
42
+
43
+ const [state, setState] = useState<FormState<T>>({
44
+ value: form.value as T,
45
+ flags: form.state,
46
+ errors: mapErrors_(form.errors),
47
+ });
48
+
49
+ useEffect(() => {
50
+ const onChange = (value: T) => {
51
+ // console.log(' useFormSchema.onChange', value);
52
+ const newState = { value, flags: form.state, errors: mapErrors_(form.errors) };
53
+ // setState(newState);
54
+ };
55
+ form.on('change', onChange);
56
+ // form.validateAndChange_();
57
+ form.revalidate_();
58
+ // const value = form.value;
59
+ // form.reset();
60
+ // form.patch(value);
61
+ // console.log('subscribe');
62
+ return () => form.off('change', onChange);
63
+ // eslint-disable-next-line react-hooks/exhaustive-deps
64
+ }, deps);
65
+
66
+ // console.log(' useFormSchema', form.value);
67
+
68
+ return {
69
+ form,
70
+ state,
71
+ setTouched,
72
+ setValue,
73
+ reset,
74
+ };
75
+ }
76
+
77
+ function mapGroup_(children: IFormBuilderGroupSchema, schema?: IFormBuilderControlSchema): FormGroup {
78
+ const controls: IFormBuilderGroupValues = {};
79
+ Object.keys(children).forEach(key => {
80
+ controls[key] = mapSchema_({ name: key, ...children[key] });
81
+ });
82
+ const group = new FormGroup(controls, schema?.validators, schema);
83
+ return group;
84
+ }
85
+
86
+ function mapArray_(children: IFormBuilderControlSchema[], schema?: IFormBuilderControlSchema): FormArray {
87
+ const controls = children.map(x => mapSchema_(x));
88
+ const array = new FormArray(controls, schema?.validators, schema);
89
+ return array;
90
+ }
91
+
92
+ function mapControl_(schema: IFormBuilderControlSchema): FormControl {
93
+ return new FormControl(schema.value, schema.validators, schema);
94
+ }
95
+
96
+ function mapSchema_(schema: IFormBuilderControlSchema): FormGroup | FormArray | FormControl {
97
+ switch (schema.schema) {
98
+ case 'group':
99
+ return mapGroup_(schema.children as IFormBuilderGroupSchema || {}, schema);
100
+ case 'array':
101
+ return mapArray_(schema.children as IFormBuilderArraySchema || [], schema);
102
+ default:
103
+ return mapControl_(schema);
104
+ }
105
+ }