@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.
Files changed (138) hide show
  1. package/CHANGELOG.md +8 -1
  2. package/Form.stories.playwright.json +0 -72
  3. package/FormBuilder/FormBuilder.mdx +1 -1
  4. package/MultiplicityField/__stories__/PreviewDisplay.js +6 -6
  5. package/Questions/__stories__/Default.js +2 -2
  6. package/Questions/index.mdx +1 -1
  7. package/es/Form.stories.playwright.json +0 -72
  8. package/es/FormBuilder/FormBuilder.mdx +1 -1
  9. package/es/MultiplicityField/__stories__/PreviewDisplay.js +6 -6
  10. package/es/Questions/__stories__/Default.js +1 -1
  11. package/es/Questions/index.mdx +1 -1
  12. package/esm/Form.stories.playwright.json +0 -72
  13. package/esm/FormBuilder/FormBuilder.mdx +1 -1
  14. package/esm/MultiplicityField/__stories__/PreviewDisplay.js +6 -6
  15. package/esm/Questions/__stories__/Default.js +1 -1
  16. package/esm/Questions/index.mdx +1 -1
  17. package/esm/index.js +1 -1
  18. package/package.json +4 -4
  19. package/src/Field/FieldBase.tsx +99 -0
  20. package/src/Field/FieldBaseContainer.tsx +57 -0
  21. package/src/Field/FieldConditional.tsx +75 -0
  22. package/src/Field/index.mdx +6 -0
  23. package/src/Field/index.tsx +92 -0
  24. package/src/Field/types.tsx +102 -0
  25. package/src/Field/utils.ts +164 -0
  26. package/src/FieldArray/FieldArray.stories.js +8 -0
  27. package/src/FieldArray/FieldArray.stories.playwright.json +353 -0
  28. package/src/FieldArray/__stories__/Default.tsx +95 -0
  29. package/src/FieldArray/__stories__/WithExactLength.tsx +95 -0
  30. package/src/FieldArray/index.tsx +83 -0
  31. package/src/FieldObject/index.tsx +92 -0
  32. package/src/Fieldset/FieldsetWithContext.tsx +41 -0
  33. package/src/Fieldset/index.tsx +40 -0
  34. package/src/Fieldset/types.tsx +6 -0
  35. package/src/Form.stories.js +5 -0
  36. package/src/Form.stories.playwright.json +71 -0
  37. package/src/FormBuilder/FormBuilder.mdx +271 -0
  38. package/src/FormBuilder/FormBuilder.stories.js +7 -0
  39. package/src/FormBuilder/FormBuilder.stories.playwright.json +52 -0
  40. package/src/FormBuilder/FormBuilder.tsx +165 -0
  41. package/src/FormBuilder/__stories__/Default.tsx +23 -0
  42. package/src/FormBuilder/index.tsx +3 -0
  43. package/src/FormContext.tsx +8 -0
  44. package/src/MultiplicityField/MultiplicityField.mdx +580 -0
  45. package/src/MultiplicityField/MultiplicityField.stories.js +12 -0
  46. package/src/MultiplicityField/MultiplicityField.stories.playwright.json +1370 -0
  47. package/src/MultiplicityField/__stories__/Default.tsx +100 -0
  48. package/src/MultiplicityField/__stories__/PreviewDisplay.tsx +160 -0
  49. package/src/MultiplicityField/__stories__/WithExactLength.tsx +99 -0
  50. package/src/MultiplicityField/__stories__/WithMaxLength.tsx +102 -0
  51. package/src/MultiplicityField/__stories__/WithMinAndMaxLength.tsx +103 -0
  52. package/src/MultiplicityField/__stories__/WithMinLength.tsx +102 -0
  53. package/src/MultiplicityField/add-objects.tsx +186 -0
  54. package/src/MultiplicityField/index.tsx +166 -0
  55. package/src/Questions/Questions.stories.js +7 -0
  56. package/src/Questions/Questions.tsx +74 -0
  57. package/src/Questions/QuestionsContext.tsx +9 -0
  58. package/src/Questions/Step/ReviewStep.tsx +63 -0
  59. package/src/Questions/Step/Step.tsx +67 -0
  60. package/src/Questions/Step/StepArrayReview.tsx +68 -0
  61. package/src/Questions/Step/StepContext.tsx +21 -0
  62. package/src/Questions/Step/StepDescription.tsx +33 -0
  63. package/src/Questions/Step/StepForm.tsx +60 -0
  64. package/src/Questions/Step/StepQuote.tsx +8 -0
  65. package/src/Questions/Step/StepTitle.tsx +60 -0
  66. package/src/Questions/Step/getAddMoreFields.tsx +28 -0
  67. package/src/Questions/Step/index.ts +13 -0
  68. package/src/Questions/Step/types.tsx +32 -0
  69. package/src/Questions/__snapshots__/index.spec.tsx.snap +887 -0
  70. package/src/Questions/__stories__/Default.tsx +130 -0
  71. package/src/Questions/getNextStep.tsx +24 -0
  72. package/src/Questions/index.mdx +418 -0
  73. package/src/Questions/index.spec.tsx +72 -0
  74. package/src/Questions/index.tsx +5 -0
  75. package/src/Questions/types.tsx +25 -0
  76. package/src/__stories__/AutoCompleteField.tsx +45 -0
  77. package/src/__stories__/IntField.tsx +38 -0
  78. package/src/create-simple-form.mdx +518 -0
  79. package/src/index.mdx +44 -0
  80. package/src/index.ts +3 -0
  81. package/src/inputs/AutoComplete/index.tsx +85 -0
  82. package/src/inputs/Checkboxes/Checkboxes.stories.js +7 -0
  83. package/src/inputs/Checkboxes/Checkboxes.stories.playwright.json +69 -0
  84. package/src/inputs/Checkboxes/__stories__/Default.tsx +39 -0
  85. package/src/inputs/Checkboxes/index.mdx +0 -0
  86. package/src/inputs/Checkboxes/index.tsx +77 -0
  87. package/src/inputs/DateInput/DateInput.stories.js +7 -0
  88. package/src/inputs/DateInput/DateInput.stories.playwright.json +72 -0
  89. package/src/inputs/DateInput/__stories__/Default.tsx +41 -0
  90. package/src/inputs/DateInput/index.tsx +130 -0
  91. package/src/inputs/FileInput/FileInput.stories.js +7 -0
  92. package/src/inputs/FileInput/FileInput.stories.playwright.json +75 -0
  93. package/src/inputs/FileInput/__stories__/Default.tsx +23 -0
  94. package/src/inputs/FileInput/index.tsx +76 -0
  95. package/src/inputs/Input/Input.stories.js +14 -0
  96. package/src/inputs/Input/Input.stories.playwright.json +376 -0
  97. package/src/inputs/Input/__stories__/AFM.tsx +24 -0
  98. package/src/inputs/Input/__stories__/Boolean.tsx +26 -0
  99. package/src/inputs/Input/__stories__/Default.tsx +25 -0
  100. package/src/inputs/Input/__stories__/IBAN.tsx +26 -0
  101. package/src/inputs/Input/__stories__/Integer.tsx +25 -0
  102. package/src/inputs/Input/__stories__/MobilePhone.tsx +24 -0
  103. package/src/inputs/Input/__stories__/PhoneNumber.tsx +24 -0
  104. package/src/inputs/Input/__stories__/PostalCode.tsx +25 -0
  105. package/src/inputs/Input/index.mdx +8 -0
  106. package/src/inputs/Input/index.tsx +62 -0
  107. package/src/inputs/Label/Label.stories.js +7 -0
  108. package/src/inputs/Label/Label.stories.playwright.json +40 -0
  109. package/src/inputs/Label/__stories__/Default.tsx +28 -0
  110. package/src/inputs/Label/index.mdx +0 -0
  111. package/src/inputs/Label/index.tsx +44 -0
  112. package/src/inputs/Radio/Radio.stories.js +7 -0
  113. package/src/inputs/Radio/Radio.stories.playwright.json +57 -0
  114. package/src/inputs/Radio/__stories__/Default.tsx +42 -0
  115. package/src/inputs/Radio/index.mdx +0 -0
  116. package/src/inputs/Radio/index.tsx +57 -0
  117. package/src/inputs/Select/Select.stories.js +7 -0
  118. package/src/inputs/Select/Select.stories.playwright.json +22 -0
  119. package/src/inputs/Select/__stories__/Default.tsx +47 -0
  120. package/src/inputs/Select/index.tsx +37 -0
  121. package/src/inputs/index.ts +7 -0
  122. package/src/installation.mdx +72 -0
  123. package/src/internal.ts +34 -0
  124. package/src/registry.js +134 -0
  125. package/src/types.tsx +110 -0
  126. package/src/utils.ts +78 -0
  127. package/src/validators/index.ts +203 -0
  128. package/src/validators/types.ts +2 -0
  129. package/src/validators/utils/afm.ts +37 -0
  130. package/src/validators/utils/file.ts +25 -0
  131. package/src/validators/utils/iban.ts +119 -0
  132. package/src/validators/utils/index.ts +94 -0
  133. package/src/validators/utils/int.ts +22 -0
  134. package/src/validators/utils/number.ts +18 -0
  135. package/src/validators/utils/phone.ts +120 -0
  136. package/src/validators/utils/postal_code.ts +33 -0
  137. package/src/validators/utils/uuid4.ts +21 -0
  138. package/src/validators/validators.spec.ts +122 -0
@@ -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,2 @@
1
+ import * as yup from 'yup';
2
+ export type ValidatorSchema = yup.TestConfig;
@@ -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
+ });