@digigov/form 0.10.8 → 0.10.10
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 +8 -1
- package/Form.stories.playwright.json +0 -72
- package/FormBuilder/FormBuilder.mdx +1 -1
- package/MultiplicityField/__stories__/PreviewDisplay.js +6 -6
- package/Questions/__stories__/Default.js +2 -2
- package/Questions/index.mdx +1 -1
- package/es/Form.stories.playwright.json +0 -72
- package/es/FormBuilder/FormBuilder.mdx +1 -1
- package/es/MultiplicityField/__stories__/PreviewDisplay.js +6 -6
- package/es/Questions/__stories__/Default.js +1 -1
- package/es/Questions/index.mdx +1 -1
- package/esm/Form.stories.playwright.json +0 -72
- package/esm/FormBuilder/FormBuilder.mdx +1 -1
- package/esm/MultiplicityField/__stories__/PreviewDisplay.js +6 -6
- package/esm/Questions/__stories__/Default.js +1 -1
- package/esm/Questions/index.mdx +1 -1
- package/esm/index.js +1 -1
- package/package.json +4 -4
- package/src/Field/FieldBase.tsx +99 -0
- package/src/Field/FieldBaseContainer.tsx +57 -0
- package/src/Field/FieldConditional.tsx +75 -0
- package/src/Field/index.mdx +6 -0
- package/src/Field/index.tsx +92 -0
- package/src/Field/types.tsx +102 -0
- package/src/Field/utils.ts +164 -0
- package/src/FieldArray/FieldArray.stories.js +8 -0
- package/src/FieldArray/FieldArray.stories.playwright.json +353 -0
- package/src/FieldArray/__stories__/Default.tsx +95 -0
- package/src/FieldArray/__stories__/WithExactLength.tsx +95 -0
- package/src/FieldArray/index.tsx +83 -0
- package/src/FieldObject/index.tsx +92 -0
- package/src/Fieldset/FieldsetWithContext.tsx +41 -0
- package/src/Fieldset/index.tsx +40 -0
- package/src/Fieldset/types.tsx +6 -0
- package/src/Form.stories.js +5 -0
- package/src/Form.stories.playwright.json +71 -0
- package/src/FormBuilder/FormBuilder.mdx +271 -0
- package/src/FormBuilder/FormBuilder.stories.js +7 -0
- package/src/FormBuilder/FormBuilder.stories.playwright.json +52 -0
- package/src/FormBuilder/FormBuilder.tsx +165 -0
- package/src/FormBuilder/__stories__/Default.tsx +23 -0
- package/src/FormBuilder/index.tsx +3 -0
- package/src/FormContext.tsx +8 -0
- package/src/MultiplicityField/MultiplicityField.mdx +580 -0
- package/src/MultiplicityField/MultiplicityField.stories.js +12 -0
- package/src/MultiplicityField/MultiplicityField.stories.playwright.json +1370 -0
- package/src/MultiplicityField/__stories__/Default.tsx +100 -0
- package/src/MultiplicityField/__stories__/PreviewDisplay.tsx +160 -0
- package/src/MultiplicityField/__stories__/WithExactLength.tsx +99 -0
- package/src/MultiplicityField/__stories__/WithMaxLength.tsx +102 -0
- package/src/MultiplicityField/__stories__/WithMinAndMaxLength.tsx +103 -0
- package/src/MultiplicityField/__stories__/WithMinLength.tsx +102 -0
- package/src/MultiplicityField/add-objects.tsx +186 -0
- package/src/MultiplicityField/index.tsx +166 -0
- package/src/Questions/Questions.stories.js +7 -0
- package/src/Questions/Questions.tsx +74 -0
- package/src/Questions/QuestionsContext.tsx +9 -0
- package/src/Questions/Step/ReviewStep.tsx +63 -0
- package/src/Questions/Step/Step.tsx +67 -0
- package/src/Questions/Step/StepArrayReview.tsx +68 -0
- package/src/Questions/Step/StepContext.tsx +21 -0
- package/src/Questions/Step/StepDescription.tsx +33 -0
- package/src/Questions/Step/StepForm.tsx +60 -0
- package/src/Questions/Step/StepQuote.tsx +8 -0
- package/src/Questions/Step/StepTitle.tsx +60 -0
- package/src/Questions/Step/getAddMoreFields.tsx +28 -0
- package/src/Questions/Step/index.ts +13 -0
- package/src/Questions/Step/types.tsx +32 -0
- package/src/Questions/__snapshots__/index.spec.tsx.snap +887 -0
- package/src/Questions/__stories__/Default.tsx +130 -0
- package/src/Questions/getNextStep.tsx +24 -0
- package/src/Questions/index.mdx +418 -0
- package/src/Questions/index.spec.tsx +72 -0
- package/src/Questions/index.tsx +5 -0
- package/src/Questions/types.tsx +25 -0
- package/src/__stories__/AutoCompleteField.tsx +45 -0
- package/src/__stories__/IntField.tsx +38 -0
- package/src/create-simple-form.mdx +518 -0
- package/src/index.mdx +44 -0
- package/src/index.ts +3 -0
- package/src/inputs/AutoComplete/index.tsx +85 -0
- package/src/inputs/Checkboxes/Checkboxes.stories.js +7 -0
- package/src/inputs/Checkboxes/Checkboxes.stories.playwright.json +69 -0
- package/src/inputs/Checkboxes/__stories__/Default.tsx +39 -0
- package/src/inputs/Checkboxes/index.mdx +0 -0
- package/src/inputs/Checkboxes/index.tsx +77 -0
- package/src/inputs/DateInput/DateInput.stories.js +7 -0
- package/src/inputs/DateInput/DateInput.stories.playwright.json +72 -0
- package/src/inputs/DateInput/__stories__/Default.tsx +41 -0
- package/src/inputs/DateInput/index.tsx +130 -0
- package/src/inputs/FileInput/FileInput.stories.js +7 -0
- package/src/inputs/FileInput/FileInput.stories.playwright.json +75 -0
- package/src/inputs/FileInput/__stories__/Default.tsx +23 -0
- package/src/inputs/FileInput/index.tsx +76 -0
- package/src/inputs/Input/Input.stories.js +14 -0
- package/src/inputs/Input/Input.stories.playwright.json +376 -0
- package/src/inputs/Input/__stories__/AFM.tsx +24 -0
- package/src/inputs/Input/__stories__/Boolean.tsx +26 -0
- package/src/inputs/Input/__stories__/Default.tsx +25 -0
- package/src/inputs/Input/__stories__/IBAN.tsx +26 -0
- package/src/inputs/Input/__stories__/Integer.tsx +25 -0
- package/src/inputs/Input/__stories__/MobilePhone.tsx +24 -0
- package/src/inputs/Input/__stories__/PhoneNumber.tsx +24 -0
- package/src/inputs/Input/__stories__/PostalCode.tsx +25 -0
- package/src/inputs/Input/index.mdx +8 -0
- package/src/inputs/Input/index.tsx +62 -0
- package/src/inputs/Label/Label.stories.js +7 -0
- package/src/inputs/Label/Label.stories.playwright.json +40 -0
- package/src/inputs/Label/__stories__/Default.tsx +28 -0
- package/src/inputs/Label/index.mdx +0 -0
- package/src/inputs/Label/index.tsx +44 -0
- package/src/inputs/Radio/Radio.stories.js +7 -0
- package/src/inputs/Radio/Radio.stories.playwright.json +57 -0
- package/src/inputs/Radio/__stories__/Default.tsx +42 -0
- package/src/inputs/Radio/index.mdx +0 -0
- package/src/inputs/Radio/index.tsx +57 -0
- package/src/inputs/Select/Select.stories.js +7 -0
- package/src/inputs/Select/Select.stories.playwright.json +22 -0
- package/src/inputs/Select/__stories__/Default.tsx +47 -0
- package/src/inputs/Select/index.tsx +37 -0
- package/src/inputs/index.ts +7 -0
- package/src/installation.mdx +72 -0
- package/src/internal.ts +34 -0
- package/src/registry.js +134 -0
- package/src/types.tsx +110 -0
- package/src/utils.ts +78 -0
- package/src/validators/index.ts +203 -0
- package/src/validators/types.ts +2 -0
- package/src/validators/utils/afm.ts +37 -0
- package/src/validators/utils/file.ts +25 -0
- package/src/validators/utils/iban.ts +119 -0
- package/src/validators/utils/index.ts +94 -0
- package/src/validators/utils/int.ts +22 -0
- package/src/validators/utils/number.ts +18 -0
- package/src/validators/utils/phone.ts +120 -0
- package/src/validators/utils/postal_code.ts +33 -0
- package/src/validators/utils/uuid4.ts +21 -0
- package/src/validators/validators.spec.ts +122 -0
package/src/registry.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
|
|
2
|
+
import * as _digigov_form_Field_FieldBase from '@digigov/form/Field/FieldBase';
|
|
3
|
+
import * as _digigov_form_Field_FieldBaseContainer from '@digigov/form/Field/FieldBaseContainer';
|
|
4
|
+
import * as _digigov_form_Field_FieldConditional from '@digigov/form/Field/FieldConditional';
|
|
5
|
+
import * as _digigov_form_Field from '@digigov/form/Field';
|
|
6
|
+
import * as _digigov_form_Field_types from '@digigov/form/Field/types';
|
|
7
|
+
import * as _digigov_form_Field_utils from '@digigov/form/Field/utils';
|
|
8
|
+
import * as _digigov_form_FieldArray from '@digigov/form/FieldArray';
|
|
9
|
+
import * as _digigov_form_FieldObject from '@digigov/form/FieldObject';
|
|
10
|
+
import * as _digigov_form_Fieldset_FieldsetWithContext from '@digigov/form/Fieldset/FieldsetWithContext';
|
|
11
|
+
import * as _digigov_form_Fieldset from '@digigov/form/Fieldset';
|
|
12
|
+
import * as _digigov_form_Fieldset_types from '@digigov/form/Fieldset/types';
|
|
13
|
+
import * as _digigov_form_FormBuilder_FormBuilder from '@digigov/form/FormBuilder/FormBuilder';
|
|
14
|
+
import * as _digigov_form_FormBuilder from '@digigov/form/FormBuilder';
|
|
15
|
+
import * as _digigov_form_FormContext from '@digigov/form/FormContext';
|
|
16
|
+
import * as _digigov_form from '@digigov/form';
|
|
17
|
+
import * as _digigov_form_inputs_AutoComplete from '@digigov/form/inputs/AutoComplete';
|
|
18
|
+
import * as _digigov_form_inputs_Checkboxes from '@digigov/form/inputs/Checkboxes';
|
|
19
|
+
import * as _digigov_form_inputs_DateInput from '@digigov/form/inputs/DateInput';
|
|
20
|
+
import * as _digigov_form_inputs_FileInput from '@digigov/form/inputs/FileInput';
|
|
21
|
+
import * as _digigov_form_inputs from '@digigov/form/inputs';
|
|
22
|
+
import * as _digigov_form_inputs_Input from '@digigov/form/inputs/Input';
|
|
23
|
+
import * as _digigov_form_inputs_Label from '@digigov/form/inputs/Label';
|
|
24
|
+
import * as _digigov_form_inputs_Radio from '@digigov/form/inputs/Radio';
|
|
25
|
+
import * as _digigov_form_inputs_Select from '@digigov/form/inputs/Select';
|
|
26
|
+
import * as _digigov_form_internal from '@digigov/form/internal';
|
|
27
|
+
import * as _digigov_form_MultiplicityField_add_objects from '@digigov/form/MultiplicityField/add-objects';
|
|
28
|
+
import * as _digigov_form_MultiplicityField from '@digigov/form/MultiplicityField';
|
|
29
|
+
import * as _digigov_form_Questions_getNextStep from '@digigov/form/Questions/getNextStep';
|
|
30
|
+
import * as _digigov_form_Questions from '@digigov/form/Questions';
|
|
31
|
+
import * as _digigov_form_Questions_Questions from '@digigov/form/Questions/Questions';
|
|
32
|
+
import * as _digigov_form_Questions_QuestionsContext from '@digigov/form/Questions/QuestionsContext';
|
|
33
|
+
import * as _digigov_form_Questions_Step_getAddMoreFields from '@digigov/form/Questions/Step/getAddMoreFields';
|
|
34
|
+
import * as _digigov_form_Questions_Step from '@digigov/form/Questions/Step';
|
|
35
|
+
import * as _digigov_form_Questions_Step_ReviewStep from '@digigov/form/Questions/Step/ReviewStep';
|
|
36
|
+
import * as _digigov_form_Questions_Step_Step from '@digigov/form/Questions/Step/Step';
|
|
37
|
+
import * as _digigov_form_Questions_Step_StepArrayReview from '@digigov/form/Questions/Step/StepArrayReview';
|
|
38
|
+
import * as _digigov_form_Questions_Step_StepContext from '@digigov/form/Questions/Step/StepContext';
|
|
39
|
+
import * as _digigov_form_Questions_Step_StepDescription from '@digigov/form/Questions/Step/StepDescription';
|
|
40
|
+
import * as _digigov_form_Questions_Step_StepForm from '@digigov/form/Questions/Step/StepForm';
|
|
41
|
+
import * as _digigov_form_Questions_Step_StepQuote from '@digigov/form/Questions/Step/StepQuote';
|
|
42
|
+
import * as _digigov_form_Questions_Step_StepTitle from '@digigov/form/Questions/Step/StepTitle';
|
|
43
|
+
import * as _digigov_form_Questions_Step_types from '@digigov/form/Questions/Step/types';
|
|
44
|
+
import * as _digigov_form_Questions_types from '@digigov/form/Questions/types';
|
|
45
|
+
import * as _digigov_form_types from '@digigov/form/types';
|
|
46
|
+
import * as _digigov_form_utils from '@digigov/form/utils';
|
|
47
|
+
import * as _digigov_form_validators from '@digigov/form/validators';
|
|
48
|
+
import * as _digigov_form_validators_types from '@digigov/form/validators/types';
|
|
49
|
+
import * as _digigov_form_validators_utils_afm from '@digigov/form/validators/utils/afm';
|
|
50
|
+
import * as _digigov_form_validators_utils_file from '@digigov/form/validators/utils/file';
|
|
51
|
+
import * as _digigov_form_validators_utils_iban from '@digigov/form/validators/utils/iban';
|
|
52
|
+
import * as _digigov_form_validators_utils from '@digigov/form/validators/utils';
|
|
53
|
+
import * as _digigov_form_validators_utils_int from '@digigov/form/validators/utils/int';
|
|
54
|
+
import * as _digigov_form_validators_utils_number from '@digigov/form/validators/utils/number';
|
|
55
|
+
import * as _digigov_form_validators_utils_phone from '@digigov/form/validators/utils/phone';
|
|
56
|
+
import * as _digigov_form_validators_utils_postal_code from '@digigov/form/validators/utils/postal_code';
|
|
57
|
+
import * as _digigov_form_validators_utils_uuid4 from '@digigov/form/validators/utils/uuid4'
|
|
58
|
+
function lazyImport(pkgImport) {
|
|
59
|
+
return new Proxy(
|
|
60
|
+
{},
|
|
61
|
+
{
|
|
62
|
+
get: (_target, name) => {
|
|
63
|
+
if (name === '__esModule' || name === 'default') {
|
|
64
|
+
return pkgImport.default;
|
|
65
|
+
} else if(
|
|
66
|
+
name === '*'
|
|
67
|
+
) {
|
|
68
|
+
return pkgImport;
|
|
69
|
+
} else {
|
|
70
|
+
return pkgImport[name];
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
}
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
export default {
|
|
77
|
+
'@digigov/form/Field/FieldBase': lazyImport(_digigov_form_Field_FieldBase),
|
|
78
|
+
'@digigov/form/Field/FieldBaseContainer': lazyImport(_digigov_form_Field_FieldBaseContainer),
|
|
79
|
+
'@digigov/form/Field/FieldConditional': lazyImport(_digigov_form_Field_FieldConditional),
|
|
80
|
+
'@digigov/form/Field': lazyImport(_digigov_form_Field),
|
|
81
|
+
'@digigov/form/Field/types': lazyImport(_digigov_form_Field_types),
|
|
82
|
+
'@digigov/form/Field/utils': lazyImport(_digigov_form_Field_utils),
|
|
83
|
+
'@digigov/form/FieldArray': lazyImport(_digigov_form_FieldArray),
|
|
84
|
+
'@digigov/form/FieldObject': lazyImport(_digigov_form_FieldObject),
|
|
85
|
+
'@digigov/form/Fieldset/FieldsetWithContext': lazyImport(_digigov_form_Fieldset_FieldsetWithContext),
|
|
86
|
+
'@digigov/form/Fieldset': lazyImport(_digigov_form_Fieldset),
|
|
87
|
+
'@digigov/form/Fieldset/types': lazyImport(_digigov_form_Fieldset_types),
|
|
88
|
+
'@digigov/form/FormBuilder/FormBuilder': lazyImport(_digigov_form_FormBuilder_FormBuilder),
|
|
89
|
+
'@digigov/form/FormBuilder': lazyImport(_digigov_form_FormBuilder),
|
|
90
|
+
'@digigov/form/FormContext': lazyImport(_digigov_form_FormContext),
|
|
91
|
+
'@digigov/form': lazyImport(_digigov_form),
|
|
92
|
+
'@digigov/form/inputs/AutoComplete': lazyImport(_digigov_form_inputs_AutoComplete),
|
|
93
|
+
'@digigov/form/inputs/Checkboxes': lazyImport(_digigov_form_inputs_Checkboxes),
|
|
94
|
+
'@digigov/form/inputs/DateInput': lazyImport(_digigov_form_inputs_DateInput),
|
|
95
|
+
'@digigov/form/inputs/FileInput': lazyImport(_digigov_form_inputs_FileInput),
|
|
96
|
+
'@digigov/form/inputs': lazyImport(_digigov_form_inputs),
|
|
97
|
+
'@digigov/form/inputs/Input': lazyImport(_digigov_form_inputs_Input),
|
|
98
|
+
'@digigov/form/inputs/Label': lazyImport(_digigov_form_inputs_Label),
|
|
99
|
+
'@digigov/form/inputs/Radio': lazyImport(_digigov_form_inputs_Radio),
|
|
100
|
+
'@digigov/form/inputs/Select': lazyImport(_digigov_form_inputs_Select),
|
|
101
|
+
'@digigov/form/internal': lazyImport(_digigov_form_internal),
|
|
102
|
+
'@digigov/form/MultiplicityField/add-objects': lazyImport(_digigov_form_MultiplicityField_add_objects),
|
|
103
|
+
'@digigov/form/MultiplicityField': lazyImport(_digigov_form_MultiplicityField),
|
|
104
|
+
'@digigov/form/Questions/getNextStep': lazyImport(_digigov_form_Questions_getNextStep),
|
|
105
|
+
'@digigov/form/Questions': lazyImport(_digigov_form_Questions),
|
|
106
|
+
'@digigov/form/Questions/Questions': lazyImport(_digigov_form_Questions_Questions),
|
|
107
|
+
'@digigov/form/Questions/QuestionsContext': lazyImport(_digigov_form_Questions_QuestionsContext),
|
|
108
|
+
'@digigov/form/Questions/Step/getAddMoreFields': lazyImport(_digigov_form_Questions_Step_getAddMoreFields),
|
|
109
|
+
'@digigov/form/Questions/Step': lazyImport(_digigov_form_Questions_Step),
|
|
110
|
+
'@digigov/form/Questions/Step/ReviewStep': lazyImport(_digigov_form_Questions_Step_ReviewStep),
|
|
111
|
+
'@digigov/form/Questions/Step/Step': lazyImport(_digigov_form_Questions_Step_Step),
|
|
112
|
+
'@digigov/form/Questions/Step/StepArrayReview': lazyImport(_digigov_form_Questions_Step_StepArrayReview),
|
|
113
|
+
'@digigov/form/Questions/Step/StepContext': lazyImport(_digigov_form_Questions_Step_StepContext),
|
|
114
|
+
'@digigov/form/Questions/Step/StepDescription': lazyImport(_digigov_form_Questions_Step_StepDescription),
|
|
115
|
+
'@digigov/form/Questions/Step/StepForm': lazyImport(_digigov_form_Questions_Step_StepForm),
|
|
116
|
+
'@digigov/form/Questions/Step/StepQuote': lazyImport(_digigov_form_Questions_Step_StepQuote),
|
|
117
|
+
'@digigov/form/Questions/Step/StepTitle': lazyImport(_digigov_form_Questions_Step_StepTitle),
|
|
118
|
+
'@digigov/form/Questions/Step/types': lazyImport(_digigov_form_Questions_Step_types),
|
|
119
|
+
'@digigov/form/Questions/types': lazyImport(_digigov_form_Questions_types),
|
|
120
|
+
'@digigov/form/types': lazyImport(_digigov_form_types),
|
|
121
|
+
'@digigov/form/utils': lazyImport(_digigov_form_utils),
|
|
122
|
+
'@digigov/form/validators': lazyImport(_digigov_form_validators),
|
|
123
|
+
'@digigov/form/validators/types': lazyImport(_digigov_form_validators_types),
|
|
124
|
+
'@digigov/form/validators/utils/afm': lazyImport(_digigov_form_validators_utils_afm),
|
|
125
|
+
'@digigov/form/validators/utils/file': lazyImport(_digigov_form_validators_utils_file),
|
|
126
|
+
'@digigov/form/validators/utils/iban': lazyImport(_digigov_form_validators_utils_iban),
|
|
127
|
+
'@digigov/form/validators/utils': lazyImport(_digigov_form_validators_utils),
|
|
128
|
+
'@digigov/form/validators/utils/int': lazyImport(_digigov_form_validators_utils_int),
|
|
129
|
+
'@digigov/form/validators/utils/number': lazyImport(_digigov_form_validators_utils_number),
|
|
130
|
+
'@digigov/form/validators/utils/phone': lazyImport(_digigov_form_validators_utils_phone),
|
|
131
|
+
'@digigov/form/validators/utils/postal_code': lazyImport(_digigov_form_validators_utils_postal_code),
|
|
132
|
+
'@digigov/form/validators/utils/uuid4': lazyImport(_digigov_form_validators_utils_uuid4)
|
|
133
|
+
};
|
|
134
|
+
|
package/src/types.tsx
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { UseFormReturn, UseFormProps } from 'react-hook-form';
|
|
2
|
+
import { GridProps } from '@digigov/ui/layouts/Grid';
|
|
3
|
+
import { ValidatorSchema } from '@digigov/form/validators/types';
|
|
4
|
+
import { FieldComponentRegistry } from '@digigov/form/Field/types';
|
|
5
|
+
|
|
6
|
+
export type FieldError = {
|
|
7
|
+
message: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type FieldLabelProps = {
|
|
11
|
+
primary?: string;
|
|
12
|
+
secondary?: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export interface FieldCondition {
|
|
16
|
+
is: string;
|
|
17
|
+
then?: Partial<FieldSpec>;
|
|
18
|
+
else?: Partial<FieldSpec>;
|
|
19
|
+
}
|
|
20
|
+
export interface FieldSpec {
|
|
21
|
+
key: string; // !TODO rename key to name;
|
|
22
|
+
type?:
|
|
23
|
+
| 'int'
|
|
24
|
+
| 'string'
|
|
25
|
+
| 'text'
|
|
26
|
+
| 'boolean'
|
|
27
|
+
| 'email'
|
|
28
|
+
| 'uuid4'
|
|
29
|
+
| 'choice:multiple'
|
|
30
|
+
| 'choice:single'
|
|
31
|
+
| 'mobile_phone'
|
|
32
|
+
| 'date'
|
|
33
|
+
| 'afm'
|
|
34
|
+
| 'iban'
|
|
35
|
+
| 'file'
|
|
36
|
+
| 'postal_code'
|
|
37
|
+
| 'phone_number'
|
|
38
|
+
| 'array'
|
|
39
|
+
| 'object';
|
|
40
|
+
component?: any;
|
|
41
|
+
condition?: Record<string, FieldCondition>;
|
|
42
|
+
controlled?: boolean;
|
|
43
|
+
label?: FieldLabelProps;
|
|
44
|
+
extra?: Record<string, any>;
|
|
45
|
+
editable?: boolean;
|
|
46
|
+
required?: boolean;
|
|
47
|
+
enabled?: boolean;
|
|
48
|
+
layout?: Record<
|
|
49
|
+
string,
|
|
50
|
+
| GridProps['xs']
|
|
51
|
+
| GridProps['sm']
|
|
52
|
+
| GridProps['md']
|
|
53
|
+
| GridProps['lg']
|
|
54
|
+
| GridProps['xl']
|
|
55
|
+
>;
|
|
56
|
+
validators?: ValidatorSchema[];
|
|
57
|
+
wrapper?: 'label' | 'fieldset';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface FieldsetSpec {
|
|
61
|
+
key: string;
|
|
62
|
+
fields: string[];
|
|
63
|
+
label?: FieldLabelProps;
|
|
64
|
+
body?: React.ReactNode;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export type FormData = UseFormProps['defaultValues'];
|
|
68
|
+
|
|
69
|
+
export interface FormContextProps {
|
|
70
|
+
fieldsetsMap?: Record<string, FieldsetSpec>;
|
|
71
|
+
fieldsMap: Record<string, FieldSpec>;
|
|
72
|
+
control: UseFormReturn['control'];
|
|
73
|
+
register: UseFormReturn['register'];
|
|
74
|
+
trigger: UseFormReturn['trigger'];
|
|
75
|
+
clearErrors: UseFormReturn['clearErrors'];
|
|
76
|
+
watch: UseFormReturn['watch'];
|
|
77
|
+
getFieldState: UseFormReturn['getFieldState'];
|
|
78
|
+
setValue: UseFormReturn['setValue'];
|
|
79
|
+
getValues: UseFormReturn['getValues'];
|
|
80
|
+
unregister: UseFormReturn['unregister'];
|
|
81
|
+
formState: UseFormReturn['formState'];
|
|
82
|
+
reset: UseFormReturn['reset'];
|
|
83
|
+
registerField: (field: FieldSpec) => void;
|
|
84
|
+
errors: UseFormReturn['formState']['errors'];
|
|
85
|
+
componentRegistry?: FieldComponentRegistry;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface FormBuilderProps {
|
|
89
|
+
fields?: FieldSpec[];
|
|
90
|
+
fieldsets?: FieldsetSpec[];
|
|
91
|
+
initial?: FormData;
|
|
92
|
+
onSubmit?: (data: FormData) => void | null | FieldError[];
|
|
93
|
+
mode?: UseFormProps['mode'];
|
|
94
|
+
reValidateMode?: UseFormProps['reValidateMode'];
|
|
95
|
+
criteriaMode?: UseFormProps['criteriaMode'];
|
|
96
|
+
children?: React.ReactNode;
|
|
97
|
+
shouldFocusError?: boolean;
|
|
98
|
+
auto?: boolean;
|
|
99
|
+
validatorRegistry?: Record<string, ValidatorSchema[]>;
|
|
100
|
+
componentRegistry?: FieldComponentRegistry;
|
|
101
|
+
grid?: boolean;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface FormBaseProps
|
|
105
|
+
extends Omit<FormBuilderProps, 'fields' | 'fieldsets' | 'auto'> {
|
|
106
|
+
fieldsetsMap?: Record<string, FieldsetSpec>;
|
|
107
|
+
fieldsMap: Record<string, FieldSpec>;
|
|
108
|
+
registerField: (field: FieldSpec) => void;
|
|
109
|
+
resolver: any;
|
|
110
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import * as Yup from 'yup';
|
|
2
|
+
import { validateFieldsNatively } from '@hookform/resolvers';
|
|
3
|
+
import { appendErrors, FieldError } from 'react-hook-form';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Why `path!` ? because it could be `undefined` in some case
|
|
7
|
+
* https://github.com/jquense/yup#validationerrorerrors-string--arraystring-value-any-path-string
|
|
8
|
+
*/
|
|
9
|
+
const parseErrorSchema = (
|
|
10
|
+
error: Yup.ValidationError,
|
|
11
|
+
validateAllFieldCriteria: boolean
|
|
12
|
+
) => {
|
|
13
|
+
return (error.inner || []).reduce<Record<string, FieldError>>(
|
|
14
|
+
(previous, error) => {
|
|
15
|
+
error.path = error.path?.replace(/\[([0-9]+)\]/g, '.$1');
|
|
16
|
+
if (!previous[error.path!]) {
|
|
17
|
+
previous[error.path!] = { message: error.message, type: error.type! };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (validateAllFieldCriteria) {
|
|
21
|
+
const types = previous[error.path!].types;
|
|
22
|
+
const messages = types && types[error.type!];
|
|
23
|
+
|
|
24
|
+
previous[error.path!] = appendErrors(
|
|
25
|
+
error.path!,
|
|
26
|
+
validateAllFieldCriteria,
|
|
27
|
+
previous,
|
|
28
|
+
error.type!,
|
|
29
|
+
messages
|
|
30
|
+
? ([] as string[]).concat(messages as string[], error.message)
|
|
31
|
+
: error.message
|
|
32
|
+
) as FieldError;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return previous;
|
|
36
|
+
},
|
|
37
|
+
{}
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const yupResolver = (
|
|
42
|
+
schema: any,
|
|
43
|
+
schemaOptions: any = {},
|
|
44
|
+
resolverOptions: any = {}
|
|
45
|
+
) => async (values, context, options) => {
|
|
46
|
+
try {
|
|
47
|
+
if (schemaOptions.context && process.env.NODE_ENV === 'development') {
|
|
48
|
+
// eslint-disable-next-line no-console
|
|
49
|
+
console.warn(
|
|
50
|
+
"You should not used the yup options context. Please, use the 'useForm' context object instead"
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const result = await schema[
|
|
55
|
+
resolverOptions.mode === 'sync' ? 'validateSync' : 'validate'
|
|
56
|
+
](values, Object.assign({ abortEarly: false }, schemaOptions, { context }));
|
|
57
|
+
|
|
58
|
+
options.shouldUseNativeValidation && validateFieldsNatively({}, options);
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
values: resolverOptions.rawValues ? values : result,
|
|
62
|
+
errors: {},
|
|
63
|
+
};
|
|
64
|
+
} catch (e) {
|
|
65
|
+
if (!e.inner) {
|
|
66
|
+
throw e;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const parsed = parseErrorSchema(
|
|
70
|
+
e,
|
|
71
|
+
!options.shouldUseNativeValidation && options.criteriaMode === 'all'
|
|
72
|
+
);
|
|
73
|
+
return {
|
|
74
|
+
values: {},
|
|
75
|
+
errors: parsed,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
};
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import * as yup from 'yup';
|
|
2
|
+
import { FieldSpec } from '@digigov/form/types';
|
|
3
|
+
import { ValidatorSchema } from '@digigov/form/validators/types';
|
|
4
|
+
import { MutableRefObject, useMemo } from 'react';
|
|
5
|
+
import dayjs from 'dayjs';
|
|
6
|
+
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
|
7
|
+
import {
|
|
8
|
+
getYupObjectShape,
|
|
9
|
+
AFM_VALIDATOR,
|
|
10
|
+
FILE_MAX_SIZE_VALIDATOR,
|
|
11
|
+
IBAN_VALIDATOR,
|
|
12
|
+
MOBILE_PHONE_VALIDATOR,
|
|
13
|
+
PHONE_NUMBER_VALIDATOR,
|
|
14
|
+
POSTALCODE_VALIDATOR,
|
|
15
|
+
UUID4_VALIDATOR,
|
|
16
|
+
} from '@digigov/form/validators/utils';
|
|
17
|
+
import { MixedSchema } from 'yup/lib/mixed';
|
|
18
|
+
import { RequiredArraySchema } from 'yup/lib/array';
|
|
19
|
+
import { AnyObject } from 'yup/lib/types';
|
|
20
|
+
import Lazy from 'yup/lib/Lazy';
|
|
21
|
+
import { TypeOfShape, AssertsShape } from 'yup/lib/object';
|
|
22
|
+
import { AnyObjectSchema, StringSchema } from 'yup';
|
|
23
|
+
import { NUMBER_VALIDATOR } from '@digigov/form/validators/utils/number';
|
|
24
|
+
import { INT_VALIDATOR } from '@digigov/form/validators/utils/int';
|
|
25
|
+
dayjs.extend(customParseFormat);
|
|
26
|
+
|
|
27
|
+
const VALID_DATE_FORMATS = ['DD/MM/YYYY'];
|
|
28
|
+
const DATE_CACHE = {};
|
|
29
|
+
const getDate = (v) => {
|
|
30
|
+
return DATE_CACHE[v] ? DATE_CACHE[v] : dayjs(v, VALID_DATE_FORMATS, true);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const getYUPTypeMap = (): Record<string, any> => {
|
|
34
|
+
const yupTypeMap = {
|
|
35
|
+
file: (field): MixedSchema => {
|
|
36
|
+
return yup
|
|
37
|
+
.mixed()
|
|
38
|
+
.transform((value) => {
|
|
39
|
+
if (!value.length) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
return value;
|
|
43
|
+
})
|
|
44
|
+
.nullable()
|
|
45
|
+
.test(FILE_MAX_SIZE_VALIDATOR(field));
|
|
46
|
+
},
|
|
47
|
+
string: yup.string,
|
|
48
|
+
text: yup.string,
|
|
49
|
+
boolean: yup.boolean,
|
|
50
|
+
object: (
|
|
51
|
+
field
|
|
52
|
+
):
|
|
53
|
+
| yup.ObjectSchema<any, AnyObject, TypeOfShape<any>, AssertsShape<any>>
|
|
54
|
+
| Lazy<any, unknown> => {
|
|
55
|
+
return getYupObjectShape(field.extra.fields, yupTypeMap);
|
|
56
|
+
},
|
|
57
|
+
array: (
|
|
58
|
+
field
|
|
59
|
+
):
|
|
60
|
+
| yup.ArraySchema<any, AnyObject, any[] | undefined>
|
|
61
|
+
| RequiredArraySchema<any, AnyObject, any[] | undefined> => {
|
|
62
|
+
if (typeof field.extra.of === 'object') {
|
|
63
|
+
// else if the field is an object then it is a scalar type
|
|
64
|
+
// eg. number, string etc.
|
|
65
|
+
let arrayValidator = yup
|
|
66
|
+
.array()
|
|
67
|
+
.of(yupTypeMap[field.extra.of.type](field.extra.of))
|
|
68
|
+
.required(field.required);
|
|
69
|
+
if (field.extra.length)
|
|
70
|
+
arrayValidator = arrayValidator.length(field.extra.length, {
|
|
71
|
+
key: 'form.error.array.length',
|
|
72
|
+
context: {
|
|
73
|
+
length: field.extra.length,
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
if (field.extra.min)
|
|
77
|
+
arrayValidator = arrayValidator.min(field.extra.min, {
|
|
78
|
+
key: 'form.error.array.min',
|
|
79
|
+
context: {
|
|
80
|
+
min: field.extra.min,
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
if (field.extra.max)
|
|
84
|
+
arrayValidator = arrayValidator.max(field.extra.max, {
|
|
85
|
+
key: 'form.error.array.max',
|
|
86
|
+
context: {
|
|
87
|
+
max: field.extra.max,
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
return arrayValidator;
|
|
91
|
+
} else if (typeof field.extra.of === 'string') {
|
|
92
|
+
return yup.array().of(yupTypeMap[field.extra.of]());
|
|
93
|
+
} else {
|
|
94
|
+
// in any other case it will be string
|
|
95
|
+
return yup.array().of(yup.string());
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
int: (): MixedSchema =>
|
|
99
|
+
yup
|
|
100
|
+
.mixed()
|
|
101
|
+
.transform((_, val) => (val !== '' ? Number(val) : null))
|
|
102
|
+
.test(NUMBER_VALIDATOR())
|
|
103
|
+
.test(INT_VALIDATOR()),
|
|
104
|
+
email: (): yup.StringSchema => yup.string().email('form.error.email'),
|
|
105
|
+
afm: (): yup.StringSchema => yup.string().test(AFM_VALIDATOR),
|
|
106
|
+
uuid4: (): yup.StringSchema => yup.string().test(UUID4_VALIDATOR),
|
|
107
|
+
iban: (field): yup.StringSchema => yup.string().test(IBAN_VALIDATOR(field)),
|
|
108
|
+
postal_code: (field): yup.StringSchema =>
|
|
109
|
+
yup.string().test(POSTALCODE_VALIDATOR(field)),
|
|
110
|
+
mobile_phone: (): yup.StringSchema =>
|
|
111
|
+
yup.string().test(MOBILE_PHONE_VALIDATOR),
|
|
112
|
+
phone_number: (field): yup.StringSchema =>
|
|
113
|
+
yup.string().test(PHONE_NUMBER_VALIDATOR(field)),
|
|
114
|
+
'choice:multiple': (): yup.ArraySchema<
|
|
115
|
+
yup.StringSchema<string | undefined, AnyObject, string | undefined>,
|
|
116
|
+
AnyObject,
|
|
117
|
+
(string | undefined)[] | null | undefined,
|
|
118
|
+
(string | undefined)[] | null | undefined
|
|
119
|
+
> => yup.array().of(yup.string()).nullable(),
|
|
120
|
+
'choice:single': (): StringSchema<
|
|
121
|
+
string | null | undefined,
|
|
122
|
+
AnyObject,
|
|
123
|
+
string | null | undefined
|
|
124
|
+
> => yup.string().nullable(),
|
|
125
|
+
date: (field) => {
|
|
126
|
+
let simpleDate = yup
|
|
127
|
+
.string()
|
|
128
|
+
.nullable(true)
|
|
129
|
+
.test('date', 'form.error.date.invalid', function (value) {
|
|
130
|
+
if (!value) return true;
|
|
131
|
+
const date = getDate(value);
|
|
132
|
+
return date.isValid();
|
|
133
|
+
});
|
|
134
|
+
const params = field.extra || {};
|
|
135
|
+
if (params.max) {
|
|
136
|
+
let maxDate;
|
|
137
|
+
if (params.max === 'now') {
|
|
138
|
+
const today = new Date();
|
|
139
|
+
maxDate = new Date(today);
|
|
140
|
+
} else {
|
|
141
|
+
maxDate = getDate(params.max).toDate();
|
|
142
|
+
}
|
|
143
|
+
const maxNextDate = new Date(maxDate);
|
|
144
|
+
maxNextDate.setDate(maxDate.getDate() + 1);
|
|
145
|
+
simpleDate = simpleDate.test({
|
|
146
|
+
name: 'earlier-than',
|
|
147
|
+
message: {
|
|
148
|
+
key: 'form.error.date.earlier_than',
|
|
149
|
+
context: {
|
|
150
|
+
maxDate: maxNextDate.toLocaleDateString(),
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
test: function (value) {
|
|
154
|
+
if (!value) return true;
|
|
155
|
+
const date = getDate(value);
|
|
156
|
+
const isValid = +date.toDate() < +maxDate;
|
|
157
|
+
return isValid;
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
if (params.min) {
|
|
162
|
+
let minDate;
|
|
163
|
+
if (params.min === 'now') {
|
|
164
|
+
const today = new Date();
|
|
165
|
+
minDate = new Date(today);
|
|
166
|
+
} else {
|
|
167
|
+
minDate = getDate(params.min).toDate();
|
|
168
|
+
}
|
|
169
|
+
const minPreviousDate = new Date(minDate);
|
|
170
|
+
minPreviousDate.setDate(minDate.getDate() - 1);
|
|
171
|
+
simpleDate = simpleDate.test({
|
|
172
|
+
name: 'later-than',
|
|
173
|
+
message: {
|
|
174
|
+
key: 'form.error.date.later_than',
|
|
175
|
+
context: {
|
|
176
|
+
minDate: minPreviousDate.toLocaleDateString(),
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
test: function (value) {
|
|
180
|
+
if (!value) return true;
|
|
181
|
+
const date = getDate(value);
|
|
182
|
+
const isValid = +date.toDate() > +minDate;
|
|
183
|
+
return isValid;
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
return simpleDate;
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
return yupTypeMap;
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
export interface MutableRefObjectProps {}
|
|
194
|
+
// Create a yup validation schema from given fields input
|
|
195
|
+
export function useValidationSchema(
|
|
196
|
+
fields: FieldSpec[] | MutableRefObject<MutableRefObjectProps>,
|
|
197
|
+
validatorRegistry?: Record<string, ValidatorSchema[]>
|
|
198
|
+
): Lazy<any, unknown> | AnyObjectSchema | void {
|
|
199
|
+
return useMemo(() => {
|
|
200
|
+
const yupTypeMap = getYUPTypeMap();
|
|
201
|
+
return getYupObjectShape(fields, yupTypeMap, validatorRegistry);
|
|
202
|
+
}, []);
|
|
203
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export function validateAFM(afm: string): boolean {
|
|
2
|
+
if (afm.length !== 9) {
|
|
3
|
+
// "afm should be 9 digits"
|
|
4
|
+
return false;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
if (!/^\d+$/.test(afm)) {
|
|
8
|
+
// "This is not a number"
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (afm === '0'.repeat(9)) {
|
|
13
|
+
// "This is zero number (000000000)"
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const sum = afm
|
|
18
|
+
.substring(0, 8)
|
|
19
|
+
.split('')
|
|
20
|
+
.reduce((s, v, i) => s + (parseInt(v) << (8 - i)), 0);
|
|
21
|
+
|
|
22
|
+
const calc = sum % 11;
|
|
23
|
+
const d9 = parseInt(afm[8]);
|
|
24
|
+
const valid = calc % 10 === d9;
|
|
25
|
+
return valid;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const AFM_VALIDATOR = {
|
|
29
|
+
name: 'afm-validator',
|
|
30
|
+
message: 'form.error.afm',
|
|
31
|
+
test: (value): boolean => {
|
|
32
|
+
if (value) {
|
|
33
|
+
return validateAFM(value);
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
},
|
|
37
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ValidatorSchema } from '@digigov/form/validators/types';
|
|
2
|
+
import { FieldSpec } from '@digigov/form/types';
|
|
3
|
+
|
|
4
|
+
const DEFAULT_FILE_MAX_SIZE = 10000000;
|
|
5
|
+
|
|
6
|
+
export const FILE_MAX_SIZE_VALIDATOR = (field: FieldSpec): ValidatorSchema => ({
|
|
7
|
+
name: 'file-max-size-validator',
|
|
8
|
+
message: 'form.error.file_size',
|
|
9
|
+
test: (value: File[]): boolean => {
|
|
10
|
+
if (field.extra && field.extra.maxSize && value) {
|
|
11
|
+
for (const file of value) {
|
|
12
|
+
if (file.size >= field.extra.maxSize) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
} else if (value) {
|
|
17
|
+
for (const file of value) {
|
|
18
|
+
if (file.size >= DEFAULT_FILE_MAX_SIZE) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return true;
|
|
24
|
+
},
|
|
25
|
+
});
|