@websolutespa/bom-mixer-forms 1.8.0 → 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 +12 -0
- package/dist/index.d.ts +48 -53
- package/dist/index.js +91 -22
- package/dist/index.mjs +90 -22
- package/package.json +1 -1
- package/src/forms/form-abstract-collection.ts +10 -7
- package/src/forms/form-abstract.ts +2 -2
- package/src/forms/form-array.ts +6 -6
- package/src/forms/form-group.ts +4 -5
- package/src/forms/types.ts +7 -5
- package/src/forms/validators/email.validator.ts +2 -2
- package/src/forms/validators/match.validator.ts +5 -2
- package/src/forms/validators/max-length.validator.ts +2 -2
- package/src/forms/validators/max.validator.ts +2 -2
- package/src/forms/validators/min-length.validator.ts +2 -2
- package/src/forms/validators/min.validator.ts +2 -2
- package/src/forms/validators/pattern.validator.ts +2 -2
- package/src/forms/validators/required-if.validator.ts +3 -3
- package/src/forms/validators/required-true.validator.ts +2 -2
- package/src/forms/validators/required.validator.ts +3 -3
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useFormBuilder/useFormBuilder.ts +8 -2
- package/src/hooks/useFormSchema/useFormSchema.ts +105 -0
package/CHANGELOG.md
CHANGED
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 |
|
|
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
|
-
|
|
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
|
|
60
|
-
constructor(controls?:
|
|
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_():
|
|
63
|
-
get value():
|
|
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?:
|
|
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
|
-
[
|
|
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
|
|
125
|
-
|
|
126
|
-
|
|
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_:
|
|
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():
|
|
251
|
-
set value(value:
|
|
234
|
+
get value(): T | null;
|
|
235
|
+
set value(value: T | null);
|
|
252
236
|
}
|
|
253
237
|
|
|
254
238
|
declare function validValue(value: FormValue): any;
|
|
@@ -261,32 +245,32 @@ declare function stringToValue(value: string | string[] | undefined, options?: I
|
|
|
261
245
|
/**
|
|
262
246
|
* an email pattern validator
|
|
263
247
|
*/
|
|
264
|
-
declare function EmailValidator(): FormValidator;
|
|
248
|
+
declare function EmailValidator(key?: string): FormValidator;
|
|
265
249
|
|
|
266
250
|
/**
|
|
267
251
|
* an equality match validation on another field
|
|
268
252
|
*/
|
|
269
|
-
declare function MatchValidator(getOtherValue: (value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormAbstract) => any): FormValidator;
|
|
253
|
+
declare function MatchValidator(getOtherValue: (value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormAbstract) => any, key?: string): FormValidator;
|
|
270
254
|
|
|
271
255
|
/**
|
|
272
256
|
* a max string length validator
|
|
273
257
|
*/
|
|
274
|
-
declare function MaxLengthValidator(maxlength: number): FormValidator;
|
|
258
|
+
declare function MaxLengthValidator(maxlength: number, key?: string): FormValidator;
|
|
275
259
|
|
|
276
260
|
/**
|
|
277
261
|
* a max number value validator
|
|
278
262
|
*/
|
|
279
|
-
declare function MaxValidator(max: number): FormValidator;
|
|
263
|
+
declare function MaxValidator(max: number, key?: string): FormValidator;
|
|
280
264
|
|
|
281
265
|
/**
|
|
282
266
|
* a min string length validator
|
|
283
267
|
*/
|
|
284
|
-
declare function MinLengthValidator(minlength: number): FormValidator;
|
|
268
|
+
declare function MinLengthValidator(minlength: number, key?: string): FormValidator;
|
|
285
269
|
|
|
286
270
|
/**
|
|
287
271
|
* a min number value validator
|
|
288
272
|
*/
|
|
289
|
-
declare function MinValidator(min: number): FormValidator;
|
|
273
|
+
declare function MinValidator(min: number, key?: string): FormValidator;
|
|
290
274
|
|
|
291
275
|
/**
|
|
292
276
|
* a null validator
|
|
@@ -296,27 +280,38 @@ declare function NullValidator(): FormValidator;
|
|
|
296
280
|
/**
|
|
297
281
|
* a regex pattern validator
|
|
298
282
|
*/
|
|
299
|
-
declare function PatternValidator(pattern: string | RegExp): FormValidator;
|
|
283
|
+
declare function PatternValidator(pattern: string | RegExp, key?: string): FormValidator;
|
|
300
284
|
|
|
301
285
|
/**
|
|
302
286
|
* a required dependant on another field
|
|
303
287
|
*/
|
|
304
|
-
declare function RequiredIfValidator(condition: (value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormAbstract) => boolean): FormValidator;
|
|
288
|
+
declare function RequiredIfValidator(condition: (value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormAbstract) => boolean, key?: string): FormValidator;
|
|
305
289
|
|
|
306
290
|
/**
|
|
307
291
|
* a required and true validator
|
|
308
292
|
*/
|
|
309
|
-
declare function RequiredTrueValidator(): FormValidator;
|
|
293
|
+
declare function RequiredTrueValidator(key?: string): FormValidator;
|
|
310
294
|
|
|
311
295
|
/**
|
|
312
296
|
* a required validator
|
|
313
297
|
*/
|
|
314
|
-
declare function RequiredValidator(): FormValidator;
|
|
298
|
+
declare function RequiredValidator(key?: string): FormValidator;
|
|
315
299
|
|
|
316
300
|
declare function useControl<T>(control: FormAbstract): [FormState<T>, (value: T | null) => void, () => void, () => void, FormAbstract];
|
|
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
|
-
|
|
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
|
});
|
|
@@ -864,11 +865,11 @@ function formGroup(controls = {}, validators) {
|
|
|
864
865
|
}
|
|
865
866
|
|
|
866
867
|
// src/forms/validators/email.validator.ts
|
|
867
|
-
function EmailValidator() {
|
|
868
|
+
function EmailValidator(key = "email") {
|
|
868
869
|
const regex = /^(?=.{1,254}$)(?=.{1,64}@)[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
|
869
870
|
return function(value) {
|
|
870
871
|
if (typeof value === "string") {
|
|
871
|
-
return regex.test(value) ? null : {
|
|
872
|
+
return regex.test(value) ? null : { [key]: true };
|
|
872
873
|
} else {
|
|
873
874
|
return null;
|
|
874
875
|
}
|
|
@@ -876,23 +877,23 @@ function EmailValidator() {
|
|
|
876
877
|
}
|
|
877
878
|
|
|
878
879
|
// src/forms/validators/match.validator.ts
|
|
879
|
-
function MatchValidator(getOtherValue) {
|
|
880
|
+
function MatchValidator(getOtherValue, key = "match") {
|
|
880
881
|
return function(value, rootValue, control, root) {
|
|
881
882
|
let otherValue = getOtherValue(value, rootValue, control, root);
|
|
882
883
|
otherValue = validValue(otherValue);
|
|
883
|
-
return value !== otherValue ? {
|
|
884
|
+
return value !== otherValue ? { [key]: { value, match: otherValue } } : null;
|
|
884
885
|
};
|
|
885
886
|
}
|
|
886
887
|
|
|
887
888
|
// src/forms/validators/max-length.validator.ts
|
|
888
|
-
function MaxLengthValidator(maxlength) {
|
|
889
|
+
function MaxLengthValidator(maxlength, key = "maxlength") {
|
|
889
890
|
return function(value) {
|
|
890
891
|
if (maxlength == null) {
|
|
891
892
|
return null;
|
|
892
893
|
}
|
|
893
894
|
if (typeof value === "string") {
|
|
894
895
|
const length = value ? value.length : 0;
|
|
895
|
-
return length > maxlength ? {
|
|
896
|
+
return length > maxlength ? { [key]: { requiredLength: maxlength, actualLength: length } } : null;
|
|
896
897
|
} else {
|
|
897
898
|
return null;
|
|
898
899
|
}
|
|
@@ -900,25 +901,25 @@ function MaxLengthValidator(maxlength) {
|
|
|
900
901
|
}
|
|
901
902
|
|
|
902
903
|
// src/forms/validators/max.validator.ts
|
|
903
|
-
function MaxValidator(max) {
|
|
904
|
+
function MaxValidator(max, key = "max") {
|
|
904
905
|
return function(value) {
|
|
905
906
|
value = typeof value === "string" ? parseFloat(value) : typeof value === "number" ? value : null;
|
|
906
907
|
if (value == null || max == null) {
|
|
907
908
|
return null;
|
|
908
909
|
}
|
|
909
|
-
return !isNaN(value) && value > max ? {
|
|
910
|
+
return !isNaN(value) && value > max ? { [key]: { max, actual: value } } : null;
|
|
910
911
|
};
|
|
911
912
|
}
|
|
912
913
|
|
|
913
914
|
// src/forms/validators/min-length.validator.ts
|
|
914
|
-
function MinLengthValidator(minlength) {
|
|
915
|
+
function MinLengthValidator(minlength, key = "minlength") {
|
|
915
916
|
return function(value) {
|
|
916
917
|
if (minlength == null) {
|
|
917
918
|
return null;
|
|
918
919
|
}
|
|
919
920
|
if (typeof value === "string") {
|
|
920
921
|
const length = value ? value.length : 0;
|
|
921
|
-
return length < minlength ? {
|
|
922
|
+
return length < minlength ? { [key]: { requiredLength: minlength, actualLength: length } } : null;
|
|
922
923
|
} else {
|
|
923
924
|
return null;
|
|
924
925
|
}
|
|
@@ -926,13 +927,13 @@ function MinLengthValidator(minlength) {
|
|
|
926
927
|
}
|
|
927
928
|
|
|
928
929
|
// src/forms/validators/min.validator.ts
|
|
929
|
-
function MinValidator(min) {
|
|
930
|
+
function MinValidator(min, key = "min") {
|
|
930
931
|
return function(value) {
|
|
931
932
|
value = typeof value === "string" ? parseFloat(value) : typeof value === "number" ? value : null;
|
|
932
933
|
if (value == null || min == null) {
|
|
933
934
|
return null;
|
|
934
935
|
}
|
|
935
|
-
return !isNaN(value) && value < min ? {
|
|
936
|
+
return !isNaN(value) && value < min ? { [key]: { min, actual: value } } : null;
|
|
936
937
|
};
|
|
937
938
|
}
|
|
938
939
|
|
|
@@ -944,14 +945,14 @@ function NullValidator() {
|
|
|
944
945
|
}
|
|
945
946
|
|
|
946
947
|
// src/forms/validators/pattern.validator.ts
|
|
947
|
-
function PatternValidator(pattern) {
|
|
948
|
+
function PatternValidator(pattern, key = "pattern") {
|
|
948
949
|
return function(value) {
|
|
949
950
|
if (pattern == null) {
|
|
950
951
|
return null;
|
|
951
952
|
}
|
|
952
953
|
if (typeof value === "string") {
|
|
953
954
|
const regex = patternToRegEx(pattern);
|
|
954
|
-
return regex.test(value) ? null : {
|
|
955
|
+
return regex.test(value) ? null : { [key]: { requiredPattern: regex.toString(), actualValue: value } };
|
|
955
956
|
} else {
|
|
956
957
|
return null;
|
|
957
958
|
}
|
|
@@ -971,13 +972,13 @@ function patternToRegEx(pattern) {
|
|
|
971
972
|
|
|
972
973
|
// src/forms/validators/required-if.validator.ts
|
|
973
974
|
var import_bom_core3 = require("@websolutespa/bom-core");
|
|
974
|
-
function RequiredIfValidator(condition) {
|
|
975
|
+
function RequiredIfValidator(condition, key = "required") {
|
|
975
976
|
return function(value, rootValue, control, root) {
|
|
976
977
|
if (Boolean(condition(value, rootValue, control, root)) === true) {
|
|
977
978
|
if ((0, import_bom_core3.isArray)(value) || typeof value === "string") {
|
|
978
|
-
return value.length === 0 ? {
|
|
979
|
+
return value.length === 0 ? { [key]: true } : null;
|
|
979
980
|
} else {
|
|
980
|
-
return value == null ? {
|
|
981
|
+
return value == null ? { [key]: true } : null;
|
|
981
982
|
}
|
|
982
983
|
} else {
|
|
983
984
|
return null;
|
|
@@ -986,20 +987,20 @@ function RequiredIfValidator(condition) {
|
|
|
986
987
|
}
|
|
987
988
|
|
|
988
989
|
// src/forms/validators/required-true.validator.ts
|
|
989
|
-
function RequiredTrueValidator() {
|
|
990
|
+
function RequiredTrueValidator(key = "required") {
|
|
990
991
|
return function(value) {
|
|
991
|
-
return value === true ? null : {
|
|
992
|
+
return value === true ? null : { [key]: true };
|
|
992
993
|
};
|
|
993
994
|
}
|
|
994
995
|
|
|
995
996
|
// src/forms/validators/required.validator.ts
|
|
996
997
|
var import_bom_core4 = require("@websolutespa/bom-core");
|
|
997
|
-
function RequiredValidator() {
|
|
998
|
+
function RequiredValidator(key = "required") {
|
|
998
999
|
return function(value) {
|
|
999
1000
|
if ((0, import_bom_core4.isArray)(value) || typeof value === "string") {
|
|
1000
|
-
return value.length === 0 ? {
|
|
1001
|
+
return value.length === 0 ? { [key]: true } : null;
|
|
1001
1002
|
} else {
|
|
1002
|
-
return value == null ? {
|
|
1003
|
+
return value == null ? { [key]: true } : null;
|
|
1003
1004
|
}
|
|
1004
1005
|
};
|
|
1005
1006
|
}
|
|
@@ -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
|
@@ -816,11 +816,11 @@ function formGroup(controls = {}, validators) {
|
|
|
816
816
|
}
|
|
817
817
|
|
|
818
818
|
// src/forms/validators/email.validator.ts
|
|
819
|
-
function EmailValidator() {
|
|
819
|
+
function EmailValidator(key = "email") {
|
|
820
820
|
const regex = /^(?=.{1,254}$)(?=.{1,64}@)[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
|
821
821
|
return function(value) {
|
|
822
822
|
if (typeof value === "string") {
|
|
823
|
-
return regex.test(value) ? null : {
|
|
823
|
+
return regex.test(value) ? null : { [key]: true };
|
|
824
824
|
} else {
|
|
825
825
|
return null;
|
|
826
826
|
}
|
|
@@ -828,23 +828,23 @@ function EmailValidator() {
|
|
|
828
828
|
}
|
|
829
829
|
|
|
830
830
|
// src/forms/validators/match.validator.ts
|
|
831
|
-
function MatchValidator(getOtherValue) {
|
|
831
|
+
function MatchValidator(getOtherValue, key = "match") {
|
|
832
832
|
return function(value, rootValue, control, root) {
|
|
833
833
|
let otherValue = getOtherValue(value, rootValue, control, root);
|
|
834
834
|
otherValue = validValue(otherValue);
|
|
835
|
-
return value !== otherValue ? {
|
|
835
|
+
return value !== otherValue ? { [key]: { value, match: otherValue } } : null;
|
|
836
836
|
};
|
|
837
837
|
}
|
|
838
838
|
|
|
839
839
|
// src/forms/validators/max-length.validator.ts
|
|
840
|
-
function MaxLengthValidator(maxlength) {
|
|
840
|
+
function MaxLengthValidator(maxlength, key = "maxlength") {
|
|
841
841
|
return function(value) {
|
|
842
842
|
if (maxlength == null) {
|
|
843
843
|
return null;
|
|
844
844
|
}
|
|
845
845
|
if (typeof value === "string") {
|
|
846
846
|
const length = value ? value.length : 0;
|
|
847
|
-
return length > maxlength ? {
|
|
847
|
+
return length > maxlength ? { [key]: { requiredLength: maxlength, actualLength: length } } : null;
|
|
848
848
|
} else {
|
|
849
849
|
return null;
|
|
850
850
|
}
|
|
@@ -852,25 +852,25 @@ function MaxLengthValidator(maxlength) {
|
|
|
852
852
|
}
|
|
853
853
|
|
|
854
854
|
// src/forms/validators/max.validator.ts
|
|
855
|
-
function MaxValidator(max) {
|
|
855
|
+
function MaxValidator(max, key = "max") {
|
|
856
856
|
return function(value) {
|
|
857
857
|
value = typeof value === "string" ? parseFloat(value) : typeof value === "number" ? value : null;
|
|
858
858
|
if (value == null || max == null) {
|
|
859
859
|
return null;
|
|
860
860
|
}
|
|
861
|
-
return !isNaN(value) && value > max ? {
|
|
861
|
+
return !isNaN(value) && value > max ? { [key]: { max, actual: value } } : null;
|
|
862
862
|
};
|
|
863
863
|
}
|
|
864
864
|
|
|
865
865
|
// src/forms/validators/min-length.validator.ts
|
|
866
|
-
function MinLengthValidator(minlength) {
|
|
866
|
+
function MinLengthValidator(minlength, key = "minlength") {
|
|
867
867
|
return function(value) {
|
|
868
868
|
if (minlength == null) {
|
|
869
869
|
return null;
|
|
870
870
|
}
|
|
871
871
|
if (typeof value === "string") {
|
|
872
872
|
const length = value ? value.length : 0;
|
|
873
|
-
return length < minlength ? {
|
|
873
|
+
return length < minlength ? { [key]: { requiredLength: minlength, actualLength: length } } : null;
|
|
874
874
|
} else {
|
|
875
875
|
return null;
|
|
876
876
|
}
|
|
@@ -878,13 +878,13 @@ function MinLengthValidator(minlength) {
|
|
|
878
878
|
}
|
|
879
879
|
|
|
880
880
|
// src/forms/validators/min.validator.ts
|
|
881
|
-
function MinValidator(min) {
|
|
881
|
+
function MinValidator(min, key = "min") {
|
|
882
882
|
return function(value) {
|
|
883
883
|
value = typeof value === "string" ? parseFloat(value) : typeof value === "number" ? value : null;
|
|
884
884
|
if (value == null || min == null) {
|
|
885
885
|
return null;
|
|
886
886
|
}
|
|
887
|
-
return !isNaN(value) && value < min ? {
|
|
887
|
+
return !isNaN(value) && value < min ? { [key]: { min, actual: value } } : null;
|
|
888
888
|
};
|
|
889
889
|
}
|
|
890
890
|
|
|
@@ -896,14 +896,14 @@ function NullValidator() {
|
|
|
896
896
|
}
|
|
897
897
|
|
|
898
898
|
// src/forms/validators/pattern.validator.ts
|
|
899
|
-
function PatternValidator(pattern) {
|
|
899
|
+
function PatternValidator(pattern, key = "pattern") {
|
|
900
900
|
return function(value) {
|
|
901
901
|
if (pattern == null) {
|
|
902
902
|
return null;
|
|
903
903
|
}
|
|
904
904
|
if (typeof value === "string") {
|
|
905
905
|
const regex = patternToRegEx(pattern);
|
|
906
|
-
return regex.test(value) ? null : {
|
|
906
|
+
return regex.test(value) ? null : { [key]: { requiredPattern: regex.toString(), actualValue: value } };
|
|
907
907
|
} else {
|
|
908
908
|
return null;
|
|
909
909
|
}
|
|
@@ -923,13 +923,13 @@ function patternToRegEx(pattern) {
|
|
|
923
923
|
|
|
924
924
|
// src/forms/validators/required-if.validator.ts
|
|
925
925
|
import { isArray } from "@websolutespa/bom-core";
|
|
926
|
-
function RequiredIfValidator(condition) {
|
|
926
|
+
function RequiredIfValidator(condition, key = "required") {
|
|
927
927
|
return function(value, rootValue, control, root) {
|
|
928
928
|
if (Boolean(condition(value, rootValue, control, root)) === true) {
|
|
929
929
|
if (isArray(value) || typeof value === "string") {
|
|
930
|
-
return value.length === 0 ? {
|
|
930
|
+
return value.length === 0 ? { [key]: true } : null;
|
|
931
931
|
} else {
|
|
932
|
-
return value == null ? {
|
|
932
|
+
return value == null ? { [key]: true } : null;
|
|
933
933
|
}
|
|
934
934
|
} else {
|
|
935
935
|
return null;
|
|
@@ -938,20 +938,20 @@ function RequiredIfValidator(condition) {
|
|
|
938
938
|
}
|
|
939
939
|
|
|
940
940
|
// src/forms/validators/required-true.validator.ts
|
|
941
|
-
function RequiredTrueValidator() {
|
|
941
|
+
function RequiredTrueValidator(key = "required") {
|
|
942
942
|
return function(value) {
|
|
943
|
-
return value === true ? null : {
|
|
943
|
+
return value === true ? null : { [key]: true };
|
|
944
944
|
};
|
|
945
945
|
}
|
|
946
946
|
|
|
947
947
|
// src/forms/validators/required.validator.ts
|
|
948
948
|
import { isArray as isArray2 } from "@websolutespa/bom-core";
|
|
949
|
-
function RequiredValidator() {
|
|
949
|
+
function RequiredValidator(key = "required") {
|
|
950
950
|
return function(value) {
|
|
951
951
|
if (isArray2(value) || typeof value === "string") {
|
|
952
|
-
return value.length === 0 ? {
|
|
952
|
+
return value.length === 0 ? { [key]: true } : null;
|
|
953
953
|
} else {
|
|
954
|
-
return value == null ? {
|
|
954
|
+
return value == null ? { [key]: true } : null;
|
|
955
955
|
}
|
|
956
956
|
};
|
|
957
957
|
}
|
|
@@ -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
|
@@ -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<
|
|
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 |
|
|
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():
|
|
287
|
-
return this.reduce_((result:
|
|
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:
|
|
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_:
|
|
10
|
+
value_: T | null;
|
|
11
11
|
validators_: FormValidator[];
|
|
12
12
|
state_: FormFlags;
|
|
13
13
|
name?: string | number;
|
package/src/forms/form-array.ts
CHANGED
|
@@ -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
|
|
5
|
+
export class FormArray<T extends FormValue[] = FormValue[]> extends FormAbstractCollection<T, FormArrayControls> {
|
|
6
6
|
|
|
7
|
-
constructor(controls:
|
|
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():
|
|
22
|
-
return this.reduce_((result:
|
|
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:
|
|
76
|
+
export function formArray(controls: FormArrayControls = [], validators?: FormValidator | FormValidator[]) {
|
|
77
77
|
return new FormArray(controls, validators);
|
|
78
78
|
}
|
package/src/forms/form-group.ts
CHANGED
|
@@ -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
|
|
6
|
-
constructor(controls:
|
|
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:
|
|
12
|
+
export function formGroup(controls: FormGroupControls = {}, validators?: FormValidator | FormValidator[]) {
|
|
14
13
|
return new FormGroup(controls, validators);
|
|
15
14
|
}
|
package/src/forms/types.ts
CHANGED
|
@@ -34,8 +34,10 @@ export type ValidationError = {
|
|
|
34
34
|
[key: string]: any
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
-
export type
|
|
38
|
-
export type
|
|
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 =
|
|
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 =
|
|
91
|
+
export type IFormBuilderGroupSchema = Record<string, IFormBuilderControlSchema>;
|
|
90
92
|
export type IFormBuilderArraySchema = IFormBuilderControlSchema[];
|
|
91
|
-
export type IFormBuilderGroupValues =
|
|
93
|
+
export type IFormBuilderGroupValues = Record<string, FormGroup | FormArray | FormControl>;
|
|
92
94
|
export type IFormBuilderSchema = IFormBuilderGroupSchema | IFormBuilderArraySchema;
|
|
@@ -3,11 +3,11 @@ import { FormValidator } from '../types';
|
|
|
3
3
|
/**
|
|
4
4
|
* an email pattern validator
|
|
5
5
|
*/
|
|
6
|
-
export function EmailValidator(): FormValidator {
|
|
6
|
+
export function EmailValidator(key: string = 'email'): FormValidator {
|
|
7
7
|
const regex = /^(?=.{1,254}$)(?=.{1,64}@)[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
|
8
8
|
return function (value) {
|
|
9
9
|
if (typeof value === 'string') {
|
|
10
|
-
return regex.test(value) ? null : {
|
|
10
|
+
return regex.test(value) ? null : { [key]: true };
|
|
11
11
|
} else {
|
|
12
12
|
return null;
|
|
13
13
|
}
|
|
@@ -5,10 +5,13 @@ import { validValue } from '../utils';
|
|
|
5
5
|
/**
|
|
6
6
|
* an equality match validation on another field
|
|
7
7
|
*/
|
|
8
|
-
export function MatchValidator(
|
|
8
|
+
export function MatchValidator(
|
|
9
|
+
getOtherValue: (value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormAbstract) => any,
|
|
10
|
+
key: string = 'match'
|
|
11
|
+
): FormValidator {
|
|
9
12
|
return function (value, rootValue, control, root) {
|
|
10
13
|
let otherValue = getOtherValue(value, rootValue, control, root);
|
|
11
14
|
otherValue = validValue(otherValue);
|
|
12
|
-
return value !== otherValue ? {
|
|
15
|
+
return value !== otherValue ? { [key]: { value: value, match: otherValue } } : null;
|
|
13
16
|
};
|
|
14
17
|
}
|
|
@@ -3,14 +3,14 @@ import { FormValidator } from '../types';
|
|
|
3
3
|
/**
|
|
4
4
|
* a max string length validator
|
|
5
5
|
*/
|
|
6
|
-
export function MaxLengthValidator(maxlength: number): FormValidator {
|
|
6
|
+
export function MaxLengthValidator(maxlength: number, key: string = 'maxlength'): FormValidator {
|
|
7
7
|
return function (value) {
|
|
8
8
|
if (maxlength == null) {
|
|
9
9
|
return null;
|
|
10
10
|
}
|
|
11
11
|
if (typeof value === 'string') {
|
|
12
12
|
const length = value ? value.length : 0;
|
|
13
|
-
return length > maxlength ? {
|
|
13
|
+
return length > maxlength ? { [key]: { requiredLength: maxlength, actualLength: length } } : null;
|
|
14
14
|
} else {
|
|
15
15
|
return null;
|
|
16
16
|
}
|
|
@@ -3,12 +3,12 @@ import { FormValidator } from '../types';
|
|
|
3
3
|
/**
|
|
4
4
|
* a max number value validator
|
|
5
5
|
*/
|
|
6
|
-
export function MaxValidator(max: number): FormValidator {
|
|
6
|
+
export function MaxValidator(max: number, key: string = 'max'): FormValidator {
|
|
7
7
|
return function (value) {
|
|
8
8
|
value = typeof value === 'string' ? parseFloat(value) : typeof value === 'number' ? value : null;
|
|
9
9
|
if (value == null || max == null) { // loose
|
|
10
10
|
return null;
|
|
11
11
|
}
|
|
12
|
-
return !isNaN(value) && value > max ? {
|
|
12
|
+
return !isNaN(value) && value > max ? { [key]: { max: max, actual: value } } : null;
|
|
13
13
|
};
|
|
14
14
|
}
|
|
@@ -3,14 +3,14 @@ import { FormValidator } from '../types';
|
|
|
3
3
|
/**
|
|
4
4
|
* a min string length validator
|
|
5
5
|
*/
|
|
6
|
-
export function MinLengthValidator(minlength: number): FormValidator {
|
|
6
|
+
export function MinLengthValidator(minlength: number, key: string = 'minlength'): FormValidator {
|
|
7
7
|
return function (value) {
|
|
8
8
|
if (minlength == null) {
|
|
9
9
|
return null;
|
|
10
10
|
}
|
|
11
11
|
if (typeof value === 'string') {
|
|
12
12
|
const length = value ? value.length : 0;
|
|
13
|
-
return length < minlength ? {
|
|
13
|
+
return length < minlength ? { [key]: { requiredLength: minlength, actualLength: length } } : null;
|
|
14
14
|
} else {
|
|
15
15
|
return null;
|
|
16
16
|
}
|
|
@@ -3,12 +3,12 @@ import { FormValidator } from '../types';
|
|
|
3
3
|
/**
|
|
4
4
|
* a min number value validator
|
|
5
5
|
*/
|
|
6
|
-
export function MinValidator(min: number): FormValidator {
|
|
6
|
+
export function MinValidator(min: number, key: string = 'min'): FormValidator {
|
|
7
7
|
return function (value) {
|
|
8
8
|
value = typeof value === 'string' ? parseFloat(value) : typeof value === 'number' ? value : null;
|
|
9
9
|
if (value == null || min == null) { // loose
|
|
10
10
|
return null;
|
|
11
11
|
}
|
|
12
|
-
return !isNaN(value) && value < min ? {
|
|
12
|
+
return !isNaN(value) && value < min ? { [key]: { min: min, actual: value } } : null;
|
|
13
13
|
};
|
|
14
14
|
}
|
|
@@ -3,14 +3,14 @@ import { FormValidator } from '../types';
|
|
|
3
3
|
/**
|
|
4
4
|
* a regex pattern validator
|
|
5
5
|
*/
|
|
6
|
-
export function PatternValidator(pattern: string | RegExp): FormValidator {
|
|
6
|
+
export function PatternValidator(pattern: string | RegExp, key: string = 'pattern'): FormValidator {
|
|
7
7
|
return function (value) {
|
|
8
8
|
if (pattern == null) { // loose
|
|
9
9
|
return null;
|
|
10
10
|
}
|
|
11
11
|
if (typeof value === 'string') {
|
|
12
12
|
const regex = patternToRegEx(pattern);
|
|
13
|
-
return regex.test(value) ? null : {
|
|
13
|
+
return regex.test(value) ? null : { [key]: { requiredPattern: regex.toString(), actualValue: value } };
|
|
14
14
|
} else {
|
|
15
15
|
return null;
|
|
16
16
|
}
|
|
@@ -5,14 +5,14 @@ import { FormValidator, FormValue } from '../types';
|
|
|
5
5
|
/**
|
|
6
6
|
* a required dependant on another field
|
|
7
7
|
*/
|
|
8
|
-
export function RequiredIfValidator(condition: (value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormAbstract) => boolean): FormValidator {
|
|
8
|
+
export function RequiredIfValidator(condition: (value: FormValue, rootValue: FormValue, control?: FormAbstract, root?: FormAbstract) => boolean, key: string = 'required'): FormValidator {
|
|
9
9
|
return function (value, rootValue, control, root) {
|
|
10
10
|
// console.log('RequiredIfValidator', value, Boolean(condition(value, rootValue, control, root)));
|
|
11
11
|
if (Boolean(condition(value, rootValue, control, root)) === true) {
|
|
12
12
|
if (isArray(value) || typeof value === 'string') {
|
|
13
|
-
return (value.length === 0) ? {
|
|
13
|
+
return (value.length === 0) ? { [key]: true } : null;
|
|
14
14
|
} else {
|
|
15
|
-
return value == null ? {
|
|
15
|
+
return value == null ? { [key]: true } : null;
|
|
16
16
|
}
|
|
17
17
|
} else {
|
|
18
18
|
return null;
|
|
@@ -3,9 +3,9 @@ import { FormValidator } from '../types';
|
|
|
3
3
|
/**
|
|
4
4
|
* a required and true validator
|
|
5
5
|
*/
|
|
6
|
-
export function RequiredTrueValidator(): FormValidator {
|
|
6
|
+
export function RequiredTrueValidator(key: string = 'required'): FormValidator {
|
|
7
7
|
return function (value) {
|
|
8
8
|
// console.log('RequiredTrueValidator', value, value === true ? null : { required: true });
|
|
9
|
-
return value === true ? null : {
|
|
9
|
+
return value === true ? null : { [key]: true };
|
|
10
10
|
};
|
|
11
11
|
}
|
|
@@ -4,13 +4,13 @@ import { FormValidator } from '../types';
|
|
|
4
4
|
/**
|
|
5
5
|
* a required validator
|
|
6
6
|
*/
|
|
7
|
-
export function RequiredValidator(): FormValidator {
|
|
7
|
+
export function RequiredValidator(key: string = 'required'): FormValidator {
|
|
8
8
|
return function (value) {
|
|
9
9
|
// console.log('RequiredValidator', value, (value == null || value.length === 0) ? { required: true } : null);
|
|
10
10
|
if (isArray(value) || typeof value === 'string') {
|
|
11
|
-
return (value.length === 0) ? {
|
|
11
|
+
return (value.length === 0) ? { [key]: true } : null;
|
|
12
12
|
} else {
|
|
13
|
-
return value == null ? {
|
|
13
|
+
return value == null ? { [key]: true } : null;
|
|
14
14
|
}
|
|
15
15
|
};
|
|
16
16
|
// return (value == null || value.length === 0) ? 'required' : null;
|
package/src/hooks/index.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
+
}
|